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

[1.6] Fix door sync #143

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
85 changes: 50 additions & 35 deletions Client/game_sa/CDamageManagerSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,50 +33,60 @@ BYTE CDamageManagerSA::GetDoorStatus(eDoors bDoor)
return NULL;
}

VOID CDamageManagerSA::SetDoorStatus(eDoors bDoor, BYTE bDoorStatus)
VOID CDamageManagerSA::SetDoorStatus(eDoors bDoor, BYTE bDoorStatus, bool bFlyingComponent)
{
DEBUG_TRACE("VOID CDamageManagerSA::SetDoorStatus ( eDoors bDoor, BYTE bDoorStatus )");

if (bDoor < MAX_DOORS)
{
unsigned char ucOldStatus = internalInterface->Door[bDoor];
// Different from before?
if (internalInterface->Door[bDoor] != bDoorStatus)
if (ucOldStatus != bDoorStatus)
{
bool bOldBashed = ucOldStatus == DT_DOOR_BASHED || ucOldStatus == DT_DOOR_BASHED_AND_SWINGING_FREE;
bool bNewBashed = bDoorStatus == DT_DOOR_BASHED || bDoorStatus == DT_DOOR_BASHED_AND_SWINGING_FREE;

// Set it
internalInterface->Door[bDoor] = bDoorStatus;

// Are we making it intact?
if (bDoorStatus == DT_DOOR_INTACT || bDoorStatus == DT_DOOR_SWINGING_FREE)
// Update door model (only if needed - this gonna shut the door)
if (bOldBashed != bNewBashed || bDoorStatus == DT_DOOR_MISSING || ucOldStatus == DT_DOOR_MISSING)
{
// Grab the car node index for the given door id
static int s_iCarNodeIndexes[6] = {0x10, 0x11, 0x0A, 0x08, 0x0B, 0x09};

// Call CAutomobile::FixDoor to update the model
DWORD dwFunc = 0x6A35A0;
DWORD dwThis = (DWORD)internalEntityInterface;
int iCarNodeIndex = s_iCarNodeIndexes[bDoor];
DWORD dwDoor = (DWORD)bDoor;
_asm
// Fix it
if (bDoorStatus == DT_DOOR_INTACT || bDoorStatus == DT_DOOR_SWINGING_FREE)
{
mov ecx, dwThis
push dwDoor
push iCarNodeIndex
call dwFunc
// Grab the car node index for the given door id
static int s_iCarNodeIndexes[6] = {0x10, 0x11, 0x0A, 0x08, 0x0B, 0x09};

// Call CAutomobile::FixDoor to update the model
DWORD dwFunc = 0x6A35A0;
DWORD dwThis = (DWORD)internalEntityInterface;
int iCarNodeIndex = s_iCarNodeIndexes[bDoor];
DWORD dwDoor = (DWORD)bDoor;
_asm
{
mov ecx, dwThis
push dwDoor
push iCarNodeIndex
call dwFunc
}
}
}
else
{
// Call CAutomobile::SetDoorDamage to update the model
DWORD dwFunc = 0x6B1600;
DWORD dwThis = (DWORD)internalEntityInterface;
DWORD dwDoor = (DWORD)bDoor;
bool bUnknown = false;
_asm

// Broke it
if (bNewBashed || bDoorStatus == DT_DOOR_MISSING || ucOldStatus == DT_DOOR_MISSING)
{
mov ecx, dwThis
push bUnknown
push dwDoor
call dwFunc
// Call CAutomobile::SetDoorDamage to update the model
DWORD dwFunc = 0x6B1600;
DWORD dwThis = (DWORD)internalEntityInterface;
DWORD dwDoor = (DWORD)bDoor;
bool bNoFlyingComponent = !bFlyingComponent;
_asm
{
mov ecx, dwThis
push bNoFlyingComponent
push dwDoor
call dwFunc
}
}
}
}
Expand Down Expand Up @@ -104,7 +114,7 @@ VOID CDamageManagerSA::SetWheelStatus(eWheelPosition bWheel, BYTE bTireStatus)
}
}

