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
CBulletInfo
CBulletTraces
CCam
CCamera
CCopPed
CCrane

View File

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

View File

@ -203,6 +203,15 @@ CAnimBlendAssociation::UpdateBlend(float timeDelta)
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
InjectHook(0x4016A0, &CAnimBlendAssociation::AllocateAnimBlendNodeArray, PATCH_JUMP);
@ -219,7 +228,7 @@ STARTPATCHES
InjectHook(0x4031F0, &CAnimBlendAssociation::UpdateTime, PATCH_JUMP);
InjectHook(0x4032B0, &CAnimBlendAssociation::UpdateBlend, PATCH_JUMP);
InjectHook(0x401460, &CAnimBlendAssociation::ctor1, PATCH_JUMP);
InjectHook(0x4014C0, &CAnimBlendAssociation::ctor2, PATCH_JUMP);
InjectHook(0x401520, &CAnimBlendAssociation::dtor, PATCH_JUMP);
InjectHook(0x401460, &CAnimBlendAssociation_::ctor1, PATCH_JUMP);
InjectHook(0x4014C0, &CAnimBlendAssociation_::ctor2, PATCH_JUMP);
InjectHook(0x401520, &CAnimBlendAssociation_::dtor, PATCH_JUMP);
ENDPATCHES

View File

