Jump to content

setVehicleHandling(for speed increase) Not Working


kenoZ

Recommended Posts

Hello everyone,

I'm currently working on an engine tuning system for vehicles in MTA and I'm running into an issue with setVehicleHandling that I haven't been able to solve despite many attempts. My goal is for vehicles to get faster with each tuning level (1-3).
 

Problem Description:

The function setVehicleHandling(theVehicle, handlingTable) consistently returns false for me, and the vehicle retains its original handling. This means the KM/H values do not change, even though I'm trying to modify maxVelocity, engineAcceleration, and driveForce.

What I've Tried So Far:

  • I'm fetching the original handling using getOriginalHandling(modelID).
  • I'm creating a new handling table, carrying over most of the original values.
  • I'm modifying maxVelocity, engineAcceleration, and driveForce based on the tuning level using multipliers > 1.0 (e.g., Level 1 = 1.10x, Level 2 = 1.20x, Level 3 = 1.30x).
  • I'm converting values like driveType and engineType to their (presumably) expected numerical equivalents for the table overload of setVehicleHandling (e.g., "awd" to 2, "petrol" to 0).
  • headLightType and tailLightType are passed as numbers.
  • Vector values like centerOfMass and inertiaTensor are passed as tables {x=..., y=..., z=...}.
  • The final table is filtered to only include properties supported by setVehicleHandling.

Relevant Log Output of the finalHandling table (Infernus, Model 411, Engine Level 3 - Target: faster): (Assuming base values: baseMaxVelocity=240, baseEngineAcceleration=12, baseDriveForce=0.3 for Infernus)

 

[HH:MM:SS] INFO: [VehiclesServer DEBUG V1.32] Finales Handling für Modell 411, Level 3: {
	ABS = false,
	brakeBias = 0.50999999046326,
	brakeDeceleration = 11,
	centerOfMass = { x = 0, y = 0, z = -0.25 }, 
	collisionDamageMultiplier = 0.72000002861023, 
	dragCoeff = 1.5, 
	driveForce = 0.345, -- (0.3 * 1.15) 
	driveType = 2, 
	engineAcceleration = 15.6, -- (12 * 1.30) 
	engineInertia = 10, 
	engineType = 0, 
	handlingFlags = 12599296, 
	headLightType = 0, 
	inertiaTensor = { x = 0.1, y = 0.1, z = 0.1 }, 
	mass = 1400, 
	maxVelocity = 312, -- (240 * 1.30) 
	modelFlags = 1073750020, 
	numberOfGears = 5, 
	percentSubmerged = 70, 
	seatOffsetDistance = 0.37000000476837, 
	steeringLock = 30, 
	suspensionAntiDiveMultiplier = 0.40000000596046, 
	suspensionBiasBetweenFrontAndRear = 0.5, 
	suspensionDampingLevel = 0.18999999761581, 
	suspensionForceLevel = 1.2000000476837, 
	suspensionHighSpeedDamping = 0, 
	suspensionLowerLimit = -0.10000000149012, 
	suspensionUpperLimit = 0.25, 
	tailLightType = 0, 
	tractionBias = 0.5, 
	tractionLoss = 0.80000001192093, 
	tractionMultiplier = 0.69999998807907, 
	turnMass = 2725.3000488281 
} 
[HH:MM:SS] INFO: [applyUpgradesOnSpawn] setVehicleHandling FEHLGESCHLAGEN für Lvl 3, Fahrzeug ID 7 (Modell: 411). 
[HH:MM:SS] INFO: [applyUpgradesOnSpawn] Aktuelles Handling NACH Fehlversuch: { ... } -- (Das Original-Handling)

