View Issue Details

IDProjectCategoryView StatusLast Update
0000554GTA ConnectedGrand Theft Auto IVpublic2026-05-09 19:26
Reporterskitzo Assigned To 
PriorityurgentSeveritymajorReproducibilityalways
Status newResolutionopen 
Platformx64OSWindowsOS Version11
Summary0000554: GTAC 1.7.3 Vehicle Passenger Sync Bug
Description

Hey, we found what seems to be a longstanding GTAC vehicle sync bug related to passengers and sync ownership transfer.

When a player enters a vehicle as passenger first, everything works fine. But as soon as another player enters as driver, the passenger gets visually kicked out of the vehicle for everyone. Re-warping the passenger back into the seat works only momentarily before the next sync tick removes them again.

We tested this with multiple methods (taskEnterCarAsPassenger, warpCharIntoCarAsPassenger, enterVehicle) and the result is always the same. From our testing, it looks like when the driver enters and becomes the new vehicle sync owner, their client syncs the vehicle as if all passenger seats are empty, which overwrites the existing occupancy state on every client.

We also tried a server-side workaround that tracks passengers and re-warps them after driver entry, but the sync system immediately overwrites it again.

I’ve attached a detailed .md file below with full reproduction steps, logs, our findings, and a minimal repro script.

TagsNo tags attached.
Game

Activities

skitzo

2026-05-09 19:26

reporter  

gtac-passenger-sync-bug.md (7,285 bytes)   
# GTAC vehicle-passenger sync bug report

**Reporter:** Liberty City Roleplay (lcrp-gamemode)
**GTAC version:** 1.7.3
**Game:** GTA IV, episode 2 (TBoGT)
**Affected since:** as far back as we have notes; we believe this is the longstanding behavior, not a regression.

## Summary

When a driver enters a vehicle that already has player passengers seated, the passengers are silently and visually kicked from their seats. They do not see themselves in the vehicle anymore; the driver does not see them in the vehicle. Re-tasking or warping the passenger back into the seat from any client succeeds momentarily but is overwritten by the next sync tick. The passenger ends up outside the vehicle.

We believe this is a vehicle-occupancy sync ownership transfer issue: when a new driver enters, they take over as syncer for the vehicle, and their authoritative view (driver only, all passenger seats empty) is propagated to every other client, overwriting the existing passenger state.

## Reproduction

1. Two players A and B connect to a GTAC server.
2. A vehicle with at least 2 seats is spawned (any standard 4-seater works).
3. **A presses G to enter as passenger** when the driver seat is empty. They successfully sit in seat 1 (or whichever passenger seat the script assigns).
4. **B walks up and presses F to enter as driver** (or scripted equivalent: `taskEnterCarAsDriver`). B sits in seat 0.
5. **Observed:** A is visually ejected from the vehicle. From A's view, A's ped is back on foot next to the car. From B's view, A is also outside the car. The vehicle's occupancy state on every client now matches B's view: driver only, all passenger seats empty.

We have confirmed this is reproducible with **any** of these passenger-entry primitives:

- `natives.taskEnterCarAsPassenger(ped, vehicle, timeout, seat)` — the documented entry path
- `natives.warpCharIntoCarAsPassenger(ped, vehicle, seat)` — direct teleport, no entry animation
- `localPlayer.enterVehicle(...)` — the GTAC API wrapper

All three put A in the seat momentarily, then A is kicked when B enters as driver.

## What we tried

We built a server-side workaround that:

1. Listens to a client-side `OnProcess` poll that fires `playerEnteredVehicleEvent` whenever the local player's `getCarCharIsUsing` / `isCharSittingInCar` state changes.
2. Tracks per-vehicle seat assignments: `vehicleElementId → Map<clientIndex, seat>`.
3. On a `seat === 0` (driver) entry, snapshots tracked passengers and after a 500ms delay (let GTAC settle) fires a server-to-client RPC to each tracked passenger.
4. Each passenger's client receives the RPC and calls `natives.warpCharIntoCarAsPassenger(localPed, vehicle, originalSeat)`.

Diagnostic logs confirm:

- The driver-entry detection fires correctly.
- The passenger map at the time of detection has the correct `clientIndex@seat` for the kicked passenger.
- The RPC reaches the passenger's client.
- `warpCharIntoCarAsPassenger` is called with the correct vehicle handle and seat number.
- The next `OnPedEnteredVehicleEx` event reports the player back in the original seat.

