summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Timer.h1
-rw-r--r--src/control/Script.cpp151
-rw-r--r--src/control/Script.h16
-rw-r--r--src/entities/Physical.h3
4 files changed, 163 insertions, 8 deletions
diff --git a/src/Timer.h b/src/Timer.h
index 75d4048c..fbb130a3 100644
--- a/src/Timer.h
+++ b/src/Timer.h
@@ -29,6 +29,7 @@ public:
static inline void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; }
static float GetTimeScale(void) { return ms_fTimeScale; }
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 GetIsUserPaused() { return m_UserPause; }
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index e7f64541..06edd16a 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -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()
{
for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){
@@ -137,16 +141,140 @@ 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()
{
for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++) {
- m_sCars[i].m_nVehicleIndex = -1;
- 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;
+ m_sCars[i].Reset();
+ }
+}
+
+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); }
@@ -160,4 +288,15 @@ InjectHook(0x437AE0, &CMissionCleanup::Init, PATCH_JUMP);
InjectHook(0x437BA0, &CMissionCleanup::AddEntityToList, PATCH_JUMP);
InjectHook(0x437BD0, &CMissionCleanup::RemoveEntityFromList, 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 \ No newline at end of file
diff --git a/src/control/Script.h b/src/control/Script.h
index 7b62a1b0..42e41c70 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -101,16 +101,24 @@ class CUpsideDownCarCheck
public:
void Init();
+ bool IsCarUpsideDown(int32);
+ void UpdateTimers();
+ bool AreAnyCarsUpsideDown();
+ void AddCarToCheck(int32);
+ void RemoveCarFromCheck(int32);
+ bool HasCarBeenUpsideDownForAWhile(int32);
};
struct CStuckCarCheckEntry
{
int32 m_nVehicleIndex;
CVector m_vecPos;
- int32 m_nStartTime;
- float m_fDistance;
+ int32 m_nLastCheck;
+ float m_fRadius;
uint32 m_nStuckTime;
bool m_bStuck;
+
+ inline void Reset();
};
class CStuckCarCheck
@@ -119,6 +127,10 @@ class CStuckCarCheck
public:
void Init();
+ void Process();
+ void AddCarToCheck(int32, float, uint32);
+ void RemoveCarFromCheck(int32);
+ bool HasCarBeenStuckForAWhile(int32);
};
class CTheScripts
diff --git a/src/entities/Physical.h b/src/entities/Physical.h
index 0f517cf3..0104268a 100644
--- a/src/entities/Physical.h
+++ b/src/entities/Physical.h
@@ -104,6 +104,9 @@ public:
bIsInSafePosition = false;
}
+ const CVector& GetMoveSpeed() { return m_vecMoveSpeed; }
+ const CVector& GetTurnSpeed() { return m_vecTurnSpeed; }
+
void ApplyMoveSpeed(void);
void ApplyTurnSpeed(void);
// Force actually means Impulse here