This commit is contained in:
2026-02-13 12:02:46 -05:00
parent 19ad4b5755
commit 6e820b8560
2 changed files with 93 additions and 16 deletions

View File

@@ -9,6 +9,28 @@ local function log(msg)
print("[Landtrain][TowSyncClient] " .. tostring(msg))
end
local function isTrailerScriptName(scriptName)
if not scriptName then return false end
return string.find(string.lower(scriptName), "trailer", 1, true) ~= nil
end
local function shouldForceNotTowingScript(vehicle)
if not vehicle then return false end
local scriptName = vehicle:getScriptName()
return not isTrailerScriptName(scriptName)
end
local function restoreTrailerScriptIfNeeded(vehicle)
if not vehicle then return end
if vehicle:getScriptName() ~= "notTowingA_Trailer" then return end
local md = vehicle:getModData()
local originalScript = md and md.towBarOriginalScriptName or nil
if originalScript and isTrailerScriptName(originalScript) then
vehicle:setScriptName(originalScript)
end
end
local function ensureAttachment(vehicle, attachmentId)
if not vehicle or not attachmentId then return false end
@@ -47,6 +69,7 @@ end
local function reconcilePairState(vehicleA, vehicleB, attachmentA, attachmentB)
if not vehicleA or not vehicleB then return end
restoreTrailerScriptIfNeeded(vehicleA)
if TowBarMod.Utils and TowBarMod.Utils.updateAttachmentsForRigidTow then
TowBarMod.Utils.updateAttachmentsForRigidTow(vehicleA, vehicleB, attachmentA, attachmentB)

View File

@@ -37,6 +37,28 @@ local function hasAttachment(vehicle, attachmentId)
return script ~= nil and script:getAttachmentById(attachmentId) ~= nil
end
local function isTrailerScriptName(scriptName)
if not scriptName then return false end
return string.find(string.lower(scriptName), "trailer", 1, true) ~= nil
end
local function shouldForceNotTowingScript(vehicle)
if not vehicle then return false end
local scriptName = vehicle:getScriptName()
return not isTrailerScriptName(scriptName)
end
local function restoreTrailerScriptIfNeeded(vehicle)
if not vehicle then return end
if vehicle:getScriptName() ~= "notTowingA_Trailer" then return end
local md = vehicle:getModData()
local originalScript = md and md.towBarOriginalScriptName or nil
if originalScript and isTrailerScriptName(originalScript) then
vehicle:setScriptName(originalScript)
end
end
local function sideFree(vehicle, attachmentId)
if vehicle == nil then return false end
if attachmentId == "trailer" then return vehicle:getVehicleTowing() == nil end
@@ -121,6 +143,27 @@ local function resolvePair(towingVehicle, towedVehicle, preferredA, preferredB)
return "trailer", "trailerfront"
end
local function resolveMenuPair(towingVehicle, towedVehicle, preferredA, preferredB)
local candidates = {
{ preferredA, preferredB },
{ "trailer", "trailerfront" },
{ towingVehicle and towingVehicle:getTowAttachmentSelf() or nil, towedVehicle and towedVehicle:getTowAttachmentSelf() or nil },
{ "trailerfront", "trailer" }
}
for _, pair in ipairs(candidates) do
local a, b = pair[1], pair[2]
if a and b and a ~= b
and hasAttachment(towingVehicle, a)
and hasAttachment(towedVehicle, b)
and canTowByLandtrain(towingVehicle, towedVehicle, a, b, false) then
return a, b
end
end
return nil, nil
end
local function clearChangedOffset(vehicle)
if not vehicle then return end
end
@@ -534,6 +577,9 @@ local function ensurePairAttached(playerObj, towingVehicle, towedVehicle, prefer
log("ensurePairAttached skipped: identical vehicles id=" .. tostring(vehicleId(towingVehicle)))
return false
end
restoreTrailerScriptIfNeeded(towingVehicle)
if wouldCreateTowLoop(towingVehicle, towedVehicle) then
log("ensurePairAttached skipped: loop A=" .. tostring(vehicleId(towingVehicle)) .. " B=" .. tostring(vehicleId(towedVehicle)))
return false
@@ -670,22 +716,30 @@ local function getLandtrainHookTypeVariants(vehicleA, vehicleB, hasTowBar)
local variants = {}
if not hasTowBar or not vehicleA or not vehicleB or vehicleA == vehicleB then return variants end
if canTowByLandtrain(vehicleA, vehicleB, "trailerfront", "trailer", false) then
restoreTrailerScriptIfNeeded(vehicleA)
restoreTrailerScriptIfNeeded(vehicleB)
local function addVariant(towingVehicle, towedVehicle)
local attachmentA, attachmentB = resolveMenuPair(towingVehicle, towedVehicle)
if not attachmentA or not attachmentB then
return false
end
table.insert(variants, {
name = getText("UI_Text_Towing_attach") .. "\n" .. ISVehicleMenu.getVehicleDisplayName(vehicleB) .. "\n" .. getText("UI_Text_Towing_byTowBar"),
name = getText("UI_Text_Towing_attach") .. "\n" .. ISVehicleMenu.getVehicleDisplayName(towedVehicle) .. "\n" .. getText("UI_Text_Towing_byTowBar"),
func = TowBarMod.Hook.attachByTowBarAction,
towingVehicle = vehicleB,
towedVehicle = vehicleA,
textureName = "tow_bar_icon"
})
elseif canTowByLandtrain(vehicleA, vehicleB, "trailer", "trailerfront", false) then
table.insert(variants, {
name = getText("UI_Text_Towing_attach") .. "\n" .. ISVehicleMenu.getVehicleDisplayName(vehicleB) .. "\n" .. getText("UI_Text_Towing_byTowBar"),
func = TowBarMod.Hook.attachByTowBarAction,
towingVehicle = vehicleA,
towedVehicle = vehicleB,
towingVehicle = towingVehicle,
towedVehicle = towedVehicle,
towingPoint = attachmentA,
towedPoint = attachmentB,
textureName = "tow_bar_icon"
})
return true
end
local addedForward = addVariant(vehicleA, vehicleB)
if not addedForward then
addVariant(vehicleB, vehicleA)
end
return variants
@@ -1060,8 +1114,7 @@ local function sortPersistedLinks(links, byRearSql)
end
local function isTowbarPairStateComplete(frontVehicle, rearVehicle)
if not isLinkedPair(frontVehicle, rearVehicle) then return false end
return rearVehicle:getScriptName() == "notTowingA_Trailer"
return isLinkedPair(frontVehicle, rearVehicle)
end
local function restoreViaAttachWrapper(playerObj, frontVehicle, rearVehicle, attachmentA, attachmentB)
@@ -1129,7 +1182,8 @@ local function restorePersistedLink(playerObj, link, bySql, byHeadOrder)
end
if wouldCreateTowLoop(frontVehicle, rearVehicle) then return false end
if not isLinkedPair(frontVehicle, rearVehicle) then
local linkedNow = isLinkedPair(frontVehicle, rearVehicle)
if not linkedNow then
if not canTowByLandtrain(frontVehicle, rearVehicle, link.attachmentA, link.attachmentB, true) then
return false
end
@@ -1138,7 +1192,7 @@ local function restorePersistedLink(playerObj, link, bySql, byHeadOrder)
end
end
return ensurePairAttached(playerObj, frontVehicle, rearVehicle, link.attachmentA, link.attachmentB, true)
return ensurePairAttached(playerObj, frontVehicle, rearVehicle, link.attachmentA, link.attachmentB, not linkedNow)
end
local function runPersistedLoadRebuildPass()