Vehicle Destruction
So, you've just spent a few weeks of your life pouring countless hours into a beautiful vehicle mod. Why not destroy it?
This tutorial will explain how destruction of lights, windows, and detachment of body parts works. This will let you add destruction of regular body parts to vanilla cars that don't have it, like the Caliburn, or make custom parts destructible.
Theory
This entire tutorial will use the Caliburn as an example, but the steps should be adaptable to any other vanilla vehicle.
TweakDB

gridCell
The settings for the destruction or detachment of parts are governed by the TweakDB. The gridCells tell the game the rough placement of your component so that when that area of the car receives damage, the component will be affected. I don't really know how gridCells work exactly and how they're placed, but I understand them enough to make use of them. By looking through the TweakDB entries under the destruction dropdown, we'll find out which part of the car each gridCell relates to.

For example, the above screenshot shows the gridCells for the brake_light_left_01. This tells us that gridCell 0 is at the left rear corner of the car. brake_light_right_01 uses gridCell 1, which, presumably, is the right rear corner of the car.

A component can also be influenced by two gridCells. Here, the license_plate is influenced by gridCell 0 and gridCell 1. Since the license plate is placed at the rear centre of the car, we can assume that two gridCells means the game extrapolates the middle distance between them to affect components placed there. This also lets us figure out where the other gridCells are placed.

