Scopes

Version

Please help with verifying or updating older sections of this article. At least some were last verified for version 3.2.

This article is for the PC version of Stellaris only.

Most objects in the game provide a scope to access them through script. A planet will provide a `planet` scope and a pop will provide a `pop` scope. The relationship between objects also relates to their scopes. To access the planet which a pop is on is called a scope switch, as your code is switching from referring to the pop to referring to the planet. Most objects and their scopes form a tree-like relationship, with the global scope representing the entire game.

In code, scopes are written as `<scope_type> = { }`, with all the script in the brackets referring to the specific object of the scope. For example:

`pop = { unemploy_pop = yes }` would cause the current pop to become unemployed. Scopes can be used in both *trigger* and *effect* blocks. Some triggers and effects will take a scope as an argument, and some apply to a specific scope despite what scope they are run. For example, `years_passed < 50` always refers to global scope, no matter what the current scope is.

A list of all known scopes is available below.

## System scopes

There are special system scopes that refer to relationships between scopes. These are `THIS`, `PREV`, `ROOT`, and `FROM`.

* **`THIS`** – Refers to the current scope. It is useless as context switch, but sometimes is used as input for certain effects. If you are in a `pop` scope, `this` would refer to that pop.
* **`PREV`** – Refers to the previous scope. If you are in a `pop` scope, and change to the `planet` scope, `prev` would refer back to the pop. `pop = { planet = { habitability = { who = prev value > 0.6 } } }` would check that the habitability of the current pop has over 60% habitability on its current planet. Sometimes you will want to refer back more than one scope step, in which case you can repeat prev up to four times, i.e. `prevprev` up to `prevprevprevprev`
* **`FROM`** – Refers to the scope from which the current script was called. For example, if an event executed a planet event, the planet event could refer back to the objects in the first event using the `from`scope. Just like PREV, up to four FROMs can be repeated to refer back multiple times.
* **`ROOT`** – Refers to the main scope of the script. For events, this will be the object the event is called in. For example, in a `planet_event`, `root` will be the specific planet the event was called on. ROOT is usually the default scope for script blocks in the event, but is shorter and more clear than PREV to refer to when you have switched to other scopes. For example, in a pop event’s `immediate` block, the pop is the default scope. But if you switch to the planet scope of the pop, and possibly to even more chained scopes, `root` will always refer back to the pop the event was called on. Note that in some scripts, such as scripted\_effects and scripted\_triggers, the default scope, `this`, is not necessarily the same as `root`.

In some contexts, these relationships aren't intuitive. For instance, `on_action`s will often override some of these system scopes to hold the objects the action refers to. For example, in events called from `on_ship_disabled`, `this` will refer to the disabled ship, and `from` will refer to the ship that disabled it. The vanilla *on\_actions.txt* file has comments describing most of these, while others you will have to look at code to determine to which objects they refer.

