Skip to content

Chapter 6.2: Vehicle System

Domů | << Předchozí: Systém entit | Vozidla | Další: Počasí >>


Úvod

DayZ vehicles are entities that extend the transport system. Cars extend CarScript, boats extend BoatScript, and oba inherit from Transport. Vehicles have fluid systems, parts with nezávislý health, gear simulation, and physics managed by engine. This chapter covers the API methods potřebujete to interact with vehicles in scripts.


Hierarchie tříd

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 (základ)

Soubor: 3_Game/entities/transport.c

Abstraktní základ pro všechna vozidla. Poskytuje správu sedadel a přístup k posádce.

Správa posádky

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 void  CrewGetOut(int posIdx);              // Force crew member out of seat
proto native void  CrewDeath(int posIdx);               // Kill crew member in seat

Nastupování posádky

c
proto native int  GetAnimInstance();
proto native int  CrewPositionIndex(int componentIdx);  // Component to seat index
proto native vector CrewEntryPoint(int posIdx);         // World entry position for seat

Příklad --- 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 (nativní engine)

Soubor: 3_Game/entities/car.c

Fyzika auta na úrovni enginu. Všechny proto native metody, které řídí simulaci vozidla.

Motor

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();

Kapaliny

Vozidla DayZ mají čtyři typy kapalin definované ve 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);

Příklad --- 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);
}

Rychlost

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

Ovládání (simulace)

c
proto native void  SetBrake(float value, int wheel = -1);    // 0.0 - 1.0, -1 = all wheels
proto native void  SetHandbrake(float value);                 // 0.0 - 1.0
proto native void  SetSteering(float value, bool analog = true);
proto native void  SetThrust(float value, int wheel = -1);    // 0.0 - 1.0
proto native void  SetClutchState(bool engaged);

Kola

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

Zpětná volání (přepsat v 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

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

The scriptable car class that většina vehicle mods extend. Adds parts, doors, lights, and sound management.

Zdraví dílů

CarScript uses damage zones to represent vehicle parts. Each part can be nezávisle 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

Diagram zón poškození

Běžné damage zones for vehicles:

ZoneDescription
"" (globální)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

Světla

c
void SetLightsState(int state);   // 0 = off, 1 = on
int  GetLightsState();

Ovládání dveří

c
bool IsDoorOpen(string doorSource);
void OpenDoor(string doorSource);
void CloseDoor(string doorSource);

Klíčová přepsání pro vlastní vozidla

c
override void EEInit();                    // Initialize vehicle parts, fluids
override void OnEngineStart();             // Custom engine start behavior
override void OnEngineStop();              // Custom engine stop behavior
override void EOnSimulate(IEntity other, float dt);  // Per-tick simulation
override bool CanObjectAttachWeapon(string slot_name);

Příklad --- create a vehicle with plný 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

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

Skriptovatelný základ pro entity lodí. Podobné API jako CarScript, ale s fyzikou založenou na vrtuli.

Motor a pohon

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

Kapaliny

Boats use the stejný CarFluid enum but typicky pouze use FUEL:

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

Rychlost

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

Příklad --- spawn a boat:

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

Kontroly interakce s vozidlem

Kontrola, zda je hráč ve vozidle

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));
    }
}

Nalezení všech vozidel ve světě

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);
        }
    }
}

Shrnutí

KonceptKlíčový bod
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
1.28 ConfiguseNewNetworking, wheelHubFriction, zdvojnásobené hodnoty brzdného momentu
1.28 PhysicsAktualizovaný Bullet Physics, nová pole API Contact, odpružení vždy aktivní
1.29 ExperimentalMultithreading fyziky, Transport sleep, dynamická kolize pro všechny transport

Osvědčené postupy

  • Vždy include ECE_CREATEPHYSICS | ECE_INITAI when spawning vehicles. Bez physics, the vehicle falls through the ground. Bez AI init, engine simulation ne start and the vehicle nemůže být driven.
  • Fill all four fluids after spawning. A vehicle chybějící oil, brake fluid, or coolant will damage itself okamžitě when 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 každý index causes crashes when seats are unoccupied.
  • Use GetSpeedometer() místo computing velocity ručně. Engine's speedometer accounts for wheel contact, transmission state, and physics správně. Manual velocity calculations from position deltas are unreliable.

Kompatibilita a dopad

Kompatibilita modů: Vehicle mods běžně extend CarScript with modded classes. Conflicts arise when více mods override the stejný zpětné volánís like OnEngineStart() or EOnSimulate().

  • Pořadí načítání: 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.
  • Konflikty modifikovaných tříd: Expansion Vehicles and vanilla vehicle mods frequently conflict on EEInit() and fluid initialization. Testujte with oba loaded.
  • Dopad na výkon: EOnSimulate() runs každý physics tick for každý active vehicle. Udržujte logic minimal in this zpětné volání; use timer accumulators for expensive operations.
  • Server/klient: EngineStart(), EngineStop(), Fill(), Leak(), and CrewGetOut() are server-authoritative. GetSpeedometer(), EngineIsOn(), and GetFluidFraction() are safe to read na obou stranách.

