summaryrefslogtreecommitdiffstats
path: root/src/control
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/control/CarCtrl.cpp2
-rw-r--r--src/control/CarCtrl.h2
-rw-r--r--src/control/PedPlacement.cpp4
-rw-r--r--src/control/Replay.cpp566
-rw-r--r--src/control/Replay.h23
5 files changed, 542 insertions, 55 deletions
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index 145c643c..1b389631 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -3,6 +3,8 @@
#include "CarCtrl.h"
int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38;
+int &CCarCtrl::NumAmbulancesOnDuty = *(int*)0x885BB0;
+int &CCarCtrl::NumFiretrucksOnDuty = *(int*)0x9411F0;
bool &CCarCtrl::bCarsGeneratedAroundCamera = *(bool*)0x95CD8A;
WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); }
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index 3469dcf1..0195219e 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -11,5 +11,7 @@ public:
static int32 ChooseCarModel(int32 vehclass);
static int32 &NumLawEnforcerCars;
+ static int32 &NumAmbulancesOnDuty;
+ static int32 &NumFiretrucksOnDuty;
static bool &bCarsGeneratedAroundCamera;
};
diff --git a/src/control/PedPlacement.cpp b/src/control/PedPlacement.cpp
index de4cdae1..e9a3f7d9 100644
--- a/src/control/PedPlacement.cpp
+++ b/src/control/PedPlacement.cpp
@@ -19,14 +19,14 @@ CPedPlacement::FindZCoorForPed(CVector* pos)
pos->z + 1.0f
);
- if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, false))
+ if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, nil))
foundColZ = foundCol.point.z;
// Adjust coords and do a second test
vec.x += 0.1f;
vec.y += 0.1f;
- if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, false))
+ if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, nil))
foundColZ2 = foundCol.point.z;
zForPed = max(foundColZ, foundColZ2);
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index 055c4ada..b6a7b8c2 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -1,11 +1,14 @@
#include "common.h"
#include "patcher.h"
#include "AnimBlendAssociation.h"
+#include "Boat.h"
#include "BulletTraces.h"
#include "CarCtrl.h"
+#include "CivilianPed.h"
#include "Clock.h"
#include "DMAudio.h"
#include "Draw.h"
+#include "Heli.h"
#include "math/Matrix.h"
#include "ModelIndices.h"
#include "ModelInfo.h"
@@ -13,6 +16,7 @@
#include "Pad.h"
#include "PhoneInfo.h"
#include "Pickups.h"
+#include "Plane.h"
#include "Pools.h"
#include "Population.h"
#include "Replay.h"
@@ -22,6 +26,7 @@
#include "render/Skidmarks.h"
#include "Streaming.h"
#include "Timer.h"
+#include "Train.h"
#include "Weather.h"
#include "Zones.h"
#include "Font.h"
@@ -42,13 +47,13 @@ uint8 *&CReplay::pBuf8 = *(uint8**)0x8E2C54;
CEntryInfoNode *&CReplay::pBuf9 = *(CEntryInfoNode**)0x8E2C58;
uint8 *&CReplay::pBuf10 = *(uint8**)0x8F2C28;
CDummyPed *&CReplay::pBuf11 = *(CDummyPed**)0x8F2C2C;
-CBlip *&CReplay::pRadarBlips = *(CBlip**)0x8F29F8;
-CCamera *&CReplay::pStoredCam = *(CCamera**)0x8F2C34;
-CSector *&CReplay::pWorld1 = *(CSector**)0x8E29C4;
+uint8 *&CReplay::pRadarBlips = *(uint8**)0x8F29F8;
+uint8 *&CReplay::pStoredCam = *(uint8**)0x8F2C34;
+uint8 *&CReplay::pWorld1 = *(uint8**)0x8E29C4;
CReference *&CReplay::pEmptyReferences = *(CReference**)0x8F256C;
CStoredDetailedAnimationState *&CReplay::pPedAnims = *(CStoredDetailedAnimationState**)0x8F6260;
-CPickup *&CReplay::pPickups = *(CPickup**)0x8F1A48;
-CReference *&CReplay::pReferences = *(CReference**)0x880FAC;
+uint8 *&CReplay::pPickups = *(uint8**)0x8F1A48;
+uint8 *&CReplay::pReferences = *(uint8**)0x880FAC;
uint8(&CReplay::BufferStatus)[8] = *(uint8(*)[8])*(uintptr*)0x8804D8;
uint8(&CReplay::Buffers)[8][100000] = *(uint8(*)[8][100000])*(uintptr*)0x779958;
bool &CReplay::bPlayingBackFromFile = *(bool*)0x95CD58;
@@ -82,11 +87,13 @@ bool &CReplay::bAllowLookAroundCam = *(bool*)0x95CDCD;
float &CReplay::LoadSceneX = *(float*)0x880F9C;
float &CReplay::LoadSceneY = *(float*)0x880F98;
float &CReplay::LoadSceneZ = *(float*)0x880F94;
+float &CReplay::CameraFocusX = *(float*)0x942F5C;
+float &CReplay::CameraFocusY = *(float*)0x942F74;
+float &CReplay::CameraFocusZ = *(float*)0x942F58;
+bool &CReplay::bPlayerInRCBuggy = *(bool*)0x95CDC3;
-#if 1
static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))*(uintptr*)0x61052C;
-#else
-static void(*CBArray[])(CAnimBlendAssociation*, void*) =
+static void(*CBArray_RE3[])(CAnimBlendAssociation*, void*) =
{
nil, &CPed::PedGetupCB, &CPed::PedStaggerCB, &CPed::PedEvadeCB, &CPed::FinishDieAnimCB,
&CPed::FinishedWaitCB, &CPed::FinishLaunchCB, &CPed::FinishHitHeadCB, &CPed::PedAnimGetInCB, &CPed::PedAnimDoorOpenCB,
@@ -95,7 +102,6 @@ static void(*CBArray[])(CAnimBlendAssociation*, void*) =
&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); }
@@ -106,13 +112,17 @@ static uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*))
if (CBArray[i] == f)
return i;
}
+ for (int i = 0; i < sizeof(CBArray_RE3) / sizeof(*CBArray_RE3); i++) {
+ if (CBArray_RE3[i] == f)
+ return i;
+ }
return 0;
}
#endif
static void(*FindCBFunction(uint8 id))(CAnimBlendAssociation*, void*)
{
- return CBArray[id];
+ return CBArray_RE3[id];
}
WRAPPER static void ApplyPanelDamageToCar(uint32, CAutomobile*, bool) { EAXJMP(0x584EA0); }
@@ -165,8 +175,6 @@ void CReplay::Init(void)
bDoLoadSceneWhenDone = false;
}
-WRAPPER void CReplay::EmptyReplayBuffer(void) { EAXJMP(0x595BD0); }
-
void CReplay::DisableReplays(void)
{
bReplayEnabled = false;
@@ -373,7 +381,7 @@ void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState
state->aFunctionCallbackID[i] = 0;
}
}else{
- state->aAnimId[i] = 173; /* TODO: enum */
+ state->aAnimId[i] = NUM_ANIMS;
state->aCurTime[i] = 0;
state->aSpeed[i] = 85;
state->aFunctionCallbackID[i] = 0;
@@ -397,7 +405,7 @@ void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState
}
}
else {
- state->aAnimId2[i] = 173; /* TODO: enum */
+ state->aAnimId2[i] = NUM_ANIMS;
state->aCurTime2[i] = 0;
state->aSpeed2[i] = 85;
state->aFunctionCallbackID2[i] = 0;
@@ -406,10 +414,165 @@ void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState
}
}
#endif
+#if 0
WRAPPER void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594050); }
+#else
+void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer)
+{
+ tPedUpdatePacket *pp = (tPedUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset];
+ if (!ped){
+ debug("Replay:Ped wasn't there\n");
+ buffer->m_nOffset += sizeof(tPedUpdatePacket);
+ return;
+ }
+ ped->m_fRotationCur = pp->heading * M_PI / 128.0f;
+ ped->m_fRotationDest = pp->heading * M_PI / 128.0f;
+ CMatrix ped_matrix;
+ pp->matrix.DecompressIntoFullMatrix(ped_matrix);
+ ped->GetMatrix() = ped->GetMatrix() * CMatrix(1.0f - interpolation);
+ *ped->GetMatrix().GetPosition() *= (1.0f - interpolation);
+ ped->GetMatrix() += CMatrix(interpolation) * ped_matrix;
+ if (pp->vehicle_index) {
+ ped->m_pMyVehicle = CPools::GetVehiclePool()->GetSlot(pp->vehicle_index - 1);
+ ped->bInVehicle = pp->vehicle_index;
+ }
+ else {
+ ped->m_pMyVehicle = nil;
+ ped->bInVehicle = false;
+ }
+ if (pp->assoc_group_id != ped->m_animGroup) {
+ ped->m_animGroup = (AssocGroupId)pp->assoc_group_id;
+ if (ped == FindPlayerPed())
+ ((CPlayerPed*)ped)->ReApplyMoveAnims();
+ }
+ RetrievePedAnimation(ped, &pp->anim_state);
+ ped->RemoveWeaponModel(-1);
+ if (pp->weapon_model != (uint8)-1)
+ ped->AddWeaponModel(pp->weapon_model);
+ CWorld::Remove(ped);
+ CWorld::Add(ped);
+ buffer->m_nOffset += sizeof(tPedUpdatePacket);
+}
+#endif
+
+#if 0
WRAPPER void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state) { EAXJMP(0x5942A0); }
+#else
+void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state)
+{
+ CAnimBlendAssociation* anim1 = CAnimManager::BlendAnimation(
+ (RpClump*)ped->m_rwObject,
+ (state->animId > 3) ? ASSOCGRP_STD : ped->m_animGroup,
+ (AnimationId)state->animId, 100.0f);
+ anim1->SetCurrentTime(state->time * 4.0f / 255.0f);
+ anim1->speed = state->speed * 3.0f / 255.0f;
+ anim1->SetBlend(1.0f, 1.0f);
+ anim1->callbackType = CAnimBlendAssociation::CB_NONE;
+ if (state->blendAmount && state->secAnimId){
+ float time = state->secTime * 4.0f / 255.0f;
+ float speed = state->secSpeed * 3.0f / 255.0f;
+ float blend = state->blendAmount * 2.0f / 255.0f;
+ CAnimBlendAssociation* anim2 = CAnimManager::BlendAnimation(
+ (RpClump*)ped->m_rwObject,
+ (state->secAnimId > 3) ? ASSOCGRP_STD : ped->m_animGroup,
+ (AnimationId)state->secAnimId, 100.0f);
+ anim2->SetCurrentTime(time);
+ anim2->speed = speed;
+ anim2->SetBlend(blend, 1.0f);
+ anim2->callbackType = CAnimBlendAssociation::CB_NONE;
+ }
+ RpAnimBlendClumpRemoveAssociations((RpClump*)ped->m_rwObject, 0x10);
+ if (state->partAnimId){
+ float time = state->partAnimTime * 4.0f / 255.0f;
+ float speed = state->partAnimSpeed * 3.0f / 255.0f;
+ float blend = state->partBlendAmount * 2.0f / 255.0f;
+ if (blend > 0.0f && state->partAnimId != ANIM_IDLE_STANCE){
+ CAnimBlendAssociation* anim3 = CAnimManager::BlendAnimation(
+ (RpClump*)ped->m_rwObject, ASSOCGRP_STD, (AnimationId)state->partAnimId, 1000.0f);
+ anim3->SetCurrentTime(time);
+ anim3->speed = speed;
+ anim3->SetBlend(blend, 0.0f);
+ }
+ }
+}
+#endif
+
+#if 0
WRAPPER void CReplay::RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state) { EAXJMP(0x5944B0); }
+#else
+void CReplay::RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state)
+{
+ for (int i = 0; i < 3; i++){
+ if (state->aAnimId[i] == NUM_ANIMS)
+ continue;
+ CAnimBlendAssociation* anim = CAnimManager::BlendAnimation(
+ (RpClump*)ped->m_rwObject,
+ state->aAnimId[i] > 3 ? ASSOCGRP_STD : ped->m_animGroup,
+ (AnimationId)state->aAnimId[i], 100.0f);
+ anim->SetCurrentTime(state->aCurTime[i] * 4.0f / 255.0f);
+ anim->speed = state->aSpeed[i] * 3.0f / 255.0f;
+ /* Lack of commented out calculation causes megajump */
+ anim->SetBlend(state->aBlendAmount[i] /* * 2.0f / 255.0f */, 1.0f);
+ anim->flags = state->aFlags[i];
+ uint8 callback = state->aFunctionCallbackID[i];
+ if (!callback)
+ anim->callbackType = CAnimBlendAssociation::CB_NONE;
+ else if (callback & 0x80)
+ anim->SetFinishCallback(FindCBFunction(callback & 0x7F), ped);
+ else
+ anim->SetDeleteCallback(FindCBFunction(callback & 0x7F), ped);
+ }
+ for (int i = 0; i < 6; i++) {
+ if (state->aAnimId2[i] == NUM_ANIMS)
+ continue;
+ CAnimBlendAssociation* anim = CAnimManager::BlendAnimation(
+ (RpClump*)ped->m_rwObject,
+ state->aAnimId2[i] > 3 ? ASSOCGRP_STD : ped->m_animGroup,
+ (AnimationId)state->aAnimId2[i], 100.0f);
+ anim->SetCurrentTime(state->aCurTime2[i] * 4.0f / 255.0f);
+ anim->speed = state->aSpeed2[i] * 3.0f / 255.0f;
+ /* Lack of commented out calculation causes megajump */
+ anim->SetBlend(state->aBlendAmount2[i] /* * 2.0f / 255.0f */, 1.0f);
+ anim->flags = state->aFlags2[i];
+ uint8 callback = state->aFunctionCallbackID2[i];
+ if (!callback)
+ anim->callbackType = CAnimBlendAssociation::CB_NONE;
+ else if (callback & 0x80)
+ anim->SetFinishCallback(FindCBFunction(callback & 0x7F), ped);
+ else
+ anim->SetDeleteCallback(FindCBFunction(callback & 0x7F), ped);
+ }
+}
+#endif
+
+#if 0
WRAPPER void CReplay::PlaybackThisFrame(void) { EAXJMP(0x5946B0); }
+#else
+void CReplay::PlaybackThisFrame(void)
+{
+ static int SlowMotionCounter = 0;
+ CAddressInReplayBuffer buf = Playback;
+ if (PlayBackThisFrameInterpolation(&buf, 1.0f, nil)){
+ DMAudio.SetEffectsFadeVol(127);
+ DMAudio.SetMusicFadeVol(127);
+ return;
+ }
+ if (SlowMotionCounter){
+ CAddressInReplayBuffer buf_sm = buf;
+ if (PlayBackThisFrameInterpolation(&buf_sm, SlowMotionCounter * 1.0f / SlowMotion, nil)){
+ DMAudio.SetEffectsFadeVol(127);
+ DMAudio.SetMusicFadeVol(127);
+ return;
+ }
+ }
+ SlowMotionCounter = (SlowMotionCounter + 1) % SlowMotion;
+ if (SlowMotionCounter == 0)
+ Playback = buf;
+ ProcessLookAroundCam();
+ DMAudio.SetEffectsFadeVol(0);
+ DMAudio.SetMusicFadeVol(0);
+}
+#endif
#if 0
WRAPPER void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) { EAXJMP(0x5947F0); }
@@ -450,10 +613,325 @@ void CReplay::StoreCarUpdate(CVehicle *vehicle, int id)
Record.m_nOffset += sizeof(tVehicleUpdatePacket);
}
#endif
+
+#if 0
WRAPPER void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594D10); }
+#else
+void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer)
+{
+ tVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset];
+ if (!vehicle){
+ debug("Replay:Car wasn't there");
+ return;
+ }
+ CMatrix vehicle_matrix;
+ vp->matrix.DecompressIntoFullMatrix(vehicle_matrix);
+ vehicle->GetMatrix() = vehicle->GetMatrix() * CMatrix(1.0f - interpolation);
+ *vehicle->GetMatrix().GetPosition() *= (1.0f - interpolation);
+ vehicle->GetMatrix() += CMatrix(interpolation) * vehicle_matrix;
+ vehicle->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ vehicle->m_fHealth = 4 * vp->health;
+ vehicle->m_fGasPedal = vp->acceleration / 100.0f;
+ if (vehicle->IsCar())
+ ApplyPanelDamageToCar(vp->panels, (CAutomobile*)vehicle, true);
+ vehicle->m_vecMoveSpeed = CVector(vp->velocityX / 8000.0f, vp->velocityY / 8000.0f, vp->velocityZ / 8000.0f);
+ if (vehicle->GetModelIndex() == MI_RHINO) {
+ ((CAutomobile*)vehicle)->m_fCarGunLR = vp->car_gun * M_PI / 128.0f;
+ vehicle->m_fSteerAngle = 0.0f;
+ }else{
+ vehicle->m_fSteerAngle = vp->wheel_state / 50.0f;
+ }
+ if (vehicle->IsCar()) {
+ CAutomobile* car = (CAutomobile*)vehicle;
+ for (int i = 0; i < 4; i++) {
+ car->m_afWheelSuspDist[i] = vp->wheel_susp_dist[i] / 50.0f;
+ car->m_afWheelRotation[i] = vp->wheel_rotation[i] * M_PI / 128.0f;
+ }
+ car->m_aDoors[2].m_fAngle = car->m_aDoors[2].m_fPreviousAngle = vp->door_angles[0] * M_PI / 127.0f;
+ car->m_aDoors[3].m_fAngle = car->m_aDoors[3].m_fPreviousAngle = vp->door_angles[1] * M_PI / 127.0f;
+ if (vp->door_angles[0])
+ car->m_DamageManager.m_bDoorStatus[2] = 2;
+ if (vp->door_angles[1])
+ car->m_DamageManager.m_bDoorStatus[3] = 2;
+ if (vp->door_status & 1 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_BONNET) != 3){
+ car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_BONNET, 3);
+ car->SetDoorDamage(17, CDamageManager::CAR_DOOR_BONNET, true);
+ }
+ if (vp->door_status & 2 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_BUMPER) != 3) {
+ car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_BUMPER, 3);
+ car->SetDoorDamage(18, CDamageManager::CAR_DOOR_BUMPER, true);
+ }
+ if (vp->door_status & 4 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_LF) != 3) {
+ car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_LF, 3);
+ car->SetDoorDamage(15, CDamageManager::CAR_DOOR_LF, true);
+ }
+ if (vp->door_status & 8 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_RF) != 3) {
+ car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_RF, 3);
+ car->SetDoorDamage(11, CDamageManager::CAR_DOOR_RF, true);
+ }
+ if (vp->door_status & 0x10 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_LR) != 3) {
+ car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_LR, 3);
+ car->SetDoorDamage(16, CDamageManager::CAR_DOOR_LR, true);
+ }
+ if (vp->door_status & 0x20 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_RR) != 3) {
+ car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_RR, 3);
+ car->SetDoorDamage(12, CDamageManager::CAR_DOOR_RR, true);
+ }
+ vehicle->m_veh_flagA10 = true;
+ if (vehicle->IsCar())
+ ((CAutomobile*)vehicle)->m_nDriveWheelsOnGround = 4;
+ CWorld::Remove(vehicle);
+ CWorld::Add(vehicle);
+ if (vehicle->IsBoat())
+ ((CBoat*)vehicle)->m_bIsAnchored = false;
+ }
+}
+#endif
+
+#if 0
WRAPPER bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer) { EAXJMP(0x595240); }
+#else
+bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer){
+ /* Mistake. Not even sure what this is even doing here...
+ * PlayerWanted is a backup to restore at the end of replay.
+ * Setting current wanted pointer to it makes it useless.
+ * Causes picking up bribes in replays reducing wanted level bug.
+ * Obviously fact of picking them up is a bug on its own,
+ * but it doesn't cancel this one.
+ */
+ FindPlayerPed()->m_pWanted = &PlayerWanted;
+
+ CBulletTraces::Init();
+ float split = 1.0f - interpolation;
+ int ped_min_index = 0; /* Optimization due to peds and vehicles placed in buffer sequentially. */
+ int vehicle_min_index = 0; /* So next ped can't have pool index less than current. */
+ for(;;){
+ uint8* ptr = buffer->m_pBase;
+ uint32 offset = buffer->m_nOffset;
+ uint8 type = ptr[offset];
+ if (type == REPLAYPACKET_ENDOFFRAME)
+ break;
+ switch (type) {
+ case REPLAYPACKET_END:
+ {
+ int slot = buffer->m_bSlot;
+ if (BufferStatus[slot] == REPLAYBUFFER_RECORD) {
+ FinishPlayback();
+ return true;
+ }
+ buffer->m_bSlot = (slot + 1) % 8;
+ buffer->m_nOffset = 0;
+ buffer->m_pBase = Buffers[buffer->m_bSlot];
+ ped_min_index = 0;
+ vehicle_min_index = 0;
+ break;
+ }
+ case REPLAYPACKET_VEHICLE:
+ {
+ tVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&ptr[offset];
+ for (int i = vehicle_min_index; i < vp->index; i++) {
+ CVehicle* v = CPools::GetVehiclePool()->GetSlot(i);
+ if (!v)
+ continue;
+ /* Removing vehicles not present in this frame. */
+ CWorld::Remove(v);
+ delete v;
+ }
+ vehicle_min_index = vp->index + 1;
+ CVehicle* v = CPools::GetVehiclePool()->GetSlot(vp->index);
+ CVehicle* new_v;
+ if (!v) {
+ int mi = vp->mi;
+ if (CStreaming::ms_aInfoForModel[mi].m_loadState != 1) {
+ CStreaming::RequestModel(mi, 0);
+ }
+ else {
+ if (mi == MI_DEADDODO || mi == MI_AIRTRAIN) {
+ new_v = new(vp->index << 8) CPlane(mi, 2);
+ }
+ else if (mi == MI_TRAIN) {
+ new_v = new(vp->index << 8) CTrain(mi, 2);
+ }
+ else if (mi == MI_CHOPPER || mi == MI_ESCAPE) {
+ new_v = new(vp->index << 8) CHeli(mi, 2);
+ }
+ else if (CModelInfo::IsBoatModel(mi)){
+ new_v = new(vp->index << 8) CBoat(mi, 2);
+ }
+ else{
+ new_v = new(vp->index << 8) CAutomobile(mi, 2);
+ }
+ new_v->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER;
+ vp->matrix.DecompressIntoFullMatrix(new_v->GetMatrix());
+ new_v->m_currentColour1 = vp->primary_color;
+ new_v->m_currentColour2 = vp->secondary_color;
+ CWorld::Add(new_v);
+ }
+ }
+ ProcessCarUpdate(CPools::GetVehiclePool()->GetSlot(vp->index), interpolation, buffer);
+ buffer->m_nOffset += sizeof(tVehicleUpdatePacket);
+ break;
+ }
+ case REPLAYPACKET_PED_HEADER:
+ {
+ tPedHeaderPacket* ph = (tPedHeaderPacket*)&ptr[offset];
+ if (!CPools::GetPedPool()->GetSlot(ph->index)) {
+ if (CStreaming::ms_aInfoForModel[ph->mi].m_loadState != 1) {
+ CStreaming::RequestModel(ph->mi, 0);
+ }
+ else {
+ CPed* new_p = new(ph->index << 8) CCivilianPed(ph->pedtype, ph->mi);
+ new_p->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER;
+ new_p->GetMatrix().SetUnity();
+ CWorld::Add(new_p);
+ }
+ }
+ buffer->m_nOffset += sizeof(tPedHeaderPacket);
+ break;
+ }
+ case REPLAYPACKET_PED_UPDATE:
+ {
+ tPedUpdatePacket* pu = (tPedUpdatePacket*)&ptr[offset];
+ for (int i = ped_min_index; i < pu->index; i++) {
+ CPed* p = CPools::GetPedPool()->GetSlot(i);
+ if (!p)
+ continue;
+ /* Removing peds not present in this frame. */
+ CWorld::Remove(p);
+ delete p;
+ }
+ ped_min_index = pu->index + 1;
+ ProcessPedUpdate(CPools::GetPedPool()->GetSlot(pu->index), interpolation, buffer);
+ break;
+ }
+ case REPLAYPACKET_GENERAL:
+ {
+ tGeneralPacket* pg = (tGeneralPacket*)&ptr[offset];
+ TheCamera.GetMatrix() = TheCamera.GetMatrix() * CMatrix(split);
+ *TheCamera.GetMatrix().GetPosition() *= split;
+ TheCamera.GetMatrix() += CMatrix(interpolation) * pg->camera_pos;
+ RwMatrix* pm = &RpAtomicGetFrame(&TheCamera.m_pRwCamera->object.object)->modelling;
+ pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition();
+ pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward();
+ pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp();
+ pm->right = *(RwV3d*)TheCamera.GetMatrix().GetRight();
+ CameraFocusX = split * CameraFocusX + interpolation * pg->player_pos.x;
+ CameraFocusY = split * CameraFocusY + interpolation * pg->player_pos.y;
+ CameraFocusZ = split * CameraFocusZ + interpolation * pg->player_pos.z;
+ bPlayerInRCBuggy = pg->in_rcvehicle;
+ buffer->m_nOffset += sizeof(tGeneralPacket);
+ break;
+ }
+ case REPLAYPACKET_CLOCK:
+ {
+ tClockPacket* pc = (tClockPacket*)&ptr[offset];
+ CClock::SetGameClock(pc->hours, pc->minutes);
+ buffer->m_nOffset += sizeof(tClockPacket);
+ break;
+ }
+ case REPLAYPACKET_WEATHER:
+ {
+ tWeatherPacket* pw = (tWeatherPacket*)&ptr[offset];
+ CWeather::OldWeatherType = pw->old_weather;
+ CWeather::NewWeatherType = pw->new_weather;
+ CWeather::InterpolationValue = pw->interpolation;
+ buffer->m_nOffset += sizeof(tWeatherPacket);
+ break;
+ }
+ case REPLAYPACKET_ENDOFFRAME:
+ {
+ /* Not supposed to be here. */
+ buffer->m_nOffset++;
+ break;
+ }
+ case REPLAYPACKET_TIMER:
+ {
+ tTimerPacket* pt = (tTimerPacket*)&ptr[offset];
+ if (pTimer)
+ *pTimer = pt->timer;
+ CTimer::SetTimeInMilliseconds(pt->timer);
+ buffer->m_nOffset += sizeof(tTimerPacket);
+ break;
+ }
+ case REPLAYPACKET_BULLET_TRACES:
+ {
+ tBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset];
+ CBulletTraces::aTraces[pb->index].m_bInUse = true;
+ CBulletTraces::aTraces[pb->index].m_bFramesInUse = pb->frames;
+ CBulletTraces::aTraces[pb->index].m_bLifeTime = pb->lifetime;
+ CBulletTraces::aTraces[pb->index].m_vecInf = pb->inf;
+ CBulletTraces::aTraces[pb->index].m_vecSup = pb->sup;
+ buffer->m_nOffset += sizeof(tBulletTracePacket);
+ }
+ default:
+ break;
+ }
+ }
+ buffer->m_nOffset += 4;
+ for (int i = vehicle_min_index; i < CPools::GetVehiclePool()->GetSize(); i++) {
+ CVehicle* v = CPools::GetVehiclePool()->GetSlot(i);
+ if (!v)
+ continue;
+ /* Removing vehicles not present in this frame. */
+ CWorld::Remove(v);
+ delete v;
+ }
+ for (int i = ped_min_index; i < CPools::GetPedPool()->GetSize(); i++) {
+ CPed* p = CPools::GetPedPool()->GetSlot(i);
+ if (!p)
+ continue;
+ /* Removing peds not present in this frame. */
+ CWorld::Remove(p);
+ delete p;
+ }
+ ProcessReplayCamera();
+ return false;
+}
+#endif
+#if 0
WRAPPER void CReplay::FinishPlayback(void) { EAXJMP(0x595B20); }
-WRAPPER void CReplay::Shutdown(void) { EAXJMP(0x595BD0); }
+#else
+void CReplay::FinishPlayback(void)
+{
+ if (Mode != MODE_PLAYBACK)
+ return;
+ EmptyAllPools();
+ RestoreStuffFromMem();
+ Mode = MODE_RECORD;
+ if (bDoLoadSceneWhenDone){
+ CVector v_ls(LoadSceneX, LoadSceneY, LoadSceneZ);
+ CGame::currLevel = CTheZones::GetLevelFromPosition(v_ls);
+ CCollision::SortOutCollisionAfterLoad();
+ CStreaming::LoadScene(v_ls);
+ }
+ bDoLoadSceneWhenDone = false;
+ if (bPlayingBackFromFile){
+ Init();
+ MarkEverythingAsNew();
+ }
+ DMAudio.SetEffectsFadeVol(127);
+ DMAudio.SetMusicFadeVol(127);
+}
+#endif
+
+#if 0
+WRAPPER void CReplay::EmptyReplayBuffer(void) { EAXJMP(0x595BD0); }
+#else
+void CReplay::EmptyReplayBuffer(void)
+{
+ if (Mode == MODE_PLAYBACK)
+ return;
+ for (int i = 0; i < 8; i++){
+ BufferStatus[i] = REPLAYBUFFER_UNUSED;
+ }
+ Record.m_bSlot = 0;
+ Record.m_pBase = Buffers[0];
+ BufferStatus[0] = REPLAYBUFFER_RECORD;
+ Record.m_pBase[Record.m_nOffset] = 0;
+ MarkEverythingAsNew();
+}
+#endif
+
WRAPPER void CReplay::ProcessReplayCamera(void) { EAXJMP(0x595C40); }
#if 0
@@ -510,7 +988,7 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca
}
#endif
-#if 1
+#if 0
WRAPPER void CReplay::StoreStuffInMem(void) { EAXJMP(0x5961F0); }
#else
void CReplay::StoreStuffInMem(void)
@@ -521,19 +999,19 @@ void CReplay::StoreStuffInMem(void)
CPools::GetPtrNodePool()->Store(pBuf6, pBuf7);
CPools::GetEntryInfoNodePool()->Store(pBuf8, pBuf9);
CPools::GetDummyPool()->Store(pBuf10, pBuf11);
- pWorld1 = (CSector*)malloc(sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y);
+ pWorld1 = new uint8[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... */
+ WorldPtrList = CWorld::GetMovingEntityList();
BigBuildingPtrList = CWorld::GetBigBuildingList(LEVEL_NONE);
- pPickups = (CPickup*)malloc(sizeof(CPickup) * NUMPICKUPS);
+ pPickups = new uint8[sizeof(CPickup) * NUMPICKUPS];
memcpy(pPickups, CPickups::aPickUps, NUMPICKUPS * sizeof(CPickup));
- pReferences = (CReference*)malloc(sizeof(CReference) * NUMREFERENCES);
+ pReferences = new uint8[(sizeof(CReference) * NUMREFERENCES)];
memcpy(pReferences, CReferences::aRefs, NUMREFERENCES * sizeof(CReference));
pEmptyReferences = CReferences::pEmptyList;
- pStoredCam = (CCamera*)malloc(sizeof(CCamera));
+ pStoredCam = new uint8[sizeof(CCamera)];
memcpy(pStoredCam, &TheCamera, sizeof(CCamera));
- pRadarBlips = (CBlip*)malloc(sizeof(CBlip) * NUMBLIPS);
- memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMBLIPS * sizeof(CBlip));
+ pRadarBlips = new uint8[sizeof(CBlip) * NUMRADARBLIPS];
+ memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(CBlip));
PlayerWanted = *FindPlayerPed()->m_pWanted;
PlayerInfo = CWorld::Players[0];
Time1 = CTimer::GetTimeInMilliseconds();
@@ -559,7 +1037,7 @@ void CReplay::StoreStuffInMem(void)
}
#endif
-#if 1
+#if 0
WRAPPER void CReplay::RestoreStuffFromMem(void) { EAXJMP(0x5966E0); }
#else
void CReplay::RestoreStuffFromMem(void)
@@ -571,28 +1049,28 @@ void CReplay::RestoreStuffFromMem(void)
CPools::GetEntryInfoNodePool()->CopyBack(pBuf8, pBuf9);
CPools::GetDummyPool()->CopyBack(pBuf10, pBuf11);
memcpy(CWorld::GetSector(0, 0), pWorld1, sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y);
- free(pWorld1);
+ delete[] pWorld1;
pWorld1 = nil;
CWorld::GetMovingEntityList() = WorldPtrList;
CWorld::GetBigBuildingList(LEVEL_NONE) = BigBuildingPtrList;
memcpy(CPickups::aPickUps, pPickups, sizeof(CPickup) * NUMPICKUPS);
- free(pPickups);
+ delete[] pPickups;
pPickups = nil;
memcpy(CReferences::aRefs, pReferences, sizeof(CReference) * NUMREFERENCES);
- free(pReferences);
+ delete[] pReferences;
pReferences = nil;
CReferences::pEmptyList = pEmptyReferences;
pEmptyReferences = nil;
memcpy(&TheCamera, pStoredCam, sizeof(CCamera));
- free(pStoredCam);
+ delete[] pStoredCam;
pStoredCam = nil;
- memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(CBlip) * NUMBLIPS);
- free(pRadarBlips);
+ memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(CBlip) * NUMRADARBLIPS);
+ delete[] 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--){
+ int i = CPools::GetPedPool()->GetSize();
+ while (--i){
CPed* ped = CPools::GetPedPool()->GetSlot(i);
if (!ped)
continue;
@@ -609,8 +1087,8 @@ void CReplay::RestoreStuffFromMem(void)
if (ped->m_wepModelID >= 0)
ped->AddWeaponModel(ped->m_wepModelID);
}
- size = CPools::GetVehiclePool()->GetSize();
- for (int i = size - 1; i >= 0; i--) {
+ i = CPools::GetVehiclePool()->GetSize();
+ while (--i){
CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!vehicle)
continue;
@@ -668,8 +1146,8 @@ void CReplay::RestoreStuffFromMem(void)
}
}
PrintElementsInPtrList();
- size = CPools::GetObjectPool()->GetSize();
- for (int i = size - 1; i >= 0; i--) {
+ i = CPools::GetObjectPool()->GetSize();
+ while (--i){
CObject* object = CPools::GetObjectPool()->GetSlot(i);
if (!object)
continue;
@@ -683,8 +1161,8 @@ void CReplay::RestoreStuffFromMem(void)
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--) {
+ i = CPools::GetDummyPool()->GetSize();
+ while (--i){
CDummy* dummy = CPools::GetDummyPool()->GetSlot(i);
if (!dummy)
continue;
@@ -710,8 +1188,7 @@ void CReplay::RestoreStuffFromMem(void)
CWeather::OldWeatherType = OldWeatherType;
CWeather::NewWeatherType = NewWeatherType;
CWeather::InterpolationValue = WeatherInterpolationValue;
- size = CPools::GetPedPool()->GetSize();
- for (int i = 0; i < size; i++) {
+ for (int i = 0; i < CPools::GetPedPool()->GetSize(); i++) {
CPed* ped = CPools::GetPedPool()->GetSlot(i);
if (!ped)
continue;
@@ -756,7 +1233,12 @@ STARTPATCHES
InjectHook(0x592FC0, PrintElementsInPtrList, PATCH_JUMP);
InjectHook(0x592FE0, CReplay::Init, PATCH_JUMP);
InjectHook(0x593150, CReplay::DisableReplays, PATCH_JUMP);
-InjectHook(0x593150, CReplay::EnableReplays, PATCH_JUMP);
+InjectHook(0x593160, CReplay::EnableReplays, PATCH_JUMP);
InjectHook(0x593170, CReplay::Update, PATCH_JUMP);
-//InjectHook(0x5966E0, CReplay::RestoreStuffFromMem, PATCH_JUMP);
+InjectHook(0x595B20, CReplay::FinishPlayback, PATCH_JUMP);
+InjectHook(0x594050, CReplay::ProcessPedUpdate, PATCH_JUMP);
+InjectHook(0x594D10, CReplay::ProcessCarUpdate, PATCH_JUMP);
+InjectHook(0x593BB0, CReplay::StoreDetailedPedAnimation, PATCH_JUMP);
+InjectHook(0x5944B0, CReplay::RetrieveDetailedPedAnimation, PATCH_JUMP);
+InjectHook(0x596030, CReplay::TriggerPlayback, PATCH_JUMP);
ENDPATCHES
diff --git a/src/control/Replay.h b/src/control/Replay.h
index c4f3b1a2..18701293 100644
--- a/src/control/Replay.h
+++ b/src/control/Replay.h
@@ -155,7 +155,7 @@ class CReplay
int8 vehicle_index;
CStoredAnimationState anim_state;
CCompressedMatrixNotAligned matrix;
- uint8 assoc_group_id;
+ int8 assoc_group_id;
uint8 weapon_model;
};
static_assert(sizeof(tPedUpdatePacket) == 40, "tPedUpdatePacket: error");
@@ -201,13 +201,13 @@ private:
static CEntryInfoNode *&pBuf9;
static uint8 *&pBuf10;
static CDummyPed *&pBuf11;
- static CBlip *&pRadarBlips;
- static CCamera *&pStoredCam;
- static CSector *&pWorld1;
+ static uint8 *&pRadarBlips;
+ static uint8 *&pStoredCam;
+ static uint8 *&pWorld1;
static CReference *&pEmptyReferences;
static CStoredDetailedAnimationState *&pPedAnims;
- static CPickup *&pPickups;
- static CReference *&pReferences;
+ static uint8 *&pPickups;
+ static uint8 *&pReferences;
static uint8 (&BufferStatus)[8];
static uint8 (&Buffers)[8][100000];
static bool &bPlayingBackFromFile;
@@ -241,15 +241,18 @@ private:
static float &LoadSceneX;
static float &LoadSceneY;
static float &LoadSceneZ;
+ static float &CameraFocusX;
+ static float &CameraFocusY;
+ static float &CameraFocusZ;
+ static bool &bPlayerInRCBuggy;
public:
static void Init(void);
- static void EmptyReplayBuffer(void);
static void DisableReplays(void);
static void EnableReplays(void);
static void Update(void);
static void FinishPlayback(void);
- static void Shutdown(void);
+ static void EmptyReplayBuffer(void);
static void Display(void);
static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene);
static void StreamAllNecessaryCarsAndPeds(void);
@@ -258,7 +261,7 @@ public:
inline static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; }
inline static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; }
-private:
+//private:
static void RecordThisFrame(void);
static void StorePedUpdate(CPed *ped, int id);
static void StorePedAnimation(CPed *ped, CStoredAnimationState *state);
@@ -272,9 +275,7 @@ 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);