Base logic class for all actor types (Being, Cohort, Structure, Vehicle).

Provides the foundation that all actor logic classes build upon. Concrete actor logic classes extend this to implement type-specific rules: health tracking, anatomy modeling, passenger management, etc.

Type Parameters

Hierarchy (View Summary)

Indexable

  • [key: symbol]: true

Constructors

Properties

actions: SohlMap<string, sohl.entity.action.SohlAction>

Executable actions for this document, keyed by shortcode — context-menu entries, chat-card buttons, and lifecycle hooks. A script action shadows (wholly overrides) the intrinsic action of the same shortcode (see the constructor).

The actor's tactical move (feet per combat round) as a sohl.entity.modifier.ValueModifier so runtime modifiers (haste, encumbrance, etc.) can layer on. Seeded from the active moveProfile when it is enabled.

The actor's overland travel speed (leagues per watch) as a sohl.entity.modifier.ValueModifier. Seeded from the active moveProfile when it is enabled.

moveProfile: MovementProfile

The active movement profile, selected during initialize by this actor's SohlActorData.currentMoveMedium. A disabled MOVEMENT_MEDIUM.NONE profile when the actor has no matching profile (a non-mover).

Accessors

  • get actor(): null | SohlActor
  • The owning SohlActor — the document itself when it is an actor, otherwise its owning actor (for an item, combatant, or effect), or null.

    Returns null | SohlActor

  • get actorLogic(): null | SohlActorLogic<any>
  • The logic of the owning actor — the Foundry-free way to reach the actor layer from any logic. For an actor's own logic this is itself; for an item's logic it is the owning actor's logic; otherwise null.

    Returns null | SohlActorLogic<any>

    Resolved through the SohlLogicData port, so logic code can navigate to the actor (and iterate items via allLogics / logicTypes / getItemLogic) without touching the Foundry document.

  • get data(): TData
  • This logic's typed data — its *Data interface (e.g. SkillData), the same persisted object as document.system. Prefer document.logic.data when reading a document's fields from a macro, Script Action, or module: it is the typed, API-documented surface (autocomplete and reference links resolve), whereas document.system is typed as the internal DataModel.

    Returns TData

    Convenience accessor for parent.

  • get item(): SohlItem
  • The owning SohlItem.

    Returns SohlItem

    If this logic is not embedded in an item.

  • get kind(): string
  • The owning document's kind (its actor or item type id).

    Returns string

  • get typeLabel(): string
  • Localized type (and sub-type, when present) label for the owning document.

    Returns string

  • get uuid(): string
  • The owning document's UUID — the opaque identity token from the data port.

    Returns string

