A group of individuals acting as a unit.

A Cohort represents multiple actors treated as a single entity for movement, combat, and other mechanics. Examples include a party of adventurers, a squad of soldiers, a pack of animals, or a ship's crew section.

Each member names its actor by a single handle — a shortcode for a world or compendium actor, or a UUID for a Token Actor (several wolves sharing one base actor but tracked separately cannot be told apart by shortcode). Members also have a role within the cohort.

One member may be the cohort's leader, named by CohortData.leaderCode.

When placed on a scene, a Cohort can appear as either a single group token or individual tokens per member. Single-token cohorts cannot participate in combat but are useful for representing group movement on large-scale maps.

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 document(): TData["parent"]
  • The owning document — the actor or item this logic is embedded in.

    Returns TData["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 leaderCode(): null | string
  • The handle of the member leading this cohort, or null when it has no leader.

    The leader is always one of the members: a stored CohortData.leaderCode that names nobody in the current list — the leader was removed, or the handle was never a member — reads as no leader at all, rather than as a stale name the sheet would go on displaying.

    Returns null | string

    The leading member's handle, or null.

  • get memberLogics(): SohlActorLogic<any>[]
  • The logic of every member actor this cohort can resolve.

    Each CohortData.members entry names its world actor by shortcodeOrUuid — a system.shortcode for a world or compendium actor, a UUID for an unlinked Token Actor — resolved through fvttActorByRef. Entries that no longer resolve (the actor was deleted, or this client cannot see it) are simply absent; a cohort with a stale member still lists the rest.

    Returns SohlActorLogic<any>[]

    One logic per resolvable member, in members order.

  • get memberRows(): CohortMemberRow[]
  • The cohort's membership as display rows — one per stored entry, in members order, each joined to the actor its handle resolves to.

    This is the single seam the Members tab, the leader readout, and the member-management actions all read: a member is named by its actor where that actor resolves, and by its raw handle where it does not (see CohortMemberRow).

    Returns CohortMemberRow[]

    One row per member entry.

  • get sharedGear(): SharedGearEntry<GearLogic>[]
  • The gear this cohort's members have shared with it (issue #76).

    A cohort carries nothing of its own: this walks each resolvable member and collects the gear whose sharing list names this cohort, pairing every item with the member that actually carries it. The result is read-only — the item stays on its custodian, and it is edited there.

    Returns SharedGearEntry<GearLogic>[]

    One entry per shared item, ordered by carrier then item name.

  • 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

  • Add a member to this cohort.

    Intrinsic-action executor for the addMember action. Asks for the member's handle — a shortcode (a world or compendium actor) or a UUID (a Token Actor: a band of orcs are each unlinked actors of one common orc world actor, which no shortcode can tell apart) — and the role it takes in the cohort. Anything already in context.scope pre-fills the dialog rather than replacing it.

    The handle must resolve to an Actor this client can see, and must not already be a member; otherwise nothing is added and the user is told why.

    Parameters

    • context: sohl.entity.action.SohlActionContext

      The action context; context.scope.shortcodeOrUuid and context.scope.role pre-fill the dialog, and skipDialog (with a handle already supplied) adds without asking.

    Returns Promise<void>

    Resolves once the member is added, or immediately if not.

  • Build an update() payload that appends a member to CohortData.members.

    Parameters

    • member: { role: string; shortcodeOrUuid: string }

      The member entry to add.

      • role: string

        This member's role within the cohort (e.g. leader, follower).

      • shortcodeOrUuid: string

        How this member's actor is found: its system.shortcode (a world or compendium actor) or a UUID (a Token Actor, which no shortcode can reliably identify). Resolved through fvttActorByRef.

    Returns PlainObject

    An update payload (does not itself persist the change).

  • 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).

  • Remove a member from this cohort, after confirming.

    Intrinsic-action executor for the removeMember action. With no handle in scope (invoked from the Actions tab rather than from a member's row) it first asks which member to remove. Removing the leader also clears the leader — see removeMemberUpdate.

    Only the cohort's membership entry is removed: the member's actor, and everything on it, is untouched.

    Parameters

    Returns Promise<void>

    Resolves once the member is removed, or immediately if not.

  • Build an update() payload that removes the member with the given shortcode or UUID from CohortData.members.

    Removing the leader also clears CohortData.leaderCode in the same payload: a leader who is no longer a member is not a leader, and leaving the code behind would make the cohort silently re-acquire that leader if the same handle were ever added back.

    Parameters

    • shortcodeOrUuid: string

      The shortcode or UUID of the member to remove.

    Returns PlainObject

    An update payload (does not itself persist the change).

  • Build an update() payload that makes the named member this cohort's leader — or clears the leader, when the given handle is already leading (the control is a toggle) or is null.

    Parameters

    • shortcodeOrUuid: null | string

      The member to promote, or null to clear.

    Returns undefined | PlainObject

    An update payload, or undefined when the handle names nobody in the member list (nothing to promote).

  • Make a member this cohort's leader — or, when that member already leads it, stand them down so the cohort has no leader.

    Intrinsic-action executor for the toggleLeader action. Invoked from a member's row the handle rides in scope and the toggle is immediate: it is an explicit, single-click, self-reversing choice by the cohort's owner, so a confirmation would only be noise. Invoked from the Actions tab, with no handle, it asks which member to promote.

    Parameters

    Returns Promise<void>

    Resolves once the leader is set or cleared, or immediately if not.

  • 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.