Revert "fixing ers"
This reverts commit e520d9a1a3a11d830a2bab82b9161f4ddb900cad.
This commit is contained in:
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
Make sure the resource name is jraxion_handlingeditor, it will break the resource if you rename it.
|
||||||
Binary file not shown.
@@ -0,0 +1,424 @@
|
|||||||
|
Config = {}
|
||||||
|
|
||||||
|
-- Make sure the resource name is jraxion_handlingeditor, it will break the resource if you rename it.
|
||||||
|
|
||||||
|
Config.isAllowed = function(source) --server side. most frameworks already have this.
|
||||||
|
-- if you know what you are doing, edit server/server.lua to change the permission.
|
||||||
|
if IsPlayerAceAllowed(source, 'admin') or IsPlayerAceAllowed(source, 'command') then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
Config.Precision = 10000.0
|
||||||
|
|
||||||
|
Config.Values = {
|
||||||
|
-- Physical
|
||||||
|
fMass = {
|
||||||
|
name = "Vehicle Mass",
|
||||||
|
type = "float",
|
||||||
|
change = 100.0,
|
||||||
|
min = 100.0,
|
||||||
|
max = 5000.0,
|
||||||
|
description = "Vehicle weight in kilograms. Affects collision physics."
|
||||||
|
},
|
||||||
|
fInitialDragCoeff = {
|
||||||
|
name = "Drag Coefficient",
|
||||||
|
type = "float",
|
||||||
|
change = 1,
|
||||||
|
min = 10.0,
|
||||||
|
max = 120.0,
|
||||||
|
description = "Aerodynamic drag coefficient. Higher values increase air resistance."
|
||||||
|
},
|
||||||
|
fPopUpLightRotation = {
|
||||||
|
name = "Pop-up Light Rotation",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 90.0,
|
||||||
|
description = "Angle of pop-up headlights when deployed"
|
||||||
|
},
|
||||||
|
fPercentSubmerged = {
|
||||||
|
name = "Submersion Percentage",
|
||||||
|
type = "float",
|
||||||
|
change = 5.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 100.0,
|
||||||
|
description = "Percentage of vehicle that must be submerged before sinking. Default is 85%."
|
||||||
|
},
|
||||||
|
vecCentreOfMassOffset = {
|
||||||
|
name = "Centre of Mass Offset",
|
||||||
|
type = "vector",
|
||||||
|
change = 0.1,
|
||||||
|
min = -2.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Center of mass offset from vehicle origin",
|
||||||
|
components = {
|
||||||
|
x = {name = "X Offset", description = "Left/Right offset"},
|
||||||
|
y = {name = "Y Offset", description = "Front/Back offset"},
|
||||||
|
z = {name = "Z Offset", description = "Up/Down offset"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
vecInertiaMultiplier = {
|
||||||
|
name = "Inertia Multiplier",
|
||||||
|
type = "vector",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.0,
|
||||||
|
max = 3.0,
|
||||||
|
description = "Inertia multiplier for each axis",
|
||||||
|
components = {
|
||||||
|
x = {name = "X Multiplier", description = "Roll inertia"},
|
||||||
|
y = {name = "Y Multiplier", description = "Pitch inertia"},
|
||||||
|
z = {name = "Z Multiplier", description = "Yaw inertia"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fSeatOffsetDistX = {
|
||||||
|
name = "Seat X Offset",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = -2.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Driver seat left/right offset"
|
||||||
|
},
|
||||||
|
fSeatOffsetDistY = {
|
||||||
|
name = "Seat Y Offset",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = -2.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Driver seat front/back offset"
|
||||||
|
},
|
||||||
|
fSeatOffsetDistZ = {
|
||||||
|
name = "Seat Z Offset",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = -2.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Driver seat up/down offset"
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Transmission
|
||||||
|
fDriveBiasFront = {
|
||||||
|
name = "Drive Type",
|
||||||
|
type = "float",
|
||||||
|
change = 0.05,
|
||||||
|
min = 0.0,
|
||||||
|
max = 1.0,
|
||||||
|
description = "Drive type: 0.0 = RWD, 1.0 = FWD, 0.5 = balanced 4WD"
|
||||||
|
},
|
||||||
|
nInitialDriveGears = {
|
||||||
|
name = "Number of Gears",
|
||||||
|
type = "int",
|
||||||
|
change = 1,
|
||||||
|
min = 1,
|
||||||
|
max = 8,
|
||||||
|
description = "Number of forward gears in the transmission"
|
||||||
|
},
|
||||||
|
fInitialDriveForce = {
|
||||||
|
name = "Engine Power",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.01,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Engine power multiplier. Higher values increase acceleration."
|
||||||
|
},
|
||||||
|
fDriveInertia = {
|
||||||
|
name = "Engine Rev Speed",
|
||||||
|
type = "float",
|
||||||
|
change = 1,
|
||||||
|
min = 0.01,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Engine rev speed. Higher values make engine reach redline faster."
|
||||||
|
},
|
||||||
|
fClutchChangeRateScaleUpShift = {
|
||||||
|
name = "Upshift Speed",
|
||||||
|
type = "float",
|
||||||
|
change = 0.5,
|
||||||
|
min = 0.1,
|
||||||
|
max = 10.0,
|
||||||
|
description = "Upshift speed multiplier. Higher values = faster shifts."
|
||||||
|
},
|
||||||
|
fClutchChangeRateScaleDownShift = {
|
||||||
|
name = "Downshift Speed",
|
||||||
|
type = "float",
|
||||||
|
change = 0.5,
|
||||||
|
min = 0.1,
|
||||||
|
max = 10.0,
|
||||||
|
description = "Downshift speed multiplier. Higher values = faster shifts."
|
||||||
|
},
|
||||||
|
fInitialDriveMaxFlatVel = {
|
||||||
|
name = "Top Speed",
|
||||||
|
type = "float",
|
||||||
|
change = 5.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 500.0,
|
||||||
|
description = "Top speed at redline in highest gear (multiply by 0.82 for MPH)"
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Brakes
|
||||||
|
fBrakeForce = {
|
||||||
|
name = "Brake Power",
|
||||||
|
type = "float",
|
||||||
|
change = 0.2,
|
||||||
|
min = 0.01,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Brake power multiplier. Higher values increase braking force."
|
||||||
|
},
|
||||||
|
fBrakeBiasFront = {
|
||||||
|
name = "Brake Balance",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.0,
|
||||||
|
max = 1.0,
|
||||||
|
description = "Brake distribution: 0.0 = rear only, 1.0 = front only, 0.5 = balanced"
|
||||||
|
},
|
||||||
|
fHandBrakeForce = {
|
||||||
|
name = "Handbrake Power",
|
||||||
|
type = "float",
|
||||||
|
change = 0.2,
|
||||||
|
min = 0.0,
|
||||||
|
max = 5.0,
|
||||||
|
description = "Handbrake power multiplier. Higher values increase handbrake strength."
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Steering
|
||||||
|
fSteeringLock = {
|
||||||
|
name = "Steering Angle",
|
||||||
|
type = "float",
|
||||||
|
change = 5.0,
|
||||||
|
min = 10.0,
|
||||||
|
max = 70.0,
|
||||||
|
description = "Maximum steering angle. Higher values increase turn radius."
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Traction
|
||||||
|
fTractionCurveMax = {
|
||||||
|
name = "Cornering Grip",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.1,
|
||||||
|
max = 4.0,
|
||||||
|
description = "Maximum cornering grip multiplier"
|
||||||
|
},
|
||||||
|
fTractionCurveMin = {
|
||||||
|
name = "Acceleration Grip",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.1,
|
||||||
|
max = 4.0,
|
||||||
|
description = "Minimum acceleration/braking grip multiplier"
|
||||||
|
},
|
||||||
|
fTractionCurveLateral = {
|
||||||
|
name = "Lateral Grip",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 4.0,
|
||||||
|
description = "Lateral grip curve shape"
|
||||||
|
},
|
||||||
|
fTractionSpringDeltaMax = {
|
||||||
|
name = "Traction Height Loss",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = 0.0,
|
||||||
|
max = 0.3,
|
||||||
|
description = "Height at which vehicle loses traction"
|
||||||
|
},
|
||||||
|
fLowSpeedTractionLossMult = {
|
||||||
|
name = "Burnout Effect",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Low speed traction loss. Higher values increase burnout effect."
|
||||||
|
},
|
||||||
|
fCamberStiffnesss = {
|
||||||
|
name = "Drift Control",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = -1.0,
|
||||||
|
max = 1.0,
|
||||||
|
description = "Drift grip modifier. Positive values maintain drift angle, negative values cause oversteer."
|
||||||
|
},
|
||||||
|
fTractionBiasFront = {
|
||||||
|
name = "Traction Balance",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = 0.01,
|
||||||
|
max = 0.99,
|
||||||
|
description = "Traction distribution: 0.01 = rear bias, 0.99 = front bias, 0.5 = balanced"
|
||||||
|
},
|
||||||
|
fTractionLossMult = {
|
||||||
|
name = "Surface Grip Loss",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Surface traction loss multiplier. Higher values reduce grip on all surfaces."
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Suspension
|
||||||
|
fSuspensionForce = {
|
||||||
|
name = "Suspension Force",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.0,
|
||||||
|
max = 5.0,
|
||||||
|
description = "Suspension spring force"
|
||||||
|
},
|
||||||
|
fSuspensionCompDamp = {
|
||||||
|
name = "Compression Damping",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.0,
|
||||||
|
max = 5.0,
|
||||||
|
description = "Suspension compression damping"
|
||||||
|
},
|
||||||
|
fSuspensionReboundDamp = {
|
||||||
|
name = "Rebound Damping",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.0,
|
||||||
|
max = 5.0,
|
||||||
|
description = "Suspension rebound damping"
|
||||||
|
},
|
||||||
|
fSuspensionUpperLimit = {
|
||||||
|
name = "Upper Limit",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = 0.0,
|
||||||
|
max = 0.5,
|
||||||
|
description = "Suspension upper movement limit"
|
||||||
|
},
|
||||||
|
fSuspensionLowerLimit = {
|
||||||
|
name = "Lower Limit",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = -0.5,
|
||||||
|
max = 0.0,
|
||||||
|
description = "Suspension lower movement limit"
|
||||||
|
},
|
||||||
|
fSuspensionRaise = {
|
||||||
|
name = "Ride Height",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = -0.2,
|
||||||
|
max = 0.2,
|
||||||
|
description = "Vehicle ride height adjustment"
|
||||||
|
},
|
||||||
|
fSuspensionBiasFront = {
|
||||||
|
name = "Suspension Balance",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = 0.0,
|
||||||
|
max = 1.0,
|
||||||
|
description = "Suspension force distribution"
|
||||||
|
},
|
||||||
|
fAntiRollBarForce = {
|
||||||
|
name = "Anti-Roll Force",
|
||||||
|
type = "float",
|
||||||
|
change = 0.1,
|
||||||
|
min = 0.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Anti-roll bar force"
|
||||||
|
},
|
||||||
|
fAntiRollBarBiasFront = {
|
||||||
|
name = "Anti-Roll Balance",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = 0.0,
|
||||||
|
max = 1.0,
|
||||||
|
description = "Anti-roll bar force distribution"
|
||||||
|
},
|
||||||
|
fRollCentreHeightFront = {
|
||||||
|
name = "Front Roll Height",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = 0.0,
|
||||||
|
max = 1.0,
|
||||||
|
description = "Front roll center height"
|
||||||
|
},
|
||||||
|
fRollCentreHeightRear = {
|
||||||
|
name = "Rear Roll Height",
|
||||||
|
type = "float",
|
||||||
|
change = 0.01,
|
||||||
|
min = 0.0,
|
||||||
|
max = 1.0,
|
||||||
|
description = "Rear roll center height"
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Damage
|
||||||
|
fCollisionDamageMult = {
|
||||||
|
name = "Collision Damage",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Collision damage multiplier"
|
||||||
|
},
|
||||||
|
fWeaponDamageMult = {
|
||||||
|
name = "Weapon Damage",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Weapon damage multiplier"
|
||||||
|
},
|
||||||
|
fDeformationDamageMult = {
|
||||||
|
name = "Visual Damage",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Visual damage deformation multiplier"
|
||||||
|
},
|
||||||
|
fEngineDamageMult = {
|
||||||
|
name = "Engine Damage",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 2.0,
|
||||||
|
description = "Engine damage multiplier"
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Misc
|
||||||
|
fPetrolTankVolume = {
|
||||||
|
name = "Fuel Capacity",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 100.0,
|
||||||
|
description = "Fuel tank capacity"
|
||||||
|
},
|
||||||
|
fOilVolume = {
|
||||||
|
name = "Oil Capacity",
|
||||||
|
type = "float",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0.0,
|
||||||
|
max = 10.0,
|
||||||
|
description = "Engine oil capacity"
|
||||||
|
},
|
||||||
|
nMonetaryValue = {
|
||||||
|
name = "Vehicle Value",
|
||||||
|
type = "int",
|
||||||
|
change = 1.0,
|
||||||
|
min = 0,
|
||||||
|
max = 1000000,
|
||||||
|
description = "Vehicle monetary value"
|
||||||
|
},
|
||||||
|
strModelFlags = {
|
||||||
|
name = "Model Flags",
|
||||||
|
type = "string",
|
||||||
|
description = "Vehicle model flags"
|
||||||
|
},
|
||||||
|
strHandlingFlags = {
|
||||||
|
name = "Handling Flags",
|
||||||
|
type = "string",
|
||||||
|
description = "Vehicle handling flags"
|
||||||
|
},
|
||||||
|
strDamageFlags = {
|
||||||
|
name = "Damage Flags",
|
||||||
|
type = "string",
|
||||||
|
description = "Vehicle damage flags"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
fx_version 'cerulean'
|
||||||
|
game 'gta5'
|
||||||
|
|
||||||
|
lua54 'yes'
|
||||||
|
|
||||||
|
name 'jraxion_handlingeditor'
|
||||||
|
version '1.0.0'
|
||||||
|
description 'Handling Editor'
|
||||||
|
author 'JRaxion'
|
||||||
|
url 'https://jraxion.tebex.io/'
|
||||||
|
|
||||||
|
client_scripts {
|
||||||
|
'config.lua',
|
||||||
|
'client/client.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
server_scripts {
|
||||||
|
'config.lua',
|
||||||
|
'server/server.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_page 'html/index.html'
|
||||||
|
|
||||||
|
files {
|
||||||
|
'html/index.html',
|
||||||
|
'html/main.js',
|
||||||
|
'html/*.js',
|
||||||
|
|
||||||
|
'handling.meta',
|
||||||
|
}
|
||||||
|
|
||||||
|
data_file 'HANDLING_FILE' 'handling.meta'
|
||||||
|
|
||||||
|
escrow_ignore {
|
||||||
|
'config.lua',
|
||||||
|
'server/server.lua',
|
||||||
|
}
|
||||||
|
|
||||||
|
dependency '/assetpacks'
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<CHandlingDataMgr>
|
||||||
|
<HandlingData>
|
||||||
|
<Item type="CHandlingData">
|
||||||
|
<handlingName>MONSTER</handlingName>
|
||||||
|
<fMass value="4000.000000" />
|
||||||
|
<fInitialDragCoeff value="28.000000" />
|
||||||
|
<fPercentSubmerged value="85.000000" />
|
||||||
|
<vecCentreOfMassOffset x="0.000000" y="0.000000" z="0.000000" />
|
||||||
|
<vecInertiaMultiplier x="1.000000" y="1.000000" z="1.000000" />
|
||||||
|
<fDriveBiasFront value="0.200000" />
|
||||||
|
<nInitialDriveGears value="2" />
|
||||||
|
<fInitialDriveForce value="2.000000" />
|
||||||
|
<fDriveInertia value="2.000000" />
|
||||||
|
<fClutchChangeRateScaleUpShift value="10.000000" />
|
||||||
|
<fClutchChangeRateScaleDownShift value="9.541000" />
|
||||||
|
<fInitialDriveMaxFlatVel value="500.000000" />
|
||||||
|
<fBrakeForce value="0.650000" />
|
||||||
|
<fBrakeBiasFront value="0.650000" />
|
||||||
|
<fHandBrakeForce value="0.300000" />
|
||||||
|
<fSteeringLock value="26.000000" />
|
||||||
|
<fTractionCurveMax value="2.533300" />
|
||||||
|
<fTractionCurveMin value="3.517800" />
|
||||||
|
<fTractionCurveLateral value="3.340600" />
|
||||||
|
<fTractionSpringDeltaMax value="0.130000" />
|
||||||
|
<fLowSpeedTractionLossMult value="1.000000" />
|
||||||
|
<fCamberStiffnesss value="0.000000" />
|
||||||
|
<fTractionBiasFront value="0.510000" />
|
||||||
|
<fTractionLossMult value="0.400000" />
|
||||||
|
<fSuspensionForce value="2.300000" />
|
||||||
|
<fSuspensionCompDamp value="1.200000" />
|
||||||
|
<fSuspensionReboundDamp value="4.800000" />
|
||||||
|
<fSuspensionUpperLimit value="0.400000" />
|
||||||
|
<fSuspensionLowerLimit value="-0.200000" />
|
||||||
|
<fSuspensionRaise value="-0.050000" />
|
||||||
|
<fSuspensionBiasFront value="0.500000" />
|
||||||
|
<fAntiRollBarForce value="0.600000" />
|
||||||
|
<fAntiRollBarBiasFront value="0.500000" />
|
||||||
|
<fRollCentreHeightFront value="0.400000" />
|
||||||
|
<fRollCentreHeightRear value="0.390000" />
|
||||||
|
<fCollisionDamageMult value="1.000000" />
|
||||||
|
<fWeaponDamageMult value="1.000000" />
|
||||||
|
<fDeformationDamageMult value="0.800000" />
|
||||||
|
<fEngineDamageMult value="1.500000" />
|
||||||
|
<fPetrolTankVolume value="80.000000" />
|
||||||
|
<fOilVolume value="10.000000" />
|
||||||
|
<fSeatOffsetDistX value="0.000000" />
|
||||||
|
<fSeatOffsetDistY value="0.080000" />
|
||||||
|
<fSeatOffsetDistZ value="-0.200000" />
|
||||||
|
<nMonetaryValue value="500000" />
|
||||||
|
<strModelFlags>2224008</strModelFlags>
|
||||||
|
<strHandlingFlags>20568081</strHandlingFlags>
|
||||||
|
<strDamageFlags>20</strDamageFlags>
|
||||||
|
<SubHandlingData>
|
||||||
|
<Item type="" />
|
||||||
|
<Item type="" />
|
||||||
|
<Item type="" />
|
||||||
|
</SubHandlingData>
|
||||||
|
</Item>
|
||||||
|
</HandlingData>
|
||||||
|
</CHandlingDataMgr>
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>jr-handling</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--dark-bg: rgba(26, 26, 26, 0.95);
|
||||||
|
--darker-bg: rgba(20, 20, 20, 0.95);
|
||||||
|
--accent: #3498db;
|
||||||
|
--text: #ffffff;
|
||||||
|
--text-muted: #a0a0a0;
|
||||||
|
--border: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: none !important;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.handling-container {
|
||||||
|
background: none;
|
||||||
|
padding: 25px;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background-color: var(--darker-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header .btn {
|
||||||
|
margin: 0 8px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-bar {
|
||||||
|
padding: 1.5rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
background-color: var(--dark-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
color: var(--text);
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control:focus {
|
||||||
|
background-color: var(--dark-bg);
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: var(--text);
|
||||||
|
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.maxheight {
|
||||||
|
max-height: 70vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
color: var(--text);
|
||||||
|
border-color: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-dark {
|
||||||
|
background-color: var(--darker-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: var(--accent);
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: var(--dark-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-inner {
|
||||||
|
max-width: 300px;
|
||||||
|
text-align: left;
|
||||||
|
background-color: var(--darker-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: var(--dark-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-color: var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 2px solid var(--dark-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
#exportArea {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
margin-top: 15px;
|
||||||
|
display: none;
|
||||||
|
background-color: var(--dark-bg);
|
||||||
|
color: var(--text);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group > * {
|
||||||
|
border-radius: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
background-color: var(--dark-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
padding: 8px;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
color: var(--text);
|
||||||
|
padding: 8px 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item:hover {
|
||||||
|
background-color: var(--darker-bg);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item input[type="checkbox"] {
|
||||||
|
accent-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-dropdown {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-dropdown .btn {
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
background: var(--dark-bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag-dropdown .btn:hover,
|
||||||
|
.flag-dropdown .btn:focus {
|
||||||
|
background: var(--darker-bg);
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body data-bs-theme="dark">
|
||||||
|
<div class="modal modal-lg handling-container fade" id="open-handling-modal" tabindex="-1" aria-labelledby="handlingEditor" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="handlingLabel">XA21</h5>
|
||||||
|
<button type="button" class="btn btn-primary" onclick="exportHandling()">Export Handling</button>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="search-bar">
|
||||||
|
<input type="text" id="searchBar" class="form-control" placeholder="Search" onkeyup="searchVehicles()">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body maxheight">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered align-middle">
|
||||||
|
<thead class="table-dark">
|
||||||
|
<tr>
|
||||||
|
<th style="width: 40%">Name</th>
|
||||||
|
<th style="width: 30%">Original</th>
|
||||||
|
<th style="width: 30%">Current</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody id="handling-data-accordion">
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<textarea id="exportArea" class="form-control" readonly></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
<script defer src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,319 @@
|
|||||||
|
const modals = {
|
||||||
|
openhandlingModal: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
async function closeNUI() {
|
||||||
|
openhandlingModal.hide();
|
||||||
|
await fetch(`https://jraxion_handlingeditor/close`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json; charset=UTF-8",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleUIMessage(data) {
|
||||||
|
switch (data.type) {
|
||||||
|
case "openHandlingEditor":
|
||||||
|
openEditor(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log("No action received.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
window.addEventListener("message", (event) => handleUIMessage(event.data));
|
||||||
|
openhandlingModal = new bootstrap.Modal(document.getElementById("open-handling-modal"));
|
||||||
|
|
||||||
|
document.querySelectorAll(".modal").forEach((modal) => {
|
||||||
|
modal.addEventListener("hidden.bs.modal", closeNUI);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function(event) {
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
closeNUI();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateValue(input, change, key) {
|
||||||
|
let currentValue;
|
||||||
|
let newValue;
|
||||||
|
|
||||||
|
if (input.dataset.type === "string") {
|
||||||
|
currentValue = input.value;
|
||||||
|
newValue = currentValue;
|
||||||
|
} else {
|
||||||
|
currentValue = parseFloat(input.value) || 0;
|
||||||
|
newValue = currentValue + change;
|
||||||
|
|
||||||
|
const min = parseFloat(input.dataset.min);
|
||||||
|
const max = parseFloat(input.dataset.max);
|
||||||
|
|
||||||
|
newValue = Math.max(min, Math.min(max, newValue));
|
||||||
|
|
||||||
|
if (input.dataset.type === "int") {
|
||||||
|
newValue = Math.round(newValue);
|
||||||
|
} else if (input.dataset.type === "float") {
|
||||||
|
newValue = parseFloat(newValue.toFixed(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.value = newValue;
|
||||||
|
|
||||||
|
const slider = input.parentElement.querySelector('input[type="range"]');
|
||||||
|
if (slider) {
|
||||||
|
slider.value = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.post('https://jraxion_handlingeditor/updateHandling', JSON.stringify({
|
||||||
|
key: key,
|
||||||
|
value: newValue
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFlag(checkbox, flagType) {
|
||||||
|
const dropdownMenu = checkbox.closest('.dropdown-menu');
|
||||||
|
const allFlags = Array.from(dropdownMenu.querySelectorAll('input[type="checkbox"]'));
|
||||||
|
|
||||||
|
const flagValue = allFlags.reduce((acc, flag, index) => {
|
||||||
|
return acc + (flag.checked ? Math.pow(2, index) : 0);
|
||||||
|
}, 0).toString(16).toUpperCase();
|
||||||
|
|
||||||
|
$.post('https://jraxion_handlingeditor/updateHandling', JSON.stringify({
|
||||||
|
key: flagType,
|
||||||
|
value: flagValue
|
||||||
|
}));
|
||||||
|
|
||||||
|
const input = dropdownMenu.parentElement.previousElementSibling.querySelector('input[type="text"]');
|
||||||
|
input.value = flagValue;
|
||||||
|
|
||||||
|
const selectedCount = allFlags.filter(f => f.checked).length;
|
||||||
|
const dropdownButton = dropdownMenu.previousElementSibling;
|
||||||
|
dropdownButton.textContent = `Selected Flags (${selectedCount})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFromSlider(slider) {
|
||||||
|
const input = slider.parentElement.querySelector('input[type="text"]');
|
||||||
|
const key = input.dataset.handlingKey;
|
||||||
|
const newValue = parseFloat(slider.value);
|
||||||
|
|
||||||
|
if (input.dataset.type === "int") {
|
||||||
|
input.value = Math.round(newValue);
|
||||||
|
} else {
|
||||||
|
input.value = parseFloat(newValue.toFixed(6));
|
||||||
|
}
|
||||||
|
|
||||||
|
$.post('https://jraxion_handlingeditor/updateHandling', JSON.stringify({
|
||||||
|
key: key,
|
||||||
|
value: input.value
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportHandling() {
|
||||||
|
const vehicleName = document.querySelector("#handlingLabel").innerHTML;
|
||||||
|
const rows = document.getElementById('handling-data-accordion').getElementsByTagName('tr');
|
||||||
|
|
||||||
|
const xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>\n\n';
|
||||||
|
const xmlStart = '<CHandlingDataMgr>\n <HandlingData>\n <Item type="CHandlingData">\n';
|
||||||
|
const xmlEnd = ' </Item>\n </HandlingData>\n</CHandlingDataMgr>';
|
||||||
|
|
||||||
|
let xmlContent = ` <handlingName>${vehicleName}</handlingName>\n`;
|
||||||
|
|
||||||
|
const handlingValues = {};
|
||||||
|
|
||||||
|
Array.from(rows).forEach(row => {
|
||||||
|
const input = row.querySelector('input[type="text"]');
|
||||||
|
if (!input) return;
|
||||||
|
|
||||||
|
const key = input.dataset.handlingKey;
|
||||||
|
const value = input.value;
|
||||||
|
|
||||||
|
switch(input.dataset.type) {
|
||||||
|
case "float":
|
||||||
|
handlingValues[key] = parseFloat(value).toFixed(6);
|
||||||
|
break;
|
||||||
|
case "int":
|
||||||
|
handlingValues[key] = Math.round(value);
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
handlingValues[key] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
handlingValues['vecCentreOfMassOffset'] = '0.000000 0.000000 0.000000';
|
||||||
|
handlingValues['vecInertiaMultiplier'] = '1.000000 1.000000 1.000000';
|
||||||
|
|
||||||
|
const propertyOrder = [
|
||||||
|
'fMass', 'fInitialDragCoeff', 'fPercentSubmerged',
|
||||||
|
'vecCentreOfMassOffset', 'vecInertiaMultiplier', 'fDriveBiasFront',
|
||||||
|
'nInitialDriveGears', 'fInitialDriveForce', 'fDriveInertia',
|
||||||
|
'fClutchChangeRateScaleUpShift', 'fClutchChangeRateScaleDownShift',
|
||||||
|
'fInitialDriveMaxFlatVel', 'fBrakeForce', 'fBrakeBiasFront',
|
||||||
|
'fHandBrakeForce', 'fSteeringLock', 'fTractionCurveMax',
|
||||||
|
'fTractionCurveMin', 'fTractionCurveLateral', 'fTractionSpringDeltaMax',
|
||||||
|
'fLowSpeedTractionLossMult', 'fCamberStiffnesss', 'fTractionBiasFront',
|
||||||
|
'fTractionLossMult', 'fSuspensionForce', 'fSuspensionCompDamp',
|
||||||
|
'fSuspensionReboundDamp', 'fSuspensionUpperLimit', 'fSuspensionLowerLimit',
|
||||||
|
'fSuspensionRaise', 'fSuspensionBiasFront', 'fAntiRollBarForce',
|
||||||
|
'fAntiRollBarBiasFront', 'fRollCentreHeightFront', 'fRollCentreHeightRear',
|
||||||
|
'fCollisionDamageMult', 'fWeaponDamageMult', 'fDeformationDamageMult',
|
||||||
|
'fEngineDamageMult', 'fPetrolTankVolume', 'fOilVolume', 'fSeatOffsetDistX',
|
||||||
|
'fSeatOffsetDistY', 'fSeatOffsetDistZ', 'nMonetaryValue', 'strModelFlags',
|
||||||
|
'strHandlingFlags', 'strDamageFlags', 'AIHandling'
|
||||||
|
];
|
||||||
|
|
||||||
|
propertyOrder.forEach(key => {
|
||||||
|
if (handlingValues[key] !== undefined) {
|
||||||
|
if (key.startsWith('vec')) {
|
||||||
|
const [x, y, z] = handlingValues[key].split(' ');
|
||||||
|
xmlContent += ` <${key} x="${x}" y="${y}" z="${z}" />\n`;
|
||||||
|
} else if (key === 'strModelFlags' || key === 'strHandlingFlags' || key === 'strDamageFlags') {
|
||||||
|
xmlContent += ` <${key}>${parseInt(handlingValues[key]).toString(16).toUpperCase()}</${key}>\n`;
|
||||||
|
} else {
|
||||||
|
xmlContent += ` <${key} value="${handlingValues[key]}" />\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const subHandlingData = ` <SubHandlingData>
|
||||||
|
<Item type="" />
|
||||||
|
<Item type="" />
|
||||||
|
<Item type="" />
|
||||||
|
</SubHandlingData>\n`;
|
||||||
|
|
||||||
|
const finalXml = xmlHeader + xmlStart + xmlContent + subHandlingData + xmlEnd;
|
||||||
|
const exportArea = document.getElementById('exportArea');
|
||||||
|
exportArea.value = finalXml;
|
||||||
|
exportArea.style.display = 'block';
|
||||||
|
exportArea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
}
|
||||||
|
|
||||||
|
const flagDefinitions = {
|
||||||
|
strModelFlags: [
|
||||||
|
"IS_VAN", "IS_BUS", "IS_LOW", "IS_BIG", "ABS_STD", "ABS_OPTION",
|
||||||
|
"ABS_ALT_STD", "ABS_ALT_OPTION", "NO_DOORS", "TANDEM_SEATS",
|
||||||
|
"SIT_IN_BOAT", "HAS_TRACKS", "NO_EXHAUST", "DOUBLE_EXHAUST",
|
||||||
|
"NO1FPS_LOOK_BEHIND", "CAN_ENTER_IF_NO_DOOR", "AXLE_F_TORSION",
|
||||||
|
"AXLE_F_SOLID", "AXLE_F_MCPHERSON", "ATTACH_PED_TO_BODYSHELL",
|
||||||
|
"AXLE_R_TORSION", "AXLE_R_SOLID", "AXLE_R_MCPHERSON",
|
||||||
|
"DONT_FORCE_GRND_CLEARANCE", "DONT_RENDER_STEER", "NO_WHEEL_BURST",
|
||||||
|
"INDESTRUCTIBLE", "DOUBLE_FRONT_WHEELS", "FORCE_FRONT_WHEEL_WIDTH",
|
||||||
|
"FORCE_REAR_WHEEL_WIDTH"
|
||||||
|
],
|
||||||
|
strHandlingFlags: [
|
||||||
|
"SMOOTH_COMPRESN", "REDUCED_MOD_MASS", "DISTRIB_FRONT_MASS",
|
||||||
|
"DISTRIB_REAR_MASS", "OFFROAD_ABILITY", "OFFROAD_ABILITY2",
|
||||||
|
"HALOGEN_LIGHTS", "PROC_REARWHEEL_1ST", "USE_MAXSP_LIMIT",
|
||||||
|
"LOW_RIDER", "STREET_RACER", "SWINGING_CHASSIS", "EXTREME_GRIP",
|
||||||
|
"INCREASED_GRAVITY", "VERTICAL_FLIGHT_MODE", "DISABLE_GROUND_CLEARANCE",
|
||||||
|
"RACING_HANDLING", "EMERGENCY_VEHICLE", "NO_HANDBRAKE",
|
||||||
|
"CVT", "ALT_EXT_WHEEL_BOUNDS_BEH", "DONT_RAISE_BOUNDS_AT_SPEED",
|
||||||
|
"NARROW_BOUNDS", "MEDIUM_BOUNDS", "WIDE_BOUNDS"
|
||||||
|
],
|
||||||
|
strDamageFlags: [
|
||||||
|
"DRIVER_SIDE_FRONT_DOOR", "DRIVER_SIDE_REAR_DOOR", "DRIVER_PASSENGER_SIDE_FRONT_DOOR",
|
||||||
|
"DRIVER_PASSENGER_SIDE_REAR_DOOR", "BONNET", "BOOT", "DRIVER_SIDE_FRONT_WINDOW",
|
||||||
|
"DRIVER_SIDE_REAR_WINDOW", "PASSENGER_SIDE_FRONT_WINDOW", "PASSENGER_SIDE_REAR_WINDOW",
|
||||||
|
"WINDSCREEN", "ENGINE", "ALL_WHEELS", "PETROL_TANK", "DOORS", "TRUNK", "WINDOWS",
|
||||||
|
"ALL_PANELS", "WHEELS", "EXHAUST", "RADIATOR", "SUSPENSION", "BRAKES", "GEARBOX",
|
||||||
|
"STEERING", "HEADLIGHTS", "TAILLIGHTS", "INDICATORS", "WIPERS", "MIRRORS"
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
function openEditor(data) {
|
||||||
|
document.querySelector("#handlingLabel").innerHTML = data.vehicleName;
|
||||||
|
let accordionContent = "";
|
||||||
|
|
||||||
|
const sortedEntries = Object.entries(data.data).sort((a, b) => a[0].localeCompare(b[0]));
|
||||||
|
|
||||||
|
for (let [i, dd] of sortedEntries) {
|
||||||
|
if (i.startsWith('vec')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isNumeric = dd.type === "float" || dd.type === "int";
|
||||||
|
const isFlag = i === "strModelFlags" || i === "strHandlingFlags" || i === "strDamageFlags";
|
||||||
|
|
||||||
|
accordionContent += `
|
||||||
|
<tr>
|
||||||
|
<td>${dd.name}
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="${dd.description}">
|
||||||
|
i
|
||||||
|
</button>
|
||||||
|
${isNumeric ? `<small class="d-block text-muted">Min: ${dd.min} | Max: ${dd.max}</small>` : ''}
|
||||||
|
</td>
|
||||||
|
<td>${data.originalvalues[i]}</td>
|
||||||
|
<td>
|
||||||
|
<div class="input-group">
|
||||||
|
${isNumeric ? `<button class="btn btn-outline-secondary" type="button" onclick="updateValue(this.parentElement.querySelector('input[type=text]'), -${dd.change}, '${i}')">-</button>` : ''}
|
||||||
|
<input type="text"
|
||||||
|
class="form-control"
|
||||||
|
value="${data.values[i]}"
|
||||||
|
data-min="${dd.min || 0}"
|
||||||
|
data-max="${dd.max || 0}"
|
||||||
|
data-type="${dd.type}"
|
||||||
|
data-handling-key="${i}"
|
||||||
|
onchange="updateValue(this, 0, '${i}')"
|
||||||
|
>
|
||||||
|
${isNumeric ? `<button class="btn btn-outline-secondary" type="button" onclick="updateValue(this.parentElement.querySelector('input[type=text]'), ${dd.change}, '${i}')">+</button>` : ''}
|
||||||
|
${isNumeric && !isFlag ? `
|
||||||
|
<input type="range"
|
||||||
|
class="form-range"
|
||||||
|
min="${dd.min}"
|
||||||
|
max="${dd.max}"
|
||||||
|
step="${dd.type === 'int' ? '1' : '0.000001'}"
|
||||||
|
value="${data.values[i]}"
|
||||||
|
oninput="updateFromSlider(this)"
|
||||||
|
>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
|
${isFlag ? `
|
||||||
|
<div class="flag-dropdown dropdown">
|
||||||
|
<button class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
Selected Flags (${(parseInt(data.values[i], 16).toString(2).match(/1/g) || []).length})
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu">
|
||||||
|
${flagDefinitions[i].map((flag, index) => `
|
||||||
|
<div class="dropdown-item">
|
||||||
|
<input type="checkbox"
|
||||||
|
id="${i}_${index}"
|
||||||
|
${(parseInt(data.values[i], 16) & (1 << index)) ? 'checked' : ''}
|
||||||
|
onchange="updateFlag(this, '${i}')"
|
||||||
|
>
|
||||||
|
<label for="${i}_${index}">${flag}</label>
|
||||||
|
</div>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector("#handling-data-accordion").innerHTML = accordionContent;
|
||||||
|
|
||||||
|
openhandlingModal.show();
|
||||||
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||||
|
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchVehicles() {
|
||||||
|
const searchInput = document.getElementById('searchBar').value.toLowerCase();
|
||||||
|
const rows = document.getElementById('handling-data-accordion').getElementsByTagName('tr');
|
||||||
|
|
||||||
|
for (let row of rows) {
|
||||||
|
const vehicleName = row.getElementsByTagName('td')[0].textContent.toLowerCase();
|
||||||
|
if (vehicleName.includes(searchInput)) {
|
||||||
|
row.style.display = '';
|
||||||
|
} else {
|
||||||
|
row.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
while GetCurrentResourceName() ~= "jraxion_handlingeditor" do
|
||||||
|
Wait(2000)
|
||||||
|
print("Make sure the resource name is jraxion_handlingeditor, it will break the resource if you rename it.")
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterCommand('handlingeditor', function(source, args, rawCommand)
|
||||||
|
-- Add your permission system here.
|
||||||
|
|
||||||
|
if Config.isAllowed(source) then
|
||||||
|
TriggerClientEvent('jraxion_handlingeditor:openHandlingEditor', source)
|
||||||
|
else
|
||||||
|
print('No permission')
|
||||||
|
end
|
||||||
|
end, false)
|
||||||
Reference in New Issue
Block a user