Flow Helpers
Reusable encounter flow tools extracted from wc_encounter: cleanup bags, proximity watchers, prompt watchers, and mission markers that clean up their own GPS route.
Creates a cleanup collector for prompts, blips, GPS routes, peds, vehicles, objects, and custom callbacks.
| Method | Description |
|---|---|
AddPed(ped) | Queue a ped for safe deletion. |
AddVehicle(vehicle) | Queue a vehicle for safe deletion. |
AddObject(object) | Queue an object or prop for deletion. |
AddPrompt(prompt) | Hide and delete a native prompt. |
AddBlip(markerOrBlip) | Clear a mission marker or raw blip. |
AddGPS() | Clear the active GPS route. |
AddCustom(fn) | Run custom cleanup code. |
Clean() | Runs cleanup once. |
Cleans a common encounter table shape: prompt, prompt2, blip, propBlips, bearTrap, sackOnWagon, peds, vehicles, and objects.
Entries in the vehicles list are checked with GetEntityType so that horse peds stored there are deleted correctly with DeletePed rather than DeleteVehicle. See also CreateEntityBlip for attaching a tracking blip to any entity before adding it to the cleanup bag.
Shows a prompt while the player is near a target, hides it when they leave, and runs a callback once the prompt completes.
| Option | Type | Description |
|---|---|---|
timeoutMs | number | Optional timeout. |
guard | function | Return false to stop watching. |
cancelWhenPlayerDead | boolean | Stops when the local player dies. |
onEnter / onLeave | function | Optional range transition callbacks. |
onCancel | function | Receives timeout, stopped, or canceled. |
Runs once when the player enters the target radius. The target may be an entity, vector3, or table with x/y/z.
Runs once when the player moves outside the target radius.
Creates a blip and returns a marker handle. Pass { route = true } to also set GPS.
Removes a mission marker or raw blip. If the marker owns a GPS route, the route is cleared too.
Encounter pattern
local ev = {
peds = { npcPed },
prompt = wc:CreatePrompt("Talk [G]"),
blip = wc:CreateMissionMarker(x, y, z, "Encounter", { route = true }),
}
wc:WatchPrompt(ev.prompt, npcPed, 3.5, function()
-- start dialogue or reward flow here
end, {
timeoutMs = 30000,
guard = function() return activeEncounter == ev end,
})
wc:CleanupEncounter(ev)Real Wild County example — stagecoach job state flow
wc_stagecoach uses WatchPlayerNear to detect arrival at the destination and a cleanup bag to tear down the whole mission in one call, whether it ends in success or the player disconnects mid-run.
local bag = wc:CreateCleanupBag()
bag:AddBlip(wc:CreateMissionMarker(dest.x, dest.y, dest.z, "Delivery Point", { route = true }))
bag:AddGPS()
wc:WatchPlayerNear(dest, 5.0, function()
bag:Clean()
TriggerServerEvent('wc_stagecoach:missionComplete')
end, {
timeoutMs = 600000, -- 10 minute run limit
onCancel = function(reason)
if reason == 'timeout' then bag:Clean() end
end,
})
Common mistakes
- Never calling
bag:Clean()on failure/timeout paths — only wiring it to the success callback leaves blips and NPCs behind when a player disconnects or times out. - Starting a new
WatchPlayerNear/WatchPromptwatcher without canceling the previous one — old watchers keep running and can double-fire your callback. - Forgetting that watchers auto-cancel when their owning resource stops (via
GetInvokingResource) — you don't need to manually track resource-stop yourself, but you do still need to clean up world entities (blips, peds) since those aren't tied to script lifetime.
Troubleshooting
- If a watcher never fires: check the
targetshape — it must be a vector3, a plain{x,y,z}table, or a valid entity handle. A stale/deleted entity handle silently never matches. - If cleanup runs twice:
Clean()is idempotent (guarded byself.cleaned), so a duplicate call is harmless — but check you're not accidentally holding two separate bags for the same mission. - If blips linger after a mission ends unexpectedly: make sure your
onCancel/timeout paths also callbag:Clean(), not just the happy path.