Files
draugnorak/AGENTS.md
T
2026-02-27 23:52:14 -05:00

11 KiB

Draugnorak Project Guidelines

NVGT Workflow

  • Use the nvgt-engine-dev skill for NVGT API behavior, include/module decisions, and engine-source verification.
  • If API behavior is uncertain, verify against primary sources in nvgt/ (engine source) and docs/nvgt/ before coding.
  • Reuse shared helpers in libstorm-nvgt/ before creating project-local replacements.

libstorm-nvgt Workflow

  • Treat ~/git/libstorm-nvgt as the canonical repository for shared library changes.
  • Do not make canonical library changes directly inside this repo's libstorm-nvgt/ copy first.
  • Hard stop: do not implement shared-library edits in this repo's libstorm-nvgt/ submodule copy. Make the change in ~/git/libstorm-nvgt, commit it there, then update the submodule pointer here.
  • When shared helper behavior must change:
    • Implement and commit the change in ~/git/libstorm-nvgt.
    • Update this repo to the new libstorm-nvgt submodule commit.
    • Verify Draugnorak still compiles with ./nvgt -c draugnorak.nvgt after updating the pointer.

AGENTS.md Maintenance

  • Keep this file aligned with the real repository layout and active workflows.
  • Update AGENTS.md in the same PR/commit when any of the following change:
    • Core directories/modules (for example new systems under src/, scripts/, or docs/).
    • Required build/test/validation commands.
    • Localization workflow expectations.
    • Canonical engine/library source locations or skill usage expectations.
  • If a section is uncertain or outdated, replace it with a short verified statement instead of leaving stale instructions.

Project Structure

Key paths (focused, not exhaustive):

  • draugnorak.nvgt - Main game entry point.
  • src/ - Core gameplay systems.
    • constants.nvgt, player.nvgt, time_system.nvgt - Global state and timing.
    • world_state.nvgt, src/world/ - World object orchestration and world systems.
    • src/enemies/, combat.nvgt, creature_* - Enemy and combat behavior.
    • inventory.nvgt, inventory_items.nvgt, inventory_menus.nvgt, item_registry.nvgt - Inventory/equipment/items.
    • crafting.nvgt, src/crafting/ - Crafting orchestration and recipe categories.
    • quest_system.nvgt, src/quests/, src/bosses/ - Quests, adventures, and boss content.
    • base_system.nvgt, environment.nvgt, weather.nvgt, fishing.nvgt, pet_system.nvgt, fylgja_system.nvgt - Survival systems.
    • i18n.nvgt - Translation loading and lookup wrappers.
    • save_system.nvgt - Save/load behavior.
  • lang/ - Localization catalogs (en.ini, en.template.ini, and per-language files such as es.ini).
  • scripts/ - Build and i18n tooling (generate_i18n_catalog.py, validate_i18n_catalog.py, audit_untranslated_strings.py).
  • docs/ - Implementation references (patterns.md, rune_system.md, localization.md).
  • libstorm-nvgt/ - Shared NVGT helpers reused by this project.
  • sounds/ - Game audio assets.

Game Mechanics

Inventory Limits

  • Personal inventory stacks are capped at 9
  • Skin pouches add +2 stack capacity, backpacks add +9

Map Layout

  • Base area: x 0-4 (wood terrain)
  • Grass area: x 5-19 (grass terrain, contains trees)
  • Gravel area: x 20-34 (gravel terrain, contains stones)

Healing System

  • Base area provides passive healing when player health < max
  • Without herb garden: 1 HP every 2.5 minutes (150000ms)
  • With herb garden: 1 HP every 30 seconds (30000ms)
  • Herb garden can only be built in base area (x <= 4)
  • Only one herb garden allowed per base

Fire System

  • Fires require a firepit to build
  • New fires start with 12 minutes (720000ms) of fuel
  • Warning at 30 seconds remaining
  • Fire goes out when fuel depletes
  • Fire sound plays within 3 tiles distance
  • Jumping over fire prevents damage
  • Feeding fire is done from the Action menu (A)

Snare System

  • Snares become active when player moves away
  • Check every hour for catching/escaping small game
  • Catch chance starts at 5%, increases by 5% per hour (max 75%)
  • Escape chance: 0% for first hour after catch, then increases by 2% per hour (max 95%)
  • Snare sound plays within 2 tiles distance
  • Residents can retrieve game from snares (daytime only, requires meat in storage)

Tree System

  • Trees regenerate fully after ~5 minutes (minute-by-minute refill logic)
  • Tree ambient sound plays within 4 tiles distance
  • Trees only play sound when not chopped
  • Climb down only when in a tree (Down arrow does nothing during jumps or when not in a tree)
  • Trees have height; falling damage is applied when falling from height

