Merge branch 'master' into garages_dev

This commit is contained in:
Nikolay Korolev 2020-03-28 15:24:55 +03:00
commit 9fb101fdd9
70 changed files with 6495 additions and 2122 deletions

View File

@ -43,7 +43,6 @@ CBoat
CBrightLights CBrightLights
CBulletInfo CBulletInfo
CBulletTraces CBulletTraces
CCam
CCamera CCamera
CCopPed CCopPed
CCrane CCrane

View File

@ -3906,8 +3906,8 @@ MACRO_STOP
#pragma warning( disable : 344 ) #pragma warning( disable : 344 )
#endif /* (defined(__ICL)) */ #endif /* (defined(__ICL)) */
//nobody needed that - AAP
#include <windows.h> //#include <windows.h>
#if (defined(RWDEBUG)) #if (defined(RWDEBUG))
#if (defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC)) #if (defined(RWMEMDEBUG) && !defined(_CRTDBG_MAP_ALLOC))

View File

@ -203,6 +203,15 @@ CAnimBlendAssociation::UpdateBlend(float timeDelta)
return true; return true;
} }
#include <new>
class CAnimBlendAssociation_ : public CAnimBlendAssociation
{
public:
CAnimBlendAssociation *ctor1(void) { return ::new (this) CAnimBlendAssociation(); }
CAnimBlendAssociation *ctor2(CAnimBlendAssociation &other) { return ::new (this) CAnimBlendAssociation(other); }
void dtor(void) { this->CAnimBlendAssociation::~CAnimBlendAssociation(); }
};
STARTPATCHES STARTPATCHES
InjectHook(0x4016A0, &CAnimBlendAssociation::AllocateAnimBlendNodeArray, PATCH_JUMP); InjectHook(0x4016A0, &CAnimBlendAssociation::AllocateAnimBlendNodeArray, PATCH_JUMP);
@ -219,7 +228,7 @@ STARTPATCHES
InjectHook(0x4031F0, &CAnimBlendAssociation::UpdateTime, PATCH_JUMP); InjectHook(0x4031F0, &CAnimBlendAssociation::UpdateTime, PATCH_JUMP);
InjectHook(0x4032B0, &CAnimBlendAssociation::UpdateBlend, PATCH_JUMP); InjectHook(0x4032B0, &CAnimBlendAssociation::UpdateBlend, PATCH_JUMP);
InjectHook(0x401460, &CAnimBlendAssociation::ctor1, PATCH_JUMP); InjectHook(0x401460, &CAnimBlendAssociation_::ctor1, PATCH_JUMP);
InjectHook(0x4014C0, &CAnimBlendAssociation::ctor2, PATCH_JUMP); InjectHook(0x4014C0, &CAnimBlendAssociation_::ctor2, PATCH_JUMP);
InjectHook(0x401520, &CAnimBlendAssociation::dtor, PATCH_JUMP); InjectHook(0x401520, &CAnimBlendAssociation_::dtor, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -85,9 +85,5 @@ public:
static CAnimBlendAssociation *FromLink(CAnimBlendLink *l) { static CAnimBlendAssociation *FromLink(CAnimBlendLink *l) {
return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link)); return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link));
} }
CAnimBlendAssociation *ctor1(void) { return ::new (this) CAnimBlendAssociation(); }
CAnimBlendAssociation *ctor2(CAnimBlendAssociation &other) { return ::new (this) CAnimBlendAssociation(other); }
void dtor(void) { this->CAnimBlendAssociation::~CAnimBlendAssociation(); }
}; };
static_assert(sizeof(CAnimBlendAssociation) == 0x40, "CAnimBlendAssociation: error"); static_assert(sizeof(CAnimBlendAssociation) == 0x40, "CAnimBlendAssociation: error");

View File

@ -36,9 +36,19 @@ CAnimBlendClumpData::ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *
cb(&frames[i], arg); cb(&frames[i], arg);
} }
#include <new>
class CAnimBlendClumpData_ : public CAnimBlendClumpData
{
public:
CAnimBlendClumpData *ctor(void) { return ::new (this) CAnimBlendClumpData(); }
void dtor(void) { this->CAnimBlendClumpData::~CAnimBlendClumpData(); }
};
STARTPATCHES STARTPATCHES
InjectHook(0x401880, &CAnimBlendClumpData::ctor, PATCH_JUMP); InjectHook(0x401880, &CAnimBlendClumpData_::ctor, PATCH_JUMP);
InjectHook(0x4018B0, &CAnimBlendClumpData::dtor, PATCH_JUMP); InjectHook(0x4018B0, &CAnimBlendClumpData_::dtor, PATCH_JUMP);
InjectHook(0x4018F0, &CAnimBlendClumpData::SetNumberOfFrames, PATCH_JUMP); InjectHook(0x4018F0, &CAnimBlendClumpData::SetNumberOfFrames, PATCH_JUMP);
InjectHook(0x401930, &CAnimBlendClumpData::ForAllFrames, PATCH_JUMP); InjectHook(0x401930, &CAnimBlendClumpData::ForAllFrames, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -49,9 +49,5 @@ public:
void SetNumberOfBones(int n) { SetNumberOfFrames(n); } void SetNumberOfBones(int n) { SetNumberOfFrames(n); }
#endif #endif
void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg); void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg);
CAnimBlendClumpData *ctor(void) { return ::new (this) CAnimBlendClumpData(); }
void dtor(void) { this->CAnimBlendClumpData::~CAnimBlendClumpData(); }
}; };
static_assert(sizeof(CAnimBlendClumpData) == 0x14, "CAnimBlendClumpData: error"); static_assert(sizeof(CAnimBlendClumpData) == 0x14, "CAnimBlendClumpData: error");

View File

@ -11,19 +11,10 @@ CPathFind &ThePaths = *(CPathFind*)0x8F6754;
WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); } WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); }
enum #define MAX_DIST INT16_MAX-1
{
NodeTypeExtern = 1,
NodeTypeIntern = 2,
ObjectFlag1 = 1,
ObjectEastWest = 2,
MAX_DIST = INT16_MAX-1
};
// object flags: // object flags:
// 1 // 1 UseInRoadBlock
// 2 east/west road(?) // 2 east/west road(?)
CPathInfoForObject *&InfoForTileCars = *(CPathInfoForObject**)0x8F1A8C; CPathInfoForObject *&InfoForTileCars = *(CPathInfoForObject**)0x8F1A8C;
@ -218,14 +209,14 @@ CPathFind::PreparePathData(void)
if(numIntern == 1 && numExtern == 2){ if(numIntern == 1 && numExtern == 2){
if(numLanes < 4){ if(numLanes < 4){
if((i & 7) == 4){ // WHAT? if((i & 7) == 4){ // WHAT?
m_objectFlags[i] |= ObjectFlag1; m_objectFlags[i] |= UseInRoadBlock;
if(maxX > maxY) if(maxX > maxY)
m_objectFlags[i] |= ObjectEastWest; m_objectFlags[i] |= ObjectEastWest;
else else
m_objectFlags[i] &= ~ObjectEastWest; m_objectFlags[i] &= ~ObjectEastWest;
} }
}else{ }else{
m_objectFlags[i] |= ObjectFlag1; m_objectFlags[i] |= UseInRoadBlock;
if(maxX > maxY) if(maxX > maxY)
m_objectFlags[i] |= ObjectEastWest; m_objectFlags[i] |= ObjectEastWest;
else else

View File

@ -9,6 +9,15 @@ public:
static bool CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16); static bool CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16);
}; };
enum
{
NodeTypeExtern = 1,
NodeTypeIntern = 2,
UseInRoadBlock = 1,
ObjectEastWest = 2,
};
enum enum
{ {
PATH_CAR = 0, PATH_CAR = 0,

View File

@ -1,7 +1,37 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "RoadBlocks.h" #include "RoadBlocks.h"
#include "PathFind.h"
int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34;
int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8;
bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810;
WRAPPER void CRoadBlocks::Init(void) { EAXJMP(0x436F50); }
WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); } WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); }
WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); } WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); }
void
CRoadBlocks::Init(void)
{
NumRoadBlocks = 0;
for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) {
if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) {
if (NumRoadBlocks < 600) {
InOrOut[NumRoadBlocks] = true;
RoadBlockObjects[NumRoadBlocks] = objId;
NumRoadBlocks++;
} else {
#ifndef MASTER
printf("Not enough room for the potential roadblocks\n");
#endif
// FIX: Don't iterate loop after NUMROADBLOCKS
return;
}
}
}
}
STARTPATCHES
InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP);
ENDPATCHES

View File

@ -6,6 +6,10 @@ class CVehicle;
class CRoadBlocks class CRoadBlocks
{ {
public: public:
static int16 (&NumRoadBlocks);
static int16 (&RoadBlockObjects)[NUMROADBLOCKS];
static bool (&InOrOut)[NUMROADBLOCKS];
static void Init(void); static void Init(void);
static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16); static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16);
static void GenerateRoadBlocks(void); static void GenerateRoadBlocks(void);

View File

@ -2,5 +2,10 @@
#include "patcher.h" #include "patcher.h"
#include "SceneEdit.h" #include "SceneEdit.h"
int32 &CSceneEdit::m_bCameraFollowActor = *(int*)0x940590;
bool &CSceneEdit::m_bRecording = *(bool*)0x95CD1F;
CVector &CSceneEdit::m_vecCurrentPosition = *(CVector*)0x943064;
CVector &CSceneEdit::m_vecCamHeading = *(CVector*)0x942F8C;
WRAPPER void CSceneEdit::Update(void) { EAXJMP(0x585570); } WRAPPER void CSceneEdit::Update(void) { EAXJMP(0x585570); }
WRAPPER void CSceneEdit::Init(void) { EAXJMP(0x585170); } WRAPPER void CSceneEdit::Init(void) { EAXJMP(0x585170); }

View File

@ -3,6 +3,11 @@
class CSceneEdit class CSceneEdit
{ {
public: public:
static int32 &m_bCameraFollowActor;
static bool &m_bRecording;
static CVector &m_vecCurrentPosition;
static CVector &m_vecCamHeading;
static void Update(void); static void Update(void);
static void Init(void); static void Init(void);
}; };

View File

@ -1,3 +1,4 @@
#define WITHWINDOWS // for our script loading hack
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"

4424
src/core/Cam.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@ class CEntity;
class CPed; class CPed;
class CAutomobile; class CAutomobile;
extern int16 &DebugCamMode;
#define NUMBER_OF_VECTORS_FOR_AVERAGE 2 #define NUMBER_OF_VECTORS_FOR_AVERAGE 2
struct CCam struct CCam
@ -66,17 +68,17 @@ struct CCam
bool m_bTheHeightFixerVehicleIsATrain; bool m_bTheHeightFixerVehicleIsATrain;
bool LookBehindCamWasInFront; bool LookBehindCamWasInFront;
bool LookingBehind; bool LookingBehind;
bool LookingLeft; // 32 bool LookingLeft;
bool LookingRight; bool LookingRight;
bool ResetStatics; //for interpolation type stuff to work bool ResetStatics; //for interpolation type stuff to work
bool Rotating; bool Rotating;
int16 Mode; // CameraMode int16 Mode; // CameraMode
uint32 m_uiFinishTime; // 52 uint32 m_uiFinishTime;
int m_iDoCollisionChecksOnFrameNum; int m_iDoCollisionChecksOnFrameNum;
int m_iDoCollisionCheckEveryNumOfFrames; int m_iDoCollisionCheckEveryNumOfFrames;
int m_iFrameNumWereAt; // 64 int m_iFrameNumWereAt;
int m_iRunningVectorArrayPos; int m_iRunningVectorArrayPos;
int m_iRunningVectorCounter; int m_iRunningVectorCounter;
int DirectionWasLooking; int DirectionWasLooking;
@ -85,9 +87,9 @@ struct CCam
float f_Roll; //used for adding a slight roll to the camera in the float f_Roll; //used for adding a slight roll to the camera in the
float f_rollSpeed; float f_rollSpeed;
float m_fSyphonModeTargetZOffSet; float m_fSyphonModeTargetZOffSet;
float m_fUnknownZOffSet; float m_fRoadOffSet;
float m_fAmountFractionObscured; float m_fAmountFractionObscured;
float m_fAlphaSpeedOverOneFrame; // 100 float m_fAlphaSpeedOverOneFrame;
float m_fBetaSpeedOverOneFrame; float m_fBetaSpeedOverOneFrame;
float m_fBufferedTargetBeta; float m_fBufferedTargetBeta;
float m_fBufferedTargetOrientation; float m_fBufferedTargetOrientation;
@ -95,7 +97,7 @@ struct CCam
float m_fCamBufferedHeight; float m_fCamBufferedHeight;
float m_fCamBufferedHeightSpeed; float m_fCamBufferedHeightSpeed;
float m_fCloseInPedHeightOffset; float m_fCloseInPedHeightOffset;
float m_fCloseInPedHeightOffsetSpeed; // 132 float m_fCloseInPedHeightOffsetSpeed;
float m_fCloseInCarHeightOffset; float m_fCloseInCarHeightOffset;
float m_fCloseInCarHeightOffsetSpeed; float m_fCloseInCarHeightOffsetSpeed;
float m_fDimensionOfHighestNearCar; float m_fDimensionOfHighestNearCar;
@ -103,7 +105,7 @@ struct CCam
float m_fFovSpeedOverOneFrame; float m_fFovSpeedOverOneFrame;
float m_fMinDistAwayFromCamWhenInterPolating; float m_fMinDistAwayFromCamWhenInterPolating;
float m_fPedBetweenCameraHeightOffset; float m_fPedBetweenCameraHeightOffset;
float m_fPlayerInFrontSyphonAngleOffSet; // 164 float m_fPlayerInFrontSyphonAngleOffSet;
float m_fRadiusForDead; float m_fRadiusForDead;
float m_fRealGroundDist; //used for follow ped mode float m_fRealGroundDist; //used for follow ped mode
float m_fTargetBeta; float m_fTargetBeta;
@ -111,7 +113,7 @@ struct CCam
float m_fTransitionBeta; float m_fTransitionBeta;
float m_fTrueBeta; float m_fTrueBeta;
float m_fTrueAlpha; // 200 float m_fTrueAlpha;
float m_fInitialPlayerOrientation; //used for first person float m_fInitialPlayerOrientation; //used for first person
float Alpha; float Alpha;
@ -120,34 +122,25 @@ struct CCam
float FOVSpeed; float FOVSpeed;
float Beta; float Beta;
float BetaSpeed; float BetaSpeed;
float Distance; // 232 float Distance;
float DistanceSpeed; float DistanceSpeed;
float CA_MIN_DISTANCE; float CA_MIN_DISTANCE;
float CA_MAX_DISTANCE; float CA_MAX_DISTANCE;
float SpeedVar; float SpeedVar;
// ped onfoot zoom distance CVector m_cvecSourceSpeedOverOneFrame;
float m_fTargetZoomGroundOne; CVector m_cvecTargetSpeedOverOneFrame;
float m_fTargetZoomGroundTwo; // 256 CVector m_cvecUpOverOneFrame;
float m_fTargetZoomGroundThree;
// ped onfoot alpha angle offset
float m_fTargetZoomOneZExtra;
float m_fTargetZoomTwoZExtra;
float m_fTargetZoomThreeZExtra;
float m_fTargetZoomZCloseIn; CVector m_cvecTargetCoorsForFudgeInter;
float m_fMinRealGroundDist; CVector m_cvecCamFixedModeVector;
float m_fTargetCloseInDist; CVector m_cvecCamFixedModeSource;
CVector m_cvecCamFixedModeUpOffSet;
CVector m_cvecTargetCoorsForFudgeInter; // 360 CVector m_vecLastAboveWaterCamPosition; //helper for when the player has gone under the water
CVector m_cvecCamFixedModeVector; // 372 CVector m_vecBufferedPlayerBodyOffset;
CVector m_cvecCamFixedModeSource; // 384
CVector m_cvecCamFixedModeUpOffSet; // 396
CVector m_vecLastAboveWaterCamPosition; //408 //helper for when the player has gone under the water
CVector m_vecBufferedPlayerBodyOffset; // 420
// The three vectors that determine this camera for this frame // The three vectors that determine this camera for this frame
CVector Front; // 432 // Direction of looking in CVector Front; // Direction of looking in
CVector Source; // Coors in world space CVector Source; // Coors in world space
CVector SourceBeforeLookBehind; CVector SourceBeforeLookBehind;
CVector Up; // Just that CVector Up; // Just that
@ -162,6 +155,10 @@ struct CCam
bool m_bFirstPersonRunAboutActive; bool m_bFirstPersonRunAboutActive;
CCam(void) { Init(); }
void Init(void);
void Process(void);
void ProcessSpecialHeightRoutines(void);
void GetVectorsReadyForRW(void); void GetVectorsReadyForRW(void);
CVector DoAverageOnVector(const CVector &vec); CVector DoAverageOnVector(const CVector &vec);
float GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies); float GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies);
@ -171,13 +168,59 @@ struct CCam
bool FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation); bool FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation);
void Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist); void Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist);
void FixCamWhenObscuredByVehicle(const CVector &TargetCoors); void FixCamWhenObscuredByVehicle(const CVector &TargetCoors);
bool Using3rdPersonMouseCam(); void LookBehind(void);
bool GetWeaponFirstPersonOn(); void LookLeft(void);
void LookRight(void);
void ClipIfPedInFrontOfPlayer(void);
void KeepTrackOfTheSpeed(const CVector &source, const CVector &target, const CVector &up, const float &alpha, const float &beta, const float &fov);
bool Using3rdPersonMouseCam(void);
bool GetWeaponFirstPersonOn(void);
bool IsTargetInWater(const CVector &CamCoors);
void AvoidWallsTopDownPed(const CVector &TargetCoors, const CVector &Offset, float *Adjuster, float *AdjusterSpeed, float yDistLimit);
void PrintMode(void);
void Process_Debug(float *vec, float a, float b, float c); void Process_Debug(const CVector&, float, float, float);
void Process_Editor(const CVector&, float, float, float);
void Process_ModelView(const CVector &CameraTarget, float, float, float);
void Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float); void Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float); void Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float); void Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_TopDown(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar);
void Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_Rocket(const CVector &CameraTarget, float, float, float);
void Process_M16_1stPerson(const CVector &CameraTarget, float, float, float);
void Process_1stPerson(const CVector &CameraTarget, float, float, float);
void Process_1rstPersonPedOnPC(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_Sniper(const CVector &CameraTarget, float, float, float);
void Process_Syphon(const CVector &CameraTarget, float, float, float);
void Process_Syphon_Crim_In_Front(const CVector &CameraTarget, float, float, float);
void Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_FlyBy(const CVector&, float, float, float);
void Process_WheelCam(const CVector&, float, float, float);
void Process_Fixed(const CVector &CameraTarget, float, float, float);
void Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_Circle(const CVector &CameraTarget, float, float, float);
void Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, float);
void ProcessPedsDeadBaby(void);
bool ProcessArrestCamOne(void);
bool ProcessArrestCamTwo(void);
/* Some of the unused PS2 cams */
void Process_Chris_With_Binding_PlusRotation(const CVector &CameraTarget, float, float, float);
void Process_ReactionCam(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_FollowPed_WithBinding(const CVector &CameraTarget, float TargetOrientation, float, float);
// TODO:
// CCam::Process_CushyPillows_Arse
// CCam::Process_Look_At_Cars
// CCam::Process_CheesyZoom
// CCam::Process_Aiming
// CCam::Process_Bill // same as BehindCar due to unused variables
// CCam::Process_Im_The_Passenger_Woo_Woo
// CCam::Process_Blood_On_The_Tracks
// CCam::Process_Cam_Running_Side_Train
// CCam::Process_Cam_On_Train_Roof
}; };
static_assert(sizeof(CCam) == 0x1A4, "CCam: wrong size"); static_assert(sizeof(CCam) == 0x1A4, "CCam: wrong size");
static_assert(offsetof(CCam, Alpha) == 0xA8, "CCam: error"); static_assert(offsetof(CCam, Alpha) == 0xA8, "CCam: error");
@ -223,6 +266,7 @@ enum
FADE_OUT = 0, FADE_OUT = 0,
FADE_IN, FADE_IN,
FADE_NONE
}; };
enum enum
@ -493,6 +537,7 @@ int m_iModeObbeCamIsInForCar;
void TakeControlNoEntity(const CVector&, int16, int32); void TakeControlNoEntity(const CVector&, int16, int32);
void SetCamPositionForFixedMode(const CVector&, const CVector&); void SetCamPositionForFixedMode(const CVector&, const CVector&);
bool GetFading(); bool GetFading();
int GetFadingDirection();
void Init(); void Init();
void SetRwCamera(RwCamera*); void SetRwCamera(RwCamera*);
@ -525,8 +570,12 @@ static_assert(offsetof(CCamera, m_uiTransitionState) == 0x89, "CCamera: error");
static_assert(offsetof(CCamera, m_uiTimeTransitionStart) == 0x94, "CCamera: error"); static_assert(offsetof(CCamera, m_uiTimeTransitionStart) == 0x94, "CCamera: error");
static_assert(offsetof(CCamera, m_BlurBlue) == 0x9C, "CCamera: error"); static_assert(offsetof(CCamera, m_BlurBlue) == 0x9C, "CCamera: error");
static_assert(offsetof(CCamera, Cams) == 0x1A4, "CCamera: error"); static_assert(offsetof(CCamera, Cams) == 0x1A4, "CCamera: error");
static_assert(offsetof(CCamera, pToGarageWeAreIn) == 0x690, "CCamera: error");
static_assert(offsetof(CCamera, m_PreviousCameraPosition) == 0x6B0, "CCamera: error");
static_assert(offsetof(CCamera, m_vecCutSceneOffset) == 0x6F8, "CCamera: error"); static_assert(offsetof(CCamera, m_vecCutSceneOffset) == 0x6F8, "CCamera: error");
static_assert(offsetof(CCamera, m_arrPathArray) == 0x7a8, "CCamera: error");
static_assert(sizeof(CCamera) == 0xE9D8, "CCamera: wrong size"); static_assert(sizeof(CCamera) == 0xE9D8, "CCamera: wrong size");
extern CCamera &TheCamera; extern CCamera &TheCamera;
void CamShakeNoPos(CCamera*, float); void CamShakeNoPos(CCamera*, float);

