Skip to content

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
    → ItemMeleeAsset

ItemWeaponAsset 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 (getState returns { 1 } for any EItemOrigin).
  • 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

FieldType.dat KeyDefaultDescription
_weakfloatWeak0.5Damage multiplier for weak/slash attacks. Applied multiplicatively on top of the base weapon damage from ItemWeaponAsset
weakAttackQuestRewardsNPCRewardsListWeak_Attack_Quest_Rewards / Weak_Attack_Quest_Reward_NEmptyQuest 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

FieldType.dat KeyDefaultDescription
_strongfloatStrong0.33Damage multiplier for strong/stab attacks
_staminabyteStamina0Stamina cost of performing a strong attack. The player must have at least this much stamina to perform the attack
_strengthfloatStrength0UI-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
strongAttackQuestRewardsNPCRewardsListStrong_Attack_Quest_Rewards / Strong_Attack_Quest_Reward_NEmptyQuest 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 (strength and stamina) 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:

  1. The player performs a normal attack on a damaged InteractableBarricade or InteractableStructure.
  2. UseableMelee detects the Repair flag and checks if the target is damaged (health < maxHealth).
  3. The weapon's base damage value is converted to a repair amount: repairAmount = baseDamage * _weak (or _strong if strong attack).
  4. The repair is applied as negative damage: DamageTool.damage(repairAmount * -1, ...).
  5. 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:

FieldTypeDescription
isLightboolTrue if the Light key exists in the .dat
lightConfigPlayerSpotLightConfigParsed 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

FieldTypeSourceDescription
_useAudioClipBundle "Use" or .dat "AttackAudioClip"Sound played on each swing/stab
impactAudioAudioReference.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:

  1. Strong attack strength modifier display (if not 1.0 and not isRepeated).
  2. Strong attack stamina cost display (if > 0).
  3. Call to BuildNonExplosiveDescription (inherited from ItemWeaponAsset) 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: Swing and Stab animations on the equipped GameObject.
  • Repeated weapons: Repeated loop animation.
  • Light-equipped weapons: Light_On and Light_Off animations 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
      → ItemTireAsset

Audio

FieldSourceDescription
_useBundle "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:

  1. Admin override: If byAdmin is true, always return true. Admins can use any tool in any safezone.
  2. Carjack exception: If the tool's useableType == typeof(UseableCarjack), return true. This allows flipping vehicles in safezones without violating safezone weapon restrictions.
  3. Default: Fall through to ItemAsset.canBeUsedInSafezone, which checks safezone.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:

  1. Player clicks → ESwingMode is set (Swing or Stab).
  2. An animation is played with configurable speed.
  3. On the attack's impact frame (determined by an animation event), a raycast is performed.
  4. RaycastInfo captures the hit point, collider, and entity.
  5. Damage is computed using the weapon's damage multipliers and the hit entity's limb multiplier.
  6. DamageTool.damage(...) applies the damage with flags for bleeding, bones, and ragdoll force.
  7. Impact audio is played at the hit point.
  8. Quest rewards are granted if applicable.
  9. Quality degrades based on use.

Repair flow:

  1. If the target is a damaged barricade/structure and the weapon has isRepair = true.
  2. A positive repair value is computed from the weapon damage.
  3. DamageTool.damage(repairValue * -1) is called to add health.
  4. Quality still degrades (repairs are not free).

Repeated attack flow:

  1. While the button is held, a coroutine loops the "Repeated" animation.
  2. Damage is applied at intervals matching the animation loop.
  3. Stamina drains continuously.

UseableCarjack (ItemToolAsset)

Vehicle flipping tool:

  1. Player faces a vehicle within interaction range.
  2. A raycast detects the vehicle's rigidbody.
  3. An upward force is applied at the player's position, scaled by carjackForceMultiplier from the vehicle's VehicleAsset (default 1.0) and the player's skill level.
  4. The vehicle's angular velocity is adjusted to encourage it to roll onto its wheels.
  5. The tool's quality degrades based on use.

UseableCarlockpick (ItemToolAsset)

