Custom Lua Injector
A powerful OpenFunscripter extension that allows you to execute custom Lua code on selected actions without creating separate extensions. Perfect for quick one-time scripts and rapid prototyping.
TL;DR
This extension lets you run Lua code on just the actions you select (by dragging on the timeline) in OpenFunscripter.
It’s perfect for quick, one-off editing without building a whole extension.
Features
- Modify Drag-Selected Actions: Write and run one-off Lua code that applies only to the actions you’ve selected in the timeline
- Code Library: Save and load frequently used code snippets
- Built-in Examples: 4 practical examples to get you started
- Comprehensive Help: Detailed documentation and API references
- Safe Execution: Sandboxed environment for secure code execution
- Keyboard Shortcuts: Quick access via key bindings
Installation 
Download from GitHub:
- Go to the GitHub repository: GitHub - Hyeoyoms/CustomLuaInjector
- Click the green “<> Code” button.
- Select “Download ZIP”.
- Extract the
main.luafile from the ZIP archive. - (Alternatively, if you’re familiar with Git, you can clone the repository.)
Place the .lua file in your OFS extensions folder:
- The typical path is:
C:\Users\[YOUR_USERNAME]\AppData\Roaming\OFS\OFS3_data\extensions\ - You can optionally create a subfolder within extensions (e.g.,
CustomLuaInjector) to keep things organized and place themain.luafile there. - Quick Tip to find the folder: In OFS, go to Extensions > Extension directory. This will usually open a folder one level above where the extensions folder is located or directly into a script folder. Navigate to the extensions subfolder within OFS3_data.
Load in OFS:
- The extension should appear in your Extensions menu in OFS after placing it in the folder. You might need to restart OFS if it doesn’t show up immediately.
Usage
- Select Actions: Drag to select actions in the OFS timeline
- Enter Code: Type your Lua code in the input field
- Execute: Click “Execute Code” to run your script
The Lua code I used in the video works as follows:
- It searches through the selected actions to find those with a
posvalue of 90. - For each of those, it calculates the time interval between the current action and the next one.
- If the interval is 130ms (0.13 seconds) or greater, it satisfies the condition.
- (In the context of the video, this corresponds to a 4-cell interval in OFS when using tempo 450 with a 16th grid. 3-cell intervals are ignored.)
- It then creates a new action at the time = current action’s
at+ 62.02ms, withposset to 80.- (Although on review, 67.02ms would have been the precise 2-cell offset — this was a small my mistake.)
- All newly created actions are added to the script.
Example Code
– Increase all selected positions by 10%
for i, action in ipairs(selectedActions) do action.pos = math.min(100, action.pos * 1.1); end;
– Remove actions with position ≤ 50
for i = #selectedActions, 1, -1 do if selectedActions[i].pos <= 50 then script:markForRemoval(getActionIndex(selectedActions[i])); end; end; script:removeMarked();
– Add intermediate action when gap is large
for i, action in ipairs(selectedActions) do if action.pos == 90 and i < #selectedActions and (selectedActions[i + 1].at - action.at) >= 0.13 then table.insert(script.actions, Action.new(action.at + 0.06702, 80, false)); end; end;
Available Functions & Variables
OFS Official API
script: Active funscript object (fromofs.Script(ofs.ActiveIdx()))Action.new(at, pos, selected): Constructor for creating new actionsscript:selectedIndices(): Get array of selected action indicesscript:markForRemoval(idx): Mark action for removalscript:removeMarked(): Remove all marked actionsscript:sort(): Sort actions by timescript:commit(): Apply changes to OFS- Standard Lua libraries:
math,table,string,pairs,ipairs, etc.
Extension Helper Functions
selectedActions: Pre-built array of currently selected actionsgetActionIndex(targetAction): Find the index of a specific actionaddAction(at, pos, selected): Convenient wrapper for creating and adding actionsprint(...): Output text to extension result area (overrides standard print)
API Reference
For complete API documentation, visit: How to create an extension - Extension API Reference
Tips
- Use semicolons (
;) to separate multiple statements action.atis time in seconds (0.1 = 100ms)action.posis position value (0-100)- Always validate array bounds with
i < #selectedActions - Use
math.min/maxfor position clamping
Contributing
Feel free to submit issues and pull requests to improve this extension.
License
This project is open source and available under the MIT License.