@ -85,9 +85,5 @@ public:
static CAnimBlendAssociation *FromLink(CAnimBlendLink *l) {
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");

View File

@ -36,9 +36,19 @@ CAnimBlendClumpData::ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *
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
InjectHook(0x401880, &CAnimBlendClumpData::ctor, PATCH_JUMP);
InjectHook(0x4018B0, &CAnimBlendClumpData::dtor, PATCH_JUMP);
InjectHook(0x401880, &CAnimBlendClumpData_::ctor, PATCH_JUMP);
InjectHook(0x4018B0, &CAnimBlendClumpData_::dtor, PATCH_JUMP);
InjectHook(0x4018F0, &CAnimBlendClumpData::SetNumberOfFrames, PATCH_JUMP);
InjectHook(0x401930, &CAnimBlendClumpData::ForAllFrames, PATCH_JUMP);
ENDPATCHES

View File

@ -49,9 +49,5 @@ public:
void SetNumberOfBones(int n) { SetNumberOfFrames(n); }
#endif
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");

View File

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

View File

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

View File

@ -1,7 +1,37 @@
#include "common.h"
#include "patcher.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::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
{
public:
static int16 (&NumRoadBlocks);
static int16 (&RoadBlockObjects)[NUMROADBLOCKS];
static bool (&InOrOut)[NUMROADBLOCKS];
static void Init(void);
static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16);
static void GenerateRoadBlocks(void);

View File

@ -2,5 +2,10 @@
#include "patcher.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::Init(void) { EAXJMP(0x585170); }

View File

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

View File

@ -1,3 +1,4 @@
#define WITHWINDOWS // for our script loading hack
#include "common.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 CAutomobile;
extern int16 &DebugCamMode;
#define NUMBER_OF_VECTORS_FOR_AVERAGE 2
struct CCam
@ -66,17 +68,17 @@ struct CCam
bool m_bTheHeightFixerVehicleIsATrain;
bool LookBehindCamWasInFront;
bool LookingBehind;
bool LookingLeft; // 32
bool LookingLeft;
bool LookingRight;
bool ResetStatics; //for interpolation type stuff to work
bool Rotating;
int16 Mode; // CameraMode
uint32 m_uiFinishTime; // 52
uint32 m_uiFinishTime;
int m_iDoCollisionChecksOnFrameNum;
int m_iDoCollisionCheckEveryNumOfFrames;
int m_iFrameNumWereAt; // 64
int m_iFrameNumWereAt;
int m_iRunningVectorArrayPos;
int m_iRunningVectorCounter;
int DirectionWasLooking;
@ -85,9 +87,9 @@ struct CCam
float f_Roll; //used for adding a slight roll to the camera in the
float f_rollSpeed;
float m_fSyphonModeTargetZOffSet;
float m_fUnknownZOffSet;
float m_fRoadOffSet;
float m_fAmountFractionObscured;
float m_fAlphaSpeedOverOneFrame; // 100
float m_fAlphaSpeedOverOneFrame;
float m_fBetaSpeedOverOneFrame;
float m_fBufferedTargetBeta;
float m_fBufferedTargetOrientation;
@ -95,7 +97,7 @@ struct CCam
float m_fCamBufferedHeight;
float m_fCamBufferedHeightSpeed;
float m_fCloseInPedHeightOffset;
float m_fCloseInPedHeightOffsetSpeed; // 132
float m_fCloseInPedHeightOffsetSpeed;
float m_fCloseInCarHeightOffset;
float m_fCloseInCarHeightOffsetSpeed;
float m_fDimensionOfHighestNearCar;
@ -103,7 +105,7 @@ struct CCam
float m_fFovSpeedOverOneFrame;
float m_fMinDistAwayFromCamWhenInterPolating;
float m_fPedBetweenCameraHeightOffset;
float m_fPlayerInFrontSyphonAngleOffSet; // 164
float m_fPlayerInFrontSyphonAngleOffSet;
float m_fRadiusForDead;
float m_fRealGroundDist; //used for follow ped mode
float m_fTargetBeta;
@ -111,7 +113,7 @@ struct CCam
float m_fTransitionBeta;
float m_fTrueBeta;
float m_fTrueAlpha; // 200
float m_fTrueAlpha;
float m_fInitialPlayerOrientation; //used for first person
float Alpha;
@ -120,34 +122,25 @@ struct CCam
float FOVSpeed;
float Beta;
float BetaSpeed;
float Distance; // 232
float Distance;
float DistanceSpeed;
float CA_MIN_DISTANCE;
float CA_MAX_DISTANCE;
float SpeedVar;
// ped onfoot zoom distance
float m_fTargetZoomGroundOne;
float m_fTargetZoomGroundTwo; // 256
float m_fTargetZoomGroundThree;
// ped onfoot alpha angle offset
float m_fTargetZoomOneZExtra;
float m_fTargetZoomTwoZExtra;
float m_fTargetZoomThreeZExtra;
CVector m_cvecSourceSpeedOverOneFrame;
CVector m_cvecTargetSpeedOverOneFrame;
CVector m_cvecUpOverOneFrame;
float m_fTargetZoomZCloseIn;
float m_fMinRealGroundDist;
float m_fTargetCloseInDist;
CVector m_cvecTargetCoorsForFudgeInter; // 360
CVector m_cvecCamFixedModeVector; // 372
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
CVector m_cvecTargetCoorsForFudgeInter;
CVector m_cvecCamFixedModeVector;
CVector m_cvecCamFixedModeSource;
CVector m_cvecCamFixedModeUpOffSet;
CVector m_vecLastAboveWaterCamPosition; //helper for when the player has gone under the water
CVector m_vecBufferedPlayerBodyOffset;
// 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 SourceBeforeLookBehind;
CVector Up; // Just that
@ -162,6 +155,10 @@ struct CCam
bool m_bFirstPersonRunAboutActive;
CCam(void) { Init(); }
void Init(void);
void Process(void);
void ProcessSpecialHeightRoutines(void);
void GetVectorsReadyForRW(void);
CVector DoAverageOnVector(const CVector &vec);
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);
void Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist);
void FixCamWhenObscuredByVehicle(const CVector &TargetCoors);
bool Using3rdPersonMouseCam();
bool GetWeaponFirstPersonOn();
void LookBehind(void);
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_FollowPedWithMouse(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_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(offsetof(CCam, Alpha) == 0xA8, "CCam: error");
@ -223,6 +266,7 @@ enum
FADE_OUT = 0,
FADE_IN,
FADE_NONE
};
enum
@ -493,6 +537,7 @@ int m_iModeObbeCamIsInForCar;
void TakeControlNoEntity(const CVector&, int16, int32);
void SetCamPositionForFixedMode(const CVector&, const CVector&);
bool GetFading();
int GetFadingDirection();
void Init();
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_BlurBlue) == 0x9C, "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_arrPathArray) == 0x7a8, "CCamera: error");
static_assert(sizeof(CCamera) == 0xE9D8, "CCamera: wrong size");
extern CCamera &TheCamera;
void CamShakeNoPos(CCamera*, float);

