You are browsing as a guest. Sign up (or log in) to start making projects!

BigSaltyBeans

@BigSaltyBeans

Joined June 5th, 2026

  • 12Devlogs
  • 3Projects
  • 2Ships
  • 19Votes
Open comments for this post

39m 12s logged

Finished work on v2 of the PCB!

  • Moved the LEDs to the right side
  • Fixed all of the DRC errors
  • Schematic now represents the board properly
  • Cleaned up routing
  • Reassigned pins to make routing cleaner

To do:

  • Adjust the case for new/moved components!
0
0
2
Ship Changes requested

# SimCruiser Ship!

SimCruiser G25 is a Lethal Company mod that changes the Company Cruiser's input logic to make it compatible with a Logitech G25 Sim Wheel. It's been a journey but this mod is such a blast to use when playing with friends and still support tech like Cruiser jumps and interacting.

## Features:
- Adds input bindings for the G25 wheel
- Rewrites the Company Cruiser input system to make driving feel more realistic with the G25
- Shifter changes between Drive, Reverse and Park
- Wheel is 1:1 with the cruiser
- Pedals accelerate and break

You can install this Mod through Thunderstore or download the `.dll` directly.

Have fun!
Liam

  • 5 devlogs
  • 10h
Try project → See source code →
Open comments for this post

42m 46s logged

Devlog 5

After I got the steering working, I wanted to be able to use the G25’s shifter to change gears in the company cruiser. This required more expirimenting to figure out how the shifter is interpreted by unity’s input system.

Investigating

It turns out that every position on the shifter is assigned a button, and that button is considered pressed when the shifter is in that gear. Below are the button assignements I found:
In 6 Gear Mode

  • 1st Gear: Button 9
  • 2nd Gear: Button 10
  • 3rd Gear: Button 11
  • 4th Gear: Button 12
  • 5th Gear: Button 13
  • 6th Gear: Button 14
  • Reverse: Button 15
    In +/- Mode
  • Forward: Button 9
  • Back: Button 10

I also took a look at how the player sets the cruiser’s gears, and it’s with a method called ShiftToGearAndSync(desiredGear). So when changing gears this is the method I need to call.

Implementation

Getting the shifting working was pretty easy. First I created 2 new actions and bindings for the Drive and Reverse gears and bound then to the 3rd and 4th gears on the shifter. I chose those as it keep it centered and feels more natural.
Then I added some code into the same method we edited for the steering that:

  • Stores the current gear.
  • Checks if the stick is in a position:
    • If yes:
      • Is the stick in the same position as it was last frame?
        • If yes ignore
        • If no set the cruiser’s gear to the new gear
    • If no:
      • Set the cruiser’s gear into park as no gear is selected.

So in our case, what IRL is neutral is park, forward (or 3rd) is drive and back (or 4th) is reverse.

Feels pretty epic when driving the cruiser!

Next up:

The mod is basically done, but there are a few things we can still do:

  • Add bindings for things like the radio, wipers, etc
  • Ship the final version in Thunderstore

Cheers!
Liam

0
0
2
Open comments for this post

2h 10m 7s logged

Devlog 4

Finished re-writing the cruiser’s steering!Not too much to say, but still a pretty big update: The cruiser’s steering wheel is now 1:1 with the physical G25 in multiple ways.
Originally the Company Cruiser was driven by holding down the A or D keys to steer. The wheel would gradually rotate in the direction you were holding and stop rotating but maintain the rotation on release. This logic obviously sucks when you want to use a sim wheel, because you want the CC’s wheel rotation to be a direct replica of the physical wheel’s rotation.
This means the logic had to be redone, therefore a rewrite of the cruiser’s GetVehicleInput() needed to be done.

Implementation

Zeekerss original code for steering was this:
float num = __instance.steeringWheelTurnSpeed; __instance.steeringInput = Mathf.Clamp(__instance.steeringInput + __instance.moveInputVector.x * num * Time.deltaTime, -3f, 3f);
Modifing these lines was pretty straightforward:

  • Remove num entirely as we done need the wheel’s turn speed
  • Don’t multiply by Time.deltaTime as it’ll be direct
  • Don’t add the old input values to the new one as we want 1:1 with the G25

In the end the code looked like this: __instance.steeringInput = Mathf.Clamp(__instance.moveInputVector.x * 3f, -3f, 3f);
We need to multiply by 3 as we want the max to be 3 but the input can only reach a max value of 1.

Animation

This new wheel logic worked great except one problem: The G25 would be at 90deg at it’s max but the game would show it at 225deg.
The solution to this was to adjust the anim’s clam values from +/- 1 to +/- 2.4.
Why? Because we need to remove 1.4f from the max value, and for some reason the anim needs us to add it onto 1 instead of remove ¯\_(ツ)_/¯

Next Up:

Going forward all that’s really left is using the G25’s shifter to change the cruiser’s gears from Park, Reverse and Drive!
Cheers,
Liam

