Space Engineers

Space Engineers

AutoPillock - universal flight automaton [SUPERSEDED]
 This topic has been pinned, so it's probably important
cheerkin  [developer] 13 Dec, 2022 @ 6:49am
User guide
Terms
  • PB - programmable block.
  • APck - AutoPillock script, PB that runs AutoPillock script.
  • Command - a script argument. It can be several types - toggle, command, etc, but I would refer it as just command.
  • Boot Sequence - commands placed into APck PB CustomData. They are ran immediately on recompile/recycle.
  • Recycle - the result of running command:recycle on APck. Almost similar to recompile, it resets state, clears tasks, re-executes Boot Sequence.
  • Unit or Agent - a single logical instance of APckUnit that has its' own blocks, task queue, weapons, etc. In other words, its a minimal usable unit. One physical APck can run many Units via SubUnit feature.
  • SubUnit - a Unit that is not primary for a given APck instance. They are created dynamically by the main Unit and can be added any time as long as their required blocks exist on the grid.
  • Parent or TG.Parent - a unit that is the leader of TacticalGraph formation in which said unit happened to be.
  • Child or TG.Child or Subordinate - a TacticalGraph subordinate of said unit, in other words, unit that is suitable to formation task.
  • STQ, Saved Task Queue - permanently PB-stored task sequence that can be executed on demand.

Intro

The APck can react to several things. The main way of influencing its' operation from a user point is running commands.

Boot Sequence

Commands can be placed into APck PB CustomData. They are ran immediately on recompile/recycle. A good way to getting familiar with APck is to look into CustomData of an existing build.
After you change Boot Sequence, you should recompile or recycle, if you want the new behavior immediately.
Commands can be 'commented out' by placing leading '//'. I often do that to not have typing commands when I want to alter behavior. I just comment out one line and uncomment alternative one.

The most obvious example:
//command:set-response:Attack command:set-response:FreeFire

Commands batching

You can issue many commands with one arg using this convention: [cmd1],[cmd2]...[cmdN]. As usual, this means direct argument pass, placing a line in Bood Sequence, using TreeMenuCommand, or making a toolbar action.

Commands routing

Any command can have filtering and routing prefix (first part when split by ':').
Example: bc<heavy bomber>:command:create-task:attack

Filtering prefix can be:
- tag, wrapped in (<>). It would try to match the Units' tag. Unit tag can be set in APck PB name wrapped in ([]). E.g. name: a-core [tag=heavy bomber-1]. If it gets command with <heavy bomber> prefix, it would match, but would not match <heavy bomber-5>
- index. A number wrapped in ([]), zero-based. This is used only for a Unit that has SubUnits or Subordinates to route a command to a index-based unit. E.g. 'su[0]:command:create-task:attack', 'w[3]:command:create-task:attack'

Routing prefix can be:

bc - pass command to everybody in antenna range, exept myself. Can use tag filter. To include this unit use command batch. E.g. '[command:cmd1],[bc:command:cmd1]'.
w - pass command to wingmen (subordinates). Can use index and tag filter.
su - pass command to SubUnit. Can use index and tag filter.
p - pass command to Parent. Can use tag.




Formations, subordination (TacticalGraph)

Units can be orhanized into tree-like structure, where each unit can have only one parent, but a parent can have many children.
Connection is based on "rank" system and constrained by range. On start, after recycle or recompile, TacticalGraph listens to other units for a few seconds, and then chooses a unit that has [rank-1] and is closer than [D]. If successful, the unit marks that one as a Parent, and tells the Parent to mark him as a Child.
That means, if you recompile the Parent, the link with all subordinates is broken. If you recompile or add a new unit intended to be a Child, then the link would be set up as long as conditions are met. In other words, the link is child-initiated.
To set a rank, add [rank=X] in the APck PB CustomName.
To change [D], which is 500m by default, run command:set-value:tg-autolink-range:X (by this moment you should guess that it needs to be done on Child unit rather than formation leader).

Example:
Two big ships that have rank 10 and rank 50, five small ships with rank 11 and five with 51. After TG resolve, two big ships would have 5 suborditates each.
Two big ships that have rank 10, ten small ships with rank 11. After TG resolve, if all ships are within 500 range, one big ship would have all 10 subordinates. If they are spaced out (500+ m between groups), then they can link to their nearby parent big ship. With this approcah, it is possible to have big ships as children for a rank-9 ship.

This is not very convenient way for subordination deeper that 1 level. I have ideas to rework TacticalGraph, but for now it stays like this.




Captain module.

