FriendlyGate
Module: friendlygate.lua
Overview
The FriendlyGate module manages the behavior of gates that open based on proximity to friendly or allied vehicles. It checks for nearby valid candidates (hero or faction-vehicles) and opens if any are present and not locked, with attitude-gated conditions for the player. The gate also has a far-edge re-check at 40m.
Inheritance
- Inherits from: none — base/utility module
- Imports:
MrxFactionManager(attitude tests + faction abbreviations),MrxUtil(GetFaction),MrxVoSequence(the guard’s “gate opening” voice line)
Instance pattern
Not the Inheritable/rich-instance pattern, and not a class-factory either — confirmed from source: a plain module-level table, _tGates[uGateGuid], with no Create/Delete/setmetatable anywhere. There’s also a module-level Init()/Deinit() pair (both empty here) and SaveSingleton/LoadSingleton for persisting the lock table, alongside the per-gate OnActivate. Each activated gate gets a sub-table entry in _tGates, not a full instance object with inherited methods. It tracks the following key fields:
_tLockedGates: A table to store locked gate GUIDs._tGates: A table to manage gate-specific data, including proximity events, attitude change events, candidate vehicles, and filter settings.
Functions
Init()
Empty in this file — no module setup happens here.
Deinit()
Empty in this file — no teardown happens here.
LockGate(uGateGuid, bLock)
Sets or clears a gate’s lock state in _tLockedGates. If the gate is already registered, it evaluates candidates again.
IsGateLocked(uGateGuid)
Checks if a gate is locked by looking up its GUID in _tLockedGates.
OnActivate(uGateGuid)
Called when the gate instance is activated. It sets up an event to call Start once the object leaves hibernation.
Start(uGateGuid)
Initializes the gate’s behavior, including setting lights and creating proximity and attitude change events. It also registers death events for specific parts of the gate.
OnDeath(uGateGuid, uNodeGuid)
Handles the gate’s death by calling OnDeactivate.
OnDeactivate(uGateGuid)
Cleans up all events and data associated with the gate when it is deactivated.
CreateProxEvent(uFilter, uGateGuid)
Creates a proximity event for the gate to detect nearby vehicles within 20m.
_EvaluateCandidates(uGateGuid, bApproaching, vObjects)
Evaluates candidate vehicles approaching or leaving the gate’s proximity. It updates the list of candidates and opens/closes the gate based on conditions.
_RemoveCandidate(uGateGuid, uGuid)
Removes a vehicle from the list of candidates by deleting associated events.
_ChangeState(uGateGuid, bOpen)
Changes the open state of the gate, playing a voice-over if it opens for the first time and updating lights accordingly.
_TestAttitude(sGateFaction, uPlayerCharGuid)
Tests the attitude between the gate’s faction and the player character to determine if the gate should open. Uses MrxFactionManager.GetPerceivedFaction/GetFactionAbbrev and MrxFactionManager.TestAttitude(..., ">=", sTargetAttitude). The threshold is "Friendly" normally, but relaxes to "Neutral" when the character reads as PMC (and additionally requires MrxFactionManager.IsAttitudeMutable(sGateFactionAbbrev)) — so a PMC player only needs the gate faction to be neutral-or-better, not friendly.
SaveSingleton()
Returns _tLockedGates so the engine can persist which gates are locked across save/load. Only the lock table is saved — live proximity/candidate state in _tGates is rebuilt on activation.
LoadSingleton(tLockedGates)
Restores _tLockedGates from a saved table (if one is passed). This is why a locked gate stays locked after loading a save.
Events
- Creates
Event.ObjectHibernation(OnActivate) to callStartwhen the gate leaves hibernation. - Creates the near
Event.ObjectProximity(CreateProxEvent): fires when a filter-matching object comes within< 20m, calling_EvaluateCandidates(uGateGuid, true). - Creates a per-candidate far
Event.ObjectProximity(> 40m) so a candidate that drives away is re-evaluated, plus a per-candidateEvent.ObjectDeathso killed candidates are dropped. - Creates two
Event.ObjectHealthlisteners (< 1health on nodespiece1a_propattach00andpiece1a_propattach01) so destroying either gate arm callsOnDeath→OnDeactivate. - Creates a one-shot
Event.TimerRelative{2}inStartto set the initial light state. - Creates a persistent attitude-change event via
MrxFactionManager.CreatePersistentAttitudeChangeEvent({sFactionAbbrev, "Pmc"}, _EvaluateCandidates, ...)so the gate re-evaluates when PMC’s standing with the gate’s faction changes (this is aMrxFactionManagerwrapper, not a rawEvent.*constant). OnActivate/OnDeactivate/OnDeathare engine lifecycle callbacks, notEvent.*subscriptions.
Module constants & tunables
- Proximity radii: open trigger
< 20m (near), re-check trigger> 40m (far) — both inline literals inCreateProxEvent/_EvaluateCandidates. - Object filter:
"Hero||(" .. sFaction .. "&&Vehicle)"— the gate opens for the hero, or for a vehicle of the gate’s own faction (built withObjectFilter.Create/SetFilter). - Destructible gate-arm nodes:
"piece1a_propattach00"and"piece1a_propattach01"(health< 1kills the gate). - Vehicle parts toggled for lights:
"LightFront"(green/open) and"LightBrake"(red/closed). - Attitude threshold:
">= Friendly"for most factions, relaxed to">= Neutral"for PMC (see_TestAttitude). - Guard voice lines on first open (
_ChangeState), by gate faction:Allied"AlliedSoldier01.Misc.GateYes01",China"ChinaSoldier01.Misc.GateYes01",Guerilla"GurSoldier01.Misc.GateYes01",OC"OCSoldier01.Misc.GateYes01",VZ"GurSoldier01.Misc.GateYes01"— played at priorityMrxVoSequence.knPriorityFreeplayon the nearest living soldier found within25m viaPg.FastCollectHumans.
The module-level
local tFactions = {"VZ", "Allied", "China", "Guerilla", "OC", "Pirate", "PMC", "Civ"}declared at the top of the file is dead — it is never read anywhere infriendlygate.lua. (An earlier version of this page told modders to edit a non-existent_tFactionstable; there is no_tFactions, and the realtFactionslocal does nothing.)
Notes for modders
- Use
LockGate(uGateGuid, bLock)to force a gate closed regardless of who is near — the lock state persists across saves (SaveSingleton/LoadSingleton). - Tune who opens the gate by editing the filter string (
"Hero||(faction&&Vehicle)") or the attitude logic in_TestAttitude; tune when by changing the20m/40m proximity radii. - Attitude re-evaluation is driven through
MrxFactionManager— changing PMC’s standing with the gate faction at runtime will open/close eligible gates automatically. - The
tFactionslocal at the top of the file is dead code (see note above) — do not rely on or edit it.