Introduction

Information

It's a small addon for the SComputers mod [FORK] in Scrap Mechanic game, which will allow you to implement any mechanisms using programmable controllers that allow you to change the rotation angles of each bearing, and even the length of the connected pistons!

Components

DayLightSensor

The DayLightSensor can be used to automate energy-saving systems and enhance security measures in structures. For instance, it enables the construction of buildings that only consume energy during daylight hours, optimizing the use of resources. Additionally, it can be integrated into automated lighting systems, ensuring lights are only activated when necessary.

Method and args Method description First appearance
DayLightSensor.isSkyNotObstructed():boolean Checks if the sky is not obstructed for the sensor. Returns true if the sensor has a clear view of the sky, false otherwise. This method is crucial for outdoor applications where the sensor's performance might be affected by physical obstructions like buildings or trees. v1.0
DayLightSensor.isDay():boolean Determines if the sensor perceives the current time as day. Returns true during daylight hours, based on the game world's day-night cycle. This can be used to activate or deactivate machines and systems during the day. v1.0
DayLightSensor.isNight():boolean Determines if the sensor perceives the current time as night. Returns true during nighttime hours, according to the game world's day-night cycle. This function can be particularly useful for activating lighting systems or triggering events that should only occur at night. v1.0

Config

There are no configurable settings for the DayLightSensor component as its functionality is solely based on environmental conditions. However, users can combine its outputs with other logic components to create complex behaviors in their creations.

Note: The effectiveness of the DayLightSensor depends on its placement in the game world. Ensure it is placed in an area where its view of the sky is unobstructed for accurate readings.

Using

Simple example (2 connected bearings, and 2 connected pistons)
    
sensor = getComponents("dayLightSensor")[1]
if controller == nil then return end

-- Checking
if sensor.isSkyNotObstructed() then
    print(sensor.isNight())
else
    print("Sky is obstructed!")
end

ScriptableController

The ScriptableController is a versatile component in Scrap Mechanic that enables the automation and dynamic control of machinery and robotic constructs. It can precisely manipulate the rotation of bearings and the extension of pistons, allowing for the creation of complex, articulated structures and mechanisms. From simple automated doors to intricate transforming robots, the ScriptableController serves as the brain behind many inventive creations within the game.

Method and args Method description First appearance
ScriptableController.setActive(state:boolean) Initiates or halts the operation of the controller. It returns true irrespective of the controller's current resource availability. To accurately determine the controller's operational state or resource availability, use: ScriptableController.isActive(). v1.0
ScriptableController.isActive():boolean Reveals whether the controller is currently activated. This status check is crucial for troubleshooting and synchronizing multiple controllers within larger systems, ensuring coordinated operations. v1.0
ScriptableController.isWorkAvailable():boolean Indicates the presence of necessary resources (e.g., fuel, batteries) for the controller to function. This method is vital for managing energy-efficient designs and ensuring machines operate only when they have adequate resources. v1.0
ScriptableController.getAvailableBatteries():number Reports the quantity of batteries available for the controller's operations. This information is key for power management and planning the deployment of battery-dependent devices. v1.0
SmartController.getCharge():number Retrieves the current charge level of the controller. v1.0
SmartController.getChargeDelta():number Returns the rate at which the charge is changing. v1.0
SmartController.getChargeAdditions():number Fetches additional charge-related parameters relevant to the controller. v1.0
ScriptableController.getSoundType():number Retrieves the type of sound effect associated with the controller. v1.0
ScriptableController.setSoundType(number) Sets the sound type for the controller, influencing the audio feedback of mechanical actions. v1.0
ScriptableController.getVelocity():number Retrieves the current velocity at which the controller manipulates bearings. This is critical for tuning the speed of mechanical movements to match the desired pace of actions in machines and robots. v1.0
ScriptableController.setVelocity(number) Adjusts the velocity of bearing rotations. By fine-tuning this setting, creators can achieve precise control over the speed of mechanical parts, enhancing the performance of their constructs. v1.0
ScriptableController.getStrength():number Returns the force applied by the controller on the bearings. This parameter is essential for ensuring that mechanical movements have sufficient power. v1.0
ScriptableController.setStrength(number) Sets the strength of the controller's actions on bearings, allowing for the adjustment of force to match the requirements of various mechanical applications. v1.0
ScriptableController.getBearingsCount():number Counts the bearings linked to the controller, aiding in the management and debugging of complex constructs by providing a quick inventory of controlled bearings. v1.0
ScriptableController.getAllBearingsAngle():table Produces a table detailing the current angular positions of all bearings. This is invaluable for diagnostics and synchronization tasks, offering a comprehensive overview of the mechanical state. v1.0
ScriptableController.getBearingAngle(id:number) Retrieves the angle of a specific bearing, allowing for precise monitoring and adjustments to individual components within a mechanism. v1.0
ScriptableController.setBearingAngle(id:number, angle:number) Sets a particular bearing's rotation angle. This method is fundamental for creating dynamic and responsive movements within mechanical constructs. v1.0
ScriptableController.resetAllBearingsAngle() Reverts all bearings to their original angular positions. This function is useful for resetting mechanisms to a known state before initiating a sequence of operations. v1.0
ScriptableController.getPistonsCount():number Determines the number of pistons connected to the controller. This aids in the configuration and troubleshooting of piston-operated elements within creations. v1.0
ScriptableController.getAllPistonsLength():table Provides a table with the current extension lengths of all pistons. This feature is crucial for assessing and coordinating the movements of multiple pistons in complex systems. v1.0
ScriptableController.getPistonLength(id:number) Returns the extension length of a specific piston, offering precise control over individual piston adjustments for tailored mechanical actions. v1.0
ScriptableController.setPistonLength(id:number, length:number) Adjusts the length of a piston, enabling the customization of piston-driven movements to suit various engineering and design needs. v1.0
ScriptableController.resetAllPistonsLength() Resets all pistons to their initial lengths. This function is useful for ensuring that mechanical systems start from a consistent baseline for each operation cycle. v1.0

