Skip to content

Capítulo 6.2: Sistema de Vehículos ​


Introducción ​

DayZ vehicles are entities that extend the transport system. Cars extend CarScript, boats extend BoatScript, and both inherit from Transport. Vehicles have fluid systems, parts with independent health, gear simulation, and physics managed by the engine. This chapter covers the API methods you need to interact with vehicles in scripts.


Class Hierarchy ​

EntityAI
└── Transport                    // 3_Game - base for all vehicles
    ├── Car                      // 3_Game - engine-native car physics
    │   └── CarScript            // 4_World - scriptable car base
    │       ├── CivilianSedan
    │       ├── OffroadHatchback
    │       ├── Hatchback_02
    │       ├── Sedan_02
    │       ├── Truck_01_Base
    │       └── ...
    └── Boat                     // 3_Game - engine-native boat physics
        └── BoatScript           // 4_World - scriptable boat base

Transport (Base) ​

Archivo: 3_Game/entities/transport.c

The abstract base for all vehicles. Provides seat management and crew access.

Crew Management ​

c
proto native int   CrewSize();                          // Total number of seats
proto native int   CrewMemberIndex(Human crew_member);  // Get seat index of a human
proto native Human CrewMember(int posIdx);              // Get human at seat index
proto native Human CrewGetOut(int posIdx);              // Force crew member out of seat (returns the ejected human)
proto native void  CrewDeath(int posIdx);               // Kill crew member in seat

Crew Entry ​

c
int  GetAnimInstance();                                 // Scripted (overridable) method, not proto native
proto native int  CrewPositionIndex(int componentIdx);  // Component to seat index
proto void CrewEntry(int posIdx, out vector pos, out vector dir);    // Entry point/direction in model space
proto void CrewEntryWS(int posIdx, out vector pos, out vector dir);  // Entry point/direction in world space

Ejemplo --- eject all passengers:

c
void EjectAllCrew(Transport vehicle)
{
    for (int i = 0; i < vehicle.CrewSize(); i++)
    {
        Human crew = vehicle.CrewMember(i);
        if (crew)
        {
            vehicle.CrewGetOut(i);
        }
    }
}

Car (Engine Native) ​

Archivo: 3_Game/entities/car.c

Engine-level car physics. All proto native methods that drive the vehicle simulation.

Engine ​

c
proto native bool  EngineIsOn();
proto native void  EngineStart();
proto native void  EngineStop();
proto native float EngineGetRPM();
proto native float EngineGetRPMRedline();
proto native float EngineGetRPMMax();
proto native int   GetGear();

Fluids ​

DayZ vehicles have four fluid types defined in the CarFluid enum:

c
enum CarFluid
{
    FUEL,
    OIL,
    BRAKE,
    COOLANT
}
c
proto native float GetFluidCapacity(CarFluid fluid);
proto native float GetFluidFraction(CarFluid fluid);     // 0.0 - 1.0
proto native void  Fill(CarFluid fluid, float amount);
proto native void  Leak(CarFluid fluid, float amount);
proto native void  LeakAll(CarFluid fluid);

Ejemplo --- refuel a vehicle:

c
void RefuelVehicle(Car car)
{
    float capacity = car.GetFluidCapacity(CarFluid.FUEL);
    float current = car.GetFluidFraction(CarFluid.FUEL) * capacity;
    float needed = capacity - current;
    car.Fill(CarFluid.FUEL, needed);
}

Speed ​

c
proto native float GetSpeedometer();    // Speed in km/h (absolute value)

Controls (Simulation) ​

c
proto native void  SetBrake(float value, float unused0 = 0, bool unused1 = false);  // 0.0 - 1.0 (extra params unused)
proto native void  SetHandbrake(float value);                 // 0.0 - 1.0
proto native void  SetSteering(float value, bool unused0 = false);  // -1.0 - 1.0 (second param unused)
proto native void  SetThrottle(float value);                  // 0.0 - 1.0 (SetThrust is obsolete)
proto native void  SetClutch(float value);                    // SetClutchState is obsolete

Wheels ​

c
proto native int   WheelCount();
proto native bool  WheelIsAnyLocked();
proto native SurfaceInfo WheelGetSurface(int wheelIdx);

Callbacks (Override in CarScript) ​

c
void OnEngineStart();
void OnEngineStop();
void OnContact(string zoneName, vector localPos, IEntity other, Contact data);
void OnFluidChanged(CarFluid fluid, float newValue, float oldValue);
void OnGearChanged(int newGear, int oldGear);
void OnSound(CarSoundCtrl ctrl, float oldValue);

CarScript ​

Archivo: 4_World/entities/vehicles/carscript.c

