Skip to content

Allow client peds to enter/exit client vehicles #3678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
152 changes: 122 additions & 30 deletions Client/mods/deathmatch/logic/CClientPed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,7 @@ CClientVehicle* CClientPed::GetRealOccupiedVehicle()

CClientVehicle* CClientPed::GetClosestEnterableVehicle(bool bGetPositionFromClosestDoor, bool bCheckDriverDoor, bool bCheckPassengerDoors,
bool bCheckStreamedOutVehicles, unsigned int* uiClosestDoor, CVector* pClosestDoorPosition,
float fWithinRange)
float fWithinRange, bool localVehicles)
{
if (bGetPositionFromClosestDoor)
{
Expand Down Expand Up @@ -1164,7 +1164,7 @@ CClientVehicle* CClientPed::GetClosestEnterableVehicle(bool bGetPositionFromClos
{
pTempVehicle = *iter;
// Skip clientside vehicles as they are not enterable
if (pTempVehicle->IsLocalEntity())
if (pTempVehicle->IsLocalEntity() != localVehicles)
continue;

CVehicle* pGameVehicle = pTempVehicle->GetGameVehicle();
Expand Down Expand Up @@ -2679,9 +2679,6 @@ void CClientPed::WorldIgnore(bool bIgnore)

void CClientPed::StreamedInPulse(bool bDoStandardPulses)
{
if (!m_pPlayerPed)
return;

// 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;

Expand Down Expand Up @@ -2710,6 +2707,10 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses)
// Do we have a player? (streamed in)
if (m_pPlayerPed)
{
// If it's local entity, update in/out vehicle state
if (IsLocalEntity())
UpdateVehicleInOut();

// Handle waiting for the ground to load
if (IsFrozenWaitingForGroundToLoad())
HandleWaitingForGroundToLoad();
Expand Down Expand Up @@ -6418,14 +6419,7 @@ void CClientPed::UpdateStreamPosition(const CVector& vecInPosition)
bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger)
{
// Are we local player or ped we are syncing
if (!IsSyncing() && !IsLocalPlayer())
{
return false;
}

// Are we a clientside ped
// TODO: Add support for clientside peds
if (IsLocalEntity())
if (!IsSyncing() && !IsLocalEntity() && !IsLocalPlayer())
{
return false;
}
Expand Down Expand Up @@ -6474,7 +6468,7 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger)
if (!pVehicle)
{
// Find the closest vehicle and door
CClientVehicle* pClosestVehicle = GetClosestEnterableVehicle(true, !bPassenger, bPassenger, false, &uiDoor, nullptr, 20.0f);
CClientVehicle* pClosestVehicle = GetClosestEnterableVehicle(true, !bPassenger, bPassenger, false, &uiDoor, nullptr, 20.0f, IsLocalEntity());
if (pClosestVehicle)
{
pVehicle = pClosestVehicle;
Expand All @@ -6496,7 +6490,7 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger)
return false;
}

if (!pVehicle->IsEnterable())
if (!pVehicle->IsEnterable(IsLocalEntity()))
{
// Stop if the vehicle is not enterable
return false;
Expand Down Expand Up @@ -6565,10 +6559,34 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger)
Arguments.PushNumber(uiSeat); // seat
Arguments.PushNumber(uiDoor); // door

if (!pVehicle->CallEvent("onClientVehicleStartEnter", Arguments, true))
{
// Event has been cancelled
if (!pVehicle->CallEvent("onClientVehicleStartEnter", Arguments, true)) // Event has been cancelled
return false;

// If it's a local entity, we can just enter the vehicle
if (IsLocalEntity())
{
// If vehicle is not local, we can't enter it
if (!pVehicle->IsLocalEntity())
return false;

// Set the vehicle id we're about to enter
m_VehicleInOutID = pVehicle->GetID();
m_ucVehicleInOutSeat = uiSeat;
m_bIsJackingVehicle = false;

// Make ped enter vehicle
GetIntoVehicle(pVehicle, uiSeat, uiDoor);

// Remember that this ped is working on entering a vehicle
SetVehicleInOutState(VEHICLE_INOUT_GETTING_IN);

pVehicle->CalcAndUpdateCanBeDamagedFlag();
pVehicle->CalcAndUpdateTyresCanBurstFlag();

m_bIsGettingIntoVehicle = true;
m_bIsGettingOutOfVehicle = false;

return true;
}

// Send an in request
Expand Down Expand Up @@ -6620,14 +6638,7 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger)
bool CClientPed::ExitVehicle()
{
// Are we local player or ped we are syncing
if (!IsSyncing() && !IsLocalPlayer())
{
return false;
}

// Are we a clientside ped
// TODO: Add support for clientside peds
if (IsLocalEntity())
if (!IsSyncing() && !IsLocalEntity() && !IsLocalPlayer())
{
return false;
}
Expand Down Expand Up @@ -6672,6 +6683,37 @@ bool CClientPed::ExitVehicle()
return false;
}

std::int8_t targetDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(m_pPlayerPed, pOccupiedVehicle->GetGameVehicle());

// If it's a local entity, we can just exit the vehicle
if (IsLocalEntity())
{
// Set the vehicle id and the seat we're about to exit from
m_VehicleInOutID = pOccupiedVehicle->GetID();
m_ucVehicleInOutSeat = GetOccupiedVehicleSeat();

// Call the onClientVehicleStartExit event for the ped
// Check if it is cancelled before making the ped exit the vehicle
CLuaArguments arguments;
arguments.PushElement(this); // player / ped
arguments.PushNumber(m_ucVehicleInOutSeat); // seat
arguments.PushNumber(0); // door

if (!pOccupiedVehicle->CallEvent("onClientVehicleStartExit", arguments, true)) // Event has been cancelled
return false;

// Make ped exit vehicle
GetOutOfVehicle(targetDoor);

// Remember that this ped is working on leaving a vehicle
SetVehicleInOutState(VEHICLE_INOUT_GETTING_OUT);

m_bIsGettingIntoVehicle = false;
m_bIsGettingOutOfVehicle = true;

return true;
}

// We're about to exit a vehicle
// Send an out request
NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream();
Expand All @@ -6691,11 +6733,10 @@ bool CClientPed::ExitVehicle()
unsigned char ucAction = static_cast<unsigned char>(CClientGame::VEHICLE_REQUEST_OUT);
pBitStream->WriteBits(&ucAction, 4);

unsigned char ucDoor = g_pGame->GetCarEnterExit()->ComputeTargetDoorToExit(m_pPlayerPed, pOccupiedVehicle->GetGameVehicle());
if (ucDoor >= 2 && ucDoor <= 5)
if (targetDoor >= 2 && targetDoor <= 5)
{
ucDoor -= 2;
pBitStream->WriteBits(&ucDoor, 2);
targetDoor -= 2;
pBitStream->WriteBits(&targetDoor, 2);
}

// Send and destroy it
Expand Down Expand Up @@ -6737,6 +6778,57 @@ void CClientPed::ResetVehicleInOut()
//////////////////////////////////////////////////////////////////
void CClientPed::UpdateVehicleInOut()
{
if (IsLocalEntity())
{
// If getting inside vehicle
if (m_bIsGettingIntoVehicle)
{
CClientVehicle* pVehicle = GetRealOccupiedVehicle();

if (pVehicle)
{
// Call the onClientVehicleEnter event for the ped
// Check if it is cancelled before allowing the ped to enter the vehicle
CLuaArguments arguments;
arguments.PushElement(this); // player / ped
arguments.PushNumber(m_ucVehicleInOutSeat); // seat

if (!pVehicle->CallEvent("onClientVehicleEnter", arguments, true))
{
m_bIsGettingIntoVehicle = false;
RemoveFromVehicle();
return;
}

m_bIsGettingIntoVehicle = false;
m_VehicleInOutID = INVALID_ELEMENT_ID;
WarpIntoVehicle(pVehicle, m_ucVehicleInOutSeat);
SetVehicleInOutState(VEHICLE_INOUT_NONE);
}
}
else if (m_bIsGettingOutOfVehicle)
{
// If getting out of vehicle
CClientVehicle* realVehicle = GetRealOccupiedVehicle();
CClientVehicle* networkVehicle = GetOccupiedVehicle();

if (!realVehicle)
{
// Call the onClientVehicleExit event for the ped
CLuaArguments arguments;
arguments.PushElement(this); // player / ped
arguments.PushNumber(m_ucVehicleInOutSeat); // seat
networkVehicle->CallEvent("onClientVehicleExit", arguments, true);

m_bIsGettingOutOfVehicle = false;
m_VehicleInOutID = INVALID_ELEMENT_ID;
SetVehicleInOutState(VEHICLE_INOUT_NONE);
}
}

return;
}

// We got told by the server to animate into a certain vehicle?
if (m_VehicleInOutID != INVALID_ELEMENT_ID)
{
Expand Down
2 changes: 1 addition & 1 deletion Client/mods/deathmatch/logic/CClientPed.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule
CClientVehicle* GetRealOccupiedVehicle();
CClientVehicle* GetClosestEnterableVehicle(bool bGetPositionFromClosestDoor, bool bCheckDriverDoor, bool bCheckPassengerDoors,
bool bCheckStreamedOutVehicles, unsigned int* uiClosestDoor = NULL, CVector* pClosestDoorPosition = NULL,
float fWithinRange = 6000.0f);
float fWithinRange = 6000.0f, bool localVehicles = false);
bool GetClosestDoor(CClientVehicle* pVehicle, bool bCheckDriverDoor, bool bCheckPassengerDoors, unsigned int& uiClosestDoor,
CVector* pClosestDoorPosition = NULL);

Expand Down
4 changes: 2 additions & 2 deletions Client/mods/deathmatch/logic/CClientVehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3859,12 +3859,12 @@ void CClientVehicle::UpdateUnderFloorFix(const CVector& vecTargetPosition, bool
}
}

bool CClientVehicle::IsEnterable()
bool CClientVehicle::IsEnterable(bool localEntity)
{
if (m_pVehicle)
{
// Server vehicle?
if (!IsLocalEntity())
if (IsLocalEntity() == localEntity)
{
if (GetHealth() > 0.0f)
{
Expand Down
2 changes: 1 addition & 1 deletion Client/mods/deathmatch/logic/CClientVehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ class CClientVehicle : public CClientStreamElement

int GetCurrentGear();

bool IsEnterable();
bool IsEnterable(bool localEntity = false);
bool HasRadio();
bool HasPoliceRadio();

Expand Down
Loading