diff options
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 ¢er, 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; |