From 1c861ce29fa0683701054d6780f93fd0e17277cb Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Sat, 29 Sep 2018 21:17:33 -0600 Subject: [PATCH 01/15] Add support for driving and being a passenger in client-side vehicles and partial client-side vehicle damage support. --- Client/mods/deathmatch/logic/CClientGame.cpp | 327 +++++++++++------- .../mods/deathmatch/logic/CClientVehicle.cpp | 14 +- Client/mods/deathmatch/logic/CNetAPI.cpp | 13 +- 3 files changed, 209 insertions(+), 145 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 84b6d1c86d8..4bbbac6bd9d 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -1544,38 +1544,43 @@ void CClientGame::UpdateVehicleInOut(void) CClientVehicle* pVehicle = m_pLocalPlayer->GetRealOccupiedVehicle(); if (!pVehicle) { - // Tell the server that we successfully left the car - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (pBitStream) + // Check if vehicle isn't local. + if (!pInOutVehicle->IsLocalEntity()) { - // Write the car id and the action id (enter complete) - pBitStream->Write(m_VehicleInOutID); - unsigned char ucAction = VEHICLE_NOTIFY_OUT; - pBitStream->WriteBits(&ucAction, 4); + // Tell the server that we successfully left the car + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (pBitStream) + { + // Write the car id and the action id (enter complete) + pBitStream->Write(m_VehicleInOutID); + unsigned char ucAction = VEHICLE_NOTIFY_OUT; + pBitStream->WriteBits(&ucAction, 4); - // Send it and destroy the packet - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); - } + // Send it and destroy the packet + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); + } - // Warp ourself out (so we're sure the records are correct) - m_pLocalPlayer->RemoveFromVehicle(); + // Warp ourself out (so we're sure the records are correct) + m_pLocalPlayer->RemoveFromVehicle(); - /* - // Make it undamagable if we're not syncing it, and damagable if we're syncing it - if ( pInOutVehicle ) - { - if ( pInOutVehicle->IsSyncing () ) + /* + // Make it undamagable if we're not syncing it, and damagable if we're syncing it + if ( pInOutVehicle ) { - pInOutVehicle->SetCanBeDamaged ( true ); - pInOutVehicle->SetTyresCanBurst ( true ); - } - else - { - pInOutVehicle->SetCanBeDamaged ( false ); - pInOutVehicle->SetTyresCanBurst ( false ); - } - }*/ + if ( pInOutVehicle->IsSyncing () ) + { + pInOutVehicle->SetCanBeDamaged ( true ); + pInOutVehicle->SetTyresCanBurst ( true ); + } + else + { + pInOutVehicle->SetCanBeDamaged ( false ); + pInOutVehicle->SetTyresCanBurst ( false ); + } + }*/ + } + if (pInOutVehicle) { pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); @@ -1586,12 +1591,20 @@ void CClientGame::UpdateVehicleInOut(void) // Don't allow a new entry/leave until we've gotten the notify return packet ElementID ReasonVehicleID = m_VehicleInOutID; g_pClientGame->ResetVehicleInOut(); - m_bNoNewVehicleTask = true; - m_NoNewVehicleTaskReasonID = ReasonVehicleID; -#ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_out"); -#endif + if (!pInOutVehicle->IsLocalEntity()) + { + m_bNoNewVehicleTask = true; + m_NoNewVehicleTaskReasonID = ReasonVehicleID; + + #ifdef MTA_DEBUG + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_out"); + #endif + } + else + { + CClientVehicle::UnpairPedAndVehicle(m_pLocalPlayer, pInOutVehicle); + } } // Are we still inside the car? else @@ -1612,33 +1625,37 @@ void CClientGame::UpdateVehicleInOut(void) CClientVehicle* pVehicle = m_pLocalPlayer->GetRealOccupiedVehicle(); if (pVehicle) { - // Tell the server that we successfully entered the car - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (pBitStream) + // Check if vehicle isn't local. + if (!pVehicle->IsLocalEntity()) { - // Write the car id and the action id (enter complete) - pBitStream->Write(m_VehicleInOutID); - unsigned char ucAction; - - if (m_bIsJackingVehicle) + // Tell the server that we successfully entered the car + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (pBitStream) { - ucAction = static_cast(VEHICLE_NOTIFY_JACK); + // Write the car id and the action id (enter complete) + pBitStream->Write(m_VehicleInOutID); + unsigned char ucAction; + + if (m_bIsJackingVehicle) + { + ucAction = static_cast(VEHICLE_NOTIFY_JACK); #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_jack"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_jack"); #endif - } - else - { - ucAction = static_cast(VEHICLE_NOTIFY_IN); + } + else + { + ucAction = static_cast(VEHICLE_NOTIFY_IN); #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_in"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_in"); #endif - } - pBitStream->WriteBits(&ucAction, 4); + } + pBitStream->WriteBits(&ucAction, 4); - // Send it and destroy the packet - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); + // Send it and destroy the packet + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); + } } // Warp ourself in (so we're sure the records are correct) @@ -1661,66 +1678,70 @@ void CClientGame::UpdateVehicleInOut(void) } else { - // Tell the server that we aborted entered the car - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (pBitStream) + // Check if vehicle isn't local. + if (!pInOutVehicle->IsLocalEntity()) { - // Write the car id and the action id (enter complete) - pBitStream->Write(m_VehicleInOutID); - unsigned char ucAction; - if (m_bIsJackingVehicle) + // Tell the server that we aborted entered the car + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (pBitStream) { - ucAction = static_cast(VEHICLE_NOTIFY_JACK_ABORT); - pBitStream->WriteBits(&ucAction, 4); - - // Did we start jacking them? - bool bAlreadyStartedJacking = false; - CClientVehicle* pVehicle = DynamicCast(CElementIDs::GetElement(m_VehicleInOutID)); - if (pVehicle) + // Write the car id and the action id (enter complete) + pBitStream->Write(m_VehicleInOutID); + unsigned char ucAction; + if (m_bIsJackingVehicle) { - CClientPed* pJackedPlayer = pVehicle->GetOccupant(); - if (pJackedPlayer) + ucAction = static_cast(VEHICLE_NOTIFY_JACK_ABORT); + pBitStream->WriteBits(&ucAction, 4); + + // Did we start jacking them? + bool bAlreadyStartedJacking = false; + CClientVehicle* pVehicle = DynamicCast(CElementIDs::GetElement(m_VehicleInOutID)); + if (pVehicle) { - // Jax: have we already started to jack the other player? - if (pJackedPlayer->IsGettingJacked()) + CClientPed* pJackedPlayer = pVehicle->GetOccupant(); + if (pJackedPlayer) { - bAlreadyStartedJacking = true; + // Jax: have we already started to jack the other player? + if (pJackedPlayer->IsGettingJacked()) + { + bAlreadyStartedJacking = true; + } } + unsigned char ucDoor = m_pLocalPlayer->m_ucEnteringDoor - 2; + pBitStream->WriteBits(&ucDoor, 3); + SDoorOpenRatioSync door; + door.data.fRatio = pVehicle->GetDoorOpenRatio(m_pLocalPlayer->m_ucEnteringDoor); + pBitStream->Write(&door); } - unsigned char ucDoor = m_pLocalPlayer->m_ucEnteringDoor - 2; - pBitStream->WriteBits(&ucDoor, 3); - SDoorOpenRatioSync door; - door.data.fRatio = pVehicle->GetDoorOpenRatio(m_pLocalPlayer->m_ucEnteringDoor); - pBitStream->Write(&door); - } - pBitStream->WriteBit(bAlreadyStartedJacking); + pBitStream->WriteBit(bAlreadyStartedJacking); #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_jack_abort"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_jack_abort"); #endif - } - else - { - ucAction = static_cast(VEHICLE_NOTIFY_IN_ABORT); - pBitStream->WriteBits(&ucAction, 4); - CClientVehicle* pVehicle = DynamicCast(CElementIDs::GetElement(m_VehicleInOutID)); - if (pVehicle) - { - unsigned char ucDoor = m_pLocalPlayer->m_ucEnteringDoor - 2; - pBitStream->WriteBits(&ucDoor, 3); - SDoorOpenRatioSync door; - door.data.fRatio = pVehicle->GetDoorOpenRatio(m_pLocalPlayer->m_ucEnteringDoor); - pBitStream->Write(&door); } + else + { + ucAction = static_cast(VEHICLE_NOTIFY_IN_ABORT); + pBitStream->WriteBits(&ucAction, 4); + CClientVehicle* pVehicle = DynamicCast(CElementIDs::GetElement(m_VehicleInOutID)); + if (pVehicle) + { + unsigned char ucDoor = m_pLocalPlayer->m_ucEnteringDoor - 2; + pBitStream->WriteBits(&ucDoor, 3); + SDoorOpenRatioSync door; + door.data.fRatio = pVehicle->GetDoorOpenRatio(m_pLocalPlayer->m_ucEnteringDoor); + pBitStream->Write(&door); + } #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_in_abort"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_in_abort"); #endif - } + } - // Send it and destroy the packet - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); + // Send it and destroy the packet + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); + } } // Warp ourself out again (so we're sure the records are correct) @@ -1753,8 +1774,12 @@ void CClientGame::UpdateVehicleInOut(void) // Don't allow a new entry/leave until we've gotten the notify return packet ElementID ReasonID = m_VehicleInOutID; ResetVehicleInOut(); - m_bNoNewVehicleTask = true; - m_NoNewVehicleTaskReasonID = ReasonID; + + if (!pInOutVehicle->IsLocalEntity()) + { + m_bNoNewVehicleTask = true; + m_NoNewVehicleTaskReasonID = ReasonID; + } } } } @@ -1780,47 +1805,50 @@ void CClientGame::UpdateVehicleInOut(void) // Jax: this happens when we try to warp into a streamed out vehicle, including when we use CClientVehicle::StreamInNow // ..maybe we need a different way to detect bike falls? - // Tell the server - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (pBitStream) + if (!pOccupiedVehicle->IsLocalEntity()) { - // Vehicle id - pBitStream->Write(pOccupiedVehicle->GetID()); - unsigned char ucAction = static_cast(VEHICLE_NOTIFY_FELL_OFF); - pBitStream->WriteBits(&ucAction, 4); + // Tell the server + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (pBitStream) + { + // Vehicle id + pBitStream->Write(pOccupiedVehicle->GetID()); + unsigned char ucAction = static_cast(VEHICLE_NOTIFY_FELL_OFF); + pBitStream->WriteBits(&ucAction, 4); - // Send it and destroy the packet - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); + // Send it and destroy the packet + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); - // We're not allowed to enter any vehicle before we get a confirm - m_bNoNewVehicleTask = true; - m_NoNewVehicleTaskReasonID = pOccupiedVehicle->GetID(); + // We're not allowed to enter any vehicle before we get a confirm + m_bNoNewVehicleTask = true; + m_NoNewVehicleTaskReasonID = pOccupiedVehicle->GetID(); - // Remove him from the vehicle - m_pLocalPlayer->RemoveFromVehicle(); + // Remove him from the vehicle + m_pLocalPlayer->RemoveFromVehicle(); - /* - // Make it undamagable if we're not syncing it - CDeathmatchVehicle* pInOutVehicle = static_cast < CDeathmatchVehicle* > ( pOccupiedVehicle ); - if ( pInOutVehicle ) - { - if ( pInOutVehicle->IsSyncing () ) + /* + // Make it undamagable if we're not syncing it + CDeathmatchVehicle* pInOutVehicle = static_cast < CDeathmatchVehicle* > ( pOccupiedVehicle ); + if ( pInOutVehicle ) { - pInOutVehicle->SetCanBeDamaged ( true ); - pInOutVehicle->SetTyresCanBurst ( true ); - } - else - { - pInOutVehicle->SetCanBeDamaged ( false ); - pInOutVehicle->SetTyresCanBurst ( false ); + if ( pInOutVehicle->IsSyncing () ) + { + pInOutVehicle->SetCanBeDamaged ( true ); + pInOutVehicle->SetTyresCanBurst ( true ); + } + else + { + pInOutVehicle->SetCanBeDamaged ( false ); + pInOutVehicle->SetTyresCanBurst ( false ); + } } - } - */ + */ #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_fell_off"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_fell_off"); #endif + } } } } @@ -2274,6 +2302,7 @@ void CClientGame::ResetVehicleInOut(void) m_bNoNewVehicleTask = false; m_NoNewVehicleTaskReasonID = INVALID_ELEMENT_ID; m_pGettingJackedBy = NULL; + m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_NONE); } void CClientGame::SetAllDimensions(unsigned short usDimension) @@ -4964,6 +4993,28 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) return; } + unsigned char ucDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(m_pLocalPlayer->GetGamePlayer(), pOccupiedVehicle->GetGameVehicle()); + + if (pOccupiedVehicle->IsLocalEntity()) + { + g_pClientGame->m_VehicleInOutID = pOccupiedVehicle->GetID(); + g_pClientGame->m_ucVehicleInOutSeat = m_pLocalPlayer->GetOccupiedVehicleSeat(); + + m_VehicleInOutID = pOccupiedVehicle->GetID(); + m_bIsGettingOutOfVehicle = true; + m_ulLastVehicleInOutTime = CClientTime::GetTime(); + + if (ucDoor >= 2 && ucDoor <= 5) + { + ucDoor -= 2; + } + + m_pLocalPlayer->GetOutOfVehicle(ucDoor); + m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_OUT); + + return; + } + // We're about to exit a vehicle // Send an in request NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); @@ -4977,7 +5028,6 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) unsigned char ucAction = static_cast(VEHICLE_REQUEST_OUT); pBitStream->WriteBits(&ucAction, 4); - unsigned char ucDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(m_pLocalPlayer->GetGamePlayer(), pOccupiedVehicle->GetGameVehicle()); if (ucDoor >= 2 && ucDoor <= 5) { ucDoor -= 2; @@ -5072,6 +5122,21 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) return; } + if (pVehicle->IsLocalEntity()) + { + g_pClientGame->m_VehicleInOutID = pVehicle->GetID(); + g_pClientGame->m_ucVehicleInOutSeat = uiSeat; + + m_VehicleInOutID = pVehicle->GetID(); + m_bIsGettingIntoVehicle = true; + m_ulLastVehicleInOutTime = CClientTime::GetTime(); + + m_pLocalPlayer->GetIntoVehicle(pVehicle, uiSeat, uiDoor); + m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN); + + return; + } + // Call the onClientVehicleStartEnter event for remote players // Local player triggered before sending packet in CClientGame CLuaArguments Arguments; diff --git a/Client/mods/deathmatch/logic/CClientVehicle.cpp b/Client/mods/deathmatch/logic/CClientVehicle.cpp index 4d0a34b20fe..c45f366b809 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicle.cpp @@ -3843,17 +3843,13 @@ bool CClientVehicle::IsEnterable(void) { if (m_pVehicle) { - // Server vehicle? - if (!IsLocalEntity()) + if (GetHealth() > 0.0f) { - if (GetHealth() > 0.0f) + if (!IsInWater() || (GetVehicleType() == CLIENTVEHICLE_BOAT || m_usModel == 447 /* sea sparrow */ + || m_usModel == 417 /* levithan */ + || m_usModel == 460 /* skimmer */)) { - if (!IsInWater() || (GetVehicleType() == CLIENTVEHICLE_BOAT || m_usModel == 447 /* sea sparrow */ - || m_usModel == 417 /* levithan */ - || m_usModel == 460 /* skimmer */)) - { - return true; - } + return true; } } } diff --git a/Client/mods/deathmatch/logic/CNetAPI.cpp b/Client/mods/deathmatch/logic/CNetAPI.cpp index 9a47836a4de..fa2b76e8266 100644 --- a/Client/mods/deathmatch/logic/CNetAPI.cpp +++ b/Client/mods/deathmatch/logic/CNetAPI.cpp @@ -313,7 +313,7 @@ void CNetAPI::DoPulse(void) if (IsPureSyncNeeded() && !g_pClientGame->IsDownloadingBigPacket()) { // Are in a vehicle? - if (pVehicle) + if (pVehicle && !pVehicle->IsLocalEntity()) { // Send a puresync packet NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); @@ -1118,11 +1118,14 @@ void CNetAPI::WritePlayerPuresync(CClientPlayer* pPlayerModel, NetBitStreamInter // If the player is in contact with a object/vehicle, make that the origin if (bInContact) { - BitStream.Write(pContactEntity->GetID()); + if (!pContactEntity->IsLocalEntity()) + { + BitStream.Write(pContactEntity->GetID()); - CVector vecOrigin; - pContactEntity->GetPosition(vecOrigin); - vecPosition -= vecOrigin; + CVector vecOrigin; + pContactEntity->GetPosition(vecOrigin); + vecPosition -= vecOrigin; + } } SPositionSync position(false); From 956db607f8a7d27b39a8a6117f7afb4478cb063b Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Sun, 30 Sep 2018 00:19:18 -0600 Subject: [PATCH 02/15] Added support for "onClientVehicleStartEnter", "onClientVehicleEnter", "onClientVehicleStartExit" and "onClientVehicleExit" events for client-side vehicles. Added proper handling for falling off a client-side bike. --- Client/mods/deathmatch/logic/CClientGame.cpp | 90 ++++++++++++++------ 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 4bbbac6bd9d..047451d9860 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -1587,6 +1587,8 @@ void CClientGame::UpdateVehicleInOut(void) pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); } + unsigned char ucSeat = m_ucVehicleInOutSeat; + // Reset the vehicle in out stuff so we're ready for another car entry/leave. // Don't allow a new entry/leave until we've gotten the notify return packet ElementID ReasonVehicleID = m_VehicleInOutID; @@ -1604,6 +1606,11 @@ void CClientGame::UpdateVehicleInOut(void) else { CClientVehicle::UnpairPedAndVehicle(m_pLocalPlayer, pInOutVehicle); + + CLuaArguments Arguments; + Arguments.PushElement(m_pLocalPlayer); + Arguments.PushNumber(ucSeat); + pInOutVehicle->CallEvent("onClientVehicleExit", Arguments, true); } } // Are we still inside the car? @@ -1770,6 +1777,8 @@ void CClientGame::UpdateVehicleInOut(void) } } + unsigned char ucSeat = m_ucVehicleInOutSeat; + // Reset // Don't allow a new entry/leave until we've gotten the notify return packet ElementID ReasonID = m_VehicleInOutID; @@ -1779,6 +1788,12 @@ void CClientGame::UpdateVehicleInOut(void) { m_bNoNewVehicleTask = true; m_NoNewVehicleTaskReasonID = ReasonID; + // Check if player is actually in the vehicle and didn't abandon entering before firing the event. + } else if(m_pLocalPlayer->IsInVehicle()) { + CLuaArguments Arguments; + Arguments.PushElement(m_pLocalPlayer); + Arguments.PushNumber(ucSeat); + pInOutVehicle->CallEvent("onClientVehicleEnter", Arguments, true); } } } @@ -1820,13 +1835,6 @@ void CClientGame::UpdateVehicleInOut(void) g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); g_pNet->DeallocateNetBitStream(pBitStream); - // We're not allowed to enter any vehicle before we get a confirm - m_bNoNewVehicleTask = true; - m_NoNewVehicleTaskReasonID = pOccupiedVehicle->GetID(); - - // Remove him from the vehicle - m_pLocalPlayer->RemoveFromVehicle(); - /* // Make it undamagable if we're not syncing it CDeathmatchVehicle* pInOutVehicle = static_cast < CDeathmatchVehicle* > ( pOccupiedVehicle ); @@ -1844,12 +1852,31 @@ void CClientGame::UpdateVehicleInOut(void) } } */ - -#ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_fell_off"); -#endif } } + + if (!pOccupiedVehicle->IsLocalEntity()) + { + // We're not allowed to enter any vehicle before we get a confirm + m_bNoNewVehicleTask = true; + m_NoNewVehicleTaskReasonID = pOccupiedVehicle->GetID(); + + // Remove him from the vehicle + m_pLocalPlayer->RemoveFromVehicle(); + + #ifdef MTA_DEBUG + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_notify_out"); + #endif + } + else + { + CLuaArguments Arguments; + Arguments.PushElement(m_pLocalPlayer); + Arguments.PushNumber(m_pLocalPlayer->GetOccupiedVehicleSeat()); + pOccupiedVehicle->CallEvent("onClientVehicleExit", Arguments, true); + + CClientVehicle::UnpairPedAndVehicle(m_pLocalPlayer, pOccupiedVehicle); + } } } } @@ -4997,8 +5024,9 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) if (pOccupiedVehicle->IsLocalEntity()) { - g_pClientGame->m_VehicleInOutID = pOccupiedVehicle->GetID(); - g_pClientGame->m_ucVehicleInOutSeat = m_pLocalPlayer->GetOccupiedVehicleSeat(); + unsigned char ucSeat = m_pLocalPlayer->GetOccupiedVehicleSeat(); + m_VehicleInOutID = pOccupiedVehicle->GetID(); + m_ucVehicleInOutSeat = ucSeat; m_VehicleInOutID = pOccupiedVehicle->GetID(); m_bIsGettingOutOfVehicle = true; @@ -5012,6 +5040,12 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) m_pLocalPlayer->GetOutOfVehicle(ucDoor); m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_OUT); + CLuaArguments Arguments; + Arguments.PushElement(m_pLocalPlayer); + Arguments.PushNumber(ucSeat); + Arguments.PushNumber(ucDoor); + pOccupiedVehicle->CallEvent("onClientVehicleStartExit", Arguments, true); + return; } @@ -5122,21 +5156,6 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) return; } - if (pVehicle->IsLocalEntity()) - { - g_pClientGame->m_VehicleInOutID = pVehicle->GetID(); - g_pClientGame->m_ucVehicleInOutSeat = uiSeat; - - m_VehicleInOutID = pVehicle->GetID(); - m_bIsGettingIntoVehicle = true; - m_ulLastVehicleInOutTime = CClientTime::GetTime(); - - m_pLocalPlayer->GetIntoVehicle(pVehicle, uiSeat, uiDoor); - m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN); - - return; - } - // Call the onClientVehicleStartEnter event for remote players // Local player triggered before sending packet in CClientGame CLuaArguments Arguments; @@ -5150,6 +5169,21 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) return; } + if (pVehicle->IsLocalEntity()) + { + m_VehicleInOutID = pVehicle->GetID(); + m_ucVehicleInOutSeat = uiSeat; + + m_VehicleInOutID = pVehicle->GetID(); + m_bIsGettingIntoVehicle = true; + m_ulLastVehicleInOutTime = CClientTime::GetTime(); + + m_pLocalPlayer->GetIntoVehicle(pVehicle, uiSeat, uiDoor); + m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN); + + return; + } + // Send an in request NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); if (!pBitStream) From b3ce97258e1c23e5a9f8e0cd7ae170935fe86a96 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Wed, 17 Oct 2018 23:31:31 -0600 Subject: [PATCH 03/15] Enabled damage for client-side vehicles that haven't been entered yet. --- Client/mods/deathmatch/logic/CClientVehicle.cpp | 6 ++++++ Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp | 3 +++ 2 files changed, 9 insertions(+) diff --git a/Client/mods/deathmatch/logic/CClientVehicle.cpp b/Client/mods/deathmatch/logic/CClientVehicle.cpp index c45f366b809..766a4c57830 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicle.cpp @@ -1161,6 +1161,9 @@ void CClientVehicle::CalcAndUpdateCanBeDamagedFlag(void) if (m_bSyncUnoccupiedDamage) bCanBeDamaged = true; + if (IsLocalEntity()) + bCanBeDamaged = true; + // Script override if (!m_bScriptCanBeDamaged) bCanBeDamaged = false; @@ -1210,6 +1213,9 @@ void CClientVehicle::CalcAndUpdateTyresCanBurstFlag(void) if (m_bSyncUnoccupiedDamage) bTyresCanBurst = true; + if (IsLocalEntity()) + bTyresCanBurst = true; + // Script override if (!m_bScriptCanBeDamaged) bTyresCanBurst = false; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 94ba85f42fe..605474d15b6 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -2668,6 +2668,9 @@ CClientVehicle* CStaticFunctionDefinitions::CreateVehicle(CResource& Resource, u if (szRegPlate) pVehicle->SetRegPlate(szRegPlate); + pVehicle->CalcAndUpdateCanBeDamagedFlag(); + pVehicle->CalcAndUpdateTyresCanBurstFlag(); + return pVehicle; } From 615cc9c2b68eb2880f231bcc255d4a2ff168f4d1 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Thu, 18 Oct 2018 03:53:45 -0600 Subject: [PATCH 04/15] Added "getPedNearestCarEntryPoint" and resolved some glitches with calculating the nearest car door. --- Client/mods/deathmatch/logic/CClientPed.cpp | 12 ++- .../logic/CStaticFunctionDefinitions.cpp | 14 ++++ .../logic/CStaticFunctionDefinitions.h | 61 +++++++-------- .../deathmatch/logic/luadefs/CLuaPedDefs.cpp | 74 +++++++++++++++++++ .../deathmatch/logic/luadefs/CLuaPedDefs.h | 1 + 5 files changed, 129 insertions(+), 33 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 77d7da32a93..e6230bc12ef 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -1156,10 +1156,10 @@ CClientVehicle* CClientPed::GetClosestVehicleInRange(bool bGetPositionFromCloses iClosestDoor = iPassengerDoor; vecClosestDoorPosition = vecVehiclePosition = vecPassengerPos; } - if (bCheckDriverDoor) + if (bCheckDriverDoor && bCheckPassengerDoors) { // If they're different, find the closest - if (iFrontDoor != iPassengerDoor && iPassengerDoor < 2) + if (iFrontDoor != iPassengerDoor) { float fDistanceFromFront = DistanceBetweenPoints3D(vecPosition, vecFrontPos); float fDistanceFromPassenger = DistanceBetweenPoints3D(vecPosition, vecPassengerPos); @@ -1167,6 +1167,9 @@ CClientVehicle* CClientPed::GetClosestVehicleInRange(bool bGetPositionFromCloses { iClosestDoor = iPassengerDoor; vecClosestDoorPosition = vecVehiclePosition = vecPassengerPos; + } else { + iClosestDoor = iFrontDoor; + vecClosestDoorPosition = vecFrontPos; } } } @@ -1250,7 +1253,7 @@ bool CClientPed::GetClosestDoor(CClientVehicle* pVehicle, bool bCheckDriverDoor, iClosestDoor = iPassengerDoor; vecClosestDoorPosition = vecPassengerPos; } - if (bCheckDriverDoor) + if (bCheckDriverDoor && bCheckPassengerDoors) { // If they're different, find the closest if (iFrontDoor != iPassengerDoor) @@ -1261,6 +1264,9 @@ bool CClientPed::GetClosestDoor(CClientVehicle* pVehicle, bool bCheckDriverDoor, { iClosestDoor = iPassengerDoor; vecClosestDoorPosition = vecPassengerPos; + } else { + iClosestDoor = iFrontDoor; + vecClosestDoorPosition = vecFrontPos; } } } diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 605474d15b6..de05efef208 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1771,6 +1771,20 @@ bool CStaticFunctionDefinitions::GetPedOccupiedVehicleSeat(CClientPed& pPed, uin return false; } +CClientVehicle* CStaticFunctionDefinitions::GetPedNearestCarEntryPoint(CClientPed& pPed, bool bCheckDriverDoor, bool bCheckPassengersDoors, + uint& uiEntryPoint, CVector& vecClosestDoorPosition) +{ + if (pPed.IsInVehicle()) + { + // The ped is already in a car, why bother checking the nearest car seat? + return false; + } + + CClientVehicle* pVehicle = pPed.GetClosestVehicleInRange(true, bCheckDriverDoor, bCheckPassengersDoors, false, &uiEntryPoint, &vecClosestDoorPosition, 20.0f); + + return pVehicle; +} + const char* CStaticFunctionDefinitions::GetPedSimplestTask(CClientPed& Ped) { CTaskManager* pTaskManager = Ped.GetTaskManager(); diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index f03205a2000..6e1da654153 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -132,36 +132,37 @@ class CStaticFunctionDefinitions static CClientPed* CreatePed(CResource& Resource, unsigned long ulModel, const CVector& vecPosition, float fRotation); static bool KillPed(CClientEntity& Entity, CClientEntity* pKiller, unsigned char ucKillerWeapon, unsigned char ucBodyPart, bool bStealth); - static CClientEntity* GetPedTarget(CClientPed& Ped); - static bool GetPedTargetCollision(CClientPed& Ped, CVector& vecOrigin); - static bool GetPedTask(CClientPed& Ped, bool bPrimary, unsigned int uiTaskType, std::vector& outTaskHierarchy); - static const char* GetPedSimplestTask(CClientPed& Ped); - static bool IsPedDoingTask(CClientPed& Ped, const char* szTaskName, bool& bIsDoingTask); - static bool GetPedBonePosition(CClientPed& Ped, eBone bone, CVector& vecPosition); - static bool GetPedClothes(CClientPed& Ped, unsigned char ucType, SString& strOutTexture, SString& strOutModel); - static bool GetPedControlState(CClientPed& Ped, const char* szControl, bool& bState); - static bool GetPedAnalogControlState(CClientPed& Ped, const char* szControl, float& fState); - static bool IsPedDoingGangDriveby(CClientPed& Ped, bool& bDoingGangDriveby); - static bool GetPedAnimation(CClientPed& Ped, SString& strOutBlockName, SString& strOutAnimName); - static bool GetPedMoveAnim(CClientPed& Ped, unsigned int& iMoveAnim); - static bool GetPedMoveState(CClientPed& Ped, std::string& strMoveState); - static bool IsPedHeadless(CClientPed& Ped, bool& bHeadless); - static bool IsPedFrozen(CClientPed& Ped, bool& bFrozen); - static bool GetPedOccupiedVehicleSeat(CClientPed& Ped, uint& uiSeat); - static bool IsPedFootBloodEnabled(CClientPed& Ped, bool& bHasFootBlood); - static bool GetPedCameraRotation(CClientPed& Ped, float& fRotation); - static bool GetPedWeaponMuzzlePosition(CClientPed& Ped, CVector& vecPosition); - static bool IsPedOnFire(CClientPed& Ped, bool& bOnFire); - static bool IsPedInVehicle(CClientPed& Ped, bool& bInVehicle); - static bool GetWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, float& fData); - static bool GetWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, int& sData); - static bool GetWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, CVector& vecData); - static bool GetWeaponPropertyFlag(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, bool& bEnable); - static bool GetOriginalWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, float& fData); - static bool GetOriginalWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, int& sData); - static bool GetOriginalWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, CVector& vecData); - static bool GetOriginalWeaponPropertyFlag(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, bool& bEnable); - static bool GetPedOxygenLevel(CClientPed& Ped, float& fOxygen); + static CClientEntity* GetPedTarget(CClientPed& Ped); + static bool GetPedTargetCollision(CClientPed& Ped, CVector& vecOrigin); + static bool GetPedTask(CClientPed& Ped, bool bPrimary, unsigned int uiTaskType, std::vector& outTaskHierarchy); + static const char* GetPedSimplestTask(CClientPed& Ped); + static bool IsPedDoingTask(CClientPed& Ped, const char* szTaskName, bool& bIsDoingTask); + static bool GetPedBonePosition(CClientPed& Ped, eBone bone, CVector& vecPosition); + static bool GetPedClothes(CClientPed& Ped, unsigned char ucType, SString& strOutTexture, SString& strOutModel); + static bool GetPedControlState(CClientPed& Ped, const char* szControl, bool& bState); + static bool GetPedAnalogControlState(CClientPed& Ped, const char* szControl, float& fState); + static bool IsPedDoingGangDriveby(CClientPed& Ped, bool& bDoingGangDriveby); + static bool GetPedAnimation(CClientPed& Ped, SString& strOutBlockName, SString& strOutAnimName); + static bool GetPedMoveAnim(CClientPed& Ped, unsigned int& iMoveAnim); + static bool GetPedMoveState(CClientPed& Ped, std::string& strMoveState); + static bool IsPedHeadless(CClientPed& Ped, bool& bHeadless); + static bool IsPedFrozen(CClientPed& Ped, bool& bFrozen); + static bool GetPedOccupiedVehicleSeat(CClientPed& Ped, uint& uiSeat); + static CClientVehicle* GetPedNearestCarEntryPoint(CClientPed& Ped, bool bCheckDriverDoor, bool bCheckPassengersDoors, uint& uiEntryPoint, CVector& vecClosestDoorPosition); + static bool IsPedFootBloodEnabled(CClientPed& Ped, bool& bHasFootBlood); + static bool GetPedCameraRotation(CClientPed& Ped, float& fRotation); + static bool GetPedWeaponMuzzlePosition(CClientPed& Ped, CVector& vecPosition); + static bool IsPedOnFire(CClientPed& Ped, bool& bOnFire); + static bool IsPedInVehicle(CClientPed& Ped, bool& bInVehicle); + static bool GetWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, float& fData); + static bool GetWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, int& sData); + static bool GetWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, CVector& vecData); + static bool GetWeaponPropertyFlag(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, bool& bEnable); + static bool GetOriginalWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, float& fData); + static bool GetOriginalWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, int& sData); + static bool GetOriginalWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, CVector& vecData); + static bool GetOriginalWeaponPropertyFlag(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, bool& bEnable); + static bool GetPedOxygenLevel(CClientPed& Ped, float& fOxygen); static bool SetPedWeaponSlot(CClientEntity& Entity, int iSlot); static bool GivePedWeapon(CClientEntity& Entity, uchar ucWeaponID, ushort usWeaponAmmo, bool bSetAsCurrent); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index f29939b4ba1..d1d0434bad9 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -43,6 +43,7 @@ void CLuaPedDefs::LoadFunctions(void) {"getPedTotalAmmo", GetPedTotalAmmo}, {"getPedOccupiedVehicle", GetPedOccupiedVehicle}, {"getPedOccupiedVehicleSeat", GetPedOccupiedVehicleSeat}, + {"getPedNearestCarEntryPoint", GetPedNearestCarEntryPoint}, {"getPedArmor", GetPedArmor}, {"isPedChoking", IsPedChoking}, {"isPedDucked", IsPedDucked}, @@ -127,6 +128,7 @@ void CLuaPedDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getMoveState", "getPedMoveState"); lua_classfunction(luaVM, "getOccupiedVehicle", "getPedOccupiedVehicle"); lua_classfunction(luaVM, "getOccupiedVehicleSeat", "getPedOccupiedVehicleSeat"); + lua_classfunction(luaVM, "getNearestCarEntryPoint", OOP_GetPedNearestCarEntryPoint); lua_classfunction(luaVM, "getOxygenLevel", "getPedOxygenLevel"); lua_classfunction(luaVM, "getStat", "getPedStat"); lua_classfunction(luaVM, "getTarget", "getPedTarget"); @@ -489,6 +491,78 @@ int CLuaPedDefs::GetPedOccupiedVehicleSeat(lua_State* luaVM) return 1; } +int CLuaPedDefs::GetPedNearestCarEntryPoint(lua_State* luaVM) +{ + // Verify the argument + CClientPed* pPed = NULL; + bool bCheckDriverDoor = true; + bool bCheckPassengersDoors = true; + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pPed); + argStream.ReadBool(bCheckDriverDoor, true); + argStream.ReadBool(bCheckPassengersDoors, true); + + if (!argStream.HasErrors()) + { + unsigned int uiEntryPoint; + CVector vecClosestDoorPosition; + + CClientVehicle* pVehicle = CStaticFunctionDefinitions::GetPedNearestCarEntryPoint(*pPed, bCheckDriverDoor, bCheckPassengersDoors, + uiEntryPoint, vecClosestDoorPosition); + + if (pVehicle) + { + lua_pushelement(luaVM, pVehicle); + lua_pushnumber(luaVM, uiEntryPoint); + lua_pushnumber(luaVM, vecClosestDoorPosition.fX); + lua_pushnumber(luaVM, vecClosestDoorPosition.fY); + lua_pushnumber(luaVM, vecClosestDoorPosition.fZ); + return 5; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + // Failed + lua_pushboolean(luaVM, false); + return 1; +} + +int CLuaPedDefs::OOP_GetPedNearestCarEntryPoint(lua_State* luaVM) +{ + // Verify the argument + CClientPed* pPed = NULL; + bool bCheckDriverDoor = true; + bool bCheckPassengersDoors = true; + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pPed); + argStream.ReadBool(bCheckDriverDoor, true); + argStream.ReadBool(bCheckPassengersDoors, true); + + if (!argStream.HasErrors()) + { + unsigned int uiEntryPoint; + CVector vecClosestDoorPosition; + + CClientVehicle* pVehicle = CStaticFunctionDefinitions::GetPedNearestCarEntryPoint(*pPed, bCheckDriverDoor, bCheckPassengersDoors, + uiEntryPoint, vecClosestDoorPosition); + + if (pVehicle) + { + lua_pushelement(luaVM, pVehicle); + lua_pushnumber(luaVM, uiEntryPoint); + lua_pushvector(luaVM, vecClosestDoorPosition); + return 3; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + // Failed + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaPedDefs::GetPedTask(lua_State* luaVM) { // Verify the argument diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index aedb671f2d5..dbcef96daba 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -36,6 +36,7 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(GetPedStat); LUA_DECLARE(GetPedOccupiedVehicle); LUA_DECLARE(GetPedOccupiedVehicleSeat); + LUA_DECLARE_OOP(GetPedNearestCarEntryPoint); LUA_DECLARE(GetPedArmor); LUA_DECLARE(IsPedChoking); LUA_DECLARE(IsPedDucked); From a976eba1d6ac235287cce84532ed806862c2c644 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Thu, 18 Oct 2018 04:30:02 -0600 Subject: [PATCH 05/15] Added proper support for client-side ped carjacking. Renamed "getPedNearestCarEntryPoint" to "getPedNearestVehicleEntryPoint". --- Client/mods/deathmatch/logic/CClientGame.cpp | 11 ++++++++++- .../logic/CStaticFunctionDefinitions.cpp | 2 +- .../logic/CStaticFunctionDefinitions.h | 2 +- .../deathmatch/logic/luadefs/CLuaPedDefs.cpp | 16 ++++++++-------- .../mods/deathmatch/logic/luadefs/CLuaPedDefs.h | 2 +- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 047451d9860..d352078b1e3 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -5179,7 +5179,16 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) m_ulLastVehicleInOutTime = CClientTime::GetTime(); m_pLocalPlayer->GetIntoVehicle(pVehicle, uiSeat, uiDoor); - m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN); + + CClientPed* pOccupyingPed = pVehicle->GetOccupant(uiSeat); + + if (pOccupyingPed) { + m_bIsJackingVehicle = true; + m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_JACKING); + pOccupyingPed->SetVehicleInOutState(VEHICLE_INOUT_GETTING_JACKED); + } else { + m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN); + } return; } diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index de05efef208..7cbf87e5bd8 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1771,7 +1771,7 @@ bool CStaticFunctionDefinitions::GetPedOccupiedVehicleSeat(CClientPed& pPed, uin return false; } -CClientVehicle* CStaticFunctionDefinitions::GetPedNearestCarEntryPoint(CClientPed& pPed, bool bCheckDriverDoor, bool bCheckPassengersDoors, +CClientVehicle* CStaticFunctionDefinitions::GetPedNearestVehicleEntryPoint(CClientPed& pPed, bool bCheckDriverDoor, bool bCheckPassengersDoors, uint& uiEntryPoint, CVector& vecClosestDoorPosition) { if (pPed.IsInVehicle()) diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 6e1da654153..24345cee6e4 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -148,7 +148,7 @@ class CStaticFunctionDefinitions static bool IsPedHeadless(CClientPed& Ped, bool& bHeadless); static bool IsPedFrozen(CClientPed& Ped, bool& bFrozen); static bool GetPedOccupiedVehicleSeat(CClientPed& Ped, uint& uiSeat); - static CClientVehicle* GetPedNearestCarEntryPoint(CClientPed& Ped, bool bCheckDriverDoor, bool bCheckPassengersDoors, uint& uiEntryPoint, CVector& vecClosestDoorPosition); + static CClientVehicle* GetPedNearestVehicleEntryPoint(CClientPed& Ped, bool bCheckDriverDoor, bool bCheckPassengersDoors, uint& uiEntryPoint, CVector& vecClosestDoorPosition); static bool IsPedFootBloodEnabled(CClientPed& Ped, bool& bHasFootBlood); static bool GetPedCameraRotation(CClientPed& Ped, float& fRotation); static bool GetPedWeaponMuzzlePosition(CClientPed& Ped, CVector& vecPosition); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index d1d0434bad9..e390f585e2d 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -43,7 +43,7 @@ void CLuaPedDefs::LoadFunctions(void) {"getPedTotalAmmo", GetPedTotalAmmo}, {"getPedOccupiedVehicle", GetPedOccupiedVehicle}, {"getPedOccupiedVehicleSeat", GetPedOccupiedVehicleSeat}, - {"getPedNearestCarEntryPoint", GetPedNearestCarEntryPoint}, + {"getPedNearestVehicleEntryPoint", GetPedNearestVehicleEntryPoint}, {"getPedArmor", GetPedArmor}, {"isPedChoking", IsPedChoking}, {"isPedDucked", IsPedDucked}, @@ -128,7 +128,7 @@ void CLuaPedDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getMoveState", "getPedMoveState"); lua_classfunction(luaVM, "getOccupiedVehicle", "getPedOccupiedVehicle"); lua_classfunction(luaVM, "getOccupiedVehicleSeat", "getPedOccupiedVehicleSeat"); - lua_classfunction(luaVM, "getNearestCarEntryPoint", OOP_GetPedNearestCarEntryPoint); + lua_classfunction(luaVM, "getNearestVehicleEntryPoint", OOP_GetPedNearestVehicleEntryPoint); lua_classfunction(luaVM, "getOxygenLevel", "getPedOxygenLevel"); lua_classfunction(luaVM, "getStat", "getPedStat"); lua_classfunction(luaVM, "getTarget", "getPedTarget"); @@ -491,7 +491,7 @@ int CLuaPedDefs::GetPedOccupiedVehicleSeat(lua_State* luaVM) return 1; } -int CLuaPedDefs::GetPedNearestCarEntryPoint(lua_State* luaVM) +int CLuaPedDefs::GetPedNearestVehicleEntryPoint(lua_State* luaVM) { // Verify the argument CClientPed* pPed = NULL; @@ -507,8 +507,8 @@ int CLuaPedDefs::GetPedNearestCarEntryPoint(lua_State* luaVM) unsigned int uiEntryPoint; CVector vecClosestDoorPosition; - CClientVehicle* pVehicle = CStaticFunctionDefinitions::GetPedNearestCarEntryPoint(*pPed, bCheckDriverDoor, bCheckPassengersDoors, - uiEntryPoint, vecClosestDoorPosition); + CClientVehicle* pVehicle = CStaticFunctionDefinitions::GetPedNearestVehicleEntryPoint(*pPed, bCheckDriverDoor, bCheckPassengersDoors, + uiEntryPoint, vecClosestDoorPosition); if (pVehicle) { @@ -528,7 +528,7 @@ int CLuaPedDefs::GetPedNearestCarEntryPoint(lua_State* luaVM) return 1; } -int CLuaPedDefs::OOP_GetPedNearestCarEntryPoint(lua_State* luaVM) +int CLuaPedDefs::OOP_GetPedNearestVehicleEntryPoint(lua_State* luaVM) { // Verify the argument CClientPed* pPed = NULL; @@ -544,8 +544,8 @@ int CLuaPedDefs::OOP_GetPedNearestCarEntryPoint(lua_State* luaVM) unsigned int uiEntryPoint; CVector vecClosestDoorPosition; - CClientVehicle* pVehicle = CStaticFunctionDefinitions::GetPedNearestCarEntryPoint(*pPed, bCheckDriverDoor, bCheckPassengersDoors, - uiEntryPoint, vecClosestDoorPosition); + CClientVehicle* pVehicle = CStaticFunctionDefinitions::GetPedNearestVehicleEntryPoint(*pPed, bCheckDriverDoor, bCheckPassengersDoors, + uiEntryPoint, vecClosestDoorPosition); if (pVehicle) { diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index dbcef96daba..b7ad00cb716 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -36,7 +36,7 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(GetPedStat); LUA_DECLARE(GetPedOccupiedVehicle); LUA_DECLARE(GetPedOccupiedVehicleSeat); - LUA_DECLARE_OOP(GetPedNearestCarEntryPoint); + LUA_DECLARE_OOP(GetPedNearestVehicleEntryPoint); LUA_DECLARE(GetPedArmor); LUA_DECLARE(IsPedChoking); LUA_DECLARE(IsPedDucked); From b737666d3c95c75803e9439e212c478db08c1539 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Sun, 21 Oct 2018 00:21:08 -0600 Subject: [PATCH 06/15] Added "setPedEnterVehicle" and "setPedLeaveVehicle" to control client-side ped (and player) entering/leaving cars. Added new events "onClientPedStartEnterVehicle", "onClientPedStartExitVehicle", "onClientPedEnterVehicle" and "onClientPedExitVehicle". Added proper support for "onClientPedEnterVehicle" and "onClientPedExitVehicle" events. Split up player enter/leave functions into new functions. Restricted "getPedNearestVehicleEntryPoint" only to local peds and player. --- Client/mods/deathmatch/logic/CClientGame.cpp | 396 +++++++++++++----- Client/mods/deathmatch/logic/CClientGame.h | 12 +- Client/mods/deathmatch/logic/CClientPed.cpp | 276 ++++++++++++ Client/mods/deathmatch/logic/CClientPed.h | 19 + .../logic/CStaticFunctionDefinitions.cpp | 92 ++++ .../logic/CStaticFunctionDefinitions.h | 4 +- .../deathmatch/logic/luadefs/CLuaPedDefs.cpp | 53 ++- .../deathmatch/logic/luadefs/CLuaPedDefs.h | 2 + 8 files changed, 747 insertions(+), 107 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index d352078b1e3..1b3d1c8b73c 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -1538,10 +1538,11 @@ void CClientGame::UpdateVehicleInOut(void) if (m_bIsGettingOutOfVehicle) { // If we aren't working on leaving the car (he's eiter finished or cancelled/failed leaving) - if (!m_pLocalPlayer->IsLeavingVehicle()) + if (!m_pLocalPlayer->IsLeavingVehicle() && !m_pLocalPlayer->IsGettingJacked()) { // Are we outside the car? CClientVehicle* pVehicle = m_pLocalPlayer->GetRealOccupiedVehicle(); + if (!pVehicle) { // Check if vehicle isn't local. @@ -1592,7 +1593,7 @@ void CClientGame::UpdateVehicleInOut(void) // Reset the vehicle in out stuff so we're ready for another car entry/leave. // Don't allow a new entry/leave until we've gotten the notify return packet ElementID ReasonVehicleID = m_VehicleInOutID; - g_pClientGame->ResetVehicleInOut(); + ResetVehicleInOut(); if (!pInOutVehicle->IsLocalEntity()) { @@ -1611,10 +1612,16 @@ void CClientGame::UpdateVehicleInOut(void) Arguments.PushElement(m_pLocalPlayer); Arguments.PushNumber(ucSeat); pInOutVehicle->CallEvent("onClientVehicleExit", Arguments, true); + + Arguments.DeleteArguments(); + Arguments.PushElement(pInOutVehicle); + Arguments.PushNumber(ucSeat); + + m_pLocalPlayer->CallEvent("onClientPlayerVehicleExit", Arguments, true); } } // Are we still inside the car? - else + else if(!pVehicle->IsLocalEntity()) { // Warp us out now to keep in sync with the server m_pLocalPlayer->RemoveFromVehicle(); @@ -1794,6 +1801,12 @@ void CClientGame::UpdateVehicleInOut(void) Arguments.PushElement(m_pLocalPlayer); Arguments.PushNumber(ucSeat); pInOutVehicle->CallEvent("onClientVehicleEnter", Arguments, true); + + Arguments.DeleteArguments(); + Arguments.PushElement(pInOutVehicle); + Arguments.PushNumber(ucSeat); + + m_pLocalPlayer->CallEvent("onClientPlayerVehicleEnter", Arguments, true); } } } @@ -1855,6 +1868,8 @@ void CClientGame::UpdateVehicleInOut(void) } } + ResetVehicleInOut(); + if (!pOccupiedVehicle->IsLocalEntity()) { // We're not allowed to enter any vehicle before we get a confirm @@ -1875,6 +1890,12 @@ void CClientGame::UpdateVehicleInOut(void) Arguments.PushNumber(m_pLocalPlayer->GetOccupiedVehicleSeat()); pOccupiedVehicle->CallEvent("onClientVehicleExit", Arguments, true); + Arguments.DeleteArguments(); + Arguments.PushElement(pOccupiedVehicle); + Arguments.PushNumber(m_pLocalPlayer->GetOccupiedVehicleSeat()); + + m_pLocalPlayer->CallEvent("onClientPlayerVehicleExit", Arguments, true); + CClientVehicle::UnpairPedAndVehicle(m_pLocalPlayer, pOccupiedVehicle); } } @@ -2835,6 +2856,10 @@ void CClientGame::AddBuiltInEvents(void) m_Events.AddEvent("onClientPedChoke", "", NULL, false); m_Events.AddEvent("onClientPedHeliKilled", "heli", NULL, false); m_Events.AddEvent("onClientPedHitByWaterCannon", "vehicle", NULL, false); + m_Events.AddEvent("onClientPedEnterVehicle", "ped, seat, jacking", NULL, false); + m_Events.AddEvent("onClientPedExitVehicle", "ped, seat, jacker", NULL, false); + m_Events.AddEvent("onClientPedStartEnterVehicle", "ped, seat, door, jacking", NULL, false); + m_Events.AddEvent("onClientPedStartExitVehicle", "ped, seat, door, jacker", NULL, false); // Vehicle events m_Events.AddEvent("onClientVehicleRespawn", "", NULL, false); @@ -4506,6 +4531,14 @@ bool CClientGame::ApplyPedDamageFromGame(eWeaponType weaponUsed, float fDamage, AnimationId animID; GetDeathAnim(pDamagedPed, pEvent, animGroup, animID); pDamagedPed->Kill(weaponUsed, hitZone, false, false, animGroup, animID); + + CClientVehicle* pOccupiedVehicle = pDamagedPed->GetOccupiedVehicle(); + + if (pOccupiedVehicle) + { + pOccupiedVehicle->UnpairPedAndVehicle(pDamagedPed); + } + return true; } if (fPreviousHealth > 0.0f) @@ -4564,8 +4597,20 @@ void CClientGame::DeathHandler(CPed* pKilledPedSA, unsigned char ucDeathReason, pKilledPed->CallEvent("onClientPedWasted", Arguments, true); - // Notify the server - SendPedWastedPacket(pKilledPed, INVALID_ELEMENT_ID, ucDeathReason, ucBodyPart); + if (!pKilledPed->IsLocalEntity()) + { + // Notify the server + SendPedWastedPacket(pKilledPed, INVALID_ELEMENT_ID, ucDeathReason, ucBodyPart); + } + else + { + CClientVehicle* pOccupiedVehicle = pKilledPed->GetOccupiedVehicle(); + + if (pOccupiedVehicle) + { + pOccupiedVehicle->UnpairPedAndVehicle(pKilledPed); + } + } } bool CClientGame::VehicleCollisionHandler(CVehicleSAInterface* pCollidingVehicle, CEntitySAInterface* pCollidedWith, int iModelIndex, float fDamageImpulseMag, @@ -4983,7 +5028,7 @@ bool CClientGame::ProcessMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPa return false; } -void CClientGame::ProcessVehicleInOutKey(bool bPassenger) +bool CClientGame::ProcessExitVehicle() { // Are we already sending an in/out request or not allowed to create a new in/out? if (m_bNoNewVehicleTask // Are we permitted to even enter a vehicle? @@ -4992,9 +5037,9 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) || m_bIsGettingIntoVehicle // We can't enter a vehicle we're currently entering... || m_bIsGettingOutOfVehicle // We can't enter a vehicle we're currently leaving... || CClientTime::GetTime() < m_ulLastVehicleInOutTime + VEHICLE_INOUT_DELAY // We are trying to enter the vehicle to soon - ) + ) { - return; + return false; } // Reset the "is jacking" bit @@ -5004,87 +5049,120 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) if (!m_pLocalPlayer) { // No local player. Stop. - return; + return false; } - // If the player is in a vehicle we need to leave the vehicle. CClientVehicle* pOccupiedVehicle = m_pLocalPlayer->GetOccupiedVehicle(); - if (pOccupiedVehicle) + + if (!pOccupiedVehicle) { - // Only let us leave the vehicle if: - // - we press F (as driver) - // - we press either F or G as a passenger - if (bPassenger && m_pLocalPlayer->GetOccupiedVehicleSeat() == 0) - { - // Driver pressed G, so stop. - return; - } + return false; + } - unsigned char ucDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(m_pLocalPlayer->GetGamePlayer(), pOccupiedVehicle->GetGameVehicle()); + unsigned char ucDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(m_pLocalPlayer->GetGamePlayer(), pOccupiedVehicle->GetGameVehicle()); - if (pOccupiedVehicle->IsLocalEntity()) - { - unsigned char ucSeat = m_pLocalPlayer->GetOccupiedVehicleSeat(); - m_VehicleInOutID = pOccupiedVehicle->GetID(); - m_ucVehicleInOutSeat = ucSeat; + if (pOccupiedVehicle->IsLocalEntity()) + { + unsigned char ucSeat = m_pLocalPlayer->GetOccupiedVehicleSeat(); + m_VehicleInOutID = pOccupiedVehicle->GetID(); + m_ucVehicleInOutSeat = ucSeat; - m_VehicleInOutID = pOccupiedVehicle->GetID(); - m_bIsGettingOutOfVehicle = true; - m_ulLastVehicleInOutTime = CClientTime::GetTime(); + m_VehicleInOutID = pOccupiedVehicle->GetID(); + m_bIsGettingOutOfVehicle = true; + m_ulLastVehicleInOutTime = CClientTime::GetTime(); - if (ucDoor >= 2 && ucDoor <= 5) - { - ucDoor -= 2; - } + if (ucDoor >= 2 && ucDoor <= 5) + { + ucDoor -= 2; + } - m_pLocalPlayer->GetOutOfVehicle(ucDoor); - m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_OUT); + m_pLocalPlayer->GetOutOfVehicle(ucDoor); + m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_OUT); - CLuaArguments Arguments; - Arguments.PushElement(m_pLocalPlayer); - Arguments.PushNumber(ucSeat); - Arguments.PushNumber(ucDoor); - pOccupiedVehicle->CallEvent("onClientVehicleStartExit", Arguments, true); + CLuaArguments Arguments; + Arguments.PushElement(m_pLocalPlayer); + Arguments.PushNumber(ucSeat); + Arguments.PushNumber(ucDoor); + pOccupiedVehicle->CallEvent("onClientVehicleStartExit", Arguments, true); - return; - } + return true; + } - // We're about to exit a vehicle - // Send an in request - NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); - if (!pBitStream) - { - return; - } + // We're about to exit a vehicle + // Send an in request + NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); + if (!pBitStream) + { + return false; + } - // Write the vehicle id to it and that we're requesting to get out of it - pBitStream->Write(pOccupiedVehicle->GetID()); - unsigned char ucAction = static_cast(VEHICLE_REQUEST_OUT); - pBitStream->WriteBits(&ucAction, 4); + // Write the vehicle id to it and that we're requesting to get out of it + pBitStream->Write(pOccupiedVehicle->GetID()); + unsigned char ucAction = static_cast(VEHICLE_REQUEST_OUT); + pBitStream->WriteBits(&ucAction, 4); - if (ucDoor >= 2 && ucDoor <= 5) - { - ucDoor -= 2; - pBitStream->WriteBits(&ucDoor, 2); - } + if (ucDoor >= 2 && ucDoor <= 5) + { + ucDoor -= 2; + pBitStream->WriteBits(&ucDoor, 2); + } - // Send and destroy it - g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); - g_pNet->DeallocateNetBitStream(pBitStream); + // Send and destroy it + g_pNet->SendPacket(PACKET_ID_VEHICLE_INOUT, pBitStream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(pBitStream); - // We're now exiting a vehicle - m_bIsGettingOutOfVehicle = true; - m_ulLastVehicleInOutTime = CClientTime::GetTime(); + // We're now exiting a vehicle + m_bIsGettingOutOfVehicle = true; + m_ulLastVehicleInOutTime = CClientTime::GetTime(); #ifdef MTA_DEBUG - g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_request_out"); + g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_request_out"); #endif - return; + + return true; +} + +bool CClientGame::ProcessEnterVehicle(CClientVehicle* pVehicle, unsigned int uiSeat, unsigned int uiDoor) +{ + // Are we already sending an in/out request or not allowed to create a new in/out? + if (m_bNoNewVehicleTask // Are we permitted to even enter a vehicle? + || m_VehicleInOutID != INVALID_ELEMENT_ID // Make sure we're not already processing a vehicle enter (would refer to valid ID if we were) + || m_bIsGettingJacked // Make sure we're not currently getting carjacked && + || m_bIsGettingIntoVehicle // We can't enter a vehicle we're currently entering... + || m_bIsGettingOutOfVehicle // We can't enter a vehicle we're currently leaving... + || CClientTime::GetTime() < m_ulLastVehicleInOutTime + VEHICLE_INOUT_DELAY // We are trying to enter the vehicle to soon + ) + { + return false; } - // - // We're going to enter a vehicle - // + // Reset the "is jacking" bit + m_bIsJackingVehicle = false; + + // Got a local player model? + if (!m_pLocalPlayer) + { + // No local player. Stop. + return false; + } + + if (!pVehicle || !pVehicle->IsEnterable()) + { + // Stop if there isn't a vehicle, or the vehicle is not enterable + return false; + } + + CVector vecPlayerPosition; + CVector vecVehiclePosition; + + m_pLocalPlayer->GetPosition(vecPlayerPosition); + pVehicle->GetPosition(vecVehiclePosition); + + // Check if we are too far away from the vehicle. + if (DistanceBetweenPoints3D(vecPlayerPosition, vecVehiclePosition) > 20.0f) + { + return false; + } // If the Jump task is playing and we are in water - I know right // Kill the task. @@ -5092,10 +5170,9 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) CTask* pTask = m_pLocalPlayer->GetCurrentPrimaryTask(); if (pTask && pTask->GetTaskType() == TASK_COMPLEX_JUMP) // Kill jump task - breaks warp in entry and doesn't really matter { - CClientVehicle* pVehicle = m_pLocalPlayer->GetClosestVehicleInRange(true, !bPassenger, bPassenger, false, nullptr, nullptr, 20.0f); if (pVehicle && (pVehicle->IsInWater() || - m_pLocalPlayer->IsInWater())) // Make sure we are about to warp in (this bug only happens when someone jumps into water with a vehicle) + m_pLocalPlayer->IsInWater())) // Make sure we are about to warp in (this bug only happens when someone jumps into water with a vehicle) { m_pLocalPlayer->KillTask(3, true); // Kill jump task if we are about to warp in } @@ -5107,7 +5184,7 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) if (m_pLocalPlayer->GetCurrentPrimaryTask()) { // We already have a primary task, so stop. - return; + return false; } // Are we holding the aim_weapon key? @@ -5115,45 +5192,22 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) if (pBind && pBind->bState) { // Stop because the player is probably using rshift + f/g - return; + return false; } if (m_pLocalPlayer->IsClimbing() // Make sure we're not currently climbing || m_pLocalPlayer->HasJetPack() // Make sure we don't have a jetpack || m_pLocalPlayer->IsUsingGun() // Make sure we're not using a gun (have the gun task active) - we stop it in UpdatePlayerTasks anyway || m_pLocalPlayer->IsRunningAnimation() // Make sure we aren't running an animation - ) + ) { - return; - } - - // Grab the closest vehicle - unsigned int uiDoor = 0; - CClientVehicle* pVehicle = m_pLocalPlayer->GetClosestVehicleInRange(true, !bPassenger, bPassenger, false, &uiDoor, nullptr, 20.0f); - unsigned int uiSeat = uiDoor; - - if (bPassenger && uiDoor == 0) - { - // We're trying to enter as a passenger, yet our closest door - // is the driver's door. Force an enter for the passenger seat. - uiSeat = 1; - } - else if (!bPassenger) - { - // We want to drive. Force our seat to the driver's seat. - uiSeat = 0; - } - - if (!pVehicle || !pVehicle->IsEnterable()) - { - // Stop if there isn't a vehicle, or the vehicle is not enterable - return; + return false; } // If the vehicle's a boat, make sure we're standing on it (we need a dif task to enter boats properly) if (pVehicle->GetVehicleType() == CLIENTVEHICLE_BOAT && m_pLocalPlayer->GetContactEntity() != pVehicle) { - return; + return false; } // Call the onClientVehicleStartEnter event for remote players @@ -5166,38 +5220,67 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) if (!pVehicle->CallEvent("onClientVehicleStartEnter", Arguments, true)) { // Event has been cancelled - return; + return false; } if (pVehicle->IsLocalEntity()) { + CClientPed* pOccupyingPed = pVehicle->GetOccupant(uiSeat); + + if (pOccupyingPed) + { + unsigned char ucOccupyingDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(pOccupyingPed->GetGamePlayer(), pVehicle->GetGameVehicle()); + unsigned char ucOccupyingSeat = pOccupyingPed->GetOccupiedVehicleSeat(); + + if (ucOccupyingDoor >= 2 && ucOccupyingDoor <= 5) + { + ucOccupyingDoor -= 2; + } + + CLuaArguments ExitArguments; + ExitArguments.PushElement(pOccupyingPed); // ped + ExitArguments.PushNumber(ucOccupyingSeat); // seat + ExitArguments.PushNumber(ucOccupyingDoor); // door + + ExitArguments.PushElement(m_pLocalPlayer); // ped that is carjacking. + + if (!pVehicle->CallEvent("onClientPedStartExitVehicle", ExitArguments, true)) + { + // Event has been cancelled + return false; + } + } + m_VehicleInOutID = pVehicle->GetID(); m_ucVehicleInOutSeat = uiSeat; m_VehicleInOutID = pVehicle->GetID(); m_bIsGettingIntoVehicle = true; m_ulLastVehicleInOutTime = CClientTime::GetTime(); - + m_pLocalPlayer->GetIntoVehicle(pVehicle, uiSeat, uiDoor); - CClientPed* pOccupyingPed = pVehicle->GetOccupant(uiSeat); - if (pOccupyingPed) { m_bIsJackingVehicle = true; + + pOccupyingPed->SetJacker(m_pLocalPlayer); m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_JACKING); pOccupyingPed->SetVehicleInOutState(VEHICLE_INOUT_GETTING_JACKED); + + CClientVehicle::SetPedOccupiedVehicle(pOccupyingPed, pVehicle, uiSeat, uiDoor); + CClientVehicle::SetPedOccupyingVehicle(pOccupyingPed, pVehicle, uiSeat, uiDoor); } else { m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN); } - return; + return true; } // Send an in request NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); if (!pBitStream) { - return; + return false; } // Write the vehicle id to it and that we're requesting to get into it @@ -5222,6 +5305,111 @@ void CClientGame::ProcessVehicleInOutKey(bool bPassenger) #ifdef MTA_DEBUG g_pCore->GetConsole()->Printf("* Sent_InOut: vehicle_request_in"); #endif + + return true; +} + +void CClientGame::ProcessVehicleInOutKey(bool bPassenger) +{ + // Are we already sending an in/out request or not allowed to create a new in/out? + if (m_bNoNewVehicleTask // Are we permitted to even enter a vehicle? + || m_VehicleInOutID != INVALID_ELEMENT_ID // Make sure we're not already processing a vehicle enter (would refer to valid ID if we were) + || m_bIsGettingJacked // Make sure we're not currently getting carjacked && + || m_bIsGettingIntoVehicle // We can't enter a vehicle we're currently entering... + || m_bIsGettingOutOfVehicle // We can't enter a vehicle we're currently leaving... + || CClientTime::GetTime() < m_ulLastVehicleInOutTime + VEHICLE_INOUT_DELAY // We are trying to enter the vehicle to soon + ) + { + return; + } + + // Got a local player model? + if (!m_pLocalPlayer) + { + // No local player. Stop. + return; + } + + // If the player is in a vehicle we need to leave the vehicle. + CClientVehicle* pOccupiedVehicle = m_pLocalPlayer->GetOccupiedVehicle(); + if (pOccupiedVehicle) + { + // Only let us leave the vehicle if: + // - we press F (as driver) + // - we press either F or G as a passenger + if (bPassenger && m_pLocalPlayer->GetOccupiedVehicleSeat() == 0) + { + // Driver pressed G, so stop. + return; + } + + ProcessExitVehicle(); + return; + } + + // + // We're going to enter a vehicle + // + + // If the Jump task is playing and we are in water - I know right + // Kill the task. + // + CTask* pTask = m_pLocalPlayer->GetCurrentPrimaryTask(); + if (pTask && pTask->GetTaskType() == TASK_COMPLEX_JUMP) // Kill jump task - breaks warp in entry and doesn't really matter + { + CClientVehicle* pVehicle = m_pLocalPlayer->GetClosestVehicleInRange(true, !bPassenger, bPassenger, false, nullptr, nullptr, 20.0f); + if (pVehicle && + (pVehicle->IsInWater() || + m_pLocalPlayer->IsInWater())) // Make sure we are about to warp in (this bug only happens when someone jumps into water with a vehicle) + { + m_pLocalPlayer->KillTask(3, true); // Kill jump task if we are about to warp in + } + } + + // Make sure we don't have any other primary tasks running, otherwise our 'enter-vehicle' + // task will replace it and fuck it up! + // + if (m_pLocalPlayer->GetCurrentPrimaryTask()) + { + // We already have a primary task, so stop. + return; + } + + // Are we holding the aim_weapon key? + SBindableGTAControl* pBind = g_pCore->GetKeyBinds()->GetBindableFromControl("aim_weapon"); + if (pBind && pBind->bState) + { + // Stop because the player is probably using rshift + f/g + return; + } + + if (m_pLocalPlayer->IsClimbing() // Make sure we're not currently climbing + || m_pLocalPlayer->HasJetPack() // Make sure we don't have a jetpack + || m_pLocalPlayer->IsUsingGun() // Make sure we're not using a gun (have the gun task active) - we stop it in UpdatePlayerTasks anyway + || m_pLocalPlayer->IsRunningAnimation() // Make sure we aren't running an animation + ) + { + return; + } + + // Grab the closest vehicle + unsigned int uiDoor = 0; + CClientVehicle* pVehicle = m_pLocalPlayer->GetClosestVehicleInRange(true, !bPassenger, bPassenger, false, &uiDoor, nullptr, 20.0f); + unsigned int uiSeat = uiDoor; + + if (bPassenger && uiDoor == 0) + { + // We're trying to enter as a passenger, yet our closest door + // is the driver's door. Force an enter for the passenger seat. + uiSeat = 1; + } + else if (!bPassenger) + { + // We want to drive. Force our seat to the driver's seat. + uiSeat = 0; + } + + ProcessEnterVehicle(pVehicle, uiSeat, uiDoor); } // Shot compensation (Jax): diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index a4b25bf47f0..196b2808d1e 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -340,6 +340,8 @@ class CClientGame bool GetDamageSent(void) { return m_bDamageSent; } void SetDamageSent(bool b) { m_bDamageSent = b; } + bool ProcessExitVehicle(); + bool ProcessEnterVehicle(CClientVehicle* pVehicle, unsigned int uiSeat, unsigned int uiDoor); void ProcessVehicleInOutKey(bool bPassenger); void ResetVehicleInOut(void); @@ -587,6 +589,14 @@ class CClientGame void SendFireSync(CFire* pFire); void SendProjectileSync(CClientProjectile* pProjectile); + void SetGettingOutOfVehicle(bool bGettingOutOfVehicle) { m_bIsGettingOutOfVehicle = bGettingOutOfVehicle; }; + void SetGettingIntoVehicle(bool bGettingIntoVehicle) { m_bIsGettingIntoVehicle = bGettingIntoVehicle; }; + void SetVehicleInOutID(ElementID vehicleInOutID) { m_VehicleInOutID = vehicleInOutID; }; + void SetVehicleInOutSeat(unsigned char ucVehicleInOutSeat) { m_ucVehicleInOutSeat = ucVehicleInOutSeat; }; + + void SetGettingJacked(bool bIsGettingJacked) { m_bIsGettingJacked = bIsGettingJacked; }; + void SetGettingJackedBy(CClientPed* pJacker) { m_pGettingJackedBy = pJacker; }; + void SetServerVersionSortable(const SString& strVersion) { m_strServerVersionSortable = strVersion; } const SString& GetServerVersionSortable(void) { return m_strServerVersionSortable; } @@ -714,7 +724,7 @@ class CClientGame unsigned char m_ucVehicleInOutSeat; bool m_bNoNewVehicleTask; ElementID m_NoNewVehicleTaskReasonID; - CClientPlayer* m_pGettingJackedBy; + CClientPed* m_pGettingJackedBy; CEntity* m_pTargetedGameEntity; CClientEntity* m_pTargetedEntity; diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index e6230bc12ef..1d48c4ef94c 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -1295,6 +1295,197 @@ bool CClientPed::GetClosestDoor(CClientVehicle* pVehicle, bool bCheckDriverDoor, return false; } +bool CClientPed::GracefullyEnterCar(CClientVehicle* pVehicle, unsigned int uiSeat, unsigned int uiDoor) +{ + // Check if we are already entering a vehicle or are already in a vehicle. + // Player leaves should be handled in CClientGame instead. + if (IsEnteringVehicle() || IsInVehicle() || IsLocalPlayer() || !IsLocalEntity()) + { + return false; + } + + if (!pVehicle || !pVehicle->IsEnterable()) + { + // Stop if there isn't a vehicle, or the vehicle is not enterable + return false; + } + + CVector vecPedPosition; + CVector vecVehiclePosition; + + GetPosition(vecPedPosition); + pVehicle->GetPosition(vecVehiclePosition); + + // Check if the is too far away from the vehicle. + if (DistanceBetweenPoints3D(vecPedPosition, vecVehiclePosition) > 20.0f) + { + return false; + } + + // Make sure the ped doesn't have any other primary tasks running, otherwise our 'enter-vehicle' + // task will replace it and fuck it up! + // + if (GetCurrentPrimaryTask()) + { + // We already have a primary task, so stop. + return false; + } + + if (IsClimbing() // Make sure we're not currently climbing + || HasJetPack() // Make sure we don't have a jetpack + || IsUsingGun() // Make sure we're not using a gun (have the gun task active) + || IsRunningAnimation() // Make sure we aren't running an animation + ) + { + return false; + } + + // If the vehicle's a boat, make sure we're standing on it (we need a dif task to enter boats properly) + if (pVehicle->GetVehicleType() == CLIENTVEHICLE_BOAT && GetContactEntity() != pVehicle) + { + return false; + } + + m_ucEnteringDoor = uiDoor; + m_uiInOutSeat = uiSeat; + + CClientPed* pOccupyingPed = pVehicle->GetOccupant(uiSeat); + + CLuaArguments Arguments; + Arguments.PushElement(this); // ped + Arguments.PushNumber(uiSeat); // seat + Arguments.PushNumber(uiDoor); // Door + + if (pOccupyingPed) + { + Arguments.PushElement(pOccupyingPed); // ped being jacked + } + + if (!this->CallEvent("onClientPedStartEnterVehicle", Arguments, true)) + { + // Event has been cancelled + return false; + } + + if (pOccupyingPed) + { + unsigned char ucOccupyingDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(pOccupyingPed->GetGamePlayer(), pVehicle->GetGameVehicle()); + unsigned char ucOccupyingSeat = pOccupyingPed->GetOccupiedVehicleSeat(); + + if (ucOccupyingDoor >= 2 && ucOccupyingDoor <= 5) + { + ucOccupyingDoor -= 2; + } + + CLuaArguments ExitArguments; + ExitArguments.PushElement(pOccupyingPed); // ped + ExitArguments.PushNumber(ucOccupyingSeat); // seat + ExitArguments.PushNumber(ucOccupyingDoor); // door + + if (pOccupyingPed->IsLocalPlayer()) + { + if (!pVehicle->CallEvent("onClientVehicleStartExit", ExitArguments, true)) + { + // Event has been cancelled + return false; + } + } + else + { + ExitArguments.PushElement(this); // ped that is carjacking. + + if (!this->CallEvent("onClientPedStartExitVehicle", ExitArguments, true)) + { + // Event has been cancelled + return false; + } + } + } + + SetEnteringVehicle(true); + SetInOutVehicle(pVehicle); + + GetIntoVehicle(pVehicle, uiSeat, uiDoor); + + if (pOccupyingPed) { + SetVehicleInOutState(VEHICLE_INOUT_JACKING); + pOccupyingPed->SetVehicleInOutState(VEHICLE_INOUT_GETTING_JACKED); + + if (pOccupyingPed->IsLocalPlayer()) + { + g_pClientGame->SetGettingJacked(true); + g_pClientGame->SetGettingJackedBy(this); + g_pClientGame->SetGettingOutOfVehicle(true); + g_pClientGame->SetVehicleInOutID(pVehicle->GetID()); + g_pClientGame->SetVehicleInOutSeat(uiSeat); + } + else + { + pOccupyingPed->SetJacker(this); + } + + this->SetJacking(pOccupyingPed); + + // We haven't yet entered the car. The ped being carjacked is still occopying it. + // Workaround for early-unpair issue. + CClientVehicle::SetPedOccupiedVehicle(pOccupyingPed, pVehicle, uiSeat, uiDoor); + CClientVehicle::SetPedOccupyingVehicle(pOccupyingPed, pVehicle, uiSeat, uiDoor); + + + } else { + SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN); + } + + return true; +} + +bool CClientPed::GracefullyExitCar() +{ + // Check if we are already leaving a vehicle or aren't in a vehicle. + // Player leaves should be handled in CClientGame instead. + if (IsLeavingVehicle() || !IsInVehicle() || IsLocalPlayer() || !IsLocalEntity()) + { + return false; + } + + CClientVehicle* pOccupiedVehicle = GetOccupiedVehicle(); + + if (!pOccupiedVehicle) + { + return false; + } + + unsigned char ucDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(GetGamePlayer(), pOccupiedVehicle->GetGameVehicle()); + unsigned char ucSeat = GetOccupiedVehicleSeat(); + + if (ucDoor >= 2 && ucDoor <= 5) + { + ucDoor -= 2; + } + + CLuaArguments Arguments; + Arguments.PushElement(this); // ped + Arguments.PushNumber(ucSeat); // seat + Arguments.PushNumber(ucDoor); // Door + + if (!this->CallEvent("onClientPedStartExitVehicle", Arguments, true)) + { + // Event has been cancelled + return false; + } + + m_ucLeavingDoor = ucDoor; + m_uiInOutSeat = GetOccupiedVehicleSeat(); + + SetLeavingVehicle(true); + SetInOutVehicle(pOccupiedVehicle); + + GetOutOfVehicle(ucDoor); + SetVehicleInOutState(VEHICLE_INOUT_GETTING_OUT); + + return true; +} + void CClientPed::GetOutOfVehicle(unsigned char ucDoor) { if (ucDoor != 0xFF) @@ -2628,6 +2819,90 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses) // ControllerState checks and fixes are done at the same same as everything else unless using alt pulse order bool bDoControllerStateFixPulse = g_pClientGame->IsUsingAlternatePulseOrder() ? !bDoStandardPulses : bDoStandardPulses; + if (IsLocalEntity()) + { + // Are we being carjacked? + if (!m_bIsLeavingVehicle && (IsGettingJacked() || IsLeavingVehicle())) + { + CClientPed* pJacker = GetJacker(); + CClientVehicle* pOccupiedVehicle = GetOccupiedVehicle(); + + if (pJacker && pOccupiedVehicle) + { + unsigned char ucDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(GetGamePlayer(), pOccupiedVehicle->GetGameVehicle()); + unsigned char ucSeat = GetOccupiedVehicleSeat(); + + if (ucDoor >= 2 && ucDoor <= 5) + { + ucDoor -= 2; + } + + m_ucLeavingDoor = ucDoor; + m_uiInOutSeat = GetOccupiedVehicleSeat(); + + SetLeavingVehicle(true); + SetInOutVehicle(pOccupiedVehicle); + + SetVehicleInOutState(VEHICLE_INOUT_GETTING_OUT); + } + } + + if (m_bIsLeavingVehicle && !IsLeavingVehicle() && !IsGettingJacked() && !IsGettingOutOfVehicle() && m_pInOutVehicle != NULL) + { + m_pInOutVehicle->UnpairPedAndVehicle(this); + m_pOccupyingVehicle = NULL; + + m_pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); + m_pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); + + CLuaArguments Arguments; + Arguments.PushElement(this); // ped + Arguments.PushNumber(m_uiInOutSeat); // seat + + if (GetJacker()) + { + Arguments.PushElement(GetJacker()); // ped who has carjacked us + } + + this->CallEvent("onClientPedExitVehicle", Arguments, true); + + m_pInOutVehicle = NULL; + m_bIsLeavingVehicle = false; + m_uiInOutSeat = NULL; + m_ucLeavingDoor = NULL; + SetJacker(NULL); + SetJacking(NULL); + } + + if (m_bIsEnteringVehicle && !IsEnteringVehicle() && !IsGettingIntoVehicle() && m_pInOutVehicle != NULL) + { + CClientVehicle::SetPedOccupiedVehicle(this, m_pInOutVehicle, m_uiInOutSeat, m_ucEnteringDoor); + CClientVehicle::SetPedOccupyingVehicle(this, m_pInOutVehicle, m_uiInOutSeat, m_ucEnteringDoor); + + m_pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); + m_pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); + + CLuaArguments Arguments; + Arguments.PushElement(this); // ped + Arguments.PushNumber(m_uiInOutSeat); // seat + + if (GetJacking()) + { + Arguments.PushElement(GetJacking()); // ped we have carjacked + } + + this->CallEvent("onClientPedEnterVehicle", Arguments, true); + + m_pInOutVehicle = NULL; + m_bIsEnteringVehicle = false; + m_uiInOutSeat = NULL; + m_ucEnteringDoor = NULL; + + SetJacker(NULL); + SetJacking(NULL); + } + } + if (!bDoStandardPulses) { if (bDoControllerStateFixPulse) @@ -4461,6 +4736,7 @@ void CClientPed::_GetIntoVehicle(CClientVehicle* pVehicle, unsigned int uiSeat, { // Create and set the get-in task CTaskComplexEnterCarAsDriver* pInTask = g_pGame->GetTasks()->CreateTaskComplexEnterCarAsDriver(pGameVehicle); + if (pInTask) { pInTask->SetTargetDoor(ucDoor); diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index e405826dee9..d5cbc1a6947 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -225,6 +225,9 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void GetIntoVehicle(CClientVehicle* pVehicle, unsigned int uiSeat = 0, unsigned char ucDoor = 0); void GetOutOfVehicle(unsigned char ucDoor); + bool GracefullyEnterCar(CClientVehicle* pVehicle, unsigned int uiSeat, unsigned int uiDoor); + bool GracefullyExitCar(); + void WarpIntoVehicle(CClientVehicle* pVehicle, unsigned int uiSeat = 0); CClientVehicle* RemoveFromVehicle(bool bIgnoreIfGettingOut = false); @@ -347,6 +350,13 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool IsInWater(void); bool IsOnGround(void); + void SetJacker(CClientPed* pJacker) { m_pJacker = pJacker; }; + void SetJacking(CClientPed* pJacking) { m_pJacking = pJacking; }; + + void SetEnteringVehicle(bool bIsEnteringVehicle) { m_bIsEnteringVehicle -= bIsEnteringVehicle; }; + void SetLeavingVehicle(bool bIsLeavingVehicle) { m_bIsLeavingVehicle = bIsLeavingVehicle; }; + void SetInOutVehicle(CClientVehicle* pVehicle) { m_pInOutVehicle = pVehicle; }; + bool IsClimbing(void); bool IsRadioOn(void) { return m_bRadioOn; }; void NextRadioChannel(void); @@ -383,6 +393,9 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool IsGettingOutOfVehicle(void); bool IsGettingJacked(void); + CClientPed* GetJacker(void) { return m_pJacker; }; + CClientPed* GetJacking(void) { return m_pJacking; }; + CClientEntity* GetContactEntity(void); bool HasAkimboPointingUpwards(void); @@ -578,6 +591,12 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule unsigned long m_ulLastTimeSprintPressed; unsigned long m_ulBlockSprintReleaseTime; bool m_bWasSprintButtonDown; + CClientPed* m_pJacking; + CClientPed* m_pJacker; + bool m_bIsEnteringVehicle; + bool m_bIsLeavingVehicle; + unsigned int m_uiInOutSeat; + CClientVehicle* m_pInOutVehicle; CModelInfo* m_pLoadedModelInfo; eWeaponSlot m_pOutOfVehicleWeaponSlot; float m_fBeginAimX; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 7cbf87e5bd8..c6a5b001fe4 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1774,6 +1774,12 @@ bool CStaticFunctionDefinitions::GetPedOccupiedVehicleSeat(CClientPed& pPed, uin CClientVehicle* CStaticFunctionDefinitions::GetPedNearestVehicleEntryPoint(CClientPed& pPed, bool bCheckDriverDoor, bool bCheckPassengersDoors, uint& uiEntryPoint, CVector& vecClosestDoorPosition) { + // This function should only work on local peds. + if (!pPed.IsLocalEntity() && !pPed.IsLocalPlayer()) + { + return false; + } + if (pPed.IsInVehicle()) { // The ped is already in a car, why bother checking the nearest car seat? @@ -2434,6 +2440,92 @@ bool CStaticFunctionDefinitions::SetPedOxygenLevel(CClientEntity& Entity, float return false; } +bool CStaticFunctionDefinitions::SetPedExitVehicle(CClientPed& pPed) +{ + // This function only works on local peds. + if (!pPed.IsLocalEntity() && !pPed.IsLocalPlayer()) + { + return false; + } + + if (!pPed.GetGamePlayer()) + { + return false; + } + + // We are not inside a vehicle, how are we supposed to exit? + if (!pPed.GetOccupiedVehicle()) + { + return false; + } + + if (pPed.IsLocalPlayer()) + { + m_pClientGame->ResetVehicleInOut(); + return m_pClientGame->ProcessExitVehicle(); + } + else + { + return pPed.GracefullyExitCar(); + } + + return false; +} + +bool CStaticFunctionDefinitions::SetPedEnterVehicle(CClientPed& pPed, CClientVehicle& pVehicle, unsigned int uiSeat) +{ + // This function only works on local peds. + if (!pPed.IsLocalEntity() && !pPed.IsLocalPlayer()) + { + return false; + } + + if (!pPed.GetGamePlayer()) + { + return false; + } + + // We are already inside a vehicle. + if (pPed.GetOccupiedVehicle()) + { + return false; + } + + if (!pVehicle.IsEnterable()) + { + return false; + } + + if (pPed.IsDead() || pVehicle.GetHealth() <= 0.0f) + { + return false; + } + + // Valid seat id for that vehicle? + uchar ucMaxPassengers = CClientVehicleManager::GetMaxPassengerCount(pVehicle.GetModel()); + if (uiSeat > ucMaxPassengers || ucMaxPassengers == 255) + { + return false; + } + + if (pPed.IsLocalPlayer()) + { + m_pClientGame->ResetVehicleInOut(); + return m_pClientGame->ProcessEnterVehicle(&pVehicle, uiSeat, uiSeat); + } + else + { + if (!pVehicle.IsLocalEntity()) + { + return false; + } + + return pPed.GracefullyEnterCar(&pVehicle, uiSeat, uiSeat); + } + + return false; +} + bool CStaticFunctionDefinitions::GetBodyPartName(unsigned char ucID, SString& strOutName) { if (ucID <= 10) diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 24345cee6e4..d1227dbde5c 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -148,7 +148,7 @@ class CStaticFunctionDefinitions static bool IsPedHeadless(CClientPed& Ped, bool& bHeadless); static bool IsPedFrozen(CClientPed& Ped, bool& bFrozen); static bool GetPedOccupiedVehicleSeat(CClientPed& Ped, uint& uiSeat); - static CClientVehicle* GetPedNearestVehicleEntryPoint(CClientPed& Ped, bool bCheckDriverDoor, bool bCheckPassengersDoors, uint& uiEntryPoint, CVector& vecClosestDoorPosition); + static CClientVehicle* GetPedNearestVehicleEntryPoint(CClientPed& pPed, bool bCheckDriverDoor, bool bCheckPassengersDoors, uint& uiEntryPoint, CVector& vecClosestDoorPosition); static bool IsPedFootBloodEnabled(CClientPed& Ped, bool& bHasFootBlood); static bool GetPedCameraRotation(CClientPed& Ped, float& fRotation); static bool GetPedWeaponMuzzlePosition(CClientPed& Ped, CVector& vecPosition); @@ -189,6 +189,8 @@ class CStaticFunctionDefinitions static bool RemovePedFromVehicle(CClientPed* pPed); static bool WarpPedIntoVehicle(CClientPed* pPed, CClientVehicle* pVehicle, unsigned int uiSeat); static bool SetPedOxygenLevel(CClientEntity& Entity, float fOxygen); + static bool SetPedExitVehicle(CClientPed& pPed); + static bool SetPedEnterVehicle(CClientPed& pPed, CClientVehicle& pVehicle, unsigned int uiSeat); // Extra Clothes functions static bool GetBodyPartName(unsigned char ucID, SString& strOutName); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index e390f585e2d..c75ef296af5 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -88,6 +88,8 @@ void CLuaPedDefs::LoadFunctions(void) {"setPedOxygenLevel", SetPedOxygenLevel}, {"givePedWeapon", GivePedWeapon}, {"isPedReloadingWeapon", IsPedReloadingWeapon}, + {"setPedExitVehicle", SetPedExitVehicle}, + {"setPedEnterVehicle", SetPedEnterVehicle} }; // Add functions @@ -179,6 +181,8 @@ void CLuaPedDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "setStat", "setPedStat"); lua_classfunction(luaVM, "giveWeapon", "givePedWeapon"); lua_classfunction(luaVM, "isReloadingWeapon", "isPedReloadingWeapon"); + lua_classfunction(luaVM, "setExitVehicle", "setPedExitVehicle"); + lua_classfunction(luaVM, "setEnterVehicle", "setPedEnterVehicle"); lua_classvariable(luaVM, "vehicle", OOP_WarpPedIntoVehicle, GetPedOccupiedVehicle); lua_classvariable(luaVM, "vehicleSeat", NULL, "getPedOccupiedVehicleSeat"); @@ -493,7 +497,6 @@ int CLuaPedDefs::GetPedOccupiedVehicleSeat(lua_State* luaVM) int CLuaPedDefs::GetPedNearestVehicleEntryPoint(lua_State* luaVM) { - // Verify the argument CClientPed* pPed = NULL; bool bCheckDriverDoor = true; bool bCheckPassengersDoors = true; @@ -2181,6 +2184,54 @@ int CLuaPedDefs::SetPedOxygenLevel(lua_State* luaVM) return 1; } +int CLuaPedDefs::SetPedExitVehicle(lua_State* luaVM) +{ + CClientPed* pPed = NULL; + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pPed); + + if (!argStream.HasErrors()) + { + if (CStaticFunctionDefinitions::SetPedExitVehicle(*pPed)) + { + lua_pushboolean(luaVM, true); + return 1; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + // Failed + lua_pushboolean(luaVM, false); + return 1; +} + +int CLuaPedDefs::SetPedEnterVehicle(lua_State* luaVM) +{ + CClientPed* pPed = NULL; + CClientVehicle* pVehicle = NULL; + unsigned int uiSeat = 0; + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pPed); + argStream.ReadUserData(pVehicle); + argStream.ReadNumber(uiSeat); + + if (!argStream.HasErrors()) + { + if (CStaticFunctionDefinitions::SetPedEnterVehicle(*pPed, *pVehicle, uiSeat)) + { + lua_pushboolean(luaVM, true); + return 1; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + // Failed + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaPedDefs::CreatePed(lua_State* luaVM) { // Verify the argument diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index b7ad00cb716..824a00e4a91 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -92,4 +92,6 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(RemovePedFromVehicle); LUA_DECLARE(SetPedOxygenLevel); LUA_DECLARE(SetPedStat); + LUA_DECLARE(SetPedExitVehicle); + LUA_DECLARE(SetPedEnterVehicle); }; From 8b39b2a4a169e167361f51ae2f33055c7cb45a45 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Sun, 21 Oct 2018 15:43:53 -0600 Subject: [PATCH 07/15] Modified "warpPedIntoVehicle" and "removePedFromVehicle" to allow you to warp/remove a player into/from a client-side vehicle. --- .../logic/CStaticFunctionDefinitions.cpp | 2 +- .../mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index c6a5b001fe4..f92beb2f70a 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -9550,7 +9550,7 @@ bool CStaticFunctionDefinitions::GetPedOxygenLevel(CClientPed& Ped, float& fOxyg bool CStaticFunctionDefinitions::WarpPedIntoVehicle(CClientPed* pPed, CClientVehicle* pVehicle, unsigned int uiSeat) { - if (pPed->IsLocalEntity() != pVehicle->IsLocalEntity()) + if (pPed->IsLocalEntity() != pVehicle->IsLocalEntity() && !pPed->IsLocalPlayer()) return false; if (pPed->IsLocalEntity()) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index c75ef296af5..6ec9d50203b 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -1495,7 +1495,7 @@ int CLuaPedDefs::WarpPedIntoVehicle(lua_State* luaVM) if (!argStream.HasErrors()) { - if (!pPed->IsLocalEntity() || !pVehicle->IsLocalEntity()) + if ((!pPed->IsLocalEntity() && !pPed->IsLocalPlayer()) || !pVehicle->IsLocalEntity()) argStream.SetCustomError("This client side function will only work with client created peds and vehicles"); } @@ -1531,7 +1531,7 @@ int CLuaPedDefs::OOP_WarpPedIntoVehicle(lua_State* luaVM) MinClientReqCheck(argStream, MIN_CLIENT_REQ_WARPPEDINTOVEHICLE_CLIENTSIDE, "function is being called client side"); if (!argStream.HasErrors()) { - if (!pPed->IsLocalEntity() || !pVehicle->IsLocalEntity()) + if ((!pPed->IsLocalEntity() && !pPed->IsLocalPlayer()) || !pVehicle->IsLocalEntity()) argStream.SetCustomError("This client side function will only work with client created peds and vehicles"); } @@ -1583,8 +1583,16 @@ int CLuaPedDefs::RemovePedFromVehicle(lua_State* luaVM) if (!argStream.HasErrors()) { - if (!pPed->IsLocalEntity()) + CClientVehicle* pOccupiedVehicle = pPed->GetOccupiedVehicle(); + + if (!pPed->IsLocalEntity() && !pPed->IsLocalPlayer()) argStream.SetCustomError("This client side function will only work with client created peds"); + + if (pOccupiedVehicle) + { + if (!pOccupiedVehicle->IsLocalEntity()) + argStream.SetCustomError("This client side function will only work with client created peds"); + } } if (!argStream.HasErrors()) From 5deae7c02e48a2eaf1fe30e8382ca245705a1704 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Mon, 29 Oct 2018 23:36:16 -0600 Subject: [PATCH 08/15] Prevent projectiles and explosions from client-side from syncing. --- .../logic/CClientExplosionManager.cpp | 19 +++++++++++- Client/mods/deathmatch/logic/CClientGame.cpp | 30 +++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientExplosionManager.cpp b/Client/mods/deathmatch/logic/CClientExplosionManager.cpp index 0d9257d6335..cf7bc48158f 100644 --- a/Client/mods/deathmatch/logic/CClientExplosionManager.cpp +++ b/Client/mods/deathmatch/logic/CClientExplosionManager.cpp @@ -92,6 +92,23 @@ bool CClientExplosionManager::Hook_ExplosionCreation(CEntity* pGameExplodingEnti if (bLocal) { CClientEntity* pOriginSource = NULL; + + // Check if the "weapon" used was a rocket or a tank grenade. + if (explosionWeaponType == WEAPONTYPE_ROCKET || explosionWeaponType == WEAPONTYPE_TANK_GRENADE) + { + CClientVehicle* pOccupiedVehicle = pLocalPlayer->GetOccupiedVehicle(); + + // Is the player in a vehicle? + if (pOccupiedVehicle) + { + // Is the vehicle only available locally? + if (pOccupiedVehicle->IsLocalEntity()) + { + // It is pretty safe to asume this was a projectile from a client-side vehicle driven by the player. Abort. + return true; + } + } + } // Is this an exploding vehicle? if (pGameExplodingEntity && pGameExplodingEntity->GetEntityType() == ENTITY_TYPE_VEHICLE) @@ -161,4 +178,4 @@ CExplosion* CClientExplosionManager::Create(eExplosionType explosionType, CVecto CExplosion* pExplosion = g_pGame->GetExplosionManager()->AddExplosion(NULL, pGameCreator, explosionType, vecPosition, 0, bMakeSound, fCamShake, bNoDamage); return pExplosion; -} \ No newline at end of file +} diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index e35cd2821d9..82ee9f834c5 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -3928,10 +3928,14 @@ void CClientGame::FireHandler(CFire* pFire) void CClientGame::ProjectileInitiateHandler(CClientProjectile* pProjectile) { + CClientEntity* pCreator = pProjectile->GetCreator(); + if (pProjectile->IsLocal()) { + bool bSyncProjectile = true; + // Did the local player create this projectile? - if (m_pLocalPlayer && pProjectile->GetCreator() == m_pLocalPlayer) + if (m_pLocalPlayer && pCreator == m_pLocalPlayer) { // Physics says our projectile should start off at our velocity CVector vecVelocity, vecPlayerVelocity; @@ -3939,16 +3943,30 @@ void CClientGame::ProjectileInitiateHandler(CClientProjectile* pProjectile) m_pLocalPlayer->GetMoveSpeed(vecPlayerVelocity); vecVelocity += vecPlayerVelocity; pProjectile->SetVelocity(vecVelocity); + } + else if(pCreator) + { + if (pCreator->GetType() == CCLIENTVEHICLE) + { + if (pCreator->IsLocalEntity()) + { + // Projectiles created by client-side vehicles should not be synced. + bSyncProjectile = false; + } + } } - SendProjectileSync(pProjectile); + if (bSyncProjectile) + { + SendProjectileSync(pProjectile); + } } // Renew the interior and dimension - if (pProjectile->GetCreator()) + if (pCreator) { - pProjectile->SetInterior(pProjectile->GetCreator()->GetInterior()); - pProjectile->SetDimension(pProjectile->GetCreator()->GetDimension()); + pProjectile->SetInterior(pCreator->GetInterior()); + pProjectile->SetDimension(pCreator->GetDimension()); } // Validate the projectile for our element tree @@ -3956,7 +3974,7 @@ void CClientGame::ProjectileInitiateHandler(CClientProjectile* pProjectile) // Call our creation event CLuaArguments Arguments; - Arguments.PushElement(pProjectile->GetCreator()); + Arguments.PushElement(pCreator); pProjectile->CallEvent("onClientProjectileCreation", Arguments, true); } From 479bdd60ca4db80e0165417045e0e85866091a62 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Mon, 29 Oct 2018 23:40:44 -0600 Subject: [PATCH 09/15] Prevent projectiles and explosions from client-side vehicles from syncing. --- .../logic/CClientExplosionManager.cpp | 19 +++++++++++- Client/mods/deathmatch/logic/CClientGame.cpp | 30 +++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientExplosionManager.cpp b/Client/mods/deathmatch/logic/CClientExplosionManager.cpp index 0d9257d6335..cf7bc48158f 100644 --- a/Client/mods/deathmatch/logic/CClientExplosionManager.cpp +++ b/Client/mods/deathmatch/logic/CClientExplosionManager.cpp @@ -92,6 +92,23 @@ bool CClientExplosionManager::Hook_ExplosionCreation(CEntity* pGameExplodingEnti if (bLocal) { CClientEntity* pOriginSource = NULL; + + // Check if the "weapon" used was a rocket or a tank grenade. + if (explosionWeaponType == WEAPONTYPE_ROCKET || explosionWeaponType == WEAPONTYPE_TANK_GRENADE) + { + CClientVehicle* pOccupiedVehicle = pLocalPlayer->GetOccupiedVehicle(); + + // Is the player in a vehicle? + if (pOccupiedVehicle) + { + // Is the vehicle only available locally? + if (pOccupiedVehicle->IsLocalEntity()) + { + // It is pretty safe to asume this was a projectile from a client-side vehicle driven by the player. Abort. + return true; + } + } + } // Is this an exploding vehicle? if (pGameExplodingEntity && pGameExplodingEntity->GetEntityType() == ENTITY_TYPE_VEHICLE) @@ -161,4 +178,4 @@ CExplosion* CClientExplosionManager::Create(eExplosionType explosionType, CVecto CExplosion* pExplosion = g_pGame->GetExplosionManager()->AddExplosion(NULL, pGameCreator, explosionType, vecPosition, 0, bMakeSound, fCamShake, bNoDamage); return pExplosion; -} \ No newline at end of file +} diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index e35cd2821d9..82ee9f834c5 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -3928,10 +3928,14 @@ void CClientGame::FireHandler(CFire* pFire) void CClientGame::ProjectileInitiateHandler(CClientProjectile* pProjectile) { + CClientEntity* pCreator = pProjectile->GetCreator(); + if (pProjectile->IsLocal()) { + bool bSyncProjectile = true; + // Did the local player create this projectile? - if (m_pLocalPlayer && pProjectile->GetCreator() == m_pLocalPlayer) + if (m_pLocalPlayer && pCreator == m_pLocalPlayer) { // Physics says our projectile should start off at our velocity CVector vecVelocity, vecPlayerVelocity; @@ -3939,16 +3943,30 @@ void CClientGame::ProjectileInitiateHandler(CClientProjectile* pProjectile) m_pLocalPlayer->GetMoveSpeed(vecPlayerVelocity); vecVelocity += vecPlayerVelocity; pProjectile->SetVelocity(vecVelocity); + } + else if(pCreator) + { + if (pCreator->GetType() == CCLIENTVEHICLE) + { + if (pCreator->IsLocalEntity()) + { + // Projectiles created by client-side vehicles should not be synced. + bSyncProjectile = false; + } + } } - SendProjectileSync(pProjectile); + if (bSyncProjectile) + { + SendProjectileSync(pProjectile); + } } // Renew the interior and dimension - if (pProjectile->GetCreator()) + if (pCreator) { - pProjectile->SetInterior(pProjectile->GetCreator()->GetInterior()); - pProjectile->SetDimension(pProjectile->GetCreator()->GetDimension()); + pProjectile->SetInterior(pCreator->GetInterior()); + pProjectile->SetDimension(pCreator->GetDimension()); } // Validate the projectile for our element tree @@ -3956,7 +3974,7 @@ void CClientGame::ProjectileInitiateHandler(CClientProjectile* pProjectile) // Call our creation event CLuaArguments Arguments; - Arguments.PushElement(pProjectile->GetCreator()); + Arguments.PushElement(pCreator); pProjectile->CallEvent("onClientProjectileCreation", Arguments, true); } From e741466ee58eb1535bb720853a8314d4b95ea827 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Thu, 25 Apr 2019 01:37:56 -0600 Subject: [PATCH 10/15] Reset InOut state when using setPedAnimation --- Client/mods/deathmatch/logic/CClientPed.cpp | 26 +++++++++---------- Client/mods/deathmatch/logic/CClientPed.h | 2 ++ .../logic/CStaticFunctionDefinitions.cpp | 17 ++++++++++++ 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 26079359bf2..7cd2a384c6f 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -1295,6 +1295,17 @@ bool CClientPed::GetClosestDoor(CClientVehicle* pVehicle, bool bCheckDriverDoor, return false; } +void CClientPed::ResetInOutState() +{ + m_pInOutVehicle = NULL; + m_bIsEnteringVehicle = false; + m_bIsLeavingVehicle = false; + m_uiInOutSeat = NULL; + m_ucLeavingDoor = NULL; + SetJacker(NULL); + SetJacking(NULL); +} + bool CClientPed::GracefullyEnterCar(CClientVehicle* pVehicle, unsigned int uiSeat, unsigned int uiDoor) { // Check if we are already entering a vehicle or are already in a vehicle. @@ -2874,12 +2885,7 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses) this->CallEvent("onClientPedExitVehicle", Arguments, true); - m_pInOutVehicle = NULL; - m_bIsLeavingVehicle = false; - m_uiInOutSeat = NULL; - m_ucLeavingDoor = NULL; - SetJacker(NULL); - SetJacking(NULL); + ResetInOutState(); } if (m_bIsEnteringVehicle && !IsEnteringVehicle() && !IsGettingIntoVehicle() && m_pInOutVehicle != NULL) @@ -2901,13 +2907,7 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses) this->CallEvent("onClientPedEnterVehicle", Arguments, true); - m_pInOutVehicle = NULL; - m_bIsEnteringVehicle = false; - m_uiInOutSeat = NULL; - m_ucEnteringDoor = NULL; - - SetJacker(NULL); - SetJacking(NULL); + ResetInOutState(); } } diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index d5cbc1a6947..77ad46b1c07 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -225,6 +225,8 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void GetIntoVehicle(CClientVehicle* pVehicle, unsigned int uiSeat = 0, unsigned char ucDoor = 0); void GetOutOfVehicle(unsigned char ucDoor); + void ResetInOutState(); + bool GracefullyEnterCar(CClientVehicle* pVehicle, unsigned int uiSeat, unsigned int uiDoor); bool GracefullyExitCar(); diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index f6cf2a9d8a9..83b91a520d5 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -2138,6 +2138,23 @@ bool CStaticFunctionDefinitions::SetPedAnimation(CClientEntity& Entity, const SS if (IS_PED(&Entity)) { CClientPed& Ped = static_cast(Entity); + + // Ped is trying to enter a vehicle, cancel it. + if (Ped.IsEnteringVehicle()) + { + if (!Ped.GetOccupiedVehicle()) + { + if (Ped.IsLocalPlayer()) + { + m_pClientGame->ResetVehicleInOut(); + } + else + { + Ped.ResetInOutState(); + } + } + } + if (strBlockName && szAnimName) { CAnimBlock* pBlock = g_pGame->GetAnimManager()->GetAnimationBlock(strBlockName); From ecd669235e7b67e7baffba1e7508d2c8cd3e8978 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Thu, 25 Apr 2019 20:55:53 -0600 Subject: [PATCH 11/15] Added cancelPedEnterVehicle and fixed ped vehicle state glitch --- Client/mods/deathmatch/logic/CClientPed.cpp | 32 +++++++++++------ .../logic/CStaticFunctionDefinitions.cpp | 36 +++++++++++++------ .../logic/CStaticFunctionDefinitions.h | 1 + .../deathmatch/logic/luadefs/CLuaPedDefs.cpp | 26 +++++++++++++- .../deathmatch/logic/luadefs/CLuaPedDefs.h | 1 + 5 files changed, 73 insertions(+), 23 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 5bd583f83fd..396b94f69b0 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -1305,6 +1305,7 @@ void CClientPed::ResetInOutState() m_bIsLeavingVehicle = false; m_uiInOutSeat = NULL; m_ucLeavingDoor = NULL; + m_bForceGettingIn = false; SetJacker(NULL); SetJacking(NULL); } @@ -2904,23 +2905,32 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses) if (m_bIsEnteringVehicle && !IsEnteringVehicle() && !IsGettingIntoVehicle() && m_pInOutVehicle != NULL) { - CClientVehicle::SetPedOccupiedVehicle(this, m_pInOutVehicle, m_uiInOutSeat, m_ucEnteringDoor); - CClientVehicle::SetPedOccupyingVehicle(this, m_pInOutVehicle, m_uiInOutSeat, m_ucEnteringDoor); + // Only update the occupying state if we are actually inside the vehicle. + if (GetRealOccupiedVehicle()) { + CClientVehicle::SetPedOccupiedVehicle(this, m_pInOutVehicle, m_uiInOutSeat, m_ucEnteringDoor); + CClientVehicle::SetPedOccupyingVehicle(this, m_pInOutVehicle, m_uiInOutSeat, m_ucEnteringDoor); - m_pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); - m_pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); + m_pInOutVehicle->CalcAndUpdateCanBeDamagedFlag(); + m_pInOutVehicle->CalcAndUpdateTyresCanBurstFlag(); - CLuaArguments Arguments; - Arguments.PushElement(this); // ped - Arguments.PushNumber(m_uiInOutSeat); // seat + CLuaArguments Arguments; + Arguments.PushElement(this); // ped + Arguments.PushNumber(m_uiInOutSeat); // seat - if (GetJacking()) + if (GetJacking()) + { + Arguments.PushElement(GetJacking()); // ped we have carjacked + } + + this->CallEvent("onClientPedEnterVehicle", Arguments, true); + } + else { - Arguments.PushElement(GetJacking()); // ped we have carjacked + // Seems like we somehow abandoned getting into the vehicle. + // For safety reasons let's make sure the ped knows this too. + KillTask(TASK_PRIORITY_PRIMARY, true); } - this->CallEvent("onClientPedEnterVehicle", Arguments, true); - ResetInOutState(); } } diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index f0aee4dd92a..8dfbfb37f53 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -2182,17 +2182,7 @@ bool CStaticFunctionDefinitions::SetPedAnimation(CClientEntity& Entity, const SS // Ped is trying to enter a vehicle, cancel it. if (Ped.IsEnteringVehicle()) { - if (!Ped.GetOccupiedVehicle()) - { - if (Ped.IsLocalPlayer()) - { - m_pClientGame->ResetVehicleInOut(); - } - else - { - Ped.ResetInOutState(); - } - } + CancelPedEnterVehicle(Ped); } if (strBlockName && szAnimName) @@ -2583,6 +2573,30 @@ bool CStaticFunctionDefinitions::SetPedEnterVehicle(CClientPed& pPed, CClientVeh return false; } +bool CStaticFunctionDefinitions::CancelPedEnterVehicle(CClientPed& pPed) +{ + if (pPed.IsEnteringVehicle()) + { + if (!pPed.GetOccupiedVehicle()) + { + if (pPed.IsLocalPlayer()) + { + m_pClientGame->ResetVehicleInOut(); + } + else + { + pPed.ResetInOutState(); + } + + pPed.KillTask(TASK_PRIORITY_PRIMARY, true); + + return true; + } + } + + return false; +} + bool CStaticFunctionDefinitions::GetBodyPartName(unsigned char ucID, SString& strOutName) { if (ucID <= 10) diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index ad5b9099712..a7e68f84e47 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -192,6 +192,7 @@ class CStaticFunctionDefinitions static bool SetPedOxygenLevel(CClientEntity& Entity, float fOxygen); static bool SetPedExitVehicle(CClientPed& pPed); static bool SetPedEnterVehicle(CClientPed& pPed, CClientVehicle& pVehicle, unsigned int uiSeat); + static bool CancelPedEnterVehicle(CClientPed& pPed); // Extra Clothes functions static bool GetBodyPartName(unsigned char ucID, SString& strOutName); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index af5af3ccc47..bef5d7ed92e 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -90,7 +90,8 @@ void CLuaPedDefs::LoadFunctions() {"givePedWeapon", GivePedWeapon}, {"isPedReloadingWeapon", IsPedReloadingWeapon}, {"setPedExitVehicle", SetPedExitVehicle}, - {"setPedEnterVehicle", SetPedEnterVehicle} + {"setPedEnterVehicle", SetPedEnterVehicle}, + {"cancelPedEnterVehicle", CancelPedEnterVehicle} }; // Add functions @@ -185,6 +186,7 @@ void CLuaPedDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "isReloadingWeapon", "isPedReloadingWeapon"); lua_classfunction(luaVM, "setExitVehicle", "setPedExitVehicle"); lua_classfunction(luaVM, "setEnterVehicle", "setPedEnterVehicle"); + lua_classfunction(luaVM, "cancelEnterVehicle", "cancelPedEnterVehicle"); lua_classvariable(luaVM, "vehicle", OOP_WarpPedIntoVehicle, GetPedOccupiedVehicle); lua_classvariable(luaVM, "vehicleSeat", NULL, "getPedOccupiedVehicleSeat"); @@ -2274,6 +2276,28 @@ int CLuaPedDefs::SetPedEnterVehicle(lua_State* luaVM) return 1; } +int CLuaPedDefs::CancelPedEnterVehicle(lua_State* luaVM) +{ + CClientPed* pPed = NULL; + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pPed); + + if (!argStream.HasErrors()) + { + if (CStaticFunctionDefinitions::CancelPedEnterVehicle(*pPed)) + { + lua_pushboolean(luaVM, true); + return 1; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + // Failed + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaPedDefs::CreatePed(lua_State* luaVM) { // Verify the argument diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index 8a510353744..9a9913881d9 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -94,4 +94,5 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(SetPedStat); LUA_DECLARE(SetPedExitVehicle); LUA_DECLARE(SetPedEnterVehicle); + LUA_DECLARE(CancelPedEnterVehicle); }; From d0ab6addf79848bef5fbf012fa589ac2cd2733a1 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Fri, 26 Apr 2019 22:45:45 -0600 Subject: [PATCH 12/15] Fix network trouble when carjacking gets abandoned and fix for softlock when ped is moved far away --- Client/mods/deathmatch/logic/CClientGame.cpp | 12 ++++++- Client/mods/deathmatch/logic/CClientGame.h | 1 + Client/mods/deathmatch/logic/CClientPed.cpp | 24 ++++++++++++- Client/mods/deathmatch/logic/CNetAPI.cpp | 34 ++++++++++++++----- .../logic/CStaticFunctionDefinitions.cpp | 6 ++++ 5 files changed, 67 insertions(+), 10 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index f97e31910a2..cfe44bb9a1c 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -2348,6 +2348,14 @@ void CClientGame::ChangeVehicleWeapon(bool bNext) void CClientGame::ResetVehicleInOut() { + if (m_pJackingPed != NULL) + { + if (m_pJackingPed->IsLocalEntity()) + { + m_pJackingPed->ResetInOutState(); + } + } + m_ulLastVehicleInOutTime = 0; m_bIsGettingOutOfVehicle = false; m_bIsGettingIntoVehicle = false; @@ -2358,6 +2366,7 @@ void CClientGame::ResetVehicleInOut() m_bNoNewVehicleTask = false; m_NoNewVehicleTaskReasonID = INVALID_ELEMENT_ID; m_pGettingJackedBy = NULL; + m_pJackingPed = NULL; m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_NONE); } @@ -5350,7 +5359,8 @@ bool CClientGame::ProcessEnterVehicle(CClientVehicle* pVehicle, unsigned int uiS if (pOccupyingPed) { m_bIsJackingVehicle = true; - + m_pJackingPed = pOccupyingPed; + pOccupyingPed->SetJacker(m_pLocalPlayer); m_pLocalPlayer->SetVehicleInOutState(VEHICLE_INOUT_JACKING); pOccupyingPed->SetVehicleInOutState(VEHICLE_INOUT_GETTING_JACKED); diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 1173d6f3215..2ccb4ce11e5 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -724,6 +724,7 @@ class CClientGame unsigned long m_ulLastVehicleInOutTime; bool m_bIsGettingOutOfVehicle; bool m_bIsGettingIntoVehicle; + CClientPed* m_pJackingPed; bool m_bIsJackingVehicle; bool m_bIsGettingJacked; ElementID m_VehicleInOutID; diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 396b94f69b0..495b8928f95 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -1306,6 +1306,21 @@ void CClientPed::ResetInOutState() m_uiInOutSeat = NULL; m_ucLeavingDoor = NULL; m_bForceGettingIn = false; + + CClientPed* pJackingPed = GetJacking(); + + if (pJackingPed != NULL) + { + if (pJackingPed->IsLocalPlayer()) + { + g_pClientGame->ResetVehicleInOut(); + } + else + { + pJackingPed->ResetInOutState(); + } + } + SetJacker(NULL); SetJacking(NULL); } @@ -1439,7 +1454,7 @@ bool CClientPed::GracefullyEnterCar(CClientVehicle* pVehicle, unsigned int uiSea pOccupyingPed->SetJacker(this); } - this->SetJacking(pOccupyingPed); + SetJacking(pOccupyingPed); // We haven't yet entered the car. The ped being carjacked is still occopying it. // Workaround for early-unpair issue. @@ -4412,6 +4427,13 @@ void CClientPed::StreamIn(bool bInstantly) void CClientPed::StreamOut() { + // Is the ped being streamed out a local ped? + if (IsLocalEntity() && !m_bIsLocalPlayer) + { + // Yes, let's reset the vehicle in/out state + ResetInOutState(); + } + // Make sure we have a player ped and that we're not // the local player if (m_pPlayerPed && !m_bIsLocalPlayer) diff --git a/Client/mods/deathmatch/logic/CNetAPI.cpp b/Client/mods/deathmatch/logic/CNetAPI.cpp index f8f5256f0d7..a78a9f917f6 100644 --- a/Client/mods/deathmatch/logic/CNetAPI.cpp +++ b/Client/mods/deathmatch/logic/CNetAPI.cpp @@ -313,22 +313,40 @@ void CNetAPI::DoPulse() if (IsPureSyncNeeded() && !g_pClientGame->IsDownloadingBigPacket()) { // Are in a vehicle? - if (pVehicle && !pVehicle->IsLocalEntity()) + if (pVehicle) { // Send a puresync packet NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream(); if (pBitStream) { - // Write our data - WriteVehiclePuresync(pPlayer, pVehicle, *pBitStream); + // Is the vehicle created on the server? + if (!pVehicle->IsLocalEntity()) + { + // It is, sync it accordingly + // Write our data + WriteVehiclePuresync(pPlayer, pVehicle, *pBitStream); - // Send the packet and destroy it - g_pNet->SendPacket(PACKET_ID_PLAYER_VEHICLE_PURESYNC, pBitStream, PACKET_PRIORITY_MEDIUM, PACKET_RELIABILITY_UNRELIABLE_SEQUENCED); - g_pNet->DeallocateNetBitStream(pBitStream); + // Send the packet and destroy it + g_pNet->SendPacket(PACKET_ID_PLAYER_VEHICLE_PURESYNC, pBitStream, PACKET_PRIORITY_MEDIUM, PACKET_RELIABILITY_UNRELIABLE_SEQUENCED); + g_pNet->DeallocateNetBitStream(pBitStream); + } + else + { + // It was created client-side, we'll sync to the server as if we were on-foot instead + // Write our data + WritePlayerPuresync(pPlayer, *pBitStream); + + // Send the packet and destroy it + g_pNet->SendPacket(PACKET_ID_PLAYER_PURESYNC, pBitStream, PACKET_PRIORITY_MEDIUM, PACKET_RELIABILITY_UNRELIABLE_SEQUENCED); + g_pNet->DeallocateNetBitStream(pBitStream); + } } - // Sync its damage model too - static_cast(pVehicle)->SyncDamageModel(); + if (!pVehicle->IsLocalEntity()) + { + // Sync its damage model too + static_cast(pVehicle)->SyncDamageModel(); + } } else { diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 8dfbfb37f53..c44d9a55ae4 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -2575,6 +2575,12 @@ bool CStaticFunctionDefinitions::SetPedEnterVehicle(CClientPed& pPed, CClientVeh bool CStaticFunctionDefinitions::CancelPedEnterVehicle(CClientPed& pPed) { + // This function only works on local peds. + if (!pPed.IsLocalEntity() && !pPed.IsLocalPlayer()) + { + return false; + } + if (pPed.IsEnteringVehicle()) { if (!pPed.GetOccupiedVehicle()) From 2f5a8c31f72cc8e3e49637ec9c37d54eb67672c0 Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Sat, 27 Apr 2019 00:49:51 -0600 Subject: [PATCH 13/15] Added getPedEnterVehicleTarget and modified getPedNearestVehicleEntryPoint to only detect local vehicles for peds --- Client/mods/deathmatch/logic/CClientGame.cpp | 3 +- Client/mods/deathmatch/logic/CClientPed.cpp | 7 ++- Client/mods/deathmatch/logic/CClientPed.h | 7 ++- .../logic/CStaticFunctionDefinitions.cpp | 43 +++++++++++++++++-- .../logic/CStaticFunctionDefinitions.h | 3 +- .../deathmatch/logic/luadefs/CLuaPedDefs.cpp | 31 +++++++++++++ .../deathmatch/logic/luadefs/CLuaPedDefs.h | 1 + 7 files changed, 87 insertions(+), 8 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index cfe44bb9a1c..116a6ea9c73 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -2356,6 +2356,8 @@ void CClientGame::ResetVehicleInOut() } } + m_pLocalPlayer->ResetInOutState(); + m_ulLastVehicleInOutTime = 0; m_bIsGettingOutOfVehicle = false; m_bIsGettingIntoVehicle = false; @@ -5351,7 +5353,6 @@ bool CClientGame::ProcessEnterVehicle(CClientVehicle* pVehicle, unsigned int uiS m_VehicleInOutID = pVehicle->GetID(); m_ucVehicleInOutSeat = uiSeat; - m_VehicleInOutID = pVehicle->GetID(); m_bIsGettingIntoVehicle = true; m_ulLastVehicleInOutTime = CClientTime::GetTime(); diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 495b8928f95..7bbc5732d0a 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -1099,7 +1099,7 @@ CClientVehicle* CClientPed::GetRealOccupiedVehicle() CClientVehicle* CClientPed::GetClosestVehicleInRange(bool bGetPositionFromClosestDoor, bool bCheckDriverDoor, bool bCheckPassengerDoors, bool bCheckStreamedOutVehicles, unsigned int* uiClosestDoor, CVector* pClosestDoorPosition, - float fWithinRange) + float fWithinRange, bool bLocalOnly) { if (bGetPositionFromClosestDoor) { @@ -1136,6 +1136,9 @@ CClientVehicle* CClientPed::GetClosestVehicleInRange(bool bGetPositionFromCloses if (!pGameVehicle && bGetPositionFromClosestDoor) continue; + if (bLocalOnly && !pTempVehicle->IsLocalEntity()) + continue; + // Should we take the position from the closest door instead of center of vehicle if (bGetPositionFromClosestDoor && pTempVehicle->GetModel() != VT_RCBARON) { @@ -1306,6 +1309,7 @@ void CClientPed::ResetInOutState() m_uiInOutSeat = NULL; m_ucLeavingDoor = NULL; m_bForceGettingIn = false; + m_pEnteringVehicle = NULL; CClientPed* pJackingPed = GetJacking(); @@ -1565,6 +1569,7 @@ void CClientPed::GetIntoVehicle(CClientVehicle* pVehicle, unsigned int uiSeat, u // Do it _GetIntoVehicle(pVehicle, uiSeat, ucDoor); + m_pEnteringVehicle = pVehicle; m_uiOccupiedVehicleSeat = uiSeat; m_ucEnteringDoor = ucDoor; m_bForceGettingIn = true; diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 5d5f58f0d2d..7c4aa6daf53 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -218,7 +218,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule CClientVehicle* GetRealOccupiedVehicle(); CClientVehicle* GetClosestVehicleInRange(bool bGetPositionFromClosestDoor, bool bCheckDriverDoor, bool bCheckPassengerDoors, bool bCheckStreamedOutVehicles, - unsigned int* uiClosestDoor = NULL, CVector* pClosestDoorPosition = NULL, float fWithinRange = 6000.0f); + unsigned int* uiClosestDoor = NULL, CVector* pClosestDoorPosition = NULL, float fWithinRange = 6000.0f, bool bLocalOnly = false); bool GetClosestDoor(CClientVehicle* pVehicle, bool bCheckDriverDoor, bool bCheckPassengerDoors, unsigned int& uiClosestDoor, CVector* pClosestDoorPosition = NULL); @@ -559,6 +559,10 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void SetTaskToBeRestoredOnAnimEnd(bool bSetOnEnd) { m_bTaskToBeRestoredOnAnimEnd = bSetOnEnd; } bool IsTaskToBeRestoredOnAnimEnd() { return m_bTaskToBeRestoredOnAnimEnd; } + CClientVehicle* GetTargetVehicle() { return m_pEnteringVehicle; } + unsigned char GetTargetDoor() { return m_ucEnteringDoor; } + unsigned int GetTargetSeat() { return m_uiOccupiedVehicleSeat; } + void NotifyCreate(); void NotifyDestroy(); @@ -685,6 +689,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule float m_fLighting; unsigned char m_ucEnteringDoor; unsigned char m_ucLeavingDoor; + CClientVehicle* m_pEnteringVehicle; bool m_bPendingRebuildPlayer; uint m_uiFrameLastRebuildPlayer; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index c44d9a55ae4..0f10e210cfa 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1812,7 +1812,7 @@ bool CStaticFunctionDefinitions::GetPedOccupiedVehicleSeat(CClientPed& pPed, uin } CClientVehicle* CStaticFunctionDefinitions::GetPedNearestVehicleEntryPoint(CClientPed& pPed, bool bCheckDriverDoor, bool bCheckPassengersDoors, - uint& uiEntryPoint, CVector& vecClosestDoorPosition) + unsigned int& uiEntryPoint, CVector& vecClosestDoorPosition) { // This function should only work on local peds. if (!pPed.IsLocalEntity() && !pPed.IsLocalPlayer()) @@ -1826,11 +1826,39 @@ CClientVehicle* CStaticFunctionDefinitions::GetPedNearestVehicleEntryPoint(CClie return false; } - CClientVehicle* pVehicle = pPed.GetClosestVehicleInRange(true, bCheckDriverDoor, bCheckPassengersDoors, false, &uiEntryPoint, &vecClosestDoorPosition, 20.0f); + CClientVehicle* pVehicle = pPed.GetClosestVehicleInRange(true, bCheckDriverDoor, bCheckPassengersDoors, false, &uiEntryPoint, &vecClosestDoorPosition, 20.0f, (!pPed.IsLocalPlayer())); return pVehicle; } +CClientVehicle* CStaticFunctionDefinitions::GetPedEnterVehicleTarget(CClientPed& pPed, unsigned int& uiSeat, unsigned int& uiEntryPoint) +{ + // This function only works on local peds. + if (!pPed.IsLocalEntity() && !pPed.IsLocalPlayer()) + { + return false; + } + + if (pPed.IsEnteringVehicle()) + { + if (!pPed.GetOccupiedVehicle()) + { + uiSeat = pPed.GetTargetSeat(); + uiEntryPoint = pPed.GetTargetDoor(); + CClientVehicle* pTargetVehicle = pPed.GetTargetVehicle(); + + if (!pTargetVehicle->IsLocalEntity() && !pPed.IsLocalPlayer()) + { + return false; + } + + return pTargetVehicle; + } + } + + return false; +} + const char* CStaticFunctionDefinitions::GetPedSimplestTask(CClientPed& Ped) { CTaskManager* pTaskManager = Ped.GetTaskManager(); @@ -2555,10 +2583,17 @@ bool CStaticFunctionDefinitions::SetPedEnterVehicle(CClientPed& pPed, CClientVeh return false; } + unsigned int uiDoor = uiSeat; + + if (uiSeat == 0) { + CVector vecDoorPos; + pPed.GetClosestDoor(&pVehicle, true, false, uiDoor, &vecDoorPos); + } + if (pPed.IsLocalPlayer()) { m_pClientGame->ResetVehicleInOut(); - return m_pClientGame->ProcessEnterVehicle(&pVehicle, uiSeat, uiSeat); + return m_pClientGame->ProcessEnterVehicle(&pVehicle, uiSeat, uiDoor); } else { @@ -2567,7 +2602,7 @@ bool CStaticFunctionDefinitions::SetPedEnterVehicle(CClientPed& pPed, CClientVeh return false; } - return pPed.GracefullyEnterCar(&pVehicle, uiSeat, uiSeat); + return pPed.GracefullyEnterCar(&pVehicle, uiSeat, uiDoor); } return false; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index a7e68f84e47..abf9d7976ce 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -149,7 +149,8 @@ class CStaticFunctionDefinitions static bool IsPedHeadless(CClientPed& Ped, bool& bHeadless); static bool IsPedFrozen(CClientPed& Ped, bool& bFrozen); static bool GetPedOccupiedVehicleSeat(CClientPed& Ped, uint& uiSeat); - static CClientVehicle* GetPedNearestVehicleEntryPoint(CClientPed& pPed, bool bCheckDriverDoor, bool bCheckPassengersDoors, uint& uiEntryPoint, CVector& vecClosestDoorPosition); + static CClientVehicle* GetPedNearestVehicleEntryPoint(CClientPed& pPed, bool bCheckDriverDoor, bool bCheckPassengersDoors, unsigned int& uiEntryPoint, CVector& vecClosestDoorPosition); + static CClientVehicle* GetPedEnterVehicleTarget(CClientPed& pPed, unsigned int& uiSeat, unsigned int& uiEntryPoint); static bool IsPedFootBloodEnabled(CClientPed& Ped, bool& bHasFootBlood); static bool GetPedCameraRotation(CClientPed& Ped, float& fRotation); static bool GetPedWeaponMuzzlePosition(CClientPed& Ped, CVector& vecPosition); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index bef5d7ed92e..4bfec5fa7a6 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -44,6 +44,7 @@ void CLuaPedDefs::LoadFunctions() {"getPedOccupiedVehicle", GetPedOccupiedVehicle}, {"getPedOccupiedVehicleSeat", GetPedOccupiedVehicleSeat}, {"getPedNearestVehicleEntryPoint", GetPedNearestVehicleEntryPoint}, + {"getPedEnterVehicleTarget", GetPedEnterVehicleTarget}, {"getPedArmor", GetPedArmor}, {"isPedChoking", IsPedChoking}, {"isPedDucked", IsPedDucked}, @@ -134,6 +135,7 @@ void CLuaPedDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getOccupiedVehicle", "getPedOccupiedVehicle"); lua_classfunction(luaVM, "getOccupiedVehicleSeat", "getPedOccupiedVehicleSeat"); lua_classfunction(luaVM, "getNearestVehicleEntryPoint", OOP_GetPedNearestVehicleEntryPoint); + lua_classfunction(luaVM, "getEnterVehicleTarget", "getPedEnterVehicleTarget"); lua_classfunction(luaVM, "getOxygenLevel", "getPedOxygenLevel"); lua_classfunction(luaVM, "getStat", "getPedStat"); lua_classfunction(luaVM, "getTarget", "getPedTarget"); @@ -571,6 +573,35 @@ int CLuaPedDefs::OOP_GetPedNearestVehicleEntryPoint(lua_State* luaVM) return 1; } +int CLuaPedDefs::GetPedEnterVehicleTarget(lua_State* luaVM) +{ + CClientPed* pPed = NULL; + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pPed); + + if (!argStream.HasErrors()) + { + unsigned int uiSeat; + unsigned int uiEntryPoint; + + CClientVehicle* pVehicle = CStaticFunctionDefinitions::GetPedEnterVehicleTarget(*pPed, uiSeat, uiEntryPoint); + + if (pVehicle) + { + lua_pushelement(luaVM, pVehicle); + lua_pushnumber(luaVM, uiSeat); + lua_pushnumber(luaVM, uiEntryPoint); + return 3; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + // Failed + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaPedDefs::GetPedTask(lua_State* luaVM) { // Verify the argument diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index 9a9913881d9..cf7704e7405 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -37,6 +37,7 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(GetPedOccupiedVehicle); LUA_DECLARE(GetPedOccupiedVehicleSeat); LUA_DECLARE_OOP(GetPedNearestVehicleEntryPoint); + LUA_DECLARE(GetPedEnterVehicleTarget); LUA_DECLARE(GetPedArmor); LUA_DECLARE(IsPedChoking); LUA_DECLARE(IsPedDucked); From c2f0c5c274e1e8ab5eb35f35edb3d9cc3d7947fe Mon Sep 17 00:00:00 2001 From: Jordy Sleeubus Date: Sat, 27 Apr 2019 03:03:26 -0600 Subject: [PATCH 14/15] Added getVehicleEntryPoints --- Client/game_sa/CCarEnterExitSA.cpp | 21 +++ Client/game_sa/CCarEnterExitSA.h | 2 + .../logic/luadefs/CLuaVehicleDefs.cpp | 141 ++++++++++++++++++ .../logic/luadefs/CLuaVehicleDefs.h | 1 + Client/sdk/game/CCarEnterExit.h | 1 + 5 files changed, 166 insertions(+) diff --git a/Client/game_sa/CCarEnterExitSA.cpp b/Client/game_sa/CCarEnterExitSA.cpp index 0899a2bd7ca..f4cfb3d9afb 100644 --- a/Client/game_sa/CCarEnterExitSA.cpp +++ b/Client/game_sa/CCarEnterExitSA.cpp @@ -183,3 +183,24 @@ bool CCarEnterExitSA::IsRoomForPedToLeaveCar(CVehicle* pVehicle, int iDoor, CVec return bRet; } + +void CCarEnterExitSA::GetPositionToOpenCarDoor(CVector& vecPosition, CVehicle* pVehicle, unsigned int uiDoor) +{ + DWORD dwFunc = FUNC_GetPositionToOpenCarDoor; + + CVehicleSA* pVehicleSA = dynamic_cast(pVehicle); + + if (pVehicleSA) + { + CVehicleSAInterface* pVehicleInterface = pVehicleSA->GetVehicleInterface(); + _asm + { + push uiDoor + push pVehicleInterface + push vecPosition + call dwFunc + add esp, 0x0C + mov vecPosition, ecx + } + } +} diff --git a/Client/game_sa/CCarEnterExitSA.h b/Client/game_sa/CCarEnterExitSA.h index c69cacca6d8..bf343aa05ef 100644 --- a/Client/game_sa/CCarEnterExitSA.h +++ b/Client/game_sa/CCarEnterExitSA.h @@ -19,6 +19,7 @@ #define FUNC_GetNearestCarPassengerDoor 0x650BB0 #define FUNC_ComputeTargetDoorToExit 0x64F110 #define FUNC_IsRoomForPedToLeaveCar 0x6504C0 +#define FUNC_GetPositionToOpenCarDoor 0x64E740 class CCarEnterExitSA : public CCarEnterExit { @@ -27,4 +28,5 @@ class CCarEnterExitSA : public CCarEnterExit bool GetNearestCarPassengerDoor(CPed* pPed, CVehicle* pVehicle, CVector* pVector, int* pDoor, bool bUnknown, bool bUnknown2, bool bCheckIfRoomToGetIn); int ComputeTargetDoorToExit(CPed* pPed, CVehicle* pVehicle); bool IsRoomForPedToLeaveCar(CVehicle* pVehicle, int iDoor, CVector* pUnknown = 0); + void GetPositionToOpenCarDoor(CVector& vecPosition, CVehicle* pVehicle, unsigned int uiDoor); }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index ea0fb9672e8..ba01a96a2f4 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -82,6 +82,7 @@ void CLuaVehicleDefs::LoadFunctions() {"getVehicleComponents", GetVehicleComponents}, {"getVehicleModelExhaustFumesPosition", GetVehicleModelExhaustFumesPosition}, {"getVehicleModelDummyPosition", GetVehicleModelDummyPosition}, + {"getVehicleEntryPoints", GetVehicleEntryPoints}, // Vehicle set funcs {"createVehicle", CreateVehicle}, @@ -221,6 +222,7 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getUpgradeOnSlot", "getVehicleUpgradeOnSlot"); lua_classfunction(luaVM, "getModelExhaustFumesPosition", OOP_GetVehicleModelExhaustFumesPosition); lua_classfunction(luaVM, "getVehicleModelDummyPosition", OOP_GetVehicleModelDummyPosition); + lua_classfunction(luaVM, "getEntryPoints", OOP_GetVehicleEntryPoints); lua_classfunction(luaVM, "setComponentVisible", "setVehicleComponentVisible"); lua_classfunction(luaVM, "setSirensOn", "setVehicleSirensOn"); @@ -3877,6 +3879,145 @@ int CLuaVehicleDefs::IsVehicleWindowOpen(lua_State* luaVM) return 1; } +int CLuaVehicleDefs::GetVehicleEntryPoints(lua_State* luaVM) +{ + CClientVehicle* pVehicle = NULL; + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pVehicle); + + if (!argStream.HasErrors()) + { + unsigned char ucMaxPassengers = CClientVehicleManager::GetMaxPassengerCount(pVehicle->GetModel()); + + if (ucMaxPassengers == 255) + { + lua_pushboolean(luaVM, false); + return 1; + } + + CVehicle* pGameVehicle = pVehicle->GetGameVehicle(); + + if (!pGameVehicle) + { + lua_pushboolean(luaVM, false); + return 1; + } + + lua_newtable(luaVM); + + for (unsigned int i = 8; i <= 11; i++) + { + CVector vecDoorPosition; + g_pGame->GetCarEnterExit()->GetPositionToOpenCarDoor(vecDoorPosition, pGameVehicle, i); + + unsigned int uiDoor = i; + + switch (uiDoor) + { + case 10: + uiDoor = 0; + break; + case 8: + uiDoor = 1; + break; + case 11: + uiDoor = 2; + break; + case 9: + uiDoor = 3; + break; + } + + lua_pushnumber(luaVM, uiDoor); + lua_createtable(luaVM, 3, 0); + + lua_pushnumber(luaVM, 1); + lua_pushnumber(luaVM, vecDoorPosition.fX); + lua_settable(luaVM, -3); + + lua_pushnumber(luaVM, 2); + lua_pushnumber(luaVM, vecDoorPosition.fY); + lua_settable(luaVM, -3); + + lua_pushnumber(luaVM, 3); + lua_pushnumber(luaVM, vecDoorPosition.fZ); + lua_settable(luaVM, -3); + + lua_settable(luaVM, -3); + } + + return 1; + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + lua_pushboolean(luaVM, false); + return 1; +} + +int CLuaVehicleDefs::OOP_GetVehicleEntryPoints(lua_State* luaVM) +{ + CClientVehicle* pVehicle = NULL; + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pVehicle); + + if (!argStream.HasErrors()) + { + unsigned char ucMaxPassengers = CClientVehicleManager::GetMaxPassengerCount(pVehicle->GetModel()); + + if (ucMaxPassengers == 255) + { + lua_pushboolean(luaVM, false); + return 1; + } + + CVehicle* pGameVehicle = pVehicle->GetGameVehicle(); + + if (!pGameVehicle) + { + lua_pushboolean(luaVM, false); + return 1; + } + + lua_newtable(luaVM); + + for (unsigned int i = 8; i <= 11; i++) + { + CVector vecDoorPosition; + g_pGame->GetCarEnterExit()->GetPositionToOpenCarDoor(vecDoorPosition, pGameVehicle, i); + + unsigned int uiDoor = i; + + switch (uiDoor) + { + case 10: + uiDoor = 0; + break; + case 8: + uiDoor = 1; + break; + case 11: + uiDoor = 2; + break; + case 9: + uiDoor = 3; + break; + } + + lua_pushnumber(luaVM, uiDoor); + lua_pushvector(luaVM, vecDoorPosition); + lua_settable(luaVM, -3); + } + + return 1; + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaVehicleDefs::SetVehicleModelDummyPosition(lua_State* luaVM) { // bool setVehicleModelDummyPosition ( int modelID, vehicle-dummy dummy, float x, float y, float z ) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h index 9ce32ab02ea..57b11bde8b0 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h @@ -78,6 +78,7 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(GetVehicleNitroLevel); LUA_DECLARE(GetHeliBladeCollisionsEnabled); LUA_DECLARE(IsVehicleWindowOpen); + LUA_DECLARE_OOP(GetVehicleEntryPoints); LUA_DECLARE(FixVehicle); LUA_DECLARE(BlowVehicle); diff --git a/Client/sdk/game/CCarEnterExit.h b/Client/sdk/game/CCarEnterExit.h index 2cfc80b1dff..1a83dab0281 100644 --- a/Client/sdk/game/CCarEnterExit.h +++ b/Client/sdk/game/CCarEnterExit.h @@ -21,4 +21,5 @@ class CCarEnterExit bool bCheckIfRoomToGetIn) = 0; virtual int ComputeTargetDoorToExit(CPed* pPed, CVehicle* pVehicle) = 0; virtual bool IsRoomForPedToLeaveCar(CVehicle* pVehicle, int iDoor, CVector* pUnknown = 0) = 0; + virtual void GetPositionToOpenCarDoor(CVector& vecPosition, CVehicle* pVehicle, unsigned int uiDoor) = 0; }; From 5f7118e13fa4f1e8f6c6072f930e04cd9837477f Mon Sep 17 00:00:00 2001 From: MegadreamsBE Date: Sat, 17 Oct 2020 12:38:52 -0400 Subject: [PATCH 15/15] Remove ASM code --- Client/game_sa/CCarEnterExitSA.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/Client/game_sa/CCarEnterExitSA.cpp b/Client/game_sa/CCarEnterExitSA.cpp index 210c71f6a12..94f3219f4b4 100644 --- a/Client/game_sa/CCarEnterExitSA.cpp +++ b/Client/game_sa/CCarEnterExitSA.cpp @@ -186,21 +186,13 @@ bool CCarEnterExitSA::IsRoomForPedToLeaveCar(CVehicle* pVehicle, int iDoor, CVec void CCarEnterExitSA::GetPositionToOpenCarDoor(CVector& vecPosition, CVehicle* pVehicle, unsigned int uiDoor) { - DWORD dwFunc = FUNC_GetPositionToOpenCarDoor; - CVehicleSA* pVehicleSA = dynamic_cast(pVehicle); if (pVehicleSA) { CVehicleSAInterface* pVehicleInterface = pVehicleSA->GetVehicleInterface(); - _asm - { - push uiDoor - push pVehicleInterface - push vecPosition - call dwFunc - add esp, 0x0C - mov vecPosition, ecx - } + + auto CCarEnterExit_GetPositionToOpenCarDoor = (void(__cdecl*)(CVector&, CVehicleSAInterface*, int))FUNC_GetPositionToOpenCarDoor; + CCarEnterExit_GetPositionToOpenCarDoor(vecPosition, pVehicleInterface, uiDoor); } }