Files
red-valley/cache/files/VehicleDeformation/resource.rpf

303 lines
16 KiB
Plaintext
Raw Normal View History

2026-03-29 21:41:17 +03:00
RPF2<00><00>6 6"<00>8<00> <00><00>/clientmain.luadeformation.luafxmanifest.lua
local isDriver = false
local vehicle = nil
local currentlySetting = {}
-- main loop - checks for vehicles with deformation in a state bag and applies them if necessary
Citizen.CreateThread(function()
while (true) do
Citizen.Wait(1000)
local playerPed = PlayerPedId()
-- apply deformation
local vehicles = GetAllVehiclesWithStateBag("deformations")
for i, veh in ipairs(vehicles) do
if (currentlySetting[plate] == nil) then
local plate = GetVehicleNumberPlateText(veh)
currentlySetting[plate] = true
SetVehicleDeformation(veh, Entity(veh).state.deformations, function()
currentlySetting[plate] = nil
end)
end
end
if (not isInVehicle and IsPedInAnyVehicle(playerPed)) then
isInVehicle = true
vehicle = GetVehiclePedIsIn(playerPed)
elseif (isInVehicle and not IsPedInAnyVehicle(playerPed)) then
isInVehicle = false
isDriver = false
end
end
end)
Citizen.CreateThread(function()
local deformation = {}
while (true) do
Citizen.Wait(5000)
-- get deformation from current vehicle
if (isInVehicle and DoesEntityExist(vehicle)) then
local playerPed = PlayerPedId()
isDriver = GetPedInVehicleSeat(vehicle, -1) == playerPed
if (isDriver) then
local newDeformation = GetVehicleDeformation(vehicle)
if (IsDeformationWorse(newDeformation, deformation)) then
deformation = newDeformation
SyncVehicleDeformation(vehicle, deformation)
end
end
end
end
end)
-- returns all client side vehicles with a specified state bag
function GetAllVehiclesWithStateBag(bagName)
local stateVehicles = {}
local vehicles = GetGamePool("CVehicle")
for i, vehicle in ipairs(vehicles) do
if (NetworkGetEntityIsNetworked(vehicle) and Entity(vehicle).state[bagName]) then
table.insert(stateVehicles, vehicle)
end
end
return stateVehicles
end
function IsDeformationWorse(newDef, oldDef)
if (#newDef > #oldDef) then
return true
end
if (#newDef < #oldDef) then
return false
end
for i, new in ipairs(newDef) do
local found = false
for j, old in ipairs(oldDef) do
if (new[1] == old[1]) then
found = true
if (new[2] > old[2]) then
return true
end
end
end
if (not found) then
return true
end
end
return false
end
-- sync deformation to all players
function SyncVehicleDeformation(vehicle, deformation)
if (DoesEntityExist(vehicle) and NetworkGetEntityIsNetworked(vehicle)) then
Log("Syncing deformation to other players.")
TriggerServerEvent("VehicleDeformation:sync_sv", NetworkGetNetworkIdFromEntity(vehicle), deformation or GetVehicleDeformation(vehicle))
end
end
-- fix deformation
function FixVehicleDeformation(vehicle)
if (DoesEntityExist(vehicle) and NetworkGetEntityIsNetworked(vehicle)) then
TriggerServerEvent("VehicleDeformation:fix_sv", NetworkGetNetworkIdFromEntity(vehicle))
end
end
exports("FixVehicleDeformation", FixVehicleDeformation)
RegisterNetEvent("VehicleDeformation:fix_cl")
AddEventHandler("VehicleDeformation:fix_cl", function(netId)
local vehicle = NetworkGetEntityFromNetworkId(netId)
if (DoesEntityExist(vehicle)) then
SetVehicleDeformationFixed(vehicle)
end
end)
local isDebug = false
-- iterations for damage application
local MAX_DEFORM_ITERATIONS = 50
-- the minimum damage value at a deformation point
local DEFORMATION_DAMAGE_THRESHOLD = 0.05
-- gets deformation from a vehicle
function GetVehicleDeformation(vehicle)
assert(vehicle ~= nil and DoesEntityExist(vehicle), "Parameter \"vehicle\" must be a valid vehicle entity!")
-- check vehicle size and pre-calc values for offsets
local min, max = GetModelDimensions(GetEntityModel(vehicle))
local X = (max.x - min.x) * 0.5
local Y = (max.y - min.y) * 0.5
local Z = (max.z - min.z) * 0.5
local halfY = Y * 0.5
-- offsets for deformation check
local positions = {
vector3(-X, Y, 0.0),
vector3(-X, Y, Z),
vector3(0.0, Y, 0.0),
vector3(0.0, Y, Z),
vector3(X, Y, 0.0),
vector3(X, Y, Z),
vector3(-X, halfY, 0.0),
vector3(-X, halfY, Z),
vector3(0.0, halfY, 0.0),
vector3(0.0, halfY, Z),
vector3(X, halfY, 0.0),
vector3(X, halfY, Z),
vector3(-X, 0.0, 0.0),
vector3(-X, 0.0, Z),
vector3(0.0, 0.0, 0.0),
vector3(0.0, 0.0, Z),
vector3(X, 0.0, 0.0),
vector3(X, 0.0, Z),
vector3(-X, -halfY, 0.0),
vector3(-X, -halfY, Z),
vector3(0.0, -halfY, 0.0),
vector3(0.0, -halfY, Z),
vector3(X, -halfY, 0.0),
vector3(X, -halfY, Z),
vector3(-X, -Y, 0.0),
vector3(-X, -Y, Z),
vector3(0.0, -Y, 0.0),
vector3(0.0, -Y, Z),
vector3(X, -Y, 0.0),
vector3(X, -Y, Z),
}
-- get deformation from vehicle
local deformationPoints = {}
for i, pos in ipairs(positions) do
-- translate damage from vector3 to a float
local dmg = #(GetVehicleDeformationAtPos(vehicle, pos))
if (dmg > DEFORMATION_DAMAGE_THRESHOLD) then
table.insert(deformationPoints, { pos, dmg })
end
end
Log("Got " .. tostring(#deformationPoints) .. " deformation point" .. (#deformationPoints == 1 and "" or "s") .. " from \"" .. tostring(GetVehicleNumberPlateText(vehicle)) .. "\"")
return deformationPoints
end
-- sets deformation on a vehicle
function SetVehicleDeformation(vehicle, deformationPoints, callback)
assert(vehicle ~= nil and DoesEntityExist(vehicle), "Parameter \"vehicle\" must be a valid vehicle entity!")
assert(deformationPoints ~= nil and type(deformationPoints) == "table", "Parameter \"deformationPoints\" must be a table!")
Citizen.CreateThread(function()
-- set radius and damage multiplier
local min, max = GetModelDimensions(GetEntityModel(vehicle))
local radius = #(max - min) * 40.0 -- might need some more experimentation
local damageMult = #(max - min) * 30.0 -- might need some more experimentation
local printMsg = false
for i, def in ipairs(deformationPoints) do
def[1] = vector3(def[1].x, def[1].y, def[1].z)
end
-- iterate over all deformation points and check if more than one application is necessary
-- looping is necessary for most vehicles that have a really bad damage model or take a lot of damage (e.g. neon, phantom3)
local deform = true
local iteration = 0
while (deform and iteration < MAX_DEFORM_ITERATIONS) do
if (not DoesEntityExist(vehicle)) then
Log("Vehicle \"" .. tostring(GetVehicleNumberPlateText(vehicle)) .. "\" got deleted mid-deformation.")
return
end
deform = false
-- apply deformation if necessary
for i, def in ipairs(deformationPoints) do
if (#(GetVehicleDeformationAtPos(vehicle, def[1])) < def[2]) then
SetVehicleDamage(
vehicle,
def[1] * 2.0,
def[2] * damageMult,
radius,
true
)
deform = true
if (not printMsg) then
Log("Applying deformation to \"" .. tostring(GetVehicleNumberPlateText(vehicle)) .. "\"")
printMsg = true
end
end
end
iteration = iteration + 1
Citizen.Wait(100)
end
if (printMsg) then
Log("Applying deformation finished for \"" .. tostring(GetVehicleNumberPlateText(vehicle)) .. "\"")
end
if (callback) then
callback()
end
end)
end
function Log(text)
if (isDebug) then
print(text)
end
end
exports("GetVehicleDeformation", GetVehicleDeformation)
exports("SetVehicleDeformation", SetVehicleDeformation)
fx_version 'cerulean'
games { 'gta5' }
client_script {
'deformation.lua',
'client/*.lua'
}
server_script {
'server/*.lua'
}
escrow_ignore {
'deformation.lua'
}