Notification System

  • Important events use notify() function (plays sounds/notify.ogg + speaks message)
  • Last 10 notifications stored in history
  • Navigation keys:
    • \ - Repeat most recent notification
    • ] - Next (newer) notification
    • [ (Shift+Comma) - Previous (older) notification
  • Navigating history speaks message without notification sound
  • Speech history (screen_reader_speak wrapper) uses , and . for previous/next message

Search System

  • Hold Shift for 1 second to search
  • Search completes after 1-second delay

Undead System

  • At night, zombies spawn (5 max) and wander outside the base
  • Zombies cannot enter the base while barricade health > 0
  • Zombies attack the barricade for 4-6 damage when they reach it; play sounds/enemies/zombie_hit.ogg
  • Zombies vanish at daybreak
  • Player can hit zombies with spear (1-tile range) or sling (8-tile range)

Barricade System

  • Base starts with 100 barricade health, capped at 500
  • In base, press B to report barricade health
  • Crafting menu includes Barricade category for reinforcement
  • Reinforcement costs and health: 3 sticks (+10), 5 vines (+15), 1 log (+30), 5 stones (+20)
  • Barricade health does not reset during gameplay

Mountains, Rope Climbing, Falling

  • Mountain ranges can appear during area expansion with elevation-based terrain
  • Steep slopes require a rope; the player is prompted to press Up/Down to climb
  • Moving left/right during rope climb cancels and causes a fall
  • Falling damage is applied beyond a safe height (10 feet)

World Expansion & Invasions

  • After day 2, bandit invasions can trigger and expand the map to the east
  • Expansion is either a 30-tile biome strip or a 60-tile mountain range
  • Invasions last 1 hour and spawn bandits in the expanded area during daytime

Weather & Ambience

  • Weather transitions between clear, windy, rainy, stormy with wind/rain/thunder audio
  • Day/night ambience crossfades on hour changes

Inventory + Equipment

  • Item definitions live in src/item_registry.nvgt (personal + storage inventories)
  • Equipment includes spear, axe, sling, bow, clothing, pouches, backpacks
  • Combat logic currently supports spear/axe/sling; bow attacks are not implemented yet
  • Quivers gate arrow capacity (12 arrows per quiver)
  • Quick slots (keys 1-0) bind equipment from the Equipment menu

Buildings

  • Firepit, Fire, Herb Garden, Storage, Pasture, Stable, Altar
  • Storage enables base inventory menus and increases resident recruitment chance

Residents and Base Automation

  • Residents consume meat daily, can repair the barricade, defend with stored weapons, and collect resources
  • Residents use spears or slings (requires stones) for defense
  • Daily weapon breakage occurs based on resident count

Favor, Altars, Incense, Blessings

  • Altar sacrifices (S key, base only) convert items to Favor
  • Burning incense (A key action) grants Favor per hour while active
  • Blessings can trigger (heal, speed boost, barricade repair) and consume Favor

Quests (Mini-Games)

  • Quest menu (Q, base only) appears after altar/favor requirements
  • Max 4 active quests; rewards grant Favor and resources

Adventures & Bosses

  • Adventure menu (Tab) available outside base; limited to once per day
  • Mountain adventure: Unicorn boss; victory grants Favor and unlocks Rune of Swiftness

Runes

  • Rune system in src/runes/ (data + effects)
  • Runes are crafted in Crafting > Runes after unlock (requires knife + clay + favor)
  • Rune of Swiftness grants move speed and gathering bonuses; runed items are tracked separately

Menu Structure

Crafting Menu (C key, base only)

Organized into categories:

  • Weapons: Spear, Sling
  • Tools: Knife, Snare, Stone Axe, Fishing Pole, Rope, Reed Basket, Clay Pot
  • Materials: Butcher Game, Incense
  • Clothing: Skin gear, Moccasins, Pouch, Backpack
  • Buildings: Firepit, Fire, Herb Garden, Storage, Pasture, Stable, Altar
  • Barricade: Reinforcement options
  • Runes: Available after rune unlocks

Equipment Menu (E key)

  • Only shows items player actually has
  • Shows equipped status
  • Says "Nothing to equip" if inventory is empty

Inventory Menu (I key)

  • Base + storage built: root menu for personal vs storage
  • No storage: personal inventory only

Action Menu (A key)

  • Place snares, feed fires, burn incense (context-sensitive)
  • Tab in menu performs “max” action for the selected option

Base Info (B key)

  • Barricade health, residents, storage totals, base buildings

Quest Menu (Q key)

  • Base-only quest selection for mini-games

Adventure Menu (Tab key)

  • Terrain-based adventures outside the base (once per day)

Testing

  • Always run ./nvgt -c draugnorak.nvgt after code changes
  • This compiles without opening the game window and prevents it from taking over the terminal
  • If user-facing text changed, also run:
    • python3 scripts/generate_i18n_catalog.py
    • python3 scripts/validate_i18n_catalog.py
    • python3 scripts/audit_untranslated_strings.py

Localization Workflow

  • Any new or changed user-facing string must be localizable; avoid hardcoded UI/gameplay text in NVGT files.
  • Update the English catalogs in the same change as text changes by running python3 scripts/generate_i18n_catalog.py.
  • Keep lang/en.ini and lang/en.template.ini in sync with code changes.
  • Validate all translation catalogs with python3 scripts/validate_i18n_catalog.py and fix missing keys/placeholders before merging.
  • Run python3 scripts/audit_untranslated_strings.py after text-heavy changes; keep scripts/i18n_audit_allowlist.txt small and commented.
  • Preserve placeholders exactly as written (for example {arg1}, {language}) and keep escapes such as \n and \t intact.
  • For new translations, copy lang/en.template.ini to lang/<code>.ini, then update [meta] (code, name, native_name) to match the file.
  • Translator-facing instructions live in translate.md; developer-level localization details live in docs/localization.md.

Code Standards

  • Use notify() for important game events that should be reviewable
  • Use screen_reader_speak() for immediate feedback that doesn't need to be stored
  • All menus must call menu_background_tick() each loop to keep game state updating
  • Time references: When discussing time (hours, minutes, days), assume game time unless explicitly stated as "real time". Game time runs at 60x speed: 1 real minute = 1 game hour, 24 real minutes = 1 game day.
  • See docs/patterns.md for module and creature patterns
  • See docs/rune_system.md for rune data/effects/save requirements