sinor-CarriageSystem
Red Dead style Carriages System.
This resource adds attached horses, movement animations, rope visuals, carriage step audio, and an optional rental system for configured carriage vehicles. Carriages remain normal vehicles, so anything your framework already does for vehicles such as storage, fuel ,Garages , keys, or extra integrations can still be used.
Features
- Spawns attached horses on configured carriage vehicles
- Plays horses animations based on carriage movement
- Draws harness ropes from horses to carriage and from driver to horses
- Plays carriage movement 3D audio with different sounds per speed state
- Optional rental system
- Keeps carriage fuel full through a configurable fuel hook
- Horses die when the carriage is destroyed if enabled
- Horses respawn and reattach automatically if the carriage is repaired
- Streaming logic only tracks nearby configured carriages
Requirements
- `ox_lib`
- `ox_target` or `qb-target` (optional)
Config
Config = Config or {}
-- note : you can add the carriages to ur vehicle shop and the script will spawn the horses on all carriages
-- rent settings
Config.Rental = {
Enabled = true, -- if standalone desable it
Framework = "qb", -- qb / esx
MoneyAccount = "cash", -- cash/bank
Interaction = "textui", -- ox_target / qb-target / textui
InteractionDistance = 5.0,
Blip = {
Enabled = true,
Sprite = 479,
Color = 3,
Scale = 0.8,
ShortRange = false,
Name = 'Carriage Rental',
},
TextUI = {
RentKey = 38,
},
Locations = {
{
Label = "Carriage Rental",
Ped = {
model = "a_m_y_hippy_01",
coords = vector4(1901.18, 4924.02, 48.81, 247.34),
scenario = "WORLD_HUMAN_CLIPBOARD",
},
Spawn = vector4(1902.87, 4918.77, 48.73, 161.82),
ReturnDistance = 12.0,
Carriages = {
wagon = 450,
cart = 330,
cab = 700,
},
},
-- add more locations
},
}
-- to give key on rental
-- examples:
-- function example:
-- give = function(plate, netId, vehicle)
-- TriggerEvent('vehiclekeys:client:SetOwner', plate)
-- end
--
-- client event example:
-- give = { event = 'vehiclekeys:client:SetOwner' }
--
-- server event example:
-- give = { serverEvent = 'my-keys:server:giveRentalKey' }
--
-- export example:
-- give = {
-- export = {
-- resource = 'mykeys',
-- func = 'GiveKey'
-- }
-- }
Config.KeyHook = {
enabled = true,
give = function(plate, netId, vehicle)
TriggerEvent('vehiclekeys:client:SetOwner', plate)
end
}
-- so fuel never go down for carriages
-- note : this work on carriages from rental or any other source "spawnd/owned...."
-- examples :
-- native/default example:
-- set = function(vehicle, amount)
-- SetVehicleFuelLevel(vehicle, amount)
-- end
-- ps-fuel example:
-- set = function(vehicle, amount)
-- exports['ps-fuel']:SetFuel(vehicle, amount)
-- end
-- LegacyFuel example:
-- set = function(vehicle, amount)
-- exports['LegacyFuel']:SetFuel(vehicle, amount)
-- end
Config.FuelHook = {
enabled = true,
level = 100.0,
tickMs = 5000,
set = function(vehicle, amount)
exports['ps-fuel']:SetFuel(vehicle, amount)
end
}
-- translations
Config.Translations = {
carriage_prefix = "Carriage",
horse_model_not_found = "Horse model not found: %s",
no_carriage_rentals = "No carriage rentals configured here",
rental_ped_model_not_found = "Rental ped model not found: %s",
rental_vehicle_model_not_found = "Rental vehicle model not found: %s",
failed_spawn_rented_carriage = "Failed to spawn rented carriage",
rental_menu_title = "Carriage Rental",
rental_menu_open = "Open carriage rental",
rental_menu_open_textui = "[E] Open carriage rental menu",
rental_menu_return_available = " [Return available in menu]",
rental_menu_rent_title = "Rent %s",
rental_menu_rent_desc = "$%s - to rent %s",
rental_menu_return_title = "Return rented carriage",
rental_menu_return_desc = "Return your current rented carriage at this rental point",
invalid_rental_option = "Invalid rental option",
carriage_not_rented_here = "This carriage cannot be rented here",
return_current_carriage_first = "Return your current rented carriage first",
not_enough_money_rental = "Not enough money for this rental",
no_rented_carriage = "You do not have a rented carriage",
invalid_return_point = "Invalid return point",
must_return_rented_carriage = "You must be in your rented carriage",
carriage_returned = "Carriage returned",
}
-- Horses streaming settings
Config.Streaming = {
Distance = 150.0,
ScanIntervalMs = 1200,
AnimTickMs = 300,
RopeDistance = 40.0,
AnimationDistance = 100.0,
TargetBlockDistance = 4.0,
RopeIdleMs = 350,
StateTickMs = 200,
}
-- native audio settings
Config.CarriageAudio = {
Enabled = true,
AudioBank = "audiodirectory/carriages_sounds",
SoundSet = "carriage_special_soundset",
HearDistance = 50.0,
TickMs = 100,
StepDuration = 10000,
Sounds = {
walk = { "carriage_lew_speed_1", "carriage_lew_speed_2" },
trot = { "carriage_mid_speed_1", "carriage_mid_speed_2" },
run = { "carriage_high_speed_2" }, -- you can use this "carriage_high_speed_1" but its better with one
},
}
-- main carriages settings
Config.Carriage = {
wagon = {
Vehicle = {
Model = "wagon", -- veh model
DriverSeat = -1,-- for the rope
},
Horses = {
Enabled = true,
PedType = 28, -- deer and addon horses...
DisableCollision = false, -- keep horse collision
Invincible = true, -- horses dont die
DieWithVehicle = true, -- kill attached horses when the carriage is destroyed
VehicleDeathHealth = 0.0,
Freeze = false,
-- horses list for the vehicle
List = {
{
model = "carriage_horse",
offset = { x = -1.1, y = 3.9, z = -0.2 },
rotation = { x = 0.0, y = 0.0, z = 0.0 },
bone = 0,
},
{
model = "carriage_horse",
offset = { x = 1.1, y = 3.9, z = -0.2 },
rotation = { x = 0.0, y = 0.0, z = 0.0 },
bone = 0,
},
},
-- animations settings
Animations = {
Enabled = true,
AnimDict = "creatures@deer@move",
Idle = "idle",
IdleTurnL = "idle",
IdleTurnR = "idle",
Walk = "walk",
WalkTurnL = "walk_turn_r",
WalkTurnR = "walk_turn_l",
Trot = "trot",
TrotTurnL = "trot_turn_r",
TrotTurnR = "trot_turn_l",
ReverseWalk = "walk_backwards",
ReverseTurnL = "walk_backwards",
ReverseTurnR = "walk_backwards",
Run = "gallop_fwd_dwn",
RunTurnL = "gallop_fwd_dwn",
RunTurnR = "gallop_fwd_dwn",
-- speed and steer to change the anim
MinMoveSpeedKmh = 1.0,
ReverseMinSpeedKmh = 1.0,
WalkMaxSpeedKmh = 15.0,
TrotMaxSpeedKmh = 45.0,
SteerDeadzone = 6.0,
},
},
-- horse to veh ropes
Ropes = {
Enabled = true,
HorseHeadBone = 31086,
HorseSideSpread = 0.16,
HorseZOffset = 0.02,
CarriageLeftOffset = { x = -0.77, y = 2.0, z = 0.10 },
CarriageRightOffset = { x = 0.77, y = 2.0, z = 0.10 },
Color = { r = 125, g = 95, b = 60, a = 220 },
Thickness = 5,
},
-- horse to driver rope
DriverRopes = {
Enabled = true,
LeftHandBone = 18905,
RightHandBone = 57005,
LeftHandOffset = { x = 0.0, y = 0.04, z = 0.02 },
RightHandOffset = { x = 0.0, y = 0.04, z = 0.02 },
HorseHeadBone = 31086,
HorseSideSpread = 0.12,
HorseZOffset = 0.02,
Color = { r = 125, g = 95, b = 60, a = 220 },
Thickness = 2,
},
},
cart = {
Vehicle = {
Model = "cart",
DriverSeat = -1,
},
Horses = {
Enabled = true,
PedType = 28,
DisableCollision = false,
Invincible = true,
DieWithVehicle = true,
VehicleDeathHealth = 0.0,
Freeze = false,
List = {
{
model = "carriage_horse",
offset = { x = 0.0, y = 3.2, z = -0.3 },
rotation = { x = 0.0, y = 0.0, z = 0.0 },
bone = 0,
},
},
Animations = {
Enabled = true,
AnimDict = "creatures@deer@move",
Idle = "idle",
IdleTurnL = "idle",
IdleTurnR = "idle",
Walk = "walk",
WalkTurnL = "walk_turn_r",
WalkTurnR = "walk_turn_l",
Trot = "trot",
TrotTurnL = "trot_turn_r",
TrotTurnR = "trot_turn_l",
ReverseWalk = "walk_backwards",
ReverseTurnL = "walk_backwards",
ReverseTurnR = "walk_backwards",
Run = "gallop_fwd_dwn",
RunTurnL = "gallop_fwd_dwn",
RunTurnR = "gallop_fwd_dwn",
MinMoveSpeedKmh = 1.0,
ReverseMinSpeedKmh = 1.0,
WalkMaxSpeedKmh = 15.0,
TrotMaxSpeedKmh = 45.0,
SteerDeadzone = 6.0,
},
},
Ropes = {
Enabled = true,
HorseHeadBone = 31086,
HorseSideSpread = 0.16,
HorseZOffset = 0.02,
CarriageLeftOffset = { x = -0.8, y = 0.95, z = 0.1 },
CarriageRightOffset = { x = 0.8, y = 0.95, z = 0.1 },
Color = { r = 125, g = 95, b = 60, a = 220 },
Thickness = 5,
},
DriverRopes = {
Enabled = true,
LeftHandBone = 18905,
RightHandBone = 57005,
LeftHandOffset = { x = 0.0, y = 0.04, z = 0.02 },
RightHandOffset = { x = 0.0, y = 0.04, z = 0.02 },
HorseHeadBone = 31086,
HorseSideSpread = 0.12,
HorseZOffset = 0.02,
Color = { r = 125, g = 95, b = 60, a = 220 },
Thickness = 2,
},
},
cab = {
Vehicle = {
Model = "cab",
DriverSeat = -1,
},
Horses = {
Enabled = true,
PedType = 28,
DisableCollision = false,
Invincible = true,
DieWithVehicle = true,
VehicleDeathHealth = 0.0,
Freeze = false,
List = {
{
model = "carriage_horse",
offset = { x = -0.9, y = 3.9, z = -0.4 },
rotation = { x = 0.0, y = 0.0, z = 0.0 },
bone = 0,
},
{
model = "carriage_horse",
offset = { x = 0.9, y = 3.9, z = -0.4 },
rotation = { x = 0.0, y = 0.0, z = 0.0 },
bone = 0,
},
},
Animations = {
Enabled = true,
AnimDict = "creatures@deer@move",
Idle = "idle",
IdleTurnL = "idle",
IdleTurnR = "idle",
Walk = "walk",
WalkTurnL = "walk_turn_r",
WalkTurnR = "walk_turn_l",
Trot = "trot",
TrotTurnL = "trot_turn_r",
TrotTurnR = "trot_turn_l",
ReverseWalk = "walk_backwards",
ReverseTurnL = "walk_backwards",
ReverseTurnR = "walk_backwards",
Run = "gallop_fwd_dwn",
RunTurnL = "gallop_fwd_dwn",
RunTurnR = "gallop_fwd_dwn",
MinMoveSpeedKmh = 1.0,
ReverseMinSpeedKmh = 1.0,
WalkMaxSpeedKmh = 15.0,
TrotMaxSpeedKmh = 45.0,
SteerDeadzone = 6.0,
},
},
Ropes = {
Enabled = true,
HorseHeadBone = 31086,
HorseSideSpread = 0.16,
HorseZOffset = 0.02,
CarriageLeftOffset = { x = -0.67, y = 2.0, z = 0.10 },
CarriageRightOffset = { x = 0.67, y = 2.0, z = 0.10 },
Color = { r = 125, g = 95, b = 60, a = 220 },
Thickness = 5,
},
DriverRopes = {
Enabled = true,
LeftHandBone = 18905,
RightHandBone = 57005,
LeftHandOffset = { x = 0.0, y = 0.04, z = 0.02 },
RightHandOffset = { x = 0.0, y = 0.04, z = 0.02 },
HorseHeadBone = 31086,
HorseSideSpread = 0.12,
HorseZOffset = 0.02,
Color = { r = 125, g = 95, b = 60, a = 220 },
Thickness = 2,
},
},
}
```
Preview
Tebex
https://sinorsystem.tebex.io/package/7404108
Images
- all 3 carriages included in the resource
other Resources
QBCore/ESX|BaseBuilding
Standalone|AdvancedZombieSystem
Standalone|SurvivalHUD
Standalone|VehicleSpawne
QBCore/ESX|UsableItems
QBCore/ESX|VehicleCrafting
QBCore/ESX|Recycler
QBCore/ESX|Gather
Standalone|SafeZone
QBCore/ESX|LootAreas
QBCore/ESX|LootPeds
QBCore/ESX|RadiationZones
Standalone|ZombieSystem
QBCore|Shop
QBCore|WeatherSync
QBCore/ESX|InGameMusic
QBCore/ESX|CamperHousing
QBCore/ESX|LootBags
Vehicles|ApocalypticVehicles-V1
QBCore/ESX|HorseRiding
QBCore/ESX|Menu
| Code is accessible | Config |
| Subscription-based | No |
| Lines (approximately) | 2000+ |
| Requirements | ox_lib |
| Support | Yes |