View File

@ -43,6 +43,7 @@ BOOL _gbCdStreamOverlapped;
BOOL _gbCdStreamAsync; BOOL _gbCdStreamAsync;
DWORD _gdwCdStreamFlags; DWORD _gdwCdStreamFlags;
DWORD WINAPI CdStreamThread(LPVOID lpThreadParameter);
void void
CdStreamInitThread(void) CdStreamInitThread(void)

View File

@ -39,7 +39,6 @@ int32 CdStreamSync(int32 channel);
void AddToQueue(Queue *queue, int32 item); void AddToQueue(Queue *queue, int32 item);
int32 GetFirstInQueue(Queue *queue); int32 GetFirstInQueue(Queue *queue);
void RemoveFirstInQueue(Queue *queue); void RemoveFirstInQueue(Queue *queue);
DWORD WINAPI CdStreamThread(LPVOID lpThreadParameter);
bool CdStreamAddImage(char const *path); bool CdStreamAddImage(char const *path);
char *CdStreamGetImageName(int32 cd); char *CdStreamGetImageName(int32 cd);
void CdStreamRemoveImages(void); void CdStreamRemoveImages(void);

View File

@ -2061,6 +2061,19 @@ CColModel::operator=(const CColModel &other)
return *this; return *this;
} }
#include <new>
struct CColLine_ : public CColLine
{
CColLine *ctor(CVector *p0, CVector *p1) { return ::new (this) CColLine(*p0, *p1); }
};
struct CColModel_ : public CColModel
{
CColModel *ctor(void) { return ::new (this) CColModel(); }
void dtor(void) { this->CColModel::~CColModel(); }
};
STARTPATCHES STARTPATCHES
InjectHook(0x4B9C30, (CMatrix& (*)(const CMatrix &src, CMatrix &dst))Invert, PATCH_JUMP); InjectHook(0x4B9C30, (CMatrix& (*)(const CMatrix &src, CMatrix &dst))Invert, PATCH_JUMP);
@ -2099,15 +2112,15 @@ STARTPATCHES
InjectHook(0x411E40, (void (CColSphere::*)(float, const CVector&, uint8, uint8))&CColSphere::Set, PATCH_JUMP); InjectHook(0x411E40, (void (CColSphere::*)(float, const CVector&, uint8, uint8))&CColSphere::Set, PATCH_JUMP);
InjectHook(0x40B2A0, &CColBox::Set, PATCH_JUMP); InjectHook(0x40B2A0, &CColBox::Set, PATCH_JUMP);
InjectHook(0x40B320, &CColLine::ctor, PATCH_JUMP); InjectHook(0x40B320, &CColLine_::ctor, PATCH_JUMP);
InjectHook(0x40B350, &CColLine::Set, PATCH_JUMP); InjectHook(0x40B350, &CColLine::Set, PATCH_JUMP);
InjectHook(0x411E70, &CColTriangle::Set, PATCH_JUMP); InjectHook(0x411E70, &CColTriangle::Set, PATCH_JUMP);
InjectHook(0x411EA0, &CColTrianglePlane::Set, PATCH_JUMP); InjectHook(0x411EA0, &CColTrianglePlane::Set, PATCH_JUMP);
InjectHook(0x412140, &CColTrianglePlane::GetNormal, PATCH_JUMP); InjectHook(0x412140, &CColTrianglePlane::GetNormal, PATCH_JUMP);
InjectHook(0x411680, &CColModel::ctor, PATCH_JUMP); InjectHook(0x411680, &CColModel_::ctor, PATCH_JUMP);
InjectHook(0x4116E0, &CColModel::dtor, PATCH_JUMP); InjectHook(0x4116E0, &CColModel_::dtor, PATCH_JUMP);
InjectHook(0x411D80, &CColModel::RemoveCollisionVolumes, PATCH_JUMP); InjectHook(0x411D80, &CColModel::RemoveCollisionVolumes, PATCH_JUMP);
InjectHook(0x411CB0, &CColModel::CalculateTrianglePlanes, PATCH_JUMP); InjectHook(0x411CB0, &CColModel::CalculateTrianglePlanes, PATCH_JUMP);
InjectHook(0x411D10, &CColModel::RemoveTrianglePlanes, PATCH_JUMP); InjectHook(0x411D10, &CColModel::RemoveTrianglePlanes, PATCH_JUMP);

View File

@ -35,8 +35,6 @@ struct CColLine
CColLine(void) { }; CColLine(void) { };
CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; }; CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
void Set(const CVector &p0, const CVector &p1); void Set(const CVector &p0, const CVector &p1);
CColLine *ctor(CVector *p0, CVector *p1) { return ::new (this) CColLine(*p0, *p1); }
}; };
struct CColTriangle struct CColTriangle
@ -106,8 +104,6 @@ struct CColModel
void SetLinkPtr(CLink<CColModel*>*); void SetLinkPtr(CLink<CColModel*>*);
void GetTrianglePoint(CVector &v, int i) const; void GetTrianglePoint(CVector &v, int i) const;
CColModel *ctor(void) { return ::new (this) CColModel(); }
void dtor(void) { this->CColModel::~CColModel(); }
CColModel& operator=(const CColModel& other); CColModel& operator=(const CColModel& other);
}; };

View File

@ -417,6 +417,11 @@ void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonDown(int32 button, i
case 13: case 13:
pad->PCTempJoyState.DPadUp = 255; pad->PCTempJoyState.DPadUp = 255;
break; break;
#ifdef REGISTER_START_BUTTON
case 12:
pad->PCTempJoyState.Start = 255;
break;
#endif
case 11: case 11:
pad->PCTempJoyState.RightShock = 255; pad->PCTempJoyState.RightShock = 255;
break; break;
@ -839,6 +844,11 @@ void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonUp(int32 button, int
case 13: case 13:
pad->PCTempJoyState.DPadUp = 0; pad->PCTempJoyState.DPadUp = 0;
break; break;
#ifdef REGISTER_START_BUTTON
case 12:
pad->PCTempJoyState.Start = 0;
break;
#endif
case 11: case 11:
pad->PCTempJoyState.RightShock = 0; pad->PCTempJoyState.RightShock = 0;
break; break;

View File

@ -1,3 +1,4 @@
#define WITHWINDOWS // just for VK_SPACE
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "General.h" #include "General.h"

View File

@ -89,3 +89,49 @@ CDebug::DebugDisplayTextBuffer()
} }
#endif #endif
} }
// custom
CDebug::ScreenStr CDebug::ms_aScreenStrs[MAX_SCREEN_STRS];
int CDebug::ms_nScreenStrs;
void
CDebug::DisplayScreenStrings()
{
int i;
CFont::SetPropOn();
CFont::SetBackgroundOff();
CFont::SetScale(1.0f, 1.0f);
CFont::SetCentreOff();
CFont::SetRightJustifyOff();
CFont::SetJustifyOff();
CFont::SetRightJustifyWrap(0.0f);
CFont::SetWrapx(9999.0f);
CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_BANK);
for(i = 0; i < ms_nScreenStrs; i++){
AsciiToUnicode(ms_aScreenStrs[i].str, gUString);
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(ms_aScreenStrs[i].x, ms_aScreenStrs[i].y, gUString);
CFont::SetColor(CRGBA(255, 255, 255, 255));
CFont::PrintString(ms_aScreenStrs[i].x+1, ms_aScreenStrs[i].y+1, gUString);
}
CFont::DrawFonts();
ms_nScreenStrs = 0;
}
void
CDebug::PrintAt(const char *str, int x, int y)
{
if(ms_nScreenStrs >= MAX_SCREEN_STRS)
return;
strncpy(ms_aScreenStrs[ms_nScreenStrs].str, str, 256);
ms_aScreenStrs[ms_nScreenStrs].x = x*12;
ms_aScreenStrs[ms_nScreenStrs].y = y*22;
ms_nScreenStrs++;
}

View File

@ -6,15 +6,29 @@ class CDebug
{ {
MAX_LINES = 15, MAX_LINES = 15,
MAX_STR_LEN = 80, MAX_STR_LEN = 80,
MAX_SCREEN_STRS = 100,
}; };
static int16 ms_nCurrentTextLine; static int16 ms_nCurrentTextLine;
static char ms_aTextBuffer[MAX_LINES][MAX_STR_LEN]; static char ms_aTextBuffer[MAX_LINES][MAX_STR_LEN];
// custom
struct ScreenStr {
int x, y;
char str[256];
};
static ScreenStr ms_aScreenStrs[MAX_SCREEN_STRS];
static int ms_nScreenStrs;
public: public:
static void DebugInitTextBuffer(); static void DebugInitTextBuffer();
static void DebugDisplayTextBuffer(); static void DebugDisplayTextBuffer();
static void DebugAddText(const char *str); static void DebugAddText(const char *str);
// custom
static void PrintAt(const char *str, int x, int y);
static void DisplayScreenStrings();
}; };
extern bool gbDebugStuffInRelease; extern bool gbDebugStuffInRelease;

View File

@ -5,10 +5,13 @@
#include "World.h" #include "World.h"
#include "Wanted.h" #include "Wanted.h"
#include "EventList.h" #include "EventList.h"
#include "Messages.h"
#include "Text.h"
#include "main.h"
int32 CEventList::ms_nFirstFreeSlotIndex; int32 CEventList::ms_nFirstFreeSlotIndex;
//CEvent gaEvent[NUMEVENTS]; CEvent gaEvent[NUMEVENTS];
CEvent *gaEvent = (CEvent*)0x6EF830; //CEvent *gaEvent = (CEvent*)0x6EF830;
enum enum
{ {
@ -207,6 +210,18 @@ CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCar
default: crime = CRIME_NONE; break; default: crime = CRIME_NONE; break;
} }
#ifdef VC_PED_PORTS
if (crime == CRIME_HIT_PED && ((CPed*)crimeId)->IsPointerValid() &&
FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 && ((CPed*)crimeId)->m_ped_flagE2) {
if(!((CPed*)crimeId)->DyingOrDead()) {
sprintf(gString, "$50 Good Citizen Bonus!");
AsciiToUnicode(gString, gUString);
CMessages::AddBigMessage(gUString, 5000, 0);
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 50;
}
} else
#endif
if(crime == CRIME_NONE) if(crime == CRIME_NONE)
return; return;

View File

@ -63,4 +63,4 @@ public:
static void ReportCrimeForEvent(eEventType type, int32, bool); static void ReportCrimeForEvent(eEventType type, int32, bool);
}; };
extern CEvent *gaEvent; extern CEvent gaEvent[NUMEVENTS];

View File