0
0
3
Open comments for this post

49m 20s logged

Devlog 3

Tried driving the company cruiser with the wheel, and a few things need to be done:

  • The CC’s steering needs to be turned 1:1 with the wheel’s input
  • Acceleration and breaking needs to be rewritten to feel more realistic

Published the input part of the mod onto Thunderstore tho to make testing easier.

I’ll make a more interesting update once I start working that out!
Cheers,
Liam

0
0
2
Open comments for this post

4h 34m 57s logged

Devlog 2

Finally finished the first and most cruicial part of the mod! The first step to this mod was to let Lethal Company’s input system receive bindings from the G25. Now this in theory should have been a fast and easy implementation. Here’s how it turned into a 4 hour journey:

Writing base code

I started off by writing the essential parts of the mod. This mod uses BenInEx and HarmonyLib to patch my custom code into Lethal Company, so I made the public BasicUnityPlugin class that applies all patches in the .GetExecutingAssembly(). This means that it’ll look at all the code in the built .dll and patch automatically instead of me specifying what classes I want to patch.

The AddWheelBindings class

This is the center of attention when it comes to the input patching. This class needs to do 3 things:

  • Find the localPlayerController
  • Get all InputActionAssets that affect the localPlayerController
  • Add new bindings to the ActionAsset’s InputAction that needs it

By fiddling around with the input system in another project, I found the name of the wheel to be <HID::G25 Racing Wheel>. Knowing the device name, I was ready to start patching the new inputs into the input assets.

The class that we will be patching is the StartOfRound class as it handles a lot of the local player and game logic. First I found the local player through StartOfRound.Instance?.localPlayerController;, then found the player’s playerActions asset and assigned a var to that. Then I made a function that takes the InputActionAsset, finds the actions we want, such as the ‘move’ action, and applies a new binding to that action. For example, we can grab the ‘interact’ action with InputAction interact = actions.FindAction("Interact"); and give it a new binding specifically for the G25: jump.AddBinding("<HID::G25 Racing Wheel>/button7").WithInteraction("press");

Weirdness

Once I finished adding all the bindings to the right actions along with some null checks, I build the .dll and got to testing. Right off the bat nothing worked, but a quick change to what method we needed to patch… kind of fixed things?

Something weird was going on: the bindings I’d made to the look action were working, but none of the other were.

3 hour long story short, Zeekerss made his PlayerControllerB read from two different instances of one InputActionAsset, so the bindings and actions across the two were the same but each one was being referanced in different spots.

The camera worked right away because the line that read the camera’s input was:playerActions.Movement.Look.ReadValue<Vector2>() as opposed to all other controls read as such: InputSystem.actions.FindAction("Move").ReadValue<Vector2>();.

The InputActionAsset I was patching was the one created in the player’s Awake() method, playerActions, and not the second global one.The only reason I found for Zeekerss to make two is that the mouse was being read by the first because the look input is not one that can be rebound in the settings menu. All the controls pulled from the second asset are controls that can be rebound in settings, meaning that the second one was the player’s local input settings when the first was the default.

Fix

All that needed to be done for the G25 controls to be read for all the actions was to also patch InputSystem.actions’s asset. It took about 3 1/2 hours to figure this  out, but at least it works now!

Next up:

Going forward we need to:

  • Test the current system on the cruiser
  • See what needs changes to feel more realistic

Cheers!
Liam

0
0
1
Open comments for this post

1h 19m 14s logged

Devlog 1

Recently, and as summer’s been coming around, I’ve been playing more and more lethal company with the bros. Now I wouldn’t say we’re sweats or anything, but we’re pretty good and can get to 3000+ quotas without many resets. On thing that’s made that possible is the wonderful Company Cruiser! For anyone who’s driven the Company Cruiser before, you already know how hellish it can be. The gear changes, janky steering and funny physics make it truly an experience to manage.

I’ve been driving this thing for a while now and would like to think that I’m quite proficient, but looking around my room got me thinking:
What if I could use my Logitech steering wheel to drive the cruiser? Now of course the base game has no support for it and the input system used to drive the Cruiser is 1-0 based and not Vector based (W key accelerates at max when a pedal would be an axis), but having modded lethal before I was sure It’d be feasible. So I got cracking.

Configuring the Wheel

The Logitech G25 is a legacy wheel and is not supported in newer Logitech software. After much fiddling I figured out I needed to use a very old version of Logitech Gaming Software to get it to register properly on my computer.   

Bringing it into Unity

To start I needed to learn how the wheel interacts in and gets registered by Unity, specifically Unity 2022.3.9f, the version Zeekerss used to build LC. I began by making a unity project in that version with the URP Template, as it already had a preconfigured controller using the new Input System. I also downloaded a unity project by Juandarn called SpaceVR that used the Logitech G25 to figure out how it configured the wheel in it’s input system. Here’s what I learnt:

  • The G25 is interpreted as a joystick with the wheel being Left and Right (X), Accelerator being Y+, and the Brake being Y-.
  • All the buttons are regular.
  • The Dpad is also a joystick.
  • Z axis is the accelerator pedal but inverted (???)
  • RZ axis is the brake pedal but inverted (also ???)
  • Trigger is just button 1
  • Slider is inverted Clutch pedal

