Skip to content

Actors and Items

forelius edited this page Aug 2, 2026 · 1 revision

Actors and Items

For developers. This page documents FaDe's internals — it's aimed at module authors and contributors, not players or GMs.

This page expands the Developer Guide section on actors and items. FaDe follows Foundry v12+'s split between document classes (behavior) and data models (schema and derived data), so actors and items each have both layers.

Factories

Foundry instantiates documents through the class registered as CONFIG.Actor.documentClass / CONFIG.Item.documentClass. FaDe registers Proxies there that dispatch construction to the right subclass based on the document's type.

  • ActorFactory — a Proxy over FDCombatActor. Its construct trap reads the actor type from the first constructor argument and uses Reflect.construct to build CharacterActor, MonsterActor, or FDVehicleActor.
  • ItemFactory — a Proxy over FDItem. Its construct trap reads data.type and news the matching item class from a fixed map (15 types). An unknown type throws Item constructor error.

The proxies keep Foundry's document system decoupled from FaDe's class hierarchy: the factory receives the standard (data, context) constructor arguments and passes them through to the chosen subclass.

Actor classes

The actor class tree, each layer adding more specific behavior:

FDActorBase (extends Actor)
└── FDCombatActor
    ├── CharacterActor
    ├── MonsterActor
    └── FDVehicleActor
  • FDActorBase — everything shared by all FaDe actors:
    • v11-compatibility toggleStatusEffect, a currentActiveToken getter, and highestLevel (delegated to the classSystem registry system).
    • prepareBaseData() runs _prepareEffects(), which disables active effects on equippable items that aren't currently equipped.
    • prepareDerivedData() delegates to registry systems: encumbranceSystem.prepareDerivedData, actorMovement.prepareMovementRates, armorSystem.prepareDerivedData.
    • HP handling: on update, toggles isDead and the dead status effect when HP crosses zero; modifyTokenAttribute intercepts HP deltas, asks for a damage type, and routes the change through damageSystem.ApplyDamage.
    • getRollData() (system data plus class roll data), getEvaluatedRollSync, and GM-whispered change logging.
  • FDCombatActor — combat-capable actors (character, monster, vehicle):
    • Owns a TagManager.
    • _preCreate() assigns sensible prototype-token defaults (vision, artwork, disposition, actor link, scale) depending on whether the actor is a character or monster.
    • Saving-throw rolling and the static chat click handlers (handleSavingThrowRequest, handleActionRoll).
    • getAmmoItem() ammo resolution and getAvailableActions() for combat maneuver declarations.
    • Helpers that sync class/ancestry-derived content onto the actor: setupSpecialAbilities, setupItems, setupLanguages, setupMinAbilityScores — each pulling definitions through fadeFinder (world first, compendium fallback).
  • CharacterActor — derives a wrestling rating and defers onUpdateActor to the classSystem and ancestrySystem registry systems; logs player changes to the GM.
  • MonsterActor — derives a wrestling rating; onUpdateActor reacts to changes in classAbilityAs / castAs / saveAs by resolving the referenced class definitions and letting classSystem set up abilities, spell casting, and saving throws.
  • FDVehicleActor — extends FDCombatActor; adds vehicle-specific _preCreate defaults.

Actor data models

Each actor type is backed by a data model registered in CONFIG.Actor.dataModels:

FDActorBaseDM
└── FDCombatActorDM
    ├── CharacterDataModel
    ├── MonsterDataModel
    └── FDVehicleDM

Schema fields are defined in actor/fields/ — FDActorBaseField, FDCombatActorField, CharacterField, FDTroopField, MonsterField — and composed into the data models. The data models also prepare data: FDCombatActorDM.prepareBaseData() resets the modifier block (mod.ac, mod.combat.*, mod.save.*, and the rest of the fields documented on the Active Effect Variables page) and delegates ability-score prep to the abilityScore registry system.

The division of labor is: data models own schema and data preparation; document classes own behavior (rolling, dialogs, chat messages, updates).

Item classes

The item class tree:

FDItem (abstract, extends Item)
├── GearItem
│   ├── WeaponItem
│   ├── ArmorItem
│   └── LightItem
├── SpellItem
├── SkillItem
├── ConditionItem
├── SpecialAbilityItem
├── ActorClassItem
├── ClassDefinitionItem
├── ActorMasteryItem
├── MasteryDefinitionItem
├── AncestryDefinitionItem
└── AmmoItem
  • FDItem (abstract) — shared behavior for every item:
    • Identification-aware names and descriptions (knownName / knownDescription fall back to the unidentified variants for non-owners; unknownName returns the unidentified name).
    • Attack-capability getters (canMelee, canShoot, canThrow, canAttack) and charge/use/cast getters (hasCharge, hasUse, hasCast).
    • Container support (containedItems, ownerToken), default icons per type, and an overridden create() that auto-assigns an icon when none is given.
    • getRollData() starts from this.system, adds the owning actor's roll data and classes, and is the roll-data source for item rolls.
    • roll() produces a generic chat message by default; subclasses override it (attacks, damage, casting, and so on).
    • _processNonTransferActiveEffects() applies the item's non-transferring active effects to the item's own system data (for example, a weapon that scales its damage).
    • Charge/usage consumption via _tryUseCharge / _tryUseUsage, which also warn when an item is exhausted.
  • GearItem — physical items: weight, quantity, cost, equipped/dropped state, and containers (recursive totalEnc, isContained). Owns a TagManager.
  • WeaponItem — the most complex: owns an AttackRollService (which produces the attack roll and digest), rollAttack(), getDamageRoll() (combining the damageSystem and weaponMastery registry systems), getAttackTypes() (melee/missile/breath, potentially mastery-gated), plus prepared damage labels and modifier text.
  • ArmorItem and LightItem extend GearItem; the remaining types extend FDItem directly.

ItemFactory maps each type to one of these classes: armor, weapon, item/treasure (both GearItem), specialAbility, mastery, skill, light, spell, class, weaponMastery, condition, species, actorClass, ammo.

Item data models

There is one data model per item type in item/dataModel/, all registered in CONFIG.Item.dataModels. The physical/equippable types share GearItemDataModel, which ArmorItemDataModel, WeaponItemDataModel, and LightItemDataModel extend; the rest extend foundry.abstract.TypeDataModel directly. Custom field groups live in item/fields/ — IdentifiableField, SpellField, SpecialAbilityField.

GearItemDataModel shows the composition pattern: it spreads IdentifiableData's schema and adds the physical fields (quantity, charges, weight, cost), the equippable field (equipped), and container fields (containerId, isOpen, container).

How actors and items connect

Items are embedded documents on actors — actor.items and item.actor (or item.parent). FaDe leans on this in both directions:

  • Actors build themselves from definitions. The setup* helpers on FDCombatActor resolve class/ancestry-given content (items, special abilities, languages, saving throws) through fadeFinder and add or update the corresponding embedded items. This is the "items as a database" idea from the Developer Guide overview in action.
  • Items read their actor. getRollData() merges the owning actor's roll data and classes, so an item's formulas can reference its owner's stats.

Extending actors and items

Modules extend this two-layer system mostly through the data-model side. The mechanism used by fade-white-box-fmag (CONFIG.Actor.dataModels.character = MyCharacterDataModel, subclassing CharacterDataModel) swaps the schema while keeping FaDe's document class and factory behavior intact.

Clone this wiki locally