177 lines
6.6 KiB
Lua
177 lines
6.6 KiB
Lua
if not TowBarMod then TowBarMod = {} end
|
|
if not TowBarMod.Utils then TowBarMod.Utils = {} end
|
|
|
|
TowBarMod.Utils.tempVector1 = Vector3f.new()
|
|
TowBarMod.Utils.tempVector2 = Vector3f.new()
|
|
|
|
---------------------------------------------------------------------------
|
|
--- Util functions
|
|
---------------------------------------------------------------------------
|
|
|
|
function TowBarMod.Utils.isTrailer(vehicle)
|
|
return string.match(string.lower(vehicle:getScript():getName()), "trailer")
|
|
end
|
|
|
|
--- Return vehicles from sector that player can tow by tow bar.
|
|
function TowBarMod.Utils.getAviableVehicles(mainVehicle, hasTowBar)
|
|
local vehicles = {}
|
|
if not hasTowBar then return vehicles end
|
|
|
|
local square = mainVehicle:getSquare()
|
|
if square == nil then return vehicles end
|
|
|
|
-- Match vanilla towing search radius.
|
|
for y=square:getY() - 6, square:getY() + 6 do
|
|
for x=square:getX() - 6, square:getX() + 6 do
|
|
local square2 = getCell():getGridSquare(x, y, square:getZ())
|
|
if square2 then
|
|
for i=1, square2:getMovingObjects():size() do
|
|
local obj = square2:getMovingObjects():get(i-1)
|
|
if obj ~= nil
|
|
and instanceof(obj, "BaseVehicle")
|
|
and obj ~= mainVehicle
|
|
and #(TowBarMod.Utils.getHookTypeVariants(mainVehicle, obj, hasTowBar)) ~= 0 then
|
|
table.insert(vehicles, obj)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return vehicles
|
|
end
|
|
|
|
--- Return a table with towbar-only hook options for vehicles.
|
|
function TowBarMod.Utils.getHookTypeVariants(vehicleA, vehicleB, hasTowBar)
|
|
local hookTypeVariants = {}
|
|
if not hasTowBar then return hookTypeVariants end
|
|
|
|
if vehicleA:getVehicleTowing() or vehicleA:getVehicleTowedBy()
|
|
or vehicleB:getVehicleTowing() or vehicleB:getVehicleTowedBy() then
|
|
return hookTypeVariants
|
|
end
|
|
|
|
-- Keep tow bars for vehicle-to-vehicle towing only.
|
|
if TowBarMod.Utils.isTrailer(vehicleA) or TowBarMod.Utils.isTrailer(vehicleB) then
|
|
return hookTypeVariants
|
|
end
|
|
|
|
if vehicleA:canAttachTrailer(vehicleB, "trailerfront", "trailer") then
|
|
local hookType = {}
|
|
hookType.name = getText("UI_Text_Towing_attach") .. "\n" .. ISVehicleMenu.getVehicleDisplayName(vehicleB) .. "\n" .. getText("UI_Text_Towing_byTowBar")
|
|
hookType.func = TowBarMod.Hook.attachByTowBarAction
|
|
hookType.towingVehicle = vehicleB
|
|
hookType.towedVehicle = vehicleA
|
|
hookType.textureName = "tow_bar_icon"
|
|
table.insert(hookTypeVariants, hookType)
|
|
elseif vehicleA:canAttachTrailer(vehicleB, "trailer", "trailerfront") then
|
|
local hookType = {}
|
|
hookType.name = getText("UI_Text_Towing_attach") .. "\n" .. ISVehicleMenu.getVehicleDisplayName(vehicleB) .. "\n" .. getText("UI_Text_Towing_byTowBar")
|
|
hookType.func = TowBarMod.Hook.attachByTowBarAction
|
|
hookType.towingVehicle = vehicleA
|
|
hookType.towedVehicle = vehicleB
|
|
hookType.textureName = "tow_bar_icon"
|
|
table.insert(hookTypeVariants, hookType)
|
|
end
|
|
|
|
return hookTypeVariants
|
|
end
|
|
|
|
function TowBarMod.Utils.updateAttachmentsForRigidTow(towingVehicle, towedVehicle, attachmentA, attachmentB)
|
|
local towingAttachment = towingVehicle:getScript():getAttachmentById(attachmentA)
|
|
local towedAttachment = towedVehicle:getScript():getAttachmentById(attachmentB)
|
|
if towingAttachment == nil or towedAttachment == nil then return end
|
|
|
|
towingAttachment:setUpdateConstraint(false)
|
|
towingAttachment:setZOffset(0)
|
|
|
|
towedAttachment:setUpdateConstraint(false)
|
|
towedAttachment:setZOffset(0)
|
|
|
|
local towedModData = towedVehicle:getModData()
|
|
local alreadyShifted = towedModData["isChangedTowedAttachment"] and towedModData["towBarChangedAttachmentId"] == attachmentB
|
|
if not alreadyShifted then
|
|
local offset = towedAttachment:getOffset()
|
|
local zShift = offset:z() > 0 and 1 or -1
|
|
towedAttachment:getOffset():set(offset:x(), offset:y(), offset:z() + zShift)
|
|
towedModData["isChangedTowedAttachment"] = true
|
|
towedModData["towBarChangedAttachmentId"] = attachmentB
|
|
towedModData["towBarChangedOffsetZShift"] = zShift
|
|
end
|
|
towedVehicle:transmitModData()
|
|
end
|
|
|
|
function TowBarMod.Utils.updateAttachmentsOnDefaultValues(towingVehicle, towedVehicle)
|
|
local towingAttachmentId = towingVehicle:getTowAttachmentSelf()
|
|
local towingAttachment = towingVehicle:getScript():getAttachmentById(towingAttachmentId)
|
|
if towingAttachment ~= nil then
|
|
towingAttachment:setUpdateConstraint(true)
|
|
local zOffset = (towingAttachmentId == "trailer") and -1 or 1
|
|
towingAttachment:setZOffset(zOffset)
|
|
end
|
|
|
|
local towedModData = towedVehicle:getModData()
|
|
local changedAttachmentId = towedModData["towBarChangedAttachmentId"] or towedVehicle:getTowAttachmentSelf()
|
|
local towedAttachment = towedVehicle:getScript():getAttachmentById(changedAttachmentId)
|
|
if towedAttachment ~= nil then
|
|
towedAttachment:setUpdateConstraint(true)
|
|
local zOffset = (changedAttachmentId == "trailer") and -1 or 1
|
|
towedAttachment:setZOffset(zOffset)
|
|
|
|
if towedModData["isChangedTowedAttachment"] then
|
|
local offset = towedAttachment:getOffset()
|
|
local storedShift = tonumber(towedModData["towBarChangedOffsetZShift"])
|
|
if storedShift ~= nil then
|
|
towedAttachment:getOffset():set(offset:x(), offset:y(), offset:z() - storedShift)
|
|
else
|
|
local zShift = offset:z() > 0 and -1 or 1
|
|
towedAttachment:getOffset():set(offset:x(), offset:y(), offset:z() + zShift)
|
|
end
|
|
end
|
|
end
|
|
|
|
towedModData["isChangedTowedAttachment"] = false
|
|
towedModData["towBarChangedAttachmentId"] = nil
|
|
towedModData["towBarChangedOffsetZShift"] = nil
|
|
towedVehicle:transmitModData()
|
|
end
|
|
|
|
-----------------------------------------------------------
|
|
|
|
--- Fix mods that add vehicles without tow attachments
|
|
local function fixTowAttachmentsForOtherVehicleMods()
|
|
local scriptManager = getScriptManager()
|
|
local vehicleScripts = scriptManager:getAllVehicleScripts()
|
|
|
|
for i = 0, vehicleScripts:size()-1 do
|
|
local script = vehicleScripts:get(i)
|
|
local wheelCount = script:getWheelCount()
|
|
|
|
local attachHeigtOffset = -0.5
|
|
if wheelCount > 0 then
|
|
attachHeigtOffset = script:getWheel(0):getOffset():y() + 0.1
|
|
end
|
|
|
|
if not string.match(string.lower(script:getName()), "trailer") then
|
|
local trailerAttachment = script:getAttachmentById("trailer")
|
|
if trailerAttachment == nil then
|
|
local attach = ModelAttachment.new("trailer")
|
|
attach:getOffset():set(0, attachHeigtOffset, -script:getPhysicsChassisShape():z()/2 - 0.1)
|
|
attach:setZOffset(-1)
|
|
script:addAttachment(attach)
|
|
end
|
|
|
|
local trailerFrontAttachment = script:getAttachmentById("trailerfront")
|
|
if trailerFrontAttachment == nil then
|
|
local attach = ModelAttachment.new("trailerfront")
|
|
attach:getOffset():set(0, attachHeigtOffset, script:getPhysicsChassisShape():z()/2 + 0.1)
|
|
attach:setZOffset(1)
|
|
script:addAttachment(attach)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Events.OnGameBoot.Add(fixTowAttachmentsForOtherVehicleMods)
|
|
|