@ -1,16 +1,286 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "Vector.h"
#include "PlayerPed.h"
#include "Entity.h"
#include "PointLights.h"
#include "Particle.h"
#include "Timer.h"
#include "Vehicle.h"
#include "Shadows.h"
#include "Automobile.h"
#include "World.h"
#include "General.h"
#include "EventList.h"
#include "DamageManager.h"
#include "Ped.h"
#include "Fire.h" #include "Fire.h"
CFireManager &gFireManager = *(CFireManager*)0x8F31D0; CFireManager &gFireManager = *(CFireManager*)0x8F31D0;
WRAPPER void CFire::Extinguish(void) { EAXJMP(0x479D40); } CFire::CFire()
WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); }
WRAPPER CFire* CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); }
uint32 CFireManager::GetTotalActiveFires() const
{ {
return m_nTotalFires; m_bIsOngoing = false;
m_bIsScriptFire = false;
m_bPropagationFlag = true;
m_bAudioSet = true;
m_vecPos = CVector(0.0f, 0.0f, 0.0f);
m_pEntity = nil;
m_pSource = nil;
m_nFiremenPuttingOut = 0;
m_nExtinguishTime = 0;
m_nStartTime = 0;
field_20 = 1;
m_nNextTimeToAddFlames = 0;
m_fStrength = 0.8f;
}
CFire::~CFire() {}
void
CFire::ProcessFire(void)
{
float fDamagePlayer;
float fDamagePeds;
float fDamageVehicle;
int8 nRandNumber;
float fGreen;
float fRed;
CVector lightpos;
CVector firePos;
CPed *ped = (CPed *)m_pEntity;
CVehicle *veh = (CVehicle*)m_pEntity;
if (m_pEntity) {
m_vecPos = m_pEntity->GetPosition();
if (((CPed *)m_pEntity)->IsPed()) {
if (ped->m_pFire != this) {
Extinguish();
return;
}
if (ped->m_nMoveState != PEDMOVE_RUN)
m_vecPos.z -= 1.0f;
if (ped->bInVehicle && ped->m_pMyVehicle) {
if (ped->m_pMyVehicle->IsCar())
ped->m_pMyVehicle->m_fHealth = 75.0f;
} else if (m_pEntity == (CPed *)FindPlayerPed()) {
fDamagePlayer = 1.2f * CTimer::GetTimeStep();
((CPlayerPed *)m_pEntity)->InflictDamage(
(CPlayerPed *)m_pSource, WEAPONTYPE_FLAMETHROWER,
fDamagePlayer, PEDPIECE_TORSO, 0);
} else {
fDamagePeds = 1.2f * CTimer::GetTimeStep();
if (((CPlayerPed *)m_pEntity)->InflictDamage(
(CPlayerPed *)m_pSource, WEAPONTYPE_FLAMETHROWER,
fDamagePeds, PEDPIECE_TORSO, 0)) {
m_pEntity->bRenderScorched = true;
}
}
} else if (m_pEntity->IsVehicle()) {
if (veh->m_pCarFire != this) {
Extinguish();
return;
}
if (!m_bIsScriptFire) {
fDamageVehicle = 1.2f * CTimer::GetTimeStep();
veh->InflictDamage((CVehicle *)m_pSource, WEAPONTYPE_FLAMETHROWER, fDamageVehicle);
}
}
}
if (!FindPlayerVehicle() && !FindPlayerPed()->m_pFire && !(FindPlayerPed()->bFireProof)
&& ((FindPlayerPed()->GetPosition() - m_vecPos).MagnitudeSqr() < 2.0f)) {
FindPlayerPed()->DoStuffToGoOnFire();
gFireManager.StartFire(FindPlayerPed(), m_pSource, 0.8f, 1);
}
if (CTimer::GetTimeInMilliseconds() > m_nNextTimeToAddFlames) {
m_nNextTimeToAddFlames = CTimer::GetTimeInMilliseconds() + 80;
firePos = m_vecPos;
if (veh && veh->IsVehicle() && veh->IsCar()) {
CVehicleModelInfo *mi = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(veh->GetModelIndex()));
CVector ModelInfo = mi->m_positions[CAR_POS_HEADLIGHTS];
ModelInfo = m_pEntity->GetMatrix() * ModelInfo;
firePos.x = ModelInfo.x;
firePos.y = ModelInfo.y;
firePos.z = ModelInfo.z + 0.15f;
}
CParticle::AddParticle(PARTICLE_CARFLAME, firePos,
CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.0125f, 0.1f) * m_fStrength),
0, m_fStrength, 0, 0, 0, 0);
rand(); rand(); rand(); /* unsure why these three rands are called */
CParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, firePos,
CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0);
}
if (CTimer::GetTimeInMilliseconds() < m_nExtinguishTime || m_bIsScriptFire) {
if (CTimer::GetTimeInMilliseconds() > m_nStartTime)
m_nStartTime = CTimer::GetTimeInMilliseconds() + 400;
nRandNumber = CGeneral::GetRandomNumber() & 127;
lightpos.x = m_vecPos.x;
lightpos.y = m_vecPos.y;
lightpos.z = m_vecPos.z + 5.0f;
if (!m_pEntity) {
CShadows::StoreStaticShadow((uint32)this, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &lightpos,
7.0f, 0.0f, 0.0f, -7.0f, 0, nRandNumber / 2, nRandNumber / 2,
0, 10.0f, 1.0f, 40.0f, 0, 0.0f);
}
fGreen = nRandNumber / 128;
fRed = nRandNumber / 128;
CPointLights::AddLight(0, m_vecPos, CVector(0.0f, 0.0f, 0.0f),
12.0f, fRed, fGreen, 0, 0, 0);
} else {
Extinguish();
}
}
void
CFire::ReportThisFire(void)
{
gFireManager.m_nTotalFires++;
CEventList::RegisterEvent(EVENT_FIRE, m_vecPos, 1000);
}
void
CFire::Extinguish(void)
{
if (m_bIsOngoing) {
if (!m_bIsScriptFire)
gFireManager.m_nTotalFires--;
m_nExtinguishTime = 0;
m_bIsOngoing = false;
if (m_pEntity) {
if (m_pEntity->IsPed()) {
((CPed *)m_pEntity)->RestorePreviousState();
((CPed *)m_pEntity)->m_pFire = nil;
} else if (m_pEntity->IsVehicle()) {
((CVehicle *)m_pEntity)->m_pCarFire = nil;
}
m_pEntity = nil;
}
}
}
void
CFireManager::StartFire(CVector pos, float size, bool propagation)
{
CFire *fire = GetNextFreeFire();
if (fire) {
fire->m_bIsOngoing = true;
fire->m_bIsScriptFire = false;
fire->m_bPropagationFlag = propagation;
fire->m_bAudioSet = true;
fire->m_vecPos = pos;
fire->m_nExtinguishTime = CTimer::GetTimeInMilliseconds() + 10000;
fire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400;
fire->m_pEntity = nil;
fire->m_pSource = nil;
fire->m_nNextTimeToAddFlames = 0;
fire->ReportThisFire();
fire->m_fStrength = size;
}
}
CFire *
CFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, bool propagation)
{
CPed *ped = (CPed *)entityOnFire;
CVehicle *veh = (CVehicle *)entityOnFire;
if (entityOnFire->IsPed()) {
if (ped->m_pFire)
return nil;
if (!ped->IsPedInControl())
return nil;
} else if (entityOnFire->IsVehicle()) {
if (veh->m_pCarFire)
return nil;
if (veh->IsCar() && ((CAutomobile *)veh)->Damage.GetEngineStatus() >= 225)
return nil;
}
CFire *fire = GetNextFreeFire();
if (fire) {
if (entityOnFire->IsPed()) {
ped->m_pFire = fire;
if (ped != FindPlayerPed()) {
if (fleeFrom) {
ped->SetFlee(fleeFrom, 10000);
} else {
CVector2D pos = entityOnFire->GetPosition();
ped->SetFlee(pos, 10000);
ped->m_fleeFrom = nil;
}
ped->bDrawLast = false;
ped->SetMoveState(PEDMOVE_SPRINT);
ped->SetMoveAnim();
ped->m_nPedState = PED_ON_FIRE;
}
if (fleeFrom) {
if (ped->m_nPedType == PEDTYPE_COP) {
CEventList::RegisterEvent(EVENT_COP_SET_ON_FIRE, EVENT_ENTITY_PED,
entityOnFire, (CPed *)fleeFrom, 10000);
} else {
CEventList::RegisterEvent(EVENT_PED_SET_ON_FIRE, EVENT_ENTITY_PED,
entityOnFire, (CPed *)fleeFrom, 10000);
}
}
} else {
if (entityOnFire->IsVehicle()) {
veh->m_pCarFire = fire;
if (fleeFrom) {
CEventList::RegisterEvent(EVENT_CAR_SET_ON_FIRE, EVENT_ENTITY_VEHICLE,
entityOnFire, (CPed *)fleeFrom, 10000);
}
}
}
fire->m_bIsOngoing = true;
fire->m_bIsScriptFire = false;
fire->m_vecPos = entityOnFire->GetPosition();
if (entityOnFire && entityOnFire->IsPed() && ped->IsPlayer()) {
fire->m_nExtinguishTime = CTimer::GetTimeInMilliseconds() + 3333;
} else if (entityOnFire->IsVehicle()) {
fire->m_nExtinguishTime = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(4000, 5000);
} else {
fire->m_nExtinguishTime = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 11000);
}
fire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400;
fire->m_pEntity = entityOnFire;
entityOnFire->RegisterReference(&fire->m_pEntity);
fire->m_pSource = fleeFrom;
if (fleeFrom)
fleeFrom->RegisterReference(&fire->m_pSource);
fire->ReportThisFire();
fire->m_nNextTimeToAddFlames = 0;
fire->m_fStrength = strength;
fire->m_bPropagationFlag = propagation;
fire->m_bAudioSet = true;
}
return fire;
}
void
CFireManager::Update(void)
{
for (int i = 0; i < NUM_FIRES; i++) {
if (m_aFires[i].m_bIsOngoing)
m_aFires[i].ProcessFire();
}
} }
CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance) CFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance)
@ -38,6 +308,44 @@ CFire* CFireManager::FindNearestFire(CVector vecPos, float* pDistance)
return nil; return nil;
} }
CFire *
CFireManager::FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange)
{
int furthestFire = -1;
float lastFireDist = 0.0f;
float fireDist;
for (int i = 0; i < NUM_FIRES; i++) {
if (m_aFires[i].m_bIsOngoing && !m_aFires[i].m_bIsScriptFire) {
fireDist = (m_aFires[i].m_vecPos - coords).Magnitude2D();
if (fireDist > minRange && fireDist < maxRange && fireDist > lastFireDist) {
lastFireDist = fireDist;
furthestFire = i;
}
}
}
if (furthestFire == -1)
return nil;
else
return &m_aFires[furthestFire];
}
CFire *
CFireManager::GetNextFreeFire(void)
{
for (int i = 0; i < NUM_FIRES; i++) {
if (!m_aFires[i].m_bIsOngoing && !m_aFires[i].m_bIsScriptFire)
return &m_aFires[i];
}
return nil;
}
uint32
CFireManager::GetTotalActiveFires(void) const
{
return m_nTotalFires;
}
void void
CFireManager::ExtinguishPoint(CVector point, float range) CFireManager::ExtinguishPoint(CVector point, float range)
{ {
@ -49,16 +357,100 @@ CFireManager::ExtinguishPoint(CVector point, float range)
} }
} }
WRAPPER void CFireManager::StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32) { EAXJMP(0x479590); } int32
WRAPPER void CFireManager::StartFire(CVector, float, uint8) { EAXJMP(0x479500); } CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation)
WRAPPER int32 CFireManager::StartScriptFire(const CVector& pos, CEntity* culprit, float, uint8) { EAXJMP(0x479E60); } {
WRAPPER bool CFireManager::IsScriptFireExtinguish(int16) { EAXJMP(0x479FC0); } CFire *fire;
WRAPPER void CFireManager::RemoveScriptFire(int16) { EAXJMP(0x479FE0); } CPed *ped = (CPed *)target;
WRAPPER void CFireManager::RemoveAllScriptFires(void) { EAXJMP(0x47A000); } CVehicle *veh = (CVehicle *)target;
WRAPPER void CFireManager::SetScriptFireAudio(int16, bool) { EAXJMP(0x47A040); }
if (target) {
if (target->IsPed()) {
if (ped->m_pFire)
ped->m_pFire->Extinguish();
} else if (target->IsVehicle()) {
if (veh->m_pCarFire)
veh->m_pCarFire->Extinguish();
if (veh->IsCar() && ((CAutomobile *)veh)->Damage.GetEngineStatus() >= 225) {
((CAutomobile *)veh)->Damage.SetEngineStatus(215);
}
}
}
fire = GetNextFreeFire();
fire->m_bIsOngoing = true;
fire->m_bIsScriptFire = true;
fire->m_bPropagationFlag = propagation;
fire->m_bAudioSet = true;
fire->m_vecPos = pos;
fire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400;
fire->m_pEntity = target;
if (target)
target->RegisterReference(&fire->m_pEntity);
fire->m_pSource = nil;
fire->m_nNextTimeToAddFlames = 0;
fire->m_fStrength = strength;
if (target) {
if (target->IsPed()) {
ped->m_pFire = fire;
if (target != (CVehicle *)FindPlayerPed()) {
CVector2D pos = target->GetPosition();
ped->SetFlee(pos, 10000);
ped->SetMoveAnim();
ped->m_nPedState = PED_ON_FIRE;
}
} else if (target->IsVehicle()) {
veh->m_pCarFire = fire;
}
}
return fire - m_aFires;
}
bool
CFireManager::IsScriptFireExtinguish(int16 index)
{
return !m_aFires[index].m_bIsOngoing;
}
void
CFireManager::RemoveAllScriptFires(void)
{
for (int i = 0; i < NUM_FIRES; i++) {
if (m_aFires[i].m_bIsScriptFire) {
m_aFires[i].Extinguish();
m_aFires[i].m_bIsScriptFire = false;
}
}
}
void
CFireManager::RemoveScriptFire(int16 index)
{
m_aFires[index].Extinguish();
m_aFires[index].m_bIsScriptFire = false;
}
void
CFireManager::SetScriptFireAudio(int16 index, bool state)
{
m_aFires[index].m_bAudioSet = state;
}
STARTPATCHES STARTPATCHES
InjectHook(0x479DB0, &CFireManager::ExtinguishPoint, PATCH_JUMP); InjectHook(0x4798D0, &CFire::ProcessFire, PATCH_JUMP);
InjectHook(0x4798B0, &CFire::ReportThisFire, PATCH_JUMP);
InjectHook(0x479D40, &CFire::Extinguish, PATCH_JUMP);
InjectHook(0x479500, (void(CFireManager::*)(CVector pos, float size, bool propagation))&CFireManager::StartFire, PATCH_JUMP);
InjectHook(0x479590, (CFire *(CFireManager::*)(CEntity *, CEntity *, float, bool))&CFireManager::StartFire, PATCH_JUMP);
InjectHook(0x479310, &CFireManager::Update, PATCH_JUMP);
InjectHook(0x479430, &CFireManager::FindFurthestFire_NeverMindFireMen, PATCH_JUMP);
InjectHook(0x479340, &CFireManager::FindNearestFire, PATCH_JUMP); InjectHook(0x479340, &CFireManager::FindNearestFire, PATCH_JUMP);
InjectHook(0x4792E0, &CFireManager::GetNextFreeFire, PATCH_JUMP);
InjectHook(0x479DB0, &CFireManager::ExtinguishPoint, PATCH_JUMP);
InjectHook(0x479E60, &CFireManager::StartScriptFire, PATCH_JUMP);
InjectHook(0x479FC0, &CFireManager::IsScriptFireExtinguish, PATCH_JUMP);
InjectHook(0x47A000, &CFireManager::RemoveAllScriptFires, PATCH_JUMP);
InjectHook(0x479FE0, &CFireManager::RemoveScriptFire, PATCH_JUMP);
InjectHook(0x47A040, &CFireManager::SetScriptFireAudio, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -7,18 +7,22 @@ class CFire
public: public:
bool m_bIsOngoing; bool m_bIsOngoing;
bool m_bIsScriptFire; bool m_bIsScriptFire;
bool m_bPropogationFlag; bool m_bPropagationFlag;
bool m_bAudioSet; bool m_bAudioSet;
CVector m_vecPos; CVector m_vecPos;
CEntity *m_pEntity; CEntity *m_pEntity;
CEntity *m_pSource; CEntity *m_pSource;
int m_nExtinguishTime; uint32 m_nExtinguishTime;
int m_nStartTime; uint32 m_nStartTime;
int field_20; int32 field_20;
int field_24; uint32 m_nNextTimeToAddFlames;
uint32 m_nFiremenPuttingOut; uint32 m_nFiremenPuttingOut;
float field_2C; float m_fStrength;
CFire();
~CFire();
void ProcessFire(void);
void ReportThisFire(void);
void Extinguish(void); void Extinguish(void);
}; };
@ -27,20 +31,21 @@ class CFireManager
enum { enum {
MAX_FIREMEN_ATTENDING = 2, MAX_FIREMEN_ATTENDING = 2,
}; };
uint32 m_nTotalFires;
public: public:
uint32 m_nTotalFires;
CFire m_aFires[NUM_FIRES]; CFire m_aFires[NUM_FIRES];
void StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32); void StartFire(CVector pos, float size, bool propagation);
void StartFire(CVector, float, uint8); CFire *StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, bool propagation);
void Update(void); void Update(void);
CFire *FindFurthestFire_NeverMindFireMen(CVector coors, float, float); CFire *FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange);
CFire *FindNearestFire(CVector, float*); CFire *FindNearestFire(CVector vecPos, float *pDistance);
CFire *GetNextFreeFire(void);
uint32 GetTotalActiveFires() const; uint32 GetTotalActiveFires() const;
void ExtinguishPoint(CVector, float); void ExtinguishPoint(CVector point, float range);
int32 StartScriptFire(const CVector& pos, CEntity* culprit, float, uint8); int32 StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation);
bool IsScriptFireExtinguish(int16); bool IsScriptFireExtinguish(int16 index);
void RemoveScriptFire(int16);
void RemoveAllScriptFires(void); void RemoveAllScriptFires(void);
void SetScriptFireAudio(int16, bool); void RemoveScriptFire(int16 index);
void SetScriptFireAudio(int16 index, bool state);
}; };
extern CFireManager &gFireManager; extern CFireManager &gFireManager;