View File

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

View File

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

View File

@ -2061,6 +2061,19 @@ CColModel::operator=(const CColModel &other)
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
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(0x40B2A0, &CColBox::Set, PATCH_JUMP);
InjectHook(0x40B320, &CColLine::ctor, PATCH_JUMP);
InjectHook(0x40B320, &CColLine_::ctor, PATCH_JUMP);
InjectHook(0x40B350, &CColLine::Set, PATCH_JUMP);
InjectHook(0x411E70, &CColTriangle::Set, PATCH_JUMP);
InjectHook(0x411EA0, &CColTrianglePlane::Set, PATCH_JUMP);
InjectHook(0x412140, &CColTrianglePlane::GetNormal, PATCH_JUMP);
InjectHook(0x411680, &CColModel::ctor, PATCH_JUMP);
InjectHook(0x4116E0, &CColModel::dtor, PATCH_JUMP);
InjectHook(0x411680, &CColModel_::ctor, PATCH_JUMP);
InjectHook(0x4116E0, &CColModel_::dtor, PATCH_JUMP);
InjectHook(0x411D80, &CColModel::RemoveCollisionVolumes, PATCH_JUMP);
InjectHook(0x411CB0, &CColModel::CalculateTrianglePlanes, PATCH_JUMP);
InjectHook(0x411D10, &CColModel::RemoveTrianglePlanes, PATCH_JUMP);

View File

@ -35,8 +35,6 @@ struct CColLine
CColLine(void) { };
CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
void Set(const CVector &p0, const CVector &p1);
CColLine *ctor(CVector *p0, CVector *p1) { return ::new (this) CColLine(*p0, *p1); }
};
struct CColTriangle
@ -106,8 +104,6 @@ struct CColModel
void SetLinkPtr(CLink<CColModel*>*);
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);
};

View File

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

View File

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

View File

@ -89,3 +89,49 @@ CDebug::DebugDisplayTextBuffer()
}
#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_STR_LEN = 80,
MAX_SCREEN_STRS = 100,
};
static int16 ms_nCurrentTextLine;
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:
static void DebugInitTextBuffer();
static void DebugDisplayTextBuffer();
static void DebugAddText(const char *str);
// custom
static void PrintAt(const char *str, int x, int y);
static void DisplayScreenStrings();
};
extern bool gbDebugStuffInRelease;

View File

@ -5,10 +5,13 @@
#include "World.h"
#include "Wanted.h"
#include "EventList.h"
#include "Messages.h"
#include "Text.h"
#include "main.h"
int32 CEventList::ms_nFirstFreeSlotIndex;
//CEvent gaEvent[NUMEVENTS];
CEvent *gaEvent = (CEvent*)0x6EF830;
CEvent gaEvent[NUMEVENTS];
//CEvent *gaEvent = (CEvent*)0x6EF830;
enum
{
@ -207,6 +210,18 @@ CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCar
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)
return;

View File

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

View File

