Space Engineers

Space Engineers

AutoPillock - universal flight automaton [SUPERSEDED]
 This topic has been pinned, so it's probably important
cheerkin  [developer] 10 Dec, 2022 @ 4:46pm
Building guide
Building guidelines

Flight control code supports all types of thrust, including gravity drive.

Preparations
The drone needs so called block-definitions to function. It is a list of block coordinates relative to root block (PB or merge block in case of SubUnit).
If the defs list is empty, the code just grabs all blocks it is interested in from the same construct (grids connected by rotors/hinges but not connectors).
It is like "hidden" group which restricts what blocks this unit is allowed to use.
When you design your drone, you need to run 'command:clear-defs' to refresh and save this list, then to re-initilize core unit.
In other words, build first, then clear defs, then test it.
Some blocks are exception from this rule, for example 'dock-host'-tagged connectors are collected without this filtering.

Required blocks
  • PB for APck core code.
  • Exactly one gyroscope named "forward-gyro". The gyro should look forward, and it would set drone orientation for every task where it matters.
  • At least one remote control .
  • Optional, but for full task compatibility - at least one thruster in each direction. Unless you use external thrust provider script.
  • Optional, but recommended on most builds: antenna with enough broadcasting range.

Optional blocks
  • ShipControllers - seats, cockpits, etc.
  • Landing Gears - for surface LandingTask.
  • Connectors tagged "dock-host" - for units that intend to provide docking services.
  • One connector tagged "docka" - for units that intend to use docking services.
  • Batteries and H2 tanks - those would get switched when docked.
  • Turrets tagged "x-designator" - for AI targeting (without them a drone can rely only on targeting data from friendly ships).
  • Cameras - for several tasks and commands related to raycasting. Mostly useful on carriers or wing commander ships.
  • Warheads - for Ram task detonation.
  • Timers - for even subscription (task-kind.OnStart, task-kind.OnComplete, proximity, etc)
  • Gravity generators and artifical mass blocks - for gravity driving - don't forget to center-of-mass balance them*.
  • Conventional thrusters
  • Merge blocks tagged "sub-unit" and/or "dumb-unit". SubUnits are APck-controlled independent fully functional units, dumb units are PMW munitions for Jab tasks (torpedoes, bombs, etc). Those merges are hardpoints.
*if you want to filter out what grav gens it should use, e.g. you have convenience generator, you can use grid-defs for your advantage by removing the gen, rebuilding defs, and then adding it. If the definition for it is missing, the code won't touch it ever.
Alternatively, you can set GGEN_GR_TAG at the top of the code to make a group that would code look for when searching for gens.

Check out how's it going so far