Using

Below is a simple example showcasing the setup and basic operation of two connected bearings and pistons using the scriptableController:

    
controller = getComponents("scriptableController")[1]
if controller == nil then return end

-- Configuring
controller.setVelocity(30)
controller.setStrength(30)
controller.setActive(true)

-- Bearings
controller.setBearingAngle(1, math.rad(math.random(140, 160)))
controller.setBearingAngle(2, math.rad(220))

-- Pistons
controller.setPistonLength(1, 4)
controller.setPistonLength(2, 10)

print()
print("Bearing index 1 angle in degrees: " .. math.deg(controller.getBearingAngle(1)))
print("Bearings count: " .. controller.getBearingsCount() .. "; Pistons count: " .. controller.getPistonsCount())
    

SmartController

The SmartController is an advanced control unit in Scrap Mechanic designed for creating intricate movement sequences for pistons and bearings. By defining a program inside it, users can orchestrate precise mechanical actions, making it ideal for automated robotic constructs, complex doors, and synchronized mechanical systems.

Method and args Method description First appearance
SmartController.start(program:table) Initiates the execution of a predefined movement sequence. The program parameter must be a dictionary defining the logic of movement. If a stage in the program does not include a delays field, the default delay of {1, 1} is applied. v1.0
SmartController.stop() Reverses the current operation of the controller, causing all active movements to run in the opposite direction. To completely stop the controller, use code SmartController.setActive(false). v1.0
SmartController.isActive():boolean Returns whether the controller is currently active, allowing for checks in automated systems. v1.0
SmartController.setActive(state:boolean|number) Enables or disables the controller. Accepts either a boolean value or a number (where non-zero values are interpreted as true). v1.0
SmartController.isWorkAvailable():boolean Checks whether the controller has the necessary power (e.g., energy or batteries) to function. v1.0
SmartController.getAvailableBatteries():number Returns the number of available batteries. In creative mode, this always returns an infinite value. v1.0
SmartController.getCharge():number Retrieves the current charge level of the controller. v1.0
SmartController.getChargeDelta():number Returns the rate at which the charge is changing. v1.0
SmartController.getChargeAdditions():number Fetches additional charge-related parameters relevant to the controller. v1.0
SmartController.getVelocity():number Retrieves the master velocity at which the controller operates. v1.0
SmartController.setVelocity(value:number) Sets the master velocity. The value is clamped between -maxMasterVelocity and maxMasterVelocity to ensure controlled speed regulation. v1.0
SmartController.getStrength():number Returns the maximum impulse force exerted by the controller. v1.0
SmartController.setStrength(value:number) Adjusts the impulse strength, ensuring movements are executed with the appropriate force. Values are clamped between 0 and mImpulse. v1.0
SmartController.getBearingsCount():number Returns the number of bearings currently controlled by the SmartController. v1.0
SmartController.getPistonsCount():number Returns the number of pistons currently connected to the controller. v1.0
SmartController.getSoundType():number Retrieves the type of sound effect associated with the controller. v1.0
SmartController.setSoundType(value:number) Sets the sound type for the controller, influencing the audio feedback of mechanical actions. v1.0

Using

Example 1: Smart Controller - Simple Program

Below is a example demonstrating how to configure and start a simple movement sequence using SmartController:

Good practice:
    
controller = getComponents("smartController")[1]
if controller == nil then return end

-- Configuring
controller.setVelocity(20)
controller.setStrength(1000)
controller.setSoundType(0)
controller.setActive(true)

