Added CUpsideDownCarCheck and CStuckCarCheck

This commit is contained in:
Nikolay Korolev 2019-07-06 18:06:08 +03:00
parent 2b592605ab
commit b1500fbe03
4 changed files with 163 additions and 8 deletions

View File

@ -29,6 +29,7 @@ public:
static inline void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; } static inline void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; }
static float GetTimeScale(void) { return ms_fTimeScale; } static float GetTimeScale(void) { return ms_fTimeScale; }
static inline void SetTimeScale(float ts) { ms_fTimeScale = ts; } static inline void SetTimeScale(float ts) { ms_fTimeScale = ts; }
static inline float GetFrameTimeStepInMilliseconds() { return ms_fTimeStep / 50.0f * 1000.0f; }
static bool GetIsPaused() { return m_UserPause || m_CodePause; } static bool GetIsPaused() { return m_UserPause || m_CodePause; }
static bool GetIsUserPaused() { return m_UserPause; } static bool GetIsUserPaused() { return m_UserPause; }

View File

@ -129,6 +129,10 @@ void CMissionCleanup::Process()
} }
} }
/* NB: CUpsideDownCarCheck is not used by actual script at all
* It has a weird usage: AreAnyCarsUpsideDown would fail any mission
* just like death or arrest. */
void CUpsideDownCarCheck::Init() void CUpsideDownCarCheck::Init()
{ {
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){ for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
@ -137,18 +141,142 @@ void CUpsideDownCarCheck::Init()
} }
} }
bool CUpsideDownCarCheck::IsCarUpsideDown(int32 id)
{
CVehicle* v = CPools::GetVehiclePool()->GetAt(id);
return v->GetMatrix().GetUp()->z <= -0.97f &&
v->GetMoveSpeed().Magnitude() < 0.01f &&
v->GetTurnSpeed().Magnitude() < 0.02f;
}
void CUpsideDownCarCheck::UpdateTimers()
{
uint32 timeStep = CTimer::GetFrameTimeStepInMilliseconds();
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sCars[i].m_nVehicleIndex);
if (v){
if (IsCarUpsideDown(m_sCars[i].m_nVehicleIndex))
m_sCars[i].m_nUpsideDownTimer += timeStep;
else
m_sCars[i].m_nUpsideDownTimer = 0;
}else{
m_sCars[i].m_nVehicleIndex = -1;
m_sCars[i].m_nUpsideDownTimer = 0;
}
}
}
bool CUpsideDownCarCheck::AreAnyCarsUpsideDown()
{
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex >= 0 && m_sCars[i].m_nUpsideDownTimer > 1000)
return true;
}
return false;
}
void CUpsideDownCarCheck::AddCarToCheck(int32 id)
{
uint16 index = 0;
while (index < MAX_UPSIDEDOWN_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)
index++;
if (index >= MAX_UPSIDEDOWN_CAR_CHECKS)
return;
m_sCars[index].m_nVehicleIndex = id;
m_sCars[index].m_nUpsideDownTimer = 0;
}
void CUpsideDownCarCheck::RemoveCarFromCheck(int32 id)
{
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex == id){
m_sCars[i].m_nVehicleIndex = -1;
m_sCars[i].m_nUpsideDownTimer = 0;
}
}
}
bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id)
{
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex == id)
return m_sCars[i].m_nUpsideDownTimer > 1000;
}
return false;
}
void CStuckCarCheckEntry::Reset()
{
m_nVehicleIndex = -1;
m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f);
m_nLastCheck = -1;
m_fRadius = 0.0f;
m_nStuckTime = 0;
m_bStuck = false;
}
void CStuckCarCheck::Init() void CStuckCarCheck::Init()
{ {
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++) { for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++) {
m_sCars[i].m_nVehicleIndex = -1; m_sCars[i].Reset();
m_sCars[i].m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f);
m_sCars[i].m_nStartTime = -1;
m_sCars[i].m_fDistance = 0.0f;
m_sCars[i].m_nStuckTime = 0;
m_sCars[i].m_bStuck = false;
} }
} }
void CStuckCarCheck::Process()
{
uint32 timer = CTimer::GetTimeInMilliseconds();
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex < 0)
continue;
if (timer <= m_sCars[i].m_nStuckTime + m_sCars[i].m_nLastCheck)
continue;
CVehicle* pv = CPools::GetVehiclePool()->GetAt(m_sCars[i].m_nVehicleIndex);
if (!pv){
m_sCars[i].Reset();
continue;
}
float distance = (pv->GetPosition() - m_sCars[i].m_vecPos).Magnitude();
m_sCars[i].m_bStuck = distance < m_sCars[i].m_fRadius;
m_sCars[i].m_vecPos = pv->GetPosition();
m_sCars[i].m_nLastCheck = timer;
}
}
void CStuckCarCheck::AddCarToCheck(int32 id, float radius, uint32 time)
{
CVehicle* pv = CPools::GetVehiclePool()->GetAt(id);
if (!pv)
return;
int index = 0;
while (index < MAX_STUCK_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)
index++;
/* Would be nice to return if index >= MAX_STUCK_CAR_CHECKS... */
m_sCars[index].m_nVehicleIndex = id;
m_sCars[index].m_vecPos = pv->GetPosition();
m_sCars[index].m_nLastCheck = CTimer::GetTimeInMilliseconds();
m_sCars[index].m_fRadius = radius;
m_sCars[index].m_nStuckTime = time;
m_sCars[index].m_bStuck = false;
}
void CStuckCarCheck::RemoveCarFromCheck(int32 id)
{
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex == id){
m_sCars[i].Reset();
}
}
}
bool CStuckCarCheck::HasCarBeenStuckForAWhile(int32 id)
{
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){
if (m_sCars[i].m_nVehicleIndex == id)
return m_sCars[i].m_bStuck;
}
return false;
}
WRAPPER void CTheScripts::CleanUpThisVehicle(CVehicle*) { EAXJMP(0x4548D0); } WRAPPER void CTheScripts::CleanUpThisVehicle(CVehicle*) { EAXJMP(0x4548D0); }
WRAPPER void CTheScripts::CleanUpThisPed(CPed*) { EAXJMP(0x4547A0); } WRAPPER void CTheScripts::CleanUpThisPed(CPed*) { EAXJMP(0x4547A0); }
WRAPPER void CTheScripts::CleanUpThisObject(CObject*) { EAXJMP(0x454910); } WRAPPER void CTheScripts::CleanUpThisObject(CObject*) { EAXJMP(0x454910); }
@ -160,4 +288,15 @@ InjectHook(0x437AE0, &CMissionCleanup::Init, PATCH_JUMP);
InjectHook(0x437BA0, &CMissionCleanup::AddEntityToList, PATCH_JUMP); InjectHook(0x437BA0, &CMissionCleanup::AddEntityToList, PATCH_JUMP);
InjectHook(0x437BD0, &CMissionCleanup::RemoveEntityFromList, PATCH_JUMP); InjectHook(0x437BD0, &CMissionCleanup::RemoveEntityFromList, PATCH_JUMP);
InjectHook(0x437C10, &CMissionCleanup::Process, PATCH_JUMP); InjectHook(0x437C10, &CMissionCleanup::Process, PATCH_JUMP);
InjectHook(0x437DC0, &CUpsideDownCarCheck::Init, PATCH_JUMP);
InjectHook(0x437EE0, &CUpsideDownCarCheck::UpdateTimers, PATCH_JUMP);
InjectHook(0x437F80, &CUpsideDownCarCheck::AreAnyCarsUpsideDown, PATCH_JUMP);
InjectHook(0x437FB0, &CUpsideDownCarCheck::AddCarToCheck, PATCH_JUMP);
InjectHook(0x437FE0, &CUpsideDownCarCheck::RemoveCarFromCheck, PATCH_JUMP);
InjectHook(0x438010, &CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile, PATCH_JUMP);
InjectHook(0x438050, &CStuckCarCheck::Init, PATCH_JUMP);
InjectHook(0x4380A0, &CStuckCarCheck::Process, PATCH_JUMP);
InjectHook(0x4381C0, &CStuckCarCheck::AddCarToCheck, PATCH_JUMP);
InjectHook(0x438240, &CStuckCarCheck::RemoveCarFromCheck, PATCH_JUMP);
InjectHook(0x4382A0, &CStuckCarCheck::HasCarBeenStuckForAWhile, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -101,16 +101,24 @@ class CUpsideDownCarCheck
public: public:
void Init(); void Init();
bool IsCarUpsideDown(int32);
void UpdateTimers();
bool AreAnyCarsUpsideDown();
void AddCarToCheck(int32);
void RemoveCarFromCheck(int32);
bool HasCarBeenUpsideDownForAWhile(int32);
}; };
struct CStuckCarCheckEntry struct CStuckCarCheckEntry
{ {
int32 m_nVehicleIndex; int32 m_nVehicleIndex;
CVector m_vecPos; CVector m_vecPos;
int32 m_nStartTime; int32 m_nLastCheck;
float m_fDistance; float m_fRadius;
uint32 m_nStuckTime; uint32 m_nStuckTime;
bool m_bStuck; bool m_bStuck;
inline void Reset();
}; };
class CStuckCarCheck class CStuckCarCheck
@ -119,6 +127,10 @@ class CStuckCarCheck
public: public:
void Init(); void Init();
void Process();
void AddCarToCheck(int32, float, uint32);
void RemoveCarFromCheck(int32);
bool HasCarBeenStuckForAWhile(int32);
}; };
class CTheScripts class CTheScripts

View File

@ -104,6 +104,9 @@ public:
bIsInSafePosition = false; bIsInSafePosition = false;
} }
const CVector& GetMoveSpeed() { return m_vecMoveSpeed; }
const CVector& GetTurnSpeed() { return m_vecTurnSpeed; }
void ApplyMoveSpeed(void); void ApplyMoveSpeed(void);
void ApplyTurnSpeed(void); void ApplyTurnSpeed(void);
// Force actually means Impulse here // Force actually means Impulse here