Methods

  • Compute derived values that depend on sibling items being initialized.

    Returns void

    Called on every item after ALL items have completed initialize.

    Safe to access: sibling items' initialized state (e.g., reading trait attribute values for a skill base formula).

    Not safe to access: sibling items' evaluated state — another item's evaluate() may not have run yet. Dependencies on evaluated state belong in finalize.

    Example: a Skill reads trait attribute values to compute its skill base; a gear item resolves its containerId to find its parent container.

  • Resolve cross-item dependencies that require all items to have been evaluated.

    Returns void

    Called on every item after ALL items have completed evaluate.

    Safe to access: all sibling items' initialized and evaluated state.

    Example: fate mastery level (which depends on an already-evaluated Aura trait); encumbrance totals summed across all evaluated gear.

  • The context-menu options — the actions currently available — for this logic's document.

    Returns ContextMenuEntry[]

    The available context-menu entries.

    One entry per action whose visible predicate currently passes (an action's trigger / domain preconditions can hide it); SCRIPT actions are additionally permission-gated when executed. Use this to discover which actions can be performed on the document.

  • Find an embedded item's logic by its shortcode and item kind.

    Type Parameters

    • K extends ItemKind

      The item kind, inferred from the type argument.

    Parameters

    • shortcode: string

      The item's system.shortcode.

    • type: K

      The ItemKind to match (e.g. ITEM_KIND.SKILL).

    Returns undefined | ItemLogicByKind[K]

    The matching item's logic typed for type, or undefined if no item matches.

    Both arguments are required: a shortcode is only unique within a given item kind, so matching the type as well prevents returning an unexpected item that happens to share the shortcode. The item kind also drives the return type — the concrete logic for that kind is resolved from ItemLogicByKind, so no cast is needed at the call site:

    const stealth = actor.logic.getItemLogic("stealth", ITEM_KIND.SKILL);
    // ^? SkillLogic | undefined
  • Find an embedded item's logic by its id.

    Parameters

    • id: string

      The item's id.

    Returns undefined | SohlItemLogic<any>

    The matching item's logic or undefined if no item matches.

  • Handle a trigger dispatched by the SoHL event queue. Override in subclasses to implement actor-specific trigger handling.

    Parameters

    • kind: string

      Subscription kind identifier

    • _context: SohlTriggerContext

      Trigger context (discriminated by context.name)

    • Optional_payload: Record<string, unknown>

      Optional context data attached when subscribing

    Returns Promise<void>

  • Set this actor's SohlActorData.currentMoveMedium — the active movement profile — to the medium carried in the action scope.

    Intrinsic-action executor for the makeDefaultMedium action.

    Parameters

    Returns Promise<void>

    Resolves once the actor update completes, or immediately when no medium was chosen.

    The Profile-tab star names the medium in scope and applies it directly. Invoked any other way — from the Actions menu, a macro, a script — there is no medium to apply, so the action offers the choice (the prefer-dialog rule) rather than returning silently as it once did (#1098). The prompt lists the no-movement medium plus every medium this actor authors a profile for, preselected at the current one. A caller that suppressed the dialog cannot be prompted, so it gets a notice instead of an unexplained no-op.

  • GM re-edit of a settled opposed contest (#1082) — the edit pencil in the Opposed Action Result card's header, and the two-sided counterpart to the standard card's sohl.document.item.logic.SohlItemBaseLogic.resultEdit (#856).

    Re-opens the standard test dialog for each side in turn, pre-filled with that side's current situational and success-level modifiers, applies the new values, re-evaluates the contest on both frozen rolls (never a re-roll, no Fate cost), and reposts the Opposed Action Result card. The settled contest rides in context.scope.opposedTestResult — the whole result serialized into the pencil's data-scope and revived by the chat-card dispatcher — so the edit acts on that contest.

    The contest lives only in the chat log, never on a document, so an edit mutates nothing persistent: it posts a new, corrected card and leaves the original standing (see the action-card consent model). Dismissing either side's dialog cancels the whole edit — no re-evaluation, no repost.

    GM-only. The pencil is render-hidden from non-GMs (sohl.document.chat.gateEditActionPencil); this is the click-time half of that gate — a synthesized click from a non-GM is refused here.

    Parameters

    • context: sohl.entity.action.SohlActionContext<
          {
              opposedTestResult?: sohl.entity.result.OpposedTestResult;
              source?: { situationalModifier?: number; successLevelMod?: number };
              target?: { situationalModifier?: number; successLevelMod?: number };
          },
      >

      The action context; context.scope.opposedTestResult is the settled contest. When skipDialog is set, each side's new situationalModifier / successLevelMod are taken from context.scope.source / context.scope.target instead of the dialogs.

    Returns Promise<undefined | sohl.entity.result.OpposedTestResult>

    The re-evaluated contest, or undefined when refused (non-GM), missing a contest, or cancelled (a dialog dismissed).

  • Serialize this logic to a plain reference.

    Returns PlainObject

    A uuid-keyed reference to this logic.

    A logic is a behavior wrapper over a live Foundry document; it is never revived from its own JSON (its constructor needs that document). Wherever a logic is persisted — a chat card, an action sohl.entity.action.SohlActionContext.scope — it is re-resolved from its uuid (e.g. via fvttLogicFromUuidSync), not rebuilt from a payload. So it serializes as a compact, resolvable reference (name/kind are carried for display and debugging); the owning document holds the actual persisted state.