CityRP Documentation Repository

Vehicle Emergency Lighting (ELS)

Last updated

Civilian-installable emergency lighting is handled by the Vehicles plugin (core/plugins/vehicles/sh_init.lua / sv_init.lua). A player uses one of four items on a vehicle they own, and the plugin swaps in a Photon lighting preset for that model.

Groups

Constant Item (uniqueID) Photon flag Gate
POLICE veh_pwl CityRP_IsPoliceELS LEO pass/orange, Presidential pass/red, IsLawenforcement(), IsPresident(), or IsRescue() (ERT)
WARNING veh_awl CityRP_IsAmbers None (amber warning lights)
ARROWS veh_arrows CityRP_IsArrowboard None (amber + directional arrowboard)
MEDICAL veh_mwl CityRP_IsMedicalELS IsDoctor() or IsRescue() (ERT; covers Paramedic and Fire Chief)

Gates live in onVehicleLightsUsed in sv_init.lua. Each item's onUse just calls onVehicleLightsUsed(ply, <GROUP>). The Photon flag column is the field a preset sets to claim the group for itself — see Self-registering from a Photon file.

carLighting — model to Photon preset

carLighting[string.lower(model)][GROUP] maps a vehicle model to the name a Photon preset was registered under (list.Set("Vehicles", name, V) — the key, which is conventionally also V.Name). onVehicleLightsUsed looks the preset up with list.Get("Vehicles")[loadout] and merges it onto the vehicle's VehicleTable.

Most entries are hand-written at the top of sh_init.lua:

carLighting["models/metrohd/audi_a6.mdl"] = {"AudiA6_RB", "AudiA6_AW"}
-- array-style: index 1 = POLICE, 2 = WARNING, 3 = ARROWS (matches the constants below)
carLighting["models/tdmcars/trucks/gmc_c5500.mdl"] = {[WARNING] = "GMCC5500_AW"}
-- or explicit group keys when a model only supports some groups

Self-registering from a Photon file

A Photon vehicle registration (an addons/vehicles_emvu/lua/autorun/*.lua file, or any other list.Set("Vehicles", name, V) call) can set its group's flag from the Groups table to claim itself as that group's preset, instead of requiring a hand-written carLighting entry:

local V = {
	Name = name,
	Model = "models/metrohd/audi_a6.mdl",
	-- ...
	CityRP_IsPoliceELS = true,
}
list.Set("Vehicles", V.Name, V)

mergeSelfRegisteredLighting() (in sh_init.lua, runs once from the CityRP.Core.PostItemLoad hook) scans every registered Photon vehicle and fills in any carLighting[model][group] slot that isn't already set. A hand-written entry always wins — self-registration only fills gaps, it never overwrites a hand-authored mapping.

Either kind of clash is dropped instead of silently picking one, and logged via PLUGIN.logger:Warning(...) (cityrp.logging, namespace plugin.Vehicles; see logging.md) so it shows up in console/DB without being confused for an audit event:

  • A self-registered preset tries to claim a group another self-registered preset already claimed for that model.
  • A self-registered preset tries to claim a group a hand-written carLighting entry already set for that model.

Use self-registration for new Photon presets going forward — it keeps the "which vehicle supports which lighting" fact next to the preset that answers it, instead of requiring a second edit in sh_init.lua that's easy to forget. The hand-written table isn't being migrated off; it stays for existing entries and as an override when you need one preset for a model to win over another's self-registration.