# Conditions

A condition decides when a mission advances: when a branch transitions to a new stage, or when a stage counts as complete. Conditions can be simple (a watched value crossed a threshold, an event fired) or compound (this and that, either of these, not that). The missions module gives you builders for the compound case so the logic stays readable.

## The builders

Three methods compose conditions:

* `PM.Missions:And(...)` is true when every condition passed is true.
* `PM.Missions:Or(...)` is true when at least one is true.
* `PM.Missions:Not(condition)` inverts a single condition.

Each returns a condition you can pass to another builder or assign onto a branch or stage. They nest, so you can build a tree:

```lua
local condition = PM.Missions:And(
    reachedOrbit,
    PM.Missions:Or(hasCrew, isProbe)
)
```

This reads as "reached orbit, and either has crew or is a probe."

## The leaf conditions

The leaves of the tree (the actual `reachedOrbit`, `hasCrew` values above) are the game's concrete condition types: a property condition that compares a watched value, an event condition that waits for a game event, or a script condition. These are JSON objects with a `ConditionType` discriminator. The builders combine them. You usually obtain a leaf by copying the form from an existing mission and adjusting it, since the exact fields depend on the condition type. The [patch cache](/doc/caching-and-invalidation-QifFi4oev9) holds those missions' final JSON, which is the easiest place to read a real condition's form to copy.

The two you will use most are property conditions and event conditions. The watcher and message names they reference come from the game. The stub `pm-missions.d.lua` lists them, and an existing mission shows real ones in use.

### Property conditions

A property condition watches a single game value and is true when that value compares a certain way against a target you set. The value comes from a **property watcher**: a small game object that knows how to read one thing, like an apoapsis, a crew count, or whether a vessel is landed. You name the watcher, the comparison, and the value to test against.

You do not write the watcher's full type name by hand. `PM.Missions:GetPropertyWatcher(name)` takes the watcher's short name and returns the fully-qualified type string the condition's `PropertyTypeAQN` field expects. (The `AQN` suffix on these field names means assembly-qualified name, the long precise form of an internal type name. You never type one yourself, the helpers produce them.)

A property condition is a plain JSON table with `ConditionType = "PropertyCondition"`:

```lua
local reachedHighOrbit = {
    ConditionType = "PropertyCondition",
    -- watchers are named by their class, like this real apoapsis-altitude watcher
    PropertyTypeAQN = PM.Missions:GetPropertyWatcher("VehicleApoapsisAltitudePropertyWatcher"),
    propOperator = "GREATER",
    TestWatchedValue = 100000,
    RequireCurrentValue = false,
}
```

* `PropertyTypeAQN` is the watcher, from `GetPropertyWatcher`.
* `propOperator` is the comparison: `"GREATER"`, `"LESSER"`, or `"EQUAL"`.
* The test value goes in the field that matches the watcher's type: `TestWatchedValue` for a number, `TestWatchedInt` for an integer or enum, `TestWatchedstring` for a string. A boolean watcher needs no test value, the condition is simply true while the watched bool is true.
* `RequireCurrentValue` decides whether the condition latches. With `false`, once the comparison has been true even for a moment the condition stays satisfied. With `true`, it has to be true at the instant it is checked. Use `false` for "reached high orbit at some point", `true` for "is in high orbit right now".

### Event conditions

An event condition waits for something to happen rather than testing a value. It is true once a particular game **message** has fired at least once. Messages are the game's events: a vessel landed after flight, a part was decoupled, a sphere of influence was entered.

As with watchers, you do not write the message's type name by hand. `PM.Missions:GetMessage(name)` turns a short message name into the fully-qualified type string the condition's `EventTypeAQN` field expects.

```lua
local landedAfterFlight = {
    ConditionType = "EventCondition",
    -- messages are named by their class
    EventTypeAQN = PM.Missions:GetMessage("VesselLandedAfterFlight"),
}
```

That is the whole condition: there is no value to compare, only an event to wait for. Once the named message fires while the condition is active, it latches to true. (An optional `inputString` field narrows it to messages carrying a matching tag, for the messages that are parameterized. Most conditions leave it out.)

Both kinds are leaves. Drop them straight onto a branch or stage, or feed them into `And` / `Or` / `Not` to build something larger.

## Where conditions go

A built condition is assigned where the mission expects one:

* On a mission branch, as the `condition` that triggers the transition to its target stage.
* On a stage, as its `scriptableCondition`.

So the typical flow is: build the leaves, combine them with `And` / `Or` / `Not`, and assign the result onto the branch or stage you are patching.

## When to use this

If you are tightening or loosening an existing mission's logic, you are often editing the condition already on a branch rather than building one from scratch. If you are adding a new branch or stage, you build the condition with these builders. Either way, the builders keep a multi-part condition readable instead of a hand-nested pile of JSON. The full leaf-condition field forms are in `pm-missions.d.lua`.