docs(game): migrate game-design canon notes from Joplin into docs/game/

Eight canon notes (Game Concept Overview, Mechanics Source Mapping,
Combat System & Stat Scaling Design, Skill & Magic System, Medals &
Honours System, Lore & World Building, Idle Fantasy Inspirations,
Tech Stack & Architecture) as markdown, note title as H1, with source
line citing the Joplin note ID. Joplin keeps status notes.
This commit is contained in:
Jan-Peter von Hunnius 2026-10-03 17:27:43 +02:00
parent 2343d5e154
commit 7a9a5a3e7b
8 changed files with 2810 additions and 0 deletions

View file

@ -0,0 +1,172 @@
# Skara Brae — Combat System & Stat Scaling Design
Source: Joplin note 0ef630db4e3e4d6dab18ccaefccaaa5a, migrated 2026-10-03
## The Core Tension
**RoleMaster approach**: Open-ended d100 roll + critical tables. A level 1 can theoretically kill a level 60 with a lucky crit (roll 01-00 on the crit table → "Instant Death"). Thrilling unpredictability, terrible long-term retention — months of work undone by RNG.
**Torn City approach**: Stats grow into hundreds of millions over years. Combat outcomes are overwhelmingly deterministic — a level 60 will always beat a level 1. Safe long-term progression, no surprise.
**Decision**: Hybrid "Scaled Brutality" — Torn-scale numbers with RoleMaster-inspired crits that are capped by level difference but never reach zero.
---
## Exponential Stat Growth (Torn-Style)
- Stats use `BIGINT` (up to 9.2 quintillion) — room for years of growth
- Training, equipment, education, and crafting all feed into stat progression
- Stats grow exponentially, not linearly — early levels feel meaningful, later levels require dedication
- **No rebirth/prestige system for now** — stats only ever go up. Can revisit with player base later.
### Stat Display
| Raw Value | Display |
|---|---|
| 1,247 | 1.2K |
| 12,432 | 12.4K |
| 4,721,000 | 4.7M |
| 1,234,567,890 | 1.2B |
| 3,800,000,000,000 | 3.8T |
- Show **effective power rating** (composite of all stats) as a single number for quick comparison
- Show **stat growth rate** (e.g., "+2.3K/day") so players feel momentum
- Historical stat graphs (like Torn) for long-term engagement
---
## RoleMaster-Inspired Critical System
Every attack rolls on a **critical table** (d100 open-ended: roll 96-100, roll again and add). But crit damage is **capped by level difference**.
### Crit Damage Caps
| Level Difference (target above attacker) | Crit Damage Cap |
|---|---|
| Equal level | Full crit range (01-100) — no cap |
| +10 levels | 60% of target's max HP |
| +20 levels | 40% of target's max HP |
| +50 levels | 15% of target's max HP |
| +100 levels | 5% of target's max HP |
The cap never reaches zero — a level 1 can always chip away at a level 60.
### Critical Effects
Crits don't just do damage. They apply **status effects** based on the crit roll and weapon type:
| Effect | Duration | Description |
|---|---|---|
| **Bleed** | 3-5 ticks | Damage over time (scaling with weapon) |
| **Stun** | 1 turn | Target skips next action |
| **Disarm** | 1 turn | Target loses weapon bonuses |
| **Cripple** | 3-5 turns | Target agility/strength reduced |
| **Blind** | 2-3 turns | Target accuracy reduced |
**Key insight**: Status effects work **regardless of level difference**. A level 1 landing a lucky crit can *disrupt* a level 60 (stun them for a turn) even if the damage is negligible. This creates the RoleMaster feel of "anyone can affect anyone" without the frustration of instant death.
### Armor and Crit Mitigation
- **Heavy armor** reduces crit roll by a flat amount (e.g., plate armor: -15 to crit roll)
- **Crit Shield enchantments**: High-end enchantments absorb X crit damage per day
- **Constitution** reduces bleed/cripple duration
---
## Why This Works
- **Long-term players** keep their billions-scale progression and feel powerful — they will win 99% of encounters
- **New players** feel the thrill of landing a lucky crit (15% HP off a whale is still exciting)
- **Guild wars become strategic**: A swarm of low-level players can chip away at a high-level defender through coordinated crit effects
- **Dueling has drama**: Crits are always possible, but rarely fight-ending between equals
- **No instant death**: No months of work lost to a single bad roll
---
## Combat Formula (Draft)
```
base_damage = weapon_damage * (1 + strength / 100)
mitigation = armor_rating * (1 + constitution / 200)
net_damage = max(1, base_damage - mitigation)
crit_roll = d100_open_ended() // 96-100: roll again and add
if crit_roll >= crit_threshold(attacker_agility, target_level_diff):
crit_multiplier = crit_table(crit_roll, weapon_type)
crit_damage = net_damage * crit_multiplier
crit_damage = min(crit_damage, target_max_hp * crit_cap(target_level_diff))
apply_critical_effect(crit_roll, target)
else:
apply_damage(net_damage, target)
```
### Open-Ended d100
```
fn d100_open_ended() -> u32:
total = d100()
while total >= 96: // 96-100: roll again and add
total += d100()
return total
```
This means most rolls are 1-95, but occasionally you get 96+100+3 = 199, or even rarer chains. The open-ended mechanic creates the "anything can happen" feel without instant death.
---
## Critical Tables (Structure)
Crit tables are weapon-type specific. Each entry maps a roll range to an effect:
```toml
# crit_tables/slash_unarmed.toml
[entries.01_20]
name = "Glancing blow"
damage_multiplier = 1.5
effect = "none"
[entries.21_50]
name = "Deep slash"
damage_multiplier = 2.0
effect = "bleed"
effect_duration = 3
[entries.51_75]
name = "Arterial strike"
damage_multiplier = 2.5
effect = "bleed"
effect_duration = 5
[entries.76_90]
name = "Debilitating wound"
damage_multiplier = 3.0
effect = "cripple"
effect_duration = 4
[entries.91_100]
name = "Devastating cleave"
damage_multiplier = 4.0
effect = "bleed"
effect_duration = 5
effect2 = "stun"
effect2_duration = 1
[entries.101_plus]
name = "Legendary strike"
damage_multiplier = 5.0
effect = "bleed"
effect_duration = 5
effect2 = "stun"
effect2_duration = 2
```
These tables live in `skara-brae-common/crit-tables/` and are loaded by both server (for combat resolution) and client (for display).
---
## Related Notes
- [Game Concept Overview](joplin://9cf8a2e701654ffbbd6512cc837c7e2f)
- [Idle Fantasy Inspirations](joplin://) *(to be created)*
- [Tech Stack & Architecture](joplin://cecd2ef2690d4d1fba3450342aa63953)
- [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b)

View file

@ -0,0 +1,569 @@
# Skara Brae — Game Concept Overview
Source: Joplin note 9cf8a2e701654ffbbd6512cc837c7e2f, migrated 2026-10-03
# Skara Brae — Fantasy Text-Based MMORPG
## Inspiration
**Torn City** is a text-based, crime-themed MMORPG running since 2004 with over a million users. Core mechanics include:
- Crime system (mugging, drug trafficking, organized crime)
- PvP combat with experience/leveling
- Factions (clan system with wars and organized crimes)
- Companies (player-run businesses)
- Properties and housing
- Stock market and banking
- Item market / bazaar / auctions
- Education system
- Bounty system
- Rich REST API for community tools
**Idle Fantasy** ([source](https://github.com/tristinbaker/IdleFantasy)) is an open-source offline idle RPG for Android with 23 skills, 20 dungeons, 170+ quests, guild rank progression, pets, and inn workers. Key inspirations: offline sessions, hireable NPC workers, pet buff system, blessing system, slayer tasks. See [Idle Fantasy Inspirations](joplin://48b3a3c76f734c8dafbbf9e8b3b5f80a) for full analysis.
**Skara Brae** transplants Torn's proven mechanics into a dark fantasy setting inspired by **The Bard's Tale I** and the real neolithic settlement on Orkney, with idle RPG elements from Idle Fantasy and a **RoleMaster-inspired critical hit system** (see [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a)).
---
## Setting
The city of **Skara Brae** — an ancient, labyrinthine city of stone and sorcery. Once a thriving hub of the Old Kingdom, now a place of shadow and opportunity. Adventurers arrive seeking fortune, power, and answers to mysteries buried beneath the cobblestones.
**Theme**: Low-to-dark fantasy. Grimy taverns, corrupt city watch, competing guilds, ancient dungeons beneath the city, magical artifacts, political intrigue. Not high fantasy — think more *The Witcher* meets *Thief* meets *Bard's Tale*.
---
## Core Game Loops
### 1. Adventures (→ Torn's "Crimes")
The primary PvE activity. Players embark on adventures throughout the city and surrounding wilderness.
| Torn Mechanic | Skara Brae Equivalent |
|---|---|
| Search for cash | Pick pockets in the marketplace |
| Sell illegal items | Fence stolen goods at the Thieves' Guild |
| Mug someone | Waylay travelers on the road |
| Burglary | Break into manors and vaults |
| Organized crime | Dungeon raids (guild activity) |
| Drug trafficking | Brew and sell potions (alchemy) |
Adventures have:
- **Risk/reward tiers** (safe but low yield → dangerous but high yield)
- **Cooldown timers** (energy system)
- **Skill-based success chances** (your thievery skill affects pickpocketing)
- **Time-of-day modifiers** (nighttime gives bonuses to stealth activities)
- **Day-of-week events** (market day, full moon effects, festival bonuses)
- **Offline continuation**: Adventures continue for up to 1 hour while logged out. On return, collect accumulated rewards. Server-side tick calculates elapsed rewards.
### 2. Combat (PvP & PvE)
- **Arena**: Structured PvP duels with ranked matchmaking
- **Ambush**: Open-world PvP with risk/reward (infamy system)
- **Dungeon bosses**: PvE endgame encounters
- **Combat is turn-based/text-based** with strategic depth (choose actions, manage stamina/mana)
- **RoleMaster-inspired critical hits**: Open-ended d100 crit tables with status effects (bleed, stun, disarm, cripple). Crit damage capped by level difference but never zero. See [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a).
- **Exponential stat growth**: BIGINT stats, tiered display (K/M/B/T). Stats only ever go up — no rebirth/prestige for now.
### 3. Economy
- **Bazaar**: Player-driven item marketplace
- **Auction House**: Rare items, timed auctions
- **Bank of Skara Brae**: Deposits, interest, loans
- **Merchant Ventures**: Invest in trading caravans (→ Torn's stocks) — returns depend on random events
- **Crafting**: Alchemy, blacksmithing, enchanting — create items to sell or use (see Crafting deep dive below)
- **Player shops/stalls**: Set up a stall in the Market Square (→ Torn's bazaar model)
### 4. Guilds (→ Torn's "Factions")
See Guilds deep dive below for full details.
- Player organizations with hierarchy (Guildmaster → Officers → Members → Initiates)
- **Guild Hall**: Upgradable base providing bonuses to members
- **Guild Wars**: Territory control, raids on rival guild halls
- **Guild Adventures**: Cooperative dungeon raids (→ organized crimes)
- **Guild treasury**: Shared resources, taxation of members
### 5. Properties (→ Torn's "Properties")
- **Dwellings**: From a straw bed at an inn to a tower in the city walls
- Properties provide: rest bonuses (energy recovery), storage, crafting stations
- Rentable, sellable, upgradable
### 6. Education (→ Torn's "Education")
- **Schools**: Fighters' Academy, College of Magic, Thieves' Den, Merchants' Guild School
- Courses take real time to complete, provide permanent stat/skill bonuses
- Some adventures require specific education prerequisites
### 7. Quests & Storylines
- **Main storyline**: Uncover the mystery beneath Skara Brae (Bard's Tale-inspired Mangar threat)
- **Side quests**: NPC-given missions with rewards
- **Dynamic events**: City-wide events (plague, invasion, festival)
- **Daily quests**: 3-5 per day from NPCs (Madame Sylara, Captain Rennick, Guildmasters). "Complete 3 adventures" / "Craft 2 potions" / "Win 1 arena duel". Rewards: gold, XP, skill XP, occasional items.
- **Weekly quests**: Larger goals, better rewards
- **Cumulative achievements**: "Mine 10,000 ore total" → permanent bonus
---
## Crafting System (Deep Dive)
### Gathering Professions (5)
| Profession | Materials | Locations |
|---|---|---|
| **Mining** | Ore, gems, stone | Mines, Undercity, mountains |
| **Herbalism** | Herbs, fungi, reagents | Forests, swamps, gardens |
| **Woodcutting** | Timber, resin, bark | Forests, groves |
| **Fishing** | Fish, pearls, salvage | Harbor, rivers, underground lakes |
| **Skinning** | Leather, bone, sinew | Wilds, dungeons (from kills) |
### Crafting Professions (7)
| Profession | Creates | Key Materials |
|---|---|---|
| **Blacksmithing** | Weapons, heavy armor, tools | Ore, coal, flux |
| **Alchemy** | Potions, poisons, elixirs | Herbs, reagents, solvents |
| **Enchanting** | Magical enhancements, scrolls | Rare reagents, essence |
| **Tailoring** | Cloth armor, bags, banners | Cloth, silk, magical thread |
| **Jewelcrafting** | Rings, amulets, gem cuts | Gems, precious metals |
| **Fletching** | Bows, crossbows, arrows | Wood, sinew, feathers |
| **Cooking** | Food (healing, buffs), beverages | Fish, meat, herbs, grain |
### Profession Mastery Levels
Novice → Apprentice → Journeyman → Expert → Master → Grandmaster
Each tier unlocks new recipes and improves crafting quality.
### Crafting Quality Rolls
Every crafted item rolls for quality:
| Quality | Chance (base) | Effect |
|---|---|---|
| Common | 50% | Base stats |
| Fine | 25% | +10% stats |
| Superior | 15% | +25% stats |
| Exceptional | 7% | +50% stats |
| Masterwork | 2.5% | +100% stats |
| Legendary | 0.5% | +200% stats + unique affix |
### Crafting Crits (RoleMaster-inspired)
- Small chance of exceptional result regardless of skill level (mirrors combat crit system)
- d100 roll on craft: 96+ triggers a crafting crit → quality tier upgraded by 1-2 levels
- High skill level improves base quality but crits can happen to anyone
### Recipe Discovery
- **Taught recipes**: From education courses, guild rank rewards
- **Adventure drops**: Recipe scrolls found in dungeons
- **Experimentation**: Combine materials with a chance to discover a new recipe (消耗 materials on failure)
- **Seasonal events**: Limited-time recipes
---
## The Inn — Social Hub (Deep Dive)
**The Singing Tavern** is the central social hub of Skara Brae, inspired by Idle Fantasy's Inn system.
### Social Features
- **Chat rooms**: General, trade, guild recruitment, district-specific, roleplay
- **Rumors board**: NPC-posted hints about adventures, dungeon openings, rare spawns, upcoming events
- **Bounty board**: Player-posted and NPC-posted bounties on other players
- **Barter table**: Direct player-to-player trading (avoid market fees) — face-to-face exchange
### Minigames & Gambling
- **Dice games**: Roll dice against other players or the house
- **Card games**: Fantasy-themed card game (simplified poker variant)
- **Arm wrestling**: Strength-based contest (simple stat check with randomness)
- **Drinking contest**: Constitution-based, winner gets bragging rights + temporary charisma bonus
### Rest & Recovery
- **Energy/HP/Mana recovery** at a rate determined by inn quality (tied to property system)
- Basic room: 1× recovery rate
- Quality room: 1.5× recovery rate
- Luxury suite: 2× recovery rate
- Members with properties can rest at home for variable rates
### Carousing
- Spend gold to temporarily boost charisma (affects next N trades, conversations, or persuasion attempts)
- Duration: Until you complete N social interactions or time expires
- Risk: Overdoing it can result in "hangover" debuff (-agility for 1 hour)
### Innkeeper Daily Quests
- **Madame Sylara** offers 3 daily quests from the inn
- Quest types: "Collect information from X NPCs", "Deliver a message", "Win X gold gambling"
- Rewards scale with difficulty
### Hire Workers (Idle Fantasy-inspired)
The most distinctive feature from Idle Fantasy — **hire NPCs to automate tasks**:
| Worker | Task | Efficiency | Cost |
|---|---|---|---|
| **Mercenary** | Runs adventures while offline | 60% of normal rewards | Gold/hour |
| **Apprentice** | Trains a skill while offline | 50% of active rate | Gold/hour |
| **Gatherer** | Collects basic materials | Low-tier materials only | Gold/hour |
- Worker quality tiers: Novice → Journeyman → Expert (better rates, higher cost)
- Workers consume your energy while active
- Creates a meaningful **gold sink** for veteran players
- Buy **provisions** in bulk (food, potions, torches) for dungeon expeditions
---
## Pets (Deep Dive)
### Acquisition
- **Taming**: Wild encounters in the Wilds (skill check, rare success)
- **Purchase**: Pet trader in the Market Square
- **Breeding**: Combine two pets for a chance at rare offspring with combined bonuses
- **Quest rewards**: Specific pets from storyline/side quests
- **Rare enemy drops**: Dungeon bosses and rare spawns can drop pet eggs/whistles
- **Seasonal events**: Limited-time pets
### Pet Rarity Tiers
Common → Uncommon → Rare → Epic → Legendary → Mythic
### Pet Types & Bonuses
| Pet | Bonus |
|---|---|
| Wolf | +tracking, +combat XP |
| Raven | +scouting, +perception |
| Cat | +stealth, +thievery XP |
| Owl | +magic XP, +wisdom |
| Hound | +combat damage, +slayer XP |
| Toad | +poison resistance, +alchemy XP |
| Hawk | +ranged accuracy, +gathering yield |
### Pet Mechanics
- **Active pet**: One pet follows you (visible in combat), providing its passive bonus
- **Pet stable**: Store up to N pets (expandable via property upgrades)
- **Pet aging**: Pets grow over time, increasing their bonus at milestones (1 week, 1 month, 6 months)
- **Pet death**: Pets can be killed in PvP ambush (creates real stakes) — resurrected at Temple Row for gold
- **Pet equipment**: Collars, armor, trinkets — crafted or found. Enhance pet bonuses.
- **Pet breeding**: Combine two pets → offspring has a chance of inheriting combined bonuses or rare mutation
---
## Guilds (Deep Dive)
### Guild Hall Upgrades
| Upgrade | Effect | Build Cost |
|---|---|---|
| **Training Grounds** | +X% stat training speed for members | Gold + materials |
| **Library** | +X% education course speed | Gold + enchanted books |
| **Vault** | Shared storage for members | Gold + crafted locks |
| **War Room** | Plan raids, view territory map | Gold + cartography tools |
| **Brewery** | Member happiness → reduced quit rate, social bonuses | Gold + cooking supplies |
| **Infirmary** | Faster HP/energy recovery for members | Gold + alchemy supplies |
| **Enchanting Lab** | +X% enchanting quality for members | Gold + rare reagents |
### Guild Taxation
- Configurable tax rate on member earnings: **0-25%**
- Tax gold flows into guild treasury
- Guildmaster and officers set the rate
- High tax → more treasury for upgrades, but member dissatisfaction
### Guild Alliances
- Formal treaties between guilds: shared chat, coordinated raids, non-aggression pacts
- Alliance leaderboard
- Alliance vs. alliance wars for territory control
### Guild Territories
- Control of city districts provides bonuses to all guild members in that district
- Territory gained through guild wars and maintained through activity
- District bonuses: Market Square (reduced listing fees), Harbor (trade route bonuses), etc.
### Guild Rank Progression (Idle Fantasy-inspired)
- **10 rank levels** per guild: Initiate → Apprentice → Journeyman → Expert → Veteran → Elite → Champion → Master → Grandmaster → Legend
- **Daily guild tasks**: Complete for reputation points
- **Rank-up quests**: Progression quests to advance in guild rank
- **Cross-skill rewards**: Higher ranks unlock resources from skills you don't personally train
- **Guild reputation**: Decayed by inactivity, increased by events, raids, member achievements
### Guild Bank
- Shared treasury with withdrawal permissions by rank
- Deposit logs visible to officers+
- Withdrawal limits configurable by rank
---
## Blessings / Church (Idle Fantasy-inspired)
- **Temple Row** offers blessings from the Old Gods
- **Blessing types**: XP boost (up to 1.5×), Damage reduction, Gold multiplier, Crit chance increase
- **Duration**: Based on Wisdom stat and offering quality
- **One blessing active** at a time
- **Offerings**: Gold, rare items, bones from undead enemies
- Higher Wisdom = longer duration, stronger effect
- Adds "buff management" layer without being tedious
---
## Slayer Tasks (Idle Fantasy-inspired)
- **Captain Rennick** at City Watch HQ gives slayer tasks (lawful targets)
- **The Beggar King** gives underground slayer tasks (criminal targets)
- "Kill 15 skeletal warriors in the Undercity" → bonus Slayer XP + gold reward
- Slayer level unlocks tougher targets with better rewards
- Ties into the bounty system naturally
---
## Character System
### Races
| Race | Bonus | Penalty |
|---|---|---|
| Human | Balanced, bonus to charisma | None (jack of all trades) |
| Dwarf | Constitution +, Smithing + | Agility - |
| Elf | Magic +, Perception + | Strength - |
| Halfling | Agility +, Thievery + | Strength - |
| Orc | Strength +, Intimidation + | Intelligence - |
| Half-Elf | Charisma +, Magic + | Constitution - |
### Classes (determine starting skills and education paths)
- **Warrior** — Melee combat, tanking
- **Rogue** — Stealth, thievery, poison
- **Mage** — Offensive magic, enchanting
- **Bard** — Buffs, social skills, lore
- **Cleric** — Healing, protection, undead turning
- **Ranger** — Ranged combat, tracking, survival
### Stats (BIGINT — exponential growth)
- **Strength** — Physical damage, carrying capacity
- **Agility** — Dodge, stealth, thievery
- **Constitution** — HP, endurance, poison resistance
- **Intelligence** — Magic power, crafting quality
- **Wisdom** — Mana, perception, healing power, blessing duration
- **Charisma** — Trading prices, faction relations, bardic abilities
Stats only ever go up. Display tiered: `1.2K`, `4.7M`, `1.2B`, `3.8T`. See [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a).
### Skills (leveled through use)
- Weapon skills (sword, axe, bow, staff, etc.)
- Thievery (lockpicking, pickpocketing, sneaking)
- Magic schools (fire, ice, illusion, necromancy, etc.)
- Crafting (alchemy, blacksmithing, enchanting, tailoring, jewelcrafting, fletching, cooking)
- Gathering (mining, herbalism, woodcutting, fishing, skinning)
- Social (persuasion, intimidation, bartering)
- Support (mercantile/trading, slayer/bounty hunting)
---
## Technology Stack
### Backend — Rust
| Component | Technology | Rationale |
|---|---|---|
| HTTP Framework | **Axum** | Modern, ergonomic, excellent ecosystem, tower middleware |
| Real-time | **WebSocket** via axum + tokio-tungstenite | Live combat, chat, notifications |
| Database | **PostgreSQL** + **SQLx** | ACID compliance, relational data fits game entities well |
| Cache/Sessions | **Redis** | Session tokens, leaderboards, rate limiting, real-time pub/sub |
| Auth | **JWT** (jsonwebtoken crate) | Stateless auth, API-friendly |
| Background Jobs | **tokio** tasks + custom scheduler | Timers for cooldowns, education courses, guild wars |
| Migrations | **sqlx-cli** or **refinery** | Database schema versioning |
| Serialization | **serde** + **serde_json** | JSON API, message passing |
| Game Tick Engine | Custom event loop on **tokio** | Time-based game events (day/night cycle, weather, offline rewards) |
### Frontend — Vue.js
| Component | Technology | Rationale |
|---|---|---|
| Framework | **Vue 3** + **Composition API** | Modern, reactive, good for complex UIs |
| Build Tool | **Vite** | Fast dev server, optimized builds |
| State Management | **Pinia** | Type-safe, modular stores for game state |
| Routing | **Vue Router** | SPA navigation |
| UI Framework | **PrimeVue** or custom dark fantasy theme | Rich component library |
| Real-time | **WebSocket client** (native) | Live updates, combat, chat |
| HTTP Client | **Axios** or **fetch API** | REST API calls |
| Mobile | **PWA** or **Capacitor** | Native-like mobile experience |
### Infrastructure
| Component | Technology |
|---|---|
| Containerization | Docker + docker-compose |
| Reverse Proxy | Caddy or nginx |
| CI/CD | GitHub Actions |
| Monitoring | Prometheus + Grafana |
| Logging | tracing crate (Rust) → structured JSON logs |
---
## Architecture Overview
```
┌──────────────────────────────────────────────────┐
│ Frontend (Vue 3) │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌───────┐ │
│ │ REST API │ │WebSocket│ │ State │ │ PWA │ │
│ │ Client │ │ Client │ │ (Pinia) │ │ Shell │ │
│ └────┬─────┘ └────┬────┘ └──────────┘ └───────┘ │
└───────┼────────────┼──────────────────────────────┘
│ HTTP/REST │ WS
▼ ▼
┌──────────────────────────────────────────────────┐
│ API Gateway (Axum) │
│ ┌──────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ Auth │ │ Rate Limiter │ │ WS Handler │ │
│ │ Middleware│ │ │ │ │ │
│ └──────────┘ └──────────────┘ └───────────────┘ │
├──────────────────────────────────────────────────┤
│ Game Services (Rust) │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌───────────┐ │
│ │ Player │ │ Combat │ │ Economy│ │ Guild │ │
│ │Service │ │Service │ │Service │ │ Service │ │
│ ├────────┤ ├────────┤ ├────────┤ ├───────────┤ │
│ │Adventure│ │ World │ │ Market │ │ Chat & │ │
│ │Service │ │Service │ │Service │ │ Social │ │
│ ├────────┤ ├────────┤ ├────────┤ ├───────────┤ │
│ │Crafting│ │ Pet │ │Blessing│ │ Worker │ │
│ │Service │ │Service │ │Service │ │ Service │ │
│ └────────┘ └────────┘ └────────┘ └───────────┘ │
├──────────────────────────────────────────────────┤
│ Game Engine Core │
│ ┌────────────┐ ┌───────────┐ ┌───────────────┐ │
│ │ Tick/Sched │ │ Event Bus │ │ Rule Engine │ │
│ │ (timers) │ │ (pub/sub) │ │ (formulas) │ │
│ └────────────┘ └───────────┘ └───────────────┘ │
├──────────────────────────────────────────────────┤
│ Data Layer │
│ ┌──────────────┐ ┌──────────┐ ┌───────────┐ │
│ │ PostgreSQL │ │ Redis │ │ S3/Minio │ │
│ │ (persistent)│ │ (cache) │ │ (assets) │ │
│ └──────────────┘ └──────────┘ └───────────┘ │
└──────────────────────────────────────────────────┘
```
---
## API Design (RESTful + WebSocket)
### REST Endpoints (examples)
```
# Authentication
POST /api/auth/register
POST /api/auth/login
POST /api/auth/refresh
# Character
GET /api/character
PUT /api/character
GET /api/character/stats
GET /api/character/skills
PUT /api/character/train/:skill
# Adventures
GET /api/adventures/available
POST /api/adventures/embark/:id
GET /api/adventures/history
GET /api/adventures/offline-rewards # Collect offline session rewards
# Combat
POST /api/combat/arena/challenge/:target_id
POST /api/combat/ambush/:target_id
GET /api/combat/arena/leaderboard
# Economy
GET /api/market/items
POST /api/market/list
POST /api/market/buy/:listing_id
GET /api/bank/balance
POST /api/bank/deposit
POST /api/bank/withdraw
# Crafting
GET /api/crafting/recipes
POST /api/crafting/craft/:recipe_id
GET /api/crafting/professions
# Pets
GET /api/pets
POST /api/pets/activate/:pet_id
POST /api/pets/breed
GET /api/pets/stable
# Guilds
GET /api/guild
POST /api/guild/create
POST /api/guild/:id/join
GET /api/guild/:id/members
POST /api/guild/:id/raid
GET /api/guild/:id/rank-quests
# Properties
GET /api/properties
POST /api/properties/:id/buy
PUT /api/properties/:id/upgrade
# Education
GET /api/education/available
POST /api/education/enroll/:course_id
GET /api/education/progress
# Blessings
GET /api/blessings/available
POST /api/blessings/activate/:blessing_id
GET /api/blessings/active
# Inn / Workers
GET /api/inn/workers
POST /api/inn/hire/:worker_type
POST /api/inn/dismiss/:worker_id
GET /api/inn/quests # Daily innkeeper quests
# Slayer
GET /api/slayer/task
POST /api/slayer/claim-reward
```
### WebSocket Channels
```
ws://server/ws?token=JWT
# Client → Server
{ "type": "combat:action", "data": { "action": "attack", "target": "enemy_1" } }
{ "type": "chat:message", "data": { "channel": "guild", "message": "..." } }
# Server → Client
{ "type": "combat:result", "data": { "damage": 42, "enemy_hp": 158, "crit": false } }
{ "type": "combat:crit", "data": { "roll": 147, "effect": "bleed", "duration": 5 } }
{ "type": "notification", "data": { "text": "Your adventure has completed!" } }
{ "type": "market:update", "data": { "item": "...", "price": 500 } }
{ "type": "adventure:offline_rewards", "data": { "gold": 1247, "xp": 5300, "items": [...] } }
```
---
## Monetization (Ethical F2P)
- **Patron Subscription** (→ Torn's donator packs): Monthly sub providing QoL benefits (extra energy, custom themes, expanded log, etc.) — no pay-to-win
- **Cosmetics**: Character portraits, UI themes, custom titles
- **Convenience**: Extra character slots, extended history logs, extra pet stable slots
- **No**: Pay-to-win items, selling power, loot boxes
---
## MVP Scope (Phase 1)
1. User registration, authentication, character creation (race + class)
2. Basic stat/skill system with training (BIGINT stats)
3. Adventure system (5-10 adventures across difficulty tiers)
4. Turn-based combat engine with crit tables
5. Basic economy: inventory, bazaar (buy/sell), bank
6. Guild creation and membership
7. REST API + basic Vue.js frontend
8. Real-time notifications via WebSocket
9. Offline adventure rewards collection
10. Basic crafting (2-3 professions)
---
## Future Phases
- **Phase 2**: PvP arena, guild wars, properties, education system, pets, blessings
- **Phase 3**: Full storyline/quests, dynamic world events, day/night cycle, inn workers, slayer tasks
- **Phase 4**: Mobile app (Capacitor), merchant ventures (stock market), advanced crafting, pet breeding
- **Phase 5**: Community API, mod support, tournament system
---
## Related Design Notes
| Note | ID | Content |
|---|---|---|
| [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a) | `0ef630db4e3e4d6dab18ccaefccaaa5a` | RoleMaster + Torn hybrid combat, crit tables, stat scaling |
| [Idle Fantasy Inspirations](joplin://48b3a3c76f734c8dafbbf9e8b3b5f80a) | `48b3a3c76f734c8dafbbf9e8b3b5f80a` | Idle RPG mechanics, offline sessions, workers, pets |
| [Lore & World Building](joplin://867bdc9845624908a90928887a71c4c9) | `867bdc9845624908a90928887a71c4c9` | 10 city districts, 8 key NPCs, 5-act storyline |
| [Tech Stack & Architecture](joplin://cecd2ef2690d4d1fba3450342aa63953) | `cecd2ef2690d4d1fba3450342aa63953` | Rust workspace, Vue frontend, database schema |
| [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b) | `d243ae57778343fca997d46b73d0ee3b` | Roadmap, MVP scope, repository structure |

View file

@ -0,0 +1,243 @@
# Skara Brae — Idle Fantasy Inspirations
Source: Joplin note 48b3a3c76f734c8dafbbf9e8b3b5f80a, migrated 2026-10-03
Source: [Idle Fantasy](https://github.com/tristinbaker/IdleFantasy) — an open-source offline idle RPG for Android (Kotlin, Jetpack Compose, GPL-3.0).
> **Status update (2026-07):** Repo re-reviewed at **v1.12.11, 366 stars, 810 commits** (was ~206 stars when this note was first written). Several new systems shipped after the original capture — they are documented in **[New Mechanics (post-2025 evolution)](#new-mechanics-post-2025-evolution)** below. The original sections (offline sessions, workers, pets, guild ranks, blessings, slayer, daily/long-term quests, mercantile) remain valid and are not repeated in the new section.
*"Set your hero to work. Close the app. Come back to loot."*
Key mechanics from Idle Fantasy to adapt for Skara Brae:
---
## Offline / Idle Sessions
**Idle Fantasy**: Pick a skill or dungeon, start a session, close the app. Hero trains for up to 1 hour while closed. Come back to collect XP and loot. No stamina bar, no energy system.
**Skara Brae adaptation**: Skara Brae keeps Torn-style energy (differentiates our game), but adds offline adventure progression:
- Adventures continue for up to **1 hour** while logged out (or up to your energy cap)
- On return, collect accumulated gold, XP, and loot
- **Server-side tick** calculates elapsed time rewards on login
- Training skills offline at **50% rate** (active play is always better)
- This keeps casual players engaged without requiring constant attention
---
## 23 Skills Across 4 Categories
**Idle Fantasy** has 23 skills organized into:
| Category | Skills |
|---|---|
| **Gathering (7)** | Mining, Fishing, Woodcutting, Farming, Firemaking, Agility, Thieving |
| **Crafting (7)** | Smithing, Cooking, Fletching, Crafting, Runecrafting, Herblore, Construction |
| **Combat (7)** | Attack, Strength, Defense, Ranged, Magic, Hitpoints, Prayer |
| **Support (2)** | Mercantile, Slayer |
**Skara Brae mapping** (merging with existing design):
| Idle Fantasy | Skara Brae Equivalent |
|---|---|
| Mining, Woodcutting | Mining, Woodcutting (gathering) |
| Fishing, Farming | Fishing, Herbalism (gathering) |
| Firemaking | — (drop, not fantasy-appropriate) |
| Agility | Agility (thievery skill tree) |
| Thieving | Thievery (existing) |
| Smithing | Blacksmithing |
| Cooking | Cooking (alchemy sub-skill) |
| Fletching | Fletching (ranged weapon crafting) |
| Crafting | Tailoring, Jewelcrafting |
| Runecrafting | Enchanting |
| Herblore | Alchemy |
| Construction | — (~~defer to property system~~ → **RE-EVALUATED, see below**: make it a real skill) |
| Attack, Strength, Defense | Melee combat skills |
| Ranged | Ranged combat skill |
| Magic | Magic skills (fire, ice, illusion, necromancy) |
| Hitpoints | Constitution |
| Prayer | Wisdom / Cleric skills |
| Mercantile | Bartering / Trading skill |
| Slayer | Slayer / Bounty Hunting |
---
## Pets — Permanent Passive Buffs
**Idle Fantasy**: Rare enemies drop **collectible pets** that grant permanent passive XP bonuses.
**Skara Brae adaptation**:
- Pets drop from rare enemies in dungeons and adventures
- Each pet provides a **permanent passive bonus** (e.g., +2% mining XP, +5% gold from adventures)
- Pets have **rarity tiers**: Common → Uncommon → Rare → Epic → Legendary → Mythic
- **Pet stable**: Multiple pets owned, one active at a time (or multiple for patrons)
- **Pet aging**: Pets grow over time, increasing their bonus at milestones (1 week, 1 month, 6 months)
- **Pet death**: Can be killed in PvP ambush — resurrected at Temple Row for gold (creates stakes)
- **Pet breeding**: Combine two pets for a chance at rare offspring with combined bonuses
- Pet types: wolf (tracking bonus), raven (scouting), cat (stealth), owl (magic XP), hound (combat XP), etc.
---
## Inn Workers — Hire NPCs to Automate Tasks
**Idle Fantasy**: The Inn lets you **hire workers** who queue up sessions on your behalf, and buy food in bulk.
**Skara Brae adaptation**:
- **The Singing Tavern** offers hireable NPCs:
- **Mercenary**: Runs adventures while you're offline (reduced rewards: 60% of normal)
- **Apprentice**: Trains a skill while you're offline (50% rate)
- **Gatherer**: Collects basic materials while you're offline (low-tier only)
- Workers cost **gold per hour** — creates a gold sink for veteran players
- Worker quality tiers: Novice → Journeyman → Expert (better rates, higher cost)
- Buy **provisions** in bulk (food for dungeon expeditions, potions, torches)
- This is Idle Fantasy's most distinctive mechanic — automating the grind for gold
---
## Guild Rank Progression
**Idle Fantasy**: 17 guilds with **10 rank levels** each. Advance by completing progression quests and earning reputation through daily requests. Higher ranks unlock harder dailies and better cross-skill rewards.
**Skara Brae adaptation** (merging with existing guild design):
- Guilds have **rank tiers** within the guild (Initiate → Apprentice → Journeyman → Expert → Master → Grandmaster)
- **Daily guild tasks**: Complete for reputation points
- **Rank-up quests**: Progression quests to advance in guild rank
- **Cross-skill rewards**: Higher ranks unlock access to resources from skills you don't personally train
- Existing guild hall upgrades (training grounds, library, vault, war room, brewery) remain
---
## Church / Blessings
**Idle Fantasy**: The Church offers **timed blessings** powered by Prayer levels and bones. Three types: XP boosts (up to 1.5×), Defense bonuses, Coin multipliers. One active at a time.
**Skara Brae adaptation**:
- **Temple Row** offers blessings from the Old Gods
- Blessing types: XP boost (up to 1.5×), Damage reduction, Gold multiplier, Crit chance increase
- Duration based on Wisdom stat and offering quality
- One blessing active at a time
- Offerings: Gold, rare items, bones from undead enemies
- Higher Wisdom = longer duration, stronger effect
- This adds a "buff management" layer without being tedious
---
## Slayer Tasks
**Idle Fantasy**: Visit the Slayer Master for kill-specific-enemy assignments. Each kill earns bonus XP. Complete tasks to level Slayer skill and unlock tougher assignments.
**Skara Brae adaptation**:
- **Captain Rennick** at City Watch HQ (or **The Beggar King** for underground targets) gives slayer tasks
- "Kill 15 skeletal warriors in the Undercity" → bonus Slayer XP + gold reward
- Slayer level unlocks tougher targets with better rewards
- Ties into the bounty system naturally
---
## Quest Diversity
**Idle Fantasy**: 170+ quests — **daily quests** (reset every morning) + **long-term cumulative quests** (track progress over many sessions).
**Skara Brae adaptation**:
- **Daily quests**: 3-5 per day from NPCs (Madame Sylara, Captain Rennick, Guildmasters)
- "Complete 3 adventures" / "Craft 2 potions" / "Win 1 arena duel"
- Rewards: gold, XP, skill XP, occasional items
- **Weekly quests**: Larger goals, better rewards
- **Storyline quests**: Multi-step, unlock new areas/NPCs/mechanics
- **Cumulative achievements**: "Mine 10,000 ore total" → permanent bonus
- Quest board in the Inn + NPC-specific quest givers
---
## New Mechanics (post-2025 evolution)
These systems appeared in Idle Fantasy **after** this note was first captured (now v1.12.11) and are strong candidates to integrate into Skara Brae.
### Infinite Tower ⭐
Endless floor-by-floor combat gauntlet; enemies scale forever; **every 10 floors = a milestone** rewarding unique gear + permanent XP/coin bonuses.
**Why it fits:** Gives the BIGINT exponential stat system a natural home — infinite content matches infinite stats. We currently have dungeons + arena but **no repeatable-scaling endgame PvE**.
**Adaptation:** Reskin as **Mangar's Tower** / the Infinite Labyrinth beneath the city. Floor milestones grant small, bounded permanent bonuses (consistent with "stats only go up"). Per-floor leaderboard. → **Phase 3**.
### Expeditions ⭐⭐ (highest-value pickup)
Non-combat *skilling* dungeons tied to a gathering skill (Agility, Fishing, Mining, Thieving, Woodcutting). Completing sessions gradually uncovers **5 hidden lore notes**; collecting all 5 **unlocks a secret combat dungeon**. Advanced expeditions are gated by having unlocked an earlier dungeon — a discovery tree.
**Why it fits:** Bridges gathering skills to content gating *and* delivers lore organically — exactly the "mystery beneath Skara Brae" theme. Our notes currently silo gathering from dungeons; Expeditions unify them into one progression tree.
**Adaptation:** Each gathering skill gets 2 expedition tiers (lvl 1, lvl 40) → reveals a themed dungeon (e.g., Mining "Copper Caverns" → "Collapsed Mine"; Fishing "Sunken Grotto" → "Drowned Temple"; Thieving "Thieves' Den" → "Rogue Sanctum"). Lore notes double as world-building collectibles. → **Phase 2–3**.
### Buildings / Builder's Workshop ⭐
Upgrade town buildings (Inn, Guild Hall, Church, Fairgrounds, Garden, Queue Master, Cape Rack) with coins + **Construction** materials. Each building has tiers (0 → 3), gating a passive bonus; higher tiers require a higher Construction level.
**Why it fits:** Reframes our scattered "guild hall upgrades" into a unified **town-meta progression** the player personally drives, and gives the crafting economy a permanent gold/material sink.
**Adaptation:** Make **Construction a real skill** (see re-evaluation below). Upgradable buildings: The Singing Tavern (+worker XP), Temple Row (+blessing duration), Adventurers' Guild (−quest requirements), Market Square / Fairgrounds (carnival), Harbor, plus queue-slot and cape-rack buildings. → **Phase 2**.
### Carnival
Traveling minigame hub. **Idle minigames** convert a skill level → tickets over time (15% → 35% chance per minute, scaling to lvl 99; Archery Range=Ranged, Strongman=Strength, Wizard's Duel=Magic, Fishing Derby=Fishing). **Active minigames** (Ring Toss, Hammer Strike, Potion Sequence, Item Appraisal, Pick-a-Cup, Higher/Lower) reward more tickets on Hard, each on a 10-minute cooldown. Ticket shop sells XP lamps, gear, pets, capes.
**Why it fits:** Richer than our "inn gambling (dice/cards)"; the skill → ticket idle conversion is a clever loop. Drops onto our existing **seasonal/festival calendar** as a traveling faire.
**Adaptation:** A traveling Carnival/Faire that appears during festivals; tickets redeemed at its shop. Active minigames map onto our inn minigame table. → **Phase 3–4**.
### Pity System ("Fortune's Favor")
Escalating bad-luck protection on the rarest gear drops (IF's v1.12.10 "Divine gear pity system").
**Adaptation:** Given our 0.5% Legendary crafting + rare drops, add an escalating counter that guarantees a high-rarity result after N dry attempts. Reskin as **Fortune's Favor**. → **Phase 2**.
### Gear Scoring
Pre-dungeon, IF tells you how your current gear stacks up against the dungeon's rating (v1.12.10 gear scoring).
**Adaptation:** A recommended-power / gear-score indicator on our risk/reward adventure tiers so players self-select difficulty. → **Phase 1–2**.
### Titles (UX reinforcement)
Permanent cosmetic titles displayed as "*Name* the *Title*"; crucially, **locked titles are visible with their unlock condition** (skill-mastery = complete all quests in a skill chain; guild-max = reach lvl 10 in a guild; boss clears; seasonal events).
**Adaptation:** Our Medals & Honours note already mentions titles — **adopt IF's locked-title-with-requirement UX** as a motivator (e.g., "Master Smith," "Archmage," "Godslayer," seasonal titles kept permanently). → **Phase 2**.
### XP Lamps
Consumable that grants XP to a chosen skill (10k / 50k variants); obtained from quests, events, the Carnival shop.
**Adaptation:** Flexible catch-up / reward currency we currently lack. → **Phase 2**.
### Queue Slots (parallel sessions)
The "Queue Master" building grants additional concurrent session/queue slots.
**Adaptation:** An idle-progression lever — patrons / upgrades can run multiple offline workers/sessions in parallel. → **Phase 3**.
### Raid Bosses (confirmed)
IF's "Godslayer" title = defeat every raid boss at least once, confirming a raid-boss roster exists.
**Adaptation:** Validates designing a raid-boss roster for our guild raids (6–12 players). → **Phase 5**.
---
## Re-evaluation: Construction Skill
Original mapping (above) said Construction → "defer to property system." **Reversed.** IF now uses Construction as the backbone of the Buildings / Builder's Workshop meta. Add **Construction** as a real crafting skill in Skara Brae, feeding town-building upgrades.
---
## Process Ideas Worth Copying
- **Auto-generated wiki from game data.** IF's entire community wiki is generated from the game's data files. This validates keeping all content (items, adventures, crit tables, spells, recipes, medals, dungeons, tower floors, expeditions) as structured JSON/TOML in `skara-brae-common` — we can auto-generate both client tooltips *and* a community game wiki from a single source.
- **Layered PvE ladder.** IF matured into: expeditions → dungeons → raids → infinite tower, with buildings + carnival as parallel progression. Adopt this as our PvE spine.
---
## What NOT to Take from Idle Fantasy
- **No energy/stamina removal**: Skara Brae keeps Torn-style energy — it's a core differentiator
- **No fully offline game**: Skara Brae is multiplayer — offline is supplementary, not primary
- **No single-player focus**: Guild interaction, PvP, and economy are central to our game
---
## Related Notes
- [Game Concept Overview](joplin://9cf8a2e701654ffbbd6512cc837c7e2f) — Full game design with all features
- [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a) — Crit tables, BIGINT stats
- [Lore & World Building](joplin://867bdc9845624908a90928887a71c4c9) — Districts, NPCs, storyline
- [Tech Stack & Architecture](joplin://cecd2ef2690d4d1fba3450342aa63953) — Rust workspace, DB schema
- [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b) — Roadmap, MVP, repo structure

View file

@ -0,0 +1,129 @@
# Skara Brae — Lore & World Building
Source: Joplin note 867bdc9845624908a90928887a71c4c9, migrated 2026-10-03
## The City of Skara Brae
Skara Brae sits on a rocky wind-swept coast, where the Old Kingdom once held sway. The city is ancient — its lowest foundations predate recorded history, carved from living stone by hands unknown. Above, generations have built layer upon layer: crooked timber houses, cobblestone squares, towering keeps, and the ever-present stench of the harbor.
### Districts
| District | Description | Game Function |
|---|---|---|
| **The Harbor** | Fish markets, smuggler coves, foreign traders, ship berths | Black market, rare imports, sea adventures, **travel to offshore locations** |
| **The Lower City** | Slums, street markets, thieves' dens | Pickpocketing, fencing, cheap lodging |
| **The Market Square** | Bazaar, auctions, money changers, Garth's Equipment Shoppe | Main marketplace, bank, player shops/stalls |
| **The Crafters' Quarter** | Smithies, alchemy labs, tailor shops | Crafting, education (trades) |
| **Temple Row** | Shrines to the Old Gods, healing houses | Cleric education, healing, divine quests, **blessings**, **pet resurrection** |
| **The Academy** | Mage towers, libraries, lecture halls | Magic education, enchanting, spell learning |
| **The Arena** | Blood-stained sand, cheering crowds | PvP combat, tournaments, betting |
| **The Noble Quarter** | Manors, gardens, the City Watch HQ | Properties, burglary targets, politics, high-stakes gambling |
| **The Undercity** | Ancient catacombs, sewers, forgotten vaults | High-level dungeons, rare loot, slayer tasks |
| **The Wilds** | Forests, roads, ruins beyond the walls | Adventures, ambushes, gathering |
| **The Adventurers' Guild** | Unmarked building — must be discovered | **Review Board**: Level up, learn spells, switch spell schools, LFG board |
### Key Locations
| Location | District | Function |
|---|---|---|
| **The Singing Tavern** | Lower City | Social hub, gambling (dice, cards, arm wrestling), hire workers, daily quests from Madame Sylara, LFG board, rumors |
| **Garth's Equipment Shoppe** | Market Square | NPC shop: buy/sell basic equipment. Always open. Buys at 40% value. |
| **The Adventurers' Guild** | (Hidden — discover via quest) | Review Board: level up, learn spells, switch magic schools. Looking for Group board. Party formation. |
| **The Bank of Skara Brae** | Market Square | Deposits, interest (0.5%/day), loans (collateral required) |
| **Temple of the Dawn** | Temple Row | Healing, cleric training, blessings, pet resurrection |
| **The Arena** | Arena | PvP duels, tournaments (Arena Day), ranked matchmaking, spectating |
| **City Watch HQ** | Noble Quarter | Bounty board (Captain Rennick), slayer tasks, wanted posters |
| **The Beggar King's Lair** | Lower City sewers | Thieves' Guild contact, rogue training, underground slayer tasks |
### Travel Destinations (Offshore)
Ships depart from the Harbor. Each trip costs gold + takes real time. Travel time = risk of pirate/sea monster encounter.
| Destination | Travel Time | Description | Function |
|---|---|---|---|
| **The Iron Islands** | 1 hour | Mining colony, volcanic forges | Rare ores, high-level blacksmithing, mining adventures |
| **Stormwatch Keep** | 2 hours | Military outpost on contested coast | PvP zone, mercenary contracts, rare weapon drops |
| **The Lost Tombs** | 3 hours | Ancient ruins on a jungle island | High-level dungeon, rare loot, puzzle content |
| **The Free Ports** | 4 hours | Neutral trade hub, no PvP | Cross-faction trading, rare imports, auction house access |
| **Seasonal locations** | Varies | Event-specific destinations | Festival of Lights → Frozen Lake, Mangar's Eve → Shadow Realm, etc. |
---
## Key NPCs
| NPC | Location | Function |
|---|---|---|
| **Mangar the Dark** | (Hidden — storyline) | Main antagonist. Ancient sorcerer seeking to unseal the Old Kingdom's power beneath the city. |
| **Guildmaster Bron** | Fighters' Academy | Combat training, warrior education |
| **Madame Sylara** | The Singing Tavern | Quest giver, information broker, daily quest board |
| **Old Grist** | Harbor | Fence (buys stolen goods, no questions asked), black market dealer |
| **High Priestess Vaela** | Temple of the Dawn | Healing, cleric training, divine quests, blessings, pet resurrection |
| **Archmage Therion** | The Academy | Magic education, enchanting instructor |
| **Captain Rennick** | City Watch HQ | Bounty board, slayer tasks, wanted posters |
| **The Beggar King** | Lower City sewers | Thieves' Guild contact, rogue training, underground slayer tasks |
| **Garth** | Garth's Equipment Shoppe | NPC shopkeeper. Buys and sells equipment. |
| **The Review Board Examiner** | Adventurers' Guild | Levels up characters, administers spell exams, allows school switching |
| **Harbormaster Kael** | Harbor | Travel booking, ship departures, sea event rumors |
---
## The Main Storyline
Mirrors Bard's Tale I's dungeon progression structure:
**Act I — Arrival**: The player arrives in Skara Brae as a nobody. Tutorials, basic adventures, introduction to guilds and the city's districts. Discover the Adventurers' Guild (hidden building). Clear the Wine Cellar beneath The Singing Tavern.
**Act II — Whispers**: Strange occurrences — undead sightings in the Undercity, magical anomalies near the Academy. Players investigate the Sewers. Introduction of Mangar as a shadowy threat. Find hints about the Mad God.
**Act III — The Catacombs**: Players venture into the Catacombs beneath the Temple of the Mad God (must learn the god's name first). Defeat the Spectre, obtain the Eye. Deeper mysteries of the Old Kingdom emerge.
**Act IV — Harkyn's Castle**: Using the Eye, players access the northeastern city via Baron Harkyn's Castle. Guilds must choose sides — the city fractures. PvP becomes narratively meaningful. Alliance warfare over territory.
**Act V — The Deep**: Kylearan's Tower (archmage ally) provides the key to Mangar's Tower. Final dungeon: 5 levels beneath the city. Requires coordinated guild effort. Rotating challenges. Defeat Mangar — or discover he was merely a servant of something worse.
---
## Day/Night Cycle
| Time | Effects |
|---|---|
| **Dawn (06:00-08:00)** | Markets open, energy refresh bonus, temple blessings available |
| **Day (08:00-18:00)** | Normal gameplay, crafting bonuses, education available, safe street travel |
| **Dusk (18:00-20:00)** | Arena tournaments, market closing deals, reduced listing fees |
| **Night (20:00-06:00)** | Stealth adventures bonus, certain NPCs appear, danger increases, **random encounters when traveling between districts** |
The cycle runs on a compressed game clock (e.g., 1 game day = 4 real hours) to ensure all time zones experience all phases.
**Navigation model**: District-based for the city (click to navigate). Room-by-room exploration for dungeons (with minimap). Night travel between districts triggers random encounter chance.
---
## Calendar & Events
### Weekly
- **Moonday** — Magic bonuses (+10% spell effectiveness)
- **Tidesday** — Harbor events, rare imports, travel discounts
- **Market Day** — Reduced listing fees, special vendors at Market Square
- **Arena Day** — Tournament with prizes, betting
- **Rest Day** — Energy recovery doubled
### Monthly
- **Full Moon** — Undercity opens new passages, were-creatures appear
- **New Moon** — Thieves' Guild special contracts
### Seasonal (with temporary locations)
- **Festival of Lights** (Winter) — **Frozen Lake**: Ice fishing, ice dungeon, cosmetic rewards
- **The Hunt** (Spring) — **The Dark Forest**: World boss hunt, rare pet drops
- **Mangar's Eve** (Autumn) — **Shadow Realm**: Special dungeon, exclusive loot
- **The Great Market** (Summer) — **Bazaar of Wonders**: Rare vendors, limited-time recipes
---
## Related Notes
- [Mechanics Source Mapping](joplin://87a0f70b45c4453caae0fa2b5b8a96f9) — How BT1, RoleMaster, Idle Fantasy, and Torn City map to our mechanics
- [Game Concept Overview](joplin://9cf8a2e701654ffbbd6512cc837c7e2f) — Full game design
- [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a) — Crit tables, BIGINT stats
- [Idle Fantasy Inspirations](joplin://48b3a3c76f734c8dafbbf9e8b3b5f80a) — Idle mechanics
- [Tech Stack & Architecture](joplin://cecd2ef2690d4d1fba3450342aa63953) — Rust workspace, DB schema
- [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b) — Roadmap, MVP, repo structure

View file

@ -0,0 +1,298 @@
# Skara Brae — Mechanics Source Mapping
Source: Joplin note 87a0f70b45c4453caae0fa2b5b8a96f9, migrated 2026-10-03
How elements from each inspiration source map to Skara Brae mechanics.
---
## Sources
| Source | Type | Key Contribution |
|---|---|---|
| **The Bard's Tale I** (1985) | Dungeon crawl RPG | Setting, city structure, review board, party system, spell learning, dungeon progression |
| **RoleMaster / MERP** (1980+) | Tabletop RPG | Combat engine (d100 open-ended, crit tables), 10-stats, skill ranks, spell realms, brutality |
| **Idle Fantasy** (2024) | Mobile idle RPG | Offline sessions, hireable workers, pets, guild ranks, blessings, slayer tasks, quest diversity |
| **Torn City** (2004) | Text-based MMORPG | Crime→adventure loop, economy, factions, properties, education, PvP, billions-scale stats, casino, travel |
---
## The Mapping
### Leveling & Progression
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Review Board** | Bard's Tale I | The **Adventurers' Guild** in Skara Brae. Unmarked building (must be discovered). Only place to level up, learn new spells, and change spell schools. Pay gold + meet XP threshold. Magical exam for spellcasters (lore check). |
| **Experience points** | All | BIGINT XP. Earned from adventures, combat, crafting, quests. Level thresholds scale exponentially. |
| **Stat growth to billions** | Torn City | BIGINT stats, tiered display (K/M/B/T). Stats only go up. Training, equipment, education, and crafting all feed into stats. |
| **Skill ranks via development points** | RoleMaster | Skills leveled through use (not point-buy). Each skill has its own XP bar. Higher ranks = logarithmic cost increase. |
| **Education courses** | Torn City | Schools (Fighters' Academy, College of Magic, Thieves' Den, Merchants' Guild). Real-time courses, permanent bonuses. Some adventures require prerequisites. |
### Spell System
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Spell schools as classes** | Bard's Tale I | Magician (offensive), Conjurer (summoning), Sorcerer (debilitating), Wizard (utility). Mages can switch schools at the Review Board. Master all four = Archmage title (cosmetic + achievement). |
| **Spell learning at Review Board** | Bard's Tale I | Must visit the Adventurers' Guild to learn new spells after leveling. Each spell costs gold + requires minimum skill level. Spell codes replaced by meaningful names. |
| **Three realms of magic** | RoleMaster | **Essence** (wizards — raw magical energy), **Channeling** (clerics — divine power from Old Gods), **Mentalism** (bards/psionics — mind power). Each realm has open lists (available to all) and closed lists (class-restricted). |
| **Bard songs as spells** | Bard's Tale I | Bard songs function as long-duration buffs. Strengthen armor, increase attack speed, heal over time, boost skill XP. Certain puzzles/adventures require specific songs. |
| **85 spells** | Bard's Tale I | Target: 60-80 spells at launch across all realms and schools. Expandable via updates. |
### Combat
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **d100 open-ended roll** | RoleMaster | All attacks roll d100 open-ended (96-100: roll again and add). Creates rare but exciting high rolls. |
| **Critical tables by weapon type** | RoleMaster | Slash, crush, puncture, unarmed crit tables. Each maps roll range to damage multiplier + status effect (bleed, stun, disarm, cripple, blind). Tables stored in `skara-brae-common/crit-tables/`. |
| **Crit damage capped by level difference** | Original design | Equal level = full crit. +50 levels = 15% cap. +100 = 5% cap. Status effects always apply. Low levels can disrupt, not kill. |
| **Armor type vs. weapon cross-reference** | RoleMaster | Attack tables cross-index weapon type against armor type (unarmored, leather, chain, plate). Heavy armor reduces crit severity. |
| **Concussion hits** | RoleMaster | Normal hits (non-crit) = concussion damage. Accumulates, can knock unconscious. Natural recovery over time. |
| **Body part damage** | RoleMaster | Crit rolls determine hit location (head, torso, arms, legs). Location affects which status effects apply. Head crits = stun. Arm crits = disarm. Leg crits = cripple. |
| **Resistance rolls (RR)** | RoleMaster | Magic attacks require resistance roll: d100 + Will stat vs. spell difficulty. Failed RR = full effect. Partial success = reduced effect. Success = resisted. |
| **Turn-based combat** | Bard's Tale I | Combat is turn-based/text-based. Choose actions each round. Manage stamina, mana, positioning (front/back rank). |
| **Party combat (6 characters)** | Bard's Tale I | See Party System below. |
### Adventures & Dungeons
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Crime tiers** | Torn City | Adventures in risk/reward tiers: Safe (pick pockets) → Moderate (burglary) → Dangerous (dungeon raid) → Extreme (Undercity deep). Higher tiers = better rewards, more energy cost, higher failure chance. |
| **Dungeon progression** | Bard's Tale I | Sequential dungeons with prerequisites: Wine Cellar → Sewers → Catacombs → Harkyn's Castle → Kylearan's Tower → Mangar's Tower. Each unlocks the next. Later dungeons require items/keys from earlier ones. |
| **Random encounters on city streets** | Bard's Tale I | Moving between districts at night triggers random encounters. Higher danger districts = harder encounters. Daytime = mostly safe. |
| **Dungeon puzzles and riddles** | Bard's Tale I | Dungeons include locked doors (lockpicking check), riddles (lore check), magical barriers (spell requirement), and boss mechanics. |
| **Racing → Idle adventuring** | Torn City + Idle Fantasy | **Expeditions**: Send your character (or a hired worker) on a timed expedition to a dungeon or adventure zone. Takes 15 min to 1 hour. Returns with loot. Reduced rewards (60%) compared to active play. Energy consumed while on expedition. Comparable to Torn's racing (timed event with wager → payout). |
| **Organized crime → Guild raids** | Torn City | **Guild raids**: Cooperative dungeon runs requiring 4-6 guild members. Each member contributes. Rewards split. Guild treasury gets a cut. Weekly cooldown. |
### City & Navigation
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **30×30 city grid** | Bard's Tale I | **Decision needed**: Full MUD-style room-by-room map, or district-based navigation? See Map Question below. |
| **Named streets and buildings** | Bard's Tale I | Key locations are named (Rakhir Street, The Singing Tavern, Garth's Equipment Shoppe). Even with district navigation, these names persist as flavor. |
| **Locked gates / guardian statues** | Bard's Tale I | Certain districts require keys, quest completion, or level thresholds to access. The Undercity requires a password from a quest. The Noble Quarter requires property ownership or guild rank. |
| **District-based navigation** | Torn City | Click on a district, see available actions. Fast, mobile-friendly, no spatial navigation needed. |
| **Christmas Town** | Torn City | **Seasonal locations**: Temporary areas that appear during seasonal events. Festival of Lights → Frozen Lake (ice fishing, ice dungeon). Mangar's Eve → Shadow Realm (special dungeon). The Great Market → Bazaar of Wonders (rare vendors). These locations disappear after the event. |
| **Travel (off-shore)** | Torn City | **Travel system**: Take a ship from the Harbor to offshore locations. Each trip costs gold + takes real time (1-4 hours). Destinations: The Iron Islands (mining colony, rare ores), Stormwatch Keep (military outpost, PvP zone), The Lost Tombs (ancient ruins, high-level dungeon), The Free Ports (neutral trade hub, no PvP). Travel time = opportunity for ambush by pirates or sea monsters. |
#### Map Question: MUD-Style vs. District Navigation
**Option A: MUD-Style Room Map**
- 30×30 grid (like BT1), each tile is a "room" with description, exits, and possible encounters
- Players navigate with cardinal directions (N/S/E/W)
- Feels immersive, authentic to BT1 roots
- Problem: Tedious on mobile. Hard to make feel good in a web UI. Most players would find it annoying.
- Works if we want a true MUD feel
**Option B: District-Based Navigation (Recommended)**
- City has 10 districts (already defined). Click a district → see available locations and actions.
- Within districts, specific locations (The Singing Tavern, Garth's Shoppe) are clickable destinations.
- Dungeons are separate instances (enter → turn-based combat + exploration).
- Problem: Less immersive. Loses the BT1 city-as-maze feel.
- Works best for web/mobile, fast navigation, Torn-like UX
**Option C: Hybrid**
- District navigation for the main city (fast, mobile-friendly)
- Dungeons use room-by-room exploration with a minimap (MUD/MUD2 style)
- City streets at night can trigger random encounters when traveling between districts (without full room navigation)
- Best of both worlds: fast city navigation, immersive dungeon crawling
- The BT1 city-as-maze can be a special dungeon instance ("Skara Brae: The Eternal Winter" — a flashback to Mangar's original attack)
**Recommendation**: Option C (Hybrid). District nav for city, room-by-room for dungeons. Night travel has encounter chance.
### Economy
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Bazaar / Item market** | Torn City | Player-driven marketplace. List items for sale. Search, filter, buy. Transaction fee (gold sink). |
| **Garth's Equipment Shoppe** | Bard's Tale I | NPC shop with basic equipment. Always available. Sells low-to-mid tier gear. Buys items at 40% value. |
| **Auction House** | Torn City | Rare items, timed auctions. 24-72 hour listings. Buyout option. |
| **Bank of Skara Brae** | Torn City | Deposit gold, earn interest (0.5%/day). Loans available (collateral required). |
| **Casino → Inn games** | Torn City | **The Singing Tavern** offers gambling: Dice (craps variant), Cards (fantasy poker), Arm Wrestling (strength check), Shell Game (perception check). Wager gold, win or lose. House edge ensures long-term gold sink. High-stakes table in the back room (Noble Quarter access). |
| **Stock market → Merchant ventures** | Torn City | Invest in trading caravans departing from the Harbor. Returns depend on random events (pirates, storms, bandits, rare finds). Check results after 24 hours. |
| **Player shops/stalls** | Torn City | Set up a stall in the Market Square. List items at custom prices. Stall rent = gold sink. Higher rent = better location (more traffic). |
| **Fencing stolen goods** | Torn City | **Old Grist** at the Harbor buys stolen goods. Lower prices than market but no questions asked. Thievery skill affects quality of goods you can fence. |
### Guilds & Clans
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Factions** | Torn City | **Guilds** (already designed). Player organizations with hierarchy, guild hall, territory, treasury, taxation, wars. Guild rank progression (10 ranks). |
| **Companies** | Torn City | **Clans** — a separate system from guilds. Clans are player-run businesses/cooperatives. |
| **Clan types** | Original design | Clan types: Trading Company (market bonuses), Mercenary Band (PvP bonuses), Crafting Cooperative (crafting bonuses), Exploration Society (adventure bonuses). A player can be in one guild AND one clan simultaneously. Guilds are about power/territory. Clans are about economic specialization. |
| **Guild wars** | Torn City | Territory control through raids. Formal war declaration. Surrender terms. Winner takes territory + treasury portion. |
| **Alliances** | Torn City | Guild-to-guild treaties. Non-aggression pacts, trade agreements, mutual defense. Alliance chat channel. |
| **Guild Adventures** | Torn City | Cooperative activities requiring multiple members (→ Torn's organized crimes). Weekly cooldown. |
### Party System & Grouping
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Party of 6 characters** | Bard's Tale I | **Parties of 2-4 players** (not 6 characters per player). Group up for adventures and dungeons. Party leader chooses destination. Loot distributed by configured rules (need/greed, round-robin, leader assigns). |
| **Front/back rank** | Bard's Tale I | Combat positions: Front rank (melee, takes hits first) and back rank (ranged/magic, protected). Party leader assigns positions. |
| **Adventurer's Guild party board** | Bard's Tale I | **Looking for Group board** at the Adventurers' Guild. Post: "Looking for healer for Catacombs run" or "Need tank for guild raid." Players apply, leader accepts. |
| **Group bonuses** | MMORPGs | Party of 2: +10% XP. Party of 3: +20% XP. Party of 4: +30% XP. Encourages grouping without making it mandatory. |
| **NPC party members** | Bard's Tale I | Hire **mercenaries** from the inn to fill empty party slots. Cost gold per adventure. Lower stats than players, no special abilities. Better than nothing for solo players attempting hard content. |
| **Raid content** | MMORPGs | **Guild raids**: 6-12 players in an instanced dungeon. Boss mechanics require coordination. Weekly lockout. Best loot in the game. |
### Races (Conservative)
Drawing from all fantasy settings but keeping it traditional:
| Race | Bonus | Penalty | Lore |
|---|---|---|---|
| **Human** | +Charisma, adaptable | None (jack of all trades) | Most numerous. Run the City Watch, merchant houses, and government. |
| **Dwarf** | +Constitution, +Smithing | -Agility | Clan-based hill-dwellers. Run the best forges in the Crafters' Quarter. |
| **Elf** | +Intelligence, +Perception | -Strength | Ancient, declining race. Tied to the Old Kingdom's magic. Run the Academy. |
| **Halfling** | +Agility, +Thievery | -Strength | Nimble, underestimated. Run the smuggling routes at the Harbor. |
| **Half-Orc** | +Strength, +Intimidation | -Intelligence | Marginalized. Often found in the Arena or as mercenaries. |
| **Half-Elf** | +Charisma, +Magic | -Constitution | Bridge between human and elven societies. Often diplomats or bards. |
**Decision**: Keep the 6 races from the current design. Conservative, well-understood, no weird ones.
### Classes (Conservative)
| Class | Role | Key Abilities | Source Inspiration |
|---|---|---|---|
| **Warrior** | Tank / Melee DPS | Heavy armor, weapon mastery, shield skills | BT1 Warrior, RM Fighter |
| **Rogue** | DPS / Utility | Stealth, lockpicking, poison, backstab (high crit chance) | BT1 Rogue, RM Thief |
| **Mage** | Ranged DPS | 4 spell schools (Magician, Conjurer, Sorcerer, Wizard). Switch schools at Review Board. | BT1 Magician/Conjurer/Sorcerer/Wizard, RM Essence user |
| **Bard** | Support / Buffs | Bard songs (long-duration buffs), lore skills, social bonuses, minor healing | BT1 Bard, RM Bard |
| **Cleric** | Healer / Support | Channeling spells (healing, protection, undead turning), blessings | RM Channeling user, D&D Cleric |
| **Ranger** | Ranged DPS / Survival | Bow mastery, tracking, wilderness survival, minor nature magic | BT1 Hunter, RM Ranger |
| **Paladin** | Tank / Healer hybrid | Heavy armor + minor healing, undead bonuses, aura buffs | BT1 Paladin, D&D Paladin |
| **Monk** | Melee DPS / Evasion | Unarmed combat, high dodge, stunning blows, meditation (mana recovery) | BT1 Monk, RM Monk |
**Decision**: 8 classes. The original 6 + Paladin and Monk (both in BT1). Conservative, recognizable archetypes. Each class has a clear role.
### Properties & Housing
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Properties** | Torn City | Buy/rent dwellings: Straw bed at inn → Room at boarding house → Apartment → House → Tower. Properties provide: energy recovery rate, storage capacity, crafting station quality, pet stable size. |
| **Upgrades** | Torn City | Upgrade properties: Add a forge (blacksmithing bonus), library (education speed bonus), garden (herbalism yield), wine cellar (entertaining bonus). |
| **Rent** | Torn City | Properties have weekly rent. Fail to pay = locked out (items in storage). Pay back rent to regain access. Permanent ownership available for high gold cost. |
### Pets & Companions
(Fully designed in Idle Fantasy Inspirations note)
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Collectible pets** | Idle Fantasy | Rare drops from enemies. Provide passive bonuses. |
| **Pet breeding** | Idle Fantasy | Combine pets for rare offspring. |
| **Pet death in PvP** | Original design | Pets can be killed, resurrected at temple. Creates stakes. |
### Crafting
(Fully designed in Game Concept Overview note)
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **23 skills** | Idle Fantasy | Mapped to 5 gathering + 7 crafting + combat + support skills. |
| **Quality rolls** | Original design | Common → Legendary quality tiers with crafting crits (RM-inspired). |
| **Crafting professions** | Idle Fantasy / RM | 12 professions with mastery levels (Novice → Grandmaster). |
### Quest System
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Main storyline (5 acts)** | Bard's Tale I | Mangar the Dark as antagonist. 5-act progression mirroring BT1's dungeon sequence. |
| **Daily quests** | Idle Fantasy | 3-5 daily quests from NPCs. Quick goals, moderate rewards. |
| **Weekly quests** | Torn City | Larger goals, better rewards. |
| **Cumulative achievements** | Idle Fantasy | "Mine 10,000 ore total" → permanent bonus. Long-term engagement. |
| **Slayer tasks** | Idle Fantasy | Kill-specific-enemy assignments from Captain Rennick or The Beggar King. |
| **Bounty board** | Torn City | Player-posted and NPC-posted bounties on other players. |
| **Riddles and puzzles** | Bard's Tale I | Dungeon-specific puzzles requiring lore knowledge, bard songs, or specific items. |
### World & Events
| Mechanic | Source | Skara Brae Adaptation |
|---|---|---|
| **Day/night cycle** | Original design | Compressed clock (1 game day = 4 real hours). Night = stealth bonuses, danger increases. |
| **Calendar events** | Original design | Moonday (magic bonus), Market Day (reduced fees), Arena Day (tournaments). |
| **Seasonal events** | Torn City | Festival of Lights, The Hunt, Mangar's Eve, The Great Market. Each with temporary locations (like Torn's Christmas Town). |
| **Dynamic world events** | Original design | Plague, invasion, festival. City-wide events affecting all players. |
| **Weather** | RoleMaster | Affects combat (rain = ranged penalty, fog = stealth bonus) and gathering (rain = herbalism bonus). |
---
## Summary: What Each Source Primarily Contributes
### Bard's Tale I — Setting & Structure
- The city of Skara Brae (setting, districts, key locations)
- Review Board (leveling, spell learning)
- Adventurer's Guild (character management, LFG board)
- Party-based combat with front/back rank
- Dungeon progression with prerequisites
- Mangar as antagonist
- Named locations (Garth's Shoppe, Rakhir Street)
- Spell schools (Magician, Conjurer, Sorcerer, Wizard → Archmage)
- Bard songs as buffs
- Paladin and Monk classes
### RoleMaster / MERP — Combat Engine
- d100 open-ended roll system
- Critical tables by weapon type (slash, crush, puncture, unarmed)
- Attack vs. armor cross-reference tables
- Body part damage with status effects
- Resistance rolls for magic
- Concussion hits vs. critical hits
- Three realms of magic (Essence, Channeling, Mentalism)
- 10 stats (expanded to fit our 6-stat system)
- Skill rank progression
- Brutality: any level can critically affect any level (adapted with caps)
### Idle Fantasy — Idle & Progression Mechanics
- Offline sessions (1-hour cap)
- Hireable NPC workers (inn system)
- Pet collection and passive bonuses
- Guild rank progression (10 ranks with daily tasks)
- Blessings/church system
- Slayer tasks
- Daily + cumulative quest system
- 23-skill framework (adapted to our profession system)
- Quality tiers in crafting
- Provision buying in bulk
### Torn City — Economy & Long-Term Engagement
- Crime → adventure loop with energy system
- Billions-scale stat growth (BIGINT)
- Player-driven economy (bazaar, auctions, bank, market)
- Properties and housing with rent
- Education system (real-time courses)
- Casino → inn gambling games
- Racing → expeditions (timed adventures)
- Travel to offshore locations
- Factions → guilds (with territory wars)
- Companies → clans (economic specialization)
- Stock market → merchant ventures
- Bounty system
- PvP (arena + ambush)
- Patron subscription (ethical F2P)
- Community API from day one
- Seasonal events with temporary locations (Christmas Town)
---
## Open Design Questions
- [ ] **Map system**: Hybrid recommended (district nav for city, room-by-room for dungeons). Confirm?
- [ ] **Clan system**: Separate from guilds? One guild + one clan per player?
- [ ] **Party size**: 2-4 players? Up to 4+2 (4 players + 2 NPCs)?
- [ ] **Raid size**: 6? 12? For guild raid content.
- [ ] **Travel time**: 1-4 hours real time for offshore locations? Too long? Too short?
- [ ] **Spell school switching**: Allow mages to switch schools freely at Review Board, or restrict (cooldown, cost)?
- [ ] **Archmage**: Cosmetic title + achievement for mastering all spell schools? Or gameplay bonus?
- [ ] **Mercenary NPCs**: How strong? Flat % of player stats? Fixed stat range by hire cost?
---
## Related Notes
- [Game Concept Overview](joplin://9cf8a2e701654ffbbd6512cc837c7e2f) — Full game design
- [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a) — Crit tables, BIGINT stats
- [Idle Fantasy Inspirations](joplin://48b3a3c76f734c8dafbbf9e8b3b5f80a) — Idle mechanics
- [Lore & World Building](joplin://867bdc9845624908a90928887a71c4c9) — Districts, NPCs, storyline
- [Tech Stack & Architecture](joplin://cecd2ef2690d4d1fba3450342aa63953) — Rust workspace, DB schema
- [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b) — Roadmap, MVP, repo structure

View file

@ -0,0 +1,358 @@
# Skara Brae — Medals & Honours System (Torn City-Inspired)
Source: Joplin note 4877acc671ed4bfcb0d6bf2c5323c94a, migrated 2026-10-03
> **Goal**: A deep, profile-defining achievement system in the spirit of **Torn City's Honours/Awards** — long-term goals, bragging rights, rare prestige, and a *few* meaningful permanent bonuses — layered onto every existing Skara Brae system (combat, adventure, crafting, magic, guild, economy, etc.).
Torn City's honours are a major long-term retention driver: hundreds of awards across every activity, displayed on the profile, some granting small permanent stat boosts. Skara Brae adapts this into a fantasy-flavoured, **three-tier** structure: **Medals** (tiered, category-based) → **Honours** (rare, prestigious, single awards) → **Titles** (displayed name prefixes/suffixes).
---
## 1. System Overview
| Layer | What It Is | How Earned | Reward Style |
|---|---|---|---|
| **Medals** | Tiered achievement badges, organized by category | Cumulative thresholds across gameplay | Mostly cosmetic; some grant small permanent bonus per tier |
| **Honours** | Rare, prestigious single awards for exceptional feats | Specific hard/rare accomplishments | Display + a few grant permanent bonus |
| **Titles** | Name prefixes/suffixes shown with character name | Unlocked by medals/honours | Cosmetic only |
| **Hall of Fame** | Leaderboards / rankings | Top N per category, season & all-time | Bragging rights + seasonal cosmetic |
**Design guardrail**: Permanent gameplay bonuses from honours/medals are **small, %-based, and collectively capped** (max ~+10% total across all sources) so this rewards dedication without creating unbridgeable gaps or pay-to-win pressure. The bulk of the value is **cosmetic prestige + long-term goals**.
---
## 2. Medals — Tiered Badges by Category
Each medal has **5 tiers**. Cross a threshold → earn that tier (and upgrade the badge on your profile). Tiers are cumulative counters tracked per character.
### Tier Progression (Fantasy-Flavoured)
| Tier | Name | Relative Rarity |
|---|---|---|
| T1 | **Copper** | Common — early game |
| T2 | **Silver** | Uncommon — mid game |
| T3 | **Gold** | Rare — dedicated players |
| T4 | **Platinum** | Very rare — long-term veterans |
| T5 | **Dragon** | Legendary — top-tier devotees |
### 2.1 Medal Categories & Examples
> Thresholds are illustrative; final values set in tuning. A medal marked ⚡ grants a small permanent bonus at one or more tiers (see §4 for the bonus catalogue).
#### ⚔️ Combat (PvP & PvE)
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Pit Fighter (arena wins) | 10 | 100 | 1,000 | 10,000 | 50,000 | ⚡ +arena XP |
| Ambusher (successful ambushes) | 5 | 50 | 500 | 2,500 | 10,000 | — |
| Survivor (survive lethal attacks <10% HP) | 1 | 10 | 50 | 200 | 1,000 | — |
| Crit Master ⚡ (critical hits landed) | 100 | 1,000 | 10,000 | 100,000 | 500,000 | +crit chance |
| Flawless (win combat without taking damage) | 5 | 50 | 250 | 1,000 | 5,000 | — |
| Duelist (1v1 ranked wins) | 10 | 100 | 500 | 2,000 | 10,000 | ⚡ +duel rewards |
| Dungeon Clearer (dungeons completed) | 1 | 10 | 50 | 200 | 1,000 | — |
#### 🗡️ Adventure (→ Torn's Crimes)
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Pickpocket (successful pickpockets) | 10 | 100 | 1,000 | 10,000 | 50,000 | — |
| Burglar (manors/vaults broken into) | 1 | 25 | 100 | 500 | 2,000 | — |
| Fencer (stolen goods fenced) | 10 | 100 | 1,000 | 10,000 | 50,000 | ⚡ +fence value |
| Waylayer (travelers waylaid) | 5 | 50 | 500 | 2,500 | 10,000 | — |
| Dungeon Raider (guild raids completed) | 1 | 5 | 25 | 100 | 500 | — |
| Adventurer (total adventures completed) | 100 | 1,000 | 10,000 | 50,000 | 250,000 | ⚡ +adventure gold |
| Night Owl ⚡ (nighttime adventures) | 50 | 500 | 5,000 | 25,000 | 100,000 | +stealth at night |
#### 🔨 Crafting & Gathering
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Smith (items crafted) | 10 | 100 | 1,000 | 10,000 | 50,000 | — |
| Artisan (Superior+ quality crafted) | 5 | 50 | 500 | 2,500 | 10,000 | — |
| Mastercraft (Masterwork crafted) | 1 | 10 | 50 | 200 | 1,000 | ⚡ +crafting crit |
| Legendary Forger (Legendary crafted) | 1 | 5 | 25 | 100 | 500 | — |
| Miner's Grit ⚡ (ore mined) | 1K | 10K | 100K | 1M | 10M | +gathering yield |
| Herbalist (herbs gathered) | 1K | 10K | 100K | 1M | 10M | — |
| Polymath (all 12 professions to Journeyman) | — | 1 | — | all to Expert | all to Master | ⚡ +crafting XP |
#### ✨ Magic & Skills (feeds the Skill/Magic System)
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Apprentice (any skill to rank 10) | 1 | 5 | 12 | 25 | 50 skills | — |
| Spellweaver (spells learned) | 5 | 25 | 75 | 150 | 250 | — |
| List Master ⚡ (spell list maxed) | 1 | 3 | 6 | 10 | 20 lists | +PP regen |
| Archmage (all 4 Essence schools mastered) | — | — | — | 1 | — | ⚡ +casting bonus |
| Loremaster (all Lore skills rank 20) | — | — | 1 | — | — | — |
| Jack of All Trades ⚡ (skills at rank 20+) | 5 | 15 | 30 | 50 | 80 | +DP gain |
#### 💰 Economy
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Coinpurse (total gold earned) | 10K | 1M | 100M | 10B | 1T | — |
| Tycoon ⚡ (net worth milestone) | 100K | 10M | 1B | 100B | 10T | +bank interest |
| Merchant (market trades completed) | 10 | 100 | 1,000 | 10,000 | 50,000 | ⚡ -listing fees |
| Gambler (inn games won) | 10 | 100 | 1,000 | 5,000 | 25,000 | — |
| Speculator (merchant ventures profited) | 1 | 10 | 50 | 200 | 1,000 | — |
#### 🛡️ Guild & Social
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Loyalist (guild tenure) | 1mo | 6mo | 1yr | 2yr | 5yr | — |
| War Hero (guild wars won) | 1 | 5 | 25 | 100 | 500 | ⚡ +guild rep gain |
| Benefactor (gold donated to guild) | 10K | 1M | 100M | 10B | 1T | — |
| Reputation (social reputation points) | 100 | 1K | 10K | 100K | 1M | — |
| Carouser ⚡ (inn carousing sessions) | 10 | 100 | 1,000 | 5,000 | 25,000 | +charisma temp |
#### 🏹 Slayer & Hunting
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Slayer (tasks completed) | 1 | 10 | 50 | 250 | 1,000 | ⚡ +slayer XP |
| Bounty Hunter (bounties claimed) | 1 | 10 | 50 | 250 | 1,000 | — |
| Exterminator (total enemies slain) | 100 | 1K | 10K | 100K | 1M | — |
| Rare Game (rare/elite enemies killed) | 1 | 10 | 50 | 200 | 1,000 | — |
#### 🗺️ Exploration
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Pathfinder (districts discovered) | 3 | 6 | all 11 | — | — | — |
| Voyager (offshore trips) | 1 | 5 | 25 | 100 | 500 | — |
| Tomb Raider (Lost Tombs cleared) | 1 | 5 | 25 | 100 | 500 | — |
| World Walker (all travel destinations visited) | — | — | — | — | 1 | — |
#### 🎪 Events & Seasonal
| Medal | Copper | Silver | Gold | Platinum | Dragon | Bonus? |
|---|---|---|---|---|---|---|
| Festival Goer (seasonal events joined) | 1 | 3 | 6 | 12 | 24 | — |
| The Hunt Champion (world boss dealt final blow) | — | — | 1 | 3 | 10 | — |
| Mangar's Eve survivor | — | 1 | 3 | 5 | 10 | — |
### 2.2 Hidden Medals
A subset of medals are **hidden** (like Torn's secret honours) — the name/description is `???` until earned. Examples: discover the Adventurers' Guild, find a hidden room in a dungeon, fence goods to Old Grist 100 times. Creates exploration-driven surprise and community wiki culture.
---
## 3. Honours — Rare Prestige Awards
Honours are **single, non-tiered** awards for exceptional, hard, or one-off accomplishments. Far rarer than medals. Displayed in a dedicated "Honours" ribbon on the profile. Each has a unique fantasy name and flavour text.
| Honour | Requirement | Bonus? | Notes |
|---|---|---|---|
| **First Light** | Be among the first 100 characters to reach level 50 | ⚡ +1% all XP | World-first cohort |
| **Dragonslayer** | Deal the final blow to a Dragon-tier world boss | ⚡ +2% damage to bosses | Coordination feat |
| **Archmage of Skara Brae** | Master all four Essence schools (Archmage) | ⚡ +5% spell effectiveness | Magic capstone |
| **Grandmaster Artisan** | Reach Grandmaster in all 12 professions | ⚡ +crafting crit chance | Ultimate crafter |
| **Unbroken** | Win 100 arena duels without a single loss streak | ⚡ +arena prestige | Combat excellence |
| **The Untouchable** | Reach level 50 without ever being ambushed/defeated | ⚡ +1% dodge | Pure PvE run |
| **Mangar's Bane** | Complete Act V (defeat Mangar) | ⚡ +title "Bane of Mangar" | Storyline capstone |
| **Citizen of the Year** | Win a seasonal Hall of Fame #1 | Cosmetic title | Seasonal |
| **Lucky Devil** | Roll an upward open-ended 200+ (any maneuver) | — | RNG flex |
| **Iron Will** | Resist 100 spells via Resistance Roll | ⚡ +5 RR | Anti-magic |
| **The Beggar King's Shadow** | Max all underground slayer tasks | ⚡ +stealth | Rogue capstone |
| **Champion of the Dawn** | Complete all of High Priestess Vaela's divine quests | ⚡ +blessing duration | Cleric capstone |
| **Patron of the Arts** | Hire 1,000 gold worth of inn workers | — | Gold-sink flex |
| **Survivor of the Deep** | Clear the Undercity without a party member falling | ⚡ +Undercity rewards | Solo/coordination |
Honours are intentionally **curated and limited** (target: ~40 at launch, expandable). They're the "wow" awards that make a profile stand out.
---
## 4. Permanent Bonuses — Bounded & Capped
The ⚡ bonuses are the main gameplay incentive. To prevent power creep:
- Each ⚡ bonus is **small**: typically +1% to +5% in its niche.
- **Collective cap**: total bonus from all honours + medals combined is capped at **+10%** per category of effect (e.g., max +10% combat-related, +10% crafting-related, etc.). Beyond the cap, additional ⚡ awards are cosmetic-only.
- **Diminishing stacking**: multiple sources of the same effect stack *multiplicatively with diminishing returns* (e.g., two +5% crit bonuses = 1 - (0.95)(0.95) = +9.75%, not +10%).
- **Cosmetic is king**: most medals/honours are display-only. The bonuses are seasoning, not the meal.
This mirrors Torn, where honours give tiny permanent stat bumps — enough to matter to min-maxers, not enough to invalidate progression.
---
## 5. Titles
Earned from medals/honours. One **active title** displayed with the character name (e.g., in chat, combat, profile). Players can switch their active title freely from earned titles.
| Title | Source |
|---|---|
| the Pit Fighter | Pit Fighter medal (Gold) |
| Slayer of the Deep | Survivor of the Deep honour |
| Bane of Mangar | Mangar's Bane honour |
| Archmage | Archmage honour |
| the Coin-King / Coin-Queen | Tycoon medal (Platinum) |
| Dragonslayer | Dragonslayer honour |
| Grandmaster | Grandmaster Artisan honour |
| Loremaster | Loremaster medal |
| Shadow / the Unseen | Beggar King's Shadow honour |
| of the Dawn | Champion of the Dawn honour |
Titles are **purely cosmetic** — no mechanical effect. They're the social currency of prestige.
---
## 6. Hall of Fame / Leaderboards
Redis-backed leaderboards (already in the tech stack) power the Hall of Fame:
| Board | Scope | Reset |
|---|---|---|
| Combat ranking | PvP rating | Seasonal (monthly) + all-time |
| Wealth ranking | Net worth | All-time |
| Adventure ranking | Adventures completed (season) | Seasonal |
| Crafting ranking | Items crafted (season) | Seasonal |
| Guild ranking | Guild reputation | Seasonal + all-time |
| Slayer ranking | Slayer tasks (season) | Seasonal |
Top 3 / Top 10 / Top 100 each season earn a **seasonal honour + cosmetic**. All-time leaders are enshrined permanently.
---
## 7. Profile Display
A character's profile (viewable by others, like Torn's profile page) shows:
- **Honours ribbon** — row of rare honour icons (the flex zone)
- **Medal case** — categorized medal badges with earned tiers; unearned show greyed silhouettes (hidden medals show `???`)
- **Active title** — prefix/suffix on the name
- **Hall of Fame badges** — seasonal & all-time rankings
- **Featured medal** — player picks one medal to feature prominently
This creates the Torn-style "let me see how impressive this player is at a glance" profile.
---
## 8. Database Schema (Draft)
```sql
-- Medal definitions (static game data, in skara-brae-common)
-- (could be JSON/TOML in common repo; shown as SQL for schema context)
CREATE TABLE medal_definitions (
id VARCHAR(64) PRIMARY KEY, -- 'pit_fighter'
category VARCHAR(32) NOT NULL,
name VARCHAR(64) NOT NULL,
description TEXT NOT NULL,
is_hidden BOOLEAN NOT NULL DEFAULT FALSE,
-- tier thresholds as JSON array: [10,100,1000,10000,50000]
thresholds JSONB NOT NULL
);
-- Character medal progress (highest tier earned + current count)
CREATE TABLE character_medals (
character_id UUID NOT NULL REFERENCES characters(id),
medal_id VARCHAR(64) NOT NULL REFERENCES medal_definitions(id),
count BIGINT NOT NULL DEFAULT 0,
highest_tier SMALLINT NOT NULL DEFAULT 0, -- 0..5
PRIMARY KEY (character_id, medal_id)
);
-- Honour definitions
CREATE TABLE honour_definitions (
id VARCHAR(64) PRIMARY KEY,
name VARCHAR(64) NOT NULL,
description TEXT NOT NULL,
bonus_json JSONB, -- null if cosmetic
title VARCHAR(64) -- granted title, if any
);
-- Character honours earned
CREATE TABLE character_honours (
character_id UUID NOT NULL REFERENCES characters(id),
honour_id VARCHAR(64) NOT NULL REFERENCES honour_definitions(id),
earned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (character_id, honour_id)
);
-- Earned titles
CREATE TABLE character_titles (
character_id UUID NOT NULL REFERENCES characters(id),
title VARCHAR(64) NOT NULL,
source VARCHAR(64) NOT NULL, -- honour_id or medal_id
earned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (character_id, title)
);
ALTER TABLE characters ADD COLUMN active_title VARCHAR(64);
ALTER TABLE characters ADD COLUMN featured_medal VARCHAR(64);
```
Counters that feed medals (arena wins, crits, gold earned, etc.) are best stored as **existing gameplay columns** or a lightweight `character_counters` key-value table to avoid schema bloat:
```sql
CREATE TABLE character_counters (
character_id UUID NOT NULL REFERENCES characters(id),
counter_key VARCHAR(48) NOT NULL, -- 'arena_wins', 'crits_landed', ...
value BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (character_id, counter_key)
);
```
---
## 9. API Additions (Draft)
```
# Profile / medals / honours (public-ish)
GET /api/profile/:character_id # overview incl. medals, honours, title
GET /api/character/medals # own medals + progress + hidden (revealed only)
GET /api/character/honours # own honours
PUT /api/character/active-title # set active title
PUT /api/character/featured-medal # set featured medal
# Hall of Fame
GET /api/leaderboard/:board # seasonal or all-time rankings
```
A new WebSocket notification type for medal/honour unlocks:
```json
{ "type": "achievement:unlock", "data": { "kind": "medal", "id": "crit_master", "tier": 3, "name": "Crit Master", "bonus": "+1% crit chance" } }
{ "type": "achievement:unlock", "data": { "kind": "honour", "id": "dragonslayer", "name": "Dragonslayer" } }
```
---
## 10. Integration With Existing Systems
| Existing System | Integration |
|---|---|
| **Cumulative achievements** (existing design) | *Replaced/augmented* by medals. "Mine 10,000 ore" → Miner's Grit medal. |
| **Skill & Magic System** (new) | Skill ranks, spell lists mastered, Archmage, Jack of All Trades all feed medals/honours. |
| **Combat crit tables** | Crit Master medal tracks crits landed. |
| **Crafting quality tiers** | Artisan / Mastercraft / Legendary Forger medals track quality outcomes. |
| **Adventures / crimes** | Pickpocket, Burglar, Fencer, Adventurer medals mirror Torn crime milestones. |
| **Guilds / Clans** | War Hero, Benefactor, Loyalist medals; seasonal guild HOF. |
| **Slayer / Bounty** | Slayer, Bounty Hunter medals. |
| **Economy** | Coinpurse, Tycoon, Merchant medals; wealth HOF. |
| **Seasonal events** | Festival Goer, seasonal HOF "Citizen of the Year" honour. |
| **Redis** (tech stack) | Powers leaderboards + counter aggregation for medal thresholds. |
---
## 11. MVP / Phasing
- **Phase 1 (MVP)**: Medal *counters* + a handful of combat/adventure medals (cosmetic only). Profile shows medal case. Lays the tracking infrastructure.
- **Phase 2**: Full medal categories, ⚡ bonuses (capped), Honours, Titles, profile ribbon.
- **Phase 3**: Hall of Fame leaderboards (seasonal + all-time), hidden medals, seasonal honours.
- **Phase 4**: Community medal wiki integration, medal-of-the-week, special event honours.
---
## 12. Open Design Questions
- [ ] **Bonus cap**: confirm +10% per-effect-category collective cap? Adjust per category?
- [ ] **Tier count**: 5 tiers (Copper→Dragon) or simplify to 4 (drop Dragon)?
- [ ] **World-first honours** (First Light): feasible to award fairly at launch? Use a registration-cohort instead?
- [ ] **Hidden medals**: how many at launch? Risk of players missing them entirely.
- [ ] **Seasonal HOF reset cadence**: monthly? Quarterly?
- [ ] **Bonus stacking math**: confirm multiplicative-diminishing vs. additive-capped.
- [ ] **Counter storage**: dedicated `character_counters` table vs. adding columns — choose before Phase 1.
---
## Related Notes
- [Game Concept Overview](joplin://9cf8a2e701654ffbbd6512cc837c7e2f) — Core loops, cumulative achievements (now medals)
- [Skill & Magic System](joplin://4c295d18c9b04aea947b534834ffaced) — Skills/magic feed medals & honours
- [Mechanics Source Mapping](joplin://87a0f70b45c4453caae0fa2b5b8a96f9) — Torn City source mapping (honours expanded here)
- [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a) — Crit Master medal tracks crits
- [Tech Stack & Architecture](joplin://cecd2ef2690d4d1fba3450342aa63953) — Redis leaderboards, DB schema
- [Lore & World Building](joplin://867bdc9845624908a90928887a71c4c9) — NPCs/districts referenced in honours
- [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b) — Roadmap, phasing

View file

@ -0,0 +1,390 @@
# Skara Brae — Skill & Magic System (MERP/Rolemaster-Inspired)
Source: Joplin note 4c295d18c9b04aea947b534834ffaced, migrated 2026-10-03
> **Goal**: Port the depth of the MERP/Rolemaster skill and magic engine into Skara Brae's existing use-based, BIGINT-stat, idle/MMO framework — *without* abandoning the Torn-style "stats only go up, train by doing" feel.
---
## 1. Design Philosophy — Reconciling Two Worlds
| Concern | RoleMaster/MERP | Skara Brae Existing | Resolution |
|---|---|---|---|
| **How skills grow** | Development Points spent per level (point-buy) | Use-based XP per skill (like RuneScape/Idle Fantasy) | **Hybrid**: practice-ranks by use **+** development-ranks by spend. See §3. |
| **Skill depth** | ~60 skills in 18+ categories, stat-linked, diminishing returns | Flat list of ~25 skills, each on its own XP bar | Adopt RM **categories**, **rank-bonus formula**, **stat integration**, **maneuver difficulties**. |
| **Magic** | Spell *lists* (open/closed/base), realm-based, learned in order, power-point cost | 4 BT1 schools + 3 realms mentioned but undefined | Full **spell-list system** (§5): curated lists per realm, ordered progression, PP cost, bolt/ball/utility classification. |
| **Resolution** | d100 open-ended + skill bonus vs. maneuver difficulty | d100 open-ended for combat only | Generalize d100 open-ended **maneuver roll** to *all* skills (§4). |
| **Stats** | 10 stats | 6 BIGINT stats (Str/Agi/Con/Int/Wis/Cha) | Map each skill to 1–3 of our 6 stats (§2.2). |
**Key principle**: Use-based training is the *primary* advancement loop (consistent with Torn + Idle Fantasy + the idle/offline features). Development Points are a *secondary* layer that lets players cross-train skills they don't actively grind — exactly Rolemaster's flexibility, but earned through play rather than per-level allocation alone.
---
## 2. The Skill Catalogue
### 2.1 Skill Categories
All skills are organized into Rolemaster-style **categories**. A character's **profession (class)** grants a **profession modifier** per category — a discount on Development Point cost and/or a small bonus to the skill bonus. This is the Rolemaster "class feel" mechanism.
| # | Category | Example Skills | Primary Use |
|---|---|---|---|
| 1 | **Armor** | Light Armor, Medium Armor, Heavy Armor, Shield | Mitigation, agility penalties |
| 2 | **Weapon — Melee** | 1H Edged, 1H Concussion, 2-Handed, Polearms, Unarmed, Martial Arts | Attack rolls, OB |
| 3 | **Weapon — Ranged** | Bow, Crossbow, Thrown, Sling | Ranged attack rolls |
| 4 | **Athletic / Brawn** | Climbing, Swimming, Gymnastics (dodge), Lifting | Movement, escape, evasion |
| 5 | **Awareness / Search** | Perception, Alertness, Tracking, Trap Sense, Ambush Awareness | Detection, scouting |
| 6 | **Body Development** | Constitution (HP pool growth), Stamina | Survivability |
| 7 | **Combat Maneuvers** | Mounted Combat, Adrenal Defense, Multiple Parry, Feint | Advanced combat options |
| 8 | **Craft / Trade** | Blacksmithing, Alchemy, Enchanting, Tailoring, Jewelcrafting, Fletching, Cooking | Crafting professions |
| 9 | **Gathering** | Mining, Herbalism, Woodcutting, Fishing, Skinning | Material acquisition |
| 10 | **Directed Spells** | Runes, Staves & Wands, Scrolls | Using magic items |
| 11 | **Influence** | Leadership, Persuasion, Intimidation, Disguise | Social, guild, trade |
| 12 | **Lore** | General Lore, Magical Lore, Religious Lore, Skara Brae Lore | Quests, puzzles, dungeon riddles |
| 13 | **Magic Lore** | Runereading, Spell Mastery, Mana Weaving | Spellcasting support |
| 14 | **Mental** *(Mentalism)* | Telepathy, Mental Defense, Mind Control, Enhancement | Mentalism spell channeling |
| 15 | **Outdoor / Environment** | Foraging, Survival, Weather Reading, Navigation | Wilderness, Wilds, offshore |
| 16 | **Self Control** | Meditation (mana regen), Frenzy (berserk), Willpower (RR bonus) | Buffs, recovery |
| 17 | **Special Attacks** | Backstab, Ambush, Poisons, Stunning Blows | Rogue/Monk techniques |
| 18 | **Spells** *(per realm)* | Essence Lists, Channeling Lists, Mentalism Lists | Spellcasting — see §5 |
| 19 | **Subterfuge / Stealth** | Lockpicking, Pickpocketing, Sneaking, Hiding, Trap Setting | Thievery, adventures |
| 20 | **Technical / Trade** | Bartering, Appraisal, Engineering (siege/traps) | Economy, guild siege |
| 21 | **Urban** | Streetwise, Gambling, Carousing, Black Market (fencing) | Inn, Lower City, Harbor |
> Mappers to existing design: categories 8 & 9 = the 5 gathering + 7 crafting professions already defined. Category 19 = the Thievery tree. Category 21 = social/inn activities. Category 18 = the magic system in §5.
### 2.2 Stat Linkage
Each skill rolls **1–3 relevant stats**. Stat bonus is derived from the BIGINT stat via a **logarithmic bonus function** (so billions-scale stats still produce a bounded, meaningful bonus):
```
stat_bonus(value) = floor( 10 * log2( value / 10 ) ) // bounded, grows slowly
// Example: 10 → 0, 20 → +10, 80 → +30, 10K → +100, 1B → ~+200
```
(Exact curve TBD in tuning — the point is **slow, diminishing** growth so that a character with 1B Intelligence isn't auto-winning every lore check, but is meaningfully better than one with 10K.)
| Sample skills | Linked Stats |
|---|---|
| 1H Edged | Str, Agi |
| Bow | Agi |
| Stealth / Sneaking | Agi |
| Lockpicking | Agi, Int |
| Blacksmithing | Str, Int |
| Alchemy | Int, Wis |
| Persuasion | Cha |
| Tracking | Wis, Int |
| Meditation | Wis, Con |
| Unarmed / Martial Arts | Str, Con, Agi |
| Runereading | Int |
---
## 3. Skill Ranks — Practice + Development (Hybrid)
### 3.1 Two Tracks, One Bonus
A skill's effectiveness is driven by its **total ranks**, which come from two sources:
1. **Practice Ranks** — earned automatically by using the skill (use-based XP → rank thresholds). *This is the core loop.* Each skill has its own XP bar. Offline apprentice workers grant practice XP at 50% (existing design).
2. **Development Ranks** — purchased with **Development Points (DP)**. Lets a player boost a skill they aren't actively grinding, or push past a practice plateau.
```
total_ranks(skill) = practice_ranks + development_ranks
skill_bonus(skill) = rank_bonus(total_ranks)
+ Σ stat_bonus(linked_stats)
+ profession_bonus(class, category)
+ equipment_bonus
+ situational_modifiers
```
### 3.2 Rank Bonus — Diminishing Returns (Rolemaster Formula, Adapted)
| Rank Band | Bonus per Rank | Cumulative at Band End |
|---|---|---|
| Ranks 1–10 | +5 each | +50 |
| Ranks 11–20 | +3 each | +80 |
| Ranks 21–30 | +2 each | +100 |
| Ranks 31–50 | +1 each | +120 |
| Ranks 51+ | +0.5 each (rounded) | slow creep |
This mirrors Rolemaster's "first rank is worth a lot, then diminishing." It keeps use-based grinding rewarding early and makes Development Points meaningful for pushing high-end skills. **Caps** per skill can be set per tuning (e.g., max 50 ranks for non-combat, higher for weapons/spells).
### 3.3 Development Points
- **DP per character level** = `5 + stat_bonus(Intelligence)` (Intelligence = learning aptitude). Patrons may get +2.
- **DP cost to buy a rank** depends on the skill's category and the character's profession:
| Profession Modifier | DP per Rank | Meaning |
|---|---|---|
| Favored | 1 | Class's core competencies |
| Normal | 2 | Secondary skills |
| Unfavored | 4 | Outside the class's wheelhouse |
| Restricted | 8 (or disallowed) | E.g., heavy spellcasting for a Warrior |
| Class | Favored Categories (examples) | Unfavored |
|---|---|---|
| **Warrior** | Armor, Weapon-Melee, Weapon-Ranged, Body Dev, Combat Maneuvers | Spells, Mental |
| **Rogue** | Subterfuge/Stealth, Special Attacks, Urban, Awareness, Weapon-Melee | Spells (closed), Self Control |
| **Mage** | Spells (Essence), Lore, Magic Lore, Directed Spells, Craft (Enchant/Alchemy) | Armor, Weapon-Melee, Subterfuge |
| **Bard** | Spells (Mentalism), Influence, Lore, Urban, Self Control | Armor (heavy), Body Dev |
| **Cleric** | Spells (Channeling), Influence, Self Control, Lore | Weapon-Ranged, Subterfuge |
| **Ranger** | Weapon-Ranged, Outdoor/Envir, Awareness, Gathering, minor Channeling | Urban, Influence |
| **Paladin** | Armor, Weapon-Melee, Spells (minor Channeling), Self Control, Influence | Subterfuge, Mental |
| **Monk** | Unarmed/Martial Arts, Athletic, Self Control, Body Dev | Armor (heavy), Spells |
### 3.4 Classless Cross-Training
Because any class *can* buy any (non-restricted) skill at higher DP cost, a Warrior *can* learn a basic Fire Bolt — but it costs 8 DP/rank and caps low. This is pure Rolemaster flexibility and rewards hybrid builds, while keeping class identity strong.
---
## 4. Skill Resolution — The Maneuver Roll (Generalized d100)
Every non-trivial skill action resolves with the same engine as combat: an **open-ended d100 maneuver**.
### 4.1 Difficulty Modifiers
| Difficulty | Modifier | Example in Skara Brae |
|---|---|---|
| Routine | +30 | Pick an easy lock (tavern cellar) |
| Easy | +20 | Track a fresh trail in snow |
| Light | +10 | Brew a basic healing potion |
| Medium | 0 | Pickpocket a sober merchant |
| Hard | −10 | Pickpocket a guard; scale a city wall |
| Very Hard | −20 | Defuse a dungeon trap; fence rare goods |
| Extremely Hard | −30 | Pick a vault lock in the Noble Quarter |
| Sheer Folly | −50 | Climb a sheer cliff in a storm |
| Absurd | −70 | Pickpocket Mangar's lieutenant |
### 4.2 Resolution
```
maneuver_total = d100_open_ended() + skill_bonus(skill) + difficulty_modifier
```
Open-ended: 96–100 rolls again and adds; 01–05 rolls again and subtracts (downward open-ended, per Rolemaster).
### 4.3 Result Table
| maneuver_total | Outcome | Effect |
|---|---|---|
| ≥ +80 | **Absolute Success** | Best result + bonus (e.g., +50% yield, bonus loot) |
| +21 to +79 | **Complete Success** | Full intended effect |
| 0 to +20 | **Partial Success** | Effect at reduced value / longer time |
| −20 to −1 | **Failure** | No effect; small chance of minor mishap |
| −80 to −21 | **Absolute Failure** | Failure + complication (broken pick, alarm, wasted materials) |
| ≤ −81 | **Spectacular Failure** | Severe consequence (injury, aggro, lost materials, trap sprung) |
Downward open-ended rolls (01–05) feed the lower bands → the "fumble" tension that makes Rolemaster feel alive.
### 4.4 Why This Matters
- **Adventures** (pickpocketing, burglary, fencing) now use real skill checks with difficulty tiers — replacing a flat success chance.
- **Crafting** quality rolls (Common→Legendary) can be driven off the maneuver table instead of a separate d100.
- **Dungeon puzzles** (lore checks, riddles, lockpicking, trap disarming) become skill encounters.
- **Social** actions (persuade the Beggar King, bluff the City Watch) use Influence skills.
- Consistent with the combat crit table already designed — **one unified resolution engine**.
---
## 5. The Magic System — Spell Lists per Realm
### 5.1 Realms & Primary Stat (Power Points)
| Realm | Casters | Primary Stat (PP) | Flavor |
|---|---|---|---|
| **Essence** | Mages | Intelligence | Raw magical energy woven from the world |
| **Channeling** | Clerics, Paladins (minor) | Wisdom | Power granted by the Old Gods |
| **Mentalism** | Bards | Charisma | Power drawn from mind and will |
**Power Points (PP)** = the spell-casting resource (replaces/generates the `mana` BIGINT pool). PP-per-level scales with the realm stat bonus:
```
max_pp = base_pp(class) + realm_stat_bonus * pp_multiplier(class)
```
PP regenerates over time, boosted by **Meditation** skill (Self Control) and blessings. Spells cost PP to cast; higher-tier spells on a list cost more.
### 5.2 Spell Lists — Open, Closed, Base
A **spell list** is an ordered progression: spell #1 is the weakest, spell #N is the strongest. You must learn a list **in order** — you can't learn spell #10 without #1–#9. This is core Rolemaster.
| List Class | Availability | Example |
|---|---|---|
| **Open** | Available to *all* casters of that realm (favored DP cost) | Essence Hand (utility) for all Essence users |
| **Closed** | Restricted to specific professions of that realm (normal/normal+ cost) | Life Mastery (healing) closed to Clerics |
| **Base** | The profession's signature lists (cheapest, defines the class) | Fire Law as a Mage base list |
You **rank up a spell list** like a skill (practice by casting + DP). Your **list rank** determines the highest spell number you can cast from that list. E.g., Fire Law rank 12 lets you cast Fire Law spells 1–12.
### 5.3 Curated Spell Lists per Realm
*(Target: ~20 lists per realm, ~10–15 spells each. Below is the launch set — expandable.)*
#### Essence (Mages)
| List | Class | Highlights |
|---|---|---|
| **Fire Law** | Base (Mage) | Spark → Fire Bolt → Wall of Fire → Fire Ball → Inferno |
| **Ice Law** | Base (Mage) | Frost → Ice Bolt → Freeze → Blizzard |
| **Light Law** | Base (Mage) | Glow → Light Bolt → Blinding Flash → Sun Bolt |
| **Earth Law** | Closed | Stone Bolt → Entangle → Earthquake |
| **Water Law** | Closed | Water Bolt → Wave → Tidal Surge |
| **Illusions** | Closed | Phantasmal Force → Blur → Invisibility |
| **Living Change** | Closed | Enhance Stat → Shrink → Polymorph |
| **Lofty Bridge** | Closed | Leap → Long Step → Gate → Teleport |
| **Essence Hand** | Open | Light → Unseen Hand → Lock Lore → Dispel |
| **Essence Ways** | Open | Detect Magic → Aura Reading → Sense Essence |
| **Spell Wall** | Open | Minor Shield → Barrier → Wall of Force |
| **Essence Perceptions** | Open | Detect Essence → Analyze Magic |
> **BT1 School Mapping**: The four Bard's Tale schools are *focuses within Essence*:
> - **Magician** (offensive) → Fire/Ice/Light Law base lists
> - **Conjurer** (summoning) → summoning sub-lists + Earth Law
> - **Sorcerer** (debilitating) → Illusions + Living Change
> - **Wizard** (utility) → Lofty Bridge + Essence Hand + Spell Wall
>
> Switching "school" at the Review Board = reprioritizing which base lists you rank. **Master all four = Archmage** (all Essence lists learned).
#### Channeling (Clerics)
| List | Class | Highlights |
|---|---|---|
| **Life Mastery** | Base (Cleric) | Minor Heal → Major Heal → Regeneration → Resurrection |
| **Repulse / Undead Mastery** | Base (Cleric) | Turn Undead → Hold Undead → Control Undead |
| **Protections** | Base (Cleric) | Sanctuary → Holy Shield → Consecration |
| **Detections** | Closed | Detect Evil → Detect Undead → Detect Trap |
| **Creations** | Closed | Create Light → Create Food → Create Water |
| **Weather Ways** | Closed | Calm Weather → Fair Winds → Storm Call |
| **Communal Ways** | Open | Sense Deity → Commune → Divine Guidance |
| **Channeling Perceptions** | Open | Detect Aura → Sense Danger |
#### Mentalism (Bards)
| List | Class | Highlights |
|---|---|---|
| **Mind Mastery** | Base (Bard) | Daze → Confusion → Mental Stun → Dominate |
| **Song / Sound** | Base (Bard) | Valor (atk buff) → Hope (morale) → Fear (debuff) → Charm → Lullaby (sleep). *Long-duration bard songs.* |
| **Self Healing** | Closed | Mend → Recover → Revitalize |
| **Mind's Door** | Closed | Telepathy → Mind Speech → Mind Store |
| **Body Control** | Closed | Adrenal Speed → Adrenal Strength → Prowess |
| **Mental Illusions** | Closed | Mirage → Phantasm → Mirage Illusion |
| **Mind's Eye** | Open | Sense Thoughts → Detect Motive |
| **Mental Defenses** | Open | Mind Barrier → Mental Shield → Iron Will |
### 5.4 Spell Classification (Combat Integration)
| Type | Resolution | Notes |
|---|---|---|
| **Bolt** (directed) | Attack roll = d100 open-ended + Directed Spells skill vs. target's defense (like a missile) | Fire Bolt, Ice Bolt. Can trigger crit tables (elemental crit). |
| **Ball / Area** (non-directed) | Target makes **Resistance Roll**: d100 + Will bonus + level vs. spell level | Fire Ball, Blizzard. Failed RR = full effect; partial = reduced. |
| **Defensive / Utility** | Auto-cast (costs PP); resisted only where noted | Shields, teleports, detections, healing. |
This slots directly into the existing **Resistance Roll** design (d100 + Will vs. spell difficulty) and the **d100 open-ended crit tables**. Elemental crit tables (burn, frost, shock) extend the slash/crush/puncture/unarmed tables already defined.
### 5.5 Spell Acquisition — The Review Board
Per existing design, the **Adventurers' Guild (Review Board)** is where you learn magic:
- Increase a spell-list rank by paying gold + meeting the level/practice prerequisite.
- Casters must visit to gain access to new spell numbers on a list.
- **Magical exam** (lore check) for spellcasters (existing design) — now a real *Magical Lore* maneuver.
- Mages switch Essence-school focus here (reprioritize base lists).
- **Archmage**: a Mage who has maxed all four BT1 schools' base lists → cosmetic title + achievement + small global casting bonus.
### 5.6 Spell Scrolls & Items
- **Scrolls** (Directed Spells → Scrolls skill): one-use spell from any list; lets non-casters cast minor spells (Torn-like consumable). Found in dungeons, crafted by Enchanting.
- **Staves & Wands** (Directed Spells → Staves & Wands): rechargeable PP-cost items casting a fixed spell. Crafted/bound via Enchanting.
- **Runes** (Magic Lore → Runereading): permanent magical inscriptions on gear; activated by Runereading skill.
---
## 6. Integration With Existing Systems
| Existing System | Change / Enhancement |
|---|---|
| **Combat (crit tables)** | Elemental crit tables added (burn, frost, shock). Bolts roll like missiles; balls use RR. Maneuver roll unified with combat. |
| **BIGINT stats** | `stat_bonus()` log function feeds skills. Stats keep growing to billions; bonuses grow slowly (bounded). |
| **Adventures** | Success now computed via maneuver roll + skill bonus + difficulty tier. Time-of-day & skill synergies become modifiers. |
| **Crafting (5 gather + 7 craft)** | These are skills in categories 8 & 9. Quality roll driven by maneuver table; crafting crits = upward open-ended success. |
| **Thievery** | Lives in Subterfuge/Stealth category (Lockpicking, Pickpocketing, Sneaking, Hiding). Adventures use these directly. |
| **Education courses** | Completing a course grants **DP** (development points) — a second DP source beyond leveling. Makes education feel impactful. |
| **Blessings** | Could grant temporary +skill bonus or +DP regen instead of flat multipliers. |
| **Workers (apprentice)** | Apprentice grants *practice XP* to a chosen skill at 50% — unchanged, now feeds practice ranks. |
| **Database** | New tables needed: `skill_categories`, `character_skill_ranks` (split practice/dev), `spell_lists`, `character_spell_list_ranks`, `spell_definitions`. See §7. |
---
## 7. Database Additions (Draft)
```sql
-- Skill ranks (practice + development split)
CREATE TABLE character_skills (
character_id UUID NOT NULL REFERENCES characters(id),
skill_name VARCHAR(48) NOT NULL,
category VARCHAR(32) NOT NULL,
practice_ranks INT NOT NULL DEFAULT 0,
development_ranks INT NOT NULL DEFAULT 0,
experience BIGINT NOT NULL DEFAULT 0, -- feeds practice_ranks
PRIMARY KEY (character_id, skill_name)
);
-- Development point pool per character
ALTER TABLE characters ADD COLUMN unspent_dp INT NOT NULL DEFAULT 0;
-- Spell lists
CREATE TABLE spell_lists (
id VARCHAR(64) PRIMARY KEY, -- e.g. 'fire_law'
realm VARCHAR(16) NOT NULL, -- essence | channeling | mentalism
list_class VARCHAR(16) NOT NULL, -- open | closed | base
name VARCHAR(64) NOT NULL,
description TEXT
);
-- Spell definitions (ordered within a list)
CREATE TABLE spells (
id VARCHAR(64) PRIMARY KEY, -- e.g. 'fire_law_3'
list_id VARCHAR(64) NOT NULL REFERENCES spell_lists(id),
spell_number INT NOT NULL, -- position in list (1..N)
name VARCHAR(64) NOT NULL,
spell_type VARCHAR(16) NOT NULL, -- bolt | ball | defensive | utility
pp_cost INT NOT NULL,
effect_json JSONB NOT NULL, -- damage, duration, modifiers
description TEXT,
UNIQUE (list_id, spell_number)
);
-- Character spell-list ranks
CREATE TABLE character_spell_lists (
character_id UUID NOT NULL REFERENCES characters(id),
list_id VARCHAR(64) NOT NULL REFERENCES spell_lists(id),
rank INT NOT NULL DEFAULT 0, -- highest spell_number accessible
experience BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (character_id, list_id)
);
```
---
## 8. Open Design Questions
- [ ] **Stat bonus curve**: exact `stat_bonus()` function shape — log2 base? Per-stat caps?
- [ ] **Rank caps**: hard cap per skill (50? 100?) or soft cap via DP scarcity?
- [ ] **PP vs. existing `mana` BIGINT column**: unify into PP, or keep mana as the raw pool and PP as derived? Recommend: rename `mana`→PP conceptually, derive max from formula.
- [ ] **Elemental crit tables**: how many (burn/frost/shock/sonic/poison)? Where stored (`skara-brae-common/crit-tables/`)?
- [ ] **Scroll/wand crafting**: which Enchanting recipes produce scrolls? List-restricted or universal?
- [ ] **DP from education**: how many DP per completed course? Balance against per-level DP.
- [ ] **Multi-realm casters**: should any class get a *second* realm at reduced effectiveness (e.g., Ranger = Essence + Channeling minor)? Rolemaster has semi/hybrid casters.
- [ ] **Archmage bonus**: cosmetic only, or small global casting bonus?
---
## Related Notes
- [Game Concept Overview](joplin://9cf8a2e701654ffbbd6512cc837c7e2f) — Skills, classes, stats, spell schools, education
- [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a) — d100 open-ended crit tables (this system generalizes them)
- [Mechanics Source Mapping](joplin://87a0f70b45c4453caae0fa2b5b8a96f9) — RoleMaster source mapping (expanded here)
- [Lore & World Building](joplin://867bdc9845624908a90928887a71c4c9) — Adventurers' Guild / Review Board, districts for learning
- [Tech Stack & Architecture](joplin://cecd2ef2690d4d1fba3450342aa63953) — DB schema, crate structure (skills.rs, spell engine)
- [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b) — Roadmap, MVP scope
- [Medals & Honours System](joplin://4877acc671ed4bfcb0d6bf2c5323c94a) — Skill/magic mastery feeds medals

View file

@ -0,0 +1,651 @@
# Skara Brae — Tech Stack & Architecture
Source: Joplin note cecd2ef2690d4d1fba3450342aa63953, migrated 2026-10-03
## Why This Stack in 2026
Torn launched in 2004 as a PHP/HTML text game. It received an engine overhaul in 2014 and a major Crimes 2.0 update in 2023. Modern Torn has real-time features, mobile apps, and a rich API.
For Skara Brae, we build for **2026+ expectations**:
- Instant real-time feedback (WebSocket everywhere)
- Mobile-first (PWA, not just responsive)
- API-first design (community tools from day one)
- Type-safe full stack
- Idle/offline progression (server-side tick engine)
---
## Deployment Topology (self-hosted, no Docker)
> Resolved 2026-08-02. Canonical reference: [Development Environment & Server Topology](joplin://58b6a5c37ba1424684e2e70eb839f1e7).
| Tier | Machine (OS) | Runtime |
|---|---|---|
| **Develop** | workhorse (Ubuntu 26.04, Ryzen 9 5950X 16C/32T, 128 GiB, RTX 5060 Ti) | Kilo + RustRover/WebStorm; local PostgreSQL (native package); `cargo run` + Vite. 32 threads → fast incremental builds. |
| **Test / Stage** | basement server (FreeBSD, LAN-only) | **Jenkins** CI (lint → test → cross-compile Linux x86_64 → transfer binary). A **bhyve Debian VM** mirrors prod: bare systemd units (PG + app binary + Caddy). Also file server + artifact store. |
| **Produce / Git** | Hetzner box (Debian, public) | **Forgejo** (primary git host — public + private repos), bare **systemd** game services (PG + app binary), **Caddy** (TLS). Planned **Codeberg** mirror for redundancy. |
**Flow:** commit on workhorse → push Forgejo (Hetzner, internet SSH) → Jenkins (basement) builds & cross-compiles via webhook → deploys to bhyve Debian staging → on green, SCPs binary to Hetzner prod → `systemctl restart`.
**Redis — deferrable for MVP.** Redis provides caching, leaderboards (sorted sets), and WebSocket pub/sub. At low player counts, the Rust process can hold session/leaderboard data in memory. Add Redis to prod when you need multi-process scaling or persistence across restarts. PostgreSQL handles all persistent data regardless.
**Sizing caveat:** the Hetzner box is "decent, not a powerhouse" and now also runs Forgejo (+ planned Codeberg mirror). A Rust binary + Forgejo is light, but watch combined RAM (Forgejo + Codeberg + PG + app). Set a threshold for upsizing or splitting.
---
## Art Direction (decided 2026-08-02)
**Torn-style graphical browser UI.** The game mechanics are text/numbers; the presentation is a fully graphical web application.
### UI characteristics
- **Location panels**: illustrated backgrounds per district (tavern, market, dungeon entrance, etc.)
- **Item/equipment icons**: sprite-style icons with quality-tier border glow (Common→Legendary)
- **Stat bars & HUD**: graphical HP/energy/PP bars, XP progress bars, skill meters
- **Themed color scheme**: dark fantasy palette, per-district tinting
- **Tab-based navigation**: Torn-style tab bar for core pages (City, Adventures, Combat, Inventory, Guild, etc.)
- **CSS animations**: transitions for page changes, stat updates, combat results
### Rendering approach
- All rendering via **HTML/CSS/SVG within Vue 3 SPA** — no canvas, no WebGL.
- Keeps it lightweight, accessible, and PWA-compatible.
- Vue component library with dark-fantasy theming.
### Art pipeline
- **Location art**: digital illustrations — ~11 district panels + dungeon room tiles
- **Item icons**: sprite sheet or SVG icon set
- **UI chrome**: Vue component library (stat bars, progress rings, modals, tooltips, tab bar)
---
## Multi-Repo Structure
The project is split into three repositories. See [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b) for full rationale.
```
git@hetzner/skara-brae/ # Forgejo on Hetzner (public + private)
├── skara-brae-server/ # Rust backend (opened in RustRover)
├── skara-brae-client/ # Vue 3 frontend (opened in WebStorm)
└── skara-brae-common/ # Shared game data, API contract, constants
```
> Git source of truth: **Forgejo** on the Hetzner box (public-facing). Jenkins on the basement box connects via deploy key + webhook. See [Deployment Topology](#deployment-topology-self-hosted-no-docker).
### Local Checkout Layout (IDE Wiring)
The two consumer repos live in different JetBrains IDEs (RustRover, WebStorm). Keep all three as **siblings under one parent folder** — the parent is a plain folder, **not** a git repo:
```
~/Development/skara-brae/ # workspace root (plain folder, NOT a git repo)
├── skara-brae-server/ # RustRover opens THIS
├── skara-brae-client/ # WebStorm opens THIS
└── skara-brae-common/ # shared — 3rd window, or "Attach" in either IDE
```
> This follows the cross-project workspace convention `~/Development/<project>/`. On workhorse, legacy repos still live in per-IDE default folders (`~/RustroverProjects`, `~/WebstormProjects`, `~/IdeaProjects`); relocate on first touch, or clone into `~/Development/skara-brae/` and symlink the repo back into the IDE folder for discoverability — but always open the **real path** in the IDE so path/file deps resolve. Full convention in [Development Environment & Server Topology § Workspace & Repository Layout](joplin://58b6a5c37ba1424684e2e70eb839f1e7).
- **RustRover (server)** — path dependency in `skara-brae-server/Cargo.toml`:
```toml
sb-common = { path = "../skara-brae-common/rust" }
```
Sibling path deps resolve fine. To edit common from inside RustRover: **Settings → Project Structure → Attach** (or add `../skara-brae-common` as a content root).
- **WebStorm (client)** — local file dependency in `skara-brae-client/package.json`:
```json
"@skara-brae/common": "file:../skara-brae-common/ts"
```
plus a Vite alias (`@common` → that path) so HMR picks up data edits. Attach the module likewise to edit it in-window.
### Shared-Repo Consumption Strategy (Bilingual Package)
`skara-brae-common` is a **bilingual package** whose source of truth is **language-neutral data + schema**, consumed at build time by both projects via codegen (never hand-duplicated types):
```
skara-brae-common/
├── data/ # language-neutral source of truth
│ ├── items/ adventures/ crit-tables/ spells/ recipes/
│ ├── medals/ dungeons/ tower/ expeditions/ (*.json / *.toml)
│ └── schema/ # JSON Schema (entities) + openapi.yaml (API contract)
├── rust/ # thin crate the server depends on
│ ├── Cargo.toml # name = "sb-common"; includes data via include_str! + serde
│ └── src/lib.rs
├── ts/ # thin package the client depends on
│ ├── package.json # name = "@skara-brae/common"; generated types + data re-exports
│ └── src/index.ts
└── codegen/ # data/ + schema → rust/ and ts/ bindings
```
**How sharing actually works:**
- **Static game data** (`data/*.json`) is the single source of truth. Both sides consume at build time: Rust via `include_str!` + `serde`; Vue via Vite JSON import.
- **API contract — server is authoritative.** Expose OpenAPI via [`utoipa`](https://docs.rs/utoipa); generate the client's TS types with `openapi-typescript` (or `orval`).
- **Entity types** — define once as JSON Schema in `data/schema/`, generate both Rust structs (`typify` / `schemars`) and TS interfaces (`json-schema-to-typescript`) from `codegen/`.
**Two clarifications:**
1. Do **not** confuse `skara-brae-common` (cross-language, this third repo) with the `sb-shared` crate in the server workspace below — `sb-shared` is a **server-internal** Rust crate (types/errors/constants) and stays inside `skara-brae-server/crates/`.
2. **Alternative for self-contained CI**: add `skara-brae-common` as a **git submodule** inside both repos. Start with sibling + path; switch to submodules only if contributors/CI demand it.
### Cross-language dependency path workaround
Cargo workspaces **cannot** resolve dependency paths that point above the workspace root. When `sb-common` is declared in `[workspace.dependencies]` with `path = "../skara-brae-common/rust"`, Cargo resolves the path relative to the **consuming crate** (e.g., `crates/sb-api/`), not the workspace root — producing the error `failed to read .../skara-brae-server/skara-brae-common/rust/Cargo.toml`.
**Current workaround (local solo dev):** use an **absolute path** in each crate's `[dependencies]`:
```toml
# In crates/sb-api/Cargo.toml and crates/sb-core/Cargo.toml:
[dependencies]
sb-common = { path = "/home/jan/Development/skara-brae/skara-brae-common/rust" }
```
Do **not** declare `sb-common` in `[workspace.dependencies]` — only in each consuming crate.
**For CI / contributors:** switch to **git submodules** (`server/common/`, `client/common/`) so each repo is self-contained. This is the planned long-term solution. For local solo work, the absolute path is functional.
---
## Server Project Structure
```
skara-brae-server/
├── Cargo.toml # Workspace root (DO NOT put sb-common in [workspace.dependencies])
├── crates/
│ ├── sb-api/ # Axum HTTP API server
│ │ ├── src/
│ │ │ ├── main.rs
│ │ │ ├── config.rs
│ │ │ ├── routes/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── auth.rs
│ │ │ │ ├── character.rs
│ │ │ │ ├── adventure.rs
│ │ │ │ ├── combat.rs
│ │ │ │ ├── market.rs
│ │ │ │ ├── guild.rs
│ │ │ │ ├── property.rs
│ │ │ │ ├── education.rs
│ │ │ │ ├── crafting.rs
│ │ │ │ ├── pets.rs
│ │ │ │ ├── blessings.rs
│ │ │ │ ├── inn.rs
│ │ │ │ └── slayer.rs
│ │ │ ├── middleware/
│ │ │ │ ├── auth.rs
│ │ │ │ └── rate_limit.rs
│ │ │ └── ws/
│ │ │ ├── handler.rs
│ │ │ └── channels.rs
│ │ └── Cargo.toml # sb-common via absolute path
│ │
│ ├── sb-core/ # Game engine core
│ │ ├── src/
│ │ │ ├── lib.rs
│ │ │ ├── items.rs
│ │ │ ├── character/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── stats.rs # BIGINT stat system, tiered display
│ │ │ │ ├── skills.rs
│ │ │ │ └── races.rs
│ │ │ ├── combat/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── engine.rs
│ │ │ │ ├── actions.rs
│ │ │ │ ├── formulas.rs
│ │ │ │ └── crit_tables.rs # RoleMaster-inspired open-ended d100
│ │ │ ├── adventure/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── templates.rs
│ │ │ │ ├── rewards.rs
│ │ │ │ └── offline.rs # Offline session reward calculation
│ │ │ ├── economy/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── market.rs
│ │ │ │ └── bank.rs
│ │ │ ├── guild/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── wars.rs
│ │ │ │ └── ranks.rs # 10-rank progression system
│ │ │ ├── crafting/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── professions.rs # 12 professions (5 gathering + 7 crafting)
│ │ │ │ ├── recipes.rs
│ │ │ │ └── quality.rs # Quality roll system (Common→Legendary)
│ │ │ ├── pets/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── breeding.rs
│ │ │ │ └── bonuses.rs
│ │ │ ├── blessings/
│ │ │ │ ├── mod.rs
│ │ │ │ └── effects.rs
│ │ │ ├── workers/
│ │ │ │ ├── mod.rs # Inn workers (NPC automation)
│ │ │ │ └── tasks.rs
│ │ │ ├── slayer/
│ │ │ │ ├── mod.rs
│ │ │ │ └── tasks.rs
│ │ │ ├── world/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── time.rs # Day/night cycle
│ │ │ │ ├── weather.rs
│ │ │ │ └── events.rs # Dynamic world events
│ │ │ └── rules/
│ │ │ ├── mod.rs
│ │ │ └── formulas.rs # All game formulas in one place
│ │ └── Cargo.toml # sb-common via absolute path
│ │
│ ├── sb-db/ # Database layer
│ │ ├── src/
│ │ │ ├── lib.rs
│ │ │ ├── models/
│ │ │ │ ├── user.rs
│ │ │ │ ├── character.rs
│ │ │ │ ├── item.rs
│ │ │ │ ├── guild.rs
│ │ │ │ ├── property.rs
│ │ │ │ ├── pet.rs
│ │ │ │ ├── crafting.rs
│ │ │ │ └── blessing.rs
│ │ │ ├── queries/
│ │ │ └── migrations/
│ │ └── Cargo.toml
│ │
│ ├── sb-auth/ # Authentication & authorization
│ │ ├── src/
│ │ │ ├── lib.rs
│ │ │ ├── jwt.rs
│ │ │ ├── hash.rs # argon2 password hashing
│ │ │ └── session.rs
│ │ └── Cargo.toml
│ │
│ └── sb-shared/ # Server-internal shared types, errors, constants
│ ├── src/
│ │ ├── lib.rs
│ │ ├── types.rs
│ │ ├── errors.rs
│ │ └── constants.rs
│ └── Cargo.toml
│
├── migrations/ # SQL migrations
│ ├── 001_initial.sql
│ ├── 002_character.sql
│ ├── 003_guilds.sql
│ ├── 004_pets.sql
│ ├── 005_crafting.sql
│ └── 006_blessings.sql
│
├── systemd/ # systemd .service unit files for deployment
│ ├── skara-brae.service
│ ├── skara-brae.env # environment variables (DB URL, Redis URL, etc.)
│ └── install.sh # install script: copy binary + unit → /etc/systemd/system/
│
└── README.md
```
> Note: `sb-shared` above is the **server-internal** Rust crate. The **cross-language** shared repo is `skara-brae-common` (consumed via `sb-common` with an absolute path). See [Cross-language dependency path workaround](#cross-language-dependency-path-workaround) above.
---
## systemd Deployment (prod & staging)
### skara-brae.service
```ini
[Unit]
Description=Skara Brae Game Server
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=skara-brae
Group=skara-brae
ExecStart=/opt/skara-brae/bin/skara-brae-server
EnvironmentFile=/opt/skara-brae/skara-brae.env
Restart=always
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
```
### skara-brae.env
```env
DATABASE_URL=postgres://skara-brae:password@127.0.0.1:5432/skara_brae
REDIS_URL=redis://127.0.0.1:6379 # only when Redis is deployed
LISTEN_ADDR=127.0.0.1:8080
JWT_SECRET=changeme
RUST_LOG=info
```
### Caddy (reverse proxy + TLS)
```
git.yourdomain.tld {
reverse_proxy 127.0.0.1:3000
}
api.skara-brae.tld {
reverse_proxy 127.0.0.1:8080
}
play.skara-brae.tld {
root * /srv/skara-brae-web
file_server
try_files {path} /index.html
}
```
### Jenkins deploy step (SSH to Hetzner)
```bash
scp target/release/skara-brae-server hetzner:/opt/skara-brae/bin/
ssh hetzner "systemctl restart skara-brae"
```
### Install script (first-time setup)
```bash
#!/bin/bash
set -euo pipefail
sudo useradd -r -s /bin/false skara-brae
sudo mkdir -p /opt/skara-brae/{bin,config}
sudo cp skara-brae-server /opt/skara-brae/bin/
sudo cp systemd/skara-brae.service /etc/systemd/system/
sudo cp systemd/skara-brae.env /opt/skara-brae/
sudo systemctl daemon-reload
sudo systemctl enable --now skara-brae
```
---
## Key Crate Dependencies
### sb-api (Axum server)
```toml
[dependencies]
axum = { version = "0.8", features = ["ws", "macros"] }
tokio = { version = "1", features = ["full"] }
tower = "0.5"
tower-http = { version = "0.6", features = ["cors", "trace", "compression-gzip"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
sb-core = { path = "../sb-core" }
sb-db = { path = "../sb-db" }
sb-auth = { path = "../sb-auth" }
sb-shared = { path = "../sb-shared" }
sb-common = { path = "/home/jan/Development/skara-brae/skara-brae-common/rust" }
utoipa = { version = "5", features = ["axum_extras"] }
tracing = "0.1"
tracing-subscriber = "0.3"
```
### sb-core (Game engine)
```toml
[dependencies]
serde = { version = "1", features = ["derive"] }
rand = "0.9"
chrono = { version = "0.4", features = ["serde"] }
thiserror = "2"
sb-shared = { path = "../sb-shared" }
sb-common = { path = "/home/jan/Development/skara-brae/skara-brae-common/rust" }
```
### sb-db (Database)
```toml
[dependencies]
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "chrono", "uuid", "migrate"] }
sb-shared = { path = "../sb-shared" }
serde = { version = "1", features = ["derive"] }
```
### sb-auth (Auth)
```toml
[dependencies]
jsonwebtoken = "9"
argon2 = "0.5"
serde = { version = "1", features = ["derive"] }
chrono = { version = "0.4", features = ["serde"] }
sb-shared = { path = "../sb-shared" }
```
---
## Database Schema (Core Tables)
```sql
-- Users
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username VARCHAR(32) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL, -- argon2 hash
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_login TIMESTAMPTZ,
is_banned BOOLEAN NOT NULL DEFAULT FALSE,
is_patron BOOLEAN NOT NULL DEFAULT FALSE
);
-- Characters (one per user, or multiple for patrons)
CREATE TABLE characters (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
name VARCHAR(32) UNIQUE NOT NULL,
race VARCHAR(16) NOT NULL,
class VARCHAR(16) NOT NULL,
level INT NOT NULL DEFAULT 1,
experience BIGINT NOT NULL DEFAULT 0,
gold BIGINT NOT NULL DEFAULT 100,
energy INT NOT NULL DEFAULT 100,
max_energy INT NOT NULL DEFAULT 100,
hp BIGINT NOT NULL DEFAULT 100,
max_hp BIGINT NOT NULL DEFAULT 100,
pp BIGINT NOT NULL DEFAULT 50,
max_pp BIGINT NOT NULL DEFAULT 50,
strength BIGINT NOT NULL DEFAULT 10,
agility BIGINT NOT NULL DEFAULT 10,
constitution BIGINT NOT NULL DEFAULT 10,
intelligence BIGINT NOT NULL DEFAULT 10,
wisdom BIGINT NOT NULL DEFAULT 10,
charisma BIGINT NOT NULL DEFAULT 10,
location VARCHAR(32) NOT NULL DEFAULT 'tavern',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Skills
CREATE TABLE character_skills (
character_id UUID NOT NULL REFERENCES characters(id),
skill_name VARCHAR(32) NOT NULL,
level INT NOT NULL DEFAULT 0,
experience BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (character_id, skill_name)
);
-- Inventory
CREATE TABLE inventory (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
character_id UUID NOT NULL REFERENCES characters(id),
item_id UUID NOT NULL,
quantity INT NOT NULL DEFAULT 1,
equipped_slot VARCHAR(16),
quality VARCHAR(16) NOT NULL DEFAULT 'common',
acquired_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Guilds
CREATE TABLE guilds (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(64) UNIQUE NOT NULL,
description TEXT,
leader_id UUID NOT NULL REFERENCES characters(id),
treasury BIGINT NOT NULL DEFAULT 0,
tax_rate SMALLINT NOT NULL DEFAULT 10 CHECK (tax_rate BETWEEN 0 AND 25),
level INT NOT NULL DEFAULT 1,
reputation BIGINT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE guild_members (
guild_id UUID NOT NULL REFERENCES guilds(id),
character_id UUID NOT NULL REFERENCES characters(id),
rank VARCHAR(16) NOT NULL DEFAULT 'initiate',
reputation BIGINT NOT NULL DEFAULT 0,
joined_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (guild_id, character_id)
);
-- Properties
CREATE TABLE properties (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
property_type VARCHAR(32) NOT NULL,
owner_id UUID REFERENCES characters(id),
guild_id UUID REFERENCES guilds(id),
level INT NOT NULL DEFAULT 1,
rent_price BIGINT,
sale_price BIGINT,
is_listed BOOLEAN NOT NULL DEFAULT FALSE
);
-- Market listings
CREATE TABLE market_listings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
seller_id UUID NOT NULL REFERENCES characters(id),
item_id UUID NOT NULL,
quantity INT NOT NULL DEFAULT 1,
price BIGINT NOT NULL,
listed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL
);
-- Adventures log
CREATE TABLE adventure_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
character_id UUID NOT NULL REFERENCES characters(id),
adventure_id VARCHAR(64) NOT NULL,
result VARCHAR(16) NOT NULL,
rewards_gold BIGINT NOT NULL DEFAULT 0,
rewards_xp BIGINT NOT NULL DEFAULT 0,
started_at TIMESTAMPTZ NOT NULL,
completed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Education enrollment
CREATE TABLE education_enrollments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
character_id UUID NOT NULL REFERENCES characters(id),
course_id VARCHAR(64) NOT NULL,
enrolled_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
completes_at TIMESTAMPTZ NOT NULL,
completed BOOLEAN NOT NULL DEFAULT FALSE
);
-- Pets
CREATE TABLE pets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
character_id UUID NOT NULL REFERENCES characters(id),
pet_type VARCHAR(32) NOT NULL,
name VARCHAR(32),
rarity VARCHAR(16) NOT NULL DEFAULT 'common',
level INT NOT NULL DEFAULT 1,
experience BIGINT NOT NULL DEFAULT 0,
bonus_type VARCHAR(32) NOT NULL,
bonus_value DECIMAL(5,2) NOT NULL DEFAULT 1.00,
is_active BOOLEAN NOT NULL DEFAULT FALSE,
age_days INT NOT NULL DEFAULT 0,
is_dead BOOLEAN NOT NULL DEFAULT FALSE,
acquired_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE pet_equipment (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
pet_id UUID NOT NULL REFERENCES pets(id) ON DELETE CASCADE,
item_id UUID NOT NULL,
slot VARCHAR(16) NOT NULL
);
-- Crafting professions
CREATE TABLE character_professions (
character_id UUID NOT NULL REFERENCES characters(id),
profession VARCHAR(32) NOT NULL,
mastery_level VARCHAR(16) NOT NULL DEFAULT 'novice',
experience BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (character_id, profession)
);
-- Crafting recipes (discovered)
CREATE TABLE character_recipes (
character_id UUID NOT NULL REFERENCES characters(id),
recipe_id VARCHAR(64) NOT NULL,
discovered_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (character_id, recipe_id)
);
-- Blessings (active)
CREATE TABLE active_blessings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
character_id UUID NOT NULL REFERENCES characters(id),
blessing_type VARCHAR(32) NOT NULL,
effect_value DECIMAL(5,2) NOT NULL,
activated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL
);
-- Inn workers (hired NPCs)
CREATE TABLE hired_workers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
character_id UUID NOT NULL REFERENCES characters(id),
worker_type VARCHAR(32) NOT NULL,
quality VARCHAR(16) NOT NULL DEFAULT 'novice',
task VARCHAR(64),
hired_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL,
cost_per_hour BIGINT NOT NULL
);
-- Slayer tasks
CREATE TABLE slayer_tasks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
character_id UUID NOT NULL REFERENCES characters(id),
enemy_type VARCHAR(64) NOT NULL,
target_count INT NOT NULL,
current_count INT NOT NULL DEFAULT 0,
assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
completed BOOLEAN NOT NULL DEFAULT FALSE
);
-- Offline session state
CREATE TABLE offline_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
character_id UUID NOT NULL REFERENCES characters(id),
session_type VARCHAR(32) NOT NULL,
started_at TIMESTAMPTZ NOT NULL,
max_duration INTERVAL NOT NULL DEFAULT INTERVAL '4 hours',
claimed BOOLEAN NOT NULL DEFAULT FALSE
);
```
---
## Why Rust for a Game Like This
1. **Performance**: Torn serves millions of requests. Rust handles this with minimal resources.
2. **Type safety**: Complex game rules caught at compile time. `sb-core` becomes a verified game engine.
3. **Fearless concurrency**: Tokio + ownership model makes the tick engine correct by construction.
4. **No GC pauses**: Deterministic performance for real-time combat.
5. **Workspace architecture**: Clean crate separation — fast independent compilation.
6. **Ecosystem**: Axum, SQLx, Tokio, Serde — mature, production-grade in 2026.
7. **Single static binary**: Cross-compile, deploy, run. No Docker, no runtime deps.
---
## Why Vue.js (Not React/Svelte)
- **Composition API** maps to game UI patterns (reactive stat bars, inventory grids, combat logs)
- **Pinia** stores model game state naturally
- **Single-file components** co-locate template + logic + styles
- User preference (stated)
- **PWA support** via Vite plugin
- **SPA only** — no Nuxt/SSR. Game is behind auth; public pages generated separately.
---
## Related Notes
- [Development Environment & Server Topology](joplin://58b6a5c37ba1424684e2e70eb839f1e7) — Canonical dev/test/prod machine roles, toolchain, workspace layout, services glossary
- [Game Concept Overview](joplin://9cf8a2e701654ffbbd6512cc837c7e2f) — Full game design with crafting, pets, inn, guilds
- [Combat System & Stat Scaling Design](joplin://0ef630db4e3e4d6dab18ccaefccaaa5a) — Crit tables, BIGINT stats, combat formula
- [Idle Fantasy Inspirations](joplin://48b3a3c76f734c8dafbbf9e8b3b5f80a) — Offline sessions, workers, pets, blessings
- [Lore & World Building](joplin://867bdc9845624908a90928887a71c4c9) — Districts, NPCs, storyline
- [Project Plan](joplin://d243ae57778343fca997d46b73d0ee3b) — Roadmap, MVP scope, repo structure, decisions log