summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Collision.cpp4
-rw-r--r--src/Collision.h2
-rw-r--r--src/DamageManager.cpp1
-rw-r--r--src/DamageManager.h18
-rw-r--r--src/Door.h17
-rw-r--r--src/Pad.cpp8
-rw-r--r--src/Radar.cpp1
-rw-r--r--src/References.h2
-rw-r--r--src/Skidmarks.cpp0
-rw-r--r--src/Streaming.cpp244
-rw-r--r--src/Streaming.h11
-rw-r--r--src/Timer.h13
-rw-r--r--src/World.cpp2
-rw-r--r--src/World.h4
-rw-r--r--src/animation/RpAnimBlend.cpp2
-rw-r--r--src/audio/DMAudio.cpp11
-rw-r--r--src/audio/DMAudio.h9
-rw-r--r--src/config.h1
-rw-r--r--src/control/CarCtrl.cpp1
-rw-r--r--src/control/CarCtrl.h1
-rw-r--r--src/control/PhoneInfo.cpp6
-rw-r--r--src/control/PhoneInfo.h6
-rw-r--r--src/control/Pickups.cpp2
-rw-r--r--src/control/Pickups.h5
-rw-r--r--src/control/Population.cpp5
-rw-r--r--src/control/Population.h4
-rw-r--r--src/control/Replay.cpp505
-rw-r--r--src/control/Replay.h117
-rw-r--r--src/entities/Automobile.cpp5
-rw-r--r--src/entities/Automobile.h16
-rw-r--r--src/entities/Object.cpp2
-rw-r--r--src/entities/Object.h1
-rw-r--r--src/entities/Ped.cpp26
-rw-r--r--src/entities/Ped.h32
-rw-r--r--src/math/Matrix.h34
-rw-r--r--src/render/Renderer.h3
-rw-r--r--src/render/Skidmarks.cpp2
-rw-r--r--src/render/Skidmarks.h1
-rw-r--r--src/templates.h36
39 files changed, 1062 insertions, 98 deletions
diff --git a/src/Collision.cpp b/src/Collision.cpp
index e6a81954..774caf9d 100644
--- a/src/Collision.cpp
+++ b/src/Collision.cpp
@@ -93,6 +93,8 @@ CCollision::LoadCollisionWhenINeedIt(bool changeLevel)
#endif
+WRAPPER void CCollision::SortOutCollisionAfterLoad(void) { EAXJMP(0x40B900); }
+
//
// Test
//
@@ -1583,6 +1585,8 @@ CColModel::GetTrianglePoint(CVector &v, int i) const
v = vertices[i];
}
+WRAPPER CColModel& CColModel::operator=(const CColModel& other) { EAXJMP(0x411710); }
+
STARTPATCHES
InjectHook(0x4B9C30, (CMatrix& (*)(const CMatrix &src, CMatrix &dst))Invert, PATCH_JUMP);
diff --git a/src/Collision.h b/src/Collision.h
index 1bd4ca4a..aa125334 100644
--- a/src/Collision.h
+++ b/src/Collision.h
@@ -108,6 +108,7 @@ struct CColModel
CColModel *ctor(void) { return ::new (this) CColModel(); }
void dtor(void) { this->CColModel::~CColModel(); }
+ CColModel& operator=(const CColModel& other);
};
class CCollision
@@ -119,6 +120,7 @@ public:
static void Init(void);
static void Update(void);
static void LoadCollisionWhenINeedIt(bool changeLevel);
+ static void SortOutCollisionAfterLoad(void);
static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
diff --git a/src/DamageManager.cpp b/src/DamageManager.cpp
new file mode 100644
index 00000000..d4c8f16e
--- /dev/null
+++ b/src/DamageManager.cpp
@@ -0,0 +1 @@
+#include "DamageManager.h" \ No newline at end of file
diff --git a/src/DamageManager.h b/src/DamageManager.h
new file mode 100644
index 00000000..4f1fa640
--- /dev/null
+++ b/src/DamageManager.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "common.h"
+
+class CDamageManager
+{
+public:
+ float field_0;
+ char m_bEngineStatus;
+ char m_bWheelStatus[4];
+ char m_bDoorStatus[7];
+ uint32 m_abLightStatus;
+ uint32 m_abPanelsStatus;
+ char field_24;
+ char field_25;
+ char field_26;
+ char field_27;
+}; \ No newline at end of file
diff --git a/src/Door.h b/src/Door.h
new file mode 100644
index 00000000..99fae5f1
--- /dev/null
+++ b/src/Door.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "common.h"
+
+struct CDoor
+{
+ float m_fAngleWhenOpened;
+ float m_fAngleWhenClosed;
+ char field_8;
+ char field_9;
+ char field_10;
+ char field_11;
+ float m_fAngle;
+ float m_fPreviousAngle;
+ float m_fAngularVelocity;
+ CVector m_vecVelocity;
+}; \ No newline at end of file
diff --git a/src/Pad.cpp b/src/Pad.cpp
index 61b7ed06..e6f36efd 100644
--- a/src/Pad.cpp
+++ b/src/Pad.cpp
@@ -1677,11 +1677,11 @@ int16 CPad::LookAroundLeftRight(void)
float axis = GetPad(0)->NewState.RightStickX;
if ( fabs(axis) > 85 && !GetLookBehindForPed() )
- return (int16) ( (axis + ( axis > 0 ) ? -85 : 85)
+ return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )
* (127.0f / 32.0f) ); // 3.96875f
else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && fabs(axis) > 10 )
- return (int16) ( (axis + ( axis > 0 ) ? -10 : 10)
+ return (int16) ( (axis + ( ( axis > 0 ) ? -10 : 10) )
* (127.0f / 64.0f) ); // 1.984375f
return 0;
@@ -1692,11 +1692,11 @@ int16 CPad::LookAroundUpDown(void)
int16 axis = GetPad(0)->NewState.RightStickY;
if ( abs(axis) > 85 && !GetLookBehindForPed() )
- return (int16) ( (axis + ( axis > 0 ) ? -85 : 85)
+ return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )
* (127.0f / 32.0f) ); // 3.96875f
else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && abs(axis) > 40 )
- return (int16) ( (axis + ( axis > 0 ) ? -40 : 40)
+ return (int16) ( (axis + ( ( axis > 0 ) ? -40 : 40) )
* (127.0f / 64.0f) ); // 1.984375f
return 0;
diff --git a/src/Radar.cpp b/src/Radar.cpp
index 3c2f24d3..1b6ca527 100644
--- a/src/Radar.cpp
+++ b/src/Radar.cpp
@@ -1,3 +1,4 @@
+#include "config.h"
#include "common.h"
#include "patcher.h"
#include "RwHelper.h"
diff --git a/src/References.h b/src/References.h
index 5ee20d38..c8017c0d 100644
--- a/src/References.h
+++ b/src/References.h
@@ -10,8 +10,8 @@ struct CReference
class CReferences
{
- static CReference *aRefs; //[NUMREFERENCES];
public:
+ static CReference *aRefs; //[NUMREFERENCES];
static CReference *&pEmptyList;
static void Init(void);
};
diff --git a/src/Skidmarks.cpp b/src/Skidmarks.cpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/Skidmarks.cpp
diff --git a/src/Streaming.cpp b/src/Streaming.cpp
index 0dc64d62..967b3ec8 100644
--- a/src/Streaming.cpp
+++ b/src/Streaming.cpp
@@ -3,6 +3,8 @@
#include "Pad.h"
#include "Hud.h"
#include "Text.h"
+#include "Clock.h"
+#include "Renderer.h"
#include "ModelInfo.h"
#include "TxdStore.h"
#include "ModelIndices.h"
@@ -60,9 +62,43 @@ int32 &islandLODsubInd = *(int32*)0x6212D4;
int32 &islandLODsubCom = *(int32*)0x6212D8;
WRAPPER void CStreaming::MakeSpaceFor(int32 size) { EAXJMP(0x409B70); }
-//WRAPPER bool CStreaming::IsTxdUsedByRequestedModels(int32 txdId) { EAXJMP(0x4094C0); }
-//WRAPPER bool CStreaming::AddToLoadedVehiclesList(int32 modelId) { EAXJMP(0x40B060); }
+WRAPPER void CStreaming::LoadScene(const CVector &pos) { EAXJMP(0x40A6D0); }
+bool
+CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size)
+{
+ if(m_size == 0)
+ return false;
+ posn = m_position;
+ size = m_size;
+ return true;
+}
+
+void
+CStreamingInfo::SetCdPosnAndSize(uint32 posn, uint32 size)
+{
+ m_position = posn;
+ m_size = size;
+}
+
+void
+CStreamingInfo::AddToList(CStreamingInfo *link)
+{
+ // Insert this after link
+ m_next = link->m_next;
+ m_prev = link;
+ link->m_next = this;
+ m_next->m_prev = this;
+}
+
+void
+CStreamingInfo::RemoveFromList(void)
+{
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+ m_next = nil;
+ m_prev = nil;
+}
void
CStreaming::Init(void)
@@ -1584,41 +1620,194 @@ CStreaming::UpdateMemoryUsed(void)
// empty
}
+#define STREAM_DIST (2*SECTOR_SIZE_X)
-bool
-CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size)
+void
+CStreaming::AddModelsToRequestList(const CVector &pos)
{
- if(m_size == 0)
- return false;
- posn = m_position;
- size = m_size;
- return true;
+ float xmin, xmax, ymin, ymax;
+ int ixmin, ixmax, iymin, iymax;
+ int ix, iy;
+ int dx, dy, d;
+ CSector *sect;
+
+ xmin = pos.x - STREAM_DIST;
+ ymin = pos.y - STREAM_DIST;
+ xmax = pos.x + STREAM_DIST;
+ ymax = pos.y + STREAM_DIST;
+
+ ixmin = CWorld::GetSectorIndexX(xmin);
+ if(ixmin < 0) ixmin = 0;
+ ixmax = CWorld::GetSectorIndexX(xmax);
+ if(ixmax >= NUMSECTORS_X) ixmax = NUMSECTORS_X-1;
+ iymin = CWorld::GetSectorIndexY(ymin);
+ if(iymin < 0) iymin = 0;
+ iymax = CWorld::GetSectorIndexY(ymax);
+ if(iymax >= NUMSECTORS_Y) iymax = NUMSECTORS_Y-1;
+
+ CWorld::AdvanceCurrentScanCode();
+
+ for(iy = iymin; iy < iymax; iy++){
+ dy = iy - CWorld::GetSectorIndexY(pos.y);
+ for(ix = ixmin; ix < ixmax; ix++){
+
+ if(CRenderer::m_loadingPriority && ms_numModelsRequested > 5)
+ return;
+
+ dx = ix - CWorld::GetSectorIndexX(pos.x);
+ d = dx*dx + dy*dy;
+ sect = CWorld::GetSector(ix, iy);
+ if(d <= 1){
+ ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);
+ ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);
+ ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);
+ ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);
+ }else if(d <= 4*4){
+ ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], pos.x, pos.y, xmin, ymin, xmax, ymax);
+ ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], pos.x, pos.y, xmin, ymin, xmax, ymax);
+ ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], pos.x, pos.y, xmin, ymin, xmax, ymax);
+ ProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], pos.x, pos.y, xmin, ymin, xmax, ymax);
+ }
+ }
+ }
}
void
-CStreamingInfo::SetCdPosnAndSize(uint32 posn, uint32 size)
+CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax)
{
- m_position = posn;
- m_size = size;
+ CPtrNode *node;
+ CEntity *e;
+ float lodDistSq;
+ CVector2D pos;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+
+ if(e->m_scanCode == CWorld::GetCurrentScanCode())
+ continue;
+
+ e->m_scanCode = CWorld::GetCurrentScanCode();
+ if(!e->m_flagC20 && !e->bIsSubway &&
+ (!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){
+ CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex());
+ if(mi->m_type != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())){
+ lodDistSq = sq(mi->GetLargestLodDistance());
+ lodDistSq = min(lodDistSq, sq(STREAM_DIST));
+ pos = CVector2D(e->GetPosition());
+ if(xmin < pos.x && pos.x < xmax &&
+ ymin < pos.y && pos.y < ymax &&
+ (CVector2D(x, y) - pos).MagnitudeSqr() < lodDistSq)
+ if(CRenderer::IsEntityCullZoneVisible(e))
+ RequestModel(e->GetModelIndex(), 0);
+ }
+ }
+ }
}
void
-CStreamingInfo::AddToList(CStreamingInfo *link)
+CStreaming::ProcessEntitiesInSectorList(CPtrList &list)
{
- // Insert this after link
- m_next = link->m_next;
- m_prev = link;
- link->m_next = this;
- m_next->m_prev = this;
+ CPtrNode *node;
+ CEntity *e;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+
+ if(e->m_scanCode == CWorld::GetCurrentScanCode())
+ continue;
+
+ e->m_scanCode = CWorld::GetCurrentScanCode();
+ if(!e->m_flagC20 && !e->bIsSubway &&
+ (!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){
+ CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex());
+ if(mi->m_type != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff()))
+ if(CRenderer::IsEntityCullZoneVisible(e))
+ RequestModel(e->GetModelIndex(), 0);
+ }
+ }
}
void
-CStreamingInfo::RemoveFromList(void)
+CStreaming::DeleteFarAwayRwObjects(const CVector &pos)
{
- m_next->m_prev = m_prev;
- m_prev->m_next = m_next;
- m_next = nil;
- m_prev = nil;
+ // TODO
+}
+
+void
+CStreaming::DeleteAllRwObjects(void)
+{
+ int x, y;
+ CSector *sect;
+
+ for(x = 0; x < NUMSECTORS_X; x++)
+ for(y = 0; y < NUMSECTORS_Y; y++){
+ sect = CWorld::GetSector(x, y);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS_OVERLAP]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES_OVERLAP]);
+ }
+}
+
+void
+CStreaming::DeleteRwObjectsAfterDeath(const CVector &pos)
+{
+ int ix, iy;
+ int x, y;
+ CSector *sect;
+
+ ix = CWorld::GetSectorIndexX(pos.x);
+ iy = CWorld::GetSectorIndexX(pos.y);
+
+ for(x = 0; x < NUMSECTORS_X; x++)
+ for(y = 0; y < NUMSECTORS_Y; y++)
+ if(fabs(ix - x) > 3.0f &&
+ fabs(iy - y) > 3.0f){
+ sect = CWorld::GetSector(x, y);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS_OVERLAP]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES_OVERLAP]);
+ }
+}
+
+void
+CStreaming::DeleteRwObjectsInSectorList(CPtrList &list)
+{
+ CPtrNode *node;
+ CEntity *e;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+ if(!e->m_flagC20 && !e->bImBeingRendered)
+ e->DeleteRwObject();
+ }
+}
+
+void
+CStreaming::DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y)
+{
+ CPtrNode *node;
+ CEntity *e;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+ if(e->m_rwObject && !e->m_flagC20 && !e->bImBeingRendered){
+ // Now this is pretty weird...
+ if(fabs(CWorld::GetSectorIndexX(e->GetPosition().x) - x) >= 2.0f)
+// {
+ e->DeleteRwObject();
+// return; // BUG?
+// }
+ else // FIX?
+ if(fabs(CWorld::GetSectorIndexY(e->GetPosition().y) - y) >= 2.0f)
+ e->DeleteRwObject();
+ }
+ }
}
STARTPATCHES
@@ -1668,6 +1857,15 @@ STARTPATCHES
InjectHook(0x40A390, CStreaming::LoadRequestedModels, PATCH_JUMP);
InjectHook(0x40A440, CStreaming::LoadAllRequestedModels, PATCH_JUMP);
+ InjectHook(0x4078F0, CStreaming::AddModelsToRequestList, PATCH_JUMP);
+ InjectHook(0x407C50, (void (*)(CPtrList&,float,float,float,float,float,float))CStreaming::ProcessEntitiesInSectorList, PATCH_JUMP);
+ InjectHook(0x407DD0, (void (*)(CPtrList&))CStreaming::ProcessEntitiesInSectorList, PATCH_JUMP);
+
+ InjectHook(0x407390, CStreaming::DeleteAllRwObjects, PATCH_JUMP);
+ InjectHook(0x407400, CStreaming::DeleteRwObjectsAfterDeath, PATCH_JUMP);
+ InjectHook(0x407560, CStreaming::DeleteRwObjectsInSectorList, PATCH_JUMP);
+ InjectHook(0x4075A0, CStreaming::DeleteRwObjectsInOverlapSectorList, PATCH_JUMP);
+
InjectHook(0x4063E0, &CStreamingInfo::GetCdPosnAndSize, PATCH_JUMP);
InjectHook(0x406410, &CStreamingInfo::SetCdPosnAndSize, PATCH_JUMP);
InjectHook(0x4063D0, &CStreamingInfo::GetCdSize, PATCH_JUMP);
diff --git a/src/Streaming.h b/src/Streaming.h
index 75d53dcd..a2ff2f5b 100644
--- a/src/Streaming.h
+++ b/src/Streaming.h
@@ -70,6 +70,7 @@ struct CStreamingChannel
class CDirectory;
enum eLevelName;
+class CPtrList;
class CStreaming
{
@@ -156,7 +157,17 @@ public:
static void IHaveUsedStreamingMemory(void);
static void UpdateMemoryUsed(void);
+ static void AddModelsToRequestList(const CVector &pos);
+ static void ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax);
+ static void ProcessEntitiesInSectorList(CPtrList &list);
+ static void DeleteFarAwayRwObjects(const CVector &pos);
+ static void DeleteAllRwObjects(void);
+ static void DeleteRwObjectsInSectorList(CPtrList &list);
+ static void DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y);
+ static void DeleteRwObjectsAfterDeath(const CVector &pos);
static void LoadInitialPeds(void);
static void LoadInitialVehicles(void);
+
+ static void LoadScene(const CVector &pos);
};
diff --git a/src/Timer.h b/src/Timer.h
index ff532050..75d4048c 100644
--- a/src/Timer.h
+++ b/src/Timer.h
@@ -14,15 +14,24 @@ class CTimer
static bool &m_CodePause;
public:
static float GetTimeStep(void) { return ms_fTimeStep; }
+ static inline void SetTimeStep(float ts) { ms_fTimeStep = ts; }
static float GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; }
- static void SetTimeStep(float ts) { ms_fTimeStep = ts; }
+ static inline void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; }
static uint32 GetFrameCounter(void) { return m_FrameCounter; }
+ static inline void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; }
static uint32 GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; }
+ static inline void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; }
+ static uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; }
+ static inline void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; }
static uint32 GetTimeInMillisecondsPauseMode(void) { return m_snTimeInMillisecondsPauseMode; }
+ static inline void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; }
+ static uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; }
+ 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 bool GetIsPaused() { return m_UserPause || m_CodePause; }
static bool GetIsUserPaused() { return m_UserPause; }
- static void SetTimeScale(float ts) { ms_fTimeScale = ts; }
static void SetCodePause(bool pause) { m_CodePause = pause; }
static void Initialise(void);
diff --git a/src/World.cpp b/src/World.cpp
index e99668ec..0a83c595 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -588,7 +588,7 @@ STARTPATCHES
InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP);
ENDPATCHES
-WRAPPER CPed *FindPlayerPed(void) { EAXJMP(0x4A1150); }
+WRAPPER CPlayerPed *FindPlayerPed(void) { EAXJMP(0x4A1150); }
WRAPPER CVector &FindPlayerCoors(CVector &v) { EAXJMP(0x4A1030); }
WRAPPER CVehicle *FindPlayerVehicle(void) { EAXJMP(0x4A10C0); }
WRAPPER CVehicle *FindPlayerTrain(void) { EAXJMP(0x4A1120); }
diff --git a/src/World.h b/src/World.h
index c8fe827d..e3a6a8f2 100644
--- a/src/World.h
+++ b/src/World.h
@@ -105,9 +105,9 @@ public:
static float GetWorldY(int y) { return y*SECTOR_SIZE_Y + WORLD_MIN_Y; }
};
-class CPed;
+class CPlayerPed;
class CVehicle;
-CPed *FindPlayerPed(void);
+CPlayerPed *FindPlayerPed(void);
CVector &FindPlayerCoors(CVector &v);
CVehicle *FindPlayerVehicle(void);
CVehicle *FindPlayerTrain(void);
diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp
index 9d5e2162..3d1439c6 100644
--- a/src/animation/RpAnimBlend.cpp
+++ b/src/animation/RpAnimBlend.cpp
@@ -48,7 +48,7 @@ CAnimBlendAssociation*
RpAnimBlendGetNextAssociation(CAnimBlendAssociation *assoc)
{
if(assoc->link.next)
- CAnimBlendAssociation::FromLink(assoc->link.next);
+ return CAnimBlendAssociation::FromLink(assoc->link.next);
return nil;
}
diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp
index bfa24ab0..0bed8d4d 100644
--- a/src/audio/DMAudio.cpp
+++ b/src/audio/DMAudio.cpp
@@ -18,9 +18,12 @@ WRAPPER void cDMAudio::ChangeMusicMode(uint8 mode) { EAXJMP(0x57CCF0); }
WRAPPER void cDMAudio::PlayFrontEndSound(uint32, uint32) { EAXJMP(0x57CC20); }
WRAPPER void cDMAudio::PlayOneShot(int, uint16, float) { EAXJMP(0x57C840); }
-WRAPPER int cDMAudio::GetRadioInCar() { EAXJMP(0x57CE40); }
-WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); }
-WRAPPER void cDMAudio::SetEffectsFadeVol(int16) { EAXJMP(0x57C8F0); }
-WRAPPER void cDMAudio::SetMusicFadeVol(int16) { EAXJMP(0x57C920); }
+WRAPPER int32 cDMAudio::GetRadioInCar() { EAXJMP(0x57CE40); }
+WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); }
+WRAPPER void cDMAudio::SetEffectsFadeVol(uint8) { EAXJMP(0x57C8F0); }
+WRAPPER void cDMAudio::SetMusicFadeVol(uint8) { EAXJMP(0x57C920); }
+WRAPPER int32 cDMAudio::CreateEntity(int, void*) { EAXJMP(0x57C7C0); }
+WRAPPER void cDMAudio::SetEntityStatus(int32, int8) { EAXJMP(0x57C810); }
+WRAPPER void cDMAudio::SetRadioInCar(int32) { EAXJMP(0x57CE60); } \ No newline at end of file
diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h
index bf9b65b9..6df2ceea 100644
--- a/src/audio/DMAudio.h
+++ b/src/audio/DMAudio.h
@@ -189,10 +189,13 @@ public:
void ChangeMusicMode(uint8 mode);
void PlayFrontEndSound(uint32, uint32);
void PlayOneShot(int, uint16, float);
- int GetRadioInCar();
+ int32 GetRadioInCar(void);
+ void SetEffectsFadeVol(uint8);
+ void SetMusicFadeVol(uint8);
+ int32 CreateEntity(int, void*);
+ void SetEntityStatus(int32, int8);
+ void SetRadioInCar(int32);
uint8 IsMP3RadioChannelAvailable();
- void SetEffectsFadeVol(int16);
- void SetMusicFadeVol(int16);
};
extern cDMAudio &DMAudio;
diff --git a/src/config.h b/src/config.h
index 1cd532ee..83aa7b8f 100644
--- a/src/config.h
+++ b/src/config.h
@@ -59,6 +59,7 @@ enum Config {
NUMONSCREENTIMERENTRIES = 1,
NUMRADARBLIPS = 32,
+ NUMPICKUPS = 336,
};
#define GTA3_1_1_PATCH
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index ff73e405..4ce856f7 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -6,3 +6,4 @@ int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38;
WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); }
WRAPPER void CCarCtrl::AddToCarArray(int id, int vehclass) { EAXJMP(0x4182F0); }
+WRAPPER void CCarCtrl::UpdateCarCount(CVehicle*, bool) { EAXJMP(0x4202E0); } \ No newline at end of file
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index 06204ddd..cc9327ee 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -7,6 +7,7 @@ class CCarCtrl
public:
static void SwitchVehicleToRealPhysics(CVehicle*);
static void AddToCarArray(int id, int vehclass);
+ static void UpdateCarCount(CVehicle*, bool);
static int32 &NumLawEnforcerCars;
};
diff --git a/src/control/PhoneInfo.cpp b/src/control/PhoneInfo.cpp
new file mode 100644
index 00000000..dbb7acc5
--- /dev/null
+++ b/src/control/PhoneInfo.cpp
@@ -0,0 +1,6 @@
+#include "common.h"
+#include "patcher.h"
+#include "PhoneInfo.h"
+
+WRAPPER void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F570); }
+WRAPPER void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F470); } \ No newline at end of file
diff --git a/src/control/PhoneInfo.h b/src/control/PhoneInfo.h
new file mode 100644
index 00000000..a29043ed
--- /dev/null
+++ b/src/control/PhoneInfo.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "AnimBlendAssociation.h"
+
+void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg);
+void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg); \ No newline at end of file
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 63aaa08e..cec13c8a 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -2,6 +2,8 @@
#include "patcher.h"
#include "Pickups.h"
+CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98;
+
WRAPPER void CPickups::RenderPickUpText(void) { EAXJMP(0x432440); }
WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index d2c3628c..3ae2764c 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -1,9 +1,14 @@
#pragma once
+#include "config.h"
+#include "Pickup.h"
+
class CPickups
{
public:
static void RenderPickUpText(void);
+
+ static CPickup(&aPickUps)[NUMPICKUPS];
};
class CPacManPickups
diff --git a/src/control/Population.cpp b/src/control/Population.cpp
index 9327452b..ebb48a93 100644
--- a/src/control/Population.cpp
+++ b/src/control/Population.cpp
@@ -1,4 +1,7 @@
#include "common.h"
+#include "patcher.h"
#include "Population.h"
-bool &CPopulation::ms_bGivePedsWeapons = *(bool*)0x95CCF6; \ No newline at end of file
+bool &CPopulation::ms_bGivePedsWeapons = *(bool*)0x95CCF6;
+
+WRAPPER void CPopulation::UpdatePedCount(uint32, bool) { EAXJMP(0x4F5A60); } \ No newline at end of file
diff --git a/src/control/Population.h b/src/control/Population.h
index ce27657a..a5572cdb 100644
--- a/src/control/Population.h
+++ b/src/control/Population.h
@@ -1,7 +1,11 @@
#pragma once
+#include "PedType.h"
+
class CPopulation
{
public:
static bool &ms_bGivePedsWeapons;
+
+ static void UpdatePedCount(uint32, bool);
}; \ No newline at end of file
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index a3d8ff1b..8003b407 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -1,16 +1,29 @@
#include "common.h"
#include "patcher.h"
+#include "AnimBlendAssociation.h"
#include "BulletTraces.h"
+#include "CarCtrl.h"
#include "Clock.h"
+#include "DMAudio.h"
#include "Draw.h"
#include "math/Matrix.h"
#include "ModelIndices.h"
-#include "Replay.h"
+#include "ModelInfo.h"
+#include "Object.h"
#include "Pad.h"
+#include "PhoneInfo.h"
+#include "Pickups.h"
#include "Pools.h"
+#include "Population.h"
+#include "Replay.h"
+#include "RpAnimBlend.h"
+#include "RwHelper.h"
#include "CutsceneMgr.h"
+#include "render/Skidmarks.h"
+#include "Streaming.h"
#include "Timer.h"
#include "Weather.h"
+#include "Zones.h"
#include "Font.h"
#include "Text.h"
@@ -43,11 +56,71 @@ bool &CReplay::bReplayEnabled = *(bool*)0x617CAC;
uint32 &CReplay::SlowMotion = *(uint32*)0x9414D4;
uint32 &CReplay::FramesActiveLookAroundCam = *(uint32*)0x880F84;
bool &CReplay::bDoLoadSceneWhenDone = *(bool*)0x95CD76;
+CPtrList &CReplay::WorldPtrList = *(CPtrList*)0x880F90;
+CPtrList &CReplay::BigBuildingPtrList = *(CPtrList*)0x941284;
+CWanted &CReplay::PlayerWanted = *(CWanted*)0x8F6278;
+CPlayerInfo &CReplay::PlayerInfo = *(CPlayerInfo*)0x8F5840;
+uint32 &CReplay::Time1 = *(uint32*)0x8F29DC;
+uint32 &CReplay::Time2 = *(uint32*)0x8F29D0;
+uint32 &CReplay::Time3 = *(uint32*)0x8F29D4;
+uint32 &CReplay::Time4 = *(uint32*)0x8F29C8;
+uint32 &CReplay::Frame = *(uint32*)0x8F2554;
+uint8 &CReplay::ClockHours = *(uint8*)0x95CDC5;
+uint8 &CReplay::ClockMinutes = *(uint8*)0x95CDA2;
+uint16 &CReplay::OldWeatherType = *(uint16*)0x95CCEA;
+uint16 &CReplay::NewWeatherType = *(uint16*)0x95CC6E;
+float &CReplay::WeatherInterpolationValue = *(float*)0x8F1A28;
+float &CReplay::TimeStepNonClipped = *(float*)0x8F5FF4;
+float &CReplay::TimeStep = *(float*)0x8F2C24;
+float &CReplay::TimeScale = *(float*)0x880E20;
+float &CReplay::CameraFixedX = *(float*)0x943054;
+float &CReplay::CameraFixedY = *(float*)0x943058;
+float &CReplay::CameraFixedZ = *(float*)0x94305C;
+int32 &CReplay::OldRadioStation = *(int32*)0x94151C;
+int8 &CReplay::CameraMode = *(int8*)0x95CD5F;
+bool &CReplay::bAllowLookAroundCam = *(bool*)0x95CDCD;
+float &CReplay::LoadSceneX = *(float*)0x880F9C;
+float &CReplay::LoadSceneY = *(float*)0x880F98;
+float &CReplay::LoadSceneZ = *(float*)0x880F94;
+
+#if 1
+static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))*(uintptr*)0x61052C;
+#else
+static void(*CBArray[])(CAnimBlendAssociation*, void*) =
+{
+ nil, &CPed::PedGetupCB, &CPed::PedStaggerCB, &CPed::PedEvadeCB, &CPed::FinishDieAnimCB,
+ &CPed::FinishedWaitCB, &CPed::FinishLaunchCB, &CPed::FinishHitHeadCB, &CPed::PedAnimGetInCB, &CPed::PedAnimDoorOpenCB,
+ &CPed::PedAnimPullPedOutCB, &CPed::PedAnimDoorCloseCB, &CPed::SetInCarCB, &CPed::PedSetOutCarCB, &CPed::PedAnimAlignCB,
+ &CPed::PedSetDraggedOutCarCB, &CPed::PedAnimStepOutCarCB, &CPed::PedSetInTrainCB, &CPed::PedSetOutTrainCB, &CPed::FinishedAttackCB,
+ &CPed::FinishFightMoveCB, &PhonePutDownCB, &PhonePickUpCB, &CPed::PedAnimDoorCloseRollingCB, &CPed::FinishJumpCB,
+ &CPed::PedLandCB, &FinishFuckUCB, &CPed::RestoreHeadingRateCB, &CPed::PedSetQuickDraggedOutCarPositionCB, &CPed::PedSetDraggedOutCarPositionCB
+};
+#endif
+
+#if 0
+WRAPPER uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*)) { EAXJMP(0x584E70); }
+#else
+static uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*))
+{
+ for (int i = 0; i < sizeof(CBArray) / sizeof(*CBArray); i++){
+ if (CBArray[i] == f)
+ return i;
+ }
+ return 0;
+}
+#endif
+
+static void(*FindCBFunction(uint8 id))(CAnimBlendAssociation*, void*)
+{
+ return CBArray[id];
+}
+
+WRAPPER static void ApplyPanelDamageToCar(uint32, CAutomobile*, bool) { EAXJMP(0x584EA0); }
void PrintElementsInPtrList(void)
{
for (CPtrNode* node = CWorld::GetBigBuildingList(LEVEL_NONE).first; node; node = node->next) {
- // Most likely debug print was present here
+ /* Most likely debug print was present here */
}
}
@@ -134,7 +207,6 @@ void CReplay::Update(void)
#if 0
WRAPPER void CReplay::RecordThisFrame(void) { EAXJMP(0x5932B0); }
#else
-
void CReplay::RecordThisFrame(void)
{
tGeneralPacket* general = (tGeneralPacket*)&Record.m_pBase[Record.m_nOffset];
@@ -184,7 +256,7 @@ void CReplay::RecordThisFrame(void)
if (!CBulletTraces::aTraces[i].m_bInUse)
continue;
tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset];
- bt->type = REPLAYPACKET_BULLETTRACES;
+ bt->type = REPLAYPACKET_BULLET_TRACES;
bt->index = i;
bt->frames = CBulletTraces::aTraces[i].m_bFramesInUse;
bt->lifetime = CBulletTraces::aTraces[i].m_bLifeTime;
@@ -212,29 +284,451 @@ void CReplay::RecordThisFrame(void)
MarkEverythingAsNew();
}
#endif
+
+#if 0
WRAPPER void CReplay::StorePedUpdate(CPed *ped, int id) { EAXJMP(0x5935B0); }
+#else
+void CReplay::StorePedUpdate(CPed *ped, int id)
+{
+ tPedUpdatePacket* pp = (tPedUpdatePacket*)&Record.m_pBase[Record.m_nOffset];
+ pp->type = REPLAYPACKET_PED_UPDATE;
+ pp->index = id;
+ pp->heading = 128.0f / M_PI * ped->m_fRotationCur;
+ pp->matrix.CompressFromFullMatrix(ped->GetMatrix());
+ pp->assoc_group_id = ped->m_animGroup;
+ /* Would be more sane to use GetJustIndex(ped->m_pMyVehicle) in following assignment */
+ if (ped->bInVehicle && ped->m_pMyVehicle)
+ pp->vehicle_index = (CPools::GetVehiclePool()->GetIndex(ped->m_pMyVehicle) >> 8) + 1;
+ else
+ pp->vehicle_index = 0;
+ pp->weapon_model = ped->m_wepModelID;
+ StorePedAnimation(ped, &pp->anim_state);
+ Record.m_nOffset += sizeof(tPedUpdatePacket);
+}
+#endif
+
+#if 0
WRAPPER void CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state) { EAXJMP(0x593670); }
+#else
+void CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state)
+{
+ CAnimBlendAssociation* second;
+ float blend_amount;
+ CAnimBlendAssociation* main = RpAnimBlendClumpGetMainAssociation((RpClump*)ped->m_rwObject, &second, &blend_amount);
+ if (main){
+ state->animId = main->animId;
+ state->time = 255.0f / 4.0f * max(0.0f, min(4.0f, main->currentTime));
+ state->speed = 255.0f / 3.0f * max(0.0f, min(3.0f, main->speed));
+ }else{
+ state->animId = 3;
+ state->time = 0;
+ state->speed = 85;
+ }
+ if (second) {
+ state->secAnimId = second->animId;
+ state->secTime = 255.0f / 4.0f * max(0.0f, min(4.0f, second->currentTime));
+ state->secSpeed = 255.0f / 3.0f * max(0.0f, min(3.0f, second->speed));
+ state->blendAmount = 255.0f / 2.0f * max(0.0f, min(2.0f, blend_amount));
+ }else{
+ state->secAnimId = 0;
+ state->secTime = 0;
+ state->secSpeed = 0;
+ state->blendAmount = 0;
+ }
+ CAnimBlendAssociation* partial = RpAnimBlendClumpGetMainPartialAssociation((RpClump*)ped->m_rwObject);
+ if (partial) {
+ state->partAnimId = partial->animId;
+ state->partAnimTime = 255.0f / 4.0f * max(0.0f, min(4.0f, partial->currentTime));
+ state->partAnimSpeed = 255.0f / 3.0f * max(0.0f, min(3.0f, partial->speed));
+ state->partBlendAmount = 255.0f / 2.0f * max(0.0f, min(2.0f, partial->blendAmount));
+ }else{
+ state->partAnimId = 0;
+ state->partAnimTime = 0;
+ state->partAnimSpeed = 0;
+ state->partBlendAmount = 0;
+ }
+}
+#endif
+
+#if 0
WRAPPER void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state) { EAXJMP(0x593BB0); }
+#else
+void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state)
+{
+ for (int i = 0; i < 3; i++){
+ CAnimBlendAssociation* assoc = RpAnimBlendClumpGetMainAssociation_N((RpClump*)ped->m_rwObject, i);
+ if (assoc){
+ state->aAnimId[i] = assoc->animId;
+ state->aCurTime[i] = 255.0f / 4.0f * max(0.0f, min(4.0f, assoc->currentTime));
+ state->aSpeed[i] = 255.0f / 3.0f * max(0.0f, min(3.0f, assoc->speed));
+ state->aBlendAmount[i] = 255.0f / 2.0f * max(0.0f, min(2.0f, assoc->blendAmount));
+ state->aFlags[i] = assoc->flags;
+ if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH || assoc->callbackType == CAnimBlendAssociation::CB_DELETE) {
+ state->aFunctionCallbackID[i] = FindCBFunctionID(assoc->callback);
+ if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH)
+ state->aFunctionCallbackID[i] |= 0x80;
+ }else{
+ state->aFunctionCallbackID[i] = 0;
+ }
+ }else{
+ state->aAnimId[i] = 173; /* TODO: enum */
+ state->aCurTime[i] = 0;
+ state->aSpeed[i] = 85;
+ state->aFunctionCallbackID[i] = 0;
+ state->aFlags[i] = 0;
+ }
+ }
+ for (int i = 0; i < 6; i++) {
+ CAnimBlendAssociation* assoc = RpAnimBlendClumpGetMainPartialAssociation_N((RpClump*)ped->m_rwObject, i);
+ if (assoc) {
+ state->aAnimId2[i] = assoc->animId;
+ state->aCurTime2[i] = 255.0f / 4.0f * max(0.0f, min(4.0f, assoc->currentTime));
+ state->aSpeed2[i] = 255.0f / 3.0f * max(0.0f, min(3.0f, assoc->speed));
+ state->aBlendAmount2[i] = 255.0f / 2.0f * max(0.0f, min(2.0f, assoc->blendAmount));
+ state->aFlags2[i] = assoc->flags;
+ if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH || assoc->callbackType == CAnimBlendAssociation::CB_DELETE) {
+ state->aFunctionCallbackID2[i] = FindCBFunctionID(assoc->callback);
+ if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH)
+ state->aFunctionCallbackID2[i] |= 0x80;
+ }else{
+ state->aFunctionCallbackID2[i] = 0;
+ }
+ }
+ else {
+ state->aAnimId2[i] = 173; /* TODO: enum */
+ state->aCurTime2[i] = 0;
+ state->aSpeed2[i] = 85;
+ state->aFunctionCallbackID2[i] = 0;
+ state->aFlags2[i] = 0;
+ }
+ }
+}
+#endif
WRAPPER void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594050); }
WRAPPER void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state) { EAXJMP(0x5942A0); }
WRAPPER void CReplay::RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state) { EAXJMP(0x5944B0); }
WRAPPER void CReplay::PlaybackThisFrame(void) { EAXJMP(0x5946B0); }
+
+#if 0
WRAPPER void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) { EAXJMP(0x5947F0); }
+#else
+void CReplay::StoreCarUpdate(CVehicle *vehicle, int id)
+{
+ tVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&Record.m_pBase[Record.m_nOffset];
+ vp->type = REPLAYPACKET_VEHICLE;
+ vp->index = id;
+ vp->matrix.CompressFromFullMatrix(vehicle->GetMatrix());
+ vp->health = vehicle->m_fHealth / 4.0f; /* Not anticipated that health can be > 1000. */
+ vp->acceleration = vehicle->m_fGasPedal * 100.0f;
+ vp->panels = vehicle->IsCar() ? ((CAutomobile*)vehicle)->m_DamageManager.m_abPanelsStatus : 0;
+ vp->velocityX = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().x)); /* 8000!? */
+ vp->velocityY = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().y));
+ vp->velocityZ = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().z));
+ vp->mi = vehicle->GetModelIndex();
+ vp->primary_color = vehicle->m_currentColour1;
+ vp->secondary_color = vehicle->m_currentColour2;
+ if (vehicle->GetModelIndex() == MI_RHINO)
+ vp->car_gun = 128.0f / M_PI * ((CAutomobile*)vehicle)->m_fCarGunLR;
+ else
+ vp->wheel_state = 50.0f * vehicle->m_fSteerAngle;
+ if (vehicle->IsCar()){
+ CAutomobile* car = (CAutomobile*)vehicle;
+ for (int i = 0; i < 4; i++){
+ vp->wheel_susp_dist[i] = 50.0f * car->m_afWheelSuspDist[i];
+ vp->wheel_rotation[i] = 128.0f / M_PI * car->m_afWheelRotation[i];
+ }
+ vp->door_angles[0] = 127.0f / M_PI * car->m_aDoors[2].m_fAngle;
+ vp->door_angles[1] = 127.0f / M_PI * car->m_aDoors[3].m_fAngle;
+ vp->door_status = 0;
+ for (int i = 0; i < 6; i++){
+ if (car->m_DamageManager.m_bDoorStatus[i] == 3)
+ vp->door_status |= BIT(i);
+ }
+ }
+ Record.m_nOffset += sizeof(tVehicleUpdatePacket);
+}
+#endif
WRAPPER void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594D10); }
WRAPPER bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer) { EAXJMP(0x595240); }
WRAPPER void CReplay::FinishPlayback(void) { EAXJMP(0x595B20); }
WRAPPER void CReplay::Shutdown(void) { EAXJMP(0x595BD0); }
WRAPPER void CReplay::ProcessReplayCamera(void) { EAXJMP(0x595C40); }
+
+#if 0
WRAPPER void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) { EAXJMP(0x596030); }
+#else
+void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene)
+{
+ if (Mode != MODE_RECORD)
+ return;
+ CameraFixedX = cam_x;
+ CameraFixedY = cam_y;
+ CameraFixedZ = cam_z;
+ Mode = MODE_PLAYBACK;
+ FramesActiveLookAroundCam = 0;
+ CameraMode = cam_mode;
+ bAllowLookAroundCam = true;
+ bPlayingBackFromFile = false;
+ OldRadioStation = DMAudio.GetRadioInCar();
+ DMAudio.ChangeMusicMode(0);
+ DMAudio.SetEffectsFadeVol(0);
+ DMAudio.SetMusicFadeVol(0);
+ int current;
+ for (current = 0; current < 8; current++)
+ if (BufferStatus[current] == REPLAYBUFFER_RECORD)
+ break;
+ int first;
+ for (first = (current + 1) % 8; ; first = (first + 1) % 8)
+ if (BufferStatus[first] == REPLAYBUFFER_RECORD || BufferStatus[first] == REPLAYBUFFER_PLAYBACK)
+ break;
+ Playback.m_bSlot = first;
+ Playback.m_nOffset = 0;
+ Playback.m_pBase = Buffers[first];
+ CObject::DeleteAllTempObjectInArea(CVector(0.0f, 0.0f, 0.0f), 1000000.0f);
+ StoreStuffInMem();
+ EmptyPedsAndVehiclePools();
+ SlowMotion = 1;
+ CSkidmarks::Clear();
+ StreamAllNecessaryCarsAndPeds();
+ if (load_scene)
+ bDoLoadSceneWhenDone = false;
+ else{
+ bDoLoadSceneWhenDone = true;
+ LoadSceneX = TheCamera.GetPosition().x;
+ LoadSceneY = TheCamera.GetPosition().y;
+ LoadSceneZ = TheCamera.GetPosition().z;
+ CVector ff_coord;
+ FindFirstFocusCoordinate(&ff_coord);
+ CGame::currLevel = CTheZones::GetLevelFromPosition(ff_coord);
+ CCollision::SortOutCollisionAfterLoad();
+ CStreaming::LoadScene(ff_coord);
+ }
+ if (cam_mode == REPLAYCAMMODE_ASSTORED)
+ TheCamera.CarZoomIndicator = 5.0f;
+}
+#endif
+
+#if 1
WRAPPER void CReplay::StoreStuffInMem(void) { EAXJMP(0x5961F0); }
+#else
+void CReplay::StoreStuffInMem(void)
+{
+ CPools::GetVehiclePool()->Store(pBuf0, pBuf1);
+ CPools::GetPedPool()->Store(pBuf2, pBuf3);
+ CPools::GetObjectPool()->Store(pBuf4, pBuf5);
+ CPools::GetPtrNodePool()->Store(pBuf6, pBuf7);
+ CPools::GetEntryInfoNodePool()->Store(pBuf8, pBuf9);
+ CPools::GetDummyPool()->Store(pBuf10, pBuf11);
+ pWorld1 = (CSector*)malloc(sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y);
+ memcpy(pWorld1, CWorld::GetSector(0, 0), NUMSECTORS_X * NUMSECTORS_Y * sizeof(CSector));
+ WorldPtrList = CWorld::GetMovingEntityList(); /* Interesting way to copy a list... */
+ BigBuildingPtrList = CWorld::GetBigBuildingList(LEVEL_NONE);
+ pPickups = (CPickup*)malloc(sizeof(CPickup) * NUMPICKUPS);
+ memcpy(pPickups, CPickups::aPickUps, NUMPICKUPS * sizeof(CPickup));
+ pReferences = (CReference*)malloc(sizeof(CReference) * NUMREFERENCES);
+ memcpy(pReferences, CReferences::aRefs, NUMREFERENCES * sizeof(CReference));
+ pEmptyReferences = CReferences::pEmptyList;
+ pStoredCam = (CCamera*)malloc(sizeof(CCamera));
+ memcpy(pStoredCam, &TheCamera, sizeof(CCamera));
+ pRadarBlips = (CBlip*)malloc(sizeof(CBlip) * NUMBLIPS);
+ memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMBLIPS * sizeof(CBlip));
+ PlayerWanted = *FindPlayerPed()->m_pWanted;
+ PlayerInfo = CWorld::Players[0];
+ Time1 = CTimer::GetTimeInMilliseconds();
+ Time2 = CTimer::GetTimeInMillisecondsNonClipped();
+ Time3 = CTimer::GetPreviousTimeInMilliseconds();
+ Time4 = CTimer::GetTimeInMillisecondsPauseMode();
+ Frame = CTimer::GetFrameCounter();
+ ClockHours = CClock::GetHours();
+ ClockMinutes = CClock::GetMinutes();
+ OldWeatherType = CWeather::OldWeatherType;
+ NewWeatherType = CWeather::NewWeatherType;
+ WeatherInterpolationValue = CWeather::InterpolationValue;
+ TimeStepNonClipped = CTimer::GetTimeStepNonClipped();
+ TimeStep = CTimer::GetTimeStep();
+ TimeScale = CTimer::GetTimeScale();
+ int size = CPools::GetPedPool()->GetSize();
+ pPedAnims = (CStoredDetailedAnimationState*)malloc(size * sizeof(CStoredDetailedAnimationState));
+ for (int i = 0; i < size; i++) {
+ CPed* ped = CPools::GetPedPool()->GetSlot(i);
+ if (ped)
+ StoreDetailedPedAnimation(ped, &pPedAnims[i]);
+ }
+}
+#endif
+
+#if 1
WRAPPER void CReplay::RestoreStuffFromMem(void) { EAXJMP(0x5966E0); }
+#else
+void CReplay::RestoreStuffFromMem(void)
+{
+ CPools::GetVehiclePool()->CopyBack(pBuf0, pBuf1);
+ CPools::GetPedPool()->CopyBack(pBuf2, pBuf3);
+ CPools::GetObjectPool()->CopyBack(pBuf4, pBuf5);
+ CPools::GetPtrNodePool()->CopyBack(pBuf6, pBuf7);
+ CPools::GetEntryInfoNodePool()->CopyBack(pBuf8, pBuf9);
+ CPools::GetDummyPool()->CopyBack(pBuf10, pBuf11);
+ memcpy(CWorld::GetSector(0, 0), pWorld1, sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y);
+ free(pWorld1);
+ pWorld1 = nil;
+ CWorld::GetMovingEntityList() = WorldPtrList;
+ CWorld::GetBigBuildingList(LEVEL_NONE) = BigBuildingPtrList;
+ memcpy(CPickups::aPickUps, pPickups, sizeof(CPickup) * NUMPICKUPS);
+ free(pPickups);
+ pPickups = nil;
+ memcpy(CReferences::aRefs, pReferences, sizeof(CReference) * NUMREFERENCES);
+ free(pReferences);
+ pReferences = nil;
+ CReferences::pEmptyList = pEmptyReferences;
+ pEmptyReferences = nil;
+ memcpy(&TheCamera, pStoredCam, sizeof(CCamera));
+ free(pStoredCam);
+ pStoredCam = nil;
+ memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(CBlip) * NUMBLIPS);
+ free(pRadarBlips);
+ pRadarBlips = nil;
+ FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted); /* Nice memory leak */
+ CWorld::Players[0] = PlayerInfo;
+ int size = CPools::GetPedPool()->GetSize();
+ for (int i = size - 1; i >= 0; i--){
+ CPed* ped = CPools::GetPedPool()->GetSlot(i);
+ if (!ped)
+ continue;
+ int mi = ped->GetModelIndex();
+ CStreaming::RequestModel(mi, 0);
+ CStreaming::LoadAllRequestedModels(false);
+ ped->m_rwObject = nil;
+ ped->m_modelIndex = -1;
+ ped->SetModelIndex(mi);
+ ped->m_pVehicleAnim = 0;
+ ped->uAudioEntityId = DMAudio.CreateEntity(0, ped);
+ DMAudio.SetEntityStatus(ped->uAudioEntityId, 1);
+ CPopulation::UpdatePedCount(ped->m_nPedType, false);
+ if (ped->m_wepModelID >= 0)
+ ped->AddWeaponModel(ped->m_wepModelID);
+ }
+ size = CPools::GetVehiclePool()->GetSize();
+ for (int i = size - 1; i >= 0; i--) {
+ CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!vehicle)
+ continue;
+ int mi = vehicle->GetModelIndex();
+ CStreaming::RequestModel(mi, 0);
+ CStreaming::LoadAllRequestedModels(false);
+ vehicle->m_rwObject = nil;
+ vehicle->m_modelIndex = -1;
+ vehicle->SetModelIndex(mi);
+ if (mi == MI_DODO){
+ CAutomobile* dodo = (CAutomobile*)vehicle;
+ GetFirstObject(dodo->m_apModelNodes[4])->flags = 0; /* TODO: 4 to enum */
+ CMatrix tmp1;
+ tmp1.Attach(&dodo->m_apModelNodes[1]->modelling, false);
+ CMatrix tmp2(&dodo->m_apModelNodes[4]->modelling, false);
+ *tmp1.GetPosition() += CVector(tmp2.GetPosition()->x + 0.1f, 0.0f, tmp2.GetPosition()->z);
+ tmp1.UpdateRW();
+ }
+ if (vehicle->IsCar()){
+ CAutomobile* car = (CAutomobile*)vehicle;
+ int32 panels = car->m_DamageManager.m_abPanelsStatus;
+ car->m_DamageManager.m_abPanelsStatus = 0;
+ ApplyPanelDamageToCar(panels, car, true);
+ car->SetDoorDamage(17, 0, true); /* BONNET */
+ car->SetDoorDamage(18, 1, true); /* BUMPER */
+ car->SetDoorDamage(15, 2, true); /* DOOR_FRONT_LEFT */
+ car->SetDoorDamage(11, 3, true); /* DOOR_FRONT_RIGHT */
+ car->SetDoorDamage(16, 4, true); /* DOOR_BACK_LEFT */
+ car->SetDoorDamage(12, 5, true); /* DOOR_BACK_RIGHT */
+ }
+ vehicle->uAudioEntityId = DMAudio.CreateEntity(0, vehicle);
+ DMAudio.SetEntityStatus(vehicle->uAudioEntityId, 1);
+ CCarCtrl::UpdateCarCount(vehicle, false);
+ if ((mi == MI_AIRTRAIN || mi == MI_DEADDODO) && vehicle->m_rwObject){
+ CVehicleModelInfo* info = (CVehicleModelInfo*)CModelInfo::GetModelInfo(mi);
+ if (RwObjectGetType(vehicle->m_rwObject) == rpATOMIC){
+ vehicle->GetMatrix().Detach();
+ if (vehicle->m_rwObject){
+ if (RwObjectGetType(vehicle->m_rwObject) == rpATOMIC){
+ RwFrame* frame = RpAtomicGetFrame(vehicle->m_rwObject);
+ RpAtomicDestroy((RpAtomic*)vehicle->m_rwObject);
+ RwFrameDestroy(frame);
+ }
+ vehicle->m_rwObject = nil;
+ }
+ }else{
+ vehicle->DeleteRwObject();
+ int model_id = info->m_wheelId;
+ if (model_id != -1){
+ if ((vehicle->m_rwObject = CModelInfo::GetModelInfo(model_id)->CreateInstance())){
+ vehicle->GetMatrix().AttachRW(&((RwFrame*)vehicle->m_rwObject->parent)->modelling, false);
+ }
+ }
+ }
+ }
+ }
+ PrintElementsInPtrList();
+ size = CPools::GetObjectPool()->GetSize();
+ for (int i = size - 1; i >= 0; i--) {
+ CObject* object = CPools::GetObjectPool()->GetSlot(i);
+ if (!object)
+ continue;
+ int mi = object->GetModelIndex();
+ CStreaming::RequestModel(mi, 0);
+ CStreaming::LoadAllRequestedModels(false);
+ object->m_rwObject = nil;
+ object->m_modelIndex = -1;
+ object->SetModelIndex(mi);
+ object->GetMatrix().m_attachment = nil;
+ if (RwObjectGetType(object->m_rwObject) == rpATOMIC)
+ object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(object->m_rwObject)), false);
+ }
+ size = CPools::GetDummyPool()->GetSize();
+ for (int i = size - 1; i >= 0; i--) {
+ CDummy* dummy = CPools::GetDummyPool()->GetSlot(i);
+ if (!dummy)
+ continue;
+ int mi = dummy->GetModelIndex();
+ CStreaming::RequestModel(mi, 0);
+ CStreaming::LoadAllRequestedModels(false);
+ dummy->m_rwObject = nil;
+ dummy->m_modelIndex = -1;
+ dummy->SetModelIndex(mi);
+ dummy->GetMatrix().m_attachment = nil;
+ if (RwObjectGetType(dummy->m_rwObject) == rpATOMIC)
+ dummy->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(dummy->m_rwObject)), false);
+ }
+ CTimer::SetTimeInMilliseconds(Time1);
+ CTimer::SetTimeInMillisecondsNonClipped(Time2);
+ CTimer::SetPreviousTimeInMilliseconds(Time3);
+ CTimer::SetTimeInMillisecondsPauseMode(Time4);
+ CTimer::SetTimeScale(TimeScale);
+ CTimer::SetFrameCounter(Frame);
+ CTimer::SetTimeStep(TimeStep);
+ CTimer::SetTimeStepNonClipped(TimeStepNonClipped);
+ CClock::SetGameClock(ClockHours, ClockMinutes);
+ CWeather::OldWeatherType = OldWeatherType;
+ CWeather::NewWeatherType = NewWeatherType;
+ CWeather::InterpolationValue = WeatherInterpolationValue;
+ size = CPools::GetPedPool()->GetSize();
+ for (int i = 0; i < size; i++) {
+ CPed* ped = CPools::GetPedPool()->GetSlot(i);
+ if (!ped)
+ continue;
+ RetrieveDetailedPedAnimation(ped, &pPedAnims[i]);
+ }
+ free(pPedAnims);
+ pPedAnims = nil;
+ DMAudio.ChangeMusicMode(0);
+ DMAudio.SetRadioInCar(OldRadioStation);
+ DMAudio.ChangeMusicMode(1);
+}
+#endif
WRAPPER void CReplay::EmptyPedsAndVehiclePools(void) { EAXJMP(0x5970E0); }
WRAPPER void CReplay::EmptyAllPools(void) { EAXJMP(0x5971B0); }
WRAPPER void CReplay::MarkEverythingAsNew(void) { EAXJMP(0x597280); }
WRAPPER void CReplay::SaveReplayToHD(void) { EAXJMP(0x597330); }
WRAPPER void PlayReplayFromHD(void) { EAXJMP(0x597420); }
WRAPPER void CReplay::StreamAllNecessaryCarsAndPeds(void) { EAXJMP(0x597560); }
-WRAPPER void CReplay::FindFirstFocusCoordinate(CVector *coord) { EAXJMP(0x5975E00); }
+WRAPPER void CReplay::FindFirstFocusCoordinate(CVector *coord) { EAXJMP(0x5975E0); }
WRAPPER bool CReplay::ShouldStandardCameraBeProcessed(void) { EAXJMP(0x597680); }
WRAPPER void CReplay::ProcessLookAroundCam(void) { EAXJMP(0x5976C0); }
WRAPPER size_t CReplay::FindSizeOfPacket(uint8 type) { EAXJMP(0x597CC0); }
@@ -262,4 +756,5 @@ InjectHook(0x592FE0, CReplay::Init, PATCH_JUMP);
InjectHook(0x593150, CReplay::DisableReplays, PATCH_JUMP);
InjectHook(0x593150, CReplay::EnableReplays, PATCH_JUMP);
InjectHook(0x593170, CReplay::Update, PATCH_JUMP);
+//InjectHook(0x5966E0, CReplay::RestoreStuffFromMem, PATCH_JUMP);
ENDPATCHES
diff --git a/src/control/Replay.h b/src/control/Replay.h
index b37bd29f..b622788f 100644
--- a/src/control/Replay.h
+++ b/src/control/Replay.h
@@ -7,6 +7,7 @@
#include "Radar.h"
#include "References.h"
#include "Vehicle.h"
+#include "Wanted.h"
#include "World.h"
#include "common.h"
@@ -19,33 +20,33 @@ struct CAddressInReplayBuffer
struct CStoredAnimationState
{
- int8 animId;
- int8 time;
- int8 speed;
- int8 secAnimId;
- int8 secTime;
- int8 secSpeed;
- int8 blendAmount;
- int8 partAnimId;
- int8 partAnimTime;
- int8 partAnimSpeed;
- int8 partBlendAmount;
+ uint8 animId;
+ uint8 time;
+ uint8 speed;
+ uint8 secAnimId;
+ uint8 secTime;
+ uint8 secSpeed;
+ uint8 blendAmount;
+ uint8 partAnimId;
+ uint8 partAnimTime;
+ uint8 partAnimSpeed;
+ uint8 partBlendAmount;
};
struct CStoredDetailedAnimationState
{
- int8 m_abAnimId[3];
- int8 m_abCurTime[3];
- int8 m_abSpeed[3];
- int8 m_abBlendAmount[3];
- int8 m_abFunctionCallbackID[3];
- int16 m_awFlags[3];
- int8 m_abAnimId2[6];
- int8 m_abCurTime2[6];
- int8 m_abSpeed2[6];
- int8 m_abBlendAmount2[6];
- int8 m_abFunctionCallbackID2[6];
- int16 m_awFlags2[6];
+ uint8 aAnimId[3];
+ uint8 aCurTime[3];
+ uint8 aSpeed[3];
+ uint8 aBlendAmount[3];
+ uint8 aFunctionCallbackID[3];
+ uint16 aFlags[3];
+ uint8 aAnimId2[6];
+ uint8 aCurTime2[6];
+ uint8 aSpeed2[6];
+ uint8 aBlendAmount2[6];
+ uint8 aFunctionCallbackID2[6];
+ uint16 aFlags2[6];
};
class CReplay
@@ -65,13 +66,13 @@ class CReplay
REPLAYPACKET_END = 0,
REPLAYPACKET_VEHICLE = 1,
REPLAYPACKET_PED_HEADER = 2,
- REPLAYPACKET_PED = 3,
+ REPLAYPACKET_PED_UPDATE = 3,
REPLAYPACKET_GENERAL = 4,
REPLAYPACKET_CLOCK = 5,
REPLAYPACKET_WEATHER = 6,
REPLAYPACKET_ENDOFFRAME = 7,
REPLAYPACKET_TIMER = 8,
- REPLAYPACKET_BULLETTRACES = 9
+ REPLAYPACKET_BULLET_TRACES = 9
};
enum {
@@ -146,6 +147,44 @@ class CReplay
};
static_assert(sizeof(tEndOfFramePacket) == 4, "tEndOfFramePacket: error");
+ struct tPedUpdatePacket
+ {
+ uint8 type;
+ uint8 index;
+ int8 heading;
+ int8 vehicle_index;
+ CStoredAnimationState anim_state;
+ CCompressedMatrixNotAligned matrix;
+ uint8 assoc_group_id;
+ uint8 weapon_model;
+ };
+ static_assert(sizeof(tPedUpdatePacket) == 40, "tPedUpdatePacket: error");
+
+ struct tVehicleUpdatePacket
+ {
+ uint8 type;
+ uint8 index;
+ uint8 health;
+ uint8 acceleration;
+ CCompressedMatrixNotAligned matrix;
+ int8 door_angles[2];
+ uint16 mi;
+ uint32 panels;
+ int8 velocityX;
+ int8 velocityY;
+ int8 velocityZ;
+ union{
+ int8 car_gun;
+ uint8 wheel_state;
+ };
+ uint8 wheel_susp_dist[4];
+ uint8 wheel_rotation[4];
+ uint8 door_status;
+ uint8 primary_color;
+ uint8 secondary_color;
+ };
+ static_assert(sizeof(tVehicleUpdatePacket) == 48, "tVehicleUpdatePacket: error");
+
private:
static uint8 &Mode;
static CAddressInReplayBuffer &Record;
@@ -176,6 +215,32 @@ private:
static uint32 &SlowMotion;
static uint32 &FramesActiveLookAroundCam;
static bool &bDoLoadSceneWhenDone;
+ static CPtrList &WorldPtrList;
+ static CPtrList &BigBuildingPtrList;
+ static CWanted &PlayerWanted;
+ static CPlayerInfo &PlayerInfo;
+ static uint32 &Time1;
+ static uint32 &Time2;
+ static uint32 &Time3;
+ static uint32 &Time4;
+ static uint32 &Frame;
+ static uint8 &ClockHours;
+ static uint8 &ClockMinutes;
+ static uint16 &OldWeatherType;
+ static uint16 &NewWeatherType;
+ static float &WeatherInterpolationValue;
+ static float &TimeStepNonClipped;
+ static float &TimeStep;
+ static float &TimeScale;
+ static float &CameraFixedX;
+ static float &CameraFixedY;
+ static float &CameraFixedZ;
+ static int32 &OldRadioStation;
+ static int8 &CameraMode;
+ static bool &bAllowLookAroundCam;
+ static float &LoadSceneX;
+ static float &LoadSceneY;
+ static float &LoadSceneZ;
public:
static void Init(void);
@@ -206,7 +271,9 @@ private:
static bool PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer);
static void ProcessReplayCamera(void);
static void StoreStuffInMem(void);
+public: /* temp */
static void RestoreStuffFromMem(void);
+private:
static void EmptyPedsAndVehiclePools(void);
static void EmptyAllPools(void);
static void MarkEverythingAsNew(void);
diff --git a/src/entities/Automobile.cpp b/src/entities/Automobile.cpp
new file mode 100644
index 00000000..89fac33e
--- /dev/null
+++ b/src/entities/Automobile.cpp
@@ -0,0 +1,5 @@
+#include "common.h"
+#include "patcher.h"
+#include "Automobile.h"
+
+WRAPPER void CAutomobile::SetDoorDamage(int32, uint32, bool) { EAXJMP(0x530200); } \ No newline at end of file
diff --git a/src/entities/Automobile.h b/src/entities/Automobile.h
index 379124e6..7422112b 100644
--- a/src/entities/Automobile.h
+++ b/src/entities/Automobile.h
@@ -1,14 +1,26 @@
#pragma once
+#include "DamageManager.h"
+#include "Door.h"
+#include "RwHelper.h"
#include "Vehicle.h"
class CAutomobile : public CVehicle
{
public:
// 0x288
- uint8 stuff1[484];
+ CDamageManager m_DamageManager;
+ CDoor m_aDoors[6];
+ RwFrame *m_apModelNodes[20];
+ uint8 stuff1[160];
float m_afWheelSuspDist[4];
- uint8 stuff2[300];
+ uint8 stuff2[44];
+ float m_afWheelRotation[4];
+ uint8 stuff3[200];
+ float m_fCarGunLR;
+ uint8 stuff4[36];
+
+ void SetDoorDamage(int32, uint32, bool); /* TODO: eDoors */
};
static_assert(sizeof(CAutomobile) == 0x5A8, "CAutomobile: error");
static_assert(offsetof(CAutomobile, m_afWheelSuspDist) == 0x46C, "CAutomobile: error");
diff --git a/src/entities/Object.cpp b/src/entities/Object.cpp
index 35a64604..8c7cc4c9 100644
--- a/src/entities/Object.cpp
+++ b/src/entities/Object.cpp
@@ -63,6 +63,8 @@ CObject::Render(void)
CEntity::Render();
}
+WRAPPER void CObject::DeleteAllTempObjectInArea(CVector, float) { EAXJMP(0x4BBED0); }
+
STARTPATCHES
InjectHook(0x4BB1E0, &CObject::Render_, PATCH_JUMP);
ENDPATCHES
diff --git a/src/entities/Object.h b/src/entities/Object.h
index 2079ff0e..a156609c 100644
--- a/src/entities/Object.h
+++ b/src/entities/Object.h
@@ -71,6 +71,7 @@ public:
void ObjectDamage(float amount);
+ static void DeleteAllTempObjectInArea(CVector, float);
void Render_(void) { CObject::Render(); }
};
diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp
index 5a4c736e..4f5147b9 100644
--- a/src/entities/Ped.cpp
+++ b/src/entities/Ped.cpp
@@ -249,7 +249,7 @@ CheckForPedsOnGroundToAttack(CPlayerPed *player, CPed **pedOnGround)
foundDead = 1;
if (!deadPed)
deadPed = (CPed*)currentPed;
- } else if (currentPed->IsPedHeadAbovePos(-0.6f)) {
+ } else if (!currentPed->IsPedHeadAbovePos(-0.6f)) {
foundOnTheFloor = 1;
if (!pedOnTheFloor)
pedOnTheFloor = (CPed*)currentPed;
@@ -1463,6 +1463,30 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
}
+WRAPPER void CPed::PedGetupCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE810); }
+WRAPPER void CPed::PedStaggerCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8D0); }
+WRAPPER void CPed::PedEvadeCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D36E0); }
+WRAPPER void CPed::FinishDieAnimCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D3950); }
+WRAPPER void CPed::FinishedWaitCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D6520); }
+WRAPPER void CPed::FinishLaunchCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D7490); }
+WRAPPER void CPed::FinishHitHeadCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D7A80); }
+WRAPPER void CPed::PedAnimGetInCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DEC80); }
+WRAPPER void CPed::PedAnimDoorOpenCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DE500); }
+WRAPPER void CPed::PedAnimPullPedOutCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DEAF0); }
+WRAPPER void CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DF1B0); }
+WRAPPER void CPed::SetInCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CF220); }
+WRAPPER void CPed::PedSetOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8F0); }
+WRAPPER void CPed::PedAnimAlignCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DE130); }
+WRAPPER void CPed::PedAnimStepOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DF5C0); }
+WRAPPER void CPed::PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E3290); }
+WRAPPER void CPed::PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E36E0); }
+WRAPPER void CPed::FinishFightMoveCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E9830); }
+WRAPPER void CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E4B90); }
+WRAPPER void CPed::FinishJumpCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D7A50); }
+WRAPPER void CPed::PedLandCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8A0); }
+WRAPPER void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4C6620); }
+WRAPPER void CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D6550); }
+
STARTPATCHES
InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP);
InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP);
diff --git a/src/entities/Ped.h b/src/entities/Ped.h
index 187bd08c..34c7a485 100644
--- a/src/entities/Ped.h
+++ b/src/entities/Ped.h
@@ -303,10 +303,32 @@ public:
static void GetPositionToOpenCarDoor(CVector* output, CVehicle* veh, uint32 enterType);
static RwObject *SetPedAtomicVisibilityCB(RwObject *object, void *data);
static RwFrame *RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data);
- static void FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg);
- static void PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg);
- static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg);
- static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg);
+ static void PedGetupCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedStaggerCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedEvadeCB(CAnimBlendAssociation *assoc, void *arg);
+ static void FinishDieAnimCB(CAnimBlendAssociation *assoc, void *arg);
+ static void FinishedWaitCB(CAnimBlendAssociation *assoc, void *arg);
+ static void FinishLaunchCB(CAnimBlendAssociation *assoc, void *arg);
+ static void FinishHitHeadCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedAnimGetInCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedAnimDoorOpenCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedAnimPullPedOutCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedAnimDoorCloseCB(CAnimBlendAssociation *assoc, void *arg);
+ static void SetInCarCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedSetOutCarCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedAnimAlignCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedSetDraggedOutCarCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedAnimStepOutCarCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg);
+ static void FinishedAttackCB(CAnimBlendAssociation *assoc, void *arg);
+ static void FinishFightMoveCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedAnimDoorCloseRollingCB(CAnimBlendAssociation *assoc, void *arg);
+ static void FinishJumpCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedLandCB(CAnimBlendAssociation *assoc, void *arg);
+ static void RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);
+ static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);
bool HasWeapon(eWeaponType weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; }
CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; }
@@ -320,6 +342,8 @@ public:
static bool &bPedCheat3;
};
+void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg);
+
static_assert(offsetof(CPed, m_nPedState) == 0x224, "CPed: error");
static_assert(offsetof(CPed, m_pCurSurface) == 0x2FC, "CPed: error");
static_assert(offsetof(CPed, m_pMyVehicle) == 0x310, "CPed: error");
diff --git a/src/math/Matrix.h b/src/math/Matrix.h
index 74e3d70d..e2e5394e 100644
--- a/src/math/Matrix.h
+++ b/src/math/Matrix.h
@@ -270,3 +270,37 @@ Multiply3x3(const CMatrix &mat, const CVector &vec)
mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z,
mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z);
}
+
+class CCompressedMatrixNotAligned
+{
+ CVector m_vecPos;
+ int8 m_rightX;
+ int8 m_rightY;
+ int8 m_rightZ;
+ int8 m_upX;
+ int8 m_upY;
+ int8 m_upZ;
+public:
+ void CompressFromFullMatrix(CMatrix &other)
+ {
+ m_rightX = 127.0f * other.GetRight()->x;
+ m_rightY = 127.0f * other.GetRight()->y;
+ m_rightZ = 127.0f * other.GetRight()->z;
+ m_upX = 127.0f * other.GetForward()->x;
+ m_upY = 127.0f * other.GetForward()->y;
+ m_upZ = 127.0f * other.GetForward()->z;
+ m_vecPos = *other.GetPosition();
+ }
+ void DecompressIntoFullMatrix(CMatrix &other)
+ {
+ other.GetRight()->x = m_rightX / 127.0f;
+ other.GetRight()->y = m_rightY / 127.0f;
+ other.GetRight()->z = m_rightZ / 127.0f;
+ other.GetForward()->x = m_upX / 127.0f;
+ other.GetForward()->y = m_upY / 127.0f;
+ other.GetForward()->z = m_upZ / 127.0f;
+ *other.GetUp() = CrossProduct(*other.GetRight(), *other.GetForward());
+ *other.GetPosition() = m_vecPos;
+ other.Reorthogonalise();
+ }
+}; \ No newline at end of file
diff --git a/src/render/Renderer.h b/src/render/Renderer.h
index e9e056c6..433035a0 100644
--- a/src/render/Renderer.h
+++ b/src/render/Renderer.h
@@ -23,8 +23,9 @@ class CRenderer
static CVector &ms_vecCameraPosition;
static CVehicle *&m_pFirstPersonVehicle;
- static bool &m_loadingPriority;
public:
+ static bool &m_loadingPriority;
+
static void Init(void);
static void PreRender(void);
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index 678e1cdc..fd5e7d2b 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -2,4 +2,6 @@
#include "patcher.h"
#include "Skidmarks.h"
+WRAPPER void CSkidmarks::Clear(void) { EAXJMP(0x518130); }
+
WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); }
diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h
index dcd61652..d1e1d996 100644
--- a/src/render/Skidmarks.h
+++ b/src/render/Skidmarks.h
@@ -3,5 +3,6 @@
class CSkidmarks
{
public:
+ static void Clear(void);
static void Render(void);
};
diff --git a/src/templates.h b/src/templates.h
index d1ef99f0..7ed7043e 100644
--- a/src/templates.h
+++ b/src/templates.h
@@ -101,26 +101,26 @@ public:
n++;
return n;
}
- void ClearStorage(uint8 **flags, U **entries){
- delete[] flags;
- delete[] entries;
- *flags = nil;
- *entries = nil;
- }
- void CopyBack(uint8 **flags, U **entries){
- memcpy(m_flags, *flags, sizeof(Flags)*m_size);
- memcpy(m_entries, *entries, sizeof(U)*m_size);
- debug("Size copied:%d (%d)", sizeof(U)*m_size, sizeof(Flags)*m_size);
+ void ClearStorage(uint8 *&flags, U *&entries){
+ free(flags);
+ free(entries);
+ flags = nil;
+ entries = nil;
+ }
+ void CopyBack(uint8 *&flags, U *&entries){
+ memcpy(m_flags, flags, sizeof(uint8)*m_size);
+ memcpy(m_entries, entries, sizeof(U)*m_size);
+ debug("Size copied:%d (%d)\n", sizeof(U)*m_size, sizeof(Flags)*m_size);
m_allocPtr = 0;
ClearStorage(flags, entries);
- debug("CopyBack:%d (/%d)", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
- }
- void Store(uint8 **flags, U** entries){
- *flags = (Flags*)malloc(sizeof(Flags)*m_size);
- *entries = (U*)malloc(sizeof(U)*m_size);
- memcpy(*flags, m_flags, sizeof(Flags)*m_size);
- memcpy(*entries, m_entries, sizeof(U)*m_size);
- debug("Stored:%d (/%d)", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
+ debug("CopyBack:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
+ }
+ void Store(uint8 *&flags, U *&entries){
+ flags = (uint8*)malloc(sizeof(uint8)*m_size);
+ entries = (U*)malloc(sizeof(U)*m_size);
+ memcpy(flags, m_flags, sizeof(uint8)*m_size);
+ memcpy(entries, m_entries, sizeof(U)*m_size);
+ debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
}
};