**But the passenger is still visually outside the vehicle within a frame or two of the warp.** This strongly suggests the issue is not a one-shot state corruption that we can repair after the fact — the sync system is continuously re-asserting the driver's authoritative view, overwriting any local re-warp on the next tick.

We can't get around this from our scripts. We'd need either (a) a way to keep the original sync owner from being displaced when the driver enters, or (b) server-authoritative seat assignment that propagates to all clients.

## Expected behavior

When a driver enters a vehicle that already has player-controlled passengers, all clients (including the new driver) should see the existing passengers remain in their seats. This matches GTA IV's own single-player behavior — a vehicle with multiple occupants is a stable state.

## Where we suspect the bug lives

The transition we're highlighting is the **sync owner handoff at driver entry**. We suspect:

1. The new driver's client takes over as vehicle syncer with no awareness of the existing non-driver occupants — its initial state snapshot shows only itself in the car.
2. That snapshot is broadcast as the new authoritative state.
3. Every other client (including the existing passengers) updates their local copy, removing the passengers from the seats.
4. Even if the passenger client immediately re-warps (server-coordinated or client-side), the next sync tick from the driver overwrites it again.

If GTAC has a per-vehicle seat-occupancy field as part of its replicated state, the fix is probably for the new syncer to inherit existing seat occupants from the prior syncer's last broadcast, rather than rebuilding the state from local game-engine truth (which on the new driver's client is "I just entered, no one else is in here").

If GTAC delegates seat occupancy to the engine and reads it from `getCharCoordinates` / `isCharSittingInCar` on the new syncer's frame, the fix is more involved — needs an explicit replicated occupancy table.

## Minimal repro script

If helpful, this is the smallest standalone passenger-entry script that exhibits the bug. Drop into a client resource:

```ts
// On G key, find nearest vehicle within 5m and warp into seat 1
addEventHandler("OnKeyDown", (_event, key) => {
    if (key !== SDLK_g) return;
    const ped = natives.getPlayerChar(natives.getPlayerId());
    const posRaw = natives.getCharCoordinates(ped) as unknown as number[];
    const pos = new Vec3(posRaw[0], posRaw[1], posRaw[2]);
    let nearest: Vehicle | null = null;
    let nearestDist = 5.0;
    for (const v of getElementsByType(ELEMENT_VEHICLE) as Vehicle[]) {
        const d = pos.distance(v.position);
        if (d < nearestDist) { nearest = v; nearestDist = d; }
    }
    if (!nearest) return;
    (natives as any).warpCharIntoCarAsPassenger(ped, nearest, 1);
});
```

With two players A and B and a vehicle nearby:

1. A presses G → A is in seat 1.
2. B presses F (vanilla driver entry) → A is kicked.

## What we'd like

Either:

1. **A patch in GTAC** that preserves vehicle seat occupancy across syncer handoff at driver entry, OR
2. **Documentation of an existing API** we can use server-side to authoritatively assign and replicate seat occupancy (we've checked all `Ped.*` and `natives.*warp*` and `setCarPedInSeat`-style names in `@types/gtac/natives.d.ts` and didn't find a server-side seat-assignment primitive — `Ped.vehicle` and `Ped.seat` are read-only on the server), OR
3. **A confirmed workaround** from your end that achieves stable multi-occupant vehicles.

We're happy to cooperate with any debugging — happy to ship a build with extra instrumentation if there are specific event hooks you'd like us to log.

## Server / repro environment

- gtaconnected/Server image, GTAC 1.7.3
- Resources are SpiderMonkey 60 with esbuild bundling; the bug repros in plain JS resources (verified with v-sandbox commands too)
- Server runs in Docker with a static IP and direct-connect-only (`<serverbrowser>false</serverbrowser>`)
- Both clients on Windows 11 with retail GTA IV TBoGT

Contact: rheo / @rheo on the GTAC discord, or via this repo's issue tracker.
gtac-passenger-sync-bug.md (7,285 bytes)   

Issue History

Date Modified Username Field Change
2026-05-09 19:26 skitzo New Issue
2026-05-09 19:26 skitzo File Added: gtac-passenger-sync-bug.md