This is the module that handles tasks, target awareness and responce. It gives move/aim assignment to Pilot module.

It has a few special properties that user can ineract with.

TargetId - a global id of friendly or detected/tracked hostile target. It is used during creation of tasks that require target (attack, dock, follow, etc). To get it, use command:pick-target. Picking a friendly target id also can set TMC context for that target so you could issue TMC commands remotely.

StaticPos - a world position for simple tasks like landing or attacking point. It can be set from GPS (command:read-gps-from), direct raycast (command:raycast-pt) and from look direction using current Range (command:range-pt, command:rangefind)

Awareness - What target sources to consider for reaction (response) purposes. TurretAi - local AI turrets, Global - global datalink, TGP - local TGP script, Full - everything.

Response Kind - How to respond when aware of enemy. FreeFire - don't stop doing current task or sitting idle, but shoot enemy when it is in range, also use PMWs when available. Attack - immediately inject Attack task and actively engage.

Response Override - Command to execute instead of Attack task injection. By default, if Response Kind is Attack, the Cap injects Attack task. This is not suitable for certain builds like missiles. You can override it with appropriate command, usually placed in Boot Sequence. You can place {id} placeholder to have it replaced with current target id by the WeapBot. Example for missile: 'command:set-response-ovr:command:inject-task:ram:TargetId={id}'.

Timer triggers - you can add timer following naming convention: {task kind}.OnStart, {task kind}.OnComplete. Taks kind is the thing you see in the log along with id, like move-11, attack-2 or landing-69. You don't use the id, just the first part before '-'.
So, if you want to trigger a timer when you finish docking, you can add a timer 'Timer Whatever landing.OnComplete'.
For Ram task (missile behavior), there is a flexible proximity timer feature.
You can add timer tagged 'proximity100' to have it triggered 100m before impact, 'proximity511' - closer than 511, etc, and you can have as many of them as you can fit on the missile.

InferTask - you can create task by using current position. Supported tasks: move, dock, land. Add wait-for-signal tast beforehand, or this new task would be immediately completed. For dock, you need to be connected to connector. For land - resting with landing gear on the surface. The script would record matrices of gear/connector and create appropriate task. It can be later re-used from exec-queue, by repeat order, etc.

Default task - you can have permanently set default task to be added every time the task queue gets empty. This task auto-completes when Cap gets any other new task, and adds istelf back again as soon as all tasks are finished.

Saved Task Queue - permanently save current task buffer (task history starting from the last wait-for-signal) for later use. Typical case: you want to make shuttle to go between docks. Start by making a wait for signal task to stop the unit from immediate action (command:create-task:wait-for-signal). Then add up tasks however you want. You can fly the actual unit and use InferTask to create tasks. Then you add repeat command at the end using TaskExecute (command:create-task:exec:FollowUp=command;repeat). At this point you can store the queue (command:save-queue). After recompile or copying the unit you can use command:exec-queue any time, or have it placed in Boot Sequence.




Pilot module

It provides grid movement and rotation using own hardware or by delegating this task to external scripts like ThrustProvider.

The vanilla dampening should be off. By default, the Pilot dampens inertia, you can switch that using toggle:damp-when-idle.

It always cancels out gravity, so if you want 'zero-g flight' on planet you can turn dampening off with 'toggle:damp-when-idle:true'.

Sometimes you want the APck to stop touching thrust or gyro override, you can switch that using 'toggle:suppress-transition-control' and 'toggle:suppress-gyro-control'.

APck can have different thruster set-ups. The most common is '3dThrust' - when you have at least one thruster in each direction, or at least 3 grav gens, in other words, when the grid can move in any direction without having to rotate. Then it can have single thrust set-up that heavily limits the number of compatible tasks, it is mostly used for compact missiles. In this set-up the Pilot ignores Aim behaviors and rotates to fulfill movement assignment. And finally, it can have ThrustDelegation, when APck assumes that external script has all means of moving the grid. In this mode it passes move assignment to external script (move point, target velocity, own velocity, speed limit, etc). In this mode Cap can work in 'hybrid-mode' (toggle:vtol-hybrid) when the external script passes back the Force vector it applied, so the Pilot would still use its' thrusters tp assist.




WeapBot module

WeapBot aims and uses weapons and controls desiged combat distance based on installed weapons and setting. It also runs condition-based triggers during combat.

Settings

1. PMW_FF_REACTION_R - top of the code. Changes the distance for threat reaction when an agent has PMWs like sub-units or dumb-units (default is 2500).

2. Set-values and toggles. See script argument reference for more info on those settings:

