Implement Active Effects automation (Phase 11)

Schema & Documentation:
- Extended EFFECT_KEYS with 24 new mappings: senses (6), movement
  capabilities (5), skill training (12), focus tracking
- Created docs/ACTIVE_EFFECTS_REFERENCE.md with comprehensive guide
  for effect keys, modes, JSON format, and formula support

Ancestry Automation:
- Goblin: Darksight (darkvision), Nimble (+5 speed)
- Orc: Darksight (darkvision), Hulking (+2 item slots)
- Halfling: Nimble (+5 speed)
- Draken: Scale (+1 armor)
- Dwarf already had automation from earlier work

Class Automation:
- Wizard: Manifold Mind I/II (+1 focus.maxConcurrent each)
- Fighter Valor already automated (proof of concept)
- Gunslinger Deadeye deferred (dynamic, not static bonus)

Added Phase 11 to PROJECT_ROADMAP.json with 18 tasks (10 complete,
8 deferred for conditional flags/UI/state tracking).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2025-12-16 22:13:18 -06:00
parent 828cfed006
commit fa71f3b985
8 changed files with 521 additions and 16 deletions

View File

@ -1070,11 +1070,195 @@
"dependencies": ["10.1", "10.2"] "dependencies": ["10.1", "10.2"]
} }
] ]
},
{
"id": "phase-11",
"name": "Active Effects Automation",
"description": "Automate mechanical effects from ancestries, perks, and class features via Active Effects changes arrays",
"tasks": [
{
"id": "11.1",
"name": "Extend EFFECT_KEYS mapping",
"description": "Add missing keys to module/helpers/effects.mjs: senses (6), movement capabilities (5), skill training (12), focus tracking",
"completed": true,
"tested": false,
"priority": "critical",
"dependencies": ["1.15"]
},
{
"id": "11.2",
"name": "Create Active Effects reference documentation",
"description": "Create docs/ACTIVE_EFFECTS_REFERENCE.md documenting all available effect keys, modes, JSON format, and formula support",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"]
},
{
"id": "11.3",
"name": "Automate Dwarf ancestry traits",
"description": "Add changes arrays: Darksight (system.senses.darkvision=true), Tough (system.resources.hp.bonus=@level)",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"],
"notes": "Sturdy trait deferred - requires conditional Favor flag system"
},
{
"id": "11.4",
"name": "Automate Goblin ancestry traits",
"description": "Add changes arrays: Darksight (system.senses.darkvision=true), Nimble (system.speed.bonus=5)",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"],
"notes": "Scavenger trait deferred - requires conditional Favor flag system"
},
{
"id": "11.5",
"name": "Automate Orc ancestry traits",
"description": "Add changes arrays: Darksight (system.senses.darkvision=true), Hulking (system.itemSlots.bonus=2)",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"],
"notes": "Beefy trait deferred - requires conditional Favor flag system"
},
{
"id": "11.6",
"name": "Automate Halfling ancestry traits",
"description": "Add changes array: Nimble (system.speed.bonus=5)",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"],
"notes": "Squat (movement rule) and Tricksy (rest bonus) deferred"
},
{
"id": "11.7",
"name": "Automate Draken ancestry traits",
"description": "Add changes array: Scale (system.armor=+1)",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"],
"notes": "Breath Attack (complex ability) and Draconic Resilience (damage type choice) deferred"
},
{
"id": "11.8",
"name": "Automate Tough perk",
"description": "Verify changes array: system.resources.hp.bonus=@level (stackable)",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"],
"notes": "Already had correct implementation from earlier work"
},
{
"id": "11.9",
"name": "Automate Fighter class features",
"description": "Valor I/II/III crit reductions for melee and ranged attacks",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"],
"notes": "Fighter is the proof of concept. Valor reduces melee+ranged crit thresholds by -1/-2/-3."
},
{
"id": "11.10",
"name": "Automate Wizard class features",
"description": "Manifold Mind I/II: system.focus.maxConcurrent += 1 each (cumulative to 2, then 3)",
"completed": true,
"tested": false,
"priority": "high",
"dependencies": ["11.1"]
},
{
"id": "11.11",
"name": "Implement Favor/Hinder flag system for traits",
"description": "Create flag-based system for conditional Favor/Hinder: Elven Eyes (Favor on sight-based Detect), Beefy (Favor on Grapple/Shove), Scavenger (Favor on Sickened saves), Sturdy (Favor on Fear/Sickened/Shove)",
"completed": false,
"tested": false,
"priority": "medium",
"dependencies": ["11.3", "11.4", "11.5"],
"notes": "Deferred - requires extending existing Favor/Hinder Active Effects flag system to handle conditional triggers"
},
{
"id": "11.12",
"name": "Implement skill selection UI for ancestry traits",
"description": "Create dialog for traits that grant skill training choice: Elf Ascendancy (1 skill), Human Knack (1 skill + 1 perk)",
"completed": false,
"tested": false,
"priority": "medium",
"dependencies": ["11.3"],
"notes": "Deferred - requires UI similar to class level-up dialog"
},
{
"id": "11.13",
"name": "Implement spell selection UI for ancestry traits",
"description": "Create dialog for traits that grant spells: Elf Naturally Attuned (1 spell of choice)",
"completed": false,
"tested": false,
"priority": "medium",
"dependencies": ["11.12"],
"notes": "Deferred - requires spell compendium browser integration"
},
{
"id": "11.14",
"name": "Implement damage type selection for Draken",
"description": "Create dialog at ancestry add for Breath Attack damage type choice (fire/cold/shock/acid), applies to Draconic Resilience resistance",
"completed": false,
"tested": false,
"priority": "medium",
"dependencies": ["11.7"],
"notes": "Deferred - requires damage resistance system"
},
{
"id": "11.15",
"name": "Implement rest bonus hooks",
"description": "Hook into rest system for: Halfling Tricksy (+1 Luck on rest)",
"completed": false,
"tested": false,
"priority": "low",
"dependencies": ["11.6"],
"notes": "Deferred - requires rest system implementation"
},
{
"id": "11.16",
"name": "Implement Sharpshooter action tracking",
"description": "Track 'skip Move' action to enable crit reduction for Sharpshooter perk",
"completed": false,
"tested": false,
"priority": "low",
"dependencies": ["11.8"],
"notes": "Deferred - requires action economy tracking system"
},
{
"id": "11.17",
"name": "Implement Situational Awareness automation",
"description": "Automate: Favor on surprise checks, flanking doesn't Hinder saves",
"completed": false,
"tested": false,
"priority": "low",
"dependencies": ["11.11"],
"notes": "Deferred - requires conditional Favor/Hinder flag system and flanking tracking"
},
{
"id": "11.18",
"name": "Implement Gunslinger Deadeye tracking",
"description": "Track consecutive ranged hits to dynamically reduce crit threshold (resets each turn)",
"completed": false,
"tested": false,
"priority": "low",
"dependencies": ["11.1"],
"notes": "Deferred - requires combat turn state tracking, not a simple static bonus"
}
]
} }
], ],
"summary": { "summary": {
"total_tasks": 98, "total_tasks": 116,
"phases": 11, "phases": 12,
"critical_path": [ "critical_path": [
"0.1 -> 1.1 -> 2.1 -> 2.2 -> 3.1 -> 3.2 -> 7.1 -> 9.2", "0.1 -> 1.1 -> 2.1 -> 2.2 -> 3.1 -> 3.2 -> 7.1 -> 9.2",
"0.1 -> 1.6 -> 1.9 -> 2.8 -> 7.4 -> 9.4" "0.1 -> 1.6 -> 1.9 -> 2.8 -> 7.4 -> 9.4"

View File

@ -0,0 +1,273 @@
# Active Effects Reference
This document describes how to use Active Effects to automate mechanical bonuses from ancestries, perks, and class features in the Vagabond RPG Foundry VTT system.
## Overview
Active Effects are Foundry's mechanism for items (classes, perks, ancestries) to modify actor data. When an item with a `changes` array is added to an actor, the system automatically creates Active Effects that modify the actor's stats, resources, senses, etc.
## Effect Modes
| Mode | Constant | Value | Description |
| --------- | ------------------------ | ----- | ----------------------------------- |
| CUSTOM | `EFFECT_MODES.CUSTOM` | 0 | Custom logic (not commonly used) |
| MULTIPLY | `EFFECT_MODES.MULTIPLY` | 1 | Multiply the base value |
| ADD | `EFFECT_MODES.ADD` | 2 | Add to the base value (most common) |
| DOWNGRADE | `EFFECT_MODES.DOWNGRADE` | 3 | Use lower of base and effect value |
| UPGRADE | `EFFECT_MODES.UPGRADE` | 4 | Use higher of base and effect value |
| OVERRIDE | `EFFECT_MODES.OVERRIDE` | 5 | Replace the base value entirely |
### When to Use Each Mode
- **ADD (2)**: Numeric bonuses like +HP, +Speed, +Armor, crit threshold reductions
- **OVERRIDE (5)**: Boolean toggles like senses (darkvision), movement capabilities (fly), skill training
## Available Effect Keys
### Stats
| Shorthand Key | Full Path | Type | Typical Mode |
| ---------------- | ------------------------------ | ------ | ------------ |
| `stat.might` | `system.stats.might.value` | Number | ADD |
| `stat.dexterity` | `system.stats.dexterity.value` | Number | ADD |
| `stat.awareness` | `system.stats.awareness.value` | Number | ADD |
| `stat.reason` | `system.stats.reason.value` | Number | ADD |
| `stat.presence` | `system.stats.presence.value` | Number | ADD |
| `stat.luck` | `system.stats.luck.value` | Number | ADD |
### Resources
| Shorthand Key | Full Path | Type | Typical Mode |
| ----------------- | ---------------------------------- | ------ | ------------ |
| `hp.bonus` | `system.resources.hp.bonus` | Number | ADD |
| `mana.bonus` | `system.resources.mana.bonus` | Number | ADD |
| `mana.castingMax` | `system.resources.mana.castingMax` | Number | ADD |
| `luck.max` | `system.resources.luck.max` | Number | ADD |
| `studiedDice.max` | `system.resources.studiedDice.max` | Number | ADD |
### Combat Stats
| Shorthand Key | Full Path | Type | Typical Mode |
| ----------------- | ------------------------ | ------ | ------------ |
| `armor` | `system.armor` | Number | ADD |
| `itemSlots.bonus` | `system.itemSlots.bonus` | Number | ADD |
| `speed.bonus` | `system.speed.bonus` | Number | ADD |
### Save Bonuses
| Shorthand Key | Full Path | Type | Typical Mode |
| ------------- | --------------------------- | ------ | ------------ |
| `save.reflex` | `system.saves.reflex.bonus` | Number | ADD |
| `save.endure` | `system.saves.endure.bonus` | Number | ADD |
| `save.will` | `system.saves.will.bonus` | Number | ADD |
### Skill Crit Thresholds
| Shorthand Key | Full Path | Type | Typical Mode |
| ------------------ | ----------------------------------------- | ------ | ------------ |
| `crit.arcana` | `system.skills.arcana.critThreshold` | Number | ADD |
| `crit.brawl` | `system.skills.brawl.critThreshold` | Number | ADD |
| `crit.craft` | `system.skills.craft.critThreshold` | Number | ADD |
| `crit.detect` | `system.skills.detect.critThreshold` | Number | ADD |
| `crit.finesse` | `system.skills.finesse.critThreshold` | Number | ADD |
| `crit.influence` | `system.skills.influence.critThreshold` | Number | ADD |
| `crit.leadership` | `system.skills.leadership.critThreshold` | Number | ADD |
| `crit.medicine` | `system.skills.medicine.critThreshold` | Number | ADD |
| `crit.mysticism` | `system.skills.mysticism.critThreshold` | Number | ADD |
| `crit.performance` | `system.skills.performance.critThreshold` | Number | ADD |
| `crit.sneak` | `system.skills.sneak.critThreshold` | Number | ADD |
| `crit.survival` | `system.skills.survival.critThreshold` | Number | ADD |
### Attack Crit Thresholds
| Shorthand Key | Full Path | Type | Typical Mode |
| --------------------- | -------------------------------------- | ------ | ------------ |
| `crit.attack.melee` | `system.attacks.melee.critThreshold` | Number | ADD |
| `crit.attack.brawl` | `system.attacks.brawl.critThreshold` | Number | ADD |
| `crit.attack.ranged` | `system.attacks.ranged.critThreshold` | Number | ADD |
| `crit.attack.finesse` | `system.attacks.finesse.critThreshold` | Number | ADD |
### Senses (Boolean)
| Shorthand Key | Full Path | Type | Typical Mode |
| -------------------- | ---------------------------- | ------- | ------------ |
| `sense.darkvision` | `system.senses.darkvision` | Boolean | OVERRIDE |
| `sense.blindsight` | `system.senses.blindsight` | Boolean | OVERRIDE |
| `sense.allsight` | `system.senses.allsight` | Boolean | OVERRIDE |
| `sense.echolocation` | `system.senses.echolocation` | Boolean | OVERRIDE |
| `sense.seismicsense` | `system.senses.seismicsense` | Boolean | OVERRIDE |
| `sense.telepathy` | `system.senses.telepathy` | Boolean | OVERRIDE |
### Movement Capabilities (Boolean)
| Shorthand Key | Full Path | Type | Typical Mode |
| ---------------- | ----------------------- | ------- | ------------ |
| `movement.fly` | `system.movement.fly` | Boolean | OVERRIDE |
| `movement.swim` | `system.movement.swim` | Boolean | OVERRIDE |
| `movement.climb` | `system.movement.climb` | Boolean | OVERRIDE |
| `movement.cling` | `system.movement.cling` | Boolean | OVERRIDE |
| `movement.phase` | `system.movement.phase` | Boolean | OVERRIDE |
### Skill Training (Boolean)
| Shorthand Key | Full Path | Type | Typical Mode |
| --------------------------- | ----------------------------------- | ------- | ------------ |
| `skill.arcana.trained` | `system.skills.arcana.trained` | Boolean | OVERRIDE |
| `skill.brawl.trained` | `system.skills.brawl.trained` | Boolean | OVERRIDE |
| `skill.craft.trained` | `system.skills.craft.trained` | Boolean | OVERRIDE |
| `skill.detect.trained` | `system.skills.detect.trained` | Boolean | OVERRIDE |
| `skill.finesse.trained` | `system.skills.finesse.trained` | Boolean | OVERRIDE |
| `skill.influence.trained` | `system.skills.influence.trained` | Boolean | OVERRIDE |
| `skill.leadership.trained` | `system.skills.leadership.trained` | Boolean | OVERRIDE |
| `skill.medicine.trained` | `system.skills.medicine.trained` | Boolean | OVERRIDE |
| `skill.mysticism.trained` | `system.skills.mysticism.trained` | Boolean | OVERRIDE |
| `skill.performance.trained` | `system.skills.performance.trained` | Boolean | OVERRIDE |
| `skill.sneak.trained` | `system.skills.sneak.trained` | Boolean | OVERRIDE |
| `skill.survival.trained` | `system.skills.survival.trained` | Boolean | OVERRIDE |
### Focus Tracking
| Shorthand Key | Full Path | Type | Typical Mode |
| --------------------- | ---------------------------- | ------ | ------------ |
| `focus.maxConcurrent` | `system.focus.maxConcurrent` | Number | ADD |
## JSON Format
### Ancestry Trait Example
```json
{
"name": "Darksight",
"description": "<p>You can see in darkness as if it were dim light.</p>",
"changes": [
{
"key": "system.senses.darkvision",
"mode": 5,
"value": "true"
}
]
}
```
### Perk Example
```json
{
"system": {
"changes": [
{
"key": "system.resources.hp.bonus",
"mode": 2,
"value": "@level"
}
]
}
}
```
### Class Feature Example
```json
{
"name": "Valor I",
"level": 1,
"description": "<p>The roll required for you to Crit on Attack Checks is reduced by 1.</p>",
"passive": true,
"changes": [
{
"key": "system.attacks.melee.critThreshold",
"mode": 2,
"value": "-1",
"priority": 10
},
{
"key": "system.attacks.ranged.critThreshold",
"mode": 2,
"value": "-1",
"priority": 10
}
]
}
```
## Formula Support
Values can use Roll Data formulas for dynamic calculations:
| Formula | Description |
| ------------------------ | -------------------------- |
| `@level` | Character's current level |
| `@stats.might.value` | Character's Might stat |
| `@stats.dexterity.value` | Character's Dexterity stat |
| `@stats.awareness.value` | Character's Awareness stat |
| `@stats.reason.value` | Character's Reason stat |
| `@stats.presence.value` | Character's Presence stat |
| `@stats.luck.value` | Character's Luck stat |
### Formula Examples
```json
// HP bonus equal to level (Dwarf Tough, Tough Perk)
{ "key": "system.resources.hp.bonus", "mode": 2, "value": "@level" }
// HP bonus equal to Might stat
{ "key": "system.resources.hp.bonus", "mode": 2, "value": "@stats.might.value" }
```
## Implementation Details
### Where Changes Are Applied
1. **Ancestry Traits**: `VagabondItem.applyAncestryTraits()` in `module/documents/item.mjs`
2. **Perk Effects**: `VagabondItem.applyPerkEffects()` in `module/documents/item.mjs`
3. **Class Features**: `VagabondItem.applyClassFeatures()` in `module/documents/item.mjs`
### Key Mapping
The system supports both full paths (`system.senses.darkvision`) and shorthand keys (`sense.darkvision`). Shorthand keys are mapped to full paths via `EFFECT_KEYS` in `module/helpers/effects.mjs`.
### Priority
Effects with higher priority values are applied later (and thus can override earlier effects). Default priority is `null`. Use explicit priority (e.g., `10`) when order matters.
## Adding New Automatable Effects
1. Add the key mapping to `EFFECT_KEYS` in `module/helpers/effects.mjs`
2. Ensure the target path exists in the actor data model (`module/data/actor/character.mjs`)
3. Add the `changes` array to the relevant compendium JSON file
4. Test by adding the item to a character and verifying the effect applies
## Current Automated Effects
### Ancestries
| Ancestry | Trait | Effect |
| -------- | --------- | ------------------------------------- |
| Dwarf | Darksight | `system.senses.darkvision = true` |
| Dwarf | Tough | `system.resources.hp.bonus += @level` |
| Goblin | Darksight | `system.senses.darkvision = true` |
| Goblin | Nimble | `system.speed.bonus += 5` |
| Orc | Darksight | `system.senses.darkvision = true` |
| Orc | Hulking | `system.itemSlots.bonus += 2` |
| Halfling | Nimble | `system.speed.bonus += 5` |
| Draken | Scale | `system.armor += 1` |
### Perks
| Perk | Effect |
| ----- | ------------------------------------------------- |
| Tough | `system.resources.hp.bonus += @level` (stackable) |
### Class Features
| Class | Feature | Effect |
| ------- | ------------------ | -------------------------------------------------------------------------------------------------- |
| Fighter | Valor I/II/III | `system.attacks.melee.critThreshold -= 1`, `system.attacks.ranged.critThreshold -= 1` (cumulative) |
| Wizard | Manifold Mind I/II | `system.focus.maxConcurrent += 1` (cumulative, base 1 → 2 → 3) |
### Not Automated (Complex Mechanics)
| Class | Feature | Reason |
| ---------- | ------- | ------------------------------------------------------------------ |
| Gunslinger | Deadeye | Dynamic crit reduction based on consecutive hits, resets each turn |
| Magus | (none) | No simple numeric bonuses; features are spell-block related |

View File

@ -78,6 +78,38 @@ export const EFFECT_KEYS = {
"crit.attack.brawl": "system.attacks.brawl.critThreshold", "crit.attack.brawl": "system.attacks.brawl.critThreshold",
"crit.attack.ranged": "system.attacks.ranged.critThreshold", "crit.attack.ranged": "system.attacks.ranged.critThreshold",
"crit.attack.finesse": "system.attacks.finesse.critThreshold", "crit.attack.finesse": "system.attacks.finesse.critThreshold",
// Senses (boolean, use OVERRIDE mode=5)
"sense.darkvision": "system.senses.darkvision",
"sense.blindsight": "system.senses.blindsight",
"sense.allsight": "system.senses.allsight",
"sense.echolocation": "system.senses.echolocation",
"sense.seismicsense": "system.senses.seismicsense",
"sense.telepathy": "system.senses.telepathy",
// Movement capabilities (boolean, use OVERRIDE mode=5)
"movement.fly": "system.movement.fly",
"movement.swim": "system.movement.swim",
"movement.climb": "system.movement.climb",
"movement.cling": "system.movement.cling",
"movement.phase": "system.movement.phase",
// Skill training (boolean, use OVERRIDE mode=5)
"skill.arcana.trained": "system.skills.arcana.trained",
"skill.brawl.trained": "system.skills.brawl.trained",
"skill.craft.trained": "system.skills.craft.trained",
"skill.detect.trained": "system.skills.detect.trained",
"skill.finesse.trained": "system.skills.finesse.trained",
"skill.influence.trained": "system.skills.influence.trained",
"skill.leadership.trained": "system.skills.leadership.trained",
"skill.medicine.trained": "system.skills.medicine.trained",
"skill.mysticism.trained": "system.skills.mysticism.trained",
"skill.performance.trained": "system.skills.performance.trained",
"skill.sneak.trained": "system.skills.sneak.trained",
"skill.survival.trained": "system.skills.survival.trained",
// Focus tracking
"focus.maxConcurrent": "system.focus.maxConcurrent",
}; };
/** /**

View File

@ -11,15 +11,18 @@
"traits": [ "traits": [
{ {
"name": "Breath Attack", "name": "Breath Attack",
"description": "<p>As an Action, you can breathe elemental energy in a 15-foot cone, dealing 2d6! damage of your chosen type (fire, cold, shock, or acid, chosen at character creation). Targets may make a Reflex save to take half damage.</p>" "description": "<p>As an Action, you can breathe elemental energy in a 15-foot cone, dealing 2d6! damage of your chosen type (fire, cold, shock, or acid, chosen at character creation). Targets may make a Reflex save to take half damage.</p>",
"changes": []
}, },
{ {
"name": "Scale", "name": "Scale",
"description": "<p>Your natural scales grant you +1 Armor.</p>" "description": "<p>Your natural scales grant you +1 Armor.</p>",
"changes": [{ "key": "system.armor", "mode": 2, "value": "1" }]
}, },
{ {
"name": "Draconic Resilience", "name": "Draconic Resilience",
"description": "<p>You take half damage from one damage type of your choice (matching your breath weapon).</p>" "description": "<p>You take half damage from one damage type of your choice (matching your breath weapon).</p>",
"changes": []
} }
] ]
}, },

View File

@ -11,15 +11,18 @@
"traits": [ "traits": [
{ {
"name": "Darksight", "name": "Darksight",
"description": "<p>You can see in darkness as if it were dim light.</p>" "description": "<p>You can see in darkness as if it were dim light.</p>",
"changes": [{ "key": "system.senses.darkvision", "mode": 5, "value": "true" }]
}, },
{ {
"name": "Nimble", "name": "Nimble",
"description": "<p>Your base Speed is increased by 5.</p>" "description": "<p>Your base Speed is increased by 5.</p>",
"changes": [{ "key": "system.speed.bonus", "mode": 2, "value": "5" }]
}, },
{ {
"name": "Scavenger", "name": "Scavenger",
"description": "<p>You gain Favor on saves against the Sickened condition.</p>" "description": "<p>You gain Favor on saves against the Sickened condition.</p>",
"changes": []
} }
] ]
}, },

View File

@ -11,15 +11,18 @@
"traits": [ "traits": [
{ {
"name": "Nimble", "name": "Nimble",
"description": "<p>Your base Speed is increased by 5.</p>" "description": "<p>Your base Speed is increased by 5.</p>",
"changes": [{ "key": "system.speed.bonus", "mode": 2, "value": "5" }]
}, },
{ {
"name": "Squat", "name": "Squat",
"description": "<p>You can move through spaces occupied by larger creatures.</p>" "description": "<p>You can move through spaces occupied by larger creatures.</p>",
"changes": []
}, },
{ {
"name": "Tricksy", "name": "Tricksy",
"description": "<p>When you take a Rest, you regain +1 additional Luck.</p>" "description": "<p>When you take a Rest, you regain +1 additional Luck.</p>",
"changes": []
} }
] ]
}, },

View File

@ -11,15 +11,18 @@
"traits": [ "traits": [
{ {
"name": "Darksight", "name": "Darksight",
"description": "<p>You can see in darkness as if it were dim light.</p>" "description": "<p>You can see in darkness as if it were dim light.</p>",
"changes": [{ "key": "system.senses.darkvision", "mode": 5, "value": "true" }]
}, },
{ {
"name": "Beefy", "name": "Beefy",
"description": "<p>You gain Favor on Grapple and Shove attempts.</p>" "description": "<p>You gain Favor on Grapple and Shove attempts.</p>",
"changes": []
}, },
{ {
"name": "Hulking", "name": "Hulking",
"description": "<p>You have +2 additional Item Slots.</p>" "description": "<p>You have +2 additional Item Slots.</p>",
"changes": [{ "key": "system.itemSlots.bonus", "mode": 2, "value": "2" }]
} }
] ]
}, },

View File

@ -74,7 +74,9 @@
"level": 4, "level": 4,
"description": "<p>You can Focus on up to two Spells at the same time.</p>", "description": "<p>You can Focus on up to two Spells at the same time.</p>",
"passive": true, "passive": true,
"changes": [] "changes": [
{ "key": "system.focus.maxConcurrent", "mode": 2, "value": "1", "priority": 10 }
]
}, },
{ {
"name": "Extracurricular", "name": "Extracurricular",
@ -88,7 +90,9 @@
"level": 8, "level": 8,
"description": "<p>You can now Focus on up to three Spells at the same time.</p>", "description": "<p>You can now Focus on up to three Spells at the same time.</p>",
"passive": true, "passive": true,
"changes": [] "changes": [
{ "key": "system.focus.maxConcurrent", "mode": 2, "value": "1", "priority": 10 }
]
}, },
{ {
"name": "Archwizard", "name": "Archwizard",