Skip to main content

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:

  1. Manage a squad of three gang members dynamically using a generic C# List<Ped>.
  2. Spawn the actors positioned in a defensive guard formation facing the player.
  3. Detect the player's weapon status and spatial proximity in real time.
  4. Trigger hostile retaliation if the player draws a weapon within 8 meters, or enters close quarters within 4 meters unarmed.
  5. Implement physical return to calm: if the player retreats beyond 18 meters, clear combat tasks and resume the guard posture.
  6. 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.RemoveAll to prevent stale reference crashes.
  • Accurate weapon detection: Check both player.IsArmed(WeaponCheckFlags.All) and player.Weapons.Current.Hash != WeaponHash.Unarmed to 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 = true on 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

  1. Declare collection storage: Define a private readonly List<Ped> _gangMembers = new List<Ped>(); in your script class.
  2. Wire lifecycle events: In the constructor, attach event handlers to Tick, Aborted, and KeyDown.
  3. Prune stale references: In OnTick, first call CleanInvalidRefs() to remove null or non-existent entity handles from the list.
  4. Populate initial squad: If _gangMembers.Count == 0, invoke SpawnGang().
  5. Evaluate player threat: Check if the player is currently wielding an active lethal weapon.
  6. Iterate squad members: Loop over each member in the list:
    • Ensure BlockPermanentEvents is 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).
  7. Build squad spawning: In SpawnGang, loop 3 times, calculate lateral offsets with player.RightVector, equip firearms, assign the guard scenario, and add each instance to _gangMembers.
  8. Build teardown and reset: In ClearGang, loop through all members, call Delete(), and clear the list. Bind Keys.NumPad9 to clear and respawn, and call ClearGang in OnAborted.

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 9 or reloading with Insert: 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.