Pozorováno v reálných modech

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

VzorModSoubor/Umístění
Override EEInit() to set vlastní 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

Změny konfigurace vozidel (1.28+)

Upozornění (1.28): DayZ 1.28 přinesl významné změny fyziky vozidel. Pokud aktualizujete mod vozidel z verze 1.27 nebo starší, pečlivě si přečtěte tuto sekci.

Parametr useNewNetworking

DayZ 1.28 přidal konfigurační parametr useNewNetworking pro všechny třídy CarScript. Výchozí hodnota je 1 (povoleno).

cpp
class CfgVehicles
{
    class CarScript;
    class MyVehicle : CarScript
    {
        // Nový networking zlepšuje gumování při vysokém pingu
        useNewNetworking = 1;  // výchozí — pro většinu modů ponechte povoleno

        // Zakažte POUZE pokud váš mod modifikuje fyziku vozidel
        // mimo konfiguraci SimulationModule:
        // useNewNetworking = 0;
    };
};

Kdy zakázat: Pokud váš mod přímo manipuluje s fyzikou vozidel přes skript (vlastní přepisování EOnSimulate, přímé aplikování sil, vlastní logika kol) namísto přes konfiguraci SimulationModule, nový systém rekonciliace může bojovat s vašimi změnami. V takovém případě nastavte useNewNetworking = 0;.

Parametr wheelHubFriction (1.28+)

Nová konfigurační proměnná, která definuje odpor nápravy, když nejsou připojena žádná kola:

cpp
class SimulationModule
{
    class Axles
    {
        class Front
        {
            wheelHubFriction = 0.5;  // Jak rychle vozidlo zpomaluje bez kol
        };
    };
};

Migrace brzdného momentu (1.28)

Narušující změna: Před verzí 1.28 se brzdný a ruční brzdný moment aplikoval dvakrát kvůli chybě. Ve verzi 1.28 to bylo opraveno. Pokud migrujete mod vozidla, zdvojnásobte hodnoty maxBrakeTorque a maxHandbrakeTorque pro zachování stejného pocitu brzdění.

cpp
// Před 1.28 (chyba: aplikováno dvakrát, takže efektivní hodnota byla 2x)
maxBrakeTorque = 2000;
maxHandbrakeTorque = 3000;

// Po 1.28 (oprava: aplikováno jednou, takže zdvojnásobte pro zachování starého chování)
maxBrakeTorque = 4000;
maxHandbrakeTorque = 6000;

Odpružení vždy aktivní (1.28+)

Odpružení vozidla je nyní vždy aktivní, dokud je vozidlo probuzené. Předtím mohlo být odpružení v určitých stavech neaktivní. To zlepšuje stabilitu, ale může změnit pocit vlastního nastavení odpružení.

Aktualizace Bullet Physics (1.28)

Knihovna Bullet Physics byla aktualizována na nejnovější verzi Enfusion. Mohou se vyskytnout jemné rozdíly v kolizní odezvě, tření a restituci. Důkladně otestujte všechny vlastní konfigurace vozidel.

Změny API fyzických kontaktů (1.28)

Třída Contact byla upravena:

Odstraněno:

  • MaterialIndex1, MaterialIndex2
  • Index1, Index2

Přidáno:

  • ShapeIndex1, ShapeIndex2 --- identifikují, který tvar ve složeném tělese byl zasažen
  • VelocityBefore1, VelocityBefore2 --- rychlosti před kolizí
  • VelocityAfter1, VelocityAfter2 --- rychlosti po kolizi

Změněno:

  • Material1, Material2 --- typ změněn z dMaterial na SurfaceProperties

Mody, které čtou data Contact v EOnContact, musí aktualizovat názvy a typy nových proměnných.


Změny vozidel v 1.29 (experimentální)

Poznámka: Tyto změny pochází z DayZ 1.29 experimentálního a mohou se před stabilní verzí změnit.

Multithreading Bullet Physics (1.29 experimentální)

Pro knihovnu Bullet Physics byla povolena podpora multithreadingu. Stresové testy serveru ukázaly až 400% zlepšení FPS (z 9 FPS na 50 FPS). Mody vozidel, které se spoléhají na specifické časování fyziky nebo volají funkce fyziky z callbacků skriptů, by měly být důkladně otestovány.

Transport Sleep (1.29 experimentální)

Na Transport byly přidány fyzikální funkce umožňující vozidlům usnout, když jsou v klidu. Neaktivní tělesa již nepřijímají callbacky EOnSimulate / EOnPostSimulate. Pokud se váš mod vozidla spoléhá na to, že tyto callbacky běží nepřetržitě, otestujte na 1.29 experimentálním.

Dynamická kolize pro všechny Transport (1.29 experimentální)

Třída Transport (rodič CarScript a BoatScript) má nyní dynamické řešení kolizí. Předtím to měl pouze CarScript. Mody lodí těží ze správného zpracování kolizí.


Domů | << Předchozí: Systém entit | Vozidla | Další: Počasí >>

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