Vehicle lock picking:

  1. Player faces a locked vehicle door.
  2. A brief minigame plays (timing-based; not shown in current UI).
  3. Success: the vehicle unlocks.
  4. Failure: quality degrades, lock remains.
  5. The ItemToolAsset class provides no special lockpick fields — the behavior is entirely in the Useable class.

UseableVehicleBattery (ItemToolAsset)

Battery installation/removal:

  1. Player faces a vehicle's battery slot.
  2. If no battery is installed and the player holds a battery item, install it. The battery item's state tracks its charge level.
  3. If a battery is installed and the player has an empty hand, remove the battery into inventory.
  4. The ItemToolAsset fields are not used — the interaction is driven by VehicleAsset.battery fields.

UseableTire (ItemTireAsset)

Tire add/remove:

  1. Player faces a vehicle wheel hub.
  2. ADD mode: If the hub is empty, place a tire. The tire item is consumed.
  3. 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).
  4. Safezone restrictions apply per mode (ADD allowed, REMOVE blocked).

UseableFuel (ItemToolAsset)

While not itself an ItemToolAsset (it's a separate ItemFuelAsset), the fueling useable:

  1. Player faces a vehicle fuel port.
  2. Fuel is transferred from the can to the vehicle (or vice versa with empty cans).
  3. Transfer rate is per-tick with configurable speed.
  4. The fuel can's state tracks remaining fuel.

UseableVehiclePaint (ItemToolAsset)

Vehicle painting:

  1. Player faces a vehicle with paint-supporting sections.
  2. The paint item defines a color.
  3. The color is applied to PaintableVehicleSection entries.
  4. Paint is directional — the player can choose which side of the vehicle to paint by their approach angle.

UseableWalkieTalkie (ItemToolAsset)

Voice chat relay:

  1. While equipped, the walkie-talkie relays voice chat over a longer distance.
  2. shouldFriendlySentryTargetUser returns false — sentries don't react to walkie-talkies.
  3. No special asset fields — behavior is entirely in the Useable class.

Field Comparison: Melee vs Tool

PropertyItemMeleeAssetItemToolAsset
Base classItemWeaponAssetItemAsset
Damage tableInherited (player/zombie/animal multiplier)None
Attack modesWeak (slash) / Strong (stab) / RepeatedNone
Stamina cost_stamina per strong attackNone
Repair capability_isRepair flagNone
Light source_isLight + lightConfigNone
Alert radiusDefault 8, configurable up to any valueNone
Impact audioimpactAudio with per-surface supportOnly _use activation sound
Quest rewardsPer-attack-type system (weakAttackQuestRewards, strongAttackQuestRewards)None
Safezone overrideDefault (blocked in weapon-restricted safezones)Allow carjacks + admin override
Sentry targetingshouldFriendlySentryTargetUser = truePer-useable (walkie = false, tire REMOVE = true)
Quality displayshowQuality = trueNot shown
State size0 or 1 byteInherited from base
Cargo dataNone beyond baseNone 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 equipped

For ItemMeleeAsset, the useableType is set to typeof(UseableMelee) during the ItemAsset base population. For ItemToolAsset, the type varies:

ItemUseable Class
Generic ItemToolAssetDepends on itemName / legacy mapping: UseableCarjack, UseableCarlockpick, UseableWalkieTalkie, UseableVehicleBattery, UseableVehiclePaint
ItemTireAssetUseableTire
ItemVehicleRepairToolAssetDepends 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:

  1. Raycast origin: The player's camera position.
  2. Raycast direction: The camera's forward vector.
  3. Range: The weapon's range field (inherited from ItemWeaponAsset).
  4. Target layers: Physics layers for entities (players, zombies, animals) and objects (barricades, structures, resources, vehicles).
  5. Hit validation: The first RaycastHit within range is evaluated.
  6. Entity detection: If the hit collider belongs to a Player, Zombie, Animal, or InteractableVehicle, the corresponding damage multiplier is used.
  7. Barricade/structure interaction: If the weapon has isRepair = true and the target is an InteractableBarricade or InteractableStructure with damage, repair is applied instead of damage.
  8. Impact effects: The impactAudio is 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:

  • Swing animation: OnSwingStart + OnSwingHit events.
  • Stab animation: OnStabStart + OnStabHit events.
  • Repeated animation: OnRepeatedHit event 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:

  1. Detection: After a successful hit raycast, check isRepair on the melee asset.
  2. Damage check: If the target is at full health, apply normal damage instead.
  3. Repair calculation: repairAmount = Mathf.Abs(effectiveDamage). The sign is inverted for DamageTool.damage().
  4. Quality effect: Repair effectiveness scales with the weapon's current quality (lower quality = less repair).
  5. 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 TypeAsset IdentificationBehavior
UseableCarjackLegacy ID-based mappingVehicle flip force
UseableCarlockpickLegacy ID-based mappingLock picking minigame
UseableWalkieTalkieLegacy ID-based mappingExtended voice range
UseableVehicleBatteryLegacy ID-based mappingBattery install/remove
UseableVehiclePaintLegacy ID-based mappingVehicle paint application
UseableTire (via ItemTireAsset)SubclassTire 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

PropertyItemMeleeAssetItemToolAsset
Range sourceItemWeaponAsset.rangeItemAsset.range (default 5)
Typical range2-5m (knife: 2m, bat: 3m, axe: 3.5m)3-6m (carjack: 4m, tire: 3m)
Hit detectionCamera raycast + limb-specific damageCamera raycast + specialized interaction

Common Issues

  1. Missing Swing animation — Non-repeated melee weapons without a Swing animation will fail to play the attack on the client. The asset validation logs a warning via ValidateEquipableHasAnimation.
  2. Repair damage sign — The repair mechanic inverts the damage value. A weapon with playerDamageMultiplier.damage = 10 will repair 10 health per hit. This can surprise modders who expect separate repair and damage values.
  3. Tire mode switchingItemTireAsset mode is immutable once the asset is loaded. A single tire item cannot both add and remove tires — separate assets are needed.
  4. Repeated weapons ignore strong attack — Setting _strength and _stamina on a repeated weapon has no effect on gameplay, though the fields still exist in memory. The description explicitly skips them when _isRepeated is true.
  5. 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.
  6. Carjack physics inconsistency — The force applied by UseableCarjack depends on the vehicle's Rigidbody.mass. Heavier vehicles require more attempts. The carjackForceMultiplier in VehicleAsset can compensate per-vehicle.
  7. Useable type mapping — The legacy ID-to-useable mapping is fragile. If a mod adds a new ItemToolAsset with an ID that coincidentally matches a vanilla tool's mapping, the useable type may be incorrect. Modern mods should use the useableType key explicitly in their .dat.
  8. Walkie-talkie safezone — The canBeUsedInSafezone logic 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.AddForce for physics flip.
  • Lockpick: No damage dealt — modifies vehicle lock state.
  • Tire REMOVE: Applies damage to the tire via DamageTool.damage with 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:

  • UseableCarjack decreases quality by 1 per use.
  • UseableCarlockpick decreases quality on failed attempts.
  • UseableTire (REMOVE mode) decreases quality by 1 per tire removal.
  • UseableVehicleBattery and UseableWalkieTalkie do 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:

  1. Client: Sends a MeleeAttack RPC with swing mode and timestamp.
  2. Server: Validates the attack (range check, line of sight, cooldown check). Applies damage.
  3. Broadcast: Server broadcasts the attack result (hit or miss, damage values, effects).
  4. 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 TypePlayer Damage (body)Zombie Damage (body)Animal Damage (body)
Weak (slash)40 × 0.5 × 0.8 = 1640 × 0.5 × 0.6 = 1240 × 0.5 × 0.6 = 12
Strong (stab)40 × 0.33 × 0.8 = 10.5640 × 0.33 × 0.6 = 7.9240 × 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:

  1. Load the item's .dat file.
  2. Determine the useableType:
    • If the .dat contains a useableType key, use that.
    • Otherwise, look up the item's legacy ID in the built-in mapping table.
  3. Set ItemAsset.useableType to the resolved type.
  4. The Useable instance 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.