View File

@ -181,6 +181,7 @@ ScaleAndCenterX(float x)
#endif #endif
#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS) #define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS)
#ifdef PS2_LIKE_MENU #ifdef PS2_LIKE_MENU
#define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \ #define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \
do { \ do { \
@ -235,67 +236,100 @@ ScaleAndCenterX(float x)
m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ m_nHoverOption = HOVEROPTION_NOT_HOVERING; \
} while(0) } while(0)
#define ScrollUpListByOne() \ // --- Functions not in the game/inlined starts
do { \
if (m_nSelectedListRow == m_nFirstVisibleRowOnList) { \
if (m_nFirstVisibleRowOnList > 0) { \
m_nSelectedListRow--; \
m_nFirstVisibleRowOnList--; \
m_nCurListItemY -= LIST_HEIGHT / m_nTotalListRow; \
} \
} else { \
m_nSelectedListRow--; \
} \
} while(0)
#define ScrollDownListByOne() \ inline void
do { \ CMenuManager::ScrollUpListByOne()
if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) { \ {
if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { \ if (m_nSelectedListRow == m_nFirstVisibleRowOnList) {
m_nSelectedListRow++; \ if (m_nFirstVisibleRowOnList > 0) {
m_nFirstVisibleRowOnList++; \ m_nSelectedListRow--;
m_nCurListItemY += LIST_HEIGHT / m_nTotalListRow; \ m_nFirstVisibleRowOnList--;
} \ m_nCurListItemY -= LIST_HEIGHT / m_nTotalListRow;
} else { \ }
if (m_nSelectedListRow < m_nTotalListRow - 1) { \ } else {
m_nSelectedListRow++; \ m_nSelectedListRow--;
} \ }
} \ }
} while(0)
#define PageUpList(playSoundOnSuccess) \ inline void
do { \ CMenuManager::ScrollDownListByOne()
if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { \ {
if (m_nFirstVisibleRowOnList > 0) { \ if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) {
if(playSoundOnSuccess) \ if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) {
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); \ m_nSelectedListRow++;
\ m_nFirstVisibleRowOnList++;
m_nFirstVisibleRowOnList = max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW); \ m_nCurListItemY += LIST_HEIGHT / m_nTotalListRow;
m_nSelectedListRow = min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1); \ }
} else { \ } else {
m_nFirstVisibleRowOnList = 0; \ if (m_nSelectedListRow < m_nTotalListRow - 1) {
m_nSelectedListRow = 0; \ m_nSelectedListRow++;
} \ }
m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; \ }
} \ }
} while(0)
#define PageDownList(playSoundOnSuccess) \ inline void
do { \ CMenuManager::PageUpList(bool playSoundOnSuccess)
if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { \ {
if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { \ if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) {
if(playSoundOnSuccess) \ if (m_nFirstVisibleRowOnList > 0) {
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); \ if(playSoundOnSuccess)
\ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0);
m_nFirstVisibleRowOnList = min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW); \
m_nSelectedListRow = max(m_nSelectedListRow, m_nFirstVisibleRowOnList); \ m_nFirstVisibleRowOnList = max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW);
} else { \ m_nSelectedListRow = min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1);
m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW; \ } else {
m_nSelectedListRow = m_nTotalListRow - 1; \ m_nFirstVisibleRowOnList = 0;
} \ m_nSelectedListRow = 0;
m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; \ }
} \ m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
} while(0) }
}
inline void
CMenuManager::PageDownList(bool playSoundOnSuccess)
{
if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) {
if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) {
if(playSoundOnSuccess)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0);
m_nFirstVisibleRowOnList = min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW);
m_nSelectedListRow = max(m_nSelectedListRow, m_nFirstVisibleRowOnList);
} else {
m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW;
m_nSelectedListRow = m_nTotalListRow - 1;
}
m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
}
}
inline void
CMenuManager::ThingsToDoBeforeLeavingPage()
{
if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) {
CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);
} else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) {
if (m_nPrefsAudio3DProviderIndex != -1)
m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex();
#ifdef TIDY_UP_PBP
DMAudio.StopFrontEndTrack();
OutputDebugString("FRONTEND AUDIO TRACK STOPPED");
#endif
} else if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) {
m_nDisplayVideoMode = m_nPrefsVideoMode;
}
if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {
CPlayerSkin::EndFrontendSkinEdit();
}
if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) || (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS)) {
m_nTotalListRow = 0;
}
}
// ------ Functions not in the game/inlined ends
void void
CMenuManager::BuildStatLine(char *text, void *stat, uint8 aFloat, void *stat2) CMenuManager::BuildStatLine(char *text, void *stat, uint8 aFloat, void *stat2)
@ -1173,7 +1207,6 @@ void CMenuManager::DrawFrontEnd()
bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT }; bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT };
bbTabCount = 6; bbTabCount = 6;
} }
m_nCurrScreen = MENUPAGE_NEW_GAME;
} else { } else {
if (bbTabCount != 8) { if (bbTabCount != 8) {
bbNames[0] = { "FEB_STA",MENUPAGE_STATS }; bbNames[0] = { "FEB_STA",MENUPAGE_STATS };
@ -1186,8 +1219,8 @@ void CMenuManager::DrawFrontEnd()
bbNames[7] = { "FESZ_QU",MENUPAGE_EXIT }; bbNames[7] = { "FESZ_QU",MENUPAGE_EXIT };
bbTabCount = 8; bbTabCount = 8;
} }
m_nCurrScreen = MENUPAGE_STATS;
} }
m_nCurrScreen = bbNames[0].screenId;
bottomBarActive = true; bottomBarActive = true;
curBottomBarOption = 0; curBottomBarOption = 0;
} }
@ -1285,7 +1318,6 @@ void CMenuManager::DrawFrontEndNormal()
eFrontendSprites currentSprite; eFrontendSprites currentSprite;
switch (m_nCurrScreen) { switch (m_nCurrScreen) {
case MENUPAGE_STATS: case MENUPAGE_STATS:
case MENUPAGE_NEW_GAME:
case MENUPAGE_START_MENU: case MENUPAGE_START_MENU:
case MENUPAGE_PAUSE_MENU: case MENUPAGE_PAUSE_MENU:
case MENUPAGE_EXIT: case MENUPAGE_EXIT:
@ -1315,7 +1347,7 @@ void CMenuManager::DrawFrontEndNormal()
currentSprite = FE_ICONCONTROLS; currentSprite = FE_ICONCONTROLS;
break; break;
default: default:
/* actually MENUPAGE_NEW_GAME too*/ /*case MENUPAGE_NEW_GAME: */
/*case MENUPAGE_BRIEFS: */ /*case MENUPAGE_BRIEFS: */
currentSprite = FE_ICONBRIEF; currentSprite = FE_ICONBRIEF;
break; break;
@ -1324,16 +1356,16 @@ void CMenuManager::DrawFrontEndNormal()
m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha)); m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha));
if (m_nMenuFadeAlpha < 255) { if (m_nMenuFadeAlpha < 255) {
static int LastFade = 0; static uint32 LastFade = 0;
if (m_nMenuFadeAlpha <= 0 && reverseAlpha) { if (m_nMenuFadeAlpha <= 0 && reverseAlpha) {
reverseAlpha = false; reverseAlpha = false;
ChangeScreen(pendingScreen, pendingOption, true, false); ChangeScreen(pendingScreen, pendingOption, true, false);
} else if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ } else {
if (!reverseAlpha) if (!reverseAlpha)
m_nMenuFadeAlpha += 20; m_nMenuFadeAlpha += min((CTimer::GetTimeInMillisecondsPauseMode() - LastFade) / 33.0f, 1.0f) * 20.0f;
else else
m_nMenuFadeAlpha = max(m_nMenuFadeAlpha - 30, 0); m_nMenuFadeAlpha = max(0, m_nMenuFadeAlpha - min((CTimer::GetTimeInMillisecondsPauseMode() - LastFade) / 33.0f, 1.0f) * 30.0f);
LastFade = CTimer::GetTimeInMillisecondsPauseMode(); LastFade = CTimer::GetTimeInMillisecondsPauseMode();
} }
@ -1537,12 +1569,18 @@ void CMenuManager::DrawFrontEndNormal()
} }
if (m_nMenuFadeAlpha < 255) { if (m_nMenuFadeAlpha < 255) {
static int LastFade = 0; static uint32 LastFade = 0;
// Famous transparent menu bug. 33.0f = 1000.f/30.f (original frame limiter fps)
#ifdef FIX_BUGS
m_nMenuFadeAlpha += min((CTimer::GetTimeInMillisecondsPauseMode() - LastFade) / 33.0f, 1.0f) * 20.0f;
LastFade = CTimer::GetTimeInMillisecondsPauseMode();
#else
if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){ if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){
m_nMenuFadeAlpha += 20; m_nMenuFadeAlpha += 20;
LastFade = CTimer::GetTimeInMillisecondsPauseMode(); LastFade = CTimer::GetTimeInMillisecondsPauseMode();
} }
#endif
if (m_nMenuFadeAlpha > 255){ if (m_nMenuFadeAlpha > 255){
m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); m_aMenuSprites[currentSprite].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
@ -1950,7 +1988,7 @@ WRAPPER void CMenuManager::Process(void) { EAXJMP(0x485100); }
#else #else
void CMenuManager::Process(void) void CMenuManager::Process(void)
{ {
m_bMenuNotProcessed = false; m_bMenuStateChanged = false;
if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0) if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0)
return; return;
@ -2701,6 +2739,8 @@ CMenuManager::ProcessButtonPresses(void)
if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) { if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0);
bottomBarActive = false; bottomBarActive = false;
// If there's a menu change with fade ongoing, finish it now
if (reverseAlpha) if (reverseAlpha)
m_nMenuFadeAlpha = 0; m_nMenuFadeAlpha = 0;
return; return;
@ -3116,51 +3156,43 @@ CMenuManager::ProcessButtonPresses(void)
if (goBack) { if (goBack) {
CMenuManager::ResetHelperText(); CMenuManager::ResetHelperText();
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_EXIT, 0); DMAudio.PlayFrontEndSound(SOUND_FRONTEND_EXIT, 0);
if (m_nCurrScreen == MENUPAGE_PAUSE_MENU && !m_bGameNotLoaded && !m_bMenuNotProcessed){ #ifdef PS2_LIKE_MENU
if (m_nCurrScreen == MENUPAGE_PAUSE_MENU || bottomBarActive) {
#else
if (m_nCurrScreen == MENUPAGE_PAUSE_MENU) {
#endif
if (!m_bGameNotLoaded && !m_bMenuStateChanged) {
if (CMenuManager::m_PrefsVsyncDisp != CMenuManager::m_PrefsVsync) { if (CMenuManager::m_PrefsVsyncDisp != CMenuManager::m_PrefsVsync) {
CMenuManager::m_PrefsVsync = CMenuManager::m_PrefsVsyncDisp; CMenuManager::m_PrefsVsync = CMenuManager::m_PrefsVsyncDisp;
} }
CMenuManager::RequestFrontEndShutDown(); CMenuManager::RequestFrontEndShutDown();
} else if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT }
#ifdef PS2_SAVE_DIALOG
|| m_nCurrScreen == MENUPAGE_SAVE // We're already resuming, we don't need further processing.
#if defined(FIX_BUGS) || defined(PS2_LIKE_MENU)
return;
#endif
}
#ifdef PS2_LIKE_MENU
else if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT || m_nCurrScreen == MENUPAGE_SAVE) {
#else
else if (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT) {
#endif #endif
) {
CMenuManager::RequestFrontEndShutDown(); CMenuManager::RequestFrontEndShutDown();
} else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) { }
// It's now in ThingsToDoBeforeLeavingPage()
#ifndef TIDY_UP_PBP
else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) {
DMAudio.StopFrontEndTrack(); DMAudio.StopFrontEndTrack();
OutputDebugString("FRONTEND AUDIO TRACK STOPPED"); OutputDebugString("FRONTEND AUDIO TRACK STOPPED");
} }
#endif
int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0]; int oldScreen = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage[1] : aScreens[m_nCurrScreen].m_PreviousPage[0];
int oldOption = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0]; int oldOption = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0];
#ifdef PS2_LIKE_MENU
if (bottomBarActive){
bottomBarActive = false;
if (!m_bGameNotLoaded) {
if (CMenuManager::m_PrefsVsyncDisp != CMenuManager::m_PrefsVsync) {
CMenuManager::m_PrefsVsync = CMenuManager::m_PrefsVsyncDisp;
}
CMenuManager::RequestFrontEndShutDown();
}
return;
}
#endif
if (oldScreen != -1) { if (oldScreen != -1) {
if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) { ThingsToDoBeforeLeavingPage();
CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);
}
if ((m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) && (m_nPrefsAudio3DProviderIndex != -1)) {
m_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex();
}
if (m_nCurrScreen == MENUPAGE_GRAPHICS_SETTINGS) {
m_nDisplayVideoMode = m_nPrefsVideoMode;
}
if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {
CPlayerSkin::EndFrontendSkinEdit();
}
#ifdef PS2_LIKE_MENU #ifdef PS2_LIKE_MENU
if (!bottomBarActive && if (!bottomBarActive &&
@ -3168,10 +3200,8 @@ CMenuManager::ProcessButtonPresses(void)
bottomBarActive = true; bottomBarActive = true;
} else } else
#endif #endif
{
ChangeScreen(oldScreen, oldOption, true, true); ChangeScreen(oldScreen, oldOption, true, true);
if ((m_nPrevScreen == MENUPAGE_SKIN_SELECT) || (m_nPrevScreen == MENUPAGE_KEYBOARD_CONTROLS)) {
m_nTotalListRow = 0;
} }
// We will go back for sure at this point, why process other things?! // We will go back for sure at this point, why process other things?!
@ -3512,11 +3542,16 @@ WRAPPER void CMenuManager::SwitchMenuOnAndOff() { EAXJMP(0x488790); }
#else #else
void CMenuManager::SwitchMenuOnAndOff() void CMenuManager::SwitchMenuOnAndOff()
{ {
if (!!(CPad::GetPad(0)->NewState.Start && !CPad::GetPad(0)->OldState.Start) bool menuWasActive = !!m_bMenuActive;
// Reminder: You need REGISTER_START_BUTTON defined to make it work.
if (CPad::GetPad(0)->GetStartJustDown()
#ifdef FIX_BUGS
&& !m_bGameNotLoaded
#endif
|| m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested) { || m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested) {
if (!m_bMenuActive) m_bMenuActive = !m_bMenuActive;
m_bMenuActive = true;
if (m_bShutDownFrontEndRequested) if (m_bShutDownFrontEndRequested)
m_bMenuActive = false; m_bMenuActive = false;
@ -3525,8 +3560,13 @@ void CMenuManager::SwitchMenuOnAndOff()
if (m_bMenuActive) { if (m_bMenuActive) {
CTimer::StartUserPause(); CTimer::StartUserPause();
} } else {
else { #ifdef PS2_LIKE_MENU
bottomBarActive = false;
#endif
#ifdef FIX_BUGS
ThingsToDoBeforeLeavingPage();
#endif
ShutdownJustMenu(); ShutdownJustMenu();
SaveSettings(); SaveSettings();
m_bStartUpFrontEndRequested = false; m_bStartUpFrontEndRequested = false;
@ -3553,7 +3593,7 @@ void CMenuManager::SwitchMenuOnAndOff()
PcSaveHelper.PopulateSlotInfo(); PcSaveHelper.PopulateSlotInfo();
m_nCurrOption = 0; m_nCurrOption = 0;
} }
/* // Unused? /* // PS2 leftover?
if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying) if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying)
{ {
DMAudio.StopFrontEndTrack(); DMAudio.StopFrontEndTrack();
@ -3561,8 +3601,8 @@ void CMenuManager::SwitchMenuOnAndOff()
gMusicPlaying = 0; gMusicPlaying = 0;
} }
*/ */
if (!m_bMenuActive) if (m_bMenuActive != menuWasActive)
m_bMenuNotProcessed = true; m_bMenuStateChanged = true;
m_bStartUpFrontEndRequested = false; m_bStartUpFrontEndRequested = false;
m_bShutDownFrontEndRequested = false; m_bShutDownFrontEndRequested = false;

View File

@ -403,7 +403,7 @@ public:
int32 m_nHelperTextMsgId; int32 m_nHelperTextMsgId;
bool m_bLanguageLoaded; bool m_bLanguageLoaded;
bool m_bMenuActive; bool m_bMenuActive;
bool m_bMenuNotProcessed; bool m_bMenuStateChanged;
bool m_bWaitingForNewKeyBind; bool m_bWaitingForNewKeyBind;
bool m_bStartGameLoading; bool m_bStartGameLoading;
bool m_bFirstTime; bool m_bFirstTime;
@ -540,8 +540,14 @@ public:
void WaitForUserCD(); void WaitForUserCD();
void PrintController(); void PrintController();
// New content: // New (not in function or inlined in the game)
uint8 GetNumberOfMenuOptions(); void ThingsToDoBeforeLeavingPage();
void ScrollUpListByOne();
void ScrollDownListByOne();
void PageUpList(bool);
void PageDownList(bool);
// uint8 GetNumberOfMenuOptions();
}; };
static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error"); static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error");

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <ctype.h>
class CGeneral class CGeneral
{ {
public: public:

View File

@ -5,6 +5,10 @@
#pragma warning( pop ) #pragma warning( pop )
#include "common.h" #include "common.h"
#ifdef XINPUT
#include <Xinput.h>
#pragma comment( lib, "Xinput9_1_0.lib" )
#endif
#include "patcher.h" #include "patcher.h"
#include "Pad.h" #include "Pad.h"
#include "ControllerConfig.h" #include "ControllerConfig.h"
@ -547,12 +551,78 @@ void CPad::AddToPCCheatString(char c)
#undef _CHEATCMP #undef _CHEATCMP
} }
#ifdef XINPUT
void CPad::AffectFromXinput(uint32 pad)
{
XINPUT_STATE xstate;
memset(&xstate, 0, sizeof(XINPUT_STATE));
if (XInputGetState(pad, &xstate) == ERROR_SUCCESS)
{
PCTempJoyState.Circle = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_B) ? 255 : 0;
PCTempJoyState.Cross = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_A) ? 255 : 0;
PCTempJoyState.Square = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_X) ? 255 : 0;
PCTempJoyState.Triangle = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_Y) ? 255 : 0;
PCTempJoyState.DPadDown = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? 255 : 0;
PCTempJoyState.DPadLeft = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) ? 255 : 0;
PCTempJoyState.DPadRight = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) ? 255 : 0;
PCTempJoyState.DPadUp = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) ? 255 : 0;
PCTempJoyState.LeftShock = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? 255 : 0;
PCTempJoyState.LeftShoulder1 = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? 255 : 0;
PCTempJoyState.LeftShoulder2 = xstate.Gamepad.bLeftTrigger;
PCTempJoyState.RightShock = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? 255 : 0;
PCTempJoyState.RightShoulder1 = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? 255 : 0;
PCTempJoyState.RightShoulder2 = xstate.Gamepad.bRightTrigger;
PCTempJoyState.Select = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? 255 : 0;
PCTempJoyState.Start = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_START) ? 255 : 0;
float lx = (float)xstate.Gamepad.sThumbLX / (float)0x7FFF;
float ly = (float)xstate.Gamepad.sThumbLY / (float)0x7FFF;
float rx = (float)xstate.Gamepad.sThumbRX / (float)0x7FFF;
float ry = (float)xstate.Gamepad.sThumbRY / (float)0x7FFF;
if (Abs(lx) > 0.3f || Abs(ly) > 0.3f) {
PCTempJoyState.LeftStickX = (int32)(lx * 128.0f);
PCTempJoyState.LeftStickY = (int32)(-ly * 128.0f);
}
if (Abs(rx) > 0.3f || Abs(ry) > 0.3f) {
PCTempJoyState.RightStickX = (int32)(rx * 128.0f);
PCTempJoyState.RightStickY = (int32)(ry * 128.0f);
}
XINPUT_VIBRATION VibrationState;
memset(&VibrationState, 0, sizeof(XINPUT_VIBRATION));
uint16 iLeftMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff);
uint16 iRightMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff);
if (ShakeDur < CTimer::GetTimeStepInMilliseconds())
ShakeDur = 0;
else
ShakeDur -= CTimer::GetTimeStepInMilliseconds();
if (ShakeDur == 0) ShakeFreq = 0;
VibrationState.wLeftMotorSpeed = iLeftMotor;
VibrationState.wRightMotorSpeed = iRightMotor;
XInputSetState(pad, &VibrationState);
}
}
#endif
void CPad::UpdatePads(void) void CPad::UpdatePads(void)
{ {
bool bUpdate = true; bool bUpdate = true;
GetPad(0)->UpdateMouse(); GetPad(0)->UpdateMouse();
#ifdef XINPUT
GetPad(0)->AffectFromXinput(0);
GetPad(1)->AffectFromXinput(1);
#else
CapturePad(0); CapturePad(0);
#endif
ControlsManager.ClearSimButtonPressCheckers(); ControlsManager.ClearSimButtonPressCheckers();
@ -565,10 +635,13 @@ void CPad::UpdatePads(void)
if ( bUpdate ) if ( bUpdate )
{ {
GetPad(0)->Update(0); GetPad(0)->Update(0);
GetPad(1)->Update(0);
} }
#if defined(MASTER) && !defined(XINPUT)
GetPad(1)->NewState.Clear(); GetPad(1)->NewState.Clear();
GetPad(1)->OldState.Clear(); GetPad(1)->OldState.Clear();
#endif
OldKeyState = NewKeyState; OldKeyState = NewKeyState;
NewKeyState = TempKeyState; NewKeyState = TempKeyState;

View File

@ -247,6 +247,10 @@ public:
static char *EditString(char *pStr, int32 nSize); static char *EditString(char *pStr, int32 nSize);
static int32 *EditCodesForControls(int32 *pRsKeys, int32 nSize); static int32 *EditCodesForControls(int32 *pRsKeys, int32 nSize);
#ifdef XINPUT
void AffectFromXinput(uint32 pad);
#endif
// mouse // mouse
bool GetLeftMouseJustDown() { return !!(NewMouseControllerState.LMB && !OldMouseControllerState.LMB); } bool GetLeftMouseJustDown() { return !!(NewMouseControllerState.LMB && !OldMouseControllerState.LMB); }
bool GetRightMouseJustDown() { return !!(NewMouseControllerState.RMB && !OldMouseControllerState.RMB); } bool GetRightMouseJustDown() { return !!(NewMouseControllerState.RMB && !OldMouseControllerState.RMB); }
@ -399,6 +403,8 @@ public:
bool GetLeftShoulder2JustDown() { return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); } bool GetLeftShoulder2JustDown() { return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); }
bool GetRightShoulder1JustDown() { return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); } bool GetRightShoulder1JustDown() { return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); }
bool GetRightShoulder2JustDown() { return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); } bool GetRightShoulder2JustDown() { return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); }
bool GetLeftShockJustDown() { return !!(NewState.LeftShock && !OldState.LeftShock); }
bool GetRightShockJustDown() { return !!(NewState.RightShock && !OldState.RightShock); }
bool GetStartJustDown() { return !!(NewState.Start && !OldState.Start); } bool GetStartJustDown() { return !!(NewState.Start && !OldState.Start); }
bool GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); } bool GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); }
bool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); } bool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); }
@ -422,6 +428,10 @@ public:
bool GetLeftShoulder2(void) { return !!NewState.LeftShoulder2; } bool GetLeftShoulder2(void) { return !!NewState.LeftShoulder2; }
bool GetRightShoulder1(void) { return !!NewState.RightShoulder1; } bool GetRightShoulder1(void) { return !!NewState.RightShoulder1; }
bool GetRightShoulder2(void) { return !!NewState.RightShoulder2; } bool GetRightShoulder2(void) { return !!NewState.RightShoulder2; }
int16 GetLeftStickX(void) { return NewState.LeftStickX; }
int16 GetLeftStickY(void) { return NewState.LeftStickY; }
int16 GetRightStickX(void) { return NewState.RightStickX; }
int16 GetRightStickY(void) { return NewState.RightStickY; }
bool ArePlayerControlsDisabled(void) { return DisablePlayerControls != PLAYERCONTROL_ENABLED; } bool ArePlayerControlsDisabled(void) { return DisablePlayerControls != PLAYERCONTROL_ENABLED; }
void SetDisablePlayerControls(uint8 who) { DisablePlayerControls |= who; } void SetDisablePlayerControls(uint8 who) { DisablePlayerControls |= who; }

