Intial Commit

This commit is contained in:
2026-02-06 14:50:37 -05:00
parent ba773ae6a3
commit b9f61adafe
62 changed files with 5055 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
BTtow = {}
BTtow.Create = {}
BTtow.Init = {}
function BTtow.Create.towbar(vehicle, part)
if part == nil then return end
for j=0, 23 do
part:setModelVisible("towbar" .. j, false)
end
end
function BTtow.Init.towbar(vehicle, part)
if part == nil then return end
for j=0, 23 do
part:setModelVisible("towbar" .. j, false)
end
if vehicle:getScript():getModelScale() > 2 or vehicle:getScript():getModelScale() < 1.5 then return end
if vehicle:getModData()["isTowingByTowBar"] and vehicle:getModData()["towed"] then
local z = vehicle:getScript():getPhysicsChassisShape():z()/2 - 0.1
part:setModelVisible("towbar" .. math.floor((z*2/3-1)*10), true)
end
end

View File

@@ -0,0 +1,71 @@
require 'Items/ProceduralDistributions'
require 'Items/SuburbsDistributions'
require 'Items/Distributions'
require 'Items/Distribution_BinJunk'
require 'Items/Distribution_ClosetJunk'
require 'Items/Distribution_DeskJunk'
require 'Items/Distribution_ShelfJunk'
require 'Items/Distribution_CounterJunk'
require 'Items/Distribution_SideTableJunk'
require 'Vehicles/VehicleDistributions'
require 'Vehicles/VehicleDistribution_GloveBoxJunk'
require 'Vehicles/VehicleDistribution_SeatJunk'
require 'Vehicles/VehicleDistribution_TrunkJunk'
----------------- TOW BAR -----------------------
-- Mirror Jack spawn chance into TowBar in container distributions (world + vehicle containers).
-- Intentionally excludes story-clutter floor placement tables (RandomizedWorldContent/StoryClutter).
local TOWBAR_ITEM_TYPE = "TowBar.TowBar"
local JACK_ITEM_TYPES = {
["Jack"] = true,
["Base.Jack"] = true,
}
local function addMissingTowBarsForJack(items)
if type(items) ~= "table" then return end
local jackCountByChance = {}
local towBarCountByChance = {}
for i = 1, #items, 2 do
local itemType = items[i]
local chance = tonumber(items[i + 1])
if type(itemType) == "string" and chance ~= nil then
if JACK_ITEM_TYPES[itemType] then
jackCountByChance[chance] = (jackCountByChance[chance] or 0) + 1
elseif itemType == TOWBAR_ITEM_TYPE then
towBarCountByChance[chance] = (towBarCountByChance[chance] or 0) + 1
end
end
end
for chance, jackCount in pairs(jackCountByChance) do
local missing = jackCount - (towBarCountByChance[chance] or 0)
for _ = 1, missing do
table.insert(items, TOWBAR_ITEM_TYPE)
table.insert(items, chance)
end
end
end
local function walkContainerDistributions(root, seen)
if type(root) ~= "table" or seen[root] then return end
seen[root] = true
for key, value in pairs(root) do
if key == "items" and type(value) == "table" then
addMissingTowBarsForJack(value)
elseif type(value) == "table" then
walkContainerDistributions(value, seen)
end
end
end
local seen = {}
walkContainerDistributions(ProceduralDistributions, seen)
walkContainerDistributions(SuburbsDistributions, seen)
walkContainerDistributions(Distributions, seen)
walkContainerDistributions(VehicleDistributions, seen)
walkContainerDistributions(ClutterTables, seen)

View File

@@ -0,0 +1,73 @@
if isClient() then return end
local Commands = {}
local TowBarItemType = "TowBar.TowBar"
function Commands.attachConstraint(player, args)
local vehicleA = args and getVehicleById(args.vehicleA)
local vehicleB = args and getVehicleById(args.vehicleB)
local attachmentA = args and args.attachmentA
local attachmentB = args and args.attachmentB
if not vehicleA or not vehicleB or not attachmentA or not attachmentB then return end
vehicleA:addPointConstraint(player, vehicleB, attachmentA, attachmentB)
end
function Commands.detachConstraint(player, args)
local vehicle = args and getVehicleById(args.vehicle)
if not vehicle then return end
vehicle:breakConstraint(true, false)
end
function Commands.consumeTowBar(player, args)
if not player then return end
local inventory = player:getInventory()
if not inventory then return end
local towBarItem = nil
local itemId = args and args.itemId
if itemId then
towBarItem = inventory:getItemWithID(itemId)
end
if not towBarItem then
towBarItem = inventory:getFirstTypeRecurse(TowBarItemType)
end
if not towBarItem then return end
local wasPrimary = player:isPrimaryHandItem(towBarItem)
local wasSecondary = player:isSecondaryHandItem(towBarItem)
player:removeFromHands(towBarItem)
inventory:Remove(towBarItem)
sendRemoveItemFromContainer(inventory, towBarItem)
if wasPrimary or wasSecondary then
sendEquip(player)
end
end
function Commands.giveTowBar(player, args)
if not player then return end
local inventory = player:getInventory()
if not inventory then return end
local towBarItem = inventory:AddItem(TowBarItemType)
if not towBarItem then return end
sendAddItemToContainer(inventory, towBarItem)
if args and args.equipPrimary then
player:setPrimaryHandItem(towBarItem)
sendEquip(player)
end
end
local function onClientCommand(module, command, player, args)
if module ~= "towbar" then return end
local fn = Commands[command]
if fn then
fn(player, args or {})
end
end
Events.OnClientCommand.Add(onClientCommand)