wb-range-override
wb-precision-override
wb-model-cycle-timeout
ripple-increment-interval
torpedo-fuse-offset
wb-snipe-range

Combat range

If there is a designator turret, then short-range distance is set to 550/700m, depending on grid size.
If there are player-made weapons (sub-unit, dumb-unit), then long-range is set to PMW_FF_REACTION_R.

Otherwise, short/long range is chosen from a weapon with the shortest/longest range available.

If wb-snipe-range toggle is set to true, then resulting combat range would be the long-range value minus 50m.
Otherwise, CR would be the short-range value minus 50m.

Finally, if the wb-range-override is set to non-zero value, CR would be set to that value, no matter what weapons/turrets/PMWs are available.

WeaponFaces

Weapons are organized into WeaponFaces, one per grid direction, so up to 6 is possible. E.g. you can have guns pointing forward and left, so there would be two WeaponFaces.
WeaponFace contains 1+ WeaponGroups, they represent different types of weapons. WeapBot switches weapon groups automatically, based on weapon cooldown rate. It wouldn't switch faces on its' own yet, so you need to tell it explicitly to do so:
command:wb-cycle-face

You can automate it using WeapBot conditional commands.

Combat conditional commands

During explicit attack task, or tasks injected as threat response, WeapBot can run condition checks and trigger commands if they success (every 5th second).

You can add those using 'command:wb-condition'.
Args: 1: comma-delimited key-value pairs (condition1=xx,condition2=yy), 2: command to be executed if test succeeds

Possible conditions for now:
  • chance - from 0 to 1
  • minSzSG - if the target it small grid check its size (larger than?)
  • minSzLG - if the target it large grid check its size (larger than?)

Example
command:wb-condition:chance=0.2,minSzSG=10:command:wb-range-override:100
- if the target is small grid larger that 10m, set combat range to 100m with 20% chance. Since tests are commited each 5 seconds, we can assume that an agent would go point blank in about half a minute, or if we have five agents attacking, when one of them would go point blank immediately (statistically speaking)

Example
command:wb-condition:chance=1:command:wb-cycle-face
- cycle WeaponFace every 5 seconds to make gun-kata-style drone



Tasks

Additional terms
  • Task - an assignment to do something in a certain way
  • Task Queue - a sequence of Tasks to be executed one by one
  • Kind - task type
  • Attribute - named value that overrides or defines certain aspect of a Task
  • Position - world coordinates of a point, similar to GPS, usually defining a target for a Task
  • OnStart - event that triggers when a Task is initialized and actually started (not created or added)
  • OnComplete - event that triggers when a Task is completed and removed

General format
'command:create-task:{kind}:{attribute-pairs?}:{p.X:p.Y:p.Z?}'

As usual, command parts are separated with ':'.

Task kinds part (required)

orbit
wait
wait-for-signal
exec
cruise-fw
move
move-rel
jab
ram
attack
follow
wingman
dock
cargo
land

Attributes (optional part)

Comma-delimeted key-value pairs. If any value contains ':', it should be escaped (replaced) with ';'.

Example:
command:create-task:attack:Name=slowpoke,TargetId=100500,SpeedLimit=10
Here, we have two attributes set. Attributes part is 'Name=slowpoke,TargetId=100500,SpeedLimit=10'.

TargetId attribute is a special one - if you don't supply it for a task that needs it, then the code would use Captains' TargetId (see above).

Usually attributes are specific to a certain task kind, but there are also uniform ones (which means they can be included in any task creation command):
Name - task name override;
TickLimit - time limit, counting from actual task start (not creation), in ticks. There are 60 ticks in a second, for a default script update rate;
SpeedLimit - max speed, in m/s.

Position coordinates (optional, 3 parts)

Certain tasks require position. It can be set as 3 trailing parts (X, Y, Z). It is similar to keen GPS, so you can get three numbers manually, or by using RTS command script.
Example:
Three parts after attribute-pairs part define the position (X:Y:Z). If you don't supply it for a task that requires it, then the code would use the position from StaticPos (see Captain module above). E.g. if you set StaticPos by raycasting, then you can just 'command:create-task:ram' to have a missile attack that StaticPos.

It's important to remember that task is not necessarily started at the moment it was created using create-task command.

Task kinds

"orbit"
Summary: Creates APckTaskMove with orbit behavior.
Attributes: R - orbit radius, default is 500.
Center point is assumed to be R meters front (at the moment of task creation, not OnStart).
Tip: if you want to queue orbit task, you might want to use Exec kind of task to inject orbit task "in place", so the APck would orbit the actual area (example below).

