ItemMeleeAsset and ItemToolAsset
Overview
ItemMeleeAsset and ItemToolAsset define two categories of non-ranged hand-held items. Melee weapons deal direct damage with slash/stab mechanics and optional utility (repair, light source). Tool assets provide item-to-world interactions like carjacking, lockpicking, and tire removal. They share the ItemWeaponAsset and ItemAsset foundations respectively but diverge entirely in their useable behavior.
ItemMeleeAsset
ItemMeleeAsset extends ItemWeaponAsset and defines close-quarters combat weapons: knives, bats, axes, swords, blowtorches, chainsaws, and similar.
Inheritance Chain
ItemAsset
→ ItemWeaponAsset
→ ItemMeleeAssetItemWeaponAsset provides the full damage multiplier infrastructure: playerDamageMultiplier, zombieDamageMultiplier, animalDamageMultiplier, each with limb-specific multipliers (skull, spine, arm, leg). These are applied by the UseableMelee class when the weapon connects with an entity.
State Layout
Melee weapon state depends on whether the weapon has a light source:
- Light melee (e.g., flashlight-melee hybrids): 1 byte, interact state (
getStatereturns{ 1 }for anyEItemOrigin). - Non-light melee: 0 bytes, empty array.
The interact state byte toggles the light on/off. When set to 1, the light component on the equipped prefab is enabled. When set to 0, the light is disabled. The state is toggled by the player pressing the interact key while the weapon is equipped.
Attack System
Melee weapons have two attack modes: weak (left-click slash) and strong (right-click stab). The UseableMelee class manages these via the ESwingMode enum.
Weak Attack Parameters
| Field | Type | .dat Key | Default | Description |
|---|---|---|---|---|
_weak | float | Weak | 0.5 | Damage multiplier for weak/slash attacks. Applied multiplicatively on top of the base weapon damage from ItemWeaponAsset |
weakAttackQuestRewards | NPCRewardsList | Weak_Attack_Quest_Rewards / Weak_Attack_Quest_Reward_N | Empty | Quest rewards granted on each successful weak attack hit |
The weak attack plays the "Swing" animation and performs a raycast forward from the player's camera. If the raycast hits an entity within range, damage is computed as baseDamage * _weak * limbMultiplier and applied through DamageTool.
Strong Attack Parameters
| Field | Type | .dat Key | Default | Description |
|---|---|---|---|---|
_strong | float | Strong | 0.33 | Damage multiplier for strong/stab attacks |
_stamina | byte | Stamina | 0 | Stamina cost of performing a strong attack. The player must have at least this much stamina to perform the attack |
_strength | float | Strength | 0 | UI-facing modifier label for strong attack damage. Displayed as "Strong Attack Modifier" in the tooltip. Not directly used in damage calculation — the _strong field is used instead |
strongAttackQuestRewards | NPCRewardsList | Strong_Attack_Quest_Rewards / Strong_Attack_Quest_Reward_N | Empty | Quest rewards granted on each successful strong attack hit |
The strong attack plays the "Stab" animation and uses a different attack motion. The damage formula is baseDamage * _strong * limbMultiplier. The stamina cost prevents spamming strong attacks.
Repeated Attack Mode
_isRepeated (Repeated key) marks weapons that use a continuous attack loop instead of separate weak/strong swings. This mode is designed for blowtorches and chainsaws where the attack animation loops while the button is held.
When isRepeated is true:
- The "Swing" and "Stab" animations are replaced by a "Repeated" loop animation.
- Strong attack fields (
strengthandstamina) are not displayed in the description UI. - The weapon deals continuous damage while the attack button is held, at intervals determined by the animation loop.
- Stamina drain is continuous rather than per-attack.
Repair System
_isRepair (Repair key) enables the melee weapon to repair barricades and structures instead of damaging them. The repair mechanic works as follows:
- The player performs a normal attack on a damaged
InteractableBarricadeorInteractableStructure. UseableMeleedetects theRepairflag and checks if the target is damaged (health < maxHealth).- The weapon's base damage value is converted to a repair amount:
repairAmount = baseDamage * _weak(or_strongif strong attack). - The repair is applied as negative damage:
DamageTool.damage(repairAmount * -1, ...). - The weapon's quality degrades from use, reducing repair effectiveness over time.
When isRepair is true but the target is at full health, the weapon deals damage normally (it can be used both as a weapon and as a repair tool).
Light Source
_isLight (Light key) enables a PlayerSpotLightConfig that attaches a spotlight to the player when the weapon is equipped:
| Field | Type | Description |
|---|---|---|
isLight | bool | True if the Light key exists in the .dat |
lightConfig | PlayerSpotLightConfig | Parsed from .dat during PopulateAsset. Configures light range, intensity, color, angle, and falloff |
The light toggles on/off via the interact key, cycling between state 0 (off) and state 1 (on). The PlayerSpotLightConfig is the same configuration class used by tactical flashlight attachments, ensuring consistent light behavior across melee and gun-mounted lights.
Audio
| Field | Type | Source | Description |
|---|---|---|---|
_use | AudioClip | Bundle "Use" or .dat "AttackAudioClip" | Sound played on each swing/stab |
impactAudio | AudioReference | .dat "ImpactAudioDef" | Sound played when the weapon connects with a surface or entity |
The impactAudio uses a .asset audio reference loaded via ReadAudioReference, which supports per-surface impact sounds (flesh, metal, wood, concrete).
Alert Radius
alertRadius (default 8) controls how far away the melee swing noise alerts zombies and NPCs. This is significantly shorter than the gun's default 48. The radius is set via the Alert_Radius .dat key. Zombies within this radius transition from idle to alert state and investigate the sound's origin.
Quest Rewards Integration
Both weak and strong attacks have independent NPCRewardsList fields. This allows quests that require specific attack types:
weakAttackQuestRewards— Granted each time a weak attack lands.strongAttackQuestRewards— Granted each time a strong attack lands.
The NPCRewardsList parser uses prefix-based .dat keys (Weak_Attack_Quest_Reward_N / Strong_Attack_Quest_Reward_N) and supports all standard NPC reward types: experience, items, flags, teleports, and more.
Description UI
BuildDescription performs:
- Strong attack
strengthmodifier display (if not 1.0 and notisRepeated). - Strong attack
staminacost display (if > 0). - Call to
BuildNonExplosiveDescription(inherited fromItemWeaponAsset) which renders:- Range in meters.
- Player damage per limb (head, body, arm, leg) with the weapon's
playerDamageMultiplier. - Zombie damage per body part with
zombieDamageMultiplier. - Animal damage per body part with
animalDamageMultiplier. - Bleeding and bones modifiers.
- Durability/quality indicator.
Asset Validation
ItemMeleeAsset requires the equipped prefab to have animations matching the attack configuration:
- Non-repeated weapons:
SwingandStabanimations on the equipped GameObject. - Repeated weapons:
Repeatedloop animation. - Light-equipped weapons:
Light_OnandLight_Offanimations for toggling the light.
The ValidateEquipableHasAnimation method (inherited from ItemWeaponAsset) checks these at asset load time and logs errors to the Unity console.
ItemToolAsset
ItemToolAsset is a lightweight base for utility items that perform non-combat interactions. It extends ItemAsset directly and provides minimal shared infrastructure — most of its behavior comes from the associated Useable implementation.
Inheritance Chain
ItemAsset
→ ItemToolAsset
→ ItemVehicleRepairToolAsset
→ ItemTireAssetAudio
| Field | Source | Description |
|---|---|---|
_use | Bundle "Use" or .dat "UseAudioClip" | Sound played when the tool is activated |
The _use AudioClip is loaded after the base PopulateAsset call, using LoadRedirectableAsset for cross-bundle asset resolution.
Safezone Behavior
The canBeUsedInSafezone override provides two-tier safezone logic:
- Admin override: If
byAdminis true, always return true. Admins can use any tool in any safezone. - Carjack exception: If the tool's
useableType == typeof(UseableCarjack), return true. This allows flipping vehicles in safezones without violating safezone weapon restrictions. - Default: Fall through to
ItemAsset.canBeUsedInSafezone, which checkssafezone.allowsItems.
This override was updated in 2025 to also affect sentry targeting (public issue #5175).
Sentry Targeting
The shouldFriendlySentryTargetUser property returns false for UseableWalkieTalkie items because walkie-talkies are communication devices, not weapons. All other tool types default to the base class behavior which returns true.
Useable Implementations
The corresponding Useable classes drive the runtime behavior for each tool:
UseableMelee (ItemMeleeAsset)
The UseableMelee class is the runtime driver for melee combat:
Attack flow:
- Player clicks →
ESwingModeis set (Swing or Stab). - An animation is played with configurable speed.
- On the attack's impact frame (determined by an animation event), a raycast is performed.
RaycastInfocaptures the hit point, collider, and entity.- Damage is computed using the weapon's damage multipliers and the hit entity's limb multiplier.
DamageTool.damage(...)applies the damage with flags for bleeding, bones, and ragdoll force.- Impact audio is played at the hit point.
- Quest rewards are granted if applicable.
- Quality degrades based on use.
Repair flow:
- If the target is a damaged barricade/structure and the weapon has
isRepair = true. - A positive repair value is computed from the weapon damage.
DamageTool.damage(repairValue * -1)is called to add health.- Quality still degrades (repairs are not free).
Repeated attack flow:
- While the button is held, a coroutine loops the "Repeated" animation.
- Damage is applied at intervals matching the animation loop.
- Stamina drains continuously.
UseableCarjack (ItemToolAsset)
Vehicle flipping tool:
- Player faces a vehicle within interaction range.
- A raycast detects the vehicle's rigidbody.
- An upward force is applied at the player's position, scaled by
carjackForceMultiplierfrom the vehicle'sVehicleAsset(default 1.0) and the player's skill level. - The vehicle's angular velocity is adjusted to encourage it to roll onto its wheels.
- The tool's quality degrades based on use.
UseableCarlockpick (ItemToolAsset)
Vehicle lock picking:
- Player faces a locked vehicle door.
- A brief minigame plays (timing-based; not shown in current UI).
- Success: the vehicle unlocks.
- Failure: quality degrades, lock remains.
- The
ItemToolAssetclass provides no special lockpick fields — the behavior is entirely in the Useable class.
UseableVehicleBattery (ItemToolAsset)
Battery installation/removal:
- Player faces a vehicle's battery slot.
- If no battery is installed and the player holds a battery item, install it. The battery item's state tracks its charge level.
- If a battery is installed and the player has an empty hand, remove the battery into inventory.
- The
ItemToolAssetfields are not used — the interaction is driven byVehicleAsset.batteryfields.
UseableTire (ItemTireAsset)
Tire add/remove:
- Player faces a vehicle wheel hub.
- ADD mode: If the hub is empty, place a tire. The tire item is consumed.
- REMOVE mode: If the hub has a tire, destroy it. The tire item is not consumed (the tool is a socket wrench, not a consumable).
- Safezone restrictions apply per mode (ADD allowed, REMOVE blocked).
UseableFuel (ItemToolAsset)
While not itself an ItemToolAsset (it's a separate ItemFuelAsset), the fueling useable:
- Player faces a vehicle fuel port.
- Fuel is transferred from the can to the vehicle (or vice versa with empty cans).
- Transfer rate is per-tick with configurable speed.
- The fuel can's state tracks remaining fuel.
UseableVehiclePaint (ItemToolAsset)
Vehicle painting:
- Player faces a vehicle with paint-supporting sections.
- The paint item defines a color.
- The color is applied to
PaintableVehicleSectionentries. - Paint is directional — the player can choose which side of the vehicle to paint by their approach angle.
UseableWalkieTalkie (ItemToolAsset)
Voice chat relay:
- While equipped, the walkie-talkie relays voice chat over a longer distance.
shouldFriendlySentryTargetUserreturnsfalse— sentries don't react to walkie-talkies.- No special asset fields — behavior is entirely in the Useable class.
Field Comparison: Melee vs Tool
| Property | ItemMeleeAsset | ItemToolAsset |
|---|---|---|
| Base class | ItemWeaponAsset | ItemAsset |
| Damage table | Inherited (player/zombie/animal multiplier) | None |
| Attack modes | Weak (slash) / Strong (stab) / Repeated | None |
| Stamina cost | _stamina per strong attack | None |
| Repair capability | _isRepair flag | None |
| Light source | _isLight + lightConfig | None |
| Alert radius | Default 8, configurable up to any value | None |
| Impact audio | impactAudio with per-surface support | Only _use activation sound |
| Quest rewards | Per-attack-type system (weakAttackQuestRewards, strongAttackQuestRewards) | None |
| Safezone override | Default (blocked in weapon-restricted safezones) | Allow carjacks + admin override |
| Sentry targeting | shouldFriendlySentryTargetUser = true | Per-useable (walkie = false, tire REMOVE = true) |
| Quality display | showQuality = true | Not shown |
| State size | 0 or 1 byte | Inherited from base |
| Cargo data | None beyond base | None beyond base |
The Useable Class Resolution
The mapping from ItemAsset to Useable class happens during item registration:
ItemAsset → useableType (System.Type) → instantiated as Useable when equippedFor ItemMeleeAsset, the useableType is set to typeof(UseableMelee) during the ItemAsset base population. For ItemToolAsset, the type varies:
| Item | Useable Class |
|---|---|
Generic ItemToolAsset | Depends on itemName / legacy mapping: UseableCarjack, UseableCarlockpick, UseableWalkieTalkie, UseableVehicleBattery, UseableVehiclePaint |
ItemTireAsset | UseableTire |
ItemVehicleRepairToolAsset | Depends on subclass |
The mapping is historically driven by the item's legacy ID range rather than by asset class, though modern mods can override useableType in their .dat.
Cargo Data Export
ItemMeleeAsset inherits BuildCargoData from ItemWeaponAsset and does not add custom tables beyond the weapon's base damage table. ItemToolAsset inherits from ItemAsset and likewise adds no custom tables. The subclass ItemTireAsset exports minimal data through inherited tables.
Damage Multiplier System
Both ItemMeleeAsset (via ItemWeaponAsset) and ItemToolAsset (indirectly) use the damage multiplier struct system. The key structs are:
PlayerDamageMultiplier
csharp
public class PlayerDamageMultiplier : IDamageMultiplier
{
public float damage; // Base damage
public float skull; // Headshot multiplier (default 1.1 for melee)
public float spine; // Body multiplier (default 0.8 for melee)
public float arm; // Arm multiplier (default 0.6 for melee)
public float leg; // Leg multiplier (default 0.6 for melee)
}ZombieDamageMultiplier
csharp
public class ZombieDamageMultiplier : IDamageMultiplier
{
public float damage; // Base damage
public float skull; // Headshot multiplier (default 1.1 for melee)
public float spine; // Body multiplier (default 0.6 for melee)
public float arm; // Arm multiplier (default 0.3 for melee)
public float leg; // Leg multiplier (default 0.3 for melee)
}AnimalDamageMultiplier
csharp
public class AnimalDamageMultiplier : IDamageMultiplier
{
public float damage; // Base damage
public float skull; // Headshot multiplier (default 1.1 for melee)
public float spine; // Body multiplier (default 0.6 for melee)
public float leg; // Leg multiplier (default 0.3 for melee)
}The melee's _weak and _strong fields multiply these base damages: effectiveDamage = baseDamage * _weak * limbMultiplier.
Standing Multiplier Values vs ItemToolAsset
Melee weapons have access to all three damage multiplier sets (player, zombie, animal) with per-limb scaling. ItemToolAsset by contrast has no damage system — tools deal damage through the Useable implementation directly (e.g., UseableCarjack applies force, not damage).
UseableMelee: Attack Raycasting
The UseableMelee class performs the actual hit detection during melee attacks:
- Raycast origin: The player's camera position.
- Raycast direction: The camera's forward vector.
- Range: The weapon's
rangefield (inherited fromItemWeaponAsset). - Target layers: Physics layers for entities (players, zombies, animals) and objects (barricades, structures, resources, vehicles).
- Hit validation: The first
RaycastHitwithin range is evaluated. - Entity detection: If the hit collider belongs to a
Player,Zombie,Animal, orInteractableVehicle, the corresponding damage multiplier is used. - Barricade/structure interaction: If the weapon has
isRepair = trueand the target is anInteractableBarricadeorInteractableStructurewith damage, repair is applied instead of damage. - Impact effects: The
impactAudiois played at the hit point. Blood/damage effects are spawned based on the hit surface type.
Animation Events
The melee attack uses animation events to synchronize hit detection with the visual swing:
Swinganimation:OnSwingStart+OnSwingHitevents.Stabanimation:OnStabStart+OnStabHitevents.Repeatedanimation:OnRepeatedHitevent at each loop cycle.
The hit event triggers the raycast. This ensures the visual and gameplay damage are synchronized.
Repair System Detail
The repair system in UseableMelee:
- Detection: After a successful hit raycast, check
isRepairon the melee asset. - Damage check: If the target is at full health, apply normal damage instead.
- Repair calculation:
repairAmount = Mathf.Abs(effectiveDamage). The sign is inverted forDamageTool.damage(). - Quality effect: Repair effectiveness scales with the weapon's current quality (lower quality = less repair).
- Network: The repair is performed on the server. If the client predicts a repair that the server rejects, the client's prediction is rolled back.
ItemToolAsset Subclass Ecosystem
Beyond the documented subclasses, ItemToolAsset types are identified by their useableType:
| Useable Type | Asset Identification | Behavior |
|---|---|---|
UseableCarjack | Legacy ID-based mapping | Vehicle flip force |
UseableCarlockpick | Legacy ID-based mapping | Lock picking minigame |
UseableWalkieTalkie | Legacy ID-based mapping | Extended voice range |
UseableVehicleBattery | Legacy ID-based mapping | Battery install/remove |
UseableVehiclePaint | Legacy ID-based mapping | Vehicle paint application |
UseableTire (via ItemTireAsset) | Subclass | Tire add/remove |
The legacy ID mapping is a hand-maintained table in the Assets class that maps specific item IDs to their useable types. This predates the modern asset system and is gradually being replaced as items are migrated to explicit useableType declarations in their .dat files.
Melee vs Tool: Interaction Range
| Property | ItemMeleeAsset | ItemToolAsset |
|---|---|---|
| Range source | ItemWeaponAsset.range | ItemAsset.range (default 5) |
| Typical range | 2-5m (knife: 2m, bat: 3m, axe: 3.5m) | 3-6m (carjack: 4m, tire: 3m) |
| Hit detection | Camera raycast + limb-specific damage | Camera raycast + specialized interaction |
Common Issues
- Missing
Swinganimation — Non-repeated melee weapons without aSwinganimation will fail to play the attack on the client. The asset validation logs a warning viaValidateEquipableHasAnimation. - Repair damage sign — The repair mechanic inverts the damage value. A weapon with
playerDamageMultiplier.damage = 10will repair 10 health per hit. This can surprise modders who expect separate repair and damage values. - Tire mode switching —
ItemTireAssetmode is immutable once the asset is loaded. A single tire item cannot both add and remove tires — separate assets are needed. - Repeated weapons ignore strong attack — Setting
_strengthand_staminaon a repeated weapon has no effect on gameplay, though the fields still exist in memory. The description explicitly skips them when_isRepeatedis true. - Light toggle state persistence — The 1-byte state is saved and loaded. Light state is preserved across server restarts, which may not be desirable for disposable melee weapons like torches.
- Carjack physics inconsistency — The force applied by
UseableCarjackdepends on the vehicle'sRigidbody.mass. Heavier vehicles require more attempts. ThecarjackForceMultiplierinVehicleAssetcan compensate per-vehicle. - Useable type mapping — The legacy ID-to-useable mapping is fragile. If a mod adds a new
ItemToolAssetwith an ID that coincidentally matches a vanilla tool's mapping, the useable type may be incorrect. Modern mods should use theuseableTypekey explicitly in their.dat. - Walkie-talkie safezone — The
canBeUsedInSafezonelogic permits carjack use by non-admins but does not give the same exception to walkie-talkies. Walkie-talkies are blocked in weapon-prohibited safezones.
DamageTool Integration
Both melee and tool assets ultimately use DamageTool for applying effects:
Melee Damage Application
csharp
DamageTool.damage(new DamagePlayerParameters(...)
{
// The damage value comes from:
// baseDamage * attackMultiplier * limbMultiplier * qualityMultiplier
damage = weapon.playerDamageMultiplier.damage * attackMultiplier * limbMultiplier,
// Optional:
bleedingModifier = weapon.bleedingModifier,
bonesModifier = weapon.bonesModifier,
ragdollForce = weapon.ragdollForce,
// From the raycast hit:
point = hitPoint,
normal = hitNormal,
collider = hitCollider,
// Tracking:
killer = player,
// etc.
});Tool Interaction Damage
Tool interactions use DamageTool differently:
- Carjack: No damage dealt — uses
Rigidbody.AddForcefor physics flip. - Lockpick: No damage dealt — modifies vehicle lock state.
- Tire REMOVE: Applies damage to the tire via
DamageTool.damagewith vehicle tire damage flag.
Melee Weapon Quality Degradation
The ItemMeleeAsset defines showQuality => true which enables the quality bar in the inventory UI. Quality degrades on each successful hit:
csharp
// Quality decrease per hit (from game mode config or default 1)
float qualityLoss = Provider.modeConfigData.Items.Melee_Quality_Loss;
weapon.quality -= qualityLoss;At 0% quality:
- Damage is reduced to 50% of base.
- Repair effectiveness is reduced to 50%.
- The weapon can still be used but is significantly less effective.
- Quality can be restored using repair benches and relevant materials.
Tool Asset Durability
ItemToolAsset does not set showQuality => true, so tool quality is not displayed in the inventory UI by default. However:
UseableCarjackdecreases quality by 1 per use.UseableCarlockpickdecreases quality on failed attempts.UseableTire(REMOVE mode) decreases quality by 1 per tire removal.UseableVehicleBatteryandUseableWalkieTalkiedo not degrade quality.- Quality still affects tool interactions even though not displayed — tools at 0% quality have reduced effectiveness.
Network Synchronization
Melee attacks are synchronized via the Steam networking layer:
- Client: Sends a
MeleeAttackRPC with swing mode and timestamp. - Server: Validates the attack (range check, line of sight, cooldown check). Applies damage.
- Broadcast: Server broadcasts the attack result (hit or miss, damage values, effects).
- Client prediction: Clients predict the hit locally and reconcile with server result.
Tool interactions follow a similar pattern but may use different RPC types depending on the operation (carjack uses CarjackVehicle, tire uses TireAdd/TireRemove).
Damage Multiplier Tables for Melee
Default values per attack type:
| Attack Type | Player Damage (body) | Zombie Damage (body) | Animal Damage (body) |
|---|---|---|---|
| Weak (slash) | 40 × 0.5 × 0.8 = 16 | 40 × 0.5 × 0.6 = 12 | 40 × 0.5 × 0.6 = 12 |
| Strong (stab) | 40 × 0.33 × 0.8 = 10.56 | 40 × 0.33 × 0.6 = 7.92 | 40 × 0.33 × 0.6 = 7.92 |
Note: These are the defaults. Each melee weapon can override playerDamageMultiplier, zombieDamageMultiplier, animalDamageMultiplier, _weak, and _strong independently.
Tool Asset Category Registration
ItemToolAsset types are registered during Assets.load by matching item IDs to a hardcoded table. The registration process:
- Load the item's
.datfile. - Determine the
useableType:- If the
.datcontains auseableTypekey, use that. - Otherwise, look up the item's legacy ID in the built-in mapping table.
- If the
- Set
ItemAsset.useableTypeto the resolved type. - The
Useableinstance is created when the player equips the item.
Modern items should always specify useableType in their .dat to avoid relying on the fragile legacy mapping.