The scriptable car class that most vehicle mods extend. Adds parts, doors, lights, and sound management.

Part Health ​

CarScript uses damage zones to represent vehicle parts. Each part can be independently damaged:

c
// Check part health via the standard EntityAI API
float engineHP = car.GetHealth("Engine", "Health");
float fuelTankHP = car.GetHealth("FuelTank", "Health");

// Set part health
car.SetHealth("Engine", "Health", 0);       // Destroy the engine
car.SetHealth("FuelTank", "Health", 100);   // Repair the fuel tank

Damage Zone Diagram ​

Common damage zones for vehicles:

ZoneDescripción
"" (global)Overall vehicle health
"Engine"Engine part
"FuelTank"Fuel tank
"Radiator"Radiator (coolant)
"Battery"Battery
"SparkPlug"Spark plug
"FrontLeft" / "FrontRight"Front wheels
"RearLeft" / "RearRight"Rear wheels
"DriverDoor" / "CoDriverDoor"Front doors
"Hood" / "Trunk"Hood and trunk

Lights ​

La API de luces reside en Transport:

c
proto native bool LightIsOn();    // True when lights are on
proto native void LightOn();      // Turn lights on
proto native void LightOff();     // Turn lights off
proto native void LightToggle();  // Toggle current light state

Door Control ​

El estado de las puertas se consulta con GetCarDoorsState, que devuelve un valor CarDoorState (DOORS_MISSING, DOORS_OPEN o DOORS_CLOSED):

c
enum CarDoorState
{
    DOORS_MISSING,
    DOORS_OPEN,
    DOORS_CLOSED
}

int GetCarDoorsState(string slotType);   // Returns a CarDoorState value

Key Overrides for Custom Vehicles ​

c
override void EEInit();                    // Initialize vehicle parts, fluids
override void OnEngineStart();             // Custom engine start behavior
override void OnEngineStop();              // Custom engine stop behavior
override void EOnPostSimulate(IEntity other, float timeSlice);  // Per-tick simulation (CarScript)

Ejemplo --- create a vehicle with full fluids:

c
void SpawnReadyVehicle(vector pos)
{
    Car car = Car.Cast(GetGame().CreateObjectEx("CivilianSedan", pos,
                        ECE_PLACE_ON_SURFACE | ECE_INITAI | ECE_CREATEPHYSICS));
    if (!car)
        return;

    // Fill all fluids
    car.Fill(CarFluid.FUEL, car.GetFluidCapacity(CarFluid.FUEL));
    car.Fill(CarFluid.OIL, car.GetFluidCapacity(CarFluid.OIL));
    car.Fill(CarFluid.BRAKE, car.GetFluidCapacity(CarFluid.BRAKE));
    car.Fill(CarFluid.COOLANT, car.GetFluidCapacity(CarFluid.COOLANT));

    // Spawn required parts
    EntityAI carEntity = EntityAI.Cast(car);
    carEntity.GetInventory().CreateAttachment("CarBattery");
    carEntity.GetInventory().CreateAttachment("SparkPlug");
    carEntity.GetInventory().CreateAttachment("CarRadiator");
    carEntity.GetInventory().CreateAttachment("HatchbackWheel");
}

BoatScript ​

Archivo: 4_World/entities/vehicles/boatscript.c

Scriptable base for boat entities. Similar API to CarScript but with propeller-based physics.

Engine & Propulsion ​

c
proto native bool  EngineIsOn();
proto native void  EngineStart();
proto native void  EngineStop();
proto native float EngineGetRPM();

Fluids ​

Boats use a separate BoatFluid enum that only defines FUEL:

c
float fuel = boat.GetFluidFraction(BoatFluid.FUEL);
boat.Fill(BoatFluid.FUEL, boat.GetFluidCapacity(BoatFluid.FUEL));

Speed & Propulsion ​

Boat no expone GetSpeedometer() (ese método existe solo en Car). En su lugar, lee las RPM del motor y la velocidad de la hélice:

c
proto native float EngineGetRPM();                   // Engine rpm
proto native float PropellerGetAngularVelocity();    // Propeller angular velocity

Ejemplo --- spawn a boat:

Boat_01 no es una clase que se pueda spawnear directamente; spawnea una de las variantes de color concretas (Boat_01_Blue, Boat_01_Orange, Boat_01_Black, Boat_01_Camo):

c
void SpawnBoat(vector waterPos)
{
    BoatScript boat = BoatScript.Cast(
        GetGame().CreateObjectEx("Boat_01_Blue", waterPos,
                                  ECE_CREATEPHYSICS | ECE_INITAI)
    );
    if (boat)
    {
        boat.Fill(BoatFluid.FUEL, boat.GetFluidCapacity(BoatFluid.FUEL));
    }
}

