No description
  • Ruby 79%
  • HTML 19.8%
  • CSS 1%
  • Shell 0.2%
Find a file
2026-07-07 06:27:05 -05:00
.opencode Finish Phase 6g: finalize docs, mark review items complete 2026-07-05 22:11:43 -05:00
app Validate initiative flag against supported mechanic types; show hint in forms 2026-07-05 22:04:48 -05:00
bin
config Phase 6a: Session CRUD, basic session play, bind address config 2026-07-03 21:00:47 -05:00
db Phase 6g: Combat initiative rolling workflow 2026-07-05 18:42:29 -05:00
docs Update docs: README user-facing rewrite, SPEC routes/models/controllers, ARCHITECTURE mechanics/sessions, PHASE6 6a complete 2026-07-04 05:41:44 -05:00
lib Add AGENTS.md, agent memory structure, fix composite JSON parse crash 2026-07-05 21:55:34 -05:00
public/css Fix computed field display and input overflow on character sheets 2026-07-04 08:53:15 -05:00
test Phase 6g: Combat initiative rolling workflow 2026-07-05 18:42:29 -05:00
.gitignore
AGENTS.md Add AGENTS.md, agent memory structure, fix composite JSON parse crash 2026-07-05 21:55:34 -05:00
app.rb Phase 6g: Combat initiative rolling workflow 2026-07-05 18:42:29 -05:00
Gemfile
Gemfile.lock
PHASE1.md
PHASE2.md
PHASE3.md
PHASE4.md Update PHASE4.md and SPECIFICATION.md to reflect Phase 4 implementation 2026-07-03 10:58:04 -05:00
PHASE5.md Note composite mechanic visual editor needed (like template builder) 2026-07-05 18:47:22 -05:00
PHASE6.md Mark 6f items 7-9 as complete (were already implemented) 2026-07-07 06:27:05 -05:00
Rakefile
README.md Implement session-scoped DM mechanic execution (6d) 2026-07-04 09:50:43 -05:00
SPECIFICATION.md Note composite mechanic visual editor needed (like template builder) 2026-07-05 18:47:22 -05:00

Campaigner

A system-agnostic tabletop RPG campaign manager. Character sheets, game mechanics, and stats are not hardcoded — the Dungeon Master defines them dynamically through the web interface. Players join campaigns and create characters from the DM-defined templates.

Built with minimal dependencies: Ruby stdlib (WEBrick, ERB, JSON, YAML) plus Sequel ORM, sqlite3, and bcrypt.


Current Features

Accounts & Authentication

  • User registration — Create a DM or player account
  • Login / Logout — Sign in and out of your account
  • Dashboard — See all your campaigns at a glance

Campaign Management

  • Create and manage campaigns — DMs set up and run campaigns
  • Player invitations — Add or remove players by username
  • Transfer ownership — Hand a campaign off to another DM
  • Import/Export — Back up or share entire campaigns
  • In-game time — Track elapsed time with formatted display
  • Game phases — Define named game states (exploration, combat, rest, etc.) that display with human-readable names

Character Sheet Templates

  • Design your own sheets — DMs create custom templates with a visual tree-based builder (Guide)
  • 12 field types: containers (vertical/horizontal boxes), labels, images, player avatars, DM-only fields, player-editable fields, creation-only fields, computed formulas, inventory lists, checkboxes, and phase-locked fields (Reference)
  • Drag-free reordering — Move fields up/down or reparent between containers
  • Conditional visibility — Show fields only when another field has a specific value (e.g., show spell slots only for wizards)
  • Live preview — See how the sheet will look before players use it

Characters

  • Create from templates — Players pick a template and fill it in; DMs can make NPCs
  • Inline editing — Edit fields right on the sheet view with a Save button (players edit their own fields, DMs also edit DM-designated fields)
  • Creation-only fields — Set once during character creation, locked afterward
  • Smart inputs — Text, numbers, dropdowns, checkboxes, and inventory tables render automatically from the template
  • Import/Export — Share or back up individual characters
  • Delete protection — Only the creator (player or DM) can delete a character

