Skip to content
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;
}

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 @@ -3855,12 +3855,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