VOID CDamageManagerSA::SetPanelStatus(BYTE bPanel, BYTE bPanelStatus)
VOID CDamageManagerSA::SetPanelStatus(BYTE bPanel, BYTE bPanelStatus, bool bFlyingComponent)
{
DEBUG_TRACE("BYTE CDamageManagerSA::SetPanelStatus ( BYTE bLight, BYTE bPanelStatus )");

Expand Down Expand Up @@ -150,11 +160,16 @@ VOID CDamageManagerSA::SetPanelStatus(BYTE bPanel, BYTE bPanelStatus)
// Call CAutomobile::SetPanelDamage to update the vehicle
dwFunction = 0x6B1480;
dwThis = (DWORD)internalEntityInterface;
bool bUnknown = false;
bool bNoFlyingComponent = !bFlyingComponent;
if (bPanel == WINDSCREEN_PANEL)
{
bNoFlyingComponent = bFlyingComponent;
}

_asm
{
mov ecx, dwThis
push bUnknown
push bNoFlyingComponent
push dwPanel
call dwFunction
}
Expand All @@ -163,13 +178,13 @@ VOID CDamageManagerSA::SetPanelStatus(BYTE bPanel, BYTE bPanelStatus)
}
}

void CDamageManagerSA::SetPanelStatus(unsigned long ulStatus)
void CDamageManagerSA::SetPanelStatus(unsigned long ulStatus, bool bFlyingComponent)
{
unsigned int uiIndex;

for (uiIndex = 0; uiIndex < MAX_PANELS; uiIndex++)
{
SetPanelStatus(static_cast<eDoors>(uiIndex), static_cast<unsigned char>(ulStatus));
SetPanelStatus(static_cast<eDoors>(uiIndex), static_cast<unsigned char>(ulStatus), bFlyingComponent);
ulStatus >>= 4;
}
}
Expand Down
11 changes: 4 additions & 7 deletions Client/game_sa/CDamageManagerSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
*
*****************************************************************************/

#ifndef __CGAMESA_DAMAGEMANAGER
#define __CGAMESA_DAMAGEMANAGER
#pragma once

#include <game/CDamageManager.h>
#include "Common.h"
Expand Down Expand Up @@ -55,13 +54,13 @@ class CDamageManagerSA : public CDamageManager
BYTE GetEngineStatus();
VOID SetEngineStatus(BYTE bEngineState);
BYTE GetDoorStatus(eDoors bDoor);
VOID SetDoorStatus(eDoors bDoor, BYTE bDoorStatus);
VOID SetDoorStatus(eDoors bDoor, BYTE bDoorStatus, bool bFlyingComponent = true);
BYTE GetWheelStatus(eWheelPosition bWheel);
VOID SetWheelStatus(eWheelPosition bWheel, BYTE bTireStatus);
BYTE GetPanelStatus(BYTE bPanel);
unsigned long GetPanelStatus(void);
VOID SetPanelStatus(BYTE bPanel, BYTE bPanelStatus);
void SetPanelStatus(unsigned long ulStatus);
VOID SetPanelStatus(BYTE bPanel, BYTE bPanelStatus, bool bFlyingComponent = true);
void SetPanelStatus(unsigned long ulStatus, bool bFlyingComponent = true);
BYTE GetLightStatus(BYTE bLight);
unsigned char GetLightStatus(void);
VOID SetLightStatus(BYTE bLight, BYTE bLightStatus);
Expand All @@ -77,5 +76,3 @@ class CDamageManagerSA : public CDamageManager
internalInterface = intInterface;
};
};

#endif
6 changes: 2 additions & 4 deletions Client/game_sa/CDoorSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
*
*****************************************************************************/

#ifndef __CGAMESA_DOOR
#define __CGAMESA_DOOR
#pragma once

#include <game/CDoor.h>
#include <CVector.h>
Expand Down Expand Up @@ -62,6 +61,5 @@ class CDoorSA : public CDoor
BOOL IsFullyOpen();
VOID Open(float fOpenRatio);
eDoorState GetDoorState() { return (eDoorState)this->GetInterface()->m_nDoorState; };
void SetDoorState(unsigned char ucState) { GetInterface()->m_nDoorState = ucState; };
};

