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)) print("[Landtrain][TowSyncClient] " .. tostring(msg))
end 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) local function ensureAttachment(vehicle, attachmentId)
if not vehicle or not attachmentId then return false end if not vehicle or not attachmentId then return false end
@@ -47,6 +69,7 @@ end
local function reconcilePairState(vehicleA, vehicleB, attachmentA, attachmentB) local function reconcilePairState(vehicleA, vehicleB, attachmentA, attachmentB)
if not vehicleA or not vehicleB then return end if not vehicleA or not vehicleB then return end
restoreTrailerScriptIfNeeded(vehicleA)
if TowBarMod.Utils and TowBarMod.Utils.updateAttachmentsForRigidTow then if TowBarMod.Utils and TowBarMod.Utils.updateAttachmentsForRigidTow then
TowBarMod.Utils.updateAttachmentsForRigidTow(vehicleA, vehicleB, attachmentA, attachmentB) 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 return script ~= nil and script:getAttachmentById(attachmentId) ~= nil
end 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) local function sideFree(vehicle, attachmentId)
if vehicle == nil then return false end if vehicle == nil then return false end
if attachmentId == "trailer" then return vehicle:getVehicleTowing() == nil end if attachmentId == "trailer" then return vehicle:getVehicleTowing() == nil end
@@ -121,6 +143,27 @@ local function resolvePair(towingVehicle, towedVehicle, preferredA, preferredB)
return "trailer", "trailerfront" return "trailer", "trailerfront"
end 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) local function clearChangedOffset(vehicle)
if not vehicle then return end if not vehicle then return end
end end
@@ -534,6 +577,9 @@ local function ensurePairAttached(playerObj, towingVehicle, towedVehicle, prefer
log("ensurePairAttached skipped: identical vehicles id=" .. tostring(vehicleId(towingVehicle))) log("ensurePairAttached skipped: identical vehicles id=" .. tostring(vehicleId(towingVehicle)))
return false return false
end end
restoreTrailerScriptIfNeeded(towingVehicle)
if wouldCreateTowLoop(towingVehicle, towedVehicle) then if wouldCreateTowLoop(towingVehicle, towedVehicle) then
log("ensurePairAttached skipped: loop A=" .. tostring(vehicleId(towingVehicle)) .. " B=" .. tostring(vehicleId(towedVehicle))) log("ensurePairAttached skipped: loop A=" .. tostring(vehicleId(towingVehicle)) .. " B=" .. tostring(vehicleId(towedVehicle)))
return false return false
@@ -670,22 +716,30 @@ local function getLandtrainHookTypeVariants(vehicleA, vehicleB, hasTowBar)
local variants = {} local variants = {}
if not hasTowBar or not vehicleA or not vehicleB or vehicleA == vehicleB then return variants end 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, { 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, func = TowBarMod.Hook.attachByTowBarAction,
towingVehicle = vehicleB, towingVehicle = towingVehicle,
towedVehicle = vehicleA, towedVehicle = towedVehicle,
textureName = "tow_bar_icon" towingPoint = attachmentA,
}) towedPoint = attachmentB,
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,
textureName = "tow_bar_icon" textureName = "tow_bar_icon"
}) })
return true
end
local addedForward = addVariant(vehicleA, vehicleB)
if not addedForward then
addVariant(vehicleB, vehicleA)
end end
return variants return variants
@@ -1060,8 +1114,7 @@ local function sortPersistedLinks(links, byRearSql)
end end
local function isTowbarPairStateComplete(frontVehicle, rearVehicle) local function isTowbarPairStateComplete(frontVehicle, rearVehicle)
if not isLinkedPair(frontVehicle, rearVehicle) then return false end return isLinkedPair(frontVehicle, rearVehicle)
return rearVehicle:getScriptName() == "notTowingA_Trailer"
end end
local function restoreViaAttachWrapper(playerObj, frontVehicle, rearVehicle, attachmentA, attachmentB) local function restoreViaAttachWrapper(playerObj, frontVehicle, rearVehicle, attachmentA, attachmentB)
@@ -1129,7 +1182,8 @@ local function restorePersistedLink(playerObj, link, bySql, byHeadOrder)
end end
if wouldCreateTowLoop(frontVehicle, rearVehicle) then return false 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 if not canTowByLandtrain(frontVehicle, rearVehicle, link.attachmentA, link.attachmentB, true) then
return false return false
end end
@@ -1138,7 +1192,7 @@ local function restorePersistedLink(playerObj, link, bySql, byHeadOrder)
end end
end end
return ensurePairAttached(playerObj, frontVehicle, rearVehicle, link.attachmentA, link.attachmentB, true) return ensurePairAttached(playerObj, frontVehicle, rearVehicle, link.attachmentA, link.attachmentB, not linkedNow)
end end
local function runPersistedLoadRebuildPass() local function runPersistedLoadRebuildPass()