> For the complete documentation index, see [llms.txt](https://5scripts-1.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://5scripts-1.gitbook.io/docs/assets/5s_zombies/editable.md).

# Editable

These files are not encrypted and can be freely modified. They are located in the `client/editable/` and `server/editable/` folders.

## Client Side

### `client/editable/events.lua`

#### `onZombieSpawned(entity, type, networkId)`

Called when a zombie is fully spawned and initialized. Use this to add custom logic like attaching props, setting blip colors by type, or triggering events.

* `entity` - the ped handle
* `type` - zombie type name from `Config.types` (e.g., `"default"`, `"screamer"`, `"trainer"`)
* `networkId` - the network ID of the ped

```lua
function onZombieSpawned(entity, type, networkId)
    -- Example: print spawn info
    print("Spawned " .. type .. " zombie with net ID " .. networkId)
end
```

#### `isDead(source)`

Returns whether a player is dead. Used internally to skip dead players during spawn checks. Override this if your death system uses a different state.

```lua
function isDead(source)
    return Player(source).state.isDead
end
```

#### No-Spawn Zone System

Coordinate-based spawn prevention. Unlike safe zones (which block spawns based on player enter/exit), no-spawn zones prevent zombies from spawning **at specific coordinates** regardless of player location.

Other scripts can register and unregister zones via exports:

```lua
exports['5s_zombies']:addNoSpawnZone("myresource:zone_1", coords, 30.0)
exports['5s_zombies']:removeNoSpawnZone("myresource:zone_1")
```

#### `canSpawnZombieAtCoords(coords)`

Called before spawning a zombie at the given coordinates. Return `true` to allow, `false` to deny. Each denial increases the spawn radius by `Config.distances.spawnRadiusIncrement` (default 5m).

You can add custom logic here beyond the no-spawn zone system:

```lua
function canSpawnZombieAtCoords(coords)
    for _, zone in pairs(noSpawnZones) do
        if #(coords - zone.coords) < zone.radius then
            return false
        end
    end
    -- Add your own checks here
    return true
end
```

#### `isInSafeZone(coords)`

Returns whether a position is inside a safe zone, so no zombie spawns there. Covers the `Config.zones.safeZones` list — extend it to add your own safe areas (a placed prop, a job/territory zone, etc.).

```lua
function isInSafeZone(coords)
    for _, zone in ipairs(Config.zones.safeZones) do
        if #(coords - zone.coords) <= (zone.zoneRadius or 0.0) then
            return true
        end
    end

    -- Example: also treat the area around a custom prop as safe
    -- local obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 20.0, GetHashKey("model_totem"), false, false, false)
    -- if obj ~= 0 then return true end

    return false
end
```

#### `isPlayerCrouched(playerPed)`

Returns whether a player is crouched/sneaking, so zombies hear their footsteps from closer (`Config.detectionDistances.crouchMultiplier`). The default covers GTA's built-in stealth mode — point it at your crouch resource's state if you use one (this also works for other players).

```lua
function isPlayerCrouched(playerPed)
    local stealth = GetPedStealthMovement(playerPed)
    return stealth == true or stealth == 1
end
```

#### `applyZombieDamageToPlayer(amount)`

Applies a zombie's melee hit to the local player. Runs on the player's own client. Override it to deal the damage through your own health system instead.

* `amount` - damage to apply

```lua
function applyZombieDamageToPlayer(amount)
    ApplyDamageToPed(cache.ped, amount, Config.customMelee.applyToArmorFirst == true)
end
```

#### `applyZombieDamageToVehicle(vehicle, hit)`

Applies a zombie's melee hit to the vehicle the local player is in/on. Runs on the player's own client. Override it to deal the damage through your own vehicle system instead.

* `vehicle` - the vehicle entity
* `hit` - damage components, any may be absent: `body`, `engine`, `deform`, `smashWindow`

```lua
function applyZombieDamageToVehicle(vehicle, hit)
    if (hit.body or 0) > 0 then
        SetVehicleBodyHealth(vehicle, math.max(0.0, GetVehicleBodyHealth(vehicle) - hit.body))
    end
    if (hit.deform or 0) > 0 then
        SetVehicleDamage(vehicle, hit.ox or 0.0, hit.oy or 0.0, hit.oz or 0.0,
            hit.deform + 0.0, (Config.customMelee.attackVehicles.deformRadius or 1.5) + 0.0, false)
    end
    if (hit.engine or 0) > 0 then
        SetVehicleEngineHealth(vehicle, math.max(-4000.0, GetVehicleEngineHealth(vehicle) - hit.engine))
    end
    if hit.smashWindow ~= nil then
        SmashVehicleWindow(vehicle, hit.smashWindow)
    end
end
```

***

### `client/editable/zones.lua`

Zone entry/exit callbacks. Use any notification system you want (ox\_lib, esx, qb, okokNotify, etc.). The zone object is passed as a parameter so you can access its properties (coords, radius, blip settings, etc.).

```lua
function onEnterSafeZone(zone)
    fs.utils.notify(locale("enter_safe_zone"), "success")
end

function onLeaveSafeZone(zone)
    fs.utils.notify(locale("leave_safe_zone"), "error")
end

function onSafeZoneGraceEnd()
    fs.utils.notify(locale("safe_zone_grace_end"), "error")
end

function onEnterDangerZone(zone)
    -- Triggered when player enters a danger zone
end

function onLeaveDangerZone(zone)
    -- Triggered when player leaves a danger zone
end
```

***

### `client/editable/target.lua`

#### `getLootDuration()`

Returns the loot duration in milliseconds for the local player. Override this to integrate with your XP / progression system.

```lua
function getLootDuration()
    return Config.lootDuration
    -- Examples:
    --   return Config.lootDuration - exports.my_skills:GetLootSpeedBonus()
    --   return Config.lootDuration * (1 - exports.my_xp:GetPlayerLevel() * 0.05)
end
```

#### `createTarget(entity, lootId)`

Sets up the loot interaction on a dropped loot object. Supports `ox_target` and `qb-target` based on `Config.targetResource`. Override this if you use a different target system.

```lua
function createTarget(entity, lootId)
    if Config.targetResource == "qb-target" then
        exports["qb-target"]:AddTargetEntity(entity, {
            options = {
                {
                    name = "loot_" .. lootId,
                    label = locale("pickup_loot"),
                    icon = "fa-solid fa-hands-holding",
                    action = function()
                        lootZombie(lootId)
                    end,
                },
            },
            distance = 2.5,
        })
    else
        exports.ox_target:addLocalEntity(entity, {
            name = "loot_" .. lootId,
            label = locale("pickup_loot"),
            icon = "fa-solid fa-hands-holding",
            onSelect = function()
                lootZombie(lootId)
            end,
        })
    end
end
```

***

### `client/editable/jacking.lua`

Controls whether zombies can pull players out of vehicles. When `Config.enableJacking` is `false`, this file prevents the player from being dragged out.

```lua
if not Config.enableJacking then
    lib.onCache('ped', function(value)
        SetPedCanBeDraggedOut(value, false)
        SetPedStayInVehicleWhenJacked(value, true)
    end)
end
```

Set `Config.enableJacking = true` in your config to allow zombies to pull players from vehicles.

***

## Server Side

### `server/editable/handlers.lua`

#### `onZombieKilled(source, pedData, networkId, coords)`

Called when a player kills a zombie. Use this for custom rewards like XP, money, kill counters, or achievements.

* `source` - player server ID who killed the zombie
* `pedData` - the zombie's type config table from `Config.types` (includes health, speed, lootTable, abilities, etc.)
* `networkId` - network ID of the zombie ped
* `coords` - `vector3` position where the zombie died

```lua
function onZombieKilled(source, pedData, networkId, coords)
    -- Example: give money for killing a tank
    if pedData.health >= 500 then
        fs.framework.addMoney(source, 100)
    end

    -- Example: custom kill counter
    -- exports['myxp']:addXP(source, 10)
end
```

***

### `server/editable/inventory.lua`

#### `addItem(source, itemName, count)`

Called when loot is added to a player's inventory. Override this if you use an inventory system that is not supported by `5s_lib`.

```lua
function addItem(source, itemName, count)
    fs.inventory.addItem(source, itemName, count)
end
```

**Custom inventory example:**

```lua
function addItem(source, itemName, count)
    exports['my-inventory']:AddItem(source, itemName, count)
end
```

#### `playerTryTriggerSecuredEvent(src)`

Anti-cheat punishment hook, called when a player sends a tampered network event. It only fires for payloads a legitimate client can never produce — laggy players can't end up here. Default action is to kick the player; override it to log, ban, or report to your anti-cheat instead.

```lua
function playerTryTriggerSecuredEvent(src)
    DropPlayer(src, "Nice try")
end
```