#endif
5 changes: 4 additions & 1 deletion Client/mods/deathmatch/logic/CClientPed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,10 @@ CClientVehicle* CClientPed::RemoveFromVehicle(bool bSkipWarpIfGettingOut)

if (pVehicle)
{
pVehicle->SetSwingingDoorsAllowed(false);
if (m_bIsLocalPlayer)
{
pVehicle->SetSwingingDoorsAllowed(false);
}

// Warp the player out of the vehicle
CVehicle* pGameVehicle = pVehicle->m_pVehicle;
Expand Down
117 changes: 92 additions & 25 deletions Client/mods/deathmatch/logic/CClientVehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,26 +654,29 @@ void CClientVehicle::ProcessDoorInterpolation()

void CClientVehicle::SetDoorOpenRatio(unsigned char ucDoor, float fRatio, unsigned long ulDelay, bool bForced)
{
unsigned char ucSeat;

if (ucDoor <= 5)
{
bool bAllow = m_bAllowDoorRatioSetting[ucDoor];

// Prevent setting the door angle ratio while a ped is entering/leaving the vehicle.
if (bAllow && bForced == false)
{
switch (ucDoor)
CClientPed * pPed = GetOccupyingPed(ucDoor - 2);
if (pPed)
{
case 2:
bAllow = m_pOccupyingDriver == 0;
break;
case 3:
case 4:
case 5:
ucSeat = ucDoor - 2;
bAllow = m_pOccupyingPassengers[ucSeat] == 0;
break;
// Don't change angle if somebody is messing with this door
// Allow critical values like fully closed or open.
bAllow = !pPed->IsGettingIntoVehicle() || fRatio == 0 || fRatio == 1;

/*
Driver closing door minor desync:

Player enters a car which has already open driver door (he enters via passenger side or warpPedIntoVehicle).
He closes the door and sends new ratio to other clients.
But other clients are also closing this door which causes ugly effect.

TODO: Find a way to detect if ped is closing door.
*/
}
}

Expand Down Expand Up @@ -825,13 +828,13 @@ void CClientVehicle::Fix(void)
SFixedArray<unsigned char, MAX_DOORS> ucDoorStates;
GetInitialDoorStates(ucDoorStates);
for (int i = 0; i < MAX_DOORS; i++)
SetDoorStatus(i, ucDoorStates[i]);
for (int i = 0; i < MAX_PANELS; i++)
SetPanelStatus(i, 0);
for (int i = 0; i < MAX_LIGHTS; i++)
SetLightStatus(i, 0);
for (int i = 0; i < MAX_WHEELS; i++)
SetWheelStatus(i, 0);
{
SetDoorStatus(i, ucDoorStates[i], false);
SetDoorOpenRatio(i, 0, 0, true);
}
for (int i = 0; i < MAX_PANELS; i++) SetPanelStatus(i, 0, false);
for (int i = 0; i < MAX_LIGHTS; i++) SetLightStatus(i, 0);
for (int i = 0; i < MAX_WHEELS; i++) SetWheelStatus(i, 0);

// These components get a funny rotation when calling Fix() (unknown reason)
struct
Expand Down Expand Up @@ -1471,13 +1474,59 @@ unsigned char CClientVehicle::GetLightStatus(unsigned char ucLight)
return 0;
}

void CClientVehicle::SetDoorStatus(unsigned char ucDoor, unsigned char ucStatus)
// Helpers for dealing with door ajar status without chance to accidently broke bashed status
void CClientVehicle::SetDoorAjarStatus(unsigned char ucDoor, bool bAjar)
{
unsigned char ucStatus = GetDoorStatus(ucDoor);
if (ucStatus != DT_DOOR_MISSING)
{
unsigned char ucNewStatus;
if (ucStatus == DT_DOOR_INTACT || ucStatus == DT_DOOR_SWINGING_FREE)
{
ucNewStatus = bAjar;
}
else if (ucStatus == DT_DOOR_BASHED || ucStatus == DT_DOOR_BASHED_AND_SWINGING_FREE)
{
ucNewStatus = bAjar + 2;
}
SetDoorStatus(ucDoor, ucNewStatus, false);
}
}

bool CClientVehicle::GetDoorAjarStatus(unsigned char ucDoor)
{
unsigned char ucStatus = GetDoorStatus(ucDoor);
if (ucStatus == DT_DOOR_MISSING)
{
// Let's say they are ajar but this really shouldn't be used without checking if they are missing first
return true;
}
return ucStatus == DT_DOOR_SWINGING_FREE || ucStatus == DT_DOOR_BASHED_AND_SWINGING_FREE;
}

void CClientVehicle::SetDoorStatus(unsigned char ucDoor, unsigned char ucStatus, bool bFlyingComponent)
{
if (ucDoor < MAX_DOORS)
{
if (m_pVehicle && HasDamageModel())
{
m_pVehicle->GetDamageManager()->SetDoorStatus(static_cast<eDoors>(ucDoor), ucStatus);
if (ucStatus == DT_DOOR_BASHED_AND_SWINGING_FREE)
{
// Set it to bashed first
SetDoorStatus(ucDoor, DT_DOOR_BASHED, bFlyingComponent);
}
else if (ucStatus == DT_DOOR_SWINGING_FREE)
{
// Set it to intact first
SetDoorStatus(ucDoor, DT_DOOR_INTACT, bFlyingComponent);
}

m_pVehicle->GetDamageManager()->SetDoorStatus(static_cast<eDoors>(ucDoor), ucStatus, bFlyingComponent);
CDoor* pDoor = m_pVehicle->GetDoor(ucDoor);
if (pDoor)
{
pDoor->SetDoorState(ucStatus);
}
}
m_ucDoorStates[ucDoor] = ucStatus;
}
Expand Down Expand Up @@ -1543,13 +1592,13 @@ bool CClientVehicle::GetWheelMissing(unsigned char ucWheel, const SString& strWh
return false;
}

void CClientVehicle::SetPanelStatus(unsigned char ucPanel, unsigned char ucStatus)
void CClientVehicle::SetPanelStatus(unsigned char ucPanel, unsigned char ucStatus, bool bSpawnComponent)
{
if (ucPanel < MAX_PANELS)
{
if (m_pVehicle && HasDamageModel())
{
m_pVehicle->GetDamageManager()->SetPanelStatus(static_cast<ePanels>(ucPanel), ucStatus);
m_pVehicle->GetDamageManager()->SetPanelStatus(static_cast<ePanels>(ucPanel), ucStatus, bSpawnComponent);
}
m_ucPanelStates[ucPanel] = ucStatus;
}
Expand Down Expand Up @@ -1683,6 +1732,20 @@ CClientPed* CClientVehicle::GetOccupant(int iSeat) const
return NULL;
}

// Returns ped which is TRYING to get this seat.
CClientPed* CClientVehicle::GetOccupyingPed(unsigned char uiSeat) const
{
if (uiSeat == 0)
{
return (CClientPed*)(const CClientPed*)m_pOccupyingDriver;
}
else if (uiSeat <= (sizeof(m_pOccupyingPassengers) / sizeof(CClientPed*)))
{
return m_pOccupyingPassengers[uiSeat - 1];
}
return NULL;
}

CClientPed* CClientVehicle::GetControllingPlayer(void)
{
CClientPed* pControllingPlayer = m_pDriver;
Expand Down Expand Up @@ -2184,9 +2247,13 @@ void CClientVehicle::StreamedInPulse(void)
CDamageManager* pDamageManager = m_pVehicle->GetDamageManager();

for (int i = 0; i < MAX_DOORS; i++)
pDamageManager->SetDoorStatus(static_cast<eDoors>(i), m_ucDoorStates[i]);
{
float fRatio = GetDoorOpenRatio(i);
SetDoorStatus(i, m_ucDoorStates[i], false);
SetDoorOpenRatio(i, fRatio, 0, true);
}
for (int i = 0; i < MAX_PANELS; i++)
pDamageManager->SetPanelStatus(static_cast<ePanels>(i), m_ucPanelStates[i]);
pDamageManager->SetPanelStatus(static_cast<ePanels>(i), m_ucPanelStates[i], false);
for (int i = 0; i < MAX_LIGHTS; i++)
pDamageManager->SetLightStatus(static_cast<eLights>(i), m_ucLightStates[i]);
}
Expand Down