Smart Terrains¶
Smart terrains are the core scheduling system for NPC and mutant life in Anomaly's offline simulation.
At script level, a smart terrain is a server entity of class se_smart_terrain (defined in smart_terrain.script) that:
- registers itself in the simulation board (
SIMBOARD) - loads and owns a list of jobs
- tracks which NPC is assigned to which job
- evaluates respawn rules
- exposes itself as a simulation target for squads
What a smart terrain actually is¶
A smart terrain is not "just a place marker." It is an active ALife object with logic.
In base scripts:
bind_smart_terrain.scriptbindsclsid.smart_terrainobjects tosmart_terrain_bindersmart_terrain_binder:update()callsself.se_smart_terrain:update()every tickse_smart_terrain:on_before_register()and:on_register()register the terrain into:SIMBOARD(sim_board.script)db.smart_terrain_by_id(db.script)
This is why smart terrains participate directly in simulation decisions instead of being passive config entries.
How squads use smart terrains¶
Squads (sim_squad_scripted) are assigned to smart terrains by the simulation board.
The main flow is:
simulation_board:get_squad_target(squad)picks candidate targets.- Smart terrains are filtered by
se_smart_terrain:target_precondition(squad). simulation_objects.evaluate_prior()scores valid targets.simulation_board:assign_squad_to_smart(squad, smart_id)moves the squad assignment.- On arrival,
se_smart_terrain:on_reach_target()links the squad to that smart terrain.
Population caps are enforced with max_population (read from the terrain config and checked in target preconditions).
Jobs: what NPCs do at a smart terrain¶
Each smart terrain owns job tables (stalker, monster, helicopter jobs).
se_smart_terrain:load_jobs():
- calls
gulag_general.load_job(self)to build a dynamic LTX with job sections - inspects each job's
activesection - resolves task anchors from logic fields like
path_walk,path_main,path_home,center_point, orpath_move - builds
CALifeSmartTerrainTasktasks for ALife routing
se_smart_terrain:update_jobs() and :select_npc_job() then:
- track arriving NPCs
- choose jobs based on availability and priority
- switch online NPC logic to the selected section via
xr_logic.configure_schemes()/xr_logic.activate_by_section()
Important detail: job ownership is stored in npc_by_job_section, so one non-exclusive job section is owned by one NPC at a time.
Config fields that matter most¶
se_smart_terrain:read_params() reads terrain behavior from the terrain's config (smart_terrain section).
Common high-impact fields:
max_population,min_populationarrive_distdefault_faction,faction_controlledrespawn_idle,respawn_radiusrespawn_only_level,respawn_only_smartrespawn_params/faction_respawn_numsafe_restr,def_restr,spawn_point
These values directly influence whether squads can target the terrain, when respawns happen, and how NPC jobs are initialized.
Respawn behavior¶
Smart terrain respawn is handled in se_smart_terrain:try_respawn().
A respawn only proceeds when key checks pass, including:
- terrain is enabled
- simulation availability allows it (
simulation_objects.available_by_id[self.id] ~= false) - actor is not too close (
respawn_radiuscheck on actor level) - enough time has passed (
respawn_idle) - section limits in
respawn_paramshave not been reached
When successful, the terrain typically spawns a squad through SIMBOARD:create_squad(self, squad_section) and tracks counts in already_spawned.
Runtime access from your scripts¶
You can work with smart terrains as server entities:
local smart = db.smart_terrain_by_id[some_smart_id]
if smart then
printf("smart: %s pop=%s/%s", smart:name(), SIMBOARD.smarts[smart.id].population, smart.max_population)
end
You can also identify smart terrain server objects by class:
local se_obj = alife_object(id)
if se_obj and se_obj:clsid() == clsid.smart_terrain then
-- se_obj is a smart terrain
end
Related simulation files worth reading¶
If you are modding smart terrain behavior, these are the core files:
scripts/smart_terrain.script- terrain class, job assignment, respawnscripts/sim_board.script- smart/squad registry and assignmentscripts/sim_squad_scripted.script- squad target logic and movement flowscripts/simulation_objects.script- target availability and priority scoringscripts/bind_smart_terrain.script- binder hookup and update bridgescripts/db.script-db.smart_terrain_by_idregistration
For spawn presets, see configs/misc/simulation.ltx (smart section -> starting squad composition).
Common modding pitfalls¶
- Do not treat smart terrains as online
game_objects; they are primarily server entities in ALife logic. - If a smart has missing/invalid job paths,
load_jobs()can silently degrade behavior (NPCs fail to get useful tasks). max_populationis enforced at simulation targeting time; adding squads elsewhere can still look "overcrowded" if you bypass normal assignment flow.respawn_only_smart = trueprevents normal target selection for that terrain (target_precondition()returnsfalse).