# Gates

A gate is a condition that decides whether a patch runs against a given asset. Where [`:Named`](/doc/targeting-assets-8eefHSmg4w) filters by id, gates filter by the asset's actual contents or by some external condition. When a gate rejects an asset, the patch is skipped for that asset and the skip is recorded in [the summary](/doc/reading-the-summary-8ahmOdWbza), so you can see why nothing happened instead of guessing.

There are three gates: `:Requires`, `:Has`, and `:HasNo`.

## Requires: an arbitrary condition

`:Requires(predicate, message)` takes a function that receives the asset and returns true to allow the patch or false to skip it. The optional message is logged when it skips.

```lua
PM.Parts:Patch("BuffHeavyEngines")
        :Requires(|part| part.mass > 5.0, "part is not heavy enough")
        :Do(function(part) ... end)
```

The predicate runs per asset, so this patch applies only to the parts that pass.

`:Requires` also accepts a plain boolean instead of a function, which gates the whole patch at once. PatchManager calculates the boolean one time, when your script registers. During registration, no feature set is active, so `PM:Loaded` counts each installed mod as on. Use the boolean for facts about the install, for example whether a different mod is installed:

```lua
PM.Parts:Patch("MatchEnginePackBalance")
        :Requires(PM:Loaded("EnginePack"), "EnginePack is not installed")
        :Do(function(part) ... end)
```

When the boolean is false, the patch is skipped entirely and the reason shows up in the summary.

To turn a patch on or off for each campaign, use a [feature](/doc/features-geboWdIiDN) with `:Feature`, not a boolean. A boolean from a [config](/doc/config-integration-aTM54Tfqkz) value does not work for this, because settings never cause a rebuild of the patch cache. To run a patch only in campaigns that have a different mod on, use [`:Needs`](/doc/dependencies-and-ordering-werp1yYh7P), not `PM:Loaded`.

## Has: the asset must expose a key

`:Has(key, predicate, message)` skips the asset unless it has the named key. This is how you guard a patch that reads a field that might not be present, so you do not error on the assets that lack it:

```lua
PM.Parts:Patch("RetuneEngines")
        :Has("Module_Engine")
        :Do(function(part) ... end)
```

The predicate and message are optional. If you pass a predicate, it runs against the **value at that key**, not the whole asset, and the asset is allowed only if the predicate also passes:

```lua
:Has("maxTemp", |value| value < 2000, "already heat-tolerant")
```

So this reads as "the asset must have `maxTemp`, and that `maxTemp` must be under 2000."

## HasNo: the asset must not expose a key

`:HasNo(key, message)` is the inverse. It skips the asset if the key is present. Use it to avoid adding something that is already there, or to target only the assets missing a piece:

```lua
PM.Parts:Patch("AddDefaultDrag")
        :HasNo("Module_Drag", "already has drag")
        :Do(function(part) ... end)
```

## Gates versus doing it in the callback

You could write any of these as an `if` inside the `Do` callback and simply return early. The difference is reporting. A gate records a named skip in the summary, so when a patch does not run you can see exactly which gate rejected which asset and why. An early return inside the callback is invisible. Prefer gates for conditions that decide whether the patch should run at all, and save callback logic for shaping the change once it does.