The front bumper uses gridCell 6 and gridCell 7. The bumper is placed in the front centre of the car, so this probably means that those gridCells are placed at its left and right front corners. By going through the other components, the full picture becomes a bit more clear. The front left mirror uses gridCell 4, while the front right mirror uses gridCell 5. The left door uses gridCell 2 and gridCell 4, while the right door uses gridCell 3 and gridCell 5. This means the layout of gridCells probably looks something like this:
6 ┌──front──┐ 7
4 │ │ 5
2 │ │ 3
0 └──rear───┘ 1component
components are identified by their name in the .app file. For glass and lights, only one component can be destroyed per TweakDB entry. detachableParts however can detach multiple parts, as is the case for the front bumper for example. There, both the bumper mesh itself and its shadow mesh are detached.
threshhold
components will be destroyed or detached after a certain threshhold of damage is reached. This treshhold is stored in Bits. 0.1 will not work, but 0.0999984741 will.
effect
The effect used for the destruction of windows (glass shards falling down) is referenced in the TweakDB, but set up in the root .ent. These work the same way as the effects for the exhaust or the smoke effects when the vehicle is damaged. If your vehicle doesn't already have glass breaking effects—as is the case for the Caliburn—you can copy-paste them from another vehicle that does, for example the Porsche. More on that later.
.app File
Since detachableParts will fly off when detached, they need to be controlled by the physics of the game. So, for a detachablePart to detach correctly, it needs to be an entPhysicalMeshComponent within the .app file of your vehicle. When flying off, the mesh will rotate around its origin. Therefore, the pivot point of your .mesh file should be placed at world origin (position x: 0, y: 0, z: 0 in Blender). It'll then be moved to its proper position on the vehicle via the localTransform array in the .app file. This is basically the same as placing the bumpers or doors on a car, but instead of the .rig file, the values are transferred from Blender into the .app file. Windows also need to be entPhysicalMeshComponents to receive damage and break properly. These just disappear when broken and don't need to be placed using the localTransform array.
.mesh File
As mentioned above, detachableParts and breakable windows need physics. These physics are influenced by the collisionShapes under the parameters dropdown inside of each .mesh file. For body parts, this affects the acceleration and speed at which the part flies off, depending on how much mass it has, and its rough shape. For windows, the collisionShape effectively means the hitbox, e.g. the area you need to hit when shooting the window with a gun for it to break. You can copy-paste the entire meshMeshParamPhysics entry from similar vanilla .mesh files into the ones of your vehicle. The collisionShapes for body parts should roughly match, but windows should be pretty accurate.
Practice
Windows
.mesh File
Find a donor
.meshfile for the hitbox of the windows of your vehicle as outlined above. The shape and position should match as closely as possible.Right click on it and choose "Open without adding to project"
Open the
parametersdropdown. You should see aphysicsDataentry of the typemeshMeshParamPhysics. Right click it and select "Copy from Array/Buffer".Open the
parametersdropdown inside the.meshfile of your car's window and delete any entries that might already be there.Right click the
parametersdropdown and select "Paste Into Array/Buffer".
.app File
Start by deleting window
componentsof your car that aren'tentPhysicalMeshComponents. We'll need to replace those.Open an
.appfile of a vanilla vehicle, and copy-paste all theentPhysicalMeshComponentsfor windows that are required for your car. Duplicate them, if necessary.change the
mesh DepotPathandmeshAppearanceto match your.meshfile, and, if necessary edit theParentTransform, reset theChunkMask, and generate a newCRUID. Thenamecan be arbitrary, we'll reference it in the.yamlfile later.
.ent File
Open the root
.entfile of a vanilla car with breakable windows. We'll use the Porsche in this example.Navigate to
components > entSlotComponent FX_slots > slots.Select all of the effects you need, right click them and select "Copy from Array/Buffer"
Open the root
.entfile of your vehicle and also navigate tocomponents > entSlotComponent FX_slots > slots. The name of theentSlotComponentmight be different. TheentSlotComponentfor the effects might also be in the.appfile, as is the case for the Type 66 Avenger, for example.Right click the
slotsarray and select "Paste Into Array/Buffer".Go back to the root
.entfile of your donor car (the Porsche) and navigate tocomponents > entEffectSpawnerComponent cars_sports_fx > effectDescs.select the
entEffectDescsthat match theentSlotComponentswe've copied earlier. Copy-paste them into theentEffectSpawnerComponentinside the root.entfile of your vehicle similarly as we've done before.
.yaml File
Add a new TweakDB entry for destruction of a window in the .yaml file of your vehicle. You can copy-paste this one and adapt it to your vehicle:
Vehicle.yv_lamborghini_murcielago_dest_window_left_secondary:
$base: Vehicle.VehicleDestructionParamsCaliburn_inline14
broken: None
component: window_fl_b
effect: damage_glass_fl_a
isWindshield: False
threshold: 0.100000001
gridCells:
- 2
- 4The name of the TweakDB entry can be arbitrary and is set as
Vehicle.yv_lamborghini_murcielago_dest_window_left_secondaryhere. We'll reference it later.The
$basehas been taken from the Caliburn as seen in the screenshots above.I'm not sure what
brokendoes. It might load an alternative appearance orcomponentbut I haven't looked into it. If you know more about it, please add the info here!componentis the name of theentPhysicalMeshComponentof your window in the.appfileeffectis the name of theentEffectDescfor theentEffectSpawnerComponententry in the root.entfile.I'm not too sure about
isWindshieldeither, but I believe it causes the window to crack before it shatters (as seen on V's car during the Scav chase after The Rescue)threshholdandgridCellswere explained above. Thethreshholdshould be very low because it's glass. ThegridCellshere are the centre of the left side of the car.
Add the new TweakDB entry to your vehicle:
Vehicle.yv_lamborghini_murcielago_black_glossy:
$base: Vehicle.v_sport1_rayfield_caliburn_player
displayName: yv_lamborghini_murcielago_black_glossy_local
appearanceName: yv_lamborghini_murcielago_black_glossy
destroyedAppearance: yv_lamborghini_murcielago_burnt
destruction:
$base: Vehicle.VehicleDestructionParamsCaliburn
glass:
- !append Vehicle.yv_lamborghini_murcielago_dest_window_left_secondary
…Your window should now break semi-correctly, depending on how accurate its hitbox is.
Body Parts
.mesh File
This works pretty much the same as it did for the windows as outlined above.
As mentioned before, the shape of the donor
.meshfile doesn't need to match as closely for body parts as for windows. The closer the better though, especially size and position.Inside the
parametersarray, you might also findmeshMeshParamDeformableShapesData. As the name suggests, theseparametershold information about the deformation of the.meshfile when damaged. You probably don't need them, so feel free to delete them.Select the pivot point of your Object when correctly positioned on the vehicle in Blender and copy-paste its X, Y, and Z values into the
positionsarray under thelocalTransformarray inside the.appfile of your vehicle.Move the pivot point of the Object to world origin, export it to
.glband import it into your.meshfile
.app File
Works very similar to windows, except for the
localTransformarray, as outlined in the previous steps.
.yaml file
Start by adding a new TweakDB entry to the .yaml file of your vehicle. You can copy-paste the following and adapt it to your car:
Vehicle.yv_lamborghini_murcielago_dest_spoiler:
$base: Vehicle.VehicleDestructionParamsCaliburn_inline19
name: Spoiler
threshold: 0.5
components:
- spoiler
- spoiler_shadow
gridCells:
- 0
- 1The name of the TweakDB entry can be arbitrary and is set as
Vehicle.yv_lamborghini_murcielago_dest_spoilerhere. We'll reference it later.The
$basehas been taken from the Caliburn as seen in the screenshots above.I'm unsure about the
name, I think it's just the name of the rule inside of the TweakDB? The other entries for the Caliburn are capitalised, too so I did the same here.threshholdhas been explained above.components:lists all theentPhysicalMeshComponentsinside of your.appfile that should detach for this entry.gridCellswere explained above. ThegridCellschosen here are the rear centre of the car.
Add the new TweakDB entry to your vehicle:
Vehicle.yv_lamborghini_murcielago_black_glossy:
$base: Vehicle.v_sport1_rayfield_caliburn_player
displayName: yv_lamborghini_murcielago_black_glossy_local
appearanceName: yv_lamborghini_murcielago_black_glossy
destroyedAppearance: yv_lamborghini_murcielago_burnt
destruction:
$base: Vehicle.VehicleDestructionParamsCaliburn
detachableParts:
- !append Vehicle.yv_lamborghini_murcielago_dest_spoiler
…Your body part should now detach when hitting the rear centre of the vehicle.
Lights
.app File
Exterior lights on vanilla vehicles usually already have destruction enabled for the vehicleLightComponents themselves. If you need more light components and you duplicate a pre-existing one, it'll lose it's "connection" to it's TweakDB entry once renamed and won't break anymore. This is most likely the reason why custom light components on your vehicle don't break. Adding a new TweakDB entry will be explained in the next step. However, should you duplicate for example an interior light, which is not destructible by default, you also need to make sure isDestructible is set to True and destructionEffect is defined for the vehicleLightComponent in your .app file.
.yaml File
Start by adding a new TweakDB entry to the .yaml file of your vehicle. You can copy-paste the following and adapt it to your car:
Vehicle.yv_lamborghini_murcielago_dest_taillight_left:
$base: Vehicle.VehicleDestructionParamsCaliburn_inline8
component: position_light_left_03
threshold: 0.100000001
gridCells:
- 0The name of the TweakDB entry can be arbitrary and is set as
Vehicle.yv_lamborghini_murcielago_dest_taillight_lefthere.The
$basehas been taken from the Caliburn.componentis the name of thevehicleLightComponentof your light in the.appfilethreshholdandgridCellswere explained above. Thethreshholdshould be very low here as well. ThegridCellsused for this light is the left rear corner of the vehicle.
Add the new TweakDB entry to your vehicle:
Vehicle.yv_lamborghini_murcielago_black_glossy:
$base: Vehicle.v_sport1_rayfield_caliburn_player
displayName: yv_lamborghini_murcielago_black_glossy_local
appearanceName: yv_lamborghini_murcielago_black_glossy
destroyedAppearance: yv_lamborghini_murcielago_burnt
destruction:
$base: Vehicle.VehicleDestructionParamsCaliburn
lights:
- !append Vehicle.yv_lamborghini_murcielago_dest_taillight_left
…Your light now breaks when hitting the left rear corner of the vehicle.
Final .yaml
And, for completeness sake, this is how the .yaml looks with all the TweakDB entries:
Vehicle.yv_lamborghini_murcielago_dest_window_left_secondary:
$base: Vehicle.VehicleDestructionParamsCaliburn_inline14
broken: None
component: window_fl_b
effect: damage_glass_fl_a
isWindshield: False
threshold: 0.100000001
gridCells:
- 2
- 4
Vehicle.yv_lamborghini_murcielago_dest_spoiler:
$base: Vehicle.VehicleDestructionParamsCaliburn_inline19
name: Spoiler
threshold: 0.5
components:
- spoiler
- spoiler_shadow
gridCells:
- 0
- 1
Vehicle.yv_lamborghini_murcielago_dest_taillight_left:
$base: Vehicle.VehicleDestructionParamsCaliburn_inline8
component: position_light_left_03
threshold: 0.100000001
gridCells:
- 0
Vehicle.yv_lamborghini_murcielago_black_glossy:
$base: Vehicle.v_sport1_rayfield_caliburn_player
displayName: yv_lamborghini_murcielago_black_glossy_local
appearanceName: yv_lamborghini_murcielago_black_glossy
destroyedAppearance: yv_lamborghini_murcielago_burnt
destruction:
$base: Vehicle.VehicleDestructionParamsCaliburn
glass:
- !append Vehicle.yv_lamborghini_murcielago_dest_window_left_secondary
detachableParts:
- !append Vehicle.yv_lamborghini_murcielago_dest_spoiler
lights:
- !append Vehicle.yv_lamborghini_murcielago_dest_taillight_left
…Last updated