diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 0ca31288508..a369a578a26 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -4338,93 +4338,91 @@ bool CStaticFunctionDefinitions::WarpPedIntoVehicle(CPed* pPed, CVehicle* pVehic if (pVehicle->GetModel() == VT_CAMPER && uiSeat > 2) return false; - // Valid seat id for that vehicle? - // Temp fix: Disable driver seat for train carriages since the whole vehicle sync logic is based on the the player on the first seat being the vehicle - // syncer (Todo) - if (pVehicle->GetVehicleType() != VEHICLE_TRAIN || !pVehicle->GetTowedByVehicle()) + // Disallow driver seat on towed carriages to preserve lead locomotive sync + if (pVehicle->GetVehicleType() == VEHICLE_TRAIN && pVehicle->GetTowedByVehicle() && uiSeat == 0) + return false; + + if (!pPed->IsDead()) { - if (!pPed->IsDead()) + if (pVehicle->GetHealth() > 0.0f) { - if (pVehicle->GetHealth() > 0.0f) + CPed* pPreviousOccupant = pVehicle->GetOccupant(uiSeat); + // Make sure no one is entering or he will get stuck in the entry packet handshaking and network trouble + if (pPreviousOccupant == NULL || (pPreviousOccupant && pPreviousOccupant->GetVehicleAction() == CPed::VEHICLEACTION_NONE)) { - CPed* pPreviousOccupant = pVehicle->GetOccupant(uiSeat); - // Make sure no one is entering or he will get stuck in the entry packet handshaking and network trouble - if (pPreviousOccupant == NULL || (pPreviousOccupant && pPreviousOccupant->GetVehicleAction() == CPed::VEHICLEACTION_NONE)) + // Toss the previous player out of it if necessary + if (pPreviousOccupant) { - // Toss the previous player out of it if necessary - if (pPreviousOccupant) - { - // Remove him from the vehicle - RemovePedFromVehicle(pPreviousOccupant); - } + // Remove him from the vehicle + RemovePedFromVehicle(pPreviousOccupant); + } - // Jax: ::RemovePedFromVehicle caused a short delay between removing and entering, - // which creates a buggy effect if we're just warping into a different seat + // Jax: ::RemovePedFromVehicle caused a short delay between removing and entering, + // which creates a buggy effect if we're just warping into a different seat - // Is he already in a vehicle? Remove him from it - CVehicle* pPreviousVehicle = pPed->GetOccupiedVehicle(); - if (pPreviousVehicle) - { - // Remove him from the vehicle - pPreviousVehicle->SetOccupant(NULL, pPed->GetOccupiedVehicleSeat()); - } + // Is he already in a vehicle? Remove him from it + CVehicle* pPreviousVehicle = pPed->GetOccupiedVehicle(); + if (pPreviousVehicle) + { + // Remove him from the vehicle + pPreviousVehicle->SetOccupant(NULL, pPed->GetOccupiedVehicleSeat()); + } - // Put him in the new vehicle - pPed->SetOccupiedVehicle(pVehicle, uiSeat); - pPed->SetVehicleAction(CPed::VEHICLEACTION_NONE); + // Put him in the new vehicle + pPed->SetOccupiedVehicle(pVehicle, uiSeat); + pPed->SetVehicleAction(CPed::VEHICLEACTION_NONE); - // If he's the driver, switch on the engine - if (uiSeat == 0 && g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART)) - pVehicle->SetEngineOn(true); + // If he's the driver, switch on the engine + if (uiSeat == 0 && g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::VEHICLE_ENGINE_AUTOSTART)) + pVehicle->SetEngineOn(true); - // Tell all the players. If the calling resource's elements haven't reached the clients yet - // (e.g. called from onResourceStart on a vehicle created in the same event), hold off until - // they have instead of just dropping it - the vehicle itself isn't synced to clients yet - // either, and an RPC referencing an unknown element there would leave the server and clients - // permanently disagreeing about whether this ped is in a vehicle. - auto sendWarpRpc = [pPed, pVehicle, uiSeat]() - { - CBitStream BitStream; - BitStream.pBitStream->Write(pVehicle->GetID()); - BitStream.pBitStream->Write(static_cast(uiSeat)); - BitStream.pBitStream->Write(pPed->GenerateSyncTimeContext()); - m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pPed, WARP_PED_INTO_VEHICLE, *BitStream.pBitStream)); - }; - - if (pCallingResource) - pCallingResource->RunOrDeferUntilClientSynced(sendWarpRpc); - else - sendWarpRpc(); - - // Call the player->vehicle event - CLuaArguments PlayerVehicleArguments; - PlayerVehicleArguments.PushElement(pVehicle); // vehicle - PlayerVehicleArguments.PushNumber(uiSeat); // seat - if (pPreviousOccupant) // jacked - PlayerVehicleArguments.PushElement(pPreviousOccupant); - else - PlayerVehicleArguments.PushBoolean(false); - // Leave onPlayerVehicleEnter for backwards compatibility - if (IS_PLAYER(pPed)) - pPed->CallEvent("onPlayerVehicleEnter", PlayerVehicleArguments); - else - pPed->CallEvent("onPedVehicleEnter", PlayerVehicleArguments); - - // Call the vehicle->player event - CLuaArguments VehiclePlayerArguments; - VehiclePlayerArguments.PushElement(pPed); // player - VehiclePlayerArguments.PushNumber(uiSeat); // seat - if (pPreviousOccupant) // jacked - VehiclePlayerArguments.PushElement(pPreviousOccupant); - else - VehiclePlayerArguments.PushBoolean(false); - pVehicle->CallEvent("onVehicleEnter", VehiclePlayerArguments); + // Tell all the players. If the calling resource's elements haven't reached the clients yet + // (e.g. called from onResourceStart on a vehicle created in the same event), hold off until + // they have instead of just dropping it - the vehicle itself isn't synced to clients yet + // either, and an RPC referencing an unknown element there would leave the server and clients + // permanently disagreeing about whether this ped is in a vehicle. + auto sendWarpRpc = [pPed, pVehicle, uiSeat]() + { + CBitStream BitStream; + BitStream.pBitStream->Write(pVehicle->GetID()); + BitStream.pBitStream->Write(static_cast(uiSeat)); + BitStream.pBitStream->Write(pPed->GenerateSyncTimeContext()); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pPed, WARP_PED_INTO_VEHICLE, *BitStream.pBitStream)); + }; + + if (pCallingResource) + pCallingResource->RunOrDeferUntilClientSynced(sendWarpRpc); + else + sendWarpRpc(); + + // Call the player->vehicle event + CLuaArguments PlayerVehicleArguments; + PlayerVehicleArguments.PushElement(pVehicle); // vehicle + PlayerVehicleArguments.PushNumber(uiSeat); // seat + if (pPreviousOccupant) // jacked + PlayerVehicleArguments.PushElement(pPreviousOccupant); + else + PlayerVehicleArguments.PushBoolean(false); + // Leave onPlayerVehicleEnter for backwards compatibility + if (IS_PLAYER(pPed)) + pPed->CallEvent("onPlayerVehicleEnter", PlayerVehicleArguments); + else + pPed->CallEvent("onPedVehicleEnter", PlayerVehicleArguments); + + // Call the vehicle->player event + CLuaArguments VehiclePlayerArguments; + VehiclePlayerArguments.PushElement(pPed); // player + VehiclePlayerArguments.PushNumber(uiSeat); // seat + if (pPreviousOccupant) // jacked + VehiclePlayerArguments.PushElement(pPreviousOccupant); + else + VehiclePlayerArguments.PushBoolean(false); + pVehicle->CallEvent("onVehicleEnter", VehiclePlayerArguments); - // Used to check if f.e. lua changed the player's vehicle (fix for #7570) - pVehicle->m_bOccupantChanged = true; + // Used to check if f.e. lua changed the player's vehicle (fix for #7570) + pVehicle->m_bOccupantChanged = true; - return true; - } + return true; } } }