Mechanics & Dice

  • 8 mechanic types: dice rolls, pools, checks (vs DC), formulas, table lookups, composite multi-step actions, phase definitions, and transitions
  • Dice expressions — Roll standard notation (d20, 2d6, d20+5) with advantage/disadvantage
  • Composite actions — Multi-step sequences (attack → damage → apply to HP) with branching, target selection, and choices
  • Apply results — Send roll outcomes directly to character fields (set, add, subtract, or append)
  • Quick roll bar — Ad-hoc dice expression on every campaign page
  • Phase system — Define game states (exploration, combat, rest) with transitions, time costs, and optional roll requirements
  • Share mechanics — Export and import individual mechanics between campaigns

Game Sessions

  • Live play — DMs start a session from the campaign page; only one active session per campaign at a time
  • Session Play screen — Dedicated view showing session status, current phase (human-readable), and in-game time
  • Phase control — Switch phases during play; transitions respect time costs and roll rules
  • Advance time — Move time forward by preset durations (1 round, 1 minute, 1 hour, etc.) or directly to a time of day (dawn, morning, noon, etc.)
  • Session log — Chronological log of everything that happens: session start/end, phase changes, time advancements, and DM-written narrative entries. DM can mark entries as DM-only (hidden from players). Previous session's log shown for continuity.
  • Player view — Players see the active session with phase, time, and log (public entries only)
  • Player actions — Players can roll mechanics from the session view; results go to the DM for confirmation
  • Pending queue — DM reviews pending player rolls and confirms or rejects them; confirmed rolls are logged and effects applied
  • DM quick roll — DMs can roll dice directly within a session, with results logged to the session log
  • Composite execution — Multi-step mechanics run within a session with each step logged
  • Auto-cleanup — Sessions auto-end after 12 hours of inactivity
  • Session history — Browse past sessions with their status and phase

Setup

git clone <repo-url> && cd campaigner
bin/setup

This installs gems, creates the db/ directory, and runs migrations.


Running the Server

bin/server

Starts WEBrick on http://0.0.0.0:8080 (configurable via config/app.ymlport and bind keys).


Usage

Open your browser to http://localhost:8080 and create an account. From there everything is driven through the web interface — register as a DM or player, create or join campaigns, design character templates, manage characters, define mechanics and dice rules, and run live game sessions.


Running Tests

bin/test

Executes all tests (350+) against a temporary test database.


Project Structure

app.rb                  Entry point — router config, WEBrick server
app/
  boot.rb               Loads config, connects DB, requires app files
  controllers/          One file per controller
  models/               Sequel model files with FieldValueModel mixin
  views/                ERB templates organized by controller
    layouts/            Master layout with nav and flash messages
config/                 Database and app configuration
db/migrations/          Sequel migration files
lib/
  router.rb             HTTP request router with named params
  controller.rb         Base controller (session, auth, rendering)
  field_value_store.rb  Dot-path key/value <-> nested hash conversion
  view_helper.rb        ERB helpers and template builder renderers
  dice_roller.rb        Dice notation parser and roller (NdM, pools, checks, tables)
  composite_executor.rb Multi-step composite mechanic execution engine
  session_logger.rb     Session log entry creation (for future Phase 6b+)
  timekeeper.rb         In-game time formatting, duration parsing, time-of-day
public/css/             Stylesheet
test/                   Unit, controller, and integration tests

Architecture

All entity data uses a hybrid model: core columns (id, FKs, timestamps, password_hash) live in fixed database columns. Everything else is stored as rows in a companion {entity}_field_values table using dot-path keys (e.g. stats.strength, equipment.0.name). This allows arbitrary character attributes and game settings without schema migrations.

The FieldValueModel mixin handles bidirectional conversion between flat database rows and nested Ruby hashes.

Template fields form a tree via a self-referential parent_id foreign key on the template_fields table, where each node stores its configuration (type, label, key, etc.) as field value rows.

Mechanics (game rules, dice rolls, phases, transitions) and game sessions use the same EAV pattern — a core table for identity and relationships, and a _field_values companion table for all mutable attributes. This means new mechanic types and session features can be added without schema changes. (Architecture Reference)