Files
draugnorak/docs/rune_system.md

140 lines
4.0 KiB
Markdown

# Rune System
Runes are permanent enchantments that can be engraved onto equipment to grant bonuses. Each piece of equipment can only have one rune.
## How It Works
1. **Unlock**: Defeat a boss to unlock a rune (e.g., unicorn boss unlocks Rune of Swiftness)
2. **Craft**: Go to Crafting > Runes menu (only visible after unlocking at least one rune)
3. **Requirements**: Knife (tool, not consumed), 1 Clay, 1 Favor, must be in base area
4. **Result**: Equipment becomes "Runed {Item} of {Effect}" (e.g., "Runed Skin Pants of Quickness")
## Current Runes
### Rune of Swiftness
- **Unlocked by**: Defeating the unicorn boss
- **Effect name**: "of Quickness"
- **Walk speed bonus**: 20ms per runed item (moccasins give 40ms)
- **Gathering bonus**: 5% faster per runed item (capped at 50% total)
- **Stacking**: All bonuses stack (moccasins + all runed items + speed blessing)
## Files Overview
| File | Purpose |
|------|---------|
| `src/runes/rune_data.nvgt` | Core data structures, constants, unlock tracking, dictionary storage |
| `src/runes/rune_effects.nvgt` | Speed bonus calculations for walking and gathering |
| `src/crafting/craft_runes.nvgt` | Rune engraving crafting menu |
## Adding a New Rune
### Step 1: Add Constants (rune_data.nvgt)
```nvgt
const int RUNE_NEWRUNE = 1; // Next available ID
bool rune_newrune_unlocked = false;
```
### Step 2: Update Helper Functions (rune_data.nvgt)
```nvgt
// In get_rune_name()
if (rune_type == RUNE_NEWRUNE) return "Rune of NewEffect";
// In get_rune_effect_name()
if (rune_type == RUNE_NEWRUNE) return "NewEffect";
// In any_rune_unlocked()
return rune_swiftness_unlocked || rune_newrune_unlocked;
// In is_rune_unlocked()
if (rune_type == RUNE_NEWRUNE) return rune_newrune_unlocked;
// In reset_rune_data()
rune_newrune_unlocked = false;
```
### Step 3: Add Effect Calculations (rune_effects.nvgt)
For a combat rune example:
```nvgt
int get_total_rune_damage_bonus() {
int bonus = 0;
if (equipped_weapon_rune == RUNE_NEWRUNE) bonus += RUNE_NEWRUNE_DAMAGE_BONUS;
return bonus;
}
```
### Step 4: Add Crafting Option (craft_runes.nvgt)
```nvgt
// In run_runes_menu(), add to the menu building:
if (rune_newrune_unlocked) {
rune_options.insert_last("Rune of NewEffect (1 Clay, 1 Favor) [Requires Knife]");
rune_types.insert_last(RUNE_NEWRUNE);
}
```
### Step 5: Add Save/Load (save_system.nvgt)
```nvgt
// In save_game_state():
saveData.set("rune_newrune_unlocked", rune_newrune_unlocked);
// In load_game_state():
rune_newrune_unlocked = get_bool(saveData, "rune_newrune_unlocked", false);
```
### Step 6: Set Unlock Condition
In the boss victory function or quest reward:
```nvgt
rune_newrune_unlocked = true;
```
### Step 7: Update Equipment Menu (if needed)
If the new rune needs special display in equipment_menu.nvgt:
```nvgt
// In the runed items loop, add check for new rune type:
int count = get_runed_item_count(equip_type, RUNE_NEWRUNE);
if (count > 0) {
// Add to menu...
}
```
## Data Storage
### Rune Unlocks
Simple boolean variables per rune type, saved individually.
### Runed Items
Uses a dictionary with key format `"equip_type:rune_type"` and count as value.
- Example: `"5:0"` = Skin Pants (EQUIP_PANTS=5) with Swiftness (RUNE_SWIFTNESS=0)
- Saved as comma-separated `key=count` pairs
### Equipped Runes
Tracked per equipment slot:
- `equipped_head_rune`
- `equipped_torso_rune`
- `equipped_arms_rune`
- `equipped_hands_rune`
- `equipped_legs_rune`
- `equipped_feet_rune`
- `equipped_weapon_rune`
## Equipment Types That Can Be Runed
All current equipment (defined in `get_runeable_equipment_types()`):
- Weapons: Spear, Axe, Sling, Bow
- Clothing: Skin Hat, Skin Gloves, Skin Pants, Skin Tunic, Moccasins, Skin Pouch, Backpack
## Constants Reference
| Constant | Value | Description |
|----------|-------|-------------|
| `RUNE_NONE` | -1 | No rune applied |
| `RUNE_SWIFTNESS` | 0 | Swiftness rune type |
| `RUNE_SWIFTNESS_SPEED_BONUS` | 20 | Walk speed reduction in ms |
| `RUNE_SWIFTNESS_GATHER_BONUS` | 5 | Gathering speed reduction % |