-
Notifications
You must be signed in to change notification settings - Fork 101
Lua Scripting
Starting with mod version 1.9 you are able to write your own effects completely in Lua! Here's how it works:
If you need native definitions (which you very likely do), ensure you have a natives_def.lua
inside your chaosmod folder already. If not, go to the scripts folder inside the repository and run the generate_natives.py
script. After a few seconds it should generate a natives_def.lua
file in the same folder. Move the resulting file into your game's chaosmod
folder.
Afterwards create a scripts
folder in the same directory. That's where all the Lua scripts will be stored in.
Now create your own Lua script inside that folder.
Autocomplete if you use VS Code: https://github.com/gta-chaos-mod/ChaosModV/blob/master/scripts/generate_vsc_snippets.py
Here's an example of what a script can look like:
ScriptInfo = {
Name = "Party Time",
ScriptId = "misc_partytime",
TimedType = "Normal",
IncompatibleIds = {
"vehs_rainbow"
}
}
function OnStart()
print("Yay party! :D")
end
function OnStop()
print("Party over :(")
local playerPed = PLAYER_PED_ID()
local playerVehicle = GET_VEHICLE_PED_IS_IN(playerPed)
if playerVehicle then
SET_ENTITY_AS_MISSION_ENTITY(playerVehicle)
DELETE_ENTITY(Holder(playerVehicle))
end
end
function OnTick()
for _, vehicle in ipairs(GetAllVehicles()) do
SET_VEHICLE_ENGINE_HEALTH(vehicle, -1.0)
SET_VEHICLE_CUSTOM_PRIMARY_COLOUR(vehicle, math.random(255), math.random(255), math.random(255))
end
end
Your script will need to contain a ScriptInfo
table to be able to register as an effect. The table either must or can contain the following:
ScriptInfo = {
Name = "Party Time", -- The name of your effect to display, required
ScriptId = "misc_partytime", -- An unique id for your effect, required
TimedType = "Normal", -- The timed type of your effect (defaults to none)
WeightMultiplier = 5, -- Weight multiplier of your effect to make it more / less likely to occur randomly (defaults to 5)
IsMeta = false, -- Whether this effect is a meta effect (defaults to false)
ExcludeFromVoting = false, -- Whether this effect should be excluded from voting (defaults to false)
IsUtility = false, -- Whether this effect should only be able to be activated through the debug menu (defaults to false)
EffectCategory = "None" -- Effect category to put this effect into, only one effect in a category can run at a time (see https://github.com/gta-chaos-mod/ChaosModV/blob/master/ChaosMod/Effects/EEffectCategory.h#L12= for a list, defaults to none)
EffectGroup = "_group_weatherchange", -- Effect group to associate this effect with, groups effects together and affects weighting (defaults to none)
ShortcutKeycode = 0, -- Trigger effect if virtual keycode is pressed, see https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes - 0 to disable (defaults to 0)
IncompatibleIds = { -- A list of incompatible effects listed by their ids (defaults to none)
"vehs_rainbow"
}
}
Natives are the game script functions you can call in your script to do certain actions.
There are several databases of all the natives that have been found online, the FiveM NativeDB being one of them for instance.
Consult the example above to see how to invoke them.
The following timed types exist:
"None" -- Non-timed effect
"Normal" -- Normal timed effect
"Short" -- Short timed effect
"Permanent" -- Permanent effect
"Custom" -- Timed effect with custom duration in seconds (also needs CustomTime entry in ScriptInfo)
The following return types exist:
ReturnType = {
None,
Boolean,
Integer,
String,
Float,
Vector3
}
Errors are printed in the chaoslog.txt
file.
You can enable a console window for logs by creating a .enableconsole
file inside the chaosmod folder.
You can reload all your scripts in-game by simply turning the mod off and on again with the CTRL + L
shortcut.
Outside of functions provided by the base, math, table, string
and bit32
lua libraries and the natives provided by natives_def.lua
, the following functions are available:
print(string): Prints a string in the `chaoslog.txt` file
_invoke(nativeHash, returnType, arguments...): Invokes a native
WAIT(ms): Pauses the current fiber for `x` milliseconds
GetTickCount(): Calls the WIN32 `GetTickCount64` function
GetAllPeds(): Returns all existing peds on the world
GetAllVehicles(): Returns all existing vehicles on the world
GetAllProps(): Returns all existing props on the world
CreatePoolPed(pedType, modelHash, x, y, z, heading): Creates a ped and adds it to the mod`s pool for automatic cleanup
CreatePoolVehicle(modelHash, x, y, z, heading): Creates a vehicle and adds it to the mod`s pool for automatic cleanup
CreatePoolProp(modelHash, x, y, z, dynamic): Creates a prop and adds it to the mod`s pool for automatic cleanup
CreateTempVehicle(modelHash, x, y, z, heading): Creates a vehicle with `SET_VEHICLE_AS_NO_LONGER_NEEDED` already applied
GetAllWeapons(): Returns every existing weapon in the game
GetAllPedModels(): Returns every existing ped model in the game
GetAllVehicleModels(): Returns every existing vehicle model in the game
OverrideShader(shaderType, shaderSource) : Replaces the lens distortion shader with your own pixel shader source, ensure EffectCategory is set to "Shader" as only one shader replacement can run at a time, see https://github.com/gta-chaos-mod/ChaosModV/blob/master/ChaosMod/Effects/db/Misc/MiscShaderTnPanel.cpp for an example pixel shader
--[[
shaderType can be any of the following:
EOverrideShaderType.LensDistortion : Overrides screen lens distortion shader
EOverrideShaderType.Snow : Overrides snow shader, requires SetSnowState(true)
]]--
ResetShader() : Reset shaders back to normal
SetSnowState(bool) : Whether there should be snow on the ground
IsVehicleBraking(vehicle) : Returns whether vehicle is braking
EnableScriptThreadBlock() : Blocks all script threads except this one
DisableScriptThreadBlock() : Disables the above block
LoadModel(model_hash) : Requests a model to be loaded into memory and blocks until done so
GetChaosModVersion() : Returns the mod version
GetGameBuild() : Returns the current game build
Effects groups are a collection of different effects. During weighting, effects within an effect group will be affected by the weight of the current effect group. Effect groups are meant to group effects with a similar purpose (e.g. spawning a vehicle) together to keep the effect selection as diverse as possible. A list of built-in effect groups can be found here.
It's also possible to register your own effect groups:
EffectGroupInfo = {
Name = "group_test", -- Name, should start with `group_` as a convention
WeightMultiplier = 1 -- Weight multiplier, Ranges from 1 (lowest) - 65535 (highest), defaults to 1
}
Effect groups may not have a duplicate name; later registrations of an effect group with the same name will be ignored and the weight multiplier of the previous registration will be used. As a recommendation, you should keep the effect group definitions in separate script files for organization purposes.
You can modify some of the behaviors of the mod using Meta Modifiers.
function OnStart()
MetaModifiers.FlipChaosUI(true)
MetaModifiers.AdditionalEffectsToDispatch(3)
end
function OnStop()
MetaModifiers.FlipChaosUI(false)
MetaModifiers.AdditionalEffectsToDispatch(0)
end
As of writing, the following modifiers are available:
EffectDurationModifier(float)
TimerSpeedModifier(float)
AdditionalEffectsToDispatch(ubyte)
HideChaosUI(bool)
DisableChaos(bool)
FlipChaosUI(bool)
Some natives require pointers as arguments. You can use Holder
s in those cases.
Storing data inside a Holder and accessing it afterwards:
local r, g, b = Holder(), Holder(), Holder()
GET_VEHICLE_CUSTOM_PRIMARY_COLOUR(vehicle, r, g, b)
print(r:AsInteger() .. " " .. g:AsInteger() .. " " .. b:AsInteger())
(You can also use AsBoolean
, AsFloat
, AsString
or AsVector3
depending on the type of the stored data)
Sending data to a native:
DELETE_ENTITY(Holder(vehicle))
Note that the data passed to the Holder won't be modified (e.g. DELETE_ENTITY
won't set vehicle
to nil
in this case).
Receiving a Vector3:
local playerCoords = GET_ENTITY_COORDS(playerPed)
print(playerCoords.x .. " " .. playerCoords.y .. " " .. playerCoords.z)
Creating a Vector3:
local vector = Vector3(5.0, 3.0, 1.0)
print(vector.x .. " " .. vector.y .. " " .. vector.z)
-- Will print: 5.0 3.0 1.0