Skip to content

Controllable

A Controllable is the X4 engine abstract class for entities that have a pilot, crew, and order queue — ships and (via Defensible) stations and modules with control. The class adds command hierarchy (commander/subordinates/fleet), order queue semantics, and scanner/software integration on top of Object.

Inheritance: object → controllable. Direct subclass: Defensible (which in turn is parent of Ship/Station).

Identifies the NPCs piloting/operating the controllable:

PropertyTypeDescription
.pilotentityPilot entity currently active
.assignedpilotentityAssigned pilot (may not currently be piloting)
.aipilotentityAI pilot entity
.assignedaipilotentityAssigned AI pilot
.defencenpcentityDefence control entity
.tradenpcentityTrade control entity
.tradecomputerentityTrade computer (player-controlled ship)
.engineerentityEngineer entity
.shiptraderentityShiptrader entity
.shadyguyentityShady guy (Pirate-DLC criminal NPC)
.controlentity.defaultentityMain control entity
.controlentity.{$controlpost}entityControl entity at a specific control post
.controlposts.alllistAll control posts for this object
.controlposts.freelistAll unoccupied control posts
.controlposts.{$entity}listControl posts the entity can take
.controlroomroomThe control room (or null)
.controlpostslot.{$controlpost}componentslotSlot for the entity at that control post
.slotactor.{$componentslot}entityActor reserved for the specified NPC slot

The order queue is the central controllable behavior. See Order for full details.

PropertyTypeDescription
.orderorderCurrent order (queue head or default)
.nextorderorderNext order in queue
.defaultorderorderDefault order if present
.orderslistAll orders in queue (current first)
.buildorderslistBuild/repair-related orders only
.tradeorderslistTrade-related orders only
.hasorderloopbooleanAre orders looping? (UI-only — read from MD, not settable)
.hasblacklist.{type}.{group}booleanBlacklist of given type+group exists

For fleet management:

PropertyTypeDescription
.commandercontrollableCommander (if subordinate)
.toplevelcommandercontrollableTop-level commander (root of hierarchy)
.commanderentityentityCommander entity
.assignmentassignmentThis subordinate’s assignment under commander
.canuseassignment.{$assignment}.{$controllable}booleanCan use that assignment under specified commander
.canhavecommander.{$component}booleanCan $component be a commander for this
.subordinateslistDirect subordinates
.subordinates.{$assignment}listSubordinates with specific assignment
.allsubordinateslistAll subordinates (recursive)
.allcommanderslistAll commanders in chain
.activesubordinategroupidslistSubordinate groups with assigned ships
.subordinategroupidintegerThis object’s subordinate group ID
.subordinategroupassignment.{$id}assignmentAssignment of subordinate group
.subordinategroupprotectedsectorsectorSector being protected by detached group (positiondefence only)
.subordinategroupprotectedpositionpositionPosition being protected
.subordinategroupdockoverridebooleanAlways dock at commander?
.subordinategroupreinforcefleetbooleanReinforce other groups when engaged?
.subordinategrouprespondtodistresscallsbooleanRespond to faction distress?
.subordinategroupresupplyatfleetbooleanRepair/resupply at fleet?
.subordinategroupattackonsightbooleanAttack hostiles on sight?
PropertyTypeDescription
.fleet.namestringFleet name (empty if not a fleet commander)
.fleet.iscommanderbooleanIs this a fleet commander?
.fleet.commandercontrollableTop-level fleet commander
.fleetunitfleetunitFleet unit if this is a rebuild replacement
.fleetunitslistFleet units for this fleet

Tracks crew/personnel as NPC templates (lower memory than actual NPCs):

PropertyTypeDescription
.people.{$npctemplate}npctemplateentryNPC template entry for specific template
.people.countintegerNumber of people on board
.people.freeintegerFree space for more people
.people.capacityintegerMax capacity
.people.listlistAll people on board
.people.{$entityrole}.listlistPeople with specific role
.people.{$entityrole}.countintegerCount per role
.people.{$entityrole}.combinedskillintegerCombined skill across role (0-100)
PropertyTypeDescription
.roleentity.{$seed}entityEntity representing seed-based person
.roleentity.{$npctemplate}entityEntity representing template-based person
.roleentitieslistAll instanced role entities
.isnpcassignmentrestrictedbooleanIs this object restricted from NPC assignment?
.canhavecontrolentity.{$controlpost}booleanCan have control entity at that post?
.waypointactors.{$componentslot}listActors moving toward that waypoint
PropertyTypeDescription
.hasscannerbooleanHas scanner software
.longrangebooleanHas long-range scanner
.maxscanlevelintegerMaximum scan level
.software.compatiblewarelistCompatible software wares
.software.defaultwarelistDefault-installed software
.software.installedwarelistCurrently installed software
.software.dockwareDock assist software installed
.software.longrangewareLong range scanner installed
.software.policewarePolice scanner installed
PropertyTypeDescription
.haswalkableroombooleanHas rooms accessible to player/NPCs
.canhavedynamicinteriorbooleanCan contain a dynamic interior
<set_value name="$pilot" exact="$ship.aipilot"/>
<do_if value="$ship.order.id == 'Patrol'">
<!-- ship is on a patrol order -->
</do_if>

"Find subordinates of a faction’s fleet"

Section titled “"Find subordinates of a faction’s fleet"”
<do_for_each name="$sub" in="$commander.subordinates">
<do_if value="$sub.iscapitalship">
<!-- this is a capital sub -->
</do_if>
</do_for_each>

"Check if a ship can be commander of another”

Section titled “"Check if a ship can be commander of another””
<do_if value="$potentialcommander.canhavecommander.{$candidate}">
<!-- candidate can command this ship -->
</do_if>
  • .hasorderloop is UI-only — readable but NOT settable from MD/aiscript. Engine-side flag; see Repeat Orders UI gotcha in Wiki
  • .commander returns the DIRECT commander, NOT the top-level fleet commander. Use .toplevelcommander for the fleet root.
  • .order returns null if no orders are running — null-check before accessing .order.id.
  • .subordinates is direct only. Use .allsubordinates to walk the full hierarchy (recursive).
  • Slots and roles can be filled by actors that don’t actually appear — use .slotactor carefully.
  • .controlentity.{$controlpost} returns null if no entity is currently at that post. Check .controlposts.free first.
object
└── controllable ← this class
└── defensible (defensive abilities — shields/surfaces)
├── ship (mobile entities with full pilot crew)
└── station/module (some — those with control posts)
ActionPurpose
<create_order>Add an order to the order queue
<cancel_order>Cancel a specific order
<cancel_all_orders>Clear the entire order queue
<set_default_order>Set the default order
<set_assignment>Set this controllable’s assignment under commander
<assign_control_entity>Assign an entity to a control post
<release_control_entity>Release an entity from a control post
<add_to_group>Add this controllable to a subordinate group

Controllable is one of the most-used engine classes — modders interact with it constantly via ships and station-control-posts. The order queue and fleet hierarchy are the central modeling concepts.