Space Engineers

Space Engineers

120 ratings
Control Module - Mod Configuring Guide
By Digi
A guide for players on how to use my Control Module mod.
   
Award
Favorite
Favorited
Unfavorite
Using the mod
Open the terminal and look at the panel for a PB or timer block, scroll down to see the mods' UI controls.


The buttons and sliders are explained in the tooltips.


Controlling the blocks
To be able to control the block with the specified inputs you'll need to be in a cockpit, passenger seat or controlling the ship via remote control block.

The PB/timer and the cockpit need to be in the same control panel list to be controllable and the player sitting in the cockpit needs to be able to access the timer/PB to be able to control it (should not say "(ACCESS DENIED)" in the control panel list).

Your game controls won't be overwritten by this mod, if you use forward you'll go forward and trigger the timer/PB.
Using it with in-game scripts
You can get more advanced stuff by using a PB script to read inputs, especially useful with analog ones.

If you don't know how to use the PB you can skip this guide section and have a look at the practical examples, even ones involving PB since it's just copy pasting :P


To get the list of pressed keys and analog values use:
var inputs = Me.GetValue<IReadOnlyDictionary<string, object>>("ControlModule.Inputs");
Alternatively, you can handle the mod missing better by showing an explicit error or make the mod optional.
var inputs = Me.GetProperty("ControlModule.Inputs")?.As<IReadOnlyDictionary<string, object>>()?.GetValue(Me); if(inputs == null) throw new Exception("Control Module mod not found!");
Both ways give the same variable type.

This dictionary will only contain keys that are pressed but analog inputs are always present.
It will also only contain inputs that are defined in the PB's control panel and the dictionary will only update when they're pressed.

Then you can simply check if a key/button/control is pressed by checking if it's in that list:

if(inputs.ContainsKey("internal name here")) { // ... }

To find the internal name either hover the input in the list or type /cm help in chat.

To get analog values you can just access them directly:
var result = (TypeHere)inputs["internal name here"];

But you can always make sure it exists by first checking
inputs.ContainsKey("internal name here")
if you want to handle errors better, like people removing inputs or not adding them properly for your script.

The inputs that are analog and have values are of the following type:
  • Vector3: "m.analog", "c.view", "c.movement"
  • Vector2: "g.lsanalog", "g.rsanalog"
  • float: "m.x", "m.y", "m.scroll", "g.ltanalog", "g.rtanalog"
Everything else either exists or does not exist in the dictionary depending on press status, use with ContainsKey().

Examples:
var mouse = (Vector3)inputs["m.analog"]; Echo("Mouse: X="+mouse.X+", Y="+mouse.Y+", scroll="+mouse.Z); var rightStick = (Vector2)inputs["g.rsanalog"]; Echo("Right stick: X="+rightStick.X+", Y="+rightStick.Y); var xAxis = (float)inputs["m.x"]; Echo("Mouse X axis = "+xAxis);

For working examples, see below in the practical examples section.

In case you can't remember the inputs getting method, you can just load this base script ingame: Control Module - Base Script.
Configuring it with in-game scripts (properties)
You can also set/get the terminal controls added by this mod within a PB script.

First get the block, either use "Me" to get the PB running or search for the PB or timer block that starts with the name you want (because of the storage being in the name you can't guarantee an exact name match).
var slider = Me.GetValue<float>("property name here");
// global vars const string blockPrefix = "Your PB prefix here"; List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>(); // in a method GridTerminalSystem.GetBlocksOfType<IMyProgrammableBlock>(blocks, (b) => b.CustomName.StartsWith(blockPrefix)); var pb = (blocks.Count > 0 ? blocks[0] as IMyProgrammableBlock : null); if(pb == null) { Echo("Can't find block: "+blockPrefix); return; } var slider = pb.GetValue<float>("property name here");

Property names and types:
  • Add input to the monitored list
    ControlModule.AddInput is type string
    Set only, use "all" for the all special input.

  • Remove input from the monitored list
    ControlModule.RemoveInput is type string
    Set only, use "all" to clear inputs.

  • Get all possible inputs and their types
    ControlModule.AllPossibleInputs is type ImmutableDictionary<string, Type>
    Get only, use ContainsKey() for fast check, values can be null if the value is null in ControlModule.Inputs.

  • Get the monitored list
    ControlModule.MonitoredInputs is type ImmutableArray<string>
    Get only, check array.Length == 1 && array[0] == "all"[/b] for the special all-inputs case.

  • Multiple inputs check
    ControlModule.InputCheck is type int; values:
    0 = Any of the inputs
    1 = All combined inputs

  • Trigger on state
    ControlModule.InputState is type int; values:
    0 = Pressed
    1 = Pressed and Released
    2 = Released

  • Hold delay
    ControlModule.HoldDelay is type float

  • Repeat delay
    ControlModule.RepeatDelay is type float

  • Release delay
    ControlModule.ReleaseDelay is type float

  • Cockpit name filter
    ControlModule.CockpitFilter is type string

  • Run on input
    ControlModule.RunOnInput is type bool
    Does not exist on timer blocks.

  • Monitor inputs in menus
    ControlModule.MonitorInMenus is type bool

  • Show behavior on HUD
    ControlModule.Debug is type bool

  • Pressed inputs
    ControlModule.Inputs is type IReadOnlyDictionary<string, object> (read-only)
    This is the internal dictionary filled with pressed inputs, which means you only need to get the reference once.

Some examples:
Me.SetValue<string>("ControlModule.AddInput", "c.forward"); Me.SetValue<string>("ControlModule.AddInput", "w"); Me.SetValue<string>("ControlModule.AddInput", "abcdef"); // invalid, throws exception Me.SetValue<string>("ControlModule.AddInput", "all"); // adds the "Special: all inputs"
Me.SetValue<string>("ControlModule.RemoveInput", "c.forward"); Me.SetValue<string>("ControlModule.RemoveInput", "abcdef"); // invalid, throws exception Me.SetValue<string>("ControlModule.RemoveInput", "all"); // clears inputs
Me.SetValueBool("ControlModule.Debug", true);
Me.SetValueFloat("ControlModule.RepeatDelay", 0.5f);
if(Me.GetValue<int>("ControlModule.InputState") == 2) { // PB is set to trigger on release }
var allInputs = Me.GetValue<ImmutableDictionary<string, Type>>("ControlModule.AllPossibleInputs"); if(allInputs.ContainsKey("c.forward")) { Echo("c.forward is valid!"); }
var monitored = Me.GetValue<ImmutableArray<string>>("ControlModule.MonitoredInputs"); if(monitored.Length == 1 && monitored[0] == "all") { // special case, all inputs } else { foreach(var input in monitored) { // ... } }
Practical examples
  • Using mouse scroll to adjust a piston height
    1. You'll need: 3 timers, a piston, a cockpit and power
    2. Timer 1's actions: Piston ON and Piston Extend
    3. Timer 1's inputs to "Mouse: Scroll Up"
    4. Timer 2's actions: Piston ON and Piston Retract
    5. Timer 2's name: "Mouse: Scroll Down"
    6. Timer 3's actions: Piston OFF
    7. Timer 3's inputs to "Mouse: Scroll (analog)" and "Delay release trigger" to 0.25.

  • Mouse controlled turret
    1. You'll need 2 rotors (or 1 rotor and 1 hinge), programmable block, cockpit, power and gun/camera/whatever to put on the turret.
    2. Place one rotor pointing up and the other rotor on that rotor but on its side (screenshot example).
    3. Name the first rotor "Rotor Horizontal" and the second rotor/hinge "Rotor Vertical".
    4. Place the PB and paste this code in it: http://pastebin.com/raw/z4gdaiGK
    5. Set up PB with inputs: "Mouse: X,Y,Scroll (analog)" and "Mouse: Right Click".
    6. Set PB's Trigger on State to "Pressed and Released" and Repeat Interval to 0.016.
    7. Place the cockpit, get in and hold right mouse button when you want to control the turret with the mouse.

  • Signal lights when steering left/right
    1. You'll need a car with suspension wheels, 2 timers and 2 lights.
    2. Make the lights blink then turn them off. Maybe also make them yellow/orange.
    3. Set Timer 1's actions: Light Left - ON/OFF
    4. Set Timer 2's actions: Light Right - ON/OFF
    5. Add to Timer 1's inputs: "Control: Strafe Left" and to Timer 2's inputs add "Control: Strafe Right".
    6. To both timers set Trigger on State to "Pressed and Released" and Delay Release Trigger to 0.1.
Blueprint Examples
  • Tank Example
    This blueprint is of a basic tank prefab that's clearly not ready for combat since it's quite open, that's to allow further customization.

    It shows how you can control a rotor-wheel tank with movement keys and using a rotor-based turret which you must hold "secondary mode" (usually right click) to move with the turret with the mouse.

    The blueprint: https://steamhost.cn/steamcommunity_com/sharedfiles/filedetails/?id=657975093
Chat commands
  • /cm help
    Shows all inputs (keys, mouse buttons/axes, gamepad butons/axes and game controls).
  • /cm showinput
    Toggles printing in the HUD the inputs you're currently pressing, very useful for quickly finding the name of something specific.
  • /cm updatetype
    Testing command, this changes how the code executes internally, before or after simulation. By default it's set to before simulation and I left it there for people to experiment. Please try it and let me know if input feels laggy with before or after sim.
About comments
Please keep comments only about the guide. If you have anything to say about the mod then say it on the mod page.
60 Comments
Digi  [author] 11 Aug, 2023 @ 6:45pm 
You can just use block.GetProperties() to see all available terminal props :P
But since I looked it up, it's "ControlModule.MonitorInMenus" of bool type.
Stoner Jezus 11 Aug, 2023 @ 7:28am 
@Digi
Is there any setting to enable the "monitor inputs in menu's" from within the code?
cant seem to find it in the documentation (here)
M.A.G.Gen. 25 Feb, 2022 @ 3:11am 
Is that posible to override them? Can you advice me a mod that has this function?
M.A.G.Gen. 25 Feb, 2022 @ 3:07am 
How can I disable ingame controls? I mean when I press k on keyboard - I don't want my terminal open, I want that only Control Module will react on k press while character sitting in cokpit. Is that posible to disable game k reaction by skript or something?
NicoBlast 28 Nov, 2019 @ 4:14am 
not sure what i am doing, your mod is the first script i have looked at and i can't seem to get the tank to work. any help?
LonelyGuardsmen 5 Aug, 2018 @ 6:46pm 
good sir, when using the script for the mouse controlled turret i am getting an error with the code.

Digi  [author] 28 Apr, 2017 @ 1:34pm 
You can ask the author of said script to include support for this mod. It can be completely optional so it doesn't harm users without the mod.
AnsontheToad 28 Apr, 2017 @ 12:03pm 
Has anyone wrote a script for this to work with Jump Distance Dialer https://steamhost.cn/steamcommunity_com/sharedfiles/filedetails/?id=484233284&searchtext=jump+dialer

I'd like to be able to use the number pad to dial in the jump drive distance instead of having to use 13 different hotbar actions. I don't know coding well and I am having a hard time understanding.
PrimOak6 16 Mar, 2017 @ 4:15pm 
@Digi can i use this to zoom out and in 3rd person? For some reason I can do it by holding Ctrl and using my mouse wheel so if I could. That would be great.
Akatosh 21 Feb, 2017 @ 1:43am 
This sounds really cool , but it would be awesome if there was a video guide or sth for those who don't understand this guide.