View File

@ -63,6 +63,8 @@ CPlaceable::IsWithinArea(float x1, float y1, float z1, float x2, float y2, float
z1 <= GetPosition().z && GetPosition().z <= z2; z1 <= GetPosition().z && GetPosition().z <= z2;
} }
#include <new>
class CPlaceable_ : public CPlaceable class CPlaceable_ : public CPlaceable
{ {
public: public:

View File

@ -198,7 +198,7 @@ CStreaming::Init(void)
// PC only, figure out how much memory we got // PC only, figure out how much memory we got
#ifdef GTA_PC #ifdef GTA_PC
#define MB (1024*1024) #define MB (1024*1024)
extern DWORD &_dwMemAvailPhys; extern unsigned long &_dwMemAvailPhys;
ms_memoryAvailable = (_dwMemAvailPhys - 10*MB)/2; ms_memoryAvailable = (_dwMemAvailPhys - 10*MB)/2;
if(ms_memoryAvailable < 50*MB) if(ms_memoryAvailable < 50*MB)
ms_memoryAvailable = 50*MB; ms_memoryAvailable = 50*MB;

View File

@ -2,7 +2,7 @@
class CTimer class CTimer
{ {
public:
static uint32 &m_snTimeInMilliseconds; static uint32 &m_snTimeInMilliseconds;
static uint32 &m_snTimeInMillisecondsPauseMode; static uint32 &m_snTimeInMillisecondsPauseMode;
static uint32 &m_snTimeInMillisecondsNonClipped; static uint32 &m_snTimeInMillisecondsNonClipped;
@ -11,19 +11,20 @@ public:
static float &ms_fTimeScale; static float &ms_fTimeScale;
static float &ms_fTimeStep; static float &ms_fTimeStep;
static float &ms_fTimeStepNonClipped; static float &ms_fTimeStepNonClipped;
public:
static bool &m_UserPause; static bool &m_UserPause;
static bool &m_CodePause; static bool &m_CodePause;
static float GetTimeStep(void) { return ms_fTimeStep; } static const float &GetTimeStep(void) { return ms_fTimeStep; }
static void SetTimeStep(float ts) { ms_fTimeStep = ts; } static void SetTimeStep(float ts) { ms_fTimeStep = ts; }
static float GetTimeStepInSeconds() { return ms_fTimeStep / 50.0f; } static float GetTimeStepInSeconds() { return ms_fTimeStep / 50.0f; }
static float GetTimeStepInMilliseconds() { return ms_fTimeStep / 50.0f * 1000.0f; } static float GetTimeStepInMilliseconds() { return ms_fTimeStep / 50.0f * 1000.0f; }
static float GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; } static const float &GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; }
static float GetTimeStepNonClippedInSeconds(void) { return ms_fTimeStepNonClipped / 50.0f; } static float GetTimeStepNonClippedInSeconds(void) { return ms_fTimeStepNonClipped / 50.0f; }
static void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; } static void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; }
static uint32 GetFrameCounter(void) { return m_FrameCounter; } static const uint32 &GetFrameCounter(void) { return m_FrameCounter; }
static void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; } static void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; }
static uint32 GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; } static const uint32 &GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; }
static void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; } static void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; }
static uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; } static uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; }
static void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; } static void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; }
@ -31,7 +32,7 @@ public:
static void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; } static void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; }
static uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; } static uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; }
static void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; } static void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; }
static float GetTimeScale(void) { return ms_fTimeScale; } static const float &GetTimeScale(void) { return ms_fTimeScale; }
static void SetTimeScale(float ts) { ms_fTimeScale = ts; } static void SetTimeScale(float ts) { ms_fTimeScale = ts; }
static bool GetIsPaused() { return m_UserPause || m_CodePause; } static bool GetIsPaused() { return m_UserPause || m_CodePause; }

View File