See the PB screen log to see if there is any errors or missing blocks (when defs and subset numbers don't match).
Take control of the grid using remote or control seat and check if it flies well (it should have dampeners set to OFF, it's the normal operation mode for the APck since it handles dampening on its' own).
Run some simple command like command:orbit-here or command:create-task:cruise-fw. To stop, recompile the script, run command:next or command:recycle.

Weapon set up, basic

Fixed guns should go to a group called "coaxial-weapons". They are def-filtered, so command:clear-defs after you add them. Check out the log to see if they were detected properly.
Guns are grouped into "WeaponFaces" based on their directions (so max 6 is possible), and inside each face they are grouped by their type.
Direction is ~40 degree tolerant, so you can have angled guns on hinges if you feel fancy.

If you add guns so they form more than one WeaponFace, you can cycle face any time using command:wb-cycle-face. You can also add this command as a combat conditional and cycle them automatically based on chance and timeout.

Weapon set up, advanced

Non-standard guns go to groups with [hd-coax] tag. Example:
'heavy dakka [hd-coax][ripple][v=500][r=1000][fwO=2][d=5]'
You must provide v and r tags that define muzzle velocity and range.
d - required precision in meters.
fwO - forward muzzle offset.
[ripple] tag enables ripple fire behavior.

Weapons should support IMyUserControllableGun interface. You can try it with mod weapons, chances are they may support it too. Just add appropriate range and velocity tags.

Alternatively, instead of actual gun you can add timer block to a group. I stress this: add only timers but not guns if you do it this way.
You can add one timer, then the code would enable/disable it. This way is intended for other script indegrations like AWT.
You can add two timers and tag them [fire] and [cease]. The code would trigger appropriate timer when it needs to start or stop firing. You should tag one of them [ref] to be used as bore reference.
Timers (at least the one you tagged [ref]) must face forward, where the "bore" is directed.
This can be used to control various non-conventional weapons like rotor displacement or jolt cannons.

If you want to lower required precision of all guns, run command:set-value:wb-precision-override:N, where N is new precision in meters. I.e. 10 would mean that the code would fire as soon as it is aligned closer than 10m dispersion.
By default, precision weapons (rail and arty) are in ripple mode, aimed individually and have 2m precision, smaller calibers have 5m precision, and rockets have 10m.

Designator turrets

To make use of internal turret AI targeting feature you should add at least one designator turret. It should be tagged "x-designator" and it is grid-def bound, so after adding clear defs.

Start-up sequence and unit tagging

Any command or toggle can be both ran manually or placed into PB CustomData to be executed on recompile/recycle. Treat it like a command queue that is guaranteed to be ran once.

PB can be tagged like this:
a-core [rank=10][tag=ASF]

Rank is needed for formation link. The idea is that all units with rank N connect to a unit with N-1 rank. This way you can have independent leaded groups:
- rank-10 leader with a few rank-11 ships
- rank-33 leader with a few rank-34 ships

Tag is needed if you want to filter commands for specific unit(s).

SubUnit design

If the grid has a merge tagged "sub-base", it is considered a potential SubUnit. It would copy defs inside sub-base CustomData. After that, the PB may be disabled or deleted.
Boot commands sequence should be placed in remote control instead (because we remove the PB).
When sub-unit is ready, you can merge it to a parent unit (attach sub-base to parent sub-unit hardpoint).

WARNING: remember to disconnect SubUnits if you happen to redesign parent unit, or it would greedely grab their blocks too and complain that it found more than one forward-gyro. If you did that, no worries, just unmerge SubUnits and clear-defs on the parent unit again.

sub-unit hardpoint can be tagged [jab], that would mean you want that unit always be released using Jab launch. The carrier would accelerate and throw out SubUnit before activating it.
sub-unit hardpoint can be tagged [tag=my-mega-missile] for later identification.
sub-unit hardpoint can be tagged dumb-unit too, in this case if it happened to be Jab-launched during close combat, the code would see that is is a smart munition and would initialize it with targeting data.
sub-base merge does not accept any tags other than 'sub-base'.

To have SubUnit do something useful after release, you need to populate remote CustomData with start-up sequence. For example:
command:create-task:wait:Ticks=240 command:create-task:move-rel:0:0:-1000 command:set-awareness:Full command:set-value:awareness-range:10000 command:set-response:Attack command:set-response-ovr:command:inject-task:ram:TargetId={id}
This means:
wait for 4 seconds
move 1000m forward relative to the position at the moment of task start
listen to every target channel: internal turret AI, global or local TGP
set response range for 10km
response to nearby enemy with Attack state
replace defaut attack task with ram task (essential for any missile)

Why this way? It works like Lock-On-After-Launch - if there is no target nearby, it would fly in the general direction of launch, and as soon as it happens to be at certain distance from an enemy, it would inject (rather than just add) ram task in the queue.

For using SubUnits, refer to appropriate guide. For now, you can use command:start-su:first, command:start-su:my-mega-missile or command:start-su:all.

To initialize new unit (i.e. if you launched a missile/drone and have welder set up to make them on the fly) just run 'command:refresh-su' as soon as it is build. Or, in case of missile, it would be called automatically when the "previous" missile was destroyed.

Here is my first released example, U-AAG/SU drone, which has two missiles.

Thruster notes

If you have omni-directional thrust, the drone needs enough thrusters to support itself on max load in the highest G environment you want it to operate in, for any orientation.
If this fails, you can get "HC FAIL not enough thrust" error which is fatal and results in script stop with attempt to release control and enable dampeners.

If you want to use ThrustProvider for VTOL or clangdrive, then you can have normal thrusters too, but in case of clangdrive they would shut down when it's active and vice versa. In case of VTOL, hybrid mode is possible when both systems work together.

Timer triggers

You can add timer following naming convention
{task kind}.OnStart
{task kind}.OnComplete
Task kind is the thing you see in the log along with id, like move-11, attack-2 or landing-69. The kind is the part before '-'.
You DON'T include the id into timer tag.
So, if you want to trigger a timer when you finish docking, you can add a timer 'Timer Whatever landing.OnComplete', not 'Timer Whatever landing-55.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.

Carrier

What makes a unit a carrier? At least one connector tagged 'dock-host'.
And, preferably, formation subordinates (see rank tag explanation above).
You can also create a navigation graph for pathfinding if you make a closed carrier. Video guide here:
https://www.youtube.com/watch?v=IwhWJ7GYP4M
Last edited by cheerkin; 2 Feb, 2023 @ 8:36am