291 lines
9.4 KiB
Lua
291 lines
9.4 KiB
Lua
local lastRpm = 0.0
|
|
local lastThrottle = false
|
|
local lastPopTime = 0
|
|
local lastTwoStepTime = 0
|
|
local lastAntiLagTime = 0
|
|
local justFiredPop = false
|
|
|
|
local state = {
|
|
systemEnabled = false,
|
|
twoStepActive = false,
|
|
antiLagActive = false
|
|
}
|
|
|
|
local AllowedCarsCache = {}
|
|
|
|
RegisterNetEvent("2step:Anti-lag")
|
|
RegisterNetEvent("c_eff_flames")
|
|
|
|
CreateThread(function()
|
|
Wait(500)
|
|
if Config and Config.TwoStepCars then
|
|
for _, car in pairs(Config.TwoStepCars) do
|
|
AllowedCarsCache[GetHashKey(car)] = true
|
|
end
|
|
end
|
|
end)
|
|
|
|
function IsAllowedCar(model)
|
|
if AllowedCarsCache[model] then return true end
|
|
local ped = PlayerPedId()
|
|
local veh = GetVehiclePedIsIn(ped, false)
|
|
if veh ~= 0 then
|
|
local class = GetVehicleClass(veh)
|
|
for _, allowedClass in ipairs(Config.AllowedClasses) do
|
|
if class == allowedClass then return true end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
AddEventHandler("2step:Anti-lag", function()
|
|
state.systemEnabled = not state.systemEnabled
|
|
Notif(state.systemEnabled and "~b~System Enabled" or "~r~System Disabled")
|
|
end)
|
|
|
|
--[[
|
|
PopStyle:
|
|
1 = Einzelner scharfer Knall
|
|
2 = Doppelknall (40-80ms)
|
|
3 = Kurzes Rattern (3-4 Pops)
|
|
4 = Leises Einzelknacken
|
|
]]
|
|
function TriggerPopStyle(veh, style)
|
|
if style == 1 then
|
|
if DoesEntityExist(veh) then
|
|
TriggerBackfire(veh, GetEntityCoords(veh), 1.0)
|
|
end
|
|
|
|
elseif style == 2 then
|
|
CreateThread(function()
|
|
if DoesEntityExist(veh) then TriggerBackfire(veh, GetEntityCoords(veh), 1.0) end
|
|
Wait(math.random(40, 80))
|
|
if DoesEntityExist(veh) then TriggerBackfire(veh, GetEntityCoords(veh), 0.8) end
|
|
end)
|
|
|
|
elseif style == 3 then
|
|
local count = math.random(1, 2)
|
|
CreateThread(function()
|
|
for i = 1, count do
|
|
if DoesEntityExist(veh) then
|
|
TriggerBackfire(veh, GetEntityCoords(veh), math.random(6, 10) / 10)
|
|
end
|
|
Wait(math.random(30, 70))
|
|
end
|
|
end)
|
|
|
|
elseif style == 4 then
|
|
if DoesEntityExist(veh) then
|
|
TriggerBackfire(veh, GetEntityCoords(veh), 0.5)
|
|
end
|
|
end
|
|
end
|
|
|
|
function PickPopStyle(rpm)
|
|
local roll = math.random(1, 100)
|
|
|
|
if rpm >= 0.75 then
|
|
-- Hohe RPM: 60% nichts, 40% irgendwas
|
|
if roll <= 60 then return nil
|
|
elseif roll <= 75 then return 1
|
|
elseif roll <= 88 then return 2
|
|
elseif roll <= 96 then return 3
|
|
else return 4
|
|
end
|
|
|
|
elseif rpm >= 0.55 then
|
|
-- Mittlere RPM: 70% nichts, 30% irgendwas
|
|
if roll <= 70 then return nil
|
|
elseif roll <= 88 then return 1
|
|
elseif roll <= 96 then return 2
|
|
else return 4
|
|
end
|
|
|
|
else
|
|
-- Niedrige RPM: 85% nichts
|
|
if roll <= 85 then return nil
|
|
elseif roll <= 95 then return 4
|
|
else return 1
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Main-Thread
|
|
CreateThread(function()
|
|
while true do
|
|
local sleep = 1000
|
|
local ped = PlayerPedId()
|
|
local veh = GetVehiclePedIsIn(ped, false)
|
|
|
|
if veh ~= 0 and GetPedInVehicleSeat(veh, -1) == ped then
|
|
sleep = 0
|
|
local model = GetEntityModel(veh)
|
|
|
|
if IsAllowedCar(model) then
|
|
local rpm = GetVehicleCurrentRpm(veh)
|
|
local coords = GetEntityCoords(veh)
|
|
local throttle = IsControlPressed(0, 71)
|
|
local brake = IsControlPressed(0, 72)
|
|
local time = GetGameTimer()
|
|
|
|
-- Guard reset: erst nach 6-10 Sekunden wieder erlaubt
|
|
if justFiredPop and time - lastPopTime > math.random(6000, 10000) then
|
|
justFiredPop = false
|
|
end
|
|
|
|
if state.systemEnabled then
|
|
|
|
-- 🔥 2 STEP
|
|
if IsControlPressed(0, Config.twoStepControl) then
|
|
if rpm > 0.3 and rpm < 0.5 then
|
|
state.twoStepActive = true
|
|
if time - lastTwoStepTime > math.random(150, 350) then
|
|
TriggerBackfire(veh, coords, 1.0)
|
|
lastTwoStepTime = time
|
|
end
|
|
else
|
|
state.twoStepActive = false
|
|
end
|
|
else
|
|
state.twoStepActive = false
|
|
end
|
|
|
|
-- 🔥 ANTI LAG
|
|
if not throttle and not brake then
|
|
if rpm > 0.75 then
|
|
state.antiLagActive = true
|
|
SetVehicleTurboPressure(veh, 25.0)
|
|
if time - lastAntiLagTime > math.random(200, 400) then
|
|
TriggerBackfire(veh, coords, 1.0)
|
|
lastAntiLagTime = time
|
|
end
|
|
else
|
|
state.antiLagActive = false
|
|
end
|
|
else
|
|
state.antiLagActive = false
|
|
end
|
|
|
|
-- 💥 POPS & BANGS
|
|
if not state.antiLagActive then
|
|
|
|
-- Gas losgelassen → frühestens alle 6-10s ein Pop möglich
|
|
if lastThrottle and not throttle and not justFiredPop and rpm >= 0.45 then
|
|
local style = PickPopStyle(rpm)
|
|
if style then
|
|
TriggerPopStyle(veh, style)
|
|
end
|
|
lastPopTime = time
|
|
justFiredPop = true
|
|
end
|
|
|
|
-- Random Cruise Pop: extrem selten (1 von 500 Frames, + langer Cooldown)
|
|
if not throttle and not brake and rpm > 0.35 and rpm < 0.7 and not justFiredPop then
|
|
if math.random(1, 500) < 1 then
|
|
if time - lastPopTime > math.random(8000, 15000) then
|
|
TriggerPopStyle(veh, math.random(1, 2))
|
|
lastPopTime = time
|
|
justFiredPop = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
else
|
|
state.twoStepActive = false
|
|
state.antiLagActive = false
|
|
end
|
|
|
|
lastRpm = rpm
|
|
lastThrottle = throttle
|
|
|
|
if state.twoStepActive then
|
|
DrawHudText("2STEP", {0,255,100,255}, 0.91, 0.87, 0.6, 0.6, 4)
|
|
elseif state.antiLagActive then
|
|
DrawHudText("ANTI-LAG", {0,255,100,255}, 0.91, 0.87, 0.6, 0.6, 4)
|
|
end
|
|
|
|
else
|
|
state.twoStepActive = false
|
|
state.antiLagActive = false
|
|
end
|
|
else
|
|
state.twoStepActive = false
|
|
state.antiLagActive = false
|
|
end
|
|
|
|
Wait(sleep)
|
|
end
|
|
end)
|
|
|
|
function TriggerBackfire(veh, coords, scale)
|
|
scale = scale or 1.0
|
|
local netId = VehToNet(veh)
|
|
TriggerServerEvent("eff_flames", netId)
|
|
AddExplosion(coords.x, coords.y, coords.z, 61, 0.0, true, true, 0.0)
|
|
end
|
|
|
|
local flameBones = {
|
|
"exhaust",
|
|
"exhaust_2",
|
|
"exhaust_3",
|
|
"exhaust_4"
|
|
}
|
|
|
|
AddEventHandler("c_eff_flames", function(netVeh)
|
|
local veh = NetToVeh(netVeh)
|
|
if not DoesEntityExist(veh) then return end
|
|
|
|
local rpm = GetVehicleCurrentRpm(veh)
|
|
|
|
for _, bone in pairs(flameBones) do
|
|
local boneIndex = GetEntityBoneIndexByName(veh, bone)
|
|
if boneIndex ~= -1 then
|
|
CreateThread(function()
|
|
UseParticleFxAssetNextCall("core")
|
|
|
|
local size = math.random(10, 25) / 10
|
|
local offsetX = math.random(-3, 3) / 100
|
|
local offsetY = math.random(-3, 3) / 100
|
|
local offsetZ = math.random(-2, 2) / 100
|
|
local rotZ = math.random(-10, 10)
|
|
|
|
local r, g, b = 255, 120, 0
|
|
if rpm > 0.75 then
|
|
r, g, b = 100, 100, 255
|
|
end
|
|
|
|
local fx = StartParticleFxLoopedOnEntityBone(
|
|
"veh_backfire",
|
|
veh,
|
|
offsetX, offsetY, offsetZ,
|
|
0.0, 0.0, rotZ,
|
|
boneIndex,
|
|
size,
|
|
false, false, false
|
|
)
|
|
|
|
SetParticleFxLoopedColour(fx, r/255, g/255, b/255)
|
|
Wait(math.random(20, 50))
|
|
StopParticleFxLooped(fx, 1)
|
|
end)
|
|
end
|
|
end
|
|
end)
|
|
|
|
function DrawHudText(text, color, x, y, scaleX, scaleY, font)
|
|
SetTextFont(font)
|
|
SetTextScale(scaleX, scaleY)
|
|
SetTextColour(color[1], color[2], color[3], color[4])
|
|
SetTextOutline()
|
|
SetTextCentre(false)
|
|
SetTextEntry("STRING")
|
|
AddTextComponentString(text)
|
|
DrawText(x, y)
|
|
end
|
|
|
|
function Notif(text)
|
|
SetNotificationTextEntry("STRING")
|
|
AddTextComponentString(text)
|
|
DrawNotification(false, false)
|
|
end |