@ -1,16 +1,286 @@
#include "common.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"
CFireManager &gFireManager = *(CFireManager*)0x8F31D0;
WRAPPER void CFire::Extinguish(void) { EAXJMP(0x479D40); }
WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); }
WRAPPER CFire* CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); }
uint32 CFireManager::GetTotalActiveFires() const
CFire::CFire()
{
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)
@ -38,6 +308,44 @@ CFire* CFireManager::FindNearestFire(CVector vecPos, float* pDistance)
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
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); }
WRAPPER void CFireManager::StartFire(CVector, float, uint8) { EAXJMP(0x479500); }
WRAPPER int32 CFireManager::StartScriptFire(const CVector& pos, CEntity* culprit, float, uint8) { EAXJMP(0x479E60); }
WRAPPER bool CFireManager::IsScriptFireExtinguish(int16) { EAXJMP(0x479FC0); }
WRAPPER void CFireManager::RemoveScriptFire(int16) { EAXJMP(0x479FE0); }
WRAPPER void CFireManager::RemoveAllScriptFires(void) { EAXJMP(0x47A000); }
WRAPPER void CFireManager::SetScriptFireAudio(int16, bool) { EAXJMP(0x47A040); }
int32
CFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, bool propagation)
{
CFire *fire;
CPed *ped = (CPed *)target;
CVehicle *veh = (CVehicle *)target;
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
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(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

View File

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

View File

@ -181,6 +181,7 @@ ScaleAndCenterX(float x)
#endif
#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS)
#ifdef PS2_LIKE_MENU
#define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \
do { \
@ -235,67 +236,100 @@ ScaleAndCenterX(float x)
m_nHoverOption = HOVEROPTION_NOT_HOVERING; \
} while(0)
#define ScrollUpListByOne() \
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)
// --- Functions not in the game/inlined starts
#define ScrollDownListByOne() \
do { \
if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) { \
if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) { \
m_nSelectedListRow++; \
m_nFirstVisibleRowOnList++; \
m_nCurListItemY += LIST_HEIGHT / m_nTotalListRow; \
} \
} else { \
if (m_nSelectedListRow < m_nTotalListRow - 1) { \
m_nSelectedListRow++; \
} \
} \
} while(0)
inline void
CMenuManager::ScrollUpListByOne()
{
if (m_nSelectedListRow == m_nFirstVisibleRowOnList) {
if (m_nFirstVisibleRowOnList > 0) {
m_nSelectedListRow--;
m_nFirstVisibleRowOnList--;
m_nCurListItemY -= LIST_HEIGHT / m_nTotalListRow;
}
} else {
m_nSelectedListRow--;
}
}
#define PageUpList(playSoundOnSuccess) \
do { \
if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) { \
if (m_nFirstVisibleRowOnList > 0) { \
if(playSoundOnSuccess) \
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); \
\
m_nFirstVisibleRowOnList = max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW); \
m_nSelectedListRow = min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1); \
} else { \
m_nFirstVisibleRowOnList = 0; \
m_nSelectedListRow = 0; \
} \
m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList; \
} \
} while(0)
inline void
CMenuManager::ScrollDownListByOne()
{
if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) {
if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) {
m_nSelectedListRow++;
m_nFirstVisibleRowOnList++;
m_nCurListItemY += LIST_HEIGHT / m_nTotalListRow;
}
} else {
if (m_nSelectedListRow < m_nTotalListRow - 1) {
m_nSelectedListRow++;
}
}
}
#define PageDownList(playSoundOnSuccess) \
do { \
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; \
} \
} while(0)
inline void
CMenuManager::PageUpList(bool playSoundOnSuccess)
{
if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) {
if (m_nFirstVisibleRowOnList > 0) {
if(playSoundOnSuccess)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0);
m_nFirstVisibleRowOnList = max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW);
m_nSelectedListRow = min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1);
} else {
m_nFirstVisibleRowOnList = 0;
m_nSelectedListRow = 0;
}
m_nCurListItemY = (LIST_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
}
}
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
CMenuManager::BuildStatLine(char *text, void *stat, uint8 aFloat, void *stat2)
@ -1173,7 +1207,6 @@ void CMenuManager::DrawFrontEnd()
bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT };
bbTabCount = 6;
}
m_nCurrScreen = MENUPAGE_NEW_GAME;
} else {
if (bbTabCount != 8) {
bbNames[0] = { "FEB_STA",MENUPAGE_STATS };
@ -1186,8 +1219,8 @@ void CMenuManager::DrawFrontEnd()
bbNames[7] = { "FESZ_QU",MENUPAGE_EXIT };
bbTabCount = 8;
}
m_nCurrScreen = MENUPAGE_STATS;
}
m_nCurrScreen = bbNames[0].screenId;
bottomBarActive = true;
curBottomBarOption = 0;
}
@ -1285,7 +1318,6 @@ void CMenuManager::DrawFrontEndNormal()
eFrontendSprites currentSprite;
switch (m_nCurrScreen) {
case MENUPAGE_STATS:
case MENUPAGE_NEW_GAME:
case MENUPAGE_START_MENU:
case MENUPAGE_PAUSE_MENU:
case MENUPAGE_EXIT:
@ -1315,7 +1347,7 @@ void CMenuManager::DrawFrontEndNormal()
currentSprite = FE_ICONCONTROLS;
break;
default:
/* actually MENUPAGE_NEW_GAME too*/
/*case MENUPAGE_NEW_GAME: */
/*case MENUPAGE_BRIEFS: */
currentSprite = FE_ICONBRIEF;
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));
if (m_nMenuFadeAlpha < 255) {
static int LastFade = 0;
static uint32 LastFade = 0;
if (m_nMenuFadeAlpha <= 0 && reverseAlpha) {
reverseAlpha = false;
ChangeScreen(pendingScreen, pendingOption, true, false);
} else if(CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 10){
} else {
if (!reverseAlpha)
m_nMenuFadeAlpha += 20;
m_nMenuFadeAlpha += min((CTimer::GetTimeInMillisecondsPauseMode() - LastFade) / 33.0f, 1.0f) * 20.0f;
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();
}
@ -1537,12 +1569,18 @@ void CMenuManager::DrawFrontEndNormal()
}
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){
m_nMenuFadeAlpha += 20;
LastFade = CTimer::GetTimeInMillisecondsPauseMode();
}
#endif
if (m_nMenuFadeAlpha > 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
void CMenuManager::Process(void)
{
m_bMenuNotProcessed = false;
m_bMenuStateChanged = false;
if (!m_bSaveMenuActive && TheCamera.GetScreenFadeStatus() != FADE_0)
return;
@ -2701,6 +2739,8 @@ CMenuManager::ProcessButtonPresses(void)
if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0);
bottomBarActive = false;
// If there's a menu change with fade ongoing, finish it now
if (reverseAlpha)
m_nMenuFadeAlpha = 0;
return;
@ -3116,51 +3156,43 @@ CMenuManager::ProcessButtonPresses(void)
if (goBack) {
CMenuManager::ResetHelperText();
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) {
CMenuManager::m_PrefsVsync = CMenuManager::m_PrefsVsyncDisp;
}
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
) {
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();
OutputDebugString("FRONTEND AUDIO TRACK STOPPED");
}
#endif
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];
#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 ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) {
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();
}
ThingsToDoBeforeLeavingPage();
#ifdef PS2_LIKE_MENU
if (!bottomBarActive &&
@ -3168,10 +3200,8 @@ CMenuManager::ProcessButtonPresses(void)
bottomBarActive = true;
} else
#endif
{
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?!
@ -3512,11 +3542,16 @@ WRAPPER void CMenuManager::SwitchMenuOnAndOff() { EAXJMP(0x488790); }
#else
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) {
if (!m_bMenuActive)
m_bMenuActive = true;
m_bMenuActive = !m_bMenuActive;
if (m_bShutDownFrontEndRequested)
m_bMenuActive = false;
@ -3525,8 +3560,13 @@ void CMenuManager::SwitchMenuOnAndOff()
if (m_bMenuActive) {
CTimer::StartUserPause();
}
else {
} else {
#ifdef PS2_LIKE_MENU
bottomBarActive = false;
#endif
#ifdef FIX_BUGS
ThingsToDoBeforeLeavingPage();
#endif
ShutdownJustMenu();
SaveSettings();
m_bStartUpFrontEndRequested = false;
@ -3553,7 +3593,7 @@ void CMenuManager::SwitchMenuOnAndOff()
PcSaveHelper.PopulateSlotInfo();
m_nCurrOption = 0;
}
/* // Unused?
/* // PS2 leftover?
if (m_nCurrScreen != MENUPAGE_SOUND_SETTINGS && gMusicPlaying)
{
DMAudio.StopFrontEndTrack();
@ -3561,8 +3601,8 @@ void CMenuManager::SwitchMenuOnAndOff()
gMusicPlaying = 0;
}
*/
if (!m_bMenuActive)
m_bMenuNotProcessed = true;
if (m_bMenuActive != menuWasActive)
m_bMenuStateChanged = true;
m_bStartUpFrontEndRequested = false;
m_bShutDownFrontEndRequested = false;

View File

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

View File

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

View File

@ -5,6 +5,10 @@
#pragma warning( pop )
#include "common.h"
#ifdef XINPUT
#include <Xinput.h>
#pragma comment( lib, "Xinput9_1_0.lib" )
#endif
#include "patcher.h"
#include "Pad.h"
#include "ControllerConfig.h"
@ -547,12 +551,78 @@ void CPad::AddToPCCheatString(char c)
#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)
{
bool bUpdate = true;
GetPad(0)->UpdateMouse();
#ifdef XINPUT
GetPad(0)->AffectFromXinput(0);
GetPad(1)->AffectFromXinput(1);
#else
CapturePad(0);
#endif
ControlsManager.ClearSimButtonPressCheckers();
@ -565,10 +635,13 @@ void CPad::UpdatePads(void)
if ( bUpdate )
{
GetPad(0)->Update(0);
GetPad(1)->Update(0);
}
#if defined(MASTER) && !defined(XINPUT)
GetPad(1)->NewState.Clear();
GetPad(1)->OldState.Clear();
#endif
OldKeyState = NewKeyState;
NewKeyState = TempKeyState;

View File

@ -247,6 +247,10 @@ public:
static char *EditString(char *pStr, int32 nSize);
static int32 *EditCodesForControls(int32 *pRsKeys, int32 nSize);
#ifdef XINPUT
void AffectFromXinput(uint32 pad);
#endif
// mouse
bool GetLeftMouseJustDown() { return !!(NewMouseControllerState.LMB && !OldMouseControllerState.LMB); }
bool GetRightMouseJustDown() { return !!(NewMouseControllerState.RMB && !OldMouseControllerState.RMB); }
@ -399,6 +403,8 @@ public:
bool GetLeftShoulder2JustDown() { return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); }
bool GetRightShoulder1JustDown() { return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); }
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 GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); }
bool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); }
@ -422,6 +428,10 @@ public:
bool GetLeftShoulder2(void) { return !!NewState.LeftShoulder2; }
bool GetRightShoulder1(void) { return !!NewState.RightShoulder1; }
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; }
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;
}
#include <new>
class CPlaceable_ : public CPlaceable
{
public:

View File

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

View File

@ -2,7 +2,7 @@
class CTimer
{
public:
static uint32 &m_snTimeInMilliseconds;
static uint32 &m_snTimeInMillisecondsPauseMode;
static uint32 &m_snTimeInMillisecondsNonClipped;
@ -11,19 +11,20 @@ public:
static float &ms_fTimeScale;
static float &ms_fTimeStep;
static float &ms_fTimeStepNonClipped;
public:
static bool &m_UserPause;
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 float GetTimeStepInSeconds() { return ms_fTimeStep / 50.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 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 uint32 GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; }
static const uint32 &GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; }
static void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; }
static uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; }
static void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; }
@ -31,7 +32,7 @@ public:
static void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; }
static uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; }
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 bool GetIsPaused() { return m_UserPause || m_CodePause; }