Vehicle Interaction Checks ​

Checking if a Player is in a Vehicle ​

c
PlayerBase player;
if (player.IsInVehicle())
{
    EntityAI vehicle = player.GetDrivingVehicle();
    CarScript car;
    if (Class.CastTo(car, vehicle))
    {
        float speed = car.GetSpeedometer();
        Print(string.Format("Driving at %1 km/h", speed));
    }
}

Finding All Vehicles in the World ​

c
void FindAllVehicles(out array<Transport> vehicles)
{
    vehicles = new array<Transport>;
    array<Object> objects = new array<Object>;
    array<CargoBase> proxyCargos = new array<CargoBase>;

    // Use a large radius from center of map
    GetGame().GetObjectsAtPosition(Vector(7500, 0, 7500), 15000, objects, proxyCargos);

    foreach (Object obj : objects)
    {
        Transport transport;
        if (Class.CastTo(transport, obj))
        {
            vehicles.Insert(transport);
        }
    }
}

Resumen ​

ConceptoPunto Clave
HierarchyTransport > Car/Boat > CarScript/BoatScript
EngineEngineStart(), EngineStop(), EngineIsOn(), EngineGetRPM()
FluidsCarFluid enum: FUEL, OIL, BRAKE, COOLANT
Fill/LeakFill(fluid, amount), Leak(fluid, amount), GetFluidFraction(fluid)
SpeedGetSpeedometer() returns km/h
CrewCrewSize(), CrewMember(idx), CrewGetOut(idx)
PartsStandard damage zones: "Engine", "FuelTank", "Radiator", etc.
CreationCreateObjectEx with ECE_PLACE_ON_SURFACE | ECE_INITAI | ECE_CREATEPHYSICS
Config 1.28useNewNetworking, wheelHubFriction, valores de torque de freno duplicados
Fisica 1.28Bullet Physics actualizado, nuevos campos de la API Contact, suspension siempre activa
Experimental 1.29Multithreading de fisica, Transport sleep, colision dinamica para todo transport

Mejores Prácticas ​

  • Always include ECE_CREATEPHYSICS | ECE_INITAI when spawning vehicles. Without physics, the vehicle falls through the ground. Without AI init, the engine simulation does not start and the vehicle cannot be driven.
  • Fill all four fluids after spawning. A vehicle missing oil, brake fluid, or coolant will damage itself immediately when the engine starts. Use GetFluidCapacity() to get correct max values per vehicle type.
  • Null-check CrewMember() before operating on crew. Empty seats return null. Iterating CrewSize() without checking each index causes crashes when seats are unoccupied.
  • Use GetSpeedometer() instead of computing velocity manually. The engine's speedometer accounts for wheel contact, transmission state, and physics correctly. Manual velocity calculations from position deltas are unreliable.

Compatibilidad e Impacto ​

Mod Compatibility: Vehicle mods commonly extend CarScript with modded classes. Conflicts arise when multiple mods override the same callbacks like OnEngineStart() or EOnSimulate().

  • Load Order: If two mods both modded class CarScript and override OnEngineStart(), only the last-loaded mod runs unless both call super. Vehicle overhaul mods should always call super in every callback.
  • Modded Class Conflicts: Expansion Vehicles and vanilla vehicle mods frequently conflict on EEInit() and fluid initialization. Test with both loaded.
  • Performance Impact: EOnSimulate() runs every physics tick for each active vehicle. Keep logic minimal in this callback; use timer accumulators for expensive operations.
  • Server/Client: EngineStart(), EngineStop(), Fill(), Leak(), and CrewGetOut() are server-authoritative. GetSpeedometer(), EngineIsOn(), and GetFluidFraction() are safe to read on both sides.

Observado en Mods Reales ​

These patterns were confirmed by studying the source code of professional DayZ mods.

PatrónModFile/Location
Override EEInit() to set custom fluid capacities and spawn partsExpansion VehiclesCarScript subclasses
EOnSimulate accumulator for periodic fuel consumption checksVanilla+ vehicle modsCarScript overrides
CrewGetOut() loop in admin eject-all commandVPP Admin ToolsVehicle management module
Custom OnContact() override for collision damage tuningExpansionExpansionCarScript

Cambios de Configuracion de Vehiculos (1.28+) ​

Advertencia (1.28): DayZ 1.28 introdujo cambios significativos en la fisica de vehiculos. Si estas actualizando un mod de vehiculos desde 1.27 o anterior, lee esta seccion cuidadosamente.

Parametro useNewNetworking ​

