[Spaar`s Modloader] Lachcim`s Scripting Mod [Beta for Besiege 0.10]

#1
Hello,
Today I'd like to present you a new Besiege mod that I've made. It lets you automate your machines with the help of scripts written in Lua, a very simple and powerful scripting language. It is based off of spaar's In-Game Scripting. Unlike spaar's mod, however, my mod doesn't require you to know C# nor look into the game's source code, is less CPU-intensive, and loads scripts from the user's file system, as opposed to providing an in-game scripting interface.

Example script

This simple script allows you to dynamically adjust the speed of your machine's wheels. I wrote it on the go while recording, which in retrospection wasn't a very good idea, sorry :(
Try it yourself, remember to change the IDs!
Code:
local speed = 0

besiege.onKeyHeld = function(keyCode)
    if keyCode == besiege.keyCodes.i then
        speed = speed + 0.1
    elseif keyCode == besiege.keyCodes.k then
        speed = speed - 0.1
    end
    
    if speed > 2 then speed = 2 end
    if speed < -2 then speed = -2 end
    
    besiege.setSliderValue(4, speed)
    besiege.setSliderValue(6, speed)
    besiege.setSliderValue(3, speed)
    besiege.setSliderValue(5, speed)
end

Usage

Creating and loading scripts
Lachcim's Scripting Mod looks for scripts to load in the /Besiege_Data/Scripts subfolder of your game's directory. If it's not there, create it yourself or launch your modded game and let the mod do it. Scripts are bound to their machines by sharing the same filename (with a different extension), so name your script file like this: <machine name>.lua. The game decides which script to load by looking at the last saved/loaded machine's name, so make sure to save your contraptions if you're creating them from scratch.

Interacting with the game
All functions and tables needed to interact with your machine are located in a predefined table named besiege. For full documentation, head over to the "Documentation" section of this post. Most functions require you to know the IDs of your machine, which you can learn how to do below.

Retrieving block IDs
Open up the console by pressing CTRL+K and enter the key mapper. Click on individual blocks, and their IDs will show up in the console window.

Launching and stopping scripts
Scripts are automatically launched when the simulation starts, and stop when the simulation stops.

Debugging
All C# exceptions (including Lua errors) are shown in the console, which you can bring up by pressing CTRL+K. You can also log messages in the console with the besiege.log() function. If you get a Lua-unrelated exception (like NullReferenceException) while calling a function, this may mean you provided invalid arguments (a wrong block ID, for example). This is an issue which remains to be fixed in a future update.

Documentation

besiege.log(string message)
Logs a message in the console. Make sure you do pass a string, as numbers and booleans result in an exception.

besiege.hasSlider(number id)
Checks if a block has a slider whose value can be changed. Returns a boolean.

besiege.getSliderValue(number id)
Returns a block's slider value.

besiege.setSliderValue(number id, number value)
Sets a block's slider value.

besiege.getSliderMinValue(number id)
Returns a block's minimal slider value. This is used by the game in the key mapper menu, you can exceed this limit (and make the value negative, for example).

besiege.getSliderMaxValue(number id)
Returns a block's maximal slider value. This is used by the game in the key mapper menu, you can exceed this limit.

besiege.canToggle(number id)
Checks if a block has a toggleable mode (e.g. a wheel's automatic mode). Returns a boolean.

besiege.setToggleMode(number id, boolean mode)
Sets a block's toggleable mode.

besiege.getPositionX(number id)
Returns the X coordinate of a block.

besiege.getPositionY(number id)
Returns the Y coordinate of a block.

besiege.getPositionZ(number id)
Returns the Z coordinate of a block.

besiege.getYaw(number id1, number id2)
Returns the yaw measured between two blocks. The blocks should be perpendicular to the vessel's length.

besiege.getPitch(number id2, number id2)
Returns the pitch measured between two blocks. The blocks should be parallel to the vessel's length.

besiege.getRoll(number id2, number id2)
Returns the roll measured between two blocks. The blocks should be perpendicular to the vessel's length.

besiege.onUpdate()
This function is not defined by default. If defined, it's called each frame the script is running.

besiege.onKeyHeld(number keyCode)
This function is not defined by default. If defined, it's called each frame a key is pressed. A number is passed as the only argument, indicating the key code.

besiege.onKeyDown(number keyCode)
This function is not defined by default. If defined, it's called the first frame a key is pressed. A number is passed as the only argument, indicating the key code.

besiege.onKeyUp(number keyCode)
This function is not defined by default. If defined, it's called the first frame a key is released. A number is passed as the only argument, indicating the key code.

besiege.keyCodes
This associative table contains all the key codes, as seen here: http://docs.unity3d.com/ScriptReference/KeyCode.html. Keep in mind Lua variables start with lowercase letters.

Downloading and installation

Download the mod from here:
Place Nlua.dll and KopiLua.dll in the /Besiege_Data/Managed subfolder of your game's directory, and Lachcim's Scripting Mod.dll in the /Besiege_Data/Mods subdirectory. spaar's Mod Loader is required for this mod to work.

Known issues and changelog

Changelog:
Alpha:
  • This is the first version. There hasn't been a change yet, but I'm certain there's going to be one.
Beta:
  • Fixed error spamming
  • Better error handling when calling functions from the besiege table
Known issues:
  • It is impossible to interact with contractible springs, grabbers and some other blocks
  • It is impossible to retrieve a single block's rotation - This is pretty much a WONTFIX due to how Unity handles rotation (damn quaternions)
Let me know if you spot any new issues.

Thumbnail

Per Von's request, here is a thumbnail for my mod:



Fullscreen: http://i.imgur.com/nbufmqF.jpg

Yeah, you can tell I'm not a graphic designer :p

Attached Files
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#3
Do some try catch to remove null-references maybe?
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#4
Oh, also, remember to join the slack group :3
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#5
Oh, also, you can upload files directly the the forum with the button to the left of the A :3
 

spaar

Active Member
#6
Looks nice! Unfortunately I don't really find the time to work on my scripting mod anymore, so it's nice to see somebody else does this.
I look forward to trying it out, it looks like it's already much better than the early-prototype I released.

It is impossible to retrieve a single block's rotation - This is pretty much a WONTFIX due to how Unity handles rotation (damn quaternions)
I don't really know how your code looks, but couldn't you use Quaternion.eulerAngles if the quaternions are the problem?
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#7
Wait, why can't quaternions be used in lua?
 

spaar

Active Member
#8
I think you could handle them perfectly fine, the way you handle vec3s. However let's be honest: Who is able to read or write a rotation that's expressed as Quaternion?
 
#9
Thanks for replying, everyone!

ITR, the thing about the exceptions is, this mod is 2 days old and I simply couldn't be bothered to fix what wasn't really broken ^^ But yes, try-catch statements are a must-have.

Thanks, spaar! Seeing how there hadn't been a reply in your thread for almost two weeks, I knew there wasn't much point in asking you to do more work. I focused on making this mod appropriate for the general public, that is, the part of the general public who can write scripts. :)

I don't know much about quaternions, but I do know that three combinations of Euler angles can result in the same quaternion, and I do know that Unity has a problem with handling these conversions. Long story short, Quaternion.eulerAngles isn't reliable at all.
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#10
Lachcim said:
Thanks for replying, everyone!

ITR, the thing about the exceptions is, this mod is 2 days old and I simply couldn't be bothered to fix what wasn't really broken ^^ But yes, try-catch statements are a must-have.

Thanks, spaar! Seeing how there hadn't been a reply in your thread for almost two weeks, I knew there wasn't much point in asking you to do more work. I focused on making this mod appropriate for the general public, that is, the part of the general public who can write scripts. :)

I don't know much about quaternions, but I do know that three combinations of Euler angles can result in the same quaternion, and I do know that Unity has a problem with handling these conversions. Long story short, Quaternion.eulerAngles isn't reliable at all.
I think I use .eulerAngles in KeepCameraRotaiion mod, which works great, but why can't we modify the quaternions directly?
 

spaar

Active Member
#11
Lachcim said:
I don't know much about quaternions, but I do know that three combinations of Euler angles can result in the same quaternion, and I do know that Unity has a problem with handling these conversions. Long story short, Quaternion.eulerAngles isn't reliable at all.
Oh, okay, that's good to know. I wasn't aware that it's not always reliable, thanks for the info.
 
#12
Sorry for the delay.

ITR, we're talking about reading rotation, not writing it. Now, try tracking a block's rotation using spaar's in-game scripting mod. You'll see that some angles change seemingly for no reason, become negative when they hit multiples of 90 and do all sorts of shenanigans. They're useless, in my opinion!
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#13
Lachcim said:
Sorry for the delay.
ITR, we're talking about reading rotation, not writing it. Now, try tracking a block's rotation using spaar's in-game scripting mod. You'll see that some angles change seemingly for no reason, become negative when they hit multiples of 90 and do all sorts of shenanigans. They're useless, in my opinion!
What about using .forward and .look instead? That might be more intuitive.
 
#14
I tried that and it doesn't exactly suit my needs. I think I'll stick to my position-based functions, that is, getYaw(), getPitch() and getRoll().
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#15
Exactly what are your needs?
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#16
Also, are you sure that .eulerAngles are unreliable?
 
#17
First off, thank you so much for this mod -- it's going to lead to great things in controlling massively complicated machines. I'm going to be using it to great effect. One thing though: Is it possible to simulate keystrokes? I'd like to programmatically control things like pistons and flamethrowers.

Also a bug report: I can't seem to get onKeyUp() to fire. I'm not sure if I'm doing something wrong but I've never gotten it to work.
 

ITR

l̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ֍̫̜̥̭͖̱̟̟͉͙̜̰ͅl̺̤͈̘̰̺͉̳͉̖̝̱̻̠̦͈ͅ
Staff member
#18
Can you send a PM to spaar with your e-mail? You should join the slack-team :3
 
#20
I was using this mod just fine a few days ago but now I can't get it to work. I haven't changed anything at all but the scripts aren't loading.

I get this in the console:
[Log] Trying to load E:\SteamLibrary\steamapps\common\Besiege\Besiege_Data\Mods\Lachcim's Scripting Mod.dll
[Log] Could not load Lachcim's Scripting Mod.dll:
[Exception] ReflectionTypeLoadException: The classes in the module cannot be loaded.
System.Reflection.Assembly.GetExportedTypes ()
spaar.ModLoader.Start ()
UnityEngine.Debug:LogException(Exception)
spaar.ModLoader:Start()
 
Top