1459 lines
68 KiB
Lua
1459 lines
68 KiB
Lua
-- Cheat Menu - Cheat menu for Grand Theft Auto SanAndreas
|
|
-- Copyright (C) 2019-2020 Grinch_
|
|
|
|
-- This program is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
|
-- (at your option) any later version.
|
|
|
|
-- This program is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details.
|
|
|
|
-- You should have received a copy of the GNU General Public License
|
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
local module = {}
|
|
|
|
module.tvehicle =
|
|
{
|
|
aircraft =
|
|
{
|
|
camera = imgui.new.bool(fconfig.Get('tvehicle.aircraft.camera',false)),
|
|
index = fconfig.Get('tvehicle.aircraft.index',2),
|
|
spawn_in_air = imgui.new.bool(fconfig.Get('tvehicle.aircraft.spawn_in_air',true)),
|
|
zoom = { -5.0,-15.0,-20.0,-30.0,-40.0},
|
|
},
|
|
apply_material_filter = imgui.new.bool(fconfig.Get('tvehicle.apply_material_filter',true)),
|
|
car_engine = imgui.new.int(fconfig.Get('tvehicle.car_engine',fconst.CHECKBOX_STATE.NOT_CONFIGURED)),
|
|
color =
|
|
{
|
|
car_data_table = {},
|
|
col_data_table = {},
|
|
default = -1,
|
|
radio_btn = imgui.new.int(1),
|
|
rgb = imgui.new.float[3](0.0,0.0,0.0),
|
|
show_all = imgui.new.bool(fconfig.Get('tvehicle.color.show_all',false))
|
|
},
|
|
components =
|
|
{
|
|
enable_saving = imgui.new.bool(fconfig.Get('tvehicle.components.enable_saving',false)),
|
|
save_data = fconfig.Get('tvehicle.components.save_data',{}),
|
|
images = {},
|
|
list = {},
|
|
names = {},
|
|
path = tcheatmenu.dir .. "vehicles\\components\\",
|
|
saved = false,
|
|
selected = imgui.new.int(0),
|
|
value = imgui.new.int(0),
|
|
},
|
|
doors = {"Hood","Boot","Front left door","Front right door","Rear left door","Rear right door","All"},
|
|
door_menu_button = imgui.new.int(0),
|
|
first_person_camera =
|
|
{
|
|
bool = imgui.new.bool(fconfig.Get('tvehicle.first_person_camera.bool',false)),
|
|
offsets = fcommon.LoadJson("first person camera offsets"),
|
|
offset_x_var = imgui.new.float(0),
|
|
offset_y_var = imgui.new.float(0),
|
|
offset_z_var = imgui.new.float(0),
|
|
},
|
|
gxt_name = imgui.new.char[32](""),
|
|
gxt_name_table = fconfig.Get('tvehicle.gxt_name_table',{}),
|
|
handling_flags = fcommon.LoadJson("handling flags"),
|
|
handling_name = {},
|
|
heavy = imgui.new.bool(fconfig.Get('tvehicle.heavy',false)),
|
|
images = {},
|
|
invisible_car = imgui.new.bool(fconfig.Get('tvehicle.invisible_car',false)),
|
|
license_plate_text = imgui.new.char[9](fconfig.Get('tvehicle.license_plate_text',"GTA__SAN")),
|
|
lights = imgui.new.bool(fconfig.Get('tvehicle.lights',false)),
|
|
lock_doors = imgui.new.bool(false),
|
|
lock_speed = imgui.new.bool(fconfig.Get('tvehicle.lock_speed',false)),
|
|
max_velocity_temp = imgui.new.int(-1),
|
|
model_flags = fcommon.LoadJson("model flags"),
|
|
names = fcommon.LoadJson("vehicle"),
|
|
paintjobs =
|
|
{
|
|
cache_images = {},
|
|
current_paintjob = imgui.new.int(-1);
|
|
enable_saving = imgui.new.bool(fconfig.Get('tvehicle.paintjobs.enable_saving',false)),
|
|
save_data = fconfig.Get('tvehicle.paintjobs.save_data',{}),
|
|
names = 0,
|
|
path = tcheatmenu.dir .. "vehicles\\paintjobs",
|
|
paintjobs_count = 0,
|
|
images = {},
|
|
texture = nil
|
|
},
|
|
neon =
|
|
{
|
|
checkbox = imgui.new.bool(fconfig.Get('tvehicle.neon.checkbox',false)),
|
|
data = fcommon.LoadJson("neon data"),
|
|
rgb = imgui.new.float[3](0.0,0.0,0.0),
|
|
rb_value = imgui.new.int(-1),
|
|
},
|
|
no_vehicles = imgui.new.bool(fconfig.Get('tvehicle.no_vehicles',false)),
|
|
no_damage = imgui.new.bool(fconfig.Get('tvehicle.no_damage',false)),
|
|
path = tcheatmenu.dir .. "vehicles\\images",
|
|
rainbow_colors =
|
|
{
|
|
bool = imgui.new.bool(fconfig.Get('tvehicle.rainbow_colors.bool',false)),
|
|
traffic = imgui.new.bool(fconfig.Get('tvehicle.rainbow_colors.traffic',false)),
|
|
speed = imgui.new.float(fconfig.Get('tvehicle.rainbow_colors.speed',0.5)),
|
|
},
|
|
rainbow_neons =
|
|
{
|
|
bool = imgui.new.bool(fconfig.Get('tvehicle.rainbow_neons.bool',false)),
|
|
traffic = imgui.new.bool(fconfig.Get('tvehicle.rainbow_neons.traffic',false)),
|
|
speed = imgui.new.float(fconfig.Get('tvehicle.rainbow_neons.speed',0.5)),
|
|
},
|
|
spawn_inside = imgui.new.bool(fconfig.Get('tvehicle.spawn_inside',true)),
|
|
speed = imgui.new.int(fconfig.Get('tvehicle.speed',0)),
|
|
stay_on_bike = imgui.new.bool(fconfig.Get('tvehicle.stay_on_bike',false)),
|
|
trains =
|
|
{
|
|
["449"] = {8,9},
|
|
["537"] = {0,3,6,10,12,13},
|
|
["538"] = {1,5,15},
|
|
},
|
|
unlimited_nitro = imgui.new.bool(fconfig.Get('tvehicle.unlimited_nitro',false)),
|
|
visual_damage = imgui.new.bool(fconfig.Get('tvehicle.visual_damage',false)),
|
|
watertight_car = imgui.new.bool(fconfig.Get('tvehicle.watertight_car',false)),
|
|
}
|
|
|
|
--------------------------------------------------
|
|
-- Neon
|
|
|
|
result, handle = loadDynamicLibrary("neon_api.asi")
|
|
module.tvehicle.neon["Handle"] = handle
|
|
|
|
if module.tvehicle.neon["Handle"] ~= 0 then
|
|
result, proc = getDynamicLibraryProcedure("SetFlag",module.tvehicle.neon["Handle"])
|
|
module.tvehicle.neon["SetFlag"] = proc
|
|
|
|
result, proc = getDynamicLibraryProcedure("GetFlag",module.tvehicle.neon["Handle"])
|
|
module.tvehicle.neon["GetFlag"] = proc
|
|
|
|
result, proc = getDynamicLibraryProcedure("SetX",module.tvehicle.neon["Handle"])
|
|
module.tvehicle.neon["SetX"] = proc
|
|
|
|
result, proc = getDynamicLibraryProcedure("SetY",module.tvehicle.neon["Handle"])
|
|
module.tvehicle.neon["SetY"] = proc
|
|
|
|
result, proc = getDynamicLibraryProcedure("InstallNeon",module.tvehicle.neon["Handle"])
|
|
module.tvehicle.neon["InstallNeon"] = proc
|
|
|
|
result, proc = getDynamicLibraryProcedure("SetRed",module.tvehicle.neon["Handle"])
|
|
module.tvehicle.neon["SetRed"] = proc
|
|
|
|
result, proc = getDynamicLibraryProcedure("SetGreen",module.tvehicle.neon["Handle"])
|
|
module.tvehicle.neon["SetGreen"] = proc
|
|
|
|
result, proc = getDynamicLibraryProcedure("SetBlue",module.tvehicle.neon["Handle"])
|
|
module.tvehicle.neon["SetBlue"] = proc
|
|
end
|
|
|
|
function InstallNeon(car,color)
|
|
car = car or getCarCharIsUsing(PLAYER_PED)
|
|
local pveh = getCarPointer(car)
|
|
|
|
if module.tvehicle.neon["Handle"] ~= 0 then
|
|
if module.tvehicle.neon["InstallNeon"] and module.tvehicle.neon["SetX"] and module.tvehicle.neon["SetY"] then
|
|
callFunction(module.tvehicle.neon["InstallNeon"],3,3,pveh,0,0)
|
|
|
|
local data = module.tvehicle.neon.data[casts.CModelInfo.GetNameFromModel(getCarModel(car))] or { X = 0.0, Y = 0.0}
|
|
|
|
callFunction(module.tvehicle.neon["SetX"],2,2,pveh,data.X)
|
|
callFunction(module.tvehicle.neon["SetY"],2,2,pveh,data.Y)
|
|
|
|
callFunction(module.tvehicle.neon["SetRed"],2,2,pveh,color[1])
|
|
callFunction(module.tvehicle.neon["SetGreen"],2,2,pveh,color[2])
|
|
callFunction(module.tvehicle.neon["SetBlue"],2,2,pveh,color[3])
|
|
|
|
if module.tvehicle.paintjobs.enable_saving[0] then
|
|
fconfig.Set(module.tvehicle.paintjobs.save_data,string.format("%d.neon.red",getCarModel(car)),color[1])
|
|
fconfig.Set(module.tvehicle.paintjobs.save_data,string.format("%d.neon.green",getCarModel(car)),color[2])
|
|
fconfig.Set(module.tvehicle.paintjobs.save_data,string.format("%d.neon.blue",getCarModel(car)),color[3])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function module.TrafficNeons()
|
|
while module.tvehicle.neon.checkbox[0] and module.tvehicle.neon["Handle"] ~= 0 do
|
|
for hveh in fcommon.pool("veh") do
|
|
local temp = 0
|
|
|
|
if getVehicleClass(hveh) == fconst.VEHICLE_CLASS.NORMAL then
|
|
temp = math.random(1,20) -- 5%
|
|
end
|
|
if getVehicleClass(hveh) == fconst.VEHICLE_CLASS.RICH_FAMILY then
|
|
temp = math.random(1,5) -- 20%
|
|
end
|
|
if getVehicleClass(hveh) == fconst.VEHICLE_CLASS.EXECUTIVE then
|
|
temp = math.random(1,3) -- 30%
|
|
end
|
|
|
|
if temp == 1 and callFunction(module.tvehicle.neon["GetFlag"],1,1,hveh) ~= 0x10 then
|
|
if getCarCharIsUsing(PLAYER_PED) ~= hveh then
|
|
InstallNeon(hveh,{math.random(0,255),math.random(0,255),math.random(0,255)})
|
|
end
|
|
end
|
|
callFunction(module.tvehicle.neon["SetFlag"],2,2,hveh,0x10)
|
|
end
|
|
wait(100)
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------
|
|
|
|
function module.GiveVehicleToPlayer(model)
|
|
model = tonumber(model)
|
|
local vehicle = nil
|
|
local interior = getCharActiveInterior(PLAYER_PED)
|
|
|
|
if isModelAvailable(model) then
|
|
|
|
local x,y,z = getCharCoordinates(PLAYER_PED)
|
|
|
|
local speed = 0
|
|
|
|
if isCharInAnyCar(PLAYER_PED) and module.tvehicle.spawn_inside[0] then
|
|
|
|
local hveh = getCarCharIsUsing(PLAYER_PED)
|
|
speed = getCarSpeed(hveh)
|
|
|
|
warpCharFromCarToCoord(PLAYER_PED,x,y,z)
|
|
|
|
if casts.CModelInfo.IsTrainModel(model) then
|
|
deleteMissionTrain(hveh)
|
|
else
|
|
deleteCar(hveh)
|
|
end
|
|
end
|
|
|
|
if interior == 0 then
|
|
if (module.tvehicle.aircraft.spawn_in_air[0]) and (isThisModelAHeli(model) or isThisModelAPlane(model)) then
|
|
z = 400
|
|
end
|
|
else
|
|
z = z - 5
|
|
end
|
|
|
|
if casts.CModelInfo.IsTrainModel(model) then
|
|
|
|
local train_id_table = module.tvehicle.trains[tostring(model)]
|
|
local train_id = train_id_table[math.random(1,#train_id_table)]
|
|
|
|
-- Loading all train related models
|
|
requestModel(590)
|
|
requestModel(538)
|
|
requestModel(570)
|
|
requestModel(569)
|
|
requestModel(537)
|
|
requestModel(449)
|
|
|
|
loadAllModelsNow()
|
|
|
|
if math.random(0,1) == 0 then
|
|
vehicle = createMissionTrain(train_id,x,y,z)
|
|
else
|
|
vehicle = createMissionTrain(train_id,x,y,z,true)
|
|
end
|
|
|
|
deleteChar(getDriverOfCar(vehicle))
|
|
|
|
if module.tvehicle.spawn_inside[0] then
|
|
warpCharIntoCar(PLAYER_PED,vehicle)
|
|
setTrainCruiseSpeed(vehicle,speed)
|
|
end
|
|
|
|
markMissionTrainAsNoLongerNeeded(vehicle)
|
|
markModelAsNoLongerNeeded(590)
|
|
markModelAsNoLongerNeeded(538)
|
|
markModelAsNoLongerNeeded(570)
|
|
markModelAsNoLongerNeeded(569)
|
|
markModelAsNoLongerNeeded(537)
|
|
markModelAsNoLongerNeeded(449)
|
|
|
|
else
|
|
|
|
requestModel(model)
|
|
loadAllModelsNow()
|
|
|
|
customPlateForNextCar(model,ffi.string(module.tvehicle.license_plate_text))
|
|
|
|
if not module.tvehicle.spawn_inside[0] then
|
|
vehicle = spawnVehicleByCheating(model)
|
|
else
|
|
vehicle = createCar(model,x,y,z)
|
|
setCarHeading(vehicle,getCharHeading(PLAYER_PED))
|
|
warpCharIntoCar(PLAYER_PED,vehicle)
|
|
setCarForwardSpeed(vehicle,speed)
|
|
end
|
|
|
|
markCarAsNoLongerNeeded(vehicle)
|
|
markModelAsNoLongerNeeded(model)
|
|
end
|
|
|
|
if doesVehicleExist(vehicle) then
|
|
setVehicleInterior(vehicle,interior)
|
|
end
|
|
|
|
fcommon.CheatActivated()
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------
|
|
-- Camera
|
|
|
|
function module.AircraftCamera()
|
|
|
|
if module.tvehicle.aircraft.camera[0] then
|
|
if isCharInAnyHeli(PLAYER_PED)
|
|
or isCharInAnyPlane(PLAYER_PED) then
|
|
while isCharInAnyHeli(PLAYER_PED)
|
|
or isCharInAnyPlane(PLAYER_PED) do
|
|
|
|
-- FirstPersonCamera controls the camera if its enabled
|
|
if module.tvehicle.aircraft.camera[0] == false or module.tvehicle.first_person_camera.bool[0] then break end
|
|
|
|
local vehicle = getCarCharIsUsing(PLAYER_PED)
|
|
local roll = getCarRoll(vehicle)
|
|
|
|
attachCameraToVehicle(vehicle,0.0,module.tvehicle.aircraft.zoom[module.tvehicle.aircraft.index],2.5,0.0,0.0,0.0,(roll*-1),2)
|
|
if isKeyDown(0x56) then
|
|
while isKeyDown(0x56) do
|
|
wait(0)
|
|
end
|
|
module.tvehicle.aircraft.index = module.tvehicle.aircraft.index + 1
|
|
if module.tvehicle.aircraft.index > #module.tvehicle.aircraft.zoom then
|
|
module.tvehicle.aircraft.index = 0
|
|
end
|
|
end
|
|
wait(0)
|
|
end
|
|
restoreCameraJumpcut()
|
|
end
|
|
end
|
|
end
|
|
|
|
function module.FirstPersonCamera()
|
|
local total_x = 0
|
|
local total_y = 0
|
|
|
|
if module.tvehicle.first_person_camera.bool[0] and not isCharOnFoot(PLAYER_PED) and not fgame.tgame.camera.bool[0] then
|
|
while module.tvehicle.first_person_camera.bool[0] and not isCharOnFoot(PLAYER_PED) and not fgame.tgame.camera.bool[0] do
|
|
|
|
local hveh = getCarCharIsUsing(PLAYER_PED)
|
|
|
|
x,y = getPcMouseMovement()
|
|
total_x = total_x + x
|
|
total_y = total_y + y
|
|
|
|
local roll = 0.0
|
|
if module.tvehicle.aircraft.camera[0] == true then -- check if new aircraft camera is enabled
|
|
roll = getCarRoll(hveh)
|
|
end
|
|
|
|
if fgame.tgame.camera.bool[0] then
|
|
break
|
|
end
|
|
attachCameraToChar(PLAYER_PED,module.tvehicle.first_person_camera.offset_x_var[0], module.tvehicle.first_person_camera.offset_y_var[0], module.tvehicle.first_person_camera.offset_z_var[0], total_x, 180, total_y, (roll*-1), 2)
|
|
wait(0)
|
|
end
|
|
restoreCameraJumpcut()
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------
|
|
-- Color/ paintjob
|
|
|
|
function module.ForEachCarComponent(func,skip,car)
|
|
car = car or getCarCharIsUsing(PLAYER_PED)
|
|
if car ~= nil then
|
|
|
|
for _, comp in ipairs(mad.get_all_vehicle_components(car)) do
|
|
for _, obj in ipairs(comp:get_objects()) do
|
|
for _, mat in ipairs(obj:get_materials()) do
|
|
func(mat,comp,car)
|
|
if skip == true then
|
|
goto _skip
|
|
end
|
|
end
|
|
end
|
|
::_skip::
|
|
end
|
|
else
|
|
printHelpString("Player ~r~not ~w~in car")
|
|
end
|
|
end
|
|
|
|
function module.GetTextureName(name)
|
|
if name == nil then
|
|
return ""
|
|
else
|
|
return name
|
|
end
|
|
end
|
|
|
|
function module.ParseCarcols()
|
|
local file_path = string.format("%s/data/carcols.dat",getGameDirectory())
|
|
local col_data = false
|
|
local car_data = false
|
|
|
|
if doesFileExist(file_path) then
|
|
|
|
for line in io.lines(file_path) do
|
|
if line == "col" then
|
|
col_data = true
|
|
goto continue
|
|
end
|
|
if line == "car" or line == "car4" then
|
|
car_data = true
|
|
goto continue
|
|
end
|
|
if line == "end" then
|
|
if col_data then col_data = false end
|
|
if car_data then car_data = false end
|
|
goto continue
|
|
end
|
|
if col_data then
|
|
local r, g, b = string.match(line,"(%d+).(%d+).(%d+)")
|
|
|
|
if r and g and b then
|
|
table.insert(module.tvehicle.color.col_data_table,string.format("%d %d %d",r,g,b))
|
|
end
|
|
end
|
|
if car_data then
|
|
local name = nil
|
|
for x in string.gmatch(line,"[^,]+") do
|
|
if type(tonumber(x)) == "nil" then
|
|
name = string.upper(x)
|
|
module.tvehicle.color.car_data_table[name] = {}
|
|
end
|
|
if type(tonumber(x)) == "number" then
|
|
table.insert(module.tvehicle.color.car_data_table[name],tonumber(x))
|
|
end
|
|
end
|
|
end
|
|
::continue::
|
|
end
|
|
end
|
|
end
|
|
|
|
function module.ParseVehiclesIDE()
|
|
local file_path = string.format("%s/data/vehicles.ide",getGameDirectory())
|
|
local cars_data = false
|
|
local tt = module.tvehicle.handling_name
|
|
if doesFileExist(file_path) then
|
|
|
|
for line in io.lines(file_path) do
|
|
if line == "cars" then
|
|
cars_data = true
|
|
end
|
|
if line == "end" then
|
|
if cars_data then cars_data = false end
|
|
goto continue
|
|
end
|
|
if cars_data then
|
|
local name = nil
|
|
local t = {}
|
|
for x in string.gmatch(line,"[^,]+") do
|
|
x = x:gsub(".",{["\t"] ="",[","] = "",[" "] = ""})
|
|
table.insert(t,x)
|
|
end
|
|
t[1] = tonumber(t[1])
|
|
if t[1] ~= nil then
|
|
tt[t[1]] = t[5]
|
|
end
|
|
end
|
|
end
|
|
::continue::
|
|
end
|
|
end
|
|
|
|
function ApplyColor(load_saved_color,car)
|
|
|
|
|
|
module.ForEachCarComponent(function(mat,comp,car)
|
|
|
|
local r, g, b, old_a = mat:get_color()
|
|
local model = getCarModel(car)
|
|
|
|
if load_saved_color then
|
|
module.tvehicle.color.rgb[0] = fconfig.Get(string.format("%d.%s.red",model,comp.name),-1,module.tvehicle.paintjobs.save_data)
|
|
module.tvehicle.color.rgb[1] = fconfig.Get(string.format("%d.%s.green",model,comp.name),-1,module.tvehicle.paintjobs.save_data)
|
|
module.tvehicle.color.rgb[2] = fconfig.Get(string.format("%d.%s.blue",model,comp.name),-1,module.tvehicle.paintjobs.save_data)
|
|
end
|
|
|
|
if (module.tvehicle.color.rgb[0] ~= -1.0 and module.tvehicle.color.rgb[1] ~= -1.0 and module.tvehicle.color.rgb[2] ~= -1.0)
|
|
and (not module.tvehicle.apply_material_filter[0] or (r == 0x3C and g == 0xFF and b == 0x00) or (r == 0xFF and g == 0x00 and b == 0xAF)) then
|
|
|
|
local save_data = false
|
|
|
|
if module.tvehicle.components.selected[0] == 0 and not load_saved_color then
|
|
mat:set_color(module.tvehicle.color.rgb[0]*255, module.tvehicle.color.rgb[1]*255, module.tvehicle.color.rgb[2]*255, 255.0)
|
|
save_data = true
|
|
end
|
|
|
|
if comp.name == module.tvehicle.components.names[module.tvehicle.components.selected[0]+1] or load_saved_color then
|
|
mat:set_color(module.tvehicle.color.rgb[0]*255, module.tvehicle.color.rgb[1]*255, module.tvehicle.color.rgb[2]*255, 255.0)
|
|
save_data = true
|
|
end
|
|
|
|
if save_data and module.tvehicle.paintjobs.enable_saving[0] then
|
|
fconfig.Set(module.tvehicle.paintjobs.save_data,string.format("%d.%s.red",model,comp.name),module.tvehicle.color.rgb[0])
|
|
fconfig.Set(module.tvehicle.paintjobs.save_data,string.format("%d.%s.green",model,comp.name),module.tvehicle.color.rgb[1])
|
|
fconfig.Set(module.tvehicle.paintjobs.save_data,string.format("%d.%s.blue",model,comp.name),module.tvehicle.color.rgb[2])
|
|
end
|
|
end
|
|
module.tvehicle.color.default = getCarColours(car)
|
|
end,false,car)
|
|
end
|
|
|
|
function ApplyTexture(filename,load_saved_texture,car)
|
|
|
|
module.ForEachCarComponent(function(mat,comp,car)
|
|
local r, g, b, old_a = mat:get_color()
|
|
|
|
local model = getCarModel(car)
|
|
|
|
if load_saved_texture then
|
|
filename = fconfig.Get(string.format("%d.%s.texture",model,comp.name),nil,module.tvehicle.paintjobs.save_data)
|
|
end
|
|
|
|
if filename ~= nil then
|
|
local fullpath = module.tvehicle.paintjobs.path .. "\\" .. filename .. ".png"
|
|
|
|
if doesFileExist(fullpath) then
|
|
|
|
if module.tvehicle.paintjobs.cache_images[filename] == nil then
|
|
module.tvehicle.paintjobs.cache_images[filename] = mad.load_png_texture(fullpath)
|
|
end
|
|
|
|
module.tvehicle.paintjobs.texture = module.tvehicle.paintjobs.cache_images[filename]
|
|
|
|
|
|
if not module.tvehicle.apply_material_filter[0] or (r == 0x3C and g == 0xFF and b == 0x00) or (r == 0xFF and g == 0x00 and b == 0xAF) then
|
|
local save_data = false
|
|
|
|
if module.tvehicle.components.selected[0] == 0 and not load_saved_texture then
|
|
mat:set_texture(module.tvehicle.paintjobs.texture)
|
|
save_data = true
|
|
end
|
|
if comp.name == module.tvehicle.components.names[module.tvehicle.components.selected[0]+1] or load_saved_texture then
|
|
mat:set_texture(module.tvehicle.paintjobs.texture)
|
|
save_data = true
|
|
end
|
|
|
|
if save_data and module.tvehicle.paintjobs.enable_saving[0] then
|
|
fconfig.Set(module.tvehicle.paintjobs.save_data,string.format("%d.%s.texture",model,comp.name),filename)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
module.tvehicle.color.default = getCarColours(car)
|
|
end,false,car)
|
|
end
|
|
|
|
function Rainbow(speed)
|
|
local r = math.floor(math.sin(os.clock() * speed) * 127 + 128)
|
|
local g = math.floor(math.sin(os.clock() * speed + 2) * 127 + 128)
|
|
local b = math.floor(math.sin(os.clock() * speed + 4) * 127 + 128)
|
|
return r,g,b
|
|
end
|
|
|
|
function RainbowVehicleColor(hveh)
|
|
module.ForEachCarComponent(function(mat,comp,hveh)
|
|
local r,g,b = mat:get_color()
|
|
|
|
if not module.tvehicle.apply_material_filter[0]
|
|
or (r == 0x3C and g == 0xFF and b == 0x00) or (r == 0xFF and g == 0x00 and b == 0xAF) then
|
|
r,g,b = Rainbow(module.tvehicle.rainbow_colors.speed[0])
|
|
mat:set_color(r,g,b,255)
|
|
end
|
|
end,false,hveh)
|
|
end
|
|
|
|
function module.RainbowColors()
|
|
while module.tvehicle.rainbow_colors.bool[0] do
|
|
|
|
if module.tvehicle.rainbow_colors.traffic[0] then -- Player + Traffic
|
|
|
|
for hveh in fcommon.pool("veh") do
|
|
RainbowVehicleColor(hveh)
|
|
end
|
|
|
|
else -- Only Player
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local hveh = getCarCharIsUsing(PLAYER_PED)
|
|
RainbowVehicleColor(hveh)
|
|
else -- function not needed at this time
|
|
break
|
|
end
|
|
end
|
|
wait(0)
|
|
end
|
|
end
|
|
|
|
function module.RainbowNeons()
|
|
|
|
while module.tvehicle.rainbow_neons.bool[0] do
|
|
|
|
if module.tvehicle.rainbow_neons.traffic[0] then -- Player + Traffic
|
|
|
|
for hveh in fcommon.pool("veh") do
|
|
InstallNeon(hveh,{Rainbow(module.tvehicle.rainbow_neons.speed[0])})
|
|
end
|
|
|
|
else -- Only Player
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local hveh = getCarCharIsUsing(PLAYER_PED)
|
|
InstallNeon(hveh,{Rainbow(module.tvehicle.rainbow_neons.speed[0])})
|
|
else -- function not needed at this time
|
|
break
|
|
end
|
|
end
|
|
|
|
wait(0)
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------
|
|
-- Component/ tune
|
|
|
|
function StoreComponentData(hveh)
|
|
if module.tvehicle.components.enable_saving[0] then
|
|
local model = tostring(getCarModel(hveh))
|
|
module.tvehicle.components.save_data[model] = {}
|
|
|
|
for x=1,14,1 do
|
|
local comp_model = getCurrentCarMod(hveh,x)
|
|
|
|
if comp_model ~= -1 then
|
|
table.insert(module.tvehicle.components.save_data[model],comp_model)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function module.AddComponentToVehicle(component,car,hide_msg)
|
|
component = tonumber(component)
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
if car == nil then
|
|
car = getCarCharIsUsing(PLAYER_PED)
|
|
end
|
|
if isModelAvailable(component) and doesVehicleExist(car) then
|
|
requestVehicleMod(component)
|
|
loadAllModelsNow()
|
|
addVehicleMod(car,component)
|
|
|
|
StoreComponentData(car)
|
|
|
|
if hide_msg ~= true then
|
|
printHelpString("Component ~g~added")
|
|
end
|
|
markModelAsNoLongerNeeded(component)
|
|
end
|
|
end
|
|
end
|
|
|
|
function module.RemoveComponentFromVehicle(component,car,hide_msg)
|
|
component = tonumber(component)
|
|
if car == nil then
|
|
car = getCarCharIsUsing(PLAYER_PED)
|
|
end
|
|
if doesVehicleExist(car) then
|
|
removeVehicleMod(car,component)
|
|
|
|
StoreComponentData(car)
|
|
|
|
if hide_msg ~= true then
|
|
printHelpString("Component ~r~removed")
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------
|
|
-- Misc
|
|
|
|
function module.OnEnterVehicle()
|
|
|
|
while true do
|
|
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local hveh = getCarCharIsUsing(PLAYER_PED)
|
|
local pVeh = getCarPointer(hveh)
|
|
local model = getCarModel(hveh)
|
|
|
|
local model_name = module.tvehicle.gxt_name_table[casts.CModelInfo.GetNameFromModel(model)] or getGxtText(casts.CModelInfo.GetNameFromModel(model))
|
|
|
|
-- Get vehicle components
|
|
module.tvehicle.components.names = {"default"}
|
|
|
|
module.ForEachCarComponent(function(mat,comp,hveh)
|
|
table.insert(module.tvehicle.components.names,comp.name)
|
|
end,true)
|
|
module.tvehicle.components.list = imgui.new['const char*'][#module.tvehicle.components.names](module.tvehicle.components.names)
|
|
|
|
imgui.StrCopy(module.tvehicle.gxt_name,model_name)
|
|
|
|
if module.tvehicle.first_person_camera.offsets[tostring(model)] == nil then
|
|
module.tvehicle.first_person_camera.offsets[tostring(model)] =
|
|
{
|
|
["x"] = 0,
|
|
["y"] = 0.1,
|
|
["z"] = 0.6,
|
|
}
|
|
end
|
|
|
|
module.tvehicle.first_person_camera.offset_x_var[0] = module.tvehicle.first_person_camera.offsets[tostring(model)]["x"]
|
|
module.tvehicle.first_person_camera.offset_y_var[0] = module.tvehicle.first_person_camera.offsets[tostring(model)]["y"]
|
|
module.tvehicle.first_person_camera.offset_z_var[0] = module.tvehicle.first_person_camera.offsets[tostring(model)]["z"]
|
|
|
|
fcommon.CreateThread(module.AircraftCamera)
|
|
fcommon.CreateThread(module.FirstPersonCamera)
|
|
fcommon.CreateThread(module.RainbowColors)
|
|
fcommon.CreateThread(module.UnlimitedNitro)
|
|
|
|
module.tvehicle.paintjobs.current_paintjob[0] = fconfig.Get(string.format("%d.paintjob",model),nil,module.tvehicle.paintjobs.save_data) or getCurrentVehiclePaintjob(hveh)
|
|
module.tvehicle.paintjobs.paintjobs_count = getNumAvailablePaintjobs(hveh)
|
|
|
|
module.tvehicle.paintjobs.names = {"None"}
|
|
|
|
for i=1,module.tvehicle.paintjobs.paintjobs_count,1 do
|
|
table.insert(module.tvehicle.paintjobs.names, string.format("Paintjob %d",i))
|
|
end
|
|
|
|
|
|
if module.tvehicle.paintjobs.enable_saving[0] then
|
|
ApplyColor(true)
|
|
ApplyTexture(nil,true)
|
|
|
|
if getNumAvailablePaintjobs(hveh) >= module.tvehicle.paintjobs.current_paintjob[0] then
|
|
giveVehiclePaintjob(hveh,module.tvehicle.paintjobs.current_paintjob[0])
|
|
end
|
|
|
|
local color =
|
|
{
|
|
fconfig.Get(string.format("tvehicle.paintjobs.save_data.%d.neon.red",model),0),
|
|
fconfig.Get(string.format("tvehicle.paintjobs.save_data.%d.neon.green",model),0),
|
|
fconfig.Get(string.format("tvehicle.paintjobs.save_data.%d.neon.blue",model),0)
|
|
}
|
|
InstallNeon(hveh,color)
|
|
end
|
|
|
|
if module.tvehicle.components.enable_saving[0] then
|
|
for tmodel,table in pairs(module.tvehicle.components.save_data) do
|
|
if tmodel == tostring(model) then
|
|
for _,component in ipairs(table) do
|
|
module.AddComponentToVehicle(component,car,true)
|
|
end
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
while isCharInCar(PLAYER_PED,hveh) do
|
|
wait(0)
|
|
end
|
|
|
|
module.tvehicle.first_person_camera.offsets[tostring(model)].x = module.tvehicle.first_person_camera.offset_x_var[0]
|
|
module.tvehicle.first_person_camera.offsets[tostring(model)].y = module.tvehicle.first_person_camera.offset_y_var[0]
|
|
module.tvehicle.first_person_camera.offsets[tostring(model)].z = module.tvehicle.first_person_camera.offset_z_var[0]
|
|
module.tvehicle.max_velocity_temp[0] = -1
|
|
end
|
|
wait(0)
|
|
end
|
|
end
|
|
|
|
function DoorMenu(func)
|
|
local vehicle = getCarCharIsUsing(PLAYER_PED)
|
|
local seats = getMaximumNumberOfPassengers(vehicle) + 1 -- passenger + driver
|
|
|
|
if seats == 4 then
|
|
doors = 5
|
|
else
|
|
doors = 3
|
|
end
|
|
if imgui.Button(module.tvehicle.doors[7],imgui.ImVec2(fcommon.GetSize(1))) then
|
|
for i=0,doors,1 do
|
|
func(vehicle,i)
|
|
end
|
|
end
|
|
for i=0,doors,1 do
|
|
if imgui.Button(module.tvehicle.doors[i+1],imgui.ImVec2(fcommon.GetSize(2))) then
|
|
func(vehicle,i)
|
|
end
|
|
if i%2 ~= 1 then
|
|
imgui.SameLine()
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function module.UnlimitedNitro()
|
|
writeMemory(0x969165,1,0,true) -- ALl cars have nitro
|
|
writeMemory(0x96918B,1,0,true) -- All taxis have nitro
|
|
local hveh = getCarCharIsUsing(PLAYER_PED)
|
|
while isCharInCar(PLAYER_PED,hveh) and module.tvehicle.unlimited_nitro[0] and isThisModelACar(getCarModel(hveh)) do
|
|
|
|
if isKeyDown(vkeys.VK_LBUTTON) then
|
|
module.AddComponentToVehicle(1010,hveh,true)
|
|
while isKeyDown(vkeys.VK_LBUTTON) do
|
|
wait(0)
|
|
end
|
|
module.RemoveComponentFromVehicle(1010,hveh,true)
|
|
end
|
|
|
|
wait(0)
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------
|
|
-- Main
|
|
|
|
function module.VehicleMain()
|
|
if imgui.Button("Blow up cars",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
callFunction(0x439D80,0,0)
|
|
fcommon.CheatActivated()
|
|
end
|
|
imgui.SameLine()
|
|
if imgui.Button("Fix vehicle",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
fixCar(car)
|
|
fcommon.CheatActivated()
|
|
else
|
|
printHelpString("Player not in vehicle")
|
|
end
|
|
end
|
|
imgui.SameLine()
|
|
if imgui.Button("Flip vehicle",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
|
|
setCarRoll(car,getCarRoll(car) + 180)
|
|
setCarRoll(car,getCarRoll(car)) -- rotation fix
|
|
fcommon.CheatActivated()
|
|
else
|
|
printHelpString("Player not in vehicle")
|
|
end
|
|
end
|
|
|
|
if fcommon.BeginTabBar('VehiclesBar') then
|
|
if fcommon.BeginTabItem('Checkboxes') then
|
|
imgui.Columns(2,nil,false)
|
|
|
|
fcommon.CheckBoxValue("Aggressive drivers",0x96914F)
|
|
fcommon.CheckBoxValue("Aim while driving",0x969179)
|
|
fcommon.CheckBoxValue("All cars have nitro",0x969165)
|
|
fcommon.CheckBoxValue("All taxis have nitro",0x96918B)
|
|
fcommon.CheckBoxValue("Boats fly",0x969153)
|
|
fcommon.CheckBox3Var("Car engine",module.tvehicle.car_engine,"Set to 'No changes' if you're using\
|
|
mods which involve fuel systems")
|
|
fcommon.CheckBoxValue("Cars fly",0x969160)
|
|
fcommon.CheckBoxVar("Car heavy",module.tvehicle.heavy)
|
|
fcommon.CheckBoxValue("Decreased traffic",0x96917A)
|
|
fcommon.CheckBoxVar("Don't fall off bike",module.tvehicle.stay_on_bike)
|
|
fcommon.CheckBoxValue("Drive on water",0x969152)
|
|
if fcommon.CheckBoxVar("First person camera",module.tvehicle.first_person_camera.bool,nil,
|
|
function()
|
|
fcommon.InputFloat("Offset X", module.tvehicle.first_person_camera.offset_x_var,nil,-5,5,0.02)
|
|
fcommon.InputFloat("Offset Y", module.tvehicle.first_person_camera.offset_y_var,nil,-5,5,0.02)
|
|
fcommon.InputFloat("Offset Z", module.tvehicle.first_person_camera.offset_z_var,nil,-5,5,0.02)
|
|
end) then
|
|
fcommon.CreateThread(module.FirstPersonCamera)
|
|
end
|
|
if fcommon.CheckBoxVar("Fixed aircraft camera",module.tvehicle.aircraft.camera) then
|
|
fcommon.CreateThread(module.AircraftCamera)
|
|
end
|
|
fcommon.CheckBoxValue("Fixed train camera",5416239,nil,fconst.TRAIN_CAM_FIX.ON,fconst.TRAIN_CAM_FIX.OFF)
|
|
|
|
imgui.NextColumn()
|
|
|
|
fcommon.CheckBoxValue("Float away when hit",0x969166)
|
|
fcommon.CheckBoxValue("Green traffic lights",0x96914E)
|
|
if fcommon.CheckBoxVar("Invisible car",module.tvehicle.invisible_car) then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
setCarVisible(car,not module.tvehicle.invisible_car[0])
|
|
end
|
|
end
|
|
if fcommon.CheckBoxVar("Lights on",module.tvehicle.lights,nil,nil,false) then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local hveh = getCarCharIsUsing(PLAYER_PED)
|
|
if module.tvehicle.lights[0] then
|
|
forceCarLights(hveh,2)
|
|
addOneOffSound(x,y,z,1052)
|
|
fcommon.CheatActivated()
|
|
else
|
|
forceCarLights(hveh,1)
|
|
addOneOffSound(x,y,z,1053)
|
|
fcommon.CheatDeactivated()
|
|
end
|
|
else
|
|
printHelpString("Player ~r~not~w~ in car")
|
|
end
|
|
end
|
|
|
|
if fcommon.CheckBoxVar("Lock doors",module.tvehicle.lock_doors,nil,nil,false) then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
if getCarDoorLockStatus(car) == 4 then
|
|
lockCarDoors(car,1)
|
|
fcommon.CheatDeactivated()
|
|
else
|
|
lockCarDoors(car,4)
|
|
fcommon.CheatActivated()
|
|
end
|
|
else
|
|
printHelpString("Player ~r~not~w~ in car")
|
|
end
|
|
end
|
|
|
|
fcommon.CheckBoxVar("No damage",module.tvehicle.no_damage)
|
|
if fcommon.CheckBoxVar("No traffic vehicles",module.tvehicle.no_vehicles) then
|
|
if module.tvehicle.no_vehicles[0] then
|
|
writeMemory(0x434237,1,0x73,false) -- change condition to unsigned (0-255)
|
|
writeMemory(0x434224,1,0,false)
|
|
writeMemory(0x484D19,1,0x83,false) -- change condition to unsigned (0-255)
|
|
writeMemory(0x484D17,1,0,false)
|
|
else
|
|
writeMemory(0x434237,1,-1063242627,false) -- change condition to unsigned (0-255)
|
|
writeMemory(0x434224,1,940431405,false)
|
|
writeMemory(0x484D19,1,292493,false) -- change condition to unsigned (0-255)
|
|
writeMemory(0x484D17,1,1988955949,false)
|
|
end
|
|
end
|
|
|
|
fcommon.CheckBoxVar("No visual damage",module.tvehicle.visual_damage)
|
|
fcommon.CheckBoxValue("Perfect handling",0x96914C)
|
|
fcommon.CheckBoxValue("Tank mode",0x969164)
|
|
if fcommon.CheckBoxVar("Traffic neons",module.tvehicle.neon.checkbox,"Adds neon lights to traffic vehicles.\nOnly some vehicles will have them.") then
|
|
fcommon.CreateThread(fvehicle.TrafficNeons)
|
|
end
|
|
if fcommon.CheckBoxVar("Unlimited nitro",module.tvehicle.unlimited_nitro,"Nitro will activate when left clicked\n\nEnabling this would disable\nAll cars have nitro\nAll taxis have nitro") then
|
|
fcommon.CreateThread(module.UnlimitedNitro)
|
|
end
|
|
if fcommon.CheckBoxVar("Watertight car",module.tvehicle.watertight_car) then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
setCarWatertight(car,module.tvehicle.watertight_car[0])
|
|
end
|
|
end
|
|
fcommon.CheckBoxValue("Wheels only",0x96914B)
|
|
|
|
imgui.Columns(1)
|
|
end
|
|
if fcommon.BeginTabItem('Menus') then
|
|
fcommon.DropDownMenu("Enter nearest vehicle as",function()
|
|
local vehicle = storeClosestEntities(PLAYER_PED)
|
|
if vehicle ~= -1 then
|
|
local seats = getMaximumNumberOfPassengers(vehicle)
|
|
imgui.Spacing()
|
|
imgui.Columns(2,nil,false)
|
|
imgui.Text(casts.CModelInfo.GetNameFromModel(getCarModel(vehicle)))
|
|
imgui.NextColumn()
|
|
imgui.Text(string.format("Total seats: %d",seats+1))
|
|
imgui.Columns(1)
|
|
|
|
imgui.Spacing()
|
|
if imgui.Button("Driver",imgui.ImVec2(fcommon.GetSize(2))) then
|
|
warpCharIntoCar(PLAYER_PED,vehicle)
|
|
end
|
|
for i=0,seats-1,1 do
|
|
if i%2 ~= 1 then
|
|
imgui.SameLine()
|
|
end
|
|
if imgui.Button("Passenger " .. tostring(i+1),imgui.ImVec2(fcommon.GetSize(2))) then
|
|
warpCharIntoCarAsPassenger(PLAYER_PED,vehicle,i)
|
|
end
|
|
end
|
|
else
|
|
imgui.Text("No near by vehicles")
|
|
end
|
|
end)
|
|
fcommon.DropDownMenu("License plate text",function()
|
|
imgui.InputText("Text", module.tvehicle.license_plate_text,ffi.sizeof(module.tvehicle.license_plate_text))
|
|
fcommon.InformationTooltip("The text of vehicle license plate\nwhich you spawn using cheat-menu")
|
|
end)
|
|
|
|
fcommon.DropDownMenu("Traffic options",function()
|
|
fcommon.RadioButtonAddress("Color",{"Black","Pink"},{0x969151,0x969150})
|
|
imgui.Spacing()
|
|
fcommon.RadioButtonAddress("Type",{"Cheap","Country","Fast"},{0x96915E,0x96917B,0x96915F})
|
|
end)
|
|
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
local pCar = getCarPointer(car)
|
|
local model = getCarModel(car)
|
|
|
|
fcommon.UpdateAddress({name = 'Density multiplier',address = 0x8A5B20,size = 4,min = 0,max = 10, default = 1,is_float = true})
|
|
fcommon.UpdateAddress({name = 'Dirt level',address = pCar + 1200 ,size = 4,min = 0,max = 15, default = 7.5,is_float = true})
|
|
fcommon.DropDownMenu("Doors",function()
|
|
if isCharInAnyCar(PLAYER_PED) and not (isCharOnAnyBike(PLAYER_PED) or isCharInAnyBoat(PLAYER_PED)
|
|
or isCharInAnyHeli(PLAYER_PED) or isCharInAnyPlane(PLAYER_PED)) then
|
|
imgui.Columns(2,nil,false)
|
|
imgui.RadioButtonIntPtr("Damage", module.tvehicle.door_menu_button,0)
|
|
imgui.RadioButtonIntPtr("Fix", module.tvehicle.door_menu_button,1)
|
|
imgui.NextColumn()
|
|
imgui.RadioButtonIntPtr("Open", module.tvehicle.door_menu_button,2)
|
|
imgui.RadioButtonIntPtr("Pop", module.tvehicle.door_menu_button,3)
|
|
imgui.Columns(1)
|
|
|
|
imgui.Spacing()
|
|
|
|
if module.tvehicle.door_menu_button[0] == 0 then
|
|
if module.tvehicle.visual_damage[0] == false then
|
|
DoorMenu(function(vehicle,door)
|
|
damageCarDoor(vehicle,door)
|
|
end)
|
|
else
|
|
imgui.Text("No visual damage enabled")
|
|
end
|
|
end
|
|
if module.tvehicle.door_menu_button[0] == 1 then
|
|
DoorMenu(function(vehicle,door)
|
|
fixCarDoor(vehicle,door)
|
|
end)
|
|
end
|
|
if module.tvehicle.door_menu_button[0] == 2 then
|
|
DoorMenu(function(vehicle,door)
|
|
openCarDoor(vehicle,door)
|
|
end)
|
|
end
|
|
if module.tvehicle.door_menu_button[0] == 3 then
|
|
DoorMenu(function(vehicle,door)
|
|
popCarDoor(vehicle,door,true)
|
|
end)
|
|
end
|
|
else
|
|
imgui.Text("Player not in car")
|
|
end
|
|
|
|
end)
|
|
fcommon.DropDownMenu("Set name",function()
|
|
|
|
imgui.Text(string.format( "Model name = %s",casts.CModelInfo.GetNameFromModel(getCarModel(car))))
|
|
imgui.Spacing()
|
|
imgui.InputText("Name", module.tvehicle.gxt_name,ffi.sizeof(module.tvehicle.gxt_name))
|
|
|
|
imgui.Spacing()
|
|
if imgui.Button("Set",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
setGxtEntry(casts.CModelInfo.GetNameFromModel(getCarModel(car)),ffi.string(module.tvehicle.gxt_name))
|
|
fcommon.CheatActivated()
|
|
end
|
|
imgui.SameLine()
|
|
if imgui.Button("Save",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
module.tvehicle.gxt_name_table[casts.CModelInfo.GetNameFromModel(getCarModel(car))] = ffi.string(module.tvehicle.gxt_name)
|
|
end
|
|
imgui.SameLine()
|
|
if imgui.Button("Clear all",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
module.tvehicle.gxt_name_table = {}
|
|
end
|
|
end)
|
|
fcommon.DropDownMenu("Set speed",function()
|
|
|
|
fcommon.CheckBoxVar("Lock speed",module.tvehicle.lock_speed)
|
|
imgui.Spacing()
|
|
imgui.InputInt("Set",module.tvehicle.speed)
|
|
|
|
imgui.Spacing()
|
|
if imgui.Button("Set speed##brn",imgui.ImVec2(fcommon.GetSize(2))) then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
car = getCarCharIsUsing(PLAYER_PED)
|
|
setCarForwardSpeed(car,module.tvehicle.speed[0])
|
|
end
|
|
end
|
|
imgui.SameLine()
|
|
if imgui.Button("Instant stop",imgui.ImVec2(fcommon.GetSize(2))) then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
car = getCarCharIsUsing(PLAYER_PED)
|
|
setCarForwardSpeed(car,0.0)
|
|
end
|
|
end
|
|
if module.tvehicle.speed[0] > 500 then
|
|
module.tvehicle.speed[0] = 500
|
|
end
|
|
if module.tvehicle.speed[0] < 0 then
|
|
module.tvehicle.speed[0] = 0
|
|
end
|
|
end)
|
|
fcommon.UpdateAddress({name = 'Wheel scale',address = pCar+0x458,size = 4,min = 0,max = 10, default = 1,is_float = true})
|
|
end
|
|
end
|
|
if fcommon.BeginTabItem('Spawn') then
|
|
imgui.Columns(2,nil,false)
|
|
fcommon.CheckBoxVar("Spawn inside",module.tvehicle.spawn_inside,"Spawn inside vehicle as driver")
|
|
|
|
imgui.NextColumn()
|
|
fcommon.CheckBoxVar("Spawn aircraft in air",module.tvehicle.aircraft.spawn_in_air)
|
|
imgui.Columns(1)
|
|
|
|
imgui.Dummy(imgui.ImVec2(0,10))
|
|
fcommon.DrawEntries(fconst.IDENTIFIER.VEHICLE,fconst.DRAW_TYPE.IMAGE,module.GiveVehicleToPlayer,nil,casts.CModelInfo.GetNameFromModel,module.tvehicle.images,fconst.VEHICLE.IMAGE_HEIGHT,fconst.VEHICLE.IMAGE_WIDTH)
|
|
|
|
end
|
|
if fcommon.BeginTabItem('Paint') then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
local model = getCarModel(car)
|
|
|
|
if imgui.Button("Reset color",imgui.ImVec2(fcommon.GetSize(2))) then
|
|
|
|
module.ForEachCarComponent(function(mat,comp,car)
|
|
mat:reset_color()
|
|
end)
|
|
module.tvehicle.color.default = -1
|
|
printHelpString("Color reset")
|
|
end
|
|
imgui.SameLine()
|
|
if imgui.Button("Reset texture",imgui.ImVec2(fcommon.GetSize(2))) then
|
|
fconfig.tconfig.temp_texture_name = nil
|
|
module.ForEachCarComponent(function(mat,comp,car)
|
|
mat:reset_texture()
|
|
end)
|
|
module.tvehicle.paintjobs.texture = nil
|
|
printHelpString("Texture reset")
|
|
end
|
|
|
|
imgui.Spacing()
|
|
imgui.Columns(2,nil,false)
|
|
if fcommon.CheckBoxVar("Enable saving",module.tvehicle.paintjobs.enable_saving,"Save and load vehicle paint data.\nApplies for all vehicles of this model.") then
|
|
if module.tvehicle.paintjobs.enable_saving[0] then
|
|
ApplyColor(true)
|
|
end
|
|
end
|
|
fcommon.CheckBoxVar("Material filter",module.tvehicle.apply_material_filter,"Filters material while applying color/ texture\nDisable if something doesn't work properly")
|
|
imgui.NextColumn()
|
|
if fcommon.CheckBoxVar("Rainbow colors",module.tvehicle.rainbow_colors.bool,"Rainbow color effect on players vehicle",
|
|
function()
|
|
if fcommon.CheckBoxVar("Apply for traffic",module.tvehicle.rainbow_colors.traffic,"Rainbow color effect on traffic vehicles") then
|
|
fcommon.CreateThread(module.RainbowColors)
|
|
end
|
|
imgui.Dummy(imgui.ImVec2(0,20))
|
|
imgui.SliderFloat("Speed",module.tvehicle.rainbow_colors.speed,0,2)
|
|
end) then
|
|
fcommon.CreateThread(module.RainbowColors)
|
|
end
|
|
|
|
if fcommon.CheckBoxVar("Rainbow neons",module.tvehicle.rainbow_neons.bool,"Rainbow neon effect on players vehicle",
|
|
function()
|
|
fcommon.CheckBoxVar("Apply for traffic",module.tvehicle.rainbow_neons.traffic,"Rainbow neon effect on traffic vehicles",
|
|
function()
|
|
fcommon.CreateThread(module.RainbowNeons)
|
|
end)
|
|
imgui.Dummy(imgui.ImVec2(0,20))
|
|
imgui.SliderFloat("Speed",module.tvehicle.rainbow_neons.speed,0,2)
|
|
end) then
|
|
fcommon.CreateThread(module.RainbowNeons)
|
|
end
|
|
imgui.Columns(1)
|
|
imgui.Spacing()
|
|
|
|
if imgui.ColorEdit3("Color",module.tvehicle.color.rgb) then
|
|
ApplyColor()
|
|
end
|
|
fcommon.ConfigPanel("Color",function()
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
fcommon.CheckBoxVar("Show all carcol colors", module.tvehicle.color.show_all)
|
|
imgui.Spacing()
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
local name = casts.CModelInfo.GetNameFromModel(getCarModel(car))
|
|
|
|
local shown_colors = {}
|
|
imgui.Text("Color:")
|
|
imgui.Spacing()
|
|
imgui.Columns(2,nil,false)
|
|
imgui.RadioButtonIntPtr("Primary", module.tvehicle.color.radio_btn, 1)
|
|
imgui.RadioButtonIntPtr("Secondary", module.tvehicle.color.radio_btn, 2)
|
|
imgui.NextColumn()
|
|
imgui.RadioButtonIntPtr("Tertiary", module.tvehicle.color.radio_btn, 3)
|
|
imgui.RadioButtonIntPtr("Quaternary", module.tvehicle.color.radio_btn, 4)
|
|
imgui.Spacing()
|
|
imgui.Columns(1)
|
|
imgui.Text("Select color preset:")
|
|
imgui.Spacing()
|
|
|
|
if imgui.BeginChild("Colors") then
|
|
local x,y = fcommon.GetSize(1)
|
|
local btns_in_row = math.floor(imgui.GetWindowContentRegionWidth()/(y*2))
|
|
local btn_size = (imgui.GetWindowContentRegionWidth() - imgui.StyleVar.ItemSpacing*(btns_in_row-0.75*btns_in_row))/btns_in_row
|
|
local btn_count = 1
|
|
|
|
func = function(v)
|
|
if not shown_colors[v] then
|
|
local t = {}
|
|
local k = 1
|
|
|
|
for i in string.gmatch(module.tvehicle.color.col_data_table[v+1],"%w+") do
|
|
table.insert( t,tonumber(i))
|
|
end
|
|
|
|
if imgui.ColorButton("Color " .. tostring(v),imgui.ImVec4(t[1]/255,t[2]/255,t[3]/255,255),0,imgui.ImVec2(btn_size,btn_size)) then
|
|
writeMemory(getCarPointer(car) + 1075 + module.tvehicle.color.radio_btn[0],1,tonumber(v),false)
|
|
module.ForEachCarComponent(function(mat,comp,car)
|
|
mat:reset_color()
|
|
end)
|
|
end
|
|
if imgui.IsItemHovered() then
|
|
local drawlist = imgui.GetWindowDrawList()
|
|
drawlist:AddRectFilled(imgui.GetItemRectMin(), imgui.GetItemRectMax(), imgui.GetColorU32(imgui.Col.ModalWindowDimBg))
|
|
end
|
|
shown_colors[v] = true
|
|
if btn_count % btns_in_row ~= 0 then
|
|
imgui.SameLine(0.0,4.0)
|
|
end
|
|
btn_count = btn_count + 1
|
|
end
|
|
end
|
|
|
|
if module.tvehicle.color.show_all[0] then
|
|
for v=0,(#module.tvehicle.color.col_data_table-1),1 do
|
|
func(v)
|
|
end
|
|
else
|
|
if module.tvehicle.color.car_data_table[name] ~= nil then
|
|
for k,v in ipairs(module.tvehicle.color.car_data_table[name]) do
|
|
func(v)
|
|
end
|
|
end
|
|
end
|
|
imgui.EndChild()
|
|
end
|
|
end
|
|
|
|
end)
|
|
|
|
imgui.Combo("Component",module.tvehicle.components.selected,module.tvehicle.components.list,#module.tvehicle.components.names)
|
|
|
|
if imgui.ColorEdit3("Neons",module.tvehicle.neon.rgb) then
|
|
InstallNeon(car,{module.tvehicle.neon.rgb[0]*255,module.tvehicle.neon.rgb[1]*255,module.tvehicle.neon.rgb[2]*255})
|
|
end
|
|
|
|
if module.tvehicle.paintjobs.paintjobs_count > 0 then
|
|
|
|
if fcommon.HorizontalSelector("Paintjob",module.tvehicle.paintjobs.current_paintjob,
|
|
module.tvehicle.paintjobs.names) then
|
|
if module.tvehicle.paintjobs.current_paintjob[0] >= -1 and module.tvehicle.paintjobs.current_paintjob[0] <= module.tvehicle.paintjobs.paintjobs_count then
|
|
giveVehiclePaintjob(car,module.tvehicle.paintjobs.current_paintjob[0])
|
|
|
|
if module.tvehicle.paintjobs.enable_saving[0] then
|
|
fconfig.Set(module.tvehicle.paintjobs.save_data,string.format("%d.paintjob",model),module.tvehicle.paintjobs.current_paintjob[0])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
fcommon.DrawEntries(fconst.IDENTIFIER.PAINTJOB,fconst.DRAW_TYPE.IMAGE,ApplyTexture,nil,module.GetTextureName,module.tvehicle.paintjobs.images,fconst.VEHICLE.IMAGE_HEIGHT,fconst.VEHICLE.IMAGE_WIDTH)
|
|
else
|
|
imgui.TextWrapped("Player needs to be inside a vehicle for options to show up here.")
|
|
end
|
|
end
|
|
if fcommon.BeginTabItem('Tune') then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
local model = getCarModel(car)
|
|
|
|
if imgui.Button("Reset vehicle components",imgui.ImVec2(fcommon.GetSize(1))) then
|
|
for x=1,fconst.COMPONENT.TOTAL_SLOTS,1 do
|
|
local comp_model = getCurrentCarMod(car,x)
|
|
|
|
if comp_model ~= -1 then
|
|
module.RemoveComponentFromVehicle(comp_model,car,true)
|
|
end
|
|
end
|
|
printHelpString("Vehicle components reset")
|
|
end
|
|
|
|
if fcommon.CheckBoxVar("Enable saving",module.tvehicle.components.enable_saving,"Save and load vehicle tune data.\nApplies for all vehicles of this model.") then
|
|
if module.tvehicle.components.enable_saving[0] then
|
|
for tmodel,table in pairs(module.tvehicle.components.save_data) do
|
|
if tmodel == tostring(model) then
|
|
for _,component in ipairs(table) do
|
|
module.AddComponentToVehicle(component,car,true)
|
|
end
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
imgui.Dummy(imgui.ImVec2(0,10))
|
|
fcommon.DrawEntries(fconst.IDENTIFIER.COMPONENT,fconst.DRAW_TYPE.IMAGE,module.AddComponentToVehicle,
|
|
function(component)
|
|
if imgui.MenuItemBool("Remove component") then
|
|
module.RemoveComponentFromVehicle(component)
|
|
end
|
|
end,function(a) return a end,module.tvehicle.components.images,fconst.COMPONENT.IMAGE_HEIGHT,fconst.COMPONENT.IMAGE_WIDTH)
|
|
|
|
else
|
|
imgui.TextWrapped("Player needs to be inside a vehicle for options to show up here.")
|
|
end
|
|
end
|
|
if fcommon.BeginTabItem('Handling') then
|
|
if isCharInAnyCar(PLAYER_PED) then
|
|
local car = getCarCharIsUsing(PLAYER_PED)
|
|
local model = getCarModel(car)
|
|
|
|
-------------------------------------------------------
|
|
local phandling = readMemory((casts.CModelInfo.ms_modelInfoPtrs[model] + 0x4A),2,false) --m_nHandlingId
|
|
phandling = phandling * 0xE0
|
|
phandling = phandling + 0xC2B9DC
|
|
|
|
if module.tvehicle.max_velocity_temp[0] == -1 then
|
|
local velocity = memory.getfloat(phandling + 0x84)
|
|
velocity = velocity*206 + (velocity-0.918668)*1501
|
|
module.tvehicle.max_velocity_temp[0] = velocity
|
|
end
|
|
|
|
if imgui.Button("Reset handling",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
local cHandlingDataMgr = readMemory(0x05BFA96,4,false)
|
|
callMethod(0x5BD830,cHandlingDataMgr,0,0)
|
|
printHelpString("Handling reset")
|
|
end
|
|
imgui.SameLine()
|
|
if imgui.Button("Save to file",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
local name = module.tvehicle.handling_name[model]
|
|
local fMass = memory.getfloat(phandling + 0x4)
|
|
local fTurnMass = memory.getfloat(phandling + 0xC)
|
|
local fDragMult = memory.getfloat(phandling + 0x10)
|
|
local CentreOfMassX = memory.getfloat(phandling + 0x14)
|
|
local CentreOfMassY = memory.getfloat(phandling + 0x18)
|
|
local CentreOfMassZ = memory.getfloat(phandling + 0x1C)
|
|
local nPercentSubmerged = memory.read(phandling + 0x20,4)
|
|
local fTractionMultiplier = memory.getfloat(phandling + 0x28)
|
|
local fTractionLoss = memory.getfloat(phandling + 0xA4)
|
|
local TractionBias = memory.getfloat(phandling + 0xA8)
|
|
local nNumberOfGears= memory.read(phandling + 0x76,1)
|
|
local fMaxVelocity = module.tvehicle.max_velocity_temp[0] --memory.getfloat(phandling + 0x84)
|
|
--fMaxVelocity = fMaxVelocity*206 + (fMaxVelocity-0.918668)*1501
|
|
local fEngineAcceleration = memory.getfloat(phandling + 0x7C)*12500
|
|
local fEngineInertia = memory.getfloat(phandling + 0x80)
|
|
local nDriveType = memory.tostring(phandling + 0x74,1)
|
|
local nEngineType = memory.tostring(phandling + 0x75,1)
|
|
local BrakeDeceleration = memory.getfloat(phandling + 0x94)*2500
|
|
local BrakeBias = memory.getfloat(phandling + 0x98)
|
|
local ABS = memory.read(phandling + 0x9C,1)
|
|
local SteeringLock = memory.getfloat(phandling + 0xA0)
|
|
local SuspensionForceLevel = memory.getfloat(phandling + 0xAC)
|
|
local SuspensionDampingLevel = memory.getfloat(phandling + 0xB0)
|
|
local SuspensionHighSpdComDamp = memory.getfloat(phandling + 0xB4)
|
|
local Suspension_upper_limit = memory.getfloat(phandling + 0xB8)
|
|
local Suspension_lower_limit = memory.getfloat(phandling + 0xBC)
|
|
local Suspension_bias = memory.getfloat(phandling + 0xC0)
|
|
local Suspension_anti_dive_multiplier = memory.getfloat(phandling + 0xC4)
|
|
local fSeatOffsetDistance = memory.getfloat(phandling + 0xD4)
|
|
local fCollisionDamageMultiplier = memory.getfloat(phandling + 0xC8)*0.338
|
|
local nMonetaryValue = memory.read(phandling + 0xD8,4)
|
|
local modelFlags = string.format('%x',memory.read(phandling + 0xCC,4))
|
|
local handlingFlags = string.format('%x',memory.read(phandling + 0xD0,4))
|
|
local front_lights = memory.read(phandling + 0xDC,1)
|
|
local rear_lights = memory.read(phandling + 0xDD,1)
|
|
local vehicle_anim_group = memory.read(phandling + 0xDE,1)
|
|
|
|
|
|
local file = io.open(getGameDirectory() .. "/handling.txt","a+")
|
|
local data = string.format("\n%s\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%d\t%d\t%.5g\t%.5g\t%s\t%s\t%.5g\t%.5g\t%d\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%d\t%s\t%s\t%d\t%d\t%d",
|
|
name,fMass,fTurnMass,fDragMult,CentreOfMassX,CentreOfMassY,CentreOfMassZ,nPercentSubmerged,fTractionMultiplier,fTractionLoss,TractionBias,nNumberOfGears,
|
|
fMaxVelocity,fEngineAcceleration,fEngineInertia,tostring(nDriveType),nEngineType,BrakeDeceleration,BrakeBias,ABS,SteeringLock,SuspensionForceLevel,SuspensionDampingLevel,
|
|
SuspensionHighSpdComDamp,Suspension_upper_limit,Suspension_lower_limit,Suspension_bias,Suspension_anti_dive_multiplier,fSeatOffsetDistance,
|
|
fCollisionDamageMultiplier,nMonetaryValue,tostring(modelFlags),tostring(handlingFlags),front_lights,rear_lights,vehicle_anim_group)
|
|
file:write(data)
|
|
file:close()
|
|
printHelpString("Data saved")
|
|
end
|
|
imgui.SameLine()
|
|
if imgui.Button("Read more",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
os.execute('explorer "https://projectcerbera.com/gta/sa/tutorials/handling"')
|
|
end
|
|
|
|
imgui.Spacing()
|
|
if imgui.BeginChild("Handling") then
|
|
fcommon.RadioButtonAddressEx("ABS",{"On","Off"},{1.0,0.0},phandling + 0x9C,false)
|
|
fcommon.UpdateAddress({name = 'Anti dive multiplier',address = phandling + 0xC4 ,size = 4,min = 0,max = 1,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Brake bias',address = phandling + 0x98 ,size = 4,min = 0,max = 1,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Brake deceleration',address = phandling + 0x94 ,size = 4,min = 0.1,max = 20,is_float = true,mul = 2500,cvalue = 0.1, save = false})
|
|
fcommon.UpdateAddress({name = 'Centre of mass X',address = phandling + 0x14 ,size = 1,min = -10.0,max = 10.0,is_float = true,cvalue = 0.05, save = false})
|
|
fcommon.UpdateAddress({name = 'Centre of mass Y',address = phandling + 0x18 ,size = 1,min = -10.0,max = 10.0,is_float = true,cvalue = 0.05, save = false})
|
|
fcommon.UpdateAddress({name = 'Centre of mass Z',address = phandling + 0x1C ,size = 1,min = -10.0,max = 10.0,is_float = true,cvalue = 0.05, save = false})
|
|
fcommon.UpdateAddress({name = 'Collision damage multiplier',address = phandling + 0xC8,size = 4,min = 0,max = 1,is_float = true,cvalue = 0.01,mul = 0.3381, save = false})
|
|
fcommon.UpdateAddress({name = 'Damping level',address = phandling + 0xB0 ,size = 4,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Drag mult',address = phandling + 0x10 ,size = 4,min = 0,max = 30.0,is_float = true, save = false})
|
|
fcommon.RadioButtonAddressEx("Drive type",{"Front wheel drive","Rear wheel drive","Four wheel drive"},{70,82,52},phandling + 0x74,false)
|
|
fcommon.UpdateAddress({name = 'Engine acceleration',address = phandling + 0x7C ,size = 4,min = 0,max = 49,is_float = true,mul = 12500, save = false})
|
|
fcommon.UpdateAddress({name = 'Engine inertia',address = phandling + 0x80 ,size = 4,min = 0,max = 400,is_float = true, save = false})
|
|
fcommon.RadioButtonAddressEx("Engine type",{"Petrol","Diseal","Electric"},{80,68,69},phandling + 0x75,false)
|
|
fcommon.RadioButtonAddressEx("Front lights",{"Long","Small","Big","Tall"},{0,1,2,3},phandling + 0xDC,false)
|
|
fcommon.UpdateAddress({name = 'Force level',address = phandling + 0xAC ,size = 4,is_float = true,cvalue = 0.1, save = false})
|
|
fcommon.UpdateBits("Handling flags",module.tvehicle.handling_flags,phandling + 0xD0,4)
|
|
fcommon.UpdateAddress({name = 'High speed damping',address = phandling + 0xB4 ,size = 4,is_float = true,cvalue = 0.1, save = false})
|
|
fcommon.UpdateAddress({name = 'Lower limit',address = phandling + 0xBC ,size = 4,min = -1,max = 1,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Mass',address = phandling + 0x4 ,size = 4,min = 1,max = 50000,is_float = true, save = false})
|
|
|
|
-- fcommon.UpdateAddress({name = 'Max velocity',address = phandling + 0x84 ,size = 4,min = 0,max = 2,is_float = true,cvalue = 0.01 , save = false})
|
|
fcommon.DropDownMenu("Max velocity",function()
|
|
imgui.Text("Info")
|
|
fcommon.InformationTooltip("Due to an issue, any changes made here won't\nbe applied in game. You can still generate your\
|
|
data file with these values changed here")
|
|
imgui.Columns(2,nil,false)
|
|
imgui.Text("Minimum = 0")
|
|
imgui.NextColumn()
|
|
imgui.Text("Maximum = 500")
|
|
imgui.Columns(1)
|
|
imgui.Spacing()
|
|
|
|
imgui.InputInt("Set##MaxVelocity",module.tvehicle.max_velocity_temp)
|
|
|
|
if imgui.Button("Minimum##MaxVelocity",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
module.tvehicle.max_velocity_temp[0] = 0
|
|
end
|
|
|
|
imgui.SameLine()
|
|
if imgui.Button("Default##MaxVelocity",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
local fMaxVelocity = memory.getfloat(phandling + 0x84)
|
|
fMaxVelocity = fMaxVelocity*206 + (fMaxVelocity-0.918668)*1501
|
|
module.tvehicle.max_velocity_temp[0] = math.floor(fMaxVelocity)
|
|
end
|
|
|
|
imgui.SameLine()
|
|
if imgui.Button("Maximum##MaxVelocity",imgui.ImVec2(fcommon.GetSize(3))) then
|
|
module.tvehicle.max_velocity_temp[0] = 500
|
|
end
|
|
|
|
if module.tvehicle.max_velocity_temp[0] > 500 then
|
|
module.tvehicle.max_velocity_temp[0] = 500
|
|
end
|
|
|
|
if module.tvehicle.max_velocity_temp[0] < 0 then
|
|
module.tvehicle.max_velocity_temp[0] = 0
|
|
end
|
|
end)
|
|
|
|
fcommon.UpdateBits("Model flags",module.tvehicle.model_flags,phandling + 0xCC,4)
|
|
fcommon.UpdateAddress({name = 'Monetary value',address = phandling + 0xD8 ,size = 4, save = false})
|
|
fcommon.UpdateAddress({name = 'Number of gears',address = phandling + 0x76 ,size = 1,min = 1,max = 10, save = false})
|
|
fcommon.UpdateAddress({name = 'Percent submerged',address = phandling + 0x20 ,size = 1,min = 10,max = 120, save = false})
|
|
fcommon.RadioButtonAddressEx("Rear lights",{"Long","Small","Big","Tall"},{0,1,2,3},phandling + 0xDD,false)
|
|
fcommon.UpdateAddress({name = 'Seat offset distance',address = phandling + 0xD4 ,size = 4,min = 0,max = 1,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Steering lock',address = phandling + 0xA0 ,size = 4,min = 10,max = 50,is_float = true, save = false})
|
|
fcommon.UpdateAddress({name = 'Suspension bias',address = phandling + 0xC0 ,size = 4,min = 0,max = 1,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Traction bias',address = phandling + 0xA8 ,size = 4,min = 0,max = 1,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Traction loss',address = phandling + 0xA4 ,size = 4,min = 0,max = 1,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Traction multiplier',address = phandling + 0x28 ,size = 4,min = 0.5,max = 2,is_float = true,cvalue = 0.05, save = false})
|
|
fcommon.UpdateAddress({name = 'Turn mass',address = phandling + 0xC ,size = 4,min = 20,is_float = true, save = false})
|
|
fcommon.UpdateAddress({name = 'Upper limit',address = phandling + 0xB8 ,size = 4,min = -1,max = 1,is_float = true,cvalue = 0.01, save = false})
|
|
fcommon.UpdateAddress({name = 'Vehicle anim group',address = phandling + 0xDE ,size = 1, save = false})
|
|
imgui.EndChild()
|
|
end
|
|
else
|
|
imgui.TextWrapped("Player needs to be inside a vehicle for options to show up here.")
|
|
end
|
|
end
|
|
fcommon.EndTabBar()
|
|
end
|
|
end
|
|
|
|
return module
|