The Vehicle System is implemented in CryAction (the interface between Engine and Game), Game, and Lua.
The following Lua files are stored in the Scripts/Entities/Vehicles
directory.
Lua file | Description |
---|---|
VehicleBase.lua | Implements several standard vehicle script functions which are mostly used to interact with other game systems. |
VehicleBaseAI.lua | Integration with the AI System. |
VehiclePool.lua | Merges all the standard vehicle script functions to the vehicle script table. |
VehicleSystem.lua | Parses all the vehicle class implementation and store them inside of a script table. |
Every vehicle class is defined inside its corresponding XML file. Vehicle class XML files should be stored in the Scripts/Entities/Vehicles/Implementations/Xml
directory.
The following interfaces represent the major code components of a vehicle:
With the exception of IVehicleClient, all these interfaces are implemented in CryAction. The IVehicleClient interface is implemented in the GameDLL as it defines the game-specific ways for the player on the client to handle the vehicles.
The CVehicleSystem singleton class keeps registrations of all the available Vehicle Objects along with all the different vehicle classes.
The following object factories can be used to extend the functionality of vehicles.
Except for IVehicleMovement, all these interface derive from IVehicleObject.
To register a new vehicle object factory, we can use the following macro:
IVehicleSystem* pVehicleSystem = pFramework->GetIVehicleSystem();
#define REGISTER_VEHICLEOBJECT(name, obj) \
REGISTER_FACTORY((IVehicleSystem*)pVehicleSystem, name, obj, false); \
obj::m_objectId = pVehicleSystem->AssignVehicleObjectId();
A vehicle class is defined in an XML file. The vehicle system will parse all the .xml files stored in this directory. The content of the XML file will instruct which vehicle objects will be required by this vehicle class.
More information are available on the structure of the vehicle class XML files.
During initialization of the Game Framework (CryAction), CVehicleSystem::RegisterVehicles() is called. This function will search for all the XML files at this path: Game\Scripts\Entities\Vehicles\Implementations\Xml
.
A new CVehicle instance is create by the vehicle system each time a vehicle is spawned by the Entity System.
The Vehicle Client is a singleton class derived from the IVehicleClient interface and is usually implemented inside the GameDLL. It is required to handle game specific functionality like mapping action maps to vehicle features and also high-level handling of player entering/exiting seats. Gamepad actions are received with the IVehicleClient::OnAction() function. Adding support for new input controllers can be done within this class.
A default implementation is located at this path: Code\Game\GameDll\VehicleClient.cpp
CVehicle::Init() will perform the following tasks:
The vehicle seat class is handling all interaction involving the actors which are seated in a vehicle. Each seat can have multiple Seat Action that implements different gameplay feature applicable to the actor who used the seat.
The seat actions provide ways to extend the functionality of the seats. The IVehicleSeatAction interface is used to implement new seat actions.
CryAction provides the following seat action implementations.
Name | Class Name | Description |
---|---|---|
Lights | CVehicleSeatActionLights | Used to implements head-lights which can be turned on/off by the passenger. |
PassengerIK | CVehicleSeatActionPassengerIK | Allows IK movement from the actor to follow a pair of vehicle helpers. |
RotateTurret | CVehicleSeatActionRotateTurret | Used for turret rotation, for tanks or mounted machine gun. |
Sound | CVehicleSeatActionSound | Triggers a sound from an actions. |
SteeringWheel | CVehicleSeatActionSteeringWheel | Used to implement a steering wheel which rotates based on the movement controls. |
Weapons | CVehicleSeatActionWeapons | Used to add a vehicle weapon which are controlled by passenger. |
The vehicle seat provides a way to shield the passenger from the damages passed from the game rules. The isPassengerShielded parameter can be used to disable any direct damages sent to the passenger until the moment when the vehicle itself is destroyed. The actor implementation needs to call IVehicleSeat::ProcessPassengerDamage() every time a hit is received in order to filter the damage in case the passenger is shielded.
Any hit sent to a vehicle pass by the IVehicle::OnHit() function. Before the hit is processed by the vehicle, the classes registered as event listener with the IVehicle::RegisterVehicleEventListener() function will receive an event of type eVE_Hit.
The hit position and radius will be tested against all the Vehicle Component bounds. When this test is positive, the IVehicleComponent::OnHit() function is called to apply the hit to the component.
There is the v_goliathMode console variable which can be used in cheat mode to disable the effect of any hit, making the all vehicles invulnerable. Additionally, if the vehicle as a player driver who enabled his God Mode, the vehicle will be invulnerable as well.
The damage multipliers are used to balance different hit types to affect differently the multiple vehicle component. For example, a multiplier can be added to make a tank invulnerable to bullets by having a bullet multiplier set to 0.
Each Vehicle Components is responsible to determines if the hit will cause any damage to the vehicle. It the case that an appropriate damage multiplier has not been defined in the component, it will verify if the vehicle damages section as defined one instead.
The Damage Behavior interface is used to implement new ways a vehicle react to damages. Explosions, flat tires or a sinking boat are all example of features which are implemented as damage behaviors.
Existing damage behaviors
The following Damage Behaviors are implemented inside CryAction:
DamageBehavior | Description | Parameters |
---|---|---|
AISignal | Sends a signal to the AI system. | signalId: integer value used as the signal id. |
Destroy | Will put the vehicle in the destroyed state, making it unusable. | No parameter |
DetachPart | Detach a vehicle part | part: specify which vehicle part to detach |
Effect | Spawns a particle effect. | effect: name of the vehicle effect |
Group | Triggers a damage group | name: name of the damage group |
Impulse | Will request an impulse to be given on the vehicle. | forceMin, forceMax: specify the range in which the impulse force will be determined from a random value |
Indicator | Used to have interaction with a damage indicator, most often on the dashboard. | No Parameter |
MovementNotification | Used to send a damage notification to the Vehicle Movement | isSteering: used to limit to the steering any movement limitation coming from the damage |
Sink | Will make a boat sink in the water by modifying the buoyancy parameters of the vehicle | No parameters |
SpawnDebris | Will automatically find in the damaged vehicle assets any part which are identified as potentially detachable | No parameters |
C++ implementation
The IVehicleDamageBehavior interfaces needs to be used to implements a new damage behavior. As example, the following code sample can be used for the definition of a new damage behavior.
class CVehicleDamageBehavior
: public IVehicleDamageBehavior
{
IMPLEMENT_VEHICLEOBJECT
public:
CVehicleDamageBehavior () {}
virtual ~CVehicleDamageBehavior() {}
virtual bool Init(IVehicle* pVehicle, const SmartScriptTable &table);
virtual void Reset() {}
virtual void Release() { delete this; }
virtual void Serialize(TSerialize ser, unsigned aspects) {}
virtual void Update(const float deltaTime) {}
virtual void OnDamageEvent(EVehicleDamageBehaviorEvent event, const SVehicleDamageBehaviorEventParams& behaviorParams);
virtual void OnVehicleEvent(EVehicleEvent event, const SVehicleEventParams& params){}
virtual void GetMemoryStatistics(ICrySizer * s);
};
It is important to add the following line inside the C++ definition file:
DEFINE_VEHICLEOBJECT(CVehicleDamageBehavior);
To have the new behavior recognized by the vehicle system, it's recommended to use the REGISTER_VEHICLEOBJECT macro. This macro is defined inside CryAction/VehicleSystem_FactoryRegistration.cpp
and also GameFactory.cpp
in the GameDLL. The name string passed to this macro will then be used to identify the behavior when requesting new instances from the vehicle system.
Registering the new damage behavior
If the damage behavior needs to be requested from a XML based vehicle class, it's required to edit the vehicle definition file (Game/Scripts/Entities/def_vehicle.xml
). Locate the section similar to the following extract:
<Array name="DamageBehaviors" elementName="DamageBehavior" extendable="1" id="idDamageBehaviors">
<Property name="class" type="string">
<Enum>
<Value>AISignal</Value>
...
</Enum>
</Property>
A new enum value needs to be added using the same name string previously passed to the REGISTER_VEHICLEOBJECT.
In order to be able to pass properties from the XML vehicle class, a new table should be added inside the DamageBehaviors array definition. It's important that this table be specified as optional.