Constructs an opposed test result from a source success test plus either a target success test or a target token (from which a fresh target test is created).
Must provide sourceTestResult, and either
targetTestResult or targetToken (a fresh target success test is
created from the token when only the latter is given).
Result options; options.parent is required (base
TestResult).
Whether a tie should be broken (see resolveTieBreak) rather than reported as a tie.
Foundry roll mode for chat output.
The initiating (source) actor's success test.
The responding (target) actor's success test.
Which side a tied contest is awarded to (an
OPPOSED_TEST_RESULT_TIEBREAK value) — NONE while the tie stands.
Set by resolveTieBreak, or supplied up front by a rule that dictates
the victor.
Which rule settled a broken tie, for the card to report; empty while the tie stands.
Whether neither side succeeded.
Human-readable description shown on the result's chat card.
Whether this contest was a tie that the tie-break rule then settled — the
two sides reached the same success level, but tieBreak awarded the
contest to one of them (see resolveTieBreak).
Whether both sides reached the same success level (and at least one succeeded — cf. bothFail).
The serialization discriminator for this instance — the concrete class's static Kind. Written into the JSON by toJSON under the kind key and read back by sohl.utils.defaultFromJSON to select the constructor. Derived from the class, never stored per-instance.
Internal identifier for this result (distinct from the display title).
Whether the source prevails — its success level exceeds the target's, or a tie was broken its way (and not bothFail).
Speaker identity (actor/token/user) used when posting this result to chat.
Whether the target prevails — its success level exceeds the source's, or a tie was broken its way (and not bothFail).
The active tie-break offset — tieBreak unless both sides failed, in which case 0.
Title shown at the top of the result's chat card.
victoryStars as one entry per star for the card to draw — true
where the star is the tester's (drawn filled) and false where it is
the target's (drawn hollow), so a glance at the line says who won as
well as by how much. Empty when nobody won.
Victory Stars — how decisively the contest was won: one star per step between the two success levels, or exactly one for a tie settled by the tie-break rule.
The margin has no ceiling. It is measured on the raw (unclamped) levels, so a modifier that pushes a level past the four-point scale widens the margin with it — a Marginal Success against a Critical Failure worsened by −1 is three stars, not two. An unbroken tie and a mutual failure are both worth none.
Deep-copy this entity, re-parenting the copy under parent with no other
changes. Shorthand for clone({}, { parent }).
The Logic to own the cloned entity.
The cloned entity.
Deep-copy this entity, optionally overriding fields and clone options.
Field overrides applied to the clone.
Clone options (e.g. a new parent).
The cloned entity.
Evaluate both sides of the contest, then settle a tie if the contest was run with breakTies. The winner is otherwise derived on demand from the two success levels (sourceWins / targetWins / isTied).
false if a test is missing or either side's evaluation is
disallowed (e.g. a permission gate); otherwise true.
Post the opposed-test card via the source's speaker — the request card
(opposed-request-card.hbs, with the Respond button) by default, or the
result card (opposed-result-card.hbs) when the caller supplies that
template (as sohl.entity.modifier.MasteryLevelModifier.opposedTestResume does).
Both sides are shaped into plain sourceTestResult / targetTestResult
data (title, token, item, mlMod display fields, roll, outcome flags) rather
than the live results, because the delegated
sohl.entity.result.SuccessTestResult.toChat folds this through
fvttMergeObject, which deep-copies and would strip a live instance's
getters. That delegation also honors the caller's template now (#845), so
the opposed card is no longer overridden by the standard test card.
Extra template data; template / title select and label
the card (request vs. result).
Serialize to a plain object satisfying OpposedTestResult.Data: the inherited TestResult fields plus both contestants' success tests and the tie-break configuration.
The plain-object representation.
The result of an opposed test — two actors directly competing via their respective success tests.
Opposed tests are used for contested actions: grappling, stealth vs. perception, persuasion vs. will, and similar skill-vs-skill situations. Each side performs a success test independently, and the results are compared to determine the winner.
Resolution
Key properties
Two-phase execution
Opposed tests are executed in two phases:
Subclass
CombatResult extends this for full combat resolution (attack vs. defense with damage calculation).