42.20 and Towtrucks

This commit is contained in:
2026-08-13 18:59:54 -04:00
parent a6ba4877d0
commit e403323017
33 changed files with 2333 additions and 142 deletions
+89
View File
@@ -0,0 +1,89 @@
local failures = 0
local function expect(condition, message)
if not condition then
failures = failures + 1
io.stderr:write("FAIL: " .. message .. "\n")
end
end
Events = { OnGameBoot = { Add = function() end } }
Vector3f = { new = function() return {} end }
local function point(x, y, z)
return {
x = function() return x end,
y = function() return y end,
z = function() return z or 0 end
}
end
local function vehicle(id, fullName, attachments)
local linkedTowing
local linkedTowedBy
local script = {
getFullName = function() return fullName end,
getName = function() return string.gsub(fullName, "^Base%.", "") end
}
return {
getId = function() return id end,
getScript = function() return script end,
attachmentExist = function(_, name) return attachments[name] ~= nil end,
getAttachmentWorldPos = function(_, name) return attachments[name] end,
getVehicleTowing = function() return linkedTowing end,
getVehicleTowedBy = function() return linkedTowedBy end,
setLinks = function(_, towing, towedBy) linkedTowing, linkedTowedBy = towing, towedBy end
}
end
dofile("42.20/media/lua/shared/TowBar/WreckerUtils.lua")
local supported = {
"Base.76chevyC30CCwrecker",
"Base.76chevyC30SCwrecker",
"Base.76chevyK30CCwrecker",
"Base.76chevyK30SCwrecker",
"Base.93chevySilveradoK3500wrecker",
"Base.93chevySilveradoK3500mechanic",
"Base.78amgeneralM62"
}
for index, fullName in ipairs(supported) do
expect(TowBarMod.Wrecker.isSupportedWrecker(vehicle(index, fullName, { hook = point(0, 0) })), fullName .. " should be supported")
expect(not TowBarMod.Wrecker.isSupportedWrecker(vehicle(index + 100, fullName, {})), fullName .. " without a hook must be rejected")
end
expect(not TowBarMod.Wrecker.isSupportedWrecker(vehicle(10, supported[1], {})), "exact variant without hook must be rejected")
expect(not TowBarMod.Wrecker.isSupportedWrecker(vehicle(11, "Base.76chevyK30CC", { hook = point(0, 0) })), "regular pickup must be rejected")
expect(not TowBarMod.Wrecker.isSupportedWrecker(vehicle(12, supported[1] .. "Burnt", { hook = point(0, 0) })), "suffixed lookalike must be rejected")
expect(not TowBarMod.Wrecker.isSupportedWrecker(vehicle(13, "Base.78amgeneralM35A2", { hook = point(0, 0) })), "ordinary M35A2 must be rejected")
expect(not TowBarMod.Wrecker.isSupportedWrecker(vehicle(14, "Base.Chevalier_Rhino_TowTruck", { hook = point(0, 0) })), "competing Rhino tow truck must be rejected")
expect(TowBarMod.Wrecker.nextHeightLevel(0, 1) == 1, "height should raise once from bottom")
expect(TowBarMod.Wrecker.nextHeightLevel(1, 1) == 2, "height should raise twice from bottom")
expect(TowBarMod.Wrecker.nextHeightLevel(2, 1) == 2, "height must clamp at the second upward step")
expect(TowBarMod.Wrecker.nextHeightLevel(0, -1) == 0, "height must not move below the initial hook position")
expect(TowBarMod.Wrecker.nextHeightLevel(2, -1) == 1, "height should lower one step")
expect(TowBarMod.Wrecker.nextHeightLevel(0, 0) == nil, "invalid height direction must be rejected")
expect(TowBarMod.Wrecker.getHeightAttachmentId(0) == "towbarWreckerHookLow", "level 0 must use the bottom hook")
expect(TowBarMod.Wrecker.getHeightAttachmentId(1) == "towbarWreckerHookMid", "level 1 must use the first upward step")
expect(TowBarMod.Wrecker.getHeightAttachmentId(2) == "towbarWreckerHookHigh", "level 2 must use the second upward step")
expect(TowBarMod.Wrecker.normalizeHeightLevel(-1) == 0, "old below-bottom state must migrate to bottom")
local wrecker = vehicle(20, supported[1], { hook = point(0, 0, 9) })
local nearRear = vehicle(21, "Base.CarA", {
trailer = point(0.599, 0, -50), trailerfront = point(4, 0, 50)
})
local nearFront = vehicle(22, "Base.CarB", {
trailer = point(5, 0), trailerfront = point(0.4, 0.1)
})
local result = TowBarMod.Wrecker.resolveNearestTarget(wrecker, { nearRear, nearFront })
expect(result and result.vehicle == nearFront and result.attachment == "trailerfront", "nearest endpoint across all vehicles must win")
result = TowBarMod.Wrecker.resolveNearestTarget(wrecker, { nearRear })
expect(result and result.attachment == "trailer", "0.599 endpoint must be accepted and world Z ignored")
local tooFar = vehicle(23, "Base.CarC", { trailer = point(0.601, 0) })
expect(TowBarMod.Wrecker.resolveNearestTarget(wrecker, { tooFar }) == nil, "0.601 endpoint must be rejected")
local trailer = vehicle(24, "Base.UtilityTrailer", { trailerfront = point(0.1, 0) })
expect(TowBarMod.Wrecker.resolveNearestTarget(wrecker, { trailer }) == nil, "trailers must be excluded from wrecker vehicle towing")
if failures > 0 then os.exit(1) end
print("PASS: wrecker helper behavior")