My getModifiedHandlingForSpawn function (Version 1.32): (It's probably best to provide the full function here, including the helper functions, for complete context in the English forum as well.)

 

-- Helper functions (getNumericValue_vehicles, isVectorTable_vehicles, createCleanVector_vehicles, typeConverters_vehicles)
-- These perform standard type conversions and vector cleaning.
-- (You can briefly describe them or paste their code here if concise enough)

local function getNumericValue_vehicles(val)
    if type(val) == "number" then return val end
    if type(val) == "string" then
        local num = tonumber(val)
        if num ~= nil then return num end
    end
    return nil
end

local function isVectorTable_vehicles(tbl)
    if type(tbl) ~= "table" then return false end
    if getNumericValue_vehicles(tbl.x) ~= nil and getNumericValue_vehicles(tbl.y) ~= nil and getNumericValue_vehicles(tbl.z) ~= nil then
        return true
    end
    if getNumericValue_vehicles(tbl[1]) ~= nil and getNumericValue_vehicles(tbl[2]) ~= nil and getNumericValue_vehicles(tbl[3]) ~= nil then
        return true
    end
    return false
end

local function createCleanVector_vehicles(originalVector, defaultX, defaultY, defaultZ)
    local defaultVec = { x = defaultX or 0, y = defaultY or 0, z = defaultZ or 0 }
    if type(originalVector) ~= "table" then return defaultVec end
    if isVectorTable_vehicles(originalVector) then
        local x_val, y_val, z_val
        if getNumericValue_vehicles(originalVector.x) ~= nil and getNumericValue_vehicles(originalVector.y) ~= nil and getNumericValue_vehicles(originalVector.z) ~= nil then
            x_val = getNumericValue_vehicles(originalVector.x); y_val = getNumericValue_vehicles(originalVector.y); z_val = getNumericValue_vehicles(originalVector.z)
        elseif getNumericValue_vehicles(originalVector[1]) ~= nil and getNumericValue_vehicles(originalVector[2]) ~= nil and getNumericValue_vehicles(originalVector[3]) ~= nil then
            x_val = getNumericValue_vehicles(originalVector[1]); y_val = getNumericValue_vehicles(originalVector[2]); z_val = getNumericValue_vehicles(originalVector[3])
        end
        if x_val ~= nil and y_val ~= nil and z_val ~= nil then return { x = x_val, y = y_val, z = z_val } end
    end
    return defaultVec
end

local typeConverters_vehicles = {
    engineType = function(val, default)
        if type(val) == "string" then local s = string.lower(val); if s == "petrol" then return 0 elseif s == "diesel" then return 1 elseif s == "electric" then return 2 end end
        local num_val = getNumericValue_vehicles(val); if num_val ~= nil and (num_val >= 0 and num_val <= 2) then return num_val end
        return default 
    end,
    driveType = function(val, default)
        if type(val) == "string" then local s = string.lower(val); if s == "fwd" then return 0 elseif s == "rwd" then return 1 elseif s == "awd" or s == "4wd" then return 2 end end
        local num_val = getNumericValue_vehicles(val); if num_val ~= nil and (num_val >= 0 and num_val <= 2) then return num_val end
        return default 
    end,
    headLightType = function(val, default)
        if type(val) == "string" then local s = string.lower(val); if s == "small" then return 0 elseif s == "long" then return 1 elseif s == "big" then return 2 elseif s == "tall" then return 3 end end
        local num_val = getNumericValue_vehicles(val); if num_val ~= nil and (num_val >= 0 and num_val <= 3) then return num_val end
        return default or 0
    end,
    tailLightType = function(val, default)
        if type(val) == "string" then local s = string.lower(val); if s == "small" then return 0 elseif s == "long" then return 1 elseif s == "big" then return 2 elseif s == "tall" then return 3 end end
        local num_val = getNumericValue_vehicles(val); if num_val ~= nil and (num_val >= 0 and num_val <= 3) then return num_val end
        return default or 0
    end,
    ABS = function(val, default)
        if type(val) == "boolean" then return val end
        if type(val) == "string" then local s = string.lower(val); if s == "true" then return true elseif s == "false" then return false end end
        local num_val = getNumericValue_vehicles(val); if num_val ~= nil and (num_val == 0 or num_val == 1) then return num_val == 1 end
        return default or false
    end
}

function getModifiedHandlingForSpawn(theVehicle, engineLevel)
    if not isElement(theVehicle) or getElementType(theVehicle) ~= "vehicle" then
        outputDebugString("[VehiclesServer|getModifiedHandlingForSpawn] Error: 'theVehicle' is not a valid vehicle element.")
        return false
    end
    if not engineLevel or type(engineLevel) ~= "number" or engineLevel < 0 or engineLevel > 3 then
        outputDebugString("[VehiclesServer|getModifiedHandlingForSpawn] Error: Invalid 'engineLevel'.")
        return false
    end

    local vehicleModelID = getElementModel(theVehicle)
    local success, originalHandling_raw = pcall(getOriginalHandling, vehicleModelID)

    if not success or type(originalHandling_raw) ~= "table" then
        outputDebugString(string.format("[VehiclesServer|getModifiedHandlingForSpawn] pcall(getOriginalHandling) for model %d FAILED. Error/Type: %s", vehicleModelID, tostring(originalHandling_raw)))
        return false
    end

    local oh = originalHandling_raw
    local finalHandling = {}
    local transData = oh.transmissionData or oh 

    finalHandling.mass = getNumericValue_vehicles(oh.mass) or 1700.0
    finalHandling.turnMass = getNumericValue_vehicles(oh.turnMass) or 5000.0
    finalHandling.dragCoeff = getNumericValue_vehicles(oh.dragCoeff) or 2.5
    finalHandling.centerOfMass = createCleanVector_vehicles(oh.centerOfMass or oh.vecCentreOfMass, 0, 0, -0.1)
    finalHandling.percentSubmerged = getNumericValue_vehicles(oh.percentSubmerged) or 85
    finalHandling.tractionMultiplier = getNumericValue_vehicles(oh.tractionMultiplier) or 0.75
    finalHandling.tractionLoss = getNumericValue_vehicles(oh.tractionLoss) or 0.85
    finalHandling.tractionBias = getNumericValue_vehicles(oh.tractionBias or oh.driveBias) or 0.5
    
    finalHandling.numberOfGears = getNumericValue_vehicles(transData.maxGear or transData.numberOfGears) or 4
    finalHandling.maxVelocity = getNumericValue_vehicles(transData.maxVelocity) or 200.0
    finalHandling.engineAcceleration = getNumericValue_vehicles(transData.engineAcceleration) or 10.0
    finalHandling.engineInertia = getNumericValue_vehicles(oh.engineInertia or (transData and transData.engineInertia)) or 5.0

    finalHandling.driveType = typeConverters_vehicles.driveType(oh.driveType or (transData and transData.driveType), 1) 
    finalHandling.engineType = typeConverters_vehicles.engineType(oh.engineType or (transData and transData.engineType), 0)

    finalHandling.brakeDeceleration = getNumericValue_vehicles(oh.brakeDeceleration) or 10.0
    finalHandling.brakeBias = getNumericValue_vehicles(oh.brakeBias) or 0.5
    finalHandling.ABS = typeConverters_vehicles.ABS(oh.ABS, (oh.ABS ~= nil and typeConverters_vehicles.ABS(oh.ABS)) or false)
    finalHandling.steeringLock = getNumericValue_vehicles(oh.steeringLock) or 35.0

    finalHandling.suspensionForceLevel = getNumericValue_vehicles(oh.suspensionForceLevel) or 1.0
    finalHandling.suspensionDampingLevel = getNumericValue_vehicles(oh.suspensionDampingLevel or oh.suspensionDamping) or 0.1
    finalHandling.suspensionHighSpeedDamping = getNumericValue_vehicles(oh.suspensionHighSpeedDamping) or 0.0
    finalHandling.suspensionUpperLimit = getNumericValue_vehicles(oh.suspensionUpperLimit) or 0.35
    finalHandling.suspensionLowerLimit = getNumericValue_vehicles(oh.suspensionLowerLimit) or -0.15
    finalHandling.suspensionBiasBetweenFrontAndRear = getNumericValue_vehicles(oh.suspensionBiasBetweenFrontAndRear or oh.suspensionFrontRearBias) or 0.5
    finalHandling.suspensionAntiDiveMultiplier = getNumericValue_vehicles(oh.suspensionAntiDiveMultiplier) or 0.3
    
    finalHandling.seatOffsetDistance = getNumericValue_vehicles(oh.seatOffsetDistance) or 0.0
    finalHandling.collisionDamageMultiplier = getNumericValue_vehicles(oh.collisionDamageMultiplier) or 1.0
    
    finalHandling.modelFlags = (type(oh.modelFlags) == "string" and string.sub(oh.modelFlags, 1, 2) == "0x" and tonumber(oh.modelFlags, 16)) or getNumericValue_vehicles(oh.modelFlags) or 0
    finalHandling.handlingFlags = (type(oh.handlingFlags) == "string" and string.sub(oh.handlingFlags, 1, 2) == "0x" and tonumber(oh.handlingFlags, 16)) or getNumericValue_vehicles(oh.handlingFlags) or 0

    finalHandling.headLightType = typeConverters_vehicles.headLightType(oh.headLight or oh.headLightType, (oh.headLight and typeConverters_vehicles.headLightType(oh.headLight)) or 0)
    finalHandling.tailLightType = typeConverters_vehicles.tailLightType(oh.tailLight or oh.tailLightType, (oh.tailLight and typeConverters_vehicles.tailLightType(oh.tailLight)) or 0)

    finalHandling.inertiaTensor = createCleanVector_vehicles(oh.inertiaTensor or oh.vecInertia, 0.1, 0.1, 0.1)

    local baseDriveForce = getNumericValue_vehicles(oh.driveForce)
    if not baseDriveForce or baseDriveForce <= 0.001 then
        baseDriveForce = (vehicleModelID == 451 and 0.30) or (vehicleModelID == 411 and 0.35) or (vehicleModelID == 560 and 0.25) or 0.20
    end
    finalHandling.driveForce = baseDriveForce

    -- Modifications for engineLevel (to make vehicle FASTER)
    if engineLevel > 0 then
        local velocityMultiplier, accelerationMultiplier, driveForceMultiplier = 1.0, 1.0, 1.0
        if engineLevel == 1 then
            velocityMultiplier = 1.10; accelerationMultiplier = 1.10; driveForceMultiplier = 1.05 
        elseif engineLevel == 2 then
            velocityMultiplier = 1.20; accelerationMultiplier = 1.20; driveForceMultiplier = 1.10
        elseif engineLevel == 3 then
            velocityMultiplier = 1.30; accelerationMultiplier = 1.30; driveForceMultiplier = 1.15
        end
        
        finalHandling.maxVelocity = (getNumericValue_vehicles(transData.maxVelocity) or 200.0) * velocityMultiplier
        finalHandling.engineAcceleration = (getNumericValue_vehicles(transData.engineAcceleration) or 10.0) * accelerationMultiplier
        finalHandling.driveForce = baseDriveForce * driveForceMultiplier
    end
    
    outputDebugString("[VehiclesServer DEBUG V1.32] Final handling for model "..vehicleModelID..", Level "..engineLevel..": " .. inspect(finalHandling))
    return finalHandling
end

Question for the Community:

Despite ensuring that driveType (e.g., 2 for AWD) and engineType (e.g., 0 for Petrol) are numerical, and headLightType/tailLightType are also numerical in the table passed to setVehicleHandling(theVehicle, handlingTable), the function still returns false. The other values in the table appear plausible and are based on getOriginalHandling. The multipliers for engineAcceleration, maxVelocity, and driveForce are now > 1.0, aiming to make the vehicle faster.

Does anyone have an idea why setVehicleHandling might still be failing with the finalHandling table shown in the logs above? Could there be an issue with min/max value violations for other properties, or a missing critical property that setVehicleHandling (table overload) requires? The test vehicle is an Infernus (model 411).

I've also tried sending a very minimal table with only the modified values (engineAcceleration, maxVelocity, driveForce) and some core values (mass, numberOfGears, driveType, engineType), which also failed.

Any help or insights would be greatly appreciated!

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...