Note that these scopes can be also treated as new script context in some initial effect blocks (when they actually aren't), e.g. for `create_leader / clone_leader` (however, it is not clear if this is a bug or a feature, as this is an inconsistent behavior).(*checked v.3.4*)

## Chaining scopes

To simplify code and increase readability, a `.` can be used to chain scopes together. For example, `owner = { capital_scope = { solar_system = { … } } }` is equivalent to `owner.capital_scope.solar_system = { … }`, and will take you to the solar system of the capital of the country that owns the current scope. For the PREV and FROM system scopes, if you need more than four, you can chain them together as well: `prevprevprevprev.prevprev`. Note that this dot-scoping does not work with the scope-changing triggers and effects referred to below, also this does not imply a new PREV.

## Scope existence

Oftentimes scripts expect certain scopes to exist, or to run in certain scopes. Sometimes, some scopes and relationships don't always exist. For example, if you scope to the owner of a planet (`planet = { … owner = { … } }`), and the planet isn't owned, the script will fail and produce an error in the error.log. As such, it is good practice to always check that a scope exists if there is any chance it might not. This is done using `exists`. Before changing the scope, use `exists = [scope]`. If it doesn't exist, the following code won't run.

`planet = { exists = owner owner = { … } }`

## Triggers and scopes

*Main article: Triggers*

Most triggers can only be called within certain scopes. For instance, `is_moon` will only work in a planet scope. If you attempt to call a trigger in the wrong scope, it will produce an error in the error.log and often cause the rest of the code to fail or produce unintended results. The code will also error if you attempt to execute a trigger on a scope that doesn't exist.

Some triggers will also perform a scope change. These triggers usually begin with `any_`, and script in them will run in the implied scope. They will return yes if any object of that scope matches the criteria. For example, `any_planet_within_border = { is_planet_class = pc_gaia }` will return yes if the country it is called on has a Gaia planet in its borders. It will iterate through all `planet` scopes of the country and execute the trigger criteria in the scope. So all script within the trigger’s braces will execute in planet scope, even though it was called from country scope.

## Effects and scopes

*Main article: Effects*

Much like triggers, most effects only work in specific scopes. If you attempt to call a trigger in the wrong scope, it will produce an error in the error.log. However, executing an effect on a scope that doesn't exist will just cause nothing to happen with no error.

Some effects will also perform a scope change. These effects usually being with `every_` or `random_`. `every_` will apply the effect(s) within to every object of that scope, while `random_` will apply the effect(s) within to a single random object of that scope. A `limit = { … }` statement can be used within these effects to narrow down the results. For example, `every_owned_planet = { limit = { is_planet_class = pc_continental } … }` is called from country scope, but would apply the enclosed effect(s) to every Continental planet the country owned. The effects within would all run in the planet scope of the continental planet, even though they were called from country scope.

## Event target

Sometimes it’s a good idea to save certain scopes as event targets to use in later events or projects in the same namespace, or to use globally.

* Use the `save_event_target_as = <name>` to save the scope for later use in the namespace, or `save_global_event_target_as = <name>` to save the scope for later use anywhere.
* They can be scoped to using `event_target:<name> = { … }`, or used as a target for trigger or effect parameter.

For example, if an event at the start of a war saved the war leader as `save_event_target_as:war_leader`, after the war you could refer to them again:

`planet.owner = { set_subject_of = { who = event_target:war_leader subject_type = vassal } }`
Event targets are used in localization by referencing directly the variable name:

`"I have decided to release my vassal [target_leader.GetFullName]"`
Or can be used in tooltips of the event in which they are saved (which is normally not possible, as tooltips are built before effects are executed).

* Dynamic event targets:(since v.3.5) you have the ability add `@scope` in event targets and global event targets names. For example:

`save_event_target_as = something@root`. Although be warned, it doesn’t handle dot scoping very well and probably won’t do what you want it to do if you try something like `something@root.owner` or `exists` check also do not work properly.(still in v.3.6)
When you know you will no longer need a saved global event target, it is good practice to clear it: `clear_global_event_target = <name>`

*See also: Event modding*

## Scope Types

Every scope is of a particular type of object. The type determines when it can be used. They can be checked with `is_scope_type =` (*see Conditions*). The following are types that apply in game:

## List of scopes

You can get the latest version in-game by using the *`trigger_docs`* console command or can be found in the ***`scopes.log`*** file in your local user data folder **`script\_documentation`** (e.g. `%USERPROFILE%\Documents\Paradox Interactive\Stellaris\logs\script_documentation\`).

### Flat list of scopes

For comparing **old lists** of Stellaris triggers, modifiers and effects for most game versions since launch, you can use the GitHub file history feature here (created by OldEnt).

## References

1. ↑ Stellaris Dev Diary #267 – 3.5 'Fornax' Patch Notes, AI, Performance, and Modding – written by Eladrin – Sep 15, 2022
2. ↑ 2.0 2.1 Each scope should match the respective object in the other column (from/to). Scopes in brackets are only indirect (per extra effect).

**Modding**