View File

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

View File

@ -60,8 +60,6 @@ class CWorld
static uint16 &ms_nCurrentScanCode;
public:
static CColPoint& ms_testSpherePoint;
static uint8 &PlayerInFocus;
static CPlayerInfo (&Players)[NUMPLAYERS];
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 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 void FindObjectsInRangeSectorList(CPtrList&, CVector&, float, bool, short*, short, CEntity**);
static void FindObjectsInRange(CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool);
@ -142,6 +140,8 @@ public:
static void Process();
};
extern CColPoint *gaTempSphereColPoints;
class CPlayerPed;
class CVehicle;
CPlayerPed *FindPlayerPed(void);

View File

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

View File

@ -8,9 +8,12 @@
#pragma warning(disable: 4996) // POSIX names
#include <stdint.h>
#include <string.h>
#include <math.h>
//#include <assert.h>
#include <new>
#ifdef WITHWINDOWS
#include <Windows.h>
#endif
#ifdef WITHD3D
#include <windows.h>
@ -30,6 +33,16 @@
#undef near
#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 int8_t int8;
typedef uint16_t uint16;

View File

@ -101,6 +101,8 @@ enum Config {
NUMPEDGROUPS = 31,
NUMMODELSPERPEDGROUP = 8,
NUMROADBLOCKS = 600,
NUMVISIBLEENTITIES = 2000,
NUMINVISIBLEENTITIES = 150,
@ -171,10 +173,12 @@ enum Config {
#endif
#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
#define XINPUT
#define KANGAROO_CHEAT
#define REGISTER_START_BUTTON // currently only in menu sadly. resumes the game
// Hud, frontend and radar
#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
#define ANIMATE_PED_COL_MODEL
#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 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
DoRWStuffEndOfFrame(void)
{
CDebug::DisplayScreenStrings(); // custom
CDebug::DebugDisplayTextBuffer();
// FlushObrsPrintfs();
RwCameraEndUpdate(Scene.camera);

View File

@ -6,13 +6,7 @@
#define VARJMP(a) { _asm jmp a }
#define WRAPARG(a) UNREFERENCED_PARAMETER(a)
#define NOVMT __declspec(novtable)
#define SETVMT(a) *((DWORD_PTR*)this) = (DWORD_PTR)a
#include <algorithm>
#include <vector>
#include "common.h"
#include <string.h> //memset
enum
{
@ -103,72 +97,36 @@ isVC(void)
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
Patch(AT address, T value)
{
DWORD dwProtect[2];
VirtualProtect((void*)address, sizeof(T), PAGE_EXECUTE_READWRITE, &dwProtect[0]);
Protect_internal((uint32)address, sizeof(T));
*(T*)address = value;
VirtualProtect((void*)address, sizeof(T), dwProtect[0], &dwProtect[1]);
Unprotect_internal();
}
template<typename AT> inline void
Nop(AT address, unsigned int nCount)
{
DWORD dwProtect[2];
VirtualProtect((void*)address, nCount, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
Protect_internal((uint32)address, 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
InjectHook(AT address, HT hook, unsigned int nType=PATCH_NOTHING)
{
if(std::any_of(usedAddresses.begin(), usedAddresses.end(),
[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;
uint32 uiHook;
_asm
{
mov eax, hook
mov dwHook, eax
mov uiHook, eax
}
*(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]);
InjectHook_internal((uint32)address, uiHook, nType);
}
inline void ExtractCall(void *dst, uint32_t a)

View File

@ -20,12 +20,64 @@
#include "debugmenu_public.h"
#include "Particle.h"
#include "Console.h"
#include "Debug.h"
#include <algorithm>
#include <vector>
#include <list>
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;
DebugMenuAPI gDebugMenuAPI;
@ -114,13 +166,16 @@ SpawnCar(int id)
CStreaming::LoadAllRequestedModels(false);
if(CStreaming::HasModelLoaded(id)){
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)
return;
}
CVehicle *v;
if(CModelInfo::IsBoatModel(id))
return;
v = new CBoat(id, RANDOM_VEHICLE);
else
v = new CAutomobile(id, RANDOM_VEHICLE);
@ -130,7 +185,11 @@ SpawnCar(int id)
if(carCol2)
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().z += 4.0f;
v->SetOrientation(0.0f, 0.0f, 3.49f);
v->m_status = STATUS_ABANDONED;
@ -197,6 +256,12 @@ PlaceOnRoad(void)
((CAutomobile*)veh)->PlaceOnRoadProperly();
}
static void
ResetCamStatics(void)
{
TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;
}
static const char *carnames[] = {
"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",
@ -359,6 +424,16 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
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");
}
}
@ -433,7 +508,8 @@ void re3_debug(const char *format, ...)
vsprintf_s(re3_buff, re3_buffsize, format, 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, ...)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,9 @@
#include "Vehicle.h"
#include "RpAnimBlend.h"
#include "General.h"
#include "ZoneCull.h"
#include "PathFind.h"
#include "RoadBlocks.h"
WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); }
@ -58,11 +61,16 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
m_bIsDisabledCop = false;
field_1356 = 0;
m_attackTimer = 0;
field_1351 = 0;
m_bBeatingSuspect = false;
m_bZoneDisabledButClose = false;
m_bZoneDisabled = false;
field_1364 = -1;
m_pPointGunAt = nil;
// VC also initializes in here, but it keeps object
#ifdef FIX_BUGS
m_wRoadblockNode = -1;
#endif
}
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
CCopPed::SetPursuit(bool iMayAlreadyBeInPursuit)
CCopPed::SetPursuit(bool ignoreCopLimit)
{
CWanted *wanted = FindPlayerPed()->m_pWanted;
if (m_bIsInPursuit || !IsPedInControl())
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) {
if (!wanted->m_pCops[i]) {
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
{
public:
@ -290,4 +568,5 @@ STARTPATCHES
InjectHook(0x4C27D0, &CCopPed::SetPursuit, PATCH_JUMP);
InjectHook(0x4C2C90, &CCopPed::ArrestPlayer, PATCH_JUMP);
InjectHook(0x4C26A0, &CCopPed::ScanForCrimes, PATCH_JUMP);
InjectHook(0x4C1B50, &CCopPed::CopAI, PATCH_JUMP);
ENDPATCHES

View File

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

View File

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

View File

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

View File

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

View File

@ -576,7 +576,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
}
// Yeah, float
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) {
int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000);

View File

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

View File

@ -115,47 +115,43 @@ void CHud::Draw()
return;
if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) {
bool Mode_RunAround = 0;
bool Mode_FirstPerson = 0;
bool DrawCrossHair = 0;
bool DrawCrossHairPC = 0;
int32 WeaponType = FindPlayerPed()->m_weapons[FindPlayerPed()->m_currentWeapon].m_eWeaponType;
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)
Mode_FirstPerson = 1;
if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)
Mode_RunAround = 1;
if (Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON)
DrawCrossHair = 1;
if (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)
DrawCrossHairPC = 1;
/*
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 ((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);
int32 SpriteBrightLikeADiamond = SpriteBrightness + 1;
if (SpriteBrightLikeADiamond > 30)
SpriteBrightLikeADiamond = 30;
SpriteBrightness = SpriteBrightLikeADiamond;
SpriteBrightness = min(SpriteBrightness+1, 30);
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);
CRect rect;
if (DrawCrossHairPC && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()) {
#ifndef ASPECT_RATIO_SCALE
if (Mode_RunAround && TheCamera.Cams->Using3rdPersonMouseCam()) {
float f3rdX = SCREEN_WIDTH * TheCamera.m_f3rdPersonCHairMultX;
float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY;
#else
if (Mode_RunAround && TheCamera.Cams->Using3rdPersonMouseCam()) {
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);
#endif
@ -179,14 +175,14 @@ void CHud::Draw()
else {
if (Mode == CCam::MODE_M16_1STPERSON ||
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.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f);
rect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f);
rect.bottom = (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(32.0f);
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.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(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));
}
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(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (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);
}
else {
// Sniper
rect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(210.0f);
rect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(210.0f);
rect.right = SCREEN_WIDTH / 2;

View File

@ -645,6 +645,9 @@ CRenderer::ScanWorld(void)
m_loadingPriority = false;
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){
CRect rect;
int x1, x2, y1, y2;
@ -756,6 +759,9 @@ CRenderer::RequestObjectsInFrustum(void)
RwV3dTransformPoints((RwV3d*)vectors, (RwV3d*)vectors, 9, cammatrix);
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){
CRect rect;
int x1, x2, y1, y2;

View File

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

View File

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

View File

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

View File

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

View File

@ -1034,6 +1034,7 @@ bool CHeli::HasCatalinaBeenShotDown(void) { return CatalinaHasBeenShotDown; }
void CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; }
#include <new>
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::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatus == CESNA_STATUS_DESTROYED; }
#include <new>
class CPlane_ : public CPlane
{

View File

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

View File

@ -33,6 +33,7 @@ void CVehicle::operator delete(void *p, int handle) { CPools::GetVehiclePool()->
WRAPPER bool CVehicle::ShufflePassengersToMakeSpace(void) { EAXJMP(0x5528A0); }
// or Weapon.cpp?
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)
{

View File

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