PlateCarriers

MrNewbPlateCarriers

Metadata plate carriers, modular armor plates, optional helmets, and repair stations. Built on Newb_Bridge.

Tebex · Discord · Installation · Exports · Preview

Requirements

  • Newb_Bridge
  • ox_lib
  • Inventory with per-item metadata (setMetadata)
  • ESX, QBCore, or Qbox via the bridge

ox_inventory item defs must not include server.export. Use is registered with bridge.framework.registerItemUse.

Config.Settings.RequireMetadataInventory errors on start if the bridge inventory is esx-framework, or auto with none of the known metadata inventories running.

Where you edit

configs/config.lua — one file.

KeyPurpose
Config.Utility.DebugConsole noise. Leave false live
Config.Utility.RunSelfChecksOptional boot checks. Leave false live
Config.Settings.PlayBrokenPlateSoundtrue. Frontend lock_break when equipped armor hits 0
Config.Settings.DisableVestClothingfalse. Skip component 9 / prop 0
Config.Settings.EnableOxExclusiveFeaturesfalse. ox_inventory drag-insert hook
Config.Settings.RequireMetadataInventorytrue. Boot error on esx-framework / empty auto
Config.Settings.ArmorSyncInterval500 ms vest condition sync
Config.Settings.PlateCooldown1500 ms between plate inserts
Config.Settings.ActionDistance3.0 station range
Config.Settings.DiminishingRepairsEnabled true, Percent 0.03, Minimum 0.5
Config.Settings.GatesInVehicle / Swimming / Dead / Cuffed (all true)
Config.Settings.DurationsEquip/Remove 1500, Insert 2500, Repair 4000
Config.VestItemsCarrier item names and clothing
Config.RepairPlatesModular plate item names
Config.BrokenPlateItemItem given when a removed plate is at 0 (broken_armor_plate)
Config.RepairMaterialItemField-repair item (armor_repair_material)
Config.RepairMaterialValueCondition added per material use (10)
Config.HelmetItemsHelmet item names and clothing
Config.Damage.Enabledtrue. false skips weaponDamageEvent (vest still tracks ped armor)
Config.DamageDefaultMultiplier, HeadMultiplier 1.35, LimbMultiplier 0.7, MaxLossPerHit 100, WeaponMultipliers. Head hits also apply helmet loss
Config.StationsRepair / salvage benches. Shipped empty
Config.RegisteredKeyMappingDefault key for /removevest (O)

Labels: locales/en.json. Restart after config or item changes.

Item names

Carriers (Config.VestItems):

pegasus_carrier, merryweather_carrier, fib_carrier, noose_carrier, armstrong_carrier.

Plates (Config.RepairPlates) — keep these names on upgrade; they are also the modular plate names:

pegasus_light_repair_plate, merryweather_standard_repair_plate, fib_tactical_repair_plate, noose_heavy_repair_plate, armstrong_elite_repair_plate.

Helmet, broken plate, and repair material — names already in shipped config. Add the inventory defs if you want the features. No PNGs ship for them.

ItemConfigNotes
tactical_helmetConfig.HelmetItemsShipped enabled. Empty HelmetItems to disable
broken_armor_plateConfig.BrokenPlateItemGiven when a removed plate is at 0
armor_repair_materialConfig.RepairMaterialItemField repair and the station default cost

Carrier fields

FieldPurpose
StrengthArmor cap is Strength * 10
ConditionSeed value used only when migrating a carrier that has no Plates table
SlotCountPlate slots (shipped 2)
PlateTypeFallback type check if CompatibleTypes is missing
CompatibleTypesPlate Type values this carrier accepts
DefaultPlatePlate item used to fill slots on first normalize
ResistMultiplier on incoming vest loss (1.0 = full)
Clothing{ drawable = { male, female }, texture = { male, female } }
JobsOptional { jobName = minGrade }. Omit = anyone

Shipped compatibility: Pegasus light only; Merryweather light+standard; FIB through tactical; NOOSE through heavy; Armstrong all five types.

Plate fields

FieldPurpose
RepairValueFallback max if PlateMax is missing
PlateMaxNew-plate condition / max
TypeMust appear in the carrier’s CompatibleTypes
MaterialStored on the plate (inspect / salvage flavor)
WeightAdded into carrier PlateWeight
PriorityDamage order (lower first). Ties use slot order

Helmet fields

Strength, Condition, Resist, Clothing, optional Jobs. Max condition is Strength * 10. Condition > 0 disables critical hits (SetPedSuffersCriticalHits). Head hits apply helmet loss through Resist.

Clothing component IDs

The clothing table is drawable / texture per gender, not the component index. Those IDs are hardcoded:

GearNativeIndex
CarrierSetPedComponentVariationcomponent 9 (body armor)
HelmetSetPedPropIndexprop 0 (hat)

Shipped drawables: every carrier male = 11, female = 1; tactical_helmet male = 39, female = 38. Textures are 0. Change the drawable numbers to match your clothing pack.

Config.Settings.DisableVestClothing skips both vest and helmet appearance. Freemode peds only (mp_m_freemode_01 / mp_f_freemode_01).

Metadata

SchemaVersion = 2. Older items migrate the first time they are handled. You do not need to rewrite every inventory row on install.

On normalize: SerialNumber is preserved (or generated). Strength, Clothing, SlotCount, and PlateCarrier come from the current config. A missing Plates table is filled from legacy Condition using DefaultPlate. Condition becomes the sum of plate conditions (capped at Strength * 10). description is rewritten.

