292 lines
10 KiB
Lua
292 lines
10 KiB
Lua
if not Config.Debug then return end
|
|
|
|
Debug('`gizmo` debug command initialized')
|
|
RegisterCommand('gizmo', function(source, args, raw)
|
|
decorate:open()
|
|
end)
|
|
|
|
---@param shellCoords vector4
|
|
---@param playerPos vector3
|
|
---@return vector3
|
|
local function GetOffsetFromShell(shellCoords, playerPos)
|
|
local dx = playerPos.x - shellCoords.x
|
|
local dy = playerPos.y - shellCoords.y
|
|
local dz = playerPos.z - shellCoords.z
|
|
local heading = shellCoords.w or 0.0
|
|
local hRad = math.rad(heading + 90)
|
|
|
|
local offsetX = dx * math.cos(hRad) + dy * math.sin(hRad)
|
|
local offsetY = -dx * math.sin(hRad) + dy * math.cos(hRad)
|
|
local offsetZ = dz
|
|
|
|
return vec3(offsetX, offsetY, offsetZ)
|
|
end
|
|
|
|
---@param shellHeading number
|
|
---@param playerHeading number
|
|
---@return number
|
|
local function GetRelativeHeading(shellHeading, playerHeading)
|
|
local relativeHeading = playerHeading - shellHeading
|
|
|
|
while relativeHeading > 180.0 do
|
|
relativeHeading = relativeHeading - 360.0
|
|
end
|
|
while relativeHeading < -180.0 do
|
|
relativeHeading = relativeHeading + 360.0
|
|
end
|
|
|
|
return relativeHeading
|
|
end
|
|
|
|
|
|
RegisterCommand('take_offset', function(source, args, raw)
|
|
if not CurrentHouse then
|
|
lib.notify({
|
|
title = 'Error',
|
|
description = 'You must be in a house to use this command',
|
|
type = 'error'
|
|
})
|
|
return
|
|
end
|
|
|
|
local houseData = Config.Houses[CurrentHouse]
|
|
if not houseData then
|
|
Notification('House data not found')
|
|
return
|
|
end
|
|
|
|
-- Show type selection menu
|
|
local input = lib.inputDialog('Take Offset', {
|
|
{
|
|
type = 'select',
|
|
label = 'Type',
|
|
description = 'Select offset type',
|
|
options = {
|
|
{ value = 'shell', label = 'Shell' },
|
|
{ value = 'ipl', label = 'IPL' }
|
|
},
|
|
required = true
|
|
},
|
|
{
|
|
type = 'input',
|
|
label = 'Object Type',
|
|
description = 'Type of object (e.g., shower, sink, cooking)',
|
|
default = 'shower',
|
|
required = true
|
|
}
|
|
})
|
|
|
|
if not input or not input[1] or not input[2] then
|
|
return
|
|
end
|
|
|
|
local offsetType = input[1]
|
|
local objectType = input[2]
|
|
|
|
local playerPos = GetEntityCoords(cache.ped)
|
|
local playerHeading = GetEntityHeading(cache.ped)
|
|
|
|
if offsetType == 'shell' then
|
|
local tier = houseData.tier
|
|
local shellModel = Config.Shells[tier].model
|
|
if not tier then
|
|
Notification('This house does not have a tier (not a shell house)')
|
|
return
|
|
end
|
|
|
|
local shellData = Config.Shells[tier]
|
|
if not shellData then
|
|
Notification('Shell data not found for tier ' .. tier)
|
|
return
|
|
end
|
|
|
|
local shellCoords = houseData.coords and houseData.coords.shellCoords or nil
|
|
if not shellCoords then
|
|
Notification('Shell coordinates not found for this house')
|
|
return
|
|
end
|
|
|
|
local shellPos = vec4(shellCoords.x, shellCoords.y, shellCoords.z, shellCoords.h or 0.0)
|
|
local ptfxOffset = GetOffsetFromShell(shellPos, playerPos)
|
|
local calculatedHeading = GetRelativeHeading(shellPos.w, playerHeading)
|
|
local animationOffset = vec4(ptfxOffset.x, ptfxOffset.y, ptfxOffset.z, calculatedHeading)
|
|
|
|
if not shellData[objectType] then
|
|
shellData[objectType] = {}
|
|
end
|
|
shellData[objectType].ptfxOffset = ptfxOffset
|
|
shellData[objectType].animationOffset = animationOffset
|
|
|
|
Debug('^2' .. objectType .. ' offset calculated and updated for shell tier ' .. shellModel .. '^0')
|
|
Debug('^3ptfxOffset: vec3(' .. string.format('%.3f', ptfxOffset.x) .. ', ' .. string.format('%.3f', ptfxOffset.y) .. ', ' .. string.format('%.3f', ptfxOffset.z) .. ')^0')
|
|
Debug('^3animationOffset: vec4(' .. string.format('%.3f', animationOffset.x) .. ', ' .. string.format('%.3f', animationOffset.y) .. ', ' .. string.format('%.3f', animationOffset.z) .. ', ' .. string.format('%.3f', animationOffset.w) .. ')^0')
|
|
elseif offsetType == 'ipl' then
|
|
if not houseData.ipl or not houseData.ipl.houseName then
|
|
Notification('This house does not have IPL data')
|
|
return
|
|
end
|
|
|
|
local iplIndex = houseData.ipl.houseName
|
|
local iplData = Config.IplData[iplIndex]
|
|
if not iplData then
|
|
Notification('IPL data not found for index ' .. iplIndex)
|
|
return
|
|
end
|
|
|
|
local iplCoords = iplData.iplCoords
|
|
if not iplCoords then
|
|
Notification('IPL coordinates not found')
|
|
return
|
|
end
|
|
|
|
local iplHeading = iplCoords.h or 0.0
|
|
local iplPos = vec4(iplCoords.x, iplCoords.y, iplCoords.z, iplHeading)
|
|
local ptfxOffset = GetOffsetFromShell(iplPos, playerPos)
|
|
local calculatedHeading = GetRelativeHeading(iplHeading, playerHeading)
|
|
local animationOffset = vec4(ptfxOffset.x, ptfxOffset.y, ptfxOffset.z, calculatedHeading)
|
|
|
|
if not iplData[objectType] then
|
|
iplData[objectType] = {}
|
|
end
|
|
iplData[objectType].ptfxOffset = ptfxOffset
|
|
iplData[objectType].animationOffset = animationOffset
|
|
|
|
print('^2' .. objectType .. ' offset calculated and updated for IPL index ' .. iplIndex .. '^0')
|
|
print('^3ptfxOffset: vec3(' .. string.format('%.3f', ptfxOffset.x) .. ', ' .. string.format('%.3f', ptfxOffset.y) .. ', ' .. string.format('%.3f', ptfxOffset.z) .. ')^0')
|
|
print('^3animationOffset: vec4(' .. string.format('%.3f', animationOffset.x) .. ', ' .. string.format('%.3f', animationOffset.y) .. ', ' .. string.format('%.3f', animationOffset.z) .. ', ' .. string.format('%.3f', animationOffset.w) .. ')^0')
|
|
end
|
|
end)
|
|
|
|
RegisterCommand('update_offset', function(source, args, raw)
|
|
if not CurrentHouse then
|
|
Notification('You must be in a house to use this command')
|
|
return
|
|
end
|
|
|
|
local houseData = Config.Houses[CurrentHouse]
|
|
if not houseData then
|
|
Notification('House data not found')
|
|
return
|
|
end
|
|
|
|
local input = lib.inputDialog('Update Offset', {
|
|
{
|
|
type = 'select',
|
|
label = 'Type',
|
|
description = 'Select offset type',
|
|
options = {
|
|
{ value = 'shell', label = 'Shell' },
|
|
{ value = 'ipl', label = 'IPL' }
|
|
},
|
|
required = true
|
|
},
|
|
{
|
|
type = 'input',
|
|
label = 'Object Type',
|
|
description = 'Type of object (e.g., shower, sink, cooking)',
|
|
default = 'shower',
|
|
required = true
|
|
},
|
|
{
|
|
type = 'select',
|
|
label = 'Offset Type',
|
|
description = 'Select which offset to update',
|
|
options = {
|
|
{ value = 'ptfxOffset', label = 'Particle FX Offset' },
|
|
{ value = 'animationOffset', label = 'Animation Offset' }
|
|
},
|
|
required = true
|
|
},
|
|
{
|
|
type = 'input',
|
|
label = 'X Offset',
|
|
description = 'X coordinate offset',
|
|
default = '0.0',
|
|
required = true
|
|
},
|
|
{
|
|
type = 'input',
|
|
label = 'Y Offset',
|
|
description = 'Y coordinate offset',
|
|
default = '0.0',
|
|
required = true
|
|
},
|
|
{
|
|
type = 'input',
|
|
label = 'Z Offset',
|
|
description = 'Z coordinate offset',
|
|
default = '0.0',
|
|
required = true
|
|
},
|
|
{
|
|
type = 'input',
|
|
label = 'W/Heading Offset (Optional)',
|
|
description = 'W/Heading offset (only for animationOffset)',
|
|
default = '0.0',
|
|
required = false
|
|
}
|
|
})
|
|
|
|
if not input or not input[1] or not input[2] or not input[3] then
|
|
return
|
|
end
|
|
|
|
local offsetType = input[1]
|
|
local objectType = input[2]
|
|
local offsetToUpdate = input[3]
|
|
local x = tonumber(input[4]) or 0.0
|
|
local y = tonumber(input[5]) or 0.0
|
|
local z = tonumber(input[6]) or 0.0
|
|
local w = tonumber(input[7]) or 0.0
|
|
|
|
if offsetType == 'shell' then
|
|
local tier = houseData.tier
|
|
if not tier then
|
|
Notification('This house does not have a tier (not a shell house)')
|
|
return
|
|
end
|
|
|
|
local shellData = Config.Shells[tier]
|
|
if not shellData then
|
|
Notification('Shell data not found for tier ' .. tier)
|
|
return
|
|
end
|
|
|
|
if not shellData[objectType] then
|
|
shellData[objectType] = {}
|
|
end
|
|
|
|
if offsetToUpdate == 'ptfxOffset' then
|
|
shellData[objectType].ptfxOffset = vec3(x, y, z)
|
|
Debug('^2ptfxOffset updated: vec3(' .. string.format('%.3f', x) .. ', ' .. string.format('%.3f', y) .. ', ' .. string.format('%.3f', z) .. ')^0')
|
|
elseif offsetToUpdate == 'animationOffset' then
|
|
shellData[objectType].animationOffset = vec4(x, y, z, w)
|
|
Debug('^2animationOffset updated: vec4(' .. string.format('%.3f', x) .. ', ' .. string.format('%.3f', y) .. ', ' .. string.format('%.3f', z) .. ', ' .. string.format('%.3f', w) .. ')^0')
|
|
end
|
|
elseif offsetType == 'ipl' then
|
|
if not houseData.ipl or not houseData.ipl.houseName then
|
|
Notification('This house does not have IPL data')
|
|
return
|
|
end
|
|
|
|
local iplIndex = houseData.ipl.houseName
|
|
local iplData = Config.IplData[iplIndex]
|
|
if not iplData then
|
|
Notification('IPL data not found for index ' .. iplIndex)
|
|
return
|
|
end
|
|
|
|
if not iplData[objectType] then
|
|
iplData[objectType] = {}
|
|
end
|
|
|
|
if offsetToUpdate == 'ptfxOffset' then
|
|
iplData[objectType].ptfxOffset = vec3(x, y, z)
|
|
Debug('^2ptfxOffset updated: vec3(' .. string.format('%.3f', x) .. ', ' .. string.format('%.3f', y) .. ', ' .. string.format('%.3f', z) .. ')^0')
|
|
elseif offsetToUpdate == 'animationOffset' then
|
|
iplData[objectType].animationOffset = vec4(x, y, z, w)
|
|
Debug('^2animationOffset updated: vec4(' .. string.format('%.3f', x) .. ', ' .. string.format('%.3f', y) .. ', ' .. string.format('%.3f', z) .. ', ' .. string.format('%.3f', w) .. ')^0')
|
|
end
|
|
end
|
|
end)
|