Looking at Lethal Company’s input system

As the goal is to be able to drive the CC with the G25, it was also time to start looking at how Zeekerss configured the Input system for LC. I did this by using an asset ripper to reverse engineer Zeekerss LC build and turn it back into a Unity Project. So now that I have LC’s source code, it turns out it’s pretty simple and all the controls under one Action Map, so in the end I’ll need to add the G25’s axis configurations to the Actions themselves. I don’t think it’ll be too hard but for that I’ll need to start on some research related to interacting with a player’s input system through an LC mod patch.

Next up:

  • Programming basic mod for Lethal that adds the wheel’s axis to the base game’s player input actions.
  • Looking into how the Company Cruiser interprets player inputs to see what needs to be reprogrammed.

This will be quite the fun mod and journey, post a comment if you have any ideas or suggestions!
Cheers,
Liam

0
0
2
Open comments for this post

1h 9m 15s logged

Major PCB Improvements

Many edits were made to the PCB, explained below:

  • Underglow LEDs on top and bottom were added!
  • Key LEDs were moved to a much better position
  • Used a ground fill instead of routing
  • Keys are more spaced and lined up
  • Traces are now 0.5mm thick

All V2 now needs is a CAD update!

0
0
2
Ship Pending review

Here is my 5 Key macropad for Hackpad! I've never designed a PCB before and this has been such a blast to learn, prototype, and ship! I'm pretty happy with my creation and proud of myself for learning how to build PCBs. Writing the firmware was also a new experience that I found extremely difficult, but you only learn through failures! Hopefully this gets to see the light of day.
Cheers!

Video of Project → See source code →
Open comments for this post

32m 30s logged

Finished Firmware and Ship!

After cleaning up the PCB design and generating gerber files I spent some time working on the firmware! I decided to use QMK for the firmware and programed support for all my hackpad’s features!

The default keys are the 4 Arrow keys, Z, and the volume knob with push to mute.

I did not expect the firmware to be as difficult to program as it was! This has been a fun project, there is still much to work on as things come together in the real world but I’m proud of where I’ve gotten up to now!

0
0
1
Open comments for this post

3h 1m 30s logged

Devlog 1!
Hello world!

To commence this project I began my reading the DIY guide and following along, eventually splitting off and designing a keypad with my own variations! Below is a detailed overview of my keypad:

My keypad consists of 5 keys and a rotary encoder. The rotary encoder contains a switch that when pressed can be interpreted as it’s own keypress. I was hoping to use the rotary as a volume knob and it’s switch as a mute/unmute button. I placed them to the side to leave space for the controller as can be seen in the PCB design.

The keypad also has 5 LED’s, all strung together through the data in/outs. For the last feature, this keypad contains a programmable OLED screen on the top that can be used to display anything your imagination wants!

Moving forward I have yet to program the firmware, and I will also have to clean up the schematic as it’s quite messy.

0
0
1
Open comments for this post

50m 14s logged

Devlog 3!

More features on the way!
After uploading v1 and creating a readme I put time into writing new methods that will further make this project easy to use!

On Flysky controllers, the switches are lettered a-d. Instead of having to find out what channel the switches are mapped to, I designed a method that lets you pass the switch’s letter and it returns the bool value without you having to deal with the channel #.

In terms of complexity I also added two new methods for more experienced programmers using this lib:

readChannelRaw: This method returns the raw data from a specified channel

readSwitchRaw: This method returns the raw uninverted state of a switch.

Next up is writing examples and making axis mode settings!

0
0
1
Open comments for this post

33m 39s logged

Devlog 2!
Real world testing!

After having written the most basic functions, I’ve gone to my electronics cabinet and put my code to the test!

Using a proper FlySky i6 controller I tested my library with an Arduino Mega and was able to find and troubleshoot many issues in my library code and .ino example. Overall everything worked really well, so I am now looking towards implementing more complex methods and features to both make the lib easier to use and to tailor it to the interests of more advanced users.

Cheers!

0
0
2
Open comments for this post

38m 16s logged

Devlog 1!

For a long time Flysky controllers have been used in personal avionics and robotics projects, interacting with many boards.
All this time there has only been one main library used to interpret the signals from these controller’s receivers: iBusBM. It’s a great library for what it’s made for, but it’s design requires the need for extra code to be written if you want to read specific channels or switches in a clean manner.

My goal with this library is to simplify the code integration of Flysky into two main easy-to-use methods:

readAxis();
readSwitch();

Each method does exactly as their name suggests!

As this project develops I plan on adding more specific methods for more advanced use cases such as getting raw inputs or setting axis modes, but next up is real world testing on different boards!

Cheers!

0
0
2

Followers

Loading…