@ -20,11 +20,12 @@
#include "Replay.h" #include "Replay.h"
#include "Population.h" #include "Population.h"
CColPoint *gaTempSphereColPoints = (CColPoint*)0x6E64C0; // [32]
CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60; CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60;
CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C; CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C;
CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x665608; CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x665608;
uint16 &CWorld::ms_nCurrentScanCode = *(uint16*)0x95CC64; uint16 &CWorld::ms_nCurrentScanCode = *(uint16*)0x95CC64;
CColPoint &CWorld::ms_testSpherePoint = *(CColPoint*)0x6E64C0;
uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61; uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61;
CPlayerInfo (&CWorld::Players)[NUMPLAYERS] = *(CPlayerInfo (*)[NUMPLAYERS])*(uintptr*)0x9412F0; CPlayerInfo (&CWorld::Players)[NUMPLAYERS] = *(CPlayerInfo (*)[NUMPLAYERS])*(uintptr*)0x9412F0;
@ -610,9 +611,9 @@ CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bo
} }
void void
CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float distance, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects) CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float radius, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects)
{ {
float distSqr = distance * distance; float radiusSqr = radius * radius;
float objDistSqr; float objDistSqr;
for (CPtrNode *node = list.first; node; node = node->next) { for (CPtrNode *node = list.first; node; node = node->next) {
@ -626,7 +627,7 @@ CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float dist
else else
objDistSqr = diff.MagnitudeSqr(); objDistSqr = diff.MagnitudeSqr();
if (objDistSqr < distSqr && *nextObject < lastObject) { if (objDistSqr < radiusSqr && *nextObject < lastObject) {
if (objects) { if (objects) {
objects[*nextObject] = object; objects[*nextObject] = object;
} }
@ -637,22 +638,22 @@ CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float dist
} }
void void
CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies) CWorld::FindObjectsInRange(CVector &centre, float radius, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies)
{ {
int minX = GetSectorIndexX(centre.x - distance); int minX = GetSectorIndexX(centre.x - radius);
if (minX <= 0) minX = 0; if (minX <= 0) minX = 0;
int minY = GetSectorIndexY(centre.y - distance); int minY = GetSectorIndexY(centre.y - radius);
if (minY <= 0) minY = 0; if (minY <= 0) minY = 0;
int maxX = GetSectorIndexX(centre.x + distance); int maxX = GetSectorIndexX(centre.x + radius);
#ifdef FIX_BUGS #ifdef FIX_BUGS
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else #else
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
#endif #endif
int maxY = GetSectorIndexY(centre.y + distance); int maxY = GetSectorIndexY(centre.y + radius);
#ifdef FIX_BUGS #ifdef FIX_BUGS
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else #else
@ -666,48 +667,48 @@ CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short
for(int curX = minX; curX <= maxX; curX++) { for(int curX = minX; curX <= maxX; curX++) {
CSector *sector = GetSector(curX, curY); CSector *sector = GetSector(curX, curY);
if (checkBuildings) { if (checkBuildings) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, radius, ignoreZ, nextObject, lastObject, objects);
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
} }
if (checkVehicles) { if (checkVehicles) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, radius, ignoreZ, nextObject, lastObject, objects);
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
} }
if (checkPeds) { if (checkPeds) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius, ignoreZ, nextObject, lastObject, objects);
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
} }
if (checkObjects) { if (checkObjects) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, radius, ignoreZ, nextObject, lastObject, objects);
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
} }
if (checkDummies) { if (checkDummies) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, radius, ignoreZ, nextObject, lastObject, objects);
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects); FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects);
} }
} }
} }
} }
CEntity* CEntity*
CWorld::TestSphereAgainstWorld(CVector centre, float distance, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects) CWorld::TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects)
{ {
CEntity* foundE = nil; CEntity* foundE = nil;
int minX = GetSectorIndexX(centre.x - distance); int minX = GetSectorIndexX(centre.x - radius);
if (minX <= 0) minX = 0; if (minX <= 0) minX = 0;
int minY = GetSectorIndexY(centre.y - distance); int minY = GetSectorIndexY(centre.y - radius);
if (minY <= 0) minY = 0; if (minY <= 0) minY = 0;
int maxX = GetSectorIndexX(centre.x + distance); int maxX = GetSectorIndexX(centre.x + radius);
#ifdef FIX_BUGS #ifdef FIX_BUGS
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else #else
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
#endif #endif
int maxY = GetSectorIndexY(centre.y + distance); int maxY = GetSectorIndexY(centre.y + radius);
#ifdef FIX_BUGS #ifdef FIX_BUGS
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else #else
@ -720,47 +721,47 @@ CWorld::TestSphereAgainstWorld(CVector centre, float distance, CEntity *entityTo
for (int curX = minX; curX <= maxX; curX++) { for (int curX = minX; curX <= maxX; curX++) {
CSector* sector = GetSector(curX, curY); CSector* sector = GetSector(curX, curY);
if (checkBuildings) { if (checkBuildings) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, distance, entityToIgnore, false); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, radius, entityToIgnore, false);
if (foundE) if (foundE)
return foundE; return foundE;
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, distance, entityToIgnore, false); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, radius, entityToIgnore, false);
if (foundE) if (foundE)
return foundE; return foundE;
} }
if (checkVehicles) { if (checkVehicles) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, distance, entityToIgnore, false); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, radius, entityToIgnore, false);
if (foundE) if (foundE)
return foundE; return foundE;
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, distance, entityToIgnore, false); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, radius, entityToIgnore, false);
if (foundE) if (foundE)
return foundE; return foundE;
} }
if (checkPeds) { if (checkPeds) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, distance, entityToIgnore, false); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius, entityToIgnore, false);
if (foundE) if (foundE)
return foundE; return foundE;
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, distance, entityToIgnore, false); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, radius, entityToIgnore, false);
if (foundE) if (foundE)
return foundE; return foundE;
} }
if (checkObjects) { if (checkObjects) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, distance, entityToIgnore, ignoreSomeObjects); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, radius, entityToIgnore, ignoreSomeObjects);
if (foundE) if (foundE)
return foundE; return foundE;
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, distance, entityToIgnore, ignoreSomeObjects); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, radius, entityToIgnore, ignoreSomeObjects);
if (foundE) if (foundE)
return foundE; return foundE;
} }
if (checkDummies) { if (checkDummies) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, distance, entityToIgnore, false); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, radius, entityToIgnore, false);
if (foundE) if (foundE)
return foundE; return foundE;
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, distance, entityToIgnore, false); foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, radius, entityToIgnore, false);
if (foundE) if (foundE)
return foundE; return foundE;
} }
@ -807,7 +808,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad
if (e->GetBoundRadius() + radius > distance) { if (e->GetBoundRadius() + radius > distance) {
CColModel *eCol = CModelInfo::GetModelInfo(e->m_modelIndex)->GetColModel(); CColModel *eCol = CModelInfo::GetModelInfo(e->m_modelIndex)->GetColModel();
int collidedSpheres = CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(), int collidedSpheres = CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(),
*eCol, &ms_testSpherePoint, nil, nil); *eCol, gaTempSphereColPoints, nil, nil);
if (collidedSpheres != 0 || if (collidedSpheres != 0 ||
(e->IsVehicle() && ((CVehicle*)e)->m_vehType == VEHICLE_TYPE_CAR && (e->IsVehicle() && ((CVehicle*)e)->m_vehType == VEHICLE_TYPE_CAR &&

View File

@ -60,8 +60,6 @@ class CWorld
static uint16 &ms_nCurrentScanCode; static uint16 &ms_nCurrentScanCode;
public: public:
static CColPoint& ms_testSpherePoint;
static uint8 &PlayerInFocus; static uint8 &PlayerInFocus;
static CPlayerInfo (&Players)[NUMPLAYERS]; static CPlayerInfo (&Players)[NUMPLAYERS];
static CEntity *&pIgnoreEntity; static CEntity *&pIgnoreEntity;
@ -101,7 +99,7 @@ public:
static bool GetIsLineOfSightSectorClear(CSector &sector, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false); static bool GetIsLineOfSightSectorClear(CSector &sector, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
static bool GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects = false); static bool GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
static CEntity *TestSphereAgainstWorld(CVector centre, float distance, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects); static CEntity *TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects);
static CEntity *TestSphereAgainstSectorList(CPtrList&, CVector, float, CEntity*, bool); static CEntity *TestSphereAgainstSectorList(CPtrList&, CVector, float, CEntity*, bool);
static void FindObjectsInRangeSectorList(CPtrList&, CVector&, float, bool, short*, short, CEntity**); static void FindObjectsInRangeSectorList(CPtrList&, CVector&, float, bool, short*, short, CEntity**);
static void FindObjectsInRange(CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool); static void FindObjectsInRange(CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool);
@ -142,6 +140,8 @@ public:
static void Process(); static void Process();
}; };
extern CColPoint *gaTempSphereColPoints;
class CPlayerPed; class CPlayerPed;
class CVehicle; class CVehicle;
CPlayerPed *FindPlayerPed(void); CPlayerPed *FindPlayerPed(void);

View File

@ -1,5 +1,6 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include <ctype.h>
#include "Zones.h" #include "Zones.h"

View File

@ -8,9 +8,12 @@
#pragma warning(disable: 4996) // POSIX names #pragma warning(disable: 4996) // POSIX names
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include <math.h> #include <math.h>
//#include <assert.h>
#include <new> #ifdef WITHWINDOWS
#include <Windows.h>
#endif
#ifdef WITHD3D #ifdef WITHD3D
#include <windows.h> #include <windows.h>
@ -30,6 +33,16 @@
#undef near #undef near
#endif #endif
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
#endif
typedef uint8_t uint8; typedef uint8_t uint8;
typedef int8_t int8; typedef int8_t int8;
typedef uint16_t uint16; typedef uint16_t uint16;

View File

@ -101,6 +101,8 @@ enum Config {
NUMPEDGROUPS = 31, NUMPEDGROUPS = 31,
NUMMODELSPERPEDGROUP = 8, NUMMODELSPERPEDGROUP = 8,
NUMROADBLOCKS = 600,
NUMVISIBLEENTITIES = 2000, NUMVISIBLEENTITIES = 2000,
NUMINVISIBLEENTITIES = 150, NUMINVISIBLEENTITIES = 150,
@ -171,10 +173,12 @@ enum Config {
#endif #endif
#define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more
#define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. doesn't have too many things #define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things
// Pad // Pad
#define XINPUT
#define KANGAROO_CHEAT #define KANGAROO_CHEAT
#define REGISTER_START_BUTTON // currently only in menu sadly. resumes the game
// Hud, frontend and radar // Hud, frontend and radar
#define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios #define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios
@ -201,5 +205,7 @@ enum Config {
// Peds // Peds
#define ANIMATE_PED_COL_MODEL #define ANIMATE_PED_COL_MODEL
#define VC_PED_PORTS // various ports from VC's CPed, mostly subtle #define VC_PED_PORTS // various ports from VC's CPed, mostly subtle
#define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward // #define NEW_WALK_AROUND_ALGORITHM // to make walking around vehicles/objects less awkward
#define CANCELLABLE_CAR_ENTER #define CANCELLABLE_CAR_ENTER
#define IMPROVED_CAMERA // Better Debug cam, and maybe more in the future

View File

@ -325,6 +325,7 @@ DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16
void void
DoRWStuffEndOfFrame(void) DoRWStuffEndOfFrame(void)
{ {
CDebug::DisplayScreenStrings(); // custom
CDebug::DebugDisplayTextBuffer(); CDebug::DebugDisplayTextBuffer();
// FlushObrsPrintfs(); // FlushObrsPrintfs();
RwCameraEndUpdate(Scene.camera); RwCameraEndUpdate(Scene.camera);

View File

@ -6,13 +6,7 @@
#define VARJMP(a) { _asm jmp a } #define VARJMP(a) { _asm jmp a }
#define WRAPARG(a) UNREFERENCED_PARAMETER(a) #define WRAPARG(a) UNREFERENCED_PARAMETER(a)
#define NOVMT __declspec(novtable) #include <string.h> //memset
#define SETVMT(a) *((DWORD_PTR*)this) = (DWORD_PTR)a
#include <algorithm>
#include <vector>
#include "common.h"
enum enum
{ {
@ -103,72 +97,36 @@ isVC(void)
InjectHook(a, func); \ InjectHook(a, func); \
} }
void InjectHook_internal(uint32 address, uint32 hook, int type);
void Protect_internal(uint32 address, uint32 size);
void Unprotect_internal(void);
template<typename T, typename AT> inline void template<typename T, typename AT> inline void
Patch(AT address, T value) Patch(AT address, T value)
{ {
DWORD dwProtect[2]; Protect_internal((uint32)address, sizeof(T));
VirtualProtect((void*)address, sizeof(T), PAGE_EXECUTE_READWRITE, &dwProtect[0]);
*(T*)address = value; *(T*)address = value;
VirtualProtect((void*)address, sizeof(T), dwProtect[0], &dwProtect[1]); Unprotect_internal();
} }
template<typename AT> inline void template<typename AT> inline void
Nop(AT address, unsigned int nCount) Nop(AT address, unsigned int nCount)
{ {
DWORD dwProtect[2]; Protect_internal((uint32)address, nCount);
VirtualProtect((void*)address, nCount, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
memset((void*)address, 0x90, nCount); memset((void*)address, 0x90, nCount);
VirtualProtect((void*)address, nCount, dwProtect[0], &dwProtect[1]); Unprotect_internal();
} }
template<typename AT> inline void
ClearCC(AT address, unsigned int nCount)
{
DWORD dwProtect[2];
VirtualProtect((void*)address, nCount, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
memset((void*)address, 0xCC, nCount);
VirtualProtect((void*)address, nCount, dwProtect[0], &dwProtect[1]);
}
extern std::vector<int32> usedAddresses;
template<typename AT, typename HT> inline void template<typename AT, typename HT> inline void
InjectHook(AT address, HT hook, unsigned int nType=PATCH_NOTHING) InjectHook(AT address, HT hook, unsigned int nType=PATCH_NOTHING)
{ {
if(std::any_of(usedAddresses.begin(), usedAddresses.end(), uint32 uiHook;
[address](AT value) { return (int32)value == address; })) {
debug("Used address %#06x twice when injecting hook\n", address);
}
usedAddresses.push_back((int32)address);
DWORD dwProtect[2];
switch ( nType )
{
case PATCH_JUMP:
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
*(BYTE*)address = 0xE9;
break;
case PATCH_CALL:
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
*(BYTE*)address = 0xE8;
break;
default:
VirtualProtect((void*)((DWORD)address + 1), 4, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
break;
}
DWORD dwHook;
_asm _asm
{ {
mov eax, hook mov eax, hook
mov dwHook, eax mov uiHook, eax
} }
InjectHook_internal((uint32)address, uiHook, nType);
*(ptrdiff_t*)((DWORD)address + 1) = (DWORD)dwHook - (DWORD)address - 5;
if ( nType == PATCH_NOTHING )
VirtualProtect((void*)((DWORD)address + 1), 4, dwProtect[0], &dwProtect[1]);
else
VirtualProtect((void*)address, 5, dwProtect[0], &dwProtect[1]);
} }
inline void ExtractCall(void *dst, uint32_t a) inline void ExtractCall(void *dst, uint32_t a)

View File

@ -20,12 +20,64 @@
#include "debugmenu_public.h" #include "debugmenu_public.h"
#include "Particle.h" #include "Particle.h"
#include "Console.h" #include "Console.h"
#include "Debug.h"
#include <algorithm>
#include <vector> #include <vector>
#include <list> #include <list>
std::vector<int32> usedAddresses; std::vector<int32> usedAddresses;
static DWORD protect[2];
static uint32 protect_address;
static uint32 protect_size;
void
Protect_internal(uint32 address, uint32 size)
{
protect_address = address;
protect_size = size;
VirtualProtect((void*)address, size, PAGE_EXECUTE_READWRITE, &protect[0]);
}
void
Unprotect_internal(void)
{
VirtualProtect((void*)protect_address, protect_size, protect[0], &protect[1]);
}
void
InjectHook_internal(uint32 address, uint32 hook, int type)
{
if(std::any_of(usedAddresses.begin(), usedAddresses.end(),
[address](uint32 value) { return (int32)value == address; })) {
debug("Used address %#06x twice when injecting hook\n", address);
}
usedAddresses.push_back((int32)address);
switch(type){
case PATCH_JUMP:
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &protect[0]);
*(uint8*)address = 0xE9;
break;
case PATCH_CALL:
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &protect[0]);
*(uint8*)address = 0xE8;
break;
default:
VirtualProtect((void*)((uint32)address + 1), 4, PAGE_EXECUTE_READWRITE, &protect[0]);
break;
}
*(ptrdiff_t*)(address + 1) = hook - address - 5;
if(type == PATCH_NOTHING)
VirtualProtect((void*)(address + 1), 4, protect[0], &protect[1]);
else
VirtualProtect((void*)address, 5, protect[0], &protect[1]);
}
void **rwengine = *(void***)0x5A10E1; void **rwengine = *(void***)0x5A10E1;
DebugMenuAPI gDebugMenuAPI; DebugMenuAPI gDebugMenuAPI;
@ -114,13 +166,16 @@ SpawnCar(int id)
CStreaming::LoadAllRequestedModels(false); CStreaming::LoadAllRequestedModels(false);
if(CStreaming::HasModelLoaded(id)){ if(CStreaming::HasModelLoaded(id)){
playerpos = FindPlayerCoors(); playerpos = FindPlayerCoors();
int node = ThePaths.FindNodeClosestToCoors(playerpos, 0, 100.0f, false, false); int node;
if(!CModelInfo::IsBoatModel(id)){
node = ThePaths.FindNodeClosestToCoors(playerpos, 0, 100.0f, false, false);
if(node < 0) if(node < 0)
return; return;
}
CVehicle *v; CVehicle *v;
if(CModelInfo::IsBoatModel(id)) if(CModelInfo::IsBoatModel(id))
return; v = new CBoat(id, RANDOM_VEHICLE);
else else
v = new CAutomobile(id, RANDOM_VEHICLE); v = new CAutomobile(id, RANDOM_VEHICLE);
@ -130,7 +185,11 @@ SpawnCar(int id)
if(carCol2) if(carCol2)
DebugMenuEntrySetAddress(carCol2, &v->m_currentColour2); DebugMenuEntrySetAddress(carCol2, &v->m_currentColour2);
if(CModelInfo::IsBoatModel(id))
v->GetPosition() = TheCamera.GetPosition() + TheCamera.GetForward()*15.0f;
else
v->GetPosition() = ThePaths.m_pathNodes[node].pos; v->GetPosition() = ThePaths.m_pathNodes[node].pos;
v->GetPosition().z += 4.0f; v->GetPosition().z += 4.0f;
v->SetOrientation(0.0f, 0.0f, 3.49f); v->SetOrientation(0.0f, 0.0f, 3.49f);
v->m_status = STATUS_ABANDONED; v->m_status = STATUS_ABANDONED;
@ -197,6 +256,12 @@ PlaceOnRoad(void)
((CAutomobile*)veh)->PlaceOnRoadProperly(); ((CAutomobile*)veh)->PlaceOnRoadProperly();
} }
static void
ResetCamStatics(void)
{
TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;
}
static const char *carnames[] = { static const char *carnames[] = {
"landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "patriot", "firetruk", "trash", "stretch", "manana", "infernus", "blista", "pony", "landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "patriot", "firetruk", "trash", "stretch", "manana", "infernus", "blista", "pony",
"mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "kuruma", "bobcat", "mrwhoop", "bfinject", "corpse", "police", "enforcer", "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "kuruma", "bobcat", "mrwhoop", "bfinject", "corpse", "police", "enforcer",
@ -359,6 +424,16 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop);
extern bool PrintDebugCode;
extern int16 &DebugCamMode;
DebugMenuAddVarBool8("Cam", "Print Debug Code", (int8*)&PrintDebugCode, nil);
DebugMenuAddVar("Cam", "Cam Mode", &DebugCamMode, nil, 1, 0, CCam::MODE_EDITOR, nil);
DebugMenuAddCmd("Cam", "Normal", []() { DebugCamMode = 0; });
DebugMenuAddCmd("Cam", "Follow Ped With Bind", []() { DebugCamMode = CCam::MODE_FOLLOW_PED_WITH_BIND; });
DebugMenuAddCmd("Cam", "Reaction", []() { DebugCamMode = CCam::MODE_REACTION; });
DebugMenuAddCmd("Cam", "Chris", []() { DebugCamMode = CCam::MODE_CHRIS; });
DebugMenuAddCmd("Cam", "Reset Statics", ResetCamStatics);
CTweakVars::AddDBG("Debug"); CTweakVars::AddDBG("Debug");
} }
} }
@ -433,7 +508,8 @@ void re3_debug(const char *format, ...)
vsprintf_s(re3_buff, re3_buffsize, format, va); vsprintf_s(re3_buff, re3_buffsize, format, va);
va_end(va); va_end(va);
printf("%s", re3_buff); // printf("%s", re3_buff);
CDebug::DebugAddText(re3_buff);
} }
void re3_trace(const char *filename, unsigned int lineno, const char *func, const char *format, ...) void re3_trace(const char *filename, unsigned int lineno, const char *func, const char *format, ...)

View File

@ -21,6 +21,8 @@ CBuilding::ReplaceWithNewModel(int32 id)
CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE); CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE);
} }
#include <new>
class CBuilding_ : public CBuilding class CBuilding_ : public CBuilding
{ {
public: public:

View File

@ -865,6 +865,8 @@ CEntity::ModifyMatrixForBannerInWind(void)
UpdateRwFrame(); UpdateRwFrame();
} }
#include <new>
class CEntity_ : public CEntity class CEntity_ : public CEntity
{ {
public: public:

View File

@ -12,6 +12,8 @@ CDummyObject::CDummyObject(CObject *obj)
m_level = obj->m_level; m_level = obj->m_level;
} }
#include <new>
class CDummyObject_ : public CDummyObject class CDummyObject_ : public CDummyObject
{ {
public: public:

View File

@ -141,6 +141,8 @@ CObject::CanBeDeleted(void)
} }
} }
#include <new>
class CObject_ : public CObject class CObject_ : public CObject
{ {
public: public:

View File

@ -14,6 +14,8 @@ CProjectile::CProjectile(int32 model) : CObject()
ObjectCreatedBy = MISSION_OBJECT; ObjectCreatedBy = MISSION_OBJECT;
} }
#include <new>
class CProjectile_ : public CProjectile class CProjectile_ : public CProjectile
{ {
public: public:

View File

@ -377,6 +377,8 @@ CCivilianPed::ProcessControl(void)
Avoid(); Avoid();
} }
#include <new>
class CCivilianPed_ : public CCivilianPed class CCivilianPed_ : public CCivilianPed
{ {
public: public:

View File

@ -7,6 +7,9 @@
#include "Vehicle.h" #include "Vehicle.h"
#include "RpAnimBlend.h" #include "RpAnimBlend.h"
#include "General.h" #include "General.h"
#include "ZoneCull.h"
#include "PathFind.h"
#include "RoadBlocks.h"
WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); } WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); }
@ -58,11 +61,16 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
m_bIsDisabledCop = false; m_bIsDisabledCop = false;
field_1356 = 0; field_1356 = 0;
m_attackTimer = 0; m_attackTimer = 0;
field_1351 = 0; m_bBeatingSuspect = false;
m_bZoneDisabledButClose = false; m_bZoneDisabledButClose = false;
m_bZoneDisabled = false; m_bZoneDisabled = false;
field_1364 = -1; field_1364 = -1;
m_pPointGunAt = nil; m_pPointGunAt = nil;
// VC also initializes in here, but it keeps object
#ifdef FIX_BUGS
m_wRoadblockNode = -1;
#endif
} }
CCopPed::~CCopPed() CCopPed::~CCopPed()
@ -181,15 +189,15 @@ CCopPed::ClearPursuit(void)
} }
} }
// TO-DO: m_MaxCops in for loop may be a bug, check it out after CopAI // TODO: I don't know why they needed that parameter.
void void
CCopPed::SetPursuit(bool iMayAlreadyBeInPursuit) CCopPed::SetPursuit(bool ignoreCopLimit)
{ {
CWanted *wanted = FindPlayerPed()->m_pWanted; CWanted *wanted = FindPlayerPed()->m_pWanted;
if (m_bIsInPursuit || !IsPedInControl()) if (m_bIsInPursuit || !IsPedInControl())
return; return;
if (wanted->m_CurrentCops < wanted->m_MaxCops || iMayAlreadyBeInPursuit) { if (wanted->m_CurrentCops < wanted->m_MaxCops || ignoreCopLimit) {
for (int i = 0; i < wanted->m_MaxCops; ++i) { for (int i = 0; i < wanted->m_MaxCops; ++i) {
if (!wanted->m_pCops[i]) { if (!wanted->m_pCops[i]) {
m_bIsInPursuit = true; m_bIsInPursuit = true;
@ -275,6 +283,276 @@ CCopPed::ScanForCrimes(void)
} }
} }
void
CCopPed::CopAI(void)
{
CWanted *wanted = FindPlayerPed()->m_pWanted;
int wantedLevel = wanted->m_nWantedLevel;
CPhysical *playerOrHisVeh = FindPlayerVehicle() ? (CPhysical*)FindPlayerVehicle() : (CPhysical*)FindPlayerPed();
if (wanted->m_bIgnoredByEveryone || wanted->m_bIgnoredByCops) {
if (m_nPedState != PED_ARREST_PLAYER)
ClearPursuit();
return;
}
if (CCullZones::NoPolice() && m_bIsInPursuit && !m_bIsDisabledCop) {
if (bHitSomethingLastFrame) {
m_bZoneDisabled = true;
m_bIsDisabledCop = true;
#ifdef FIX_BUGS
m_wRoadblockNode = -1;
#else
m_wRoadblockNode = 0;
#endif
bKindaStayInSamePlace = true;
bIsRunning = false;
bNotAllowedToDuck = false;
bCrouchWhenShooting = false;
SetIdle();
ClearObjective();
ClearPursuit();
m_prevObjective = OBJECTIVE_NONE;
m_nLastPedState = PED_NONE;
SetAttackTimer(0);
if (m_fDistanceToTarget > 15.0f)
m_bZoneDisabledButClose = true;
}
} else if (m_bZoneDisabled && !CCullZones::NoPolice()) {
m_bZoneDisabled = false;
m_bIsDisabledCop = false;
m_bZoneDisabledButClose = false;
bKindaStayInSamePlace = false;
bCrouchWhenShooting = false;
bDuckAndCover = false;
ClearPursuit();
}
if (wantedLevel > 0) {
if (!m_bIsDisabledCop) {
if (!m_bIsInPursuit || wanted->m_CurrentCops > wanted->m_MaxCops) {
CCopPed *copFarthestToTarget = nil;
float copFarthestToTargetDist = m_fDistanceToTarget;
int oldCopNum = wanted->m_CurrentCops;
int maxCops = wanted->m_MaxCops;
for (int i = 0; i < max(maxCops, oldCopNum); i++) {
CCopPed *cop = wanted->m_pCops[i];
if (cop && cop->m_fDistanceToTarget > copFarthestToTargetDist) {
copFarthestToTargetDist = cop->m_fDistanceToTarget;
copFarthestToTarget = wanted->m_pCops[i];
}
}
if (m_bIsInPursuit) {
if (copFarthestToTarget && oldCopNum > maxCops) {
if (copFarthestToTarget == this && m_fDistanceToTarget > 10.0f) {
ClearPursuit();
} else if(copFarthestToTargetDist > 10.0f)
copFarthestToTarget->ClearPursuit();
}
} else {
if (oldCopNum < maxCops) {
SetPursuit(true);
} else {
if (m_fDistanceToTarget <= 10.0f || copFarthestToTarget && m_fDistanceToTarget < copFarthestToTargetDist) {
if (copFarthestToTarget && copFarthestToTargetDist > 10.0f)
copFarthestToTarget->ClearPursuit();
SetPursuit(true);
}
}
}
} else
SetPursuit(false);
if (!m_bIsInPursuit)
return;
if (wantedLevel > 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
SetCurrentWeapon(WEAPONTYPE_COLT45);
else if (wantedLevel == 1 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !FindPlayerPed()->m_pCurrentPhysSurface) {
// i.e. if player is on top of car, cop will still use colt45.
SetCurrentWeapon(WEAPONTYPE_UNARMED);
}
if (FindPlayerVehicle()) {
if (m_bBeatingSuspect) {
--wanted->m_CopsBeatingSuspect;
m_bBeatingSuspect = false;
}
if (m_fDistanceToTarget * FindPlayerSpeed().Magnitude() > 4.0f)
ClearPursuit();
}
return;
}
float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange;
SetLookFlag(playerOrHisVeh, true);
TurnBody();
SetCurrentWeapon(WEAPONTYPE_COLT45);
if (!bIsDucking) {
if (m_attackTimer >= CTimer::GetTimeInMilliseconds()) {
if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT && !m_bZoneDisabled) {
CVector targetDist = playerOrHisVeh->GetPosition() - GetPosition();
if (m_fDistanceToTarget > 30.0f) {
CAnimBlendAssociation* crouchShootAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT);
if (crouchShootAssoc)
crouchShootAssoc->blendDelta = -1000.0f;
// Target is coming onto us
if (DotProduct(playerOrHisVeh->m_vecMoveSpeed, targetDist) > 0.0f) {
m_bIsDisabledCop = false;
bKindaStayInSamePlace = false;
bNotAllowedToDuck = false;
bDuckAndCover = false;
SetPursuit(false);
SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, FindPlayerPed());
}
} else if (m_fDistanceToTarget < 5.0f
&& (!FindPlayerVehicle() || FindPlayerVehicle()->m_vecMoveSpeed.MagnitudeSqr() < sq(1.f/200.f))) {
m_bIsDisabledCop = false;
bKindaStayInSamePlace = false;
bNotAllowedToDuck = false;
bDuckAndCover = false;
} else {
// VC checks for != nil compared to buggy behaviour of III. I check for != -1 here.
#ifdef VC_PED_PORTS
float dotProd;
if (m_wRoadblockNode != -1) {
CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]];
dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), GetPosition() - roadBlockRoad->GetPosition());
} else
dotProd = -1.0f;
if(dotProd >= 0.0f) {
#else
#ifndef FIX_BUGS
float copRoadDotProd, targetRoadDotProd;
#else
float copRoadDotProd = 1.0f, targetRoadDotProd = 1.0f;
if (m_wRoadblockNode != -1)
#endif
{
CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]];
CVector2D roadFwd = roadBlockRoad->GetForward();
copRoadDotProd = DotProduct2D(GetPosition() - roadBlockRoad->GetPosition(), roadFwd);
targetRoadDotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), roadFwd);
}
// Roadblock may be towards road's fwd or opposite, so check both
if ((copRoadDotProd >= 0.0f || targetRoadDotProd >= 0.0f)
&& (copRoadDotProd <= 0.0f || targetRoadDotProd <= 0.0f)) {
#endif
bIsPointingGunAt = true;
} else {
m_bIsDisabledCop = false;
bKindaStayInSamePlace = false;
bNotAllowedToDuck = false;
bCrouchWhenShooting = false;
bIsDucking = false;
bDuckAndCover = false;
SetPursuit(false);
}
}
}
} else {
if (m_fDistanceToTarget < weaponRange) {
CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
CVector gunPos = weaponInfo->m_vecFireOffset;
for (RwFrame *i = GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i))
RwV3dTransformPoints((RwV3d*)&gunPos, (RwV3d*)&gunPos, 1, RwFrameGetMatrix(i));
CColPoint foundCol;
CEntity *foundEnt;
if (!CWorld::ProcessLineOfSight(gunPos, playerOrHisVeh->GetPosition(), foundCol, foundEnt,
false, true, false, false, true, false, false)
|| foundEnt && foundEnt == playerOrHisVeh) {
m_pPointGunAt = playerOrHisVeh;
if (playerOrHisVeh)
playerOrHisVeh->RegisterReference((CEntity**) &m_pPointGunAt);
SetAttack(playerOrHisVeh);
SetShootTimer(CGeneral::GetRandomNumberInRange(500, 1000));
}
SetAttackTimer(CGeneral::GetRandomNumberInRange(100, 300));
}
SetMoveState(PEDMOVE_STILL);
}
}
} else {
if (!m_bIsDisabledCop || m_bZoneDisabled) {
if (m_nPedState != PED_AIM_GUN) {
if (m_bIsInPursuit)
ClearPursuit();
if (IsPedInControl()) {
// Entering the vehicle
if (m_pMyVehicle && !bInVehicle) {
if (m_pMyVehicle->IsLawEnforcementVehicle()) {
if (m_pMyVehicle->pDriver) {
if (m_pMyVehicle->pDriver->m_nPedType == PEDTYPE_COP) {
if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER)
SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_pMyVehicle);
} else if (m_pMyVehicle->pDriver->IsPlayer()) {
FindPlayerPed()->SetWantedLevelNoDrop(1);
}
} else if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
}
} else {
m_pMyVehicle = nil;
ClearObjective();
SetWanderPath(CGeneral::GetRandomNumber() & 7);
}
}
#ifdef VC_PED_PORTS
else {
if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && CharCreatedBy == RANDOM_CHAR) {
for (int i = 0; i < m_numNearPeds; i++) {
CPed *nearPed = m_nearPeds[i];
if (nearPed->CharCreatedBy == RANDOM_CHAR) {
if ((nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->IsGangMember())
&& nearPed->IsPedInControl()) {
bool anotherCopChasesHim = false;
if (nearPed->m_nPedState == PED_FLEE_ENTITY) {
if (nearPed->m_fleeFrom && nearPed->m_fleeFrom->IsPed() &&
((CPed*)nearPed->m_fleeFrom)->m_nPedType == PEDTYPE_COP) {
anotherCopChasesHim = true;
}
}
if (!anotherCopChasesHim) {
SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, nearPed);
nearPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, this);
nearPed->m_ped_flagE2 = true;
return;
}
}
}
}
}
}
#endif
}
}
} else {
if (m_bIsInPursuit && m_nPedState != PED_AIM_GUN)
ClearPursuit();
m_bIsDisabledCop = false;
bKindaStayInSamePlace = false;
bNotAllowedToDuck = false;
bCrouchWhenShooting = false;
bIsDucking = false;
bDuckAndCover = false;
if (m_pMyVehicle)
SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
}
}
}
#include <new>
class CCopPed_ : public CCopPed class CCopPed_ : public CCopPed
{ {
public: public:
@ -290,4 +568,5 @@ STARTPATCHES
InjectHook(0x4C27D0, &CCopPed::SetPursuit, PATCH_JUMP); InjectHook(0x4C27D0, &CCopPed::SetPursuit, PATCH_JUMP);
InjectHook(0x4C2C90, &CCopPed::ArrestPlayer, PATCH_JUMP); InjectHook(0x4C2C90, &CCopPed::ArrestPlayer, PATCH_JUMP);
InjectHook(0x4C26A0, &CCopPed::ScanForCrimes, PATCH_JUMP); InjectHook(0x4C26A0, &CCopPed::ScanForCrimes, PATCH_JUMP);
InjectHook(0x4C1B50, &CCopPed::CopAI, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -17,9 +17,9 @@ public:
int8 field_1343; int8 field_1343;
float m_fDistanceToTarget; float m_fDistanceToTarget;
int8 m_bIsInPursuit; int8 m_bIsInPursuit;
int8 m_bIsDisabledCop; int8 m_bIsDisabledCop; // What disabled cop actually is?
int8 field_1350; int8 field_1350;
int8 field_1351; bool m_bBeatingSuspect;
int8 m_bZoneDisabledButClose; int8 m_bZoneDisabledButClose;
int8 m_bZoneDisabled; int8 m_bZoneDisabled;
int8 field_1354; int8 field_1354;
@ -40,6 +40,7 @@ public:
void SetPursuit(bool); void SetPursuit(bool);
void ArrestPlayer(void); void ArrestPlayer(void);
void ScanForCrimes(void); void ScanForCrimes(void);
void CopAI(void);
}; };
static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error"); static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error");

