Project 05: Gang encounter
In previous projects, you managed single entities: one pedestrian, one bodyguard, or one car. In Project 05, you graduate to multi-entity management. You will create an active turf encounter with three gang members who stand guard, enter alert posture when approached, open fire if the player draws a weapon, and return to calm if the player retreats.
The mission
Build a dynamic multi-actor gang encounter fulfilling six core criteria:
- Manage a squad of three gang members dynamically using a generic C#
List<Ped>. - Spawn the actors positioned in a defensive guard formation facing the player.
- Detect the player's weapon status and spatial proximity in real time.
- Trigger hostile retaliation if the player draws a weapon within 8 meters, or enters close quarters within 4 meters unarmed.
- Implement physical return to calm: if the player retreats beyond 18 meters, clear combat tasks and resume the guard posture.
- Prune stale entity handles automatically and guarantee clean deletion on script reload or manual reset.
Specifications, constraints
- Collection hygiene: Prune invalid, dead, or culled handles on every tick using
List.RemoveAllto prevent stale reference crashes. - Accurate weapon detection: Check both
player.IsArmed(WeaponCheckFlags.All)andplayer.Weapons.Current.Hash != WeaponHash.Unarmedto distinguish lethal weapons from bare hands or mobile phones. - Physical return to calm: Changing an internal state variable is not enough; you must explicitly call
member.Task.ClearAll()and restart the"WORLD_HUMAN_GUARD_STAND"scenario. - Behavioral isolation: Set
member.BlockPermanentEvents = trueon every member so ambient game panics do not override your scripted logic. - Zero entity leakage: Wipe all entities in
ClearGang()upon unload or manual reset.
Implementation steps
- Declare collection storage: Define a
private readonly List<Ped> _gangMembers = new List<Ped>();in your script class. - Wire lifecycle events: In the constructor, attach event handlers to
Tick,Aborted, andKeyDown. - Prune stale references: In
OnTick, first callCleanInvalidRefs()to remove null or non-existent entity handles from the list. - Populate initial squad: If
_gangMembers.Count == 0, invokeSpawnGang(). - Evaluate player threat: Check if the player is currently wielding an active lethal weapon.
- Iterate squad members: Loop over each member in the list:
- Ensure
BlockPermanentEventsis locked. - If the member is dead, skip execution.
- Compute distance to the player using
player.Position.DistanceTo(member.Position). - If armed within 8 meters or within 4 meters unarmed, command
member.Task.Combat(player). - If distance exceeds 18 meters and the member is fighting, clear tasks and call
member.Task.StartScenarioInPlace("WORLD_HUMAN_GUARD_STAND", 0, false).
- Ensure
- Build squad spawning: In
SpawnGang, loop 3 times, calculate lateral offsets withplayer.RightVector, equip firearms, assign the guard scenario, and add each instance to_gangMembers. - Build teardown and reset: In
ClearGang, loop through all members, callDelete(), and clear the list. BindKeys.NumPad9to clear and respawn, and callClearGanginOnAborted.
APIs, tools to explore
System.Collections.Generic.List<Ped>: Standard dynamic collection for tracking variable numbers of entities.List<T>.RemoveAll(Predicate<T> match): Prunes all elements matching a given condition in place.Ped.IsArmed(WeaponCheckFlags flags): Native check determining if a pedestrian is holding a weapon.Ped.Task.StartScenarioInPlace(string scenarioName, int unkDelay, bool playIntroClip): Orders an entity to play an ambient behavioral scenario.Ped.Task.ClearAll(): Immediately cancels all active and queued task orders.Vector3.DistanceTo(Vector3 target): Calculates Euclidean 3D distance between two points in world space.
Validation checklist
Your mod is validated when:
- Approaching unarmed to 10 meters: The gang stands in formation watching without opening fire.
- Drawing a firearm at 7 meters: All three gang members draw their pistols and open fire immediately.
- Approaching to 3 meters unarmed: The gang perceives an imminent threat and opens fire.
- Retreating past 18 meters: Gunfire stops, the gang clears combat tasks, and members resume their guard scenario.
- Returning unarmed to 10 meters: The gang remains in guard posture and does not shoot without a new trigger.
- Pressing
NumPad 9or reloading withInsert: The entire gang is cleanly deleted without leaving corpses behind.
Solution, explanations
Partner
Verified solution and code explanations
The mission, specifications, and guided steps remain 100% free and open for everyone. The complete verified reference code and production explanations are reserved for Partner members.