function onStart()
    -- Execute the program (direct order)
    controller.start({
        -- Stages (step-by-step)
        [1] = { -- Synchronized actions
            ["pistons"] = {
                -- [pistonIndex] = {lengthBefore, lengthAfter}
                [{1,25}] = {1, 4}  -- Short notation (1-25 indexes pistons)
            },
            ["bearings"] = {
                -- [bearingIndex] = {degreeBefore, degreeAfter}
                [1] = {0, 90}
            }
        },
        [2] = {
            ["pistons"] = {
                [{1,25}] = {4, 1}
            },
            ["bearings"] = {
                [1] = {90, 0},
            },

            -- Delays when [onDirectDelay, onReverseDelay] (start/stop delays)
            -- If a stage in the program does not include a ["delays"] field, the default delay of {1, 1} is applied.
            ["delays"] = {2, 2}
        }
    })
end

function onStop()
    -- Execute the program (reversed order)
    controller.stop()
end

_enableCallbacks = true
    
B A D practice:
    
controller = getComponents("smartController")[1]

controller.setVelocity(20)
controller.setStrength(10000)
controller.setSoundType(0)
controller.setActive(true)

function onStart()
    controller.start({
        [1] = {
            ["pistons"] = {
                [1] = {1, 4}, -- Very long and not optimized!
                [2] = {1, 4},
                [3] = {1, 4},
                [4] = {1, 4},
                [5] = {1, 4},
                [6] = {1, 4},
                [7] = {1, 4},
                [8] = {1, 4},
                [9] = {1, 4},
                [10] = {1, 4},
                [11] = {1, 4},
                [12] = {1, 4},
                [13] = {1, 4},
                [14] = {1, 4},
                [15] = {1, 4},
                [16] = {1, 4},
                [17] = {1, 4},
                [18] = {1, 4},
                [19] = {1, 4},
                [20] = {1, 4},
                [21] = {1, 4},
                [22] = {1, 4},
                [23] = {1, 4},
                [24] = {1, 4}
                [25] = {1, 4}
            },
            ["bearings"] = {
                [1] = {0, 90}
            }
        },
        [2] = {
            ["pistons"] = {
                [1] = {4, 1},
                [2] = {4, 1},
                [3] = {4, 1},
                [4] = {4, 1},
                [5] = {4, 1},
                [6] = {4, 1},
                [7] = {4, 1},
                [8] = {4, 1},
                [9] = {4, 1},
                [10] = {4, 1},
                [11] = {4, 1},
                [12] = {4, 1},
                [13] = {4, 1},
                [14] = {4, 1},
                [15] = {4, 1},
                [16] = {4, 1},
                [17] = {4, 1},
                [18] = {4, 1},
                [19] = {4, 1},
                [20] = {4, 1},
                [21] = {4, 1},
                [22] = {4, 1},
                [23] = {4, 1},
                [24] = {4, 1}
                [25] = {4, 1}
            },
            ["bearings"] = {
                [1] = {90, 0},
            },

            ["delays"] = {2, 2}
        }
})
end

function onStop()
    controller.stop()
end

_enableCallbacks = true
    
Example 2: Smart Controller - Various Program Configurations

A code example showcasing various possible program configurations:

                
controller = getComponents("smartController")[1]
if controller == nil then return end

-- Configuring
controller.setVelocity(20)
controller.setStrength(1000)
controller.setSoundType(0)
controller.setActive(true)

function onStart()
    -- Execute the program (direct order)
    controller.start({
        -- Stages (step-by-step)
        [1] = { -- Synchronized actions
            ["pistons"] = {
                -- [pistonIndex] = {lengthBefore, lengthAfter}
                [3] = {1, 7}, -- Maybe we should change it to a short notation? The example is below :D
                [4] = {1, 7}
            },
            ["bearings"] = {
                -- [bearingIndex] = {degreeBefore, degreeAfter}
                [{1,2}] = {90, 90} -- Short notation (1-2 indexes bearings)
                -- [1] = {90, 90}, -- Long notation
                -- [2] = {90, 90} -- Loooong
            }
        },
        [2] = {
            ["pistons"] = {
                [{1,2}] = {1, 4}
            },
            ["bearings"] = {
                [{1,2}] = {180, 180}
            },

            -- Delays when [onDirectDelay, onReverseDelay] (start/stop delays)
            -- If a stage in the program does not include a 
            -- ["delays"] field, the default delay of {1, 1} is applied.
            ["delays"] = {2, 2}
        },
        [3] = {
            -- Pistons are not affected (saved state from stage 2)
            ["bearings"] = {
                [1] = {45, 45},
                [2] = {45, 45}
            },

            ["delays"] = {2, 2}
        }
    })
end

function onStop()
    -- Execute the program (reversed order)
    controller.stop()
end

_enableCallbacks = true
                
Design and docs by TheDIMONDK. 2025