Carrier (NormalizeCarrierMetadata)

{
    SchemaVersion = 2,
    PlateCarrier = true,
    SerialNumber = '...',
    Strength = 6,
    SlotCount = 2,
    Clothing = { drawable = { male = 11, female = 1 }, texture = { male = 0, female = 0 } },
    Plates = {
        [1] = {
            slot = 1,
            item = 'merryweather_standard_repair_plate',
            condition = 30,
            max = 30,
            max0 = 30,
            serial = '...',
            material = 'ceramic',
            priority = 2,
        },
    },
    PlateWeight = 700,
    Condition = 30, -- sum of plate conditions
    description = '...',
}

Loose plate (after remove / swap)

PlateCondition, PlateMax, PlateMax0, PlateSerial.

Broken plate

material, originalItem, serial.

Helmet (NormalizeHelmetMetadata)

{
    SchemaVersion = 2,
    PlateHelmet = true,
    SerialNumber = '...',
    Strength = 5,
    Condition = 50,
    MaxCondition = 50,
    Clothing = { drawable = { male = 39, female = 38 }, texture = { male = 0, female = 0 } },
    description = '...',
}

Equipped gear is stored on player metadata keys PlateCarrier and PlateHelmet as { name, metadata }.

Repair / insert / remove

Equip — use a carrier item. Progress Durations.Equip. Swapping returns the old carrier to inventory.

Insert — use a plate while wearing a compatible carrier → first empty slot. If every slot is filled, slot 1 is replaced. Use a plate with no vest equipped → menu of carriers in inventory. With EnableOxExclusiveFeatures, dragging a plate onto a carrier in ox_inventory inserts with no progress bar.

Remove plate/inspectvest or OpenPlateCarrierMenu on the equipped carrier. Condition > 0 returns the plate item; 0 returns broken_armor_plate.

Field repair — use armor_repair_material while wearing a vest. Repairs the lowest-percent plate by RepairMaterialValue. If DiminishingRepairs.Enabled, that plate’s max drops by Percent (0.03) down to max0 * Minimum (0.5).

Station repair — equipped vest only. Pays station.repairCost (default one armor_repair_material) and fills each damaged plate to its diminished max.

Station salvage — one broken_armor_platesalvageYield of armor_repair_material (default 1).

Unequip/removevest (key Config.RegisteredKeyMapping) or ForceRemovePlayerVest. Helmet: /removehelmet.

Gates (InVehicle, Swimming, Dead, Cuffed) block the progress callback when true.

Stations

Config.Stations ships empty. Uncomment and set your own coords:

['mission_row_armory'] = {
    coords = vector4(452.6, -980.0, 30.7, 90.0),
    model = `prop_tool_bench02`,
    jobs = { police = 0 },
    repairCost = { [Config.RepairMaterialItem] = 1 },
    salvageYield = 1,
    radius = 50.0,
},
FieldPurpose
coordsvector4 (heading in w)
modelBench prop (default prop_tool_bench02)
jobsOptional job → min grade. Omit = anyone
repairCostItem → count. Default { [RepairMaterialItem] = 1 }
salvageYieldMaterials per broken plate (default 1)
radiusInteraction spawn radius (default 50)

Must be within Config.Settings.ActionDistance (3.0). Recipes are validated server-side.

Optional Buckshot_Crafting JSON: [INSTALL]/crafting/README.md.

State bags

Replicated, read-only snapshots. Do not write these from another resource.

BagShape
plateCarrier{ equipped, name, condition, max, plates } or { equipped = false }
plateHelmet{ equipped, name, condition, max } or { equipped = false }

plates[slot] is { item, condition, max, material } or false for an empty slot.

Exports

Server: IsPlayerWearingVest, ForceRemovePlayerVest, IsPlayerWearingHelmet, ForceRemovePlayerHelmet, GetPlateArmorState.

Client: IsPlayerWearingVest, GetPlateCarrierState, IsPlayerWearingHelmet, GetPlateArmorState, OpenPlateCarrierMenu.

Client vest / helmet checks take no player id (local ped).

Full signatures: Server exports · Client exports.

Commands

CommandWhat it does
/removevestUnequip the carrier (also keybound, shipped O)
/removehelmetUnequip the helmet
/inspectvestRemove plates from the equipped carrier

Layout

PathRole
resource/shared/vest_helpers.luaMigration, plate condition, serial
resource/server/inventory_capability.luaMetadata-inventory boot check
resource/server/permissions.luaOptional Jobs gate
resource/server/equip_and_remove_vest.luaEquip/remove, usable carriers
resource/server/sync_vest_state.luaCondition + plateCarrier bag
resource/server/repair_plates.luaInsert / remove / field repair
resource/server/helmet.luaHelmet metadata + plateHelmet bag
resource/server/damage.luaHit classification
resource/server/stations.luaRepair / salvage callbacks
resource/server/ox_inventory.luaOptional drag-insert hook
resource/server/selfcheck.luaOptional boot asserts (RunSelfChecks)
resource/client/appearance.luaComponent 9 / prop 0
resource/client/vest.luaEquip visuals, /removevest + keybind, client vest exports
resource/client/helmet.luaHelmet events, /removehelmet, client helmet / HUD exports
resource/client/inspect_vest_menu.luaSlot inspection
resource/client/stations.luaArmor-bench interactions