summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/BulletTrace.h12
-rw-r--r--src/BulletTraces.cpp7
-rw-r--r--src/BulletTraces.h11
-rw-r--r--src/Camera.cpp1
-rw-r--r--src/Camera.h1
-rw-r--r--src/DamageManager.h25
-rw-r--r--src/Pad.cpp30
-rw-r--r--src/Radar.cpp4
-rw-r--r--src/Skidmarks.cpp0
-rw-r--r--src/animation/RpAnimBlend.h1
-rw-r--r--src/common.h40
-rw-r--r--src/config.h54
-rw-r--r--src/control/PedStats.h4
-rw-r--r--src/control/Replay.cpp413
-rw-r--r--src/control/Replay.h10
-rw-r--r--src/entities/Automobile.cpp2
-rw-r--r--src/entities/Automobile.h2
-rw-r--r--src/entities/CivilianPed.cpp13
-rw-r--r--src/entities/CivilianPed.h6
-rw-r--r--src/entities/CutsceneObject.h12
-rw-r--r--src/entities/EmergencyPed.cpp (renamed from src/EmergencyPed.cpp)0
-rw-r--r--src/entities/Entity.h2
-rw-r--r--src/entities/Ped.cpp439
-rw-r--r--src/entities/Ped.h133
-rw-r--r--src/entities/PedIK.cpp22
-rw-r--r--src/entities/PedIK.h1
-rw-r--r--src/entities/Physical.h13
-rw-r--r--src/entities/Vehicle.h2
-rw-r--r--src/main.cpp40
-rw-r--r--src/modelinfo/VehicleModelInfo.cpp1
-rw-r--r--src/render/Draw.cpp34
-rw-r--r--src/render/Draw.h20
-rw-r--r--src/render/Hud.cpp16
-rw-r--r--src/render/SpecialFX.cpp5
-rw-r--r--src/render/SpecialFX.h17
-rw-r--r--src/render/Sprite.cpp66
-rw-r--r--src/skel/win/win.cpp42
-rw-r--r--src/skel/win/win.h4
-rw-r--r--src/weapons/Weapon.cpp37
-rw-r--r--src/weapons/Weapon.h14
-rw-r--r--src/weapons/WeaponInfo.cpp8
41 files changed, 1275 insertions, 289 deletions
diff --git a/src/BulletTrace.h b/src/BulletTrace.h
deleted file mode 100644
index d6831ef1..00000000
--- a/src/BulletTrace.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-
-#include "common.h"
-
-struct CBulletTrace
-{
- CVector m_vecInf;
- CVector m_vecSup;
- bool m_bInUse;
- uint8 m_bFramesInUse;
- uint8 m_bLifeTime;
-};
diff --git a/src/BulletTraces.cpp b/src/BulletTraces.cpp
deleted file mode 100644
index e7348a7b..00000000
--- a/src/BulletTraces.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "common.h"
-#include "patcher.h"
-#include "BulletTraces.h"
-
-CBulletTrace (&CBulletTraces::aTraces)[16] = *(CBulletTrace(*)[16])*(uintptr*)0x72B1B8;
-
-WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); }
diff --git a/src/BulletTraces.h b/src/BulletTraces.h
deleted file mode 100644
index 5a37c53c..00000000
--- a/src/BulletTraces.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-#include "BulletTrace.h"
-
-class CBulletTraces
-{
-public:
- static CBulletTrace(&aTraces)[16];
-
- static void Init(void);
-};
diff --git a/src/Camera.cpp b/src/Camera.cpp
index e2dd12ff..e5e50ef2 100644
--- a/src/Camera.cpp
+++ b/src/Camera.cpp
@@ -19,6 +19,7 @@ CCamera &TheCamera = *(CCamera*)0x6FACF8;
bool &CCamera::m_bUseMouse3rdPerson = *(bool *)0x5F03D8;
WRAPPER void CCamera::DrawBordersForWideScreen(void) { EAXJMP(0x46B430); }
+WRAPPER void CCamera::CalculateDerivedValues(void) { EAXJMP(0x46EEA0); }
bool
CCamera::IsSphereVisible(const CVector &center, float radius, const CMatrix *mat)
diff --git a/src/Camera.h b/src/Camera.h
index 2316fd5d..6d20de72 100644
--- a/src/Camera.h
+++ b/src/Camera.h
@@ -456,6 +456,7 @@ int m_iModeObbeCamIsInForCar;
void SetMotionBlur(int r, int g, int b, int a, int type);
void SetMotionBlurAlpha(int a);
void RenderMotionBlur(void);
+ void CalculateDerivedValues(void);
void DrawBordersForWideScreen(void);
diff --git a/src/DamageManager.h b/src/DamageManager.h
index 01269a42..4c1e3925 100644
--- a/src/DamageManager.h
+++ b/src/DamageManager.h
@@ -15,12 +15,35 @@ public:
CAR_DOOR_RR
};
+ enum {
+ PANEL_FL = 0,
+ PANEL_FR,
+ PANEL_RL,
+ PANEL_RR,
+ PANEL_WINDSHIELD,
+ PANEL_FRONT,
+ PANEL_BACK
+ };
+
+ struct PanelStatus {
+ uint32 m_nPanelFrontLeftStatus : 4;
+ uint32 m_nPanelFrontRightStatus : 4;
+ uint32 m_nPanelBackLeftStatus : 4;
+ uint32 m_nPanelBackRightStatus : 4;
+ uint32 m_nWindshieldStatus : 4;
+ uint32 m_nPanelFrontStatus : 4;
+ uint32 m_nPanelBackStatus : 4;
+ };
+
float field_0;
char m_bEngineStatus;
char m_bWheelStatus[4];
char m_bDoorStatus[7];
uint32 m_abLightStatus;
- uint32 m_abPanelsStatus;
+ union{
+ PanelStatus m_sPanelsStatus;
+ uint32 m_abPanelsStatus;
+ };
char field_24;
char field_25;
char field_26;
diff --git a/src/Pad.cpp b/src/Pad.cpp
index 13b9b589..002e7180 100644
--- a/src/Pad.cpp
+++ b/src/Pad.cpp
@@ -14,6 +14,7 @@
#include "Game.h"
#include "CutsceneMgr.h"
#include "Font.h"
+#include "Hud.h"
#include "Text.h"
#include "Timer.h"
#include "World.h"
@@ -24,7 +25,6 @@
#include "Weather.h"
#include "win.h"
-
CPad *Pads = (CPad*)0x6F0360; // [2]
CMousePointerStateHelper &MousePointerStateHelper = *(CMousePointerStateHelper*)0x95CC8C;
@@ -70,6 +70,28 @@ WRAPPER void StrongGripCheat() { EAXJMP(0x491670); }
WRAPPER void NastyLimbsCheat() { EAXJMP(0x4916A0); }
//////////////////////////////////////////////////////////////////////////
+#ifdef KANGAROO_CHEAT
+void KangarooCheat()
+{
+ wchar *string;
+ CPed *playerPed = FindPlayerPed();
+ int m_fMass;
+
+ if (playerPed->m_ped_flagI80) {
+ string = TheText.Get("CHEATOF");
+ m_fMass = 70.0f;
+ } else {
+ string = TheText.Get("CHEAT1");
+ m_fMass = 15.0f;
+ }
+ CHud::SetHelpMessage(string, 1);
+ playerPed->m_ped_flagI80 = !playerPed->m_ped_flagI80;
+
+ playerPed->m_fMass = m_fMass;
+ playerPed->m_fAirResistance = 0.4f / m_fMass;
+}
+#endif
+
void
CControllerState::Clear(void)
{
@@ -509,6 +531,12 @@ void CPad::AddToPCCheatString(char c)
// "NASTYLIMBSCHEAT"
if ( !_CHEATCMP("TAEHCSBMILYTSAN") )
NastyLimbsCheat();
+
+#ifdef KANGAROO_CHEAT
+ // "KANGAROO"
+ if (!_CHEATCMP("OORAGNAK"))
+ KangarooCheat();
+#endif
#undef _CHEATCMP
}
diff --git a/src/Radar.cpp b/src/Radar.cpp
index ec02144e..a071b96b 100644
--- a/src/Radar.cpp
+++ b/src/Radar.cpp
@@ -899,8 +899,8 @@ void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D
// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0)
void CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in)
{
- // FIX: game doesn't scale RADAR_LEFT here
- out.x = (in.x + 1.0f)*0.5f*SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT);
+ // FIX? scale RADAR_LEFT here somehow
+ out.x = (in.x + 1.0f)*0.5f*SCREEN_SCALE_X(RADAR_WIDTH) + RADAR_LEFT;
out.y = (1.0f - in.y)*0.5f*SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT);
}
diff --git a/src/Skidmarks.cpp b/src/Skidmarks.cpp
deleted file mode 100644
index e69de29b..00000000
--- a/src/Skidmarks.cpp
+++ /dev/null
diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h
index 24c3d273..68fa03cb 100644
--- a/src/animation/RpAnimBlend.h
+++ b/src/animation/RpAnimBlend.h
@@ -24,6 +24,7 @@ void RpAnimBlendClumpRemoveAllAssociations(RpClump *clump);
void RpAnimBlendClumpRemoveAssociations(RpClump *clump, uint32 mask);
void RpAnimBlendClumpInit(RpClump *clump);
bool RpAnimBlendClumpIsInitialized(RpClump *clump);
+void RpAnimBlendClumpFillFrameArray(RpClump* clump, AnimBlendFrameData** frames);
AnimBlendFrameData *RpAnimBlendClumpFindFrame(RpClump *clump, const char *name);
void FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg);
CAnimBlendAssociation *RpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id);
diff --git a/src/common.h b/src/common.h
index f959de42..7f304e90 100644
--- a/src/common.h
+++ b/src/common.h
@@ -67,27 +67,37 @@ extern void **rwengine;
In theory should look good on any screen.
*/
+#define DEFAULT_SCREEN_WIDTH (640)
+#define DEFAULT_SCREEN_HEIGHT (448)
+#define DEFAULT_ASPECT_RATIO (4.0f/3.0f)
+
+// game uses maximumWidth/Height, but this probably won't work
+// with RW windowed mode
+// TODO: get rid of one of the two
+#define SCREENW (RsGlobal.width)
+#define SCREENH (RsGlobal.height)
+#define SCREEN_WIDTH ((float)RsGlobal.width)
+#define SCREEN_HEIGHT ((float)RsGlobal.height)
#define SCREEN_ASPECT_RATIO (CDraw::GetAspectRatio())
-#define SCREENW (RsGlobal.maximumWidth)
-#define SCREENH (RsGlobal.maximumHeight)
+// This scales from PS2 pixel coordinates to the real resolution
+#define SCREEN_STRETCH_X(a) ((a) * (float) SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH)
+#define SCREEN_STRETCH_Y(a) ((a) * (float) SCREEN_HEIGHT / DEFAULT_SCREEN_HEIGHT)
+#define SCREEN_STRETCH_FROM_RIGHT(a) (SCREEN_WIDTH - SCREEN_STRETCH_X(a))
+#define SCREEN_STRETCH_FROM_BOTTOM(a) (SCREEN_HEIGHT - SCREEN_STRETCH_Y(a))
-#define DEFAULT_SCREEN_WIDTH (640)
-#define DEFAULT_SCREEN_HEIGHT (448)
-#define SCREEN_WIDTH float(RsGlobal.width)
-#define SCREEN_HEIGHT float(RsGlobal.height)
-#define SCREEN_STRETCH_X(a) float((a) * (SCREEN_WIDTH / float(DEFAULT_SCREEN_WIDTH)))
-#define SCREEN_STRETCH_Y(a) float((a) * (SCREEN_HEIGHT / float(DEFAULT_SCREEN_HEIGHT)))
-#define SCREEN_STRETCH_FROM_RIGHT(a) float(SCREEN_WIDTH - SCREEN_STRETCH_X(a))
-#define SCREEN_STRETCH_FROM_BOTTOM(a) float(SCREEN_HEIGHT - SCREEN_STRETCH_Y(a))
-
-#define SCREEN_MULTIPLIER (CDraw::GetScreenMult())
-#define SCREEN_SCALE(a) float((a) * (4.0f / 3.0f) / SCREEN_ASPECT_RATIO)
-#define SCREEN_SCALE_X(a) SCREEN_SCALE(SCREEN_STRETCH_X(a) * SCREEN_MULTIPLIER)
-#define SCREEN_SCALE_Y(a) (SCREEN_STRETCH_Y(a) * SCREEN_MULTIPLIER)
+// This scales from PS2 pixel coordinates while optionally maintaining the aspect ratio
+#define SCREEN_SCALE_X(a) SCREEN_SCALE_AR(SCREEN_STRETCH_X(a))
+#define SCREEN_SCALE_Y(a) SCREEN_STRETCH_Y(a)
#define SCREEN_SCALE_FROM_RIGHT(a) (SCREEN_WIDTH - SCREEN_SCALE_X(a))
#define SCREEN_SCALE_FROM_BOTTOM(a) (SCREEN_HEIGHT - SCREEN_SCALE_Y(a))
+#ifdef ASPECT_RATIO_SCALE
+#define SCREEN_SCALE_AR(a) ((a) * (4.0f / 3.0f) / SCREEN_ASPECT_RATIO)
+#else
+#define SCREEN_SCALE_AR(a) (a)
+#endif
+
#include "math/Vector.h"
#include "math/Vector2D.h"
#include "math/Matrix.h"
diff --git a/src/config.h b/src/config.h
index 61b4f9b6..a753b678 100644
--- a/src/config.h
+++ b/src/config.h
@@ -62,20 +62,52 @@ enum Config {
NUMPICKUPS = 336,
};
+
// We don't expect to compile for PS2 or Xbox
// but it might be interesting for documentation purposes
#define GTA_PC
//#define GTA_PS2
//#define GTA_XBOX
-#define GTA3_1_1_PATCH
-#define USE_PS2_RAND
-#define RANDOMSPLASH
-#define CHATTYSPLASH
-//#define FIX_BUGS
-//#define NO_CDCHECK
-#define NO_MOVIES
-//#define USE_MY_DOCUMENTS
-#define NASTY_GAME
-#define PS2_MATFX
-
+// This enables things from the PS2 version on PC
+#define GTA_PS2_STUFF
+
+// This is enabled for all released games.
+// any debug stuff that isn't left in any game is not in FINAL
+//#define FINAL
+
+// This is enabled for all released games except mobile
+// any debug stuff that is only left in mobile, is not in MASTER
+//#define MASTER
+
+#if defined GTA_PS2
+# define RANDOMSPLASH
+#elif defined GTA_PC
+# define GTA3_1_1_PATCH
+# ifdef GTA_PS2_STUFF
+# define USE_PS2_RAND
+# define RANDOMSPLASH // use random splash as on PS2
+# define PS2_MATFX
+# endif
+#elif defined GTA_XBOX
+#endif
+
+#ifdef MASTER
+ // only in master builds
+#else
+ // not in master builds
+#endif
+
+#ifdef FINAL
+ // in all games
+# define USE_MY_DOCUMENTS // use my documents directory for user files
+#else
+ // not in any game
+# define NASTY_GAME // nasty game for all languages
+# define NO_MOVIES // disable intro videos
+# define CHATTYSPLASH // print what the game is loading
+#endif
+
+#define FIX_BUGS // fix bugs in the game, TODO: use this more
+#define KANGAROO_CHEAT
+#define ASPECT_RATIO_SCALE
diff --git a/src/control/PedStats.h b/src/control/PedStats.h
index 78414341..ce92d4da 100644
--- a/src/control/PedStats.h
+++ b/src/control/PedStats.h
@@ -56,8 +56,6 @@ enum
class CPedStats
{
- static CPedStats *(&ms_apPedStats)[NUM_PEDSTATS];
-
public:
ePedStats m_type;
char m_name[24];
@@ -71,6 +69,8 @@ public:
float m_defendWeakness;
int16 m_flags;
+ static CPedStats* (&ms_apPedStats)[NUM_PEDSTATS];
+
static void Initialise(void);
static void Shutdown(void);
static void LoadPedStats(void);
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index b6a7b8c2..b80b04ba 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -2,13 +2,15 @@
#include "patcher.h"
#include "AnimBlendAssociation.h"
#include "Boat.h"
-#include "BulletTraces.h"
+#include "SpecialFX.h"
#include "CarCtrl.h"
#include "CivilianPed.h"
#include "Clock.h"
#include "DMAudio.h"
#include "Draw.h"
+#include "FileMgr.h"
#include "Heli.h"
+#include "main.h"
#include "math/Matrix.h"
#include "ModelIndices.h"
#include "ModelInfo.h"
@@ -91,6 +93,9 @@ float &CReplay::CameraFocusX = *(float*)0x942F5C;
float &CReplay::CameraFocusY = *(float*)0x942F74;
float &CReplay::CameraFocusZ = *(float*)0x942F58;
bool &CReplay::bPlayerInRCBuggy = *(bool*)0x95CDC3;
+float &CReplay::fDistanceLookAroundCam = *(float*)0x885B44;
+float &CReplay::fBetaAngleLookAroundCam = *(float*)0x94072C;
+float &CReplay::fAlphaAngleLookAroundCam = *(float*)0x8F2A0C;
static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))*(uintptr*)0x61052C;
static void(*CBArray_RE3[])(CAnimBlendAssociation*, void*) =
@@ -125,7 +130,42 @@ static void(*FindCBFunction(uint8 id))(CAnimBlendAssociation*, void*)
return CBArray_RE3[id];
}
+#if 0
WRAPPER static void ApplyPanelDamageToCar(uint32, CAutomobile*, bool) { EAXJMP(0x584EA0); }
+#else
+static void ApplyPanelDamageToCar(uint32 panels, CAutomobile* vehicle, bool flying)
+{
+ CDamageManager::PanelStatus rp = *(CDamageManager::PanelStatus*)&panels;
+ if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontLeftStatus != rp.m_nPanelFrontLeftStatus){
+ vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontLeftStatus = rp.m_nPanelFrontLeftStatus;
+ vehicle->SetPanelDamage(13, CDamageManager::PANEL_FL, flying);
+ }
+ if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontRightStatus != rp.m_nPanelFrontRightStatus) {
+ vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontRightStatus = rp.m_nPanelFrontRightStatus;
+ vehicle->SetPanelDamage(9, CDamageManager::PANEL_FR, flying);
+ }
+ if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackLeftStatus != rp.m_nPanelBackLeftStatus) {
+ vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackLeftStatus = rp.m_nPanelBackLeftStatus;
+ vehicle->SetPanelDamage(14, CDamageManager::PANEL_RL, flying);
+ }
+ if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackRightStatus != rp.m_nPanelBackRightStatus) {
+ vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackRightStatus = rp.m_nPanelBackRightStatus;
+ vehicle->SetPanelDamage(10, CDamageManager::PANEL_RR, flying);
+ }
+ if (vehicle->m_DamageManager.m_sPanelsStatus.m_nWindshieldStatus != rp.m_nWindshieldStatus) {
+ vehicle->m_DamageManager.m_sPanelsStatus.m_nWindshieldStatus = rp.m_nWindshieldStatus;
+ vehicle->SetPanelDamage(19, CDamageManager::PANEL_WINDSHIELD, flying);
+ }
+ if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontStatus != rp.m_nPanelFrontStatus) {
+ vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelFrontStatus = rp.m_nPanelFrontStatus;
+ vehicle->SetPanelDamage(7, CDamageManager::PANEL_FRONT, flying);
+ }
+ if (vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackStatus != rp.m_nPanelBackStatus) {
+ vehicle->m_DamageManager.m_sPanelsStatus.m_nPanelBackStatus = rp.m_nPanelBackStatus;
+ vehicle->SetPanelDamage(8, CDamageManager::PANEL_BACK, flying);
+ }
+}
+#endif
void PrintElementsInPtrList(void)
{
@@ -268,8 +308,8 @@ void CReplay::RecordThisFrame(void)
tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset];
bt->type = REPLAYPACKET_BULLET_TRACES;
bt->index = i;
- bt->frames = CBulletTraces::aTraces[i].m_bFramesInUse;
- bt->lifetime = CBulletTraces::aTraces[i].m_bLifeTime;
+ bt->frames = CBulletTraces::aTraces[i].m_framesInUse;
+ bt->lifetime = CBulletTraces::aTraces[i].m_lifeTime;
bt->inf = CBulletTraces::aTraces[i].m_vecInf;
bt->sup = CBulletTraces::aTraces[i].m_vecSup;
Record.m_nOffset += sizeof(*bt);
@@ -810,7 +850,7 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
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;
+ RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));
pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition();
pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward();
pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp();
@@ -857,8 +897,8 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
{
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_framesInUse = pb->frames;
+ CBulletTraces::aTraces[pb->index].m_lifeTime = pb->lifetime;
CBulletTraces::aTraces[pb->index].m_vecInf = pb->inf;
CBulletTraces::aTraces[pb->index].m_vecSup = pb->sup;
buffer->m_nOffset += sizeof(tBulletTracePacket);
@@ -932,7 +972,53 @@ void CReplay::EmptyReplayBuffer(void)
}
#endif
+#if 0
WRAPPER void CReplay::ProcessReplayCamera(void) { EAXJMP(0x595C40); }
+#else
+void CReplay::ProcessReplayCamera(void)
+{
+ switch (CameraMode) {
+ case REPLAYCAMMODE_TOPDOWN:
+ {
+ *TheCamera.GetMatrix().GetPosition() = CVector(CameraFocusX, CameraFocusY, CameraFocusZ + 15.0f);
+ *TheCamera.GetMatrix().GetForward() = CVector(0.0f, 0.0f, -1.0f);
+ *TheCamera.GetMatrix().GetUp() = CVector(0.0f, 1.0f, 0.0f);
+ *TheCamera.GetMatrix().GetRight() = CVector(1.0f, 0.0f, 0.0f);
+ RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));
+ pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition();
+ pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward();
+ pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp();
+ pm->right = *(RwV3d*)TheCamera.GetMatrix().GetRight();
+ break;
+ }
+ case REPLAYCAMMODE_FIXED:
+ {
+ *TheCamera.GetMatrix().GetPosition() = CVector(CameraFixedX, CameraFixedY, CameraFixedZ);
+ CVector forward(CameraFocusX - CameraFixedX, CameraFocusY - CameraFixedY, CameraFocusZ - CameraFixedZ);
+ forward.Normalise();
+ CVector right = CrossProduct(CVector(0.0f, 0.0f, 1.0f), forward);
+ right.Normalise();
+ CVector up = CrossProduct(forward, right);
+ up.Normalise();
+ *TheCamera.GetMatrix().GetForward() = forward;
+ *TheCamera.GetMatrix().GetUp() = up;
+ *TheCamera.GetMatrix().GetRight() = right;
+ RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));
+ pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition();
+ pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward();
+ pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp();
+ pm->right = *(RwV3d*)TheCamera.GetMatrix().GetRight();
+ break;
+ }
+ default:
+ break;
+ }
+ TheCamera.m_vecGameCamPos = *TheCamera.GetMatrix().GetPosition();
+ TheCamera.CalculateDerivedValues();
+ RwMatrixUpdate(RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)));
+ RwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera));
+}
+#endif
#if 0
WRAPPER void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) { EAXJMP(0x596030); }
@@ -1070,7 +1156,7 @@ void CReplay::RestoreStuffFromMem(void)
FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted); /* Nice memory leak */
CWorld::Players[0] = PlayerInfo;
int i = CPools::GetPedPool()->GetSize();
- while (--i){
+ while (i--){
CPed* ped = CPools::GetPedPool()->GetSlot(i);
if (!ped)
continue;
@@ -1088,7 +1174,7 @@ void CReplay::RestoreStuffFromMem(void)
ped->AddWeaponModel(ped->m_wepModelID);
}
i = CPools::GetVehiclePool()->GetSize();
- while (--i){
+ while (i--){
CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!vehicle)
continue;
@@ -1147,7 +1233,7 @@ void CReplay::RestoreStuffFromMem(void)
}
PrintElementsInPtrList();
i = CPools::GetObjectPool()->GetSize();
- while (--i){
+ while (i--){
CObject* object = CPools::GetObjectPool()->GetSlot(i);
if (!object)
continue;
@@ -1162,7 +1248,7 @@ void CReplay::RestoreStuffFromMem(void)
object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(object->m_rwObject)), false);
}
i = CPools::GetDummyPool()->GetSize();
- while (--i){
+ while (i--){
CDummy* dummy = CPools::GetDummyPool()->GetSlot(i);
if (!dummy)
continue;
@@ -1201,44 +1287,313 @@ void CReplay::RestoreStuffFromMem(void)
DMAudio.ChangeMusicMode(1);
}
#endif
+
+#if 0
WRAPPER void CReplay::EmptyPedsAndVehiclePools(void) { EAXJMP(0x5970E0); }
+#else
+void CReplay::EmptyPedsAndVehiclePools(void)
+{
+ int i = CPools::GetVehiclePool()->GetSize();
+ while (i--) {
+ CVehicle* v = CPools::GetVehiclePool()->GetSlot(i);
+ if (!v)
+ continue;
+ CWorld::Remove(v);
+ delete v;
+ }
+ i = CPools::GetPedPool()->GetSize();
+ while (i--) {
+ CPed* p = CPools::GetPedPool()->GetSlot(i);
+ if (!p)
+ continue;
+ CWorld::Remove(p);
+ delete p;
+ }
+}
+#endif
+
+#if 0
WRAPPER void CReplay::EmptyAllPools(void) { EAXJMP(0x5971B0); }
+#else
+void CReplay::EmptyAllPools(void)
+{
+ EmptyPedsAndVehiclePools();
+ int i = CPools::GetObjectPool()->GetSize();
+ while (i--) {
+ CObject* o = CPools::GetObjectPool()->GetSlot(i);
+ if (!o)
+ continue;
+ CWorld::Remove(o);
+ delete o;
+ }
+ i = CPools::GetDummyPool()->GetSize();
+ while (i--) {
+ CDummy* d = CPools::GetDummyPool()->GetSlot(i);
+ if (!d)
+ continue;
+ CWorld::Remove(d);
+ delete d;
+ }
+}
+#endif
+
+#if 0
WRAPPER void CReplay::MarkEverythingAsNew(void) { EAXJMP(0x597280); }
+#else
+void CReplay::MarkEverythingAsNew(void)
+{
+ int i = CPools::GetVehiclePool()->GetSize();
+ while (i--) {
+ CVehicle* v = CPools::GetVehiclePool()->GetSlot(i);
+ if (!v)
+ continue;
+ v->bRecordedForReplay = false;
+ }
+ i = CPools::GetPedPool()->GetSize();
+ while (i--) {
+ CPed* p = CPools::GetPedPool()->GetSlot(i);
+ if (!p)
+ continue;
+ p->bRecordedForReplay = false;
+ }
+}
+#endif
+
+#if 0
WRAPPER void CReplay::SaveReplayToHD(void) { EAXJMP(0x597330); }
+#else
+void CReplay::SaveReplayToHD(void)
+{
+ CFileMgr::SetDirMyDocuments();
+ int fw = CFileMgr::OpenFileForWriting("replay.rep");
+ if (fw < 0){
+ debug("Couldn't open replay.rep for writing");
+ CFileMgr::SetDir("");
+ return;
+ }
+ CFileMgr::Write(fw, "gta3_7f", sizeof("gta3_7f"));
+ 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;
+ for(int i = first;; i = (i + 1) % 8 ){
+ CFileMgr::Write(fw, (char*)Buffers[first], sizeof(Buffers[first]));
+ if (BufferStatus[i] == REPLAYBUFFER_RECORD)
+ break;
+ }
+ CFileMgr::CloseFile(fw);
+ CFileMgr::SetDir("");
+}
+#endif
+
+#if 0
WRAPPER void PlayReplayFromHD(void) { EAXJMP(0x597420); }
+#else
+void PlayReplayFromHD(void)
+{
+ CFileMgr::SetDirMyDocuments();
+ int fr = CFileMgr::OpenFile("replay.rep", "rb");
+ if (fr < 0) {
+ debug("Couldn't open replay.rep for reading");
+ /* Forgot to SetDir? */
+ return;
+ }
+ CFileMgr::Read(fr, gString, 8);
+ if (strncmp(gString, "gta3_7f", sizeof("gta3_7f"))){
+ CFileMgr::CloseFile(fr);
+ debug("Wrong file type for replay");
+ CFileMgr::SetDir("");
+ return;
+ }
+ int slot;
+ for (slot = 0; CFileMgr::Read(fr, (char*)CReplay::Buffers[slot], sizeof(CReplay::Buffers[slot])); slot++)
+ CReplay::BufferStatus[slot] = CReplay::REPLAYBUFFER_PLAYBACK;
+ CReplay::BufferStatus[slot - 1] = CReplay::REPLAYBUFFER_RECORD;
+ while (slot < 8)
+ CReplay::BufferStatus[slot++] = CReplay::REPLAYBUFFER_UNUSED;
+ CFileMgr::CloseFile(fr);
+ CFileMgr::SetDir("");
+ CReplay::TriggerPlayback(CReplay::REPLAYCAMMODE_ASSTORED, 0.0f, 0.0f, 0.0f, false);
+ CReplay::bPlayingBackFromFile = true;
+ CReplay::bAllowLookAroundCam = true;
+ CReplay::StreamAllNecessaryCarsAndPeds();
+}
+#endif
+
+#if 0
WRAPPER void CReplay::StreamAllNecessaryCarsAndPeds(void) { EAXJMP(0x597560); }
+#else
+void CReplay::StreamAllNecessaryCarsAndPeds(void)
+{
+ for (int slot = 0; slot < 8; slot++) {
+ if (BufferStatus[slot] == REPLAYBUFFER_UNUSED)
+ continue;
+ for (int offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) {
+ switch (Buffers[slot][offset]) {
+ case REPLAYPACKET_VEHICLE:
+ CStreaming::RequestModel(((tVehicleUpdatePacket*)&Buffers[slot][offset])->mi, 0);
+ break;
+ case REPLAYPACKET_PED_HEADER:
+ CStreaming::RequestModel(((tPedHeaderPacket*)&Buffers[slot][offset])->mi, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ CStreaming::LoadAllRequestedModels(false);
+}
+#endif
+
+#if 0
WRAPPER void CReplay::FindFirstFocusCoordinate(CVector *coord) { EAXJMP(0x5975E0); }
+#else
+void CReplay::FindFirstFocusCoordinate(CVector *coord)
+{
+ *coord = CVector(0.0f, 0.0f, 0.0f);
+ for (int slot = 0; slot < 8; slot++) {
+ if (BufferStatus[slot] == REPLAYBUFFER_UNUSED)
+ continue;
+ for (int offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) {
+ if (Buffers[slot][offset] == REPLAYPACKET_GENERAL) {
+ *coord = ((tGeneralPacket*)&Buffers[slot][offset])->player_pos;
+ return;
+ }
+ }
+ }
+}
+#endif
+
+#if 0
WRAPPER bool CReplay::ShouldStandardCameraBeProcessed(void) { EAXJMP(0x597680); }
+#else
+bool CReplay::ShouldStandardCameraBeProcessed(void)
+{
+ if (Mode != MODE_PLAYBACK)
+ return true;
+ if (FramesActiveLookAroundCam || bPlayerInRCBuggy)
+ return false;
+ return FindPlayerVehicle() != nil;
+}
+#endif
+
+#if 0
WRAPPER void CReplay::ProcessLookAroundCam(void) { EAXJMP(0x5976C0); }
+#else
+void CReplay::ProcessLookAroundCam(void)
+{
+ if (!bAllowLookAroundCam)
+ return;
+ float x_moved = CPad::NewMouseControllerState.x / 200.0f;
+ float y_moved = CPad::NewMouseControllerState.y / 200.0f;
+ if (x_moved > 0.01f || y_moved > 0.01f) {
+ if (FramesActiveLookAroundCam == 0)
+ fDistanceLookAroundCam = 9.0f;
+ FramesActiveLookAroundCam = 60;
+ }
+ if (bPlayerInRCBuggy)
+ FramesActiveLookAroundCam = 0;
+ if (!FramesActiveLookAroundCam)
+ return;
+ --FramesActiveLookAroundCam;
+ fBetaAngleLookAroundCam += x_moved;
+ if (CPad::NewMouseControllerState.LMB && CPad::NewMouseControllerState.RMB)
+ fDistanceLookAroundCam = max(3.0f, min(15.0f, fDistanceLookAroundCam + 2.0f * y_moved));
+ else
+ fAlphaAngleLookAroundCam = max(0.1f, min(1.5f, fAlphaAngleLookAroundCam + y_moved));
+ CVector camera_pt(
+ fDistanceLookAroundCam * sin(fBetaAngleLookAroundCam) * cos(fAlphaAngleLookAroundCam),
+ fDistanceLookAroundCam * cos(fBetaAngleLookAroundCam) * cos(fAlphaAngleLookAroundCam),
+ fDistanceLookAroundCam * sin(fAlphaAngleLookAroundCam)
+ );
+ CVector focus = CVector(CameraFocusX, CameraFocusY, CameraFocusZ);
+ camera_pt += focus;
+ CColPoint cp;
+ CEntity* pe = nil;
+ if (CWorld::ProcessLineOfSight(focus, camera_pt, cp, pe, true, false, false, false, false, true, true)){
+ camera_pt = cp.point;
+ CVector direction = focus - cp.point;
+ direction.Normalise();
+ camera_pt += direction / 4.0f;
+ }
+ CVector forward = focus - camera_pt;
+ forward.Normalise();
+ CVector right = CrossProduct(CVector(0.0f, 0.0f, 1.0f), forward);
+ right.Normalise();
+ CVector up = CrossProduct(forward, right);
+ up.Normalise();
+ *TheCamera.GetMatrix().GetForward() = forward;
+ *TheCamera.GetMatrix().GetUp() = up;
+ *TheCamera.GetMatrix().GetRight() = right;
+ *TheCamera.GetMatrix().GetPosition() = camera_pt;
+ RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));
+ pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition();
+ pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward();
+ pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp();
+ pm->right = *(RwV3d*)TheCamera.GetMatrix().GetRight();
+ TheCamera.CalculateDerivedValues();
+ RwMatrixUpdate(RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)));
+ RwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera));
+}
+#endif
+
+#if 0
WRAPPER size_t CReplay::FindSizeOfPacket(uint8 type) { EAXJMP(0x597CC0); }
+#else
+size_t CReplay::FindSizeOfPacket(uint8 type)
+{
+ switch (type) {
+ case REPLAYPACKET_END: return 4;
+ case REPLAYPACKET_VEHICLE: return sizeof(tVehicleUpdatePacket);
+ case REPLAYPACKET_PED_HEADER: return sizeof(tPedHeaderPacket);
+ case REPLAYPACKET_PED_UPDATE: return sizeof(tPedUpdatePacket);
+ case REPLAYPACKET_GENERAL: return sizeof(tGeneralPacket);
+ case REPLAYPACKET_CLOCK: return sizeof(tClockPacket);
+ case REPLAYPACKET_WEATHER: return sizeof(tWeatherPacket);
+ case REPLAYPACKET_ENDOFFRAME: return 4;
+ case REPLAYPACKET_TIMER: return sizeof(tTimerPacket);
+ case REPLAYPACKET_BULLET_TRACES:return sizeof(tBulletTracePacket);
+ default: break;
+ }
+ return 0;
+}
+#endif
#if 0
WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); }
#else
void CReplay::Display()
{
- if (CReplay::IsPlayingBack() && CTimer::GetFrameCounter() + 1 & 0x20) {
- CFont::SetPropOn();
- CFont::SetBackgroundOff();
- CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));
- CFont::SetAlignment(ALIGN_LEFT);
- CFont::SetColor(CRGBA(255, 255, 200, 200));
- CFont::SetFontStyle(FONT_BANK);
+ static int counter = 0;
+ if (Mode == MODE_RECORD)
+ return;
+ counter = (counter + 1) % 65536;
+ if (counter & 0x20 == 0)
+ return;
+ CFont::SetPropOn();
+ CFont::SetBackgroundOff();
+ CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));
+ CFont::SetAlignment(ALIGN_LEFT);
+ CFont::SetColor(CRGBA(255, 255, 200, 200));
+ CFont::SetFontStyle(FONT_BANK);
+ if (Mode == MODE_PLAYBACK)
CFont::PrintString(SCREEN_SCALE_X(63.5f), SCREEN_SCALE_Y(30.0f), TheText.Get("REPLAY"));
- }
}
#endif
STARTPATCHES
-InjectHook(0x592FC0, PrintElementsInPtrList, PATCH_JUMP);
-InjectHook(0x592FE0, CReplay::Init, PATCH_JUMP);
-InjectHook(0x593150, CReplay::DisableReplays, PATCH_JUMP);
-InjectHook(0x593160, CReplay::EnableReplays, PATCH_JUMP);
-InjectHook(0x593170, CReplay::Update, 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);
+InjectHook(0x592FE0, &CReplay::Init, PATCH_JUMP);
+InjectHook(0x593150, &CReplay::DisableReplays, PATCH_JUMP);
+InjectHook(0x593160, &CReplay::EnableReplays, PATCH_JUMP);
+InjectHook(0x593170, &CReplay::Update, PATCH_JUMP);
+InjectHook(0x595B20, &CReplay::FinishPlayback, PATCH_JUMP);
+InjectHook(0x595BD0, &CReplay::EmptyReplayBuffer, PATCH_JUMP);
+InjectHook(0x595EE0, &CReplay::Display, PATCH_JUMP);
+InjectHook(0x596030, &CReplay::TriggerPlayback, PATCH_JUMP);
+InjectHook(0x597560, &CReplay::StreamAllNecessaryCarsAndPeds, PATCH_JUMP);
+InjectHook(0x597680, &CReplay::ShouldStandardCameraBeProcessed, PATCH_JUMP);
ENDPATCHES
diff --git a/src/control/Replay.h b/src/control/Replay.h
index d0f55839..e6885f59 100644
--- a/src/control/Replay.h
+++ b/src/control/Replay.h
@@ -48,6 +48,8 @@ struct CStoredDetailedAnimationState
uint16 aFlags2[6];
};
+void PlayReplayFromHD(void);
+
class CReplay
{
enum {
@@ -244,6 +246,9 @@ private:
static float &CameraFocusY;
static float &CameraFocusZ;
static bool &bPlayerInRCBuggy;
+ static float &fDistanceLookAroundCam;
+ static float &fAlphaAngleLookAroundCam;
+ static float &fBetaAngleLookAroundCam;
public:
static void Init(void);
@@ -260,7 +265,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);
@@ -282,4 +287,7 @@ public:
static void FindFirstFocusCoordinate(CVector *coord);
static void ProcessLookAroundCam(void);
static size_t FindSizeOfPacket(uint8);
+
+ /* Absolute nonsense, but how could this function end up being outside of class? */
+ friend void PlayReplayFromHD(void);
};
diff --git a/src/entities/Automobile.cpp b/src/entities/Automobile.cpp
index e74013be..54eed17a 100644
--- a/src/entities/Automobile.cpp
+++ b/src/entities/Automobile.cpp
@@ -10,6 +10,8 @@ CAutomobile::CAutomobile(int mi, uint8 owner)
WRAPPER CAutomobile* CAutomobile::ctor(int, uint8) { EAXJMP(0x52C6B0); }
WRAPPER void CAutomobile::SetDoorDamage(int32, uint32, bool) { EAXJMP(0x530200); }
+WRAPPER void CAutomobile::SetPanelDamage(int32, uint32, bool) { EAXJMP(0x5301A0); }
+WRAPPER void CAutomobile::SetBumperDamage(int32, uint32, bool) { EAXJMP(0x530120); }
STARTPATCHES
InjectHook(0x52D170, &CAutomobile::dtor, PATCH_JUMP);
diff --git a/src/entities/Automobile.h b/src/entities/Automobile.h
index 246943a7..64e411ce 100644
--- a/src/entities/Automobile.h
+++ b/src/entities/Automobile.h
@@ -25,6 +25,8 @@ public:
CAutomobile(int, uint8);
CAutomobile* ctor(int, uint8);
void SetDoorDamage(int32, uint32, bool); /* TODO: eDoors */
+ void SetPanelDamage(int32, uint32, bool); /* TODO: ePanels */
+ void SetBumperDamage(int32, uint32, bool); /* TODO: ePanels */
void dtor() { this->CAutomobile::~CAutomobile(); }
};
static_assert(sizeof(CAutomobile) == 0x5A8, "CAutomobile: error");
diff --git a/src/entities/CivilianPed.cpp b/src/entities/CivilianPed.cpp
index cf589211..a4881e71 100644
--- a/src/entities/CivilianPed.cpp
+++ b/src/entities/CivilianPed.cpp
@@ -2,13 +2,18 @@
#include "patcher.h"
#include "CivilianPed.h"
-CCivilianPed::CCivilianPed(int pedtype, int mi)
+WRAPPER void CCivilianPed::ProcessControl(void) { EAXJMP(0x4BFFE0); }
+
+CCivilianPed::CCivilianPed(int pedtype, int mi) : CPed(pedtype)
{
- ctor(pedtype, mi);
+ CPed::SetModelIndex(mi);
+ for (int i = 0; i < 10; i++)
+ {
+ m_nearPeds[i] = nil;
+ }
}
-WRAPPER CCivilianPed* CCivilianPed::ctor(int pedtype, int mi) { EAXJMP(0x4BFF30); }
-
STARTPATCHES
+ InjectHook(0x4BFF30, &CCivilianPed::ctor, PATCH_JUMP);
InjectHook(0x4BFFC0, &CCivilianPed::dtor, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/entities/CivilianPed.h b/src/entities/CivilianPed.h
index 4d3346d3..8d004ad7 100644
--- a/src/entities/CivilianPed.h
+++ b/src/entities/CivilianPed.h
@@ -6,7 +6,11 @@ class CCivilianPed : public CPed
{
public:
CCivilianPed(int, int);
- CCivilianPed* ctor(int, int);
+ virtual ~CCivilianPed(void) { }
+
+ virtual void ProcessControl(void);
+
+ CCivilianPed *ctor(int pedtype, int mi) { return ::new (this) CCivilianPed(pedtype, mi); };
void dtor(void) { this->CCivilianPed::~CCivilianPed(); }
};
static_assert(sizeof(CCivilianPed) == 0x53C, "CCivilianPed: error");
diff --git a/src/entities/CutsceneObject.h b/src/entities/CutsceneObject.h
index b4325f4b..9360651e 100644
--- a/src/entities/CutsceneObject.h
+++ b/src/entities/CutsceneObject.h
@@ -7,12 +7,12 @@ class CCutsceneObject : public CObject
public:
CCutsceneObject(void);
- void SetModelIndex(uint32 id);
- void ProcessControl(void);
- void PreRender(void);
- void Render(void);
- bool SetupLighting(void);
- void RemoveLighting(bool reset);
+ virtual void SetModelIndex(uint32 id);
+ virtual void ProcessControl(void);
+ virtual void PreRender(void);
+ virtual void Render(void);
+ virtual bool SetupLighting(void);
+ virtual void RemoveLighting(bool reset);
void dtor(void) { this->CCutsceneObject::~CCutsceneObject(); }
void SetModelIndex_(uint32 id) { CCutsceneObject::SetModelIndex(id); }
diff --git a/src/EmergencyPed.cpp b/src/entities/EmergencyPed.cpp
index 7b847896..7b847896 100644
--- a/src/EmergencyPed.cpp
+++ b/src/entities/EmergencyPed.cpp
diff --git a/src/entities/Entity.h b/src/entities/Entity.h
index 3e100879..92c4c351 100644
--- a/src/entities/Entity.h
+++ b/src/entities/Entity.h
@@ -95,7 +95,7 @@ public:
CReference *m_pFirstReference;
CEntity(void);
- ~CEntity(void);
+ virtual ~CEntity(void);
virtual void Add(void);
virtual void Remove(void);
diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp
index 61d6d182..4d55de15 100644
--- a/src/entities/Ped.cpp
+++ b/src/entities/Ped.cpp
@@ -19,10 +19,31 @@
#include "CullZones.h"
#include "Population.h"
+WRAPPER void CPed::QuitEnteringCar() { EAXJMP(0x4E0E00); }
+WRAPPER void CPed::KillPedWithCar(CVehicle* veh, float impulse) { EAXJMP(0x4EC430); }
+WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); }
+WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4D37D0); }
+WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); }
+WRAPPER void CPed::RestorePreviousState(void) { EAXJMP(0x4C5E30); }
+WRAPPER void CPed::ClearAttack(void) { EAXJMP(0x4E6790); }
+WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2480); }
+WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* dragAssoc, void* arg) { EAXJMP(0x4E2920); }
+WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); }
+WRAPPER void CPed::ProcessControl(void) { EAXJMP(0x4C8910); }
+WRAPPER void CPed::Teleport(CVector) { EAXJMP(0x4D3E70); }
+WRAPPER void CPed::PreRender(void) { EAXJMP(0x4CFDD0); }
+WRAPPER void CPed::Render(void) { EAXJMP(0x4D03F0); }
+WRAPPER bool CPed::SetupLighting(void) { EAXJMP(0x4A7D30); }
+WRAPPER void CPed::RemoveLighting(bool) { EAXJMP(0x4A7DC0); }
+WRAPPER int32 CPed::ProcessEntityCollision(CEntity*, CColPoint*) { EAXJMP(0x4CBB30); }
+WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); }
+
bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44;
bool &CPed::bPedCheat2 = *(bool*)0x95CD5A;
bool &CPed::bPedCheat3 = *(bool*)0x95CD59;
+uint16 &CPed::distanceMultToCountPedNear = *(uint16*)0x5F8C98;
+
CVector &CPed::offsetToOpenRegularCarDoor = *(CVector*)0x62E030;
CVector &CPed::offsetToOpenLowCarDoor = *(CVector*)0x62E03C;
CVector &CPed::offsetToOpenVanDoor = *(CVector*)0x62E048;
@@ -66,7 +87,8 @@ CPed::~CPed(void)
DMAudio.DestroyEntity(m_audioEntityId);
}
-void CPed::FlagToDestroyWhenNextProcessed(void)
+void
+CPed::FlagToDestroyWhenNextProcessed(void)
{
bRemoveFromWorld = true;
if (!bInVehicle || !m_pMyVehicle)
@@ -87,17 +109,6 @@ void CPed::FlagToDestroyWhenNextProcessed(void)
m_pVehicleAnim = nil;
}
-WRAPPER void CPed::QuitEnteringCar() { EAXJMP(0x4E0E00); }
-WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); }
-WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); }
-WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4D37D0); }
-WRAPPER void CPed::SpawnFlyingComponent(int, int8) { EAXJMP(0x4EB060); }
-WRAPPER void CPed::RestorePreviousState(void) { EAXJMP(0x4C5E30); }
-WRAPPER void CPed::ClearAttack(void) { EAXJMP(0x4E6790); }
-WRAPPER void CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2480); }
-WRAPPER void CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg) { EAXJMP(0x4E2920); }
-WRAPPER void CPed::SetPedPositionInCar(void) { EAXJMP(0x4D4970); }
-
static char ObjectiveText[34][28] = {
"No Obj",
"Wait on Foot",
@@ -253,6 +264,247 @@ static char WaitStateText[21][16] = {
"Finish Flee",
};
+CPed::CPed(uint32 pedType) : m_pedIK(this)
+{
+ m_type = ENTITY_TYPE_PED;
+ bPedPhysics = true;
+ bUseCollisionRecords = true;
+
+ m_vecAnimMoveDelta.x = 0.0;
+ m_vecAnimMoveDelta.y = 0.0;
+ m_fHealth = 100.0f;
+ m_fArmour = 0.0f;
+ m_nPedType = pedType;
+ field_520 = 0;
+ m_talkTimer = 0;
+ m_talkTypeLast = 167;
+ m_talkType = 167;
+ m_objective = 0;
+ m_prevObjective = 0;
+ m_nCreatedBy = 1;
+ field_180 = 0;
+ m_field_16C = nil;
+ field_170 = 0;
+ bInVehicle = 0;
+ m_pMyVehicle = nil;
+ m_pVehicleAnim = nil;
+ m_vecOffsetSeek.x = 0.0;
+ m_vecOffsetSeek.y = 0.0;
+ m_vecOffsetSeek.z = 0.0;
+ m_pedFormation = 0;
+ m_lastThreatTimer = 0;
+ m_nPedStateTimer = 0;
+ m_actionX = 0;
+ m_actionY = 0;
+ m_phoneTalkTimer = 0;
+ m_stateUnused = 0;
+ m_leaveCarTimer = 0;
+ m_getUpTimer = 0;
+ m_attackTimer = 0;
+ m_timerUnused = 0;
+ m_lookTimer = 0;
+ m_standardTimer = 0;
+ m_lastHitTime = 0;
+ m_hitRecoverTimer = 0;
+ field_4E8 = 0;
+ m_movedX = 0;
+ m_movedY = 0;
+ m_fRotationCur = 0.0f;
+ m_headingRate = 15.0f;
+ m_fRotationDest = 0.0f;
+ m_vehEnterType = VEHICLE_ENTER_FRONT_LEFT;
+ m_walkAroundType = 0;
+ m_pCurrentPhysSurface = nil;
+ m_vecOffsetFromPhysSurface = CVector(0.0f, 0.0f, 0.0f);
+ m_pSeekTarget = nil;
+ m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f);
+ m_wepSkills = 0;
+ field_318 = 1.0f;
+ field_31C = 0;
+ m_phoneId = -1;
+ m_lastAccident = 0;
+ m_fleeFrom = nil;
+ m_fleeFromPosX = 0;
+ m_fleeFromPosY = 0;
+ m_fleeTimer = 0;
+ m_vecSeekPosEx = CVector(0.0f, 0.0f, 0.0f);
+ m_seekExAngle = 0.0f;
+ m_nWaitState = 0;
+ m_nWaitTimer = 0;
+ m_pCollidingEntity = nil;
+ m_nPedState = PED_IDLE;
+ m_nLastPedState = PED_NONE;
+ m_nMoveState = 1;
+ m_nStoredActionState = 0;
+ m_pFire = nil;
+ m_pPointGunAt = nil;
+ m_pLookTarget = 0;
+ m_fLookDirection = 0.0f;
+ m_pCurSurface = 0;
+ m_targetUnused = nil;
+ m_nPathNodes = 0;
+ m_nCurPathNode = 0;
+ m_nPathState = 0;
+ m_pNextPathNode = nil;
+ m_pLastPathNode = nil;
+ m_routeLastPoint = -1;
+ m_routePoints = 0;
+ m_routePos = 0;
+ m_routeType = 0;
+ m_bodyPartBleeding = -1;
+
+ m_fMass = 70.0f;
+ m_fTurnMass = 100.0f;
+ m_fAirResistance = 0.4f / m_fMass;
+ m_fElasticity = 0.05f;
+
+ bIsStanding = false;
+ m_ped_flagA2 = false;
+ m_ped_flagA4 = false;
+ bIsPointingGunAt = false;
+ bIsLooking = false;
+ m_ped_flagA20 = false;
+ bIsRestoringLook = false;
+ bIsAimingGun = false;
+
+ bIsRestoringGun = false;
+ bCanPointGunAtTarget = false;
+ m_ped_flagB4 = false;
+ m_ped_flagB8 = false;
+ m_ped_flagB10 = false;
+ m_ped_flagB20 = false;
+ m_ped_flagB40 = false;
+ m_ped_flagB80 = false;
+
+ m_ped_flagC1 = false;
+ m_ped_flagC2 = true;
+ m_ped_flagC4 = true;
+ m_ped_flagC8 = false;
+ m_ped_flagC10 = false;
+ m_ped_flagC20 = false;
+ m_ped_flagC40 = false;
+ m_ped_flagC80 = false;
+
+ m_ped_flagD1 = false;
+ m_ped_flagD2 = false;
+ m_ped_flagD4 = false;
+ m_ped_flagD8 = false;
+ m_ped_flagD10 = false;
+ m_ped_flagD20 = false;
+ m_ped_flagD40 = false;
+ m_ped_flagD80 = false;
+
+ m_ped_flagE1 = false;
+ m_ped_flagE2 = false;
+ m_ped_flagE4 = false;
+ m_ped_flagE8 = false;
+ bCantFireBecauseCrouched = false;
+ m_ped_flagE20 = false;
+ bDoBloodyFootprints = false;
+ m_ped_flagE80 = false;
+
+ m_ped_flagF1 = false;
+ m_ped_flagF2 = false;
+ m_ped_flagF4 = false;
+ m_ped_flagF8 = false;
+ m_ped_flagF10 = false;
+ m_ped_flagF20 = false;
+ m_ped_flagF40 = false;
+ m_ped_flagF80 = false;
+
+ m_ped_flagG1 = false;
+ m_ped_flagG2 = true;
+ m_ped_flagG4 = false;
+ m_ped_flagG8 = false;
+ m_ped_flagG10 = false;
+ m_ped_flagG20 = false;
+ m_ped_flagG40 = false;
+ m_ped_flagG80 = false;
+
+ m_ped_flagH1 = false;
+ m_ped_flagH2 = false;
+ m_ped_flagH4 = false;
+ m_ped_flagH8 = false;
+ m_ped_flagH10 = false;
+ m_ped_flagH20 = false;
+ m_ped_flagH40 = false;
+ m_ped_flagH80 = false;
+
+ m_ped_flagI1 = false;
+ m_ped_flagI2 = false;
+ m_ped_flagI4 = false;
+ bRecordedForReplay = false;
+ m_ped_flagI10 = false;
+#ifdef KANGAROO_CHEAT
+ m_ped_flagI80 = false;
+#endif
+
+ if ((CGeneral::GetRandomNumber() & 3) == 0)
+ m_ped_flagD1 = true;
+
+ m_audioEntityId = DMAudio.CreateEntity(0, this);
+ DMAudio.SetEntityStatus(m_audioEntityId, 1);
+ m_fearFlags = CPedType::GetThreats(m_nPedType);
+ m_threatEntity = nil;
+ m_eventOrThread = CVector2D(0.0f, 0.0f);
+ m_pEventEntity = nil;
+ m_fAngleToEvent = 0.0f;
+ m_numNearPeds = 0;
+
+ for (int i = 0; i < 10; i++)
+ {
+ m_nearPeds[i] = nil;
+ if (i < 8) {
+ m_pPathNodesStates[i] = nil;
+ }
+ }
+ m_maxWeaponTypeAllowed = 0;
+ m_currentWeapon = 0;
+ m_storedWeapon = NO_STORED_WEAPON;
+
+ for(int i = 0; i < NUM_PED_WEAPONTYPES; i++)
+ {
+ CWeapon &weapon = GetWeapon(i);
+ weapon.m_eWeaponType = WEAPONTYPE_UNARMED;
+ weapon.m_eWeaponState = WEAPONSTATE_READY;
+ weapon.m_nAmmoInClip = 0;
+ weapon.m_nAmmoTotal = 0;
+ weapon.m_nTimer = 0;
+ }
+
+ m_lastHitState = 0;
+ GiveWeapon(WEAPONTYPE_UNARMED, 0);
+ m_wepAccuracy = 60;
+ m_lastWepDam = -1;
+ m_collPoly.valid = false;
+ m_fCollisionSpeed = 0.0f;
+ m_wepModelID = -1;
+ CPopulation::UpdatePedCount(m_nPedType, false);
+}
+
+uint32
+CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo)
+{
+ CWeapon &weapon = GetWeapon(weaponType);
+
+ if (HasWeapon(weaponType)) {
+ if (weapon.m_nAmmoTotal + ammo > 99999)
+ weapon.m_nAmmoTotal = 99999;
+ else
+ weapon.m_nAmmoTotal += ammo;
+
+ weapon.Reload();
+ } else {
+ weapon.Initialise(weaponType, ammo);
+ // TODO: It seems game uses this as both weapon count and max WeaponType we have, which is ofcourse erroneous.
+ m_maxWeaponTypeAllowed++;
+ }
+ if (weapon.m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO)
+ weapon.m_eWeaponState = WEAPONSTATE_READY;
+
+ return weaponType;
+}
+
static RwObject*
RemoveAllModelCB(RwObject *object, void *data)
{
@@ -787,7 +1039,7 @@ CPed::Attack(void)
if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
if (weaponAnimAssoc->speed < 1.0f)
- weaponAnimAssoc->speed = 1.0;
+ weaponAnimAssoc->speed = 1.0f;
} else {
firePos = ourWeapon->m_vecFireOffset;
@@ -871,7 +1123,7 @@ CPed::Attack(void)
}
animLoopEnd = ourWeapon->m_fAnimLoopEnd;
if (ourWeaponFire == WEAPON_FIRE_MELEE && weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
- animLoopEnd = 0.56f;
+ animLoopEnd = 3.4f/6.0f;
weaponAnimTime = weaponAnimAssoc->currentTime;
@@ -963,10 +1215,9 @@ CPed::RemoveWeaponModel(int modelId)
}
void
-CPed::SetCurrentWeapon(eWeaponType weaponType)
+CPed::SetCurrentWeapon(uint32 weaponType)
{
CWeaponInfo *weaponInfo;
-
if (HasWeapon(weaponType)) {
weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
RemoveWeaponModel(weaponInfo->m_nModelId);
@@ -982,15 +1233,11 @@ CPed::SetCurrentWeapon(eWeaponType weaponType)
bool
CPed::SelectGunIfArmed(void)
{
- eWeaponType weaponType;
-
for (int i = 0; i < m_maxWeaponTypeAllowed; i++) {
-
- if (m_weapons[i].m_nAmmoTotal > 0) {
- weaponType = m_weapons[i].m_eWeaponType;
-
+ if (GetWeapon(i).m_nAmmoTotal > 0) {
+ eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) {
- SetCurrentWeapon(weaponType);
+ SetCurrentWeapon(i);
return true;
}
}
@@ -1659,6 +1906,146 @@ CPed::PlayFootSteps(void)
}
}
+bool
+CPed::IsPointerValid(void)
+{
+ int8 pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8;
+ if (pedIndex < 0 || pedIndex >= NUMPEDS)
+ return false;
+
+ if (m_entryInfoList.first || FindPlayerPed() == this)
+ return true;
+
+ return false;
+}
+
+// Some kind of binary sort
+void
+CPed::SortPeds(CPed** list, int min, int max)
+{
+ if (min >= max)
+ return;
+
+ CVector leftDiff, rightDiff;
+ CVector middleDiff = GetPosition() - list[(max + min) / 2]->GetPosition();
+ float middleDist = middleDiff.Magnitude();
+
+ int left = max;
+ int right;
+ for(right = min; right <= left; ){
+ // Those 1.0s are to make sure loop always run for first time.
+ for (float rightDist = middleDist-1.0f; middleDist > rightDist; right++) {
+ rightDiff = GetPosition() - list[right]->GetPosition();
+ rightDist = rightDiff.Magnitude();
+ }
+ right--;
+
+ for (float leftDist = middleDist+1.0f; middleDist < leftDist; left--) {
+ leftDiff = GetPosition() - list[left]->GetPosition();
+ leftDist = leftDiff.Magnitude();
+ }
+ left++;
+
+ if (right <= left) {
+ CPed *ped = list[right];
+ list[right] = list[left];
+ list[left] = ped;
+ right++;
+ left--;
+ }
+ }
+ SortPeds(list, min, left);
+ SortPeds(list, right, max);
+}
+
+void
+CPed::BuildPedLists(void)
+{
+ static CPed* unsortedNearPeds[10];
+ uint16 nextNearPedSlot = 0;
+
+ if ((CTimer::GetFrameCounter() + m_randomSeed) & 15) {
+
+ for(int i = 0; i < 10; ) {
+ if (m_nearPeds[i]) {
+ if (m_nearPeds[i]->IsPointerValid()) {
+ float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D();
+ if (distSqr < 900.0f) {
+ i++;
+ continue;
+ }
+ }
+
+ // If we arrive here, the ped we're checking isn't "near", so we should remove it.
+ for (int j = i; j < 9; j++) {
+ m_nearPeds[j] = m_nearPeds[j + 1];
+ m_nearPeds[j + 1] = nil;
+ }
+ // Above loop won't work when it's 9, so we need to empty slot 9.
+ m_nearPeds[9] = nil;
+ m_numNearPeds--;
+ } else
+ i++;
+ }
+ } else {
+ CVector centre = CEntity::GetBoundCentre();
+ CRect rect(
+ (centre.x - 20.0f) * 0.025f + 50.0f,
+ (centre.y - 20.0f) * 0.025f + 50.0f,
+ (centre.x + 20.0f) * 0.025f + 50.0f,
+ (centre.y + 20.0f) * 0.025f + 50.0f);
+
+ for(int y = rect.top; y <= rect.bottom; y++) {
+ for(int x = rect.left; x <= rect.right; x++) {
+ for (CPtrNode *pedPtrNode = CWorld::GetSector(x,y)->m_lists[ENTITYLIST_PEDS].first; pedPtrNode; pedPtrNode = pedPtrNode->next) {
+ CPed *ped = (CPed*)pedPtrNode->item;
+ if (ped != this && !ped->bInVehicle) {
+ float dist = (ped->GetPosition() - GetPosition()).Magnitude2D();
+ if (distanceMultToCountPedNear * 30.0f > dist)
+ {
+ unsortedNearPeds[nextNearPedSlot] = ped;
+ nextNearPedSlot++;
+ }
+ }
+ }
+ }
+ }
+ unsortedNearPeds[nextNearPedSlot] = nil;
+ SortPeds(unsortedNearPeds, 0, nextNearPedSlot - 1);
+ for (m_numNearPeds = 0; m_numNearPeds < 10; m_numNearPeds++) {
+ CPed *ped = unsortedNearPeds[m_numNearPeds];
+ if (!ped)
+ break;
+
+ m_nearPeds[m_numNearPeds] = ped;
+ }
+ for (int pedToClear = m_numNearPeds; pedToClear < 10; pedToClear++)
+ m_nearPeds[pedToClear] = nil;
+ }
+}
+
+void
+CPed::SetPedStats(ePedStats pedStat)
+{
+ m_pedStats = CPedStats::ms_apPedStats[pedStat];
+}
+
+void
+CPed::SetModelIndex(uint32 mi)
+{
+ CEntity::SetModelIndex(mi);
+ RpAnimBlendClumpInit((RpClump*) m_rwObject);
+ RpAnimBlendClumpFillFrameArray((RpClump*) m_rwObject, m_pFrames);
+ CPedModelInfo *modelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex);
+ SetPedStats(static_cast<ePedStats>(modelInfo->m_pedStatType));
+ m_headingRate = m_pedStats->m_headingChangeRate;
+ m_animGroup = static_cast<AssocGroupId>(modelInfo->m_animGroup);
+ CAnimManager::AddAnimation((RpClump*) m_rwObject, m_animGroup, ANIM_IDLE_STANCE);
+
+ // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D.
+ (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta;
+}
+
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); }
@@ -1684,6 +2071,7 @@ WRAPPER void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4
WRAPPER void CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D6550); }
STARTPATCHES
+ InjectHook(0x4C41C0, &CPed::ctor, PATCH_JUMP);
InjectHook(0x4C50D0, &CPed::dtor, PATCH_JUMP);
InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP);
InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP);
@@ -1714,4 +2102,9 @@ STARTPATCHES
InjectHook(0x4E1A30, (void (*)(CVector*, CVehicle*, uint32)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP);
InjectHook(0x4DF940, &CPed::LineUpPedWithCar, PATCH_JUMP);
InjectHook(0x4CC6C0, &CPed::PlayFootSteps, PATCH_JUMP);
+ InjectHook(0x4C5350, &CPed::BuildPedLists, PATCH_JUMP);
+ InjectHook(0x4CF9B0, &CPed::GiveWeapon, PATCH_JUMP);
+ InjectHook(0x4C5330, &CPed::SetPedStats, PATCH_JUMP);
+ InjectHook(0x4C52A0, &CPed::SetModelIndex_, PATCH_JUMP);
+ InjectHook(0x4D6570, &CPed::FlagToDestroyWhenNextProcessed_, PATCH_JUMP);
ENDPATCHES
diff --git a/src/entities/Ped.h b/src/entities/Ped.h
index 8f4939fc..92fa32c1 100644
--- a/src/entities/Ped.h
+++ b/src/entities/Ped.h
@@ -121,6 +121,7 @@ public:
uint8 m_ped_flagA20 : 1; // "look" method? - probably missing in SA
uint8 bIsRestoringLook : 1;
uint8 bIsAimingGun : 1;
+
uint8 bIsRestoringGun : 1;
uint8 bCanPointGunAtTarget : 1;
uint8 m_ped_flagB4 : 1;
@@ -129,6 +130,7 @@ public:
uint8 m_ped_flagB20 : 1;
uint8 m_ped_flagB40 : 1;
uint8 m_ped_flagB80 : 1;
+
uint8 m_ped_flagC1 : 1;
uint8 m_ped_flagC2 : 1;
uint8 m_ped_flagC4 : 1;
@@ -137,6 +139,7 @@ public:
uint8 m_ped_flagC20 : 1; // just left some body part?
uint8 m_ped_flagC40 : 1;
uint8 m_ped_flagC80 : 1;
+
uint8 m_ped_flagD1 : 1;
uint8 m_ped_flagD2 : 1;
uint8 m_ped_flagD4 : 1;
@@ -145,6 +148,7 @@ public:
uint8 m_ped_flagD20 : 1;
uint8 m_ped_flagD40 : 1;
uint8 m_ped_flagD80 : 1;
+
uint8 m_ped_flagE1 : 1;
uint8 m_ped_flagE2 : 1;
uint8 m_ped_flagE4 : 1;
@@ -153,6 +157,7 @@ public:
uint8 m_ped_flagE20 : 1;
uint8 bDoBloodyFootprints : 1;
uint8 m_ped_flagE80 : 1;
+
uint8 m_ped_flagF1 : 1;
uint8 m_ped_flagF2 : 1;
uint8 m_ped_flagF4 : 1;
@@ -161,6 +166,7 @@ public:
uint8 m_ped_flagF20 : 1;
uint8 m_ped_flagF40 : 1;
uint8 m_ped_flagF80 : 1;
+
uint8 m_ped_flagG1 : 1;
uint8 m_ped_flagG2 : 1;
uint8 m_ped_flagG4 : 1;
@@ -169,6 +175,7 @@ public:
uint8 m_ped_flagG20 : 1;
uint8 m_ped_flagG40 : 1;
uint8 m_ped_flagG80 : 1;
+
uint8 m_ped_flagH1 : 1;
uint8 m_ped_flagH2 : 1;
uint8 m_ped_flagH4 : 1;
@@ -177,6 +184,7 @@ public:
uint8 m_ped_flagH20 : 1;
uint8 m_ped_flagH40 : 1;
uint8 m_ped_flagH80 : 1;
+
uint8 m_ped_flagI1 : 1;
uint8 m_ped_flagI2 : 1;
uint8 m_ped_flagI4 : 1;
@@ -187,10 +195,22 @@ public:
uint8 m_ped_flagI80 : 1;
uint8 stuff10[3];
uint8 m_nCreatedBy;
- uint8 stuff14[11];
- CPed *m_field_16C;
- uint8 stuff12[44];
- int32 m_pEventEntity;
+ uint8 field_161;
+ uint8 pad_162[2];
+ uint32 m_objective;
+ uint32 m_prevObjective;
+ CPed* m_field_16C;
+ uint32 field_170;
+ uint32 field_174;
+ uint32 field_178;
+ uint32 field_17C;
+ uint32 field_180;
+ uint32 m_pedFormation;
+ uint32 m_fearFlags;
+ CEntity *m_threatEntity;
+ CVector2D m_eventOrThread;
+ uint32 m_eventType;
+ CEntity* m_pEventEntity;
float m_fAngleToEvent;
AnimBlendFrameData *m_pFrames[PED_NODE_MAX];
AssocGroupId m_animGroup;
@@ -198,7 +218,8 @@ public:
CVector2D m_vecAnimMoveDelta;
CVector m_vecOffsetSeek;
CPedIK m_pedIK;
- uint8 stuff1[8];
+ float m_actionX;
+ float m_actionY;
uint32 m_nPedStateTimer;
PedState m_nPedState;
PedState m_nLastPedState;
@@ -206,10 +227,9 @@ public:
int32 m_nStoredActionState;
int32 m_nPrevActionState;
int32 m_nWaitState;
- int32 m_nWaitTimer;
-private:
- uint32 stuff0[28];
-public:
+ uint32 m_nWaitTimer;
+ void *m_pPathNodesStates[8];
+ CVector2D m_stPathNodeStates[10];
uint16 m_nPathNodes;
uint8 m_nCurPathNode;
int8 m_nPathState;
@@ -220,33 +240,59 @@ public:
CPathNode *m_pLastPathNode;
float m_fHealth;
float m_fArmour;
- uint8 stuff2[20];
+ int16 m_routeLastPoint;
+ uint16 m_routePoints;
+ uint16 m_routePos;
+ uint16 m_routeType;
+ uint16 m_routeCurDir;
+ uint16 field_2D2;
+ float m_movedX;
+ float m_movedY;
float m_fRotationCur;
float m_fRotationDest;
- uint32 m_headingRate;
+ float m_headingRate;
uint16 m_vehEnterType;
uint16 m_walkAroundType;
CEntity *m_pCurrentPhysSurface;
CVector m_vecOffsetFromPhysSurface;
CEntity *m_pCurSurface;
- uint8 stuff3[12];
+ CVector m_vecSeekVehicle;
CEntity *m_pSeekTarget;
CVehicle *m_pMyVehicle;
bool bInVehicle;
- uint8 stuff4[23];
+ uint8 pad_315[3];
+ uint32 field_318;
+ uint8 field_31C;
+ uint8 field_31D;
+ int16 m_phoneId;
+ uint32 m_lookingForPhone;
+ uint32 m_phoneTalkTimer;
+ void *m_lastAccident;
int32 m_nPedType;
CPedStats *m_pedStats;
- uint8 stuff5[24];
+ float m_fleeFromPosX;
+ float m_fleeFromPosY;
+ CEntity *m_fleeFrom;
+ uint32 m_fleeTimer;
+ uint32 field_344;
+ uint32 m_lastThreatTimer;
CEntity *m_pCollidingEntity;
- uint8 stuff6[12];
+ uint8 m_stateUnused;
+ uint8 pad_351[3];
+ uint32 m_timerUnused;
+ CEntity *m_targetUnused;
CWeapon m_weapons[NUM_PED_WEAPONTYPES];
eWeaponType m_storedWeapon;
uint8 m_currentWeapon; // eWeaponType
uint8 m_maxWeaponTypeAllowed; // eWeaponType
- uint8 stuff[2];
- int32 m_pPointGunAt;
+ uint8 m_wepSkills;
+ uint8 m_wepAccuracy;
+ CEntity *m_pPointGunAt;
CVector m_vecHitLastPos;
- uint8 stuff8[8];
+ uint32 m_lastHitState;
+ uint8 m_fightFlags1;
+ uint8 m_fightFlags2;
+ uint8 pad_4B2[2];
CFire* m_pFire;
CEntity *m_pLookTarget;
float m_fLookDirection;
@@ -260,23 +306,43 @@ public:
uint32 m_hitRecoverTimer;
uint32 field_4E0;
uint32 m_duckTimer;
- uint8 stuff13[4];
+ uint32 field_4E8;
int32 m_bloodyFootprintCount;
uint8 stuff9[2];
- uint8 m_bodyPartBleeding; // PedNode
+ int8 m_bodyPartBleeding; // PedNode
uint8 m_field_4F3;
CPed *m_nearPeds[10];
uint16 m_numNearPeds;
- uint8 stuff11[30];
+ int8 m_lastWepDam;
+ uint8 pad_51F;
+ uint8 field_520;
+ uint8 pad_521[3];
+ uint32 m_talkTimer;
+ uint16 m_talkTypeLast;
+ uint16 m_talkType;
+ CVector m_vecSeekPosEx;
+ float m_seekExAngle;
static void *operator new(size_t);
static void *operator new(size_t, int);
static void operator delete(void*, size_t);
static void operator delete(void*, int);
- ~CPed(void);
- void FlagToDestroyWhenNextProcessed(void);
+ CPed(uint32 pedType);
+ virtual ~CPed(void);
+ virtual void SetModelIndex(uint32 mi);
+ virtual void ProcessControl(void);
+ virtual void Teleport(CVector);
+ virtual void PreRender(void);
+ virtual void Render(void);
+ virtual bool SetupLighting(void);
+ virtual void RemoveLighting(bool);
+ virtual void FlagToDestroyWhenNextProcessed(void);
+ virtual int32 ProcessEntityCollision(CEntity*, CColPoint*);
+ virtual void SetMoveAnim(void);
+
+ CPed* ctor(uint32 pedType) { return ::new (this) CPed(pedType); }
void dtor(void) { this->CPed::~CPed(); }
bool IsPlayer(void);
@@ -302,7 +368,7 @@ public:
void ClearAttack(void);
bool IsPedHeadAbovePos(float zOffset);
void RemoveWeaponModel(int modelId);
- void SetCurrentWeapon(eWeaponType weaponType);
+ void SetCurrentWeapon(uint32 weaponType);
bool SelectGunIfArmed(void);
void Duck(void);
void ClearDuck(void);
@@ -313,6 +379,11 @@ public:
void SetPedPositionInCar(void);
void PlayFootSteps(void);
void QuitEnteringCar(void);
+ bool IsPointerValid(void);
+ void SortPeds(CPed**, int, int);
+ void BuildPedLists(void);
+ uint32 GiveWeapon(eWeaponType weaponType, uint32 ammo);
+ void SetPedStats(ePedStats);
static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset);
static void GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float seatPosMult);
static void GetPositionToOpenCarDoor(CVector* output, CVehicle* veh, uint32 enterType);
@@ -345,9 +416,17 @@ public:
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]; }
- RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; }
+ inline bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; }
+ inline CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; }
+ inline CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; }
+ inline RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; }
+
+ // to make patching virtual functions possible
+ void SetModelIndex_(uint32 mi) { CPed::SetModelIndex(mi); }
+ void FlagToDestroyWhenNextProcessed_(void) { CPed::FlagToDestroyWhenNextProcessed(); }
+
+ // set by 0482:set_threat_reaction_range_multiplier opcode
+ static uint16 &distanceMultToCountPedNear;
static CVector &offsetToOpenRegularCarDoor;
static CVector &offsetToOpenLowCarDoor;
diff --git a/src/entities/PedIK.cpp b/src/entities/PedIK.cpp
index ebc17097..fa773bbf 100644
--- a/src/entities/PedIK.cpp
+++ b/src/entities/PedIK.cpp
@@ -6,6 +6,20 @@
WRAPPER bool CPedIK::PointGunInDirection(float phi, float theta) { EAXJMP(0x4ED9B0); }
WRAPPER bool CPedIK::PointGunAtPosition(CVector *position) { EAXJMP(0x4ED920); }
+CPedIK::CPedIK(CPed *ped)
+{
+ m_ped = ped;
+ m_flags = 0;
+ m_headOrient.phi = 0.0f;
+ m_headOrient.theta = 0.0f;
+ m_torsoOrient.phi = 0.0f;
+ m_torsoOrient.theta = 0.0f;
+ m_upperArmOrient.phi = 0.0f;
+ m_upperArmOrient.theta = 0.0f;
+ m_lowerArmOrient.phi = 0.0f;
+ m_lowerArmOrient.theta = 0.0f;
+}
+
void
CPedIK::GetComponentPosition(RwV3d *pos, PedNode node)
{
@@ -13,11 +27,11 @@ CPedIK::GetComponentPosition(RwV3d *pos, PedNode node)
RwMatrix *mat;
f = m_ped->GetNodeFrame(node);
- mat = &f->modelling;
+ mat = RwFrameGetMatrix(f);
*pos = mat->pos;
for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f))
- RwV3dTransformPoints(pos, pos, 1, &f->modelling);
+ RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(f));
}
RwMatrix*
@@ -25,10 +39,10 @@ CPedIK::GetWorldMatrix(RwFrame *source, RwMatrix *destination)
{
RwFrame *i;
- *destination = source->modelling;
+ *destination = *RwFrameGetMatrix(source);
for (i = RwFrameGetParent(source); i; i = RwFrameGetParent(i))
- RwMatrixTransform(destination, &i->modelling, rwCOMBINEPOSTCONCAT);
+ RwMatrixTransform(destination, RwFrameGetMatrix(i), rwCOMBINEPOSTCONCAT);
return destination;
}
diff --git a/src/entities/PedIK.h b/src/entities/PedIK.h
index 68e4014a..7c798dc2 100644
--- a/src/entities/PedIK.h
+++ b/src/entities/PedIK.h
@@ -27,6 +27,7 @@ public:
LimbOrientation m_lowerArmOrient;
int32 m_flags;
+ CPedIK(CPed *ped);
bool PointGunInDirection(float phi, float theta);
bool PointGunAtPosition(CVector *position);
void GetComponentPosition(RwV3d *pos, PedNode node);
diff --git a/src/entities/Physical.h b/src/entities/Physical.h
index 25bc1185..7776da92 100644
--- a/src/entities/Physical.h
+++ b/src/entities/Physical.h
@@ -65,12 +65,13 @@ public:
~CPhysical(void);
// from CEntity
- void Add(void);
- void Remove(void);
- CRect GetBoundRect(void);
- void ProcessControl(void);
-
+ virtual void Add(void);
+ virtual void Remove(void);
+ virtual CRect GetBoundRect(void);
+ virtual void ProcessControl(void);
virtual int32 ProcessEntityCollision(CEntity *ent, CColPoint *point);
+ virtual void ProcessShift(void);
+ virtual void ProcessCollision(void);
void RemoveAndAdd(void);
void AddToMovingList(void);
@@ -130,8 +131,6 @@ public:
bool ProcessCollisionSectorList(CPtrList *lists);
bool CheckCollision(void);
bool CheckCollision_SimpleCar(void);
- void ProcessShift(void);
- void ProcessCollision(void);
// to make patching virtual functions possible
void dtor(void) { this->CPhysical::~CPhysical(); }
diff --git a/src/entities/Vehicle.h b/src/entities/Vehicle.h
index 997720f6..27641e47 100644
--- a/src/entities/Vehicle.h
+++ b/src/entities/Vehicle.h
@@ -77,7 +77,7 @@ public:
uint8 m_veh_flagD2 : 1;
uint8 m_veh_flagD4 : 1;
uint8 m_veh_flagD8 : 1;
- uint8 m_veh_flagD10 : 1;
+ uint8 bRecordedForReplay : 1;
uint8 m_veh_flagD20 : 1;
uint8 m_veh_flagD40 : 1;
uint8 m_veh_flagD80 : 1;
diff --git a/src/main.cpp b/src/main.cpp
index 307d0b66..de3d8b62 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -48,14 +48,8 @@
#include "RpAnimBlend.h"
#include "Frontend.h"
-#define DEFAULT_VIEWWINDOW (tan(CDraw::GetFOV() * (360.0f / PI)))
+#define DEFAULT_VIEWWINDOW (tan(DEGTORAD(CDraw::GetFOV() * 0.5f)))
-#ifdef WIDE_SCREEN
-#define DEFAULT_ASPECTRATIO (16.0f/9.0f)
-#else
-#define DEFAULT_ASPECTRATIO (4.0f/3.0f)
-#endif
-
GlobalScene &Scene = *(GlobalScene*)0x726768;
@@ -100,6 +94,10 @@ InitialiseGame(void)
void
Idle(void *arg)
{
+#ifdef ASPECT_RATIO_SCALE
+ CDraw::SetAspectRatio(CDraw::FindAspectRatio());
+#endif
+
CTimer::Update();
CSprite2d::InitPerFrame();
CFont::InitPerFrame();
@@ -160,9 +158,8 @@ Idle(void *arg)
Render2dStuff();
}else{
- float viewWindow = tan(DEGTORAD(CDraw::GetFOV() * 0.5f));
- CDraw::CalculateAspectRatio();
- CameraSize(Scene.camera, nil, viewWindow, SCREEN_ASPECT_RATIO);
+ float viewWindow = DEFAULT_VIEWWINDOW;
+ CameraSize(Scene.camera, nil, viewWindow, DEFAULT_ASPECT_RATIO);
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
if(!RsCameraBeginUpdate(Scene.camera))
@@ -170,7 +167,9 @@ Idle(void *arg)
}
RenderMenus();
+#ifndef FINAL
PrintGameVersion();
+#endif
DoFade();
Render2dStuffAfterFade();
CCredits::Render();
@@ -183,6 +182,10 @@ Idle(void *arg)
void
FrontendIdle(void)
{
+#ifdef ASPECT_RATIO_SCALE
+ CDraw::SetAspectRatio(CDraw::FindAspectRatio());
+#endif
+
CTimer::Update();
CSprite2d::SetRecipNearClip();
CSprite2d::InitPerFrame();
@@ -193,9 +196,8 @@ FrontendIdle(void)
if(RsGlobal.quit)
return;
- float viewWindow = tan(DEGTORAD(CDraw::GetFOV() * 0.5f));
- CDraw::CalculateAspectRatio();
- CameraSize(Scene.camera, nil, viewWindow, SCREEN_ASPECT_RATIO);
+ float viewWindow = DEFAULT_VIEWWINDOW;
+ CameraSize(Scene.camera, nil, viewWindow, DEFAULT_ASPECT_RATIO);
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
if(!RsCameraBeginUpdate(Scene.camera))
@@ -203,7 +205,9 @@ FrontendIdle(void)
DefinedState();
RenderMenus();
+#ifndef FINAL
PrintGameVersion();
+#endif
DoFade();
Render2dStuffAfterFade();
CFont::DrawFonts();
@@ -216,9 +220,7 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR
CRGBA TopColor(TopRed, TopGreen, TopBlue, Alpha);
CRGBA BottomColor(BottomRed, BottomGreen, BottomBlue, Alpha);
- float viewWindow = tan(DEGTORAD(CDraw::GetFOV() * 0.5f));
- CDraw::CalculateAspectRatio();
- CameraSize(Scene.camera, nil, viewWindow, SCREEN_ASPECT_RATIO);
+ CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, SCREEN_ASPECT_RATIO);
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
@@ -236,9 +238,7 @@ DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomR
bool
DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha)
{
- float viewWindow = tan(DEGTORAD(CDraw::GetFOV() * 0.5f));
- CDraw::CalculateAspectRatio();
- CameraSize(Scene.camera, nil, viewWindow, SCREEN_ASPECT_RATIO);
+ CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, SCREEN_ASPECT_RATIO);
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
@@ -782,7 +782,7 @@ AppEventHandler(RsEvent event, void *param)
{
CameraSize(Scene.camera, (RwRect *)param,
- DEFAULT_VIEWWINDOW, DEFAULT_ASPECTRATIO);
+ DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
return rsEVENTPROCESSED;
}
diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp
index 78eee96c..0d206db0 100644
--- a/src/modelinfo/VehicleModelInfo.cpp
+++ b/src/modelinfo/VehicleModelInfo.cpp
@@ -875,6 +875,7 @@ CreateCarColourTexture(uint8 r, uint8 g, uint8 b)
pixels[14] = b;
pixels[15] = 0xFF;
RwImageSetPixels(img, pixels);
+ RwImageSetStride(img, 8);
RwImageSetPalette(img, nil);
RwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
ras = RwRasterCreate(width, height, depth, format);
diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp
index 90875299..922d96d4 100644
--- a/src/render/Draw.cpp
+++ b/src/render/Draw.cpp
@@ -4,8 +4,9 @@
#include "Frontend.h"
#include "Camera.h"
-float CDraw::ms_fAspectRatio;
-float CDraw::ms_fScreenMultiplier;
+#ifdef ASPECT_RATIO_SCALE
+float CDraw::ms_fAspectRatio = DEFAULT_ASPECT_RATIO;
+#endif
float &CDraw::ms_fNearClipZ = *(float*)0x8E2DC4;
float &CDraw::ms_fFarClipZ = *(float*)0x9434F0;
@@ -16,26 +17,25 @@ uint8 &CDraw::FadeRed = *(uint8*)0x95CD90;
uint8 &CDraw::FadeGreen = *(uint8*)0x95CD71;
uint8 &CDraw::FadeBlue = *(uint8*)0x95CD53;
-void
-CDraw::CalculateAspectRatio()
+float
+CDraw::FindAspectRatio(void)
{
- SetScreenMult(DEFAULT_SCALE);
-
if(FrontEndMenuManager.m_PrefsUseWideScreen)
- ms_fAspectRatio = 16.0f/9.0f;
+ return 16.0f/9.0f;
else
- ms_fAspectRatio = 4.0f/3.0f;
+ return 4.0f/3.0f;
}
-static float hFov2vFov(float hfov)
+// convert a 4:3 hFOV to vFOV,
+// then convert that vFOV to hFOV for our aspect ratio,
+// i.e. HOR+
+float
+CDraw::ConvertFOV(float hfov)
{
- float w = SCREENW;
- float h = SCREENH;
-
// => tan(hFOV/2) = tan(vFOV/2)*aspectRatio
// => tan(vFOV/2) = tan(hFOV/2)/aspectRatio
- float ar1 = 4.0/3.0;
- float ar2 = w/h;
+ float ar1 = DEFAULT_ASPECT_RATIO;
+ float ar2 = GetAspectRatio();
hfov = DEGTORAD(hfov);
float vfov = atan(tan(hfov/2) / ar1) *2;
hfov = atan(tan(vfov/2) * ar2) *2;
@@ -45,9 +45,11 @@ static float hFov2vFov(float hfov)
void
CDraw::SetFOV(float fov)
{
-// TODO: fix FOV here or somewhere else?
-// ms_fFOV = hFov2vFov(fov);
+#ifdef ASPECT_RATIO_SCALE
+ ms_fFOV = ConvertFOV(fov);
+#else
ms_fFOV = fov;
+#endif
}
STARTPATCHES
diff --git a/src/render/Draw.h b/src/render/Draw.h
index 1fcb5212..3349c6c9 100644
--- a/src/render/Draw.h
+++ b/src/render/Draw.h
@@ -1,16 +1,18 @@
#pragma once
-#define HUD_SCALE 0.8f
-#define DEFAULT_SCALE 1.0f
-
class CDraw
{
private:
static float &ms_fNearClipZ;
static float &ms_fFarClipZ;
static float &ms_fFOV;
+ static float ms_fLODDistance; // unused
+
+#ifdef ASPECT_RATIO_SCALE
+ // we use this variable to scale a lot of 2D elements
+ // so better cache it
static float ms_fAspectRatio;
- static float ms_fScreenMultiplier;
+#endif
public:
static uint8 &FadeValue;
@@ -26,8 +28,12 @@ public:
static void SetFOV(float fov);
static float GetFOV(void) { return ms_fFOV; }
- static void CalculateAspectRatio();
+ static float FindAspectRatio(void);
+#ifdef ASPECT_RATIO_SCALE
+ static float ConvertFOV(float fov);
static float GetAspectRatio(void) { return ms_fAspectRatio; }
- static void SetScreenMult(float mult) { ms_fScreenMultiplier = mult; };
- static float GetScreenMult(void) { return ms_fScreenMultiplier; };
+ static void SetAspectRatio(float ratio) { ms_fAspectRatio = ratio; }
+#else
+ static float GetAspectRatio(void) { return FindAspectRatio(); }
+#endif
};
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index 83e62ba0..e5a44221 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -300,10 +300,10 @@ void CHud::Draw()
/*
DrawAmmo
*/
- int16 AmmoAmount = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition;
- int32 AmmoInClip = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoInClip;
- int32 TotalAmmo = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal;
- int32 Ammo, Clip;
+ uint32 AmmoAmount = CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition;
+ uint32 AmmoInClip = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoInClip;
+ uint32 TotalAmmo = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal;
+ uint32 Ammo, Clip;
if (AmmoAmount <= 1 || AmmoAmount >= 1000)
sprintf(sTemp, "%d", TotalAmmo);
@@ -787,8 +787,8 @@ void CHud::Draw()
if (m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_RADAR) {
CRadar::DrawMap();
CRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT));
- // FIX: game doesn't scale RADAR_LEFT here
- rect.Translate(SCREEN_SCALE_X(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT));
+ // FIX? scale RADAR_LEFT here somehow
+ rect.Translate(RADAR_LEFT, SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT));
rect.Grow(4.0f);
Sprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255));
CRadar::DrawBlips();
@@ -1359,7 +1359,7 @@ void CHud::SetHelpMessage(wchar *message, bool quick)
CMessages::InsertPlayerControlKeysInString(m_HelpMessage);
for (int i = 0; i < 256; i++) {
- m_LastHelpMessage[i] = message[i];
+ m_LastHelpMessage[i] = 0;
}
m_HelpMessageState = 0;
@@ -1443,7 +1443,7 @@ STARTPATCHES
InjectHook(0x5048F0, &CHud::Initialise, PATCH_JUMP);
InjectHook(0x504CC0, &CHud::ReInitialise, PATCH_JUMP);
InjectHook(0x50A250, &CHud::SetBigMessage, PATCH_JUMP);
- //InjectHook(0x5051E0, &CHud::SetHelpMessage, PATCH_JUMP);
+ InjectHook(0x5051E0, &CHud::SetHelpMessage, PATCH_JUMP);
InjectHook(0x50A210, &CHud::SetMessage, PATCH_JUMP);
InjectHook(0x50A320, &CHud::SetPagerMessage, PATCH_JUMP);
InjectHook(0x505290, &CHud::SetVehicleName, PATCH_JUMP);
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index 32923b12..a0731b1c 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -5,3 +5,8 @@
WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); }
WRAPPER void CMotionBlurStreaks::RegisterStreak(int32 id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) { EAXJMP(0x519460); }
+
+
+CBulletTrace (&CBulletTraces::aTraces)[16] = *(CBulletTrace(*)[16])*(uintptr*)0x72B1B8;
+
+WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); }
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index 1a1a4c1e..1035b315 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -11,3 +11,20 @@ class CMotionBlurStreaks
public:
static void RegisterStreak(int32 id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2);
};
+
+struct CBulletTrace
+{
+ CVector m_vecInf;
+ CVector m_vecSup;
+ bool m_bInUse;
+ uint8 m_framesInUse;
+ uint8 m_lifeTime;
+};
+
+class CBulletTraces
+{
+public:
+ static CBulletTrace (&aTraces)[16];
+
+ static void Init(void);
+};
diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp
index 57a8a22f..d917117a 100644
--- a/src/render/Sprite.cpp
+++ b/src/render/Sprite.cpp
@@ -16,7 +16,7 @@ CSprite::CalcHorizonCoors(void)
CVector p = TheCamera.GetPosition() + CVector(TheCamera.CamFrontXNorm, TheCamera.CamFrontYNorm, 0.0f)*3000.0f;
p.z = 0.0f;
p = TheCamera.m_viewMatrix * p;
- return p.y * RsGlobal.maximumHeight / p.z;
+ return p.y * SCREEN_HEIGHT / p.z;
}
bool
@@ -27,13 +27,13 @@ CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh,
if(out->z <= CDraw::GetNearClipZ() + 1.0f) return false;
if(out->z >= CDraw::GetFarClipZ() && farclip) return false;
float recip = 1.0f/out->z;
- out->x *= RsGlobal.maximumWidth * recip;
- out->y *= RsGlobal.maximumHeight * recip;
+ out->x *= SCREEN_WIDTH * recip;
+ out->y *= SCREEN_HEIGHT * recip;
// What is this? size?
*outw = 70.0f/CDraw::GetFOV();
*outh = 70.0f/CDraw::GetFOV();
- *outw *= RsGlobal.maximumWidth * recip;
- *outh *= RsGlobal.maximumHeight * recip;
+ *outw *= SCREEN_WIDTH * recip;
+ *outh *= SCREEN_HEIGHT * recip;
return true;
}
@@ -99,17 +99,17 @@ CSprite::RenderOneXLUSprite(float x, float y, float z, float w, float h, uint8 r
us[i] = -xs[i] / (2.0f*w);
xs[i] = 0.0f;
}
- if(xs[i] > RsGlobal.maximumWidth){
- us[i] = 1.0f - (xs[i]-RsGlobal.maximumWidth) / (2.0f*w);
- xs[i] = RsGlobal.maximumWidth;
+ if(xs[i] > SCREEN_WIDTH){
+ us[i] = 1.0f - (xs[i]-SCREEN_WIDTH) / (2.0f*w);
+ xs[i] = SCREEN_WIDTH;
}
if(ys[i] < 0.0f){
vs[i] = -ys[i] / (2.0f*h);
ys[i] = 0.0f;
}
- if(ys[i] > RsGlobal.maximumHeight){
- vs[i] = 1.0f - (ys[i]-RsGlobal.maximumHeight) / (2.0f*h);
- ys[i] = RsGlobal.maximumHeight;
+ if(ys[i] > SCREEN_HEIGHT){
+ vs[i] = 1.0f - (ys[i]-SCREEN_HEIGHT) / (2.0f*h);
+ ys[i] = SCREEN_HEIGHT;
}
}
@@ -169,10 +169,10 @@ CSprite::RenderOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, fl
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
- if(xs[0] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
- xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
- if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
- ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) return;
+ if(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&
+ xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;
+ if(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&
+ ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
@@ -221,17 +221,17 @@ CSprite::RenderBufferedOneXLUSprite(float x, float y, float z, float w, float h,
us[i] = -xs[i] / (2.0f*w);
xs[i] = 0.0f;
}
- if(xs[i] > RsGlobal.maximumWidth){
- us[i] = 1.0f - (xs[i]-RsGlobal.maximumWidth) / (2.0f*w);
- xs[i] = RsGlobal.maximumWidth;
+ if(xs[i] > SCREEN_WIDTH){
+ us[i] = 1.0f - (xs[i]-SCREEN_WIDTH) / (2.0f*w);
+ xs[i] = SCREEN_WIDTH;
}
if(ys[i] < 0.0f){
vs[i] = -ys[i] / (2.0f*h);
ys[i] = 0.0f;
}
- if(ys[i] > RsGlobal.maximumHeight){
- vs[i] = 1.0f - (ys[i]-RsGlobal.maximumHeight) / (2.0f*h);
- ys[i] = RsGlobal.maximumHeight;
+ if(ys[i] > SCREEN_HEIGHT){
+ vs[i] = 1.0f - (ys[i]-SCREEN_HEIGHT) / (2.0f*h);
+ ys[i] = SCREEN_HEIGHT;
}
}
@@ -283,10 +283,10 @@ CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(float x, float y, float z,
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
- if(xs[0] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
- xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
- if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
- ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) return;
+ if(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&
+ xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;
+ if(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&
+ ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
@@ -335,10 +335,10 @@ CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(float x, float y, float z, flo
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
- if(xs[0] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
- xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
- if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
- ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) return;
+ if(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&
+ xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;
+ if(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&
+ ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
@@ -388,10 +388,10 @@ CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, f
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
- if(xs[0] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
- xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
- if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
- ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) return;
+ if(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&
+ xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;
+ if(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&
+ ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;
// Colour factors, cx/y is the direction in which colours change from rgb1 to rgb2
cf[0] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f;
diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp
index 9638e53a..0481e104 100644
--- a/src/skel/win/win.cpp
+++ b/src/skel/win/win.cpp
@@ -626,9 +626,7 @@ psInitialise(void)
C_PcSave::SetSaveDirectory(_psGetUserFilesFolder());
-#ifndef NASTY_GAME
- InitialiseLanguage();
-#endif
+ InitialiseLanguage();
FrontEndMenuManager.LoadSettings();
@@ -1262,7 +1260,7 @@ UINT GetBestRefreshRate(UINT width, UINT height, UINT depth)
ASSERT(d3d != nil);
- INT refreshRate = -1;
+ UINT refreshRate = INT_MAX;
D3DFORMAT format;
if ( depth == 32 )
@@ -1284,12 +1282,9 @@ UINT GetBestRefreshRate(UINT width, UINT height, UINT depth)
{
if ( mode.RefreshRate == 0 )
return 0;
-#pragma warning( push )
-#pragma warning( disable : 4018)
if ( mode.RefreshRate < refreshRate && mode.RefreshRate >= 60 )
refreshRate = mode.RefreshRate;
-#pragma warning( pop )
}
}
@@ -1540,8 +1535,6 @@ CommandLineToArgv(RwChar *cmdLine, RwInt32 *argCount)
*/
void InitialiseLanguage()
{
-#pragma warning( push )
-#pragma warning( disable : 4302)
WORD primUserLCID = PRIMARYLANGID(GetSystemDefaultLCID());
WORD primSystemLCID = PRIMARYLANGID(GetUserDefaultLCID());
WORD primLayout = PRIMARYLANGID((DWORD)GetKeyboardLayout(0));
@@ -1549,7 +1542,6 @@ void InitialiseLanguage()
WORD subUserLCID = SUBLANGID(GetSystemDefaultLCID());
WORD subSystemLCID = SUBLANGID(GetUserDefaultLCID());
WORD subLayout = SUBLANGID((DWORD)GetKeyboardLayout(0));
-#pragma warning( pop )
if ( primUserLCID == LANG_GERMAN
|| primSystemLCID == LANG_GERMAN
@@ -1573,6 +1565,12 @@ void InitialiseLanguage()
|| subSystemLCID == SUBLANG_ENGLISH_AUS
|| subLayout == SUBLANG_ENGLISH_AUS )
CGame::noProstitutes = true;
+
+#ifdef NASTY_GAME
+ CGame::nastyGame = true;
+ CMenuManager::m_PrefsAllowNastyGame = true;
+ CGame::noProstitutes = false;
+#endif
int32 lang;
@@ -2420,14 +2418,10 @@ void _InputInitialiseJoys()
}
}
-#pragma warning( push )
-#pragma warning( disable : 4700)
-HRESULT _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num)
+void _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num)
{
- HRESULT hr;
-
DIDEVICEOBJECTINSTANCE objInst;
-
+
objInst.dwSize = sizeof( DIDEVICEOBJECTINSTANCE );
DIPROPRANGE range;
@@ -2445,7 +2439,7 @@ HRESULT _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num)
if ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst, DIJOFS_X, DIPH_BYOFFSET ) ) )
{
if( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) )
- return S_FALSE;
+ return;
else
;
}
@@ -2457,7 +2451,7 @@ HRESULT _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num)
if ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst, DIJOFS_Y, DIPH_BYOFFSET ) ) )
{
if( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) )
- return S_FALSE;
+ return;
else
;
}
@@ -2469,7 +2463,7 @@ HRESULT _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num)
if ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst, DIJOFS_Z, DIPH_BYOFFSET ) ) )
{
if( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) )
- return S_FALSE;
+ return;
else
AllValidWinJoys.m_aJoys[num].m_bHasAxisZ = true; // z rightStickPos.x
}
@@ -2481,15 +2475,12 @@ HRESULT _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num)
if ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst, DIJOFS_RZ, DIPH_BYOFFSET ) ) )
{
if( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) )
- return S_FALSE;
+ return;
else
AllValidWinJoys.m_aJoys[num].m_bHasAxisR = true; // r rightStickPos.y
}
}
-
- return hr;
}
-#pragma warning( pop )
HRESULT _InputAddJoys()
{
@@ -2973,9 +2964,7 @@ void _InputTranslateShiftKeyUpDown(RsKeyCodes *rs)
}
}
-#pragma warning( push )
-#pragma warning( disable : 4805)
-BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, bool bDown)
+BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown)
{
*rs = rsNULL;
switch ( key )
@@ -3002,7 +2991,6 @@ BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, bool bDown)
return TRUE;
}
-#pragma warning( pop )
BOOL _InputIsExtended(INT flag)
{
diff --git a/src/skel/win/win.h b/src/skel/win/win.h
index 371b9e44..a1f37bfd 100644
--- a/src/skel/win/win.h
+++ b/src/skel/win/win.h
@@ -63,14 +63,14 @@ HRESULT _InputInitialise();
HRESULT _InputInitialiseMouse();
HRESULT CapturePad(RwInt32 padID);
void _InputInitialiseJoys();
-HRESULT _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num);
+void _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num);
HRESULT _InputAddJoys();
HRESULT _InputGetMouseState(DIMOUSESTATE2 *state);
void _InputShutdown();
BOOL CALLBACK _InputEnumDevicesCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext );
BOOL _InputTranslateKey(RsKeyCodes *rs, UINT flag, UINT key);
void _InputTranslateShiftKeyUpDown(RsKeyCodes *rs);;
-BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, bool bDown);
+BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown);
BOOL _InputIsExtended(INT flag);
void InitialiseLanguage();
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp
index fea09245..0c48db6b 100644
--- a/src/weapons/Weapon.cpp
+++ b/src/weapons/Weapon.cpp
@@ -1,6 +1,41 @@
#include "common.h"
#include "patcher.h"
#include "Weapon.h"
+#include "Timer.h"
+#include "WeaponInfo.h"
WRAPPER bool CWeapon::Fire(CEntity*, CVector*) { EAXJMP(0x55C380); }
-WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); } \ No newline at end of file
+WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); }
+
+void
+CWeapon::Initialise(eWeaponType type, int ammo)
+{
+ m_eWeaponType = type;
+ m_eWeaponState = WEAPONSTATE_READY;
+ if (ammo > 99999)
+ m_nAmmoTotal = 99999;
+ else
+ m_nAmmoTotal = ammo;
+ m_nAmmoInClip = 0;
+ Reload();
+ m_nTimer = 0;
+}
+
+void
+CWeapon::Reload(void)
+{
+ if (m_nAmmoTotal == 0)
+ return;
+
+ CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType);
+
+ if (m_nAmmoTotal >= info->m_nAmountofAmmunition)
+ m_nAmmoInClip = info->m_nAmountofAmmunition;
+ else
+ m_nAmmoInClip = m_nAmmoTotal;
+}
+
+STARTPATCHES
+ InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP);
+ InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP);
+ENDPATCHES \ No newline at end of file
diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h
index aebcb2c6..8cb435ce 100644
--- a/src/weapons/Weapon.h
+++ b/src/weapons/Weapon.h
@@ -1,7 +1,7 @@
#pragma once
#include "Entity.h"
-enum eWeaponType
+enum eWeaponType : uint32
{
WEAPONTYPE_UNARMED = 0,
WEAPONTYPE_BASEBALLBAT,
@@ -45,11 +45,17 @@ class CWeapon
public:
eWeaponType m_eWeaponType;
eWeaponState m_eWeaponState;
- int32 m_nAmmoInClip;
- int32 m_nAmmoTotal;
- int32 m_nTimer;
+ uint32 m_nAmmoInClip;
+ uint32 m_nAmmoTotal;
+ uint32 m_nTimer;
bool m_bAddRotOffset;
+ CWeapon() {
+ m_bAddRotOffset = false;
+ }
+
+ void Initialise(eWeaponType type, int ammo);
+ void Reload(void);
bool Fire(CEntity*, CVector*);
void AddGunshell(CEntity*, CVector const&, CVector2D const&, float);
};
diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp
index 46ecfb54..4830c86a 100644
--- a/src/weapons/WeaponInfo.cpp
+++ b/src/weapons/WeaponInfo.cpp
@@ -61,7 +61,7 @@ CWeaponInfo::LoadWeaponData(void)
char animToPlay[32], anim2ToPlay[32];
CAnimBlendAssociation *animAssoc;
- AnimationId animId, anim2Id;
+ AnimationId animId;
int bp, buflen;
int lp, linelen;
@@ -101,7 +101,6 @@ CWeaponInfo::LoadWeaponData(void)
fireOffsetY = 0.0f;
fireOffsetZ = 0.0f;
animId = ANIM_WALK;
- anim2Id = ANIM_WALK;
sscanf(
&line[lp],
"%s %s %f %d %d %d %d %f %f %f %f %f %f %f %s %s %f %f %f %f %d %d",
@@ -136,9 +135,9 @@ CWeaponInfo::LoadWeaponData(void)
animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animToPlay);
animId = static_cast<AnimationId>(animAssoc->animId);
- if (strncmp(anim2ToPlay, "null", 5) != 0) {
+ if (strncmp(anim2ToPlay, "null", 4) != 0) {
animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, anim2ToPlay);
- anim2Id = static_cast<AnimationId>(animAssoc->animId);
+ ms_apWeaponInfos[weaponType].m_Anim2ToPlay = static_cast<AnimationId>(animAssoc->animId);
}
CVector vecFireOffset(fireOffsetX, fireOffsetY, fireOffsetZ);
@@ -155,7 +154,6 @@ CWeaponInfo::LoadWeaponData(void)
ms_apWeaponInfos[weaponType].m_fSpread = spread;
ms_apWeaponInfos[weaponType].m_vecFireOffset = vecFireOffset;
ms_apWeaponInfos[weaponType].m_AnimToPlay = animId;
- ms_apWeaponInfos[weaponType].m_Anim2ToPlay = anim2Id;
ms_apWeaponInfos[weaponType].m_fAnimLoopStart = animLoopStart * 0.03f;
ms_apWeaponInfos[weaponType].m_fAnimLoopEnd = animLoopEnd * 0.03f;
ms_apWeaponInfos[weaponType].m_fAnimFrameFire = delayBetweenAnimAndFire * 0.03f;