View File

@ -413,6 +413,8 @@ CEmergencyPed::MedicAI(void)
} }
} }
#include <new>
class CEmergencyPed_ : public CEmergencyPed class CEmergencyPed_ : public CEmergencyPed
{ {
public: public:

View File

@ -2720,6 +2720,10 @@ CPed::SetObjective(eObjective newObj, void *entity)
return; return;
} }
#ifdef VC_PED_PORTS
SetObjectiveTimer(0);
ClearPointGunAt();
#endif
bObjectiveCompleted = false; bObjectiveCompleted = false;
if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) { if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) {
if (m_objective != newObj) { if (m_objective != newObj) {
@ -3444,8 +3448,12 @@ CPed::ClearAll(void)
m_fleeFrom = nil; m_fleeFrom = nil;
m_fleeTimer = 0; m_fleeTimer = 0;
bUsesCollision = true; bUsesCollision = true;
#ifdef VC_PED_PORTS
ClearPointGunAt();
#else
ClearAimFlag(); ClearAimFlag();
ClearLookFlag(); ClearLookFlag();
#endif
bIsPointingGunAt = false; bIsPointingGunAt = false;
bRenderPedInCar = true; bRenderPedInCar = true;
bKnockedUpIntoAir = false; bKnockedUpIntoAir = false;
@ -12169,11 +12177,11 @@ CPed::PlacePedOnDryLand(void)
if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false)) if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false))
return false; return false;
CVector potentialGroundDist = CWorld::ms_testSpherePoint.point - GetPosition(); CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition();
potentialGroundDist.z = 0.0f; potentialGroundDist.z = 0.0f;
potentialGroundDist.Normalise(); potentialGroundDist.Normalise();
CVector posToCheck = 0.5f * potentialGroundDist + CWorld::ms_testSpherePoint.point; CVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point;
posToCheck.z = 3.0f + waterLevel; posToCheck.z = 3.0f + waterLevel;
if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, false)) { if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, false)) {
@ -17447,6 +17455,8 @@ CPed::SetExitBoat(CVehicle *boat)
CWaterLevel::FreeBoatWakeArray(); CWaterLevel::FreeBoatWakeArray();
} }
#include <new>
class CPed_ : public CPed class CPed_ : public CPed
{ {
public: public:

View File

@ -1414,6 +1414,8 @@ CPlayerPed::ProcessControl(void)
} }
} }
#include <new>
class CPlayerPed_ : public CPlayerPed class CPlayerPed_ : public CPlayerPed
{ {
public: public:

View File

@ -576,7 +576,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
} }
// Yeah, float // Yeah, float
float maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier; float maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier;
// maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse); maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse);
if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) { if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) {
int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000); int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000);

View File

@ -94,7 +94,7 @@ CFont::Initialise(void)
SetBackgroundColor(CRGBA(0x80, 0x80, 0x80, 0x80)); SetBackgroundColor(CRGBA(0x80, 0x80, 0x80, 0x80));
SetBackGroundOnlyTextOff(); SetBackGroundOnlyTextOff();
SetPropOn(); SetPropOn();
SetFontStyle(0); SetFontStyle(FONT_BANK);
SetRightJustifyWrap(0.0f); SetRightJustifyWrap(0.0f);
SetAlphaFade(255.0f); SetAlphaFade(255.0f);
SetDropShadowPosition(0); SetDropShadowPosition(0);

View File