DayZ 1.28 agrego el parametro de configuracion useNewNetworking para todas las clases CarScript. El valor predeterminado es 1 (activado).

cpp
class CfgVehicles
{
    class CarScript;
    class MyVehicle : CarScript
    {
        // El nuevo networking mejora el rubber-banding con ping alto
        useNewNetworking = 1;  // predeterminado --- dejalo activado para la mayoria de mods

        // Desactiva SOLO si tu mod modifica la fisica del vehiculo
        // fuera de la configuracion del SimulationModule:
        // useNewNetworking = 0;
    };
};

Cuando desactivar: Si tu mod manipula directamente la fisica del vehiculo a traves de script (sobreescrituras personalizadas de EOnSimulate, aplicacion directa de fuerzas, logica de ruedas personalizada) en lugar de hacerlo a traves del SimulationModule basado en configuracion, el nuevo sistema de reconciliacion puede luchar contra tus cambios. Pon useNewNetworking = 0; en ese caso.

Parametro wheelHubFriction (1.28+) ​

Nueva variable de configuracion que define la resistencia del eje cuando no hay ruedas conectadas:

cpp
class SimulationModule
{
    class Axles
    {
        class Front
        {
            wheelHubFriction = 0.5;  // Que tan rapido desacelera el vehiculo con ruedas faltantes
        };
    };
};

Migracion de Torque de Freno (1.28) ​

Cambio incompatible: Antes de 1.28, el torque de freno y freno de mano se aplicaba dos veces debido a un bug. Esto fue corregido en 1.28. Si estas migrando un mod de vehiculos, duplica tus valores de maxBrakeTorque y maxHandbrakeTorque para mantener la misma sensacion de frenado.

cpp
// Pre-1.28 (bug: se aplicaba dos veces, asi que el valor efectivo era 2x)
maxBrakeTorque = 2000;
maxHandbrakeTorque = 3000;

// Post-1.28 (correccion: se aplica una vez, asi que duplica para igualar el comportamiento anterior)
maxBrakeTorque = 4000;
maxHandbrakeTorque = 6000;

Suspension Siempre Activa (1.28+) ​

La suspension del vehiculo ahora esta siempre activa mientras el vehiculo esta despierto. Anteriormente, la suspension podia estar inactiva en ciertos estados. Esto mejora la estabilidad pero puede cambiar la sensacion de la calibracion de suspension personalizada.

Actualizacion de Bullet Physics (1.28) ​

La libreria Bullet Physics fue actualizada a la ultima version de Enfusion. Pueden ocurrir diferencias sutiles en respuesta de colision, friccion y restitucion. Prueba todas las configuraciones de vehiculos personalizados exhaustivamente.

Cambios en la API de Contacto Fisico (1.28) ​

La clase Contact fue modificada:

Eliminados:

  • MaterialIndex1, MaterialIndex2
  • Index1, Index2

Agregados:

  • ShapeIndex1, ShapeIndex2 --- identifican que forma en un cuerpo compuesto fue golpeada
  • VelocityBefore1, VelocityBefore2 --- velocidades pre-colision
  • VelocityAfter1, VelocityAfter2 --- velocidades post-colision

Cambiados:

  • Material1, Material2 --- el tipo cambio de dMaterial a SurfaceProperties

Los mods que leen datos de Contact en OnContact deben actualizarse a los nuevos nombres y tipos de variables.


Cambios de Vehiculos en 1.29 (Experimental) ​

Nota: Estos cambios son de DayZ 1.29 experimental y pueden cambiar antes del lanzamiento estable.

Multithreading de Bullet Physics (1.29 Experimental) ​

Se habilito el soporte de multithreading para la libreria Bullet Physics. Las pruebas de estres del servidor mostraron hasta 400% de mejora en FPS (de 9 FPS a 50 FPS). Los mods de vehiculos que dependen de timing especifico de fisica o hacen llamadas de fisica desde callbacks de script deben probarse exhaustivamente.

Transport Sleep (1.29 Experimental) ​

Se agregaron funciones de fisica directamente en Transport para permitir que los vehiculos entren en sleep cuando estan en reposo. Los cuerpos inactivos ya no reciben callbacks de EOnSimulate / EOnPostSimulate. Si tu mod de vehiculos depende de que estos callbacks se disparen continuamente, prueba en 1.29 experimental.

Colision Dinamica para Todo Transport (1.29 Experimental) ​

La clase Transport (padre de CarScript y BoatScript) ahora tiene resolucion de colision dinamica. Anteriormente, solo CarScript tenia esto. Los mods de botes se benefician de un manejo de colision adecuado.

Released under CC BY-SA 4.0 | Code examples under MIT License