fixing ulc script

This commit is contained in:
KingMcDonalds
2025-01-28 07:05:49 -08:00
parent f7a4525aa2
commit 057134bdfb
51 changed files with 4497 additions and 17 deletions
+56
View File
@@ -0,0 +1,56 @@
--[[
Ultimate Lighting Controller Config
the ULC resource is required to use this configuration
get the resource here: https://github.com/Flohhhhh/ultimate-lighting-controller/releases/latest
To learn how to setup and use ULC visit here: https://docs.dwnstr.com/ulc/overview
]]
return {names = {"24ramambo"},
steadyBurnConfig = {
forceOn = false, useTime = false,
disableWithLights = false,
sbExtras = {}
},
parkConfig = {
usePark = true,
useSync = true,
syncWith = {"615", "376", "gpd7", "640", "128", "704", "st23tahoe", "24sub", "24ramambo", "23sierrafire", "23gmcleoslick", "23gmcleo", "ccso1", "gpdchief1" },
pExtras = {10},
dExtras = {11}
},
hornConfig = {
useHorn = false,
hornExtras = {},
},
brakeConfig = {
useBrakes = false,
speedThreshold = 3,
brakeExtras = {},
disableExtras = {}
},
reverseConfig = {
useReverse = false,
reverseExtras = {}
},
doorConfig = {
useDoors = false,
driverSide = {enable = {}, disable = {}},
passSide = {enable = {}, disable = {}},
trunk = {enable ={}, disable = {}}
},
buttons = {
{label = "Stage 1", key = 1, color = "red", extra = 2, linkedExtras = {2}, oppositeExtras = {}, offExtras = {1}, repair = false},
{label = "Stage 2", key = 2, color = "red", extra = 1, linkedExtras = {1}, oppositeExtras = {}, offExtras = {2}, repair = false},
{label = "Cruise", key = 3, color = "red", extra = 3, linkedExtras = {3}, oppositeExtras = {}, offExtras = {2,1,4,5,6}, repair = false},
{label = "TKDN", key = 4, color = "red", extra = 4, linkedExtras = {4}, oppositeExtras = {}, offExtras = {3,2,1,5,6}, repair = false},
{label = "<-", key = 5, color = "amber", extra = 5, linkedExtras = {5}, oppositeExtras = {}, offExtras = {6}, repair = false},
{label = "->", key = 6, color = "amber", extra = 6, linkedExtras = {6}, oppositeExtras = {}, offExtras = {5}, repair = false}
},
defaultStages = {
useDefaults = false,
enableKeys = {},
disableKeys = {}
}
}
+3 -3
View File
@@ -15,9 +15,9 @@ return {names = {"24sub"},
parkConfig = {
usePark = true,
useSync = true,
syncWith = {},
pExtras = {2},
dExtras = {1}
syncWith = {"615", "376", "gpd7", "640", "128", "704", "st23tahoe", "24sub", "24ramambo", "23sierrafire", "23gmcleoslick", "23gmcleo", "ccso1", "gpdchief1" },
pExtras = {10},
dExtras = {11}
},
hornConfig = {
useHorn = false,
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<CVehicleModelInfoVariation>
<variationData>
<Item>
<modelName>ccso1</modelName>
<colors>
<Item>
<indices content="char_array">
0
134
0
64
64
64
64
</indices>
<liveries>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
<Item value="false"/>
</liveries>
</Item>
</colors>
<kits>
<Item>0_default_modkit</Item>
</kits>
<windowsWithExposedEdges/>
<plateProbabilities>
<Probabilities>
<Item>
<Name>Police guv plate</Name>
<Value value="100"/>
</Item>
</Probabilities>
</plateProbabilities>
<lightSettings value="1649874"/>
<sirenSettings value="46546544"/>
</Item>
</variationData>
</CVehicleModelInfoVariation>
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<CHandlingDataMgr>
<HandlingData>
<Item type="CHandlingData">
<handlingName>FUCKASSEXPLORER1</handlingName>
<fMass value="2004.000000" />
<fInitialDragCoeff value="5.900000" />
<fPercentSubmerged value="85.000000" />
<vecCentreOfMassOffset x="0.000000" y="-0.100000" z="0.000000" />
<vecInertiaMultiplier x="1.000000" y="1.000000" z="1.200000" />
<fDriveBiasFront value="0.500000" />
<nInitialDriveGears value="10" />
<fInitialDriveForce value="0.400000" />
<fDriveInertia value="1.000000" />
<fClutchChangeRateScaleUpShift value="2.000000" />
<fClutchChangeRateScaleDownShift value="2.000000" />
<fInitialDriveMaxFlatVel value="185.000000" />
<fBrakeForce value="1.400000" />
<fBrakeBiasFront value="0.650000" />
<fHandBrakeForce value="0.800000" />
<fSteeringLock value="40.000000" />
<fTractionCurveMax value="2.800000" />
<fTractionCurveMin value="2.300000" />
<fTractionCurveLateral value="22.500000" />
<fTractionSpringDeltaMax value="0.150000" />
<fLowSpeedTractionLossMult value="1.000000" />
<fCamberStiffnesss value="0.000000" />
<fTractionBiasFront value="0.480000" />
<fTractionLossMult value="1.000000" />
<fSuspensionForce value="2.500000" />
<fSuspensionCompDamp value="1.400000" />
<fSuspensionReboundDamp value="1.800000" />
<fSuspensionUpperLimit value="0.120000" />
<fSuspensionLowerLimit value="-0.130000" />
<fSuspensionRaise value="0.000000" />
<fSuspensionBiasFront value="0.500000" />
<fAntiRollBarForce value="0.900000" />
<fAntiRollBarBiasFront value="0.550000" />
<fRollCentreHeightFront value="0.400000" />
<fRollCentreHeightRear value="0.400000" />
<fCollisionDamageMult value="0.700000" />
<fWeaponDamageMult value="1.000000" />
<fDeformationDamageMult value="0.800000" />
<fEngineDamageMult value="1.200000" />
<fPetrolTankVolume value="65.000000" />
<fOilVolume value="5.000000" />
<fSeatOffsetDistX value="0.000000" />
<fSeatOffsetDistY value="0.000000" />
<fSeatOffsetDistZ value="0.000000" />
<nMonetaryValue value="35000" />
<strModelFlags>440010</strModelFlags>
<strHandlingFlags>0</strHandlingFlags>
<strDamageFlags>0</strDamageFlags>
<AIHandling>AVERAGE</AIHandling>
<SubHandlingData>
<Item type="CCarHandlingData">
<fBackEndPopUpCarImpulseMult value="0.100000" />
<fBackEndPopUpBuildingImpulseMult value="0.030000" />
<fBackEndPopUpMaxDeltaSpeed value="0.600000" />
</Item>
<Item type="NULL" />
<Item type="NULL" />
</SubHandlingData>
</Item>
</HandlingData>
</CHandlingDataMgr>
@@ -0,0 +1,59 @@
--[[
Ultimate Lighting Controller Config
the ULC resource is required to use this configuration
get the resource here: https://github.com/Flohhhhh/ultimate-lighting-controller/releases/latest
To learn how to setup and use ULC visit here: https://docs.dwnstr.com/ulc/overview
]]
return {names = {"ccso1"},
steadyBurnConfig = {
forceOn = false, useTime = false,
disableWithLights = false,
sbExtras = {}
},
parkConfig = {
usePark = true,
useSync = true,
syncWith = {"ccso1, "615", "376", "gpd7", "640", "128", "704", "st23tahoe", "24sub", "24ramambo","ccso1", "gpdchief1",},
pExtras = {1,2},
dExtras = {3,4,10}
},
hornConfig = {
useHorn = false,
hornExtras = {},
disableExtras = {}
},
brakeConfig = {
useBrakes = false,
speedThreshold = 3,
brakeExtras = {},
disableExtras = {}
},
reverseConfig = {
useReverse = false,
reverseExtras = {},
disableExtras = {}
},
doorConfig = {
useDoors = false,
driverSide = {enable = {}, disable = {}},
passSide = {enable = {}, disable = {}},
trunk = {enable ={}, disable = {}}
},
buttons = {
{label = "Park", key = 1, color = "green", extra = 1, linkedExtras = {2}, oppositeExtras = {}, offExtras = {3,4,5,6}, repair = false},
{label = "Drive", key = 2, color = "green", extra = 3, linkedExtras = {4}, oppositeExtras = {}, offExtras = {1,2,6,5}, repair = false},
{label = "Takedowns", key = 3, color = "green", extra = 5, linkedExtras = {}, oppositeExtras = {}, offExtras = {3}, repair = false},
{label = "Cruise", key = 4, color = "green", extra = 6, linkedExtras = {7,8,9}, oppositeExtras = {}, offExtras = {}, repair = false}
},
stages = {
useStages = false,
stageKeys = {},
},
defaultStages = {
useDefaults = false,
enableKeys = {},
disableKeys = {}
}
}
@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<CVehicleModelInfo__InitDataList>
<residentTxd>vehshare</residentTxd>
<residentAnims />
<InitDatas>
<Item>
<modelName>ccso1</modelName>
<txdName>ccso1</txdName>
<handlingId>FUCKASSEXPLORER1</handlingId>
<gameName>CODE3</gameName>
<vehicleMakeName />
<expressionDictName>null</expressionDictName>
<expressionName>null</expressionName>
<animConvRoofDictName>null</animConvRoofDictName>
<animConvRoofName>null</animConvRoofName>
<animConvRoofWindowsAffected />
<ptfxAssetName>null</ptfxAssetName>
<audioNameHash>ecoboostv6</audioNameHash>
<layout>LAYOUT_STD_EXITFIXUP</layout>
<coverBoundOffsets>POLICE3_COVER_OFFSET_INFO</coverBoundOffsets>
<explosionInfo>EXPLOSION_INFO_DEFAULT</explosionInfo>
<scenarioLayout />
<cameraName>DEFAULT_FOLLOW_VEHICLE_CAMERA</cameraName>
<aimCameraName>MID_BOX_VEHICLE_AIM_CAMERA</aimCameraName>
<bonnetCameraName>VEHICLE_BONNET_CAMERA_MID_NEAR</bonnetCameraName>
<povCameraName>DEFAULT_POV_CAMERA</povCameraName>
<FirstPersonDriveByIKOffset x="0.000000" y="-0.060000" z="-0.030000" />
<FirstPersonDriveByUnarmedIKOffset x="0.000000" y="0.000000" z="-0.020000" />
<FirstPersonProjectileDriveByIKOffset x="0.055000" y="-0.075000" z="-0.045000" />
<FirstPersonProjectileDriveByPassengerIKOffset x="-0.055000" y="-0.075000" z="-0.045000" />
<FirstPersonProjectileDriveByRearLeftIKOffset x="0.000000" y="0.000000" z="0.000000" />
<FirstPersonProjectileDriveByRearRightIKOffset x="0.000000" y="0.000000" z="0.000000" />
<FirstPersonDriveByLeftPassengerIKOffset x="0.000000" y="0.000000" z="0.000000" />
<FirstPersonDriveByRightPassengerIKOffset x="0.000000" y="-0.060000" z="-0.030000" />
<FirstPersonDriveByRightRearPassengerIKOffset x="0.000000" y="0.000000" z="0.000000" />
<FirstPersonDriveByLeftPassengerUnarmedIKOffset x="0.000000" y="0.000000" z="0.000000" />
<FirstPersonDriveByRightPassengerUnarmedIKOffset x="0.000000" y="0.000000" z="0.000000" />
<FirstPersonMobilePhoneOffset x="0.130000" y="0.275000" z="0.530000" />
<FirstPersonPassengerMobilePhoneOffset x="0.136000" y="0.223000" z="0.425000" />
<FirstPersonMobilePhoneSeatIKOffset>
<Item>
<Offset x="0.136000" y="0.156000" z="0.445000" />
<SeatIndex value="2" />
</Item>
<Item>
<Offset x="0.136000" y="0.156000" z="0.445000" />
<SeatIndex value="3" />
</Item>
</FirstPersonMobilePhoneSeatIKOffset>
<PovCameraOffset x="0.000000" y="-0.175000" z="0.675000" />
<PovCameraVerticalAdjustmentForRollCage value="0.000000" />
<PovPassengerCameraOffset x="0.000000" y="0.000000" z="0.000000" />
<PovRearPassengerCameraOffset x="0.000000" y="0.000000" z="0.000000" />
<vfxInfoName>VFXVEHICLEINFO_CAR_GENERIC</vfxInfoName>
<shouldUseCinematicViewMode value="true" />
<shouldCameraTransitionOnClimbUpDown value="false" />
<shouldCameraIgnoreExiting value="false" />
<AllowPretendOccupants value="true" />
<AllowJoyriding value="false" />
<AllowSundayDriving value="false" />
<AllowBodyColorMapping value="false" />
<wheelScale value="0.244000" />
<wheelScaleRear value="0.244000" />
<dirtLevelMin value="0.000000" />
<dirtLevelMax value="0.300000" />
<envEffScaleMin value="0.000000" />
<envEffScaleMax value="1.000000" />
<envEffScaleMin2 value="0.000000" />
<envEffScaleMax2 value="1.000000" />
<damageMapScale value="0.600000" />
<damageOffsetScale value="1.000000" />
<diffuseTint value="0x00FFFFFF" />
<steerWheelMult value="1.000000" />
<HDTextureDist value="5.000000" />
<lodDistances content="float_array">
35.000000
55.000000
70.000000
140.000000
500.000000
500.000000
</lodDistances>
<minSeatHeight value="0.83" />
<identicalModelSpawnDistance value="20" />
<maxNumOfSameColor value="10" />
<defaultBodyHealth value="1000.000000" />
<pretendOccupantsScale value="1.000000" />
<visibleSpawnDistScale value="1.000000" />
<trackerPathWidth value="2.000000" />
<weaponForceMult value="1.000000" />
<frequency value="100" />
<swankness>SWANKNESS_0</swankness>
<maxNum value="2" />
<flags>FLAG_EXTRAS_STRONG FLAG_HAS_LIVERY FLAG_EXTRAS_ALL FLAG_LAW_ENFORCEMENT FLAG_EMERGENCY_SERVICE FLAG_NO_RESPRAY FLAG_DONT_SPAWN_IN_CARGEN FLAG_HAS_INTERIOR_EXTRAS FLAG_REPORT_CRIME_IF_STANDING_ON</flags>
<type>VEHICLE_TYPE_CAR</type>
<plateType>VPT_BACK_PLATES</plateType>
<dashboardType>VDT_FEROCI</dashboardType>
<vehicleClass>VC_EMERGENCY</vehicleClass>
<wheelType>VWT_SPORT</wheelType>
<trailers />
<additionalTrailers />
<drivers>
<Item>
<driverName>S_M_Y_Cop_01</driverName>
<npcName />
</Item>
</drivers>
<extraIncludes />
<doorsWithCollisionWhenClosed />
<driveableDoors />
<bumpersNeedToCollideWithMap value="false" />
<needsRopeTexture value="false" />
<requiredExtras />
<rewards>
<Item>REWARD_WEAPON_PUMPSHOTGUN</Item>
<Item>REWARD_AMMO_PUMPSHOTGUN_ENTER_VEHICLE</Item>
<Item>REWARD_STAT_WEAPON</Item>
</rewards>
<cinematicPartCamera>
<Item>WHEEL_FRONT_RIGHT_CAMERA</Item>
<Item>WHEEL_FRONT_LEFT_CAMERA</Item>
<Item>WHEEL_REAR_RIGHT_CAMERA</Item>
<Item>WHEEL_REAR_LEFT_CAMERA</Item>
</cinematicPartCamera>
<NmBraceOverrideSet />
<buoyancySphereOffset x="0.000000" y="0.000000" z="0.000000" />
<buoyancySphereSizeScale value="1.000000" />
<pOverrideRagdollThreshold type="NULL" />
<firstPersonDrivebyData>
<Item>STD_POLICE3_FRONT_LEFT</Item>
<Item>STD_POLICE3_FRONT_RIGHT</Item>
<Item>STD_POLICE2_REAR_LEFT</Item>
<Item>STD_POLICE2_REAR_RIGHT</Item>
</firstPersonDrivebyData>
</Item>
</InitDatas>
<txdRelationships>
<Item>
<parent>vehicles_feroci_interior</parent>
<child>FPIUK</child>
</Item>
</txdRelationships>
</CVehicleModelInfo__InitDataList>
Binary file not shown.
Binary file not shown.
@@ -14,10 +14,10 @@ return {names = {"st23tahoe"},
},
parkConfig = {
usePark = true,
useSync = false,
syncWith = {},
pExtras = {4},
dExtras = {3,5}
useSync = true,
syncWith = {"615", "376", "gpd7", "640", "128", "704", "st23tahoe", "24sub", "24ramambo", "23sierrafire", "23gmcleoslick", "23gmcleo", "ccso1", "gpdchief1" },
pExtras = {11},
dExtras = {10,15}
},
hornConfig = {
useHorn = false,
@@ -0,0 +1,60 @@
--[[
Ultimate Lighting Controller Config
the ULC resource is required to use this configuration
get the resource here: https://github.com/Flohhhhh/ultimate-lighting-controller/releases/latest
To learn how to setup and use ULC visit here: https://docs.dwnstr.com/ulc/overview
]]
return {names = {"128"},
steadyBurnConfig = {
forceOn = false, useTime = false,
disableWithLights = false,
sbExtras = {}
},
parkConfig = {
usePark = true,
useSync = true,
syncWith = {"615", "376", "gpd7", "640", "128", "704", "st23tahoe", "24sub", "24ramambo", "23sierrafire", "23gmcleoslick", "23gmcleo", "ccso1", "gpdchief1" },
pExtras = {11},
dExtras = {10}
},
hornConfig = {
useHorn = false,
hornExtras = {},
disableExtras = {}
},
brakeConfig = {
useBrakes = false,
speedThreshold = 3,
brakeExtras = {},
disableExtras = {}
},
reverseConfig = {
useReverse = false,
reverseExtras = {},
disableExtras = {}
},
doorConfig = {
useDoors = false,
driverSide = {enable = {}, disable = {}},
passSide = {enable = {}, disable = {}},
trunk = {enable ={}, disable = {}}
},
buttons = {
{label = "GSP Cover", key = 1, color = "green", extra = 1, linkedExtras = {}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Park Lights", key = 2, color = "green", extra = 2, linkedExtras = {3,4,5}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Drive Lights", key = 3, color = "green", extra = 6, linkedExtras = {7}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Cruise Lights", key = 4, color = "green", extra = 8, linkedExtras = {9,10,11}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Flood Lights", key = 5, color = "green", extra = 12, linkedExtras = {}, oppositeExtras = {}, offExtras = {}, repair = false}
},
stages = {
useStages = false,
stageKeys = {},
},
defaultStages = {
useDefaults = false,
enableKeys = {},
disableKeys = {}
}
}
@@ -0,0 +1,51 @@
--[[
Ultimate Lighting Controller Config
the ULC resource is required to use this configuration
get the resource here: https://github.com/Flohhhhh/ultimate-lighting-controller/releases/latest
To learn how to setup and use ULC visit here: https://docs.dwnstr.com/ulc/overview
]]
return {names = {"640"},
steadyBurnConfig = {
forceOn = false, useTime = false,
disableWithLights = false,
sbExtras = {}
},
parkConfig = {
usePark = true,
useSync = true,
syncWith = {"615", "376", "gpd7", "640", "128", "704", "st23tahoe", "24sub", "24ramambo", "23sierrafire", "23gmcleoslick", "23gmcleo", "ccso1", "gpdchief1" },
pExtras = {10},
dExtras = {11}
},
hornConfig = {
useHorn = true,
hornExtras = {12},
},
brakeConfig = {
useBrakes = true,
speedThreshold = 3,
brakeExtras = {7},
disableExtras = {}
},
reverseConfig = {
useReverse = false,
reverseExtras = {}
},
doorConfig = {
useDoors = true,
driverSide = {enable = {}, disable = {5}},
passSide = {enable = {}, disable = {6}},
trunk = {enable ={}, disable = {}}
},
buttons = {
{label = "Main Lights", key = 1, color = "green", extra = 1, linkedExtras = {}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Cruise Lights", key = 2, color = "green", extra = 3, linkedExtras = {}, oppositeExtras = {}, offExtras = {}, repair = false}
},
defaultStages = {
useDefaults = false,
enableKeys = {},
disableKeys = {}
}
}
@@ -0,0 +1,60 @@
--[[
Ultimate Lighting Controller Config
the ULC resource is required to use this configuration
get the resource here: https://github.com/Flohhhhh/ultimate-lighting-controller/releases/latest
To learn how to setup and use ULC visit here: https://docs.dwnstr.com/ulc/overview
]]
return {names = {"704"},
steadyBurnConfig = {
forceOn = false, useTime = false,
disableWithLights = false,
sbExtras = {}
},
parkConfig = {
usePark = false,
useSync = false,
syncWith = {"615", "376", "gpd7", "640", "128", "704", "st23tahoe", "24sub", "24ramambo", "23sierrafire", "23gmcleoslick", "23gmcleo", "ccso1", "gpdchief1" },
pExtras = {10},
dExtras = {11}
},
hornConfig = {
useHorn = false,
hornExtras = {},
disableExtras = {}
},
brakeConfig = {
useBrakes = false,
speedThreshold = 3,
brakeExtras = {},
disableExtras = {}
},
reverseConfig = {
useReverse = false,
reverseExtras = {},
disableExtras = {}
},
doorConfig = {
useDoors = false,
driverSide = {enable = {}, disable = {}},
passSide = {enable = {}, disable = {}},
trunk = {enable ={}, disable = {}}
},
buttons = {
{label = "GSP Cover", key = 1, color = "green", extra = 1, linkedExtras = {}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Park Lights", key = 2, color = "green", extra = 2, linkedExtras = {3,4,5}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Drive Lights", key = 3, color = "green", extra = 6, linkedExtras = {7}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Cruise Lights", key = 4, color = "green", extra = 8, linkedExtras = {9,10,11}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Flood Lights", key = 5, color = "green", extra = 12, linkedExtras = {}, oppositeExtras = {}, offExtras = {}, repair = false}
},
stages = {
useStages = false,
stageKeys = {},
},
defaultStages = {
useDefaults = false,
enableKeys = {},
disableKeys = {}
}
}
@@ -0,0 +1,60 @@
--[[
Ultimate Lighting Controller Config
the ULC resource is required to use this configuration
get the resource here: https://github.com/Flohhhhh/ultimate-lighting-controller/releases/latest
To learn how to setup and use ULC visit here: https://docs.dwnstr.com/ulc/overview
]]
return {names = {"gpd7"},
steadyBurnConfig = {
forceOn = false, useTime = false,
disableWithLights = false,
sbExtras = {}
},
parkConfig = {
usePark = true,
useSync = true,
syncWith = {"615", "376", "gpd7", "640", "128", "704", "st23tahoe", "24sub", "24ramambo", "23sierrafire", "23gmcleoslick", "23gmcleo", "ccso1", "gpdchief1" },
pExtras = {11},
dExtras = {10}
},
hornConfig = {
useHorn = false,
hornExtras = {},
disableExtras = {}
},
brakeConfig = {
useBrakes = false,
speedThreshold = 3,
brakeExtras = {},
disableExtras = {}
},
reverseConfig = {
useReverse = false,
reverseExtras = {},
disableExtras = {}
},
doorConfig = {
useDoors = false,
driverSide = {enable = {}, disable = {}},
passSide = {enable = {}, disable = {}},
trunk = {enable ={}, disable = {}}
},
buttons = {
{label = "Front", key = 1, color = "green", extra = 1, linkedExtras = {}, oppositeExtras = {}, offExtras = {6,7}, repair = false},
{label = "Front White", key = 2, color = "green", extra = 2, linkedExtras = {}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Rear", key = 3, color = "green", extra = 3, linkedExtras = {4}, oppositeExtras = {}, offExtras = {}, repair = false},
{label = "Takedowns", key = 4, color = "green", extra = 5, linkedExtras = {}, oppositeExtras = {}, offExtras = {1,2}, repair = false},
{label = "Cruise", key = 5, color = "green", extra = 6, linkedExtras = {7}, oppositeExtras = {}, offExtras = {}, repair = false}
},
stages = {
useStages = false,
stageKeys = {},
},
defaultStages = {
useDefaults = false,
enableKeys = {},
disableKeys = {}
}
}
+38
View File
@@ -0,0 +1,38 @@
-------------------------
--------- SOUND ---------
-------------------------
function PlayBeep(highPitched)
if highPitched then
PlaySoundFrontend(-1, "5_SEC_WARNING", "HUD_MINI_GAME_SOUNDSET", 1)
else
PlaySoundFrontend(-1, "Beep_Red", "DLC_HEIST_HACKING_SNAKE_SOUNDS", 1)
end
end
--[[
coming soon, once client options arrive it will be opt in per client
---------------
-- REMINDERS --
---------------
local mute = false
if Config.reminderBeeps then
CreateThread(function()
while true do Wait(Config.reminderBeepTime * 1000)
if Lights and not mute then PlayBeep(false) end
end
end)
end
RegisterCommand('mutelights', function()
mute = not mute
if mute then
print("Lighting reminders muted.")
else
print("Lighting reminders unmuted.")
end
end)
]]
+114
View File
@@ -0,0 +1,114 @@
local rblIntegration = false
function ULC:SetBlackout(newState)
--print("Setting blackout to " .. newState)
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if newState == 0 then
-- do blackout stuff
-- turn off headlights
SetVehicleLights(vehicle, 1)
-- turn off emergency lights
SetVehicleSiren(vehicle, false)
-- turn off specified blackout extras?
-- might need to just make a blackout file and config section, i think this can work when brake patterns aren't being used?
-- turn off cruise lights (do in c_cruise.lua)
-- if lights are turned on with q, or h, or a button is pressed, cancel effect, not sure how to do this.
-- when these actions are done check [if Entity(GetVehiclePedIsIn(PlayerPedId())).state.rbl_blackout or ulc_blackout] <- depending on if these can be accessed when not defined, may have to just use a static global variable in here.
-- if rbl is not loaded, start checking if vehicle is moving to disable blackout, rbl handles this itself if loaded
if not rblIntegration then
CreateThread(function()
while true do Wait(500)
if Entity(vehicle).state.ulc_blackout == 1 then ULC:SetBlackout(1) return end
local speed = GetEntitySpeed(vehicle) * 2.236936
--print("Speed is " .. speed)
if speed > 5 then ULC:SetBlackout(1) return end
end
end)
end
elseif newState == 1 then
-- do undo blackout stuff
SetVehicleLights(vehicle, 0)
end
end
-- add statebag change handler for ulc_blackout
AddStateBagChangeHandler('ulc_blackout', null, function(bagName, key, value)
Wait(0)
local vehicle = GetEntityFromStateBagName(bagName)
--print("ulc_blackout listener: Vehicle is " .. vehicle .. " and GetVehiclePedIsIn(PlayerPedId()) is " .. GetVehiclePedIsIn(PlayerPedId()))
if vehicle == 0 or vehicle ~= GetVehiclePedIsIn(PlayerPedId()) then
print("ulc_blackout listener: Vehicle is 0 or not mine.")
return
end
local blackout = value
--print("ulc_blackout listener: new state value is " .. tostring(blackout))
if blackout == 0 then
ULC:SetBlackout(0)
elseif blackout == 1 then
ULC:SetBlackout(1)
end
end)
-- add statebag change handler for rbl blackout
AddStateBagChangeHandler('rbl_blackout', null, function(bagName, key, value)
Wait(0)
rblIntegration = true
local vehicle = GetEntityFromStateBagName(bagName)
--print("rbl_blackout listener: Vehicle is " .. vehicle .. " and GetVehiclePedIsIn(PlayerPedId()) is " .. GetVehiclePedIsIn(PlayerPedId()))
if vehicle == 0 or vehicle ~= GetVehiclePedIsIn(PlayerPedId()) then
--print("rbl_blackout listener: Vehicle is 0 or not mine")
return
end
local blackout = value
--print("rbl_blackout listener: new state value is " .. tostring(blackout))
if blackout == true then
--print("rbl_blackout listener: setting blackout to 0")
ULC:SetBlackout(0)
elseif blackout == false then
--print("rbl_blackout listener: setting blackout to 1")
ULC:SetBlackout(1)
end
end)
-- register command for blackout
-- if rbl loads first then ULC
-- ulc will overwrite command
-- ULC needs to trigger rbl:setBlackout state change on server
-- ULC only manages the extras
-- if ulc loads first then rbl
-- rbl will overwrite command
-- rbl needs to trigger ulc:setBlackout state change on server
-- rbl only manages the brake lights
RegisterCommand('blackout', function()
local newState
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if not vehicle then return end
local currentState = Entity(vehicle).state.ulc_blackout
--print("/blackout: Current state: " .. tostring(currentState))
if currentState == nil or currentState == 1 then
print("Setting blackout to true/0")
newState = 0
elseif currentState == 0 then
print("Setting blackout to false/1")
newState = 1
end
-- trigger server event to set blackout on my vehicle
-- might need to extract this to an event/function to control the effect programmatically, like disbling when q pressed
TriggerServerEvent('ulc:setBlackout', VehToNet(GetVehiclePedIsIn(PlayerPedId())), newState)
TriggerServerEvent('rbl:setBlackout', VehToNet(GetVehiclePedIsIn(PlayerPedId())), newState)
end)
-- toggle blackout state on vehicle
-------------------------------
-- DISABLE BLACKOUT TRIGGERS --
-------------------------------
--TODO when H is pressed to control headlights disable blackout
--TODO when Q is pressed to control emergency lights disable blackout
+137
View File
@@ -0,0 +1,137 @@
--print("[ULC] Brake Extras Loaded")
local realBrakeThreshold = 3
local shouldUseRealBrakes = function()
return (MyVehicleConfig.brakeConfig.speedThreshold or 3) <= realBrakeThreshold
end
local braking = false
-------------------
-- MAIN FUNCTIONS --
-------------------
local disabledExtras = {}
local function setBrakeExtras(newState)
for _, v in pairs(MyVehicleConfig.brakeConfig.brakeExtras) do
local currentState
if IsVehicleExtraTurnedOn(MyVehicle, v) then currentState = 0 else currentState = 1 end
--print("[ULC] setBrakeExtras() newState: " .. newState .. " currentState: " .. currentState)
if currentState == newState then break end
ULC:SetStage(v, newState, false, true, false, false, true, false)
end
if newState == 0 then
-- disable the disable extras and save the ones that we change
if not MyVehicleConfig.brakeConfig.disableExtras then return end
for _, v in pairs(MyVehicleConfig.brakeConfig.disableExtras) do
if IsVehicleExtraTurnedOn(MyVehicle, v) then
ULC:SetStage(v, 1, false, true, false, false, true, false)
table.insert(disabledExtras, v)
end
end
elseif newState == 1 then
-- re-enable any extras that were disabled
for _, v in pairs(disabledExtras) do
ULC:SetStage(v, 0, false, true, false, false, true, false)
end
disabledExtras = {}
end
end
----------------------------
-- REALISTIC BRAKE LIGHTS --
----------------------------
if shouldUseRealBrakes then
print("Realistic brake light functionality intialized.")
local mode = "STANDARD"
-- start checking if stopped manually with a loop
CreateThread(function()
local sleep = 1000
while true do
Wait(sleep)
-- if rbl_brakelights change handler gets triggered that means rbl exists and we want to use that functionality instead, return from this loop
if mode == "RBL" then
print("real-brake-lights resource detected, integrating brakelight functionality.")
return
end
if not MyVehicle then
sleep = 1000
goto continue
end
if not shouldUseRealBrakes() then
sleep = 1000
goto continue
end
if not MyVehicleConfig.brakeConfig.useBrakes then
sleep = 1000
goto continue
end
if braking then goto continue end
sleep = 250
local speed = GetVehicleSpeedConverted(MyVehicle)
if speed < realBrakeThreshold and shouldUseRealBrakes() and not IsControlPressed(0, 72) then
--print("[manual checks] Enabling brakes")
setBrakeExtras(0)
else
--print("[manual checks] Disabling brakes")
setBrakeExtras(1)
end
::continue::
end
end)
-- add a statebag change handler for rbl_brakelights
-- once this is triggered, disable manual checking
AddStateBagChangeHandler('rbl_brakelights', null, function(bagName, key, value)
Wait(0) -- Nedded as GetEntityFromStateBagName sometimes returns 0 on first frame
mode = "RBL" -- set mode to RBL to disable manual checking
if not MyVehicle then return end
if not MyVehicleConfig.brakeConfig.useBrakes then return end
local vehicle = GetEntityFromStateBagName(bagName)
--print("state changed for vehicle")
if vehicle == 0 or vehicle ~= MyVehicle then return end
local newState
if value then newState = 0 else newState = 1 end
--print("ULC: Setting brakes to state" .. newState)
setBrakeExtras(newState)
end)
end
-----------------
-- KEYBINDINGS --
-----------------
-- pressed brakes
RegisterCommand('+ulc:brakePattern', function()
braking = true
if MyVehicle and MyVehicleConfig.brakeConfig.useBrakes then
if GetVehicleCurrentGear(MyVehicle) == 0 then return end -- disable while reversing
--print("Enabling brakes")
local speed = GetVehicleSpeedConverted(MyVehicle)
-- if using real brakes always enable
if shouldUseRealBrakes() or speed > (MyVehicleConfig.brakeConfig.speedThreshold or 3) then
setBrakeExtras(0)
end
end
SendNUIMessage({
type = 'toggleBrakeIndicator',
state = true
})
end)
RegisterCommand('-ulc:brakePattern', function()
braking = false
if MyVehicle and MyVehicleConfig.brakeConfig.useBrakes then
local speed = GetVehicleSpeedConverted(MyVehicle)
if shouldUseRealBrakes() and speed < realBrakeThreshold then return end
--print("Disabling brakes")
setBrakeExtras(1)
end
SendNUIMessage({
type = 'toggleBrakeIndicator',
state = false
})
end)
RegisterKeyMapping('+ulc:brakePattern', 'ULC: Activate Brake Pattern (Hold)', 'keyboard', 's')
+275
View File
@@ -0,0 +1,275 @@
--print("[ULC]: Stage Controls Loaded")
-------------------
-------------------
----- HELPERS -----
-------------------
-------------------
function GetExtraByKey(key)
local result = nil
for _, v in pairs(MyVehicleConfig.buttons) do
if v.key == key then
result = v.extra
end
end
return result
end
function GetButtonByExtra(extra)
local result = nil
for _, v in pairs(MyVehicleConfig.buttons) do
if v.extra == extra then
result = v
end
end
return result
end
function ULC:ChangeExtra(extra, newState, repair)
--print("[ULC:ChangeExtra()] Changing extra: " .. extra .. " to: " .. newState)
-- disable repair
if not repair then
SetVehicleAutoRepairDisabled(MyVehicle, true)
end
-- change extra
SetVehicleExtra(MyVehicle, extra, newState)
-- fix deformation if repair is true
if repair then
SetVehicleDeformationFixed(MyVehicle)
end
-- enable repair
SetVehicleAutoRepairDisabled(MyVehicle, false)
end
---------------
---------------
-- MAIN CODE --
---------------
---------------
-- new event
AddEventHandler('ulc:SetStage', function(extra, action, playSound, extraOnly, repair, forceChange, forceUi)
ULC:SetStage(extra, action, playSound, extraOnly, repair, forceChange, forceUi)
end)
-- change specified extra, and if not extraOnly, and extra is in a button, act on the linked and off extras as well, acts recursively;
-- action 0 enables, 1 disables, 2 toggles;
-- updates ui whenever extra is used in a button
function ULC:SetStage(extra, action, playSound, extraOnly, repair, forceChange, forceUi, allowOutside)
----------
-- checks
if not MyVehicle then
print("[ULC:SetStage()] MyVehicle is not defined right now :/")
return false
end
if not allowOutside and not IsPedInAnyVehicle(PlayerPedId(), false) then
print("[ULC:SetStage()] Player must be in a vehicle, or allowOutside must be true.")
return false
end
--print("[ulc:SetStage]", extra, action, playSound, extraOnly)
--------------
-- definitions
local button = GetButtonByExtra(extra)
local buttonStates = {} -- track button states for UI
--------------------------
-- determine the new state
local newState
if IsVehicleExtraTurnedOn(MyVehicle, extra) then
if action == 1 or action == 2 then
newState = 1
end
else
if action == 0 or action == 2 then
newState = 0
end
end
---------------------------------------------------------
-- built in don't try to change if it's the same already!
--[[ forceChange is used to forceChange the change even if it's the same
this is used to trigger the additional actions like linked and off extras
even if the extra is already in the state we want it to be
(used in cycling stages and one other place i cant remember)]]
if not forceChange and not newState then return end
local canChange = true
if repair then
if not AreVehicleDoorsClosed(MyVehicle) then
canChange = false
print("[ULC:SetStage] Can't change stage with repair while a door is open.")
end
if not IsVehicleHealthy(MyVehicle) then
canChange = false
print("[ULC:SetStage] Can't change stage with repair while vehicle is damaged.")
end
end
if not canChange then return end
---------------------------------------
-- if the extra corresponds to a button
if button then
--------------------
-- sound
if playSound then
if newState == 0 then
PlayBeep(true)
else
PlayBeep(false)
end
end
----------------------
-- smart stages stuff
local key = button.key
if MyVehicleConfig.stages then
local keyStage = contains(MyVehicleConfig.stages.stageKeys, key) -- find whether MyVehicleConfig.stages.stageKeys contain the key
-- # TODO we're not getting here for some reason when cycling stages at max stage
-- if the key pressed is not a stage, just change the extra
if not keyStage then
ULC:ChangeExtra(extra, newState, repair)
end
-- if the key pressed is a stage and extraOnly is false
if keyStage and not extraOnly then
print("key: " .. key .. " keyStage: " .. tostring(keyStage) .. " currentStage: " .. currentStage)
-- if it's the same as the current stage, change the extra and proceed normally
if keyStage == currentStage then
print("Key is the same as current stage")
ULC:ChangeExtra(extra, newState, repair)
-- set the stage to 0
print("Setting stage to: 0")
currentStage = 0
else
-- if it's a different stage then we want to change to a state where that stage is enabled
print("Key is not the same as current stage")
newState = 0 -- change to newState to 0 since we want the new stage to be enabled
local currentPrimaryExtraState = IsVehicleExtraTurnedOn(MyVehicle, extra)
print("New state: " ..
newState .. "Extra " .. extra .. " current state: " .. tostring(currentPrimaryExtraState))
if not IsVehicleExtraTurnedOn(MyVehicle, extra) and newState == 0 then
print("Extra needs to be turned on")
ULC:ChangeExtra(extra, newState, repair)
elseif IsVehicleExtraTurnedOn(MyVehicle, extra) and newState == 1 then
print("Extra needs to be turned off")
ULC:ChangeExtra(extra, newState, repair)
else
-- if it's in the correct state
print("Extra is already in the correct state")
end
-- set the new stage
print("Setting stage to: " .. keyStage)
currentStage = keyStage
end
else -- if extraOnly is true
ULC:ChangeExtra(extra, newState, repair)
end
else
-- if there are no stages, just change the extra
ULC:ChangeExtra(extra, newState, repair)
end
----------------------
-- initialize UI changes
-- add that button to the new button states for UI with it's extra and new state
table.insert(buttonStates, { extra = extra, newState = newState })
-----------------------------
-- additional actions/extras
if not extraOnly then
-- set linked extras
if button.linkedExtras then
for _, v in ipairs(button.linkedExtras) do
ULC:SetStage(v, newState, false, true, repair, forceChange)
-- add linked buttons to the new button states for UI with their extras and new state
table.insert(buttonStates, { extra = v, newState = newState })
end
end
-- set opposite extras
if button.oppositeExtras or false then -- in case they have old config without the feature
local oppState
if newState == 1 then oppState = 0 elseif newState == 0 then oppState = 1 end
for _, v in pairs(button.oppositeExtras) do
ULC:SetStage(v, oppState, false, true, repair, forceChange)
-- add opposite buttons to the new button states for UI with their extras and new state
table.insert(buttonStates, { extra = v, newState = oppState })
end
end
-- set off extras
if button.offExtras then
for _, v in ipairs(button.offExtras) do
ULC:SetStage(v, 1, false, true, repair, forceChange)
-- add off buttons to the new button states for UI with their extras and new state
table.insert(buttonStates, { extra = v, newState = 1 })
end
end
end
if not extraOnly or forceUi then
-- update UI
ULC:SetButtons(buttonStates)
end
else -- if it's not a button, we just change the extra because we don't care about stages or linked extras etc.
ULC:ChangeExtra(extra, newState, repair)
end
end
-----------------------
-----------------------
------ KEYBINDS -------
-----------------------
-----------------------
for i = 1, 9, 1 do
RegisterKeyMapping('ulc:num' .. i, 'ULC: Toggle Button ' .. i, 'keyboard', 'NUMPAD' .. i)
RegisterCommand('ulc:num' .. i, function()
local extra = GetExtraByKey(i)
local button = GetButtonByExtra(extra)
if not button then return end
ULC:SetStage(extra, 2, true, false, button.repair or false)
end)
end
------------------
------ HELP ------
------------------
local activeButtons = {}
local showingHelp = false
function ShowHelp()
CreateThread(function()
if not showingHelp then
-- show help
showingHelp = true
for k, v in ipairs(activeButtons) do
--print('Showing help for button: ' .. k .. ' : ' .. v.key)
SendNUIMessage({
type = 'showHelp',
button = k,
key = v.key,
})
end
Wait(3000)
-- hide help
showingHelp = false
for k, v in ipairs(activeButtons) do
SendNUIMessage({
type = 'hideHelp',
button = k,
label = string.upper(v.label),
})
end
end
end)
end
+77
View File
@@ -0,0 +1,77 @@
--print("[ULC]: Cruise lights Loaded")
-- 1 disabled, 0 enabled
local sbState = 1
-- 0 on, 1 off
local function setCruiseLights(newState)
sbState = newState
for _, v in pairs(MyVehicleConfig.steadyBurnConfig.sbExtras) do
--print("Setting cruise lights extra: " .. v)
ULC:SetStage(v, newState, false, true, false, false, true, false)
end
end
local function getSteadyBurnState()
if IsVehicleExtraTurnedOn(MyVehicle, MyVehicleConfig.steadyBurnConfig.sbExtras[1]) then
return 0
else
return 1
end
end
CreateThread(function()
while true do
if MyVehicle then
TriggerEvent('ulc:CheckCruise', false)
end
Wait(1000)
end
end)
--TODO: disable when lights are on, enable when lights are off
AddEventHandler('ulc:lightsOn', function()
--print("Lights on")
if MyVehicle and (MyVehicleConfig.steadyBurnConfig.disableWithLights or false) then
setCruiseLights(1)
end
end)
AddEventHandler('ulc:lightsOff', function()
--print("Lights off")
if MyVehicle and (MyVehicleConfig.steadyBurnConfig.disableWithLights or false) then
TriggerEvent('ulc:CheckCruise')
end
end)
AddEventHandler('ulc:CheckCruise', function()
sbState = getSteadyBurnState()
if not MyVehicle then return end
if Entity(MyVehicle).state.ulc_blackout == 0 then
-- print("Blackout is on, disabling cruise lights")
setCruiseLights(1)
return
end
if MyVehicleConfig.steadyBurnConfig.forceOn then
if sbState == 0 then return end
if Lights and MyVehicleConfig.steadyBurnConfig.disableWithLights then return end
--print("Setting cruise lights on")
setCruiseLights(0)
elseif MyVehicleConfig.steadyBurnConfig.useTime then
local isTime = GetClockHours() > Config.SteadyBurnSettings.nightStartHour or
GetClockHours() < Config.SteadyBurnSettings.nightEndHour
if isTime then
-- if lights are already on do nothing
if sbState == 0 then return end
if Lights and MyVehicleConfig.steadyBurnConfig.disableWithLights then return end
setCruiseLights(0)
else
-- if already off do nothing
if sbState == 1 then return end
setCruiseLights(1)
end
end
end)
+85
View File
@@ -0,0 +1,85 @@
local doors = {
[0] = false, -- d front
[1] = false, -- p front
[2] = false, -- d rear
[3] = false, -- p rear
[4] = false, -- hood
[5] = false -- trunk
}
local function intNot(value)
result = 0
if value == 0 then
result = 1
end
return result
end
-- state 1 = closed, state 0 = open
local function onDoorStateChange(door, newDoorState)
--print("Handling door change", door, newDoorState)
if door == 0 or door == 2 then -- if driver side
for _, v in pairs(MyVehicleConfig.doorConfig.driverSide.enable) do
--print("Enable extra:", v)
ULC:SetStage(v, newDoorState, true, true, false, false, true, true)
end
for _, v in pairs(MyVehicleConfig.doorConfig.driverSide.disable) do
--print("Disable extra:", v, intNot(newDoorState))
ULC:SetStage(v, intNot(newDoorState), true, true, false, false, true, true)
end
elseif door == 1 or door == 3 then -- if pass side
for _, v in pairs(MyVehicleConfig.doorConfig.passSide.enable) do
--print("Enable extra:", v)
ULC:SetStage(v, newDoorState, true, true, false, false, true, true)
end
for _, v in pairs(MyVehicleConfig.doorConfig.passSide.disable) do
--print("Disable extra:", v, intNot(newDoorState))
ULC:SetStage(v, intNot(newDoorState), true, true, false, false, true, true)
end
elseif door == 5 then -- if trunk
for _, v in pairs(MyVehicleConfig.doorConfig.trunk.enable) do
ULC:SetStage(v, newDoorState, true, true, false, false, true, true)
end
for _, v in pairs(MyVehicleConfig.doorConfig.trunk.disable) do
ULC:SetStage(v, intNot(newDoorState), true, true, false, false, true, true)
end
end
end
CreateThread(function()
local sleep = 1000
while true do
Wait(sleep)
if not MyVehicle then
sleep = 1000
goto continue
end
if not MyVehicleConfig.doorConfig or false then
sleep = 1000
goto continue
end
if not MyVehicleConfig.doorConfig.useDoors then
sleep = 1000
goto continue
end
sleep = 250
for k, v in pairs(doors) do
if GetVehicleDoorAngleRatio(MyVehicle, k) > 0.0 then
if v == false then
-- print("Setting door", k, "open.")
doors[k] = true -- set door open
onDoorStateChange(k, 0) -- handle what to do
end
else
if v == true then
-- print("Setting door", k, "closed.")
doors[k] = false -- set door closed
onDoorStateChange(k, 1) -- handle what to do
end
end
end
::continue::
end
end)
+67
View File
@@ -0,0 +1,67 @@
--print("[ULC]: Horn Extras Loaded")
local extraStates = {}
local function GetPreviousStateByExtra(extra)
for k, v in pairs(extraStates) do
--print(v.extra, v.state)
if extra == v.extra then
--print('Found state of : ' .. tostring(v.state) .. ' for extra ' .. extra)
return v.state
end
end
end
function SetHornExtras(newState)
-- print('SetHornExtras: ' .. newState)
if newState == 0 then
for _, extra in pairs(MyVehicleConfig.hornConfig.hornExtras) do
local extraState = {
extra = extra,
state = IsVehicleExtraTurnedOn(MyVehicle, extra)
}
table.insert(extraStates, extraState)
ULC:SetStage(extra, 0, false, true, false, false, true, false)
end
if not MyVehicleConfig.hornConfig.disableExtras then return end
for _, extra in pairs(MyVehicleConfig.hornConfig.disableExtras) do
local extraState = {
extra = extra,
state = IsVehicleExtraTurnedOn(MyVehicle, extra)
}
table.insert(extraStates, extraState)
ULC:SetStage(extra, 1, false, true, false, false, true, false)
end
elseif newState == 1 then
for _, extra in pairs(MyVehicleConfig.hornConfig.hornExtras) do
local prevState = GetPreviousStateByExtra(extra)
if not prevState then
ULC:SetStage(extra, 1, false, true, false, false, true, false)
end
end
if not MyVehicleConfig.hornConfig.disableExtras then return end
for _, extra in pairs(MyVehicleConfig.hornConfig.disableExtras) do
local prevState = GetPreviousStateByExtra(extra)
if prevState then
ULC:SetStage(extra, 0, false, true, false, false, true, false)
end
end
end
end
RegisterCommand('+ulc:horn', function()
--print('horn')
extraStates = {}
if MyVehicle and MyVehicleConfig.hornConfig.useHorn then
SetHornExtras(0)
end
end)
RegisterCommand('-ulc:horn', function()
if MyVehicle and MyVehicleConfig.hornConfig.useHorn then
SetHornExtras(1)
end
end)
RegisterKeyMapping('+ulc:horn', 'ULC: Activate Horn Extras', 'keyboard', 'e')
+298
View File
@@ -0,0 +1,298 @@
-- MAIN FUNCTIONS --
function ULC:PopulateButtons(_buttons, placeholders)
--print("Populating buttons")
local buttons = _buttons
if placeholders then
buttons = {
{ label = 'TEST STAGE', extra = 1, color = 'green', enabled = true },
{ label = 'TEST STAGE', extra = 2, color = 'blue', enabled = false },
{ label = 'TEST STAGE', extra = 3, color = 'blue', enabled = false },
{ label = 'TEST STAGE', extra = 4, color = 'blue', enabled = true },
{ label = 'test stage', extra = 5, color = 'red', enabled = true }
}
end
local buttonsToSend = {}
for _, v in pairs(buttons) do
local thisButton = {}
local thisState = false
if IsVehicleExtraTurnedOn(MyVehicle, v.extra) then thisState = true end
thisButton.extra = v.extra
thisButton.enabled = thisState
thisButton.color = v.color or 'green'
thisButton.label = string.upper(v.label)
thisButton.numKey = v.key
--print("Sending button: " .. json.encode(thisButton))
table.insert(buttonsToSend, thisButton)
end
SendNUIMessage({
type = 'populateButtons',
buttons = buttonsToSend
})
end
-- deprecated in exchange for "SetButtons"
function ULC:SetButton(extra, enabled)
local newState
if enabled == 0 then
newState = true
elseif enabled == 1 then
newState = false
end
SendNUIMessage({
type = 'setButton',
extra = extra,
newState = newState
})
end
function ULC:SetButtons(buttonStates)
-- print("Setting buttons", json.encode(buttonStates))
-- go through the buttons and replace newState with a boolean
-- newState = 1 means false, 0 means true
for k, v in pairs(buttonStates) do
if v.newState == 1 then
v.newState = false
elseif v.newState == 0 then
v.newState = true
end
end
SendNUIMessage({
type = 'setButtons',
buttonStates = buttonStates
})
end
-----------------
-- UI SETTINGS --
-----------------
function ULC:SetDisplay(bool)
if bool then
SendNUIMessage({
type = 'showHUD',
})
else
SendNUIMessage({
type = 'hideHUD',
})
end
end
function ULC:SetPosition(x, y)
SendNUIMessage({
type = 'setPosition',
x = x,
y = y
})
end
function ULC:SetScale(float)
SendNUIMessage({
type = 'setScale',
scale = float
})
end
-- TODO this is unused in game, should be in menu
function ULC:SetUseLeftAnchor(bool)
SendNUIMessage({
type = 'setAnchor',
bool = bool
})
end
function ULC:SetHudDisabled(bool)
SendNUIMessage({
type = 'setHudDisabled',
bool = bool
})
end
function ULC:SetHelpDisplay(bool)
if bool then
SendNUIMessage({ type = 'showHelp' })
else
SendNUIMessage({ type = 'hideHelp' })
end
end
----------
-- MENU --
----------
-- TODO set this up in js
function ULC:SetMenuDisplay(bool)
--print("Client setting display", bool)
if bool then
SendNUIMessage({
type = 'showMenu',
})
else
SendNUIMessage({
type = 'hideHideMenu',
})
end
end
----------------------
-- USER PREFERENCES --
----------------------
print("[ULC] Client Storage Loaded")
ClientPrefs = {}
local function loadUserPrefs()
-- if prefs already exist
local prefsExist = GetResourceKvpString('ulc')
if prefsExist == "exists" then
print("[ULC] Loading prefs")
-- load
ClientPrefs.hideUi = GetResourceKvpInt("ulc:hideUi")
ClientPrefs.x = GetResourceKvpInt("ulc:x")
ClientPrefs.y = GetResourceKvpInt("ulc:y")
ClientPrefs.scale = GetResourceKvpFloat("ulc:scale")
ClientPrefs.useLeftAnchor = GetResourceKvpString("ulc:useLeftAnchor")
else
print("[ULC] Creating prefs")
-- set defaults
SetResourceKvp('ulc', "exists")
SetResourceKvpInt('ulc:x', 0)
SetResourceKvpInt('ulc:y', 0)
SetResourceKvpFloat('ulc:scale', 1.0)
SetResourceKvpInt('ulc:hideUi', 0)
SetResourceKvp('ulc:useLeftAnchor', 'false')
loadUserPrefs()
Wait(5000)
TriggerEvent('chat:addMessage', {
color = { 0, 153, 204 },
multiline = false,
args = { "ULC", "^4This server uses ULC! Type /ulc to view settings and adjust the HUD!" }
})
end
end
loadUserPrefs()
-- use the values
CreateThread(function()
--print("CLIENT PREF DISABLED =", ClientPrefs.hideUi)
Wait(1000)
-- positioning
if ClientPrefs.x then
--print("Loaded position from kvp: ", ClientPrefs.x, ClientPrefs.y)
ULC:SetPosition(ClientPrefs.x, ClientPrefs.y)
end
if ClientPrefs.scale then
-- print("Loaded saved scale from kvp: " .. ClientPrefs.scale)
ULC:SetScale(ClientPrefs.scale + 0.0)
end
if ClientPrefs.hideUi then
-- print("Loaded disabled HUD kvp: " .. ClientPrefs.hideUi)
ULC:SetHudDisabled(ClientPrefs.hideUi)
end
if ClientPrefs.useLeftAnchor then
-- print("Loaded useLeftAnchor from kvp", ClientPrefs.useLeftAnchor)
ULC:SetUseLeftAnchor(ClientPrefs.useLeftAnchor)
end
end)
--------------
-- COMMANDS --
--------------
RegisterCommand('ulc', function()
if not MyVehicle then
ULC:PopulateButtons({}, true)
ULC:SetDisplay(true)
end
ULC:SetMenuDisplay(true)
if MyVehicle then
ULC:SetHelpDisplay(true)
end
SetNuiFocus(true, true)
end)
TriggerEvent('chat:addSuggestion', '/ulc', 'Enables dragging ULC HUD and shows settings menu and controls.', {
})
RegisterCommand("ulcReset", function()
DeleteResourceKvp("ulc")
loadUserPrefs()
end)
TriggerEvent('chat:addSuggestion', '/ulcReset', 'Resets all saved ULC settings to defaults.', {
})
-- NUI CALLBACKS --
RegisterNUICallback("savePosition", function(data, cb)
--print("NUI Setting position", data.newX, data.newY, "type = ", type(data.newX))
SetResourceKvpInt('ulc:x', data.newX)
SetResourceKvpInt('ulc:y', data.newY)
cb({ success = true })
end)
RegisterNUICallback("saveScale", function(data, cb)
--print("NUI Setting Scale " .. data.scale + 0.0)
SetResourceKvpFloat('ulc:scale', data.scale + 0.0)
cb({ success = true })
end)
RegisterNUICallback("saveAnchor", function(data, cb)
--print("NUI Setting Anchor ", data.useLeftAnchor)
SetResourceKvp('ulc:useLeftAnchor', data.useLeftAnchor)
cb({ success = true })
end)
RegisterNUICallback("focusGame", function(data, cb)
ULC:SetMenuDisplay(false)
SetNuiFocus(false, false)
ULC:SetHelpDisplay(false)
if not MyVehicle then
ULC:SetDisplay(false)
end
cb({ success = true })
end)
RegisterNUICallback("setHudDisabled", function(data, cb)
--print("NUI Setting HUD Disabled ", data.hudDisabled)
if not data.hudDisabled then
--print("Set HUD enabled")
if MyVehicle then
ULC:SetDisplay(true)
end
if #ClientPrefs > 0 then
ClientPrefs.hideUi = 0
--print("Are we here?")
end
SetResourceKvpInt('ulc:hideUi', 0)
else
--print("Set HUD disabled")
ULC:SetDisplay(false)
if #ClientPrefs > 0 then
ClientPrefs.hideUi = 1
--print("Are we here?")
end
SetResourceKvpInt('ulc:hideUi', 1)
end
cb({ success = true })
end)
+32
View File
@@ -0,0 +1,32 @@
print("[ULC] LVC Integrations Loaded")
-- going to store the LVC siren state just for fun
LVC_SirenState = 0
-- received from s_lvc.lua when player changes main siren state in LVC
-- sirenId is an int representing the index of a siren in lvc/SIRENS.lua:SIRENS
RegisterNetEvent("ulc:LVC_MainSirenStateChange")
AddEventHandler("ulc:LVC_MainSirenStateChange", function(sirenId)
print("[ulc:LVC_MainSirenStateChange] " .. sirenId)
-- # TODO check how much of this is actually needed
if not MyVehicle then return end
if not MyVehicleConfig.luxartVehicleControlConfig then return end
if not MyVehicleConfig.luxartVehicleControlConfig.useLVC then return end
local config = MyVehicleConfig.luxartVehicleControlConfig
-- if sirenId is not in the config, return
if not MyVehicleConfig.luxartVehicleControlConfig[sirenId] then
print("[ULC: LVC_MainSirenStateChange()] siren [" ..
sirenId .. "] is not defined in MyVehicleConfig.luxartVehicleControlConfig")
return false
end
for _, v in pairs(config[sirenId].enable) do
ULC:SetStage(v, 0, false, false, false, false, false, false)
end
for _, v in pairs(config[sirenId].disable) do
ULC:SetStage(v, 1, false, false, false, false, false, false)
end
end)
+202
View File
@@ -0,0 +1,202 @@
--print("[ULC]: Main Thread Loaded")
ULC = {}
-----------------
-- DEFINITIONS --
-----------------
Lights = false
MyVehicle = nil
MyVehicleConfig = nil
------------------------------------
------------------------------------
------- LIGHTS STATE HANDLER -------
------------------------------------
------------------------------------
if Config.controlLights then
RegisterCommand('ulc:toggleLights', function()
if Lights then
SetVehicleSiren(MyVehicle, false)
else
SetVehicleSiren(MyVehicle, true)
end
end)
RegisterKeyMapping('ulc:toggleLights', 'Toggle Emergency Lights', 'keyboard', 'q')
end
AddEventHandler('ulc:lightsOn', function()
--print("Lights On")
-- set Lights on
Lights = true
setDefaultStages()
-- check if parked or driving for park patterns
TriggerEvent('ulc:checkParkState', GetVehiclePedIsIn(PlayerPedId()), false)
SendNUIMessage({
type = 'toggleIndicator',
state = Lights
})
if Config.controlLights then
PlayBeep(true)
end
end)
AddEventHandler('ulc:lightsOff', function()
--print("Lights Off")
Lights = false
SendNUIMessage({
type = 'toggleIndicator',
state = Lights
})
if Config.controlLights then
PlayBeep(false)
end
end)
-- check if lights are on 10 times a second;
-- used to trigger above events
CreateThread(function()
local sleep = 1000
while true do
Wait(sleep)
if not MyVehicle then
sleep = 1000
goto continue
end
sleep = 100
if not IsPedInAnyVehicle(PlayerPedId()) then goto continue end
if IsVehicleSirenOn(GetVehiclePedIsIn(PlayerPedId())) then
if not Lights then
TriggerEvent('ulc:lightsOn')
end
else
if Lights then
TriggerEvent('ulc:lightsOff')
end
end
::continue::
end
end)
---------------------------
---------------------------
-------- MAIN CODE --------
---------------------------
---------------------------
-- this event is called whenever player enters vehicle
RegisterNetEvent('ulc:checkVehicle')
AddEventHandler('ulc:checkVehicle', function()
CreateThread(function()
while not GlobalState.ulcloaded do
print("ULC: Waiting for load.")
Wait(250)
end
print("[ULC:checkVehicle] Checking for vehicle configuration")
local ped = PlayerPedId()
local vehicle = GetVehiclePedIsIn(ped)
local passed, vehicleConfig = GetVehicleFromConfig(vehicle)
--print(passed, vehicleConfig)
if passed then
MyVehicle = vehicle
MyVehicleConfig = vehicleConfig
table.sort(MyVehicleConfig.buttons, function(a, b) return a["key"] < b["key"] end)
print("[ULC:checkVehicle] Found vehicle, ready to go.")
-- if i am driver
if ped == GetPedInVehicleSeat(vehicle, -1) then
ULC:PopulateButtons(MyVehicleConfig.buttons)
--ShowHelp()
if not Config.hideHud and ClientPrefs.hideUi == 0 then
ULC:SetDisplay(true)
else
print(
"HUD is hidden. Type /ulc to see if you disabled it. Otherwise, the server owner may have disabled the HUD.")
end
TriggerEvent('ulc:CheckCruise')
TriggerEvent('ulc:checkParkState', true)
TriggerEvent('ulc:StartCheckingReverseState')
currentStage = 0
end
else
MyVehicle = nil
TriggerEvent('ulc:cleanup')
TriggerEvent('ulc:StopCheckingReverseState')
end
end)
end)
-- used to hide the hud
RegisterNetEvent('ulc:cleanup')
AddEventHandler('ulc:cleanup', function()
-- MyVehicle = nil
-- MyVehicleConfig = nil
ULC:SetDisplay(false)
-- hide hud
-- SendNUIMessage({
-- type = 'hideLightsHUD',
-- })
end)
-----------------
-- CONFIG SYNC --
-----------------
RegisterNetEvent('UpdateVehicleConfigs', function(newData)
print("[ULC] Updating vehicle table. Done loading.")
Config.Vehicles = newData
end)
-- trigger checks when spawning from one vehicle into another directly, or from another seat to driver seat
CreateThread(function()
local lastVehicle
local wasDriving
while true do
Wait(500)
if IsPedInAnyVehicle(PlayerPedId()) then
local currentVehicle = GetVehiclePedIsIn(PlayerPedId(), false)
local driving = GetPedInVehicleSeat(MyVehicle, -1) == PlayerPedId()
if currentVehicle ~= lastVehicle then
TriggerEvent('ulc:checkVehicle')
end
if MyVehicle and not wasDriving and driving then
TriggerEvent('ulc:checkVehicle')
end
lastVehicle = currentVehicle
wasDriving = driving
end
end
end)
-------------------------
-------------------------
-- AUTO REPAIR HANDLER --
-------------------------
-------------------------
-- every second set no repair on all vehicles except my own
CreateThread(function()
while true do
Wait(1000)
local vehicles = GetGamePool("CVehicle")
for _, v in pairs(vehicles) do
if v ~= GetVehiclePedIsIn(PlayerPedId(), false) then
SetVehicleAutoRepairDisabled(v, true)
else
--print("Enabling repair for" .. v)
SetVehicleAutoRepairDisabled(v, false)
end
end
end
end)
+150
View File
@@ -0,0 +1,150 @@
--print("[ULC]: Park Patterns Loaded")
local veh = GetVehiclePedIsIn(PlayerPedId())
parked = false
local lastSync = 0
local effectDelay = 1000
CreateThread(function()
while true do
if IsPedInAnyVehicle(PlayerPedId()) then
TriggerEvent('ulc:checkParkState', veh, false)
Wait(Config.ParkSettings.delay * 1000)
else
Wait(2000)
end
end
end)
RegisterNetEvent("ulc:checkParkState", function(delay)
CreateThread(function()
--print('Checking park state')
if delay then
--print('Delay...')
Wait(5000)
end
local speed = GetVehicleSpeedConverted(MyVehicle)
if speed > Config.ParkSettings.speedThreshold and parked then
TriggerEvent("ulc:vehDrive")
end
if speed < Config.ParkSettings.speedThreshold and not parked then
Wait(effectDelay)
if not parked then -- double checks
TriggerEvent('ulc:vehPark')
end
end
end)
end)
AddEventHandler('ulc:vehPark', function()
if Lights then
--print('[ulc:vehPark] My vehicle is parked.')
parked = true
if MyVehicle and MyVehicleConfig.parkConfig.usePark then
-- enable pExtras
for _, v in pairs(MyVehicleConfig.parkConfig.pExtras) do
ULC:SetStage(v, 0, false, true, false, false, true, false)
end
-- disable dExtras
for _, v in pairs(MyVehicleConfig.parkConfig.dExtras) do
ULC:SetStage(v, 1, false, true, false, false, true, false)
end
-- park pattern sync stuff
if MyVehicleConfig.parkConfig.useSync then
-- cooldown
local gameSeconds = GetGameTimer() / 1000
if gameSeconds >= lastSync + Config.ParkSettings.syncCooldown then
lastSync = gameSeconds
local loadedVehicles = GetGamePool("CVehicle")
--print(#loadedVehicles .. " vehicles in pool")
local vehsToSync = {}
for k, v in pairs(loadedVehicles) do
-- don't include my vehicle
if v ~= veh then
local vehCoords = GetEntityCoords(v)
local pedCoords = GetEntityCoords(PlayerPedId())
local distance = GetDistanceBetweenCoords(vehCoords, pedCoords)
if distance < Config.ParkSettings.syncDistance then
if GetVehicleClass(v) == 18 then
-- check if my vehicle is set to sync with this vehicle or if the vehicle is the same model as my vehicle
if IsVehicleInTable(v, MyVehicleConfig.parkConfig.syncWith) or GetEntityModel(v) == GetEntityModel(MyVehicle) then
--print('Vehicle' .. v .. ' should sync with me.')
local speed = GetVehicleSpeedConverted(veh)
if speed < Config.ParkSettings.speedThreshold then
--print("Found an eligible sync vehicle.")
table.insert(vehsToSync, v)
end
end
end
end
end
end
if #vehsToSync > 0 then
-- sync my vehicle
SetVehicleSiren(veh, false)
SetVehicleSiren(veh, true)
-- sync other vehicles on my screen
for k, v in pairs(vehsToSync) do
if IsVehicleSirenOn(v) then
SetVehicleSiren(v, false)
SetVehicleSiren(v, true)
end
end
-- send sync to other clients nearby
--print("Preparing to send sync to server")
local vehsToSyncNet = {}
for k, v in pairs(vehsToSync) do
--print("Candidate: " .. VehToNet(v))
table.insert(vehsToSyncNet, VehToNet(v))
end
TriggerServerEvent("sync:send", vehsToSyncNet)
else --print('Found no vehicles to sync.')
end
else
print("Sync on cooldown, time left: " ..
Config.ParkSettings.syncCooldown - (gameSeconds - lastSync) .. " seconds.")
end
end
end
end
end)
RegisterNetEvent('ulc:sync:receive', function(vehicles)
--print("[sync:receive] Trying to sync " .. #vehicles .. " vehicles.")
for _, v in pairs(vehicles) do
--print("Attempting to sync: " .. NetToVeh(v))
SetVehicleSiren(NetToVeh(v), false)
SetVehicleSiren(NetToVeh(v), true)
end
end)
AddEventHandler('ulc:vehDrive', function()
if Lights then
--print('[ulc:vehDrive] My vehicle is driving.')
parked = false
if MyVehicle and MyVehicleConfig.parkConfig.usePark then
-- disable pExtras
for _, v in pairs(MyVehicleConfig.parkConfig.pExtras) do
ULC:SetStage(v, 1, false, true, false, false, true, false)
end
-- enable dExtras
for _, v in pairs(MyVehicleConfig.parkConfig.dExtras) do
ULC:SetStage(v, 0, false, true, false, false, true, false)
end
end
end
end)
+125
View File
@@ -0,0 +1,125 @@
--print("[ULC]: Reverse Extras Loaded")
local reversing = false
local disabledExtras = {}
local timerExpired = false
function setReverseExtras(newState)
-- set enable extras to match the new state
for _, v in ipairs(MyVehicleConfig.reverseConfig.reverseExtras) do
ULC:SetStage(v, newState, false, true, false, false, true, false)
end
if not MyVehicleConfig.reverseConfig.disableExtras then return end
if newState == 0 then
-- set disable extras off and save the ones we changed
for _, v in ipairs(MyVehicleConfig.reverseConfig.disableExtras) do
--print("Checking extra " .. v .. " for reverse state")
if IsVehicleExtraTurnedOn(MyVehicle, v) then
ULC:SetStage(v, 1, false, true, false, false, true, false)
table.insert(disabledExtras, v)
end
end
else -- newState == 1
-- set the disabled extras back on
for _, v in ipairs(disabledExtras) do
ULC:SetStage(v, 0, false, true, false, false, true, false)
end
disabledExtras = {}
end
end
AddEventHandler('ulc:StartCheckingReverseState', function()
CreateThread(function()
while true do
Wait(250)
--print("Checking reverse state")
if not IsPedInAnyVehicle(PlayerPedId()) then return end
-- this feels unncessary, but I think some people may not have .reverseConfig
if not MyVehicle then return end
if not MyVehicleConfig.reverseConfig then return end
if not MyVehicleConfig.reverseConfig.useReverse then return end
local gear = GetVehicleCurrentGear(MyVehicle)
if gear == 0 then
if not reversing then
startTimer()
reversing = true
setReverseExtras(0)
end
else
if reversing then
reversing = false
setReverseExtras(1)
end
end
end
end)
end)
-- handle disabling lights after some time
function startTimer()
-- if disabled in config, don't start timer , if enabled or missing config, start timer
if Config and Config.ReverseSettings and not Config.ReverseSettings.useRandomExpiration then return end
-- timer thread
CreateThread(function()
local speed
local duration = math.random(3, 8) * 1000
local expirationTime
while true do
--print("Reverse timer tick")
if not MyVehicle then return end
if not MyVehicleConfig.reverseConfig then return end
if not MyVehicleConfig.reverseConfig.useReverse then return end
if not reversing then
timerExpired = false
--print("Not reversing")
return
end
speed = GetVehicleSpeedConverted(MyVehicle)
if speed < 0.5 then -- if we are in reverse and stopped
if timerExpired then
goto continue
end
if Config and Config.ReverseSettings then
duration = math.random(
(Config.ReverseSettings.minExpiration or 3) * 1000,
(Config.ReverseSettings.maxExpiration or 8) * 1000
)
end
expirationTime = GetGameTimer() + duration
while GetGameTimer() < expirationTime do
Wait(500)
--print("Reverse timer active")
if GetVehicleSpeedConverted(MyVehicle) > 1 then
-- print("[ULC] Reverse: Moving, breaking timer")
break
end
if not reversing then
-- print("[ULC] Reverse: Not reversing, breaking timer")
break
end
if not IsPedInAnyVehicle(PlayerPedId()) then
-- print("[ULC] Reverse: Not in vehicle, breaking timer")
break
end
if GetGameTimer() > expirationTime then
print("[ULC] Reverse: Timer expired, disabling extras")
timerExpired = true
setReverseExtras(1)
break
end
end
else -- if we are in reverse and moving
-- print("[ULC] Reverse: Resetting timer")
setReverseExtras(0)
timerExpired = false
end
::continue::
Wait(500)
end
end)
end
+157
View File
@@ -0,0 +1,157 @@
print("[ULC] Stages Loaded")
-- Definitions
-- # TODO maybe currentStage should not be 0 when entering a vehicle?
--[[ # TODO this file does not handle setting the currentStage, instead ULC:SetStage does,
may want to change this if possible, leads to hacky stuff like in CycleStage function ]]
-- this is set to 0 whenever ulc:checkVehicle is triggered
currentStage = 0
-- helpers
local function checks()
if not MyVehicle then return end
if not MyVehicleConfig.stages then return end
if not MyVehicleConfig.stages.useStages then return end
if not MyVehicleConfig.stages.stageKeys
then
return false
end
return true
end
function getMaxStage()
if not MyVehicle then return end
if not MyVehicleConfig.stages then return end
if not MyVehicleConfig.stages.stageKeys then return end
return #MyVehicleConfig.stages.stageKeys
end
-- main functions
function stageUp()
print("[ULC:stageUp] Increasing stage from " .. currentStage)
if currentStage == getMaxStage() then
print("Already at max stage")
return
end
-- this is handled in ULC:SetStage?
-- currentStage = currentStage + 1
-- instead we just want to keep track locally
local nextStage = currentStage + 1
-- # TODO might want to check if the key is actually a button that exists (maybe do this in the initial checks when script starts?)
local key = MyVehicleConfig.stages.stageKeys[nextStage]
local extra = GetExtraByKey(key)
local button = GetButtonByExtra(extra)
if not button then
print("[stageUp()] Could not find button for extra " .. extra)
return
end
print("Setting stage to: " .. nextStage .. " using key " .. key .. " with extra " .. extra)
ULC:SetStage(extra, 0, true, false, button.repair or false, false, true, false)
end
function stageDown()
print("[ULC:stageDown] Decreasing stage from " .. currentStage)
if currentStage == 0 then
print("Already stage 0")
return
end
-- this is handled in ULC:SetStage?
-- currentStage = currentStage - 1
-- instead we just want to keep track locally
local nextStage = currentStage - 1
-- # TODO might want to check if the key is actually a button that exists (maybe do this in the initial checks when script starts?)
local key = MyVehicleConfig.stages.stageKeys[nextStage]
local extra = GetExtraByKey(key)
local button = GetButtonByExtra(extra)
if not button then
print("[stageDown()] Could not find button for extra " .. extra)
return
end
print("Setting stage to: " .. nextStage .. " using key " .. key .. " with extra " .. extra)
ULC:SetStage(extra, 0, true, false, button.repair or false, false, true, false)
end
function cycleStages()
if not checks() then return end
if currentStage == getMaxStage() then
print("Tried to cycle stages at max stage, resetting to 0")
-- we need to turn off the current stage
local key = MyVehicleConfig.stages.stageKeys[currentStage]
local extra = GetExtraByKey(key)
local button = GetButtonByExtra(extra)
if not button then
print("[cycleStages()] Could not find button for extra " .. extra)
return
end
print("Setting stage to: 0 using key " .. key .. " with extra " .. extra)
ULC:SetStage(extra, 1, true, false, button.repair or false, true, true, false)
return
end
stageUp()
end
-- Keybinds
RegisterKeyMapping("ulc:stage_down", "ULC: Stage Down", "keyboard", "SUBTRACT")
RegisterCommand("ulc:stage_down", function()
if not checks() then return end
stageDown()
end)
RegisterKeyMapping("ulc:stage_up", "ULC: Stage Up", "keyboard", "ADD")
RegisterCommand("ulc:stage_up", function()
if not checks() then return end
stageUp()
end)
RegisterKeyMapping("ulc:stage_cycle", "ULC: Cycle Stages", "keyboard", "NUMPAD0")
RegisterCommand("ulc:stage_cycle", function()
if not checks() then return end
cycleStages()
end)
--------------------
--------------------
-- DEFAULT STAGES --
--------------------
--------------------
-- checks if the button.key is contained in the stageKeys array and returns the index
function getStageFromButton(button)
if not button then return false end
if not MyVehicle then return false end
-- if MyVehicleConfig.stages.stageKeys is nil or doesn't contain the button.key return false
if not MyVehicleConfig.stages.stageKeys then return false end
for i, key in pairs(MyVehicleConfig.stages.stageKeys) do
if key == button.key then
return i
end
end
return false
end
function setDefaultStages()
-- default stages
if not MyVehicleConfig.defaultStages or false then return end
if not MyVehicleConfig.defaultStages.useDefaults then return end
for _, e in pairs(MyVehicleConfig.defaultStages.enableKeys) do
local button = GetButtonByExtra(GetExtraByKey(e))
if not button then break end
-- if the button is a stage
local stage = getStageFromButton(button)
-- if the index of this stage = the current stage do nothing
if stage and stage == currentStage then return end
-- if this button is not a stage or the stage is not the current stage proceed normally
ULC:SetStage(GetExtraByKey(e), 0, false, false, button.repair, true, true, false)
end
for _, d in pairs(MyVehicleConfig.defaultStages.disableKeys) do
local button = GetButtonByExtra(GetExtraByKey(d))
if not button then break end
ULC:SetStage(GetExtraByKey(d), 1, false, false, button.repair, true, true, false)
end
end
+85
View File
@@ -0,0 +1,85 @@
-- Ultimate Lighting Controller by Dawnstar FiveM
-- Written by Dawnstar
-- Documentation: https://docs.dwnstr.com/ulc/overview
-- For support: https://discord.gg/dwnstr-fivem
-- Most of these can be left at their default values.
-- View documentation for details on each value
Config = {
-- whether to enable control of lights on/off state using Q key
-- disabled by default to allow other scripts to control lights such as Luxart
-- make sure to disable light controls in other scripts if you enable this
controlLights = false,
-- HUD SETTINGS
-- global toggle for UI (affects all clients)
hideHud = false,
-- whether to use KPH instead of MPH
useKPH = false,
-- Park Pattern Settings;
ParkSettings = {
-- extras will toggle below this speed
speedThreshold = 1,
-- time between checks in seconds
-- should not be any lower than .5 seconds
delay = 0.5,
-- distance at which to check for other vehicles to sync patterns with
syncDistance = 32,
-- seconds before a single client triggers sync again
syncCooldown = 10,
},
-- Steady Burn Config;
-- changes settings for extras that are enabled at night, or enabled all the time.
SteadyBurnSettings = {
-- hour effect starts (extras are enabled)
nightStartHour = 18,
-- hour effect ends (extras are disabled)
nightEndHour = 6,
},
-- Brake Extras/Patterns Config;
-- temporarily empty as of v1.3.0
BrakeSettings = {},
-- Reverse Extras/Patterns Config;
-- introduced in v1.8.0
ReverseSettings = {
-- these options control the expiration of the reverse extras
-- if enabled, reverse extras will turn off after a random time between min and max
-- this is to simulate more realistic behavior where the vehicle would shifted out of reverse
-- after being stopped for some time
useRandomExpiration = true,
-- minimum time in seconds extras will stay on after stopping
minExpiration = 3,
-- maximum time in seconds extras will stay on after stopping
maxExpiration = 8,
},
-- Import confiurations here
-- Add the resource names of vehicle resources that include a ulc.lua config file
ExternalVehResources = {
-- ex. "my-police-vehicle",
"615",
"ccso1",
"24sub",
"24ramambo",
"704",
"640",
"128",
"gpd7",
"gpdchief1",
""st23tahoe"",
},
Vehicles = {
-- this is not required!
-- see documentation for instructions!
-- https://docs.dwnstr.com/ulc/configuration
}
}
+50
View File
@@ -0,0 +1,50 @@
fx_version 'cerulean'
games { 'gta5' }
lua54 'yes'
name "Ultimate Lighting Controls"
description "The ultimate non-els lighting controller. Documentation: https://docs.dwnstr.com/ulc/overview"
author "Dawnstar"
version "1.8.0"
ui_page "html/index.html"
files {
"html/index.html",
"html/assets/*.js",
"html/assets/*.css",
"html/assets/*.png",
"html/assets/*.jpg"
}
dependencies {
"baseevents",
"/onesync"
}
shared_scripts {
'config.lua',
'shared/shared_functions.lua'
}
client_scripts {
'client/c_main.lua',
'client/c_hud.lua',
'client/c_buttons.lua',
'client/c_brake.lua',
'client/c_blackout.lua',
'client/c_cruise.lua',
'client/c_horn.lua',
'client/c_park.lua',
'client/c_doors.lua',
'client/c_reverse.lua',
'client/c_stages.lua',
'client/c_beeps.lua',
}
server_scripts {
'server/s_main.lua',
'server/s_main.js',
'server/s_blackout.lua',
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+15
View File
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<script type="module" crossorigin src="./assets/index.7ebd96a6.js"></script>
<link rel="stylesheet" href="./assets/index.e1c6fa6f.css">
</head>
<body>
<div id="root"></div>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+7
View File
@@ -0,0 +1,7 @@
RegisterNetEvent('ulc:setBlackout', function(netId, state)
print("[ULC] Setting blackout to " .. tostring(state) .. " on vehicle " .. tostring(netId))
local vehicle = NetworkGetEntityFromNetworkId(netId)
Entity(vehicle).state.ulc_blackout = state
end)
+12
View File
@@ -0,0 +1,12 @@
print("[ULC] LVC Integrations Loaded")
-- triggers when player changes main siren state in LVC
-- newState is an int representing the index of a siren in lvc/SIRENS.lua:SIRENS
RegisterNetEvent("lvc:SetLxSirenState_s")
AddEventHandler("lvc:SetLxSirenState_s", function(newState)
local src = source
print("[lvc:SetLxSirenState_s] " .. src .. " " .. newState)
TriggerClientEvent("ulc:LVC_MainSirenStateChange", src, newState)
end)
-- TODO: this isn't use anywhere yet
+45
View File
@@ -0,0 +1,45 @@
// This API died :(
// https.get('https://api.countapi.xyz/hit/dwnstr.com/ulcloadcount/', (res) => {
// const { statusCode } = res;
// const contentType = res.headers['content-type'];
// let error;
// // Any 2xx status code signals a successful response but
// // here we're only checking for 200.
// if (statusCode !== 200) {
// error = new Error('Request Failed.\n' +
// `Status Code: ${statusCode}`);
// } else if (!/^application\/json/.test(contentType)) {
// error = new Error('Invalid content-type.\n' +
// `Expected application/json but received ${contentType}`);
// }
// if (error) {
// // console.error(error.message);
// // Consume response data to free up memory
// res.resume();
// return;
// }
// res.setEncoding('utf8');
// let rawData = '';
// res.on('data', (chunk) => { rawData += chunk; });
// res.on('end', () => {
// try {
// const parsedData = JSON.parse(rawData);
// console.log(`[ULC] ULC has been loaded on servers ${parsedData.value} times :D`);
// } catch (e) {
// // console.error(e.message);
// }
// });
// }).on('error', (e) => {
// // console.error(`Got error: ${e.message}`);
// });
// // Create a local server to receive data from
// const server = http.createServer((req, res) => {
// res.writeHead(200, { 'Content-Type': 'application/json' });
// res.end(JSON.stringify({
// data: 'Hello World!',
// }));
// });
+390
View File
@@ -0,0 +1,390 @@
print("Server thread loaded.")
AddEventHandler('ulc:error', function(error)
print("^1[ULC ERROR] " .. error)
end)
AddEventHandler('ulc:warn', function(error)
print("^3[ULC WARNING] " .. error)
end)
local myVersion = GetResourceMetadata("ulc", "version", 0)
local latestVersion = ''
if GetCurrentResourceName() ~= 'ulc' then
TriggerEvent('ulc:error', "Resource is named incorrectly. Version checks will not work.")
end
--TODO change loading state to use this instead of events
GlobalState.ulcloaded = false
PerformHttpRequest("https://api.github.com/repos/Flohhhhh/ultimate-lighting-controller/releases/latest",
function(errorCode, resultData, resultHeaders)
print("[ULC] My Version: [" .. myVersion .. "]")
local errorString = tostring(errorCode)
if errorString == "403" or errorString == "404" then
print("Got code " .. errorString .. " when trying to get version.")
return
end
latestVersion = json.decode(resultData).name
print("^0[ULC] Latest Version: [" .. latestVersion .. "]")
print([[
___ ___ ___ ________
|\ \|\ \ |\ \ |\ ____\
\ \ \\\ \\ \ \ \ \ \___|
\ \ \\\ \\ \ \ \ \ \
\ \ \\\ \\ \ \____ \ \ \____
\ \_______\\ \_______\\ \_______\
\|_______| \|_______| \|_______|
ULTIMATE LIGHTING CONTROLLER
by Dawnstar
^2Loaded
]])
if myVersion and ("v" .. myVersion) == latestVersion then
print('[ULC] Up to date!')
else
print("^1[ULC] OUTDATED. A NEW VERSION (" .. latestVersion .. ") IS AVAILABLE.^0")
print("^1[ULC] YOUR VERSION: " .. myVersion .. "^0")
print("[ULC] GET LATEST VERSION HERE: https://github.com/Flohhhhh/ultimate-lighting-controller/releases/")
end
end)
local function IsIntInTable(table, int)
for k, v in ipairs(table) do
if v == int then
return true
end
end
return false
end
if Config.ParkSettings.delay < 0.5 then
TriggerEvent("ulc:warn",
'Park Pattern delay is too short! This will hurt performance! Recommended values are above 0.5s.')
end
-- removed v1.7.0
-- if Config.SteadyBurnSettings.delay <= 2 then
-- TriggerEvent("ulc:error", 'Steady burn delay is too short! Steady burns will be unstable or not work!')
-- end
if Config.SteadyBurnSettings.nightStartHour < Config.SteadyBurnSettings.nightEndHour then
TriggerEvent("ulc:error", 'Steady burn night start hour should be later/higher than night end hour.')
end
-- removed v1.7.0
-- if Config.SteadyBurnSettings.delay < 2 then
-- TriggerEvent("ulc:error", "Steady burn check delay can never be lower than 2 seconds. Will cause stability issues.")
-- end
local function CheckData(data, resourceName)
if not data.name and not data.names then
TriggerEvent("ulc:error", "^1Vehicle config in resource \"" .. resourceName .. "\" does not include model names!^0")
return false
elseif data.name then
TriggerEvent("ulc:warn",
"^1Vehicle config in resource \"" ..
resourceName .. "\" uses deprecated 'name' field. Change to > names = {'yourvehicle'}^0")
if type(data.name) ~= "string" then
TriggerEvent("ulc:error",
"^1Vehicle config in resource \"" .. resourceName .. "\" 'name' field can only accept a string.^0")
return false
end
elseif data.names then
if type(data.names) ~= "table" then
TriggerEvent("ulc:error",
"^1Vehicle config in resource \"" .. resourceName .. "\" 'names' field can only accept a table of strings.^0")
return false
end
end
-- check if data is missing
if not data.parkConfig or not data.brakeConfig or not data.buttons or not data.hornConfig then
TriggerEvent("ulc:error",
"^1Vehicle config in resource \"" .. resourceName .. "\" is missing data or not formatted properly. View docs.^0")
return false
end
-- check if steady burns are enabled but no extras specified
if (data.steadyBurnConfig.forceOn or data.steadyBurnConfig.useTime) and #data.steadyBurnConfig.sbExtras == 0 then
TriggerEvent("ulc:warn",
'A config in "' .. resourceName .. '" uses Steady Burns, but no extras were specified (sbExtras = {})')
end
-- check if park pattern enabled but no extras specified
if data.parkConfig.usePark then
if #data.parkConfig.pExtras == 0 and #data.parkConfig.dExtras == 0 then
TriggerEvent("ulc:warn",
'A config in "' ..
resourceName .. '" uses Park Patterns, but no park or drive extras were specified (pExtras = {}, dExtras = {})')
end
end
-- check if brakes enabled but no extras specified
if data.brakeConfig.useBrakes and #data.brakeConfig.brakeExtras == 0 then
TriggerEvent("ulc:warn",
'A config in "' .. resourceName .. '" uses Brake Pattern, but no brake extras were specified.')
end
-- check if horn enabled but no extras specified
if data.hornConfig.useHorn and #data.hornConfig.hornExtras == 0 then
TriggerEvent("ulc:warn", 'A config in "' .. resourceName .. '" uses Horn Extras, but no horn extras were specified.')
end
-- stages
if data.stages then
-- check if stages are enabled but no keys specified
if data.stages.useStages and #data.stages.stageKeys == 0 then
TriggerEvent("ulc:warn",
'A config in "' .. resourceName .. '" uses Stages, but no keys were specified.')
end
-- check each key
for _, v in pairs(data.stages.stageKeys) do
-- if key is not a numpad value
if v > 9 then
TriggerEvent("ulc:error",
'A config in "' ..
resourceName ..
'" has an invalid key in stageKeys (' .. v .. '). Value must be 1-9 representing numpad keys.')
break
end
-- make sure each item in data.stages.stageKeys corresponds to a button with key = the value
local buttonExists = false
for _, b in pairs(data.buttons) do
if b.key == v then
buttonExists = true
break
end
end
if not buttonExists then
TriggerEvent("ulc:error",
'A config in "' ..
resourceName ..
'" has a key in stageKeys (' .. v .. ') that does not correspond to a key assigned to a button.')
end
end
end
--------------------
-- DEFAULT STAGES --
--------------------
if data.defaultStages or false then
if data.defaultStages.useDefaults then
if #data.defaultStages.enableKeys == 0 and #data.defaultStages.disableKeys == 0 then
TriggerEvent("ulc:warn",
'A config in "' ..
resourceName ..
'" uses Default Stages, but no keys were specified to enable (enableKeys = {}) or disable (disableKeys = {}).')
else
if #data.defaultStages.enableKeys > 0 then
for _, v in pairs(data.defaultStages.enableKeys) do
if v > 9 then
TriggerEvent("ulc:error",
'A config in "' ..
resourceName ..
'" has an invalid key in enableKeys = {}. Value must be 1-9 representing numpad keys.')
end
end
end
if #data.defaultStages.disableKeys > 0 then
for _, v in pairs(data.defaultStages.disableKeys) do
if v > 9 then
TriggerEvent("ulc:error",
'A config in "' ..
resourceName .. '" has an invalid key in disableKeys = {}. Value must be 1-9 representing numpad keys.')
end
end
end
end
end
end
-- Buttons
-- check if vehicle uses buttons but hud is disabled
if #data.buttons > 0 and Config.hideHud == true then
TriggerEvent("ulc:warn",
'A config in "' ..
resourceName ..
'" uses Stage Buttons, but HUD/UI is globally disabled. This is not recommended for user experience.')
end
local usedButtons = {}
local usedExtras = {}
for i, b in ipairs(data.buttons) do
-- check if key is valid
if b.key > 9 or b.key < 1 then
TriggerEvent('ulc:error',
'Button ' ..
i ..
' in a config found in the resource: "' ..
resourceName .. '" has an invalid key. Key must be 1-9 representing number pad keys.')
return false
end
-- check if label is empty
if b.label == '' then
TriggerEvent("ulc:error",
'A config in "' .. resourceName .. '" has an un-labeled button using extra: ' .. b.extra)
return false
end
if not validateButtonText(b.label) then
TriggerEvent("ulc:warn",
'A config in "' ..
resourceName ..
'" has a button with label: "' ..
b.label ..
'" which is not valid and will result in a poor user experience. Please make sure there are no more than 3 words and each word is a maximum of 5 characters. Use abbreviations where possible. Ex. "Takedowns" -> "TKD".')
end
if b.color and (b.color ~= 'blue' and b.color ~= 'green' and b.color ~= 'amber' and b.color ~= 'red') then
TriggerEvent("ulc:error",
'A config in "' ..
resourceName .. '" has a button with an invalid color input: "' .. b.color .. '" is not a supported color.')
end
-- check if any keys are used twice
if IsIntInTable(usedButtons, b.key) then
TriggerEvent("ulc:error",
'A config in "' .. resourceName .. '" uses key: " .. b.key .. " more than once in button config.')
return false
end
-- check if any extras are used twice
if IsIntInTable(usedExtras, b.extra) then
TriggerEvent("ulc:error",
'A config in "' .. resourceName .. '" uses extra: " .. b.extra .. " more than once in button config.')
return false
end
end
return true
end
RegisterNetEvent('baseevents:enteredVehicle')
AddEventHandler('baseevents:enteredVehicle', function()
local src = source
TriggerClientEvent("UpdateVehicleConfigs", src, Config.Vehicles)
TriggerClientEvent('ulc:checkVehicle', src)
end)
RegisterNetEvent('baseevents:leftVehicle')
AddEventHandler('baseevents:leftVehicle', function()
local src = source
TriggerClientEvent('ulc:cleanup', src)
end)
RegisterNetEvent('ulc:sync:send')
AddEventHandler('ulc:sync:send', function(vehicles)
print("Player " .. source .. " sent a sync request.")
local players = GetPlayers()
for i, v in ipairs(players) do
if not v == source then
--print("Sending veh sync array to player: " .. v)
TriggerClientEvent('ulc:sync:receive', vehicles)
end
end
end)
local function LoadExternalVehicleConfig(resourceName)
local resourceState = GetResourceState(resourceName)
if resourceState == "missing" then
TriggerEvent("ulc:error",
"^1Couldn't load external ulc.lua file from resource: \"" ..
resourceName ..
"\". Resource is missing. You probably entered the model name in config.lua instead of the resource name.^0")
return
end
if resourceState == "stopped" then
TriggerEvent("ulc:error",
"^1Couldn't load external ulc.lua file from resource: \"" .. resourceName .. "\". Resource is stopped.^0")
return
end
if resourceState == "uninitialized" or resourceState == "unknown" then
TriggerEvent("ulc:error",
"^1Couldn't load external ulc.lua file from resource: \"" ..
resourceName .. "\". Resource could not be loaded. Unknown issue.^0")
return
end
local data = LoadResourceFile(resourceName, "data/ulc.lua")
if not data then
data = LoadResourceFile(resourceName, "ulc.lua")
if not data then
print("Error loading 'ulc.lua' file. Make sure it is at the root of your resource or in the 'data' folder.")
TriggerEvent("ulc:error", '^1Could not load external configuration in: "' .. resourceName .. '"^0')
return
end
end
local f, err = load(data)
if err then
TriggerEvent("ulc:error",
'^1Could not load external configuration in: "' .. resourceName .. '"; error: "' .. err .. '"^0')
return
end
if not f or not f() then
TriggerEvent("ulc:error",
'^1Could not load external configuration; data loaded from: "' .. resourceName .. '" was nil. ^0')
return
end
-- NEW STUFF FOR MULTIPLE CONFIGS
local configs = { f() }
for _, v in pairs(configs) do
if CheckData(v, resourceName) then
if v.name then -- if using old single name
print('^2[ULC] Loaded external configuration for "' .. v.name .. '"^0')
elseif v.names then -- if using new table
for _, name in ipairs(v.names) do
print('^2[ULC] Loaded external configuration for "' .. name .. '"^0')
end
end
table.insert(Config.Vehicles, v)
else
TriggerEvent("ulc:error", '^1Could not load external configuration in "' .. resourceName .. '"^0')
end
end
-- if CheckData(f(), resourceName) then
-- print('^2Loaded external configuration for "' .. f().name .. '"^0')
-- table.insert(Config.Vehicles, f())
-- else
-- TriggerEvent("ulc:error", '^1Could not load external configuration for "' .. f().name .. '"^0')
-- end
end
CreateThread(function()
Wait(2000)
print("[ULC] Checking for external vehicle resources.")
for k, v in ipairs(Config.ExternalVehResources) do
local resourceState = GetResourceState(v)
while resourceState == "starting" do
print("^3[ULC] Waiting for resource: " .. resourceName .. " to load.")
Wait(100)
end
LoadExternalVehicleConfig(v)
end
--TriggerClientEvent('ulc:Loaded', -1)
GlobalState.ulcloaded = true
TriggerClientEvent("UpdateVehicleConfigs", -1, Config.Vehicles)
print("[ULC] Loading complete: " ..
#Config.Vehicles .. " external vehicle configurations loaded. State check: " .. tostring(GlobalState.ulcloaded))
for _, v in ipairs(Config.Vehicles) do
if v.name then -- if using old single name
print('[ULC] Loaded: ' .. v.name)
elseif v.names then -- if using new table
for _, name in ipairs(v.names) do
print('[ULC] Loaded: ' .. name)
end
end
end
end)
+110
View File
@@ -0,0 +1,110 @@
-- Returns: bool (whether vehicle was found), table (vehicle config info)
function GetVehicleFromConfig(vehicle)
for _, v in pairs(Config.Vehicles) do
-- if old method with just a string
if v.name then
-- find which vehicle matches
if GetEntityModel(vehicle) == GetHashKey(v.name) then
--print("Vehicle [" .. v.name .. "] was found in Config.")
return true, v
end
elseif v.names then -- if new method with a table
-- for each name check if it matches the vehicle
for _, n in ipairs(v.names) do
if GetEntityModel(vehicle) == GetHashKey(n) then
--print("Vehicle [" .. v.name .. "] was found in Config.")
return true, v
end
end
end
end
end
-- Returns whether a vehicle is in a table of vehicle spawn names given a vehicle handle
function IsVehicleInTable(vehicle, table)
--print(table)
for _, v in pairs(table) do
--print(v)
--print(GetHashKey(v))
--print(vehicle)
--print(GetEntityModel(vehicle))
if GetEntityModel(vehicle) == GetHashKey(v) then
return true, v
else
--print("Vehicle [" .. v .. "] not found in table.")
end
end
end
-- Returns the vehicle speed converted to MPH or KPH based on config value
function GetVehicleSpeedConverted(vehicle)
if Config.useKPH then
return GetEntitySpeed(Entity(vehicle)) * 3.6
else
return GetEntitySpeed(Entity(vehicle)) * 2.236936
end
end
-- returns true when all vehicle doors are fully closed
function AreVehicleDoorsClosed(vehicle)
local result = true
local numberOfDoors = GetNumberOfVehicleDoors(vehicle)
for i = 0, numberOfDoors, 1 do
if GetVehicleDoorAngleRatio(vehicle, i) > 0.0 then
--print("[AreVehicleDoorsClosed()] Door " .. i .. " is open.")
result = false
end
end
return result
end
-- returns true when vehicle health is above config threshold
function IsVehicleHealthy(vehicle)
local vehHealth = GetVehicleBodyHealth(vehicle)
if vehHealth > 980 then
return true
else
--print("[IsVehicleHealth())] Vehicle is damaged.")
return false
end
end
function SortButtonsByKey(arr)
table.sort(arr, function(a, b)
return a["key"] < b["key"]
end)
end
function formatInt(num)
local formatted = tostring(num)
local length = formatted:len()
for i = length - 3, 1, -3 do
formatted = formatted:sub(1, i) .. ',' .. formatted:sub(i + 1)
end
return formatted
end
function validateButtonText(text)
local count = 0
for word in text:gmatch("%w+") do
count = count + 1
if count > 3 or #word > 5 then
return false
end
end
return true
end
-- Function to check if a value exists in a table
-- Returns: bool (whether value is contained), int (index of value if contained)
function contains(table, val)
for i, v in ipairs(table) do
if v == val then
return i
end
end
return false
end