@ -115,47 +115,43 @@ void CHud::Draw()
return; return;
if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) { if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) {
bool Mode_RunAround = 0; bool DrawCrossHair = 0;
bool Mode_FirstPerson = 0; bool DrawCrossHairPC = 0;
int32 WeaponType = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_eWeaponType; int32 WeaponType = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_eWeaponType;
int32 Mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; int32 Mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_EDITOR) if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON)
Mode_FirstPerson = 1; DrawCrossHair = 1;
if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT) if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)
Mode_RunAround = 1; DrawCrossHairPC = 1;
/* /*
Draw Crosshairs Draw Crosshairs
*/ */
if (TheCamera.Cams->Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) { if (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() &&
(!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) {
if (FindPlayerPed() && !FindPlayerPed()->EnteringCar()) { if (FindPlayerPed() && !FindPlayerPed()->EnteringCar()) {
if ((WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_M16) || WeaponType == WEAPONTYPE_FLAMETHROWER) if ((WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_M16) || WeaponType == WEAPONTYPE_FLAMETHROWER)
Mode_RunAround = 1; DrawCrossHairPC = 1;
} }
} }
if (Mode_FirstPerson || Mode_RunAround) { if (DrawCrossHair || DrawCrossHairPC) {
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
int32 SpriteBrightLikeADiamond = SpriteBrightness + 1; SpriteBrightness = min(SpriteBrightness+1, 30);
if (SpriteBrightLikeADiamond > 30)
SpriteBrightLikeADiamond = 30;
SpriteBrightness = SpriteBrightLikeADiamond;
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
float fStep = Sin((CTimer::GetTimeInMilliseconds() & 1023) * 0.0061328127); float fStep = Sin((CTimer::GetTimeInMilliseconds() & 1023)/1024.0f * 6.28f);
float fMultBright = SpriteBrightness * 0.03f * (0.25f * fStep + 0.75f); float fMultBright = SpriteBrightness * 0.03f * (0.25f * fStep + 0.75f);
CRect rect; CRect rect;
if (DrawCrossHairPC && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()) {
#ifndef ASPECT_RATIO_SCALE #ifndef ASPECT_RATIO_SCALE
if (Mode_RunAround && TheCamera.Cams->Using3rdPersonMouseCam()) {
float f3rdX = SCREEN_WIDTH * TheCamera.m_f3rdPersonCHairMultX; float f3rdX = SCREEN_WIDTH * TheCamera.m_f3rdPersonCHairMultX;
float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY; float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY;
#else #else
if (Mode_RunAround && TheCamera.Cams->Using3rdPersonMouseCam()) {
float f3rdX = (((TheCamera.m_f3rdPersonCHairMultX - 0.5f) / ((CDraw::GetAspectRatio()) / (DEFAULT_ASPECT_RATIO))) + 0.5f) * SCREEN_WIDTH; float f3rdX = (((TheCamera.m_f3rdPersonCHairMultX - 0.5f) / ((CDraw::GetAspectRatio()) / (DEFAULT_ASPECT_RATIO))) + 0.5f) * SCREEN_WIDTH;
float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY + SCREEN_SCALE_Y(-2.0f); float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY + SCREEN_SCALE_Y(-2.0f);
#endif #endif
@ -179,14 +175,14 @@ void CHud::Draw()
else { else {
if (Mode == CCam::MODE_M16_1STPERSON || if (Mode == CCam::MODE_M16_1STPERSON ||
Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||
Mode == CCam::MODE_EDITOR) { Mode == CCam::MODE_HELICANNON_1STPERSON) {
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f); rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f);
rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f); rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f);
rect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f); rect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f);
rect.bottom = (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(32.0f); rect.bottom = (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(32.0f);
Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255)); Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255));
} }
else if (Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) { else if (Mode == CCam::MODE_1STPERSON_RUNABOUT) {
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f * 0.7f); rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f * 0.7f);
rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f * 0.7f); rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f * 0.7f);
rect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f * 0.7f); rect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f * 0.7f);
@ -194,17 +190,18 @@ void CHud::Draw()
Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255)); Sprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255));
} }
else if (Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_SNIPER_RUNABOUT) { else if (Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) {
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRocketSightTex->raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRocketSightTex));
CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255); CSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255);
} }
else { else {
// Sniper
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(210.0f); rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(210.0f);
rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(210.0f); rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(210.0f);
rect.right = SCREEN_WIDTH / 2; rect.right = SCREEN_WIDTH / 2;

View File

@ -645,6 +645,9 @@ CRenderer::ScanWorld(void)
m_loadingPriority = false; m_loadingPriority = false;
if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||
#ifdef FIX_BUGS
TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_GTACLASSIC ||
#endif
TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){ TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){
CRect rect; CRect rect;
int x1, x2, y1, y2; int x1, x2, y1, y2;
@ -756,6 +759,9 @@ CRenderer::RequestObjectsInFrustum(void)
RwV3dTransformPoints((RwV3d*)vectors, (RwV3d*)vectors, 9, cammatrix); RwV3dTransformPoints((RwV3d*)vectors, (RwV3d*)vectors, 9, cammatrix);
if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||
#ifdef FIX_BUGS
TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_GTACLASSIC ||
#endif
TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){ TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){
CRect rect; CRect rect;
int x1, x2, y1, y2; int x1, x2, y1, y2;

View File

@ -1,3 +1,4 @@
#define WITHWINDOWS
#include "common.h" #include "common.h"
#include "main.h" #include "main.h"
#include "patcher.h" #include "patcher.h"
@ -61,9 +62,9 @@ do {\
MakeSpaceForSizeInBufferPointer(presize, buf, postsize);\ MakeSpaceForSizeInBufferPointer(presize, buf, postsize);\
save_func(buf, &size);\ save_func(buf, &size);\
CopySizeAndPreparePointer(presize, buf, postsize, reserved, size);\ CopySizeAndPreparePointer(presize, buf, postsize, reserved, size);\
if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, size + 4))\ if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff))\
return false;\ return false;\
totalSize += size;\ totalSize += buf - work_buff;\
} while (0) } while (0)
bool bool
@ -74,7 +75,6 @@ GenericSave(int file)
uint32 reserved; uint32 reserved;
uint32 totalSize; uint32 totalSize;
uint32 i;
wchar *lastMissionPassed; wchar *lastMissionPassed;
wchar suffix[6]; wchar suffix[6];
@ -85,13 +85,11 @@ GenericSave(int file)
CheckSum = 0; CheckSum = 0;
buf = work_buff; buf = work_buff;
reserved = 0; reserved = 0;
totalSize = 0;
// Save simple vars // Save simple vars
INITSAVEBUF
lastMissionPassed = TheText.Get(CStats::LastMissionPassedName); lastMissionPassed = TheText.Get(CStats::LastMissionPassedName);
if (*lastMissionPassed) { if (*lastMissionPassed) {
AsciiToUnicode("'...", suffix); AsciiToUnicode("...'", suffix);
TextCopy(saveName, lastMissionPassed); TextCopy(saveName, lastMissionPassed);
int len = UnicodeStrlen(saveName); int len = UnicodeStrlen(saveName);
saveName[len] = '\0'; saveName[len] = '\0';
@ -104,20 +102,20 @@ INITSAVEBUF
WriteDataToBufferPointer(buf, saveTime); WriteDataToBufferPointer(buf, saveTime);
WriteDataToBufferPointer(buf, SIZE_OF_ONE_GAME_IN_BYTES); WriteDataToBufferPointer(buf, SIZE_OF_ONE_GAME_IN_BYTES);
WriteDataToBufferPointer(buf, CGame::currLevel); WriteDataToBufferPointer(buf, CGame::currLevel);
WriteDataToBufferPointer(buf, TheCamera.m_matrix.m_matrix.pos.x); WriteDataToBufferPointer(buf, TheCamera.GetPosition().x);
WriteDataToBufferPointer(buf, TheCamera.m_matrix.m_matrix.pos.y); WriteDataToBufferPointer(buf, TheCamera.GetPosition().y);
WriteDataToBufferPointer(buf, TheCamera.m_matrix.m_matrix.pos.z); WriteDataToBufferPointer(buf, TheCamera.GetPosition().z);
WriteDataToBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute); WriteDataToBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute);
WriteDataToBufferPointer(buf, CClock::ms_nLastClockTick); WriteDataToBufferPointer(buf, CClock::ms_nLastClockTick);
WriteDataToBufferPointer(buf, CClock::ms_nGameClockHours); WriteDataToBufferPointer(buf, CClock::ms_nGameClockHours);
WriteDataToBufferPointer(buf, CClock::ms_nGameClockMinutes); WriteDataToBufferPointer(buf, CClock::ms_nGameClockMinutes);
currPad = CPad::GetPad(0); currPad = CPad::GetPad(0);
WriteDataToBufferPointer(buf, currPad->Mode); WriteDataToBufferPointer(buf, currPad->Mode);
WriteDataToBufferPointer(buf, CTimer::m_snTimeInMilliseconds); WriteDataToBufferPointer(buf, CTimer::GetTimeInMilliseconds());
WriteDataToBufferPointer(buf, CTimer::ms_fTimeScale); WriteDataToBufferPointer(buf, CTimer::GetTimeScale());
WriteDataToBufferPointer(buf, CTimer::ms_fTimeStep); WriteDataToBufferPointer(buf, CTimer::GetTimeStep());
WriteDataToBufferPointer(buf, CTimer::ms_fTimeStepNonClipped); WriteDataToBufferPointer(buf, CTimer::GetTimeStepNonClipped());
WriteDataToBufferPointer(buf, CTimer::m_FrameCounter); WriteDataToBufferPointer(buf, CTimer::GetFrameCounter());
WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeStep); WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeStep);
WriteDataToBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate); WriteDataToBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);
WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeScale); WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeScale);
@ -134,10 +132,8 @@ INITSAVEBUF
WriteDataToBufferPointer(buf, CWeather::WeatherTypeInList); WriteDataToBufferPointer(buf, CWeather::WeatherTypeInList);
WriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator); WriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator);
WriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator); WriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator);
#ifdef VALIDATE_SAVE_SIZE
_saveBufCount = buf - work_buff; assert(buf - work_buff == SIZE_OF_SIMPLEVARS);
#endif
VALIDATESAVEBUF(SIZE_OF_SIMPLEVARS);
// Save scripts, block is nested within the same block as simple vars for some reason // Save scripts, block is nested within the same block as simple vars for some reason
presize = buf; presize = buf;
@ -145,9 +141,10 @@ VALIDATESAVEBUF(SIZE_OF_SIMPLEVARS);
postsize = buf; postsize = buf;
CTheScripts::SaveAllScripts(buf, &size); CTheScripts::SaveAllScripts(buf, &size);
CopySizeAndPreparePointer(presize, buf, postsize, reserved, size); CopySizeAndPreparePointer(presize, buf, postsize, reserved, size);
if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, size + SIZE_OF_SIMPLEVARS + 4)) if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff))
return false; return false;
totalSize += size + SIZE_OF_SIMPLEVARS;
totalSize = buf - work_buff;
// Save the rest // Save the rest
WRITE_BLOCK(CPools::SavePedPool); WRITE_BLOCK(CPools::SavePedPool);
@ -171,8 +168,7 @@ VALIDATESAVEBUF(SIZE_OF_SIMPLEVARS);
WRITE_BLOCK(CPedType::Save); WRITE_BLOCK(CPedType::Save);
// Write padding // Write padding
i = 0; for (int i = 0; i < 4; i++) {
do {
size = align4bytes(SIZE_OF_ONE_GAME_IN_BYTES - totalSize - 4); size = align4bytes(SIZE_OF_ONE_GAME_IN_BYTES - totalSize - 4);
if (size > sizeof(work_buff)) if (size > sizeof(work_buff))
size = sizeof(work_buff); size = sizeof(work_buff);
@ -181,15 +177,15 @@ VALIDATESAVEBUF(SIZE_OF_SIMPLEVARS);
return false; return false;
totalSize += size; totalSize += size;
} }
i++; }
} while (i < 4);
// Write checksum and close // Write checksum and close
CFileMgr::Write(file, (const char *) &CheckSum, sizeof(CheckSum)); CFileMgr::Write(file, (const char *) &CheckSum, sizeof(CheckSum));
if (CFileMgr::GetErrorReadWrite(file)) { if (CFileMgr::GetErrorReadWrite(file)) {
PcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; PcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
if (CloseFile(file)) if (!CloseFile(file))
PcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_CLOSE; PcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_CLOSE;
return false; return false;
} }

View File

@ -1,3 +1,4 @@
#define WITHWINDOWS
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "FileMgr.h" #include "FileMgr.h"
@ -38,7 +39,7 @@ C_PcSave::SaveSlot(int32 slot)
if (file != 0) { if (file != 0) {
DoGameSpecificStuffBeforeSave(); DoGameSpecificStuffBeforeSave();
if (GenericSave(file)) { if (GenericSave(file)) {
if (CFileMgr::CloseFile(file) != 0) if (!!CFileMgr::CloseFile(file))
nErrorCode = SAVESTATUS_ERR_SAVE_CLOSE; nErrorCode = SAVESTATUS_ERR_SAVE_CLOSE;
return true; return true;
} }
@ -55,21 +56,21 @@ C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
CFileMgr::Write(file, (const char*)&size, sizeof(size)); CFileMgr::Write(file, (const char*)&size, sizeof(size));
if (CFileMgr::GetErrorReadWrite(file)) { if (CFileMgr::GetErrorReadWrite(file)) {
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, 259); strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false; return false;
} }
CFileMgr::Write(file, (const char*)data, align4bytes(size)); CFileMgr::Write(file, (const char*)data, align4bytes(size));
CheckSum += ((uint8*)&size)[0]; CheckSum += (uint8) size;
CheckSum += ((uint8*)&size)[1]; CheckSum += (uint8) (size >> 8);
CheckSum += ((uint8*)&size)[2]; CheckSum += (uint8) (size >> 16);
CheckSum += ((uint8*)&size)[3]; CheckSum += (uint8) (size >> 24);
for (int i = 0; i < align4bytes(size); i++) { for (int i = 0; i < align4bytes(size); i++) {
CheckSum += *data++; CheckSum += *data++;
} }
if (CFileMgr::GetErrorReadWrite(file)) { if (CFileMgr::GetErrorReadWrite(file)) {
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, 259); strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false; return false;
} }

View File

@ -4483,6 +4483,8 @@ CAutomobile::SetAllTaxiLights(bool set)
m_sAllTaxiLights = set; m_sAllTaxiLights = set;
} }
#include <new>
class CAutomobile_ : public CAutomobile class CAutomobile_ : public CAutomobile
{ {
public: public:

View File

@ -299,6 +299,8 @@ CBoat::FillBoatList()
} }
} }
#include <new>
class CBoat_ : public CBoat class CBoat_ : public CBoat
{ {
public: public:

View File

@ -1034,6 +1034,7 @@ bool CHeli::HasCatalinaBeenShotDown(void) { return CatalinaHasBeenShotDown; }
void CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; } void CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; }
#include <new>
class CHeli_ : public CHeli class CHeli_ : public CHeli
{ {

View File

@ -964,6 +964,7 @@ bool CPlane::HasCesnaLanded(void) { return CesnaMissionStatus == CESNA_STATUS_LA
bool CPlane::HasCesnaBeenDestroyed(void) { return CesnaMissionStatus == CESNA_STATUS_DESTROYED; } bool CPlane::HasCesnaBeenDestroyed(void) { return CesnaMissionStatus == CESNA_STATUS_DESTROYED; }
bool CPlane::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatus == CESNA_STATUS_DESTROYED; } bool CPlane::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatus == CESNA_STATUS_DESTROYED; }
#include <new>
class CPlane_ : public CPlane class CPlane_ : public CPlane
{ {

View File

@ -691,6 +691,8 @@ CTrain::UpdateTrains(void)
} }
} }
#include <new>
class CTrain_ : public CTrain class CTrain_ : public CTrain
{ {
public: public:

View File

@ -33,6 +33,7 @@ void CVehicle::operator delete(void *p, int handle) { CPools::GetVehiclePool()->
WRAPPER bool CVehicle::ShufflePassengersToMakeSpace(void) { EAXJMP(0x5528A0); } WRAPPER bool CVehicle::ShufflePassengersToMakeSpace(void) { EAXJMP(0x5528A0); }
// or Weapon.cpp? // or Weapon.cpp?
WRAPPER void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage) { EAXJMP(0x563B00); } WRAPPER void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage) { EAXJMP(0x563B00); }
WRAPPER void CVehicle::InflictDamage(CEntity *damagedBy, uint32 weaponType, float damage) { EAXJMP(0x551950); }
CVehicle::CVehicle(uint8 CreatedBy) CVehicle::CVehicle(uint8 CreatedBy)
{ {

View File

@ -266,6 +266,7 @@ public:
void ProcessCarAlarm(void); void ProcessCarAlarm(void);
bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius); bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius);
bool ShufflePassengersToMakeSpace(void); bool ShufflePassengersToMakeSpace(void);
void InflictDamage(CEntity *damagedBy, uint32 weaponType, float damage);
bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; } bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; }
CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); } CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); }