"wait"
Summary: holds position until signal or until set ticks limit is reached.
Attributes: TickLimit (60 means one second of simulation time).

"wait-for-signal"
Same as above, but also clears task queue buffer (for queue saving purposes).

"exec"
Summary: executes arbitrary command (.OnComplete).
Attributes: FollowUp - full command text, but with ':' replaced by ';' (to not interfere with the wrapping command itself).

Example for 'command:create-task:orbit:R=1000'
command:create-task:exec:FollowUp=command;create-task;orbit;R=1000

Example for repeat command (looping current task buffer starting from the last wait-for-signal task)
command:create-task:exec:FollowUp=command;repeat

"cruise-fw"
Summary: creates infinite task for moving forward, maintaining altitude in case of planet (i.e. can be used for stable planet orbit).

Direction is not fixed at task creation - if you rotate an agent, or it changes direction due to combat interrupt, then it would continue that way.

Remember that you can use TickLimit and SpeedLimit attributes when needed.

"move"
Summary: moves to a Position.

'move-through' value (see arg reference discussion) sets if an agent should break or just rush through a Position point. It takes effect only for tasks to be created, not existing ones. Setting it to false may be useful for missiles, so they won't lose speed during intermediate waypoints when attacking.

"move-rel"
Summary: same as above, but Position is treated like a vector relative to an agent at the moment of task creation.

X is a left-right axis, Y is top-down, Z is forward-backward.

Example for moving 1000m forward
command:create-task:move-rel:0:0:1000

"jab"
Summary: inertial torpedo strike using own acceleration to launch (dumb-unit or sub-unit).
Attributes: TargetId.

If id is not supplied, it is treated as untargeted jab using current forward direction. TargetId should be id of datalink enemy target.

"ram"
Summary: missile attack type with evasion, warhead detonation and proximity timers trigger.
Attributes: TargetId.

If Position/StaticPos is set, then it would ignore TargetId. TargetId should be id of datalink enemy target.

You can add any amount of timers including desired trigger distance in their name. E.g. timer tagged 'proximity100' to have it triggered 100m before impact, 'proximity511' - closer than 511, etc.

This task supports single-direction thrust set-up.

"attack"
Summary: force attack using fixed weapons, test combat conditions, etc, with evasion movement behavior. Similar to threat response, but for specific target or Position.
Attributes: TargetId.

If Position/StaticPos is set, then it would ignore TargetId. TargetId should be id of datalink enemy target.

"follow"
Summary: infinite task for maintaining relative position, given a friendly APck id, or just following sensor-detected player.
Attributes: TargetId.

TargetId should be id of friendly APck grid. If no TargetId is provided, tries to use sensor block named 'sensor-apck'.
The relative position is captured at the moment of task initialization (OnStart).

"wingman"
Summary: infinite task for following TG.Parent, using assigned formation position.

"dock"
Summary: docking to a friendly APck grid or to known connector position/normal.
Attributes: TargetId, AimNormal.

TargetId should be id of friendly APck grid. If no TargetId is provided, it tries to use Position and AimNormal attribute.
AimNormal attribute is 3-part vector that matches known static connector direction. It is used to match static connector orientation, and Position is used to reach said connector.
Both values are better created using InferTask feature (see above). Then you can store inferred task, or see PB log to get the task string.

"cargo"
Summary: tries to store/retreive cargo to match specified order.
Attributes: [varying]

Desired item amount is set in a way similar to attribute-pairs. Key is item tag (Ore, Iron, Ingot, etc), value is amount.
An agent would attempt to exchange cargo until it has amounts matching the order.
An agent won't proceed with next tasks until all desired item amount entries are satisfied. Cargo items which do not match are ignored.

Example for loading 2000 units of ore combined
command:create-task:cargo:Ore=2000

Example for unloading all ore and steel plates
command:create-task:cargo:Name=unload,Ore=0,SteelPlate=0

To make cargo shuttle, create a queue like 'move-dock-cargo-move-move-dock-cargo-exec(repeat command)'. Move command requests undock so as long as cargo task condition is satisfied, an agent would proceed to the next task. See 'Saved Task Queue' above for more info.

"land"
Summary: lands to surface (planet, asteroid, ship, etc) using designated landing gear.
Attributes: AimNormal.

Needs Position. AimNormal attribute is optionally supplied to match the surface.
Both values are better created using InferTask feature (see above). Then you can store inferred task, or see PB log to get the task string.

If nothing is provided, and used near planet, the code would attempt to land using gravity to align, and altitude data to deduce surface point.
Last edited by cheerkin; 19 May, 2023 @ 5:35am