From 04c9affe2e97697346c431b773230332e7bcebfb Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 12 Apr 2020 12:06:33 +0300 Subject: [PATCH 001/123] scene init --- src/control/SceneEdit.cpp | 322 +++++++++++++++++++++++++++++++++++++- src/control/SceneEdit.h | 88 ++++++++++- src/core/Game.cpp | 2 +- 3 files changed, 398 insertions(+), 14 deletions(-) diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index 3e55d431..f7e17dcc 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -2,11 +2,319 @@ #include "patcher.h" #include "SceneEdit.h" -bool &CSceneEdit::m_bEditOn = *(bool*)0x95CD77; -int32 &CSceneEdit::m_bCameraFollowActor = *(int*)0x940590; -bool &CSceneEdit::m_bRecording = *(bool*)0x95CD1F; -CVector &CSceneEdit::m_vecCurrentPosition = *(CVector*)0x943064; -CVector &CSceneEdit::m_vecCamHeading = *(CVector*)0x942F8C; +#include "Camera.h" +#include "FileMgr.h" +#include "Font.h" +#include "ModelIndices.h" +#include "ModelInfo.h" +#include "Ped.h" +#include "Population.h" +#include "Text.h" +#include "Vehicle.h" +#include "World.h" -WRAPPER void CSceneEdit::Update(void) { EAXJMP(0x585570); } -WRAPPER void CSceneEdit::Init(void) { EAXJMP(0x585170); } +bool CSceneEdit::m_bEditOn; +int32 CSceneEdit::m_bCameraFollowActor; +bool CSceneEdit::m_bRecording; +CVector CSceneEdit::m_vecCurrentPosition; +CVector CSceneEdit::m_vecCamHeading; +CVector CSceneEdit::m_vecGotoPosition; +int32 CSceneEdit::m_nVehicle; +int32 CSceneEdit::m_nVehicle2; +int32 CSceneEdit::m_nActor; +int32 CSceneEdit::m_nActor2; +int32 CSceneEdit::m_nVehiclemodelId; +int32 CSceneEdit::m_nPedmodelId; +int16 CSceneEdit::m_nCurrentMovieCommand; +int16 CSceneEdit::m_nNumActors; +int16 CSceneEdit::m_nNumMovieCommands; +int16 CSceneEdit::m_nCurrentCommand; +int16 CSceneEdit::m_nCurrentVehicle; +bool CSceneEdit::m_bCommandActive; +int16 CSceneEdit::m_nNumVehicles; +CPed* CSceneEdit::pActors[NUM_ACTORS_IN_MOVIE]; +CVehicle* CSceneEdit::pVehicles[NUM_VEHICLES_IN_MOVIE]; +bool CSceneEdit::m_bDrawGotoArrow; +CMovieCommand CSceneEdit::Movie[NUM_COMMANDS_IN_MOVIE]; + +#define SHADOW_OFFSET (2.0f) +#define ACTION_MESSAGE_X_RIGHT (60.0f) +#define ACTION_MESSAGE_Y (8.0f) +#define SELECTED_MESSAGE_X_RIGHT (60.0f) +#define SELECTED_MESSAGE_Y (248.0f) +#define COMMAND_NAME_X_RIGHT (60.0f) +#define COMMAND_NAME_Y (38.0f) +#define COMMAND_NAME_HEIGHT (16.0f) + +#define NUM_COMMANDS_TO_DRAW (9) + +static const char* pCommandStrings[] = { + "do-nothing", "New Actor", "Move Actor", "Select Actor", "Delete Actor", + "New Vehicle", "Move Vehicle", "Select Vehicle", "Delete Vehicle", "Give Weapon", + "Goto", "Goto (wait)", "Get In Car", "Get Out Car", "Kill", + "Flee", "Wait", "Position Camera", "Set Camera Target", "Select Camera Mode", + "Save Movie", "Load Movie", "Play Movie", "END" +}; + +static_assert(ARRAY_SIZE(pCommandStrings) == CSceneEdit::MOVIE_TOTAL_COMMANDS, "Scene edit: not all commands have names"); + +static int32 NextValidModelId(int32 mi, int32 step) +{ + int32 result = -1; + int32 i = mi; + while (result == -1) { + if (i < 0 || i > 5500) { + i = -i; + continue; + } + CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(i); + CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo; + if (!i) + continue; + if (pInfo->m_type == MITYPE_PED || + pInfo->m_type == MITYPE_VEHICLE && +#ifdef FIX_BUGS + (pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR || pVehicleInfo->m_vehicleType == VEHICLE_TYPE_BOAT)) +#else // && and || priority failure it seems + pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR || pVehicleInfo->m_vehicleType == VEHICLE_TYPE_BOAT) +#endif + result = i; + } + return result; +} + +void CSceneEdit::LoadMovie(void) +{ + ReInitialise(); + CFileMgr::SetDir("DATA"); + int fid = CFileMgr::OpenFile("movie.dat", "r"); +#ifdef FIX_BUGS + if (fid > 0) +#endif + { + CFileMgr::Read(fid, (char*)Movie, sizeof(Movie)); + CFileMgr::Read(fid, (char*)m_nNumMovieCommands, sizeof(m_nNumMovieCommands)); + CFileMgr::CloseFile(fid); + } + CFileMgr::SetDir(""); + m_bCommandActive = false; +} + +void CSceneEdit::SaveMovie(void) +{ + CFileMgr::SetDir("DATA"); + int fid = CFileMgr::OpenFileForWriting("movie.dat"); + if (fid >= 0) { + CFileMgr::Write(fid, (char*)Movie, sizeof(Movie)); + CFileMgr::Write(fid, (char*)m_nNumMovieCommands, sizeof(m_nNumMovieCommands)); + CFileMgr::CloseFile(fid); + } + CFileMgr::SetDir(""); + m_bCommandActive = false; +} + +void CSceneEdit::Initialise(void) +{ + m_nActor = -1; + m_nActor2 = -1; + m_nVehicle = -1; + m_nVehicle2 = -1; + m_nCurrentCommand = MOVIE_NEW_ACTOR; + m_nVehiclemodelId = MI_INFERNUS; + m_nPedmodelId = MI_MALE01; + m_nNumVehicles = 0; + m_nNumActors = 0; + m_nNumMovieCommands = 0; + m_bCommandActive = false; + m_bRecording = true; + m_bEditOn = false; + for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) + pActors[i] = nil; + for (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) + pVehicles[i] = nil; + m_vecCamHeading = TheCamera.Cams[TheCamera.ActiveCam].Front; + m_vecGotoPosition = CVector(0.0f, 0.0f, 0.0f); + m_bCameraFollowActor = false; + TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true; + m_bDrawGotoArrow = false; +} + +void CSceneEdit::InitPlayback(void) +{ + m_nVehiclemodelId = MI_INFERNUS; + m_nPedmodelId = MI_MALE01; + m_bCommandActive = false; + m_nNumActors = 0; + m_nNumVehicles = 0; + m_nActor = -1; + m_nActor2 = -1; + m_nVehicle = -1; + m_nVehicle2 = -1; + TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true; + m_vecCamHeading = TheCamera.Cams[TheCamera.ActiveCam].Front; + for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) { + if (pActors[i]) { + CPopulation::RemovePed(pActors[i]); + pActors[i] = nil; + } + } + for (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) { + if (pVehicles[i]) { + CWorld::Remove(pVehicles[i]); + delete pVehicles[i]; + pVehicles[i] = nil; + } + } + m_vecGotoPosition = CVector(0.0f, 0.0f, 0.0f); + m_nCurrentVehicle = 0; + m_nCurrentMovieCommand = MOVIE_DO_NOTHING; + m_bDrawGotoArrow = false; +} + +void CSceneEdit::ReInitialise(void) +{ + m_nVehiclemodelId = MI_INFERNUS; + m_nPedmodelId = MI_MALE01; + m_nCurrentCommand = MOVIE_NEW_ACTOR; + m_bEditOn = true; + m_bRecording = true; + m_bCommandActive = false; + m_nActor = -1; + m_nActor2 = -1; + m_nVehicle = -1; + m_nVehicle2 = -1; + m_nNumMovieCommands = 0; + m_nCurrentMovieCommand = MOVIE_DO_NOTHING; + m_nNumActors = 0; + m_nNumVehicles = 0; + for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) { + if (pActors[i]) { + CPopulation::RemovePed(pActors[i]); + pActors[i] = nil; + } + } + for (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) { + if (pVehicles[i]) { + CWorld::Remove(pVehicles[i]); + delete pVehicles[i]; + pVehicles[i] = nil; + } + } + for (int i = 0; i < NUM_COMMANDS_IN_MOVIE; i++) { + Movie[i].m_nCommandId = MOVIE_DO_NOTHING; + Movie[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f); + Movie[i].m_vecCamera = CVector(0.0f, 0.0f, 0.0f); + Movie[i].m_nActorId = -1; + Movie[i].m_nActor2Id = -1; + Movie[i].m_nVehicleId = -1; + Movie[i].m_nModelIndex = 0; + } + m_vecGotoPosition = CVector(0.0f, 0.0f, 0.0f); + m_bDrawGotoArrow = false; +} + +void CSceneEdit::Update(void) +{ + if (!m_bEditOn) + return; + if (m_bRecording) + ProcessCommand(); + else { + if (m_bCameraFollowActor && m_nActor != -1) { + if (pActors[m_nActor]->bInVehicle) + TheCamera.TakeControl(pActors[m_nActor]->m_pMyVehicle, CCam::MODE_BEHINDCAR, JUMP_CUT, CAMCONTROL_SCRIPT); + else + TheCamera.TakeControl(pActors[m_nActor], CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT); + } + PlayBack(); + } +} + +void CSceneEdit::Draw(void) +{ + char str[200]; + wchar wstr[200]; + if (TheCamera.m_WideScreenOn) + return; + CFont::SetPropOff(); + CFont::SetBackgroundOff(); + CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); + CFont::SetCentreOn(); + CFont::SetRightJustifyOn(); + CFont::SetRightJustifyWrap(0.0f); + CFont::SetBackGroundOnlyTextOff(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetPropOff(); + sprintf(str, "Action"); + AsciiToUnicode(str, wstr); + CFont::SetColor(CRGBA(0, 0, 0, 0)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT + SHADOW_OFFSET), SCREEN_SCALE_Y(ACTION_MESSAGE_Y + SHADOW_OFFSET), wstr); + CFont::SetColor(CRGBA(193, 164, 120, 255)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(ACTION_MESSAGE_Y), wstr); + sprintf(str, "Selected"); + AsciiToUnicode(str, wstr); + CFont::SetColor(CRGBA(0, 0, 0, 0)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT + SHADOW_OFFSET), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y + SHADOW_OFFSET), wstr); + CFont::SetColor(CRGBA(193, 164, 120, 255)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y), wstr); + CFont::SetCentreOff(); + CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.7f)); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetColor(CRGBA(0, 0, 0, 0)); + for (int i = 0; i < NUM_COMMANDS_TO_DRAW; i++) { + int16 nCommandDrawn = m_nCurrentCommand + i - NUM_COMMANDS_TO_DRAW / 2; + if (nCommandDrawn >= MOVIE_TOTAL_COMMANDS) + nCommandDrawn -= (MOVIE_TOTAL_COMMANDS - 1); + if (nCommandDrawn <= MOVIE_DO_NOTHING) + nCommandDrawn += (MOVIE_TOTAL_COMMANDS - 1); + sprintf(str, pCommandStrings[nCommandDrawn]); + AsciiToUnicode(str, wstr); + CFont::SetColor(CRGBA(0, 0, 0, 0)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT + SHADOW_OFFSET), SCREEN_SCALE_Y(COMMAND_NAME_Y + SHADOW_OFFSET + i * COMMAND_NAME_HEIGHT), wstr); + if (nCommandDrawn == m_nCurrentCommand) + CFont::SetColor(CRGBA(156, 91, 40, 255)); + else + CFont::SetColor(CRGBA(193, 164, 120, 255)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT), SCREEN_SCALE_Y(COMMAND_NAME_Y + i * COMMAND_NAME_HEIGHT), wstr); + } +} + +void CSceneEdit::ProcessCommand(void) +{ + if (!m_bCommandActive) + return; + switch (m_nCurrentCommand) { + case MOVIE_DO_NOTHING: + m_bCommandActive = false; + break; + } +} + +void CSceneEdit::PlayBack(void) +{ + +} + +void CSceneEdit::ClearForNewCommand(void) +{ + +} +void CSceneEdit::SelectActor(void) +{ + +} + +void CSceneEdit::SelectActor2(void) +{ + +} + +void CSceneEdit::SelectVehicle(void) +{ + +} + +void CSceneEdit::SelectWeapon(void) +{ + +} \ No newline at end of file diff --git a/src/control/SceneEdit.h b/src/control/SceneEdit.h index 0de72c19..66ec5735 100644 --- a/src/control/SceneEdit.h +++ b/src/control/SceneEdit.h @@ -1,14 +1,90 @@ #pragma once +class CPed; +class CVehicle; + +struct CMovieCommand +{ + int32 m_nCommandId; + CVector m_vecPosition; + CVector m_vecCamera; + int16 m_nActorId; + int16 m_nActor2Id; + int16 m_nVehicleId; + int16 m_nModelIndex; +}; + class CSceneEdit { public: - static bool &m_bEditOn; - static int32 &m_bCameraFollowActor; - static bool &m_bRecording; - static CVector &m_vecCurrentPosition; - static CVector &m_vecCamHeading; + enum { + MOVIE_DO_NOTHING = 0, + MOVIE_NEW_ACTOR, + MOVIE_MOVE_ACTOR, + MOVIE_SELECT_ACTOR, + MOVIE_DELETE_ACTOR, + MOVIE_NEW_VEHICLE, + MOVIE_MOVE_VEHICLE, + MOVIE_SELECT_VEHICLE, + MOVIE_DELETE_VEHICLE, + MOVIE_GIVE_WEAPON, + MOVIE_GOTO, + MOVIE_GOTO_WAIT, + MOVIE_GET_IN_CAR, + MOVIE_GET_OUT_CAR, + MOVIE_KILL, + MOVIE_FLEE, + MOVIE_WAIT, + MOVIE_POSITION_CAMERA, + MOVIE_SET_CAMERA_TARGET, + MOVIE_SELECT_CAMERA_MODE, + MOVIE_SAVE_MOVIE, + MOVIE_LOAD_MOVIE, + MOVIE_PLAY_MOVIE, + MOVIE_END, + MOVIE_TOTAL_COMMANDS + }; + enum { + NUM_ACTORS_IN_MOVIE = 5, + NUM_VEHICLES_IN_MOVIE = 5, + NUM_COMMANDS_IN_MOVIE = 20 + }; + static int32 m_bCameraFollowActor; + static CVector m_vecCurrentPosition; + static CVector m_vecCamHeading; + static CVector m_vecGotoPosition; + static int32 m_nVehicle; + static int32 m_nVehicle2; + static int32 m_nActor; + static int32 m_nActor2; + static int32 m_nVehiclemodelId; + static int32 m_nPedmodelId; + static int16 m_nCurrentMovieCommand; + static int16 m_nCurrentCommand; + static int16 m_nCurrentVehicle; + static bool m_bEditOn; + static bool m_bRecording; + static bool m_bCommandActive; + static int16 m_nNumActors; + static int16 m_nNumVehicles; + static int16 m_nNumMovieCommands; + static CPed* pActors[NUM_ACTORS_IN_MOVIE]; + static CVehicle* pVehicles[NUM_VEHICLES_IN_MOVIE]; + static bool m_bDrawGotoArrow; + static CMovieCommand Movie[NUM_COMMANDS_IN_MOVIE]; + static void LoadMovie(void); + static void SaveMovie(void); + static void Initialise(void); + static void InitPlayback(void); + static void ReInitialise(void); static void Update(void); - static void Init(void); + static void Draw(void); + static void ProcessCommand(void); + static void PlayBack(void); + static void ClearForNewCommand(void); + static void SelectActor(void); + static void SelectActor2(void); + static void SelectVehicle(void); + static void SelectWeapon(void); }; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index daac3ec5..fe747ac1 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -350,7 +350,7 @@ bool CGame::Initialise(const char* datFile) CAntennas::Init(); CGlass::Init(); gPhoneInfo.Initialise(); - CSceneEdit::Init(); + CSceneEdit::Initialise(); LoadingScreen("Loading the Game", "Load scripts", nil); CTheScripts::Init(); CGangs::Initialise(); From cb85091d34dd92695a075a13ff129ae568c0acda Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Mon, 13 Apr 2020 21:50:56 +0300 Subject: [PATCH 002/123] scene edit --- src/control/SceneEdit.cpp | 813 +++++++++++++++++++++++++++++++++++++- src/control/SceneEdit.h | 7 +- src/core/Pad.cpp | 4 +- src/core/main.cpp | 3 +- src/core/re3.cpp | 4 + 5 files changed, 806 insertions(+), 25 deletions(-) diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index f7e17dcc..251f093f 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -2,15 +2,22 @@ #include "patcher.h" #include "SceneEdit.h" +#include "Automobile.h" #include "Camera.h" +#include "CarCtrl.h" +#include "CivilianPed.h" #include "FileMgr.h" #include "Font.h" #include "ModelIndices.h" #include "ModelInfo.h" +#include "Pad.h" #include "Ped.h" #include "Population.h" #include "Text.h" +#include "Timecycle.h" +#include "Streaming.h" #include "Vehicle.h" +#include "WeaponInfo.h" #include "World.h" bool CSceneEdit::m_bEditOn; @@ -30,7 +37,12 @@ int16 CSceneEdit::m_nNumActors; int16 CSceneEdit::m_nNumMovieCommands; int16 CSceneEdit::m_nCurrentCommand; int16 CSceneEdit::m_nCurrentVehicle; +int16 CSceneEdit::m_nCurrentActor; +int16 CSceneEdit::m_nWeaponType; bool CSceneEdit::m_bCommandActive; +bool CSceneEdit::m_bActorSelected; +bool CSceneEdit::m_bActor2Selected; +bool CSceneEdit::m_bVehicleSelected; int16 CSceneEdit::m_nNumVehicles; CPed* CSceneEdit::pActors[NUM_ACTORS_IN_MOVIE]; CVehicle* CSceneEdit::pVehicles[NUM_VEHICLES_IN_MOVIE]; @@ -63,19 +75,24 @@ static int32 NextValidModelId(int32 mi, int32 step) int32 result = -1; int32 i = mi; while (result == -1) { + i += step; if (i < 0 || i > 5500) { - i = -i; + step = -step; continue; } CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(i); CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo; - if (!i) + if (!pInfo) continue; - if (pInfo->m_type == MITYPE_PED || + if (pInfo->m_type == MITYPE_PED +#ifdef FIX_BUGS + && !(i >= MI_SPECIAL01 && i <= MI_SPECIAL04) +#endif + || pInfo->m_type == MITYPE_VEHICLE && #ifdef FIX_BUGS (pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR || pVehicleInfo->m_vehicleType == VEHICLE_TYPE_BOAT)) -#else // && and || priority failure it seems +#else // && and || priority failure it seems, also crashes on special models pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR || pVehicleInfo->m_vehicleType == VEHICLE_TYPE_BOAT) #endif result = i; @@ -92,8 +109,8 @@ void CSceneEdit::LoadMovie(void) if (fid > 0) #endif { - CFileMgr::Read(fid, (char*)Movie, sizeof(Movie)); - CFileMgr::Read(fid, (char*)m_nNumMovieCommands, sizeof(m_nNumMovieCommands)); + CFileMgr::Read(fid, (char*)&Movie, sizeof(Movie)); + CFileMgr::Read(fid, (char*)&m_nNumMovieCommands, sizeof(m_nNumMovieCommands)); CFileMgr::CloseFile(fid); } CFileMgr::SetDir(""); @@ -105,8 +122,8 @@ void CSceneEdit::SaveMovie(void) CFileMgr::SetDir("DATA"); int fid = CFileMgr::OpenFileForWriting("movie.dat"); if (fid >= 0) { - CFileMgr::Write(fid, (char*)Movie, sizeof(Movie)); - CFileMgr::Write(fid, (char*)m_nNumMovieCommands, sizeof(m_nNumMovieCommands)); + CFileMgr::Write(fid, (char*)&Movie, sizeof(Movie)); + CFileMgr::Write(fid, (char*)&m_nNumMovieCommands, sizeof(m_nNumMovieCommands)); CFileMgr::CloseFile(fid); } CFileMgr::SetDir(""); @@ -158,6 +175,7 @@ void CSceneEdit::InitPlayback(void) pActors[i] = nil; } } + m_nCurrentActor = 0; for (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) { if (pVehicles[i]) { CWorld::Remove(pVehicles[i]); @@ -165,8 +183,8 @@ void CSceneEdit::InitPlayback(void) pVehicles[i] = nil; } } - m_vecGotoPosition = CVector(0.0f, 0.0f, 0.0f); m_nCurrentVehicle = 0; + m_vecGotoPosition = CVector(0.0f, 0.0f, 0.0f); m_nCurrentMovieCommand = MOVIE_DO_NOTHING; m_bDrawGotoArrow = false; } @@ -236,30 +254,43 @@ void CSceneEdit::Draw(void) wchar wstr[200]; if (TheCamera.m_WideScreenOn) return; +#ifndef FIX_BUGS CFont::SetPropOff(); +#endif CFont::SetBackgroundOff(); CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); CFont::SetCentreOn(); CFont::SetRightJustifyOn(); CFont::SetRightJustifyWrap(0.0f); CFont::SetBackGroundOnlyTextOff(); +#ifdef FIX_BUGS + CFont::SetFontStyle(FONT_BANK); + CFont::SetPropOn(); + CFont::SetDropColor(CRGBA(0, 0, 0, 255)); + CFont::SetDropShadowPosition(1); +#else CFont::SetFontStyle(FONT_HEADING); CFont::SetPropOff(); +#endif sprintf(str, "Action"); AsciiToUnicode(str, wstr); CFont::SetColor(CRGBA(0, 0, 0, 0)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT + SHADOW_OFFSET), SCREEN_SCALE_Y(ACTION_MESSAGE_Y + SHADOW_OFFSET), wstr); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(ACTION_MESSAGE_Y + SHADOW_OFFSET), wstr); CFont::SetColor(CRGBA(193, 164, 120, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(ACTION_MESSAGE_Y), wstr); sprintf(str, "Selected"); AsciiToUnicode(str, wstr); CFont::SetColor(CRGBA(0, 0, 0, 0)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT + SHADOW_OFFSET), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y + SHADOW_OFFSET), wstr); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y + SHADOW_OFFSET), wstr); CFont::SetColor(CRGBA(193, 164, 120, 255)); CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y), wstr); CFont::SetCentreOff(); CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.7f)); +#ifdef FIX_BUGS + CFont::SetFontStyle(FONT_BANK); +#else CFont::SetFontStyle(FONT_HEADING); +#endif CFont::SetColor(CRGBA(0, 0, 0, 0)); for (int i = 0; i < NUM_COMMANDS_TO_DRAW; i++) { int16 nCommandDrawn = m_nCurrentCommand + i - NUM_COMMANDS_TO_DRAW / 2; @@ -270,7 +301,7 @@ void CSceneEdit::Draw(void) sprintf(str, pCommandStrings[nCommandDrawn]); AsciiToUnicode(str, wstr); CFont::SetColor(CRGBA(0, 0, 0, 0)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT + SHADOW_OFFSET), SCREEN_SCALE_Y(COMMAND_NAME_Y + SHADOW_OFFSET + i * COMMAND_NAME_HEIGHT), wstr); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(COMMAND_NAME_Y + SHADOW_OFFSET + i * COMMAND_NAME_HEIGHT), wstr); if (nCommandDrawn == m_nCurrentCommand) CFont::SetColor(CRGBA(156, 91, 40, 255)); else @@ -281,40 +312,782 @@ void CSceneEdit::Draw(void) void CSceneEdit::ProcessCommand(void) { - if (!m_bCommandActive) + if (!m_bCommandActive) { + ClearForNewCommand(); + if (CPad::GetPad(1)->GetDPadUpJustDown()) { + if (--m_nCurrentCommand == MOVIE_DO_NOTHING) + m_nCurrentCommand = MOVIE_END; + } + if (CPad::GetPad(1)->GetDPadDownJustDown()) { + if (++m_nCurrentCommand == MOVIE_TOTAL_COMMANDS) + m_nCurrentCommand = MOVIE_NEW_ACTOR; + } + if (CPad::GetPad(1)->GetTriangleJustDown()) { + if (m_nCurrentCommand != MOVIE_DO_NOTHING) + m_bCommandActive = true; + } return; + } switch (m_nCurrentCommand) { case MOVIE_DO_NOTHING: m_bCommandActive = false; break; + case MOVIE_NEW_ACTOR: + if (m_nActor == -1) { + if (m_nNumActors == NUM_ACTORS_IN_MOVIE) + break; + if (!CStreaming::HasModelLoaded(m_nPedmodelId)) { + CStreaming::RequestModel(m_nPedmodelId, 0); +#ifdef FIX_BUGS + CStreaming::LoadAllRequestedModels(false); // otherwise gets stuck :( +#endif + break; + } + CPed* pPed = new CCivilianPed(PEDTYPE_SPECIAL, m_nPedmodelId); + pPed->CharCreatedBy = MISSION_CHAR; + pPed->GetPosition() = m_vecCurrentPosition; + pPed->SetOrientation(0.0f, 0.0f, 0.0f); + CWorld::Add(pPed); + pPed->bUsesCollision = false; + pPed->bAffectedByGravity = false; + for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) { + if (pActors[i] == nil) { + m_nActor = i; + pActors[i] = pPed; + break; + } + } + } + else { + pActors[m_nActor]->GetPosition() = m_vecCurrentPosition; + pActors[m_nActor]->SetOrientation(0.0f, 0.0f, 0.0f); + int32 mi = m_nPedmodelId; + if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) + mi = NextValidModelId(m_nPedmodelId, -1); + else if (CPad::GetPad(1)->GetRightShoulder1JustDown()) + mi = NextValidModelId(m_nPedmodelId, 1); + if (mi == m_nPedmodelId) { + if (CPad::GetPad(1)->GetTriangleJustDown()) { + pActors[m_nActor]->bUsesCollision = true; + pActors[m_nActor]->bAffectedByGravity = true; + ++m_nNumActors; + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_NEW_ACTOR; + Movie[m_nNumMovieCommands].m_vecPosition = m_vecCurrentPosition; + Movie[m_nNumMovieCommands].m_nModelIndex = m_nPedmodelId; + Movie[m_nNumMovieCommands++].m_nActorId = m_nActor; + m_nActor = -1; + m_bCommandActive = false; + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + CWorld::Remove(pActors[m_nActor]); + delete pActors[m_nActor]; + pActors[m_nActor] = nil; + m_nActor = -1; + m_bCommandActive = false; + } + } + else { + m_nPedmodelId = mi; + if (pActors[m_nActor]) { + CWorld::Remove(pActors[m_nActor]); + delete pActors[m_nActor]; + } + pActors[m_nActor] = nil; + m_nActor = -1; + } + } + break; + case MOVIE_MOVE_ACTOR: + SelectActor(); + if (m_bCommandActive) + break; + pActors[m_nActor]->GetPosition() = m_vecCurrentPosition; + if (CPad::GetPad(1)->GetTriangleJustDown()) { + m_bCommandActive = false; +#ifndef FIX_BUGS // why? it crashes, also makes no sense + pActors[m_nActor] = nil; +#endif + SelectActor(); + } + break; + case MOVIE_SELECT_ACTOR: + SelectActor(); + break; + case MOVIE_DELETE_ACTOR: + SelectActor(); + if (m_bActorSelected) { + CPopulation::RemovePed(pActors[m_nActor]); + m_nCurrentActor = 0; + --m_nNumActors; +#ifdef FIX_BUGS + pActors[m_nActor] = nil; + m_nActor = -1; +#else + m_nActor = -1; + pActors[m_nActor] = nil; +#endif + SelectActor(); + m_bCommandActive = false; + } + else if (CPad::GetPad(1)->GetCircleJustDown()) { + m_nActor = -1; + m_bCommandActive = false; + } + break; + case MOVIE_NEW_VEHICLE: + if (m_nVehicle == -1) { + if (m_nNumVehicles == NUM_VEHICLES_IN_MOVIE) + break; + if (!CStreaming::HasModelLoaded(m_nVehiclemodelId)) { + CStreaming::RequestModel(m_nVehiclemodelId, 0); +#ifdef FIX_BUGS + CStreaming::LoadAllRequestedModels(false); // otherwise gets stuck :( +#endif + break; + } + CVehicle* pVehicle = new CAutomobile(m_nVehiclemodelId, MISSION_VEHICLE); + pVehicle->m_status = STATUS_PHYSICS; + pVehicle->GetPosition() = m_vecCurrentPosition; + pVehicle->SetOrientation(0.0f, 0.0f, 0.0f); + CWorld::Add(pVehicle); + pVehicle->bUsesCollision = false; + pVehicle->bAffectedByGravity = false; + for (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) { + if (pVehicles[i] == nil) { + m_nVehicle = i; + pVehicles[i] = pVehicle; + break; + } + } + } + else { + pVehicles[m_nVehicle]->GetPosition() = m_vecCurrentPosition; + pVehicles[m_nVehicle]->SetOrientation(0.0f, 0.0f, 0.0f); + int32 mi = m_nVehiclemodelId; + if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) + mi = NextValidModelId(m_nVehiclemodelId, -1); + else if (CPad::GetPad(1)->GetRightShoulder1JustDown()) + mi = NextValidModelId(m_nVehiclemodelId, 1); + if (mi == m_nVehiclemodelId) { + if (CPad::GetPad(1)->GetTriangleJustDown()) { + pVehicles[m_nVehicle]->bUsesCollision = true; + pVehicles[m_nVehicle]->bAffectedByGravity = true; + ++m_nNumVehicles; + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_NEW_VEHICLE; + Movie[m_nNumMovieCommands].m_vecPosition = m_vecCurrentPosition; + Movie[m_nNumMovieCommands].m_nModelIndex = m_nVehiclemodelId; + Movie[m_nNumMovieCommands++].m_nVehicleId = m_nVehicle; + m_nVehicle = -1; + m_bCommandActive = false; + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + CWorld::Remove(pVehicles[m_nVehicle]); + delete pVehicles[m_nVehicle]; + pVehicles[m_nVehicle] = nil; + m_nVehicle = -1; + m_bCommandActive = false; + } + } + else { + m_nVehiclemodelId = mi; + if (pVehicles[m_nVehicle]) { + CWorld::Remove(pVehicles[m_nVehicle]); + delete pVehicles[m_nVehicle]; + } + pVehicles[m_nVehicle] = nil; + m_nVehicle = -1; + } + } + break; + case MOVIE_MOVE_VEHICLE: + SelectVehicle(); + if (m_bCommandActive) + break; + pVehicles[m_nVehicle]->GetPosition() = m_vecCurrentPosition; + if (CPad::GetPad(1)->GetTriangleJustDown()) { + m_bCommandActive = false; +#ifndef FIX_BUGS // again, why? works wrong + pVehicles[m_nVehicle] = nil; +#endif + m_nVehicle = -1; + } + break; + case MOVIE_SELECT_VEHICLE: + SelectVehicle(); + break; + case MOVIE_DELETE_VEHICLE: + SelectVehicle(); + if (m_bVehicleSelected) { + CWorld::Remove(pVehicles[m_nVehicle]); + delete pVehicles[m_nVehicle]; + m_nCurrentVehicle = 0; + --m_nNumVehicles; + pVehicles[m_nVehicle] = nil; + m_nVehicle = -1; + SelectVehicle(); + m_bCommandActive = false; + } + else if (CPad::GetPad(1)->GetCircleJustDown()) { + pVehicles[m_nVehicle] = nil; + m_nVehicle = -1; + m_bCommandActive = false; + } + break; + case MOVIE_GIVE_WEAPON: + if (m_bActorSelected) { + if (SelectWeapon()) { + m_bCommandActive = false; + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_GIVE_WEAPON; + Movie[m_nNumMovieCommands].m_nActorId = m_nActor; + Movie[m_nNumMovieCommands++].m_nModelIndex = m_nWeaponType; + } + } + else { + SelectActor(); + m_bCommandActive = true; + } + break; + case MOVIE_GOTO: + case MOVIE_GOTO_WAIT: + if (!m_bActorSelected) { + m_bDrawGotoArrow = true; + SelectActor(); + if (m_nActor == -1) + m_bCommandActive = true; + } + else { + m_vecGotoPosition = m_vecCurrentPosition; + if (CPad::GetPad(1)->GetTriangleJustDown()) { + if (pActors[m_nActor]->bInVehicle) { + if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pActors[m_nActor]->m_pMyVehicle, m_vecGotoPosition, false)) + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT; + else + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS; + pActors[m_nActor]->m_pMyVehicle->m_status = STATUS_PHYSICS; + pActors[m_nActor]->m_pMyVehicle->bEngineOn = true; + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed); + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); + TheCamera.TakeControl(pActors[m_nActor]->m_pMyVehicle, CCam::MODE_BEHINDCAR, JUMP_CUT, CAMCONTROL_SCRIPT); + } + else { + pActors[m_nActor]->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_vecGotoPosition); + TheCamera.TakeControl(pActors[m_nActor], CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT); + } + m_bDrawGotoArrow = false; + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_GOTO; + Movie[m_nNumMovieCommands].m_nActorId = m_nActor; + Movie[m_nNumMovieCommands++].m_vecPosition = m_vecGotoPosition; + } + if (!m_bDrawGotoArrow) { + if (pActors[m_nActor]->bInVehicle && pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_NONE || + !pActors[m_nActor]->bInVehicle && pActors[m_nActor]->m_objective == OBJECTIVE_NONE) { + if (pActors[m_nActor]) // if there is something that requires this check the least, it's this one + m_vecCamHeading = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].Source; + m_bCommandActive = false; + TheCamera.Cams[TheCamera.ActiveCam].Mode = CCam::MODE_FIGHT_CAM_RUNABOUT; + m_vecCurrentPosition = pActors[m_nActor]->GetPosition(); + pActors[m_nActor]->SetObjective(OBJECTIVE_NONE); + if (pActors[m_nActor]->bInVehicle) + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + } + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + pActors[m_nActor] = nil; + m_nActor = -1; + m_bCommandActive = false; + } + } + break; + case MOVIE_GET_IN_CAR: + if (m_bActorSelected) + SelectVehicle(); + else { + SelectActor(); + if (m_nActor != -1) + m_bCommandActive = true; + } + if (m_bVehicleSelected) { + pActors[m_nActor]->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicles[m_nVehicle]); + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_GET_IN_CAR; + Movie[m_nNumMovieCommands].m_nActorId = m_nActor; + Movie[m_nNumMovieCommands++].m_nVehicleId = m_nVehicle; + m_nVehicle = -1; + m_bCommandActive = false; + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + pVehicles[m_nVehicle] = nil; + m_nVehicle = -1; + pActors[m_nActor] = nil; + m_nActor = -1; + m_bCommandActive = false; + } + break; + case MOVIE_GET_OUT_CAR: + SelectActor(); + if (m_bActorSelected) { + if (pActors[m_nActor]->bInVehicle) { + pActors[m_nActor]->SetObjective(OBJECTIVE_LEAVE_VEHICLE); + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_GET_OUT_CAR; + Movie[m_nNumMovieCommands++].m_nActorId = m_nActor; + } + m_nActor = -1; + m_bCommandActive = false; + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + pVehicles[m_nVehicle] = nil; + m_nVehicle = -1; + pActors[m_nActor] = nil; + m_nActor = -1; + m_bCommandActive = false; + } + break; + case MOVIE_KILL: + if (!m_bActorSelected) { + SelectActor(); + m_bCommandActive = true; + } + else if (!m_bActor2Selected) { + SelectActor2(); + if (m_bActorSelected && m_bActor2Selected && m_nActor != -1 && m_nActor2 != -1 && m_nActor != m_nActor2) { + pActors[m_nActor]->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pActors[m_nActor2]); + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_KILL; + Movie[m_nNumMovieCommands].m_nActorId = m_nActor; + Movie[m_nNumMovieCommands++].m_nActor2Id = m_nActor2; + m_bCommandActive = false; + } + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + pActors[m_nActor] = nil; + m_nActor = -1; + pActors[m_nActor2] = nil; + m_nActor2 = -1; + m_bCommandActive = false; + } + break; + case MOVIE_FLEE: + if (!m_bActorSelected) { + SelectActor(); + m_bCommandActive = true; + } + else if (!m_bActor2Selected) { + SelectActor2(); + if (m_bActorSelected && m_bActor2Selected && m_nActor != -1 && m_nActor2 != -1 && m_nActor != m_nActor2) { + pActors[m_nActor]->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pActors[m_nActor2]); + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_FLEE; + Movie[m_nNumMovieCommands].m_nActorId = m_nActor; + Movie[m_nNumMovieCommands++].m_nActor2Id = m_nActor2; + m_bCommandActive = false; + } + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + pActors[m_nActor] = nil; + m_nActor = -1; + pActors[m_nActor2] = nil; + m_nActor2 = -1; + m_bCommandActive = false; + } + break; + case MOVIE_WAIT: + SelectActor(); + if (m_bActorSelected) { + pActors[m_nActor]->SetObjective(OBJECTIVE_IDLE); + Movie[m_nCurrentMovieCommand].m_nCommandId = MOVIE_WAIT; + Movie[m_nCurrentMovieCommand++].m_nActorId = m_nActor; + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + pActors[m_nActor] = nil; + m_nActor = -1; + m_bCommandActive = false; + } + break; + case MOVIE_POSITION_CAMERA: + if (CPad::GetPad(1)->GetTriangleJustDown()) { + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_POSITION_CAMERA; + Movie[m_nNumMovieCommands].m_vecPosition = TheCamera.Cams[TheCamera.ActiveCam].Source; + Movie[m_nNumMovieCommands++].m_vecCamera = m_vecCamHeading; + m_bCommandActive = false; + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + m_bCommandActive = false; + } + break; + case MOVIE_SET_CAMERA_TARGET: + if (!m_bActorSelected) { + SelectActor(); + m_bCommandActive = true; + } + else { + TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity = pActors[m_nActor]; + if (CPad::GetPad(1)->GetTriangleJustDown()) { + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_SET_CAMERA_TARGET; + Movie[m_nNumMovieCommands++].m_nActorId = m_nActor; + m_bCommandActive = false; + } + } + break; + case MOVIE_SELECT_CAMERA_MODE: + m_bCommandActive = false; + break; + case MOVIE_SAVE_MOVIE: + SaveMovie(); + break; + case MOVIE_LOAD_MOVIE: + LoadMovie(); + break; + case MOVIE_PLAY_MOVIE: + InitPlayback(); + LoadMovie(); + m_bRecording = false; + break; + case MOVIE_END: + m_bRecording = false; + break; + default: + assert(0); } } void CSceneEdit::PlayBack(void) { - + m_nCurrentCommand = Movie[m_nCurrentMovieCommand].m_nCommandId; + if (m_nCurrentMovieCommand >= m_nNumMovieCommands) { + if (CPad::GetPad(1)->GetTriangleJustDown()) { + m_nCurrentCommand = MOVIE_DO_NOTHING; + m_bRecording = true; + ReInitialise(); + } + return; + } + switch (m_nCurrentCommand) { + case MOVIE_DO_NOTHING: + case MOVIE_MOVE_ACTOR: + case MOVIE_SELECT_ACTOR: + case MOVIE_DELETE_ACTOR: + case MOVIE_MOVE_VEHICLE: + case MOVIE_SELECT_VEHICLE: + case MOVIE_DELETE_VEHICLE: + break; + case MOVIE_NEW_ACTOR: + { + m_nPedmodelId = Movie[m_nCurrentMovieCommand].m_nModelIndex; + m_vecCurrentPosition = Movie[m_nCurrentMovieCommand].m_vecPosition; + if (!CStreaming::HasModelLoaded(m_nPedmodelId)) { + CStreaming::RequestModel(m_nPedmodelId, 0); +#ifdef FIX_BUGS + CStreaming::LoadAllRequestedModels(false); // otherwise gets stuck :( +#endif + break; + } + CPed* pPed = new CCivilianPed(PEDTYPE_SPECIAL, m_nPedmodelId); + pPed->CharCreatedBy = MISSION_CHAR; + CWorld::Add(pPed); + pPed->GetPosition() = m_vecCurrentPosition; + pPed->SetOrientation(0.0f, 0.0f, 0.0f); + for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) { + if (pActors[i] == nil) { + m_nActor = i; + pActors[i] = pPed; + break; + } + } + m_nNumActors++; + m_nCurrentMovieCommand++; + break; + } + case MOVIE_NEW_VEHICLE: + { + m_nVehiclemodelId = Movie[m_nCurrentMovieCommand].m_nModelIndex; + m_vecCurrentPosition = Movie[m_nCurrentMovieCommand].m_vecPosition; + if (!CStreaming::HasModelLoaded(m_nVehiclemodelId)) { + CStreaming::RequestModel(m_nVehiclemodelId, 0); +#ifdef FIX_BUGS + CStreaming::LoadAllRequestedModels(false); // otherwise gets stuck :( +#endif + break; + } + CVehicle* pVehicle = new CAutomobile(m_nVehiclemodelId, MISSION_VEHICLE); + pVehicle->m_status = STATUS_PHYSICS; + pVehicle->GetPosition() = m_vecCurrentPosition; + pVehicle->SetOrientation(0.0f, 0.0f, 0.0f); + CWorld::Add(pVehicle); + for (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) { + if (pVehicles[i] == nil) { + m_nVehicle = i; + pVehicles[i] = pVehicle; + break; + } + } + m_nNumVehicles++; + m_nCurrentMovieCommand++; + break; + } + case MOVIE_GIVE_WEAPON: + m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; + m_nWeaponType = Movie[m_nCurrentMovieCommand].m_nModelIndex; + pActors[m_nActor]->GiveWeapon((eWeaponType)m_nWeaponType, 1000); + pActors[m_nActor]->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pActors[m_nActor]->GetWeapon()->m_eWeaponType)->m_nModelId); + pActors[m_nActor]->SetCurrentWeapon(m_nWeaponType); + m_nCurrentMovieCommand++; + break; + case MOVIE_GOTO: + case MOVIE_GOTO_WAIT: + m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; + m_vecGotoPosition = Movie[m_nCurrentMovieCommand].m_vecPosition; + if (pActors[m_nActor]->bInVehicle) { + if (pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS && + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS_STRAIGHT) { + if ((pActors[m_nActor]->m_pMyVehicle->GetPosition() - m_vecGotoPosition).Magnitude() < 5.0f) { + if (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pActors[m_nActor]->m_pMyVehicle, m_vecGotoPosition, false)) + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT; + else + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS; + pActors[m_nActor]->m_pMyVehicle->m_status = STATUS_PHYSICS; + pActors[m_nActor]->m_pMyVehicle->bEngineOn = true; + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed); + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); + if (m_nCurrentCommand != MOVIE_GOTO_WAIT) + ++m_nCurrentMovieCommand; + } + else + ++m_nCurrentMovieCommand; + } + } + else { + if (pActors[m_nActor]->m_objective != OBJECTIVE_GOTO_AREA_ON_FOOT) { + pActors[m_nActor]->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_vecGotoPosition); + ++m_nCurrentMovieCommand; + } + } + break; + case MOVIE_GET_IN_CAR: + m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; + if (!pActors[m_nActor]->bInVehicle){ + m_nVehicle = Movie[m_nCurrentMovieCommand].m_nVehicleId; + pActors[m_nActor]->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicles[m_nVehicle]); + } + else + ++m_nCurrentMovieCommand; + break; + case MOVIE_GET_OUT_CAR: + m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; + if (pActors[m_nActor]->bInVehicle) + pActors[m_nActor]->SetObjective(OBJECTIVE_LEAVE_VEHICLE); + else + ++m_nCurrentMovieCommand; + break; + case MOVIE_KILL: + m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; + m_nActor2 = Movie[m_nCurrentMovieCommand].m_nActor2Id; + pActors[m_nActor]->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pActors[m_nActor2]); + if (pActors[m_nActor2]->GetPedState() == PED_DEAD) + ++m_nCurrentMovieCommand; + break; + case MOVIE_FLEE: + m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; + m_nActor2 = Movie[m_nCurrentMovieCommand].m_nActor2Id; + pActors[m_nActor]->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pActors[m_nActor2]); + ++m_nCurrentMovieCommand; + break; + case MOVIE_WAIT: + m_nActor = Movie[m_nCurrentMovieCommand].m_nActorId; + pActors[m_nActor]->SetObjective(OBJECTIVE_IDLE); + ++m_nCurrentMovieCommand; + break; + case MOVIE_POSITION_CAMERA: + TheCamera.Cams[TheCamera.ActiveCam].Source = Movie[m_nCurrentMovieCommand].m_vecPosition; + m_vecCamHeading = Movie[m_nCurrentMovieCommand].m_vecCamera; + TheCamera.Cams[TheCamera.ActiveCam].Front = m_vecCamHeading; + ++m_nCurrentMovieCommand; + break; + case MOVIE_SET_CAMERA_TARGET: + m_bCameraFollowActor = true; + TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity = pActors[Movie[m_nNumMovieCommands].m_nActorId]; + TheCamera.pTargetEntity = pActors[Movie[m_nNumMovieCommands].m_nActorId]; + TheCamera.m_bLookingAtPlayer = false; + ++m_nCurrentMovieCommand; + break; + case MOVIE_SELECT_CAMERA_MODE: + m_bCommandActive = false; // this is wrong + break; + } } void CSceneEdit::ClearForNewCommand(void) { - + m_nActor = -1; + m_nActor2 = -1; + m_nVehicle = -1; + m_bActorSelected = false; + m_bActor2Selected = false; + m_bVehicleSelected = false; + m_bDrawGotoArrow = false; } void CSceneEdit::SelectActor(void) { - + m_bActorSelected = false; + if (m_nActor != -1) { + if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) { + CPed* pPed; + do { + if (--m_nActor < 0) + m_nActor = NUM_ACTORS_IN_MOVIE - 1; + pPed = pActors[m_nActor]; + } while (pPed == nil); + TheCamera.Cams[TheCamera.ActiveCam].Source = pPed->GetPosition() - m_vecCamHeading; + } + else if (CPad::GetPad(1)->GetRightShoulder1JustDown()) { + CPed* pPed; + do { + if (++m_nActor == NUM_ACTORS_IN_MOVIE) + m_nActor = 0; + pPed = pActors[m_nActor]; + } while (pPed == nil); + TheCamera.Cams[TheCamera.ActiveCam].Source = pPed->GetPosition() - m_vecCamHeading; + } + m_vecCurrentPosition = pActors[m_nActor]->GetPosition(); + if (CPad::GetPad(1)->GetTriangleJustDown()) { + m_bActorSelected = true; + m_bCommandActive = false; + } + else if (CPad::GetPad(1)->GetCircleJustDown()) { + m_nActor = -1; + } + } + else if (m_nNumActors != 0) { + for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) { + if (pActors[i] != nil) { + m_nActor = i; + break; + } + } + TheCamera.Cams[TheCamera.ActiveCam].Source = pActors[m_nActor]->GetPosition() - m_vecCamHeading; + if (m_nNumActors == 1) { + m_bActorSelected = true; + m_bCommandActive = false; + } + } + else { + m_bCommandActive = false; + } } void CSceneEdit::SelectActor2(void) { - + m_bActor2Selected = false; + if (m_nNumActors <= 1) { + m_bCommandActive = false; + return; + } + if (m_nActor2 != -1) { + if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) { + CPed* pPed; + do { + if (--m_nActor2 < 0) + m_nActor2 = NUM_ACTORS_IN_MOVIE - 1; + pPed = pActors[m_nActor2]; + } while (pPed == nil || pPed == pActors[m_nActor]); + TheCamera.Cams[TheCamera.ActiveCam].Source = pPed->GetPosition() - m_vecCamHeading; + } + else if (CPad::GetPad(1)->GetRightShoulder1JustDown()) { + CPed* pPed; + do { + if (++m_nActor2 == NUM_ACTORS_IN_MOVIE) + m_nActor2 = 0; + pPed = pActors[m_nActor2]; + } while (pPed == nil || pPed == pActors[m_nActor]); + TheCamera.Cams[TheCamera.ActiveCam].Source = pPed->GetPosition() - m_vecCamHeading; + } + m_vecCurrentPosition = pActors[m_nActor2]->GetPosition(); + if (CPad::GetPad(1)->GetTriangleJustDown()) { + m_bActor2Selected = true; + m_bCommandActive = false; + } + else if (CPad::GetPad(1)->GetCircleJustDown()) { + m_nActor2 = -1; + } + } + else { + for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) { + if (pActors[i] != nil && pActors[m_nActor] != pActors[i] ) { + m_nActor2 = i; + break; + } + } + TheCamera.Cams[TheCamera.ActiveCam].Source = pActors[m_nActor2]->GetPosition() - m_vecCamHeading; + } } void CSceneEdit::SelectVehicle(void) { - + m_bVehicleSelected = false; + if (m_nVehicle != -1) { + if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) { + CVehicle* pVehicle; + do { + if (--m_nVehicle < 0) + m_nVehicle = NUM_VEHICLES_IN_MOVIE - 1; + pVehicle = pVehicles[m_nVehicle]; + } while (pVehicle == nil); + } + else if (CPad::GetPad(1)->GetRightShoulder1JustDown()) { + CVehicle* pVehicle; + do { + if (++m_nVehicle == NUM_VEHICLES_IN_MOVIE) + m_nVehicle = 0; + pVehicle = pVehicles[m_nVehicle]; + } while (pVehicle == nil); + } + m_vecCurrentPosition = pVehicles[m_nVehicle]->GetPosition(); + TheCamera.Cams[TheCamera.ActiveCam].Source = pVehicles[m_nVehicle]->GetPosition() - m_vecCamHeading; + if (CPad::GetPad(1)->GetTriangleJustDown()) { + m_bVehicleSelected = true; + m_bCommandActive = false; + } + else if (CPad::GetPad(1)->GetCircleJustDown()) { + m_nVehicle = -1; + } + } + else if (m_nNumVehicles != 0) { + for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) { + if (pVehicles[i] != nil) { + m_nVehicle = i; + break; + } + } + } } -void CSceneEdit::SelectWeapon(void) +bool CSceneEdit::SelectWeapon(void) { - + if (m_nWeaponType == WEAPONTYPE_UNARMED) { + m_nWeaponType = WEAPONTYPE_COLT45; + return false; + } + if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) { + if (++m_nWeaponType >= WEAPONTYPE_DETONATOR) + m_nWeaponType = WEAPONTYPE_BASEBALLBAT; + pActors[m_nActor]->ClearWeapons(); + pActors[m_nActor]->GiveWeapon((eWeaponType)m_nWeaponType, 1000); + pActors[m_nActor]->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pActors[m_nActor]->GetWeapon()->m_eWeaponType)->m_nModelId); + pActors[m_nActor]->SetCurrentWeapon(m_nWeaponType); + } + else if (CPad::GetPad(1)->GetRightShoulder1JustDown()){ + if (--m_nWeaponType <= WEAPONTYPE_UNARMED) + m_nWeaponType = WEAPONTYPE_GRENADE; + pActors[m_nActor]->ClearWeapons(); + pActors[m_nActor]->GiveWeapon((eWeaponType)m_nWeaponType, 1000); + pActors[m_nActor]->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pActors[m_nActor]->GetWeapon()->m_eWeaponType)->m_nModelId); + pActors[m_nActor]->SetCurrentWeapon(m_nWeaponType); + } + if (CPad::GetPad(1)->GetTriangleJustDown()) { + m_bCommandActive = false; + return true; + } + if (CPad::GetPad(1)->GetCircleJustDown()) { + pActors[m_nActor]->ClearWeapons(); + m_nWeaponType = WEAPONTYPE_UNARMED; + m_bCommandActive = false; + return false; + } + return false; } \ No newline at end of file diff --git a/src/control/SceneEdit.h b/src/control/SceneEdit.h index 66ec5735..6dcefa31 100644 --- a/src/control/SceneEdit.h +++ b/src/control/SceneEdit.h @@ -62,12 +62,17 @@ public: static int16 m_nCurrentMovieCommand; static int16 m_nCurrentCommand; static int16 m_nCurrentVehicle; + static int16 m_nCurrentActor; static bool m_bEditOn; static bool m_bRecording; static bool m_bCommandActive; + static bool m_bActorSelected; + static bool m_bActor2Selected; + static bool m_bVehicleSelected; static int16 m_nNumActors; static int16 m_nNumVehicles; static int16 m_nNumMovieCommands; + static int16 m_nWeaponType; static CPed* pActors[NUM_ACTORS_IN_MOVIE]; static CVehicle* pVehicles[NUM_VEHICLES_IN_MOVIE]; static bool m_bDrawGotoArrow; @@ -86,5 +91,5 @@ public: static void SelectActor(void); static void SelectActor2(void); static void SelectVehicle(void); - static void SelectWeapon(void); + static bool SelectWeapon(void); }; diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index f83998b8..aa840541 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -931,8 +931,8 @@ void CPad::UpdatePads(void) GetPad(0)->UpdateMouse(); #ifdef XINPUT - GetPad(0)->AffectFromXinput(0); - GetPad(1)->AffectFromXinput(1); + GetPad(0)->AffectFromXinput(1); + GetPad(1)->AffectFromXinput(0); #else CapturePad(0); #endif diff --git a/src/core/main.cpp b/src/core/main.cpp index f09c2e0a..2bfe8290 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -58,6 +58,7 @@ #include "Console.h" #include "timebars.h" #include "GenericGameStorage.h" +#include "SceneEdit.h" GlobalScene &Scene = *(GlobalScene*)0x726768; @@ -863,11 +864,9 @@ Render2dStuff(void) MusicManager.DisplayRadioStationName(); TheConsole.Display(); -/* if(CSceneEdit::m_bEditOn) CSceneEdit::Draw(); else -*/ CHud::Draw(); CUserDisplay::OnscnTimer.ProcessForDisplay(); CMessages::Display(); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 00674b19..475176b6 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -22,6 +22,8 @@ #include "Console.h" #include "Debug.h" #include "Hud.h" +#include "SceneEdit.h" +#include "Pad.h" #include @@ -344,6 +346,8 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); }); DebugMenuAddVarBool8("Debug", "Draw hud", (int8*)&CHud::m_Wants_To_Draw_Hud, nil); + DebugMenuAddVarBool8("Debug", "Edit on", (int8*)&CSceneEdit::m_bEditOn, nil); + DebugMenuAddVarBool8("Debug", "MapPadOneToPadTwo", (int8*)&CPad::m_bMapPadOneToPadTwo, nil); DebugMenuAddVar("Debug", "Engine Status", &engineStatus, nil, 1, 0, 226, nil); DebugMenuAddCmd("Debug", "Set Engine Status", SetEngineStatus); DebugMenuAddCmd("Debug", "Fix Car", FixCar); From b4d5d5249c5c9f8d7d7685e2f402f0a4d214892b Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 15:45:47 +0500 Subject: [PATCH 003/123] CPedPath complete --- src/control/PathFind.cpp | 218 ++++++++++++++++++++++++++++++++++++++- src/control/PathFind.h | 33 +++++- 2 files changed, 244 insertions(+), 7 deletions(-) diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 61cd3d4e..dbfd6d0e 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -14,8 +14,6 @@ bool gbShowCarPathsLinks; CPathFind &ThePaths = *(CPathFind*)0x8F6754; -WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); } - #define MAX_DIST INT16_MAX-1 // object flags: @@ -28,6 +26,215 @@ CPathInfoForObject *&InfoForTilePeds = *(CPathInfoForObject**)0x8F1AE4; CTempDetachedNode *&DetachedNodesCars = *(CTempDetachedNode**)0x8E2824; CTempDetachedNode *&DetachedNodesPeds = *(CTempDetachedNode**)0x8E28A0; +bool +CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints) +{ + *pointsFound = 0; + CVector vecDistance = destination - position; + if (Abs(vecDistance.x) > 23.8f || Abs(vecDistance.y) > 23.8f || Abs(vecDistance.z) > 23.8f) + return false; + CVector vecPos = (position + destination) * 0.5f; + CVector vecSectorStartPos (vecPos.x - 14.0f, vecPos.y - 14.0f, vecPos.z); + CVector2D vecSectorEndPos (vecPos.x + 28.0f, vecPos.x + 28.0f); + const int16 nodeStartX = (position.x - vecSectorStartPos.x) * 1.4286f; + const int16 nodeStartY = (position.y - vecSectorStartPos.y) * 1.4286f; + const int16 nodeEndX = (destination.x - vecSectorStartPos.x) * 1.4286f; + const int16 nodeEndY = (destination.y - vecSectorStartPos.y) * 1.4286f; + if (nodeStartX == nodeEndX && nodeStartY == nodeEndY) + return false; + CPedPathNode pathNodes[40][40]; + CPedPathNode pathNodesList[416]; + for (int32 x = 0; x < 40; x++) { + for (int32 y = 0; y < 40; y++) { + pathNodes[x][y].bBlockade = false; + pathNodes[x][y].id = 0x7FFF; + pathNodes[x][y].nodeIdX = x; + pathNodes[x][y].nodeIdY = y; + } + } + CWorld::AdvanceCurrentScanCode(); + if (pathType != ROUTE_NO_BLOCKADE) { + const int32 nStartX = max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + AddBlockadeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], pathNodes, &vecSectorStartPos); + AddBlockadeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pathNodes, &vecSectorStartPos); + AddBlockadeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], pathNodes, &vecSectorStartPos); + AddBlockadeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], pathNodes, &vecSectorStartPos); + } + } + } + for (int32 i = 0; i < 416; i++) { + pathNodesList[i].prev = nil; + pathNodesList[i].next = nil; + } + CPedPathNode *pStartPathNode = &pathNodes[nodeStartX][nodeStartY]; + CPedPathNode *pEndPathNode = &pathNodes[nodeEndX][nodeEndY]; + pEndPathNode->bBlockade = false; + pEndPathNode->id = 0; + pEndPathNode->prev = nil; + pEndPathNode->next = pathNodesList; + pathNodesList[0].prev = pEndPathNode; + int32 pathNodeIndex = 0; + CPedPathNode *pPreviousNode = nil; + for (; pathNodeIndex < 414; pathNodeIndex++) + { + pPreviousNode = pathNodesList[pathNodeIndex].prev; + while (pPreviousNode && pPreviousNode != pStartPathNode) { + const uint8 nodeIdX = pPreviousNode->nodeIdX; + const uint8 nodeIdY = pPreviousNode->nodeIdY; + if (nodeIdX > 0) { + AddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY], pathNodeIndex + 5, pathNodesList); + if (nodeIdY > 0) + AddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY - 1], pathNodeIndex + 7, pathNodesList); + if (nodeIdY < 39) + AddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY + 1], pathNodeIndex + 7, pathNodesList); + } + if (nodeIdX < 39) { + AddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY], pathNodeIndex + 5, pathNodesList); + if (nodeIdY > 0) + AddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY - 1], pathNodeIndex + 7, pathNodesList); + if (nodeIdY < 39) + AddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY + 1], pathNodeIndex + 7, pathNodesList); + } + if (nodeIdY > 0) + AddNodeToPathList(&pathNodes[nodeIdX][nodeIdY - 1], pathNodeIndex + 5, pathNodesList); + if (nodeIdY < 39) + AddNodeToPathList(&pathNodes[nodeIdX][nodeIdY + 1], pathNodeIndex + 5, pathNodesList); + pPreviousNode = pPreviousNode->prev; + if (!pPreviousNode) + break; + } + + if (pPreviousNode && pPreviousNode == pStartPathNode) + break; + } + if (pathNodeIndex == 414) + return false; + CPedPathNode *pPathNode = pStartPathNode; + for (*pointsFound = 0; pPathNode != pEndPathNode && *pointsFound < maxPoints; ++ *pointsFound) { + const uint8 nodeIdX = pPathNode->nodeIdX; + const uint8 nodeIdY = pPathNode->nodeIdY; + if (nodeIdX <= 0 || pathNodes[nodeIdX - 1][nodeIdY].id + 5 != pPathNode->id) { + if (nodeIdX >= 39 || pathNodes[nodeIdX + 1][nodeIdY].id + 5 != pPathNode->id) { + if (nodeIdY <= 0 || pathNodes[nodeIdX][nodeIdY - 1].id + 5 != pPathNode->id) { + if (nodeIdY >= 39 || pathNodes[nodeIdX][nodeIdY + 1].id + 5 != pPathNode->id) { + if (nodeIdX <= 0 || nodeIdY <= 0 || pathNodes[nodeIdX - 1][nodeIdY - 1].id + 7 != pPathNode->id) { + if (nodeIdX <= 0 || nodeIdY >= 39 || pathNodes[nodeIdX - 1][nodeIdY + 1].id + 7 != pPathNode->id) { + if (nodeIdX >= 39 || nodeIdY <= 0 || pathNodes[nodeIdX + 1][nodeIdY - 1].id + 7 != pPathNode->id) { + if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1]; + } else { + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY - 1]; + } + } else { + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY + 1]; + } + } else { + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY - 1]; + } + } else { + pPathNode = &pathNodes[nodeIdX][nodeIdY + 1]; + } + } else { + pPathNode = &pathNodes[nodeIdX][nodeIdY - 1]; + } + } + else { + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY]; + } + } + else { + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY]; + } + pointPoses[*pointsFound] = vecSectorStartPos; + pointPoses[*pointsFound].x += (float)pPathNode->nodeIdX * 0.7f; + pointPoses[*pointsFound].y += (float)pPathNode->nodeIdY * 0.7f; + } + return true; +} + + +void +CPedPath::AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList) +{ + if (!pNodeToAdd->bBlockade && id < pNodeToAdd->id) { + if (pNodeToAdd->id != 0x7FFF) + RemoveNodeFromList(pNodeToAdd); + AddNodeToList(pNodeToAdd, id, pNodeList); + } +} + +void +CPedPath::RemoveNodeFromList(CPedPathNode *pNode) +{ + pNode->next->prev = pNode->prev; + if (pNode->prev) + pNode->prev->next = pNode->next; +} + +void +CPedPath::AddNodeToList(CPedPathNode *pNode, int16 index, CPedPathNode *pList) +{ + pNode->prev = pList[index].prev; + pNode->next = &pList[index]; + if (pList[index].prev) + pList[index].prev->next = pNode; + pList[index].prev = pNode; + pNode->id = index; +} + +void +CPedPath::AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CVector *pPosition) +{ + CPtrNode* listNode = list.first; + while (listNode) { + CEntity* pEntity = (CEntity*)listNode->item; + if (pEntity->m_scanCode != CWorld::GetCurrentScanCode() && pEntity->bUsesCollision) { + pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + AddBlockade(pEntity, pathNodes, pPosition); + } + listNode = listNode->next; + } +} + +void +CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition) +{ + const CColBox& boundingBox = pEntity->GetColModel()->boundingBox; + const float fBoundMaxY = boundingBox.max.y + 0.3f; + const float fBoundMinY = boundingBox.min.y - 0.3f; + const float fBoundMaxX = boundingBox.max.x + 0.3f; + const float fDistanceX = pPosition->x - pEntity->m_matrix.GetPosition().x; + const float fDistanceY = pPosition->y - pEntity->m_matrix.GetPosition().y; + const float fBoundRadius = pEntity->GetBoundRadius(); + CVector vecBoundCentre; + pEntity->GetBoundCentre(vecBoundCentre); + if (vecBoundCentre.x + fBoundRadius >= pPosition->x && + vecBoundCentre.y + fBoundRadius >= pPosition->y && + vecBoundCentre.x - fBoundRadius <= pPosition->x + 28.0f && + vecBoundCentre.y - fBoundRadius <= pPosition->y + 28.0f) { + for (int16 x = 0; x < 40; x++) { + const float pointX = (float)x * 0.7f + fDistanceX; + for (int16 y = 0; y < 40; y++) { + if (!pathNodes[x][y].bBlockade) { + const float pointY = (float)y * 0.7f + fDistanceY; + CVector2D point(pointX, pointY); + if (fBoundMaxX > Abs(DotProduct2D(point, pEntity->m_matrix.GetRight()))) { + float fDotProduct = DotProduct2D(point, pEntity->m_matrix.GetForward()); + if (fBoundMaxY > fDotProduct && fBoundMinY < fDotProduct) + pathNodes[x][y].bBlockade = true; + } + } + } + } + } +} + void CPathFind::Init(void) { @@ -1576,6 +1783,13 @@ CPathFind::DisplayPathData(void) } STARTPATCHES + InjectHook(0x42E680, &CPedPath::CalcPedRoute, PATCH_JUMP); + InjectHook(0x42F100, &CPedPath::AddNodeToPathList, PATCH_JUMP); + InjectHook(0x42F140, &CPedPath::RemoveNodeFromList, PATCH_JUMP); + InjectHook(0x42F160, &CPedPath::AddNodeToList, PATCH_JUMP); + InjectHook(0x42F1A0, &CPedPath::AddBlockade, PATCH_JUMP); + InjectHook(0x42F420, &CPedPath::AddBlockadeSectorList, PATCH_JUMP); + InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP); InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP); InjectHook(0x429540, &CPathFind::RegisterMapObject, PATCH_JUMP); diff --git a/src/control/PathFind.h b/src/control/PathFind.h index 81467cdf..ea88ade6 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -3,11 +3,7 @@ #include "Treadable.h" class CVehicle; - -class CPedPath { -public: - static bool CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16); -}; +class CPtrList; enum { @@ -30,6 +26,33 @@ enum SWITCH_ON = 1, }; +enum +{ + ROUTE_ADD_BLOCKADE = 0, + ROUTE_NO_BLOCKADE = 1 +}; + +struct CPedPathNode +{ + bool bBlockade; + uint8 nodeIdX; + uint8 nodeIdY; + int16 id; + CPedPathNode* prev; + CPedPathNode* next; +}; +static_assert(sizeof(CPedPathNode) == 0x10, "CPedPathNode: error"); + +class CPedPath { +public: + static bool CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints); + static void AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList); + static void RemoveNodeFromList(CPedPathNode *pNode); + static void AddNodeToList(CPedPathNode *pNode, int16 index, CPedPathNode *pList); + static void AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition); + static void AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CVector *pPosition); +}; + struct CPathNode { CVector pos; From 8bb23ca5d4d8404c21a0e5f79f4548b86f4456a9 Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 16:57:28 +0500 Subject: [PATCH 004/123] Refactor CPedPath::CalcPedRoute --- src/control/PathFind.cpp | 56 ++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index dbfd6d0e..f0431db9 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -36,10 +36,10 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe CVector vecPos = (position + destination) * 0.5f; CVector vecSectorStartPos (vecPos.x - 14.0f, vecPos.y - 14.0f, vecPos.z); CVector2D vecSectorEndPos (vecPos.x + 28.0f, vecPos.x + 28.0f); - const int16 nodeStartX = (position.x - vecSectorStartPos.x) * 1.4286f; - const int16 nodeStartY = (position.y - vecSectorStartPos.y) * 1.4286f; - const int16 nodeEndX = (destination.x - vecSectorStartPos.x) * 1.4286f; - const int16 nodeEndY = (destination.y - vecSectorStartPos.y) * 1.4286f; + const int16 nodeStartX = (position.x - vecSectorStartPos.x) / 0.7f; + const int16 nodeStartY = (position.y - vecSectorStartPos.y) / 0.7f; + const int16 nodeEndX = (destination.x - vecSectorStartPos.x) / 0.7f; + const int16 nodeEndY = (destination.y - vecSectorStartPos.y) / 0.7f; if (nodeStartX == nodeEndX && nodeStartY == nodeEndY) return false; CPedPathNode pathNodes[40][40]; @@ -119,38 +119,22 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe for (*pointsFound = 0; pPathNode != pEndPathNode && *pointsFound < maxPoints; ++ *pointsFound) { const uint8 nodeIdX = pPathNode->nodeIdX; const uint8 nodeIdY = pPathNode->nodeIdY; - if (nodeIdX <= 0 || pathNodes[nodeIdX - 1][nodeIdY].id + 5 != pPathNode->id) { - if (nodeIdX >= 39 || pathNodes[nodeIdX + 1][nodeIdY].id + 5 != pPathNode->id) { - if (nodeIdY <= 0 || pathNodes[nodeIdX][nodeIdY - 1].id + 5 != pPathNode->id) { - if (nodeIdY >= 39 || pathNodes[nodeIdX][nodeIdY + 1].id + 5 != pPathNode->id) { - if (nodeIdX <= 0 || nodeIdY <= 0 || pathNodes[nodeIdX - 1][nodeIdY - 1].id + 7 != pPathNode->id) { - if (nodeIdX <= 0 || nodeIdY >= 39 || pathNodes[nodeIdX - 1][nodeIdY + 1].id + 7 != pPathNode->id) { - if (nodeIdX >= 39 || nodeIdY <= 0 || pathNodes[nodeIdX + 1][nodeIdY - 1].id + 7 != pPathNode->id) { - if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id) - pPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1]; - } else { - pPathNode = &pathNodes[nodeIdX + 1][nodeIdY - 1]; - } - } else { - pPathNode = &pathNodes[nodeIdX - 1][nodeIdY + 1]; - } - } else { - pPathNode = &pathNodes[nodeIdX - 1][nodeIdY - 1]; - } - } else { - pPathNode = &pathNodes[nodeIdX][nodeIdY + 1]; - } - } else { - pPathNode = &pathNodes[nodeIdX][nodeIdY - 1]; - } - } - else { - pPathNode = &pathNodes[nodeIdX + 1][nodeIdY]; - } - } - else { - pPathNode = &pathNodes[nodeIdX - 1][nodeIdY]; - } + if (nodeIdX > 0 && pathNodes[nodeIdX - 1][nodeIdY].id + 5 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY]; + else if (nodeIdX > 39 && pathNodes[nodeIdX + 1][nodeIdY].id + 5 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY]; + else if (nodeIdY > 0 && pathNodes[nodeIdX][nodeIdY - 1].id + 5 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX][nodeIdY - 1]; + else if (nodeIdY > 39 && pathNodes[nodeIdX][nodeIdY + 1].id + 5 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX][nodeIdY + 1]; + else if (nodeIdX > 0 && nodeIdY > 0 && pathNodes[nodeIdX - 1][nodeIdY - 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY - 1]; + else if (nodeIdX > 0 && nodeIdY < 39 && pathNodes[nodeIdX - 1][nodeIdY + 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY + 1]; + else if (nodeIdX < 39 && nodeIdY > 0 && pathNodes[nodeIdX + 1][nodeIdY - 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY - 1]; + else if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1]; pointPoses[*pointsFound] = vecSectorStartPos; pointPoses[*pointsFound].x += (float)pPathNode->nodeIdX * 0.7f; pointPoses[*pointsFound].y += (float)pPathNode->nodeIdY * 0.7f; From bf040c7cd1c336af160d8672324b3029f5ba7cc3 Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 17:05:51 +0500 Subject: [PATCH 005/123] Remove float casts --- src/control/PathFind.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index f0431db9..ea81b9b7 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -136,8 +136,8 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe else if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id) pPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1]; pointPoses[*pointsFound] = vecSectorStartPos; - pointPoses[*pointsFound].x += (float)pPathNode->nodeIdX * 0.7f; - pointPoses[*pointsFound].y += (float)pPathNode->nodeIdY * 0.7f; + pointPoses[*pointsFound].x += pPathNode->nodeIdX * 0.7f; + pointPoses[*pointsFound].y += pPathNode->nodeIdY * 0.7f; } return true; } @@ -203,10 +203,10 @@ CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *p vecBoundCentre.x - fBoundRadius <= pPosition->x + 28.0f && vecBoundCentre.y - fBoundRadius <= pPosition->y + 28.0f) { for (int16 x = 0; x < 40; x++) { - const float pointX = (float)x * 0.7f + fDistanceX; + const float pointX = x * 0.7f + fDistanceX; for (int16 y = 0; y < 40; y++) { if (!pathNodes[x][y].bBlockade) { - const float pointY = (float)y * 0.7f + fDistanceY; + const float pointY = y * 0.7f + fDistanceY; CVector2D point(pointX, pointY); if (fBoundMaxX > Abs(DotProduct2D(point, pEntity->m_matrix.GetRight()))) { float fDotProduct = DotProduct2D(point, pEntity->m_matrix.GetForward()); From 21a11fd3437f341f280a3a6ba9871abc6b7d6a9a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 14 Apr 2020 20:09:42 +0300 Subject: [PATCH 006/123] scene edit --- src/control/SceneEdit.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index 251f093f..306aba14 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -197,6 +197,10 @@ void CSceneEdit::ReInitialise(void) m_bEditOn = true; m_bRecording = true; m_bCommandActive = false; +#ifdef FIX_BUGS + m_bCameraFollowActor = false; + TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true; // not enough... +#endif m_nActor = -1; m_nActor2 = -1; m_nVehicle = -1; @@ -691,8 +695,8 @@ void CSceneEdit::ProcessCommand(void) SelectActor(); if (m_bActorSelected) { pActors[m_nActor]->SetObjective(OBJECTIVE_IDLE); - Movie[m_nCurrentMovieCommand].m_nCommandId = MOVIE_WAIT; - Movie[m_nCurrentMovieCommand++].m_nActorId = m_nActor; + Movie[m_nNumMovieCommands].m_nCommandId = MOVIE_WAIT; + Movie[m_nNumMovieCommands++].m_nActorId = m_nActor; } if (CPad::GetPad(1)->GetCircleJustDown()) { pActors[m_nActor] = nil; From fbed2c4530a88c0a9cf92bd8bf135125f54a577e Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 14 Apr 2020 20:12:26 +0300 Subject: [PATCH 007/123] fix debug stuff --- src/core/Pad.cpp | 4 ++-- src/core/re3.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index aa840541..f83998b8 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -931,8 +931,8 @@ void CPad::UpdatePads(void) GetPad(0)->UpdateMouse(); #ifdef XINPUT - GetPad(0)->AffectFromXinput(1); - GetPad(1)->AffectFromXinput(0); + GetPad(0)->AffectFromXinput(0); + GetPad(1)->AffectFromXinput(1); #else CapturePad(0); #endif diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 096b9d9e..5d76d642 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -335,7 +335,6 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "Draw hud", (int8*)&CHud::m_Wants_To_Draw_Hud, nil); DebugMenuAddVarBool8("Debug", "Edit on", (int8*)&CSceneEdit::m_bEditOn, nil); - DebugMenuAddVarBool8("Debug", "MapPadOneToPadTwo", (int8*)&CPad::m_bMapPadOneToPadTwo, nil); DebugMenuAddVar("Debug", "Engine Status", &engineStatus, nil, 1, 0, 226, nil); DebugMenuAddCmd("Debug", "Set Engine Status", SetEngineStatus); DebugMenuAddCmd("Debug", "Fix Car", FixCar); From f35d2721f5f0ead5f663cffeb2eae6bfc95a176c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 14 Apr 2020 20:16:02 +0300 Subject: [PATCH 008/123] fix --- src/control/SceneEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index 306aba14..8d804e4d 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -106,7 +106,7 @@ void CSceneEdit::LoadMovie(void) CFileMgr::SetDir("DATA"); int fid = CFileMgr::OpenFile("movie.dat", "r"); #ifdef FIX_BUGS - if (fid > 0) + if (fid >= 0) #endif { CFileMgr::Read(fid, (char*)&Movie, sizeof(Movie)); From 6d5464b6bbf44481a56682c9a3fe8d22baf8282e Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 23:32:15 +0500 Subject: [PATCH 009/123] CPedPath improvements --- src/control/PathFind.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index ea81b9b7..9f45c454 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -15,6 +15,7 @@ bool gbShowCarPathsLinks; CPathFind &ThePaths = *(CPathFind*)0x8F6754; #define MAX_DIST INT16_MAX-1 +#define MIN_PED_ROUTE_DISTANCE 23.8f // object flags: // 1 UseInRoadBlock @@ -31,7 +32,7 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe { *pointsFound = 0; CVector vecDistance = destination - position; - if (Abs(vecDistance.x) > 23.8f || Abs(vecDistance.y) > 23.8f || Abs(vecDistance.z) > 23.8f) + if (Abs(vecDistance.x) > MIN_PED_ROUTE_DISTANCE || Abs(vecDistance.y) > MIN_PED_ROUTE_DISTANCE || Abs(vecDistance.z) > MIN_PED_ROUTE_DISTANCE) return false; CVector vecPos = (position + destination) * 0.5f; CVector vecSectorStartPos (vecPos.x - 14.0f, vecPos.y - 14.0f, vecPos.z); @@ -47,7 +48,7 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe for (int32 x = 0; x < 40; x++) { for (int32 y = 0; y < 40; y++) { pathNodes[x][y].bBlockade = false; - pathNodes[x][y].id = 0x7FFF; + pathNodes[x][y].id = INT16_MAX; pathNodes[x][y].nodeIdX = x; pathNodes[x][y].nodeIdY = y; } @@ -147,7 +148,7 @@ void CPedPath::AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList) { if (!pNodeToAdd->bBlockade && id < pNodeToAdd->id) { - if (pNodeToAdd->id != 0x7FFF) + if (pNodeToAdd->id != INT16_MAX) RemoveNodeFromList(pNodeToAdd); AddNodeToList(pNodeToAdd, id, pNodeList); } From b657a8e17c8654d5eeb645e3a7da9fbb5759cae8 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 15 Apr 2020 01:06:32 +0300 Subject: [PATCH 010/123] bullet info --- src/weapons/BulletInfo.cpp | 265 ++++++++++++++++++++++++++++++++++++- src/weapons/BulletInfo.h | 17 +++ src/weapons/Weapon.cpp | 1 + src/weapons/Weapon.h | 1 + 4 files changed, 283 insertions(+), 1 deletion(-) diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp index 54fa6844..cb9e0b2d 100644 --- a/src/weapons/BulletInfo.cpp +++ b/src/weapons/BulletInfo.cpp @@ -2,4 +2,267 @@ #include "patcher.h" #include "BulletInfo.h" -WRAPPER bool CBulletInfo::TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2) { EAXJMP(0x558D40); } +#include "AnimBlendAssociation.h" +#include "AudioManager.h" +#include "AudioScriptObject.h" +#ifdef FIX_BUGS +#include "Collision.h" +#endif +#include "RpAnimBlend.h" +#include "Entity.h" +#include "EventList.h" +#include "Fire.h" +#include "Glass.h" +#include "Particle.h" +#include "Ped.h" +#include "Object.h" +#include "Stats.h" +#include "Timer.h" +#include "Vehicle.h" +#include "Weapon.h" +#include "WeaponInfo.h" +#include "World.h" + +#define BULLET_LIFETIME (1000) +#define NUM_PED_BLOOD_PARTICLES (8) +#define BLOOD_PARTICLE_OFFSET (CVector(0.0f, 0.0f, 0.0f)) +#define NUM_VEHICLE_SPARKS (16) +#define NUM_OTHER_SPARKS (8) +#define BULLET_HIT_FORCE (7.5f) +#define MAP_BORDER (1960.0f) + +CBulletInfo gaBulletInfo[CBulletInfo::NUM_BULLETS]; +bool bPlayerSniperBullet; +CVector PlayerSniperBulletStart; +CVector PlayerSniperBulletEnd; + +void CBulletInfo::Initialise(void) +{ + debug("Initialising CBulletInfo...\n"); + for (int i = 0; i < NUM_BULLETS; i++) { + gaBulletInfo[i].m_bInUse = false; + gaBulletInfo[i].m_eWeaponType = WEAPONTYPE_COLT45; + gaBulletInfo[i].m_fTimer = 0.0f; + gaBulletInfo[i].m_pSource = nil; + } + debug("CBulletInfo ready\n"); +} + +void CBulletInfo::Shutdown(void) +{ + debug("Shutting down CBulletInfo...\n"); + debug("CBulletInfo shut down\n"); +} + +bool CBulletInfo::AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosition, CVector vecSpeed) +{ + int i; + for (i = 0; i < NUM_BULLETS; i++) { + if (!gaBulletInfo[i].m_bInUse) + break; + } + if (i == NUM_BULLETS) + return false; + gaBulletInfo[i].m_pSource = pSource; + gaBulletInfo[i].m_eWeaponType = type; + gaBulletInfo[i].m_nDamage = CWeaponInfo::GetWeaponInfo(type)->m_nDamage; + gaBulletInfo[i].m_vecPosition = vecPosition; + gaBulletInfo[i].m_vecSpeed = vecSpeed; + gaBulletInfo[i].m_fTimer = CTimer::GetTimeInMilliseconds() + BULLET_LIFETIME; + gaBulletInfo[i].m_bInUse = true; +} + +void CBulletInfo::Update(void) +{ + bool bAddSound = true; + bPlayerSniperBullet = false; + for (int i = 0; i < NUM_BULLETS; i++) { + CBulletInfo* pBullet = &gaBulletInfo[i]; + if (pBullet->m_pSource && pBullet->m_pSource->IsPed() && !((CPed*)pBullet->m_pSource)->IsPointerValid()) + pBullet->m_pSource = nil; + if (!pBullet->m_bInUse) + continue; + if (CTimer::GetTimeInMilliseconds() > pBullet->m_fTimer) + pBullet->m_bInUse = false; + CVector vecOldPos = pBullet->m_vecPosition; + CVector vecNewPos = pBullet->m_vecPosition + pBullet->m_vecSpeed * CTimer::GetTimeStep() * 0.5f; + CWorld::bIncludeCarTyres = true; + CWorld::bIncludeDeadPeds = true; + CWorld::pIgnoreEntity = pBullet->m_pSource; + CColPoint point; + CEntity* pHitEntity; + if (CWorld::ProcessLineOfSight(vecOldPos, vecNewPos, point, pHitEntity, true, true, true, true, true, true)) { + if (pBullet->m_pSource && (pHitEntity->IsPed() || pHitEntity->IsVehicle())) + CStats::InstantHitsHitByPlayer++; + if (pHitEntity->IsPed()) { + CPed* pPed = (CPed*)pHitEntity; + if (!pPed->DyingOrDead() && pPed != pBullet->m_pSource) { + if (pPed->DoesLOSBulletHitPed(point)) { + if (pPed->IsPedInControl() && !pPed->bIsDucking) { + pPed->ClearAttackByRemovingAnim(); + CAnimBlendAssociation* pAnim = CAnimManager::AddAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_SHOT_FRONT_PARTIAL); + pAnim->SetBlend(0.0f, 8.0f); + } + pPed->InflictDamage(pBullet->m_pSource, pBullet->m_eWeaponType, pBullet->m_nDamage, (ePedPieceTypes)point.pieceB, pPed->GetLocalDirection(pPed->GetPosition() - point.point)); + CEventList::RegisterEvent(pPed->m_nPedType == PEDTYPE_COP ? EVENT_SHOOT_COP : EVENT_SHOOT_PED, EVENT_ENTITY_PED, pPed, (CPed*)pBullet->m_pSource, 1000); + pBullet->m_bInUse = false; + vecNewPos = point.point; + } + else { + bAddSound = false; + } + } + if (CGame::nastyGame) { + CVector vecParticleDirection = (point.point - pPed->GetPosition()) / 100; + vecParticleDirection.z = 0.01f; + if (pPed->GetIsOnScreen()) { + for (int j = 0; j < NUM_PED_BLOOD_PARTICLES; j++) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point + BLOOD_PARTICLE_OFFSET, vecParticleDirection); + } + if (pPed->GetPedState() == PED_DEAD) { + CAnimBlendAssociation* pAnim; + if (RpAnimBlendClumpGetFirstAssociation(pPed->GetClump(), ASSOC_FLAG800)) + pAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f); + else + pAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f); + if (pAnim) { + pAnim->SetCurrentTime(0.0f); + pAnim->flags |= ASSOC_RUNNING; + pAnim->flags &= ASSOC_FADEOUTWHENDONE; + } + } + pBullet->m_bInUse = false; + vecNewPos = point.point; + } + } + else if (pHitEntity->IsVehicle()) { + CVehicle* pVehicle = (CVehicle*)pHitEntity; + pVehicle->InflictDamage(pBullet->m_pSource, pBullet->m_eWeaponType, pBullet->m_nDamage); + if (pBullet->m_eWeaponType == WEAPONTYPE_FLAMETHROWER) // how? + gFireManager.StartFire(pVehicle, pBullet->m_pSource, 0.8f, true); + else { + for (int j = 0; j < NUM_VEHICLE_SPARKS; j++) + CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal / 20); + } +#ifdef FIX_BUGS + pBullet->m_bInUse = false; + vecNewPos = point.point; +#endif + } + else { + for (int j = 0; j < NUM_OTHER_SPARKS; j++) + CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal / 20); + if (pHitEntity->IsObject()) { + CObject* pObject = (CObject*)pHitEntity; + if (!pObject->bInfiniteMass) { + if (pObject->bIsStatic && pObject->m_fUprootLimit <= 0.0f) { + pObject->bIsStatic = false; + pObject->AddToMovingList(); + } + if (!pObject->bIsStatic) + pObject->ApplyMoveForce(-BULLET_HIT_FORCE * point.normal); + } + } +#ifdef FIX_BUGS + pBullet->m_bInUse = false; + vecNewPos = point.point; +#endif + } + if (pBullet->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE && bAddSound) { + cAudioScriptObject* pAudio; + switch (pHitEntity->m_type) { + case ENTITY_TYPE_BUILDING: + pAudio = new cAudioScriptObject(); + pAudio->Posn = pHitEntity->GetPosition(); + pAudio->AudioId = SCRIPT_SOUND_BULLET_HIT_GROUND_1; + pAudio->AudioEntity = AEHANDLE_NONE; + DMAudio.CreateOneShotScriptObject(pAudio); + break; + case ENTITY_TYPE_OBJECT: + pAudio = new cAudioScriptObject(); + pAudio->Posn = pHitEntity->GetPosition(); + pAudio->AudioId = SCRIPT_SOUND_BULLET_HIT_GROUND_2; + pAudio->AudioEntity = AEHANDLE_NONE; + DMAudio.CreateOneShotScriptObject(pAudio); + break; + case ENTITY_TYPE_DUMMY: + pAudio = new cAudioScriptObject(); + pAudio->Posn = pHitEntity->GetPosition(); + pAudio->AudioId = SCRIPT_SOUND_BULLET_HIT_GROUND_3; + pAudio->AudioEntity = AEHANDLE_NONE; + DMAudio.CreateOneShotScriptObject(pAudio); + break; + case ENTITY_TYPE_PED: + DMAudio.PlayOneShot(((CPed*)pHitEntity)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)pHitEntity)->Say(SOUND_PED_BULLET_HIT); + break; + case ENTITY_TYPE_VEHICLE: + DMAudio.PlayOneShot(((CVehicle*)pHitEntity)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + } + CGlass::WasGlassHitByBullet(pHitEntity, point.point); + CWeapon::BlowUpExplosiveThings(pHitEntity); + } + CWorld::pIgnoreEntity = nil; + CWorld::bIncludeDeadPeds = false; + CWorld::bIncludeCarTyres = false; + if (pBullet->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE) { + bPlayerSniperBullet = true; + PlayerSniperBulletStart = pBullet->m_vecPosition; + PlayerSniperBulletEnd = vecNewPos; + } + pBullet->m_vecPosition = vecNewPos; + if (pBullet->m_vecPosition.x < -MAP_BORDER || pBullet->m_vecPosition.x > MAP_BORDER || + pBullet->m_vecPosition.y < -MAP_BORDER || pBullet->m_vecPosition.y > MAP_BORDER) + pBullet->m_bInUse = false; + } +} + +bool CBulletInfo::TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2) +{ + if (!bPlayerSniperBullet) + return false; +#ifdef FIX_BUGS // original code is not going work anyway... + CColLine line(PlayerSniperBulletStart, PlayerSniperBulletEnd); + CColBox box; + box.Set(CVector(x1, y1, z1), CVector(x2, y2, z2), 0, 0); + return CCollision::TestLineBox(line, box); +#else + float minP = 0.0f; + float maxP = 1.0f; + float minX = min(PlayerSniperBulletStart.x, PlayerSniperBulletEnd.x); + float maxX = max(PlayerSniperBulletStart.x, PlayerSniperBulletEnd.x); + if (minX < x2 || maxX > x1) { + if (minX < x1) + minP = min(minP, (x1 - minX) / (maxX - minX)); + if (maxX > x2) + maxP = max(maxP, (maxX - x2) / (maxX - minX)); + } + else + return false; + float minY = min(PlayerSniperBulletStart.y, PlayerSniperBulletEnd.y); + float maxY = max(PlayerSniperBulletStart.y, PlayerSniperBulletEnd.y); + if (minY < y2 || maxY > y1) { + if (minY < y1) + minP = min(minP, (y1 - minY) / (maxY - minY)); + if (maxY > y2) + maxP = max(maxP, (maxY - y2) / (maxY - minY)); + } +#ifdef FIX_BUGS + else + return false; +#endif + float minZ = min(PlayerSniperBulletStart.z, PlayerSniperBulletEnd.z); + float maxZ = max(PlayerSniperBulletStart.z, PlayerSniperBulletEnd.z); + if (minZ < z2 || maxZ > z1) { + if (minZ < z1) + minP = min(minP, (z1 - minZ) / (maxZ - minZ)); + if (maxZ > z2) + maxP = max(maxP, (maxZ - z2) / (maxZ - minZ)); + } + else + return false; + return minP <= maxP; +#endif +} diff --git a/src/weapons/BulletInfo.h b/src/weapons/BulletInfo.h index 3905b56d..fb8fd3a8 100644 --- a/src/weapons/BulletInfo.h +++ b/src/weapons/BulletInfo.h @@ -1,7 +1,24 @@ #pragma once +#include "Weapon.h" + +class CEntity; class CBulletInfo { + eWeaponType m_eWeaponType; + CEntity* m_pSource; + float m_fTimer; // big mistake + bool m_bInUse; + CVector m_vecPosition; + CVector m_vecSpeed; + int16 m_nDamage; public: + enum { + NUM_BULLETS = 100 + }; + static void Initialise(void); + static void Shutdown(void); + static bool AddBullet(CEntity*, eWeaponType, CVector, CVector); + static void Update(void); static bool TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2); }; \ No newline at end of file diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 0f41264f..290b9179 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -15,6 +15,7 @@ WRAPPER void CWeapon::Update(int32 audioEntity) { EAXJMP(0x563A10); } WRAPPER void CWeapon::DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end) { EAXJMP(0x563200); } WRAPPER void CWeapon::InitialiseWeapons(void) { EAXJMP(0x55C2D0); } WRAPPER void FireOneInstantHitRound(CVector* shotSource, CVector* shotTarget, int32 damage) { EAXJMP(0x563B00); } +WRAPPER void CWeapon::BlowUpExplosiveThings(CEntity* pEntity) { EAXJMP(0x564A60); } void CWeapon::Initialise(eWeaponType type, int ammo) diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 84760550..79a53dcb 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -79,6 +79,7 @@ public: bool HasWeaponAmmoToBeUsed(void); static void InitialiseWeapons(void); static void UpdateWeapons(void); + static void BlowUpExplosiveThings(CEntity*); }; static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error"); From daed13485ef47d9c8992e53e1a976fba237fca50 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 08:03:53 +0300 Subject: [PATCH 011/123] CWeapon done, ps2 cheats fix --- src/audio/AudioManager.h | 2 +- src/control/AutoPilot.cpp | 2 +- src/control/CarCtrl.cpp | 2 +- src/control/Garages.cpp | 2 +- src/core/General.h | 5 + src/core/Pad.cpp | 2 + src/core/World.cpp | 1 + src/core/World.h | 2 + src/core/main.cpp | 3 +- src/entities/Physical.cpp | 2 +- src/math/Vector.h | 7 + src/math/Vector2D.h | 7 +- src/modelinfo/ModelIndices.h | 7 + src/peds/Ped.cpp | 2 +- src/peds/Ped.h | 5 + src/peds/PlayerPed.cpp | 8 +- src/peds/PlayerPed.h | 4 +- src/render/Glass.cpp | 16 +- src/weapons/BulletInfo.cpp | 4 + src/weapons/BulletInfo.h | 7 + src/weapons/Weapon.cpp | 2237 +++++++++++++++++++++++++++++++++- src/weapons/Weapon.h | 64 +- 22 files changed, 2331 insertions(+), 60 deletions(-) diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 910ffcaf..40aabcfc 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -117,7 +117,7 @@ enum eScriptSounds : int16 SCRIPT_SOUND_BULLET_HIT_GROUND_1 = 106, SCRIPT_SOUND_BULLET_HIT_GROUND_2 = 107, SCRIPT_SOUND_BULLET_HIT_GROUND_3 = 108, - SCRIPT_SOUND_109 = 109, + SCRIPT_SOUND_BULLET_HIT_WATER = 109, //no sound SCRIPT_SOUND_110 = 110, SCRIPT_SOUND_111 = 111, SCRIPT_SOUND_PAYPHONE_RINGING = 112, diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index 70099291..319cebab 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -35,7 +35,7 @@ void CAutoPilot::ModifySpeed(float speed) m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - (uint32)(positionBetweenNodes * m_nTimeToSpendOnCurrentCurve); #else - m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - positionBetweenNodes * m_nSpeedScaleFactor; + m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - positionBetweenNodes * m_nTimeToSpendOnCurrentCurve; #endif } diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 3174a253..ef89965a 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -426,7 +426,7 @@ CCarCtrl::GenerateOneRandomCar() (uint32)((0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve); #else pCar->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - - (0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nSpeedScaleFactor; + (0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve; #endif CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f); CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f); diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 84d49bee..48a99170 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1082,7 +1082,7 @@ void CGarage::Update() #ifdef FIX_BUGS bool bCreatedAllCars = false; #else - bool bCraetedAllCars; + bool bCreatedAllCars; #endif switch (m_eGarageType) { case GARAGE_HIDEOUT_ONE: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse1); break; diff --git a/src/core/General.h b/src/core/General.h index f32846eb..77828854 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -90,6 +90,11 @@ public: return -Atan2(x / y, 1.0f); } } + + static float GetAngleBetweenPoints(float x1, float y1, float x2, float y2) + { + return RADTODEG(GetRadianAngleBetweenPoints(x1, y1, x2, y2)); + } // should return direction in 0-8 range. fits perfectly to peds' path directions. static int GetNodeHeadingFromVector(float x, float y) diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 6efbeb8e..9d00cef7 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -642,6 +642,8 @@ void CPad::AddToCheatString(char c) { for ( int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i-- ) CheatString[i + 1] = CheatString[i]; + + CheatString[0] = c; #define _CHEATCMP(str) strncmp(str, CheatString, sizeof(str)-1) // "4414LDRULDRU" - R2 R2 L1 R2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP diff --git a/src/core/World.cpp b/src/core/World.cpp index d64569b3..b4ae9346 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -58,6 +58,7 @@ WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); } WRAPPER void CWorld::TriggerExplosion(const CVector& a1, float a2, float a3, CEntity *a4, bool a5) { EAXJMP(0x4B1140); } WRAPPER void CWorld::SetPedsOnFire(float, float, float, float, CEntity*) { EAXJMP(0x4B3D30); } +WRAPPER void CWorld::UseDetonator(CEntity *) { EAXJMP(0x4B4650); } void CWorld::Initialise() diff --git a/src/core/World.h b/src/core/World.h index 07e7889f..0ee3fdda 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -142,6 +142,8 @@ public: static void RemoveStaticObjects(); static void Process(); static void TriggerExplosion(const CVector &, float, float, CEntity*, bool); + + static void UseDetonator(CEntity *); }; extern CColPoint *gaTempSphereColPoints; diff --git a/src/core/main.cpp b/src/core/main.cpp index 93e4c71c..02f7d523 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1557,8 +1557,9 @@ void SystemInit() // #endif - +#ifdef GTA_PS2_STUFF CPad::Initialise(); +#endif CPad::GetPad(0)->Mode = 0; CGame::frenchGame = false; diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index faa8a484..bd13ff37 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -612,7 +612,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(model == MI_FIRE_HYDRANT && !Bobj->bHasBeenDamaged){ CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true); Bobj->bHasBeenDamaged = true; - }else if(B->IsObject() && model != MI_EXPLODINGBARREL && model != MI_PETROLPUMP) + }else if(B->IsObject() && !IsExplosiveThingModel(model)) Bobj->bHasBeenDamaged = true; }else{ if(IsGlass(B->GetModelIndex())) diff --git a/src/math/Vector.h b/src/math/Vector.h index 6f544ada..9b732610 100644 --- a/src/math/Vector.h +++ b/src/math/Vector.h @@ -46,6 +46,13 @@ public: y *= invsqrt; z *= invsqrt; } + + void Normalise2D(void) { + float sq = MagnitudeSqr2D(); + float invsqrt = RecipSqrt(sq); + x *= invsqrt; + y *= invsqrt; + } const CVector &operator+=(CVector const &right) { x += right.x; diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h index 1e4d698f..705ad763 100644 --- a/src/math/Vector2D.h +++ b/src/math/Vector2D.h @@ -13,13 +13,14 @@ public: void Normalise(void){ float sq = MagnitudeSqr(); - if(sq > 0.0f){ + //if(sq > 0.0f){ float invsqrt = RecipSqrt(sq); x *= invsqrt; y *= invsqrt; - }else - x = 1.0f; + //}else + // x = 1.0f; } + const CVector2D &operator+=(CVector2D const &right) { x += right.x; y += right.y; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 20d1b7f3..309fa1bb 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -490,3 +490,10 @@ IsPoliceVehicleModel(int16 id) id == MI_POLICE || id == MI_ENFORCER; } + +inline bool +IsExplosiveThingModel(int16 id) +{ + return id == MI_EXPLODINGBARREL || + id == MI_PETROLPUMP; +} \ No newline at end of file diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 2cd942f9..4ee31a30 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -1231,7 +1231,7 @@ CPed::Attack(void) weaponAnimAssoc->SetCurrentTime(0.0f); if (IsPlayer()) { - ((CPlayerPed*)this)->field_1376 = 0.0f; + ((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f; ((CPlayerPed*)this)->m_bHaveTargetSelected = false; } } diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 2edd5d68..ea8c4080 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -796,7 +796,12 @@ public: PedState GetPedState(void) { return m_nPedState; } void SetPedState(PedState state) { m_nPedState = state; } + bool Dead(void) { return m_nPedState == PED_DEAD; } + bool Dying(void) { return m_nPedState == PED_DIE; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } + bool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } + + bool Driving(void) { return m_nPedState == PED_DRIVING; } bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; } diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index ccc0a43a..dcd9486f 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -43,8 +43,8 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) m_fStaminaProgress = 0.0f; m_nEvadeAmount = 0; field_1367 = 0; - m_nShotDelay = 0; - field_1376 = 0.0f; + m_nHitAnimDelayTimer = 0; + m_fAttackButtonCounter = 0.0f; m_bHaveTargetSelected = false; m_bHasLockOnTarget = false; m_bCanBeDamaged = true; @@ -1024,10 +1024,10 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) if (padUsed->WeaponJustDown()) { m_bHaveTargetSelected = true; } else if (!m_bHaveTargetSelected) { - field_1376 += CTimer::GetTimeStepNonClipped(); + m_fAttackButtonCounter += CTimer::GetTimeStepNonClipped(); } } else { - field_1376 = 0.0f; + m_fAttackButtonCounter = 0.0f; m_bHaveTargetSelected = false; } SetAttack(nil); diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index c139bbbc..c6823c2d 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -20,8 +20,8 @@ public: uint8 m_nEvadeAmount; int8 field_1367; uint32 m_nSpeedTimer; - int32 m_nShotDelay; - float field_1376; // m_fAttackButtonCounter? + uint32 m_nHitAnimDelayTimer; + float m_fAttackButtonCounter; // m_fAttackButtonCounter? bool m_bHaveTargetSelected; // may have better name int8 field_1381; int8 field_1382; diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index 41d31985..46a12a6f 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -404,6 +404,7 @@ CGlass::AskForObjectToBeRenderedInGlass(CEntity *entity) void CGlass::RenderEntityInGlass(CEntity *entity) { + ASSERT(entity!=NULL); CObject *object = (CObject *)entity; if ( object->bGlassBroken ) @@ -419,7 +420,7 @@ CGlass::RenderEntityInGlass(CEntity *entity) uint8 alpha = CalcAlphaWithNormal(&fwdNorm); CColModel *col = object->GetColModel(); - + ASSERT(col!=NULL); if ( col->numTriangles >= 2 ) { CVector a = object->GetMatrix() * col->vertices[0]; @@ -523,6 +524,8 @@ CGlass::RenderEntityInGlass(CEntity *entity) int32 CGlass::CalcAlphaWithNormal(CVector *normal) { + ASSERT(normal!=NULL); + float fwdDir = 2.0f * DotProduct(*normal, TheCamera.GetForward()); float fwdDot = DotProduct(TheCamera.GetForward()-fwdDir*(*normal), CVector(0.57f, 0.57f, -0.57f)); return int32(lerp(fwdDot*fwdDot*fwdDot*fwdDot*fwdDot*fwdDot, 20.0f, 255.0f)); @@ -597,6 +600,8 @@ CGlass::RenderReflectionPolys(void) void CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector point, bool explosion) { + ASSERT(entity!=NULL); + CObject *object = (CObject *)entity; if ( object->bGlassBroken ) @@ -605,7 +610,8 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, object->bGlassCracked = true; CColModel *col = object->GetColModel(); - + ASSERT(col!=NULL); + CVector a = object->GetMatrix() * col->vertices[0]; CVector b = object->GetMatrix() * col->vertices[1]; CVector c = object->GetMatrix() * col->vertices[2]; @@ -647,6 +653,8 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, void CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) { + ASSERT(entity!=NULL); + CObject *object = (CObject *)entity; if ( amount > 50.0f && !object->bGlassCracked ) @@ -659,6 +667,8 @@ CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) void CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) { + ASSERT(entity!=NULL); + CObject *object = (CObject *)entity; if ( IsGlass(object->GetModelIndex()) ) @@ -679,6 +689,8 @@ CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) void CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point) { + ASSERT(entity!=NULL); + CObject *object = (CObject *)entity; CVector distToGlass = object->GetPosition() - point; diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp index 54fa6844..81138c0f 100644 --- a/src/weapons/BulletInfo.cpp +++ b/src/weapons/BulletInfo.cpp @@ -2,4 +2,8 @@ #include "patcher.h" #include "BulletInfo.h" +WRAPPER void CBulletInfo::Initialise(void) { EAXJMP(0x558220); } +WRAPPER void CBulletInfo::Shutdown(void) { EAXJMP(0x558450); } +WRAPPER void CBulletInfo::AddBullet(CEntity *firingEntity, eWeaponType type, CVector pos, CVector velocity) { EAXJMP(0x558470); } +WRAPPER void CBulletInfo::Update(void) { EAXJMP(0x558550); } WRAPPER bool CBulletInfo::TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2) { EAXJMP(0x558D40); } diff --git a/src/weapons/BulletInfo.h b/src/weapons/BulletInfo.h index 3905b56d..b10ef0a1 100644 --- a/src/weapons/BulletInfo.h +++ b/src/weapons/BulletInfo.h @@ -1,7 +1,14 @@ #pragma once +class CEntity; +enum eWeaponType; + class CBulletInfo { public: + static void Initialise(void); + static void Shutdown(void); + static void AddBullet(CEntity *firingEntity, eWeaponType type, CVector pos, CVector velocity); + static void Update(void); static bool TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2); }; \ No newline at end of file diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 0f41264f..d4312649 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1,23 +1,91 @@ #include "common.h" #include "patcher.h" #include "Weapon.h" -#include "Timer.h" -#include "WeaponInfo.h" +#include "AnimBlendAssociation.h" +#include "AudioManager.h" +#include "BulletInfo.h" +#include "Camera.h" +#include "Coronas.h" +#include "DMAudio.h" +#include "Explosion.h" +#include "General.h" +#include "Glass.h" +#include "Heli.h" +#include "ModelIndices.h" +#include "Object.h" +#include "Pad.h" +#include "Particle.h" #include "Ped.h" +#include "PointLights.h" +#include "Pools.h" +#include "ProjectileInfo.h" +#include "RpAnimBlend.h" +#include "ShotInfo.h" +#include "SpecialFX.h" +#include "Stats.h" +#include "TempColModels.h" +#include "Timer.h" +#include "Vehicle.h" +#include "WaterLevel.h" +#include "WeaponInfo.h" #include "World.h" -WRAPPER void CWeapon::ShutdownWeapons(void) { EAXJMP(0x55C2F0); } -WRAPPER void CWeapon::UpdateWeapons(void) { EAXJMP(0x55C310); } -WRAPPER bool CWeapon::Fire(CEntity*, CVector*) { EAXJMP(0x55C380); } -WRAPPER void CWeapon::FireFromCar(CAutomobile *car, bool left) { EAXJMP(0x55C940); } -WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); } -WRAPPER void CWeapon::Update(int32 audioEntity) { EAXJMP(0x563A10); } -WRAPPER void CWeapon::DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end) { EAXJMP(0x563200); } -WRAPPER void CWeapon::InitialiseWeapons(void) { EAXJMP(0x55C2D0); } -WRAPPER void FireOneInstantHitRound(CVector* shotSource, CVector* shotTarget, int32 damage) { EAXJMP(0x563B00); } +uint16 gReloadSampleTime[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS] = +{ + /*UNARMED*/ 0, + /*BASEBALLBAT*/ 0, + /*COLT45*/ 250, + /*UZI*/ 400, + /*SHOTGUN*/ 650, + /*AK47*/ 300, + /*M16*/ 300, + /*SNIPERRIFLE*/ 423, + /*ROCKETLAUNCHER*/ 400, + /*FLAMETHROWER*/ 0, + /*MOLOTOV*/ 0, + /*GRENADE*/ 0, + /*DETONATOR*/ 0 +}; + +CWeaponInfo * +CWeapon::GetInfo() +{ + CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType); + ASSERT(info!=NULL); + return info; +} void -CWeapon::Initialise(eWeaponType type, int ammo) +CWeapon::InitialiseWeapons(void) +{ + CWeaponInfo::Initialise(); + CShotInfo::Initialise(); + CExplosion::Initialise(); + CProjectileInfo::Initialise(); + CBulletInfo::Initialise(); +} + +void +CWeapon::ShutdownWeapons(void) +{ + CWeaponInfo::Shutdown(); + CShotInfo::Shutdown(); + CExplosion::Shutdown(); + CProjectileInfo::Shutdown(); + CBulletInfo::Shutdown(); +} + +void +CWeapon::UpdateWeapons(void) +{ + CShotInfo::Update(); + CExplosion::Update(); + CProjectileInfo::Update(); + CBulletInfo::Update(); +} + +void +CWeapon::Initialise(eWeaponType type, int32 ammo) { m_eWeaponType = type; m_eWeaponState = WEAPONSTATE_READY; @@ -30,13 +98,1872 @@ CWeapon::Initialise(eWeaponType type, int ammo) m_nTimer = 0; } +bool +CWeapon::Fire(CEntity *shooter, CVector *fireSource) +{ + ASSERT(shooter!=NULL); + + CVector fireOffset(0.0f, 0.0f, 0.6f); + CVector *source = fireSource; + + if ( !fireSource ) + source = &(shooter->GetMatrix() * fireOffset); + + if ( m_bAddRotOffset ) + { + float heading = RADTODEG(shooter->GetForward().Heading()); + float angle = DEGTORAD(heading); + (*source).x += -Sin(angle) * 0.15f; + (*source).y += Cos(angle) * 0.15f; + } + + if ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING ) + return false; + + bool fired; + + if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE ) + { + if ( m_nAmmoInClip <= 0 ) + return false; + + switch ( m_eWeaponType ) + { + case WEAPONTYPE_SHOTGUN: + { + fired = FireShotgun(shooter, source); + + break; + } + + case WEAPONTYPE_COLT45: + case WEAPONTYPE_UZI: + case WEAPONTYPE_AK47: + { + fired = FireInstantHit(shooter, source); + + break; + } + + case WEAPONTYPE_SNIPERRIFLE: + { + fired = FireSniper(shooter); + + break; + } + + case WEAPONTYPE_M16: + { + if ( TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON && shooter == FindPlayerPed() ) + fired = FireM16_1stPerson(shooter); + else + fired = FireInstantHit(shooter, source); + + break; + } + + case WEAPONTYPE_ROCKETLAUNCHER: + { + if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != NULL ) + { + float distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude(); + + if ( distToTarget > 8.0f || ((CPed*)shooter)->IsPlayer() ) + fired = FireProjectile(shooter, source, 0.0f); + else + fired = false; + } + else + fired = FireProjectile(shooter, source, 0.0f); + + break; + } + + case WEAPONTYPE_MOLOTOV: + case WEAPONTYPE_GRENADE: + { + if ( shooter == FindPlayerPed() ) + { + fired = FireProjectile(shooter, source, ((CPlayerPed*)shooter)->m_fAttackButtonCounter*0.0375f); + if ( m_eWeaponType == WEAPONTYPE_GRENADE ) + CStats::KgsOfExplosivesUsed++; + } + else if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != NULL ) + { + float distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude(); + float power = clamp((distToTarget-10.0f)*0.02f, 0.2f, 1.0f); + + fired = FireProjectile(shooter, source, power); + } + else + fired = FireProjectile(shooter, source, 0.3f); + + break; + } + + case WEAPONTYPE_FLAMETHROWER: + { + fired = FireAreaEffect(shooter, source); + + break; + } + + case WEAPONTYPE_DETONATOR: + { + CWorld::UseDetonator(shooter); + m_nAmmoTotal = 1; + m_nAmmoInClip = m_nAmmoTotal; + fired = true; + + break; + } + + case WEAPONTYPE_HELICANNON: + { + if ( (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON ) + && shooter == FindPlayerPed() ) + { + fired = FireM16_1stPerson(shooter); + } + else + fired = FireInstantHit(shooter, source); + + break; + } + + default: + { + debug("Unknown weapon type, Weapon.cpp"); + break; + } + } + + if ( fired ) + { + bool isPlayer = false; + + if ( shooter->IsPed() ) + { + CPed *shooterPed = (CPed*)shooter; + + shooterPed->bIsShooting = true; + + if ( shooterPed->IsPlayer() ) + isPlayer = true; + + DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); + } + + if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; + if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) ) m_nAmmoTotal--; + + if ( m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER ) + DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f); + + m_eWeaponState = WEAPONSTATE_FIRING; + } + + if ( m_nAmmoInClip == 0 ) + { + if ( m_nAmmoTotal == 0 ) + return true; + + m_eWeaponState = WEAPONSTATE_RELOADING; + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; + + if ( shooter == FindPlayerPed() ) + { + if ( CWorld::Players[CWorld::PlayerInFocus].m_bFastReload ) + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4; + } + + return true; + } + + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; + if ( shooter == FindPlayerPed() ) + CStats::RoundsFiredByPlayer++; + } + else + { + if ( m_eWeaponState != WEAPONSTATE_FIRING ) + { + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; + m_eWeaponState = WEAPONSTATE_FIRING; + } + + FireMelee(shooter, *source); + } + + if ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT ) + return true; + else + return fired; +} + +bool +CWeapon::FireFromCar(CAutomobile *shooter, bool left) +{ + ASSERT(shooter!=NULL); + + if ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING ) + return false; + + if ( m_nAmmoInClip <= 0 ) + return false; + + if ( FireInstantHitFromCar(shooter, left) ) + { + DMAudio.PlayOneShot(shooter->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); + + if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; + if ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 ) m_nAmmoTotal--; + + m_eWeaponState = WEAPONSTATE_FIRING; + + if ( m_nAmmoInClip == 0 ) + { + if ( m_nAmmoTotal == 0 ) + return true; + + m_eWeaponState = WEAPONSTATE_RELOADING; + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; + + return true; + } + + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; + if ( shooter == FindPlayerVehicle() ) + CStats::RoundsFiredByPlayer++; + } + + return true; +} + +bool +CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) +{ + ASSERT(shooter!=NULL); + + CWeaponInfo *info = GetInfo(); + + bool anim2Playing = false; + if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), info->m_Anim2ToPlay) ) + anim2Playing = true; + + ASSERT(shooter->IsPed()); + + CPed *shooterPed = (CPed*)shooter; + + for ( int32 i = 0; i < shooterPed->m_numNearPeds; i++ ) + { + CPed *victimPed = shooterPed->m_nearPeds[i]; + ASSERT(victimPed!=NULL); + + if ( (victimPed->m_nPedType != shooterPed->m_nPedType || victimPed == shooterPed->m_pSeekTarget) + && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) ) + { + bool collided = false; + + CColModel *victimPedCol = &CTempColModels::ms_colModelPed1; + if ( victimPed->OnGround() || !victimPed->IsPedHeadAbovePos(-0.3f) ) + victimPedCol = &CTempColModels::ms_colModelPedGroundHit; + + ASSERT(victimPedCol!=NULL); + + float victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius; + if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() ) + { + CVector victimPedPos = victimPed->GetPosition(); + if ( SQR(victimPedRadius) > (victimPedPos-(*fireSource)).MagnitudeSqr() ) + { + CVector collisionDist; + + int32 s = 0; + while ( s < victimPedCol->numSpheres ) + { + CColSphere *sphere = &victimPedCol->spheres[s]; + collisionDist = victimPedPos+sphere->center-(*fireSource); + + if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() ) + { + collided = true; + break; + } + s++; + } + + if ( !(victimPed->IsPlayer() && victimPed->GetPedState() == PED_GETUP) ) + { + if ( collided ) + { + float victimPedHealth = victimPed->m_fHealth; + CVector bloodPos = fireSource + collisionDist*0.7f; + + CVector2D posOffset(shooterPed->GetPosition().x-victimPedPos.x, shooterPed->GetPosition().y-victimPedPos.y); + + int32 localDir = victimPed->GetLocalDirection(posOffset); + + bool isBat = m_eWeaponType == WEAPONTYPE_BASEBALLBAT; + + if ( !victimPed->DyingOrDead() ) + victimPed->ReactToAttack(shooterPed); + + uint8 hitLevel = HITLEVEL_HIGH; + if ( isBat && victimPed->OnGround() ) + hitLevel = HITLEVEL_GROUND; + + victimPed->StartFightDefend(localDir, hitLevel, 10); + + if ( !victimPed->DyingOrDead() ) + { + if ( shooterPed->IsPlayer() && isBat && anim2Playing ) + victimPed->InflictDamage(shooterPed, m_eWeaponType, 100.0f, PEDPIECE_TORSO, localDir); + else if ( shooterPed->IsPlayer() && ((CPlayerPed*)shooterPed)->m_bAdrenalineActive ) + victimPed->InflictDamage(shooterPed, m_eWeaponType, 3.5f*info->m_nDamage, PEDPIECE_TORSO, localDir); + else + { + if ( victimPed->IsPlayer() && isBat ) // wtf, it's not fair + victimPed->InflictDamage(shooterPed, m_eWeaponType, 2.0f*info->m_nDamage, PEDPIECE_TORSO, localDir); + else + victimPed->InflictDamage(shooterPed, m_eWeaponType, info->m_nDamage, PEDPIECE_TORSO, localDir); + } + } + + if ( CGame::nastyGame ) + { + if ( victimPed->GetIsOnScreen() ) + { + CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr()); + + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + + if ( isBat ) + { + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + } + } + } + + if ( !victimPed->OnGround() ) + { + if ( victimPed->m_fHealth > 0.0f + && (victimPed->m_fHealth < 20.0f && victimPedHealth > 20.0f || isBat && !victimPed->IsPlayer()) ) + { + posOffset.Normalise(); + victimPed->bIsStanding = false; + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); + + if ( isBat && victimPed->IsPlayer() ) + victimPed->SetFall(3000, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); + else + victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); + + shooterPed->m_pSeekTarget = victimPed; + shooterPed->m_pSeekTarget->RegisterReference(&shooterPed->m_pSeekTarget); + } + } + else if (victimPed->Dying() && !anim2Playing) + { + posOffset.Normalise(); + victimPed->bIsStanding = false; + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); + } + + m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; + + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + else + CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + } + } + } + } + } + } + + return true; +} + +bool +CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) +{ + ASSERT(shooter!=NULL); + ASSERT(fireSource!=NULL); + + CWeaponInfo *info = GetInfo(); + + CVector source, target; + CColPoint point; + CEntity *victim = NULL; + + float heading = RADTODEG(shooter->GetForward().Heading()); + float angle = DEGTORAD(heading); + + CVector2D ahead(-Sin(angle), Cos(angle)); + ahead.Normalise(); + + CVector vel = ((CPed *)shooter)->m_vecMoveSpeed; + int32 shooterMoving = false; + if ( Abs(vel.x) > 0.0f && Abs(vel.y) > 0.0f ) + shooterMoving = true; + + if ( shooter == FindPlayerPed() ) + { + static float prev_heading = 0.0f; + prev_heading = ((CPed*)shooter)->m_fRotationCur; + } + + if ( shooter->IsPed() && ((CPed *)shooter)->m_pPointGunAt ) + { + CPed *shooterPed = (CPed *)shooter; + if ( shooterPed->m_pedIK.m_flags & CPedIK::GUN_POINTED_SUCCESSFULLY ) + { + int32 accuracy = shooterPed->m_wepAccuracy; + int32 inaccuracy = 100-accuracy; + + if ( accuracy != 100 ) + FindPlayerPed(); //what ? + + CPed *threatAttack = (CPed*)shooterPed->m_pPointGunAt; + if ( threatAttack->IsPed() ) + { + threatAttack->m_pedIK.GetComponentPosition(target, PED_MID); + threatAttack->ReactToPointGun(shooter); + } + else + target = threatAttack->GetPosition(); + + target -= *fireSource; + target *= info->m_fRange / target.Magnitude(); + target += *fireSource; + + if ( inaccuracy != 0 ) + { + target.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; + target.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; + target.z += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * inaccuracy; + } + + CWorld::bIncludeDeadPeds = true; + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeDeadPeds = false; + } + else + { + target.x = info->m_fRange; + target.y = 0.0f; + target.z = 0.0f; + + for (RwFrame *i = shooterPed->GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i)) + RwV3dTransformPoints(target, target, 1, RwFrameGetMatrix(i)); + + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + } + } + else if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) + { + CVector src, trgt; + TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, src, trgt); + + CWorld::bIncludeDeadPeds = true; + ProcessLineOfSight(src, trgt,point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeDeadPeds = false; + + int32 rotSpeed = 1; + if ( m_eWeaponType == WEAPONTYPE_M16 ) + rotSpeed = 4; + + CVector bulletPos; + if ( CHeli::TestBulletCollision(&src, &trgt, &bulletPos, 4) ) + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, rotSpeed); + } + } + else + { + float shooterHeading = RADTODEG(shooter->GetForward().Heading()); + float shooterAngle = DEGTORAD(shooterHeading); + + CVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle)); + rotOffset.Normalise(); + + target = *fireSource; + target.x = rotOffset.x * info->m_fRange; + target.y = rotOffset.y * info->m_fRange; + + if ( shooter->IsPed() ) + DoDoomAiming(shooter, fireSource, &target); + + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + + int32 rotSpeed = 1; + if ( m_eWeaponType == WEAPONTYPE_M16 ) + rotSpeed = 4; + + CVector bulletPos; + if ( CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4) ) + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, rotSpeed); + } + } + + if ( victim && shooter->IsPed() && victim == ((CPed*)shooter)->m_leader ) + return false; + + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed *)shooter, 1000); + + if ( shooter == FindPlayerPed() ) + { + CStats::InstantHitsFiredByPlayer++; + if ( !(CTimer::GetFrameCounter() & 3) ) + MakePedsJumpAtShot((CPhysical*)shooter, fireSource, &target); + } + + switch ( m_eWeaponType ) + { + case WEAPONTYPE_AK47: + { + static uint8 counter = 0; + + if ( !(++counter & 1) ) + { + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CVector gunflashPos = *fireSource; + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.10f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f); + gunflashPos += CVector(0.05f*ahead.x, 0.05f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + + CVector gunsmokePos = *fireSource; + float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); + + CVector gunshellPos = *fireSource; + gunshellPos -= CVector(0.5f*ahead.x, 0.5f*ahead.y, 0.0f); + CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + dir.Normalise2D(); + AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.018f); + } + + break; + } + + case WEAPONTYPE_M16: + { + static uint8 counter = 0; + + if ( !(++counter & 1) ) + { + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CVector gunflashPos = *fireSource; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + + gunflashPos = *fireSource; + gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); + gunflashPos.z += 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos.z += 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + gunflashPos.z += 0.03f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + gunflashPos = *fireSource; + gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); + gunflashPos.z -= 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos.z -= 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + gunflashPos.z -= 0.03f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + CVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + offset.Normalise2D(); + + gunflashPos = *fireSource; + gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); + gunflashPos += CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos += CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + gunflashPos += CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + gunflashPos = *fireSource; + gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); + gunflashPos -= CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos -= CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + gunflashPos -= CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + CVector gunsmokePos = *fireSource; + float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); + + CVector gunshellPos = *fireSource; + gunshellPos -= CVector(0.65f*ahead.x, 0.65f*ahead.y, 0.0f); + CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + dir.Normalise2D(); + AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.02f); + } + + break; + } + + case WEAPONTYPE_UZI: + { + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CVector gunflashPos = *fireSource; + + if ( shooterMoving ) + gunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.07f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.05f); + gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + gunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + gunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + gunflashPos += CVector(0.02f*ahead.x, 0.02f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.01f); + + CVector gunsmokePos = *fireSource; + float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); + + CVector gunshellPos = *fireSource; + gunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f); + CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + dir.Normalise2D(); + AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f); + + break; + } + + case WEAPONTYPE_COLT45: + { + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CVector gunflashPos = *fireSource; + + if ( shooterMoving ) + gunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + CVector gunsmokePos = *fireSource; + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.10f, ahead.y*0.10f, 0.0f), NULL, 0.005f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.15f, ahead.y*0.15f, 0.0f), NULL, 0.015f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.20f, ahead.y*0.20f, 0.0f), NULL, 0.025f); + + CVector gunshellPos = *fireSource; + gunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f); + CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + dir.Normalise2D(); + AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f); + + break; + } + } + + DoBulletImpact(shooter, victim, fireSource, &target, &point, ahead); + + return true; +} + +void +CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &direction, float size) +{ + ASSERT(shooter!=NULL); + + if ( shooter == NULL) + return; + + CVector dir(direction.x*0.05f, direction.y*0.05f, CGeneral::GetRandomNumberInRange(0.02f, 0.08f)); + + static CVector prevEntityPosition(0.0f, 0.0f, 0.0f); + CVector entityPosition = shooter->GetPosition(); + + CVector diff = entityPosition - prevEntityPosition; + + if ( Abs(diff.x)+Abs(diff.y)+Abs(diff.z) > 1.5f ) + { + prevEntityPosition = entityPosition; + + CParticle::AddParticle(PARTICLE_GUNSHELL_FIRST, + source, dir, NULL, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); + } + else + { + CParticle::AddParticle(PARTICLE_GUNSHELL, + source, dir, NULL, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); + } +} + +void +CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, + CVector *source, CVector *target, CColPoint *point, CVector2D ahead) +{ + ASSERT(shooter!=NULL); + ASSERT(source!=NULL); + ASSERT(target!=NULL); + ASSERT(point!=NULL); + + CWeaponInfo *info = GetInfo(); + + if ( victim ) + { + CGlass::WasGlassHitByBullet(victim, point->point); + + CVector traceTarget = *target; + CBulletTraces::AddTrace(source, &traceTarget); + + if ( shooter != NULL ) + { + if ( shooter == FindPlayerPed() ) + { + if ( victim->IsPed() || victim->IsVehicle() ) + CStats::InstantHitsHitByPlayer++; + } + } + + if ( victim->IsPed() && ((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 ) + { + CPed *victimPed = (CPed *)victim; + if ( !victimPed->OnGround() && victim != shooter ) + { + if ( victimPed->DoesLOSBulletHitPed(*point) ) + { + CVector pos = victimPed->GetPosition(); + + CVector2D posOffset(source->x-pos.x, source->y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); + + victimPed->ReactToAttack(shooter); + + if ( !victimPed->IsPedInControl() || victimPed->bIsDucking ) + { + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); + } + else + { + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) + { + posOffset.Normalise(); + victimPed->bIsStanding = false; + + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 5.0f); + victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); + + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); + } + else + { + if ( victimPed->IsPlayer() ) + { + CPlayerPed *victimPlayer = (CPlayerPed *)victimPed; + if ( victimPlayer->m_nHitAnimDelayTimer < CTimer::GetTimeInMilliseconds() ) + { + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); + ASSERT(asoc!=NULL); + + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; + + if ( m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_M16 ) + victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 2500; + else + victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 1000; + } + } + else + { + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); + ASSERT(asoc!=NULL); + + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; + } + + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); + } + } + + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + else + CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + + if ( CGame::nastyGame ) + { + uint8 bloodAmount = 8; + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) + bloodAmount = 32; + + CVector dir = (point->point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; + + if ( victimPed->GetIsOnScreen() ) + { + for ( uint8 i = 0; i < bloodAmount; i++ ) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point, dir); + } + } + } + } + else + { + if ( CGame::nastyGame ) + { + CVector dir = (point->point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; + + if ( victim->GetIsOnScreen() ) + { + for ( int32 i = 0; i < 8; i++ ) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point + CVector(0.0f, 0.0f, 0.15f), dir); + } + + if ( victimPed->Dead() ) + { + CAnimBlendAssociation *asoc; + if ( RpAnimBlendClumpGetFirstAssociation(victimPed->GetClump(), ASSOC_FLAG800) ) + asoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f); + else + asoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f); + + if ( asoc ) + { + asoc->SetCurrentTime(0.0f); + asoc->flags |= ASSOC_RUNNING; + asoc->flags &= ~ASSOC_FADEOUTWHENDONE; + } + } + } + } + } + else + { + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); + + CVector dist = point->point - (*source); + CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(ahead.x, ahead.y, 0.0f); + CVector smokePos = *source + offset; + + smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + smokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + smokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + + break; + } + case ENTITY_TYPE_VEHICLE: + { + ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); + + CVector dist = point->point - (*source); + CVector offset = dist - max(0.2f*dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f); + CVector smokePos = *source + offset; + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + + if ( shooter->IsPed() ) + { + CPed *shooterPed = (CPed *)shooter; + + if ( shooterPed->bNotAllowedToDuck ) + { + if ( shooterPed->bKindaStayInSamePlace && victim != shooterPed->m_pPointGunAt ) + { + shooterPed->bKindaStayInSamePlace = false; + shooterPed->m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + 15000; + } + } + } + + break; + } + case ENTITY_TYPE_OBJECT: + { + for ( int32 i = 0; i < 8; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); + + CObject *victimObject = (CObject *)victim; + + if ( !victimObject->bInfiniteMass ) + { + if ( victimObject->bIsStatic && victimObject->m_fUprootLimit <= 0.0f ) + { + victimObject->bIsStatic = false; + victimObject->AddToMovingList(); + } + + if ( !victimObject->bIsStatic ) + { + CVector moveForce = point->normal*-4.0f; + victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); + } + } + + break; + } + } + } + + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point->point); + break; + } + case ENTITY_TYPE_VEHICLE: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + case ENTITY_TYPE_PED: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); + break; + } + case ENTITY_TYPE_OBJECT: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point->point); + break; + } + case ENTITY_TYPE_DUMMY: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point->point); + break; + } + } + } + else + CBulletTraces::AddTrace(source, target); + + if ( shooter == FindPlayerPed() ) + CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); + + BlowUpExplosiveThings(victim); +} + +bool +CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) +{ + ASSERT(shooter!=NULL); + ASSERT(fireSource!=NULL); + + CWeaponInfo *info = GetInfo(); + + float heading = RADTODEG(shooter->GetForward().Heading()); + float angle = DEGTORAD(heading); + + CVector2D rotOffset(-Sin(angle), Cos(angle)); + rotOffset.Normalise(); + + CVector gunflashPos = *fireSource; + gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f); + gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.15f); + gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.2f); + CParticle::AddParticle(PARTICLE_GUNFLASH, *fireSource, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f); + + CVector gunsmokePos = *fireSource; + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.10f, rotOffset.y*0.10f, 0.0f), NULL, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.15f, rotOffset.y*0.15f, 0.0f), NULL, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.20f, rotOffset.y*0.20f, 0.0f), NULL, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.25f, rotOffset.y*0.25f, 0.0f), NULL, 0.1f); + + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000); + + CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0, 0.0, 0.0), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + float shooterAngle; + + if ( shooter->IsPed() && ((CPed*)shooter)->m_pPointGunAt != NULL ) + { + CEntity *threatAttack = ((CPed*)shooter)->m_pPointGunAt; + shooterAngle = CGeneral::GetAngleBetweenPoints(threatAttack->GetPosition().x, threatAttack->GetPosition().y, + (*fireSource).x, (*fireSource).y); + } + else + shooterAngle = RADTODEG(shooter->GetForward().Heading()); + + + for ( int32 i = 0; i < 5; i++ ) // five shoots at once + { + float shootAngle = DEGTORAD(7.5f*i + shooterAngle - 15.0f); + CVector2D shootRot(-Sin(shootAngle), Cos(shootAngle)); + + CVector source, target; + CColPoint point; + CEntity *victim; + + if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) + { + TheCamera.Find3rdPersonCamTargetVector(1.0f, *fireSource, source, target); + CVector Left = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Front, TheCamera.Cams[TheCamera.ActiveCam].Up); + + float f = float(i - 2) * (DEGTORAD(7.5f) / 2); + target = f * Left + target - source; + target *= info->m_fRange; + target += source; + + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + } + else + { + target = *fireSource; + target.x += shootRot.x * info->m_fRange; + target.y += shootRot.y * info->m_fRange; + + if ( shooter->IsPed() ) + { + CPed *shooterPed = (CPed *)shooter; + + if ( shooterPed->m_pPointGunAt == NULL ) + DoDoomAiming(shooter, fireSource, &target); + else + { + float distToTarget = (shooterPed->m_pPointGunAt->GetPosition() - (*fireSource)).Magnitude2D(); + target.z += info->m_fRange / distToTarget * (shooterPed->m_pPointGunAt->GetPosition().z - target.z); + } + } + + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + } + + if ( victim ) + { + CGlass::WasGlassHitByBullet(victim, point.point); + + CBulletTraces::AddTrace(fireSource, &point.point); + + if ( victim->IsPed() ) + { + CPed *victimPed = (CPed *)victim; + if ( !victimPed->OnGround() && victim != shooter && victimPed->DoesLOSBulletHitPed(point) ) + { + bool cantStandup = true; + + CVector pos = victimPed->GetPosition(); + + CVector2D posOffset((*fireSource).x-pos.x, (*fireSource).y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); + + victimPed->ReactToAttack(FindPlayerPed()); + + posOffset.Normalise(); + + if ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) ) + cantStandup = false; + + if ( victimPed->bIsStanding && cantStandup ) + { + victimPed->bIsStanding = false; + + victimPed->ApplyMoveForce(posOffset.x*-6.0f, posOffset.y*-6.0f, 5.0f); + } + else + victimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 0.0f); + + if ( cantStandup ) + victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); + + victimPed->InflictDamage(NULL, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); + + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + else + CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + + if ( CGame::nastyGame ) + { + uint8 bloodAmount = 8; + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN ) + bloodAmount = 32; + + CVector dir = (point.point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; + + if ( victimPed->GetIsOnScreen() ) + { + for ( uint8 i = 0; i < bloodAmount; i++ ) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point, dir); + } + } + } + } + else + { + switch ( victim->m_type ) + { + case ENTITY_TYPE_VEHICLE: + { + ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); + + CVector dist = point.point - (*fireSource); + CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); + CVector smokePos = *fireSource + offset; + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + + break; + } + + case ENTITY_TYPE_BUILDING: + case ENTITY_TYPE_OBJECT: + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); + + CVector dist = point.point - (*fireSource); + CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); + CVector smokePos = *fireSource + offset; + + smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + smokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + smokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + + if ( victim->IsObject() ) + { + CObject *victimObject = (CObject *)victim; + + if ( !victimObject->bInfiniteMass ) + { + if ( victimObject->bIsStatic && victimObject->m_fUprootLimit <= 0.0f ) + { + victimObject->bIsStatic = false; + victimObject->AddToMovingList(); + } + + if ( !victimObject->bIsStatic ) + { + CVector moveForce = point.normal*-5.0f; + victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); + } + } + } + + break; + } + } + } + + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point); + break; + } + case ENTITY_TYPE_VEHICLE: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + case ENTITY_TYPE_PED: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); + break; + } + case ENTITY_TYPE_OBJECT: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); + break; + } + case ENTITY_TYPE_DUMMY: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point); + break; + } + } + } + else + { + CVector traceTarget = *fireSource; + traceTarget += (target - (*fireSource)) * min(info->m_fRange, 30.0f) / info->m_fRange; + CBulletTraces::AddTrace(fireSource, &traceTarget); + } + } + + if ( shooter == FindPlayerPed() ) + CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); + + return true; +} + +bool +CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) +{ + ASSERT(shooter!=NULL); + ASSERT(fireSource!=NULL); + + CVector source, target; + + if ( m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER ) + { + source = *fireSource; + + if ( shooter->IsPed() && ((CPed*)shooter)->IsPlayer() ) + { + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (!( mode == CCam::MODE_M16_1STPERSON + || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_M16_1STPERSON_RUNABOUT + || mode == CCam::MODE_SNIPER_RUNABOUT + || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) ) + { + return false; + } + + *fireSource += TheCamera.Cams[TheCamera.ActiveCam].Front; + } + else + *fireSource += shooter->GetForward(); + + target = *fireSource; + } + else + { + float dot = DotProduct(*fireSource-shooter->GetPosition(), shooter->GetForward()); + + if ( dot < 0.3f ) + *fireSource += (0.3f-dot) * shooter->GetForward(); + + target = *fireSource; + + if ( target.z - shooter->GetPosition().z > 0.0f ) + target += 0.6f*shooter->GetForward(); + + source = *fireSource - shooter->GetPosition(); + + source = *fireSource - DotProduct(source, shooter->GetForward()) * shooter->GetForward(); + } + + if ( !CWorld::GetIsLineOfSightClear(source, target, true, true, false, true, false, false, false) ) + { + if ( m_eWeaponType != WEAPONTYPE_GRENADE ) + CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource); + else + { + if ( shooter->IsPed() ) + { + source = shooter->GetPosition() - shooter->GetForward(); + source.z -= 0.4f; + + if ( !CWorld::TestSphereAgainstWorld(source, 0.5f, NULL, false, false, true, false, false, false) ) + CProjectileInfo::AddProjectile(shooter, m_eWeaponType, source, 0.0f); + else + CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource); + } + } + } + else + CProjectileInfo::AddProjectile(shooter, m_eWeaponType, *fireSource, power); + + return true; +} + +void +CWeapon::GenerateFlameThrowerParticles(CVector pos, CVector dir) +{ + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); + + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); + + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); + + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); + + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); +} + +bool +CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) +{ + ASSERT(shooter!=NULL); + ASSERT(fireSource!=NULL); + + CWeaponInfo *info = GetInfo(); + + float heading = RADTODEG(shooter->GetForward().Heading()); + + CVector source; + CVector target; + CVector dir; + + if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) + { + TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target); + float norm = (1.0f / info->m_fRange); + dir = (target - source) * norm; + } + else + { + float angle = DEGTORAD(heading); + dir = CVector(-Sin(angle)*0.5f, Cos(angle)*0.5f, 0.0f); + target = *fireSource + dir; + } + + CShotInfo::AddShot(shooter, m_eWeaponType, *fireSource, target); + CWeapon::GenerateFlameThrowerParticles(*fireSource, dir); + + return true; +} + +bool +CWeapon::FireSniper(CEntity *shooter) +{ + ASSERT(shooter!=NULL); + + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (!( mode == CCam::MODE_M16_1STPERSON + || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_M16_1STPERSON_RUNABOUT + || mode == CCam::MODE_SNIPER_RUNABOUT + || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) ) + { + return false; + } + +#ifndef FIX_BUGS + CWeaponInfo *info = GetInfo(); //unused +#endif + + CCam *cam = &TheCamera.Cams[TheCamera.ActiveCam]; + ASSERT(cam!=NULL); + + CVector source = cam->Source; + CVector dir = cam->Front; + + if ( DotProduct(dir, CVector(0.0f, -0.9894f, 0.145f)) > 0.997f ) + CCoronas::bSmallMoon = !CCoronas::bSmallMoon; + + dir.Normalise(); + dir *= 16.0f; + + CBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir); + + if ( shooter == FindPlayerPed() ) + ++CStats::InstantHitsFiredByPlayer; + + if ( shooter == FindPlayerPed() ) + { + CPad::GetPad(0)->StartShake_Distance(240, 128, + FindPlayerPed()->GetPosition().x, + FindPlayerPed()->GetPosition().y, + FindPlayerPed()->GetPosition().z); + + CamShakeNoPos(&TheCamera, 0.2f); + } + + return true; +} + +bool +CWeapon::FireM16_1stPerson(CEntity *shooter) +{ + ASSERT(shooter!=NULL); + + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + + if (!( mode == CCam::MODE_M16_1STPERSON + || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_M16_1STPERSON_RUNABOUT + || mode == CCam::MODE_SNIPER_RUNABOUT + || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT + || mode == CCam::MODE_HELICANNON_1STPERSON) ) + { + return false; + } + + CWeaponInfo *info = GetInfo(); + + CColPoint point; + CEntity *victim; + + CWorld::bIncludeCarTyres = true; + CWorld::pIgnoreEntity = shooter; + CWorld::bIncludeDeadPeds = true; + + CCam *cam = &TheCamera.Cams[TheCamera.ActiveCam]; + ASSERT(cam!=NULL); + + CVector source = cam->Source; + CVector target = cam->Front*info->m_fRange + source; + + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeDeadPeds = false; + CWorld::pIgnoreEntity = NULL; + CWorld::bIncludeCarTyres = false; + + CVector2D front(cam->Front.x, cam->Front.y); + front.Normalise(); + + DoBulletImpact(shooter, victim, &source, &target, &point, front); + + CVector bulletPos; + if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, 4) ) + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f)); + } + + if ( shooter == FindPlayerPed() ) + { + CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); + + if ( m_eWeaponType == WEAPONTYPE_M16 ) + { + TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f; + TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f; + } + else if ( m_eWeaponType == WEAPONTYPE_HELICANNON ) + { + TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f; + TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f; + } + } + + return true; +} + +bool +CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) +{ + CWeaponInfo *info = GetInfo(); + + CVehicleModelInfo *modelInfo = shooter->GetModelInfo(); + + #define FRONTSEATPOS() (&(shooter->IsBoat() ? modelInfo->m_positions[BOAT_POS_FRONTSEAT] : modelInfo->m_positions[CAR_POS_FRONTSEAT])) + + CVector source, target; + if ( left ) + { + source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.2f, + float(CGeneral::GetRandomNumber() & 255) * 0.001f + FRONTSEATPOS()->y, + FRONTSEATPOS()->z + 0.5f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + + target = shooter->GetMatrix() * CVector(-info->m_fRange, + FRONTSEATPOS()->y, + FRONTSEATPOS()->z + 0.5f); + } + else + { + source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.2f, + float(CGeneral::GetRandomNumber() & 255) * 0.001f + FRONTSEATPOS()->y, + FRONTSEATPOS()->z + 0.5f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + target = shooter->GetMatrix() * CVector(info->m_fRange, + FRONTSEATPOS()->y, + FRONTSEATPOS()->z + 0.5f); + } + #undef FRONTSEATPOS + + if ( TheCamera.GetLookingLRBFirstPerson() && !left ) + { + source -= 0.3f * shooter->GetForward(); + target -= 0.3f * shooter->GetForward(); + } + + target += CVector(float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, + float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, + float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f); + + DoDriveByAutoAiming(FindPlayerPed(), &source, &target); + + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); + + if ( !TheCamera.GetLookingLRBFirstPerson() ) + CParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f)); + else + CamShakeNoPos(&TheCamera, 0.01f); + + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, FindPlayerPed(), 1000); + + CPointLights::AddLight(CPointLights::LIGHT_POINT, source, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CColPoint point; + CEntity *victim; + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + + if ( !(CTimer::GetFrameCounter() & 3) ) + MakePedsJumpAtShot(shooter, &source, &target); + + if ( victim ) + { + CVector traceTarget = point.point; + CBulletTraces::AddTrace(&source, &traceTarget); + + if ( victim->IsPed() ) + { + CPed *victimPed = (CPed*)victim; + + if ( !victimPed->DyingOrDead() && victim != (CEntity *)shooter ) + { + CVector pos = victimPed->GetPosition(); + + CVector2D posOffset(source.x-pos.x, source.y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); + + victimPed->ReactToAttack(FindPlayerPed()); + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); + ASSERT(asoc!=NULL); + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; + + victimPed->InflictDamage(shooter, WEAPONTYPE_UZI_DRIVEBY, 3*info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); + + pos.z += 0.8f; + + if ( victimPed->GetIsOnScreen() ) + { + if ( CGame::nastyGame ) + { + for ( int32 i = 0; i < 4; i++ ) + { + CVector dir; + dir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + dir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + dir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + + CParticle::AddParticle(PARTICLE_BLOOD, pos, dir); + } + } + } + + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victimPed, FindPlayerPed(), 10000); + else + CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victimPed, FindPlayerPed(), 10000); + } + } + else if ( victim->IsVehicle() ) + ((CVehicle *)victim)->InflictDamage(FindPlayerPed(), WEAPONTYPE_UZI_DRIVEBY, info->m_nDamage); + else + CGlass::WasGlassHitByBullet(victim, point.point); + + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point); + break; + } + case ENTITY_TYPE_VEHICLE: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + case ENTITY_TYPE_PED: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); + break; + } + case ENTITY_TYPE_OBJECT: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); + break; + } + case ENTITY_TYPE_DUMMY: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point); + break; + } + } + } + else + { + float norm = 30.0f/info->m_fRange; + CVector traceTarget = (target-source)*norm + source; + CBulletTraces::AddTrace(&source, &traceTarget); + } + + if ( shooter == FindPlayerVehicle() ) + CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y, FindPlayerVehicle()->GetPosition().z); + + return true; +} + +void +CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) +{ + ASSERT(shooter!=NULL); + ASSERT(source!=NULL); + ASSERT(target !=NULL); + +#ifndef FIX_BUGS + CEntity entity; // unused +#endif + + CPed *shooterPed = (CPed*)shooter; + if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) + return; + + int16 lastEntity; + CEntity *entities[16]; + CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, true, true, false, false); + + float closestEntityDist = 10000.0f; + int16 closestEntity; + + for ( int32 i = 0; i < lastEntity; i++ ) + { + CEntity *victim = entities[i]; + ASSERT(victim!=NULL); + + if ( (CEntity*)shooterPed != victim && shooterPed->CanSeeEntity(victim, DEGTORAD(22.5f)) ) + { + if ( !(victim->m_status == STATUS_TRAIN_MOVING + || victim->m_status == STATUS_TRAIN_NOT_MOVING + || victim->m_status == STATUS_HELI + || victim->m_status == STATUS_PLANE) ) + { + float distToVictim = (shooterPed->GetPosition()-victim->GetPosition()).Magnitude2D(); + float distToVictimZ = Abs(shooterPed->GetPosition().z-victim->GetPosition().z); + + if ( 1.5f*distToVictimZ < distToVictim ) + { + float entityDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ)); + + if ( entityDist < closestEntityDist ) + { + closestEntityDist = entityDist; + closestEntity = i; + } + } + } + } + } + + if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) + { + CEntity *victim = entities[closestEntity]; + ASSERT(victim !=NULL); + + float distToTarget = (*target - *source).Magnitude2D(); + float distToSource = (victim->GetPosition() - *source).Magnitude2D(); + + float victimZ = victim->GetPosition().z + 0.3f; + if ( victim->IsPed() ) + { + if ( ((CPed*)victim)->bIsDucking ) + victimZ -= 0.8f; + } + + (*target).z = (distToTarget / distToSource) * (victimZ - (*source).z) + (*source).z; + } +} + +void +CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CVector *target) +{ + ASSERT(shooter!=NULL); + ASSERT(driver!=NULL); + ASSERT(source!=NULL); + ASSERT(target!=NULL); + +#ifndef FIX_BUGS + CEntity entity; // unused +#endif + + int16 lastEntity; + CEntity *entities[16]; + CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, true, false, false, false); + + float closestEntityDist = 10000.0f; + int16 closestEntity; + + float normZ = (target->z - source->z) / (*target-*source).Magnitude(); + + for ( int32 i = 0; i < lastEntity; i++ ) + { + CEntity *victim = entities[i]; + + ASSERT(victim!=NULL); + + if ( shooter != victim && driver != victim ) + { + if ( !(victim->m_status == STATUS_TRAIN_MOVING + || victim->m_status == STATUS_TRAIN_NOT_MOVING + || victim->m_status == STATUS_HELI + || victim->m_status == STATUS_PLANE) ) + { + if ( !(victim->IsVehicle() && victim->bRenderScorched) ) + { + float distToVictim = (shooter->GetPosition()-victim->GetPosition()).Magnitude2D(); + float distToVictimZ = Abs(shooter->GetPosition().z - (distToVictim*normZ + victim->GetPosition().z)); + + if ( 3.0f*distToVictimZ < distToVictim ) + { + if ( CCollision::DistToLine(source, target, + &CVector(victim->GetPosition().x, victim->GetPosition().y, 0.0f)) < victim->GetBoundRadius()*3.0f ) + { + float vehicleDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ)); + if ( vehicleDist < closestEntityDist ) + { + closestEntityDist = vehicleDist; + closestEntity = i; + } + } + } + } + } + } + } + + if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) + { + CEntity *victim = entities[closestEntity]; + ASSERT(victim!=NULL); + + float distToTarget = (*target - *source).Magnitude2D(); + float distToSource = (victim->GetPosition() - *source).Magnitude2D(); + + (*target).z = (distToTarget / distToSource) * (0.3f + victim->GetPosition().z - (*source).z) + (*source).z; + } +} + +void +CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) +{ + ASSERT(shooter!=NULL); + ASSERT(source!=NULL); + ASSERT(target!=NULL); + +#ifndef FIX_BUGS + CEntity entity; // unused +#endif + + CPed *shooterPed = (CPed*)shooter; + if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) + return; + + int16 lastEntity; + CEntity *entities[16]; + CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, false, true, false, false); + + float closestEntityDist = 10000.0f; + int16 closestEntity; + + for ( int32 i = 0; i < lastEntity; i++ ) + { + CEntity *victim = entities[i]; + ASSERT(victim!=NULL); + + if ( shooter != victim ) + { + float lineDist = CCollision::DistToLine(source, target, &victim->GetPosition()); + float distToVictim = (victim->GetPosition() - shooter->GetPosition()).Magnitude(); + float pedDist = 0.15f*distToVictim + lineDist; + + if ( DotProduct((*target-*source), victim->GetPosition()-*source) > 0.0f && pedDist < closestEntityDist) + { + closestEntity = i; + closestEntityDist = pedDist; + } + } + } + + if ( closestEntityDist < DRIVEBYAUTOAIMING_MAXDIST ) + { + CEntity *victim = entities[closestEntity]; + ASSERT(victim!=NULL); + + float distToTarget = (*source - *target).Magnitude(); + float distToSource = (*source - victim->GetPosition()).Magnitude(); + *target = (distToTarget / distToSource) * (victim->GetPosition() - *source) + *source; + } +} + void CWeapon::Reload(void) { if (m_nAmmoTotal == 0) return; - CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType); + CWeaponInfo *info = GetInfo(); if (m_nAmmoTotal >= info->m_nAmountofAmmunition) m_nAmmoInClip = info->m_nAmountofAmmunition; @@ -44,10 +1971,159 @@ CWeapon::Reload(void) m_nAmmoInClip = m_nAmmoTotal; } -bool -CWeapon::IsType2Handed(void) +void +CWeapon::Update(int32 audioEntity) { - return m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType <= WEAPONTYPE_FLAMETHROWER && m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER; + switch ( m_eWeaponState ) + { + case WEAPONSTATE_MELEE_MADECONTACT: + { + m_eWeaponState = WEAPONSTATE_READY; + break; + } + + case WEAPONSTATE_FIRING: + { + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN && AEHANDLE_IS_OK(audioEntity) ) + { + uint32 timePassed = m_nTimer - gReloadSampleTime[WEAPONTYPE_SHOTGUN]; + if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); + } + + if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) + { + if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE && m_nAmmoTotal == 0 ) + m_eWeaponState = WEAPONSTATE_OUT_OF_AMMO; + else + m_eWeaponState = WEAPONSTATE_READY; + } + + break; + } + + case WEAPONSTATE_RELOADING: + { + if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_LAST_WEAPONTYPE ) + { + uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType]; + if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); + } + + if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) + { + Reload(); + m_eWeaponState = WEAPONSTATE_READY; + } + + break; + } + } +} + +void +FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) +{ + ASSERT(source!=NULL); + ASSERT(target!=NULL); + + CParticle::AddParticle(PARTICLE_GUNFLASH, *source, CVector(0.0f, 0.0f, 0.0f)); + + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *source, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CColPoint point; + CEntity *victim; + CWorld::ProcessLineOfSight(*source, *target, point, victim, true, true, true, true, true, true, false); + + CParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, (*target) - (*source) * 0.15f); + + if ( victim ) + { + if ( victim->IsPed() ) + { + CPed *victimPed = (CPed *)victim; + if ( !victimPed->DyingOrDead() ) + { + CVector pos = victimPed->GetPosition(); + + CVector2D posOffset((*source).x-pos.x, (*source).y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); + + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); + ASSERT(asoc!=NULL); + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; + + victimPed->InflictDamage(NULL, WEAPONTYPE_UZI, damage, (ePedPieceTypes)point.pieceB, localDir); + + pos.z += 0.8f; + + if ( victimPed->GetIsOnScreen() ) + { + if ( CGame::nastyGame ) + { + for ( int32 i = 0; i < 4; i++ ) + { + CVector dir; + dir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + dir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + dir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + + CParticle::AddParticle(PARTICLE_BLOOD, pos, dir); + } + } + } + } + } + else if ( victim->IsVehicle() ) + ((CVehicle *)victim)->InflictDamage(NULL, WEAPONTYPE_UZI, damage); + //BUG ? no CGlass::WasGlassHitByBullet + + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point); + CParticle::AddParticle(PARTICLE_SMOKE, point.point, CVector(0.0f, 0.0f, 0.01f)); + break; + } + case ENTITY_TYPE_VEHICLE: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + case ENTITY_TYPE_PED: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); + break; + } + case ENTITY_TYPE_OBJECT: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); + break; + } + case ENTITY_TYPE_DUMMY: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point); + break; + } + } + } + else + { + float waterLevel; + if ( CWaterLevel::GetWaterLevel((*target).x, (*target).y, (*target).z + 10.0f, &waterLevel, false) ) + { + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, CVector((*target).x, (*target).y, waterLevel), CVector(0.0f, 0.0f, 0.01f)); + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_WATER, point.point); // no sound(empty) + } + } } bool @@ -57,32 +2133,75 @@ CWeapon::IsTypeMelee(void) } bool -CWeapon::HitsGround(CEntity *holder, CVector *firePos, CEntity *aimingTo) +CWeapon::IsType2Handed(void) { + return m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType <= WEAPONTYPE_FLAMETHROWER && m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER; +} + +void +CWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target) +{ + ASSERT(shooter!=NULL); + ASSERT(source!=NULL); + ASSERT(target!=NULL); + + float minx = min(source->x, target->x) - 2.0f; + float maxx = max(source->x, target->x) + 2.0f; + float miny = min(source->y, target->y) - 2.0f; + float maxy = max(source->y, target->y) + 2.0f; + float minz = min(source->z, target->z) - 2.0f; + float maxz = max(source->z, target->z) + 2.0f; + + for ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) + { + CPed *ped = CPools::GetPedPool()->GetSlot(i); + + if ( ped ) + { + if ( ped->GetPosition().x > minx && ped->GetPosition().x < maxx + && ped->GetPosition().y > miny && ped->GetPosition().y < maxy + && ped->GetPosition().z > minz && ped->GetPosition().z < maxz ) + { + if ( ped != FindPlayerPed() && (uint8)(ped->m_randomSeed ^ CGeneral::GetRandomNumber()) & 31 ) + ped->SetEvasiveDive(shooter, 1); + } + } + } +} + +bool +CWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo) +{ + ASSERT(holder!=NULL); + ASSERT(aimingTo!=NULL); + if (!holder->IsPed() || !((CPed*)holder)->m_pSeekTarget) return false; - CWeaponInfo *ourType = CWeaponInfo::GetWeaponInfo(m_eWeaponType); - CVector adjustedOffset = ourType->m_vecFireOffset; + CWeaponInfo *info = GetInfo(); + + CVector adjustedOffset = info->m_vecFireOffset; adjustedOffset.z += 0.6f; - CVector point1, point2; + CVector source, target; CEntity *foundEnt = nil; CColPoint foundCol; - if (firePos) - point1 = *firePos; + if (fireSource) + source = *fireSource; else - point1 = holder->GetMatrix() * adjustedOffset; + source = holder->GetMatrix() * adjustedOffset; CEntity *aimEntity = aimingTo ? aimingTo : ((CPed*)holder)->m_pSeekTarget; - point2 = aimEntity->GetPosition(); - point2.z += 0.6f; + ASSERT(aimEntity!=NULL); + + target = aimEntity->GetPosition(); + target.z += 0.6f; - CWorld::ProcessLineOfSight(point1, point2, foundCol, foundEnt, true, false, false, false, false, false, false); + CWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, false, false, false, false, false, false); if (foundEnt && foundEnt->IsBuilding()) { // That was supposed to be Magnitude, according to leftover code in assembly - float diff = (foundCol.point.z - point1.z); + float diff = (foundCol.point.z - source.z); if (diff < 0.0f && diff > -3.0f) return true; } @@ -90,6 +2209,36 @@ CWeapon::HitsGround(CEntity *holder, CVector *firePos, CEntity *aimingTo) return false; } +void +CWeapon::BlowUpExplosiveThings(CEntity *thing) +{ + if ( thing ) + { + CObject *object = (CObject*)thing; + int32 mi = object->GetModelIndex(); + if ( IsExplosiveThingModel(mi) && !object->bHasBeenDamaged ) + { + object->bHasBeenDamaged = true; + + CExplosion::AddExplosion(object, FindPlayerPed(), EXPLOSION_BARREL, object->GetPosition()+CVector(0.0f,0.0f,0.5f), 100); + + if ( MI_EXPLODINGBARREL == mi ) + object->m_vecMoveSpeed.z += 0.75f; + else + object->m_vecMoveSpeed.z += 0.45f; + + object->m_vecMoveSpeed.x += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f; + object->m_vecMoveSpeed.y += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f; + + if ( object->bIsStatic ) + { + object->bIsStatic = false; + object->AddToMovingList(); + } + } + } +} + bool CWeapon::HasWeaponAmmoToBeUsed(void) { @@ -101,9 +2250,43 @@ CWeapon::HasWeaponAmmoToBeUsed(void) return m_nAmmoTotal != 0; } } + +bool +CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) +{ + return CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects); +} STARTPATCHES + + InjectHook(0x55C2D0, CWeapon::InitialiseWeapons, PATCH_JUMP); + InjectHook(0x55C2F0, CWeapon::ShutdownWeapons, PATCH_JUMP); + InjectHook(0x55C310, CWeapon::UpdateWeapons, PATCH_JUMP); InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP); + InjectHook(0x55C380, &CWeapon::Fire, PATCH_JUMP); + InjectHook(0x55C940, &CWeapon::FireFromCar, PATCH_JUMP); + InjectHook(0x55CA20, &CWeapon::FireMelee, PATCH_JUMP); + InjectHook(0x55D2E0, &CWeapon::FireInstantHit, PATCH_JUMP); + InjectHook(0x55F770, &CWeapon::AddGunshell, PATCH_JUMP); + InjectHook(0x55F950, &CWeapon::DoBulletImpact, PATCH_JUMP); + InjectHook(0x560620, &CWeapon::FireShotgun, PATCH_JUMP); + InjectHook(0x561900, &CWeapon::FireProjectile, PATCH_JUMP); + InjectHook(0x561C70, CWeapon::GenerateFlameThrowerParticles, PATCH_JUMP); + InjectHook(0x561E00, &CWeapon::FireAreaEffect, PATCH_JUMP); + InjectHook(0x561FE0, &CWeapon::FireSniper, PATCH_JUMP); + InjectHook(0x562180, &CWeapon::FireM16_1stPerson, PATCH_JUMP); + InjectHook(0x5624D0, &CWeapon::FireInstantHitFromCar, PATCH_JUMP); + InjectHook(0x562EB0, CWeapon::DoDoomAiming, PATCH_JUMP); + InjectHook(0x563200, CWeapon::DoTankDoomAiming, PATCH_JUMP); + InjectHook(0x563660, CWeapon::DoDriveByAutoAiming, PATCH_JUMP); InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP); + InjectHook(0x563A10, &CWeapon::Update, PATCH_JUMP); + InjectHook(0x563FB0, &CWeapon::IsTypeMelee, PATCH_JUMP); + InjectHook(0x563FD0, &CWeapon::IsType2Handed, PATCH_JUMP); + InjectHook(0x564680, CWeapon::MakePedsJumpAtShot, PATCH_JUMP); InjectHook(0x564890, &CWeapon::HitsGround, PATCH_JUMP); + InjectHook(0x564A60, CWeapon::BlowUpExplosiveThings, PATCH_JUMP); + InjectHook(0x564B80, &CWeapon::HasWeaponAmmoToBeUsed, PATCH_JUMP); + InjectHook(0x564C00, CWeapon::ProcessLineOfSight, PATCH_JUMP); + ENDPATCHES diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 84760550..265ffddb 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -1,5 +1,8 @@ #pragma once +#define DRIVEBYAUTOAIMING_MAXDIST (2.5f) +#define DOOMAUTOAIMING_MAXDIST (9000.0f) + enum eWeaponType { WEAPONTYPE_UNARMED, @@ -49,7 +52,10 @@ enum eWeaponState }; class CEntity; +class CPhysical; class CAutomobile; +struct CColPoint; +class CWeaponInfo; class CWeapon { @@ -64,22 +70,50 @@ public: CWeapon() { m_bAddRotOffset = false; } + + CWeaponInfo *GetInfo(); - static void ShutdownWeapons(void); - void Initialise(eWeaponType type, int ammo); - void Update(int32 audioEntity); - void Reload(void); - bool Fire(CEntity*, CVector*); - void FireFromCar(CAutomobile *car, bool left); - void AddGunshell(CEntity*, CVector const&, CVector2D const&, float); - bool IsTypeMelee(void); - bool IsType2Handed(void); - static void DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end); - bool HitsGround(CEntity* holder, CVector* firePos, CEntity* aimingTo); - bool HasWeaponAmmoToBeUsed(void); static void InitialiseWeapons(void); - static void UpdateWeapons(void); + static void ShutdownWeapons (void); + static void UpdateWeapons (void); + + void Initialise(eWeaponType type, int32 ammo); + + bool Fire (CEntity *shooter, CVector *fireSource); + bool FireFromCar (CAutomobile *shooter, bool left); + bool FireMelee (CEntity *shooter, CVector &fireSource); + bool FireInstantHit(CEntity *shooter, CVector *fireSource); + + void AddGunshell (CEntity *shooter, CVector const &source, CVector2D const &direction, float size); + void DoBulletImpact(CEntity *shooter, CEntity *victim, CVector *source, CVector *target, CColPoint *point, CVector2D ahead); + + bool FireShotgun (CEntity *shooter, CVector *fireSource); + bool FireProjectile(CEntity *shooter, CVector *fireSource, float power); + + static void GenerateFlameThrowerParticles(CVector pos, CVector dir); + + bool FireAreaEffect (CEntity *shooter, CVector *fireSource); + bool FireSniper (CEntity *shooter); + bool FireM16_1stPerson (CEntity *shooter); + bool FireInstantHitFromCar(CAutomobile *shooter, bool left); + + static void DoDoomAiming (CEntity *shooter, CVector *source, CVector *target); + static void DoTankDoomAiming (CEntity *shooter, CEntity *driver, CVector *source, CVector *target); + static void DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target); + + void Reload(void); + void Update(int32 audioEntity); + bool IsTypeMelee (void); + bool IsType2Handed(void); + + static void MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target); + + bool HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo); + static void BlowUpExplosiveThings(CEntity *thing); + bool HasWeaponAmmoToBeUsed(void); + + static bool ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects); }; -static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error"); +VALIDATE_SIZE(CWeapon, 0x18); -void FireOneInstantHitRound(CVector* shotSource, CVector* shotTarget, int32 damage); \ No newline at end of file +void FireOneInstantHitRound(CVector *source, CVector *target, int32 damage); \ No newline at end of file From 7c13d72edc43ad0f141739937ab6238197a1db38 Mon Sep 17 00:00:00 2001 From: Fire_Head Date: Wed, 15 Apr 2020 08:13:46 +0300 Subject: [PATCH 012/123] Update Weapon.cpp --- src/weapons/Weapon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index d4312649..28031847 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1518,7 +1518,7 @@ CWeapon::FireSniper(CEntity *shooter) CBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir); if ( shooter == FindPlayerPed() ) - ++CStats::InstantHitsFiredByPlayer; + CStats::InstantHitsFiredByPlayer++; if ( shooter == FindPlayerPed() ) { From 90be379bede299aa53bca5027ecc19c356e50f86 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 15 Apr 2020 14:05:24 +0200 Subject: [PATCH 013/123] implemented most of librw wrapper --- premake5.lua | 22 +- src/audio/AudioManager.cpp | 4 +- src/control/Replay.cpp | 10 +- src/core/TempColModels.cpp | 42 +- src/core/common.h | 14 +- src/fakerw/fake.cpp | 795 +++++++++++++++++++++++++++++++++++++ src/fakerw/rphanim.h | 20 + src/fakerw/rpmatfx.h | 43 ++ src/fakerw/rpskin.h | 8 + src/fakerw/rpworld.h | 336 ++++++++++++++++ src/fakerw/rtbmp.h | 4 + src/fakerw/rwcore.h | 413 +++++++++++++++++++ src/fakerw/rwplcore.h | 498 +++++++++++++++++++++++ src/peds/Ped.cpp | 2 +- src/render/Console.cpp | 1 + src/render/Shadows.h | 1 - src/render/Weather.cpp | 2 +- src/rw/ClumpRead.cpp | 6 +- src/rw/RwHelper.cpp | 4 + src/rw/RwMatFX.cpp | 4 + src/rw/TexRead.cpp | 25 +- src/rw/rw.cpp | 2 + 22 files changed, 2212 insertions(+), 44 deletions(-) create mode 100644 src/fakerw/fake.cpp create mode 100644 src/fakerw/rphanim.h create mode 100644 src/fakerw/rpmatfx.h create mode 100644 src/fakerw/rpskin.h create mode 100644 src/fakerw/rpworld.h create mode 100644 src/fakerw/rtbmp.h create mode 100644 src/fakerw/rwcore.h create mode 100644 src/fakerw/rwplcore.h diff --git a/premake5.lua b/premake5.lua index 173fe3e4..cebc8ee9 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,5 +1,7 @@ +Librw = os.getenv("LIBRW") + workspace "re3" - configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW" } + configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW", "DebugLIBRW" } location "build" files { "src/*.*" } @@ -43,18 +45,28 @@ workspace "re3" includedirs { "eax" } includedirs { "dxsdk/include" } - includedirs { "rwsdk/include/d3d8" } includedirs { "milessdk/include" } includedirs { "eax" } libdirs { "dxsdk/lib" } libdirs { "milessdk/lib" } + filter "configurations:*LIBRW" + files { "src/fakerw/*.*" } + includedirs { "src/fakerw" } + includedirs { Librw } + libdirs { path.join(Librw, "lib/win-x86-d3d9/Debug") } + links { "rw", "d3d9" } + + filter "configurations:not *LIBRW" + includedirs { "rwsdk/include/d3d8" } + filter "configurations:DebugRW or configurations:ReleaseRW" defines { "RWLIBS" } libdirs { "rwsdk/lib/d3d8/release" } links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp" } filter {} + pbcommands = { "setlocal EnableDelayedExpansion", @@ -123,3 +135,9 @@ project "re3" optimize "On" staticruntime "on" setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") + + filter "configurations:DebugLIBRW" + defines { "DEBUG", "LIBRW", "RW_D3D9" } + symbols "On" + setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") + diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 1d2835cf..f99891ec 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -1,4 +1,4 @@ -#include "common.h" +#include "common.h" #include "patcher.h" #include "audio_enums.h" @@ -6269,7 +6269,7 @@ cAudioManager::ProcessPedHeadphones(cPedParams *params) emittingVol = 10; veh = (CAutomobile *)ped->m_pMyVehicle; if(veh && veh->IsCar()) { - for(int32 i = 2; i < ARRAYSIZE(veh->Doors); i++) { + for(int32 i = 2; i < ARRAY_SIZE(veh->Doors); i++) { if(!veh->IsDoorClosed((eDoors)i) || veh->IsDoorMissing((eDoors)i)) { emittingVol = 42; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 0da32dd2..9e0bed66 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1215,7 +1215,7 @@ void CReplay::RestoreStuffFromMem(void) vehicle->SetModelIndex(mi); if (mi == MI_DODO){ CAutomobile* dodo = (CAutomobile*)vehicle; - RpAtomicSetFlags(GetFirstObject(dodo->m_aCarNodes[CAR_WHEEL_LF]), 0); + RpAtomicSetFlags((RpAtomic*)GetFirstObject(dodo->m_aCarNodes[CAR_WHEEL_LF]), 0); CMatrix tmp1; tmp1.Attach(RwFrameGetMatrix(dodo->m_aCarNodes[CAR_WHEEL_RF]), false); CMatrix tmp2(RwFrameGetMatrix(dodo->m_aCarNodes[CAR_WHEEL_LF]), false); @@ -1243,7 +1243,7 @@ void CReplay::RestoreStuffFromMem(void) vehicle->GetMatrix().Detach(); if (vehicle->m_rwObject){ if (RwObjectGetType(vehicle->m_rwObject) == rpATOMIC){ - RwFrame* frame = RpAtomicGetFrame(vehicle->m_rwObject); + RwFrame* frame = RpAtomicGetFrame((RpAtomic*)vehicle->m_rwObject); RpAtomicDestroy((RpAtomic*)vehicle->m_rwObject); RwFrameDestroy(frame); } @@ -1254,7 +1254,7 @@ void CReplay::RestoreStuffFromMem(void) int model_id = info->m_wheelId; if (model_id != -1){ if ((vehicle->m_rwObject = CModelInfo::GetModelInfo(model_id)->CreateInstance())){ - vehicle->GetMatrix().AttachRW(&((RwFrame*)vehicle->m_rwObject->parent)->modelling, false); + vehicle->GetMatrix().AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)vehicle->m_rwObject)), false); } } } @@ -1274,7 +1274,7 @@ void CReplay::RestoreStuffFromMem(void) object->SetModelIndex(mi); object->GetMatrix().m_attachment = nil; if (RwObjectGetType(object->m_rwObject) == rpATOMIC) - object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(object->m_rwObject)), false); + object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)object->m_rwObject)), false); } i = CPools::GetDummyPool()->GetSize(); while (--i >= 0) { @@ -1289,7 +1289,7 @@ void CReplay::RestoreStuffFromMem(void) dummy->SetModelIndex(mi); dummy->GetMatrix().m_attachment = nil; if (RwObjectGetType(dummy->m_rwObject) == rpATOMIC) - dummy->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(dummy->m_rwObject)), false); + dummy->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)dummy->m_rwObject)), false); } CTimer::SetTimeInMilliseconds(Time1); CTimer::SetTimeInMillisecondsNonClipped(Time2); diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index f7cf035e..22ef31bd 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -34,7 +34,7 @@ void CTempColModels::Initialise(void) { #define SET_COLMODEL_SPHERES(colmodel, sphrs)\ - colmodel.numSpheres = ARRAYSIZE(sphrs);\ + colmodel.numSpheres = ARRAY_SIZE(sphrs);\ colmodel.spheres = sphrs;\ colmodel.level = LEVEL_NONE;\ colmodel.ownsCollisionVolumes = false;\ @@ -45,7 +45,7 @@ CTempColModels::Initialise(void) ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); ms_colModelBBox.level = LEVEL_NONE; - for (i = 0; i < ARRAYSIZE(ms_colModelCutObj); i++) { + for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) { ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0); ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0); ms_colModelCutObj[i].level = LEVEL_NONE; @@ -53,7 +53,7 @@ CTempColModels::Initialise(void) // Ped Spheres - for (i = 0; i < ARRAYSIZE(s_aPedSpheres); i++) + for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) s_aPedSpheres[i].radius = 0.35f; s_aPedSpheres[0].center = CVector(0.0f, 0.0f, -0.25f); @@ -61,9 +61,9 @@ CTempColModels::Initialise(void) s_aPedSpheres[2].center = CVector(0.0f, 0.0f, 0.55f); #ifdef FIX_BUGS - for (i = 0; i < ARRAYSIZE(s_aPedSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) { #else - for (i = 0; i < ARRAYSIZE(s_aPedGSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aPedGSpheres); i++) { #endif s_aPedSpheres[i].surface = SURFACE_FLESH; s_aPedSpheres[i].piece = 0; @@ -83,7 +83,7 @@ CTempColModels::Initialise(void) s_aPed2Spheres[1].center = CVector(0.0f, 0.0f, -0.9f); s_aPed2Spheres[2].center = CVector(0.0f, -0.35f, -0.9f); - for (i = 0; i < ARRAYSIZE(s_aPed2Spheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) { s_aPed2Spheres[i].surface = SURFACE_FLESH; s_aPed2Spheres[i].piece = 0; } @@ -129,7 +129,7 @@ CTempColModels::Initialise(void) s_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f); s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f); - for (i = 0; i < ARRAYSIZE(s_aDoorSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) { s_aDoorSpheres[i].surface = SURFACE_BILLBOARD; s_aDoorSpheres[i].piece = 0; } @@ -141,7 +141,7 @@ CTempColModels::Initialise(void) // Bumper Spheres - for (i = 0; i < ARRAYSIZE(s_aBumperSpheres); i++) + for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) s_aBumperSpheres[i].radius = 0.15f; s_aBumperSpheres[0].center = CVector(0.85f, -0.05f, 0.0f); @@ -149,7 +149,7 @@ CTempColModels::Initialise(void) s_aBumperSpheres[2].center = CVector(-0.4f, 0.05f, 0.0f); s_aBumperSpheres[3].center = CVector(-0.85f, -0.05f, 0.0f); - for (i = 0; i < ARRAYSIZE(s_aBumperSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) { s_aBumperSpheres[i].surface = SURFACE_BILLBOARD; s_aBumperSpheres[i].piece = 0; } @@ -161,7 +161,7 @@ CTempColModels::Initialise(void) // Panel Spheres - for (i = 0; i < ARRAYSIZE(s_aPanelSpheres); i++) + for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) s_aPanelSpheres[i].radius = 0.15f; s_aPanelSpheres[0].center = CVector(0.15f, 0.45f, 0.0f); @@ -169,7 +169,7 @@ CTempColModels::Initialise(void) s_aPanelSpheres[2].center = CVector(-0.15f, -0.45f, 0.0f); s_aPanelSpheres[3].center = CVector(-0.15f, 0.45f, 0.0f); - for (i = 0; i < ARRAYSIZE(s_aPanelSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) { s_aPanelSpheres[i].surface = SURFACE_BILLBOARD; s_aPanelSpheres[i].piece = 0; } @@ -181,7 +181,7 @@ CTempColModels::Initialise(void) // Bonnet Spheres - for (i = 0; i < ARRAYSIZE(s_aBonnetSpheres); i++) + for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) s_aBonnetSpheres[i].radius = 0.2f; s_aBonnetSpheres[0].center = CVector(-0.4f, 0.1f, 0.0f); @@ -189,7 +189,7 @@ CTempColModels::Initialise(void) s_aBonnetSpheres[2].center = CVector(0.4f, 0.1f, 0.0f); s_aBonnetSpheres[3].center = CVector(0.4f, 0.9f, 0.0f); - for (i = 0; i < ARRAYSIZE(s_aBonnetSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) { s_aBonnetSpheres[i].surface = SURFACE_BILLBOARD; s_aBonnetSpheres[i].piece = 0; } @@ -201,7 +201,7 @@ CTempColModels::Initialise(void) // Boot Spheres - for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) s_aBootSpheres[i].radius = 0.2f; s_aBootSpheres[0].center = CVector(-0.4f, -0.1f, 0.0f); @@ -209,7 +209,7 @@ CTempColModels::Initialise(void) s_aBootSpheres[2].center = CVector(0.4f, -0.1f, 0.0f); s_aBootSpheres[3].center = CVector(0.4f, -0.6f, 0.0f); - for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { s_aBootSpheres[i].surface = SURFACE_BILLBOARD; s_aBootSpheres[i].piece = 0; } @@ -228,9 +228,9 @@ CTempColModels::Initialise(void) s_aWheelSpheres[1].center = CVector(0.3f, 0.0f, 0.0f); #ifdef FIX_BUGS - for (i = 0; i < ARRAYSIZE(s_aWheelSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aWheelSpheres); i++) { #else - for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif s_aWheelSpheres[i].surface = SURFACE_RUBBER29; s_aWheelSpheres[i].piece = 0; @@ -250,9 +250,9 @@ CTempColModels::Initialise(void) s_aBodyPartSpheres1[1].center = CVector(0.8f, 0.0f, 0.0f); #ifdef FIX_BUGS - for (i = 0; i < ARRAYSIZE(s_aBodyPartSpheres1); i++) { + for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres1); i++) { #else - for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif s_aBodyPartSpheres1[i].surface = SURFACE_FLESH; s_aBodyPartSpheres1[i].piece = 0; @@ -272,9 +272,9 @@ CTempColModels::Initialise(void) s_aBodyPartSpheres2[1].center = CVector(0.5f, 0.0f, 0.0f); #ifdef FIX_BUGS - for (i = 0; i < ARRAYSIZE(s_aBodyPartSpheres2); i++) { + for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres2); i++) { #else - for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) { + for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) { #endif s_aBodyPartSpheres2[i].surface = SURFACE_FLESH; s_aBodyPartSpheres2[i].piece = 0; diff --git a/src/core/common.h b/src/core/common.h index 7688b182..454b848a 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -23,6 +23,15 @@ #include #include +// gotta put this somewhere +#ifdef LIBRW +#define STREAMPOS(str) ((str)->tell()) +#define STREAMFILE(str) (((rw::StreamFile*)(str))->file) +#else +#define STREAMPOS(str) ((str)->Type.memory.position) +#define STREAMFILE(str) ((str)->Type.file.fpFile) +#endif + #define rwVENDORID_ROCKSTAR 0x0253F2 // Get rid of bullshit windows definitions, we're not running on an 8086 @@ -39,9 +48,6 @@ #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; @@ -55,7 +61,9 @@ typedef int64_t int64; // hardcode ucs-2 typedef uint16_t wchar; +#ifndef nil #define nil nullptr +#endif #include "config.h" diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp new file mode 100644 index 00000000..1aaa8d11 --- /dev/null +++ b/src/fakerw/fake.cpp @@ -0,0 +1,795 @@ +#define _CRT_SECURE_NO_WARNINGS +#define WITH_D3D +#include +#include +#include +#include +#include +#include + +// TODO: split image<->raster functions in two +// implement raster context +// BMP reader +// geometry locking + +using namespace rw; + +RwUInt8 RwObjectGetType(const RwObject *obj) { return obj->type; } + + +void *RwMalloc(size_t size) { return malloc(size); } +void *RwCalloc(size_t numObj, size_t sizeObj) { return calloc(numObj, sizeObj); } +void RwFree(void *mem) { free(mem); } + + +//RwReal RwV3dNormalize(RwV3d * out, const RwV3d * in); +RwReal RwV3dLength(const RwV3d * in) { return length(*in); } +//RwReal RwV2dLength(const RwV2d * in); +//RwReal RwV2dNormalize(RwV2d * out, const RwV2d * in); +//void RwV2dAssign(RwV2d * out, const RwV2d * ina); +//void RwV2dAdd(RwV2d * out, const RwV2d * ina, const RwV2d * inb); +//void RwV2dLineNormal(RwV2d * out, const RwV2d * ina, const RwV2d * inb); +//void RwV2dSub(RwV2d * out, const RwV2d * ina, const RwV2d * inb); +//void RwV2dPerp(RwV2d * out, const RwV2d * in); +//void RwV2dScale(RwV2d * out, const RwV2d * in, RwReal scalar); +//RwReal RwV2dDotProduct(const RwV2d * ina, const RwV2d * inb); +//void RwV3dAssign(RwV3d * out, const RwV3d * ina); +void RwV3dAdd(RwV3d * out, const RwV3d * ina, const RwV3d * inb) { *out = add(*ina, *inb); } +void RwV3dSub(RwV3d * out, const RwV3d * ina, const RwV3d * inb) { *out = sub(*ina, *inb); } +//void RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar); +//void RwV3dIncrementScaled(RwV3d * out, const RwV3d * in, RwReal scalar); +//void RwV3dNegate(RwV3d * out, const RwV3d * in); +RwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb) { return dot(*ina, *inb); } +//void RwV3dCrossProduct(RwV3d * out, const RwV3d * ina, const RwV3d * inb); +RwV3d *RwV3dTransformPoints(RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix) + { V3d::transformPoints(pointsOut, pointsIn, numPoints, matrix); return pointsOut; } +//RwV3d *RwV3dTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, RwInt32 numPoints, const RwMatrix * matrix); + + + +RwBool RwMatrixDestroy(RwMatrix *mpMat) { mpMat->destroy(); return true; } +RwMatrix *RwMatrixCreate(void) { return Matrix::create(); } +void RwMatrixCopy(RwMatrix * dstMatrix, const RwMatrix * srcMatrix) { *dstMatrix = *srcMatrix; } +void RwMatrixSetIdentity(RwMatrix * matrix) { matrix->setIdentity(); } +RwMatrix *RwMatrixMultiply(RwMatrix * matrixOut, const RwMatrix * MatrixIn1, const RwMatrix * matrixIn2); +RwMatrix *RwMatrixTransform(RwMatrix * matrix, const RwMatrix * transform, RwOpCombineType combineOp) + { matrix->transform(transform, (rw::CombineOp)combineOp); return matrix; } +//RwMatrix *RwMatrixOrthoNormalize(RwMatrix * matrixOut, const RwMatrix * matrixIn); +//RwMatrix *RwMatrixInvert(RwMatrix * matrixOut, const RwMatrix * matrixIn); +RwMatrix *RwMatrixScale(RwMatrix * matrix, const RwV3d * scale, RwOpCombineType combineOp) + { matrix->scale(scale, (rw::CombineOp)combineOp); return matrix; } +RwMatrix *RwMatrixTranslate(RwMatrix * matrix, const RwV3d * translation, RwOpCombineType combineOp) + { matrix->translate(translation, (rw::CombineOp)combineOp); return matrix; } +RwMatrix *RwMatrixRotate(RwMatrix * matrix, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp) + { matrix->rotate(axis, angle, (rw::CombineOp)combineOp); return matrix; } +//RwMatrix *RwMatrixRotateOneMinusCosineSine(RwMatrix * matrix, const RwV3d * unitAxis, RwReal oneMinusCosine, RwReal sine, RwOpCombineType combineOp); +//const RwMatrix *RwMatrixQueryRotate(const RwMatrix * matrix, RwV3d * unitAxis, RwReal * angle, RwV3d * center); +RwV3d *RwMatrixGetRight(RwMatrix * matrix) { return &matrix->right; } +RwV3d *RwMatrixGetUp(RwMatrix * matrix) { return &matrix->up; } +RwV3d *RwMatrixGetAt(RwMatrix * matrix) { return &matrix->at; } +RwV3d *RwMatrixGetPos(RwMatrix * matrix) { return &matrix->pos; } +RwMatrix *RwMatrixUpdate(RwMatrix * matrix) { matrix->update(); return matrix; } +//RwMatrix *RwMatrixOptimize(RwMatrix * matrix, const RwMatrixTolerance *tolerance); + + + + +RwFrame *RwFrameForAllObjects(RwFrame * frame, RwObjectCallBack callBack, void *data) { + FORLIST(lnk, frame->objectList) + if(callBack(&ObjectWithFrame::fromFrame(lnk)->object, data) == nil) + break; + return frame; +} +RwFrame *RwFrameTranslate(RwFrame * frame, const RwV3d * v, RwOpCombineType combine) { frame->translate(v, (CombineOp)combine); return frame; } +RwFrame *RwFrameRotate(RwFrame * frame, const RwV3d * axis, RwReal angle, RwOpCombineType combine) { frame->rotate(axis, angle, (CombineOp)combine); return frame; } +RwFrame *RwFrameScale(RwFrame * frame, const RwV3d * v, RwOpCombineType combine) { frame->scale(v, (CombineOp)combine); return frame; } +RwFrame *RwFrameTransform(RwFrame * frame, const RwMatrix * m, RwOpCombineType combine) { frame->transform(m, (CombineOp)combine); return frame; } +//RwFrame *RwFrameOrthoNormalize(RwFrame * frame); +RwFrame *RwFrameSetIdentity(RwFrame * frame) { frame->matrix.setIdentity(); frame->updateObjects(); return frame; } +//RwFrame *RwFrameCloneHierarchy(RwFrame * root); +//RwBool RwFrameDestroyHierarchy(RwFrame * frame); +RwFrame *RwFrameForAllChildren(RwFrame * frame, RwFrameCallBack callBack, void *data) + { return frame->forAllChildren(callBack, data); } +RwFrame *RwFrameRemoveChild(RwFrame * child) { child->removeChild(); return child; } +RwFrame *RwFrameAddChild(RwFrame * parent, RwFrame * child) { parent->addChild(child); return parent; } +RwFrame *RwFrameGetParent(const RwFrame * frame) { return frame->getParent(); } +//RwFrame *RwFrameGetRoot(const RwFrame * frame); +RwMatrix *RwFrameGetLTM(RwFrame * frame) { return frame->getLTM(); } +RwMatrix *RwFrameGetMatrix(RwFrame * frame) { return &frame->matrix; } +RwFrame *RwFrameUpdateObjects(RwFrame * frame) { frame->updateObjects(); return frame; } +RwFrame *RwFrameCreate(void) { return rw::Frame::create(); } +//RwBool RwFrameInit(RwFrame *frame); +//RwBool RwFrameDeInit(RwFrame *frame); +RwBool RwFrameDestroy(RwFrame * frame) { frame->destroy(); return true; } +//void _rwFrameInit(RwFrame *frame); +//void _rwFrameDeInit(RwFrame *frame); +//RwBool RwFrameDirty(const RwFrame * frame); +//RwInt32 RwFrameCount(RwFrame * frame); +//RwBool RwFrameSetStaticPluginsSize(RwInt32 size); +RwInt32 RwFrameRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) + { return Frame::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); } +//RwInt32 RwFrameGetPluginOffset(RwUInt32 pluginID); +//RwBool RwFrameValidatePlugins(const RwFrame * frame); +//RwFrame *_rwFrameCloneAndLinkClones(RwFrame * root); +//RwFrame *_rwFramePurgeClone(RwFrame *root); + +RwInt32 RwFrameRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) + { return Frame::registerPluginStream(pluginID, readCB, (StreamWrite)writeCB, (StreamGetSize)getSizeCB); } + + +rwFrameList *rwFrameListDeinitialize(rwFrameList *frameList) { + rwFree(frameList->frames); + frameList->frames = nil; + return frameList; +} +rwFrameList *rwFrameListStreamRead(RwStream *stream, rwFrameList *fl) { return fl->streamRead(stream); } + + + + +RwCamera *RwCameraBeginUpdate(RwCamera * camera) { camera->beginUpdate(); return camera; } +RwCamera *RwCameraEndUpdate(RwCamera * camera) { camera->endUpdate(); return camera; } +RwCamera *RwCameraClear(RwCamera * camera, RwRGBA * colour, RwInt32 clearMode) { camera->clear(colour, clearMode); return camera; } +// WARNING: ignored arguments +RwCamera *RwCameraShowRaster(RwCamera * camera, void *pDev, RwUInt32 flags) { camera->showRaster(); return camera; } +RwBool RwCameraDestroy(RwCamera * camera) { camera->destroy(); return true; } +RwCamera *RwCameraCreate(void) { return rw::Camera::create(); } +RwCamera *RwCameraClone(RwCamera * camera) { return camera->clone(); } +RwCamera *RwCameraSetViewOffset(RwCamera *camera, const RwV2d *offset) { camera->setViewOffset(offset); return camera; } +RwCamera *RwCameraSetViewWindow(RwCamera *camera, const RwV2d *viewWindow) { camera->setViewWindow(viewWindow); return camera; } +RwCamera *RwCameraSetProjection(RwCamera *camera, RwCameraProjection projection); +RwCamera *RwCameraSetNearClipPlane(RwCamera *camera, RwReal nearClip) { camera->setNearPlane(nearClip); return camera; } +RwCamera *RwCameraSetFarClipPlane(RwCamera *camera, RwReal farClip) { camera->setFarPlane(farClip); return camera; } +RwInt32 RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwCameraGetPluginOffset(RwUInt32 pluginID); +RwBool RwCameraValidatePlugins(const RwCamera * camera); +RwFrustumTestResult RwCameraFrustumTestSphere(const RwCamera * camera, const RwSphere * sphere) { return (RwFrustumTestResult)camera->frustumTestSphere(sphere); } +const RwV2d *RwCameraGetViewOffset(const RwCamera *camera) { return &camera->viewOffset; } +RwCamera *RwCameraSetRaster(RwCamera *camera, RwRaster *raster) { camera->frameBuffer = raster; return camera; } +RwRaster *RwCameraGetRaster(const RwCamera *camera) { return camera->frameBuffer; } +RwCamera *RwCameraSetZRaster(RwCamera *camera, RwRaster *zRaster) { camera->zBuffer = zRaster; return camera; } +RwRaster *RwCameraGetZRaster(const RwCamera *camera) { return camera->zBuffer; } +RwReal RwCameraGetNearClipPlane(const RwCamera *camera) { return camera->nearPlane; } +RwReal RwCameraGetFarClipPlane(const RwCamera *camera) { return camera->farPlane; } +RwCamera *RwCameraSetFogDistance(RwCamera *camera, RwReal fogDistance) { camera->fogPlane = fogDistance; return camera; } +RwReal RwCameraGetFogDistance(const RwCamera *camera) { return camera->fogPlane; } +RwCamera *RwCameraGetCurrentCamera(void); +RwCameraProjection RwCameraGetProjection(const RwCamera *camera); +const RwV2d *RwCameraGetViewWindow(const RwCamera *camera) { return &camera->viewWindow; } +RwMatrix *RwCameraGetViewMatrix(RwCamera *camera) { return &camera->viewMatrix; } +RwCamera *RwCameraSetFrame(RwCamera *camera, RwFrame *frame) { camera->setFrame(frame); return camera; } +RwFrame *RwCameraGetFrame(const RwCamera *camera) { return camera->getFrame(); } + + + + + +RwImage *RwImageCreate(RwInt32 width, RwInt32 height, RwInt32 depth) { return Image::create(width, height, depth); } +RwBool RwImageDestroy(RwImage * image) { image->destroy(); return true; } +RwImage *RwImageAllocatePixels(RwImage * image); +RwImage *RwImageFreePixels(RwImage * image); +RwImage *RwImageCopy(RwImage * destImage, const RwImage * sourceImage); +RwImage *RwImageResize(RwImage * image, RwInt32 width, RwInt32 height); +RwImage *RwImageApplyMask(RwImage * image, const RwImage * mask); +RwImage *RwImageMakeMask(RwImage * image); +RwImage *RwImageReadMaskedImage(const RwChar * imageName, const RwChar * maskname); +RwImage *RwImageRead(const RwChar * imageName); +RwImage *RwImageWrite(RwImage * image, const RwChar * imageName); +RwChar *RwImageGetPath(void); +const RwChar *RwImageSetPath(const RwChar * path) { Image::setSearchPath(path); return path; } +RwImage *RwImageSetStride(RwImage * image, RwInt32 stride) { image->stride = stride; return image; } +RwImage *RwImageSetPixels(RwImage * image, RwUInt8 * pixels) { image->setPixels(pixels); return image; } +RwImage *RwImageSetPalette(RwImage * image, RwRGBA * palette) { image->setPalette((uint8*)palette); return image; } +RwInt32 RwImageGetWidth(const RwImage * image); +RwInt32 RwImageGetHeight(const RwImage * image); +RwInt32 RwImageGetDepth(const RwImage * image); +RwInt32 RwImageGetStride(const RwImage * image); +RwUInt8 *RwImageGetPixels(const RwImage * image); +RwRGBA *RwImageGetPalette(const RwImage * image); +RwUInt32 RwRGBAToPixel(RwRGBA * rgbIn, RwInt32 rasterFormat); +RwRGBA *RwRGBASetFromPixel(RwRGBA * rgbOut, RwUInt32 pixelValue, RwInt32 rasterFormat); +RwBool RwImageSetGamma(RwReal gammaValue); +RwReal RwImageGetGamma(void); +RwImage *RwImageGammaCorrect(RwImage * image); +RwRGBA *RwRGBAGammaCorrect(RwRGBA * rgb); +RwInt32 RwImageRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwImageGetPluginOffset(RwUInt32 pluginID); +RwBool RwImageValidatePlugins(const RwImage * image); +//RwBool RwImageRegisterImageFormat(const RwChar * extension, RwImageCallBackRead imageRead, RwImageCallBackWrite imageWrite); +const RwChar *RwImageFindFileType(const RwChar * imageName); +RwInt32 RwImageStreamGetSize(const RwImage * image); +RwImage *RwImageStreamRead(RwStream * stream); +const RwImage *RwImageStreamWrite(const RwImage * image, RwStream * stream); + +// TODO: this is kind hard... +RwImage *RwImageFindRasterFormat(RwImage *ipImage,RwInt32 nRasterType, RwInt32 *npWidth,RwInt32 *npHeight, RwInt32 *npDepth,RwInt32 *npFormat) +{ + // very dumb implementation for now + // this is also platform specific + if((nRasterType&rwRASTERTYPEMASK) != rwRASTERTYPETEXTURE){ + *npFormat = 0; + return nil; + } + *npWidth = ipImage->width; + *npHeight = ipImage->height; + switch(ipImage->depth){ + case 4: + case 8: + *npDepth = 8; + *npFormat = Raster::C8888 | Raster::PAL8; + break; + case 16: + *npDepth = 16; + *npFormat = Raster::C1555; + break; + case 24: + *npDepth = 32; + *npFormat = Raster::C888; + break; + case 32: + *npDepth = 32; + *npFormat = Raster::C8888; + break; + default: + assert(0 && "invalid depth"); + return nil; + } + return ipImage; +} + + + + +RwRaster *RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags) { return Raster::create(width, height, depth, flags); } +RwBool RwRasterDestroy(RwRaster * raster) { raster->destroy(); return true; } +RwInt32 RwRasterGetWidth(const RwRaster *raster) { return raster->width; } +RwInt32 RwRasterGetHeight(const RwRaster *raster) { return raster->height; } +RwInt32 RwRasterGetStride(const RwRaster *raster); +RwInt32 RwRasterGetDepth(const RwRaster *raster) { return raster->depth; } +RwInt32 RwRasterGetFormat(const RwRaster *raster); +RwInt32 RwRasterGetType(const RwRaster *raster); +RwRaster *RwRasterGetParent(const RwRaster *raster) { return raster->parent; } +RwRaster *RwRasterGetOffset(RwRaster *raster, RwInt16 *xOffset, RwInt16 *yOffset); +RwInt32 RwRasterGetNumLevels(RwRaster * raster); +RwRaster *RwRasterSubRaster(RwRaster * subRaster, RwRaster * raster, RwRect * rect); +RwRaster *RwRasterRenderFast(RwRaster * raster, RwInt32 x, RwInt32 y); +RwRaster *RwRasterRender(RwRaster * raster, RwInt32 x, RwInt32 y); +RwRaster *RwRasterRenderScaled(RwRaster * raster, RwRect * rect); +RwRaster *RwRasterPushContext(RwRaster * raster); +RwRaster *RwRasterPopContext(void); +RwRaster *RwRasterGetCurrentContext(void); +RwBool RwRasterClear(RwInt32 pixelValue); +RwBool RwRasterClearRect(RwRect * rpRect, RwInt32 pixelValue); +RwRaster *RwRasterShowRaster(RwRaster * raster, void *dev, RwUInt32 flags); +RwUInt8 *RwRasterLock(RwRaster * raster, RwUInt8 level, RwInt32 lockMode); +RwRaster *RwRasterUnlock(RwRaster * raster); +RwUInt8 *RwRasterLockPalette(RwRaster * raster, RwInt32 lockMode); +RwRaster *RwRasterUnlockPalette(RwRaster * raster); +RwInt32 RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwRasterGetPluginOffset(RwUInt32 pluginID); +RwBool RwRasterValidatePlugins(const RwRaster * raster); + +// TODO: let's hope this works +RwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image) { + engine->driver[raster->platform]->rasterFromImage(raster, image); + return raster; +} + + + + +RwTexture *RwTextureCreate(RwRaster * raster) { return Texture::create(raster); } +RwBool RwTextureDestroy(RwTexture * texture) { texture->destroy(); return true; } +RwTexture *RwTextureAddRef(RwTexture *texture) { texture->refCount++; return texture; } +// TODO +RwBool RwTextureSetMipmapping(RwBool enable) { return true; } +RwBool RwTextureGetMipmapping(void); +// TODO +RwBool RwTextureSetAutoMipmapping(RwBool enable) { return true; } +RwBool RwTextureGetAutoMipmapping(void); +RwBool RwTextureSetMipmapGenerationCallBack(RwTextureCallBackMipmapGeneration callback); +RwTextureCallBackMipmapGeneration RwTextureGetMipmapGenerationCallBack(void); +RwBool RwTextureSetMipmapNameCallBack(RwTextureCallBackMipmapName callback); +RwTextureCallBackMipmapName RwTextureGetMipmapNameCallBack(void); +RwBool RwTextureGenerateMipmapName(RwChar * name, RwChar * maskName, RwUInt8 mipLevel, RwInt32 format); +RwBool RwTextureRasterGenerateMipmaps(RwRaster * raster, RwImage * image); +RwTextureCallBackRead RwTextureGetReadCallBack(void); +RwBool RwTextureSetReadCallBack(RwTextureCallBackRead fpCallBack); +RwTexture *RwTextureSetName(RwTexture * texture, const RwChar * name) { strncpy(texture->name, name, 32); return texture; } +RwTexture *RwTextureSetMaskName(RwTexture * texture, const RwChar * maskName); +RwChar *RwTextureGetName(RwTexture *texture) { return texture->name; } +RwChar *RwTextureGetMaskName(RwTexture *texture); +RwTexture *RwTextureSetRaster(RwTexture * texture, RwRaster * raster) { texture->raster = raster; return texture; } +RwTexture *RwTextureRead(const RwChar * name, const RwChar * maskName) { return Texture::read(name, maskName); } +RwRaster *RwTextureGetRaster(const RwTexture *texture) { return texture->raster; } +RwInt32 RwTextureRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwTextureGetPluginOffset(RwUInt32 pluginID); +RwBool RwTextureValidatePlugins(const RwTexture * texture); + +RwTexDictionary *RwTextureGetDictionary(RwTexture *texture); +RwTexture *RwTextureSetFilterMode(RwTexture *texture, RwTextureFilterMode filtering) { texture->setFilter((Texture::FilterMode)filtering); return texture; } +RwTextureFilterMode RwTextureGetFilterMode(const RwTexture *texture); +RwTexture *RwTextureSetAddressing(RwTexture *texture, RwTextureAddressMode addressing) { + texture->setAddressU((Texture::Addressing)addressing); + texture->setAddressV((Texture::Addressing)addressing); + return texture; +} +RwTexture *RwTextureSetAddressingU(RwTexture *texture, RwTextureAddressMode addressing) { + texture->setAddressU((Texture::Addressing)addressing); + return texture; +} +RwTexture *RwTextureSetAddressingV(RwTexture *texture, RwTextureAddressMode addressing) { + texture->setAddressV((Texture::Addressing)addressing); + return texture; +} +RwTextureAddressMode RwTextureGetAddressing(const RwTexture *texture); +RwTextureAddressMode RwTextureGetAddressingU(const RwTexture *texture); +RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture); + +// TODO +void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { } + +// hack for reading native textures +RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size) + { *tex = Texture::streamReadNative(stream); return *tex != nil; } + + + + + +RwTexDictionary *RwTexDictionaryCreate(void) { return TexDictionary::create(); } +RwBool RwTexDictionaryDestroy(RwTexDictionary * dict) { dict->destroy(); return true; } +RwTexture *RwTexDictionaryAddTexture(RwTexDictionary * dict, RwTexture * texture) { dict->add(texture); return texture; } +//RwTexture *RwTexDictionaryRemoveTexture(RwTexture * texture); +RwTexture *RwTexDictionaryFindNamedTexture(RwTexDictionary * dict, const RwChar * name) { return dict->find(name); } +RwTexDictionary *RwTexDictionaryGetCurrent(void) { return TexDictionary::getCurrent(); } +RwTexDictionary *RwTexDictionarySetCurrent(RwTexDictionary * dict) { TexDictionary::setCurrent(dict); return dict; } +const RwTexDictionary *RwTexDictionaryForAllTextures(const RwTexDictionary * dict, RwTextureCallBack fpCallBack, void *pData) { + FORLIST(lnk, ((RwTexDictionary*)dict)->textures) + if(fpCallBack(Texture::fromDict(lnk), pData) == nil) + break; + return dict; +} +RwBool RwTexDictionaryForAllTexDictionaries(RwTexDictionaryCallBack fpCallBack, void *pData); +RwInt32 RwTexDictionaryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwTexDictionaryGetPluginOffset(RwUInt32 pluginID); +RwBool RwTexDictionaryValidatePlugins(const RwTexDictionary * dict); +RwUInt32 RwTexDictionaryStreamGetSize(const RwTexDictionary *texDict); +RwTexDictionary *RwTexDictionaryStreamRead(RwStream *stream); +const RwTexDictionary *RwTexDictionaryStreamWrite(const RwTexDictionary *texDict, RwStream *stream) { + ((RwTexDictionary*)texDict)->streamWrite(stream); + return texDict; +} + + + + + +RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const void *pData) { + StreamFile *file; + StreamMemory *mem; + RwMemory *memargs; + const char *mode; + + switch(accessType){ + case rwSTREAMREAD: mode = "rb"; break; + case rwSTREAMWRITE: mode = "wb"; break; + case rwSTREAMAPPEND: mode = "ab"; break; + default: return nil; + } + + switch(type){ + case rwSTREAMFILENAME: + file = rwNewT(StreamFile, 1, 0); + if(file->open((char*)pData, mode)) + return file; + rwFree(file); + return nil; + case rwSTREAMMEMORY: + memargs = (RwMemory*)pData; + mem = rwNewT(StreamMemory, 1, 0); + if(mem->open(memargs->start, memargs->length)) + return mem; + rwFree(mem); + return nil; + default: + assert(0 && "unknown type"); + return nil; + } +} +RwBool RwStreamClose(RwStream * stream, void *pData) { stream->close(); rwFree(stream); return true; } +RwUInt32 RwStreamRead(RwStream * stream, void *buffer, RwUInt32 length) { return stream->read(buffer, length); } +RwStream *RwStreamWrite(RwStream * stream, const void *buffer, RwUInt32 length) { stream->write(buffer, length); return stream; } +RwStream *RwStreamSkip(RwStream * stream, RwUInt32 offset) { stream->seek(offset); return stream; } + +RwBool RwStreamFindChunk(RwStream *stream, RwUInt32 type, RwUInt32 *lengthOut, RwUInt32 *versionOut) + { return findChunk(stream, type, lengthOut, versionOut); } + + + +void RwIm2DVertexSetCameraX(RwIm2DVertex *vert, RwReal camx) { } +void RwIm2DVertexSetCameraY(RwIm2DVertex *vert, RwReal camy) { } +void RwIm2DVertexSetCameraZ(RwIm2DVertex *vert, RwReal camz) { vert->setCameraZ(camz); } +void RwIm2DVertexSetRecipCameraZ(RwIm2DVertex *vert, RwReal recipz) { vert->setRecipCameraZ(recipz); } +void RwIm2DVertexSetScreenX(RwIm2DVertex *vert, RwReal scrnx) { vert->setScreenX(scrnx); } +void RwIm2DVertexSetScreenY(RwIm2DVertex *vert, RwReal scrny) { vert->setScreenY(scrny); } +void RwIm2DVertexSetScreenZ(RwIm2DVertex *vert, RwReal scrnz) { vert->setScreenZ(scrnz); } +void RwIm2DVertexSetU(RwIm2DVertex *vert, RwReal texU, RwReal recipz) { vert->setU(texU, recipz); } +void RwIm2DVertexSetV(RwIm2DVertex *vert, RwReal texV, RwReal recipz) { vert->setV(texV, recipz); } +void RwIm2DVertexSetIntRGBA(RwIm2DVertex *vert, RwUInt8 red, RwUInt8 green, RwUInt8 blue, RwUInt8 alpha) { vert->setColor(red, green, blue, alpha); } + +RwReal RwIm2DGetNearScreenZ(void) { return im2d::GetNearZ(); } +RwReal RwIm2DGetFarScreenZ(void) { return im2d::GetFarZ(); } +RwBool RwIm2DRenderLine(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2) + { im2d::RenderLine(vertices, numVertices, vert1, vert2); return true; } +RwBool RwIm2DRenderTriangle(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2, RwInt32 vert3 ) + { im2d::RenderTriangle(vertices, numVertices, vert1, vert2, vert3); return true; } +RwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices) + { im2d::RenderPrimitive((PrimitiveType)primType, vertices, numVertices); return true; } +RwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices) + { im2d::RenderIndexedPrimitive((PrimitiveType)primType, vertices, numVertices, indices, numIndices); return true; } + + +void RwIm3DVertexSetPos(RwIm3DVertex *vert, RwReal x, RwReal y, RwReal z) { vert->setX(x); vert->setY(y); vert->setZ(z); } +void RwIm3DVertexSetU(RwIm3DVertex *vert, RwReal u) { vert->setU(u); } +void RwIm3DVertexSetV(RwIm3DVertex *vert, RwReal v) { vert->setV(v); } +void RwIm3DVertexSetRGBA(RwIm3DVertex *vert, RwUInt8 r, RwUInt8 g, RwUInt8 b, RwUInt8 a) { vert->setColor(r, g, b, a); } + +// WARNING: ignoring flags +void *RwIm3DTransform(RwIm3DVertex *pVerts, RwUInt32 numVerts, RwMatrix *ltm, RwUInt32 flags) { im3d::Transform(pVerts, numVerts, ltm); return pVerts; } +RwBool RwIm3DEnd(void) { im3d::End(); return true; } +RwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2) { + RwImVertexIndex indices[2]; + indices[0] = vert1; + indices[1] = vert2; + im3d::RenderIndexed((PrimitiveType)PRIMTYPELINELIST, indices, 2); + return true; +} +RwBool RwIm3DRenderTriangle(RwInt32 vert1, RwInt32 vert2, RwInt32 vert3); +RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices) { im3d::RenderIndexed((PrimitiveType)primType, indices, numIndices); return true; } +RwBool RwIm3DRenderPrimitive(RwPrimitiveType primType); + + + + + +RwBool RwRenderStateSet(RwRenderState state, void *value) +{ + uint32 uival = (uintptr)value; + switch(state){ + case rwRENDERSTATETEXTURERASTER: SetRenderState(TEXTURERASTER, uival); return true; + case rwRENDERSTATETEXTUREADDRESS: SetRenderState(TEXTUREADDRESS, uival); return true; + case rwRENDERSTATETEXTUREADDRESSU: SetRenderState(TEXTUREADDRESSU, uival); return true; + case rwRENDERSTATETEXTUREADDRESSV: SetRenderState(TEXTUREADDRESSV, uival); return true; + case rwRENDERSTATETEXTUREPERSPECTIVE: return true; + case rwRENDERSTATEZTESTENABLE: SetRenderState(ZTESTENABLE, uival); return true; + case rwRENDERSTATESHADEMODE: return true; + case rwRENDERSTATEZWRITEENABLE: SetRenderState(ZWRITEENABLE, uival); return true; + case rwRENDERSTATETEXTUREFILTER: SetRenderState(TEXTUREFILTER, uival); return true; + case rwRENDERSTATESRCBLEND: SetRenderState(SRCBLEND, uival); return true; + case rwRENDERSTATEDESTBLEND: SetRenderState(DESTBLEND, uival); return true; + case rwRENDERSTATEVERTEXALPHAENABLE: SetRenderState(VERTEXALPHA, uival); return true; + case rwRENDERSTATEBORDERCOLOR: return true; + case rwRENDERSTATEFOGENABLE: SetRenderState(FOGENABLE, uival); return true; + case rwRENDERSTATEFOGCOLOR: SetRenderState(FOGCOLOR, uival); return true; + case rwRENDERSTATEFOGTYPE: return true; + case rwRENDERSTATEFOGDENSITY: return true; + case rwRENDERSTATEFOGTABLE: return true; + case rwRENDERSTATEALPHAPRIMITIVEBUFFER: return true; + case rwRENDERSTATECULLMODE: SetRenderState(CULLMODE, uival); return true; + + // all unsupported + case rwRENDERSTATESTENCILENABLE: + case rwRENDERSTATESTENCILFAIL: + case rwRENDERSTATESTENCILZFAIL: + case rwRENDERSTATESTENCILPASS: + case rwRENDERSTATESTENCILFUNCTION: + case rwRENDERSTATESTENCILFUNCTIONREF: + case rwRENDERSTATESTENCILFUNCTIONMASK: + case rwRENDERSTATESTENCILFUNCTIONWRITEMASK: + default: + return true; + } +} + + +static EngineOpenParams openParams; +// WARNING: unused parameters +RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { Engine::init(); return true; } +// TODO: this is platform dependent +RwBool RwEngineOpen(RwEngineOpenParams *initParams) { + openParams.window = (HWND)initParams->displayID; + return Engine::open(&openParams); +} +RwBool RwEngineStart(void) { return Engine::start(); } +RwBool RwEngineStop(void) { Engine::stop(); return true; } +RwBool RwEngineClose(void) { Engine::close(); return true; } +RwBool RwEngineTerm(void) { Engine::term(); return true; } +RwInt32 RwEngineRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor initCB, RwPluginObjectDestructor termCB); +RwInt32 RwEngineGetPluginOffset(RwUInt32 pluginID); +RwInt32 RwEngineGetNumSubSystems(void) { return Engine::getNumSubSystems(); } +RwSubSystemInfo *RwEngineGetSubSystemInfo(RwSubSystemInfo *subSystemInfo, RwInt32 subSystemIndex) + { return Engine::getSubSystemInfo(subSystemInfo, subSystemIndex); } +RwInt32 RwEngineGetCurrentSubSystem(void) { return Engine::getCurrentSubSystem(); } +RwBool RwEngineSetSubSystem(RwInt32 subSystemIndex) { return Engine::setSubSystem(subSystemIndex); } +RwInt32 RwEngineGetNumVideoModes(void) { return Engine::getNumVideoModes(); } +RwVideoMode *RwEngineGetVideoModeInfo(RwVideoMode *modeinfo, RwInt32 modeIndex) + { return Engine::getVideoModeInfo(modeinfo, modeIndex); } +RwInt32 RwEngineGetCurrentVideoMode(void) { return Engine::getCurrentVideoMode(); } +RwBool RwEngineSetVideoMode(RwInt32 modeIndex) { return Engine::setVideoMode(modeIndex); } +RwInt32 RwEngineGetTextureMemorySize(void); +RwInt32 RwEngineGetMaxTextureSize(void); + + + +// TODO +void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate) {} +RwBool RwD3D8DeviceSupportsDXTTexture(void) { return true; } + + + +RpMaterial *RpMaterialCreate(void) { return Material::create(); } +RwBool RpMaterialDestroy(RpMaterial *material) { material->destroy(); return true; } +//RpMaterial *RpMaterialClone(RpMaterial *material); +RpMaterial *RpMaterialSetTexture(RpMaterial *material, RwTexture *texture) { material->setTexture(texture); return material; } +//RpMaterial *RpMaterialAddRef(RpMaterial *material); +RwTexture *RpMaterialGetTexture(const RpMaterial *material) { return material->texture; } +RpMaterial *RpMaterialSetColor(RpMaterial *material, const RwRGBA *color) { material->color = *color; return material; } +const RwRGBA *RpMaterialGetColor(const RpMaterial *material) { return &material->color; } +RpMaterial *RpMaterialSetSurfaceProperties(RpMaterial *material, const RwSurfaceProperties *surfaceProperties); +const RwSurfaceProperties *RpMaterialGetSurfaceProperties(const RpMaterial *material) { return &material->surfaceProps; } +//RwInt32 RpMaterialRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +//RwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +//RwInt32 RpMaterialSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +//RwInt32 RpMaterialGetPluginOffset(RwUInt32 pluginID); +//RwBool RpMaterialValidatePlugins(const RpMaterial *material); +//RwUInt32 RpMaterialStreamGetSize(const RpMaterial *material); +//RpMaterial *RpMaterialStreamRead(RwStream *stream); +//const RpMaterial *RpMaterialStreamWrite(const RpMaterial *material, RwStream *stream); +//RpMaterialChunkInfo *_rpMaterialChunkInfoRead(RwStream *stream, RpMaterialChunkInfo *materialChunkInfo, RwInt32 *bytesRead); + + + + + +RwReal RpLightGetRadius(const RpLight *light) { return light->radius; } +//const RwRGBAReal *RpLightGetColor(const RpLight *light); +RpLight *RpLightSetFrame(RpLight *light, RwFrame *frame) { light->setFrame(frame); return light; } +RwFrame *RpLightGetFrame(const RpLight *light) { return light->getFrame(); } +//RpLightType RpLightGetType(const RpLight *light); +RpLight *RpLightSetFlags(RpLight *light, RwUInt32 flags) { light->setFlags(flags); return light; } +//RwUInt32 RpLightGetFlags(const RpLight *light); +RpLight *RpLightCreate(RwInt32 type) { return rw::Light::create(type); } +RwBool RpLightDestroy(RpLight *light) { light->destroy(); return true; } +RpLight *RpLightSetRadius(RpLight *light, RwReal radius) { light->radius = radius; return light; } +RpLight *RpLightSetColor(RpLight *light, const RwRGBAReal *color) { light->setColor(color->red, color->green, color->blue); return light; } +//RwReal RpLightGetConeAngle(const RpLight *light); +//RpLight *RpLightSetConeAngle(RpLight * ight, RwReal angle); +//RwUInt32 RpLightStreamGetSize(const RpLight *light); +//RpLight *RpLightStreamRead(RwStream *stream); +//const RpLight *RpLightStreamWrite(const RpLight *light, RwStream *stream); +//RpLightChunkInfo *_rpLightChunkInfoRead(RwStream *stream, RpLightChunkInfo *lightChunkInfo, RwInt32 *bytesRead); +//RwInt32 RpLightRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +//RwInt32 RpLightRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +//RwInt32 RpLightSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +//RwInt32 RpLightGetPluginOffset(RwUInt32 pluginID); +//RwBool RpLightValidatePlugins(const RpLight * light); + + + + + +RpGeometry *RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format) { return Geometry::create(numVert, numTriangles, format); } +RwBool RpGeometryDestroy(RpGeometry *geometry) { geometry->destroy(); return true; } +RpGeometry *_rpGeometryAddRef(RpGeometry *geometry); +// TODO: implement this +RpGeometry *RpGeometryLock(RpGeometry *geometry, RwInt32 lockMode) { return geometry; } +RpGeometry *RpGeometryUnlock(RpGeometry *geometry) { return geometry; } +RpGeometry *RpGeometryTransform(RpGeometry *geometry, const RwMatrix *matrix); +RpGeometry *RpGeometryCreateSpace(RwReal radius); +RpMorphTarget *RpMorphTargetSetBoundingSphere(RpMorphTarget *morphTarget, const RwSphere *boundingSphere) { morphTarget->boundingSphere = *boundingSphere; return morphTarget; } +RwSphere *RpMorphTargetGetBoundingSphere(RpMorphTarget *morphTarget) { return &morphTarget->boundingSphere; } +const RpMorphTarget *RpMorphTargetCalcBoundingSphere(const RpMorphTarget *morphTarget, RwSphere *boundingSphere) { *boundingSphere = morphTarget->calculateBoundingSphere(); return morphTarget; } +RwInt32 RpGeometryAddMorphTargets(RpGeometry *geometry, RwInt32 mtcount); +RwInt32 RpGeometryAddMorphTarget(RpGeometry *geometry); +RpGeometry *RpGeometryRemoveMorphTarget(RpGeometry *geometry, RwInt32 morphTarget); +RwInt32 RpGeometryGetNumMorphTargets(const RpGeometry *geometry); +RpMorphTarget *RpGeometryGetMorphTarget(const RpGeometry *geometry, RwInt32 morphTarget) { return &geometry->morphTargets[morphTarget]; } +RwRGBA *RpGeometryGetPreLightColors(const RpGeometry *geometry) { return geometry->colors; } +RwTexCoords *RpGeometryGetVertexTexCoords(const RpGeometry *geometry, RwTextureCoordinateIndex uvIndex) { return geometry->texCoords[uvIndex]; } +RwInt32 RpGeometryGetNumTexCoordSets(const RpGeometry *geometry) { return geometry->numTexCoordSets; } +RwInt32 RpGeometryGetNumVertices (const RpGeometry *geometry) { return geometry->numVertices; } +RwV3d *RpMorphTargetGetVertices(const RpMorphTarget *morphTarget) { return morphTarget->vertices; } +RwV3d *RpMorphTargetGetVertexNormals(const RpMorphTarget *morphTarget) { return morphTarget->normals; } +RpTriangle *RpGeometryGetTriangles(const RpGeometry *geometry) { return geometry->triangles; } +RwInt32 RpGeometryGetNumTriangles(const RpGeometry *geometry) { return geometry->numTriangles; } +RpMaterial *RpGeometryGetMaterial(const RpGeometry *geometry, RwInt32 matNum) { return geometry->matList.materials[matNum]; } +const RpGeometry *RpGeometryTriangleSetVertexIndices(const RpGeometry *geometry, RpTriangle *triangle, RwUInt16 vert1, RwUInt16 vert2, RwUInt16 vert3) + { triangle->v[0] = vert1; triangle->v[1] = vert2; triangle->v[2] = vert3; return geometry; } +RpGeometry *RpGeometryTriangleSetMaterial(RpGeometry *geometry, RpTriangle *triangle, RpMaterial *material) { + int id = geometry->matList.findIndex(material); + if(id < 0) + id = geometry->matList.appendMaterial(material); + if(id < 0) + return nil; + triangle->matId = id; + return geometry; +} +const RpGeometry *RpGeometryTriangleGetVertexIndices(const RpGeometry *geometry, const RpTriangle *triangle, RwUInt16 *vert1, RwUInt16 *vert2, RwUInt16 *vert3); +RpMaterial *RpGeometryTriangleGetMaterial(const RpGeometry *geometry, const RpTriangle *triangle); +RwInt32 RpGeometryGetNumMaterials(const RpGeometry *geometry); +RpGeometry *RpGeometryForAllMaterials(RpGeometry *geometry, RpMaterialCallBack fpCallBack, void *pData) { + int i; + for(i = 0; i < geometry->matList.numMaterials; i++) + if(fpCallBack(geometry->matList.materials[i], pData) == nil) + break; + return geometry; +} +//const RpGeometry *RpGeometryForAllMeshes(const RpGeometry *geometry, RpMeshCallBack fpCallBack, void *pData); +RwInt32 RpGeometryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RpGeometryRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +RwInt32 RpGeometrySetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +RwInt32 RpGeometryGetPluginOffset(RwUInt32 pluginID); +RwBool RpGeometryValidatePlugins(const RpGeometry *geometry); +RwUInt32 RpGeometryStreamGetSize(const RpGeometry *geometry); +const RpGeometry *RpGeometryStreamWrite(const RpGeometry *geometry, RwStream *stream); +RpGeometry *RpGeometryStreamRead(RwStream *stream) { return Geometry::streamRead(stream); } +//RpGeometryChunkInfo *_rpGeometryChunkInfoRead(RwStream *stream, RpGeometryChunkInfo *geometryChunkInfo, RwInt32 *bytesRead); +RwUInt32 RpGeometryGetFlags(const RpGeometry *geometry) { return geometry->flags; } +RpGeometry *RpGeometrySetFlags(RpGeometry *geometry, RwUInt32 flags) { geometry->flags = flags; return geometry; } +const RwSurfaceProperties *_rpGeometryGetSurfaceProperties(const RpGeometry *geometry); +RpGeometry *_rpGeometrySetSurfaceProperties(RpGeometry *geometry, const RwSurfaceProperties *surfaceProperties); + + + + + +RwFrame *RpClumpGetFrame(const RpClump * clump) { return clump->getFrame(); } +RpClump *RpClumpSetFrame(RpClump * clump, RwFrame * frame) { clump->setFrame(frame); return clump; } +RpClump *RpClumpForAllAtomics(RpClump * clump, RpAtomicCallBack callback, void *pData) { + FORLIST(lnk, clump->atomics) + if(callback(Atomic::fromClump(lnk), pData) == nil) + break; + return clump; +} +RpClump *RpClumpForAllLights(RpClump * clump, RpLightCallBack callback, void *pData); +RpClump *RpClumpForAllCameras(RpClump * clump, RwCameraCallBack callback, void *pData); +//RpClump *RpClumpCreateSpace(const RwV3d * position, RwReal radius); +RpClump *RpClumpRender(RpClump * clump) { clump->render(); return clump; } +RpClump *RpClumpRemoveAtomic(RpClump * clump, RpAtomic * atomic) { atomic->removeFromClump(); return clump; } +RpClump *RpClumpAddAtomic(RpClump * clump, RpAtomic * atomic) { clump->addAtomic(atomic); return clump; } +//RpClump *RpClumpRemoveLight(RpClump * clump, RpLight * light); +//RpClump *RpClumpAddLight(RpClump * clump, RpLight * light); +//RpClump *RpClumpRemoveCamera(RpClump * clump, RwCamera * camera); +//RpClump *RpClumpAddCamera(RpClump * clump, RwCamera * camera); +RwBool RpClumpDestroy(RpClump * clump) { clump->destroy(); return true; } +RpClump *RpClumpCreate(void) { return rw::Clump::create(); } +RpClump *RpClumpClone(RpClump * clump) { return clump->clone(); } +//RpClump *RpClumpSetCallBack(RpClump * clump, RpClumpCallBack callback); +//RpClumpCallBack RpClumpGetCallBack(const RpClump * clump); +RwInt32 RpClumpGetNumAtomics(RpClump * clump) { return clump->countAtomics(); } +//RwInt32 RpClumpGetNumLights(RpClump * clump); +//RwInt32 RpClumpGetNumCameras(RpClump * clump); +RpClump *RpClumpStreamRead(RwStream * stream) { return rw::Clump::streamRead(stream); } +//RpClump *RpClumpStreamWrite(RpClump * clump, RwStream * stream); +RwInt32 RpClumpRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) + { return Clump::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); } +RwInt32 RpClumpRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) + { return Clump::registerPluginStream(pluginID, readCB, (StreamWrite)writeCB, (StreamGetSize)getSizeCB); } +//RwInt32 RpClumpSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +//RwInt32 RpClumpGetPluginOffset(RwUInt32 pluginID); +//RwBool RpClumpValidatePlugins(const RpClump * clump); + + + +RpAtomic *RpAtomicCreate(void) { return rw::Atomic::create(); } +RwBool RpAtomicDestroy(RpAtomic * atomic) { atomic->destroy(); return true; } +RpAtomic *RpAtomicClone(RpAtomic * atomic) { return atomic->clone(); } +RpAtomic *RpAtomicSetFrame(RpAtomic * atomic, RwFrame * frame) { atomic->setFrame(frame); return atomic; } +RpAtomic *RpAtomicSetGeometry(RpAtomic * atomic, RpGeometry * geometry, RwUInt32 flags) { atomic->setGeometry(geometry, flags); return atomic; } + +RwFrame *RpAtomicGetFrame(const RpAtomic * atomic) { return atomic->getFrame(); } +RpAtomic *RpAtomicSetFlags(RpAtomic * atomic, RwUInt32 flags) { atomic->setFlags(flags); return atomic; } +RwUInt32 RpAtomicGetFlags(const RpAtomic * atomic) { return atomic->getFlags(); } +RwSphere *RpAtomicGetBoundingSphere(RpAtomic * atomic) { return &atomic->boundingSphere; } +RpAtomic *RpAtomicRender(RpAtomic * atomic) { atomic->render(); return atomic; } +RpClump *RpAtomicGetClump(const RpAtomic * atomic) { return atomic->clump; } +//RpInterpolator *RpAtomicGetInterpolator(RpAtomic * atomic); +RpGeometry *RpAtomicGetGeometry(const RpAtomic * atomic) { return atomic->geometry; } +// WARNING: illegal cast +void RpAtomicSetRenderCallBack(RpAtomic * atomic, RpAtomicCallBackRender callback) { atomic->setRenderCB((Atomic::RenderCB)callback); } +RpAtomicCallBackRender RpAtomicGetRenderCallBack(const RpAtomic * atomic) { return (RpAtomicCallBackRender)atomic->renderCB; } +//RwBool RpAtomicInstance(RpAtomic *atomic); +//RwUInt32 RpAtomicStreamGetSize(RpAtomic * atomic); +//RpAtomic *RpAtomicStreamRead(RwStream * stream); +//RpAtomic *RpAtomicStreamWrite(RpAtomic * atomic, RwStream * stream); +RwInt32 RpAtomicRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) + { return Atomic::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); } +//RwInt32 RpAtomicRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +//RwInt32 RpAtomicSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +//RwInt32 RpAtomicSetStreamRightsCallBack(RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB); +//RwInt32 RpAtomicGetPluginOffset(RwUInt32 pluginID); +//RwBool RpAtomicValidatePlugins(const RpAtomic * atomic); + +RpAtomic *AtomicDefaultRenderCallBack(RpAtomic * atomic) { Atomic::defaultRenderCB(atomic); return atomic; } + + +// TODO: this is extremely simplified +RpWorld *RpWorldCreate(RwBBox * boundingBox) { return World::create(); } +RwBool RpWorldDestroy(RpWorld * world) { world->destroy(); return true; } + +RwBool RpWorldPluginAttach(void) { + registerMeshPlugin(); + registerNativeDataPlugin(); + registerAtomicRightsPlugin(); + registerMaterialRightsPlugin(); + return true; +} + +RpWorld *RpWorldRemoveCamera(RpWorld *world, RwCamera *camera) { world->removeCamera(camera); return world; } +RpWorld *RpWorldAddCamera(RpWorld *world, RwCamera *camera) { world->addCamera(camera); return world; } +RpWorld *RwCameraGetWorld(const RwCamera *camera); +RpWorld *RpWorldRemoveAtomic(RpWorld *world, RpAtomic *atomic); +RpWorld *RpWorldAddAtomic(RpWorld *world, RpAtomic *atomic); +RpWorld *RpAtomicGetWorld(const RpAtomic *atomic); +RpWorld *RpWorldAddClump(RpWorld *world, RpClump *clump); +RpWorld *RpWorldRemoveClump(RpWorld *world, RpClump *clump); +RpWorld *RpClumpGetWorld(const RpClump *clump); +RpWorld *RpWorldAddLight(RpWorld *world, RpLight *light) { world->addLight(light); return world; } +RpWorld *RpWorldRemoveLight(RpWorld *world, RpLight *light) { world->removeLight(light); return world; } +RpWorld *RpLightGetWorld(const RpLight *light); +RwCamera *RwCameraForAllClumpsInFrustum(RwCamera *camera, void *data); +RwCamera *RwCameraForAllClumpsNotInFrustum(RwCamera *camera, RwInt32 numClumps, void *data); + + + + +RwBool RpMatFXPluginAttach( void ) { registerMatFXPlugin(); return true; } +RpAtomic *RpMatFXAtomicEnableEffects( RpAtomic *atomic ) { MatFX::enableEffects(atomic); return atomic; } +RpMaterial *RpMatFXMaterialSetEffects( RpMaterial *material, RpMatFXMaterialFlags flags ) { MatFX::setEffects(material, (uint32)flags); return material; } +RpMaterial *RpMatFXMaterialSetupEnvMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwBool useFrameBufferAlpha, RwReal coef ) { + MatFX *mfx = MatFX::get(material); + mfx->setEnvTexture(texture); + mfx->setEnvFrame(frame); + mfx->setEnvCoefficient(coef); + return material; +} + + + + + +RwBool RpHAnimPluginAttach(void) { + registerHAnimPlugin(); + return true; +} + +RwBool RpHAnimFrameSetHierarchy(RwFrame *frame, RpHAnimHierarchy *hierarchy) { HAnimData::get(frame)->hierarchy = hierarchy; return true; } +RpHAnimHierarchy *RpHAnimFrameGetHierarchy(RwFrame *frame) { return HAnimHierarchy::get(frame); } + +RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim) { hierarchy->currentAnim->setCurrentAnim(anim); return true; } +RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time) { hierarchy->currentAnim->addTime(time); return true; } + +RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy) { hierarchy->updateMatrices(); return true; } + +RpHAnimAnimation *RpHAnimAnimationStreamRead(RwStream *stream) { return Animation::streamRead(stream); } + + + + + + +RwBool RpSkinPluginAttach(void) { + registerSkinPlugin(); + return true; +} + +RpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy ) { Skin::setHierarchy(atomic, hierarchy); return atomic; } +RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ) { return Skin::getHierarchy(atomic); } + + + + + +RwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName) { rw::writeBMP(image, imageName); return image; } +RwImage *RtBMPImageRead(const RwChar * imageName) { return rw::readBMP(imageName); } diff --git a/src/fakerw/rphanim.h b/src/fakerw/rphanim.h new file mode 100644 index 00000000..665e03f8 --- /dev/null +++ b/src/fakerw/rphanim.h @@ -0,0 +1,20 @@ +#pragma once + +//struct RpHAnimHierarchy; +typedef rw::HAnimHierarchy RpHAnimHierarchy; +//struct RpHAnimAnimation; +typedef rw::Animation RpHAnimAnimation; + +RwBool RpHAnimPluginAttach(void); + +RwBool RpHAnimFrameSetHierarchy(RwFrame *frame, RpHAnimHierarchy *hierarchy); +RpHAnimHierarchy *RpHAnimFrameGetHierarchy(RwFrame *frame); + +RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim); +RwBool RpHAnimHierarchySetCurrentAnimTime(RpHAnimHierarchy *hierarchy, RwReal time); +RwBool RpHAnimHierarchySubAnimTime(RpHAnimHierarchy *hierarchy, RwReal time); +RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time); + +RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy); + +RpHAnimAnimation *RpHAnimAnimationStreamRead(RwStream *stream); diff --git a/src/fakerw/rpmatfx.h b/src/fakerw/rpmatfx.h new file mode 100644 index 00000000..87c8fb2e --- /dev/null +++ b/src/fakerw/rpmatfx.h @@ -0,0 +1,43 @@ +#pragma once + +enum RpMatFXMaterialFlags +{ + rpMATFXEFFECTNULL = rw::MatFX::NOTHING, + rpMATFXEFFECTBUMPMAP = rw::MatFX::BUMPMAP, + rpMATFXEFFECTENVMAP = rw::MatFX::ENVMAP, + rpMATFXEFFECTBUMPENVMAP = rw::MatFX::BUMPENVMAP, + rpMATFXEFFECTDUAL = rw::MatFX::DUAL, + + rpMATFXEFFECTMAX, + rpMATFXNUMEFFECTS = rpMATFXEFFECTMAX - 1, +}; + +RwBool RpMatFXPluginAttach( void ); +RpAtomic *RpMatFXAtomicEnableEffects( RpAtomic *atomic ); +RwBool RpMatFXAtomicQueryEffects( RpAtomic *atomic ); +//RpWorldSector *RpMatFXWorldSectorEnableEffects( RpWorldSector *worldSector ); +//RwBool RpMatFXWorldSectorQueryEffects( RpWorldSector *worldSector ); +RpMaterial *RpMatFXMaterialSetEffects( RpMaterial *material, RpMatFXMaterialFlags flags ); +RpMaterial *RpMatFXMaterialSetupBumpMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwReal coef ); +RpMaterial *RpMatFXMaterialSetupEnvMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwBool useFrameBufferAlpha, RwReal coef ); +RpMaterial *RpMatFXMaterialSetupDualTexture( RpMaterial *material, RwTexture *texture, RwBlendFunction srcBlendMode, RwBlendFunction dstBlendMode ); +RpMatFXMaterialFlags RpMatFXMaterialGetEffects( const RpMaterial *material ); +RpMaterial *RpMatFXMaterialSetBumpMapTexture( RpMaterial *material, RwTexture *texture ); +RpMaterial *RpMatFXMaterialSetBumpMapFrame( RpMaterial *material, RwFrame *frame ); +RpMaterial *RpMatFXMaterialSetBumpMapCoefficient( RpMaterial *material, RwReal coef ); +RwTexture *RpMatFXMaterialGetBumpMapTexture( const RpMaterial *material ); +RwTexture *RpMatFXMaterialGetBumpMapBumpedTexture( const RpMaterial *material ); +RwFrame *RpMatFXMaterialGetBumpMapFrame( const RpMaterial *material ); +RwReal RpMatFXMaterialGetBumpMapCoefficient( const RpMaterial *material ); +RpMaterial *RpMatFXMaterialSetEnvMapTexture( RpMaterial *material, RwTexture *texture ); +RpMaterial *RpMatFXMaterialSetEnvMapFrame( RpMaterial *material, RwFrame *frame ); +RpMaterial *RpMatFXMaterialSetEnvMapFrameBufferAlpha( RpMaterial *material, RwBool useFrameBufferAlpha ); +RpMaterial *RpMatFXMaterialSetEnvMapCoefficient( RpMaterial *material, RwReal coef ); +RwTexture *RpMatFXMaterialGetEnvMapTexture( const RpMaterial *material ); +RwFrame *RpMatFXMaterialGetEnvMapFrame( const RpMaterial *material ); +RwBool RpMatFXMaterialGetEnvMapFrameBufferAlpha( const RpMaterial *material ); +RwReal RpMatFXMaterialGetEnvMapCoefficient( const RpMaterial *material ); +RpMaterial *RpMatFXMaterialSetDualTexture( RpMaterial *material, RwTexture *texture ); +RpMaterial *RpMatFXMaterialSetDualBlendModes( RpMaterial *material, RwBlendFunction srcBlendMode, RwBlendFunction dstBlendMode ); +RwTexture *RpMatFXMaterialGetDualTexture( const RpMaterial *material ); +const RpMaterial *RpMatFXMaterialGetDualBlendModes( const RpMaterial *material, RwBlendFunction *srcBlendMode, RwBlendFunction *dstBlendMode ); diff --git a/src/fakerw/rpskin.h b/src/fakerw/rpskin.h new file mode 100644 index 00000000..dd8551ae --- /dev/null +++ b/src/fakerw/rpskin.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +RwBool RpSkinPluginAttach(void); + +RpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy ); +RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ); diff --git a/src/fakerw/rpworld.h b/src/fakerw/rpworld.h new file mode 100644 index 00000000..d2ac2454 --- /dev/null +++ b/src/fakerw/rpworld.h @@ -0,0 +1,336 @@ +#pragma once + +#define rpATOMIC rw::Atomic::ID +#define rpCLUMP rw::Clump::ID + +/* + *********************************************** + * + * RpMaterial + * + *********************************************** + */ + +//struct RpMaterial; +typedef rw::Material RpMaterial; + +typedef RpMaterial *(*RpMaterialCallBack)(RpMaterial *material, void *data); + +RpMaterial *RpMaterialCreate(void); +RwBool RpMaterialDestroy(RpMaterial *material); +RpMaterial *RpMaterialClone(RpMaterial *material); +RpMaterial *RpMaterialSetTexture(RpMaterial *material, RwTexture *texture); +RpMaterial *RpMaterialAddRef(RpMaterial *material); +RwTexture *RpMaterialGetTexture(const RpMaterial *material); +RpMaterial *RpMaterialSetColor(RpMaterial *material, const RwRGBA *color); +const RwRGBA *RpMaterialGetColor(const RpMaterial *material); +RpMaterial *RpMaterialSetSurfaceProperties(RpMaterial *material, const RwSurfaceProperties *surfaceProperties); +const RwSurfaceProperties *RpMaterialGetSurfaceProperties(const RpMaterial *material); +RwInt32 RpMaterialRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +RwInt32 RpMaterialSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +RwInt32 RpMaterialGetPluginOffset(RwUInt32 pluginID); +RwBool RpMaterialValidatePlugins(const RpMaterial *material); +RwUInt32 RpMaterialStreamGetSize(const RpMaterial *material); +RpMaterial *RpMaterialStreamRead(RwStream *stream); +const RpMaterial *RpMaterialStreamWrite(const RpMaterial *material, RwStream *stream); +//RpMaterialChunkInfo *_rpMaterialChunkInfoRead(RwStream *stream, RpMaterialChunkInfo *materialChunkInfo, RwInt32 *bytesRead); + + +/* + *********************************************** + * + * RpLight + * + *********************************************** + */ + +//struct RpLight; +typedef rw::Light RpLight; + +enum RpLightType +{ + rpNALIGHTTYPE = 0, + rpLIGHTDIRECTIONAL, + rpLIGHTAMBIENT, + rpLIGHTPOINT = 0x80, + rpLIGHTSPOT, + rpLIGHTSPOTSOFT, +}; + +enum RpLightFlag +{ + rpLIGHTLIGHTATOMICS = 0x01, + rpLIGHTLIGHTWORLD = 0x02, +}; + +typedef RpLight *(*RpLightCallBack) (RpLight * light, void *data); + +RwReal RpLightGetRadius(const RpLight *light); +const RwRGBAReal *RpLightGetColor(const RpLight *light); +RpLight *RpLightSetFrame(RpLight *light, RwFrame *frame); +RwFrame *RpLightGetFrame(const RpLight *light); +RpLightType RpLightGetType(const RpLight *light); +RpLight *RpLightSetFlags(RpLight *light, RwUInt32 flags); +RwUInt32 RpLightGetFlags(const RpLight *light); +RpLight *RpLightCreate(RwInt32 type); +RwBool RpLightDestroy(RpLight *light); +RpLight *RpLightSetRadius(RpLight *light, RwReal radius); +RpLight *RpLightSetColor(RpLight *light, const RwRGBAReal *color); +RwReal RpLightGetConeAngle(const RpLight *light); +RpLight *RpLightSetConeAngle(RpLight * ight, RwReal angle); +RwUInt32 RpLightStreamGetSize(const RpLight *light); +RpLight *RpLightStreamRead(RwStream *stream); +const RpLight *RpLightStreamWrite(const RpLight *light, RwStream *stream); +//RpLightChunkInfo *_rpLightChunkInfoRead(RwStream *stream, RpLightChunkInfo *lightChunkInfo, RwInt32 *bytesRead); +RwInt32 RpLightRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RpLightRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +RwInt32 RpLightSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +RwInt32 RpLightGetPluginOffset(RwUInt32 pluginID); +RwBool RpLightValidatePlugins(const RpLight * light); + +/* + *********************************************** + * + * RpGeometry + * + *********************************************** + */ + +typedef rw::Triangle RpTriangle; + +//struct RpGeometry; +typedef rw::Geometry RpGeometry; +//struct RpMorphTarget; +typedef rw::MorphTarget RpMorphTarget; + +enum RpGeometryFlag +{ + rpGEOMETRYTRISTRIP = rw::Geometry::TRISTRIP, + rpGEOMETRYPOSITIONS = rw::Geometry::POSITIONS, + rpGEOMETRYTEXTURED = rw::Geometry::TEXTURED, + rpGEOMETRYPRELIT = rw::Geometry::PRELIT, + rpGEOMETRYNORMALS = rw::Geometry::NORMALS, + rpGEOMETRYLIGHT = rw::Geometry::LIGHT, + rpGEOMETRYMODULATEMATERIALCOLOR = rw::Geometry::MODULATE, + rpGEOMETRYTEXTURED2 = rw::Geometry::TEXTURED2, + rpGEOMETRYNATIVE = rw::Geometry::NATIVE, + rpGEOMETRYNATIVEINSTANCE = rw::Geometry::NATIVEINSTANCE, + rpGEOMETRYFLAGSMASK = 0x000000FF, + rpGEOMETRYNATIVEFLAGSMASK = 0x0F000000, +}; + +enum RpGeometryLockMode +{ + rpGEOMETRYLOCKPOLYGONS = 0x01, + rpGEOMETRYLOCKVERTICES = 0x02, + rpGEOMETRYLOCKNORMALS = 0x04, + rpGEOMETRYLOCKPRELIGHT = 0x08, + rpGEOMETRYLOCKTEXCOORDS = 0x10, + rpGEOMETRYLOCKTEXCOORDS1 = 0x10, + rpGEOMETRYLOCKTEXCOORDS2 = 0x20, + rpGEOMETRYLOCKTEXCOORDS3 = 0x40, + rpGEOMETRYLOCKTEXCOORDS4 = 0x80, + rpGEOMETRYLOCKTEXCOORDS5 = 0x0100, + rpGEOMETRYLOCKTEXCOORDS6 = 0x0200, + rpGEOMETRYLOCKTEXCOORDS7 = 0x0400, + rpGEOMETRYLOCKTEXCOORDS8 = 0x0800, + rpGEOMETRYLOCKTEXCOORDSALL = 0x0ff0, + rpGEOMETRYLOCKALL = 0x0fff +}; + +RpGeometry *RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format); +RwBool RpGeometryDestroy(RpGeometry *geometry); +RpGeometry *_rpGeometryAddRef(RpGeometry *geometry); +RpGeometry *RpGeometryLock(RpGeometry *geometry, RwInt32 lockMode); +RpGeometry *RpGeometryUnlock(RpGeometry *geometry); +RpGeometry *RpGeometryTransform(RpGeometry *geometry, const RwMatrix *matrix); +RpGeometry *RpGeometryCreateSpace(RwReal radius); +RpMorphTarget *RpMorphTargetSetBoundingSphere(RpMorphTarget *morphTarget, const RwSphere *boundingSphere); +RwSphere *RpMorphTargetGetBoundingSphere(RpMorphTarget *morphTarget); +const RpMorphTarget *RpMorphTargetCalcBoundingSphere(const RpMorphTarget *morphTarget, RwSphere *boundingSphere); +RwInt32 RpGeometryAddMorphTargets(RpGeometry *geometry, RwInt32 mtcount); +RwInt32 RpGeometryAddMorphTarget(RpGeometry *geometry); +RpGeometry *RpGeometryRemoveMorphTarget(RpGeometry *geometry, RwInt32 morphTarget); +RwInt32 RpGeometryGetNumMorphTargets(const RpGeometry *geometry); +RpMorphTarget *RpGeometryGetMorphTarget(const RpGeometry *geometry, RwInt32 morphTarget); +RwRGBA *RpGeometryGetPreLightColors(const RpGeometry *geometry); +RwTexCoords *RpGeometryGetVertexTexCoords(const RpGeometry *geometry, RwTextureCoordinateIndex uvIndex); +RwInt32 RpGeometryGetNumTexCoordSets(const RpGeometry *geometry); +RwInt32 RpGeometryGetNumVertices (const RpGeometry *geometry); +RwV3d *RpMorphTargetGetVertices(const RpMorphTarget *morphTarget); +RwV3d *RpMorphTargetGetVertexNormals(const RpMorphTarget *morphTarget); +RpTriangle *RpGeometryGetTriangles(const RpGeometry *geometry); +RwInt32 RpGeometryGetNumTriangles(const RpGeometry *geometry); +RpMaterial *RpGeometryGetMaterial(const RpGeometry *geometry, RwInt32 matNum); +const RpGeometry *RpGeometryTriangleSetVertexIndices(const RpGeometry *geometry, RpTriangle *triangle, RwUInt16 vert1, RwUInt16 vert2, RwUInt16 vert3); +RpGeometry *RpGeometryTriangleSetMaterial(RpGeometry *geometry, RpTriangle *triangle, RpMaterial *material); +const RpGeometry *RpGeometryTriangleGetVertexIndices(const RpGeometry *geometry, const RpTriangle *triangle, RwUInt16 *vert1, RwUInt16 *vert2, RwUInt16 *vert3); +RpMaterial *RpGeometryTriangleGetMaterial(const RpGeometry *geometry, const RpTriangle *triangle); +RwInt32 RpGeometryGetNumMaterials(const RpGeometry *geometry); +RpGeometry *RpGeometryForAllMaterials(RpGeometry *geometry, RpMaterialCallBack fpCallBack, void *pData); +//const RpGeometry *RpGeometryForAllMeshes(const RpGeometry *geometry, RpMeshCallBack fpCallBack, void *pData); +RwInt32 RpGeometryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RpGeometryRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +RwInt32 RpGeometrySetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +RwInt32 RpGeometryGetPluginOffset(RwUInt32 pluginID); +RwBool RpGeometryValidatePlugins(const RpGeometry *geometry); +RwUInt32 RpGeometryStreamGetSize(const RpGeometry *geometry); +const RpGeometry *RpGeometryStreamWrite(const RpGeometry *geometry, RwStream *stream); +RpGeometry *RpGeometryStreamRead(RwStream *stream); +//RpGeometryChunkInfo *_rpGeometryChunkInfoRead(RwStream *stream, RpGeometryChunkInfo *geometryChunkInfo, RwInt32 *bytesRead); +RwUInt32 RpGeometryGetFlags(const RpGeometry *geometry); +RpGeometry *RpGeometrySetFlags(RpGeometry *geometry, RwUInt32 flags); +const RwSurfaceProperties *_rpGeometryGetSurfaceProperties(const RpGeometry *geometry); +RpGeometry *_rpGeometrySetSurfaceProperties(RpGeometry *geometry, const RwSurfaceProperties *surfaceProperties); + + +/* + *********************************************** + * + * RpAtomic and RpClump + * + *********************************************** + */ + +//struct RpAtomic; +typedef rw::Atomic RpAtomic; + +enum RpAtomicFlag +{ + rpATOMICCOLLISIONTEST = 0x01, + rpATOMICRENDER = 0x04, +}; + +enum RpAtomicSetGeomFlag +{ + rpATOMICSAMEBOUNDINGSPHERE = 0x01, +}; + +typedef RpAtomic *(*RpAtomicCallBack) (RpAtomic * atomic, void *data); +typedef RpAtomic *(*RpAtomicCallBackRender) (RpAtomic * atomic); + + +//struct RpClump; +typedef rw::Clump RpClump; + +struct RpClumpChunkInfo +{ + RwInt32 numAtomics; + RwInt32 numLights; + RwInt32 numCameras; +}; + +typedef RpClump *(*RpClumpCallBack) (RpClump * clump, void *data); + + +RpAtomic *AtomicDefaultRenderCallBack(RpAtomic * atomic); +//void _rpAtomicResyncInterpolatedSphere(RpAtomic * atomic); +//const RwSphere *RpAtomicGetWorldBoundingSphere(RpAtomic * atomic); + +RwFrame *RpClumpGetFrame(const RpClump * clump); +RpClump *RpClumpSetFrame(RpClump * clump, RwFrame * frame); +RpClump *RpClumpForAllAtomics(RpClump * clump, RpAtomicCallBack callback, void *pData); +RpClump *RpClumpForAllLights(RpClump * clump, RpLightCallBack callback, void *pData); +RpClump *RpClumpForAllCameras(RpClump * clump, RwCameraCallBack callback, void *pData); +RpClump *RpClumpCreateSpace(const RwV3d * position, RwReal radius); +RpClump *RpClumpRender(RpClump * clump); +RpClump *RpClumpRemoveAtomic(RpClump * clump, RpAtomic * atomic); +RpClump *RpClumpAddAtomic(RpClump * clump, RpAtomic * atomic); +RpClump *RpClumpRemoveLight(RpClump * clump, RpLight * light); +RpClump *RpClumpAddLight(RpClump * clump, RpLight * light); +RpClump *RpClumpRemoveCamera(RpClump * clump, RwCamera * camera); +RpClump *RpClumpAddCamera(RpClump * clump, RwCamera * camera); +RwBool RpClumpDestroy(RpClump * clump); +RpClump *RpClumpCreate(void); +RpClump *RpClumpClone(RpClump * clump); +RpClump *RpClumpSetCallBack(RpClump * clump, RpClumpCallBack callback); +RpClumpCallBack RpClumpGetCallBack(const RpClump * clump); +RwInt32 RpClumpGetNumAtomics(RpClump * clump); +RwInt32 RpClumpGetNumLights(RpClump * clump); +RwInt32 RpClumpGetNumCameras(RpClump * clump); +RwUInt32 RpClumpStreamGetSize(RpClump * clump); +RpClump *RpClumpStreamRead(RwStream * stream); +RpClump *RpClumpStreamWrite(RpClump * clump, RwStream * stream); +RwInt32 RpClumpRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RpClumpRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +RwInt32 RpClumpSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +RwInt32 RpClumpGetPluginOffset(RwUInt32 pluginID); +RwBool RpClumpValidatePlugins(const RpClump * clump); + +RpAtomic *RpAtomicCreate(void); +RwBool RpAtomicDestroy(RpAtomic * atomic); +RpAtomic *RpAtomicClone(RpAtomic * atomic); +RpAtomic *RpAtomicSetFrame(RpAtomic * atomic, RwFrame * frame); +RpAtomic *RpAtomicSetGeometry(RpAtomic * atomic, RpGeometry * geometry, RwUInt32 flags); + +RwFrame *RpAtomicGetFrame(const RpAtomic * atomic); +RpAtomic *RpAtomicSetFlags(RpAtomic * atomic, RwUInt32 flags); +RwUInt32 RpAtomicGetFlags(const RpAtomic * atomic); +RwSphere *RpAtomicGetBoundingSphere(RpAtomic * atomic); +RpAtomic *RpAtomicRender(RpAtomic * atomic); +RpClump *RpAtomicGetClump(const RpAtomic * atomic); +//RpInterpolator *RpAtomicGetInterpolator(RpAtomic * atomic); +RpGeometry *RpAtomicGetGeometry(const RpAtomic * atomic); +void RpAtomicSetRenderCallBack(RpAtomic * atomic, RpAtomicCallBackRender callback); +RpAtomicCallBackRender RpAtomicGetRenderCallBack(const RpAtomic * atomic); +RwBool RpAtomicInstance(RpAtomic *atomic); +RwUInt32 RpAtomicStreamGetSize(RpAtomic * atomic); +RpAtomic *RpAtomicStreamRead(RwStream * stream); +RpAtomic *RpAtomicStreamWrite(RpAtomic * atomic, RwStream * stream); +RwInt32 RpAtomicRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RpAtomicRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +RwInt32 RpAtomicSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); +RwInt32 RpAtomicSetStreamRightsCallBack(RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB); +RwInt32 RpAtomicGetPluginOffset(RwUInt32 pluginID); +RwBool RpAtomicValidatePlugins(const RpAtomic * atomic); + +//RwInt32 RpInterpolatorGetEndMorphTarget(const RpInterpolator * interpolator); +//RwInt32 RpInterpolatorGetStartMorphTarget(const RpInterpolator * interpolator); +//RwReal RpInterpolatorGetValue(const RpInterpolator * interpolator); +//RwReal RpInterpolatorGetScale(const RpInterpolator * interpolator); +//RpInterpolator *RpInterpolatorSetEndMorphTarget(RpInterpolator * interpolator, RwInt32 morphTarget, RpAtomic * atomic); +//RpInterpolator *RpInterpolatorSetStartMorphTarget(RpInterpolator * interpolator, RwInt32 morphTarget, RpAtomic * atomic); +//RpInterpolator *RpInterpolatorSetValue(RpInterpolator * interpolator, RwReal value, RpAtomic *atomic); +//RpInterpolator *RpInterpolatorSetScale(RpInterpolator * interpolator, RwReal scale, RpAtomic *atomic); + + +RpClump *RpLightGetClump(const RpLight *light); +RpClump *RwCameraGetClump(const RwCamera *camera); + +/* + *********************************************** + * + * RpWorld + * + *********************************************** + */ + +//struct RpWorld; +typedef rw::World RpWorld; + +RwBool RpWorldDestroy(RpWorld * world); +RpWorld *RpWorldCreate(RwBBox * boundingBox); + +RwBool RpWorldPluginAttach(void); + +RpWorld *RpWorldRemoveCamera(RpWorld *world, RwCamera *camera); +RpWorld *RpWorldAddCamera(RpWorld *world, RwCamera *camera); +RpWorld *RwCameraGetWorld(const RwCamera *camera); +RpWorld *RpWorldRemoveAtomic(RpWorld *world, RpAtomic *atomic); +RpWorld *RpWorldAddAtomic(RpWorld *world, RpAtomic *atomic); +RpWorld *RpAtomicGetWorld(const RpAtomic *atomic); +RpWorld *RpWorldAddClump(RpWorld *world, RpClump *clump); +RpWorld *RpWorldRemoveClump(RpWorld *world, RpClump *clump); +RpWorld *RpClumpGetWorld(const RpClump *clump); +RpWorld *RpWorldAddLight(RpWorld *world, RpLight *light); +RpWorld *RpWorldRemoveLight(RpWorld *world, RpLight *light); +RpWorld *RpLightGetWorld(const RpLight *light); +RwCamera *RwCameraForAllClumpsInFrustum(RwCamera *camera, void *data); +RwCamera *RwCameraForAllClumpsNotInFrustum(RwCamera *camera, RwInt32 numClumps, void *data); +//RwCamera *RwCameraForAllSectorsInFrustum(RwCamera *camera, RpWorldSectorCallBack callBack, void *pData); +//RpLight *RpLightForAllWorldSectors(RpLight *light, RpWorldSectorCallBack callback, void *data); +//RpAtomic *RpAtomicForAllWorldSectors(RpAtomic *atomic, RpWorldSectorCallBack callback, void *data); +//RpWorldSector *RpWorldSectorForAllAtomics(RpWorldSector *sector, RpAtomicCallBack callback, void *data); +//RpWorldSector *RpWorldSectorForAllCollisionAtomics(RpWorldSector *sector, RpAtomicCallBack callback, void *data); +//RpWorldSector *RpWorldSectorForAllLights(RpWorldSector *sector, RpLightCallBack callback, void *data); diff --git a/src/fakerw/rtbmp.h b/src/fakerw/rtbmp.h new file mode 100644 index 00000000..896d276b --- /dev/null +++ b/src/fakerw/rtbmp.h @@ -0,0 +1,4 @@ +#pragma once + +RwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName); +RwImage *RtBMPImageRead(const RwChar * imageName); diff --git a/src/fakerw/rwcore.h b/src/fakerw/rwcore.h new file mode 100644 index 00000000..22e29737 --- /dev/null +++ b/src/fakerw/rwcore.h @@ -0,0 +1,413 @@ +#pragma once + +#define RWCORE_H // needed by CVector + +#include + +#include + +/* + *********************************************** + * + * RwIm2D and RwIm3D + * + *********************************************** + */ + +typedef rw::RWDEVICE::Im2DVertex RwIm2DVertex; +typedef rw::RWDEVICE::Im3DVertex RwIm3DVertex; +typedef RwUInt16 RwImVertexIndex; + +enum RwIm3DTransformFlags +{ + rwIM3D_VERTEXUV = 1, + rwIM3D_ALLOPAQUE = 2, + rwIM3D_NOCLIP = 4, + rwIM3D_VERTEXXYZ = 8, + rwIM3D_VERTEXRGBA = 16, +}; + +void RwIm2DVertexSetCameraX(RwIm2DVertex *vert, RwReal camx); +void RwIm2DVertexSetCameraY(RwIm2DVertex *vert, RwReal camy); +void RwIm2DVertexSetCameraZ(RwIm2DVertex *vert, RwReal camz); +void RwIm2DVertexSetRecipCameraZ(RwIm2DVertex *vert, RwReal recipz); +void RwIm2DVertexSetScreenX(RwIm2DVertex *vert, RwReal scrnx); +void RwIm2DVertexSetScreenY(RwIm2DVertex *vert, RwReal scrny); +void RwIm2DVertexSetScreenZ(RwIm2DVertex *vert, RwReal scrnz); +void RwIm2DVertexSetU(RwIm2DVertex *vert, RwReal texU, RwReal recipz); +void RwIm2DVertexSetV(RwIm2DVertex *vert, RwReal texV, RwReal recipz); +void RwIm2DVertexSetIntRGBA(RwIm2DVertex *vert, RwUInt8 red, RwUInt8 green, RwUInt8 blue, RwUInt8 alpha); + +RwReal RwIm2DGetNearScreenZ(void); +RwReal RwIm2DGetFarScreenZ(void); +RwBool RwIm2DRenderLine(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2); +RwBool RwIm2DRenderTriangle(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2, RwInt32 vert3 ); +RwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices); +RwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices); + + +void RwIm3DVertexSetPos(RwIm3DVertex *vert, RwReal x, RwReal y, RwReal z); +void RwIm3DVertexSetU(RwIm3DVertex *vert, RwReal u); +void RwIm3DVertexSetV(RwIm3DVertex *vert, RwReal v); +void RwIm3DVertexSetRGBA(RwIm3DVertex *vert, RwUInt8 r, RwUInt8 g, RwUInt8 b, RwUInt8 a); + +void *RwIm3DTransform(RwIm3DVertex *pVerts, RwUInt32 numVerts, RwMatrix *ltm, RwUInt32 flags); +RwBool RwIm3DEnd(void); +RwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2); +RwBool RwIm3DRenderTriangle(RwInt32 vert1, RwInt32 vert2, RwInt32 vert3); +RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices); +RwBool RwIm3DRenderPrimitive(RwPrimitiveType primType); + + +/* + *********************************************** + * + * RwRaster + * + *********************************************** + */ + +//struct RwRaster; +typedef rw::Raster RwRaster; + +enum RwRasterType +{ + rwRASTERTYPENORMAL = rw::Raster::NORMAL, + rwRASTERTYPEZBUFFER = rw::Raster::ZBUFFER, + rwRASTERTYPECAMERA = rw::Raster::CAMERA, + rwRASTERTYPETEXTURE = rw::Raster::TEXTURE, + rwRASTERTYPECAMERATEXTURE = rw::Raster::CAMERATEXTURE, + rwRASTERTYPEMASK = 0x07, + rwRASTERDONTALLOCATE = rw::Raster::DONTALLOCATE, +}; + +enum RwRasterFormat +{ + rwRASTERFORMATDEFAULT = rw::Raster::DEFAULT, + rwRASTERFORMAT1555 = rw::Raster::C1555, + rwRASTERFORMAT565 = rw::Raster::C565, + rwRASTERFORMAT4444 = rw::Raster::C4444, + rwRASTERFORMATLUM8 = rw::Raster::LUM8, + rwRASTERFORMAT8888 = rw::Raster::C8888, + rwRASTERFORMAT888 = rw::Raster::C888, + rwRASTERFORMAT16 = rw::Raster::D16, + rwRASTERFORMAT24 = rw::Raster::D24, + rwRASTERFORMAT32 = rw::Raster::D32, + rwRASTERFORMAT555 = rw::Raster::C555, + + rwRASTERFORMATAUTOMIPMAP = rw::Raster::AUTOMIPMAP, + rwRASTERFORMATPAL8 = rw::Raster::PAL8, + rwRASTERFORMATPAL4 = rw::Raster::PAL4, + rwRASTERFORMATMIPMAP = rw::Raster::MIPMAP, + + rwRASTERFORMATPIXELFORMATMASK = 0x0f00, + rwRASTERFORMATMASK = 0xff00 +}; + +enum RwRasterFlipMode +{ + rwRASTERFLIPDONTWAIT = 0, + rwRASTERFLIPWAITVSYNC = 1, +}; + +RwRaster *RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags); +RwBool RwRasterDestroy(RwRaster * raster); +RwInt32 RwRasterGetWidth(const RwRaster *raster); +RwInt32 RwRasterGetHeight(const RwRaster *raster); +RwInt32 RwRasterGetStride(const RwRaster *raster); +RwInt32 RwRasterGetDepth(const RwRaster *raster); +RwInt32 RwRasterGetFormat(const RwRaster *raster); +RwInt32 RwRasterGetType(const RwRaster *raster); +RwRaster *RwRasterGetParent(const RwRaster *raster); +RwRaster *RwRasterGetOffset(RwRaster *raster, RwInt16 *xOffset, RwInt16 *yOffset); +RwInt32 RwRasterGetNumLevels(RwRaster * raster); +RwRaster *RwRasterSubRaster(RwRaster * subRaster, RwRaster * raster, RwRect * rect); +RwRaster *RwRasterRenderFast(RwRaster * raster, RwInt32 x, RwInt32 y); +RwRaster *RwRasterRender(RwRaster * raster, RwInt32 x, RwInt32 y); +RwRaster *RwRasterRenderScaled(RwRaster * raster, RwRect * rect); +RwRaster *RwRasterPushContext(RwRaster * raster); +RwRaster *RwRasterPopContext(void); +RwRaster *RwRasterGetCurrentContext(void); +RwBool RwRasterClear(RwInt32 pixelValue); +RwBool RwRasterClearRect(RwRect * rpRect, RwInt32 pixelValue); +RwRaster *RwRasterShowRaster(RwRaster * raster, void *dev, RwUInt32 flags); +RwUInt8 *RwRasterLock(RwRaster * raster, RwUInt8 level, RwInt32 lockMode); +RwRaster *RwRasterUnlock(RwRaster * raster); +RwUInt8 *RwRasterLockPalette(RwRaster * raster, RwInt32 lockMode); +RwRaster *RwRasterUnlockPalette(RwRaster * raster); +RwInt32 RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwRasterGetPluginOffset(RwUInt32 pluginID); +RwBool RwRasterValidatePlugins(const RwRaster * raster); + + +/* + *********************************************** + * + * RwImage + * + *********************************************** + */ + +//struct RwImage; +typedef rw::Image RwImage; + +RwImage *RwImageCreate(RwInt32 width, RwInt32 height, RwInt32 depth); +RwBool RwImageDestroy(RwImage * image); +RwImage *RwImageAllocatePixels(RwImage * image); +RwImage *RwImageFreePixels(RwImage * image); +RwImage *RwImageCopy(RwImage * destImage, const RwImage * sourceImage); +RwImage *RwImageResize(RwImage * image, RwInt32 width, RwInt32 height); +RwImage *RwImageApplyMask(RwImage * image, const RwImage * mask); +RwImage *RwImageMakeMask(RwImage * image); +RwImage *RwImageReadMaskedImage(const RwChar * imageName, const RwChar * maskname); +RwImage *RwImageRead(const RwChar * imageName); +RwImage *RwImageWrite(RwImage * image, const RwChar * imageName); +RwChar *RwImageGetPath(void); +const RwChar *RwImageSetPath(const RwChar * path); +RwImage *RwImageSetStride(RwImage * image, RwInt32 stride); +RwImage *RwImageSetPixels(RwImage * image, RwUInt8 * pixels); +RwImage *RwImageSetPalette(RwImage * image, RwRGBA * palette); +RwInt32 RwImageGetWidth(const RwImage * image); +RwInt32 RwImageGetHeight(const RwImage * image); +RwInt32 RwImageGetDepth(const RwImage * image); +RwInt32 RwImageGetStride(const RwImage * image); +RwUInt8 *RwImageGetPixels(const RwImage * image); +RwRGBA *RwImageGetPalette(const RwImage * image); +RwUInt32 RwRGBAToPixel(RwRGBA * rgbIn, RwInt32 rasterFormat); +RwRGBA *RwRGBASetFromPixel(RwRGBA * rgbOut, RwUInt32 pixelValue, RwInt32 rasterFormat); +RwBool RwImageSetGamma(RwReal gammaValue); +RwReal RwImageGetGamma(void); +RwImage *RwImageGammaCorrect(RwImage * image); +RwRGBA *RwRGBAGammaCorrect(RwRGBA * rgb); +RwInt32 RwImageRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwImageGetPluginOffset(RwUInt32 pluginID); +RwBool RwImageValidatePlugins(const RwImage * image); +//RwBool RwImageRegisterImageFormat(const RwChar * extension, RwImageCallBackRead imageRead, RwImageCallBackWrite imageWrite); +const RwChar *RwImageFindFileType(const RwChar * imageName); +RwInt32 RwImageStreamGetSize(const RwImage * image); +RwImage *RwImageStreamRead(RwStream * stream); +const RwImage *RwImageStreamWrite(const RwImage * image, RwStream * stream); + + +/* + *********************************************** + * + * RwTexture + * + *********************************************** + */ + +//struct RwTexture; +typedef rw::Texture RwTexture; +//struct RwTexDictionary; +typedef rw::TexDictionary RwTexDictionary; + +typedef RwTexture *(*RwTextureCallBackRead)(const RwChar *name, const RwChar *maskName); +typedef RwTexture *(*RwTextureCallBack)(RwTexture *texture, void *pData); +typedef RwTexDictionary *(*RwTexDictionaryCallBack)(RwTexDictionary *dict, void *data); +typedef RwRaster *(*RwTextureCallBackMipmapGeneration)(RwRaster * raster, RwImage * image); +typedef RwBool (*RwTextureCallBackMipmapName)(RwChar *name, RwChar *maskName, RwUInt8 mipLevel, RwInt32 format); + +RwTexture *RwTextureCreate(RwRaster * raster); +RwBool RwTextureDestroy(RwTexture * texture); +RwTexture *RwTextureAddRef(RwTexture *texture); +RwBool RwTextureSetMipmapping(RwBool enable); +RwBool RwTextureGetMipmapping(void); +RwBool RwTextureSetAutoMipmapping(RwBool enable); +RwBool RwTextureGetAutoMipmapping(void); +RwBool RwTextureSetMipmapGenerationCallBack(RwTextureCallBackMipmapGeneration callback); +RwTextureCallBackMipmapGeneration RwTextureGetMipmapGenerationCallBack(void); +RwBool RwTextureSetMipmapNameCallBack(RwTextureCallBackMipmapName callback); +RwTextureCallBackMipmapName RwTextureGetMipmapNameCallBack(void); +RwBool RwTextureGenerateMipmapName(RwChar * name, RwChar * maskName, RwUInt8 mipLevel, RwInt32 format); +RwBool RwTextureRasterGenerateMipmaps(RwRaster * raster, RwImage * image); +RwTextureCallBackRead RwTextureGetReadCallBack(void); +RwBool RwTextureSetReadCallBack(RwTextureCallBackRead fpCallBack); +RwTexture *RwTextureSetName(RwTexture * texture, const RwChar * name); +RwTexture *RwTextureSetMaskName(RwTexture * texture, const RwChar * maskName); +RwChar *RwTextureGetName(RwTexture *texture); +RwChar *RwTextureGetMaskName(RwTexture *texture); +RwTexture *RwTextureSetRaster(RwTexture * texture, RwRaster * raster); +RwTexture *RwTextureRead(const RwChar * name, const RwChar * maskName); +RwRaster *RwTextureGetRaster(const RwTexture *texture); +RwInt32 RwTextureRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwTextureGetPluginOffset(RwUInt32 pluginID); +RwBool RwTextureValidatePlugins(const RwTexture * texture); + +RwTexDictionary *RwTextureGetDictionary(RwTexture *texture); +RwTexture *RwTextureSetFilterMode(RwTexture *texture, RwTextureFilterMode filtering); +RwTextureFilterMode RwTextureGetFilterMode(const RwTexture *texture); +RwTexture *RwTextureSetAddressing(RwTexture *texture, RwTextureAddressMode addressing); +RwTexture *RwTextureSetAddressingU(RwTexture *texture, RwTextureAddressMode addressing); +RwTexture *RwTextureSetAddressingV(RwTexture *texture, RwTextureAddressMode addressing); +RwTextureAddressMode RwTextureGetAddressing(const RwTexture *texture); +RwTextureAddressMode RwTextureGetAddressingU(const RwTexture *texture); +RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture); + +void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable); + +// hack for reading native textures +RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size); + + +RwTexDictionary *RwTexDictionaryCreate(void); +RwBool RwTexDictionaryDestroy(RwTexDictionary * dict); +RwTexture *RwTexDictionaryAddTexture(RwTexDictionary * dict, RwTexture * texture); +RwTexture *RwTexDictionaryRemoveTexture(RwTexture * texture); +RwTexture *RwTexDictionaryFindNamedTexture(RwTexDictionary * dict, const RwChar * name); +RwTexDictionary *RwTexDictionaryGetCurrent(void); +RwTexDictionary *RwTexDictionarySetCurrent(RwTexDictionary * dict); +const RwTexDictionary *RwTexDictionaryForAllTextures(const RwTexDictionary * dict, RwTextureCallBack fpCallBack, void *pData); +RwBool RwTexDictionaryForAllTexDictionaries(RwTexDictionaryCallBack fpCallBack, void *pData); +RwInt32 RwTexDictionaryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwTexDictionaryGetPluginOffset(RwUInt32 pluginID); +RwBool RwTexDictionaryValidatePlugins(const RwTexDictionary * dict); +RwUInt32 RwTexDictionaryStreamGetSize(const RwTexDictionary *texDict); +RwTexDictionary *RwTexDictionaryStreamRead(RwStream *stream); +const RwTexDictionary *RwTexDictionaryStreamWrite(const RwTexDictionary *texDict, RwStream *stream); + +/* RwImage/RwRaster */ + +RwImage *RwImageSetFromRaster(RwImage *image, RwRaster *raster); +RwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image); +RwRGBA *RwRGBAGetRasterPixel(RwRGBA *rgbOut, RwRaster *raster, RwInt32 x, RwInt32 y); +RwRaster *RwRasterRead(const RwChar *filename); +RwRaster *RwRasterReadMaskedRaster(const RwChar *filename, const RwChar *maskname); +RwImage *RwImageFindRasterFormat(RwImage *ipImage,RwInt32 nRasterType, RwInt32 *npWidth,RwInt32 *npHeight, RwInt32 *npDepth,RwInt32 *npFormat); + + +/* + *********************************************** + * + * RwFrame + * + *********************************************** + */ + +//struct RwFrame; +typedef rw::Frame RwFrame; + +typedef RwFrame *(*RwFrameCallBack)(RwFrame *frame, void *data); + + +RwFrame *RwFrameForAllObjects(RwFrame * frame, RwObjectCallBack callBack, void *data); +RwFrame *RwFrameTranslate(RwFrame * frame, const RwV3d * v, RwOpCombineType combine); +RwFrame *RwFrameRotate(RwFrame * frame, const RwV3d * axis, RwReal angle, RwOpCombineType combine); +RwFrame *RwFrameScale(RwFrame * frame, const RwV3d * v, RwOpCombineType combine); +RwFrame *RwFrameTransform(RwFrame * frame, const RwMatrix * m, RwOpCombineType combine); +RwFrame *RwFrameOrthoNormalize(RwFrame * frame); +RwFrame *RwFrameSetIdentity(RwFrame * frame); +RwFrame *RwFrameCloneHierarchy(RwFrame * root); +RwBool RwFrameDestroyHierarchy(RwFrame * frame); +RwFrame *RwFrameForAllChildren(RwFrame * frame, RwFrameCallBack callBack, void *data); +RwFrame *RwFrameRemoveChild(RwFrame * child); +RwFrame *RwFrameAddChild(RwFrame * parent, RwFrame * child); +RwFrame *RwFrameGetParent(const RwFrame * frame); +RwFrame *RwFrameGetRoot(const RwFrame * frame); +RwMatrix *RwFrameGetLTM(RwFrame * frame); +RwMatrix *RwFrameGetMatrix(RwFrame * frame); +RwFrame *RwFrameUpdateObjects(RwFrame * frame); +RwFrame *RwFrameCreate(void); +RwBool RwFrameInit(RwFrame *frame); +RwBool RwFrameDeInit(RwFrame *frame); +RwBool RwFrameDestroy(RwFrame * frame); +void _rwFrameInit(RwFrame *frame); +void _rwFrameDeInit(RwFrame *frame); +RwBool RwFrameDirty(const RwFrame * frame); +RwInt32 RwFrameCount(RwFrame * frame); +RwBool RwFrameSetStaticPluginsSize(RwInt32 size); +RwInt32 RwFrameRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwFrameGetPluginOffset(RwUInt32 pluginID); +RwBool RwFrameValidatePlugins(const RwFrame * frame); +RwFrame *_rwFrameCloneAndLinkClones(RwFrame * root); +RwFrame *_rwFramePurgeClone(RwFrame *root); + +RwInt32 RwFrameRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB); +RwInt32 RwFrameSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB); + +typedef rw::FrameList_ rwFrameList; +rwFrameList *rwFrameListInitialize(rwFrameList *frameList, RwFrame *frame); +RwBool rwFrameListFindFrame(const rwFrameList *frameList, const RwFrame *frame, RwInt32 *npIndex); +rwFrameList *rwFrameListDeinitialize(rwFrameList *frameList); +RwUInt32 rwFrameListStreamGetSize(const rwFrameList *frameList); +rwFrameList *rwFrameListStreamRead(RwStream *stream, rwFrameList *fl); +const rwFrameList *rwFrameListStreamWrite(const rwFrameList *frameList, RwStream *stream); + + +typedef rw::BBox RwBBox; + +/* + *********************************************** + * + * RwCamera + * + *********************************************** + */ + +//struct RwCamera; +typedef rw::Camera RwCamera; + +typedef RwCamera *(*RwCameraCallBack)(RwCamera *camera, void *data); + +enum RwCameraClearMode +{ + rwCAMERACLEARIMAGE = 0x1, + rwCAMERACLEARZ = 0x2, + rwCAMERACLEARSTENCIL = 0x4 +}; + +enum RwCameraProjection +{ + rwNACAMERAPROJECTION = 0, + rwPERSPECTIVE = 1, + rwPARALLEL = 2 +}; + +enum RwFrustumTestResult +{ + rwSPHEREOUTSIDE = 0, + rwSPHEREBOUNDARY = 1, + rwSPHEREINSIDE = 2 +}; + +RwCamera *RwCameraBeginUpdate(RwCamera * camera); +RwCamera *RwCameraEndUpdate(RwCamera * camera); +RwCamera *RwCameraClear(RwCamera * camera, RwRGBA * colour, RwInt32 clearMode); +RwCamera *RwCameraShowRaster(RwCamera * camera, void *pDev, RwUInt32 flags); +RwBool RwCameraDestroy(RwCamera * camera); +RwCamera *RwCameraCreate(void); +RwCamera *RwCameraClone(RwCamera * camera); +RwCamera *RwCameraSetViewOffset(RwCamera *camera, const RwV2d *offset); +RwCamera *RwCameraSetViewWindow(RwCamera *camera, const RwV2d *viewWindow); +RwCamera *RwCameraSetProjection(RwCamera *camera, RwCameraProjection projection); +RwCamera *RwCameraSetNearClipPlane(RwCamera *camera, RwReal nearClip); +RwCamera *RwCameraSetFarClipPlane(RwCamera *camera, RwReal farClip); +RwInt32 RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB); +RwInt32 RwCameraGetPluginOffset(RwUInt32 pluginID); +RwBool RwCameraValidatePlugins(const RwCamera * camera); +RwFrustumTestResult RwCameraFrustumTestSphere(const RwCamera * camera, const RwSphere * sphere); +const RwV2d *RwCameraGetViewOffset(const RwCamera *camera); +RwCamera *RwCameraSetRaster(RwCamera *camera, RwRaster *raster); +RwRaster *RwCameraGetRaster(const RwCamera *camera); +RwCamera *RwCameraSetZRaster(RwCamera *camera, RwRaster *zRaster); +RwRaster *RwCameraGetZRaster(const RwCamera *camera); +RwReal RwCameraGetNearClipPlane(const RwCamera *camera); +RwReal RwCameraGetFarClipPlane(const RwCamera *camera); +RwCamera *RwCameraSetFogDistance(RwCamera *camera, RwReal fogDistance); +RwReal RwCameraGetFogDistance(const RwCamera *camera); +RwCamera *RwCameraGetCurrentCamera(void); +RwCameraProjection RwCameraGetProjection(const RwCamera *camera); +const RwV2d *RwCameraGetViewWindow(const RwCamera *camera); +RwMatrix *RwCameraGetViewMatrix(RwCamera *camera); +RwCamera *RwCameraSetFrame(RwCamera *camera, RwFrame *frame); +RwFrame *RwCameraGetFrame(const RwCamera *camera); + + +/* + * + * D3D-engine specific stuff + * + */ + +void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate); +RwBool RwD3D8DeviceSupportsDXTTexture(void); diff --git a/src/fakerw/rwplcore.h b/src/fakerw/rwplcore.h new file mode 100644 index 00000000..79c745b6 --- /dev/null +++ b/src/fakerw/rwplcore.h @@ -0,0 +1,498 @@ +#pragma once + +typedef rw::int8 RwInt8; +typedef rw::int16 RwInt16; +typedef rw::int32 RwInt32; +typedef rw::uint8 RwUInt8; +typedef rw::uint16 RwUInt16; +typedef rw::uint32 RwUInt32; +typedef rw::float32 RwReal; + +typedef char RwChar; +typedef RwInt32 RwBool; + +#define __RWUNUSED__ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE !FALSE +#endif + +// used for unicode +#define RWSTRING(x) x + +typedef rw::V2d RwV2d; + +typedef rw::V3d RwV3d; + +typedef rw::Rect RwRect; + +typedef rw::Sphere RwSphere; + +enum RwTextureCoordinateIndex +{ + rwNARWTEXTURECOORDINATEINDEX = 0, + rwTEXTURECOORDINATEINDEX0, + rwTEXTURECOORDINATEINDEX1, + rwTEXTURECOORDINATEINDEX2, + rwTEXTURECOORDINATEINDEX3, + rwTEXTURECOORDINATEINDEX4, + rwTEXTURECOORDINATEINDEX5, + rwTEXTURECOORDINATEINDEX6, + rwTEXTURECOORDINATEINDEX7, +}; + +typedef rw::TexCoords RwTexCoords; + +typedef rw::SurfaceProperties RwSurfaceProperties; + +#define RWRGBALONG(r,g,b,a) \ + ((RwUInt32) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))) + + +#define MAKECHUNKID(vendorID, chunkID) (((vendorID & 0xFFFFFF) << 8) | (chunkID & 0xFF)) + +enum RwCorePluginID +{ + rwID_NAOBJECT = 0x00, + rwID_STRUCT = 0x01, + rwID_STRING = 0x02, + rwID_EXTENSION = 0x03, + rwID_CAMERA = 0x05, + rwID_TEXTURE = 0x06, + rwID_MATERIAL = 0x07, + rwID_MATLIST = 0x08, + rwID_ATOMICSECT = 0x09, + rwID_PLANESECT = 0x0A, + rwID_WORLD = 0x0B, + rwID_SPLINE = 0x0C, + rwID_MATRIX = 0x0D, + rwID_FRAMELIST = 0x0E, + rwID_GEOMETRY = 0x0F, + rwID_CLUMP = 0x10, + rwID_LIGHT = 0x12, + rwID_UNICODESTRING = 0x13, + rwID_ATOMIC = 0x14, + rwID_TEXTURENATIVE = 0x15, + rwID_TEXDICTIONARY = 0x16, + rwID_ANIMDATABASE = 0x17, + rwID_IMAGE = 0x18, + rwID_SKINANIMATION = 0x19, + rwID_GEOMETRYLIST = 0x1A, + rwID_HANIMANIMATION = 0x1B, + rwID_TEAM = 0x1C, + rwID_CROWD = 0x1D, + rwID_DMORPHANIMATION = 0x1E, + rwID_RIGHTTORENDER = 0x1f, + rwID_MTEFFECTNATIVE = 0x20, + rwID_MTEFFECTDICT = 0x21, + rwID_TEAMDICTIONARY = 0x22, + rwID_PITEXDICTIONARY = 0x23, + rwID_TOC = 0x24, + rwID_PRTSTDGLOBALDATA = 0x25, + /* Insert before MAX and increment MAX */ + rwID_COREPLUGINIDMAX = 0x26, +}; + + +/* + *********************************************** + * + * RwObject + * + *********************************************** + */ + +//struct RwObject; +typedef rw::Object RwObject; + +typedef RwObject *(*RwObjectCallBack)(RwObject *object, void *data); + +RwUInt8 RwObjectGetType(const RwObject *obj); + + + +#define rwsprintf sprintf +#define rwvsprintf vsprintf +#define rwstrcpy strcpy +#define rwstrncpy strncpy +#define rwstrcat strcat +#define rwstrncat strncat +#define rwstrrchr strrchr +#define rwstrchr strchr +#define rwstrstr strstr +#define rwstrcmp strcmp +#define rwstricmp stricmp +#define rwstrlen strlen +#define rwstrupr strupr +#define rwstrlwr strlwr +#define rwstrtok strtok +#define rwsscanf sscanf + + +/* + *********************************************** + * + * Memory + * + *********************************************** + */ + +struct RwMemoryFunctions; +/* +{ + void *(*rwmalloc)(size_t size); + void (*rwfree)(void *mem); + void *(*rwrealloc)(void *mem, size_t newSize); + void *(*rwcalloc)(size_t numObj, size_t sizeObj); +}; +*/ + +void *RwMalloc(size_t size); +void RwFree(void *mem); +void *RwRealloc(void *mem, size_t newSize); +void *RwCalloc(size_t numObj, size_t sizeObj); + +/* + *********************************************** + * + * RwStream + * + *********************************************** + */ + +//struct RwStream; +typedef rw::Stream RwStream; + +struct RwMemory +{ + RwUInt8 *start; + RwUInt32 length; +}; + +enum RwStreamType +{ + rwNASTREAM = 0, + rwSTREAMFILE, + rwSTREAMFILENAME, + rwSTREAMMEMORY, + rwSTREAMCUSTOM +}; + +enum RwStreamAccessType +{ + rwNASTREAMACCESS = 0, + rwSTREAMREAD, + rwSTREAMWRITE, + rwSTREAMAPPEND +}; + +RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const void *pData); +RwBool RwStreamClose(RwStream * stream, void *pData); +RwUInt32 RwStreamRead(RwStream * stream, void *buffer, RwUInt32 length); +RwStream *RwStreamWrite(RwStream * stream, const void *buffer, RwUInt32 length); +RwStream *RwStreamSkip(RwStream * stream, RwUInt32 offset); + + +/* + *********************************************** + * + * Plugin Registry + * + *********************************************** + */ + +#define RWPLUGINOFFSET(_type, _base, _offset) \ + ((_type *)((RwUInt8 *)(_base) + (_offset))) + +typedef RwStream *(*RwPluginDataChunkWriteCallBack)(RwStream *stream, RwInt32 binaryLength, const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); +typedef RwStream *(*RwPluginDataChunkReadCallBack)(RwStream *stream, RwInt32 binaryLength, void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); +typedef RwInt32(*RwPluginDataChunkGetSizeCallBack)(const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); +typedef RwBool(*RwPluginDataChunkAlwaysCallBack)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); +typedef RwBool(*RwPluginDataChunkRightsCallBack)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject, RwUInt32 extraData); +typedef void *(*RwPluginObjectConstructor)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); +typedef void *(*RwPluginObjectCopy)(void *dstObject, const void *srcObject, RwInt32 offsetInObject, RwInt32 sizeInObject); +typedef void *(*RwPluginObjectDestructor)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject); + +/* + *********************************************** + * + * RwMatrix + * + *********************************************** + */ + +typedef rw::Matrix RwMatrix; + +enum RwOpCombineType +{ + rwCOMBINEREPLACE = rw::COMBINEREPLACE, + rwCOMBINEPRECONCAT = rw::COMBINEPRECONCAT, + rwCOMBINEPOSTCONCAT = rw::COMBINEPOSTCONCAT +}; + +enum RwMatrixType +{ + rwMATRIXTYPENORMAL = rw::Matrix::TYPENORMAL, + rwMATRIXTYPEORTHOGANAL = rw::Matrix::TYPEORTHOGONAL, + rwMATRIXTYPEORTHONORMAL = rw::Matrix::TYPEORTHONORMAL, + rwMATRIXTYPEMASK = 0x00000003, +}; + +typedef rw::Matrix::Tolerance RwMatrixTolerance; + +RwBool RwMatrixDestroy(RwMatrix *mpMat); +RwMatrix *RwMatrixCreate(void); +void RwMatrixCopy(RwMatrix * dstMatrix, const RwMatrix * srcMatrix); +void RwMatrixSetIdentity(RwMatrix * matrix); +RwMatrix *RwMatrixMultiply(RwMatrix * matrixOut, const RwMatrix * MatrixIn1, const RwMatrix * matrixIn2); +RwMatrix *RwMatrixTransform(RwMatrix * matrix, const RwMatrix * transform, RwOpCombineType combineOp); +RwMatrix *RwMatrixOrthoNormalize(RwMatrix * matrixOut, const RwMatrix * matrixIn); +RwMatrix *RwMatrixInvert(RwMatrix * matrixOut, const RwMatrix * matrixIn); +RwMatrix *RwMatrixScale(RwMatrix * matrix, const RwV3d * scale, RwOpCombineType combineOp); +RwMatrix *RwMatrixTranslate(RwMatrix * matrix, const RwV3d * translation, RwOpCombineType combineOp); +RwMatrix *RwMatrixRotate(RwMatrix * matrix, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp); +RwMatrix *RwMatrixRotateOneMinusCosineSine(RwMatrix * matrix, const RwV3d * unitAxis, RwReal oneMinusCosine, RwReal sine, RwOpCombineType combineOp); +const RwMatrix *RwMatrixQueryRotate(const RwMatrix * matrix, RwV3d * unitAxis, RwReal * angle, RwV3d * center); +RwV3d *RwMatrixGetRight(RwMatrix * matrix); +RwV3d *RwMatrixGetUp(RwMatrix * matrix); +RwV3d *RwMatrixGetAt(RwMatrix * matrix); +RwV3d *RwMatrixGetPos(RwMatrix * matrix); +RwMatrix *RwMatrixUpdate(RwMatrix * matrix); +RwMatrix *RwMatrixOptimize(RwMatrix * matrix, const RwMatrixTolerance *tolerance); + +/* + *********************************************** + * + * RwRGBA + * + *********************************************** + */ + +typedef rw::RGBA RwRGBA; +typedef rw::RGBAf RwRGBAReal; + + +inline void RwRGBAAssign(RwRGBA *target, const RwRGBA *source) { *target = *source; } + + +RwReal RwV3dNormalize(RwV3d * out, const RwV3d * in); +RwReal RwV3dLength(const RwV3d * in); +RwReal RwV2dLength(const RwV2d * in); +RwReal RwV2dNormalize(RwV2d * out, const RwV2d * in); +void RwV2dAssign(RwV2d * out, const RwV2d * ina); +void RwV2dAdd(RwV2d * out, const RwV2d * ina, const RwV2d * inb); +void RwV2dLineNormal(RwV2d * out, const RwV2d * ina, const RwV2d * inb); +void RwV2dSub(RwV2d * out, const RwV2d * ina, const RwV2d * inb); +void RwV2dPerp(RwV2d * out, const RwV2d * in); +void RwV2dScale(RwV2d * out, const RwV2d * in, RwReal scalar); +RwReal RwV2dDotProduct(const RwV2d * ina, const RwV2d * inb); +void RwV3dAssign(RwV3d * out, const RwV3d * ina); +void RwV3dAdd(RwV3d * out, const RwV3d * ina, const RwV3d * inb); +void RwV3dSub(RwV3d * out, const RwV3d * ina, const RwV3d * inb); +void RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar); +void RwV3dIncrementScaled(RwV3d * out, const RwV3d * in, RwReal scalar); +void RwV3dNegate(RwV3d * out, const RwV3d * in); +RwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb); +void RwV3dCrossProduct(RwV3d * out, const RwV3d * ina, const RwV3d * inb); +RwV3d *RwV3dTransformPoints(RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix); +RwV3d *RwV3dTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, RwInt32 numPoints, const RwMatrix * matrix); + + +/* + *********************************************** + * + * Render States + * + *********************************************** + */ + +// not librw because we don't support all of them (yet?) - mapping in wrapper functions +enum RwRenderState +{ + rwRENDERSTATENARENDERSTATE = 0, + rwRENDERSTATETEXTURERASTER, + rwRENDERSTATETEXTUREADDRESS, + rwRENDERSTATETEXTUREADDRESSU, + rwRENDERSTATETEXTUREADDRESSV, + rwRENDERSTATETEXTUREPERSPECTIVE, + rwRENDERSTATEZTESTENABLE, + rwRENDERSTATESHADEMODE, + rwRENDERSTATEZWRITEENABLE, + rwRENDERSTATETEXTUREFILTER, + rwRENDERSTATESRCBLEND, + rwRENDERSTATEDESTBLEND, + rwRENDERSTATEVERTEXALPHAENABLE, + rwRENDERSTATEBORDERCOLOR, + rwRENDERSTATEFOGENABLE, + rwRENDERSTATEFOGCOLOR, + rwRENDERSTATEFOGTYPE, + rwRENDERSTATEFOGDENSITY, + rwRENDERSTATEFOGTABLE, + rwRENDERSTATEALPHAPRIMITIVEBUFFER, + rwRENDERSTATECULLMODE, + rwRENDERSTATESTENCILENABLE, + rwRENDERSTATESTENCILFAIL, + rwRENDERSTATESTENCILZFAIL, + rwRENDERSTATESTENCILPASS, + rwRENDERSTATESTENCILFUNCTION, + rwRENDERSTATESTENCILFUNCTIONREF, + rwRENDERSTATESTENCILFUNCTIONMASK, + rwRENDERSTATESTENCILFUNCTIONWRITEMASK +}; + +// not supported - we only do gouraud +enum RwShadeMode +{ + rwSHADEMODENASHADEMODE = 0, + rwSHADEMODEFLAT, + rwSHADEMODEGOURAUD +}; + +enum RwBlendFunction +{ + rwBLENDNABLEND = 0, + rwBLENDZERO = rw::BLENDZERO, + rwBLENDONE = rw::BLENDONE, + rwBLENDSRCCOLOR = rw::BLENDSRCCOLOR, + rwBLENDINVSRCCOLOR = rw::BLENDINVSRCCOLOR, + rwBLENDSRCALPHA = rw::BLENDSRCALPHA, + rwBLENDINVSRCALPHA = rw::BLENDINVSRCALPHA, + rwBLENDDESTALPHA = rw::BLENDDESTALPHA, + rwBLENDINVDESTALPHA = rw::BLENDINVDESTALPHA, + rwBLENDDESTCOLOR = rw::BLENDDESTCOLOR, + rwBLENDINVDESTCOLOR = rw::BLENDINVDESTCOLOR, + rwBLENDSRCALPHASAT = rw::BLENDSRCALPHASAT +}; + +// unsupported - we only need linear +enum RwFogType +{ + rwFOGTYPENAFOGTYPE = 0, + rwFOGTYPELINEAR, + rwFOGTYPEEXPONENTIAL, + rwFOGTYPEEXPONENTIAL2 +}; + +enum RwTextureFilterMode +{ + rwFILTERNAFILTERMODE = 0, + rwFILTERNEAREST = rw::Texture::NEAREST, + rwFILTERLINEAR = rw::Texture::LINEAR, + rwFILTERMIPNEAREST = rw::Texture::MIPNEAREST, + rwFILTERMIPLINEAR = rw::Texture::MIPLINEAR, + rwFILTERLINEARMIPNEAREST = rw::Texture::LINEARMIPNEAREST, + rwFILTERLINEARMIPLINEAR = rw::Texture::LINEARMIPLINEAR +}; + +enum RwTextureAddressMode +{ + rwTEXTUREADDRESSNATEXTUREADDRESS = 0, + rwTEXTUREADDRESSWRAP = rw::Texture::WRAP, + rwTEXTUREADDRESSMIRROR = rw::Texture::MIRROR, + rwTEXTUREADDRESSCLAMP = rw::Texture::CLAMP, + rwTEXTUREADDRESSBORDER = rw::Texture::BORDER +}; + +enum RwCullMode +{ + rwCULLMODENACULLMODE = 0, + rwCULLMODECULLNONE = rw::CULLNONE, + rwCULLMODECULLBACK = rw::CULLBACK, + rwCULLMODECULLFRONT = rw::CULLFRONT +}; + +enum RwPrimitiveType +{ + rwPRIMTYPENAPRIMTYPE = rw::PRIMTYPENONE, + rwPRIMTYPELINELIST = rw::PRIMTYPELINELIST, + rwPRIMTYPEPOLYLINE = rw::PRIMTYPEPOLYLINE, + rwPRIMTYPETRILIST = rw::PRIMTYPETRILIST, + rwPRIMTYPETRISTRIP = rw::PRIMTYPETRISTRIP, + rwPRIMTYPETRIFAN = rw::PRIMTYPETRIFAN, + rwPRIMTYPEPOINTLIST = rw::PRIMTYPEPOINTLIST +}; + + +RwBool RwRenderStateGet(RwRenderState state, void *value); +RwBool RwRenderStateSet(RwRenderState state, void *value); + + +/* + *********************************************** + * + * Engine + * + *********************************************** + */ + +struct RwEngineOpenParams +{ + void *displayID; +}; + +typedef rw::SubSystemInfo RwSubSystemInfo; + +enum RwVideoModeFlag +{ + rwVIDEOMODEEXCLUSIVE = rw::VIDEOMODEEXCLUSIVE, +/* + rwVIDEOMODEINTERLACE = 0x2, + rwVIDEOMODEFFINTERLACE = 0x4, + rwVIDEOMODEFSAA0 = 0x8, + rwVIDEOMODEFSAA1 = 0x10 +*/ +}; + +typedef rw::VideoMode RwVideoMode; + +#if 0 +struct RwFileFunctions +{ + rwFnFexist rwfexist; /**< Pointer to fexist function */ + rwFnFopen rwfopen; /**< Pointer to fopen function */ + rwFnFclose rwfclose; /**< Pointer to fclose function */ + rwFnFread rwfread; /**< Pointer to fread function */ + rwFnFwrite rwfwrite; /**< Pointer to fwrite function */ + rwFnFgets rwfgets; /**< Pointer to fgets function */ + rwFnFputs rwfputs; /**< Pointer to puts function */ + rwFnFeof rwfeof; /**< Pointer to feof function */ + rwFnFseek rwfseek; /**< Pointer to fseek function */ + rwFnFflush rwfflush; /**< Pointer to fflush function */ + rwFnFtell rwftell; /**< Pointer to ftell function */ +}; +RwFileFunctions *RwOsGetFileInterface(void); +#endif + +RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize); +RwInt32 RwEngineRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor initCB, RwPluginObjectDestructor termCB); +RwInt32 RwEngineGetPluginOffset(RwUInt32 pluginID); +RwBool RwEngineOpen(RwEngineOpenParams *initParams); +RwBool RwEngineStart(void); +RwBool RwEngineStop(void); +RwBool RwEngineClose(void); +RwBool RwEngineTerm(void); +RwInt32 RwEngineGetNumSubSystems(void); +RwSubSystemInfo *RwEngineGetSubSystemInfo(RwSubSystemInfo *subSystemInfo, RwInt32 subSystemIndex); +RwInt32 RwEngineGetCurrentSubSystem(void); +RwBool RwEngineSetSubSystem(RwInt32 subSystemIndex); +RwInt32 RwEngineGetNumVideoModes(void); +RwVideoMode *RwEngineGetVideoModeInfo(RwVideoMode *modeinfo, RwInt32 modeIndex); +RwInt32 RwEngineGetCurrentVideoMode(void); +RwBool RwEngineSetVideoMode(RwInt32 modeIndex); +RwInt32 RwEngineGetTextureMemorySize(void); +RwInt32 RwEngineGetMaxTextureSize(void); + + +/* + *********************************************** + * + * Binary stream + * + *********************************************** + */ + +RwBool RwStreamFindChunk(RwStream *stream, RwUInt32 type, RwUInt32 *lengthOut, RwUInt32 *versionOut); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index cee2b323..80d99e29 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2244,7 +2244,7 @@ CPed::BuildPedLists(void) if (nThreatReactionRangeMultiplier * 30.0f > dist) { gapTempPedList[gnNumTempPedList] = ped; gnNumTempPedList++; - assert(gnNumTempPedList < ARRAYSIZE(gapTempPedList)); + assert(gnNumTempPedList < ARRAY_SIZE(gapTempPedList)); } } } diff --git a/src/render/Console.cpp b/src/render/Console.cpp index d4940955..545122b0 100644 --- a/src/render/Console.cpp +++ b/src/render/Console.cpp @@ -1,4 +1,5 @@ #include "common.h" +#include #include "patcher.h" #include "Console.h" #include "Font.h" diff --git a/src/render/Shadows.h b/src/render/Shadows.h index fb41ebbc..ced9f11b 100644 --- a/src/render/Shadows.h +++ b/src/render/Shadows.h @@ -6,7 +6,6 @@ #define MAX_PERMAMENTSHADOWS 48 -struct RwTexture; class CEntity; enum eShadowType diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index b440e77c..7aa2778f 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -126,7 +126,7 @@ void CWeather::Update(void) if (ForcedWeatherType >= 0) NewWeatherType = ForcedWeatherType; else { - WeatherTypeInList = (WeatherTypeInList + 1) % ARRAYSIZE(WeatherTypesList); + WeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList); NewWeatherType = WeatherTypesList[WeatherTypeInList]; #ifdef FIX_BUGS } diff --git a/src/rw/ClumpRead.cpp b/src/rw/ClumpRead.cpp index c9f027e7..0bf62f32 100644 --- a/src/rw/ClumpRead.cpp +++ b/src/rw/ClumpRead.cpp @@ -153,7 +153,7 @@ RpClumpGtaStreamRead1(RwStream *stream) if(!RwStreamFindChunk(stream, rwID_FRAMELIST, nil, &version)) return false; - if(_rwFrameListStreamRead(stream, &gFrameList) == nil) + if(rwFrameListStreamRead(stream, &gFrameList) == nil) return false; if(!RwStreamFindChunk(stream, rwID_GEOMETRYLIST, nil, &version)){ @@ -164,7 +164,7 @@ RpClumpGtaStreamRead1(RwStream *stream) rwFrameListDeinitialize(&gFrameList); return false; } - streamPosition = stream->Type.memory.position; + streamPosition = STREAMPOS(stream); return true; } @@ -180,7 +180,7 @@ RpClumpGtaStreamRead2(RwStream *stream) if(clump == nil) return nil; - RwStreamSkip(stream, streamPosition - stream->Type.memory.position); + RwStreamSkip(stream, streamPosition - STREAMPOS(stream)); if(GeometryListStreamRead2(stream, &gGeomList) == nil){ GeometryListDeinitialize(&gGeomList); diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 44ca3a0a..cf1a6f2b 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -90,9 +90,13 @@ DefinedState(void) RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR); RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); +#ifdef LIBRW + #pragma message (" TODO: alphatest func") +#else // D3D stuff RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); RwD3D8SetRenderState(D3DRS_ALPHAREF, 2); +#endif } RwFrame* diff --git a/src/rw/RwMatFX.cpp b/src/rw/RwMatFX.cpp index 3af6fabe..c4fe0b0b 100644 --- a/src/rw/RwMatFX.cpp +++ b/src/rw/RwMatFX.cpp @@ -1,3 +1,5 @@ +#ifndef LIBRW + #define WITHD3D #include "common.h" #include "patcher.h" @@ -224,3 +226,5 @@ STARTPATCHES ENDPATCHES #endif + +#endif diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 50b99d47..8ada080d 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -25,6 +25,12 @@ float &texLoadTime = *(float*)0x8F1B50; int32 &texNumLoaded = *(int32*)0x8F252C; +#ifdef LIBRW +#define READNATIVE(stream, tex, size) rwNativeTextureHackRead(stream, tex, size) +#else +#define READNATIVE(stream, tex, size) RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, tex, size)) +#endif + RwTexture* RwTextureGtaStreamRead(RwStream *stream) { @@ -36,7 +42,7 @@ RwTextureGtaStreamRead(RwStream *stream) float preloadTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond(); - if(!RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, &tex, size))) + if(!READNATIVE(stream, &tex, size)) return nil; if (gGameState == GS_INIT_PLAYING_GAME) { @@ -121,7 +127,7 @@ RwTexDictionaryGtaStreamRead1(RwStream *stream) } numberTextures = numTextures; - streamPosition = stream->Type.memory.position; + streamPosition = STREAMPOS(stream); return texDict; } @@ -131,7 +137,7 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict) { RwTexture *tex; - RwStreamSkip(stream, streamPosition - stream->Type.memory.position); + RwStreamSkip(stream, streamPosition - STREAMPOS(stream)); while(numberTextures--){ tex = RwTextureGtaStreamRead(stream); @@ -251,6 +257,12 @@ DealWithTxdWriteError(uint32 num, uint32 count, const char *text) RsGlobal.quit = true; } +#ifdef LIBRW +#define STREAMTELL(str) str->tell() +#else +#define STREAMTELL(str) filesys->rwftell((str)->Type.file.fpFile) +#endif + bool CreateTxdImageForVideoCard() { @@ -260,7 +272,9 @@ CreateTxdImageForVideoCard() CStreaming::FlushRequestList(); +#ifndef LIBRW RwFileFunctions *filesys = RwOsGetFileInterface(); +#endif RwStream *img = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, "models\\txd.img"); if (img == nil) { @@ -287,7 +301,8 @@ CreateTxdImageForVideoCard() sprintf(filename, "%s.txd", CTxdStore::GetTxdName(i)); if (CTxdStore::GetSlot(i)->texDict) { - int32 pos = filesys->rwftell(img->Type.file.fpFile); + + int32 pos = STREAMTELL(img); if (RwTexDictionaryStreamWrite(CTxdStore::GetSlot(i)->texDict, img) == nil) { DealWithTxdWriteError(i, TXDSTORESIZE, "CVT_ERR"); @@ -298,7 +313,7 @@ CreateTxdImageForVideoCard() return false; } - int32 size = filesys->rwftell(img->Type.file.fpFile) - pos; + int32 size = STREAMTELL(img) - pos; int32 num = size % CDSTREAM_SECTOR_SIZE; size /= CDSTREAM_SECTOR_SIZE; diff --git a/src/rw/rw.cpp b/src/rw/rw.cpp index 3875f2a1..196cf189 100644 --- a/src/rw/rw.cpp +++ b/src/rw/rw.cpp @@ -1,3 +1,4 @@ +#ifndef LIBRW #include "common.h" #include "patcher.h" #include "rwcore.h" @@ -836,4 +837,5 @@ InjectHook(0x5DF040, &RxNodeDefinitionGetLight, PATCH_JUMP); InjectHook(0x5DF560, &RxNodeDefinitionGetPostLight, PATCH_JUMP); InjectHook(0x5DFC60, &RxD3D8AllInOneSetRenderCallBack, PATCH_JUMP); ENDPATCHES +#endif #endif \ No newline at end of file From d7eee5c1307d80b64771e15458e0b1fd70898706 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 15 Apr 2020 15:26:55 +0200 Subject: [PATCH 014/123] fixed clouds and sprites --- src/render/Clouds.cpp | 2 +- src/render/Sprite.cpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 39866294..7debe3d3 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -233,7 +233,7 @@ CClouds::Render(void) szx*55.0f, szy*55.0f, tr, tg, tb, br, bg, bb, 0.0f, -1.0f, 1.0f/screenpos.z, - IndividualRotation/65336.0f * 2*3.14f + ms_cameraRoll, + (uint16)IndividualRotation/65336.0f * 6.28f + ms_cameraRoll, fluffyalpha); bCloudOnScreen[i] = true; }else diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 8ac2315f..82754121 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -137,8 +137,8 @@ CSprite::RenderOneXLUSprite(float x, float y, float z, float w, float h, uint8 r void CSprite::RenderOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a) { - float c = Cos(DEGTORAD(rotation)); - float s = Sin(DEGTORAD(rotation)); + float c = Cos(rotation); + float s = Sin(rotation); float xs[4]; float ys[4]; @@ -315,8 +315,8 @@ void CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a) { m_bFlushSpriteBufferSwitchZTest = 0; - float c = Cos(DEGTORAD(rotation)); - float s = Sin(DEGTORAD(rotation)); + float c = Cos(rotation); + float s = Sin(rotation); float xs[4]; float ys[4]; @@ -367,8 +367,8 @@ void CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, float w, float h, uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2, float cx, float cy, float recipz, float rotation, uint8 a) { m_bFlushSpriteBufferSwitchZTest = 0; - float c = Cos(DEGTORAD(rotation)); - float s = Sin(DEGTORAD(rotation)); + float c = Cos(rotation); + float s = Sin(rotation); float xs[4]; float ys[4]; @@ -398,11 +398,11 @@ CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, f // Colour factors, cx/y is the direction in which colours change from rgb1 to rgb2 cf[0] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f; cf[0] = clamp(cf[0], 0.0f, 1.0f); - cf[1] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f; + cf[1] = (cx*(-c+s) + cy*( c+s))*0.5f + 0.5f; cf[1] = clamp(cf[1], 0.0f, 1.0f); - cf[2] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f; + cf[2] = (cx*( c+s) + cy*( c-s))*0.5f + 0.5f; cf[2] = clamp(cf[2], 0.0f, 1.0f); - cf[3] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f; + cf[3] = (cx*( c-s) + cy*(-c-s))*0.5f + 0.5f; cf[3] = clamp(cf[3], 0.0f, 1.0f); float screenz = m_f2DNearScreenZ + From eccc4a3a5b45253ad8a6bdacbfccb8a15299d334 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 15 Apr 2020 16:17:18 +0200 Subject: [PATCH 015/123] fixed bug and weirdness in CHeli --- src/vehicles/Heli.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 3dc1deeb..c4cdcb02 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -78,6 +78,9 @@ CHeli::CHeli(int32 id, uint8 CreatedBy) m_bTestRight = true; m_fTargetOffset = 0.0f; m_fSearchLightX = m_fSearchLightY = 0.0f; + + // BUG: not in game but gets initialized to CDCDCDCD in debug + m_nLastShotTime = 0; } void @@ -590,7 +593,12 @@ CHeli::PreRender(void) break; } RwRGBA col = { r, g, b, 32 }; +#ifdef FIX_BUGS + pos.z = m_fHeliDustZ[frm]; +#else + // What the hell is the point of this? pos.z = m_fHeliDustZ[(i - (i&3))/4]; // advance every 4 iterations, why not just /4? +#endif if(pos.z > -200.0f && GetPosition().z - pos.z < 20.0f) CParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, 0.0f, col); i++; From 1d8484ed7dca21681d2ad08ba605d4d197d2b99f Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 15 Apr 2020 17:36:38 +0300 Subject: [PATCH 016/123] fix --- src/weapons/BulletInfo.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp index cb9e0b2d..177a99d1 100644 --- a/src/weapons/BulletInfo.cpp +++ b/src/weapons/BulletInfo.cpp @@ -70,6 +70,7 @@ bool CBulletInfo::AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosit gaBulletInfo[i].m_vecSpeed = vecSpeed; gaBulletInfo[i].m_fTimer = CTimer::GetTimeInMilliseconds() + BULLET_LIFETIME; gaBulletInfo[i].m_bInUse = true; + return true; } void CBulletInfo::Update(void) @@ -138,7 +139,7 @@ void CBulletInfo::Update(void) else if (pHitEntity->IsVehicle()) { CVehicle* pVehicle = (CVehicle*)pHitEntity; pVehicle->InflictDamage(pBullet->m_pSource, pBullet->m_eWeaponType, pBullet->m_nDamage); - if (pBullet->m_eWeaponType == WEAPONTYPE_FLAMETHROWER) // how? + if (pBullet->m_eWeaponType == WEAPONTYPE_FLAMETHROWER) // huh? gFireManager.StartFire(pVehicle, pBullet->m_pSource, 0.8f, true); else { for (int j = 0; j < NUM_VEHICLE_SPARKS; j++) @@ -266,3 +267,10 @@ bool CBulletInfo::TestForSniperBullet(float x1, float x2, float y1, float y2, fl return minP <= maxP; #endif } + +STARTPATCHES + InjectHook(0x558220, &CBulletInfo::Initialise, PATCH_JUMP); + InjectHook(0x558450, &CBulletInfo::Shutdown, PATCH_JUMP); + InjectHook(0x558470, &CBulletInfo::AddBullet, PATCH_JUMP); + InjectHook(0x558550, &CBulletInfo::Update, PATCH_JUMP); +ENDPATCHES \ No newline at end of file From 4da1879975ef28cb7f406166d62d154d03ef47d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 15 Apr 2020 19:19:45 +0300 Subject: [PATCH 017/123] Many fixes and cleanup --- src/control/Garages.cpp | 10 ++- src/control/Script.cpp | 2 +- src/core/Collision.cpp | 5 +- src/core/Collision.h | 11 +++- src/core/Frontend.cpp | 127 ++++++++++++++++++------------------ src/core/Frontend.h | 8 ++- src/core/World.cpp | 4 +- src/core/World.h | 4 +- src/core/main.cpp | 5 +- src/entities/Physical.cpp | 6 +- src/peds/Ped.cpp | 17 ++--- src/peds/Ped.h | 10 +-- src/peds/Population.cpp | 58 ++++++++-------- src/render/Renderer.cpp | 17 ++--- src/render/Renderer.h | 16 ++--- src/vehicles/Automobile.cpp | 7 +- src/vehicles/Vehicle.cpp | 12 ++-- src/vehicles/Vehicle.h | 12 ++-- 18 files changed, 174 insertions(+), 157 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index d971d453..9bd9a577 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -307,13 +307,13 @@ void CGarage::Update() CGarages::bCamShouldBeOutisde = true; } if (pVehicle) { - if (IsEntityEntirelyOutside(pVehicle, 0.0f)) + if (!IsEntityEntirelyOutside(pVehicle, 0.0f)) TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = this; if (pVehicle->GetModelIndex() == MI_MRWHOOP) { if (pVehicle->IsWithinArea( m_fX1 - DISTANCE_FOR_MRWHOOP_HACK, - m_fX2 + DISTANCE_FOR_MRWHOOP_HACK, - m_fY1 - DISTANCE_FOR_MRWHOOP_HACK, + m_fY1 + DISTANCE_FOR_MRWHOOP_HACK, + m_fX2 - DISTANCE_FOR_MRWHOOP_HACK, m_fY2 + DISTANCE_FOR_MRWHOOP_HACK)) { TheCamera.pToGarageWeAreIn = this; CGarages::bCamShouldBeOutisde = true; @@ -2313,6 +2313,10 @@ void CGarages::Load(uint8* buf, uint32 size) #ifdef FIX_GARAGE_SIZE VALIDATESAVEBUF(size); #endif + + MessageEndTime = 0; + bCamShouldBeOutisde = false; + MessageStartTime = 0; } bool diff --git a/src/control/Script.cpp b/src/control/Script.cpp index ff89f0fc..7a890656 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -11358,7 +11358,7 @@ VALIDATESAVEBUF(size) void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity) { - static CColPoint aTempColPoints[32]; + static CColPoint aTempColPoints[MAX_COLLISION_POINTS]; int16 entities = 0; CEntity* aEntities[16]; CWorld::FindObjectsKindaColliding(pos, pEntity->GetBoundRadius(), false, &entities, 16, aEntities, false, true, true, false, false); diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index c884f751..85145e86 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -31,8 +31,8 @@ enum Direction DIR_Z_NEG, }; -eLevelName &CCollision::ms_collisionInMemory = *(eLevelName*)0x8F6250; -CLinkList &CCollision::ms_colModelCache = *(CLinkList*)0x95CB58; +eLevelName CCollision::ms_collisionInMemory; +CLinkList CCollision::ms_colModelCache; void CCollision::Init(void) @@ -1355,6 +1355,7 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA, modelB.triangles[aTriangleIndicesB[j]], modelB.trianglePlanes[aTriangleIndicesB[j]], spherepoints[numCollisions], coldist); + if(hasCollided) numCollisions++; } diff --git a/src/core/Collision.h b/src/core/Collision.h index 1cbd1690..bdf51eb8 100644 --- a/src/core/Collision.h +++ b/src/core/Collision.h @@ -3,6 +3,13 @@ #include "templates.h" #include "Game.h" // for eLevelName +// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32. +#ifdef FIX_BUGS +#define MAX_COLLISION_POINTS 64 +#else +#define MAX_COLLISION_POINTS 32 +#endif + struct CColSphere { CVector center; @@ -110,8 +117,8 @@ struct CColModel class CCollision { public: - static eLevelName &ms_collisionInMemory; - static CLinkList &ms_colModelCache; + static eLevelName ms_collisionInMemory; + static CLinkList ms_colModelCache; static void Init(void); static void Shutdown(void); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 48683abc..166ecb35 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -82,34 +82,34 @@ int curBottomBarOption = -1; int hoveredBottomBarOption = -1; #endif -int32 CMenuManager::OS_Language = LANG_ENGLISH; // *(int32*)0x5F2F78; -int8 CMenuManager::m_PrefsUseVibration; // = *(int8*)0x95CD92; -int8 CMenuManager::m_DisplayControllerOnFoot; // = *(int8*)0x95CD8D; -int8 CMenuManager::m_PrefsVsync = 1; // *(int8*)0x5F2E58; -int8 CMenuManager::m_PrefsVsyncDisp = 1; // *(int8*)0x5F2E5C; -int8 CMenuManager::m_PrefsFrameLimiter = 1; // *(int8*)0x5F2E60; -int8 CMenuManager::m_PrefsShowSubtitles = 1; // *(int8*)0x5F2E54; -int8 CMenuManager::m_PrefsSpeakers; // = *(int8*)0x95CD7E; -int32 CMenuManager::m_ControlMethod; // = *(int32*)0x8F5F7C; -int8 CMenuManager::m_PrefsDMA = 1; // *(int8*)0x5F2F74; -int32 CMenuManager::m_PrefsLanguage; // = *(int32*)0x941238; +int32 CMenuManager::OS_Language = LANG_ENGLISH; +int8 CMenuManager::m_PrefsUseVibration; +int8 CMenuManager::m_DisplayControllerOnFoot; +int8 CMenuManager::m_PrefsVsync = 1; +int8 CMenuManager::m_PrefsVsyncDisp = 1; +int8 CMenuManager::m_PrefsFrameLimiter = 1; +int8 CMenuManager::m_PrefsShowSubtitles = 1; +int8 CMenuManager::m_PrefsSpeakers; +int32 CMenuManager::m_ControlMethod; +int8 CMenuManager::m_PrefsDMA = 1; +int32 CMenuManager::m_PrefsLanguage; uint8 CMenuManager::m_PrefsStereoMono; // *(bool*)0x95CDB5; // unused except restore settings -bool CMenuManager::m_PrefsAllowNastyGame = true; // *(bool*)0x5F2E64; -bool CMenuManager::m_bStartUpFrontEndRequested; // = *(bool*)0x95CCF4; -bool CMenuManager::m_bShutDownFrontEndRequested; // = *(bool*)0x95CD6A; +bool CMenuManager::m_PrefsAllowNastyGame = true; +bool CMenuManager::m_bStartUpFrontEndRequested; +bool CMenuManager::m_bShutDownFrontEndRequested; -int8 CMenuManager::m_PrefsUseWideScreen; // = *(int8*)0x95CD23; -int8 CMenuManager::m_PrefsRadioStation; // = *(int8*)0x95CDA4; -int32 CMenuManager::m_PrefsBrightness = 256; // = *(int32*)0x5F2E50; -float CMenuManager::m_PrefsLOD; // = *(float*)0x8F42C4; -int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; // = *(int8*)0x628CFC; -int32 CMenuManager::m_PrefsMusicVolume = 102; // = *(int32*)0x5F2E4C; -int32 CMenuManager::m_PrefsSfxVolume = 102; // = *(int32*)0x5F2E48; +int8 CMenuManager::m_PrefsUseWideScreen; +int8 CMenuManager::m_PrefsRadioStation; +int32 CMenuManager::m_PrefsBrightness = 256; +float CMenuManager::m_PrefsLOD = CRenderer::ms_lodDistScale; +int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; +int32 CMenuManager::m_PrefsMusicVolume = 102; +int32 CMenuManager::m_PrefsSfxVolume = 102; -char CMenuManager::m_PrefsSkinFile[256] = "$$\"\""; // = (char*)0x5F2E74; +char CMenuManager::m_PrefsSkinFile[256] = "$$\"\""; -int32 CMenuManager::m_KeyPressedCode = -1; // = *(int32*)0x5F2E70; +int32 CMenuManager::m_KeyPressedCode = -1; // Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway) #ifdef PS2_LIKE_MENU @@ -119,29 +119,26 @@ const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color #endif const float menuXYpadding = MENUACTION_POS_Y; // *(float*)0x5F355C; // not original name -float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; //*(float*)0x5F2E40; -float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; //*(float*)0x5F2E44; +float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; +float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; bool holdingScrollBar; // *(bool*)0x628D59; // not original name -int32 CMenuManager::m_SelectedMap; // *(int32*)0x8E2880; -int32 CMenuManager::m_SelectedGameType; // *(int32*)0x942F88; +int32 CMenuManager::m_SelectedMap; +int32 CMenuManager::m_SelectedGameType; // Used in a hidden menu uint8 CMenuManager::m_PrefsPlayerRed = 255; uint8 CMenuManager::m_PrefsPlayerGreen = 128; uint8 CMenuManager::m_PrefsPlayerBlue; // why?? -CMenuManager FrontEndMenuManager; // = *(CMenuManager*)0x8F59D8; +CMenuManager FrontEndMenuManager; -// Move this somewhere else. -float CRenderer::ms_lodDistScale = 1.2f; // *(float*)0x5F726C; - -uint32 TimeToStopPadShaking; // = *(uint32*)0x628CF8; -char *pEditString; // = *(char**)0x628D00; -int32 *pControlEdit; // = *(int32**)0x628D08; -bool DisplayComboButtonErrMsg; // = *(bool*)0x628D14; -int32 MouseButtonJustClicked; // = *(int32*)0x628D0C; -int32 JoyButtonJustClicked; // = *(int32*)0x628D10; +uint32 TimeToStopPadShaking; +char *pEditString; +int32 *pControlEdit; +bool DisplayComboButtonErrMsg; +int32 MouseButtonJustClicked; +int32 JoyButtonJustClicked; //int32 *pControlTemp = 0; #ifndef MASTER @@ -283,6 +280,12 @@ ScaleAndCenterX(float x) } while(0) #endif +#define PREPARE_MENU_HEADER \ + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \ + CFont::SetRightJustifyOn(); \ + CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \ + CFont::SetFontStyle(FONT_HEADING); + #define ProcessSlider(value, increaseAction, decreaseAction, hoverStartX, hoverEndX) \ do { \ lastActiveBarX = DisplaySlider(SCREEN_STRETCH_FROM_RIGHT(MENUSLIDER_X + columnWidth), MENU_Y(bitAboveNextItemY), MENU_Y(smallestSliderBar), MENU_Y(usableLineHeight), MENU_X(MENUSLIDER_UNK), value); \ @@ -447,8 +450,8 @@ CMenuManager::CheckCodesForControls(int typeOfControl) if (typeOfControl == KEYBOARD) { if (*pControlEdit == rsESC) { escPressed = true; - } else if (*pControlEdit > rsF3 && *pControlEdit != rsF9 && *pControlEdit != rsLWIN && - *pControlEdit != rsRWIN && *pControlEdit != rsRALT) { + } else if (*pControlEdit != rsF1 && *pControlEdit != rsF2 && *pControlEdit != rsF3 && *pControlEdit != rsF9 && + *pControlEdit != rsLWIN && *pControlEdit != rsRWIN && *pControlEdit != rsRALT) { typeToSave = KEYBOARD; if (ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD) != rsNULL && *pControlEdit != ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD)) { @@ -465,7 +468,10 @@ CMenuManager::CheckCodesForControls(int typeOfControl) DisplayComboButtonErrMsg = true; } - ControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave); +#ifdef FIX_BUGS + if(!escPressed && !invalidKey) +#endif + ControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave); if (!DisplayComboButtonErrMsg && !escPressed && !invalidKey) { if (typeOfControl == KEYBOARD) { ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, KEYBOARD); @@ -670,6 +676,17 @@ CMenuManager::Draw() CFont::SetCentreOff(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); +#ifdef GTA3_1_1_PATCH + CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetRightJustifyOn(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::SetRightJustifyWrap(0.0f); + strcpy(gString, "V1.1"); + AsciiToUnicode(gString, gUString); + CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); +#endif CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); @@ -696,17 +713,9 @@ CMenuManager::Draw() #endif if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { - CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); -#ifdef PS2_LIKE_MENU - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(1.3f)); - CFont::PrintString(MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(75.0f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); -#else - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); + PREPARE_MENU_HEADER CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); -#endif + // Weird place to put that. nextYToUse += 24.0f + 10.0f; } @@ -1735,11 +1744,8 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); - // Page header - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetRightJustifyOn(); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); - CFont::SetFontStyle(FONT_HEADING); + PREPARE_MENU_HEADER + switch (m_ControlMethod) { case CONTROL_STANDARD: CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), @@ -2417,10 +2423,8 @@ CMenuManager::DrawPlayerSetupScreen() CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); - CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); + PREPARE_MENU_HEADER + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); // lstrcpy's changed with strcpy @@ -3314,10 +3318,7 @@ CMenuManager::PrintStats() // ::Draw already does that. /* - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); + PREPARE_MENU_HEADER CFont::PrintString(MENU_X_RIGHT_ALIGNED(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); */ CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 9064cf4e..8fe61a36 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -2,10 +2,16 @@ #include "Sprite2d.h" +#ifdef PS2_LIKE_MENU +#define MENUHEADER_POS_X 50.0f +#define MENUHEADER_POS_Y 75.0f +#define MENUHEADER_HEIGHT 1.3f +#else #define MENUHEADER_POS_X 35.0f #define MENUHEADER_POS_Y 93.0f -#define MENUHEADER_WIDTH 0.84f #define MENUHEADER_HEIGHT 1.6f +#endif +#define MENUHEADER_WIDTH 0.84f #define MENU_X_MARGIN 40.0f #define MENUACTION_POS_Y 60.0f diff --git a/src/core/World.cpp b/src/core/World.cpp index d64569b3..289be256 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -21,7 +21,7 @@ #include "Population.h" #include "Fire.h" -CColPoint *gaTempSphereColPoints = (CColPoint*)0x6E64C0; // [32] +CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60; CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C; @@ -29,7 +29,7 @@ CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x6656 uint16 &CWorld::ms_nCurrentScanCode = *(uint16*)0x95CC64; uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61; -CPlayerInfo (&CWorld::Players)[NUMPLAYERS] = *(CPlayerInfo (*)[NUMPLAYERS])*(uintptr*)0x9412F0; +CPlayerInfo CWorld::Players[NUMPLAYERS]; bool &CWorld::bNoMoreCollisionTorque = *(bool*)0x95CDCC; CEntity *&CWorld::pIgnoreEntity = *(CEntity**)0x8F6494; bool &CWorld::bIncludeDeadPeds = *(bool*)0x95CD8F; diff --git a/src/core/World.h b/src/core/World.h index 07e7889f..62fdc3b3 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -61,7 +61,7 @@ class CWorld public: static uint8 &PlayerInFocus; - static CPlayerInfo (&Players)[NUMPLAYERS]; + static CPlayerInfo Players[NUMPLAYERS]; static CEntity *&pIgnoreEntity; static bool &bIncludeDeadPeds; static bool &bNoMoreCollisionTorque; @@ -144,7 +144,7 @@ public: static void TriggerExplosion(const CVector &, float, float, CEntity*, bool); }; -extern CColPoint *gaTempSphereColPoints; +extern CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; class CPlayerPed; class CVehicle; diff --git a/src/core/main.cpp b/src/core/main.cpp index f09c2e0a..2d452f9c 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -690,14 +690,14 @@ DisplayGameDebugText() CFont::SetPropOn(); CFont::SetBackgroundOff(); CFont::SetFontStyle(FONT_BANK); - CFont::SetScale(SCREEN_STRETCH_X(0.5f), SCREEN_STRETCH_Y(0.5f)); + CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.5f)); CFont::SetCentreOff(); CFont::SetRightJustifyOff(); CFont::SetWrapx(SCREEN_WIDTH); CFont::SetJustifyOff(); CFont::SetBackGroundOnlyTextOff(); CFont::SetColor(CRGBA(255, 108, 0, 255)); - CFont::PrintString(10.0f, 10.0f, ver); + CFont::PrintString(SCREEN_SCALE_X(10.0f), SCREEN_SCALE_Y(10.0f), ver); FrameSamples++; FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f); @@ -748,6 +748,7 @@ DisplayGameDebugText() AsciiToUnicode(str, ustr); + // Let's not scale those numbers, they look better that way :eyes: CFont::SetPropOff(); CFont::SetBackgroundOff(); CFont::SetScale(0.7f, 1.5f); diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 9fc77a8c..72d6844d 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1037,7 +1037,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) int numCollisions; int mostColliding; - CColPoint colpoints[32]; + CColPoint colpoints[MAX_COLLISION_POINTS]; CVector shift = { 0.0f, 0.0f, 0.0f }; bool doShift = false; CEntity *boat = nil; @@ -1187,7 +1187,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) bool CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists) { - static CColPoint aColPoints[32]; + static CColPoint aColPoints[MAX_COLLISION_POINTS]; float radius; CVector center; int listtype; @@ -1349,7 +1349,7 @@ collision: bool CPhysical::ProcessCollisionSectorList(CPtrList *lists) { - static CColPoint aColPoints[32]; + static CColPoint aColPoints[MAX_COLLISION_POINTS]; float radius; CVector center; CPtrList *list; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index cee2b323..d6077ed8 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -62,7 +62,7 @@ CPed *gapTempPedList[50]; uint16 gnNumTempPedList; -CColPoint &aTempPedColPts = *(CColPoint*)0x62DB14; +CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; // Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL) PedAudioData CommentWaitTime[39] = { @@ -106,8 +106,6 @@ PedAudioData CommentWaitTime[39] = { {1000, 1000, 1000, 1000}, {1000, 1000, 5000, 5000}, }; -// *(CPedAudioData(*)[39]) * (uintptr*)0x5F94C4; - uint16 nPlayerInComboMove; RpClump *flyingClumpTemp; @@ -139,10 +137,9 @@ FightMove tFightMoves[NUM_FIGHTMOVES] = { {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, }; -// *(FightMove(*)[NUM_FIGHTMOVES])* (uintptr*)0x5F9844; -uint16 &CPed::nThreatReactionRangeMultiplier = *(uint16*)0x5F8C98; -uint16 &CPed::nEnterCarRangeMultiplier = *(uint16*)0x5F8C94; +uint16 CPed::nThreatReactionRangeMultiplier = 1; +uint16 CPed::nEnterCarRangeMultiplier = 1; CVector vecPedCarDoorAnimOffset; CVector vecPedCarDoorLoAnimOffset; @@ -151,9 +148,9 @@ CVector vecPedQuickDraggedOutCarAnimOffset; CVector vecPedDraggedOutCarAnimOffset; CVector vecPedTrainDoorAnimOffset; -bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; -bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; -bool &CPed::bPedCheat3 = *(bool*)0x95CD59; +bool CPed::bNastyLimbsCheat; +bool CPed::bPedCheat2; +bool CPed::bPedCheat3; CVector2D CPed::ms_vec2DFleePosition; void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); } @@ -4143,7 +4140,7 @@ CPed::SetGetUp(void) && ((CTimer::GetFrameCounter() + m_randomSeed % 256 + 5) % 8 || CCollision::ProcessColModels(GetMatrix(), *CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(), collidingVeh->GetMatrix(), *CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(), - &aTempPedColPts, nil, nil) > 0)) { + aTempPedColPts, nil, nil) > 0)) { bGetUpAnimStarted = false; if (IsPlayer()) diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 2edd5d68..321d5bff 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -823,14 +823,14 @@ public: } // set by 0482:set_threat_reaction_range_multiplier opcode - static uint16 &nThreatReactionRangeMultiplier; + static uint16 nThreatReactionRangeMultiplier; // set by 0481:set_enter_car_range_multiplier opcode - static uint16 &nEnterCarRangeMultiplier; + static uint16 nEnterCarRangeMultiplier; - static bool &bNastyLimbsCheat; - static bool &bPedCheat2; - static bool &bPedCheat3; + static bool bNastyLimbsCheat; + static bool bPedCheat2; + static bool bPedCheat3; static CVector2D ms_vec2DFleePosition; #ifdef TOGGLEABLE_BETA_FEATURES diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 6959487f..e26e2eaf 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -47,36 +47,36 @@ const RegenerationPoint aSafeZones[] = { CVector(-321.0f, -1043.0f, -13.2f), CVector(-328.0f, -1045.0f, -13.2f), CVector(-398.0f, -1044.0f, -13.5f), CVector(-390.0f, -1040.5f, -13.5f) }, { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 425.0f, 280.0f, 471.0f, 447.0f, 20.0f, 5.0f, CVector(-292.0f, -457.0f, -11.6f), CVector(-310.0f, -461.0f, -11.6f), CVector(-413.0f, -461.0f, -11.5f), CVector(-399.0f, -457.0f, -11.3f) } -}; // *(RegenerationPoint(*)[8]) * (uintptr*)0x5FA578; +}; -PedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS]; // = *(PedGroup(*)[NUMPEDGROUPS]) * (uintptr*)0x6E9248; -bool CPopulation::ms_bGivePedsWeapons; // = *(bool*)0x95CCF6; -int32 CPopulation::m_AllRandomPedsThisType = -1; // = *(int32*)0x5FA570; -float CPopulation::PedDensityMultiplier = 1.0f; // = *(float*)0x5FA56C; -uint32 CPopulation::ms_nTotalMissionPeds; // = *(uint32*)0x8F5F70; -int32 CPopulation::MaxNumberOfPedsInUse = 25; // *(int32*)0x5FA574; -uint32 CPopulation::ms_nNumCivMale; // = *(uint32*)0x8F2548; -uint32 CPopulation::ms_nNumCivFemale; // = *(uint32*)0x8F5F44; -uint32 CPopulation::ms_nNumCop; // = *(uint32*)0x885AFC; -bool CPopulation::bZoneChangeHasHappened; // = *(bool*)0x95CD79; -uint32 CPopulation::ms_nNumEmergency; // = *(uint32*)0x94071C; -int8 CPopulation::m_CountDownToPedsAtStart; // = *(int8*)0x95CD4F; -uint32 CPopulation::ms_nNumGang1; // = *(uint32*)0x8F1B1C; -uint32 CPopulation::ms_nNumGang2; // = *(uint32*)0x8F1B14; -uint32 CPopulation::ms_nTotalPeds; // = *(uint32*)0x95CB50; -uint32 CPopulation::ms_nNumGang3; // = *(uint32*)0x8F2548; -uint32 CPopulation::ms_nTotalGangPeds; // = *(uint32*)0x885AF0; -uint32 CPopulation::ms_nNumGang4; // = *(uint32*)0x8F1B2C; -uint32 CPopulation::ms_nTotalCivPeds; // = *(uint32*)0x8F2C3C; -uint32 CPopulation::ms_nNumGang5; // = *(uint32*)0x8F1B30; -uint32 CPopulation::ms_nNumDummy; // = *(uint32*)0x8F1A98; -uint32 CPopulation::ms_nNumGang6; // = *(uint32*)0x8F1B20; -uint32 CPopulation::ms_nNumGang9; // = *(uint32*)0x8F1B10; -uint32 CPopulation::ms_nNumGang7; // = *(uint32*)0x8F1B28; -uint32 CPopulation::ms_nNumGang8; // = *(uint32*)0x8F1B0C; -CVector CPopulation::RegenerationPoint_a; // = *(CVector*)0x8E2AA4; -CVector CPopulation::RegenerationPoint_b; // = *(CVector*)0x8E2A98; -CVector CPopulation::RegenerationForward; // = *(CVector*)0x8F1AD4; +PedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS]; +bool CPopulation::ms_bGivePedsWeapons; +int32 CPopulation::m_AllRandomPedsThisType = -1; +float CPopulation::PedDensityMultiplier = 1.0f; +uint32 CPopulation::ms_nTotalMissionPeds; +int32 CPopulation::MaxNumberOfPedsInUse = 25; +uint32 CPopulation::ms_nNumCivMale; +uint32 CPopulation::ms_nNumCivFemale; +uint32 CPopulation::ms_nNumCop; +bool CPopulation::bZoneChangeHasHappened; +uint32 CPopulation::ms_nNumEmergency; +int8 CPopulation::m_CountDownToPedsAtStart; +uint32 CPopulation::ms_nNumGang1; +uint32 CPopulation::ms_nNumGang2; +uint32 CPopulation::ms_nTotalPeds; +uint32 CPopulation::ms_nNumGang3; +uint32 CPopulation::ms_nTotalGangPeds; +uint32 CPopulation::ms_nNumGang4; +uint32 CPopulation::ms_nTotalCivPeds; +uint32 CPopulation::ms_nNumGang5; +uint32 CPopulation::ms_nNumDummy; +uint32 CPopulation::ms_nNumGang6; +uint32 CPopulation::ms_nNumGang9; +uint32 CPopulation::ms_nNumGang7; +uint32 CPopulation::ms_nNumGang8; +CVector CPopulation::RegenerationPoint_a; +CVector CPopulation::RegenerationPoint_b; +CVector CPopulation::RegenerationForward; void CPopulation::Initialise() diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d7834065..7b2f90e8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -39,16 +39,17 @@ struct EntityInfo float sort; }; -CLinkList &gSortedVehiclesAndPeds = *(CLinkList*)0x629AC0; +CLinkList gSortedVehiclesAndPeds; -int32 &CRenderer::ms_nNoOfVisibleEntities = *(int32*)0x940730; -CEntity *(&CRenderer::ms_aVisibleEntityPtrs)[NUMVISIBLEENTITIES] = *(CEntity * (*)[NUMVISIBLEENTITIES]) * (uintptr*)0x6E9920; -CEntity *(&CRenderer::ms_aInVisibleEntityPtrs)[NUMINVISIBLEENTITIES] = *(CEntity * (*)[NUMINVISIBLEENTITIES]) * (uintptr*)0x880B50; -int32 &CRenderer::ms_nNoOfInVisibleEntities = *(int32*)0x8F1B78; +int32 CRenderer::ms_nNoOfVisibleEntities; +CEntity *CRenderer::ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES]; +CEntity *CRenderer::ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES]; +int32 CRenderer::ms_nNoOfInVisibleEntities; -CVector &CRenderer::ms_vecCameraPosition = *(CVector*)0x8E2C3C; -CVehicle *&CRenderer::m_pFirstPersonVehicle = *(CVehicle**)0x885B80; -bool &CRenderer::m_loadingPriority = *(bool*)0x95CD86; +CVector CRenderer::ms_vecCameraPosition; +CVehicle *CRenderer::m_pFirstPersonVehicle; +bool CRenderer::m_loadingPriority; +float CRenderer::ms_lodDistScale = 1.2f; void CRenderer::Init(void) diff --git a/src/render/Renderer.h b/src/render/Renderer.h index 42c154ec..362741e3 100644 --- a/src/render/Renderer.h +++ b/src/render/Renderer.h @@ -20,17 +20,17 @@ class CPtrList; class CRenderer { - static int32 &ms_nNoOfVisibleEntities; - static CEntity *(&ms_aVisibleEntityPtrs)[NUMVISIBLEENTITIES]; - static int32 &ms_nNoOfInVisibleEntities; - static CEntity *(&ms_aInVisibleEntityPtrs)[NUMINVISIBLEENTITIES]; + static int32 ms_nNoOfVisibleEntities; + static CEntity *ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES]; + static int32 ms_nNoOfInVisibleEntities; + static CEntity *ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES]; - static CVector &ms_vecCameraPosition; - static CVehicle *&m_pFirstPersonVehicle; + static CVector ms_vecCameraPosition; + static CVehicle *m_pFirstPersonVehicle; public: - static float ms_lodDistScale; // defined in Frontend.cpp - static bool &m_loadingPriority; + static float ms_lodDistScale; + static bool m_loadingPriority; static void Init(void); static void Shutdown(void); diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 257c8d33..2a325b3d 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -356,7 +356,7 @@ CAutomobile::ProcessControl(void) PruneReferences(); - if(m_status == STATUS_PLAYER && CRecordDataForChase::IsRecording()) + if(m_status == STATUS_PLAYER && !CRecordDataForChase::IsRecording()) DoDriveByShootings(); } break; @@ -4206,8 +4206,7 @@ GetCurrentAtomicObjectCB(RwObject *object, void *data) return object; } -CColPoint aTempPedColPts[32]; // this name doesn't make any sense - // they probably copied it from Ped (both serves same purpose) and didn't change the name +CColPoint spherepoints[MAX_COLLISION_POINTS]; CObject* CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) @@ -4327,7 +4326,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(), this->GetMatrix(), *this->GetColModel(), - aTempPedColPts, nil, nil) > 0) + spherepoints, nil, nil) > 0) obj->m_pCollidingEntity = this; if(bRenderScorched) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index f47fd131..ed8f4221 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -19,12 +19,12 @@ #include "Fire.h" #include "Darkel.h" -bool &CVehicle::bWheelsOnlyCheat = *(bool *)0x95CD78; -bool &CVehicle::bAllDodosCheat = *(bool *)0x95CD75; -bool &CVehicle::bCheat3 = *(bool *)0x95CD66; -bool &CVehicle::bCheat4 = *(bool *)0x95CD65; -bool &CVehicle::bCheat5 = *(bool *)0x95CD64; -bool &CVehicle::m_bDisableMouseSteering = *(bool *)0x60252C; +bool CVehicle::bWheelsOnlyCheat; +bool CVehicle::bAllDodosCheat; +bool CVehicle::bCheat3; +bool CVehicle::bCheat4; +bool CVehicle::bCheat5; +bool CVehicle::m_bDisableMouseSteering; void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); } void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); } diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index f9becda0..bfc6d95d 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -277,12 +277,12 @@ public: bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE; } AnimationId GetDriverAnim(void) { return IsCar() && bLowVehicle ? ANIM_CAR_LSIT : (IsBoat() && GetModelIndex() != MI_SPEEDER ? ANIM_DRIVE_BOAT : ANIM_CAR_SIT); } - static bool &bWheelsOnlyCheat; - static bool &bAllDodosCheat; - static bool &bCheat3; - static bool &bCheat4; - static bool &bCheat5; - static bool &m_bDisableMouseSteering; + static bool bWheelsOnlyCheat; + static bool bAllDodosCheat; + static bool bCheat3; + static bool bCheat4; + static bool bCheat5; + static bool m_bDisableMouseSteering; }; static_assert(sizeof(CVehicle) == 0x288, "CVehicle: error"); From 01d18e8f28d3de5b22a688fffe57ace1c98fd714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 15 Apr 2020 19:37:41 +0300 Subject: [PATCH 018/123] Readme update --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c7d83212..53f2136a 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ to reverse at the time, calling the original functions is acceptable. ### Unreversed / incomplete classes (at least the ones we know) ``` CBulletInfo -CPedPath CWeapon CWorld ``` From 85fe445fef1a20a0b5bc74f30bc3fd14418efb3d Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 19:43:16 +0300 Subject: [PATCH 019/123] weapon cosmetic fix --- src/weapons/Weapon.cpp | 967 +++++++++++++++++++++-------------------- 1 file changed, 484 insertions(+), 483 deletions(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 28031847..b0c9b61f 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -32,26 +32,28 @@ uint16 gReloadSampleTime[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS] = { - /*UNARMED*/ 0, - /*BASEBALLBAT*/ 0, - /*COLT45*/ 250, - /*UZI*/ 400, - /*SHOTGUN*/ 650, - /*AK47*/ 300, - /*M16*/ 300, - /*SNIPERRIFLE*/ 423, - /*ROCKETLAUNCHER*/ 400, - /*FLAMETHROWER*/ 0, - /*MOLOTOV*/ 0, - /*GRENADE*/ 0, - /*DETONATOR*/ 0 + 0, // UNARMED + 0, // BASEBALLBAT + 250, // COLT45 + 400, // UZI + 650, // SHOTGUN + 300, // AK47 + 300, // M16 + 423, // SNIPERRIFLE + 400, // ROCKETLAUNCHER + 0, // FLAMETHROWER + 0, // MOLOTOV + 0, // GRENADE + 0, // DETONATOR + + 0 // WEAPONTYPE_HELICANNON }; CWeaponInfo * CWeapon::GetInfo() { CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType); - ASSERT(info!=NULL); + ASSERT(info!=nil); return info; } @@ -101,14 +103,14 @@ CWeapon::Initialise(eWeaponType type, int32 ammo) bool CWeapon::Fire(CEntity *shooter, CVector *fireSource) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + CVector fireOffset(0.0f, 0.0f, 0.6f); CVector *source = fireSource; - + if ( !fireSource ) source = &(shooter->GetMatrix() * fireOffset); - + if ( m_bAddRotOffset ) { float heading = RADTODEG(shooter->GetForward().Heading()); @@ -116,58 +118,58 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) (*source).x += -Sin(angle) * 0.15f; (*source).y += Cos(angle) * 0.15f; } - + if ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING ) return false; bool fired; - + if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE ) { if ( m_nAmmoInClip <= 0 ) return false; - + switch ( m_eWeaponType ) { case WEAPONTYPE_SHOTGUN: { fired = FireShotgun(shooter, source); - + break; } - + case WEAPONTYPE_COLT45: case WEAPONTYPE_UZI: case WEAPONTYPE_AK47: { fired = FireInstantHit(shooter, source); - + break; } - + case WEAPONTYPE_SNIPERRIFLE: { fired = FireSniper(shooter); - + break; } - + case WEAPONTYPE_M16: { if ( TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON && shooter == FindPlayerPed() ) fired = FireM16_1stPerson(shooter); else fired = FireInstantHit(shooter, source); - + break; } - + case WEAPONTYPE_ROCKETLAUNCHER: { - if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != NULL ) + if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil ) { float distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude(); - + if ( distToTarget > 8.0f || ((CPed*)shooter)->IsPlayer() ) fired = FireProjectile(shooter, source, 0.0f); else @@ -175,10 +177,10 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) } else fired = FireProjectile(shooter, source, 0.0f); - + break; } - + case WEAPONTYPE_MOLOTOV: case WEAPONTYPE_GRENADE: { @@ -188,81 +190,81 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) if ( m_eWeaponType == WEAPONTYPE_GRENADE ) CStats::KgsOfExplosivesUsed++; } - else if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != NULL ) + else if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil ) { float distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude(); float power = clamp((distToTarget-10.0f)*0.02f, 0.2f, 1.0f); - + fired = FireProjectile(shooter, source, power); } else fired = FireProjectile(shooter, source, 0.3f); - + break; } - + case WEAPONTYPE_FLAMETHROWER: { fired = FireAreaEffect(shooter, source); - + break; } - + case WEAPONTYPE_DETONATOR: { CWorld::UseDetonator(shooter); m_nAmmoTotal = 1; m_nAmmoInClip = m_nAmmoTotal; fired = true; - + break; } - + case WEAPONTYPE_HELICANNON: { if ( (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON ) && shooter == FindPlayerPed() ) { fired = FireM16_1stPerson(shooter); - } + } else fired = FireInstantHit(shooter, source); - + break; } - + default: { debug("Unknown weapon type, Weapon.cpp"); break; } } - + if ( fired ) { bool isPlayer = false; - + if ( shooter->IsPed() ) { CPed *shooterPed = (CPed*)shooter; - + shooterPed->bIsShooting = true; - + if ( shooterPed->IsPlayer() ) isPlayer = true; - + DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); } - + if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) ) m_nAmmoTotal--; - + if ( m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER ) DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f); - + m_eWeaponState = WEAPONSTATE_FIRING; } - + if ( m_nAmmoInClip == 0 ) { if ( m_nAmmoTotal == 0 ) @@ -270,16 +272,16 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) m_eWeaponState = WEAPONSTATE_RELOADING; m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; - + if ( shooter == FindPlayerPed() ) { if ( CWorld::Players[CWorld::PlayerInFocus].m_bFastReload ) m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4; } - + return true; } - + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; if ( shooter == FindPlayerPed() ) CStats::RoundsFiredByPlayer++; @@ -291,10 +293,10 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; m_eWeaponState = WEAPONSTATE_FIRING; } - + FireMelee(shooter, *source); } - + if ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT ) return true; else @@ -304,23 +306,23 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) bool CWeapon::FireFromCar(CAutomobile *shooter, bool left) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + if ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING ) return false; - + if ( m_nAmmoInClip <= 0 ) return false; - + if ( FireInstantHitFromCar(shooter, left) ) { DMAudio.PlayOneShot(shooter->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); - + if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; if ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 ) m_nAmmoTotal--; - + m_eWeaponState = WEAPONSTATE_FIRING; - + if ( m_nAmmoInClip == 0 ) { if ( m_nAmmoTotal == 0 ) @@ -328,49 +330,48 @@ CWeapon::FireFromCar(CAutomobile *shooter, bool left) m_eWeaponState = WEAPONSTATE_RELOADING; m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; - + return true; } - + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; if ( shooter == FindPlayerVehicle() ) CStats::RoundsFiredByPlayer++; } - + return true; } bool CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + CWeaponInfo *info = GetInfo(); - + bool anim2Playing = false; if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), info->m_Anim2ToPlay) ) anim2Playing = true; - + ASSERT(shooter->IsPed()); - + CPed *shooterPed = (CPed*)shooter; - + for ( int32 i = 0; i < shooterPed->m_numNearPeds; i++ ) { CPed *victimPed = shooterPed->m_nearPeds[i]; - ASSERT(victimPed!=NULL); - + ASSERT(victimPed!=nil); + if ( (victimPed->m_nPedType != shooterPed->m_nPedType || victimPed == shooterPed->m_pSeekTarget) && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) ) { bool collided = false; - + CColModel *victimPedCol = &CTempColModels::ms_colModelPed1; if ( victimPed->OnGround() || !victimPed->IsPedHeadAbovePos(-0.3f) ) victimPedCol = &CTempColModels::ms_colModelPedGroundHit; - - ASSERT(victimPedCol!=NULL); - + + float victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius; if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() ) { @@ -378,13 +379,13 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) if ( SQR(victimPedRadius) > (victimPedPos-(*fireSource)).MagnitudeSqr() ) { CVector collisionDist; - + int32 s = 0; while ( s < victimPedCol->numSpheres ) { CColSphere *sphere = &victimPedCol->spheres[s]; collisionDist = victimPedPos+sphere->center-(*fireSource); - + if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() ) { collided = true; @@ -392,29 +393,29 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) } s++; } - + if ( !(victimPed->IsPlayer() && victimPed->GetPedState() == PED_GETUP) ) { if ( collided ) { float victimPedHealth = victimPed->m_fHealth; - CVector bloodPos = fireSource + collisionDist*0.7f; - + CVector bloodPos = fireSource + (collisionDist*0.7f); + CVector2D posOffset(shooterPed->GetPosition().x-victimPedPos.x, shooterPed->GetPosition().y-victimPedPos.y); - + int32 localDir = victimPed->GetLocalDirection(posOffset); - + bool isBat = m_eWeaponType == WEAPONTYPE_BASEBALLBAT; - + if ( !victimPed->DyingOrDead() ) victimPed->ReactToAttack(shooterPed); - + uint8 hitLevel = HITLEVEL_HIGH; if ( isBat && victimPed->OnGround() ) hitLevel = HITLEVEL_GROUND; - + victimPed->StartFightDefend(localDir, hitLevel, 10); - + if ( !victimPed->DyingOrDead() ) { if ( shooterPed->IsPlayer() && isBat && anim2Playing ) @@ -429,30 +430,30 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) victimPed->InflictDamage(shooterPed, m_eWeaponType, info->m_nDamage, PEDPIECE_TORSO, localDir); } } - + if ( CGame::nastyGame ) { if ( victimPed->GetIsOnScreen() ) { CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr()); - + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - + if ( isBat ) { dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); } } } - + if ( !victimPed->OnGround() ) { if ( victimPed->m_fHealth > 0.0f @@ -461,12 +462,12 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) posOffset.Normalise(); victimPed->bIsStanding = false; victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); - + if ( isBat && victimPed->IsPlayer() ) victimPed->SetFall(3000, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); else victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); - + shooterPed->m_pSeekTarget = victimPed; shooterPed->m_pSeekTarget->RegisterReference(&shooterPed->m_pSeekTarget); } @@ -477,9 +478,9 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) victimPed->bIsStanding = false; victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); } - + m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; - + if ( victimPed->m_nPedType == PEDTYPE_COP ) CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); else @@ -490,39 +491,39 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) } } } - + return true; } bool CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { - ASSERT(shooter!=NULL); - ASSERT(fireSource!=NULL); - + ASSERT(shooter!=nil); + ASSERT(fireSource!=nil); + CWeaponInfo *info = GetInfo(); - + CVector source, target; CColPoint point; - CEntity *victim = NULL; - + CEntity *victim = nil; + float heading = RADTODEG(shooter->GetForward().Heading()); float angle = DEGTORAD(heading); - + CVector2D ahead(-Sin(angle), Cos(angle)); ahead.Normalise(); - + CVector vel = ((CPed *)shooter)->m_vecMoveSpeed; int32 shooterMoving = false; if ( Abs(vel.x) > 0.0f && Abs(vel.y) > 0.0f ) shooterMoving = true; - + if ( shooter == FindPlayerPed() ) { static float prev_heading = 0.0f; prev_heading = ((CPed*)shooter)->m_fRotationCur; } - + if ( shooter->IsPed() && ((CPed *)shooter)->m_pPointGunAt ) { CPed *shooterPed = (CPed *)shooter; @@ -530,10 +531,10 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { int32 accuracy = shooterPed->m_wepAccuracy; int32 inaccuracy = 100-accuracy; - + if ( accuracy != 100 ) FindPlayerPed(); //what ? - + CPed *threatAttack = (CPed*)shooterPed->m_pPointGunAt; if ( threatAttack->IsPed() ) { @@ -542,18 +543,18 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } else target = threatAttack->GetPosition(); - + target -= *fireSource; target *= info->m_fRange / target.Magnitude(); target += *fireSource; - + if ( inaccuracy != 0 ) { target.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; target.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; target.z += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * inaccuracy; } - + CWorld::bIncludeDeadPeds = true; ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); CWorld::bIncludeDeadPeds = false; @@ -563,10 +564,10 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) target.x = info->m_fRange; target.y = 0.0f; target.z = 0.0f; - + for (RwFrame *i = shooterPed->GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i)) RwV3dTransformPoints(target, target, 1, RwFrameGetMatrix(i)); - + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); } } @@ -574,270 +575,270 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { CVector src, trgt; TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, src, trgt); - + CWorld::bIncludeDeadPeds = true; ProcessLineOfSight(src, trgt,point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); CWorld::bIncludeDeadPeds = false; - + int32 rotSpeed = 1; if ( m_eWeaponType == WEAPONTYPE_M16 ) rotSpeed = 4; - + CVector bulletPos; if ( CHeli::TestBulletCollision(&src, &trgt, &bulletPos, 4) ) { for ( int32 i = 0; i < 16; i++ ) - CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, rotSpeed); + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed); } } else { float shooterHeading = RADTODEG(shooter->GetForward().Heading()); float shooterAngle = DEGTORAD(shooterHeading); - + CVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle)); rotOffset.Normalise(); - + target = *fireSource; target.x = rotOffset.x * info->m_fRange; target.y = rotOffset.y * info->m_fRange; - + if ( shooter->IsPed() ) DoDoomAiming(shooter, fireSource, &target); - + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); - + int32 rotSpeed = 1; if ( m_eWeaponType == WEAPONTYPE_M16 ) rotSpeed = 4; - + CVector bulletPos; if ( CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4) ) { for ( int32 i = 0; i < 16; i++ ) - CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, rotSpeed); + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed); } } - + if ( victim && shooter->IsPed() && victim == ((CPed*)shooter)->m_leader ) return false; CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed *)shooter, 1000); - + if ( shooter == FindPlayerPed() ) { CStats::InstantHitsFiredByPlayer++; if ( !(CTimer::GetFrameCounter() & 3) ) MakePedsJumpAtShot((CPhysical*)shooter, fireSource, &target); } - + switch ( m_eWeaponType ) { case WEAPONTYPE_AK47: { static uint8 counter = 0; - + if ( !(++counter & 1) ) { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CVector gunflashPos = *fireSource; gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.10f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.10f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); gunflashPos += CVector(0.05f*ahead.x, 0.05f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + CVector gunsmokePos = *fireSource; float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); - + CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.5f*ahead.x, 0.5f*ahead.y, 0.0f); CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); dir.Normalise2D(); AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.018f); } - + break; } - + case WEAPONTYPE_M16: { static uint8 counter = 0; - + if ( !(++counter & 1) ) { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CVector gunflashPos = *fireSource; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); + gunflashPos = *fireSource; gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); gunflashPos.z += 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos.z += 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); gunflashPos.z += 0.03f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + gunflashPos = *fireSource; gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); gunflashPos.z -= 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos.z -= 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); gunflashPos.z -= 0.03f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + CVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); offset.Normalise2D(); - + gunflashPos = *fireSource; gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); gunflashPos += CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos += CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); gunflashPos += CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + gunflashPos = *fireSource; gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); gunflashPos -= CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos -= CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); gunflashPos -= CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + CVector gunsmokePos = *fireSource; float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); - + CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.65f*ahead.x, 0.65f*ahead.y, 0.0f); CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); dir.Normalise2D(); AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.02f); } - + break; } - + case WEAPONTYPE_UZI: { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CVector gunflashPos = *fireSource; - + if ( shooterMoving ) gunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f); - - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.07f); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.07f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.05f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.05f); gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); gunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); gunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); gunflashPos += CVector(0.02f*ahead.x, 0.02f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.01f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.01f); + CVector gunsmokePos = *fireSource; float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); - + CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f); CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); dir.Normalise2D(); AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f); - + break; } - + case WEAPONTYPE_COLT45: { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CVector gunflashPos = *fireSource; - + if ( shooterMoving ) gunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f); - - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + CVector gunsmokePos = *fireSource; - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.10f, ahead.y*0.10f, 0.0f), NULL, 0.005f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.15f, ahead.y*0.15f, 0.0f), NULL, 0.015f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.20f, ahead.y*0.20f, 0.0f), NULL, 0.025f); - + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.10f, ahead.y*0.10f, 0.0f), nil, 0.005f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.15f, ahead.y*0.15f, 0.0f), nil, 0.015f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.20f, ahead.y*0.20f, 0.0f), nil, 0.025f); + CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f); CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); dir.Normalise2D(); AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f); - + break; } } - + DoBulletImpact(shooter, victim, fireSource, &target, &point, ahead); - + return true; } void CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &direction, float size) { - ASSERT(shooter!=NULL); - - if ( shooter == NULL) + ASSERT(shooter!=nil); + + if ( shooter == nil) return; - + CVector dir(direction.x*0.05f, direction.y*0.05f, CGeneral::GetRandomNumberInRange(0.02f, 0.08f)); - + static CVector prevEntityPosition(0.0f, 0.0f, 0.0f); CVector entityPosition = shooter->GetPosition(); - + CVector diff = entityPosition - prevEntityPosition; - + if ( Abs(diff.x)+Abs(diff.y)+Abs(diff.z) > 1.5f ) { prevEntityPosition = entityPosition; - + CParticle::AddParticle(PARTICLE_GUNSHELL_FIRST, - source, dir, NULL, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); + source, dir, nil, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); } else { CParticle::AddParticle(PARTICLE_GUNSHELL, - source, dir, NULL, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); + source, dir, nil, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); } } @@ -845,21 +846,21 @@ void CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CVector *source, CVector *target, CColPoint *point, CVector2D ahead) { - ASSERT(shooter!=NULL); - ASSERT(source!=NULL); - ASSERT(target!=NULL); - ASSERT(point!=NULL); - + ASSERT(shooter!=nil); + ASSERT(source!=nil); + ASSERT(target!=nil); + ASSERT(point!=nil); + CWeaponInfo *info = GetInfo(); - + if ( victim ) { CGlass::WasGlassHitByBullet(victim, point->point); - + CVector traceTarget = *target; CBulletTraces::AddTrace(source, &traceTarget); - - if ( shooter != NULL ) + + if ( shooter != nil ) { if ( shooter == FindPlayerPed() ) { @@ -867,7 +868,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CStats::InstantHitsHitByPlayer++; } } - + if ( victim->IsPed() && ((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 ) { CPed *victimPed = (CPed *)victim; @@ -876,12 +877,12 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, if ( victimPed->DoesLOSBulletHitPed(*point) ) { CVector pos = victimPed->GetPosition(); - + CVector2D posOffset(source->x-pos.x, source->y-pos.y); int32 localDir = victimPed->GetLocalDirection(posOffset); - + victimPed->ReactToAttack(shooter); - + if ( !victimPed->IsPedInControl() || victimPed->bIsDucking ) { victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); @@ -892,10 +893,10 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, { posOffset.Normalise(); victimPed->bIsStanding = false; - + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 5.0f); victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); - + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); } else @@ -906,13 +907,13 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, if ( victimPlayer->m_nHitAnimDelayTimer < CTimer::GetTimeInMilliseconds() ) { victimPed->ClearAttackByRemovingAnim(); - + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); - ASSERT(asoc!=NULL); - + ASSERT(asoc!=nil); + asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; - + if ( m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_M16 ) victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 2500; else @@ -922,32 +923,32 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, else { victimPed->ClearAttackByRemovingAnim(); - + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); - ASSERT(asoc!=NULL); - + ASSERT(asoc!=nil); + asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; } - + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); } } - + if ( victimPed->m_nPedType == PEDTYPE_COP ) CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); else CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); - + if ( CGame::nastyGame ) { uint8 bloodAmount = 8; if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) bloodAmount = 32; - + CVector dir = (point->point - victim->GetPosition()) * 0.01f; dir.z = 0.01f; - + if ( victimPed->GetIsOnScreen() ) { for ( uint8 i = 0; i < bloodAmount; i++ ) @@ -962,13 +963,13 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, { CVector dir = (point->point - victim->GetPosition()) * 0.01f; dir.z = 0.01f; - + if ( victim->GetIsOnScreen() ) { for ( int32 i = 0; i < 8; i++ ) CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point + CVector(0.0f, 0.0f, 0.15f), dir); } - + if ( victimPed->Dead() ) { CAnimBlendAssociation *asoc; @@ -976,7 +977,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, asoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f); else asoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f); - + if ( asoc ) { asoc->SetCurrentTime(0.0f); @@ -995,36 +996,36 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, { for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); - + CVector dist = point->point - (*source); CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(ahead.x, ahead.y, 0.0f); CVector smokePos = *source + offset; - + smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); smokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); smokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + break; } case ENTITY_TYPE_VEHICLE: { ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); - + for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); - + CVector dist = point->point - (*source); CVector offset = dist - max(0.2f*dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f); CVector smokePos = *source + offset; - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + if ( shooter->IsPed() ) { CPed *shooterPed = (CPed *)shooter; - + if ( shooterPed->bNotAllowedToDuck ) { if ( shooterPed->bKindaStayInSamePlace && victim != shooterPed->m_pPointGunAt ) @@ -1034,16 +1035,16 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } } } - + break; } case ENTITY_TYPE_OBJECT: { for ( int32 i = 0; i < 8; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); - + CObject *victimObject = (CObject *)victim; - + if ( !victimObject->bInfiniteMass ) { if ( victimObject->bIsStatic && victimObject->m_fUprootLimit <= 0.0f ) @@ -1051,19 +1052,19 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, victimObject->bIsStatic = false; victimObject->AddToMovingList(); } - + if ( !victimObject->bIsStatic ) { CVector moveForce = point->normal*-4.0f; victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); } } - + break; } } } - + switch ( victim->m_type ) { case ENTITY_TYPE_BUILDING: @@ -1096,50 +1097,50 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } else CBulletTraces::AddTrace(source, target); - + if ( shooter == FindPlayerPed() ) CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - + BlowUpExplosiveThings(victim); } bool CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { - ASSERT(shooter!=NULL); - ASSERT(fireSource!=NULL); - + ASSERT(shooter!=nil); + ASSERT(fireSource!=nil); + CWeaponInfo *info = GetInfo(); - + float heading = RADTODEG(shooter->GetForward().Heading()); float angle = DEGTORAD(heading); - + CVector2D rotOffset(-Sin(angle), Cos(angle)); rotOffset.Normalise(); - + CVector gunflashPos = *fireSource; gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f); gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.15f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.15f); gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.2f); - CParticle::AddParticle(PARTICLE_GUNFLASH, *fireSource, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f); - + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.2f); + CParticle::AddParticle(PARTICLE_GUNFLASH, *fireSource, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f); + CVector gunsmokePos = *fireSource; - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.10f, rotOffset.y*0.10f, 0.0f), NULL, 0.1f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.15f, rotOffset.y*0.15f, 0.0f), NULL, 0.1f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.20f, rotOffset.y*0.20f, 0.0f), NULL, 0.1f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.25f, rotOffset.y*0.25f, 0.0f), NULL, 0.1f); - + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.10f, rotOffset.y*0.10f, 0.0f), nil, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.15f, rotOffset.y*0.15f, 0.0f), nil, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.20f, rotOffset.y*0.20f, 0.0f), nil, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.25f, rotOffset.y*0.25f, 0.0f), nil, 0.1f); + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000); - + CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0, 0.0, 0.0), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + float shooterAngle; - - if ( shooter->IsPed() && ((CPed*)shooter)->m_pPointGunAt != NULL ) + + if ( shooter->IsPed() && ((CPed*)shooter)->m_pPointGunAt != nil ) { CEntity *threatAttack = ((CPed*)shooter)->m_pPointGunAt; shooterAngle = CGeneral::GetAngleBetweenPoints(threatAttack->GetPosition().x, threatAttack->GetPosition().y, @@ -1147,13 +1148,13 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } else shooterAngle = RADTODEG(shooter->GetForward().Heading()); - - + + for ( int32 i = 0; i < 5; i++ ) // five shoots at once { float shootAngle = DEGTORAD(7.5f*i + shooterAngle - 15.0f); CVector2D shootRot(-Sin(shootAngle), Cos(shootAngle)); - + CVector source, target; CColPoint point; CEntity *victim; @@ -1167,7 +1168,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) target = f * Left + target - source; target *= info->m_fRange; target += source; - + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); } else @@ -1175,12 +1176,12 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) target = *fireSource; target.x += shootRot.x * info->m_fRange; target.y += shootRot.y * info->m_fRange; - + if ( shooter->IsPed() ) { CPed *shooterPed = (CPed *)shooter; - - if ( shooterPed->m_pPointGunAt == NULL ) + + if ( shooterPed->m_pPointGunAt == nil ) DoDoomAiming(shooter, fireSource, &target); else { @@ -1188,63 +1189,63 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) target.z += info->m_fRange / distToTarget * (shooterPed->m_pPointGunAt->GetPosition().z - target.z); } } - + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); } - + if ( victim ) { CGlass::WasGlassHitByBullet(victim, point.point); - + CBulletTraces::AddTrace(fireSource, &point.point); - + if ( victim->IsPed() ) { CPed *victimPed = (CPed *)victim; if ( !victimPed->OnGround() && victim != shooter && victimPed->DoesLOSBulletHitPed(point) ) { bool cantStandup = true; - + CVector pos = victimPed->GetPosition(); - + CVector2D posOffset((*fireSource).x-pos.x, (*fireSource).y-pos.y); int32 localDir = victimPed->GetLocalDirection(posOffset); - + victimPed->ReactToAttack(FindPlayerPed()); - + posOffset.Normalise(); - + if ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) ) cantStandup = false; - + if ( victimPed->bIsStanding && cantStandup ) { victimPed->bIsStanding = false; - + victimPed->ApplyMoveForce(posOffset.x*-6.0f, posOffset.y*-6.0f, 5.0f); } else victimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 0.0f); - + if ( cantStandup ) victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); - - victimPed->InflictDamage(NULL, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); - + + victimPed->InflictDamage(nil, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); + if ( victimPed->m_nPedType == PEDTYPE_COP ) CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); else CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); - + if ( CGame::nastyGame ) { uint8 bloodAmount = 8; if ( m_eWeaponType == WEAPONTYPE_SHOTGUN ) bloodAmount = 32; - + CVector dir = (point.point - victim->GetPosition()) * 0.01f; dir.z = 0.01f; - + if ( victimPed->GetIsOnScreen() ) { for ( uint8 i = 0; i < bloodAmount; i++ ) @@ -1254,45 +1255,45 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } } else - { + { switch ( victim->m_type ) { case ENTITY_TYPE_VEHICLE: { ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); - + for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); - + CVector dist = point.point - (*fireSource); CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); CVector smokePos = *fireSource + offset; - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + break; } - + case ENTITY_TYPE_BUILDING: case ENTITY_TYPE_OBJECT: { for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); - + CVector dist = point.point - (*fireSource); CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); CVector smokePos = *fireSource + offset; - + smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); smokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); smokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + if ( victim->IsObject() ) { CObject *victimObject = (CObject *)victim; - + if ( !victimObject->bInfiniteMass ) { if ( victimObject->bIsStatic && victimObject->m_fUprootLimit <= 0.0f ) @@ -1300,7 +1301,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) victimObject->bIsStatic = false; victimObject->AddToMovingList(); } - + if ( !victimObject->bIsStatic ) { CVector moveForce = point.normal*-5.0f; @@ -1308,12 +1309,12 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } } } - + break; } } } - + switch ( victim->m_type ) { case ENTITY_TYPE_BUILDING: @@ -1351,25 +1352,25 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) CBulletTraces::AddTrace(fireSource, &traceTarget); } } - + if ( shooter == FindPlayerPed() ) CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - + return true; } bool CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) { - ASSERT(shooter!=NULL); - ASSERT(fireSource!=NULL); - + ASSERT(shooter!=nil); + ASSERT(fireSource!=nil); + CVector source, target; - + if ( m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER ) { source = *fireSource; - + if ( shooter->IsPed() && ((CPed*)shooter)->IsPlayer() ) { int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; @@ -1382,31 +1383,31 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) { return false; } - + *fireSource += TheCamera.Cams[TheCamera.ActiveCam].Front; } else *fireSource += shooter->GetForward(); - + target = *fireSource; } else { float dot = DotProduct(*fireSource-shooter->GetPosition(), shooter->GetForward()); - + if ( dot < 0.3f ) *fireSource += (0.3f-dot) * shooter->GetForward(); - + target = *fireSource; - + if ( target.z - shooter->GetPosition().z > 0.0f ) target += 0.6f*shooter->GetForward(); - + source = *fireSource - shooter->GetPosition(); source = *fireSource - DotProduct(source, shooter->GetForward()) * shooter->GetForward(); } - + if ( !CWorld::GetIsLineOfSightClear(source, target, true, true, false, true, false, false, false) ) { if ( m_eWeaponType != WEAPONTYPE_GRENADE ) @@ -1417,8 +1418,8 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) { source = shooter->GetPosition() - shooter->GetForward(); source.z -= 0.4f; - - if ( !CWorld::TestSphereAgainstWorld(source, 0.5f, NULL, false, false, true, false, false, false) ) + + if ( !CWorld::TestSphereAgainstWorld(source, 0.5f, nil, false, false, true, false, false, false) ) CProjectileInfo::AddProjectile(shooter, m_eWeaponType, source, 0.0f); else CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource); @@ -1427,7 +1428,7 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) } else CProjectileInfo::AddProjectile(shooter, m_eWeaponType, *fireSource, power); - + return true; } @@ -1436,16 +1437,16 @@ CWeapon::GenerateFlameThrowerParticles(CVector pos, CVector dir) { dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); - + dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); - + dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); - + dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); - + dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); } @@ -1453,22 +1454,22 @@ CWeapon::GenerateFlameThrowerParticles(CVector pos, CVector dir) bool CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) { - ASSERT(shooter!=NULL); - ASSERT(fireSource!=NULL); - + ASSERT(shooter!=nil); + ASSERT(fireSource!=nil); + CWeaponInfo *info = GetInfo(); - + float heading = RADTODEG(shooter->GetForward().Heading()); - + CVector source; CVector target; CVector dir; - + if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) { TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target); float norm = (1.0f / info->m_fRange); - dir = (target - source) * norm; + dir = (target - source) * norm; } else { @@ -1476,18 +1477,18 @@ CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) dir = CVector(-Sin(angle)*0.5f, Cos(angle)*0.5f, 0.0f); target = *fireSource + dir; } - + CShotInfo::AddShot(shooter, m_eWeaponType, *fireSource, target); CWeapon::GenerateFlameThrowerParticles(*fireSource, dir); - + return true; } bool CWeapon::FireSniper(CEntity *shooter) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; if (!( mode == CCam::MODE_M16_1STPERSON || mode == CCam::MODE_SNIPER @@ -1498,28 +1499,28 @@ CWeapon::FireSniper(CEntity *shooter) { return false; } - + #ifndef FIX_BUGS CWeaponInfo *info = GetInfo(); //unused #endif CCam *cam = &TheCamera.Cams[TheCamera.ActiveCam]; - ASSERT(cam!=NULL); - + ASSERT(cam!=nil); + CVector source = cam->Source; CVector dir = cam->Front; - + if ( DotProduct(dir, CVector(0.0f, -0.9894f, 0.145f)) > 0.997f ) CCoronas::bSmallMoon = !CCoronas::bSmallMoon; - + dir.Normalise(); dir *= 16.0f; - + CBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir); - + if ( shooter == FindPlayerPed() ) CStats::InstantHitsFiredByPlayer++; - + if ( shooter == FindPlayerPed() ) { CPad::GetPad(0)->StartShake_Distance(240, 128, @@ -1529,17 +1530,17 @@ CWeapon::FireSniper(CEntity *shooter) CamShakeNoPos(&TheCamera, 0.2f); } - + return true; } bool CWeapon::FireM16_1stPerson(CEntity *shooter) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; - + if (!( mode == CCam::MODE_M16_1STPERSON || mode == CCam::MODE_SNIPER || mode == CCam::MODE_ROCKETLAUNCHER @@ -1550,30 +1551,30 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) { return false; } - + CWeaponInfo *info = GetInfo(); - + CColPoint point; CEntity *victim; - + CWorld::bIncludeCarTyres = true; CWorld::pIgnoreEntity = shooter; CWorld::bIncludeDeadPeds = true; - + CCam *cam = &TheCamera.Cams[TheCamera.ActiveCam]; - ASSERT(cam!=NULL); - + ASSERT(cam!=nil); + CVector source = cam->Source; CVector target = cam->Front*info->m_fRange + source; - + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); CWorld::bIncludeDeadPeds = false; - CWorld::pIgnoreEntity = NULL; + CWorld::pIgnoreEntity = nil; CWorld::bIncludeCarTyres = false; - + CVector2D front(cam->Front.x, cam->Front.y); front.Normalise(); - + DoBulletImpact(shooter, victim, &source, &target, &point, front); CVector bulletPos; @@ -1582,11 +1583,11 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f)); } - + if ( shooter == FindPlayerPed() ) { CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - + if ( m_eWeaponType == WEAPONTYPE_M16 ) { TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f; @@ -1598,7 +1599,7 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f; } } - + return true; } @@ -1606,56 +1607,56 @@ bool CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) { CWeaponInfo *info = GetInfo(); - + CVehicleModelInfo *modelInfo = shooter->GetModelInfo(); - + #define FRONTSEATPOS() (&(shooter->IsBoat() ? modelInfo->m_positions[BOAT_POS_FRONTSEAT] : modelInfo->m_positions[CAR_POS_FRONTSEAT])) - + CVector source, target; if ( left ) { - source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.2f, + source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.2f, float(CGeneral::GetRandomNumber() & 255) * 0.001f + FRONTSEATPOS()->y, FRONTSEATPOS()->z + 0.5f); source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; - - + + target = shooter->GetMatrix() * CVector(-info->m_fRange, FRONTSEATPOS()->y, FRONTSEATPOS()->z + 0.5f); } else { - source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.2f, + source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.2f, float(CGeneral::GetRandomNumber() & 255) * 0.001f + FRONTSEATPOS()->y, FRONTSEATPOS()->z + 0.5f); source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; - + target = shooter->GetMatrix() * CVector(info->m_fRange, FRONTSEATPOS()->y, FRONTSEATPOS()->z + 0.5f); } #undef FRONTSEATPOS - + if ( TheCamera.GetLookingLRBFirstPerson() && !left ) { source -= 0.3f * shooter->GetForward(); target -= 0.3f * shooter->GetForward(); } - + target += CVector(float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f); - + DoDriveByAutoAiming(FindPlayerPed(), &source, &target); - + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); if ( !TheCamera.GetLookingLRBFirstPerson() ) CParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f)); else CamShakeNoPos(&TheCamera, 0.01f); - + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, FindPlayerPed(), 1000); CPointLights::AddLight(CPointLights::LIGHT_POINT, source, CVector(0.0f, 0.0f, 0.0f), 5.0f, @@ -1664,38 +1665,38 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) CColPoint point; CEntity *victim; ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); - + if ( !(CTimer::GetFrameCounter() & 3) ) MakePedsJumpAtShot(shooter, &source, &target); - + if ( victim ) { CVector traceTarget = point.point; CBulletTraces::AddTrace(&source, &traceTarget); - + if ( victim->IsPed() ) { CPed *victimPed = (CPed*)victim; - + if ( !victimPed->DyingOrDead() && victim != (CEntity *)shooter ) { CVector pos = victimPed->GetPosition(); - + CVector2D posOffset(source.x-pos.x, source.y-pos.y); int32 localDir = victimPed->GetLocalDirection(posOffset); - + victimPed->ReactToAttack(FindPlayerPed()); victimPed->ClearAttackByRemovingAnim(); - + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); - ASSERT(asoc!=NULL); + ASSERT(asoc!=nil); asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; - + victimPed->InflictDamage(shooter, WEAPONTYPE_UZI_DRIVEBY, 3*info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); - + pos.z += 0.8f; - + if ( victimPed->GetIsOnScreen() ) { if ( CGame::nastyGame ) @@ -1706,12 +1707,12 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) dir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); dir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); dir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); - + CParticle::AddParticle(PARTICLE_BLOOD, pos, dir); } } } - + if ( victimPed->m_nPedType == PEDTYPE_COP ) CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victimPed, FindPlayerPed(), 10000); else @@ -1722,7 +1723,7 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) ((CVehicle *)victim)->InflictDamage(FindPlayerPed(), WEAPONTYPE_UZI_DRIVEBY, info->m_nDamage); else CGlass::WasGlassHitByBullet(victim, point.point); - + switch ( victim->m_type ) { case ENTITY_TYPE_BUILDING: @@ -1759,20 +1760,20 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) CVector traceTarget = (target-source)*norm + source; CBulletTraces::AddTrace(&source, &traceTarget); } - + if ( shooter == FindPlayerVehicle() ) CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y, FindPlayerVehicle()->GetPosition().z); - + return true; } void CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) { - ASSERT(shooter!=NULL); - ASSERT(source!=NULL); - ASSERT(target !=NULL); - + ASSERT(shooter!=nil); + ASSERT(source!=nil); + ASSERT(target !=nil); + #ifndef FIX_BUGS CEntity entity; // unused #endif @@ -1780,19 +1781,19 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) CPed *shooterPed = (CPed*)shooter; if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) return; - + int16 lastEntity; CEntity *entities[16]; CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, true, true, false, false); float closestEntityDist = 10000.0f; int16 closestEntity; - + for ( int32 i = 0; i < lastEntity; i++ ) { CEntity *victim = entities[i]; - ASSERT(victim!=NULL); - + ASSERT(victim!=nil); + if ( (CEntity*)shooterPed != victim && shooterPed->CanSeeEntity(victim, DEGTORAD(22.5f)) ) { if ( !(victim->m_status == STATUS_TRAIN_MOVING @@ -1802,11 +1803,11 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) { float distToVictim = (shooterPed->GetPosition()-victim->GetPosition()).Magnitude2D(); float distToVictimZ = Abs(shooterPed->GetPosition().z-victim->GetPosition().z); - + if ( 1.5f*distToVictimZ < distToVictim ) { float entityDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ)); - + if ( entityDist < closestEntityDist ) { closestEntityDist = entityDist; @@ -1816,22 +1817,22 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) } } } - + if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) { CEntity *victim = entities[closestEntity]; - ASSERT(victim !=NULL); - + ASSERT(victim !=nil); + float distToTarget = (*target - *source).Magnitude2D(); float distToSource = (victim->GetPosition() - *source).Magnitude2D(); - + float victimZ = victim->GetPosition().z + 0.3f; if ( victim->IsPed() ) { if ( ((CPed*)victim)->bIsDucking ) victimZ -= 0.8f; } - + (*target).z = (distToTarget / distToSource) * (victimZ - (*source).z) + (*source).z; } } @@ -1839,11 +1840,11 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) void CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CVector *target) { - ASSERT(shooter!=NULL); - ASSERT(driver!=NULL); - ASSERT(source!=NULL); - ASSERT(target!=NULL); - + ASSERT(shooter!=nil); + ASSERT(driver!=nil); + ASSERT(source!=nil); + ASSERT(target!=nil); + #ifndef FIX_BUGS CEntity entity; // unused #endif @@ -1854,17 +1855,17 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV float closestEntityDist = 10000.0f; int16 closestEntity; - + float normZ = (target->z - source->z) / (*target-*source).Magnitude(); - + for ( int32 i = 0; i < lastEntity; i++ ) { CEntity *victim = entities[i]; - - ASSERT(victim!=NULL); - + + ASSERT(victim!=nil); + if ( shooter != victim && driver != victim ) - { + { if ( !(victim->m_status == STATUS_TRAIN_MOVING || victim->m_status == STATUS_TRAIN_NOT_MOVING || victim->m_status == STATUS_HELI @@ -1874,7 +1875,7 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV { float distToVictim = (shooter->GetPosition()-victim->GetPosition()).Magnitude2D(); float distToVictimZ = Abs(shooter->GetPosition().z - (distToVictim*normZ + victim->GetPosition().z)); - + if ( 3.0f*distToVictimZ < distToVictim ) { if ( CCollision::DistToLine(source, target, @@ -1892,15 +1893,15 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV } } } - + if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) { CEntity *victim = entities[closestEntity]; - ASSERT(victim!=NULL); - + ASSERT(victim!=nil); + float distToTarget = (*target - *source).Magnitude2D(); float distToSource = (victim->GetPosition() - *source).Magnitude2D(); - + (*target).z = (distToTarget / distToSource) * (0.3f + victim->GetPosition().z - (*source).z) + (*source).z; } } @@ -1908,36 +1909,36 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV void CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) { - ASSERT(shooter!=NULL); - ASSERT(source!=NULL); - ASSERT(target!=NULL); - + ASSERT(shooter!=nil); + ASSERT(source!=nil); + ASSERT(target!=nil); + #ifndef FIX_BUGS CEntity entity; // unused #endif - + CPed *shooterPed = (CPed*)shooter; if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) return; - + int16 lastEntity; CEntity *entities[16]; CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, false, true, false, false); float closestEntityDist = 10000.0f; int16 closestEntity; - + for ( int32 i = 0; i < lastEntity; i++ ) { CEntity *victim = entities[i]; - ASSERT(victim!=NULL); - + ASSERT(victim!=nil); + if ( shooter != victim ) { float lineDist = CCollision::DistToLine(source, target, &victim->GetPosition()); float distToVictim = (victim->GetPosition() - shooter->GetPosition()).Magnitude(); float pedDist = 0.15f*distToVictim + lineDist; - + if ( DotProduct((*target-*source), victim->GetPosition()-*source) > 0.0f && pedDist < closestEntityDist) { closestEntity = i; @@ -1945,12 +1946,12 @@ CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) } } } - + if ( closestEntityDist < DRIVEBYAUTOAIMING_MAXDIST ) { CEntity *victim = entities[closestEntity]; - ASSERT(victim!=NULL); - + ASSERT(victim!=nil); + float distToTarget = (*source - *target).Magnitude(); float distToSource = (*source - victim->GetPosition()).Magnitude(); *target = (distToTarget / distToSource) * (victim->GetPosition() - *source) + *source; @@ -1981,7 +1982,7 @@ CWeapon::Update(int32 audioEntity) m_eWeaponState = WEAPONSTATE_READY; break; } - + case WEAPONSTATE_FIRING: { if ( m_eWeaponType == WEAPONTYPE_SHOTGUN && AEHANDLE_IS_OK(audioEntity) ) @@ -1990,7 +1991,7 @@ CWeapon::Update(int32 audioEntity) if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); } - + if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) { if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE && m_nAmmoTotal == 0 ) @@ -1998,10 +1999,10 @@ CWeapon::Update(int32 audioEntity) else m_eWeaponState = WEAPONSTATE_READY; } - + break; } - + case WEAPONSTATE_RELOADING: { if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_LAST_WEAPONTYPE ) @@ -2010,13 +2011,13 @@ CWeapon::Update(int32 audioEntity) if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); } - + if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) { Reload(); m_eWeaponState = WEAPONSTATE_READY; } - + break; } } @@ -2025,21 +2026,21 @@ CWeapon::Update(int32 audioEntity) void FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) { - ASSERT(source!=NULL); - ASSERT(target!=NULL); - + ASSERT(source!=nil); + ASSERT(target!=nil); + CParticle::AddParticle(PARTICLE_GUNFLASH, *source, CVector(0.0f, 0.0f, 0.0f)); - + CPointLights::AddLight(CPointLights::LIGHT_POINT, *source, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CColPoint point; CEntity *victim; CWorld::ProcessLineOfSight(*source, *target, point, victim, true, true, true, true, true, true, false); - + CParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, (*target) - (*source) * 0.15f); - + if ( victim ) { if ( victim->IsPed() ) @@ -2048,21 +2049,21 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) if ( !victimPed->DyingOrDead() ) { CVector pos = victimPed->GetPosition(); - + CVector2D posOffset((*source).x-pos.x, (*source).y-pos.y); int32 localDir = victimPed->GetLocalDirection(posOffset); - + victimPed->ClearAttackByRemovingAnim(); - + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); - ASSERT(asoc!=NULL); + ASSERT(asoc!=nil); asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; - - victimPed->InflictDamage(NULL, WEAPONTYPE_UZI, damage, (ePedPieceTypes)point.pieceB, localDir); - + + victimPed->InflictDamage(nil, WEAPONTYPE_UZI, damage, (ePedPieceTypes)point.pieceB, localDir); + pos.z += 0.8f; - + if ( victimPed->GetIsOnScreen() ) { if ( CGame::nastyGame ) @@ -2073,7 +2074,7 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) dir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); dir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); dir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); - + CParticle::AddParticle(PARTICLE_BLOOD, pos, dir); } } @@ -2081,9 +2082,9 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) } } else if ( victim->IsVehicle() ) - ((CVehicle *)victim)->InflictDamage(NULL, WEAPONTYPE_UZI, damage); + ((CVehicle *)victim)->InflictDamage(nil, WEAPONTYPE_UZI, damage); //BUG ? no CGlass::WasGlassHitByBullet - + switch ( victim->m_type ) { case ENTITY_TYPE_BUILDING: @@ -2141,21 +2142,21 @@ CWeapon::IsType2Handed(void) void CWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target) { - ASSERT(shooter!=NULL); - ASSERT(source!=NULL); - ASSERT(target!=NULL); - + ASSERT(shooter!=nil); + ASSERT(source!=nil); + ASSERT(target!=nil); + float minx = min(source->x, target->x) - 2.0f; float maxx = max(source->x, target->x) + 2.0f; float miny = min(source->y, target->y) - 2.0f; float maxy = max(source->y, target->y) + 2.0f; float minz = min(source->z, target->z) - 2.0f; float maxz = max(source->z, target->z) + 2.0f; - + for ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) { CPed *ped = CPools::GetPedPool()->GetSlot(i); - + if ( ped ) { if ( ped->GetPosition().x > minx && ped->GetPosition().x < maxx @@ -2172,14 +2173,14 @@ CWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target bool CWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo) { - ASSERT(holder!=NULL); - ASSERT(aimingTo!=NULL); - + ASSERT(holder!=nil); + ASSERT(aimingTo!=nil); + if (!holder->IsPed() || !((CPed*)holder)->m_pSeekTarget) return false; CWeaponInfo *info = GetInfo(); - + CVector adjustedOffset = info->m_vecFireOffset; adjustedOffset.z += 0.6f; @@ -2193,8 +2194,8 @@ CWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo) source = holder->GetMatrix() * adjustedOffset; CEntity *aimEntity = aimingTo ? aimingTo : ((CPed*)holder)->m_pSeekTarget; - ASSERT(aimEntity!=NULL); - + ASSERT(aimEntity!=nil); + target = aimEntity->GetPosition(); target.z += 0.6f; @@ -2219,17 +2220,17 @@ CWeapon::BlowUpExplosiveThings(CEntity *thing) if ( IsExplosiveThingModel(mi) && !object->bHasBeenDamaged ) { object->bHasBeenDamaged = true; - + CExplosion::AddExplosion(object, FindPlayerPed(), EXPLOSION_BARREL, object->GetPosition()+CVector(0.0f,0.0f,0.5f), 100); - + if ( MI_EXPLODINGBARREL == mi ) object->m_vecMoveSpeed.z += 0.75f; else object->m_vecMoveSpeed.z += 0.45f; - + object->m_vecMoveSpeed.x += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f; object->m_vecMoveSpeed.y += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f; - + if ( object->bIsStatic ) { object->bIsStatic = false; @@ -2250,7 +2251,7 @@ CWeapon::HasWeaponAmmoToBeUsed(void) return m_nAmmoTotal != 0; } } - + bool CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) { From 708d247c982c7a95620723e520c718afd2058690 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 19:53:08 +0300 Subject: [PATCH 020/123] 'fix' fix --- src/weapons/Weapon.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index b0c9b61f..fbd25f81 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -30,23 +30,22 @@ #include "WeaponInfo.h" #include "World.h" -uint16 gReloadSampleTime[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS] = +uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] = { - 0, // UNARMED - 0, // BASEBALLBAT - 250, // COLT45 - 400, // UZI - 650, // SHOTGUN - 300, // AK47 - 300, // M16 - 423, // SNIPERRIFLE - 400, // ROCKETLAUNCHER - 0, // FLAMETHROWER - 0, // MOLOTOV - 0, // GRENADE - 0, // DETONATOR - - 0 // WEAPONTYPE_HELICANNON + 0, // UNARMED + 0, // BASEBALLBAT + 250, // COLT45 + 400, // UZI + 650, // SHOTGUN + 300, // AK47 + 300, // M16 + 423, // SNIPERRIFLE + 400, // ROCKETLAUNCHER + 0, // FLAMETHROWER + 0, // MOLOTOV + 0, // GRENADE + 0, // DETONATOR + 0 // HELICANNON }; CWeaponInfo * From cb4e1d68e77a7fd7f17563d0522eeb2f0c39e94d Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 20:09:51 +0300 Subject: [PATCH 021/123] glass NULL->nil --- src/render/Glass.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index 46a12a6f..ac6c1728 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -404,7 +404,7 @@ CGlass::AskForObjectToBeRenderedInGlass(CEntity *entity) void CGlass::RenderEntityInGlass(CEntity *entity) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; if ( object->bGlassBroken ) @@ -420,7 +420,7 @@ CGlass::RenderEntityInGlass(CEntity *entity) uint8 alpha = CalcAlphaWithNormal(&fwdNorm); CColModel *col = object->GetColModel(); - ASSERT(col!=NULL); + ASSERT(col!=nil); if ( col->numTriangles >= 2 ) { CVector a = object->GetMatrix() * col->vertices[0]; @@ -524,7 +524,7 @@ CGlass::RenderEntityInGlass(CEntity *entity) int32 CGlass::CalcAlphaWithNormal(CVector *normal) { - ASSERT(normal!=NULL); + ASSERT(normal!=nil); float fwdDir = 2.0f * DotProduct(*normal, TheCamera.GetForward()); float fwdDot = DotProduct(TheCamera.GetForward()-fwdDir*(*normal), CVector(0.57f, 0.57f, -0.57f)); @@ -600,7 +600,7 @@ CGlass::RenderReflectionPolys(void) void CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector point, bool explosion) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; @@ -610,7 +610,7 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, object->bGlassCracked = true; CColModel *col = object->GetColModel(); - ASSERT(col!=NULL); + ASSERT(col!=nil); CVector a = object->GetMatrix() * col->vertices[0]; CVector b = object->GetMatrix() * col->vertices[1]; @@ -653,7 +653,7 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, void CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; @@ -667,7 +667,7 @@ CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) void CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; @@ -689,7 +689,7 @@ CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) void CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; From c3647ee51e05df419ebb456416cb84e7f902e581 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 20:34:58 +0300 Subject: [PATCH 022/123] rem comment --- src/peds/PlayerPed.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index c6823c2d..f96d8e6a 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -21,7 +21,7 @@ public: int8 field_1367; uint32 m_nSpeedTimer; uint32 m_nHitAnimDelayTimer; - float m_fAttackButtonCounter; // m_fAttackButtonCounter? + float m_fAttackButtonCounter; bool m_bHaveTargetSelected; // may have better name int8 field_1381; int8 field_1382; From a9713125dc6d7857e14da8ea50d4ac4f37e6c8db Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 20:58:28 +0300 Subject: [PATCH 023/123] fixed uzi/ak47/m16 trace --- src/weapons/Weapon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index fbd25f81..96f86989 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -856,7 +856,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, { CGlass::WasGlassHitByBullet(victim, point->point); - CVector traceTarget = *target; + CVector traceTarget = point->point; CBulletTraces::AddTrace(source, &traceTarget); if ( shooter != nil ) From 190bc696d898f77c7355a0d919add8ab4f232b15 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 21:29:00 +0300 Subject: [PATCH 024/123] fixed crash --- src/weapons/Weapon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 96f86989..7b6b4170 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -2038,7 +2038,7 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) CEntity *victim; CWorld::ProcessLineOfSight(*source, *target, point, victim, true, true, true, true, true, true, false); - CParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, (*target) - (*source) * 0.15f); + CParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, ((*target) - (*source)) * 0.15f); if ( victim ) { From 2a96846eac58bd9b0c7ac87f6e7c1ab8356280d0 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 15 Apr 2020 23:48:08 +0300 Subject: [PATCH 025/123] anim fix --- src/weapons/BulletInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp index d975c464..9e83a4ec 100644 --- a/src/weapons/BulletInfo.cpp +++ b/src/weapons/BulletInfo.cpp @@ -114,7 +114,7 @@ void CBulletInfo::Update(void) } } if (CGame::nastyGame) { - CVector vecParticleDirection = (point.point - pPed->GetPosition()) / 100; + CVector vecParticleDirection = (point.point - pPed->GetPosition()) * 0.01f; vecParticleDirection.z = 0.01f; if (pPed->GetIsOnScreen()) { for (int j = 0; j < NUM_PED_BLOOD_PARTICLES; j++) @@ -129,7 +129,7 @@ void CBulletInfo::Update(void) if (pAnim) { pAnim->SetCurrentTime(0.0f); pAnim->flags |= ASSOC_RUNNING; - pAnim->flags &= ASSOC_FADEOUTWHENDONE; + pAnim->flags &= ~ASSOC_FADEOUTWHENDONE; } } pBullet->m_bInUse = false; From 480573452eb7bfe938b15d89b03560aab9e668ee Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 15 Apr 2020 23:49:23 +0300 Subject: [PATCH 026/123] definition fix --- src/weapons/BulletInfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weapons/BulletInfo.h b/src/weapons/BulletInfo.h index 51954565..ae773b04 100644 --- a/src/weapons/BulletInfo.h +++ b/src/weapons/BulletInfo.h @@ -18,7 +18,7 @@ public: }; static void Initialise(void); static void Shutdown(void); - static bool AddBullet(CEntity*, eWeaponType, CVector, CVector); + static bool AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosition, CVector vecSpeed); static void Update(void); static bool TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2); }; \ No newline at end of file From e0394a1558f5245fb2fda68d85cd30aa07de2576 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 16 Apr 2020 00:00:04 +0300 Subject: [PATCH 027/123] vs botch --- src/weapons/BulletInfo.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/weapons/BulletInfo.h b/src/weapons/BulletInfo.h index ae773b04..c7d740b2 100644 --- a/src/weapons/BulletInfo.h +++ b/src/weapons/BulletInfo.h @@ -5,20 +5,20 @@ enum eWeaponType; class CBulletInfo { - eWeaponType m_eWeaponType; - CEntity* m_pSource; - float m_fTimer; // big mistake - bool m_bInUse; - CVector m_vecPosition; - CVector m_vecSpeed; - int16 m_nDamage; + eWeaponType m_eWeaponType; + CEntity* m_pSource; + float m_fTimer; // big mistake + bool m_bInUse; + CVector m_vecPosition; + CVector m_vecSpeed; + int16 m_nDamage; public: - enum { - NUM_BULLETS = 100 - }; + enum { + NUM_BULLETS = 100 + }; static void Initialise(void); static void Shutdown(void); - static bool AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosition, CVector vecSpeed); + static bool AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosition, CVector vecSpeed); static void Update(void); static bool TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2); }; \ No newline at end of file From 3517f3f1a1c41d3a5334f8676c60f7cb87d4bc4c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 16 Apr 2020 00:31:57 +0300 Subject: [PATCH 028/123] fix script crash --- src/control/Script.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 83d072f3..d1134b7c 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -10076,8 +10076,8 @@ void CRunningScript::LocatePlayerCarCommand(int32 command, uint32* pIp) case COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D: result = !pPlayerInfo->m_pPed->bInVehicle; break; - case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D: - case COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D: + case COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D: result = pPlayerInfo->m_pPed->bInVehicle; break; default: From a8f0d77b873e3c8dff22e60acd00bffecaf1fc50 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 16 Apr 2020 00:33:11 +0300 Subject: [PATCH 029/123] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 53f2136a..9b5f09b1 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ to reverse at the time, calling the original functions is acceptable. ### Unreversed / incomplete classes (at least the ones we know) ``` -CBulletInfo CWeapon CWorld ``` From 378f1d180d8736cdc55eedcb36b9a2d59796f1e0 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 16 Apr 2020 00:33:57 +0300 Subject: [PATCH 030/123] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 53f2136a..17b00862 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ to reverse at the time, calling the original functions is acceptable. ### Unreversed / incomplete classes (at least the ones we know) ``` CBulletInfo -CWeapon CWorld ``` @@ -41,7 +40,6 @@ The following classes have only unused or practically unused code left: ``` CCullZone - only mobile stuff CCullZones - only mobile stuff -CSceneEdit ``` ### Coding style From d455cd8a62639145d7b5c03ada6fc84d2ad8ac36 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 16 Apr 2020 00:44:25 +0300 Subject: [PATCH 031/123] Default native resolution mode and small camera fixes --- src/core/Camera.cpp | 8 ++++++++ src/core/Camera.h | 4 ++-- src/core/config.h | 1 + src/core/main.cpp | 5 +++++ src/save/GenericGameStorage.cpp | 19 +++++++++++++++++++ src/skel/win/win.cpp | 29 +++++++++++++++++++++++++---- 6 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 91dd6573..c7fa41e4 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -2183,13 +2183,21 @@ CCamera::DrawBordersForWideScreen(void) SetMotionBlurAlpha(80); CSprite2d::DrawRect( +#ifdef FIX_BUGS + CRect(0.0f, (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - SCREEN_SCALE_Y(8.0f), +#else CRect(0.0f, (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - 8.0f, +#endif SCREEN_WIDTH, 0.0f), CRGBA(0, 0, 0, 255)); CSprite2d::DrawRect( CRect(0.0f, SCREEN_HEIGHT, +#ifdef FIX_BUGS + SCREEN_WIDTH, SCREEN_HEIGHT - (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - SCREEN_SCALE_Y(8.0f)), +#else SCREEN_WIDTH, SCREEN_HEIGHT - (SCREEN_HEIGHT/2) * m_ScreenReductionPercentage/100.0f - 8.0f), +#endif CRGBA(0, 0, 0, 255)); } diff --git a/src/core/Camera.h b/src/core/Camera.h index eca4518a..09a8d603 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -415,7 +415,7 @@ uint32 unknown; // some counter having to do with music float CamFrontXNorm; float CamFrontYNorm; -#if 0 // TODO: FIX_BUGS once GenericLoad is done +#ifdef FIX_BUGS int32 CarZoomIndicator; #else float CarZoomIndicator; @@ -455,7 +455,7 @@ uint32 unknown; // some counter having to do with music float m_ScreenReductionSpeed; float m_AlphaForPlayerAnim1rstPerson; float Orientation; -#if 0 // TODO: FIX_BUGS once GenericLoad is done +#ifdef FIX_BUGS int32 PedZoomIndicator; #else float PedZoomIndicator; diff --git a/src/core/config.h b/src/core/config.h index f7fde579..38e7679f 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -189,6 +189,7 @@ enum Config { #define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more #define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things #define MORE_LANGUAGES // Add more translations to the game +#define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) // Pad #define XINPUT diff --git a/src/core/main.cpp b/src/core/main.cpp index b028b5fb..08463df9 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -240,8 +240,13 @@ DoFade(void) float y = SCREEN_HEIGHT/2 * TheCamera.m_ScreenReductionPercentage/100.0f; rect.left = 0.0f; rect.right = SCREEN_WIDTH; +#ifdef FIX_BUGS + rect.top = y - SCREEN_SCALE_Y(8.0f); + rect.bottom = SCREEN_HEIGHT - y - SCREEN_SCALE_Y(8.0f); +#else rect.top = y - 8.0f; rect.bottom = SCREEN_HEIGHT - y - 8.0f; +#endif // FIX_BUGS }else{ rect.left = 0.0f; rect.right = SCREEN_WIDTH; diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 0ec0b117..1e4acd3d 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -154,8 +154,17 @@ GenericSave(int file) WriteDataToBufferPointer(buf, CompileDateAndTime.m_nMonth); WriteDataToBufferPointer(buf, CompileDateAndTime.m_nYear); WriteDataToBufferPointer(buf, CWeather::WeatherTypeInList); +#ifdef FIX_BUGS + // converted to float for compatibility with original format + // TODO: maybe remove this? not really gonna break anything vital + float f = TheCamera.CarZoomIndicator; + WriteDataToBufferPointer(buf, f); + f = TheCamera.PedZoomIndicator; + WriteDataToBufferPointer(buf, f); +#else WriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator); WriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator); +#endif assert(buf - work_buff == SIZE_OF_SIMPLEVARS); // Save scripts, block is nested within the same block as simple vars for some reason @@ -264,8 +273,18 @@ GenericLoad() ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMonth); ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nYear); ReadDataFromBufferPointer(buf, CWeather::WeatherTypeInList); +#ifdef FIX_BUGS + // converted to float for compatibility with original format + // TODO: maybe remove this? not really gonna break anything vital + float f; + ReadDataFromBufferPointer(buf, f); + TheCamera.CarZoomIndicator = f; + ReadDataFromBufferPointer(buf, f); + TheCamera.PedZoomIndicator = f; +#else ReadDataFromBufferPointer(buf, TheCamera.CarZoomIndicator); ReadDataFromBufferPointer(buf, TheCamera.PedZoomIndicator); +#endif assert(buf - work_buff == SIZE_OF_SIMPLEVARS); ReadDataFromBlock("Loading Scripts \n", CTheScripts::LoadAllScripts); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index ec84e968..acc9650c 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -679,11 +679,17 @@ psInitialise(void) _dwMemAvailVirtual = memstats.dwAvailVirtual; _GetVideoMemInfo(&_dwMemTotalVideo, &_dwMemAvailVideo); - +#ifdef FIX_BUGS + debug("Physical memory size %u\n", _dwMemTotalPhys); + debug("Available physical memory %u\n", _dwMemAvailPhys); + debug("Video memory size %u\n", _dwMemTotalVideo); + debug("Available video memory %u\n", _dwMemAvailVideo); +#else debug("Physical memory size %d\n", _dwMemTotalPhys); debug("Available physical memory %d\n", _dwMemAvailPhys); debug("Video memory size %d\n", _dwMemTotalVideo); debug("Available video memory %d\n", _dwMemAvailVideo); +#endif if ( _dwMemAvailVideo < (12 * 1024 * 1024) /*12 MB*/ ) { @@ -1321,12 +1327,23 @@ psSelectDevice() } else { +#ifdef DEFAULT_NATIVE_RESOLUTION + // get the native video mode + HDC hDevice = GetDC(NULL); + int w = GetDeviceCaps(hDevice, HORZRES); + int h = GetDeviceCaps(hDevice, VERTRES); + int d = GetDeviceCaps(hDevice, BITSPIXEL); +#else + const int w = 640; + const int h = 480; + const int d = 16; +#endif while ( !modeFound && GcurSelVM < RwEngineGetNumVideoModes() ) { RwEngineGetVideoModeInfo(&vm, GcurSelVM); - if ( defaultFullscreenRes && vm.width != 640 - || vm.height != 480 - || vm.depth != 16 + if ( defaultFullscreenRes && vm.width != w + || vm.height != h + || vm.depth != d || !(vm.flags & rwVIDEOMODEEXCLUSIVE) ) ++GcurSelVM; else @@ -1335,8 +1352,12 @@ psSelectDevice() if ( !modeFound ) { +#ifdef DEFAULT_NATIVE_RESOLUTION + GcurSelVM = 1; +#else MessageBox(nil, "Cannot find 640x480 video mode", "GTA3", MB_OK); return FALSE; +#endif } } } From 1fd7b0288c00486721faaff6af4d9d36ebe9b57d Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 16 Apr 2020 01:19:08 +0300 Subject: [PATCH 032/123] fix Bait crash --- src/control/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index d1134b7c..428ac66a 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -9147,7 +9147,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) } case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER: { - CollectParameters(&m_nIp, 2); + CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, FindPlayerCoors(), false); From b9a8ad94816ac27ce6a669807e0eb60c7e35f037 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 16 Apr 2020 01:44:02 +0300 Subject: [PATCH 033/123] Fix misplaced targeting --- src/render/Hud.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index f8b86bd2..9529c4c1 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -144,12 +144,10 @@ void CHud::Draw() float fMultBright = SpriteBrightness * 0.03f * (0.25f * fStep + 0.75f); CRect rect; if (DrawCrossHairPC && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()) { -#ifndef ASPECT_RATIO_SCALE float f3rdX = SCREEN_WIDTH * TheCamera.m_f3rdPersonCHairMultX; float f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY; -#else - 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); +#ifdef ASPECT_RATIO_SCALE + f3rdY -= SCREEN_SCALE_Y(2.0f); #endif if (FindPlayerPed() && WeaponType == WEAPONTYPE_M16) { rect.left = f3rdX - SCREEN_SCALE_X(32.0f * 0.6f); From f435455bdee2bbe6a55f12fb8854659260b7a559 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 16 Apr 2020 01:56:15 +0300 Subject: [PATCH 034/123] Removed refs from weapons/, WeaponEffects moved --- src/weapons/Explosion.cpp | 2 +- src/weapons/Explosion.h | 2 +- src/weapons/ProjectileInfo.cpp | 4 ++-- src/weapons/ProjectileInfo.h | 8 ++++---- src/{render => weapons}/WeaponEffects.cpp | 0 src/{render => weapons}/WeaponEffects.h | 0 6 files changed, 8 insertions(+), 8 deletions(-) rename src/{render => weapons}/WeaponEffects.cpp (100%) rename src/{render => weapons}/WeaponEffects.h (100%) diff --git a/src/weapons/Explosion.cpp b/src/weapons/Explosion.cpp index 3d00052a..02243702 100644 --- a/src/weapons/Explosion.cpp +++ b/src/weapons/Explosion.cpp @@ -19,7 +19,7 @@ #include "WaterLevel.h" #include "World.h" -CExplosion(&gaExplosion)[NUM_EXPLOSIONS] = *(CExplosion(*)[NUM_EXPLOSIONS])*(uintptr*)0x64E208; +CExplosion gaExplosion[NUM_EXPLOSIONS]; // these two were not initialised in original code, I'm really not sure what were they meant to be RwRGBA colMedExpl = { 0, 0, 0, 0 }; diff --git a/src/weapons/Explosion.h b/src/weapons/Explosion.h index 45e2d5bb..bf54328c 100644 --- a/src/weapons/Explosion.h +++ b/src/weapons/Explosion.h @@ -46,4 +46,4 @@ public: static void RemoveAllExplosionsInArea(CVector pos, float radius); }; -extern CExplosion (&gaExplosion)[NUM_EXPLOSIONS]; \ No newline at end of file +extern CExplosion gaExplosion[NUM_EXPLOSIONS]; \ No newline at end of file diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp index b33d2d62..8f04278c 100644 --- a/src/weapons/ProjectileInfo.cpp +++ b/src/weapons/ProjectileInfo.cpp @@ -13,8 +13,8 @@ #include "Weapon.h" #include "World.h" -CProjectileInfo (&gaProjectileInfo)[NUM_PROJECTILES] = *(CProjectileInfo(*)[NUM_PROJECTILES])*(uintptr*)0x64ED50; -CProjectile* (&CProjectileInfo::ms_apProjectile)[NUM_PROJECTILES] = *(CProjectile*(*)[NUM_PROJECTILES])*(uintptr*)0x87C748; +CProjectileInfo gaProjectileInfo[NUM_PROJECTILES]; +CProjectile *CProjectileInfo::ms_apProjectile[NUM_PROJECTILES]; void CProjectileInfo::Initialise() diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h index a4ea369a..b88322f9 100644 --- a/src/weapons/ProjectileInfo.h +++ b/src/weapons/ProjectileInfo.h @@ -9,14 +9,14 @@ class CProjectileInfo { public: eWeaponType m_eWeaponType; - CEntity* m_pSource; + CEntity *m_pSource; uint32 m_nExplosionTime; bool m_bInUse; CVector m_vecPos; public: - static CProjectileInfo* GetProjectileInfo(int32 id); - static CProjectile* (&ms_apProjectile)[NUM_PROJECTILES]; + static CProjectileInfo *GetProjectileInfo(int32 id); + static CProjectile *ms_apProjectile[NUM_PROJECTILES]; static void Initialise(); static void Shutdown(); @@ -29,4 +29,4 @@ public: static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove); }; -extern CProjectileInfo (&gaProjectileInfo)[NUM_PROJECTILES]; \ No newline at end of file +extern CProjectileInfo gaProjectileInfo[NUM_PROJECTILES]; \ No newline at end of file diff --git a/src/render/WeaponEffects.cpp b/src/weapons/WeaponEffects.cpp similarity index 100% rename from src/render/WeaponEffects.cpp rename to src/weapons/WeaponEffects.cpp diff --git a/src/render/WeaponEffects.h b/src/weapons/WeaponEffects.h similarity index 100% rename from src/render/WeaponEffects.h rename to src/weapons/WeaponEffects.h From 5993c66efbf160e47beedb2b594e3a9a56f737e5 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 16 Apr 2020 01:59:19 +0300 Subject: [PATCH 035/123] Fixed bridge despawns --- src/peds/Population.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index e26e2eaf..d3a67a57 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -35,17 +35,17 @@ const RegenerationPoint aSafeZones[] = { CVector(790.0f, -917.0f, 39.0f), CVector(775.0f, -921.0f, 39.0f), CVector(424.0f, -942.0f, 38.0f), CVector(439.0f, -938.0f, 38.0f) }, { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 555.0f, 711.0f, 118.0f, 186.0f, -30.0f, -10.0f, CVector(698.0f, 182.0f, -20.0f), CVector(681.0f, 178.0f, -20.0f), CVector(586.0f, 144.0f, -20.0f), CVector(577.0f, 135.0f, -20.0f) }, - { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 26.0f, 44.0f, 124.0f, 87.0f, 20.0f, 6.0f, + { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 626.0f, 744.0f, -124.0f, -87.0f, -20.0f, -6.0f, CVector(736.0f, -117.0f, -13.0f), CVector(730.0f, -115.0f, -13.0f), CVector(635.0f, -93.0f, -12.5f), CVector(650.0f, -89.0f, -12.5f) }, - { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 45.0f, 34.0f, 780.0f, 750.0f, 25.0f, 6.0f, + { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 645.0f, 734.0f, -780.0f, -750.0f, -25.0f, -6.0f, CVector(729.0f, -764.0f, -18.0f), CVector(720.0f, -769.0f, -17.0f), CVector(652.0f, -774.0f, -10.5f), CVector(659.0f, -770.0f, -10.5f) }, - { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 532.0f, 136.0f, 668.0f, 599.0f, 4.0f, 0.0f, + { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -532.0f, -136.0f, -668.0f, -599.0f, 34.0f, 60.0f, CVector(-172.0f, -619.0f, 44.0f), CVector(-183.0f, -623.0f, 44.0f), CVector(-511.0f, -645.0f, 41.0f), CVector(-493.0f, -639.0f, 41.5f) }, - { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 325.0f, 175.0f, 7.0f, 5.0f, 30.0f, 10.0f, + { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -325.0f, -175.0f, 27.0f, 75.0f, -30.0f, -10.0f, CVector(-185.0f, 40.8f, -20.5f), CVector(-202.0f, 37.0f, -20.5f), CVector(-315.0f, 65.5f, -20.5f), CVector(-306.0f, 62.4f, -20.5f) }, - { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 410.0f, 310.0f, 1055.0f, 1030.0f, 20.0f, 6.0f, + { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -410.0f, -310.0f, -1055.0f, -1030.0f, -20.0f, -6.0f, CVector(-321.0f, -1043.0f, -13.2f), CVector(-328.0f, -1045.0f, -13.2f), CVector(-398.0f, -1044.0f, -13.5f), CVector(-390.0f, -1040.5f, -13.5f) }, - { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 425.0f, 280.0f, 471.0f, 447.0f, 20.0f, 5.0f, + { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -425.0f, -280.0f, -471.0f, -447.0f, -20.0f, -5.0f, CVector(-292.0f, -457.0f, -11.6f), CVector(-310.0f, -461.0f, -11.6f), CVector(-413.0f, -461.0f, -11.5f), CVector(-399.0f, -457.0f, -11.3f) } }; From c22e59abab331376cdc8557a863eb2584b4bef4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Thu, 16 Apr 2020 05:07:32 +0300 Subject: [PATCH 036/123] Various fixes --- src/audio/AudioManager.cpp | 3 +++ src/core/Frontend.cpp | 1 + src/weapons/Weapon.cpp | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 1d2835cf..246b1bda 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -9132,6 +9132,9 @@ cAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams *params) CVehicle *veh = params->m_pVehicle; if(veh->m_bSirenOrAlarm == 0 && veh->m_nAlarmState <= 0) return; +#ifdef FIX_BUGS + if (params->m_pVehicle->m_status == STATUS_WRECKED) return; +#endif CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); m_sQueueSample.m_bVolume = ComputeVolume(80, 110.f, m_sQueueSample.m_fDistance); if(m_sQueueSample.m_bVolume) { diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 166ecb35..a01689e4 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5246,6 +5246,7 @@ CMenuManager::PrintController(void) void CMenuManager::PrintMap(void) { + CFont::SetJustifyOn(); bMenuMapActive = true; CRadar::InitFrontEndMap(); diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 7b6b4170..98154e93 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -2162,7 +2162,7 @@ CWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target && ped->GetPosition().y > miny && ped->GetPosition().y < maxy && ped->GetPosition().z > minz && ped->GetPosition().z < maxz ) { - if ( ped != FindPlayerPed() && (uint8)(ped->m_randomSeed ^ CGeneral::GetRandomNumber()) & 31 ) + if ( ped != FindPlayerPed() && !((uint8)(ped->m_randomSeed ^ CGeneral::GetRandomNumber()) & 31) ) ped->SetEvasiveDive(shooter, 1); } } From c1fcb7bd43fc1fd7e867e1e76f63d28e0ad7b8f1 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Thu, 16 Apr 2020 08:28:17 +0300 Subject: [PATCH 037/123] Removed refs from sampman --- src/audio/sampman.cpp | 98 ++++++++++++++----------------------------- src/audio/sampman.h | 4 +- 2 files changed, 33 insertions(+), 69 deletions(-) diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index 6edb6028..6dd744c3 100644 --- a/src/audio/sampman.cpp +++ b/src/audio/sampman.cpp @@ -17,9 +17,8 @@ #pragma comment( lib, "mss32.lib" ) -cSampleManager &SampleManager = *(cSampleManager *)0x7341E0; -extern int32 (&BankStartOffset)[MAX_SAMPLEBANKS] = *(int32 (*)[MAX_SAMPLEBANKS])*(int *)0x6FAB70; - +cSampleManager SampleManager; +int32 BankStartOffset[MAX_SAMPLEBANKS]; /////////////////////////////////////////////////////////////// char SampleBankDescFilename[] = "AUDIO\\SFX.SDT"; @@ -116,7 +115,7 @@ typedef struct provider_stuff static int __cdecl comp(const provider_stuff*s1,const provider_stuff*s2) { - return(strcasecmp(s1->name, s2->name)); + return( _stricmp(s1->name,s2->name) ); } static void @@ -435,21 +434,17 @@ _FindMP3s(void) OutputDebugString("Resolving Link"); OutputDebugString(filepath); - if ( f ) - fprintf(f, " - shortcut to \"%s\"", filepath); + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); } else { - if ( f ) - fprintf(f, " - couldn't resolve shortcut"); + if ( f ) fprintf(f, " - couldn't resolve shortcut"); } bShortcut = true; } else - { bShortcut = false; - } } mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); @@ -494,8 +489,7 @@ _FindMP3s(void) _pMP3List->pLinkPath = NULL; } - if ( f ) - fprintf(f, " - OK\n"); + if ( f ) fprintf(f, " - OK\n"); bInitFirstEntry = false; } @@ -505,8 +499,7 @@ _FindMP3s(void) OutputDebugString(filepath); - if ( f ) - fprintf(f, " - not an MP3 or supported MP3 type\n"); + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); bInitFirstEntry = true; } @@ -514,17 +507,7 @@ _FindMP3s(void) while ( true ) { if ( !FindNextFile(hFind, &fd) ) - { - if ( f ) - { - fprintf(f, "\nTOTAL SUPPORTED MP3s: %d\n", nNumMP3s); - fclose(f); - } - - FindClose(hFind); - - return; - } + break; if ( bInitFirstEntry ) { @@ -533,8 +516,7 @@ _FindMP3s(void) int32 filepathlen = strlen(filepath); - if ( f ) - fprintf(f, "\"%s\"", fd.cFileName); + if ( f ) fprintf(f, "\"%s\"", fd.cFileName); if ( filepathlen > 0 ) { @@ -547,13 +529,11 @@ _FindMP3s(void) OutputDebugString("Resolving Link"); OutputDebugString(filepath); - if ( f ) - fprintf(f, " - shortcut to \"%s\"", filepath); + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); } else { - if ( f ) - fprintf(f, " - couldn't resolve shortcut"); + if ( f ) fprintf(f, " - couldn't resolve shortcut"); } bShortcut = true; @@ -564,8 +544,7 @@ _FindMP3s(void) if ( filepathlen > MAX_PATH ) { - if ( f ) - fprintf(f, " - Filename and path too long - %s - IGNORED)\n", filepath); + if ( f ) fprintf(f, " - Filename and path too long - %s - IGNORED)\n", filepath); continue; } @@ -585,15 +564,7 @@ _FindMP3s(void) _pMP3List = new tMP3Entry; if ( _pMP3List == NULL) - { - if ( f ) - { - fprintf(f, "\nTOTAL SUPPORTED MP3s: %d\n", nNumMP3s); - fclose(f); - } - FindClose(hFind); - return; - } + break; nNumMP3s = 1; @@ -614,8 +585,7 @@ _FindMP3s(void) pList = _pMP3List; - if ( f ) - fprintf(f, " - OK\n"); + if ( f ) fprintf(f, " - OK\n"); bInitFirstEntry = false; } @@ -624,8 +594,7 @@ _FindMP3s(void) strcat(filepath, " - NOT A VALID MP3"); OutputDebugString(filepath); - if ( f ) - fprintf(f, " - not an MP3 or supported MP3 type\n"); + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); } } } @@ -638,8 +607,7 @@ _FindMP3s(void) if ( filepathlen > 0 ) { - if ( f ) - fprintf(f, "\"%s\"", fd.cFileName); + if ( f ) fprintf(f, "\"%s\"", fd.cFileName); if ( filepathlen > 4 ) { @@ -650,13 +618,11 @@ _FindMP3s(void) OutputDebugString("Resolving Link"); OutputDebugString(filepath); - if ( f ) - fprintf(f, " - shortcut to \"%s\"", filepath); + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); } else { - if ( f ) - fprintf(f, " - couldn't resolve shortcut"); + if ( f ) fprintf(f, " - couldn't resolve shortcut"); } bShortcut = true; @@ -679,16 +645,8 @@ _FindMP3s(void) tMP3Entry *e = pList->pNext; - if ( e == NULL) - { - if ( f ) - { - fprintf(f, "\nTOTAL SUPPORTED MP3s: %d\n", nNumMP3s); - fclose(f); - } - FindClose(hFind); - return; - } + if ( e == NULL ) + break; pList = pList->pNext; @@ -710,20 +668,26 @@ _FindMP3s(void) OutputDebugString(fd.cFileName); - if ( f ) - fprintf(f, " - OK\n"); + if ( f ) fprintf(f, " - OK\n"); } else { strcat(filepath, " - NOT A VALID MP3"); OutputDebugString(filepath); - if ( f ) - fprintf(f, " - not an MP3 or supported MP3 type\n"); + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); } } } } + + if ( f ) + { + fprintf(f, "\nTOTAL SUPPORTED MP3s: %d\n", nNumMP3s); + fclose(f); + } + + FindClose(hFind); } static void @@ -2257,7 +2221,7 @@ cSampleManager::InitialiseSampleBanks(void) for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) { - if ( BankStartOffset[nBank] == BankStartOffset[0] + i ) + if ( BankStartOffset[nBank] == BankStartOffset[SAMPLEBANK_MAIN] + i ) { nSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset; nBank++; diff --git a/src/audio/sampman.h b/src/audio/sampman.h index 4b546911..4f3c3eeb 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -135,8 +135,8 @@ public: bool InitialiseSampleBanks(void); }; -extern cSampleManager &SampleManager; -extern int32 (&BankStartOffset)[MAX_SAMPLEBANKS]; +extern cSampleManager SampleManager; +extern int32 BankStartOffset[MAX_SAMPLEBANKS]; static char StreamedNameTable[][25]= { From 4b602940eb79c637f70a22046d414a0b1358eea8 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 16 Apr 2020 10:26:16 +0200 Subject: [PATCH 038/123] first fake RW implementation working --- src/core/Game.cpp | 4 ++++ src/core/config.h | 1 + src/fakerw/fake.cpp | 45 +++++++++++++++++++++++++++++++------------- src/fakerw/rpworld.h | 30 ++++++++++++++--------------- src/rw/TexRead.cpp | 11 +++++------ src/rw/rw.cpp | 5 +++++ 6 files changed, 62 insertions(+), 34 deletions(-) diff --git a/src/core/Game.cpp b/src/core/Game.cpp index fe747ac1..8699ffeb 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -307,6 +307,7 @@ bool CGame::Initialise(const char* datFile) CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; LoadingScreen("Loading the Game", "Setup streaming", nil); +#ifdef USE_TXD_CDIMAGE int txdHandle = CFileMgr::OpenFile("MODELS\\TXD.IMG", "r"); if (txdHandle) CFileMgr::CloseFile(txdHandle); @@ -321,6 +322,9 @@ bool CGame::Initialise(const char* datFile) CStreaming::Init(); } } +#else + CStreaming::Init(); +#endif CStreaming::LoadInitialVehicles(); CStreaming::LoadInitialPeds(); CStreaming::RequestBigBuildings(LEVEL_NONE); diff --git a/src/core/config.h b/src/core/config.h index 38e7679f..f684ed3c 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -190,6 +190,7 @@ enum Config { #define TOGGLEABLE_BETA_FEATURES // toggleable from debug menu. not too many things #define MORE_LANGUAGES // Add more translations to the game #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) +//#define USE_TXD_CDIMAGE // generate and load textures from txd.img // Pad #define XINPUT diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 1aaa8d11..b91a9c49 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -178,8 +178,8 @@ RwImage *RwImageWrite(RwImage * image, const RwChar * imageName); RwChar *RwImageGetPath(void); const RwChar *RwImageSetPath(const RwChar * path) { Image::setSearchPath(path); return path; } RwImage *RwImageSetStride(RwImage * image, RwInt32 stride) { image->stride = stride; return image; } -RwImage *RwImageSetPixels(RwImage * image, RwUInt8 * pixels) { image->setPixels(pixels); return image; } -RwImage *RwImageSetPalette(RwImage * image, RwRGBA * palette) { image->setPalette((uint8*)palette); return image; } +RwImage *RwImageSetPixels(RwImage * image, RwUInt8 * pixels) { image->pixels = pixels; return image; } +RwImage *RwImageSetPalette(RwImage * image, RwRGBA * palette) { image->palette = (uint8*)palette; return image; } RwInt32 RwImageGetWidth(const RwImage * image); RwInt32 RwImageGetHeight(const RwImage * image); RwInt32 RwImageGetDepth(const RwImage * image); @@ -252,12 +252,12 @@ RwRaster *RwRasterGetParent(const RwRaster *raster) { return raster->parent; RwRaster *RwRasterGetOffset(RwRaster *raster, RwInt16 *xOffset, RwInt16 *yOffset); RwInt32 RwRasterGetNumLevels(RwRaster * raster); RwRaster *RwRasterSubRaster(RwRaster * subRaster, RwRaster * raster, RwRect * rect); -RwRaster *RwRasterRenderFast(RwRaster * raster, RwInt32 x, RwInt32 y); +RwRaster *RwRasterRenderFast(RwRaster * raster, RwInt32 x, RwInt32 y) { return raster->renderFast(x, y) ? raster : nil; } RwRaster *RwRasterRender(RwRaster * raster, RwInt32 x, RwInt32 y); RwRaster *RwRasterRenderScaled(RwRaster * raster, RwRect * rect); -RwRaster *RwRasterPushContext(RwRaster * raster); -RwRaster *RwRasterPopContext(void); -RwRaster *RwRasterGetCurrentContext(void); +RwRaster *RwRasterPushContext(RwRaster * raster) { return Raster::pushContext(raster); } +RwRaster *RwRasterPopContext(void) { return Raster::popContext(); } +RwRaster *RwRasterGetCurrentContext(void) { return Raster::getCurrentContext(); } RwBool RwRasterClear(RwInt32 pixelValue); RwBool RwRasterClearRect(RwRect * rpRect, RwInt32 pixelValue); RwRaster *RwRasterShowRaster(RwRaster * raster, void *dev, RwUInt32 flags); @@ -378,20 +378,27 @@ RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const v default: return nil; } + // oh god this is horrible. librw streams really need fixing switch(type){ - case rwSTREAMFILENAME: + case rwSTREAMFILENAME:{ + StreamFile fakefile; file = rwNewT(StreamFile, 1, 0); + memcpy(file, &fakefile, sizeof(StreamFile)); if(file->open((char*)pData, mode)) return file; rwFree(file); return nil; - case rwSTREAMMEMORY: + } + case rwSTREAMMEMORY:{ + StreamMemory fakemem; memargs = (RwMemory*)pData; mem = rwNewT(StreamMemory, 1, 0); + memcpy(mem, &fakemem, sizeof(StreamMemory)); if(mem->open(memargs->start, memargs->length)) return mem; rwFree(mem); return nil; + } default: assert(0 && "unknown type"); return nil; @@ -501,7 +508,10 @@ RwBool RwEngineOpen(RwEngineOpenParams *initParams) { openParams.window = (HWND)initParams->displayID; return Engine::open(&openParams); } -RwBool RwEngineStart(void) { return Engine::start(); } +RwBool RwEngineStart(void) { + rw::d3d::isP8supported = false; + return Engine::start(); +} RwBool RwEngineStop(void) { Engine::stop(); return true; } RwBool RwEngineClose(void) { Engine::close(); return true; } RwBool RwEngineTerm(void) { Engine::term(); return true; } @@ -582,9 +592,8 @@ RpLight *RpLightSetColor(RpLight *light, const RwRGBAReal *color) { light->setCo RpGeometry *RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format) { return Geometry::create(numVert, numTriangles, format); } RwBool RpGeometryDestroy(RpGeometry *geometry) { geometry->destroy(); return true; } RpGeometry *_rpGeometryAddRef(RpGeometry *geometry); -// TODO: implement this -RpGeometry *RpGeometryLock(RpGeometry *geometry, RwInt32 lockMode) { return geometry; } -RpGeometry *RpGeometryUnlock(RpGeometry *geometry) { return geometry; } +RpGeometry *RpGeometryLock(RpGeometry *geometry, RwInt32 lockMode) { geometry->lock(lockMode); return geometry; } +RpGeometry *RpGeometryUnlock(RpGeometry *geometry) { geometry->unlock(); return geometry; } RpGeometry *RpGeometryTransform(RpGeometry *geometry, const RwMatrix *matrix); RpGeometry *RpGeometryCreateSpace(RwReal radius); RpMorphTarget *RpMorphTargetSetBoundingSphere(RpMorphTarget *morphTarget, const RwSphere *boundingSphere) { morphTarget->boundingSphere = *boundingSphere; return morphTarget; } @@ -596,7 +605,11 @@ RpGeometry *RpGeometryRemoveMorphTarget(RpGeometry *geometry, RwInt32 morphTarg RwInt32 RpGeometryGetNumMorphTargets(const RpGeometry *geometry); RpMorphTarget *RpGeometryGetMorphTarget(const RpGeometry *geometry, RwInt32 morphTarget) { return &geometry->morphTargets[morphTarget]; } RwRGBA *RpGeometryGetPreLightColors(const RpGeometry *geometry) { return geometry->colors; } -RwTexCoords *RpGeometryGetVertexTexCoords(const RpGeometry *geometry, RwTextureCoordinateIndex uvIndex) { return geometry->texCoords[uvIndex]; } +RwTexCoords *RpGeometryGetVertexTexCoords(const RpGeometry *geometry, RwTextureCoordinateIndex uvIndex) { + if(uvIndex == rwNARWTEXTURECOORDINATEINDEX) + return nil; + return geometry->texCoords[uvIndex-rwTEXTURECOORDINATEINDEX0]; +} RwInt32 RpGeometryGetNumTexCoordSets(const RpGeometry *geometry) { return geometry->numTexCoordSets; } RwInt32 RpGeometryGetNumVertices (const RpGeometry *geometry) { return geometry->numVertices; } RwV3d *RpMorphTargetGetVertices(const RpMorphTarget *morphTarget) { return morphTarget->vertices; } @@ -793,3 +806,9 @@ RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ) { retu RwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName) { rw::writeBMP(image, imageName); return image; } RwImage *RtBMPImageRead(const RwChar * imageName) { return rw::readBMP(imageName); } + + + + +// fake shit +RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags) { return 1; } diff --git a/src/fakerw/rpworld.h b/src/fakerw/rpworld.h index d2ac2454..f10a3754 100644 --- a/src/fakerw/rpworld.h +++ b/src/fakerw/rpworld.h @@ -122,21 +122,21 @@ enum RpGeometryFlag enum RpGeometryLockMode { - rpGEOMETRYLOCKPOLYGONS = 0x01, - rpGEOMETRYLOCKVERTICES = 0x02, - rpGEOMETRYLOCKNORMALS = 0x04, - rpGEOMETRYLOCKPRELIGHT = 0x08, - rpGEOMETRYLOCKTEXCOORDS = 0x10, - rpGEOMETRYLOCKTEXCOORDS1 = 0x10, - rpGEOMETRYLOCKTEXCOORDS2 = 0x20, - rpGEOMETRYLOCKTEXCOORDS3 = 0x40, - rpGEOMETRYLOCKTEXCOORDS4 = 0x80, - rpGEOMETRYLOCKTEXCOORDS5 = 0x0100, - rpGEOMETRYLOCKTEXCOORDS6 = 0x0200, - rpGEOMETRYLOCKTEXCOORDS7 = 0x0400, - rpGEOMETRYLOCKTEXCOORDS8 = 0x0800, - rpGEOMETRYLOCKTEXCOORDSALL = 0x0ff0, - rpGEOMETRYLOCKALL = 0x0fff + rpGEOMETRYLOCKPOLYGONS = rw::Geometry::LOCKPOLYGONS, + rpGEOMETRYLOCKVERTICES = rw::Geometry::LOCKVERTICES, + rpGEOMETRYLOCKNORMALS = rw::Geometry::LOCKNORMALS, + rpGEOMETRYLOCKPRELIGHT = rw::Geometry::LOCKPRELIGHT, + rpGEOMETRYLOCKTEXCOORDS = rw::Geometry::LOCKTEXCOORDS, + rpGEOMETRYLOCKTEXCOORDS1 = rw::Geometry::LOCKTEXCOORDS1, + rpGEOMETRYLOCKTEXCOORDS2 = rw::Geometry::LOCKTEXCOORDS2, + rpGEOMETRYLOCKTEXCOORDS3 = rw::Geometry::LOCKTEXCOORDS3, + rpGEOMETRYLOCKTEXCOORDS4 = rw::Geometry::LOCKTEXCOORDS4, + rpGEOMETRYLOCKTEXCOORDS5 = rw::Geometry::LOCKTEXCOORDS5, + rpGEOMETRYLOCKTEXCOORDS6 = rw::Geometry::LOCKTEXCOORDS6, + rpGEOMETRYLOCKTEXCOORDS7 = rw::Geometry::LOCKTEXCOORDS7, + rpGEOMETRYLOCKTEXCOORDS8 = rw::Geometry::LOCKTEXCOORDS8, + rpGEOMETRYLOCKTEXCOORDSALL = rw::Geometry::LOCKTEXCOORDSALL, + rpGEOMETRYLOCKALL = rw::Geometry::LOCKALL }; RpGeometry *RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format); diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 8ada080d..c91b71c0 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -70,7 +70,9 @@ RwTexDictionaryGtaStreamRead(RwStream *stream) if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version)) return nil; assert(size == 4); - if(RwStreamRead(stream, &numTextures, size) != size) +int foo = RwStreamRead(stream, &numTextures, size); +if(foo != size) +// if(RwStreamRead(stream, &numTextures, size) != size) return nil; texDict = RwTexDictionaryCreate(); @@ -153,11 +155,6 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict) } #ifdef GTA_PC -#ifdef RWLIBS -extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); -#else -WRAPPER RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags) { EAXJMP(0x59A350); } -#endif void ReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8) @@ -177,6 +174,8 @@ ReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8) } } +RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); + bool CheckVideoCardCaps(void) { diff --git a/src/rw/rw.cpp b/src/rw/rw.cpp index 196cf189..c525f49f 100644 --- a/src/rw/rw.cpp +++ b/src/rw/rw.cpp @@ -415,6 +415,9 @@ WRAPPER RxNodeDefinition* RxNodeDefinitionGetMaterialScatter() { EAXJMP(0x5DDAA0 WRAPPER RxNodeDefinition* RxNodeDefinitionGetLight() { EAXJMP(0x5DF040); } WRAPPER RxNodeDefinition* RxNodeDefinitionGetPostLight() { EAXJMP(0x5DF560); } WRAPPER void RxD3D8AllInOneSetRenderCallBack(RxPipelineNode* node, RxD3D8AllInOneRenderCallBack callback) { EAXJMP(0x5DFC60); } + +WRAPPER RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags) { EAXJMP(0x59A350); } + #else extern "C" @@ -433,6 +436,8 @@ extern "C" void* _rwVectorOpen(void* instance, RwInt32 offset, RwInt32 size); RwBool _rwPluginRegistryOpen(); RwBool _rwPluginRegistryClose(); + + RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); } STARTPATCHES From b1fc7bc533dc7d603daafbf8a158a92f710c1e60 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 16 Apr 2020 11:50:45 +0300 Subject: [PATCH 039/123] More refs removed --- src/animation/FrameUpdate.cpp | 2 +- src/animation/RpAnimBlend.h | 2 +- src/audio/MusicManager.cpp | 8 +++--- src/audio/MusicManager.h | 2 +- src/core/Camera.cpp | 1 + src/core/main.h | 3 -- src/rw/Lights.cpp | 20 ++++++------- src/rw/NodeName.cpp | 2 +- src/rw/TexRead.cpp | 12 ++++---- src/rw/TxdStore.cpp | 4 +-- src/rw/TxdStore.h | 4 +-- src/rw/VisibilityPlugins.cpp | 50 +++++++++++++++++---------------- src/rw/VisibilityPlugins.h | 34 +++++++++++----------- src/save/GenericGameStorage.cpp | 28 +++++++++--------- src/save/GenericGameStorage.h | 28 +++++++++--------- src/save/PCSave.cpp | 2 +- src/save/PCSave.h | 2 +- src/text/Messages.cpp | 6 ++-- src/text/Messages.h | 6 ++-- src/text/Text.cpp | 2 +- src/text/Text.h | 2 +- 21 files changed, 111 insertions(+), 109 deletions(-) diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp index dcb71944..393d22a8 100644 --- a/src/animation/FrameUpdate.cpp +++ b/src/animation/FrameUpdate.cpp @@ -6,7 +6,7 @@ #include "AnimBlendAssociation.h" #include "RpAnimBlend.h" -CAnimBlendClumpData *&gpAnimBlendClump = *(CAnimBlendClumpData**)0x621000; +CAnimBlendClumpData *gpAnimBlendClump; void FrameUpdateCallBack(AnimBlendFrameData *frame, void *arg); void FrameUpdateCallBackWithVelocityExtraction(AnimBlendFrameData *frame, void *arg); diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h index 55a4456b..f9e14c42 100644 --- a/src/animation/RpAnimBlend.h +++ b/src/animation/RpAnimBlend.h @@ -37,5 +37,5 @@ CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump); void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta); -extern CAnimBlendClumpData *&gpAnimBlendClump; +extern CAnimBlendClumpData *gpAnimBlendClump; void FrameUpdateCallBack(AnimBlendFrameData *frame, void *arg); diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index d840c57b..d4b60d9b 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -15,10 +15,10 @@ #include "sampman.h" #include "patcher.h" -cMusicManager &MusicManager = *(cMusicManager *)0x8F3964; -int32 &gNumRetunePresses = *(int32 *)0x650B80; -int32 &gRetuneCounter = *(int32*)0x650B84; -bool& bHasStarted = *(bool*)0x650B7C; +cMusicManager MusicManager; +int32 gNumRetunePresses; +int32 gRetuneCounter; +bool bHasStarted; const int maxVolume = 127; diff --git a/src/audio/MusicManager.h b/src/audio/MusicManager.h index 5c255069..5d6f41cf 100644 --- a/src/audio/MusicManager.h +++ b/src/audio/MusicManager.h @@ -86,4 +86,4 @@ public: static_assert(sizeof(cMusicManager) == 0x95C, "cMusicManager: error"); -extern cMusicManager &MusicManager; +extern cMusicManager MusicManager; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index c7fa41e4..c2392d3b 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -29,6 +29,7 @@ #include "SceneEdit.h" #include "Pools.h" #include "Debug.h" +#include "GenericGameStorage.h" #include "Camera.h" enum diff --git a/src/core/main.h b/src/core/main.h index 5e9401b9..5ee758a4 100644 --- a/src/core/main.h +++ b/src/core/main.h @@ -16,11 +16,8 @@ extern char *gString; extern char *gString2; extern wchar *gUString; extern wchar *gUString2; -extern bool &b_FoundRecentSavedGameWantToLoad; extern bool gbPrintShite; extern bool &gbModelViewer; -extern bool &StillToFadeOut; -extern bool &JustLoadedDontFadeInYet; class CSprite2d; diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp index cd83a898..9218a055 100644 --- a/src/rw/Lights.cpp +++ b/src/rw/Lights.cpp @@ -9,18 +9,18 @@ #include "ZoneCull.h" #include "Frontend.h" -RpLight *&pAmbient = *(RpLight**)0x885B6C; -RpLight *&pDirect = *(RpLight**)0x880F7C; -RpLight **pExtraDirectionals = (RpLight**)0x60009C; -int *LightStrengths = (int*)0x87BEF0; -int &NumExtraDirLightsInWorld = *(int*)0x64C608; +RpLight *pAmbient;// = *(RpLight**)0x885B6C; +RpLight *pDirect;// = *(RpLight**)0x880F7C; +RpLight *pExtraDirectionals[] = { nil, nil, nil, nil };// = (RpLight**)0x60009C; +int LightStrengths[4];// = (int*)0x87BEF0; +int NumExtraDirLightsInWorld;// = *(int*)0x64C608; -RwRGBAReal &AmbientLightColourForFrame = *(RwRGBAReal*)0x6F46F8; -RwRGBAReal &AmbientLightColourForFrame_PedsCarsAndObjects = *(RwRGBAReal*)0x6F1D10; -RwRGBAReal &DirectionalLightColourForFrame = *(RwRGBAReal*)0x87C6B8; +RwRGBAReal AmbientLightColourForFrame;// = *(RwRGBAReal*)0x6F46F8; +RwRGBAReal AmbientLightColourForFrame_PedsCarsAndObjects;// = *(RwRGBAReal*)0x6F1D10; +RwRGBAReal DirectionalLightColourForFrame;// = *(RwRGBAReal*)0x87C6B8; -RwRGBAReal &AmbientLightColour = *(RwRGBAReal*)0x86B0F8; -RwRGBAReal &DirectionalLightColour = *(RwRGBAReal*)0x72E308; +RwRGBAReal AmbientLightColour;// = *(RwRGBAReal*)0x86B0F8; +RwRGBAReal DirectionalLightColour;// = *(RwRGBAReal*)0x72E308; void SetLightsWithTimeOfDayColour(RpWorld *) diff --git a/src/rw/NodeName.cpp b/src/rw/NodeName.cpp index 2aea3c83..7422a323 100644 --- a/src/rw/NodeName.cpp +++ b/src/rw/NodeName.cpp @@ -2,7 +2,7 @@ #include "patcher.h" #include "NodeName.h" -static int32 &gPluginOffset = *(int32*)0x64C610; +static int32 gPluginOffset;// = *(int32*)0x64C610; enum { diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index c91b71c0..1ac5a75e 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -22,8 +22,8 @@ #include "RwHelper.h" #endif //GTA_PC -float &texLoadTime = *(float*)0x8F1B50; -int32 &texNumLoaded = *(int32*)0x8F252C; +float texLoadTime;// = *(float*)0x8F1B50; +int32 texNumLoaded;// = *(int32*)0x8F252C; #ifdef LIBRW #define READNATIVE(stream, tex, size) rwNativeTextureHackRead(stream, tex, size) @@ -155,7 +155,11 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict) } #ifdef GTA_PC - +#ifdef RWLIBS +extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); +#else +RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); +#endif void ReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8) { @@ -174,8 +178,6 @@ ReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8) } } -RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); - bool CheckVideoCardCaps(void) { diff --git a/src/rw/TxdStore.cpp b/src/rw/TxdStore.cpp index c751147d..a32755a4 100644 --- a/src/rw/TxdStore.cpp +++ b/src/rw/TxdStore.cpp @@ -6,8 +6,8 @@ #include "RwHelper.h" #include "TxdStore.h" -CPool *&CTxdStore::ms_pTxdPool = *(CPool**)0x8F5FB8; -RwTexDictionary *&CTxdStore::ms_pStoredTxd = *(RwTexDictionary**)0x9405BC; +CPool *CTxdStore::ms_pTxdPool;// = *(CPool**)0x8F5FB8; +RwTexDictionary *CTxdStore::ms_pStoredTxd;// = *(RwTexDictionary**)0x9405BC; void CTxdStore::Initialise(void) diff --git a/src/rw/TxdStore.h b/src/rw/TxdStore.h index 12ac708f..937fd1b7 100644 --- a/src/rw/TxdStore.h +++ b/src/rw/TxdStore.h @@ -10,8 +10,8 @@ struct TxdDef { class CTxdStore { - static CPool *&ms_pTxdPool; - static RwTexDictionary *&ms_pStoredTxd; + static CPool *ms_pTxdPool; + static RwTexDictionary *ms_pStoredTxd; public: static void Initialise(void); static void Shutdown(void); diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index f8b1f6b2..def3b23e 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -11,32 +11,24 @@ #define FADE_DISTANCE 20.0f -/* -CLinkList CVisibilityPlugins::m_alphaList; -CLinkList CVisibilityPlugins::m_alphaEntityList; +CLinkList CVisibilityPlugins::m_alphaList;// = *(CLinkList*)0x8F42E4; +CLinkList CVisibilityPlugins::m_alphaEntityList;// = *(CLinkList*)0x943084; -int32 CVisibilityPlugins::ms_atomicPluginOffset = -1; -int32 CVisibilityPlugins::ms_framePluginOffset = -1; -int32 CVisibilityPlugins::ms_clumpPluginOffset = -1; -*/ -CLinkList &CVisibilityPlugins::m_alphaList = *(CLinkList*)0x8F42E4; -CLinkList &CVisibilityPlugins::m_alphaEntityList = *(CLinkList*)0x943084; +int32 CVisibilityPlugins::ms_atomicPluginOffset = -1;// = *(int32*)0x600124; +int32 CVisibilityPlugins::ms_framePluginOffset = -1;// = *(int32*)0x600128; +int32 CVisibilityPlugins::ms_clumpPluginOffset = -1;// = *(int32*)0x60012C; -int32 &CVisibilityPlugins::ms_atomicPluginOffset = *(int32*)0x600124; -int32 &CVisibilityPlugins::ms_framePluginOffset = *(int32*)0x600128; -int32 &CVisibilityPlugins::ms_clumpPluginOffset = *(int32*)0x60012C; - -RwCamera *&CVisibilityPlugins::ms_pCamera = *(RwCamera**)0x8F2514; -RwV3d *&CVisibilityPlugins::ms_pCameraPosn = *(RwV3d**)0x8F6270; -float &CVisibilityPlugins::ms_cullCompsDist = *(float*)0x8F2BC4; -float &CVisibilityPlugins::ms_vehicleLod0Dist = *(float*)0x885B28; -float &CVisibilityPlugins::ms_vehicleLod1Dist = *(float*)0x885B30; -float &CVisibilityPlugins::ms_vehicleFadeDist = *(float*)0x8E28B4; -float &CVisibilityPlugins::ms_bigVehicleLod0Dist = *(float*)0x8E2A84; -float &CVisibilityPlugins::ms_bigVehicleLod1Dist = *(float*)0x8E2A8C; -float &CVisibilityPlugins::ms_pedLod0Dist = *(float*)0x8F2BD4; -float &CVisibilityPlugins::ms_pedLod1Dist = *(float*)0x8F2BD8; -float &CVisibilityPlugins::ms_pedFadeDist = *(float*)0x8E2C34; +RwCamera *CVisibilityPlugins::ms_pCamera;// = *(RwCamera**)0x8F2514; +RwV3d *CVisibilityPlugins::ms_pCameraPosn;// = *(RwV3d**)0x8F6270; +float CVisibilityPlugins::ms_cullCompsDist;// = *(float*)0x8F2BC4; +float CVisibilityPlugins::ms_vehicleLod0Dist;// = *(float*)0x885B28; +float CVisibilityPlugins::ms_vehicleLod1Dist;// = *(float*)0x885B30; +float CVisibilityPlugins::ms_vehicleFadeDist;// = *(float*)0x8E28B4; +float CVisibilityPlugins::ms_bigVehicleLod0Dist;// = *(float*)0x8E2A84; +float CVisibilityPlugins::ms_bigVehicleLod1Dist;// = *(float*)0x8E2A8C; +float CVisibilityPlugins::ms_pedLod0Dist;// = *(float*)0x8F2BD4; +float CVisibilityPlugins::ms_pedLod1Dist;// = *(float*)0x8F2BD8; +float CVisibilityPlugins::ms_pedFadeDist;// = *(float*)0x8E2C34; void CVisibilityPlugins::Initialise(void) @@ -602,6 +594,16 @@ CVisibilityPlugins::DefaultVisibilityCB(RpClump *clump) return true; } +bool +CVisibilityPlugins::MloVisibilityCB(RpClump *clump) +{ + RwFrame *frame = RpClumpGetFrame(clump); + CMloModelInfo *modelInfo = (CMloModelInfo*)GetFrameHierarchyId(frame); + if (sq(modelInfo->field_34) < GetDistanceSquaredFromCamera(frame)) + return false; + return CVisibilityPlugins::FrustumSphereCB(clump); +} + bool CVisibilityPlugins::FrustumSphereCB(RpClump *clump) { diff --git a/src/rw/VisibilityPlugins.h b/src/rw/VisibilityPlugins.h index 65d2675a..63bc95e4 100644 --- a/src/rw/VisibilityPlugins.h +++ b/src/rw/VisibilityPlugins.h @@ -20,19 +20,19 @@ public: float sort; }; - static CLinkList &m_alphaList; - static CLinkList &m_alphaEntityList; - static RwCamera *&ms_pCamera; - static RwV3d *&ms_pCameraPosn; - static float &ms_cullCompsDist; - static float &ms_vehicleLod0Dist; - static float &ms_vehicleLod1Dist; - static float &ms_vehicleFadeDist; - static float &ms_bigVehicleLod0Dist; - static float &ms_bigVehicleLod1Dist; - static float &ms_pedLod0Dist; - static float &ms_pedLod1Dist; - static float &ms_pedFadeDist; + static CLinkList m_alphaList; + static CLinkList m_alphaEntityList; + static RwCamera *ms_pCamera; + static RwV3d *ms_pCameraPosn; + static float ms_cullCompsDist; + static float ms_vehicleLod0Dist; + static float ms_vehicleLod1Dist; + static float ms_vehicleFadeDist; + static float ms_bigVehicleLod0Dist; + static float ms_bigVehicleLod1Dist; + static float ms_pedLod0Dist; + static float ms_pedLod1Dist; + static float ms_pedFadeDist; static void Initialise(void); static void Shutdown(void); @@ -70,7 +70,7 @@ public: // All actually unused static bool DefaultVisibilityCB(RpClump *clump); static bool FrustumSphereCB(RpClump *clump); -// static bool MloVisibilityCB(RpClump *clump); + static bool MloVisibilityCB(RpClump *clump); static bool VehicleVisibilityCB(RpClump *clump); static bool VehicleVisibilityCB_BigVehicle(RpClump *clump); @@ -97,7 +97,7 @@ public: static void *AtomicDestructor(void *object, int32 offset, int32 len); static void *AtomicCopyConstructor(void *dst, const void *src, int32 offset, int32 len); - static int32 &ms_atomicPluginOffset; + static int32 ms_atomicPluginOffset; struct FrameExt { @@ -111,7 +111,7 @@ public: static void *FrameDestructor(void *object, int32 offset, int32 len); static void *FrameCopyConstructor(void *dst, const void *src, int32 offset, int32 len); - static int32 &ms_framePluginOffset; + static int32 ms_framePluginOffset; // Not actually used struct ClumpExt @@ -127,7 +127,7 @@ public: static void *ClumpDestructor(void *object, int32 offset, int32 len); static void *ClumpCopyConstructor(void *dst, const void *src, int32 offset, int32 len); - static int32 &ms_clumpPluginOffset; + static int32 ms_clumpPluginOffset; static bool PluginAttach(void); }; diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 1e4acd3d..0bae979b 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -40,22 +40,22 @@ const uint32 SIZE_OF_ONE_GAME_IN_BYTES = 201729; -char (&DefaultPCSaveFileName)[260] = *(char(*)[260])*(uintptr*)0x8E28C0; -char (&ValidSaveName)[260] = *(char(*)[260])*(uintptr*)0x8E2CBC; -char (&LoadFileName)[256] = *(char(*)[256])*(uintptr*)0x9403C4; -wchar (&SlotFileName)[SLOT_COUNT][260] = *(wchar(*)[SLOT_COUNT][260])*(uintptr*)0x6F07C8; -wchar (&SlotSaveDate)[SLOT_COUNT][70] = *(wchar(*)[SLOT_COUNT][70])*(uintptr*)0x72B858; -int &CheckSum = *(int*)0x8E2BE0; -eLevelName &m_LevelToLoad = *(eLevelName*)0x8E29CC; +char DefaultPCSaveFileName[260];// = *(char(*)[260]) * (uintptr*)0x8E28C0; +char ValidSaveName[260];// = *(char(*)[260])*(uintptr*)0x8E2CBC; +char LoadFileName[256];// = *(char(*)[256])*(uintptr*)0x9403C4; +wchar SlotFileName[SLOT_COUNT][260];// = *(wchar(*)[SLOT_COUNT][260])*(uintptr*)0x6F07C8; +wchar SlotSaveDate[SLOT_COUNT][70];// = *(wchar(*)[SLOT_COUNT][70])*(uintptr*)0x72B858; +int CheckSum;// = *(int*)0x8E2BE0; +eLevelName m_LevelToLoad;// = *(eLevelName*)0x8E29CC; char SaveFileNameJustSaved[260]; -int (&Slots)[SLOT_COUNT+1] = *(int(*)[SLOT_COUNT+1])*(uintptr*)0x72803C; -CDate &CompileDateAndTime = *(CDate*)0x72BCB8; +int Slots[SLOT_COUNT+1];// = *(int(*)[SLOT_COUNT+1])*(uintptr*)0x72803C; +CDate CompileDateAndTime;// = *(CDate*)0x72BCB8; -bool &b_FoundRecentSavedGameWantToLoad = *(bool*)0x95CDA8; -bool &JustLoadedDontFadeInYet = *(bool*)0x95CDB4; -bool &StillToFadeOut = *(bool*)0x95CD99; -uint32 &TimeStartedCountingForFade = *(uint32*)0x9430EC; -uint32 &TimeToStayFadedBeforeFadeOut = *(uint32*)0x611564; +bool b_FoundRecentSavedGameWantToLoad;// = *(bool*)0x95CDA8; +bool JustLoadedDontFadeInYet;// = *(bool*)0x95CDB4; +bool StillToFadeOut;// = *(bool*)0x95CD99; +uint32 TimeStartedCountingForFade;// = *(uint32*)0x9430EC; +uint32 TimeToStayFadedBeforeFadeOut = 1750;// = *(uint32*)0x611564; #define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to)); #define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from)); diff --git a/src/save/GenericGameStorage.h b/src/save/GenericGameStorage.h index e6fd2e2d..b913c305 100644 --- a/src/save/GenericGameStorage.h +++ b/src/save/GenericGameStorage.h @@ -21,22 +21,22 @@ bool CheckDataNotCorrupt(int32 slot, char *name); bool RestoreForStartLoad(); int align4bytes(int32 size); -extern class CDate& CompileDateAndTime; +extern class CDate CompileDateAndTime; -extern char (&DefaultPCSaveFileName)[260]; -extern char (&ValidSaveName)[260]; -extern char (&LoadFileName)[256]; -extern wchar (&SlotFileName)[SLOT_COUNT][260]; -extern wchar (&SlotSaveDate)[SLOT_COUNT][70]; -extern int &CheckSum; -extern enum eLevelName &m_LevelToLoad; -extern int (&Slots)[SLOT_COUNT+1]; +extern char DefaultPCSaveFileName[260]; +extern char ValidSaveName[260]; +extern char LoadFileName[256]; +extern wchar SlotFileName[SLOT_COUNT][260]; +extern wchar SlotSaveDate[SLOT_COUNT][70]; +extern int CheckSum; +extern enum eLevelName m_LevelToLoad; +extern int Slots[SLOT_COUNT+1]; -extern bool &b_FoundRecentSavedGameWantToLoad; -extern bool &JustLoadedDontFadeInYet; -extern bool &StillToFadeOut; -extern uint32 &TimeStartedCountingForFade; -extern uint32 &TimeToStayFadedBeforeFadeOut; +extern bool b_FoundRecentSavedGameWantToLoad; +extern bool JustLoadedDontFadeInYet; +extern bool StillToFadeOut; +extern uint32 TimeStartedCountingForFade; +extern uint32 TimeToStayFadedBeforeFadeOut; extern char SaveFileNameJustSaved[260]; // 8F2570 diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 744f5e0d..4afcb645 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -9,7 +9,7 @@ const char* _psGetUserFilesFolder(); -C_PcSave &PcSaveHelper = *(C_PcSave*)0x8E2C60; +C_PcSave PcSaveHelper;// = *(C_PcSave*)0x8E2C60; void C_PcSave::SetSaveDirectory(const char *path) diff --git a/src/save/PCSave.h b/src/save/PCSave.h index c58a5c9e..4a2d9a66 100644 --- a/src/save/PCSave.h +++ b/src/save/PCSave.h @@ -37,4 +37,4 @@ public: static void SetSaveDirectory(const char *path); }; -extern C_PcSave &PcSaveHelper; +extern C_PcSave PcSaveHelper; diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp index 9896a8e0..4b181d67 100644 --- a/src/text/Messages.cpp +++ b/src/text/Messages.cpp @@ -12,9 +12,9 @@ #include "ControllerConfig.h" -tMessage(&CMessages::BriefMessages)[NUMBRIEFMESSAGES] = *(tMessage(*)[NUMBRIEFMESSAGES])*(uintptr*)0x8786E0; -tPreviousBrief(&CMessages::PreviousBriefs)[NUMPREVIOUSBRIEFS] = *(tPreviousBrief(*)[NUMPREVIOUSBRIEFS])*(uintptr*)0x713C08; -tBigMessage(&CMessages::BIGMessages)[NUMBIGMESSAGES] = *(tBigMessage(*)[NUMBIGMESSAGES])*(uintptr*)0x773628; +tMessage CMessages::BriefMessages[NUMBRIEFMESSAGES];// = *(tMessage(*)[NUMBRIEFMESSAGES]) * (uintptr*)0x8786E0; +tPreviousBrief CMessages::PreviousBriefs[NUMPREVIOUSBRIEFS];// = *(tPreviousBrief(*)[NUMPREVIOUSBRIEFS]) * (uintptr*)0x713C08; +tBigMessage CMessages::BIGMessages[NUMBIGMESSAGES];// = *(tBigMessage(*)[NUMBIGMESSAGES]) * (uintptr*)0x773628; char CMessages::PreviousMissionTitle[16]; // unused void diff --git a/src/text/Messages.h b/src/text/Messages.h index 8044c626..e8ba1bf7 100644 --- a/src/text/Messages.h +++ b/src/text/Messages.h @@ -29,9 +29,9 @@ struct tPreviousBrief class CMessages { public: - static tMessage(&BriefMessages)[NUMBRIEFMESSAGES]; - static tBigMessage(&BIGMessages)[NUMBIGMESSAGES]; - static tPreviousBrief(&PreviousBriefs)[NUMPREVIOUSBRIEFS]; + static tMessage BriefMessages[NUMBRIEFMESSAGES]; + static tBigMessage BIGMessages[NUMBIGMESSAGES]; + static tPreviousBrief PreviousBriefs[NUMPREVIOUSBRIEFS]; static char PreviousMissionTitle[16]; // unused public: static void Init(void); diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 5fc19f12..b3da27e8 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -7,7 +7,7 @@ static wchar WideErrorString[25]; -CText &TheText = *(CText*)0x941520; +CText TheText;// = *(CText*)0x941520; CText::CText(void) { diff --git a/src/text/Text.h b/src/text/Text.h index 6f39ba49..00d1c5e6 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -56,4 +56,4 @@ public: void UpperCase(wchar *s); }; -extern CText &TheText; +extern CText TheText; From 69c32376fe6ff99c17662533e9e6999fb24708b0 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 16 Apr 2020 12:44:04 +0300 Subject: [PATCH 040/123] Increase alpha entity list capacity for wide screen --- src/core/config.h | 3 ++- src/rw/VisibilityPlugins.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/core/config.h b/src/core/config.h index f684ed3c..f9edb74a 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -47,7 +47,8 @@ enum Config { NUM_PATHCONNECTIONS = 10260, // Link list lengths - // TODO: alpha list + NUMALPHALIST = 20, + NUMALPHAENTITYLIST = 150, NUMCOLCACHELINKS = 200, NUMREFERENCES = 800, diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index def3b23e..5438ed0f 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -33,10 +33,15 @@ float CVisibilityPlugins::ms_pedFadeDist;// = *(float*)0x8E2C34; void CVisibilityPlugins::Initialise(void) { - m_alphaList.Init(20); + m_alphaList.Init(NUMALPHALIST); m_alphaList.head.item.sort = 0.0f; m_alphaList.tail.item.sort = 100000000.0f; - m_alphaEntityList.Init(150); +#ifdef ASPECT_RATIO_SCALE + // default 150 if not enough for bigger FOVs + m_alphaEntityList.Init(NUMALPHAENTITYLIST * 3); +#else + m_alphaEntityList.Init(NUMALPHAENTITYLIST); +#endif // ASPECT_RATIO_SCALE m_alphaEntityList.head.item.sort = 0.0f; m_alphaEntityList.tail.item.sort = 100000000.0f; } From 7bd12f4a48e081fb96c4d65d47eb3954afc13f60 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 16 Apr 2020 13:33:32 +0200 Subject: [PATCH 041/123] add textures in correct order --- src/fakerw/fake.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index b91a9c49..557318be 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -339,7 +339,7 @@ RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size) RwTexDictionary *RwTexDictionaryCreate(void) { return TexDictionary::create(); } RwBool RwTexDictionaryDestroy(RwTexDictionary * dict) { dict->destroy(); return true; } -RwTexture *RwTexDictionaryAddTexture(RwTexDictionary * dict, RwTexture * texture) { dict->add(texture); return texture; } +RwTexture *RwTexDictionaryAddTexture(RwTexDictionary * dict, RwTexture * texture) { dict->addFront(texture); return texture; } //RwTexture *RwTexDictionaryRemoveTexture(RwTexture * texture); RwTexture *RwTexDictionaryFindNamedTexture(RwTexDictionary * dict, const RwChar * name) { return dict->find(name); } RwTexDictionary *RwTexDictionaryGetCurrent(void) { return TexDictionary::getCurrent(); } From 83cbe4e39ede4853e0d352e55aeddbd481b39948 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Thu, 16 Apr 2020 15:30:47 +0300 Subject: [PATCH 042/123] More refs removed --- src/core/IniFile.cpp | 4 +-- src/core/IniFile.h | 4 +-- src/{core => render}/Instance.cpp | 0 src/{core => render}/Instance.h | 0 src/render/Sprite2d.cpp | 14 ++++---- src/render/Sprite2d.h | 14 ++++---- src/vehicles/Automobile.cpp | 2 +- src/vehicles/Automobile.h | 2 +- src/vehicles/Boat.cpp | 10 +++--- src/vehicles/Boat.h | 2 +- src/vehicles/Floater.cpp | 5 ++- src/vehicles/Floater.h | 2 +- src/vehicles/HandlingMgr.cpp | 2 +- src/vehicles/HandlingMgr.h | 2 +- src/vehicles/Heli.cpp | 12 +++---- src/vehicles/Heli.h | 12 +++---- src/vehicles/Plane.cpp | 56 +++++++++++++++---------------- src/vehicles/Plane.h | 6 ++-- src/vehicles/Train.cpp | 28 ++++++++-------- 19 files changed, 88 insertions(+), 89 deletions(-) rename src/{core => render}/Instance.cpp (100%) rename src/{core => render}/Instance.h (100%) diff --git a/src/core/IniFile.cpp b/src/core/IniFile.cpp index 08b30876..744f4bd0 100644 --- a/src/core/IniFile.cpp +++ b/src/core/IniFile.cpp @@ -7,8 +7,8 @@ #include "main.h" #include "Population.h" -float &CIniFile::PedNumberMultiplier = *(float*)0x6182F4; -float &CIniFile::CarNumberMultiplier = *(float*)0x6182F8; +float CIniFile::PedNumberMultiplier = 1.0f;// = *(float*)0x6182F4; +float CIniFile::CarNumberMultiplier = 1.0f;// = *(float*)0x6182F8; void CIniFile::LoadIniFile() { diff --git a/src/core/IniFile.h b/src/core/IniFile.h index 9a98151b..1e30c4de 100644 --- a/src/core/IniFile.h +++ b/src/core/IniFile.h @@ -5,6 +5,6 @@ class CIniFile public: static void LoadIniFile(); - static float& PedNumberMultiplier; - static float& CarNumberMultiplier; + static float PedNumberMultiplier; + static float CarNumberMultiplier; }; diff --git a/src/core/Instance.cpp b/src/render/Instance.cpp similarity index 100% rename from src/core/Instance.cpp rename to src/render/Instance.cpp diff --git a/src/core/Instance.h b/src/render/Instance.h similarity index 100% rename from src/core/Instance.h rename to src/render/Instance.h diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index 3f21516a..1fe70121 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -5,13 +5,13 @@ #include "Camera.h" #include "Sprite2d.h" -RwIm2DVertex *CSprite2d::maVertices = (RwIm2DVertex*)0x6E9168; -float &CSprite2d::RecipNearClip = *(float*)0x880DB4; -int32 &CSprite2d::mCurrentBank = *(int32*)0x8F1AF4; -RwTexture **CSprite2d::mpBankTextures = (RwTexture**)0x774DC0; -int32 *CSprite2d::mCurrentSprite = (int32*)0x6F4500; -int32 *CSprite2d::mBankStart = (int32*)0x774BE8; -RwIm2DVertex *CSprite2d::maBankVertices = (RwIm2DVertex*)0x8429F8; +RwIm2DVertex CSprite2d::maVertices[4]; +float CSprite2d::RecipNearClip; +int32 CSprite2d::mCurrentBank; +RwTexture *CSprite2d::mpBankTextures[10]; +int32 CSprite2d::mCurrentSprite[10]; +int32 CSprite2d::mBankStart[10]; +RwIm2DVertex CSprite2d::maBankVertices[500]; void CSprite2d::SetRecipNearClip(void) diff --git a/src/render/Sprite2d.h b/src/render/Sprite2d.h index 268c7d2b..0b073557 100644 --- a/src/render/Sprite2d.h +++ b/src/render/Sprite2d.h @@ -2,13 +2,13 @@ class CSprite2d { - static float &RecipNearClip; - static int32 &mCurrentBank; - static RwTexture **mpBankTextures; //[10]; - static int32 *mCurrentSprite; //[10]; - static int32 *mBankStart; //[10]; - static RwIm2DVertex *maBankVertices; //[500]; - static RwIm2DVertex *maVertices; //[4]; + static float RecipNearClip; + static int32 mCurrentBank; + static RwTexture *mpBankTextures[10]; + static int32 mCurrentSprite[10]; + static int32 mBankStart[10]; + static RwIm2DVertex maBankVertices[500]; + static RwIm2DVertex maVertices[4]; public: RwTexture *m_pTexture; diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 2a325b3d..12d4f589 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -49,7 +49,7 @@ bool bAllCarCheat; // unused RwObject *GetCurrentAtomicObjectCB(RwObject *object, void *data); -bool &CAutomobile::m_sAllTaxiLights = *(bool*)0x95CD21; +bool CAutomobile::m_sAllTaxiLights;// = *(bool*)0x95CD21; CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) : CVehicle(CreatedBy) diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 561ab566..66774612 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -120,7 +120,7 @@ public: float m_fGasPedalAudio; tWheelState m_aWheelState[4]; - static bool &m_sAllTaxiLights; + static bool m_sAllTaxiLights; CAutomobile(int32 id, uint8 CreatedBy); diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 0159d168..d694d8b0 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -21,16 +21,16 @@ #define INVALID_ORIENTATION (-9999.99f) -float &fShapeLength = *(float*)0x600E78; -float &fShapeTime = *(float*)0x600E7C; -float &fRangeMult = *(float*)0x600E80; //0.6f; // 0.75f gta 3 -float &fTimeMult = *(float*)0x943008; +float fShapeLength = 0.4f;// *(float*)0x600E78; +float fShapeTime = 0.05f;// *(float*)0x600E7C; +float fRangeMult = 0.75f; // = *(float*)0x600E80; //0.6f; // 0.75f gta 3 +float fTimeMult;// = *(float*)0x943008; float MAX_WAKE_LENGTH = 50.0f; float MIN_WAKE_INTERVAL = 1.0f; float WAKE_LIFETIME = 400.0f; -CBoat * (&CBoat::apFrameWakeGeneratingBoats)[4] = *(CBoat * (*)[4])*(uintptr*)0x8620E0; +CBoat *CBoat::apFrameWakeGeneratingBoats[4];// = *(CBoat * (*)[4]) * (uintptr*)0x8620E0; CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) { diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h index f4c6a747..ba56e355 100644 --- a/src/vehicles/Boat.h +++ b/src/vehicles/Boat.h @@ -58,7 +58,7 @@ public: void PruneWakeTrail(void); void AddWakePoint(CVector point); - static CBoat *(&apFrameWakeGeneratingBoats)[4]; + static CBoat *apFrameWakeGeneratingBoats[4]; static bool IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoats); static float IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat); diff --git a/src/vehicles/Floater.cpp b/src/vehicles/Floater.cpp index 62d55925..ee4a1191 100644 --- a/src/vehicles/Floater.cpp +++ b/src/vehicles/Floater.cpp @@ -7,10 +7,9 @@ #include "Vehicle.h" #include "Floater.h" -cBuoyancy &mod_Buoyancy = *(cBuoyancy*)0x8F2674; +cBuoyancy mod_Buoyancy;// = *(cBuoyancy*)0x8F2674; -//static float fVolMultiplier = 1.0f; -static float &fVolMultiplier = *(float*)0x601394; +static float fVolMultiplier = 1.0f; // 0x601394; // amount of boat volume in bounding box // 1.0-volume is the empty space in the bbox static float fBoatVolumeDistribution[9] = { diff --git a/src/vehicles/Floater.h b/src/vehicles/Floater.h index 4754a235..1cfb46fb 100644 --- a/src/vehicles/Floater.h +++ b/src/vehicles/Floater.h @@ -42,4 +42,4 @@ public: void FindWaterLevel(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition); bool CalcBuoyancyForce(CPhysical *phys, CVector *impulse, CVector *point); }; -extern cBuoyancy &mod_Buoyancy; +extern cBuoyancy mod_Buoyancy; diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index 0f16401e..40715887 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -4,7 +4,7 @@ #include "FileMgr.h" #include "HandlingMgr.h" -cHandlingDataMgr &mod_HandlingManager = *(cHandlingDataMgr*)0x728060; +cHandlingDataMgr mod_HandlingManager;// = *(cHandlingDataMgr*)0x728060; const char *HandlingFilename = "HANDLING.CFG"; diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h index 70f1c005..137925f3 100644 --- a/src/vehicles/HandlingMgr.h +++ b/src/vehicles/HandlingMgr.h @@ -140,4 +140,4 @@ public: bool HasFrontWheelDrive(eHandlingId id) { return HandlingData[id].Transmission.nDriveType == 'F'; } }; VALIDATE_SIZE(cHandlingDataMgr, 0x3030); -extern cHandlingDataMgr &mod_HandlingManager; +extern cHandlingDataMgr mod_HandlingManager; diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index c4cdcb02..61714133 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -34,13 +34,13 @@ enum HELI_STATUS_HOVER2, }; -CHeli **CHeli::pHelis = (CHeli**)0x72CF50; -int16 &CHeli::NumRandomHelis = *(int16*)0x95CCAA; -uint32 &CHeli::TestForNewRandomHelisTimer = *(uint32*)0x8F1A7C; +CHeli *CHeli::pHelis[NUM_HELIS];// = (CHeli**)0x72CF50; +int16 CHeli::NumRandomHelis;// = *(int16*)0x95CCAA; +uint32 CHeli::TestForNewRandomHelisTimer;// = *(uint32*)0x8F1A7C; int16 CHeli::NumScriptHelis; // unused -bool &CHeli::CatalinaHeliOn = *(bool*)0x95CD85; -bool &CHeli::CatalinaHasBeenShotDown = *(bool*)0x95CD56; -bool &CHeli::ScriptHeliOn = *(bool*)0x95CD43; +bool CHeli::CatalinaHeliOn;// = *(bool*)0x95CD85; +bool CHeli::CatalinaHasBeenShotDown;// = *(bool*)0x95CD56; +bool CHeli::ScriptHeliOn;// = *(bool*)0x95CD43; CHeli::CHeli(int32 id, uint8 CreatedBy) : CVehicle(CreatedBy) diff --git a/src/vehicles/Heli.h b/src/vehicles/Heli.h index bb10345d..15dff7b1 100644 --- a/src/vehicles/Heli.h +++ b/src/vehicles/Heli.h @@ -61,13 +61,13 @@ public: float m_fTargetOffset; bool m_bTestRight; - static CHeli **pHelis; //[NUM_HELIS] - static int16 &NumRandomHelis; - static uint32 &TestForNewRandomHelisTimer; + static CHeli *pHelis[NUM_HELIS]; + static int16 NumRandomHelis; + static uint32 TestForNewRandomHelisTimer; static int16 NumScriptHelis; // unused - static bool &CatalinaHeliOn; - static bool &CatalinaHasBeenShotDown; - static bool &ScriptHeliOn; + static bool CatalinaHeliOn; + static bool CatalinaHasBeenShotDown; + static bool ScriptHeliOn; CHeli(int32 id, uint8 CreatedBy); CHeli* ctor(int, uint8); diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index c2b9e493..49f5d69d 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -16,35 +16,35 @@ #include "HandlingMgr.h" #include "Plane.h" -CPlaneNode *&pPathNodes = *(CPlaneNode**)0x8F1B68; -CPlaneNode *&pPath2Nodes = *(CPlaneNode**)0x885B8C; -CPlaneNode *&pPath3Nodes = *(CPlaneNode**)0x885B78; -CPlaneNode *&pPath4Nodes = *(CPlaneNode**)0x885AD8; -int32 &NumPathNodes = *(int32*)0x8F2BE4; -int32 &NumPath2Nodes = *(int32*)0x941498; -int32 &NumPath3Nodes = *(int32*)0x9414D8; -int32 &NumPath4Nodes = *(int32*)0x9412C8; -float &TotalLengthOfFlightPath = *(float*)0x8F2C6C; -float &TotalLengthOfFlightPath2 = *(float*)0x64CFBC; -float &TotalLengthOfFlightPath3 = *(float*)0x64CFD0; -float &TotalLengthOfFlightPath4 = *(float*)0x64CFDC; -float &TotalDurationOfFlightPath = *(float*)0x64CFB8; -float &TotalDurationOfFlightPath2 = *(float*)0x64CFC0; -float &TotalDurationOfFlightPath3 = *(float*)0x64CFD4; -float &TotalDurationOfFlightPath4 = *(float*)0x64CFE0; -float &LandingPoint = *(float*)0x8F2C7C; -float &TakeOffPoint = *(float*)0x8E28A4; -CPlaneInterpolationLine *aPlaneLineBits = (CPlaneInterpolationLine*)0x734168; //[6] +CPlaneNode *pPathNodes;// = *(CPlaneNode**)0x8F1B68; +CPlaneNode *pPath2Nodes;// = *(CPlaneNode**)0x885B8C; +CPlaneNode *pPath3Nodes;// = *(CPlaneNode**)0x885B78; +CPlaneNode *pPath4Nodes;// = *(CPlaneNode**)0x885AD8; +int32 NumPathNodes;// = *(int32*)0x8F2BE4; +int32 NumPath2Nodes;// = *(int32*)0x941498; +int32 NumPath3Nodes;// = *(int32*)0x9414D8; +int32 NumPath4Nodes;// = *(int32*)0x9412C8; +float TotalLengthOfFlightPath;// = *(float*)0x8F2C6C; +float TotalLengthOfFlightPath2;// = *(float*)0x64CFBC; +float TotalLengthOfFlightPath3;// = *(float*)0x64CFD0; +float TotalLengthOfFlightPath4;// = *(float*)0x64CFDC; +float TotalDurationOfFlightPath;// = *(float*)0x64CFB8; +float TotalDurationOfFlightPath2;// = *(float*)0x64CFC0; +float TotalDurationOfFlightPath3;// = *(float*)0x64CFD4; +float TotalDurationOfFlightPath4;// = *(float*)0x64CFE0; +float LandingPoint;// = *(float*)0x8F2C7C; +float TakeOffPoint;// = *(float*)0x8E28A4; +CPlaneInterpolationLine aPlaneLineBits[6]; // = (CPlaneInterpolationLine*)0x734168; -float *PlanePathPosition = (float*)0x8F5FC8; //[3] -float *OldPlanePathPosition = (float*)0x8F5FBC; //[3] -float *PlanePathSpeed = (float*)0x941538; //[3] -float *PlanePath2Position = (float*)0x64CFC4; //[3] -float &PlanePath3Position = *(float*)0x64CFD8; -float &PlanePath4Position = *(float*)0x64CFE4; -float *PlanePath2Speed = (float*)0x8F1A54; //[3] -float &PlanePath3Speed = *(float*)0x8F1A94; -float &PlanePath4Speed = *(float*)0x8F1AFC; +float PlanePathPosition[3];// = (float*)0x8F5FC8; //[3] +float OldPlanePathPosition[3];// = (float*)0x8F5FBC; //[3] +float PlanePathSpeed[3];// = (float*)0x941538; //[3] +float PlanePath2Position[3];// = (float*)0x64CFC4; //[3] +float PlanePath3Position;// = *(float*)0x64CFD8; +float PlanePath4Position;// = *(float*)0x64CFE4; +float PlanePath2Speed[3];// = (float*)0x8F1A54; //[3] +float PlanePath3Speed;// = *(float*)0x8F1A94; +float PlanePath4Speed;// = *(float*)0x8F1AFC; enum diff --git a/src/vehicles/Plane.h b/src/vehicles/Plane.h index edca92ec..4c8e70aa 100644 --- a/src/vehicles/Plane.h +++ b/src/vehicles/Plane.h @@ -67,6 +67,6 @@ public: }; static_assert(sizeof(CPlane) == 0x29C, "CPlane: error"); -extern float &LandingPoint; -extern float &TakeOffPoint; -extern float *PlanePathPosition; //[3] +extern float LandingPoint; +extern float TakeOffPoint; +extern float PlanePathPosition[3]; diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp index 7d81fd57..25be193c 100644 --- a/src/vehicles/Train.cpp +++ b/src/vehicles/Train.cpp @@ -14,23 +14,23 @@ #include "HandlingMgr.h" #include "Train.h" -static CTrainNode *&pTrackNodes = *(CTrainNode**)0x8F4338; -static int16 &NumTrackNodes = *(int16*)0x95CC5C; +static CTrainNode* pTrackNodes; +static int16 NumTrackNodes; static float StationDist[3] = { 873.0f, 1522.0f, 2481.0f }; -static float &TotalLengthOfTrack = *(float*)0x64D000; -static float &TotalDurationOfTrack = *(float*)0x64D004; -static CTrainInterpolationLine *aLineBits = (CTrainInterpolationLine*)0x70D838; // [17] -static float *EngineTrackPosition = (float*)0x64D008; //[2] -static float *EngineTrackSpeed = (float*)0x880848; //[2] +static float TotalLengthOfTrack; +static float TotalDurationOfTrack; +static CTrainInterpolationLine aLineBits[17]; +static float EngineTrackPosition[2]; +static float EngineTrackSpeed[2]; -static CTrainNode *&pTrackNodes_S = *(CTrainNode**)0x8F2560; -static int16 &NumTrackNodes_S = *(int16*)0x95CC6A; +static CTrainNode* pTrackNodes_S; +static int16 NumTrackNodes_S; static float StationDist_S[4] = { 55.0f, 1388.0f, 2337.0f, 3989.0f }; -static float &TotalLengthOfTrack_S = *(float*)0x64D010; -static float &TotalDurationOfTrack_S = *(float*)0x64D014; -static CTrainInterpolationLine *aLineBits_S = (CTrainInterpolationLine*)0x726600; // [18] -static float *EngineTrackPosition_S = (float*)0x64D018; //[4] -static float *EngineTrackSpeed_S = (float*)0x87C7C8; //[4] +static float TotalLengthOfTrack_S; +static float TotalDurationOfTrack_S; +static CTrainInterpolationLine aLineBits_S[18]; +static float EngineTrackPosition_S[4]; +static float EngineTrackSpeed_S[4]; CVector CTrain::aStationCoors[3]; CVector CTrain::aStationCoors_S[4]; From 52d0d811b79f810aae9d10beb671f9889b8e4330 Mon Sep 17 00:00:00 2001 From: saml1er Date: Thu, 16 Apr 2020 23:46:08 +0500 Subject: [PATCH 043/123] Reverse CWorld --- src/animation/CutsceneMgr.h | 1 + src/control/Replay.cpp | 2 +- src/core/World.cpp | 846 +++++++++++++++++++++++++++++++++++- src/core/World.h | 33 +- src/entities/Entity.cpp | 10 + src/entities/Entity.h | 3 + src/objects/Object.cpp | 4 +- src/objects/Object.h | 2 +- 8 files changed, 867 insertions(+), 34 deletions(-) diff --git a/src/animation/CutsceneMgr.h b/src/animation/CutsceneMgr.h index 3c915eea..a455e784 100644 --- a/src/animation/CutsceneMgr.h +++ b/src/animation/CutsceneMgr.h @@ -28,6 +28,7 @@ public: static void StartCutsceneProcessing() { ms_cutsceneProcessing = true; } static bool IsRunning(void) { return ms_running; } + static bool HasLoaded(void) { return ms_loaded; } static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; } static bool UseLodMultiplier(void) { return ms_useLodMultiplier; } static CCutsceneObject* GetCutsceneObject(int id) { return ms_pCutsceneObjects[id]; } diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 0da32dd2..97debfdc 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1087,7 +1087,7 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca Playback.m_bSlot = first; Playback.m_nOffset = 0; Playback.m_pBase = Buffers[first]; - CObject::DeleteAllTempObjectInArea(CVector(0.0f, 0.0f, 0.0f), 1000000.0f); + CObject::DeleteAllTempObjectsInArea(CVector(0.0f, 0.0f, 0.0f), 1000000.0f); StoreStuffInMem(); EmptyPedsAndVehiclePools(); SlowMotion = 1; diff --git a/src/core/World.cpp b/src/core/World.cpp index d64569b3..7f18abbf 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -20,6 +20,14 @@ #include "Replay.h" #include "Population.h" #include "Fire.h" +#include "ProjectileInfo.h" +#include "WaterLevel.h" +#include "CopPed.h" +#include "Object.h" +#include "Shadows.h" +#include "Explosion.h" + +#define OBJECT_REPOSITION_OFFSET_Z 0.2f CColPoint *gaTempSphereColPoints = (CColPoint*)0x6E64C0; // [32] @@ -40,24 +48,24 @@ bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B; bool &CWorld::bDoingCarCollisions = *(bool*)0x95CD8C; bool &CWorld::bIncludeCarTyres = *(bool*)0x95CDAA; -WRAPPER void CWorld::ClearForRestart(void) { EAXJMP(0x4AE850); } -WRAPPER void CWorld::AddParticles(void) { EAXJMP(0x4B4010); } -WRAPPER void CWorld::ShutDown(void) { EAXJMP(0x4AE450); } -WRAPPER void CWorld::RepositionCertainDynamicObjects() { EAXJMP(0x4B42B0); } -WRAPPER void CWorld::RemoveStaticObjects() { EAXJMP(0x4B4D50); } -WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); } -WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); } -WRAPPER void CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8) { EAXJMP(0x4B4E70) }; -WRAPPER void CWorld::FindObjectsIntersectingCube(const CVector &, const CVector &, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B2E70); } -WRAPPER void CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B3280); } -WRAPPER void CWorld::FindObjectsOfTypeInRange(uint32, CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool) { EAXJMP(0x4B2600); } -WRAPPER void CWorld::FindObjectsOfTypeInRangeSectorList(uint32, CPtrList&, CVector&, float, bool, short*, short, CEntity**) { EAXJMP(0x4B2960); } -WRAPPER void CWorld::FindMissionEntitiesIntersectingCube(const CVector&, const CVector&, int16*, int16, CEntity**, bool, bool, bool) { EAXJMP(0x4B3680); } -WRAPPER void CWorld::ClearCarsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B50E0); } -WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B52B0); } -WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); } -WRAPPER void CWorld::TriggerExplosion(const CVector& a1, float a2, float a3, CEntity *a4, bool a5) { EAXJMP(0x4B1140); } -WRAPPER void CWorld::SetPedsOnFire(float, float, float, float, CEntity*) { EAXJMP(0x4B3D30); } +//WRAPPER void CWorld::ClearForRestart(void) { EAXJMP(0x4AE850); } +//WRAPPER void CWorld::AddParticles(void) { EAXJMP(0x4B4010); } +//WRAPPER void CWorld::ShutDown(void) { EAXJMP(0x4AE450); } +//WRAPPER void CWorld::RepositionCertainDynamicObjects() { EAXJMP(0x4B42B0); } +//WRAPPER void CWorld::RemoveStaticObjects() { EAXJMP(0x4B4D50); } +//WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); } +//WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); } +//WRAPPER void CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8 unused) { EAXJMP(0x4B4E70) }; +//WRAPPER void CWorld::FindObjectsIntersectingCube(const CVector &, const CVector &, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B2E70); } +//WRAPPER void CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B3280); } +//WRAPPER void CWorld::FindObjectsOfTypeInRange(uint32, CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool) { EAXJMP(0x4B2600); } +//WRAPPER void CWorld::FindObjectsOfTypeInRangeSectorList(uint32, CPtrList&, CVector&, float, bool, short*, short, CEntity**) { EAXJMP(0x4B2960); } +//WRAPPER void CWorld::FindMissionEntitiesIntersectingCube(const CVector&, const CVector&, int16*, int16, CEntity**, bool, bool, bool) { EAXJMP(0x4B3680); } +//WRAPPER void CWorld::ClearCarsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B50E0); } +//WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B52B0); } +//WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); } +WRAPPER void CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity *pCreator, bool bProcessVehicleBombTimer) { EAXJMP(0x4B1140); } +//WRAPPER void CWorld::SetPedsOnFire(float, float, float, float, CEntity*) { EAXJMP(0x4B3D30); } void CWorld::Initialise() @@ -128,6 +136,48 @@ CWorld::ClearScanCodes(void) } } +void +CWorld::ClearExcitingStuffFromArea(const CVector& pos, float radius, bool bRemoveProjectilesAndTidyUpShadows) +{ + CPedPool* pedPool = CPools::GetPedPool(); + for (int32 i = 0; i < pedPool->GetSize(); i++) { + CPed* pPed = pedPool->GetSlot(i); + if (pPed && !pPed->IsPlayer() && pPed->CanBeDeleted() && + CVector2D(pPed->GetPosition() - pos).MagnitudeSqr() < radius) { + CPopulation::RemovePed(pPed); + } + } + CVehiclePool* VehiclePool = CPools::GetVehiclePool(); + for (int32 i = 0; i < VehiclePool->GetSize(); i++) { + CVehicle* pVehicle = VehiclePool->GetSlot(i); + if (pVehicle && CVector2D(pVehicle->GetPosition() - pos).MagnitudeSqr() < radius && + !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { + if (pVehicle->pDriver) { + CPopulation::RemovePed(pVehicle->pDriver); + pVehicle->pDriver = nil; + } + for (int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) { + if (pVehicle->pPassengers[j]) { + CPopulation::RemovePed(pVehicle->pPassengers[j]); + pVehicle->pPassengers[j] = nil; + --pVehicle->m_nNumPassengers; + } + } + CCarCtrl::RemoveFromInterestingVehicleList(pVehicle); + CWorld::Remove(pVehicle); + delete pVehicle; + } + } + CObject::DeleteAllTempObjectsInArea(pos, radius); + gFireManager.ExtinguishPoint(pos, radius); + CWorld::ExtinguishAllCarFiresInArea(pos, radius); + CExplosion::RemoveAllExplosionsInArea(pos, radius); + if (bRemoveProjectilesAndTidyUpShadows) { + CProjectileInfo::RemoveAllProjectiles(); + CShadows::TidyUpShadows(); + } +} + bool CWorld::CameraToIgnoreThisObject(CEntity *ent) { @@ -694,6 +744,67 @@ CWorld::FindObjectsInRange(CVector ¢re, float radius, bool ignoreZ, short *n } } +void +CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != ms_nCurrentScanCode) { + pEntity->m_scanCode = ms_nCurrentScanCode; + float fMagnitude = 0.0f; + if (bCheck2DOnly) + fMagnitude = CVector2D(position - pEntity->GetPosition()).Magnitude(); + else + fMagnitude = CVector(position - pEntity->GetPosition()).Magnitude(); + if (fMagnitude < radius * radius && *nEntitiesFound < maxEntitiesToFind) { + if (aEntities) + aEntities[*nEntitiesFound] = pEntity; + ++*nEntitiesFound; + } + } + pNode = pNode->next; + } +} + +void +CWorld::FindObjectsOfTypeInRange(uint32 modelId, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) +{ + CWorld::AdvanceCurrentScanCode(); + *nEntitiesFound = 0; + const CVector2D vecSectorStartPos(position.x - radius, position.y - radius); + const CVector2D vecSectorEndPos(position.x + radius, position.y + radius); + const int32 nStartX = max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector* pSector = CWorld::GetSector(x, y); + if (bBuildings) { + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + } + if (bVehicles) { + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + } + if (bPeds) { + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_PEDS], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + } + if (bObjects) { + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + } + if (bDummies) { + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + } + } + } +} + CEntity* CWorld::TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects) { @@ -872,6 +983,273 @@ CWorld::FindRoofZFor3DCoord(float x, float y, float z, bool *found) } } +void +CWorld::RemoveReferencesToDeletedObject(CEntity* pDeletedObject) +{ + int32 i = CPools::GetPedPool()->GetSize(); + while (--i >= 0) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (pPed && pPed != pDeletedObject) { + pPed->RemoveRefsToEntity(pDeletedObject); + if (pPed->m_pCurrentPhysSurface == pDeletedObject) + pPed->m_pCurrentPhysSurface = nil; + } + } + i = CPools::GetVehiclePool()->GetSize(); + while (--i >= 0) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (pVehicle && pVehicle != pDeletedObject) { + pVehicle->RemoveRefsToEntity(pDeletedObject); + pVehicle->RemoveRefsToVehicle(pDeletedObject); + } + } + i = CPools::GetObjectPool()->GetSize(); + while (--i >= 0) { + CObject* pObject = CPools::GetObjectPool()->GetSlot(i); + if (pObject && pObject != pDeletedObject) { + pObject->RemoveRefsToEntity(pDeletedObject); + } + } +} + +void +CWorld::FindObjectsKindaColliding(const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) +{ + CWorld::AdvanceCurrentScanCode(); + *nCollidingEntities = 0; + const CVector2D vecSectorStartPos(position.x - radius, position.y - radius); + const CVector2D vecSectorEndPos(position.x + radius, position.y + radius); + const int32 nStartX = max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector* pSector = CWorld::GetSector(x, y); + if (bBuildings) { + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + } + if (bVehicles) { + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + } + if (bPeds) { + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_PEDS], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + } + if (bObjects) { + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + } + if (bDummies) { + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + } + } + } +} + +void +CWorld::FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != ms_nCurrentScanCode) { + pEntity->m_scanCode = ms_nCurrentScanCode; + float fMagnitude = 0.0f; + if (bCheck2DOnly) + fMagnitude = CVector2D(position - pEntity->GetPosition()).Magnitude(); + else + fMagnitude = CVector(position - pEntity->GetPosition()).Magnitude(); + if (pEntity->GetBoundRadius() + radius > fMagnitude && *nCollidingEntities < maxEntitiesToFind) { + if (aEntities) + aEntities[*nCollidingEntities] = pEntity; + ++*nCollidingEntities; + } + } + pNode = pNode->next; + } +} + +void +CWorld::FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) +{ + CWorld::AdvanceCurrentScanCode(); + *nIntersecting = 0; + const int32 nStartX = max(CWorld::GetSectorIndexX(vecStartPos.x), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector* pSector = CWorld::GetSector(x, y); + if (bBuildings) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + } + if (bVehicles) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + } + if (bPeds) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + } + if (bObjects) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + } + if (bDummies) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_DUMMIES], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + } + } + } + +} + +void +CWorld::FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { + pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + float fRadius = pEntity->GetBoundRadius(); + const CVector& entityPos = pEntity->GetPosition(); + if (fRadius + entityPos.x >= vecStartPos.x && entityPos.x - fRadius <= vecEndPos.x && + fRadius + entityPos.y >= vecStartPos.y && entityPos.y - fRadius <= vecEndPos.y && + fRadius + entityPos.z >= vecStartPos.z && entityPos.z - fRadius <= vecEndPos.z && + *nIntersecting < maxEntitiesToFind) { + if (aEntities) + aEntities[*nIntersecting] = pEntity; + ++*nIntersecting; + } + } + pNode = pNode->next; + } +} + +void +CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, float fStartX, float fStartY, float fEndX, float fEndY, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) +{ + CWorld::AdvanceCurrentScanCode(); + *nEntitiesFound = 0; + const int32 nStartX = max(CWorld::GetSectorIndexX(fStartX), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector* pSector = CWorld::GetSector(x, y); + if (bBuildings) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + } + if (bVehicles) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + } + if (bPeds) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_PEDS], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + } + if (bObjects) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + } + if (bDummies) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_DUMMIES], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + } + } + } +} + +void +CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { + pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + CColSphere sphere; + CVector vecDistance = pEntity->m_matrix.GetPosition() - position; + sphere.radius = pEntity->GetBoundRadius(); + sphere.center = Multiply3x3(vecDistance, matrix); + if (CCollision::TestSphereBox(sphere, boundingBox) && *nEntitiesFound < maxEntitiesToFind) { + if (aEntities) + aEntities[*nEntitiesFound] = pEntity; + ++*nEntitiesFound; + } + } + pNode = pNode->next; + } +} + +void +CWorld::FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bVehicles, bool bPeds, bool bObjects) +{ + CWorld::AdvanceCurrentScanCode(); + *nIntersecting = 0; + const int32 nStartX = max(CWorld::GetSectorIndexX(vecStartPos.x), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector* pSector = CWorld::GetSector(x, y); + if (bVehicles) { + CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, true, false); + CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, true, false); + } + if (bPeds) { + CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, false, true); + CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, false, true); + } + if (bObjects) { + CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, false, false); + CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, false, false); + } + } + } +} + +void +CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { + pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + bool bIsMissionEntity = false; + if (bIsVehicleList) + bIsMissionEntity = ((CVehicle*)pEntity)->VehicleCreatedBy == MISSION_VEHICLE; + else if (bIsPedList) + bIsMissionEntity = ((CPed*)pEntity)->CharCreatedBy == MISSION_CHAR; + else + bIsMissionEntity = ((CObject*)pEntity)->ObjectCreatedBy == MISSION_OBJECT; + float fRadius = pEntity->GetBoundRadius(); + const CVector& entityPos = pEntity->GetPosition(); + if (bIsMissionEntity && + fRadius + entityPos.x >= vecStartPos.x && entityPos.x - fRadius <= vecEndPos.x && + fRadius + entityPos.y >= vecStartPos.y && entityPos.y - fRadius <= vecEndPos.y && + fRadius + entityPos.z >= vecStartPos.z && entityPos.z - fRadius <= vecEndPos.z && + *nIntersecting < maxEntitiesToFind) { + if (aEntities) + aEntities[*nIntersecting] = (CEntity*)pEntity; + ++*nIntersecting; + } + } + pNode = pNode->next; + } +} + CPlayerPed* FindPlayerPed(void) { @@ -960,6 +1338,155 @@ FindPlayerHeading(void) return FindPlayerPed()->GetForward().Heading(); } + +void CWorld::ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2) +{ + CVehiclePool *pVehiclePool = CPools::GetVehiclePool(); + for (int32 i = 0; i < pVehiclePool->GetSize(); i++) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (pVehicle) { + const CVector& position = pVehicle->GetPosition(); + if (position.x >= x1 && position.x <= x2 && + position.y >= y1 && position.y <= y2 && + position.z >= z1 && position.z <= z2 && + !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { + if (pVehicle->pDriver) { + CPopulation::RemovePed(pVehicle->pDriver); + pVehicle->pDriver = nil; + } + for (int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) { + if (pVehicle->pPassengers[j]) { + CPopulation::RemovePed(pVehicle->pPassengers[j]); + pVehicle->pPassengers[j] = nil; + --pVehicle->m_nNumPassengers; + } + } + CCarCtrl::RemoveFromInterestingVehicleList(pVehicle); + CWorld::Remove(pVehicle); + delete pVehicle; + } + } + } +} + +void +CWorld::ClearPedsFromArea(float x1, float y1, float z1, float x2, float y2, float z2) +{ + CPedPool* pPedPool = CPools::GetPedPool(); + for (int32 i = 0; i < pPedPool->GetSize(); i++) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (pPed) { + const CVector& position = pPed->GetPosition(); + if (!pPed->IsPlayer() && pPed->CanBeDeleted() && + position.x >= x1 && position.x <= x2 && + position.y >= y1 && position.y <= y2 && + position.z >= z1 && position.z <= z2) { + CPopulation::RemovePed(pPed); + } + } + } +} + +void +CWorld::CallOffChaseForArea(float x1, float y1, float x2, float y2) +{ + CWorld::AdvanceCurrentScanCode(); + float fStartX = x1 - 10.0f; + float fStartY = y1 - 10.0f; + float fEndX = x2 + 10.0f; + float fEndY = y2 + 10.0f; + const int32 nStartX = max(CWorld::GetSectorIndexX(fStartX), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector* pSector = CWorld::GetSector(x, y); + CWorld::CallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES], x1, y1, x2, y2, fStartX, fStartY, fEndX, fEndY); + CWorld::CallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], x1, y1, x2, y2, fStartX, fStartY, fEndX, fEndY); + CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS], x1, y1, x2, y2); + CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], x1, y1, x2, y2); + } + } +} + +void +CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CVehicle *pVehicle = (CVehicle*)pNode->item; + if (pVehicle->m_scanCode != CWorld::ms_nCurrentScanCode) { + pVehicle->m_scanCode = CWorld::ms_nCurrentScanCode; + const CVector& vehiclePos = pVehicle->m_matrix.GetPosition(); + eCarMission carMission = pVehicle->AutoPilot.m_nCarMission; + if (pVehicle != FindPlayerVehicle() && + vehiclePos.x > fStartX && vehiclePos.x < fEndX && + vehiclePos.y > fStartY && vehiclePos.y < fEndY && + pVehicle->bIsLawEnforcer && + (carMission == MISSION_RAMPLAYER_FARAWAY || carMission == MISSION_RAMPLAYER_CLOSE || + carMission == MISSION_BLOCKPLAYER_FARAWAY || carMission == MISSION_BLOCKPLAYER_CLOSE) + ) { + pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; + CColModel* pColModel = pVehicle->GetColModel(); + bool bInsideSphere = false; + for (int32 i = 0; i < pColModel->numSpheres; i++) { + CVector pos = pVehicle->m_matrix * pColModel->spheres[i].center; + float fRadius = pColModel->spheres[i].radius; + if (pos.x + fRadius > x1 && pos.x - fRadius < x2 && pos.y + fRadius > y1 && pos.y - fRadius < y2) + bInsideSphere = true; + // Maybe break the loop when bInsideSphere is set to true? + } + if (bInsideSphere) { + if (pVehicle->m_matrix.GetPosition().x <= (x1 + x2) * 0.5f) + pVehicle->m_vecMoveSpeed.x = min(pVehicle->m_vecMoveSpeed.x, 0.0f); + else + pVehicle->m_vecMoveSpeed.x = max(pVehicle->m_vecMoveSpeed.x, 0.0f); + if (pVehicle->m_matrix.GetPosition().y <= (y1 + y2) * 0.5f) + pVehicle->m_vecMoveSpeed.y = min(pVehicle->m_vecMoveSpeed.y, 0.0f); + else + pVehicle->m_vecMoveSpeed.y = max(pVehicle->m_vecMoveSpeed.y, 0.0f); + } + } + } + pNode = pNode->next; + } +} + +void +CWorld::CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CPed* pPed = (CPed*)pNode->item; + const CVector& pedPos = pPed->GetPosition(); + if (pPed->m_scanCode != CWorld::ms_nCurrentScanCode) + { + pPed->m_scanCode = CWorld::ms_nCurrentScanCode; + if (pPed != FindPlayerPed() && pPed->m_leader != FindPlayerPed() && + pedPos.x > x1 && pedPos.x < x2 && + pedPos.y > y1 && pedPos.y < y2 && + (pPed->m_pedInObjective == FindPlayerPed() || pPed->m_carInObjective && pPed->m_carInObjective == FindPlayerVehicle()) && + pPed->m_nPedState != PED_DEAD && pPed->m_nPedState != PED_DIE && + (pPed->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || + pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || + pPed->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)) { + if (pPed->IsPedInControl()) { + if (pPed->m_nPedType == PEDTYPE_COP) + ((CCopPed*)pPed)->ClearPursuit(); + else + pPed->SetIdle(); + pPed->SetObjective(OBJECTIVE_NONE); + } + else { + pPed->m_prevObjective = OBJECTIVE_NONE; + pPed->m_nLastPedState = PED_IDLE; + } + } + } + } +} + void CWorld::RemoveEntityInsteadOfProcessingIt(CEntity* ent) { @@ -1056,6 +1583,214 @@ CWorld::ExtinguishAllCarFiresInArea(CVector point, float range) } } +void +CWorld::AddParticles(void) +{ + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector* pSector = GetSector(x, y); + CEntity::AddSteamsFromGround1(pSector->m_lists[ENTITYLIST_BUILDINGS]); + CEntity::AddSteamsFromGround1(pSector->m_lists[ENTITYLIST_DUMMIES]); + } + } +} + +void +CWorld::ShutDown(void) +{ + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector *pSector = GetSector(x, y); + CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_PEDS].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); + } + } + for (int32 i = 0; i < 4; i ++) { + CPtrNode* pNode = GetBigBuildingList((eLevelName)i).first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + // Maybe remove from world here? + delete pEntity; + } + pNode = pNode->next; + } + GetBigBuildingList((eLevelName)i).Flush(); + } + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector* pSector = GetSector(x, y); + if (pSector->m_lists[ENTITYLIST_BUILDINGS].first) { + sprintf(gString, "Building list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); + } + if (pSector->m_lists[ENTITYLIST_DUMMIES].first) { + sprintf(gString, "Dummy list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); + } + if (pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first) { + sprintf(gString, "Building overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first) { + sprintf(gString, "Vehicle overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].first) { + sprintf(gString, "Ped overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].first) { + sprintf(gString, "Object overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].first) { + sprintf(gString, "Dummy overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); + } + } + } + ms_listMovingEntityPtrs.Flush(); +} + +void +CWorld::ClearForRestart(void) +{ + if (CCutsceneMgr::HasLoaded()) + CCutsceneMgr::DeleteCutsceneData(); + CProjectileInfo::RemoveAllProjectiles(); + CObject::DeleteAllTempObjects(); + CObject::DeleteAllMissionObjects(); + CPopulation::ConvertAllObjectsToDummyObjects(); + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector *pSector = GetSector(x, y); + CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; + while (pNode) { + CEntity *pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = GetBigBuildingList(LEVEL_NONE).first; + while (pNode) { + CVehicle *pVehicle = (CVehicle*)pNode->item; + if (pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) { + CWorld::Remove(pVehicle); + delete pVehicle; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + } + } + CPools::CheckPoolsEmpty(); +} + +void +CWorld::RepositionCertainDynamicObjects() +{ + int32 i = CPools::GetDummyPool()->GetSize(); + while (--i >= 0) { + CDummy* dummy = CPools::GetDummyPool()->GetSlot(i); + if (dummy) { + RepositionOneObject(dummy); + } + } +} + +void +CWorld::RepositionOneObject(CEntity* pEntity) +{ + int16 modeId = pEntity->m_modelIndex; + if (MI_SINGLESTREETLIGHTS1 == modeId || MI_SINGLESTREETLIGHTS2 == modeId || MI_SINGLESTREETLIGHTS3 == modeId + || MI_DOUBLESTREETLIGHTS == modeId || MI_TREE1 == modeId || MI_TREE2 == modeId || MI_TREE3 == modeId + || MI_TREE4 == modeId || MI_TREE5 == modeId || MI_TREE6 == modeId || MI_TREE7 == modeId + || MI_TREE8 == modeId || MI_TREE9 == modeId || MI_TREE10 == modeId || MI_TREE11 == modeId + || MI_TREE12 == modeId || MI_TREE13 == modeId || MI_TREE14 == modeId || MI_TRAFFICLIGHTS == modeId + || MI_PARKINGMETER == modeId || MI_PHONEBOOTH1 == modeId || MI_WASTEBIN == modeId || MI_BIN == modeId + || MI_POSTBOX1 == modeId || MI_NEWSSTAND == modeId || MI_TRAFFICCONE == modeId || MI_DUMP1 == modeId + || MI_ROADWORKBARRIER1 == modeId || MI_BUSSIGN1 == modeId || MI_NOPARKINGSIGN1 == modeId + || MI_PHONESIGN == modeId || MI_TAXISIGN == modeId || MI_FISHSTALL01 == modeId || MI_FISHSTALL02 == modeId + || MI_FISHSTALL03 == modeId || MI_FISHSTALL04 == modeId || MI_BAGELSTAND2 == modeId || MI_FIRE_HYDRANT == modeId + || MI_BOLLARDLIGHT == modeId || MI_PARKTABLE == modeId) { + CVector& position = pEntity->m_matrix.GetPosition(); + float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z; + position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - fBoundingBoxMinZ; + pEntity->m_matrix.UpdateRW(); + pEntity->UpdateRwFrame(); + } else if (MI_BUOY == modeId) { + float fWaterLevel = 0.0f; + bool found = true; + const CVector& position = pEntity->m_matrix.GetPosition(); + float fGroundZ = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &found); + if (CWaterLevel::GetWaterLevelNoWaves(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &fWaterLevel)) { + if (!found || fWaterLevel > fGroundZ) { + CColModel* pColModel = pEntity->GetColModel(); + float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; + pEntity->m_matrix.GetPosition().z = 0.2f * fHeight + fWaterLevel - 0.5f * fHeight; + } + } + } +} + void CWorld::SetCarsOnFire(float x, float y, float z, float radius, CEntity *reason) { @@ -1069,6 +1804,60 @@ CWorld::SetCarsOnFire(float x, float y, float z, float radius, CEntity *reason) } } +void +CWorld::SetPedsOnFire(float x, float y, float z, float radius, CEntity* reason) +{ + int32 poolSize = CPools::GetPedPool()->GetSize(); + for (int32 i = poolSize - 1; i >= 0; i--) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (pPed && pPed->m_nPedState != PED_DEAD && !pPed->bInVehicle && !pPed->m_pFire && !pPed->bFireProof) { + if (Abs(pPed->GetPosition().z - z) < 5.0f && Abs(pPed->GetPosition().x - x) < radius && Abs(pPed->GetPosition().y - y) < radius) + gFireManager.StartFire(pPed, reason, 0.8f, true); + } + } +} + +void +CWorld::RemoveStaticObjects() +{ + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector* pSector = GetSector(x, y); + CPtrNode* pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); + } + } +} + void CWorld::Process(void) { @@ -1246,6 +2035,27 @@ CWorld::Process(void) } } } +/* +void +CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer) +{ + CVector2D vecStartPos(position.x - fRadius, position.y - fRadius); + CVector2D vecEndPos(position.x + fRadius, position.y + fRadius); + const int32 nStartX = max(CWorld::GetSectorIndexX(vecStartPos.x), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector* pSector = CWorld::GetSector(x, y); + CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], position, fRadius, fPower, pCreator, bDrecementBombTimer); + CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_PEDS], position, fRadius, fPower, pCreator, bDrecementBombTimer); + CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], position, fRadius, fPower, pCreator, bDrecementBombTimer); + } + } + +} +*/ STARTPATCHES InjectHook(0x4AE930, CWorld::Add, PATCH_JUMP); diff --git a/src/core/World.h b/src/core/World.h index 07e7889f..bcb9ca27 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -85,7 +85,7 @@ public: } } static void ClearScanCodes(void); - static void ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8); + static void ClearExcitingStuffFromArea(const CVector &pos, float radius, bool bRemoveProjectilesAndTidyUpShadows); static bool CameraToIgnoreThisObject(CEntity *ent); @@ -103,19 +103,26 @@ public: 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); - static void FindObjectsOfTypeInRangeSectorList(uint32, CPtrList&, CVector&, float, bool, short*, short, CEntity**); - static void FindObjectsOfTypeInRange(uint32, CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool); + static void FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities); + static void FindObjectsOfTypeInRange(uint32 modelId, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies); static float FindGroundZForCoord(float x, float y); static float FindGroundZFor3DCoord(float x, float y, float z, bool *found); static float FindRoofZFor3DCoord(float x, float y, float z, bool *found); static void RemoveReferencesToDeletedObject(CEntity*); - static void FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool); - static void FindObjectsIntersectingCube(const CVector &, const CVector &, int16*, int16, CEntity **, bool, bool, bool, bool, bool); + static void FindObjectsKindaColliding(const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies); + static void FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities); + static void FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies); + static void FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities); static void FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool); - static void FindMissionEntitiesIntersectingCube(const CVector&, const CVector&, int16*, int16, CEntity**, bool, bool, bool); - static void ClearCarsFromArea(float, float, float, float, float, float); - static void ClearPedsFromArea(float, float, float, float, float, float); - static void CallOffChaseForArea(float, float, float, float); + static void FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities); + static void FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bVehicles, bool bPeds, bool bObjects); + static void FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList); + + static void ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2); + static void ClearPedsFromArea(float x1, float y1, float z1, float x2, float y2, float z2); + static void CallOffChaseForArea(float x1, float y1, float x2, float y2); + static void CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY); + static void CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2); static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); } static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); } @@ -131,17 +138,19 @@ public: static void StopAllLawEnforcersInTheirTracks(); static void SetAllCarsCanBeDamaged(bool); static void ExtinguishAllCarFiresInArea(CVector, float); - static void SetCarsOnFire(float, float, float, float, CEntity*); - static void SetPedsOnFire(float, float, float, float, CEntity*); + static void SetCarsOnFire(float x, float y, float z, float radius, CEntity* reason); + static void SetPedsOnFire(float x, float y, float z, float radius, CEntity* reason); static void Initialise(); static void AddParticles(); static void ShutDown(); static void ClearForRestart(void); static void RepositionCertainDynamicObjects(); + static void RepositionOneObject(CEntity* pEntity); static void RemoveStaticObjects(); static void Process(); - static void TriggerExplosion(const CVector &, float, float, CEntity*, bool); + static void TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer); + static void TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer); }; extern CColPoint *gaTempSphereColPoints; diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 25e5db48..c0da6ede 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -865,6 +865,16 @@ CEntity::ModifyMatrixForBannerInWind(void) UpdateRwFrame(); } +void +CEntity::AddSteamsFromGround1(CPtrList& list) +{ + CPtrNode *pNode = list.first; + while (pNode) { + ((CEntity*)pNode->item)->AddSteamsFromGround(nil); + pNode = pNode->next; + } +} + #include class CEntity_ : public CEntity diff --git a/src/entities/Entity.h b/src/entities/Entity.h index ca501ba4..15333162 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -4,6 +4,7 @@ #include "Placeable.h" struct CReference; +class CPtrList; enum eEntityType { @@ -152,5 +153,7 @@ public: void ModifyMatrixForTreeInWind(void); void ModifyMatrixForBannerInWind(void); void ProcessLightsForEntity(void); + + static void AddSteamsFromGround1(CPtrList& list); }; static_assert(sizeof(CEntity) == 0x64, "CEntity: error"); diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index 867624c7..88773b83 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -383,7 +383,7 @@ CObject::DeleteAllTempObjects() } void -CObject::DeleteAllTempObjectInArea(CVector point, float fRadius) +CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius) { CObjectPool *objectPool = CPools::GetObjectPool(); for (int32 i = 0; i < objectPool->GetSize(); i++) { @@ -426,5 +426,5 @@ STARTPATCHES InjectHook(0x4BB010, &CObject::CanBeDeleted, PATCH_JUMP); InjectHook(0x4BBE60, &CObject::DeleteAllMissionObjects, PATCH_JUMP); InjectHook(0x4BBDF0, &CObject::DeleteAllTempObjects, PATCH_JUMP); - InjectHook(0x4BBED0, &CObject::DeleteAllTempObjectInArea, PATCH_JUMP); + InjectHook(0x4BBED0, &CObject::DeleteAllTempObjectsInArea, PATCH_JUMP); ENDPATCHES diff --git a/src/objects/Object.h b/src/objects/Object.h index 6d04c78a..80c742a0 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -99,6 +99,6 @@ public: static void DeleteAllMissionObjects(); static void DeleteAllTempObjects(); - static void DeleteAllTempObjectInArea(CVector point, float fRadius); + static void DeleteAllTempObjectsInArea(CVector point, float fRadius); }; static_assert(sizeof(CObject) == 0x198, "CObject: error"); From 2c2da558cac7e235d1dc89264aa78695aae32394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Thu, 16 Apr 2020 22:19:56 +0300 Subject: [PATCH 044/123] Some refs removed, little fixes and teleport --- src/animation/AnimManager.cpp | 12 +++++----- src/animation/AnimManager.h | 12 +++++----- src/animation/CutsceneMgr.cpp | 26 ++++++++++---------- src/animation/CutsceneMgr.h | 26 ++++++++++---------- src/audio/sampman.cpp | 3 +++ src/control/Bridge.cpp | 20 ++++++++-------- src/control/Bridge.h | 10 ++++---- src/control/Darkel.cpp | 40 +++++++++++++++---------------- src/control/Darkel.h | 32 ++++++++++++------------- src/control/Garages.cpp | 45 ++++++++++++++++++----------------- src/control/Garages.h | 44 +++++++++++++++++----------------- src/core/MenuScreens.h | 2 +- src/core/Radar.cpp | 8 ++++--- src/core/Radar.h | 5 ++-- src/core/re3.cpp | 18 ++++++++++++++ src/render/Sprite2d.cpp | 2 +- src/render/Sprite2d.h | 2 +- src/rw/Lights.cpp | 2 +- 18 files changed, 167 insertions(+), 142 deletions(-) diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index e5721bdf..82343e93 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -10,12 +10,12 @@ #include "AnimBlendAssocGroup.h" #include "AnimManager.h" -CAnimBlock *CAnimManager::ms_aAnimBlocks = (CAnimBlock*)0x6F01A0; -CAnimBlendHierarchy *CAnimManager::ms_aAnimations = (CAnimBlendHierarchy*)0x70F430; -int32 &CAnimManager::ms_numAnimBlocks = *(int32*)0x885AF8; -int32 &CAnimManager::ms_numAnimations = *(int32*)0x8E2DD4; -CAnimBlendAssocGroup *&CAnimManager::ms_aAnimAssocGroups = *(CAnimBlendAssocGroup**)0x8F583C; -CLinkList &CAnimManager::ms_animCache = *(CLinkList*)0x9414DC; +CAnimBlock CAnimManager::ms_aAnimBlocks[2]; +CAnimBlendHierarchy CAnimManager::ms_aAnimations[250]; +int32 CAnimManager::ms_numAnimBlocks; +int32 CAnimManager::ms_numAnimations; +CAnimBlendAssocGroup *CAnimManager::ms_aAnimAssocGroups; +CLinkList CAnimManager::ms_animCache; AnimAssocDesc aStdAnimDescs[] = { { ANIM_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_FLAG80 }, diff --git a/src/animation/AnimManager.h b/src/animation/AnimManager.h index 0d4e17fe..93fec74b 100644 --- a/src/animation/AnimManager.h +++ b/src/animation/AnimManager.h @@ -242,12 +242,12 @@ struct AnimAssocDefinition class CAnimManager { static const AnimAssocDefinition ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS]; - static CAnimBlock *ms_aAnimBlocks; //[2] - static CAnimBlendHierarchy *ms_aAnimations; //[250] - static int32 &ms_numAnimBlocks; - static int32 &ms_numAnimations; - static CAnimBlendAssocGroup *&ms_aAnimAssocGroups; - static CLinkList &ms_animCache; + static CAnimBlock ms_aAnimBlocks[2]; + static CAnimBlendHierarchy ms_aAnimations[250]; + static int32 ms_numAnimBlocks; + static int32 ms_numAnimations; + static CAnimBlendAssocGroup *ms_aAnimAssocGroups; + static CLinkList ms_animCache; public: static void Initialise(void); diff --git a/src/animation/CutsceneMgr.cpp b/src/animation/CutsceneMgr.cpp index 6f8e9790..5c0daaf0 100644 --- a/src/animation/CutsceneMgr.cpp +++ b/src/animation/CutsceneMgr.cpp @@ -117,19 +117,19 @@ FindCutsceneAudioTrackId(const char *szCutsceneName) return -1; } -bool &CCutsceneMgr::ms_running = *(bool*)0x95CCF5; -bool &CCutsceneMgr::ms_cutsceneProcessing = *(bool*)0x95CD9F; -CDirectory *&CCutsceneMgr::ms_pCutsceneDir = *(CDirectory**)0x8F5F88; -CCutsceneObject *(&CCutsceneMgr::ms_pCutsceneObjects)[NUMCUTSCENEOBJECTS] = *(CCutsceneObject*(*)[NUMCUTSCENEOBJECTS]) *(uintptr*) 0x862170; -int32 &CCutsceneMgr::ms_numCutsceneObjs = *(int32*)0x942FA4; -bool &CCutsceneMgr::ms_loaded = *(bool*)0x95CD95; -bool &CCutsceneMgr::ms_animLoaded = *(bool*)0x95CDA0; -bool &CCutsceneMgr::ms_useLodMultiplier = *(bool*)0x95CD74; -char(&CCutsceneMgr::ms_cutsceneName)[CUTSCENENAMESIZE] = *(char(*)[CUTSCENENAMESIZE]) *(uintptr*)0x70D9D0; -CAnimBlendAssocGroup &CCutsceneMgr::ms_cutsceneAssociations = *(CAnimBlendAssocGroup*)0x709C58; -CVector &CCutsceneMgr::ms_cutsceneOffset = *(CVector*)0x8F2C0C; -float &CCutsceneMgr::ms_cutsceneTimer = *(float*)0x941548; -uint32 &CCutsceneMgr::ms_cutsceneLoadStatus = *(uint32*)0x95CB40; +bool CCutsceneMgr::ms_running; +bool CCutsceneMgr::ms_cutsceneProcessing; +CDirectory *CCutsceneMgr::ms_pCutsceneDir; +CCutsceneObject *CCutsceneMgr::ms_pCutsceneObjects[NUMCUTSCENEOBJECTS]; +int32 CCutsceneMgr::ms_numCutsceneObjs; +bool CCutsceneMgr::ms_loaded; +bool CCutsceneMgr::ms_animLoaded; +bool CCutsceneMgr::ms_useLodMultiplier; +char CCutsceneMgr::ms_cutsceneName[CUTSCENENAMESIZE]; +CAnimBlendAssocGroup CCutsceneMgr::ms_cutsceneAssociations; +CVector CCutsceneMgr::ms_cutsceneOffset; +float CCutsceneMgr::ms_cutsceneTimer; +uint32 CCutsceneMgr::ms_cutsceneLoadStatus; RpAtomic * CalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data) diff --git a/src/animation/CutsceneMgr.h b/src/animation/CutsceneMgr.h index 3c915eea..b025816b 100644 --- a/src/animation/CutsceneMgr.h +++ b/src/animation/CutsceneMgr.h @@ -9,22 +9,22 @@ class CCutsceneHead; class CCutsceneMgr { - static bool &ms_running; - static CCutsceneObject *(&ms_pCutsceneObjects)[NUMCUTSCENEOBJECTS]; + static bool ms_running; + static CCutsceneObject *ms_pCutsceneObjects[NUMCUTSCENEOBJECTS]; - static int32 &ms_numCutsceneObjs; - static bool &ms_loaded; - static bool &ms_animLoaded; - static bool &ms_useLodMultiplier; + static int32 ms_numCutsceneObjs; + static bool ms_loaded; + static bool ms_animLoaded; + static bool ms_useLodMultiplier; - static char(&ms_cutsceneName)[CUTSCENENAMESIZE]; - static CAnimBlendAssocGroup &ms_cutsceneAssociations; - static CVector &ms_cutsceneOffset; - static float &ms_cutsceneTimer; - static bool &ms_cutsceneProcessing; + static char ms_cutsceneName[CUTSCENENAMESIZE]; + static CAnimBlendAssocGroup ms_cutsceneAssociations; + static CVector ms_cutsceneOffset; + static float ms_cutsceneTimer; + static bool ms_cutsceneProcessing; public: - static CDirectory *&ms_pCutsceneDir; - static uint32 &ms_cutsceneLoadStatus; + static CDirectory *ms_pCutsceneDir; + static uint32 ms_cutsceneLoadStatus; static void StartCutsceneProcessing() { ms_cutsceneProcessing = true; } static bool IsRunning(void) { return ms_running; } diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index 6dd744c3..7887c363 100644 --- a/src/audio/sampman.cpp +++ b/src/audio/sampman.cpp @@ -2221,6 +2221,9 @@ cSampleManager::InitialiseSampleBanks(void) for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) { +#ifdef FIX_BUGS + if (nBank >= MAX_SAMPLEBANKS) break; +#endif if ( BankStartOffset[nBank] == BankStartOffset[SAMPLEBANK_MAIN] + i ) { nSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset; diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp index 6a577449..53cf6af2 100644 --- a/src/control/Bridge.cpp +++ b/src/control/Bridge.cpp @@ -6,20 +6,20 @@ #include "PathFind.h" #include "Stats.h" -CEntity*& CBridge::pLiftRoad = *(CEntity**)0x8E2C8C; -CEntity*& CBridge::pLiftPart = *(CEntity**)0x8E2C94; -CEntity*& CBridge::pWeight = *(CEntity**)0x8E28BC; +CEntity *CBridge::pLiftRoad; +CEntity *CBridge::pLiftPart; +CEntity *CBridge::pWeight; -int& CBridge::State = *(int*)0x8F2A1C; -int& CBridge::OldState = *(int*)0x8F2A20; +int CBridge::State; +int CBridge::OldState; -float& CBridge::DefaultZLiftPart = *(float*)0x941430; -float& CBridge::DefaultZLiftRoad = *(float*)0x941438; -float& CBridge::DefaultZLiftWeight = *(float*)0x8F1A44; +float CBridge::DefaultZLiftPart; +float CBridge::DefaultZLiftRoad; +float CBridge::DefaultZLiftWeight; -float& CBridge::OldLift = *(float*)0x8F6254; +float CBridge::OldLift; -uint32& CBridge::TimeOfBridgeBecomingOperational = *(uint32*)0x8F2BC0; +uint32 CBridge::TimeOfBridgeBecomingOperational; void CBridge::Init() { diff --git a/src/control/Bridge.h b/src/control/Bridge.h index 63f41578..c5702629 100644 --- a/src/control/Bridge.h +++ b/src/control/Bridge.h @@ -14,11 +14,11 @@ enum bridgeStates { class CBridge { public: - static CEntity *&pLiftRoad, *&pLiftPart, *&pWeight; - static int &State, &OldState; - static float &DefaultZLiftPart, &DefaultZLiftRoad, &DefaultZLiftWeight; - static float &OldLift; - static uint32 &TimeOfBridgeBecomingOperational; + static CEntity *pLiftRoad, *pLiftPart, *pWeight; + static int State, OldState; + static float DefaultZLiftPart, DefaultZLiftRoad, DefaultZLiftWeight; + static float OldLift; + static uint32 TimeOfBridgeBecomingOperational; static void Init(); static void Update(); diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index b4d15abf..3265d1c2 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -17,29 +17,29 @@ #define FRENZY_ANY_PED -1 #define FRENZY_ANY_CAR -2 -int32 &CDarkel::TimeLimit = *(int32*)0x885BAC; -int32 &CDarkel::PreviousTime = *(int32*)0x885B00; -int32 &CDarkel::TimeOfFrenzyStart = *(int32*)0x9430D8; -int32 &CDarkel::WeaponType = *(int32*)0x9430F0; -int32 &CDarkel::AmmoInterruptedWeapon = *(int32*)0x8E29C8; -int32 &CDarkel::KillsNeeded = *(int32*)0x8F1AB8; -int8 &CDarkel::InterruptedWeapon = *(int8*)0x95CD60; +int32 CDarkel::TimeLimit; +int32 CDarkel::PreviousTime; +int32 CDarkel::TimeOfFrenzyStart; +int32 CDarkel::WeaponType; +int32 CDarkel::AmmoInterruptedWeapon; +int32 CDarkel::KillsNeeded; +int8 CDarkel::InterruptedWeapon; /* * bStandardSoundAndMessages is a completely beta thing, * makes game handle sounds & messages instead of SCM (just like in GTA2) * but it's never been used in the game. Has unused sliding text when frenzy completed etc. */ -int8 &CDarkel::bStandardSoundAndMessages = *(int8*)0x95CDB6; -int8 &CDarkel::bNeedHeadShot = *(int8*)0x95CDCA; -int8 &CDarkel::bProperKillFrenzy = *(int8*)0x95CD98; -uint16 &CDarkel::Status = *(uint16*)0x95CCB4; -uint16 (&CDarkel::RegisteredKills)[NUM_DEFAULT_MODELS] = *(uint16(*)[NUM_DEFAULT_MODELS]) * (uintptr*)0x6EDBE0; -int32 &CDarkel::ModelToKill = *(int32*)0x8F2C78; -int32 &CDarkel::ModelToKill2 = *(int32*)0x885B40; -int32 &CDarkel::ModelToKill3 = *(int32*)0x885B3C; -int32 &CDarkel::ModelToKill4 = *(int32*)0x885B34; -wchar *CDarkel::pStartMessage = (wchar*)0x8F2C08; +int8 CDarkel::bStandardSoundAndMessages; +int8 CDarkel::bNeedHeadShot; +int8 CDarkel::bProperKillFrenzy; +uint16 CDarkel::Status; +uint16 CDarkel::RegisteredKills[NUM_DEFAULT_MODELS]; +int32 CDarkel::ModelToKill; +int32 CDarkel::ModelToKill2; +int32 CDarkel::ModelToKill3; +int32 CDarkel::ModelToKill4; +wchar *CDarkel::pStartMessage; uint8 CDarkel::CalcFade(uint32 time, uint32 start, uint32 end) @@ -262,10 +262,10 @@ CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 mode pStartMessage = text; if (text == TheText.Get("PAGE_00")) { - CDarkel::bProperKillFrenzy = 1; - CDarkel::pStartMessage = 0; + CDarkel::bProperKillFrenzy = true; + CDarkel::pStartMessage = nil; } else - bProperKillFrenzy = 0; + bProperKillFrenzy = false; bStandardSoundAndMessages = standardSound; bNeedHeadShot = needHeadShot; diff --git a/src/control/Darkel.h b/src/control/Darkel.h index 12ce4451..b6092dcb 100644 --- a/src/control/Darkel.h +++ b/src/control/Darkel.h @@ -16,22 +16,22 @@ enum class CDarkel { private: - static int32 &TimeLimit; - static int32 &PreviousTime; - static int32 &TimeOfFrenzyStart; - static int32 &WeaponType; - static int32 &AmmoInterruptedWeapon; - static int32 &KillsNeeded; - static int8 &InterruptedWeapon; - static int8 &bStandardSoundAndMessages; - static int8 &bNeedHeadShot; - static int8 &bProperKillFrenzy; - static uint16 &Status; - static uint16 (&RegisteredKills)[NUM_DEFAULT_MODELS]; - static int32 &ModelToKill; - static int32 &ModelToKill2; - static int32 &ModelToKill3; - static int32 &ModelToKill4; + static int32 TimeLimit; + static int32 PreviousTime; + static int32 TimeOfFrenzyStart; + static int32 WeaponType; + static int32 AmmoInterruptedWeapon; + static int32 KillsNeeded; + static int8 InterruptedWeapon; + static int8 bStandardSoundAndMessages; + static int8 bNeedHeadShot; + static int8 bProperKillFrenzy; + static uint16 Status; + static uint16 RegisteredKills[NUM_DEFAULT_MODELS]; + static int32 ModelToKill; + static int32 ModelToKill2; + static int32 ModelToKill3; + static int32 ModelToKill4; static wchar *pStartMessage; public: diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index d187f666..cca8c3b8 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -111,27 +111,27 @@ const int32 gaCarsToCollectInCraigsGarages[TOTAL_COLLECTCARS_GARAGES][TOTAL_COLL { MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_CHEETAH, MI_TAXI, MI_ESPERANT, MI_SENTINEL, MI_IDAHO } }; -int32& CGarages::BankVansCollected = *(int32*)0x8F1B34; -bool& CGarages::BombsAreFree = *(bool*)0x95CD7A; -bool& CGarages::RespraysAreFree = *(bool*)0x95CD1D; -int32& CGarages::CarsCollected = *(int32*)0x880E18; -int32(&CGarages::CarTypesCollected)[TOTAL_COLLECTCARS_GARAGES] = *(int32(*)[TOTAL_COLLECTCARS_GARAGES]) * (uintptr*)0x8E286C; -int32& CGarages::CrushedCarId = *(int32*)0x943060; -uint32& CGarages::LastTimeHelpMessage = *(uint32*)0x8F1B58; -int32& CGarages::MessageNumberInString = *(int32*)0x885BA8; -char(&CGarages::MessageIDString)[MESSAGE_LENGTH] = *(char(*)[MESSAGE_LENGTH]) * (uintptr*)0x878358; -int32& CGarages::MessageNumberInString2 = *(int32*)0x8E2C14; -uint32& CGarages::MessageStartTime = *(uint32*)0x8F2530; -uint32& CGarages::MessageEndTime = *(uint32*)0x8F597C; -uint32& CGarages::NumGarages = *(uint32*)0x8F29F4; -bool& CGarages::PlayerInGarage = *(bool*)0x95CD83; -int32& CGarages::PoliceCarsCollected = *(int32*)0x941444; -CStoredCar(&CGarages::aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA210; -CStoredCar(&CGarages::aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA300; -CStoredCar(&CGarages::aCarsInSafeHouse3)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA3F0; -int32& CGarages::AudioEntity = *(int32*)0x5ECEA8; -CGarage(&CGarages::aGarages)[NUM_GARAGES] = *(CGarage(*)[NUM_GARAGES]) * (uintptr*)0x72BCD0; -bool& CGarages::bCamShouldBeOutisde = *(bool*)0x95CDB2; +int32 CGarages::BankVansCollected; +bool CGarages::BombsAreFree; +bool CGarages::RespraysAreFree; +int32 CGarages::CarsCollected; +int32 CGarages::CarTypesCollected[TOTAL_COLLECTCARS_GARAGES]; +int32 CGarages::CrushedCarId; +uint32 CGarages::LastTimeHelpMessage; +int32 CGarages::MessageNumberInString; +char CGarages::MessageIDString[MESSAGE_LENGTH]; +int32 CGarages::MessageNumberInString2; +uint32 CGarages::MessageStartTime; +uint32 CGarages::MessageEndTime; +uint32 CGarages::NumGarages; +bool CGarages::PlayerInGarage; +int32 CGarages::PoliceCarsCollected; +CStoredCar CGarages::aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS]; +CStoredCar CGarages::aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS]; +CStoredCar CGarages::aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS]; +int32 CGarages::AudioEntity = AEHANDLE_NONE; +CGarage CGarages::aGarages[NUM_GARAGES]; +bool CGarages::bCamShouldBeOutisde; void CGarages::Init(void) { @@ -2256,7 +2256,7 @@ void CGarages::Save(uint8 * buf, uint32 * size) #endif } -CStoredCar::CStoredCar(const CStoredCar & other) +const CStoredCar &CStoredCar::operator=(const CStoredCar & other) { m_nModelIndex = other.m_nModelIndex; m_vecPos = other.m_vecPos; @@ -2272,6 +2272,7 @@ CStoredCar::CStoredCar(const CStoredCar & other) m_nVariationA = other.m_nVariationA; m_nVariationB = other.m_nVariationB; m_nCarBombType = other.m_nCarBombType; + return *this; } void CGarages::Load(uint8* buf, uint32 size) diff --git a/src/control/Garages.h b/src/control/Garages.h index 26e7a89a..65193b32 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -70,7 +70,7 @@ public: void Init() { m_nModelIndex = 0; } void Clear() { m_nModelIndex = 0; } bool HasCar() { return m_nModelIndex != 0; } - CStoredCar(const CStoredCar& other); + const CStoredCar &operator=(const CStoredCar& other); void StoreCar(CVehicle*); CVehicle* RestoreCar(); }; @@ -179,27 +179,27 @@ class CGarages enum { MESSAGE_LENGTH = 8 }; - static int32 &BankVansCollected; - static bool &BombsAreFree; - static bool &RespraysAreFree; - static int32 &CarsCollected; - static int32 (&CarTypesCollected)[TOTAL_COLLECTCARS_GARAGES]; - static int32 &CrushedCarId; - static uint32 &LastTimeHelpMessage; - static int32 &MessageNumberInString; - static char(&MessageIDString)[MESSAGE_LENGTH]; - static int32 &MessageNumberInString2; - static uint32 &MessageStartTime; - static uint32 &MessageEndTime; - static uint32 &NumGarages; - static bool &PlayerInGarage; - static int32 &PoliceCarsCollected; - static CGarage(&aGarages)[NUM_GARAGES]; - static CStoredCar(&aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS]; - static CStoredCar(&aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS]; - static CStoredCar(&aCarsInSafeHouse3)[NUM_GARAGE_STORED_CARS]; - static int32 &AudioEntity; - static bool &bCamShouldBeOutisde; + static int32 BankVansCollected; + static bool BombsAreFree; + static bool RespraysAreFree; + static int32 CarsCollected; + static int32 CarTypesCollected[TOTAL_COLLECTCARS_GARAGES]; + static int32 CrushedCarId; + static uint32 LastTimeHelpMessage; + static int32 MessageNumberInString; + static char MessageIDString[MESSAGE_LENGTH]; + static int32 MessageNumberInString2; + static uint32 MessageStartTime; + static uint32 MessageEndTime; + static uint32 NumGarages; + static bool PlayerInGarage; + static int32 PoliceCarsCollected; + static CGarage aGarages[NUM_GARAGES]; + static CStoredCar aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS]; + static CStoredCar aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS]; + static CStoredCar aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS]; + static int32 AudioEntity; + static bool bCamShouldBeOutisde; public: static void Init(void); diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.h index e1b1bac6..8692d4dc 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.h @@ -32,7 +32,7 @@ const CMenuScreen aScreens[] = { MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, - // MENU_CONTROLLER_SETTINGS = 4 + // MENUPAGE_CONTROLLER_SETTINGS = 4 { "FET_CON", 1, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, 0, 0, MENUACTION_CTRLCONFIG, "FEC_CCF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, MENUACTION_CTRLDISPLAY, "FEC_CDP", SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS, diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 154e7e9a..ed24814d 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -16,9 +16,9 @@ #include "Streaming.h" #include "SpecialFX.h" -float &CRadar::m_radarRange = *(float*)0x8E281C; -sRadarTrace (&CRadar::ms_RadarTrace)[NUMRADARBLIPS] = *(sRadarTrace(*)[NUMRADARBLIPS]) * (uintptr*)0x6ED5E0; -CVector2D &vec2DRadarOrigin = *(CVector2D*)0x6299B8; +float CRadar::m_radarRange; +sRadarTrace CRadar::ms_RadarTrace[NUMRADARBLIPS]; +CVector2D vec2DRadarOrigin; int32 gRadarTxdIds[64];// = (int*)0x6299C0; CSprite2d CRadar::AsukaSprite;// = *(CSprite2d*)0x8F1A40; @@ -81,6 +81,7 @@ CRGBA CRadar::ArrowBlipColour2; uint16 CRadar::MapLegendCounter; uint16 CRadar::MapLegendList[NUM_MAP_LEGENDS]; int CRadar::TargetMarkerId = -1; +CVector CRadar::TargetMarkerPos; #endif // taken from VC @@ -1442,6 +1443,7 @@ CRadar::ToggleTargetMarker(float x, float y) ms_RadarTrace[nextBlip].m_bInUse = 1; ms_RadarTrace[nextBlip].m_Radius = 1.0f; CVector pos(x, y, CWorld::FindGroundZForCoord(x,y)); + TargetMarkerPos = pos; ms_RadarTrace[nextBlip].m_vec2DPos = pos; ms_RadarTrace[nextBlip].m_vecPos = pos; ms_RadarTrace[nextBlip].m_nEntityHandle = 0; diff --git a/src/core/Radar.h b/src/core/Radar.h index 27f3a6f0..e39a17f0 100644 --- a/src/core/Radar.h +++ b/src/core/Radar.h @@ -82,8 +82,8 @@ static_assert(sizeof(sRadarTrace) == 0x30, "sRadarTrace: error"); class CRadar { public: - static float &m_radarRange; - static sRadarTrace (&ms_RadarTrace)[NUMRADARBLIPS]; + static float m_radarRange; + static sRadarTrace ms_RadarTrace[NUMRADARBLIPS]; static CSprite2d AsukaSprite; static CSprite2d BombSprite; static CSprite2d CatSprite; @@ -114,6 +114,7 @@ public: static uint16 MapLegendList[NUM_MAP_LEGENDS]; static uint16 MapLegendCounter; static int TargetMarkerId; + static CVector TargetMarkerPos; static void InitFrontEndMap(); static void DrawYouAreHereSprite(float, float); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 5d76d642..ecf02f39 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -24,6 +24,8 @@ #include "Hud.h" #include "SceneEdit.h" #include "Pad.h" +#include "PlayerPed.h" +#include "Radar.h" #include @@ -164,6 +166,19 @@ FixCar(void) ((CAutomobile*)veh)->Fix(); } +#ifdef MENU_MAP +static void +TeleportToWaypoint(void) +{ + if (FindPlayerVehicle()) { + if (CRadar::TargetMarkerId != -1) + FindPlayerVehicle()->Teleport(CRadar::TargetMarkerPos + CVector(0.0f, 0.0f, FindPlayerVehicle()->GetColModel()->boundingSphere.center.z)); + } else + if(CRadar::TargetMarkerId != -1) + FindPlayerPed()->Teleport(CRadar::TargetMarkerPos + CVector(0.0f, 0.0f, FEET_OFFSET)); +} +#endif + static int engineStatus; static void SetEngineStatus(void) @@ -359,6 +374,9 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil); DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil); DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); +#ifdef MENU_MAP + DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); +#endif #ifdef TOGGLEABLE_BETA_FEATURES DebugMenuAddVarBool8("Debug", "Toggle banned particles", (int8*)&CParticle::bEnableBannedParticles, nil); DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil); diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index 1fe70121..655fd841 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -5,7 +5,7 @@ #include "Camera.h" #include "Sprite2d.h" -RwIm2DVertex CSprite2d::maVertices[4]; +RwIm2DVertex CSprite2d::maVertices[8]; float CSprite2d::RecipNearClip; int32 CSprite2d::mCurrentBank; RwTexture *CSprite2d::mpBankTextures[10]; diff --git a/src/render/Sprite2d.h b/src/render/Sprite2d.h index 0b073557..0e12d441 100644 --- a/src/render/Sprite2d.h +++ b/src/render/Sprite2d.h @@ -8,7 +8,7 @@ class CSprite2d static int32 mCurrentSprite[10]; static int32 mBankStart[10]; static RwIm2DVertex maBankVertices[500]; - static RwIm2DVertex maVertices[4]; + static RwIm2DVertex maVertices[8]; public: RwTexture *m_pTexture; diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp index 9218a055..112c8982 100644 --- a/src/rw/Lights.cpp +++ b/src/rw/Lights.cpp @@ -108,7 +108,7 @@ LightsCreate(RpWorld *world) pDirect = RpLightCreate(rpLIGHTDIRECTIONAL); RpLightSetFlags(pDirect, rpLIGHTLIGHTATOMICS); color.red = 1.0f; - color.green = 0.84f; + color.green = 0.85f; color.blue = 0.45f; RpLightSetColor(pDirect, &color); RpLightSetRadius(pDirect, 2.0f); From 6b1093f1c8f2a2c59383c2d8f2223b22e2f6cb42 Mon Sep 17 00:00:00 2001 From: saml1er Date: Fri, 17 Apr 2020 03:20:34 +0500 Subject: [PATCH 045/123] CWorld complete --- src/core/World.cpp | 147 +++++++++++++++++++++++++++++------ src/core/World.h | 2 +- src/modelinfo/ModelIndices.h | 7 ++ 3 files changed, 133 insertions(+), 23 deletions(-) diff --git a/src/core/World.cpp b/src/core/World.cpp index 324be962..131625a5 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -26,6 +26,9 @@ #include "Object.h" #include "Shadows.h" #include "Explosion.h" +#include "Glass.h" +#include "ParticleObject.h" +#include "EventList.h" #define OBJECT_REPOSITION_OFFSET_Z 0.2f @@ -48,26 +51,6 @@ bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B; bool &CWorld::bDoingCarCollisions = *(bool*)0x95CD8C; bool &CWorld::bIncludeCarTyres = *(bool*)0x95CDAA; -//WRAPPER void CWorld::ClearForRestart(void) { EAXJMP(0x4AE850); } -//WRAPPER void CWorld::AddParticles(void) { EAXJMP(0x4B4010); } -//WRAPPER void CWorld::ShutDown(void) { EAXJMP(0x4AE450); } -//WRAPPER void CWorld::RepositionCertainDynamicObjects() { EAXJMP(0x4B42B0); } -//WRAPPER void CWorld::RemoveStaticObjects() { EAXJMP(0x4B4D50); } -//WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); } -//WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); } -//WRAPPER void CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8 unused) { EAXJMP(0x4B4E70) }; -//WRAPPER void CWorld::FindObjectsIntersectingCube(const CVector &, const CVector &, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B2E70); } -//WRAPPER void CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B3280); } -//WRAPPER void CWorld::FindObjectsOfTypeInRange(uint32, CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool) { EAXJMP(0x4B2600); } -//WRAPPER void CWorld::FindObjectsOfTypeInRangeSectorList(uint32, CPtrList&, CVector&, float, bool, short*, short, CEntity**) { EAXJMP(0x4B2960); } -//WRAPPER void CWorld::FindMissionEntitiesIntersectingCube(const CVector&, const CVector&, int16*, int16, CEntity**, bool, bool, bool) { EAXJMP(0x4B3680); } -//WRAPPER void CWorld::ClearCarsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B50E0); } -//WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B52B0); } -//WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); } -WRAPPER void CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity *pCreator, bool bProcessVehicleBombTimer) { EAXJMP(0x4B1140); } -//WRAPPER void CWorld::SetPedsOnFire(float, float, float, float, CEntity*) { EAXJMP(0x4B3D30); } -WRAPPER void CWorld::UseDetonator(CEntity *) { EAXJMP(0x4B4650); } - void CWorld::Initialise() { @@ -2037,7 +2020,6 @@ CWorld::Process(void) } } -/* void CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer) { @@ -2057,7 +2039,128 @@ CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, C } } -*/ + +void +CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CPhysical* pEntity = (CPhysical*)pNode->item; + CVector vecDistance = pEntity->m_matrix.GetPosition() - position; + float fMagnitude = vecDistance.Magnitude(); + if (fRadius > fMagnitude) { + CWeapon::BlowUpExplosiveThings(pEntity); + CPed* pPed = (CPed*)pEntity; + CObject* pObject = (CObject*)pEntity; + CVehicle* pVehicle = (CVehicle*)pEntity; + if (!pEntity->bExplosionProof && (!pEntity->IsPed() || !pPed->bInVehicle)) { + if (pEntity->bIsStatic) { + if (pEntity->IsObject()) { + if (fPower > pObject->m_fUprootLimit || IsFence(pObject->m_modelIndex)) { + if (IsGlass(pObject->m_modelIndex)) { + CGlass::WindowRespondsToExplosion(pObject, position); + } else { + pObject->bIsStatic = false; + pObject->AddToMovingList(); + int16 modelId = pEntity->m_modelIndex; + if (modelId != MI_FIRE_HYDRANT || pObject->bHasBeenDamaged) { + if (pEntity->IsObject() && modelId != MI_EXPLODINGBARREL && modelId != MI_PETROLPUMP) + pObject->bHasBeenDamaged = true; + } else { + CVector pos = pEntity->m_matrix.GetPosition(); + pos.z -= 0.5f; + CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, pos, true); + pObject->bHasBeenDamaged = true; + } + } + } + if (pEntity->bIsStatic) { + float fDamageMultiplier = (fRadius - fMagnitude) * 2.0f / fRadius; + float fDamage = 300.0f * min(fDamageMultiplier, 1.0f); + pObject->ObjectDamage(fDamage); + } + } else { + pEntity->bIsStatic = false; + pEntity->AddToMovingList(); + } + } + if (!pEntity->bIsStatic) { + float fDamageMultiplier = min((fRadius - fMagnitude) * 2.0f / fRadius, 1.0f); + CVector vecForceDir = vecDistance * (fPower * pEntity->m_fMass * 0.00071429f * fDamageMultiplier / max(fMagnitude, 0.01f)); + vecForceDir.z = max(vecForceDir.z, 0.0f); + if (pEntity == FindPlayerPed()) + vecForceDir.z = min(vecForceDir.z, 1.0f); + pEntity->ApplyMoveForce(vecForceDir); + if (!pEntity->bPedPhysics) { + float fBoundRadius = pEntity->GetBoundRadius(); + float fDistanceZ = position.z - pEntity->m_matrix.GetPosition().z; + float fPointZ = fBoundRadius; + if (max(fDistanceZ, -fBoundRadius) < fBoundRadius) + { + if (fDistanceZ <= -fBoundRadius) + fPointZ = -fBoundRadius; + else + fPointZ = fDistanceZ; + } + pEntity->ApplyTurnForce(vecForceDir.x, vecForceDir.y, vecForceDir.z, 0.0f, 0.0f, fPointZ); + } + switch (pEntity->m_type) + { + case ENTITY_TYPE_VEHICLE: + if (pEntity->m_status == STATUS_SIMPLE) { + pEntity->m_status = STATUS_PHYSICS; + CCarCtrl::SwitchVehicleToRealPhysics(pVehicle); + } + pVehicle->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, 1100.0f * fDamageMultiplier); + if (bProcessVehicleBombTimer) { + if (pVehicle->m_nBombTimer) + pVehicle->m_nBombTimer /= 10; + } + break; + case ENTITY_TYPE_PED: { + int8 direction = pPed->GetLocalDirection(-vecForceDir); + pPed->bIsStanding = false; + pPed->ApplyMoveForce(0.0, 0.0, 2.0f); + float fDamage = 250.0f * fDamageMultiplier; + pPed->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, fDamage, PEDPIECE_TORSO, direction); + if (pPed->m_nPedState!= PED_DIE) + pPed->SetFall(2000, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0); + if (pCreator && pCreator->IsPed()) { + eEventType eventType = EVENT_SHOOT_PED; + if (pPed->m_nPedType == PEDTYPE_COP) + eventType = EVENT_SHOOT_COP; + CEventList::RegisterEvent(eventType, EVENT_ENTITY_PED, pEntity, (CPed*)pCreator, 10000); + pPed->RegisterThreatWithGangPeds(pCreator); + } + break; + } + case ENTITY_TYPE_OBJECT: + pObject->ObjectDamage(300.0f * fDamageMultiplier); + break; + } + } + } + } + pNode = pNode->next; + } +} + +void +CWorld::UseDetonator(CEntity* pEntity) +{ + int32 i = CPools::GetVehiclePool()->GetSize(); + while (--i >= 0) { + CAutomobile* pVehicle = (CAutomobile*)CPools::GetVehiclePool()->GetSlot(i); + if (pVehicle && !pVehicle->m_vehType && pVehicle->m_bombType == CARBOMB_REMOTE && pVehicle->m_pBombRigger == pEntity) { + pVehicle->m_bombType = CARBOMB_NONE; + pVehicle->m_nBombTimer = 500; + pVehicle->m_pBlowUpEntity = pVehicle->m_pBombRigger; + if (pVehicle->m_pBlowUpEntity) + pVehicle->m_pBlowUpEntity->RegisterReference(&pVehicle->m_pBlowUpEntity); + } + } +} + STARTPATCHES InjectHook(0x4AE930, CWorld::Add, PATCH_JUMP); InjectHook(0x4AE9D0, CWorld::Remove, PATCH_JUMP); diff --git a/src/core/World.h b/src/core/World.h index fcf7b7cb..a1e2acfd 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -151,7 +151,7 @@ public: static void Process(); static void TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer); static void TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer); - static void UseDetonator(CEntity *); + static void UseDetonator(CEntity *pEntity); }; extern CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 309fa1bb..cc8399e7 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -496,4 +496,11 @@ IsExplosiveThingModel(int16 id) { return id == MI_EXPLODINGBARREL || id == MI_PETROLPUMP; +} + +inline bool +IsFence(int16 id) +{ + return id == MI_FENCE || + id == MI_FENCE2; } \ No newline at end of file From 03247ce98f9f6b9f09861e50c8903ec6221e42fa Mon Sep 17 00:00:00 2001 From: saml1er Date: Fri, 17 Apr 2020 03:54:22 +0500 Subject: [PATCH 046/123] Fix CWorld::RepositionOneObject bugs --- src/core/World.cpp | 61 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/core/World.cpp b/src/core/World.cpp index 131625a5..a9571c8b 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1743,30 +1743,59 @@ CWorld::RepositionCertainDynamicObjects() void CWorld::RepositionOneObject(CEntity* pEntity) { - int16 modeId = pEntity->m_modelIndex; - if (MI_SINGLESTREETLIGHTS1 == modeId || MI_SINGLESTREETLIGHTS2 == modeId || MI_SINGLESTREETLIGHTS3 == modeId - || MI_DOUBLESTREETLIGHTS == modeId || MI_TREE1 == modeId || MI_TREE2 == modeId || MI_TREE3 == modeId - || MI_TREE4 == modeId || MI_TREE5 == modeId || MI_TREE6 == modeId || MI_TREE7 == modeId - || MI_TREE8 == modeId || MI_TREE9 == modeId || MI_TREE10 == modeId || MI_TREE11 == modeId - || MI_TREE12 == modeId || MI_TREE13 == modeId || MI_TREE14 == modeId || MI_TRAFFICLIGHTS == modeId - || MI_PARKINGMETER == modeId || MI_PHONEBOOTH1 == modeId || MI_WASTEBIN == modeId || MI_BIN == modeId - || MI_POSTBOX1 == modeId || MI_NEWSSTAND == modeId || MI_TRAFFICCONE == modeId || MI_DUMP1 == modeId - || MI_ROADWORKBARRIER1 == modeId || MI_BUSSIGN1 == modeId || MI_NOPARKINGSIGN1 == modeId - || MI_PHONESIGN == modeId || MI_TAXISIGN == modeId || MI_FISHSTALL01 == modeId || MI_FISHSTALL02 == modeId - || MI_FISHSTALL03 == modeId || MI_FISHSTALL04 == modeId || MI_BAGELSTAND2 == modeId || MI_FIRE_HYDRANT == modeId - || MI_BOLLARDLIGHT == modeId || MI_PARKTABLE == modeId) { + int16 modelId = pEntity->m_modelIndex; + if (modelId == MI_SINGLESTREETLIGHTS1 + || modelId == MI_SINGLESTREETLIGHTS2 + || modelId == MI_SINGLESTREETLIGHTS3 + || modelId == MI_DOUBLESTREETLIGHTS + || modelId == MI_TREE1 + || modelId == MI_TREE2 + || modelId == MI_TREE3 + || modelId == MI_TREE4 + || modelId == MI_TREE5 + || modelId == MI_TREE6 + || modelId == MI_TREE7 + || modelId == MI_TREE8 + || modelId == MI_TREE9 + || modelId == MI_TREE10 + || modelId == MI_TREE11 + || modelId == MI_TREE12 + || modelId == MI_TREE13 + || modelId == MI_TREE14 + || modelId == MI_TRAFFICLIGHTS + || modelId == MI_PARKINGMETER + || modelId == MI_PHONEBOOTH1 + || modelId == MI_WASTEBIN + || modelId == MI_BIN + || modelId == MI_POSTBOX1 + || modelId == MI_NEWSSTAND + || modelId == MI_TRAFFICCONE + || modelId == MI_DUMP1 + || modelId == MI_ROADWORKBARRIER1 + || modelId == MI_BUSSIGN1 + || modelId == MI_NOPARKINGSIGN1 + || modelId == MI_PHONESIGN + || modelId == MI_TAXISIGN + || modelId == MI_FISHSTALL01 + || modelId == MI_FISHSTALL02 + || modelId == MI_FISHSTALL03 + || modelId == MI_FISHSTALL04 + || modelId == MI_BAGELSTAND2 + || modelId == MI_FIRE_HYDRANT + || modelId == MI_BOLLARDLIGHT + || modelId == MI_PARKTABLE) { CVector& position = pEntity->m_matrix.GetPosition(); float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z; position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - fBoundingBoxMinZ; pEntity->m_matrix.UpdateRW(); pEntity->UpdateRwFrame(); - } else if (MI_BUOY == modeId) { + } else if (modelId == MI_BUOY) { float fWaterLevel = 0.0f; - bool found = true; + bool bFound = true; const CVector& position = pEntity->m_matrix.GetPosition(); - float fGroundZ = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &found); + float fGroundZ = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &bFound); if (CWaterLevel::GetWaterLevelNoWaves(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &fWaterLevel)) { - if (!found || fWaterLevel > fGroundZ) { + if (!bFound || fWaterLevel > fGroundZ) { CColModel* pColModel = pEntity->GetColModel(); float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; pEntity->m_matrix.GetPosition().z = 0.2f * fHeight + fWaterLevel - 0.5f * fHeight; From e777f240642a6f287d08d7c536e878cae372fdfa Mon Sep 17 00:00:00 2001 From: saml1er Date: Fri, 17 Apr 2020 05:38:05 +0500 Subject: [PATCH 047/123] More CWorld fixes --- src/core/World.cpp | 48 ++++++++++++++++++++--------------------- src/entities/Entity.cpp | 4 ++-- src/entities/Entity.h | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/core/World.cpp b/src/core/World.cpp index a9571c8b..02c0e2f6 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -30,7 +30,7 @@ #include "ParticleObject.h" #include "EventList.h" -#define OBJECT_REPOSITION_OFFSET_Z 0.2f +#define OBJECT_REPOSITION_OFFSET_Z 2.0f CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; @@ -738,9 +738,9 @@ CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const pEntity->m_scanCode = ms_nCurrentScanCode; float fMagnitude = 0.0f; if (bCheck2DOnly) - fMagnitude = CVector2D(position - pEntity->GetPosition()).Magnitude(); + fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr2D(); else - fMagnitude = CVector(position - pEntity->GetPosition()).Magnitude(); + fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr(); if (fMagnitude < radius * radius && *nEntitiesFound < maxEntitiesToFind) { if (aEntities) aEntities[*nEntitiesFound] = pEntity; @@ -1044,9 +1044,9 @@ CWorld::FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& posit pEntity->m_scanCode = ms_nCurrentScanCode; float fMagnitude = 0.0f; if (bCheck2DOnly) - fMagnitude = CVector2D(position - pEntity->GetPosition()).Magnitude(); + fMagnitude = (position - pEntity->GetPosition()).Magnitude2D(); else - fMagnitude = CVector(position - pEntity->GetPosition()).Magnitude(); + fMagnitude = (position - pEntity->GetPosition()).Magnitude(); if (pEntity->GetBoundRadius() + radius > fMagnitude && *nCollidingEntities < maxEntitiesToFind) { if (aEntities) aEntities[*nCollidingEntities] = pEntity; @@ -1162,7 +1162,7 @@ CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, cons if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; CColSphere sphere; - CVector vecDistance = pEntity->m_matrix.GetPosition() - position; + CVector vecDistance = pEntity->GetPosition() - position; sphere.radius = pEntity->GetBoundRadius(); sphere.center = Multiply3x3(vecDistance, matrix); if (CCollision::TestSphereBox(sphere, boundingBox) && *nEntitiesFound < maxEntitiesToFind) { @@ -1226,7 +1226,7 @@ CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVec fRadius + entityPos.z >= vecStartPos.z && entityPos.z - fRadius <= vecEndPos.z && *nIntersecting < maxEntitiesToFind) { if (aEntities) - aEntities[*nIntersecting] = (CEntity*)pEntity; + aEntities[*nIntersecting] = pEntity; ++*nIntersecting; } } @@ -1402,7 +1402,7 @@ CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1 CVehicle *pVehicle = (CVehicle*)pNode->item; if (pVehicle->m_scanCode != CWorld::ms_nCurrentScanCode) { pVehicle->m_scanCode = CWorld::ms_nCurrentScanCode; - const CVector& vehiclePos = pVehicle->m_matrix.GetPosition(); + const CVector& vehiclePos = pVehicle->GetPosition(); eCarMission carMission = pVehicle->AutoPilot.m_nCarMission; if (pVehicle != FindPlayerVehicle() && vehiclePos.x > fStartX && vehiclePos.x < fEndX && @@ -1422,11 +1422,11 @@ CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1 // Maybe break the loop when bInsideSphere is set to true? } if (bInsideSphere) { - if (pVehicle->m_matrix.GetPosition().x <= (x1 + x2) * 0.5f) + if (pVehicle->GetPosition().x <= (x1 + x2) * 0.5f) pVehicle->m_vecMoveSpeed.x = min(pVehicle->m_vecMoveSpeed.x, 0.0f); else pVehicle->m_vecMoveSpeed.x = max(pVehicle->m_vecMoveSpeed.x, 0.0f); - if (pVehicle->m_matrix.GetPosition().y <= (y1 + y2) * 0.5f) + if (pVehicle->GetPosition().y <= (y1 + y2) * 0.5f) pVehicle->m_vecMoveSpeed.y = min(pVehicle->m_vecMoveSpeed.y, 0.0f); else pVehicle->m_vecMoveSpeed.y = max(pVehicle->m_vecMoveSpeed.y, 0.0f); @@ -1573,8 +1573,8 @@ CWorld::AddParticles(void) for (int32 y = 0; y < NUMSECTORS_Y; y++) { for (int32 x = 0; x < NUMSECTORS_X; x++) { CSector* pSector = GetSector(x, y); - CEntity::AddSteamsFromGround1(pSector->m_lists[ENTITYLIST_BUILDINGS]); - CEntity::AddSteamsFromGround1(pSector->m_lists[ENTITYLIST_DUMMIES]); + CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_BUILDINGS]); + CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_DUMMIES]); } } } @@ -1605,7 +1605,7 @@ CWorld::ShutDown(void) } pNode = pSector->m_lists[ENTITYLIST_PEDS].first; while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; + CEntity *pEntity = (CEntity*)pNode->item; if (pEntity) { CWorld::Remove(pEntity); delete pEntity; @@ -1614,7 +1614,7 @@ CWorld::ShutDown(void) } pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; + CEntity *pEntity = (CEntity*)pNode->item; if (pEntity) { CWorld::Remove(pEntity); delete pEntity; @@ -1623,7 +1623,7 @@ CWorld::ShutDown(void) } pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; + CEntity *pEntity = (CEntity*)pNode->item; if (pEntity) { CWorld::Remove(pEntity); delete pEntity; @@ -1637,9 +1637,9 @@ CWorld::ShutDown(void) } } for (int32 i = 0; i < 4; i ++) { - CPtrNode* pNode = GetBigBuildingList((eLevelName)i).first; + CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; + CEntity *pEntity = (CEntity*)pNode->item; if (pEntity) { // Maybe remove from world here? delete pEntity; @@ -1650,7 +1650,7 @@ CWorld::ShutDown(void) } for (int32 y = 0; y < NUMSECTORS_Y; y++) { for (int32 x = 0; x < NUMSECTORS_X; x++) { - CSector* pSector = GetSector(x, y); + CSector *pSector = GetSector(x, y); if (pSector->m_lists[ENTITYLIST_BUILDINGS].first) { sprintf(gString, "Building list %d,%d not empty\n", x, y); pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); @@ -1784,7 +1784,7 @@ CWorld::RepositionOneObject(CEntity* pEntity) || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT || modelId == MI_PARKTABLE) { - CVector& position = pEntity->m_matrix.GetPosition(); + CVector& position = pEntity->GetPosition(); float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z; position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - fBoundingBoxMinZ; pEntity->m_matrix.UpdateRW(); @@ -1792,13 +1792,13 @@ CWorld::RepositionOneObject(CEntity* pEntity) } else if (modelId == MI_BUOY) { float fWaterLevel = 0.0f; bool bFound = true; - const CVector& position = pEntity->m_matrix.GetPosition(); + const CVector& position = pEntity->GetPosition(); float fGroundZ = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &bFound); if (CWaterLevel::GetWaterLevelNoWaves(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &fWaterLevel)) { if (!bFound || fWaterLevel > fGroundZ) { CColModel* pColModel = pEntity->GetColModel(); float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; - pEntity->m_matrix.GetPosition().z = 0.2f * fHeight + fWaterLevel - 0.5f * fHeight; + pEntity->GetPosition().z = 0.2f * fHeight + fWaterLevel - 0.5f * fHeight; } } } @@ -2075,7 +2075,7 @@ CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, floa CPtrNode* pNode = list.first; while (pNode) { CPhysical* pEntity = (CPhysical*)pNode->item; - CVector vecDistance = pEntity->m_matrix.GetPosition() - position; + CVector vecDistance = pEntity->GetPosition() - position; float fMagnitude = vecDistance.Magnitude(); if (fRadius > fMagnitude) { CWeapon::BlowUpExplosiveThings(pEntity); @@ -2096,7 +2096,7 @@ CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, floa if (pEntity->IsObject() && modelId != MI_EXPLODINGBARREL && modelId != MI_PETROLPUMP) pObject->bHasBeenDamaged = true; } else { - CVector pos = pEntity->m_matrix.GetPosition(); + CVector pos = pEntity->GetPosition(); pos.z -= 0.5f; CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, pos, true); pObject->bHasBeenDamaged = true; @@ -2122,7 +2122,7 @@ CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, floa pEntity->ApplyMoveForce(vecForceDir); if (!pEntity->bPedPhysics) { float fBoundRadius = pEntity->GetBoundRadius(); - float fDistanceZ = position.z - pEntity->m_matrix.GetPosition().z; + float fDistanceZ = position.z - pEntity->GetPosition().z; float fPointZ = fBoundRadius; if (max(fDistanceZ, -fBoundRadius) < fBoundRadius) { diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index c0da6ede..0efee4e7 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -866,7 +866,7 @@ CEntity::ModifyMatrixForBannerInWind(void) } void -CEntity::AddSteamsFromGround1(CPtrList& list) +CEntity::AddSteamsFromGround(CPtrList& list) { CPtrNode *pNode = list.first; while (pNode) { @@ -922,7 +922,7 @@ STARTPATCHES InjectHook(0x473F60, &CEntity::DetachFromRwObject, PATCH_JUMP); InjectHook(0x475A20, &CEntity::PreRenderForGlassWindow, PATCH_JUMP); - InjectHook(0x50CE40, &CEntity::AddSteamsFromGround, PATCH_JUMP); + InjectHook(0x50CE40, (void (CEntity::*)(CVector*))& CEntity::AddSteamsFromGround, PATCH_JUMP); InjectHook(0x475670, &CEntity::ModifyMatrixForTreeInWind, PATCH_JUMP); InjectHook(0x475830, &CEntity::ModifyMatrixForBannerInWind, PATCH_JUMP); InjectHook(0x4FA530, &CEntity::ProcessLightsForEntity, PATCH_JUMP); diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 15333162..dadeee54 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -154,6 +154,6 @@ public: void ModifyMatrixForBannerInWind(void); void ProcessLightsForEntity(void); - static void AddSteamsFromGround1(CPtrList& list); + static void AddSteamsFromGround(CPtrList& list); }; static_assert(sizeof(CEntity) == 0x64, "CEntity: error"); From 425395ad2547e262c5c6f62b4c3fd95dd79ee679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Fri, 17 Apr 2020 07:01:54 +0300 Subject: [PATCH 048/123] Ped fixes and ref removal --- src/core/re3.cpp | 6 +-- src/peds/Ped.cpp | 94 +++++++++++++++++++++++++++++------------- src/peds/PedRoutes.cpp | 2 +- src/peds/PedStats.cpp | 1 - src/peds/PedType.cpp | 2 +- src/peds/PedType.h | 2 +- src/render/Clouds.cpp | 14 +++---- src/render/Clouds.h | 12 +++--- src/render/Console.cpp | 2 +- src/render/Console.h | 2 +- src/render/Coronas.cpp | 16 +++---- src/render/Coronas.h | 16 +++---- 12 files changed, 102 insertions(+), 67 deletions(-) diff --git a/src/core/re3.cpp b/src/core/re3.cpp index ecf02f39..2046a7f9 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -350,6 +350,9 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "Draw hud", (int8*)&CHud::m_Wants_To_Draw_Hud, nil); DebugMenuAddVarBool8("Debug", "Edit on", (int8*)&CSceneEdit::m_bEditOn, nil); +#ifdef MENU_MAP + DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); +#endif DebugMenuAddVar("Debug", "Engine Status", &engineStatus, nil, 1, 0, 226, nil); DebugMenuAddCmd("Debug", "Set Engine Status", SetEngineStatus); DebugMenuAddCmd("Debug", "Fix Car", FixCar); @@ -374,9 +377,6 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil); DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil); DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); -#ifdef MENU_MAP - DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); -#endif #ifdef TOGGLEABLE_BETA_FEATURES DebugMenuAddVarBool8("Debug", "Toggle banned particles", (int8*)&CParticle::bEnableBannedParticles, nil); DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil); diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 412b1f04..8ea41230 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -1623,6 +1623,15 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg) if (ped->IsPlayer()) AudioManager.PlayerJustLeftCar(); +#ifdef VC_PED_PORTS + if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { + dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped); + ped->m_fHealth = 0.0f; + ped->SetDie(ANIM_FLOOR_HIT, 1000.0f, 0.5f); + return; + } +#endif + if (quickJackedAssoc) { dragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped); } else { @@ -5186,7 +5195,7 @@ CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl) } if (extraTime == -1) { - m_getUpTimer = -1; + m_getUpTimer = UINT32_MAX; } else if (fallAssoc) { if (IsPlayer()) { m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength @@ -6448,7 +6457,7 @@ CPed::ExitCar(void) void CPed::Fall(void) { - if (m_getUpTimer != -1 && CTimer::GetTimeInMilliseconds() > m_getUpTimer + if (m_getUpTimer != UINT32_MAX && CTimer::GetTimeInMilliseconds() > m_getUpTimer #ifdef VC_PED_PORTS && bIsStanding #endif @@ -10663,7 +10672,7 @@ CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) return; if (ped->EnteringCar()) { - bool isLow = veh->bLowVehicle; + bool isLow = !!veh->bLowVehicle; if (!veh->bIsBus) veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_CLOSEDOOR_LHS, 1.0f); @@ -10691,7 +10700,11 @@ CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) #endif || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) { - if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) + if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER +#ifdef VC_PED_PORTS + || ped->m_nPedState == PED_CARJACK +#endif + ) veh->bIsBeingCarJacked = false; ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER; @@ -11027,9 +11040,9 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) PedSetInCarCB(nil, ped); return; } - bool isVan = veh->bIsVan; - bool isBus = veh->bIsBus; - bool isLow = veh->bLowVehicle; + bool isVan = !!veh->bIsVan; + bool isBus = !!veh->bIsBus; + bool isLow = !!veh->bLowVehicle; eDoors enterDoor; switch (ped->m_vehEnterType) { case CAR_DOOR_RF: @@ -11144,7 +11157,7 @@ CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg) if (!ped->IsNotInWreckedVehicle()) return; - bool isLow = veh->bLowVehicle; + bool isLow = !!veh->bLowVehicle; int padNo; if (ped->IsPlayer()) { @@ -11426,7 +11439,9 @@ CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg) CMatrix pedMat(ped->GetMatrix()); CVector posAfterBeingDragged = Multiply3x3(pedMat, (itsRearDoor ? -vecPedDraggedOutCarAnimOffset : vecPedDraggedOutCarAnimOffset)); posAfterBeingDragged += ped->GetPosition(); +#ifndef VC_PED_PORTS posAfterBeingDragged.z += 1.0f; +#endif CPedPlacement::FindZCoorForPed(&posAfterBeingDragged); ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); ped->GetPosition() = posAfterBeingDragged; @@ -11476,17 +11491,26 @@ CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg) && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && driver && driver->IsPlayer() && !CTheScripts::IsPlayerOnAMission()) { +#ifndef VC_PED_PORTS if (CGeneral::GetRandomNumber() & 1) ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver); else +#endif ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle); } else { - ped->m_nPedState = PED_NONE; - ped->m_nLastPedState = PED_NONE; - ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 10000); - ped->bUsePedNodeSeek = true; - ped->m_pNextPathNode = nil; +#ifdef VC_PED_PORTS + if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR + && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !driver + && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission()) + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle); + else +#endif + { + ped->m_nPedState = PED_NONE; + ped->m_nLastPedState = PED_NONE; + ped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000); + } } ped->SetGetUp(); } @@ -12289,24 +12313,36 @@ CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void ped->Say(SOUND_PED_FLEE_RUN); } } else { - if (ped->m_pedStats->m_temper <= ped->m_pedStats->m_fear - || ped->CharCreatedBy == MISSION_CHAR || veh->VehicleCreatedBy == MISSION_VEHICLE - || !veh->pDriver || !veh->pDriver->IsPlayer() - || CTheScripts::IsPlayerOnAMission()) { + if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear + && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE + && veh->pDriver && veh->pDriver->IsPlayer() + && !CTheScripts::IsPlayerOnAMission()) { - ped->SetFlee(veh->GetPosition(), 10000); - ped->bUsePedNodeSeek = true; - ped->m_pNextPathNode = nil; - if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) { - ped->SetMoveState(PEDMOVE_SPRINT); - ped->Say(SOUND_PED_FLEE_SPRINT); - } else { - ped->Say(SOUND_PED_FLEE_RUN); +#ifndef VC_PED_PORTS + if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) { + ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver); + } else +#endif + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + + } else { +#ifdef VC_PED_PORTS + if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR + && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !veh->pDriver + && FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission()) + ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + else +#endif + { + ped->SetFindPathAndFlee(veh->GetPosition(), 10000); + if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) { + ped->SetMoveState(PEDMOVE_SPRINT); + ped->Say(SOUND_PED_FLEE_SPRINT); + } else { + ped->Say(SOUND_PED_FLEE_RUN); + } } - } else if (CGeneral::GetRandomNumber() < 0x3FFF) { - ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver); - } else - ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh); + } } } if (ped->m_nLastPedState == PED_IDLE) diff --git a/src/peds/PedRoutes.cpp b/src/peds/PedRoutes.cpp index 3bc17002..b6512edd 100644 --- a/src/peds/PedRoutes.cpp +++ b/src/peds/PedRoutes.cpp @@ -3,7 +3,7 @@ #include "main.h" #include "PedRoutes.h" -CRouteNode (&gaRoutes)[NUMPEDROUTES] = *(CRouteNode(*)[NUMPEDROUTES]) * (uintptr*)0x62E090; +CRouteNode gaRoutes[NUMPEDROUTES]; void CRouteNode::Initialise() diff --git a/src/peds/PedStats.cpp b/src/peds/PedStats.cpp index 147f11e2..a2ccb567 100644 --- a/src/peds/PedStats.cpp +++ b/src/peds/PedStats.cpp @@ -4,7 +4,6 @@ #include "FileMgr.h" #include "PedStats.h" -//CPedStats *(&CPedStats::ms_apPedStats)[NUM_PEDSTATS] = *(CPedStats *(*)[NUM_PEDSTATS]) *(uintptr*)0x9404D4; CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS]; void diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp index 4c9d6b3f..30af6dcc 100644 --- a/src/peds/PedType.cpp +++ b/src/peds/PedType.cpp @@ -3,7 +3,7 @@ #include "FileMgr.h" #include "PedType.h" -CPedType *(&CPedType::ms_apPedType)[NUM_PEDTYPES] = *(CPedType *(*)[NUM_PEDTYPES]) *(uintptr*)0x941594; +CPedType *CPedType::ms_apPedType[NUM_PEDTYPES]; void CPedType::Initialise(void) diff --git a/src/peds/PedType.h b/src/peds/PedType.h index 3d927df5..c0c72550 100644 --- a/src/peds/PedType.h +++ b/src/peds/PedType.h @@ -71,7 +71,7 @@ class CPedType uint32 m_threats; uint32 m_avoid; - static CPedType *(&ms_apPedType)[NUM_PEDTYPES]; + static CPedType *ms_apPedType[NUM_PEDTYPES]; public: static void Initialise(void); diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 7debe3d3..02035896 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -16,15 +16,15 @@ #define SMALLSTRIPHEIGHT 4.0f #define HORIZSTRIPHEIGHT 48.0f -RwTexture **gpCloudTex = (RwTexture**)0x9411C0; //[5]; +RwTexture *gpCloudTex[5]; -float &CClouds::CloudRotation = *(float*)0x8F5F40; -uint32 &CClouds::IndividualRotation = *(uint32*)0x943078; +float CClouds::CloudRotation; +uint32 CClouds::IndividualRotation; -float &CClouds::ms_cameraRoll = *(float*)0x8F29CC; -float &CClouds::ms_horizonZ = *(float*)0x8F31C0; -CRGBA &CClouds::ms_colourTop = *(CRGBA*)0x94143C; -CRGBA &CClouds::ms_colourBottom = *(CRGBA*)0x8F2C38; +float CClouds::ms_cameraRoll; +float CClouds::ms_horizonZ; +CRGBA CClouds::ms_colourTop; +CRGBA CClouds::ms_colourBottom; void CClouds::Init(void) diff --git a/src/render/Clouds.h b/src/render/Clouds.h index c8000569..4d8cd2c8 100644 --- a/src/render/Clouds.h +++ b/src/render/Clouds.h @@ -3,13 +3,13 @@ class CClouds { public: - static float &CloudRotation; - static uint32 &IndividualRotation; + static float CloudRotation; + static uint32 IndividualRotation; - static float &ms_cameraRoll; - static float &ms_horizonZ; - static CRGBA &ms_colourTop; - static CRGBA &ms_colourBottom; + static float ms_cameraRoll; + static float ms_horizonZ; + static CRGBA ms_colourTop; + static CRGBA ms_colourBottom; static void Init(void); static void Shutdown(void); diff --git a/src/render/Console.cpp b/src/render/Console.cpp index 545122b0..bfdb2701 100644 --- a/src/render/Console.cpp +++ b/src/render/Console.cpp @@ -9,7 +9,7 @@ #define CONSOLE_Y_POS (10.0f) #define CONSOLE_LINE_HEIGHT (12.0f) -CConsole &TheConsole = *(CConsole*)0x8F6498; +CConsole TheConsole; void CConsole::AddLine(char *s, uint8 r, uint8 g, uint8 b) diff --git a/src/render/Console.h b/src/render/Console.h index c454d75e..b4fa60c4 100644 --- a/src/render/Console.h +++ b/src/render/Console.h @@ -22,4 +22,4 @@ public: void Init() { m_nCurrentLine = 0; m_nLineCount = 0; } }; -extern CConsole &TheConsole; +extern CConsole TheConsole; diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index 68994b0b..d70f70d6 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -48,16 +48,16 @@ FlareDef HeadLightsFlareDef[] = { }; -RwTexture **gpCoronaTexture = (RwTexture**)0x5FAF44; //[9] +RwTexture *gpCoronaTexture[9] = { nil, nil, nil, nil, nil, nil, nil, nil, nil }; -float &CCoronas::LightsMult = *(float*)0x5FB088; // 1.0 -float &CCoronas::SunScreenX = *(float*)0x8F4358; -float &CCoronas::SunScreenY = *(float*)0x8F4354; -bool &CCoronas::bSmallMoon = *(bool*)0x95CD49; -bool &CCoronas::SunBlockedByClouds = *(bool*)0x95CD73; -int &CCoronas::bChangeBrightnessImmediately = *(int*)0x8E2C30; +float CCoronas::LightsMult = 1.0f; +float CCoronas::SunScreenX; +float CCoronas::SunScreenY; +bool CCoronas::bSmallMoon; +bool CCoronas::SunBlockedByClouds; +int CCoronas::bChangeBrightnessImmediately; -CRegisteredCorona *CCoronas::aCoronas = (CRegisteredCorona*)0x72E518; +CRegisteredCorona CCoronas::aCoronas[NUMCORONAS]; const char aCoronaSpriteNames[][32] = { "coronastar", diff --git a/src/render/Coronas.h b/src/render/Coronas.h index 359a34ed..4b49e40e 100644 --- a/src/render/Coronas.h +++ b/src/render/Coronas.h @@ -1,6 +1,6 @@ #pragma once -extern RwTexture **gpCoronaTexture; //[9] +extern RwTexture *gpCoronaTexture[9]; struct CRegisteredCorona { @@ -42,7 +42,7 @@ static_assert(sizeof(CRegisteredCorona) == 0x80, "CRegisteredCorona: error"); class CCoronas { - static CRegisteredCorona *aCoronas; //[NUMCORONAS]; + static CRegisteredCorona aCoronas[NUMCORONAS]; public: enum { SUN_CORE = 1, @@ -77,12 +77,12 @@ public: STREAK_ON, }; - static float &LightsMult; - static float &SunScreenY; - static float &SunScreenX; - static bool &bSmallMoon; - static bool &SunBlockedByClouds; - static int &bChangeBrightnessImmediately; + static float LightsMult; + static float SunScreenY; + static float SunScreenX; + static bool bSmallMoon; + static bool SunBlockedByClouds; + static int bChangeBrightnessImmediately; static void Init(void); static void Shutdown(void); From a4922d5cb77e31657768d5da4b286a2e67ee0e6f Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Fri, 17 Apr 2020 08:54:14 +0300 Subject: [PATCH 049/123] rem refs --- src/animation/RpAnimBlend.cpp | 2 +- src/animation/RpAnimBlend.h | 2 +- src/audio/AudioManager.cpp | 24 ++-- src/audio/DMAudio.cpp | 2 +- src/audio/DMAudio.h | 2 +- src/audio/PoliceRadio.cpp | 14 +-- src/control/CarAI.cpp | 1 - src/control/CarCtrl.cpp | 38 +++--- src/control/CarCtrl.h | 36 +++--- src/control/GameLogic.cpp | 2 +- src/control/PathFind.cpp | 10 +- src/control/PathFind.h | 6 +- src/control/Phones.cpp | 12 +- src/control/Phones.h | 12 +- src/control/Pickups.cpp | 16 +-- src/control/Pickups.h | 10 +- src/control/Record.cpp | 28 ++--- src/control/Record.h | 30 ++--- src/control/Replay.cpp | 134 ++++++++++----------- src/control/Replay.h | 124 +++++++++---------- src/control/Restart.cpp | 26 ++-- src/control/Restart.h | 26 ++-- src/control/RoadBlocks.cpp | 6 +- src/control/RoadBlocks.h | 6 +- src/control/Script.cpp | 82 ++++++------- src/control/Script.h | 80 ++++++------- src/core/Accident.cpp | 2 +- src/core/Accident.h | 2 +- src/core/Cam.cpp | 2 +- src/core/Camera.cpp | 6 +- src/core/Camera.h | 6 +- src/core/Clock.cpp | 20 ++-- src/core/Clock.h | 18 +-- src/core/ControllerConfig.cpp | 2 +- src/core/ControllerConfig.h | 2 +- src/core/EventList.cpp | 1 - src/core/FileMgr.cpp | 4 +- src/core/FileMgr.h | 4 +- src/core/Fire.cpp | 2 +- src/core/Fire.h | 2 +- src/core/Frontend.cpp | 2 +- src/core/Game.cpp | 22 ++-- src/core/Game.h | 16 +-- src/core/IniFile.cpp | 4 +- src/core/Pad.cpp | 24 ++-- src/core/Pad.h | 22 ++-- src/core/Pools.cpp | 18 +-- src/core/Pools.h | 18 +-- src/core/Radar.cpp | 42 +++---- src/core/References.cpp | 4 +- src/core/References.h | 4 +- src/core/Stats.cpp | 106 ++++++++--------- src/core/Stats.h | 106 ++++++++--------- src/core/Streaming.cpp | 80 ++++++------- src/core/Streaming.h | 56 ++++----- src/core/SurfaceTable.cpp | 2 +- src/core/SurfaceTable.h | 3 +- src/core/TempColModels.cpp | 26 ++-- src/core/TempColModels.h | 26 ++-- src/core/TimeStep.cpp | 6 +- src/core/TimeStep.h | 6 +- src/core/Timer.cpp | 38 +++--- src/core/Timer.h | 20 ++-- src/core/User.cpp | 8 +- src/core/User.h | 8 +- src/core/Wanted.cpp | 4 +- src/core/Wanted.h | 4 +- src/core/ZoneCull.cpp | 28 ++--- src/core/ZoneCull.h | 28 ++--- src/core/Zones.cpp | 22 ++-- src/core/Zones.h | 22 ++-- src/core/config.h | 1 + src/core/main.cpp | 17 +-- src/core/main.h | 16 +-- src/modelinfo/ModelInfo.cpp | 5 +- src/modelinfo/ModelInfo.h | 2 +- src/modelinfo/VehicleModelInfo.cpp | 14 +-- src/modelinfo/VehicleModelInfo.h | 10 +- src/objects/Object.cpp | 4 +- src/objects/Object.h | 4 +- src/objects/ParticleObject.cpp | 8 +- src/objects/ParticleObject.h | 8 +- src/peds/PedRoutes.cpp | 2 +- src/peds/PedStats.cpp | 1 - src/peds/PedType.cpp | 2 +- src/peds/PedType.h | 2 +- src/render/Clouds.cpp | 14 +-- src/render/Clouds.h | 12 +- src/render/Console.cpp | 2 +- src/render/Console.h | 2 +- src/render/Coronas.cpp | 16 +-- src/render/Coronas.h | 16 +-- src/render/Credits.cpp | 4 +- src/render/Credits.h | 4 +- src/render/Draw.cpp | 16 +-- src/render/Draw.h | 16 +-- src/render/Font.cpp | 10 +- src/render/Font.h | 11 +- src/render/Hud.cpp | 76 ++++++------ src/render/MBlur.cpp | 6 +- src/render/MBlur.h | 6 +- src/render/Particle.cpp | 15 +-- src/render/Particle.h | 7 +- src/render/PointLights.cpp | 6 +- src/render/PointLights.h | 4 +- src/render/RenderBuffer.cpp | 12 +- src/render/RenderBuffer.h | 12 +- src/render/Shadows.cpp | 44 +++---- src/render/Shadows.h | 30 ++--- src/render/Sprite.cpp | 14 +-- src/render/Sprite.h | 8 +- src/render/Timecycle.cpp | 184 ++++++++++++++--------------- src/render/Timecycle.h | 184 ++++++++++++++--------------- src/render/WaterLevel.cpp | 4 +- src/render/WaterLevel.h | 2 +- src/render/Weather.cpp | 48 ++++---- src/render/Weather.h | 50 ++++---- src/rw/Lights.cpp | 20 ++-- src/rw/NodeName.cpp | 2 +- src/rw/RwHelper.cpp | 2 + src/rw/TexRead.cpp | 4 +- src/rw/TxdStore.cpp | 4 +- src/rw/VisibilityPlugins.cpp | 32 ++--- src/save/GenericGameStorage.cpp | 28 ++--- src/save/PCSave.cpp | 2 +- src/skel/skeleton.cpp | 3 +- src/skel/skeleton.h | 2 +- src/skel/win/win.cpp | 26 ++-- src/skel/win/win.h | 6 +- src/text/Messages.cpp | 6 +- src/text/Text.cpp | 2 +- src/vehicles/Automobile.cpp | 2 +- src/vehicles/Boat.cpp | 10 +- src/vehicles/Floater.cpp | 4 +- src/vehicles/HandlingMgr.cpp | 2 +- src/vehicles/Heli.cpp | 12 +- src/vehicles/Plane.cpp | 68 +++++------ src/weapons/ShotInfo.cpp | 2 - src/weapons/WeaponInfo.cpp | 1 - 139 files changed, 1350 insertions(+), 1400 deletions(-) diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp index 9c847139..07b8e7d8 100644 --- a/src/animation/RpAnimBlend.cpp +++ b/src/animation/RpAnimBlend.cpp @@ -8,7 +8,7 @@ #include "AnimBlendAssociation.h" #include "RpAnimBlend.h" -RwInt32 &ClumpOffset = *(RwInt32*)0x8F1B84; +RwInt32 ClumpOffset; enum { diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h index f9e14c42..ccfa5872 100644 --- a/src/animation/RpAnimBlend.h +++ b/src/animation/RpAnimBlend.h @@ -11,7 +11,7 @@ struct AnimBlendFrameUpdateData CAnimBlendNode *nodes[16]; }; -extern RwInt32 &ClumpOffset; +extern RwInt32 ClumpOffset; #define RPANIMBLENDCLUMPDATA(o) (RWPLUGINOFFSET(CAnimBlendClumpData*, o, ClumpOffset)) bool RpAnimBlendPluginAttach(void); diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 8a9a81f9..2ee7e602 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -40,18 +40,18 @@ #include "sampman.h" cAudioManager AudioManager; -uint32 gPornNextTime; // = *(uint32*)0x6508A0; -uint32 gSawMillNextTime; // = *(uint32*)0x6508A4; -uint32 gShopNextTime; // = *(uint32*)0x6508A8; -uint32 gAirportNextTime; // = *(uint32*)0x6508AC; -uint32 gCinemaNextTime; //= *(uint32*)0x6508B0; -uint32 gDocksNextTime; // = *(uint32*)0x6508B4; -uint32 gHomeNextTime; // = *(uint32*)0x6508B8; -uint32 gCellNextTime; // = *(uint32*)0x6508BC; -uint32 gNextCryTime; // = *(uint32*)0x6508C0; -uint8 gJumboVolOffsetPercentage; // = *(uint8 *)0x6508ED; -bool bPlayerJustEnteredCar; // = *(bool *)0x6508C4; -bool g_bMissionAudioLoadFailed; // = *(bool *)0x95CD8E; +uint32 gPornNextTime; +uint32 gSawMillNextTime; +uint32 gShopNextTime; +uint32 gAirportNextTime; +uint32 gCinemaNextTime; +uint32 gDocksNextTime; +uint32 gHomeNextTime; +uint32 gCellNextTime; +uint32 gNextCryTime; +uint8 gJumboVolOffsetPercentage; +bool bPlayerJustEnteredCar; +bool g_bMissionAudioLoadFailed; const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples); const int policeChannel = channels + 1; diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index a01c85ae..e55790ea 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -6,7 +6,7 @@ #include "AudioScriptObject.h" #include "sampman.h" -cDMAudio &DMAudio = *(cDMAudio*)0x95CDBE; +cDMAudio DMAudio; void cDMAudio::Initialise(void) diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index d2cdf466..9ce073b4 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -256,4 +256,4 @@ public: void SetRadioInCar(uint32 radio); void SetRadioChannel(int8 radio, int32 pos); }; -extern cDMAudio &DMAudio; +extern cDMAudio DMAudio; diff --git a/src/audio/PoliceRadio.cpp b/src/audio/PoliceRadio.cpp index 255d7026..a81fcbe9 100644 --- a/src/audio/PoliceRadio.cpp +++ b/src/audio/PoliceRadio.cpp @@ -21,14 +21,14 @@ struct tPoliceRadioZone { int32 field_12; }; -tPoliceRadioZone (&ZoneSfx)[NUMAUDIOZONES] = *(tPoliceRadioZone(*)[NUMAUDIOZONES])*(uintptr*)0x880240; -char *SubZo2Label = (char*)0x6E9918; -char *SubZo3Label = (char*)0x6E9870; +tPoliceRadioZone ZoneSfx[NUMAUDIOZONES]; +char SubZo2Label[8]; +char SubZo3Label[8]; -int32 &g_nMissionAudioSfx = *(int32*)0x60ED84; -int8 &g_nMissionAudioPlayingStatus = *(int8*)0x60ED88; -uint8 &gSpecialSuspectLastSeenReport = *(uint8*)0x95CD4D; -uint32 (&gMinTimeToNextReport)[NUM_CRIME_TYPES] = *(uint32(*)[NUM_CRIME_TYPES])*(uintptr*)0x8E2828; +int32 g_nMissionAudioSfx = TOTAL_AUDIO_SAMPLES; +int8 g_nMissionAudioPlayingStatus = 2; +uint8 gSpecialSuspectLastSeenReport; +uint32 gMinTimeToNextReport[NUM_CRIME_TYPES]; void cAudioManager::InitialisePoliceRadioZones() diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index e47e3d5e..f48e4c78 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -33,7 +33,6 @@ float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle) void CCarAI::UpdateCarAI(CVehicle* pVehicle) { - //((void(*)(CVehicle*))(0x413E50))(pVehicle); //return; if (pVehicle->bIsLawEnforcer){ if (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_FARAWAY || diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 197fca63..6e47670d 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -67,25 +67,25 @@ #define MIN_ANGLE_TO_APPLY_HANDBRAKE 0.7f #define MIN_SPEED_TO_APPLY_HANDBRAKE 0.3f -int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38; -int &CCarCtrl::NumAmbulancesOnDuty = *(int*)0x885BB0; -int &CCarCtrl::NumFiretrucksOnDuty = *(int*)0x9411F0; -bool &CCarCtrl::bCarsGeneratedAroundCamera = *(bool*)0x95CD8A; -float& CCarCtrl::CarDensityMultiplier = *(float*)0x5EC8B4; -int32 &CCarCtrl::NumMissionCars = *(int32*)0x8F1B54; -int32 &CCarCtrl::NumRandomCars = *(int32*)0x943118; -int32 &CCarCtrl::NumParkedCars = *(int32*)0x8F29E0; -int32 &CCarCtrl::NumPermanentCars = *(int32*)0x8F29F0; -int8 &CCarCtrl::CountDownToCarsAtStart = *(int8*)0x95CD63; -int32 &CCarCtrl::MaxNumberOfCarsInUse = *(int32*)0x5EC8B8; -uint32 &CCarCtrl::LastTimeLawEnforcerCreated = *(uint32*)0x8F5FF0; -uint32 &CCarCtrl::LastTimeFireTruckCreated = *(uint32*)0x880F5C; -uint32 &CCarCtrl::LastTimeAmbulanceCreated = *(uint32*)0x941450; -int32 (&CCarCtrl::TotalNumOfCarsOfRating)[TOTAL_CUSTOM_CLASSES] = *(int32(*)[TOTAL_CUSTOM_CLASSES])*(uintptr*)0x8F1A60; -int32 (&CCarCtrl::NextCarOfRating)[TOTAL_CUSTOM_CLASSES] = *(int32(*)[TOTAL_CUSTOM_CLASSES])*(uintptr*)0x9412AC; -int32 (&CCarCtrl::CarArrays)[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY] = *(int32(*)[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY])*(uintptr*)0x6EB860; -CVehicle* (&apCarsToKeep)[MAX_CARS_TO_KEEP] = *(CVehicle*(*)[MAX_CARS_TO_KEEP])*(uintptr*)0x70D830; -uint32 (&aCarsToKeepTime)[MAX_CARS_TO_KEEP] = *(uint32(*)[MAX_CARS_TO_KEEP])*(uintptr*)0x87F9A8; +int CCarCtrl::NumLawEnforcerCars; +int CCarCtrl::NumAmbulancesOnDuty; +int CCarCtrl::NumFiretrucksOnDuty; +bool CCarCtrl::bCarsGeneratedAroundCamera; +float CCarCtrl::CarDensityMultiplier = 1.0f; +int32 CCarCtrl::NumMissionCars; +int32 CCarCtrl::NumRandomCars; +int32 CCarCtrl::NumParkedCars; +int32 CCarCtrl::NumPermanentCars; +int8 CCarCtrl::CountDownToCarsAtStart; +int32 CCarCtrl::MaxNumberOfCarsInUse = 12; +uint32 CCarCtrl::LastTimeLawEnforcerCreated; +uint32 CCarCtrl::LastTimeFireTruckCreated; +uint32 CCarCtrl::LastTimeAmbulanceCreated; +int32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES]; +int32 CCarCtrl::NextCarOfRating[TOTAL_CUSTOM_CLASSES]; +int32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; +CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; +uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP]; void CCarCtrl::GenerateRandomCars() diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 925552b5..44ef9ab6 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -120,23 +120,23 @@ public: return angle; } - static int32 &NumLawEnforcerCars; - static int32 &NumAmbulancesOnDuty; - static int32 &NumFiretrucksOnDuty; - static int32 &NumRandomCars; - static int32 &NumMissionCars; - static int32 &NumParkedCars; - static int32 &NumPermanentCars; - static bool &bCarsGeneratedAroundCamera; - static float &CarDensityMultiplier; - static int8 &CountDownToCarsAtStart; - static int32 &MaxNumberOfCarsInUse; - static uint32 &LastTimeLawEnforcerCreated; - static uint32 &LastTimeFireTruckCreated; - static uint32 &LastTimeAmbulanceCreated; - static int32 (&TotalNumOfCarsOfRating)[TOTAL_CUSTOM_CLASSES]; - static int32 (&NextCarOfRating)[TOTAL_CUSTOM_CLASSES]; - static int32 (&CarArrays)[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; + static int32 NumLawEnforcerCars; + static int32 NumAmbulancesOnDuty; + static int32 NumFiretrucksOnDuty; + static int32 NumRandomCars; + static int32 NumMissionCars; + static int32 NumParkedCars; + static int32 NumPermanentCars; + static bool bCarsGeneratedAroundCamera; + static float CarDensityMultiplier; + static int8 CountDownToCarsAtStart; + static int32 MaxNumberOfCarsInUse; + static uint32 LastTimeLawEnforcerCreated; + static uint32 LastTimeFireTruckCreated; + static uint32 LastTimeAmbulanceCreated; + static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES]; + static int32 NextCarOfRating[TOTAL_CUSTOM_CLASSES]; + static int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; }; -extern CVehicle* (&apCarsToKeep)[MAX_CARS_TO_KEEP]; \ No newline at end of file +extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; \ No newline at end of file diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp index 8e0ea02d..0cfaac17 100644 --- a/src/control/GameLogic.cpp +++ b/src/control/GameLogic.cpp @@ -20,7 +20,7 @@ #include "Script.h" #include "Garages.h" -uint8 CGameLogic::ActivePlayers; // 0x95CD5E +uint8 CGameLogic::ActivePlayers; void CGameLogic::InitAtStartOfGame() diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 9f45c454..d9594490 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -12,7 +12,7 @@ bool gbShowPedPaths; bool gbShowCarPaths; bool gbShowCarPathsLinks; -CPathFind &ThePaths = *(CPathFind*)0x8F6754; +CPathFind ThePaths; #define MAX_DIST INT16_MAX-1 #define MIN_PED_ROUTE_DISTANCE 23.8f @@ -21,11 +21,11 @@ CPathFind &ThePaths = *(CPathFind*)0x8F6754; // 1 UseInRoadBlock // 2 east/west road(?) -CPathInfoForObject *&InfoForTileCars = *(CPathInfoForObject**)0x8F1A8C; -CPathInfoForObject *&InfoForTilePeds = *(CPathInfoForObject**)0x8F1AE4; +CPathInfoForObject *InfoForTileCars; +CPathInfoForObject *InfoForTilePeds; // unused -CTempDetachedNode *&DetachedNodesCars = *(CTempDetachedNode**)0x8E2824; -CTempDetachedNode *&DetachedNodesPeds = *(CTempDetachedNode**)0x8E28A0; +CTempDetachedNode *DetachedNodesCars; +CTempDetachedNode *DetachedNodesPeds; bool CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints) diff --git a/src/control/PathFind.h b/src/control/PathFind.h index ea88ade6..64c12d5b 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -138,8 +138,8 @@ struct CPathInfoForObject int8 numRightLanes; uint8 crossing : 1; }; -extern CPathInfoForObject *&InfoForTileCars; -extern CPathInfoForObject *&InfoForTilePeds; +extern CPathInfoForObject *InfoForTileCars; +extern CPathInfoForObject *InfoForTilePeds; struct CTempNode { @@ -234,7 +234,7 @@ public: }; static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error"); -extern CPathFind &ThePaths; +extern CPathFind ThePaths; extern bool gbShowPedPaths; extern bool gbShowCarPaths; diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index 276f02b9..90939f0e 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -13,13 +13,13 @@ #include "RpAnimBlend.h" #include "AnimBlendAssociation.h" -CPhoneInfo &gPhoneInfo = *(CPhoneInfo*)0x732A20; +CPhoneInfo gPhoneInfo; -bool &CPhoneInfo::bDisplayingPhoneMessage = *(bool*)0x6283AC; // is phone picked up -uint32 &CPhoneInfo::PhoneEnableControlsTimer = *(uint32*)0x6283A8; -CPhone *&CPhoneInfo::pPhoneDisplayingMessages = *(CPhone**)0x6283B0; -bool &CPhoneInfo::bPickingUpPhone = *(bool*)0x6283B4; -CPed *&CPhoneInfo::pCallBackPed = *(CPed**)0x6283B8; // ped who picking up the phone (reset after pickup cb) +bool CPhoneInfo::bDisplayingPhoneMessage; // is phone picked up +uint32 CPhoneInfo::PhoneEnableControlsTimer; +CPhone *CPhoneInfo::pPhoneDisplayingMessages; +bool CPhoneInfo::bPickingUpPhone; +CPed *CPhoneInfo::pCallBackPed; // ped who picking up the phone (reset after pickup cb) /* Entering phonebooth cutscene, showing messages and triggering these things diff --git a/src/control/Phones.h b/src/control/Phones.h index e7e3c9a7..7fbf403f 100644 --- a/src/control/Phones.h +++ b/src/control/Phones.h @@ -36,11 +36,11 @@ static_assert(sizeof(CPhone) == 0x34, "CPhone: error"); class CPhoneInfo { public: - static bool &bDisplayingPhoneMessage; - static uint32 &PhoneEnableControlsTimer; - static CPhone *&pPhoneDisplayingMessages; - static bool &bPickingUpPhone; - static CPed *&pCallBackPed; + static bool bDisplayingPhoneMessage; + static uint32 PhoneEnableControlsTimer; + static CPhone *pPhoneDisplayingMessages; + static bool bPickingUpPhone; + static CPed *pCallBackPed; int32 m_nMax; int32 m_nScriptPhonesMax; @@ -63,7 +63,7 @@ public: void Update(void); }; -extern CPhoneInfo &gPhoneInfo; +extern CPhoneInfo gPhoneInfo; void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg); void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg); diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index eb561670..d52c386c 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -31,16 +31,16 @@ #include "WaterLevel.h" #include "World.h" -CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98; -int16 CPickups::NumMessages;// = *(int16*)0x95CC98; -int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];// = *(int32(*)[NUMCOLLECTEDPICKUPS])*(uintptr*)0x87C538; -int16 CPickups::CollectedPickUpIndex;// = *(int16*)0x95CC8A; +CPickup CPickups::aPickUps[NUMPICKUPS]; +int16 CPickups::NumMessages; +int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS]; +int16 CPickups::CollectedPickUpIndex; // unused -bool &CPickups::bPickUpcamActivated = *(bool*)0x95CD71; -CVehicle *&CPickups::pPlayerVehicle = *(CVehicle**)0x8F29E8; -CVector &CPickups::StaticCamCoors = *(CVector*)0x9404C8; -uint32 &CPickups::StaticCamStartTime = *(uint32*)0x8E289C; +bool CPickups::bPickUpcamActivated; +CVehicle *CPickups::pPlayerVehicle; +CVector CPickups::StaticCamCoors; +uint32 CPickups::StaticCamStartTime; tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES]; diff --git a/src/control/Pickups.h b/src/control/Pickups.h index b5b4f396..11da5f54 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -89,13 +89,13 @@ public: static void Load(uint8 *buf, uint32 size); static void Save(uint8 *buf, uint32 *size); - static CPickup(&aPickUps)[NUMPICKUPS]; + static CPickup aPickUps[NUMPICKUPS]; // unused - static bool &bPickUpcamActivated; - static CVehicle *&pPlayerVehicle; - static CVector &StaticCamCoors; - static uint32 &StaticCamStartTime; + static bool bPickUpcamActivated; + static CVehicle *pPlayerVehicle; + static CVector StaticCamCoors; + static uint32 StaticCamStartTime; }; extern uint16 AmmoForWeapon[20]; diff --git a/src/control/Record.cpp b/src/control/Record.cpp index ca4128e3..08e3c5b9 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -10,11 +10,11 @@ #include "VehicleModelInfo.h" #include "World.h" -uint16 &CRecordDataForGame::RecordingState = *(uint16*)0x95CC24; -uint8*& CRecordDataForGame::pDataBuffer = *(uint8**)0x8F1B70; -uint8*& CRecordDataForGame::pDataBufferPointer = *(uint8**)0x8F1AB0; -int& CRecordDataForGame::FId = *(int*)0x885BA4; -tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0; +uint16 CRecordDataForGame::RecordingState; +uint8* CRecordDataForGame::pDataBuffer; +uint8* CRecordDataForGame::pDataBufferPointer; +int CRecordDataForGame::FId; +tGameBuffer CRecordDataForGame::pDataBufferForFrame; #define MEMORY_FOR_GAME_RECORD (150000) @@ -176,15 +176,15 @@ uint16 CRecordDataForGame::CalcGameChecksum(void) return checksum ^ checksum >> 16; } -uint8& CRecordDataForChase::Status = *(uint8*)0x95CDCE; -int& CRecordDataForChase::PositionChanges = *(int*)0x8F59C8; -uint8& CRecordDataForChase::CurrentCar = *(uint8*)0x95CDC9; -CAutomobile* (&CRecordDataForChase::pChaseCars)[NUM_CHASE_CARS] = *(CAutomobile * (*)[NUM_CHASE_CARS])*(uintptr*)0x6F46A8; -uint32& CRecordDataForChase::AnimStartTime = *(uint32*)0x8F1AEC; -float& CRecordDataForChase::AnimTime = *(float*)0x880F88; -CCarStateEachFrame* (&CRecordDataForChase::pBaseMemForCar)[NUM_CHASE_CARS] = *(CCarStateEachFrame * (*)[NUM_CHASE_CARS])*(uintptr*)0x70EA18; -float& CRecordDataForChase::TimeMultiplier = *(float*)0x8E2A94; -int& CRecordDataForChase::FId2 = *(int*)0x8E2C18; +uint8 CRecordDataForChase::Status; +int CRecordDataForChase::PositionChanges; +uint8 CRecordDataForChase::CurrentCar; +CAutomobile* CRecordDataForChase::pChaseCars[NUM_CHASE_CARS]; +uint32 CRecordDataForChase::AnimStartTime; +float CRecordDataForChase::AnimTime; +CCarStateEachFrame* CRecordDataForChase::pBaseMemForCar[NUM_CHASE_CARS]; +float CRecordDataForChase::TimeMultiplier; +int CRecordDataForChase::FId2; #define CHASE_SCENE_LENGTH_IN_SECONDS (80) #define CHASE_SCENE_FRAMES_PER_SECOND (15) // skipping every second frame diff --git a/src/control/Record.h b/src/control/Record.h index 4abeb68a..7af733ba 100644 --- a/src/control/Record.h +++ b/src/control/Record.h @@ -23,7 +23,7 @@ public: CVector pos; }; -extern char* gString; +extern char gString[256];; class CRecordDataForChase { @@ -37,15 +37,15 @@ class CRecordDataForChase STATE_PLAYBACK = 3, STATE_PLAYBACK_BEFORE_RECORDING = 4 }; - static uint8 &Status; - static int &PositionChanges; - static uint8 &CurrentCar; - static CAutomobile*(&pChaseCars)[NUM_CHASE_CARS]; - static float &AnimTime; - static uint32 &AnimStartTime; - static CCarStateEachFrame* (&pBaseMemForCar)[NUM_CHASE_CARS]; - static float &TimeMultiplier; - static int &FId2; + static uint8 Status; + static int PositionChanges; + static uint8 CurrentCar; + static CAutomobile*pChaseCars[NUM_CHASE_CARS]; + static float AnimTime; + static uint32 AnimStartTime; + static CCarStateEachFrame* pBaseMemForCar[NUM_CHASE_CARS]; + static float TimeMultiplier; + static int FId2; public: static bool IsRecording(void) { return Status == STATE_RECORD; } @@ -86,11 +86,11 @@ class CRecordDataForGame STATE_RECORD = 1, STATE_PLAYBACK = 2, }; - static uint16& RecordingState; - static uint8* &pDataBuffer; - static uint8* &pDataBufferPointer; - static int &FId; - static tGameBuffer &pDataBufferForFrame; + static uint16 RecordingState; + static uint8* pDataBuffer; + static uint8* pDataBufferPointer; + static int FId; + static tGameBuffer pDataBufferForFrame; public: static bool IsRecording() { return RecordingState == STATE_RECORD; } diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 9e0bed66..92d1736d 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -39,71 +39,70 @@ #include "Camera.h" #include "Radar.h" -uint8 &CReplay::Mode = *(uint8*)0x95CD5B; -CAddressInReplayBuffer &CReplay::Record = *(CAddressInReplayBuffer*)0x942F7C; -CAddressInReplayBuffer &CReplay::Playback = *(CAddressInReplayBuffer*)0x8F5F48; -uint8 *&CReplay::pBuf0 = *(uint8**)0x8E2C64; -CAutomobile *&CReplay::pBuf1 = *(CAutomobile**)0x8E2C68; -uint8 *&CReplay::pBuf2 = *(uint8**)0x8E2C6C; -CPlayerPed *&CReplay::pBuf3 = *(CPlayerPed**)0x8E2C70; -uint8 *&CReplay::pBuf4 = *(uint8**)0x8E2C74; -CCutsceneHead *&CReplay::pBuf5 = *(CCutsceneHead**)0x8E2C78; -uint8 *&CReplay::pBuf6 = *(uint8**)0x8E2C80; -CPtrNode *&CReplay::pBuf7 = *(CPtrNode**)0x8E2C84; -uint8 *&CReplay::pBuf8 = *(uint8**)0x8E2C54; -CEntryInfoNode *&CReplay::pBuf9 = *(CEntryInfoNode**)0x8E2C58; -uint8 *&CReplay::pBuf10 = *(uint8**)0x8F2C28; -CDummyPed *&CReplay::pBuf11 = *(CDummyPed**)0x8F2C2C; -uint8 *&CReplay::pRadarBlips = *(uint8**)0x8F29F8; -uint8 *&CReplay::pStoredCam = *(uint8**)0x8F2C34; -uint8 *&CReplay::pWorld1 = *(uint8**)0x8E29C4; -CReference *&CReplay::pEmptyReferences = *(CReference**)0x8F256C; -CStoredDetailedAnimationState *&CReplay::pPedAnims = *(CStoredDetailedAnimationState**)0x8F6260; -uint8 *&CReplay::pPickups = *(uint8**)0x8F1A48; -uint8 *&CReplay::pReferences = *(uint8**)0x880FAC; -uint8(&CReplay::BufferStatus)[NUM_REPLAYBUFFERS] = *(uint8(*)[NUM_REPLAYBUFFERS])*(uintptr*)0x8804D8; -uint8(&CReplay::Buffers)[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE] = *(uint8(*)[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE])*(uintptr*)0x779958; -bool &CReplay::bPlayingBackFromFile = *(bool*)0x95CD58; -bool &CReplay::bReplayEnabled = *(bool*)0x617CAC; -uint32 &CReplay::SlowMotion = *(uint32*)0x9414D4; -uint32 &CReplay::FramesActiveLookAroundCam = *(uint32*)0x880F84; -bool &CReplay::bDoLoadSceneWhenDone = *(bool*)0x95CD76; -CPtrList &CReplay::WorldPtrList = *(CPtrList*)0x880F90; -CPtrList &CReplay::BigBuildingPtrList = *(CPtrList*)0x941284; -CWanted &CReplay::PlayerWanted = *(CWanted*)0x8F6278; -CPlayerInfo &CReplay::PlayerInfo = *(CPlayerInfo*)0x8F5840; -uint32 &CReplay::Time1 = *(uint32*)0x8F29DC; -uint32 &CReplay::Time2 = *(uint32*)0x8F29D0; -uint32 &CReplay::Time3 = *(uint32*)0x8F29D4; -uint32 &CReplay::Time4 = *(uint32*)0x8F29C8; -uint32 &CReplay::Frame = *(uint32*)0x8F2554; -uint8 &CReplay::ClockHours = *(uint8*)0x95CDC5; -uint8 &CReplay::ClockMinutes = *(uint8*)0x95CDA2; -uint16 &CReplay::OldWeatherType = *(uint16*)0x95CCEA; -uint16 &CReplay::NewWeatherType = *(uint16*)0x95CC6E; -float &CReplay::WeatherInterpolationValue = *(float*)0x8F1A28; -float &CReplay::TimeStepNonClipped = *(float*)0x8F5FF4; -float &CReplay::TimeStep = *(float*)0x8F2C24; -float &CReplay::TimeScale = *(float*)0x880E20; -float &CReplay::CameraFixedX = *(float*)0x943054; -float &CReplay::CameraFixedY = *(float*)0x943058; -float &CReplay::CameraFixedZ = *(float*)0x94305C; -int32 &CReplay::OldRadioStation = *(int32*)0x94151C; -int8 &CReplay::CameraMode = *(int8*)0x95CD5F; -bool &CReplay::bAllowLookAroundCam = *(bool*)0x95CDCD; -float &CReplay::LoadSceneX = *(float*)0x880F9C; -float &CReplay::LoadSceneY = *(float*)0x880F98; -float &CReplay::LoadSceneZ = *(float*)0x880F94; -float &CReplay::CameraFocusX = *(float*)0x942F5C; -float &CReplay::CameraFocusY = *(float*)0x942F74; -float &CReplay::CameraFocusZ = *(float*)0x942F58; -bool &CReplay::bPlayerInRCBuggy = *(bool*)0x95CDC3; -float &CReplay::fDistanceLookAroundCam = *(float*)0x885B44; -float &CReplay::fBetaAngleLookAroundCam = *(float*)0x94072C; -float &CReplay::fAlphaAngleLookAroundCam = *(float*)0x8F2A0C; +uint8 CReplay::Mode; +CAddressInReplayBuffer CReplay::Record; +CAddressInReplayBuffer CReplay::Playback; +uint8 *CReplay::pBuf0; +CAutomobile *CReplay::pBuf1; +uint8 *CReplay::pBuf2; +CPlayerPed *CReplay::pBuf3; +uint8 *CReplay::pBuf4; +CCutsceneHead *CReplay::pBuf5; +uint8 *CReplay::pBuf6; +CPtrNode *CReplay::pBuf7; +uint8 *CReplay::pBuf8; +CEntryInfoNode *CReplay::pBuf9; +uint8 *CReplay::pBuf10; +CDummyPed *CReplay::pBuf11; +uint8 *CReplay::pRadarBlips; +uint8 *CReplay::pStoredCam; +uint8 *CReplay::pWorld1; +CReference *CReplay::pEmptyReferences; +CStoredDetailedAnimationState *CReplay::pPedAnims; +uint8 *CReplay::pPickups; +uint8 *CReplay::pReferences; +uint8 CReplay::BufferStatus[NUM_REPLAYBUFFERS]; +uint8 CReplay::Buffers[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE]; +bool CReplay::bPlayingBackFromFile; +bool CReplay::bReplayEnabled = true; +uint32 CReplay::SlowMotion; +uint32 CReplay::FramesActiveLookAroundCam; +bool CReplay::bDoLoadSceneWhenDone; +CPtrList CReplay::WorldPtrList; +CPtrList CReplay::BigBuildingPtrList; +CWanted CReplay::PlayerWanted; +CPlayerInfo CReplay::PlayerInfo; +uint32 CReplay::Time1; +uint32 CReplay::Time2; +uint32 CReplay::Time3; +uint32 CReplay::Time4; +uint32 CReplay::Frame; +uint8 CReplay::ClockHours; +uint8 CReplay::ClockMinutes; +uint16 CReplay::OldWeatherType; +uint16 CReplay::NewWeatherType; +float CReplay::WeatherInterpolationValue; +float CReplay::TimeStepNonClipped; +float CReplay::TimeStep; +float CReplay::TimeScale; +float CReplay::CameraFixedX; +float CReplay::CameraFixedY; +float CReplay::CameraFixedZ; +int32 CReplay::OldRadioStation; +int8 CReplay::CameraMode; +bool CReplay::bAllowLookAroundCam; +float CReplay::LoadSceneX; +float CReplay::LoadSceneY; +float CReplay::LoadSceneZ; +float CReplay::CameraFocusX; +float CReplay::CameraFocusY; +float CReplay::CameraFocusZ; +bool CReplay::bPlayerInRCBuggy; +float CReplay::fDistanceLookAroundCam; +float CReplay::fBetaAngleLookAroundCam; +float CReplay::fAlphaAngleLookAroundCam; -static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))*(uintptr*)0x61052C; -static void(*CBArray_RE3[])(CAnimBlendAssociation*, void*) = +static void(*CBArray[])(CAnimBlendAssociation*, void*) = { nil, &CPed::PedGetupCB, &CPed::PedStaggerCB, &CPed::PedEvadeCB, &CPed::FinishDieAnimCB, &CPed::FinishedWaitCB, &CPed::FinishLaunchCB, &CPed::FinishHitHeadCB, &CPed::PedAnimGetInCB, &CPed::PedAnimDoorOpenCB, @@ -119,16 +118,13 @@ static uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*)) if (CBArray[i] == f) return i; } - for (int i = 0; i < sizeof(CBArray_RE3) / sizeof(*CBArray_RE3); i++) { - if (CBArray_RE3[i] == f) - return i; - } + return 0; } static void(*FindCBFunction(uint8 id))(CAnimBlendAssociation*, void*) { - return CBArray_RE3[id]; + return CBArray[id]; } static void ApplyPanelDamageToCar(uint32 panels, CAutomobile* vehicle, bool flying) diff --git a/src/control/Replay.h b/src/control/Replay.h index 56de52a3..6f6c2a91 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -205,68 +205,68 @@ class CReplay static_assert(sizeof(tVehicleUpdatePacket) == 48, "tVehicleUpdatePacket: error"); private: - static uint8 &Mode; - static CAddressInReplayBuffer &Record; - static CAddressInReplayBuffer &Playback; - static uint8 *&pBuf0; - static CAutomobile *&pBuf1; - static uint8 *&pBuf2; - static CPlayerPed *&pBuf3; - static uint8 *&pBuf4; - static CCutsceneHead *&pBuf5; - static uint8 *&pBuf6; - static CPtrNode *&pBuf7; - static uint8 *&pBuf8; - static CEntryInfoNode *&pBuf9; - static uint8 *&pBuf10; - static CDummyPed *&pBuf11; - static uint8 *&pRadarBlips; - static uint8 *&pStoredCam; - static uint8 *&pWorld1; - static CReference *&pEmptyReferences; - static CStoredDetailedAnimationState *&pPedAnims; - static uint8 *&pPickups; - static uint8 *&pReferences; - static uint8 (&BufferStatus)[NUM_REPLAYBUFFERS]; - static uint8 (&Buffers)[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE]; - static bool &bPlayingBackFromFile; - static bool &bReplayEnabled; - static uint32 &SlowMotion; - static uint32 &FramesActiveLookAroundCam; - static bool &bDoLoadSceneWhenDone; - static CPtrList &WorldPtrList; - static CPtrList &BigBuildingPtrList; - static CWanted &PlayerWanted; - static CPlayerInfo &PlayerInfo; - static uint32 &Time1; - static uint32 &Time2; - static uint32 &Time3; - static uint32 &Time4; - static uint32 &Frame; - static uint8 &ClockHours; - static uint8 &ClockMinutes; - static uint16 &OldWeatherType; - static uint16 &NewWeatherType; - static float &WeatherInterpolationValue; - static float &TimeStepNonClipped; - static float &TimeStep; - static float &TimeScale; - static float &CameraFixedX; - static float &CameraFixedY; - static float &CameraFixedZ; - static int32 &OldRadioStation; - static int8 &CameraMode; - static bool &bAllowLookAroundCam; - static float &LoadSceneX; - static float &LoadSceneY; - static float &LoadSceneZ; - static float &CameraFocusX; - static float &CameraFocusY; - static float &CameraFocusZ; - static bool &bPlayerInRCBuggy; - static float &fDistanceLookAroundCam; - static float &fAlphaAngleLookAroundCam; - static float &fBetaAngleLookAroundCam; + static uint8 Mode; + static CAddressInReplayBuffer Record; + static CAddressInReplayBuffer Playback; + static uint8 *pBuf0; + static CAutomobile *pBuf1; + static uint8 *pBuf2; + static CPlayerPed *pBuf3; + static uint8 *pBuf4; + static CCutsceneHead *pBuf5; + static uint8 *pBuf6; + static CPtrNode *pBuf7; + static uint8 *pBuf8; + static CEntryInfoNode *pBuf9; + static uint8 *pBuf10; + static CDummyPed *pBuf11; + static uint8 *pRadarBlips; + static uint8 *pStoredCam; + static uint8 *pWorld1; + static CReference *pEmptyReferences; + static CStoredDetailedAnimationState *pPedAnims; + static uint8 *pPickups; + static uint8 *pReferences; + static uint8 BufferStatus[NUM_REPLAYBUFFERS]; + static uint8 Buffers[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE]; + static bool bPlayingBackFromFile; + static bool bReplayEnabled; + static uint32 SlowMotion; + static uint32 FramesActiveLookAroundCam; + static bool bDoLoadSceneWhenDone; + static CPtrList WorldPtrList; + static CPtrList BigBuildingPtrList; + static CWanted PlayerWanted; + static CPlayerInfo PlayerInfo; + static uint32 Time1; + static uint32 Time2; + static uint32 Time3; + static uint32 Time4; + static uint32 Frame; + static uint8 ClockHours; + static uint8 ClockMinutes; + static uint16 OldWeatherType; + static uint16 NewWeatherType; + static float WeatherInterpolationValue; + static float TimeStepNonClipped; + static float TimeStep; + static float TimeScale; + static float CameraFixedX; + static float CameraFixedY; + static float CameraFixedZ; + static int32 OldRadioStation; + static int8 CameraMode; + static bool bAllowLookAroundCam; + static float LoadSceneX; + static float LoadSceneY; + static float LoadSceneZ; + static float CameraFocusX; + static float CameraFocusY; + static float CameraFocusZ; + static bool bPlayerInRCBuggy; + static float fDistanceLookAroundCam; + static float fAlphaAngleLookAroundCam; + static float fBetaAngleLookAroundCam; public: static void Init(void); diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp index 788a054a..2730f5c0 100644 --- a/src/control/Restart.cpp +++ b/src/control/Restart.cpp @@ -4,22 +4,22 @@ #include "Zones.h" #include "PathFind.h" -uint8 &CRestart::OverrideHospitalLevel = *(uint8*)0x95CD4C; -uint8 &CRestart::OverridePoliceStationLevel = *(uint8*)0x95CD50; -bool &CRestart::bFadeInAfterNextArrest = *(bool*)0x95CD69; -bool &CRestart::bFadeInAfterNextDeath = *(bool*)0x95CD9D; +uint8 CRestart::OverrideHospitalLevel; +uint8 CRestart::OverridePoliceStationLevel; +bool CRestart::bFadeInAfterNextArrest; +bool CRestart::bFadeInAfterNextDeath; -bool &CRestart::bOverrideRestart = *(bool*)0x95CD5D; -CVector &CRestart::OverridePosition = *(CVector*)0x8E2C00; -float &CRestart::OverrideHeading = *(float*)0x8F2A18; +bool CRestart::bOverrideRestart; +CVector CRestart::OverridePosition; +float CRestart::OverrideHeading; -CVector(&CRestart::HospitalRestartPoints)[NUM_RESTART_POINTS] = *(CVector(*)[NUM_RESTART_POINTS])*(uintptr*)0x87F9B0; -float(&CRestart::HospitalRestartHeadings)[NUM_RESTART_POINTS] = *(float(*)[NUM_RESTART_POINTS])*(uintptr*)0x6F1D40; -uint16 &CRestart::NumberOfHospitalRestarts = *(uint16*)0x95CC46; +CVector CRestart::HospitalRestartPoints[NUM_RESTART_POINTS]; +float CRestart::HospitalRestartHeadings[NUM_RESTART_POINTS]; +uint16 CRestart::NumberOfHospitalRestarts; -CVector(&CRestart::PoliceRestartPoints)[NUM_RESTART_POINTS] = *(CVector(*)[NUM_RESTART_POINTS])*(uintptr*)0x846228; -float(&CRestart::PoliceRestartHeadings)[NUM_RESTART_POINTS] = *(float(*)[NUM_RESTART_POINTS])*(uintptr*)0x6F1D20; -uint16 &CRestart::NumberOfPoliceRestarts = *(uint16*)0x95CC44; +CVector CRestart::PoliceRestartPoints[NUM_RESTART_POINTS]; +float CRestart::PoliceRestartHeadings[NUM_RESTART_POINTS]; +uint16 CRestart::NumberOfPoliceRestarts; void CRestart::Initialise() diff --git a/src/control/Restart.h b/src/control/Restart.h index fb7806db..5d84c723 100644 --- a/src/control/Restart.h +++ b/src/control/Restart.h @@ -17,20 +17,20 @@ public: static void LoadAllRestartPoints(uint8 *buf, uint32 size); static void SaveAllRestartPoints(uint8 *buf, uint32 *size); - static uint8 &OverrideHospitalLevel; - static uint8 &OverridePoliceStationLevel; - static bool &bFadeInAfterNextArrest; - static bool &bFadeInAfterNextDeath; + static uint8 OverrideHospitalLevel; + static uint8 OverridePoliceStationLevel; + static bool bFadeInAfterNextArrest; + static bool bFadeInAfterNextDeath; - static bool &bOverrideRestart; - static CVector &OverridePosition; - static float &OverrideHeading; + static bool bOverrideRestart; + static CVector OverridePosition; + static float OverrideHeading; - static CVector(&HospitalRestartPoints)[NUM_RESTART_POINTS]; - static float (&HospitalRestartHeadings)[NUM_RESTART_POINTS]; - static uint16 &NumberOfHospitalRestarts; + static CVector HospitalRestartPoints[NUM_RESTART_POINTS]; + static float HospitalRestartHeadings[NUM_RESTART_POINTS]; + static uint16 NumberOfHospitalRestarts; - static CVector (&PoliceRestartPoints)[NUM_RESTART_POINTS]; - static float (&PoliceRestartHeadings)[NUM_RESTART_POINTS]; - static uint16 &NumberOfPoliceRestarts; + static CVector PoliceRestartPoints[NUM_RESTART_POINTS]; + static float PoliceRestartHeadings[NUM_RESTART_POINTS]; + static uint16 NumberOfPoliceRestarts; }; diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 9548bc0a..fcfa42e3 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -15,9 +15,9 @@ #include "CarCtrl.h" #include "General.h" -int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34; -int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8; -bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810; +int16 CRoadBlocks::NumRoadBlocks; +int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS]; +bool CRoadBlocks::InOrOut[NUMROADBLOCKS]; void CRoadBlocks::Init(void) diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h index 16e3a362..0f0c1882 100644 --- a/src/control/RoadBlocks.h +++ b/src/control/RoadBlocks.h @@ -6,9 +6,9 @@ class CVehicle; class CRoadBlocks { public: - static int16 (&NumRoadBlocks); - static int16 (&RoadBlockObjects)[NUMROADBLOCKS]; - static bool (&InOrOut)[NUMROADBLOCKS]; + static int16 NumRoadBlocks; + static int16 RoadBlockObjects[NUMROADBLOCKS]; + static bool InOrOut[NUMROADBLOCKS]; static void Init(void); static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 428ac66a..d4ede846 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -87,47 +87,47 @@ #define FEET_IN_METER 3.33f #endif -uint8 (&CTheScripts::ScriptSpace)[SIZE_SCRIPT_SPACE] = *(uint8(*)[SIZE_SCRIPT_SPACE])*(uintptr*)0x74B248; -CRunningScript(&CTheScripts::ScriptsArray)[MAX_NUM_SCRIPTS] = *(CRunningScript(*)[MAX_NUM_SCRIPTS])*(uintptr*)0x6F5C08; -int32(&CTheScripts::BaseBriefIdForContact)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x880200; -int32(&CTheScripts::OnAMissionForContactFlag)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x8622F0; -intro_text_line (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(intro_text_line (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68; -intro_script_rectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(intro_script_rectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108; -CSprite2d (&CTheScripts::ScriptSprites)[MAX_NUM_SCRIPT_SRPITES] = *(CSprite2d(*)[MAX_NUM_SCRIPT_SRPITES])*(uintptr*)0x72B090; -script_sphere_struct(&CTheScripts::ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES] = *(script_sphere_struct(*)[MAX_NUM_SCRIPT_SPHERES])*(uintptr*)0x727D60; -tCollectiveData(&CTheScripts::CollectiveArray)[MAX_NUM_COLLECTIVES] = *(tCollectiveData(*)[MAX_NUM_COLLECTIVES])*(uintptr*)0x6FA008; -tUsedObject(&CTheScripts::UsedObjectArray)[MAX_NUM_USED_OBJECTS] = *(tUsedObject(*)[MAX_NUM_USED_OBJECTS])*(uintptr*)0x6E69C8; -int32(&CTheScripts::MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS] = *(int32(*)[MAX_NUM_MISSION_SCRIPTS])*(uintptr*)0x6F0558; -tBuildingSwap(&CTheScripts::BuildingSwapArray)[MAX_NUM_BUILDING_SWAPS] = *(tBuildingSwap(*)[MAX_NUM_BUILDING_SWAPS])*(uintptr*)0x880E30; -CEntity*(&CTheScripts::InvisibilitySettingArray)[MAX_NUM_INVISIBILITY_SETTINGS] = *(CEntity*(*)[MAX_NUM_INVISIBILITY_SETTINGS])*(uintptr*)0x8620F0; -CStoredLine (&CTheScripts::aStoredLines)[MAX_NUM_STORED_LINES] = *(CStoredLine(*)[MAX_NUM_STORED_LINES])*(uintptr*)0x743018; -bool &CTheScripts::DbgFlag = *(bool*)0x95CD87; -uint32 &CTheScripts::OnAMissionFlag = *(uint32*)0x8F1B64; -int32 &CTheScripts::StoreVehicleIndex = *(int32*)0x8F5F3C; -bool &CTheScripts::StoreVehicleWasRandom = *(bool*)0x95CDBC; -CRunningScript *&CTheScripts::pIdleScripts = *(CRunningScript**)0x9430D4; -CRunningScript *&CTheScripts::pActiveScripts = *(CRunningScript**)0x8E2BF4; -uint32 &CTheScripts::NextFreeCollectiveIndex = *(uint32*)0x942F98; -int32 &CTheScripts::LastRandomPedId = *(int32*)0x8F251C; -uint16 &CTheScripts::NumberOfUsedObjects = *(uint16*)0x95CC72; -bool &CTheScripts::bAlreadyRunningAMissionScript = *(bool*)0x95CDB3; -bool &CTheScripts::bUsingAMultiScriptFile = *(bool*)0x95CD55; -uint16 &CTheScripts::NumberOfMissionScripts = *(uint16*)0x95CC9A; -uint32 &CTheScripts::LargestMissionScriptSize = *(uint32*)0x9414C8; -uint32 &CTheScripts::MainScriptSize = *(uint32*)0x9405A4; -uint8 &CTheScripts::FailCurrentMission = *(uint8*)0x95CD41; -uint8 &CTheScripts::CountdownToMakePlayerUnsafe = *(uint8*)0x95CD51; -uint8 &CTheScripts::DelayMakingPlayerUnsafeThisTime = *(uint8*)0x95CD88; -uint16 &CTheScripts::NumScriptDebugLines = *(uint16*)0x95CC42; -uint16 &CTheScripts::NumberOfIntroRectanglesThisFrame = *(uint16*)0x95CC88; -uint16 &CTheScripts::NumberOfIntroTextLinesThisFrame = *(uint16*)0x95CC32; -uint8 &CTheScripts::UseTextCommands = *(uint8*)0x95CD57; -CMissionCleanup (&CTheScripts::MissionCleanup) = *(CMissionCleanup*)0x8F2A24; -CUpsideDownCarCheck (&CTheScripts::UpsideDownCars) = *(CUpsideDownCarCheck*)0x6EE450; -CStuckCarCheck (&CTheScripts::StuckCars) = *(CStuckCarCheck*)0x87C588; -uint16 &CTheScripts::CommandsExecuted = *(uint16*)0x95CCA6; -uint16 &CTheScripts::ScriptsUpdated = *(uint16*)0x95CC5E; -int32(&ScriptParams)[32] = *(int32(*)[32])*(uintptr*)0x6ED460; +uint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE]; +CRunningScript CTheScripts::ScriptsArray[MAX_NUM_SCRIPTS]; +int32 CTheScripts::BaseBriefIdForContact[MAX_NUM_CONTACTS]; +int32 CTheScripts::OnAMissionForContactFlag[MAX_NUM_CONTACTS]; +intro_text_line CTheScripts::IntroTextLines[MAX_NUM_INTRO_TEXT_LINES]; +intro_script_rectangle CTheScripts::IntroRectangles[MAX_NUM_INTRO_RECTANGLES]; +CSprite2d CTheScripts::ScriptSprites[MAX_NUM_SCRIPT_SRPITES]; +script_sphere_struct CTheScripts::ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES]; +tCollectiveData CTheScripts::CollectiveArray[MAX_NUM_COLLECTIVES]; +tUsedObject CTheScripts::UsedObjectArray[MAX_NUM_USED_OBJECTS]; +int32 CTheScripts::MultiScriptArray[MAX_NUM_MISSION_SCRIPTS]; +tBuildingSwap CTheScripts::BuildingSwapArray[MAX_NUM_BUILDING_SWAPS]; +CEntity* CTheScripts::InvisibilitySettingArray[MAX_NUM_INVISIBILITY_SETTINGS]; +CStoredLine CTheScripts::aStoredLines[MAX_NUM_STORED_LINES]; +bool CTheScripts::DbgFlag; +uint32 CTheScripts::OnAMissionFlag; +int32 CTheScripts::StoreVehicleIndex; +bool CTheScripts::StoreVehicleWasRandom; +CRunningScript *CTheScripts::pIdleScripts; +CRunningScript *CTheScripts::pActiveScripts; +uint32 CTheScripts::NextFreeCollectiveIndex; +int32 CTheScripts::LastRandomPedId; +uint16 CTheScripts::NumberOfUsedObjects; +bool CTheScripts::bAlreadyRunningAMissionScript; +bool CTheScripts::bUsingAMultiScriptFile; +uint16 CTheScripts::NumberOfMissionScripts; +uint32 CTheScripts::LargestMissionScriptSize; +uint32 CTheScripts::MainScriptSize; +uint8 CTheScripts::FailCurrentMission; +uint8 CTheScripts::CountdownToMakePlayerUnsafe; +uint8 CTheScripts::DelayMakingPlayerUnsafeThisTime; +uint16 CTheScripts::NumScriptDebugLines; +uint16 CTheScripts::NumberOfIntroRectanglesThisFrame; +uint16 CTheScripts::NumberOfIntroTextLinesThisFrame; +uint8 CTheScripts::UseTextCommands; +CMissionCleanup CTheScripts::MissionCleanup; +CUpsideDownCarCheck CTheScripts::UpsideDownCars; +CStuckCarCheck CTheScripts::StuckCars; +uint16 CTheScripts::CommandsExecuted; +uint16 CTheScripts::ScriptsUpdated; +int32 ScriptParams[32]; CMissionCleanup::CMissionCleanup() { diff --git a/src/control/Script.h b/src/control/Script.h index 4338bd18..2eed29fe 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -240,46 +240,46 @@ enum { class CTheScripts { - static uint8(&ScriptSpace)[SIZE_SCRIPT_SPACE]; - static CRunningScript(&ScriptsArray)[MAX_NUM_SCRIPTS]; - static int32(&BaseBriefIdForContact)[MAX_NUM_CONTACTS]; - static int32(&OnAMissionForContactFlag)[MAX_NUM_CONTACTS]; - static intro_text_line(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES]; - static intro_script_rectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES]; - static CSprite2d(&ScriptSprites)[MAX_NUM_SCRIPT_SRPITES]; - static script_sphere_struct(&ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES]; - static tCollectiveData(&CollectiveArray)[MAX_NUM_COLLECTIVES]; - static tUsedObject(&UsedObjectArray)[MAX_NUM_USED_OBJECTS]; - static int32(&MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS]; - static tBuildingSwap(&BuildingSwapArray)[MAX_NUM_BUILDING_SWAPS]; - static CEntity*(&InvisibilitySettingArray)[MAX_NUM_INVISIBILITY_SETTINGS]; - static CStoredLine(&aStoredLines)[MAX_NUM_STORED_LINES]; - static bool &DbgFlag; - static uint32 &OnAMissionFlag; - static CMissionCleanup &MissionCleanup; - static CStuckCarCheck &StuckCars; - static CUpsideDownCarCheck &UpsideDownCars; - static int32 &StoreVehicleIndex; - static bool &StoreVehicleWasRandom; - static CRunningScript *&pIdleScripts; - static CRunningScript *&pActiveScripts; - static uint32 &NextFreeCollectiveIndex; - static int32 &LastRandomPedId; - static uint16 &NumberOfUsedObjects; - static bool &bAlreadyRunningAMissionScript; - static bool &bUsingAMultiScriptFile; - static uint16 &NumberOfMissionScripts; - static uint32 &LargestMissionScriptSize; - static uint32 &MainScriptSize; - static uint8 &FailCurrentMission; - static uint8 &CountdownToMakePlayerUnsafe; - static uint8 &DelayMakingPlayerUnsafeThisTime; - static uint16 &NumScriptDebugLines; - static uint16 &NumberOfIntroRectanglesThisFrame; - static uint16 &NumberOfIntroTextLinesThisFrame; - static uint8 &UseTextCommands; - static uint16 &CommandsExecuted; - static uint16 &ScriptsUpdated; + static uint8 ScriptSpace[SIZE_SCRIPT_SPACE]; + static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS]; + static int32 BaseBriefIdForContact[MAX_NUM_CONTACTS]; + static int32 OnAMissionForContactFlag[MAX_NUM_CONTACTS]; + static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES]; + static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES]; + static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES]; + static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES]; + static tCollectiveData CollectiveArray[MAX_NUM_COLLECTIVES]; + static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS]; + static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS]; + static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS]; + static CEntity* InvisibilitySettingArray[MAX_NUM_INVISIBILITY_SETTINGS]; + static CStoredLine aStoredLines[MAX_NUM_STORED_LINES]; + static bool DbgFlag; + static uint32 OnAMissionFlag; + static CMissionCleanup MissionCleanup; + static CStuckCarCheck StuckCars; + static CUpsideDownCarCheck UpsideDownCars; + static int32 StoreVehicleIndex; + static bool StoreVehicleWasRandom; + static CRunningScript *pIdleScripts; + static CRunningScript *pActiveScripts; + static uint32 NextFreeCollectiveIndex; + static int32 LastRandomPedId; + static uint16 NumberOfUsedObjects; + static bool bAlreadyRunningAMissionScript; + static bool bUsingAMultiScriptFile; + static uint16 NumberOfMissionScripts; + static uint32 LargestMissionScriptSize; + static uint32 MainScriptSize; + static uint8 FailCurrentMission; + static uint8 CountdownToMakePlayerUnsafe; + static uint8 DelayMakingPlayerUnsafeThisTime; + static uint16 NumScriptDebugLines; + static uint16 NumberOfIntroRectanglesThisFrame; + static uint16 NumberOfIntroTextLinesThisFrame; + static uint8 UseTextCommands; + static uint16 CommandsExecuted; + static uint16 ScriptsUpdated; public: static void Init(); diff --git a/src/core/Accident.cpp b/src/core/Accident.cpp index d8313ddc..3c39b11d 100644 --- a/src/core/Accident.cpp +++ b/src/core/Accident.cpp @@ -6,7 +6,7 @@ #include "Pools.h" #include "World.h" -CAccidentManager& gAccidentManager = *(CAccidentManager*)0x87FD10; +CAccidentManager gAccidentManager; CAccident* CAccidentManager::GetNextFreeAccident() diff --git a/src/core/Accident.h b/src/core/Accident.h index 69889645..949d5fb9 100644 --- a/src/core/Accident.h +++ b/src/core/Accident.h @@ -29,4 +29,4 @@ public: bool WorkToDoForMedics(); }; -extern CAccidentManager& gAccidentManager; \ No newline at end of file +extern CAccidentManager gAccidentManager; \ No newline at end of file diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index cfdea46a..4d954ccd 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -28,7 +28,7 @@ const float DefaultFOV = 70.0f; // beta: 80.0f bool PrintDebugCode = false; -int16 &DebugCamMode = *(int16*)0x95CCF2; +int16 DebugCamMode; #ifdef FREE_CAM bool CCamera::bFreeCam = false; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index c2392d3b..a1f36d93 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -58,9 +58,9 @@ enum #define PLAYER (CWorld::Players[CWorld::PlayerInFocus].m_pPed) // NB: removed explicit TheCamera from all functions -CCamera &TheCamera = *(CCamera*)0x6FACF8; -bool &CCamera::m_bUseMouse3rdPerson = *(bool *)0x5F03D8; -bool &bDidWeProcessAnyCinemaCam = *(bool*)0x95CD46; +CCamera TheCamera; +bool CCamera::m_bUseMouse3rdPerson = true; +bool bDidWeProcessAnyCinemaCam; #ifdef IMPROVED_CAMERA #define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k) diff --git a/src/core/Camera.h b/src/core/Camera.h index 09a8d603..d1c8ec03 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -6,7 +6,7 @@ class CPed; class CAutomobile; class CGarage; -extern int16 &DebugCamMode; +extern int16 DebugCamMode; enum { @@ -540,7 +540,7 @@ uint32 unknown; // some counter having to do with music uint32 m_uiFadeTimeStarted; uint32 m_uiFadeTimeStartedMusic; - static bool &m_bUseMouse3rdPerson; + static bool m_bUseMouse3rdPerson; #ifdef FREE_CAM static bool bFreeCam; #endif @@ -647,7 +647,7 @@ 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; +extern CCamera TheCamera; void CamShakeNoPos(CCamera*, float); void MakeAngleLessThan180(float &Angle); diff --git a/src/core/Clock.cpp b/src/core/Clock.cpp index a97dcb5f..69fdd682 100644 --- a/src/core/Clock.cpp +++ b/src/core/Clock.cpp @@ -6,17 +6,17 @@ #include "Stats.h" _TODO("gbFastTime"); -bool &gbFastTime = *(bool*)0x95CDBB; +bool gbFastTime; -uint8 &CClock::ms_nGameClockHours = *(uint8*)0x95CDA6; -uint8 &CClock::ms_nGameClockMinutes = *(uint8*)0x95CDC8; -uint16 &CClock::ms_nGameClockSeconds = *(uint16*)0x95CC7C; -uint8 &CClock::ms_Stored_nGameClockHours = *(uint8*)0x95CD7B; -uint8 &CClock::ms_Stored_nGameClockMinutes = *(uint8*)0x95CD9B; -uint16 &CClock::ms_Stored_nGameClockSeconds = *(uint16*)0x95CC9C; -uint32 &CClock::ms_nMillisecondsPerGameMinute = *(uint32*)0x8F2C64; -uint32 &CClock::ms_nLastClockTick = *(uint32*)0x9430E4; -bool &CClock::ms_bClockHasBeenStored = *(bool*)0x95CD82; +uint8 CClock::ms_nGameClockHours; +uint8 CClock::ms_nGameClockMinutes; +uint16 CClock::ms_nGameClockSeconds; +uint8 CClock::ms_Stored_nGameClockHours; +uint8 CClock::ms_Stored_nGameClockMinutes; +uint16 CClock::ms_Stored_nGameClockSeconds; +uint32 CClock::ms_nMillisecondsPerGameMinute; +uint32 CClock::ms_nLastClockTick; +bool CClock::ms_bClockHasBeenStored; void CClock::Initialise(uint32 scale) diff --git a/src/core/Clock.h b/src/core/Clock.h index 6b9908ba..a611cd50 100644 --- a/src/core/Clock.h +++ b/src/core/Clock.h @@ -3,15 +3,15 @@ class CClock { public: - static uint8 &ms_nGameClockHours; - static uint8 &ms_nGameClockMinutes; - static uint16 &ms_nGameClockSeconds; - static uint8 &ms_Stored_nGameClockHours; - static uint8 &ms_Stored_nGameClockMinutes; - static uint16 &ms_Stored_nGameClockSeconds; - static uint32 &ms_nMillisecondsPerGameMinute; - static uint32 &ms_nLastClockTick; - static bool &ms_bClockHasBeenStored; + static uint8 ms_nGameClockHours; + static uint8 ms_nGameClockMinutes; + static uint16 ms_nGameClockSeconds; + static uint8 ms_Stored_nGameClockHours; + static uint8 ms_Stored_nGameClockMinutes; + static uint16 ms_Stored_nGameClockSeconds; + static uint32 ms_nMillisecondsPerGameMinute; + static uint32 ms_nLastClockTick; + static bool ms_bClockHasBeenStored; static void Initialise(uint32 scale); static void Update(void); diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 541257c6..ce8674d7 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -18,7 +18,7 @@ #include "win.h" #include "GenericGameStorage.h" -CControllerConfigManager &ControlsManager = *(CControllerConfigManager*)0x8F43A4; +CControllerConfigManager ControlsManager; CControllerConfigManager::CControllerConfigManager() { diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index 458e457c..c328594e 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -198,4 +198,4 @@ public: VALIDATE_SIZE(CControllerConfigManager, 0x143C); -extern CControllerConfigManager &ControlsManager; \ No newline at end of file +extern CControllerConfigManager ControlsManager; \ No newline at end of file diff --git a/src/core/EventList.cpp b/src/core/EventList.cpp index d1c76f33..5ca4cdb0 100644 --- a/src/core/EventList.cpp +++ b/src/core/EventList.cpp @@ -11,7 +11,6 @@ int32 CEventList::ms_nFirstFreeSlotIndex; CEvent gaEvent[NUMEVENTS]; -//CEvent *gaEvent = (CEvent*)0x6EF830; enum { diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp index 2a8628b0..382316bb 100644 --- a/src/core/FileMgr.cpp +++ b/src/core/FileMgr.cpp @@ -168,8 +168,8 @@ myfeof(int fd) } -char *CFileMgr::ms_rootDirName = (char*)0x5F18F8; -char *CFileMgr::ms_dirName = (char*)0x713CA8; +char CFileMgr::ms_rootDirName[128] = {'\0'}; +char CFileMgr::ms_dirName[128]; void CFileMgr::Initialise(void) diff --git a/src/core/FileMgr.h b/src/core/FileMgr.h index 3df0c7d8..a6e4b6e5 100644 --- a/src/core/FileMgr.h +++ b/src/core/FileMgr.h @@ -2,8 +2,8 @@ class CFileMgr { - static char *ms_rootDirName; //[128]; - static char *ms_dirName; //[128]; + static char ms_rootDirName[128]; + static char ms_dirName[128]; public: static void Initialise(void); static void ChangeDir(const char *dir); diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index cfa849e9..f900091e 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -16,7 +16,7 @@ #include "Ped.h" #include "Fire.h" -CFireManager &gFireManager = *(CFireManager*)0x8F31D0; +CFireManager gFireManager; CFire::CFire() { diff --git a/src/core/Fire.h b/src/core/Fire.h index a4599d11..85e53f61 100644 --- a/src/core/Fire.h +++ b/src/core/Fire.h @@ -48,4 +48,4 @@ public: void RemoveScriptFire(int16 index); void SetScriptFireAudio(int16 index, bool state); }; -extern CFireManager &gFireManager; +extern CFireManager gFireManager; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index a01689e4..b2ecdac5 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -93,7 +93,7 @@ int8 CMenuManager::m_PrefsSpeakers; int32 CMenuManager::m_ControlMethod; int8 CMenuManager::m_PrefsDMA = 1; int32 CMenuManager::m_PrefsLanguage; -uint8 CMenuManager::m_PrefsStereoMono; // *(bool*)0x95CDB5; // unused except restore settings +uint8 CMenuManager::m_PrefsStereoMono; // unused except restore settings bool CMenuManager::m_PrefsAllowNastyGame = true; bool CMenuManager::m_bStartUpFrontEndRequested; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 8699ffeb..f115d52f 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -89,19 +89,19 @@ -eLevelName &CGame::currLevel = *(eLevelName*)0x941514; -bool &CGame::bDemoMode = *(bool*)0x5F4DD0; -bool &CGame::nastyGame = *(bool*)0x5F4DD4; -bool &CGame::frenchGame = *(bool*)0x95CDCB; -bool &CGame::germanGame = *(bool*)0x95CD1E; -bool &CGame::noProstitutes = *(bool*)0x95CDCF; -bool &CGame::playingIntro = *(bool*)0x95CDC2; -char *CGame::aDatFile = (char*)0x773A48; +eLevelName CGame::currLevel; +bool CGame::bDemoMode = true; +bool CGame::nastyGame = true; +bool CGame::frenchGame; +bool CGame::germanGame; +bool CGame::noProstitutes; +bool CGame::playingIntro; +char CGame::aDatFile[32]; #ifdef MORE_LANGUAGES bool CGame::russianGame = false; #endif -int &gameTxdSlot = *(int*)0x628D88; +int gameTxdSlot; bool CGame::InitialiseOnceBeforeRW(void) @@ -115,7 +115,9 @@ CGame::InitialiseOnceBeforeRW(void) bool CGame::InitialiseRenderWare(void) { +#ifdef USE_TEXTURE_POOL _TexturePoolsInitialise(); +#endif CTxdStore::Initialise(); CVisibilityPlugins::Initialise(); @@ -188,7 +190,9 @@ void CGame::ShutdownRenderWare(void) CVisibilityPlugins::Shutdown(); +#ifdef USE_TEXTURE_POOL _TexturePoolsShutdown(); +#endif } bool CGame::InitialiseOnceAfterRW(void) diff --git a/src/core/Game.h b/src/core/Game.h index 30581893..8dc73e8a 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -11,17 +11,17 @@ enum eLevelName class CGame { public: - static eLevelName &currLevel; - static bool &bDemoMode; - static bool &nastyGame; - static bool &frenchGame; - static bool &germanGame; + static eLevelName currLevel; + static bool bDemoMode; + static bool nastyGame; + static bool frenchGame; + static bool germanGame; #ifdef MORE_LANGUAGES static bool russianGame; #endif - static bool &noProstitutes; - static bool &playingIntro; - static char *aDatFile; //[32]; + static bool noProstitutes; + static bool playingIntro; + static char aDatFile[32]; static bool InitialiseOnceBeforeRW(void); static bool InitialiseRenderWare(void); diff --git a/src/core/IniFile.cpp b/src/core/IniFile.cpp index 744f4bd0..d8e91c98 100644 --- a/src/core/IniFile.cpp +++ b/src/core/IniFile.cpp @@ -7,8 +7,8 @@ #include "main.h" #include "Population.h" -float CIniFile::PedNumberMultiplier = 1.0f;// = *(float*)0x6182F4; -float CIniFile::CarNumberMultiplier = 1.0f;// = *(float*)0x6182F8; +float CIniFile::PedNumberMultiplier = 1.0f; +float CIniFile::CarNumberMultiplier = 1.0f; void CIniFile::LoadIniFile() { diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 201dc5b6..2db375b2 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -35,26 +35,26 @@ #include "Wanted.h" #include "General.h" -CPad *Pads = (CPad*)0x6F0360; // [2] -CMousePointerStateHelper &MousePointerStateHelper = *(CMousePointerStateHelper*)0x95CC8C; +CPad Pads[MAX_PADS]; +CMousePointerStateHelper MousePointerStateHelper; -bool &CPad::bDisplayNoControllerMessage = *(bool *)0x95CD52; -bool &CPad::bObsoleteControllerMessage = *(bool *)0x95CDB8; +bool CPad::bDisplayNoControllerMessage; +bool CPad::bObsoleteControllerMessage; bool CPad::bOldDisplayNoControllerMessage; -bool &CPad::m_bMapPadOneToPadTwo = *(bool *)0x95CD48; +bool CPad::m_bMapPadOneToPadTwo; -CKeyboardState &CPad::OldKeyState = *(CKeyboardState*)0x6F1E70; -CKeyboardState &CPad::NewKeyState = *(CKeyboardState*)0x6E60D0; -CKeyboardState &CPad::TempKeyState = *(CKeyboardState*)0x774DE8; +CKeyboardState CPad::OldKeyState; +CKeyboardState CPad::NewKeyState; +CKeyboardState CPad::TempKeyState; char CPad::KeyBoardCheatString[20]; -CMouseControllerState &CPad::OldMouseControllerState = *(CMouseControllerState*)0x8472A0; -CMouseControllerState &CPad::NewMouseControllerState = *(CMouseControllerState*)0x8809F0; -CMouseControllerState &CPad::PCTempMouseControllerState = *(CMouseControllerState*)0x6F1E60; +CMouseControllerState CPad::OldMouseControllerState; +CMouseControllerState CPad::NewMouseControllerState; +CMouseControllerState CPad::PCTempMouseControllerState; _TODO("gbFastTime"); -extern bool &gbFastTime; +extern bool gbFastTime; void WeaponCheat() { diff --git a/src/core/Pad.h b/src/core/Pad.h index cb705c6b..9ebd6396 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -66,7 +66,7 @@ public: VALIDATE_SIZE(CMousePointerStateHelper, 0x2); -extern CMousePointerStateHelper &MousePointerStateHelper; +extern CMousePointerStateHelper MousePointerStateHelper; class CKeyboardState @@ -163,18 +163,18 @@ public: CPad() { } ~CPad() { } - static bool &bDisplayNoControllerMessage; - static bool &bObsoleteControllerMessage; + static bool bDisplayNoControllerMessage; + static bool bObsoleteControllerMessage; static bool bOldDisplayNoControllerMessage; - static bool &m_bMapPadOneToPadTwo; + static bool m_bMapPadOneToPadTwo; - static CKeyboardState &OldKeyState; - static CKeyboardState &NewKeyState; - static CKeyboardState &TempKeyState; + static CKeyboardState OldKeyState; + static CKeyboardState NewKeyState; + static CKeyboardState TempKeyState; static char KeyBoardCheatString[20]; - static CMouseControllerState &OldMouseControllerState; - static CMouseControllerState &NewMouseControllerState; - static CMouseControllerState &PCTempMouseControllerState; + static CMouseControllerState OldMouseControllerState; + static CMouseControllerState NewMouseControllerState; + static CMouseControllerState PCTempMouseControllerState; #ifdef GTA_PS2_STUFF @@ -450,4 +450,4 @@ public: }; VALIDATE_SIZE(CPad, 0xFC); -extern CPad *Pads; //[2] +extern CPad Pads[MAX_PADS]; diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index 6add9e0c..65294368 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -10,15 +10,15 @@ #include "Wanted.h" #include "World.h" -CCPtrNodePool *&CPools::ms_pPtrNodePool = *(CCPtrNodePool**)0x943044; -CEntryInfoNodePool *&CPools::ms_pEntryInfoNodePool = *(CEntryInfoNodePool**)0x941448; -CPedPool *&CPools::ms_pPedPool = *(CPedPool**)0x8F2C60; -CVehiclePool *&CPools::ms_pVehiclePool = *(CVehiclePool**)0x9430DC; -CBuildingPool *&CPools::ms_pBuildingPool = *(CBuildingPool**)0x8F2C04; -CTreadablePool *&CPools::ms_pTreadablePool = *(CTreadablePool**)0x8F2568; -CObjectPool *&CPools::ms_pObjectPool = *(CObjectPool**)0x880E28; -CDummyPool *&CPools::ms_pDummyPool = *(CDummyPool**)0x8F2C18; -CAudioScriptObjectPool *&CPools::ms_pAudioScriptObjectPool = *(CAudioScriptObjectPool**)0x8F1B6C; +CCPtrNodePool *CPools::ms_pPtrNodePool; +CEntryInfoNodePool *CPools::ms_pEntryInfoNodePool; +CPedPool *CPools::ms_pPedPool; +CVehiclePool *CPools::ms_pVehiclePool; +CBuildingPool *CPools::ms_pBuildingPool; +CTreadablePool *CPools::ms_pTreadablePool; +CObjectPool *CPools::ms_pObjectPool; +CDummyPool *CPools::ms_pDummyPool; +CAudioScriptObjectPool *CPools::ms_pAudioScriptObjectPool; void CPools::Initialise(void) diff --git a/src/core/Pools.h b/src/core/Pools.h index 74b87585..b0ba6598 100644 --- a/src/core/Pools.h +++ b/src/core/Pools.h @@ -22,15 +22,15 @@ typedef CPool CAudioScriptObjectPool; class CPools { - static CCPtrNodePool *&ms_pPtrNodePool; - static CEntryInfoNodePool *&ms_pEntryInfoNodePool; - static CPedPool *&ms_pPedPool; - static CVehiclePool *&ms_pVehiclePool; - static CBuildingPool *&ms_pBuildingPool; - static CTreadablePool *&ms_pTreadablePool; - static CObjectPool *&ms_pObjectPool; - static CDummyPool *&ms_pDummyPool; - static CAudioScriptObjectPool *&ms_pAudioScriptObjectPool; + static CCPtrNodePool *ms_pPtrNodePool; + static CEntryInfoNodePool *ms_pEntryInfoNodePool; + static CPedPool *ms_pPedPool; + static CVehiclePool *ms_pVehiclePool; + static CBuildingPool *ms_pBuildingPool; + static CTreadablePool *ms_pTreadablePool; + static CObjectPool *ms_pObjectPool; + static CDummyPool *ms_pDummyPool; + static CAudioScriptObjectPool *ms_pAudioScriptObjectPool; public: static CCPtrNodePool *GetPtrNodePool(void) { return ms_pPtrNodePool; } static CEntryInfoNodePool *GetEntryInfoNodePool(void) { return ms_pEntryInfoNodePool; } diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index ed24814d..48b97832 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -19,28 +19,28 @@ float CRadar::m_radarRange; sRadarTrace CRadar::ms_RadarTrace[NUMRADARBLIPS]; CVector2D vec2DRadarOrigin; -int32 gRadarTxdIds[64];// = (int*)0x6299C0; +int32 gRadarTxdIds[64]; -CSprite2d CRadar::AsukaSprite;// = *(CSprite2d*)0x8F1A40; -CSprite2d CRadar::BombSprite;// = (CSprite2d*)0x8F5FB4; -CSprite2d CRadar::CatSprite;// = (CSprite2d*)0x885B24; -CSprite2d CRadar::CentreSprite;// = (CSprite2d*)0x8F6268; -CSprite2d CRadar::CopcarSprite;// = (CSprite2d*)0x8F1A2C; -CSprite2d CRadar::DonSprite;// = (CSprite2d*)0x8F2BE0; -CSprite2d CRadar::EightSprite;// = (CSprite2d*)0x8F2BCC; -CSprite2d CRadar::ElSprite;// = (CSprite2d*)0x8F1B80; -CSprite2d CRadar::IceSprite;// = (CSprite2d*)0x9415FC; -CSprite2d CRadar::JoeySprite;// = (CSprite2d*)0x8F2C00; -CSprite2d CRadar::KenjiSprite;// = (CSprite2d*)0x8F2C68; -CSprite2d CRadar::LizSprite;// = (CSprite2d*)0x8F5830; -CSprite2d CRadar::LuigiSprite;// = (CSprite2d*)0x8F1A3C; -CSprite2d CRadar::NorthSprite;// = (CSprite2d*)0x8F6274; -CSprite2d CRadar::RaySprite;// = (CSprite2d*)0x8E2A7C; -CSprite2d CRadar::SalSprite;// = (CSprite2d*)0x8F29EC; -CSprite2d CRadar::SaveSprite;// = (CSprite2d*)0x8F5F74; -CSprite2d CRadar::SpraySprite;// = (CSprite2d*)0x94307C; -CSprite2d CRadar::TonySprite;// = (CSprite2d*)0x885B58; -CSprite2d CRadar::WeaponSprite;// = (CSprite2d*)0x941534; +CSprite2d CRadar::AsukaSprite; +CSprite2d CRadar::BombSprite; +CSprite2d CRadar::CatSprite; +CSprite2d CRadar::CentreSprite; +CSprite2d CRadar::CopcarSprite; +CSprite2d CRadar::DonSprite; +CSprite2d CRadar::EightSprite; +CSprite2d CRadar::ElSprite; +CSprite2d CRadar::IceSprite; +CSprite2d CRadar::JoeySprite; +CSprite2d CRadar::KenjiSprite; +CSprite2d CRadar::LizSprite; +CSprite2d CRadar::LuigiSprite; +CSprite2d CRadar::NorthSprite; +CSprite2d CRadar::RaySprite; +CSprite2d CRadar::SalSprite; +CSprite2d CRadar::SaveSprite; +CSprite2d CRadar::SpraySprite; +CSprite2d CRadar::TonySprite; +CSprite2d CRadar::WeaponSprite; CSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = { nil, diff --git a/src/core/References.cpp b/src/core/References.cpp index e87f0fd5..668ea9f1 100644 --- a/src/core/References.cpp +++ b/src/core/References.cpp @@ -6,8 +6,8 @@ #include "Pools.h" #include "References.h" -CReference *CReferences::aRefs = (CReference*)0x70BBE0; //[NUMREFERENCES]; -CReference *&CReferences::pEmptyList = *(CReference**)0x8F1AF8; +CReference CReferences::aRefs[NUMREFERENCES]; +CReference *CReferences::pEmptyList; void CReferences::Init(void) diff --git a/src/core/References.h b/src/core/References.h index 6476e243..e7a64de7 100644 --- a/src/core/References.h +++ b/src/core/References.h @@ -11,8 +11,8 @@ struct CReference class CReferences { public: - static CReference *aRefs; //[NUMREFERENCES]; - static CReference *&pEmptyList; + static CReference aRefs[NUMREFERENCES]; + static CReference *pEmptyList; static void Init(void); static void RemoveReferencesToPlayer(void); diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index 02092a30..8d7a3048 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -4,59 +4,59 @@ #include "Text.h" #include "World.h" -int32 &CStats::DaysPassed = *(int32*)0x8F2BB8; -int32 &CStats::HeadsPopped = *(int32*)0x8F647C; -int32& CStats::CommercialPassed = *(int32*)0x8F4334; -int32& CStats::IndustrialPassed = *(int32*)0x8E2A68; -int32& CStats::SuburbanPassed = *(int32*)0x8F2740; -int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C; -int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50; -int32 &CStats::HelisDestroyed = *(int32*)0x8E2A64; -int32(&CStats::PedsKilledOfThisType)[NUM_PEDTYPES] = *(int32(*)[NUM_PEDTYPES]) * (uintptr*)0x880DBC; -int32 &CStats::TimesDied = *(int32*)0x8E2BDC; -int32 &CStats::TimesArrested = *(int32*)0x8E2BEC; -int32 &CStats::KillsSinceLastCheckpoint = *(int32*)0x8F2C8C; -int32& CStats::DistanceTravelledInVehicle = *(int32*)0x940574; -int32& CStats::DistanceTravelledOnFoot = *(int32*)0x941518; -int32 &CStats::ProgressMade = *(int32*)0x8F6224; -int32 &CStats::TotalProgressInGame = *(int32*)0x885B2C; -int32& CStats::CarsExploded = *(int32*)0x941288; -int32& CStats::PeopleKilledByPlayer = *(int32*)0x8F1B7C; -float &CStats::MaximumJumpDistance = *(float*)0x8F2BDC; -float &CStats::MaximumJumpHeight = *(float*)0x940564; -int32 &CStats::MaximumJumpFlips = *(int32*)0x8F2524; -int32 &CStats::MaximumJumpSpins = *(int32*)0x8F29B0; -int32 &CStats::BestStuntJump = *(int32*)0x885B50; -int32 &CStats::NumberOfUniqueJumpsFound = *(int32*)0x885B74; -int32 &CStats::TotalNumberOfUniqueJumps = *(int32*)0x8E2DC0; -int32 &CStats::PassengersDroppedOffWithTaxi = *(int32*)0x940724; -int32 &CStats::MoneyMadeWithTaxi = *(int32*)0x941544; -int32 &CStats::MissionsGiven = *(int32*)0x9430E8; -int32 &CStats::MissionsPassed = *(int32*)0x940768; -char(&CStats::LastMissionPassedName)[8] = *(char(*)[8])*(uintptr*)0x70D828; -int32 &CStats::TotalLegitimateKills = *(int32*)0x8F6004; -int32 &CStats::ElBurroTime = *(int32*)0x8E2A6C; -int32& CStats::Record4x4One = *(int32*)0x940570; -int32& CStats::Record4x4Two = *(int32*)0x94058C; -int32& CStats::Record4x4Three = *(int32*)0x880FA8; -int32& CStats::Record4x4Mayhem = *(int32*)0x885B70; -int32& CStats::LivesSavedWithAmbulance = *(int32*)0x8F57E0; -int32& CStats::CriminalsCaught = *(int32*)0x8F2518; -int32& CStats::HighestLevelAmbulanceMission = *(int32*)0x8F2A04; -int32& CStats::FiresExtinguished = *(int32*)0x8F5FEC; -int32& CStats::LongestFlightInDodo = *(int32*)0x8F5FE4; -int32& CStats::TimeTakenDefuseMission = *(int32*)0x880E24; -int32& CStats::TotalNumberKillFrenzies = *(int32*)0x8E2884; -int32& CStats::TotalNumberMissions = *(int32*)0x8E2820; -int32& CStats::RoundsFiredByPlayer = *(int32*)0x8E2BE8; -int32& CStats::KgsOfExplosivesUsed = *(int32*)0x8F2510; -int32& CStats::InstantHitsFiredByPlayer = *(int32*)0x943070; -int32& CStats::InstantHitsHitByPlayer = *(int32*)0x95CB8C; -int32& CStats::BestTimeBombDefusal = *(int32*)0x880E24; -int32& CStats::mmRain = *(int32*)0x8F2C98; -int32& CStats::CarsCrushed = *(int32*)0x943050; -int32(&CStats::FastestTimes)[CStats::TOTAL_FASTEST_TIMES] = *(int32(*)[CStats::TOTAL_FASTEST_TIMES])*(uintptr*)0x6E9128; -int32(&CStats::HighestScores)[CStats::TOTAL_HIGHEST_SCORES] = *(int32(*)[CStats::TOTAL_HIGHEST_SCORES]) * (uintptr*)0x8622B0; +int32 CStats::DaysPassed; +int32 CStats::HeadsPopped; +int32 CStats::CommercialPassed; +int32 CStats::IndustrialPassed; +int32 CStats::SuburbanPassed; +int32 CStats::NumberKillFrenziesPassed; +int32 CStats::PeopleKilledByOthers; +int32 CStats::HelisDestroyed; +int32 CStats::PedsKilledOfThisType[NUM_PEDTYPES]; +int32 CStats::TimesDied; +int32 CStats::TimesArrested; +int32 CStats::KillsSinceLastCheckpoint; +int32 CStats::DistanceTravelledInVehicle; +int32 CStats::DistanceTravelledOnFoot; +int32 CStats::ProgressMade; +int32 CStats::TotalProgressInGame; +int32 CStats::CarsExploded; +int32 CStats::PeopleKilledByPlayer; +float CStats::MaximumJumpDistance; +float CStats::MaximumJumpHeight; +int32 CStats::MaximumJumpFlips; +int32 CStats::MaximumJumpSpins; +int32 CStats::BestStuntJump; +int32 CStats::NumberOfUniqueJumpsFound; +int32 CStats::TotalNumberOfUniqueJumps; +int32 CStats::PassengersDroppedOffWithTaxi; +int32 CStats::MoneyMadeWithTaxi; +int32 CStats::MissionsGiven; +int32 CStats::MissionsPassed; +char CStats::LastMissionPassedName[8]; +int32 CStats::TotalLegitimateKills; +int32 CStats::ElBurroTime; +int32 CStats::Record4x4One; +int32 CStats::Record4x4Two; +int32 CStats::Record4x4Three; +int32 CStats::Record4x4Mayhem; +int32 CStats::LivesSavedWithAmbulance; +int32 CStats::CriminalsCaught; +int32 CStats::HighestLevelAmbulanceMission; +int32 CStats::FiresExtinguished; +int32 CStats::LongestFlightInDodo; +int32 CStats::TimeTakenDefuseMission; +int32 CStats::TotalNumberKillFrenzies; +int32 CStats::TotalNumberMissions; +int32 CStats::RoundsFiredByPlayer; +int32 CStats::KgsOfExplosivesUsed; +int32 CStats::InstantHitsFiredByPlayer; +int32 CStats::InstantHitsHitByPlayer; +int32 CStats::BestTimeBombDefusal; +int32 CStats::mmRain; +int32 CStats::CarsCrushed; +int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES]; +int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES]; void CStats::Init() { diff --git a/src/core/Stats.h b/src/core/Stats.h index ac3259f9..4445ecf4 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -9,59 +9,59 @@ public: TOTAL_FASTEST_TIMES = 16, TOTAL_HIGHEST_SCORES = 16 }; - static int32 &DaysPassed; - static int32 &HeadsPopped; - static int32& CommercialPassed; - static int32& IndustrialPassed; - static int32& SuburbanPassed; - static int32 &NumberKillFrenziesPassed; - static int32 &PeopleKilledByOthers; - static int32 &HelisDestroyed; - static int32(&PedsKilledOfThisType)[ePedType::NUM_PEDTYPES]; - static int32 &TimesDied; - static int32 &TimesArrested; - static int32 &KillsSinceLastCheckpoint; - static int32 &DistanceTravelledInVehicle; - static int32 &DistanceTravelledOnFoot; - static int32 &CarsExploded; - static int32 &PeopleKilledByPlayer; - static int32 &ProgressMade; - static int32 &TotalProgressInGame; - static float &MaximumJumpDistance; - static float &MaximumJumpHeight; - static int32 &MaximumJumpFlips; - static int32 &MaximumJumpSpins; - static int32 &BestStuntJump; - static int32 &NumberOfUniqueJumpsFound; - static int32 &TotalNumberOfUniqueJumps; - static int32 &PassengersDroppedOffWithTaxi; - static int32 &MoneyMadeWithTaxi; - static int32 &MissionsGiven; - static int32 &MissionsPassed; - static char (&LastMissionPassedName)[8]; - static int32 &TotalLegitimateKills; - static int32 &ElBurroTime; - static int32 &Record4x4One; - static int32 &Record4x4Two; - static int32 &Record4x4Three; - static int32 &Record4x4Mayhem; - static int32 &LivesSavedWithAmbulance; - static int32 &CriminalsCaught; - static int32 &HighestLevelAmbulanceMission; - static int32 &FiresExtinguished; - static int32 &LongestFlightInDodo; - static int32 &TimeTakenDefuseMission; - static int32 &TotalNumberKillFrenzies; - static int32 &TotalNumberMissions; - static int32 &RoundsFiredByPlayer; - static int32 &KgsOfExplosivesUsed; - static int32 &InstantHitsFiredByPlayer; - static int32 &InstantHitsHitByPlayer; - static int32 &BestTimeBombDefusal; - static int32 &mmRain; - static int32 &CarsCrushed; - static int32(&FastestTimes)[TOTAL_FASTEST_TIMES]; - static int32(&HighestScores)[TOTAL_HIGHEST_SCORES]; + static int32 DaysPassed; + static int32 HeadsPopped; + static int32 CommercialPassed; + static int32 IndustrialPassed; + static int32 SuburbanPassed; + static int32 NumberKillFrenziesPassed; + static int32 PeopleKilledByOthers; + static int32 HelisDestroyed; + static int32 PedsKilledOfThisType[ePedType::NUM_PEDTYPES]; + static int32 TimesDied; + static int32 TimesArrested; + static int32 KillsSinceLastCheckpoint; + static int32 DistanceTravelledInVehicle; + static int32 DistanceTravelledOnFoot; + static int32 CarsExploded; + static int32 PeopleKilledByPlayer; + static int32 ProgressMade; + static int32 TotalProgressInGame; + static float MaximumJumpDistance; + static float MaximumJumpHeight; + static int32 MaximumJumpFlips; + static int32 MaximumJumpSpins; + static int32 BestStuntJump; + static int32 NumberOfUniqueJumpsFound; + static int32 TotalNumberOfUniqueJumps; + static int32 PassengersDroppedOffWithTaxi; + static int32 MoneyMadeWithTaxi; + static int32 MissionsGiven; + static int32 MissionsPassed; + static char LastMissionPassedName[8]; + static int32 TotalLegitimateKills; + static int32 ElBurroTime; + static int32 Record4x4One; + static int32 Record4x4Two; + static int32 Record4x4Three; + static int32 Record4x4Mayhem; + static int32 LivesSavedWithAmbulance; + static int32 CriminalsCaught; + static int32 HighestLevelAmbulanceMission; + static int32 FiresExtinguished; + static int32 LongestFlightInDodo; + static int32 TimeTakenDefuseMission; + static int32 TotalNumberKillFrenzies; + static int32 TotalNumberMissions; + static int32 RoundsFiredByPlayer; + static int32 KgsOfExplosivesUsed; + static int32 InstantHitsFiredByPlayer; + static int32 InstantHitsHitByPlayer; + static int32 BestTimeBombDefusal; + static int32 mmRain; + static int32 CarsCrushed; + static int32 FastestTimes[TOTAL_FASTEST_TIMES]; + static int32 HighestScores[TOTAL_HIGHEST_SCORES]; public: static void Init(void); diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index d00edf51..56f4a862 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -30,49 +30,49 @@ #include "Streaming.h" #include "main.h" -bool &CStreaming::ms_disableStreaming = *(bool*)0x95CD6E; -bool &CStreaming::ms_bLoadingBigModel = *(bool*)0x95CDB0; -int32 &CStreaming::ms_numModelsRequested = *(int32*)0x8E2C10; -CStreamingInfo *CStreaming::ms_aInfoForModel = (CStreamingInfo*)0x6C7088; -CStreamingInfo &CStreaming::ms_startLoadedList = *(CStreamingInfo*)0x942F60; -CStreamingInfo &CStreaming::ms_endLoadedList = *(CStreamingInfo*)0x8F1AC0; -CStreamingInfo &CStreaming::ms_startRequestedList = *(CStreamingInfo*)0x8F1B3C; -CStreamingInfo &CStreaming::ms_endRequestedList = *(CStreamingInfo*)0x940738; -int32 &CStreaming::ms_oldSectorX = *(int32*)0x8F2C84; -int32 &CStreaming::ms_oldSectorY = *(int32*)0x8F2C88; -int32 &CStreaming::ms_streamingBufferSize = *(int32*)0x942FB0; -int8 **CStreaming::ms_pStreamingBuffer = (int8**)0x87F818; -int32 &CStreaming::ms_memoryUsed = *(int32*)0x940568; -CStreamingChannel *CStreaming::ms_channel = (CStreamingChannel*)0x727EE0; -int32 &CStreaming::ms_channelError = *(int32*)0x880DB8; -int32 &CStreaming::ms_numVehiclesLoaded = *(int32*)0x8F2C80; -int32 *CStreaming::ms_vehiclesLoaded = (int32*)0x773560; -int32 &CStreaming::ms_lastVehicleDeleted = *(int32*)0x95CBF8; -CDirectory *&CStreaming::ms_pExtraObjectsDir = *(CDirectory**)0x95CB90; -int32 &CStreaming::ms_numPriorityRequests = *(int32*)0x8F31C4; -bool &CStreaming::ms_hasLoadedLODs = *(bool*)0x95CD47; -int32 &CStreaming::ms_currentPedGrp = *(int32*)0x8F2BBC; +bool CStreaming::ms_disableStreaming; +bool CStreaming::ms_bLoadingBigModel; +int32 CStreaming::ms_numModelsRequested; +CStreamingInfo CStreaming::ms_aInfoForModel[NUMSTREAMINFO]; +CStreamingInfo CStreaming::ms_startLoadedList; +CStreamingInfo CStreaming::ms_endLoadedList; +CStreamingInfo CStreaming::ms_startRequestedList; +CStreamingInfo CStreaming::ms_endRequestedList; +int32 CStreaming::ms_oldSectorX; +int32 CStreaming::ms_oldSectorY; +int32 CStreaming::ms_streamingBufferSize; +int8 *CStreaming::ms_pStreamingBuffer[2]; +int32 CStreaming::ms_memoryUsed; +CStreamingChannel CStreaming::ms_channel[2]; +int32 CStreaming::ms_channelError; +int32 CStreaming::ms_numVehiclesLoaded; +int32 CStreaming::ms_vehiclesLoaded[MAXVEHICLESLOADED]; +int32 CStreaming::ms_lastVehicleDeleted; +CDirectory *CStreaming::ms_pExtraObjectsDir; +int32 CStreaming::ms_numPriorityRequests; +bool CStreaming::ms_hasLoadedLODs; +int32 CStreaming::ms_currentPedGrp; int32 CStreaming::ms_currentPedLoading; int32 CStreaming::ms_lastCullZone; -uint16 &CStreaming::ms_loadedGangs = *(uint16*)0x95CC60; -uint16 &CStreaming::ms_loadedGangCars = *(uint16*)0x95CC2E; -int32 *CStreaming::ms_imageOffsets = (int32*)0x6E60A0; -int32 &CStreaming::ms_lastImageRead = *(int32*)0x880E2C; -int32 &CStreaming::ms_imageSize = *(int32*)0x8F1A34; -uint32 &CStreaming::ms_memoryAvailable = *(uint32*)0x880F8C; +uint16 CStreaming::ms_loadedGangs; +uint16 CStreaming::ms_loadedGangCars; +int32 CStreaming::ms_imageOffsets[NUMCDIMAGES]; +int32 CStreaming::ms_lastImageRead; +int32 CStreaming::ms_imageSize; +uint32 CStreaming::ms_memoryAvailable; -int32 &desiredNumVehiclesLoaded = *(int32*)0x5EC194; +int32 desiredNumVehiclesLoaded = 12; -CEntity *&pIslandLODindustEntity = *(CEntity**)0x6212DC; -CEntity *&pIslandLODcomIndEntity = *(CEntity**)0x6212E0; -CEntity *&pIslandLODcomSubEntity = *(CEntity**)0x6212E4; -CEntity *&pIslandLODsubIndEntity = *(CEntity**)0x6212E8; -CEntity *&pIslandLODsubComEntity = *(CEntity**)0x6212EC; -int32 &islandLODindust = *(int32*)0x6212C8; -int32 &islandLODcomInd = *(int32*)0x6212CC; -int32 &islandLODcomSub = *(int32*)0x6212D0; -int32 &islandLODsubInd = *(int32*)0x6212D4; -int32 &islandLODsubCom = *(int32*)0x6212D8; +CEntity *pIslandLODindustEntity; +CEntity *pIslandLODcomIndEntity; +CEntity *pIslandLODcomSubEntity; +CEntity *pIslandLODsubIndEntity; +CEntity *pIslandLODsubComEntity; +int32 islandLODindust; +int32 islandLODcomInd; +int32 islandLODcomSub; +int32 islandLODsubInd; +int32 islandLODsubCom; bool CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size) @@ -199,7 +199,7 @@ CStreaming::Init(void) // PC only, figure out how much memory we got #ifdef GTA_PC #define MB (1024*1024) - extern unsigned long &_dwMemAvailPhys; + extern unsigned long _dwMemAvailPhys; ms_memoryAvailable = (_dwMemAvailPhys - 10*MB)/2; if(ms_memoryAvailable < 50*MB) ms_memoryAvailable = 50*MB; diff --git a/src/core/Streaming.h b/src/core/Streaming.h index 1100fd1b..c910c068 100644 --- a/src/core/Streaming.h +++ b/src/core/Streaming.h @@ -77,36 +77,36 @@ class CPtrList; class CStreaming { public: - static bool &ms_disableStreaming; - static bool &ms_bLoadingBigModel; - static int32 &ms_numModelsRequested; - static CStreamingInfo *ms_aInfoForModel; //[NUMSTREAMINFO] - static CStreamingInfo &ms_startLoadedList; - static CStreamingInfo &ms_endLoadedList; - static CStreamingInfo &ms_startRequestedList; - static CStreamingInfo &ms_endRequestedList; - static int32 &ms_oldSectorX; - static int32 &ms_oldSectorY; - static int32 &ms_streamingBufferSize; - static int8 **ms_pStreamingBuffer; //[2] - static int32 &ms_memoryUsed; - static CStreamingChannel *ms_channel; //[2] - static int32 &ms_channelError; - static int32 &ms_numVehiclesLoaded; - static int32 *ms_vehiclesLoaded; //[MAXVEHICLESLOADED] - static int32 &ms_lastVehicleDeleted; - static CDirectory *&ms_pExtraObjectsDir; - static int32 &ms_numPriorityRequests; - static bool &ms_hasLoadedLODs; - static int32 &ms_currentPedGrp; + static bool ms_disableStreaming; + static bool ms_bLoadingBigModel; + static int32 ms_numModelsRequested; + static CStreamingInfo ms_aInfoForModel[NUMSTREAMINFO]; + static CStreamingInfo ms_startLoadedList; + static CStreamingInfo ms_endLoadedList; + static CStreamingInfo ms_startRequestedList; + static CStreamingInfo ms_endRequestedList; + static int32 ms_oldSectorX; + static int32 ms_oldSectorY; + static int32 ms_streamingBufferSize; + static int8 *ms_pStreamingBuffer[2]; + static int32 ms_memoryUsed; + static CStreamingChannel ms_channel[2]; + static int32 ms_channelError; + static int32 ms_numVehiclesLoaded; + static int32 ms_vehiclesLoaded[MAXVEHICLESLOADED]; + static int32 ms_lastVehicleDeleted; + static CDirectory *ms_pExtraObjectsDir; + static int32 ms_numPriorityRequests; + static bool ms_hasLoadedLODs; + static int32 ms_currentPedGrp; static int32 ms_lastCullZone; - static uint16 &ms_loadedGangs; - static uint16 &ms_loadedGangCars; + static uint16 ms_loadedGangs; + static uint16 ms_loadedGangCars; static int32 ms_currentPedLoading; - static int32 *ms_imageOffsets; //[NUMCDIMAGES] - static int32 &ms_lastImageRead; - static int32 &ms_imageSize; - static uint32 &ms_memoryAvailable; + static int32 ms_imageOffsets[NUMCDIMAGES]; + static int32 ms_lastImageRead; + static int32 ms_imageSize; + static uint32 ms_memoryAvailable; static void Init(void); static void Shutdown(void); diff --git a/src/core/SurfaceTable.cpp b/src/core/SurfaceTable.cpp index 2ba884b1..85572fbd 100644 --- a/src/core/SurfaceTable.cpp +++ b/src/core/SurfaceTable.cpp @@ -6,7 +6,7 @@ #include "Collision.h" #include "SurfaceTable.h" -float (*CSurfaceTable::ms_aAdhesiveLimitTable)[NUMADHESIVEGROUPS] = (float (*)[NUMADHESIVEGROUPS])0x8E29D4; +float CSurfaceTable::ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS]; void CSurfaceTable::Initialise(char *filename) diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h index 27f4ecca..4af6a265 100644 --- a/src/core/SurfaceTable.h +++ b/src/core/SurfaceTable.h @@ -98,8 +98,7 @@ struct CColPoint; class CSurfaceTable { -// static float ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS]; - static float (*ms_aAdhesiveLimitTable)[NUMADHESIVEGROUPS]; + static float ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS]; public: static void Initialise(char *filename); static int GetAdhesionGroup(uint8 surfaceType); diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index 22ef31bd..05b272ab 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -3,19 +3,19 @@ #include "TempColModels.h" #include "SurfaceTable.h" -CColModel &CTempColModels::ms_colModelPed1 = *(CColModel*)0x726CB0; -CColModel &CTempColModels::ms_colModelPed2 = *(CColModel*)0x726D08; -CColModel &CTempColModels::ms_colModelBBox = *(CColModel*)0x727FE0; -CColModel &CTempColModels::ms_colModelBumper1 = *(CColModel*)0x86BE88; -CColModel &CTempColModels::ms_colModelWheel1 = *(CColModel*)0x878C40; -CColModel &CTempColModels::ms_colModelPanel1 = *(CColModel*)0x87BDD8; -CColModel &CTempColModels::ms_colModelBodyPart2 = *(CColModel*)0x87BE30; -CColModel &CTempColModels::ms_colModelBodyPart1 = *(CColModel*)0x87BE88; -CColModel (&CTempColModels::ms_colModelCutObj)[5] = *(CColModel(*)[5]) *(uintptr*)0x87C960; -CColModel &CTempColModels::ms_colModelPedGroundHit = *(CColModel*)0x880480; -CColModel &CTempColModels::ms_colModelBoot1 = *(CColModel*)0x880670; -CColModel &CTempColModels::ms_colModelDoor1 = *(CColModel*)0x880850; -CColModel &CTempColModels::ms_colModelBonnet1 = *(CColModel*)0x8808A8; +CColModel CTempColModels::ms_colModelPed1; +CColModel CTempColModels::ms_colModelPed2; +CColModel CTempColModels::ms_colModelBBox; +CColModel CTempColModels::ms_colModelBumper1; +CColModel CTempColModels::ms_colModelWheel1; +CColModel CTempColModels::ms_colModelPanel1; +CColModel CTempColModels::ms_colModelBodyPart2; +CColModel CTempColModels::ms_colModelBodyPart1; +CColModel CTempColModels::ms_colModelCutObj[5]; +CColModel CTempColModels::ms_colModelPedGroundHit; +CColModel CTempColModels::ms_colModelBoot1; +CColModel CTempColModels::ms_colModelDoor1; +CColModel CTempColModels::ms_colModelBonnet1; CColSphere s_aPedSpheres[3]; diff --git a/src/core/TempColModels.h b/src/core/TempColModels.h index 263904d3..3e1dd5e1 100644 --- a/src/core/TempColModels.h +++ b/src/core/TempColModels.h @@ -5,19 +5,19 @@ class CTempColModels { public: - static CColModel &ms_colModelPed1; - static CColModel &ms_colModelPed2; - static CColModel &ms_colModelBBox; - static CColModel &ms_colModelBumper1; - static CColModel &ms_colModelWheel1; - static CColModel &ms_colModelPanel1; - static CColModel &ms_colModelBodyPart2; - static CColModel &ms_colModelBodyPart1; - static CColModel (&ms_colModelCutObj)[5]; - static CColModel &ms_colModelPedGroundHit; - static CColModel &ms_colModelBoot1; - static CColModel &ms_colModelDoor1; - static CColModel &ms_colModelBonnet1; + static CColModel ms_colModelPed1; + static CColModel ms_colModelPed2; + static CColModel ms_colModelBBox; + static CColModel ms_colModelBumper1; + static CColModel ms_colModelWheel1; + static CColModel ms_colModelPanel1; + static CColModel ms_colModelBodyPart2; + static CColModel ms_colModelBodyPart1; + static CColModel ms_colModelCutObj[5]; + static CColModel ms_colModelPedGroundHit; + static CColModel ms_colModelBoot1; + static CColModel ms_colModelDoor1; + static CColModel ms_colModelBonnet1; static void Initialise(void); }; diff --git a/src/core/TimeStep.cpp b/src/core/TimeStep.cpp index 9ccf7200..09dae911 100644 --- a/src/core/TimeStep.cpp +++ b/src/core/TimeStep.cpp @@ -1,5 +1,5 @@ #include "TimeStep.h" -float &CTimeStep::ms_fTimeScale = *(float*)0x5F76C8; -float &CTimeStep::ms_fFramesPerUpdate = *(float*)0x5F76CC; -float &CTimeStep::ms_fTimeStep = *(float*)0x5F76D0; +float CTimeStep::ms_fTimeScale = 1.0f; +float CTimeStep::ms_fFramesPerUpdate = 1.0f; +float CTimeStep::ms_fTimeStep = 1.0f; diff --git a/src/core/TimeStep.h b/src/core/TimeStep.h index c74df02a..6101b4c2 100644 --- a/src/core/TimeStep.h +++ b/src/core/TimeStep.h @@ -4,7 +4,7 @@ class CTimeStep { public: - static float &ms_fTimeScale; - static float &ms_fFramesPerUpdate; - static float &ms_fTimeStep; + static float ms_fTimeScale; + static float ms_fFramesPerUpdate; + static float ms_fTimeStep; }; diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index fda862f1..68b31e6f 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -5,34 +5,28 @@ #include "Record.h" #include "Timer.h" -uint32 &CTimer::m_snTimeInMilliseconds = *(uint32*)0x885B48; -uint32 &CTimer::m_snTimeInMillisecondsPauseMode = *(uint32*)0x5F7614; -uint32 &CTimer::m_snTimeInMillisecondsNonClipped = *(uint32*)0x9412E8; -uint32 &CTimer::m_snPreviousTimeInMilliseconds = *(uint32*)0x8F29E4; -uint32 &CTimer::m_FrameCounter = *(uint32*)0x9412EC; -float &CTimer::ms_fTimeScale = *(float*)0x8F2C20; -float &CTimer::ms_fTimeStep = *(float*)0x8E2CB4; -float &CTimer::ms_fTimeStepNonClipped = *(float*)0x8E2C4C; -bool &CTimer::m_UserPause = *(bool*)0x95CD7C; -bool &CTimer::m_CodePause = *(bool*)0x95CDB1; +uint32 CTimer::m_snTimeInMilliseconds; +uint32 CTimer::m_snTimeInMillisecondsPauseMode = 1; +uint32 CTimer::m_snTimeInMillisecondsNonClipped; +uint32 CTimer::m_snPreviousTimeInMilliseconds; +uint32 CTimer::m_FrameCounter; +float CTimer::ms_fTimeScale; +float CTimer::ms_fTimeStep; +float CTimer::ms_fTimeStepNonClipped; +bool CTimer::m_UserPause; +bool CTimer::m_CodePause; -//UInt32 oldPcTimer; -uint32 &oldPcTimer = *(uint32*)0x9434F4; +uint32 oldPcTimer; -//UInt32 suspendPcTimer; -uint32 &suspendPcTimer = *(uint32*)0x62A308; +uint32 suspendPcTimer; -//UInt32 _nCyclesPerMS = 1; -uint32 &_nCyclesPerMS = *(uint32*)0x5F7610; +uint32 _nCyclesPerMS = 1; -//LARGE_INTEGER _oldPerfCounter; -LARGE_INTEGER &_oldPerfCounter = *(LARGE_INTEGER*)0x62A310; +LARGE_INTEGER _oldPerfCounter; -//LARGE_INTEGER perfSuspendCounter; -LARGE_INTEGER &perfSuspendCounter = *(LARGE_INTEGER*)0x62A318; +LARGE_INTEGER perfSuspendCounter; -//UInt32 suspendDepth; -uint32 &suspendDepth = *(uint32*)0x62A320; +uint32 suspendDepth; #ifdef FIX_BUGS double frameTime; diff --git a/src/core/Timer.h b/src/core/Timer.h index a4d674da..00a11409 100644 --- a/src/core/Timer.h +++ b/src/core/Timer.h @@ -3,17 +3,17 @@ class CTimer { - static uint32 &m_snTimeInMilliseconds; - static uint32 &m_snTimeInMillisecondsPauseMode; - static uint32 &m_snTimeInMillisecondsNonClipped; - static uint32 &m_snPreviousTimeInMilliseconds; - static uint32 &m_FrameCounter; - static float &ms_fTimeScale; - static float &ms_fTimeStep; - static float &ms_fTimeStepNonClipped; + static uint32 m_snTimeInMilliseconds; + static uint32 m_snTimeInMillisecondsPauseMode; + static uint32 m_snTimeInMillisecondsNonClipped; + static uint32 m_snPreviousTimeInMilliseconds; + static uint32 m_FrameCounter; + static float ms_fTimeScale; + static float ms_fTimeStep; + static float ms_fTimeStepNonClipped; public: - static bool &m_UserPause; - static bool &m_CodePause; + static bool m_UserPause; + static bool m_CodePause; static const float &GetTimeStep(void) { return ms_fTimeStep; } static void SetTimeStep(float ts) { ms_fTimeStep = ts; } diff --git a/src/core/User.cpp b/src/core/User.cpp index d89d1cec..a1a69b2d 100644 --- a/src/core/User.cpp +++ b/src/core/User.cpp @@ -9,10 +9,10 @@ #include "World.h" #include "Zones.h" -CPlaceName& CUserDisplay::PlaceName = *(CPlaceName*)0x8F29BC; -COnscreenTimer& CUserDisplay::OnscnTimer = *(COnscreenTimer*)0x862238; -CPager& CUserDisplay::Pager = *(CPager*)0x8F2744; -CCurrentVehicle& CUserDisplay::CurrentVehicle = *(CCurrentVehicle*)0x8F5FE8; +CPlaceName CUserDisplay::PlaceName; +COnscreenTimer CUserDisplay::OnscnTimer; +CPager CUserDisplay::Pager; +CCurrentVehicle CUserDisplay::CurrentVehicle; CPlaceName::CPlaceName() { diff --git a/src/core/User.h b/src/core/User.h index 02d5f613..153ef57b 100644 --- a/src/core/User.h +++ b/src/core/User.h @@ -31,10 +31,10 @@ public: class CUserDisplay { public: - static CPlaceName &PlaceName; - static COnscreenTimer &OnscnTimer; - static CPager &Pager; - static CCurrentVehicle &CurrentVehicle; + static CPlaceName PlaceName; + static COnscreenTimer OnscnTimer; + static CPager Pager; + static CCurrentVehicle CurrentVehicle; static void Init(); static void Process(); diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp index 29294a2b..1911ae59 100644 --- a/src/core/Wanted.cpp +++ b/src/core/Wanted.cpp @@ -11,8 +11,8 @@ #include "Wanted.h" #include "General.h" -int32 &CWanted::MaximumWantedLevel = *(int32*)0x5F7714; // 6 -int32 &CWanted::nMaximumWantedLevel = *(int32*)0x5F7718; // 6400 +int32 CWanted::MaximumWantedLevel = 6; +int32 CWanted::nMaximumWantedLevel = 6400; void CWanted::Initialise() diff --git a/src/core/Wanted.h b/src/core/Wanted.h index 9823529c..afeec8b0 100644 --- a/src/core/Wanted.h +++ b/src/core/Wanted.h @@ -60,8 +60,8 @@ public: CCrimeBeingQd m_aCrimes[16]; CCopPed *m_pCops[10]; - static int32 &MaximumWantedLevel; - static int32 &nMaximumWantedLevel; + static int32 MaximumWantedLevel; + static int32 nMaximumWantedLevel; public: void Initialise(); diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp index 4a2bea4f..4cdd283e 100644 --- a/src/core/ZoneCull.cpp +++ b/src/core/ZoneCull.cpp @@ -11,21 +11,21 @@ #include "ZoneCull.h" #include "Zones.h" -int32 &CCullZones::NumCullZones = *(int*)0x8F2564; -CCullZone(&CCullZones::aZones)[NUMCULLZONES] = *(CCullZone(*)[NUMCULLZONES])*(uintptr*)0x864750; -int32 &CCullZones::NumAttributeZones = *(int*)0x8E29D0; -CAttributeZone (&CCullZones::aAttributeZones)[NUMATTRIBZONES] = *(CAttributeZone(*)[NUMATTRIBZONES])*(uintptr*)0x709C60; -uint16 (&CCullZones::aIndices)[NUMZONEINDICES] = *(uint16(*)[NUMZONEINDICES])*(uintptr*)0x847330; -int16 (&CCullZones::aPointersToBigBuildingsForBuildings)[NUMBUILDINGS] = *(int16(*)[NUMBUILDINGS])*(uintptr*)0x86C9D0; -int16 (&CCullZones::aPointersToBigBuildingsForTreadables)[NUMTREADABLES] = *(int16(*)[NUMTREADABLES])*(uintptr*)0x8F1B8C; +int32 CCullZones::NumCullZones; +CCullZone CCullZones::aZones[NUMCULLZONES]; +int32 CCullZones::NumAttributeZones; +CAttributeZone CCullZones::aAttributeZones[NUMATTRIBZONES]; +uint16 CCullZones::aIndices[NUMZONEINDICES]; +int16 CCullZones::aPointersToBigBuildingsForBuildings[NUMBUILDINGS]; +int16 CCullZones::aPointersToBigBuildingsForTreadables[NUMTREADABLES]; -int32 &CCullZones::CurrentWantedLevelDrop_Player = *(int32*)0x880DA8; -int32 &CCullZones::CurrentFlags_Camera = *(int32*)0x940718; -int32 &CCullZones::CurrentFlags_Player = *(int32*)0x9415F0; -int32 &CCullZones::OldCullZone = *(int32*)0x8E2C90; -int32 &CCullZones::EntityIndicesUsed = *(int32*)0x8F2508; -bool &CCullZones::bCurrentSubwayIsInvisible = *(bool*)0x95CDA5; -bool &CCullZones::bCullZonesDisabled = *(bool*)0x95CD4A; +int32 CCullZones::CurrentWantedLevelDrop_Player; +int32 CCullZones::CurrentFlags_Camera; +int32 CCullZones::CurrentFlags_Player; +int32 CCullZones::OldCullZone; +int32 CCullZones::EntityIndicesUsed; +bool CCullZones::bCurrentSubwayIsInvisible; +bool CCullZones::bCullZonesDisabled; void diff --git a/src/core/ZoneCull.h b/src/core/ZoneCull.h index edaa7c4b..9bc07b8c 100644 --- a/src/core/ZoneCull.h +++ b/src/core/ZoneCull.h @@ -79,21 +79,21 @@ struct CAttributeZone class CCullZones { public: - static int32 &NumCullZones; - static CCullZone (&aZones)[NUMCULLZONES]; - static int32 &NumAttributeZones; - static CAttributeZone(&aAttributeZones)[NUMATTRIBZONES]; - static uint16 (&aIndices)[NUMZONEINDICES]; - static int16 (&aPointersToBigBuildingsForBuildings)[NUMBUILDINGS]; - static int16 (&aPointersToBigBuildingsForTreadables)[NUMTREADABLES]; + static int32 NumCullZones; + static CCullZone aZones[NUMCULLZONES]; + static int32 NumAttributeZones; + static CAttributeZone aAttributeZones[NUMATTRIBZONES]; + static uint16 aIndices[NUMZONEINDICES]; + static int16 aPointersToBigBuildingsForBuildings[NUMBUILDINGS]; + static int16 aPointersToBigBuildingsForTreadables[NUMTREADABLES]; - static int32 &CurrentWantedLevelDrop_Player; - static int32 &CurrentFlags_Camera; - static int32 &CurrentFlags_Player; - static int32 &OldCullZone; - static int32 &EntityIndicesUsed; - static bool &bCurrentSubwayIsInvisible; - static bool &bCullZonesDisabled; + static int32 CurrentWantedLevelDrop_Player; + static int32 CurrentFlags_Camera; + static int32 CurrentFlags_Player; + static int32 OldCullZone; + static int32 EntityIndicesUsed; + static bool bCurrentSubwayIsInvisible; + static bool bCullZonesDisabled; static void Init(void); static void ResolveVisibilities(void); diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 4bce3e79..39d4c3b5 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -8,18 +8,18 @@ #include "Text.h" #include "World.h" -eLevelName &CTheZones::m_CurrLevel = *(eLevelName*)0x8F2BC8; -CZone *&CTheZones::m_pPlayersZone = *(CZone**)0x8F254C; -int16 &CTheZones::FindIndex = *(int16*)0x95CC40; +eLevelName CTheZones::m_CurrLevel; +CZone *CTheZones::m_pPlayersZone; +int16 CTheZones::FindIndex; -uint16 &CTheZones::NumberOfAudioZones = *(uint16*)0x95CC84; -int16 *CTheZones::AudioZoneArray = (int16*)0x713BC0; -uint16 &CTheZones::TotalNumberOfMapZones = *(uint16*)0x95CC74; -uint16 &CTheZones::TotalNumberOfZones = *(uint16*)0x95CC36; -CZone *CTheZones::ZoneArray = (CZone*)0x86BEE0; -CZone *CTheZones::MapZoneArray = (CZone*)0x663EC0; -uint16 &CTheZones::TotalNumberOfZoneInfos = *(uint16*)0x95CC3C; -CZoneInfo *CTheZones::ZoneInfoArray = (CZoneInfo*)0x714400; +uint16 CTheZones::NumberOfAudioZones; +int16 CTheZones::AudioZoneArray[NUMAUDIOZONES]; +uint16 CTheZones::TotalNumberOfMapZones; +uint16 CTheZones::TotalNumberOfZones; +CZone CTheZones::ZoneArray[NUMZONES]; +CZone CTheZones::MapZoneArray[NUMMAPZONES]; +uint16 CTheZones::TotalNumberOfZoneInfos; +CZoneInfo CTheZones::ZoneInfoArray[2*NUMZONES]; #define SWAPF(a, b) { float t; t = a; a = b; b = t; } diff --git a/src/core/Zones.h b/src/core/Zones.h index 76855e8b..bb1585dc 100644 --- a/src/core/Zones.h +++ b/src/core/Zones.h @@ -52,18 +52,18 @@ public: class CTheZones { public: - static eLevelName &m_CurrLevel; - static CZone *&m_pPlayersZone; - static int16 &FindIndex; + static eLevelName m_CurrLevel; + static CZone *m_pPlayersZone; + static int16 FindIndex; - static uint16 &NumberOfAudioZones; - static int16 *AudioZoneArray; //[NUMAUDIOZONES]; - static uint16 &TotalNumberOfMapZones; - static uint16 &TotalNumberOfZones; - static CZone *ZoneArray; //[NUMZONES]; - static CZone *MapZoneArray; //[NUMMAPZONES]; - static uint16 &TotalNumberOfZoneInfos; - static CZoneInfo *ZoneInfoArray; //[2*NUMZONES]; + static uint16 NumberOfAudioZones; + static int16 AudioZoneArray[NUMAUDIOZONES]; + static uint16 TotalNumberOfMapZones; + static uint16 TotalNumberOfZones; + static CZone ZoneArray[NUMZONES]; + static CZone MapZoneArray[NUMMAPZONES]; + static uint16 TotalNumberOfZoneInfos; + static CZoneInfo ZoneInfoArray[2*NUMZONES]; static void Init(void); static void Update(void); diff --git a/src/core/config.h b/src/core/config.h index f9edb74a..ba684092 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -192,6 +192,7 @@ enum Config { #define MORE_LANGUAGES // Add more translations to the game #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) //#define USE_TXD_CDIMAGE // generate and load textures from txd.img +//#define USE_TEXTURE_POOL // Pad #define XINPUT diff --git a/src/core/main.cpp b/src/core/main.cpp index 08463df9..1b46d453 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -60,23 +60,18 @@ #include "GenericGameStorage.h" #include "SceneEdit.h" -GlobalScene &Scene = *(GlobalScene*)0x726768; +GlobalScene Scene; uint8 work_buff[55000]; -//char gString[256]; -//char gString2[512]; -//wchar gUString[256]; -//wchar gUString2[256]; -char *gString = (char*)0x711B40; -char *gString2 = (char*)0x878A40; -wchar *gUString = (wchar*)0x74B018; -wchar *gUString2 = (wchar*)0x6EDD70; - +char gString[256]; +char gString2[512]; +wchar gUString[256]; +wchar gUString2[256]; float FramesPerSecond = 30.0f; bool gbPrintShite = false; -bool &gbModelViewer = *(bool*)0x95CD93; +bool gbModelViewer; int32 frameCount; diff --git a/src/core/main.h b/src/core/main.h index 5ee758a4..90b13fbb 100644 --- a/src/core/main.h +++ b/src/core/main.h @@ -5,19 +5,15 @@ struct GlobalScene RpWorld *world; RwCamera *camera; }; -extern GlobalScene &Scene; +extern GlobalScene Scene; extern uint8 work_buff[55000]; -//extern char gString[256]; -//extern char gString2[512]; -//extern wchar gUString[256]; -//extern wchar gUString2[256]; -extern char *gString; -extern char *gString2; -extern wchar *gUString; -extern wchar *gUString2; +extern char gString[256]; +extern char gString2[512]; +extern wchar gUString[256]; +extern wchar gUString2[256]; extern bool gbPrintShite; -extern bool &gbModelViewer; +extern bool gbModelViewer; class CSprite2d; diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp index b6a95992..58124e53 100644 --- a/src/modelinfo/ModelInfo.cpp +++ b/src/modelinfo/ModelInfo.cpp @@ -5,11 +5,8 @@ #include "ModelIndices.h" #include "ModelInfo.h" -CBaseModelInfo **CModelInfo::ms_modelInfoPtrs = (CBaseModelInfo**)0x83D408; +CBaseModelInfo *CModelInfo::ms_modelInfoPtrs[MODELINFOSIZE]; -//CStore &CModelInfo::ms_simpleModelStore = *(CStore*)0x885BB4; -//CStore &CModelInfo::ms_timeModelStore = *(CStore*)0x94076C; -//CStore &CModelInfo::ms_2dEffectStore = *(CStore*)0x9434F8; CStore CModelInfo::ms_simpleModelStore; CStore CModelInfo::ms_mloModelStore; CStore CModelInfo::ms_mloInstanceStore; diff --git a/src/modelinfo/ModelInfo.h b/src/modelinfo/ModelInfo.h index e6dec1d8..65cfa4e7 100644 --- a/src/modelinfo/ModelInfo.h +++ b/src/modelinfo/ModelInfo.h @@ -13,7 +13,7 @@ class CModelInfo { - static CBaseModelInfo **ms_modelInfoPtrs; //[MODELINFOSIZE]; + static CBaseModelInfo *ms_modelInfoPtrs[MODELINFOSIZE]; static CStore ms_simpleModelStore; static CStore ms_mloModelStore; static CStore ms_mloInstanceStore; diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index 0c45aa12..fb9e0358 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -19,14 +19,14 @@ #include "ModelIndices.h" #include "ModelInfo.h" -int8 *CVehicleModelInfo::ms_compsToUse = (int8*)0x5FF2EC; // -2, -2 -int8 *CVehicleModelInfo::ms_compsUsed = (int8*)0x95CCB2; -RwTexture **CVehicleModelInfo::ms_pEnvironmentMaps = (RwTexture **)0x8F1A30; -RwRGBA *CVehicleModelInfo::ms_vehicleColourTable = (RwRGBA*)0x86BA88; -RwTexture **CVehicleModelInfo::ms_colourTextureTable = (RwTexture**)0x711C40; +int8 CVehicleModelInfo::ms_compsToUse[2] = { -2, -2 }; +int8 CVehicleModelInfo::ms_compsUsed[2]; +RwTexture *CVehicleModelInfo::ms_pEnvironmentMaps[NUM_VEHICLE_ENVMAPS]; +RwRGBA CVehicleModelInfo::ms_vehicleColourTable[256]; +RwTexture *CVehicleModelInfo::ms_colourTextureTable[256]; -RwTexture *&gpWhiteTexture = *(RwTexture**)0x64C4F8; -RwFrame *&pMatFxIdentityFrame = *(RwFrame**)0x64C510; +RwTexture *gpWhiteTexture; +RwFrame *pMatFxIdentityFrame; enum { VEHICLE_FLAG_COLLAPSE = 0x2, diff --git a/src/modelinfo/VehicleModelInfo.h b/src/modelinfo/VehicleModelInfo.h index 5969c4ca..9992ab98 100644 --- a/src/modelinfo/VehicleModelInfo.h +++ b/src/modelinfo/VehicleModelInfo.h @@ -81,11 +81,11 @@ public: RpAtomic *m_comps[6]; int32 m_numComps; - static int8 *ms_compsToUse; // [2]; - static int8 *ms_compsUsed; // [2]; - static RwTexture **ms_pEnvironmentMaps; // [NUM_VEHICLE_ENVMAPS] - static RwRGBA *ms_vehicleColourTable; // [256] - static RwTexture **ms_colourTextureTable; // [256] + static int8 ms_compsToUse[2]; + static int8 ms_compsUsed[2]; + static RwTexture *ms_pEnvironmentMaps[NUM_VEHICLE_ENVMAPS]; + static RwRGBA ms_vehicleColourTable[256]; + static RwTexture *ms_colourTextureTable[256]; static RwObjectNameIdAssocation *ms_vehicleDescs[NUM_VEHICLE_TYPES]; CVehicleModelInfo(void); diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index 867624c7..57713241 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -12,8 +12,8 @@ #include "World.h" #include "Floater.h" -int16 &CObject::nNoTempObjects = *(int16*)0x95CCA2; -int16 &CObject::nBodyCastHealth = *(int16*)0x5F7D4C; // 1000 +int16 CObject::nNoTempObjects; +int16 CObject::nBodyCastHealth = 1000; void *CObject::operator new(size_t sz) { return CPools::GetObjectPool()->New(); } void *CObject::operator new(size_t sz, int handle) { return CPools::GetObjectPool()->New(handle);}; diff --git a/src/objects/Object.h b/src/objects/Object.h index 6d04c78a..90663cc5 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -73,8 +73,8 @@ public: CEntity *m_pCollidingEntity; int8 m_colour1, m_colour2; - static int16 &nNoTempObjects; - static int16 &nBodyCastHealth; + static int16 nNoTempObjects; + static int16 nBodyCastHealth; static void *operator new(size_t); static void *operator new(size_t, int); diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp index 60827411..5e4ad231 100644 --- a/src/objects/ParticleObject.cpp +++ b/src/objects/ParticleObject.cpp @@ -9,11 +9,11 @@ #include "Game.h" -CParticleObject (&gPObjectArray)[MAX_PARTICLEOBJECTS] = *(CParticleObject(*)[MAX_PARTICLEOBJECTS])*(uintptr*)0x62A58C; +CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS]; -CParticleObject *&CParticleObject::pCloseListHead = *(CParticleObject **)int(0x8F4340); -CParticleObject *&CParticleObject::pFarListHead = *(CParticleObject **)int(0x942F78); -CParticleObject *&CParticleObject::pUnusedListHead = *(CParticleObject **)int(0x94128C); +CParticleObject *CParticleObject::pCloseListHead; +CParticleObject *CParticleObject::pFarListHead; +CParticleObject *CParticleObject::pUnusedListHead; CAudioHydrant List[MAX_AUDIOHYDRANTS]; diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h index 45a3fa30..cfa5936d 100644 --- a/src/objects/ParticleObject.h +++ b/src/objects/ParticleObject.h @@ -62,9 +62,9 @@ public: int8 m_nCreationChance; char _pad1[2]; - static CParticleObject *&pCloseListHead; - static CParticleObject *&pFarListHead; - static CParticleObject *&pUnusedListHead; + static CParticleObject *pCloseListHead; + static CParticleObject *pFarListHead; + static CParticleObject *pUnusedListHead; CParticleObject(); ~CParticleObject(); @@ -89,7 +89,7 @@ public: static void MoveToList(CParticleObject **from, CParticleObject **to, CParticleObject *obj); }; -extern CParticleObject (&gPObjectArray)[MAX_PARTICLEOBJECTS]; +extern CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS]; class CAudioHydrant { diff --git a/src/peds/PedRoutes.cpp b/src/peds/PedRoutes.cpp index 3bc17002..b6512edd 100644 --- a/src/peds/PedRoutes.cpp +++ b/src/peds/PedRoutes.cpp @@ -3,7 +3,7 @@ #include "main.h" #include "PedRoutes.h" -CRouteNode (&gaRoutes)[NUMPEDROUTES] = *(CRouteNode(*)[NUMPEDROUTES]) * (uintptr*)0x62E090; +CRouteNode gaRoutes[NUMPEDROUTES]; void CRouteNode::Initialise() diff --git a/src/peds/PedStats.cpp b/src/peds/PedStats.cpp index 147f11e2..a2ccb567 100644 --- a/src/peds/PedStats.cpp +++ b/src/peds/PedStats.cpp @@ -4,7 +4,6 @@ #include "FileMgr.h" #include "PedStats.h" -//CPedStats *(&CPedStats::ms_apPedStats)[NUM_PEDSTATS] = *(CPedStats *(*)[NUM_PEDSTATS]) *(uintptr*)0x9404D4; CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS]; void diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp index 4c9d6b3f..30af6dcc 100644 --- a/src/peds/PedType.cpp +++ b/src/peds/PedType.cpp @@ -3,7 +3,7 @@ #include "FileMgr.h" #include "PedType.h" -CPedType *(&CPedType::ms_apPedType)[NUM_PEDTYPES] = *(CPedType *(*)[NUM_PEDTYPES]) *(uintptr*)0x941594; +CPedType *CPedType::ms_apPedType[NUM_PEDTYPES]; void CPedType::Initialise(void) diff --git a/src/peds/PedType.h b/src/peds/PedType.h index 3d927df5..c0c72550 100644 --- a/src/peds/PedType.h +++ b/src/peds/PedType.h @@ -71,7 +71,7 @@ class CPedType uint32 m_threats; uint32 m_avoid; - static CPedType *(&ms_apPedType)[NUM_PEDTYPES]; + static CPedType *ms_apPedType[NUM_PEDTYPES]; public: static void Initialise(void); diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 7debe3d3..02035896 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -16,15 +16,15 @@ #define SMALLSTRIPHEIGHT 4.0f #define HORIZSTRIPHEIGHT 48.0f -RwTexture **gpCloudTex = (RwTexture**)0x9411C0; //[5]; +RwTexture *gpCloudTex[5]; -float &CClouds::CloudRotation = *(float*)0x8F5F40; -uint32 &CClouds::IndividualRotation = *(uint32*)0x943078; +float CClouds::CloudRotation; +uint32 CClouds::IndividualRotation; -float &CClouds::ms_cameraRoll = *(float*)0x8F29CC; -float &CClouds::ms_horizonZ = *(float*)0x8F31C0; -CRGBA &CClouds::ms_colourTop = *(CRGBA*)0x94143C; -CRGBA &CClouds::ms_colourBottom = *(CRGBA*)0x8F2C38; +float CClouds::ms_cameraRoll; +float CClouds::ms_horizonZ; +CRGBA CClouds::ms_colourTop; +CRGBA CClouds::ms_colourBottom; void CClouds::Init(void) diff --git a/src/render/Clouds.h b/src/render/Clouds.h index c8000569..4d8cd2c8 100644 --- a/src/render/Clouds.h +++ b/src/render/Clouds.h @@ -3,13 +3,13 @@ class CClouds { public: - static float &CloudRotation; - static uint32 &IndividualRotation; + static float CloudRotation; + static uint32 IndividualRotation; - static float &ms_cameraRoll; - static float &ms_horizonZ; - static CRGBA &ms_colourTop; - static CRGBA &ms_colourBottom; + static float ms_cameraRoll; + static float ms_horizonZ; + static CRGBA ms_colourTop; + static CRGBA ms_colourBottom; static void Init(void); static void Shutdown(void); diff --git a/src/render/Console.cpp b/src/render/Console.cpp index 545122b0..bfdb2701 100644 --- a/src/render/Console.cpp +++ b/src/render/Console.cpp @@ -9,7 +9,7 @@ #define CONSOLE_Y_POS (10.0f) #define CONSOLE_LINE_HEIGHT (12.0f) -CConsole &TheConsole = *(CConsole*)0x8F6498; +CConsole TheConsole; void CConsole::AddLine(char *s, uint8 r, uint8 g, uint8 b) diff --git a/src/render/Console.h b/src/render/Console.h index c454d75e..b4fa60c4 100644 --- a/src/render/Console.h +++ b/src/render/Console.h @@ -22,4 +22,4 @@ public: void Init() { m_nCurrentLine = 0; m_nLineCount = 0; } }; -extern CConsole &TheConsole; +extern CConsole TheConsole; diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index 68994b0b..38f86f4b 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -48,16 +48,16 @@ FlareDef HeadLightsFlareDef[] = { }; -RwTexture **gpCoronaTexture = (RwTexture**)0x5FAF44; //[9] +RwTexture *gpCoronaTexture[9] = { NULL }; -float &CCoronas::LightsMult = *(float*)0x5FB088; // 1.0 -float &CCoronas::SunScreenX = *(float*)0x8F4358; -float &CCoronas::SunScreenY = *(float*)0x8F4354; -bool &CCoronas::bSmallMoon = *(bool*)0x95CD49; -bool &CCoronas::SunBlockedByClouds = *(bool*)0x95CD73; -int &CCoronas::bChangeBrightnessImmediately = *(int*)0x8E2C30; +float CCoronas::LightsMult = 1.0f; +float CCoronas::SunScreenX; +float CCoronas::SunScreenY; +bool CCoronas::bSmallMoon; +bool CCoronas::SunBlockedByClouds; +int CCoronas::bChangeBrightnessImmediately; -CRegisteredCorona *CCoronas::aCoronas = (CRegisteredCorona*)0x72E518; +CRegisteredCorona CCoronas::aCoronas[NUMCORONAS]; const char aCoronaSpriteNames[][32] = { "coronastar", diff --git a/src/render/Coronas.h b/src/render/Coronas.h index 359a34ed..4b49e40e 100644 --- a/src/render/Coronas.h +++ b/src/render/Coronas.h @@ -1,6 +1,6 @@ #pragma once -extern RwTexture **gpCoronaTexture; //[9] +extern RwTexture *gpCoronaTexture[9]; struct CRegisteredCorona { @@ -42,7 +42,7 @@ static_assert(sizeof(CRegisteredCorona) == 0x80, "CRegisteredCorona: error"); class CCoronas { - static CRegisteredCorona *aCoronas; //[NUMCORONAS]; + static CRegisteredCorona aCoronas[NUMCORONAS]; public: enum { SUN_CORE = 1, @@ -77,12 +77,12 @@ public: STREAK_ON, }; - static float &LightsMult; - static float &SunScreenY; - static float &SunScreenX; - static bool &bSmallMoon; - static bool &SunBlockedByClouds; - static int &bChangeBrightnessImmediately; + static float LightsMult; + static float SunScreenY; + static float SunScreenX; + static bool bSmallMoon; + static bool SunBlockedByClouds; + static int bChangeBrightnessImmediately; static void Init(void); static void Shutdown(void); diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp index b423fcc0..25f7bbcf 100644 --- a/src/render/Credits.cpp +++ b/src/render/Credits.cpp @@ -8,8 +8,8 @@ #include "Text.h" #include "Credits.h" -bool &CCredits::bCreditsGoing = *(bool*)0x95CDD3; -uint32 &CCredits::CreditsStartTime = *(uint32*)0x8F2528; +bool CCredits::bCreditsGoing; +uint32 CCredits::CreditsStartTime; void CCredits::Init(void) diff --git a/src/render/Credits.h b/src/render/Credits.h index c39fb035..e049ce76 100644 --- a/src/render/Credits.h +++ b/src/render/Credits.h @@ -2,8 +2,8 @@ class CCredits { - static bool &bCreditsGoing; - static uint32 &CreditsStartTime; + static bool bCreditsGoing; + static uint32 CreditsStartTime; public: static void Init(void); static void Start(void); diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index 862fc024..dcbb6342 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -8,15 +8,15 @@ float CDraw::ms_fAspectRatio = DEFAULT_ASPECT_RATIO; #endif -float &CDraw::ms_fNearClipZ = *(float*)0x8E2DC4; -float &CDraw::ms_fFarClipZ = *(float*)0x9434F0; -float &CDraw::ms_fFOV = *(float*)0x5FBC6C; -float &CDraw::ms_fLODDistance = *(float*)0x8F2C30; +float CDraw::ms_fNearClipZ; +float CDraw::ms_fFarClipZ; +float CDraw::ms_fFOV = 45.0f; +float CDraw::ms_fLODDistance; -uint8 &CDraw::FadeValue = *(uint8*)0x95CD68; -uint8 &CDraw::FadeRed = *(uint8*)0x95CD90; -uint8 &CDraw::FadeGreen = *(uint8*)0x95CD71; -uint8 &CDraw::FadeBlue = *(uint8*)0x95CD53; +uint8 CDraw::FadeValue; +uint8 CDraw::FadeRed; +uint8 CDraw::FadeGreen; +uint8 CDraw::FadeBlue; float CDraw::FindAspectRatio(void) diff --git a/src/render/Draw.h b/src/render/Draw.h index 50e1e294..55958a2a 100644 --- a/src/render/Draw.h +++ b/src/render/Draw.h @@ -13,11 +13,11 @@ enum eAspectRatio class CDraw { private: - static float &ms_fNearClipZ; - static float &ms_fFarClipZ; - static float &ms_fFOV; + static float ms_fNearClipZ; + static float ms_fFarClipZ; + static float ms_fFOV; public: - static float &ms_fLODDistance; // set but unused? + static float ms_fLODDistance; // set but unused? #ifdef ASPECT_RATIO_SCALE // we use this variable to scale a lot of 2D elements @@ -25,10 +25,10 @@ public: static float ms_fAspectRatio; #endif - static uint8 &FadeValue; - static uint8 &FadeRed; - static uint8 &FadeGreen; - static uint8 &FadeBlue; + static uint8 FadeValue; + static uint8 FadeRed; + static uint8 FadeGreen; + static uint8 FadeBlue; static void SetNearClipZ(float nearclip) { ms_fNearClipZ = nearclip; } static float GetNearClipZ(void) { return ms_fNearClipZ; } diff --git a/src/render/Font.cpp b/src/render/Font.cpp index ca15cba7..ba4c4301 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -4,18 +4,18 @@ #include "TxdStore.h" #include "Font.h" -CFontDetails &CFont::Details = *(CFontDetails*)0x8F317C; -int16 &CFont::NewLine = *(int16*)0x95CC94; -CSprite2d *CFont::Sprite = (CSprite2d*)0x95CC04; +CFontDetails CFont::Details; +int16 CFont::NewLine; +CSprite2d CFont::Sprite[MAX_FONTS]; #ifdef MORE_LANGUAGES uint8 CFont::LanguageSet = FONT_LANGSET_EFIGS; int32 CFont::Slot = -1; -int16 CFont::Size[2][3][193] = { +int16 CFont::Size[2][MAX_FONTS][193] = { { #else -int16 CFont::Size[3][193] = { +int16 CFont::Size[MAX_FONTS][193] = { #endif { 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17, 13, 31, diff --git a/src/render/Font.h b/src/render/Font.h index 0659dda1..ebf5e292 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -31,6 +31,7 @@ enum { FONT_BANK, FONT_PAGER, FONT_HEADING, + MAX_FONTS }; enum { @@ -50,16 +51,16 @@ enum class CFont { #ifdef MORE_LANGUAGES - static int16 Size[2][3][193]; + static int16 Size[2][MAX_FONTS][193]; static uint8 LanguageSet; static int32 Slot; #else - static int16 Size[3][193]; + static int16 Size[MAX_FONTS][193]; #endif - static int16 - static CSprite2d *Sprite; //[3] + static int16 NewLine; + static CSprite2d Sprite[MAX_FONTS]; public: - static CFontDetails& Details; + static CFontDetails Details; static void Initialise(void); static void Shutdown(void); diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 9529c4c1..5bcdd450 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -21,52 +21,52 @@ #include "User.h" #include "World.h" -wchar CHud::m_HelpMessage[256]; // = (wchar*)0x86B888; -wchar CHud::m_LastHelpMessage[256]; // = (wchar*)0x6E8F28; -uint32 CHud::m_HelpMessageState; // = *(int32*)0x880E1C; -uint32 CHud::m_HelpMessageTimer; // = *(int32*)0x880FA4; -int32 CHud::m_HelpMessageFadeTimer; // = *(int32*)0x8F6258; -wchar CHud::m_HelpMessageToPrint[256]; // = (wchar*)0x664480; -float CHud::m_fHelpMessageTime; // *(float *)0x8E2C28; -bool CHud::m_HelpMessageQuick; // = *(bool*)0x95CCF7; -uint32 CHud::m_ZoneState; // = *(int32*)0x8F29AC; +wchar CHud::m_HelpMessage[256]; +wchar CHud::m_LastHelpMessage[256]; +uint32 CHud::m_HelpMessageState; +uint32 CHud::m_HelpMessageTimer; +int32 CHud::m_HelpMessageFadeTimer; +wchar CHud::m_HelpMessageToPrint[256]; +float CHud::m_fHelpMessageTime; +bool CHud::m_HelpMessageQuick; +uint32 CHud::m_ZoneState; int32 CHud::m_ZoneFadeTimer; -uint32 CHud::m_ZoneNameTimer; // = *(int32*)0x8F1A50; -wchar *CHud::m_pZoneName; // = *(wchar**)0x8E2C2C; -wchar *CHud::m_pLastZoneName; // = (wchar*)0x8F432C; +uint32 CHud::m_ZoneNameTimer; +wchar *CHud::m_pZoneName; +wchar *CHud::m_pLastZoneName; wchar *CHud::m_ZoneToPrint; -uint32 CHud::m_VehicleState; // = *(int32*)0x940560; +uint32 CHud::m_VehicleState; int32 CHud::m_VehicleFadeTimer; -uint32 CHud::m_VehicleNameTimer; // = *(int32*)0x8F2A14; -wchar *CHud::m_VehicleName; // = *(wchar**)0x942FB4; -wchar *CHud::m_pLastVehicleName; // = *(wchar**)0x8E2DD8; +uint32 CHud::m_VehicleNameTimer; +wchar *CHud::m_VehicleName; +wchar *CHud::m_pLastVehicleName; wchar *CHud::m_pVehicleNameToPrint; -wchar CHud::m_Message[256];// = (wchar*)0x72E318; -wchar CHud::m_PagerMessage[256]; // = (wchar*)0x878840; -bool CHud::m_Wants_To_Draw_Hud; // (bool*)0x95CD89; -bool CHud::m_Wants_To_Draw_3dMarkers; // = *(bool*)0x95CD62; -wchar CHud::m_BigMessage[6][128]; // = *(wchar(*)[6][128]) * (uintptr*)0x664CE0; -int16 CHud::m_ItemToFlash; // = *(int16*)0x95CC82; +wchar CHud::m_Message[256]; +wchar CHud::m_PagerMessage[256]; +bool CHud::m_Wants_To_Draw_Hud; +bool CHud::m_Wants_To_Draw_3dMarkers; +wchar CHud::m_BigMessage[6][128]; +int16 CHud::m_ItemToFlash; // These aren't really in CHud float CHud::BigMessageInUse[6]; float CHud::BigMessageAlpha[6]; float CHud::BigMessageX[6]; -float CHud::OddJob2OffTimer; // = *(float*)0x942FA0; -bool CHud::CounterOnLastFrame; // = *(int8*)0x95CD67; -float CHud::OddJob2XOffset; // = *(float*)0x8F1B5C; -uint16 CHud::CounterFlashTimer; // = *(int16*)0x95CC20; -uint16 CHud::OddJob2Timer; // = *(int16*)0x95CC52; -bool CHud::TimerOnLastFrame; //= *(int8*)0x95CDA7; -int16 CHud::OddJob2On; //= *(int16*)0x95CC78; -uint16 CHud::TimerFlashTimer; //= *(int16*)0x95CC6C; -int16 CHud::PagerSoundPlayed; //= *(int16*)0x95CC4A; -int32 CHud::SpriteBrightness; //= *(int32*)0x95CC54; -float CHud::PagerXOffset; //= *(float*)0x941590; -int16 CHud::PagerTimer; //= *(int16*)0x95CC3A; -int16 CHud::PagerOn; //= *(int16*)0x95CCA0; +float CHud::OddJob2OffTimer; +bool CHud::CounterOnLastFrame; +float CHud::OddJob2XOffset; +uint16 CHud::CounterFlashTimer; +uint16 CHud::OddJob2Timer; +bool CHud::TimerOnLastFrame; +int16 CHud::OddJob2On; +uint16 CHud::TimerFlashTimer; +int16 CHud::PagerSoundPlayed; +int32 CHud::SpriteBrightness; +float CHud::PagerXOffset; +int16 CHud::PagerTimer; +int16 CHud::PagerOn; -CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; // = (CSprite2d*)0x95CB9C; +CSprite2d CHud::Sprites[NUM_HUD_SPRITES]; struct { @@ -98,8 +98,8 @@ struct {"siterocket", "siterocket"} }; -RwTexture *&gpSniperSightTex = *(RwTexture**)0x8F5834; -RwTexture *&gpRocketSightTex = *(RwTexture**)0x8E2C20; +RwTexture *gpSniperSightTex; +RwTexture *gpRocketSightTex; void CHud::Draw() { diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp index d28671fa..d15fa422 100644 --- a/src/render/MBlur.cpp +++ b/src/render/MBlur.cpp @@ -6,9 +6,9 @@ // Originally taken from RW example 'mblur' -RwRaster *&CMBlur::pFrontBuffer = *(RwRaster**)0x8E2C48; -bool &CMBlur::ms_bJustInitialised = *(bool*)0x95CDAB; -bool &CMBlur::BlurOn = *(bool*)0x95CDAD; +RwRaster *CMBlur::pFrontBuffer; +bool CMBlur::ms_bJustInitialised; +bool CMBlur::BlurOn; static RwIm2DVertex Vertex[4]; static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 }; diff --git a/src/render/MBlur.h b/src/render/MBlur.h index 42827f99..e8a5bef8 100644 --- a/src/render/MBlur.h +++ b/src/render/MBlur.h @@ -3,9 +3,9 @@ class CMBlur { public: - static RwRaster *&pFrontBuffer; - static bool &ms_bJustInitialised; - static bool &BlurOn; + static RwRaster *pFrontBuffer; + static bool ms_bJustInitialised; + static bool BlurOn; public: static void MotionBlurOpen(RwCamera *cam); diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index 6956a887..eb188128 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -204,26 +204,21 @@ RwRaster *gpGunShellRaster; RwRaster *gpWakeOldRaster; -//RwRaster *gpPointlightRaster; // CPointLights::RenderFogEffect -RwRaster *&gpPointlightRaster = *(RwRaster **)0x8F5FE0; +RwRaster *gpPointlightRaster; // CPointLights::RenderFogEffect -//RwTexture *gpRainDropTex[MAX_RAINDROP_FILES]; // CWeather::RenderRainStreaks -RwTexture * (&gpRainDropTex)[MAX_RAINDROP_FILES] = *(RwTexture * (*)[MAX_RAINDROP_FILES])*(int *)0x880660; +RwTexture *gpRainDropTex[MAX_RAINDROP_FILES]; // CWeather::RenderRainStreaks RwRaster *gpRainDropRaster[MAX_RAINDROP_FILES]; -//Float CParticle::ms_afRandTable[CParticle::RAND_TABLE_SIZE]; // -float (&CParticle::ms_afRandTable)[CParticle::RAND_TABLE_SIZE] = *(float (*)[CParticle::RAND_TABLE_SIZE])*(int *)0x6E98C8; +float CParticle::ms_afRandTable[CParticle::RAND_TABLE_SIZE]; CParticle *CParticle::m_pUnusedListHead; -//Float CParticle::m_SinTable[CParticle::SIN_COS_TABLE_SIZE]; // -//Float CParticle::m_CosTable[CParticle::SIN_COS_TABLE_SIZE]; / -float (&CParticle::m_SinTable)[CParticle::SIN_COS_TABLE_SIZE] = *(float (*)[CParticle::SIN_COS_TABLE_SIZE])*(int *)0x877358; -float (&CParticle::m_CosTable)[CParticle::SIN_COS_TABLE_SIZE] = *(float (*)[CParticle::SIN_COS_TABLE_SIZE])*(int *)0x70DA18; +float CParticle::m_SinTable[CParticle::SIN_COS_TABLE_SIZE]; +float CParticle::m_CosTable[CParticle::SIN_COS_TABLE_SIZE]; int32 Randomizer; diff --git a/src/render/Particle.h b/src/render/Particle.h index 310ef0d4..604fbb82 100644 --- a/src/render/Particle.h +++ b/src/render/Particle.h @@ -49,16 +49,11 @@ public: ; } - //static float ms_afRandTable[RAND_TABLE_SIZE]; - static float (&ms_afRandTable)[RAND_TABLE_SIZE]; + static float ms_afRandTable[RAND_TABLE_SIZE]; static CParticle *m_pUnusedListHead; - /* static float m_SinTable[SIN_COS_TABLE_SIZE]; static float m_CosTable[SIN_COS_TABLE_SIZE]; - */ - static float (&m_SinTable)[SIN_COS_TABLE_SIZE]; - static float (&m_CosTable)[SIN_COS_TABLE_SIZE]; static float Sin(int32 value) { return m_SinTable[value]; } static float Cos(int32 value) { return m_CosTable[value]; } diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp index a015ec54..92a89582 100644 --- a/src/render/PointLights.cpp +++ b/src/render/PointLights.cpp @@ -10,8 +10,8 @@ #include "Timer.h" #include "PointLights.h" -int16 &CPointLights::NumLights = *(int16*)0x95CC3E; -CRegisteredPointLight *CPointLights::aLights = (CRegisteredPointLight*)0x7096D0; +int16 CPointLights::NumLights; +CRegisteredPointLight CPointLights::aLights[NUMPOINTLIGHTS]; void CPointLights::InitPerFrame(void) @@ -114,7 +114,7 @@ CPointLights::GenerateLightsAffectingObject(CVector *objCoors) return ret; } -extern RwRaster *&gpPointlightRaster; +extern RwRaster *gpPointlightRaster; void CPointLights::RemoveLightsAffectingObject(void) diff --git a/src/render/PointLights.h b/src/render/PointLights.h index c1dad87f..215e1dc9 100644 --- a/src/render/PointLights.h +++ b/src/render/PointLights.h @@ -18,8 +18,8 @@ static_assert(sizeof(CRegisteredPointLight) == 0x2C, "CRegisteredPointLight: err class CPointLights { public: - static int16 &NumLights; - static CRegisteredPointLight *aLights; //[NUMPOINTLIGHTS] + static int16 NumLights; + static CRegisteredPointLight aLights[NUMPOINTLIGHTS]; enum { LIGHT_POINT, diff --git a/src/render/RenderBuffer.cpp b/src/render/RenderBuffer.cpp index f6499451..4225619f 100644 --- a/src/render/RenderBuffer.cpp +++ b/src/render/RenderBuffer.cpp @@ -2,14 +2,14 @@ #include "patcher.h" #include "RenderBuffer.h" -int32 &TempBufferVerticesStored = *(int32*)0x8F5F78; -int32 &TempBufferIndicesStored = *(int32*)0x8F1A4C; +int32 TempBufferVerticesStored; +int32 TempBufferIndicesStored; -RwIm3DVertex *TempBufferRenderVertices = (RwIm3DVertex*)0x862330; -RwImVertexIndex *TempBufferRenderIndexList = (RwImVertexIndex*)0x846288; +RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE]; +RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE]; -int &RenderBuffer::VerticesToBeStored = *(int*)0x8F59C4; -int &RenderBuffer::IndicesToBeStored = *(int*)0x8E28B0; +int RenderBuffer::VerticesToBeStored; +int RenderBuffer::IndicesToBeStored; void RenderBuffer::ClearRenderBuffer(void) diff --git a/src/render/RenderBuffer.h b/src/render/RenderBuffer.h index 2b8a9f86..485d24e3 100644 --- a/src/render/RenderBuffer.h +++ b/src/render/RenderBuffer.h @@ -1,8 +1,8 @@ class RenderBuffer { public: - static int &VerticesToBeStored; - static int &IndicesToBeStored; + static int VerticesToBeStored; + static int IndicesToBeStored; static void ClearRenderBuffer(void); static void StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, RwIm3DVertex **vertexStart); static void StopStoring(void); @@ -12,7 +12,7 @@ public: #define TEMPBUFFERVERTSIZE 256 #define TEMPBUFFERINDEXSIZE 1024 -extern int32 &TempBufferVerticesStored; -extern int32 &TempBufferIndicesStored; -extern RwIm3DVertex *TempBufferRenderVertices; -extern RwImVertexIndex *TempBufferRenderIndexList; \ No newline at end of file +extern int32 TempBufferVerticesStored; +extern int32 TempBufferIndicesStored; +extern RwIm3DVertex TempBufferRenderVertices[TEMPBUFFERVERTSIZE]; +extern RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE]; \ No newline at end of file diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index e14b0453..56a93238 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -20,43 +20,31 @@ SETTWEAKPATH("Shadows"); TWEAKBOOL(gbPrintShite); -#if 1 RwImVertexIndex ShadowIndexList[24]; -#else -RwImVertexIndex (&ShadowIndexList)[24] = *(RwImVertexIndex (*)[24])*(int *)0x649188; -#endif -RwTexture *&gpShadowCarTex = *(RwTexture **)0x8F2C90; -RwTexture *&gpShadowPedTex = *(RwTexture **)0x8F59D0; -RwTexture *&gpShadowHeliTex = *(RwTexture **)0x8E2A90; -RwTexture *&gpShadowExplosionTex = *(RwTexture **)0x8F2A00; -RwTexture *&gpShadowHeadLightsTex = *(RwTexture **)0x95CB98; -RwTexture *&gpOutline1Tex = *(RwTexture **)0x8F1B24; -RwTexture *&gpOutline2Tex = *(RwTexture **)0x8F1B04; -RwTexture *&gpOutline3Tex = *(RwTexture **)0x8F1B08; -RwTexture *&gpBloodPoolTex = *(RwTexture **)0x9415F8; -RwTexture *&gpReflectionTex = *(RwTexture **)0x8F582C; -RwTexture *&gpGoalMarkerTex = *(RwTexture **)0x94142C; -RwTexture *&gpWalkDontTex = *(RwTexture **)0x95CB4C; -RwTexture *&gpCrackedGlassTex = *(RwTexture **)0x95CB94; -RwTexture *&gpPostShadowTex = *(RwTexture **)0x8F59D4; -RwTexture *&gpGoalTex = *(RwTexture**)0x94142C; +RwTexture *gpShadowCarTex; +RwTexture *gpShadowPedTex; +RwTexture *gpShadowHeliTex; +RwTexture *gpShadowExplosionTex; +RwTexture *gpShadowHeadLightsTex; +RwTexture *gpOutline1Tex; +RwTexture *gpOutline2Tex; +RwTexture *gpOutline3Tex; +RwTexture *gpBloodPoolTex; +RwTexture *gpReflectionTex; +RwTexture *gpGoalMarkerTex; +RwTexture *gpWalkDontTex; +RwTexture *gpCrackedGlassTex; +RwTexture *gpPostShadowTex; +RwTexture *gpGoalTex; -#if 1 int16 CShadows::ShadowsStoredToBeRendered; CStoredShadow CShadows::asShadowsStored [MAX_STOREDSHADOWS]; CPolyBunch CShadows::aPolyBunches [MAX_POLYBUNCHES]; CStaticShadow CShadows::aStaticShadows [MAX_STATICSHADOWS]; CPolyBunch *CShadows::pEmptyBunchList; CPermanentShadow CShadows::aPermanentShadows[MAX_PERMAMENTSHADOWS]; -#else -int16 &CShadows::ShadowsStoredToBeRendered = *(int16*)0x95CCEE; -CStoredShadow (&CShadows::asShadowsStored)[MAX_STOREDSHADOWS] = *(CStoredShadow (*)[MAX_STOREDSHADOWS])*(int *)0x779058; -CPolyBunch (&CShadows::aPolyBunches)[MAX_POLYBUNCHES] = *(CPolyBunch (*)[MAX_POLYBUNCHES])*(int *)0x86F4C8; -CStaticShadow (&CShadows::aStaticShadows)[MAX_STATICSHADOWS] = *(CStaticShadow (*)[MAX_STATICSHADOWS])*(int *)0x773BE8; -CPolyBunch *&CShadows::pEmptyBunchList = *(CPolyBunch**)0x8F435C; -CPermanentShadow (&CShadows::aPermanentShadows)[MAX_PERMAMENTSHADOWS] = *(CPermanentShadow (*)[MAX_PERMAMENTSHADOWS])*(int *)0x712040; -#endif + void CShadows::Init(void) diff --git a/src/render/Shadows.h b/src/render/Shadows.h index ced9f11b..d209fe90 100644 --- a/src/render/Shadows.h +++ b/src/render/Shadows.h @@ -174,18 +174,18 @@ public: static void RenderIndicatorShadow (uint32 nID, uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity); }; -extern RwTexture *&gpShadowCarTex; -extern RwTexture *&gpShadowPedTex; -extern RwTexture *&gpShadowHeliTex; -extern RwTexture *&gpShadowExplosionTex; -extern RwTexture *&gpShadowHeadLightsTex; -extern RwTexture *&gpOutline1Tex; -extern RwTexture *&gpOutline2Tex; -extern RwTexture *&gpOutline3Tex; -extern RwTexture *&gpBloodPoolTex; -extern RwTexture *&gpReflectionTex; -extern RwTexture *&gpGoalMarkerTex; -extern RwTexture *&gpWalkDontTex; -extern RwTexture *&gpCrackedGlassTex; -extern RwTexture *&gpPostShadowTex; -extern RwTexture *&gpGoalTex; +extern RwTexture *gpShadowCarTex; +extern RwTexture *gpShadowPedTex; +extern RwTexture *gpShadowHeliTex; +extern RwTexture *gpShadowExplosionTex; +extern RwTexture *gpShadowHeadLightsTex; +extern RwTexture *gpOutline1Tex; +extern RwTexture *gpOutline2Tex; +extern RwTexture *gpOutline3Tex; +extern RwTexture *gpBloodPoolTex; +extern RwTexture *gpReflectionTex; +extern RwTexture *gpGoalMarkerTex; +extern RwTexture *gpWalkDontTex; +extern RwTexture *gpCrackedGlassTex; +extern RwTexture *gpPostShadowTex; +extern RwTexture *gpGoalTex; diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 82754121..57ab8f14 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -5,10 +5,10 @@ #include "Camera.h" #include "Sprite.h" -float &CSprite::m_f2DNearScreenZ = *(float*)0x8F1ABC; -float &CSprite::m_f2DFarScreenZ = *(float*)0x8F2C94; -float &CSprite::m_fRecipNearClipPlane = *(float*)0x8F5FFC; -int32 &CSprite::m_bFlushSpriteBufferSwitchZTest = *(int32*)0x8F5FB0; +float CSprite::m_f2DNearScreenZ; +float CSprite::m_f2DFarScreenZ; +float CSprite::m_fRecipNearClipPlane; +int32 CSprite::m_bFlushSpriteBufferSwitchZTest; float CSprite::CalcHorizonCoors(void) @@ -40,9 +40,9 @@ CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, } #define SPRITEBUFFERSIZE 64 -static int32 &nSpriteBufferIndex = *(int32*)0x649A80; -static RwIm2DVertex *SpriteBufferVerts = (RwIm2DVertex*)0x649A84; //[SPRITEBUFFERSIZE*6]; -static RwIm2DVertex *verts = (RwIm2DVertex*)0x64C484; //[4]; +static int32 nSpriteBufferIndex; +static RwIm2DVertex SpriteBufferVerts[SPRITEBUFFERSIZE*6]; +static RwIm2DVertex verts[4]; void CSprite::InitSpriteBuffer(void) diff --git a/src/render/Sprite.h b/src/render/Sprite.h index 33953ff3..ec4c1d1b 100644 --- a/src/render/Sprite.h +++ b/src/render/Sprite.h @@ -2,10 +2,10 @@ class CSprite { - static float &m_f2DNearScreenZ; - static float &m_f2DFarScreenZ; - static float &m_fRecipNearClipPlane; - static int32 &m_bFlushSpriteBufferSwitchZTest; + static float m_f2DNearScreenZ; + static float m_f2DFarScreenZ; + static float m_fRecipNearClipPlane; + static int32 m_bFlushSpriteBufferSwitchZTest; public: static float CalcHorizonCoors(void); static bool CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip); diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp index 7ab3e91e..6e24a76e 100644 --- a/src/render/Timecycle.cpp +++ b/src/render/Timecycle.cpp @@ -10,101 +10,101 @@ #include "FileMgr.h" #include "Timecycle.h" -int (*CTimeCycle::m_nAmbientRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x86AF78; -int (*CTimeCycle::m_nAmbientGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x665308; -int (*CTimeCycle::m_nAmbientBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x72CF88; -int (*CTimeCycle::m_nDirectionalRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x6FAB78; -int (*CTimeCycle::m_nDirectionalGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x6F4528; -int (*CTimeCycle::m_nDirectionalBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x83CE58; -int (*CTimeCycle::m_nSkyTopRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x87FB90; -int (*CTimeCycle::m_nSkyTopGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x8460A8; -int (*CTimeCycle::m_nSkyTopBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x87B158; -int (*CTimeCycle::m_nSkyBottomRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x6FA960; -int (*CTimeCycle::m_nSkyBottomGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x70D6A8; -int (*CTimeCycle::m_nSkyBottomBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x83D288; -int (*CTimeCycle::m_nSunCoreRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x878360; -int (*CTimeCycle::m_nSunCoreGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x6EE088; -int (*CTimeCycle::m_nSunCoreBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x773A68; -int (*CTimeCycle::m_nSunCoronaRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x664B60; -int (*CTimeCycle::m_nSunCoronaGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x6F01E0; -int (*CTimeCycle::m_nSunCoronaBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x6E6340; -float (*CTimeCycle::m_fSunSize)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x733510; -float (*CTimeCycle::m_fSpriteSize)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x87F820; -float (*CTimeCycle::m_fSpriteBrightness)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x6E96F0; -short (*CTimeCycle::m_nShadowStrength)[NUMWEATHERS] = (short(*)[NUMWEATHERS])0x83CFD8; -short (*CTimeCycle::m_nLightShadowStrength)[NUMWEATHERS] = (short(*)[NUMWEATHERS])0x72B0F8; -short (*CTimeCycle::m_nTreeShadowStrength)[NUMWEATHERS] = (short(*)[NUMWEATHERS])0x733450; -float (*CTimeCycle::m_fFogStart)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x8806C8; -float (*CTimeCycle::m_fFarClip)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x8804E0; -float (*CTimeCycle::m_fLightsOnGroundBrightness)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x83D108; -int (*CTimeCycle::m_nLowCloudsRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x726770; -int (*CTimeCycle::m_nLowCloudsGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x87BF08; -int (*CTimeCycle::m_nLowCloudsBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x87FA10; -int (*CTimeCycle::m_nFluffyCloudsTopRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x70F2B0; -int (*CTimeCycle::m_nFluffyCloudsTopGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x72D288; -int (*CTimeCycle::m_nFluffyCloudsTopBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x86B108; -int (*CTimeCycle::m_nFluffyCloudsBottomRed)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x6E8DA8; -int (*CTimeCycle::m_nFluffyCloudsBottomGreen)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x715AA8; -int (*CTimeCycle::m_nFluffyCloudsBottomBlue)[NUMWEATHERS] = (int(*)[NUMWEATHERS])0x6EE2D0; -float (*CTimeCycle::m_fBlurRed)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x87C7E0; -float (*CTimeCycle::m_fBlurGreen)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x774C10; -float (*CTimeCycle::m_fBlurBlue)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x8784E0; -float (*CTimeCycle::m_fBlurAlpha)[NUMWEATHERS] = (float(*)[NUMWEATHERS])0x733690; +int CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSkyTopRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSkyTopGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSkyTopBlue[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSkyBottomRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSunCoreRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSunCoreGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSunCoreBlue[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSunCoronaRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fSunSize[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS]; +short CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS]; +short CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS]; +short CTimeCycle::m_nTreeShadowStrength[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nLowCloudsRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS]; +int CTimeCycle::m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fBlurRed[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fBlurGreen[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fBlurBlue[NUMHOURS][NUMWEATHERS]; +float CTimeCycle::m_fBlurAlpha[NUMHOURS][NUMWEATHERS]; -float &CTimeCycle::m_fCurrentAmbientRed = *(float*)0x8F29B4; -float &CTimeCycle::m_fCurrentAmbientGreen = *(float*)0x94144C; -float &CTimeCycle::m_fCurrentAmbientBlue = *(float*)0x942FC0; -float &CTimeCycle::m_fCurrentDirectionalRed = *(float*)0x8F29D8; -float &CTimeCycle::m_fCurrentDirectionalGreen = *(float*)0x940594; -float &CTimeCycle::m_fCurrentDirectionalBlue = *(float*)0x942FAC; -int &CTimeCycle::m_nCurrentSkyTopRed = *(int*)0x9403C0; -int &CTimeCycle::m_nCurrentSkyTopGreen = *(int*)0x943074; -int &CTimeCycle::m_nCurrentSkyTopBlue = *(int*)0x8F29B8; -int &CTimeCycle::m_nCurrentSkyBottomRed = *(int*)0x9414D0; -int &CTimeCycle::m_nCurrentSkyBottomGreen = *(int*)0x8F2BD0; -int &CTimeCycle::m_nCurrentSkyBottomBlue = *(int*)0x8F625C; -int &CTimeCycle::m_nCurrentSunCoreRed = *(int*)0x8F2534; -int &CTimeCycle::m_nCurrentSunCoreGreen = *(int*)0x8F6264; -int &CTimeCycle::m_nCurrentSunCoreBlue = *(int*)0x94149C; -int &CTimeCycle::m_nCurrentSunCoronaRed = *(int*)0x8F2C1C; -int &CTimeCycle::m_nCurrentSunCoronaGreen = *(int*)0x885B54; -int &CTimeCycle::m_nCurrentSunCoronaBlue = *(int*)0x880F60; -float &CTimeCycle::m_fCurrentSunSize = *(float*)0x940588; -float &CTimeCycle::m_fCurrentSpriteSize = *(float*)0x8F1AA8; -float &CTimeCycle::m_fCurrentSpriteBrightness = *(float*)0x8F5FDC; -int &CTimeCycle::m_nCurrentShadowStrength = *(int*)0x95CC76; -int &CTimeCycle::m_nCurrentLightShadowStrength = *(int*)0x95CC66; -int &CTimeCycle::m_nCurrentTreeShadowStrength = *(int*)0x95CC86; -float &CTimeCycle::m_fCurrentFogStart = *(float*)0x8F1AE0; -float &CTimeCycle::m_fCurrentFarClip = *(float*)0x8F5FD8; -float &CTimeCycle::m_fCurrentLightsOnGroundBrightness = *(float*)0x8F1B60; -int &CTimeCycle::m_nCurrentLowCloudsRed = *(int*)0x95CB54; -int &CTimeCycle::m_nCurrentLowCloudsGreen = *(int*)0x95CB48; -int &CTimeCycle::m_nCurrentLowCloudsBlue = *(int*)0x95CC1C; -int &CTimeCycle::m_nCurrentFluffyCloudsTopRed = *(int*)0x8F2550; -int &CTimeCycle::m_nCurrentFluffyCloudsTopGreen = *(int*)0x8F59CC; -int &CTimeCycle::m_nCurrentFluffyCloudsTopBlue = *(int*)0x941434; -int &CTimeCycle::m_nCurrentFluffyCloudsBottomRed = *(int*)0x8F1A38; -int &CTimeCycle::m_nCurrentFluffyCloudsBottomGreen = *(int*)0x8E28B8; -int &CTimeCycle::m_nCurrentFluffyCloudsBottomBlue = *(int*)0x8F3960; -float &CTimeCycle::m_fCurrentBlurRed = *(float*)0x8F6000; -float &CTimeCycle::m_fCurrentBlurGreen = *(float*)0x9405A0; -float &CTimeCycle::m_fCurrentBlurBlue = *(float*)0x8F250C; -float &CTimeCycle::m_fCurrentBlurAlpha = *(float*)0x940728; -int &CTimeCycle::m_nCurrentFogColourRed = *(int*)0x940714; -int &CTimeCycle::m_nCurrentFogColourGreen = *(int*)0x8E2A60; -int &CTimeCycle::m_nCurrentFogColourBlue = *(int*)0x8F57EC; +float CTimeCycle::m_fCurrentAmbientRed; +float CTimeCycle::m_fCurrentAmbientGreen; +float CTimeCycle::m_fCurrentAmbientBlue; +float CTimeCycle::m_fCurrentDirectionalRed; +float CTimeCycle::m_fCurrentDirectionalGreen; +float CTimeCycle::m_fCurrentDirectionalBlue; +int CTimeCycle::m_nCurrentSkyTopRed; +int CTimeCycle::m_nCurrentSkyTopGreen; +int CTimeCycle::m_nCurrentSkyTopBlue; +int CTimeCycle::m_nCurrentSkyBottomRed; +int CTimeCycle::m_nCurrentSkyBottomGreen; +int CTimeCycle::m_nCurrentSkyBottomBlue; +int CTimeCycle::m_nCurrentSunCoreRed; +int CTimeCycle::m_nCurrentSunCoreGreen; +int CTimeCycle::m_nCurrentSunCoreBlue; +int CTimeCycle::m_nCurrentSunCoronaRed; +int CTimeCycle::m_nCurrentSunCoronaGreen; +int CTimeCycle::m_nCurrentSunCoronaBlue; +float CTimeCycle::m_fCurrentSunSize; +float CTimeCycle::m_fCurrentSpriteSize; +float CTimeCycle::m_fCurrentSpriteBrightness; +int CTimeCycle::m_nCurrentShadowStrength; +int CTimeCycle::m_nCurrentLightShadowStrength; +int CTimeCycle::m_nCurrentTreeShadowStrength; +float CTimeCycle::m_fCurrentFogStart; +float CTimeCycle::m_fCurrentFarClip; +float CTimeCycle::m_fCurrentLightsOnGroundBrightness; +int CTimeCycle::m_nCurrentLowCloudsRed; +int CTimeCycle::m_nCurrentLowCloudsGreen; +int CTimeCycle::m_nCurrentLowCloudsBlue; +int CTimeCycle::m_nCurrentFluffyCloudsTopRed; +int CTimeCycle::m_nCurrentFluffyCloudsTopGreen; +int CTimeCycle::m_nCurrentFluffyCloudsTopBlue; +int CTimeCycle::m_nCurrentFluffyCloudsBottomRed; +int CTimeCycle::m_nCurrentFluffyCloudsBottomGreen; +int CTimeCycle::m_nCurrentFluffyCloudsBottomBlue; +float CTimeCycle::m_fCurrentBlurRed; +float CTimeCycle::m_fCurrentBlurGreen; +float CTimeCycle::m_fCurrentBlurBlue; +float CTimeCycle::m_fCurrentBlurAlpha; +int CTimeCycle::m_nCurrentFogColourRed; +int CTimeCycle::m_nCurrentFogColourGreen; +int CTimeCycle::m_nCurrentFogColourBlue; -int &CTimeCycle::m_FogReduction = *(int*)0x880FB8; +int CTimeCycle::m_FogReduction; -int &CTimeCycle::m_CurrentStoredValue = *(int*)0x94057C; -CVector *CTimeCycle::m_VectorToSun = (CVector*)0x665548; // [16] -float *CTimeCycle::m_fShadowFrontX = (float*)0x72CE90; -float *CTimeCycle::m_fShadowFrontY = (float*)0x72CE50; -float *CTimeCycle::m_fShadowSideX = (float*)0x87C708; -float *CTimeCycle::m_fShadowSideY = (float*)0x87C6C8; -float *CTimeCycle::m_fShadowDisplacementX = (float*)0x6F0748; -float *CTimeCycle::m_fShadowDisplacementY = (float*)0x6F0788; +int CTimeCycle::m_CurrentStoredValue; +CVector CTimeCycle::m_VectorToSun[16]; +float CTimeCycle::m_fShadowFrontX[16]; +float CTimeCycle::m_fShadowFrontY[16]; +float CTimeCycle::m_fShadowSideX[16]; +float CTimeCycle::m_fShadowSideY[16]; +float CTimeCycle::m_fShadowDisplacementX[16]; +float CTimeCycle::m_fShadowDisplacementY[16]; void diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h index ed4a026b..28a0b7dd 100644 --- a/src/render/Timecycle.h +++ b/src/render/Timecycle.h @@ -2,102 +2,102 @@ class CTimeCycle { - static int (*m_nAmbientRed)[NUMWEATHERS]; - static int (*m_nAmbientGreen)[NUMWEATHERS]; - static int (*m_nAmbientBlue)[NUMWEATHERS]; - static int (*m_nDirectionalRed)[NUMWEATHERS]; - static int (*m_nDirectionalGreen)[NUMWEATHERS]; - static int (*m_nDirectionalBlue)[NUMWEATHERS]; - static int (*m_nSkyTopRed)[NUMWEATHERS]; - static int (*m_nSkyTopGreen)[NUMWEATHERS]; - static int (*m_nSkyTopBlue)[NUMWEATHERS]; - static int (*m_nSkyBottomRed)[NUMWEATHERS]; - static int (*m_nSkyBottomGreen)[NUMWEATHERS]; - static int (*m_nSkyBottomBlue)[NUMWEATHERS]; - static int (*m_nSunCoreRed)[NUMWEATHERS]; - static int (*m_nSunCoreGreen)[NUMWEATHERS]; - static int (*m_nSunCoreBlue)[NUMWEATHERS]; - static int (*m_nSunCoronaRed)[NUMWEATHERS]; - static int (*m_nSunCoronaGreen)[NUMWEATHERS]; - static int (*m_nSunCoronaBlue)[NUMWEATHERS]; - static float (*m_fSunSize)[NUMWEATHERS]; - static float (*m_fSpriteSize)[NUMWEATHERS]; - static float (*m_fSpriteBrightness)[NUMWEATHERS]; - static short (*m_nShadowStrength)[NUMWEATHERS]; - static short (*m_nLightShadowStrength)[NUMWEATHERS]; - static short (*m_nTreeShadowStrength)[NUMWEATHERS]; - static float (*m_fFogStart)[NUMWEATHERS]; - static float (*m_fFarClip)[NUMWEATHERS]; - static float (*m_fLightsOnGroundBrightness)[NUMWEATHERS]; - static int (*m_nLowCloudsRed)[NUMWEATHERS]; - static int (*m_nLowCloudsGreen)[NUMWEATHERS]; - static int (*m_nLowCloudsBlue)[NUMWEATHERS]; - static int (*m_nFluffyCloudsTopRed)[NUMWEATHERS]; - static int (*m_nFluffyCloudsTopGreen)[NUMWEATHERS]; - static int (*m_nFluffyCloudsTopBlue)[NUMWEATHERS]; - static int (*m_nFluffyCloudsBottomRed)[NUMWEATHERS]; - static int (*m_nFluffyCloudsBottomGreen)[NUMWEATHERS]; - static int (*m_nFluffyCloudsBottomBlue)[NUMWEATHERS]; - static float (*m_fBlurRed)[NUMWEATHERS]; - static float (*m_fBlurGreen)[NUMWEATHERS]; - static float (*m_fBlurBlue)[NUMWEATHERS]; - static float (*m_fBlurAlpha)[NUMWEATHERS]; + static int m_nAmbientRed[NUMHOURS][NUMWEATHERS]; + static int m_nAmbientGreen[NUMHOURS][NUMWEATHERS]; + static int m_nAmbientBlue[NUMHOURS][NUMWEATHERS]; + static int m_nDirectionalRed[NUMHOURS][NUMWEATHERS]; + static int m_nDirectionalGreen[NUMHOURS][NUMWEATHERS]; + static int m_nDirectionalBlue[NUMHOURS][NUMWEATHERS]; + static int m_nSkyTopRed[NUMHOURS][NUMWEATHERS]; + static int m_nSkyTopGreen[NUMHOURS][NUMWEATHERS]; + static int m_nSkyTopBlue[NUMHOURS][NUMWEATHERS]; + static int m_nSkyBottomRed[NUMHOURS][NUMWEATHERS]; + static int m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS]; + static int m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS]; + static int m_nSunCoreRed[NUMHOURS][NUMWEATHERS]; + static int m_nSunCoreGreen[NUMHOURS][NUMWEATHERS]; + static int m_nSunCoreBlue[NUMHOURS][NUMWEATHERS]; + static int m_nSunCoronaRed[NUMHOURS][NUMWEATHERS]; + static int m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS]; + static int m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS]; + static float m_fSunSize[NUMHOURS][NUMWEATHERS]; + static float m_fSpriteSize[NUMHOURS][NUMWEATHERS]; + static float m_fSpriteBrightness[NUMHOURS][NUMWEATHERS]; + static short m_nShadowStrength[NUMHOURS][NUMWEATHERS]; + static short m_nLightShadowStrength[NUMHOURS][NUMWEATHERS]; + static short m_nTreeShadowStrength[NUMHOURS][NUMWEATHERS]; + static float m_fFogStart[NUMHOURS][NUMWEATHERS]; + static float m_fFarClip[NUMHOURS][NUMWEATHERS]; + static float m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS]; + static int m_nLowCloudsRed[NUMHOURS][NUMWEATHERS]; + static int m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS]; + static int m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS]; + static int m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS]; + static int m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS]; + static int m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS]; + static int m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS]; + static int m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS]; + static int m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS]; + static float m_fBlurRed[NUMHOURS][NUMWEATHERS]; + static float m_fBlurGreen[NUMHOURS][NUMWEATHERS]; + static float m_fBlurBlue[NUMHOURS][NUMWEATHERS]; + static float m_fBlurAlpha[NUMHOURS][NUMWEATHERS]; - static float &m_fCurrentAmbientRed; - static float &m_fCurrentAmbientGreen; - static float &m_fCurrentAmbientBlue; - static float &m_fCurrentDirectionalRed; - static float &m_fCurrentDirectionalGreen; - static float &m_fCurrentDirectionalBlue; - static int &m_nCurrentSkyTopRed; - static int &m_nCurrentSkyTopGreen; - static int &m_nCurrentSkyTopBlue; - static int &m_nCurrentSkyBottomRed; - static int &m_nCurrentSkyBottomGreen; - static int &m_nCurrentSkyBottomBlue; - static int &m_nCurrentSunCoreRed; - static int &m_nCurrentSunCoreGreen; - static int &m_nCurrentSunCoreBlue; - static int &m_nCurrentSunCoronaRed; - static int &m_nCurrentSunCoronaGreen; - static int &m_nCurrentSunCoronaBlue; - static float &m_fCurrentSunSize; - static float &m_fCurrentSpriteSize; - static float &m_fCurrentSpriteBrightness; - static int &m_nCurrentShadowStrength; - static int &m_nCurrentLightShadowStrength; - static int &m_nCurrentTreeShadowStrength; - static float &m_fCurrentFogStart; - static float &m_fCurrentFarClip; - static float &m_fCurrentLightsOnGroundBrightness; - static int &m_nCurrentLowCloudsRed; - static int &m_nCurrentLowCloudsGreen; - static int &m_nCurrentLowCloudsBlue; - static int &m_nCurrentFluffyCloudsTopRed; - static int &m_nCurrentFluffyCloudsTopGreen; - static int &m_nCurrentFluffyCloudsTopBlue; - static int &m_nCurrentFluffyCloudsBottomRed; - static int &m_nCurrentFluffyCloudsBottomGreen; - static int &m_nCurrentFluffyCloudsBottomBlue; - static float &m_fCurrentBlurRed; - static float &m_fCurrentBlurGreen; - static float &m_fCurrentBlurBlue; - static float &m_fCurrentBlurAlpha; - static int &m_nCurrentFogColourRed; - static int &m_nCurrentFogColourGreen; - static int &m_nCurrentFogColourBlue; + static float m_fCurrentAmbientRed; + static float m_fCurrentAmbientGreen; + static float m_fCurrentAmbientBlue; + static float m_fCurrentDirectionalRed; + static float m_fCurrentDirectionalGreen; + static float m_fCurrentDirectionalBlue; + static int m_nCurrentSkyTopRed; + static int m_nCurrentSkyTopGreen; + static int m_nCurrentSkyTopBlue; + static int m_nCurrentSkyBottomRed; + static int m_nCurrentSkyBottomGreen; + static int m_nCurrentSkyBottomBlue; + static int m_nCurrentSunCoreRed; + static int m_nCurrentSunCoreGreen; + static int m_nCurrentSunCoreBlue; + static int m_nCurrentSunCoronaRed; + static int m_nCurrentSunCoronaGreen; + static int m_nCurrentSunCoronaBlue; + static float m_fCurrentSunSize; + static float m_fCurrentSpriteSize; + static float m_fCurrentSpriteBrightness; + static int m_nCurrentShadowStrength; + static int m_nCurrentLightShadowStrength; + static int m_nCurrentTreeShadowStrength; + static float m_fCurrentFogStart; + static float m_fCurrentFarClip; + static float m_fCurrentLightsOnGroundBrightness; + static int m_nCurrentLowCloudsRed; + static int m_nCurrentLowCloudsGreen; + static int m_nCurrentLowCloudsBlue; + static int m_nCurrentFluffyCloudsTopRed; + static int m_nCurrentFluffyCloudsTopGreen; + static int m_nCurrentFluffyCloudsTopBlue; + static int m_nCurrentFluffyCloudsBottomRed; + static int m_nCurrentFluffyCloudsBottomGreen; + static int m_nCurrentFluffyCloudsBottomBlue; + static float m_fCurrentBlurRed; + static float m_fCurrentBlurGreen; + static float m_fCurrentBlurBlue; + static float m_fCurrentBlurAlpha; + static int m_nCurrentFogColourRed; + static int m_nCurrentFogColourGreen; + static int m_nCurrentFogColourBlue; - static int &m_FogReduction; + static int m_FogReduction; public: - static int &m_CurrentStoredValue; - static CVector *m_VectorToSun; // [16] - static float *m_fShadowFrontX; // [16] - static float *m_fShadowFrontY; // [16] - static float *m_fShadowSideX; // [16] - static float *m_fShadowSideY; // [16] - static float *m_fShadowDisplacementX; // [16] - static float *m_fShadowDisplacementY; // [16] + static int m_CurrentStoredValue; + static CVector m_VectorToSun[16]; + static float m_fShadowFrontX[16]; + static float m_fShadowFrontY[16]; + static float m_fShadowSideX[16]; + static float m_fShadowSideY[16]; + static float m_fShadowDisplacementX[16]; + static float m_fShadowDisplacementY[16]; static float GetAmbientRed(void) { return m_fCurrentAmbientRed; } static float GetAmbientGreen(void) { return m_fCurrentAmbientGreen; } diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index a1c2af93..d5a54742 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -39,8 +39,8 @@ int16 CWaterLevel::nGeomUsed; //RwTexture *gpWaterTex; //RwRaster *gpWaterRaster; -RwTexture *&gpWaterTex = *(RwTexture **)0x64D070; -RwRaster *&gpWaterRaster = *(RwRaster **)0x8F5FD4; +RwTexture *gpWaterTex; +RwRaster *gpWaterRaster; const float fAdd1 = 180.0f; diff --git a/src/render/WaterLevel.h b/src/render/WaterLevel.h index 827e83d2..a471bc52 100644 --- a/src/render/WaterLevel.h +++ b/src/render/WaterLevel.h @@ -64,7 +64,7 @@ #define MAX_BOAT_WAKES 8 -extern RwRaster*& gpWaterRaster; +extern RwRaster* gpWaterRaster; class CWaterLevel { diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index 7aa2778f..1aa6be82 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -18,35 +18,35 @@ #include "World.h" #include "ZoneCull.h" -int32 &CWeather::SoundHandle = *(int32*)0x5FFBC4; +int32 CWeather::SoundHandle = -1; -int32 &CWeather::WeatherTypeInList = *(int32*)0x8F626C; -int16 &CWeather::OldWeatherType = *(int16*)0x95CCEC; -int16 &CWeather::NewWeatherType = *(int16*)0x95CC70; -int16 &CWeather::ForcedWeatherType = *(int16*)0x95CC80; +int32 CWeather::WeatherTypeInList; +int16 CWeather::OldWeatherType; +int16 CWeather::NewWeatherType; +int16 CWeather::ForcedWeatherType; -bool &CWeather::LightningFlash = *(bool*)0x95CDA3; -bool &CWeather::LightningBurst = *(bool*)0x95CDAC; -uint32 &CWeather::LightningStart = *(uint32*)0x8F5F84; -uint32 &CWeather::LightningFlashLastChange = *(uint32*)0x8E2C0C; -uint32 &CWeather::WhenToPlayLightningSound = *(uint32*)0x8F57E4; -uint32 &CWeather::LightningDuration = *(uint32*)0x940578; +bool CWeather::LightningFlash; +bool CWeather::LightningBurst; +uint32 CWeather::LightningStart; +uint32 CWeather::LightningFlashLastChange; +uint32 CWeather::WhenToPlayLightningSound; +uint32 CWeather::LightningDuration; -float &CWeather::Foggyness = *(float*)0x885AF4; -float &CWeather::CloudCoverage = *(float*)0x8E2818; -float &CWeather::Wind = *(float*)0x8E2BF8; -float &CWeather::Rain = *(float*)0x8E2BFC; -float &CWeather::InterpolationValue = *(float*)0x8F2520; -float &CWeather::WetRoads = *(float*)0x8F5FF8; -float &CWeather::Rainbow = *(float*)0x940598; +float CWeather::Foggyness; +float CWeather::CloudCoverage; +float CWeather::Wind; +float CWeather::Rain; +float CWeather::InterpolationValue; +float CWeather::WetRoads; +float CWeather::Rainbow; -bool &CWeather::bScriptsForceRain = *(bool*)0x95CD7D; -bool &CWeather::Stored_StateStored = *(bool*)0x95CDC1; +bool CWeather::bScriptsForceRain; +bool CWeather::Stored_StateStored; -float &CWeather::Stored_InterpolationValue = *(float*)0x942F54; -int16 &CWeather::Stored_OldWeatherType = *(int16*)0x95CC68; -int16 &CWeather::Stored_NewWeatherType = *(int16*)0x95CCAE; -float &CWeather::Stored_Rain = *(float*)0x885B4C; +float CWeather::Stored_InterpolationValue; +int16 CWeather::Stored_OldWeatherType; +int16 CWeather::Stored_NewWeatherType; +float CWeather::Stored_Rain; tRainStreak Streaks[NUM_RAIN_STREAKS]; diff --git a/src/render/Weather.h b/src/render/Weather.h index 9e4ea378..9c670317 100644 --- a/src/render/Weather.h +++ b/src/render/Weather.h @@ -16,34 +16,34 @@ public: WEATHER_FOGGY = 3, WEATHER_TOTAL = 4 }; - static int32 &SoundHandle; + static int32 SoundHandle; - static int32 &WeatherTypeInList; - static int16 &OldWeatherType; - static int16 &NewWeatherType; - static int16 &ForcedWeatherType; + static int32 WeatherTypeInList; + static int16 OldWeatherType; + static int16 NewWeatherType; + static int16 ForcedWeatherType; - static bool &LightningFlash; - static bool &LightningBurst; - static uint32 &LightningStart; - static uint32 &LightningFlashLastChange; - static uint32 &WhenToPlayLightningSound; - static uint32 &LightningDuration; + static bool LightningFlash; + static bool LightningBurst; + static uint32 LightningStart; + static uint32 LightningFlashLastChange; + static uint32 WhenToPlayLightningSound; + static uint32 LightningDuration; - static float &Foggyness; - static float &CloudCoverage; - static float &Wind; - static float &Rain; - static float &InterpolationValue; - static float &WetRoads; - static float &Rainbow; + static float Foggyness; + static float CloudCoverage; + static float Wind; + static float Rain; + static float InterpolationValue; + static float WetRoads; + static float Rainbow; - static bool &bScriptsForceRain; - static bool &Stored_StateStored; - static float &Stored_InterpolationValue; - static int16 &Stored_OldWeatherType; - static int16 &Stored_NewWeatherType; - static float &Stored_Rain; + static bool bScriptsForceRain; + static bool Stored_StateStored; + static float Stored_InterpolationValue; + static int16 Stored_OldWeatherType; + static int16 Stored_NewWeatherType; + static float Stored_Rain; static void RenderRainStreaks(void); static void Update(void); @@ -68,4 +68,4 @@ struct tRainStreak uint32 timer; }; -extern RwTexture* (&gpRainDropTex)[4]; \ No newline at end of file +extern RwTexture* gpRainDropTex[4]; \ No newline at end of file diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp index 112c8982..6e9edbed 100644 --- a/src/rw/Lights.cpp +++ b/src/rw/Lights.cpp @@ -9,18 +9,18 @@ #include "ZoneCull.h" #include "Frontend.h" -RpLight *pAmbient;// = *(RpLight**)0x885B6C; -RpLight *pDirect;// = *(RpLight**)0x880F7C; -RpLight *pExtraDirectionals[] = { nil, nil, nil, nil };// = (RpLight**)0x60009C; -int LightStrengths[4];// = (int*)0x87BEF0; -int NumExtraDirLightsInWorld;// = *(int*)0x64C608; +RpLight *pAmbient; +RpLight *pDirect; +RpLight *pExtraDirectionals[] = { nil }; +int LightStrengths[4]; +int NumExtraDirLightsInWorld; -RwRGBAReal AmbientLightColourForFrame;// = *(RwRGBAReal*)0x6F46F8; -RwRGBAReal AmbientLightColourForFrame_PedsCarsAndObjects;// = *(RwRGBAReal*)0x6F1D10; -RwRGBAReal DirectionalLightColourForFrame;// = *(RwRGBAReal*)0x87C6B8; +RwRGBAReal AmbientLightColourForFrame; +RwRGBAReal AmbientLightColourForFrame_PedsCarsAndObjects; +RwRGBAReal DirectionalLightColourForFrame; -RwRGBAReal AmbientLightColour;// = *(RwRGBAReal*)0x86B0F8; -RwRGBAReal DirectionalLightColour;// = *(RwRGBAReal*)0x72E308; +RwRGBAReal AmbientLightColour; +RwRGBAReal DirectionalLightColour; void SetLightsWithTimeOfDayColour(RpWorld *) diff --git a/src/rw/NodeName.cpp b/src/rw/NodeName.cpp index 7422a323..b3477dba 100644 --- a/src/rw/NodeName.cpp +++ b/src/rw/NodeName.cpp @@ -2,7 +2,7 @@ #include "patcher.h" #include "NodeName.h" -static int32 gPluginOffset;// = *(int32*)0x64C610; +static int32 gPluginOffset; enum { diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index cf1a6f2b..6bb78e7b 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -389,8 +389,10 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer) return (nil); } +#ifdef USE_TEXTURE_POOL WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); } WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); } +#endif STARTPATCHES //InjectHook(0x526450, GetFirstObjectCallback, PATCH_JUMP); diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 1ac5a75e..64fea20f 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -22,8 +22,8 @@ #include "RwHelper.h" #endif //GTA_PC -float texLoadTime;// = *(float*)0x8F1B50; -int32 texNumLoaded;// = *(int32*)0x8F252C; +float texLoadTime; +int32 texNumLoaded; #ifdef LIBRW #define READNATIVE(stream, tex, size) rwNativeTextureHackRead(stream, tex, size) diff --git a/src/rw/TxdStore.cpp b/src/rw/TxdStore.cpp index a32755a4..d640d99d 100644 --- a/src/rw/TxdStore.cpp +++ b/src/rw/TxdStore.cpp @@ -6,8 +6,8 @@ #include "RwHelper.h" #include "TxdStore.h" -CPool *CTxdStore::ms_pTxdPool;// = *(CPool**)0x8F5FB8; -RwTexDictionary *CTxdStore::ms_pStoredTxd;// = *(RwTexDictionary**)0x9405BC; +CPool *CTxdStore::ms_pTxdPool; +RwTexDictionary *CTxdStore::ms_pStoredTxd; void CTxdStore::Initialise(void) diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 5438ed0f..b7afd751 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -11,24 +11,24 @@ #define FADE_DISTANCE 20.0f -CLinkList CVisibilityPlugins::m_alphaList;// = *(CLinkList*)0x8F42E4; -CLinkList CVisibilityPlugins::m_alphaEntityList;// = *(CLinkList*)0x943084; +CLinkList CVisibilityPlugins::m_alphaList; +CLinkList CVisibilityPlugins::m_alphaEntityList; -int32 CVisibilityPlugins::ms_atomicPluginOffset = -1;// = *(int32*)0x600124; -int32 CVisibilityPlugins::ms_framePluginOffset = -1;// = *(int32*)0x600128; -int32 CVisibilityPlugins::ms_clumpPluginOffset = -1;// = *(int32*)0x60012C; +int32 CVisibilityPlugins::ms_atomicPluginOffset = -1; +int32 CVisibilityPlugins::ms_framePluginOffset = -1; +int32 CVisibilityPlugins::ms_clumpPluginOffset = -1; -RwCamera *CVisibilityPlugins::ms_pCamera;// = *(RwCamera**)0x8F2514; -RwV3d *CVisibilityPlugins::ms_pCameraPosn;// = *(RwV3d**)0x8F6270; -float CVisibilityPlugins::ms_cullCompsDist;// = *(float*)0x8F2BC4; -float CVisibilityPlugins::ms_vehicleLod0Dist;// = *(float*)0x885B28; -float CVisibilityPlugins::ms_vehicleLod1Dist;// = *(float*)0x885B30; -float CVisibilityPlugins::ms_vehicleFadeDist;// = *(float*)0x8E28B4; -float CVisibilityPlugins::ms_bigVehicleLod0Dist;// = *(float*)0x8E2A84; -float CVisibilityPlugins::ms_bigVehicleLod1Dist;// = *(float*)0x8E2A8C; -float CVisibilityPlugins::ms_pedLod0Dist;// = *(float*)0x8F2BD4; -float CVisibilityPlugins::ms_pedLod1Dist;// = *(float*)0x8F2BD8; -float CVisibilityPlugins::ms_pedFadeDist;// = *(float*)0x8E2C34; +RwCamera *CVisibilityPlugins::ms_pCamera; +RwV3d *CVisibilityPlugins::ms_pCameraPosn; +float CVisibilityPlugins::ms_cullCompsDist; +float CVisibilityPlugins::ms_vehicleLod0Dist; +float CVisibilityPlugins::ms_vehicleLod1Dist; +float CVisibilityPlugins::ms_vehicleFadeDist; +float CVisibilityPlugins::ms_bigVehicleLod0Dist; +float CVisibilityPlugins::ms_bigVehicleLod1Dist; +float CVisibilityPlugins::ms_pedLod0Dist; +float CVisibilityPlugins::ms_pedLod1Dist; +float CVisibilityPlugins::ms_pedFadeDist; void CVisibilityPlugins::Initialise(void) diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 0bae979b..88f32c33 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -40,22 +40,22 @@ const uint32 SIZE_OF_ONE_GAME_IN_BYTES = 201729; -char DefaultPCSaveFileName[260];// = *(char(*)[260]) * (uintptr*)0x8E28C0; -char ValidSaveName[260];// = *(char(*)[260])*(uintptr*)0x8E2CBC; -char LoadFileName[256];// = *(char(*)[256])*(uintptr*)0x9403C4; -wchar SlotFileName[SLOT_COUNT][260];// = *(wchar(*)[SLOT_COUNT][260])*(uintptr*)0x6F07C8; -wchar SlotSaveDate[SLOT_COUNT][70];// = *(wchar(*)[SLOT_COUNT][70])*(uintptr*)0x72B858; -int CheckSum;// = *(int*)0x8E2BE0; -eLevelName m_LevelToLoad;// = *(eLevelName*)0x8E29CC; +char DefaultPCSaveFileName[260]; +char ValidSaveName[260]; +char LoadFileName[256]; +wchar SlotFileName[SLOT_COUNT][260]; +wchar SlotSaveDate[SLOT_COUNT][70]; +int CheckSum; +eLevelName m_LevelToLoad; char SaveFileNameJustSaved[260]; -int Slots[SLOT_COUNT+1];// = *(int(*)[SLOT_COUNT+1])*(uintptr*)0x72803C; -CDate CompileDateAndTime;// = *(CDate*)0x72BCB8; +int Slots[SLOT_COUNT+1]; +CDate CompileDateAndTime; -bool b_FoundRecentSavedGameWantToLoad;// = *(bool*)0x95CDA8; -bool JustLoadedDontFadeInYet;// = *(bool*)0x95CDB4; -bool StillToFadeOut;// = *(bool*)0x95CD99; -uint32 TimeStartedCountingForFade;// = *(uint32*)0x9430EC; -uint32 TimeToStayFadedBeforeFadeOut = 1750;// = *(uint32*)0x611564; +bool b_FoundRecentSavedGameWantToLoad; +bool JustLoadedDontFadeInYet; +bool StillToFadeOut; +uint32 TimeStartedCountingForFade; +uint32 TimeToStayFadedBeforeFadeOut = 1750; #define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to)); #define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from)); diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 4afcb645..06024e04 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -9,7 +9,7 @@ const char* _psGetUserFilesFolder(); -C_PcSave PcSaveHelper;// = *(C_PcSave*)0x8E2C60; +C_PcSave PcSaveHelper; void C_PcSave::SetSaveDirectory(const char *path) diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index 73dd8bf8..a02d7e0b 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -17,8 +17,7 @@ static RwBool DefaultVideoMode = TRUE; bool TurnOnAnimViewer = false; -//RsGlobalType RsGlobal; -RsGlobalType &RsGlobal = *(RsGlobalType*)0x8F4360; +RsGlobalType RsGlobal; RwUInt32 RsTimer(void) diff --git a/src/skel/skeleton.h b/src/skel/skeleton.h index 6bf8d2fd..13588411 100644 --- a/src/skel/skeleton.h +++ b/src/skel/skeleton.h @@ -232,7 +232,7 @@ enum RsPadButtons typedef enum RsPadButtons RsPadButtons; -extern RsGlobalType &RsGlobal; +extern RsGlobalType RsGlobal; extern RsEventStatus AppEventHandler(RsEvent event, void *param); extern RwBool AttachInputDevices(void); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index acc9650c..351b7247 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -45,31 +45,25 @@ #define MAX_SUBSYSTEMS (16) -//static RwBool ForegroundApp = TRUE; -static RwBool &ForegroundApp = *(RwBool*)0x060F000; +static RwBool ForegroundApp = TRUE; -//static RwBool RwInitialised = FALSE; -static RwBool &RwInitialised = *(RwBool*)0x885B88; +static RwBool RwInitialised = FALSE; static RwSubSystemInfo GsubSysInfo[MAX_SUBSYSTEMS]; static RwInt32 GnumSubSystems = 0; static RwInt32 GcurSel = 0, GcurSelVM = 0; -//static RwBool startupDeactivate; -static RwBool &startupDeactivate = *(RwBool*)0x8E2878; +static RwBool startupDeactivate; -//static RwBool useDefault; -static RwBool &useDefault = *(RwBool*)0x6510D4; +static RwBool useDefault; -//static RwBool defaultFullscreenRes = TRUE; -static RwBool &defaultFullscreenRes = *(RwBool*)0x60EFFC; +static RwBool defaultFullscreenRes = TRUE; /* Class name for the MS Window's window class. */ static const RwChar *AppClassName = RWSTRING("Grand theft auto 3"); -//static psGlobalType PsGlobal; -static psGlobalType &PsGlobal = *(psGlobalType*)0x72CF60; +static psGlobalType PsGlobal; #define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var) @@ -107,14 +101,14 @@ IMediaSeeking *pMS = nil; DWORD dwDXVersion; DWORD _dwMemTotalPhys; -DWORD &_dwMemAvailPhys = *(DWORD*)0x70F29C; +DWORD _dwMemAvailPhys; DWORD _dwMemTotalVirtual; DWORD _dwMemAvailVirtual; -DWORD &_dwMemTotalVideo = *(DWORD*)0x70F2A8; +DWORD _dwMemTotalVideo; DWORD _dwMemAvailVideo; -DWORD &_dwOperatingSystemVersion = *(DWORD*)0x70F290; +DWORD _dwOperatingSystemVersion; -RwUInt32 &gGameState = *(RwUInt32*)0x8F5838; +RwUInt32 gGameState; CJoySticks AllValidWinJoys; CJoySticks::CJoySticks() diff --git a/src/skel/win/win.h b/src/skel/win/win.h index 242438ea..ca16c4a0 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -29,9 +29,9 @@ enum eWinVersion OS_WINXP, }; -extern DWORD &_dwOperatingSystemVersion; +extern DWORD _dwOperatingSystemVersion; -extern RwUInt32 &gGameState; +extern RwUInt32 gGameState; /* platform specfic global data */ typedef struct @@ -127,5 +127,5 @@ void HandleExit(); #endif /* __cplusplus */ -extern DWORD &_dwOperatingSystemVersion; +extern DWORD _dwOperatingSystemVersion; #endif /* (!defined(_PLATFORM_WIN_H)) */ diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp index 4b181d67..67a7bab4 100644 --- a/src/text/Messages.cpp +++ b/src/text/Messages.cpp @@ -12,9 +12,9 @@ #include "ControllerConfig.h" -tMessage CMessages::BriefMessages[NUMBRIEFMESSAGES];// = *(tMessage(*)[NUMBRIEFMESSAGES]) * (uintptr*)0x8786E0; -tPreviousBrief CMessages::PreviousBriefs[NUMPREVIOUSBRIEFS];// = *(tPreviousBrief(*)[NUMPREVIOUSBRIEFS]) * (uintptr*)0x713C08; -tBigMessage CMessages::BIGMessages[NUMBIGMESSAGES];// = *(tBigMessage(*)[NUMBIGMESSAGES]) * (uintptr*)0x773628; +tMessage CMessages::BriefMessages[NUMBRIEFMESSAGES]; +tPreviousBrief CMessages::PreviousBriefs[NUMPREVIOUSBRIEFS]; +tBigMessage CMessages::BIGMessages[NUMBIGMESSAGES]; char CMessages::PreviousMissionTitle[16]; // unused void diff --git a/src/text/Text.cpp b/src/text/Text.cpp index b3da27e8..144dfed1 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -7,7 +7,7 @@ static wchar WideErrorString[25]; -CText TheText;// = *(CText*)0x941520; +CText TheText; CText::CText(void) { diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 12d4f589..0a0bc7a6 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -49,7 +49,7 @@ bool bAllCarCheat; // unused RwObject *GetCurrentAtomicObjectCB(RwObject *object, void *data); -bool CAutomobile::m_sAllTaxiLights;// = *(bool*)0x95CD21; +bool CAutomobile::m_sAllTaxiLights; CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) : CVehicle(CreatedBy) diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index d694d8b0..478257b6 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -21,16 +21,16 @@ #define INVALID_ORIENTATION (-9999.99f) -float fShapeLength = 0.4f;// *(float*)0x600E78; -float fShapeTime = 0.05f;// *(float*)0x600E7C; -float fRangeMult = 0.75f; // = *(float*)0x600E80; //0.6f; // 0.75f gta 3 -float fTimeMult;// = *(float*)0x943008; +float fShapeLength = 0.4f; +float fShapeTime = 0.05f; +float fRangeMult = 0.75f; //0.6f; // 0.75f gta 3 +float fTimeMult; float MAX_WAKE_LENGTH = 50.0f; float MIN_WAKE_INTERVAL = 1.0f; float WAKE_LIFETIME = 400.0f; -CBoat *CBoat::apFrameWakeGeneratingBoats[4];// = *(CBoat * (*)[4]) * (uintptr*)0x8620E0; +CBoat *CBoat::apFrameWakeGeneratingBoats[4]; CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) { diff --git a/src/vehicles/Floater.cpp b/src/vehicles/Floater.cpp index ee4a1191..8b5e1e0a 100644 --- a/src/vehicles/Floater.cpp +++ b/src/vehicles/Floater.cpp @@ -7,9 +7,9 @@ #include "Vehicle.h" #include "Floater.h" -cBuoyancy mod_Buoyancy;// = *(cBuoyancy*)0x8F2674; +cBuoyancy mod_Buoyancy; -static float fVolMultiplier = 1.0f; // 0x601394; +static float fVolMultiplier = 1.0f; // amount of boat volume in bounding box // 1.0-volume is the empty space in the bbox static float fBoatVolumeDistribution[9] = { diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index 40715887..b33015ab 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -4,7 +4,7 @@ #include "FileMgr.h" #include "HandlingMgr.h" -cHandlingDataMgr mod_HandlingManager;// = *(cHandlingDataMgr*)0x728060; +cHandlingDataMgr mod_HandlingManager; const char *HandlingFilename = "HANDLING.CFG"; diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 61714133..81ac9bd3 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -34,13 +34,13 @@ enum HELI_STATUS_HOVER2, }; -CHeli *CHeli::pHelis[NUM_HELIS];// = (CHeli**)0x72CF50; -int16 CHeli::NumRandomHelis;// = *(int16*)0x95CCAA; -uint32 CHeli::TestForNewRandomHelisTimer;// = *(uint32*)0x8F1A7C; +CHeli *CHeli::pHelis[NUM_HELIS]; +int16 CHeli::NumRandomHelis; +uint32 CHeli::TestForNewRandomHelisTimer; int16 CHeli::NumScriptHelis; // unused -bool CHeli::CatalinaHeliOn;// = *(bool*)0x95CD85; -bool CHeli::CatalinaHasBeenShotDown;// = *(bool*)0x95CD56; -bool CHeli::ScriptHeliOn;// = *(bool*)0x95CD43; +bool CHeli::CatalinaHeliOn; +bool CHeli::CatalinaHasBeenShotDown; +bool CHeli::ScriptHeliOn; CHeli::CHeli(int32 id, uint8 CreatedBy) : CVehicle(CreatedBy) diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 49f5d69d..892bc0d5 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -16,35 +16,35 @@ #include "HandlingMgr.h" #include "Plane.h" -CPlaneNode *pPathNodes;// = *(CPlaneNode**)0x8F1B68; -CPlaneNode *pPath2Nodes;// = *(CPlaneNode**)0x885B8C; -CPlaneNode *pPath3Nodes;// = *(CPlaneNode**)0x885B78; -CPlaneNode *pPath4Nodes;// = *(CPlaneNode**)0x885AD8; -int32 NumPathNodes;// = *(int32*)0x8F2BE4; -int32 NumPath2Nodes;// = *(int32*)0x941498; -int32 NumPath3Nodes;// = *(int32*)0x9414D8; -int32 NumPath4Nodes;// = *(int32*)0x9412C8; -float TotalLengthOfFlightPath;// = *(float*)0x8F2C6C; -float TotalLengthOfFlightPath2;// = *(float*)0x64CFBC; -float TotalLengthOfFlightPath3;// = *(float*)0x64CFD0; -float TotalLengthOfFlightPath4;// = *(float*)0x64CFDC; -float TotalDurationOfFlightPath;// = *(float*)0x64CFB8; -float TotalDurationOfFlightPath2;// = *(float*)0x64CFC0; -float TotalDurationOfFlightPath3;// = *(float*)0x64CFD4; -float TotalDurationOfFlightPath4;// = *(float*)0x64CFE0; -float LandingPoint;// = *(float*)0x8F2C7C; -float TakeOffPoint;// = *(float*)0x8E28A4; -CPlaneInterpolationLine aPlaneLineBits[6]; // = (CPlaneInterpolationLine*)0x734168; +CPlaneNode *pPathNodes; +CPlaneNode *pPath2Nodes; +CPlaneNode *pPath3Nodes; +CPlaneNode *pPath4Nodes; +int32 NumPathNodes; +int32 NumPath2Nodes; +int32 NumPath3Nodes; +int32 NumPath4Nodes; +float TotalLengthOfFlightPath; +float TotalLengthOfFlightPath2; +float TotalLengthOfFlightPath3; +float TotalLengthOfFlightPath4; +float TotalDurationOfFlightPath; +float TotalDurationOfFlightPath2; +float TotalDurationOfFlightPath3; +float TotalDurationOfFlightPath4; +float LandingPoint; +float TakeOffPoint; +CPlaneInterpolationLine aPlaneLineBits[6]; -float PlanePathPosition[3];// = (float*)0x8F5FC8; //[3] -float OldPlanePathPosition[3];// = (float*)0x8F5FBC; //[3] -float PlanePathSpeed[3];// = (float*)0x941538; //[3] -float PlanePath2Position[3];// = (float*)0x64CFC4; //[3] -float PlanePath3Position;// = *(float*)0x64CFD8; -float PlanePath4Position;// = *(float*)0x64CFE4; -float PlanePath2Speed[3];// = (float*)0x8F1A54; //[3] -float PlanePath3Speed;// = *(float*)0x8F1A94; -float PlanePath4Speed;// = *(float*)0x8F1AFC; +float PlanePathPosition[3]; +float OldPlanePathPosition[3]; +float PlanePathSpeed[3]; +float PlanePath2Position[3]; +float PlanePath3Position; +float PlanePath4Position; +float PlanePath2Speed[3]; +float PlanePath3Speed; +float PlanePath4Speed; enum @@ -55,12 +55,12 @@ enum CESNA_STATUS_LANDED, }; -int32 &CesnaMissionStatus = *(int32*)0x64CFE8; -int32 &CesnaMissionStartTime = *(int32*)0x64CFEC; -CPlane *&pDrugRunCesna = *(CPlane**)0x8F5F80; -int32 &DropOffCesnaMissionStatus = *(int32*)0x64CFF0; -int32 &DropOffCesnaMissionStartTime = *(int32*)0x64CFF4; -CPlane *&pDropOffCesna = *(CPlane**)0x8E2A38; +int32 CesnaMissionStatus; +int32 CesnaMissionStartTime; +CPlane *pDrugRunCesna; +int32 DropOffCesnaMissionStatus; +int32 DropOffCesnaMissionStartTime; +CPlane *pDropOffCesna; CPlane::CPlane(int32 id, uint8 CreatedBy) diff --git a/src/weapons/ShotInfo.cpp b/src/weapons/ShotInfo.cpp index 43d0579d..1eae5e87 100644 --- a/src/weapons/ShotInfo.cpp +++ b/src/weapons/ShotInfo.cpp @@ -13,8 +13,6 @@ CShotInfo gaShotInfo[NUMSHOTINFOS]; float CShotInfo::ms_afRandTable[20]; -// CShotInfo (&gaShotInfo)[100] = *(CShotInfo(*)[100])*(uintptr*)0x64F0D0; -// float (&CShotInfo::ms_afRandTable)[20] = *(float(*)[20])*(uintptr*)0x6E9878; /* Used for flamethrower. I don't know why it's name is CShotInfo. diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index a4a1a085..dca120a3 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -7,7 +7,6 @@ #include "AnimBlendAssociation.h" #include "Weapon.h" -//CWeaponInfo (&CWeaponInfo::ms_apWeaponInfos)[14] = * (CWeaponInfo(*)[14]) * (uintptr*)0x6503EC; CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS]; static char ms_aWeaponNames[][32] = { From fd229ed47e4e3a8074f89f3444c91e312bfb713d Mon Sep 17 00:00:00 2001 From: Sergey P Date: Fri, 17 Apr 2020 11:09:26 +0300 Subject: [PATCH 050/123] librw submodule --- .gitmodules | 3 +++ librw | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 librw diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..fec30cac --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "librw"] + path = librw + url = https://github.com/aap/librw diff --git a/librw b/librw new file mode 160000 index 00000000..7bd6d464 --- /dev/null +++ b/librw @@ -0,0 +1 @@ +Subproject commit 7bd6d4649e575e0a2a5f046fdf0d687cea87ca84 From ce7d6848ba0ffabb6616502c1a18ec2fb2af4259 Mon Sep 17 00:00:00 2001 From: saml1er Date: Fri, 17 Apr 2020 16:13:55 +0500 Subject: [PATCH 051/123] CWorld fixes --- src/core/World.cpp | 371 ++++++++++++++++++--------------------------- 1 file changed, 151 insertions(+), 220 deletions(-) diff --git a/src/core/World.cpp b/src/core/World.cpp index 02c0e2f6..f0b290a3 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -731,11 +731,10 @@ CWorld::FindObjectsInRange(CVector ¢re, float radius, bool ignoreZ, short *n void CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities) { - CPtrNode* pNode = list.first; - while (pNode) { + for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != ms_nCurrentScanCode) { - pEntity->m_scanCode = ms_nCurrentScanCode; + if (pEntity->m_scanCode != GetCurrentScanCode()) { + pEntity->m_scanCode = GetCurrentScanCode(); float fMagnitude = 0.0f; if (bCheck2DOnly) fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr2D(); @@ -747,7 +746,6 @@ CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const ++*nEntitiesFound; } } - pNode = pNode->next; } } @@ -1037,11 +1035,10 @@ CWorld::FindObjectsKindaColliding(const CVector& position, float radius, bool bC void CWorld::FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities) { - CPtrNode* pNode = list.first; - while (pNode) { + for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != ms_nCurrentScanCode) { - pEntity->m_scanCode = ms_nCurrentScanCode; + if (pEntity->m_scanCode != GetCurrentScanCode()) { + pEntity->m_scanCode = GetCurrentScanCode(); float fMagnitude = 0.0f; if (bCheck2DOnly) fMagnitude = (position - pEntity->GetPosition()).Magnitude2D(); @@ -1053,7 +1050,6 @@ CWorld::FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& posit ++*nCollidingEntities; } } - pNode = pNode->next; } } @@ -1097,11 +1093,10 @@ CWorld::FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& v void CWorld::FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities) { - CPtrNode* pNode = list.first; - while (pNode) { + for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { - pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + if (pEntity->m_scanCode != GetCurrentScanCode()) { + pEntity->m_scanCode = GetCurrentScanCode(); float fRadius = pEntity->GetBoundRadius(); const CVector& entityPos = pEntity->GetPosition(); if (fRadius + entityPos.x >= vecStartPos.x && entityPos.x - fRadius <= vecEndPos.x && @@ -1113,7 +1108,6 @@ CWorld::FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vec ++*nIntersecting; } } - pNode = pNode->next; } } @@ -1156,11 +1150,10 @@ CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox& boundingBox, co void CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities) { - CPtrNode* pNode = list.first; - while (pNode) { + for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { - pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + if (pEntity->m_scanCode != GetCurrentScanCode()) { + pEntity->m_scanCode = GetCurrentScanCode(); CColSphere sphere; CVector vecDistance = pEntity->GetPosition() - position; sphere.radius = pEntity->GetBoundRadius(); @@ -1171,7 +1164,6 @@ CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, cons ++*nEntitiesFound; } } - pNode = pNode->next; } } @@ -1206,11 +1198,10 @@ CWorld::FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CV void CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList) { - CPtrNode* pNode = list.first; - while (pNode) { + for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { - pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + if (pEntity->m_scanCode != GetCurrentScanCode()) { + pEntity->m_scanCode = GetCurrentScanCode(); bool bIsMissionEntity = false; if (bIsVehicleList) bIsMissionEntity = ((CVehicle*)pEntity)->VehicleCreatedBy == MISSION_VEHICLE; @@ -1230,7 +1221,6 @@ CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVec ++*nIntersecting; } } - pNode = pNode->next; } } @@ -1397,11 +1387,10 @@ CWorld::CallOffChaseForArea(float x1, float y1, float x2, float y2) void CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY) { - CPtrNode* pNode = list.first; - while (pNode) { + for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { CVehicle *pVehicle = (CVehicle*)pNode->item; - if (pVehicle->m_scanCode != CWorld::ms_nCurrentScanCode) { - pVehicle->m_scanCode = CWorld::ms_nCurrentScanCode; + if (pVehicle->m_scanCode != GetCurrentScanCode()) { + pVehicle->m_scanCode = GetCurrentScanCode(); const CVector& vehiclePos = pVehicle->GetPosition(); eCarMission carMission = pVehicle->AutoPilot.m_nCarMission; if (pVehicle != FindPlayerVehicle() && @@ -1411,42 +1400,40 @@ CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1 (carMission == MISSION_RAMPLAYER_FARAWAY || carMission == MISSION_RAMPLAYER_CLOSE || carMission == MISSION_BLOCKPLAYER_FARAWAY || carMission == MISSION_BLOCKPLAYER_CLOSE) ) { - pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; - CColModel* pColModel = pVehicle->GetColModel(); - bool bInsideSphere = false; - for (int32 i = 0; i < pColModel->numSpheres; i++) { - CVector pos = pVehicle->m_matrix * pColModel->spheres[i].center; - float fRadius = pColModel->spheres[i].radius; - if (pos.x + fRadius > x1 && pos.x - fRadius < x2 && pos.y + fRadius > y1 && pos.y - fRadius < y2) - bInsideSphere = true; - // Maybe break the loop when bInsideSphere is set to true? - } - if (bInsideSphere) { - if (pVehicle->GetPosition().x <= (x1 + x2) * 0.5f) - pVehicle->m_vecMoveSpeed.x = min(pVehicle->m_vecMoveSpeed.x, 0.0f); - else - pVehicle->m_vecMoveSpeed.x = max(pVehicle->m_vecMoveSpeed.x, 0.0f); - if (pVehicle->GetPosition().y <= (y1 + y2) * 0.5f) - pVehicle->m_vecMoveSpeed.y = min(pVehicle->m_vecMoveSpeed.y, 0.0f); - else - pVehicle->m_vecMoveSpeed.y = max(pVehicle->m_vecMoveSpeed.y, 0.0f); - } + pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; + CColModel* pColModel = pVehicle->GetColModel(); + bool bInsideSphere = false; + for (int32 i = 0; i < pColModel->numSpheres; i++) { + CVector pos = pVehicle->m_matrix * pColModel->spheres[i].center; + float fRadius = pColModel->spheres[i].radius; + if (pos.x + fRadius > x1 && pos.x - fRadius < x2 && pos.y + fRadius > y1 && pos.y - fRadius < y2) + bInsideSphere = true; + // Maybe break the loop when bInsideSphere is set to true? + } + if (bInsideSphere) { + if (pVehicle->GetPosition().x <= (x1 + x2) * 0.5f) + pVehicle->m_vecMoveSpeed.x = min(pVehicle->m_vecMoveSpeed.x, 0.0f); + else + pVehicle->m_vecMoveSpeed.x = max(pVehicle->m_vecMoveSpeed.x, 0.0f); + if (pVehicle->GetPosition().y <= (y1 + y2) * 0.5f) + pVehicle->m_vecMoveSpeed.y = min(pVehicle->m_vecMoveSpeed.y, 0.0f); + else + pVehicle->m_vecMoveSpeed.y = max(pVehicle->m_vecMoveSpeed.y, 0.0f); } } - pNode = pNode->next; + } } } void CWorld::CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2) { - CPtrNode* pNode = list.first; - while (pNode) { + for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { CPed* pPed = (CPed*)pNode->item; const CVector& pedPos = pPed->GetPosition(); - if (pPed->m_scanCode != CWorld::ms_nCurrentScanCode) + if (pPed->m_scanCode != GetCurrentScanCode()) { - pPed->m_scanCode = CWorld::ms_nCurrentScanCode; + pPed->m_scanCode = GetCurrentScanCode(); if (pPed != FindPlayerPed() && pPed->m_leader != FindPlayerPed() && pedPos.x > x1 && pedPos.x < x2 && pedPos.y > y1 && pedPos.y < y2 && @@ -1582,103 +1569,75 @@ CWorld::AddParticles(void) void CWorld::ShutDown(void) { - for (int32 y = 0; y < NUMSECTORS_Y; y++) { - for (int32 x = 0; x < NUMSECTORS_X; x++) { - CSector *pSector = GetSector(x, y); - CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; - while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; - while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pNode = pSector->m_lists[ENTITYLIST_PEDS].first; - while (pNode) { - CEntity *pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; - while (pNode) { - CEntity *pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; - while (pNode) { - CEntity *pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); - pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); - pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); - pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); + for (int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { + CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); + for (CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; } + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; + } + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; + } + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; + } + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; + } + pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); } for (int32 i = 0; i < 4; i ++) { - CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; - while (pNode) { + for (CPtrNode* pNode = GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) { CEntity *pEntity = (CEntity*)pNode->item; - if (pEntity) { - // Maybe remove from world here? - delete pEntity; - } - pNode = pNode->next; + // Maybe remove from world here? + delete pEntity; } GetBigBuildingList((eLevelName)i).Flush(); } - for (int32 y = 0; y < NUMSECTORS_Y; y++) { - for (int32 x = 0; x < NUMSECTORS_X; x++) { - CSector *pSector = GetSector(x, y); - if (pSector->m_lists[ENTITYLIST_BUILDINGS].first) { - sprintf(gString, "Building list %d,%d not empty\n", x, y); - pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); - } - if (pSector->m_lists[ENTITYLIST_DUMMIES].first) { - sprintf(gString, "Dummy list %d,%d not empty\n", x, y); - pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); - } - if (pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first) { - sprintf(gString, "Building overlap list %d,%d not empty\n", x, y); - pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); - } - if (pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first) { - sprintf(gString, "Vehicle overlap list %d,%d not empty\n", x, y); - pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].Flush(); - } - if (pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].first) { - sprintf(gString, "Ped overlap list %d,%d not empty\n", x, y); - pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].Flush(); - } - if (pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].first) { - sprintf(gString, "Object overlap list %d,%d not empty\n", x, y); - pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].Flush(); - } - if (pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].first) { - sprintf(gString, "Dummy overlap list %d,%d not empty\n", x, y); - pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); - } + for (int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { + CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); + if (pSector->m_lists[ENTITYLIST_BUILDINGS].first) { + sprintf(gString, "Building list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); + pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); + } + if (pSector->m_lists[ENTITYLIST_DUMMIES].first) { + sprintf(gString, "Dummy list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); + pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); + } + if (pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first) { + sprintf(gString, "Building overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first) { + sprintf(gString, "Vehicle overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); + pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].first) { + sprintf(gString, "Ped overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); + pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].first) { + sprintf(gString, "Object overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); + pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].first) { + sprintf(gString, "Dummy overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); } } ms_listMovingEntityPtrs.Flush(); @@ -1693,37 +1652,25 @@ CWorld::ClearForRestart(void) CObject::DeleteAllTempObjects(); CObject::DeleteAllMissionObjects(); CPopulation::ConvertAllObjectsToDummyObjects(); - for (int32 y = 0; y < NUMSECTORS_Y; y++) { - for (int32 x = 0; x < NUMSECTORS_X; x++) { - CSector *pSector = GetSector(x, y); - CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; - while (pNode) { - CEntity *pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pNode = GetBigBuildingList(LEVEL_NONE).first; - while (pNode) { - CVehicle *pVehicle = (CVehicle*)pNode->item; - if (pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) { - CWorld::Remove(pVehicle); - delete pVehicle; - } - pNode = pNode->next; - } - pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; - while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; + for (int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { + CSector* pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; + } + for (CPtrNode* pNode = GetBigBuildingList(LEVEL_NONE).first; pNode; pNode = pNode->next) { + CVehicle *pVehicle = (CVehicle*)pNode->item; + if (pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) { + CWorld::Remove(pVehicle); + delete pVehicle; } } + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; + } } CPools::CheckPoolsEmpty(); } @@ -1833,41 +1780,27 @@ CWorld::SetPedsOnFire(float x, float y, float z, float radius, CEntity* reason) void CWorld::RemoveStaticObjects() { - for (int32 y = 0; y < NUMSECTORS_Y; y++) { - for (int32 x = 0; x < NUMSECTORS_X; x++) { - CSector* pSector = GetSector(x, y); - CPtrNode* pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; - while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; - while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; - while (pNode) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity) { - CWorld::Remove(pEntity); - delete pEntity; - } - pNode = pNode->next; - } - pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); - pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); - pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); - pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); + for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { + CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; } + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; + } + for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) { + CEntity* pEntity = (CEntity*)pNode->item; + CWorld::Remove(pEntity); + delete pEntity; + } + pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); } } @@ -2072,18 +2005,17 @@ CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, C void CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer) { - CPtrNode* pNode = list.first; - while (pNode) { - CPhysical* pEntity = (CPhysical*)pNode->item; - CVector vecDistance = pEntity->GetPosition() - position; - float fMagnitude = vecDistance.Magnitude(); - if (fRadius > fMagnitude) { - CWeapon::BlowUpExplosiveThings(pEntity); - CPed* pPed = (CPed*)pEntity; - CObject* pObject = (CObject*)pEntity; - CVehicle* pVehicle = (CVehicle*)pEntity; - if (!pEntity->bExplosionProof && (!pEntity->IsPed() || !pPed->bInVehicle)) { - if (pEntity->bIsStatic) { + for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { + CPhysical* pEntity = (CPhysical*)pNode->item; + CVector vecDistance = pEntity->GetPosition() - position; + float fMagnitude = vecDistance.Magnitude(); + if(fRadius > fMagnitude) { + CWeapon::BlowUpExplosiveThings(pEntity); + CPed *pPed = (CPed *)pEntity; + CObject *pObject = (CObject *)pEntity; + CVehicle *pVehicle = (CVehicle *)pEntity; + if(!pEntity->bExplosionProof && (!pEntity->IsPed() || !pPed->bInVehicle)) { + if(pEntity->bIsStatic) { if (pEntity->IsObject()) { if (fPower > pObject->m_fUprootLimit || IsFence(pObject->m_modelIndex)) { if (IsGlass(pObject->m_modelIndex)) { @@ -2170,7 +2102,6 @@ CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, floa } } } - pNode = pNode->next; } } From 2a4717fa41c332add177d18ef99bcddff9fece93 Mon Sep 17 00:00:00 2001 From: saml1er Date: Fri, 17 Apr 2020 16:14:59 +0500 Subject: [PATCH 052/123] Apply clang format to CWorld --- src/core/World.cpp | 1921 +++++++++++++++++++++++--------------------- 1 file changed, 1007 insertions(+), 914 deletions(-) diff --git a/src/core/World.cpp b/src/core/World.cpp index f0b290a3..358e1823 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1,55 +1,54 @@ -#include "common.h" -#include "patcher.h" +#include "World.h" +#include "Camera.h" +#include "CarCtrl.h" +#include "CopPed.h" +#include "CutsceneMgr.h" +#include "DMAudio.h" #include "Entity.h" +#include "EventList.h" +#include "Explosion.h" +#include "Fire.h" +#include "Garages.h" +#include "Glass.h" +#include "Messages.h" +#include "ModelIndices.h" +#include "Object.h" +#include "ParticleObject.h" #include "Ped.h" #include "PlayerPed.h" -#include "Vehicle.h" -#include "Object.h" -#include "Camera.h" -#include "DMAudio.h" -#include "CarCtrl.h" -#include "Garages.h" -#include "TempColModels.h" -#include "World.h" -#include "ModelIndices.h" -#include "References.h" -#include "CutsceneMgr.h" -#include "Record.h" -#include "RpAnimBlend.h" -#include "Messages.h" -#include "Replay.h" #include "Population.h" -#include "Fire.h" #include "ProjectileInfo.h" -#include "WaterLevel.h" -#include "CopPed.h" -#include "Object.h" +#include "Record.h" +#include "References.h" +#include "Replay.h" +#include "RpAnimBlend.h" #include "Shadows.h" -#include "Explosion.h" -#include "Glass.h" -#include "ParticleObject.h" -#include "EventList.h" +#include "TempColModels.h" +#include "Vehicle.h" +#include "WaterLevel.h" +#include "common.h" +#include "patcher.h" #define OBJECT_REPOSITION_OFFSET_Z 2.0f CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; -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; +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; uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61; CPlayerInfo CWorld::Players[NUMPLAYERS]; -bool &CWorld::bNoMoreCollisionTorque = *(bool*)0x95CDCC; -CEntity *&CWorld::pIgnoreEntity = *(CEntity**)0x8F6494; -bool &CWorld::bIncludeDeadPeds = *(bool*)0x95CD8F; -bool &CWorld::bSecondShift = *(bool*)0x95CD54; -bool &CWorld::bForceProcessControl = *(bool*)0x95CD6C; -bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B; +bool &CWorld::bNoMoreCollisionTorque = *(bool *)0x95CDCC; +CEntity *&CWorld::pIgnoreEntity = *(CEntity **)0x8F6494; +bool &CWorld::bIncludeDeadPeds = *(bool *)0x95CD8F; +bool &CWorld::bSecondShift = *(bool *)0x95CD54; +bool &CWorld::bForceProcessControl = *(bool *)0x95CD6C; +bool &CWorld::bProcessCutsceneOnly = *(bool *)0x95CD8B; -bool &CWorld::bDoingCarCollisions = *(bool*)0x95CD8C; -bool &CWorld::bIncludeCarTyres = *(bool*)0x95CDAA; +bool &CWorld::bDoingCarCollisions = *(bool *)0x95CD8C; +bool &CWorld::bIncludeCarTyres = *(bool *)0x95CDAA; void CWorld::Initialise() @@ -67,37 +66,31 @@ CWorld::Initialise() void CWorld::Add(CEntity *ent) { - if(ent->IsVehicle() || ent->IsPed()) - DMAudio.SetEntityStatus(((CPhysical*)ent)->m_audioEntityId, true); + if(ent->IsVehicle() || ent->IsPed()) DMAudio.SetEntityStatus(((CPhysical *)ent)->m_audioEntityId, true); if(ent->bIsBIGBuilding) ms_bigBuildingsList[ent->m_level].InsertItem(ent); else ent->Add(); - if(ent->IsBuilding() || ent->IsDummy()) - return; + if(ent->IsBuilding() || ent->IsDummy()) return; - if(!ent->bIsStatic) - ((CPhysical*)ent)->AddToMovingList(); + if(!ent->bIsStatic) ((CPhysical *)ent)->AddToMovingList(); } void CWorld::Remove(CEntity *ent) { - if(ent->IsVehicle() || ent->IsPed()) - DMAudio.SetEntityStatus(((CPhysical*)ent)->m_audioEntityId, false); + if(ent->IsVehicle() || ent->IsPed()) DMAudio.SetEntityStatus(((CPhysical *)ent)->m_audioEntityId, false); if(ent->bIsBIGBuilding) ms_bigBuildingsList[ent->m_level].RemoveItem(ent); else ent->Remove(); - if(ent->IsBuilding() || ent->IsDummy()) - return; + if(ent->IsBuilding() || ent->IsDummy()) return; - if(!ent->bIsStatic) - ((CPhysical*)ent)->RemoveFromMovingList(); + if(!ent->bIsStatic) ((CPhysical *)ent)->RemoveFromMovingList(); } void @@ -105,43 +98,43 @@ CWorld::ClearScanCodes(void) { CPtrNode *node; for(int i = 0; i < NUMSECTORS_Y; i++) - for(int j = 0; j < NUMSECTORS_X; j++){ - CSector *s = &ms_aSectors[i][j]; - for(node = s->m_lists[ENTITYLIST_BUILDINGS].first; node; node = node->next) - ((CEntity*)node->item)->m_scanCode = 0; - for(node = s->m_lists[ENTITYLIST_VEHICLES].first; node; node = node->next) - ((CEntity*)node->item)->m_scanCode = 0; - for(node = s->m_lists[ENTITYLIST_PEDS].first; node; node = node->next) - ((CEntity*)node->item)->m_scanCode = 0; - for(node = s->m_lists[ENTITYLIST_OBJECTS].first; node; node = node->next) - ((CEntity*)node->item)->m_scanCode = 0; - for(node = s->m_lists[ENTITYLIST_DUMMIES].first; node; node = node->next) - ((CEntity*)node->item)->m_scanCode = 0; - } + for(int j = 0; j < NUMSECTORS_X; j++) { + CSector *s = &ms_aSectors[i][j]; + for(node = s->m_lists[ENTITYLIST_BUILDINGS].first; node; node = node->next) + ((CEntity *)node->item)->m_scanCode = 0; + for(node = s->m_lists[ENTITYLIST_VEHICLES].first; node; node = node->next) + ((CEntity *)node->item)->m_scanCode = 0; + for(node = s->m_lists[ENTITYLIST_PEDS].first; node; node = node->next) + ((CEntity *)node->item)->m_scanCode = 0; + for(node = s->m_lists[ENTITYLIST_OBJECTS].first; node; node = node->next) + ((CEntity *)node->item)->m_scanCode = 0; + for(node = s->m_lists[ENTITYLIST_DUMMIES].first; node; node = node->next) + ((CEntity *)node->item)->m_scanCode = 0; + } } void -CWorld::ClearExcitingStuffFromArea(const CVector& pos, float radius, bool bRemoveProjectilesAndTidyUpShadows) +CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, bool bRemoveProjectilesAndTidyUpShadows) { - CPedPool* pedPool = CPools::GetPedPool(); - for (int32 i = 0; i < pedPool->GetSize(); i++) { - CPed* pPed = pedPool->GetSlot(i); - if (pPed && !pPed->IsPlayer() && pPed->CanBeDeleted() && - CVector2D(pPed->GetPosition() - pos).MagnitudeSqr() < radius) { + CPedPool *pedPool = CPools::GetPedPool(); + for(int32 i = 0; i < pedPool->GetSize(); i++) { + CPed *pPed = pedPool->GetSlot(i); + if(pPed && !pPed->IsPlayer() && pPed->CanBeDeleted() && + CVector2D(pPed->GetPosition() - pos).MagnitudeSqr() < radius) { CPopulation::RemovePed(pPed); } } - CVehiclePool* VehiclePool = CPools::GetVehiclePool(); - for (int32 i = 0; i < VehiclePool->GetSize(); i++) { - CVehicle* pVehicle = VehiclePool->GetSlot(i); - if (pVehicle && CVector2D(pVehicle->GetPosition() - pos).MagnitudeSqr() < radius && - !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { - if (pVehicle->pDriver) { + CVehiclePool *VehiclePool = CPools::GetVehiclePool(); + for(int32 i = 0; i < VehiclePool->GetSize(); i++) { + CVehicle *pVehicle = VehiclePool->GetSlot(i); + if(pVehicle && CVector2D(pVehicle->GetPosition() - pos).MagnitudeSqr() < radius && + !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { + if(pVehicle->pDriver) { CPopulation::RemovePed(pVehicle->pDriver); pVehicle->pDriver = nil; } - for (int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) { - if (pVehicle->pPassengers[j]) { + for(int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) { + if(pVehicle->pPassengers[j]) { CPopulation::RemovePed(pVehicle->pPassengers[j]); pVehicle->pPassengers[j] = nil; --pVehicle->m_nNumPassengers; @@ -156,7 +149,7 @@ CWorld::ClearExcitingStuffFromArea(const CVector& pos, float radius, bool bRemov gFireManager.ExtinguishPoint(pos, radius); CWorld::ExtinguishAllCarFiresInArea(pos, radius); CExplosion::RemoveAllExplosionsInArea(pos, radius); - if (bRemoveProjectilesAndTidyUpShadows) { + if(bRemoveProjectilesAndTidyUpShadows) { CProjectileInfo::RemoveAllProjectiles(); CShadows::TidyUpShadows(); } @@ -165,13 +158,14 @@ CWorld::ClearExcitingStuffFromArea(const CVector& pos, float radius, bool bRemov bool CWorld::CameraToIgnoreThisObject(CEntity *ent) { - if(CGarages::IsModelIndexADoor(ent->GetModelIndex())) - return false; - return ((CObject*)ent)->m_bCameraToAvoidThisObject != 1; + if(CGarages::IsModelIndexADoor(ent->GetModelIndex())) return false; + return ((CObject *)ent)->m_bCameraToAvoidThisObject != 1; } bool -CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) +CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, + bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, + bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) { int x, xstart, xend; int y, ystart, yend; @@ -188,94 +182,80 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi xend = GetSectorIndexX(point2.x); yend = GetSectorIndexY(point2.y); -#define LOSARGS CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects +#define LOSARGS \ + CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, \ + checkDummies, ignoreSeeThrough, ignoreSomeObjects - if(xstart == xend && ystart == yend){ + if(xstart == xend && ystart == yend) { // Only one sector return ProcessLineOfSightSector(*GetSector(xstart, ystart), LOSARGS); - }else if(xstart == xend){ + } else if(xstart == xend) { // Only step in y if(ystart < yend) - for(y = ystart; y <= yend; y++) - ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); + for(y = ystart; y <= yend; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); else - for(y = ystart; y >= yend; y--) - ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); + for(y = ystart; y >= yend; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); return dist < 1.0f; - }else if(ystart == yend){ + } else if(ystart == yend) { // Only step in x if(xstart < xend) - for(x = xstart; x <= xend; x++) - ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS); + for(x = xstart; x <= xend; x++) ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS); else - for(x = xstart; x >= xend; x--) - ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS); + for(x = xstart; x >= xend; x--) ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS); return dist < 1.0f; - }else{ - if(point1.x < point2.x){ + } else { + if(point1.x < point2.x) { // Step from left to right float m = (point2.y - point1.y) / (point2.x - point1.x); y1 = ystart; - y2 = GetSectorIndexY((GetWorldX(xstart+1) - point1.x)*m + point1.y); + y2 = GetSectorIndexY((GetWorldX(xstart + 1) - point1.x) * m + point1.y); if(y1 < y2) - for(y = y1; y <= y2; y++) - ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); + for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); else - for(y = y1; y >= y2; y--) - ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); + for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); - for(x = xstart+1; x < xend; x++){ + for(x = xstart + 1; x < xend; x++) { y1 = y2; - y2 = GetSectorIndexY((GetWorldX(x+1) - point1.x)*m + point1.y); + y2 = GetSectorIndexY((GetWorldX(x + 1) - point1.x) * m + point1.y); if(y1 < y2) - for(y = y1; y <= y2; y++) - ProcessLineOfSightSector(*GetSector(x, y), LOSARGS); + for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS); else - for(y = y1; y >= y2; y--) - ProcessLineOfSightSector(*GetSector(x, y), LOSARGS); + for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS); } y1 = y2; y2 = yend; if(y1 < y2) - for(y = y1; y <= y2; y++) - ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS); + for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS); else - for(y = y1; y >= y2; y--) - ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS); - }else{ + for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS); + } else { // Step from right to left float m = (point2.y - point1.y) / (point2.x - point1.x); y1 = ystart; - y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x)*m + point1.y); + y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x) * m + point1.y); if(y1 < y2) - for(y = y1; y <= y2; y++) - ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); + for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); else - for(y = y1; y >= y2; y--) - ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); + for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS); - for(x = xstart-1; x > xend; x--){ + for(x = xstart - 1; x > xend; x--) { y1 = y2; - y2 = GetSectorIndexY((GetWorldX(x) - point1.x)*m + point1.y); + y2 = GetSectorIndexY((GetWorldX(x) - point1.x) * m + point1.y); if(y1 < y2) - for(y = y1; y <= y2; y++) - ProcessLineOfSightSector(*GetSector(x, y), LOSARGS); + for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS); else - for(y = y1; y >= y2; y--) - ProcessLineOfSightSector(*GetSector(x, y), LOSARGS); + for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS); } y1 = y2; y2 = yend; if(y1 < y2) - for(y = y1; y <= y2; y++) - ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS); + for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS); else - for(y = y1; y >= y2; y--) - ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS); + for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS); } return dist < 1.0f; } @@ -284,51 +264,63 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi } bool -CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) +CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, + bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, + bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) { float mindist = dist; bool deadPeds = !!bIncludeDeadPeds; bIncludeDeadPeds = false; - if(checkBuildings){ - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, ignoreSeeThrough); - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough); + if(checkBuildings) { + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, + ignoreSeeThrough); + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough); } - if(checkVehicles){ - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, ignoreSeeThrough); - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough); + if(checkVehicles) { + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, + ignoreSeeThrough); + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough); } - if(checkPeds){ - if(deadPeds) - bIncludeDeadPeds = true; - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, ignoreSeeThrough); - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough); + if(checkPeds) { + if(deadPeds) bIncludeDeadPeds = true; + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, + ignoreSeeThrough); + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough); bIncludeDeadPeds = false; } - if(checkObjects){ - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, ignoreSeeThrough, ignoreSomeObjects); - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, ignoreSomeObjects); + if(checkObjects) { + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, + ignoreSeeThrough, ignoreSomeObjects); + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough, ignoreSomeObjects); } - if(checkDummies){ - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, ignoreSeeThrough); - ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough); + if(checkDummies) { + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, + ignoreSeeThrough); + ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough); } bIncludeDeadPeds = deadPeds; - if(mindist < dist){ + if(mindist < dist) { dist = mindist; return true; - }else + } else return false; } bool -CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects) +CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, + CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects) { bool deadPeds = false; float mindist = dist; @@ -336,119 +328,137 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP CEntity *e; CColModel *colmodel; - if(list.first && bIncludeDeadPeds && ((CEntity*)list.first->item)->IsPed()) - deadPeds = true; + if(list.first && bIncludeDeadPeds && ((CEntity *)list.first->item)->IsPed()) deadPeds = true; - for(node = list.first; node; node = node->next){ - e = (CEntity*)node->item; - if(e->m_scanCode != GetCurrentScanCode() && - e != pIgnoreEntity && - (e->bUsesCollision || deadPeds) && - !(ignoreSomeObjects && CameraToIgnoreThisObject(e))){ + for(node = list.first; node; node = node->next) { + e = (CEntity *)node->item; + if(e->m_scanCode != GetCurrentScanCode() && e != pIgnoreEntity && (e->bUsesCollision || deadPeds) && + !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) { colmodel = nil; e->m_scanCode = GetCurrentScanCode(); - if(e->IsPed()){ - if(e->bUsesCollision || - deadPeds && ((CPed*)e)->m_nPedState == PED_DEAD){ - if (((CPed*)e)->UseGroundColModel()) + if(e->IsPed()) { + if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) { + if(((CPed *)e)->UseGroundColModel()) colmodel = &CTempColModels::ms_colModelPedGroundHit; else #ifdef ANIMATE_PED_COL_MODEL - colmodel = CPedModelInfo::AnimatePedColModel(((CPedModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->GetHitColModel(), RpClumpGetFrame(e->GetClump())); + colmodel = CPedModelInfo::AnimatePedColModel( + ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex())) + ->GetHitColModel(), + RpClumpGetFrame(e->GetClump())); #else - colmodel = ((CPedModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->GetHitColModel(); + colmodel = + ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex())) + ->GetHitColModel(); #endif - }else + } else colmodel = nil; - }else if(e->bUsesCollision) + } else if(e->bUsesCollision) colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); - if(colmodel && - CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, dist, ignoreSeeThrough)) + if(colmodel && CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, dist, + ignoreSeeThrough)) entity = e; } } - if(mindist < dist){ + if(mindist < dist) { dist = mindist; return true; - }else + } else return false; } -bool -CWorld::ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly) +bool +CWorld::ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings, + bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, + bool ignoreSeeThrough, CStoredCollPoly *poly) { AdvanceCurrentScanCode(); CVector point2(point1.x, point1.y, z2); return ProcessVerticalLineSector(*GetSector(GetSectorIndexX(point1.x), GetSectorIndexX(point1.y)), - CColLine(point1, point2), point, entity, - checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, poly); + CColLine(point1, point2), point, entity, checkBuildings, checkVehicles, + checkPeds, checkObjects, checkDummies, ignoreSeeThrough, poly); } bool -CWorld::ProcessVerticalLineSector(CSector §or, const CColLine &line, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly) +CWorld::ProcessVerticalLineSector(CSector §or, const CColLine &line, CColPoint &point, CEntity *&entity, + bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, + bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly) { float mindist = 1.0f; - if(checkBuildings){ - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, ignoreSeeThrough, poly); - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly); + if(checkBuildings) { + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, + ignoreSeeThrough, poly); + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, + entity, ignoreSeeThrough, poly); } - if(checkVehicles){ - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, ignoreSeeThrough, poly); - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly); + if(checkVehicles) { + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, + ignoreSeeThrough, poly); + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough, poly); } - if(checkPeds){ - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, ignoreSeeThrough, poly); - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly); + if(checkPeds) { + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, + ignoreSeeThrough, poly); + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough, poly); } - if(checkObjects){ - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, ignoreSeeThrough, poly); - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly); + if(checkObjects) { + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, + ignoreSeeThrough, poly); + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough, poly); } - if(checkDummies){ - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, ignoreSeeThrough, poly); - ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly); + if(checkDummies) { + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, + ignoreSeeThrough, poly); + ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, + ignoreSeeThrough, poly); } return mindist < 1.0f; } bool -CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly) +CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, + CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly) { float mindist = dist; CPtrNode *node; CEntity *e; CColModel *colmodel; - for(node = list.first; node; node = node->next){ - e = (CEntity*)node->item; - if(e->m_scanCode != GetCurrentScanCode() && - e->bUsesCollision){ + for(node = list.first; node; node = node->next) { + e = (CEntity *)node->item; + if(e->m_scanCode != GetCurrentScanCode() && e->bUsesCollision) { e->m_scanCode = GetCurrentScanCode(); colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); - if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist, ignoreSeeThrough, poly)) + if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist, + ignoreSeeThrough, poly)) entity = e; } } - if(mindist < dist){ + if(mindist < dist) { dist = mindist; return true; - }else + } else return false; } bool -CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) +CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles, + bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, + bool ignoreSomeObjects) { int x, xstart, xend; int y, ystart, yend; @@ -461,58 +471,54 @@ CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool xend = GetSectorIndexX(point2.x); yend = GetSectorIndexY(point2.y); -#define LOSARGS CColLine(point1, point2), checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects +#define LOSARGS \ + CColLine(point1, point2), checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, \ + ignoreSeeThrough, ignoreSomeObjects - if(xstart == xend && ystart == yend){ + if(xstart == xend && ystart == yend) { // Only one sector return GetIsLineOfSightSectorClear(*GetSector(xstart, ystart), LOSARGS); - }else if(xstart == xend){ + } else if(xstart == xend) { // Only step in y - if(ystart < yend){ + if(ystart < yend) { for(y = ystart; y <= yend; y++) - if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) - return false; - }else{ + if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false; + } else { for(y = ystart; y >= yend; y--) - if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) - return false; + if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false; } - }else if(ystart == yend){ + } else if(ystart == yend) { // Only step in x - if(xstart < xend){ + if(xstart < xend) { for(x = xstart; x <= xend; x++) - if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS)) - return false; - }else{ + if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS)) return false; + } else { for(x = xstart; x >= xend; x--) - if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS)) - return false; + if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS)) return false; } - }else{ - if(point1.x < point2.x){ + } else { + if(point1.x < point2.x) { // Step from left to right float m = (point2.y - point1.y) / (point2.x - point1.x); y1 = ystart; - y2 = GetSectorIndexY((GetWorldX(xstart+1) - point1.x)*m + point1.y); - if(y1 < y2){ + y2 = GetSectorIndexY((GetWorldX(xstart + 1) - point1.x) * m + point1.y); + if(y1 < y2) { for(y = y1; y <= y2; y++) - if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) - return false; - }else{ + if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false; + } else { for(y = y1; y >= y2; y--) - if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) - return false; + if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false; } - for(x = xstart+1; x < xend; x++){ + for(x = xstart + 1; x < xend; x++) { y1 = y2; - y2 = GetSectorIndexY((GetWorldX(x+1) - point1.x)*m + point1.y); - if(y1 < y2){ + y2 = GetSectorIndexY((GetWorldX(x + 1) - point1.x) * m + point1.y); + if(y1 < y2) { for(y = y1; y <= y2; y++) if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS)) return false; - }else{ + } else { for(y = y1; y >= y2; y--) if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS)) return false; @@ -521,39 +527,35 @@ CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool y1 = y2; y2 = yend; - if(y1 < y2){ + if(y1 < y2) { for(y = y1; y <= y2; y++) - if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) - return false; - }else{ + if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false; + } else { for(y = y1; y >= y2; y--) - if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) - return false; + if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false; } - }else{ + } else { // Step from right to left float m = (point2.y - point1.y) / (point2.x - point1.x); y1 = ystart; - y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x)*m + point1.y); - if(y1 < y2){ + y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x) * m + point1.y); + if(y1 < y2) { for(y = y1; y <= y2; y++) - if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) - return false; - }else{ + if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false; + } else { for(y = y1; y >= y2; y--) - if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) - return false; + if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false; } - for(x = xstart-1; x > xend; x--){ + for(x = xstart - 1; x > xend; x--) { y1 = y2; - y2 = GetSectorIndexY((GetWorldX(x) - point1.x)*m + point1.y); - if(y1 < y2){ + y2 = GetSectorIndexY((GetWorldX(x) - point1.x) * m + point1.y); + if(y1 < y2) { for(y = y1; y <= y2; y++) if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS)) return false; - }else{ + } else { for(y = y1; y >= y2; y--) if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS)) return false; @@ -562,14 +564,12 @@ CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool y1 = y2; y2 = yend; - if(y1 < y2){ + if(y1 < y2) { for(y = y1; y <= y2; y++) - if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) - return false; - }else{ + if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false; + } else { for(y = y1; y >= y2; y--) - if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) - return false; + if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false; } } } @@ -580,37 +580,43 @@ CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool } bool -CWorld::GetIsLineOfSightSectorClear(CSector §or, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) +CWorld::GetIsLineOfSightSectorClear(CSector §or, const CColLine &line, bool checkBuildings, bool checkVehicles, + bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, + bool ignoreSomeObjects) { - if(checkBuildings){ + if(checkBuildings) { if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS], line, ignoreSeeThrough)) return false; - if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, ignoreSeeThrough)) + if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, + ignoreSeeThrough)) return false; } - if(checkVehicles){ + if(checkVehicles) { if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES], line, ignoreSeeThrough)) return false; - if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, ignoreSeeThrough)) + if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, + ignoreSeeThrough)) return false; } - if(checkPeds){ + if(checkPeds) { if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS], line, ignoreSeeThrough)) return false; if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, ignoreSeeThrough)) return false; } - if(checkObjects){ - if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS], line, ignoreSeeThrough, ignoreSomeObjects)) + if(checkObjects) { + if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS], line, ignoreSeeThrough, + ignoreSomeObjects)) return false; - if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, ignoreSeeThrough, ignoreSomeObjects)) + if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, ignoreSeeThrough, + ignoreSomeObjects)) return false; } - if(checkDummies){ + if(checkDummies) { if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_DUMMIES], line, ignoreSeeThrough)) return false; if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, ignoreSeeThrough)) @@ -621,21 +627,20 @@ CWorld::GetIsLineOfSightSectorClear(CSector §or, const CColLine &line, bool } bool -CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects) +CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, + bool ignoreSomeObjects) { CPtrNode *node; CEntity *e; CColModel *colmodel; - for(node = list.first; node; node = node->next){ - e = (CEntity*)node->item; - if(e->m_scanCode != GetCurrentScanCode() && - e->bUsesCollision){ + for(node = list.first; node; node = node->next) { + e = (CEntity *)node->item; + if(e->m_scanCode != GetCurrentScanCode() && e->bUsesCollision) { e->m_scanCode = GetCurrentScanCode(); - if(e != pIgnoreEntity && - !(ignoreSomeObjects && CameraToIgnoreThisObject(e))){ + if(e != pIgnoreEntity && !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) { colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); @@ -649,26 +654,25 @@ CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bo } void -CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector ¢re, float radius, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects) +CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector ¢re, float radius, bool ignoreZ, short *nextObject, + short lastObject, CEntity **objects) { float radiusSqr = radius * radius; float objDistSqr; - for (CPtrNode *node = list.first; node; node = node->next) { - CEntity *object = (CEntity*)node->item; - if (object->m_scanCode != GetCurrentScanCode()) { + for(CPtrNode *node = list.first; node; node = node->next) { + CEntity *object = (CEntity *)node->item; + if(object->m_scanCode != GetCurrentScanCode()) { object->m_scanCode = GetCurrentScanCode(); CVector diff = centre - object->GetPosition(); - if (ignoreZ) + if(ignoreZ) objDistSqr = diff.MagnitudeSqr2D(); else objDistSqr = diff.MagnitudeSqr(); - if (objDistSqr < radiusSqr && *nextObject < lastObject) { - if (objects) { - objects[*nextObject] = object; - } + if(objDistSqr < radiusSqr && *nextObject < lastObject) { + if(objects) { objects[*nextObject] = object; } (*nextObject)++; } } @@ -676,81 +680,96 @@ CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector ¢re, float radi } void -CWorld::FindObjectsInRange(CVector ¢re, float radius, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies) +CWorld::FindObjectsInRange(CVector ¢re, 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 - radius); - if (minX <= 0) minX = 0; + if(minX <= 0) minX = 0; int minY = GetSectorIndexY(centre.y - radius); - if (minY <= 0) minY = 0; + if(minY <= 0) minY = 0; int maxX = GetSectorIndexX(centre.x + radius); #ifdef FIX_BUGS - if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; + if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; #else - if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; + if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; #endif int maxY = GetSectorIndexY(centre.y + radius); #ifdef FIX_BUGS - if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; + if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; #else - if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; + if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; #endif - + AdvanceCurrentScanCode(); *nextObject = 0; for(int curY = minY; curY <= maxY; curY++) { for(int curX = minX; curX <= maxX; curX++) { CSector *sector = GetSector(curX, curY); - if (checkBuildings) { - 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(checkBuildings) { + 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, radius, ignoreZ, nextObject, lastObject, objects); - FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects); + if(checkVehicles) { + 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, radius, ignoreZ, nextObject, lastObject, objects); - FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects); + if(checkPeds) { + 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, radius, ignoreZ, nextObject, lastObject, objects); - FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects); + if(checkObjects) { + 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, radius, ignoreZ, nextObject, lastObject, objects); - FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, radius, ignoreZ, nextObject, lastObject, objects); + if(checkDummies) { + 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); } } } } -void -CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities) +void +CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList &list, const CVector &position, float radius, + bool bCheck2DOnly, int16 *nEntitiesFound, int16 maxEntitiesToFind, + CEntity **aEntities) { - for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != GetCurrentScanCode()) { + for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; + if(pEntity->m_scanCode != GetCurrentScanCode()) { pEntity->m_scanCode = GetCurrentScanCode(); float fMagnitude = 0.0f; - if (bCheck2DOnly) + if(bCheck2DOnly) fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr2D(); else fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr(); - if (fMagnitude < radius * radius && *nEntitiesFound < maxEntitiesToFind) { - if (aEntities) - aEntities[*nEntitiesFound] = pEntity; + if(fMagnitude < radius * radius && *nEntitiesFound < maxEntitiesToFind) { + if(aEntities) aEntities[*nEntitiesFound] = pEntity; ++*nEntitiesFound; } } } } -void -CWorld::FindObjectsOfTypeInRange(uint32 modelId, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) +void +CWorld::FindObjectsOfTypeInRange(uint32 modelId, const CVector &position, float radius, bool bCheck2DOnly, + int16 *nEntitiesFound, int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings, + bool bVehicles, bool bPeds, bool bObjects, bool bDummies) { CWorld::AdvanceCurrentScanCode(); *nEntitiesFound = 0; @@ -760,115 +779,138 @@ CWorld::FindObjectsOfTypeInRange(uint32 modelId, const CVector& position, float const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); - for (int32 y = nStartY; y <= nEndY; y++) { - for (int32 x = nStartX; x <= nEndX; x++) { - CSector* pSector = CWorld::GetSector(x, y); - if (bBuildings) { - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + for(int32 y = nStartY; y <= nEndY; y++) { + for(int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + if(bBuildings) { + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly, + nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius, + bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); } - if (bVehicles) { - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + if(bVehicles) { + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly, + nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius, + bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); } - if (bPeds) { - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_PEDS], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + if(bPeds) { + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_PEDS], position, radius, bCheck2DOnly, + nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly, + nEntitiesFound, maxEntitiesToFind, aEntities); } - if (bObjects) { - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + if(bObjects) { + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly, + nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius, + bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); } - if (bDummies) { - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsOfTypeInRangeSectorList(modelId, pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius, bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); + if(bDummies) { + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly, + nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsOfTypeInRangeSectorList( + modelId, pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius, + bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities); } } } } -CEntity* -CWorld::TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects) +CEntity * +CWorld::TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings, + bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, + bool ignoreSomeObjects) { - CEntity* foundE = nil; + CEntity *foundE = nil; int minX = GetSectorIndexX(centre.x - radius); - if (minX <= 0) minX = 0; + if(minX <= 0) minX = 0; int minY = GetSectorIndexY(centre.y - radius); - if (minY <= 0) minY = 0; + if(minY <= 0) minY = 0; int maxX = GetSectorIndexX(centre.x + radius); #ifdef FIX_BUGS - if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; + if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1; #else - if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; + if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X; #endif int maxY = GetSectorIndexY(centre.y + radius); #ifdef FIX_BUGS - if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; + if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1; #else - if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; + if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; #endif AdvanceCurrentScanCode(); - for (int curY = minY; curY <= maxY; curY++) { - for (int curX = minX; curX <= maxX; curX++) { - CSector* sector = GetSector(curX, curY); - if (checkBuildings) { - foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, radius, entityToIgnore, false); - if (foundE) - return foundE; + for(int curY = minY; curY <= maxY; curY++) { + for(int curX = minX; curX <= maxX; curX++) { + CSector *sector = GetSector(curX, curY); + if(checkBuildings) { + foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, + radius, entityToIgnore, false); + if(foundE) return foundE; - foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, radius, entityToIgnore, false); - if (foundE) - return foundE; + 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, radius, entityToIgnore, false); - if (foundE) - return foundE; + if(checkVehicles) { + foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, + radius, entityToIgnore, false); + if(foundE) return foundE; - foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, radius, entityToIgnore, false); - if (foundE) - return foundE; + 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, radius, entityToIgnore, false); - if (foundE) - return foundE; + if(checkPeds) { + foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius, + entityToIgnore, false); + if(foundE) return foundE; - foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, radius, entityToIgnore, false); - if (foundE) - return foundE; + 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, radius, entityToIgnore, ignoreSomeObjects); - if (foundE) - return foundE; + if(checkObjects) { + foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, + radius, entityToIgnore, ignoreSomeObjects); + if(foundE) return foundE; - foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, radius, entityToIgnore, ignoreSomeObjects); - if (foundE) - return foundE; + 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, radius, entityToIgnore, false); - if (foundE) - return foundE; + if(checkDummies) { + foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, + radius, entityToIgnore, false); + if(foundE) return foundE; - foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, radius, entityToIgnore, false); - if (foundE) - return foundE; + foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], + centre, radius, entityToIgnore, false); + if(foundE) return foundE; } } } return foundE; } -CEntity* -CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore, bool ignoreSomeObjects) +CEntity * +CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore, + bool ignoreSomeObjects) { static CColModel sphereCol; @@ -892,24 +934,27 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad CMatrix sphereMat; sphereMat.SetTranslate(spherePos); - for(CPtrNode *node=list.first; node; node = node->next) { - CEntity *e = (CEntity*)node->item; + for(CPtrNode *node = list.first; node; node = node->next) { + CEntity *e = (CEntity *)node->item; - if (e->m_scanCode != GetCurrentScanCode()) { + if(e->m_scanCode != GetCurrentScanCode()) { e->m_scanCode = GetCurrentScanCode(); - if (e != entityToIgnore && e->bUsesCollision && !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) { + if(e != entityToIgnore && e->bUsesCollision && + !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) { CVector diff = spherePos - e->GetPosition(); float distance = diff.Magnitude(); - if (e->GetBoundRadius() + radius > distance) { + if(e->GetBoundRadius() + radius > distance) { CColModel *eCol = CModelInfo::GetModelInfo(e->m_modelIndex)->GetColModel(); - int collidedSpheres = CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(), - *eCol, gaTempSphereColPoints, nil, nil); + int collidedSpheres = + CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(), *eCol, + gaTempSphereColPoints, nil, nil); - if (collidedSpheres != 0 || - (e->IsVehicle() && ((CVehicle*)e)->m_vehType == VEHICLE_TYPE_CAR && - e->m_modelIndex != MI_DODO && radius + eCol->boundingBox.max.x > distance)) { + if(collidedSpheres != 0 || + (e->IsVehicle() && ((CVehicle *)e)->m_vehType == VEHICLE_TYPE_CAR && + e->m_modelIndex != MI_DODO && + radius + eCol->boundingBox.max.x > distance)) { return e; } } @@ -925,7 +970,8 @@ CWorld::FindGroundZForCoord(float x, float y) { CColPoint point; CEntity *ent; - if(ProcessVerticalLine(CVector(x, y, 1000.0f), -1000.0f, point, ent, true, false, false, false, true, false, nil)) + if(ProcessVerticalLine(CVector(x, y, 1000.0f), -1000.0f, point, ent, true, false, false, false, true, false, + nil)) return point.point.z; else return 20.0f; @@ -936,13 +982,11 @@ CWorld::FindGroundZFor3DCoord(float x, float y, float z, bool *found) { CColPoint point; CEntity *ent; - if(ProcessVerticalLine(CVector(x, y, z), -1000.0f, point, ent, true, false, false, false, false, false, nil)){ - if(found) - *found = true; + if(ProcessVerticalLine(CVector(x, y, z), -1000.0f, point, ent, true, false, false, false, false, false, nil)) { + if(found) *found = true; return point.point.z; - }else{ - if(found) - *found = false; + } else { + if(found) *found = false; return 0.0f; } } @@ -952,51 +996,49 @@ CWorld::FindRoofZFor3DCoord(float x, float y, float z, bool *found) { CColPoint point; CEntity *ent; - if(ProcessVerticalLine(CVector(x, y, z), 1000.0f, point, ent, true, false, false, false, true, false, nil)){ - if(found) - *found = true; + if(ProcessVerticalLine(CVector(x, y, z), 1000.0f, point, ent, true, false, false, false, true, false, nil)) { + if(found) *found = true; return point.point.z; - }else{ + } else { if(found == nil) - printf("THERE IS NO MAP BELOW THE FOLLOWING COORS:%f %f %f. (FindGroundZFor3DCoord)\n", x, y, z); - if(found) - *found = false; + printf("THERE IS NO MAP BELOW THE FOLLOWING COORS:%f %f %f. (FindGroundZFor3DCoord)\n", x, y, + z); + if(found) *found = false; return 20.0f; } } -void -CWorld::RemoveReferencesToDeletedObject(CEntity* pDeletedObject) -{ +void +CWorld::RemoveReferencesToDeletedObject(CEntity *pDeletedObject) +{ int32 i = CPools::GetPedPool()->GetSize(); - while (--i >= 0) { - CPed* pPed = CPools::GetPedPool()->GetSlot(i); - if (pPed && pPed != pDeletedObject) { + while(--i >= 0) { + CPed *pPed = CPools::GetPedPool()->GetSlot(i); + if(pPed && pPed != pDeletedObject) { pPed->RemoveRefsToEntity(pDeletedObject); - if (pPed->m_pCurrentPhysSurface == pDeletedObject) - pPed->m_pCurrentPhysSurface = nil; + if(pPed->m_pCurrentPhysSurface == pDeletedObject) pPed->m_pCurrentPhysSurface = nil; } } i = CPools::GetVehiclePool()->GetSize(); - while (--i >= 0) { - CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); - if (pVehicle && pVehicle != pDeletedObject) { + while(--i >= 0) { + CVehicle *pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if(pVehicle && pVehicle != pDeletedObject) { pVehicle->RemoveRefsToEntity(pDeletedObject); pVehicle->RemoveRefsToVehicle(pDeletedObject); } } i = CPools::GetObjectPool()->GetSize(); - while (--i >= 0) { - CObject* pObject = CPools::GetObjectPool()->GetSlot(i); - if (pObject && pObject != pDeletedObject) { - pObject->RemoveRefsToEntity(pDeletedObject); - } + while(--i >= 0) { + CObject *pObject = CPools::GetObjectPool()->GetSlot(i); + if(pObject && pObject != pDeletedObject) { pObject->RemoveRefsToEntity(pDeletedObject); } } } -void -CWorld::FindObjectsKindaColliding(const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) -{ +void +CWorld::FindObjectsKindaColliding(const CVector &position, float radius, bool bCheck2DOnly, int16 *nCollidingEntities, + int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings, bool bVehicles, + bool bPeds, bool bObjects, bool bDummies) +{ CWorld::AdvanceCurrentScanCode(); *nCollidingEntities = 0; const CVector2D vecSectorStartPos(position.x - radius, position.y - radius); @@ -1005,48 +1047,68 @@ CWorld::FindObjectsKindaColliding(const CVector& position, float radius, bool bC const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); - for (int32 y = nStartY; y <= nEndY; y++) { - for (int32 x = nStartX; x <= nEndX; x++) { - CSector* pSector = CWorld::GetSector(x, y); - if (bBuildings) { - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + for(int32 y = nStartY; y <= nEndY; y++) { + for(int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + if(bBuildings) { + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); } - if (bVehicles) { - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + if(bVehicles) { + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); } - if (bPeds) { - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_PEDS], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + if(bPeds) { + CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_PEDS], position, + radius, bCheck2DOnly, nCollidingEntities, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); } - if (bObjects) { - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + if(bObjects) { + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); } - if (bDummies) { - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); - CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius, bCheck2DOnly, nCollidingEntities, maxEntitiesToFind, aEntities); + if(bDummies) { + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); + CWorld::FindObjectsKindaCollidingSectorList( + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius, bCheck2DOnly, + nCollidingEntities, maxEntitiesToFind, aEntities); } } } } -void -CWorld::FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities) +void +CWorld::FindObjectsKindaCollidingSectorList(CPtrList &list, const CVector &position, float radius, bool bCheck2DOnly, + int16 *nCollidingEntities, int16 maxEntitiesToFind, CEntity **aEntities) { - for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != GetCurrentScanCode()) { + for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; + if(pEntity->m_scanCode != GetCurrentScanCode()) { pEntity->m_scanCode = GetCurrentScanCode(); float fMagnitude = 0.0f; - if (bCheck2DOnly) + if(bCheck2DOnly) fMagnitude = (position - pEntity->GetPosition()).Magnitude2D(); else fMagnitude = (position - pEntity->GetPosition()).Magnitude(); - if (pEntity->GetBoundRadius() + radius > fMagnitude && *nCollidingEntities < maxEntitiesToFind) { - if (aEntities) - aEntities[*nCollidingEntities] = pEntity; + if(pEntity->GetBoundRadius() + radius > fMagnitude && *nCollidingEntities < maxEntitiesToFind) { + if(aEntities) aEntities[*nCollidingEntities] = pEntity; ++*nCollidingEntities; } } @@ -1054,65 +1116,90 @@ CWorld::FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& posit } void -CWorld::FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) -{ +CWorld::FindObjectsIntersectingCube(const CVector &vecStartPos, const CVector &vecEndPos, int16 *nIntersecting, + int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings, bool bVehicles, + bool bPeds, bool bObjects, bool bDummies) +{ CWorld::AdvanceCurrentScanCode(); *nIntersecting = 0; const int32 nStartX = max(CWorld::GetSectorIndexX(vecStartPos.x), 0); const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); - for (int32 y = nStartY; y <= nEndY; y++) { - for (int32 x = nStartX; x <= nEndX; x++) { - CSector* pSector = CWorld::GetSector(x, y); - if (bBuildings) { - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + for(int32 y = nStartY; y <= nEndY; y++) { + for(int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + if(bBuildings) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS], + vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], vecStartPos, vecEndPos, + nIntersecting, maxEntitiesToFind, aEntities); } - if (bVehicles) { - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + if(bVehicles) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], + vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos, + nIntersecting, maxEntitiesToFind, aEntities); } - if (bPeds) { - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + if(bPeds) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS], + vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], + vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities); } - if (bObjects) { - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + if(bObjects) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], + vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities); } - if (bDummies) { - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_DUMMIES], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities); + if(bDummies) { + CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_DUMMIES], + vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities); } } } - } -void -CWorld::FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities) +void +CWorld::FindObjectsIntersectingCubeSectorList(CPtrList &list, const CVector &vecStartPos, const CVector &vecEndPos, + int16 *nIntersecting, int16 maxEntitiesToFind, CEntity **aEntities) { - for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != GetCurrentScanCode()) { - pEntity->m_scanCode = GetCurrentScanCode(); - float fRadius = pEntity->GetBoundRadius(); - const CVector& entityPos = pEntity->GetPosition(); - if (fRadius + entityPos.x >= vecStartPos.x && entityPos.x - fRadius <= vecEndPos.x && - fRadius + entityPos.y >= vecStartPos.y && entityPos.y - fRadius <= vecEndPos.y && - fRadius + entityPos.z >= vecStartPos.z && entityPos.z - fRadius <= vecEndPos.z && - *nIntersecting < maxEntitiesToFind) { - if (aEntities) - aEntities[*nIntersecting] = pEntity; - ++*nIntersecting; - } + for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; + if(pEntity->m_scanCode != GetCurrentScanCode()) { + pEntity->m_scanCode = GetCurrentScanCode(); + float fRadius = pEntity->GetBoundRadius(); + const CVector &entityPos = pEntity->GetPosition(); + if(fRadius + entityPos.x >= vecStartPos.x && entityPos.x - fRadius <= vecEndPos.x && + fRadius + entityPos.y >= vecStartPos.y && entityPos.y - fRadius <= vecEndPos.y && + fRadius + entityPos.z >= vecStartPos.z && entityPos.z - fRadius <= vecEndPos.z && + *nIntersecting < maxEntitiesToFind) { + if(aEntities) aEntities[*nIntersecting] = pEntity; + ++*nIntersecting; } + } } } -void -CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, float fStartX, float fStartY, float fEndX, float fEndY, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) +void +CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &boundingBox, const CMatrix &matrix, + const CVector &position, float fStartX, float fStartY, float fEndX, + float fEndY, int16 *nEntitiesFound, int16 maxEntitiesToFind, + CEntity **aEntities, bool bBuildings, bool bVehicles, bool bPeds, + bool bObjects, bool bDummies) { CWorld::AdvanceCurrentScanCode(); *nEntitiesFound = 0; @@ -1120,47 +1207,69 @@ CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox& boundingBox, co const int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0); const int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1); const int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); - for (int32 y = nStartY; y <= nEndY; y++) { - for (int32 x = nStartX; x <= nEndX; x++) { - CSector* pSector = CWorld::GetSector(x, y); - if (bBuildings) { - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + for(int32 y = nStartY; y <= nEndY; y++) { + for(int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + if(bBuildings) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_BUILDINGS], boundingBox, matrix, position, + nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], boundingBox, matrix, position, + nEntitiesFound, maxEntitiesToFind, aEntities); } - if (bVehicles) { - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + if(bVehicles) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_VEHICLES], boundingBox, matrix, position, + nEntitiesFound, maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], boundingBox, matrix, position, + nEntitiesFound, maxEntitiesToFind, aEntities); } - if (bPeds) { - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_PEDS], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + if(bPeds) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_PEDS], boundingBox, matrix, position, nEntitiesFound, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], boundingBox, matrix, position, + nEntitiesFound, maxEntitiesToFind, aEntities); } - if (bObjects) { - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + if(bObjects) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_OBJECTS], boundingBox, matrix, position, nEntitiesFound, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], boundingBox, matrix, position, + nEntitiesFound, maxEntitiesToFind, aEntities); } - if (bDummies) { - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_DUMMIES], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); - CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], boundingBox, matrix, position, nEntitiesFound, maxEntitiesToFind, aEntities); + if(bDummies) { + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_DUMMIES], boundingBox, matrix, position, nEntitiesFound, + maxEntitiesToFind, aEntities); + CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList( + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], boundingBox, matrix, position, + nEntitiesFound, maxEntitiesToFind, aEntities); } } } } -void -CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities) +void +CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList &list, const CColBox &boundingBox, + const CMatrix &matrix, const CVector &position, + int16 *nEntitiesFound, int16 maxEntitiesToFind, + CEntity **aEntities) { - for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != GetCurrentScanCode()) { + for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; + if(pEntity->m_scanCode != GetCurrentScanCode()) { pEntity->m_scanCode = GetCurrentScanCode(); CColSphere sphere; CVector vecDistance = pEntity->GetPosition() - position; sphere.radius = pEntity->GetBoundRadius(); sphere.center = Multiply3x3(vecDistance, matrix); - if (CCollision::TestSphereBox(sphere, boundingBox) && *nEntitiesFound < maxEntitiesToFind) { - if (aEntities) - aEntities[*nEntitiesFound] = pEntity; + if(CCollision::TestSphereBox(sphere, boundingBox) && *nEntitiesFound < maxEntitiesToFind) { + if(aEntities) aEntities[*nEntitiesFound] = pEntity; ++*nEntitiesFound; } } @@ -1168,7 +1277,9 @@ CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, cons } void -CWorld::FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bVehicles, bool bPeds, bool bObjects) +CWorld::FindMissionEntitiesIntersectingCube(const CVector &vecStartPos, const CVector &vecEndPos, int16 *nIntersecting, + int16 maxEntitiesToFind, CEntity **aEntities, bool bVehicles, bool bPeds, + bool bObjects) { CWorld::AdvanceCurrentScanCode(); *nIntersecting = 0; @@ -1176,70 +1287,82 @@ CWorld::FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CV const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); - for (int32 y = nStartY; y <= nEndY; y++) { - for (int32 x = nStartX; x <= nEndX; x++) { - CSector* pSector = CWorld::GetSector(x, y); - if (bVehicles) { - CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, true, false); - CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, true, false); + for(int32 y = nStartY; y <= nEndY; y++) { + for(int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + if(bVehicles) { + CWorld::FindMissionEntitiesIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_VEHICLES], vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities, true, false); + CWorld::FindMissionEntitiesIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos, + nIntersecting, maxEntitiesToFind, aEntities, true, false); } - if (bPeds) { - CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, false, true); - CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, false, true); + if(bPeds) { + CWorld::FindMissionEntitiesIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_PEDS], vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities, false, true); + CWorld::FindMissionEntitiesIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities, false, true); } - if (bObjects) { - CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, false, false); - CWorld::FindMissionEntitiesIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, maxEntitiesToFind, aEntities, false, false); + if(bObjects) { + CWorld::FindMissionEntitiesIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_OBJECTS], vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities, false, false); + CWorld::FindMissionEntitiesIntersectingCubeSectorList( + pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting, + maxEntitiesToFind, aEntities, false, false); } } } } void -CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList) +CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList &list, const CVector &vecStartPos, + const CVector &vecEndPos, int16 *nIntersecting, + int16 maxEntitiesToFind, CEntity **aEntities, bool bIsVehicleList, + bool bIsPedList) { - for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; - if (pEntity->m_scanCode != GetCurrentScanCode()) { + for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; + if(pEntity->m_scanCode != GetCurrentScanCode()) { pEntity->m_scanCode = GetCurrentScanCode(); bool bIsMissionEntity = false; - if (bIsVehicleList) - bIsMissionEntity = ((CVehicle*)pEntity)->VehicleCreatedBy == MISSION_VEHICLE; - else if (bIsPedList) - bIsMissionEntity = ((CPed*)pEntity)->CharCreatedBy == MISSION_CHAR; + if(bIsVehicleList) + bIsMissionEntity = ((CVehicle *)pEntity)->VehicleCreatedBy == MISSION_VEHICLE; + else if(bIsPedList) + bIsMissionEntity = ((CPed *)pEntity)->CharCreatedBy == MISSION_CHAR; else - bIsMissionEntity = ((CObject*)pEntity)->ObjectCreatedBy == MISSION_OBJECT; + bIsMissionEntity = ((CObject *)pEntity)->ObjectCreatedBy == MISSION_OBJECT; float fRadius = pEntity->GetBoundRadius(); - const CVector& entityPos = pEntity->GetPosition(); - if (bIsMissionEntity && - fRadius + entityPos.x >= vecStartPos.x && entityPos.x - fRadius <= vecEndPos.x && - fRadius + entityPos.y >= vecStartPos.y && entityPos.y - fRadius <= vecEndPos.y && - fRadius + entityPos.z >= vecStartPos.z && entityPos.z - fRadius <= vecEndPos.z && - *nIntersecting < maxEntitiesToFind) { - if (aEntities) - aEntities[*nIntersecting] = pEntity; + const CVector &entityPos = pEntity->GetPosition(); + if(bIsMissionEntity && fRadius + entityPos.x >= vecStartPos.x && + entityPos.x - fRadius <= vecEndPos.x && fRadius + entityPos.y >= vecStartPos.y && + entityPos.y - fRadius <= vecEndPos.y && fRadius + entityPos.z >= vecStartPos.z && + entityPos.z - fRadius <= vecEndPos.z && *nIntersecting < maxEntitiesToFind) { + if(aEntities) aEntities[*nIntersecting] = pEntity; ++*nIntersecting; } } } } -CPlayerPed* +CPlayerPed * FindPlayerPed(void) { return CWorld::Players[CWorld::PlayerInFocus].m_pPed; } -CVehicle* +CVehicle * FindPlayerVehicle(void) { CPlayerPed *ped = FindPlayerPed(); - if(ped && ped->InVehicle()) - return ped->m_pMyVehicle; + if(ped && ped->InVehicle()) return ped->m_pMyVehicle; return nil; } -CVehicle* +CVehicle * FindPlayerTrain(void) { if(FindPlayerVehicle() && FindPlayerVehicle()->IsTrain()) @@ -1248,7 +1371,7 @@ FindPlayerTrain(void) return nil; } -CEntity* +CEntity * FindPlayerEntity(void) { CPlayerPed *ped = FindPlayerPed(); @@ -1268,7 +1391,7 @@ FindPlayerCoors(void) return ped->GetPosition(); } -CVector& +CVector & FindPlayerSpeed(void) { CPlayerPed *ped = FindPlayerPed(); @@ -1278,27 +1401,22 @@ FindPlayerSpeed(void) return ped->m_vecMoveSpeed; } -CVector& +CVector & FindPlayerCentreOfWorld(int32 player) { - if(CCarCtrl::bCarsGeneratedAroundCamera) - return TheCamera.GetPosition(); - if(CWorld::Players[player].m_pRemoteVehicle) - return CWorld::Players[player].m_pRemoteVehicle->GetPosition(); - if(FindPlayerVehicle()) - return FindPlayerVehicle()->GetPosition(); + if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition(); + if(CWorld::Players[player].m_pRemoteVehicle) return CWorld::Players[player].m_pRemoteVehicle->GetPosition(); + if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition(); return CWorld::Players[player].m_pPed->GetPosition(); } -CVector& +CVector & FindPlayerCentreOfWorld_NoSniperShift(void) { - if(CCarCtrl::bCarsGeneratedAroundCamera) - return TheCamera.GetPosition(); + if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition(); if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition(); - if(FindPlayerVehicle()) - return FindPlayerVehicle()->GetPosition(); + if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition(); return FindPlayerPed()->GetPosition(); } @@ -1307,29 +1425,26 @@ FindPlayerHeading(void) { if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetForward().Heading(); - if(FindPlayerVehicle()) - return FindPlayerVehicle()->GetForward().Heading(); + if(FindPlayerVehicle()) return FindPlayerVehicle()->GetForward().Heading(); return FindPlayerPed()->GetForward().Heading(); } - -void CWorld::ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2) +void +CWorld::ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2) { CVehiclePool *pVehiclePool = CPools::GetVehiclePool(); - for (int32 i = 0; i < pVehiclePool->GetSize(); i++) { - CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); - if (pVehicle) { - const CVector& position = pVehicle->GetPosition(); - if (position.x >= x1 && position.x <= x2 && - position.y >= y1 && position.y <= y2 && - position.z >= z1 && position.z <= z2 && - !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { - if (pVehicle->pDriver) { + for(int32 i = 0; i < pVehiclePool->GetSize(); i++) { + CVehicle *pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if(pVehicle) { + const CVector &position = pVehicle->GetPosition(); + if(position.x >= x1 && position.x <= x2 && position.y >= y1 && position.y <= y2 && + position.z >= z1 && position.z <= z2 && !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { + if(pVehicle->pDriver) { CPopulation::RemovePed(pVehicle->pDriver); pVehicle->pDriver = nil; } - for (int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) { - if (pVehicle->pPassengers[j]) { + for(int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) { + if(pVehicle->pPassengers[j]) { CPopulation::RemovePed(pVehicle->pPassengers[j]); pVehicle->pPassengers[j] = nil; --pVehicle->m_nNumPassengers; @@ -1343,25 +1458,23 @@ void CWorld::ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, } } -void +void CWorld::ClearPedsFromArea(float x1, float y1, float z1, float x2, float y2, float z2) { - CPedPool* pPedPool = CPools::GetPedPool(); - for (int32 i = 0; i < pPedPool->GetSize(); i++) { - CPed* pPed = CPools::GetPedPool()->GetSlot(i); - if (pPed) { - const CVector& position = pPed->GetPosition(); - if (!pPed->IsPlayer() && pPed->CanBeDeleted() && - position.x >= x1 && position.x <= x2 && - position.y >= y1 && position.y <= y2 && - position.z >= z1 && position.z <= z2) { + CPedPool *pPedPool = CPools::GetPedPool(); + for(int32 i = 0; i < pPedPool->GetSize(); i++) { + CPed *pPed = CPools::GetPedPool()->GetSlot(i); + if(pPed) { + const CVector &position = pPed->GetPosition(); + if(!pPed->IsPlayer() && pPed->CanBeDeleted() && position.x >= x1 && position.x <= x2 && + position.y >= y1 && position.y <= y2 && position.z >= z1 && position.z <= z2) { CPopulation::RemovePed(pPed); } } } } -void +void CWorld::CallOffChaseForArea(float x1, float y1, float x2, float y2) { CWorld::AdvanceCurrentScanCode(); @@ -1373,49 +1486,51 @@ CWorld::CallOffChaseForArea(float x1, float y1, float x2, float y2) const int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0); const int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1); const int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); - for (int32 y = nStartY; y <= nEndY; y++) { - for (int32 x = nStartX; x <= nEndX; x++) { - CSector* pSector = CWorld::GetSector(x, y); - CWorld::CallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES], x1, y1, x2, y2, fStartX, fStartY, fEndX, fEndY); - CWorld::CallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], x1, y1, x2, y2, fStartX, fStartY, fEndX, fEndY); + for(int32 y = nStartY; y <= nEndY; y++) { + for(int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + CWorld::CallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES], x1, y1, x2, + y2, fStartX, fStartY, fEndX, fEndY); + CWorld::CallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], x1, + y1, x2, y2, fStartX, fStartY, fEndX, fEndY); CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS], x1, y1, x2, y2); - CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], x1, y1, x2, y2); + CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], x1, y1, x2, + y2); } } } -void -CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY) +void +CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList &list, float x1, float y1, float x2, float y2, float fStartX, + float fStartY, float fEndX, float fEndY) { - for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { - CVehicle *pVehicle = (CVehicle*)pNode->item; - if (pVehicle->m_scanCode != GetCurrentScanCode()) { + for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) { + CVehicle *pVehicle = (CVehicle *)pNode->item; + if(pVehicle->m_scanCode != GetCurrentScanCode()) { pVehicle->m_scanCode = GetCurrentScanCode(); - const CVector& vehiclePos = pVehicle->GetPosition(); + const CVector &vehiclePos = pVehicle->GetPosition(); eCarMission carMission = pVehicle->AutoPilot.m_nCarMission; - if (pVehicle != FindPlayerVehicle() && - vehiclePos.x > fStartX && vehiclePos.x < fEndX && - vehiclePos.y > fStartY && vehiclePos.y < fEndY && - pVehicle->bIsLawEnforcer && - (carMission == MISSION_RAMPLAYER_FARAWAY || carMission == MISSION_RAMPLAYER_CLOSE || - carMission == MISSION_BLOCKPLAYER_FARAWAY || carMission == MISSION_BLOCKPLAYER_CLOSE) - ) { + if(pVehicle != FindPlayerVehicle() && vehiclePos.x > fStartX && vehiclePos.x < fEndX && + vehiclePos.y > fStartY && vehiclePos.y < fEndY && pVehicle->bIsLawEnforcer && + (carMission == MISSION_RAMPLAYER_FARAWAY || carMission == MISSION_RAMPLAYER_CLOSE || + carMission == MISSION_BLOCKPLAYER_FARAWAY || carMission == MISSION_BLOCKPLAYER_CLOSE)) { pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; - CColModel* pColModel = pVehicle->GetColModel(); + CColModel *pColModel = pVehicle->GetColModel(); bool bInsideSphere = false; - for (int32 i = 0; i < pColModel->numSpheres; i++) { + for(int32 i = 0; i < pColModel->numSpheres; i++) { CVector pos = pVehicle->m_matrix * pColModel->spheres[i].center; float fRadius = pColModel->spheres[i].radius; - if (pos.x + fRadius > x1 && pos.x - fRadius < x2 && pos.y + fRadius > y1 && pos.y - fRadius < y2) + if(pos.x + fRadius > x1 && pos.x - fRadius < x2 && pos.y + fRadius > y1 && + pos.y - fRadius < y2) bInsideSphere = true; // Maybe break the loop when bInsideSphere is set to true? } - if (bInsideSphere) { - if (pVehicle->GetPosition().x <= (x1 + x2) * 0.5f) + if(bInsideSphere) { + if(pVehicle->GetPosition().x <= (x1 + x2) * 0.5f) pVehicle->m_vecMoveSpeed.x = min(pVehicle->m_vecMoveSpeed.x, 0.0f); else pVehicle->m_vecMoveSpeed.x = max(pVehicle->m_vecMoveSpeed.x, 0.0f); - if (pVehicle->GetPosition().y <= (y1 + y2) * 0.5f) + if(pVehicle->GetPosition().y <= (y1 + y2) * 0.5f) pVehicle->m_vecMoveSpeed.y = min(pVehicle->m_vecMoveSpeed.y, 0.0f); else pVehicle->m_vecMoveSpeed.y = max(pVehicle->m_vecMoveSpeed.y, 0.0f); @@ -1425,31 +1540,29 @@ CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1 } } -void -CWorld::CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2) +void +CWorld::CallOffChaseForAreaSectorListPeds(CPtrList &list, float x1, float y1, float x2, float y2) { - for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { - CPed* pPed = (CPed*)pNode->item; - const CVector& pedPos = pPed->GetPosition(); - if (pPed->m_scanCode != GetCurrentScanCode()) - { + for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) { + CPed *pPed = (CPed *)pNode->item; + const CVector &pedPos = pPed->GetPosition(); + if(pPed->m_scanCode != GetCurrentScanCode()) { pPed->m_scanCode = GetCurrentScanCode(); - if (pPed != FindPlayerPed() && pPed->m_leader != FindPlayerPed() && - pedPos.x > x1 && pedPos.x < x2 && - pedPos.y > y1 && pedPos.y < y2 && - (pPed->m_pedInObjective == FindPlayerPed() || pPed->m_carInObjective && pPed->m_carInObjective == FindPlayerVehicle()) && - pPed->m_nPedState != PED_DEAD && pPed->m_nPedState != PED_DIE && - (pPed->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || - pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || - pPed->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)) { - if (pPed->IsPedInControl()) { - if (pPed->m_nPedType == PEDTYPE_COP) - ((CCopPed*)pPed)->ClearPursuit(); + if(pPed != FindPlayerPed() && pPed->m_leader != FindPlayerPed() && pedPos.x > x1 && + pedPos.x < x2 && pedPos.y > y1 && pedPos.y < y2 && + (pPed->m_pedInObjective == FindPlayerPed() || + pPed->m_carInObjective && pPed->m_carInObjective == FindPlayerVehicle()) && + pPed->m_nPedState != PED_DEAD && pPed->m_nPedState != PED_DIE && + (pPed->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || + pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || + pPed->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)) { + if(pPed->IsPedInControl()) { + if(pPed->m_nPedType == PEDTYPE_COP) + ((CCopPed *)pPed)->ClearPursuit(); else pPed->SetIdle(); pPed->SetObjective(OBJECTIVE_NONE); - } - else { + } else { pPed->m_prevObjective = OBJECTIVE_NONE; pPed->m_nLastPedState = PED_IDLE; } @@ -1459,13 +1572,13 @@ CWorld::CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, fl } void -CWorld::RemoveEntityInsteadOfProcessingIt(CEntity* ent) +CWorld::RemoveEntityInsteadOfProcessingIt(CEntity *ent) { - if (ent->IsPed()) { - if (FindPlayerPed() == ent) + if(ent->IsPed()) { + if(FindPlayerPed() == ent) Remove(ent); else - CPopulation::RemovePed((CPed*)ent); + CPopulation::RemovePed((CPed *)ent); } else { Remove(ent); delete ent; @@ -1476,12 +1589,13 @@ void CWorld::RemoveFallenPeds(void) { int poolSize = CPools::GetPedPool()->GetSize(); - for(int poolIndex = poolSize-1; poolIndex >= 0; poolIndex--) { + for(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex); - if (ped) { - if (ped->GetPosition().z < MAP_Z_LOW_LIMIT) { - if (ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) { - int closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED, 999999.9f, false, false); + if(ped) { + if(ped->GetPosition().z < MAP_Z_LOW_LIMIT) { + if(ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) { + int closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED, + 999999.9f, false, false); CVector newPos = ThePaths.m_pathNodes[closestNode].pos; newPos.z += 2.0f; ped->Teleport(newPos); @@ -1498,17 +1612,20 @@ void CWorld::RemoveFallenCars(void) { int poolSize = CPools::GetVehiclePool()->GetSize(); - for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { - CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex); - if (veh) { - if (veh->GetPosition().z < MAP_Z_LOW_LIMIT) { - if (veh->VehicleCreatedBy == MISSION_VEHICLE || veh == FindPlayerVehicle() || (veh->pDriver && veh->pDriver->IsPlayer())) { - int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR, 999999.9f, false, false); + for(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { + CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex); + if(veh) { + if(veh->GetPosition().z < MAP_Z_LOW_LIMIT) { + if(veh->VehicleCreatedBy == MISSION_VEHICLE || veh == FindPlayerVehicle() || + (veh->pDriver && veh->pDriver->IsPlayer())) { + int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR, + 999999.9f, false, false); CVector newPos = ThePaths.m_pathNodes[closestNode].pos; newPos.z += 3.0f; veh->Teleport(newPos); veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - } else if (veh->VehicleCreatedBy == RANDOM_VEHICLE || veh->VehicleCreatedBy == PARKED_VEHICLE) { + } else if(veh->VehicleCreatedBy == RANDOM_VEHICLE || + veh->VehicleCreatedBy == PARKED_VEHICLE) { Remove(veh); delete veh; } @@ -1521,11 +1638,10 @@ void CWorld::StopAllLawEnforcersInTheirTracks(void) { int poolSize = CPools::GetVehiclePool()->GetSize(); - for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { - CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex); - if (veh) { - if (veh->bIsLawEnforcer) - veh->SetMoveSpeed(0.0f, 0.0f, 0.0f); + for(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { + CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex); + if(veh) { + if(veh->bIsLawEnforcer) veh->SetMoveSpeed(0.0f, 0.0f, 0.0f); } } } @@ -1534,10 +1650,9 @@ void CWorld::SetAllCarsCanBeDamaged(bool toggle) { int poolSize = CPools::GetVehiclePool()->GetSize(); - for (int poolIndex = 0; poolIndex < poolSize; poolIndex++) { + for(int poolIndex = 0; poolIndex < poolSize; poolIndex++) { CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex); - if (veh) - veh->bCanBeDamaged = toggle; + if(veh) veh->bCanBeDamaged = toggle; } } @@ -1545,54 +1660,53 @@ void CWorld::ExtinguishAllCarFiresInArea(CVector point, float range) { int poolSize = CPools::GetVehiclePool()->GetSize(); - for (int poolIndex = 0; poolIndex < poolSize; poolIndex++) { - CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex); - if (veh) { - if ((point - veh->GetPosition()).MagnitudeSqr() < sq(range)) - veh->ExtinguishCarFire(); + for(int poolIndex = 0; poolIndex < poolSize; poolIndex++) { + CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex); + if(veh) { + if((point - veh->GetPosition()).MagnitudeSqr() < sq(range)) veh->ExtinguishCarFire(); } } } -void -CWorld::AddParticles(void) +void +CWorld::AddParticles(void) { - for (int32 y = 0; y < NUMSECTORS_Y; y++) { - for (int32 x = 0; x < NUMSECTORS_X; x++) { - CSector* pSector = GetSector(x, y); + for(int32 y = 0; y < NUMSECTORS_Y; y++) { + for(int32 x = 0; x < NUMSECTORS_X; x++) { + CSector *pSector = GetSector(x, y); CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_BUILDINGS]); CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_DUMMIES]); } } } -void +void CWorld::ShutDown(void) { - for (int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { + for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); - for (CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) { - CEntity *pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) { - CEntity *pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) { - CEntity *pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } @@ -1601,41 +1715,41 @@ CWorld::ShutDown(void) pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); } - for (int32 i = 0; i < 4; i ++) { - for (CPtrNode* pNode = GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) { - CEntity *pEntity = (CEntity*)pNode->item; + for(int32 i = 0; i < 4; i++) { + for(CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; // Maybe remove from world here? delete pEntity; } GetBigBuildingList((eLevelName)i).Flush(); } - for (int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { + for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); - if (pSector->m_lists[ENTITYLIST_BUILDINGS].first) { + if(pSector->m_lists[ENTITYLIST_BUILDINGS].first) { sprintf(gString, "Building list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); } - if (pSector->m_lists[ENTITYLIST_DUMMIES].first) { + if(pSector->m_lists[ENTITYLIST_DUMMIES].first) { sprintf(gString, "Dummy list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); } - if (pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first) { + if(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first) { sprintf(gString, "Building overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); } - if (pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first) { + if(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first) { sprintf(gString, "Vehicle overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].Flush(); } - if (pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].first) { + if(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].first) { sprintf(gString, "Ped overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].Flush(); } - if (pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].first) { + if(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].first) { sprintf(gString, "Object overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].Flush(); } - if (pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].first) { + if(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].first) { sprintf(gString, "Dummy overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y); pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); } @@ -1643,31 +1757,30 @@ CWorld::ShutDown(void) ms_listMovingEntityPtrs.Flush(); } -void -CWorld::ClearForRestart(void) +void +CWorld::ClearForRestart(void) { - if (CCutsceneMgr::HasLoaded()) - CCutsceneMgr::DeleteCutsceneData(); + if(CCutsceneMgr::HasLoaded()) CCutsceneMgr::DeleteCutsceneData(); CProjectileInfo::RemoveAllProjectiles(); CObject::DeleteAllTempObjects(); CObject::DeleteAllMissionObjects(); CPopulation::ConvertAllObjectsToDummyObjects(); - for (int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { - CSector* pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) { - CEntity *pEntity = (CEntity*)pNode->item; + for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { + CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } - for (CPtrNode* pNode = GetBigBuildingList(LEVEL_NONE).first; pNode; pNode = pNode->next) { - CVehicle *pVehicle = (CVehicle*)pNode->item; - if (pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) { + for(CPtrNode *pNode = GetBigBuildingList(LEVEL_NONE).first; pNode; pNode = pNode->next) { + CVehicle *pVehicle = (CVehicle *)pNode->item; + if(pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) { CWorld::Remove(pVehicle); delete pVehicle; } } - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } @@ -1675,75 +1788,50 @@ CWorld::ClearForRestart(void) CPools::CheckPoolsEmpty(); } -void -CWorld::RepositionCertainDynamicObjects() -{ +void +CWorld::RepositionCertainDynamicObjects() +{ int32 i = CPools::GetDummyPool()->GetSize(); - while (--i >= 0) { - CDummy* dummy = CPools::GetDummyPool()->GetSlot(i); - if (dummy) { - RepositionOneObject(dummy); - } + while(--i >= 0) { + CDummy *dummy = CPools::GetDummyPool()->GetSlot(i); + if(dummy) { RepositionOneObject(dummy); } } } void -CWorld::RepositionOneObject(CEntity* pEntity) +CWorld::RepositionOneObject(CEntity *pEntity) { int16 modelId = pEntity->m_modelIndex; - if (modelId == MI_SINGLESTREETLIGHTS1 - || modelId == MI_SINGLESTREETLIGHTS2 - || modelId == MI_SINGLESTREETLIGHTS3 - || modelId == MI_DOUBLESTREETLIGHTS - || modelId == MI_TREE1 - || modelId == MI_TREE2 - || modelId == MI_TREE3 - || modelId == MI_TREE4 - || modelId == MI_TREE5 - || modelId == MI_TREE6 - || modelId == MI_TREE7 - || modelId == MI_TREE8 - || modelId == MI_TREE9 - || modelId == MI_TREE10 - || modelId == MI_TREE11 - || modelId == MI_TREE12 - || modelId == MI_TREE13 - || modelId == MI_TREE14 - || modelId == MI_TRAFFICLIGHTS - || modelId == MI_PARKINGMETER - || modelId == MI_PHONEBOOTH1 - || modelId == MI_WASTEBIN - || modelId == MI_BIN - || modelId == MI_POSTBOX1 - || modelId == MI_NEWSSTAND - || modelId == MI_TRAFFICCONE - || modelId == MI_DUMP1 - || modelId == MI_ROADWORKBARRIER1 - || modelId == MI_BUSSIGN1 - || modelId == MI_NOPARKINGSIGN1 - || modelId == MI_PHONESIGN - || modelId == MI_TAXISIGN - || modelId == MI_FISHSTALL01 - || modelId == MI_FISHSTALL02 - || modelId == MI_FISHSTALL03 - || modelId == MI_FISHSTALL04 - || modelId == MI_BAGELSTAND2 - || modelId == MI_FIRE_HYDRANT - || modelId == MI_BOLLARDLIGHT - || modelId == MI_PARKTABLE) { - CVector& position = pEntity->GetPosition(); + if(modelId == MI_SINGLESTREETLIGHTS1 || modelId == MI_SINGLESTREETLIGHTS2 || + modelId == MI_SINGLESTREETLIGHTS3 || modelId == MI_DOUBLESTREETLIGHTS || modelId == MI_TREE1 || + modelId == MI_TREE2 || modelId == MI_TREE3 || modelId == MI_TREE4 || modelId == MI_TREE5 || + modelId == MI_TREE6 || modelId == MI_TREE7 || modelId == MI_TREE8 || modelId == MI_TREE9 || + modelId == MI_TREE10 || modelId == MI_TREE11 || modelId == MI_TREE12 || modelId == MI_TREE13 || + modelId == MI_TREE14 || modelId == MI_TRAFFICLIGHTS || modelId == MI_PARKINGMETER || + modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN || modelId == MI_BIN || modelId == MI_POSTBOX1 || + modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE || modelId == MI_DUMP1 || + modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 || + modelId == MI_PHONESIGN || modelId == MI_TAXISIGN || modelId == MI_FISHSTALL01 || + modelId == MI_FISHSTALL02 || modelId == MI_FISHSTALL03 || modelId == MI_FISHSTALL04 || + modelId == MI_BAGELSTAND2 || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT || + modelId == MI_PARKTABLE) { + CVector &position = pEntity->GetPosition(); float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z; - position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - fBoundingBoxMinZ; + position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y, + position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - + fBoundingBoxMinZ; pEntity->m_matrix.UpdateRW(); pEntity->UpdateRwFrame(); - } else if (modelId == MI_BUOY) { + } else if(modelId == MI_BUOY) { float fWaterLevel = 0.0f; bool bFound = true; - const CVector& position = pEntity->GetPosition(); - float fGroundZ = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &bFound); - if (CWaterLevel::GetWaterLevelNoWaves(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, &fWaterLevel)) { - if (!bFound || fWaterLevel > fGroundZ) { - CColModel* pColModel = pEntity->GetColModel(); + const CVector &position = pEntity->GetPosition(); + float fGroundZ = CWorld::FindGroundZFor3DCoord(position.x, position.y, + position.z + OBJECT_REPOSITION_OFFSET_Z, &bFound); + if(CWaterLevel::GetWaterLevelNoWaves(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, + &fWaterLevel)) { + if(!bFound || fWaterLevel > fGroundZ) { + CColModel *pColModel = pEntity->GetColModel(); float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; pEntity->GetPosition().z = 0.2f * fHeight + fWaterLevel - 0.5f * fHeight; } @@ -1755,45 +1843,47 @@ void CWorld::SetCarsOnFire(float x, float y, float z, float radius, CEntity *reason) { int poolSize = CPools::GetVehiclePool()->GetSize(); - for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { + for(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex); - if (veh && veh->m_status != STATUS_WRECKED && !veh->m_pCarFire && !veh->bFireProof) { - if (Abs(veh->GetPosition().z - z) < 5.0f && Abs(veh->GetPosition().x - x) < radius && Abs(veh->GetPosition().y - y) < radius) - gFireManager.StartFire(veh, reason, 0.8f, true); + if(veh && veh->m_status != STATUS_WRECKED && !veh->m_pCarFire && !veh->bFireProof) { + if(Abs(veh->GetPosition().z - z) < 5.0f && Abs(veh->GetPosition().x - x) < radius && + Abs(veh->GetPosition().y - y) < radius) + gFireManager.StartFire(veh, reason, 0.8f, true); } } } -void -CWorld::SetPedsOnFire(float x, float y, float z, float radius, CEntity* reason) +void +CWorld::SetPedsOnFire(float x, float y, float z, float radius, CEntity *reason) { int32 poolSize = CPools::GetPedPool()->GetSize(); - for (int32 i = poolSize - 1; i >= 0; i--) { - CPed* pPed = CPools::GetPedPool()->GetSlot(i); - if (pPed && pPed->m_nPedState != PED_DEAD && !pPed->bInVehicle && !pPed->m_pFire && !pPed->bFireProof) { - if (Abs(pPed->GetPosition().z - z) < 5.0f && Abs(pPed->GetPosition().x - x) < radius && Abs(pPed->GetPosition().y - y) < radius) + for(int32 i = poolSize - 1; i >= 0; i--) { + CPed *pPed = CPools::GetPedPool()->GetSlot(i); + if(pPed && pPed->m_nPedState != PED_DEAD && !pPed->bInVehicle && !pPed->m_pFire && !pPed->bFireProof) { + if(Abs(pPed->GetPosition().z - z) < 5.0f && Abs(pPed->GetPosition().x - x) < radius && + Abs(pPed->GetPosition().y - y) < radius) gFireManager.StartFire(pPed, reason, 0.8f, true); } } } -void -CWorld::RemoveStaticObjects() +void +CWorld::RemoveStaticObjects() { for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) { CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y); - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } - for (CPtrNode* pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) { - CEntity* pEntity = (CEntity*)pNode->item; + for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) { + CEntity *pEntity = (CEntity *)pNode->item; CWorld::Remove(pEntity); delete pEntity; } @@ -1807,16 +1897,18 @@ CWorld::RemoveStaticObjects() void CWorld::Process(void) { - if (!(CTimer::GetFrameCounter() & 63)) - CReferences::PruneAllReferencesInWorld(); + if(!(CTimer::GetFrameCounter() & 63)) CReferences::PruneAllReferencesInWorld(); - if (bProcessCutsceneOnly) { - for (int i = 0; i < NUMCUTSCENEOBJECTS; i++) { + if(bProcessCutsceneOnly) { + for(int i = 0; i < NUMCUTSCENEOBJECTS; i++) { CCutsceneObject *csObj = CCutsceneMgr::GetCutsceneObject(i); - if (csObj && csObj->m_entryInfoList.first) { - if (csObj->m_rwObject && RwObjectGetType(csObj->m_rwObject) == rpCLUMP - && RpAnimBlendClumpGetFirstAssociation(csObj->GetClump())) { - RpAnimBlendClumpUpdateAnimations(csObj->GetClump(), 0.02f * (csObj->m_type == ENTITY_TYPE_OBJECT ? CTimer::GetTimeStepNonClipped() : CTimer::GetTimeStep())); + if(csObj && csObj->m_entryInfoList.first) { + if(csObj->m_rwObject && RwObjectGetType(csObj->m_rwObject) == rpCLUMP && + RpAnimBlendClumpGetFirstAssociation(csObj->GetClump())) { + RpAnimBlendClumpUpdateAnimations(csObj->GetClump(), + 0.02f * (csObj->m_type == ENTITY_TYPE_OBJECT + ? CTimer::GetTimeStepNonClipped() + : CTimer::GetTimeStep())); } csObj->ProcessControl(); csObj->ProcessCollision(); @@ -1827,102 +1919,98 @@ CWorld::Process(void) CRecordDataForChase::ProcessControlCars(); CRecordDataForChase::SaveOrRetrieveCarPositions(); } else { - for (CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CEntity *movingEnt = (CEntity*)node->item; - if (movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP - && RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) { - RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), 0.02f * (movingEnt->m_type == ENTITY_TYPE_OBJECT ? CTimer::GetTimeStepNonClipped() : CTimer::GetTimeStep())); + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity *movingEnt = (CEntity *)node->item; + if(movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP && + RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) { + RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), + 0.02f * (movingEnt->m_type == ENTITY_TYPE_OBJECT + ? CTimer::GetTimeStepNonClipped() + : CTimer::GetTimeStep())); } } - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CPhysical* movingEnt = (CPhysical*)node->item; - if (movingEnt->bRemoveFromWorld) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CPhysical *movingEnt = (CPhysical *)node->item; + if(movingEnt->bRemoveFromWorld) { RemoveEntityInsteadOfProcessingIt(movingEnt); } else { movingEnt->ProcessControl(); - if (movingEnt->bIsStatic) { - movingEnt->RemoveFromMovingList(); - } + if(movingEnt->bIsStatic) { movingEnt->RemoveFromMovingList(); } } } bForceProcessControl = true; - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CPhysical* movingEnt = (CPhysical*)node->item; - if (movingEnt->bWasPostponed) { - if (movingEnt->bRemoveFromWorld) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CPhysical *movingEnt = (CPhysical *)node->item; + if(movingEnt->bWasPostponed) { + if(movingEnt->bRemoveFromWorld) { RemoveEntityInsteadOfProcessingIt(movingEnt); } else { movingEnt->ProcessControl(); - if (movingEnt->bIsStatic) { - movingEnt->RemoveFromMovingList(); - } + if(movingEnt->bIsStatic) { movingEnt->RemoveFromMovingList(); } } } } bForceProcessControl = false; - if (CReplay::IsPlayingBack()) { - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CEntity* movingEnt = (CEntity*)node->item; + if(CReplay::IsPlayingBack()) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity *movingEnt = (CEntity *)node->item; movingEnt->bIsInSafePosition = true; movingEnt->GetMatrix().UpdateRW(); movingEnt->UpdateRwFrame(); } } else { bNoMoreCollisionTorque = false; - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CEntity* movingEnt = (CEntity*)node->item; - if (!movingEnt->bIsInSafePosition) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity *movingEnt = (CEntity *)node->item; + if(!movingEnt->bIsInSafePosition) { movingEnt->ProcessCollision(); movingEnt->GetMatrix().UpdateRW(); movingEnt->UpdateRwFrame(); } } bNoMoreCollisionTorque = true; - for (int i = 0; i < 4; i++) { - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CEntity* movingEnt = (CEntity*)node->item; - if (!movingEnt->bIsInSafePosition) { + for(int i = 0; i < 4; i++) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity *movingEnt = (CEntity *)node->item; + if(!movingEnt->bIsInSafePosition) { movingEnt->ProcessCollision(); movingEnt->GetMatrix().UpdateRW(); movingEnt->UpdateRwFrame(); } } } - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CEntity* movingEnt = (CEntity*)node->item; - if (!movingEnt->bIsInSafePosition) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity *movingEnt = (CEntity *)node->item; + if(!movingEnt->bIsInSafePosition) { movingEnt->bIsStuck = true; movingEnt->ProcessCollision(); movingEnt->GetMatrix().UpdateRW(); movingEnt->UpdateRwFrame(); - if (!movingEnt->bIsInSafePosition) { - movingEnt->bIsStuck = true; - } + if(!movingEnt->bIsInSafePosition) { movingEnt->bIsStuck = true; } } } bSecondShift = false; - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CEntity* movingEnt = (CEntity*)node->item; - if (!movingEnt->bIsInSafePosition) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CEntity *movingEnt = (CEntity *)node->item; + if(!movingEnt->bIsInSafePosition) { movingEnt->ProcessShift(); movingEnt->GetMatrix().UpdateRW(); movingEnt->UpdateRwFrame(); - if (!movingEnt->bIsInSafePosition) { - movingEnt->bIsStuck = true; - } + if(!movingEnt->bIsInSafePosition) { movingEnt->bIsStuck = true; } } } bSecondShift = true; - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CPhysical* movingEnt = (CPhysical*)node->item; - if (!movingEnt->bIsInSafePosition) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CPhysical *movingEnt = (CPhysical *)node->item; + if(!movingEnt->bIsInSafePosition) { movingEnt->ProcessShift(); movingEnt->GetMatrix().UpdateRW(); movingEnt->UpdateRwFrame(); - if (!movingEnt->bIsInSafePosition) { + if(!movingEnt->bIsInSafePosition) { movingEnt->bIsStuck = true; - if (movingEnt->m_status == STATUS_PLAYER) { - printf("STUCK: Final Step: Player Entity %d Is Stuck\n", movingEnt->m_modelIndex); + if(movingEnt->m_status == STATUS_PLAYER) { + printf("STUCK: Final Step: Player Entity %d Is Stuck\n", + movingEnt->m_modelIndex); movingEnt->m_vecMoveSpeed *= 0.3f; movingEnt->ApplyMoveSpeed(); movingEnt->ApplyTurnSpeed(); @@ -1931,35 +2019,28 @@ CWorld::Process(void) } } } - for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { - CPed* movingPed = (CPed*)node->item; - if (movingPed->IsPed()) { - if (movingPed->bInVehicle && movingPed->m_nPedState != PED_EXIT_TRAIN || movingPed->EnteringCar()) { + for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) { + CPed *movingPed = (CPed *)node->item; + if(movingPed->IsPed()) { + if(movingPed->bInVehicle && movingPed->m_nPedState != PED_EXIT_TRAIN || + movingPed->EnteringCar()) { CVehicle *movingCar = movingPed->m_pMyVehicle; - if (movingCar) { - if (movingCar->IsTrain()) { + if(movingCar) { + if(movingCar->IsTrain()) { movingPed->SetPedPositionInTrain(); } else { - switch (movingPed->m_nPedState) { - case PED_ENTER_CAR: - case PED_CARJACK: - movingPed->EnterCar(); - break; - case PED_DRAG_FROM_CAR: + switch(movingPed->m_nPedState) { + case PED_ENTER_CAR: + case PED_CARJACK: movingPed->EnterCar(); break; + case PED_DRAG_FROM_CAR: movingPed->BeingDraggedFromCar(); break; + case PED_EXIT_CAR: movingPed->ExitCar(); break; + case PED_ARRESTED: + if(movingPed->m_nLastPedState == PED_DRAG_FROM_CAR) { movingPed->BeingDraggedFromCar(); break; - case PED_EXIT_CAR: - movingPed->ExitCar(); - break; - case PED_ARRESTED: - if (movingPed->m_nLastPedState == PED_DRAG_FROM_CAR) { - movingPed->BeingDraggedFromCar(); - break; - } - // fall through - default: - movingPed->SetPedPositionInCar(); - break; + } + // fall through + default: movingPed->SetPedPositionInCar(); break; } } movingPed->GetMatrix().UpdateRW(); @@ -1974,16 +2055,17 @@ CWorld::Process(void) CMessages::Process(); Players[PlayerInFocus].Process(); CRecordDataForChase::SaveOrRetrieveCarPositions(); - if ((CTimer::GetFrameCounter() & 7) == 1) { + if((CTimer::GetFrameCounter() & 7) == 1) { RemoveFallenPeds(); - } else if ((CTimer::GetFrameCounter() & 7) == 5) { + } else if((CTimer::GetFrameCounter() & 7) == 5) { RemoveFallenCars(); } } } -void -CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer) +void +CWorld::TriggerExplosion(const CVector &position, float fRadius, float fPower, CEntity *pCreator, + bool bProcessVehicleBombTimer) { CVector2D vecStartPos(position.x - fRadius, position.y - fRadius); CVector2D vecEndPos(position.x + fRadius, position.y + fRadius); @@ -1991,52 +2073,60 @@ CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, C const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); - for (int32 y = nStartY; y <= nEndY; y++) { - for (int32 x = nStartX; x <= nEndX; x++) { - CSector* pSector = CWorld::GetSector(x, y); - CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], position, fRadius, fPower, pCreator, bProcessVehicleBombTimer); - CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_PEDS], position, fRadius, fPower, pCreator, bProcessVehicleBombTimer); - CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], position, fRadius, fPower, pCreator, bProcessVehicleBombTimer); + for(int32 y = nStartY; y <= nEndY; y++) { + for(int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], position, fRadius, + fPower, pCreator, bProcessVehicleBombTimer); + CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_PEDS], position, fRadius, fPower, + pCreator, bProcessVehicleBombTimer); + CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], position, fRadius, + fPower, pCreator, bProcessVehicleBombTimer); } } - } void -CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer) +CWorld::TriggerExplosionSectorList(CPtrList &list, const CVector &position, float fRadius, float fPower, + CEntity *pCreator, bool bProcessVehicleBombTimer) { - for (CPtrNode* pNode = list.first; pNode; pNode = pNode->next) { - CPhysical* pEntity = (CPhysical*)pNode->item; - CVector vecDistance = pEntity->GetPosition() - position; - float fMagnitude = vecDistance.Magnitude(); - if(fRadius > fMagnitude) { - CWeapon::BlowUpExplosiveThings(pEntity); - CPed *pPed = (CPed *)pEntity; - CObject *pObject = (CObject *)pEntity; - CVehicle *pVehicle = (CVehicle *)pEntity; - if(!pEntity->bExplosionProof && (!pEntity->IsPed() || !pPed->bInVehicle)) { - if(pEntity->bIsStatic) { - if (pEntity->IsObject()) { - if (fPower > pObject->m_fUprootLimit || IsFence(pObject->m_modelIndex)) { - if (IsGlass(pObject->m_modelIndex)) { + for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) { + CPhysical *pEntity = (CPhysical *)pNode->item; + CVector vecDistance = pEntity->GetPosition() - position; + float fMagnitude = vecDistance.Magnitude(); + if(fRadius > fMagnitude) { + CWeapon::BlowUpExplosiveThings(pEntity); + CPed *pPed = (CPed *)pEntity; + CObject *pObject = (CObject *)pEntity; + CVehicle *pVehicle = (CVehicle *)pEntity; + if(!pEntity->bExplosionProof && (!pEntity->IsPed() || !pPed->bInVehicle)) { + if(pEntity->bIsStatic) { + if(pEntity->IsObject()) { + if(fPower > pObject->m_fUprootLimit || IsFence(pObject->m_modelIndex)) { + if(IsGlass(pObject->m_modelIndex)) { CGlass::WindowRespondsToExplosion(pObject, position); } else { pObject->bIsStatic = false; pObject->AddToMovingList(); int16 modelId = pEntity->m_modelIndex; - if (modelId != MI_FIRE_HYDRANT || pObject->bHasBeenDamaged) { - if (pEntity->IsObject() && modelId != MI_EXPLODINGBARREL && modelId != MI_PETROLPUMP) + if(modelId != MI_FIRE_HYDRANT || + pObject->bHasBeenDamaged) { + if(pEntity->IsObject() && + modelId != MI_EXPLODINGBARREL && + modelId != MI_PETROLPUMP) pObject->bHasBeenDamaged = true; } else { CVector pos = pEntity->GetPosition(); pos.z -= 0.5f; - CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, pos, true); + CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, + pos, true); pObject->bHasBeenDamaged = true; } } } - if (pEntity->bIsStatic) { - float fDamageMultiplier = (fRadius - fMagnitude) * 2.0f / fRadius; + if(pEntity->bIsStatic) { + float fDamageMultiplier = + (fRadius - fMagnitude) * 2.0f / fRadius; float fDamage = 300.0f * min(fDamageMultiplier, 1.0f); pObject->ObjectDamage(fDamage); } @@ -2045,37 +2135,37 @@ CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, floa pEntity->AddToMovingList(); } } - if (!pEntity->bIsStatic) { + if(!pEntity->bIsStatic) { float fDamageMultiplier = min((fRadius - fMagnitude) * 2.0f / fRadius, 1.0f); - CVector vecForceDir = vecDistance * (fPower * pEntity->m_fMass * 0.00071429f * fDamageMultiplier / max(fMagnitude, 0.01f)); + CVector vecForceDir = + vecDistance * (fPower * pEntity->m_fMass * 0.00071429f * fDamageMultiplier / + max(fMagnitude, 0.01f)); vecForceDir.z = max(vecForceDir.z, 0.0f); - if (pEntity == FindPlayerPed()) - vecForceDir.z = min(vecForceDir.z, 1.0f); + if(pEntity == FindPlayerPed()) vecForceDir.z = min(vecForceDir.z, 1.0f); pEntity->ApplyMoveForce(vecForceDir); - if (!pEntity->bPedPhysics) { + if(!pEntity->bPedPhysics) { float fBoundRadius = pEntity->GetBoundRadius(); float fDistanceZ = position.z - pEntity->GetPosition().z; float fPointZ = fBoundRadius; - if (max(fDistanceZ, -fBoundRadius) < fBoundRadius) - { - if (fDistanceZ <= -fBoundRadius) + if(max(fDistanceZ, -fBoundRadius) < fBoundRadius) { + if(fDistanceZ <= -fBoundRadius) fPointZ = -fBoundRadius; else fPointZ = fDistanceZ; } - pEntity->ApplyTurnForce(vecForceDir.x, vecForceDir.y, vecForceDir.z, 0.0f, 0.0f, fPointZ); + pEntity->ApplyTurnForce(vecForceDir.x, vecForceDir.y, vecForceDir.z, + 0.0f, 0.0f, fPointZ); } - switch (pEntity->m_type) - { + switch(pEntity->m_type) { case ENTITY_TYPE_VEHICLE: - if (pEntity->m_status == STATUS_SIMPLE) { + if(pEntity->m_status == STATUS_SIMPLE) { pEntity->m_status = STATUS_PHYSICS; CCarCtrl::SwitchVehicleToRealPhysics(pVehicle); } - pVehicle->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, 1100.0f * fDamageMultiplier); - if (bProcessVehicleBombTimer) { - if (pVehicle->m_nBombTimer) - pVehicle->m_nBombTimer /= 10; + pVehicle->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, + 1100.0f * fDamageMultiplier); + if(bProcessVehicleBombTimer) { + if(pVehicle->m_nBombTimer) pVehicle->m_nBombTimer /= 10; } break; case ENTITY_TYPE_PED: { @@ -2083,14 +2173,16 @@ CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, floa pPed->bIsStanding = false; pPed->ApplyMoveForce(0.0, 0.0, 2.0f); float fDamage = 250.0f * fDamageMultiplier; - pPed->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, fDamage, PEDPIECE_TORSO, direction); - if (pPed->m_nPedState!= PED_DIE) - pPed->SetFall(2000, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0); - if (pCreator && pCreator->IsPed()) { + pPed->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, fDamage, + PEDPIECE_TORSO, direction); + if(pPed->m_nPedState != PED_DIE) + pPed->SetFall(2000, + (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0); + if(pCreator && pCreator->IsPed()) { eEventType eventType = EVENT_SHOOT_PED; - if (pPed->m_nPedType == PEDTYPE_COP) - eventType = EVENT_SHOOT_COP; - CEventList::RegisterEvent(eventType, EVENT_ENTITY_PED, pEntity, (CPed*)pCreator, 10000); + if(pPed->m_nPedType == PEDTYPE_COP) eventType = EVENT_SHOOT_COP; + CEventList::RegisterEvent(eventType, EVENT_ENTITY_PED, pEntity, + (CPed *)pCreator, 10000); pPed->RegisterThreatWithGangPeds(pCreator); } break; @@ -2105,17 +2197,18 @@ CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, floa } } -void -CWorld::UseDetonator(CEntity* pEntity) +void +CWorld::UseDetonator(CEntity *pEntity) { int32 i = CPools::GetVehiclePool()->GetSize(); - while (--i >= 0) { - CAutomobile* pVehicle = (CAutomobile*)CPools::GetVehiclePool()->GetSlot(i); - if (pVehicle && !pVehicle->m_vehType && pVehicle->m_bombType == CARBOMB_REMOTE && pVehicle->m_pBombRigger == pEntity) { + while(--i >= 0) { + CAutomobile *pVehicle = (CAutomobile *)CPools::GetVehiclePool()->GetSlot(i); + if(pVehicle && !pVehicle->m_vehType && pVehicle->m_bombType == CARBOMB_REMOTE && + pVehicle->m_pBombRigger == pEntity) { pVehicle->m_bombType = CARBOMB_NONE; pVehicle->m_nBombTimer = 500; pVehicle->m_pBlowUpEntity = pVehicle->m_pBombRigger; - if (pVehicle->m_pBlowUpEntity) + if(pVehicle->m_pBlowUpEntity) pVehicle->m_pBlowUpEntity->RegisterReference(&pVehicle->m_pBlowUpEntity); } } From ac61da3febc557c16e54bbe8cc946b023e434dc5 Mon Sep 17 00:00:00 2001 From: saml1er Date: Fri, 17 Apr 2020 17:04:09 +0500 Subject: [PATCH 053/123] Fix CWorld::FindObjectsOfTypeInRangeSectorList bug --- src/core/World.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/core/World.cpp b/src/core/World.cpp index 358e1823..c9e3c11f 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -753,14 +753,16 @@ CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList &list, const CEntity *pEntity = (CEntity *)pNode->item; if(pEntity->m_scanCode != GetCurrentScanCode()) { pEntity->m_scanCode = GetCurrentScanCode(); - float fMagnitude = 0.0f; - if(bCheck2DOnly) - fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr2D(); - else - fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr(); - if(fMagnitude < radius * radius && *nEntitiesFound < maxEntitiesToFind) { - if(aEntities) aEntities[*nEntitiesFound] = pEntity; - ++*nEntitiesFound; + if(modelId == pEntity->m_modelIndex) { + float fMagnitude = 0.0f; + if(bCheck2DOnly) + fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr2D(); + else + fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr(); + if(fMagnitude < radius * radius && *nEntitiesFound < maxEntitiesToFind) { + if(aEntities) aEntities[*nEntitiesFound] = pEntity; + ++*nEntitiesFound; + } } } } From 6ef7924e0122155c390698bdd66e9757f4da5fa0 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 17 Apr 2020 15:15:42 +0200 Subject: [PATCH 054/123] implemented CVector2D::NormaliseSafe for SkidMarks --- src/math/Vector2D.h | 12 +++++++----- src/math/math.cpp | 13 +++++++++++++ src/render/Skidmarks.cpp | 3 ++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h index 705ad763..0885a5d2 100644 --- a/src/math/Vector2D.h +++ b/src/math/Vector2D.h @@ -11,16 +11,18 @@ public: float Magnitude(void) const { return Sqrt(x*x + y*y); } float MagnitudeSqr(void) const { return x*x + y*y; } - void Normalise(void){ + void Normalise(void); + + void NormaliseSafe(void) { float sq = MagnitudeSqr(); - //if(sq > 0.0f){ + if(sq > 0.0f){ float invsqrt = RecipSqrt(sq); x *= invsqrt; y *= invsqrt; - //}else - // x = 1.0f; + }else + y = 1.0f; } - + const CVector2D &operator+=(CVector2D const &right) { x += right.x; y += right.y; diff --git a/src/math/math.cpp b/src/math/math.cpp index 4f74fac9..04fab797 100644 --- a/src/math/math.cpp +++ b/src/math/math.cpp @@ -4,6 +4,19 @@ // TODO: move more stuff into here +void +CVector2D::Normalise(void) +{ + float sq = MagnitudeSqr(); + assert(sq != 0.0f); // just be safe here + //if(sq > 0.0f){ + float invsqrt = RecipSqrt(sq); + x *= invsqrt; + y *= invsqrt; + //}else + // x = 1.0f; +} + void CMatrix::SetRotate(float xAngle, float yAngle, float zAngle) { diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp index 41ee5d1d..e003079e 100644 --- a/src/render/Skidmarks.cpp +++ b/src/render/Skidmarks.cpp @@ -214,7 +214,8 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos; CVector2D dist = aSkidmarks[i].m_pos[aSkidmarks[i].m_last] - aSkidmarks[i].m_pos[aSkidmarks[i].m_last-1]; - dist.Normalise(); + dist.NormaliseSafe(); + fwd.NormaliseSafe(); CVector2D right(dist.y, -dist.x); float turn = DotProduct2D(fwd, right); turn = Abs(turn) + 1.0f; From 599164006a9e7eb7328fc194c9bae1acbb2c887d Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Apr 2020 16:31:11 +0300 Subject: [PATCH 055/123] Remove patches --- premake5.lua | 58 +- src/animation/AnimBlendAssocGroup.cpp | 14 +- src/animation/AnimBlendAssociation.cpp | 32 +- src/animation/AnimBlendClumpData.cpp | 19 +- src/animation/AnimBlendHierarchy.cpp | 12 +- src/animation/AnimBlendNode.cpp | 12 +- src/animation/AnimBlendSequence.cpp | 8 +- src/animation/AnimManager.cpp | 22 +- src/animation/CutsceneMgr.cpp | 18 +- src/animation/FrameUpdate.cpp | 8 +- src/animation/RpAnimBlend.cpp | 25 +- src/audio/AudioCollision.cpp | 13 +- src/audio/AudioManager.cpp | 216 +------ src/audio/AudioScriptObject.cpp | 9 +- src/audio/DMAudio.cpp | 56 +- src/audio/MusicManager.cpp | 33 +- src/audio/PoliceRadio.cpp | 18 +- src/audio/sampman.cpp | 65 +- src/control/AutoPilot.cpp | 2 +- src/control/Bridge.cpp | 10 +- src/control/CarAI.cpp | 5 +- src/control/CarCtrl.cpp | 19 +- src/control/Curves.cpp | 2 +- src/control/Darkel.cpp | 18 +- src/control/GameLogic.cpp | 10 +- src/control/Garages.cpp | 9 +- src/control/OnscreenTimer.cpp | 17 +- src/control/PathFind.cpp | 47 +- src/control/Phones.cpp | 19 +- src/control/Pickups.cpp | 46 +- src/control/Record.cpp | 2 +- src/control/Remote.cpp | 7 +- src/control/Replay.cpp | 15 +- src/control/Restart.cpp | 15 +- src/control/RoadBlocks.cpp | 8 +- src/control/SceneEdit.cpp | 2 +- src/control/Script.cpp | 16 +- src/control/TrafficLights.cpp | 8 +- src/core/Accident.cpp | 12 +- src/core/AnimViewer.cpp | 2 +- src/core/Cam.cpp | 54 +- src/core/Camera.cpp | 57 +- src/core/CdStream.cpp | 23 +- src/core/Clock.cpp | 13 +- src/core/Collision.cpp | 69 +-- src/core/ControllerConfig.cpp | 56 +- src/core/Directory.cpp | 9 +- src/core/EventList.cpp | 13 +- src/core/FileLoader.cpp | 42 +- src/core/FileMgr.cpp | 18 +- src/core/Fire.cpp | 20 +- src/core/Frontend.cpp | 20 +- src/core/Game.cpp | 19 +- src/core/IniFile.cpp | 2 +- src/core/Pad.cpp | 120 +--- src/core/Placeable.cpp | 20 +- src/core/PlayerInfo.cpp | 19 +- src/core/Pools.cpp | 18 +- src/core/Radar.cpp | 50 +- src/core/References.cpp | 8 +- src/core/Stats.cpp | 10 +- src/core/Streaming.cpp | 81 +-- src/core/SurfaceTable.cpp | 9 +- src/core/TempColModels.cpp | 6 +- src/core/Timer.cpp | 17 +- src/core/User.cpp | 15 +- src/core/Wanted.cpp | 24 +- src/core/World.cpp | 57 +- src/core/World.h | 26 +- src/core/ZoneCull.cpp | 16 +- src/core/Zones.cpp | 35 +- src/core/main.cpp | 27 +- src/core/re3.cpp | 44 +- src/entities/Building.cpp | 17 +- src/entities/Dummy.cpp | 16 +- src/entities/Entity.cpp | 55 +- src/entities/Physical.cpp | 57 +- src/entities/Treadable.cpp | 12 +- src/math/math.cpp | 7 +- src/modelinfo/BaseModelInfo.cpp | 24 +- src/modelinfo/ClumpModelInfo.cpp | 29 +- src/modelinfo/MloModelInfo.cpp | 2 +- src/modelinfo/ModelIndices.cpp | 9 +- src/modelinfo/ModelIndices.h | 2 +- src/modelinfo/ModelInfo.cpp | 14 +- src/modelinfo/PedModelInfo.cpp | 16 +- src/modelinfo/SimpleModelInfo.cpp | 27 +- src/modelinfo/TimeModelInfo.cpp | 6 +- src/modelinfo/VehicleModelInfo.cpp | 64 +- src/objects/CutsceneHead.cpp | 19 +- src/objects/CutsceneObject.cpp | 24 +- src/objects/DummyObject.cpp | 18 +- src/objects/Object.cpp | 36 +- src/objects/ObjectData.cpp | 7 +- src/objects/ParticleObject.cpp | 38 +- src/objects/Projectile.cpp | 16 +- src/peds/CivilianPed.cpp | 20 +- src/peds/CopPed.cpp | 24 +- src/peds/EmergencyPed.cpp | 19 +- src/peds/Gangs.cpp | 12 +- src/peds/Ped.cpp | 239 +------- src/peds/PedIK.cpp | 18 +- src/peds/PedPlacement.cpp | 7 +- src/peds/PedRoutes.cpp | 2 +- src/peds/PedStats.cpp | 9 +- src/peds/PedType.cpp | 11 +- src/peds/PlayerPed.cpp | 40 +- src/peds/Population.cpp | 15 +- src/render/Antennas.cpp | 16 +- src/render/Clouds.cpp | 11 +- src/render/Console.cpp | 2 +- src/render/Coronas.cpp | 16 +- src/render/Credits.cpp | 12 +- src/render/Draw.cpp | 9 +- src/render/Fluff.cpp | 30 +- src/render/Font.cpp | 47 +- src/render/Glass.cpp | 25 +- src/render/Hud.cpp | 17 +- src/render/Instance.cpp | 13 +- src/render/Lines.cpp | 2 +- src/render/MBlur.cpp | 10 +- src/render/Particle.cpp | 18 +- src/render/ParticleMgr.cpp | 8 +- src/render/PlayerSkin.cpp | 11 +- src/render/PointLights.cpp | 9 +- src/render/RenderBuffer.cpp | 9 +- src/render/Renderer.cpp | 39 +- src/render/Rubbish.cpp | 2 +- src/render/Shadows.cpp | 35 +- src/render/Skidmarks.cpp | 2 +- src/render/SpecialFX.cpp | 31 +- src/render/Sprite.cpp | 18 +- src/render/Sprite2d.cpp | 36 +- src/render/Timecycle.cpp | 7 +- src/render/WaterCannon.cpp | 16 +- src/render/WaterLevel.cpp | 21 +- src/render/Weather.cpp | 2 +- src/rw/ClumpRead.cpp | 8 +- src/rw/Lights.cpp | 23 +- src/rw/NodeName.cpp | 2 +- src/rw/RwHelper.cpp | 10 +- src/rw/RwMatFX.cpp | 9 +- src/rw/TexRead.cpp | 16 +- src/rw/TxdStore.cpp | 24 +- src/rw/VisibilityPlugins.cpp | 58 +- src/rw/rw.cpp | 808 +------------------------ src/save/GenericGameStorage.cpp | 21 +- src/save/PCSave.cpp | 10 +- src/skel/events.cpp | 13 +- src/skel/skeleton.cpp | 25 +- src/skel/win/win.cpp | 63 +- src/text/Messages.cpp | 32 +- src/text/Pager.cpp | 14 +- src/text/Text.cpp | 20 +- src/vehicles/Automobile.cpp | 87 +-- src/vehicles/Boat.cpp | 23 +- src/vehicles/CarGen.cpp | 9 +- src/vehicles/Cranes.cpp | 2 +- src/vehicles/DamageManager.cpp | 23 +- src/vehicles/Door.cpp | 18 +- src/vehicles/Floater.cpp | 11 +- src/vehicles/HandlingMgr.cpp | 10 +- src/vehicles/Heli.cpp | 23 +- src/vehicles/Plane.cpp | 23 +- src/vehicles/Train.cpp | 31 +- src/vehicles/Transmission.cpp | 7 +- src/vehicles/Vehicle.cpp | 49 +- src/weapons/BulletInfo.cpp | 2 +- src/weapons/Explosion.cpp | 17 +- src/weapons/ProjectileInfo.cpp | 15 +- src/weapons/ShotInfo.cpp | 11 +- src/weapons/Weapon.cpp | 38 +- src/weapons/WeaponEffects.cpp | 14 +- src/weapons/WeaponInfo.cpp | 13 +- 174 files changed, 244 insertions(+), 4689 deletions(-) diff --git a/premake5.lua b/premake5.lua index cebc8ee9..586996f8 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,7 +1,7 @@ Librw = os.getenv("LIBRW") workspace "re3" - configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW", "DebugLIBRW" } + configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW" } location "build" files { "src/*.*" } @@ -51,20 +51,20 @@ workspace "re3" libdirs { "dxsdk/lib" } libdirs { "milessdk/lib" } - filter "configurations:*LIBRW" - files { "src/fakerw/*.*" } - includedirs { "src/fakerw" } - includedirs { Librw } - libdirs { path.join(Librw, "lib/win-x86-d3d9/Debug") } - links { "rw", "d3d9" } - - filter "configurations:not *LIBRW" - includedirs { "rwsdk/include/d3d8" } - - filter "configurations:DebugRW or configurations:ReleaseRW" - defines { "RWLIBS" } - libdirs { "rwsdk/lib/d3d8/release" } - links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp" } + filter "configurations:Debug or Release" + files { "src/fakerw/*.*" } + includedirs { "src/fakerw" } + includedirs { "librw" } + includedirs { "librw/src" } + libdirs { path.join("librw", "lib/win-x86-d3d9/%{cfg.buildcfg}") } + links { "rw", "d3d9" } + filter {} + + filter "configurations:DebugRW or ReleaseRW" + defines { "RWLIBS" } + includedirs { "rwsdk/include/d3d8" } + libdirs { "rwsdk/lib/d3d8/release" } + links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp" } filter {} @@ -95,49 +95,43 @@ workspace "re3" end project "re3" - kind "SharedLib" + kind "WindowedApp" language "C++" targetname "re3" targetdir "bin/%{cfg.buildcfg}" - targetextension ".dll" + targetextension ".exe" characterset ("MBCS") linkoptions "/SAFESEH:NO" filter "configurations:Debug" - defines { "DEBUG" } - staticruntime "on" + defines { "DEBUG", "LIBRW", "RW_D3D9" } + staticruntime "off" symbols "Full" - setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") + setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") filter "configurations:Release" - defines { "NDEBUG" } + defines { "NDEBUG", "LIBRW", "RW_D3D9" } optimize "On" - staticruntime "on" + staticruntime "off" symbols "Full" - setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") + setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") filter "configurations:ReleaseFH" defines { "NDEBUG" } symbols "Full" optimize "off" staticruntime "on" - targetextension ".asi" - setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "scripts/") + setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") filter "configurations:DebugRW" defines { "DEBUG" } staticruntime "on" symbols "On" - setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") + setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") filter "configurations:ReleaseRW" defines { "NDEBUG" } optimize "On" staticruntime "on" - setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") - - filter "configurations:DebugLIBRW" - defines { "DEBUG", "LIBRW", "RW_D3D9" } - symbols "On" - setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") + setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp index ecdebd29..e65bdf8d 100644 --- a/src/animation/AnimBlendAssocGroup.cpp +++ b/src/animation/AnimBlendAssocGroup.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "ModelInfo.h" #include "AnimManager.h" @@ -148,15 +148,3 @@ CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump, } numAssociations = numAssocs; } - - - -STARTPATCHES - InjectHook(0x4012D0, &CAnimBlendAssocGroup::DestroyAssociations, PATCH_JUMP); - InjectHook(0x4013D0, (CAnimBlendAssociation *(CAnimBlendAssocGroup::*)(uint32))&CAnimBlendAssocGroup::GetAnimation, PATCH_JUMP); - InjectHook(0x401300, (CAnimBlendAssociation *(CAnimBlendAssocGroup::*)(const char*))&CAnimBlendAssocGroup::GetAnimation, PATCH_JUMP); - InjectHook(0x401420, (CAnimBlendAssociation *(CAnimBlendAssocGroup::*)(uint32))&CAnimBlendAssocGroup::CopyAnimation, PATCH_JUMP); - InjectHook(0x4013E0, (CAnimBlendAssociation *(CAnimBlendAssocGroup::*)(const char*))&CAnimBlendAssocGroup::CopyAnimation, PATCH_JUMP); - InjectHook(0x401130, (void (CAnimBlendAssocGroup::*)(const char*))&CAnimBlendAssocGroup::CreateAssociations, PATCH_JUMP); - InjectHook(0x401220, (void (CAnimBlendAssocGroup::*)(const char*, RpClump*, const char**, int))&CAnimBlendAssocGroup::CreateAssociations, PATCH_JUMP); -ENDPATCHES diff --git a/src/animation/AnimBlendAssociation.cpp b/src/animation/AnimBlendAssociation.cpp index 246322ba..fb8c16d7 100644 --- a/src/animation/AnimBlendAssociation.cpp +++ b/src/animation/AnimBlendAssociation.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "AnimBlendHierarchy.h" #include "AnimBlendClumpData.h" #include "RpAnimBlend.h" @@ -202,33 +202,3 @@ CAnimBlendAssociation::UpdateBlend(float timeDelta) return true; } - -#include - -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); - InjectHook(0x4016F0, &CAnimBlendAssociation::FreeAnimBlendNodeArray, PATCH_JUMP); - InjectHook(0x4017B0, &CAnimBlendAssociation::GetNode, PATCH_JUMP); - InjectHook(0x401560, (void (CAnimBlendAssociation::*)(RpClump*, CAnimBlendHierarchy*))&CAnimBlendAssociation::Init, PATCH_JUMP); - InjectHook(0x401620, (void (CAnimBlendAssociation::*)(CAnimBlendAssociation&))&CAnimBlendAssociation::Init, PATCH_JUMP); - InjectHook(0x4017E0, &CAnimBlendAssociation::SetBlend, PATCH_JUMP); - InjectHook(0x401820, &CAnimBlendAssociation::SetFinishCallback, PATCH_JUMP); - InjectHook(0x401800, &CAnimBlendAssociation::SetDeleteCallback, PATCH_JUMP); - InjectHook(0x401700, &CAnimBlendAssociation::SetCurrentTime, PATCH_JUMP); - InjectHook(0x401780, &CAnimBlendAssociation::SyncAnimation, PATCH_JUMP); - InjectHook(0x4017D0, &CAnimBlendAssociation::Start, PATCH_JUMP); - 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); -ENDPATCHES diff --git a/src/animation/AnimBlendClumpData.cpp b/src/animation/AnimBlendClumpData.cpp index cc4281d6..d40e8357 100644 --- a/src/animation/AnimBlendClumpData.cpp +++ b/src/animation/AnimBlendClumpData.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "AnimBlendClumpData.h" #include "RwHelper.h" @@ -35,20 +35,3 @@ CAnimBlendClumpData::ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void * for(i = 0; i < numFrames; i++) cb(&frames[i], arg); } - -#include - -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(0x4018F0, &CAnimBlendClumpData::SetNumberOfFrames, PATCH_JUMP); - InjectHook(0x401930, &CAnimBlendClumpData::ForAllFrames, PATCH_JUMP); -ENDPATCHES diff --git a/src/animation/AnimBlendHierarchy.cpp b/src/animation/AnimBlendHierarchy.cpp index e4bcdc69..7f39d37a 100644 --- a/src/animation/AnimBlendHierarchy.cpp +++ b/src/animation/AnimBlendHierarchy.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "AnimBlendSequence.h" #include "AnimBlendHierarchy.h" @@ -72,13 +72,3 @@ CAnimBlendHierarchy::RemoveUncompressedData(void) // useless compressed = 1; } - -STARTPATCHES - InjectHook(0x4019A0, &CAnimBlendHierarchy::Shutdown, PATCH_JUMP); - InjectHook(0x4019C0, &CAnimBlendHierarchy::SetName, PATCH_JUMP); - InjectHook(0x4019E0, &CAnimBlendHierarchy::CalcTotalTime, PATCH_JUMP); - InjectHook(0x401A80, &CAnimBlendHierarchy::RemoveQuaternionFlips, PATCH_JUMP); - InjectHook(0x401AB0, &CAnimBlendHierarchy::RemoveAnimSequences, PATCH_JUMP); - InjectHook(0x401AD0, &CAnimBlendHierarchy::Uncompress, PATCH_JUMP); - InjectHook(0x401B00, &CAnimBlendHierarchy::RemoveUncompressedData, PATCH_JUMP); -ENDPATCHES diff --git a/src/animation/AnimBlendNode.cpp b/src/animation/AnimBlendNode.cpp index be5fcc9c..193e9176 100644 --- a/src/animation/AnimBlendNode.cpp +++ b/src/animation/AnimBlendNode.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "AnimBlendAssociation.h" #include "AnimBlendNode.h" @@ -158,13 +158,3 @@ CAnimBlendNode::GetEndTranslation(CVector &trans, float weight) trans = kf->translation * blend; } } - -STARTPATCHES - InjectHook(0x401B10, &CAnimBlendNode::Init, PATCH_JUMP); - InjectHook(0x401B30, &CAnimBlendNode::Update, PATCH_JUMP); - InjectHook(0x401DC0, &CAnimBlendNode::NextKeyFrame, PATCH_JUMP); - InjectHook(0x4021B0, &CAnimBlendNode::FindKeyFrame, PATCH_JUMP); - InjectHook(0x401E70, &CAnimBlendNode::CalcDeltas, PATCH_JUMP); - InjectHook(0x401FE0, &CAnimBlendNode::GetCurrentTranslation, PATCH_JUMP); - InjectHook(0x402110, &CAnimBlendNode::GetEndTranslation, PATCH_JUMP); -ENDPATCHES diff --git a/src/animation/AnimBlendSequence.cpp b/src/animation/AnimBlendSequence.cpp index 4b675774..4578ec50 100644 --- a/src/animation/AnimBlendSequence.cpp +++ b/src/animation/AnimBlendSequence.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "AnimBlendSequence.h" CAnimBlendSequence::CAnimBlendSequence(void) @@ -60,9 +60,3 @@ CAnimBlendSequence::RemoveQuaternionFlips(void) last = frame->rotation; } } - -STARTPATCHES - InjectHook(0x402330, &CAnimBlendSequence::SetName, PATCH_JUMP); - InjectHook(0x402350, &CAnimBlendSequence::SetNumFrames, PATCH_JUMP); - InjectHook(0x4023A0, &CAnimBlendSequence::RemoveQuaternionFlips, PATCH_JUMP); -ENDPATCHES diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index 82343e93..7c09b0dd 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "ModelInfo.h" #include "ModelIndices.h" @@ -909,23 +909,3 @@ CAnimManager::RemoveLastAnimFile(void) for(i = 0; i < ms_aAnimBlocks[ms_numAnimBlocks].numAnims; i++) ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].RemoveAnimSequences(); } - - -STARTPATCHES - InjectHook(0x403380, CAnimManager::Initialise, PATCH_JUMP); - InjectHook(0x4033B0, CAnimManager::Shutdown, PATCH_JUMP); - InjectHook(0x403410, CAnimManager::UncompressAnimation, PATCH_JUMP); - InjectHook(0x4034A0, CAnimManager::GetAnimationBlock, PATCH_JUMP); - InjectHook(0x4034F0, (CAnimBlendHierarchy *(*)(const char*, CAnimBlock*))CAnimManager::GetAnimation, PATCH_JUMP); - InjectHook(0x4035B0, CAnimManager::GetAnimGroupName, PATCH_JUMP); - InjectHook(0x4035C0, CAnimManager::CreateAnimAssociation, PATCH_JUMP); - InjectHook(0x4035E0, (CAnimBlendAssociation *(*)(AssocGroupId, AnimationId))CAnimManager::GetAnimAssociation, PATCH_JUMP); - InjectHook(0x403600, (CAnimBlendAssociation *(*)(AssocGroupId, const char*))CAnimManager::GetAnimAssociation, PATCH_JUMP); - InjectHook(0x403620, CAnimManager::AddAnimation, PATCH_JUMP); - InjectHook(0x4036A0, CAnimManager::AddAnimationAndSync, PATCH_JUMP); - InjectHook(0x403710, CAnimManager::BlendAnimation, PATCH_JUMP); - InjectHook(0x4038F0, CAnimManager::LoadAnimFiles, PATCH_JUMP); - InjectHook(0x403A10, (void (*)(const char *))CAnimManager::LoadAnimFile, PATCH_JUMP); - InjectHook(0x403A40, (void (*)(int, bool))CAnimManager::LoadAnimFile, PATCH_JUMP); - InjectHook(0x404320, CAnimManager::RemoveLastAnimFile, PATCH_JUMP); -ENDPATCHES diff --git a/src/animation/CutsceneMgr.cpp b/src/animation/CutsceneMgr.cpp index 5c0daaf0..6d9b9755 100644 --- a/src/animation/CutsceneMgr.cpp +++ b/src/animation/CutsceneMgr.cpp @@ -1,6 +1,6 @@ #define WITHWINDOWS // just for VK_SPACE #include "common.h" -#include "patcher.h" + #include "General.h" #include "CutsceneMgr.h" #include "Directory.h" @@ -423,19 +423,3 @@ CCutsceneMgr::Update(void) bool CCutsceneMgr::HasCutsceneFinished(void) { return TheCamera.GetPositionAlongSpline() == 1.0f; } -STARTPATCHES - InjectHook(0x4045D0, &CCutsceneMgr::Initialise, PATCH_JUMP); - InjectHook(0x404630, &CCutsceneMgr::Shutdown, PATCH_JUMP); - InjectHook(0x404650, &CCutsceneMgr::LoadCutsceneData, PATCH_JUMP); - InjectHook(0x405140, &CCutsceneMgr::FinishCutscene, PATCH_JUMP); - InjectHook(0x404D80, &CCutsceneMgr::SetHeadAnim, PATCH_JUMP); - InjectHook(0x404DC0, &CCutsceneMgr::SetupCutsceneToStart, PATCH_JUMP); - InjectHook(0x404D20, &CCutsceneMgr::SetCutsceneAnim, PATCH_JUMP); - InjectHook(0x404CD0, &CCutsceneMgr::AddCutsceneHead, PATCH_JUMP); - InjectHook(0x404BE0, &CCutsceneMgr::CreateCutsceneObject, PATCH_JUMP); - InjectHook(0x4048E0, &CCutsceneMgr::DeleteCutsceneData, PATCH_JUMP); - InjectHook(0x404EE0, &CCutsceneMgr::Update, PATCH_JUMP); - InjectHook(0x4051B0, &CCutsceneMgr::GetCutsceneTimeInMilleseconds, PATCH_JUMP); - InjectHook(0x4051F0, &CCutsceneMgr::HasCutsceneFinished, PATCH_JUMP); - InjectHook(0x404B40, &CalculateBoundingSphereRadiusCB, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp index 393d22a8..df45bfb5 100644 --- a/src/animation/FrameUpdate.cpp +++ b/src/animation/FrameUpdate.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "NodeName.h" #include "VisibilityPlugins.h" #include "AnimBlendClumpData.h" @@ -220,9 +220,3 @@ FrameUpdateCallBackWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg } RwMatrixUpdate(mat); } - -STARTPATCHES - InjectHook(0x4025F0, FrameUpdateCallBack, PATCH_JUMP); - InjectHook(0x4028B0, FrameUpdateCallBackWithVelocityExtraction, PATCH_JUMP); - InjectHook(0x402D40, FrameUpdateCallBackWith3dVelocityExtraction, PATCH_JUMP); -ENDPATCHES diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp index 07b8e7d8..20290666 100644 --- a/src/animation/RpAnimBlend.cpp +++ b/src/animation/RpAnimBlend.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "NodeName.h" #include "VisibilityPlugins.h" @@ -378,26 +378,3 @@ RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta) } RwFrameUpdateObjects(RpClumpGetFrame(clump)); } - - -STARTPATCHES - InjectHook(0x4052D0, RpAnimBlendPluginAttach, PATCH_JUMP); - InjectHook(0x4052A0, RpAnimBlendAllocateData, PATCH_JUMP); - InjectHook(0x405780, (CAnimBlendAssociation *(*)(CAnimBlendAssociation*))RpAnimBlendGetNextAssociation, PATCH_JUMP); - InjectHook(0x4057A0, (CAnimBlendAssociation *(*)(CAnimBlendAssociation*,uint32))RpAnimBlendGetNextAssociation, PATCH_JUMP); - - InjectHook(0x405520, RpAnimBlendClumpSetBlendDeltas, PATCH_JUMP); - InjectHook(0x405560, RpAnimBlendClumpRemoveAllAssociations, PATCH_JUMP); - InjectHook(0x405570, RpAnimBlendClumpRemoveAssociations, PATCH_JUMP); - InjectHook(0x405480, RpAnimBlendClumpInit, PATCH_JUMP); - InjectHook(0x405500, RpAnimBlendClumpIsInitialized, PATCH_JUMP); - InjectHook(0x4055C0, RpAnimBlendClumpGetAssociation, PATCH_JUMP); - InjectHook(0x4055F0, RpAnimBlendClumpGetMainAssociation, PATCH_JUMP); - InjectHook(0x405680, RpAnimBlendClumpGetMainPartialAssociation, PATCH_JUMP); - InjectHook(0x4056D0, RpAnimBlendClumpGetMainAssociation_N, PATCH_JUMP); - InjectHook(0x405710, RpAnimBlendClumpGetMainPartialAssociation_N, PATCH_JUMP); - InjectHook(0x405750, (CAnimBlendAssociation *(*)(RpClump*, uint32))RpAnimBlendClumpGetFirstAssociation, PATCH_JUMP); - InjectHook(0x4031B0, (CAnimBlendAssociation *(*)(RpClump*))RpAnimBlendClumpGetFirstAssociation, PATCH_JUMP); - InjectHook(0x405460, RpAnimBlendClumpFillFrameArray, PATCH_JUMP); - InjectHook(0x4024B0, RpAnimBlendClumpUpdateAnimations, PATCH_JUMP); -ENDPATCHES diff --git a/src/audio/AudioCollision.cpp b/src/audio/AudioCollision.cpp index fecd079e..ac8e04c3 100644 --- a/src/audio/AudioCollision.cpp +++ b/src/audio/AudioCollision.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "DMAudio.h" #include "Entity.h" #include "AudioCollision.h" @@ -406,14 +406,3 @@ cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface m_sCollisionManager.AddCollisionToRequestedQueue(); } } - -STARTPATCHES -InjectHook(0x5685E0, &cAudioCollisionManager::AddCollisionToRequestedQueue, PATCH_JUMP); -InjectHook(0x569060, &cAudioManager::GetCollisionOneShotRatio, PATCH_JUMP); -InjectHook(0x5693B0, &cAudioManager::GetCollisionRatio, PATCH_JUMP); -InjectHook(0x568410, &cAudioManager::ReportCollision, PATCH_JUMP); -InjectHook(0x5686D0, &cAudioManager::ServiceCollisions, PATCH_JUMP); -InjectHook(0x568E20, &cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol, PATCH_JUMP); -InjectHook(0x568D30, &cAudioManager::SetUpLoopingCollisionSound, PATCH_JUMP); -InjectHook(0x5689D0, &cAudioManager::SetUpOneShotCollisionSound, PATCH_JUMP); -ENDPATCHES diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 2ee7e602..4d5f8474 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "audio_enums.h" #include "AudioManager.h" @@ -10147,217 +10147,3 @@ cAudioManager::ComputeEmittingVolume(uint8 emittingVolume, float intensity, floa quatIntensity; return emittingVolume; } - -// STARTPATCHES -// InjectHook(0x57B210, &cAudioManager::AddDetailsToRequestedOrderList, PATCH_JUMP); -// InjectHook(0x56AD30, &cAudioManager::AddPlayerCarSample, PATCH_JUMP); -// InjectHook(0x57B300, &cAudioManager::AddReflectionsToRequestedQueue, PATCH_JUMP); -// InjectHook(0x57B8D0, &cAudioManager::AddReleasingSounds, PATCH_JUMP); -// InjectHook(0x57B070, &cAudioManager::AddSampleToRequestedQueue, PATCH_JUMP); -// InjectHook(0x5697A0, &cAudioManager::CalculateDistance, PATCH_JUMP); -// InjectHook(0x57AA10, &cAudioManager::CheckForAnAudioFileOnCD, PATCH_JUMP); -// InjectHook(0x57C160, &cAudioManager::ClearActiveSamples, PATCH_JUMP); -// InjectHook(0x5796A0, &cAudioManager::ClearMissionAudio, PATCH_JUMP); -// InjectHook(0x57C120, &cAudioManager::ClearRequestedQueue, PATCH_JUMP); -// InjectHook(0x57AE00, &cAudioManager::ComputeDopplerEffectedFrequency, PATCH_JUMP); -// InjectHook(0x57AD20, &cAudioManager::ComputePan, PATCH_JUMP); -// InjectHook(0x57ABB0, &cAudioManager::ComputeVolume, PATCH_JUMP); -// InjectHook(0x57A310, &cAudioManager::CreateEntity, PATCH_JUMP); -// InjectHook(0x57A830, &cAudioManager::DestroyAllGameCreatedEntities, PATCH_JUMP); -// InjectHook(0x57A400, &cAudioManager::DestroyEntity, PATCH_JUMP); -// InjectHook(0x57C290, &cAudioManager::GenerateIntegerRandomNumberTable, PATCH_JUMP); -// InjectHook(0x57A8C0, &cAudioManager::Get3DProviderName, PATCH_JUMP); -// InjectHook(0x571110, &cAudioManager::GetArmyTalkSfx, PATCH_JUMP); -// InjectHook(0x573AB0, &cAudioManager::GetBlackBusinessFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x572050, &cAudioManager::GetBlackCasualFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x574380, &cAudioManager::GetBlackConstructionWorkerTalkSfx, PATCH_JUMP); -// InjectHook(0x571D80, &cAudioManager::GetBlackCriminalTalkSfx, PATCH_JUMP); -// InjectHook(0x5735E0, &cAudioManager::GetBlackDockerMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5724D0, &cAudioManager::GetBlackFatFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5726C0, &cAudioManager::GetBlackFatMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5728B0, &cAudioManager::GetBlackFemaleProstituteTalkSfx, PATCH_JUMP); -// InjectHook(0x572C20, &cAudioManager::GetBlackProjectFemaleOldTalkSfx, PATCH_JUMP); -// InjectHook(0x572D20, &cAudioManager::GetBlackProjectFemaleYoungTalkSfx, PATCH_JUMP); -// InjectHook(0x572AF0, &cAudioManager::GetBlackProjectMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5739C0, &cAudioManager::GetBlackWorkerMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x574FF0, &cAudioManager::GetBomberTalkSfx, PATCH_JUMP); -// InjectHook(0x5712C0, &cAudioManager::GetBusinessMaleOldTalkSfx, PATCH_JUMP); -// InjectHook(0x5713E0, &cAudioManager::GetBusinessMaleYoungTalkSfx, PATCH_JUMP); -// InjectHook(0x572040, &cAudioManager::GetCasualMaleOldTalkSfx, PATCH_JUMP); -// InjectHook(0x574FE0, &cAudioManager::GetCatatalinaTalkSfx, PATCH_JUMP); -// InjectHook(0x57AA30, &cAudioManager::GetCDAudioDriveLetter, PATCH_JUMP); -// InjectHook(0x573010, &cAudioManager::GetChinatownFemaleOldTalkSfx, PATCH_JUMP); -// InjectHook(0x5730F0, &cAudioManager::GetChinatownFemaleYoungTalkSfx, PATCH_JUMP); -// InjectHook(0x572E10, &cAudioManager::GetChinatownMaleOldTalkSfx, PATCH_JUMP); -// InjectHook(0x572F10, &cAudioManager::GetChinatownMaleYoungTalkSfx, PATCH_JUMP); -// InjectHook(0x575120, &cAudioManager::GetChunkyTalkSfx, PATCH_JUMP); -// InjectHook(0x571B00, &cAudioManager::GetColumbianTalkSfx, PATCH_JUMP); -// InjectHook(0x570EA0, &cAudioManager::GetCopTalkSfx, PATCH_JUMP); -// InjectHook(0x57A8F0, &cAudioManager::GetCurrent3DProviderIndex, PATCH_JUMP); -// InjectHook(0x571770, &cAudioManager::GetDiabloTalkSfx, PATCH_JUMP); -// InjectHook(0x569750, &cAudioManager::GetDistanceSquared, PATCH_JUMP); -// InjectHook(0x574DA0, &cAudioManager::GetEightTalkSfx, PATCH_JUMP); -// InjectHook(0x574040, &cAudioManager::GetFanFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x573F60, &cAudioManager::GetFanMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x571040, &cAudioManager::GetFBITalkSfx, PATCH_JUMP); -// InjectHook(0x572280, &cAudioManager::GetFemaleNo3TalkSfx, PATCH_JUMP); -// InjectHook(0x5712B0, &cAudioManager::GetFiremanTalkSfx, PATCH_JUMP); -// InjectHook(0x574E50, &cAudioManager::GetFrankieTalkSfx, PATCH_JUMP); -// InjectHook(0x575510, &cAudioManager::GetGenericFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x575460, &cAudioManager::GetGenericMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x571C30, &cAudioManager::GetHoodTalkSfx, PATCH_JUMP); -// InjectHook(0x5741F0, &cAudioManager::GetHospitalFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x574120, &cAudioManager::GetHospitalMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x56F410, &cAudioManager::GetJumboTaxiFreq, PATCH_JUMP); -// InjectHook(0x573310, &cAudioManager::GetLittleItalyFemaleOldTalkSfx, PATCH_JUMP); -// InjectHook(0x573400, &cAudioManager::GetLittleItalyFemaleYoungTalkSfx, PATCH_JUMP); -// InjectHook(0x5731E0, &cAudioManager::GetLittleItalyMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x571510, &cAudioManager::GetMafiaTalkSfx, PATCH_JUMP); -// InjectHook(0x571F40, &cAudioManager::GetMaleNo2TalkSfx, PATCH_JUMP); -// InjectHook(0x5711C0, &cAudioManager::GetMedicTalkSfx, PATCH_JUMP); -// InjectHook(0x5795D0, &cAudioManager::GetMissionAudioLoadingStatus, PATCH_JUMP); -// InjectHook(0x574F00, &cAudioManager::GetMistyTalkSfx, PATCH_JUMP); -// InjectHook(0x575340, &cAudioManager::GetNormalMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x57A8A0, &cAudioManager::GetNum3DProvidersAvailable, PATCH_JUMP); -// InjectHook(0x574FD0, &cAudioManager::GetOJGTalkSfx, PATCH_JUMP); -// InjectHook(0x570960, &cAudioManager::GetPedCommentSfx, PATCH_JUMP); -// InjectHook(0x570DB0, &cAudioManager::GetPhrase, PATCH_JUMP); -// InjectHook(0x56BF80, &cAudioManager::GetVehicleDriveWheelSkidValue, PATCH_JUMP); -// InjectHook(0x56C120, &cAudioManager::GetVehicleNonDriveWheelSkidValue, PATCH_JUMP); -// InjectHook(0x575240, &cAudioManager::GetPimpTalkSfx, PATCH_JUMP); -// InjectHook(0x570E00, &cAudioManager::GetPlayerTalkSfx, PATCH_JUMP); -// InjectHook(0x5737E0, &cAudioManager::GetScumFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5736D0, &cAudioManager::GetScumMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x575060, &cAudioManager::GetSecurityGuardTalkSfx, PATCH_JUMP); -// InjectHook(0x574480, &cAudioManager::GetShopperFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x574790, &cAudioManager::GetSpecialCharacterTalkSfx, PATCH_JUMP); -// InjectHook(0x573E90, &cAudioManager::GetStewardFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x573DC0, &cAudioManager::GetStewardMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x574690, &cAudioManager::GetStudentFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x574590, &cAudioManager::GetStudentMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x573CD0, &cAudioManager::GetSupermodelFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x573BD0, &cAudioManager::GetSupermodelMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x570F80, &cAudioManager::GetSwatTalkSfx, PATCH_JUMP); -// InjectHook(0x575190, &cAudioManager::GetTaxiDriverTalkSfx, PATCH_JUMP); -// InjectHook(0x571650, &cAudioManager::GetTriadTalkSfx, PATCH_JUMP); -// InjectHook(0x5723A0, &cAudioManager::GetWhiteBusinessFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x572170, &cAudioManager::GetWhiteCasualFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x574290, &cAudioManager::GetWhiteConstructionWorkerTalkSfx, PATCH_JUMP); -// InjectHook(0x571E60, &cAudioManager::GetWhiteCriminalTalkSfx, PATCH_JUMP); -// InjectHook(0x5734F0, &cAudioManager::GetWhiteDockerMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5727B0, &cAudioManager::GetWhiteFatFemaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5725D0, &cAudioManager::GetWhiteFatMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5729D0, &cAudioManager::GetWhiteFemaleProstituteTalkSfx, PATCH_JUMP); -// InjectHook(0x5738D0, &cAudioManager::GetWhiteWorkerMaleTalkSfx, PATCH_JUMP); -// InjectHook(0x5718D0, &cAudioManager::GetYakuzaTalkSfx, PATCH_JUMP); -// InjectHook(0x5719E0, &cAudioManager::GetYardieTalkSfx, PATCH_JUMP); -// InjectHook(0x56CAB0, &cAudioManager::HasAirBrakes, PATCH_JUMP); -// InjectHook(0x57A0E0, &cAudioManager::Initialise, PATCH_JUMP); -// InjectHook(0x57B030, &cAudioManager::InterrogateAudioEntities, PATCH_JUMP); -// InjectHook(0x57AA50, &cAudioManager::IsAudioInitialised, PATCH_JUMP); -// InjectHook(0x579650, &cAudioManager::IsMissionAudioSampleFinished, PATCH_JUMP); -// InjectHook(0x57A9C0, &cAudioManager::IsMP3RadioChannelAvailable, PATCH_JUMP); -// InjectHook(0x579520, &cAudioManager::MissionScriptAudioUsesPoliceChannel, PATCH_JUMP); -// InjectHook(0x56AD10, &cAudioManager::PlayerJustGotInCar, PATCH_JUMP); -// InjectHook(0x56AD20, &cAudioManager::PlayerJustLeftCar, PATCH_JUMP); -// InjectHook(0x579620, &cAudioManager::PlayLoadedMissionAudio, PATCH_JUMP); -// InjectHook(0x57A500, &cAudioManager::PlayOneShot, PATCH_JUMP); -// InjectHook(0x569420, &cAudioManager::PostInitialiseGameSpecificSetup, PATCH_JUMP); -// InjectHook(0x569640, &cAudioManager::PostTerminateGameSpecificShutdown, PATCH_JUMP); -// InjectHook(0x569400, &cAudioManager::PreInitialiseGameSpecificSetup, PATCH_JUMP); -// InjectHook(0x579550, &cAudioManager::PreloadMissionAudio, PATCH_JUMP); -// InjectHook(0x569570, &cAudioManager::PreTerminateGameSpecificShutdown, PATCH_JUMP); -// InjectHook(0x57BA60, &cAudioManager::ProcessActiveQueues, PATCH_JUMP); -// InjectHook(0x56C940, &cAudioManager::ProcessAirBrakes, PATCH_JUMP); -// InjectHook(0x577B30, &cAudioManager::ProcessAirportScriptObject, PATCH_JUMP); -// InjectHook(0x56DE80, &cAudioManager::ProcessBoatEngine, PATCH_JUMP); -// InjectHook(0x56E500, &cAudioManager::ProcessBoatMovingOverWater, PATCH_JUMP); -// InjectHook(0x5790D0, &cAudioManager::ProcessBridge, PATCH_JUMP); -// InjectHook(0x579250, &cAudioManager::ProcessBridgeMotor, PATCH_JUMP); -// InjectHook(0x579310, &cAudioManager::ProcessBridgeOneShots, PATCH_JUMP); -// InjectHook(0x579170, &cAudioManager::ProcessBridgeWarning, PATCH_JUMP); -// InjectHook(0x56CC20, &cAudioManager::ProcessCarBombTick, PATCH_JUMP); -// InjectHook(0x577CA0, &cAudioManager::ProcessCinemaScriptObject, PATCH_JUMP); -// InjectHook(0x577E50, &cAudioManager::ProcessDocksScriptObject, PATCH_JUMP); -// InjectHook(0x56CAF0, &cAudioManager::ProcessEngineDamage, PATCH_JUMP); -// InjectHook(0x569870, &cAudioManager::ProcessEntity, PATCH_JUMP); -// InjectHook(0x575AC0, &cAudioManager::ProcessExplosions, PATCH_JUMP); -// InjectHook(0x578FD0, &cAudioManager::ProcessFireHydrant, PATCH_JUMP); -// InjectHook(0x5785E0, &cAudioManager::ProcessFrontEnd, PATCH_JUMP); -// InjectHook(0x56E6A0, &cAudioManager::ProcessHelicopter, PATCH_JUMP); -// InjectHook(0x577FE0, &cAudioManager::ProcessHomeScriptObject, PATCH_JUMP); -// InjectHook(0x56E8F0, &cAudioManager::ProcessJumbo, PATCH_JUMP); -// InjectHook(0x56EA40, &cAudioManager::ProcessJumboAccel, PATCH_JUMP); -// InjectHook(0x56EE40, &cAudioManager::ProcessJumboDecel, PATCH_JUMP); -// InjectHook(0x56ECF0, &cAudioManager::ProcessJumboFlying, PATCH_JUMP); -// InjectHook(0x56ED10, &cAudioManager::ProcessJumboLanding, PATCH_JUMP); -// InjectHook(0x56EC00, &cAudioManager::ProcessJumboTakeOff, PATCH_JUMP); -// InjectHook(0x56EA10, &cAudioManager::ProcessJumboTaxi, PATCH_JUMP); -// InjectHook(0x5777E0, &cAudioManager::ProcessLaunderetteScriptObject, PATCH_JUMP); -// InjectHook(0x576770, &cAudioManager::ProcessLoopingScriptObject, PATCH_JUMP); -// InjectHook(0x5796E0, &cAudioManager::ProcessMissionAudio, PATCH_JUMP); -// InjectHook(0x56A050, &cAudioManager::ProcessModelCarEngine, PATCH_JUMP); -// InjectHook(0x5760C0, &cAudioManager::ProcessOneShotScriptObject, PATCH_JUMP); -// InjectHook(0x56F450, &cAudioManager::ProcessPed, PATCH_JUMP); -// InjectHook(0x56F4D0, &cAudioManager::ProcessPedHeadphones, PATCH_JUMP); -// InjectHook(0x56F650, &cAudioManager::ProcessPedOneShots, PATCH_JUMP); -// InjectHook(0x5699C0, &cAudioManager::ProcessPhysical, PATCH_JUMP); -// InjectHook(0x56E860, &cAudioManager::ProcessPlane, PATCH_JUMP); -// InjectHook(0x56B0D0, &cAudioManager::ProcessPlayersVehicleEngine, PATCH_JUMP); -// InjectHook(0x578190, &cAudioManager::ProcessPoliceCellBeatingScriptObject, PATCH_JUMP); -// InjectHook(0x577280, &cAudioManager::ProcessPornCinema, PATCH_JUMP); -// InjectHook(0x578A80, &cAudioManager::ProcessProjectiles, PATCH_JUMP); -// InjectHook(0x569CC0, &cAudioManager::ProcessRainOnVehicle, PATCH_JUMP); -// InjectHook(0x569700, &cAudioManager::ProcessReverb, PATCH_JUMP); -// InjectHook(0x569E50, &cAudioManager::ProcessReverseGear, PATCH_JUMP); -// InjectHook(0x577630, &cAudioManager::ProcessSawMillScriptObject, PATCH_JUMP); -// InjectHook(0x576070, &cAudioManager::ProcessScriptObject, PATCH_JUMP); -// InjectHook(0x577970, &cAudioManager::ProcessShopScriptObject, PATCH_JUMP); -// InjectHook(0x5697D0, &cAudioManager::ProcessSpecial, PATCH_JUMP); -// InjectHook(0x56DBF0, &cAudioManager::ProcessTrainNoise, PATCH_JUMP); -// InjectHook(0x569A00, &cAudioManager::ProcessVehicle, PATCH_JUMP); -// InjectHook(0x56C770, &cAudioManager::ProcessVehicleDoors, PATCH_JUMP); -// InjectHook(0x56C200, &cAudioManager::ProcessVehicleHorn, PATCH_JUMP); -// InjectHook(0x56C640, &cAudioManager::ProcessVehicleReverseWarning, PATCH_JUMP); -// InjectHook(0x56A230, &cAudioManager::ProcessVehicleRoadNoise, PATCH_JUMP); -// InjectHook(0x56C420, &cAudioManager::ProcessVehicleSirenOrAlarm, PATCH_JUMP); -// InjectHook(0x56BCB0, &cAudioManager::ProcessVehicleSkidding, PATCH_JUMP); -// InjectHook(0x575F30, &cAudioManager::ProcessWaterCannon, PATCH_JUMP); -// InjectHook(0x578370, &cAudioManager::ProcessWeather, PATCH_JUMP); -// InjectHook(0x56A440, &cAudioManager::ProcessWetRoadNoise, PATCH_JUMP); -// InjectHook(0x577530, &cAudioManager::ProcessWorkShopScriptObject, PATCH_JUMP); -// InjectHook(0x57AF90, &cAudioManager::RandomDisplacement, PATCH_JUMP); -// InjectHook(0x57A9F0, &cAudioManager::ReacquireDigitalHandle, PATCH_JUMP); -// InjectHook(0x57A9E0, &cAudioManager::ReleaseDigitalHandle, PATCH_JUMP); -// InjectHook(0x569650, &cAudioManager::ResetAudioLogicTimers, PATCH_JUMP); -// InjectHook(0x57A7B0, &cAudioManager::ResetTimers, PATCH_JUMP); -// InjectHook(0x57A2A0, &cAudioManager::Service, PATCH_JUMP); -// InjectHook(0x57AA60, &cAudioManager::ServiceSoundEffects, PATCH_JUMP); -// InjectHook(0x57A910, &cAudioManager::SetCurrent3DProvider, PATCH_JUMP); -// InjectHook(0x57AA00, &cAudioManager::SetDynamicAcousticModelingStatus, PATCH_JUMP); -// InjectHook(0x57A770, &cAudioManager::SetEffectsFadeVolume, PATCH_JUMP); -// InjectHook(0x57A730, &cAudioManager::SetEffectsMasterVolume, PATCH_JUMP); -// InjectHook(0x57A4C0, &cAudioManager::SetEntityStatus, PATCH_JUMP); -// InjectHook(0x5795F0, &cAudioManager::SetMissionAudioLocation, PATCH_JUMP); -// InjectHook(0x57A790, &cAudioManager::SetMusicFadeVolume, PATCH_JUMP); -// InjectHook(0x57A750, &cAudioManager::SetMusicMasterVolume, PATCH_JUMP); -// InjectHook(0x57A9A0, &cAudioManager::SetSpeakerConfig, PATCH_JUMP); -// InjectHook(0x56F230, &cAudioManager::SetupJumboFlySound, PATCH_JUMP); -// InjectHook(0x56F310, &cAudioManager::SetupJumboRumbleSound, PATCH_JUMP); -// InjectHook(0x56EF20, &cAudioManager::SetupJumboTaxiSound, PATCH_JUMP); -// InjectHook(0x56F070, &cAudioManager::SetupJumboWhineSound, PATCH_JUMP); -// InjectHook(0x570690, &cAudioManager::SetupPedComments, PATCH_JUMP); -// InjectHook(0x57A150, &cAudioManager::Terminate, PATCH_JUMP); -// InjectHook(0x57AC60, &cAudioManager::TranslateEntity, PATCH_JUMP); -// InjectHook(0x56AC80, &cAudioManager::UpdateGasPedalAudio, PATCH_JUMP); -// InjectHook(0x57B470, &cAudioManager::UpdateReflections, PATCH_JUMP); -// InjectHook(0x56C600, &cAudioManager::UsesReverseWarning, PATCH_JUMP); -// InjectHook(0x56C3C0, &cAudioManager::UsesSiren, PATCH_JUMP); -// InjectHook(0x56C3F0, &cAudioManager::UsesSirenSwitching, PATCH_JUMP); - -// InjectHook(0x57C2B0, &cAudioManager::AdjustSamplesVolume, PATCH_JUMP); -// InjectHook(0x57C320, &cAudioManager::ComputeEmittingVolume, PATCH_JUMP); - -// InjectHook(0x5755C0, &cPedComments::Add, PATCH_JUMP); -// InjectHook(0x575730, &cPedComments::Process, PATCH_JUMP); -// ENDPATCHES diff --git a/src/audio/AudioScriptObject.cpp b/src/audio/AudioScriptObject.cpp index da9e1d2e..3d84006d 100644 --- a/src/audio/AudioScriptObject.cpp +++ b/src/audio/AudioScriptObject.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "AudioScriptObject.h" #include "Pools.h" #include "DMAudio.h" @@ -86,10 +86,3 @@ PlayOneShotScriptObject(uint8 id, CVector const &pos) audioScriptObject->AudioEntity = AEHANDLE_NONE; DMAudio.CreateOneShotScriptObject(audioScriptObject); } - -STARTPATCHES -InjectHook(0x57C430, &cAudioScriptObject::Reset, PATCH_JUMP); -InjectHook(0x57C5F0, &PlayOneShotScriptObject, PATCH_JUMP); -InjectHook(0x57C560, &cAudioScriptObject::LoadAllAudioScriptObjects, PATCH_JUMP); -InjectHook(0x57c460, &cAudioScriptObject::SaveAllAudioScriptObjects, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index e55790ea..11c85dbd 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "DMAudio.h" #include "MusicManager.h" #include "AudioManager.h" @@ -318,57 +318,3 @@ cDMAudio::SetRadioChannel(int8 radio, int32 pos) { MusicManager.SetRadioChannelByScript(radio, pos); } - -STARTPATCHES - InjectHook(0x57C760, &cDMAudio::Initialise, PATCH_JUMP); - InjectHook(0x57C780, &cDMAudio::Terminate, PATCH_JUMP); - InjectHook(0x57C7A0, &cDMAudio::Service, PATCH_JUMP); - InjectHook(0x57C7C0, &cDMAudio::CreateEntity, PATCH_JUMP); - InjectHook(0x57C7F0, &cDMAudio::DestroyEntity, PATCH_JUMP); - InjectHook(0x57C810, &cDMAudio::SetEntityStatus, PATCH_JUMP); - InjectHook(0x57C840, &cDMAudio::PlayOneShot, PATCH_JUMP); - InjectHook(0x57C870, &cDMAudio::DestroyAllGameCreatedEntities, PATCH_JUMP); - InjectHook(0x57C890, &cDMAudio::SetEffectsMasterVolume, PATCH_JUMP); - InjectHook(0x57C8C0, &cDMAudio::SetMusicMasterVolume, PATCH_JUMP); - InjectHook(0x57C8F0, &cDMAudio::SetEffectsFadeVol, PATCH_JUMP); - InjectHook(0x57C920, &cDMAudio::SetMusicFadeVol, PATCH_JUMP); - InjectHook(0x57C950, &cDMAudio::GetNum3DProvidersAvailable, PATCH_JUMP); - InjectHook(0x57C970, &cDMAudio::Get3DProviderName, PATCH_JUMP); - InjectHook(0x57C990, &cDMAudio::GetCurrent3DProviderIndex, PATCH_JUMP); - InjectHook(0x57C9B0, &cDMAudio::SetCurrent3DProvider, PATCH_JUMP); - InjectHook(0x57C9D0, &cDMAudio::SetSpeakerConfig, PATCH_JUMP); - InjectHook(0x57C9F0, &cDMAudio::IsMP3RadioChannelAvailable, PATCH_JUMP); - InjectHook(0x57CA10, &cDMAudio::ReleaseDigitalHandle, PATCH_JUMP); - InjectHook(0x57CA30, &cDMAudio::ReacquireDigitalHandle, PATCH_JUMP); - InjectHook(0x57CA50, &cDMAudio::SetDynamicAcousticModelingStatus, PATCH_JUMP); - InjectHook(0x57CA70, &cDMAudio::CheckForAnAudioFileOnCD, PATCH_JUMP); - InjectHook(0x57CA90, &cDMAudio::GetCDAudioDriveLetter, PATCH_JUMP); - InjectHook(0x57CAB0, &cDMAudio::IsAudioInitialised, PATCH_JUMP); - InjectHook(0x57CAD0, &cDMAudio::ReportCrime, PATCH_JUMP); - InjectHook(0x57CB00, &cDMAudio::CreateLoopingScriptObject, PATCH_JUMP); - InjectHook(0x57CB40, &cDMAudio::DestroyLoopingScriptObject, PATCH_JUMP); - InjectHook(0x57CB60, &cDMAudio::CreateOneShotScriptObject, PATCH_JUMP); - InjectHook(0x57CBB0, &cDMAudio::PlaySuspectLastSeen, PATCH_JUMP); - InjectHook(0x57CBE0, &cDMAudio::ReportCollision, PATCH_JUMP); - InjectHook(0x57CC20, &cDMAudio::PlayFrontEndSound, PATCH_JUMP); - InjectHook(0x57CC60, &cDMAudio::PlayRadioAnnouncement, PATCH_JUMP); - InjectHook(0x57CC80, &cDMAudio::PlayFrontEndTrack, PATCH_JUMP); - InjectHook(0x57CCB0, &cDMAudio::StopFrontEndTrack, PATCH_JUMP); - InjectHook(0x57CCD0, &cDMAudio::ResetTimers, PATCH_JUMP); - InjectHook(0x57CCF0, &cDMAudio::ChangeMusicMode, PATCH_JUMP); - InjectHook(0x57CD10, &cDMAudio::PreloadCutSceneMusic, PATCH_JUMP); - InjectHook(0x57CD30, &cDMAudio::PlayPreloadedCutSceneMusic, PATCH_JUMP); - InjectHook(0x57CD50, &cDMAudio::StopCutSceneMusic, PATCH_JUMP); - InjectHook(0x57CD70, &cDMAudio::PreloadMissionAudio, PATCH_JUMP); - InjectHook(0x57CD90, &cDMAudio::GetMissionAudioLoadingStatus, PATCH_JUMP); - InjectHook(0x57CDB0, &cDMAudio::SetMissionAudioLocation, PATCH_JUMP); - InjectHook(0x57CDE0, &cDMAudio::PlayLoadedMissionAudio, PATCH_JUMP); - InjectHook(0x57CE00, &cDMAudio::IsMissionAudioSampleFinished, PATCH_JUMP); - InjectHook(0x57CE20, &cDMAudio::ClearMissionAudio, PATCH_JUMP); - InjectHook(0x57CE40, &cDMAudio::GetRadioInCar, PATCH_JUMP); - InjectHook(0x57CE60, &cDMAudio::SetRadioInCar, PATCH_JUMP); - InjectHook(0x57CE80, &cDMAudio::SetRadioChannel, PATCH_JUMP); - - //InjectHook(0x57CEB0, `global constructor keyed to'dmaudio.cpp, PATCH_JUMP); - //InjectHook(0x57CED0, cDMAudio::~cDMAudio, PATCH_JUMP); -ENDPATCHES diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index d4b60d9b..2cc1d929 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -13,7 +13,7 @@ #include "Timer.h" #include "World.h" #include "sampman.h" -#include "patcher.h" + cMusicManager MusicManager; int32 gNumRetunePresses; @@ -904,34 +904,3 @@ cMusicManager::ChangeRadioChannel() } return true; } - -STARTPATCHES -InjectHook(0x57E4B0, &cMusicManager::PlayerInCar, PATCH_JUMP); -InjectHook(0x57E6D0, &cMusicManager::DisplayRadioStationName, PATCH_JUMP); -InjectHook(0x57CF70, &cMusicManager::Initialise, PATCH_JUMP); -InjectHook(0x57D140, &cMusicManager::Terminate, PATCH_JUMP); -InjectHook(0x57D1D0, &cMusicManager::GetRadioInCar, PATCH_JUMP); -InjectHook(0x57D2C0, &cMusicManager::SetRadioInCar, PATCH_JUMP); -InjectHook(0x57D180, &cMusicManager::SetRadioChannelByScript, PATCH_JUMP); -InjectHook(0x57CF30, &cMusicManager::ResetMusicAfterReload, PATCH_JUMP); -InjectHook(0x57E6A0, &cMusicManager::UsesPoliceRadio, PATCH_JUMP); -InjectHook(0x57D310, &cMusicManager::ChangeMusicMode, PATCH_JUMP); -InjectHook(0x57D420, &cMusicManager::ResetTimers, PATCH_JUMP); -InjectHook(0x57D440, &cMusicManager::Service, PATCH_JUMP); -InjectHook(0x57D530, &cMusicManager::ServiceFrontEndMode, PATCH_JUMP); -InjectHook(0x57E3D0, &cMusicManager::StopFrontEndTrack, PATCH_JUMP); -InjectHook(0x57E430, &cMusicManager::PlayAnnouncement, PATCH_JUMP); -InjectHook(0x57E2E0, &cMusicManager::PlayFrontEndTrack, PATCH_JUMP); -InjectHook(0x57E210, &cMusicManager::PreloadCutSceneMusic, PATCH_JUMP); -InjectHook(0x57E290, &cMusicManager::PlayPreloadedCutSceneMusic, PATCH_JUMP); -InjectHook(0x57E2B0, &cMusicManager::StopCutSceneMusic, PATCH_JUMP); -InjectHook(0x57E450, &cMusicManager::GetTrackStartPos, PATCH_JUMP); -InjectHook(0x57D690, &cMusicManager::ServiceGameMode, PATCH_JUMP); -InjectHook(0x57DCB0, &cMusicManager::ServiceAmbience, PATCH_JUMP); -InjectHook(0x57DEA0, &cMusicManager::ComputeAmbienceVol, PATCH_JUMP); -InjectHook(0x57E100, &cMusicManager::ServiceTrack, PATCH_JUMP); -InjectHook(0x57DFC0, &cMusicManager::ServiceAnnouncement, PATCH_JUMP); -InjectHook(0x57E530, &cMusicManager::GetCarTuning, PATCH_JUMP); -InjectHook(0x57E5A0, &cMusicManager::GetNextCarTuning, PATCH_JUMP); -InjectHook(0x57E130, &cMusicManager::ChangeRadioChannel, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/audio/PoliceRadio.cpp b/src/audio/PoliceRadio.cpp index a81fcbe9..d9c6bfd7 100644 --- a/src/audio/PoliceRadio.cpp +++ b/src/audio/PoliceRadio.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "DMAudio.h" #include "AudioManager.h" #include "AudioSamples.h" @@ -774,19 +774,3 @@ cAudioManager::AgeCrimes() } } } - -STARTPATCHES -InjectHook(0x580AF0, &cAudioManager::AgeCrimes, PATCH_JUMP); -InjectHook(0x57F060, &cAudioManager::DoPoliceRadioCrackle, PATCH_JUMP); -InjectHook(0x57F050, &cAudioManager::GetMissionScriptPoliceAudioPlayingStatus, PATCH_JUMP); -InjectHook(0x57EEC0, &cAudioManager::InitialisePoliceRadio, PATCH_JUMP); -InjectHook(0x57EAC0, &cAudioManager::InitialisePoliceRadioZones, PATCH_JUMP); -InjectHook(0x580500, &cAudioManager::PlaySuspectLastSeen, PATCH_JUMP); -InjectHook(0x5803D0, &cAudioManager::ReportCrime, PATCH_JUMP); -InjectHook(0x57EFF0, &cAudioManager::ResetPoliceRadio, PATCH_JUMP); -InjectHook(0x57F110, &cAudioManager::ServicePoliceRadio, PATCH_JUMP); -InjectHook(0x57F1B0, &cAudioManager::ServicePoliceRadioChannel, PATCH_JUMP); -InjectHook(0x57F020, &cAudioManager::SetMissionScriptPoliceAudio, PATCH_JUMP); -InjectHook(0x57F5B0, &cAudioManager::SetupCrimeReport, PATCH_JUMP); -InjectHook(0x57FCC0, &cAudioManager::SetupSuspectLastSeenReport, PATCH_JUMP); -ENDPATCHES diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index 7887c363..d24de27f 100644 --- a/src/audio/sampman.cpp +++ b/src/audio/sampman.cpp @@ -13,7 +13,7 @@ #include "MusicManager.h" #include "Frontend.h" #include "Timer.h" -#include "patcher.h" + #pragma comment( lib, "mss32.lib" ) @@ -2236,66 +2236,3 @@ cSampleManager::InitialiseSampleBanks(void) return true; } - -STARTPATCHES - //InjectHook(0x565500, cSampleManager::cSampleManager, PATCH_JUMP); - //InjectHook(0x565510, cSampleManager::~cSampleManager, PATCH_JUMP); - InjectHook(0x565520, comp, PATCH_JUMP); - InjectHook(0x565540, add_providers, PATCH_JUMP); - InjectHook(0x565680, release_existing, PATCH_JUMP); - InjectHook(0x5656F0, set_new_provider, PATCH_JUMP); - InjectHook(0x565900, &cSampleManager::SetSpeakerConfig, PATCH_JUMP); - InjectHook(0x565970, &cSampleManager::GetMaximumSupportedChannels, PATCH_JUMP); - InjectHook(0x565990, &cSampleManager::GetCurrent3DProviderIndex, PATCH_JUMP); - InjectHook(0x5659A0, &cSampleManager::SetCurrent3DProvider, PATCH_JUMP); - InjectHook(0x565A10, _ResolveLink, PATCH_JUMP); - InjectHook(0x565B40, _FindMP3s, PATCH_JUMP); - InjectHook(0x566380, _DeleteMP3Entries, PATCH_JUMP); - InjectHook(0x566400, _GetMP3EntryByIndex, PATCH_JUMP); - InjectHook(0x566490, &cSampleManager::IsMP3RadioChannelAvailable, PATCH_JUMP); - InjectHook(0x5664B0, &cSampleManager::ReleaseDigitalHandle, PATCH_JUMP); - InjectHook(0x5664F0, &cSampleManager::ReacquireDigitalHandle, PATCH_JUMP); - InjectHook(0x566530, &cSampleManager::Initialise, PATCH_JUMP); - InjectHook(0x566DC0, &cSampleManager::Terminate, PATCH_JUMP); - InjectHook(0x566EA0, &cSampleManager::CheckForAnAudioFileOnCD, PATCH_JUMP); - InjectHook(0x566F20, &cSampleManager::GetCDAudioDriveLetter, PATCH_JUMP); - InjectHook(0x566F50, &cSampleManager::UpdateEffectsVolume, PATCH_JUMP); - InjectHook(0x567010, &cSampleManager::SetEffectsMasterVolume, PATCH_JUMP); - InjectHook(0x567020, &cSampleManager::SetMusicMasterVolume, PATCH_JUMP); - InjectHook(0x567030, &cSampleManager::SetEffectsFadeVolume, PATCH_JUMP); - InjectHook(0x567040, &cSampleManager::SetMusicFadeVolume, PATCH_JUMP); - InjectHook(0x567050, &cSampleManager::LoadSampleBank, PATCH_JUMP); - InjectHook(0x567110, &cSampleManager::UnloadSampleBank, PATCH_JUMP); - InjectHook(0x567130, &cSampleManager::IsSampleBankLoaded, PATCH_JUMP); - InjectHook(0x567150, &cSampleManager::IsPedCommentLoaded, PATCH_JUMP); - InjectHook(0x5671A0, &cSampleManager::LoadPedComment, PATCH_JUMP); - InjectHook(0x5672A0, &cSampleManager::GetSampleBaseFrequency, PATCH_JUMP); - InjectHook(0x5672C0, &cSampleManager::GetSampleLoopStartOffset, PATCH_JUMP); - InjectHook(0x5672E0, &cSampleManager::GetSampleLoopEndOffset, PATCH_JUMP); - InjectHook(0x567300, &cSampleManager::GetSampleLength, PATCH_JUMP); - InjectHook(0x567320, &cSampleManager::UpdateReverb, PATCH_JUMP); - InjectHook(0x567630, &cSampleManager::SetChannelReverbFlag, PATCH_JUMP); - InjectHook(0x5676A0, &cSampleManager::InitialiseChannel, PATCH_JUMP); - InjectHook(0x567820, &cSampleManager::SetChannelEmittingVolume, PATCH_JUMP); - InjectHook(0x567890, &cSampleManager::SetChannel3DPosition, PATCH_JUMP); - InjectHook(0x5678D0, &cSampleManager::SetChannel3DDistances, PATCH_JUMP); - InjectHook(0x567900, &cSampleManager::SetChannelVolume, PATCH_JUMP); - InjectHook(0x567980, &cSampleManager::SetChannelPan, PATCH_JUMP); - InjectHook(0x5679D0, &cSampleManager::SetChannelFrequency, PATCH_JUMP); - InjectHook(0x567A30, &cSampleManager::SetChannelLoopPoints, PATCH_JUMP); - InjectHook(0x567AA0, &cSampleManager::SetChannelLoopCount, PATCH_JUMP); - InjectHook(0x567B00, &cSampleManager::GetChannelUsedFlag, PATCH_JUMP); - InjectHook(0x567B80, &cSampleManager::StartChannel, PATCH_JUMP); - InjectHook(0x567BE0, &cSampleManager::StopChannel, PATCH_JUMP); - InjectHook(0x567C50, &cSampleManager::PreloadStreamedFile, PATCH_JUMP); - InjectHook(0x567D30, &cSampleManager::PauseStream, PATCH_JUMP); - InjectHook(0x567D60, &cSampleManager::StartPreloadedStreamedFile, PATCH_JUMP); - InjectHook(0x567D80, &cSampleManager::StartStreamedFile, PATCH_JUMP); - InjectHook(0x5680E0, &cSampleManager::StopStreamedFile, PATCH_JUMP); - InjectHook(0x568130, &cSampleManager::GetStreamedFilePosition, PATCH_JUMP); - InjectHook(0x5681D0, &cSampleManager::SetStreamedVolumeAndPan, PATCH_JUMP); - InjectHook(0x568270, &cSampleManager::GetStreamedFileLength, PATCH_JUMP); - InjectHook(0x568290, &cSampleManager::IsStreamPlaying, PATCH_JUMP); - InjectHook(0x5682D0, &cSampleManager::InitialiseSampleBanks, PATCH_JUMP); - //InjectHook(0x5683F0, `global constructor keyed to'sampman.cpp, PATCH_JUMP); -ENDPATCHES diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index 65e73e5d..3fc9b154 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "AutoPilot.h" #include "CarCtrl.h" diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp index 53cf6af2..8514ef9e 100644 --- a/src/control/Bridge.cpp +++ b/src/control/Bridge.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Bridge.h" #include "Pools.h" #include "ModelIndices.h" @@ -144,11 +144,3 @@ bool CBridge::ThisIsABridgeObjectMovingUp(int index) return State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP || State == STATE_LIFT_PART_MOVING_UP; } - -STARTPATCHES - InjectHook(0x413A30, &CBridge::Init, PATCH_JUMP); - InjectHook(0x413AC0, &CBridge::Update, PATCH_JUMP); - InjectHook(0x413D10, &CBridge::ShouldLightsBeFlashing, PATCH_JUMP); - InjectHook(0x413D20, &CBridge::FindBridgeEntities, PATCH_JUMP); - InjectHook(0x413DE0, &CBridge::ThisIsABridgeObjectMovingUp, PATCH_JUMP); -ENDPATCHES diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index f48e4c78..7c9a1ad4 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "CarAI.h" #include "Accident.h" @@ -636,6 +636,3 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle) } } } - -STARTPATCHES -ENDPATCHES diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 6e47670d..827c97e7 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "CarCtrl.h" #include "Accident.h" @@ -2736,20 +2736,3 @@ bool CCarCtrl::MapCouldMoveInThisArea(float x, float y) return x > -342.0f && x < -219.0f && y > -677.0f && y < -580.0f; } - -STARTPATCHES -InjectHook(0x416580, &CCarCtrl::GenerateRandomCars, PATCH_JUMP); -InjectHook(0x417EC0, &CCarCtrl::ChooseModel, PATCH_JUMP); -InjectHook(0x418320, &CCarCtrl::RemoveDistantCars, PATCH_JUMP); -InjectHook(0x418430, &CCarCtrl::PossiblyRemoveVehicle, PATCH_JUMP); -InjectHook(0x41D280, &CCarCtrl::Init, PATCH_JUMP); -InjectHook(0x41D3B0, &CCarCtrl::ReInit, PATCH_JUMP); -InjectHook(0x41E250, &CCarCtrl::SteerAIBoatWithPhysics, PATCH_JUMP); -InjectHook(0x41F6E0, &CCarCtrl::RegisterVehicleOfInterest, PATCH_JUMP); -InjectHook(0x41F780, &CCarCtrl::IsThisVehicleInteresting, PATCH_JUMP); -InjectHook(0x41F7A0, &CCarCtrl::RemoveFromInterestingVehicleList, PATCH_JUMP); -InjectHook(0x41F7D0, &CCarCtrl::ClearInterestingVehicleList, PATCH_JUMP); -InjectHook(0x41F7F0, &CCarCtrl::SwitchVehicleToRealPhysics, PATCH_JUMP); -InjectHook(0x41F820, &CCarCtrl::JoinCarWithRoadSystem, PATCH_JUMP); -InjectHook(0x41FA00, &CCarCtrl::JoinCarWithRoadSystemGotoCoors, PATCH_JUMP); -ENDPATCHES diff --git a/src/control/Curves.cpp b/src/control/Curves.cpp index 5c6ef06d..623ab040 100644 --- a/src/control/Curves.cpp +++ b/src/control/Curves.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Curves.h" float CCurves::CalcSpeedScaleFactor(CVector* pPoint1, CVector* pPoint2, float dir1X, float dir1Y, float dir2X, float dir2Y) diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index 3265d1c2..e81d4112 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Darkel.h" #include "PlayerPed.h" @@ -371,19 +371,3 @@ CDarkel::Update() DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_PASSED, 0); } } - -STARTPATCHES - InjectHook(0x421380, CDarkel::CalcFade, PATCH_JUMP); - InjectHook(0x420650, CDarkel::Init, PATCH_JUMP); - InjectHook(0x420660, CDarkel::Update, PATCH_JUMP); - InjectHook(0x420E60, CDarkel::FrenzyOnGoing, PATCH_JUMP); - InjectHook(0x420E50, CDarkel::ReadStatus, PATCH_JUMP); - InjectHook(0x420E70, CDarkel::ResetOnPlayerDeath, PATCH_JUMP); - InjectHook(0x4210E0, CDarkel::StartFrenzy, PATCH_JUMP); - InjectHook(0x421370, CDarkel::QueryModelsKilledByPlayer, PATCH_JUMP); - InjectHook(0x421060, CDarkel::RegisterKillNotByPlayer, PATCH_JUMP); - InjectHook(0x421310, CDarkel::ResetModelsKilledByPlayer, PATCH_JUMP); - InjectHook(0x420920, CDarkel::DrawMessages, PATCH_JUMP); - InjectHook(0x421070, CDarkel::RegisterCarBlownUpByPlayer, PATCH_JUMP); - InjectHook(0x420F60, CDarkel::RegisterKillByPlayer, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp index 0cfaac17..e7f642fe 100644 --- a/src/control/GameLogic.cpp +++ b/src/control/GameLogic.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "GameLogic.h" #include "Clock.h" #include "Stats.h" @@ -284,11 +284,3 @@ CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector CWorld::Remove(pPlayerPed); CWorld::Add(pPlayerPed); } - -STARTPATCHES - InjectHook(0x4213F0, &CGameLogic::InitAtStartOfGame, PATCH_JUMP); - InjectHook(0x421C00, &CGameLogic::PassTime, PATCH_JUMP); - InjectHook(0x421A20, &CGameLogic::SortOutStreamingAndMemory, PATCH_JUMP); - InjectHook(0x421400, &CGameLogic::Update, PATCH_JUMP); - InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index cca8c3b8..1ee8f99c 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Garages.h" #include "main.h" @@ -2357,10 +2357,3 @@ CGarages::IsModelIndexADoor(uint32 id) id == MI_CRUSHERBODY || id == MI_CRUSHERLID; } - - -STARTPATCHES - InjectHook(0x427AB0, CGarages::IsPointInAGarageCameraZone, PATCH_JUMP); // CCamera::CamControl - InjectHook(0x427BC0, CGarages::CameraShouldBeOutside, PATCH_JUMP); // CCamera::CamControl - InjectHook(0x428940, CGarages::Load, PATCH_JUMP); // GenericLoad -ENDPATCHES diff --git a/src/control/OnscreenTimer.cpp b/src/control/OnscreenTimer.cpp index 5406522c..d128efeb 100644 --- a/src/control/OnscreenTimer.cpp +++ b/src/control/OnscreenTimer.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "DMAudio.h" #include "Hud.h" @@ -153,18 +153,3 @@ void COnscreenTimerEntry::ProcessForDisplayCounter() { uint32 counter = *CTheScripts::GetPointerToScriptVariable(m_nCounterOffset); sprintf(m_bCounterBuffer, "%d", counter); } - -STARTPATCHES - InjectHook(0x429160, &COnscreenTimerEntry::Process, PATCH_JUMP); - InjectHook(0x429110, &COnscreenTimerEntry::ProcessForDisplay, PATCH_JUMP); - InjectHook(0x429080, &COnscreenTimerEntry::ProcessForDisplayClock, PATCH_JUMP); - InjectHook(0x4290F0, &COnscreenTimerEntry::ProcessForDisplayCounter, PATCH_JUMP); - - InjectHook(0x429220, &COnscreenTimer::Init, PATCH_JUMP); - InjectHook(0x429320, &COnscreenTimer::Process, PATCH_JUMP); - InjectHook(0x4292E0, &COnscreenTimer::ProcessForDisplay, PATCH_JUMP); - InjectHook(0x429450, &COnscreenTimer::ClearCounter, PATCH_JUMP); - InjectHook(0x429410, &COnscreenTimer::ClearClock, PATCH_JUMP); - InjectHook(0x4293B0, &COnscreenTimer::AddCounter, PATCH_JUMP); - InjectHook(0x429350, &COnscreenTimer::AddClock, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index d9594490..9d0959a8 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "FileMgr.h" // only needed for empty function #include "Camera.h" @@ -1766,48 +1766,3 @@ CPathFind::DisplayPathData(void) } } } - -STARTPATCHES - InjectHook(0x42E680, &CPedPath::CalcPedRoute, PATCH_JUMP); - InjectHook(0x42F100, &CPedPath::AddNodeToPathList, PATCH_JUMP); - InjectHook(0x42F140, &CPedPath::RemoveNodeFromList, PATCH_JUMP); - InjectHook(0x42F160, &CPedPath::AddNodeToList, PATCH_JUMP); - InjectHook(0x42F1A0, &CPedPath::AddBlockade, PATCH_JUMP); - InjectHook(0x42F420, &CPedPath::AddBlockadeSectorList, PATCH_JUMP); - - InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP); - InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP); - InjectHook(0x429540, &CPathFind::RegisterMapObject, PATCH_JUMP); - InjectHook(0x42D7E0, &CPathFind::StoreNodeInfoPed, PATCH_JUMP); - InjectHook(0x42D690, &CPathFind::StoreNodeInfoCar, PATCH_JUMP); - InjectHook(0x429610, &CPathFind::PreparePathData, PATCH_JUMP); - InjectHook(0x42B810, &CPathFind::CountFloodFillGroups, PATCH_JUMP); - InjectHook(0x429C20, &CPathFind::PreparePathDataForType, PATCH_JUMP); - - InjectHook(0x42C990, &CPathFind::CalcRoadDensity, PATCH_JUMP); - InjectHook(0x42E1B0, &CPathFind::TestForPedTrafficLight, PATCH_JUMP); - InjectHook(0x42E340, &CPathFind::TestCrossesRoad, PATCH_JUMP); - InjectHook(0x42CBE0, &CPathFind::AddNodeToList, PATCH_JUMP); - InjectHook(0x42CBB0, &CPathFind::RemoveNodeFromList, PATCH_JUMP); - InjectHook(0x42B790, &CPathFind::RemoveBadStartNode, PATCH_JUMP); - InjectHook(0x42E3B0, &CPathFind::SetLinksBridgeLights, PATCH_JUMP); - InjectHook(0x42DED0, &CPathFind::SwitchOffNodeAndNeighbours, PATCH_JUMP); - InjectHook(0x42D960, &CPathFind::SwitchRoadsOffInArea, PATCH_JUMP); - InjectHook(0x42DA50, &CPathFind::SwitchPedRoadsOffInArea, PATCH_JUMP); - InjectHook(0x42DB50, &CPathFind::SwitchRoadsInAngledArea, PATCH_JUMP); - InjectHook(0x42E140, &CPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours, PATCH_JUMP); - InjectHook(0x42DF50, &CPathFind::MarkRoadsBetweenLevelsInArea, PATCH_JUMP); - InjectHook(0x42E040, &CPathFind::PedMarkRoadsBetweenLevelsInArea, PATCH_JUMP); - InjectHook(0x42CC30, &CPathFind::FindNodeClosestToCoors, PATCH_JUMP); - InjectHook(0x42CDC0, &CPathFind::FindNodeClosestToCoorsFavourDirection, PATCH_JUMP); - InjectHook(0x42CFC0, &CPathFind::FindNodeOrientationForCarPlacement, PATCH_JUMP); - InjectHook(0x42D060, &CPathFind::FindNodeOrientationForCarPlacementFacingDestination, PATCH_JUMP); - InjectHook(0x42BF10, &CPathFind::NewGenerateCarCreationCoors, PATCH_JUMP); - InjectHook(0x42C1E0, &CPathFind::GeneratePedCreationCoors, PATCH_JUMP); - InjectHook(0x42D2A0, &CPathFind::FindRoadObjectClosestToCoors, PATCH_JUMP); - InjectHook(0x42B9F0, &CPathFind::FindNextNodeWandering, PATCH_JUMP); - InjectHook(0x42B040, &CPathFind::DoPathSearch, PATCH_JUMP); - InjectHook(0x42C8C0, &CPathFind::TestCoorsCloseness, PATCH_JUMP); - InjectHook(0x42E450, &CPathFind::Save, PATCH_JUMP); - InjectHook(0x42E550, &CPathFind::Load, PATCH_JUMP); -ENDPATCHES diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index 90939f0e..7fdc81c5 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Phones.h" #include "Pools.h" #include "ModelIndices.h" @@ -377,20 +377,3 @@ PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg) CPhoneInfo::pCallBackPed = nil; } - -STARTPATCHES - InjectHook(0x42F720, &CPhoneInfo::FindNearestFreePhone, PATCH_JUMP); - InjectHook(0x42FD50, &CPhoneInfo::PhoneAtThisPosition, PATCH_JUMP); - InjectHook(0x42FFF0, &CPhoneInfo::HasMessageBeenDisplayed, PATCH_JUMP); - InjectHook(0x430030, &CPhoneInfo::IsMessageBeingDisplayed, PATCH_JUMP); - InjectHook(0x430120, &CPhoneInfo::Load, PATCH_JUMP); - InjectHook(0x42FF90, &CPhoneInfo::SetPhoneMessage_JustOnce, PATCH_JUMP); - InjectHook(0x42FF30, &CPhoneInfo::SetPhoneMessage_Repeatedly, PATCH_JUMP); - InjectHook(0x430060, &CPhoneInfo::Save, PATCH_JUMP); - InjectHook(0x42F710, &CPhoneInfo::Shutdown, PATCH_JUMP); - InjectHook(0x42F640, &CPhoneInfo::Initialise, PATCH_JUMP); - InjectHook(0x42FDB0, &CPhoneInfo::GrabPhone, PATCH_JUMP); - InjectHook(0x42F7A0, &CPhoneInfo::Update, PATCH_JUMP); - InjectHook(0x42F570, &PhonePutDownCB, PATCH_JUMP); - InjectHook(0x42F470, &PhonePickUpCB, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index d52c386c..9836c9c2 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Camera.h" @@ -1406,47 +1406,3 @@ CPacManPickups::ResetPowerPillsCarriedByPlayer() FindPlayerVehicle()->m_fForceMultiplier = 1.0f; } } - -STARTPATCHES - InjectHook(0x430220, CPickups::Init, PATCH_JUMP); - InjectHook(0x4303D0, CPickups::Update, PATCH_JUMP); - InjectHook(0x432440, CPickups::RenderPickUpText, PATCH_JUMP); - InjectHook(0x431C30, CPickups::DoCollectableEffects, PATCH_JUMP); - InjectHook(0x431F40, CPickups::DoMoneyEffects, PATCH_JUMP); - InjectHook(0x4321C0, CPickups::DoMineEffects, PATCH_JUMP); - InjectHook(0x431520, CPickups::DoPickUpEffects, PATCH_JUMP); - InjectHook(0x4304B0, CPickups::GenerateNewOne, PATCH_JUMP); - InjectHook(0x430660, CPickups::GenerateNewOne_WeaponType, PATCH_JUMP); - InjectHook(0x4307A0, CPickups::RemovePickUp, PATCH_JUMP); - InjectHook(0x430800, CPickups::RemoveAllFloatingPickups, PATCH_JUMP); - InjectHook(0x433D60, CPickups::AddToCollectedPickupsArray, PATCH_JUMP); - InjectHook(0x430770, CPickups::IsPickUpPickedUp, PATCH_JUMP); - InjectHook(0x430690, CPickups::ModelForWeapon, PATCH_JUMP); - InjectHook(0x4306F0, CPickups::WeaponForModel, PATCH_JUMP); - InjectHook(0x431510, CPickups::FindColourIndexForWeaponMI, PATCH_JUMP);/**/ - InjectHook(0x433DF0, CPickups::GetActualPickupIndex, PATCH_JUMP); - InjectHook(0x433DB0, CPickups::GetNewUniquePickupIndex, PATCH_JUMP); - InjectHook(0x433B60, CPickups::PassTime, PATCH_JUMP); - InjectHook(0x4339F0, CPickups::GivePlayerGoodiesWithPickUpMI, PATCH_JUMP); - InjectHook(0x433F60, CPickups::Load, PATCH_JUMP); - InjectHook(0x433E40, CPickups::Save, PATCH_JUMP); - InjectHook(0x433BA0, &CPickup::GiveUsAPickUpObject, PATCH_JUMP); - InjectHook(0x430860, &CPickup::Update, PATCH_JUMP); - InjectHook(0x4331B0, &CPacManPickup::Update, PATCH_JUMP); - InjectHook(0x432760, CPacManPickups::Init, PATCH_JUMP); - InjectHook(0x432800, CPacManPickups::Update, PATCH_JUMP); - InjectHook(0x432AE0, CPacManPickups::GeneratePMPickUps, PATCH_JUMP); - InjectHook(0x432D50, CPacManPickups::GeneratePMPickUpsForRace, PATCH_JUMP); - InjectHook(0x432F20, CPacManPickups::GenerateOnePMPickUp, PATCH_JUMP); - InjectHook(0x432F60, CPacManPickups::Render, PATCH_JUMP); - InjectHook(0x433150, CPacManPickups::ClearPMPickUps, PATCH_JUMP); - InjectHook(0x433340, CPacManPickups::StartPacManRace, PATCH_JUMP); - InjectHook(0x433360, CPacManPickups::StartPacManRecord, PATCH_JUMP); - InjectHook(0x4333A0, CPacManPickups::QueryPowerPillsEatenInRace, PATCH_JUMP); - InjectHook(0x4333B0, CPacManPickups::ResetPowerPillsEatenInRace, PATCH_JUMP); - InjectHook(0x4333C0, CPacManPickups::CleanUpPacManStuff, PATCH_JUMP); - InjectHook(0x4333D0, CPacManPickups::StartPacManScramble, PATCH_JUMP); - InjectHook(0x4333F0, CPacManPickups::QueryPowerPillsCarriedByPlayer, PATCH_JUMP); - InjectHook(0x433410, CPacManPickups::ResetPowerPillsCarriedByPlayer, PATCH_JUMP); - -ENDPATCHES diff --git a/src/control/Record.cpp b/src/control/Record.cpp index 08e3c5b9..6687cbff 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Record.h" #include "FileMgr.h" diff --git a/src/control/Remote.cpp b/src/control/Remote.cpp index f7d12702..9c749bd9 100644 --- a/src/control/Remote.cpp +++ b/src/control/Remote.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Automobile.h" #include "CarCtrl.h" #include "Camera.h" @@ -49,8 +49,3 @@ CRemote::TakeRemoteControlledCarFromPlayer(void) CWorld::Players[CWorld::PlayerInFocus].m_bInRemoteMode = true; CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->bRemoveFromWorld = true; } - -STARTPATCHES - InjectHook(0x435C30, &CRemote::GivePlayerRemoteControlledCar, PATCH_JUMP); - InjectHook(0x435DA0, &CRemote::TakeRemoteControlledCarFromPlayer, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 0570f9a8..c67e7cbf 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "AnimBlendAssociation.h" #include "Boat.h" #include "SpecialFX.h" @@ -1570,16 +1570,3 @@ void CReplay::Display() if (Mode == MODE_PLAYBACK) CFont::PrintString(SCREEN_SCALE_X(63.5f), SCREEN_SCALE_Y(30.0f), TheText.Get("REPLAY")); } - -STARTPATCHES -InjectHook(0x592FE0, &CReplay::Init, PATCH_JUMP); -InjectHook(0x593150, &CReplay::DisableReplays, PATCH_JUMP); -InjectHook(0x593160, &CReplay::EnableReplays, PATCH_JUMP); -InjectHook(0x593170, &CReplay::Update, PATCH_JUMP); -InjectHook(0x595B20, &CReplay::FinishPlayback, PATCH_JUMP); -InjectHook(0x595BD0, &CReplay::EmptyReplayBuffer, PATCH_JUMP); -InjectHook(0x595EE0, &CReplay::Display, PATCH_JUMP); -InjectHook(0x596030, &CReplay::TriggerPlayback, PATCH_JUMP); -InjectHook(0x597560, &CReplay::StreamAllNecessaryCarsAndPeds, PATCH_JUMP); -InjectHook(0x597680, &CReplay::ShouldStandardCameraBeProcessed, PATCH_JUMP); -ENDPATCHES diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp index 2730f5c0..2a31f8f1 100644 --- a/src/control/Restart.cpp +++ b/src/control/Restart.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Restart.h" #include "Zones.h" #include "PathFind.h" @@ -247,16 +247,3 @@ INITSAVEBUF WriteSaveBuf(buf, OverridePoliceStationLevel); VALIDATESAVEBUF(*size); } - - -STARTPATCHES - InjectHook(0x435E20, &CRestart::Initialise, PATCH_JUMP); - InjectHook(0x436100, &CRestart::AddHospitalRestartPoint, PATCH_JUMP); - InjectHook(0x436150, &CRestart::AddPoliceRestartPoint, PATCH_JUMP); - InjectHook(0x4366C0, &CRestart::OverrideNextRestart, PATCH_JUMP); - InjectHook(0x4366F0, &CRestart::CancelOverrideRestart, PATCH_JUMP); - InjectHook(0x4361A0, &CRestart::FindClosestHospitalRestartPoint, PATCH_JUMP); - InjectHook(0x436450, &CRestart::FindClosestPoliceRestartPoint, PATCH_JUMP); - InjectHook(0x436B20, &CRestart::LoadAllRestartPoints, PATCH_JUMP); - InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index fcfa42e3..7fb0c211 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "RoadBlocks.h" #include "PathFind.h" #include "ModelIndices.h" @@ -195,9 +195,3 @@ CRoadBlocks::GenerateRoadBlocks(void) } } } - -STARTPATCHES - InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP); - InjectHook(0x4376A0, &CRoadBlocks::GenerateRoadBlockCopsForCar, PATCH_JUMP); - InjectHook(0x436FA0, &CRoadBlocks::GenerateRoadBlocks, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index 8d804e4d..571b526a 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "SceneEdit.h" #include "Automobile.h" diff --git a/src/control/Script.cpp b/src/control/Script.cpp index d4ede846..6a8028a2 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1,6 +1,6 @@ #define WITHWINDOWS // for our script loading hack #include "common.h" -#include "patcher.h" + #include "Script.h" #include "ScriptCommands.h" @@ -11626,17 +11626,3 @@ void CTheScripts::ReadMultiScriptFileOffsetsFromScript() MultiScriptArray[i] = Read4BytesFromScript(&ip); } } - -STARTPATCHES -InjectHook(0x438790, &CTheScripts::Init, PATCH_JUMP); -InjectHook(0x439040, &CTheScripts::Process, PATCH_JUMP); -InjectHook(0x439400, &CTheScripts::StartTestScript, PATCH_JUMP); -InjectHook(0x439410, &CTheScripts::IsPlayerOnAMission, PATCH_JUMP); -InjectHook(0x44FD10, &CTheScripts::UndoBuildingSwaps, PATCH_JUMP); -InjectHook(0x44FD60, &CTheScripts::UndoEntityInvisibilitySettings, PATCH_JUMP); -InjectHook(0x4534E0, &CTheScripts::ScriptDebugLine3D, PATCH_JUMP); -InjectHook(0x453550, &CTheScripts::RenderTheScriptDebugLines, PATCH_JUMP); -InjectHook(0x4535E0, &CTheScripts::SaveAllScripts, PATCH_JUMP); -InjectHook(0x453B30, &CTheScripts::LoadAllScripts, PATCH_JUMP); -InjectHook(0x454060, &CTheScripts::ClearSpaceForMissionEntity, PATCH_JUMP); -ENDPATCHES diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index ab9cd92d..096bb484 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "Camera.h" #include "World.h" @@ -327,9 +327,3 @@ CTrafficLights::LightForCars2(void) else return CAR_LIGHTS_RED; } - -STARTPATCHES - InjectHook(0x455760, &CTrafficLights::LightForCars1, PATCH_JUMP); - InjectHook(0x455790, &CTrafficLights::LightForCars2, PATCH_JUMP); - InjectHook(0x4557D0, &CTrafficLights::LightForPeds, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Accident.cpp b/src/core/Accident.cpp index 3c39b11d..1fd6c123 100644 --- a/src/core/Accident.cpp +++ b/src/core/Accident.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Accident.h" #include "Ped.h" @@ -122,13 +122,3 @@ CAccidentManager::UnattendedAccidents() } return false; } - -STARTPATCHES - InjectHook(0x4565A0, &CAccidentManager::GetNextFreeAccident, PATCH_JUMP); - InjectHook(0x4565D0, &CAccidentManager::ReportAccident, PATCH_JUMP); - InjectHook(0x456710, &CAccidentManager::Update, PATCH_JUMP); - InjectHook(0x456760, &CAccidentManager::FindNearestAccident, PATCH_JUMP); - InjectHook(0x456880, &CAccidentManager::CountActiveAccidents, PATCH_JUMP); - InjectHook(0x4568A0, &CAccidentManager::WorkToDoForMedics, PATCH_JUMP); - InjectHook(0x4568D0, &CAccidentManager::UnattendedAccidents, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp index 1086db20..20e94bf4 100644 --- a/src/core/AnimViewer.cpp +++ b/src/core/AnimViewer.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Font.h" #include "Pad.h" #include "Text.h" diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 4d954ccd..07dc2051 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Draw.h" #include "World.h" @@ -5236,55 +5236,3 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, } } #endif - -STARTPATCHES - InjectHook(0x456F40, WellBufferMe, PATCH_JUMP); - InjectHook(0x458410, &CCam::Init, PATCH_JUMP); - InjectHook(0x4582F0, &CCam::GetVectorsReadyForRW, PATCH_JUMP); - InjectHook(0x457710, &CCam::DoAverageOnVector, PATCH_JUMP); - InjectHook(0x458060, &CCam::GetPedBetaAngleForClearView, PATCH_JUMP); - InjectHook(0x457210, &CCam::Cam_On_A_String_Unobscured, PATCH_JUMP); - InjectHook(0x457A80, &CCam::FixCamWhenObscuredByVehicle, PATCH_JUMP); - InjectHook(0x457B90, &CCam::FixCamIfObscured, PATCH_JUMP); - InjectHook(0x465DA0, &CCam::RotCamIfInFrontCar, PATCH_JUMP); - InjectHook(0x4662D0, &CCam::WorkOutCamHeightWeeCar, PATCH_JUMP); - InjectHook(0x466650, &CCam::WorkOutCamHeight, PATCH_JUMP); - InjectHook(0x458600, &CCam::LookBehind, PATCH_JUMP); - InjectHook(0x458C40, &CCam::LookLeft, PATCH_JUMP); - InjectHook(0x458FB0, &CCam::LookRight, PATCH_JUMP); - InjectHook(0x4574C0, &CCam::ClipIfPedInFrontOfPlayer, PATCH_JUMP); - InjectHook(0x459300, &CCam::KeepTrackOfTheSpeed, PATCH_JUMP); - InjectHook(0x458580, &CCam::IsTargetInWater, PATCH_JUMP); - InjectHook(0x4570C0, &CCam::AvoidWallsTopDownPed, PATCH_JUMP); - InjectHook(0x4595B0, &CCam::PrintMode, PATCH_JUMP); - - InjectHook(0x467400, &CCam::ProcessSpecialHeightRoutines, PATCH_JUMP); - InjectHook(0x4596A0, &CCam::Process, PATCH_JUMP); - InjectHook(0x45E3A0, &CCam::Process_FollowPed, PATCH_JUMP); - InjectHook(0x45FF70, &CCam::Process_FollowPedWithMouse, PATCH_JUMP); - InjectHook(0x45BE60, &CCam::Process_BehindCar, PATCH_JUMP); - InjectHook(0x45C090, &CCam::Process_Cam_On_A_String, PATCH_JUMP); - InjectHook(0x463EB0, &CCam::Process_TopDown, PATCH_JUMP); - InjectHook(0x464390, &CCam::Process_TopDownPed, PATCH_JUMP); - InjectHook(0x461AF0, &CCam::Process_Rocket, PATCH_JUMP); - InjectHook(0x460E00, &CCam::Process_M16_1stPerson, PATCH_JUMP); - InjectHook(0x459FA0, &CCam::Process_1stPerson, PATCH_JUMP); - InjectHook(0x462420, &CCam::Process_Sniper, PATCH_JUMP); - InjectHook(0x463130, &CCam::Process_Syphon, PATCH_JUMP); - InjectHook(0x463A70, &CCam::Process_Syphon_Crim_In_Front, PATCH_JUMP); - InjectHook(0x45B470, &CCam::Process_BehindBoat, PATCH_JUMP); - InjectHook(0x45D2F0, &CCam::Process_Fight_Cam, PATCH_JUMP); - InjectHook(0x45DC20, &CCam::Process_FlyBy, PATCH_JUMP); - InjectHook(0x464D10, &CCam::Process_WheelCam, PATCH_JUMP); - InjectHook(0x45DA20, &CCam::Process_Fixed, PATCH_JUMP); - InjectHook(0x461940, &CCam::Process_Player_Fallen_Water, PATCH_JUMP); - InjectHook(0x45C400, &CCam::Process_Circle, PATCH_JUMP); - InjectHook(0x462FC0, &CCam::Process_SpecialFixedForSyphon, PATCH_JUMP); - InjectHook(0x45CCC0, &CCam::Process_Debug, PATCH_JUMP); - InjectHook(0x4656C0, &CCam::ProcessPedsDeadBaby, PATCH_JUMP); - InjectHook(0x465000, &CCam::ProcessArrestCamOne, PATCH_JUMP); - InjectHook(0x4653C0, &CCam::ProcessArrestCamTwo, PATCH_JUMP); - - InjectHook(0x456CE0, &FindSplinePathPositionFloat, PATCH_JUMP); - InjectHook(0x4569A0, &FindSplinePathPositionVector, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index a1f36d93..f1445d2e 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Draw.h" #include "World.h" @@ -3386,58 +3386,3 @@ CCamPathSplines::CCamPathSplines(void) for(i = 0; i < MAXPATHLENGTH; i++) m_arr_PathData[i] = 0.0f; } - - -STARTPATCHES - InjectHook(0x42C760, (bool (CCamera::*)(const CVector ¢er, float radius, const CMatrix *mat))&CCamera::IsSphereVisible, PATCH_JUMP); - InjectHook(0x46FD00, &CCamera::SetFadeColour, PATCH_JUMP); - - InjectHook(0x46FD40, &CCamera::SetMotionBlur, PATCH_JUMP); - InjectHook(0x46FD80, &CCamera::SetMotionBlurAlpha, PATCH_JUMP); - InjectHook(0x46F940, &CCamera::RenderMotionBlur, PATCH_JUMP); - - InjectHook(0x46FC90, &CCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString, PATCH_JUMP); - - InjectHook(0x46FF00, &CCamera::SetWideScreenOn, PATCH_JUMP); - InjectHook(0x46FF10, &CCamera::SetWideScreenOff, PATCH_JUMP); - - InjectHook(0x46FCC0, &CCamera::SetCamPositionForFixedMode, PATCH_JUMP); - InjectHook(0x46FEC0, &CCamera::SetRwCamera, PATCH_JUMP); - InjectHook(0x46B920, &CCamera::GetCutSceneFinishTime, PATCH_JUMP); - InjectHook(0x46B560, &CCamera::FinishCutscene, PATCH_JUMP); - InjectHook(0x46FF30, &CCamera::SetZoomValueFollowPedScript, PATCH_JUMP); - InjectHook(0x46FF90, &CCamera::SetZoomValueCamStringScript, PATCH_JUMP); - - - InjectHook(0x46F8E0, &CCamera::ProcessWideScreenOn, PATCH_JUMP); - InjectHook(0x46FDE0, &CCamera::SetParametersForScriptInterpolation, PATCH_JUMP); - InjectHook(0x46BA20, &CCamera::GetLookingLRBFirstPerson, PATCH_JUMP); - InjectHook(0x470D80, &CCamera::StartTransitionWhenNotFinishedInter, PATCH_JUMP); - InjectHook(0x46FFF0, &CCamera::StartTransition, PATCH_JUMP); - InjectHook(0x46BEB0, &CCamera::InitialiseCameraForDebugMode, PATCH_JUMP); - InjectHook(0x471500, &CCamera::TakeControl, PATCH_JUMP); - InjectHook(0x4715B0, &CCamera::TakeControlNoEntity, PATCH_JUMP); - InjectHook(0x46B3A0, &CCamera::Fade, PATCH_JUMP); - InjectHook(0x46FE20, &CCamera::SetPercentAlongCutScene, PATCH_JUMP); - InjectHook(0x46B100, &CamShakeNoPos, PATCH_JUMP); - InjectHook(0x46B200, &CCamera::CamShake, PATCH_JUMP); - InjectHook(0x46F520, &CCamera::ProcessObbeCinemaCameraPed, PATCH_JUMP); - InjectHook(0x46F3E0, &CCamera::ProcessObbeCinemaCameraCar, PATCH_JUMP); - InjectHook(0x470DA0, &CCamera::StoreValuesDuringInterPol, PATCH_JUMP); - InjectHook(0x46B430, &CCamera::DrawBordersForWideScreen, PATCH_JUMP); - InjectHook(0x46F990, &CCamera::Restore, PATCH_JUMP); - InjectHook(0x46FAE0, &CCamera::RestoreWithJumpCut, PATCH_JUMP); - InjectHook(0x46F080, &CCamera::ProcessFade, PATCH_JUMP); - InjectHook(0x46EEA0, &CCamera::CalculateDerivedValues, PATCH_JUMP); - InjectHook(0x46F1E0, &CCamera::ProcessMusicFade, PATCH_JUMP); - InjectHook(0x46D1D0, &CCamera::LoadPathSplines, PATCH_JUMP); - InjectHook(0x4712A0, &CCamera::UpdateTargetEntity, PATCH_JUMP); - InjectHook(0x46B580, &CCamera::Find3rdPersonCamTargetVector, PATCH_JUMP); - InjectHook(0x46BAD0, &CCamera::Init, PATCH_JUMP); - InjectHook(0x46C9E0, &CCamera::LoadTrainCamNodes, PATCH_JUMP); - InjectHook(0x46F600, &CCamera::Process_Train_Camera_Control, PATCH_JUMP); - InjectHook(0x470EA0, &CCamera::UpdateSoundDistances, PATCH_JUMP); - InjectHook(0x46BF10, &CCamera::IsItTimeForNewcam, PATCH_JUMP); - InjectHook(0x471650, &CCamera::TryToStartNewCamMode, PATCH_JUMP); -// InjectHook(0x46D3F0, &CCamera::Process, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp index a400c039..1ab1c8b0 100644 --- a/src/core/CdStream.cpp +++ b/src/core/CdStream.cpp @@ -1,6 +1,6 @@ #include #include "common.h" -#include "patcher.h" + #include "CdStream.h" #include "rwcore.h" #include "RwHelper.h" @@ -507,24 +507,3 @@ CdStreamGetNumImages(void) { return gNumImages; } - - -STARTPATCHES - InjectHook(0x405B50, CdStreamInitThread, PATCH_JUMP); - InjectHook(0x405C80, CdStreamInit, PATCH_JUMP); - //InjectHook(0x405DB0, debug, PATCH_JUMP); - InjectHook(0x405DC0, GetGTA3ImgSize, PATCH_JUMP); - InjectHook(0x405DD0, CdStreamShutdown, PATCH_JUMP); - InjectHook(0x405E40, CdStreamRead, PATCH_JUMP); - InjectHook(0x405F90, CdStreamGetStatus, PATCH_JUMP); - InjectHook(0x406000, CdStreamGetLastPosn, PATCH_JUMP); - InjectHook(0x406010, CdStreamSync, PATCH_JUMP); - InjectHook(0x4060B0, AddToQueue, PATCH_JUMP); - InjectHook(0x4060F0, GetFirstInQueue, PATCH_JUMP); - InjectHook(0x406110, RemoveFirstInQueue, PATCH_JUMP); - InjectHook(0x406140, CdStreamThread, PATCH_JUMP); - InjectHook(0x406270, CdStreamAddImage, PATCH_JUMP); - InjectHook(0x4062E0, CdStreamGetImageName, PATCH_JUMP); - InjectHook(0x406300, CdStreamRemoveImages, PATCH_JUMP); - InjectHook(0x406370, CdStreamGetNumImages, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/core/Clock.cpp b/src/core/Clock.cpp index 69fdd682..e4b908e0 100644 --- a/src/core/Clock.cpp +++ b/src/core/Clock.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Timer.h" #include "Pad.h" #include "Clock.h" @@ -115,14 +115,3 @@ CClock::RestoreClock(void) ms_nGameClockMinutes = ms_Stored_nGameClockMinutes; ms_nGameClockSeconds = ms_Stored_nGameClockSeconds; } - - -STARTPATCHES - InjectHook(0x473370, CClock::Initialise, PATCH_JUMP); - InjectHook(0x473460, CClock::Update, PATCH_JUMP); - InjectHook(0x4733C0, CClock::SetGameClock, PATCH_JUMP); - InjectHook(0x4733F0, CClock::GetGameClockMinutesUntil, PATCH_JUMP); - InjectHook(0x473420, CClock::GetIsTimeInRange, PATCH_JUMP); - InjectHook(0x473540, CClock::StoreClock, PATCH_JUMP); - InjectHook(0x473570, CClock::RestoreClock, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index 85145e86..5bdb32dc 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Lists.h" #include "Game.h" @@ -2140,70 +2140,3 @@ CColModel::operator=(const CColModel &other) } return *this; } - -#include -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); - - InjectHook(0x40B380, CCollision::Init, PATCH_JUMP); - InjectHook(0x40B3A0, CCollision::Shutdown, PATCH_JUMP); - InjectHook(0x40B3B0, CCollision::Update, PATCH_JUMP); - InjectHook(0x40B5B0, CCollision::LoadCollisionWhenINeedIt, PATCH_JUMP); - InjectHook(0x40B900, CCollision::SortOutCollisionAfterLoad, PATCH_JUMP); - - InjectHook(0x40BB70, CCollision::TestSphereBox, PATCH_JUMP); - InjectHook(0x40E130, CCollision::TestLineBox, PATCH_JUMP); - InjectHook(0x40E5C0, CCollision::TestVerticalLineBox, PATCH_JUMP); - InjectHook(0x40EC10, CCollision::TestLineTriangle, PATCH_JUMP); - InjectHook(0x40DAA0, CCollision::TestLineSphere, PATCH_JUMP); - InjectHook(0x40C580, CCollision::TestSphereTriangle, PATCH_JUMP); - InjectHook(0x40F720, CCollision::TestLineOfSight, PATCH_JUMP); - - InjectHook(0x40B9F0, CCollision::ProcessSphereSphere, PATCH_JUMP); - InjectHook(0x40BC00, CCollision::ProcessSphereBox, PATCH_JUMP); - InjectHook(0x40E670, CCollision::ProcessLineBox, PATCH_JUMP); - InjectHook(0x40DE80, CCollision::ProcessLineSphere, PATCH_JUMP); - InjectHook(0x40FB50, CCollision::ProcessVerticalLineTriangle, PATCH_JUMP); - InjectHook(0x40F140, CCollision::ProcessLineTriangle, PATCH_JUMP); - InjectHook(0x40CE30, CCollision::ProcessSphereTriangle, PATCH_JUMP); - - InjectHook(0x40F910, CCollision::ProcessLineOfSight, PATCH_JUMP); - InjectHook(0x410120, CCollision::ProcessVerticalLine, PATCH_JUMP); - InjectHook(0x410BE0, CCollision::ProcessColModels, PATCH_JUMP); - - InjectHook(0x40B960, CCollision::CalculateTrianglePlanes, PATCH_JUMP); - InjectHook(0x411640, &CLink::Remove, PATCH_JUMP); - InjectHook(0x411620, &CLink::Insert, PATCH_JUMP); - InjectHook(0x4115C0, &CLinkList::Insert, PATCH_JUMP); - InjectHook(0x411600, &CLinkList::Remove, PATCH_JUMP); -// InjectHook(0x411530, &CLinkList::Init, PATCH_JUMP); - - 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(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(0x411D80, &CColModel::RemoveCollisionVolumes, PATCH_JUMP); - InjectHook(0x411CB0, &CColModel::CalculateTrianglePlanes, PATCH_JUMP); - InjectHook(0x411D10, &CColModel::RemoveTrianglePlanes, PATCH_JUMP); - InjectHook(0x411D40, &CColModel::SetLinkPtr, PATCH_JUMP); - InjectHook(0x411D60, &CColModel::GetLinkPtr, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index ce8674d7..a2382c12 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -1,7 +1,7 @@ #define DIRECTINPUT_VERSION 0x0800 #include #include "common.h" -#include "patcher.h" + #include "ControllerConfig.h" #include "Pad.h" #include "FileMgr.h" @@ -2362,57 +2362,3 @@ void CControllerConfigManager::ResetSettingOrder(e_ControllerAction action) } } } - - -STARTPATCHES - InjectHook(0x58B7A0, &CControllerConfigManager::MakeControllerActionsBlank, PATCH_JUMP); - InjectHook(0x58B7D0, &CControllerConfigManager::GetJoyButtonJustDown, PATCH_JUMP); - InjectHook(0x58B800, &CControllerConfigManager::SaveSettings, PATCH_JUMP); - InjectHook(0x58B870, &CControllerConfigManager::LoadSettings, PATCH_JUMP); - InjectHook(0x58B930, &CControllerConfigManager::InitDefaultControlConfiguration, PATCH_JUMP); - InjectHook(0x58BD00, &CControllerConfigManager::InitDefaultControlConfigMouse, PATCH_JUMP); - InjectHook(0x58BD90, &CControllerConfigManager::InitDefaultControlConfigJoyPad, PATCH_JUMP); - InjectHook(0x58C060, &CControllerConfigManager::InitialiseControllerActionNameArray, PATCH_JUMP); - InjectHook(0x58C5E0, &CControllerConfigManager::UpdateJoyInConfigMenus_ButtonDown, PATCH_JUMP); - InjectHook(0x58C730, &CControllerConfigManager::AffectControllerStateOn_ButtonDown, PATCH_JUMP); - InjectHook(0x58C880, &CControllerConfigManager::AffectControllerStateOn_ButtonDown_Driving, PATCH_JUMP); - InjectHook(0x58CAD0, &CControllerConfigManager::AffectControllerStateOn_ButtonDown_FirstPersonOnly, PATCH_JUMP); - InjectHook(0x58CB10, &CControllerConfigManager::AffectControllerStateOn_ButtonDown_ThirdPersonOnly, PATCH_JUMP); - InjectHook(0x58CBD0, &CControllerConfigManager::AffectControllerStateOn_ButtonDown_FirstAndThirdPersonOnly, PATCH_JUMP); - InjectHook(0x58CD70, &CControllerConfigManager::AffectControllerStateOn_ButtonDown_AllStates, PATCH_JUMP); - InjectHook(0x58CE50, &CControllerConfigManager::AffectControllerStateOn_ButtonDown_VehicleAndThirdPersonOnly, PATCH_JUMP); - InjectHook(0x58CE80, &CControllerConfigManager::UpdateJoyInConfigMenus_ButtonUp, PATCH_JUMP); - InjectHook(0x58CFD0, &CControllerConfigManager::AffectControllerStateOn_ButtonUp, PATCH_JUMP); - InjectHook(0x58D090, &CControllerConfigManager::AffectControllerStateOn_ButtonUp_All_Player_States, PATCH_JUMP); - InjectHook(0x58D0C0, &CControllerConfigManager::AffectPadFromKeyBoard, PATCH_JUMP); - InjectHook(0x58D1A0, &CControllerConfigManager::AffectPadFromMouse, PATCH_JUMP); - InjectHook(0x58D220, &CControllerConfigManager::ClearSimButtonPressCheckers, PATCH_JUMP); - InjectHook(0x58D2A0, &CControllerConfigManager::GetIsKeyboardKeyDown, PATCH_JUMP); - InjectHook(0x58D8A0, &CControllerConfigManager::GetIsKeyboardKeyJustDown, PATCH_JUMP); - InjectHook(0x58E280, &CControllerConfigManager::GetIsMouseButtonDown, PATCH_JUMP); - InjectHook(0x58E360, &CControllerConfigManager::GetIsMouseButtonUp, PATCH_JUMP); - InjectHook(0x58E440, &CControllerConfigManager::DeleteMatchingCommonControls, PATCH_JUMP); - InjectHook(0x58E540, &CControllerConfigManager::DeleteMatching3rdPersonControls, PATCH_JUMP); - InjectHook(0x58E630, &CControllerConfigManager::DeleteMatching1rst3rdPersonControls, PATCH_JUMP); - InjectHook(0x58E710, &CControllerConfigManager::DeleteMatchingVehicleControls, PATCH_JUMP); - InjectHook(0x58E890, &CControllerConfigManager::DeleteMatchingVehicle_3rdPersonControls, PATCH_JUMP); - InjectHook(0x58E8D0, &CControllerConfigManager::DeleteMatching1rstPersonControls, PATCH_JUMP); - InjectHook(0x58E920, &CControllerConfigManager::DeleteMatchingActionInitiators, PATCH_JUMP); - InjectHook(0x58EA70, &CControllerConfigManager::GetIsKeyBlank, PATCH_JUMP); - InjectHook(0x58EAD0, &CControllerConfigManager::GetActionType, PATCH_JUMP); - InjectHook(0x58EB40, &CControllerConfigManager::ClearSettingsAssociatedWithAction, PATCH_JUMP); - InjectHook(0x58EBF0, &CControllerConfigManager::GetControllerSettingTextWithOrderNumber, PATCH_JUMP); - InjectHook(0x58EC50, &CControllerConfigManager::GetControllerSettingTextKeyBoard, PATCH_JUMP); - InjectHook(0x58F320, &CControllerConfigManager::GetControllerSettingTextMouse, PATCH_JUMP); - InjectHook(0x58F3D0, &CControllerConfigManager::GetControllerSettingTextJoystick, PATCH_JUMP); - InjectHook(0x58F420, &CControllerConfigManager::GetNumOfSettingsForAction, PATCH_JUMP); - InjectHook(0x58F460, &CControllerConfigManager::GetWideStringOfCommandKeys, PATCH_JUMP); - InjectHook(0x58F590, &CControllerConfigManager::GetControllerKeyAssociatedWithAction, PATCH_JUMP); - InjectHook(0x58F5B0, &CControllerConfigManager::UpdateJoyButtonState, PATCH_JUMP); - InjectHook(0x58F660, &CControllerConfigManager::GetIsActionAButtonCombo, PATCH_JUMP); - InjectHook(0x58F690, &CControllerConfigManager::GetButtonComboText, PATCH_JUMP); - InjectHook(0x58F700, &CControllerConfigManager::SetControllerKeyAssociatedWithAction, PATCH_JUMP); - InjectHook(0x58F740, &CControllerConfigManager::GetMouseButtonAssociatedWithAction, PATCH_JUMP); - InjectHook(0x58F760, &CControllerConfigManager::SetMouseButtonAssociatedWithAction, PATCH_JUMP); - InjectHook(0x58F790, &CControllerConfigManager::ResetSettingOrder, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Directory.cpp b/src/core/Directory.cpp index d4b4279d..27539824 100644 --- a/src/core/Directory.cpp +++ b/src/core/Directory.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "FileMgr.h" #include "Directory.h" @@ -57,10 +57,3 @@ CDirectory::FindItem(const char *name, uint32 &offset, uint32 &size) } return false; } - -STARTPATCHES - InjectHook(0x473630, &CDirectory::ReadDirFile, PATCH_JUMP); - InjectHook(0x473690, &CDirectory::WriteDirFile, PATCH_JUMP); - InjectHook(0x473600, &CDirectory::AddItem, PATCH_JUMP); - InjectHook(0x4736E0, &CDirectory::FindItem, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/EventList.cpp b/src/core/EventList.cpp index 5ca4cdb0..675040ea 100644 --- a/src/core/EventList.cpp +++ b/src/core/EventList.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Pools.h" #include "ModelIndices.h" #include "World.h" @@ -227,14 +227,3 @@ CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCar FindPlayerPed()->SetWantedLevelNoDrop(2); } - -STARTPATCHES - InjectHook(0x475B60, CEventList::Initialise, PATCH_JUMP); - InjectHook(0x475BE0, CEventList::Update, PATCH_JUMP); - InjectHook(0x475C50, (void (*)(eEventType,eEventEntity,CEntity *,CPed *,int32))CEventList::RegisterEvent, PATCH_JUMP); - InjectHook(0x475E10, (void (*)(eEventType,CVector,int32))CEventList::RegisterEvent, PATCH_JUMP); - InjectHook(0x475F40, CEventList::GetEvent, PATCH_JUMP); - InjectHook(0x475F70, CEventList::ClearEvent, PATCH_JUMP); - InjectHook(0x475F90, CEventList::FindClosestEvent, PATCH_JUMP); - InjectHook(0x476070, CEventList::ReportCrimeForEvent, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index e0a0fafc..b7d82089 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "main.h" -#include "patcher.h" + #include "Quaternion.h" #include "ModelInfo.h" #include "ModelIndices.h" @@ -1355,43 +1355,3 @@ CFileLoader::ReLoadScene(const char *filename) } CFileMgr::CloseFile(fd); } - -STARTPATCHES - InjectHook(0x476290, CFileLoader::LoadLevel, PATCH_JUMP); - - InjectHook(0x476520, CFileLoader::LoadCollisionFromDatFile, PATCH_JUMP); - InjectHook(0x4761D0, CFileLoader::LoadLine, PATCH_JUMP); - InjectHook(0x4765B0, CFileLoader::LoadTexDictionary, PATCH_JUMP); - InjectHook(0x478B20, CFileLoader::LoadCollisionFile, PATCH_JUMP); - InjectHook(0x478C20, CFileLoader::LoadCollisionModel, PATCH_JUMP); - InjectHook(0x476750, CFileLoader::LoadModelFile, PATCH_JUMP); - InjectHook(0x476810, (void (*)(const char*))CFileLoader::LoadClumpFile, PATCH_JUMP); - InjectHook(0x476990, (bool (*)(RwStream*,uint32))CFileLoader::LoadClumpFile, PATCH_JUMP); - InjectHook(0x476A20, CFileLoader::StartLoadClumpFile, PATCH_JUMP); - InjectHook(0x476A70, CFileLoader::FinishLoadClumpFile, PATCH_JUMP); - InjectHook(0x476930, CFileLoader::LoadAtomicFile, PATCH_JUMP); - InjectHook(0x4767C0, CFileLoader::LoadAtomicFile2Return, PATCH_JUMP); - InjectHook(0x476630, CFileLoader::AddTexDictionaries, PATCH_JUMP); - - InjectHook(0x476AC0, CFileLoader::LoadObjectTypes, PATCH_JUMP); - InjectHook(0x477040, CFileLoader::LoadObject, PATCH_JUMP); - InjectHook(0x4774B0, CFileLoader::LoadTimeObject, PATCH_JUMP); - InjectHook(0x477920, CFileLoader::LoadClumpObject, PATCH_JUMP); - InjectHook(0x477990, CFileLoader::LoadVehicleObject, PATCH_JUMP); - InjectHook(0x477DE0, CFileLoader::LoadPedObject, PATCH_JUMP); - InjectHook(0x477ED0, CFileLoader::LoadPathHeader, PATCH_JUMP); - InjectHook(0x477FF0, CFileLoader::LoadCarPathNode, PATCH_JUMP); - InjectHook(0x477F00, CFileLoader::LoadPedPathNode, PATCH_JUMP); - InjectHook(0x4780E0, CFileLoader::Load2dEffect, PATCH_JUMP); - - InjectHook(0x478370, CFileLoader::LoadScene, PATCH_JUMP); - InjectHook(0x4786B0, CFileLoader::LoadObjectInstance, PATCH_JUMP); - InjectHook(0x478A00, CFileLoader::LoadZone, PATCH_JUMP); - InjectHook(0x478A90, CFileLoader::LoadCullZone, PATCH_JUMP); - - InjectHook(0x478550, CFileLoader::LoadMapZones, PATCH_JUMP); - - InjectHook(0x476DB0, CFileLoader::ReloadPaths, PATCH_JUMP); - InjectHook(0x476F30, CFileLoader::ReloadObjectTypes, PATCH_JUMP); - InjectHook(0x4772B0, CFileLoader::ReloadObject, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp index 382316bb..46d725cd 100644 --- a/src/core/FileMgr.cpp +++ b/src/core/FileMgr.cpp @@ -2,7 +2,7 @@ #include #include #include "common.h" -#include "patcher.h" + #include "FileMgr.h" const char *_psGetUserFilesFolder(); @@ -282,19 +282,3 @@ CFileMgr::GetErrorReadWrite(int fd) { return myfeof(fd); } - -STARTPATCHES - InjectHook(0x478F80, CFileMgr::Initialise, PATCH_JUMP); - InjectHook(0x478FB0, CFileMgr::ChangeDir, PATCH_JUMP); - InjectHook(0x479020, CFileMgr::SetDir, PATCH_JUMP); - InjectHook(0x479080, CFileMgr::SetDirMyDocuments, PATCH_JUMP); - InjectHook(0x479090, CFileMgr::LoadFile, PATCH_JUMP); - InjectHook(0x479100, CFileMgr::OpenFile, PATCH_JUMP); - InjectHook(0x479120, CFileMgr::OpenFileForWriting, PATCH_JUMP); - InjectHook(0x479140, CFileMgr::Read, PATCH_JUMP); - InjectHook(0x479160, CFileMgr::Write, PATCH_JUMP); - InjectHook(0x479180, CFileMgr::Seek, PATCH_JUMP); - InjectHook(0x4791D0, CFileMgr::ReadLine, PATCH_JUMP); - InjectHook(0x479200, CFileMgr::CloseFile, PATCH_JUMP); - InjectHook(0x479210, CFileMgr::GetErrorReadWrite, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index f900091e..65b6deb2 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Vector.h" #include "PlayerPed.h" #include "Entity.h" @@ -438,21 +438,3 @@ CFireManager::SetScriptFireAudio(int16 index, bool state) { m_aFires[index].m_bAudioSet = state; } - -STARTPATCHES - 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 diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index b2ecdac5..790de046 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -1,7 +1,7 @@ #define DIRECTINPUT_VERSION 0x0800 #include #include "common.h" -#include "patcher.h" + #include "win.h" #include "Frontend.h" #include "Font.h" @@ -5624,21 +5624,3 @@ uint8 CMenuManager::GetNumberOfMenuOptions() #undef GetBackJustUp #undef GetBackJustDown - -STARTPATCHES - for (int i = 1; i < ARRAY_SIZE(aScreens); i++) - Patch(0x611930 + sizeof(CMenuScreen) * i, aScreens[i]); - InjectHook(0x4856F0, &CMenuManager::ProcessButtonPresses, PATCH_JUMP); - InjectHook(0x485100, &CMenuManager::Process, PATCH_JUMP); - InjectHook(0x47A230, &CMenuManager::LoadAllTextures, PATCH_JUMP); - InjectHook(0x47A540, &CMenuManager::DrawFrontEnd, PATCH_JUMP); - - InjectHook(0x48ABE0, &CMenuManager::StretchX, PATCH_JUMP); - InjectHook(0x48AC20, &CMenuManager::StretchY, PATCH_JUMP); - InjectHook(0x488EE0, &CMenuManager::LoadSettings, PATCH_JUMP); - InjectHook(0x488CC0, &CMenuManager::SaveSettings, PATCH_JUMP); - InjectHook(0x47A440, &CMenuManager::UnloadTextures, PATCH_JUMP); - InjectHook(0x48AB40, &CMenuManager::DoSettingsBeforeStartingAGame, PATCH_JUMP); - InjectHook(0x48AE60, &CMenuManager::ProcessOnOffMenuOptions, PATCH_JUMP); - InjectHook(0x489710, &CMenuManager::DrawControllerBound, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/core/Game.cpp b/src/core/Game.cpp index f115d52f..7ccf78d0 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -5,7 +5,7 @@ #pragma warning( pop ) #include "common.h" #include "win.h" -#include "patcher.h" + #include "Game.h" #include "main.h" #include "RwHelper.h" @@ -710,20 +710,3 @@ void CGame::ProcessTidyUpMemory(void) // meow #endif } - -STARTPATCHES - InjectHook(0x48BB80, CGame::InitialiseOnceBeforeRW, PATCH_JUMP); - InjectHook(0x48BBA0, CGame::InitialiseRenderWare, PATCH_JUMP); - InjectHook(0x48BCB0, CGame::ShutdownRenderWare, PATCH_JUMP); - InjectHook(0x48BD50, CGame::InitialiseOnceAfterRW, PATCH_JUMP); - InjectHook(0x48BEC0, CGame::FinalShutdown, PATCH_JUMP); - InjectHook(0x48BED0, CGame::Initialise, PATCH_JUMP); - InjectHook(0x48C3A0, CGame::ShutDown, PATCH_JUMP); - InjectHook(0x48C4B0, CGame::ReInitGameObjectVariables, PATCH_JUMP); - InjectHook(0x48C620, CGame::ReloadIPLs, PATCH_JUMP); - InjectHook(0x48C6B0, CGame::ShutDownForRestart, PATCH_JUMP); - InjectHook(0x48C740, CGame::InitialiseWhenRestarting, PATCH_JUMP); - InjectHook(0x48C850, CGame::Process, PATCH_JUMP); - InjectHook(0x48CA10, CGame::DrasticTidyUpMemory, PATCH_JUMP); - InjectHook(0x48CA20, CGame::TidyUpMemory, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/IniFile.cpp b/src/core/IniFile.cpp index d8e91c98..16e35633 100644 --- a/src/core/IniFile.cpp +++ b/src/core/IniFile.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "IniFile.h" #include "CarCtrl.h" diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 2db375b2..86aff05e 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -9,7 +9,7 @@ #include #pragma comment( lib, "Xinput9_1_0.lib" ) #endif -#include "patcher.h" + #include "Pad.h" #include "ControllerConfig.h" #include "Timer.h" @@ -1285,7 +1285,7 @@ bool CPad::GetLookRight(void) { if ( ArePlayerControlsDisabled() ) return false; - + return !!(NewState.RightShoulder2 && !NewState.LeftShoulder2); } @@ -1294,7 +1294,7 @@ bool CPad::GetLookBehindForCar(void) { if ( ArePlayerControlsDisabled() ) return false; - + return !!(NewState.RightShoulder2 && NewState.LeftShoulder2); } @@ -1768,7 +1768,7 @@ bool CPad::CycleWeaponRightJustDown(void) { if ( ArePlayerControlsDisabled() ) return false; - + return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); } @@ -1865,7 +1865,7 @@ bool CPad::ShiftTargetLeftJustDown(void) { if ( ArePlayerControlsDisabled() ) return false; - + return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); } @@ -1873,7 +1873,7 @@ bool CPad::ShiftTargetRightJustDown(void) { if ( ArePlayerControlsDisabled() ) return false; - + return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); } @@ -2404,111 +2404,3 @@ int32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize) return pRsKeys; } - -STARTPATCHES - InjectHook(0x490D90, &WeaponCheat, PATCH_JUMP); - InjectHook(0x490E70, &HealthCheat, PATCH_JUMP); - InjectHook(0x490EE0, &TankCheat, PATCH_JUMP); - InjectHook(0x491040, &BlowUpCarsCheat, PATCH_JUMP); - InjectHook(0x4910B0, &ChangePlayerCheat, PATCH_JUMP); - InjectHook(0x4911C0, &MayhemCheat, PATCH_JUMP); - InjectHook(0x491270, &EverybodyAttacksPlayerCheat, PATCH_JUMP); - InjectHook(0x491370, &WeaponsForAllCheat, PATCH_JUMP); - InjectHook(0x4913A0, &FastTimeCheat, PATCH_JUMP); - InjectHook(0x4913F0, &SlowTimeCheat, PATCH_JUMP); - InjectHook(0x491430, &MoneyCheat, PATCH_JUMP); - InjectHook(0x491460, &ArmourCheat, PATCH_JUMP); - InjectHook(0x491490, &WantedLevelUpCheat, PATCH_JUMP); - InjectHook(0x4914F0, &WantedLevelDownCheat, PATCH_JUMP); - InjectHook(0x491520, &SunnyWeatherCheat, PATCH_JUMP); - InjectHook(0x491550, &CloudyWeatherCheat, PATCH_JUMP); - InjectHook(0x491580, &RainyWeatherCheat, PATCH_JUMP); - InjectHook(0x4915B0, &FoggyWeatherCheat, PATCH_JUMP); - InjectHook(0x4915E0, &FastWeatherCheat, PATCH_JUMP); - InjectHook(0x491610, &OnlyRenderWheelsCheat, PATCH_JUMP); - InjectHook(0x491640, &ChittyChittyBangBangCheat, PATCH_JUMP); - InjectHook(0x491670, &StrongGripCheat, PATCH_JUMP); - InjectHook(0x4916A0, &NastyLimbsCheat, PATCH_JUMP); - - InjectHook(0x4916C0, &CControllerState::Clear, PATCH_JUMP); - InjectHook(0x491760, &CKeyboardState::Clear, PATCH_JUMP); - InjectHook(0x491A10, &CPad::Clear, PATCH_JUMP); - InjectHook(0x491B50, &CPad::ClearMouseHistory, PATCH_JUMP); - //InjectHook(0x491B80, &CMouseControllerState::CMouseControllerState, PATCH_JUMP); - InjectHook(0x491BB0, &CMouseControllerState::Clear, PATCH_JUMP); - InjectHook(0x491BD0, &CMousePointerStateHelper::GetMouseSetUp, PATCH_JUMP); - InjectHook(0x491CA0, &CPad::UpdateMouse, PATCH_JUMP); - InjectHook(0x491E60, &CPad::ReconcileTwoControllersInput, PATCH_JUMP); - InjectHook(0x492230, &CPad::StartShake, PATCH_JUMP); - InjectHook(0x492290, &CPad::StartShake_Distance, PATCH_JUMP); - InjectHook(0x492360, &CPad::StartShake_Train, PATCH_JUMP); - InjectHook(0x492450, &CPad::AddToPCCheatString, PATCH_JUMP); - InjectHook(0x492720, CPad::UpdatePads, PATCH_JUMP); - InjectHook(0x492C60, &CPad::ProcessPCSpecificStuff, PATCH_JUMP); - InjectHook(0x492C70, &CPad::Update, PATCH_JUMP); -#pragma warning( push ) -#pragma warning( disable : 4573) - InjectHook(0x492F00, (void (*)())CPad::DoCheats, PATCH_JUMP); -#pragma warning( pop ) - InjectHook(0x492F20, (void (CPad::*)(int16))&CPad::DoCheats, PATCH_JUMP); - InjectHook(0x492F30, CPad::StopPadsShaking, PATCH_JUMP); - InjectHook(0x492F50, &CPad::StopShaking, PATCH_JUMP); - InjectHook(0x492F60, CPad::GetPad, PATCH_JUMP); - InjectHook(0x492F70, &CPad::GetSteeringLeftRight, PATCH_JUMP); - InjectHook(0x492FF0, &CPad::GetSteeringUpDown, PATCH_JUMP); - InjectHook(0x493070, &CPad::GetCarGunUpDown, PATCH_JUMP); - InjectHook(0x4930C0, &CPad::GetCarGunLeftRight, PATCH_JUMP); - InjectHook(0x493110, &CPad::GetPedWalkLeftRight, PATCH_JUMP); - InjectHook(0x493190, &CPad::GetPedWalkUpDown, PATCH_JUMP); - InjectHook(0x493210, &CPad::GetAnalogueUpDown, PATCH_JUMP); - InjectHook(0x493290, &CPad::GetLookLeft, PATCH_JUMP); - InjectHook(0x4932C0, &CPad::GetLookRight, PATCH_JUMP); - InjectHook(0x4932F0, &CPad::GetLookBehindForCar, PATCH_JUMP); - InjectHook(0x493320, &CPad::GetLookBehindForPed, PATCH_JUMP); - InjectHook(0x493350, &CPad::GetHorn, PATCH_JUMP); - InjectHook(0x4933F0, &CPad::HornJustDown, PATCH_JUMP); - InjectHook(0x493490, &CPad::GetCarGunFired, PATCH_JUMP); - InjectHook(0x4934F0, &CPad::CarGunJustDown, PATCH_JUMP); - InjectHook(0x493560, &CPad::GetHandBrake, PATCH_JUMP); - InjectHook(0x4935A0, &CPad::GetBrake, PATCH_JUMP); - InjectHook(0x4935F0, &CPad::GetExitVehicle, PATCH_JUMP); - InjectHook(0x493650, &CPad::ExitVehicleJustDown, PATCH_JUMP); - InjectHook(0x4936C0, &CPad::GetWeapon, PATCH_JUMP); - InjectHook(0x493700, &CPad::WeaponJustDown, PATCH_JUMP); - InjectHook(0x493780, &CPad::GetAccelerate, PATCH_JUMP); - InjectHook(0x4937D0, &CPad::CycleCameraModeUpJustDown, PATCH_JUMP); - InjectHook(0x493830, &CPad::CycleCameraModeDownJustDown, PATCH_JUMP); - InjectHook(0x493870, &CPad::ChangeStationJustDown, PATCH_JUMP); - InjectHook(0x493910, &CPad::CycleWeaponLeftJustDown, PATCH_JUMP); - InjectHook(0x493940, &CPad::CycleWeaponRightJustDown, PATCH_JUMP); - InjectHook(0x493970, &CPad::GetTarget, PATCH_JUMP); - InjectHook(0x4939D0, &CPad::TargetJustDown, PATCH_JUMP); - InjectHook(0x493A40, &CPad::JumpJustDown, PATCH_JUMP); - InjectHook(0x493A70, &CPad::GetSprint, PATCH_JUMP); - InjectHook(0x493AE0, &CPad::ShiftTargetLeftJustDown, PATCH_JUMP); - InjectHook(0x493B10, &CPad::ShiftTargetRightJustDown, PATCH_JUMP); - InjectHook(0x493B40, &CPad::GetAnaloguePadUp, PATCH_JUMP); - InjectHook(0x493BA0, &CPad::GetAnaloguePadDown, PATCH_JUMP); - InjectHook(0x493C00, &CPad::GetAnaloguePadLeft, PATCH_JUMP); - InjectHook(0x493C60, &CPad::GetAnaloguePadRight, PATCH_JUMP); - InjectHook(0x493CC0, &CPad::GetAnaloguePadLeftJustUp, PATCH_JUMP); - InjectHook(0x493D20, &CPad::GetAnaloguePadRightJustUp, PATCH_JUMP); - InjectHook(0x493D80, &CPad::ForceCameraBehindPlayer, PATCH_JUMP); - InjectHook(0x493E00, &CPad::SniperZoomIn, PATCH_JUMP); - InjectHook(0x493E70, &CPad::SniperZoomOut, PATCH_JUMP); - InjectHook(0x493EE0, &CPad::SniperModeLookLeftRight, PATCH_JUMP); - InjectHook(0x493F30, &CPad::SniperModeLookUpDown, PATCH_JUMP); - InjectHook(0x493F80, &CPad::LookAroundLeftRight, PATCH_JUMP); - InjectHook(0x494130, &CPad::LookAroundUpDown, PATCH_JUMP); - InjectHook(0x494290, &CPad::ResetAverageWeapon, PATCH_JUMP); - InjectHook(0x4942B0, CPad::PrintErrorMessage, PATCH_JUMP); - InjectHook(0x494420, LittleTest, PATCH_JUMP); - InjectHook(0x494450, CPad::ResetCheats, PATCH_JUMP); - InjectHook(0x4944B0, CPad::EditString, PATCH_JUMP); - InjectHook(0x494690, CPad::EditCodesForControls, PATCH_JUMP); - - //InjectHook(0x494E50, `global constructor keyed to'Pad.cpp, PATCH_JUMP); - //InjectHook(0x494EB0, sub_494EB0, PATCH_JUMP); - //InjectHook(0x494ED0, &CPad::~CPad, PATCH_JUMP); - //InjectHook(0x494EE0, &CPad::CPad, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Placeable.cpp b/src/core/Placeable.cpp index c882fc27..99ca5659 100644 --- a/src/core/Placeable.cpp +++ b/src/core/Placeable.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "Placeable.h" -#include "patcher.h" + CPlaceable::CPlaceable(void) { @@ -62,21 +62,3 @@ CPlaceable::IsWithinArea(float x1, float y1, float z1, float x2, float y2, float y1 <= GetPosition().y && GetPosition().y <= y2 && z1 <= GetPosition().z && GetPosition().z <= z2; } - -#include - -class CPlaceable_ : public CPlaceable -{ -public: - CPlaceable *ctor(void) { return ::new (this) CPlaceable(); } - void dtor(void) { CPlaceable::~CPlaceable(); } -}; - -STARTPATCHES - InjectHook(0x49F9A0, &CPlaceable_::ctor, PATCH_JUMP); - InjectHook(0x49F9E0, &CPlaceable_::dtor, PATCH_JUMP); - - InjectHook(0x49FA00, &CPlaceable::SetHeading, PATCH_JUMP); - InjectHook(0x49FA50, (bool (CPlaceable::*)(float, float, float, float))&CPlaceable::IsWithinArea, PATCH_JUMP); - InjectHook(0x49FAF0, (bool (CPlaceable::*)(float, float, float, float, float, float))&CPlaceable::IsWithinArea, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 0043c2f4..cfa0cea4 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "PlayerPed.h" #include "Wanted.h" @@ -558,20 +558,3 @@ CPlayerInfo::Process(void) CStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled; } } - -STARTPATCHES - InjectHook(0x4B5DC0, &CPlayerInfo::dtor, PATCH_JUMP); - InjectHook(0x4A1700, &CPlayerInfo::LoadPlayerSkin, PATCH_JUMP); - InjectHook(0x4A1750, &CPlayerInfo::DeletePlayerSkin, PATCH_JUMP); - InjectHook(0x4A12E0, &CPlayerInfo::KillPlayer, PATCH_JUMP); - InjectHook(0x4A1330, &CPlayerInfo::ArrestPlayer, PATCH_JUMP); - InjectHook(0x49FC10, &CPlayerInfo::Clear, PATCH_JUMP); - InjectHook(0x4A15C0, &CPlayerInfo::BlowUpRCBuggy, PATCH_JUMP); - InjectHook(0x4A13B0, &CPlayerInfo::CancelPlayerEnteringCars, PATCH_JUMP); - InjectHook(0x4A1400, &CPlayerInfo::MakePlayerSafe, PATCH_JUMP); - InjectHook(0x4A0EC0, &CPlayerInfo::EvaluateCarPosition, PATCH_JUMP); - InjectHook(0x4A15F0, &CPlayerInfo::AwardMoneyForExplosion, PATCH_JUMP); - InjectHook(0x4A0B20, &CPlayerInfo::LoadPlayerInfo, PATCH_JUMP); - InjectHook(0x4A0960, &CPlayerInfo::SavePlayerInfo, PATCH_JUMP); - InjectHook(0x49FD30, &CPlayerInfo::Process, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index 65294368..dfc6974a 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Pools.h" #include "Boat.h" @@ -425,19 +425,3 @@ INITSAVEBUF } VALIDATESAVEBUF(size) } - -STARTPATCHES - InjectHook(0x4A1770, CPools::Initialise, PATCH_JUMP); - InjectHook(0x4A1880, CPools::ShutDown, PATCH_JUMP); - InjectHook(0x4A1A50, CPools::CheckPoolsEmpty, PATCH_JUMP); - InjectHook(0x4A1A80, CPools::GetPedRef, PATCH_JUMP); - InjectHook(0x4A1AA0, CPools::GetPed, PATCH_JUMP); - InjectHook(0x4A1AC0, CPools::GetVehicleRef, PATCH_JUMP); - InjectHook(0x4A1AE0, CPools::GetVehicle, PATCH_JUMP); - InjectHook(0x4A1B00, CPools::GetObjectRef, PATCH_JUMP); - InjectHook(0x4A1B20, CPools::GetObject, PATCH_JUMP); - InjectHook(0x4A2DB0, CPools::MakeSureSlotInObjectPoolIsEmpty, PATCH_JUMP); - InjectHook(0x4A1B40, CPools::LoadVehiclePool, PATCH_JUMP); - InjectHook(0x4A2550, CPools::LoadObjectPool, PATCH_JUMP); - InjectHook(0x4A2B50, CPools::LoadPedPool, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index 48b97832..2b3e6f1e 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -1,6 +1,6 @@ #include "config.h" #include "common.h" -#include "patcher.h" + #include "RwHelper.h" #include "Radar.h" #include "Camera.h" @@ -1458,51 +1458,3 @@ CRadar::ToggleTargetMarker(float x, float y) } #endif -STARTPATCHES - InjectHook(0x4A3EF0, CRadar::Initialise, PATCH_JUMP); - InjectHook(0x4A3F60, CRadar::Shutdown, PATCH_JUMP); - InjectHook(0x4A4030, CRadar::LoadTextures, PATCH_JUMP); - InjectHook(0x4A4180, CRadar::GetNewUniqueBlipIndex, PATCH_JUMP); - InjectHook(0x4A41C0, CRadar::GetActualBlipArrayIndex, PATCH_JUMP); - InjectHook(0x4A4200, CRadar::DrawMap, PATCH_JUMP); - InjectHook(0x4A42F0, CRadar::DrawBlips, PATCH_JUMP); - InjectHook(0x4A4C70, CRadar::Draw3dMarkers, PATCH_JUMP); - InjectHook(0x4A4F30, CRadar::LimitRadarPoint, PATCH_JUMP); - InjectHook(0x4A4F90, CRadar::CalculateBlipAlpha, PATCH_JUMP); - InjectHook(0x4A5040, CRadar::TransformRadarPointToScreenSpace, PATCH_JUMP); - InjectHook(0x4A50D0, CRadar::TransformRealWorldPointToRadarSpace, PATCH_JUMP); - InjectHook(0x4A5300, CRadar::TransformRadarPointToRealWorldSpace, PATCH_JUMP); - InjectHook(0x4A5530, CRadar::TransformRealWorldToTexCoordSpace, PATCH_JUMP); - InjectHook(0x4A5590, CRadar::SetCoordBlip, PATCH_JUMP); - InjectHook(0x4A5640, CRadar::SetEntityBlip, PATCH_JUMP); - InjectHook(0x4A56C0, CRadar::ClearBlipForEntity, PATCH_JUMP); - InjectHook(0x4A5720, CRadar::ClearBlip, PATCH_JUMP); - InjectHook(0x4A5770, CRadar::ChangeBlipColour, PATCH_JUMP); - InjectHook(0x4A57A0, CRadar::ChangeBlipBrightness, PATCH_JUMP); - InjectHook(0x4A57E0, CRadar::ChangeBlipScale, PATCH_JUMP); - InjectHook(0x4A5810, CRadar::ChangeBlipDisplay, PATCH_JUMP); - InjectHook(0x4A5840, CRadar::SetBlipSprite, PATCH_JUMP); - InjectHook(0x4A5870, CRadar::ShowRadarTrace, PATCH_JUMP); - InjectHook(0x4A59C0, CRadar::ShowRadarMarker, PATCH_JUMP); - InjectHook(0x4A5BB0, CRadar::GetRadarTraceColour, PATCH_JUMP); - InjectHook(0x4A5C60, CRadar::SetRadarMarkerState, PATCH_JUMP); - InjectHook(0x4A5D10, CRadar::DrawRotatingRadarSprite, PATCH_JUMP); - InjectHook(0x4A5EF0, CRadar::DrawRadarSprite, PATCH_JUMP); - InjectHook(0x4A6020, ClipRadarTileCoords, PATCH_JUMP); - InjectHook(0x4A6060, RequestMapSection, PATCH_JUMP); - InjectHook(0x4A60A0, RemoveMapSection, PATCH_JUMP); - InjectHook(0x4A60E0, CRadar::RemoveRadarSections, PATCH_JUMP); - InjectHook(0x4A6100, (void (*)(int32, int32))&CRadar::StreamRadarSections, PATCH_JUMP); - InjectHook(0x4A6160, IsPointInsideRadar, PATCH_JUMP); - InjectHook(0x4A61C0, GetTextureCorners, PATCH_JUMP); - InjectHook(0x4A6250, LineRadarBoxCollision, PATCH_JUMP); - InjectHook(0x4A64A0, CRadar::ClipRadarPoly, PATCH_JUMP); - InjectHook(0x4A67E0, CRadar::DrawRadarSection, PATCH_JUMP); - InjectHook(0x4A69C0, CRadar::DrawRadarMask, PATCH_JUMP); - InjectHook(0x4A6B60, (void (*)(const CVector&))&CRadar::StreamRadarSections, PATCH_JUMP); - InjectHook(0x4A6C20, CRadar::DrawRadarMap, PATCH_JUMP); - InjectHook(0x4A6E30, CRadar::SaveAllRadarBlips, PATCH_JUMP); - InjectHook(0x4A6F30, CRadar::LoadAllRadarBlips, PATCH_JUMP); - //InjectHook(0x4A7000, `global constructor keyed to'Radar.cpp, PATCH_JUMP); - //InjectHook(0x4A7260, sRadarTrace::sRadarTrace, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/core/References.cpp b/src/core/References.cpp index 668ea9f1..3eb2eaf3 100644 --- a/src/core/References.cpp +++ b/src/core/References.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "World.h" #include "Vehicle.h" #include "PlayerPed.h" @@ -57,9 +57,3 @@ CReferences::PruneAllReferencesInWorld(void) e->PruneReferences(); } } - -STARTPATCHES - InjectHook(0x4A7350, CReferences::Init, PATCH_JUMP); - InjectHook(0x4A7570, CReferences::RemoveReferencesToPlayer, PATCH_JUMP); - InjectHook(0x4A75A0, CReferences::PruneAllReferencesInWorld, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index 8d7a3048..ef3c0ab6 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Stats.h" #include "Text.h" #include "World.h" @@ -418,11 +418,3 @@ void CStats::LoadStats(uint8 *buf, uint32 size) assert(buf - buf_start == size); #undef CopyFromBuf } - -STARTPATCHES - InjectHook(0x48C5A3, CStats::Init, PATCH_JUMP); // CGame::ReInitGameObjectVariables - InjectHook(0x4AB3E0, CStats::SaveStats, PATCH_JUMP); - InjectHook(0x4AB670, CStats::LoadStats, PATCH_JUMP); - InjectHook(0x4AB090, CStats::FindCriminalRatingString, PATCH_JUMP); - InjectHook(0x4AB2A0, CStats::FindCriminalRatingNumber, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 56f4a862..039377f4 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "Pad.h" #include "Hud.h" @@ -2439,82 +2439,3 @@ CStreaming::UpdateForAnimViewer(void) CStreaming::RetryLoadFile(CStreaming::ms_channelError); } } - -STARTPATCHES - InjectHook(0x406430, CStreaming::Init, PATCH_JUMP); - InjectHook(0x406C80, CStreaming::Shutdown, PATCH_JUMP); - InjectHook(0x4076C0, CStreaming::Update, PATCH_JUMP); - InjectHook(0x406CC0, (void (*)(void))CStreaming::LoadCdDirectory, PATCH_JUMP); - InjectHook(0x406DA0, (void (*)(const char*, int))CStreaming::LoadCdDirectory, PATCH_JUMP); - InjectHook(0x409740, CStreaming::ConvertBufferToObject, PATCH_JUMP); - InjectHook(0x409580, CStreaming::FinishLoadingLargeFile, PATCH_JUMP); - InjectHook(0x407EA0, CStreaming::RequestModel, PATCH_JUMP); - InjectHook(0x407FD0, CStreaming::RequestSubway, PATCH_JUMP); - InjectHook(0x408190, CStreaming::RequestBigBuildings, PATCH_JUMP); - InjectHook(0x408210, CStreaming::RequestIslands, PATCH_JUMP); - InjectHook(0x40A890, CStreaming::RequestSpecialModel, PATCH_JUMP); - InjectHook(0x40ADA0, CStreaming::RequestSpecialChar, PATCH_JUMP); - InjectHook(0x54A5F0, CStreaming::HasModelLoaded, PATCH_JUMP); - InjectHook(0x40ADC0, CStreaming::HasSpecialCharLoaded, PATCH_JUMP); - InjectHook(0x40ADE0, CStreaming::SetMissionDoesntRequireSpecialChar, PATCH_JUMP); - - InjectHook(0x408830, CStreaming::RemoveModel, PATCH_JUMP); - InjectHook(0x4083A0, CStreaming::RemoveUnusedBuildings, PATCH_JUMP); - InjectHook(0x4083D0, CStreaming::RemoveBuildings, PATCH_JUMP); - InjectHook(0x408640, CStreaming::RemoveUnusedBigBuildings, PATCH_JUMP); - InjectHook(0x408680, CStreaming::RemoveBigBuildings, PATCH_JUMP); - InjectHook(0x408780, CStreaming::RemoveIslandsNotUsed, PATCH_JUMP); - InjectHook(0x40B180, CStreaming::RemoveLoadedVehicle, PATCH_JUMP); - InjectHook(0x4089B0, CStreaming::RemoveLeastUsedModel, PATCH_JUMP); - InjectHook(0x408940, CStreaming::RemoveAllUnusedModels, PATCH_JUMP); - InjectHook(0x409450, CStreaming::RemoveReferencedTxds, PATCH_JUMP); - - InjectHook(0x40B160, CStreaming::GetAvailableVehicleSlot, PATCH_JUMP); - InjectHook(0x40B060, CStreaming::AddToLoadedVehiclesList, PATCH_JUMP); - InjectHook(0x4094C0, CStreaming::IsTxdUsedByRequestedModels, PATCH_JUMP); - InjectHook(0x407E70, CStreaming::IsObjectInCdImage, PATCH_JUMP); - InjectHook(0x408280, CStreaming::HaveAllBigBuildingsLoaded, PATCH_JUMP); - InjectHook(0x40A790, CStreaming::SetModelIsDeletable, PATCH_JUMP); - InjectHook(0x40A800, CStreaming::SetModelTxdIsDeletable, PATCH_JUMP); - InjectHook(0x40A820, CStreaming::SetMissionDoesntRequireModel, PATCH_JUMP); - - InjectHook(0x40AA00, CStreaming::LoadInitialPeds, PATCH_JUMP); - InjectHook(0x40ADF0, CStreaming::LoadInitialVehicles, PATCH_JUMP); - InjectHook(0x40AE60, CStreaming::StreamVehiclesAndPeds, PATCH_JUMP); - InjectHook(0x40AA30, CStreaming::StreamZoneModels, PATCH_JUMP); - InjectHook(0x40AD00, CStreaming::RemoveCurrentZonesModels, PATCH_JUMP); - - InjectHook(0x409BE0, CStreaming::ProcessLoadingChannel, PATCH_JUMP); - InjectHook(0x40A610, CStreaming::FlushChannels, PATCH_JUMP); - InjectHook(0x40A680, CStreaming::FlushRequestList, PATCH_JUMP); - InjectHook(0x409FF0, CStreaming::GetCdImageOffset, PATCH_JUMP); - InjectHook(0x409E50, CStreaming::GetNextFileOnCd, PATCH_JUMP); - InjectHook(0x40A060, CStreaming::RequestModelStream, PATCH_JUMP); - InjectHook(0x4077F0, CStreaming::RetryLoadFile, PATCH_JUMP); - InjectHook(0x40A390, CStreaming::LoadRequestedModels, PATCH_JUMP); - InjectHook(0x40A440, CStreaming::LoadAllRequestedModels, PATCH_JUMP); - - InjectHook(0x4078F0, CStreaming::AddModelsToRequestList, PATCH_JUMP); - InjectHook(0x407C50, (void (*)(CPtrList&,float,float,float,float,float,float))CStreaming::ProcessEntitiesInSectorList, PATCH_JUMP); - InjectHook(0x407DD0, (void (*)(CPtrList&))CStreaming::ProcessEntitiesInSectorList, PATCH_JUMP); - - InjectHook(0x407070, CStreaming::DeleteFarAwayRwObjects, PATCH_JUMP); - InjectHook(0x407390, CStreaming::DeleteAllRwObjects, PATCH_JUMP); - InjectHook(0x407400, CStreaming::DeleteRwObjectsAfterDeath, PATCH_JUMP); - InjectHook(0x408A60, CStreaming::DeleteRwObjectsBehindCamera, PATCH_JUMP); - InjectHook(0x407560, CStreaming::DeleteRwObjectsInSectorList, PATCH_JUMP); - InjectHook(0x4075A0, CStreaming::DeleteRwObjectsInOverlapSectorList, PATCH_JUMP); - InjectHook(0x409340, CStreaming::DeleteRwObjectsBehindCameraInSectorList, PATCH_JUMP); - InjectHook(0x4093C0, CStreaming::DeleteRwObjectsNotInFrustumInSectorList, PATCH_JUMP); - InjectHook(0x409B70, CStreaming::MakeSpaceFor, PATCH_JUMP); - InjectHook(0x40A6D0, CStreaming::LoadScene, PATCH_JUMP); - - InjectHook(0x40B210, CStreaming::MemoryCardSave, PATCH_JUMP); - InjectHook(0x40B250, CStreaming::MemoryCardLoad, PATCH_JUMP); - - InjectHook(0x4063E0, &CStreamingInfo::GetCdPosnAndSize, PATCH_JUMP); - InjectHook(0x406410, &CStreamingInfo::SetCdPosnAndSize, PATCH_JUMP); - InjectHook(0x4063D0, &CStreamingInfo::GetCdSize, PATCH_JUMP); - InjectHook(0x406380, &CStreamingInfo::AddToList, PATCH_JUMP); - InjectHook(0x4063A0, &CStreamingInfo::RemoveFromList, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/SurfaceTable.cpp b/src/core/SurfaceTable.cpp index 85572fbd..7212fc65 100644 --- a/src/core/SurfaceTable.cpp +++ b/src/core/SurfaceTable.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "FileMgr.h" #include "Weather.h" @@ -141,10 +141,3 @@ CSurfaceTable::GetAdhesiveLimit(CColPoint &colpoint) { return ms_aAdhesiveLimitTable[GetAdhesionGroup(colpoint.surfaceB)][GetAdhesionGroup(colpoint.surfaceA)]; } - -STARTPATCHES - InjectHook(0x4AB8F0, CSurfaceTable::Initialise, PATCH_JUMP); - InjectHook(0x4ABA60, CSurfaceTable::GetAdhesionGroup, PATCH_JUMP); - InjectHook(0x4ABAA0, CSurfaceTable::GetWetMultiplier, PATCH_JUMP); - InjectHook(0x4ABA30, CSurfaceTable::GetAdhesiveLimit, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp index 05b272ab..79d6252b 100644 --- a/src/core/TempColModels.cpp +++ b/src/core/TempColModels.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "TempColModels.h" #include "SurfaceTable.h" @@ -287,7 +287,3 @@ CTempColModels::Initialise(void) #undef SET_COLMODEL_SPHERES } - -STARTPATCHES - InjectHook(0x412160, CTempColModels::Initialise, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index 68b31e6f..ebd79695 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -1,6 +1,6 @@ #include #include "common.h" -#include "patcher.h" + #include "DMAudio.h" #include "Record.h" #include "Timer.h" @@ -225,18 +225,3 @@ uint32 CTimer::GetCyclesPerFrame() return 20; } -#if 1 -STARTPATCHES - InjectHook(0x4ACE60, CTimer::Initialise, PATCH_JUMP); - InjectHook(0x4ACF60, CTimer::Shutdown, PATCH_JUMP); - InjectHook(0x4ACF70, CTimer::Update, PATCH_JUMP); - InjectHook(0x4AD310, CTimer::Suspend, PATCH_JUMP); - InjectHook(0x4AD370, CTimer::Resume, PATCH_JUMP); - InjectHook(0x4AD3F0, CTimer::GetCyclesPerMillisecond, PATCH_JUMP); - InjectHook(0x4AD410, CTimer::GetCurrentTimeInCycles, PATCH_JUMP); - InjectHook(0x4AD450, CTimer::GetIsSlowMotionActive, PATCH_JUMP); - InjectHook(0x4AD480, CTimer::Stop, PATCH_JUMP); - InjectHook(0x4AD490, CTimer::StartUserPause, PATCH_JUMP); - InjectHook(0x4AD4A0, CTimer::EndUserPause, PATCH_JUMP); -ENDPATCHES -#endif diff --git a/src/core/User.cpp b/src/core/User.cpp index a1a69b2d..36f07cbd 100644 --- a/src/core/User.cpp +++ b/src/core/User.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Hud.h" #include "PlayerPed.h" @@ -120,16 +120,3 @@ CUserDisplay::Process() Pager.Process(); CurrentVehicle.Process(); } - -STARTPATCHES - InjectHook(0x4AD4C0, &CPlaceName::Init, PATCH_JUMP); - InjectHook(0x4AD4E0, &CPlaceName::Process, PATCH_JUMP); - InjectHook(0x4AD5B0, &CPlaceName::Display, PATCH_JUMP); - - InjectHook(0x4AD5F0, &CCurrentVehicle::Init, PATCH_JUMP); - InjectHook(0x4AD600, &CCurrentVehicle::Process, PATCH_JUMP); - InjectHook(0x4AD630, &CCurrentVehicle::Display, PATCH_JUMP); - - InjectHook(0x4AD660, &CUserDisplay::Init, PATCH_JUMP); - InjectHook(0x4AD690, &CUserDisplay::Process, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp index 1911ae59..ce7d217e 100644 --- a/src/core/Wanted.cpp +++ b/src/core/Wanted.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Pools.h" #include "ModelIndices.h" #include "Timer.h" @@ -456,25 +456,3 @@ CWanted::UpdateCrimesQ(void) } } } - -STARTPATCHES - InjectHook(0x4AD6E0, &CWanted::Initialise, PATCH_JUMP); - InjectHook(0x4AD790, &CWanted::Reset, PATCH_JUMP); - InjectHook(0x4AD7B0, &CWanted::Update, PATCH_JUMP); - InjectHook(0x4AD900, &CWanted::UpdateWantedLevel, PATCH_JUMP); - InjectHook(0x4AD9F0, &CWanted::RegisterCrime, PATCH_JUMP); - InjectHook(0x4ADA10, &CWanted::RegisterCrime_Immediately, PATCH_JUMP); - InjectHook(0x4ADA50, &CWanted::SetWantedLevel, PATCH_JUMP); - InjectHook(0x4ADAC0, &CWanted::SetWantedLevelNoDrop, PATCH_JUMP); - InjectHook(0x4ADAE0, &CWanted::SetMaximumWantedLevel, PATCH_JUMP); - InjectHook(0x4ADBA0, &CWanted::AreSwatRequired, PATCH_JUMP); - InjectHook(0x4ADBC0, &CWanted::AreFbiRequired, PATCH_JUMP); - InjectHook(0x4ADBE0, &CWanted::AreArmyRequired, PATCH_JUMP); - InjectHook(0x4ADC00, &CWanted::NumOfHelisRequired, PATCH_JUMP); - InjectHook(0x4ADC40, &CWanted::ResetPolicePursuit, PATCH_JUMP); - InjectHook(0x4ADD00, &CWanted::WorkOutPolicePresence, PATCH_JUMP); - InjectHook(0x4ADF20, &CWanted::ClearQdCrimes, PATCH_JUMP); - InjectHook(0x4ADFD0, &CWanted::AddCrimeToQ, PATCH_JUMP); - InjectHook(0x4AE090, &CWanted::UpdateCrimesQ, PATCH_JUMP); - InjectHook(0x4AE110, &CWanted::ReportCrimeNow, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/World.cpp b/src/core/World.cpp index c9e3c11f..eacb3404 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -27,28 +27,28 @@ #include "Vehicle.h" #include "WaterLevel.h" #include "common.h" -#include "patcher.h" + #define OBJECT_REPOSITION_OFFSET_Z 2.0f CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; -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; +CPtrList CWorld::ms_bigBuildingsList[4];// = (CPtrList*)0x6FAB60; +CPtrList CWorld::ms_listMovingEntityPtrs;// = *(CPtrList*)0x8F433C; +CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X];// = (CSector (*)[NUMSECTORS_Y])0x665608; +uint16 CWorld::ms_nCurrentScanCode;// = *(uint16*)0x95CC64; -uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61; +uint8 CWorld::PlayerInFocus;// = *(uint8 *)0x95CD61; CPlayerInfo CWorld::Players[NUMPLAYERS]; -bool &CWorld::bNoMoreCollisionTorque = *(bool *)0x95CDCC; -CEntity *&CWorld::pIgnoreEntity = *(CEntity **)0x8F6494; -bool &CWorld::bIncludeDeadPeds = *(bool *)0x95CD8F; -bool &CWorld::bSecondShift = *(bool *)0x95CD54; -bool &CWorld::bForceProcessControl = *(bool *)0x95CD6C; -bool &CWorld::bProcessCutsceneOnly = *(bool *)0x95CD8B; +bool CWorld::bNoMoreCollisionTorque;// = *(bool*)0x95CDCC; +CEntity *CWorld::pIgnoreEntity;// = *(CEntity**)0x8F6494; +bool CWorld::bIncludeDeadPeds;// = *(bool*)0x95CD8F; +bool CWorld::bSecondShift;// = *(bool*)0x95CD54; +bool CWorld::bForceProcessControl;// = *(bool*)0x95CD6C; +bool CWorld::bProcessCutsceneOnly;// = *(bool*)0x95CD8B; -bool &CWorld::bDoingCarCollisions = *(bool *)0x95CD8C; -bool &CWorld::bIncludeCarTyres = *(bool *)0x95CDAA; +bool CWorld::bDoingCarCollisions;// = *(bool*)0x95CD8C; +bool CWorld::bIncludeCarTyres;// = *(bool*)0x95CDAA; void CWorld::Initialise() @@ -2215,32 +2215,3 @@ CWorld::UseDetonator(CEntity *pEntity) } } } - -STARTPATCHES - InjectHook(0x4AE930, CWorld::Add, PATCH_JUMP); - InjectHook(0x4AE9D0, CWorld::Remove, PATCH_JUMP); - InjectHook(0x4B1F60, CWorld::ClearScanCodes, PATCH_JUMP); - InjectHook(0x4AF970, CWorld::ProcessLineOfSight, PATCH_JUMP); - InjectHook(0x4B0A80, CWorld::ProcessLineOfSightSector, PATCH_JUMP); - InjectHook(0x4B0C70, CWorld::ProcessLineOfSightSectorList, PATCH_JUMP); - InjectHook(0x4B0DE0, CWorld::ProcessVerticalLine, PATCH_JUMP); - InjectHook(0x4B0EF0, CWorld::ProcessVerticalLineSector, PATCH_JUMP); - InjectHook(0x4B1090, CWorld::ProcessVerticalLineSectorList, PATCH_JUMP); - InjectHook(0x4AEAA0, CWorld::GetIsLineOfSightClear, PATCH_JUMP); - InjectHook(0x4B2000, CWorld::GetIsLineOfSightSectorClear, PATCH_JUMP); - InjectHook(0x4B2160, CWorld::GetIsLineOfSightSectorListClear, PATCH_JUMP); - - InjectHook(0x4B2200, CWorld::FindObjectsInRange, PATCH_JUMP); - InjectHook(0x4B2540, CWorld::FindObjectsInRangeSectorList, PATCH_JUMP); - InjectHook(0x4B4AC0, CWorld::TestSphereAgainstSectorList, PATCH_JUMP); - InjectHook(0x4B4710, CWorld::TestSphereAgainstWorld, PATCH_JUMP); - InjectHook(0x4B3A80, CWorld::FindGroundZForCoord, PATCH_JUMP); - InjectHook(0x4B3AE0, CWorld::FindGroundZFor3DCoord, PATCH_JUMP); - InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP); - - InjectHook(0x4B5BC0, CWorld::StopAllLawEnforcersInTheirTracks, PATCH_JUMP); - InjectHook(0x4B53F0, CWorld::SetAllCarsCanBeDamaged, PATCH_JUMP); - InjectHook(0x4B5460, CWorld::ExtinguishAllCarFiresInArea, PATCH_JUMP); - - InjectHook(0x4B1A60, CWorld::Process, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/World.h b/src/core/World.h index a1e2acfd..25c76531 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -54,22 +54,22 @@ struct CStoredCollPoly; class CWorld { - static CPtrList *ms_bigBuildingsList; // [4]; - static CPtrList &ms_listMovingEntityPtrs; - static CSector (*ms_aSectors)[NUMSECTORS_X]; // [NUMSECTORS_Y][NUMSECTORS_X]; - static uint16 &ms_nCurrentScanCode; + static CPtrList ms_bigBuildingsList[4]; + static CPtrList ms_listMovingEntityPtrs; + static CSector ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X]; + static uint16 ms_nCurrentScanCode; public: - static uint8 &PlayerInFocus; + static uint8 PlayerInFocus; static CPlayerInfo Players[NUMPLAYERS]; - static CEntity *&pIgnoreEntity; - static bool &bIncludeDeadPeds; - static bool &bNoMoreCollisionTorque; - static bool &bSecondShift; - static bool &bForceProcessControl; - static bool &bProcessCutsceneOnly; - static bool &bDoingCarCollisions; - static bool &bIncludeCarTyres; + static CEntity *pIgnoreEntity; + static bool bIncludeDeadPeds; + static bool bNoMoreCollisionTorque; + static bool bSecondShift; + static bool bForceProcessControl; + static bool bProcessCutsceneOnly; + static bool bDoingCarCollisions; + static bool bIncludeCarTyres; static void Remove(CEntity *entity); static void Add(CEntity *entity); diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp index 4cdd283e..d17a33d4 100644 --- a/src/core/ZoneCull.cpp +++ b/src/core/ZoneCull.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Building.h" #include "Treadable.h" #include "Train.h" @@ -562,17 +562,3 @@ CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set) } return false; } - -STARTPATCHES - InjectHook(0x524BC0, &CCullZones::Init, PATCH_JUMP); - InjectHook(0x524EC0, &CCullZones::ResolveVisibilities, PATCH_JUMP); - InjectHook(0x524F80, &CCullZones::Update, PATCH_JUMP); - InjectHook(0x525370, &CCullZones::AddCullZone, PATCH_JUMP); - InjectHook(0x5250D0, &CCullZones::ForceCullZoneCoors, PATCH_JUMP); - InjectHook(0x525130, &CCullZones::FindCullZoneForCoors, PATCH_JUMP); - InjectHook(0x5251C0, &CCullZones::FindAttributesForCoors, PATCH_JUMP); - InjectHook(0x525290, &CCullZones::FindZoneWithStairsAttributeForPlayer, PATCH_JUMP); - - InjectHook(0x525610, &CCullZone::DoStuffLeavingZone, PATCH_JUMP); - InjectHook(0x525810, &CCullZone::DoStuffEnteringZone, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 39d4c3b5..6375de1c 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include #include "Zones.h" @@ -840,36 +840,3 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 length) TotalNumberOfMapZones = *(uint16*)(buffer); NumberOfAudioZones = *(uint16*)(buffer+2); } - - -STARTPATCHES - InjectHook(0x4B5DD0, &CZone::GetTranslatedName, PATCH_JUMP); - InjectHook(0x4B5DE0, CTheZones::Init, PATCH_JUMP); - InjectHook(0x4B61D0, CTheZones::Update, PATCH_JUMP); - InjectHook(0x4B6210, CTheZones::CreateZone, PATCH_JUMP); - InjectHook(0x4B6380, CTheZones::CreateMapZone, PATCH_JUMP); - InjectHook(0x4B64C0, CTheZones::PostZoneCreation, PATCH_JUMP); - InjectHook(0x4B6500, CTheZones::InsertZoneIntoZoneHierarchy, PATCH_JUMP); - InjectHook(0x4B6530, CTheZones::InsertZoneIntoZoneHierRecursive, PATCH_JUMP); - InjectHook(0x4B65F0, CTheZones::ZoneIsEntirelyContainedWithinOtherZone, PATCH_JUMP); - InjectHook(0x4B6710, CTheZones::PointLiesWithinZone, PATCH_JUMP); - InjectHook(0x4B6910, CTheZones::GetLevelFromPosition, PATCH_JUMP); - InjectHook(0x4B69B0, CTheZones::FindSmallestZonePosition, PATCH_JUMP); - InjectHook(0x4B6790, CTheZones::FindSmallestZonePositionType, PATCH_JUMP); - InjectHook(0x4B6890, CTheZones::FindSmallestZonePositionILN, PATCH_JUMP); - InjectHook(0x4B6800, CTheZones::FindZoneByLabelAndReturnIndex, PATCH_JUMP); - InjectHook(0x4B6FA0, CTheZones::GetZone, PATCH_JUMP); - InjectHook(0x4B84F0, CTheZones::GetPointerForZoneIndex, PATCH_JUMP); - InjectHook(0x4B6A10, CTheZones::GetZoneInfo, PATCH_JUMP); - InjectHook(0x4B6FB0, CTheZones::GetZoneInfoForTimeOfDay, PATCH_JUMP); - InjectHook(0x4B6A50, CTheZones::SetZoneCarInfo, PATCH_JUMP); - InjectHook(0x4B6DC0, CTheZones::SetZonePedInfo, PATCH_JUMP); - InjectHook(0x4B6EB0, CTheZones::SetCarDensity, PATCH_JUMP); - InjectHook(0x4B6F00, CTheZones::SetPedDensity, PATCH_JUMP); - InjectHook(0x4B6F50, CTheZones::SetPedGroup, PATCH_JUMP); - InjectHook(0x4B83E0, CTheZones::FindAudioZone, PATCH_JUMP); - InjectHook(0x4B8430, CTheZones::FindZoneForPoint, PATCH_JUMP); - InjectHook(0x4B8340, CTheZones::AddZoneToAudioZoneArray, PATCH_JUMP); - InjectHook(0x4B8510, CTheZones::SaveAllZones, PATCH_JUMP); - InjectHook(0x4B8950, CTheZones::LoadAllZones, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/main.cpp b/src/core/main.cpp index 1b46d453..d5d4065d 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -2,7 +2,7 @@ #include "rpmatfx.h" #include "rphanim.h" #include "rpskin.h" -#include "patcher.h" + #include "main.h" #include "CdStream.h" #include "General.h" @@ -1838,28 +1838,3 @@ main(int argc, char *argv[]) return 0; } - -STARTPATCHES - InjectHook(0x48E480, Idle, PATCH_JUMP); - InjectHook(0x48E700, FrontendIdle, PATCH_JUMP); - - InjectHook(0x48CF10, DoRWStuffStartOfFrame, PATCH_JUMP); - InjectHook(0x48D040, DoRWStuffStartOfFrame_Horizon, PATCH_JUMP); - InjectHook(0x48E030, RenderScene, PATCH_JUMP); - InjectHook(0x48E080, RenderDebugShit, PATCH_JUMP); - InjectHook(0x48E090, RenderEffects, PATCH_JUMP); - InjectHook(0x48E0E0, Render2dStuff, PATCH_JUMP); - InjectHook(0x48E450, RenderMenus, PATCH_JUMP); - InjectHook(0x48D120, DoFade, PATCH_JUMP); - InjectHook(0x48E470, Render2dStuffAfterFade, PATCH_JUMP); - - InjectHook(0x48D550, LoadSplash, PATCH_JUMP); - InjectHook(0x48D670, DestroySplashScreen, PATCH_JUMP); - InjectHook(0x48D770, LoadingScreen, PATCH_JUMP); - InjectHook(0x48D760, ResetLoadingScreenBar, PATCH_JUMP); - - InjectHook(0x48D470, PluginAttach, PATCH_JUMP); - InjectHook(0x48D520, Initialise3D, PATCH_JUMP); - InjectHook(0x48D540, Terminate3D, PATCH_JUMP); - InjectHook(0x48E800, AppEventHandler, PATCH_JUMP); -ENDPATCHES diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 2046a7f9..e5f42696 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -29,18 +29,12 @@ #include -#ifndef RWLIBS -void **rwengine = *(void***)0x5A10E1; -#else +#ifdef RWLIBS extern "C" int vsprintf(char* const _Buffer, char const* const _Format, va_list _ArgList); #endif DebugMenuAPI gDebugMenuAPI; -STARTPATCHES - InjectHook(0x5A07E0, (void (*)(void*)) &operator delete, PATCH_JUMP); - InjectHook(0x5A0690, (void* (*)(size_t)) &operator new, PATCH_JUMP); -ENDPATCHES #ifdef USE_PS2_RAND unsigned __int64 myrand_seed = 1; @@ -387,7 +381,7 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop); extern bool PrintDebugCode; - extern int16 &DebugCamMode; + extern int16 DebugCamMode; DebugMenuAddVarBool8("Cam", "Use mouse Cam", (int8*)&CCamera::m_bUseMouse3rdPerson, nil); #ifdef FREE_CAM DebugMenuAddVarBool8("Cam", "Free Cam", (int8*)&CCamera::bFreeCam, nil); @@ -494,37 +488,3 @@ void re3_trace(const char *filename, unsigned int lineno, const char *func, cons #ifdef VALIDATE_SAVE_SIZE int32 _saveBufCount; #endif - -void -patch() -{ - StaticPatcher::Apply(); - -// Patch(0x46BC61+6, 1.0f); // car distance - InjectHook(0x59E460, printf, PATCH_JUMP); - InjectHook(0x475E00, printf, PATCH_JUMP); // _Error - - -// InterceptCall(&open_script_orig, open_script, 0x438869); - -// InterceptCall(&RsEventHandler_orig, delayedPatches10, 0x58275E); -} - -BOOL WINAPI -DllMain(HINSTANCE hInst, DWORD reason, LPVOID) -{ - if(reason == DLL_PROCESS_ATTACH){ - - AllocConsole(); - freopen("CONIN$", "r", stdin); - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); - - if (*(DWORD*)0x5C1E75 == 0xB85548EC) // 1.0 - patch(); - else - return FALSE; - } - - return TRUE; -} diff --git a/src/entities/Building.cpp b/src/entities/Building.cpp index 7813c87f..aad2d402 100644 --- a/src/entities/Building.cpp +++ b/src/entities/Building.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Building.h" #include "Streaming.h" #include "Pools.h" @@ -20,18 +20,3 @@ CBuilding::ReplaceWithNewModel(int32 id) if(m_level == LEVEL_NONE || m_level == CGame::currLevel) CStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE); } - -#include - -class CBuilding_ : public CBuilding -{ -public: - CBuilding *ctor(void) { return ::new (this) CBuilding(); } - void dtor(void) { CBuilding::~CBuilding(); } -}; - -STARTPATCHES - InjectHook(0x4057D0, &CBuilding_::ctor, PATCH_JUMP); - InjectHook(0x405800, &CBuilding_::dtor, PATCH_JUMP); - InjectHook(0x405850, &CBuilding::ReplaceWithNewModel, PATCH_JUMP); -ENDPATCHES diff --git a/src/entities/Dummy.cpp b/src/entities/Dummy.cpp index 176e5682..8a4bfd5f 100644 --- a/src/entities/Dummy.cpp +++ b/src/entities/Dummy.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Pools.h" #include "World.h" #include "Dummy.h" @@ -50,17 +50,3 @@ CDummy::Remove(void) m_entryInfoList.DeleteNode(node); } } - -class CDummy_ : public CDummy -{ -public: - void Add_(void) { CDummy::Add(); } - void Remove_(void) { CDummy::Remove(); } - void dtor(void) { CDummy::~CDummy(); } -}; - -STARTPATCHES - InjectHook(0x473810, &CDummy_::dtor, PATCH_JUMP); - InjectHook(0x473860, &CDummy_::Add_, PATCH_JUMP); - InjectHook(0x473AD0, &CDummy_::Remove_, PATCH_JUMP); -ENDPATCHES diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 0efee4e7..3dce53da 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "ModelIndices.h" #include "Timer.h" @@ -874,56 +874,3 @@ CEntity::AddSteamsFromGround(CPtrList& list) pNode = pNode->next; } } - -#include - -class CEntity_ : public CEntity -{ -public: - CEntity *ctor(void) { return ::new (this) CEntity(); } - void dtor(void) { this->CEntity::~CEntity(); } - void Add_(void) { CEntity::Add(); } - void Remove_(void) { CEntity::Remove(); } - void SetModelIndex_(uint32 i) { CEntity::SetModelIndex(i); } - void CreateRwObject_(void) { CEntity::CreateRwObject(); } - void DeleteRwObject_(void) { CEntity::DeleteRwObject(); } - CRect GetBoundRect_(void) { return CEntity::GetBoundRect(); } - void PreRender_(void) { CEntity::PreRender(); } - void Render_(void) { CEntity::Render(); } - bool SetupLighting_(void) { return CEntity::SetupLighting(); } -}; - -STARTPATCHES - InjectHook(0x473C30, &CEntity_::ctor, PATCH_JUMP); - InjectHook(0x473E40, &CEntity_::dtor, PATCH_JUMP); - InjectHook(0x473E70, &CEntity_::SetModelIndex_, PATCH_JUMP); - InjectHook(0x475080, &CEntity_::Add_, PATCH_JUMP); - InjectHook(0x475310, &CEntity_::Remove_, PATCH_JUMP); - InjectHook(0x473EA0, &CEntity_::CreateRwObject_, PATCH_JUMP); - InjectHook(0x473F90, &CEntity_::DeleteRwObject_, PATCH_JUMP); - InjectHook(0x474000, &CEntity_::GetBoundRect_, PATCH_JUMP); - InjectHook(0x474350, &CEntity_::PreRender_, PATCH_JUMP); - InjectHook(0x474BD0, &CEntity_::Render_, PATCH_JUMP); - InjectHook(0x4A7C60, &CEntity_::SetupLighting_, PATCH_JUMP); - - InjectHook(0x4742C0, (void (CEntity::*)(CVector&))&CEntity::GetBoundCentre, PATCH_JUMP); - InjectHook(0x474310, &CEntity::GetBoundRadius, PATCH_JUMP); - InjectHook(0x474C10, &CEntity::GetIsTouching, PATCH_JUMP); - InjectHook(0x474CC0, &CEntity::GetIsOnScreen, PATCH_JUMP); - InjectHook(0x474D20, &CEntity::GetIsOnScreenComplex, PATCH_JUMP); - InjectHook(0x474CA0, &CEntity::IsVisible, PATCH_JUMP); - InjectHook(0x474330, &CEntity::UpdateRwFrame, PATCH_JUMP); - InjectHook(0x4755E0, &CEntity::SetupBigBuilding, PATCH_JUMP); - InjectHook(0x4A7480, &CEntity::RegisterReference, PATCH_JUMP); - InjectHook(0x4A74E0, &CEntity::ResolveReferences, PATCH_JUMP); - InjectHook(0x4A7530, &CEntity::PruneReferences, PATCH_JUMP); - - InjectHook(0x473F10, &CEntity::AttachToRwObject, PATCH_JUMP); - InjectHook(0x473F60, &CEntity::DetachFromRwObject, PATCH_JUMP); - - InjectHook(0x475A20, &CEntity::PreRenderForGlassWindow, PATCH_JUMP); - InjectHook(0x50CE40, (void (CEntity::*)(CVector*))& CEntity::AddSteamsFromGround, PATCH_JUMP); - InjectHook(0x475670, &CEntity::ModifyMatrixForTreeInWind, PATCH_JUMP); - InjectHook(0x475830, &CEntity::ModifyMatrixForBannerInWind, PATCH_JUMP); - InjectHook(0x4FA530, &CEntity::ProcessLightsForEntity, PATCH_JUMP); -ENDPATCHES diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index bbdf68f5..445cd83f 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "World.h" #include "Timer.h" #include "ModelIndices.h" @@ -1933,58 +1933,3 @@ CPhysical::ProcessCollision(void) bIsInSafePosition = true; RemoveAndAdd(); } - -class CPhysical_ : public CPhysical -{ -public: - void dtor(void) { CPhysical::~CPhysical(); } - void Add_(void) { CPhysical::Add(); } - void Remove_(void) { CPhysical::Remove(); } - CRect GetBoundRect_(void) { return CPhysical::GetBoundRect(); } - void ProcessControl_(void) { CPhysical::ProcessControl(); } - void ProcessShift_(void) { CPhysical::ProcessShift(); } - void ProcessCollision_(void) { CPhysical::ProcessCollision(); } - int32 ProcessEntityCollision_(CEntity *ent, CColPoint *point) { return CPhysical::ProcessEntityCollision(ent, point); } -}; - -STARTPATCHES - InjectHook(0x495130, &CPhysical_::dtor, PATCH_JUMP); - InjectHook(0x4951F0, &CPhysical_::Add_, PATCH_JUMP); - InjectHook(0x4954B0, &CPhysical_::Remove_, PATCH_JUMP); - InjectHook(0x495540, &CPhysical_::RemoveAndAdd, PATCH_JUMP); - InjectHook(0x495F10, &CPhysical_::ProcessControl_, PATCH_JUMP); - InjectHook(0x496F10, &CPhysical_::ProcessShift_, PATCH_JUMP); - InjectHook(0x4961A0, &CPhysical_::ProcessCollision_, PATCH_JUMP); - InjectHook(0x49F790, &CPhysical_::ProcessEntityCollision_, PATCH_JUMP); - InjectHook(0x4958F0, &CPhysical::AddToMovingList, PATCH_JUMP); - InjectHook(0x495940, &CPhysical::RemoveFromMovingList, PATCH_JUMP); - InjectHook(0x497180, &CPhysical::AddCollisionRecord, PATCH_JUMP); - InjectHook(0x4970C0, &CPhysical::AddCollisionRecord_Treadable, PATCH_JUMP); - InjectHook(0x497240, &CPhysical::GetHasCollidedWith, PATCH_JUMP); - InjectHook(0x49F820, &CPhysical::RemoveRefsToEntity, PATCH_JUMP); - InjectHook(0x49F890, &CPhysical::PlacePhysicalRelativeToOtherPhysical, PATCH_JUMP); - -#define F3 float, float, float - InjectHook(0x495B10, &CPhysical::ApplyMoveSpeed, PATCH_JUMP); - InjectHook(0x497280, &CPhysical::ApplyTurnSpeed, PATCH_JUMP); - InjectHook(0x4959A0, (void (CPhysical::*)(F3))&CPhysical::ApplyMoveForce, PATCH_JUMP); - InjectHook(0x495A10, (void (CPhysical::*)(F3, F3))&CPhysical::ApplyTurnForce, PATCH_JUMP); - InjectHook(0x495D90, (void (CPhysical::*)(F3))&CPhysical::ApplyFrictionMoveForce, PATCH_JUMP); - InjectHook(0x495E10, (void (CPhysical::*)(F3, F3))&CPhysical::ApplyFrictionTurnForce, PATCH_JUMP); - InjectHook(0x499890, &CPhysical::ApplySpringCollision, PATCH_JUMP); - InjectHook(0x499990, &CPhysical::ApplySpringDampening, PATCH_JUMP); - InjectHook(0x495B50, &CPhysical::ApplyGravity, PATCH_JUMP); - InjectHook(0x495B80, (void (CPhysical::*)(void))&CPhysical::ApplyFriction, PATCH_JUMP); - InjectHook(0x495C20, &CPhysical::ApplyAirResistance, PATCH_JUMP); - - InjectHook(0x4973A0, &CPhysical::ApplyCollision, PATCH_JUMP); - InjectHook(0x4992A0, &CPhysical::ApplyCollisionAlt, PATCH_JUMP); - InjectHook(0x499BE0, (bool (CPhysical::*)(float, CColPoint&))&CPhysical::ApplyFriction, PATCH_JUMP); - InjectHook(0x49A180, (bool (CPhysical::*)(CPhysical*, float, CColPoint&))&CPhysical::ApplyFriction, PATCH_JUMP); - - InjectHook(0x49DA10, &CPhysical::ProcessShiftSectorList, PATCH_JUMP); - InjectHook(0x49E790, &CPhysical::ProcessCollisionSectorList_SimpleCar, PATCH_JUMP); - InjectHook(0x49B620, &CPhysical::ProcessCollisionSectorList, PATCH_JUMP); - InjectHook(0x496E50, &CPhysical::CheckCollision, PATCH_JUMP); - InjectHook(0x496EB0, &CPhysical::CheckCollision_SimpleCar, PATCH_JUMP); -ENDPATCHES diff --git a/src/entities/Treadable.cpp b/src/entities/Treadable.cpp index ea949f00..00abbe13 100644 --- a/src/entities/Treadable.cpp +++ b/src/entities/Treadable.cpp @@ -1,18 +1,8 @@ #include "common.h" -#include "patcher.h" + #include "rpworld.h" #include "Treadable.h" #include "Pools.h" void *CTreadable::operator new(size_t sz) { return CPools::GetTreadablePool()->New(); } void CTreadable::operator delete(void *p, size_t sz) { CPools::GetTreadablePool()->Delete((CTreadable*)p); } - -class CTreadable_ : public CTreadable -{ -public: - void dtor(void) { CTreadable::~CTreadable(); } -}; - -STARTPATCHES - InjectHook(0x405A10, &CTreadable_::dtor, PATCH_JUMP); -ENDPATCHES diff --git a/src/math/math.cpp b/src/math/math.cpp index 4f74fac9..e11d048c 100644 --- a/src/math/math.cpp +++ b/src/math/math.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Quaternion.h" // TODO: move more stuff into here @@ -191,8 +191,3 @@ CQuaternion::Get(RwMatrix *matrix) matrix->up.z = y_2z + w_2x; matrix->at.z = 1.0f - (x_2x + y_2y); } - -STARTPATCHES - InjectHook(0x4BA1C0, &CQuaternion::Slerp, PATCH_JUMP); - InjectHook(0x4BA0D0, &CQuaternion::Get, PATCH_JUMP); -ENDPATCHES diff --git a/src/modelinfo/BaseModelInfo.cpp b/src/modelinfo/BaseModelInfo.cpp index 830ead51..e8d2601f 100644 --- a/src/modelinfo/BaseModelInfo.cpp +++ b/src/modelinfo/BaseModelInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "templates.h" #include "TxdStore.h" #include "2dEffect.h" @@ -99,25 +99,3 @@ CBaseModelInfo::Get2dEffect(int n) else return nil; } - - -class CBaseModelInfo_ : public CBaseModelInfo -{ -public: - void Shutdown_(void) { CBaseModelInfo::Shutdown(); } -}; -STARTPATCHES - // can't easily replace ctor at 4F6A50 - InjectHook(0x4F6A90, &CBaseModelInfo_::Shutdown_, PATCH_JUMP); - - InjectHook(0x4F6AC0, &CBaseModelInfo::DeleteCollisionModel, PATCH_JUMP); - InjectHook(0x4F6B70, &CBaseModelInfo::ClearTexDictionary, PATCH_JUMP); - InjectHook(0x4F6BA0, &CBaseModelInfo::AddRef, PATCH_JUMP); - InjectHook(0x4F6BB0, &CBaseModelInfo::RemoveRef, PATCH_JUMP); - InjectHook(0x4F6B40, &CBaseModelInfo::SetTexDictionary, PATCH_JUMP); - InjectHook(0x4F6B80, &CBaseModelInfo::AddTexDictionaryRef, PATCH_JUMP); - InjectHook(0x4F6B90, &CBaseModelInfo::RemoveTexDictionaryRef, PATCH_JUMP); - InjectHook(0x4F6B20, &CBaseModelInfo::Add2dEffect, PATCH_JUMP); - InjectHook(0x4F6AF0, &CBaseModelInfo::Init2dEffects, PATCH_JUMP); - InjectHook(0x4F6B00, &CBaseModelInfo::Get2dEffect, PATCH_JUMP); -ENDPATCHES diff --git a/src/modelinfo/ClumpModelInfo.cpp b/src/modelinfo/ClumpModelInfo.cpp index c6a6d5d0..464bda61 100644 --- a/src/modelinfo/ClumpModelInfo.cpp +++ b/src/modelinfo/ClumpModelInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "NodeName.h" #include "VisibilityPlugins.h" @@ -138,30 +138,3 @@ CClumpModelInfo::GetFrameFromId(RpClump *clump, int32 id) RwFrameForAllChildren(RpClumpGetFrame(clump), FindFrameFromIdCB, &assoc); return assoc.frame; } - - -class CClumpModelInfo_ : public CClumpModelInfo -{ -public: - void DeleteRwObject_(void) { this->CClumpModelInfo::DeleteRwObject(); } - RwObject *CreateInstance_1(void) { return CClumpModelInfo::CreateInstance(); } - RwObject *CreateInstance_2(RwMatrix *m) { return CClumpModelInfo::CreateInstance(m); } - RwObject *GetRwObject_(void) { return CClumpModelInfo::GetRwObject(); } - void SetClump_(RpClump *clump) { CClumpModelInfo::SetClump(clump); } -}; - -STARTPATCHES - InjectHook(0x4F8800, &CClumpModelInfo_::DeleteRwObject_, PATCH_JUMP); - InjectHook(0x4F8920, &CClumpModelInfo_::CreateInstance_1, PATCH_JUMP); - InjectHook(0x4F88A0, &CClumpModelInfo_::CreateInstance_2, PATCH_JUMP); - InjectHook(0x50C1C0, &CClumpModelInfo_::GetRwObject_, PATCH_JUMP); - InjectHook(0x4F8830, &CClumpModelInfo_::SetClump_, PATCH_JUMP); - InjectHook(0x4F8940, &CClumpModelInfo::SetAtomicRendererCB, PATCH_JUMP); - InjectHook(0x4F8960, &CClumpModelInfo::FindFrameFromNameCB, PATCH_JUMP); - InjectHook(0x4F8A10, &CClumpModelInfo::FindFrameFromNameWithoutIdCB, PATCH_JUMP); - InjectHook(0x4F8AD0, &CClumpModelInfo::FindFrameFromIdCB, PATCH_JUMP); - InjectHook(0x4F8BB0, &CClumpModelInfo::SetFrameIds, PATCH_JUMP); - InjectHook(0x4F8B20, &CClumpModelInfo::FillFrameArrayCB, PATCH_JUMP); - InjectHook(0x4F8B90, &CClumpModelInfo::FillFrameArray, PATCH_JUMP); - InjectHook(0x4F8B50, &CClumpModelInfo::GetFrameFromId, PATCH_JUMP); -ENDPATCHES diff --git a/src/modelinfo/MloModelInfo.cpp b/src/modelinfo/MloModelInfo.cpp index 746d9db4..7535e6c5 100644 --- a/src/modelinfo/MloModelInfo.cpp +++ b/src/modelinfo/MloModelInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "VisibilityPlugins.h" #include "ModelInfo.h" diff --git a/src/modelinfo/ModelIndices.cpp b/src/modelinfo/ModelIndices.cpp index ec039a0b..9a6a74d0 100644 --- a/src/modelinfo/ModelIndices.cpp +++ b/src/modelinfo/ModelIndices.cpp @@ -1,9 +1,9 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "ModelIndices.h" -#define X(name, var, addr) int16 &var = *(int16*)addr; +#define X(name, var, addr) int16 var; MODELINDICES #undef X @@ -32,8 +32,3 @@ TestModelIndices(void) { ; } - -STARTPATCHES - InjectHook(0x48EB60, InitModelIndices, PATCH_JUMP); - InjectHook(0x48F030, MatchModelString, PATCH_JUMP); -ENDPATCHES diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index cc8399e7..8e117882 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -158,7 +158,7 @@ X("subplatform_sub", MI_SUBPLATFORM_SUB2, 0x5F5BC0) \ X("files", MI_FILES, 0x5F5BC4) -#define X(name, var, addr) extern int16 &var; +#define X(name, var, addr) extern int16 var; MODELINDICES #undef X diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp index 58124e53..c1ae692f 100644 --- a/src/modelinfo/ModelInfo.cpp +++ b/src/modelinfo/ModelInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "TempColModels.h" #include "ModelIndices.h" @@ -248,15 +248,3 @@ CModelInfo::ReInit2dEffects() ms_modelInfoPtrs[i]->Init2dEffects(); } } - -STARTPATCHES - InjectHook(0x50B310, CModelInfo::Initialise, PATCH_JUMP); - InjectHook(0x50B5B0, CModelInfo::ShutDown, PATCH_JUMP); - InjectHook(0x50B920, CModelInfo::AddSimpleModel, PATCH_JUMP); - InjectHook(0x50B9C0, CModelInfo::AddTimeModel, PATCH_JUMP); - InjectHook(0x50BA10, CModelInfo::AddClumpModel, PATCH_JUMP); - InjectHook(0x50BAD0, CModelInfo::AddPedModel, PATCH_JUMP); - InjectHook(0x50BA60, CModelInfo::AddVehicleModel, PATCH_JUMP); - InjectHook(0x50B860, (CBaseModelInfo *(*)(const char*, int*))CModelInfo::GetModelInfo, PATCH_JUMP); - InjectHook(0x50BBC0, CModelInfo::RemoveColModelsFromOtherLevels, PATCH_JUMP); -ENDPATCHES diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp index 015c6949..5c801a2b 100644 --- a/src/modelinfo/PedModelInfo.cpp +++ b/src/modelinfo/PedModelInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "Ped.h" #include "NodeName.h" @@ -229,17 +229,3 @@ CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame) return colmodel; } - -class CPedModelInfo_ : public CPedModelInfo -{ -public: - void DeleteRwObject_(void) { CPedModelInfo::DeleteRwObject(); } - void SetClump_(RpClump *clump) { CPedModelInfo::SetClump(clump); } -}; - -STARTPATCHES - InjectHook(0x510210, &CPedModelInfo_::SetClump_, PATCH_JUMP); - InjectHook(0x510280, &CPedModelInfo_::DeleteRwObject_, PATCH_JUMP); - InjectHook(0x510390, &CPedModelInfo::SetLowDetailClump, PATCH_JUMP); - InjectHook(0x5104D0, &CPedModelInfo::CreateHitColModel, PATCH_JUMP); -ENDPATCHES diff --git a/src/modelinfo/SimpleModelInfo.cpp b/src/modelinfo/SimpleModelInfo.cpp index f8742f1e..2fb2adeb 100644 --- a/src/modelinfo/SimpleModelInfo.cpp +++ b/src/modelinfo/SimpleModelInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "Camera.h" #include "ModelInfo.h" @@ -154,28 +154,3 @@ CSimpleModelInfo::SetupBigBuilding(void) m_lodDistances[2] = 100.0f; } } - -class CSimpleModelInfo_ : public CSimpleModelInfo -{ -public: - void DeleteRwObject_(void) { CSimpleModelInfo::DeleteRwObject(); } - RwObject *CreateInstance_1(void) { return CSimpleModelInfo::CreateInstance(); } - RwObject *CreateInstance_2(RwMatrix *m) { return CSimpleModelInfo::CreateInstance(m); } - RwObject *GetRwObject_(void) { return CSimpleModelInfo::GetRwObject(); } -}; - -STARTPATCHES - InjectHook(0x5179B0, &CSimpleModelInfo_::DeleteRwObject_, PATCH_JUMP); - InjectHook(0x517B60, &CSimpleModelInfo_::CreateInstance_1, PATCH_JUMP); - InjectHook(0x517AC0, &CSimpleModelInfo_::CreateInstance_2, PATCH_JUMP); - InjectHook(0x4A9BA0, &CSimpleModelInfo_::GetRwObject_, PATCH_JUMP); - InjectHook(0x517990, &CSimpleModelInfo::Init, PATCH_JUMP); - InjectHook(0x517C60, &CSimpleModelInfo::IncreaseAlpha, PATCH_JUMP); - InjectHook(0x517950, &CSimpleModelInfo::SetAtomic, PATCH_JUMP); - InjectHook(0x517AA0, &CSimpleModelInfo::SetLodDistances, PATCH_JUMP); - InjectHook(0x517A90, &CSimpleModelInfo::GetNearDistance, PATCH_JUMP); - InjectHook(0x517A60, &CSimpleModelInfo::GetLargestLodDistance, PATCH_JUMP); - InjectHook(0x517A00, &CSimpleModelInfo::GetAtomicFromDistance, PATCH_JUMP); - InjectHook(0x517C00, &CSimpleModelInfo::FindRelatedModel, PATCH_JUMP); - InjectHook(0x517B90, &CSimpleModelInfo::SetupBigBuilding, PATCH_JUMP); -ENDPATCHES diff --git a/src/modelinfo/TimeModelInfo.cpp b/src/modelinfo/TimeModelInfo.cpp index 3ab3e13a..fec3f6e5 100644 --- a/src/modelinfo/TimeModelInfo.cpp +++ b/src/modelinfo/TimeModelInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Camera.h" #include "ModelInfo.h" @@ -30,7 +30,3 @@ CTimeModelInfo::FindOtherTimeModel(void) } return nil; } - -STARTPATCHES - InjectHook(0x517C80, &CTimeModelInfo::FindOtherTimeModel, PATCH_JUMP); -ENDPATCHES diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp index fb9e0358..0c3a7720 100644 --- a/src/modelinfo/VehicleModelInfo.cpp +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -1,6 +1,6 @@ #include "common.h" #include -#include "patcher.h" + #include "RwHelper.h" #include "General.h" #include "NodeName.h" @@ -1104,65 +1104,3 @@ CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(int id) return n - 1; } - -class CVehicleModelInfo_ : public CVehicleModelInfo -{ -public: - void DeleteRwObject_(void) { CVehicleModelInfo::DeleteRwObject(); } - RwObject *CreateInstance_(void) { return CVehicleModelInfo::CreateInstance(); } - void SetClump_(RpClump *clump) { CVehicleModelInfo::SetClump(clump); } -}; - -STARTPATCHES - InjectHook(0x427820, &CVehicleModelInfo::SetComponentsToUse, PATCH_JUMP); - - InjectHook(0x51FDC0, &CVehicleModelInfo_::DeleteRwObject_, PATCH_JUMP); - InjectHook(0x51FCB0, &CVehicleModelInfo_::CreateInstance_, PATCH_JUMP); - InjectHook(0x51FC60, &CVehicleModelInfo_::SetClump_, PATCH_JUMP); - - InjectHook(0x51FE10, &CVehicleModelInfo::CollapseFramesCB, PATCH_JUMP); - InjectHook(0x51FE50, &CVehicleModelInfo::MoveObjectsCB, PATCH_JUMP); - InjectHook(0x51FE70, &CVehicleModelInfo::HideDamagedAtomicCB, PATCH_JUMP); - InjectHook(0x51FED0, &CVehicleModelInfo::HideAllComponentsAtomicCB, PATCH_JUMP); - InjectHook(0x51FEF0, &CVehicleModelInfo::HasAlphaMaterialCB, PATCH_JUMP); - - InjectHook(0x51FF10, &CVehicleModelInfo::SetAtomicRendererCB, PATCH_JUMP); - InjectHook(0x520030, &CVehicleModelInfo::SetAtomicRendererCB_BigVehicle, PATCH_JUMP); - InjectHook(0x520230, &CVehicleModelInfo::SetAtomicRendererCB_Train, PATCH_JUMP); - InjectHook(0x520120, &CVehicleModelInfo::SetAtomicRendererCB_Boat, PATCH_JUMP); - InjectHook(0x520210, &CVehicleModelInfo::SetAtomicRendererCB_Heli, PATCH_JUMP); - InjectHook(0x5202C0, &CVehicleModelInfo::SetAtomicRenderCallbacks, PATCH_JUMP); - - InjectHook(0x520340, &CVehicleModelInfo::SetAtomicFlagCB, PATCH_JUMP); - InjectHook(0x520360, &CVehicleModelInfo::ClearAtomicFlagCB, PATCH_JUMP); - - InjectHook(0x5204D0, &CVehicleModelInfo::PreprocessHierarchy, PATCH_JUMP); - InjectHook(0x5203C0, &CVehicleModelInfo::SetVehicleComponentFlags, PATCH_JUMP); - - InjectHook(0x520840, &CVehicleModelInfo::GetWheelPosn, PATCH_JUMP); - - InjectHook(0x520880, IsValidCompRule, PATCH_JUMP); - InjectHook(0x520990, CountCompsInRule, PATCH_JUMP); - InjectHook(0x5209C0, ChooseComponent, PATCH_JUMP); - InjectHook(0x5208C0, GetListOfComponentsNotUsedByRules, PATCH_JUMP); - InjectHook(0x520AB0, &CVehicleModelInfo::ChooseComponent, PATCH_JUMP); - InjectHook(0x520BE0, &CVehicleModelInfo::ChooseSecondComponent, PATCH_JUMP); - - InjectHook(0x520DC0, (RpAtomic *(*)(RpAtomic*, void*))CVehicleModelInfo::GetEditableMaterialListCB, PATCH_JUMP); - InjectHook(0x520D30, (RpMaterial *(*)(RpMaterial*, void*))CVehicleModelInfo::GetEditableMaterialListCB, PATCH_JUMP); - InjectHook(0x520DE0, &CVehicleModelInfo::FindEditableMaterialList, PATCH_JUMP); - InjectHook(0x520E70, &CVehicleModelInfo::SetVehicleColour, PATCH_JUMP); - InjectHook(0x520FD0, &CVehicleModelInfo::ChooseVehicleColour, PATCH_JUMP); - InjectHook(0x5210A0, &CVehicleModelInfo::AvoidSameVehicleColour, PATCH_JUMP); - InjectHook(0x521260, &CVehicleModelInfo::LoadVehicleColours, PATCH_JUMP); - InjectHook(0x521650, &CVehicleModelInfo::DeleteVehicleColourTextures, PATCH_JUMP); - - InjectHook(0x5219D0, &CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors, PATCH_JUMP); - - InjectHook(0x521820, (RpAtomic *(*)(RpAtomic*, void*))CVehicleModelInfo::SetEnvironmentMapCB, PATCH_JUMP); - InjectHook(0x5217A0, (RpMaterial *(*)(RpMaterial*, void*))CVehicleModelInfo::SetEnvironmentMapCB, PATCH_JUMP); - InjectHook(0x521770, CVehicleModelInfo::HasSpecularMaterialCB, PATCH_JUMP); - InjectHook(0x521890, &CVehicleModelInfo::SetEnvironmentMap, PATCH_JUMP); - InjectHook(0x521680, CVehicleModelInfo::LoadEnvironmentMaps, PATCH_JUMP); - InjectHook(0x521720, CVehicleModelInfo::ShutdownEnvironmentMaps, PATCH_JUMP); -ENDPATCHES diff --git a/src/objects/CutsceneHead.cpp b/src/objects/CutsceneHead.cpp index a7722b8a..b716e17e 100644 --- a/src/objects/CutsceneHead.cpp +++ b/src/objects/CutsceneHead.cpp @@ -1,6 +1,6 @@ #include "common.h" #include -#include "patcher.h" + #include "main.h" #include "RwHelper.h" #include "RpAnimBlend.h" @@ -109,20 +109,3 @@ CCutsceneHead::PlayAnimation(const char *animName) RwStreamClose(stream, nil); } } - -class CCutsceneHead_ : public CCutsceneHead -{ -public: - void CreateRwObject_(void) { CCutsceneHead::CreateRwObject(); } - void DeleteRwObject_(void) { CCutsceneHead::DeleteRwObject(); } - void ProcessControl_(void) { CCutsceneHead::ProcessControl(); } - void Render_(void) { CCutsceneHead::Render(); } -}; - -STARTPATCHES - InjectHook(0x4BA650, &CCutsceneHead_::CreateRwObject_, PATCH_JUMP); - InjectHook(0x4BA690, &CCutsceneHead_::DeleteRwObject_, PATCH_JUMP); - InjectHook(0x4BA760, &CCutsceneHead_::ProcessControl_, PATCH_JUMP); - InjectHook(0x4BA800, &CCutsceneHead_::Render_, PATCH_JUMP); - InjectHook(0x4BA6A0, &CCutsceneHead::PlayAnimation, PATCH_JUMP); -ENDPATCHES diff --git a/src/objects/CutsceneObject.cpp b/src/objects/CutsceneObject.cpp index 2f667a5d..cee83848 100644 --- a/src/objects/CutsceneObject.cpp +++ b/src/objects/CutsceneObject.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Lights.h" #include "PointLights.h" @@ -88,25 +88,3 @@ CCutsceneObject::RemoveLighting(bool reset) { CRenderer::RemoveVehiclePedLights(this, reset); } - -class CCutsceneObject_ : public CCutsceneObject -{ -public: - void dtor(void) { this->CCutsceneObject::~CCutsceneObject(); } - void SetModelIndex_(uint32 id) { CCutsceneObject::SetModelIndex(id); } - void ProcessControl_(void) { CCutsceneObject::ProcessControl(); } - void PreRender_(void) { CCutsceneObject::PreRender(); } - void Render_(void) { CCutsceneObject::Render(); } - bool SetupLighting_(void) { return CCutsceneObject::SetupLighting(); } - void RemoveLighting_(bool reset) { CCutsceneObject::RemoveLighting(reset); } -}; - -STARTPATCHES - InjectHook(0x4BA960, &CCutsceneObject_::dtor, PATCH_JUMP); - InjectHook(0x4BA980, &CCutsceneObject_::SetModelIndex_, PATCH_JUMP); - InjectHook(0x4BA9C0, &CCutsceneObject_::ProcessControl_, PATCH_JUMP); - InjectHook(0x4BAA40, &CCutsceneObject_::PreRender_, PATCH_JUMP); - InjectHook(0x4BAAA0, &CCutsceneObject_::Render_, PATCH_JUMP); - InjectHook(0x4A7E70, &CCutsceneObject_::SetupLighting_, PATCH_JUMP); - InjectHook(0x4A7F00, &CCutsceneObject_::RemoveLighting_, PATCH_JUMP); -ENDPATCHES diff --git a/src/objects/DummyObject.cpp b/src/objects/DummyObject.cpp index ba09ac3e..d5805073 100644 --- a/src/objects/DummyObject.cpp +++ b/src/objects/DummyObject.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "DummyObject.h" #include "Pools.h" @@ -11,19 +11,3 @@ CDummyObject::CDummyObject(CObject *obj) obj->DetachFromRwObject(); m_level = obj->m_level; } - -#include - -class CDummyObject_ : public CDummyObject -{ -public: - void dtor(void) { CDummyObject::~CDummyObject(); } - CDummyObject *ctor(void) { return ::new (this) CDummyObject(); } - CDummyObject *ctor(CObject *obj) { return ::new (this) CDummyObject(obj); } -}; - -STARTPATCHES - InjectHook(0x4BAAF0, (CDummyObject* (CDummyObject::*)(void)) &CDummyObject_::ctor, PATCH_JUMP); - InjectHook(0x4BAB10, (CDummyObject* (CDummyObject::*)(CObject*)) &CDummyObject_::ctor, PATCH_JUMP); - InjectHook(0x4BAB70, &CDummyObject_::dtor, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index c22148e9..8968c117 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Lights.h" #include "Pools.h" @@ -394,37 +394,3 @@ CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius) } } } - -#include - -class CObject_ : public CObject -{ -public: - CObject *ctor(void) { return ::new (this) CObject(); } - CObject *ctor(int32 mi, bool createRW) { return ::new (this) CObject(mi, createRW); } - CObject *ctor(CDummyObject *dummy) { return ::new (this) CObject(dummy); } - void dtor(void) { CObject::~CObject(); } - void Render_(void) { CObject::Render(); } - void ProcessControl_(void) { CObject::ProcessControl(); } - bool SetupLighting_(void) { return CObject::SetupLighting(); } - void RemoveLighting_(bool reset) { CObject::RemoveLighting(reset); } -}; - -STARTPATCHES - InjectHook(0x4BABD0, (CObject* (CObject::*)(void)) &CObject_::ctor, PATCH_JUMP); - InjectHook(0x4BACE0, (CObject* (CObject::*)(int32, bool)) &CObject_::ctor, PATCH_JUMP); - InjectHook(0x4BAD50, (CObject* (CObject::*)(CDummyObject*)) &CObject_::ctor, PATCH_JUMP); - InjectHook(0x4BAE00, &CObject_::dtor, PATCH_JUMP); - InjectHook(0x4BB040, &CObject_::ProcessControl_, PATCH_JUMP); - InjectHook(0x4BBDA0, &CObject::Teleport, PATCH_JUMP); - InjectHook(0x4BB1E0, &CObject_::Render_, PATCH_JUMP); - InjectHook(0x4A7C90, &CObject_::SetupLighting_, PATCH_JUMP); - InjectHook(0x4A7CD0, &CObject_::RemoveLighting_, PATCH_JUMP); - InjectHook(0x4BB240, &CObject::ObjectDamage, PATCH_JUMP); - InjectHook(0x4BBD80, &CObject::RefModelInfo, PATCH_JUMP); - InjectHook(0x4BAEC0, &CObject::Init, PATCH_JUMP); - InjectHook(0x4BB010, &CObject::CanBeDeleted, PATCH_JUMP); - InjectHook(0x4BBE60, &CObject::DeleteAllMissionObjects, PATCH_JUMP); - InjectHook(0x4BBDF0, &CObject::DeleteAllTempObjects, PATCH_JUMP); - InjectHook(0x4BBED0, &CObject::DeleteAllTempObjectsInArea, PATCH_JUMP); -ENDPATCHES diff --git a/src/objects/ObjectData.cpp b/src/objects/ObjectData.cpp index aa58a845..589cc3f7 100644 --- a/src/objects/ObjectData.cpp +++ b/src/objects/ObjectData.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "ModelInfo.h" #include "Object.h" @@ -96,8 +96,3 @@ CObjectData::SetObjectData(int32 modelId, CObject &object) object.bExplosionProof = true; } } - -STARTPATCHES - InjectHook(0x4BC0E0, CObjectData::Initialise, PATCH_JUMP); - InjectHook(0x4BC270, CObjectData::SetObjectData, PATCH_JUMP); -ENDPATCHES diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp index 5e4ad231..fe448966 100644 --- a/src/objects/ParticleObject.cpp +++ b/src/objects/ParticleObject.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "ParticleObject.h" #include "Timer.h" #include "General.h" @@ -1099,39 +1099,3 @@ CParticleObject::MoveToList(CParticleObject **from, CParticleObject **to, CParti if ( obj->m_pNext ) obj->m_pNext->m_pPrev = obj; } - -class CParticleObject_ : public CParticleObject -{ -public: - void ctor() { CParticleObject::CParticleObject(); } - void dtor() { CParticleObject::~CParticleObject(); } -}; - -STARTPATCHES - InjectHook(0x4BC330, CAudioHydrant::Add, PATCH_JUMP); - InjectHook(0x4BC390, CAudioHydrant::Remove, PATCH_JUMP); - - InjectHook(0x4BC3E0, &CParticleObject_::ctor, PATCH_JUMP); - InjectHook(0x4BC420, &CParticleObject_::dtor, PATCH_JUMP); - InjectHook(0x4BC440, CParticleObject::Initialise, PATCH_JUMP); - - InjectHook(0x4BC4D0, (CParticleObject *(*)(uint16, CVector const &, uint8))CParticleObject::AddObject, PATCH_JUMP); - InjectHook(0x4BC520, (CParticleObject *(*)(uint16, CVector const &, float, uint8))CParticleObject::AddObject, PATCH_JUMP); - InjectHook(0x4BC570, (CParticleObject *(*)(uint16, CVector const &, CVector const &, float, uint8))CParticleObject::AddObject, PATCH_JUMP); - InjectHook(0x4BC5B0, (CParticleObject *(*)(uint16, CVector const &, CVector const &, float, uint32, RwRGBA const &, uint8))CParticleObject::AddObject, PATCH_JUMP); - - InjectHook(0x4BC9F0, &CParticleObject::RemoveObject, PATCH_JUMP); - InjectHook(0x4BCA30, CParticleObject::UpdateAll, PATCH_JUMP); - InjectHook(0x4BCA80, &CParticleObject::UpdateClose, PATCH_JUMP); - InjectHook(0x4BF9F0, &CParticleObject::UpdateFar, PATCH_JUMP); - InjectHook(0x4BFA80, CParticleObject::SaveParticle, PATCH_JUMP); - InjectHook(0x4BFB30, CParticleObject::LoadParticle, PATCH_JUMP); - InjectHook(0x4BFC80, CParticleObject::RemoveAllParticleObjects, PATCH_JUMP); - InjectHook(0x4BFD10, CParticleObject::MoveToList, PATCH_JUMP); - //InjectHook(0x4BFD70, CParticleObject::~CParticleObject, PATCH_JUMP); // virtual - //InjectHook(0x4BFDB0, `global constructor keyed to'ParticleObject.cpp, PATCH_JUMP); - //InjectHook(0x4BFE00, CAudioHydrant::CAudioHydrant, PATCH_JUMP); - //InjectHook(0x4BFE10, sub_4BFE10, PATCH_JUMP); // destroy gPObjectArray array - - -ENDPATCHES diff --git a/src/objects/Projectile.cpp b/src/objects/Projectile.cpp index 32bc6bdb..fe8b0c68 100644 --- a/src/objects/Projectile.cpp +++ b/src/objects/Projectile.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Projectile.h" CProjectile::CProjectile(int32 model) : CObject() @@ -13,17 +13,3 @@ CProjectile::CProjectile(int32 model) : CObject() SetModelIndex(model); ObjectCreatedBy = MISSION_OBJECT; } - -#include - -class CProjectile_ : public CProjectile -{ -public: - CProjectile* ctor(int32 model) { return ::new (this) CProjectile(model); } - void dtor(void) { CProjectile::~CProjectile(); } -}; - -STARTPATCHES - InjectHook(0x4BFE30, &CProjectile_::ctor, PATCH_JUMP); - InjectHook(0x4BFED0, &CProjectile_::dtor, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index a9e0580e..f38f5a73 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "CivilianPed.h" #include "Phones.h" #include "General.h" @@ -376,21 +376,3 @@ CCivilianPed::ProcessControl(void) if (m_moved.Magnitude() > 0.0f) Avoid(); } - -#include - -class CCivilianPed_ : public CCivilianPed -{ -public: - CCivilianPed *ctor(ePedType pedtype, uint32 mi) { return ::new (this) CCivilianPed(pedtype, mi); }; - void dtor(void) { CCivilianPed::~CCivilianPed(); } - void ProcessControl_(void) { CCivilianPed::ProcessControl(); } -}; - -STARTPATCHES - InjectHook(0x4BFF30, &CCivilianPed_::ctor, PATCH_JUMP); - InjectHook(0x4BFFC0, &CCivilianPed_::dtor, PATCH_JUMP); - InjectHook(0x4BFFE0, &CCivilianPed_::ProcessControl_, PATCH_JUMP); - - InjectHook(0x4C07A0, &CCivilianPed::CivilianAI, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index b5812136..e62743de 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "World.h" #include "PlayerPed.h" #include "CopPed.h" @@ -736,25 +736,3 @@ CCopPed::ProcessControl(void) SetAttack(m_pedInObjective); } } - -#include - -class CCopPed_ : public CCopPed -{ -public: - CCopPed *ctor(eCopType type) { return ::new (this) CCopPed(type); }; - void dtor(void) { CCopPed::~CCopPed(); } - void ProcessControl_(void) { CCopPed::ProcessControl(); } -}; - -STARTPATCHES - InjectHook(0x4C11B0, &CCopPed_::ctor, PATCH_JUMP); - InjectHook(0x4C13E0, &CCopPed_::dtor, PATCH_JUMP); - InjectHook(0x4C1400, &CCopPed_::ProcessControl_, PATCH_JUMP); - InjectHook(0x4C28C0, &CCopPed::ClearPursuit, PATCH_JUMP); - InjectHook(0x4C2B00, &CCopPed::SetArrestPlayer, PATCH_JUMP); - 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 diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index 3a5067e7..7229ed3f 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "EmergencyPed.h" #include "DMAudio.h" #include "ModelIndices.h" @@ -413,20 +413,3 @@ CEmergencyPed::MedicAI(void) } } } - -#include - -class CEmergencyPed_ : public CEmergencyPed -{ -public: - CEmergencyPed* ctor(int pedtype) { return ::new (this) CEmergencyPed(pedtype); }; - void dtor(void) { CEmergencyPed::~CEmergencyPed(); } - void ProcessControl_(void) { CEmergencyPed::ProcessControl(); } -}; - -STARTPATCHES - InjectHook(0x4C2E40, &CEmergencyPed_::ctor, PATCH_JUMP); - InjectHook(0x4C2EF0, &CEmergencyPed_::dtor, PATCH_JUMP); - InjectHook(0x4C2F10, &CEmergencyPed_::ProcessControl_, PATCH_JUMP); - InjectHook(0x4C3EC0, &CEmergencyPed::InRange, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/Gangs.cpp b/src/peds/Gangs.cpp index c67fe599..8859e61e 100644 --- a/src/peds/Gangs.cpp +++ b/src/peds/Gangs.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "ModelIndices.h" #include "Gangs.h" #include "Weapon.h" @@ -75,13 +75,3 @@ INITSAVEBUF Gang[i] = ReadSaveBuf(buf); VALIDATESAVEBUF(size); } - -STARTPATCHES - InjectHook(0x4C3FB0, CGangs::Initialise, PATCH_JUMP); - InjectHook(0x4C4010, CGangs::SetGangVehicleModel, PATCH_JUMP); - InjectHook(0x4C4030, CGangs::SetGangWeapons, PATCH_JUMP); - InjectHook(0x4C4050, CGangs::SetGangPedModelOverride, PATCH_JUMP); - InjectHook(0x4C4070, CGangs::GetGangPedModelOverride, PATCH_JUMP); - InjectHook(0x4C4080, CGangs::SaveAllGangData, PATCH_JUMP); - InjectHook(0x4C4100, CGangs::LoadAllGangData, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 8ea41230..4737051e 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Pools.h" #include "Particle.h" @@ -17502,240 +17502,3 @@ CPed::SetExitBoat(CVehicle *boat) // Not there in VC. CWaterLevel::FreeBoatWakeArray(); } - -#include - -class CPed_ : public CPed -{ -public: - CPed *ctor(uint32 pedType) { return ::new (this) CPed(pedType); } - void dtor(void) { CPed::~CPed(); } - - void SetModelIndex_(uint32 mi) { CPed::SetModelIndex(mi); } - void FlagToDestroyWhenNextProcessed_(void) { CPed::FlagToDestroyWhenNextProcessed(); } - bool SetupLighting_(void) { return CPed::SetupLighting(); } - void RemoveLighting_(bool reset) { CPed::RemoveLighting(reset); } - void Teleport_(CVector pos) { CPed::Teleport(pos); } - void ProcessControl_(void) { CPed::ProcessControl(); } - void Render_(void) { CPed::Render(); } - void PreRender_(void) { CPed::PreRender(); } - int32 ProcessEntityCollision_(CEntity *collidingEnt, CColPoint *collidingPoints) { return CPed::ProcessEntityCollision(collidingEnt, collidingPoints); } - void SetMoveAnim_(void) { CPed::SetMoveAnim(); } -}; - -STARTPATCHES - InjectHook(0x4C41C0, &CPed_::ctor, PATCH_JUMP); - InjectHook(0x4C50D0, &CPed_::dtor, PATCH_JUMP); - InjectHook(0x4C52A0, &CPed_::SetModelIndex_, PATCH_JUMP); - InjectHook(0x4D6570, &CPed_::FlagToDestroyWhenNextProcessed_, PATCH_JUMP); - InjectHook(0x4A7D30, &CPed_::SetupLighting_, PATCH_JUMP); - InjectHook(0x4A7DC0, &CPed_::RemoveLighting_, PATCH_JUMP); - InjectHook(0x4D3E70, &CPed_::Teleport_, PATCH_JUMP); - InjectHook(0x4C8910, &CPed_::ProcessControl_, PATCH_JUMP); - InjectHook(0x4D03F0, &CPed_::Render_, PATCH_JUMP); - InjectHook(0x4CBB30, &CPed_::ProcessEntityCollision_, PATCH_JUMP); - InjectHook(0x4CFDD0, &CPed_::PreRender_, PATCH_JUMP); - InjectHook(0x4C5A40, &CPed_::SetMoveAnim_, PATCH_JUMP); - - InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP); - InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP); - InjectHook(0x4EB470, &CPed::ApplyHeadShot, PATCH_JUMP); - InjectHook(0x4EAEE0, &CPed::RemoveBodyPart, PATCH_JUMP); - InjectHook(0x4C6460, (void (CPed::*)(CEntity*, bool)) &CPed::SetLookFlag, PATCH_JUMP); - InjectHook(0x4C63E0, (void (CPed::*)(float, bool)) &CPed::SetLookFlag, PATCH_JUMP); - InjectHook(0x4D12E0, &CPed::SetLookTimer, PATCH_JUMP); - InjectHook(0x4C5700, &CPed::OurPedCanSeeThisOne, PATCH_JUMP); - InjectHook(0x4D2BB0, &CPed::Avoid, PATCH_JUMP); - InjectHook(0x4C6A50, &CPed::ClearAimFlag, PATCH_JUMP); - InjectHook(0x4C64F0, &CPed::ClearLookFlag, PATCH_JUMP); - InjectHook(0x4EB670, &CPed::IsPedHeadAbovePos, PATCH_JUMP); - InjectHook(0x4E68A0, &CPed::FinishedAttackCB, PATCH_JUMP); - InjectHook(0x4E5BD0, &CheckForPedsOnGroundToAttack, PATCH_JUMP); - InjectHook(0x4E6BA0, &CPed::Attack, PATCH_JUMP); - InjectHook(0x4CF980, &CPed::RemoveWeaponModel, PATCH_JUMP); - InjectHook(0x4CFA60, &CPed::SetCurrentWeapon, PATCH_JUMP); - InjectHook(0x4E4A10, &CPed::Duck, PATCH_JUMP); - InjectHook(0x4E4A30, &CPed::ClearDuck, PATCH_JUMP); - InjectHook(0x4E6180, &CPed::ClearPointGunAt, PATCH_JUMP); - InjectHook(0x4E07D0, &CPed::BeingDraggedFromCar, PATCH_JUMP); - InjectHook(0x4CF000, &CPed::PedSetDraggedOutCarCB, PATCH_JUMP); - InjectHook(0x4C5D80, &CPed::RestartNonPartialAnims, PATCH_JUMP); - InjectHook(0x4E4730, &CPed::GetLocalPositionToOpenCarDoor, PATCH_JUMP); - InjectHook(0x4E4660, (CVector (*)(CVehicle*, uint32, float)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP); - InjectHook(0x4E1A30, (CVector (*)(CVehicle*, uint32)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP); - InjectHook(0x4DF940, &CPed::LineUpPedWithCar, PATCH_JUMP); - InjectHook(0x4CC6C0, &CPed::PlayFootSteps, PATCH_JUMP); - InjectHook(0x4C5350, &CPed::BuildPedLists, PATCH_JUMP); - InjectHook(0x4CF9B0, &CPed::GiveWeapon, PATCH_JUMP); - InjectHook(0x4C7EA0, &CPed::CalculateNewOrientation, PATCH_JUMP); - InjectHook(0x4C78F0, &CPed::WorkOutHeadingForMovingFirstPerson, PATCH_JUMP); - InjectHook(0x4C73F0, &CPed::CalculateNewVelocity, PATCH_JUMP); - InjectHook(0x4DD820, &CPed::CanSeeEntity, PATCH_JUMP); - InjectHook(0x4D9460, &CPed::RestorePreviousObjective, PATCH_JUMP); - InjectHook(0x4D82C0, (void (CPed::*)(eObjective)) &CPed::SetObjective, PATCH_JUMP); - InjectHook(0x4D83E0, (void (CPed::*)(eObjective, void*)) &CPed::SetObjective, PATCH_JUMP); - InjectHook(0x4D89A0, (void (CPed::*)(eObjective, int16, int16)) &CPed::SetObjective, PATCH_JUMP); - InjectHook(0x4D8A90, (void (CPed::*)(eObjective, CVector)) &CPed::SetObjective, PATCH_JUMP); - InjectHook(0x4D8770, (void (CPed::*)(eObjective, CVector, float)) &CPed::SetObjective, PATCH_JUMP); - InjectHook(0x4DDEC0, &CPed::ReactToAttack, PATCH_JUMP); - InjectHook(0x4D0600, &CPed::SetIdle, PATCH_JUMP); - InjectHook(0x4E0E00, &CPed::QuitEnteringCar, PATCH_JUMP); - InjectHook(0x4E4AD0, &CPed::InformMyGangOfAttack, PATCH_JUMP); - InjectHook(0x4D3C80, &CPed::ClearChat, PATCH_JUMP); - InjectHook(0x4D1390, &CPed::TurnBody, PATCH_JUMP); - InjectHook(0x4D3AC0, &CPed::Chat, PATCH_JUMP); - InjectHook(0x4D0490, &CPed::CheckAroundForPossibleCollisions, PATCH_JUMP); - InjectHook(0x4D3E20, &CPed::MakePhonecall, PATCH_JUMP); - InjectHook(0x4D3CC0, &CPed::FacePhone, PATCH_JUMP); - InjectHook(0x4D4860, &CPed::CheckForDeadPeds, PATCH_JUMP); - InjectHook(0x4D4650, &CPed::CheckForExplosions, PATCH_JUMP); - InjectHook(0x4D47D0, &CPed::CheckForGunShots, PATCH_JUMP); - InjectHook(0x4E6990, &CPed::CheckForPointBlankPeds, PATCH_JUMP); - InjectHook(0x4D0BE0, &CPed::CheckIfInTheAir, PATCH_JUMP); - InjectHook(0x4C7F20, &CPed::ClearAll, PATCH_JUMP); - InjectHook(0x4E6790, &CPed::ClearAttack, PATCH_JUMP); - InjectHook(0x4E67F0, &CPed::ClearAttackByRemovingAnim, PATCH_JUMP); - InjectHook(0x4D37D0, &CPed::SetDie, PATCH_JUMP); - InjectHook(0x4C5D50, &CPed::StopNonPartialAnims, PATCH_JUMP); - InjectHook(0x4C5DB0, &CPed::SetStoredState, PATCH_JUMP); - InjectHook(0x4EA420, &CPed::InflictDamage, PATCH_JUMP); - InjectHook(0x4D1EA0, &CPed::ClearFlee, PATCH_JUMP); - InjectHook(0x4D0BB0, &CPed::ClearFall, PATCH_JUMP); - InjectHook(0x4D0F20, &CPed::SetGetUp, PATCH_JUMP); - InjectHook(0x4D6550, &CPed::RestoreHeadingRateCB, PATCH_JUMP); - InjectHook(0x4C5E30, &CPed::RestorePreviousState, PATCH_JUMP); - InjectHook(0x4E5F70, &CPed::SetPointGunAt, PATCH_JUMP); - InjectHook(0x4D2750, &CPed::SetWanderPath, PATCH_JUMP); - InjectHook(0x4D30C0, &CPed::SetEvasiveStep, PATCH_JUMP); - InjectHook(0x4EA360, &CPed::ClearInvestigateEvent, PATCH_JUMP); - InjectHook(0x4D8E80, &CPed::ClearLeader, PATCH_JUMP); - InjectHook(0x4D1360, &CPed::ClearLook, PATCH_JUMP); - InjectHook(0x4D8DF0, &CPed::ClearObjective, PATCH_JUMP); - InjectHook(0x4D0970, &CPed::ClearPause, PATCH_JUMP); - InjectHook(0x4D1620, &CPed::ClearSeek, PATCH_JUMP); - InjectHook(0x4CFB70, &CPed::ClearWeapons, PATCH_JUMP); - InjectHook(0x4C6BB0, &CPed::RestoreGunPosition, PATCH_JUMP); - InjectHook(0x4D6540, &CPed::RestoreHeadingRate, PATCH_JUMP); - InjectHook(0x4C69E0, (void (CPed::*)(CEntity*)) &CPed::SetAimFlag, PATCH_JUMP); - InjectHook(0x4C6960, (void (CPed::*)(float)) &CPed::SetAimFlag, PATCH_JUMP); - InjectHook(0x4CFAD0, &CPed::GrantAmmo, PATCH_JUMP); - InjectHook(0x4CFB20, &CPed::SetAmmo, PATCH_JUMP); - InjectHook(0x4D33A0, &CPed::SetEvasiveDive, PATCH_JUMP); - InjectHook(0x4D09B0, &CPed::SetFall, PATCH_JUMP); - InjectHook(0x4E6220, &CPed::SetAttack, PATCH_JUMP); - InjectHook(0x4E7530, &CPed::StartFightAttack, PATCH_JUMP); - InjectHook(0x4E8EC0, &CPed::FightStrike, PATCH_JUMP); - InjectHook(0x4CCE20, &CPed::GetLocalDirection, PATCH_JUMP); - InjectHook(0x4E8E20, &CPed::PlayHitSound, PATCH_JUMP); - InjectHook(0x4E5A10, &CPed::Say, PATCH_JUMP); - InjectHook(0x4D58D0, &CPed::SetWaitState, PATCH_JUMP); - InjectHook(0x4D1D70, (void (CPed::*)(CEntity*, int)) &CPed::SetFlee, PATCH_JUMP); - InjectHook(0x4D1C40, (void (CPed::*)(CVector2D const &, int)) &CPed::SetFlee, PATCH_JUMP); - InjectHook(0x4EB9A0, &CPed::CollideWithPed, PATCH_JUMP); - InjectHook(0x433490, &CPed::CreateDeadPedMoney, PATCH_JUMP); - InjectHook(0x433660, &CPed::CreateDeadPedWeaponPickups, PATCH_JUMP); - InjectHook(0x4D3970, &CPed::SetDead, PATCH_JUMP); - InjectHook(0x53CDF0, &CPed::DeadPedMakesTyresBloody, PATCH_JUMP); - InjectHook(0x4E0640, &CPed::SetBeingDraggedFromCar, PATCH_JUMP); - InjectHook(0x4D1300, &CPed::SetAttackTimer, PATCH_JUMP); - InjectHook(0x4D6950, &CPed::SetBuyIceCream, PATCH_JUMP); - InjectHook(0x4D3A60, &CPed::SetChat, PATCH_JUMP); - InjectHook(0x4D14B0, (void (CPed::*)(CVector, float)) &CPed::SetSeek, PATCH_JUMP); - InjectHook(0x4D15A0, (void (CPed::*)(CEntity*, float)) &CPed::SetSeek, PATCH_JUMP); - InjectHook(0x4EB5C0, &CPed::DoesLOSBulletHitPed, PATCH_JUMP); - InjectHook(0x4E3EC0, &CPed::DuckAndCover, PATCH_JUMP); - InjectHook(0x4E8D30, &CPed::EndFight, PATCH_JUMP); - InjectHook(0x4E0D30, &CPed::EnterCar, PATCH_JUMP); - InjectHook(0x4E2E50, &CPed::GetNearestTrainPedPosition, PATCH_JUMP); - InjectHook(0x4E2D70, &CPed::GetNearestTrainDoor, PATCH_JUMP); - InjectHook(0x4E33D0, &CPed::LineUpPedWithTrain, PATCH_JUMP); - InjectHook(0x4E18D0, &CPed::ExitCar, PATCH_JUMP); - InjectHook(0x4E7EE0, &CPed::Fight, PATCH_JUMP); - InjectHook(0x4D3950, &CPed::FinishDieAnimCB, PATCH_JUMP); - InjectHook(0x4E9830, &CPed::FinishFightMoveCB, PATCH_JUMP); - InjectHook(0x4D7A80, &CPed::FinishHitHeadCB, PATCH_JUMP); - InjectHook(0x4D7A50, &CPed::FinishJumpCB, PATCH_JUMP); - InjectHook(0x4D7490, &CPed::FinishLaunchCB, PATCH_JUMP); - InjectHook(0x4D6520, &CPed::FinishedWaitCB, PATCH_JUMP); - InjectHook(0x4D5D80, &CPed::Wait, PATCH_JUMP); - InjectHook(0x4E3A90, &CPed::FindBestCoordsFromNodes, PATCH_JUMP); - InjectHook(0x4D2E70, &CPed::SeekFollowingPath, PATCH_JUMP); - InjectHook(0x4D1640, &CPed::Seek, PATCH_JUMP); - InjectHook(0x4D3020, &CPed::FollowPath, PATCH_JUMP); - InjectHook(0x4D1ED0, &CPed::Flee, PATCH_JUMP); - InjectHook(0x4E1CF0, &CPed::GetNearestDoor, PATCH_JUMP); - InjectHook(0x4DF420, &CPed::GetFormationPosition, PATCH_JUMP); - InjectHook(0x4E1F30, &CPed::GetNearestPassengerDoor, PATCH_JUMP); - InjectHook(0x4D0690, &CPed::Idle, PATCH_JUMP); - InjectHook(0x4DD720, &CPed::GetNextPointOnRoute, PATCH_JUMP); - InjectHook(0x4D7B50, &CPed::GetPedRadioCategory, PATCH_JUMP); - InjectHook(0x4CFA40, &CPed::GetWeaponSlot, PATCH_JUMP); - InjectHook(0x4E2220, &CPed::GoToNearestDoor, PATCH_JUMP); - InjectHook(0x4DD7B0, &CPed::HaveReachedNextPointOnRoute, PATCH_JUMP); - InjectHook(0x4D0D10, &CPed::InTheAir, PATCH_JUMP); - InjectHook(0x4C5270, &CPed::Initialise, PATCH_JUMP); - InjectHook(0x4D0E40, &CPed::SetLanding, PATCH_JUMP); - InjectHook(0x4E9B50, &CPed::InvestigateEvent, PATCH_JUMP); - InjectHook(0x564BB0, &CPed::IsPedDoingDriveByShooting, PATCH_JUMP); - InjectHook(0x4E4D90, &CPed::IsRoomToBeCarJacked, PATCH_JUMP); - InjectHook(0x4EC430, &CPed::KillPedWithCar, PATCH_JUMP); - InjectHook(0x4E9A80, &CPed::SetInvestigateEvent, PATCH_JUMP); - InjectHook(0x4D5040, &CPed::LookForInterestingNodes, PATCH_JUMP); - InjectHook(0x4D4F50, &CPed::LookForSexyCars, PATCH_JUMP); - InjectHook(0x4D4DF0, &CPed::LookForSexyPeds, PATCH_JUMP); - InjectHook(0x53CFD0, &CPed::MakeTyresMuddySectorList, PATCH_JUMP); - InjectHook(0x4C6580, &FinishFuckUCB, PATCH_JUMP); - InjectHook(0x4D11D0, &CPed::Mug, PATCH_JUMP); - InjectHook(0x4DE130, &CPed::PedAnimAlignCB, PATCH_JUMP); - InjectHook(0x4D0980, &CPed::Pause, PATCH_JUMP); - InjectHook(0x4C65B0, &CPed::MoveHeadToLook, PATCH_JUMP); - InjectHook(0x4DF1B0, &CPed::PedAnimDoorCloseCB, PATCH_JUMP); - InjectHook(0x4E4B90, &CPed::PedAnimDoorCloseRollingCB, PATCH_JUMP); - InjectHook(0x4DE500, &CPed::PedAnimDoorOpenCB, PATCH_JUMP); - InjectHook(0x4D73D0, &CPed::SetJump, PATCH_JUMP); - InjectHook(0x4E4E20, &CPed::RemoveInCarAnims, PATCH_JUMP); - InjectHook(0x4DEC80, &CPed::PedAnimGetInCB, PATCH_JUMP); - InjectHook(0x4DEAF0, &CPed::PedAnimPullPedOutCB, PATCH_JUMP); - InjectHook(0x4DF5C0, &CPed::PedAnimStepOutCarCB, PATCH_JUMP); - InjectHook(0x4D36E0, &CPed::PedEvadeCB, PATCH_JUMP); - InjectHook(0x4CE810, &CPed::PedGetupCB, PATCH_JUMP); - InjectHook(0x4CE8A0, &CPed::PedLandCB, PATCH_JUMP); - InjectHook(0x4E2920, &CPed::PedSetDraggedOutCarPositionCB, PATCH_JUMP); - InjectHook(0x4CF220, &CPed::PedSetInCarCB, PATCH_JUMP); - InjectHook(0x4E3290, &CPed::PedSetInTrainCB, PATCH_JUMP); - InjectHook(0x4C10C0, &CPed::RunToReportCrime, PATCH_JUMP); - InjectHook(0x4E3870, &CPed::RegisterThreatWithGangPeds, PATCH_JUMP); - InjectHook(0x4DD980, &CPed::ReactToPointGun, PATCH_JUMP); - InjectHook(0x4CE8F0, &CPed::PedSetOutCarCB, PATCH_JUMP); - InjectHook(0x4E36E0, &CPed::PedSetOutTrainCB, PATCH_JUMP); - InjectHook(0x4EB6E0, &CPed::PlacePedOnDryLand, PATCH_JUMP); - InjectHook(0x4E2480, &CPed::PedSetQuickDraggedOutCarPositionCB, PATCH_JUMP); - InjectHook(0x4E4F30, &CPed::PositionPedOutOfCollision, PATCH_JUMP); - InjectHook(0x4D6A00, &CPed::PossiblyFindBetterPosToSeekCar, PATCH_JUMP); - InjectHook(0x4D94E0, &CPed::ProcessObjective, PATCH_JUMP); - InjectHook(0x4CCEB0, &CPed::SetDirectionToWalkAroundObject, PATCH_JUMP); - InjectHook(0x4DF3E0, &CPed::SetFormation, PATCH_JUMP); - InjectHook(0x4C7340, &CPed::WillChat, PATCH_JUMP); - InjectHook(0x4E32D0, &CPed::SetEnterTrain, PATCH_JUMP); - InjectHook(0x4E4920, &CPed::SetDuck, PATCH_JUMP); - InjectHook(0x4E0920, &CPed::SetEnterCar, PATCH_JUMP); - InjectHook(0x4D7BC0, &CPed::SetRadioStation, PATCH_JUMP); - InjectHook(0x4C7FF0, &CPed::ProcessBuoyancy, PATCH_JUMP); - InjectHook(0x4D6620, &CPed::SetSolicit, PATCH_JUMP); - InjectHook(0x4D2EA0, &CPed::SetFollowPath, PATCH_JUMP); - InjectHook(0x4E1010, &CPed::SetExitCar, PATCH_JUMP); - InjectHook(0x4C5FE0, &CPed::ScanForThreats, PATCH_JUMP); - InjectHook(0x4C6C10, &CPed::ScanForInterestingStuff, PATCH_JUMP); - InjectHook(0x4D3F90, &CPed::SeekCar, PATCH_JUMP); - InjectHook(0x4E5870, &CPed::ServiceTalking, PATCH_JUMP); - InjectHook(0x4E7780, &CPed::StartFightDefend, PATCH_JUMP); - InjectHook(0x4D8F30, &CPed::UpdateFromLeader, PATCH_JUMP); - InjectHook(0x4D4970, &CPed::SetPedPositionInCar, PATCH_JUMP); - InjectHook(0x4D7D20, &CPed::WarpPedIntoCar, PATCH_JUMP); - InjectHook(0x4E0A40, &CPed::SetEnterCar_AllClear, PATCH_JUMP); - InjectHook(0x4D28D0, &CPed::WanderPath, PATCH_JUMP); - InjectHook(0x4E5570, &CPed::WarpPedToNearEntityOffScreen, PATCH_JUMP); - InjectHook(0x4E52A0, &CPed::WarpPedToNearLeaderOffScreen, PATCH_JUMP); - InjectHook(0x4E0220, &CPed::SetCarJack, PATCH_JUMP); - InjectHook(0x4D6780, &CPed::Solicit, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index 8e450ee6..1464c4e8 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Camera.h" #include "PedIK.h" #include "Ped.h" @@ -362,19 +362,3 @@ CPedIK::ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch) *pitch = Acos(f); if (mat->up.x > 0.0f) *pitch = -*pitch; } - -STARTPATCHES - InjectHook(0x4ED0F0, &CPedIK::GetComponentPosition, PATCH_JUMP); - InjectHook(0x4ED060, &CPedIK::GetWorldMatrix, PATCH_JUMP); - InjectHook(0x4EDDB0, &CPedIK::RotateTorso, PATCH_JUMP); - InjectHook(0x4ED440, &CPedIK::MoveLimb, PATCH_JUMP); - InjectHook(0x4EDD70, &CPedIK::RestoreGunPosn, PATCH_JUMP); - InjectHook(0x4ED620, &CPedIK::LookInDirection, PATCH_JUMP); - InjectHook(0x4ED590, &CPedIK::LookAtPosition, PATCH_JUMP); - InjectHook(0x4ED9B0, &CPedIK::PointGunInDirection, PATCH_JUMP); - InjectHook(0x4EDB20, &CPedIK::PointGunInDirectionUsingArm, PATCH_JUMP); - InjectHook(0x4ED920, &CPedIK::PointGunAtPosition, PATCH_JUMP); - InjectHook(0x4ED810, &CPedIK::RestoreLookAt, PATCH_JUMP); - InjectHook(0x4ED140, &CPedIK::ExtractYawAndPitchWorld, PATCH_JUMP); - InjectHook(0x4ED2C0, &CPedIK::ExtractYawAndPitchLocal, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/peds/PedPlacement.cpp b/src/peds/PedPlacement.cpp index e5f6a077..6038cf91 100644 --- a/src/peds/PedPlacement.cpp +++ b/src/peds/PedPlacement.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Ped.h" #include "PedPlacement.h" #include "World.h" @@ -49,8 +49,3 @@ CPedPlacement::IsPositionClearForPed(CVector* pos) CWorld::FindObjectsKindaColliding(*pos, 0.75f, true, &count, 2, nil, false, true, true, false, false); return count == 0; } - -STARTPATCHES - InjectHook(0x4EE340, &CPedPlacement::FindZCoorForPed, PATCH_JUMP); - InjectHook(0x4EE310, &CPedPlacement::IsPositionClearOfCars, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/PedRoutes.cpp b/src/peds/PedRoutes.cpp index b6512edd..3ff080e6 100644 --- a/src/peds/PedRoutes.cpp +++ b/src/peds/PedRoutes.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "PedRoutes.h" diff --git a/src/peds/PedStats.cpp b/src/peds/PedStats.cpp index a2ccb567..06e39039 100644 --- a/src/peds/PedStats.cpp +++ b/src/peds/PedStats.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "FileMgr.h" #include "PedStats.h" @@ -116,10 +116,3 @@ CPedStats::GetPedStatType(char *name) return NUM_PEDSTATS; } - -STARTPATCHES - InjectHook(0x4EF460, &CPedStats::Initialise, PATCH_JUMP); - InjectHook(0x4EF540, &CPedStats::Shutdown, PATCH_JUMP); - InjectHook(0x4EF580, &CPedStats::LoadPedStats, PATCH_JUMP); - InjectHook(0x4EF780, &CPedStats::GetPedStatType, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp index 30af6dcc..8bf4c6e1 100644 --- a/src/peds/PedType.cpp +++ b/src/peds/PedType.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "FileMgr.h" #include "PedType.h" @@ -202,12 +202,3 @@ INITSAVEBUF *ms_apPedType[i] = ReadSaveBuf(buf); VALIDATESAVEBUF(size) } - -STARTPATCHES - InjectHook(0x4EE7E0, &CPedType::Initialise, PATCH_JUMP); - InjectHook(0x4EE890, &CPedType::Shutdown, PATCH_JUMP); - InjectHook(0x4EEC10, &CPedType::FindPedType, PATCH_JUMP); - InjectHook(0x4EEF40, &CPedType::FindPedFlag, PATCH_JUMP); - InjectHook(0x4EF320, &CPedType::Save, PATCH_JUMP); - InjectHook(0x4EF3D0, &CPedType::Load, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index dcd9486f..0a0fe6a3 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "PlayerPed.h" #include "Wanted.h" #include "Fire.h" @@ -1495,41 +1495,3 @@ CPlayerPed::ProcessControl(void) m_bSpeedTimerFlag = false; } } - -#include - -class CPlayerPed_ : public CPlayerPed -{ -public: - CPlayerPed* ctor(void) { return ::new (this) CPlayerPed(); } - void dtor(void) { CPlayerPed::~CPlayerPed(); } - void SetMoveAnim_(void) { CPlayerPed::SetMoveAnim(); } - void ProcessControl_(void) { CPlayerPed::ProcessControl(); } -}; - -STARTPATCHES - InjectHook(0x4EF7E0, &CPlayerPed_::ctor, PATCH_JUMP); - InjectHook(0x4EFB30, &CPlayerPed_::dtor, PATCH_JUMP); - InjectHook(0x4F3760, &CPlayerPed_::SetMoveAnim_, PATCH_JUMP); - InjectHook(0x4EFD90, &CPlayerPed_::ProcessControl_, PATCH_JUMP); - InjectHook(0x4F28A0, &CPlayerPed::ClearWeaponTarget, PATCH_JUMP); - InjectHook(0x4F3700, &CPlayerPed::AnnoyPlayerPed, PATCH_JUMP); - InjectHook(0x4F36C0, &CPlayerPed::GetPlayerInfoForThisPlayerPed, PATCH_JUMP); - InjectHook(0x4F2560, &CPlayerPed::MakeChangesForNewWeapon, PATCH_JUMP); - InjectHook(0x4F07C0, &CPlayerPed::ReApplyMoveAnims, PATCH_JUMP); - InjectHook(0x4F0880, &CPlayerPed::SetRealMoveAnim, PATCH_JUMP); - InjectHook(0x4F1810, &CPlayerPed::PlayerControlFighter, PATCH_JUMP); - InjectHook(0x4F1340, &CPlayerPed::RestoreSprintEnergy, PATCH_JUMP); - InjectHook(0x4F1380, &CPlayerPed::DoWeaponSmoothSpray, PATCH_JUMP); - InjectHook(0x4F36E0, &CPlayerPed::DoStuffToGoOnFire, PATCH_JUMP); - InjectHook(0x4F3350, &CPlayerPed::DoesTargetHaveToBeBroken, PATCH_JUMP); - InjectHook(0x4F31D0, &CPlayerPed::RunningLand, PATCH_JUMP); - InjectHook(0x4F2D00, &CPlayerPed::IsThisPedAttackingPlayer, PATCH_JUMP); - InjectHook(0x4F1CF0, &CPlayerPed::PlayerControlSniper, PATCH_JUMP); - InjectHook(0x4F2310, &CPlayerPed::ProcessWeaponSwitch, PATCH_JUMP); - InjectHook(0x4F1DF0, &CPlayerPed::PlayerControlM16, PATCH_JUMP); - InjectHook(0x4F3460, &CPlayerPed::KeepAreaAroundPlayerClear, PATCH_JUMP); - InjectHook(0x4F1970, &CPlayerPed::PlayerControl1stPersonRunAround, PATCH_JUMP); - InjectHook(0x4F1EF0, &CPlayerPed::ProcessPlayerWeapon, PATCH_JUMP); - InjectHook(0x4F2640, &CPlayerPed::ProcessAnimGroups, PATCH_JUMP); -ENDPATCHES diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index d3a67a57..681c6b1a 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Game.h" #include "General.h" #include "World.h" @@ -1180,16 +1180,3 @@ CPopulation::ManagePopulation(void) } } } - -STARTPATCHES - InjectHook(0x4F3770, &CPopulation::Initialise, PATCH_JUMP); - InjectHook(0x4F5780, &CPopulation::ChooseGangOccupation, PATCH_JUMP); - InjectHook(0x4F6200, &CPopulation::DealWithZoneChange, PATCH_JUMP); - InjectHook(0x4F6010, &CPopulation::FindCollisionZoneForCoors, PATCH_JUMP); - InjectHook(0x4F6410, &CPopulation::PedCreationDistMultiplier, PATCH_JUMP); - InjectHook(0x4F5280, &CPopulation::AddPed, PATCH_JUMP); - InjectHook(0x4F4470, &CPopulation::ConvertToRealObject, PATCH_JUMP); - InjectHook(0x4F4690, &CPopulation::TestRoomForDummyObject, PATCH_JUMP); - InjectHook(0x4F45A0, &CPopulation::ConvertToDummyObject, PATCH_JUMP); - InjectHook(0x4F4410, &CPopulation::ConvertAllObjectsToDummyObjects, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Antennas.cpp b/src/render/Antennas.cpp index d564c196..452069a0 100644 --- a/src/render/Antennas.cpp +++ b/src/render/Antennas.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Antennas.h" CAntenna CAntennas::aAntennas[NUMANTENNAS]; @@ -123,17 +123,3 @@ CAntenna::Update(CVector dir, CVector basepos) pos[i] = newpos; } } - -STARTPATCHES - InjectHook(0x4F64D0, &CAntennas::Init, PATCH_JUMP); - InjectHook(0x4F6550, &CAntennas::Update, PATCH_JUMP); - InjectHook(0x4F66C0, &CAntennas::RegisterOne, PATCH_JUMP); - InjectHook(0x4F6590, &CAntennas::Render, PATCH_JUMP); - InjectHook(0x4F6830, &CAntenna::Update, PATCH_JUMP); - - // give to cheetah for testing -// Patch(0x535B50+1, 105); -// Patch(0x535B57+7, -0.84); -// Patch(0x535B74+7, 0.78); -// Patch(0x535B69+7, 0.24); -ENDPATCHES diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 02035896..58dc3f93 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Sprite.h" #include "Sprite2d.h" #include "General.h" @@ -430,12 +430,3 @@ CClouds::RenderHorizon(void) CSprite2d::DrawRect(CRect(0, z1, SCREEN_WIDTH, z2), ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop); } - -STARTPATCHES - InjectHook(0x4F6C10, CClouds::Init, PATCH_JUMP); - InjectHook(0x4F6CA0, CClouds::Shutdown, PATCH_JUMP); - InjectHook(0x4F6CE0, CClouds::Update, PATCH_JUMP); - InjectHook(0x4F6D90, CClouds::Render, PATCH_JUMP); - InjectHook(0x4F7F00, CClouds::RenderBackground, PATCH_JUMP); - InjectHook(0x4F85F0, CClouds::RenderHorizon, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Console.cpp b/src/render/Console.cpp index bfdb2701..5ae5d763 100644 --- a/src/render/Console.cpp +++ b/src/render/Console.cpp @@ -1,6 +1,6 @@ #include "common.h" #include -#include "patcher.h" + #include "Console.h" #include "Font.h" #include "Timer.h" diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index d70f70d6..b21e087b 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "General.h" #include "TxdStore.h" @@ -572,17 +572,3 @@ CRegisteredCorona::Update(void) firstUpdate = false; registeredThisFrame = false; } - -STARTPATCHES - InjectHook(0x4F9F90, CCoronas::Init, PATCH_JUMP); - InjectHook(0x4FA050, CCoronas::Shutdown, PATCH_JUMP); - InjectHook(0x4F8EC0, CCoronas::Update, PATCH_JUMP); - InjectHook(0x4FA0E0, (void (*)(uint32, uint8, uint8, uint8, uint8, const CVector&, float, float, RwTexture*, int8, uint8, uint8, uint8, float))CCoronas::RegisterCorona, PATCH_JUMP); - InjectHook(0x4FA080, (void (*)(uint32, uint8, uint8, uint8, uint8, const CVector&, float, float, uint8, int8, uint8, uint8, uint8, float))CCoronas::RegisterCorona, PATCH_JUMP); - InjectHook(0x4FA2D0, CCoronas::UpdateCoronaCoors, PATCH_JUMP); - InjectHook(0x4F8FB0, CCoronas::Render, PATCH_JUMP); - InjectHook(0x4F9B40, CCoronas::RenderReflections, PATCH_JUMP); - InjectHook(0x4FA380, CCoronas::DoSunAndMoon, PATCH_JUMP); - - InjectHook(0x4F8C40, &CRegisteredCorona::Update, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Credits.cpp b/src/render/Credits.cpp index 25f7bbcf..dc0b0252 100644 --- a/src/render/Credits.cpp +++ b/src/render/Credits.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Timer.h" #include "Font.h" #include "Frontend.h" @@ -497,13 +497,3 @@ bool CCredits::AreCreditsDone(void) { return !bCreditsGoing; } - -STARTPATCHES - InjectHook(0x4FE7A0, CCredits::Init, PATCH_JUMP); - InjectHook(0x4FE760, CCredits::Start, PATCH_JUMP); - InjectHook(0x4FE780, CCredits::Stop, PATCH_JUMP); - InjectHook(0x4FE790, CCredits::AreCreditsDone, PATCH_JUMP); - InjectHook(0x4FADF0, CCredits::Render, PATCH_JUMP); - InjectHook(0x4FE710, CCredits::PrintCreditSpace, PATCH_JUMP); - InjectHook(0x4FE620, CCredits::PrintCreditText, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Draw.cpp b/src/render/Draw.cpp index dcbb6342..b31cc624 100644 --- a/src/render/Draw.cpp +++ b/src/render/Draw.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Draw.h" #include "Frontend.h" #include "Camera.h" @@ -66,10 +66,3 @@ CDraw::SetFOV(float fov) ms_fFOV = fov; #endif } - -STARTPATCHES - InjectHook(0x4FE7B0, CDraw::SetFOV, PATCH_JUMP); - - Nop(0x46B618, 2); - Patch(0x5F0A64, 1.3333334f); -ENDPATCHES diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index e2899532..e068747e 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "main.h" -#include "patcher.h" + #include "Entity.h" #include "Fluff.h" #include "Camera.h" @@ -864,31 +864,3 @@ void CDigitalClock::Render() CSprite::FlushSpriteBuffer(); } } - -STARTPATCHES -InjectHook(0x4FF290, &CMovingThing::Update, PATCH_JUMP); -InjectHook(0x4FF320, &CMovingThing::AddToList, PATCH_JUMP); -InjectHook(0x4FF340, &CMovingThing::RemoveFromList, PATCH_JUMP); - -InjectHook(0x4FE7C0, &CMovingThings::Init, PATCH_JUMP); -InjectHook(0x4FF020, &CMovingThings::Shutdown, PATCH_JUMP); -InjectHook(0x4FF0D0, &CMovingThings::Update, PATCH_JUMP); -InjectHook(0x4FF210, &CMovingThings::Render, PATCH_JUMP); - -InjectHook(0x4FF360, &FindTunnelMessage, PATCH_JUMP); -InjectHook(0x4FF390, &FindBridgeMessage, PATCH_JUMP); -InjectHook(0x4FF3C0, &FindTimeMessage, PATCH_JUMP); -InjectHook(0x4FF450, &FindDigitalClockMessage, PATCH_JUMP); - -InjectHook(0x4FF610, &CScrollBar::Init, PATCH_JUMP); -InjectHook(0x4FF6E0, &CScrollBar::Update, PATCH_JUMP); -InjectHook(0x4FFCE0, &CScrollBar::Render, PATCH_JUMP); - -InjectHook(0x5000D0, &CTowerClock::Init, PATCH_JUMP); -InjectHook(0x500130, &CTowerClock::Update, PATCH_JUMP); -InjectHook(0x5001D0, &CTowerClock::Render, PATCH_JUMP); - -InjectHook(0x5004F0, &CDigitalClock::Init, PATCH_JUMP); -InjectHook(0x500550, &CDigitalClock::Update, PATCH_JUMP); -InjectHook(0x5005F0, &CDigitalClock::Render, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Font.cpp b/src/render/Font.cpp index ba4c4301..14a678b8 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Sprite2d.h" #include "TxdStore.h" #include "Font.h" @@ -589,48 +589,3 @@ CFont::character_code(uint8 c) return c; return foreign_table[c-128]; } - -STARTPATCHES - - InjectHook(0x500A40, CFont::Initialise, PATCH_JUMP); - InjectHook(0x500BA0, CFont::Shutdown, PATCH_JUMP); - InjectHook(0x500BE0, CFont::InitPerFrame, PATCH_JUMP); - InjectHook(0x500C30, CFont::PrintChar, PATCH_JUMP); - InjectHook(0x500F50, (void (*)(float, float, wchar*))CFont::PrintString, PATCH_JUMP); - InjectHook(0x501260, CFont::GetNumberLines, PATCH_JUMP); - InjectHook(0x5013B0, CFont::GetTextRect, PATCH_JUMP); - InjectHook(0x501730, (void (*)(float, float, wchar*, wchar*, float))CFont::PrintString, PATCH_JUMP); - InjectHook(0x5017E0, CFont::GetCharacterWidth, PATCH_JUMP); - InjectHook(0x501840, CFont::GetCharacterSize, PATCH_JUMP); - InjectHook(0x5018A0, CFont::GetStringWidth, PATCH_JUMP); - InjectHook(0x501960, CFont::GetNextSpace, PATCH_JUMP); - InjectHook(0x5019A0, CFont::ParseToken, PATCH_JUMP); - InjectHook(0x501B50, CFont::DrawFonts, PATCH_JUMP); - InjectHook(0x501E80, CFont::character_code, PATCH_JUMP); - - InjectHook(0x501B80, CFont::SetScale, PATCH_JUMP); - InjectHook(0x501BA0, CFont::SetSlantRefPoint, PATCH_JUMP); - InjectHook(0x501BC0, CFont::SetSlant, PATCH_JUMP); - InjectHook(0x501BD0, CFont::SetColor, PATCH_JUMP); - InjectHook(0x501C60, CFont::SetJustifyOn, PATCH_JUMP); - InjectHook(0x501C80, CFont::SetJustifyOff, PATCH_JUMP); - InjectHook(0x501C90, CFont::SetCentreOn, PATCH_JUMP); - InjectHook(0x501CB0, CFont::SetCentreOff, PATCH_JUMP); - InjectHook(0x501CC0, CFont::SetWrapx, PATCH_JUMP); - InjectHook(0x501CD0, CFont::SetCentreSize, PATCH_JUMP); - InjectHook(0x501CE0, CFont::SetBackgroundOn, PATCH_JUMP); - InjectHook(0x501CF0, CFont::SetBackgroundOff, PATCH_JUMP); - InjectHook(0x501D00, CFont::SetBackgroundColor, PATCH_JUMP); - InjectHook(0x501D30, CFont::SetBackGroundOnlyTextOn, PATCH_JUMP); - InjectHook(0x501D40, CFont::SetBackGroundOnlyTextOff, PATCH_JUMP); - InjectHook(0x501D50, CFont::SetRightJustifyOn, PATCH_JUMP); - InjectHook(0x501D70, CFont::SetRightJustifyOff, PATCH_JUMP); - InjectHook(0x501D90, CFont::SetPropOff, PATCH_JUMP); - InjectHook(0x501DA0, CFont::SetPropOn, PATCH_JUMP); - InjectHook(0x501DB0, CFont::SetFontStyle, PATCH_JUMP); - InjectHook(0x501DC0, CFont::SetRightJustifyWrap, PATCH_JUMP); - InjectHook(0x501DD0, CFont::SetAlphaFade, PATCH_JUMP); - InjectHook(0x501DE0, CFont::SetDropColor, PATCH_JUMP); - InjectHook(0x501E70, CFont::SetDropShadowPosition, PATCH_JUMP); - -ENDPATCHES diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index ac6c1728..33e22c87 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Glass.h" #include "Timer.h" #include "Object.h" @@ -708,26 +708,3 @@ CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point) object->bGlassCracked = true; } } - -STARTPATCHES - InjectHook(0x501F20, CGlass::Init, PATCH_JUMP); - InjectHook(0x502050, CGlass::Update, PATCH_JUMP); - InjectHook(0x502080, &CFallingGlassPane::Update, PATCH_JUMP); - InjectHook(0x502350, CGlass::Render, PATCH_JUMP); - InjectHook(0x502490, CGlass::FindFreePane, PATCH_JUMP); - InjectHook(0x5024C0, &CFallingGlassPane::Render, PATCH_JUMP); - InjectHook(0x502AC0, CGlass::GeneratePanesForWindow, PATCH_JUMP); - InjectHook(0x5033F0, CGlass::AskForObjectToBeRenderedInGlass, PATCH_JUMP); - InjectHook(0x503420, CGlass::RenderEntityInGlass, PATCH_JUMP); - InjectHook(0x503C90, CGlass::CalcAlphaWithNormal, PATCH_JUMP); - InjectHook(0x503D60, CGlass::RenderHiLightPolys, PATCH_JUMP); - InjectHook(0x503DE0, CGlass::RenderShatteredPolys, PATCH_JUMP); - InjectHook(0x503E70, CGlass::RenderReflectionPolys, PATCH_JUMP); - InjectHook(0x503F10, CGlass::WindowRespondsToCollision, PATCH_JUMP); - InjectHook(0x504630, CGlass::WindowRespondsToSoftCollision, PATCH_JUMP); - InjectHook(0x504670, CGlass::WasGlassHitByBullet, PATCH_JUMP); - InjectHook(0x504790, CGlass::WindowRespondsToExplosion, PATCH_JUMP); - //InjectHook(0x504880, `global constructor keyed to'glass.cpp, PATCH_JUMP); - //InjectHook(0x5048D0, CFallingGlassPane::~CFallingGlassPane, PATCH_JUMP); - //InjectHook(0x5048E0, CFallingGlassPane::CFallingGlassPane, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 5bcdd450..03ffe59a 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Camera.h" #include "DMAudio.h" #include "Clock.h" @@ -1483,18 +1483,3 @@ void CHud::Shutdown() int HudTXD = CTxdStore::FindTxdSlot("hud"); CTxdStore::RemoveTxdSlot(HudTXD); } - -STARTPATCHES - InjectHook(0x5052A0, &CHud::Draw, PATCH_JUMP); - InjectHook(0x509030, &CHud::DrawAfterFade, PATCH_JUMP); - InjectHook(0x504F90, &CHud::GetRidOfAllHudMessages, PATCH_JUMP); - InjectHook(0x5048F0, &CHud::Initialise, PATCH_JUMP); - InjectHook(0x504CC0, &CHud::ReInitialise, PATCH_JUMP); - InjectHook(0x50A250, &CHud::SetBigMessage, PATCH_JUMP); - InjectHook(0x5051E0, &CHud::SetHelpMessage, PATCH_JUMP); - InjectHook(0x50A210, &CHud::SetMessage, PATCH_JUMP); - InjectHook(0x50A320, &CHud::SetPagerMessage, PATCH_JUMP); - InjectHook(0x505290, &CHud::SetVehicleName, PATCH_JUMP); - InjectHook(0x5051D0, &CHud::SetZoneName, PATCH_JUMP); - InjectHook(0x504C50, &CHud::Shutdown, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Instance.cpp b/src/render/Instance.cpp index 775341be..be6d73d6 100644 --- a/src/render/Instance.cpp +++ b/src/render/Instance.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Instance.h" void @@ -7,14 +7,3 @@ CInstance::Shutdown() { GetMatrix().Detach(); } - -class CInstance_ : public CInstance -{ -public: - void dtor() { CInstance::~CInstance(); } -}; - -STARTPATCHES - InjectHook(0x50BE90, &CInstance_::dtor, PATCH_JUMP); - InjectHook(0x50B850, &CInstance::Shutdown, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Lines.cpp b/src/render/Lines.cpp index ea433048..b5c85149 100644 --- a/src/render/Lines.cpp +++ b/src/render/Lines.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Lines.h" diff --git a/src/render/MBlur.cpp b/src/render/MBlur.cpp index d15fa422..c3a25bce 100644 --- a/src/render/MBlur.cpp +++ b/src/render/MBlur.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "RwHelper.h" #include "Camera.h" #include "MBlur.h" @@ -213,11 +213,3 @@ CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); } - -STARTPATCHES - InjectHook(0x50AE40, CMBlur::MotionBlurOpen, PATCH_JUMP); - InjectHook(0x50B170, CMBlur::MotionBlurClose, PATCH_JUMP); - InjectHook(0x50A800, CMBlur::CreateImmediateModeData, PATCH_JUMP); - InjectHook(0x50AD70, CMBlur::MotionBlurRender, PATCH_JUMP); - InjectHook(0x50A9C0, CMBlur::OverlayRender, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index eb188128..0388e779 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "Timer.h" #include "TxdStore.h" @@ -1849,19 +1849,3 @@ void CParticle::AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatr 0.3f, color, 0, 0, 0, 0); } } - -STARTPATCHES - //InjectHook(0x50C410, &CParticle::ctor, PATCH_JUMP); - //InjectHook(0x50C420, &CParticle::dtor, PATCH_JUMP); - InjectHook(0x50C430, CParticle::ReloadConfig, PATCH_JUMP); - InjectHook(0x50C570, CParticle::Initialise, PATCH_JUMP); - InjectHook(0x50CF40, CParticle::Shutdown, PATCH_JUMP); - //InjectHook(0x50D140, CParticle::AddParticle, PATCH_JUMP); - InjectHook(0x50D190, (CParticle *(*)(tParticleType, CVector const&, CVector const&, CEntity*, float, RwRGBA const&, int, int, int, int))CParticle::AddParticle, PATCH_JUMP); - InjectHook(0x50DCF0, CParticle::Update, PATCH_JUMP); - InjectHook(0x50EE20, CParticle::Render, PATCH_JUMP); - InjectHook(0x50F6E0, CParticle::RemovePSystem, PATCH_JUMP); - InjectHook(0x50F720, CParticle::RemoveParticle, PATCH_JUMP); - InjectHook(0x50F760, CParticle::AddJetExplosion, PATCH_JUMP); - InjectHook(0x50FAA0, CParticle::AddYardieDoorSmoke, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/ParticleMgr.cpp b/src/render/ParticleMgr.cpp index 7a1804de..4bfb6380 100644 --- a/src/render/ParticleMgr.cpp +++ b/src/render/ParticleMgr.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "FileMgr.h" #include "ParticleMgr.h" @@ -242,9 +242,3 @@ void cParticleSystemMgr::LoadParticleData() lineEnd++; } } - -STARTPATCHES - InjectHook(0x50FCB0, &cParticleSystemMgr::ctor, PATCH_JUMP); - InjectHook(0x50FCD0, &cParticleSystemMgr::Initialise, PATCH_JUMP); - InjectHook(0x50FDF0, &cParticleSystemMgr::LoadParticleData, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/render/PlayerSkin.cpp b/src/render/PlayerSkin.cpp index 2cba45fe..94af1fd1 100644 --- a/src/render/PlayerSkin.cpp +++ b/src/render/PlayerSkin.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "PlayerSkin.h" #include "TxdStore.h" @@ -163,12 +163,3 @@ CPlayerSkin::RenderFrontendSkinEdit(void) SetAmbientColours(&AmbientColor); RpClumpRender(gpPlayerClump); } - -STARTPATCHES -InjectHook(0x59B9B0, &CPlayerSkin::Initialise, PATCH_JUMP); -InjectHook(0x59B9E0, &CPlayerSkin::Shutdown, PATCH_JUMP); -InjectHook(0x59B9F0, &CPlayerSkin::GetSkinTexture, PATCH_JUMP); -InjectHook(0x59BC70, &CPlayerSkin::BeginFrontendSkinEdit, PATCH_JUMP); -InjectHook(0x59BCB0, &CPlayerSkin::EndFrontendSkinEdit, PATCH_JUMP); -InjectHook(0x59BCE0, &CPlayerSkin::RenderFrontendSkinEdit, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp index 92a89582..55be40b2 100644 --- a/src/render/PointLights.cpp +++ b/src/render/PointLights.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Lights.h" #include "Camera.h" @@ -284,10 +284,3 @@ CPointLights::RenderFogEffect(void) } } } - -STARTPATCHES - InjectHook(0x510790, CPointLights::AddLight, PATCH_JUMP); - InjectHook(0x510960, CPointLights::GenerateLightsAffectingObject, PATCH_JUMP); - InjectHook(0x510C20, CPointLights::RemoveLightsAffectingObject, PATCH_JUMP); - InjectHook(0x510C30, CPointLights::RenderFogEffect, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/RenderBuffer.cpp b/src/render/RenderBuffer.cpp index 4225619f..6120dfe2 100644 --- a/src/render/RenderBuffer.cpp +++ b/src/render/RenderBuffer.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "RenderBuffer.h" int32 TempBufferVerticesStored; @@ -50,10 +50,3 @@ RenderBuffer::RenderStuffInBuffer(void) } ClearRenderBuffer(); } - -STARTPATCHES - InjectHook(0x517620, RenderBuffer::ClearRenderBuffer, PATCH_JUMP); - InjectHook(0x517640, RenderBuffer::StartStoring, PATCH_JUMP); - InjectHook(0x5176B0, RenderBuffer::StopStoring, PATCH_JUMP); - InjectHook(0x5177C0, RenderBuffer::RenderStuffInBuffer, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7b2f90e8..9c78853f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Lights.h" #include "ModelInfo.h" @@ -1207,40 +1207,3 @@ CRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset) if(reset) ReSetAmbientAndDirectionalColours(); } - -STARTPATCHES - InjectHook(0x4A7680, CRenderer::Init, PATCH_JUMP); - InjectHook(0x4A76A0, CRenderer::Shutdown, PATCH_JUMP); - - InjectHook(0x4A7B90, CRenderer::RenderOneRoad, PATCH_JUMP); - InjectHook(0x4A7BA0, CRenderer::RenderOneNonRoad, PATCH_JUMP); - InjectHook(0x4A7B20, CRenderer::RenderFirstPersonVehicle, PATCH_JUMP); - InjectHook(0x4A78B0, CRenderer::RenderRoads, PATCH_JUMP); - InjectHook(0x4A7930, CRenderer::RenderEverythingBarRoads, PATCH_JUMP); - InjectHook(0x4A7AA0, CRenderer::RenderVehiclesButNotBoats, PATCH_JUMP); - InjectHook(0x4A7AE0, CRenderer::RenderBoats, PATCH_JUMP); - InjectHook(0x4A7910, CRenderer::RenderFadingInEntities, PATCH_JUMP); - - InjectHook(0x4A9350, CRenderer::SetupEntityVisibility, PATCH_JUMP); - InjectHook(0x4A9920, CRenderer::SetupBigBuildingVisibility, PATCH_JUMP); - - InjectHook(0x4A76B0, CRenderer::ConstructRenderList, PATCH_JUMP); - InjectHook(0x4A7840, CRenderer::PreRender, PATCH_JUMP); - InjectHook(0x4A8970, CRenderer::ScanWorld, PATCH_JUMP); - InjectHook(0x4AA240, CRenderer::RequestObjectsInFrustum, PATCH_JUMP); - InjectHook(0x4A7F30, CRenderer::ScanSectorPoly, PATCH_JUMP); - InjectHook(0x4A9300, CRenderer::ScanBigBuildingList, PATCH_JUMP); - InjectHook(0x4A9BB0, CRenderer::ScanSectorList, PATCH_JUMP); - InjectHook(0x4A9E30, CRenderer::ScanSectorList_Priority, PATCH_JUMP); - InjectHook(0x4AA0A0, CRenderer::ScanSectorList_Subway, PATCH_JUMP); - InjectHook(0x4AA1D0, CRenderer::ScanSectorList_RequestModels, PATCH_JUMP); - - InjectHook(0x4AA940, CRenderer::SortBIGBuildings, PATCH_JUMP); - InjectHook(0x4AA990, CRenderer::SortBIGBuildingsForSectorList, PATCH_JUMP); - - InjectHook(0x4A9840, CRenderer::ShouldModelBeStreamed, PATCH_JUMP); - InjectHook(0x4AAA00, CRenderer::IsEntityCullZoneVisible, PATCH_JUMP); - InjectHook(0x4AAAA0, CRenderer::IsVehicleCullZoneVisible, PATCH_JUMP); - - InjectHook(0x4A7CF0, CRenderer::RemoveVehiclePedLights, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp index 65d8b2dd..31110046 100644 --- a/src/render/Rubbish.cpp +++ b/src/render/Rubbish.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "main.h" -#include "patcher.h" + #include "General.h" #include "Timer.h" #include "Weather.h" diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 56a93238..8685b93a 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "TxdStore.h" #include "Timer.h" @@ -1760,36 +1760,3 @@ CShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTextur 0, 128, 255, 128, 2048, 0.2f, 0); } - - -STARTPATCHES - InjectHook(0x512AB0, CShadows::Init, PATCH_JUMP); - InjectHook(0x512F20, CShadows::Shutdown, PATCH_JUMP); - InjectHook(0x512FD0, CShadows::AddPermanentShadow, PATCH_JUMP); - InjectHook(0x5130A0, CShadows::StoreStaticShadow, PATCH_JUMP); - InjectHook(0x513550, (void(*)(uint8, CVector *, float, float, float, float, int16, uint8, uint8, uint8))CShadows::StoreShadowToBeRendered, PATCH_JUMP); - InjectHook(0x513750, (void(*)(uint8, RwTexture *, CVector *, float, float, float, float, int16, uint8, uint8, uint8, float, bool, float))CShadows::StoreShadowToBeRendered, PATCH_JUMP); - InjectHook(0x513830, CShadows::StoreShadowForCar, PATCH_JUMP); - InjectHook(0x513A70, CShadows::StoreCarLightShadow, PATCH_JUMP); - InjectHook(0x513C50, CShadows::StoreShadowForPed, PATCH_JUMP); - InjectHook(0x513CB0, CShadows::StoreShadowForPedObject, PATCH_JUMP); - InjectHook(0x513E00, CShadows::StoreShadowForTree, PATCH_JUMP); - InjectHook(0x513E10, CShadows::StoreShadowForPole, PATCH_JUMP); - InjectHook(0x513FC0, CShadows::SetRenderModeForShadowType, PATCH_JUMP); - InjectHook(0x514010, CShadows::RenderStoredShadows, PATCH_JUMP); - InjectHook(0x5145F0, CShadows::RenderStaticShadows, PATCH_JUMP); - InjectHook(0x514910, CShadows::GeneratePolysForStaticShadow, PATCH_JUMP); - InjectHook(0x514C90, CShadows::CastShadowSectorList, PATCH_JUMP); - InjectHook(0x514E30, CShadows::CastShadowEntity, PATCH_JUMP); - InjectHook(0x516BE0, CShadows::UpdateStaticShadows, PATCH_JUMP); - InjectHook(0x516C40, CShadows::UpdatePermanentShadows, PATCH_JUMP); - InjectHook(0x516E70, &CStaticShadow::Free, PATCH_JUMP); - InjectHook(0x516EB0, CShadows::CalcPedShadowValues, PATCH_JUMP); - InjectHook(0x516F90, CShadows::RenderExtraPlayerShadows, PATCH_JUMP); - InjectHook(0x517570, CShadows::TidyUpShadows, PATCH_JUMP); - InjectHook(0x517810, CShadows::RenderIndicatorShadow, PATCH_JUMP); - //InjectHook(0x517900, &CPermanentShadow::CPermanentShadow, PATCH_JUMP); - //InjectHook(0x517910, &CStaticShadow::CStaticShadow, PATCH_JUMP); - //InjectHook(0x517920, &CPolyBunch::CPolyBunch, PATCH_JUMP); - //InjectHook(0x517940, &CStoredShadow::CStoredShadow, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp index 41ee5d1d..0848796b 100644 --- a/src/render/Skidmarks.cpp +++ b/src/render/Skidmarks.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "TxdStore.h" #include "Timer.h" diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index 9189a7c2..16057420 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "SpecialFX.h" #include "RenderBuffer.h" #include "Timer.h" @@ -1151,32 +1151,3 @@ CSpecialParticleStuff::UpdateBoatFoamAnimation(CMatrix* pMatrix) dZ = 2.0f; } } - -STARTPATCHES - InjectHook(0x518DE0, &CBulletTraces::Init, PATCH_JUMP); - InjectHook(0x518E90, &CBulletTraces::AddTrace, PATCH_JUMP); - InjectHook(0x518F20, &CBulletTraces::Render, PATCH_JUMP); - InjectHook(0x519240, &CBulletTraces::Update, PATCH_JUMP); - - InjectHook(0x51B070, &C3dMarker::AddMarker, PATCH_JUMP); - InjectHook(0x51B170, &C3dMarker::DeleteMarkerObject, PATCH_JUMP); - InjectHook(0x51B1B0, &C3dMarker::Render, PATCH_JUMP); - InjectHook(0x51B2B0, C3dMarkers::Init, PATCH_JUMP); - InjectHook(0x51B480, C3dMarkers::PlaceMarker, PATCH_JUMP); - InjectHook(0x51BB80, C3dMarkers::PlaceMarkerSet, PATCH_JUMP); - InjectHook(0x51B400, C3dMarkers::Render, PATCH_JUMP); - InjectHook(0x51B3B0, C3dMarkers::Shutdown, PATCH_JUMP); - - InjectHook(0x5197A0, CBrightLights::Init, PATCH_JUMP); - InjectHook(0x51A410, CBrightLights::RegisterOne, PATCH_JUMP); - InjectHook(0x5197B0, CBrightLights::Render, PATCH_JUMP); - InjectHook(0x51A3B0, CBrightLights::RenderOutGeometryBuffer, PATCH_JUMP); - - InjectHook(0x51A5A0, CShinyTexts::Init, PATCH_JUMP); - InjectHook(0x51AAB0, CShinyTexts::RegisterOne, PATCH_JUMP); - InjectHook(0x51A5B0, CShinyTexts::Render, PATCH_JUMP); - InjectHook(0x51AA50, CShinyTexts::RenderOutGeometryBuffer, PATCH_JUMP); - - InjectHook(0x51AF70, CMoneyMessages::Init, PATCH_JUMP); - InjectHook(0x51B030, CMoneyMessages::Render, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 57ab8f14..30eaf840 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Draw.h" #include "Camera.h" @@ -593,19 +593,3 @@ CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(float x, float y, float w if(nSpriteBufferIndex >= SPRITEBUFFERSIZE) FlushSpriteBuffer(); } - -STARTPATCHES - InjectHook(0x51C4A0, CSprite::CalcHorizonCoors, PATCH_JUMP); - InjectHook(0x51C3A0, CSprite::CalcScreenCoors, PATCH_JUMP); - InjectHook(0x51C590, CSprite::InitSpriteBuffer, PATCH_JUMP); - InjectHook(0x51C5B0, CSprite::InitSpriteBuffer2D, PATCH_JUMP); - InjectHook(0x51C520, CSprite::FlushSpriteBuffer, PATCH_JUMP); - InjectHook(0x51C960, CSprite::RenderOneXLUSprite, PATCH_JUMP); - InjectHook(0x51D110, CSprite::RenderOneXLUSprite_Rotate_Aspect, PATCH_JUMP); - InjectHook(0x51C5D0, CSprite::RenderBufferedOneXLUSprite, PATCH_JUMP); - InjectHook(0x51D5B0, CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension, PATCH_JUMP); - InjectHook(0x51CCD0, CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect, PATCH_JUMP); - InjectHook(0x51D9E0, CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours, PATCH_JUMP); - InjectHook(0x51E3C0, CSprite::RenderBufferedOneXLUSprite2D, PATCH_JUMP); - InjectHook(0x51E490, CSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Sprite2d.cpp b/src/render/Sprite2d.cpp index 655fd841..52b85018 100644 --- a/src/render/Sprite2d.cpp +++ b/src/render/Sprite2d.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Draw.h" #include "Camera.h" @@ -474,37 +474,3 @@ void CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD); } - -STARTPATCHES -#define C4 const CRGBA&, const CRGBA&, const CRGBA&, const CRGBA& -#define F8 float, float, float, float, float, float, float, float - - InjectHook(0x51EA20, CSprite2d::SetRecipNearClip, PATCH_JUMP); - InjectHook(0x51EAE0, CSprite2d::InitPerFrame, PATCH_JUMP); - InjectHook(0x51EB70, CSprite2d::GetBank, PATCH_JUMP); - InjectHook(0x51EBC0, CSprite2d::AddSpriteToBank, PATCH_JUMP); - InjectHook(0x51EC50, CSprite2d::DrawBank, PATCH_JUMP); - - InjectHook(0x51EA00, &CSprite2d::Delete, PATCH_JUMP); - InjectHook(0x51F950, &CSprite2d::SetRenderState, PATCH_JUMP); - InjectHook(0x51EA40, (void (CSprite2d::*)(const char*))&CSprite2d::SetTexture, PATCH_JUMP); - InjectHook(0x51EA70, (void (CSprite2d::*)(const char*,const char*))&CSprite2d::SetTexture, PATCH_JUMP); - InjectHook(0x51EAA0, &CSprite2d::SetAddressing, PATCH_JUMP); - - InjectHook(0x51EE90, (void (*)(const CRect&, C4, uint32))CSprite2d::SetVertices, PATCH_JUMP); - InjectHook(0x51F220, (void (*)(const CRect&, C4, F8))CSprite2d::SetVertices, PATCH_JUMP); - InjectHook(0x51F070, (void (*)(F8, C4))CSprite2d::SetVertices, PATCH_JUMP); - InjectHook(0x51F3E0, (void (*)(int, float*, float*, const CRGBA&))CSprite2d::SetVertices, PATCH_JUMP); - InjectHook(0x51F490, CSprite2d::SetMaskVertices, PATCH_JUMP); - InjectHook(0x51F720, (void (*)(RwIm2DVertex*, const CRect&, C4, F8))CSprite2d::SetVertices, PATCH_JUMP); - - InjectHook(0x51ECE0, (void (CSprite2d::*)(float, float, float, float, const CRGBA &))&CSprite2d::Draw, PATCH_JUMP); - InjectHook(0x51ED50, (void (CSprite2d::*)(const CRect &, const CRGBA &))&CSprite2d::Draw, PATCH_JUMP); - InjectHook(0x51ED90, (void (CSprite2d::*)(const CRect &, const CRGBA &, F8))&CSprite2d::Draw, PATCH_JUMP); - InjectHook(0x51EDF0, (void (CSprite2d::*)(const CRect &, C4))&CSprite2d::Draw, PATCH_JUMP); - InjectHook(0x51EE40, (void (CSprite2d::*)(F8, const CRGBA &))&CSprite2d::Draw, PATCH_JUMP); - - InjectHook(0x51F970, (void (*)(const CRect&, const CRGBA&))CSprite2d::DrawRect, PATCH_JUMP); - InjectHook(0x51FA00, (void (*)(const CRect&, C4))CSprite2d::DrawRect, PATCH_JUMP); - InjectHook(0x51FA80, CSprite2d::DrawRectXLU, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp index 6e24a76e..e47015a0 100644 --- a/src/render/Timecycle.cpp +++ b/src/render/Timecycle.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "Clock.h" #include "Weather.h" @@ -315,8 +315,3 @@ CTimeCycle::Update(void) else m_FogReduction = max(m_FogReduction-1, 0); } - -STARTPATCHES - InjectHook(0x4ABAE0, CTimeCycle::Initialise, PATCH_JUMP); - InjectHook(0x4ABF40, CTimeCycle::Update, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/WaterCannon.cpp b/src/render/WaterCannon.cpp index e848fb43..1a9b983f 100644 --- a/src/render/WaterCannon.cpp +++ b/src/render/WaterCannon.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "WaterCannon.h" #include "Vector.h" #include "General.h" @@ -304,17 +304,3 @@ void CWaterCannons::Render(void) aCannons[i].Render(); } } - -STARTPATCHES - InjectHook(0x521A30, &CWaterCannon::Init, PATCH_JUMP); - InjectHook(0x521B80, &CWaterCannon::Update_OncePerFrame, PATCH_JUMP); - InjectHook(0x521CC0, &CWaterCannon::Update_NewInput, PATCH_JUMP); - InjectHook(0x521D30, &CWaterCannon::Render, PATCH_JUMP); - InjectHook(0x5220B0, &CWaterCannon::PushPeds, PATCH_JUMP); - InjectHook(0x522440, CWaterCannons::Init, PATCH_JUMP); - InjectHook(0x522470, CWaterCannons::UpdateOne, PATCH_JUMP); - InjectHook(0x522510, CWaterCannons::Update, PATCH_JUMP); - InjectHook(0x522550, CWaterCannons::Render, PATCH_JUMP); - //InjectHook(0x522B40, `global constructor keyed to'watercannon.cpp, PATCH_JUMP); - //InjectHook(0x522B60, CWaterCannon::CWaterCannon, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index d5a54742..ad0b3ec4 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -21,7 +21,7 @@ #include "RenderBuffer.h" #include #include "WaterLevel.h" -#include "patcher.h" + float TEXTURE_ADDU; float TEXTURE_ADDV; @@ -1234,22 +1234,3 @@ CWaterLevel::FreeBoatWakeArray() nGeomUsed = 0; } - -STARTPATCHES - InjectHook(0x554EA0, &CWaterLevel::Initialise, PATCH_JUMP); - InjectHook(0x554FE0, &CWaterLevel::Shutdown, PATCH_JUMP); - InjectHook(0x555010, &CWaterLevel::CreateWavyAtomic, PATCH_JUMP); - InjectHook(0x5552A0, &CWaterLevel::DestroyWavyAtomic, PATCH_JUMP); - InjectHook(0x5552C0, (bool (*)(float,float,float,float*,bool))&CWaterLevel::GetWaterLevel, PATCH_JUMP); - InjectHook(0x555440, &CWaterLevel::GetWaterLevelNoWaves, PATCH_JUMP); - InjectHook(0x5554E0, &CWaterLevel::RenderWater, PATCH_JUMP); - InjectHook(0x556C30, &CWaterLevel::RenderOneFlatSmallWaterPoly, PATCH_JUMP); - InjectHook(0x556E80, &CWaterLevel::RenderOneFlatLargeWaterPoly, PATCH_JUMP); - InjectHook(0x5570D0, &CWaterLevel::RenderOneFlatHugeWaterPoly, PATCH_JUMP); - InjectHook(0x557320, &CWaterLevel::RenderOneFlatExtraHugeWaterPoly, PATCH_JUMP); - InjectHook(0x557570, &CWaterLevel::RenderOneWavySector, PATCH_JUMP); - InjectHook(0x557C30, &CWaterLevel::CalcDistanceToWater, PATCH_JUMP); - InjectHook(0x557EA0, &CWaterLevel::RenderAndEmptyRenderBuffer, PATCH_JUMP); - InjectHook(0x557F00, &CWaterLevel::AllocateBoatWakeArray, PATCH_JUMP); - InjectHook(0x5581C0, &CWaterLevel::FreeBoatWakeArray, PATCH_JUMP); -ENDPATCHES diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index 1aa6be82..8bc544c6 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Weather.h" #include "Camera.h" diff --git a/src/rw/ClumpRead.cpp b/src/rw/ClumpRead.cpp index 0bf62f32..5f50f52d 100644 --- a/src/rw/ClumpRead.cpp +++ b/src/rw/ClumpRead.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + struct rpGeometryList { @@ -222,9 +222,3 @@ RpClumpGtaCancelStream(void) rwFrameListDeinitialize(&gFrameList); gFrameList.numFrames = 0; } - -STARTPATCHES - InjectHook(0x526060, RpClumpGtaStreamRead1, PATCH_JUMP); - InjectHook(0x526180, RpClumpGtaStreamRead2, PATCH_JUMP); - InjectHook(0x5262D0, RpClumpGtaCancelStream, PATCH_JUMP); -ENDPATCHES diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp index 6e9edbed..9c5d4f22 100644 --- a/src/rw/Lights.cpp +++ b/src/rw/Lights.cpp @@ -1,7 +1,7 @@ #include "common.h" #include #include -#include "patcher.h" + #include "Lights.h" #include "Timecycle.h" #include "Coronas.h" @@ -11,7 +11,7 @@ RpLight *pAmbient; RpLight *pDirect; -RpLight *pExtraDirectionals[] = { nil }; +RpLight *pExtraDirectionals[4] = { nil }; int LightStrengths[4]; int NumExtraDirLightsInWorld; @@ -312,22 +312,3 @@ SetAmbientColours(RwRGBAReal *color) { RpLightSetColor(pAmbient, color); } - - -STARTPATCHES - InjectHook(0x526510, SetLightsWithTimeOfDayColour, PATCH_JUMP); - InjectHook(0x5269A0, LightsCreate, PATCH_JUMP); - InjectHook(0x526B40, LightsDestroy, PATCH_JUMP); - InjectHook(0x526C10, WorldReplaceNormalLightsWithScorched, PATCH_JUMP); - InjectHook(0x526C50, WorldReplaceScorchedLightsWithNormal, PATCH_JUMP); - InjectHook(0x526C70, AddAnExtraDirectionalLight, PATCH_JUMP); - InjectHook(0x526DB0, RemoveExtraDirectionalLights, PATCH_JUMP); - InjectHook(0x526DE0, SetAmbientAndDirectionalColours, PATCH_JUMP); - InjectHook(0x526E60, SetBrightMarkerColours, PATCH_JUMP); - InjectHook(0x526F10, ReSetAmbientAndDirectionalColours, PATCH_JUMP); - InjectHook(0x526F40, DeActivateDirectional, PATCH_JUMP); - InjectHook(0x526F50, ActivateDirectional, PATCH_JUMP); - InjectHook(0x526F60, (void (*)(void))SetAmbientColours, PATCH_JUMP); - InjectHook(0x526F80, SetAmbientColoursForPedsCarsAndObjects, PATCH_JUMP); - InjectHook(0x526FA0, (void (*)(RwRGBAReal*))SetAmbientColours, PATCH_JUMP); -ENDPATCHES diff --git a/src/rw/NodeName.cpp b/src/rw/NodeName.cpp index b3477dba..d62884f7 100644 --- a/src/rw/NodeName.cpp +++ b/src/rw/NodeName.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "NodeName.h" static int32 gPluginOffset; diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 6bb78e7b..e5c4ceae 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -1,6 +1,6 @@ #define WITHD3D #include "common.h" -#include "patcher.h" + #include "Timecycle.h" #include "skeleton.h" #if defined(RWLIBS) && !defined(FINAL) @@ -393,11 +393,3 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer) WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); } WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); } #endif - -STARTPATCHES - //InjectHook(0x526450, GetFirstObjectCallback, PATCH_JUMP); - InjectHook(0x526460, GetFirstObject, PATCH_JUMP); - InjectHook(0x527170, CameraSize, PATCH_JUMP); - InjectHook(0x527340, CameraDestroy, PATCH_JUMP); - InjectHook(0x5273B0, CameraCreate, PATCH_JUMP); -ENDPATCHES diff --git a/src/rw/RwMatFX.cpp b/src/rw/RwMatFX.cpp index c4fe0b0b..1e64c560 100644 --- a/src/rw/RwMatFX.cpp +++ b/src/rw/RwMatFX.cpp @@ -2,7 +2,9 @@ #define WITHD3D #include "common.h" +#ifdef RWLIBS #include "patcher.h" +#endif struct MatFXNothing { int pad[5]; int effect; }; @@ -216,14 +218,11 @@ _rpMatFXD3D8AtomicMatFXEnvRender_ps2(RxD3D8InstanceData *inst, int flags, int se RwD3D8SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); } - -STARTPATCHES #ifdef RWLIBS +STARTPATCHES InjectHook((uintptr)&_rpMatFXD3D8AtomicMatFXEnvRender, _rpMatFXD3D8AtomicMatFXEnvRender_ps2, PATCH_JUMP); -#else - InjectHook(0x5CF6C0, _rpMatFXD3D8AtomicMatFXEnvRender_ps2, PATCH_JUMP); -#endif ENDPATCHES +#endif #endif diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 64fea20f..258d520d 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -6,7 +6,7 @@ #define WITHWINDOWS #include "common.h" #include "win.h" -#include "patcher.h" + #include "Timer.h" #ifdef GTA_PC #include "FileMgr.h" @@ -349,17 +349,3 @@ CreateTxdImageForVideoCard() return true; } #endif // GTA_PC - -STARTPATCHES - InjectHook(0x592380, RwTextureGtaStreamRead, PATCH_JUMP); - InjectHook(0x5924A0, RwTexDictionaryGtaStreamRead, PATCH_JUMP); - InjectHook(0x592550, RwTexDictionaryGtaStreamRead1, PATCH_JUMP); - InjectHook(0x592650, RwTexDictionaryGtaStreamRead2, PATCH_JUMP); - - InjectHook(0x5926C0, ReadVideoCardCapsFile, PATCH_JUMP); - InjectHook(0x592740, CheckVideoCardCaps, PATCH_JUMP); - InjectHook(0x5927D0, WriteVideoCardCapsFile, PATCH_JUMP); - InjectHook(0x592880, ConvertingTexturesScreen, PATCH_JUMP); - InjectHook(0x592BF0, DealWithTxdWriteError, PATCH_JUMP); - InjectHook(0x592C70, CreateTxdImageForVideoCard, PATCH_JUMP); -ENDPATCHES diff --git a/src/rw/TxdStore.cpp b/src/rw/TxdStore.cpp index d640d99d..51d018f6 100644 --- a/src/rw/TxdStore.cpp +++ b/src/rw/TxdStore.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "templates.h" #include "General.h" #include "Streaming.h" @@ -185,25 +185,3 @@ CTxdStore::RemoveTxd(int slot) RwTexDictionaryDestroy(def->texDict); def->texDict = nil; } - -STARTPATCHES - InjectHook(0x527440, CTxdStore::Initialise, PATCH_JUMP); - InjectHook(0x527470, CTxdStore::Shutdown, PATCH_JUMP); - InjectHook(0x527490, CTxdStore::GameShutdown, PATCH_JUMP); - InjectHook(0x5274E0, CTxdStore::AddTxdSlot, PATCH_JUMP); - InjectHook(0x5275D0, CTxdStore::FindTxdSlot, PATCH_JUMP); - InjectHook(0x527590, CTxdStore::GetTxdName, PATCH_JUMP); - InjectHook(0x527900, CTxdStore::PushCurrentTxd, PATCH_JUMP); - InjectHook(0x527910, CTxdStore::PopCurrentTxd, PATCH_JUMP); - InjectHook(0x5278C0, CTxdStore::SetCurrentTxd, PATCH_JUMP); - InjectHook(0x527830, CTxdStore::Create, PATCH_JUMP); - InjectHook(0x527A00, CTxdStore::GetNumRefs, PATCH_JUMP); - InjectHook(0x527930, CTxdStore::AddRef, PATCH_JUMP); - InjectHook(0x527970, CTxdStore::RemoveRef, PATCH_JUMP); - InjectHook(0x5279C0, CTxdStore::RemoveRefWithoutDelete, PATCH_JUMP); - InjectHook(0x527700, (bool (*)(int, RwStream*))CTxdStore::LoadTxd, PATCH_JUMP); - InjectHook(0x5276B0, (bool (*)(int, const char*))CTxdStore::LoadTxd, PATCH_JUMP); - InjectHook(0x527770, CTxdStore::StartLoadTxd, PATCH_JUMP); - InjectHook(0x5277E0, CTxdStore::FinishLoadTxd, PATCH_JUMP); - InjectHook(0x527870, CTxdStore::RemoveTxd, PATCH_JUMP); -ENDPATCHES diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index b7afd751..89bd13a6 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "templates.h" #include "Entity.h" #include "ModelInfo.h" @@ -838,59 +838,3 @@ CVisibilityPlugins::GetClumpAlpha(RpClump *clump) { return CLUMPEXT(clump)->alpha; } - - -STARTPATCHES - InjectHook(0x527E50, CVisibilityPlugins::Initialise, PATCH_JUMP); - InjectHook(0x527EA0, CVisibilityPlugins::Shutdown, PATCH_JUMP); - InjectHook(0x528F90, CVisibilityPlugins::InitAlphaEntityList, PATCH_JUMP); - InjectHook(0x528FF0, CVisibilityPlugins::InsertEntityIntoSortedList, PATCH_JUMP); - InjectHook(0x528F80, CVisibilityPlugins::InitAlphaAtomicList, PATCH_JUMP); - InjectHook(0x528FA0, CVisibilityPlugins::InsertAtomicIntoSortedList, PATCH_JUMP); - InjectHook(0x528C50, CVisibilityPlugins::SetRenderWareCamera, PATCH_JUMP); - - InjectHook(0x527F60, SetAlphaCB, PATCH_JUMP); - InjectHook(0x529040, CVisibilityPlugins::RenderAlphaAtomics, PATCH_JUMP); - InjectHook(0x529070, CVisibilityPlugins::RenderFadingEntities, PATCH_JUMP); - - InjectHook(0x527F70, CVisibilityPlugins::RenderWheelAtomicCB, PATCH_JUMP); - InjectHook(0x528000, CVisibilityPlugins::RenderObjNormalAtomic, PATCH_JUMP); - InjectHook(0x5280B0, CVisibilityPlugins::RenderAlphaAtomic, PATCH_JUMP); - InjectHook(0x528100, CVisibilityPlugins::RenderFadingAtomic, PATCH_JUMP); - - InjectHook(0x5283E0, CVisibilityPlugins::RenderVehicleHiDetailCB, PATCH_JUMP); - InjectHook(0x5284B0, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB, PATCH_JUMP); - InjectHook(0x5288A0, CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle, PATCH_JUMP); - InjectHook(0x528A10, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle, PATCH_JUMP); - InjectHook(0x528AD0, CVisibilityPlugins::RenderVehicleHiDetailCB_Boat, PATCH_JUMP); - InjectHook(0x5287F0, CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle, PATCH_JUMP); - InjectHook(0x528940, CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle, PATCH_JUMP); - InjectHook(0x528240, CVisibilityPlugins::RenderVehicleReallyLowDetailCB, PATCH_JUMP); - InjectHook(0x5287B0, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle, PATCH_JUMP); - InjectHook(0x5285D0, CVisibilityPlugins::RenderTrainHiDetailCB, PATCH_JUMP); - InjectHook(0x5286A0, CVisibilityPlugins::RenderTrainHiDetailAlphaCB, PATCH_JUMP); - - InjectHook(0x528BC0, CVisibilityPlugins::RenderPedHiDetailCB, PATCH_JUMP); - InjectHook(0x528B60, CVisibilityPlugins::RenderPedLowDetailCB, PATCH_JUMP); - - - InjectHook(0x527DC0, CVisibilityPlugins::PluginAttach, PATCH_JUMP); - - InjectHook(0x527EC0, CVisibilityPlugins::SetAtomicModelInfo, PATCH_JUMP); - InjectHook(0x527F00, CVisibilityPlugins::GetAtomicModelInfo, PATCH_JUMP); - InjectHook(0x527F10, CVisibilityPlugins::SetAtomicFlag, PATCH_JUMP); - InjectHook(0x527F30, CVisibilityPlugins::ClearAtomicFlag, PATCH_JUMP); - InjectHook(0x527F50, CVisibilityPlugins::GetAtomicId, PATCH_JUMP); - InjectHook(0x528C20, CVisibilityPlugins::SetAtomicRenderCallback, PATCH_JUMP); - - InjectHook(0x528D60, CVisibilityPlugins::SetFrameHierarchyId, PATCH_JUMP); - InjectHook(0x528D80, CVisibilityPlugins::GetFrameHierarchyId, PATCH_JUMP); - - InjectHook(0x528ED0, CVisibilityPlugins::SetClumpModelInfo, PATCH_JUMP); - InjectHook(0x528F50, CVisibilityPlugins::SetClumpAlpha, PATCH_JUMP); - InjectHook(0x528F70, CVisibilityPlugins::GetClumpAlpha, PATCH_JUMP); - - - InjectHook(0x529120, CVisibilityPlugins::GetDistanceSquaredFromCamera, PATCH_JUMP); - InjectHook(0x5282A0, CVisibilityPlugins::GetDotProductWithCameraVector, PATCH_JUMP); -ENDPATCHES diff --git a/src/rw/rw.cpp b/src/rw/rw.cpp index c525f49f..09cd246e 100644 --- a/src/rw/rw.cpp +++ b/src/rw/rw.cpp @@ -1,6 +1,6 @@ #ifndef LIBRW #include "common.h" -#include "patcher.h" + #include "rwcore.h" #include "rpworld.h" #include "rpmatfx.h" @@ -14,409 +14,6 @@ typedef RwV3d *(*rwVectorsMultFn) (RwV3d * pointsOut, const RwMatrix * matrix); #ifndef RWLIBS - -WRAPPER void _rwObjectHasFrameSetFrame(void* object, RwFrame* frame) { EAXJMP(0x5BC950); } -WRAPPER RpAtomic* AtomicDefaultRenderCallBack(RpAtomic* atomic) { EAXJMP(0x59E690); } -WRAPPER void _rpAtomicResyncInterpolatedSphere(RpAtomic* atomic) { EAXJMP(0x59E6C0); } -WRAPPER RwSphere const* RpAtomicGetWorldBoundingSphere(RpAtomic* atomic) { EAXJMP(0x59E800); } -WRAPPER RwInt32 RpClumpGetNumAtomics(RpClump* clump) { EAXJMP(0x59ED50); } -WRAPPER RpClump* RpClumpRender(RpClump* clump) { EAXJMP(0x59ED80); } -WRAPPER RpClump* RpClumpForAllAtomics(RpClump* clump, RpAtomicCallBack callback, void* pData) { EAXJMP(0x59EDD0); } -WRAPPER RpClump* RpClumpForAllCameras(RpClump* clump, RwCameraCallBack callback, void* pData) { EAXJMP(0x59EE10); } -WRAPPER RpClump* RpClumpForAllLights(RpClump* clump, RpLightCallBack callback, void* pData) { EAXJMP(0x59EE60); } -WRAPPER RpAtomic* RpAtomicCreate() { EAXJMP(0x59EEB0); } -WRAPPER RpAtomic* RpAtomicSetGeometry(RpAtomic* atomic, RpGeometry* geometry, RwUInt32 flags) { EAXJMP(0x59EFA0); } -WRAPPER RwBool RpAtomicDestroy(RpAtomic* atomic) { EAXJMP(0x59F020); } -WRAPPER RpAtomic* RpAtomicClone(RpAtomic* atomic) { EAXJMP(0x59F0A0); } -WRAPPER RpClump* RpClumpClone(RpClump* clump) { EAXJMP(0x59F1B0); } -WRAPPER RpClump* RpClumpCreate() { EAXJMP(0x59F490); } -WRAPPER RwBool RpClumpDestroy(RpClump* clump) { EAXJMP(0x59F500); } -WRAPPER RpClump* RpClumpAddAtomic(RpClump* clump, RpAtomic* atomic) { EAXJMP(0x59F680); } -WRAPPER RpClump* RpClumpRemoveAtomic(RpClump* clump, RpAtomic* atomic) { EAXJMP(0x59F6B0); } -WRAPPER RpClump* RpClumpRemoveLight(RpClump* clump, RpLight* light) { EAXJMP(0x59F6E0); } -WRAPPER RpClump* RpClumpStreamRead(RwStream* stream) { EAXJMP(0x59FC50); } -WRAPPER RwInt32 RpAtomicRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5A0510); } -WRAPPER RwInt32 RpClumpRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5A0540); } -WRAPPER RwInt32 RpAtomicRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5A0570); } -WRAPPER RwInt32 RpAtomicSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB) { EAXJMP(0x5A05A0); } -WRAPPER RwInt32 RpAtomicSetStreamRightsCallBack(RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB) { EAXJMP(0x5A05C0); } -WRAPPER RwInt32 RpAtomicGetPluginOffset(RwUInt32 pluginID) { EAXJMP(0x5A05E0); } -WRAPPER RpAtomic* RpAtomicSetFrame(RpAtomic* atomic, RwFrame* frame) { EAXJMP(0x5A0600); } -WRAPPER RwInt32 RwEngineRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor initCB, RwPluginObjectDestructor termCB) { EAXJMP(0x5A0DC0); } -WRAPPER RwInt32 RwEngineGetPluginOffset(RwUInt32 pluginID) { EAXJMP(0x5A0DF0); } -WRAPPER RwInt32 RwEngineGetNumSubSystems() { EAXJMP(0x5A0E10); } -WRAPPER RwSubSystemInfo* RwEngineGetSubSystemInfo(RwSubSystemInfo* subSystemInfo, RwInt32 subSystemIndex) { EAXJMP(0x5A0E40); } -WRAPPER RwInt32 RwEngineGetCurrentSubSystem() { EAXJMP(0x5A0E70); } -WRAPPER RwBool RwEngineSetSubSystem(RwInt32 subSystemIndex) { EAXJMP(0x5A0EA0); } -WRAPPER RwInt32 RwEngineGetNumVideoModes() { EAXJMP(0x5A0ED0); } -WRAPPER RwVideoMode* RwEngineGetVideoModeInfo(RwVideoMode* modeinfo, RwInt32 modeIndex) { EAXJMP(0x5A0F00); } -WRAPPER RwInt32 RwEngineGetCurrentVideoMode() { EAXJMP(0x5A0F30); } -WRAPPER RwBool RwEngineSetVideoMode(RwInt32 modeIndex) { EAXJMP(0x5A0F60); } -WRAPPER RwBool RwEngineStop() { EAXJMP(0x5A0F90); } -WRAPPER RwBool RwEngineStart() { EAXJMP(0x5A0FE0); } -WRAPPER RwBool RwEngineClose() { EAXJMP(0x5A1070); } -WRAPPER RwBool RwEngineOpen(RwEngineOpenParams* initParams) { EAXJMP(0x5A10E0); } -WRAPPER RwBool RwEngineTerm() { EAXJMP(0x5A1290); } -WRAPPER RwBool RwEngineInit(RwMemoryFunctions* memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { EAXJMP(0x5A12D0); } -WRAPPER void* _rwFrameOpen(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A15E0); } -WRAPPER void* _rwFrameClose(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A1650); } -WRAPPER RwFrame* _rwFrameCloneAndLinkClones(RwFrame* root) { EAXJMP(0x5A1690); } -WRAPPER RwFrame* _rwFramePurgeClone(RwFrame* root) { EAXJMP(0x5A1880); } -WRAPPER RwBool RwFrameDirty(RwFrame const* frame) { EAXJMP(0x5A1930); } -WRAPPER void _rwFrameInit(RwFrame* frame) { EAXJMP(0x5A1950); } -WRAPPER RwFrame* RwFrameCreate() { EAXJMP(0x5A1A00); } -WRAPPER RwBool RwFrameDestroy(RwFrame* frame) { EAXJMP(0x5A1A30); } -WRAPPER RwBool RwFrameDestroyHierarchy(RwFrame* frame) { EAXJMP(0x5A1BF0); } -WRAPPER RwFrame* RwFrameUpdateObjects(RwFrame* frame) { EAXJMP(0x5A1C60); } -WRAPPER RwMatrix* RwFrameGetLTM(RwFrame* frame) { EAXJMP(0x5A1CE0); } -WRAPPER RwFrame* RwFrameAddChild(RwFrame* parent, RwFrame* child) { EAXJMP(0x5A1D00); } -WRAPPER RwFrame* RwFrameRemoveChild(RwFrame* child) { EAXJMP(0x5A1ED0); } -WRAPPER RwFrame* RwFrameForAllChildren(RwFrame* frame, RwFrameCallBack callBack, void* data) { EAXJMP(0x5A1FC0); } -WRAPPER RwFrame* RwFrameTranslate(RwFrame* frame, RwV3d const* v, RwOpCombineType combine) { EAXJMP(0x5A2000); } -WRAPPER RwFrame* RwFrameScale(RwFrame* frame, RwV3d const* v, RwOpCombineType combine) { EAXJMP(0x5A20A0); } -WRAPPER RwFrame* RwFrameTransform(RwFrame* frame, RwMatrix const* m, RwOpCombineType combine) { EAXJMP(0x5A2140); } -WRAPPER RwFrame* RwFrameRotate(RwFrame* frame, RwV3d const* axis, RwReal angle, RwOpCombineType combine) { EAXJMP(0x5A21E0); } -WRAPPER RwFrame* RwFrameSetIdentity(RwFrame* frame) { EAXJMP(0x5A2280); } -WRAPPER RwFrame* RwFrameForAllObjects(RwFrame* frame, RwObjectCallBack callBack, void* data) { EAXJMP(0x5A2340); } -WRAPPER RwInt32 RwFrameRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5A2380); } -WRAPPER RwBool _rwMatrixSetMultFn(rwMatrixMultFn multMat) { EAXJMP(0x5A23B0); } -WRAPPER RwReal _rwMatrixDeterminant(RwMatrix const* matrix) { EAXJMP(0x5A2520); } -WRAPPER RwReal _rwMatrixOrthogonalError(RwMatrix const* matrix) { EAXJMP(0x5A2570); } -WRAPPER RwReal _rwMatrixNormalError(RwMatrix const* matrix) { EAXJMP(0x5A25D0); } -WRAPPER RwReal _rwMatrixIdentityError(RwMatrix const* matrix) { EAXJMP(0x5A2660); } -WRAPPER void* _rwMatrixClose(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A2730); } -WRAPPER void* _rwMatrixOpen(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A2770); } -WRAPPER RwMatrix* RwMatrixOptimize(RwMatrix* matrix, RwMatrixTolerance const* tolerance) { EAXJMP(0x5A2820); } -WRAPPER RwMatrix* RwMatrixUpdate(RwMatrix* matrix) { EAXJMP(0x5A28E0); } -WRAPPER RwMatrix* RwMatrixMultiply(RwMatrix* matrixOut, RwMatrix const* MatrixIn1, RwMatrix const* matrixIn2) { EAXJMP(0x5A28F0); } -WRAPPER RwMatrix* RwMatrixRotateOneMinusCosineSine(RwMatrix* matrix, RwV3d const* unitAxis, RwReal oneMinusCosine, RwReal sine, RwOpCombineType combineOp) { EAXJMP(0x5A2960); } -WRAPPER RwMatrix* RwMatrixRotate(RwMatrix* matrix, RwV3d const* axis, RwReal angle, RwOpCombineType combineOp) { EAXJMP(0x5A2BF0); } -WRAPPER RwMatrix* RwMatrixInvert(RwMatrix* matrixOut, RwMatrix const* matrixIn) { EAXJMP(0x5A2C90); } -WRAPPER RwMatrix* RwMatrixScale(RwMatrix* matrix, RwV3d const* scale, RwOpCombineType combineOp) { EAXJMP(0x5A2EE0); } -WRAPPER RwMatrix* RwMatrixTranslate(RwMatrix* matrix, RwV3d const* translation, RwOpCombineType combineOp) { EAXJMP(0x5A3070); } -WRAPPER RwMatrix* RwMatrixTransform(RwMatrix* matrix, RwMatrix const* transform, RwOpCombineType combineOp) { EAXJMP(0x5A31C0); } -WRAPPER RwBool RwMatrixDestroy(RwMatrix* mpMat) { EAXJMP(0x5A3300); } -WRAPPER RwMatrix* RwMatrixCreate() { EAXJMP(0x5A3330); } -WRAPPER RwBool _rwVectorSetMultFn(rwVectorMultFn multPoint, rwVectorsMultFn multPoints, rwVectorMultFn multVector, rwVectorsMultFn multVectors) { EAXJMP(0x5A3450); } -WRAPPER RwReal _rwV3dNormalize(RwV3d* out, RwV3d const* in) { EAXJMP(0x5A3600); } -WRAPPER RwReal RwV3dLength(RwV3d const* in) { EAXJMP(0x5A36A0); } -WRAPPER RwReal _rwSqrt(RwReal const num) { EAXJMP(0x5A3710); } -WRAPPER RwReal _rwInvSqrt(RwReal const num) { EAXJMP(0x5A3770); } -WRAPPER RwV3d* RwV3dTransformPoints(RwV3d* pointsOut, RwV3d const* pointsIn, RwInt32 numPoints, RwMatrix const* matrix) { EAXJMP(0x5A37D0); } -WRAPPER RwV3d* RwV3dTransformVectors(RwV3d* vectorsOut, RwV3d const* vectorsIn, RwInt32 numPoints, RwMatrix const* matrix) { EAXJMP(0x5A37E0); } -WRAPPER void* _rwVectorClose(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A37F0); } -WRAPPER void* _rwVectorOpen(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A3860); } -WRAPPER RwUInt32 RwStreamRead(RwStream* stream, void* buffer, RwUInt32 length) { EAXJMP(0x5A3AD0); } -WRAPPER RwStream* RwStreamWrite(RwStream* stream, void const* buffer, RwUInt32 length) { EAXJMP(0x5A3C30); } -WRAPPER RwStream* RwStreamSkip(RwStream* stream, RwUInt32 offset) { EAXJMP(0x5A3DF0); } -WRAPPER RwBool RwStreamClose(RwStream* stream, void* pData) { EAXJMP(0x5A3F10); } -WRAPPER RwStream* RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, void const* pData) { EAXJMP(0x5A3FE0); } -WRAPPER RwReal RwIm2DGetNearScreenZ() { EAXJMP(0x5A43A0); } -WRAPPER RwReal RwIm2DGetFarScreenZ() { EAXJMP(0x5A43B0); } -WRAPPER RwBool RwRenderStateSet(RwRenderState state, void* value) { EAXJMP(0x5A43C0); } -WRAPPER RwBool RwRenderStateGet(RwRenderState state, void* value) { EAXJMP(0x5A4410); } -WRAPPER RwBool RwIm2DRenderLine(RwIm2DVertex* vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2) { EAXJMP(0x5A4420); } -WRAPPER RwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex* vertices, RwInt32 numVertices) { EAXJMP(0x5A4430); } -WRAPPER RwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex* vertices, RwInt32 numVertices, RwImVertexIndex* indices, RwInt32 numIndices) { EAXJMP(0x5A4440); } -WRAPPER RwCamera* RwCameraEndUpdate(RwCamera* camera) { EAXJMP(0x5A5020); } -WRAPPER RwCamera* RwCameraBeginUpdate(RwCamera* camera) { EAXJMP(0x5A5030); } -WRAPPER RwCamera* RwCameraSetViewOffset(RwCamera* camera, RwV2d const* offset) { EAXJMP(0x5A5040); } -WRAPPER RwCamera* RwCameraSetNearClipPlane(RwCamera* camera, RwReal nearClip) { EAXJMP(0x5A5070); } -WRAPPER RwCamera* RwCameraSetFarClipPlane(RwCamera* camera, RwReal farClip) { EAXJMP(0x5A5140); } -WRAPPER RwFrustumTestResult RwCameraFrustumTestSphere(RwCamera const* camera, RwSphere const* sphere) { EAXJMP(0x5A5170); } -WRAPPER RwCamera* RwCameraClear(RwCamera* camera, RwRGBA* colour, RwInt32 clearMode) { EAXJMP(0x5A51E0); } -WRAPPER RwCamera* RwCameraShowRaster(RwCamera* camera, void* pDev, RwUInt32 flags) { EAXJMP(0x5A5210); } -WRAPPER RwCamera* RwCameraSetProjection(RwCamera* camera, RwCameraProjection projection) { EAXJMP(0x5A5240); } -WRAPPER RwCamera* RwCameraSetViewWindow(RwCamera* camera, RwV2d const* viewWindow) { EAXJMP(0x5A52B0); } -WRAPPER RwInt32 RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5A52F0); } -WRAPPER RwBool RwCameraDestroy(RwCamera* camera) { EAXJMP(0x5A5320); } -WRAPPER RwCamera* RwCameraCreate() { EAXJMP(0x5A5360); } -WRAPPER RwBool RwTextureSetMipmapping(RwBool enable) { EAXJMP(0x5A7100); } -WRAPPER RwBool RwTextureGetMipmapping() { EAXJMP(0x5A7120); } -WRAPPER RwBool RwTextureSetAutoMipmapping(RwBool enable) { EAXJMP(0x5A7130); } -WRAPPER RwBool RwTextureGetAutoMipmapping() { EAXJMP(0x5A7150); } -WRAPPER RwTexDictionary* RwTexDictionaryCreate() { EAXJMP(0x5A7160); } -WRAPPER RwBool RwTexDictionaryDestroy(RwTexDictionary* dict) { EAXJMP(0x5A7200); } -WRAPPER RwTexDictionary const* RwTexDictionaryForAllTextures(RwTexDictionary const* dict, RwTextureCallBack fpCallBack, void* pData) { EAXJMP(0x5A7290); } -WRAPPER RwTexture* RwTextureCreate(RwRaster* raster) { EAXJMP(0x5A72D0); } -WRAPPER RwBool RwTextureDestroy(RwTexture* texture) { EAXJMP(0x5A7330); } -WRAPPER RwTexture* RwTextureSetName(RwTexture* texture, RwChar const* name) { EAXJMP(0x5A73B0); } -WRAPPER RwTexture* RwTextureSetMaskName(RwTexture* texture, RwChar const* maskName) { EAXJMP(0x5A7420); } -WRAPPER RwTexture* RwTexDictionaryAddTexture(RwTexDictionary* dict, RwTexture* texture) { EAXJMP(0x5A7490); } -WRAPPER RwTexture* RwTexDictionaryFindNamedTexture(RwTexDictionary* dict, RwChar const* name) { EAXJMP(0x5A74D0); } -WRAPPER RwTexDictionary* RwTexDictionarySetCurrent(RwTexDictionary* dict) { EAXJMP(0x5A7550); } -WRAPPER RwTexDictionary* RwTexDictionaryGetCurrent() { EAXJMP(0x5A7570); } -WRAPPER RwTexture* RwTextureRead(RwChar const* name, RwChar const* maskName) { EAXJMP(0x5A7580); } -WRAPPER RwBool RwTextureRasterGenerateMipmaps(RwRaster* raster, RwImage* image) { EAXJMP(0x5A7780); } -WRAPPER RwImage* RwImageCreate(RwInt32 width, RwInt32 height, RwInt32 depth) { EAXJMP(0x5A9120); } -WRAPPER RwBool RwImageDestroy(RwImage* image) { EAXJMP(0x5A9180); } -WRAPPER RwImage* RwImageAllocatePixels(RwImage* image) { EAXJMP(0x5A91E0); } -WRAPPER RwImage* RwImageFreePixels(RwImage* image) { EAXJMP(0x5A92A0); } -WRAPPER RwImage* RwImageMakeMask(RwImage* image) { EAXJMP(0x5A92D0); } -WRAPPER RwImage* RwImageApplyMask(RwImage* image, RwImage const* mask) { EAXJMP(0x5A93A0); } -WRAPPER RwChar const* RwImageSetPath(RwChar const* path) { EAXJMP(0x5A9750); } -WRAPPER RwImage* RwImageRead(RwChar const* imageName) { EAXJMP(0x5A9810); } -WRAPPER RwChar const* RwImageFindFileType(RwChar const* imageName) { EAXJMP(0x5A9B40); } -WRAPPER RwImage* RwImageReadMaskedImage(RwChar const* imageName, RwChar const* maskname) { EAXJMP(0x5A9C10); } -WRAPPER RwImage* RwImageCopy(RwImage* destImage, RwImage const* sourceImage) { EAXJMP(0x5A9F50); } -WRAPPER RwImage* RwImageGammaCorrect(RwImage* image) { EAXJMP(0x5AA130); } -WRAPPER RwBool RwImageSetGamma(RwReal gammaValue) { EAXJMP(0x5AA2C0); } -WRAPPER RwStream* _rwStreamWriteVersionedChunkHeader(RwStream* stream, RwInt32 type, RwInt32 size, RwUInt32 version, RwUInt32 buildNum) { EAXJMP(0x5AA4E0); } -WRAPPER RwBool RwStreamFindChunk(RwStream* stream, RwUInt32 type, RwUInt32* lengthOut, RwUInt32* versionOut) { EAXJMP(0x5AA540); } -WRAPPER void* RwMemLittleEndian32(void* mem, RwUInt32 size) { EAXJMP(0x5AA640); } -WRAPPER void* RwMemNative32(void* mem, RwUInt32 size) { EAXJMP(0x5AA650); } -WRAPPER void* RwMemFloat32ToReal(void* mem, RwUInt32 size) { EAXJMP(0x5AA660); } -WRAPPER RwStream* RwStreamWriteReal(RwStream* stream, RwReal const* reals, RwUInt32 numBytes) { EAXJMP(0x5AA680); } -WRAPPER RwStream* RwStreamWriteInt32(RwStream* stream, RwInt32 const* ints, RwUInt32 numBytes) { EAXJMP(0x5AA720); } -WRAPPER RwStream* RwStreamReadReal(RwStream* stream, RwReal* reals, RwUInt32 numBytes) { EAXJMP(0x5AA740); } -WRAPPER RwStream* RwStreamReadInt32(RwStream* stream, RwInt32* ints, RwUInt32 numBytes) { EAXJMP(0x5AA7B0); } -WRAPPER RwUInt32 RwTextureStreamGetSize(RwTexture const* texture) { EAXJMP(0x5AA800); } -WRAPPER RwTexture const* RwTextureStreamWrite(RwTexture const* texture, RwStream* stream) { EAXJMP(0x5AA870); } -WRAPPER RwTexture* RwTextureStreamRead(RwStream* stream) { EAXJMP(0x5AAA40); } -WRAPPER RwTexDictionary const* RwTexDictionaryStreamWrite(RwTexDictionary const* texDict, RwStream* stream) { EAXJMP(0x5AB020); } -WRAPPER RpMorphTarget const* RpMorphTargetCalcBoundingSphere(RpMorphTarget const* morphTarget, RwSphere* boundingSphere) { EAXJMP(0x5AC890); } -WRAPPER RwInt32 RpGeometryAddMorphTargets(RpGeometry* geometry, RwInt32 mtcount) { EAXJMP(0x5AC9A0); } -WRAPPER RpGeometry const* RpGeometryTriangleSetVertexIndices(RpGeometry const* geometry, RpTriangle* triangle, RwUInt16 vert1, RwUInt16 vert2, RwUInt16 vert3) { EAXJMP(0x5ACB60); } -WRAPPER RpGeometry* RpGeometryTriangleSetMaterial(RpGeometry* geometry, RpTriangle* triangle, RpMaterial* material) { EAXJMP(0x5ACB90); } -WRAPPER RpGeometry* RpGeometryForAllMaterials(RpGeometry* geometry, RpMaterialCallBack fpCallBack, void* pData) { EAXJMP(0x5ACBF0); } -WRAPPER RpGeometry* RpGeometryLock(RpGeometry* geometry, RwInt32 lockMode) { EAXJMP(0x5ACC30); } -WRAPPER RpGeometry* RpGeometryUnlock(RpGeometry* geometry) { EAXJMP(0x5ACC60); } -WRAPPER RpGeometry* RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format) { EAXJMP(0x5ACD10); } -WRAPPER RpGeometry* _rpGeometryAddRef(RpGeometry* geometry) { EAXJMP(0x5ACF40); } -WRAPPER RwBool RpGeometryDestroy(RpGeometry* geometry) { EAXJMP(0x5ACF50); } -WRAPPER RwInt32 RpGeometryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5ACFF0); } -WRAPPER RwInt32 RpGeometryRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5AD020); } -WRAPPER RpGeometry* RpGeometryStreamRead(RwStream* stream) { EAXJMP(0x5AD050); } -WRAPPER RwRaster* RwRasterGetCurrentContext() { EAXJMP(0x5AD6D0); } -WRAPPER RwRaster* RwRasterUnlock(RwRaster* raster) { EAXJMP(0x5AD6F0); } -WRAPPER RwRaster* RwRasterRenderFast(RwRaster* raster, RwInt32 x, RwInt32 y) { EAXJMP(0x5AD710); } -WRAPPER RwRaster* RwRasterUnlockPalette(RwRaster* raster) { EAXJMP(0x5AD750); } -WRAPPER RwBool RwRasterDestroy(RwRaster* raster) { EAXJMP(0x5AD780); } -WRAPPER RwRaster* RwRasterPushContext(RwRaster* raster) { EAXJMP(0x5AD7C0); } -WRAPPER RwInt32 RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5AD810); } -WRAPPER RwUInt8* RwRasterLockPalette(RwRaster* raster, RwInt32 lockMode) { EAXJMP(0x5AD840); } -WRAPPER RwRaster* RwRasterPopContext() { EAXJMP(0x5AD870); } -WRAPPER RwInt32 RwRasterGetNumLevels(RwRaster* raster) { EAXJMP(0x5AD8C0); } -WRAPPER RwRaster* RwRasterShowRaster(RwRaster* raster, void* dev, RwUInt32 flags) { EAXJMP(0x5AD900); } -WRAPPER RwRaster* RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags) { EAXJMP(0x5AD930); } -WRAPPER RwUInt8* RwRasterLock(RwRaster* raster, RwUInt8 level, RwInt32 lockMode) { EAXJMP(0x5AD9D0); } -WRAPPER RpMaterial* RpMaterialCreate() { EAXJMP(0x5ADC30); } -WRAPPER RwBool RpMaterialDestroy(RpMaterial* material) { EAXJMP(0x5ADCB0); } -WRAPPER RpMaterial* RpMaterialSetTexture(RpMaterial* material, RwTexture* texture) { EAXJMP(0x5ADD10); } -WRAPPER RwInt32 RpMaterialRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5ADD40); } -WRAPPER RwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5ADD70); } -WRAPPER RpMaterial* RpMaterialStreamRead(RwStream* stream) { EAXJMP(0x5ADDA0); } -WRAPPER RpWorldSector* _rpSectorDefaultRenderCallBack(RpWorldSector* sector) { EAXJMP(0x5AE0B0); } -WRAPPER RwBool _rpWorldForAllGlobalLights(RpLightCallBack callBack, void* pData) { EAXJMP(0x5AE100); } -WRAPPER RpWorldSector* _rpWorldSectorForAllLocalLights(RpWorldSector* sector, RpLightCallBack callBack, void* pData) { EAXJMP(0x5AE150); } -WRAPPER RpWorld* RpWorldUnlock(RpWorld* world) { EAXJMP(0x5AE190); } -WRAPPER RpWorld* RpWorldSectorGetWorld(RpWorldSector const* sector) { EAXJMP(0x5AE2B0); } -WRAPPER RwBool RpWorldDestroy(RpWorld* world) { EAXJMP(0x5AE340); } -WRAPPER RpWorld* RpWorldCreate(RwBBox* boundingBox) { EAXJMP(0x5AE6A0); } -WRAPPER RwInt32 RpWorldRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5AEA40); } -WRAPPER RwInt32 RpWorldRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5AEA70); } -WRAPPER RwBool RpWorldPluginAttach() { EAXJMP(0x5AEAA0); } -WRAPPER RpWorld* RpWorldAddCamera(RpWorld* world, RwCamera* camera) { EAXJMP(0x5AFB80); } -WRAPPER RpWorld* RpWorldRemoveCamera(RpWorld* world, RwCamera* camera) { EAXJMP(0x5AFBB0); } -WRAPPER RpWorld* RpAtomicGetWorld(RpAtomic const* atomic) { EAXJMP(0x5AFC10); } -WRAPPER RpWorld* RpWorldAddClump(RpWorld* world, RpClump* clump) { EAXJMP(0x5AFC20); } -WRAPPER RpWorld* RpWorldAddLight(RpWorld* world, RpLight* light) { EAXJMP(0x5AFDA0); } -WRAPPER RpWorld* RpWorldRemoveLight(RpWorld* world, RpLight* light) { EAXJMP(0x5AFDF0); } -WRAPPER RwImage* RtBMPImageRead(RwChar const* imageName) { EAXJMP(0x5AFE70); } -WRAPPER RwBool RpSkinPluginAttach() { EAXJMP(0x5B07D0); } -WRAPPER RpAtomic* RpSkinAtomicSetHAnimHierarchy(RpAtomic* atomic, RpHAnimHierarchy* hierarchy) { EAXJMP(0x5B1050); } -WRAPPER RpHAnimHierarchy* RpSkinAtomicGetHAnimHierarchy(RpAtomic const* atomic) { EAXJMP(0x5B1070); } -WRAPPER RpSkin* RpSkinGeometryGetSkin(RpGeometry* geometry) { EAXJMP(0x5B1080); } -WRAPPER RpGeometry* RpSkinGeometrySetSkin(RpGeometry* geometry, RpSkin* skin) { EAXJMP(0x5B1090); } -WRAPPER RwMatrix const* RpSkinGetSkinToBoneMatrices(RpSkin* skin) { EAXJMP(0x5B10D0); } -WRAPPER RpHAnimHierarchy* RpHAnimHierarchyCreate(RwInt32 numNodes, RwUInt32* nodeFlags, RwInt32* nodeIDs, RpHAnimHierarchyFlag flags, RwInt32 maxKeyFrameSize) { EAXJMP(0x5B10E0); } -WRAPPER RpHAnimHierarchy* RpHAnimFrameGetHierarchy(RwFrame* frame) { EAXJMP(0x5B11F0); } -WRAPPER RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy* hierarchy, RpHAnimAnimation* anim) { EAXJMP(0x5B1200); } -WRAPPER RwBool RpHAnimHierarchySubAnimTime(RpHAnimHierarchy* hierarchy, RwReal time) { EAXJMP(0x5B12B0); } -WRAPPER RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy* hierarchy, RwReal time) { EAXJMP(0x5B1480); } -WRAPPER RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy* hierarchy) { EAXJMP(0x5B1780); } -WRAPPER RpHAnimAnimation* RpHAnimAnimationStreamRead(RwStream* stream) { EAXJMP(0x5B1C10); } -WRAPPER RwBool RpHAnimPluginAttach() { EAXJMP(0x5B1D50); } -WRAPPER RwBool RpMatFXPluginAttach() { EAXJMP(0x5B2640); } -WRAPPER RpAtomic* RpMatFXAtomicEnableEffects(RpAtomic* atomic) { EAXJMP(0x5B3750); } -WRAPPER RpMaterial* RpMatFXMaterialSetEffects(RpMaterial* material, RpMatFXMaterialFlags flags) { EAXJMP(0x5B3780); } -WRAPPER RpMaterial* RpMatFXMaterialSetupEnvMap(RpMaterial* material, RwTexture* texture, RwFrame* frame, RwBool useFrameBufferAlpha, RwReal coef) { EAXJMP(0x5B38D0); } -WRAPPER RpMaterial* RpMatFXMaterialSetBumpMapTexture(RpMaterial* material, RwTexture* texture) { EAXJMP(0x5B3A40); } -WRAPPER RwBool RwD3D8SetRenderState(RwUInt32 state, RwUInt32 value) { EAXJMP(0x5B3CF0); } -WRAPPER void RwD3D8GetRenderState(RwUInt32 state, void* value) { EAXJMP(0x5B3D40); } -WRAPPER RwBool RwD3D8SetTextureStageState(RwUInt32 stage, RwUInt32 type, RwUInt32 value) { EAXJMP(0x5B3D60); } -WRAPPER RwBool RwD3D8SetTexture(RwTexture* texture, RwUInt32 stage) { EAXJMP(0x5B53A0); } -WRAPPER void* RwIm3DTransform(RwIm3DVertex* pVerts, RwUInt32 numVerts, RwMatrix* ltm, RwUInt32 flags) { EAXJMP(0x5B6720); } -WRAPPER RwBool RwIm3DEnd() { EAXJMP(0x5B67F0); } -WRAPPER RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex* indices, RwInt32 numIndices) { EAXJMP(0x5B6820); } -WRAPPER RwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2) { EAXJMP(0x5B6980); } -WRAPPER RxPipeline* RwIm3DSetTransformPipeline(RxPipeline* pipeline) { EAXJMP(0x5B6A50); } -WRAPPER RxPipeline* RwIm3DSetRenderPipeline(RxPipeline* pipeline, RwPrimitiveType primType) { EAXJMP(0x5B6AC0); } -WRAPPER void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate) { EAXJMP(0x5B95D0); } -WRAPPER RwBool RwD3D8CameraAttachWindow(void* camera, void* hwnd) { EAXJMP(0x5B9640); } -WRAPPER RwBool RwD3D8DeviceSupportsDXTTexture() { EAXJMP(0x5BAEB0); } -WRAPPER RwBool RwD3D8SetVertexShader(RwUInt32 handle) { EAXJMP(0x5BAF90); } -WRAPPER RwBool RwD3D8SetPixelShader(RwUInt32 handle) { EAXJMP(0x5BAFD0); } -WRAPPER RwBool RwD3D8SetStreamSource(RwUInt32 streamNumber, void* streamData, RwUInt32 stride) { EAXJMP(0x5BB010); } -WRAPPER RwBool RwD3D8SetIndices(void* indexData, RwUInt32 baseVertexIndex) { EAXJMP(0x5BB060); } -WRAPPER RwBool RwD3D8DrawIndexedPrimitive(RwUInt32 primitiveType, RwUInt32 minIndex, RwUInt32 numVertices, RwUInt32 startIndex, RwUInt32 numIndices) { EAXJMP(0x5BB0B0); } -WRAPPER RwBool RwD3D8DrawPrimitive(RwUInt32 primitiveType, RwUInt32 startVertex, RwUInt32 numVertices) { EAXJMP(0x5BB140); } -WRAPPER RwBool RwD3D8SetTransform(RwUInt32 state, void const* matrix) { EAXJMP(0x5BB1D0); } -WRAPPER void RwD3D8GetTransform(RwUInt32 state, void* matrix) { EAXJMP(0x5BB310); } -WRAPPER RwBool RwD3D8SetTransformWorld(RwMatrix const* matrix) { EAXJMP(0x5BB340); } -WRAPPER RwBool RwD3D8SetSurfaceProperties(RwRGBA const* color, RwSurfaceProperties const* surfaceProps, RwBool modulate) { EAXJMP(0x5BB490); } -WRAPPER RwBool RwD3D8SetLight(RwInt32 index, void const* light) { EAXJMP(0x5BB7A0); } -WRAPPER RwBool RwD3D8EnableLight(RwInt32 index, RwBool enable) { EAXJMP(0x5BB890); } -WRAPPER RwBool RwD3D8DynamicVertexBufferCreate(RwUInt32 fvf, RwUInt32 size, void** vertexBuffer) { EAXJMP(0x5BB9F0); } -WRAPPER void RwD3D8DynamicVertexBufferDestroy(void* vertexBuffer) { EAXJMP(0x5BBAE0); } -WRAPPER RwBool RwD3D8IndexBufferCreate(RwUInt32 numIndices, void** indexBuffer) { EAXJMP(0x5BBB10); } -WRAPPER RwBool RwD3D8CreatePixelShader(RwUInt32 const* function, RwUInt32* handle) { EAXJMP(0x5BBB40); } -WRAPPER void RwD3D8DeletePixelShader(RwUInt32 handle) { EAXJMP(0x5BBB90); } -WRAPPER RwBool RwD3D8SetPixelShaderConstant(RwUInt32 registerAddress, void const* antData, RwUInt32 antCount) { EAXJMP(0x5BBC00); } -WRAPPER void const* RwD3D8GetCaps() { EAXJMP(0x5BBC30); } -WRAPPER RwBool RwD3D8CameraIsSphereFullyInsideFrustum(void const* camera, void const* sphere) { EAXJMP(0x5BBC40); } -WRAPPER RwBool RwD3D8CameraIsBBoxFullyInsideFrustum(void const* camera, void const* boundingBox) { EAXJMP(0x5BBCA0); } -WRAPPER RwBool RwD3D8DynamicVertexBufferLock(RwUInt32 vertexSize, RwUInt32 numVertex, void** vertexBufferOut, void** vertexDataOut, RwUInt32* baseIndexOut) { EAXJMP(0x5BBD30); } -WRAPPER RwBool RwD3D8DynamicVertexBufferUnlock(void* vertexBuffer) { EAXJMP(0x5BBEB0); } -WRAPPER RwBool _rwIntelSSEsupported() { EAXJMP(0x5BBED0); } -WRAPPER RwImage* RwImageSetFromRaster(RwImage* image, RwRaster* raster) { EAXJMP(0x5BBF10); } -WRAPPER RwRaster* RwRasterSetFromImage(RwRaster* raster, RwImage* image) { EAXJMP(0x5BBF50); } -WRAPPER RwImage* RwImageFindRasterFormat(RwImage* ipImage, RwInt32 nRasterType, RwInt32* npWidth, RwInt32* npHeight, RwInt32* npDepth, RwInt32* npFormat) { EAXJMP(0x5BBF80); } -WRAPPER RwInt32 RwFrameRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5BBFF0); } -WRAPPER rwFrameList* _rwFrameListDeinitialize(rwFrameList* frameList) { EAXJMP(0x5BC020); } -WRAPPER rwFrameList* _rwFrameListStreamRead(RwStream* stream, rwFrameList* fl) { EAXJMP(0x5BC050); } -WRAPPER RpLight* RpLightSetRadius(RpLight* light, RwReal radius) { EAXJMP(0x5BC300); } -WRAPPER RpLight* RpLightSetColor(RpLight* light, RwRGBAReal const* color) { EAXJMP(0x5BC320); } -WRAPPER RwReal RpLightGetConeAngle(RpLight const* light) { EAXJMP(0x5BC370); } -WRAPPER RwInt32 RpLightRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5BC5B0); } -WRAPPER RpLight* RpLightStreamRead(RwStream* stream) { EAXJMP(0x5BC5E0); } -WRAPPER RwBool RpLightDestroy(RpLight* light) { EAXJMP(0x5BC780); } -WRAPPER RpLight* RpLightCreate(RwInt32 type) { EAXJMP(0x5BC7C0); } -WRAPPER void _rwD3D8TexDictionaryEnableRasterFormatConversion(RwBool enable) { EAXJMP(0x5BE280); } -WRAPPER RwFileFunctions* RwOsGetFileInterface() { EAXJMP(0x5BF110); } -WRAPPER RwBool RwFreeListDestroy(RwFreeList* freelist) { EAXJMP(0x5C1720); } -WRAPPER RwFreeList* RwFreeListCreate(RwInt32 entrySize, RwInt32 entriesPerBlock, RwInt32 alignment) { EAXJMP(0x5C1790); } -WRAPPER RwInt32 RwFreeListPurge(RwFreeList* freelist) { EAXJMP(0x5C19F0); } -WRAPPER RwInt32 RwFreeListPurgeAllFreeLists() { EAXJMP(0x5C1B90); } -WRAPPER RwFreeList* RwFreeListForAllUsed(RwFreeList* freelist, RwFreeListCallBack fpCallBack, void* pData) { EAXJMP(0x5C1D40); } -WRAPPER RwBool _rxPipelineClose() { EAXJMP(0x5C2780); } -WRAPPER RwBool _rxPipelineOpen() { EAXJMP(0x5C27E0); } -WRAPPER RxHeap* RxHeapGetGlobalHeap() { EAXJMP(0x5C2AD0); } -WRAPPER RxPacket* RxPacketCreate(RxPipelineNode* node) { EAXJMP(0x5C2AE0); } -WRAPPER RxCluster* RxClusterSetExternalData(RxCluster* cluster, void* data, RwInt32 stride, RwInt32 numElements) { EAXJMP(0x5C2B10); } -WRAPPER RxCluster* RxClusterSetData(RxCluster* cluster, void* data, RwInt32 stride, RwInt32 numElements) { EAXJMP(0x5C2B70); } -WRAPPER RxCluster* RxClusterInitializeData(RxCluster* cluster, RwUInt32 numElements, RwUInt16 stride) { EAXJMP(0x5C2BD0); } -WRAPPER RxCluster* RxClusterResizeData(RxCluster* CurrentCluster, RwUInt32 NumElements) { EAXJMP(0x5C2C40); } -WRAPPER RxCluster* RxClusterLockWrite(RxPacket* packet, RwUInt32 clusterIndex, RxPipelineNode* node) { EAXJMP(0x5C2C90); } -WRAPPER RxPipeline* RxPipelineExecute(RxPipeline* pipeline, void* data, RwBool heapReset) { EAXJMP(0x5C2D60); } -WRAPPER RxPipeline* RxPipelineCreate() { EAXJMP(0x5C2E00); } -WRAPPER void _rxPipelineDestroy(RxPipeline* Pipeline) { EAXJMP(0x5C2E70); } -WRAPPER RwBool RwResourcesFreeResEntry(RwResEntry* entry) { EAXJMP(0x5C3080); } -WRAPPER void _rwResourcesPurge() { EAXJMP(0x5C30F0); } -WRAPPER RwResEntry* RwResourcesAllocateResEntry(void* owner, RwResEntry** ownerRef, RwInt32 size, RwResEntryDestroyNotify destroyNotify) { EAXJMP(0x5C3170); } -WRAPPER RwBool RwResourcesEmptyArena() { EAXJMP(0x5C3360); } -WRAPPER RwBool _rwPluginRegistryOpen() { EAXJMP(0x5C3450); } -WRAPPER RwBool _rwPluginRegistryClose() { EAXJMP(0x5C3480); } -WRAPPER RwInt32 _rwPluginRegistryGetPluginOffset(RwPluginRegistry const* reg, RwUInt32 pluginID) { EAXJMP(0x5C3590); } -WRAPPER RwInt32 _rwPluginRegistryAddPlugin(RwPluginRegistry* reg, RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5C35C0); } -WRAPPER RwPluginRegistry const* _rwPluginRegistryInitObject(RwPluginRegistry const* reg, void* object) { EAXJMP(0x5C37F0); } -WRAPPER RwPluginRegistry const* _rwPluginRegistryDeInitObject(RwPluginRegistry const* reg, void* object) { EAXJMP(0x5C3850); } -WRAPPER RwPluginRegistry const* _rwPluginRegistryCopyObject(RwPluginRegistry const* reg, void* dstObject, void const* srcObject) { EAXJMP(0x5C3880); } -WRAPPER RwError* RwErrorSet(RwError* code) { EAXJMP(0x5C3910); } -WRAPPER RwInt32 _rwerror(RwInt32 code, ...) { EAXJMP(0x5C3970); } -WRAPPER RwInt32 _rwPluginRegistryAddPluginStream(RwPluginRegistry* reg, RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5C3980); } -WRAPPER RwInt32 _rwPluginRegistryAddPlgnStrmlwysCB(RwPluginRegistry* reg, RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB) { EAXJMP(0x5C39C0); } -WRAPPER RwInt32 _rwPluginRegistryAddPlgnStrmRightsCB(RwPluginRegistry* reg, RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB) { EAXJMP(0x5C39F0); } -WRAPPER RwPluginRegistry const* _rwPluginRegistryReadDataChunks(RwPluginRegistry const* reg, RwStream* stream, void* object) { EAXJMP(0x5C3A20); } -WRAPPER RwPluginRegistry const* _rwPluginRegistryInvokeRights(RwPluginRegistry const* reg, RwUInt32 id, void* obj, RwUInt32 extraData) { EAXJMP(0x5C3B50); } -WRAPPER RwInt32 _rwPluginRegistryGetSize(RwPluginRegistry const* reg, void const* object) { EAXJMP(0x5C3BA0); } -WRAPPER RwPluginRegistry const* _rwPluginRegistryWriteDataChunks(RwPluginRegistry const* reg, RwStream* stream, void const* object) { EAXJMP(0x5C3BE0); } -WRAPPER RwPluginRegistry const* _rwPluginRegistrySkipDataChunks(RwPluginRegistry const* reg, RwStream* stream) { EAXJMP(0x5C3CB0); } -WRAPPER RwCamera* RwCameraStreamRead(RwStream* stream) { EAXJMP(0x5C3D30); } -WRAPPER RwBBox* RwBBoxCalculate(RwBBox* boundBox, RwV3d const* verts, RwInt32 numVerts) { EAXJMP(0x5C5570); } -WRAPPER RwImage* RwImageResample(RwImage* dstImage, RwImage const* srcImage) { EAXJMP(0x5C72B0); } -WRAPPER RwImage* RwImageCreateResample(RwImage const* srcImage, RwInt32 width, RwInt32 height) { EAXJMP(0x5C7B30); } -WRAPPER RxRenderStateVector* RxRenderStateVectorSetDefaultRenderStateVector(RxRenderStateVector* rsvp) { EAXJMP(0x5D9240); } -WRAPPER RxRenderStateVector* RxRenderStateVectorCreate(RwBool current) { EAXJMP(0x5D9340); } -WRAPPER void RxRenderStateVectorDestroy(RxRenderStateVector* rsvp) { EAXJMP(0x5D9410); } -WRAPPER RxRenderStateVector* RxRenderStateVectorLoadDriverState(RxRenderStateVector* rsvp) { EAXJMP(0x5D9460); } -WRAPPER void _rxEmbeddedPacketBetweenPipelines(RxPipeline* fromPipeline, RxPipeline* toPipeline) { EAXJMP(0x5D95D0); } -WRAPPER RxPipelineNode* _rxEmbeddedPacketBetweenNodes(RxPipeline* pipeline, RxPipelineNode* nodeFrom, RwUInt32 whichOutput) { EAXJMP(0x5D9740); } -WRAPPER void _rxPacketDestroy(RxPacket* Packet) { EAXJMP(0x5D9810); } -WRAPPER RpMaterialList* _rpMaterialListDeinitialize(RpMaterialList* matList) { EAXJMP(0x5C8B10); } -WRAPPER RpMaterialList* _rpMaterialListInitialize(RpMaterialList* matList) { EAXJMP(0x5C8B70); } -WRAPPER RpMaterial* _rpMaterialListGetMaterial(RpMaterialList const* matList, RwInt32 matIndex) { EAXJMP(0x5C8B80); } -WRAPPER RwInt32 _rpMaterialListAppendMaterial(RpMaterialList* matList, RpMaterial* material) { EAXJMP(0x5C8B90); } -WRAPPER RwInt32 _rpMaterialListFindMaterialIndex(RpMaterialList const* matList, RpMaterial const* material) { EAXJMP(0x5C8C50); } -WRAPPER RpMaterialList* _rpMaterialListStreamRead(RwStream* stream, RpMaterialList* matList) { EAXJMP(0x5C8C80); } -WRAPPER RpMeshHeader* _rpMeshHeaderCreate(RwUInt32 size) { EAXJMP(0x5C8FE0); } -WRAPPER void* _rpMeshClose(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5C8FF0); } -WRAPPER void* _rpMeshOpen(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5C9020); } -WRAPPER RpBuildMesh* _rpBuildMeshCreate(RwUInt32 bufferSize) { EAXJMP(0x5C9140); } -WRAPPER RwBool _rpBuildMeshDestroy(RpBuildMesh* mesh) { EAXJMP(0x5C9220); } -WRAPPER RwBool _rpMeshDestroy(RpMeshHeader* mesh) { EAXJMP(0x5C9260); } -WRAPPER RpBuildMesh* _rpBuildMeshAddTriangle(RpBuildMesh* mesh, RpMaterial* material, RwInt32 vert1, RwInt32 vert2, RwInt32 vert3) { EAXJMP(0x5C92A0); } -WRAPPER RpMeshHeader* _rpMeshHeaderForAllMeshes(RpMeshHeader* meshHeader, RpMeshCallBack fpCallBack, void* pData) { EAXJMP(0x5C9380); } -WRAPPER RwStream* _rpMeshWrite(RpMeshHeader const* meshHeader, void const* object, RwStream* stream, RpMaterialList const* matList) { EAXJMP(0x5C93C0); } -WRAPPER RpMeshHeader* _rpMeshRead(RwStream* stream, void const* object, RpMaterialList const* matList) { EAXJMP(0x5C9510); } -WRAPPER RwInt32 _rpMeshSize(RpMeshHeader const* meshHeader, void const* object) { EAXJMP(0x5C96E0); } -WRAPPER RpMeshHeader* RpBuildMeshGenerateDefaultTriStrip(RpBuildMesh* buildmesh, void* data) { EAXJMP(0x5C9730); } -WRAPPER RpMeshHeader* _rpTriListMeshGenerate(RpBuildMesh* buildMesh, void* data) { EAXJMP(0x5CAE10); } -WRAPPER RpMeshHeader* _rpMeshOptimise(RpBuildMesh* buildmesh, RwUInt32 flags) { EAXJMP(0x5CB230); } -WRAPPER RwInt32 RpWorldSectorRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5CB2B0); } -WRAPPER RwInt32 RpWorldSectorRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5CB2E0); } -WRAPPER RxPipeline* RpWorldSetDefaultSectorPipeline(RxPipeline* pipeline) { EAXJMP(0x5CB630); } -WRAPPER RxPipeline* RpAtomicSetDefaultPipeline(RxPipeline* pipeline) { EAXJMP(0x5CB670); } -WRAPPER void RpHAnimStdKeyFrameToMatrix(RwMatrix* matrix, void* voidIFrame) { EAXJMP(0x5CDEE0); } -WRAPPER void RpHAnimStdKeyFrameInterpolate(void* voidOut, void* voidIn1, void* voidIn2, RwReal time) { EAXJMP(0x5CE000); } -WRAPPER void RpHAnimStdKeyFrameBlend(void* voidOut, void* voidIn1, void* voidIn2, RwReal alpha) { EAXJMP(0x5CE420); } -WRAPPER RpHAnimAnimation* RpHAnimStdKeyFrameStreamRead(RwStream* stream, RpHAnimAnimation* animation) { EAXJMP(0x5CE820); } -WRAPPER RwBool RpHAnimStdKeyFrameStreamWrite(RpHAnimAnimation* animation, RwStream* stream) { EAXJMP(0x5CE8C0); } -WRAPPER RwInt32 RpHAnimStdKeyFrameStreamGetSize(RpHAnimAnimation* animation) { EAXJMP(0x5CE930); } -WRAPPER void RpHAnimStdKeyFrameMulRecip(void* voidFrame, void* voidStart) { EAXJMP(0x5CE950); } -WRAPPER void RpHAnimStdKeyFrameAdd(void* voidOut, void* voidIn1, void* voidIn2) { EAXJMP(0x5CEAB0); } -WRAPPER void RxHeapFree(RxHeap* heap, void* block) { EAXJMP(0x5D1070); } -WRAPPER void* RxHeapAlloc(RxHeap* heap, RwUInt32 size) { EAXJMP(0x5D1260); } -WRAPPER void* RxHeapRealloc(RxHeap* heap, void* block, RwUInt32 newSize, RwBool allowCopy) { EAXJMP(0x5D14D0); } -WRAPPER RwBool _rxHeapReset(RxHeap* heap) { EAXJMP(0x5D1680); } -WRAPPER void RxHeapDestroy(RxHeap* heap) { EAXJMP(0x5D16F0); } -WRAPPER RxHeap* RxHeapCreate(RwUInt32 size) { EAXJMP(0x5D1750); } -WRAPPER RxNodeOutput RxPipelineNodeFindOutputByName(RxPipelineNode* node, RwChar const* outputname) { EAXJMP(0x5D1EC0); } -WRAPPER RxNodeInput RxPipelineNodeFindInput(RxPipelineNode* node) { EAXJMP(0x5D1F20); } -WRAPPER RxPipeline* RxPipelineNodeRequestCluster(RxPipeline* pipeline, RxPipelineNode* node, RxClusterDefinition* clusterDef) { EAXJMP(0x5D1F30); } -WRAPPER RxPipeline* RxLockedPipeUnlock(RxLockedPipe* pipeline) { EAXJMP(0x5D1FA0); } -WRAPPER RxLockedPipe* RxPipelineLock(RxPipeline* pipeline) { EAXJMP(0x5D29F0); } -WRAPPER RxPipelineNode* RxPipelineFindNodeByName(RxPipeline* pipeline, RwChar const* name, RxPipelineNode* start, RwInt32* nodeIndex) { EAXJMP(0x5D2B10); } -WRAPPER RxLockedPipe* RxLockedPipeAddFragment(RxLockedPipe *pipeline, RwUInt32 *firstIndex, RxNodeDefinition *nodeDef0, ...) { EAXJMP(0x5D2BA0); } -WRAPPER RxPipeline* RxLockedPipeAddPath(RxLockedPipe* pipeline, RxNodeOutput out, RxNodeInput in) { EAXJMP(0x5D2EE0); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmRenderSetup() { EAXJMP(0x5D31C0); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmMangleTriangleIndices() { EAXJMP(0x5D35C0); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetCullTriangle() { EAXJMP(0x5D3C60); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetClipTriangle() { EAXJMP(0x5D4F80); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetSubmitTriangle() { EAXJMP(0x5D51C0); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmInstance() { EAXJMP(0x5D5400); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetTransform() { EAXJMP(0x5D6000); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmStash() { EAXJMP(0x5D61C0); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmMangleLineIndices() { EAXJMP(0x5D6470); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetClipLine() { EAXJMP(0x5D7230); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetSubmitLine() { EAXJMP(0x5D74C0); } -WRAPPER RwBool _rwD3D8LightsOpen() { EAXJMP(0x5D9C90); } -WRAPPER void _rwD3D8LightsClose() { EAXJMP(0x5D9EF0); } -WRAPPER RwBool _rwD3D8LightsGlobalEnable(RpLightFlag flags) { EAXJMP(0x5D9F80); } -WRAPPER RwBool _rwD3D8LightLocalEnable(RpLight* light) { EAXJMP(0x5DA210); } -WRAPPER void _rwD3D8LightsEnable(RwBool enable, RwUInt32 type) { EAXJMP(0x5DA450); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetD3D8WorldSectorAllInOne() { EAXJMP(0x5DAAC0); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetD3D8AtomicAllInOne() { EAXJMP(0x5DC500); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetWorldSectorInstance() { EAXJMP(0x5DCC50); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetWorldSectorEnumerateLights() { EAXJMP(0x5DCD80); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetAtomicInstance() { EAXJMP(0x5DD800); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetAtomicEnumerateLights() { EAXJMP(0x5DD9B0); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetMaterialScatter() { EAXJMP(0x5DDAA0); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetLight() { EAXJMP(0x5DF040); } -WRAPPER RxNodeDefinition* RxNodeDefinitionGetPostLight() { EAXJMP(0x5DF560); } -WRAPPER void RxD3D8AllInOneSetRenderCallBack(RxPipelineNode* node, RxD3D8AllInOneRenderCallBack callback) { EAXJMP(0x5DFC60); } - -WRAPPER RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags) { EAXJMP(0x59A350); } #else @@ -439,408 +36,5 @@ extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); } - -STARTPATCHES -InjectHook(0x5BC950, &_rwObjectHasFrameSetFrame, PATCH_JUMP); -InjectHook(0x59E690, &AtomicDefaultRenderCallBack, PATCH_JUMP); -InjectHook(0x59E6C0, &_rpAtomicResyncInterpolatedSphere, PATCH_JUMP); -InjectHook(0x59E800, &RpAtomicGetWorldBoundingSphere, PATCH_JUMP); -InjectHook(0x59ED50, &RpClumpGetNumAtomics, PATCH_JUMP); -InjectHook(0x59ED80, &RpClumpRender, PATCH_JUMP); -InjectHook(0x59EDD0, &RpClumpForAllAtomics, PATCH_JUMP); -InjectHook(0x59EE10, &RpClumpForAllCameras, PATCH_JUMP); -InjectHook(0x59EE60, &RpClumpForAllLights, PATCH_JUMP); -InjectHook(0x59EEB0, &RpAtomicCreate, PATCH_JUMP); -InjectHook(0x59EFA0, &RpAtomicSetGeometry, PATCH_JUMP); -InjectHook(0x59F020, &RpAtomicDestroy, PATCH_JUMP); -InjectHook(0x59F0A0, &RpAtomicClone, PATCH_JUMP); -InjectHook(0x59F1B0, &RpClumpClone, PATCH_JUMP); -InjectHook(0x59F490, &RpClumpCreate, PATCH_JUMP); -InjectHook(0x59F500, &RpClumpDestroy, PATCH_JUMP); -InjectHook(0x59F680, &RpClumpAddAtomic, PATCH_JUMP); -InjectHook(0x59F6B0, &RpClumpRemoveAtomic, PATCH_JUMP); -InjectHook(0x59F6E0, &RpClumpRemoveLight, PATCH_JUMP); -InjectHook(0x59FC50, &RpClumpStreamRead, PATCH_JUMP); -InjectHook(0x5A0510, &RpAtomicRegisterPlugin, PATCH_JUMP); -InjectHook(0x5A0540, &RpClumpRegisterPlugin, PATCH_JUMP); -InjectHook(0x5A0570, &RpAtomicRegisterPluginStream, PATCH_JUMP); -InjectHook(0x5A05A0, &RpAtomicSetStreamAlwaysCallBack, PATCH_JUMP); -InjectHook(0x5A05C0, &RpAtomicSetStreamRightsCallBack, PATCH_JUMP); -InjectHook(0x5A05E0, &RpAtomicGetPluginOffset, PATCH_JUMP); -InjectHook(0x5A0600, &RpAtomicSetFrame, PATCH_JUMP); -InjectHook(0x5A0DC0, &RwEngineRegisterPlugin, PATCH_JUMP); -InjectHook(0x5A0DF0, &RwEngineGetPluginOffset, PATCH_JUMP); -InjectHook(0x5A0E10, &RwEngineGetNumSubSystems, PATCH_JUMP); -InjectHook(0x5A0E40, &RwEngineGetSubSystemInfo, PATCH_JUMP); -InjectHook(0x5A0E70, &RwEngineGetCurrentSubSystem, PATCH_JUMP); -InjectHook(0x5A0EA0, &RwEngineSetSubSystem, PATCH_JUMP); -InjectHook(0x5A0ED0, &RwEngineGetNumVideoModes, PATCH_JUMP); -InjectHook(0x5A0F00, &RwEngineGetVideoModeInfo, PATCH_JUMP); -InjectHook(0x5A0F30, &RwEngineGetCurrentVideoMode, PATCH_JUMP); -InjectHook(0x5A0F60, &RwEngineSetVideoMode, PATCH_JUMP); -InjectHook(0x5A0F90, &RwEngineStop, PATCH_JUMP); -InjectHook(0x5A0FE0, &RwEngineStart, PATCH_JUMP); -InjectHook(0x5A1070, &RwEngineClose, PATCH_JUMP); -InjectHook(0x5A10E0, &RwEngineOpen, PATCH_JUMP); -InjectHook(0x5A1290, &RwEngineTerm, PATCH_JUMP); -InjectHook(0x5A12D0, &RwEngineInit, PATCH_JUMP); -InjectHook(0x5A15E0, &_rwFrameOpen, PATCH_JUMP); -InjectHook(0x5A1650, &_rwFrameClose, PATCH_JUMP); -InjectHook(0x5A1690, &_rwFrameCloneAndLinkClones, PATCH_JUMP); -InjectHook(0x5A1880, &_rwFramePurgeClone, PATCH_JUMP); -InjectHook(0x5A1930, &RwFrameDirty, PATCH_JUMP); -InjectHook(0x5A1950, &_rwFrameInit, PATCH_JUMP); -InjectHook(0x5A1A00, &RwFrameCreate, PATCH_JUMP); -InjectHook(0x5A1A30, &RwFrameDestroy, PATCH_JUMP); -InjectHook(0x5A1BF0, &RwFrameDestroyHierarchy, PATCH_JUMP); -InjectHook(0x5A1C60, &RwFrameUpdateObjects, PATCH_JUMP); -InjectHook(0x5A1CE0, &RwFrameGetLTM, PATCH_JUMP); -InjectHook(0x5A1D00, &RwFrameAddChild, PATCH_JUMP); -InjectHook(0x5A1ED0, &RwFrameRemoveChild, PATCH_JUMP); -InjectHook(0x5A1FC0, &RwFrameForAllChildren, PATCH_JUMP); -InjectHook(0x5A2000, &RwFrameTranslate, PATCH_JUMP); -InjectHook(0x5A20A0, &RwFrameScale, PATCH_JUMP); -InjectHook(0x5A2140, &RwFrameTransform, PATCH_JUMP); -InjectHook(0x5A21E0, &RwFrameRotate, PATCH_JUMP); -InjectHook(0x5A2280, &RwFrameSetIdentity, PATCH_JUMP); -InjectHook(0x5A2340, &RwFrameForAllObjects, PATCH_JUMP); -InjectHook(0x5A2380, &RwFrameRegisterPlugin, PATCH_JUMP); -InjectHook(0x5A23B0, &_rwMatrixSetMultFn, PATCH_JUMP); -InjectHook(0x5A2520, &_rwMatrixDeterminant, PATCH_JUMP); -InjectHook(0x5A2570, &_rwMatrixOrthogonalError, PATCH_JUMP); -InjectHook(0x5A25D0, &_rwMatrixNormalError, PATCH_JUMP); -InjectHook(0x5A2660, &_rwMatrixIdentityError, PATCH_JUMP); -InjectHook(0x5A2730, &_rwMatrixClose, PATCH_JUMP); -InjectHook(0x5A2770, &_rwMatrixOpen, PATCH_JUMP); -InjectHook(0x5A2820, &RwMatrixOptimize, PATCH_JUMP); -InjectHook(0x5A28E0, &RwMatrixUpdate, PATCH_JUMP); -InjectHook(0x5A28F0, &RwMatrixMultiply, PATCH_JUMP); -InjectHook(0x5A2960, &RwMatrixRotateOneMinusCosineSine, PATCH_JUMP); -InjectHook(0x5A2BF0, &RwMatrixRotate, PATCH_JUMP); -InjectHook(0x5A2C90, &RwMatrixInvert, PATCH_JUMP); -InjectHook(0x5A2EE0, &RwMatrixScale, PATCH_JUMP); -InjectHook(0x5A3070, &RwMatrixTranslate, PATCH_JUMP); -InjectHook(0x5A31C0, &RwMatrixTransform, PATCH_JUMP); -InjectHook(0x5A3300, &RwMatrixDestroy, PATCH_JUMP); -InjectHook(0x5A3330, &RwMatrixCreate, PATCH_JUMP); -InjectHook(0x5A3450, &_rwVectorSetMultFn, PATCH_JUMP); -InjectHook(0x5A3600, &_rwV3dNormalize, PATCH_JUMP); -InjectHook(0x5A36A0, &RwV3dLength, PATCH_JUMP); -InjectHook(0x5A3710, &_rwSqrt, PATCH_JUMP); -InjectHook(0x5A3770, &_rwInvSqrt, PATCH_JUMP); -InjectHook(0x5A37D0, &RwV3dTransformPoints, PATCH_JUMP); -InjectHook(0x5A37E0, &RwV3dTransformVectors, PATCH_JUMP); -InjectHook(0x5A37F0, &_rwVectorClose, PATCH_JUMP); -InjectHook(0x5A3860, &_rwVectorOpen, PATCH_JUMP); -InjectHook(0x5A3AD0, &RwStreamRead, PATCH_JUMP); -InjectHook(0x5A3C30, &RwStreamWrite, PATCH_JUMP); -InjectHook(0x5A3DF0, &RwStreamSkip, PATCH_JUMP); -InjectHook(0x5A3F10, &RwStreamClose, PATCH_JUMP); -InjectHook(0x5A3FE0, &RwStreamOpen, PATCH_JUMP); -InjectHook(0x5A43A0, &RwIm2DGetNearScreenZ, PATCH_JUMP); -InjectHook(0x5A43B0, &RwIm2DGetFarScreenZ, PATCH_JUMP); -InjectHook(0x5A43C0, &RwRenderStateSet, PATCH_JUMP); -InjectHook(0x5A4410, &RwRenderStateGet, PATCH_JUMP); -InjectHook(0x5A4420, &RwIm2DRenderLine, PATCH_JUMP); -InjectHook(0x5A4430, &RwIm2DRenderPrimitive, PATCH_JUMP); -InjectHook(0x5A4440, &RwIm2DRenderIndexedPrimitive, PATCH_JUMP); -InjectHook(0x5A5020, &RwCameraEndUpdate, PATCH_JUMP); -InjectHook(0x5A5030, &RwCameraBeginUpdate, PATCH_JUMP); -InjectHook(0x5A5040, &RwCameraSetViewOffset, PATCH_JUMP); -InjectHook(0x5A5070, &RwCameraSetNearClipPlane, PATCH_JUMP); -InjectHook(0x5A5140, &RwCameraSetFarClipPlane, PATCH_JUMP); -InjectHook(0x5A5170, &RwCameraFrustumTestSphere, PATCH_JUMP); -InjectHook(0x5A51E0, &RwCameraClear, PATCH_JUMP); -InjectHook(0x5A5210, &RwCameraShowRaster, PATCH_JUMP); -InjectHook(0x5A5240, &RwCameraSetProjection, PATCH_JUMP); -InjectHook(0x5A52B0, &RwCameraSetViewWindow, PATCH_JUMP); -InjectHook(0x5A52F0, &RwCameraRegisterPlugin, PATCH_JUMP); -InjectHook(0x5A5320, &RwCameraDestroy, PATCH_JUMP); -InjectHook(0x5A5360, &RwCameraCreate, PATCH_JUMP); -InjectHook(0x5A7100, &RwTextureSetMipmapping, PATCH_JUMP); -InjectHook(0x5A7120, &RwTextureGetMipmapping, PATCH_JUMP); -InjectHook(0x5A7130, &RwTextureSetAutoMipmapping, PATCH_JUMP); -InjectHook(0x5A7150, &RwTextureGetAutoMipmapping, PATCH_JUMP); -InjectHook(0x5A7160, &RwTexDictionaryCreate, PATCH_JUMP); -InjectHook(0x5A7200, &RwTexDictionaryDestroy, PATCH_JUMP); -InjectHook(0x5A7290, &RwTexDictionaryForAllTextures, PATCH_JUMP); -InjectHook(0x5A72D0, &RwTextureCreate, PATCH_JUMP); -InjectHook(0x5A7330, &RwTextureDestroy, PATCH_JUMP); -InjectHook(0x5A73B0, &RwTextureSetName, PATCH_JUMP); -InjectHook(0x5A7420, &RwTextureSetMaskName, PATCH_JUMP); -InjectHook(0x5A7490, &RwTexDictionaryAddTexture, PATCH_JUMP); -InjectHook(0x5A74D0, &RwTexDictionaryFindNamedTexture, PATCH_JUMP); -InjectHook(0x5A7550, &RwTexDictionarySetCurrent, PATCH_JUMP); -InjectHook(0x5A7570, &RwTexDictionaryGetCurrent, PATCH_JUMP); -InjectHook(0x5A7580, &RwTextureRead, PATCH_JUMP); -InjectHook(0x5A7780, &RwTextureRasterGenerateMipmaps, PATCH_JUMP); -InjectHook(0x5A9120, &RwImageCreate, PATCH_JUMP); -InjectHook(0x5A9180, &RwImageDestroy, PATCH_JUMP); -InjectHook(0x5A91E0, &RwImageAllocatePixels, PATCH_JUMP); -InjectHook(0x5A92A0, &RwImageFreePixels, PATCH_JUMP); -InjectHook(0x5A92D0, &RwImageMakeMask, PATCH_JUMP); -InjectHook(0x5A93A0, &RwImageApplyMask, PATCH_JUMP); -InjectHook(0x5A9750, &RwImageSetPath, PATCH_JUMP); -InjectHook(0x5A9810, &RwImageRead, PATCH_JUMP); -InjectHook(0x5A9B40, &RwImageFindFileType, PATCH_JUMP); -InjectHook(0x5A9C10, &RwImageReadMaskedImage, PATCH_JUMP); -InjectHook(0x5A9F50, &RwImageCopy, PATCH_JUMP); -InjectHook(0x5AA130, &RwImageGammaCorrect, PATCH_JUMP); -InjectHook(0x5AA2C0, &RwImageSetGamma, PATCH_JUMP); -InjectHook(0x5AA4E0, &_rwStreamWriteVersionedChunkHeader, PATCH_JUMP); -InjectHook(0x5AA540, &RwStreamFindChunk, PATCH_JUMP); -InjectHook(0x5AA640, &RwMemLittleEndian32, PATCH_JUMP); -InjectHook(0x5AA650, &RwMemNative32, PATCH_JUMP); -InjectHook(0x5AA660, &RwMemFloat32ToReal, PATCH_JUMP); -InjectHook(0x5AA680, &RwStreamWriteReal, PATCH_JUMP); -InjectHook(0x5AA720, &RwStreamWriteInt32, PATCH_JUMP); -InjectHook(0x5AA740, &RwStreamReadReal, PATCH_JUMP); -InjectHook(0x5AA7B0, &RwStreamReadInt32, PATCH_JUMP); -InjectHook(0x5AA800, &RwTextureStreamGetSize, PATCH_JUMP); -InjectHook(0x5AA870, &RwTextureStreamWrite, PATCH_JUMP); -InjectHook(0x5AAA40, &RwTextureStreamRead, PATCH_JUMP); -InjectHook(0x5AB020, &RwTexDictionaryStreamWrite, PATCH_JUMP); -InjectHook(0x5AC890, &RpMorphTargetCalcBoundingSphere, PATCH_JUMP); -InjectHook(0x5AC9A0, &RpGeometryAddMorphTargets, PATCH_JUMP); -InjectHook(0x5ACB60, &RpGeometryTriangleSetVertexIndices, PATCH_JUMP); -InjectHook(0x5ACB90, &RpGeometryTriangleSetMaterial, PATCH_JUMP); -InjectHook(0x5ACBF0, &RpGeometryForAllMaterials, PATCH_JUMP); -InjectHook(0x5ACC30, &RpGeometryLock, PATCH_JUMP); -InjectHook(0x5ACC60, &RpGeometryUnlock, PATCH_JUMP); -InjectHook(0x5ACD10, &RpGeometryCreate, PATCH_JUMP); -InjectHook(0x5ACF40, &_rpGeometryAddRef, PATCH_JUMP); -InjectHook(0x5ACF50, &RpGeometryDestroy, PATCH_JUMP); -InjectHook(0x5ACFF0, &RpGeometryRegisterPlugin, PATCH_JUMP); -InjectHook(0x5AD020, &RpGeometryRegisterPluginStream, PATCH_JUMP); -InjectHook(0x5AD050, &RpGeometryStreamRead, PATCH_JUMP); -InjectHook(0x5AD6D0, &RwRasterGetCurrentContext, PATCH_JUMP); -InjectHook(0x5AD6F0, &RwRasterUnlock, PATCH_JUMP); -InjectHook(0x5AD710, &RwRasterRenderFast, PATCH_JUMP); -InjectHook(0x5AD750, &RwRasterUnlockPalette, PATCH_JUMP); -InjectHook(0x5AD780, &RwRasterDestroy, PATCH_JUMP); -InjectHook(0x5AD7C0, &RwRasterPushContext, PATCH_JUMP); -InjectHook(0x5AD810, &RwRasterRegisterPlugin, PATCH_JUMP); -InjectHook(0x5AD840, &RwRasterLockPalette, PATCH_JUMP); -InjectHook(0x5AD870, &RwRasterPopContext, PATCH_JUMP); -InjectHook(0x5AD8C0, &RwRasterGetNumLevels, PATCH_JUMP); -InjectHook(0x5AD900, &RwRasterShowRaster, PATCH_JUMP); -InjectHook(0x5AD930, &RwRasterCreate, PATCH_JUMP); -InjectHook(0x5AD9D0, &RwRasterLock, PATCH_JUMP); -InjectHook(0x5ADC30, &RpMaterialCreate, PATCH_JUMP); -InjectHook(0x5ADCB0, &RpMaterialDestroy, PATCH_JUMP); -InjectHook(0x5ADD10, &RpMaterialSetTexture, PATCH_JUMP); -InjectHook(0x5ADD40, &RpMaterialRegisterPlugin, PATCH_JUMP); -InjectHook(0x5ADD70, &RpMaterialRegisterPluginStream, PATCH_JUMP); -InjectHook(0x5ADDA0, &RpMaterialStreamRead, PATCH_JUMP); -InjectHook(0x5AE0B0, &_rpSectorDefaultRenderCallBack, PATCH_JUMP); -InjectHook(0x5AE100, &_rpWorldForAllGlobalLights, PATCH_JUMP); -InjectHook(0x5AE150, &_rpWorldSectorForAllLocalLights, PATCH_JUMP); -InjectHook(0x5AE190, &RpWorldUnlock, PATCH_JUMP); -InjectHook(0x5AE2B0, &RpWorldSectorGetWorld, PATCH_JUMP); -InjectHook(0x5AE340, &RpWorldDestroy, PATCH_JUMP); -InjectHook(0x5AE6A0, &RpWorldCreate, PATCH_JUMP); -InjectHook(0x5AEA40, &RpWorldRegisterPlugin, PATCH_JUMP); -InjectHook(0x5AEA70, &RpWorldRegisterPluginStream, PATCH_JUMP); -InjectHook(0x5AEAA0, &RpWorldPluginAttach, PATCH_JUMP); -InjectHook(0x5AFB80, &RpWorldAddCamera, PATCH_JUMP); -InjectHook(0x5AFBB0, &RpWorldRemoveCamera, PATCH_JUMP); -InjectHook(0x5AFC10, &RpAtomicGetWorld, PATCH_JUMP); -InjectHook(0x5AFC20, &RpWorldAddClump, PATCH_JUMP); -InjectHook(0x5AFDA0, &RpWorldAddLight, PATCH_JUMP); -InjectHook(0x5AFDF0, &RpWorldRemoveLight, PATCH_JUMP); -InjectHook(0x5AFE70, &RtBMPImageRead, PATCH_JUMP); -InjectHook(0x5B07D0, &RpSkinPluginAttach, PATCH_JUMP); -InjectHook(0x5B1050, &RpSkinAtomicSetHAnimHierarchy, PATCH_JUMP); -InjectHook(0x5B1070, &RpSkinAtomicGetHAnimHierarchy, PATCH_JUMP); -InjectHook(0x5B1080, &RpSkinGeometryGetSkin, PATCH_JUMP); -InjectHook(0x5B1090, &RpSkinGeometrySetSkin, PATCH_JUMP); -InjectHook(0x5B10D0, &RpSkinGetSkinToBoneMatrices, PATCH_JUMP); -InjectHook(0x5B10E0, &RpHAnimHierarchyCreate, PATCH_JUMP); -InjectHook(0x5B11F0, &RpHAnimFrameGetHierarchy, PATCH_JUMP); -InjectHook(0x5B1200, &RpHAnimHierarchySetCurrentAnim, PATCH_JUMP); -InjectHook(0x5B12B0, &RpHAnimHierarchySubAnimTime, PATCH_JUMP); -InjectHook(0x5B1480, &RpHAnimHierarchyAddAnimTime, PATCH_JUMP); -InjectHook(0x5B1780, &RpHAnimHierarchyUpdateMatrices, PATCH_JUMP); -InjectHook(0x5B1C10, &RpHAnimAnimationStreamRead, PATCH_JUMP); -InjectHook(0x5B1D50, &RpHAnimPluginAttach, PATCH_JUMP); -InjectHook(0x5B2640, &RpMatFXPluginAttach, PATCH_JUMP); -InjectHook(0x5B3750, &RpMatFXAtomicEnableEffects, PATCH_JUMP); -InjectHook(0x5B3780, &RpMatFXMaterialSetEffects, PATCH_JUMP); -InjectHook(0x5B38D0, &RpMatFXMaterialSetupEnvMap, PATCH_JUMP); -InjectHook(0x5B3A40, &RpMatFXMaterialSetBumpMapTexture, PATCH_JUMP); -InjectHook(0x5B3CF0, &RwD3D8SetRenderState, PATCH_JUMP); -InjectHook(0x5B3D40, &RwD3D8GetRenderState, PATCH_JUMP); -InjectHook(0x5B3D60, &RwD3D8SetTextureStageState, PATCH_JUMP); -InjectHook(0x5B53A0, &RwD3D8SetTexture, PATCH_JUMP); -InjectHook(0x5B6720, &RwIm3DTransform, PATCH_JUMP); -InjectHook(0x5B67F0, &RwIm3DEnd, PATCH_JUMP); -InjectHook(0x5B6820, &RwIm3DRenderIndexedPrimitive, PATCH_JUMP); -InjectHook(0x5B6980, &RwIm3DRenderLine, PATCH_JUMP); -InjectHook(0x5B6A50, &RwIm3DSetTransformPipeline, PATCH_JUMP); -InjectHook(0x5B6AC0, &RwIm3DSetRenderPipeline, PATCH_JUMP); -InjectHook(0x5B95D0, &RwD3D8EngineSetRefreshRate, PATCH_JUMP); -InjectHook(0x5B9640, &RwD3D8CameraAttachWindow, PATCH_JUMP); -InjectHook(0x5BAEB0, &RwD3D8DeviceSupportsDXTTexture, PATCH_JUMP); -InjectHook(0x5BAF90, &RwD3D8SetVertexShader, PATCH_JUMP); -InjectHook(0x5BAFD0, &RwD3D8SetPixelShader, PATCH_JUMP); -InjectHook(0x5BB010, &RwD3D8SetStreamSource, PATCH_JUMP); -InjectHook(0x5BB060, &RwD3D8SetIndices, PATCH_JUMP); -InjectHook(0x5BB0B0, &RwD3D8DrawIndexedPrimitive, PATCH_JUMP); -InjectHook(0x5BB140, &RwD3D8DrawPrimitive, PATCH_JUMP); -InjectHook(0x5BB1D0, &RwD3D8SetTransform, PATCH_JUMP); -InjectHook(0x5BB310, &RwD3D8GetTransform, PATCH_JUMP); -InjectHook(0x5BB340, &RwD3D8SetTransformWorld, PATCH_JUMP); -InjectHook(0x5BB490, &RwD3D8SetSurfaceProperties, PATCH_JUMP); -InjectHook(0x5BB7A0, &RwD3D8SetLight, PATCH_JUMP); -InjectHook(0x5BB890, &RwD3D8EnableLight, PATCH_JUMP); -InjectHook(0x5BB9F0, &RwD3D8DynamicVertexBufferCreate, PATCH_JUMP); -InjectHook(0x5BBAE0, &RwD3D8DynamicVertexBufferDestroy, PATCH_JUMP); -InjectHook(0x5BBB10, &RwD3D8IndexBufferCreate, PATCH_JUMP); -InjectHook(0x5BBB40, &RwD3D8CreatePixelShader, PATCH_JUMP); -InjectHook(0x5BBB90, &RwD3D8DeletePixelShader, PATCH_JUMP); -InjectHook(0x5BBC00, &RwD3D8SetPixelShaderConstant, PATCH_JUMP); -InjectHook(0x5BBC30, &RwD3D8GetCaps, PATCH_JUMP); -InjectHook(0x5BBC40, &RwD3D8CameraIsSphereFullyInsideFrustum, PATCH_JUMP); -InjectHook(0x5BBCA0, &RwD3D8CameraIsBBoxFullyInsideFrustum, PATCH_JUMP); -InjectHook(0x5BBD30, &RwD3D8DynamicVertexBufferLock, PATCH_JUMP); -InjectHook(0x5BBEB0, &RwD3D8DynamicVertexBufferUnlock, PATCH_JUMP); -InjectHook(0x5BBED0, &_rwIntelSSEsupported, PATCH_JUMP); -InjectHook(0x5BBF10, &RwImageSetFromRaster, PATCH_JUMP); -InjectHook(0x5BBF50, &RwRasterSetFromImage, PATCH_JUMP); -InjectHook(0x5BBF80, &RwImageFindRasterFormat, PATCH_JUMP); -InjectHook(0x5BBFF0, &RwFrameRegisterPluginStream, PATCH_JUMP); -InjectHook(0x5BC020, &_rwFrameListDeinitialize, PATCH_JUMP); -InjectHook(0x5BC050, &_rwFrameListStreamRead, PATCH_JUMP); -InjectHook(0x5BC300, &RpLightSetRadius, PATCH_JUMP); -InjectHook(0x5BC320, &RpLightSetColor, PATCH_JUMP); -InjectHook(0x5BC370, &RpLightGetConeAngle, PATCH_JUMP); -InjectHook(0x5BC5B0, &RpLightRegisterPlugin, PATCH_JUMP); -InjectHook(0x5BC5E0, &RpLightStreamRead, PATCH_JUMP); -InjectHook(0x5BC780, &RpLightDestroy, PATCH_JUMP); -InjectHook(0x5BC7C0, &RpLightCreate, PATCH_JUMP); -InjectHook(0x5BE280, &_rwD3D8TexDictionaryEnableRasterFormatConversion, PATCH_JUMP); -InjectHook(0x5BF110, &RwOsGetFileInterface, PATCH_JUMP); -InjectHook(0x5C1720, &RwFreeListDestroy, PATCH_JUMP); -InjectHook(0x5C1790, &RwFreeListCreate, PATCH_JUMP); -InjectHook(0x5C19F0, &RwFreeListPurge, PATCH_JUMP); -InjectHook(0x5C1B90, &RwFreeListPurgeAllFreeLists, PATCH_JUMP); -InjectHook(0x5C1D40, &RwFreeListForAllUsed, PATCH_JUMP); -InjectHook(0x5C2780, &_rxPipelineClose, PATCH_JUMP); -InjectHook(0x5C27E0, &_rxPipelineOpen, PATCH_JUMP); -InjectHook(0x5C2AD0, &RxHeapGetGlobalHeap, PATCH_JUMP); -InjectHook(0x5C2AE0, &RxPacketCreate, PATCH_JUMP); -InjectHook(0x5C2B10, &RxClusterSetExternalData, PATCH_JUMP); -InjectHook(0x5C2B70, &RxClusterSetData, PATCH_JUMP); -InjectHook(0x5C2BD0, &RxClusterInitializeData, PATCH_JUMP); -InjectHook(0x5C2C40, &RxClusterResizeData, PATCH_JUMP); -InjectHook(0x5C2C90, &RxClusterLockWrite, PATCH_JUMP); -InjectHook(0x5C2D60, &RxPipelineExecute, PATCH_JUMP); -InjectHook(0x5C2E00, &RxPipelineCreate, PATCH_JUMP); -InjectHook(0x5C2E70, &_rxPipelineDestroy, PATCH_JUMP); -InjectHook(0x5C3080, &RwResourcesFreeResEntry, PATCH_JUMP); -InjectHook(0x5C30F0, &_rwResourcesPurge, PATCH_JUMP); -InjectHook(0x5C3170, &RwResourcesAllocateResEntry, PATCH_JUMP); -InjectHook(0x5C3360, &RwResourcesEmptyArena, PATCH_JUMP); -InjectHook(0x5C3450, &_rwPluginRegistryOpen, PATCH_JUMP); -InjectHook(0x5C3480, &_rwPluginRegistryClose, PATCH_JUMP); -InjectHook(0x5C3590, &_rwPluginRegistryGetPluginOffset, PATCH_JUMP); -InjectHook(0x5C35C0, &_rwPluginRegistryAddPlugin, PATCH_JUMP); -InjectHook(0x5C37F0, &_rwPluginRegistryInitObject, PATCH_JUMP); -InjectHook(0x5C3850, &_rwPluginRegistryDeInitObject, PATCH_JUMP); -InjectHook(0x5C3880, &_rwPluginRegistryCopyObject, PATCH_JUMP); -InjectHook(0x5C3910, &RwErrorSet, PATCH_JUMP); -InjectHook(0x5C3970, &_rwerror, PATCH_JUMP); -InjectHook(0x5C3980, &_rwPluginRegistryAddPluginStream, PATCH_JUMP); -InjectHook(0x5C39C0, &_rwPluginRegistryAddPlgnStrmlwysCB, PATCH_JUMP); -InjectHook(0x5C39F0, &_rwPluginRegistryAddPlgnStrmRightsCB, PATCH_JUMP); -InjectHook(0x5C3A20, & _rwPluginRegistryReadDataChunks, PATCH_JUMP); -InjectHook(0x5C3B50, & _rwPluginRegistryInvokeRights, PATCH_JUMP); -InjectHook(0x5C3BA0, &_rwPluginRegistryGetSize, PATCH_JUMP); -InjectHook(0x5C3BE0, &_rwPluginRegistryWriteDataChunks, PATCH_JUMP); -InjectHook(0x5C3CB0, &_rwPluginRegistrySkipDataChunks, PATCH_JUMP); -InjectHook(0x5C3D30, &RwCameraStreamRead, PATCH_JUMP); -InjectHook(0x5C5570, &RwBBoxCalculate, PATCH_JUMP); -InjectHook(0x5C72B0, &RwImageResample, PATCH_JUMP); -InjectHook(0x5C7B30, &RwImageCreateResample, PATCH_JUMP); -InjectHook(0x5D9240, &RxRenderStateVectorSetDefaultRenderStateVector, PATCH_JUMP); -InjectHook(0x5D9340, &RxRenderStateVectorCreate, PATCH_JUMP); -InjectHook(0x5D9410, &RxRenderStateVectorDestroy, PATCH_JUMP); -InjectHook(0x5D9460, &RxRenderStateVectorLoadDriverState, PATCH_JUMP); -InjectHook(0x5D95D0, &_rxEmbeddedPacketBetweenPipelines, PATCH_JUMP); -InjectHook(0x5D9740, &_rxEmbeddedPacketBetweenNodes, PATCH_JUMP); -InjectHook(0x5D9810, &_rxPacketDestroy, PATCH_JUMP); -InjectHook(0x5C8B10, &_rpMaterialListDeinitialize, PATCH_JUMP); -InjectHook(0x5C8B70, &_rpMaterialListInitialize, PATCH_JUMP); -InjectHook(0x5C8B80, &_rpMaterialListGetMaterial, PATCH_JUMP); -InjectHook(0x5C8B90, &_rpMaterialListAppendMaterial, PATCH_JUMP); -InjectHook(0x5C8C50, &_rpMaterialListFindMaterialIndex, PATCH_JUMP); -InjectHook(0x5C8C80, &_rpMaterialListStreamRead, PATCH_JUMP); -InjectHook(0x5C8FE0, &_rpMeshHeaderCreate, PATCH_JUMP); -InjectHook(0x5C8FF0, &_rpMeshClose, PATCH_JUMP); -InjectHook(0x5C9020, &_rpMeshOpen, PATCH_JUMP); -InjectHook(0x5C9140, &_rpBuildMeshCreate, PATCH_JUMP); -InjectHook(0x5C9220, &_rpBuildMeshDestroy, PATCH_JUMP); -InjectHook(0x5C9260, &_rpMeshDestroy, PATCH_JUMP); -InjectHook(0x5C92A0, &_rpBuildMeshAddTriangle, PATCH_JUMP); -InjectHook(0x5C9380, &_rpMeshHeaderForAllMeshes, PATCH_JUMP); -InjectHook(0x5C93C0, &_rpMeshWrite, PATCH_JUMP); -InjectHook(0x5C9510, &_rpMeshRead, PATCH_JUMP); -InjectHook(0x5C96E0, &_rpMeshSize, PATCH_JUMP); -InjectHook(0x5C9730, &RpBuildMeshGenerateDefaultTriStrip, PATCH_JUMP); -InjectHook(0x5CAE10, &_rpTriListMeshGenerate, PATCH_JUMP); -InjectHook(0x5CB230, &_rpMeshOptimise, PATCH_JUMP); -InjectHook(0x5CB2B0, &RpWorldSectorRegisterPlugin, PATCH_JUMP); -InjectHook(0x5CB2E0, &RpWorldSectorRegisterPluginStream, PATCH_JUMP); -InjectHook(0x5CB630, &RpWorldSetDefaultSectorPipeline, PATCH_JUMP); -InjectHook(0x5CB670, &RpAtomicSetDefaultPipeline, PATCH_JUMP); -InjectHook(0x5CDEE0, &RpHAnimStdKeyFrameToMatrix, PATCH_JUMP); -InjectHook(0x5CE000, &RpHAnimStdKeyFrameInterpolate, PATCH_JUMP); -InjectHook(0x5CE420, &RpHAnimStdKeyFrameBlend, PATCH_JUMP); -InjectHook(0x5CE820, &RpHAnimStdKeyFrameStreamRead, PATCH_JUMP); -InjectHook(0x5CE8C0, &RpHAnimStdKeyFrameStreamWrite, PATCH_JUMP); -InjectHook(0x5CE930, &RpHAnimStdKeyFrameStreamGetSize, PATCH_JUMP); -InjectHook(0x5CE950, &RpHAnimStdKeyFrameMulRecip, PATCH_JUMP); -InjectHook(0x5CEAB0, &RpHAnimStdKeyFrameAdd, PATCH_JUMP); -InjectHook(0x5D1070, &RxHeapFree, PATCH_JUMP); -InjectHook(0x5D1260, &RxHeapAlloc, PATCH_JUMP); -InjectHook(0x5D14D0, &RxHeapRealloc, PATCH_JUMP); -InjectHook(0x5D1680, &_rxHeapReset, PATCH_JUMP); -InjectHook(0x5D16F0, &RxHeapDestroy, PATCH_JUMP); -InjectHook(0x5D1750, &RxHeapCreate, PATCH_JUMP); -InjectHook(0x5D1EC0, &RxPipelineNodeFindOutputByName, PATCH_JUMP); -InjectHook(0x5D1F20, &RxPipelineNodeFindInput, PATCH_JUMP); -InjectHook(0x5D1F30, &RxPipelineNodeRequestCluster, PATCH_JUMP); -InjectHook(0x5D1FA0, &RxLockedPipeUnlock, PATCH_JUMP); -InjectHook(0x5D29F0, &RxPipelineLock, PATCH_JUMP); -InjectHook(0x5D2B10, &RxPipelineFindNodeByName, PATCH_JUMP); -InjectHook(0x5D2BA0, &RxLockedPipeAddFragment, PATCH_JUMP); -InjectHook(0x5D2EE0, &RxLockedPipeAddPath, PATCH_JUMP); -InjectHook(0x5D31C0, &RxNodeDefinitionGetImmRenderSetup, PATCH_JUMP); -InjectHook(0x5D35C0, &RxNodeDefinitionGetImmMangleTriangleIndices, PATCH_JUMP); -InjectHook(0x5D3C60, &RxNodeDefinitionGetCullTriangle, PATCH_JUMP); -InjectHook(0x5D4F80, &RxNodeDefinitionGetClipTriangle, PATCH_JUMP); -InjectHook(0x5D51C0, &RxNodeDefinitionGetSubmitTriangle, PATCH_JUMP); -InjectHook(0x5D5400, &RxNodeDefinitionGetImmInstance, PATCH_JUMP); -InjectHook(0x5D6000, &RxNodeDefinitionGetTransform, PATCH_JUMP); -InjectHook(0x5D61C0, &RxNodeDefinitionGetImmStash, PATCH_JUMP); -InjectHook(0x5D6470, &RxNodeDefinitionGetImmMangleLineIndices, PATCH_JUMP); -InjectHook(0x5D7230, &RxNodeDefinitionGetClipLine, PATCH_JUMP); -InjectHook(0x5D74C0, &RxNodeDefinitionGetSubmitLine, PATCH_JUMP); -InjectHook(0x5D9C90, &_rwD3D8LightsOpen, PATCH_JUMP); -InjectHook(0x5D9EF0, &_rwD3D8LightsClose, PATCH_JUMP); -InjectHook(0x5D9F80, &_rwD3D8LightsGlobalEnable, PATCH_JUMP); -InjectHook(0x5DA210, &_rwD3D8LightLocalEnable, PATCH_JUMP); -InjectHook(0x5DA450, &_rwD3D8LightsEnable, PATCH_JUMP); -InjectHook(0x5DAAC0, &RxNodeDefinitionGetD3D8WorldSectorAllInOne, PATCH_JUMP); -InjectHook(0x5DC500, &RxNodeDefinitionGetD3D8AtomicAllInOne, PATCH_JUMP); -InjectHook(0x5DCC50, &RxNodeDefinitionGetWorldSectorInstance, PATCH_JUMP); -InjectHook(0x5DCD80, &RxNodeDefinitionGetWorldSectorEnumerateLights, PATCH_JUMP); -InjectHook(0x5DD800, &RxNodeDefinitionGetAtomicInstance, PATCH_JUMP); -InjectHook(0x5DD9B0, &RxNodeDefinitionGetAtomicEnumerateLights, PATCH_JUMP); -InjectHook(0x5DDAA0, &RxNodeDefinitionGetMaterialScatter, PATCH_JUMP); -InjectHook(0x5DF040, &RxNodeDefinitionGetLight, PATCH_JUMP); -InjectHook(0x5DF560, &RxNodeDefinitionGetPostLight, PATCH_JUMP); -InjectHook(0x5DFC60, &RxD3D8AllInOneSetRenderCallBack, PATCH_JUMP); -ENDPATCHES #endif #endif \ No newline at end of file diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 88f32c33..763f516a 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -1,7 +1,7 @@ #define WITHWINDOWS #include "common.h" #include "main.h" -#include "patcher.h" + #include "AudioScriptObject.h" #include "Camera.h" #include "CarGen.h" @@ -553,22 +553,3 @@ align4bytes(int32 size) { return (size + 3) & 0xFFFFFFFC; } - -STARTPATCHES - InjectHook(0x58F8D0, GenericSave, PATCH_JUMP); - InjectHook(0x590A00, GenericLoad, PATCH_JUMP); - InjectHook(0x591910, ReadInSizeofSaveFileBuffer, PATCH_JUMP); - InjectHook(0x591990, ReadDataFromFile, PATCH_JUMP); - InjectHook(0x591A00, CloseFile, PATCH_JUMP); - InjectHook(0x591A20, DoGameSpecificStuffAfterSucessLoad, PATCH_JUMP); - InjectHook(0x591A40, CheckSlotDataValid, PATCH_JUMP); - InjectHook(0x591A80, MakeSpaceForSizeInBufferPointer, PATCH_JUMP); - InjectHook(0x591AA0, CopySizeAndPreparePointer, PATCH_JUMP); - InjectHook(0x591AE0, DoGameSpecificStuffBeforeSave, PATCH_JUMP); - InjectHook(0x591B10, MakeValidSaveName, PATCH_JUMP); - InjectHook(0x591B50, GetSavedGameDateAndTime, PATCH_JUMP); - InjectHook(0x591B60, GetNameOfSavedGame, PATCH_JUMP); - InjectHook(0x591B70, CheckDataNotCorrupt, PATCH_JUMP); - InjectHook(0x591D60, RestoreForStartLoad, PATCH_JUMP); - InjectHook(0x591E80, align4bytes, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 06024e04..3794ba88 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -1,6 +1,6 @@ #define WITHWINDOWS #include "common.h" -#include "patcher.h" + #include "FileMgr.h" #include "GenericGameStorage.h" #include "Messages.h" @@ -136,11 +136,3 @@ C_PcSave::PopulateSlotInfo() } } } - -STARTPATCHES - InjectHook(0x591EA0, C_PcSave::SetSaveDirectory, PATCH_JUMP); - InjectHook(0x5922F0, &C_PcSave::DeleteSlot, PATCH_JUMP); - InjectHook(0x591EC0, &C_PcSave::SaveSlot, PATCH_JUMP); - InjectHook(0x591F80, &C_PcSave::PcClassSaveRoutine, PATCH_JUMP); - InjectHook(0x592090, &C_PcSave::PopulateSlotInfo, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/skel/events.cpp b/src/skel/events.cpp index 60e1482e..5d16d5b0 100644 --- a/src/skel/events.cpp +++ b/src/skel/events.cpp @@ -12,7 +12,7 @@ #include "Camera.h" -#include "patcher.h" + /* ***************************************************************************** @@ -832,14 +832,3 @@ AttachInputDevices(void) return TRUE; } - - -STARTPATCHES - InjectHook(0x583F10, HandleKeyDown, PATCH_JUMP); - InjectHook(0x5842F0, HandleKeyUp, PATCH_JUMP); - InjectHook(0x5846C0, KeyboardHandler, PATCH_JUMP); - InjectHook(0x5846F0, HandlePadButtonDown, PATCH_JUMP); - InjectHook(0x584770, HandlePadButtonUp, PATCH_JUMP); - InjectHook(0x584830, PadHandler, PATCH_JUMP); - InjectHook(0x584860, AttachInputDevices, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index a02d7e0b..f48089cb 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include #include @@ -415,26 +415,3 @@ RsInitialise(void) return result; } - - - - -STARTPATCHES - InjectHook(0x584890, RsTimer, PATCH_JUMP); - InjectHook(0x5848A0, RsCameraShowRaster, PATCH_JUMP); - InjectHook(0x5848B0, RsCameraBeginUpdate, PATCH_JUMP); - InjectHook(0x5848C0, RsRegisterImageLoader, PATCH_JUMP); - InjectHook(0x5848D0, RsSetDebug, PATCH_JUMP); - InjectHook(0x5848E0, RsMouseSetPos, PATCH_JUMP); - InjectHook(0x5848F0, RsSelectDevice, PATCH_JUMP); - InjectHook(0x584900, RsInputDeviceAttach, PATCH_JUMP); - InjectHook(0x584960, rsCommandLine, PATCH_JUMP); - InjectHook(0x584980, rsPreInitCommandLine, PATCH_JUMP); - InjectHook(0x5849C0, RsKeyboardEventHandler, PATCH_JUMP); - InjectHook(0x5849F0, RsPadEventHandler, PATCH_JUMP); - InjectHook(0x584A20, RsEventHandler, PATCH_JUMP); - InjectHook(0x584B30, RsRwTerminate, PATCH_JUMP); - InjectHook(0x584B40, RsRwInitialise, PATCH_JUMP); - InjectHook(0x584C30, RsTerminate, PATCH_JUMP); - InjectHook(0x584C40, RsInitialise, PATCH_JUMP); -ENDPATCHES \ No newline at end of file diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index 351b7247..a534e903 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1366,7 +1366,7 @@ psSelectDevice() { return FALSE; } - + if (vm.flags & rwVIDEOMODEEXCLUSIVE) { debug("%dx%dx%d", vm.width, vm.height, vm.depth); @@ -1754,7 +1754,7 @@ void HandleExit() ***************************************************************************** */ int PASCAL -_WinMain(HINSTANCE instance, +WinMain(HINSTANCE instance, HINSTANCE prevInstance __RWUNUSED__, CMDSTR cmdLine, int cmdShow) @@ -1763,7 +1763,7 @@ _WinMain(HINSTANCE instance, RwV2d pos; RwInt32 argc, i; RwChar **argv; - + StaticPatcher::Apply(); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); /* @@ -3025,60 +3025,3 @@ int strcasecmp(const char *str1, const char *str2) return _strcmpi(str1, str2); } #endif - - -STARTPATCHES - //InjectHook(0x580B30, &CJoySticks::CJoySticks, PATCH_JUMP); - //InjectHook(0x580B50, &CJoySticks::ClearJoyInfo, PATCH_JUMP); - InjectHook(0x580B70, _psCreateFolder, PATCH_JUMP); - InjectHook(0x580BB0, _psGetUserFilesFolder, PATCH_JUMP); - InjectHook(0x580C70, psCameraBeginUpdate, PATCH_JUMP); - InjectHook(0x580CA0, psCameraShowRaster, PATCH_JUMP); - InjectHook(0x580CE0, psTimer, PATCH_JUMP); - InjectHook(0x580D20, psMouseSetPos, PATCH_JUMP); - InjectHook(0x580E10, psGetMemoryFunctions, PATCH_JUMP); - InjectHook(0x580E20, psInstallFileSystem, PATCH_JUMP); - InjectHook(0x580E30, psNativeTextureSupport, PATCH_JUMP); - InjectHook(0x580E40, InitApplication, PATCH_JUMP); - InjectHook(0x580EB0, InitInstance, PATCH_JUMP); - InjectHook(0x580F30, _GetVideoMemInfo, PATCH_JUMP); - InjectHook(0x580FA0, GetDXVersion, PATCH_JUMP); - InjectHook(0x5810C0, _psGetCpuVendr, PATCH_JUMP); - InjectHook(0x5810E0, _psGetCpuFeatures, PATCH_JUMP); - InjectHook(0x5810F0, _psGetCpuFeaturesEx, PATCH_JUMP); - InjectHook(0x581120, _psPrintCpuInfo, PATCH_JUMP); - InjectHook(0x581180, psInitialise, PATCH_JUMP); - InjectHook(0x581460, psTerminate, PATCH_JUMP); - InjectHook(0x581470, _psGetNumVideModes, PATCH_JUMP); - InjectHook(0x581480, _psFreeVideoModeList, PATCH_JUMP); - InjectHook(0x5814F0, _psGetVideoModeList, PATCH_JUMP); - InjectHook(0x581630, _psSelectScreenVM, PATCH_JUMP); - InjectHook(0x5816B0, WaitForState, PATCH_JUMP); - InjectHook(0x5816E0, HandleGraphEvent, PATCH_JUMP); - InjectHook(0x581790, MainWndProc, PATCH_JUMP); - InjectHook(0x581C90, IsForegroundApp, PATCH_JUMP); - InjectHook(0x581CB0, GetBestRefreshRate, PATCH_JUMP); - InjectHook(0x581D80, psSelectDevice, PATCH_JUMP); - InjectHook(0x581F90, _psSetVideoMode, PATCH_JUMP); - InjectHook(0x582030, CommandLineToArgv, PATCH_JUMP); - InjectHook(0x582160, InitialiseLanguage, PATCH_JUMP); - InjectHook(0x5822F0, CenterVideo, PATCH_JUMP); - InjectHook(0x582380, PlayMovieInWindow, PATCH_JUMP); - InjectHook(0x5825E0, CloseInterfaces, PATCH_JUMP); - InjectHook(0x582680, CloseClip, PATCH_JUMP); - InjectHook(0x5826A0, HandleExit, PATCH_JUMP); - InjectHook(0x582710, _WinMain, PATCH_JUMP); - InjectHook(0x5830D0, _InputInitialise, PATCH_JUMP); - InjectHook(0x583110, _InputInitialiseMouse, PATCH_JUMP); - InjectHook(0x583190, CapturePad, PATCH_JUMP); - InjectHook(0x583580, _InputInitialiseJoys, PATCH_JUMP); - InjectHook(0x583670, _InputAddJoyStick, PATCH_JUMP); - InjectHook(0x583810, _InputAddJoys, PATCH_JUMP); - InjectHook(0x583870, _InputGetMouseState, PATCH_JUMP); - InjectHook(0x583910, _InputShutdown, PATCH_JUMP); - InjectHook(0x583940, _InputEnumDevicesCallback, PATCH_JUMP); - InjectHook(0x583A20, _InputTranslateKey, PATCH_JUMP); - InjectHook(0x583DC0, _InputTranslateShiftKeyUpDown, PATCH_JUMP); - InjectHook(0x583E50, _InputTranslateShiftKey, PATCH_JUMP); - InjectHook(0x583EE0, _InputIsExtended, PATCH_JUMP); -ENDPATCHES diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp index 67a7bab4..3233ebc4 100644 --- a/src/text/Messages.cpp +++ b/src/text/Messages.cpp @@ -2,7 +2,7 @@ #include "dinput.h" #include "common.h" -#include "patcher.h" + #include "Messages.h" #include "RwHelper.h" #include "Hud.h" @@ -803,33 +803,3 @@ CMessages::ClearAllMessagesDisplayedByGame() CHud::GetRidOfAllHudMessages(); CUserDisplay::Pager.ClearMessages(); } - -STARTPATCHES - InjectHook(0x529310, CMessages::Init, PATCH_JUMP); - InjectHook(0x529490, CMessages::GetWideStringLength, PATCH_JUMP); - InjectHook(0x5294B0, CMessages::WideStringCopy, PATCH_JUMP); - InjectHook(0x529510, CMessages::WideStringCompare, PATCH_JUMP); - InjectHook(0x529580, CMessages::Process, PATCH_JUMP); - InjectHook(0x529800, CMessages::Display, PATCH_JUMP); - InjectHook(0x529900, CMessages::AddMessage, PATCH_JUMP); - InjectHook(0x529A10, CMessages::AddMessageJumpQ, PATCH_JUMP); - InjectHook(0x529AF0, CMessages::AddMessageSoon, PATCH_JUMP); - InjectHook(0x529CE0, CMessages::ClearMessages, PATCH_JUMP); - InjectHook(0x529E00, CMessages::ClearSmallMessagesOnly, PATCH_JUMP); - InjectHook(0x529EB0, CMessages::AddBigMessage, PATCH_JUMP); - InjectHook(0x529F60, CMessages::AddBigMessageQ, PATCH_JUMP); - InjectHook(0x52A040, CMessages::AddToPreviousBriefArray, PATCH_JUMP); - InjectHook(0x52A1A0, CMessages::InsertNumberInString, PATCH_JUMP); - InjectHook(0x52A300, CMessages::InsertStringInString, PATCH_JUMP); - InjectHook(0x52A490, CMessages::InsertPlayerControlKeysInString, PATCH_JUMP); - InjectHook(0x52A850, CMessages::AddMessageWithNumber, PATCH_JUMP); - InjectHook(0x52A9A0, CMessages::AddMessageJumpQWithNumber, PATCH_JUMP); - InjectHook(0x52AAC0, CMessages::AddMessageSoonWithNumber, PATCH_JUMP); - InjectHook(0x52AD10, CMessages::AddBigMessageWithNumber, PATCH_JUMP); - InjectHook(0x52AE00, CMessages::AddBigMessageWithNumberQ, PATCH_JUMP); - InjectHook(0x52AF30, CMessages::AddMessageWithString, PATCH_JUMP); - InjectHook(0x52B050, CMessages::AddMessageJumpQWithString, PATCH_JUMP); - InjectHook(0x52B140, CMessages::ClearThisPrint, PATCH_JUMP); - InjectHook(0x52B3C0, CMessages::ClearThisBigPrint, PATCH_JUMP); - InjectHook(0x52B670, CMessages::ClearAllMessagesDisplayedByGame, PATCH_JUMP); -ENDPATCHES diff --git a/src/text/Pager.cpp b/src/text/Pager.cpp index 5c6b3ee2..565f2c20 100644 --- a/src/text/Pager.cpp +++ b/src/text/Pager.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Pager.h" #include "Timer.h" #include "Messages.h" @@ -181,14 +181,4 @@ CPager::RestartCurrentMessage() m_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10); m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs; } -} - -STARTPATCHES - InjectHook(0x52B6F0, &CPager::Init, PATCH_JUMP); - InjectHook(0x52B740, &CPager::Process, PATCH_JUMP); - InjectHook(0x52B890, &CPager::Display, PATCH_JUMP); - InjectHook(0x52B940, &CPager::AddMessage, PATCH_JUMP); - InjectHook(0x52BB50, &CPager::AddMessageWithNumber, PATCH_JUMP); - InjectHook(0x52BE50, &CPager::RestartCurrentMessage, PATCH_JUMP); - InjectHook(0x52BE00, &CPager::ClearMessages, PATCH_JUMP); -ENDPATCHES \ No newline at end of file +} \ No newline at end of file diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 144dfed1..69025df1 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "FileMgr.h" #include "Frontend.h" #include "Messages.h" @@ -304,21 +304,3 @@ TextCopy(wchar *dst, const wchar *src) { while((*dst++ = *src++) != '\0'); } - - -STARTPATCHES - InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP); - InjectHook(0x52C580, &CText::Unload, PATCH_JUMP); - InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP); - InjectHook(0x52C220, &CText::GetUpperCase, PATCH_JUMP); - InjectHook(0x52C2C0, &CText::UpperCase, PATCH_JUMP); - - InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP); - InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP); - InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP); - InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP); - InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP); - - InjectHook(0x52C120, &CData::Load, PATCH_JUMP); - InjectHook(0x52C200, &CData::Unload, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 0a0bc7a6..c2a664a6 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "main.h" -#include "patcher.h" + #include "General.h" #include "RwHelper.h" #include "Pad.h" @@ -4492,88 +4492,3 @@ CAutomobile::SetAllTaxiLights(bool set) { m_sAllTaxiLights = set; } - -#include - -class CAutomobile_ : public CAutomobile -{ -public: - void ctor(int32 id, uint8 CreatedBy) { ::new (this) CAutomobile(id, CreatedBy); } - void dtor() { CAutomobile::~CAutomobile(); } - void SetModelIndex_(uint32 id) { CAutomobile::SetModelIndex(id); } - void ProcessControl_(void) { CAutomobile::ProcessControl(); } - void Teleport_(CVector v) { CAutomobile::Teleport(v); } - void PreRender_(void) { CAutomobile::PreRender(); } - void Render_(void) { CAutomobile::Render(); } - - int32 ProcessEntityCollision_(CEntity *ent, CColPoint *colpoints){ return CAutomobile::ProcessEntityCollision(ent, colpoints); } - - void ProcessControlInputs_(uint8 pad) { CAutomobile::ProcessControlInputs(pad); } - void GetComponentWorldPosition_(int32 component, CVector &pos) { CAutomobile::GetComponentWorldPosition(component, pos); } - bool IsComponentPresent_(int32 component) { return CAutomobile::IsComponentPresent(component); } - void SetComponentRotation_(int32 component, CVector rotation) { CAutomobile::SetComponentRotation(component, rotation); } - void OpenDoor_(int32 component, eDoors door, float ratio) { CAutomobile::OpenDoor(component, door, ratio); } - void ProcessOpenDoor_(uint32 component, uint32 anim, float time) { CAutomobile::ProcessOpenDoor(component, anim, time); } - bool IsDoorReady_(eDoors door) { return CAutomobile::IsDoorReady(door); } - bool IsDoorFullyOpen_(eDoors door) { return CAutomobile::IsDoorFullyOpen(door); } - bool IsDoorClosed_(eDoors door) { return CAutomobile::IsDoorClosed(door); } - bool IsDoorMissing_(eDoors door) { return CAutomobile::IsDoorMissing(door); } - void RemoveRefsToVehicle_(CEntity *ent) { CAutomobile::RemoveRefsToVehicle(ent); } - void BlowUpCar_(CEntity *ent) { CAutomobile::BlowUpCar(ent); } - bool SetUpWheelColModel_(CColModel *colModel) { return CAutomobile::SetUpWheelColModel(colModel); } - void BurstTyre_(uint8 tyre) { CAutomobile::BurstTyre(tyre); } - bool IsRoomForPedToLeaveCar_(uint32 door, CVector *pos) { return CAutomobile::IsRoomForPedToLeaveCar(door, pos); } - float GetHeightAboveRoad_(void) { return CAutomobile::GetHeightAboveRoad(); } - void PlayCarHorn_(void) { CAutomobile::PlayCarHorn(); } -}; - -STARTPATCHES - InjectHook(0x52C6B0, &CAutomobile_::ctor, PATCH_JUMP); - InjectHook(0x52D170, &CAutomobile_::dtor, PATCH_JUMP); - InjectHook(0x52D190, &CAutomobile_::SetModelIndex_, PATCH_JUMP); - InjectHook(0x531470, &CAutomobile_::ProcessControl_, PATCH_JUMP); - InjectHook(0x535180, &CAutomobile_::Teleport_, PATCH_JUMP); - InjectHook(0x539EA0, &CAutomobile_::Render_, PATCH_JUMP); - InjectHook(0x535B40, &CAutomobile_::PreRender_, PATCH_JUMP); - InjectHook(0x53B270, &CAutomobile_::ProcessEntityCollision_, PATCH_JUMP); - InjectHook(0x53B660, &CAutomobile_::ProcessControlInputs_, PATCH_JUMP); - InjectHook(0x52E5F0, &CAutomobile_::GetComponentWorldPosition_, PATCH_JUMP); - InjectHook(0x52E660, &CAutomobile_::IsComponentPresent_, PATCH_JUMP); - InjectHook(0x52E680, &CAutomobile_::SetComponentRotation_, PATCH_JUMP); - InjectHook(0x52E750, &CAutomobile_::OpenDoor_, PATCH_JUMP); - InjectHook(0x52EF10, &CAutomobile_::IsDoorReady_, PATCH_JUMP); - InjectHook(0x52EF90, &CAutomobile_::IsDoorFullyOpen_, PATCH_JUMP); - InjectHook(0x52EFD0, &CAutomobile_::IsDoorClosed_, PATCH_JUMP); - InjectHook(0x52F000, &CAutomobile_::IsDoorMissing_, PATCH_JUMP); - InjectHook(0x53BF40, &CAutomobile_::RemoveRefsToVehicle_, PATCH_JUMP); - InjectHook(0x53BC60, &CAutomobile_::BlowUpCar_, PATCH_JUMP); - InjectHook(0x53BF70, &CAutomobile_::SetUpWheelColModel_, PATCH_JUMP); - InjectHook(0x53C0E0, &CAutomobile_::BurstTyre_, PATCH_JUMP); - InjectHook(0x53C5B0, &CAutomobile_::IsRoomForPedToLeaveCar_, PATCH_JUMP); - InjectHook(0x437690, &CAutomobile_::GetHeightAboveRoad_, PATCH_JUMP); - InjectHook(0x53C450, &CAutomobile_::PlayCarHorn_, PATCH_JUMP); - InjectHook(0x53E090, &CAutomobile::PlaceOnRoadProperly, PATCH_JUMP); - InjectHook(0x52F030, &CAutomobile::dmgDrawCarCollidingParticles, PATCH_JUMP); - InjectHook(0x535450, &CAutomobile::AddDamagedVehicleParticles, PATCH_JUMP); - InjectHook(0x5357D0, &CAutomobile::AddWheelDirtAndWater, PATCH_JUMP); - InjectHook(0x5353A0, &CAutomobile::ResetSuspension, PATCH_JUMP); - InjectHook(0x52D210, &CAutomobile::SetupSuspensionLines, PATCH_JUMP); - InjectHook(0x53E000, &CAutomobile::BlowUpCarsInPath, PATCH_JUMP); - InjectHook(0x42E220, &CAutomobile::HasCarStoppedBecauseOfLight, PATCH_JUMP); - InjectHook(0x53D320, &CAutomobile::SetBusDoorTimer, PATCH_JUMP); - InjectHook(0x53D370, &CAutomobile::ProcessAutoBusDoors, PATCH_JUMP); - InjectHook(0x535250, &CAutomobile::ProcessSwingingDoor, PATCH_JUMP); - InjectHook(0x53C240, &CAutomobile::Fix, PATCH_JUMP); - InjectHook(0x53C310, &CAutomobile::SetupDamageAfterLoad, PATCH_JUMP); - InjectHook(0x530300, &CAutomobile::SpawnFlyingComponent, PATCH_JUMP); - InjectHook(0x535320, &CAutomobile::RemoveBonnetInPedCollision, PATCH_JUMP); - InjectHook(0x5301A0, &CAutomobile::SetPanelDamage, PATCH_JUMP); - InjectHook(0x530120, &CAutomobile::SetBumperDamage, PATCH_JUMP); - InjectHook(0x530200, &CAutomobile::SetDoorDamage, PATCH_JUMP); - InjectHook(0x5300E0, &CAutomobile::SetComponentVisibility, PATCH_JUMP); - InjectHook(0x52D1B0, &CAutomobile::SetupModelNodes, PATCH_JUMP); - InjectHook(0x53C420, &CAutomobile::SetTaxiLight, PATCH_JUMP); - InjectHook(0x53BC40, &CAutomobile::GetAllWheelsOffGround, PATCH_JUMP); - InjectHook(0x5308C0, &CAutomobile::ReduceHornCounter, PATCH_JUMP); - InjectHook(0x53C440, &CAutomobile::SetAllTaxiLights, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 478257b6..ed38bafd 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "Timecycle.h" #include "HandlingMgr.h" @@ -850,24 +850,3 @@ CBoat::AddWakePoint(CVector point) m_nNumWakePoints = 1; } } - -#include - -class CBoat_ : public CBoat -{ -public: - CBoat* ctor(int32 id, uint8 CreatedBy) { return ::new (this) CBoat(id, CreatedBy); } - void dtor() { CBoat::~CBoat(); }; -}; - -STARTPATCHES - InjectHook(0x53E3E0, &CBoat_::ctor, PATCH_JUMP); - InjectHook(0x53E790, &CBoat_::dtor, PATCH_JUMP); - InjectHook(0x53E7D0, &CBoat::SetupModelNodes, PATCH_JUMP); - InjectHook(0x542370, CBoat::IsSectorAffectedByWake, PATCH_JUMP); - InjectHook(0x5424A0, CBoat::IsVertexAffectedByWake, PATCH_JUMP); - InjectHook(0x542250, CBoat::FillBoatList, PATCH_JUMP); - InjectHook(0x542140, &CBoat::AddWakePoint, PATCH_JUMP); - InjectHook(0x5420D0, &CBoat::PruneWakeTrail, PATCH_JUMP); - InjectHook(0x541A30, &CBoat::ApplyWaterResistance, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index c35005a1..4156ec2a 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "CarGen.h" #include "Automobile.h" @@ -249,10 +249,3 @@ INITSAVEBUF CarGeneratorArray[i] = ReadSaveBuf(buffer); VALIDATESAVEBUF(size) } - -STARTPATCHES -InjectHook(0x543020, CTheCarGenerators::Init, PATCH_JUMP); -InjectHook(0x542F40, CTheCarGenerators::Process, PATCH_JUMP); -InjectHook(0x543050, CTheCarGenerators::SaveAllCarGenerators, PATCH_JUMP); -InjectHook(0x5431E0, CTheCarGenerators::LoadAllCarGenerators, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index dbc3c340..ef19873c 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Cranes.h" #include "Camera.h" diff --git a/src/vehicles/DamageManager.cpp b/src/vehicles/DamageManager.cpp index 9a697b6b..03ccfe77 100644 --- a/src/vehicles/DamageManager.cpp +++ b/src/vehicles/DamageManager.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "General.h" #include "Vehicle.h" #include "DamageManager.h" @@ -228,24 +228,3 @@ CDamageManager::ProgressEngineDamage(void) SetEngineStatus(newstatus); return true; } - -STARTPATCHES - InjectHook(0x545850, &CDamageManager::ResetDamageStatus, PATCH_JUMP); - InjectHook(0x545B70, &CDamageManager::FuckCarCompletely, PATCH_JUMP); - InjectHook(0x545790, &CDamageManager::GetComponentGroup, PATCH_JUMP); - InjectHook(0x545A80, &CDamageManager::ApplyDamage, PATCH_JUMP); - InjectHook(0x545920, &CDamageManager::SetDoorStatus, PATCH_JUMP); - InjectHook(0x545930, &CDamageManager::GetDoorStatus, PATCH_JUMP); - InjectHook(0x545970, &CDamageManager::ProgressDoorDamage, PATCH_JUMP); - InjectHook(0x5458B0, &CDamageManager::SetPanelStatus, PATCH_JUMP); - InjectHook(0x5458E0, (int32 (CDamageManager::*)(int32))&CDamageManager::GetPanelStatus, PATCH_JUMP); - InjectHook(0x545A00, &CDamageManager::ProgressPanelDamage, PATCH_JUMP); - InjectHook(0x545860, &CDamageManager::SetLightStatus, PATCH_JUMP); - InjectHook(0x545890, &CDamageManager::GetLightStatus, PATCH_JUMP); - InjectHook(0x545900, &CDamageManager::SetWheelStatus, PATCH_JUMP); - InjectHook(0x545910, &CDamageManager::GetWheelStatus, PATCH_JUMP); - InjectHook(0x545A40, &CDamageManager::ProgressWheelDamage, PATCH_JUMP); - InjectHook(0x545940, &CDamageManager::SetEngineStatus, PATCH_JUMP); - InjectHook(0x545960, &CDamageManager::GetEngineStatus, PATCH_JUMP); - InjectHook(0x5459B0, &CDamageManager::ProgressEngineDamage, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Door.cpp b/src/vehicles/Door.cpp index c569be59..c80965aa 100644 --- a/src/vehicles/Door.cpp +++ b/src/vehicles/Door.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Vehicle.h" #include "Door.h" @@ -168,19 +168,3 @@ CTrainDoor::IsClosed(void) { return m_fPosn == RetTranslationWhenClosed(); } - -STARTPATCHES - InjectHook(0x545EF0, &CDoor::Open, PATCH_JUMP); - InjectHook(0x545BD0, &CDoor::Process, PATCH_JUMP); - InjectHook(0x545FE0, &CDoor::RetAngleWhenClosed, PATCH_JUMP); - InjectHook(0x546020, &CDoor::RetAngleWhenOpen, PATCH_JUMP); - InjectHook(0x545F80, &CDoor::GetAngleOpenRatio, PATCH_JUMP); - InjectHook(0x546090, &CDoor::IsFullyOpen, PATCH_JUMP); - InjectHook(0x546060, &CDoor::IsClosed, PATCH_JUMP); - - InjectHook(0x546200, &CTrainDoor::Open, PATCH_JUMP); - InjectHook(0x546180, &CTrainDoor::RetTranslationWhenClosed, PATCH_JUMP); - InjectHook(0x5461C0, &CTrainDoor::RetTranslationWhenOpen, PATCH_JUMP); - InjectHook(0x546120, &CTrainDoor::IsFullyOpen, PATCH_JUMP); - InjectHook(0x5460F0, &CTrainDoor::IsClosed, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Floater.cpp b/src/vehicles/Floater.cpp index 8b5e1e0a..1ae1c5c3 100644 --- a/src/vehicles/Floater.cpp +++ b/src/vehicles/Floater.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Timer.h" #include "WaterLevel.h" #include "ModelIndices.h" @@ -183,12 +183,3 @@ cBuoyancy::CalcBuoyancyForce(CPhysical *phys, CVector *point, CVector *impulse) *impulse = CVector(0.0f, 0.0f, m_volumeUnderWater*m_buoyancy*CTimer::GetTimeStep()); return true; } - -STARTPATCHES - InjectHook(0x546270, &cBuoyancy::ProcessBuoyancy, PATCH_JUMP); - InjectHook(0x546360, &cBuoyancy::PreCalcSetup, PATCH_JUMP); - InjectHook(0x5466F0, &cBuoyancy::SimpleCalcBuoyancy, PATCH_JUMP); - InjectHook(0x546820, &cBuoyancy::SimpleSumBuoyancyData, PATCH_JUMP); - InjectHook(0x546620, &cBuoyancy::FindWaterLevel, PATCH_JUMP); - InjectHook(0x5465A0, &cBuoyancy::CalcBuoyancyForce, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index b33015ab..3ac0da38 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "FileMgr.h" #include "HandlingMgr.h" @@ -237,11 +237,3 @@ cHandlingDataMgr::GetHandlingId(const char *name) break; return i; } - -STARTPATCHES - InjectHook(0x546D80, &cHandlingDataMgr::Initialise, PATCH_JUMP); - InjectHook(0x546DB0, &cHandlingDataMgr::LoadHandlingData, PATCH_JUMP); - InjectHook(0x546BB0, &cHandlingDataMgr::ConvertDataToGameUnits, PATCH_JUMP); - InjectHook(0x546AA0, &cHandlingDataMgr::FindExactWord, PATCH_JUMP); - InjectHook(0x546B70, &cHandlingDataMgr::GetHandlingId, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 81ac9bd3..1f92b678 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "main.h" -#include "patcher.h" + #include "General.h" #include "Darkel.h" #include "Stats.h" @@ -1043,24 +1043,3 @@ void CHeli::MakeCatalinaHeliFlyAway(void) { pHelis[HELI_CATALINA]->m_pathState = bool CHeli::HasCatalinaBeenShotDown(void) { return CatalinaHasBeenShotDown; } void CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; } - -#include - -class CHeli_ : public CHeli -{ -public: - void ctor(int32 id, uint8 CreatedBy) { ::new (this) CHeli(id, CreatedBy); } - void dtor(void) { CHeli::~CHeli(); } -}; - -STARTPATCHES - InjectHook(0x547220, &CHeli_::ctor, PATCH_JUMP); - InjectHook(0x5474A0, &CHeli_::dtor, PATCH_JUMP); - InjectHook(0x54AE50, &CHeli::SpawnFlyingComponent, PATCH_JUMP); - InjectHook(0x549970, CHeli::InitHelis, PATCH_JUMP); - InjectHook(0x5499F0, CHeli::UpdateHelis, PATCH_JUMP); - InjectHook(0x54AE10, CHeli::SpecialHeliPreRender, PATCH_JUMP); - InjectHook(0x54AA30, CHeli::TestRocketCollision, PATCH_JUMP); - InjectHook(0x54AB30, CHeli::TestBulletCollision, PATCH_JUMP); - InjectHook(0x54A640, GenerateHeli, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 892bc0d5..273ac54a 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "main.h" -#include "patcher.h" + #include "General.h" #include "ModelIndices.h" #include "FileMgr.h" @@ -965,24 +965,3 @@ const CVector CPlane::FindDropOffCesnaCoordinates(void) { return pDropOffCesna-> bool CPlane::HasCesnaLanded(void) { return CesnaMissionStatus == CESNA_STATUS_LANDED; } bool CPlane::HasCesnaBeenDestroyed(void) { return CesnaMissionStatus == CESNA_STATUS_DESTROYED; } bool CPlane::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatus == CESNA_STATUS_DESTROYED; } - -#include - -class CPlane_ : public CPlane -{ -public: - void ctor(int32 id, uint8 CreatedBy) { ::new (this) CPlane(id, CreatedBy); } - void dtor(void) { CPlane::~CPlane(); } -}; - -STARTPATCHES - InjectHook(0x54B170, &CPlane_::ctor, PATCH_JUMP); - InjectHook(0x54B270, &CPlane_::dtor, PATCH_JUMP); - InjectHook(0x54B820, CPlane::InitPlanes, PATCH_JUMP); - InjectHook(0x54BCD0, CPlane::Shutdown, PATCH_JUMP); - InjectHook(0x54BD50, CPlane::LoadPath, PATCH_JUMP); - InjectHook(0x54BEC0, CPlane::UpdatePlanes, PATCH_JUMP); - InjectHook(0x54DE90, CPlane::TestRocketCollision, PATCH_JUMP); - InjectHook(0x54E000, CPlane::CreateIncomingCesna, PATCH_JUMP); - InjectHook(0x54E160, CPlane::CreateDropOffCesna, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp index 25be193c..0d1ff9b0 100644 --- a/src/vehicles/Train.cpp +++ b/src/vehicles/Train.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "main.h" -#include "patcher.h" + #include "Timer.h" #include "ModelIndices.h" #include "FileMgr.h" @@ -691,32 +691,3 @@ CTrain::UpdateTrains(void) time += 0x40000/4; } } - -#include - -class CTrain_ : public CTrain -{ -public: - void ctor(int32 id, uint8 CreatedBy) { ::new (this) CTrain(id, CreatedBy); } - void SetModelIndex_(uint32 id) { CTrain::SetModelIndex(id); } - void ProcessControl_(void) { CTrain::ProcessControl(); } - void PreRender_(void) { CTrain::PreRender(); } - void Render_(void) { CTrain::Render(); } - void dtor(void) { CTrain::~CTrain(); } -}; - -STARTPATCHES - InjectHook(0x54E470, &CTrain_::SetModelIndex_, PATCH_JUMP); - InjectHook(0x54E4C0, &CTrain_::PreRender_, PATCH_JUMP); - InjectHook(0x54EAA0, &CTrain_::Render_, PATCH_JUMP); - InjectHook(0x54E450, &CTrain_::dtor, PATCH_JUMP); - InjectHook(0x54E2A0, &CTrain_::ctor, PATCH_JUMP); - InjectHook(0x550300, &CTrain::TrainHitStuff, PATCH_JUMP); - InjectHook(0x5504A0, &CTrain::AddPassenger, PATCH_JUMP); - InjectHook(0x550360, &CTrain::OpenTrainDoor, PATCH_JUMP); - - InjectHook(0x54F000, CTrain::InitTrains, PATCH_JUMP); - InjectHook(0x54F360, CTrain::Shutdown, PATCH_JUMP); - InjectHook(0x54EAB0, CTrain::ReadAndInterpretTrackFile, PATCH_JUMP); - InjectHook(0x54F3A0, CTrain::UpdateTrains, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Transmission.cpp b/src/vehicles/Transmission.cpp index d500d004..5287055d 100644 --- a/src/vehicles/Transmission.cpp +++ b/src/vehicles/Transmission.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Timer.h" #include "HandlingMgr.h" #include "Transmission.h" @@ -136,8 +136,3 @@ cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, fl } return fAcceleration; } - -STARTPATCHES - InjectHook(0x550A00, &cTransmission::CalculateGearForSimpleCar, PATCH_JUMP); - InjectHook(0x5506B0, &cTransmission::CalculateDriveAcceleration, PATCH_JUMP); -ENDPATCHES diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index ed8f4221..48c836f8 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1,6 +1,6 @@ #include "common.h" #include "main.h" -#include "patcher.h" + #include "General.h" #include "Timer.h" #include "Pad.h" @@ -1015,49 +1015,4 @@ DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle) } CWorld::Remove(pVehicle); delete pVehicle; -} - - -class CVehicle_ : public CVehicle -{ -public: - void dtor(void) { CVehicle::~CVehicle(); } - void SetModelIndex_(uint32 id) { CVehicle::SetModelIndex(id); } - bool SetupLighting_(void) { return CVehicle::SetupLighting(); } - void RemoveLighting_(bool reset) { CVehicle::RemoveLighting(reset); } - float GetHeightAboveRoad_(void) { return CVehicle::GetHeightAboveRoad(); } -}; - -STARTPATCHES - InjectHook(0x551170, &CVehicle_::SetModelIndex_, PATCH_JUMP); - InjectHook(0x4A7DD0, &CVehicle_::SetupLighting_, PATCH_JUMP); - InjectHook(0x4A7E60, &CVehicle_::RemoveLighting_, PATCH_JUMP); - InjectHook(0x417E60, &CVehicle_::GetHeightAboveRoad_, PATCH_JUMP); - - InjectHook(0x552BB0, &CVehicle::FlyingControl, PATCH_JUMP); - InjectHook(0x5512E0, &CVehicle::ProcessWheel, PATCH_JUMP); - InjectHook(0x551280, &CVehicle::ProcessWheelRotation, PATCH_JUMP); - InjectHook(0x552AF0, &CVehicle::ExtinguishCarFire, PATCH_JUMP); - InjectHook(0x551C90, &CVehicle::ProcessDelayedExplosion, PATCH_JUMP); - InjectHook(0x552880, &CVehicle::IsLawEnforcementVehicle, PATCH_JUMP); - InjectHook(0x552820, &CVehicle::ChangeLawEnforcerState, PATCH_JUMP); - InjectHook(0x552200, &CVehicle::UsesSiren, PATCH_JUMP); - InjectHook(0x5527E0, &CVehicle::IsVehicleNormal, PATCH_JUMP); - InjectHook(0x552B70, &CVehicle::CarHasRoof, PATCH_JUMP); - InjectHook(0x552230, &CVehicle::IsUpsideDown, PATCH_JUMP); - InjectHook(0x552260, &CVehicle::IsOnItsSide, PATCH_JUMP); - InjectHook(0x5511B0, &CVehicle::CanBeDeleted, PATCH_JUMP); - InjectHook(0x5522A0, &CVehicle::CanPedOpenLocks, PATCH_JUMP); - InjectHook(0x5522F0, &CVehicle::CanPedEnterCar, PATCH_JUMP); - InjectHook(0x5523C0, &CVehicle::CanPedExitCar, PATCH_JUMP); - InjectHook(0x5520C0, &CVehicle::SetUpDriver, PATCH_JUMP); - InjectHook(0x552160, &CVehicle::SetupPassenger, PATCH_JUMP); - InjectHook(0x551F20, &CVehicle::SetDriver, PATCH_JUMP); - InjectHook(0x551D90, (bool (CVehicle::*)(CPed*))&CVehicle::AddPassenger, PATCH_JUMP); - InjectHook(0x551E10, (bool (CVehicle::*)(CPed*,uint8))&CVehicle::AddPassenger, PATCH_JUMP); - InjectHook(0x5520A0, &CVehicle::RemoveDriver, PATCH_JUMP); - InjectHook(0x551EB0, &CVehicle::RemovePassenger, PATCH_JUMP); - InjectHook(0x5525A0, &CVehicle::ProcessCarAlarm, PATCH_JUMP); - InjectHook(0x552620, &CVehicle::IsSphereTouchingVehicle, PATCH_JUMP); - InjectHook(0x551950, &CVehicle::InflictDamage, PATCH_JUMP); -ENDPATCHES +} \ No newline at end of file diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp index 9e83a4ec..abf5c061 100644 --- a/src/weapons/BulletInfo.cpp +++ b/src/weapons/BulletInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "BulletInfo.h" #include "AnimBlendAssociation.h" diff --git a/src/weapons/Explosion.cpp b/src/weapons/Explosion.cpp index 02243702..d0a68279 100644 --- a/src/weapons/Explosion.cpp +++ b/src/weapons/Explosion.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Automobile.h" #include "Bike.h" #include "Camera.h" @@ -457,17 +457,4 @@ CExplosion::RemoveAllExplosionsInArea(CVector pos, float radius) gaExplosion[i].m_nIteration = 0; } } -} - -STARTPATCHES - InjectHook(0x559030, &CExplosion::Initialise, PATCH_JUMP); - InjectHook(0x559100, &CExplosion::Shutdown, PATCH_JUMP); - InjectHook(0x559140, &CExplosion::GetExplosionActiveCounter, PATCH_JUMP); - InjectHook(0x559160, &CExplosion::ResetExplosionActiveCounter, PATCH_JUMP); - InjectHook(0x559180, &CExplosion::GetExplosionType, PATCH_JUMP); - InjectHook(0x5591A0, &CExplosion::GetExplosionPosition, PATCH_JUMP); - InjectHook(0x5591C0, &CExplosion::AddExplosion, PATCH_JUMP); - InjectHook(0x55A0C0, &CExplosion::Update, PATCH_JUMP); - InjectHook(0x55AC80, &CExplosion::TestForExplosionInArea, PATCH_JUMP); - InjectHook(0x55AD40, &CExplosion::RemoveAllExplosionsInArea, PATCH_JUMP); -ENDPATCHES \ No newline at end of file +} \ No newline at end of file diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp index 8f04278c..c174305c 100644 --- a/src/weapons/ProjectileInfo.cpp +++ b/src/weapons/ProjectileInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Camera.h" #include "General.h" #include "Heli.h" @@ -287,16 +287,3 @@ CProjectileInfo::RemoveIfThisIsAProjectile(CObject *object) ms_apProjectile[i] = nil; return true; } - -STARTPATCHES - InjectHook(0x55ADF0, CProjectileInfo::Initialise, PATCH_JUMP); - InjectHook(0x55AFF0, CProjectileInfo::Shutdown, PATCH_JUMP); - InjectHook(0x55B010, CProjectileInfo::GetProjectileInfo, PATCH_JUMP); - InjectHook(0x55B030, CProjectileInfo::AddProjectile, PATCH_JUMP); - InjectHook(0x55B700, CProjectileInfo::RemoveProjectile, PATCH_JUMP); - InjectHook(0x55B770, CProjectileInfo::RemoveNotAdd, PATCH_JUMP); - InjectHook(0x55B7C0, CProjectileInfo::Update, PATCH_JUMP); - InjectHook(0x55BA50, CProjectileInfo::IsProjectileInRange, PATCH_JUMP); - InjectHook(0x55BB80, CProjectileInfo::RemoveAllProjectiles, PATCH_JUMP); - InjectHook(0x55BBD0, CProjectileInfo::RemoveIfThisIsAProjectile, PATCH_JUMP); -ENDPATCHES diff --git a/src/weapons/ShotInfo.cpp b/src/weapons/ShotInfo.cpp index 1eae5e87..83ce2a02 100644 --- a/src/weapons/ShotInfo.cpp +++ b/src/weapons/ShotInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "ShotInfo.h" #include "Entity.h" #include "Weapon.h" @@ -128,11 +128,4 @@ CShotInfo::Update() if (!((CTimer::GetFrameCounter() + slot) & 3)) CWorld::SetCarsOnFire(shot.m_startPos.x, shot.m_startPos.y, shot.m_startPos.z, 4.0f, shot.m_sourceEntity); } -} - -STARTPATCHES - InjectHook(0x55BFF0, &CShotInfo::Update, PATCH_JUMP); - InjectHook(0x55BD70, &CShotInfo::AddShot, PATCH_JUMP); - InjectHook(0x55BC60, &CShotInfo::Initialise, PATCH_JUMP); - InjectHook(0x55BD50, &CShotInfo::Shutdown, PATCH_JUMP); -ENDPATCHES \ No newline at end of file +} \ No newline at end of file diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 98154e93..276693e8 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "Weapon.h" #include "AnimBlendAssociation.h" #include "AudioManager.h" @@ -2255,38 +2255,4 @@ bool CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) { return CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects); -} - -STARTPATCHES - - InjectHook(0x55C2D0, CWeapon::InitialiseWeapons, PATCH_JUMP); - InjectHook(0x55C2F0, CWeapon::ShutdownWeapons, PATCH_JUMP); - InjectHook(0x55C310, CWeapon::UpdateWeapons, PATCH_JUMP); - InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP); - InjectHook(0x55C380, &CWeapon::Fire, PATCH_JUMP); - InjectHook(0x55C940, &CWeapon::FireFromCar, PATCH_JUMP); - InjectHook(0x55CA20, &CWeapon::FireMelee, PATCH_JUMP); - InjectHook(0x55D2E0, &CWeapon::FireInstantHit, PATCH_JUMP); - InjectHook(0x55F770, &CWeapon::AddGunshell, PATCH_JUMP); - InjectHook(0x55F950, &CWeapon::DoBulletImpact, PATCH_JUMP); - InjectHook(0x560620, &CWeapon::FireShotgun, PATCH_JUMP); - InjectHook(0x561900, &CWeapon::FireProjectile, PATCH_JUMP); - InjectHook(0x561C70, CWeapon::GenerateFlameThrowerParticles, PATCH_JUMP); - InjectHook(0x561E00, &CWeapon::FireAreaEffect, PATCH_JUMP); - InjectHook(0x561FE0, &CWeapon::FireSniper, PATCH_JUMP); - InjectHook(0x562180, &CWeapon::FireM16_1stPerson, PATCH_JUMP); - InjectHook(0x5624D0, &CWeapon::FireInstantHitFromCar, PATCH_JUMP); - InjectHook(0x562EB0, CWeapon::DoDoomAiming, PATCH_JUMP); - InjectHook(0x563200, CWeapon::DoTankDoomAiming, PATCH_JUMP); - InjectHook(0x563660, CWeapon::DoDriveByAutoAiming, PATCH_JUMP); - InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP); - InjectHook(0x563A10, &CWeapon::Update, PATCH_JUMP); - InjectHook(0x563FB0, &CWeapon::IsTypeMelee, PATCH_JUMP); - InjectHook(0x563FD0, &CWeapon::IsType2Handed, PATCH_JUMP); - InjectHook(0x564680, CWeapon::MakePedsJumpAtShot, PATCH_JUMP); - InjectHook(0x564890, &CWeapon::HitsGround, PATCH_JUMP); - InjectHook(0x564A60, CWeapon::BlowUpExplosiveThings, PATCH_JUMP); - InjectHook(0x564B80, &CWeapon::HasWeaponAmmoToBeUsed, PATCH_JUMP); - InjectHook(0x564C00, CWeapon::ProcessLineOfSight, PATCH_JUMP); - -ENDPATCHES +} \ No newline at end of file diff --git a/src/weapons/WeaponEffects.cpp b/src/weapons/WeaponEffects.cpp index 2ed9e662..f7e50f78 100644 --- a/src/weapons/WeaponEffects.cpp +++ b/src/weapons/WeaponEffects.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "WeaponEffects.h" #include "TxdStore.h" #include "Sprite.h" @@ -93,14 +93,4 @@ CWeaponEffects::Render(void) RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); } -} - -STARTPATCHES - //InjectHook(0x564C40, CWeaponEffects::CWeaponEffects, PATCH_JUMP); - //InjectHook(0x564C50, CWeaponEffects::~CWeaponEffects, PATCH_JUMP); - InjectHook(0x564C60, CWeaponEffects::Init, PATCH_JUMP); - InjectHook(0x564CF0, CWeaponEffects::Shutdown, PATCH_JUMP); - InjectHook(0x564D00, CWeaponEffects::MarkTarget, PATCH_JUMP); - InjectHook(0x564D60, CWeaponEffects::ClearCrossHair, PATCH_JUMP); - InjectHook(0x564D70, CWeaponEffects::Render, PATCH_JUMP); -ENDPATCHES \ No newline at end of file +} \ No newline at end of file diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp index dca120a3..aec9c69a 100644 --- a/src/weapons/WeaponInfo.cpp +++ b/src/weapons/WeaponInfo.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include "main.h" #include "FileMgr.h" #include "WeaponInfo.h" @@ -201,13 +201,4 @@ CWeaponInfo::Shutdown(void) { debug("Shutting down CWeaponInfo...\n"); debug("CWeaponInfo shut down\n"); -} - -STARTPATCHES - InjectHook(0x564EA0, &CWeaponInfo::Initialise, PATCH_JUMP); - InjectHook(0x564FD0, &CWeaponInfo::GetWeaponInfo, PATCH_JUMP); - InjectHook(0x5653E0, &CWeaponInfo::FindWeaponType, PATCH_JUMP); - InjectHook(0x5653B0, &CWeaponInfo::FindWeaponFireType, PATCH_JUMP); - InjectHook(0x564FE0, &CWeaponInfo::LoadWeaponData, PATCH_JUMP); - InjectHook(0x564FB0, &CWeaponInfo::Shutdown, PATCH_JUMP); -ENDPATCHES \ No newline at end of file +} \ No newline at end of file From 49a5df77be4383c00b154188317f8fb576502565 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Apr 2020 16:46:34 +0300 Subject: [PATCH 056/123] appveyor setup --- .appveyor.yml | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 41ada399..a1b526be 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -10,38 +10,17 @@ install: - cmd: >- git submodule update --init --recursive - premake-vs2019.cmd + copy premake5.exe "librw/premake5.exe" + + cd "librw" && premake5 vs2019 && msbuild "build/librw.sln" /property:Configuration=%CONFIGURATION% /property:Platform="win-x86-d3d9" + + cd "%APPVEYOR_BUILD_FOLDER%" && premake5 vs2019 + build: project: build/re3.sln verbosity: minimal -after_build: -# downloading latest release of UAL to make release with UAL and ASI. -- ps: >- - $releases = "https://github.com/ThirteenAG/Ultimate-ASI-Loader/releases" - - $name = "Ultimate-ASI-Loader.zip" - - $latestRelease = Invoke-WebRequest $releases/latest -Headers @{"Accept"="application/json"} - - $json = $latestRelease.Content | ConvertFrom-Json - - $latestVersion = $json.tag_name - - $url = "$releases/download/$latestVersion/$name" - - Start-FileDownload $url -FileName 'C:\Ultimate-ASI-Loader.zip' - - 7z e c:\Ultimate-ASI-Loader.zip -oc:\Projects\re3\bin\${env:CONFIGURATION} - - cd "bin\${env:CONFIGURATION}" - - copy re3.dll re3.asi - - 7z u "RE3_${env:CONFIGURATION}+UAL.zip" re3.asi dinput8.dll - - Get-ChildItem .\*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } artifacts: -- path: bin/%CONFIGURATION%/re3.dll - name: re3.dll +- path: bin/%CONFIGURATION%/re3.exe + name: re3.exe - path: bin/%CONFIGURATION%/re3.pdb name: re3.pdb From 7e652ef2d3a3a688a2b988b88e767de2df26087a Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Apr 2020 18:09:42 +0300 Subject: [PATCH 057/123] Remove CWorld from README --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index e97af343..540a8861 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,6 @@ If a function uses only few unreversed functions that would be inconvenient to reverse at the time, calling the original functions is acceptable. ### Unreversed / incomplete classes (at least the ones we know) -``` -CWorld -``` - The following classes have only unused or practically unused code left: ``` CCullZone - only mobile stuff From 4ff01484c8bc4b9012d8bb64ffbd83025da49b43 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Apr 2020 18:22:33 +0300 Subject: [PATCH 058/123] Update links --- README.md | 4 ++-- premake5.lua | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 540a8861..3b55e44c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # re3 [![Build status](https://ci.appveyor.com/api/projects/status/hyiwgegks122h8jg?svg=true)](https://ci.appveyor.com/project/aap/re3/branch/master) - - + + ## Intro diff --git a/premake5.lua b/premake5.lua index 586996f8..e5db2dd0 100644 --- a/premake5.lua +++ b/premake5.lua @@ -55,7 +55,6 @@ workspace "re3" files { "src/fakerw/*.*" } includedirs { "src/fakerw" } includedirs { "librw" } - includedirs { "librw/src" } libdirs { path.join("librw", "lib/win-x86-d3d9/%{cfg.buildcfg}") } links { "rw", "d3d9" } filter {} From ac26d9cddaa31004ea0a2f1449830b25031ecdef Mon Sep 17 00:00:00 2001 From: erorcun Date: Fri, 17 Apr 2020 18:30:59 +0300 Subject: [PATCH 059/123] Update README.md --- README.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 3b55e44c..45bed219 100644 --- a/README.md +++ b/README.md @@ -12,23 +12,18 @@ such that we have a working game at all times. ## How can I try it? -- re3 requires game assets to work, so you need to own a copy of GTA III. -- Since re3 is a DLL that works with original GTA III for now, you need Simple DLL Loader. You can get it [here](https://github.com/aap/simpledllloader). +- re3 requires game assets to work, so you **must** own a copy of GTA III. - Build re3 or download it from one of the above links (Debug or Release). -- Make sure you included the re3 in `plugins.cfg` or `dlls.cfg`. +- (Optional) If you want to use optional features like Russian language or menu map, copy the files in /gamefiles folder to your game root folder. +- Move re3.exe to GTA 3 directory and run it. -![#ffa500](https://placehold.it/15/ffa500/000000?text=+) **Notice if you will build it** +> :information_source: **Rendering engine** re3 uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw. -There are various settings at the very bottom of `config.h`, you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across. +> :warning: **Notice for builders** There are various settings at the very bottom of `config.h`, you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across. https://github.com/GTAmodding/re3/tree/master/src/core/config.h -## I want to contribute, where should I start? - -A good approach is to start at the fringes of the code base, -i.e. classes that don't depend on code that we don't have reversed yet. -If a function uses only few unreversed functions that would be inconvenient -to reverse at the time, calling the original functions is acceptable. +## Contributing ### Unreversed / incomplete classes (at least the ones we know) The following classes have only unused or practically unused code left: @@ -150,4 +145,5 @@ Here you can find a list of variables that you might need to set in windows: ``` "GTA_III_RE_DIR" * path to "gta3_re" game folder usually where this plugin run. "GTA_III_DIR" * path to "GTAIII" game folder. +"LIBRW" * path to LIBRW. ``` From 64cf568691a9bbf124165e666f79645da1edd237 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Apr 2020 18:46:01 +0300 Subject: [PATCH 060/123] We don't need rw.cpp anymore --- src/rw/rw.cpp | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/rw/rw.cpp diff --git a/src/rw/rw.cpp b/src/rw/rw.cpp deleted file mode 100644 index 09cd246e..00000000 --- a/src/rw/rw.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef LIBRW -#include "common.h" - -#include "rwcore.h" -#include "rpworld.h" -#include "rpmatfx.h" -#include "rpskin.h" -#include "rphanim.h" -#include "rtbmp.h" - -typedef RwV3d *(*rwVectorsMultFn) (RwV3d * pointsOut, - const RwV3d * pointsIn, - RwInt32 numPoints, - const RwMatrix * matrix); - -#ifndef RWLIBS - -#else - -extern "C" -{ - void* _rwFrameOpen(void* instance, RwInt32 offset, RwInt32 size); - void* _rwFrameClose(void* instance, RwInt32 offset, RwInt32 size); - RwFrame* _rwFrameCloneAndLinkClones(RwFrame* root); - RwFrame* _rwFramePurgeClone(RwFrame* root); - RwBool RwFrameDirty(RwFrame const* frame); - void _rwFrameInit(RwFrame* frame); - RwBool _rwMatrixSetMultFn(rwMatrixMultFn multMat); - void* _rwMatrixClose(void* instance, RwInt32 offset, RwInt32 size); - void* _rwMatrixOpen(void* instance, RwInt32 offset, RwInt32 size); - RwBool _rwVectorSetMultFn(rwVectorMultFn multPoint, rwVectorsMultFn multPoints, rwVectorMultFn multVector, rwVectorsMultFn multVectors); - void* _rwVectorClose(void* instance, RwInt32 offset, RwInt32 size); - void* _rwVectorOpen(void* instance, RwInt32 offset, RwInt32 size); - RwBool _rwPluginRegistryOpen(); - RwBool _rwPluginRegistryClose(); - - RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags); -} -#endif -#endif \ No newline at end of file From 6822cc5de85ffc393d7bf89c2b83fe980935d240 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Apr 2020 19:22:29 +0300 Subject: [PATCH 061/123] Use LIBRW env var it it's set --- premake5.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/premake5.lua b/premake5.lua index e5db2dd0..65443714 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,4 +1,4 @@ -Librw = os.getenv("LIBRW") +Librw = os.getenv("LIBRW") or "librw" workspace "re3" configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW" } @@ -54,8 +54,8 @@ workspace "re3" filter "configurations:Debug or Release" files { "src/fakerw/*.*" } includedirs { "src/fakerw" } - includedirs { "librw" } - libdirs { path.join("librw", "lib/win-x86-d3d9/%{cfg.buildcfg}") } + includedirs { Librw } + libdirs { path.join(Librw, "lib/win-x86-d3d9/%{cfg.buildcfg}") } links { "rw", "d3d9" } filter {} From 5922a9b88d58a81cef4c8ccb9652786b7b904e68 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Fri, 17 Apr 2020 19:46:17 +0300 Subject: [PATCH 062/123] premake fixes --- premake5.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/premake5.lua b/premake5.lua index 65443714..c427211a 100644 --- a/premake5.lua +++ b/premake5.lua @@ -106,31 +106,33 @@ project "re3" defines { "DEBUG", "LIBRW", "RW_D3D9" } staticruntime "off" symbols "Full" - setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") + setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") filter "configurations:Release" defines { "NDEBUG", "LIBRW", "RW_D3D9" } optimize "On" staticruntime "off" symbols "Full" - setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") + setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") filter "configurations:ReleaseFH" defines { "NDEBUG" } symbols "Full" optimize "off" staticruntime "on" - setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") + setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") filter "configurations:DebugRW" defines { "DEBUG" } staticruntime "on" symbols "On" - setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") + setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") + linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text" filter "configurations:ReleaseRW" defines { "NDEBUG" } optimize "On" staticruntime "on" - setpaths("$(GTA_III_RE_DIR)/", "re3.exe", "") + setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") + linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text" From 63951d9b957b30a110f42a03edb4833cbbaf380e Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Fri, 17 Apr 2020 19:30:57 +0200 Subject: [PATCH 063/123] Part one --- CMakeLists.txt | 25 ++++++ src/animation/AnimBlendAssocGroup.cpp | 20 +++-- src/audio/AudioManager.cpp | 2 +- src/audio/DMAudio.h | 1 + src/audio/sampman.cpp | 119 +++++++++++++++----------- src/control/Darkel.h | 3 +- src/control/PathFind.cpp | 35 +++++--- src/control/TrafficLights.cpp | 2 +- src/core/CrimeType.h | 23 +++++ src/core/Game.cpp | 2 +- src/core/General.h | 2 +- src/core/Pad.cpp | 2 +- src/core/PlayerInfo.cpp | 2 +- src/core/Wanted.h | 22 +---- src/core/common.h | 4 +- src/objects/ParticleObject.h | 2 +- src/peds/Ped.h | 10 +-- src/render/ParticleMgr.h | 78 +---------------- src/weapons/Weapon.h | 48 +---------- 19 files changed, 172 insertions(+), 230 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 src/core/CrimeType.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..2871dff4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_Minimum_required(VERSION 3.8) + +project(Re3) + +set (CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -masm=intel -Wdouble-promotion") + +file(GLOB_RECURSE Sources "*.cpp" "*.h") + +MACRO(HEADER_DIRECTORIES return_list) + FILE(GLOB_RECURSE new_list *.h) + SET(dir_list "") + FOREACH(file_path ${new_list}) + GET_FILENAME_COMPONENT(dir_path ${file_path} PATH) + SET(dir_list ${dir_list} ${dir_path}) + ENDFOREACH() + LIST(REMOVE_DUPLICATES dir_list) + SET(${return_list} ${dir_list}) +ENDMACRO() + +HEADER_DIRECTORIES(header_list) + +include_directories(${header_list}) + +add_library(re3 ${Sources}) diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp index e65bdf8d..27b091bd 100644 --- a/src/animation/AnimBlendAssocGroup.cpp +++ b/src/animation/AnimBlendAssocGroup.cpp @@ -59,8 +59,7 @@ CAnimBlendAssociation* CAnimBlendAssocGroup::CopyAnimation(const char *name) { CAnimBlendAssociation *anim = GetAnimation(name); - if(anim == nil) - return nil; + if(anim == nil) return nil; CAnimManager::UncompressAnimation(anim->hierarchy); return new CAnimBlendAssociation(*anim); } @@ -70,19 +69,26 @@ strcmpIgnoringDigits(const char *s1, const char *s2) { char c1, c2; - for(;;){ + for(;;) { c1 = *s1; c2 = *s2; if(c1) s1++; if(c2) s2++; - if(c1 == '\0' && c2 == '\0') - return true; + if(c1 == '\0' && c2 == '\0') return true; +#if 1 + if(iswdigit(c1) && iswdigit(c2)) +#else if(__ascii_iswdigit(c1) && __ascii_iswdigit(c2)) +#endif continue; +#if 1 + c1 = toupper(c1); + c2 = toupper(c2); +#else c1 = __ascii_toupper(c1); c2 = __ascii_toupper(c2); - if(c1 != c2) - return false; +#endif + if(c1 != c2) return false; } } diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 4d5f8474..0a156cd4 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -10035,7 +10035,7 @@ cAudioManager::UpdateReflections() if(CWorld::ProcessVerticalLine( camPos, m_avecReflectionsPos[4].z, colpoint, ent, true, false, false, false, true, false, - false)) { + nil)) { m_afReflectionsDistances[4] = colpoint.point.z - camPos.z; } else { diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 9ce073b4..00bf75ad 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -1,6 +1,7 @@ #pragma once #include "audio_enums.h" +#include "CrimeType.h" enum eSound : int16 { diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index d24de27f..a375b847 100644 --- a/src/audio/sampman.cpp +++ b/src/audio/sampman.cpp @@ -1986,50 +1986,59 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) if ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER ) { uint32 i = 0; - - if ( !_bIsMp3Active ) goto FIND_MP3TRACK; - - do - { - if ( ++_CurMP3Index >= nNumMP3s ) - _CurMP3Index = 0; - - _CurMP3Pos = 0; - - tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); - - if ( mp3 ) - { - mp3 = _pMP3List; - if ( mp3 == NULL ) - { - _bIsMp3Active = false; - nFile = 0; - goto PLAY_STREAMEDTRACK; + do { + if(i != 0 || _bIsMp3Active) { + if(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0; + + _CurMP3Pos = 0; + + tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); + + if(mp3) { + mp3 = _pMP3List; + if(mp3 == NULL) { + _bIsMp3Active = false; + nFile = 0; + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count( + mp3Stream[nStream], 1); + AIL_set_stream_ms_position( + mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], + 0); + return true; + } + + return false; + } } + + if(mp3->pLinkPath != NULL) + mp3Stream[nStream] = + AIL_open_stream(DIG, mp3->pLinkPath, 0); + else { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, mp3->aFilename); + + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + } + + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], 0); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + _bIsMp3Active = false; + continue; } - - if ( mp3->pLinkPath != NULL ) - mp3Stream[nStream] = AIL_open_stream(DIG, mp3->pLinkPath, 0); - else - { - strcpy(filename, _mp3DirectoryPath); - strcat(filename, mp3->aFilename); - - mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); - } - - if ( mp3Stream[nStream] ) - { - AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_set_stream_ms_position(mp3Stream[nStream], 0); - AIL_pause_stream(mp3Stream[nStream], 0); - return true; - } - - goto NEXT_MP3TRACK; - -FIND_MP3TRACK: if ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] ) position = 0; @@ -2039,10 +2048,23 @@ FIND_MP3TRACK: if ( e == NULL ) { nFile = 0; - goto PLAY_STREAMEDTRACK; + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count( + mp3Stream[nStream], 1); + AIL_set_stream_ms_position( + mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + return false; } } - + if ( e->pLinkPath != NULL ) mp3Stream[nStream] = AIL_open_stream(DIG, e->pLinkPath, 0); else @@ -2064,17 +2086,14 @@ FIND_MP3TRACK: return true; } -NEXT_MP3TRACK: _bIsMp3Active = false; - - } while ( ++i < nNumMP3s ); - + + } while(++i < nNumMP3s); + position = 0; nFile = 0; - goto PLAY_STREAMEDTRACK; } -PLAY_STREAMEDTRACK: strcpy(filename, m_szCDRomRootPath); strcat(filename, StreamedNameTable[nFile]); diff --git a/src/control/Darkel.h b/src/control/Darkel.h index b6092dcb..14529c63 100644 --- a/src/control/Darkel.h +++ b/src/control/Darkel.h @@ -1,9 +1,10 @@ #pragma once + #include "ModelIndices.h" +#include "WeaponType.h" class CVehicle; class CPed; -enum eWeaponType; enum { diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 9d0959a8..cedef63c 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -1466,8 +1466,11 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta targetNode = FindNodeClosestToCoors(target, type, distLimit); else targetNode = forcedTargetNode; - if(targetNode < 0) - goto fail; + if(targetNode < 0) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } // Find start int numPathsToTry; @@ -1486,19 +1489,28 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta numPathsToTry = 1; startObj = m_mapObjects[m_pathNodes[startNodeId].objectIndex]; } - if(numPathsToTry == 0) - goto fail; + if(numPathsToTry == 0) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } if(startNodeId < 0){ // why only check node 0? - if(m_pathNodes[startObj->m_nodeIndices[type][0]].group != m_pathNodes[targetNode].group) - goto fail; + if(m_pathNodes[startObj->m_nodeIndices[type][0]].group != + m_pathNodes[targetNode].group) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } }else{ - if(m_pathNodes[startNodeId].group != m_pathNodes[targetNode].group) - goto fail; + if(m_pathNodes[startNodeId].group != m_pathNodes[targetNode].group) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } } - for(i = 0; i < 512; i++) m_searchNodes[i].next = nil; AddNodeToList(&m_pathNodes[targetNode], 0); @@ -1576,11 +1588,6 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta for(i = 0; i < numNodesToBeCleared; i++) apNodesToBeCleared[i]->distance = MAX_DIST; return; - -fail: - *pNumNodes = 0; - if(pDist) - *pDist = 100000.0f; } static CPathNode *pNodeList[32]; diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index 096bb484..70fcbc32 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -8,7 +8,7 @@ #include "Clock.h" #include "Weather.h" #include "Timecycle.h" -#include "Pointlights.h" +#include "PointLights.h" #include "Shadows.h" #include "Coronas.h" #include "SpecialFX.h" diff --git a/src/core/CrimeType.h b/src/core/CrimeType.h new file mode 100644 index 00000000..23f609eb --- /dev/null +++ b/src/core/CrimeType.h @@ -0,0 +1,23 @@ +#pragma once + +enum eCrimeType +{ + CRIME_NONE, + CRIME_POSSESSION_GUN, + CRIME_HIT_PED, + CRIME_HIT_COP, + CRIME_SHOOT_PED, + CRIME_SHOOT_COP, + CRIME_STEAL_CAR, + CRIME_RUN_REDLIGHT, + CRIME_RECKLESS_DRIVING, + CRIME_SPEEDING, + CRIME_RUNOVER_PED, + CRIME_RUNOVER_COP, + CRIME_SHOOT_HELI, + CRIME_PED_BURNED, + CRIME_COP_BURNED, + CRIME_VEHICLE_BURNED, + CRIME_DESTROYED_CESSNA, + NUM_CRIME_TYPES +}; \ No newline at end of file diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 7ccf78d0..8b2f8604 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -72,7 +72,7 @@ #include "Streaming.h" #include "SurfaceTable.h" #include "TempColModels.h" -#include "TimeCycle.h" +#include "Timecycle.h" #include "TrafficLights.h" #include "Train.h" #include "TxdStore.h" diff --git a/src/core/General.h b/src/core/General.h index 77828854..103bafde 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -124,7 +124,7 @@ public: static bool faststricmp(const char *str1, const char *str2) { for (; *str1; str1++, str2++) { -#if MUCH_SLOWER +#if 1 if (toupper(*str1) != toupper(*str2)) #else if (__ascii_toupper(*str1) != __ascii_toupper(*str2)) diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 86aff05e..49affbbe 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -6,7 +6,7 @@ #include "common.h" #ifdef XINPUT -#include +#include #pragma comment( lib, "Xinput9_1_0.lib" ) #endif diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index cfa0cea4..3852f540 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -180,7 +180,7 @@ CPlayerInfo::MakePlayerSafe(bool toggle) m_pPed->bExplosionProof = true; m_pPed->m_bCanBeDamaged = false; ((CPlayerPed*)m_pPed)->ClearAdrenaline(); - CancelPlayerEnteringCars(false); + CancelPlayerEnteringCars(nil); gFireManager.ExtinguishPoint(GetPos(), 4000.0f); CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f); CProjectileInfo::RemoveAllProjectiles(); diff --git a/src/core/Wanted.h b/src/core/Wanted.h index afeec8b0..c5e9d388 100644 --- a/src/core/Wanted.h +++ b/src/core/Wanted.h @@ -3,27 +3,7 @@ class CEntity; class CCopPed; -enum eCrimeType -{ - CRIME_NONE, - CRIME_POSSESSION_GUN, - CRIME_HIT_PED, - CRIME_HIT_COP, - CRIME_SHOOT_PED, - CRIME_SHOOT_COP, - CRIME_STEAL_CAR, - CRIME_RUN_REDLIGHT, - CRIME_RECKLESS_DRIVING, - CRIME_SPEEDING, - CRIME_RUNOVER_PED, - CRIME_RUNOVER_COP, - CRIME_SHOOT_HELI, - CRIME_PED_BURNED, - CRIME_COP_BURNED, - CRIME_VEHICLE_BURNED, - CRIME_DESTROYED_CESSNA, - NUM_CRIME_TYPES -}; +#include "CrimeType.h" class CCrimeBeingQd { diff --git a/src/core/common.h b/src/core/common.h index 454b848a..e10b222c 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -12,7 +12,7 @@ #include #ifdef WITHWINDOWS -#include +#include #endif #ifdef WITHD3D @@ -62,7 +62,7 @@ typedef int64_t int64; typedef uint16_t wchar; #ifndef nil -#define nil nullptr +#define nil NULL #endif #include "config.h" diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h index cfa5936d..fc74bef0 100644 --- a/src/objects/ParticleObject.h +++ b/src/objects/ParticleObject.h @@ -1,6 +1,7 @@ #pragma once #include "Placeable.h" #include "AudioManager.h" +#include "ParticleType.h" #define MAX_PARTICLEOBJECTS 100 #define MAX_AUDIOHYDRANTS 8 @@ -37,7 +38,6 @@ enum eParticleObjectState POBJECTSTATE_FREE, }; -enum tParticleType; class CParticle; class CParticleObject : public CPlaceable diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 9f660693..27f699d5 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -1,12 +1,13 @@ #pragma once +#include "AnimManager.h" +#include "CrimeType.h" +#include "EventList.h" +#include "PedIK.h" +#include "PedStats.h" #include "Physical.h" #include "Weapon.h" -#include "PedStats.h" -#include "PedIK.h" -#include "AnimManager.h" #include "WeaponInfo.h" -#include "EventList.h" #define FEET_OFFSET 1.04f #define CHECK_NEARBY_THINGS_MAX_DIST 15.0f @@ -17,7 +18,6 @@ class CObject; class CFire; struct AnimBlendFrameData; class CAnimBlendAssociation; -enum eCrimeType; struct PedAudioData { diff --git a/src/render/ParticleMgr.h b/src/render/ParticleMgr.h index 5e8da1e4..e3ec21c6 100644 --- a/src/render/ParticleMgr.h +++ b/src/render/ParticleMgr.h @@ -1,82 +1,8 @@ #pragma once -class CParticle; +#include "ParticleType.h" -enum tParticleType -{ - PARTICLE_SPARK = 0, - PARTICLE_SPARK_SMALL, - PARTICLE_WHEEL_DIRT, - PARTICLE_WHEEL_WATER, - PARTICLE_BLOOD, - PARTICLE_BLOOD_SMALL, - PARTICLE_BLOOD_SPURT, - PARTICLE_DEBRIS, - PARTICLE_DEBRIS2, - PARTICLE_WATER, - PARTICLE_FLAME, - PARTICLE_FIREBALL, - PARTICLE_GUNFLASH, - PARTICLE_GUNFLASH_NOANIM, - PARTICLE_GUNSMOKE, - PARTICLE_GUNSMOKE2, - PARTICLE_SMOKE, - PARTICLE_SMOKE_SLOWMOTION, - PARTICLE_GARAGEPAINT_SPRAY, - PARTICLE_SHARD, - PARTICLE_SPLASH, - PARTICLE_CARFLAME, - PARTICLE_STEAM, - PARTICLE_STEAM2, - PARTICLE_STEAM_NY, - PARTICLE_STEAM_NY_SLOWMOTION, - PARTICLE_ENGINE_STEAM, - PARTICLE_RAINDROP, - PARTICLE_RAINDROP_SMALL, - PARTICLE_RAIN_SPLASH, - PARTICLE_RAIN_SPLASH_BIGGROW, - PARTICLE_RAIN_SPLASHUP, - PARTICLE_WATERSPRAY, - PARTICLE_EXPLOSION_MEDIUM, - PARTICLE_EXPLOSION_LARGE, - PARTICLE_EXPLOSION_MFAST, - PARTICLE_EXPLOSION_LFAST, - PARTICLE_CAR_SPLASH, - PARTICLE_BOAT_SPLASH, - PARTICLE_BOAT_THRUSTJET, - PARTICLE_BOAT_WAKE, - PARTICLE_WATER_HYDRANT, - PARTICLE_WATER_CANNON, - PARTICLE_EXTINGUISH_STEAM, - PARTICLE_PED_SPLASH, - PARTICLE_PEDFOOT_DUST, - PARTICLE_HELI_DUST, - PARTICLE_HELI_ATTACK, - PARTICLE_ENGINE_SMOKE, - PARTICLE_ENGINE_SMOKE2, - PARTICLE_CARFLAME_SMOKE, - PARTICLE_FIREBALL_SMOKE, - PARTICLE_PAINT_SMOKE, - PARTICLE_TREE_LEAVES, - PARTICLE_CARCOLLISION_DUST, - PARTICLE_CAR_DEBRIS, - PARTICLE_HELI_DEBRIS, - PARTICLE_EXHAUST_FUMES, - PARTICLE_RUBBER_SMOKE, - PARTICLE_BURNINGRUBBER_SMOKE, - PARTICLE_BULLETHIT_SMOKE, - PARTICLE_GUNSHELL_FIRST, - PARTICLE_GUNSHELL, - PARTICLE_GUNSHELL_BUMP1, - PARTICLE_GUNSHELL_BUMP2, - PARTICLE_TEST, - PARTICLE_BIRD_FRONT, - PARTICLE_RAINDROP_2D, - - MAX_PARTICLES, - PARTICLE_FIRST = PARTICLE_SPARK, - PARTICLE_LAST = PARTICLE_RAINDROP_2D -}; +class CParticle; enum { diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 265ffddb..76fe0870 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -3,53 +3,7 @@ #define DRIVEBYAUTOAIMING_MAXDIST (2.5f) #define DOOMAUTOAIMING_MAXDIST (9000.0f) -enum eWeaponType -{ - WEAPONTYPE_UNARMED, - WEAPONTYPE_BASEBALLBAT, - WEAPONTYPE_COLT45, - WEAPONTYPE_UZI, - WEAPONTYPE_SHOTGUN, - WEAPONTYPE_AK47, - WEAPONTYPE_M16, - WEAPONTYPE_SNIPERRIFLE, - WEAPONTYPE_ROCKETLAUNCHER, - WEAPONTYPE_FLAMETHROWER, - WEAPONTYPE_MOLOTOV, - WEAPONTYPE_GRENADE, - WEAPONTYPE_DETONATOR, - WEAPONTYPE_HELICANNON, - WEAPONTYPE_LAST_WEAPONTYPE, - WEAPONTYPE_ARMOUR, - WEAPONTYPE_RAMMEDBYCAR, - WEAPONTYPE_RUNOVERBYCAR, - WEAPONTYPE_EXPLOSION, - WEAPONTYPE_UZI_DRIVEBY, - WEAPONTYPE_DROWNING, - WEAPONTYPE_FALL, - WEAPONTYPE_UNIDENTIFIED, - - WEAPONTYPE_TOTALWEAPONS = WEAPONTYPE_LAST_WEAPONTYPE, - WEAPONTYPE_TOTAL_INVENTORY_WEAPONS = 13, -}; - -enum eWeaponFire { - WEAPON_FIRE_MELEE, - WEAPON_FIRE_INSTANT_HIT, - WEAPON_FIRE_PROJECTILE, - WEAPON_FIRE_AREA_EFFECT, - WEAPON_FIRE_USE -}; - -// Taken from MTA SA, seems it's unchanged -enum eWeaponState -{ - WEAPONSTATE_READY, - WEAPONSTATE_FIRING, - WEAPONSTATE_RELOADING, - WEAPONSTATE_OUT_OF_AMMO, - WEAPONSTATE_MELEE_MADECONTACT -}; +#include "WeaponType.h" class CEntity; class CPhysical; From 886d73b123bcda23d4c6de1d5b3458278731de47 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 17 Apr 2020 21:45:02 +0200 Subject: [PATCH 064/123] fixed raster from image conversion --- src/fakerw/fake.cpp | 39 ++------------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 557318be..03df55e2 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -201,40 +201,9 @@ RwInt32 RwImageStreamGetSize(const RwImage * image); RwImage *RwImageStreamRead(RwStream * stream); const RwImage *RwImageStreamWrite(const RwImage * image, RwStream * stream); -// TODO: this is kind hard... RwImage *RwImageFindRasterFormat(RwImage *ipImage,RwInt32 nRasterType, RwInt32 *npWidth,RwInt32 *npHeight, RwInt32 *npDepth,RwInt32 *npFormat) { - // very dumb implementation for now - // this is also platform specific - if((nRasterType&rwRASTERTYPEMASK) != rwRASTERTYPETEXTURE){ - *npFormat = 0; - return nil; - } - *npWidth = ipImage->width; - *npHeight = ipImage->height; - switch(ipImage->depth){ - case 4: - case 8: - *npDepth = 8; - *npFormat = Raster::C8888 | Raster::PAL8; - break; - case 16: - *npDepth = 16; - *npFormat = Raster::C1555; - break; - case 24: - *npDepth = 32; - *npFormat = Raster::C888; - break; - case 32: - *npDepth = 32; - *npFormat = Raster::C8888; - break; - default: - assert(0 && "invalid depth"); - return nil; - } - return ipImage; + return Raster::imageFindRasterFormat(ipImage, nRasterType, npWidth, npHeight, npDepth, npFormat) ? ipImage : nil; } @@ -269,11 +238,7 @@ RwInt32 RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObj RwInt32 RwRasterGetPluginOffset(RwUInt32 pluginID); RwBool RwRasterValidatePlugins(const RwRaster * raster); -// TODO: let's hope this works -RwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image) { - engine->driver[raster->platform]->rasterFromImage(raster, image); - return raster; -} +RwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image) { return raster->setFromImage(image); } From 15f1080b18d3e8f9566ad45b12946ae89c92fd5a Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Apr 2020 00:00:47 +0300 Subject: [PATCH 065/123] librw update --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 7bd6d464..48938896 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 7bd6d4649e575e0a2a5f046fdf0d687cea87ca84 +Subproject commit 4893889621621c077690d522e7e9a10249a65a85 From bdf9fa2f01e5dfaa6cd09c1eb1b66fc75a92b208 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 17 Apr 2020 23:55:20 +0200 Subject: [PATCH 066/123] implemented librw alphatest setting --- src/rw/RwHelper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index e5c4ceae..acf811ad 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -91,7 +91,8 @@ DefinedState(void) RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); #ifdef LIBRW - #pragma message (" TODO: alphatest func") + rw::SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL); + rw::SetRenderState(rw::ALPHATESTREF, 3); #else // D3D stuff RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); From 812b9e7edab26cc04d28931b0e89ed9317b818c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 18 Apr 2020 05:58:43 +0300 Subject: [PATCH 067/123] Various fixes --- src/control/Script.cpp | 2 +- src/core/Frontend.cpp | 15 +++++++++------ src/core/Frontend.h | 4 ++++ src/peds/Population.cpp | 6 +++--- src/render/Renderer.cpp | 2 -- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 6a8028a2..f1cc8ede 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -6909,7 +6909,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z); CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z); int16 collisions; - CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos, + CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, newPosition, min(cp1.x, min(cp2.x, min(cp3.x, cp4.x))), min(cp1.y, min(cp2.y, min(cp3.y, cp4.y))), max(cp1.x, max(cp2.x, max(cp3.x, cp4.x))), diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 790de046..e9282c44 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -118,7 +118,7 @@ const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color #endif -const float menuXYpadding = MENUACTION_POS_Y; // *(float*)0x5F355C; // not original name +const float menuXYpadding = MENUACTION_POS_Y; // TODO this is non-existant, remove it float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; @@ -754,9 +754,9 @@ CMenuManager::Draw() #ifdef FIX_BUGS // Label is wrapped from right by StretchX(40)px, but wrapped from left by 40px. And this is only place R* didn't use StretchX in here. - CFont::PrintString(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN), MENU_Y(menuXYpadding), str); + CFont::PrintString(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN), MENU_Y(MENUACTION_POS_Y), str); #else - CFont::PrintString(MENU_X_MARGIN, menuXYpadding, str); + CFont::PrintString(MENU_X_MARGIN, MENUACTION_POS_Y, str); #endif } @@ -3181,7 +3181,7 @@ CMenuManager::PrintBriefs() CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why - float nextY = 40.0f; + float nextY = BRIEFS_TOP_MARGIN; CRGBA newColor; for (int i = 4; i >= 0; i--) { tPreviousBrief &brief = CMessages::PreviousBriefs[i]; @@ -3214,8 +3214,8 @@ CMenuManager::PrintBriefs() newColor.a = FadeIn(255); CFont::SetColor(newColor); #endif - CFont::PrintString(MENU_X_LEFT_ALIGNED(50.0f), nextY, gUString); - nextY += MENU_Y(menuXYpadding); + CFont::PrintString(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), nextY, gUString); + nextY += MENU_Y(BRIEFS_LINE_HEIGHT); } } @@ -3252,6 +3252,9 @@ void CMenuManager::PrintStats() { int rowNum = ConstructStatLine(99999); +#ifdef GTA3_1_1_PATCH + CFont::SetFontStyle(FONT_BANK); +#endif CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why float nextYChange, y, alphaMult; diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 8fe61a36..41c12122 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -68,6 +68,10 @@ #define STATS_RATING_X 24.0f #define STATS_RATING_Y 20.0f +#define BRIEFS_TOP_MARGIN 40.0f +#define BRIEFS_LINE_X 50.0f +#define BRIEFS_LINE_HEIGHT 60.0f + #define CONTSETUP_STANDARD_ROW_HEIGHT 10.7f #define CONTSETUP_CLASSIC_ROW_HEIGHT 9.0f #define CONTSETUP_BOUND_HIGHLIGHT_HEIGHT 10 diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 681c6b1a..c1eee828 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -1050,7 +1050,7 @@ CPopulation::TestSafeForRealObject(CDummyObject *dummy) if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y; #endif - static CColPoint aTempColPoints; + static CColPoint aTempColPoints[MAX_COLLISION_POINTS]; for (int curY = minY; curY <= maxY; curY++) { for (int curX = minX; curX <= maxX; curX++) { @@ -1061,7 +1061,7 @@ CPopulation::TestSafeForRealObject(CDummyObject *dummy) if (veh->m_scanCode != CWorld::GetCurrentScanCode()) { if (veh->GetIsTouching(colCentre, colRadius)) { veh->m_scanCode = CWorld::GetCurrentScanCode(); - if (CCollision::ProcessColModels(dummy->GetMatrix(), *dummyCol, veh->GetMatrix(), *veh->GetColModel(), &aTempColPoints, nil, nil) > 0) + if (CCollision::ProcessColModels(dummy->GetMatrix(), *dummyCol, veh->GetMatrix(), *veh->GetColModel(), aTempColPoints, nil, nil) > 0) return false; } } @@ -1072,7 +1072,7 @@ CPopulation::TestSafeForRealObject(CDummyObject *dummy) if (veh->m_scanCode != CWorld::GetCurrentScanCode()) { if (veh->GetIsTouching(colCentre, colRadius)) { veh->m_scanCode = CWorld::GetCurrentScanCode(); - if (CCollision::ProcessColModels(dummy->GetMatrix(), *dummyCol, veh->GetMatrix(), *veh->GetColModel(), &aTempColPoints, nil, nil) > 0) + if (CCollision::ProcessColModels(dummy->GetMatrix(), *dummyCol, veh->GetMatrix(), *veh->GetColModel(), aTempColPoints, nil, nil) > 0) return false; } } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 9c78853f..3d308c52 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -194,8 +194,6 @@ CRenderer::RenderRoads(void) DeActivateDirectional(); SetAmbientColours(); - ThePaths.m_pathNodes[-1].group = 6; - for(i = 0; i < ms_nNoOfVisibleEntities; i++){ t = (CTreadable*)ms_aVisibleEntityPtrs[i]; if(t->IsBuilding() && t->GetIsATreadable()){ From e41c32df431a5cf5df8740c43766d6fcd9200d77 Mon Sep 17 00:00:00 2001 From: gennariarmando Date: Fri, 17 Apr 2020 20:22:33 +0200 Subject: [PATCH 068/123] Fixed menu radio icons. --- src/core/Frontend.cpp | 73 ++++++++++++++++++++++--------------------- src/core/Frontend.h | 13 +++----- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 790de046..20b13820 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -118,7 +118,7 @@ const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color #endif -const float menuXYpadding = MENUACTION_POS_Y; // *(float*)0x5F355C; // not original name +const float menuXYpadding = MENUACTION_POS_Y; // TODO this is non-existant, remove it float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; @@ -167,15 +167,15 @@ const char* FrontendFilenames[][2] = { {"fe_arrows2", "" }, {"fe_arrows3", "" }, {"fe_arrows4", "" }, - {"fe_radio1", "" }, // HEAD_RADIO - {"fe_radio2", "" }, // DOUBLE_CLEF - {"fe_radio3", "" }, // JAH_RADIO - {"fe_radio4", "" }, // RISE_FM - {"fe_radio5", "" }, // LIPS_106 - {"fe_radio6", "" }, // GAME_FM - {"fe_radio7", "" }, // MSX_FM - {"fe_radio8", "" }, // FLASHBACK - {"fe_radio9", "" }, // CHATTERBOX + {"fe_radio1", "" }, + {"fe_radio2", "" }, + {"fe_radio3", "" }, + {"fe_radio4", "" }, + {"fe_radio5", "" }, + {"fe_radio6", "" }, + {"fe_radio7", "" }, + {"fe_radio8", "" }, + {"fe_radio9", "" }, }; #ifdef MENU_MAP @@ -231,7 +231,8 @@ ScaleAndCenterX(float x) else { if (x > DEFAULT_SCREEN_WIDTH / 2) { return SCREEN_WIDTH / 2 + SCREEN_SCALE_X(x - DEFAULT_SCREEN_WIDTH / 2); - } else { + } + else { return SCREEN_WIDTH / 2 - SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH / 2 - x); } } @@ -303,6 +304,11 @@ ScaleAndCenterX(float x) m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ } while(0) +#define ProcessRadioIcon(sprite, x, y, radioId, hoverOpt) \ + sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); \ + if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \ + m_nHoverOption = hoverOpt; + // --- Functions not in the game/inlined starts inline void @@ -754,9 +760,9 @@ CMenuManager::Draw() #ifdef FIX_BUGS // Label is wrapped from right by StretchX(40)px, but wrapped from left by 40px. And this is only place R* didn't use StretchX in here. - CFont::PrintString(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN), MENU_Y(menuXYpadding), str); + CFont::PrintString(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN), MENU_Y(MENUACTION_POS_Y), str); #else - CFont::PrintString(MENU_X_MARGIN, menuXYpadding, str); + CFont::PrintString(MENU_X_MARGIN, MENUACTION_POS_Y, str); #endif } @@ -1253,27 +1259,21 @@ CMenuManager::Draw() nextYToUse += lineHeight * CFont::GetNumberLines(menuXYpadding, nextYToUse, leftText); - // TODO: This should be rewritten as multiple macro calls instead of loop, radio order is wrong. - // And hover detection is missing. - float fIconSpacing = 59.52f; + // Radio icons if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) { - for (int i = 0; i < POLICE_RADIO; i++) { -#ifndef ASPECT_RATIO_SCALE - if (i < USERTRACK) - m_aFrontEndSprites[i + FE_RADIO1].Draw(SCREEN_STRETCH_X(MENURADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENURADIO_ICON_Y), SCREEN_SCALE_X(MENURADIO_ICON_W), SCREEN_SCALE_Y(MENURADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); - if (i > CHATTERBOX && DMAudio.IsMP3RadioChannelAvailable()) - m_aMenuSprites[MENUSPRITE_MP3LOGO].Draw(SCREEN_STRETCH_X(MENURADIO_ICON_X + fIconSpacing * i), (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(MENURADIO_ICON_Y), SCREEN_SCALE_X(MENURADIO_ICON_W), SCREEN_SCALE_Y(MENURADIO_ICON_H), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); -#else - float fMp3Pos = 0.0f; - if (DMAudio.IsMP3RadioChannelAvailable()) - fMp3Pos = 34.0f; + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO1], MENU_X_LEFT_ALIGNED(30.0f), MENU_Y(nextYToUse), 0, HOVEROPTION_RADIO_0); + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO2], MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(nextYToUse), 1, HOVEROPTION_RADIO_1); + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO5], MENU_X_LEFT_ALIGNED(150.0f), MENU_Y(nextYToUse), 2, HOVEROPTION_RADIO_2); + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO7], MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(nextYToUse), 3, HOVEROPTION_RADIO_3); + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO8], MENU_X_LEFT_ALIGNED(270.0f), MENU_Y(nextYToUse), 4, HOVEROPTION_RADIO_4); + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO3], MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(nextYToUse), 5, HOVEROPTION_RADIO_5); + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO4], MENU_X_LEFT_ALIGNED(360.0f), MENU_Y(nextYToUse), 6, HOVEROPTION_RADIO_6); + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO6], MENU_X_LEFT_ALIGNED(420.0f), MENU_Y(nextYToUse), 7, HOVEROPTION_RADIO_7); + ProcessRadioIcon(m_aFrontEndSprites[FE_RADIO9], MENU_X_LEFT_ALIGNED(480.0f), MENU_Y(nextYToUse), 8, HOVEROPTION_RADIO_8); + + if (DMAudio.IsMP3RadioChannelAvailable()) + ProcessRadioIcon(m_aMenuSprites[MENUSPRITE_MP3LOGO], MENU_X_LEFT_ALIGNED(540.0f), MENU_Y(nextYToUse), 9, HOVEROPTION_RADIO_9); - if (i < USERTRACK) - m_aFrontEndSprites[i + FE_RADIO1].Draw((SCREEN_WIDTH * 0.5) + SCREEN_SCALE_X(-fMp3Pos + MENURADIO_ICON_X + (fIconSpacing * i)), MENU_Y(nextYToUse), MENU_X(menuXYpadding), MENU_Y(menuXYpadding), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); - if (i > CHATTERBOX && DMAudio.IsMP3RadioChannelAvailable()) - m_aMenuSprites[MENUSPRITE_MP3LOGO].Draw((SCREEN_WIDTH * 0.5) + SCREEN_SCALE_X(-fMp3Pos + MENURADIO_ICON_X + (fIconSpacing * i)), MENU_Y(nextYToUse), MENU_X(menuXYpadding), MENU_Y(menuXYpadding), i == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); -#endif - } nextYToUse += 70.0f; } } @@ -3181,7 +3181,7 @@ CMenuManager::PrintBriefs() CFont::SetRightJustifyOff(); CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why - float nextY = 40.0f; + float nextY = BRIEFS_TOP_MARGIN; CRGBA newColor; for (int i = 4; i >= 0; i--) { tPreviousBrief &brief = CMessages::PreviousBriefs[i]; @@ -3214,8 +3214,8 @@ CMenuManager::PrintBriefs() newColor.a = FadeIn(255); CFont::SetColor(newColor); #endif - CFont::PrintString(MENU_X_LEFT_ALIGNED(50.0f), nextY, gUString); - nextY += MENU_Y(menuXYpadding); + CFont::PrintString(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), nextY, gUString); + nextY += MENU_Y(BRIEFS_LINE_HEIGHT); } } @@ -3252,6 +3252,9 @@ void CMenuManager::PrintStats() { int rowNum = ConstructStatLine(99999); +#ifdef GTA3_1_1_PATCH + CFont::SetFontStyle(FONT_BANK); +#endif CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why float nextYChange, y, alphaMult; diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 8fe61a36..71aac605 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -18,14 +18,7 @@ #define MENUACTION_WIDTH 38.0f #define MENUACTION_SCALE_MULT 0.9f -#ifndef ASPECT_RATIO_SCALE -#define MENURADIO_ICON_X 31.5f -#else -#define MENURADIO_ICON_X -262.0f -#endif -#define MENURADIO_ICON_Y 29.5f -#define MENURADIO_ICON_W 60.0f -#define MENURADIO_ICON_H 60.0f +#define MENURADIO_ICON_SCALE 60.0f #define MENUSLIDER_X 256.0f #define MENUSLIDER_UNK 256.0f @@ -68,6 +61,10 @@ #define STATS_RATING_X 24.0f #define STATS_RATING_Y 20.0f +#define BRIEFS_TOP_MARGIN 40.0f +#define BRIEFS_LINE_X 50.0f +#define BRIEFS_LINE_HEIGHT 60.0f + #define CONTSETUP_STANDARD_ROW_HEIGHT 10.7f #define CONTSETUP_CLASSIC_ROW_HEIGHT 9.0f #define CONTSETUP_BOUND_HIGHLIGHT_HEIGHT 10 From 555f933780653012e7c2c664f91f88914a42e05e Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Apr 2020 11:31:53 +0300 Subject: [PATCH 069/123] Remove padding fields --- src/audio/AudioManager.h | 37 -------- src/core/ControllerConfig.h | 5 +- src/core/Pad.h | 1 - src/core/PlayerInfo.h | 12 --- src/core/timebars.cpp | 2 +- src/objects/Object.h | 6 +- src/objects/ParticleObject.h | 2 - src/peds/CopPed.h | 12 +-- src/peds/Ped.h | 158 ++++++++++++++++------------------- src/peds/PlayerPed.h | 7 -- src/render/Glass.h | 1 - src/render/Particle.h | 2 - src/render/ParticleMgr.h | 2 - src/render/Shadows.h | 6 -- src/render/WaterCannon.h | 1 - src/save/PCSave.cpp | 4 + src/vehicles/Automobile.h | 1 - src/vehicles/Heli.h | 1 - src/vehicles/Plane.h | 2 - src/vehicles/Vehicle.h | 3 - src/weapons/WeaponEffects.h | 1 - 21 files changed, 86 insertions(+), 180 deletions(-) diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index ad558061..01fa055d 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -143,28 +143,17 @@ public: int32 m_nSampleIndex; uint8 m_bBankIndex; bool m_bIs2D; - uint8 field_14; // unused - uint8 field_15; // unused int32 m_nReleasingVolumeModificator; int32 m_nFrequency; uint8 m_bVolume; - uint8 field_25; // unused - uint8 field_26; // unused - uint8 field_27; // unused float m_fDistance; int32 m_nLoopCount; int32 m_nLoopStart; int32 m_nLoopEnd; uint8 m_bEmittingVolume; - uint8 field_45; // unused - uint8 field_46; // unused - uint8 field_47; // unused float m_fSpeedMultiplier; float m_fSoundIntensity; bool m_bReleasingSoundFlag; - uint8 field_57; // unused - uint8 field_58; // unused - uint8 field_59; // unused CVector m_vecPos; bool m_bReverbFlag; uint8 m_bLoopsRemaining; @@ -173,15 +162,8 @@ public: int32 m_nReleasingVolumeDivider; bool m_bIsProcessed; bool m_bLoopEnded; - uint8 field_82; // unused - uint8 field_83; // unused int32 m_nCalculatedVolume; int8 m_nVolumeChange; - uint8 field_89; // unused - uint8 field_90; // unused - uint8 field_91; // unused - - // no methods }; static_assert(sizeof(tSound) == 92, "tSound: error"); @@ -197,12 +179,8 @@ public: bool m_bIsUsed; uint8 m_bStatus; int16 m_awAudioEvent[NUM_AUDIOENTITY_EVENTS]; - //uint8 gap_18[2]; float m_afVolume[NUM_AUDIOENTITY_EVENTS]; uint8 m_AudioEvents; - uint8 field_25[3]; - - // no methods }; static_assert(sizeof(tAudioEntity) == 40, "tAudioEntity: error"); @@ -216,8 +194,6 @@ public: float m_fDistance; uint8 m_bVolume; int8 m_nProcess; - - // no methods }; static_assert(sizeof(tPedComment) == 28, "tPedComment: error"); @@ -244,18 +220,12 @@ class cMissionAudio public: CVector m_vecPos; bool m_bPredefinedProperties; - //uint8 gap_13[3]; int m_nSampleIndex; uint8 m_bLoadingStatus; uint8 m_bPlayStatus; uint8 field_22; // todo find a name - uint8 field_23; // unused int32 m_nMissionAudioCounter; bool m_bIsPlayed; - uint8 field_29; // unused - uint8 field_30; // unused - uint8 field_31; // unused - // no methods }; static_assert(sizeof(cMissionAudio) == 32, "cMissionAudio: error"); @@ -305,17 +275,11 @@ public: uint8 m_bActiveSamples; uint8 field_4; // unused bool m_bDynamicAcousticModelingStatus; - uint8 field_6; // unused - uint8 field_7; // unused float m_fSpeedOfSound; bool m_bTimerJustReset; - uint8 field_13; // unused - uint8 field_14; // unused - uint8 field_15; // unused int32 m_nTimer; tSound m_sQueueSample; bool m_bActiveSampleQueue; - uint8 gap_109[3]; // unused tSound m_asSamples[NUM_SOUNDS_SAMPLES_BANKS][NUM_SOUNDS_SAMPLES_SLOTS]; uint8 m_abSampleQueueIndexTable[NUM_SOUNDS_SAMPLES_BANKS][NUM_SOUNDS_SAMPLES_SLOTS]; uint8 m_bSampleRequestQueuesStatus[NUM_SOUNDS_SAMPLES_BANKS]; @@ -341,7 +305,6 @@ public: uint8 m_bTimeSpent; uint8 m_bUserPause; uint8 m_bPreviousUserPause; - uint8 field_19195; // unused uint32 m_FrameCounter; cAudioManager(); diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index c328594e..82174343 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -112,20 +112,17 @@ public: }; bool m_bFirstCapture; - char _pad0[3]; #ifdef __DINPUT_INCLUDED__ DIJOYSTATE2 m_OldState; DIJOYSTATE2 m_NewState; #else - uint8 ___padd[0x110 * 2]; + uint32 ___padd[0x110 / 4 * 2]; #endif wchar m_aActionNames[MAX_CONTROLLERACTIONS][ACTIONNAME_LENGTH]; bool m_aButtonStates[MAX_BUTTONS]; - char _pad1[3]; tControllerConfigBind m_aSettings[MAX_CONTROLLERACTIONS][MAX_CONTROLLERTYPES]; bool m_aSimCheckers[MAX_SIMS][MAX_CONTROLLERTYPES]; bool m_bMouseAssociated; - char _pad2[3]; CControllerConfigManager(); diff --git a/src/core/Pad.h b/src/core/Pad.h index 9ebd6396..b3b0849b 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -155,7 +155,6 @@ public: uint8 DisablePlayerControls; int8 bApplyBrakes; char CheatString[12]; - char _pad0[3]; int32 LastTimeTouched; int32 AverageWeapon; int32 AverageEntries; diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 19c5ce23..ff31418c 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -31,22 +31,13 @@ public: uint32 m_nLastBumpPlayerCarTimer; uint32 m_nUnusedTaxiTimer; bool m_bUnusedTaxiThing; - int8 field_197; - int8 field_198; - int8 field_199; uint32 m_nNextSexFrequencyUpdateTime; uint32 m_nNextSexMoneyUpdateTime; int32 m_nSexFrequency; CCivilianPed *m_pHooker; int8 m_WBState; // eWastedBustedState - int8 field_217; - int8 field_218; - int8 field_219; uint32 m_nWBTime; bool m_bInRemoteMode; - int8 field_225; - int8 field_226; - int8 field_227; uint32 m_nTimeLostRemoteCar; uint32 m_nTimeLastHealthLoss; uint32 m_nTimeLastArmourLoss; @@ -54,8 +45,6 @@ public: int32 m_nUpsideDownCounter; int32 field_248; int16 m_nTrafficMultiplier; - int8 field_254; - int8 field_255; float m_fRoadDensity; uint32 m_nPreviousTimeRewardedForExplosion; int32 m_nExplosionsSinceLastReward; @@ -90,7 +79,6 @@ public: void FindClosestCarSectorList(CPtrList&, CPed*, float, float, float, float, float*, CVehicle**); ~CPlayerInfo() { }; - void dtor(void) { this->CPlayerInfo::~CPlayerInfo(); } }; static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error"); diff --git a/src/core/timebars.cpp b/src/core/timebars.cpp index 93d85f8d..5c2dbe3a 100644 --- a/src/core/timebars.cpp +++ b/src/core/timebars.cpp @@ -1,5 +1,5 @@ -#ifndef MASTER #include "common.h" +#ifndef MASTER #include "Font.h" #include "Frontend.h" #include "Timer.h" diff --git a/src/objects/Object.h b/src/objects/Object.h index 0c00f441..081c285a 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -55,20 +55,20 @@ public: int8 bUseVehicleColours : 1; int8 m_obj_flag80 : 1; int8 m_nBonusValue; - int8 field_173; float m_fCollisionDamageMultiplier; uint8 m_nCollisionDamageEffect; uint8 m_nSpecialCollisionResponseCases; bool m_bCameraToAvoidThisObject; + + // this batch is unused int8 field_17B; int8 field_17C; int8 field_17D; int8 field_17E; int8 field_17F; + uint32 m_nEndOfLifeTime; int16 m_nRefModelIndex; - int8 field_186; - int8 field_187; CEntity *m_pCurSurface; CEntity *m_pCollidingEntity; int8 m_colour1, m_colour2; diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h index cfa5936d..9e28d272 100644 --- a/src/objects/ParticleObject.h +++ b/src/objects/ParticleObject.h @@ -53,14 +53,12 @@ public: uint8 m_nSkipFrames; uint16 m_nFrameCounter; uint16 m_nState; - char _pad0[2]; CVector m_vecTarget; float m_fRandVal; float m_fSize; CRGBA m_Color; uint8 m_bRemove; int8 m_nCreationChance; - char _pad1[2]; static CParticleObject *pCloseListHead; static CParticleObject *pFarListHead; diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index 625cae49..62234b7e 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -13,17 +13,13 @@ class CCopPed : public CPed { public: int16 m_wRoadblockNode; - int8 field_1342; - int8 field_1343; float m_fDistanceToTarget; - int8 m_bIsInPursuit; - int8 m_bIsDisabledCop; + bool m_bIsInPursuit; + bool m_bIsDisabledCop; int8 field_1350; bool m_bBeatingSuspect; - int8 m_bStopAndShootDisabledZone; - int8 m_bZoneDisabled; - int8 field_1354; - int8 field_1355; + bool m_bStopAndShootDisabledZone; + bool m_bZoneDisabled; int32 field_1356; eCopType m_nCopType; int8 field_1364; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 9f660693..fc53e4bc 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -301,95 +301,92 @@ public: float m_fCollisionSpeed; // cf. https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CPed.h from R* - uint8 bIsStanding : 1; - uint8 m_ped_flagA2 : 1; // bWasStanding? - uint8 bIsAttacking : 1; // doesn't reset after fist fight - uint8 bIsPointingGunAt : 1; - uint8 bIsLooking : 1; - uint8 bKeepTryingToLook : 1; // if we can't look somewhere due to unreachable angles - uint8 bIsRestoringLook : 1; - uint8 bIsAimingGun : 1; + uint32 bIsStanding : 1; + uint32 m_ped_flagA2 : 1; // bWasStanding? + uint32 bIsAttacking : 1; // doesn't reset after fist fight + uint32 bIsPointingGunAt : 1; + uint32 bIsLooking : 1; + uint32 bKeepTryingToLook : 1; // if we can't look somewhere due to unreachable angles + uint32 bIsRestoringLook : 1; + uint32 bIsAimingGun : 1; - uint8 bIsRestoringGun : 1; - uint8 bCanPointGunAtTarget : 1; - uint8 bIsTalking : 1; - uint8 bIsInTheAir : 1; - uint8 bIsLanding : 1; - uint8 bIsRunning : 1; // on some conditions - uint8 bHitSomethingLastFrame : 1; - uint8 bVehEnterDoorIsBlocked : 1; // because someone else enters/exits from there + uint32 bIsRestoringGun : 1; + uint32 bCanPointGunAtTarget : 1; + uint32 bIsTalking : 1; + uint32 bIsInTheAir : 1; + uint32 bIsLanding : 1; + uint32 bIsRunning : 1; // on some conditions + uint32 bHitSomethingLastFrame : 1; + uint32 bVehEnterDoorIsBlocked : 1; // because someone else enters/exits from there - uint8 bCanPedEnterSeekedCar : 1; - uint8 bRespondsToThreats : 1; - uint8 bRenderPedInCar : 1; - uint8 bChangedSeat : 1; - uint8 bUpdateAnimHeading : 1; - uint8 bBodyPartJustCameOff : 1; - uint8 bIsShooting : 1; - uint8 bFindNewNodeAfterStateRestore : 1; + uint32 bCanPedEnterSeekedCar : 1; + uint32 bRespondsToThreats : 1; + uint32 bRenderPedInCar : 1; + uint32 bChangedSeat : 1; + uint32 bUpdateAnimHeading : 1; + uint32 bBodyPartJustCameOff : 1; + uint32 bIsShooting : 1; + uint32 bFindNewNodeAfterStateRestore : 1; - uint8 bHasACamera : 1; // does ped possess a camera to document accidents involves fire/explosion - uint8 bGonnaInvestigateEvent : 1; - uint8 bPedIsBleeding : 1; - uint8 bStopAndShoot : 1; // Ped cannot reach target to attack with fist, need to use gun - uint8 bIsPedDieAnimPlaying : 1; - uint8 bUsePedNodeSeek : 1; - uint8 bObjectiveCompleted : 1; - uint8 bScriptObjectiveCompleted : 1; + uint32 bHasACamera : 1; // does ped possess a camera to document accidents involves fire/explosion + uint32 bGonnaInvestigateEvent : 1; + uint32 bPedIsBleeding : 1; + uint32 bStopAndShoot : 1; // Ped cannot reach target to attack with fist, need to use gun + uint32 bIsPedDieAnimPlaying : 1; + uint32 bUsePedNodeSeek : 1; + uint32 bObjectiveCompleted : 1; + uint32 bScriptObjectiveCompleted : 1; - uint8 bKindaStayInSamePlace : 1; - uint8 bBeingChasedByPolice : 1; // Unused VC leftover. Should've been set for criminal/gang members - uint8 bNotAllowedToDuck : 1; - uint8 bCrouchWhenShooting : 1; - uint8 bIsDucking : 1; - uint8 bGetUpAnimStarted : 1; - uint8 bDoBloodyFootprints : 1; - uint8 bFleeAfterExitingCar : 1; + uint32 bKindaStayInSamePlace : 1; + uint32 bBeingChasedByPolice : 1; // Unused VC leftover. Should've been set for criminal/gang members + uint32 bNotAllowedToDuck : 1; + uint32 bCrouchWhenShooting : 1; + uint32 bIsDucking : 1; + uint32 bGetUpAnimStarted : 1; + uint32 bDoBloodyFootprints : 1; + uint32 bFleeAfterExitingCar : 1; - uint8 bWanderPathAfterExitingCar : 1; - uint8 bIsLeader : 1; - uint8 bDontDragMeOutCar : 1; // unfinished feature - uint8 m_ped_flagF8 : 1; - uint8 bWillBeQuickJacked : 1; - uint8 bCancelEnteringCar : 1; // after door is opened or couldn't be opened due to it's locked - uint8 bObstacleShowedUpDuringKillObjective : 1; - uint8 bDuckAndCover : 1; + uint32 bWanderPathAfterExitingCar : 1; + uint32 bIsLeader : 1; + uint32 bDontDragMeOutCar : 1; // unfinished feature + uint32 m_ped_flagF8 : 1; + uint32 bWillBeQuickJacked : 1; + uint32 bCancelEnteringCar : 1; // after door is opened or couldn't be opened due to it's locked + uint32 bObstacleShowedUpDuringKillObjective : 1; + uint32 bDuckAndCover : 1; - uint8 bStillOnValidPoly : 1; // set if the polygon the ped is on is still valid for collision - uint8 bAllowMedicsToReviveMe : 1; - uint8 bResetWalkAnims : 1; - uint8 bStartWanderPathOnFoot : 1; // exits the car if he's in it, reset after path found - uint8 bOnBoat : 1; // not just driver, may be just standing - uint8 bBusJacked : 1; - uint8 bGonnaKillTheCarJacker : 1; // only set when car is jacked from right door and when arrested by police - uint8 bFadeOut : 1; + uint32 bStillOnValidPoly : 1; // set if the polygon the ped is on is still valid for collision + uint32 bAllowMedicsToReviveMe : 1; + uint32 bResetWalkAnims : 1; + uint32 bStartWanderPathOnFoot : 1; // exits the car if he's in it, reset after path found + uint32 bOnBoat : 1; // not just driver, may be just standing + uint32 bBusJacked : 1; + uint32 bGonnaKillTheCarJacker : 1; // only set when car is jacked from right door and when arrested by police + uint32 bFadeOut : 1; - uint8 bKnockedUpIntoAir : 1; // has ped been knocked up into the air by a car collision - uint8 bHitSteepSlope : 1; // has ped collided/is standing on a steep slope (surface type) - uint8 bCullExtraFarAway : 1; // special ped only gets culled if it's extra far away (for roadblocks) - uint8 bClearObjective : 1; - uint8 bTryingToReachDryLand : 1; // has ped just exited boat and trying to get to dry land - uint8 bCollidedWithMyVehicle : 1; - uint8 bRichFromMugging : 1; // ped has lots of cash cause they've been mugging people - uint8 bChrisCriminal : 1; // Is a criminal as killed during Chris' police mission (should be counted as such) + uint32 bKnockedUpIntoAir : 1; // has ped been knocked up into the air by a car collision + uint32 bHitSteepSlope : 1; // has ped collided/is standing on a steep slope (surface type) + uint32 bCullExtraFarAway : 1; // special ped only gets culled if it's extra far away (for roadblocks) + uint32 bClearObjective : 1; + uint32 bTryingToReachDryLand : 1; // has ped just exited boat and trying to get to dry land + uint32 bCollidedWithMyVehicle : 1; + uint32 bRichFromMugging : 1; // ped has lots of cash cause they've been mugging people + uint32 bChrisCriminal : 1; // Is a criminal as killed during Chris' police mission (should be counted as such) - uint8 bShakeFist : 1; // test shake hand at look entity - uint8 bNoCriticalHits : 1; // if set, limbs won't came off - uint8 bVehExitWillBeInstant : 1; - uint8 bHasAlreadyBeenRecorded : 1; - uint8 bFallenDown : 1; + uint32 bShakeFist : 1; // test shake hand at look entity + uint32 bNoCriticalHits : 1; // if set, limbs won't came off + uint32 bVehExitWillBeInstant : 1; + uint32 bHasAlreadyBeenRecorded : 1; + uint32 bFallenDown : 1; #ifdef VC_PED_PORTS - uint8 bSomeVCflag1 : 1; + uint32 bSomeVCflag1 : 1; #else - uint8 m_ped_flagI20 : 1; + uint32 m_ped_flagI20 : 1; #endif - uint8 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator - uint8 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle + uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator + uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle - uint8 stuff10[3]; uint8 CharCreatedBy; - uint8 field_161; - uint8 pad_162[2]; eObjective m_objective; eObjective m_prevObjective; CPed *m_pedInObjective; @@ -424,8 +421,6 @@ public: uint16 m_nPathNodes; int16 m_nCurPathNode; int8 m_nPathDir; -private: - int8 _pad2B5[3]; public: CPathNode *m_pLastPathNode; CPathNode *m_pNextPathNode; @@ -436,7 +431,6 @@ public: int16 m_routePointsPassed; int16 m_routeType; // See PedRouteType int16 m_routePointsBeingPassed; - uint16 field_2D2; CVector2D m_moved; float m_fRotationCur; float m_fRotationDest; @@ -450,10 +444,8 @@ public: CEntity *m_pSeekTarget; CVehicle *m_pMyVehicle; bool bInVehicle; - uint8 pad_315[3]; float m_distanceToCountSeekDone; bool bRunningToPhone; - uint8 field_31D; int16 m_phoneId; eCrimeType m_crimeToReportOnPhone; uint32 m_phoneTalkTimer; @@ -468,7 +460,6 @@ public: uint32 m_collidingThingTimer; CEntity *m_pCollidingEntity; uint8 m_stateUnused; - uint8 pad_351[3]; uint32 m_timerUnused; CVector2D *m_wanderRangeBounds; // array with 2 CVector2D (actually unused CRange2D class) - unused CWeapon m_weapons[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS]; @@ -483,7 +474,6 @@ public: uint8 m_fightButtonPressure; FightState m_fightState; bool m_takeAStepAfterAttack; - uint8 pad_4B3; CFire *m_pFire; CEntity *m_pLookTarget; float m_fLookDirection; @@ -502,11 +492,9 @@ public: uint8 m_panicCounter; bool m_deadBleeding; int8 m_bodyPartBleeding; // PedNode, but -1 if there isn't - uint8 m_field_4F3; CPed *m_nearPeds[10]; uint16 m_numNearPeds; int8 m_lastWepDam; - uint8 pad_51F; uint32 m_lastSoundStart; uint32 m_soundStart; uint16 m_lastQueuedSound; diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index f96d8e6a..81f8e4d7 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -23,20 +23,13 @@ public: uint32 m_nHitAnimDelayTimer; float m_fAttackButtonCounter; bool m_bHaveTargetSelected; // may have better name - int8 field_1381; - int8 field_1382; - int8 field_1383; CEntity *m_pEvadingFrom; // is this CPhysical? int32 m_nTargettableObjects[4]; bool m_bAdrenalineActive; bool m_bHasLockOnTarget; - int8 field_1406; - int8 field_1407; uint32 m_nAdrenalineTime; bool m_bCanBeDamaged; int8 field_1413; - int8 field_1414; - int8 field_1415; CVector m_vecSafePos[6]; // safe places from the player, for example behind a tree CPed *m_pPedAtSafePos[6]; float m_fWalkAngle; diff --git a/src/render/Glass.h b/src/render/Glass.h index dccd9d3d..51c5aae9 100644 --- a/src/render/Glass.h +++ b/src/render/Glass.h @@ -13,7 +13,6 @@ public: uint8 m_nTriIndex; bool m_bActive; bool m_bShattered; - char _pad0[1]; CFallingGlassPane() { } ~CFallingGlassPane() { } diff --git a/src/render/Particle.h b/src/render/Particle.h index 604fbb82..b51be6a5 100644 --- a/src/render/Particle.h +++ b/src/render/Particle.h @@ -24,7 +24,6 @@ public: uint16 m_nZRotationTimer; float m_fCurrentZRadius; uint16 m_nZRadiusTimer; - char _pad0[2]; float m_fSize; float m_fExpansionRate; uint16 m_nFadeToBlackTimer; @@ -36,7 +35,6 @@ public: int16 m_nRotationStep; int16 m_nRotation; RwRGBA m_Color; - char _pad1[2]; CParticle *m_pNext; CParticle() diff --git a/src/render/ParticleMgr.h b/src/render/ParticleMgr.h index 5e8da1e4..605e69fe 100644 --- a/src/render/ParticleMgr.h +++ b/src/render/ParticleMgr.h @@ -120,7 +120,6 @@ struct tParticleSystemData uint16 m_nFinalAnimationFrame; uint16 m_nAnimationSpeed; uint16 m_nRotationSpeed; - char _pad1[2]; float m_fGravitationalAcceleration; int32 m_nFrictionDecceleration; int32 m_nLifeSpan; @@ -134,7 +133,6 @@ struct tParticleSystemData RwRGBA m_RenderColouring; uint8 m_InitialColorVariation; RwRGBA m_FadeDestinationColor; - char _pad2[3]; uint32 m_ColorFadeTime; RwRaster **m_ppRaster; diff --git a/src/render/Shadows.h b/src/render/Shadows.h index d209fe90..65274879 100644 --- a/src/render/Shadows.h +++ b/src/render/Shadows.h @@ -46,7 +46,6 @@ public: uint8 bRendered : 1; //uint8 bDrawOnBuildings : 1; } m_nFlags; - char _pad0; RwTexture *m_pTexture; CStoredShadow() @@ -58,11 +57,9 @@ class CPolyBunch { public: int16 m_nNumVerts; - char _pad0[2]; CVector m_aVerts[7]; uint8 m_aU[7]; uint8 m_aV[7]; - char _pad1[2]; CPolyBunch *m_pNext; CPolyBunch() @@ -82,7 +79,6 @@ public: float m_fZDistance; float m_fScale; uint8 m_nType; - char _pad0; int16 m_nIntensity; // unsigned ? uint8 m_nRed; uint8 m_nGreen; @@ -90,7 +86,6 @@ public: bool m_bJustCreated; bool m_bRendered; bool m_bTemp; - char _pad1[2]; RwTexture *m_pTexture; CStaticShadow() @@ -113,7 +108,6 @@ public: uint8 m_nRed; uint8 m_nGreen; uint8 m_nBlue; - char _pad0[2]; uint32 m_nTimeCreated; uint32 m_nLifeTime; RwTexture *m_pTexture; diff --git a/src/render/WaterCannon.h b/src/render/WaterCannon.h index 826dc78e..d2d20863 100644 --- a/src/render/WaterCannon.h +++ b/src/render/WaterCannon.h @@ -13,7 +13,6 @@ public: int32 m_nId; int16 m_nCur; - char _pad0[2]; uint32 m_nTimeCreated; CVector m_avecPos[NUM_SEGMENTPOINTS]; CVector m_avecVelocity[NUM_SEGMENTPOINTS]; diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 3794ba88..46185850 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -86,7 +86,11 @@ C_PcSave::PopulateSlotInfo() SlotSaveDate[i][0] = '\0'; } for (int i = 0; i < SLOT_COUNT; i++) { +#ifdef FIX_BUGS + char savename[MAX_PATH]; +#else char savename[52]; +#endif struct { int size; wchar FileName[24]; diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 66774612..2de85a99 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -92,7 +92,6 @@ public: uint8 bWaterTight : 1; // no damage for non-player peds uint8 bNotDamagedUpsideDown : 1; uint8 bMoreResistantToDamage : 1; - uint8 field_4DB; CEntity *m_pBombRigger; int16 field_4E0; uint16 m_hydraulicState; diff --git a/src/vehicles/Heli.h b/src/vehicles/Heli.h index 15dff7b1..39e4cbcf 100644 --- a/src/vehicles/Heli.h +++ b/src/vehicles/Heli.h @@ -70,7 +70,6 @@ public: static bool ScriptHeliOn; CHeli(int32 id, uint8 CreatedBy); - CHeli* ctor(int, uint8); // from CEntity void SetModelIndex(uint32 id); diff --git a/src/vehicles/Plane.h b/src/vehicles/Plane.h index 4c8e70aa..79738858 100644 --- a/src/vehicles/Plane.h +++ b/src/vehicles/Plane.h @@ -33,8 +33,6 @@ public: int16 m_nPlaneId; int16 m_isFarAway; int16 m_nCurPathNode; - char field_654; - char field_655; float m_fSpeed; uint32 m_nFrameWhenHit; bool m_bHasBeenHit; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index bfc6d95d..2ae78829 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -130,7 +130,6 @@ public: int8 m_nGettingInFlags; int8 m_nGettingOutFlags; uint8 m_nNumMaxPassengers; - char field_1CD[3]; float field_1D0[4]; CEntity *m_pCurGroundEntity; CFire *m_pCarFire; @@ -180,7 +179,6 @@ public: int16 m_nRoadblockNode; float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode uint8 m_nCurrentGear; - int8 field_205[3]; float m_fChangeGearTime; uint32 m_nGunFiringTime; // last time when gun on vehicle was fired (used on boats) uint32 m_nTimeOfDeath; @@ -296,7 +294,6 @@ class cVehicleParams { public: bool m_bDistanceCalculated; - char gap_1[3]; float m_fDistance; CVehicle *m_pVehicle; cTransmission *m_pTransmission; diff --git a/src/weapons/WeaponEffects.h b/src/weapons/WeaponEffects.h index 31c5a309..f6592b3e 100644 --- a/src/weapons/WeaponEffects.h +++ b/src/weapons/WeaponEffects.h @@ -4,7 +4,6 @@ class CWeaponEffects { public: bool m_bActive; - char _pad[3]; CVector m_vecPos; uint8 m_nRed; uint8 m_nGreen; From a6825e1ae6c9b60d7f3bc42f6916839d707d6797 Mon Sep 17 00:00:00 2001 From: ThirteenAG Date: Sat, 18 Apr 2020 11:59:46 +0300 Subject: [PATCH 070/123] librw compilation in prebuild event of reIII --- librw | 2 +- premake5.lua | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/librw b/librw index 48938896..bc9cb506 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 4893889621621c077690d522e7e9a10249a65a85 +Subproject commit bc9cb506ecd5abb869292860ed287c1b029b30cc diff --git a/premake5.lua b/premake5.lua index c427211a..ce637640 100644 --- a/premake5.lua +++ b/premake5.lua @@ -101,6 +101,8 @@ project "re3" targetextension ".exe" characterset ("MBCS") linkoptions "/SAFESEH:NO" + + prebuildcommands { "cd \"../librw\" && premake5 " .. _ACTION .. " && msbuild \"build/librw.sln\" /property:Configuration=%{cfg.longname} /property:Platform=\"win-x86-d3d9\"" } filter "configurations:Debug" defines { "DEBUG", "LIBRW", "RW_D3D9" } From eadb5a16aa36a5187e7bc244577451607069d016 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Apr 2020 12:23:20 +0300 Subject: [PATCH 071/123] Zones save/load --- src/core/Zones.cpp | 271 ++++++++++++++------------------------------- 1 file changed, 83 insertions(+), 188 deletions(-) diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 6375de1c..804708b4 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -625,218 +625,113 @@ CTheZones::InitialiseAudioZoneArray(void) } void -CTheZones::SaveAllZones(uint8 *buffer, uint32 *length) +CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) { + INITSAVEBUF int i; - *length = 8 + 12 + - NUMZONES*56 + 2*NUMZONES*58 + 4 + - NUMMAPZONES*56 + NUMAUDIOZONES*2 + 4; + *size = SAVE_HEADER_SIZE + + sizeof(int32) // GetIndexForZonePointer + + sizeof(m_CurrLevel) + sizeof(FindIndex) + + sizeof(int16) // padding + + sizeof(ZoneArray) + sizeof(ZoneInfoArray) + + sizeof(TotalNumberOfZones) + sizeof(TotalNumberOfZoneInfos) + + sizeof(MapZoneArray) + sizeof(AudioZoneArray) + + sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones); - buffer[0] = 'Z'; - buffer[1] = 'N'; - buffer[2] = 'S'; - buffer[3] = '\0'; - *(uint32*)(buffer+4) = *length - 8; - buffer += 8; + WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); - *(int32*)(buffer) = GetIndexForZonePointer(m_pPlayersZone); - *(int32*)(buffer+4) = m_CurrLevel; - *(int16*)(buffer+8) = FindIndex; - *(int16*)(buffer+10) = 0; - buffer += 12; + WriteSaveBuf(buffer, GetIndexForZonePointer(m_pPlayersZone)); + WriteSaveBuf(buffer, m_CurrLevel); + WriteSaveBuf(buffer, FindIndex); + WriteSaveBuf(buffer, (int16)0); // padding - for(i = 0; i < NUMZONES; i++){ - memcpy(buffer, ZoneArray[i].name, 8); - *(float*)(buffer+8) = ZoneArray[i].minx; - *(float*)(buffer+12) = ZoneArray[i].miny; - *(float*)(buffer+16) = ZoneArray[i].minz; - *(float*)(buffer+20) = ZoneArray[i].maxx; - *(float*)(buffer+24) = ZoneArray[i].maxy; - *(float*)(buffer+28) = ZoneArray[i].maxz; - *(int32*)(buffer+32) = ZoneArray[i].type; - *(int32*)(buffer+36) = ZoneArray[i].level; - *(int16*)(buffer+40) = ZoneArray[i].zoneinfoDay; - *(int16*)(buffer+42) = ZoneArray[i].zoneinfoNight; - *(int32*)(buffer+44) = GetIndexForZonePointer(ZoneArray[i].child); - *(int32*)(buffer+48) = GetIndexForZonePointer(ZoneArray[i].parent); - *(int32*)(buffer+52) = GetIndexForZonePointer(ZoneArray[i].next); - buffer += 56; + for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ + CZone *zone = WriteSaveBuf(buffer, ZoneArray[i]); + zone->child = (CZone*)GetIndexForZonePointer(ZoneArray[i].child); + zone->parent = (CZone*)GetIndexForZonePointer(ZoneArray[i].parent); + zone->next = (CZone*)GetIndexForZonePointer(ZoneArray[i].next); } - for(i = 0; i < 2*NUMZONES; i++){ - *(int16*)(buffer) = ZoneInfoArray[i].carDensity; - *(int16*)(buffer+2) = ZoneInfoArray[i].carThreshold[0]; - *(int16*)(buffer+4) = ZoneInfoArray[i].carThreshold[1]; - *(int16*)(buffer+6) = ZoneInfoArray[i].carThreshold[2]; - *(int16*)(buffer+8) = ZoneInfoArray[i].carThreshold[3]; - *(int16*)(buffer+10) = ZoneInfoArray[i].carThreshold[4]; - *(int16*)(buffer+12) = ZoneInfoArray[i].carThreshold[5]; - *(int16*)(buffer+14) = ZoneInfoArray[i].copThreshold; - *(int16*)(buffer+16) = ZoneInfoArray[i].gangThreshold[0]; - *(int16*)(buffer+18) = ZoneInfoArray[i].gangThreshold[1]; - *(int16*)(buffer+20) = ZoneInfoArray[i].gangThreshold[2]; - *(int16*)(buffer+22) = ZoneInfoArray[i].gangThreshold[3]; - *(int16*)(buffer+24) = ZoneInfoArray[i].gangThreshold[4]; - *(int16*)(buffer+26) = ZoneInfoArray[i].gangThreshold[5]; - *(int16*)(buffer+28) = ZoneInfoArray[i].gangThreshold[6]; - *(int16*)(buffer+30) = ZoneInfoArray[i].gangThreshold[7]; - *(int16*)(buffer+32) = ZoneInfoArray[i].gangThreshold[8]; - *(uint16*)(buffer+34) = ZoneInfoArray[i].pedDensity; - *(uint16*)(buffer+36) = ZoneInfoArray[i].copDensity; - *(uint16*)(buffer+38) = ZoneInfoArray[i].gangDensity[0]; - *(uint16*)(buffer+40) = ZoneInfoArray[i].gangDensity[1]; - *(uint16*)(buffer+42) = ZoneInfoArray[i].gangDensity[2]; - *(uint16*)(buffer+44) = ZoneInfoArray[i].gangDensity[3]; - *(uint16*)(buffer+46) = ZoneInfoArray[i].gangDensity[4]; - *(uint16*)(buffer+48) = ZoneInfoArray[i].gangDensity[5]; - *(uint16*)(buffer+50) = ZoneInfoArray[i].gangDensity[6]; - *(uint16*)(buffer+52) = ZoneInfoArray[i].gangDensity[7]; - *(uint16*)(buffer+54) = ZoneInfoArray[i].gangDensity[8]; - *(uint16*)(buffer+56) = ZoneInfoArray[i].pedGroup; - buffer += 58; + for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) + WriteSaveBuf(buffer, ZoneInfoArray[i]); + + WriteSaveBuf(buffer, TotalNumberOfZones); + WriteSaveBuf(buffer, TotalNumberOfZoneInfos); + + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) { + CZone* zone = WriteSaveBuf(buffer, MapZoneArray[i]); + + /* + The call of GetIndexForZonePointer is wrong, as it is + meant for a different array, but the game doesn't brake + if those fields are nil. Let's make sure they are. + */ + assert(MapZoneArray[i].child == nil); + assert(MapZoneArray[i].parent == nil); + assert(MapZoneArray[i].next == nil); + zone->child = (CZone*)GetIndexForZonePointer(MapZoneArray[i].child); + zone->parent = (CZone*)GetIndexForZonePointer(MapZoneArray[i].parent); + zone->next = (CZone*)GetIndexForZonePointer(MapZoneArray[i].next); } - *(uint16*)(buffer) = TotalNumberOfZones; - *(uint16*)(buffer+2) = TotalNumberOfZoneInfos; - buffer += 4; + for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) + WriteSaveBuf(buffer, AudioZoneArray[i]); - for(i = 0; i < NUMMAPZONES; i++){ - memcpy(buffer, MapZoneArray[i].name, 8); - *(float*)(buffer+8) = MapZoneArray[i].minx; - *(float*)(buffer+12) = MapZoneArray[i].miny; - *(float*)(buffer+16) = MapZoneArray[i].minz; - *(float*)(buffer+20) = MapZoneArray[i].maxx; - *(float*)(buffer+24) = MapZoneArray[i].maxy; - *(float*)(buffer+28) = MapZoneArray[i].maxz; - *(int32*)(buffer+32) = MapZoneArray[i].type; - *(int32*)(buffer+36) = MapZoneArray[i].level; - *(int16*)(buffer+40) = MapZoneArray[i].zoneinfoDay; - *(int16*)(buffer+42) = MapZoneArray[i].zoneinfoNight; -#ifdef STANDALONE - // BUG: GetIndexForZonePointer uses ZoneArray - // so indices will be unpredictable with different memory layout - assert(0); -#endif - *(int32*)(buffer+44) = GetIndexForZonePointer(MapZoneArray[i].child); - *(int32*)(buffer+48) = GetIndexForZonePointer(MapZoneArray[i].parent); - *(int32*)(buffer+52) = GetIndexForZonePointer(MapZoneArray[i].next); - buffer += 56; - } + WriteSaveBuf(buffer, TotalNumberOfMapZones); + WriteSaveBuf(buffer, NumberOfAudioZones); - for(i = 0; i < NUMAUDIOZONES; i++){ - *(int16*)buffer = AudioZoneArray[i]; - buffer += 2; - } - - *(uint16*)(buffer) = TotalNumberOfMapZones; - *(uint16*)(buffer+2) = NumberOfAudioZones; + VALIDATESAVEBUF(*size) } void -CTheZones::LoadAllZones(uint8 *buffer, uint32 length) +CTheZones::LoadAllZones(uint8 *buffer, uint32 size) { + INITSAVEBUF int i; - assert(length == 8 + 12 + - NUMZONES*56 + 2*NUMZONES*58 + 4 + - NUMMAPZONES*56 + NUMAUDIOZONES*2 + 4); - assert(buffer[0] == 'Z'); - assert(buffer[1] == 'N'); - assert(buffer[2] == 'S'); - assert(buffer[3] == '\0'); - assert(*(uint32*)(buffer+4) == length - 8); - buffer += 8; + CheckSaveHeader(buffer, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); - m_pPlayersZone = GetPointerForZoneIndex(*(int32*)(buffer)); - m_CurrLevel = (eLevelName)*(int32*)(buffer+4); - FindIndex = *(int16*)(buffer+8); - assert(*(int16*)(buffer+10) == 0); - buffer += 12; + m_pPlayersZone = GetPointerForZoneIndex(ReadSaveBuf(buffer)); + m_CurrLevel = ReadSaveBuf(buffer); + FindIndex = ReadSaveBuf(buffer); + ReadSaveBuf(buffer); - for(i = 0; i < NUMZONES; i++){ - memcpy(ZoneArray[i].name, buffer, 8); - ZoneArray[i].minx = *(float*)(buffer+8); - ZoneArray[i].miny = *(float*)(buffer+12); - ZoneArray[i].minz = *(float*)(buffer+16); - ZoneArray[i].maxx = *(float*)(buffer+20); - ZoneArray[i].maxy = *(float*)(buffer+24); - ZoneArray[i].maxz = *(float*)(buffer+28); - ZoneArray[i].type = (eZoneType)*(int32*)(buffer+32); - ZoneArray[i].level = (eLevelName)*(int32*)(buffer+36); - ZoneArray[i].zoneinfoDay = *(int16*)(buffer+40); - ZoneArray[i].zoneinfoNight = *(int16*)(buffer+42); - ZoneArray[i].child = GetPointerForZoneIndex(*(int32*)(buffer+44)); - ZoneArray[i].parent = GetPointerForZoneIndex(*(int32*)(buffer+48)); - ZoneArray[i].next = GetPointerForZoneIndex(*(int32*)(buffer+52)); - buffer += 56; + for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ + ZoneArray[i] = ReadSaveBuf(buffer); + + ZoneArray[i].child = GetPointerForZoneIndex((int32)ZoneArray[i].child); + ZoneArray[i].parent = GetPointerForZoneIndex((int32)ZoneArray[i].parent); + ZoneArray[i].next = GetPointerForZoneIndex((int32)ZoneArray[i].next); } - for(i = 0; i < 2*NUMZONES; i++){ - ZoneInfoArray[i].carDensity = *(int16*)(buffer); - ZoneInfoArray[i].carThreshold[0] = *(int16*)(buffer+2); - ZoneInfoArray[i].carThreshold[1] = *(int16*)(buffer+4); - ZoneInfoArray[i].carThreshold[2] = *(int16*)(buffer+6); - ZoneInfoArray[i].carThreshold[3] = *(int16*)(buffer+8); - ZoneInfoArray[i].carThreshold[4] = *(int16*)(buffer+10); - ZoneInfoArray[i].carThreshold[5] = *(int16*)(buffer+12); - ZoneInfoArray[i].copThreshold = *(int16*)(buffer+14); - ZoneInfoArray[i].gangThreshold[0] = *(int16*)(buffer+16); - ZoneInfoArray[i].gangThreshold[1] = *(int16*)(buffer+18); - ZoneInfoArray[i].gangThreshold[2] = *(int16*)(buffer+20); - ZoneInfoArray[i].gangThreshold[3] = *(int16*)(buffer+22); - ZoneInfoArray[i].gangThreshold[4] = *(int16*)(buffer+24); - ZoneInfoArray[i].gangThreshold[5] = *(int16*)(buffer+26); - ZoneInfoArray[i].gangThreshold[6] = *(int16*)(buffer+28); - ZoneInfoArray[i].gangThreshold[7] = *(int16*)(buffer+30); - ZoneInfoArray[i].gangThreshold[8] = *(int16*)(buffer+32); - ZoneInfoArray[i].pedDensity = *(uint16*)(buffer+34); - ZoneInfoArray[i].copDensity = *(uint16*)(buffer+36); - ZoneInfoArray[i].gangDensity[0] = *(uint16*)(buffer+38); - ZoneInfoArray[i].gangDensity[1] = *(uint16*)(buffer+40); - ZoneInfoArray[i].gangDensity[2] = *(uint16*)(buffer+42); - ZoneInfoArray[i].gangDensity[3] = *(uint16*)(buffer+44); - ZoneInfoArray[i].gangDensity[4] = *(uint16*)(buffer+46); - ZoneInfoArray[i].gangDensity[5] = *(uint16*)(buffer+48); - ZoneInfoArray[i].gangDensity[6] = *(uint16*)(buffer+50); - ZoneInfoArray[i].gangDensity[7] = *(uint16*)(buffer+52); - ZoneInfoArray[i].gangDensity[8] = *(uint16*)(buffer+54); - ZoneInfoArray[i].pedGroup = *(uint16*)(buffer+56); - buffer += 58; + for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) + ZoneInfoArray[i] = ReadSaveBuf(buffer); + + TotalNumberOfZones = ReadSaveBuf(buffer); + TotalNumberOfZoneInfos = ReadSaveBuf(buffer); + + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){ + MapZoneArray[i] = ReadSaveBuf(buffer); + + /* + The call of GetPointerForZoneIndex is wrong, as it is + meant for a different array, but the game doesn't brake + if save data stored is -1. + */ + MapZoneArray[i].child = GetPointerForZoneIndex((int32)MapZoneArray[i].child); + MapZoneArray[i].parent = GetPointerForZoneIndex((int32)MapZoneArray[i].parent); + MapZoneArray[i].next = GetPointerForZoneIndex((int32)MapZoneArray[i].next); + assert(MapZoneArray[i].child == nil); + assert(MapZoneArray[i].parent == nil); + assert(MapZoneArray[i].next == nil); } - TotalNumberOfZones = *(uint16*)(buffer); - TotalNumberOfZoneInfos = *(uint16*)(buffer+2); - buffer += 4; + for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) + AudioZoneArray[i] = ReadSaveBuf(buffer); - for(i = 0; i < NUMMAPZONES; i++){ - memcpy(MapZoneArray[i].name, buffer, 8); - MapZoneArray[i].minx = *(float*)(buffer+8); - MapZoneArray[i].miny = *(float*)(buffer+12); - MapZoneArray[i].minz = *(float*)(buffer+16); - MapZoneArray[i].maxx = *(float*)(buffer+20); - MapZoneArray[i].maxy = *(float*)(buffer+24); - MapZoneArray[i].maxz = *(float*)(buffer+28); - MapZoneArray[i].type = (eZoneType)*(int32*)(buffer+32); - MapZoneArray[i].level = (eLevelName)*(int32*)(buffer+36); - MapZoneArray[i].zoneinfoDay = *(int16*)(buffer+40); - MapZoneArray[i].zoneinfoNight = *(int16*)(buffer+42); -#ifdef STANDALONE - // BUG: GetPointerForZoneIndex uses ZoneArray - // so pointers will be unpredictable with different memory layout - assert(0); -#endif - MapZoneArray[i].child = GetPointerForZoneIndex(*(int32*)(buffer+44)); - MapZoneArray[i].parent = GetPointerForZoneIndex(*(int32*)(buffer+48)); - MapZoneArray[i].next = GetPointerForZoneIndex(*(int32*)(buffer+52)); - buffer += 56; - } + TotalNumberOfMapZones = ReadSaveBuf(buffer); + NumberOfAudioZones = ReadSaveBuf(buffer); - for(i = 0; i < NUMAUDIOZONES; i++){ - AudioZoneArray[i] = *(int16*)buffer; - buffer += 2; - } - - TotalNumberOfMapZones = *(uint16*)(buffer); - NumberOfAudioZones = *(uint16*)(buffer+2); + VALIDATESAVEBUF(size) } From 3f32b69a79c2eb26f12e76b09a5923adf9e2fb3d Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Sat, 18 Apr 2020 12:20:20 +0200 Subject: [PATCH 072/123] Fix crash in cAudioManager::ServicePoliceRadio --- src/audio/PoliceRadio.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/audio/PoliceRadio.cpp b/src/audio/PoliceRadio.cpp index d9c6bfd7..c4946da6 100644 --- a/src/audio/PoliceRadio.cpp +++ b/src/audio/PoliceRadio.cpp @@ -1,15 +1,18 @@ #include "common.h" #include "DMAudio.h" + #include "AudioManager.h" + #include "AudioSamples.h" #include "MusicManager.h" -#include "PoliceRadio.h" #include "PlayerPed.h" -#include "sampman.h" -#include "Zones.h" +#include "PoliceRadio.h" +#include "Replay.h" #include "Vehicle.h" #include "World.h" +#include "Zones.h" +#include "sampman.h" const int maxVolume = 127; const int channels = ARRAY_SIZE(cAudioManager::m_asActiveSamples); @@ -155,7 +158,8 @@ cAudioManager::ServicePoliceRadio() if(!m_bUserPause) { bool crimeReport = SetupCrimeReport(); #ifdef FIX_BUGS // Crash at 0x5fe6ef - if(!FindPlayerPed() || !FindPlayerPed()->m_pWanted) return; + if(CReplay::IsPlayingBack() || !FindPlayerPed() || !FindPlayerPed()->m_pWanted) + return; #endif wantedLevel = FindPlayerPed()->m_pWanted->m_nWantedLevel; if(!crimeReport) { From d6314f9564912393134d832b8cc268dd3dbfcbaa Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Sat, 18 Apr 2020 12:29:28 +0200 Subject: [PATCH 073/123] Revert "Part one" This reverts commit 63951d9b957b30a110f42a03edb4833cbbaf380e. --- CMakeLists.txt | 25 ------ src/animation/AnimBlendAssocGroup.cpp | 20 ++--- src/audio/AudioManager.cpp | 2 +- src/audio/DMAudio.h | 1 - src/audio/sampman.cpp | 119 +++++++++++--------------- src/control/Darkel.h | 3 +- src/control/PathFind.cpp | 35 +++----- src/control/TrafficLights.cpp | 2 +- src/core/CrimeType.h | 23 ----- src/core/Game.cpp | 2 +- src/core/General.h | 2 +- src/core/Pad.cpp | 2 +- src/core/PlayerInfo.cpp | 2 +- src/core/Wanted.h | 22 ++++- src/core/common.h | 4 +- src/objects/ParticleObject.h | 2 +- src/peds/Ped.h | 10 +-- src/render/ParticleMgr.h | 78 ++++++++++++++++- src/weapons/Weapon.h | 48 ++++++++++- 19 files changed, 230 insertions(+), 172 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 src/core/CrimeType.h diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 2871dff4..00000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -cmake_Minimum_required(VERSION 3.8) - -project(Re3) - -set (CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -masm=intel -Wdouble-promotion") - -file(GLOB_RECURSE Sources "*.cpp" "*.h") - -MACRO(HEADER_DIRECTORIES return_list) - FILE(GLOB_RECURSE new_list *.h) - SET(dir_list "") - FOREACH(file_path ${new_list}) - GET_FILENAME_COMPONENT(dir_path ${file_path} PATH) - SET(dir_list ${dir_list} ${dir_path}) - ENDFOREACH() - LIST(REMOVE_DUPLICATES dir_list) - SET(${return_list} ${dir_list}) -ENDMACRO() - -HEADER_DIRECTORIES(header_list) - -include_directories(${header_list}) - -add_library(re3 ${Sources}) diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp index 27b091bd..e65bdf8d 100644 --- a/src/animation/AnimBlendAssocGroup.cpp +++ b/src/animation/AnimBlendAssocGroup.cpp @@ -59,7 +59,8 @@ CAnimBlendAssociation* CAnimBlendAssocGroup::CopyAnimation(const char *name) { CAnimBlendAssociation *anim = GetAnimation(name); - if(anim == nil) return nil; + if(anim == nil) + return nil; CAnimManager::UncompressAnimation(anim->hierarchy); return new CAnimBlendAssociation(*anim); } @@ -69,26 +70,19 @@ strcmpIgnoringDigits(const char *s1, const char *s2) { char c1, c2; - for(;;) { + for(;;){ c1 = *s1; c2 = *s2; if(c1) s1++; if(c2) s2++; - if(c1 == '\0' && c2 == '\0') return true; -#if 1 - if(iswdigit(c1) && iswdigit(c2)) -#else + if(c1 == '\0' && c2 == '\0') + return true; if(__ascii_iswdigit(c1) && __ascii_iswdigit(c2)) -#endif continue; -#if 1 - c1 = toupper(c1); - c2 = toupper(c2); -#else c1 = __ascii_toupper(c1); c2 = __ascii_toupper(c2); -#endif - if(c1 != c2) return false; + if(c1 != c2) + return false; } } diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 0a156cd4..4d5f8474 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -10035,7 +10035,7 @@ cAudioManager::UpdateReflections() if(CWorld::ProcessVerticalLine( camPos, m_avecReflectionsPos[4].z, colpoint, ent, true, false, false, false, true, false, - nil)) { + false)) { m_afReflectionsDistances[4] = colpoint.point.z - camPos.z; } else { diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 00bf75ad..9ce073b4 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -1,7 +1,6 @@ #pragma once #include "audio_enums.h" -#include "CrimeType.h" enum eSound : int16 { diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index a375b847..d24de27f 100644 --- a/src/audio/sampman.cpp +++ b/src/audio/sampman.cpp @@ -1986,59 +1986,50 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) if ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER ) { uint32 i = 0; - do { - if(i != 0 || _bIsMp3Active) { - if(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0; - - _CurMP3Pos = 0; - - tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); - - if(mp3) { - mp3 = _pMP3List; - if(mp3 == NULL) { - _bIsMp3Active = false; - nFile = 0; - strcpy(filename, m_szCDRomRootPath); - strcat(filename, StreamedNameTable[nFile]); - - mp3Stream[nStream] = - AIL_open_stream(DIG, filename, 0); - if(mp3Stream[nStream]) { - AIL_set_stream_loop_count( - mp3Stream[nStream], 1); - AIL_set_stream_ms_position( - mp3Stream[nStream], position); - AIL_pause_stream(mp3Stream[nStream], - 0); - return true; - } - - return false; - } + + if ( !_bIsMp3Active ) goto FIND_MP3TRACK; + + do + { + if ( ++_CurMP3Index >= nNumMP3s ) + _CurMP3Index = 0; + + _CurMP3Pos = 0; + + tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); + + if ( mp3 ) + { + mp3 = _pMP3List; + if ( mp3 == NULL ) + { + _bIsMp3Active = false; + nFile = 0; + goto PLAY_STREAMEDTRACK; } - - if(mp3->pLinkPath != NULL) - mp3Stream[nStream] = - AIL_open_stream(DIG, mp3->pLinkPath, 0); - else { - strcpy(filename, _mp3DirectoryPath); - strcat(filename, mp3->aFilename); - - mp3Stream[nStream] = - AIL_open_stream(DIG, filename, 0); - } - - if(mp3Stream[nStream]) { - AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_set_stream_ms_position(mp3Stream[nStream], 0); - AIL_pause_stream(mp3Stream[nStream], 0); - return true; - } - - _bIsMp3Active = false; - continue; } + + if ( mp3->pLinkPath != NULL ) + mp3Stream[nStream] = AIL_open_stream(DIG, mp3->pLinkPath, 0); + else + { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, mp3->aFilename); + + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + } + + if ( mp3Stream[nStream] ) + { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], 0); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + goto NEXT_MP3TRACK; + +FIND_MP3TRACK: if ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] ) position = 0; @@ -2048,23 +2039,10 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) if ( e == NULL ) { nFile = 0; - strcpy(filename, m_szCDRomRootPath); - strcat(filename, StreamedNameTable[nFile]); - mp3Stream[nStream] = - AIL_open_stream(DIG, filename, 0); - if(mp3Stream[nStream]) { - AIL_set_stream_loop_count( - mp3Stream[nStream], 1); - AIL_set_stream_ms_position( - mp3Stream[nStream], position); - AIL_pause_stream(mp3Stream[nStream], 0); - return true; - } - - return false; + goto PLAY_STREAMEDTRACK; } } - + if ( e->pLinkPath != NULL ) mp3Stream[nStream] = AIL_open_stream(DIG, e->pLinkPath, 0); else @@ -2086,14 +2064,17 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) return true; } +NEXT_MP3TRACK: _bIsMp3Active = false; - - } while(++i < nNumMP3s); - + + } while ( ++i < nNumMP3s ); + position = 0; nFile = 0; + goto PLAY_STREAMEDTRACK; } +PLAY_STREAMEDTRACK: strcpy(filename, m_szCDRomRootPath); strcat(filename, StreamedNameTable[nFile]); diff --git a/src/control/Darkel.h b/src/control/Darkel.h index 14529c63..b6092dcb 100644 --- a/src/control/Darkel.h +++ b/src/control/Darkel.h @@ -1,10 +1,9 @@ #pragma once - #include "ModelIndices.h" -#include "WeaponType.h" class CVehicle; class CPed; +enum eWeaponType; enum { diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index cedef63c..9d0959a8 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -1466,11 +1466,8 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta targetNode = FindNodeClosestToCoors(target, type, distLimit); else targetNode = forcedTargetNode; - if(targetNode < 0) { - *pNumNodes = 0; - if(pDist) *pDist = 100000.0f; - return; - } + if(targetNode < 0) + goto fail; // Find start int numPathsToTry; @@ -1489,28 +1486,19 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta numPathsToTry = 1; startObj = m_mapObjects[m_pathNodes[startNodeId].objectIndex]; } - if(numPathsToTry == 0) { - *pNumNodes = 0; - if(pDist) *pDist = 100000.0f; - return; - } + if(numPathsToTry == 0) + goto fail; if(startNodeId < 0){ // why only check node 0? - if(m_pathNodes[startObj->m_nodeIndices[type][0]].group != - m_pathNodes[targetNode].group) { - *pNumNodes = 0; - if(pDist) *pDist = 100000.0f; - return; - } + if(m_pathNodes[startObj->m_nodeIndices[type][0]].group != m_pathNodes[targetNode].group) + goto fail; }else{ - if(m_pathNodes[startNodeId].group != m_pathNodes[targetNode].group) { - *pNumNodes = 0; - if(pDist) *pDist = 100000.0f; - return; - } + if(m_pathNodes[startNodeId].group != m_pathNodes[targetNode].group) + goto fail; } + for(i = 0; i < 512; i++) m_searchNodes[i].next = nil; AddNodeToList(&m_pathNodes[targetNode], 0); @@ -1588,6 +1576,11 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta for(i = 0; i < numNodesToBeCleared; i++) apNodesToBeCleared[i]->distance = MAX_DIST; return; + +fail: + *pNumNodes = 0; + if(pDist) + *pDist = 100000.0f; } static CPathNode *pNodeList[32]; diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index 70fcbc32..096bb484 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -8,7 +8,7 @@ #include "Clock.h" #include "Weather.h" #include "Timecycle.h" -#include "PointLights.h" +#include "Pointlights.h" #include "Shadows.h" #include "Coronas.h" #include "SpecialFX.h" diff --git a/src/core/CrimeType.h b/src/core/CrimeType.h deleted file mode 100644 index 23f609eb..00000000 --- a/src/core/CrimeType.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -enum eCrimeType -{ - CRIME_NONE, - CRIME_POSSESSION_GUN, - CRIME_HIT_PED, - CRIME_HIT_COP, - CRIME_SHOOT_PED, - CRIME_SHOOT_COP, - CRIME_STEAL_CAR, - CRIME_RUN_REDLIGHT, - CRIME_RECKLESS_DRIVING, - CRIME_SPEEDING, - CRIME_RUNOVER_PED, - CRIME_RUNOVER_COP, - CRIME_SHOOT_HELI, - CRIME_PED_BURNED, - CRIME_COP_BURNED, - CRIME_VEHICLE_BURNED, - CRIME_DESTROYED_CESSNA, - NUM_CRIME_TYPES -}; \ No newline at end of file diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 8b2f8604..7ccf78d0 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -72,7 +72,7 @@ #include "Streaming.h" #include "SurfaceTable.h" #include "TempColModels.h" -#include "Timecycle.h" +#include "TimeCycle.h" #include "TrafficLights.h" #include "Train.h" #include "TxdStore.h" diff --git a/src/core/General.h b/src/core/General.h index 103bafde..77828854 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -124,7 +124,7 @@ public: static bool faststricmp(const char *str1, const char *str2) { for (; *str1; str1++, str2++) { -#if 1 +#if MUCH_SLOWER if (toupper(*str1) != toupper(*str2)) #else if (__ascii_toupper(*str1) != __ascii_toupper(*str2)) diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 49affbbe..86aff05e 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -6,7 +6,7 @@ #include "common.h" #ifdef XINPUT -#include +#include #pragma comment( lib, "Xinput9_1_0.lib" ) #endif diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 3852f540..cfa0cea4 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -180,7 +180,7 @@ CPlayerInfo::MakePlayerSafe(bool toggle) m_pPed->bExplosionProof = true; m_pPed->m_bCanBeDamaged = false; ((CPlayerPed*)m_pPed)->ClearAdrenaline(); - CancelPlayerEnteringCars(nil); + CancelPlayerEnteringCars(false); gFireManager.ExtinguishPoint(GetPos(), 4000.0f); CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f); CProjectileInfo::RemoveAllProjectiles(); diff --git a/src/core/Wanted.h b/src/core/Wanted.h index c5e9d388..afeec8b0 100644 --- a/src/core/Wanted.h +++ b/src/core/Wanted.h @@ -3,7 +3,27 @@ class CEntity; class CCopPed; -#include "CrimeType.h" +enum eCrimeType +{ + CRIME_NONE, + CRIME_POSSESSION_GUN, + CRIME_HIT_PED, + CRIME_HIT_COP, + CRIME_SHOOT_PED, + CRIME_SHOOT_COP, + CRIME_STEAL_CAR, + CRIME_RUN_REDLIGHT, + CRIME_RECKLESS_DRIVING, + CRIME_SPEEDING, + CRIME_RUNOVER_PED, + CRIME_RUNOVER_COP, + CRIME_SHOOT_HELI, + CRIME_PED_BURNED, + CRIME_COP_BURNED, + CRIME_VEHICLE_BURNED, + CRIME_DESTROYED_CESSNA, + NUM_CRIME_TYPES +}; class CCrimeBeingQd { diff --git a/src/core/common.h b/src/core/common.h index e10b222c..454b848a 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -12,7 +12,7 @@ #include #ifdef WITHWINDOWS -#include +#include #endif #ifdef WITHD3D @@ -62,7 +62,7 @@ typedef int64_t int64; typedef uint16_t wchar; #ifndef nil -#define nil NULL +#define nil nullptr #endif #include "config.h" diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h index 7e4aebb7..9e28d272 100644 --- a/src/objects/ParticleObject.h +++ b/src/objects/ParticleObject.h @@ -1,7 +1,6 @@ #pragma once #include "Placeable.h" #include "AudioManager.h" -#include "ParticleType.h" #define MAX_PARTICLEOBJECTS 100 #define MAX_AUDIOHYDRANTS 8 @@ -38,6 +37,7 @@ enum eParticleObjectState POBJECTSTATE_FREE, }; +enum tParticleType; class CParticle; class CParticleObject : public CPlaceable diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 41f0ffb2..fc53e4bc 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -1,13 +1,12 @@ #pragma once -#include "AnimManager.h" -#include "CrimeType.h" -#include "EventList.h" -#include "PedIK.h" -#include "PedStats.h" #include "Physical.h" #include "Weapon.h" +#include "PedStats.h" +#include "PedIK.h" +#include "AnimManager.h" #include "WeaponInfo.h" +#include "EventList.h" #define FEET_OFFSET 1.04f #define CHECK_NEARBY_THINGS_MAX_DIST 15.0f @@ -18,6 +17,7 @@ class CObject; class CFire; struct AnimBlendFrameData; class CAnimBlendAssociation; +enum eCrimeType; struct PedAudioData { diff --git a/src/render/ParticleMgr.h b/src/render/ParticleMgr.h index 0b4091de..605e69fe 100644 --- a/src/render/ParticleMgr.h +++ b/src/render/ParticleMgr.h @@ -1,9 +1,83 @@ #pragma once -#include "ParticleType.h" - class CParticle; +enum tParticleType +{ + PARTICLE_SPARK = 0, + PARTICLE_SPARK_SMALL, + PARTICLE_WHEEL_DIRT, + PARTICLE_WHEEL_WATER, + PARTICLE_BLOOD, + PARTICLE_BLOOD_SMALL, + PARTICLE_BLOOD_SPURT, + PARTICLE_DEBRIS, + PARTICLE_DEBRIS2, + PARTICLE_WATER, + PARTICLE_FLAME, + PARTICLE_FIREBALL, + PARTICLE_GUNFLASH, + PARTICLE_GUNFLASH_NOANIM, + PARTICLE_GUNSMOKE, + PARTICLE_GUNSMOKE2, + PARTICLE_SMOKE, + PARTICLE_SMOKE_SLOWMOTION, + PARTICLE_GARAGEPAINT_SPRAY, + PARTICLE_SHARD, + PARTICLE_SPLASH, + PARTICLE_CARFLAME, + PARTICLE_STEAM, + PARTICLE_STEAM2, + PARTICLE_STEAM_NY, + PARTICLE_STEAM_NY_SLOWMOTION, + PARTICLE_ENGINE_STEAM, + PARTICLE_RAINDROP, + PARTICLE_RAINDROP_SMALL, + PARTICLE_RAIN_SPLASH, + PARTICLE_RAIN_SPLASH_BIGGROW, + PARTICLE_RAIN_SPLASHUP, + PARTICLE_WATERSPRAY, + PARTICLE_EXPLOSION_MEDIUM, + PARTICLE_EXPLOSION_LARGE, + PARTICLE_EXPLOSION_MFAST, + PARTICLE_EXPLOSION_LFAST, + PARTICLE_CAR_SPLASH, + PARTICLE_BOAT_SPLASH, + PARTICLE_BOAT_THRUSTJET, + PARTICLE_BOAT_WAKE, + PARTICLE_WATER_HYDRANT, + PARTICLE_WATER_CANNON, + PARTICLE_EXTINGUISH_STEAM, + PARTICLE_PED_SPLASH, + PARTICLE_PEDFOOT_DUST, + PARTICLE_HELI_DUST, + PARTICLE_HELI_ATTACK, + PARTICLE_ENGINE_SMOKE, + PARTICLE_ENGINE_SMOKE2, + PARTICLE_CARFLAME_SMOKE, + PARTICLE_FIREBALL_SMOKE, + PARTICLE_PAINT_SMOKE, + PARTICLE_TREE_LEAVES, + PARTICLE_CARCOLLISION_DUST, + PARTICLE_CAR_DEBRIS, + PARTICLE_HELI_DEBRIS, + PARTICLE_EXHAUST_FUMES, + PARTICLE_RUBBER_SMOKE, + PARTICLE_BURNINGRUBBER_SMOKE, + PARTICLE_BULLETHIT_SMOKE, + PARTICLE_GUNSHELL_FIRST, + PARTICLE_GUNSHELL, + PARTICLE_GUNSHELL_BUMP1, + PARTICLE_GUNSHELL_BUMP2, + PARTICLE_TEST, + PARTICLE_BIRD_FRONT, + PARTICLE_RAINDROP_2D, + + MAX_PARTICLES, + PARTICLE_FIRST = PARTICLE_SPARK, + PARTICLE_LAST = PARTICLE_RAINDROP_2D +}; + enum { ZCHECK_FIRST = BIT(0), diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 76fe0870..265ffddb 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -3,7 +3,53 @@ #define DRIVEBYAUTOAIMING_MAXDIST (2.5f) #define DOOMAUTOAIMING_MAXDIST (9000.0f) -#include "WeaponType.h" +enum eWeaponType +{ + WEAPONTYPE_UNARMED, + WEAPONTYPE_BASEBALLBAT, + WEAPONTYPE_COLT45, + WEAPONTYPE_UZI, + WEAPONTYPE_SHOTGUN, + WEAPONTYPE_AK47, + WEAPONTYPE_M16, + WEAPONTYPE_SNIPERRIFLE, + WEAPONTYPE_ROCKETLAUNCHER, + WEAPONTYPE_FLAMETHROWER, + WEAPONTYPE_MOLOTOV, + WEAPONTYPE_GRENADE, + WEAPONTYPE_DETONATOR, + WEAPONTYPE_HELICANNON, + WEAPONTYPE_LAST_WEAPONTYPE, + WEAPONTYPE_ARMOUR, + WEAPONTYPE_RAMMEDBYCAR, + WEAPONTYPE_RUNOVERBYCAR, + WEAPONTYPE_EXPLOSION, + WEAPONTYPE_UZI_DRIVEBY, + WEAPONTYPE_DROWNING, + WEAPONTYPE_FALL, + WEAPONTYPE_UNIDENTIFIED, + + WEAPONTYPE_TOTALWEAPONS = WEAPONTYPE_LAST_WEAPONTYPE, + WEAPONTYPE_TOTAL_INVENTORY_WEAPONS = 13, +}; + +enum eWeaponFire { + WEAPON_FIRE_MELEE, + WEAPON_FIRE_INSTANT_HIT, + WEAPON_FIRE_PROJECTILE, + WEAPON_FIRE_AREA_EFFECT, + WEAPON_FIRE_USE +}; + +// Taken from MTA SA, seems it's unchanged +enum eWeaponState +{ + WEAPONSTATE_READY, + WEAPONSTATE_FIRING, + WEAPONSTATE_RELOADING, + WEAPONSTATE_OUT_OF_AMMO, + WEAPONSTATE_MELEE_MADECONTACT +}; class CEntity; class CPhysical; From 89688843ece0f6c9968f0f8b9b644d707b96d34a Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 18 Apr 2020 13:56:21 +0300 Subject: [PATCH 074/123] bug fixes --- src/audio/MusicManager.cpp | 6 ++++++ src/core/Frontend.cpp | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index 2cc1d929..01b7df56 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -51,6 +51,12 @@ cMusicManager::PlayerInCar() if(State == PED_DRAG_FROM_CAR || State == PED_EXIT_CAR || State == PED_ARRESTED) return false; + if (!FindPlayerVehicle()) + return true; + + if (FindPlayerVehicle()->m_status == STATUS_WRECKED) + return false; + switch(FindPlayerVehicle()->m_modelIndex) { case MI_FIRETRUCK: case MI_AMBULAN: diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index e9282c44..4dab8ae4 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5470,7 +5470,8 @@ CMenuManager::ConstructStatLine(int rowIdx) if (player.m_nTotalPackages != 0) packagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages; - STAT_LINE("PERPIC", &packagesPercent, 0, &(nTemp = 100)); + int nPackagesPercent = packagesPercent; + STAT_LINE("PERPIC", &nPackagesPercent, 0, &(nTemp = 100)); STAT_LINE("NOUNIF", &CStats::TotalNumberOfUniqueJumps, 0, &CStats::NumberOfUniqueJumpsFound); STAT_LINE("DAYSPS", &CStats::DaysPassed, false, nil); if (CGame::nastyGame) { From 444d6462c5dadc976f8f0f3c2f649888c21bf4d9 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Apr 2020 14:20:49 +0300 Subject: [PATCH 075/123] premake cleanup --- premake5.lua | 51 ++++++++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/premake5.lua b/premake5.lua index ce637640..6037b01c 100644 --- a/premake5.lua +++ b/premake5.lua @@ -60,7 +60,6 @@ workspace "re3" filter {} filter "configurations:DebugRW or ReleaseRW" - defines { "RWLIBS" } includedirs { "rwsdk/include/d3d8" } libdirs { "rwsdk/lib/d3d8/release" } links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp" } @@ -102,39 +101,29 @@ project "re3" characterset ("MBCS") linkoptions "/SAFESEH:NO" - prebuildcommands { "cd \"../librw\" && premake5 " .. _ACTION .. " && msbuild \"build/librw.sln\" /property:Configuration=%{cfg.longname} /property:Platform=\"win-x86-d3d9\"" } - - filter "configurations:Debug" - defines { "DEBUG", "LIBRW", "RW_D3D9" } - staticruntime "off" - symbols "Full" - setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") - - filter "configurations:Release" - defines { "NDEBUG", "LIBRW", "RW_D3D9" } + setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") + symbols "Full" + staticruntime "off" + + filter "configurations:not *RW" + prebuildcommands { "cd \"../librw\" && premake5 " .. _ACTION .. " && msbuild \"build/librw.sln\" /property:Configuration=%{cfg.longname} /property:Platform=\"win-x86-d3d9\"" } + defines { "LIBRW", "RW_D3D9" } + + filter "configurations:*RW" + defines { "RWLIBS" } + staticruntime "on" + linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text" + + filter "configurations:Debug*" + defines { "DEBUG" } + + filter "configurations:Release*" + defines { "NDEBUG" } optimize "On" - staticruntime "off" - symbols "Full" - setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") + filter "configurations:ReleaseFH" - defines { "NDEBUG" } - symbols "Full" + prebuildcommands {} optimize "off" staticruntime "on" - setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") - - filter "configurations:DebugRW" - defines { "DEBUG" } - staticruntime "on" - symbols "On" - setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") - linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text" - - filter "configurations:ReleaseRW" - defines { "NDEBUG" } - optimize "On" - staticruntime "on" - setpaths("$(GTA_III_RE_DIR)/", "$(TargetFileName)", "") - linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text" From 522d14814f58e8a8ed9445c9c1a213aa9ca2cad2 Mon Sep 17 00:00:00 2001 From: gennariarmando Date: Sat, 18 Apr 2020 15:05:06 +0200 Subject: [PATCH 076/123] Changed extraOffset value. --- src/core/Frontend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index f4e0996b..a900d696 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -1127,7 +1127,7 @@ CMenuManager::Draw() int extraOffset = 0; if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_RADIO) - extraOffset = (int) 60.0f; + extraOffset = MENURADIO_ICON_SCALE; // There were many unused codes in here to calculate how much space will texts gonna take. From ffe5dce7f58b6eae5b2bcb6cb9e4d4c0d8a8f426 Mon Sep 17 00:00:00 2001 From: gennariarmando Date: Sat, 18 Apr 2020 18:13:47 +0200 Subject: [PATCH 077/123] Hide Vehicle/Zone name during Wasted/Busted... Fixed little mistake in my latest commit. --- src/core/Frontend.cpp | 8 +++++--- src/core/config.h | 1 + src/render/Hud.cpp | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index a900d696..eec143c3 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -305,9 +305,11 @@ ScaleAndCenterX(float x) } while(0) #define ProcessRadioIcon(sprite, x, y, radioId, hoverOpt) \ - sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); \ - if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \ - m_nHoverOption = hoverOpt; + do { \ + sprite.Draw(x, y, MENU_X(MENURADIO_ICON_SCALE), MENU_Y(MENURADIO_ICON_SCALE), radioId == m_PrefsRadioStation ? CRGBA(255, 255, 255, 255) : CRGBA(225, 0, 0, 170)); \ + if (CheckHover(x, x + MENU_X(MENURADIO_ICON_SCALE), y, y + MENU_Y(MENURADIO_ICON_SCALE))) \ + m_nHoverOption = hoverOpt; \ + } while (0) // --- Functions not in the game/inlined starts diff --git a/src/core/config.h b/src/core/config.h index ba684092..12e6ed69 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -208,6 +208,7 @@ enum Config { #define SCROLLABLE_STATS_PAGE // only draggable by mouse atm #define TRIANGLE_BACK_BUTTON // #define CIRCLE_BACK_BUTTON +#define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. // Script #define USE_DEBUG_SCRIPT_LOADER // makes game load main_freeroam.scm by default diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 03ffe59a..fc399741 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -473,7 +473,12 @@ void CHud::Draw() break; } + +#ifndef HUD_ENHANCEMENTS if (!m_Message[0]) { +#else + if (!m_Message[0] && !m_BigMessage[2][0]) { // Hide zone name if wasted/busted text is displaying +#endif m_ZoneNameTimer += CTimer::GetTimeStepInMilliseconds(); CFont::SetJustifyOff(); CFont::SetPropOn(); @@ -563,7 +568,11 @@ void CHud::Draw() break; } +#ifndef HUD_ENHANCEMENTS if (!m_Message[0]) { +#else + if (!m_Message[0] && !m_BigMessage[2][0]) { // Hide vehicle name if wasted/busted text is displaying +#endif m_VehicleNameTimer += CTimer::GetTimeStepInMilliseconds(); CFont::SetJustifyOff(); CFont::SetPropOn(); From 2f63e5e751dc268a6778e076098320dac9a03699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 18 Apr 2020 21:28:49 +0300 Subject: [PATCH 078/123] Vc ped ports and Frontend fixes --- src/core/Frontend.cpp | 10 ++++------ src/peds/Ped.cpp | 24 +++++++++++++++++++----- src/vehicles/Vehicle.cpp | 4 ++++ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index a900d696..e4f8ac96 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -118,7 +118,6 @@ const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255); const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color #endif -const float menuXYpadding = MENUACTION_POS_Y; // TODO this is non-existant, remove it float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; @@ -231,8 +230,7 @@ ScaleAndCenterX(float x) else { if (x > DEFAULT_SCREEN_WIDTH / 2) { return SCREEN_WIDTH / 2 + SCREEN_SCALE_X(x - DEFAULT_SCREEN_WIDTH / 2); - } - else { + } else { return SCREEN_WIDTH / 2 - SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH / 2 - x); } } @@ -1257,7 +1255,8 @@ CMenuManager::Draw() break; } - nextYToUse += lineHeight * CFont::GetNumberLines(menuXYpadding, nextYToUse, leftText); + // 60.0 is silly + nextYToUse += lineHeight * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText); // Radio icons if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) { @@ -3385,8 +3384,7 @@ CMenuManager::Process(void) DMAudio.SetEffectsFadeVol(0); DMAudio.SetMusicFadeVol(0); DMAudio.ResetTimers(CTimer::GetTimeInMilliseconds()); - } - else + } else SaveLoadFileError_SetUpErrorScreen(); } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 4737051e..1f1930d7 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -3038,7 +3038,6 @@ CPed::QuitEnteringCar(void) if (animAssoc) { animAssoc->blendDelta = -4.0f; animAssoc->flags |= ASSOC_DELETEFADEDOUT; - animAssoc = m_pVehicleAnim; animAssoc->flags &= ~ASSOC_RUNNING; } } else @@ -3047,7 +3046,11 @@ CPed::QuitEnteringCar(void) m_pVehicleAnim = nil; if (veh) { +#ifdef VC_PED_PORTS + if (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE) +#else if (veh->AutoPilot.m_nCruiseSpeed == 0) +#endif veh->AutoPilot.m_nCruiseSpeed = 17; } } @@ -4146,7 +4149,7 @@ CPed::SetGetUp(void) CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition()); if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE || collidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE - && ((CTimer::GetFrameCounter() + m_randomSeed % 256 + 5) % 8 + && ((uint8)(CTimer::GetFrameCounter() + m_randomSeed + 5) % 8 || CCollision::ProcessColModels(GetMatrix(), *CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(), collidingVeh->GetMatrix(), *CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(), aTempPedColPts, nil, nil) > 0)) { @@ -10729,7 +10732,10 @@ CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg) ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped); } } else { - ped->QuitEnteringCar(); +#ifdef VC_PED_PORTS + if (ped->m_nPedState != PED_DRIVING) +#endif + ped->QuitEnteringCar(); } } @@ -11014,7 +11020,10 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg) return; if (!ped->EnteringCar()) { - ped->QuitEnteringCar(); +#ifdef VC_PED_PORTS + if(ped->m_nPedState != PED_DRIVING) +#endif + ped->QuitEnteringCar(); return; } @@ -13733,7 +13742,12 @@ CPed::ProcessObjective(void) // fall through case OBJECTIVE_LEAVE_VEHICLE: if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { - if (InVehicle()) { + if (InVehicle() +#ifdef VC_PED_PORTS + && (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() + || bBusJacked) +#endif + ) { if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN && (m_nPedType != PEDTYPE_COP #ifdef VC_PED_PORTS diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 48c836f8..bc47b486 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -787,6 +787,10 @@ CVehicle::CanPedExitCar(void) { CVector up = GetUp(); if(up.z > 0.1f || up.z < -0.1f){ +#ifdef VC_PED_PORTS + if (IsBoat()) + return true; +#endif // can't exit when car is moving too fast if(m_vecMoveSpeed.MagnitudeSqr() > 0.005f) return false; From 4f58ef3e46718b4b8c750f38e729d103e7249a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 18 Apr 2020 21:33:58 +0300 Subject: [PATCH 079/123] submodule update --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index bc9cb506..e6c7d910 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit bc9cb506ecd5abb869292860ed287c1b029b30cc +Subproject commit e6c7d910ffc32bc059c4e750a797fde51ee29fd9 From 5320bf7964c6a5a0731a4aabf5053344e36d58a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 18 Apr 2020 21:44:07 +0300 Subject: [PATCH 080/123] RpClumpRemoveAtomic update --- src/fakerw/fake.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 03df55e2..3977007f 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -634,7 +634,7 @@ RpClump *RpClumpForAllLights(RpClump * clump, RpLightCallBack callback, void *pD RpClump *RpClumpForAllCameras(RpClump * clump, RwCameraCallBack callback, void *pData); //RpClump *RpClumpCreateSpace(const RwV3d * position, RwReal radius); RpClump *RpClumpRender(RpClump * clump) { clump->render(); return clump; } -RpClump *RpClumpRemoveAtomic(RpClump * clump, RpAtomic * atomic) { atomic->removeFromClump(); return clump; } +RpClump *RpClumpRemoveAtomic(RpClump * clump, RpAtomic * atomic) { clump->removeAtomic(atomic); return clump; } RpClump *RpClumpAddAtomic(RpClump * clump, RpAtomic * atomic) { clump->addAtomic(atomic); return clump; } //RpClump *RpClumpRemoveLight(RpClump * clump, RpLight * light); //RpClump *RpClumpAddLight(RpClump * clump, RpLight * light); From 9bfcaff84976b2af7242f846c782287e9bacf851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 18 Apr 2020 22:56:49 +0300 Subject: [PATCH 081/123] slider fix --- src/core/Frontend.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 0966b2a2..6fe06d96 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -287,7 +287,7 @@ ScaleAndCenterX(float x) #define ProcessSlider(value, increaseAction, decreaseAction, hoverStartX, hoverEndX) \ do { \ - lastActiveBarX = DisplaySlider(SCREEN_STRETCH_FROM_RIGHT(MENUSLIDER_X + columnWidth), MENU_Y(bitAboveNextItemY), MENU_Y(smallestSliderBar), MENU_Y(usableLineHeight), MENU_X(MENUSLIDER_UNK), value); \ + lastActiveBarX = DisplaySlider(MENU_X_RIGHT_ALIGNED(MENUSLIDER_X + columnWidth), MENU_Y(bitAboveNextItemY), MENU_Y(smallestSliderBar), MENU_Y(usableLineHeight), MENU_X(MENUSLIDER_UNK), value); \ if (i != m_nCurrOption || !itemsAreSelectable) \ break; \ \ @@ -298,7 +298,7 @@ ScaleAndCenterX(float x) break; \ \ m_nHoverOption = increaseAction; \ - if (m_nMousePosX < SCREEN_STRETCH_FROM_RIGHT(MENUSLIDER_X + columnWidth)) \ + if (m_nMousePosX < MENU_X_RIGHT_ALIGNED(MENUSLIDER_X + columnWidth)) \ m_nHoverOption = HOVEROPTION_NOT_HOVERING; \ } while(0) @@ -1237,7 +1237,6 @@ CMenuManager::Draw() } // Sliders - // We stretch slider start X here(like original code), because it will always be center of screen int lastActiveBarX; switch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) { case MENUACTION_BRIGHTNESS: From c4cd45d47c01d89bab28f196f03ed9cb1978005b Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 18 Apr 2020 23:50:37 +0300 Subject: [PATCH 082/123] replays bug fix --- src/control/Phones.cpp | 7 ++ src/control/Replay.cpp | 33 +++++++--- src/control/Replay.h | 47 +++++++------- src/core/Camera.cpp | 8 +++ src/core/PlayerInfo.cpp | 8 +++ src/core/References.cpp | 9 +++ src/core/Streaming.cpp | 15 ++++- src/core/User.cpp | 5 ++ src/core/World.cpp | 15 +++++ src/peds/PlayerPed.cpp | 1 + src/render/Shadows.cpp | 7 ++ src/vehicles/Heli.cpp | 139 ++++++++++++++++++++++------------------ 12 files changed, 198 insertions(+), 96 deletions(-) diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index 7fdc81c5..15e9f9f1 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -12,6 +12,9 @@ #include "AudioScriptObject.h" #include "RpAnimBlend.h" #include "AnimBlendAssociation.h" +#ifdef FIX_BUGS +#include "Replay.h" +#endif CPhoneInfo gPhoneInfo; @@ -45,6 +48,10 @@ isPhoneAvailable(int m_phoneId) void CPhoneInfo::Update(void) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif CPlayerPed *player = FindPlayerPed(); CPlayerInfo *playerInfo = &CWorld::Players[CWorld::PlayerInFocus]; if (bDisplayingPhoneMessage && CTimer::GetTimeInMilliseconds() > PhoneEnableControlsTimer) { diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index c67e7cbf..466aa25e 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -68,8 +68,8 @@ bool CReplay::bReplayEnabled = true; uint32 CReplay::SlowMotion; uint32 CReplay::FramesActiveLookAroundCam; bool CReplay::bDoLoadSceneWhenDone; -CPtrList CReplay::WorldPtrList; -CPtrList CReplay::BigBuildingPtrList; +CPtrNode* CReplay::WorldPtrList; +CPtrNode* CReplay::BigBuildingPtrList; CWanted CReplay::PlayerWanted; CPlayerInfo CReplay::PlayerInfo; uint32 CReplay::Time1; @@ -101,6 +101,9 @@ bool CReplay::bPlayerInRCBuggy; float CReplay::fDistanceLookAroundCam; float CReplay::fBetaAngleLookAroundCam; float CReplay::fAlphaAngleLookAroundCam; +#ifdef FIX_BUGS +int CReplay::nHandleOfPlayerPed[NUMPLAYERS]; +#endif static void(*CBArray[])(CAnimBlendAssociation*, void*) = { @@ -275,7 +278,7 @@ void CReplay::RecordThisFrame(void) continue; memory_required += sizeof(tBulletTracePacket); } - memory_required += sizeof(tEndOfFramePacket); + memory_required += sizeof(tEndOfFramePacket) + 1; // 1 for Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END; if (Record.m_nOffset + memory_required > REPLAYBUFFERSIZE) { Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END; BufferStatus[Record.m_bSlot] = REPLAYBUFFER_PLAYBACK; @@ -1108,6 +1111,10 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca void CReplay::StoreStuffInMem(void) { +#ifdef FIX_BUGS + for (int i = 0; i < NUMPLAYERS; i++) + nHandleOfPlayerPed[i] = CPools::GetPedPool()->GetIndex(CWorld::Players[i].m_pPed); +#endif CPools::GetVehiclePool()->Store(pBuf0, pBuf1); CPools::GetPedPool()->Store(pBuf2, pBuf3); CPools::GetObjectPool()->Store(pBuf4, pBuf5); @@ -1116,8 +1123,8 @@ void CReplay::StoreStuffInMem(void) CPools::GetDummyPool()->Store(pBuf10, pBuf11); pWorld1 = new uint8[sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y]; memcpy(pWorld1, CWorld::GetSector(0, 0), NUMSECTORS_X * NUMSECTORS_Y * sizeof(CSector)); - WorldPtrList = CWorld::GetMovingEntityList(); - BigBuildingPtrList = CWorld::GetBigBuildingList(LEVEL_NONE); + WorldPtrList = CWorld::GetMovingEntityList().first; // why + BigBuildingPtrList = CWorld::GetBigBuildingList(LEVEL_NONE).first; pPickups = new uint8[sizeof(CPickup) * NUMPICKUPS]; memcpy(pPickups, CPickups::aPickUps, NUMPICKUPS * sizeof(CPickup)); pReferences = new uint8[(sizeof(CReference) * NUMREFERENCES)]; @@ -1162,8 +1169,8 @@ void CReplay::RestoreStuffFromMem(void) memcpy(CWorld::GetSector(0, 0), pWorld1, sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y); delete[] pWorld1; pWorld1 = nil; - CWorld::GetMovingEntityList() = WorldPtrList; - CWorld::GetBigBuildingList(LEVEL_NONE) = BigBuildingPtrList; + CWorld::GetMovingEntityList().first = WorldPtrList; + CWorld::GetBigBuildingList(LEVEL_NONE).first = BigBuildingPtrList; memcpy(CPickups::aPickUps, pPickups, sizeof(CPickup) * NUMPICKUPS); delete[] pPickups; pPickups = nil; @@ -1178,6 +1185,14 @@ void CReplay::RestoreStuffFromMem(void) memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(sRadarTrace) * NUMRADARBLIPS); delete[] pRadarBlips; pRadarBlips = nil; +#ifdef FIX_BUGS + for (int i = 0; i < NUMPLAYERS; i++) { + CPlayerPed* pPlayerPed = (CPlayerPed*)CPools::GetPedPool()->GetAt(nHandleOfPlayerPed[i]); + assert(pPlayerPed); + CWorld::Players[i].m_pPed = pPlayerPed; + pPlayerPed->RegisterReference((CEntity**)&CWorld::Players[i].m_pPed); + } +#endif FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted); CWorld::Players[0] = PlayerInfo; int i = CPools::GetPedPool()->GetSize(); @@ -1393,8 +1408,8 @@ void CReplay::SaveReplayToHD(void) for (first = (current + 1) % NUM_REPLAYBUFFERS; ; first = (first + 1) % NUM_REPLAYBUFFERS) if (BufferStatus[first] == REPLAYBUFFER_RECORD || BufferStatus[first] == REPLAYBUFFER_PLAYBACK) break; - for(int i = first;; i = (i + 1) % NUM_REPLAYBUFFERS){ - CFileMgr::Write(fw, (char*)Buffers[first], sizeof(Buffers[first])); + for(int i = first; ; i = (i + 1) % NUM_REPLAYBUFFERS){ + CFileMgr::Write(fw, (char*)Buffers[i], sizeof(Buffers[i])); if (BufferStatus[i] == REPLAYBUFFER_RECORD) break; } diff --git a/src/control/Replay.h b/src/control/Replay.h index 6f6c2a91..bf70a28a 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -192,7 +192,7 @@ class CReplay int8 velocityX; int8 velocityY; int8 velocityZ; - union{ + union { int8 car_gun; int8 wheel_state; }; @@ -208,25 +208,25 @@ private: static uint8 Mode; static CAddressInReplayBuffer Record; static CAddressInReplayBuffer Playback; - static uint8 *pBuf0; - static CAutomobile *pBuf1; - static uint8 *pBuf2; - static CPlayerPed *pBuf3; - static uint8 *pBuf4; - static CCutsceneHead *pBuf5; - static uint8 *pBuf6; - static CPtrNode *pBuf7; - static uint8 *pBuf8; - static CEntryInfoNode *pBuf9; - static uint8 *pBuf10; - static CDummyPed *pBuf11; - static uint8 *pRadarBlips; - static uint8 *pStoredCam; - static uint8 *pWorld1; - static CReference *pEmptyReferences; - static CStoredDetailedAnimationState *pPedAnims; - static uint8 *pPickups; - static uint8 *pReferences; + static uint8* pBuf0; + static CAutomobile* pBuf1; + static uint8* pBuf2; + static CPlayerPed* pBuf3; + static uint8* pBuf4; + static CCutsceneHead* pBuf5; + static uint8* pBuf6; + static CPtrNode* pBuf7; + static uint8* pBuf8; + static CEntryInfoNode* pBuf9; + static uint8* pBuf10; + static CDummyPed* pBuf11; + static uint8* pRadarBlips; + static uint8* pStoredCam; + static uint8* pWorld1; + static CReference* pEmptyReferences; + static CStoredDetailedAnimationState* pPedAnims; + static uint8* pPickups; + static uint8* pReferences; static uint8 BufferStatus[NUM_REPLAYBUFFERS]; static uint8 Buffers[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE]; static bool bPlayingBackFromFile; @@ -234,8 +234,8 @@ private: static uint32 SlowMotion; static uint32 FramesActiveLookAroundCam; static bool bDoLoadSceneWhenDone; - static CPtrList WorldPtrList; - static CPtrList BigBuildingPtrList; + static CPtrNode* WorldPtrList; + static CPtrNode* BigBuildingPtrList; static CWanted PlayerWanted; static CPlayerInfo PlayerInfo; static uint32 Time1; @@ -267,6 +267,9 @@ private: static float fDistanceLookAroundCam; static float fAlphaAngleLookAroundCam; static float fBetaAngleLookAroundCam; +#ifdef FIX_BUGS + static int nHandleOfPlayerPed[NUMPLAYERS]; +#endif public: static void Init(void); diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index f1445d2e..6747ebf5 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -2490,6 +2490,10 @@ CCamera::TryToStartNewCamMode(int obbeMode) TakeControl(FindPlayerEntity(), CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE); return true; case OBBE_COPCAR: +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return false; +#endif if(FindPlayerPed()->m_pWanted->m_nWantedLevel < 1) return false; if(FindPlayerVehicle() == nil) @@ -2514,6 +2518,10 @@ CCamera::TryToStartNewCamMode(int obbeMode) } return false; case OBBE_COPCAR_WHEEL: +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return false; +#endif if(FindPlayerPed()->m_pWanted->m_nWantedLevel < 1) return false; if(FindPlayerVehicle() == nil) diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index cfa0cea4..1c641be3 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -41,6 +41,10 @@ CPlayerInfo::SetPlayerSkin(char *skin) CVector& CPlayerInfo::GetPos() { +#ifdef FIX_BUGS + if (!m_pPed) + return TheCamera.GetPosition(); +#endif if (m_pPed->InVehicle()) return m_pPed->m_pMyVehicle->GetPosition(); return m_pPed->GetPosition(); @@ -342,6 +346,10 @@ CPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, void CPlayerInfo::Process(void) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif // Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode. bool startTaxiTimer = true; if (m_bUnusedTaxiThing && m_pPed->bInVehicle) { diff --git a/src/core/References.cpp b/src/core/References.cpp index 3eb2eaf3..52abbc3e 100644 --- a/src/core/References.cpp +++ b/src/core/References.cpp @@ -26,8 +26,17 @@ CReferences::RemoveReferencesToPlayer(void) { if(FindPlayerVehicle()) FindPlayerVehicle()->ResolveReferences(); +#ifdef FIX_BUGS + if (FindPlayerPed()) { + CPlayerPed* pPlayerPed = FindPlayerPed(); + FindPlayerPed()->ResolveReferences(); + CWorld::Players[CWorld::PlayerInFocus].m_pPed = pPlayerPed; + pPlayerPed->RegisterReference((CEntity**)&CWorld::Players[CWorld::PlayerInFocus].m_pPed); + } +#else if(FindPlayerPed()) FindPlayerPed()->ResolveReferences(); +#endif } void diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 039377f4..dae83d89 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -28,6 +28,9 @@ #include "CutsceneMgr.h" #include "CdStream.h" #include "Streaming.h" +#ifdef FIX_BUGS +#include "Replay.h" +#endif #include "main.h" bool CStreaming::ms_disableStreaming; @@ -280,7 +283,11 @@ CStreaming::Update(void) !requestedSubway && !CGame::playingIntro && ms_numModelsRequested < 5 && - !CRenderer::m_loadingPriority){ + !CRenderer::m_loadingPriority +#ifdef FIX_BUGS + && !CReplay::IsPlayingBack() +#endif + ){ StreamVehiclesAndPeds(); StreamZoneModels(FindPlayerCoors()); } @@ -1248,7 +1255,11 @@ CStreaming::StreamVehiclesAndPeds(void) static int modelQualityClass = 0; if(CRecordDataForGame::IsRecording() || - CRecordDataForGame::IsPlayingBack()) + CRecordDataForGame::IsPlayingBack() +#ifdef FIX_BUGS + || CReplay::IsPlayingBack() +#endif + ) return; if(FindPlayerPed()->m_pWanted->AreSwatRequired()){ diff --git a/src/core/User.cpp b/src/core/User.cpp index 36f07cbd..50eb7d9d 100644 --- a/src/core/User.cpp +++ b/src/core/User.cpp @@ -3,6 +3,7 @@ #include "Hud.h" #include "PlayerPed.h" +#include "Replay.h" #include "Text.h" #include "User.h" #include "Vehicle.h" @@ -115,6 +116,10 @@ CUserDisplay::Init() void CUserDisplay::Process() { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif PlaceName.Process(); OnscnTimer.Process(); Pager.Process(); diff --git a/src/core/World.cpp b/src/core/World.cpp index eacb3404..7ef43593 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1386,6 +1386,10 @@ FindPlayerEntity(void) CVector FindPlayerCoors(void) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return TheCamera.GetPosition(); +#endif CPlayerPed *ped = FindPlayerPed(); if(ped->InVehicle()) return ped->m_pMyVehicle->GetPosition(); @@ -1396,6 +1400,11 @@ FindPlayerCoors(void) CVector & FindPlayerSpeed(void) { +#ifdef FIX_BUGS + static CVector vecTmpVector(0.0f, 0.0f, 0.0f); + if (CReplay::IsPlayingBack()) + return vecTmpVector; +#endif CPlayerPed *ped = FindPlayerPed(); if(ped->InVehicle()) return ped->m_pMyVehicle->m_vecMoveSpeed; @@ -1406,6 +1415,9 @@ FindPlayerSpeed(void) CVector & FindPlayerCentreOfWorld(int32 player) { +#ifdef FIX_BUGS + if(CReplay::IsPlayingBack()) return TheCamera.GetPosition(); +#endif if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition(); if(CWorld::Players[player].m_pRemoteVehicle) return CWorld::Players[player].m_pRemoteVehicle->GetPosition(); if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition(); @@ -1415,6 +1427,9 @@ FindPlayerCentreOfWorld(int32 player) CVector & FindPlayerCentreOfWorld_NoSniperShift(void) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) return TheCamera.GetPosition(); +#endif if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition(); if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition(); diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 0a0fe6a3..c8e24e48 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -135,6 +135,7 @@ CPlayerPed::SetupPlayerPed(int32 index) { CPlayerPed *player = new CPlayerPed(); CWorld::Players[index].m_pPed = player; + player->RegisterReference((CEntity**)&CWorld::Players[index].m_pPed); player->SetOrientation(0.0f, 0.0f, 0.0f); diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 8685b93a..330f1b06 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -13,6 +13,9 @@ #include "Weather.h" #include "ModelIndices.h" #include "RenderBuffer.h" +#ifdef FIX_BUGS +#include "Replay.h" +#endif #include "PointLights.h" #include "SpecialFX.h" #include "Shadows.h" @@ -1609,6 +1612,10 @@ CShadows::CalcPedShadowValues(CVector vecLightDir, void CShadows::RenderExtraPlayerShadows(void) { +#ifdef FIX_BUGS + if (CReplay::IsPlayingBack()) + return; +#endif if ( CTimeCycle::GetLightShadowStrength() != 0 ) { CVehicle *pCar = FindPlayerVehicle(); diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 1f92b678..6a83a30e 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -24,6 +24,9 @@ #include "Object.h" #include "HandlingMgr.h" #include "Heli.h" +#ifdef FIX_BUGS +#include "Replay.h" +#endif enum { @@ -428,89 +431,95 @@ CHeli::ProcessControl(void) // Search light and shooting if(m_heliStatus == HELI_STATUS_FLY_AWAY || m_heliType == HELI_TYPE_CATALINA || CCullZones::PlayerNoRain()) m_fSearchLightIntensity = 0.0f; - else{ + else { // Update search light history once every 1000ms int timeDiff = CTimer::GetTimeInMilliseconds() - m_nSearchLightTimer; - while(timeDiff > 1000){ - for(i = 5; i > 0; i--){ - m_aSearchLightHistoryX[i] = m_aSearchLightHistoryX[i-1]; - m_aSearchLightHistoryY[i] = m_aSearchLightHistoryY[i-1]; + while (timeDiff > 1000) { + for (i = 5; i > 0; i--) { + m_aSearchLightHistoryX[i] = m_aSearchLightHistoryX[i - 1]; + m_aSearchLightHistoryY[i] = m_aSearchLightHistoryY[i - 1]; } - m_aSearchLightHistoryX[0] = FindPlayerCoors().x + FindPlayerSpeed().x*50.0f*(m_nHeliId+2); - m_aSearchLightHistoryY[0] = FindPlayerCoors().y + FindPlayerSpeed().y*50.0f*(m_nHeliId+2); + m_aSearchLightHistoryX[0] = FindPlayerCoors().x + FindPlayerSpeed().x * 50.0f * (m_nHeliId + 2); + m_aSearchLightHistoryY[0] = FindPlayerCoors().y + FindPlayerSpeed().y * 50.0f * (m_nHeliId + 2); timeDiff -= 1000; m_nSearchLightTimer += 1000; } assert(timeDiff <= 1000); - float f1 = timeDiff/1000.0f; + float f1 = timeDiff / 1000.0f; float f2 = 1.0f - f1; - m_fSearchLightX = m_aSearchLightHistoryX[m_nHeliId+2]*f2 + m_aSearchLightHistoryX[m_nHeliId+2-1]*f1; - m_fSearchLightY = m_aSearchLightHistoryY[m_nHeliId+2]*f2 + m_aSearchLightHistoryY[m_nHeliId+2-1]*f1; + m_fSearchLightX = m_aSearchLightHistoryX[m_nHeliId + 2] * f2 + m_aSearchLightHistoryX[m_nHeliId + 2 - 1] * f1; + m_fSearchLightY = m_aSearchLightHistoryY[m_nHeliId + 2] * f2 + m_aSearchLightHistoryY[m_nHeliId + 2 - 1] * f1; float searchLightDist = (CVector2D(m_fSearchLightX, m_fSearchLightY) - GetPosition()).Magnitude(); - if(searchLightDist > 60.0f) + if (searchLightDist > 60.0f) m_fSearchLightIntensity = 0.0f; - else if(searchLightDist < 40.0f) + else if (searchLightDist < 40.0f) m_fSearchLightIntensity = 1.0f; else - m_fSearchLightIntensity = 1.0f - (40.0f-searchLightDist)/40.0f; + m_fSearchLightIntensity = 1.0f - (40.0f - searchLightDist) / 40.0f; - if(m_fSearchLightIntensity < 0.9f || sq(FindPlayerCoors().x-m_fSearchLightX) + sq(FindPlayerCoors().y-m_fSearchLightY) > sq(7.0f)) + if (m_fSearchLightIntensity < 0.9f || sq(FindPlayerCoors().x - m_fSearchLightX) + sq(FindPlayerCoors().y - m_fSearchLightY) > sq(7.0f)) m_nShootTimer = CTimer::GetTimeInMilliseconds(); - else if(CTimer::GetTimeInMilliseconds() > m_nPoliceShoutTimer){ + else if (CTimer::GetTimeInMilliseconds() > m_nPoliceShoutTimer) { DMAudio.PlayOneShot(m_audioEntityId, SOUND_PED_HELI_PLAYER_FOUND, 0.0f); - m_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds() + 4500 + (CGeneral::GetRandomNumber()&0xFFF); + m_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds() + 4500 + (CGeneral::GetRandomNumber() & 0xFFF); } - - // Shoot - int shootTimeout; - if(m_heliType == HELI_TYPE_RANDOM){ - switch(FindPlayerPed()->m_pWanted->m_nWantedLevel){ - case 0: - case 1: - case 2: shootTimeout = 999999; break; - case 3: shootTimeout = 10000; break; - case 4: shootTimeout = 5000; break; - case 5: shootTimeout = 3500; break; - case 6: shootTimeout = 2000; break; - } - if(CCullZones::NoPolice()) - shootTimeout /= 2; - }else - shootTimeout = 1500; - - if(FindPlayerPed()->m_pWanted->IsIgnored()) - m_nShootTimer = CTimer::GetTimeInMilliseconds(); - else{ - // Check if line of sight is clear - if(CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout && - CTimer::GetPreviousTimeInMilliseconds() <= m_nShootTimer + shootTimeout){ - if(CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false)){ - if(m_heliStatus == HELI_STATUS_HOVER2) - m_heliStatus = HELI_STATUS_HOVER; - }else{ - m_nShootTimer = CTimer::GetTimeInMilliseconds(); - if(m_heliStatus == HELI_STATUS_HOVER) - m_heliStatus = HELI_STATUS_HOVER2; +#ifdef FIX_BUGS + if (!CReplay::IsPlayingBack()) +#endif + { + // Shoot + int shootTimeout; + if (m_heliType == HELI_TYPE_RANDOM) { + switch (FindPlayerPed()->m_pWanted->m_nWantedLevel) { + case 0: + case 1: + case 2: shootTimeout = 999999; break; + case 3: shootTimeout = 10000; break; + case 4: shootTimeout = 5000; break; + case 5: shootTimeout = 3500; break; + case 6: shootTimeout = 2000; break; } + if (CCullZones::NoPolice()) + shootTimeout /= 2; } + else + shootTimeout = 1500; - // Shoot! - if(CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout && - CTimer::GetTimeInMilliseconds() > m_nLastShotTime + 200){ - CVector shotTarget = FindPlayerCoors(); - // some inaccuracy - shotTarget.x += ((CGeneral::GetRandomNumber()&0xFF)-128)/50.0f; - shotTarget.y += ((CGeneral::GetRandomNumber()&0xFF)-128)/50.0f; - CVector direction = FindPlayerCoors() - GetPosition(); - direction.Normalise(); - shotTarget += 3.0f*direction; - CVector shotSource = GetPosition(); - shotSource += 3.0f*direction; - FireOneInstantHitRound(&shotSource, &shotTarget, 20); - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); - m_nLastShotTime = CTimer::GetTimeInMilliseconds(); + if (FindPlayerPed()->m_pWanted->IsIgnored()) + m_nShootTimer = CTimer::GetTimeInMilliseconds(); + else { + // Check if line of sight is clear + if (CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout && + CTimer::GetPreviousTimeInMilliseconds() <= m_nShootTimer + shootTimeout) { + if (CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false)) { + if (m_heliStatus == HELI_STATUS_HOVER2) + m_heliStatus = HELI_STATUS_HOVER; + } + else { + m_nShootTimer = CTimer::GetTimeInMilliseconds(); + if (m_heliStatus == HELI_STATUS_HOVER) + m_heliStatus = HELI_STATUS_HOVER2; + } + } + + // Shoot! + if (CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout && + CTimer::GetTimeInMilliseconds() > m_nLastShotTime + 200) { + CVector shotTarget = FindPlayerCoors(); + // some inaccuracy + shotTarget.x += ((CGeneral::GetRandomNumber() & 0xFF) - 128) / 50.0f; + shotTarget.y += ((CGeneral::GetRandomNumber() & 0xFF) - 128) / 50.0f; + CVector direction = FindPlayerCoors() - GetPosition(); + direction.Normalise(); + shotTarget += 3.0f * direction; + CVector shotSource = GetPosition(); + shotSource += 3.0f * direction; + FireOneInstantHitRound(&shotSource, &shotTarget, 20); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); + m_nLastShotTime = CTimer::GetTimeInMilliseconds(); + } } } } @@ -825,7 +834,11 @@ CHeli::UpdateHelis(void) int i, j; // Spawn new police helis - int numHelisRequired = FindPlayerPed()->m_pWanted->NumOfHelisRequired(); + int numHelisRequired = +#ifdef FIX_BUGS + CReplay::IsPlayingBack() ? 0 : +#endif + FindPlayerPed()->m_pWanted->NumOfHelisRequired(); if(CStreaming::HasModelLoaded(MI_CHOPPER) && CTimer::GetTimeInMilliseconds() > TestForNewRandomHelisTimer){ // Spawn a police heli TestForNewRandomHelisTimer = CTimer::GetTimeInMilliseconds() + 15000; From fce2e02444a056cc420be6b32844de039fbfafac Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sat, 18 Apr 2020 23:58:43 +0300 Subject: [PATCH 083/123] Fix savename buffer overflow --- src/save/GenericGameStorage.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 763f516a..5e483dc7 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -112,14 +112,22 @@ GenericSave(int file) // Save simple vars lastMissionPassed = TheText.Get(CStats::LastMissionPassedName); - if (*lastMissionPassed) { + if (lastMissionPassed[0] != '\0') { AsciiToUnicode("...'", suffix); +#ifdef FIX_BUGS + // fix buffer overflow + int len = UnicodeStrlen(lastMissionPassed); + if (len > ARRAY_SIZE(saveName)-1) + len = ARRAY_SIZE(saveName)-1; + memcpy(saveName, lastMissionPassed, sizeof(wchar) * len); +#else TextCopy(saveName, lastMissionPassed); int len = UnicodeStrlen(saveName); +#endif saveName[len] = '\0'; - if (len > 22) - TextCopy(saveName + 18, suffix); - saveName[23] = '\0'; + if (len > ARRAY_SIZE(saveName)-2) + TextCopy(&saveName[ARRAY_SIZE(saveName)-ARRAY_SIZE(suffix)], suffix); + saveName[ARRAY_SIZE(saveName)-1] = '\0'; } WriteDataToBufferPointer(buf, saveName); GetLocalTime(&saveTime); From bcc3a8b6c76ef5851af350ef4d839ef44d473f56 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 19 Apr 2020 01:20:14 +0300 Subject: [PATCH 084/123] missing ifded --- src/peds/PlayerPed.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index c8e24e48..962c83df 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -135,7 +135,9 @@ CPlayerPed::SetupPlayerPed(int32 index) { CPlayerPed *player = new CPlayerPed(); CWorld::Players[index].m_pPed = player; +#ifdef FIX_BUGS player->RegisterReference((CEntity**)&CWorld::Players[index].m_pPed); +#endif player->SetOrientation(0.0f, 0.0f, 0.0f); From 1ffc37735ed247eef1f20997a0136ef8d866ebad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sun, 19 Apr 2020 07:14:13 +0300 Subject: [PATCH 085/123] Struct cleanup, various fixes, enable PS2 rand --- src/audio/sampman.h | 2 +- src/control/Pickups.cpp | 8 ++++---- src/control/Script.cpp | 4 ++-- src/core/EventList.h | 3 +-- src/core/Game.h | 1 + src/core/PlayerInfo.cpp | 4 ++-- src/core/Pools.cpp | 8 ++++---- src/core/config.h | 2 +- src/entities/Entity.h | 36 ++++++++++++++++++------------------ src/entities/Physical.cpp | 12 ++++++------ src/entities/Physical.h | 6 +++--- src/objects/Object.cpp | 4 ++-- src/objects/Object.h | 3 +-- src/peds/CopPed.cpp | 4 +++- src/peds/CopPed.h | 5 +---- src/peds/EmergencyPed.h | 5 ++--- src/peds/Ped.cpp | 25 +++++++++++++++++++++---- src/peds/Ped.h | 2 +- src/render/Fluff.cpp | 12 ++++++------ src/render/Fluff.h | 2 +- src/render/Particle.h | 2 +- src/text/Pager.cpp | 4 ++-- src/text/Pager.h | 2 +- src/vehicles/Automobile.cpp | 4 ++-- src/vehicles/HandlingMgr.h | 4 ++-- src/vehicles/Vehicle.cpp | 8 ++++---- src/weapons/WeaponInfo.h | 1 - 27 files changed, 93 insertions(+), 80 deletions(-) diff --git a/src/audio/sampman.h b/src/audio/sampman.h index 4f3c3eeb..ebedfb63 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -45,7 +45,7 @@ class cSampleManager uint8 m_nEffectsFadeVolume; uint8 m_nMusicFadeVolume; uint8 m_nMonoMode; - char _pad0[1]; + char unk; char m_szCDRomRootPath[80]; bool m_bInitialised; uint8 m_nNumberOfProviders; diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 9836c9c2..f9605ca6 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -99,7 +99,7 @@ CPickup::GiveUsAPickUpObject(int32 handle) switch (m_eType) { case PICKUP_IN_SHOP: - object->m_obj_flag2 = true; + object->bPickupObjWithMessage = true; object->bOutOfStock = false; break; case PICKUP_ON_STREET: @@ -113,11 +113,11 @@ CPickup::GiveUsAPickUpObject(int32 handle) case PICKUP_NAUTICAL_MINE_ARMED: case PICKUP_FLOATINGPACKAGE: case PICKUP_ON_STREET_SLOW: - object->m_obj_flag2 = false; + object->bPickupObjWithMessage = false; object->bOutOfStock = false; break; case PICKUP_IN_SHOP_OUT_OF_STOCK: - object->m_obj_flag2 = false; + object->bPickupObjWithMessage = false; object->bOutOfStock = true; object->bRenderScorched = true; break; @@ -690,7 +690,7 @@ CPickups::DoPickUpEffects(CEntity *entity) size, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); CObject *object = (CObject*)entity; - if (object->m_obj_flag2 || object->bOutOfStock || object->m_nBonusValue) { + if (object->bPickupObjWithMessage || object->bOutOfStock || object->m_nBonusValue) { float dist = (TheCamera.GetPosition() - pos).Magnitude(); const float MAXDIST = 12.0f; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index f1cc8ede..bfe2de34 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -8931,7 +8931,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); if (ScriptParams[1]) - pPed->m_nZoneLevel = -1; + pPed->m_nZoneLevel = LEVEL_IGNORE; else pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(pPed->GetPosition()); return 0; @@ -9130,7 +9130,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); if (ScriptParams[1]) - pVehicle->m_nZoneLevel = -1; + pVehicle->m_nZoneLevel = LEVEL_IGNORE; else pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(pVehicle->GetPosition()); return 0; diff --git a/src/core/EventList.h b/src/core/EventList.h index 1c03c9d6..8840afc4 100644 --- a/src/core/EventList.h +++ b/src/core/EventList.h @@ -26,8 +26,7 @@ enum eEventType EVENT_ICECREAM, EVENT_ATM, EVENT_SHOPSTALL, // used on graffitis - EVENT_SHOPWINDOW, - EVENT_LAST_EVENT // may be above one + EVENT_LAST_EVENT }; enum eEventEntity diff --git a/src/core/Game.h b/src/core/Game.h index 8dc73e8a..e3f0f616 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -2,6 +2,7 @@ enum eLevelName { + LEVEL_IGNORE = -1, // beware, this is only used in CPhysical's m_nZoneLevel LEVEL_NONE = 0, LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index cfa0cea4..6209e5ab 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -548,10 +548,10 @@ CPlayerInfo::Process(void) } if (FindPlayerVehicle()) { CVehicle *veh = FindPlayerVehicle(); - veh->m_nZoneLevel = -1; + veh->m_nZoneLevel = LEVEL_IGNORE; for (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) { if (veh->pPassengers[i]) - veh->pPassengers[i]->m_nZoneLevel = 0; + veh->pPassengers[i]->m_nZoneLevel = LEVEL_NONE; } CStats::DistanceTravelledInVehicle += veh->m_fDistanceTravelled; } else { diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index dfc6974a..fb64c551 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -251,7 +251,7 @@ INITSAVEBUF continue; if (pObject->ObjectCreatedBy == MISSION_OBJECT) { bool bIsPickup = pObject->bIsPickup; - bool bFlag2 = pObject->m_obj_flag2; + bool bPickupObjWithMessage = pObject->bPickupObjWithMessage; bool bOutOfStock = pObject->bOutOfStock; bool bGlassCracked = pObject->bGlassCracked; bool bGlassBroken = pObject->bGlassBroken; @@ -269,7 +269,7 @@ INITSAVEBUF WriteSaveBuf(buf, (uint32)0); // same WriteSaveBuf(buf, pObject->ObjectCreatedBy); WriteSaveBuf(buf, bIsPickup); - WriteSaveBuf(buf, bFlag2); + WriteSaveBuf(buf, bPickupObjWithMessage); WriteSaveBuf(buf, bOutOfStock); WriteSaveBuf(buf, bGlassCracked); WriteSaveBuf(buf, bGlassBroken); @@ -305,7 +305,7 @@ INITSAVEBUF ReadSaveBuf(buf); pBufferObject->ObjectCreatedBy = ReadSaveBuf(buf); pBufferObject->bIsPickup = ReadSaveBuf(buf); - pBufferObject->m_flagE2 = ReadSaveBuf(buf); + pBufferObject->bPickupObjWithMessage = ReadSaveBuf(buf); pBufferObject->bOutOfStock = ReadSaveBuf(buf); pBufferObject->bGlassCracked = ReadSaveBuf(buf); pBufferObject->bGlassBroken = ReadSaveBuf(buf); @@ -325,7 +325,7 @@ INITSAVEBUF pObject->m_objectMatrix = pBufferObject->m_objectMatrix; pObject->ObjectCreatedBy = pBufferObject->ObjectCreatedBy; pObject->bIsPickup = pBufferObject->bIsPickup; - pObject->m_flagE2 = pBufferObject->m_flagE2; + pObject->bPickupObjWithMessage = pBufferObject->bPickupObjWithMessage; pObject->bOutOfStock = pBufferObject->bOutOfStock; pObject->bGlassCracked = pBufferObject->bGlassCracked; pObject->bGlassBroken = pBufferObject->bGlassBroken; diff --git a/src/core/config.h b/src/core/config.h index 12e6ed69..4ca79cb5 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -161,7 +161,7 @@ enum Config { # define GTA3_1_1_PATCH //# define GTA3_STEAM_PATCH # ifdef GTA_PS2_STUFF -//# define USE_PS2_RAND // this is unsafe until we have the game reversed +# define USE_PS2_RAND # define RANDOMSPLASH // use random splash as on PS2 # define PS2_MATFX # endif diff --git a/src/entities/Entity.h b/src/entities/Entity.h index dadeee54..8c2634f3 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -40,25 +40,25 @@ public: uint32 m_status : 5; // flagsA - uint32 bUsesCollision : 1; - uint32 bCollisionProcessed : 1; - uint32 bIsStatic : 1; - uint32 bHasContacted : 1; + uint32 bUsesCollision : 1; // does entity use collision + uint32 bCollisionProcessed : 1; // has object been processed by a ProcessEntityCollision function + uint32 bIsStatic : 1; // is entity static + uint32 bHasContacted : 1; // has entity processed some contact forces uint32 bPedPhysics : 1; - uint32 bIsStuck : 1; - uint32 bIsInSafePosition : 1; + uint32 bIsStuck : 1; // is entity stuck + uint32 bIsInSafePosition : 1; // is entity in a collision free safe position uint32 bUseCollisionRecords : 1; // flagsB - uint32 bWasPostponed : 1; + uint32 bWasPostponed : 1; // was entity control processing postponed uint32 bExplosionProof : 1; - uint32 bIsVisible : 1; - uint32 bHasCollided : 1; // + uint32 bIsVisible : 1; //is the entity visible + uint32 bHasCollided : 1; uint32 bRenderScorched : 1; uint32 bHasBlip : 1; - uint32 bIsBIGBuilding : 1; + uint32 bIsBIGBuilding : 1; // Set if this entity is a big building // VC inserts one more flag here: if drawdist <= 2000 - uint32 bRenderDamaged : 1; + uint32 bRenderDamaged : 1; // use damaged LOD models for objects with applicable damage // flagsC uint32 bBulletProof : 1; @@ -66,22 +66,22 @@ public: uint32 bCollisionProof : 1; uint32 bMeleeProof : 1; uint32 bOnlyDamagedByPlayer : 1; - uint32 bStreamingDontDelete : 1; + uint32 bStreamingDontDelete : 1; // Dont let the streaming remove this uint32 bZoneCulled : 1; - uint32 bZoneCulled2 : 1; // only treadables+10m + uint32 bZoneCulled2 : 1; // only treadables+10m // flagsD - uint32 bRemoveFromWorld : 1; - uint32 bHasHitWall : 1; - uint32 bImBeingRendered : 1; + uint32 bRemoveFromWorld : 1; // remove this entity next time it should be processed + uint32 bHasHitWall : 1; // has collided with a building (changes subsequent collisions) + uint32 bImBeingRendered : 1; // don't delete me because I'm being rendered uint32 bTouchingWater : 1; // used by cBuoyancy::ProcessBuoyancy uint32 bIsSubway : 1; // set when subway, but maybe different meaning? - uint32 bDrawLast : 1; + uint32 bDrawLast : 1; // draw object last uint32 bNoBrightHeadLights : 1; uint32 bDoNotRender : 1; // flagsE - uint32 bDistanceFade : 1; + uint32 bDistanceFade : 1; // Fade entity because it is far away uint32 m_flagE2 : 1; uint16 m_scanCode; diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 445cd83f..ec4543f6 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -36,7 +36,7 @@ CPhysical::CPhysical(void) for(i = 0; i < 6; i++) m_aCollisionRecords[i] = nil; - field_EF = false; + m_bIsVehicleBeingShifted = false; m_nDamagePieceType = 0; m_fDamageImpulse = 0.0f; @@ -63,7 +63,7 @@ CPhysical::CPhysical(void) m_phy_flagA10 = false; m_phy_flagA20 = false; - m_nZoneLevel = 0; + m_nZoneLevel = LEVEL_NONE; } CPhysical::~CPhysical(void) @@ -1767,13 +1767,13 @@ CPhysical::ProcessShift(void) CWorld::AdvanceCurrentScanCode(); if(IsVehicle()) - field_EF = true; + m_bIsVehicleBeingShifted = true; CEntryInfoNode *node; bool hasshifted = false; // whatever that means... for(node = m_entryInfoList.first; node; node = node->next) hasshifted |= ProcessShiftSectorList(node->sector->m_lists); - field_EF = false; + m_bIsVehicleBeingShifted = false; if(hasshifted){ CWorld::AdvanceCurrentScanCode(); for(node = m_entryInfoList.first; node; node = node->next) @@ -1799,7 +1799,7 @@ CPhysical::ProcessCollision(void) CPed *ped = (CPed*)this; m_fDistanceTravelled = 0.0f; - field_EF = 0; + m_bIsVehicleBeingShifted = false; m_phy_flagA80 = false; if(!bUsesCollision){ @@ -1912,7 +1912,7 @@ CPhysical::ProcessCollision(void) ApplyMoveSpeed(); ApplyTurnSpeed(); GetMatrix().Reorthogonalise(); - field_EF = 0; + m_bIsVehicleBeingShifted = false; m_phy_flagA80 = false; if(!m_vecMoveSpeed.IsZero() || !m_vecTurnSpeed.IsZero() || diff --git a/src/entities/Physical.h b/src/entities/Physical.h index 6fbc3ffd..fa5ada05 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -40,7 +40,7 @@ public: char field_EC; uint8 m_nStaticFrames; uint8 m_nCollisionRecords; - bool field_EF; + bool m_bIsVehicleBeingShifted; CEntity *m_aCollisionRecords[PHYSICAL_MAX_COLLISIONRECORDS]; float m_fDistanceTravelled; @@ -55,8 +55,8 @@ public: uint8 bAffectedByGravity : 1; uint8 bInfiniteMass : 1; uint8 bIsInWater : 1; - uint8 m_phy_flagA10 : 1; - uint8 m_phy_flagA20 : 1; + uint8 m_phy_flagA10 : 1; // unused + uint8 m_phy_flagA20 : 1; // unused uint8 bHitByTrain : 1; uint8 m_phy_flagA80 : 1; diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index 8968c117..d03dd405 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -35,7 +35,7 @@ CObject::CObject(void) m_colour1 = m_colour2; m_nBonusValue = 0; bIsPickup = false; - m_obj_flag2 = false; + bPickupObjWithMessage = false; bOutOfStock = false; bGlassCracked = false; bGlassBroken = false; @@ -315,7 +315,7 @@ CObject::Init(void) ObjectCreatedBy = GAME_OBJECT; bIsStatic = true; bIsPickup = false; - m_obj_flag2 = false; + bPickupObjWithMessage = false; bOutOfStock = false; bGlassCracked = false; bGlassBroken = false; diff --git a/src/objects/Object.h b/src/objects/Object.h index 081c285a..319ec4bc 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -47,13 +47,12 @@ public: float m_fUprootLimit; int8 ObjectCreatedBy; int8 bIsPickup : 1; - int8 m_obj_flag2 : 1; + int8 bPickupObjWithMessage : 1; int8 bOutOfStock : 1; int8 bGlassCracked : 1; int8 bGlassBroken : 1; int8 bHasBeenDamaged : 1; int8 bUseVehicleColours : 1; - int8 m_obj_flag80 : 1; int8 m_nBonusValue; float m_fCollisionDamageMultiplier; uint8 m_nCollisionDamageEffect; diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index e62743de..81c9fa6e 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -63,7 +63,7 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP) m_bIsInPursuit = false; field_1350 = 1; m_bIsDisabledCop = false; - field_1356 = 0; + m_fAbseilPos = 0.0f; m_attackTimer = 0; m_bBeatingSuspect = false; m_bStopAndShootDisabledZone = false; @@ -668,11 +668,13 @@ CCopPed::ProcessControl(void) } if (bDuckAndCover) { +#if !defined(GTA3_1_1_PATCH) && !defined(VC_PED_PORTS) if (!bNotAllowedToDuck && Seek()) { SetMoveState(PEDMOVE_STILL); SetMoveAnim(); SetPointGunAt(m_pedInObjective); } +#endif } else if (Seek()) { CVehicle *playerVeh = FindPlayerVehicle(); if (!playerVeh && player && player->EnteringCar()) { diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index 62234b7e..e3454875 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -20,12 +20,9 @@ public: bool m_bBeatingSuspect; bool m_bStopAndShootDisabledZone; bool m_bZoneDisabled; - int32 field_1356; + float m_fAbseilPos; // VC leftover, unused eCopType m_nCopType; int8 field_1364; - int8 field_1365; - int8 field_1366; - int8 field_1367; CCopPed(eCopType); ~CCopPed(); diff --git a/src/peds/EmergencyPed.h b/src/peds/EmergencyPed.h index 5693e908..6546e902 100644 --- a/src/peds/EmergencyPed.h +++ b/src/peds/EmergencyPed.h @@ -22,13 +22,12 @@ enum EmergencyPedState class CEmergencyPed : public CPed { public: - // 0x53C CPed *m_pRevivedPed; EmergencyPedState m_nEmergencyPedState; CAccident *m_pAttendedAccident; CFire *m_pAttendedFire; - bool m_bStartedToCPR; // set but unused(?) - int32 field_1360; // also something for medics, unused(?) + bool m_bStartedToCPR; // set but unused + int32 field_1360; // set to 0 but unused CEmergencyPed(uint32); ~CEmergencyPed() { } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 1f1930d7..915c5d35 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -9191,8 +9191,11 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg) ped->QuitEnteringCar(); return; } - bool itsVan = veh->bIsVan; - bool itsBus = veh->bIsBus; + bool itsVan = !!veh->bIsVan; + bool itsBus = !!veh->bIsBus; +#ifdef FIX_BUGS + bool itsLow = !!veh->bLowVehicle; +#endif eDoors enterDoor; AnimationId enterAnim; @@ -9227,6 +9230,10 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg) enterAnim = ANIM_VAN_GETIN; } else if (itsBus) { enterAnim = ANIM_COACH_IN_R; +#ifdef FIX_BUGS + } else if (itsLow) { + enterAnim = ANIM_CAR_GETIN_LOW_RHS; +#endif } else { enterAnim = ANIM_CAR_GETIN_RHS; } @@ -9234,6 +9241,10 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg) enterAnim = ANIM_VAN_GETIN_L; } else if (itsBus) { enterAnim = ANIM_COACH_IN_L; +#ifdef FIX_BUGS + } else if (itsLow) { + enterAnim = ANIM_CAR_GETIN_LOW_LHS; +#endif } else { enterAnim = ANIM_CAR_GETIN_LHS; } @@ -10806,6 +10817,11 @@ CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg) } } } +#ifdef CANCELLABLE_CAR_ENTER + if (!veh->IsDoorMissing(door) && veh->CanPedOpenLocks(ped) && veh->IsCar()) { + ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING); + } +#endif ped->QuitEnteringCar(); ped->RestorePreviousObjective(); ped->bCancelEnteringCar = false; @@ -14492,7 +14508,8 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) collidedWithBoat = true; - if (!field_EF && !m_phy_flagA80 + // ofc we're not vehicle + if (!m_bIsVehicleBeingShifted && !m_phy_flagA80 #ifdef VC_PED_PORTS && !collidingEnt->IsPed() #endif @@ -15259,7 +15276,7 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) { uint32 optedDoorNode = wantedDoorNode; bool teleportNeeded = false; - bool isLow = veh->bLowVehicle; + bool isLow = !!veh->bLowVehicle; if (!veh->CanPedExitCar()) { if (veh->pDriver && !veh->pDriver->IsPlayer()) { veh->AutoPilot.m_nCruiseSpeed = 0; diff --git a/src/peds/Ped.h b/src/peds/Ped.h index fc53e4bc..90e16269 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -435,7 +435,7 @@ public: float m_fRotationCur; float m_fRotationDest; float m_headingRate; - uint16 m_vehEnterType; // TODO: this is more like a door, not a type + uint16 m_vehEnterType; int16 m_walkAroundType; CPhysical *m_pCurrentPhysSurface; CVector m_vecOffsetFromPhysSurface; diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index e068747e..9f3f6929 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -159,12 +159,12 @@ void CMovingThings::Update() int block = CTimer::GetFrameCounter() % TIME_SPAN; for (i = (block * NUMMOVINGTHINGS) / TIME_SPAN; i < ((block + 1) * NUMMOVINGTHINGS) / TIME_SPAN; i++) { - if (aMovingThings[i].field_A == 1) + if (aMovingThings[i].m_nHidden == 1) aMovingThings[i].Update(); } for (i = 0; i < CMovingThings::Num; i++) { - if (aMovingThings[i].field_A == 0) + if (aMovingThings[i].m_nHidden == 0) aMovingThings[i].Update(); } @@ -212,14 +212,14 @@ void CMovingThing::Update() m_pEntity->UpdateRwFrame(); if (SQR(m_pEntity->GetPosition().x - TheCamera.GetPosition().x) + SQR(m_pEntity->GetPosition().y - TheCamera.GetPosition().y) < 40000.0f) { - if (field_A == 1) { + if (m_nHidden == 1) { AddToList(&CMovingThings::StartCloseList); - field_A = 0; + m_nHidden = 0; } } else { - if (field_A == 0) { + if (m_nHidden == 0) { RemoveFromList(); - field_A = 1; + m_nHidden = 1; } } } diff --git a/src/render/Fluff.h b/src/render/Fluff.h index 7ab2d81d..fe3ab256 100644 --- a/src/render/Fluff.h +++ b/src/render/Fluff.h @@ -8,7 +8,7 @@ public: CMovingThing *m_pNext; CMovingThing *m_pPrev; int16 m_nType; - int16 field_A; + int16 m_nHidden; CVector m_vecPosn; CEntity* m_pEntity; diff --git a/src/render/Particle.h b/src/render/Particle.h index b51be6a5..8999f4f6 100644 --- a/src/render/Particle.h +++ b/src/render/Particle.h @@ -90,7 +90,7 @@ public: static void AddJetExplosion(CVector const &vecPos, float fPower, float fSize); static void AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatrix); -#ifndef MASTER +#ifdef TOGGLEABLE_BETA_FEATURES static bool bEnableBannedParticles; #endif }; diff --git a/src/text/Pager.cpp b/src/text/Pager.cpp index 565f2c20..609c6860 100644 --- a/src/text/Pager.cpp +++ b/src/text/Pager.cpp @@ -98,7 +98,7 @@ CPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5) m_messages[i].m_pText = str; m_messages[i].m_nSpeedMs = speed; m_messages[i].m_nPriority = priority; - m_messages[i].field_10 = a5; + m_messages[i].unused = a5; m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10); m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed; m_messages[i].m_nStringLength = size; @@ -142,7 +142,7 @@ CPager::AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, m_messages[i].m_pText = str; m_messages[i].m_nSpeedMs = speed; m_messages[i].m_nPriority = priority; - m_messages[i].field_10 = a11; + m_messages[i].unused = a11; m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10); m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed; m_messages[i].m_nStringLength = size; diff --git a/src/text/Pager.h b/src/text/Pager.h index a628be6f..16307971 100644 --- a/src/text/Pager.h +++ b/src/text/Pager.h @@ -7,7 +7,7 @@ struct PagerMessage { uint16 m_nStringLength; uint16 m_nPriority; uint32 m_nTimeToChangePosition; - int16 field_10; + int16 unused; // but still set in SCM. importance? ringtone? int32 m_nNumber[6]; }; diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index c2a664a6..2d0aadcc 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -562,7 +562,7 @@ CAutomobile::ProcessControl(void) bWasPostponed = false; bHasHitWall = false; m_fDistanceTravelled = 0.0f; - field_EF = false; + m_bIsVehicleBeingShifted = false; m_phy_flagA80 = false; ApplyMoveSpeed(); ApplyTurnSpeed(); @@ -2148,7 +2148,7 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) // m_aSuspensionSpringRatio are now set to the point where the tyre touches ground. // In ProcessControl these will be re-normalized to ignore the tyre radius. - if(field_EF || m_phy_flagA80 || + if(m_bIsVehicleBeingShifted || m_phy_flagA80 || GetModelIndex() == MI_DODO && (ent->IsPed() || ent->IsVehicle())){ // don't do line collision for(i = 0; i < 4; i++) diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h index 137925f3..398a415f 100644 --- a/src/vehicles/HandlingMgr.h +++ b/src/vehicles/HandlingMgr.h @@ -101,7 +101,7 @@ struct tHandlingData float fSteeringLock; float fTractionLoss; float fTractionBias; - uint32 field_AC; + float fABS; // should be VC leftover float fSuspensionForceLevel; float fSuspensionDampingLevel; float fSuspensionUpperLimit; @@ -126,7 +126,7 @@ private: float field_C; // unused it seems float field_10; // tHandlingData HandlingData[NUMHANDLINGS]; - uint32 field_302C; // unused it seems, padding? + uint32 field_302C; // unused it seems public: cHandlingDataMgr(void); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index bc47b486..0ed83f87 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -65,7 +65,7 @@ CVehicle::CVehicle(uint8 CreatedBy) m_nNumGettingIn = 0; m_nGettingInFlags = 0; m_nGettingOutFlags = 0; - m_nNumMaxPassengers = 8; + m_nNumMaxPassengers = ARRAY_SIZE(pPassengers); for(i = 0; i < m_nNumMaxPassengers; i++) pPassengers[i] = nil; m_nBombTimer = 0; @@ -101,7 +101,7 @@ CVehicle::CVehicle(uint8 CreatedBy) m_nLastWeaponDamage = -1; m_fMapObjectHeightAhead = m_fMapObjectHeightBehind = 0.0f; m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this); - if(m_audioEntityId) + if(m_audioEntityId >= 0) DMAudio.SetEntityStatus(m_audioEntityId, true); m_nRadioStation = CGeneral::GetRandomNumber() % USERTRACK; m_pCurGroundEntity = nil; @@ -728,7 +728,7 @@ CVehicle::CanBeDeleted(void) return false; } - for(i = 0; i < 8; i++){ + for(i = 0; i < ARRAY_SIZE(pPassengers); i++){ // Same check as above if(pPassengers[i]){ if(pPassengers[i]->CharCreatedBy == MISSION_CHAR) @@ -941,7 +941,7 @@ void CVehicle::RemovePassenger(CPed *p) { if (IsTrain()){ - for (int i = 0; i < 8; i++){ + for (int i = 0; i < ARRAY_SIZE(pPassengers); i++){ if (pPassengers[i] == p) { pPassengers[i] = nil; m_nNumPassengers--; diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h index e2e71d23..f82f18c5 100644 --- a/src/weapons/WeaponInfo.h +++ b/src/weapons/WeaponInfo.h @@ -38,7 +38,6 @@ public: uint8 m_b1stPerson : 1; uint8 m_bHeavy : 1; uint8 m_bThrow : 1; - uint8 stuff; static void Initialise(void); static void LoadWeaponData(void); From 2308321805b97105cf03e8a38d44c90d9f652cd1 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Sun, 19 Apr 2020 22:32:59 +0300 Subject: [PATCH 086/123] Add polish lang support --- gamefiles/fonts_p.txd | Bin 0 -> 1379752 bytes gamefiles/polish.gxt | Bin 0 -> 239930 bytes src/core/Frontend.cpp | 13 +++++++++ src/core/Frontend.h | 2 ++ src/core/Game.cpp | 1 + src/core/Game.h | 1 + src/core/MenuScreens.h | 1 + src/render/Font.cpp | 58 ++++++++++++++++++++++++++++++++++++++++- src/render/Font.h | 6 +++-- src/text/Text.cpp | 3 +++ 10 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 gamefiles/fonts_p.txd create mode 100644 gamefiles/polish.gxt diff --git a/gamefiles/fonts_p.txd b/gamefiles/fonts_p.txd new file mode 100644 index 0000000000000000000000000000000000000000..c05e402ea668edaf0df58b56517da73c2f50f81a GIT binary patch literal 1379752 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

dQNan{A6yN=$e2VM9*q&CkSHkF@zi2}$w;FZA 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�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

m{F3vqW9m0Z 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 literal 0 HcmV?d00001 diff --git a/gamefiles/polish.gxt b/gamefiles/polish.gxt new file mode 100644 index 0000000000000000000000000000000000000000..1782ef870ab8bdc8f9d306eb71419c2c04146bfb GIT binary patch literal 239930 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 MJxy?STJZk=0vDTZ3IG5A literal 0 HcmV?d00001 diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 6fe06d96..6bfde701 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -2893,6 +2893,9 @@ CMenuManager::InitialiseChangedLanguageSettings() CGame::germanGame = false; #ifdef MORE_LANGUAGES switch (m_PrefsLanguage) { + case LANGUAGE_POLISH: + CFont::ReloadFonts(FONT_LANGSET_POLISH); + break; case LANGUAGE_RUSSIAN: CFont::ReloadFonts(FONT_LANGSET_RUSSIAN); break; @@ -2910,6 +2913,9 @@ CMenuManager::InitialiseChangedLanguageSettings() CGame::germanGame = true; break; #ifdef MORE_LANGUAGES + case LANGUAGE_POLISH: + CGame::polishGame = true; + break; case LANGUAGE_RUSSIAN: CGame::russianGame = true; break; @@ -4254,6 +4260,12 @@ CMenuManager::ProcessButtonPresses(void) SaveSettings(); break; #ifdef MORE_LANGUAGES + case MENUACTION_LANG_PL: + m_PrefsLanguage = LANGUAGE_POLISH; + m_bFrontEnd_ReloadObrTxtGxt = true; + InitialiseChangedLanguageSettings(); + SaveSettings(); + break; case MENUACTION_LANG_RUS: m_PrefsLanguage = LANGUAGE_RUSSIAN; m_bFrontEnd_ReloadObrTxtGxt = true; @@ -5550,6 +5562,7 @@ CMenuManager::ConstructStatLine(int rowIdx) case LANGUAGE_ITALIAN: case LANGUAGE_SPANISH: #ifdef MORE_LANGUAGES + case LANGUAGE_POLISH: case LANGUAGE_RUSSIAN: #endif STAT_LINE("FESTDFM", &CStats::DistanceTravelledOnFoot, true, nil); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 71aac605..7877d6f1 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -89,6 +89,7 @@ enum eLanguages LANGUAGE_ITALIAN, LANGUAGE_SPANISH, #ifdef MORE_LANGUAGES + LANGUAGE_POLISH, LANGUAGE_RUSSIAN, #endif }; @@ -365,6 +366,7 @@ enum eMenuAction MENUACTION_UNK109, MENUACTION_UNK110, #ifdef MORE_LANGUAGES + MENUACTION_LANG_PL, MENUACTION_LANG_RUS, #endif }; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 7ccf78d0..b1d29161 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -98,6 +98,7 @@ bool CGame::noProstitutes; bool CGame::playingIntro; char CGame::aDatFile[32]; #ifdef MORE_LANGUAGES +bool CGame::polishGame = false; bool CGame::russianGame = false; #endif diff --git a/src/core/Game.h b/src/core/Game.h index e3f0f616..3b8a856d 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -18,6 +18,7 @@ public: static bool frenchGame; static bool germanGame; #ifdef MORE_LANGUAGES + static bool polishGame; static bool russianGame; #endif static bool noProstitutes; diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.h index 8692d4dc..48e2173e 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.h @@ -74,6 +74,7 @@ const CMenuScreen aScreens[] = { MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_NONE, #ifdef MORE_LANGUAGES + MENUACTION_LANG_PL, "FEL_POL", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_RUS, "FEL_RUS", SAVESLOT_NONE, MENUPAGE_NONE, #endif MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, diff --git a/src/render/Font.cpp b/src/render/Font.cpp index 14a678b8..e4bd2a11 100644 --- a/src/render/Font.cpp +++ b/src/render/Font.cpp @@ -12,7 +12,7 @@ CSprite2d CFont::Sprite[MAX_FONTS]; uint8 CFont::LanguageSet = FONT_LANGSET_EFIGS; int32 CFont::Slot = -1; -int16 CFont::Size[2][MAX_FONTS][193] = { +int16 CFont::Size[LANGSET_MAX][MAX_FONTS][193] = { { #else int16 CFont::Size[MAX_FONTS][193] = { @@ -112,6 +112,56 @@ int16 CFont::Size[MAX_FONTS][193] = { 21, 32, 21, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 11, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 }, + }, + + { + { + 13, 12, 31, 35, 23, 35, 31, 9, 14, 15, 25, 30, 11, 17, 13, 31, + 23, 16, 22, 21, 24, 23, 23, 20, 23, 22, 10, 35, 26, 26, 26, 26, + 30, 26, 24, 23, 24, 22, 21, 24, 26, 10, 20, 26, 22, 29, 26, 25, + 23, 25, 24, 24, 22, 25, 24, 29, 29, 23, 25, 37, 22, 37, 35, 37, + 35, 21, 22, 21, 21, 22, 13, 22, 21, 10, 16, 22, 11, 32, 21, 21, + 23, 22, 16, 20, 14, 21, 20, 30, 25, 21, 21, 33, 33, 33, 33, 35, + 27, 27, 27, 27, 32, 24, 23, 23, 23, 23, 11, 11, 11, 11, 26, 26, + 26, 26, 26, 26, 26, 25, 26, 21, 21, 21, 21, 32, 23, 22, 22, 22, + 22, 11, 11, 11, 11, 22, 22, 22, 22, 22, 22, 22, 22, 26, 21, 24, + 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 18, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 20 + }, + + { + 13, 9, 21, 35, 23, 35, 35, 11, 35, 35, 25, 35, 11, 17, 13, 33, + 28, 14, 22, 21, 24, 23, 23, 21, 23, 22, 10, 35, 13, 35, 13, 33, + 5, 25, 22, 23, 24, 21, 21, 24, 24, 9, 20, 24, 21, 27, 25, 25, + 22, 25, 23, 20, 23, 23, 23, 31, 23, 23, 23, 37, 33, 37, 35, 37, + 35, 21, 19, 19, 21, 19, 17, 21, 21, 8, 17, 18, 14, 24, 21, 21, + 20, 22, 19, 20, 20, 19, 20, 26, 21, 20, 21, 33, 33, 33, 33, 35, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 16 + }, + + { + 15, 14, 16, 25, 19, 26, 22, 11, 18, 18, 27, 26, 13, 19, 9, 27, + 19, 18, 19, 19, 22, 19, 20, 18, 19, 20, 12, 32, 15, 32, 15, 35, + 15, 19, 19, 19, 19, 19, 16, 19, 20, 9, 19, 20, 14, 29, 19, 20, + 19, 19, 19, 19, 21, 19, 20, 32, 20, 19, 19, 33, 31, 39, 37, 39, + 37, 21, 21, 21, 23, 21, 19, 23, 23, 10, 19, 20, 16, 26, 23, 23, + 20, 20, 20, 22, 21, 22, 22, 26, 22, 22, 23, 35, 35, 35, 35, 37, + 19, 19, 19, 19, 29, 19, 19, 19, 19, 19, 9, 9, 9, 9, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 30, 19, 19, 19, 19, + 19, 10, 10, 10, 10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 35, + 12, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 11, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19 + } } #endif }; @@ -141,6 +191,9 @@ CFont::Initialise(void) default: CTxdStore::LoadTxd(slot, "MODELS/FONTS.TXD"); break; + case FONT_LANGSET_POLISH: + CTxdStore::LoadTxd(slot, "MODELS/FONTS_P.TXD"); + break; case FONT_LANGSET_RUSSIAN: CTxdStore::LoadTxd(slot, "MODELS/FONTS_R.TXD"); break; @@ -189,6 +242,9 @@ CFont::ReloadFonts(uint8 set) default: CTxdStore::LoadTxd(Slot, "MODELS/FONTS.TXD"); break; + case FONT_LANGSET_POLISH: + CTxdStore::LoadTxd(Slot, "MODELS/FONTS_P.TXD"); + break; case FONT_LANGSET_RUSSIAN: CTxdStore::LoadTxd(Slot, "MODELS/FONTS_R.TXD"); break; diff --git a/src/render/Font.h b/src/render/Font.h index ebf5e292..01d67700 100644 --- a/src/render/Font.h +++ b/src/render/Font.h @@ -44,14 +44,16 @@ enum { enum { FONT_LANGSET_EFIGS, - FONT_LANGSET_RUSSIAN + FONT_LANGSET_RUSSIAN, + FONT_LANGSET_POLISH, + LANGSET_MAX }; #endif class CFont { #ifdef MORE_LANGUAGES - static int16 Size[2][MAX_FONTS][193]; + static int16 Size[LANGSET_MAX][MAX_FONTS][193]; static uint8 LanguageSet; static int32 Slot; #else diff --git a/src/text/Text.cpp b/src/text/Text.cpp index 69025df1..f481403d 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -44,6 +44,9 @@ CText::Load(void) sprintf(filename, "SPANISH.GXT"); break; #ifdef MORE_LANGUAGES + case LANGUAGE_POLISH: + sprintf(filename, "POLISH.GXT"); + break; case LANGUAGE_RUSSIAN: sprintf(filename, "RUSSIAN.GXT"); break; From 4c5edda82e45918bf4665bd0f5720907c87e15a9 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Sun, 19 Apr 2020 22:37:20 +0300 Subject: [PATCH 087/123] MenuScreens.h fix --- src/core/MenuScreens.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.h index 48e2173e..957b2d53 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.h @@ -72,7 +72,7 @@ const CMenuScreen aScreens[] = { MENUACTION_LANG_FRE, "FEL_FRE", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_NONE, #ifdef MORE_LANGUAGES MENUACTION_LANG_PL, "FEL_POL", SAVESLOT_NONE, MENUPAGE_NONE, MENUACTION_LANG_RUS, "FEL_RUS", SAVESLOT_NONE, MENUPAGE_NONE, From 36f08269a5da1dbb234b443d01ddb0795186579e Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Sun, 19 Apr 2020 22:38:02 +0300 Subject: [PATCH 088/123] MenuScreens.h fix --- src/core/MenuScreens.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/MenuScreens.h b/src/core/MenuScreens.h index 957b2d53..e55ec49f 100644 --- a/src/core/MenuScreens.h +++ b/src/core/MenuScreens.h @@ -75,7 +75,7 @@ const CMenuScreen aScreens[] = { MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_NONE, #ifdef MORE_LANGUAGES MENUACTION_LANG_PL, "FEL_POL", SAVESLOT_NONE, MENUPAGE_NONE, - MENUACTION_LANG_RUS, "FEL_RUS", SAVESLOT_NONE, MENUPAGE_NONE, + MENUACTION_LANG_RUS, "FEL_RUS", SAVESLOT_NONE, MENUPAGE_NONE, #endif MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE, }, From 8e9c9fa445729f67020bf3e96d3c2f801c9cbc87 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 20 Apr 2020 00:14:48 +0300 Subject: [PATCH 089/123] Fix CPickups::GenerateNewOne loop --- src/control/Pickups.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index f9605ca6..1bf6d9ce 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -491,7 +491,7 @@ CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quan int32 slot = 0; if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) { - for (slot = NUMPICKUPS; slot >= 0; slot--) { + for (slot = NUMPICKUPS-1; slot >= 0; slot--) { if (aPickUps[slot].m_eType == PICKUP_NONE) { bFreeFound = true; break; From 81ca8596c8c860f5c9478deb5e303b86aa7e95eb Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Mon, 20 Apr 2020 07:18:26 +0300 Subject: [PATCH 090/123] fixed missing keys in gxt for PL/RU langs --- gamefiles/american.gxt | Bin 0 -> 218578 bytes gamefiles/english.gxt | Bin 0 -> 204494 bytes gamefiles/french.gxt | Bin 0 -> 244494 bytes gamefiles/german.gxt | Bin 0 -> 240448 bytes gamefiles/italian.gxt | Bin 0 -> 239912 bytes gamefiles/russian.gxt | Bin 220394 -> 220398 bytes gamefiles/spanish.gxt | Bin 0 -> 246088 bytes 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 gamefiles/american.gxt create mode 100644 gamefiles/english.gxt create mode 100644 gamefiles/french.gxt create mode 100644 gamefiles/german.gxt create mode 100644 gamefiles/italian.gxt create mode 100644 gamefiles/spanish.gxt diff --git a/gamefiles/american.gxt b/gamefiles/american.gxt new file mode 100644 index 0000000000000000000000000000000000000000..eb56fa617e47a4657cd0e727d31b569061cb47ef GIT binary patch literal 218578 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 UEJnqb)`zp2h3~AKLD^98?|=quH~;_u literal 0 HcmV?d00001 diff --git a/gamefiles/english.gxt b/gamefiles/english.gxt new file mode 100644 index 0000000000000000000000000000000000000000..ced720ad9b14f9a435328e65683c4af471bd828a GIT binary patch literal 204494 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 z zm~U1q;-?o9Zh3WoO^>_qIQ3in#0{2cuAWuIABTEcmr73d^YybTAZW>5 zk-G|#9PIs#uKb#L`;Ls=uR0`$VC5fIU!ARJX{7_#22q~WH(D4f_F8gh(>DHcY~$T( zUBxK#;3%7QfxJ7t?}#hh!!L-Hd6V{jb`9zC-6OA^JUCTWn(gV1gkXH6g`Tv_Td|3i zN}0_%5_igmAu8@@<)Z$_heT+qj@j4HobTFS`1-hhB}p}Dl2(Y4{eVTE6iMTbkX>)Yr~ud%*h)&S1#evouUDj zYZI?dXRX%gGQAzDw|#}BbAjt3=P&Z)BqJpuBOzzHL*lO&^|9&S4iz`6f8kV6%xS1Tf%<3kUd=o-t|=&T>Z|8)f_d$Wht`M8Ho8h(dVvWD2%aiys( ze{Ge7;aNxY=Vnb;Jtp}_wJtf@%g)&?F7X#_867d07x{gz0k3OocmW8L`0< zPW)q4!^7W97wJLkeWVhsY!sDosT@4n_EW9rq-9RQeWIy&g!~l~Bs+1HmdO{+=~M2H zzg@WztWFKllk70@EgYZ7HyWd=*m)DaW;|;fiG=z0Xy6yeeY$IQ4)2UW%W5*QKfLK| zU@TUq@U)&A&WVcfieHBM<88g~!`x2zD=xyVeXg*M^g2G@gp1*@2qv?5K^i+aRP+C~ z`c~1rRo~Pk)gSG<%3fyos{O8&##hfhPIV+4y&G+JgeD1xrRUgt6}fmvYN))n|SH=bK^JB`uKt)Y)) zvthBmHHv-OaQx_H^&!feOa*?3E(b}hpMoHbGjL$yTey&w3aQcX_v;R*^mDK1%^rt+ zEV)|2xs_VKyLOQCQ1U)|`oFIT-YR_w!O6WrR@vJa5i<&#YaI1ad-E zuSOIx8GX*SVzowQ4Mon7GLr15wX$nnM~zE)vgNxzg-^KET!1d8{j*~7$Ge;XCVHb8 zkG6hMwXeLx(_TN2r_H=f9iBHyuTQq?y*41xp;;#L&&C^!LX|#_cdZ!{M2j?yWJY_8 z?61|YFXvJ4s@LqRFJ%o<>(#kAg>c8L7pus8#4*QCpF21Hygyt2#qk!?NeQZ3sy3awHbptO>m-+Yd%pCb?SuB-Rfb24Dfy7Sd{ddZrb|0`~-GQy3wwmV_h zbt_n4j5`NSP{YC^Nj=5t;Xp=tjFrclyHfOW{GYWm(@$h-?0A3d8;@7htgCpmmUV5% zRIMv_%qE`KhV`!Fbvmspt#SCq7eZ~mJCe*C_#m;>Jmx3VHU6divei|eRR5^N-Qhf& zlfkdP;#Dp1)@FUG0KwVE)!rcXan{LWWDOD2~&-uNMn`BdJA7l`Yzz3W`W#X8ODKfn*)J%+UUG~1-&HmGW zM{_h_f5*#4z*elyAARMJm(_rj>Z##%PaUGGf1*-|8?!YXLaSu?n%W^ZCTw&jLd$lt|OyhOh(r-I^~AZ zrdIc1wQ4@{anYO^w0xUN-luiPoUNp0fC|+rV>r$DlT}@A)S1bPht=wfS5LSDRpyda z5ITlcPvD2MTGX4R*&~mfnCkXM{dy0Id#<|Q-|&@<9%!lxnVDW||5O$FR8{$|cN*k$ zkSFywm5wiF?W(iWNu+UwtoRA^=Tu@n_S{~otHasc+^}%`)Z$|h>FjGW=Vpq0 zReVp6Ovah@q+oRd4a+{WtQyL^x^eut?vblzq^Iw;z3IpfM;y%ggqi!D8i>_OsTOxe zWo(wM;C~_hp_lFbzeAVjEPIkSH zD0&6!TAOIbdT-Yvvo1w%czHUa)`)o%talt5fj3~r_k330KP$8`caK6gqjuqxc{Y&| zsdai%tl%7$lXnbcs6>FH@>8bnR%OFdEO?F{WQrYc&4oP*4JK!`lQWJ z9ir#m^Q?{SL`zU@G**$|JUIj>Ne^mS)sXBaW3XBy9)-<_q2xBu%)Qf3zuT`fpV>9! z{eX70dn%O>z0!|u$nm^1 zlg;6L>?k~?6T$A(7h@aVGc}amuREId*oHTh<7n(7IvDMY%-5CAu~_m&K_tvRoIrng zPP6$bNJC4{?*R+FpVm|KUf=&u-KiDd)VZR4_p2u|$Qw?LpJtnt<&n+I2Y0Px33_CQ z!e~$4vXyshg=hbxo??Na{&+3u;d$TAyGXy$7_*vm8->;+(gS<aF}vg0U5&NsJQNj*YZjB5m4As)@j2dBd&qo^hSi!(s1NwSox+kuXovXHJPq z*f%sYK6l0QWQEM(Ie#A4J>xH;J$wI4tJqO^7B1#Kt+yw^8SONFwFY{&*9XE7t>FUM zlk%rKJ)zaH-PNK~_4njdQKLof5Bm1Z@#-Ip`|y0Ek2Y!RQA;G1F`a%pmUyphZH)-m zSr2KGAO42REEg9@CpB=Rj{HB_u+Fcf6B{=Id?SU~LGtT`?%2Ah6^|jAC*nKEIoQ_w zt~!>OxiC6GL-i24va>CEVf3pH_I3)?wGYpzBB_l3@SLOY7%zUcaa2XgjQs2M^rMXj ziMS@JSR)7T7RmWntbpdW=0vj7%hxx$T@_6k13GRWaUzis%H!4C*Ippsboxv zAzE&sZQW}XwEd_sZ1vVN2AqRgK1|JN05ZU1bUCgpGZG~ec`mOP6a_M<}@lI^>p zK+bl^cwbC!$F$yd_)fJXFB28+<#(s9jP^koRx`5tYP~^#gx)LusI+EY<+A>In~2Eg za?wraSjh2ZibfP)wOYRQghoeqRy&B52G3_b`Oq=wqvv1`x`MyK9>|7Q^kMbJxZDWb zy0UuM)|f-t7`h_ON1F|-eZ?D+Fw2Li#z<2p+RiZ%=J# zjF<9jdzHqcth`)tB9UISB%Djs=V^9i^sECewCy({PA=i?0{(-1B8d;`6FZVsWJN=3 zVp}1-YJE->EH##Ug_JU^M^#fb!|<@~nmfI#!W%2@*F9`CGcdk=WxFr64*1MVLl{W+ zo%$P}q!vw@?eC$RON|78d-YL0L~48uGq6G{xc` zmi%E&PDr?(niYL%L(8@iV^A2bXZ>yKsBu0hddW2LhVf+8`$RHYgn7I`MwM)wSMppC zlUCSSPS!a$DR0};PV~rmOn5WBIY<5QoKNr8ef`_of~zyC?uCaX$8Ix76WbO4WSt^Z z2|r^IKYDH%ACw}M<@y4zOvUqik zS8@4h>-&4#^Q`;fCOJBuX!ciyZ4>p-51MHt*&FcdtMMeN`^l9@{mrbhdr6*?xGZ!{ zWt{FoIf$u-N~1rnYqUP+;52ToUeA1+xZ)di=dl*iOEwk1|FBvVC%W>>ZH$k$_Q{7F zXtJy^QswCmr5UlnL6X+>Xcd{JSNu)x#ui)aP^v|}(!8w3{h&UPaK6*j*w80echaX7 z4|$@_-EasEq9oFNr@r%7xRt#6`iz#X<0yQWTYJ*D^*8mqeiwSIM2$9)?$gZ{rjpUp zz^S%5wl#>5&+(i_|G|RI>zF3O&hyzdr8eik%pxRO_EbKpfZ@WR&neybGvkU65Jx21 zR!vyB43kCjtxqT>JGjiVX0115GQyVsnzy6%;YL;Blr@IH3o(P1V)bmHy|O1|JBeD1 z5hvouXM{hw_}5K~g4nssoKSoGNFiCDej?#mHyooobfkS->}&NcF;%|K8+8@RhmO`(5@r8AT9gj6>vGbp~lndFV+a<5&^ch zbsnhY&U$0fXi84d+LShODvHsDPpL!1=O3f;)U1M{vBjpdvyF_2fBj_J71KHrOs7XQ zTKv;Gg%^8YWQ_MWJYdm#i!nymqQ`rr(h_NYTAb?`J3g#OE!sWR=oeY8yH|^CdnZvE z@v#2VL2b0(?3jrq^(+paWt{Erv(J-Gcs?hwt(ho2Jk>9)?Awg~(ngg9IO@stH!*Ga z^>n+#*@Qjji4z;sNv>xYa$hR4+PtXeSkl+45ASo>kKcH^#>UdpC+n6M>T#tf{Cl%n zLMu-%vx|1)Z1CB0;b(SJ^*Dq5ZISNsjCd(^E#DHc`_$5!I=P-wnGlt^GaS=W&&U~R z=$hq>4eizD^|B5ZQ_B0(VA(jZG>aN@DW!*}?HWqtT7r$>?HfvVSr=Y_!P|STG$4Znq}I zCbQ#I{LCu6#gqKSrg>fl9W6?ID-!Cq+;x6FvF9h`ry^YM4%A~uo!S*&Czc5kuLw$? zTGMk*AsHu{N|q4~zyZ7qBDBxtQ~B|Xt7Es(_SuCl=TG#Qlf~fbI`*$`zsHODCBCz* z#`|CYwCM8hpI-di`ZPWyURYjE8n81`*n2g)+qKJy47yIzkwRNluE#=q78VcN+DLgQ zU|k{%SE7f$4MHUnI6Uuvdr7`zR1v==C$MbH8Sg{eNZ@AO(YH%h|0|C8zD zOR-?6n6`rs`>|!zbdfHwBiP$=mko(+;y>20My}nPNE*VVmi4rr!PDS~JA1!R&MX~o z6YQKgEIJq(U@A&@xY%WTL@|#${TfMj1{@5JFWOVYXC_uzvlj9Ua>DCgFBFdz?&*^^ z@i%nt(K8x^dwoZHk05~R6>gw48vN6RQ;(|c=ziCm*wm>G#HwS#PN9L-_|j7N&c%PN ztL!dS!sy1`8Z%3ttZ?PYY8@Tf;^yso0#&RFHL;F;1Ti|_esYZyBKNd%ZU;D>BV*O( zc#d^FL8Gf*_%8g6C*SA16Q$E!dWzGjZnJ}-arKHpC-HbVY zB*FJ&1o%VSqsQUE;kng5xZ;6aJEvQOLu_xYBhcjddmnX-UY(nnhzt zMeytJoHs$~*d2bu*u+)sxq{JF@B|5Bn~i&^O$BKpua$SP>qJ^8K?APi8|@*{@j~%3 zuAPfUjeyRqGg{H4AXV1MB<|OKY_&aG`c#P_3+fmTO^;i--l6eOY=|niuc%Rtq{jCZREIFqmYYiayHz*S>qdqHh@YjAi$Z93c zMN!gu_{5KFDsebYx7@TEylMLP2tGQUPood3zmF`9P|u{*F;hHx$8?>I!pb02X9aY5 zTBIxS?X8!sV;SG*viYK8%?hX4f7(nWk{pMX(ulncq_3_*pf>&C)XM#w)sU(tZ03u2 zZsRfPceZiqe?^}jb@Nh-G>Jxvwd1|T@3{8{FRW<|xFy882~A4Q8| zV~NJ`sx@LXGks(|n-S0>a=LTXOV+}q9s0M%QR=h2O!C1;^)&r#U$4K6IhjECm}n=p z!$hyzlnpkj7}Ho~EQ9<}=I?`&4Xcb!x$^hh`UO!K8PUev8UGua68){Q=$(3wKBTYA zW|E6h;5R?&ZJeF^#5<}ve1DU2@{ZsFo=4YJp%Qs#yxJJO)AmP2{U=uy6#d6vkthW0 z*f%~7|BO)Nkhd3g9F*8NYhw;2ucij~Si6-qss46eg&WB!v}b&=d)FcXdKdkS9n!vN zMn<%k6Ae7ZP*#w$KohY=ht-G8r%!da=@tLo+A4H(Ypejz#-HKjXh?Mb`dMDu8*Z4} zW;?AJ!{KBZ^eF4l5(&1Ycl;JRJ3MbM8Xha?71Qw)kts>ZkUF9#iFo85S)R)3(4beZ zPeWVBFl%Osqrt}DCC#1@-Y>p(J$FA3N(!s?uCj}TBr-;GGVTvHO{4kwr7>`-?fT^r z)RsKO7Wf5xgx2=k%(duDqIQ_fwqE=uusza460#dTqf^(PNQAnz|In1omMuVfz98cx z#orcHsV@Fm^-MEW8ZS4g(rNe*9hu0W0yusu@tkJ^KCS?y*wn|*5!D?YVH%&t5;W8bW2NlnxOsrU^m z4xk}E?|uAdg}9$>Bev%tb90}SullV1)8zV$l9|RA?XIF-zt3aK&X9LDDK=-U|5wR@k?jFy1uYnde9@^Kz*t5{Q0u4Qysv*bR(&y;^)yt?$>`^g6&;ZF>NH@(*^`u#n&p zKRSHw+BMpp7n9Yf@%0@ar25UmvW}9MP|aB5}3AVy;nCVy8L|SYV3^e#wqQRm85v zq&IktcTgt&^?0Q5!HxPE5oAq%q!kz$UG8;2!D46{s>U~nP*3N55)r|hoRW6h=A#-B zTs>4@i47xXI6tTtw2t;fKN3mDM`adH)-66vu5c(mnM-qDt|jO5o&LR7?Tg>E%m$3- zvs$(HSel;`S<4LY9OGG1{cACpJgKYKSD9&Hw4pN< z`WJ6%y`uV!nU_>4vMy-dKSHbNY3Dq2>XaYHK|GwW`{7@z7uuHW za$VbZC_X)^>#J4dUf$(8tDrIWYFwf#h#L#lBVB(`nhwhoZKjTrwmR>N9~~bO{Qrk) zX+`;7M^`k_O$_N+L8dwZJ+UUm(U zzW=07#SfqNt$)At44v9~S~Q%tM8`;ZkZ0bikoC`^TQ-Ld_N@|?c;KyS5#4f}R5pS! z?u;$X{ihM`i{ehF^xUh6lMfTq{!RVwgeI}?#G64PyCSkT()%Wz&T`mB%N9aKWMriD zBJq3n@+JG}8b+)(5yQ{R19$b~=JE2Y&>cD=wW++s%I_3kp;C|F%j6@Soa)tD71w_} z8|{!&iu&Tqqw8=n@qXy_`B?IJ-aLiruabYAGI$Y!?V%{9-6lczx`{xVuS3| zYCMD?FCQ%OxO7=&&mViJ+*zOKKs_SUy)uk^}laA z!_U0veH%Oo#EAFr6LPI+a+c2i1lcD=#XfRW>19u1A}GC&8PB)TZ+h-GfV{SyxwXCz z3zDeQrZ$$ik9|P&&d#SsJy;csm8AsRNsPX!30nn$cX)NER*XCGp0#Li6$fBfJXgH^ zir%qKJdQt3G?I6`kWIAwi@-3oJap$h#Hb%X6e{%9a*9r6RSy0)!Wj!~JyaCzE{XZzDc=LY_4*rIn&W$d*_r-dF7;5pUu_p5MJ)nVNaeiwzwT z!LtBZL|1NaEkJ2rU5?5B^eivG4(}81{`890=w`>MSrZ^)P$!EXYVZ0OoHl;5T2<#u zw6X5_5VsR(a}rgbM>+k4m2 z_|e#B<1^0dy|dt%c`*}^7{si5?(fx9$FjmLxoUJf)Y8tb4agd_<_hi5W1@jn(tP(6 zzOfcERBx~f01r_R>9Gg2rsf?T;IU&ve3SJ&IbG%OT(amka&uvHd*y;>qp{zv>p!e< z{Hp$XHYcK3d*KArL){mBO|LWq-I*f}%0bm&>l&x5BY`<-1(LM}r=4z*g(dq;mW*qz zBwCw1Z*~oMg1*Vv{O&U@hR?D|HtSnPdbjSQLF>xA!*gz-thGceo9~JL&@z(JUn+Tx z8KR(`U7yGm@{nX>e(L}(@pZ>0dmeyI4=gK&FG*sEW^> zEG%9l&%{!P`;9K18!tQ-oI3i7Tc4KqO`Qs_<2~v1o#MaRv3j`E5#kGT;_QRUZQm-L zJ#7CqHr=`SZ@d3Kta0^!hi$~Tpr#D%j%V9$62acBT}pSa=782r{O`&ZQS^5C?&GXH z8WKeO&H6C+^yaRI(dN~&iK@)=H@dYJ(6dzd$UnHN?lhKob1JO?yIVUY|E}n9YLhn_ z?#I55=Hoe%GlmPaF?vbgcrUgei;EVZ6@5Lc*5h!MPA1!FyZkaU>y>)^V$JMay#R#} z>0dUQMz^L`(wNtKTiTocK?bjujf}ScK?dyPN`ozbX8@0Yfo@_Ri{B=+M%85~`|0zFYbu~UUlDI^tXhvpS2r2_h|i4` zbX6dz=d_mZl$<@Q1-{L!b?jeI7rp)n>)nuBc$B*QWI zwXbxTEz&>(bAk1F&H1I_Nd64_QX?1=X#eW9kEZx2(A6qAM3Qw znQmo0MJh`BO6TMsvksbW;3AD-RCKIM3?he;d zE%6=iRV-39w31KjsX57_wH^Q9?lt!`KJs)w8XuRu+EP+?46o>ETZ(&ADPR+8#1d(F zf+SzBU!QI~OpR!woUWUr3521ig3a`9^Kj{H9U6yue$3og&9; zc_+lwY$lQprqYd$zJ~6s`HcMqZA0m+tu6kO=bnRfY1sI2Hcm>UIW*xztdO+Av-U<1 zJ32O+cq|oj4t-Zf(>5J^od|QHyU-ETVlQNw%5JK#(LCq~z3_|nvKVdW+_5{=@8?-{ zJ&{G$UFSVid3%iW!PUX9m!0+1=8~<0Lf5MQ(fRg!%|q7sLDk!7nb|b>`_XfrH&TtS z?#fhRWU^vGb9VeHyYtjs&zaB^e>W>LyJB+8nKvp{yHi^IB7T^K=t#@@<*ZdF-<8hv z8~g40T=I=Q4!{Vyv|0h=fl`St&5I<$#1ps%qo8$WCVGBuQ0dE+3Jyf)m`smrol?`d?}_21Qd z(!?+C)F-jaIq$d51+6i{ugaUrrFb`4GtYe!$s|jgm{K$y2`6LgT(^DG%jou&#C5J{ z^yVg%pL!j7ay^ej>2-eeWweIJ#>-p28l}zSetOk@Jd_QI(0UEW|J;1OnNGZT9rN(F z^{eOFMo&d6FUO7R_2IWg=YHkLiz!Z?`adJh=W7z8tgIZ)=`U(77iB;8Gd(Shr~51* z)feA8UzCT)dVaE1E|ZmrLgVo|%cm##e0bjOle#ObW}Ttra-bWDt1$e>RR!B?P>19q3igND#$)#>Nx=G7_ug= zx!c;9I;&jDKH;JD-Zs)?GN~e}c#86Hkp}dx{T}b}?^;$5ZM<+O~Pe#OQQ&v}?i5Zuc>^fvo-=q>q89V<3HSth(7zsTzSx)XAE0&R8{(i0vv zE6Qe`%=J@F-P=Zncd6UueF52Vs6uY%p-9M#M{Fya=dA*#cU{(9-rlSltEJpQnKr=r>B#i+x0G5bZ1vNW)7@9s(!2m*Z)K`iScGWucMl0HK!=b&~DGGw5QCtLbJ*R z4=C2`h3ei}SLNxY7zCHu%c>*Q*`1?nK9PzE~;-i2!DAhNwbh90{UP?GFt` z(h(4U9l04>>g{*ylc%g*PK@bWb8v09B}k{b-SaU)V&oM8K zdfsGOY~9$$f#EWFMq2iP|9FeD))mgja-J6RRCdgXmNPSpD|okBj>z@?c9q2YOzG%M zEH7j1k&iBkq%zOfSwg67UeB(5qw(LYpKzy@No_4zNn&=J6y!WwVI5*PpJh;)Phd}!^u1zzW3GJiw!~s zy3v*$d_cbu=Al}8R`k#!tr<zMztQn6nN+vebD*eR^_9qTI-DKN{hy< zKX9kzc#bdeXqjoSxmPftxxxOwd1+vlale)jxm@@z*a{oawB z%|55o#M2qstb0IZ{02OPk~p%y*(iFl>S3R}Lhkt6YovO8;Mzj-E?Aor5nY>TaWI*@ zX8j`%g4UdW$pRBktXgQbVX7Il0yR!B3KBH`5}iced}?R)u|++sHZ4A(cXn~5wzHyt zxYJtNzPkB=M`(!jwS3O^v*P&nV1l|73`#8HDZH{?4rTf{MS-bDq`q`)>4)dG^rTwo z3U9Z!*W->h6OV;rI^3K^Z`ZoROZN7~n?N|N^A&iQ`PNY7XSDNm)X?M`$c zR>;28Q%jC$))zYQwL2cR?%*$THj#+S;q|Wg-*LjER2%c;Sw}OVz6f#Vt^WN6h zamBj(SZBH$B}Otig(s2Uu{MQ2ZCkD9m!&1*kaw!rPqv(hoUDE9xdOF$ob#r)hjo?p zz`&epI@&49@hn|Cy~hgSIejY9j25(Rin3J5@L5$p_L+4^tRZ&Rr}G8P;(hRhb+z3z zXOqu$gdMC-l$n#mpKTgropVl64+^o{v>W=yiqdDIdD5pBbccp_{DhCEh~0BCjT(m< z<7)jpiIqWQG;6GQj(^>Lpp}^x>8&KRWl`GArBI1b^47A&o9}M05A+8lWUZ ziUmHdJEM&({CphQ_!Hl8s$rgHJJRbuSHwHiz3Q;vs(-!z z{Zaj!cQT}=tj2Ty>SQ6G?rrz4y#=N5WmYwll2Puhft20V<8P^Fb?_ct!+r5z;+Ww& z2{vN})bvo~Tg9oJSlWd?YLt=@@wy-k6>=MC9X zcZVy+kr*fKq`nqJd%BGwaehYc?zZnxF!evZhA(+5Fd5}p5r=kBNHgIU9jA3!MeR%( z(Ggnok-NiB+~`;+_t30FUrkFQ){d`2ect19S$X;W@)eoCyHhQRE}zwE!Uy%&+kW1t zZ%#P>cKz0KeVNa^tSeTRJ6oNHadLgD*1^`2pUyPkWrdA4KU zM`@I5>4*_%f4IIsqdt6%w{8Sbi?L^te#Cc;{WS{b^yAS!?MKGEDL+Q{r=^YvzEPBT zt2^4XeW<%$wPO0PV%=MXwfj|!S!MUbqxLgz^Xff(#!?$$2`daC=I%1+%2-%;5hO8*RB|38w_hhgw((_l=6JT<>PYJ;-S=ec zA$$&=43cFY*ckaLBTBDXUCGzuUUCsRzdMqUN|JlIkw$X(N$_J+Sd{$ycl6gorTKKIUQs$B2Sgz8_m)q7@>pRtE=Od4bllQh3f3k6epT&*NP}z30Hc|>-V)0om z9L@9VXjV&h^#hICoYssck_gPQ}IiEHm7!s?V`1*aFykeFDvOc+Mru6sT;O^hcC20 zc_*2q+F<7WaCmtiXC_lMMZUI5^TPmbyi;n%_j35J&ESzOnZ4K&~3mtl;WaqP_Tx ztElSyHgQ96)OcVI-gzQ--rLY}DhWox4%X^|ICDQvI-q*MHV&HxtSAgUX@}YO@GuD1 zeh_j-l5|G2oi;LZV-x|3gF4e^(aTTizY-vvd9$b_XIcuW6Z?~wQ3TI&=kXhfb0@8gZH0I1{yg;2 z)Q(eeOQx>+WqyF%Z*MvnnxE9Y$5cbbS+&vhy|J|!t8JOVI`bAkSz5ePSE2{uftl;f zu+cKoJ$-A2HF)pVFYjH&?Rlrhp(GS4*Svw2&^+8r^usRUN{{(a-`~9Y-ZPV#3q>u< zI@fa74BX>gMJ>ajf1Y}48~4chm}59XDyfA|Brz?#xzVxm38wJWVsTV0TU{^?dIo@$}uY^{lwy|8W5=_9Wq$cDsf=s6iiH zZR?89g-4NCYnFb`Swvb*+-Hoj0odY~Xv?5uqkZD6w(*rNzwq>jO>>Ouy^VhHmliu> z#W^vNknsR*PiN0NSBC}iFCOi5H8bhq zqr8~SiZXqp=k0BwWB450j{H->cvv(V+tg}(JI2oTI9f_}rH||}^rSpFXf-F_bmT!F z^!riKMIU}z{aw^2Ex;H3`8{Jmjb21NWQ8+6(}s-a{c52jrg(wQE!;ugq}XxkYNdTG znngR+uYw-9dpzp5YGm?_j$Pj<*{j&=71jPlb>cJQrN^j^Ur_Kn3-pC;UlBJ=Y68P?J4`DDy^vq zPlQF&#kOt5$NseKWY%i1q-Pr+X&!kSTjWhA$Q!*zL;F()B-hz%-qFc;4mzIE26>EM zyXP>mXB<}Ugui4iBa)jKUqckhSEAb8lBn^{jp|uaQ}fC-qHqmRSkj z315G>MXj(wKd#1tBdyHMgsUhLCGBOC-!6-5u-3UlgGaH}_*qyoaaq>ar>(oyV~>bt zCWGyHw;)g7!|ot!-;*9_WvtPstl00jt|X_=djr`k%ZUVF8GB}hkLs`ASg}tu)!6A7 z6f(ONoym2wd{9*THPN%DlMl}tq>Q{J?D?rd;53>=**_^uL&w^tNIce*H)qozEs%8Y z+&(;if)8w2(J9%SjKxztaw;O@QQ?56FSmPJ!>_BjdM+7B-aL*g(NYrJN6UJYJ(0rC zD+Zk`!c)y%HsQWVS9BO3f(Q5NTi&fb)-n5`_NZ{{;;*U|eQ7=RIug#Rt5{WHob-|^ zh$l#hyrERAAE(Z*m{RMWScA>S-eQ5L^3?w7lfs!~qI8ek8^2=-v8AWQ(SBPre%vlJ zX3I~jJ@$K9f8VJq@})Ify1(&Z@+JI@9{1|iUV}tup$LnOr_@g}1D-Jz>Q!4q`*CZD zY=Y&@&) zEjE`P>A5F^3CFaqt9HlISeUrH{rIUAX%&q?7cTfaD;Tu&@an3ZC3O<_(6s2PF|iWV z$G@aX(Kb1hC08}lH4adx4*!h|hu7S!y%9g5eShU>K>>Qzn1fb0nlnAwdhjn=5-!BE z^*CwBC)<6gw?<3hkvW3sa997@oFo%^58YHSFkz8pZO);+oz7Pa5=I{Z|KAeeghZBi$mjn zOI_ky(%Q>8n4yhmP>s5^pb4NKkhSRa{E!vzIN$aBf(Ar$ocVSDv79RfUGK+LeC4d zZ@3=)jg>{MbsppTdbRf97GZUz6auUnVKgAmubN`4sH8W&nqhK-raw=MdQx#tOq1OF zCtEbev)!o?854b5cize6yt9pL(bYQMzLF*-)_|?C1#*{rLT*pq-E1`3QB&12G-j2h zX!g*m)p$R@CNh3j?U5XNx07H$1Ku)K2N~~psQWLA9titdJ>NJ@Co?uOVBguneJEZ$ z+$6QO65WA4dWkn%S6a~`+_~Q4#1>HVcHR5q3!k3WCkUoZG7Rtc5g6+3)c^04#pO-6 zPwLLrlps>i1a#%0(Tl_*li&$_YaMvMep&U3$Y#2J7c=2gchqt7pBD;h{KgJ%B!5&3f=~Y9Ohzl2m+WkM7soTg7B0>j_CKQjrAC zOkFtR!cQYcHR*PXcn9Bk9dB(E7g=FCt;Cz>ndA$pb0w?Ls-4ImRD4fU!^((C^^FG){1St-9ILk`-iG#XFdFiIQf0qLt8MT)WL#3G_&(IlH~uSzpB z`%RkrD$0x30`}UD)#|modeLYi{-mwgK(MS4=CE<$hgS%)K93`7)Z7w>DeAZ6mI_Av z?)CS|Dnv?fL965$86_jgTsAuQSQ~2yXJo_V9lyVh`f>fDz6Akgi0Nar#EcLd!h70B zlg`Usq^6x0KfCI5cI>c2l5BmpPUE~58$G|Q<`nI=L+Ez(>X-2oiEG#ct%_y1qvwuY zr(0j&ByM!$qdM*uo6y9@sqyURSMwyJCEIv08KL#gqsezl-obdZL?43HEUGm*74;d* z?c%2upK>Jc8h=vXC+6|Kuf#-7lzmY5B(KT}QL8uANv_MT_WVz->J)u=a@Y{VI;K@y z*a#WFsP^hf5)hwfo*;P*Bz#hwZl7e-!7LhmdiO<*wCfceu&fFgyk1v&-z*8 z#(3iR05l&;j;pnH@8<;$ z)zkUd4QrpDkeN;+>`W5eq*MZKj0@}PR}$c+^w`fIJH zt;3xeVRBW~40s+iI``)C^bvV=W=}Tf+fQVf?AzV_HnC_~S8STb;04<0Ir-Avp2NT& z-1^$~TO=6t^vmc6yKdb%Y+OnFBhT|Zy~uoS^uV=ln?`p%Ch?>eWI-&84`u@*4m8so zbENEBp7N-?l54BK$xb3D0te&^`a939u5_R$kr{7fZr84jwy(?TyAcK6wl8d}Pkl*` zxYB>SuJxm?roip#8QUgMBiuhm)FVUtDb*QDap$8}AtVMgX|`RLSJWPoB5F^GSi zrgnehpcAvzd0mC`vh=50@AvDfy(gE;uXOI+@_&zN&8oQPaphfUQyio6rwu!39xpAX zuIw!CN81V<^<}Hnt=_rZo_M#~%8nUcO$+v{g!b#&)xwkQzGu6U+V5%XYS|Bp){E^f z?_f1{e6Sbv{>9(a-*4CRPwE%<7=aj0EN7+AtTDQ*J8{zUsNog)#k804<_^&wjy8YK zQ7Ha$mf_rWo@?REIcYXM``%F2yO)fTJTGc&#$pc;{vYZ}@I06#Z)n~B#-^KWA~8)P z!mK37IUUi=wSExX=~(Byo~GCI@q?|0wg{M(7809_aWW5<*laz$R)%yF%YahX*{Jnk z@0PVZc+QJ+RIQ^v*XK|jzX&0M&5dtp_(qKsnn4uxqV>cK(YKMSC-Pe=-k;VpR#UND zc1h>>rmT6pQ=emZ@`?NP?KDPf&wpIaKaQir+j%?GVdDlL{BRq|%JuckVA>KSigrXZ=gbheLzEt`uSJo7x&jVDaJ&==@C2FBgL;RJ zei_lRSLirc#X!ZIl-f6$HNu$}M}EVlNO3CBdY%4^o*&_@kL$EeMdkrA2QxI^-~7E? zKJzN9lD>2VqVk>9c=HSkPK3dy#J9zh;s5wWZP8IJHU~PUU8TI%ww_ks@qg#zfpg>A zYgFPE(hOJBX{@px`mIbvIhrF85y*ZliIPISIEd!yJAJvra&VosMfX=;(iG!Q9ZJL+ zJAD~%Wy18%t{mEk0`<1z-Bz*d=;F|F*tFvFz0alJv+!!?|I2~lNM=HM)T1@o&xq6Z zwXoI92Zr)UIy{wOIN3|Il{vhg7x?`ePuE-7MfUoTW#^Q8RBnAc)}lEns5Kz^4pma2 z>Y4Z8m9+}tCfkKB_?4aL0Czm0yk2Z^T;?uS!BzeW{9)A+P2y%KVyjl#$DI zcso6W<8YK7k!bX4a6Pp5ytN7+DeDh1d{CdVA|p92xuQMTHkG>Lk;WG!D~{fg?2k)Z zlArmd>+qRd*FrpaQ=2w3#>9EB9kb}Kpvf8)CJv;JD4BTG zGwq*wb!$C(&1CL+QdICl-PhFUTI%e9rUl*ic>U>BUriwjQu7!(gEARyS1i{3H6o5+ z{5+HTb2JRSt?9He_W4=SYy^0i$S>nD{(E&LF)c0S2a*l2%2+sm3}G|IjxIBgP3qzG z52~GsYlk{M2G+c`QKlVLwal>Gsb3PY<3s!bDIbcisqrLwk0neG(e=TM@nB=Cv@ex3 zt(u$GU&mF!UYf(IGK&{a95h+SgB!Tn>)PQ+?;47}_gW-bNk#*^Q3e0>AJh>kqbW0{ z9XZ~;qGBCSd!~%ED>3PH_9Gt0mZYB%kt6F2#-alU`1RJ-SxeB=ugD$$U^Lo9sr3xO zOjnHbyM+a<^P`)_7P$sd5*uoX#u;l{vHQXaEt>zvDSDU8E%A3#7wed6oj!7Y0GWGg zXn+~o_-LcMBT}+z4Q?*X+@1Cl!J;O;qWI}1{ph-1=qjzwy|FUakL^92rcJCMw$4A% z3;b+Kl6^pzicxt-{3_vNX1LHp-531h`HtT~I5y&`y#&IY{d0%9>%C1sS4n$T1g3R*l!z$$wwHDyi0+U7KjmrAKO>IS zvl~`0@n%;q4#mBo@i`8$59pg55T`Ql;CpL|dssJ4v_=KT63ydWw?T3%Mn=1qb%j)2H#b9c`Syx1$d@0FfbDp3iI! z)Xtn0D#oLtWcI?5xUq(hnGFetQ)z;n&MlD@9iCGcE$aCv=U_JXM2&m7&zK$-rO9OI zQ2P+q*n0d-V?<~=Z^?Yo-`9+f95B&fYx|Sp!Ftk7D8`Qm)dxN_7Uj)h>zIyDFj^56 z{`K0c<`k##<-ip=1+e zr7*d#ak|Ssa+vqu>b{AmCU!|~$wNdk;sw3pNl>Qw+S+ThBtklE#oDWA0{*o2iK3?Z5qY7REzr#5HIdfoym)Hv->iNU zk+J)auVfXT?yF^N$Y@{N>>h32`nRrbc#-Fh|3KT|+3L9u#f$f@G@0JGtFyK2F=x9p z0hR7vJw|hFbT%j1HoAoqbYaiaL$!H%#Y33f+-v^J0~!HN`IDL>u1uCQe5a8;hRB3= zBvwdujx8qZ@%*|vp|xmce~h^K3uj36S6llyo0!9XWbH%?vtl(FK*wMzL3!UQ&Gr0e zWzU~gYesJuRkXZOBG!FwoT24VRNX7CCJGS6Kdf&o84Za5f;{xLrLmVoa?MbqClqu< z72W+=X_=TTwJ}t8R%l%vlt*vmC+lY^?eXIqJKmRZOx)$_2X$}L!#i5Ka?xax=uxXFJ(i0pDJ>iMep|iNIbCPdMi~B(8lR;9NIh2PJGrZpW_2jqR2m(`2)D)v)Z zXJW0ueyE3gM;%b_rA*Un#%j%tl1gV^px1S5XkatjL+87#Of*#uj{6bc|p6ios$UY$M zN-^J%T};-#(6n{ExtKor2LGieceKZg7Q{DaRwy%fdX2u}+#U}PrMIv-xY%*`sW+wf zbSs`a9xfhuumXbow6dUhP|TWYT79lxG%Y)3@YnGJlT>R-*uejwWq)t@kLYAy~}*Von(rxue#P) z-%%Z}L;k^?A${bRY6D7G$LA?tTd92 z#0wy?#>Ht&)Tp->UnwYA&az``5YZ zSqYn`v-{9^TN<%BeCL~jQ_!~8gZ3I#zLc7is_l<1@E+jy$T_Ih=B(cs@zEUmz zMUBCFvaE>A`bcY~9&XQE7HutKr%At6|4&SGzj!hA z>{)FM16jWlbgYbO>-hiMySHb%uIs+@{8Mx)siN~hbtK!VwBJAgyhtDk10ZGlMa57u z?TAuTy2OzmT>a9OKf#siw)(+Osr-{YKkJKux%NH>BtX%QlTxvWv-jF-%{k_{{KjQo z)}!@JeYNN@DScUmwwO6P8b6Z$Ov*&SUhn|~OtuFXl7C({}u6g)iS@jA`iX&nbf|@7sLyOx2^j zU9Cyg8-tNe1NB8(~ zZ}n(xp#M8tDSdprS{wX_PqcVTcaS$8sT(D2@*_=_Ri01EPuCR~v5`4s@0m{bPwIJT zQS?vN|9^K-_27*kE?aNs!4DRVb_ZBZ?{{xg*j)GAU# zZ++%s_+VKZvV~2SkC;h~H<^ReUe!HAPc1*ZS?% zm)LjmjZ4Ieij7S4qFM^P6NR^KWo8*zn^8koK6NT-d&K;WyoQzUxP9W$OI%PzX7!B+ zKEYcwSmOqX)ehyLe}CKuuU+pHlJT}5A9v!$tX4ICS(O%M-A(ad5$se2MPG7hBjOi} z1wErr?UPiVhi?-14|>h_bjCYMM2gM6?wM>MA@)LA^eYpA_4&knsBU3|8lhsEWwBh#~Y(Qv|J z$(_PNzO?7Ezv8mds_V7)dcU{Yt?p*zTfg=AW&Y}u#R0MI{Ud7p;gKOYNt&0+3-CK- zBDHh--9O{iimAwPW?zef&OAwb_)gl!?%3o$6Y}@t_+MKd-WoOf@Vc5)3^q}m=oiYI zwP)hHFd)2vcF-jIdwFJ4q$bn*-qJp&MBTi2Dh%(A^B&~gw|m1Y*}%*LoFlo7>1=pr zBAs>Etj4UK4dunqB5H_fR8CO(VtuY=eis5%1?j}rYX13*_NENZis>$^7I-rw9)Iz0 z^&`SBj~=cTshg`2mz%L=`OuT4Lch<}r?K5mRCOOD=462=KiaZl4-Rr5r z(VwpC)@k4f&ZRZhM3o)xY~tJN*AG@d?G-rJJNNix&XcR&_N_D0_V&nIq7Y)4#k41G zd)KnNnbAV?1d?D^m48o@x$9eZi-jF<}0!7N(GH|o3`oR$goYy?y<@q!xZSN{> z(kk;K0eKyc`R`jR-{?#^8f*;~&YqvB+FVR__o(hK%9=y0dfXf~?a-E4ktCPQAFaM8 z62Pg(-E6G;M?x~VAFr0hMXsmybgR)7!O*yJxFjP_o_e6Cwq4@?L|}Z~Z5yV2&iF{f zc(Uk2?|ZA?pRfGh)t^1*-5aa*(Tm9z8*k^2>i?{J@vxkjFH52#ld;JM>#CX*{X*}( z#ksw60oCG^>?L_tg~4NbBZ8T>*d**ig^@j5cX)cNG9OH5wRE$3+nhJo1T$&TjzYv> zdYIJ~THUMW-6u}0551!392HNFe9f1k$kQ}1%FK?{7Ripjsx#7w&sO{BCZSIFv4d;R zs~Brs5l5t#6A8kqxHoY~vs7DGv~)hP$f}q2r<*fWr!<%H;riD;@!r6uW;XV%Pn3nR z>X0+DR8(`8v-_aU@3j9E)3F59@574<5sa^!0K*IK8*?@2$n-v?`xL zlCWdyx?zVo=lr12&B>bHUGiw%eQ*8W=jMcWZFA@@w}_vR5iNbI)t?`lHF+X=!Jgy< ztBn*6jnrEK0A+91)uIj6IV%scPn?=sAuZW$Pqit{bpP3_H2&Mjg~#Dml;gv!@`(F` z3#h-&!u)pjg~rbEQ8;rhTkcsA>05Wh>)#x`sWv_PN*%Z>BZ)&{Gt7`>7B}H4)Vxjg zSj^c@k_c3Ky6ETI;PX_!;|VG+Bfq=b4_8$Y<{cZJ9Q#i9i%zl`^w88Ke97UVb;pCF zJ2bDIPH!JQ#R-;imPb}HIJ^-zbYcD4yLlmncb2a0Ec-l?&g^L(-@6vha{x|E;Bi@t zQI8)<-sI1AivvGhzxu`(yKf@3?oDHd2GJ}^^L}!^skD3c@u6co`@etmt(|7_NbTNw zcGgU6X+;gqFv2}=ej9zD#a=%}KU%xOi{!7M?9J+F@8B9+zLaFK5Hu|YIgdOo?F_Ff z3}-!SN8(V+w(yvw%{sBSP-N^hlxrmj4sR>w6$Yb{Q7bUN$=qmnwEOqfwlCc@OKEQ+<<^vJUb>eY z@kafN9$$vjydi(H2Om>FdK?OOH!O~0pqxZ0>KRVK5F=hlXwxC3E!WaCP` z&}-MN!k1G{ZhfZ2J$n`1z9;lj|05BUCq+D(TA}OuhO3u6p15OV&vw$u^T@YWeAy^G zdyWMf#o3?19$tFZ^RWl^!*aHlLTTQ6&-o7m%{gdv+c^Cl%ciC21`9NQK9$&)osC0o zWLf0#{z6ZcLi@?~x!q?EhhF?H;+ovHC}Ma_N~A!Zdj%y9-d{Ei4fh^{=IB^|Iau%4 z7{Se)nag&p`y4wnd){mJt58Z-+V}kL|H#_ES}@uY62eCZ6nVko$?9ITb;mmTa$|C^yO<$W_D(bgA_N zXv)8rb-?WNYT@1AqxHNzlkY;Kkv$5|59HVaB8 zd~24*3NyGWqGuVC4P-HA9AZh+Hc1!7m1XS8*6(8dc>3(1CT%5y$t{d=YB~8|V_(LX6LxEV`Vx~+zCB@vwHYq{ocx1(i@Z@pH>sis!Hd=e0<#TGQAx7 z;xr_dH6?cv$fhsX3ma{BiqK#l4(RLsMVV34KGqd~HWHZy#66?^#mSTG+FaS--W7p{ zA|UO~-tlI>(#P=&zg_k}JHcqHdpsk8Mr~D$n-?58U*Ep8@m~LC1l90b$$XC4M+*io z&SOb0Sh9Y{DtV&vFVUo5^J_GlW$G=RBAr=p4j=My{9*jh62d9i7mu{Tx9PLYH0@8@ zr@|t3zI`5zI!B06ESq%2WNdXy!hI9xk9_N$cB0_F98Zve--~ICvj~mW+NU;kzr0sG z)Xvj&-;b8R<_ohlJ&J?<3I*=1Po4^eJ5|588i`=uT9K`_Detd4f3Utg7xAsts#!q4 z?@CG>y33c-1rkAP9s{0)(|#k}-xdABYq@?gJ`NQ{(EK8vX0`_*_$+a=Ge+Xtm!CRN z4>JNMNA1;wPWscMvv;pXy8f;7-E?(@@8ir#i7F~!{ ziV)6mWKWiTUB)1rpU)17HGUk~xufyYCx5Nc-nE&VWo=)s8~U6omR8u~B?Y?;>v=_D zkY{k}a`D=DsR zSB^8rw2vC+V7+mo@^VMYUGzDbB;Vh7ib2m_rATVDv{-li@OhR?>*Jxx3wHnfu$x_b zDJn4%93$!Rup{Sd{SH~?*ZT*;T;@n3x4r6}gxJD(za1U03|B)*`gealHwZkuanHns zt{Lx{PJX17?sS`-hq?K4QAhiNzqfuZk18*jac1-WO|QetzgcuS74EG=4}W=7j@Z-I zkW0Qmzq3_;f89$$Wme~3W_%EQ#wfmPY@v6UDF!dk%wxgPYXsHGc<{8pEU~Da{m|gM z@B+UdA39;T89mteGIV`4Y7XkezbbDxtK~<}d%olnO2iNHleD79rCCx@P~1P`@=))W z;t2?6-4?AaMhH#LmTYuy9{#ksBQr{GuK%4wg-xpGt{9Zv<|z`FniN3d)}GhzdQNn^JvJ8_2UMO#*N+6 z%?l2Y!oI#eWV&94IO`B*<^`2dqDnPOcO|&HzsMk(8a`ok6D$e5VJg+p$uIG&? zY7B50J;rl6PjEQ{;GWAhAIa~7^&A9d<5nxslmBqk7PDFB^3(B&=}8DL2JdI5|H#X@ ztfun2ssyby!dJ1m)?IyZ%yQu!4(dDIY%dYMHWq#GF2(4sRb|FYNVhe9N9U-#)SSsM zb{;Jg(psKQe)JEAt$QEAv(+-3XV-CM5NoWf_V8%i=ckJUm)`LG!xpuoq5(5KU+wap zqmSmWXGME7j}Gp)AI_V~^+s!VrMA2S@?3I>4UNpF5=ypum`b{tL@i!wkQwdrR2CU- z#&x>umn1{dxLnP~$j1YZgyy_PNW-pc>smG_J^R#jf9l?&cS&LDL(Zrtw~19~K^g4q zv0x|vV~vzfHlI4DM&4VoxVMjZH_XHJtNoPw`^_5B_^nSCUFOu!>xV-?a!)(UX7K6d zNLbab_~zzC>%3{#;)^yz?sUrteE-EdaWCx)v7t#GK8}j)f3+mjN}pNnBDyHU@P^E| zUn{7g`&y40_wJQH^vl>_7;U4`_^6GYOa5%|AUM^ehkraub zVk3MARNY;?%?8*G9`eoNjFEWvvSC$bQtv&5xICya0x-PB{~+TNd4)e zpgNLV!*e%_%O5Y={7P@VAq~x>f!6bT)mm3E`j>rY@%s$__F~|aI8R%2b`WqPoR>3%a=H__OwjsT2~wSMII*dvh)X zGkZ5DTf6>n{km5ym0#aoeZxm%6!GyaB!-sy+~<;J|06Hsg|}z<&Sz)k?Nb#vWx_xKeuYSuOD-K%R@o;ShZ2AT4P+BDz6M)+A{U}2%f;C8XZ zAe?9S`u}2^ugY0Nk-fUk$R=AG-)_XSuBv$Qt_=R#H)M^F75&y9rFn0!(Y4N3WwcM} zeYSv;;d%2*?2YEq$0zIAxr!rI`Lv8eSH{}!uUtalMB7c zQg9bF^pthPkD-mUSk^h_m`asc;PdtWNNeM3)-_S!=9yM}E3b-E&BusN_PXfv%3eBq z&5@bGfGV`=%im)8X!(`SPBCLd@A%!lid#-tJSw)@QocZbVU!2TT6#B-JRVz2jYG524s9w*O#!H;_LVbh;e{oa{ zi-=hAA1u6ny3Qv0H|z7Z|Ik^qpslQT@XT6lZzg@RRvL)7`I!gn({~Q^|KoKs(Z5~a zzJFkb=uVztKhICsRgpu~(R+we9c7~>`elEY>zrx*C+iyPF)PTLAV}4$)=&N7*hBjV zi!#;-huq~1>c~0AgYx`^?nHmS0qNx zP}$#&Qm>|sA!FY9^)!(Wr+3vX(?L{-187{dq#`t{;NG3~tbUj55kg{_p> zm3L36|IZ2a@tcNBUa#hH^Wuq*)}8QBys5vb9T(?9N%0S~$cJxDx?B-Zi*nqj>;B@s zqJa2+*ZQ8zyxVr8@s2glLP+NVCl znu{n&S}Z9aV@Ie_8~wBOZ|Gaj;pD*1*0ti{;gO9zcrns@i&O1&9_zc5>(t3<2j5jK z=^SNGZg+dF8C@whnYb(e5?W0~V6u)KPl*B5#o`hixUEmuR2Bhm9m1XS8m+WYZGQGn zR$rs>YFgQw8j(r{+{*s^`|~&c+v0H5gY7TbaxpLY%zGN$uPO$^JVPpbjn$bO=l4&B z=h2Ls&kj9>26^fHb@h&-Z1PB3X!K-U=kp!P&$OJ*gsNqfBr}=DwN`7lx%nM~Uu$}K zn}{LHAPt|2dxqMuOokE{^GlQ4e!eIe-x8{@1$4P8uF7ZN;^xm#%_EBCQBrm?QIZ@z z9+e|E;=RJEY}GTjqpma38S~@kysKhD9--^ruYvpJwQ+)0K&bgU*)t>^OKWY^WPg_$ zGCuAyXDib%-h3z-&3M_#RBehutyLT?Z(sJ)MdjPeTg-lXCviVrd>X&;&3Xa2&bsl+ zxaq^_#$a+0@pvMBHvWupL3lCF;BT~jog^)jEbZI@1czIyn4 z>Ep(=>SyhR+BTroEunLtXUnUGlrI|Z9*&JYxtlc>CDm)$i+Jc|d(fJffYen2iqf;J z(7-;n^rwid>cq=^pYfbWq1`I?J+r;Y-f=rKjb8^(N%i%8**i-*;U&alL2!I3zCt0?1>X%J~>J3ofX`|DfW;Uma$u!6qi#X_i_uhtd%OciX;qC|@x zAxw4Y@bX%kYHR$|%(&7KbcDH6aUI$R(c|lz&ofbTgz>8wYP^ThYx%Yv;lL#aFH!W` zGSB!)GvMcFxX(lNpym7}m8s_7w#v;JtD|FZQsGrlZe*p4f?PbfIQh7a^JU8p@cIaa=-RO5i-_ttOk ztPy>%{+p9kVeO-XuWAOf#^f4hXNO%8x16F?!BNkH@VIbIG(b+1*$)!CzP;XXiVXSd zSsnFd5k21|Cfii9h%@fqTRD-8y=lSIqJPoIREf2A`Bsx+)XNA4&9~3c%8w0C&h{{4 zw6f<%OG;>=GiN*>%bLHkAdJ=qz; zcGO*(CyEU^DWALl(I}Gn$Hzzuy*69B=>Lu?Y%zaw% z;76<2?#7PS@h&_1xWwX+^qMBUXJtEs!hy2c__pO=G<&wkGiPb4JM4OEHaA_-Gb?Bv z>4)nZ*~88_az@la{Nc)u1VXf@M}<(P>!hd4HMaK;-7t4l+b^qMoVE4-!h^~4clLi7 zX?__(UG_P-ARHgxau;GfJ}d+uvW0v@D1`R2--@eHPfIsTHrs}7%Y%G>b8wg?W&iB( zv-J&6C(o+Ko$qOz-tyzsns}M7MueV7>Uyl5Yuwh(Wz{49tC}(twR*tHAV^jof6h_O ziK1@rZ)GdjUUh07#mVQ&#~^zs84f_1Y9;8#`Af_%UL6^0!N~L>3$dc?*Gqqj!_PQ$ zy^08LC!QJ}$#Cbi$Q}3d2C^Vm@|{0Bq;Te**2S86BBzOm@O{GB&JNgm{_SvI}*Ik$)PPwzu|xl{6xG2)!h+V!*pJ-LI&)&di28$&5UT4yKKB z>uKe$*2+WHTVM11M7%i2BDbZ8q|f_4a10j)0cKRV;~ixx!s08jDxN{2iIA>meChtK zoh6&-=QFLLxmkSr_|U7?`WPRr#@TAo!?W~iBJI&RQtbVPXwiepZu%Yi;w;qkOM0+r7W4<# zs}^*==FZxzz7`7@lMJWTDMfV?H;D(x86R#I4WiB&QTkf^jAFXq=-*s5>wCxhTmG+g zw>N2hyre`^dymS0UDxg%b?vEQ-CkX1Z{2s-GtGoTdHgFT4wK8!yn`d0WEr$*Y^D8q zW(d1K%p|8IQbxjyh`Fcbjdr0z{Mb9)>B#sGW3QGn8JU*OCm23^p_OI9L)&etcfaNp zE_aKKCV#Q|rZ?3@iU_{5C}-Po!)R}ooEi;pIdyb+5HCoazfxO4E&ZPneQQ05^MAaq zUEenx+8#0=HCE<&JieR5Y_&EXt$u0tU#+pA!z!6-CoFyHT~X3b?7QBNI2Jf-hV#KH zTSmppunWKbmqi!d{ZB`4`Rtz_SJ3o>;JLzIBQ}v zB6PJwGxf%mb`|5Bzvowb&OXGfay&czMjtwQjy}@%^wfQH3Kpb6f3Rdl@6@Tx&VLgv z{`6?+z2`lr(?i+UrR#TXEt;M#n!Z@vD35qOUO~)G`j|CRGp1MNHXL`Fo`3f`z^V_RuIfd$EzD-o%Ghcz%5US__(vjjX*4Y#+ z$7$T^4Mi9H0!)_O532p>d8|i+XD@*IXKzNG6?uQW(B+TUQ`fZIEY5tmMsR9i2{dfqQ0 zW0r~+tuT;5sc9fbVfZM6Bg zIa&UkvlMZ}NqP+HdGlK<}!q^H8I_ff z-mRFOXn*@Vp4=Gsejah^k5@Y)@A3O*kEy4z5%$i1j5odf?RL9^5C3^R_x^zkybkQ> zZ0c`7&>rPwhRZi~%fEeYKm z)WN|}rkyI+C?nPzdf#2o;j2}P&z3ZPykZyjOcp$=UCjP-zxzls-12Yely!$J)pLHm z;>75m*fU?rLxmbWqeWPtt&{l!^Oo%gd~l3#PFudW?&1kQTzASTo-D87 zybqcrn-Hr(Kl=*Z1>x^4T;>O@rSzKT}+WcsJw!Y@ik2akk^1=EY zEj&MuYu!!#@$l|&l9#yA*|XN-M445cAFQYD9ruVIJ^NtY`*7VWPjx?9^!5F9wG+XN z%~|W6EA4GbRxUWb;L-Z!`|B?b{9rxlWHGv_-TLZ${mqSfY`u`DT04Y7Bk4R~luutq zTOF7G#3jD>y`u*^9&i+=>(SUgShP8<)q5~`GNXx`I4*h-FFiS)YxIAyzJKqaH_m)- z@#rtsQ{P|rSOaI|@2=lFS-X?c@Zge4_YYOyJLoLeB&8=u zFHwyDBuq0<8?E14f8SaE)tY}W_06ux_ZS=JvM4OewNg>!}nIZxX&Vu(06T|I#=+~AxGNy(P~}$Y2uTE25;9r>*G7?t{)sUo%NUXT-yikCd0FRd>J0u zrDYe(qlNGjo4;O6J@Jk>^V`Qbc*JvD&DWai`o$5W^MiS)GJ#j=t$1bTkIIa+A=gm> z5&O4puh|b?aM$wZ&YLyPqMq|QSrOJ9B*%6-RQQKW0C&K}JtEwxmvO?(gy{;95Gz0T^MGQlOcJIFi z6~?-s{<0Bh`Qb|_oGj~l=f>TdLvPH|S6kL6EfPD%BlR(}q1DxAUDTP*uNvi4V6S;@ zv{idrSw?R7Y}cx}2RUXrkm{Q_X-C$Nj_+uFYu){yp8rx5NHf1qJ9byA($n6-vjegCO@$lMj z#sJS}kG>kI`JBBTfd+fCyt#qvI`_?L>A})9=s)Yurlo6?$H6kdFKbN>ex~PxMNK=_ zzRuGs1jaKK`1<|7ehc3$KeYDw(#Ei8%js9gs-v{r=sJ_P3Q1SLdaQ3R?);A>=`+8t z&#wIHR=)Z1eskLN_R=O^|Elcg;hMwX#b)K| z*vsov1pg-TyFEhqrWX{e1XZng75X}7v}kFlQ-@dAel;upW_9A>LTS9er0DMP?RsBm z+8lqg`1z=>=D;^g{a&j*)wils!`a)GeD}y+jc$>yS+7f8y`J=B&+i;LoZ8U)N0sUE zYS-Mie^u%}TgdNZSy8PlT(&GPlf6DWVs<&IEL(mii@bMyn<)R``ld2a&gZI@RG8Ec zWc3e^SiIcuTPsJCy;i62cQQfQv#hUu=CTt{$nVPSJ*B5|J->VM*0gzJ9MF z`rf*O1iPxH+MK)J)e7m3y^_Cteg~{HizBNn^TZ2r+1J~@FT;AU_UfxJ;j{XSI;Fh( zu6_G-fnCWnx9#yM=%tOt{Jyov)B0-KsR}F-`Co_9`z!MyDOLA9|2472UYRytS+0AT zF{xOYkG^aFE3fjZ^=FxZ6`+5!B%?jEx1t=+s}S^-wvQI?X$9#(5A}XILAq52)$BPr z$?MvGMyIMXv_?f%Bf^(svHmpj_N>4g%jzHlohWmf-dk-Zx}^ur;`UiyO?TS+!CRx1 zcJsGd+fTUq^yps?<{0<<#c0=g20`z9pjLi-jM_ZnZ=QcDGcR^>pYP$@kJcT}4myms zSrkma-NdBflv&+n9#kxcOxj(_!hPTZN5^Tr@%QGSC~||Cck!mVuG@2Z=XtMf;bf^LBO`rs*fV*q(^3Dz@aCzk?7Li%oW8ui7N}ZU zgSqGG8)+Kw_3=|Jo{zqNc)=g8zs+Ts2l?Sb6cu_aG=8}B#u~Ia<>@XjkcQGXcKF*v zJ4u*jk1y!dnAT3*9*uc7v%B+N>aXX$em|z)%ZXk5F1ly#!c6N&NA!1lMdtqf>C*1z zMpa-tt#wXsojBIoBVK>n-1Y41tJn2wUgjsu@|}bClVwXHybq7R@Vs}DL-l(H?u0&k zLOvo)f;K#pXXTxpR|tuDiBMh-MFjbMEj&5UjE@p6ShM$=_5ZJr`?Q$v9Y1cKHQOx; z#eWegoGc=Nk31Kuv~G1Sd@K?aTg*7-)W7E6_9`*Fp84-)h0$omE^Kb)Lii(&ncP~% z?u<>vJTMAU?e*R`GIJQ#RGRt!_PWx3qH_y8ggc9fZWi5d9(2LTCo6-v{{kn6UMPBR zjb0vMANrdscQBtXBa%DGRvMW(EAw>sj_AAhU%k2RX;xXT^z4oQy6)(-e%Gy`Gpks; zXDu6EeSBn8-SK3#MGmA-UZnL;8-3$aXEu;=IqBr(#h7`FEe$%A951tp+p|Wb;7wU{ zy82k-QY)v^+R6J|>cH$%O-EX1@p~@F#MEAkV_Fkab+`%|3*KBkTZGd+Nwy5o-J#2+ zm5p4rll7e|&3iSK`}EX0pPPSns?PQ1L5u&{G^q?)Ipp0;|8h8Wu2=p`p^A2$YhC{m zBuJlSQ{mqiUn;@o%OU#5%lD|fe7x?TdY9E3H_IX(9p0;aVlooe_vAo5)d@cK$Lqh= z0r34lJ5bfCSiT#=dP0t)GJbtx-*=w3@M!%eF6ZB;)qPDCr>EAJStDl6mFlULua~EL zbsjF9R}X5Zd-bpD%&NNRzg~BS6XkC+J1DD+5;>)|@Z-13mzQBqW}ymaUD=y!>{fnR zSL5B;c==?tov*c)td%0_jhzx>f6XVWMR~SZ63u0RMumT6mQ}ObXZ88Id*+LW?tX!c zRYc~gse#NY1S5jJ$zF}g`-=4X!FuxEqQMTBAFo*F=D5qc48PE+{hPVDRw|e~R|W8P zgLa+O^3GUcv>44;c*~+0l(L`6*NjO!GkbQkek&ewRc%j{bUy#5EAn3``qqm5tY-Y_ zbGkeEMjV@OZk_G<f+>*uAHb z2CJpcQ#_pN$@L8W;KsTu5d0gZ2MH#KceqCGpc zMOwisP)xsgNmUHr#lTJv5e9CV)mOE z>%&DKy@zXiMvTPADt1PMg5Jr2jyWIQePaRVCV{i48JLuDB!R7Arp5}|>t=4I)2cl}$`CCU{Y)J-<4FCTA zK#GqJy0jn1Mk3Z_%8AKb1zPnrUh)WLIdMmeqcyV3Sr244;D2Ag(S`a{xux^+47jeJ zekF~u+L2m!7)5-$jXJmed_0>yrK-KwcEhMyK{bd+o-E#o%FNE#fljubtk^aVkee(% z%fD+6(O}A;+xB9icKH%7kk*`$g8o+1_H^DmZ0T)PX+<89ma+%DPq*jf_;x6`9*&g( z7L_#C>?8z%Uahxd#YHHyVm|$*mDRJuHoMi;0E{4>;ML4`}JmI`W|3y6+Uhk7HR@vC1+7Y_PEu-bD2Tj5Obj?os&R&>YEUVFv zeb)I~wluuScB&!Gid430FU9O4r>!)EkD}46K01p;SYsaME)R6Gcw#49r;pTABNs7L z@nXy5mt{biLAR_LX3@tj1>-8xX?4SG3>dAg%0x2vSF1R2_e_2KMQ7LrkH&_K`J7j8 zwAwYSo7F=xTk+PeQ$1eNr*GXM5}YeW)XwT6I=k!L^}(W)4D{Z3Ssot|9pzbeKkE~Y=tvY`h3&Fq{tCGAaDiq7yeZlL43 z{n2Y}`<-QkNm>fc9z7o~{VAT{15xtXVdwLQIxwrmzZ8Fg(>z>id+jQ2dk?eT%yhG~K)mmCi2Jx;4YRCGW zp@f=r--?X(vq7zJm`;j_{4$ckb^M@D>7Cg!9H0wPw%?tXhP%(1JvciVnu+YJZkXuBErb~?2yqa80hI&4$WK;L{;@@RZ3}q-98S*iZQqP+|S|i)*m@{oE;=&JcqVYMyl(&Q>UmVY!^@1-QiHw!= ziN%v_G{2HxLU+_;pS&FUp_8a=xG*&GX|4@Qc#5{+0be}6^X_*D#fNeWc?ykUdGv4e z`Q_Sd3`rPm`VCEePG9kN_8Oi!%p(^KB}4t@hs46J<@<+vZ5s14)E5 zL$~BLu|q9X=@DO+=V@W^^3uA-0SEA5eXYdE3j%^KUEuDeM| zoDzO}I_n>6q{sL&^q=?fdp1hr8}7Uc%AL=~8jU$egV!3qqxq;hbB9EEJ#@xP8jD(2 z_=aK*vfT43>18|$S*MS5h5eM9<6!al;2^CkVn&BK6_zxSa@RaRc_ZJ1M z%X3wW&B&C&T9fc_-B}%UPI}m$=#$l!R(38bB1hwBUAmr5>v>iKh0oRc$gNY&<3+j! zuOWce)2~Z^>K!3u{pR}pT#pFdaKC4x;K^$1T*1q`v4)xP9J}mJ9%9$?CZAF#nYeBw zhQ{kY$M(Zs((F{cch)D>zihWR$|VOGru9QGEenkc?a?5+L9teMSW8CU_zk1T7Ej+_ z9EKivYHaz#k^KL+TB&M?r?7}$LjCZ3&OjTEZW+YK$E!`_CDCklDh*?!;sc|Ip0BSV zBlWa1L>ZZH?87VC&fZ3!WmJO-Q62jJ%d zzkRm)-+j}`^a?KFN)haE{I(~UXQ59!#n?J&cBZzhr)4nSAg)X_Xuhehl&!R=$!D2BWZjd66Tyeq*Ej2 zxku|aa;qjf94NLZ+rZh;+wlf0$#q$>e=j{;F@2h{d%C~w95g!LK^}Q%W8>|!m8=;W zh;rd}(k?P<)LGdXA<#M%e{=j=%XW>8zhV>FB)g-d&Z|oww@=uf=rUf^-bUH;9D3{0 z8n37mXUTBSZ|sp8zkH@Q@AB7qyu5;u*A861tDWqy8cW9P6eZ;S$dn<;la<_tqJc?WZVzcz3mU&L_;mP4zvj8GkgDZ*zG{aK0#I>Um_iD{WKLySK)wH%}+4 z+NZNlu@S{L?=U(^|2#v|m$92@Nn|+mZmp!_W1GFj$ypAa=3Z^ViYRLpt(vmWLQKb3 z<5Ci#$M*fC+vf`O%zE-0&(@P_q$G#Z&^f#=hLCr3etP^dE@NiDc6s9PtgZd_y50$> zoA;B0?ztj#;Rni!Tk2!x7)F=Lt5rt&D{A*nZ2E}Hqk;VS7l#+TchJ@B&i0C*tl#Tt z=J$pJ+HF)?)XwBr;Q+eIAd}{k_5C*|fBR^CSH-kKjc?$)aF7&?VlDnG&F>|XV#Ct-1=hEZKFP__Ryo5*JIxK>gyGEl)vS+jQ;$w8d+W+`szK;iX zl{6;C-PH-)C_1@Wyt~$&JqM>Rct>Nx-?TCm4rwON-?sjAjm8eD?;l$8a6OBT(Zgzf z?JHrs@#mbo4hQ=iHX5xsfqb(1>=l<9NmAXX9v45dZ`7v=V;Rl0ka2H%!YP(Jcp7SF zZy|zS@#@~P!rnc$XQj8_!6R!v;_g^w9RlBk8Mvpv)xdt56O4uLI&VFE4_2Vn6Q)_6xfwbqzxDD}oUn{%IhRzW;bQ{Ua zr|xPo%`95Zi-l~V^dNaw#2?_r^-lEY+BUnZi$z6^p?Z3Vf+JZ4JO2FO3+-U>TmDhf znD3$=RS(xw+8|e4c=+6_f3`lq%JWZG-{#fL*oX^#db-+!)@s?RA99>IKl7bKt6(Tj zh=J4+lCYg6kCz-ehx6(B{lWU(>SMeA+7DtkNb@I`y%tm5)w9_ByNeD_>B~rG-rlvm z9&{M%?y5bH_YeIQ(|*3F@wV5yuCco6_9UyP%jdp($8)ZI)pLJ%$8)ZI)pLJz$8)aT zey(c7`Se@%)wwJD!}VS=`$d1W@EtOc>*p)0nO$7Q%);q$@eAw!Vqw2FKUz=O$Mrf- z{A}HSTfgqQM*1NN>E=bmYGgY&Jl2moXrHC0Ev+n;m4)#7t$4V6=XKeF$fv4~oZnN?(`n<*S9#f)Q`Q6-2k$;- zY?9*kTuIrg8UDW*YxG)W?qzS&=8^ta;Lznezj0AKw%<9+qI^ccNU3+-QO*%`@6$-@sA{-#LaUm*t*#; z7>26WW?L^fCzpF`j$hdIua0(x{#~&jUqdrs$L%|wJa2htEb(Bs(Rb0)V8YY&j6D6X zR(sD58s+j<9euI5RJMaEc?6V_?a2zNK94_sysp?K-C7lSQ7dxqdR{&CcfF(YhdL#v zlWft-n~-RyT=Nh-E^DIGKV5&*a?$76PlvvD#hxtSmy0`ieOF}qvg>F4;CKGHJnY+R zobx7#>QKBVe=(f6tgeXU*!gG2yS&s>c#rBfm$jscxXt#QSJ=>l^pS^yA$ReSFACA} zURj8kK*l>ysxspDj$QKSm(?XmT2IlcZWT`6)pK<)I-ov?KC=Jo^#tFkt!5Tl@lIB) zr)_S0SJ6b1tR~Mp8uQo3o*%P=a#*w*Q?<2CohZaeT62dJ=&_eWd(O2dgGY-h>sG~+ zW(myHoU`$-pCxuW7o_{)vWY)i@z%37_Bepolc~hT87WHU9(N3vjos?}J)*fQ>oTTh zv3}2sOJ01kxJdG8&uu(^bIFC2I&u5Mb!X=YI9dGTCM}Tn$5qxv82Rj`CP4f zzZokmXU}BTeP@Z^e!ExCerLV+=6rWCF3XH|R%}+G+>4xNrS52{7H(e9cK@h@kI$fS zwRm@X>>Hox5eq2CqL1t|3hzDxy}pc`#Ynqv+=B8*&L+hXC8ic zegFDA{O)V;@MiTiazw>O4`_k&w`H~K5Aoz>`y-nru8IkX?v~egpUcZz)o57~CWr7U z6vGXYNQ=H)iW^zXbKO;;)H+WL1^H;G*H~mG=1#szosrk@Pp$WX$J;8>8K*A2w@&#e zI=30U)(iL7RD~v$3$MAt*1PX z-Yj@i(fn+Y)9g-7Mv&Cp;;g>wnKC>U$(qGA6X~*R;}D^R!^Q+VWTvftt%`M~XFn~r zRwZrb)w=}jgN3^JGVdDUt_HW`%3Up=NB`++`8p;gk4D7CMgA&< zYH;n)nUy!~dEsYvRi%}e_tv%EEN}JR$ZJ=V#LeUqx3(wry}j6Rcq8C-3>fxYKi`~c z6&-Th^VZ`9M2bC2Lh`ho-A&|b>_yv2BOOed>B8(E8A*qJvSZO9S&1*oj`>HKVLW|V zCgVL1*Of-kk+gsL;HR(L($pYsw`j(eF3JFQEKc+3V?GY=trE*FCnCunE_1(GmzCxH z;d(-Tn?>W|*xt2vmX~bX!tc&=x8_1tA;(1x%G7mQ?^R}XmW_F#opb1OJYMt~6`2(g zk-kw|cMukMmaeuIyiDS67Y%IoW{t-BuWGIj*RyhD(N8gt4CvmXkk!c(oxG5)8-e^U z-^MFHKKf-(Ml^gW8k7sTdS1ci`~1p}SJx^(DqpzwfNlgtslBgE+i;YvShXY8Gww&n6HwaPq$m}0nW54%DbNFz3g3&z$fw_}DD?|E zdYWYz_2teHS9Y%-9aLD|=036QWoB3|UOP}~)}4>6s}_%joa>2m4K4bd6BT^64i1+1 z<>mzkK3c6O7d#5DqRhDT_;MQAXSL<*(B;=bW~*3G)-Rb-fQaoLI*}0&+BdT zn?=jUcc!rVFX>v<%G=Dz2zsesl@OH)+`oAtrN@gJb63gdgY}Iyk{$ot_tEKAnq@Pp zBBK*kOT^&6T5WmKxX`FCf7N~QFyx%-wO`WhyR0)W%$6P=JYjq7Xv4Sk2b!cO)6E7iTKr*}GL=-&eqHU=cC|9I$OSO9(K4(~Lv#o0g3>QL1CpIy{yYxi)vmO9;_cnxi# zcp92!nwSNNg#EOO%9e7RK@qnovQwz@s;Gv!4eJjd2s8XB^+|N2kX zZ`DxokoFd3i@71q{EG9Xicj*vje+HwEDAk-K>{Ll1+LCfP1$V z(Y^d~QqlWuf1JE}59gn+JFLLA+rD=w_QnNq)4lcER029_*0+rWmoZU1HN(P^o5iWR z(MccQTjO(%Se$0nFO&JBrS~kZbFGR^Uv}?U^KSM2!ACk5_d@_W6H-;*jR)zQJ=aec zpT1a8gM5OVCdX6-`1m=8Wh8d7K$?k}YUj2--MsK%4-R_n>Va&E+wEpetJu>-m$ZbZ z>U1ITe4~`Z4mbIljg4u%v5F(<;_Oztd?p*(d>&7q4tjpKWP}@AapvY2+qp$rcy6us zM>b#9`rZ{(tFU0Nhd%qK!5Q*_h{}m^_3_-5-G75)_=pQ_lA=%mE8UzkK;0i`>Q`sp0RQE_mm6xl_%pBs+?SUE!a3SVsx|otTpRZ7m7_EE*^}R zE@tzs7PBX(Y>_IRBaO*MP(U(}_+|I+5s49tsI}hwwAN^N`KVP$TZi_Odq&}G4K(5| zUj|?PenlSYU?`Lmh$-6BaL!dAGQ2D#+2Q1E>~!@UXU+~19&%`R z2MMYXiUzC^Fvco0#_?=X5^5K#@P;%Tck{sdIqTcjeDR66&?1>PH2;BYO*WEi}JV!_@ z^IVnC`i$wk%BH7_H6i)!y`Se^aAPFVj)$8UTJrQcC(ha9S&x6YR!(&up{rzUJo+Rl z@mBk9*r=$CKiIn|$BOk%3yh~02kBv?Gfr3lX&BkASQRz$1))WL{cLyJ7Q_VUL3mNT z2DP>Rc>N`Tvz*T8o+j@~H`|-aVmgd-XU{FttiN-cYP#gnDqcP7wK?>&cldAXo)9nT z6i?yZdH-H~W}`Ss-f>d2ppF;H7N4Z46A^TG&uvOKx6;uxNZU@sh*QqSf|f>IwH5av z!G4;QRlsl7eb;=?Ptudkhck!HvG+tlo5CFj)24S;KjomlJyT|33QE ze;TyC$>8g4EPl4yzsBiyw?pOdZ=!?ok@SnaI@=B%%~Fz9m^HCI+5h5bC3IC&>e<%o zWQ}2azP2}3CD${KBv+D}9tIckQ_#k*eE;4Nx^avBWoLKU5Pt2m7@B#vQ|{g6Sst!d z&1*bef9IFJ?+PnlL)Xv9QICTOw8fZr9E&$7=25o{^W?6FakPl-S2;V|Us}(4YK13` zx4z5UWsh0Z8Nr9Hv7Qf)dpsj@n;K&AnfGN`$7{X9!$aF2tyV81C(qGK|I*d^9?j-! ztGBlA6~ehY>dB{(<&WGwm?9p5VeY(nVe9WNZlIOcetu}yIXdFcWtC7wFX^8MW%o&^ z{jQbUd1Jb$oicPBcdeasXKLfJcJD9g^R4Aof3rSqdGctpPLv$abp~;1zJyFJy#~ss z20jsWxf0qTVz!^=W-r4VQCU2XH)ApR5Ej4d;bY-bSFhegmy4P|Tc6Uz9ZL=e;TyT7 zbs~c432iUacE89i&o#d5EIXa9j`;r`eIza1Ls2?>)@tvmsG1B3s;X>6P<7k#y3L21 z7y9+^(BN6Ki4WDL@{BNXtai>S^1Z5RT+^%Z&pb*znLWPhc5LHJ&DKZu5Z=GFC^jMy zqYPoV)hZw{V{}|+k27cKttPwP`!ajW3UBkniAx(hjb&s!IC*c~@!rA)Gri6~wn9^s zp`zkDY&0kMXX{_5P=2)j^?nwZ3QwxKbZ$IsdGJC4AFXH-C;4GL8!7C}CbR44&T9C5 z+{E+#(#f=d-4Ex)QXd`d<)Lf47)Ru_YZBX|RFka6viY(5Mce4)Z7vSiA1(UHiDaEn zg@>0_ZJ0{d=3mRw&Pb1*A|Bev{?D`;N3pi}s`^{_cOE%xXxF;FXdsU2vz24DIyQgS zd%9L^#ka=MMy7J3QsnO69R4P33U{}L!xlP@Q)rq~?#t6}S3>csF>M@u=g%KW1@cw6Jv+U4yYq9&61w5gtm*U=4^_n)j%ly_dURr{O6jTi zGX9>c0*}^J`btmpnwMUome0QC90M4E=Z#>jvfssy!#TVW@lSLYBG;Rz>B^vJ*3=0w zTHjoMceP<8GiQA6Ri9a0_Oh*JOP;Jc?GblFeKcIQSMHM?`}O7p78C*EP97MR&N(km zVHvF&eGDZ+Ty*ETcYEj9yNdn&byqWTqF%cBU|soO$-S6=`!sO{N}~mTCxSbpsCkHq zasJ{M$%jiSg9MYq#tU-`EXK}&PgalganP(h{LN)?=hJbVHr(5I&pXN?ZD%{KfGJjV$wx6_ul9uaEiualiMr z{&M+|zrN#+CyPFNA^zt1$Zoe`wlVobyUo!z*LC#qA7Pgqwvjbz5~Me{Tn4C8HoM*E z&&~ROuiW0Nj%r6SzE`C_ z+k81hQP}9G^>&c#f8UY)>EaoAJ69DJLchJ=07tD5sm2Gds_~2sreCa@u52$inVa9~ zw>z{Y>evyzea0)BK9~0{71}-rgxxBoOV}H$^!ep7W6C#!xYI%Zl7l>;^+r zX=VS$!xF>gXY1QkKheKix_dmI9vFB&Ee6tLf9JJ$wY68z(m^AB{DNE8oV}LO_~_TM zyEm6ia5s8j(Qnt7%?h_J&3H|Qu4<0%mr82@@4c4ja%PZTv|OP8j8Vqi`KB7SEhQudV2(VtD}Egt?Hfh?;mfl zQsH?0tmSpHoY%h}<(_(aaHGGMqwq_!*VYBN*ZQpc>py40$;#wpPml3ETAu#n6_tq% z*onxjId~SfPd_M@8r`2+rR@IR(!!rE`MkAwx4rMp;@;Dv-BxGpHH+j(FQ7NeVv%~~ zQThHXmi=CzXH#|oiRN@Cnmp~D>xp7b`pf%id#c81zOm8uyvEjj9**v^mm(+8xtOJW zJkwj*c<)NrR(J?Ep~$W}PtGtDvJjt}F)K1{T?7j_uWJ}w(|hZZMG-x*s}O^Pa<6|_ zbk};3SAM#T1tP?UvCzwG%Xo_s#RGq}{(rUSsx)oQ`Q^&|+p`w zf4;a@?AR>Gj;)7Ft&5(j#^e~HbdfiU;nCqA&Xt#VmT$O5|2%(at&UekBihe4nRIuo zkaiUZKvlZFHL&)gj7_LlrFH1wXNOxnp&ilI4xsJP`pYWLR>l99#}>`Oh&&zKFlyh; zoHq9I=dc4OhE~45&*k(J&)iiDo=Bw`gUR_uqsmIEle9)Hna6Sc(@^8su}gS{&TujN z9a&H11wi>;HFQ}5sItz4$vD-YMG-#+|iX9(Ei@^C$UZ(aXj$?aQj{NV6r`LpsYG!~CP zJLLP9YecP-MzOVv{=2&}PM>IZdecfpeaPG%EQ)_{`2YWN?YZoo->=paInlu+f|_!= zDo�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 literal 0 HcmV?d00001 diff --git a/gamefiles/italian.gxt b/gamefiles/italian.gxt new file mode 100644 index 0000000000000000000000000000000000000000..95e2dd367ac9d75e5e328f863fb21765e4265f97 GIT binary patch literal 239912 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 delta 19842 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 Date: Mon, 20 Apr 2020 07:20:14 +0300 Subject: [PATCH 091/123] rem english.gxt --- gamefiles/english.gxt | Bin 204494 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 gamefiles/english.gxt diff --git a/gamefiles/english.gxt b/gamefiles/english.gxt deleted file mode 100644 index ced720ad9b14f9a435328e65683c4af471bd828a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204494 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 Date: Mon, 20 Apr 2020 07:45:17 +0300 Subject: [PATCH 092/123] beta OddJob(unique jump etc) sliding text --- src/core/config.h | 1 + src/render/Hud.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/core/config.h b/src/core/config.h index 4ca79cb5..9f5bfeb6 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -209,6 +209,7 @@ enum Config { #define TRIANGLE_BACK_BUTTON // #define CIRCLE_BACK_BUTTON #define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better. +#define BETA_SLIDING_TEXT // Script #define USE_DEBUG_SCRIPT_LOADER // makes game load main_freeroam.scm by default diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index fc399741..137b1afa 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -1240,10 +1240,17 @@ void CHud::DrawAfterFade() CFont::SetColor(CRGBA(0, 0, 0, 255)); CFont::SetFontStyle(FONT_BANK); +#ifdef BETA_SLIDING_TEXT + CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f) - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]); + + CFont::SetColor(CRGBA(156, 91, 40, 255)); + CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(OddJob2XOffset), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); +#else CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f) + SCREEN_SCALE_Y(2.0f), m_BigMessage[5]); CFont::SetColor(CRGBA(156, 91, 40, 255)); CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(20.0f), m_BigMessage[5]); +#endif } } From 556a6df4017eb26a4912e62097de3c0033b58a25 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Mon, 20 Apr 2020 08:17:08 +0300 Subject: [PATCH 093/123] camerapickup ps2 code --- src/control/Pickups.cpp | 28 ++++++++++++++++++++++++++++ src/core/config.h | 1 + 2 files changed, 29 insertions(+) diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index f9605ca6..a40821f9 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -623,6 +623,34 @@ CPickups::Update() if (CReplay::IsPlayingBack()) return; #endif +#ifdef CAMERA_PICKUP + if ( bPickUpcamActivated ) // taken from PS2 + { + float dist = (FindPlayerCoors() - StaticCamCoors).Magnitude2D(); + float mult; + if ( dist < 10.0f ) + mult = 1.0f - (dist / 10.0f ); + else + mult = 0.0f; + + CVector pos = StaticCamCoors; + pos.z += (pPlayerVehicle->GetColModel()->boundingBox.GetSize().z + 2.0f) * mult; + + if ( (CTimer::GetTimeInMilliseconds() - StaticCamStartTime) > 750 ) + { + TheCamera.SetCamPositionForFixedMode(pos, CVector(0.0f, 0.0f, 0.0f)); + TheCamera.TakeControl(FindPlayerVehicle(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_SCRIPT); + } + + if ( FindPlayerVehicle() != pPlayerVehicle + || (FindPlayerCoors() - StaticCamCoors).Magnitude() > 40.0f + || ((CTimer::GetTimeInMilliseconds() - StaticCamStartTime) > 60000) ) + { + TheCamera.RestoreWithJumpCut(); + bPickUpcamActivated = false; + } + } +#endif #define PICKUPS_FRAME_SPAN (6) #ifdef FIX_BUGS for (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) { diff --git a/src/core/config.h b/src/core/config.h index 9f5bfeb6..b5022b9f 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -226,6 +226,7 @@ enum Config { // Pickups //#define MONEY_MESSAGES +#define CAMERA_PICKUP // Peds #define ANIMATE_PED_COL_MODEL From 98fc8ecef09ba9c50a511c3bcfaca3cffe2fed0b Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 20 Apr 2020 16:05:39 +0200 Subject: [PATCH 094/123] update librw (matfx) --- librw | 2 +- src/core/Game.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/librw b/librw index e6c7d910..8b677c4d 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit e6c7d910ffc32bc059c4e750a797fde51ee29fd9 +Subproject commit 8b677c4dd77a73da68447556e3b07c6c0371629e diff --git a/src/core/Game.cpp b/src/core/Game.cpp index b1d29161..94c775ae 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -156,6 +156,14 @@ CGame::InitialiseRenderWare(void) LightsCreate(Scene.world); CreateDebugFont(); + +#ifdef LIBRW +#ifdef PS2_MATFX + rw::MatFX::modulateEnvMap = true; +#else + rw::MatFX::modulateEnvMap = false; +#endif +#endif CFont::Initialise(); CHud::Initialise(); From 370c4e48cd87122e8d38f1a72f6b8f62ff7b9c96 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Sun, 19 Apr 2020 18:34:08 +0200 Subject: [PATCH 095/123] Try to build with mingw --- src/animation/AnimBlendAssocGroup.cpp | 15 ++- src/animation/AnimBlendAssociation.cpp | 4 +- src/animation/AnimBlendHierarchy.cpp | 2 +- src/animation/AnimManager.h | 180 +------------------------ src/animation/AnimationId.h | 180 +++++++++++++++++++++++++ src/audio/AudioCollision.cpp | 2 +- src/audio/AudioManager.cpp | 64 ++++----- src/audio/DMAudio.h | 2 +- src/audio/MusicManager.cpp | 2 +- src/audio/sampman.cpp | 119 +++++++++------- src/control/AutoPilot.cpp | 2 +- src/control/CarAI.cpp | 6 +- src/control/CarCtrl.cpp | 94 ++++++------- src/control/Darkel.cpp | 2 +- src/control/Darkel.h | 3 +- src/control/GameLogic.cpp | 4 +- src/control/Garages.cpp | 76 +++++------ src/control/PathFind.cpp | 53 ++++---- src/control/Record.cpp | 4 +- src/control/Replay.cpp | 10 +- src/control/SceneEdit.cpp | 4 +- src/control/Script.cpp | 82 +++++------ src/control/TrafficLights.cpp | 26 ++-- src/core/Cam.cpp | 64 ++++----- src/core/Camera.cpp | 44 +++--- src/core/Collision.cpp | 8 +- src/core/Crime.h | 36 +++++ src/core/Frontend.cpp | 18 +-- src/core/Frontend.h | 2 +- src/core/Game.cpp | 2 +- src/core/Game.h | 3 +- src/core/General.h | 2 +- src/core/IniFile.cpp | 4 +- src/core/Pad.cpp | 8 +- src/core/PlayerInfo.cpp | 50 +++---- src/core/Pools.cpp | 2 +- src/core/Profile.cpp | 28 ++-- src/core/Stats.cpp | 8 +- src/core/Streaming.cpp | 42 +++--- src/core/Streaming.h | 1 - src/core/Timer.cpp | 2 +- src/core/Wanted.cpp | 4 +- src/core/Wanted.h | 38 +----- src/core/World.cpp | 76 +++++------ src/core/ZoneCull.cpp | 2 +- src/core/common.h | 57 ++++---- src/core/main.cpp | 2 +- src/core/patcher.cpp | 2 +- src/core/timebars.cpp | 4 +- src/entities/Physical.cpp | 40 +++--- src/math/Vector.h | 5 + src/objects/Object.cpp | 4 +- src/objects/ParticleObject.h | 5 +- src/peds/CivilianPed.cpp | 8 +- src/peds/CopPed.cpp | 4 +- src/peds/Ped.cpp | 68 +++++----- src/peds/Ped.h | 10 +- src/peds/PedPlacement.cpp | 2 +- src/peds/PlayerPed.cpp | 8 +- src/peds/Population.cpp | 4 +- src/render/Clouds.cpp | 8 +- src/render/Coronas.cpp | 20 +-- src/render/Glass.cpp | 14 +- src/render/Hud.cpp | 8 +- src/render/ParticleMgr.cpp | 2 +- src/render/ParticleMgr.h | 78 +---------- src/render/ParticleType.h | 77 +++++++++++ src/render/PointLights.cpp | 2 +- src/render/Rubbish.cpp | 4 +- src/render/Shadows.cpp | 26 ++-- src/render/Timecycle.cpp | 6 +- src/render/WaterCannon.cpp | 12 +- src/render/WaterLevel.cpp | 10 +- src/render/Weather.cpp | 6 +- src/rw/Lights.cpp | 34 ++--- src/vehicles/Automobile.cpp | 34 ++--- src/vehicles/Boat.cpp | 14 +- src/vehicles/CarGen.cpp | 2 +- src/vehicles/Cranes.cpp | 8 +- src/vehicles/Heli.cpp | 10 +- src/vehicles/Vehicle.cpp | 8 +- src/weapons/BulletInfo.cpp | 24 ++-- src/weapons/BulletInfo.h | 3 +- src/weapons/ProjectileInfo.h | 3 +- src/weapons/ShotInfo.cpp | 2 +- src/weapons/ShotInfo.h | 3 +- src/weapons/Weapon.cpp | 33 ++--- src/weapons/Weapon.h | 50 +------ src/weapons/WeaponInfo.h | 5 +- src/weapons/WeaponType.h | 49 +++++++ 90 files changed, 1107 insertions(+), 1051 deletions(-) create mode 100644 src/animation/AnimationId.h create mode 100644 src/core/Crime.h create mode 100644 src/render/ParticleType.h create mode 100644 src/weapons/WeaponType.h diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp index e65bdf8d..bdcca2f8 100644 --- a/src/animation/AnimBlendAssocGroup.cpp +++ b/src/animation/AnimBlendAssocGroup.cpp @@ -1,5 +1,7 @@ #include "common.h" +#include "ctype.h" + #include "General.h" #include "ModelInfo.h" #include "AnimManager.h" @@ -75,12 +77,21 @@ strcmpIgnoringDigits(const char *s1, const char *s2) c2 = *s2; if(c1) s1++; if(c2) s2++; - if(c1 == '\0' && c2 == '\0') - return true; + if(c1 == '\0' && c2 == '\0') return true; +#if defined _WIN32 && !defined __MINGW32__ if(__ascii_iswdigit(c1) && __ascii_iswdigit(c2)) +#else + if(iswdigit(c1) && iswdigit(c2)) +#endif continue; +#if defined _WIN32 && !defined __MINGW32__ c1 = __ascii_toupper(c1); c2 = __ascii_toupper(c2); +#else + c1 = toupper(c1); + c2 = toupper(c2); +#endif + if(c1 != c2) return false; } diff --git a/src/animation/AnimBlendAssociation.cpp b/src/animation/AnimBlendAssociation.cpp index fb8c16d7..daca7d68 100644 --- a/src/animation/AnimBlendAssociation.cpp +++ b/src/animation/AnimBlendAssociation.cpp @@ -185,7 +185,7 @@ CAnimBlendAssociation::UpdateBlend(float timeDelta) if(blendAmount <= 0.0f && blendDelta < 0.0f){ // We're faded out and are not fading in blendAmount = 0.0f; - blendDelta = max(0.0f, blendDelta); + blendDelta = Max(0.0f, blendDelta); if(flags & ASSOC_DELETEFADEDOUT){ if(callbackType == CB_FINISH || callbackType == CB_DELETE) callback(this, callbackArg); @@ -197,7 +197,7 @@ CAnimBlendAssociation::UpdateBlend(float timeDelta) if(blendAmount > 1.0f){ // Maximally faded in, clamp values blendAmount = 1.0f; - blendDelta = min(0.0f, blendDelta); + blendDelta = Min(0.0f, blendDelta); } return true; diff --git a/src/animation/AnimBlendHierarchy.cpp b/src/animation/AnimBlendHierarchy.cpp index 7f39d37a..feeaca3d 100644 --- a/src/animation/AnimBlendHierarchy.cpp +++ b/src/animation/AnimBlendHierarchy.cpp @@ -36,7 +36,7 @@ CAnimBlendHierarchy::CalcTotalTime(void) float seqTime = 0.0f; for(j = 0; j < sequences[i].numFrames; j++) seqTime += sequences[i].GetKeyFrame(j)->deltaTime; - totalTime = max(totalTime, seqTime); + totalTime = Max(totalTime, seqTime); } totalLength = totalTime; } diff --git a/src/animation/AnimManager.h b/src/animation/AnimManager.h index 93fec74b..1b333b60 100644 --- a/src/animation/AnimManager.h +++ b/src/animation/AnimManager.h @@ -1,6 +1,7 @@ #pragma once #include "AnimBlendHierarchy.h" +#include "AnimationId.h" enum AssocGroupId { @@ -33,185 +34,6 @@ enum AssocGroupId NUM_ANIM_ASSOC_GROUPS }; -enum AnimationId -{ - ANIM_WALK, - ANIM_RUN, - ANIM_SPRINT, - ANIM_IDLE_STANCE, - ANIM_WALK_START, - ANIM_RUN_STOP, - ANIM_RUN_STOP_R, - ANIM_IDLE_CAM, - ANIM_IDLE_HBHB, - ANIM_IDLE_TIRED, - ANIM_IDLE_ARMED, - ANIM_IDLE_CHAT, - ANIM_IDLE_TAXI, - ANIM_KO_SHOT_FRONT1, - ANIM_KO_SHOT_FRONT2, - ANIM_KO_SHOT_FRONT3, - ANIM_KO_SHOT_FRONT4, - ANIM_KO_SHOT_FACE, - ANIM_KO_SHOT_STOM, - ANIM_KO_SHOT_ARML, - ANIM_KO_SHOT_ARMR, - ANIM_KO_SHOT_LEGL, - ANIM_KO_SHOT_LEGR, - ANIM_KD_LEFT, - ANIM_KD_RIGHT, - ANIM_KO_SKID_FRONT, - ANIM_KO_SPIN_R, // named left in VC - ANIM_KO_SKID_BACK, - ANIM_KO_SPIN_L, // named right in VC - ANIM_SHOT_FRONT_PARTIAL, - ANIM_SHOT_LEFT_PARTIAL, - ANIM_SHOT_BACK_PARTIAL, - ANIM_SHOT_RIGHT_PARTIAL, - ANIM_HIT_FRONT, - ANIM_HIT_LEFT, - ANIM_HIT_BACK, - ANIM_HIT_RIGHT, - ANIM_FLOOR_HIT, - ANIM_HIT_BODYBLOW, - ANIM_HIT_CHEST, - ANIM_HIT_HEAD, - ANIM_HIT_WALK, - ANIM_HIT_WALL, - ANIM_FLOOR_HIT_F, - ANIM_HIT_BEHIND, - ANIM_PUNCH_R, - ANIM_KICK_FLOOR, - ANIM_WEAPON_BAT_H, - ANIM_WEAPON_BAT_V, - ANIM_WEAPON_HGUN_BODY, - ANIM_WEAPON_AK_BODY, - ANIM_WEAPON_PUMP, - ANIM_WEAPON_SNIPER, - ANIM_WEAPON_THROW, - ANIM_WEAPON_THROWU, - ANIM_WEAPON_START_THROW, - ANIM_BOMBER, - ANIM_HGUN_RELOAD, - ANIM_AK_RELOAD, - ANIM_FPS_PUNCH, - ANIM_FPS_BAT, - ANIM_FPS_UZI, - ANIM_FPS_PUMP, - ANIM_FPS_AK, - ANIM_FPS_M16, - ANIM_FPS_ROCKET, - ANIM_FIGHT_IDLE, - ANIM_FIGHT2_IDLE, - ANIM_FIGHT_SH_F, - ANIM_FIGHT_BODYBLOW, - ANIM_FIGHT_HEAD, - ANIM_FIGHT_KICK, - ANIM_FIGHT_KNEE, - ANIM_FIGHT_LHOOK, - ANIM_FIGHT_PUNCH, - ANIM_FIGHT_ROUNDHOUSE, - ANIM_FIGHT_LONGKICK, - ANIM_FIGHT_PPUNCH, - ANIM_CAR_JACKED_RHS, - ANIM_CAR_LJACKED_RHS, - ANIM_CAR_JACKED_LHS, - ANIM_CAR_LJACKED_LHS, - ANIM_CAR_QJACK, - ANIM_CAR_QJACKED, - ANIM_CAR_ALIGN_LHS, - ANIM_CAR_ALIGNHI_LHS, - ANIM_CAR_OPEN_LHS, - ANIM_CAR_DOORLOCKED_LHS, - ANIM_CAR_PULLOUT_LHS, - ANIM_CAR_PULLOUT_LOW_LHS, - ANIM_CAR_GETIN_LHS, - ANIM_CAR_GETIN_LOW_LHS, - ANIM_CAR_CLOSEDOOR_LHS, - ANIM_CAR_CLOSEDOOR_LOW_LHS, - ANIM_CAR_ROLLDOOR, - ANIM_CAR_ROLLDOOR_LOW, - ANIM_CAR_GETOUT_LHS, - ANIM_CAR_GETOUT_LOW_LHS, - ANIM_CAR_CLOSE_LHS, - ANIM_CAR_ALIGN_RHS, - ANIM_CAR_ALIGNHI_RHS, - ANIM_CAR_OPEN_RHS, - ANIM_CAR_DOORLOCKED_RHS, - ANIM_CAR_PULLOUT_RHS, - ANIM_CAR_PULLOUT_LOW_RHS, - ANIM_CAR_GETIN_RHS, - ANIM_CAR_GETIN_LOW_RHS, - ANIM_CAR_CLOSEDOOR_RHS, - ANIM_CAR_CLOSEDOOR_LOW_RHS, - ANIM_CAR_SHUFFLE_RHS, - ANIM_CAR_LSHUFFLE_RHS, - ANIM_CAR_SIT, - ANIM_CAR_LSIT, - ANIM_CAR_SITP, - ANIM_CAR_SITPLO, - ANIM_DRIVE_L, - ANIM_DRIVE_R, - ANIM_DRIVE_LOW_L, - ANIM_DRIVE_LOW_R, - ANIM_DRIVEBY_L, - ANIM_DRIVEBY_R, - ANIM_CAR_LB, - ANIM_DRIVE_BOAT, - ANIM_CAR_GETOUT_RHS, - ANIM_CAR_GETOUT_LOW_RHS, - ANIM_CAR_CLOSE_RHS, - ANIM_CAR_HOOKERTALK, - ANIM_COACH_OPEN_L, - ANIM_COACH_OPEN_R, - ANIM_COACH_IN_L, - ANIM_COACH_IN_R, - ANIM_COACH_OUT_L, - ANIM_TRAIN_GETIN, - ANIM_TRAIN_GETOUT, - ANIM_CAR_CRAWLOUT_RHS, - ANIM_CAR_CRAWLOUT_RHS2, - ANIM_VAN_OPEN_L, - ANIM_VAN_GETIN_L, - ANIM_VAN_CLOSE_L, - ANIM_VAN_GETOUT_L, - ANIM_VAN_OPEN, - ANIM_VAN_GETIN, - ANIM_VAN_CLOSE, - ANIM_VAN_GETOUT, - ANIM_GETUP1, - ANIM_GETUP2, - ANIM_GETUP3, - ANIM_GETUP_FRONT, - ANIM_JUMP_LAUNCH, - ANIM_JUMP_GLIDE, - ANIM_JUMP_LAND, - ANIM_FALL_FALL, - ANIM_FALL_GLIDE, - ANIM_FALL_LAND, - ANIM_FALL_COLLAPSE, - ANIM_EV_STEP, - ANIM_EV_DIVE, - ANIM_XPRESS_SCRATCH, - ANIM_ROAD_CROSS, - ANIM_TURN_180, - ANIM_ARREST_GUN, - ANIM_DROWN, - ANIM_CPR, - ANIM_DUCK_DOWN, - ANIM_DUCK_LOW, - ANIM_RBLOCK_CSHOOT, - ANIM_WEAPON_THROWU2, - ANIM_HANDSUP, - ANIM_HANDSCOWER, - ANIM_FUCKU, - ANIM_PHONE_IN, - ANIM_PHONE_OUT, - ANIM_PHONE_TALK, - - NUM_ANIMS -}; - class CAnimBlendAssociation; class CAnimBlendAssocGroup; diff --git a/src/animation/AnimationId.h b/src/animation/AnimationId.h new file mode 100644 index 00000000..82fed8bd --- /dev/null +++ b/src/animation/AnimationId.h @@ -0,0 +1,180 @@ +#pragma once + +enum AnimationId +{ + ANIM_WALK, + ANIM_RUN, + ANIM_SPRINT, + ANIM_IDLE_STANCE, + ANIM_WALK_START, + ANIM_RUN_STOP, + ANIM_RUN_STOP_R, + ANIM_IDLE_CAM, + ANIM_IDLE_HBHB, + ANIM_IDLE_TIRED, + ANIM_IDLE_ARMED, + ANIM_IDLE_CHAT, + ANIM_IDLE_TAXI, + ANIM_KO_SHOT_FRONT1, + ANIM_KO_SHOT_FRONT2, + ANIM_KO_SHOT_FRONT3, + ANIM_KO_SHOT_FRONT4, + ANIM_KO_SHOT_FACE, + ANIM_KO_SHOT_STOM, + ANIM_KO_SHOT_ARML, + ANIM_KO_SHOT_ARMR, + ANIM_KO_SHOT_LEGL, + ANIM_KO_SHOT_LEGR, + ANIM_KD_LEFT, + ANIM_KD_RIGHT, + ANIM_KO_SKID_FRONT, + ANIM_KO_SPIN_R, // named left in VC + ANIM_KO_SKID_BACK, + ANIM_KO_SPIN_L, // named right in VC + ANIM_SHOT_FRONT_PARTIAL, + ANIM_SHOT_LEFT_PARTIAL, + ANIM_SHOT_BACK_PARTIAL, + ANIM_SHOT_RIGHT_PARTIAL, + ANIM_HIT_FRONT, + ANIM_HIT_LEFT, + ANIM_HIT_BACK, + ANIM_HIT_RIGHT, + ANIM_FLOOR_HIT, + ANIM_HIT_BODYBLOW, + ANIM_HIT_CHEST, + ANIM_HIT_HEAD, + ANIM_HIT_WALK, + ANIM_HIT_WALL, + ANIM_FLOOR_HIT_F, + ANIM_HIT_BEHIND, + ANIM_PUNCH_R, + ANIM_KICK_FLOOR, + ANIM_WEAPON_BAT_H, + ANIM_WEAPON_BAT_V, + ANIM_WEAPON_HGUN_BODY, + ANIM_WEAPON_AK_BODY, + ANIM_WEAPON_PUMP, + ANIM_WEAPON_SNIPER, + ANIM_WEAPON_THROW, + ANIM_WEAPON_THROWU, + ANIM_WEAPON_START_THROW, + ANIM_BOMBER, + ANIM_HGUN_RELOAD, + ANIM_AK_RELOAD, + ANIM_FPS_PUNCH, + ANIM_FPS_BAT, + ANIM_FPS_UZI, + ANIM_FPS_PUMP, + ANIM_FPS_AK, + ANIM_FPS_M16, + ANIM_FPS_ROCKET, + ANIM_FIGHT_IDLE, + ANIM_FIGHT2_IDLE, + ANIM_FIGHT_SH_F, + ANIM_FIGHT_BODYBLOW, + ANIM_FIGHT_HEAD, + ANIM_FIGHT_KICK, + ANIM_FIGHT_KNEE, + ANIM_FIGHT_LHOOK, + ANIM_FIGHT_PUNCH, + ANIM_FIGHT_ROUNDHOUSE, + ANIM_FIGHT_LONGKICK, + ANIM_FIGHT_PPUNCH, + ANIM_CAR_JACKED_RHS, + ANIM_CAR_LJACKED_RHS, + ANIM_CAR_JACKED_LHS, + ANIM_CAR_LJACKED_LHS, + ANIM_CAR_QJACK, + ANIM_CAR_QJACKED, + ANIM_CAR_ALIGN_LHS, + ANIM_CAR_ALIGNHI_LHS, + ANIM_CAR_OPEN_LHS, + ANIM_CAR_DOORLOCKED_LHS, + ANIM_CAR_PULLOUT_LHS, + ANIM_CAR_PULLOUT_LOW_LHS, + ANIM_CAR_GETIN_LHS, + ANIM_CAR_GETIN_LOW_LHS, + ANIM_CAR_CLOSEDOOR_LHS, + ANIM_CAR_CLOSEDOOR_LOW_LHS, + ANIM_CAR_ROLLDOOR, + ANIM_CAR_ROLLDOOR_LOW, + ANIM_CAR_GETOUT_LHS, + ANIM_CAR_GETOUT_LOW_LHS, + ANIM_CAR_CLOSE_LHS, + ANIM_CAR_ALIGN_RHS, + ANIM_CAR_ALIGNHI_RHS, + ANIM_CAR_OPEN_RHS, + ANIM_CAR_DOORLOCKED_RHS, + ANIM_CAR_PULLOUT_RHS, + ANIM_CAR_PULLOUT_LOW_RHS, + ANIM_CAR_GETIN_RHS, + ANIM_CAR_GETIN_LOW_RHS, + ANIM_CAR_CLOSEDOOR_RHS, + ANIM_CAR_CLOSEDOOR_LOW_RHS, + ANIM_CAR_SHUFFLE_RHS, + ANIM_CAR_LSHUFFLE_RHS, + ANIM_CAR_SIT, + ANIM_CAR_LSIT, + ANIM_CAR_SITP, + ANIM_CAR_SITPLO, + ANIM_DRIVE_L, + ANIM_DRIVE_R, + ANIM_DRIVE_LOW_L, + ANIM_DRIVE_LOW_R, + ANIM_DRIVEBY_L, + ANIM_DRIVEBY_R, + ANIM_CAR_LB, + ANIM_DRIVE_BOAT, + ANIM_CAR_GETOUT_RHS, + ANIM_CAR_GETOUT_LOW_RHS, + ANIM_CAR_CLOSE_RHS, + ANIM_CAR_HOOKERTALK, + ANIM_COACH_OPEN_L, + ANIM_COACH_OPEN_R, + ANIM_COACH_IN_L, + ANIM_COACH_IN_R, + ANIM_COACH_OUT_L, + ANIM_TRAIN_GETIN, + ANIM_TRAIN_GETOUT, + ANIM_CAR_CRAWLOUT_RHS, + ANIM_CAR_CRAWLOUT_RHS2, + ANIM_VAN_OPEN_L, + ANIM_VAN_GETIN_L, + ANIM_VAN_CLOSE_L, + ANIM_VAN_GETOUT_L, + ANIM_VAN_OPEN, + ANIM_VAN_GETIN, + ANIM_VAN_CLOSE, + ANIM_VAN_GETOUT, + ANIM_GETUP1, + ANIM_GETUP2, + ANIM_GETUP3, + ANIM_GETUP_FRONT, + ANIM_JUMP_LAUNCH, + ANIM_JUMP_GLIDE, + ANIM_JUMP_LAND, + ANIM_FALL_FALL, + ANIM_FALL_GLIDE, + ANIM_FALL_LAND, + ANIM_FALL_COLLAPSE, + ANIM_EV_STEP, + ANIM_EV_DIVE, + ANIM_XPRESS_SCRATCH, + ANIM_ROAD_CROSS, + ANIM_TURN_180, + ANIM_ARREST_GUN, + ANIM_DROWN, + ANIM_CPR, + ANIM_DUCK_DOWN, + ANIM_DUCK_LOW, + ANIM_RBLOCK_CSHOOT, + ANIM_WEAPON_THROWU2, + ANIM_HANDSUP, + ANIM_HANDSCOWER, + ANIM_FUCKU, + ANIM_PHONE_IN, + ANIM_PHONE_OUT, + ANIM_PHONE_TALK, + + NUM_ANIMS +}; \ No newline at end of file diff --git a/src/audio/AudioCollision.cpp b/src/audio/AudioCollision.cpp index ac8e04c3..a963b293 100644 --- a/src/audio/AudioCollision.cpp +++ b/src/audio/AudioCollision.cpp @@ -226,7 +226,7 @@ cAudioManager::SetUpOneShotCollisionSound(cAudioCollision *col) if(s1 == SURFACE_METAL6 && s2 == SURFACE_FLESH) ratio = 0.25f * ratio; if(s1 == SURFACE_METAL6 && ratio < 0.6f) { s1 = SURFACE_BILLBOARD; - ratio = min(1.f, 2.f * ratio); + ratio = Min(1.f, 2.f * ratio); } emittingVol = 40.f * ratio; if(emittingVol) { diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 4d5f8474..f836f1c4 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -635,9 +635,9 @@ cAudioManager::ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float speedOfSource = (dist / m_bTimeSpent) * speedMultiplier; if(m_fSpeedOfSound > Abs(speedOfSource)) { if(speedOfSource < 0.0f) { - speedOfSource = max(speedOfSource, -1.5f); + speedOfSource = Max(speedOfSource, -1.5f); } else { - speedOfSource = min(speedOfSource, 1.5f); + speedOfSource = Min(speedOfSource, 1.5f); } newFreq = (oldFreq * m_fSpeedOfSound) / (speedOfSource + m_fSpeedOfSound); @@ -650,10 +650,10 @@ cAudioManager::ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, int32 cAudioManager::ComputePan(float dist, CVector *vec) { - int32 index = min(63, Abs(vec->x / (dist / 64.f))); + int32 index = Min(63, Abs(vec->x / (dist / 64.f))); - if(vec->x > 0.f) return max(20, 63 - panTable[index]); - return min(107, panTable[index] + 63); + if(vec->x > 0.f) return Max(20, 63 - panTable[index]); + return Min(107, panTable[index] + 63); } uint8 @@ -2894,7 +2894,7 @@ cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobil relativeVelChange = (gasPedalAudio - 0.4f) * 1.25f; } else if(wheelState == WHEEL_STATE_SKIDDING) { - relativeVelChange = min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); + relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); } else if(wheelState == WHEEL_STATE_FIXED) { modificator = 0.4f; relativeVelChange = gasPedalAudio; @@ -2905,7 +2905,7 @@ cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobil velChange = Abs(velocityChange); if(relativeVelChange > 0.4f) relativeVelChange = relativeVelChange * modificator; if(velChange > 0.04f) { - relativeVel = min(1.0f, velChange / transmission->fMaxVelocity); + relativeVel = Min(1.0f, velChange / transmission->fMaxVelocity); } else { relativeVel = 0.0f; } @@ -2914,7 +2914,7 @@ cAudioManager::GetVehicleDriveWheelSkidValue(uint8 wheel, CAutomobile *automobil relativeVelChange = 0.0f; } - return max(relativeVelChange, min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); + return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); } float @@ -2924,12 +2924,12 @@ cAudioManager::GetVehicleNonDriveWheelSkidValue(uint8 wheel, CAutomobile *automo float relativeVelChange; if(automobile->m_aWheelState[wheel] == 2) { - relativeVelChange = min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); + relativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity); } else { relativeVelChange = 0.0f; } - return max(relativeVelChange, min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); + return Max(relativeVelChange, Min(1.0f, Abs(automobile->m_vecTurnSpeed.z) * 20.0f)); } bool @@ -3326,7 +3326,7 @@ cAudioManager::ProcessActiveQueues() if(field_4) { emittingVol = 2 * - min(63, + Min(63, sample.m_bEmittingVolume); } else { emittingVol = @@ -3353,13 +3353,13 @@ cAudioManager::ProcessActiveQueues() if(sample.m_nFrequency <= m_asActiveSamples[j] .m_nFrequency) { - freq = max( + freq = Max( sample.m_nFrequency, m_asActiveSamples[j] .m_nFrequency - 6000); } else { - freq = min( + freq = Min( sample.m_nFrequency, m_asActiveSamples[j] .m_nFrequency + @@ -3376,14 +3376,14 @@ cAudioManager::ProcessActiveQueues() if(sample.m_bEmittingVolume <= m_asActiveSamples[j] .m_bEmittingVolume) { - vol = max( + vol = Max( m_asActiveSamples[j] .m_bEmittingVolume - 10, sample .m_bEmittingVolume); } else { - vol = min( + vol = Min( m_asActiveSamples[j] .m_bEmittingVolume + 10, @@ -3394,7 +3394,7 @@ cAudioManager::ProcessActiveQueues() uint8 emittingVol; if(field_4) { emittingVol = - 2 * min(63, vol); + 2 * Min(63, vol); } else { emittingVol = vol; } @@ -3461,7 +3461,7 @@ cAudioManager::ProcessActiveQueues() &position); if(field_4) { emittingVol = - 2 * min(63, m_asActiveSamples[j] + 2 * Min(63, m_asActiveSamples[j] .m_bEmittingVolume); } else { emittingVol = @@ -3783,7 +3783,7 @@ cAudioManager::ProcessBoatMovingOverWater(cVehicleParams *params) velocityChange = Abs(params->m_fVelocityChange); if(velocityChange <= 0.0005f && params->m_pVehicle->GetPosition().y) return true; - velocityChange = min(0.75f, velocityChange); + velocityChange = Min(0.75f, velocityChange); multiplier = (velocityChange - 0.0005f) * 1.3342f; CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); vol = (30.f * multiplier); @@ -5044,7 +5044,7 @@ void cAudioManager::ProcessJumboDecel(CPlane *plane) { if(SetupJumboFlySound(20) && SetupJumboTaxiSound(75)) { - const float modificator = min(1.f, (plane->m_fSpeed - 0.10334f) * 1.676f); + const float modificator = Min(1.f, (plane->m_fSpeed - 0.10334f) * 1.676f); SetupJumboEngineSound(maxVolume * modificator, 6050.f * modificator + 16000); SetupJumboWhineSound(18, 29500); } @@ -7259,7 +7259,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * CurrentPretendGear = 1; } if(CReplay::IsPlayingBack()) { - accelerateState = 255.f * max(0.0f, min(1.0f, automobile->m_fGasPedal)); + accelerateState = 255.f * Max(0.0f, Min(1.0f, automobile->m_fGasPedal)); } else { accelerateState = Pads->GetAccelerate(); } @@ -7268,7 +7268,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * velocityChange = params->m_fVelocityChange; relativeVelocityChange = 2.0f * velocityChange / transmission->fMaxVelocity; - accelerationMultipler = min(min(1.f, relativeVelocityChange), 0.f); + accelerationMultipler = Min(Min(1.f, relativeVelocityChange), 0.f); gasPedalAudio = accelerationMultipler; currentGear = params->m_pVehicle->m_nCurrentGear; @@ -7290,9 +7290,9 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * if(0.0f != velocityChange) { time = params->m_pVehicle->m_vecMoveSpeed.z / velocityChange; if(time <= 0.0f) { - freqModifier = max(-0.2f, time) * -15000.f; + freqModifier = Max(-0.2f, time) * -15000.f; } else { - freqModifier = -(min(0.2f, time) * 15000.f); + freqModifier = -(Min(0.2f, time) * 15000.f); } if(params->m_fVelocityChange < -0.001f) freqModifier = -freqModifier; } else { @@ -7311,10 +7311,10 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * gasPedalAudio = automobile->m_fGasPedalAudio; } else { gasPedalAudio = - min(1.0f, params->m_fVelocityChange / + Min(1.0f, params->m_fVelocityChange / params->m_pTransmission->fMaxReverseVelocity); } - gasPedalAudio = max(0.0f, gasPedalAudio); + gasPedalAudio = Max(0.0f, gasPedalAudio); automobile->m_fGasPedalAudio = gasPedalAudio; } else if(LastAccel > 0) { if(channelUsed) { @@ -7343,7 +7343,7 @@ cAudioManager::ProcessPlayersVehicleEngine(cVehicleParams *params, CAutomobile * AddPlayerCarSample(110 - (40.f * gasPedalAudio), freq, (engineSoundType + SFX_CAR_REV_10), 0, 52, 1); - CurrentPretendGear = max(1, currentGear); + CurrentPretendGear = Max(1, currentGear); LastAccel = accelerateState; bHandbrakeOnLastFrame = automobile->bIsHandbrakeOn; @@ -8005,7 +8005,7 @@ cAudioManager::ProcessTrainNoise(cVehicleParams *params) if(params->m_fVelocityChange > 0.0f) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); train = (CTrain *)params->m_pVehicle; - speedMultipler = min(1.0f, train->m_fSpeed * 250.f / 51.f); + speedMultipler = Min(1.0f, train->m_fSpeed * 250.f / 51.f); emittingVol = (75.f * speedMultipler); if(train->m_fWagonPosition == 0.0f) { m_sQueueSample.m_bVolume = @@ -8176,7 +8176,7 @@ cAudioManager::ProcessVehicleDoors(cVehicleParams *params) if(automobile->Damage.GetDoorStatus(i) == 2) { doorState = automobile->Doors[i].m_nDoorState; if(doorState == 1 || doorState == 2) { - velocity = min(0.3f, Abs(automobile->Doors[i].m_fAngVel)); + velocity = Min(0.3f, Abs(automobile->Doors[i].m_fAngVel)); if(velocity > 0.0035f) { emittingVol = (100.f * velocity * 10.f / 3.f); m_sQueueSample.m_bVolume = ComputeVolume( @@ -8599,7 +8599,7 @@ cAudioManager::ProcessVehicleOneShots(cVehicleParams *params) m_sQueueSample.m_fSoundIntensity = 30.0f; break; case SOUND_CAR_JUMP: - emittingVol = max( + emittingVol = Max( 80.f, 2 * (100.f * m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i])); @@ -9081,7 +9081,7 @@ cAudioManager::ProcessVehicleRoadNoise(cVehicleParams *params) params->m_fDistance); emittingVol = 30.f * - min(1.f, + Min(1.f, velocity / (0.5f * params->m_pTransmission->fMaxVelocity)); m_sQueueSample.m_bVolume = ComputeVolume(emittingVol, 95.f, m_sQueueSample.m_fDistance); @@ -9397,7 +9397,7 @@ cAudioManager::ProcessWetRoadNoise(cVehicleParams *params) CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); relativeVelocity = - min(1.0f, + Min(1.0f, velChange / (0.5f * params->m_pTransmission->fMaxVelocity)); emittingVol = 23.0f * relativeVelocity * CWeather::WetRoads; m_sQueueSample.m_bVolume = @@ -10035,7 +10035,7 @@ cAudioManager::UpdateReflections() if(CWorld::ProcessVerticalLine( camPos, m_avecReflectionsPos[4].z, colpoint, ent, true, false, false, false, true, false, - false)) { + nil)) { m_afReflectionsDistances[4] = colpoint.point.z - camPos.z; } else { diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 9ce073b4..42688fa6 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -1,6 +1,7 @@ #pragma once #include "audio_enums.h" +#include "Crime.h" enum eSound : int16 { @@ -179,7 +180,6 @@ enum eSound : int16 class cAudioScriptObject; class CEntity; -enum eCrimeType; class cDMAudio { diff --git a/src/audio/MusicManager.cpp b/src/audio/MusicManager.cpp index 01b7df56..efea6e45 100644 --- a/src/audio/MusicManager.cpp +++ b/src/audio/MusicManager.cpp @@ -705,7 +705,7 @@ cMusicManager::GetTrackStartPos(uint8 track) result = m_aTracks[track].m_nPosition; m_aTracks[track].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode(); } else - result = min(CTimer::GetTimeInMillisecondsPauseMode() - timer, 90000) + m_aTracks[track].m_nPosition; + result = Min(CTimer::GetTimeInMillisecondsPauseMode() - timer, 90000) + m_aTracks[track].m_nPosition; if (result > m_aTracks[track].m_nLength) result %= m_aTracks[track].m_nLength; return result; diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index d24de27f..a375b847 100644 --- a/src/audio/sampman.cpp +++ b/src/audio/sampman.cpp @@ -1986,50 +1986,59 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) if ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER ) { uint32 i = 0; - - if ( !_bIsMp3Active ) goto FIND_MP3TRACK; - - do - { - if ( ++_CurMP3Index >= nNumMP3s ) - _CurMP3Index = 0; - - _CurMP3Pos = 0; - - tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); - - if ( mp3 ) - { - mp3 = _pMP3List; - if ( mp3 == NULL ) - { - _bIsMp3Active = false; - nFile = 0; - goto PLAY_STREAMEDTRACK; + do { + if(i != 0 || _bIsMp3Active) { + if(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0; + + _CurMP3Pos = 0; + + tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); + + if(mp3) { + mp3 = _pMP3List; + if(mp3 == NULL) { + _bIsMp3Active = false; + nFile = 0; + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count( + mp3Stream[nStream], 1); + AIL_set_stream_ms_position( + mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], + 0); + return true; + } + + return false; + } } + + if(mp3->pLinkPath != NULL) + mp3Stream[nStream] = + AIL_open_stream(DIG, mp3->pLinkPath, 0); + else { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, mp3->aFilename); + + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + } + + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], 0); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + _bIsMp3Active = false; + continue; } - - if ( mp3->pLinkPath != NULL ) - mp3Stream[nStream] = AIL_open_stream(DIG, mp3->pLinkPath, 0); - else - { - strcpy(filename, _mp3DirectoryPath); - strcat(filename, mp3->aFilename); - - mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); - } - - if ( mp3Stream[nStream] ) - { - AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_set_stream_ms_position(mp3Stream[nStream], 0); - AIL_pause_stream(mp3Stream[nStream], 0); - return true; - } - - goto NEXT_MP3TRACK; - -FIND_MP3TRACK: if ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] ) position = 0; @@ -2039,10 +2048,23 @@ FIND_MP3TRACK: if ( e == NULL ) { nFile = 0; - goto PLAY_STREAMEDTRACK; + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count( + mp3Stream[nStream], 1); + AIL_set_stream_ms_position( + mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + return false; } } - + if ( e->pLinkPath != NULL ) mp3Stream[nStream] = AIL_open_stream(DIG, e->pLinkPath, 0); else @@ -2064,17 +2086,14 @@ FIND_MP3TRACK: return true; } -NEXT_MP3TRACK: _bIsMp3Active = false; - - } while ( ++i < nNumMP3s ); - + + } while(++i < nNumMP3s); + position = 0; nFile = 0; - goto PLAY_STREAMEDTRACK; } -PLAY_STREAMEDTRACK: strcpy(filename, m_szCDRomRootPath); strcat(filename, StreamedNameTable[nFile]); diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index 3fc9b154..69511bc8 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -8,7 +8,7 @@ void CAutoPilot::ModifySpeed(float speed) { - m_fMaxTrafficSpeed = max(0.01f, speed); + m_fMaxTrafficSpeed = Max(0.01f, speed); float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo]; diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index 7c9a1ad4..a8e77fc2 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -374,7 +374,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 750; pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); if (pVehicle->VehicleCreatedBy == RANDOM_VEHICLE) - pVehicle->AutoPilot.m_nDrivingStyle = max(DRIVINGSTYLE_AVOID_CARS, pVehicle->AutoPilot.m_nDrivingStyle); + pVehicle->AutoPilot.m_nDrivingStyle = Max(DRIVINGSTYLE_AVOID_CARS, pVehicle->AutoPilot.m_nDrivingStyle); pVehicle->PlayCarHorn(); } } @@ -510,7 +510,7 @@ void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget) pTarget->RegisterReference((CEntity**)&pVehicle->AutoPilot.m_pTargetCar); pVehicle->AutoPilot.m_nCarMission = MISSION_RAMCAR_FARAWAY; pVehicle->bEngineOn = true; - pVehicle->AutoPilot.m_nCruiseSpeed = max(6, pVehicle->AutoPilot.m_nCruiseSpeed); + pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); } void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget) @@ -519,7 +519,7 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget) pTarget->RegisterReference((CEntity**)&pVehicle->AutoPilot.m_pTargetCar); pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKCAR_FARAWAY; pVehicle->bEngineOn = true; - pVehicle->AutoPilot.m_nCruiseSpeed = max(6, pVehicle->AutoPilot.m_nCruiseSpeed); + pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); } eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() { diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 827c97e7..ae38b68f 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -362,7 +362,7 @@ CCarCtrl::GenerateOneRandomCar() if (distanceBetweenNodes / 2 < carLength) positionBetweenNodes = 0.5f; else - positionBetweenNodes = min(1.0f - carLength / distanceBetweenNodes, max(carLength / distanceBetweenNodes, positionBetweenNodes)); + positionBetweenNodes = Min(1.0f - carLength / distanceBetweenNodes, Max(carLength / distanceBetweenNodes, positionBetweenNodes)); pCar->AutoPilot.m_nNextDirection = (curNodeId >= nextNodeId) ? 1 : -1; if (pCurNode->numLinks == 1){ /* Do not create vehicle if there is nowhere to go. */ @@ -804,10 +804,10 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle) float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER; float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER; float bottom = pVehicle->GetPosition().y + DISTANCE_TO_SCAN_FOR_DANGER; - int xstart = max(0, CWorld::GetSectorIndexX(left)); - int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right)); - int ystart = max(0, CWorld::GetSectorIndexY(top)); - int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom)); + int xstart = Max(0, CWorld::GetSectorIndexX(left)); + int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right)); + int ystart = Max(0, CWorld::GetSectorIndexY(top)); + int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom)); assert(xstart <= xend); assert(ystart <= yend); @@ -838,10 +838,10 @@ CCarCtrl::ScanForPedDanger(CVehicle* pVehicle) float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER; float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER; float bottom = pVehicle->GetPosition().y + DISTANCE_TO_SCAN_FOR_DANGER; - int xstart = max(0, CWorld::GetSectorIndexX(left)); - int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right)); - int ystart = max(0, CWorld::GetSectorIndexY(top)); - int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom)); + int xstart = Max(0, CWorld::GetSectorIndexX(left)); + int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right)); + int ystart = Max(0, CWorld::GetSectorIndexY(top)); + int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom)); assert(xstart <= xend); assert(ystart <= yend); @@ -873,12 +873,12 @@ CCarCtrl::SlowCarOnRailsDownForTrafficAndLights(CVehicle* pVehicle) float curSpeed = pVehicle->AutoPilot.m_fMaxTrafficSpeed; if (maxSpeed >= curSpeed){ if (maxSpeed > curSpeed) - pVehicle->AutoPilot.ModifySpeed(min(maxSpeed, curSpeed + 0.05f * CTimer::GetTimeStep())); + pVehicle->AutoPilot.ModifySpeed(Min(maxSpeed, curSpeed + 0.05f * CTimer::GetTimeStep())); }else if (curSpeed != 0.0f) { if (curSpeed < 0.1f) pVehicle->AutoPilot.ModifySpeed(0.0f); else - pVehicle->AutoPilot.ModifySpeed(max(maxSpeed, curSpeed - 0.5f * CTimer::GetTimeStep())); + pVehicle->AutoPilot.ModifySpeed(Max(maxSpeed, curSpeed - 0.5f * CTimer::GetTimeStep())); } } @@ -979,7 +979,7 @@ void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList& lst, CVehicle* pVehicle, f if (distanceUntilHit < 10.0f){ if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_SLOW_DOWN_FOR_CARS){ - *pSpeed = min(*pSpeed, ABS(distanceUntilHit - 1.0f) * 0.1f * curSpeed); + *pSpeed = Min(*pSpeed, ABS(distanceUntilHit - 1.0f) * 0.1f * curSpeed); pVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds = true; if (distanceUntilHit < 2.0f){ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; @@ -1028,11 +1028,11 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float projectionY = speedOtherY - forwardA.y * curSpeed; float proximityA = TestCollisionBetween2MovingRects(pOtherVehicle, pVehicle, projectionX, projectionY, &forwardA, &forwardB, 0); float proximityB = TestCollisionBetween2MovingRects(pVehicle, pOtherVehicle, -projectionX, -projectionY, &forwardB, &forwardA, 1); - float minProximity = min(proximityA, proximityB); + float minProximity = Min(proximityA, proximityB); if (minProximity >= 0.0f && minProximity < 1.0f){ - minProximity = max(0.0f, (minProximity - 0.2f) * 1.25f); + minProximity = Max(0.0f, (minProximity - 0.2f) * 1.25f); pVehicle->AutoPilot.m_bSlowedDownBecauseOfCars = true; - *pSpeed = min(*pSpeed, minProximity * curSpeed); + *pSpeed = Min(*pSpeed, minProximity * curSpeed); } if (minProximity >= 0.0f && minProximity < 0.5f && pOtherEntity->IsVehicle() && CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 15000 && @@ -1041,7 +1041,7 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, if (pOtherEntity != FindPlayerVehicle() && DotProduct2D(pVehicle->GetForward(), pOtherVehicle->GetForward()) < 0.5f && pVehicle < pOtherVehicle){ /* that comparasion though... */ - *pSpeed = max(curSpeed / 5, *pSpeed); + *pSpeed = Max(curSpeed / 5, *pSpeed); if (pVehicle->m_status == STATUS_SIMPLE){ pVehicle->m_status = STATUS_PHYSICS; SwitchVehicleToRealPhysics(pVehicle); @@ -1097,7 +1097,7 @@ float CCarCtrl::TestCollisionBetween2MovingRects(CVehicle* pVehicleA, CVehicle* float proximityWidth = -(widthDistance - widthB) / widthProjection; if (proximityWidth < 1.0f){ baseWidthProximity = proximityWidth; - fullWidthProximity = min(1.0f, proximityWidth - fullWidthB / widthProjection); + fullWidthProximity = Min(1.0f, proximityWidth - fullWidthB / widthProjection); }else{ baseWidthProximity = 1.0f; } @@ -1110,7 +1110,7 @@ float CCarCtrl::TestCollisionBetween2MovingRects(CVehicle* pVehicleA, CVehicle* float proximityWidth = -(widthDistance + widthB) / widthProjection; if (proximityWidth < 1.0f) { baseWidthProximity = proximityWidth; - fullWidthProximity = min(1.0f, proximityWidth + fullWidthB / widthProjection); + fullWidthProximity = Min(1.0f, proximityWidth + fullWidthB / widthProjection); } else { baseWidthProximity = 1.0f; @@ -1135,7 +1135,7 @@ float CCarCtrl::TestCollisionBetween2MovingRects(CVehicle* pVehicleA, CVehicle* float proximityLength = -(lenDistance - lenB) / lenProjection; if (proximityLength < 1.0f) { baseLengthProximity = proximityLength; - fullLengthProximity = min(1.0f, proximityLength - fullLenB / lenProjection); + fullLengthProximity = Min(1.0f, proximityLength - fullLenB / lenProjection); } else { baseLengthProximity = 1.0f; @@ -1151,7 +1151,7 @@ float CCarCtrl::TestCollisionBetween2MovingRects(CVehicle* pVehicleA, CVehicle* float proximityLength = -(lenDistance + backLenB) / lenProjection; if (proximityLength < 1.0f) { baseLengthProximity = proximityLength; - fullLengthProximity = min(1.0f, proximityLength + fullLenB / lenProjection); + fullLengthProximity = Min(1.0f, proximityLength + fullLenB / lenProjection); } else { baseLengthProximity = 1.0f; @@ -1168,24 +1168,24 @@ float CCarCtrl::TestCollisionBetween2MovingRects(CVehicle* pVehicleA, CVehicle* else if (lenProjection < 0.0f) { fullLengthProximity = -(backLenB + lenDistance) / lenProjection; } - float baseProximity = max(baseWidthProximity, baseLengthProximity); + float baseProximity = Max(baseWidthProximity, baseLengthProximity); if (baseProximity < fullWidthProximity && baseProximity < fullLengthProximity) - proximity = min(proximity, baseProximity); + proximity = Min(proximity, baseProximity); } return proximity; } float CCarCtrl::FindAngleToWeaveThroughTraffic(CVehicle* pVehicle, CPhysical* pTarget, float angleToTarget, float angleForward) { - float distanceToTest = min(2.0f, pVehicle->GetMoveSpeed().Magnitude2D() * 2.5f + 1.0f) * 12.0f; + float distanceToTest = Min(2.0f, pVehicle->GetMoveSpeed().Magnitude2D() * 2.5f + 1.0f) * 12.0f; float left = pVehicle->GetPosition().x - distanceToTest; float right = pVehicle->GetPosition().x + distanceToTest; float top = pVehicle->GetPosition().y - distanceToTest; float bottom = pVehicle->GetPosition().y + distanceToTest; - int xstart = max(0, CWorld::GetSectorIndexX(left)); - int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right)); - int ystart = max(0, CWorld::GetSectorIndexY(top)); - int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom)); + int xstart = Max(0, CWorld::GetSectorIndexX(left)); + int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right)); + int ystart = Max(0, CWorld::GetSectorIndexY(top)); + int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom)); assert(xstart <= xend); assert(ystart <= yend); @@ -1566,8 +1566,8 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) pVehicle->AutoPilot.m_nNextLane -= 1; } } - pVehicle->AutoPilot.m_nNextLane = min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane); - pVehicle->AutoPilot.m_nNextLane = max(0, pVehicle->AutoPilot.m_nNextLane); + pVehicle->AutoPilot.m_nNextLane = Min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane); + pVehicle->AutoPilot.m_nNextLane = Max(0, pVehicle->AutoPilot.m_nNextLane); }else{ pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane; } @@ -1595,7 +1595,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) if (pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve < 10) /* Oh hey there Obbe */ printf("fout\n"); - pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = Max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); } uint8 CCarCtrl::FindPathDirection(int32 prevNode, int32 curNode, int32 nextNode) @@ -1746,8 +1746,8 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t pVehicle->AutoPilot.m_nNextLane -= 1; } } - pVehicle->AutoPilot.m_nNextLane = min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane); - pVehicle->AutoPilot.m_nNextLane = max(0, pVehicle->AutoPilot.m_nNextLane); + pVehicle->AutoPilot.m_nNextLane = Min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane); + pVehicle->AutoPilot.m_nNextLane = Max(0, pVehicle->AutoPilot.m_nNextLane); } else { pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane; @@ -1773,7 +1773,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t directionCurrentLinkX, directionCurrentLinkY, directionNextLinkX, directionNextLinkY ) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed); - pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = Max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); } bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) @@ -1826,8 +1826,8 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) else pVehicle->AutoPilot.m_nNextLane -= 1; } - pVehicle->AutoPilot.m_nNextLane = min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane); - pVehicle->AutoPilot.m_nNextLane = max(0, pVehicle->AutoPilot.m_nNextLane); + pVehicle->AutoPilot.m_nNextLane = Min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane); + pVehicle->AutoPilot.m_nNextLane = Max(0, pVehicle->AutoPilot.m_nNextLane); } else { pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane; @@ -1853,7 +1853,7 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) directionCurrentLinkX, directionCurrentLinkY, directionNextLinkX, directionNextLinkY ) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed); - pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = Max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); return false; } @@ -1965,7 +1965,7 @@ float CCarCtrl::FindSpeedMultiplier(float angleChange, float minAngle, float max { float angle = Abs(LimitRadianAngle(angleChange)); float n = angle - minAngle; - n = max(0.0f, n); + n = Max(0.0f, n); float d = maxAngle - minAngle; float mult = 1.0f - n / d * (1.0f - coef); if (n > d) @@ -2252,9 +2252,9 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv angleCurrentLink = FindAngleToWeaveThroughTraffic(pVehicle, nil, angleCurrentLink, angleForward); float steerAngle = LimitRadianAngle(angleCurrentLink - angleForward); float maxAngle = FindMaxSteerAngle(pVehicle); - steerAngle = min(maxAngle, max(-maxAngle, steerAngle)); + steerAngle = Min(maxAngle, Max(-maxAngle, steerAngle)); if (pVehicle->GetMoveSpeed().Magnitude() > MIN_SPEED_TO_START_LIMITING_STEER) - steerAngle = min(MAX_ANGLE_TO_STEER_AT_HIGH_SPEED, max(-MAX_ANGLE_TO_STEER_AT_HIGH_SPEED, steerAngle)); + steerAngle = Min(MAX_ANGLE_TO_STEER_AT_HIGH_SPEED, Max(-MAX_ANGLE_TO_STEER_AT_HIGH_SPEED, steerAngle)); float currentForwardSpeed = DotProduct(pVehicle->GetMoveSpeed(), pVehicle->GetForward()) * GAME_SPEED_TO_CARAI_SPEED; float speedStyleMultiplier; switch (pVehicle->AutoPilot.m_nDrivingStyle) { @@ -2298,21 +2298,21 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv speedNodesMultiplier = 1.0f - (1.0f - scalarDistanceToNextNode / DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN) * (1.0f - tmpWideMultiplier); - float speedMultiplier = min(speedStyleMultiplier, min(speedAngleMultiplier, speedNodesMultiplier)); + float speedMultiplier = Min(speedStyleMultiplier, Min(speedAngleMultiplier, speedNodesMultiplier)); float speed = pVehicle->AutoPilot.m_nCruiseSpeed * speedMultiplier; float speedDifference = speed - currentForwardSpeed; if (speed < 0.05f && speedDifference < 0.03f){ *pBrake = 1.0f; *pAccel = 0.0f; }else if (speedDifference <= 0.0f){ - *pBrake = min(0.5f, -speedDifference * 0.05f); + *pBrake = Min(0.5f, -speedDifference * 0.05f); *pAccel = 0.0f; }else if (currentForwardSpeed < 2.0f){ *pBrake = 0.0f; - *pAccel = min(1.0f, speedDifference * 0.25f); + *pAccel = Min(1.0f, speedDifference * 0.25f); }else{ *pBrake = 0.0f; - *pAccel = min(1.0f, speedDifference * 0.125f); + *pAccel = Min(1.0f, speedDifference * 0.125f); } *pSwerve = steerAngle; *pHandbrake = false; @@ -2332,7 +2332,7 @@ void CCarCtrl::SteerAICarWithPhysicsHeadingForTarget(CVehicle* pVehicle, CPhysic if (ABS(steerAngle) > MIN_ANGLE_TO_APPLY_HANDBRAKE) *pHandbrake = true; float maxAngle = FindMaxSteerAngle(pVehicle); - steerAngle = min(maxAngle, max(-maxAngle, steerAngle)); + steerAngle = Min(maxAngle, Max(-maxAngle, steerAngle)); float speedMultiplier = FindSpeedMultiplier(angleToTarget - angleForward, MIN_ANGLE_FOR_SPEED_LIMITING, MAX_ANGLE_FOR_SPEED_LIMITING, MIN_LOWERING_SPEED_COEFFICIENT); float speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed * speedMultiplier; @@ -2340,9 +2340,9 @@ void CCarCtrl::SteerAICarWithPhysicsHeadingForTarget(CVehicle* pVehicle, CPhysic float speedDiff = speedTarget - currentSpeed; if (speedDiff <= 0.0f){ *pAccel = 0.0f; - *pBrake = min(0.5f, -speedDiff * 0.05f); + *pBrake = Min(0.5f, -speedDiff * 0.05f); }else if (currentSpeed < 25.0f){ - *pAccel = min(1.0f, speedDiff * 0.1f); + *pAccel = Min(1.0f, speedDiff * 0.1f); *pBrake = 0.0f; }else{ *pAccel = 1.0f; @@ -2414,7 +2414,7 @@ void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CBoat* pBoat, float target float angleToTarget = CGeneral::GetATanOfXY(distanceToTarget.x, distanceToTarget.y); float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y); float angleDiff = LimitRadianAngle(angleToTarget - angleForward); - angleDiff = min(DEFAULT_MAX_STEER_ANGLE, max(-DEFAULT_MAX_STEER_ANGLE, angleDiff)); + angleDiff = Min(DEFAULT_MAX_STEER_ANGLE, Max(-DEFAULT_MAX_STEER_ANGLE, angleDiff)); float currentSpeed = pBoat->GetMoveSpeed().Magnitude2D(); // +0.0f for some reason float speedDiff = pBoat->AutoPilot.m_nCruiseSpeed - currentSpeed * 60.0f; if (speedDiff > 0.0f){ diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index e81d4112..cfd58340 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -284,7 +284,7 @@ CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 mode if (FindPlayerVehicle()) { player->m_currentWeapon = player->m_nSelectedWepSlot; - player->GetWeapon()->m_nAmmoInClip = min(player->GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition); + player->GetWeapon()->m_nAmmoInClip = Min(player->GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition); player->ClearWeaponTarget(); } } diff --git a/src/control/Darkel.h b/src/control/Darkel.h index b6092dcb..14529c63 100644 --- a/src/control/Darkel.h +++ b/src/control/Darkel.h @@ -1,9 +1,10 @@ #pragma once + #include "ModelIndices.h" +#include "WeaponType.h" class CVehicle; class CPed; -enum eWeaponType; enum { diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp index e7f642fe..f8c8fa69 100644 --- a/src/control/GameLogic.cpp +++ b/src/control/GameLogic.cpp @@ -93,7 +93,7 @@ CGameLogic::Update() if (pPlayerInfo.m_bGetOutOfHospitalFree) { pPlayerInfo.m_bGetOutOfHospitalFree = false; } else { - pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000); + pPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - 1000); pPlayerInfo.m_pPed->ClearWeapons(); } @@ -163,7 +163,7 @@ CGameLogic::Update() if (pPlayerInfo.m_bGetOutOfJailFree) { pPlayerInfo.m_bGetOutOfJailFree = false; } else { - pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney); + pPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - takeMoney); pPlayerInfo.m_pPed->ClearWeapons(); } diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 1ee8f99c..a4aa3729 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -206,12 +206,12 @@ int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z return NumGarages++; } CGarage* pGarage = &aGarages[NumGarages]; - pGarage->m_fX1 = min(X1, X2); - pGarage->m_fX2 = max(X1, X2); - pGarage->m_fY1 = min(Y1, Y2); - pGarage->m_fY2 = max(Y1, Y2); - pGarage->m_fZ1 = min(Z1, Z2); - pGarage->m_fZ2 = max(Z1, Z2); + pGarage->m_fX1 = Min(X1, X2); + pGarage->m_fX2 = Max(X1, X2); + pGarage->m_fY1 = Min(Y1, Y2); + pGarage->m_fY2 = Max(Y1, Y2); + pGarage->m_fZ1 = Min(Z1, Z2); + pGarage->m_fZ2 = Max(Z1, Z2); pGarage->m_pDoor1 = nil; pGarage->m_pDoor2 = nil; pGarage->m_fDoor1Z = Z1; @@ -361,7 +361,7 @@ void CGarage::Update() } break; case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_RESPRAY; @@ -440,7 +440,7 @@ void CGarage::Update() } if (bTakeMoney) { if (!CGarages::RespraysAreFree) - CWorld::Players[CWorld::PlayerInFocus].m_nMoney = max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - RESPRAY_PRICE); + CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - RESPRAY_PRICE); CGarages::TriggerMessage("GA_2", -1, 4000, -1); // New engine and paint job. The cops won't recognize you! } else if (bChangedColour) { @@ -458,7 +458,7 @@ void CGarage::Update() m_fY2 + DISTANCE_TO_CALL_OFF_CHASE); break; case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENEDCONTAINSCAR; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -503,7 +503,7 @@ void CGarage::Update() } break; case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_SETUP_BOMB; @@ -520,7 +520,7 @@ void CGarage::Update() } m_eGarageState = GS_OPENING; if (!CGarages::BombsAreFree) - CWorld::Players[CWorld::PlayerInFocus].m_nMoney = max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE); + CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE); if (FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) { ((CAutomobile*)(FindPlayerVehicle()))->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType); ((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed(); @@ -562,7 +562,7 @@ void CGarage::Update() } break; case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENEDCONTAINSCAR; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -597,7 +597,7 @@ void CGarage::Update() } break; case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); if (m_bClosingWithoutTargetCar) @@ -626,7 +626,7 @@ void CGarage::Update() } break; case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -663,7 +663,7 @@ void CGarage::Update() } break; case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); @@ -710,7 +710,7 @@ void CGarage::Update() m_pTarget = FindPlayerVehicle(); m_pTarget->RegisterReference((CEntity**)&m_pTarget); } - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -759,7 +759,7 @@ void CGarage::Update() } break; case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); @@ -799,7 +799,7 @@ void CGarage::Update() m_pTarget = FindPlayerVehicle(); m_pTarget->RegisterReference((CEntity**)&m_pTarget); } - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -820,7 +820,7 @@ void CGarage::Update() m_eGarageState = GS_CLOSING; break; case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); @@ -831,7 +831,7 @@ void CGarage::Update() case GS_FULLYCLOSED: break; case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -865,7 +865,7 @@ void CGarage::Update() } case GS_CLOSING: if (m_pTarget) { - m_fDoorPos = max(0.0f, m_fDoorPos - CRUSHER_CRANE_SPEED * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - CRUSHER_CRANE_SPEED * CTimer::GetTimeStep()); if (m_fDoorPos < TWOPI / 5) { m_pTarget->bUsesCollision = false; m_pTarget->bAffectedByGravity = false; @@ -876,7 +876,7 @@ void CGarage::Update() } if (m_fDoorPos == 0.0f) { CGarages::CrushedCarId = CPools::GetVehiclePool()->GetIndex(m_pTarget); - float reward = min(CRUSHER_MAX_REWARD, CRUSHER_MIN_REWARD + m_pTarget->pHandling->nMonetaryValue * m_pTarget->m_fHealth * CRUSHER_REWARD_COEFFICIENT); + float reward = Min(CRUSHER_MAX_REWARD, CRUSHER_MIN_REWARD + m_pTarget->pHandling->nMonetaryValue * m_pTarget->m_fHealth * CRUSHER_REWARD_COEFFICIENT); CWorld::Players[CWorld::PlayerInFocus].m_nMoney += reward; DestroyVehicleAndDriverAndPassengers(m_pTarget); ++CStats::CarsCrushed; @@ -900,7 +900,7 @@ void CGarage::Update() } break; case GS_OPENING: - m_fDoorPos = min(HALFPI, m_fDoorPos + CTimer::GetTimeStep() * CRUSHER_CRANE_SPEED); + m_fDoorPos = Min(HALFPI, m_fDoorPos + CTimer::GetTimeStep() * CRUSHER_CRANE_SPEED); if (m_fDoorPos == HALFPI) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -933,7 +933,7 @@ void CGarage::Update() } break; case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); if (m_bClosingWithoutTargetCar) @@ -961,7 +961,7 @@ void CGarage::Update() m_eGarageState = GS_OPENING; break; case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -981,7 +981,7 @@ void CGarage::Update() case GARAGE_FOR_SCRIPT_TO_OPEN: switch (m_eGarageState) { case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -1001,7 +1001,7 @@ void CGarage::Update() case GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE: switch (m_eGarageState) { case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); @@ -1009,7 +1009,7 @@ void CGarage::Update() UpdateDoorsHeight(); break; case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -1050,7 +1050,7 @@ void CGarage::Update() break; } case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (!IsPlayerOutsideGarage()) m_eGarageState = GS_OPENING; else if (m_fDoorPos == 0.0f) { @@ -1096,7 +1096,7 @@ void CGarage::Update() break; } case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -1121,7 +1121,7 @@ void CGarage::Update() } break; case GS_CLOSING: - m_fDoorPos = max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == 0.0f) { m_eGarageState = GS_FULLYCLOSED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f); @@ -1137,7 +1137,7 @@ void CGarage::Update() m_eGarageState = GS_OPENING; break; case GS_OPENING: - m_fDoorPos = min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); + m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep()); if (m_fDoorPos == m_fDoorHeight) { m_eGarageState = GS_OPENED; DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f); @@ -1695,17 +1695,17 @@ float CGarage::CalcSmallestDistToGarageDoorSquared(float X, float Y) dist1 = SQR(m_fDoor1X - X) + SQR(m_fDoor1Y - Y); if (m_pDoor2) dist2 = SQR(m_fDoor2X - X) + SQR(m_fDoor2Y - Y); - return min(dist1, dist2); + return Min(dist1, dist2); } void CGarage::FindDoorsEntities() { m_pDoor1 = nil; m_pDoor2 = nil; - int xstart = max(0, CWorld::GetSectorIndexX(m_fX1)); - int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2)); - int ystart = max(0, CWorld::GetSectorIndexY(m_fY1)); - int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fY2)); + int xstart = Max(0, CWorld::GetSectorIndexX(m_fX1)); + int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2)); + int ystart = Max(0, CWorld::GetSectorIndexY(m_fY1)); + int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fY2)); assert(xstart <= xend); assert(ystart <= yend); @@ -1891,7 +1891,7 @@ void CGarage::StoreAndRemoveCarsForThisHideout(CStoredCar* aCars, int32 nMax) pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 && pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2) { if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) { - if (index < max(NUM_GARAGE_STORED_CARS, nMax) && !EntityHasASphereWayOutsideGarage(pVehicle, 1.0f)) + if (index < Max(NUM_GARAGE_STORED_CARS, nMax) && !EntityHasASphereWayOutsideGarage(pVehicle, 1.0f)) aCars[index++].StoreCar(pVehicle); CWorld::Players[CWorld::PlayerInFocus].CancelPlayerEnteringCars(pVehicle); CWorld::Remove(pVehicle); diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 9d0959a8..44062b38 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -55,10 +55,10 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe } CWorld::AdvanceCurrentScanCode(); if (pathType != ROUTE_NO_BLOCKADE) { - const int32 nStartX = max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); - const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); - const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); - const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); + const int32 nStartX = Max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); + const int32 nStartY = Max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); + const int32 nEndX = Min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = Min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); for (int32 y = nStartY; y <= nEndY; y++) { for (int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = CWorld::GetSector(x, y); @@ -397,8 +397,8 @@ CPathFind::PreparePathData(void) numExtern++; if(InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes > numLanes) numLanes = InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes; - maxX = max(maxX, Abs(InfoForTileCars[k].x)); - maxY = max(maxY, Abs(InfoForTileCars[k].y)); + maxX = Max(maxX, Abs(InfoForTileCars[k].x)); + maxY = Max(maxY, Abs(InfoForTileCars[k].y)); }else if(InfoForTileCars[k].type == NodeTypeIntern) numIntern++; } @@ -582,7 +582,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor if(Abs(dx) < nearestDist){ dy = tempnodes[k].pos.y - CoorsXFormed.y; if(Abs(dy) < nearestDist){ - nearestDist = max(Abs(dx), Abs(dy)); + nearestDist = Max(Abs(dx), Abs(dy)); nearestId = k; } } @@ -691,13 +691,13 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor // Find i inside path segment iseg = 0; - for(j = max(oldNumPathNodes, i-12); j < i; j++) + for(j = Max(oldNumPathNodes, i-12); j < i; j++) if(m_pathNodes[j].objectIndex == m_pathNodes[i].objectIndex) iseg++; istart = 12*m_mapObjects[m_pathNodes[i].objectIndex]->m_modelIndex; // Add links to other internal nodes - for(j = max(oldNumPathNodes, i-12); j < min(m_numPathNodes, i+12); j++){ + for(j = Max(oldNumPathNodes, i-12); j < Min(m_numPathNodes, i+12); j++){ if(m_pathNodes[i].objectIndex != m_pathNodes[j].objectIndex || i == j) continue; // N.B.: in every path segment, the externals have to be at the end @@ -1466,8 +1466,11 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta targetNode = FindNodeClosestToCoors(target, type, distLimit); else targetNode = forcedTargetNode; - if(targetNode < 0) - goto fail; + if(targetNode < 0) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } // Find start int numPathsToTry; @@ -1486,19 +1489,28 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta numPathsToTry = 1; startObj = m_mapObjects[m_pathNodes[startNodeId].objectIndex]; } - if(numPathsToTry == 0) - goto fail; + if(numPathsToTry == 0) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } if(startNodeId < 0){ // why only check node 0? - if(m_pathNodes[startObj->m_nodeIndices[type][0]].group != m_pathNodes[targetNode].group) - goto fail; + if(m_pathNodes[startObj->m_nodeIndices[type][0]].group != + m_pathNodes[targetNode].group) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } }else{ - if(m_pathNodes[startNodeId].group != m_pathNodes[targetNode].group) - goto fail; + if(m_pathNodes[startNodeId].group != m_pathNodes[targetNode].group) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } } - for(i = 0; i < 512; i++) m_searchNodes[i].next = nil; AddNodeToList(&m_pathNodes[targetNode], 0); @@ -1576,11 +1588,6 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta for(i = 0; i < numNodesToBeCleared; i++) apNodesToBeCleared[i]->distance = MAX_DIST; return; - -fail: - *pNumNodes = 0; - if(pDist) - *pDist = 100000.0f; } static CPathNode *pNodeList[32]; diff --git a/src/control/Record.cpp b/src/control/Record.cpp index 6687cbff..b9e8f8da 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -296,7 +296,7 @@ void CRecordDataForChase::SaveOrRetrieveCarPositions(void) case STATE_PLAYBACK: { TimeMultiplier += CTimer::GetTimeStepNonClippedInSeconds(); - float EndOfFrameTime = CHASE_SCENE_FRAMES_PER_SECOND * min(CHASE_SCENE_LENGTH_IN_SECONDS, TimeMultiplier); + float EndOfFrameTime = CHASE_SCENE_FRAMES_PER_SECOND * Min(CHASE_SCENE_LENGTH_IN_SECONDS, TimeMultiplier); for (int i = 0; i < NUM_CHASE_CARS; i++) { if (!pBaseMemForCar[i]) continue; @@ -371,7 +371,7 @@ void CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFram else pCar->GetModelInfo()->ChooseVehicleColour(pCar->m_currentColour1, pCar->m_currentColour2); } - pCar->m_fHealth = min(pCar->m_fHealth, 500.0f); + pCar->m_fHealth = Min(pCar->m_fHealth, 500.0f); if (stop) { pCar->m_fGasPedal = 0.0f; pCar->m_fBrakePedal = 0.0f; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 466aa25e..d37e98cf 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -681,9 +681,9 @@ void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) vp->health = vehicle->m_fHealth / 4.0f; /* Not anticipated that health can be > 1000. */ vp->acceleration = vehicle->m_fGasPedal * 100.0f; vp->panels = vehicle->IsCar() ? ((CAutomobile*)vehicle)->Damage.m_panelStatus : 0; - vp->velocityX = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetMoveSpeed().x)); /* 8000!? */ - vp->velocityY = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetMoveSpeed().y)); - vp->velocityZ = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetMoveSpeed().z)); + vp->velocityX = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().x)); /* 8000!? */ + vp->velocityY = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().y)); + vp->velocityZ = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().z)); vp->mi = vehicle->GetModelIndex(); vp->primary_color = vehicle->m_currentColour1; vp->secondary_color = vehicle->m_currentColour2; @@ -1512,9 +1512,9 @@ void CReplay::ProcessLookAroundCam(void) --FramesActiveLookAroundCam; fBetaAngleLookAroundCam += x_moved; if (CPad::NewMouseControllerState.LMB && CPad::NewMouseControllerState.RMB) - fDistanceLookAroundCam = max(3.0f, min(15.0f, fDistanceLookAroundCam + 2.0f * y_moved)); + fDistanceLookAroundCam = Max(3.0f, Min(15.0f, fDistanceLookAroundCam + 2.0f * y_moved)); else - fAlphaAngleLookAroundCam = max(0.1f, min(1.5f, fAlphaAngleLookAroundCam + y_moved)); + fAlphaAngleLookAroundCam = Max(0.1f, Min(1.5f, fAlphaAngleLookAroundCam + y_moved)); CVector camera_pt( fDistanceLookAroundCam * Sin(fBetaAngleLookAroundCam) * Cos(fAlphaAngleLookAroundCam), fDistanceLookAroundCam * Cos(fBetaAngleLookAroundCam) * Cos(fAlphaAngleLookAroundCam), diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index 571b526a..7f914a76 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -569,7 +569,7 @@ void CSceneEdit::ProcessCommand(void) pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS; pActors[m_nActor]->m_pMyVehicle->m_status = STATUS_PHYSICS; pActors[m_nActor]->m_pMyVehicle->bEngineOn = true; - pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed); + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = Max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed); pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); TheCamera.TakeControl(pActors[m_nActor]->m_pMyVehicle, CCam::MODE_BEHINDCAR, JUMP_CUT, CAMCONTROL_SCRIPT); } @@ -847,7 +847,7 @@ void CSceneEdit::PlayBack(void) pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS; pActors[m_nActor]->m_pMyVehicle->m_status = STATUS_PHYSICS; pActors[m_nActor]->m_pMyVehicle->bEngineOn = true; - pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed); + pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = Max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed); pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); if (m_nCurrentCommand != MOVIE_GOTO_WAIT) ++m_nCurrentMovieCommand; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index bfe2de34..ca676f52 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -5,6 +5,7 @@ #include "Script.h" #include "ScriptCommands.h" +#include "AnimBlendAssociation.h" #include "Boat.h" #include "BulletInfo.h" #include "Camera.h" @@ -18,11 +19,12 @@ #include "Cranes.h" #include "Credits.h" #include "CutsceneMgr.h" -#include "Darkel.h" #include "DMAudio.h" +#include "Darkel.h" #include "EmergencyPed.h" #include "Explosion.h" #include "FileMgr.h" +#include "Fire.h" #include "Frontend.h" #include "Gangs.h" #include "Garages.h" @@ -31,7 +33,6 @@ #include "Heli.h" #include "Hud.h" #include "Lines.h" -#include "main.h" #include "Messages.h" #include "ModelIndices.h" #include "Pad.h" @@ -48,13 +49,12 @@ #include "Population.h" #include "PowerPoints.h" #include "ProjectileInfo.h" +#include "Radar.h" #include "Record.h" #include "Remote.h" -#include "Restart.h" #include "Replay.h" +#include "Restart.h" #include "RpAnimBlend.h" -#include "AnimBlendAssociation.h" -#include "Fire.h" #include "Rubbish.h" #include "Shadows.h" #include "SpecialFX.h" @@ -67,7 +67,7 @@ #include "Weather.h" #include "World.h" #include "Zones.h" -#include "Radar.h" +#include "main.h" #define PICKUP_PLACEMENT_OFFSET 0.5f #define PED_FIND_Z_OFFSET 5.0f @@ -2010,7 +2010,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) car->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS; car->m_status = STATUS_PHYSICS; car->bEngineOn = true; - car->AutoPilot.m_nCruiseSpeed = max(car->AutoPilot.m_nCruiseSpeed, 6); + car->AutoPilot.m_nCruiseSpeed = Max(car->AutoPilot.m_nCruiseSpeed, 6); car->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); return 0; } @@ -2022,7 +2022,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) CCarCtrl::JoinCarWithRoadSystem(car); car->AutoPilot.m_nCarMission = MISSION_CRUISE; car->bEngineOn = true; - car->AutoPilot.m_nCruiseSpeed = max(car->AutoPilot.m_nCruiseSpeed, 6); + car->AutoPilot.m_nCruiseSpeed = Max(car->AutoPilot.m_nCruiseSpeed, 6); car->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); return 0; } @@ -2106,7 +2106,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) CollectParameters(&m_nIp, 2); CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(car); - car->AutoPilot.m_nCruiseSpeed = min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fUnkMaxVelocity); + car->AutoPilot.m_nCruiseSpeed = Min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fUnkMaxVelocity); return 0; } case COMMAND_SET_CAR_DRIVING_STYLE: @@ -3645,7 +3645,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pos.x = (infX + supX) / 2; pos.y = (infY + supY) / 2; pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = max(pos.x - infX, pos.y - infY); + float radius = Max(pos.x - infX, pos.y - infY); pPed->bScriptObjectiveCompleted = false; pPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos, radius); return 0; @@ -4151,7 +4151,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pos.x = (infX + supX) / 2; pos.y = (infY + supY) / 2; pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = max(pos.x - infX, pos.y - infY); + float radius = Max(pos.x - infX, pos.y - infY); pPed->bScriptObjectiveCompleted = false; pPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius); return 0; @@ -4947,7 +4947,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) pos.x = (infX + supX) / 2; pos.y = (infY + supY) / 2; pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = max(pos.x - infX, pos.y - infY); + float radius = Max(pos.x - infX, pos.y - infY); pPed->bScriptObjectiveCompleted = false; pPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos, radius); return 0; @@ -5369,7 +5369,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) pos.x = (infX + supX) / 2; pos.y = (infY + supY) / 2; pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float radius = max(pos.x - infX, pos.y - infY); + float radius = Max(pos.x - infX, pos.y - infY); pPed->bScriptObjectiveCompleted = false; pPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius); return 0; @@ -5606,7 +5606,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE; pVehicle->m_status = STATUS_PHYSICS; pVehicle->bEngineOn = true; - pVehicle->AutoPilot.m_nCruiseSpeed = max(6, pVehicle->AutoPilot.m_nCruiseSpeed); + pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); return 0; } @@ -5721,7 +5721,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS; pBoat->AutoPilot.m_vecDestinationCoors = pos; pBoat->m_status = STATUS_PHYSICS; - pBoat->AutoPilot.m_nCruiseSpeed = max(6, pBoat->AutoPilot.m_nCruiseSpeed); + pBoat->AutoPilot.m_nCruiseSpeed = Max(6, pBoat->AutoPilot.m_nCruiseSpeed); pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); return 0; } @@ -6306,23 +6306,23 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) return 0; case COMMAND_REGISTER_JUMP_DISTANCE: CollectParameters(&m_nIp, 1); - CStats::MaximumJumpDistance = max(CStats::MaximumJumpDistance, *(float*)&ScriptParams[0]); + CStats::MaximumJumpDistance = Max(CStats::MaximumJumpDistance, *(float*)&ScriptParams[0]); return 0; case COMMAND_REGISTER_JUMP_HEIGHT: CollectParameters(&m_nIp, 1); - CStats::MaximumJumpHeight = max(CStats::MaximumJumpHeight, *(float*)&ScriptParams[0]); + CStats::MaximumJumpHeight = Max(CStats::MaximumJumpHeight, *(float*)&ScriptParams[0]); return 0; case COMMAND_REGISTER_JUMP_FLIPS: CollectParameters(&m_nIp, 1); - CStats::MaximumJumpFlips = max(CStats::MaximumJumpFlips, ScriptParams[0]); + CStats::MaximumJumpFlips = Max(CStats::MaximumJumpFlips, ScriptParams[0]); return 0; case COMMAND_REGISTER_JUMP_SPINS: CollectParameters(&m_nIp, 1); - CStats::MaximumJumpSpins = max(CStats::MaximumJumpSpins, ScriptParams[0]); + CStats::MaximumJumpSpins = Max(CStats::MaximumJumpSpins, ScriptParams[0]); return 0; case COMMAND_REGISTER_JUMP_STUNT: CollectParameters(&m_nIp, 1); - CStats::BestStuntJump = max(CStats::BestStuntJump, ScriptParams[0]); + CStats::BestStuntJump = Max(CStats::BestStuntJump, ScriptParams[0]); return 0; case COMMAND_REGISTER_UNIQUE_JUMP_FOUND: ++CStats::NumberOfUniqueJumpsFound; @@ -6855,10 +6855,10 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z); int16 collisions; CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos, - min(cp1.x, min(cp2.x, min(cp3.x, cp4.x))), - min(cp1.y, min(cp2.y, min(cp3.y, cp4.y))), - max(cp1.x, max(cp2.x, max(cp3.x, cp4.x))), - max(cp1.y, max(cp2.y, max(cp3.y, cp4.y))), + Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))), + Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))), + Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))), + Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))), &collisions, 2, nil, false, true, true, false, false); if (collisions > 0) obstacleInPath = true; @@ -6910,10 +6910,10 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z); int16 collisions; CWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, newPosition, - min(cp1.x, min(cp2.x, min(cp3.x, cp4.x))), - min(cp1.y, min(cp2.y, min(cp3.y, cp4.y))), - max(cp1.x, max(cp2.x, max(cp3.x, cp4.x))), - max(cp1.y, max(cp2.y, max(cp3.y, cp4.y))), + Min(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))), + Min(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))), + Max(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))), + Max(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))), &collisions, 2, nil, false, true, true, false, false); if (collisions > 0) obstacleInPath = true; @@ -7746,7 +7746,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CVector pos = *(CVector*)&ScriptParams[1]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - float size = max(0.0f, *(float*)&ScriptParams[7]); + float size = Max(0.0f, *(float*)&ScriptParams[7]); eParticleObjectType type = (eParticleObjectType)ScriptParams[0]; RwRGBA color; if (type == POBJECT_SMOKE_TRAIL){ @@ -11456,22 +11456,22 @@ void CTheScripts::HighlightImportantAngledArea(uint32 id, float x1, float y1, fl supY = infY = Y; X = (x2 + x3) / 2; Y = (y2 + y3) / 2; - infX = min(infX, X); - supX = max(supX, X); - infY = min(infY, Y); - supY = max(supY, Y); + infX = Min(infX, X); + supX = Max(supX, X); + infY = Min(infY, Y); + supY = Max(supY, Y); X = (x3 + x4) / 2; Y = (y3 + y4) / 2; - infX = min(infX, X); - supX = max(supX, X); - infY = min(infY, Y); - supY = max(supY, Y); + infX = Min(infX, X); + supX = Max(supX, X); + infY = Min(infY, Y); + supY = Max(supY, Y); X = (x4 + x1) / 2; Y = (y4 + y1) / 2; - infX = min(infX, X); - supX = max(supX, X); - infY = min(infY, Y); - supY = max(supY, Y); + infX = Min(infX, X); + supX = Max(supX, X); + infY = Min(infY, Y); + supY = Max(supY, Y); CVector center; center.x = (infX + supX) / 2; center.y = (infY + supY) / 2; diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index 096bb484..c8d3f79f 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -1,19 +1,19 @@ #include "common.h" -#include "General.h" #include "Camera.h" -#include "World.h" -#include "PathFind.h" -#include "Timer.h" #include "Clock.h" -#include "Weather.h" -#include "Timecycle.h" -#include "Pointlights.h" -#include "Shadows.h" #include "Coronas.h" +#include "General.h" +#include "PathFind.h" +#include "PointLights.h" +#include "Shadows.h" #include "SpecialFX.h" -#include "Vehicle.h" +#include "Timecycle.h" +#include "Timer.h" #include "TrafficLights.h" +#include "Vehicle.h" +#include "Weather.h" +#include "World.h" // TODO: figure out the meaning of this enum { SOME_FLAG = 0x80 }; @@ -39,10 +39,10 @@ CTrafficLights::DisplayActualLight(CEntity *ent) float zMax = mi->Get2dEffect(0)->pos.z; for(i = 1; i < 6; i++){ assert(mi->Get2dEffect(i)); - yMin = min(yMin, mi->Get2dEffect(i)->pos.y); - yMax = max(yMax, mi->Get2dEffect(i)->pos.y); - zMin = min(zMin, mi->Get2dEffect(i)->pos.z); - zMax = max(zMax, mi->Get2dEffect(i)->pos.z); + yMin = Min(yMin, mi->Get2dEffect(i)->pos.y); + yMax = Max(yMax, mi->Get2dEffect(i)->pos.y); + zMin = Min(zMin, mi->Get2dEffect(i)->pos.z); + zMax = Max(zMax, mi->Get2dEffect(i)->pos.z); } CVector pos1, pos2; diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index 07dc2051..f0a60093 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -117,9 +117,9 @@ CCam::Process(void) float FwdSpeedX = ((CVehicle*)CamTargetEntity)->GetMoveSpeed().x * Fwd.x; float FwdSpeedY = ((CVehicle*)CamTargetEntity)->GetMoveSpeed().y * Fwd.y; if(FwdSpeedX + FwdSpeedY > 0.0f) - TargetSpeedVar = min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/0.9f, 1.0f); + TargetSpeedVar = Min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/0.9f, 1.0f); else - TargetSpeedVar = -min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/1.8f, 0.5f); + TargetSpeedVar = -Min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/1.8f, 0.5f); SpeedVar = 0.895f*SpeedVar + 0.105*TargetSpeedVar; }else{ CameraTarget = CamTargetEntity->GetPosition(); @@ -341,7 +341,7 @@ WellBufferMe(float Target, float *CurrentValue, float *CurrentSpeed, float MaxSp else if(TargetSpeed > 0.0f && *CurrentSpeed > TargetSpeed) *CurrentSpeed = TargetSpeed; - *CurrentValue += *CurrentSpeed * min(10.0f, CTimer::GetTimeStep()); + *CurrentValue += *CurrentSpeed * Min(10.0f, CTimer::GetTimeStep()); } void @@ -467,7 +467,7 @@ CCam::ProcessSpecialHeightRoutines(void) vehicle->IsVehicle()){ float height = vehicle->GetColModel()->boundingBox.GetSize().z; if(FoundCar){ - HighestCar = max(HighestCar, height); + HighestCar = Max(HighestCar, height); }else{ FoundCar = true; HighestCar = height; @@ -481,7 +481,7 @@ CCam::ProcessSpecialHeightRoutines(void) vehicle->IsVehicle()){ float height = vehicle->GetColModel()->boundingBox.GetSize().z; if(FoundCar){ - HighestCar = max(HighestCar, height); + HighestCar = Max(HighestCar, height); }else{ FoundCar = true; HighestCar = height; @@ -1323,7 +1323,7 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl else if(ReqSpeed > 0.0f && BetaSpeed > ReqSpeed) BetaSpeed = ReqSpeed; - Beta += BetaSpeed * min(10.0f, CTimer::GetTimeStep()); + Beta += BetaSpeed * Min(10.0f, CTimer::GetTimeStep()); */ WellBufferMe(FixedTargetOrientation, &Beta, &BetaSpeed, MaxSpeed, Acceleration, true); @@ -1398,7 +1398,7 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl // Process height offset to avoid peds and cars float TargetZOffSet = m_fRoadOffSet + m_fDimensionOfHighestNearCar; - TargetZOffSet = max(TargetZOffSet, m_fPedBetweenCameraHeightOffset); + TargetZOffSet = Max(TargetZOffSet, m_fPedBetweenCameraHeightOffset); float TargetHeight = CameraTarget.z + TargetZOffSet - Source.z; if(TargetHeight > m_fCamBufferedHeight){ @@ -1454,7 +1454,7 @@ CCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, fl } } - TargetCoors.z += min(1.0f, m_fCamBufferedHeight/2.0f); + TargetCoors.z += Min(1.0f, m_fCamBufferedHeight/2.0f); m_cvecTargetCoorsForFudgeInter = TargetCoors; Front = TargetCoors - Source; @@ -1553,7 +1553,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient #else if(Alpha > fBaseDist) // comparing an angle against a distance? #endif - CamDist = fBaseDist + Cos(min(Alpha*fFalloff, HALFPI))*fAngleDist; + CamDist = fBaseDist + Cos(Min(Alpha*fFalloff, HALFPI))*fAngleDist; else CamDist = fBaseDist + Cos(Alpha)*fAngleDist; @@ -1585,14 +1585,14 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient PedColDist = (TargetCoors - colPoint.point).Magnitude(); Source = colPoint.point; if(PedColDist < DEFAULT_NEAR + 0.3f) - RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f)); + RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f)); }else{ - RwCameraSetNearClipPlane(Scene.camera, min(ColCamDist-0.35f, DEFAULT_NEAR)); + RwCameraSetNearClipPlane(Scene.camera, Min(ColCamDist-0.35f, DEFAULT_NEAR)); } }else{ Source = colPoint.point; if(PedColDist < DEFAULT_NEAR + 0.3f) - RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f)); + RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f)); } } CWorld::pIgnoreEntity = nil; @@ -1609,7 +1609,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient float dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth; // Try to decrease near clip - dist = max(min(Near, dist), 0.1f); + dist = Max(Min(Near, dist), 0.1f); if(dist < Near) RwCameraSetNearClipPlane(Scene.camera, dist); @@ -1639,7 +1639,7 @@ CCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrient float PlayerDist = (Source - player->GetPosition()).Magnitude(); if(PlayerDist < 2.75f) Near = PlayerDist/2.75f * DEFAULT_NEAR - 0.3f; - RwCameraSetNearClipPlane(Scene.camera, max(Near, 0.1f)); + RwCameraSetNearClipPlane(Scene.camera, Max(Near, 0.1f)); } } @@ -1881,7 +1881,7 @@ CCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, floa } if(FoundCamRoof){ // Camera is under something - float roof = FoundRoofCenter ? min(CamRoof, CarRoof) : CamRoof; + float roof = FoundRoofCenter ? Min(CamRoof, CarRoof) : CamRoof; // Same weirdness again? TargetAlpha = CGeneral::GetATanOfXY(CA_MAX_DISTANCE, roof - CamTargetZ - 1.5f); CamClear = false; @@ -2139,7 +2139,7 @@ void CCam::Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist) { CA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth; - CA_MIN_DISTANCE = min(BaseDist*0.6f, 3.5f); + CA_MIN_DISTANCE = Min(BaseDist*0.6f, 3.5f); CVector Dist = Source - TargetCoors; @@ -2361,7 +2361,7 @@ CCam::Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, f if(FindPlayerPed()->m_pPointGunAt){ Dist = (FindPlayerPed()->m_pPointGunAt->GetPosition() - CameraTarget).Magnitude2D(); if(Dist > 6.0f) - HeightTarget = max(HeightTarget, Dist/22.0f*37.0f); + HeightTarget = Max(HeightTarget, Dist/22.0f*37.0f); } Source = TargetCoors + CVector(0.0f, -1.0f, 9.0f); @@ -2813,13 +2813,13 @@ CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, m_vecBufferedPlayerBodyOffset.z = TheCamera.m_fGaitSwayBuffer * m_vecBufferedPlayerBodyOffset.z + (1.0f-TheCamera.m_fGaitSwayBuffer) * HeadPos.z; - HeadPos = RwV3d(CamTargetEntity->GetMatrix() * m_vecBufferedPlayerBodyOffset); + HeadPos = (CamTargetEntity->GetMatrix() * m_vecBufferedPlayerBodyOffset).toRwV3d(); }else{ float HeadDelta = (HeadPos - InitialHeadPos).Magnitude2D(); CVector Fwd = CamTargetEntity->GetForward(); Fwd.z = 0.0f; Fwd.Normalise(); - HeadPos = RwV3d(HeadDelta*1.23f*Fwd + CamTargetEntity->GetPosition()); + HeadPos = (HeadDelta*1.23f*Fwd + CamTargetEntity->GetPosition()).toRwV3d(); HeadPos.z += 0.59f; } Source = HeadPos; @@ -3125,7 +3125,7 @@ CCam::Process_Syphon(const CVector &CameraTarget, float, float, float) Front = TargetCoors - Source; m_fMinDistAwayFromCamWhenInterPolating = Front.Magnitude2D(); if(m_fMinDistAwayFromCamWhenInterPolating < 1.1f) - RwCameraSetNearClipPlane(Scene.camera, max(m_fMinDistAwayFromCamWhenInterPolating - 0.35f, 0.05f)); + RwCameraSetNearClipPlane(Scene.camera, Max(m_fMinDistAwayFromCamWhenInterPolating - 0.35f, 0.05f)); Front.Normalise(); GetVectorsReadyForRW(); } @@ -3382,7 +3382,7 @@ CCam::Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, fl WellBufferMe(TargetOrientation, &m_fBufferedTargetOrientation, &m_fBufferedTargetOrientationSpeed, 0.07f, 0.004f, true); TargetCoors = CameraTarget + 0.5f*CVector(Cos(m_fBufferedTargetOrientation), Sin(m_fBufferedTargetOrientation), 0.0f); - TargetCamHeight = CameraTarget.z - Source.z + max(m_fPedBetweenCameraHeightOffset, m_fRoadOffSet + m_fDimensionOfHighestNearCar) - 0.5f; + TargetCamHeight = CameraTarget.z - Source.z + Max(m_fPedBetweenCameraHeightOffset, m_fRoadOffSet + m_fDimensionOfHighestNearCar) - 0.5f; if(TargetCamHeight > m_fCamBufferedHeight) WellBufferMe(TargetCamHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.15f, 0.04f, false); else @@ -4556,14 +4556,14 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient PedColDist = (TargetCoors - colPoint.point).Magnitude(); Source = colPoint.point; if(PedColDist < DEFAULT_NEAR + 0.3f) - RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f)); + RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f)); }else{ - RwCameraSetNearClipPlane(Scene.camera, min(ColCamDist-0.35f, DEFAULT_NEAR)); + RwCameraSetNearClipPlane(Scene.camera, Min(ColCamDist-0.35f, DEFAULT_NEAR)); } }else{ Source = colPoint.point; if(PedColDist < DEFAULT_NEAR + 0.3f) - RwCameraSetNearClipPlane(Scene.camera, max(PedColDist-0.3f, 0.05f)); + RwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f)); } } CWorld::pIgnoreEntity = nil; @@ -4580,7 +4580,7 @@ CCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrient float dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth; // Try to decrease near clip - dist = max(min(Near, dist), 0.1f); + dist = Max(Min(Near, dist), 0.1f); if(dist < Near) RwCameraSetNearClipPlane(Scene.camera, dist); @@ -4714,7 +4714,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, minDistForVehType = minDistForVehType * 0.65f; } - float nextDistance = max(newDistance, minDistForVehType); + float nextDistance = Max(newDistance, minDistForVehType); CA_MAX_DISTANCE = newDistance; CA_MIN_DISTANCE = 3.5f; @@ -4811,7 +4811,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float betaChangeMult2 = (car->m_vecMoveSpeed - DotProduct(car->m_vecMoveSpeed, Front) * Front).Magnitude(); - float betaChange = min(1.0f, betaChangeMult1 * betaChangeMult2) * (velocityRightHeading - camRightHeading); + float betaChange = Min(1.0f, betaChangeMult1 * betaChangeMult2) * (velocityRightHeading - camRightHeading); if (betaChange <= betaChangeLimit) { if (betaChange < -betaChangeLimit) betaChange = -betaChangeLimit; @@ -4827,7 +4827,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float carPosChange = (TargetCoors - m_aTargetHistoryPosTwo).Magnitude(); if (carPosChange < newDistance && newDistance > minDistForThisCar) { - newDistance = max(minDistForThisCar, carPosChange); + newDistance = Max(minDistForThisCar, carPosChange); } float maxAlphaAllowed = CARCAM_SET[camSetArrPos][13]; @@ -4851,7 +4851,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, v200 = (1.5f - carCol->boundingBox.min.y) / Cos(v88); } else { float a6g = 1.2f + carCol->boundingBox.max.x; - v200 = a6g / Cos(max(0.0f, HALFPI - v88)); + v200 = a6g / Cos(Max(0.0f, HALFPI - v88)); } maxAlphaAllowed = Cos(Beta - (car->GetForward().Heading() - HALFPI)) * Atan2(car->GetForward().z, car->GetForward().Magnitude2D()) + Atan2(TargetCoors.z - car->GetPosition().z + car->GetHeightAboveRoad(), v200 * 1.2f); @@ -4944,7 +4944,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, yMovement = 0.0; xMovement = 0.0; targetAlpha = Alpha; - stepsLeftToChangeBetaByMouse = max(0.0f, stepsLeftToChangeBetaByMouse - CTimer::GetTimeStep()); + stepsLeftToChangeBetaByMouse = Max(0.0f, stepsLeftToChangeBetaByMouse - CTimer::GetTimeStep()); mouseChangesBeta = true; } } @@ -4963,7 +4963,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float newAngleSpeedMaxBlendAmount = CARCAM_SET[camSetArrPos][9]; float angleChangeStep = pow(CARCAM_SET[camSetArrPos][8], CTimer::GetTimeStep()); - float targetBetaWithStickBlendAmount = betaSpeedFromStickX + (targetBeta - Beta) / max(CTimer::GetTimeStep(), 1.0f); + float targetBetaWithStickBlendAmount = betaSpeedFromStickX + (targetBeta - Beta) / Max(CTimer::GetTimeStep(), 1.0f); if (targetBetaWithStickBlendAmount < -newAngleSpeedMaxBlendAmount) targetBetaWithStickBlendAmount = -newAngleSpeedMaxBlendAmount; @@ -5088,7 +5088,7 @@ CCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, if (!foundEnt->IsPed() || obstacleCamDist <= 1.0f) { Source = foundCol.point; if (obstacleTargetDist < 1.2f) { - RwCameraSetNearClipPlane(Scene.camera, max(0.05f, obstacleTargetDist - 0.3f)); + RwCameraSetNearClipPlane(Scene.camera, Max(0.05f, obstacleTargetDist - 0.3f)); } } else { if (!CWorld::ProcessLineOfSight(foundCol.point, Source, foundCol, foundEnt, true, dontCollideWithCars < 0.1f, false, true, false, true, false)) { diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 6747ebf5..c8eaaa56 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -467,7 +467,7 @@ CCamera::Process(void) GetPosition().z += shakeOffset*(((shakeRand&0xF00)>>8)-7); if(shakeOffset > 0.0f && m_BlurType != MBLUR_SNIPER) - SetMotionBlurAlpha(min((int)(shakeStrength*255.0f) + 25, 150)); + SetMotionBlurAlpha(Min((int)(shakeStrength*255.0f) + 25, 150)); if(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && FindPlayerVehicle() && FindPlayerVehicle()->GetUp().z < 0.2f) SetMotionBlur(230, 230, 230, 215, MBLUR_NORMAL); @@ -489,19 +489,19 @@ CCamera::Process(void) CDraw::SetFOV(Cams[2].FOV); m_vecGameCamPos = Cams[ActiveCam].Source; - *RwMatrixGetPos(RwFrameGetMatrix(frame)) = (RwV3d)GetPosition(); - *RwMatrixGetAt(RwFrameGetMatrix(frame)) = (RwV3d)GetForward(); - *RwMatrixGetUp(RwFrameGetMatrix(frame)) = (RwV3d)GetUp(); - *RwMatrixGetRight(RwFrameGetMatrix(frame)) = (RwV3d)GetRight(); + *RwMatrixGetPos(RwFrameGetMatrix(frame)) = GetPosition().toRwV3d(); + *RwMatrixGetAt(RwFrameGetMatrix(frame)) = GetForward().toRwV3d(); + *RwMatrixGetUp(RwFrameGetMatrix(frame)) = GetUp().toRwV3d(); + *RwMatrixGetRight(RwFrameGetMatrix(frame)) = GetRight().toRwV3d(); RwMatrixUpdate(RwFrameGetMatrix(frame)); RwFrameUpdateObjects(frame); }else{ RwFrame *frame = RwCameraGetFrame(m_pRwCamera); m_vecGameCamPos = GetPosition(); - *RwMatrixGetPos(RwFrameGetMatrix(frame)) = (RwV3d)GetPosition(); - *RwMatrixGetAt(RwFrameGetMatrix(frame)) = (RwV3d)GetForward(); - *RwMatrixGetUp(RwFrameGetMatrix(frame)) = (RwV3d)GetUp(); - *RwMatrixGetRight(RwFrameGetMatrix(frame)) = (RwV3d)GetRight(); + *RwMatrixGetPos(RwFrameGetMatrix(frame)) = GetPosition().toRwV3d(); + *RwMatrixGetAt(RwFrameGetMatrix(frame)) = GetForward().toRwV3d(); + *RwMatrixGetUp(RwFrameGetMatrix(frame)) = GetUp().toRwV3d(); + *RwMatrixGetRight(RwFrameGetMatrix(frame)) = GetRight().toRwV3d(); RwMatrixUpdate(RwFrameGetMatrix(frame)); RwFrameUpdateObjects(frame); } @@ -768,27 +768,27 @@ CCamera::CamControl(void) if(m_bUseScriptZoomValueCar){ if(CarZoomValueSmooth < m_fCarZoomValueScript){ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); - CarZoomValueSmooth = min(CarZoomValueSmooth, m_fCarZoomValueScript); + CarZoomValueSmooth = Min(CarZoomValueSmooth, m_fCarZoomValueScript); }else{ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); - CarZoomValueSmooth = max(CarZoomValueSmooth, m_fCarZoomValueScript); + CarZoomValueSmooth = Max(CarZoomValueSmooth, m_fCarZoomValueScript); } }else if(m_bFailedCullZoneTestPreviously){ CloseInCarHeightTarget = 0.65f; if(CarZoomValueSmooth < -0.65f){ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); - CarZoomValueSmooth = min(CarZoomValueSmooth, -0.65f); + CarZoomValueSmooth = Min(CarZoomValueSmooth, -0.65f); }else{ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); - CarZoomValueSmooth = max(CarZoomValueSmooth, -0.65f); + CarZoomValueSmooth = Max(CarZoomValueSmooth, -0.65f); } }else{ if(CarZoomValueSmooth < CarZoomValue){ CarZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); - CarZoomValueSmooth = min(CarZoomValueSmooth, CarZoomValue); + CarZoomValueSmooth = Min(CarZoomValueSmooth, CarZoomValue); }else{ CarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); - CarZoomValueSmooth = max(CarZoomValueSmooth, CarZoomValue); + CarZoomValueSmooth = Max(CarZoomValueSmooth, CarZoomValue); } } @@ -872,28 +872,28 @@ CCamera::CamControl(void) if(m_bUseScriptZoomValuePed){ if(m_fPedZoomValueSmooth < m_fPedZoomValueScript){ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); - m_fPedZoomValueSmooth = min(m_fPedZoomValueSmooth, m_fPedZoomValueScript); + m_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, m_fPedZoomValueScript); }else{ m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); - m_fPedZoomValueSmooth = max(m_fPedZoomValueSmooth, m_fPedZoomValueScript); + m_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, m_fPedZoomValueScript); } }else if(m_bFailedCullZoneTestPreviously){ static float PedZoomedInVal = 0.5f; CloseInPedHeightTarget = 0.7f; if(m_fPedZoomValueSmooth < PedZoomedInVal){ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); - m_fPedZoomValueSmooth = min(m_fPedZoomValueSmooth, PedZoomedInVal); + m_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, PedZoomedInVal); }else{ m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); - m_fPedZoomValueSmooth = max(m_fPedZoomValueSmooth, PedZoomedInVal); + m_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, PedZoomedInVal); } }else{ if(m_fPedZoomValueSmooth < m_fPedZoomValue){ m_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep(); - m_fPedZoomValueSmooth = min(m_fPedZoomValueSmooth, m_fPedZoomValue); + m_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, m_fPedZoomValue); }else{ m_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep(); - m_fPedZoomValueSmooth = max(m_fPedZoomValueSmooth, m_fPedZoomValue); + m_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, m_fPedZoomValue); } } @@ -2256,7 +2256,7 @@ CCamera::IsItTimeForNewcam(int32 obbeMode, int32 time) if(fwd.Magnitude() < 2.0f) // very close, fix near clip - SetNearClipScript(max(fwd.Magnitude()*0.5f, 0.05f)); + SetNearClipScript(Max(fwd.Magnitude()*0.5f, 0.05f)); // too far and driving away from cam if(fwd.Magnitude() > 19.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f) return true; diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index 5bdb32dc..7dfe3651 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -153,10 +153,10 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) // on water we expect to be between levels multipleLevels = true; }else{ - xmin = max(sx - 1, 0); - xmax = min(sx + 1, NUMSECTORS_X-1); - ymin = max(sy - 1, 0); - ymax = min(sy + 1, NUMSECTORS_Y-1); + xmin = Max(sx - 1, 0); + xmax = Min(sx + 1, NUMSECTORS_X-1); + ymin = Max(sy - 1, 0); + ymax = Min(sy + 1, NUMSECTORS_Y-1); for(x = xmin; x <= xmax; x++) for(y = ymin; y <= ymax; y++){ diff --git a/src/core/Crime.h b/src/core/Crime.h new file mode 100644 index 00000000..8dfae5b8 --- /dev/null +++ b/src/core/Crime.h @@ -0,0 +1,36 @@ +#pragma once + +enum eCrimeType { + CRIME_NONE, + CRIME_POSSESSION_GUN, + CRIME_HIT_PED, + CRIME_HIT_COP, + CRIME_SHOOT_PED, + CRIME_SHOOT_COP, + CRIME_STEAL_CAR, + CRIME_RUN_REDLIGHT, + CRIME_RECKLESS_DRIVING, + CRIME_SPEEDING, + CRIME_RUNOVER_PED, + CRIME_RUNOVER_COP, + CRIME_SHOOT_HELI, + CRIME_PED_BURNED, + CRIME_COP_BURNED, + CRIME_VEHICLE_BURNED, + CRIME_DESTROYED_CESSNA, + NUM_CRIME_TYPES +}; + +class CCrimeBeingQd +{ +public: + eCrimeType m_nType; + uint32 m_nId; + uint32 m_nTime; + CVector m_vecPosn; + bool m_bReported; + bool m_bPoliceDoesntCare; + + CCrimeBeingQd() { }; + ~CCrimeBeingQd() { }; +}; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 6fe06d96..db6073a6 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -349,8 +349,8 @@ CMenuManager::PageUpList(bool playSoundOnSuccess) 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); + 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; @@ -367,8 +367,8 @@ CMenuManager::PageDownList(bool playSoundOnSuccess) if(playSoundOnSuccess) DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_DENIED, 0); - m_nFirstVisibleRowOnList = min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW); - m_nSelectedListRow = max(m_nSelectedListRow, m_nFirstVisibleRowOnList); + m_nFirstVisibleRowOnList = 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; @@ -643,7 +643,7 @@ CMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostR } else color = CRGBA(185, 120, 0, FadeIn(255)); - maxBarHeight = max(mostLeftBarSize, mostRightBarSize); + maxBarHeight = Max(mostLeftBarSize, mostRightBarSize); float curBarFreeSpace = ((16 - i) * mostLeftBarSize + i * mostRightBarSize) / 16.0f; float left = curBarX; @@ -2492,7 +2492,7 @@ CMenuManager::DrawPlayerSetupScreen() strncpy(&m_pSelectedSkin->skinNameDisplayed[k], "(", 1); if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], "}", 1)) strncpy(&m_pSelectedSkin->skinNameDisplayed[k], ")", 1); - if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], "£", 1)) + if (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], "�", 1)) strncpy(&m_pSelectedSkin->skinNameDisplayed[k], "$", 1); } @@ -2829,7 +2829,7 @@ CMenuManager::FadeIn(int alpha) m_nCurrScreen == MENUPAGE_DELETING) return alpha; - return min(m_nMenuFadeAlpha, alpha); + return Min(m_nMenuFadeAlpha, alpha); } void @@ -5393,7 +5393,7 @@ CMenuManager::PrintMap(void) if (fMapCenterY + fMapSize < SCREEN_HEIGHT - MENU_Y(60.0f)) fMapCenterY = SCREEN_HEIGHT - MENU_Y(60.0f) - fMapSize; - fMapCenterY = min(fMapCenterY, fMapSize); // To not show beyond north border + fMapCenterY = Min(fMapCenterY, fMapSize); // To not show beyond north border bMenuMapActive = false; @@ -5455,7 +5455,7 @@ CMenuManager::ConstructStatLine(int rowIdx) int percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1)); - percentCompleted = min(percentCompleted, 100); + percentCompleted = Min(percentCompleted, 100); STAT_LINE("PER_COM", &percentCompleted, false, nil); STAT_LINE("NMISON", &CStats::MissionsGiven, false, nil); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 71aac605..db54d2a5 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -1,4 +1,4 @@ -#pragma +#pragma once #include "Sprite2d.h" diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 7ccf78d0..8b2f8604 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -72,7 +72,7 @@ #include "Streaming.h" #include "SurfaceTable.h" #include "TempColModels.h" -#include "TimeCycle.h" +#include "Timecycle.h" #include "TrafficLights.h" #include "Train.h" #include "TxdStore.h" diff --git a/src/core/Game.h b/src/core/Game.h index e3f0f616..acfeff0f 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -1,7 +1,6 @@ #pragma once -enum eLevelName -{ +enum eLevelName { LEVEL_IGNORE = -1, // beware, this is only used in CPhysical's m_nZoneLevel LEVEL_NONE = 0, LEVEL_INDUSTRIAL, diff --git a/src/core/General.h b/src/core/General.h index 77828854..7ffa99de 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -124,7 +124,7 @@ public: static bool faststricmp(const char *str1, const char *str2) { for (; *str1; str1++, str2++) { -#if MUCH_SLOWER +#if MUCH_SLOWER || !defined _WIN32 || defined __MINGW32__ if (toupper(*str1) != toupper(*str2)) #else if (__ascii_toupper(*str1) != __ascii_toupper(*str2)) diff --git a/src/core/IniFile.cpp b/src/core/IniFile.cpp index 16e35633..df01b440 100644 --- a/src/core/IniFile.cpp +++ b/src/core/IniFile.cpp @@ -17,10 +17,10 @@ void CIniFile::LoadIniFile() if (f){ CFileMgr::ReadLine(f, gString, 200); sscanf(gString, "%f", &PedNumberMultiplier); - PedNumberMultiplier = min(3.0f, max(0.5f, PedNumberMultiplier)); + PedNumberMultiplier = Min(3.0f, Max(0.5f, PedNumberMultiplier)); CFileMgr::ReadLine(f, gString, 200); sscanf(gString, "%f", &CarNumberMultiplier); - CarNumberMultiplier = min(3.0f, max(0.5f, CarNumberMultiplier)); + CarNumberMultiplier = Min(3.0f, Max(0.5f, CarNumberMultiplier)); CFileMgr::CloseFile(f); } CPopulation::MaxNumberOfPedsInUse = 25.0f * PedNumberMultiplier; diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 86aff05e..8a3fc7cb 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -6,7 +6,7 @@ #include "common.h" #ifdef XINPUT -#include +#include #pragma comment( lib, "Xinput9_1_0.lib" ) #endif @@ -205,7 +205,7 @@ void ArmourCheat() void WantedLevelUpCheat() { CHud::SetHelpMessage(TheText.Get("CHEAT5"), true); - FindPlayerPed()->SetWantedLevel(min(FindPlayerPed()->m_pWanted->m_nWantedLevel + 2, 6)); + FindPlayerPed()->SetWantedLevel(Min(FindPlayerPed()->m_pWanted->m_nWantedLevel + 2, 6)); } void WantedLevelDownCheat() @@ -513,10 +513,10 @@ CControllerState CPad::ReconcileTwoControllersInput(CControllerState const &Stat { if ( State1.button || State2.button ) ReconState.button = 255; } #define _RECONCILE_AXIS_POSITIVE(axis) \ - { if ( State1.axis >= 0 && State2.axis >= 0 ) ReconState.axis = max(State1.axis, State2.axis); } + { if ( State1.axis >= 0 && State2.axis >= 0 ) ReconState.axis = Max(State1.axis, State2.axis); } #define _RECONCILE_AXIS_NEGATIVE(axis) \ - { if ( State1.axis <= 0 && State2.axis <= 0 ) ReconState.axis = min(State1.axis, State2.axis); } + { if ( State1.axis <= 0 && State2.axis <= 0 ) ReconState.axis = Min(State1.axis, State2.axis); } #define _RECONCILE_AXIS(axis) \ { _RECONCILE_AXIS_POSITIVE(axis); _RECONCILE_AXIS_NEGATIVE(axis); } diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index 69b8b7bf..e92f7568 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -1,35 +1,35 @@ #include "common.h" -#include "main.h" -#include "PlayerPed.h" -#include "Wanted.h" -#include "PlayerInfo.h" +#include "Automobile.h" +#include "Bridge.h" +#include "Camera.h" +#include "Cranes.h" +#include "Darkel.h" +#include "Explosion.h" #include "Fire.h" #include "Frontend.h" -#include "PlayerSkin.h" -#include "Darkel.h" -#include "Messages.h" -#include "Text.h" -#include "Stats.h" -#include "Remote.h" -#include "World.h" -#include "Replay.h" -#include "Camera.h" -#include "Pad.h" -#include "ProjectileInfo.h" -#include "Explosion.h" -#include "Script.h" -#include "Automobile.h" -#include "HandlingMgr.h" #include "General.h" -#include "SpecialFX.h" -#include "Cranes.h" -#include "Bridge.h" -#include "WaterLevel.h" +#include "HandlingMgr.h" +#include "Messages.h" +#include "Pad.h" #include "PathFind.h" -#include "ZoneCull.h" +#include "PlayerInfo.h" +#include "PlayerPed.h" +#include "PlayerSkin.h" +#include "ProjectileInfo.h" +#include "Remote.h" #include "Renderer.h" +#include "Replay.h" +#include "Script.h" +#include "SpecialFX.h" +#include "Stats.h" #include "Streaming.h" +#include "Text.h" +#include "Wanted.h" +#include "WaterLevel.h" +#include "World.h" +#include "ZoneCull.h" +#include "main.h" void CPlayerInfo::SetPlayerSkin(char *skin) @@ -184,7 +184,7 @@ CPlayerInfo::MakePlayerSafe(bool toggle) m_pPed->bExplosionProof = true; m_pPed->m_bCanBeDamaged = false; ((CPlayerPed*)m_pPed)->ClearAdrenaline(); - CancelPlayerEnteringCars(false); + CancelPlayerEnteringCars(nil); gFireManager.ExtinguishPoint(GetPos(), 4000.0f); CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f); CProjectileInfo::RemoveAllProjectiles(); diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index fb64c551..4f4588da 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -110,7 +110,7 @@ INITSAVEBUF CStreaming::LoadAllRequestedModels(false); int32 slot = ReadSaveBuf(buf); CVehicle* pVehicle; - char* vbuf = new char[max(sizeof(CAutomobile), sizeof(CBoat))]; + char* vbuf = new char[Max(sizeof(CAutomobile), sizeof(CBoat))]; if (type == VEHICLE_TYPE_BOAT) { memcpy(vbuf, buf, sizeof(CBoat)); SkipSaveBuf(buf, sizeof(CBoat)); diff --git a/src/core/Profile.cpp b/src/core/Profile.cpp index 56584d12..05d54133 100644 --- a/src/core/Profile.cpp +++ b/src/core/Profile.cpp @@ -52,20 +52,20 @@ void CProfile::SuspendProfile(eProfile profile) void CProfile::ShowResults() { - ms_afMaxEndTime[PROFILE_FRAME_RATE] = max(ms_afMaxEndTime[PROFILE_FRAME_RATE], ms_afEndTime[PROFILE_FRAME_RATE]); - ms_afMaxEndTime[PROFILE_PHYSICS] = max(ms_afMaxEndTime[PROFILE_PHYSICS], ms_afEndTime[PROFILE_PHYSICS]); - ms_afMaxEndTime[PROFILE_COLLISION] = max(ms_afMaxEndTime[PROFILE_COLLISION], ms_afEndTime[PROFILE_COLLISION]); - ms_afMaxEndTime[PROFILE_PED_AI] = max(ms_afMaxEndTime[PROFILE_PED_AI], ms_afEndTime[PROFILE_PED_AI]); - ms_afMaxEndTime[PROFILE_PROCESSING_TIME] = max(ms_afMaxEndTime[PROFILE_PROCESSING_TIME], ms_afEndTime[PROFILE_PROCESSING_TIME]); - ms_afMaxEndTime[PROFILE_RENDERING_TIME] = max(ms_afMaxEndTime[PROFILE_RENDERING_TIME], ms_afEndTime[PROFILE_RENDERING_TIME]); - ms_afMaxEndTime[PROFILE_TOTAL] = max(ms_afMaxEndTime[PROFILE_TOTAL], ms_afEndTime[PROFILE_TOTAL]); + ms_afMaxEndTime[PROFILE_FRAME_RATE] = Max(ms_afMaxEndTime[PROFILE_FRAME_RATE], ms_afEndTime[PROFILE_FRAME_RATE]); + ms_afMaxEndTime[PROFILE_PHYSICS] = Max(ms_afMaxEndTime[PROFILE_PHYSICS], ms_afEndTime[PROFILE_PHYSICS]); + ms_afMaxEndTime[PROFILE_COLLISION] = Max(ms_afMaxEndTime[PROFILE_COLLISION], ms_afEndTime[PROFILE_COLLISION]); + ms_afMaxEndTime[PROFILE_PED_AI] = Max(ms_afMaxEndTime[PROFILE_PED_AI], ms_afEndTime[PROFILE_PED_AI]); + ms_afMaxEndTime[PROFILE_PROCESSING_TIME] = Max(ms_afMaxEndTime[PROFILE_PROCESSING_TIME], ms_afEndTime[PROFILE_PROCESSING_TIME]); + ms_afMaxEndTime[PROFILE_RENDERING_TIME] = Max(ms_afMaxEndTime[PROFILE_RENDERING_TIME], ms_afEndTime[PROFILE_RENDERING_TIME]); + ms_afMaxEndTime[PROFILE_TOTAL] = Max(ms_afMaxEndTime[PROFILE_TOTAL], ms_afEndTime[PROFILE_TOTAL]); - ms_afMaxCumulativeTime[PROFILE_FRAME_RATE] = max(ms_afMaxCumulativeTime[PROFILE_FRAME_RATE], ms_afCumulativeTime[PROFILE_FRAME_RATE]); - ms_afMaxCumulativeTime[PROFILE_PHYSICS] = max(ms_afMaxCumulativeTime[PROFILE_PHYSICS], ms_afCumulativeTime[PROFILE_PHYSICS]); - ms_afMaxCumulativeTime[PROFILE_COLLISION] = max(ms_afMaxCumulativeTime[PROFILE_COLLISION], ms_afCumulativeTime[PROFILE_COLLISION]); - ms_afMaxCumulativeTime[PROFILE_PED_AI] = max(ms_afMaxCumulativeTime[PROFILE_PED_AI], ms_afCumulativeTime[PROFILE_PED_AI]); - ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME] = max(ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME], ms_afCumulativeTime[PROFILE_PROCESSING_TIME]); - ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME] = max(ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME], ms_afCumulativeTime[PROFILE_RENDERING_TIME]); - ms_afMaxCumulativeTime[PROFILE_TOTAL] = max(ms_afMaxCumulativeTime[PROFILE_TOTAL], ms_afCumulativeTime[PROFILE_TOTAL]); + ms_afMaxCumulativeTime[PROFILE_FRAME_RATE] = Max(ms_afMaxCumulativeTime[PROFILE_FRAME_RATE], ms_afCumulativeTime[PROFILE_FRAME_RATE]); + ms_afMaxCumulativeTime[PROFILE_PHYSICS] = Max(ms_afMaxCumulativeTime[PROFILE_PHYSICS], ms_afCumulativeTime[PROFILE_PHYSICS]); + ms_afMaxCumulativeTime[PROFILE_COLLISION] = Max(ms_afMaxCumulativeTime[PROFILE_COLLISION], ms_afCumulativeTime[PROFILE_COLLISION]); + ms_afMaxCumulativeTime[PROFILE_PED_AI] = Max(ms_afMaxCumulativeTime[PROFILE_PED_AI], ms_afCumulativeTime[PROFILE_PED_AI]); + ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME] = Max(ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME], ms_afCumulativeTime[PROFILE_PROCESSING_TIME]); + ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME] = Max(ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME], ms_afCumulativeTime[PROFILE_RENDERING_TIME]); + ms_afMaxCumulativeTime[PROFILE_TOTAL] = Max(ms_afMaxCumulativeTime[PROFILE_TOTAL], ms_afCumulativeTime[PROFILE_TOTAL]); } #endif \ No newline at end of file diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index ef3c0ab6..99274e04 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -121,13 +121,13 @@ void CStats::RegisterFastestTime(int32 index, int32 time) if (FastestTimes[index] == 0) FastestTimes[index] = time; else - FastestTimes[index] = min(FastestTimes[index], time); + FastestTimes[index] = Min(FastestTimes[index], time); } void CStats::RegisterHighestScore(int32 index, int32 score) { assert(index >= 0 && index < TOTAL_HIGHEST_SCORES); - HighestScores[index] = max(HighestScores[index], score); + HighestScores[index] = Max(HighestScores[index], score); } void CStats::RegisterElBurroTime(int32 time) @@ -167,7 +167,7 @@ void CStats::AnotherCriminalCaught() void CStats::RegisterLevelAmbulanceMission(int32 level) { - HighestLevelAmbulanceMission = max(HighestLevelAmbulanceMission, level); + HighestLevelAmbulanceMission = Max(HighestLevelAmbulanceMission, level); } void CStats::AnotherFireExtinguished() @@ -177,7 +177,7 @@ void CStats::AnotherFireExtinguished() void CStats::RegisterLongestFlightInDodo(int32 time) { - LongestFlightInDodo = max(LongestFlightInDodo, time); + LongestFlightInDodo = Max(LongestFlightInDodo, time); } void CStats::RegisterTimeTakenDefuseMission(int32 time) diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index dae83d89..15fe60e2 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -1950,7 +1950,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()); if(mi->m_type != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())){ lodDistSq = sq(mi->GetLargestLodDistance()); - lodDistSq = min(lodDistSq, sq(STREAM_DIST)); + lodDistSq = Min(lodDistSq, sq(STREAM_DIST)); pos = CVector2D(e->GetPosition()); if(xmin < pos.x && pos.x < xmax && ymin < pos.y && pos.y < ymax && @@ -2170,20 +2170,20 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem) if(Abs(TheCamera.GetForward().x) > Abs(TheCamera.GetForward().y)){ // looking west/east - ymin = max(iy - 10, 0); - ymax = min(iy + 10, NUMSECTORS_Y - 1); + ymin = Max(iy - 10, 0); + ymax = Min(iy + 10, NUMSECTORS_Y - 1); assert(ymin <= ymax); // Delete a block of sectors that we know is behind the camera if(TheCamera.GetForward().x > 0){ // looking east - xmax = max(ix - 2, 0); - xmin = max(ix - 10, 0); + xmax = Max(ix - 2, 0); + xmin = Max(ix - 10, 0); inc = 1; }else{ // looking west - xmax = min(ix + 2, NUMSECTORS_X - 1); - xmin = min(ix + 10, NUMSECTORS_X - 1); + xmax = Min(ix + 2, NUMSECTORS_X - 1); + xmin = Min(ix + 10, NUMSECTORS_X - 1); inc = -1; } for(y = ymin; y <= ymax; y++){ @@ -2199,13 +2199,13 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem) // Now a block that intersects with the camera's frustum if(TheCamera.GetForward().x > 0){ // looking east - xmax = max(ix + 10, 0); - xmin = max(ix - 2, 0); + xmax = Max(ix + 10, 0); + xmin = Max(ix - 2, 0); inc = 1; }else{ // looking west - xmax = min(ix - 10, NUMSECTORS_X - 1); - xmin = min(ix + 2, NUMSECTORS_X - 1); + xmax = Min(ix - 10, NUMSECTORS_X - 1); + xmin = Min(ix + 2, NUMSECTORS_X - 1); inc = -1; } for(y = ymin; y <= ymax; y++){ @@ -2234,20 +2234,20 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem) }else{ // looking north/south - xmin = max(ix - 10, 0); - xmax = min(ix + 10, NUMSECTORS_X - 1); + xmin = Max(ix - 10, 0); + xmax = Min(ix + 10, NUMSECTORS_X - 1); assert(xmin <= xmax); // Delete a block of sectors that we know is behind the camera if(TheCamera.GetForward().y > 0){ // looking north - ymax = max(iy - 2, 0); - ymin = max(iy - 10, 0); + ymax = Max(iy - 2, 0); + ymin = Max(iy - 10, 0); inc = 1; }else{ // looking south - ymax = min(iy + 2, NUMSECTORS_Y - 1); - ymin = min(iy + 10, NUMSECTORS_Y - 1); + ymax = Min(iy + 2, NUMSECTORS_Y - 1); + ymin = Min(iy + 10, NUMSECTORS_Y - 1); inc = -1; } for(x = xmin; x <= xmax; x++){ @@ -2263,13 +2263,13 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem) // Now a block that intersects with the camera's frustum if(TheCamera.GetForward().y > 0){ // looking north - ymax = max(iy + 10, 0); - ymin = max(iy - 2, 0); + ymax = Max(iy + 10, 0); + ymin = Max(iy - 2, 0); inc = 1; }else{ // looking south - ymax = min(iy - 10, NUMSECTORS_Y - 1); - ymin = min(iy + 2, NUMSECTORS_Y - 1); + ymax = Min(iy - 10, NUMSECTORS_Y - 1); + ymin = Min(iy + 2, NUMSECTORS_Y - 1); inc = -1; } for(x = xmin; x <= xmax; x++){ diff --git a/src/core/Streaming.h b/src/core/Streaming.h index c910c068..cf8790e9 100644 --- a/src/core/Streaming.h +++ b/src/core/Streaming.h @@ -71,7 +71,6 @@ struct CStreamingChannel }; class CDirectory; -enum eLevelName; class CPtrList; class CStreaming diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index ebd79695..8f8570d7 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -138,7 +138,7 @@ void CTimer::Update(void) if ( !CRecordDataForGame::IsPlayingBack() ) { - ms_fTimeStep = min(3.0f, ms_fTimeStep); + ms_fTimeStep = Min(3.0f, ms_fTimeStep); if ( (m_snTimeInMilliseconds - m_snPreviousTimeInMilliseconds) > 60 ) m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 60; diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp index ce7d217e..6f5fdf06 100644 --- a/src/core/Wanted.cpp +++ b/src/core/Wanted.cpp @@ -212,7 +212,7 @@ CWanted::ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesnt else sensitivity = m_fCrimeSensitivity; - wantedLevelDrop = min(CCullZones::GetWantedLevelDrop(), 100); + wantedLevelDrop = Min(CCullZones::GetWantedLevelDrop(), 100); chaos = (1.0f - wantedLevelDrop/100.0f) * sensitivity; if (policeDoesntCare) @@ -371,7 +371,7 @@ CWanted::Update(void) CVector playerPos = FindPlayerCoors(); if (WorkOutPolicePresence(playerPos, radius) == 0) { m_nLastUpdateTime = CTimer::GetTimeInMilliseconds(); - m_nChaos = max(0, m_nChaos - 1); + m_nChaos = Max(0, m_nChaos - 1); UpdateWantedLevel(); } } diff --git a/src/core/Wanted.h b/src/core/Wanted.h index afeec8b0..e3e407b0 100644 --- a/src/core/Wanted.h +++ b/src/core/Wanted.h @@ -1,44 +1,10 @@ #pragma once +#include "Crime.h" + class CEntity; class CCopPed; -enum eCrimeType -{ - CRIME_NONE, - CRIME_POSSESSION_GUN, - CRIME_HIT_PED, - CRIME_HIT_COP, - CRIME_SHOOT_PED, - CRIME_SHOOT_COP, - CRIME_STEAL_CAR, - CRIME_RUN_REDLIGHT, - CRIME_RECKLESS_DRIVING, - CRIME_SPEEDING, - CRIME_RUNOVER_PED, - CRIME_RUNOVER_COP, - CRIME_SHOOT_HELI, - CRIME_PED_BURNED, - CRIME_COP_BURNED, - CRIME_VEHICLE_BURNED, - CRIME_DESTROYED_CESSNA, - NUM_CRIME_TYPES -}; - -class CCrimeBeingQd -{ -public: - eCrimeType m_nType; - uint32 m_nId; - uint32 m_nTime; - CVector m_vecPosn; - bool m_bReported; - bool m_bPoliceDoesntCare; - - CCrimeBeingQd() { }; - ~CCrimeBeingQd() { }; -}; - class CWanted { public: diff --git a/src/core/World.cpp b/src/core/World.cpp index 7ef43593..404b92c0 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -777,10 +777,10 @@ CWorld::FindObjectsOfTypeInRange(uint32 modelId, const CVector &position, float *nEntitiesFound = 0; const CVector2D vecSectorStartPos(position.x - radius, position.y - radius); const CVector2D vecSectorEndPos(position.x + radius, position.y + radius); - const int32 nStartX = max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); - const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); - const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); - const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); + const int32 nStartX = Max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); + const int32 nStartY = Max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); + const int32 nEndX = Min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = Min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = CWorld::GetSector(x, y); @@ -1045,10 +1045,10 @@ CWorld::FindObjectsKindaColliding(const CVector &position, float radius, bool bC *nCollidingEntities = 0; const CVector2D vecSectorStartPos(position.x - radius, position.y - radius); const CVector2D vecSectorEndPos(position.x + radius, position.y + radius); - const int32 nStartX = max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); - const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); - const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); - const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); + const int32 nStartX = Max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); + const int32 nStartY = Max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); + const int32 nEndX = Min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = Min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = CWorld::GetSector(x, y); @@ -1124,10 +1124,10 @@ CWorld::FindObjectsIntersectingCube(const CVector &vecStartPos, const CVector &v { CWorld::AdvanceCurrentScanCode(); *nIntersecting = 0; - const int32 nStartX = max(CWorld::GetSectorIndexX(vecStartPos.x), 0); - const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); - const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); - const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); + const int32 nStartX = Max(CWorld::GetSectorIndexX(vecStartPos.x), 0); + const int32 nStartY = Max(CWorld::GetSectorIndexY(vecStartPos.y), 0); + const int32 nEndX = Min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = Min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = CWorld::GetSector(x, y); @@ -1205,10 +1205,10 @@ CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &boundingBox, co { CWorld::AdvanceCurrentScanCode(); *nEntitiesFound = 0; - const int32 nStartX = max(CWorld::GetSectorIndexX(fStartX), 0); - const int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0); - const int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1); - const int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); + const int32 nStartX = Max(CWorld::GetSectorIndexX(fStartX), 0); + const int32 nStartY = Max(CWorld::GetSectorIndexY(fStartY), 0); + const int32 nEndX = Min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1); + const int32 nEndY = Min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = CWorld::GetSector(x, y); @@ -1285,10 +1285,10 @@ CWorld::FindMissionEntitiesIntersectingCube(const CVector &vecStartPos, const CV { CWorld::AdvanceCurrentScanCode(); *nIntersecting = 0; - const int32 nStartX = max(CWorld::GetSectorIndexX(vecStartPos.x), 0); - const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); - const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); - const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); + const int32 nStartX = Max(CWorld::GetSectorIndexX(vecStartPos.x), 0); + const int32 nStartY = Max(CWorld::GetSectorIndexY(vecStartPos.y), 0); + const int32 nEndX = Min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = Min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = CWorld::GetSector(x, y); @@ -1499,10 +1499,10 @@ CWorld::CallOffChaseForArea(float x1, float y1, float x2, float y2) float fStartY = y1 - 10.0f; float fEndX = x2 + 10.0f; float fEndY = y2 + 10.0f; - const int32 nStartX = max(CWorld::GetSectorIndexX(fStartX), 0); - const int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0); - const int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1); - const int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); + const int32 nStartX = Max(CWorld::GetSectorIndexX(fStartX), 0); + const int32 nStartY = Max(CWorld::GetSectorIndexY(fStartY), 0); + const int32 nEndX = Min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1); + const int32 nEndY = Min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1); for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = CWorld::GetSector(x, y); @@ -1544,13 +1544,13 @@ CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList &list, float x1, float y1 } if(bInsideSphere) { if(pVehicle->GetPosition().x <= (x1 + x2) * 0.5f) - pVehicle->m_vecMoveSpeed.x = min(pVehicle->m_vecMoveSpeed.x, 0.0f); + pVehicle->m_vecMoveSpeed.x = Min(pVehicle->m_vecMoveSpeed.x, 0.0f); else - pVehicle->m_vecMoveSpeed.x = max(pVehicle->m_vecMoveSpeed.x, 0.0f); + pVehicle->m_vecMoveSpeed.x = Max(pVehicle->m_vecMoveSpeed.x, 0.0f); if(pVehicle->GetPosition().y <= (y1 + y2) * 0.5f) - pVehicle->m_vecMoveSpeed.y = min(pVehicle->m_vecMoveSpeed.y, 0.0f); + pVehicle->m_vecMoveSpeed.y = Min(pVehicle->m_vecMoveSpeed.y, 0.0f); else - pVehicle->m_vecMoveSpeed.y = max(pVehicle->m_vecMoveSpeed.y, 0.0f); + pVehicle->m_vecMoveSpeed.y = Max(pVehicle->m_vecMoveSpeed.y, 0.0f); } } } @@ -2086,10 +2086,10 @@ CWorld::TriggerExplosion(const CVector &position, float fRadius, float fPower, C { CVector2D vecStartPos(position.x - fRadius, position.y - fRadius); CVector2D vecEndPos(position.x + fRadius, position.y + fRadius); - const int32 nStartX = max(CWorld::GetSectorIndexX(vecStartPos.x), 0); - const int32 nStartY = max(CWorld::GetSectorIndexY(vecStartPos.y), 0); - const int32 nEndX = min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); - const int32 nEndY = min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); + const int32 nStartX = Max(CWorld::GetSectorIndexX(vecStartPos.x), 0); + const int32 nStartY = Max(CWorld::GetSectorIndexY(vecStartPos.y), 0); + const int32 nEndX = Min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = Min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1); for(int32 y = nStartY; y <= nEndY; y++) { for(int32 x = nStartX; x <= nEndX; x++) { CSector *pSector = CWorld::GetSector(x, y); @@ -2144,7 +2144,7 @@ CWorld::TriggerExplosionSectorList(CPtrList &list, const CVector &position, floa if(pEntity->bIsStatic) { float fDamageMultiplier = (fRadius - fMagnitude) * 2.0f / fRadius; - float fDamage = 300.0f * min(fDamageMultiplier, 1.0f); + float fDamage = 300.0f * Min(fDamageMultiplier, 1.0f); pObject->ObjectDamage(fDamage); } } else { @@ -2153,18 +2153,18 @@ CWorld::TriggerExplosionSectorList(CPtrList &list, const CVector &position, floa } } if(!pEntity->bIsStatic) { - float fDamageMultiplier = min((fRadius - fMagnitude) * 2.0f / fRadius, 1.0f); + float fDamageMultiplier = Min((fRadius - fMagnitude) * 2.0f / fRadius, 1.0f); CVector vecForceDir = vecDistance * (fPower * pEntity->m_fMass * 0.00071429f * fDamageMultiplier / - max(fMagnitude, 0.01f)); - vecForceDir.z = max(vecForceDir.z, 0.0f); - if(pEntity == FindPlayerPed()) vecForceDir.z = min(vecForceDir.z, 1.0f); + Max(fMagnitude, 0.01f)); + vecForceDir.z = Max(vecForceDir.z, 0.0f); + if(pEntity == FindPlayerPed()) vecForceDir.z = Min(vecForceDir.z, 1.0f); pEntity->ApplyMoveForce(vecForceDir); if(!pEntity->bPedPhysics) { float fBoundRadius = pEntity->GetBoundRadius(); float fDistanceZ = position.z - pEntity->GetPosition().z; float fPointZ = fBoundRadius; - if(max(fDistanceZ, -fBoundRadius) < fBoundRadius) { + if(Max(fDistanceZ, -fBoundRadius) < fBoundRadius) { if(fDistanceZ <= -fBoundRadius) fPointZ = -fBoundRadius; else diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp index d17a33d4..7a221f39 100644 --- a/src/core/ZoneCull.cpp +++ b/src/core/ZoneCull.cpp @@ -289,7 +289,7 @@ CCullZones::FindAttributesForCoors(CVector coors, int32 *wantedLevel) coors.z >= aAttributeZones[i].minz && coors.z <= aAttributeZones[i].maxz){ attribs |= aAttributeZones[i].attributes; if(wantedLevel) - *wantedLevel = max(*wantedLevel, aAttributeZones[i].wantedLevel); + *wantedLevel = Max(*wantedLevel, aAttributeZones[i].wantedLevel); } return attribs; } diff --git a/src/core/common.h b/src/core/common.h index 454b848a..46b4d03a 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -12,7 +12,7 @@ #include #ifdef WITHWINDOWS -#include +#include #endif #ifdef WITHD3D @@ -42,12 +42,8 @@ #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 +#define Max(a,b) ((a) > (b) ? (a) : (b)) +#define Min(a,b) ((a) < (b) ? (a) : (b)) typedef uint8_t uint8; typedef int8_t int8; @@ -62,7 +58,7 @@ typedef int64_t int64; typedef uint16_t wchar; #ifndef nil -#define nil nullptr +#define nil NULL #endif #include "config.h" @@ -276,7 +272,7 @@ class CTweakFunc : public CTweakVar void (*m_pFunc)(); public: CTweakFunc(void (*pFunc)(), const char *strName, const char *strPath) : - m_pFunc(pFunc), m_pVarName(strName), m_pPath(strPath) + m_pPath(strPath), m_pVarName(strName), m_pFunc(pFunc) { CTweakVars::Add(this); } @@ -290,7 +286,7 @@ class CTweakBool : public CTweakVar bool *m_pBoolVar; public: CTweakBool(bool *pBool, const char *strName, const char *strPath) : - m_pBoolVar(pBool), m_pVarName(strName), m_pPath(strPath) + m_pPath(strPath), m_pVarName(strName), m_pBoolVar(pBool) { CTweakVars::Add(this); } @@ -306,9 +302,10 @@ class CTweakSwitch : public CTweakVar const char **m_aStr; void (*m_pFunc)(); public: - CTweakSwitch(void *pInt, const char *strName, int32 nMin, int32 nMax, const char **aStr, void (*pFunc)(), const char *strPath) : - m_pVarName(strName), m_pPath(strPath), - m_aStr(aStr), m_pIntVar(pInt), m_nMin(nMin), m_nMax(nMax) + CTweakSwitch(void *pInt, const char *strName, int32 nMin, int32 nMax, const char **aStr, + void (*pFunc)(), const char *strPath) + : m_pPath(strPath), m_pVarName(strName), m_pIntVar(pInt), m_nMin(nMin), m_nMax(nMax), + m_aStr(aStr) { CTweakVars::Add(this); } @@ -316,22 +313,24 @@ public: void AddDBG(const char *path); }; -#define _TWEEKCLASS(name, type) \ -class name : public CTweakVar \ -{ \ -public: \ - const char *m_pPath, *m_pVarName; \ - type *m_pIntVar, m_nLoawerBound, m_nUpperBound, m_nStep; \ - \ - name(type *pInt, const char *strName, type nLower, type nUpper, type nStep, const char *strPath) : \ - m_pIntVar(pInt), m_nLoawerBound(nLower), m_nUpperBound(nUpper), m_nStep(nStep), \ - m_pVarName(strName), m_pPath(strPath) \ - { \ - CTweakVars::Add(this); \ - } \ - \ - void AddDBG(const char *path); \ -}; +#define _TWEEKCLASS(name, type) \ + class name : public CTweakVar \ + { \ + public: \ + const char *m_pPath, *m_pVarName; \ + type *m_pIntVar, m_nLoawerBound, m_nUpperBound, m_nStep; \ + \ + name(type *pInt, const char *strName, type nLower, type nUpper, type nStep, \ + const char *strPath) \ + : m_pPath(strPath), m_pVarName(strName), m_pIntVar(pInt), \ + m_nLoawerBound(nLower), m_nUpperBound(nUpper), m_nStep(nStep) \ + \ + { \ + CTweakVars::Add(this); \ + } \ + \ + void AddDBG(const char *path); \ + }; _TWEEKCLASS(CTweakInt8, int8); _TWEEKCLASS(CTweakUInt8, uint8); diff --git a/src/core/main.cpp b/src/core/main.cpp index d5d4065d..77daaa01 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -205,7 +205,7 @@ DoFade(void) CRGBA fadeColor; CRect rect; int fadeValue = CDraw::FadeValue; - float brightness = min(CMenuManager::m_PrefsBrightness, 256); + float brightness = Min(CMenuManager::m_PrefsBrightness, 256); if(brightness <= 50) brightness = 50; if(FrontEndMenuManager.m_bMenuActive) diff --git a/src/core/patcher.cpp b/src/core/patcher.cpp index 19ca5f07..58f19767 100644 --- a/src/core/patcher.cpp +++ b/src/core/patcher.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include StaticPatcher *StaticPatcher::ms_head; diff --git a/src/core/timebars.cpp b/src/core/timebars.cpp index 5c2dbe3a..6b841a5c 100644 --- a/src/core/timebars.cpp +++ b/src/core/timebars.cpp @@ -102,14 +102,14 @@ void tbDisplay() #ifndef FINAL // Timers output (my own implementation) for (uint32 i = 0; i < TimerBar.count; i++) { - MaxTimes[i] = max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime); + MaxTimes[i] = Max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime); sprintf(temp, "%s: %.2f", &TimerBar.Timers[i].name[0], MaxTimes[i]); AsciiToUnicode(temp, wtemp); CFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp); } #ifdef FRAMETIME - MaxFrameTime = max(MaxFrameTime, FrameEndTime - FrameInitTime); + MaxFrameTime = Max(MaxFrameTime, FrameEndTime - FrameInitTime); sprintf(temp, "Frame Time: %.2f", MaxFrameTime); AsciiToUnicode(temp, wtemp); diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index ec4543f6..a27e4d7b 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -457,7 +457,7 @@ CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector & { float compression = 1.0f - springRatio; if(compression > 0.0f){ - float step = min(CTimer::GetTimeStep(), 3.0f); + float step = Min(CTimer::GetTimeStep(), 3.0f); float impulse = -GRAVITY*m_fMass*step * springConst * compression * bias*2.0f; ApplyMoveForce(springDir*impulse); ApplyTurnForce(springDir*impulse, point); @@ -471,12 +471,12 @@ CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &poin { float speedA = DotProduct(speed, springDir); float speedB = DotProduct(GetSpeed(point), springDir); - float step = min(CTimer::GetTimeStep(), 3.0f); + float step = Min(CTimer::GetTimeStep(), 3.0f); float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f; // what is this? float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass); - a = min(a, 1.0f); + a = Min(a, 1.0f); float b = Abs(impulse / (speedB * m_fMass)); if(a < b) impulse *= a/b; @@ -646,7 +646,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl // positive if B is moving towards A // not interested in how much B moves into A apparently? // only interested in cases where A collided into B - speedB = max(0.0f, DotProduct(B->m_vecMoveSpeed, colpoint.normal)); + speedB = Max(0.0f, DotProduct(B->m_vecMoveSpeed, colpoint.normal)); // A has moved into B if(speedA < speedB){ if(!A->bHasHitWall) @@ -1147,18 +1147,18 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) CVector dir = A->GetPosition() - B->GetPosition(); dir.Normalise(); if(dir.z < 0.0f && dir.z < A->GetForward().z && dir.z < A->GetRight().z) - dir.z = min(0.0f, min(A->GetForward().z, A->GetRight().z)); + dir.z = Min(0.0f, Min(A->GetForward().z, A->GetRight().z)); shift += dir * colpoints[mostColliding].depth * 0.5f; }else if(A->IsPed() && B->IsVehicle() && ((CVehicle*)B)->IsBoat()){ CVector dir = colpoints[mostColliding].normal; - float f = min(Abs(dir.z), 0.9f); + float f = Min(Abs(dir.z), 0.9f); dir.z = 0.0f; dir.Normalise(); shift += dir * colpoints[mostColliding].depth / (1.0f - f); boat = B; }else if(B->IsPed() && A->IsVehicle() && ((CVehicle*)A)->IsBoat()){ CVector dir = colpoints[mostColliding].normal * -1.0f; - float f = min(Abs(dir.z), 0.9f); + float f = Min(Abs(dir.z), 0.9f); dir.z = 0.0f; dir.Normalise(); B->GetPosition() += dir * colpoints[mostColliding].depth / (1.0f - f); @@ -1246,7 +1246,7 @@ collision: float turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr(); float moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); } }else if(A->bHasContacted){ CVector savedMoveFriction = A->m_vecMoveFriction; @@ -1268,7 +1268,7 @@ collision: float turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr(); float moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); if(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){ A->bHasContacted = true; @@ -1301,7 +1301,7 @@ collision: float turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr(); float moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); if(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){ A->bHasContacted = true; @@ -1328,7 +1328,7 @@ collision: float turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr(); float moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); if(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){ A->bHasContacted = true; @@ -1506,7 +1506,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, imp, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, imp, Max(turnSpeedDiff, moveSpeedDiff)); } }else{ for(i = 0; i < numCollisions; i++){ @@ -1527,7 +1527,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, imp, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, imp, Max(turnSpeedDiff, moveSpeedDiff)); float adhesion = CSurfaceTable::GetAdhesiveLimit(aColPoints[i]) / numCollisions; @@ -1545,7 +1545,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) else if(A->GetUp().z > 0.3f) adhesion = 0.0f; else - adhesion *= min(5.0f, 0.03f*impulseA + 1.0f); + adhesion *= Min(5.0f, 0.03f*impulseA + 1.0f); } if(A->ApplyFriction(adhesion, aColPoints[i])) @@ -1594,7 +1594,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) float turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr(); float moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); } }else if(A->bHasContacted){ CVector savedMoveFriction = A->m_vecMoveFriction; @@ -1619,7 +1619,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) float turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr(); float moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); if(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){ A->bHasContacted = true; @@ -1655,7 +1655,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) float turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr(); float moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); if(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){ A->bHasContacted = true; @@ -1685,7 +1685,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) float turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr(); float moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr(); - DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, max(turnSpeedDiff, moveSpeedDiff)); + DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff)); if(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){ A->bHasContacted = true; @@ -1831,7 +1831,7 @@ CPhysical::ProcessCollision(void) if(IsPed() && (distSq >= sq(0.2f) || ped->IsPlayer())){ if(ped->IsPlayer()) - n = max(NUMSTEPS(0.2f), 2.0f); + n = Max(NUMSTEPS(0.2f), 2.0f); else n = NUMSTEPS(0.3f); step = savedTimeStep / n; @@ -1852,7 +1852,7 @@ CPhysical::ProcessCollision(void) speedDown = Multiply3x3(GetMatrix(), speedDown); speedUp = GetSpeed(speedUp); speedDown = GetSpeed(speedDown); - distSq = max(speedUp.MagnitudeSqr(), speedDown.MagnitudeSqr()) * sq(CTimer::GetTimeStep()); + distSq = Max(speedUp.MagnitudeSqr(), speedDown.MagnitudeSqr()) * sq(CTimer::GetTimeStep()); if(distSq >= sq(0.3f)){ n = NUMSTEPS(0.3f); step = savedTimeStep / n; diff --git a/src/math/Vector.h b/src/math/Vector.h index 269ffc88..44e646e9 100644 --- a/src/math/Vector.h +++ b/src/math/Vector.h @@ -9,6 +9,11 @@ public: #ifdef RWCORE_H CVector(const RwV3d &v) : x(v.x), y(v.y), z(v.z) {} + RwV3d toRwV3d(void) const { + RwV3d vecRw = { this->x, this->y, this->z }; + return vecRw; + } + operator RwV3d (void) const { RwV3d vecRw = { this->x, this->y, this->z }; return vecRw; diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index d03dd405..c0ce38f8 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -214,7 +214,7 @@ CObject::ObjectDamage(float amount) ++nFrameGen; int32 currentFrame = nFrameGen & 3; float fRandom = CGeneral::GetRandomNumberInRange(0.01f, 1.0f); - RwRGBA randomColor = { color.red * fRandom, color.green * fRandom , color.blue, color.alpha }; + RwRGBA randomColor = { uint8(color.red * fRandom), uint8(color.green * fRandom) , color.blue, color.alpha }; float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f); int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0); @@ -237,7 +237,7 @@ CObject::ObjectDamage(float amount) ++nFrameGen; int32 currentFrame = nFrameGen & 3; float fRandom = CGeneral::GetRandomNumberInRange(0.5f, 0.5f); - RwRGBA randomColor = { color.red * fRandom, color.green * fRandom , color.blue * fRandom, color.alpha }; + RwRGBA randomColor = { uint8(color.red * fRandom), uint8(color.green * fRandom), uint8(color.blue * fRandom), color.alpha }; float fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.18f); int32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 80); CParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0); diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h index 9e28d272..34a672bb 100644 --- a/src/objects/ParticleObject.h +++ b/src/objects/ParticleObject.h @@ -1,6 +1,8 @@ #pragma once -#include "Placeable.h" + #include "AudioManager.h" +#include "ParticleType.h" +#include "Placeable.h" #define MAX_PARTICLEOBJECTS 100 #define MAX_AUDIOHYDRANTS 8 @@ -37,7 +39,6 @@ enum eParticleObjectState POBJECTSTATE_FREE, }; -enum tParticleType; class CParticle; class CParticleObject : public CPlaceable diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index f38f5a73..2dee0397 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -318,12 +318,12 @@ CCivilianPed::ProcessControl(void) if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= 10 && playerSexFrequency > 250) { CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + playerSexFrequency; if (playerSexFrequency >= 350) { - CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = max(250, playerSexFrequency - 30); + CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 30); } else { - CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = max(250, playerSexFrequency - 10); + CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 10); } - m_pMyVehicle->pDriver->m_fHealth = min(125.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth); + m_pMyVehicle->pDriver->m_fHealth = Min(125.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth); if (CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency == 250) CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000; } else { @@ -357,7 +357,7 @@ CCivilianPed::ProcessControl(void) if (playerMoney <= 1) { CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 250; } else { - CWorld::Players[CWorld::PlayerInFocus].m_nMoney = max(0, playerMoney - 1); + CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, playerMoney - 1); } CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000; } diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 81c9fa6e..98a07316 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -153,7 +153,7 @@ CCopPed::ClearPursuit(void) return; m_bIsInPursuit = false; - for (int i = 0; i < max(wanted->m_MaxCops, wanted->m_CurrentCops); ++i) { + for (int i = 0; i < Max(wanted->m_MaxCops, wanted->m_CurrentCops); ++i) { if (!foundMyself && wanted->m_pCops[i] == this) { wanted->m_pCops[i] = nil; --wanted->m_CurrentCops; @@ -342,7 +342,7 @@ CCopPed::CopAI(void) int oldCopNum = wanted->m_CurrentCops; int maxCops = wanted->m_MaxCops; - for (int i = 0; i < max(maxCops, oldCopNum); i++) { + 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; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 915c5d35..1f15aa6c 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -344,15 +344,15 @@ CPed::DebugRenderOnePedText(void) bitAbove.z += 2.0f; if (CSprite::CalcScreenCoors(bitAbove, &screenCoords, &width, &height, true)) { - float lineHeight = SCREEN_SCALE_Y(min(height/100.0f, 0.7f) * 22.0f); + float lineHeight = SCREEN_SCALE_Y(Min(height/100.0f, 0.7f) * 22.0f); DefinedState(); CFont::SetPropOn(); CFont::SetBackgroundOn(); // Originally both of them were being divided by 60.0f. - float xScale = min(width / 240.0f, 0.7f); - float yScale = min(height / 80.0f, 0.7f); + float xScale = Min(width / 240.0f, 0.7f); + float yScale = Min(height / 80.0f, 0.7f); CFont::SetScale(SCREEN_SCALE_X(xScale), SCREEN_SCALE_Y(yScale)); CFont::SetCentreOn(); @@ -1837,7 +1837,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) case ANIM_VAN_GETIN: #ifdef VC_PED_PORTS multExtractedFromAnim = true; - zBlend = max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.3f, 0.0f) / (1.0f - 0.3f); + zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.3f, 0.0f) / (1.0f - 0.3f); // fall through #endif case ANIM_CAR_QJACKED: @@ -1848,7 +1848,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) #ifdef VC_PED_PORTS if (!multExtractedFromAnim) { multExtractedFromAnim = true; - zBlend = max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.5f, 0.0f) / (1.0f - 0.5f); + zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.5f, 0.0f) / (1.0f - 0.5f); } // fall through #endif @@ -1863,7 +1863,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) #ifdef VC_PED_PORTS if (veh && veh->IsCar() && veh->bIsBus) { multExtractedFromAnimBus = true; - zBlend = min(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength, 0.5f) / 0.5f; + zBlend = Min(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength, 0.5f) / 0.5f; } // fall through #endif @@ -1943,7 +1943,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) neededPos.z = autoZPos.z; m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) { - adjustedTimeStep = min(m_pVehicleAnim->timeStep, 0.1f); + adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f); // Smoothly change ped position neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep); @@ -1965,12 +1965,12 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) if (m_pVehicleAnim && (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) { - adjustedTimeStep = min(m_pVehicleAnim->timeStep, 0.1f); + adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f); // Smoothly change ped position neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ; } else if (EnteringCar()) { - neededPos.z = max(currentZ, autoZPos.z); + neededPos.z = Max(currentZ, autoZPos.z); } #ifdef VC_PED_PORTS } @@ -2511,7 +2511,7 @@ CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil) CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f); invDamageNormal *= 1.0f / collPower; CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius; - forwardOffset = estimatedJumpDist * min(2.0f / collPower, 4.0f); + forwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f); } } else { pos.z -= 0.15f; @@ -5155,12 +5155,12 @@ CPed::FightStrike(CVector &touchedNodePos) float moveMult; if (m_lastFightMove == FIGHTMOVE_GROUNDKICK) { - moveMult = min(damageMult * 0.6f, 4.0f); + moveMult = Min(damageMult * 0.6f, 4.0f); } else { if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) { moveMult = damageMult; } else { - moveMult = min(damageMult * 2.0f, 14.0f); + moveMult = Min(damageMult * 2.0f, 14.0f); } } @@ -5884,7 +5884,7 @@ CPed::CreateDeadPedWeaponPickups(void) pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f; } if (found) - CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, min(weaponAmmo, AmmoForWeapon_OnStreet[weapon])); + CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon])); } ClearWeapons(); } @@ -5893,7 +5893,7 @@ void CPed::SetAttackTimer(uint32 time) { if (CTimer::GetTimeInMilliseconds() > m_attackTimer) - m_attackTimer = max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time; + m_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time; } void @@ -8676,7 +8676,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) distVec.Normalise(); #ifdef VC_PED_PORTS - distVec *= min(car->m_fMass / 1400.0f, 1.0f); + distVec *= Min(car->m_fMass / 1400.0f, 1.0f); #endif car->ApplyMoveForce(distVec * -100.0f); Say(SOUND_PED_DEFEND); @@ -8709,7 +8709,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse) m_vecMoveSpeed.z = 0.0f; distVec.Normalise(); #ifdef VC_PED_PORTS - distVec *= min(car->m_fMass / 1400.0f, 1.0f); + distVec *= Min(car->m_fMass / 1400.0f, 1.0f); #endif car->ApplyMoveForce(distVec * -60.0f); Say(SOUND_PED_DEFEND); @@ -10027,7 +10027,7 @@ CPed::ProcessControl(void) CVector offsetToCheck; m_nPedStateTimer++; - float adjustedTs = max(CTimer::GetTimeStep(), 0.01f); + float adjustedTs = Max(CTimer::GetTimeStep(), 0.01f); CPad *pad0 = CPad::GetPad(0); if ((m_nPedStateTimer <= 50.0f / (4.0f * adjustedTs) || m_nPedStateTimer * 0.01f <= forceDir.MagnitudeSqr()) @@ -10051,7 +10051,7 @@ CPed::ProcessControl(void) CColPoint obstacleForFlying, obstacleForFlyingOtherDir; // Check is there any room for being knocked up in reverse direction of force - if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlying, foundEnt, true, false, false, false, false, false, false)) { + if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlying, foundEnt, true, false, false, false, false, false, nil)) { obstacleForFlyingZ = obstacleForFlying.point.z; } else { obstacleForFlyingZ = 500.0f; @@ -10060,7 +10060,7 @@ CPed::ProcessControl(void) posToCheck = GetPosition() - offsetToCheck; // Now check for direction of force this time - if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlyingOtherDir, foundEnt, true, false, false, false, false, false, false)) { + if (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlyingOtherDir, foundEnt, true, false, false, false, false, false, nil)) { obstacleForFlyingOtherDirZ = obstacleForFlyingOtherDir.point.z; } else { obstacleForFlyingOtherDirZ = 501.0f; @@ -10180,7 +10180,7 @@ CPed::ProcessControl(void) offsetToCheck = GetPosition(); offsetToCheck.z += 0.5f; - if (CWorld::ProcessVerticalLine(offsetToCheck, GetPosition().z - FEET_OFFSET, foundCol, foundEnt, true, true, false, true, false, false, false)) { + if (CWorld::ProcessVerticalLine(offsetToCheck, GetPosition().z - FEET_OFFSET, foundCol, foundEnt, true, true, false, true, false, false, nil)) { #ifdef VC_PED_PORTS if (!bSomeVCflag1 || FEET_OFFSET + foundCol.point.z < GetPosition().z) { GetPosition().z = FEET_OFFSET + foundCol.point.z; @@ -12245,7 +12245,7 @@ CPed::PlacePedOnDryLand(void) 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)) { + if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) { foundColZ = foundCol.point.z; if (foundColZ >= waterLevel) { posToCheck.z = 0.8f + foundColZ; @@ -12259,7 +12259,7 @@ CPed::PlacePedOnDryLand(void) posToCheck = 5.0f * potentialGroundDist + GetPosition(); posToCheck.z = 3.0f + waterLevel; - if (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, false)) + if (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) return false; foundColZ = foundCol.point.z; @@ -13975,9 +13975,9 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj) CVector2D adjustedColMin(objColMin.x - 0.35f, objColMin.y - 0.35f); CVector2D adjustedColMax(objColMax.x + 0.35f, objColMax.y + 0.35f); - checkIntervalInDist = max(checkIntervalInDist, 0.5f); - checkIntervalInDist = min(checkIntervalInDist, (objColMax.z - objColMin.z) / 2.0f); - checkIntervalInDist = min(checkIntervalInDist, (adjustedColMax.x - adjustedColMin.x) / 2.0f); + checkIntervalInDist = Max(checkIntervalInDist, 0.5f); + checkIntervalInDist = Min(checkIntervalInDist, (objColMax.z - objColMin.z) / 2.0f); + checkIntervalInDist = Min(checkIntervalInDist, (adjustedColMax.x - adjustedColMin.x) / 2.0f); if (objMat.GetUp().z < 0.0f) objUpsideDown = true; @@ -14649,7 +14649,7 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2); } } else { - float damage = 100.0f * max(speed - 0.25f, 0.0f); + float damage = 100.0f * Max(speed - 0.25f, 0.0f); float damage2 = damage; if (m_vecMoveSpeed.z < -0.25f) damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f; @@ -14727,8 +14727,8 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints) #ifdef VC_PED_PORTS } else { float speed = m_vecMoveSpeed.Magnitude2D(); - sphereNormal.x = -m_vecMoveSpeed.x / max(0.001f, speed); - sphereNormal.y = -m_vecMoveSpeed.y / max(0.001f, speed); + sphereNormal.x = -m_vecMoveSpeed.x / Max(0.001f, speed); + sphereNormal.y = -m_vecMoveSpeed.y / Max(0.001f, speed); GetPosition().z -= 0.05f; bSomeVCflag1 = true; } @@ -15093,7 +15093,7 @@ CPed::ProcessBuoyancy(void) bTouchingWater = true; CEntity *entity; CColPoint point; - if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, false) + if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil) && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat()) { bIsInWater = false; return; @@ -15470,7 +15470,7 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode) if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil)) foundColZ2 = foundCol.point.z; - zForPed = max(foundColZ, foundColZ2); + zForPed = Max(foundColZ, foundColZ2); if (zForPed > -99.0f) GetPosition().z = FEET_OFFSET + zForPed; @@ -17069,7 +17069,7 @@ CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) // Because buses have stairs if (!m_pMyVehicle->bIsBus) - zDiff = max(0.0f, doorOpenPos.z - GetPosition().z); + zDiff = Max(0.0f, doorOpenPos.z - GetPosition().z); m_vecOffsetSeek = doorOpenPos - GetPosition(); m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600; @@ -17220,7 +17220,7 @@ CPed::WarpPedToNearEntityOffScreen(CEntity *warpTo) CVector appropriatePos = GetPosition(); CVector zCorrectedPos = appropriatePos; - int tryCount = min(10, halfOfDist); + int tryCount = Min(10, halfOfDist); for (int i = 0; i < tryCount; ++i) { appropriatePos += halfNormalizedDist; CPedPlacement::FindZCoorForPed(&zCorrectedPos); @@ -17254,7 +17254,7 @@ CPed::WarpPedToNearLeaderOffScreen(void) CVector appropriatePos = GetPosition(); CVector zCorrectedPos = appropriatePos; - int tryCount = min(10, halfOfDist); + int tryCount = Min(10, halfOfDist); for (int i = 0; i < tryCount; ++i) { appropriatePos += halfNormalizedDist; CPedPlacement::FindZCoorForPed(&zCorrectedPos); @@ -17296,7 +17296,7 @@ CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag) car->m_nGettingInFlags |= doorFlag; m_vecOffsetSeek = carEnterPos - GetPosition(); m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600; - float zDiff = max(0.0f, carEnterPos.z - GetPosition().z); + float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z); bUsesCollision = false; if (zDiff > 4.4f) { diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 90e16269..fd454528 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -1,12 +1,13 @@ #pragma once +#include "AnimManager.h" +#include "Crime.h" +#include "EventList.h" +#include "PedIK.h" +#include "PedStats.h" #include "Physical.h" #include "Weapon.h" -#include "PedStats.h" -#include "PedIK.h" -#include "AnimManager.h" #include "WeaponInfo.h" -#include "EventList.h" #define FEET_OFFSET 1.04f #define CHECK_NEARBY_THINGS_MAX_DIST 15.0f @@ -17,7 +18,6 @@ class CObject; class CFire; struct AnimBlendFrameData; class CAnimBlendAssociation; -enum eCrimeType; struct PedAudioData { diff --git a/src/peds/PedPlacement.cpp b/src/peds/PedPlacement.cpp index 6038cf91..8b8b3dfa 100644 --- a/src/peds/PedPlacement.cpp +++ b/src/peds/PedPlacement.cpp @@ -30,7 +30,7 @@ CPedPlacement::FindZCoorForPed(CVector* pos) if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, nil)) foundColZ2 = foundCol.point.z; - zForPed = max(foundColZ, foundColZ2); + zForPed = Max(foundColZ, foundColZ2); if (zForPed > -99.0f) pos->z = FEET_OFFSET + zForPed; diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 962c83df..0163c12c 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -182,7 +182,7 @@ CPlayerPed::MakeChangesForNewWeapon(int8 weapon) } SetCurrentWeapon(weapon); - GetWeapon()->m_nAmmoInClip = min(GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition); + GetWeapon()->m_nAmmoInClip = Min(GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition); if (!(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAim)) ClearWeaponTarget(); @@ -699,7 +699,7 @@ CPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed) #else m_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation); #endif - m_fMoveSpeed = min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed); + m_fMoveSpeed = Min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed); } else { m_fMoveSpeed = 0.0f; } @@ -1186,7 +1186,7 @@ CPlayerPed::PlayerControlZelda(CPad *padUsed) } float maxAcc = 0.07f * CTimer::GetTimeStep(); - m_fMoveSpeed = min(padMoveInGameUnit, m_fMoveSpeed + maxAcc); + m_fMoveSpeed = Min(padMoveInGameUnit, m_fMoveSpeed + maxAcc); } else { m_fMoveSpeed = 0.0f; @@ -1406,7 +1406,7 @@ CPlayerPed::ProcessControl(void) if (bVehEnterDoorIsBlocked || bKindaStayInSamePlace) { m_fMoveSpeed = 0.0f; } else { - m_fMoveSpeed = min(2.0f, 2.0f * (m_vecSeekPos - GetPosition()).Magnitude2D()); + m_fMoveSpeed = Min(2.0f, 2.0f * (m_vecSeekPos - GetPosition()).Magnitude2D()); } if (padUsed && !padUsed->ArePlayerControlsDisabled()) { if (padUsed->GetTarget() || padUsed->GetLeftStickXJustDown() || padUsed->GetLeftStickYJustDown() || diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index c1eee828..cd89a05d 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -595,7 +595,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); @@ -703,7 +703,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree if (!foundGround) return; - generatedCoors.z = max(generatedCoors.z, groundZ); + generatedCoors.z = Max(generatedCoors.z, groundZ); } bool farEnoughToAdd = true; CMatrix mat(TheCamera.GetCameraMatrix()); diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 58dc3f93..cb08a997 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -388,7 +388,7 @@ CClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue, ms_colourBottom.b = topblue; ms_colourBottom.a = alpha; - botpos = min(SCREEN_HEIGHT, topedge); + botpos = Min(SCREEN_HEIGHT, topedge); CSprite2d::DrawRect(CRect(0, 0, SCREEN_WIDTH, botpos), ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop); } @@ -415,18 +415,18 @@ CClouds::RenderHorizon(void) if(ms_horizonZ > SCREEN_HEIGHT) return; - float z1 = min(ms_horizonZ + SMALLSTRIPHEIGHT, SCREEN_HEIGHT); + float z1 = Min(ms_horizonZ + SMALLSTRIPHEIGHT, SCREEN_HEIGHT); CSprite2d::DrawRectXLU(CRect(0, ms_horizonZ, SCREEN_WIDTH, z1), ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop); // This is just weird float a = SCREEN_HEIGHT/400.0f * HORIZSTRIPHEIGHT + - SCREEN_HEIGHT/300.0f * max(TheCamera.GetPosition().z, 0.0f); + SCREEN_HEIGHT/300.0f * Max(TheCamera.GetPosition().z, 0.0f); float b = TheCamera.GetUp().z < 0.0f ? SCREEN_HEIGHT : SCREEN_HEIGHT * Abs(TheCamera.GetRight().z); float z2 = z1 + (a + b)*TheCamera.LODDistMultiplier; - z2 = min(z2, SCREEN_HEIGHT); + z2 = Min(z2, SCREEN_HEIGHT); CSprite2d::DrawRect(CRect(0, z1, SCREEN_WIDTH, z2), ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop); } diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp index b21e087b..de3b5c78 100644 --- a/src/render/Coronas.cpp +++ b/src/render/Coronas.cpp @@ -106,7 +106,7 @@ CCoronas::Update(void) int i; static int LastCamLook = 0; - LightsMult = min(LightsMult + 0.03f * CTimer::GetTimeStep(), 1.0f); + LightsMult = Min(LightsMult + 0.03f * CTimer::GetTimeStep(), 1.0f); int CamLook = 0; if(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft) CamLook |= 1; @@ -118,7 +118,7 @@ CCoronas::Update(void) if(LastCamLook != CamLook) bChangeBrightnessImmediately = 3; else - bChangeBrightnessImmediately = max(bChangeBrightnessImmediately-1, 0); + bChangeBrightnessImmediately = Max(bChangeBrightnessImmediately-1, 0); LastCamLook = CamLook; for(i = 0; i < NUMCORONAS; i++) @@ -305,7 +305,7 @@ CCoronas::Render(void) // render corona itself if(aCoronas[i].texture){ - float fogscale = CWeather::Foggyness*min(spriteCoors.z, 40.0f)/40.0f + 1.0f; + float fogscale = CWeather::Foggyness*Min(spriteCoors.z, 40.0f)/40.0f + 1.0f; if(CCoronas::aCoronas[i].id == SUN_CORE) spriteCoors.z = 0.95f * RwCameraGetFarClipPlane(Scene.camera); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(aCoronas[i].texture)); @@ -316,7 +316,7 @@ CCoronas::Render(void) float f = 1.0f - aCoronas[i].someAngle*2.0f/PI; float wscale = 6.0f*sq(sq(sq(f))) + 0.5f; float hscale = 0.35f - (wscale - 0.5f) * 0.06f; - hscale = max(hscale, 0.15f); + hscale = Max(hscale, 0.15f); CSprite::RenderOneXLUSprite(spriteCoors.x, spriteCoors.y, spriteCoors.z, spritew * aCoronas[i].size * wscale, @@ -466,7 +466,7 @@ CCoronas::RenderReflections(void) float spritew, spriteh; if(CSprite::CalcScreenCoors(coors, spriteCoors, &spritew, &spriteh, true)){ float drawDist = 0.75f * aCoronas[i].drawDist; - drawDist = min(drawDist, 50.0f); + drawDist = Min(drawDist, 50.0f); if(spriteCoors.z < drawDist){ float fadeDistance = drawDist / 2.0f; float distanceFade = spriteCoors.z < fadeDistance ? 1.0f : 1.0f - (spriteCoors.z - fadeDistance)/fadeDistance; @@ -545,25 +545,25 @@ CRegisteredCorona::Update(void) (CCoronas::SunBlockedByClouds && id == CCoronas::SUN_CORONA || !CWorld::GetIsLineOfSightClear(coors, TheCamera.GetPosition(), true, false, false, false, false, false))){ // Corona is blocked, fade out - fadeAlpha = max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), 0.0f); + fadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), 0.0f); }else if(offScreen){ // Same when off screen - fadeAlpha = max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), 0.0f); + fadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), 0.0f); }else{ // Visible if(alpha > fadeAlpha){ // fade in - fadeAlpha = min(fadeAlpha + 15.0f*CTimer::GetTimeStep(), alpha); + fadeAlpha = Min(fadeAlpha + 15.0f*CTimer::GetTimeStep(), alpha); if(CCoronas::bChangeBrightnessImmediately) fadeAlpha = alpha; }else if(alpha < fadeAlpha){ // too visible, decrease alpha but not below alpha - fadeAlpha = max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), alpha); + fadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), alpha); } // darken scene when the sun is visible if(id == CCoronas::SUN_CORONA) - CCoronas::LightsMult = max(CCoronas::LightsMult - CTimer::GetTimeStep()*0.06f, 0.6f); + CCoronas::LightsMult = Max(CCoronas::LightsMult - CTimer::GetTimeStep()*0.06f, 0.6f); } // remove if invisible diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index 33e22c87..9a4dbcfe 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -6,7 +6,7 @@ #include "General.h" #include "AudioScriptObject.h" #include "World.h" -#include "TimeCycle.h" +#include "Timecycle.h" #include "Particle.h" #include "Camera.h" #include "RenderBuffer.h" @@ -617,12 +617,12 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector c = object->GetMatrix() * col->vertices[2]; CVector d = object->GetMatrix() * col->vertices[3]; - float minx = min(min(a.x, b.x), min(c.x, d.x)); - float maxx = max(max(a.x, b.x), max(c.x, d.x)); - float miny = min(min(a.y, b.y), min(c.y, d.y)); - float maxy = max(max(a.y, b.y), max(c.y, d.y)); - float minz = min(min(a.z, b.z), min(c.z, d.z)); - float maxz = max(max(a.z, b.z), max(c.z, d.z)); + float minx = Min(Min(a.x, b.x), Min(c.x, d.x)); + float maxx = Max(Max(a.x, b.x), Max(c.x, d.x)); + float miny = Min(Min(a.y, b.y), Min(c.y, d.y)); + float maxy = Max(Max(a.y, b.y), Max(c.y, d.y)); + float minz = Min(Min(a.z, b.z), Min(c.z, d.z)); + float maxz = Max(Max(a.z, b.z), Max(c.z, d.z)); if ( amount > 300.0f ) diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index fc399741..01512383 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -136,7 +136,7 @@ void CHud::Draw() if (DrawCrossHair || DrawCrossHairPC) { RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); - SpriteBrightness = min(SpriteBrightness+1, 30); + SpriteBrightness = Min(SpriteBrightness+1, 30); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); @@ -715,7 +715,7 @@ void CHud::Draw() } else { int counter = atoi(CUserDisplay::OnscnTimer.m_sEntries[0].m_bCounterBuffer); #ifdef FIX_BUGS - counter = min(counter, 100); + counter = Min(counter, 100); #endif CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(11.0f) + SCREEN_SCALE_Y(8.0f)), CRGBA(0, 106, 164, 80)); CSprite2d::DrawRect(CRect(SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET) - SCREEN_SCALE_X(100.0f) / 2 + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f), SCREEN_SCALE_X(counter) / 2.0f + SCREEN_SCALE_FROM_RIGHT(TIMER_RIGHT_OFFSET + 50.0f) + SCREEN_SCALE_X(4.0f), SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(11.0f) + SCREEN_SCALE_Y(8.0f)), CRGBA(0, 106, 164, 255)); @@ -1206,7 +1206,7 @@ void CHud::DrawAfterFade() OddJob2On = 2; } else { - fStep = min(40.0f, OddJob2XOffset / 6.0f); + fStep = Min(40.0f, OddJob2XOffset / 6.0f); OddJob2XOffset = OddJob2XOffset - fStep; } break; @@ -1217,7 +1217,7 @@ void CHud::DrawAfterFade() } break; case 3: - fStep = max(30.0f, OddJob2XOffset / 5.0f); + fStep = Max(30.0f, OddJob2XOffset / 5.0f); OddJob2XOffset = OddJob2XOffset - fStep; diff --git a/src/render/ParticleMgr.cpp b/src/render/ParticleMgr.cpp index 4bfb6380..00391ac5 100644 --- a/src/render/ParticleMgr.cpp +++ b/src/render/ParticleMgr.cpp @@ -91,7 +91,7 @@ void cParticleSystemMgr::LoadParticleData() break; case CFG_PARAM_INITIAL_COLOR_VARIATION: - entry->m_InitialColorVariation = min(atoi(value), 100); + entry->m_InitialColorVariation = Min(atoi(value), 100); break; case CFG_PARAM_FADE_DESTINATION_COLOR_R: diff --git a/src/render/ParticleMgr.h b/src/render/ParticleMgr.h index 605e69fe..0b4091de 100644 --- a/src/render/ParticleMgr.h +++ b/src/render/ParticleMgr.h @@ -1,82 +1,8 @@ #pragma once -class CParticle; +#include "ParticleType.h" -enum tParticleType -{ - PARTICLE_SPARK = 0, - PARTICLE_SPARK_SMALL, - PARTICLE_WHEEL_DIRT, - PARTICLE_WHEEL_WATER, - PARTICLE_BLOOD, - PARTICLE_BLOOD_SMALL, - PARTICLE_BLOOD_SPURT, - PARTICLE_DEBRIS, - PARTICLE_DEBRIS2, - PARTICLE_WATER, - PARTICLE_FLAME, - PARTICLE_FIREBALL, - PARTICLE_GUNFLASH, - PARTICLE_GUNFLASH_NOANIM, - PARTICLE_GUNSMOKE, - PARTICLE_GUNSMOKE2, - PARTICLE_SMOKE, - PARTICLE_SMOKE_SLOWMOTION, - PARTICLE_GARAGEPAINT_SPRAY, - PARTICLE_SHARD, - PARTICLE_SPLASH, - PARTICLE_CARFLAME, - PARTICLE_STEAM, - PARTICLE_STEAM2, - PARTICLE_STEAM_NY, - PARTICLE_STEAM_NY_SLOWMOTION, - PARTICLE_ENGINE_STEAM, - PARTICLE_RAINDROP, - PARTICLE_RAINDROP_SMALL, - PARTICLE_RAIN_SPLASH, - PARTICLE_RAIN_SPLASH_BIGGROW, - PARTICLE_RAIN_SPLASHUP, - PARTICLE_WATERSPRAY, - PARTICLE_EXPLOSION_MEDIUM, - PARTICLE_EXPLOSION_LARGE, - PARTICLE_EXPLOSION_MFAST, - PARTICLE_EXPLOSION_LFAST, - PARTICLE_CAR_SPLASH, - PARTICLE_BOAT_SPLASH, - PARTICLE_BOAT_THRUSTJET, - PARTICLE_BOAT_WAKE, - PARTICLE_WATER_HYDRANT, - PARTICLE_WATER_CANNON, - PARTICLE_EXTINGUISH_STEAM, - PARTICLE_PED_SPLASH, - PARTICLE_PEDFOOT_DUST, - PARTICLE_HELI_DUST, - PARTICLE_HELI_ATTACK, - PARTICLE_ENGINE_SMOKE, - PARTICLE_ENGINE_SMOKE2, - PARTICLE_CARFLAME_SMOKE, - PARTICLE_FIREBALL_SMOKE, - PARTICLE_PAINT_SMOKE, - PARTICLE_TREE_LEAVES, - PARTICLE_CARCOLLISION_DUST, - PARTICLE_CAR_DEBRIS, - PARTICLE_HELI_DEBRIS, - PARTICLE_EXHAUST_FUMES, - PARTICLE_RUBBER_SMOKE, - PARTICLE_BURNINGRUBBER_SMOKE, - PARTICLE_BULLETHIT_SMOKE, - PARTICLE_GUNSHELL_FIRST, - PARTICLE_GUNSHELL, - PARTICLE_GUNSHELL_BUMP1, - PARTICLE_GUNSHELL_BUMP2, - PARTICLE_TEST, - PARTICLE_BIRD_FRONT, - PARTICLE_RAINDROP_2D, - - MAX_PARTICLES, - PARTICLE_FIRST = PARTICLE_SPARK, - PARTICLE_LAST = PARTICLE_RAINDROP_2D -}; +class CParticle; enum { diff --git a/src/render/ParticleType.h b/src/render/ParticleType.h new file mode 100644 index 00000000..8d352c44 --- /dev/null +++ b/src/render/ParticleType.h @@ -0,0 +1,77 @@ +#pragma once + +enum tParticleType +{ + PARTICLE_SPARK = 0, + PARTICLE_SPARK_SMALL, + PARTICLE_WHEEL_DIRT, + PARTICLE_WHEEL_WATER, + PARTICLE_BLOOD, + PARTICLE_BLOOD_SMALL, + PARTICLE_BLOOD_SPURT, + PARTICLE_DEBRIS, + PARTICLE_DEBRIS2, + PARTICLE_WATER, + PARTICLE_FLAME, + PARTICLE_FIREBALL, + PARTICLE_GUNFLASH, + PARTICLE_GUNFLASH_NOANIM, + PARTICLE_GUNSMOKE, + PARTICLE_GUNSMOKE2, + PARTICLE_SMOKE, + PARTICLE_SMOKE_SLOWMOTION, + PARTICLE_GARAGEPAINT_SPRAY, + PARTICLE_SHARD, + PARTICLE_SPLASH, + PARTICLE_CARFLAME, + PARTICLE_STEAM, + PARTICLE_STEAM2, + PARTICLE_STEAM_NY, + PARTICLE_STEAM_NY_SLOWMOTION, + PARTICLE_ENGINE_STEAM, + PARTICLE_RAINDROP, + PARTICLE_RAINDROP_SMALL, + PARTICLE_RAIN_SPLASH, + PARTICLE_RAIN_SPLASH_BIGGROW, + PARTICLE_RAIN_SPLASHUP, + PARTICLE_WATERSPRAY, + PARTICLE_EXPLOSION_MEDIUM, + PARTICLE_EXPLOSION_LARGE, + PARTICLE_EXPLOSION_MFAST, + PARTICLE_EXPLOSION_LFAST, + PARTICLE_CAR_SPLASH, + PARTICLE_BOAT_SPLASH, + PARTICLE_BOAT_THRUSTJET, + PARTICLE_BOAT_WAKE, + PARTICLE_WATER_HYDRANT, + PARTICLE_WATER_CANNON, + PARTICLE_EXTINGUISH_STEAM, + PARTICLE_PED_SPLASH, + PARTICLE_PEDFOOT_DUST, + PARTICLE_HELI_DUST, + PARTICLE_HELI_ATTACK, + PARTICLE_ENGINE_SMOKE, + PARTICLE_ENGINE_SMOKE2, + PARTICLE_CARFLAME_SMOKE, + PARTICLE_FIREBALL_SMOKE, + PARTICLE_PAINT_SMOKE, + PARTICLE_TREE_LEAVES, + PARTICLE_CARCOLLISION_DUST, + PARTICLE_CAR_DEBRIS, + PARTICLE_HELI_DEBRIS, + PARTICLE_EXHAUST_FUMES, + PARTICLE_RUBBER_SMOKE, + PARTICLE_BURNINGRUBBER_SMOKE, + PARTICLE_BULLETHIT_SMOKE, + PARTICLE_GUNSHELL_FIRST, + PARTICLE_GUNSHELL, + PARTICLE_GUNSHELL_BUMP1, + PARTICLE_GUNSHELL_BUMP2, + PARTICLE_TEST, + PARTICLE_BIRD_FRONT, + PARTICLE_RAINDROP_2D, + + MAX_PARTICLES, + PARTICLE_FIRST = PARTICLE_SPARK, + PARTICLE_LAST = PARTICLE_RAINDROP_2D +}; \ No newline at end of file diff --git a/src/render/PointLights.cpp b/src/render/PointLights.cpp index 55be40b2..b92e7e83 100644 --- a/src/render/PointLights.cpp +++ b/src/render/PointLights.cpp @@ -98,7 +98,7 @@ CPointLights::GenerateLightsAffectingObject(CVector *objCoors) if(aLights[i].type == LIGHT_DIRECTIONAL){ float dot = -DotProduct(dir, aLights[i].dir); - intensity *= max((dot-0.5f)*2.0f, 0.0f); + intensity *= Max((dot-0.5f)*2.0f, 0.0f); } if(intensity > 0.0f) diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp index 31110046..d21dd558 100644 --- a/src/render/Rubbish.cpp +++ b/src/render/Rubbish.cpp @@ -217,9 +217,9 @@ CRubbish::Update(void) // FRAMETIME if(bRubbishInvisible) - RubbishVisibility = max(RubbishVisibility-5, 0); + RubbishVisibility = Max(RubbishVisibility-5, 0); else - RubbishVisibility = min(RubbishVisibility+5, 255); + RubbishVisibility = Min(RubbishVisibility+5, 255); // Spawn a new sheet COneSheet *sheet = StartEmptyList.m_next; diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 330f1b06..319cdd3c 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -719,10 +719,10 @@ CShadows::RenderStoredShadows(void) float fStartY = shadowPos.y - fHeight; float fEndY = shadowPos.y + fHeight; - int32 nStartX = max(CWorld::GetSectorIndexX(fStartX), 0); - int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0); - int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X-1); - int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y-1); + int32 nStartX = Max(CWorld::GetSectorIndexX(fStartX), 0); + int32 nStartY = Max(CWorld::GetSectorIndexY(fStartY), 0); + int32 nEndX = Min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X-1); + int32 nEndY = Min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y-1); CWorld::AdvanceCurrentScanCode(); @@ -865,10 +865,10 @@ CShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID) float fStartY = shadowPos.y - fHeight; float fEndY = shadowPos.y + fHeight; - int32 nStartX = max(CWorld::GetSectorIndexX(fStartX), 0); - int32 nStartY = max(CWorld::GetSectorIndexY(fStartY), 0); - int32 nEndX = min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X-1); - int32 nEndY = min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y-1); + int32 nStartX = Max(CWorld::GetSectorIndexX(fStartX), 0); + int32 nStartY = Max(CWorld::GetSectorIndexY(fStartY), 0); + int32 nEndX = Min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X-1); + int32 nEndY = Min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y-1); CWorld::AdvanceCurrentScanCode(); @@ -1008,11 +1008,11 @@ CShadows::CastShadowEntity(CEntity *pEntity, float fStartX, float fStartY, floa Points[3].x = (fLengthRight - fFrontRight) - fSideRight; Points[3].y = (fLengthForward - fFrontForward) - fSideForward; - float MinX = min(min(Points[0].x, Points[1].x), min(Points[2].x, Points[3].x)); - float MaxX = max(max(Points[0].x, Points[1].x), max(Points[2].x, Points[3].x)); + float MinX = Min(Min(Points[0].x, Points[1].x), Min(Points[2].x, Points[3].x)); + float MaxX = Max(Max(Points[0].x, Points[1].x), Max(Points[2].x, Points[3].x)); - float MinY = min(min(Points[0].y, Points[1].y), min(Points[2].y, Points[3].y)); - float MaxY = max(max(Points[0].y, Points[1].y), max(Points[2].y, Points[3].y)); + float MinY = Min(Min(Points[0].y, Points[1].y), Min(Points[2].y, Points[3].y)); + float MaxY = Max(Max(Points[0].y, Points[1].y), Max(Points[2].y, Points[3].y)); float MaxZ = pPosn->z - pEntity->GetPosition().z; float MinZ = MaxZ - fZDistance; @@ -1763,7 +1763,7 @@ CShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTextur { ASSERT(pPosn != NULL); - C3dMarkers::PlaceMarkerSet(nID, _TODOCONST(4), *pPosn, max(fFrontX, -fSideY), + C3dMarkers::PlaceMarkerSet(nID, _TODOCONST(4), *pPosn, Max(fFrontX, -fSideY), 0, 128, 255, 128, 2048, 0.2f, 0); } diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp index e47015a0..cf3426d7 100644 --- a/src/render/Timecycle.cpp +++ b/src/render/Timecycle.cpp @@ -290,7 +290,7 @@ CTimeCycle::Update(void) TheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, m_fCurrentBlurAlpha, MBLUR_NORMAL); if(m_FogReduction != 0) - m_fCurrentFarClip = max(m_fCurrentFarClip, m_FogReduction/64.0f * 650.0f); + m_fCurrentFarClip = Max(m_fCurrentFarClip, m_FogReduction/64.0f * 650.0f); m_nCurrentFogColourRed = (m_nCurrentSkyTopRed + 2*m_nCurrentSkyBottomRed) / 3; m_nCurrentFogColourGreen = (m_nCurrentSkyTopGreen + 2*m_nCurrentSkyBottomGreen) / 3; m_nCurrentFogColourBlue = (m_nCurrentSkyTopBlue + 2*m_nCurrentSkyBottomBlue) / 3; @@ -311,7 +311,7 @@ CTimeCycle::Update(void) if(TheCamera.GetForward().z < -0.9f || !CWeather::bScriptsForceRain && (CCullZones::PlayerNoRain() || CCullZones::CamNoRain() || CCutsceneMgr::IsRunning())) - m_FogReduction = min(m_FogReduction+1, 64); + m_FogReduction = Min(m_FogReduction+1, 64); else - m_FogReduction = max(m_FogReduction-1, 0); + m_FogReduction = Max(m_FogReduction-1, 0); } diff --git a/src/render/WaterCannon.cpp b/src/render/WaterCannon.cpp index 1a9b983f..2ef10d77 100644 --- a/src/render/WaterCannon.cpp +++ b/src/render/WaterCannon.cpp @@ -195,14 +195,14 @@ void CWaterCannon::PushPeds(void) { if ( m_abUsed[i] ) { - minx = min(minx, m_avecPos[i].x); - maxx = max(maxx, m_avecPos[i].x); + minx = Min(minx, m_avecPos[i].x); + maxx = Max(maxx, m_avecPos[i].x); - miny = min(miny, m_avecPos[i].y); - maxy = max(maxy, m_avecPos[i].y); + miny = Min(miny, m_avecPos[i].y); + maxy = Max(maxy, m_avecPos[i].y); - minz = min(minz, m_avecPos[i].z); - maxz = max(maxz, m_avecPos[i].z); + minz = Min(minz, m_avecPos[i].z); + maxz = Max(maxz, m_avecPos[i].z); } } diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp index ad0b3ec4..d7035ab1 100644 --- a/src/render/WaterLevel.cpp +++ b/src/render/WaterLevel.cpp @@ -979,7 +979,7 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col SMALL_SECTOR_SIZE / 2, apBoatList) ) { - float fWakeColor = fAdd1 - max(255.0f - float(color.blue + color.red + color.green) / 3, fAdd2); + float fWakeColor = fAdd1 - Max(255.0f - float(color.blue + color.red + color.green) / 3, fAdd2); RpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic); RpGeometry *geom = apGeomArray[nGeomUsed++]; @@ -1035,9 +1035,9 @@ CWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &col RwRGBAAssign(&wakeColor, &color); - wakeColor.red = min(color.red + int32(fWakeColor * fRedMult * fDistMult), 255); - wakeColor.green = min(color.green + int32(fWakeColor * fGreenMult * fDistMult), 255); - wakeColor.blue = min(color.blue + int32(fWakeColor * fBlueMult * fDistMult), 255); + wakeColor.red = Min(color.red + int32(fWakeColor * fRedMult * fDistMult), 255); + wakeColor.green = Min(color.green + int32(fWakeColor * fGreenMult * fDistMult), 255); + wakeColor.blue = Min(color.blue + int32(fWakeColor * fBlueMult * fDistMult), 255); RwRGBAAssign(&geomPreLights[9*i+j], &wakeColor); @@ -1114,7 +1114,7 @@ CWaterLevel::CalcDistanceToWater(float fX, float fY) fSectorY + SMALL_SECTOR_SIZE - fY ); - fDistSqr = min(vecDist.MagnitudeSqr(), fDistSqr); + fDistSqr = Min(vecDist.MagnitudeSqr(), fDistSqr); } } } diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp index 8bc544c6..b4031705 100644 --- a/src/render/Weather.cpp +++ b/src/render/Weather.cpp @@ -163,7 +163,7 @@ void CWeather::Update(void) else { // 0.125 probability LightningBurst = false; - LightningDuration = min(CTimer::GetFrameCounter() - LightningStart, 20); + LightningDuration = Min(CTimer::GetFrameCounter() - LightningStart, 20); LightningFlash = false; WhenToPlayLightningSound = CTimer::GetTimeInMilliseconds() + 150 * (20 - LightningDuration); } @@ -219,9 +219,9 @@ void CWeather::Update(void) fNewRain = 0.0f; if (Rain != fNewRain) { // ok to use comparasion if (Rain < fNewRain) - Rain = min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); + Rain = Min(fNewRain, Rain + RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); else - Rain = max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); + Rain = Max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep()); } // Clouds diff --git a/src/rw/Lights.cpp b/src/rw/Lights.cpp index 9c5d4f22..5a253854 100644 --- a/src/rw/Lights.cpp +++ b/src/rw/Lights.cpp @@ -37,9 +37,9 @@ SetLightsWithTimeOfDayColour(RpWorld *) AmbientLightColourForFrame.green = 1.0f; AmbientLightColourForFrame.blue = 1.0f; } - AmbientLightColourForFrame_PedsCarsAndObjects.red = min(1.0f, AmbientLightColourForFrame.red*1.3f); - AmbientLightColourForFrame_PedsCarsAndObjects.green = min(1.0f, AmbientLightColourForFrame.green*1.3f); - AmbientLightColourForFrame_PedsCarsAndObjects.blue = min(1.0f, AmbientLightColourForFrame.blue*1.3f); + AmbientLightColourForFrame_PedsCarsAndObjects.red = Min(1.0f, AmbientLightColourForFrame.red*1.3f); + AmbientLightColourForFrame_PedsCarsAndObjects.green = Min(1.0f, AmbientLightColourForFrame.green*1.3f); + AmbientLightColourForFrame_PedsCarsAndObjects.blue = Min(1.0f, AmbientLightColourForFrame.blue*1.3f); RpLightSetColor(pAmbient, &AmbientLightColourForFrame); } @@ -70,20 +70,20 @@ SetLightsWithTimeOfDayColour(RpWorld *) float f1 = 2.0f * (CMenuManager::m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f; float f2 = 3.0f * (CMenuManager::m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f; - AmbientLightColourForFrame.red = min(1.0f, AmbientLightColourForFrame.red * f2); - AmbientLightColourForFrame.green = min(1.0f, AmbientLightColourForFrame.green * f2); - AmbientLightColourForFrame.blue = min(1.0f, AmbientLightColourForFrame.blue * f2); - AmbientLightColourForFrame_PedsCarsAndObjects.red = min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.red * f1); - AmbientLightColourForFrame_PedsCarsAndObjects.green = min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.green * f1); - AmbientLightColourForFrame_PedsCarsAndObjects.blue = min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.blue * f1); + AmbientLightColourForFrame.red = Min(1.0f, AmbientLightColourForFrame.red * f2); + AmbientLightColourForFrame.green = Min(1.0f, AmbientLightColourForFrame.green * f2); + AmbientLightColourForFrame.blue = Min(1.0f, AmbientLightColourForFrame.blue * f2); + AmbientLightColourForFrame_PedsCarsAndObjects.red = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.red * f1); + AmbientLightColourForFrame_PedsCarsAndObjects.green = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.green * f1); + AmbientLightColourForFrame_PedsCarsAndObjects.blue = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.blue * f1); #ifdef FIX_BUGS - DirectionalLightColourForFrame.red = min(1.0f, DirectionalLightColourForFrame.red * f1); - DirectionalLightColourForFrame.green = min(1.0f, DirectionalLightColourForFrame.green * f1); - DirectionalLightColourForFrame.blue = min(1.0f, DirectionalLightColourForFrame.blue * f1); + DirectionalLightColourForFrame.red = Min(1.0f, DirectionalLightColourForFrame.red * f1); + DirectionalLightColourForFrame.green = Min(1.0f, DirectionalLightColourForFrame.green * f1); + DirectionalLightColourForFrame.blue = Min(1.0f, DirectionalLightColourForFrame.blue * f1); #else - DirectionalLightColourForFrame.red = min(1.0f, AmbientLightColourForFrame.red * f1); - DirectionalLightColourForFrame.green = min(1.0f, AmbientLightColourForFrame.green * f1); - DirectionalLightColourForFrame.blue = min(1.0f, AmbientLightColourForFrame.blue * f1); + DirectionalLightColourForFrame.red = Min(1.0f, AmbientLightColourForFrame.red * f1); + DirectionalLightColourForFrame.green = Min(1.0f, AmbientLightColourForFrame.green * f1); + DirectionalLightColourForFrame.blue = Min(1.0f, AmbientLightColourForFrame.blue * f1); #endif } } @@ -193,7 +193,7 @@ AddAnExtraDirectionalLight(RpWorld *world, float dirx, float diry, float dirz, f RwRGBAReal color; RwV3d *dir; - strength = max(max(red, green), blue); + strength = Max(Max(red, green), blue); n = -1; if(NumExtraDirLightsInWorld < NUMEXTRADIRECTIONALS) n = NumExtraDirLightsInWorld; @@ -221,7 +221,7 @@ AddAnExtraDirectionalLight(RpWorld *world, float dirx, float diry, float dirz, f RwFrameUpdateObjects(RpLightGetFrame(pExtraDirectionals[n])); RpLightSetFlags(pExtraDirectionals[n], rpLIGHTLIGHTATOMICS); LightStrengths[n] = strength; - NumExtraDirLightsInWorld = min(NumExtraDirLightsInWorld+1, NUMEXTRADIRECTIONALS); + NumExtraDirLightsInWorld = Min(NumExtraDirLightsInWorld+1, NUMEXTRADIRECTIONALS); } void diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 2d0aadcc..1b14e7a2 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -692,7 +692,7 @@ CAutomobile::ProcessControl(void) if(m_aSuspensionSpringRatio[i] < 1.0f) m_aWheelTimer[i] = 4.0f; else - m_aWheelTimer[i] = max(m_aWheelTimer[i]-CTimer::GetTimeStep(), 0.0f); + m_aWheelTimer[i] = Max(m_aWheelTimer[i]-CTimer::GetTimeStep(), 0.0f); if(m_aWheelTimer[i] > 0.0f){ m_nWheelsOnGround++; @@ -1010,7 +1010,7 @@ CAutomobile::ProcessControl(void) if(m_status != STATUS_PLAYER && m_status != STATUS_PLAYER_REMOTE && m_status != STATUS_PHYSICS){ if(GetModelIndex() == MI_MIAMI_RCRAIDER || GetModelIndex() == MI_MIAMI_SPARROW) - m_aWheelSpeed[0] = max(m_aWheelSpeed[0]-0.0005f, 0.0f); + m_aWheelSpeed[0] = Max(m_aWheelSpeed[0]-0.0005f, 0.0f); }else if((GetModelIndex() == MI_DODO || CVehicle::bAllDodosCheat) && m_vecMoveSpeed.Magnitude() > 0.0f && CTimer::GetTimeStep() > 0.0f){ FlyingControl(FLIGHT_MODEL_DODO); @@ -1018,7 +1018,7 @@ CAutomobile::ProcessControl(void) FlyingControl(FLIGHT_MODEL_RCPLANE); }else if(GetModelIndex() == MI_MIAMI_RCRAIDER || GetModelIndex() == MI_MIAMI_SPARROW || bAllCarCheat){ if(CPad::GetPad(0)->GetCircleJustDown()) - m_aWheelSpeed[0] = max(m_aWheelSpeed[0]-0.03f, 0.0f); + m_aWheelSpeed[0] = Max(m_aWheelSpeed[0]-0.03f, 0.0f); if(m_aWheelSpeed[0] < 0.22f) m_aWheelSpeed[0] += 0.0001f; if(m_aWheelSpeed[0] > 0.15f) @@ -1130,10 +1130,10 @@ CAutomobile::ProcessControl(void) if(speed > sq(0.1f)){ speed = Sqrt(speed); if(suspShake > 0.0f){ - uint8 freq = min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f); + uint8 freq = Min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f); CPad::GetPad(0)->StartShake(20000.0f*CTimer::GetTimeStep()/freq, freq); }else{ - uint8 freq = min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 145.0f); + uint8 freq = Min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 145.0f); CPad::GetPad(0)->StartShake(5000.0f*CTimer::GetTimeStep()/freq, freq); } } @@ -2601,7 +2601,7 @@ CAutomobile::HydraulicControl(void) float minz = pos.z + extendedLowerLimit - wheelRadius; if(minz < specialColModel->boundingBox.min.z) specialColModel->boundingBox.min.z = minz; - float radius = max(specialColModel->boundingBox.min.Magnitude(), specialColModel->boundingBox.max.Magnitude()); + float radius = Max(specialColModel->boundingBox.min.Magnitude(), specialColModel->boundingBox.max.Magnitude()); if(specialColModel->boundingSphere.radius < radius) specialColModel->boundingSphere.radius = radius; @@ -2700,10 +2700,10 @@ CAutomobile::HydraulicControl(void) float front = -rear; float right = CPad::GetPad(0)->GetCarGunLeftRight()/128.0f; float left = -right; - suspChange[CARWHEEL_FRONT_LEFT] = max(front+left, 0.0f); - suspChange[CARWHEEL_REAR_LEFT] = max(rear+left, 0.0f); - suspChange[CARWHEEL_FRONT_RIGHT] = max(front+right, 0.0f); - suspChange[CARWHEEL_REAR_RIGHT] = max(rear+right, 0.0f); + suspChange[CARWHEEL_FRONT_LEFT] = Max(front+left, 0.0f); + suspChange[CARWHEEL_REAR_LEFT] = Max(rear+left, 0.0f); + suspChange[CARWHEEL_FRONT_RIGHT] = Max(front+right, 0.0f); + suspChange[CARWHEEL_REAR_RIGHT] = Max(rear+right, 0.0f); if(m_hydraulicState < 100){ // Lowered, move wheels up @@ -2819,7 +2819,7 @@ CAutomobile::ProcessBuoyancy(void) ApplyTurnForce(impulse, point); CVector initialSpeed = m_vecMoveSpeed; - float timeStep = max(CTimer::GetTimeStep(), 0.01f); + float timeStep = Max(CTimer::GetTimeStep(), 0.01f); float impulseRatio = impulse.z / (GRAVITY * m_fMass * timeStep); float waterResistance = Pow(1.0f - 0.05f*impulseRatio, CTimer::GetTimeStep()); m_vecMoveSpeed *= waterResistance; @@ -2912,7 +2912,7 @@ CAutomobile::ProcessBuoyancy(void) float fSpeed = vSpeed.MagnitudeSqr(); if(fSpeed > sq(0.05f)){ fSpeed = Sqrt(fSpeed); - float size = min((fSpeed < 0.15f ? 0.25f : 0.75f)*fSpeed, 0.6f); + float size = Min((fSpeed < 0.15f ? 0.25f : 0.75f)*fSpeed, 0.6f); CVector right = 0.2f*fSpeed*GetRight() + 0.2f*vSpeed; CParticle::AddParticle(PARTICLE_PED_SPLASH, @@ -2994,11 +2994,11 @@ CAutomobile::DoDriveByShootings(void) // TODO: what is this? if(!lookingLeft && m_weaponDoorTimerLeft > 0.0f){ - m_weaponDoorTimerLeft = max(m_weaponDoorTimerLeft - CTimer::GetTimeStep()*0.1f, 0.0f); + m_weaponDoorTimerLeft = Max(m_weaponDoorTimerLeft - CTimer::GetTimeStep()*0.1f, 0.0f); ProcessOpenDoor(CAR_DOOR_LF, NUM_ANIMS, m_weaponDoorTimerLeft); } if(!lookingRight && m_weaponDoorTimerRight > 0.0f){ - m_weaponDoorTimerRight = max(m_weaponDoorTimerRight - CTimer::GetTimeStep()*0.1f, 0.0f); + m_weaponDoorTimerRight = Max(m_weaponDoorTimerRight - CTimer::GetTimeStep()*0.1f, 0.0f); ProcessOpenDoor(CAR_DOOR_RF, NUM_ANIMS, m_weaponDoorTimerRight); } } @@ -3146,7 +3146,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) FindPlayerPed()->SetWantedLevelNoDrop(1); if(m_status == STATUS_PLAYER && impulse > 50.0f){ - uint8 freq = min(0.4f*impulse*2000.0f/m_fMass + 100.0f, 250.0f); + uint8 freq = Min(0.4f*impulse*2000.0f/m_fMass + 100.0f, 250.0f); CPad::GetPad(0)->StartShake(40000/freq, freq); } @@ -3299,7 +3299,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) if(m_pDamageEntity && m_pDamageEntity == FindPlayerVehicle() && impulse > 10.0f){ int money = (doubleMoney ? 2 : 1) * impulse*pHandling->nMonetaryValue/1000000.0f; - money = min(money, 40); + money = Min(money, 40); if(money > 2){ sprintf(gString, "$%d", money); CWorld::Players[CWorld::PlayerInFocus].m_nMoney += money; @@ -4004,7 +4004,7 @@ CAutomobile::SetupSuspensionLines(void) // adjust col model to include suspension lines if(colModel->boundingBox.min.z > colModel->lines[0].p1.z) colModel->boundingBox.min.z = colModel->lines[0].p1.z; - float radius = max(colModel->boundingBox.min.Magnitude(), colModel->boundingBox.max.Magnitude()); + float radius = Max(colModel->boundingBox.min.Magnitude(), colModel->boundingBox.max.Magnitude()); if(colModel->boundingSphere.radius < radius) colModel->boundingSphere.radius = radius; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index ed38bafd..42beeb6c 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -272,7 +272,7 @@ CBoat::ProcessControl(void) impulse = m_vecMoveSpeed.MagnitudeSqr()*pHandling->fSuspensionForceLevel*buoyanceImpulse.z*CTimer::GetTimeStep()*0.5f*m_fGasPedal; else impulse = 0.0f; - impulse = min(impulse, GRAVITY*pHandling->fSuspensionDampingLevel*m_fMass*CTimer::GetTimeStep()); + impulse = Min(impulse, GRAVITY*pHandling->fSuspensionDampingLevel*m_fMass*CTimer::GetTimeStep()); ApplyMoveForce(impulse*GetUp()); ApplyTurnForce(impulse*GetUp(), buoyancePoint - pHandling->fSuspensionBias*GetForward()); } @@ -375,10 +375,10 @@ CBoat::ProcessControl(void) } // Slow down or push down boat as it approaches the world limits - m_vecMoveSpeed.x = min(m_vecMoveSpeed.x, -(GetPosition().x - 1900.0f)*0.01f); // east - m_vecMoveSpeed.x = max(m_vecMoveSpeed.x, -(GetPosition().x - -1515.0f)*0.01f); // west - m_vecMoveSpeed.y = min(m_vecMoveSpeed.y, -(GetPosition().y - 600.0f)*0.01f); // north - m_vecMoveSpeed.y = max(m_vecMoveSpeed.y, -(GetPosition().y - -1900.0f)*0.01f); // south + m_vecMoveSpeed.x = Min(m_vecMoveSpeed.x, -(GetPosition().x - 1900.0f)*0.01f); // east + m_vecMoveSpeed.x = Max(m_vecMoveSpeed.x, -(GetPosition().x - -1515.0f)*0.01f); // west + m_vecMoveSpeed.y = Min(m_vecMoveSpeed.y, -(GetPosition().y - 600.0f)*0.01f); // north + m_vecMoveSpeed.y = Max(m_vecMoveSpeed.y, -(GetPosition().y - -1900.0f)*0.01f); // south if(!onLand && bBoatInWater) ApplyWaterResistance(); @@ -765,7 +765,7 @@ CBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat) float fDist = vecDist.MagnitudeSqr(); if ( fDist < SQR(fMaxDist) ) - return 1.0f - min(fRangeMult * Sqrt(fDist / SQR(fMaxDist)) + (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fTimeMult, 1.0f); + return 1.0f - Min(fRangeMult * Sqrt(fDist / SQR(fMaxDist)) + (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fTimeMult, 1.0f); } return 0.0f; @@ -837,7 +837,7 @@ CBoat::AddWakePoint(CVector point) int i; if(m_afWakePointLifeTime[0] > 0.0f){ if((CVector2D(GetPosition()) - m_avec2dWakePoints[0]).MagnitudeSqr() < SQR(1.0f)){ - for(i = min(m_nNumWakePoints, ARRAY_SIZE(m_afWakePointLifeTime)-1); i != 0; i--){ + for(i = Min(m_nNumWakePoints, ARRAY_SIZE(m_afWakePointLifeTime)-1); i != 0; i--){ m_avec2dWakePoints[i] = m_avec2dWakePoints[i-1]; m_afWakePointLifeTime[i] = m_afWakePointLifeTime[i-1]; } diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index 4156ec2a..64743929 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -157,7 +157,7 @@ void CCarGenerator::Setup(float x, float y, float z, float angle, int32 mi, int1 m_bIsBlocking = false; m_vecInf = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.min; m_vecSup = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.max; - m_fSize = max(m_vecInf.Magnitude(), m_vecSup.Magnitude()); + m_fSize = Max(m_vecInf.Magnitude(), m_vecSup.Magnitude()); } bool CCarGenerator::CheckForBlockage() diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index ef19873c..7d2160d9 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -213,10 +213,10 @@ void CCrane::Update(void) CTimer::GetTimeInMilliseconds() > m_nTimeForNextCheck) { CWorld::AdvanceCurrentScanCode(); #ifdef FIX_BUGS - int xstart = max(0, CWorld::GetSectorIndexX(m_fPickupX1)); - int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fPickupX2)); - int ystart = max(0, CWorld::GetSectorIndexY(m_fPickupY1)); - int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fPickupY2)); + int xstart = Max(0, CWorld::GetSectorIndexX(m_fPickupX1)); + int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fPickupX2)); + int ystart = Max(0, CWorld::GetSectorIndexY(m_fPickupY1)); + int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fPickupY2)); #else int xstart = CWorld::GetSectorIndexX(m_fPickupX1); int xend = CWorld::GetSectorIndexX(m_fPickupX2); diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 6a83a30e..0073a5ad 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -231,19 +231,19 @@ CHeli::ProcessControl(void) switch(m_heliStatus){ case HELI_STATUS_HOVER: groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil); - m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f; + m_fTargetZ = Max(groundZ, m_fTargetZ) + 8.0f; break; case HELI_STATUS_SHOT_DOWN: groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil); - m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset; + m_fTargetZ = Max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset; break; case HELI_STATUS_HOVER2: groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil); - m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset; + m_fTargetZ = Max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset; break; default: groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil); - m_fTargetZ = max(groundZ, m_fTargetZ) + 12.0f; + m_fTargetZ = Max(groundZ, m_fTargetZ) + 12.0f; break; } @@ -1017,7 +1017,7 @@ CHeli::TestBulletCollision(CVector *line0, CVector *line1, CVector *bulletPos, i float distToHeli = (pHelis[i]->GetPosition() - *line0).Magnitude(); CVector line = (*line1 - *line0); float lineLength = line.Magnitude(); - *bulletPos = *line0 + line*max(1.0f, distToHeli-5.0f); + *bulletPos = *line0 + line*Max(1.0f, distToHeli-5.0f); pHelis[i]->m_nBulletDamage += damage; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 0ed83f87..c09375cc 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -281,7 +281,7 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon right = -contactSpeedRight/wheelsOnGround; if(wheelStatus == WHEEL_STATUS_BURST){ - float fwdspeed = min(contactSpeedFwd, 0.3f); + float fwdspeed = Min(contactSpeedFwd, 0.3f); right += fwdspeed * CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); } } @@ -533,7 +533,7 @@ CVehicle::DoFixedMachineGuns(void) void CVehicle::ExtinguishCarFire(void) { - m_fHealth = max(m_fHealth, 300.0f); + m_fHealth = Max(m_fHealth, 300.0f); if(m_pCarFire) m_pCarFire->Extinguish(); if(IsCar()){ @@ -874,13 +874,13 @@ CVehicle::SetDriver(CPed *driver) if(bFreebies && driver == FindPlayerPed()){ if(GetModelIndex() == MI_AMBULAN) - FindPlayerPed()->m_fHealth = min(FindPlayerPed()->m_fHealth + 20.0f, 100.0f); + FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, 100.0f); else if(GetModelIndex() == MI_TAXI) CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25; else if(GetModelIndex() == MI_POLICE) driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5); else if(GetModelIndex() == MI_ENFORCER) - driver->m_fArmour = max(driver->m_fArmour, 100.0f); + driver->m_fArmour = Max(driver->m_fArmour, 100.0f); else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE) CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25; bFreebies = false; diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp index abf5c061..36c3cc78 100644 --- a/src/weapons/BulletInfo.cpp +++ b/src/weapons/BulletInfo.cpp @@ -232,35 +232,35 @@ bool CBulletInfo::TestForSniperBullet(float x1, float x2, float y1, float y2, fl #else float minP = 0.0f; float maxP = 1.0f; - float minX = min(PlayerSniperBulletStart.x, PlayerSniperBulletEnd.x); - float maxX = max(PlayerSniperBulletStart.x, PlayerSniperBulletEnd.x); + float minX = Min(PlayerSniperBulletStart.x, PlayerSniperBulletEnd.x); + float maxX = Max(PlayerSniperBulletStart.x, PlayerSniperBulletEnd.x); if (minX < x2 || maxX > x1) { if (minX < x1) - minP = min(minP, (x1 - minX) / (maxX - minX)); + minP = Min(minP, (x1 - minX) / (maxX - minX)); if (maxX > x2) - maxP = max(maxP, (maxX - x2) / (maxX - minX)); + maxP = Max(maxP, (maxX - x2) / (maxX - minX)); } else return false; - float minY = min(PlayerSniperBulletStart.y, PlayerSniperBulletEnd.y); - float maxY = max(PlayerSniperBulletStart.y, PlayerSniperBulletEnd.y); + float minY = Min(PlayerSniperBulletStart.y, PlayerSniperBulletEnd.y); + float maxY = Max(PlayerSniperBulletStart.y, PlayerSniperBulletEnd.y); if (minY < y2 || maxY > y1) { if (minY < y1) - minP = min(minP, (y1 - minY) / (maxY - minY)); + minP = Min(minP, (y1 - minY) / (maxY - minY)); if (maxY > y2) - maxP = max(maxP, (maxY - y2) / (maxY - minY)); + maxP = Max(maxP, (maxY - y2) / (maxY - minY)); } #ifdef FIX_BUGS else return false; #endif - float minZ = min(PlayerSniperBulletStart.z, PlayerSniperBulletEnd.z); - float maxZ = max(PlayerSniperBulletStart.z, PlayerSniperBulletEnd.z); + float minZ = Min(PlayerSniperBulletStart.z, PlayerSniperBulletEnd.z); + float maxZ = Max(PlayerSniperBulletStart.z, PlayerSniperBulletEnd.z); if (minZ < z2 || maxZ > z1) { if (minZ < z1) - minP = min(minP, (z1 - minZ) / (maxZ - minZ)); + minP = Min(minP, (z1 - minZ) / (maxZ - minZ)); if (maxZ > z2) - maxP = max(maxP, (maxZ - z2) / (maxZ - minZ)); + maxP = Max(maxP, (maxZ - z2) / (maxZ - minZ)); } else return false; diff --git a/src/weapons/BulletInfo.h b/src/weapons/BulletInfo.h index c7d740b2..cf1dd27f 100644 --- a/src/weapons/BulletInfo.h +++ b/src/weapons/BulletInfo.h @@ -1,7 +1,8 @@ #pragma once +#include "WeaponType.h" + class CEntity; -enum eWeaponType; class CBulletInfo { diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h index b88322f9..3d8074c9 100644 --- a/src/weapons/ProjectileInfo.h +++ b/src/weapons/ProjectileInfo.h @@ -1,9 +1,10 @@ #pragma once +#include "WeaponType.h" + class CEntity; class CObject; class CProjectile; -enum eWeaponType; class CProjectileInfo { diff --git a/src/weapons/ShotInfo.cpp b/src/weapons/ShotInfo.cpp index 83ce2a02..f09ae052 100644 --- a/src/weapons/ShotInfo.cpp +++ b/src/weapons/ShotInfo.cpp @@ -109,7 +109,7 @@ CShotInfo::Update() if (shot.m_sourceEntity) { assert(shot.m_sourceEntity->IsPed()); CPed *ped = (CPed*) shot.m_sourceEntity; - float radius = max(1.0f, shot.m_radius); + float radius = Max(1.0f, shot.m_radius); for (int i = 0; i < ped->m_numNearPeds; ++i) { CPed *nearPed = ped->m_nearPeds[i]; diff --git a/src/weapons/ShotInfo.h b/src/weapons/ShotInfo.h index a5e5fd35..db6158c2 100644 --- a/src/weapons/ShotInfo.h +++ b/src/weapons/ShotInfo.h @@ -1,7 +1,8 @@ #pragma once +#include "WeaponType.h" + class CEntity; -enum eWeaponType; class CShotInfo { diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 276693e8..b7ccb455 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -107,9 +107,11 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) CVector fireOffset(0.0f, 0.0f, 0.6f); CVector *source = fireSource; - if ( !fireSource ) - source = &(shooter->GetMatrix() * fireOffset); - + if (!fireSource) { + static CVector tmp; + tmp = shooter->GetMatrix() * fireOffset; + source = &tmp; + } if ( m_bAddRotOffset ) { float heading = RADTODEG(shooter->GetForward().Heading()); @@ -997,7 +999,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); CVector dist = point->point - (*source); - CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(ahead.x, ahead.y, 0.0f); + CVector offset = dist - Max(0.2f*dist.Magnitude(), 2.0f) * CVector(ahead.x, ahead.y, 0.0f); CVector smokePos = *source + offset; smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); @@ -1016,7 +1018,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); CVector dist = point->point - (*source); - CVector offset = dist - max(0.2f*dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f); + CVector offset = dist - Max(0.2f*dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f); CVector smokePos = *source + offset; CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); @@ -1265,7 +1267,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); CVector dist = point.point - (*fireSource); - CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); + CVector offset = dist - Max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); CVector smokePos = *fireSource + offset; CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); @@ -1280,7 +1282,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); CVector dist = point.point - (*fireSource); - CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); + CVector offset = dist - Max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); CVector smokePos = *fireSource + offset; smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); @@ -1347,7 +1349,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) else { CVector traceTarget = *fireSource; - traceTarget += (target - (*fireSource)) * min(info->m_fRange, 30.0f) / info->m_fRange; + traceTarget += (target - (*fireSource)) * Min(info->m_fRange, 30.0f) / info->m_fRange; CBulletTraces::AddTrace(fireSource, &traceTarget); } } @@ -1877,8 +1879,9 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV if ( 3.0f*distToVictimZ < distToVictim ) { + CVector tmp = CVector(victim->GetPosition().x, victim->GetPosition().y, 0.0f); if ( CCollision::DistToLine(source, target, - &CVector(victim->GetPosition().x, victim->GetPosition().y, 0.0f)) < victim->GetBoundRadius()*3.0f ) + &tmp) < victim->GetBoundRadius()*3.0f ) { float vehicleDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ)); if ( vehicleDist < closestEntityDist ) @@ -2145,12 +2148,12 @@ CWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target ASSERT(source!=nil); ASSERT(target!=nil); - float minx = min(source->x, target->x) - 2.0f; - float maxx = max(source->x, target->x) + 2.0f; - float miny = min(source->y, target->y) - 2.0f; - float maxy = max(source->y, target->y) + 2.0f; - float minz = min(source->z, target->z) - 2.0f; - float maxz = max(source->z, target->z) + 2.0f; + float minx = Min(source->x, target->x) - 2.0f; + float maxx = Max(source->x, target->x) + 2.0f; + float miny = Min(source->y, target->y) - 2.0f; + float maxy = Max(source->y, target->y) + 2.0f; + float minz = Min(source->z, target->z) - 2.0f; + float maxz = Max(source->z, target->z) + 2.0f; for ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) { diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 265ffddb..2c3a9657 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -1,56 +1,10 @@ #pragma once +#include "WeaponType.h" + #define DRIVEBYAUTOAIMING_MAXDIST (2.5f) #define DOOMAUTOAIMING_MAXDIST (9000.0f) -enum eWeaponType -{ - WEAPONTYPE_UNARMED, - WEAPONTYPE_BASEBALLBAT, - WEAPONTYPE_COLT45, - WEAPONTYPE_UZI, - WEAPONTYPE_SHOTGUN, - WEAPONTYPE_AK47, - WEAPONTYPE_M16, - WEAPONTYPE_SNIPERRIFLE, - WEAPONTYPE_ROCKETLAUNCHER, - WEAPONTYPE_FLAMETHROWER, - WEAPONTYPE_MOLOTOV, - WEAPONTYPE_GRENADE, - WEAPONTYPE_DETONATOR, - WEAPONTYPE_HELICANNON, - WEAPONTYPE_LAST_WEAPONTYPE, - WEAPONTYPE_ARMOUR, - WEAPONTYPE_RAMMEDBYCAR, - WEAPONTYPE_RUNOVERBYCAR, - WEAPONTYPE_EXPLOSION, - WEAPONTYPE_UZI_DRIVEBY, - WEAPONTYPE_DROWNING, - WEAPONTYPE_FALL, - WEAPONTYPE_UNIDENTIFIED, - - WEAPONTYPE_TOTALWEAPONS = WEAPONTYPE_LAST_WEAPONTYPE, - WEAPONTYPE_TOTAL_INVENTORY_WEAPONS = 13, -}; - -enum eWeaponFire { - WEAPON_FIRE_MELEE, - WEAPON_FIRE_INSTANT_HIT, - WEAPON_FIRE_PROJECTILE, - WEAPON_FIRE_AREA_EFFECT, - WEAPON_FIRE_USE -}; - -// Taken from MTA SA, seems it's unchanged -enum eWeaponState -{ - WEAPONSTATE_READY, - WEAPONSTATE_FIRING, - WEAPONSTATE_RELOADING, - WEAPONSTATE_OUT_OF_AMMO, - WEAPONSTATE_MELEE_MADECONTACT -}; - class CEntity; class CPhysical; class CAutomobile; diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h index f82f18c5..3bafd324 100644 --- a/src/weapons/WeaponInfo.h +++ b/src/weapons/WeaponInfo.h @@ -1,8 +1,7 @@ #pragma once -enum AnimationId; -enum eWeaponFire; -enum eWeaponType; +#include "AnimationId.h" +#include "WeaponType.h" class CWeaponInfo { // static CWeaponInfo(&ms_apWeaponInfos)[14]; diff --git a/src/weapons/WeaponType.h b/src/weapons/WeaponType.h new file mode 100644 index 00000000..b45740b7 --- /dev/null +++ b/src/weapons/WeaponType.h @@ -0,0 +1,49 @@ +#pragma once + +enum eWeaponType +{ + WEAPONTYPE_UNARMED, + WEAPONTYPE_BASEBALLBAT, + WEAPONTYPE_COLT45, + WEAPONTYPE_UZI, + WEAPONTYPE_SHOTGUN, + WEAPONTYPE_AK47, + WEAPONTYPE_M16, + WEAPONTYPE_SNIPERRIFLE, + WEAPONTYPE_ROCKETLAUNCHER, + WEAPONTYPE_FLAMETHROWER, + WEAPONTYPE_MOLOTOV, + WEAPONTYPE_GRENADE, + WEAPONTYPE_DETONATOR, + WEAPONTYPE_HELICANNON, + WEAPONTYPE_LAST_WEAPONTYPE, + WEAPONTYPE_ARMOUR, + WEAPONTYPE_RAMMEDBYCAR, + WEAPONTYPE_RUNOVERBYCAR, + WEAPONTYPE_EXPLOSION, + WEAPONTYPE_UZI_DRIVEBY, + WEAPONTYPE_DROWNING, + WEAPONTYPE_FALL, + WEAPONTYPE_UNIDENTIFIED, + + WEAPONTYPE_TOTALWEAPONS = WEAPONTYPE_LAST_WEAPONTYPE, + WEAPONTYPE_TOTAL_INVENTORY_WEAPONS = 13, +}; + +enum eWeaponFire { + WEAPON_FIRE_MELEE, + WEAPON_FIRE_INSTANT_HIT, + WEAPON_FIRE_PROJECTILE, + WEAPON_FIRE_AREA_EFFECT, + WEAPON_FIRE_USE +}; + +// Taken from MTA SA, seems it's unchanged +enum eWeaponState +{ + WEAPONSTATE_READY, + WEAPONSTATE_FIRING, + WEAPONSTATE_RELOADING, + WEAPONSTATE_OUT_OF_AMMO, + WEAPONSTATE_MELEE_MADECONTACT +}; \ No newline at end of file From 36f7550f8402e533b89a8e2d531647a0f79669f4 Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 20 Apr 2020 19:20:22 +0200 Subject: [PATCH 096/123] updated librw again --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 8b677c4d..808290e7 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 8b677c4dd77a73da68447556e3b07c6c0371629e +Subproject commit 808290e73efaa7e52f69875d1d5d8f18c30e019b From 6494bdaf114704346a2be38b8f46a573e1d5f4ea Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 20 Apr 2020 20:17:34 +0200 Subject: [PATCH 097/123] librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 808290e7..5fa0e179 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 808290e73efaa7e52f69875d1d5d8f18c30e019b +Subproject commit 5fa0e179866e12d5933107232675428664914016 From 6571715cb29c65d149a0d7101ece28fb09649306 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 21 Apr 2020 01:27:27 +0200 Subject: [PATCH 098/123] librw skin pipe --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 5fa0e179..a2b79a71 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 5fa0e179866e12d5933107232675428664914016 +Subproject commit a2b79a71aa45e083c18789a21e8c99990b1a5202 From 9c2fd41bce44f83c3936383e7923f76b43a1008e Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 21 Apr 2020 13:40:44 +0200 Subject: [PATCH 099/123] librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index a2b79a71..752fceb1 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit a2b79a71aa45e083c18789a21e8c99990b1a5202 +Subproject commit 752fceb1e3c4ce06b6f20b9c4471927821469bf2 From 959f84ff9566297701064e30b46fd292e7e840a1 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 21 Apr 2020 13:56:33 +0200 Subject: [PATCH 100/123] fixed extra directory issues --- src/core/Directory.cpp | 14 ++++++++++++++ src/core/Directory.h | 1 + src/core/Streaming.cpp | 6 +++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/core/Directory.cpp b/src/core/Directory.cpp index 27539824..cc4d65d8 100644 --- a/src/core/Directory.cpp +++ b/src/core/Directory.cpp @@ -41,9 +41,23 @@ void CDirectory::AddItem(const DirectoryInfo &dirinfo) { assert(numEntries < maxEntries); +#ifdef FIX_BUGS + // don't add if already exists + uint32 offset, size; + if(FindItem(dirinfo.name, offset, size)) + return; +#endif entries[numEntries++] = dirinfo; } +void +CDirectory::AddItem(const DirectoryInfo &dirinfo, int32 imgId) +{ + DirectoryInfo di = dirinfo; + di.offset |= imgId<<24; + AddItem(di); +} + bool CDirectory::FindItem(const char *name, uint32 &offset, uint32 &size) { diff --git a/src/core/Directory.h b/src/core/Directory.h index 06e6bba4..0fef080f 100644 --- a/src/core/Directory.h +++ b/src/core/Directory.h @@ -18,5 +18,6 @@ public: void ReadDirFile(const char *filename); bool WriteDirFile(const char *filename); void AddItem(const DirectoryInfo &dirinfo); + void AddItem(const DirectoryInfo &dirinfo, int32 imgId); bool FindItem(const char *name, uint32 &offset, uint32 &size); }; diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 15fe60e2..8124d11c 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -369,8 +369,12 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) lastID = modelId; } }else{ - // BUG: doesn't remember which cdimage this was in +#ifdef FIX_BUGS + // remember which cdimage this came from + ms_pExtraObjectsDir->AddItem(direntry, n); +#else ms_pExtraObjectsDir->AddItem(direntry); +#endif lastID = -1; } }else if(!CGeneral::faststrcmp(dot+1, "TXD") || !CGeneral::faststrcmp(dot+1, "txd")){ From 2cb0df1ef3201bcdf2884d0a46a8390ad66775d5 Mon Sep 17 00:00:00 2001 From: withmorten Date: Tue, 21 Apr 2020 15:09:08 +0200 Subject: [PATCH 101/123] switch out milessdk with fake miles header and lib --- milessdk/include/mss.h | 4885 +--------------------------------------- milessdk/lib/mss32.lib | Bin 246322 -> 15316 bytes 2 files changed, 98 insertions(+), 4787 deletions(-) diff --git a/milessdk/include/mss.h b/milessdk/include/mss.h index fbc91c73..38371eb9 100644 --- a/milessdk/include/mss.h +++ b/milessdk/include/mss.h @@ -1,4805 +1,116 @@ -//############################################################################ -//## ## -//## Miles Sound System ## -//## ## -//## MSS.H: Miles Sound System main header file ## -//## ## -//## Version 1.00 of 15-Feb-95: Initial, derived from AIL.H V3.02 ## -//## 1.01 of 19-Jun-95: Added various functions for V3.03 release ## -//## 1.02 of 22-Nov-95: C++ typedef problem fixed, declspecs added ## -//## 1.03 of 15-Feb-96: Changes for 16 bit callbacks and multiple ## -//## 16 bit DLL loads (JKR) ## -//## 1.04 of 2-Nov-97: Changes made to handle DLS in future ## -//## versions ## -//## 1.05 of 1-Jan-98: Massive changes for version 4.0 ## -//## 1.06 of 17-Sep-98: Massive changes for version 5.0 ## -//## 1.07 of 2-Feb-99: Changes for new input API ## -//## 1.08 of 8-Feb-99: Changes for new filter helper functions ## -//## ## -//## Author: John Miles ## -//## ## -//############################################################################ -//## ## -//## Contact RAD Game Tools at 425-893-4300 for technical support. ## -//## ## -//############################################################################ +#pragma once -#ifndef MSS_VERSION +// fake mss.h header for use with re3, to make using mss32.dll possible +// gta3 uses miles 6.1a +// check https://github.com/withmorten/re3mss for more info -#define MSS_VERSION "6.1a" -#define MSS_MAJOR_VERSION 6 -#define MSS_MINOR_VERSION 1 -#define MSS_SUB_VERSION 1 -#define MSS_VERSION_DATE "06-Mar-01" +#include -#define MSS_COPYRIGHT "Copyright (C) 1991-2001, RAD Game Tools, Inc." - -#endif - -#ifndef MSS_H -#define MSS_H - -// IS_DOS for DOS -// IS_WINDOWS for Windows or Win32s -// IS_WIN32 for Win32s -// IS_WIN16 for Windows -// IS_32 for 32-bit DOS or Win32s -// IS_16 for 16-bit Windows -// IS_LE for little endian (PCs) -// IS_BE for big endian (Macs) -// IS_X86 for Intel -// IS_MAC for Mac -// IS_PPC for PPC Mac -// IS_68K for 68K Mac - - -#ifdef IS_DOS -#undef IS_DOS -#endif - -#ifdef IS_WINDOWS -#undef IS_WINDOWS -#endif - -#ifdef IS_WIN32 -#undef IS_WIN32 -#endif - -#ifdef IS_WIN16 -#undef IS_WIN16 -#endif - -#ifdef IS_32 -#undef IS_32 -#endif - -#ifdef IS_16 -#undef IS_16 -#endif - -#ifdef IS_LE -#undef IS_LE -#endif - -#ifdef IS_BE -#undef IS_BE -#endif - -#ifdef IS_X86 -#undef IS_X86 -#endif - -#ifdef IS_MAC -#undef IS_MAC -#endif - -#ifdef IS_PPC -#undef IS_PPC -#endif - -#ifdef IS_68K -#undef IS_68K -#endif - -#ifdef __DOS__ - #define IS_DOS - #define IS_32 - #define IS_LE - #define IS_X86 -#else - #ifdef _WIN32 - #define IS_WINDOWS - #define IS_WIN32 - #define IS_32 - #define IS_LE - #define IS_X86 - #else - #ifdef WIN32 - #define IS_WINDOWS - #define IS_WIN32 - #define IS_32 - #define IS_LE - #define IS_X86 - #else - #ifdef __NT__ - #define IS_WINDOWS - #define IS_WIN32 - #define IS_32 - #define IS_LE - #define IS_X86 - #else - #ifdef __WIN32__ - #define IS_WINDOWS - #define IS_WIN32 - #define IS_32 - #define IS_LE - #define IS_X86 - #else - #ifdef _WINDOWS - #define IS_WINDOWS - #define IS_WIN16 - #define IS_16 - #define IS_LE - #define IS_X86 - #else - #ifdef _WINDLL - #define IS_WINDOWS - #define IS_WIN16 - #define IS_16 - #define IS_LE - #define IS_X86 - #else - #ifdef WINDOWS - #define IS_WINDOWS - #define IS_WIN16 - #define IS_16 - #define IS_LE - #define IS_X86 - #else - #ifdef __WINDOWS__ - #define IS_WINDOWS - #define IS_WIN16 - #define IS_16 - #define IS_LE - #define IS_X86 - #else - #ifdef _Windows - #define IS_WINDOWS - #define IS_WIN16 - #define IS_16 - #define IS_LE - #define IS_X86 - #else - #if defined(macintosh) || defined(__powerc) || defined(powerc) || defined(__POWERPC__) || defined(__MC68K__) - #define IS_MAC - #define IS_32 - #define IS_BE - #if defined(__powerc) || defined(powerc) || defined(__POWERPC__) - #define IS_PPC - #else - #if defined(__MC68K__) - #define IS_68K - #endif - #endif - #endif - #endif - #endif - #endif - #endif - #endif - #endif - #endif - #endif - #endif -#endif - -#if (!defined(IS_LE) && !defined(IS_BE)) - #error MSS.H did not detect your platform. Define __DOS__, _WINDOWS, WIN32, or macintosh. -#endif - - -#if defined(_PUSHPOP_SUPPORTED) || PRAGMA_STRUCT_PACKPUSH - #pragma pack(push,1) -#else - #pragma pack(1) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef IS_DOS - -#define AILCALLBACK __pascal -#define AILEXPORT cdecl -#define DXDEC extern -#define DXDEF -#define AILCALL cdecl -#define FAR -#define HIWORD(ptr) (((U32)ptr)>>16) -#define LOWORD(ptr) ((U16)((U32)ptr)) - -#define FOURCC U32 - -#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ - ((U32)(U8)(ch0) | ((U32)(U8)(ch1) << 8) | \ - ((U32)(U8)(ch2) << 16) | ((U32)(U8)(ch3) << 24 )) - -#define mmioFOURCC(w,x,y,z) MAKEFOURCC(w,x,y,z) - -#define AILLIBCALLBACK __pascal - -#define MSS_MAIN_DEF - -#define MSS_REDIST_DIR_NAME "DOS" - -#define MSS_DIR_SEP "\\" -#define MSS_DIR_UP ".." MSS_DIR_SEP -#define MSS_DIR_UP_TWO MSS_DIR_UP MSS_DIR_UP - -#else - -#ifdef IS_WINDOWS - -#define AILLIBCALLBACK WINAPI - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#ifndef WIN32_EXTRA_LEAN -#define WIN32_EXTRA_LEAN -#endif - -#ifndef STRICT -#define STRICT -#endif - -#include -#include - -#define MSS_MAIN_DEF __cdecl - -// -// If compiling MSS DLL, use __declspec(dllexport) for both -// declarations and definitions -// -// If compiling MSS16 library or application, use "extern" in declarations -// and nothing in definitions -// - -#ifdef IS_WIN32 - - #define AILEXPORT WINAPI - - #ifdef BUILD_MSS - #define DXDEC __declspec(dllexport) - #define DXDEF __declspec(dllexport) - #else - - #if 1 /*def __BORLANDC__*/ - #define DXDEC extern - #define DXDEF - #else - #define DXDEC __declspec(dllimport) - #endif - - #endif - - #define MSSDLLNAME "MSS32.DLL" - #define MSS_REDIST_DIR_NAME "WIN32" - - #define MSS_DIR_SEP "\\" - #define MSS_DIR_UP ".." MSS_DIR_SEP - #define MSS_DIR_UP_TWO MSS_DIR_UP MSS_DIR_UP - -#else - - #define AILEXPORT __export WINAPI - - #define DXDEC extern - #define DXDEF - - #define MSSDLLNAME "MSS16.DLL" - #define MSS_REDIST_DIR_NAME "WIN16" - - #define MSS_DIR_SEP "\\" - #define MSS_DIR_UP ".." MSS_DIR_SEP - #define MSS_DIR_UP_TWO MSS_DIR_UP MSS_DIR_UP - -#endif - -#define AILCALL WINAPI -#define AILCALLBACK AILEXPORT - -typedef LPVOID AILLPDIRECTSOUND; -typedef LPVOID AILLPDIRECTSOUNDBUFFER; - -#else - -#ifdef IS_MAC - -#include -#include -#include -#include // needed for GetResource, ReleaseResource - -#define FAR - -#define AILLIBCALLBACK //pascal -#define AILCALL //pascal -#define AILEXPORT //pascal -#define AILCALLBACK //pascal - -#ifdef BUILD_MSS - #define DXDEC __declspec(export) - #define DXDEF -#else - #define DXDEC extern - #define DXDEF -#endif - -#define MSS_REDIST_DIR_NAME "MAC" - -#define MSS_DIR_SEP ":" -#define MSS_DIR_UP ":" MSS_DIR_SEP -#define MSS_DIR_UP_TWO MSS_DIR_UP MSS_DIR_SEP - -#define HIWORD(ptr) (((U32)ptr)>>16) -#define LOWORD(ptr) ((U16)((U32)ptr)) - -#define FOURCC U32 - -#ifndef MAKEFOURCC -#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ - (((U32)(U8)(ch0) << 24) | ((U32)(U8)(ch1) << 16) | \ - ((U32)(U8)(ch2) << 8) | ((U32)(U8)(ch3) )) -#endif - -#define mmioFOURCC(w,x,y,z) MAKEFOURCC(w,x,y,z) - -#define MSS_MAIN_DEF - -#endif - -#endif - -#endif - -#ifndef NULL -#define NULL 0 -#endif - -// -// Misc. constant definitions -// - -#define MAX_DRVRS 16 // Max. # of simultaneous drivers -#define MAX_TIMERS 16 // Max. # of simultaneous timers -#define MAX_NOTES 32 // Max # of notes "on" -#define FOR_NEST 4 // # of nested XMIDI FOR loops -#define NUM_CHANS 16 // # of possible MIDI channels -#define MAX_W_VOICES 16 // Max virtual wave synth voice cnt -#define MAX_W_ENTRIES 512 // 512 wave library entries max. -#ifdef IS_MAC -#define MAX_INSTR 150 // Max # of instruments 128 + 32 -#endif - -#define MIN_CHAN ( 1-1) // Min channel recognized (0-based) -#define MAX_CHAN (16-1) // Max channel recognized -#define MIN_LOCK_CHAN ( 2-1) // Min channel available for locking -#define MAX_LOCK_CHAN ( 9-1) // Max channel available for locking -#define PERCUSS_CHAN (10-1) // Percussion channel (no locking) - -#define AIL_MAX_FILE_HEADER_SIZE 4096 // AIL_set_named_sample_file() requires at least 4K - // of data or the entire file image, whichever is less, - // to determine sample format -#define DIG_F_16BITS_MASK 1 -#define DIG_F_STEREO_MASK 2 -#define DIG_F_ADPCM_MASK 4 - -#define DIG_F_MONO_8 0 // PCM data formats -#define DIG_F_MONO_16 (DIG_F_16BITS_MASK) -#define DIG_F_STEREO_8 (DIG_F_STEREO_MASK) -#define DIG_F_STEREO_16 (DIG_F_STEREO_MASK|DIG_F_16BITS_MASK) -#define DIG_F_ADPCM_MONO_16 (DIG_F_ADPCM_MASK |DIG_F_16BITS_MASK) -#define DIG_F_ADPCM_STEREO_16 (DIG_F_ADPCM_MASK |DIG_F_16BITS_MASK|DIG_F_STEREO_MASK) -#define DIG_F_USING_ASI 16 - -#define DIG_PCM_SIGN 0x0001 // (obsolete) -#define DIG_PCM_ORDER 0x0002 - -#define DIG_PCM_POLARITY 0x0004 // PCM flags used by driver hardware -#define DIG_PCM_SPLIT 0x0008 -#define DIG_BUFFER_SERVICE 0x0010 -#define DIG_DUAL_DMA 0x0020 -#define DIG_RECORDING_SUPPORTED 0x8000 - -#define WAVE_FORMAT_PCM 1 -#define WAVE_FORMAT_IMA_ADPCM 0x0011 - -#ifdef IS_DOS - -#define AIL3DIG 0 // .DIG driver -#define AIL3MDI 1 // .MDI driver - -#define DIG_DETECT_8_BIT_ONLY 0x0001 // Detect 8-bit DMA only -#define DIG_DETECT_16_BIT_ONLY 0x0002 // Detect 16-bit DMA only -#define DIG_DETECT_8_AND_16_BITS 0x0003 // Detect both 8- and 16-bit DMA - -#define DRV_INIT 0x300 // Functions common to .MDI and .DIG -#define DRV_GET_INFO 0x301 // drivers -#define DRV_SERVE 0x302 -#define DRV_PARSE_ENV 0x303 -#define DRV_VERIFY_IO 0x304 -#define DRV_INIT_DEV 0x305 -#define DRV_SHUTDOWN_DEV 0x306 - -#define DIG_HW_VOLUME 0x400 // .DIG driver functions -#define DIG_START_P_CMD 0x401 -#define DIG_STOP_P_REQ 0x402 -#define DIG_START_R_CMD 0x403 -#define DIG_STOP_R_REQ 0x404 -#define DIG_VSE 0x405 - -#define MDI_HW_VOLUME 0x500 // .MDI driver functions -#define MDI_INIT_INS_MGR 0x501 -#define MDI_MIDI_XMIT 0x502 -#define MDI_INSTALL_T_SET 0x503 -#define MDI_GET_T_STATUS 0x504 -#define MDI_PROT_UNPROT_T 0x505 -#define MDI_VSE 0x506 - -#else - -// -// Pass to AIL_midiOutOpen for NULL MIDI driver -// - -#define MIDI_NULL_DRIVER ((U32)(S32)-2) - -#endif - - -// -// Non-specific XMIDI/MIDI controllers and event types -// - -#define SYSEX_BYTE 105 -#define PB_RANGE 106 -#define CHAN_MUTE 107 -#define CALLBACK_PFX 108 -#define SEQ_BRANCH 109 -#define CHAN_LOCK 110 -#define CHAN_PROTECT 111 -#define VOICE_PROTECT 112 -#define TIMBRE_PROTECT 113 -#define PATCH_BANK_SEL 114 -#define INDIRECT_C_PFX 115 -#define FOR_LOOP 116 -#define NEXT_LOOP 117 -#define CLEAR_BEAT_BAR 118 -#define CALLBACK_TRIG 119 -#define SEQ_INDEX 120 - -#define GM_BANK_MSB 0 -#define MODULATION 1 -#define DATA_MSB 6 -#define PART_VOLUME 7 -#define PANPOT 10 -#define EXPRESSION 11 -#define GM_BANK_LSB 32 -#define DATA_LSB 38 -#define SUSTAIN 64 -#define REVERB 91 -#define CHORUS 93 -#define RPN_LSB 100 -#define RPN_MSB 101 -#define RESET_ALL_CTRLS 121 -#define ALL_NOTES_OFF 123 - -#define EV_NOTE_OFF 0x80 -#define EV_NOTE_ON 0x90 -#define EV_POLY_PRESS 0xa0 -#define EV_CONTROL 0xb0 -#define EV_PROGRAM 0xc0 -#define EV_CHAN_PRESS 0xd0 -#define EV_PITCH 0xe0 -#define EV_SYSEX 0xf0 -#define EV_ESC 0xf7 -#define EV_META 0xff - -#define META_EOT 0x2f -#define META_TEMPO 0x51 -#define META_TIME_SIG 0x58 - -// -// SAMPLE.system_data[] usage -// - -#define SSD_EOD_CALLBACK 0 // Application end-of-data callback if not NULL -#define VOC_BLK_PTR 1 // Pointer to current block -#define VOC_REP_BLK 2 // Pointer to beginning of repeat loop block -#define VOC_N_REPS 3 // # of iterations left in repeat loop -#define VOC_MARKER 4 // Marker to search for, or -1 if all -#define VOC_MARKER_FOUND 5 // Desired marker found if 1, else 0 -#define SSD_RELEASE 6 // Release sample handle upon termination if >0 -#ifdef IS_WINDOWS -#define SSD_EOD_CB_WIN32S 7 // Application end-of-data callback is in Win32s -#else -#define SSD_TEMP 7 // Temporary storage location for general use -#endif - -// -// Timer status values -// - -#define AILT_FREE 0 // Timer handle is free for allocation -#define AILT_STOPPED 1 // Timer is stopped -#define AILT_RUNNING 2 // Timer is running - -// -// SAMPLE.status flag values -// - -#define SMP_FREE 0x0001 // Sample is available for allocation - -#define SMP_DONE 0x0002 // Sample has finished playing, or has - // never been started - -#define SMP_PLAYING 0x0004 // Sample is playing - -#define SMP_STOPPED 0x0008 // Sample has been stopped - -#define SMP_PLAYINGBUTRELEASED 0x0010 // Sample is playing, but digital handle - // has been temporarily released - - - -// -// SEQUENCE.status flag values -// - -#define SEQ_FREE 0x0001 // Sequence is available for allocation - -#define SEQ_DONE 0x0002 // Sequence has finished playing, or has - // never been started - -#define SEQ_PLAYING 0x0004 // Sequence is playing - -#define SEQ_STOPPED 0x0008 // Sequence has been stopped - -#define SEQ_PLAYINGBUTRELEASED 0x0010 // Sequence is playing, but MIDI handle - // has been temporarily released - -#ifdef IS_DOS - -// -// MIDI driver types -// - -#define MDIDRVRTYPE_GM 0 // General MIDI driver (Roland-compatible) -#define MDIDRVRTYPE_FM_2 1 // 2-operator FM MIDI driver (OPL2) -#define MDIDRVRTYPE_FM_4 2 // 4-operator FM MIDI driver (OPL3) -#define MDIDRVRTYPE_SPKR 3 // Tandy or PC speaker "beep" driver - -// -// .INI installation result codes -// - -#define AIL_INIT_SUCCESS 0 // Driver installed successfully -#define AIL_NO_INI_FILE 1 // No MDI.INI or DIG.INI file exists -#define AIL_INIT_FAILURE 2 // Driver could not be initialized - -#ifdef __BORLANDC__ - - #ifndef REALPTR - #define REALPTR(x) ((void *) (U32) ((((U32) (x))>>16<<4) + ((x) & 0xffff) \ - - AIL_sel_base(_DS))) - #endif - -#else - - #ifndef REALPTR - #define REALPTR(x) ((void *) (U32) ((((U32) (x))>>16<<4) + ((x) & 0xffff))) - #endif - -#endif - -#else - -#ifdef IS_WINDOWS - -// -// AIL_set_direct_buffer_control() command values -// - -#define AILDS_RELINQUISH 0 // App returns control of secondary buffer -#define AILDS_SEIZE 1 // App takes control of secondary buffer -#define AILDS_SEIZE_LOOP 2 // App wishes to loop the secondary buffer - -#endif - -#endif - -// -// General type definitions for portability -// - -#ifndef C8 -#define C8 char -#endif - -#ifndef U8 -#define U8 unsigned char -#endif - -#ifndef S8 -#define S8 signed char -#endif - -#ifndef U16 -#define U16 unsigned short -#endif - -#ifndef S16 -#define S16 signed short -#endif - -#ifndef U32 -#define U32 unsigned long -#endif - -#ifndef S32 -#define S32 signed long -#endif - -#ifndef F32 -#define F32 float -#endif - -#ifndef F64 -#define F64 double -#endif - - -#ifndef REALFAR -#define REALFAR unsigned long -#endif - -#ifndef FILE_ERRS -#define FILE_ERRS - -#define AIL_NO_ERROR 0 -#define AIL_IO_ERROR 1 -#define AIL_OUT_OF_MEMORY 2 -#define AIL_FILE_NOT_FOUND 3 -#define AIL_CANT_WRITE_FILE 4 -#define AIL_CANT_READ_FILE 5 -#define AIL_DISK_FULL 6 - -#endif - -#define MIN_VAL 0 -#define NOM_VAL 1 -#define MAX_VAL 2 - -#ifndef YES -#define YES 1 -#endif - -#ifndef NO -#define NO 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -// -// Preference names and default values -// - -#define DIG_RESAMPLING_TOLERANCE 0 -#define DEFAULT_DRT 131 // Resampling triggered at +/- 0.2% - -#define DIG_MIXER_CHANNELS 1 -#define DEFAULT_DMC 64 // 64 allocatable SAMPLE structures - -#define DIG_DEFAULT_VOLUME 2 -#define DEFAULT_DDV 127 // Default sample volume = 127 (0-127) - -#define MDI_SERVICE_RATE 3 -#define DEFAULT_MSR 120 // XMIDI sequencer timing = 120 Hz - -#define MDI_SEQUENCES 4 -#define DEFAULT_MS 8 // 8 sequence handles/driver - -#define MDI_DEFAULT_VOLUME 5 -#define DEFAULT_MDV 127 // Default sequence volume = 127 (0-127) - -#define MDI_QUANT_ADVANCE 6 -#define DEFAULT_MQA 1 // Beat/bar count +1 interval - -#define MDI_ALLOW_LOOP_BRANCHING 7 -#define DEFAULT_ALB NO // Branches cancel XMIDI FOR loops - -#define MDI_DEFAULT_BEND_RANGE 8 -#define DEFAULT_MDBR 2 // Default pitch-bend range = 2 - -#ifdef IS_X86 - -#define MDI_DOUBLE_NOTE_OFF 9 -#define DEFAULT_MDNO NO // For stuck notes on SB daughterboards - -#endif - -#define DIG_ENABLE_RESAMPLE_FILTER 31 // Enable resampling filter by -#define DEFAULT_DERF YES // default - -#define DIG_DECODE_BUFFER_SIZE 32 // 2K decode buffer size by default -#define DEFAULT_DDBS 2048 - -#if defined(IS_WINDOWS) || defined(IS_MAC) - -#define MDI_SYSEX_BUFFER_SIZE 10 -#define DEFAULT_MSBS 1536 // Default sysex buffer = 1536 bytes - -#define DIG_OUTPUT_BUFFER_SIZE 11 -#define DEFAULT_DOBS 49152 // 48K output buffer size - -#define AIL_MM_PERIOD 12 -#define DEFAULT_AMP 5 // Default MM timer period = 5 msec. - -#endif - -#ifdef IS_WINDOWS - -#define DIG_DS_FRAGMENT_SIZE 34 -#define DEFAULT_DDFS 8 // Use 8 millisecond buffer fragments with DirectSound if MSS mixer in use - -#define DIG_DS_FRAGMENT_CNT 35 -#define DEFAULT_DDFC 96 // Use 96 buffer fragments with DirectSound if MSS mixer in use - -#define DIG_DS_MIX_FRAGMENT_CNT 42 -#define DEFAULT_DDMFC 8 // Mix ahead 8 buffer fragments - -#define DIG_DS_USE_PRIMARY 36 -#define DEFAULT_DDUP NO // Mix into secondary DirectSound buffer by default - -#define DIG_DS_DSBCAPS_CTRL3D 37 -#define DEFAULT_DDDC NO // Do not use DSBCAPS_CTRL3D by default - -#define DIG_DS_CREATION_HANDLER 38 -#define DEFAULT_DDCH NULL // Use DirectSoundCreate() by default - -#define AIL_TIMERS 13 -#define DEFAULT_AT 16 // 16 allocatable HTIMER handles - -#define DIG_MAX_CHAIN_ELEMENT_SIZE 14 -#define DEFAULT_MCES 8192 // max of 8192 bytes/waveOut buffer - -#define DIG_MIN_CHAIN_ELEMENT_TIME 45 -#define DEFAULT_MCET 100 // 100 milliseconds buffers - -#define DIG_USE_WAVEOUT 15 -#define DEFAULT_DUW NO // Use DirectSound by default - -#define DIG_DS_SECONDARY_SIZE 16 -#define DEFAULT_DDSS (32*1024L) // Must be 2^n -- use 32K by default - -#define DIG_DS_SAMPLE_CEILING 17 -#define DEFAULT_DDSC 44100 // Allow up to 44 kHz samples - -#define AIL_LOCK_PROTECTION 18 -#define DEFAULT_ALP NO // Don't suspend foreground thread by default - -#define AIL_WIN32S_CALLBACK_SIZE 19 -#define DEFAULT_WCS 4096 // Size of callback data in bytes - -#define AIL_MUTEX_PROTECTION 44 -#define DEFAULT_AMPR YES // Lock each call into Miles with a mutex - -#else - -#ifdef IS_DOS - -#define DIG_SERVICE_RATE 10 -#define DEFAULT_DSR 200 // DMA buffer-polling rate = 200 Hz - -#define DIG_HARDWARE_SAMPLE_RATE 11 -#define DEFAULT_DHSR NOM_VAL // Use nominal sample rate by default - -#define DIG_DMA_RESERVE 12 -#define DEFAULT_DDR 32768 // Reserve 32K real-mode mem for DMA - -#define DIG_LATENCY 13 -#define DEFAULT_DL 100 // Half-buffer size in ms = 100 - -#define DIG_USE_STEREO 14 -#define DEFAULT_DUS NO // Use mono output only - -#define DIG_USE_16_BITS 15 -#define DEFAULT_DU16 NO // Use 8-bit output by default - -#define DIG_ALLOW_16_BIT_DMA 16 -#define DEFAULT_DA16DMA YES // OK to use 16-bit DMA if necessary - -#define DIG_SS_LOCK 17 -#define DEFAULT_DSL NO // Don't disable IRQs while mixing - -#define AIL_SCAN_FOR_HARDWARE 18 -#define DEFAULT_ASH YES // Scan for I/O settings if necessary - -#define AIL_ALLOW_VDM_EXECUTION 19 -#define DEFAULT_AVE YES // Allow Windows "DOS box" execution - -#endif - -#endif - -// ---------------------------------- -// DLS Preference names and default values -// Unless otherwise specified, values must be established -// BEFORE calling DLSMSSOpen()! -// ---------------------------------- - -#define DLS_TIMEBASE 20 -#define DEFAULT_DTB 120 // 120 intervals/second by default - -#define DLS_VOICE_LIMIT 21 -#define DEFAULT_DVL 24 // 24 voices supported - -#define DLS_BANK_SELECT_ALIAS 22 -#define DEFAULT_DBSA NO // Do not treat controller 114 as bank - -#define DLS_STREAM_BOOTSTRAP 23 // Don't submit first stream buffer -#define DEFAULT_DSB YES // until at least 2 available - -#define DLS_VOLUME_BOOST 24 -#define DEFAULT_DVB 0 // Boost final volume by 0 dB - -#define DLS_ENABLE_FILTERING 25 // Filtering = on by default -#define DEFAULT_DEF YES // (may be changed at any time) - -#ifdef IS_X86 - -#define AIL_ENABLE_MMX_SUPPORT 27 // Enable MMX support if present -#define DEFAULT_AEMS YES // (may be changed at any time) - -#endif - -#define DLS_GM_PASSTHROUGH 28 // Pass unrecognized traffic on to -#define DEFAULT_DGP YES // default GM driver layer - // (may be changed at any time) - -#define DLS_ADPCM_TO_ASI_THRESHOLD 39 // Size in samples to switch to ASI -#define DEFAULT_DATAT 32768 - -// -// Add'l platform-independent prefs -// - -#define DIG_REVERB_BUFFER_SIZE 40 -#define DEFAULT_DRBS 0 // No reverb support by default - -#define DIG_INPUT_LATENCY 41 // Use >= 250-millisecond input buffers if -#define DEFAULT_DIL 250 // explicit size request cannot be satisfied - -#ifdef IS_WINDOWS - -#define DIG_USE_WAVEIN 43 -#define DEFAULT_DUWI YES // Use waveIn for input by default - -#endif - -#define N_PREFS 46 // # of preference types - -typedef struct _AILSOUNDINFO { - S32 format; - void const FAR* data_ptr; - U32 data_len; - U32 rate; - S32 bits; - S32 channels; - U32 samples; - U32 block_size; - void const FAR* initial_ptr; -} AILSOUNDINFO; - - -// for multi-processor machines - -#ifdef IS_WIN32 - -#ifdef BUILD_MSS - - #define MSSLockedIncrement(var) _asm { lock inc [var] } - #define MSSLockedDecrement(var) _asm { lock dec [var] } - - static void __MSSLockedIncrementAddr(void * addr) - { - _asm - { - mov eax,[addr] - lock inc dword ptr [eax] - } - } - - static void __MSSLockedDecrementAddr(void * addr) - { - _asm { - mov eax,[addr] - lock dec dword ptr [eax] - } - } - - #define MSSLockedIncrementPtr(var) __MSSLockedIncrementAddr(&(var)) - #define MSSLockedDecrementPtr(var) __MSSLockedDecrementAddr(&(var)) - -#else - - #define MSSLockedIncrement(var) (++var) - #define MSSLockedDecrement(var) (--var) - - #define MSSLockedIncrementPtr(var) (++var) - #define MSSLockedDecrementPtr(var) (--var) - -#endif - -#else - #define MSSLockedIncrement(var) (++var) - #define MSSLockedDecrement(var) (--var) - - #define MSSLockedIncrementPtr(var) (++var) - #define MSSLockedDecrementPtr(var) (--var) -#endif - -#ifndef RIB_H // RIB.H contents included if RIB.H not already included - -// #include "rib.h" - -#define RIB_H -#define ARY_CNT(x) (sizeof((x)) / sizeof((x)[0])) - -// ---------------------------------- -// RIB data types -// ---------------------------------- - -typedef S32 RIBRESULT; - -#define RIB_NOERR 0 // Success -- no error -#define RIB_NOT_ALL_AVAILABLE 1 // Some requested functions/attribs not available -#define RIB_NOT_FOUND 2 // Resource not found -#define RIB_OUT_OF_MEM 3 // Out of system RAM - -// -// Handle to interface provider -// +typedef char C8; +typedef uint8_t U8; +typedef int8_t S8; +typedef int16_t S16; +typedef uint16_t U16; +typedef int32_t S32; +typedef uint32_t U32; +typedef float F32; +typedef double F64; +typedef void *HSTREAM; typedef U32 HPROVIDER; - -// -// Handle representing token used to obtain attribute or preference -// data from RIB provider -// - -typedef U32 HATTRIB; - -// -// Handle representing an enumerated interface entry -// -// RIB_enumerate_interface() returns 1 if valid next entry found, else -// 0 if end of list reached -// - -typedef U32 HINTENUM; -#define HINTENUM_FIRST 0 - -// -// Handle representing an enumerated provider entry -// -// RIB_enumerate_providers() returns 1 if valid next entry found, else -// 0 if end of list reached -// +typedef void *H3DPOBJECT; +typedef H3DPOBJECT H3DSAMPLE; +typedef void *HSAMPLE; +typedef void *HDIGDRIVER; typedef U32 HPROENUM; #define HPROENUM_FIRST 0 -// -// Data types for RIB attributes and preferences -// - -typedef enum -{ - RIB_NONE = 0, // No type - RIB_CUSTOM, // Used for pointers to application-specific structures - RIB_DEC, // Used for 32-bit integer values to be reported in decimal - RIB_HEX, // Used for 32-bit integer values to be reported in hex - RIB_FLOAT, // Used for 32-bit single-precision FP values - RIB_PERCENT, // Used for 32-bit single-precision FP values to be reported as percentages - RIB_BOOL, // Used for Boolean-constrained integer values to be reported as TRUE or FALSE - RIB_STRING // Used for pointers to null-terminated ASCII strings -} -RIB_DATA_SUBTYPE; - -// -// RIB_ENTRY_TYPE structure, used to register an interface or request one -// - -typedef enum -{ - RIB_FUNCTION = 0, - RIB_ATTRIBUTE, // Attribute: read-only data type used for status/info communication - RIB_PREFERENCE // Preference: read/write data type used to control behavior -} -RIB_ENTRY_TYPE; - -// -// RIB_INTERFACE_ENTRY, used to represent a function or data entry in an -// interface -// - -typedef struct -{ - RIB_ENTRY_TYPE type; // See list above - C8 FAR *entry_name; // Name of desired function or attribute - U32 token; // Function pointer or attribute token - RIB_DATA_SUBTYPE subtype; // Data (attrib or preference) subtype -} -RIB_INTERFACE_ENTRY; - -// -// Standard RAD Interface Broker provider identification attributes -// - -#define PROVIDER_NAME (-100) // RIB_STRING name of decoder -#define PROVIDER_VERSION (-101) // RIB_HEX BCD version number - -// -// Standard function to obtain provider attributes (see PROVIDER_ defines -// above) -// -// Each provider of a searchable interface must export this function -// - -typedef U32 (AILCALL FAR *PROVIDER_QUERY_ATTRIBUTE) (HATTRIB index); - -// -// Macros to simplify interface registrations/requests for functions, -// attributes, and preferences -// - -#define FN(entry_name) { RIB_FUNCTION, #entry_name, (U32) &(entry_name), RIB_NONE } -#define REG_FN(entry_name) { RIB_FUNCTION, #entry_name, (U32) &(entry_name), RIB_NONE } - -#define AT(entry_name,ID) { RIB_ATTRIBUTE, (entry_name), (U32) &(ID), RIB_NONE } -#define REG_AT(entry_name,ID,subtype) { RIB_ATTRIBUTE, (entry_name), (U32) (ID), subtype } - -#define PR(entry_name,ID) { RIB_PREFERENCE, (entry_name), (U32) &(ID), RIB_NONE } -#define REG_PR(entry_name,ID,subtype) { RIB_PREFERENCE, (entry_name), (U32) (ID), subtype } - -#define RIB_register(x,y,z) RIB_register_interface (HPROVIDER(x), y, ARY_CNT(z), z) -#define RIB_unregister(x,y,z) RIB_unregister_interface(HPROVIDER(x), y, ARY_CNT(z), z) -#define RIB_unregister_all(x) RIB_unregister_interface(HPROVIDER(x), NULL, 0, NULL) -#define RIB_free_libraries() RIB_free_provider_library(HPROVIDER(NULL)); -#define RIB_request(x,y,z) RIB_request_interface (x, y, ARY_CNT(z), z) - -// ---------------------------------- -// Standard RIB API prototypes -// ---------------------------------- - -DXDEC HPROVIDER AILCALL RIB_alloc_provider_handle (U32 module); -DXDEC void AILCALL RIB_free_provider_handle (HPROVIDER provider); - -DXDEC HPROVIDER AILCALL RIB_load_provider_library (C8 const FAR *filename); -DXDEC void AILCALL RIB_free_provider_library (HPROVIDER provider); - -DXDEC HPROVIDER AILCALL RIB_provider_library_handle (void); - -DXDEC RIBRESULT AILCALL RIB_register_interface (HPROVIDER provider, - C8 const FAR *interface_name, - S32 entry_count, - RIB_INTERFACE_ENTRY const FAR *rlist); - -DXDEC RIBRESULT AILCALL RIB_unregister_interface (HPROVIDER provider, - C8 const FAR *interface_name, - S32 entry_count, - RIB_INTERFACE_ENTRY const FAR *rlist); - -DXDEC RIBRESULT AILCALL RIB_request_interface (HPROVIDER provider, - C8 const FAR *interface_name, - S32 entry_count, - RIB_INTERFACE_ENTRY FAR *rlist); - -DXDEC RIBRESULT AILCALL RIB_request_interface_entry (HPROVIDER provider, - C8 const FAR *interface_name, - RIB_ENTRY_TYPE entry_type, - C8 const FAR *entry_name, - U32 FAR *token); - -DXDEC S32 AILCALL RIB_enumerate_interface (HPROVIDER provider, - C8 FAR *interface_name, - RIB_ENTRY_TYPE type, - HINTENUM FAR *next, - RIB_INTERFACE_ENTRY FAR *dest); - -DXDEC S32 AILCALL RIB_enumerate_providers (C8 FAR *interface_name, - HPROENUM FAR *next, - HPROVIDER FAR *dest); - -DXDEC C8 FAR * AILCALL RIB_type_string (U32 data, - RIB_DATA_SUBTYPE subtype); - -DXDEC HPROVIDER AILCALL RIB_find_file_provider (C8 const FAR *interface_name, - C8 const FAR *attribute_name, - C8 const FAR *file_suffix); - -DXDEC HPROVIDER AILCALL RIB_find_provider (C8 const FAR *interface_name, - C8 const FAR *attribute_name, - C8 const FAR *attribute_value); - -DXDEC HPROVIDER AILCALL RIB_find_files_provider (C8 const FAR *interface_name, - C8 const FAR *attribute_name_1, - C8 const FAR *file_suffix_1, - C8 const FAR *attribute_name_2, - C8 const FAR *file_suffix_2); - -DXDEC HPROVIDER AILCALL RIB_find_file_dec_provider (C8 const FAR *interface_name, - C8 const FAR *attribute_name_1, - U32 attribute_value_1, - C8 const FAR *attribute_name_2, - C8 const FAR *file_suffix_2); - -DXDEC S32 AILCALL RIB_load_application_providers - (C8 const FAR *filespec); - -DXDEC void AILCALL RIB_set_provider_user_data (HPROVIDER provider, - U32 index, - S32 value); - -DXDEC S32 AILCALL RIB_provider_user_data (HPROVIDER provider, - U32 index); - -DXDEC void AILCALL RIB_set_provider_system_data - (HPROVIDER provider, - U32 index, - S32 value); - -DXDEC S32 AILCALL RIB_provider_system_data (HPROVIDER provider, - U32 index); - -DXDEC C8 FAR * AILCALL RIB_error (void); - -#endif - -#ifndef MSS_ASI_VERSION // MSSASI.H contents included if MSSASI.H not already included - -// #include "mssasi.h" - -#define AIL_ASI_VERSION 1 -#define AIL_ASI_REVISION 0 - -// -// Handle to stream being managed by ASI codec -// - -typedef S32 HASISTREAM; - -// -// ASI result codes -// - -typedef S32 ASIRESULT; - -#define ASI_NOERR 0 // Success -- no error -#define ASI_NOT_ENABLED 1 // ASI not enabled -#define ASI_ALREADY_STARTED 2 // ASI already started -#define ASI_INVALID_PARAM 3 // Invalid parameters used -#define ASI_INTERNAL_ERR 4 // Internal error in ASI driver -#define ASI_OUT_OF_MEM 5 // Out of system RAM -#define ASI_ERR_NOT_IMPLEMENTED 6 // Feature not implemented -#define ASI_NOT_FOUND 7 // ASI supported device not found -#define ASI_NOT_INIT 8 // ASI not initialized -#define ASI_CLOSE_ERR 9 // ASI not closed correctly - -// ---------------------------------- -// Application-provided ASI callbacks -// ---------------------------------- - -// -// AILASIFETCHCB: Called by ASI to obtain data from stream source -// -// offset normally will be either 0 at the first call made by the codec -// or -1 to specify a continuous stream, except when ASI_stream_seek() -// is called to restart the stream codec at a new stream offset. In this -// case, the application must execute the seek operation on the ASI codec's -// behalf. -// -// In response to this callback, the application should read the requested -// data and copy it to the specified destination buffer, returning the number -// of bytes copied (which can be less than bytes_requested if the end of -// the stream is reached). -// - -typedef S32 (AILCALLBACK FAR * AILASIFETCHCB) (U32 user, // User value passed to ASI_open_stream() - void FAR *dest, // Location to which stream data should be copied by app - S32 bytes_requested, // # of bytes requested by ASI codec - S32 offset); // If not -1, application should seek to this point in stream - -//############################################################################ -//## ## -//## Interface "ASI codec" ## -//## ## -//############################################################################ - -// -// Initialize ASI stream codec -// -// No other ASI functions may be called outside an ASI_startup() / -// ASI_shutdown() pair, except for the standard RIB function -// PROVIDER_query_attribute(). All provider attributes must be accessible -// without starting up the codec. -// - -typedef ASIRESULT (AILCALL FAR *ASI_STARTUP)(void); - -// -// Shut down ASI codec -// - -typedef ASIRESULT (AILCALL FAR * ASI_SHUTDOWN)(void); - -// -// Return codec error message, or NULL if no errors have occurred since -// last call -// -// The ASI error text state is global to all streams -// - -typedef C8 FAR * (AILCALL FAR * ASI_ERROR)(void); - -//############################################################################ -//## ## -//## Interface "ASI stream" ## -//## ## -//############################################################################ - -// -// Open a stream, returning handle to stream -// - -typedef HASISTREAM (AILCALL FAR *ASI_STREAM_OPEN) (U32 user, // User value passed to fetch callback - AILASIFETCHCB fetch_CB, // Source data fetch handler - U32 total_size); // Total size for %-done calculations (0=unknown) - -// -// Translate data in stream, returning # of bytes actually decoded or encoded -// -// Any number of bytes may be requested. Requesting more data than is -// available in the codec's internal buffer will cause the AILASIFETCHCB -// handler to be called to fetch more data from the stream. -// - -typedef S32 (AILCALL FAR *ASI_STREAM_PROCESS) (HASISTREAM stream, // Handle of stream - void FAR *buffer, // Destination for processed data - S32 buffer_size); // # of bytes to return in buffer - -// -// Restart stream decoding process at new offset -// -// Relevant for decoders only -// -// Seek destination is given as offset in bytes from beginning of stream -// -// At next ASI_stream_process() call, decoder will seek to the closest possible -// point in the stream which occurs at or after the specified position -// -// This function has no effect for decoders which do not support random -// seeks on a given stream type -// -// Warning: some decoders may need to implement seeking by reparsing -// the entire stream up to the specified offset, through multiple calls -// to the data-fetch callback. This operation may be extremely -// time-consuming on large files or slow network connections. -// -// A stream_offset value of -1 may be used to inform the decoder that the -// application has changed the input stream offset on its own, e.g. for a -// double-buffering application where the ASI decoder is not accessing the -// stream directly. ASI decoders should respond to this by flushing all -// internal buffers and resynchronizing themselves to the data stream. -// - -typedef ASIRESULT (AILCALL FAR *ASI_STREAM_SEEK) (HASISTREAM stream, - S32 stream_offset); - -// -// Retrieve an ASI stream attribute or preference value by index -// - -typedef S32 (AILCALL FAR *ASI_STREAM_ATTRIBUTE) (HASISTREAM stream, - HATTRIB attrib); - -// -// Set an ASI stream preference value by index -// - -typedef S32 (AILCALL FAR *ASI_STREAM_SET_PREFERENCE) (HASISTREAM stream, - HATTRIB preference, - void const FAR * value); - -// -// Close stream, freeing handle and all internally-allocated resources -// - -typedef ASIRESULT (AILCALL FAR *ASI_STREAM_CLOSE) (HASISTREAM stream); - -#endif - -//############################################################################ -//## ## -//## Interface "MSS 3D audio services" ## -//## ## -//############################################################################ - -// -// 3D positioning services -// - - -typedef struct h3DPOBJECT -{ - U32 junk; -} h3DPOBJECT; - -typedef h3DPOBJECT FAR * H3DPOBJECT; -typedef H3DPOBJECT H3DSAMPLE; - -// -// M3D result codes -// - typedef S32 M3DRESULT; -#define M3D_NOERR 0 // Success -- no error -#define M3D_NOT_ENABLED 1 // M3D not enabled -#define M3D_ALREADY_STARTED 2 // M3D already started -#define M3D_INVALID_PARAM 3 // Invalid parameters used -#define M3D_INTERNAL_ERR 4 // Internal error in M3D driver -#define M3D_OUT_OF_MEM 5 // Out of system RAM -#define M3D_ERR_NOT_IMPLEMENTED 6 // Feature not implemented -#define M3D_NOT_FOUND 7 // M3D supported device not found -#define M3D_NOT_INIT 8 // M3D not initialized -#define M3D_CLOSE_ERR 9 // M3D not closed correctly +#define M3D_NOERR 0 +enum { ENVIRONMENT_CAVE = 8 }; -typedef void (AILCALLBACK FAR* AIL3DSAMPLECB) (H3DSAMPLE sample); +#define AIL_3D_2_SPEAKER 0 +#define AIL_3D_HEADPHONE 1 +#define AIL_3D_4_SPEAKER 3 -typedef M3DRESULT (AILCALL FAR *M3D_STARTUP)(void); +#define DIG_MIXER_CHANNELS 1 -typedef M3DRESULT (AILCALL FAR *M3D_SHUTDOWN)(void); +#define DIG_F_MONO_16 1 +#define DIG_PCM_SIGN 1 -typedef C8 FAR * (AILCALL FAR *M3D_ERROR)(void); +#define SMP_PLAYING 4 -typedef S32 (AILCALL FAR *M3D_SET_PROVIDER_PREFERENCE)(HATTRIB preference, - void const FAR * value); - -typedef M3DRESULT (AILCALL FAR * M3D_ACTIVATE)(S32 enable); - -typedef H3DSAMPLE (AILCALL FAR * M3D_ALLOCATE_3D_SAMPLE_HANDLE)(void); - - -typedef void (AILCALL FAR * M3D_RELEASE_3D_SAMPLE_HANDLE)(H3DSAMPLE samp); - - -typedef void (AILCALL FAR * M3D_START_3D_SAMPLE)(H3DSAMPLE samp); - - -typedef void (AILCALL FAR * M3D_STOP_3D_SAMPLE)(H3DSAMPLE samp); - - -typedef void (AILCALL FAR * M3D_RESUME_3D_SAMPLE)(H3DSAMPLE samp); - -typedef void (AILCALL FAR * M3D_END_3D_SAMPLE)(H3DSAMPLE samp); - -typedef S32 (AILCALL FAR * M3D_SET_3D_SAMPLE_DATA)(H3DSAMPLE samp, - AILSOUNDINFO const FAR *info); - -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_VOLUME)(H3DSAMPLE samp, - S32 volume); - -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_PLAYBACK_RATE)(H3DSAMPLE samp, - S32 playback_rate); - -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_OFFSET)(H3DSAMPLE samp, - U32 offset); - - -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_LOOP_COUNT)(H3DSAMPLE samp, - U32 loops); - -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_LOOP_BLOCK)(H3DSAMPLE S, - S32 loop_start_offset, - S32 loop_end_offset); - -typedef U32 (AILCALL FAR * M3D_3D_SAMPLE_STATUS)(H3DSAMPLE samp); - -typedef U32 (AILCALL FAR * M3D_3D_SAMPLE_ATTRIBUTE)(H3DSAMPLE samp, HATTRIB index); - -typedef S32 (AILCALL FAR * M3D_3D_SET_SAMPLE_PREFERENCE)(H3DSAMPLE samp, HATTRIB preference, void const FAR * value); - -typedef S32 (AILCALL FAR * M3D_3D_SAMPLE_VOLUME)(H3DSAMPLE samp); - -typedef S32 (AILCALL FAR * M3D_3D_SAMPLE_PLAYBACK_RATE)(H3DSAMPLE samp); - -typedef U32 (AILCALL FAR * M3D_3D_SAMPLE_OFFSET)(H3DSAMPLE samp); - -typedef U32 (AILCALL FAR * M3D_3D_SAMPLE_LENGTH)(H3DSAMPLE samp); - -typedef U32 (AILCALL FAR * M3D_3D_SAMPLE_LOOP_COUNT)(H3DSAMPLE samp); - -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_DISTANCES)(H3DSAMPLE samp, - F32 max_dist, - F32 min_dist); - - -typedef void (AILCALL FAR * M3D_3D_SAMPLE_DISTANCES)(H3DSAMPLE samp, - F32 FAR * max_dist, - F32 FAR * min_dist); - -typedef S32 (AILCALL FAR * M3D_ACTIVE_3D_SAMPLE_COUNT)(void); - -typedef H3DPOBJECT (AILCALL FAR * M3D_3D_OPEN_LISTENER)(void); - -typedef void (AILCALL FAR * M3D_3D_CLOSE_LISTENER)(H3DPOBJECT listener); - -typedef H3DPOBJECT (AILCALL FAR * M3D_3D_OPEN_OBJECT)(void); - -typedef void (AILCALL FAR * M3D_3D_CLOSE_OBJECT)(H3DPOBJECT obj); - -typedef void (AILCALL FAR * M3D_SET_3D_POSITION)(H3DPOBJECT obj, - F32 X, - F32 Y, - F32 Z); - -typedef void (AILCALL FAR * M3D_SET_3D_VELOCITY)(H3DPOBJECT obj, - F32 dX_per_ms, - F32 dY_per_ms, - F32 dZ_per_ms, - F32 magnitude); - -typedef void (AILCALL FAR * M3D_SET_3D_VELOCITY_VECTOR)(H3DPOBJECT obj, - F32 dX_per_ms, - F32 dY_per_ms, - F32 dZ_per_ms); - -typedef void (AILCALL FAR * M3D_SET_3D_ORIENTATION)(H3DPOBJECT obj, - F32 X_face, - F32 Y_face, - F32 Z_face, - F32 X_up, - F32 Y_up, - F32 Z_up); - -typedef void (AILCALL FAR * M3D_3D_POSITION)(H3DPOBJECT obj, - F32 FAR *X, - F32 FAR *Y, - F32 FAR *Z); - -typedef void (AILCALL FAR * M3D_3D_VELOCITY)(H3DPOBJECT obj, - F32 FAR *dX_per_ms, - F32 FAR *dY_per_ms, - F32 FAR *dZ_per_ms); - -typedef void (AILCALL FAR * M3D_3D_ORIENTATION)(H3DPOBJECT obj, - F32 FAR *X_face, - F32 FAR *Y_face, - F32 FAR *Z_face, - F32 FAR *X_up, - F32 FAR *Y_up, - F32 FAR *Z_up); - -typedef void (AILCALL FAR * M3D_3D_UPDATE_POSITION)(H3DPOBJECT obj, - F32 dt_milliseconds); - -typedef void (AILCALL FAR * M3D_3D_AUTO_UPDATE_POSITION)(H3DPOBJECT obj, - S32 enable); - -typedef S32 (AILCALL FAR * M3D_3D_ROOM_TYPE)(void); -typedef void (AILCALL FAR * M3D_SET_3D_ROOM_TYPE)(S32 EAX_room_type); -typedef S32 (AILCALL FAR * M3D_3D_SPEAKER_TYPE)(void); -typedef void (AILCALL FAR * M3D_SET_3D_SPEAKER_TYPE)(S32 speaker_type); -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_OBSTRUCTION)(H3DSAMPLE samp, F32 obstruction); -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_OCCLUSION)(H3DSAMPLE samp, F32 occlusion); -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_EFFECTS_LEVEL)(H3DSAMPLE samp, F32 effects_level); -typedef F32 (AILCALL FAR * M3D_3D_SAMPLE_OBSTRUCTION)(H3DSAMPLE samp); -typedef F32 (AILCALL FAR * M3D_3D_SAMPLE_OCCLUSION)(H3DSAMPLE samp); -typedef F32 (AILCALL FAR * M3D_3D_SAMPLE_EFFECTS_LEVEL)(H3DSAMPLE samp); - -typedef AIL3DSAMPLECB (AILCALL FAR * M3D_SET_3D_EOS)(H3DSAMPLE client,H3DSAMPLE samp,AIL3DSAMPLECB cb); - -typedef void (AILCALL FAR * M3D_SET_3D_SAMPLE_CONE)(H3DSAMPLE samp, F32 inner_angle, F32 outer_angle, S32 outer_volume); -typedef void (AILCALL FAR * M3D_3D_SAMPLE_CONE)(H3DSAMPLE samp, F32 FAR* inner_angle, F32 FAR* outer_angle, S32 FAR* outer_volume); - -//############################################################################ -//## ## -//## Interface "MSS mixer services" ## -//## ## -//############################################################################ - -// -// Operation flags used by mixer module -// - -#define M_DEST_STEREO 1 // Set to enable stereo mixer output -#define M_SRC_16 2 // Set to enable mixing of 16-bit samples -#define M_FILTER 4 // Set to enable filtering when resampling -#define M_SRC_STEREO 8 // Set to enable mixing of stereo input samples -#define M_VOL_SCALING 16 // Set to enable volume scalars other than 2047 -#define M_RESAMPLE 32 // Set to enable playback ratios other than 65536 -#define M_ORDER 64 // Set to reverse L/R stereo order for sample - -#ifdef IS_32 - -// -// Initialize mixer -// -// No other mixer functions may be called outside a MIXER_startup() / -// MIXER_shutdown() pair, except for the standard RIB function -// PROVIDER_query_attribute(). All provider attributes must be accessible -// without starting up the module. -// - -typedef void (AILCALL FAR *MIXER_STARTUP)(void); - -// -// Shut down mixer -// - -typedef void (AILCALL FAR *MIXER_SHUTDOWN)(void); - -// -// Flush mixer buffer -// - -typedef void (AILCALL FAR *MIXER_FLUSH) (S32 FAR *dest, - S32 len, - S32 FAR *reverb_buffer, - S32 reverb_level -#ifdef IS_X86 - ,U32 MMX_available -#endif - ); - -// -// Perform audio mixing operation -// - -typedef void (AILCALL FAR *MIXER_MERGE) (void const FAR * FAR *src, - U32 FAR *src_fract, - void const FAR *src_end, - S32 FAR * FAR *dest, - void FAR *dest_end, - S32 FAR *left_val, - S32 FAR *right_val, - S32 playback_ratio, - S32 scale_left, - S32 scale_right, - U32 operation -#ifdef IS_X86 - ,U32 MMX_available -#endif - ); - -// -// Translate mixer buffer contents to final output format -// - -#ifdef IS_MAC - -typedef void (AILCALL FAR *MIXER_COPY) (void const FAR *src, - S32 src_len, - void FAR *dest, - U32 operation, - U32 big_endian_output); -#else - -typedef void (AILCALL FAR *MIXER_COPY) (void const FAR *src, - S32 src_len, - void FAR *dest, - U32 operation, - U32 MMX_available); -#endif -#else - -// -// Initialize mixer -// -// No other mixer functions may be called outside a MIXER_startup() / -// MIXER_shutdown() pair, except for the standard RIB function -// PROVIDER_query_attribute(). All provider attributes must be accessible -// without starting up the module. -// - -typedef void (AILCALL FAR *MIXER_STARTUP)(void); - -// -// Shut down mixer -// - -typedef void (AILCALL FAR *MIXER_SHUTDOWN)(void); - -// -// Flush mixer buffer -// - -typedef void (AILCALL FAR *MIXER_FLUSH) (S32 FAR *dest, - S32 len, - S32 FAR *reverb_buffer, - S32 reverb_level, - U32 MMX_available); - -// -// Perform audio mixing operation -// - -typedef void (AILCALL FAR *MIXER_MERGE) (U32 src_sel, - U32 dest_sel, - U32 FAR *src_fract, - U32 FAR *src_offset, - U32 FAR *dest_offset, - U32 src_end_offset, - U32 dest_end_offset, - S32 FAR *left_val, - S32 FAR *right_val, - S32 playback_ratio, - S32 scale_both, - U32 operation); - -// -// Translate mixer buffer contents to final output format -// - -typedef void (AILCALL FAR *MIXER_COPY) (void const FAR *src, - S32 src_len, - void FAR *dest, - U32 operation, - U32 MMX_available); -#endif - -// -// Type definitions -// - -struct _DIG_DRIVER; - -struct _MDI_DRIVER; - -typedef struct _DIG_DRIVER FAR * HDIGDRIVER; // Handle to digital driver - -typedef struct _MDI_DRIVER FAR * HMDIDRIVER; // Handle to XMIDI driver - -typedef struct _SAMPLE FAR * HSAMPLE; // Handle to sample - -typedef struct _SEQUENCE FAR * HSEQUENCE; // Handle to sequence - -typedef S32 HTIMER; // Handle to timer - - -#ifdef IS_DOS - -// -// Type definitions -// - -typedef struct // I/O parameters structure +typedef struct _AILSOUNDINFO { - S16 IO; - S16 IRQ; - S16 DMA_8_bit; - S16 DMA_16_bit; - S32 IO_reserved[4]; -} -IO_PARMS; - -typedef struct // Standard MSS 3.X VDI driver header -{ - S8 ID[8]; // "AIL3xxx" ID string, followed by ^Z - - U32 driver_version; - - REALFAR common_IO_configurations; - U16 num_IO_configurations; - - REALFAR environment_string; - - IO_PARMS IO; - - S16 service_rate; - - U16 busy; - - U16 driver_num; // Driver number - - U16 this_ISR; // Offset of INT 66H dispatcher - REALFAR prev_ISR; // Pointer to previous INT 66H ISR - - S8 scratch[128]; // Shared scratch workspace - - S8 dev_name[80]; // Device name (VDI version >= 1.12 only) -} -VDI_HDR; - -typedef struct -{ - U16 minimum_physical_sample_rate; - U16 nominal_physical_sample_rate; - U16 maximum_physical_sample_rate; - - U16 minimum_DMA_half_buffer_size; - U16 maximum_DMA_half_buffer_size; - - U32 flags; -} -DIG_MODE; - -typedef struct -{ - U8 format_supported[16]; - DIG_MODE format_data[16]; -} -DIG_DDT; - -typedef struct -{ - REALFAR DMA_buffer_A; - REALFAR DMA_buffer_B; - S16 active_buffer; -} -DIG_DST; - -typedef struct -{ - REALFAR library_environment; - REALFAR GTL_suffix; - - U16 num_voices; - - U16 max_melodic_channel; - U16 min_melodic_channel; - U16 percussion_channel; -} -MDI_DDT; - -typedef struct -{ - S8 library_directory[128]; - S8 GTL_filename[128]; - - S8 MIDI_data[512]; -} -MDI_DST; - -typedef struct // Initialization file structure -{ - char device_name[128]; // Device name - char driver_name[128]; // Driver filename - IO_PARMS IO; // I/O parameters for driver -} -AIL_INI; - -typedef struct // Handle to driver -{ - REALFAR seg; // Seg:off pointer to driver (off=0) - U32 sel; // Selector for driver (off=0) - void *buf; // Protected-mode pointer to driver - U32 size; // Size of driver image - VDI_HDR *VHDR; // Pointer to driver header (same as buf) - S32 type; // AIL3DIG or AIL3MDI (see below) - - S32 initialized; // 1 if hardware successfully init'd, else 0 - - S32 PM_ISR; // -1 if no PM ISR hooked, else IRQ # - - HTIMER server; // DRV_SERVE periodic timer, if requested - - // Vector to high-level destructor, if any - - void (AILCALL *destructor)(HDIGDRIVER); - - // High-level descriptor (DIG_ or MDI_DRIVER) - void *descriptor; -} -AIL_DRIVER; - -typedef struct // VDI interface register structure -{ - S16 AX; - S16 BX; - S16 CX; - S16 DX; - S16 SI; - S16 DI; -} -VDI_CALL; - -#endif - -// -// Function pointer types -// - -typedef void (AILCALLBACK FAR* AILINCB) (void const FAR *data, S32 len, U32 user_data); - -typedef void (AILCALLBACK FAR* AILTIMERCB) (U32 user); - -typedef void (AILCALLBACK FAR* AILSAMPLECB) (HSAMPLE sample); - -typedef S32 (AILCALLBACK FAR* AILEVENTCB) (HMDIDRIVER hmi,HSEQUENCE seq,S32 status,S32 data_1,S32 data_2); - -typedef S32 (AILCALLBACK FAR* AILTIMBRECB) (HMDIDRIVER hmi,S32 bank,S32 patch); - -typedef S32 (AILCALLBACK FAR* AILPREFIXCB) (HSEQUENCE seq,S32 log,S32 data); - -typedef void (AILCALLBACK FAR* AILTRIGGERCB) (HSEQUENCE seq,S32 log,S32 data); - -typedef void (AILCALLBACK FAR* AILBEATCB) (HMDIDRIVER hmi,HSEQUENCE seq,S32 beat,S32 measure); - -typedef void (AILCALLBACK FAR* AILSEQUENCECB) (HSEQUENCE seq); - -// -// Handle to sample and driver being managed by pipeline filter -// - -typedef S32 HSAMPLESTATE; -typedef S32 HDRIVERSTATE; - -// -// Digital pipeline stages -// -// These are the points at which external modules may be installed into -// a given HSAMPLE or HDIGDRIVER's processing pipeline -// - -typedef enum -{ - DP_ASI_DECODER=0, // Must be "ASI codec stream" provider - DP_FILTER, // Must be "MSS pipeline filter" provider - DP_MERGE, // Must be "MSS mixer" provider - N_SAMPLE_STAGES, // Placeholder for end of list (= # of valid stages) - SAMPLE_ALL_STAGES // Used to signify all pipeline stages, for shutdown -} -SAMPLESTAGE; - -typedef enum -{ - DP_FLUSH = 0, // Must be "MSS mixer" provider - DP_DEFAULT_FILTER, // Must be "MSS pipeline filter" provider (sets the default) - DP_DEFAULT_MERGE, // Must be "MSS mixer" provider (sets the default) - DP_COPY, // Must be "MSS mixer" provider - N_DIGDRV_STAGES, // Placeholder for end of list (= # of valid stages) - DIGDRV_ALL_STAGES // Used to signify all pipeline stages, for shutdown -} -DIGDRVSTAGE; - -typedef struct - { - ASI_STREAM_OPEN ASI_stream_open; - ASI_STREAM_PROCESS ASI_stream_process; - ASI_STREAM_SEEK ASI_stream_seek; - ASI_STREAM_CLOSE ASI_stream_close; - ASI_STREAM_ATTRIBUTE ASI_stream_attribute; - ASI_STREAM_SET_PREFERENCE ASI_stream_set_preference; - - HATTRIB INPUT_BIT_RATE; - HATTRIB INPUT_SAMPLE_RATE; - HATTRIB INPUT_BITS; - HATTRIB INPUT_CHANNELS; - HATTRIB OUTPUT_BIT_RATE; - HATTRIB OUTPUT_SAMPLE_RATE; - HATTRIB OUTPUT_BITS; - HATTRIB OUTPUT_CHANNELS; - HATTRIB POSITION; - HATTRIB PERCENT_DONE; - HATTRIB MIN_INPUT_BLOCK_SIZE; - HATTRIB RAW_RATE; - HATTRIB RAW_BITS; - HATTRIB RAW_CHANNELS; - HATTRIB REQUESTED_RATE; - HATTRIB REQUESTED_BITS; - HATTRIB REQUESTED_CHANS; - - HASISTREAM stream; - } -ASISTAGE; - -typedef struct - { - MIXER_FLUSH MSS_mixer_flush; - MIXER_MERGE MSS_mixer_merge; - MIXER_COPY MSS_mixer_copy; - } -MIXSTAGE; - -typedef struct - { - struct _FLTPROVIDER FAR *provider; - HSAMPLESTATE sample_state; - } -FLTSTAGE; - -typedef struct -{ - S32 active; // Pass-through if 0, active if 1 - HPROVIDER provider; - - union - { - ASISTAGE ASI; - MIXSTAGE MIX; - FLTSTAGE FLT; - } - TYPE; -} -DPINFO; - -// -// Other data types -// - -typedef struct _AIL_INPUT_INFO // Input descriptor type -{ - U32 device_ID; // DS LPGUID or wave device ID - U32 hardware_format; // e.g., DIG_F_STEREO_16 - U32 hardware_rate; // e.g., 22050 - AILINCB callback; // Callback function to receive incoming data - S32 buffer_size; // Maximum # of bytes to be passed to callback (-1 to use DIG_INPUT_LATENCY) - U32 user_data; // this is a user defined value -} -AIL_INPUT_INFO; - -typedef struct _AILTIMER // Timer instance -{ - U32 status; - AILTIMERCB callback; - U32 user; - - S32 elapsed; - S32 value; - S32 callingCT; // Calling EXE's task number (16 bit only) - S32 callingDS; // Calling EXE's DS (used in 16 bit only) - S32 IsWin32s; // Is this a Win32s callback -} AILTIMERSTR; - -typedef struct _ADPCMDATATAG -{ - U32 blocksize; - U32 extrasamples; - U32 blockleft; - U32 step; - U32 savesrc; - U32 sample; - U32 destend; - U32 srcend; - U32 samplesL; - U32 samplesR; - U16 moresamples[16]; -} ADPCMDATA; - -typedef struct _SAMPLE // Sample instance -{ - char tag[4]; // HSAM - - HDIGDRIVER driver; // Driver for playback - - U32 status; // SMP_ flags: _FREE, _DONE, _PLAYING - - void const FAR *start[2]; // Sample buffer address (W) - U32 len [2]; // Sample buffer size in bytes (W) - U32 pos [2]; // Index to next byte (R/W) - U32 done [2]; // Nonzero if buffer with len=0 sent by app - S32 reset_ASI [2]; // Reset the ASI decoder at the end of the buffer - - U32 src_fract; // Fractional part of source address - S32 left_val; // Mixer source value from end of last buffer - S32 right_val; // Mixer source value from end of last buffer - - S32 current_buffer; // Buffer # active (0/1) - S32 last_buffer; // Last active buffer (for double-buffering) - S32 starved; // Buffer stream has run out of data - - S32 loop_count; // # of cycles-1 (1=one-shot, 0=indefinite) - S32 loop_start; // Starting offset of loop block (0=SOF) - S32 loop_end; // End offset of loop block (-1=EOF) - - S32 format; // DIG_F format (8/16 bits, mono/stereo) - U32 flags; // DIG_PCM_SIGN / DIG_PCM_ORDER (stereo only) - - S32 playback_rate; // Playback rate in hertz - - S32 volume; // Sample volume 0-127 - S32 pan; // Mono panpot/stereo balance (0=L ... 127=R) - - S32 left_scale; // Left/mono volume scalar 0-2047 - S32 right_scale; // Right volume scalar 0-2047 - - S32 service_type; // 1 if single-buffered; 2 if streamed - - AILSAMPLECB SOB; // Start-of-block callback function - AILSAMPLECB EOB; // End-of-buffer callback function - AILSAMPLECB EOS; // End-of-sample callback function - - S32 user_data [8]; // Miscellaneous user data - S32 system_data[8]; // Miscellaneous system data - - ADPCMDATA adpcm; - -#ifdef IS_WINDOWS - - S32 SOB_IsWin32s; // Is this a Win32s callback - S32 EOB_IsWin32s; // Is this a Win32s callback - S32 EOS_IsWin32s; // Is this a Win32s callback - - // - // DirectSound-specific data - // - - S32 secondary_buffer; // Secondary buffer index - - S32 service_interval; // Service sample every n ms - S32 service_tick; // Current service countdown value - S32 buffer_segment_size; // Buffer segment size to fill - - S32 prev_segment; // Previous segment # (0...n) - S32 prev_cursor; // Previous play cursor location - - S32 bytes_remaining; // # of bytes left to play (if not -1) - - S32 direct_control; // 1 if app controls buffer, 0 if MSS - -#endif - - S32 doeob; // Flags to trigger callbacks - S32 dosob; - S32 doeos; - - // - // Sample pipeline stages - // - - DPINFO pipeline[N_SAMPLE_STAGES]; - - // - // Reverb parms - // - - F32 reverb_level; // Level [0.0, 1.0] - F32 reverb_reflect_time; // Reflect time in milliseconds - F32 reverb_decay_time; // Decay time [0.1, 20.0] - S32 base_scale; // Original 12-bit volume scalar -} -SAMPLE; - -#if defined(IS_WINDOWS) || defined(IS_MAC) - -DXDEC U32 AILCALL AIL_get_timer_highest_delay (void); - -DXDEC void AILCALL AIL_serve(void); - -#ifdef IS_MAC - -typedef void * LPSTR; - -#define WHDR_DONE 0 - -typedef struct _WAVEIN -{ - long temp; -} * HWAVEIN; - -typedef struct _WAVEHDR -{ - S32 dwFlags; - S32 dwBytesRecorded; - S32 dwUser; - S32 temp; - void * lpData; - S32 dwBufferLength; - S32 longdwLoops; - S32 dwLoops; - void * lpNext; - U32 * reserved; - -} WAVEHDR, * LPWAVEHDR; - -#endif - -typedef struct _DIG_INPUT_DRIVER FAR *HDIGINPUT; // Handle to digital input driver - -typedef struct _DIG_INPUT_DRIVER // Handle to digital input driver -{ - C8 tag[4]; // HDIN - - HTIMER background_timer; // Background timer handle - - AIL_INPUT_INFO info; // Input device descriptor - - S32 input_enabled; // 1 if enabled, 0 if not - -#ifndef IS_MAC - - U32 callback_user; // Callback user value - - // - // Provider-independent data - // - - U32 DMA_size; // Size of each DMA sub-buffer in bytes - void FAR *DMA[2]; // Simulated DMA buffers - - U8 silence; // Silence value for current format (0 or 128) - - S32 device_active; // 1 if buffers submittable, 0 if not - - // - // waveOut-specific data - // - - HWAVEIN hWaveIn; // Handle to wave input device - volatile WAVEHDR wavehdr[2]; // Handles to wave headers - -#else - Boolean timer_started; - Boolean locked; - Boolean enter_lock; - U32 saved_period; - - void* my_vars; - - // - // Input related - // - - U32 input_buffer_size; - char * input_buffers[2]; - - // - // Mix related - // - - char * build_buffer; - U32 build_buffer_size; - - // - // Output related - // - struct - { - S8 * buffer; - S8 * buffer_end; - - U32 size; - S8 * right_margine; - S8 * current_head; - S8 * current_tail; - } output_buffer; - - S32 mix_operation; - S32 playback_ratio; - U32 src_fract; - S8 * current_head; - S32 left_val; - S32 right_val; - - U32 stored_sample_size; - U32 stored_number_of_channels; - - U32 last_rw_delta; - U32 period; - -#endif -} -DIG_INPUT_DRIVER; - -#endif - -typedef struct _DIG_DRIVER // Handle to digital audio driver -{ - char tag[4]; // HDIG - - HTIMER backgroundtimer; // Background timer handle - - S32 quiet; // # of consecutive quiet sample periods - - S32 n_active_samples; // # of samples being processed - - S32 master_volume; // Master sample volume 0-127 - - S32 DMA_rate; // Hardware sample rate - S32 hw_format; // DIG_F code in use - U32 hw_mode_flags; // DIG_PCM_ flags for mode in use - - S32 channels_per_sample; // # of channels per sample (1 or 2) - S32 bytes_per_channel; // # of bytes per channel (1 or 2) - S32 channels_per_buffer; // # of channels per half-buffer - S32 samples_per_buffer; // # of samples per half-buffer - - S32 playing; // Playback active if non-zero - -#ifdef IS_MAC - U32 n_samples_allocated; - U32 n_samples_used; - U32 n_samples_played; - SAMPLE *samples; // Pointer to SAMPLEs - - HDIGDRIVER next; // Pointer to next HDIGDRIVER in use - U32 reset_works; // TRUE if OK to do waveOutReset - U32 request_reset; // If nonzero, do waveOutReset ASAP - S32 released; // has the sound manager been released? - - ExtSoundHeader sound_header; - SndChannelPtr sound_channel; - SndCallBackUPP global_callback; - Ptr buffers[2]; - Boolean loaded[2]; - U32 work_buffer; - U32 play_buffer; - U32 load_pos; - U32 load_size; - Boolean load; - U32 start_time; - void* background_processor; - -#else - HSAMPLE samples; // Pointer to list of SAMPLEs -#endif - - S32 n_samples; // # of SAMPLEs - - S32 build_size; // # of bytes in build buffer - S32 FAR *build_buffer; // Build buffer (4 * samples_per_buffer) - - S32 system_data[8]; // Miscellaneous system data - - S32 buffer_size; // Size of each output buffer - -#ifdef IS_WINDOWS - - // - // waveOut-specific interface data - // - - HWAVEOUT hWaveOut; // Wave output driver - - U32 reset_works; // TRUE if OK to do waveOutReset - U32 request_reset; // If nonzero, do waveOutReset ASAP - - LPWAVEHDR first; // Pointer to first WAVEHDR in chain - S32 n_buffers; // # of output WAVEHDRs in chain - - LPWAVEHDR volatile FAR *return_list; // Circular list of returned WAVEHDRs - S32 volatile return_head; // Head of WAVEHDR list (insertion point) - S32 volatile return_tail; // Tail of WAVEHDR list (retrieval point) - - - U32 deviceid; // id from waveout open - PCMWAVEFORMAT wformat; // format from waveout open - - // - // DirectSound-specific interface data - // - - U32 guid; // The guid id of the ds driver - AILLPDIRECTSOUND pDS; // DirectSound output driver (don't - // use with Smacker directly anymore!) - - U32 ds_priority; // priority opened with - - S32 emulated_ds; // is ds emulated or not? - AILLPDIRECTSOUNDBUFFER lppdsb; // primary buffer or null - - U32 dsHwnd; // HWND used with DirectSound - - AILLPDIRECTSOUNDBUFFER FAR * lpbufflist; // List of pointers to secondary buffers - HSAMPLE FAR *samp_list; // HSAMPLE associated with each buffer - S32 FAR *sec_format; // DIG_F_ format for secondary buffer - S32 max_buffs; // Max. allowable # of secondary buffers - - // - // Misc. data - // - - S32 released; // has the sound manager been released? - - U32 foreground_timer; // Foreground timer handle - - HDIGDRIVER next; // Pointer to next HDIGDRIVER in use - S32 callingCT; // Calling EXE's task number (16 bit only) - S32 callingDS; // Calling EXE's DS (used in 16 bit only) - - // - // Vars for waveOut emulation - // - - S32 DS_initialized; - - AILLPDIRECTSOUNDBUFFER DS_sec_buff; // Secondary buffer (or NULL if none) - AILLPDIRECTSOUNDBUFFER DS_out_buff; // Output buffer (may be sec or prim) - S32 DS_buffer_size; // Size of entire output buffer - - S32 DS_frag_cnt; // Total fragment count and size, and - S32 DS_frag_size; // last fragment occupied by play cursor - S32 DS_last_frag; - S32 DS_last_write; - S32 DS_last_timer; - S32 DS_skip_time; - - S32 DS_use_default_format; // 1 to force use of default DS primary buffer format - -#else - - #ifdef IS_DOS - - // must be first in the DOS section - void *DMA[2]; // Protected-mode pointers to half-buffers - // (note that DMA[0] may != DMA_buf) - - - REALFAR DMA_seg; // Seg:off pointer to DMA buffers (off=0) - U32 DMA_sel; // Selector for DMA buffers (off=0) - void *DMA_buf; // Protected-mode pointer to DMA buffers - - S16 *buffer_flag; // Protected-mode pointer to buffer flag - S32 last_buffer; // Last active buffer flag value in driver - - AIL_DRIVER *drvr; // Base driver descriptor - - DIG_DDT *DDT; // Protected-mode pointer to DDT - DIG_DST *DST; // Protected-mode pointer to DST - - #endif - -#endif - -#ifdef IS_X86 - S32 use_MMX; // Use MMX with this driver if TRUE -#endif - - void FAR *decode_buffer; // Buffer used by optional ASI pipeline decoder - S32 decode_buffer_size; // # of bytes in decode buffer - - U32 us_count; - U32 ms_count; - U32 last_ms_polled; - U32 last_percent; - - // - // Digital driver pipeline stages - // - - DPINFO pipeline[N_DIGDRV_STAGES]; - - // - // Reverb buffer - // - - S32 FAR *reverb_buffer; - S32 reverb_buffer_size; - S32 reverb_buffer_position; - -#ifdef IS_WINDOWS - S32 no_wom_done; // don't process WOM_DONEs on this driver - U32 wom_done_buffers; -#endif -} -DIG_DRIVER; - -typedef struct // MIDI status log structure - { - S32 program [NUM_CHANS]; // Program Change - S32 pitch_l [NUM_CHANS]; // Pitch Bend LSB - S32 pitch_h [NUM_CHANS]; // Pitch Bend MSB - - S32 c_lock [NUM_CHANS]; // Channel Lock - S32 c_prot [NUM_CHANS]; // Channel Lock Protection - S32 c_mute [NUM_CHANS]; // Channel Mute - S32 c_v_prot [NUM_CHANS]; // Voice Protection - S32 bank [NUM_CHANS]; // Patch Bank Select - S32 gm_bank_l [NUM_CHANS]; // GM Bank Select - S32 gm_bank_m [NUM_CHANS]; // GM Bank Select - S32 indirect [NUM_CHANS]; // ICA indirect controller value - S32 callback [NUM_CHANS]; // Callback Trigger - - S32 mod [NUM_CHANS]; // Modulation - S32 vol [NUM_CHANS]; // Volume - S32 pan [NUM_CHANS]; // Panpot - S32 exp [NUM_CHANS]; // Expression - S32 sus [NUM_CHANS]; // Sustain - S32 reverb [NUM_CHANS]; // Reverb - S32 chorus [NUM_CHANS]; // Chorus - - S32 bend_range[NUM_CHANS]; // Bender Range (data MSB, RPN 0 assumed) - - S32 RPN_L [NUM_CHANS]; // RPN # LSB - S32 RPN_M [NUM_CHANS]; // RPN # MSB - } -CTRL_LOG; - -typedef struct _SEQUENCE // XMIDI sequence state table -{ - char tag[4]; // HSEQ - - HMDIDRIVER driver; // Driver for playback - - U32 status; // SEQ_ flags - - void const FAR *TIMB; // XMIDI IFF chunk pointers - void const FAR *RBRN; - void const FAR *EVNT; - - U8 const FAR *EVNT_ptr; // Current event pointer - - U8 FAR *ICA; // Indirect Controller Array - - AILPREFIXCB prefix_callback; // XMIDI Callback Prefix handler - AILTRIGGERCB trigger_callback; // XMIDI Callback Trigger handler - AILBEATCB beat_callback; // XMIDI beat/bar change handler - AILSEQUENCECB EOS; // End-of-sequence callback function - - S32 loop_count; // 0=one-shot, -1=indefinite, ... - - S32 interval_count; // # of intervals until next event - S32 interval_num; // # of intervals since start - - S32 volume; // Sequence volume 0-127 - S32 volume_target; // Target sequence volume 0-127 - S32 volume_accum; // Accumulated volume period - S32 volume_period; // Period for volume stepping - - S32 tempo_percent; // Relative tempo percentage 0-100 - S32 tempo_target; // Target tempo 0-100 - S32 tempo_accum; // Accumulated tempo period - S32 tempo_period; // Period for tempo stepping - S32 tempo_error; // Error counter for tempo DDA - - S32 beat_count; // Sequence playback position - S32 measure_count; - - S32 time_numerator; // Sequence timing data - S32 time_fraction; - S32 beat_fraction; - S32 time_per_beat; - - void const FAR *FOR_ptrs[FOR_NEST]; // Loop stack - S32 FOR_loop_count [FOR_NEST]; - - S32 chan_map [NUM_CHANS]; // Physical channel map for sequence - - CTRL_LOG shadow; // Controller values for sequence - - S32 note_count; // # of notes "on" - - S32 note_chan [MAX_NOTES]; // Channel for queued note (-1=free) - S32 note_num [MAX_NOTES]; // Note # for queued note - S32 note_time [MAX_NOTES]; // Remaining duration in intervals - - S32 user_data [8]; // Miscellaneous user data - S32 system_data[8]; // Miscellaneous system data - -#ifdef IS_WINDOWS - S32 PREFIX_IsWin32s; // Is this a Win32s callback - S32 TRIGGER_IsWin32s; // Is this a Win32s callback - S32 BEAT_IsWin32s; // Is this a Win32s callback - S32 EOS_IsWin32s; // Is this a Win32s callback -#endif -} SEQUENCE; - -#ifdef IS_MAC - -struct MIDIHDR; -struct MIDIOUT; -typedef struct MIDIOUT* HMIDIOUT; - -#endif - -typedef struct _MDI_DRIVER // Handle to XMIDI driver -{ - char tag[4]; // HMDI - - HTIMER timer; // XMIDI quantization timer - S32 interval_time; // XMIDI quantization timer interval in uS - - S32 disable; // > 0 to disable XMIDI service - - HSEQUENCE sequences; // Pointer to list of SEQUENCEs - S32 n_sequences; // # of SEQUENCEs - - S32 lock [NUM_CHANS]; // 1 if locked, 2 if protected, else 0 - HSEQUENCE locker[NUM_CHANS]; // HSEQUENCE which locked channel - HSEQUENCE owner [NUM_CHANS]; // HSEQUENCE which owned locked channel - HSEQUENCE user [NUM_CHANS]; // Last sequence to use channel - S32 state [NUM_CHANS]; // Lock state prior to being locked - - S32 notes [NUM_CHANS]; // # of active notes in channel - - AILEVENTCB event_trap; // MIDI event trap callback function - AILTIMBRECB timbre_trap; // Timbre request callback function - - S32 master_volume; // Master XMIDI note volume 0-127 - - S32 system_data[8]; // Miscellaneous system data - -#if defined(IS_WINDOWS) || defined(IS_MAC) - - S32 released; // has the hmidiout handle been released - U32 deviceid; // ID of the MIDI device - U8 FAR *sysdata; // SysEx buffer - -#endif - -#ifdef IS_WINDOWS - - S32 EVENT_IsWin32s; // Is this a Win32s callback - S32 TIMBRE_IsWin32s; // Is this a Win32s callback - - MIDIHDR FAR *mhdr; // SysEx header - - HMDIDRIVER next; // Pointer to next HMDIDRIVER in use - S32 callingCT; // Calling EXE's task number (16 bit only) - S32 callingDS; // Calling EXE's DS (used in 16 bit only) - - HMIDIOUT hMidiOut; // MIDI output driver - -#else - - #ifdef IS_DOS - - S32 message_count; // MIDI message count - S32 offset; // MIDI buffer offset - - AIL_DRIVER *drvr; // Base driver descriptor - - MDI_DDT *DDT; // Protected-mode pointer to DDT - MDI_DST *DST; // Protected-mode pointer to DST - #else - #ifdef IS_MAC - struct MIDIHDR FAR *mhdr; // SysEx header - HMDIDRIVER next; // Pointer to next HMDIDRIVER in use - HMIDIOUT hMidiOut; // MIDI output driver - U32 last_us_time; - long period_counter; - long current_period_sum; - #endif - #endif - -#endif - -} -MDI_DRIVER; - -typedef struct // XMIDI TIMB IFF chunk - { - S8 name[4]; - - U8 msb; - U8 lsb; - U8 lsb2; - U8 lsb3; - - U16 n_entries; - - U16 timbre[1]; - } -TIMB_chunk; - -typedef struct // XMIDI RBRN IFF entry - { - S16 bnum; - U32 offset; - } -RBRN_entry; - -typedef struct // Wave library entry -{ - S32 bank; // XMIDI bank, MIDI patch for sample - S32 patch; - - S32 root_key; // Root MIDI note # for sample (or -1) - - U32 file_offset; // Offset of wave data from start-of-file - U32 size; // Size of wave sample in bytes - - S32 format; // DIG_F format (8/16 bits, mono/stereo) - U32 flags; // DIG_PCM_SIGN / DIG_PCM_ORDER (stereo) - S32 playback_rate; // Playback rate in hertz -} -WAVE_ENTRY; - -typedef struct // Virtual "wave synthesizer" descriptor -{ - HMDIDRIVER mdi; // MIDI driver for use with synthesizer - HDIGDRIVER dig; // Digital driver for use with synthesizer - - WAVE_ENTRY FAR *library; // Pointer to wave library - - AILEVENTCB prev_event_fn; // Previous MIDI event trap function - AILTIMBRECB prev_timb_fn; // Previous timbre request trap function - - CTRL_LOG controls; // MIDI controller states - - WAVE_ENTRY FAR *wave [NUM_CHANS];// Pointer to WAVE_ENTRY for each channel - - HSAMPLE S [MAX_W_VOICES]; // List of HSAMPLE voices - S32 n_voices; // Actual # of voices allocated to synth - - S32 chan [MAX_W_VOICES]; // MIDI channel for each voice, or -1 - S32 note [MAX_W_VOICES]; // MIDI note number for voice - S32 root [MAX_W_VOICES]; // MIDI root note for voice - S32 rate [MAX_W_VOICES]; // Playback rate for voice - S32 vel [MAX_W_VOICES]; // MIDI note velocity for voice - U32 time [MAX_W_VOICES]; // Timestamp for voice - - U32 event; // Event counter for LRU timestamps -} -WAVE_SYNTH; - -typedef WAVE_SYNTH FAR * HWAVESYNTH;// Handle to virtual wave synthesizer - -// -// Handle to thread which called AIL_startup() -// -// This thread is suspended by MSS callback threads, to simulate DOS-style -// interrupt handler behavior -// - -#ifdef IS_WIN32 - -extern HANDLE hAppThread; - -#endif - -// -// Background flag for timers -// - -extern volatile S32 AIL_bkgnd_flag; - -// -// Global preference array -// - -extern S32 AIL_preference [N_PREFS]; - -// -// DIG_DRIVER list -// - -extern HDIGDRIVER DIG_first; - -// -// MDI_DRIVER list -// - -extern HMDIDRIVER MDI_first; - -// -// Miscellaneous system services -// - -#define FILE_READ_WITH_SIZE ((void FAR*)(S32)-1) - -#ifndef NO_OLD_SYS_FUNCTIONS - -#define MEM_alloc_lock AIL_mem_alloc_lock -#define MEM_free_lock AIL_mem_free_lock -#define FILE_error AIL_file_error -#define FILE_size AIL_file_size -#define FILE_read AIL_file_read -#define FILE_write AIL_file_write - -#ifdef IS_DOS - -#define MEM_alloc AIL_mem_alloc -#define MEM_free AIL_mem_free -#define MEM_use_malloc AIL_mem_use_malloc -#define MEM_use_free AIL_mem_use_free -#define MEM_alloc_DOS AIL_mem_alloc_DOS -#define MEM_free_DOS AIL_mem_free_DOS -#define VMM_lock_range AIL_vmm_lock_range -#define VMM_unlock_range AIL_vmm_unlock_range -#define VMM_lock AIL_vmm_lock -#define VMM_unlock AIL_vmm_unlock - -#endif - -#endif - -extern S32 AILCALLBACK DP_ASI_DECODER_callback(U32 user, - void FAR *dest, - S32 bytes_requested, - S32 offset); - -DXDEC void FAR * AILCALL AIL_mem_alloc_lock(U32 size); -DXDEC void AILCALL AIL_mem_free_lock (void FAR *ptr); - -DXDEC S32 AILCALL AIL_file_error (void); - -DXDEC S32 AILCALL AIL_file_size (char const FAR *filename); - -DXDEC void FAR * AILCALL AIL_file_read (char const FAR *filename, - void FAR *dest); - -DXDEC S32 AILCALL AIL_file_write (char const FAR *filename, - void const FAR *buf, - U32 len); - -DXDEC S32 AILCALL AIL_WAV_file_write - (char const FAR *filename, - void const FAR *buf, - U32 len, - S32 rate, - S32 format); - -DXDEC S32 AILCALL AIL_file_append (char const FAR *filename, - void const FAR *buf, U32 len); - -#ifdef IS_MAC - - -DXDEC S32 AILCALL AIL_file_fss_size(FSSpec const FAR *filename); - -DXDEC void FAR * AILCALL AIL_file_fss_read(FSSpec const FAR *filename, - void FAR *dest); - -DXDEC S32 AILCALL AIL_file_fss_write(FSSpec const FAR *filename, - void const FAR *buf, - U32 len); - -DXDEC S32 AILCALL AIL_file_fss_attrib_write - (FSSpec const FAR *filename, - void const FAR *buf, - U32 len, - U32 type, - U32 creator ); - -DXDEC S32 AILCALL AIL_WAV_file_fss_write - (FSSpec const FAR *filename, - void const FAR *buf, - U32 len, - S32 rate, - S32 format); - -DXDEC void * AILCALL AIL_mem_use_malloc(void * AILCALLBACK (*fn)(U32)); -DXDEC void * AILCALL AIL_mem_use_free (void AILCALLBACK (*fn)(void *)); - -#endif - -#ifdef IS_DOS - -extern void * AILCALLBACK (*AIL_mem_alloc) (U32); -extern void AILCALLBACK (*AIL_mem_free) (void *); - -void * cdecl AIL_mem_use_malloc(void * AILCALLBACK (*fn)(U32)); -void * cdecl AIL_mem_use_free (void AILCALLBACK (*fn)(void *)); - -// -// Other memory-management functions -// - -DXDEC S32 AILCALL AIL_mem_alloc_DOS (U32 n_paras, - void **protected_ptr, - U32 *segment_far_ptr, - U32 *selector); - -DXDEC void AILCALL AIL_mem_free_DOS (void *protected_ptr, - U32 segment_far_ptr, - U32 selector); - -DXDEC S32 AILCALL AIL_vmm_lock_range (void *p1, void *p2); -DXDEC S32 AILCALL AIL_vmm_unlock_range (void *p1, void *p2); - -DXDEC S32 AILCALL AIL_vmm_lock (void *start, U32 size); -DXDEC S32 AILCALL AIL_vmm_unlock (void *start, U32 size); - -DXDEC U32 AILCALL AIL_sel_base (U32 sel); - -DXDEC void AILCALL AIL_sel_set_limit (U32 sel, - U32 limit); -// -// Last IO_PARMS structure used to attempt device detection -// - -extern IO_PARMS AIL_last_IO_attempt; - -// -// Low-level support services -// - -DXDEC REALFAR AILCALL AIL_get_real_vect (U32 vectnum); - -DXDEC void AILCALL AIL_set_real_vect (U32 vectnum, - REALFAR real_ptr); - -DXDEC void AILCALL AIL_set_USE16_ISR (S32 IRQ, - REALFAR real_base, - U32 ISR_offset); - -DXDEC void AILCALL AIL_restore_USE16_ISR (S32 IRQ); - -DXDEC U32 AILCALL AIL_disable_interrupts (void); -DXDEC void AILCALL AIL_restore_interrupts (U32 FD_register); - -DXDEC void AILCALL AIL_switch_stack (void *stack, - U32 size, - U32 *SS, - void **ESP, - void **EBP); - -DXDEC void AILCALL AIL_restore_stack (U32 SS, - void *ESP, - void *EBP); - -DXDEC S32 AILCALL AIL_call_driver (AIL_DRIVER *drvr, - S32 fn, - VDI_CALL *in, - VDI_CALL *out); - -DXDEC S32 AILCALL AIL_read_INI (AIL_INI *INI, - char *filename); - -DXDEC U32 AILCALL AIL_interrupt_divisor (void); - -#endif - - -#ifdef __WATCOMC__ - -void MSSBreakPoint(); -#pragma aux MSSBreakPoint = "int 3"; - -#else - -#define MSSBreakPoint() __asm {int 3} - -#endif - - -// -// High-level support services -// - -#ifdef IS_MAC - -#if !defined(max) -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif -#if !defined(min) -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#endif - -#ifdef IS_DOS - -#ifdef IS_WATCOM - -#if !defined(max) // Watcom stdlib.h doesn't define these for C++ -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif -#if !defined(min) -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#endif - -#ifdef __SW_3R -extern S32 AILCALL AIL_startup_reg (void); -#define AIL_startup AIL_startup_reg -#else -extern S32 AILCALL AIL_startup_stack (void); -#define AIL_startup AIL_startup_stack -#endif - -#define AIL_quick_startup(ud,um,opr,opb,ops) AIL_quick_startup_with_start(&AIL_startup,ud,um,opr,opb,ops) - -#define AIL_get_preference(number) (AIL_preference[number]) - -#else - -DXDEC S32 AILCALL AIL_startup (void); - -DXDEC S32 AILCALL AIL_get_preference (U32 number); - -#endif - -DXDEC void AILCALL AIL_shutdown (void); - -DXDEC S32 AILCALL AIL_set_preference (U32 number, - S32 value); - -DXDEC char FAR *AILCALL AIL_last_error (void); - -DXDEC void AILCALL AIL_set_error (char const FAR * error_msg); - -// -// Low-level support services -// - -DXDEC void -#ifndef IS_MAC -__cdecl -#endif -AIL_debug_printf (C8 const FAR *fmt, ...); - -#ifdef IS_X86 - -DXDEC U32 AILCALL AIL_MMX_available (void); - -#endif - -DXDEC void AILCALL AIL_lock (void); -DXDEC void AILCALL AIL_unlock (void); - -#ifdef IS_WIN32 - -DXDEC void AILCALL AIL_lock_mutex (void); -DXDEC void AILCALL AIL_unlock_mutex (void); - -#endif - -DXDEC void AILCALL AIL_delay (S32 intervals); - -DXDEC S32 AILCALL AIL_background (void); - -// -// Process services -// - -DXDEC HTIMER AILCALL AIL_register_timer (AILTIMERCB fn); - -DXDEC U32 AILCALL AIL_set_timer_user (HTIMER timer, - U32 user); - -DXDEC void AILCALL AIL_set_timer_period (HTIMER timer, - U32 microseconds); - -DXDEC void AILCALL AIL_set_timer_frequency (HTIMER timer, - U32 hertz); - -DXDEC void AILCALL AIL_set_timer_divisor (HTIMER timer, - U32 PIT_divisor); - -DXDEC void AILCALL AIL_start_timer (HTIMER timer); -DXDEC void AILCALL AIL_start_all_timers (void); - -DXDEC void AILCALL AIL_stop_timer (HTIMER timer); -DXDEC void AILCALL AIL_stop_all_timers (void); - -DXDEC void AILCALL AIL_release_timer_handle (HTIMER timer); -DXDEC void AILCALL AIL_release_all_timers (void); - -#ifdef IS_WIN32 - -#ifndef BUILD_MSS - -// static function that handles shutdown -int __cdecl MSS_auto_cleanup(void); - -#ifdef _MSC_VER -// on MSVC, automatically register a cleanup function -//ODCODENOTE Remove -//#define AIL_startup() (MSS_auto_cleanup(),AIL_startup()) -#endif - -#endif - -DXDEC HWND AILCALL AIL_HWND (void); - -#else - #ifdef IS_MAC - DXDEC ProcessSerialNumber AIL_Process(void); - #endif -#endif - -// -// high-level digital services -// - -DXDEC HDIGDRIVER AILCALL AIL_open_digital_driver( U32 frequency, - S32 bits, - S32 channel, - U32 flags ); - -#define AIL_OPEN_DIGITAL_FORCE_PREFERENCE 1 - -DXDEC void AILCALL AIL_close_digital_driver( HDIGDRIVER dig ); - -#ifdef IS_WINDOWS - -#define AIL_MSS_version(str,len) \ -{ \ - HINSTANCE l=LoadLibrary(MSSDLLNAME); \ - if ((U32)l<=32) \ - *(str)=0; \ - else { \ - LoadString(l,1,str,len); \ - FreeLibrary(l); \ - } \ -} - -DXDEC S32 AILCALL AIL_waveOutOpen (HDIGDRIVER FAR *drvr, - LPHWAVEOUT FAR *lphWaveOut, - S32 wDeviceID, - LPWAVEFORMAT lpFormat); - -DXDEC void AILCALL AIL_waveOutClose (HDIGDRIVER drvr); - -DXDEC S32 AILCALL AIL_digital_handle_release(HDIGDRIVER drvr); - -DXDEC S32 AILCALL AIL_digital_handle_reacquire - (HDIGDRIVER drvr); - -#else - -#ifdef IS_MAC - -typedef struct MSS_VersionType_ -{ - Str255 version_name; -} MSS_VersionType; - -#define AIL_MSS_version(str,len) \ -{ \ - long _res = OpenResFile("\pMiles Shared Library"); \ - if (_res==-1) \ - { \ - str[0]=0; \ - } \ - else \ - { \ - Handle _H; \ - short _Err; \ - long _cur= CurResFile(); \ - UseResFile(_res); \ - _H = GetResource('vers', 2); \ - _Err = ResError(); \ - if((_Err != noErr) || (_H==0)) \ - { \ - str[0]=0; \ - UseResFile(_cur); \ - CloseResFile(_res); \ - } \ - else \ - { \ - if (GetHandleSize(_H)==0) \ - { \ - str[0]=0; \ - UseResFile(_cur); \ - CloseResFile(_res); \ - } \ - else \ - { \ - MSS_VersionType * _vt = (MSS_VersionType*)*_H; \ - if ((U32)_vt->version_name[6]>4) \ - _vt->version_name[6]-=4; \ - else \ - _vt->version_name[6]=0; \ - if (((U32)len) <= ((U32)_vt->version_name[6])) \ - _vt->version_name[6] = (U8)len-1; \ - memcpy( str, _vt->version_name+11, _vt->version_name[6] ); \ - str[_vt->version_name[6]]=0; \ - UseResFile(_cur); \ - CloseResFile(_res); \ - } \ - ReleaseResource(_H); \ - } \ - } \ -} - -DXDEC S32 AILCALL AIL_digital_handle_release(HDIGDRIVER drvr); - -DXDEC S32 AILCALL AIL_digital_handle_reacquire - (HDIGDRIVER drvr); - -#else - -// -// DOS installation services -// - -DXDEC IO_PARMS * AILCALL AIL_get_IO_environment (AIL_DRIVER *drvr); - -DXDEC AIL_DRIVER* AILCALL AIL_install_driver (U8 const *driver_image, - U32 n_bytes); - -DXDEC void AILCALL AIL_uninstall_driver (AIL_DRIVER *drvr); - -DXDEC S32 AILCALL AIL_install_DIG_INI (HDIGDRIVER *dig); - -DXDEC HDIGDRIVER AILCALL AIL_install_DIG_driver_file - (char const *filename, - IO_PARMS *IO); - -DXDEC void AILCALL AIL_uninstall_DIG_driver (HDIGDRIVER dig); - - -DXDEC HDIGDRIVER AILCALL AIL_install_DIG_driver_image - (void const *driver_image, - U32 size, - IO_PARMS *IO); -#endif -#endif - -DXDEC char FAR* AILCALL AIL_set_redist_directory(char const FAR*dir); - -DXDEC S32 AILCALL AIL_digital_CPU_percent (HDIGDRIVER dig); - -DXDEC S32 AILCALL AIL_digital_latency (HDIGDRIVER dig); - -DXDEC HSAMPLE AILCALL AIL_allocate_sample_handle - (HDIGDRIVER dig); - -DXDEC HSAMPLE AILCALL AIL_allocate_file_sample (HDIGDRIVER dig, - void const FAR *file_image, - S32 block); - -DXDEC void AILCALL AIL_release_sample_handle (HSAMPLE S); - -DXDEC void AILCALL AIL_init_sample (HSAMPLE S); - -DXDEC S32 AILCALL AIL_set_sample_file (HSAMPLE S, - void const FAR *file_image, - S32 block); - -DXDEC S32 AILCALL AIL_set_named_sample_file (HSAMPLE S, - C8 const FAR *file_type_suffix, - void const FAR *file_image, - S32 file_size, - S32 block); - -DXDEC HPROVIDER AILCALL AIL_set_sample_processor (HSAMPLE S, - SAMPLESTAGE pipeline_stage, - HPROVIDER provider); - -DXDEC HPROVIDER AILCALL AIL_set_digital_driver_processor - (HDIGDRIVER dig, - DIGDRVSTAGE pipeline_stage, - HPROVIDER provider); - -DXDEC void AILCALL AIL_set_sample_adpcm_block_size - (HSAMPLE S, - U32 blocksize); - -DXDEC void AILCALL AIL_set_sample_address (HSAMPLE S, - void const FAR *start, - U32 len); - -DXDEC void AILCALL AIL_set_sample_type (HSAMPLE S, - S32 format, - U32 flags); - -DXDEC void AILCALL AIL_start_sample (HSAMPLE S); - -DXDEC void AILCALL AIL_stop_sample (HSAMPLE S); - -DXDEC void AILCALL AIL_resume_sample (HSAMPLE S); - -DXDEC void AILCALL AIL_end_sample (HSAMPLE S); - -DXDEC void AILCALL AIL_set_sample_playback_rate - (HSAMPLE S, - S32 playback_rate); - -DXDEC void AILCALL AIL_set_sample_volume (HSAMPLE S, - S32 volume); - -DXDEC void AILCALL AIL_set_sample_pan (HSAMPLE S, - S32 pan); - -DXDEC void AILCALL AIL_set_sample_loop_count (HSAMPLE S, - S32 loop_count); - -DXDEC void AILCALL AIL_set_sample_loop_block (HSAMPLE S, - S32 loop_start_offset, - S32 loop_end_offset); - -DXDEC U32 AILCALL AIL_sample_status (HSAMPLE S); - -DXDEC S32 AILCALL AIL_sample_playback_rate (HSAMPLE S); - -DXDEC S32 AILCALL AIL_sample_volume (HSAMPLE S); - -DXDEC S32 AILCALL AIL_sample_pan (HSAMPLE S); - -DXDEC S32 AILCALL AIL_sample_loop_count (HSAMPLE S); - -DXDEC void AILCALL AIL_set_digital_master_volume - (HDIGDRIVER dig, - S32 master_volume); - -DXDEC S32 AILCALL AIL_digital_master_volume (HDIGDRIVER dig); - -DXDEC void AILCALL AIL_set_sample_reverb(HSAMPLE S, - F32 reverb_level, - F32 reverb_reflect_time, - F32 reverb_decay_time); - -DXDEC void AILCALL AIL_sample_reverb (HSAMPLE S, - F32 FAR *reverb_level, - F32 FAR *reverb_reflect_time, - F32 FAR *reverb_decay_time); - -// -// low-level digital services -// - -DXDEC S32 AILCALL AIL_minimum_sample_buffer_size(HDIGDRIVER dig, - S32 playback_rate, - S32 format); - -DXDEC S32 AILCALL AIL_sample_buffer_ready (HSAMPLE S); - -DXDEC void AILCALL AIL_load_sample_buffer (HSAMPLE S, - U32 buff_num, - void const FAR *buffer, - U32 len); - -DXDEC void AILCALL AIL_request_EOB_ASI_reset (HSAMPLE S, - U32 buff_num); - -DXDEC S32 AILCALL AIL_sample_buffer_info (HSAMPLE S, //) - U32 FAR *pos0, - U32 FAR *len0, - U32 FAR *pos1, - U32 FAR *len1); - -DXDEC U32 AILCALL AIL_sample_granularity (HSAMPLE S); - -DXDEC void AILCALL AIL_set_sample_position (HSAMPLE S, - U32 pos); - -DXDEC U32 AILCALL AIL_sample_position (HSAMPLE S); - -DXDEC AILSAMPLECB AILCALL AIL_register_SOB_callback - (HSAMPLE S, - AILSAMPLECB SOB); - -DXDEC AILSAMPLECB AILCALL AIL_register_EOB_callback - (HSAMPLE S, - AILSAMPLECB EOB); - -DXDEC AILSAMPLECB AILCALL AIL_register_EOS_callback - (HSAMPLE S, - AILSAMPLECB EOS); - -DXDEC AILSAMPLECB AILCALL AIL_register_EOF_callback - (HSAMPLE S, - AILSAMPLECB EOFILE); - -DXDEC void AILCALL AIL_set_sample_user_data (HSAMPLE S, - U32 index, - S32 value); - -DXDEC S32 AILCALL AIL_sample_user_data (HSAMPLE S, - U32 index); - -DXDEC S32 AILCALL AIL_active_sample_count (HDIGDRIVER dig); - -DXDEC void AILCALL AIL_digital_configuration (HDIGDRIVER dig, - S32 FAR *rate, - S32 FAR *format, - char FAR *string); -#ifdef IS_WIN32 - -DXDEC S32 AILCALL AIL_set_direct_buffer_control (HSAMPLE S, - U32 command); - -DXDEC void AILCALL AIL_get_DirectSound_info (HSAMPLE S, - AILLPDIRECTSOUND *lplpDS, - AILLPDIRECTSOUNDBUFFER *lplpDSB); - -DXDEC S32 AILCALL AIL_set_DirectSound_HWND(HDIGDRIVER dig, HWND wnd); - -#endif - -DXDEC void AILCALL AIL_set_sample_ms_position (HSAMPLE S, //) - S32 milliseconds); - -DXDEC void AILCALL AIL_sample_ms_position (HSAMPLE S, //) - S32 FAR * total_milliseconds, - S32 FAR * current_milliseconds); - - -// -// Digital input services -// - -#if defined(IS_WINDOWS) || defined (IS_MAC) - -DXDEC HDIGINPUT AILCALL AIL_open_input (AIL_INPUT_INFO FAR *info); - -DXDEC void AILCALL AIL_close_input (HDIGINPUT dig); - -DXDEC AIL_INPUT_INFO FAR * - AILCALL AIL_get_input_info (HDIGINPUT dig); - -DXDEC S32 AILCALL AIL_set_input_state (HDIGINPUT dig, - S32 enable); -#endif - - -// -// High-level XMIDI services -// - -DXDEC HMDIDRIVER AILCALL AIL_open_XMIDI_driver( U32 flags ); - -#define AIL_OPEN_XMIDI_NULL_DRIVER 1 - -DXDEC void AILCALL AIL_close_XMIDI_driver( HMDIDRIVER mdi ); - -#ifdef IS_MAC - -DXDEC S32 AILCALL AIL_MIDI_handle_release - (HMDIDRIVER mdi); - -DXDEC S32 AILCALL AIL_MIDI_handle_reacquire - (HMDIDRIVER mdi); - -#else - -#ifdef IS_WINDOWS - -DXDEC S32 AILCALL AIL_midiOutOpen(HMDIDRIVER FAR *drvr, - LPHMIDIOUT FAR *lphMidiOut, - S32 dwDeviceID); - -DXDEC void AILCALL AIL_midiOutClose (HMDIDRIVER mdi); - -DXDEC S32 AILCALL AIL_MIDI_handle_release - (HMDIDRIVER mdi); - -DXDEC S32 AILCALL AIL_MIDI_handle_reacquire - (HMDIDRIVER mdi); - -#else - -#ifdef IS_DOS - -DXDEC S32 AILCALL AIL_install_MDI_INI (HMDIDRIVER *mdi); - -DXDEC HMDIDRIVER AILCALL AIL_install_MDI_driver_file - (char const *filename, - IO_PARMS *IO); - -DXDEC void AILCALL AIL_uninstall_MDI_driver (HMDIDRIVER mdi); - - -DXDEC HMDIDRIVER AILCALL AIL_install_MDI_driver_image - (void const *driver_image, - U32 size, - IO_PARMS *IO); - -DXDEC S32 AILCALL AIL_MDI_driver_type (HMDIDRIVER mdi); - -DXDEC void AILCALL AIL_set_GTL_filename_prefix (char const*prefix); - -DXDEC S32 AILCALL AIL_timbre_status (HMDIDRIVER mdi, - S32 bank, - S32 patch); - -DXDEC S32 AILCALL AIL_install_timbre (HMDIDRIVER mdi, - S32 bank, - S32 patch); - -DXDEC void AILCALL AIL_protect_timbre (HMDIDRIVER mdi, - S32 bank, - S32 patch); - -DXDEC void AILCALL AIL_unprotect_timbre (HMDIDRIVER mdi, - S32 bank, - S32 patch); - -#endif - -#endif - -#endif - -DXDEC HSEQUENCE AILCALL AIL_allocate_sequence_handle - (HMDIDRIVER mdi); - -DXDEC void AILCALL AIL_release_sequence_handle - (HSEQUENCE S); - -DXDEC S32 AILCALL AIL_init_sequence (HSEQUENCE S, - void const FAR *start, - S32 sequence_num); - -DXDEC void AILCALL AIL_start_sequence (HSEQUENCE S); - -DXDEC void AILCALL AIL_stop_sequence (HSEQUENCE S); - -DXDEC void AILCALL AIL_resume_sequence (HSEQUENCE S); - -DXDEC void AILCALL AIL_end_sequence (HSEQUENCE S); - -DXDEC void AILCALL AIL_set_sequence_tempo (HSEQUENCE S, - S32 tempo, - S32 milliseconds); - -DXDEC void AILCALL AIL_set_sequence_volume (HSEQUENCE S, - S32 volume, - S32 milliseconds); - -DXDEC void AILCALL AIL_set_sequence_loop_count - (HSEQUENCE S, - S32 loop_count); - -DXDEC U32 AILCALL AIL_sequence_status (HSEQUENCE S); - -DXDEC S32 AILCALL AIL_sequence_tempo (HSEQUENCE S); - -DXDEC S32 AILCALL AIL_sequence_volume (HSEQUENCE S); - -DXDEC S32 AILCALL AIL_sequence_loop_count (HSEQUENCE S); - -DXDEC void AILCALL AIL_set_XMIDI_master_volume - (HMDIDRIVER mdi, - S32 master_volume); - -DXDEC S32 AILCALL AIL_XMIDI_master_volume (HMDIDRIVER mdi); - - -// -// Low-level XMIDI services -// - -DXDEC S32 AILCALL AIL_active_sequence_count (HMDIDRIVER mdi); - -DXDEC S32 AILCALL AIL_controller_value (HSEQUENCE S, - S32 channel, - S32 controller_num); - -DXDEC S32 AILCALL AIL_channel_notes (HSEQUENCE S, - S32 channel); - -DXDEC void AILCALL AIL_sequence_position (HSEQUENCE S, - S32 FAR *beat, - S32 FAR *measure); - -DXDEC void AILCALL AIL_branch_index (HSEQUENCE S, - U32 marker); - -DXDEC AILPREFIXCB AILCALL AIL_register_prefix_callback - (HSEQUENCE S, - AILPREFIXCB callback); - -DXDEC AILTRIGGERCB AILCALL AIL_register_trigger_callback - (HSEQUENCE S, - AILTRIGGERCB callback); - -DXDEC AILSEQUENCECB AILCALL AIL_register_sequence_callback - (HSEQUENCE S, - AILSEQUENCECB callback); - -DXDEC AILBEATCB AILCALL AIL_register_beat_callback (HSEQUENCE S, - AILBEATCB callback); - -DXDEC AILEVENTCB AILCALL AIL_register_event_callback (HMDIDRIVER mdi, - AILEVENTCB callback); - -DXDEC AILTIMBRECB AILCALL AIL_register_timbre_callback - (HMDIDRIVER mdi, - AILTIMBRECB callback); - -DXDEC void AILCALL AIL_set_sequence_user_data (HSEQUENCE S, - U32 index, - S32 value); - -DXDEC S32 AILCALL AIL_sequence_user_data (HSEQUENCE S, - U32 index); - -DXDEC void AILCALL AIL_register_ICA_array (HSEQUENCE S, - U8 FAR *array); - -DXDEC S32 AILCALL AIL_lock_channel (HMDIDRIVER mdi); - -DXDEC void AILCALL AIL_release_channel (HMDIDRIVER mdi, - S32 channel); - -DXDEC void AILCALL AIL_map_sequence_channel (HSEQUENCE S, - S32 seq_channel, - S32 new_channel); - -DXDEC S32 AILCALL AIL_true_sequence_channel (HSEQUENCE S, - S32 seq_channel); - -DXDEC void AILCALL AIL_send_channel_voice_message - (HMDIDRIVER mdi, - HSEQUENCE S, - S32 status, - S32 data_1, - S32 data_2); - -DXDEC void AILCALL AIL_send_sysex_message (HMDIDRIVER mdi, - void const FAR *buffer); - -DXDEC HWAVESYNTH - AILCALL AIL_create_wave_synthesizer (HDIGDRIVER dig, - HMDIDRIVER mdi, - void const FAR *wave_lib, - S32 polyphony); - -DXDEC void AILCALL AIL_destroy_wave_synthesizer (HWAVESYNTH W); - -DXDEC void AILCALL AIL_set_sequence_ms_position (HSEQUENCE S, //) - S32 milliseconds); - -DXDEC void AILCALL AIL_sequence_ms_position(HSEQUENCE S, //) - S32 FAR *total_milliseconds, - S32 FAR *current_milliseconds); - - - -// -// red book functions -// - -#ifdef IS_DOS -typedef struct _REDBOOKTRACKINFO { - U32 tracks; - U32 trackstarts[100]; -} REDBOOKTRACKINFO; -#endif - -typedef struct _REDBOOK { - U32 DeviceID; - U32 paused; - U32 pausedsec; - U32 lastendsec; -#ifdef IS_DOS - U32 readcontents; - REDBOOKTRACKINFO info; -#endif -#ifdef IS_MAC - short vDRefNum; -#endif -} REDBOOK; - -typedef struct _REDBOOK FAR* HREDBOOK; - -#define REDBOOK_ERROR 0 -#define REDBOOK_PLAYING 1 -#define REDBOOK_PAUSED 2 -#define REDBOOK_STOPPED 3 - - -DXDEC HREDBOOK AILCALL AIL_redbook_open(U32 which); - -#ifdef IS_MAC -DXDEC HREDBOOK AILCALL AIL_redbook_open_volume(char const * drive); -#else -DXDEC HREDBOOK AILCALL AIL_redbook_open_drive(S32 drive); -#endif - -DXDEC void AILCALL AIL_redbook_close(HREDBOOK hand); - -DXDEC void AILCALL AIL_redbook_eject(HREDBOOK hand); - -DXDEC void AILCALL AIL_redbook_retract(HREDBOOK hand); - -DXDEC U32 AILCALL AIL_redbook_status(HREDBOOK hand); - -DXDEC U32 AILCALL AIL_redbook_tracks(HREDBOOK hand); - -DXDEC U32 AILCALL AIL_redbook_track(HREDBOOK hand); - -DXDEC void AILCALL AIL_redbook_track_info(HREDBOOK hand,U32 tracknum, - U32 FAR* startmsec,U32 FAR* endmsec); - -DXDEC U32 AILCALL AIL_redbook_id(HREDBOOK hand); - -DXDEC U32 AILCALL AIL_redbook_position(HREDBOOK hand); - -DXDEC U32 AILCALL AIL_redbook_play(HREDBOOK hand,U32 startmsec, U32 endmsec); - -DXDEC U32 AILCALL AIL_redbook_stop(HREDBOOK hand); - -DXDEC U32 AILCALL AIL_redbook_pause(HREDBOOK hand); - -DXDEC U32 AILCALL AIL_redbook_resume(HREDBOOK hand); - -DXDEC S32 AILCALL AIL_redbook_volume(HREDBOOK hand); - -DXDEC S32 AILCALL AIL_redbook_set_volume(HREDBOOK hand, S32 volume); - -#ifdef IS_WIN16 - #define AIL_ms_count timeGetTime - DXDEC U32 AILCALL AIL_us_count(void); -#else - DXDEC U32 AILCALL AIL_ms_count(void); - DXDEC U32 AILCALL AIL_us_count(void); -#endif - - -typedef struct _STREAM FAR* HSTREAM; // Handle to stream - -typedef void (AILCALLBACK FAR* AILSTREAMCB) (HSTREAM stream); - -typedef struct _STREAM { - - S32 block_oriented; // 1 if this is an ADPCM or ASI-compressed stream - S32 using_ASI; // 1 if using ASI decoder to uncompress stream data - ASISTAGE FAR *ASI; // handy pointer to our ASI coded - - HSAMPLE samp; // the sample handle - - U32 fileh; // the open file handle - - U8 FAR* bufs[3]; // the data buffers - U32 bufsizes[3]; // the size of each buffer - S32 reset_ASI[3]; // should we reset the ASI at the end of the buffer? - S32 bufstart[3]; // offset of where this buffer started - void FAR* asyncs[3];// async read structures - - S32 loadedbufstart[2]; // offset of where the loaded buffer started - S32 loadedorder[2]; // order of the buffers as they were loaded - S32 loadorder; // incremented as each buffer is loaded - - S32 bufsize; // size of each buffer - S32 readsize; // size of each read block - - U32 buf1; // 0,1,2 (current buffer that we are reading into) - S32 size1; // holds the current amount of data read - - U32 buf2; // 0,1,2 (the next buffer that we are reading into) - S32 size2; // next buffer loaded up to - - U32 buf3; // 0,1,2 (the next buffer that we are reading into) - S32 size3; // next buffer loaded up to - - U32 datarate; // datarate in bytes per second - S32 filerate; // original datarate of the file - S32 filetype; // file format type - U32 fileflags; // file format flags (signed or unsigned) - S32 totallen; // total length of the sound data - - S32 substart; // subblock loop start - S32 sublen; // subblock loop len - S32 subpadding; // amount to pad the final block - - U32 blocksize; // ADPCM block size - S32 padding; // padding to be done - S32 padded; // padding done - - S32 loadedsome; // have we done any loads? - - U32 startpos; // point that the sound data begins - U32 totalread; // total bytes read from the disk - - U32 loopsleft; // how many loops are left - - U32 error; // read error has occurred - - S32 preload; // preload the file into the first buffer - U32 preloadpos; // position to use in preload - S32 noback; // no background processing - S32 alldone; // alldone - S32 primeamount; // amount to load after a seek - S32 readatleast; // forced amount to read on next service - - S32 playcontrol; // control: 0=stopped, 1=started, |8=paused, |16=sample paused - - AILSTREAMCB callback; // end of stream callback - - S32 user_data[8]; // Miscellaneous user data - void FAR* next; // pointer to next stream - -#if defined(IS_WINDOWS) || defined(IS_MAC) - S32 autostreaming; // are we autostreaming this stream -#endif - -#ifdef IS_WINDOWS - S32 cb_IsWin32s; // Is the callback win32s? -#endif - - S32 docallback; // set when it time to poll for a callback - -#ifdef IS_MAC - IOParam stream_param; - S32 donext; - S32 donext1; - U32 fillup; - U32 session; - U32 tamt; - U32 buf; - S32* size; - S32* done; - S32 done1; - S32 done2; - S32 done3; - Boolean force_quit; -#endif - -} MSTREAM_TYPE; - - -DXDEC HSTREAM AILCALL AIL_open_stream(HDIGDRIVER dig, char const FAR * filename, S32 stream_mem); - -DXDEC void AILCALL AIL_close_stream(HSTREAM stream); - -DXDEC S32 AILCALL AIL_service_stream(HSTREAM stream, S32 fillup); - -DXDEC void AILCALL AIL_start_stream(HSTREAM stream); - -DXDEC void AILCALL AIL_pause_stream(HSTREAM stream, S32 onoff); - -DXDEC void AILCALL AIL_set_stream_volume(HSTREAM stream,S32 volume); - -DXDEC void AILCALL AIL_set_stream_pan(HSTREAM stream,S32 pan); - -DXDEC S32 AILCALL AIL_stream_volume(HSTREAM stream); - -DXDEC S32 AILCALL AIL_stream_pan(HSTREAM stream); - -DXDEC void AILCALL AIL_set_stream_playback_rate(HSTREAM stream, S32 rate); - -DXDEC S32 AILCALL AIL_stream_playback_rate(HSTREAM stream); - -DXDEC S32 AILCALL AIL_stream_loop_count(HSTREAM stream); - -DXDEC void AILCALL AIL_set_stream_loop_count(HSTREAM stream, S32 count); - -DXDEC void AILCALL AIL_set_stream_loop_block (HSTREAM S, - S32 loop_start_offset, - S32 loop_end_offset); - -DXDEC S32 AILCALL AIL_stream_status(HSTREAM stream); - -DXDEC void AILCALL AIL_set_stream_position(HSTREAM stream,S32 offset); - -DXDEC S32 AILCALL AIL_stream_position(HSTREAM stream); - -DXDEC void AILCALL AIL_stream_info(HSTREAM stream, S32 FAR* datarate, S32 FAR* sndtype, S32 FAR* length, S32 FAR* memory); - -DXDEC AILSTREAMCB AILCALL AIL_register_stream_callback(HSTREAM stream, AILSTREAMCB callback); - -DXDEC void AILCALL AIL_auto_service_stream(HSTREAM stream, S32 onoff); - -DXDEC void AILCALL AIL_set_stream_user_data (HSTREAM S, - U32 index, - S32 value); - -DXDEC S32 AILCALL AIL_stream_user_data (HSTREAM S, - U32 index); - -DXDEC void AILCALL AIL_set_stream_ms_position (HSTREAM S, - S32 milliseconds); - -DXDEC void AILCALL AIL_stream_ms_position (HSTREAM S, //) - S32 FAR * total_milliseconds, - S32 FAR * current_milliseconds); - -DXDEC void AILCALL AIL_set_stream_reverb(HSTREAM S, - F32 reverb_level, - F32 reverb_reflect_time, - F32 reverb_decay_time); - -DXDEC void AILCALL AIL_stream_reverb (HSTREAM S, - F32 FAR *reverb_level, - F32 FAR *reverb_reflect_time, - F32 FAR *reverb_decay_time); - -DXDEC HPROVIDER AILCALL AIL_set_stream_processor (HSTREAM S, - SAMPLESTAGE pipeline_stage, - HPROVIDER provider); - -#ifdef IS_MAC -typedef struct MSS_FILE -{ - S32 file_type; // 0 = char*, 1 = FSSpec* - void const FAR* file; -} MSS_FILE; -#else -typedef char MSS_FILE; -#endif - -typedef U32 (AILCALLBACK FAR*AIL_file_open_callback) (MSS_FILE const FAR* Filename, - U32 FAR* FileHandle); - -typedef void (AILCALLBACK FAR*AIL_file_close_callback) (U32 FileHandle); - -#define AIL_FILE_SEEK_BEGIN 0 -#define AIL_FILE_SEEK_CURRENT 1 -#define AIL_FILE_SEEK_END 2 - -typedef S32 (AILCALLBACK FAR*AIL_file_seek_callback) (U32 FileHandle, - S32 Offset, - U32 Type); - -typedef U32 (AILCALLBACK FAR*AIL_file_read_callback) (U32 FileHandle, - void FAR* Buffer, - U32 Bytes); - -DXDEC void AILCALL AIL_set_file_callbacks (AIL_file_open_callback opencb, - AIL_file_close_callback closecb, - AIL_file_seek_callback seekcb, - AIL_file_read_callback readcb); - -#ifdef IS_32 - -typedef void FAR* (AILCALLBACK FAR*AIL_file_async_read_callback) (U32 FileHandle, - void FAR* Buffer, - U32 Bytes); - -typedef S32 (AILCALLBACK FAR*AIL_file_async_status_callback) (void FAR* async, - S32 wait, - U32 FAR* BytesRead); - -DXDEC void AILCALL AIL_set_file_async_callbacks (AIL_file_open_callback opencb, - AIL_file_close_callback closecb, - AIL_file_seek_callback seekcb, - AIL_file_async_read_callback areadcb, - AIL_file_async_status_callback statuscb); - -#endif - -// -// High-level DLS functions -// - -typedef struct _DLSFILEID { - S32 id; - struct _DLSFILEID FAR* next; -} DLSFILEID; - -typedef struct _DLSFILEID FAR* HDLSFILEID; - -typedef struct _DLSDEVICE { - void FAR* pGetPref; - void FAR* pSetPref; - void FAR* pMSSOpen; - void FAR* pOpen; - void FAR* pClose; - void FAR* pLoadFile; - void FAR* pLoadMem; - void FAR* pUnloadFile; - void FAR* pUnloadAll; - void FAR* pGetInfo; - void FAR* pCompact; - void FAR* pSetAttr; - S32 DLSHandle; - U32 format; - U32 buffer_size; - void FAR* buffer[2]; - HSAMPLE sample; - HMDIDRIVER mdi; - HDIGDRIVER dig; - HDLSFILEID first; -#ifdef IS_WINDOWS - HMODULE lib; -#else - #ifdef IS_DOS - char FAR* DOSname; - #endif -#endif -} DLSDEVICE; - -typedef struct _DLSDEVICE FAR* HDLSDEVICE; - -typedef struct _AILDLSINFO { - char Description[128]; - S32 MaxDLSMemory; - S32 CurrentDLSMemory; - S32 LargestSize; - S32 GMAvailable; - S32 GMBankSize; -} AILDLSINFO; - -#ifdef IS_DOS - -typedef struct _AILDOSDLS { - char FAR* description; - void FAR* pDLSOpen; - void FAR* pMSSOpen; - void FAR* pOpen; - void FAR* pClose; - void FAR* pLoadFile; - void FAR* pLoadMem; - void FAR* pUnloadFile; - void FAR* pUnloadAll; - void FAR* pGetInfo; - void FAR* pCompact; - void FAR* pSetAttr; -} AILDOSDLS; - -#endif - - -DXDEC HDLSDEVICE AILCALL AIL_DLS_open(HMDIDRIVER mdi, HDIGDRIVER dig, -#if defined(IS_WINDOWS) || defined(IS_MAC) - char const FAR * libname, -#else - AILDOSDLS const FAR * dosdls, -#endif - U32 flags, U32 rate, S32 bits, S32 channels); - -// -// Parameters for the dwFlag used in DLSClose() and flags in AIL_DLS_close -// - -#define RETAIN_DLS_COLLECTION 0x00000001 -#define RETURN_TO_BOOTUP_STATE 0x00000002 -#define RETURN_TO_GM_ONLY_STATE 0x00000004 -#define DLS_COMPACT_MEMORY 0x00000008 - -DXDEC void AILCALL AIL_DLS_close(HDLSDEVICE dls, U32 flags); - -DXDEC HDLSFILEID AILCALL AIL_DLS_load_file(HDLSDEVICE dls, char const FAR* filename, U32 flags); - -DXDEC HDLSFILEID AILCALL AIL_DLS_load_memory(HDLSDEVICE dls, void const FAR* memfile, U32 flags); - -// -// other parameters for AIL_DLS_unload -// - -#define AIL_DLS_UNLOAD_MINE 0 -#define AIL_DLS_UNLOAD_ALL ((HDLSFILEID)(U32)(S32)-1) - -DXDEC void AILCALL AIL_DLS_unload(HDLSDEVICE dls, HDLSFILEID dlsid); - -DXDEC void AILCALL AIL_DLS_compact(HDLSDEVICE dls); - -DXDEC void AILCALL AIL_DLS_get_info(HDLSDEVICE dls, AILDLSINFO FAR* info, S32 FAR* PercentCPU); - -DXDEC void AILCALL AIL_DLS_set_reverb(HDLSDEVICE dls, - F32 reverb_level, - F32 reverb_reflect_time, - F32 reverb_decay_time); - -DXDEC void AILCALL AIL_DLS_get_reverb(HDLSDEVICE dls, - F32 FAR* reverb_level, - F32 FAR* reverb_reflect_time, - F32 FAR* reverb_decay_time); - -DXDEC HPROVIDER AILCALL AIL_set_DLS_processor (HDLSDEVICE dev, - SAMPLESTAGE pipeline_stage, - HPROVIDER provider); - - -// -// Quick-integration service functions and data types -// - -typedef struct -{ - U32 const FAR *data; - S32 size; - S32 type; - void FAR *handle; - S32 status; - void FAR* next; - S32 speed; - S32 volume; - S32 extravol; - F32 rlevel; - F32 rrtime; - F32 rdtime; - HDLSFILEID dlsid; - void FAR* dlsmem; - void FAR* dlsmemunc; - S32 milliseconds; - S32 length; - S32 userdata; -} -AUDIO_TYPE; - - -#define QSTAT_DONE 1 // Data has finished playing -#define QSTAT_LOADED 2 // Data has been loaded, but not yet played -#define QSTAT_PLAYING 3 // Data is currently playing - -typedef AUDIO_TYPE FAR * HAUDIO; // Generic handle to any audio data type - -#define AIL_QUICK_USE_WAVEOUT 2 -#define AIL_QUICK_MIDI_AND_DLS 2 -#define AIL_QUICK_DLS_ONLY 3 -#define AIL_QUICK_MIDI_AND_VORTEX_DLS 4 -#define AIL_QUICK_MIDI_AND_SONICVIBES_DLS 5 - -DXDEC S32 AILCALL -#if defined(IS_WINDOWS) || defined(IS_MAC) - AIL_quick_startup ( -#else - AIL_quick_startup_with_start(void* startup, -#endif - S32 use_digital, - S32 use_MIDI, - U32 output_rate, - S32 output_bits, - S32 output_channels); - -DXDEC void AILCALL AIL_quick_shutdown (void); - -DXDEC void AILCALL AIL_quick_handles (HDIGDRIVER FAR* pdig, - HMDIDRIVER FAR* pmdi, - HDLSDEVICE FAR* pdls ); - -DXDEC HAUDIO AILCALL AIL_quick_load (char const FAR *filename); - -#ifdef IS_MAC -DXDEC HAUDIO AILCALL AIL_quick_fss_load (FSSpec const FAR *filename); -#endif - -DXDEC HAUDIO AILCALL AIL_quick_load_mem (void const FAR *mem, - U32 size); - -DXDEC HAUDIO AILCALL AIL_quick_copy (HAUDIO audio); - -DXDEC void AILCALL AIL_quick_unload (HAUDIO audio); - -DXDEC S32 AILCALL AIL_quick_play (HAUDIO audio, - U32 loop_count); - -DXDEC void AILCALL AIL_quick_halt (HAUDIO audio); - -DXDEC S32 AILCALL AIL_quick_status (HAUDIO audio); - -DXDEC HAUDIO AILCALL AIL_quick_load_and_play (char const FAR *filename, - U32 loop_count, - S32 wait_request); - -#ifdef IS_MAC -DXDEC HAUDIO AILCALL AIL_quick_fss_load_and_play (FSSpec const FAR *filename, - U32 loop_count, - S32 wait_request); -#endif - -DXDEC void AILCALL AIL_quick_set_speed (HAUDIO audio, S32 speed); - -DXDEC void AILCALL AIL_quick_set_volume (HAUDIO audio, S32 volume, S32 extravol); - -DXDEC void AILCALL AIL_quick_set_reverb (HAUDIO audio, - F32 reverb_level, - F32 reverb_reflect_time, - F32 reverb_decay_time); - -DXDEC void AILCALL AIL_quick_set_ms_position(HAUDIO audio,S32 milliseconds); - -DXDEC S32 AILCALL AIL_quick_ms_position(HAUDIO audio); - -DXDEC S32 AILCALL AIL_quick_ms_length(HAUDIO audio); - - -#define AIL_QUICK_XMIDI_TYPE 1 -#define AIL_QUICK_DIGITAL_TYPE 2 -#define AIL_QUICK_DLS_XMIDI_TYPE 3 -#define AIL_QUICK_MPEG_DIGITAL_TYPE 4 - -DXDEC S32 AILCALL AIL_quick_type(HAUDIO audio); - -// -// used for AIL_process -// - -typedef struct _AILMIXINFO { - AILSOUNDINFO Info; - ADPCMDATA mss_adpcm; - U32 src_fract; - S32 left_val; - S32 right_val; -} AILMIXINFO; - - - -DXDEC S32 AILCALL AIL_WAV_info(void const FAR* data, AILSOUNDINFO FAR* info); - -DXDEC S32 AILCALL AIL_size_processed_digital_audio( - U32 dest_rate, - U32 dest_format, - S32 num_srcs, - AILMIXINFO const FAR* src); - -DXDEC S32 AILCALL AIL_process_digital_audio( - void FAR *dest_buffer, - S32 dest_buffer_size, - U32 dest_rate, - U32 dest_format, - S32 num_srcs, - AILMIXINFO FAR* src); - -#define AIL_LENGTHY_INIT 0 -#define AIL_LENGTHY_SET_PREFERENCE 1 -#define AIL_LENGTHY_UPDATE 2 -#define AIL_LENGTHY_DONE 3 - -typedef S32 (AILCALLBACK FAR* AILLENGTHYCB)(U32 state,U32 user); - -typedef S32 (AILCALLBACK FAR* AILCODECSETPREF)(char const FAR* preference,U32 value); - -DXDEC S32 AILCALL AIL_compress_ASI(AILSOUNDINFO const FAR * info, //) - char const FAR* filename_ext, - void FAR* FAR* outdata, - U32 FAR* outsize, - AILLENGTHYCB callback); - -DXDEC S32 AILCALL AIL_decompress_ASI(void const FAR* indata, //) - U32 insize, - char const FAR* filename_ext, - void FAR* FAR* wav, - U32 FAR* wavsize, - AILLENGTHYCB callback); - -DXDEC S32 AILCALL AIL_compress_ADPCM(AILSOUNDINFO const FAR * info, - void FAR* FAR* outdata, U32 FAR* outsize); - -DXDEC S32 AILCALL AIL_decompress_ADPCM(AILSOUNDINFO const FAR * info, - void FAR* FAR* outdata, U32 FAR* outsize); - -DXDEC S32 AILCALL AIL_compress_DLS(void const FAR* dls, - char const FAR* compression_extension, - void FAR* FAR* mls, U32 FAR* mlssize, - AILLENGTHYCB callback); - -DXDEC S32 AILCALL AIL_merge_DLS_with_XMI(void const FAR* xmi, void const FAR* dls, - void FAR* FAR* mss, U32 FAR* msssize); - -DXDEC S32 AILCALL AIL_extract_DLS( void const FAR *source_image, //) - U32 source_size, - void FAR * FAR *XMI_output_data, - U32 FAR *XMI_output_size, - void FAR * FAR *DLS_output_data, - U32 FAR *DLS_output_size, - AILLENGTHYCB callback); - -#define AILFILTERDLS_USINGLIST 1 - -DXDEC S32 AILCALL AIL_filter_DLS_with_XMI(void const FAR* xmi, void const FAR* dls, - void FAR* FAR* dlsout, U32 FAR* dlssize, - S32 flags, AILLENGTHYCB callback); - -#define AILMIDITOXMI_USINGLIST 1 -#define AILMIDITOXMI_TOLERANT 2 - -DXDEC S32 AILCALL AIL_MIDI_to_XMI (void const FAR* MIDI, - U32 MIDI_size, - void FAR* FAR*XMIDI, - U32 FAR* XMIDI_size, - S32 flags); - -#define AILMIDILIST_ROLANDSYSEX 1 -#define AILMIDILIST_ROLANDUN 2 -#define AILMIDILIST_ROLANDAB 4 - -DXDEC S32 AILCALL AIL_list_MIDI (void const FAR* MIDI, - U32 MIDI_size, - char FAR* FAR* lst, - U32 FAR* lst_size, - S32 flags); -#define AILDLSLIST_ARTICULATION 1 -#define AILDLSLIST_DUMP_WAVS 2 - -DXDEC S32 AILCALL AIL_list_DLS (void const FAR* DLS, - char FAR* FAR* lst, - U32 FAR* lst_size, - S32 flags, - C8 FAR* title); - -#define AILFILETYPE_UNKNOWN 0 -#define AILFILETYPE_PCM_WAV 1 -#define AILFILETYPE_ADPCM_WAV 2 -#define AILFILETYPE_OTHER_WAV 3 -#define AILFILETYPE_VOC 4 -#define AILFILETYPE_MIDI 5 -#define AILFILETYPE_XMIDI 6 -#define AILFILETYPE_XMIDI_DLS 7 -#define AILFILETYPE_XMIDI_MLS 8 -#define AILFILETYPE_DLS 9 -#define AILFILETYPE_MLS 10 -#define AILFILETYPE_MPEG_L1_AUDIO 11 -#define AILFILETYPE_MPEG_L2_AUDIO 12 -#define AILFILETYPE_MPEG_L3_AUDIO 13 -#define AILFILETYPE_OTHER_ASI_WAV 14 - - -DXDEC S32 AILCALL AIL_file_type(void const FAR* data, U32 size); - -DXDEC S32 AILCALL AIL_find_DLS (void const FAR* data, U32 size, - void FAR* FAR* xmi, U32 FAR* xmisize, - void FAR* FAR* dls, U32 FAR* dlssize); - -#if defined(IS_WIN32) || defined(IS_MAC) - -// -// Auxiliary 2D interface calls -// - -DXDEC HDIGDRIVER AILCALL AIL_primary_digital_driver (HDIGDRIVER new_primary); - -// -// Filter result codes -// - -typedef S32 FLTRESULT; - -#define FLT_NOERR 0 // Success -- no error -#define FLT_NOT_ENABLED 1 // FLT not enabled -#define FLT_ALREADY_STARTED 2 // FLT already started -#define FLT_INVALID_PARAM 3 // Invalid parameters used -#define FLT_INTERNAL_ERR 4 // Internal error in FLT driver -#define FLT_OUT_OF_MEM 5 // Out of system RAM -#define FLT_ERR_NOT_IMPLEMENTED 6 // Feature not implemented -#define FLT_NOT_FOUND 7 // FLT supported device not found -#define FLT_NOT_INIT 8 // FLT not initialized -#define FLT_CLOSE_ERR 9 // FLT not closed correctly - -//############################################################################ -//## ## -//## Interface "MSS pipeline filter" ## -//## ## -//############################################################################ - -typedef FLTRESULT (AILCALL FAR *FLT_STARTUP)(void); - -typedef FLTRESULT (AILCALL FAR *FLT_SHUTDOWN)(void); - -typedef C8 FAR * (AILCALL FAR *FLT_ERROR)(void); - -typedef S32 (AILCALL FAR *FLT_SET_PROVIDER_PREFERENCE)(HATTRIB preference, - void const FAR* value); - -typedef HDRIVERSTATE (AILCALL FAR *FLT_OPEN_DRIVER) (HDIGDRIVER dig, - S32 FAR *build_buffer, - S32 build_buffer_size); - -typedef FLTRESULT (AILCALL FAR *FLT_CLOSE_DRIVER) (HDRIVERSTATE state); - -typedef void (AILCALL FAR *FLT_PREMIX_PROCESS) (HDRIVERSTATE driver -#ifdef IS_MAC - ,U32 buffer_size -#endif -); - -typedef void (AILCALL FAR *FLT_POSTMIX_PROCESS) (HDRIVERSTATE driver -#ifdef IS_MAC - ,U32 buffer_size -#endif -); - -//############################################################################ -//## ## -//## Interface "Pipeline filter sample services" ## -//## ## -//############################################################################ - -typedef HSAMPLESTATE (AILCALL FAR * FLTSMP_OPEN_SAMPLE) (HDRIVERSTATE driver, - HSAMPLE S); - -typedef FLTRESULT (AILCALL FAR * FLTSMP_CLOSE_SAMPLE) (HSAMPLESTATE state); - -typedef S32 (AILCALL FAR * FLTSMP_SAMPLE_PROCESS) (HSAMPLESTATE state, - void const FAR * FAR *orig_src, - U32 FAR * orig_src_fract, - void FAR * orig_src_end, - S32 FAR * FAR *build_dest, - void FAR * build_dest_end, - S32 FAR * left_val, - S32 FAR * right_val, - S32 playback_ratio, - S32 left_scale, - S32 right_scale, - S32 base_scale, - MIXSTAGE FAR * mixer_provider, - U32 mixer_operation); - -typedef S32 (AILCALL FAR * FLTSMP_SAMPLE_ATTRIBUTE) (HSAMPLESTATE state, - HATTRIB attribute); - -typedef S32 (AILCALL FAR * FLTSMP_SET_SAMPLE_PREFERENCE) (HSAMPLESTATE state, - HATTRIB preference, - void const FAR* value); - -// -// Pipeline filter calls -// - -DXDEC S32 AILCALL AIL_enumerate_filters (HPROENUM FAR *next, - HPROVIDER FAR *dest, - C8 FAR * FAR *name); - -DXDEC HDRIVERSTATE - AILCALL AIL_open_filter (HPROVIDER lib, - HDIGDRIVER dig); - -DXDEC void AILCALL AIL_close_filter (HDRIVERSTATE filter); - -DXDEC S32 AILCALL AIL_enumerate_filter_attributes - (HPROVIDER lib, - HINTENUM FAR * next, - RIB_INTERFACE_ENTRY FAR * dest); - -DXDEC void AILCALL AIL_filter_attribute (HPROVIDER lib, - C8 const FAR* name, - void FAR * val); - -DXDEC void AILCALL AIL_set_filter_preference - (HPROVIDER lib, - C8 const FAR* name, - void const FAR* val); - -DXDEC S32 AILCALL AIL_enumerate_filter_sample_attributes - (HPROVIDER lib, - HINTENUM FAR * next, - RIB_INTERFACE_ENTRY FAR * dest); - -DXDEC void AILCALL AIL_filter_sample_attribute - (HSAMPLE S, - C8 const FAR* name, - void FAR * val); - -DXDEC void AILCALL AIL_filter_stream_attribute - (HSTREAM S, - C8 const FAR* name, - void FAR* val); - -DXDEC void AILCALL AIL_filter_DLS_attribute - (HDLSDEVICE dls, - C8 const FAR* name, - void FAR * val); - -DXDEC void AILCALL AIL_set_filter_sample_preference - (HSAMPLE S, - C8 const FAR * name, - void const FAR * val); - -DXDEC void AILCALL AIL_set_filter_stream_preference - (HSTREAM S, - C8 const FAR * name, - void const FAR * val); - -DXDEC void AILCALL AIL_set_filter_DLS_preference - (HDLSDEVICE dls, - C8 const FAR * name, - void const FAR * val); - -typedef struct _FLTPROVIDER -{ - PROVIDER_QUERY_ATTRIBUTE PROVIDER_query_attribute; - - FLT_STARTUP startup; - FLT_ERROR error; - FLT_SHUTDOWN shutdown; - FLT_SET_PROVIDER_PREFERENCE set_provider_preference; - FLT_OPEN_DRIVER open_driver; - FLT_CLOSE_DRIVER close_driver; - FLT_PREMIX_PROCESS premix_process; - FLT_POSTMIX_PROCESS postmix_process; - - FLTSMP_OPEN_SAMPLE open_sample; - FLTSMP_CLOSE_SAMPLE close_sample; - FLTSMP_SAMPLE_PROCESS sample_process; - FLTSMP_SAMPLE_ATTRIBUTE sample_attribute; - FLTSMP_SET_SAMPLE_PREFERENCE set_sample_preference; - - HDIGDRIVER dig; - HPROVIDER provider; - HDRIVERSTATE driver_state; - - struct _FLTPROVIDER FAR *next; -} -FLTPROVIDER; - -// -// 3D provider calls -// - -DXDEC S32 AILCALL AIL_enumerate_3D_providers (HPROENUM FAR *next, - HPROVIDER FAR *dest, - C8 FAR * FAR *name); - -DXDEC M3DRESULT AILCALL AIL_open_3D_provider (HPROVIDER lib); - -DXDEC void AILCALL AIL_close_3D_provider (HPROVIDER lib); - -DXDEC S32 AILCALL AIL_enumerate_3D_provider_attributes - (HPROVIDER lib, - HINTENUM FAR * next, - RIB_INTERFACE_ENTRY FAR * dest); - -DXDEC void AILCALL AIL_3D_provider_attribute (HPROVIDER lib, - C8 const FAR* name, - void FAR * val); - -DXDEC void AILCALL AIL_set_3D_provider_preference(HPROVIDER lib, - C8 const FAR* name, - void const FAR* val); - -struct H3D -{ - H3DPOBJECT actual; - HPROVIDER owner; - S32 user_data[8]; -}; - -typedef struct _M3DPROVIDER -{ - PROVIDER_QUERY_ATTRIBUTE PROVIDER_query_attribute; - M3D_STARTUP startup; - M3D_ERROR error; - M3D_SHUTDOWN shutdown; - M3D_SET_PROVIDER_PREFERENCE set_provider_preference; - M3D_ACTIVATE activate; - M3D_ALLOCATE_3D_SAMPLE_HANDLE allocate_3D_sample_handle; - M3D_RELEASE_3D_SAMPLE_HANDLE release_3D_sample_handle; - M3D_START_3D_SAMPLE start_3D_sample; - M3D_STOP_3D_SAMPLE stop_3D_sample; - M3D_RESUME_3D_SAMPLE resume_3D_sample; - M3D_END_3D_SAMPLE end_3D_sample; - M3D_SET_3D_SAMPLE_DATA set_3D_sample_data; - M3D_SET_3D_SAMPLE_VOLUME set_3D_sample_volume; - M3D_SET_3D_SAMPLE_PLAYBACK_RATE set_3D_sample_playback_rate; - M3D_SET_3D_SAMPLE_OFFSET set_3D_sample_offset; - M3D_SET_3D_SAMPLE_LOOP_COUNT set_3D_sample_loop_count; - M3D_SET_3D_SAMPLE_LOOP_BLOCK set_3D_sample_loop_block; - M3D_3D_SAMPLE_STATUS sample_status; - M3D_3D_SAMPLE_VOLUME sample_volume; - M3D_3D_SAMPLE_PLAYBACK_RATE sample_playback_rate; - M3D_3D_SAMPLE_OFFSET sample_offset; - M3D_3D_SAMPLE_LENGTH sample_length; - M3D_3D_SAMPLE_LOOP_COUNT sample_loop_count; - M3D_SET_3D_SAMPLE_DISTANCES set_3D_sample_distances; - M3D_3D_SAMPLE_DISTANCES sample_distances; - M3D_ACTIVE_3D_SAMPLE_COUNT active_3D_sample_count; - M3D_3D_OPEN_LISTENER open_listener; - M3D_3D_CLOSE_LISTENER close_listener; - M3D_3D_OPEN_OBJECT open_object; - M3D_3D_CLOSE_OBJECT close_object; - M3D_SET_3D_POSITION set_3D_position; - M3D_SET_3D_VELOCITY set_3D_velocity; - M3D_SET_3D_VELOCITY_VECTOR set_3D_velocity_vector; - M3D_SET_3D_ORIENTATION set_3D_orientation; - M3D_3D_POSITION position; - M3D_3D_VELOCITY velocity; - M3D_3D_ORIENTATION orientation; - M3D_3D_UPDATE_POSITION update_position; - M3D_3D_AUTO_UPDATE_POSITION auto_update_position; - M3D_3D_SAMPLE_ATTRIBUTE sample_query_attribute; - M3D_3D_SET_SAMPLE_PREFERENCE set_sample_preference; - M3D_3D_ROOM_TYPE room_type; - M3D_SET_3D_ROOM_TYPE set_3D_room_type; - M3D_3D_SPEAKER_TYPE speaker_type; - M3D_SET_3D_SPEAKER_TYPE set_3D_speaker_type; - M3D_SET_3D_SAMPLE_OBSTRUCTION set_3D_sample_obstruction; - M3D_SET_3D_SAMPLE_OCCLUSION set_3D_sample_occlusion; - M3D_SET_3D_SAMPLE_CONE set_3D_sample_cone; - M3D_SET_3D_SAMPLE_EFFECTS_LEVEL set_3D_sample_effects_level; - M3D_3D_SAMPLE_OBSTRUCTION sample_obstruction; - M3D_3D_SAMPLE_OCCLUSION sample_occlusion; - M3D_3D_SAMPLE_CONE sample_cone; - M3D_3D_SAMPLE_EFFECTS_LEVEL sample_effects_level; - M3D_SET_3D_EOS set_3D_EOS; -} M3DPROVIDER; - -// -// Sample calls -// - -DXDEC H3DSAMPLE AILCALL AIL_allocate_3D_sample_handle - (HPROVIDER lib); - - -DXDEC void AILCALL AIL_release_3D_sample_handle - (H3DSAMPLE S); - - -DXDEC void AILCALL AIL_start_3D_sample (H3DSAMPLE S); - - -DXDEC void AILCALL AIL_stop_3D_sample (H3DSAMPLE S); - - -DXDEC void AILCALL AIL_resume_3D_sample (H3DSAMPLE S); - -DXDEC void AILCALL AIL_end_3D_sample (H3DSAMPLE S); - -DXDEC S32 AILCALL AIL_set_3D_sample_file (H3DSAMPLE S, - void const FAR*file_image); - -DXDEC S32 AILCALL AIL_set_3D_sample_info (H3DSAMPLE S, - AILSOUNDINFO const FAR*info); - -DXDEC void AILCALL AIL_set_3D_sample_volume (H3DSAMPLE S, - S32 volume); - -DXDEC void AILCALL AIL_set_3D_sample_offset (H3DSAMPLE S, - U32 offset); - -DXDEC void AILCALL AIL_set_3D_sample_playback_rate - (H3DSAMPLE S, - S32 playback_rate); - -DXDEC void AILCALL AIL_set_3D_sample_loop_count(H3DSAMPLE S, - U32 loops); - -DXDEC void AILCALL AIL_set_3D_sample_loop_block(H3DSAMPLE S, - S32 loop_start_offset, - S32 loop_end_offset); - -DXDEC U32 AILCALL AIL_3D_sample_status (H3DSAMPLE S); - -DXDEC S32 AILCALL AIL_3D_sample_volume (H3DSAMPLE S); - -DXDEC U32 AILCALL AIL_3D_sample_offset (H3DSAMPLE S); - -DXDEC S32 AILCALL AIL_3D_sample_playback_rate (H3DSAMPLE S); - -DXDEC U32 AILCALL AIL_3D_sample_length (H3DSAMPLE S); - -DXDEC U32 AILCALL AIL_3D_sample_loop_count (H3DSAMPLE S); - - -DXDEC S32 AILCALL AIL_3D_room_type (HPROVIDER lib); - -DXDEC void AILCALL AIL_set_3D_room_type (HPROVIDER lib, - S32 room_type); - -#define AIL_3D_2_SPEAKER 0 -#define AIL_3D_HEADPHONE 1 -#define AIL_3D_SURROUND 2 -#define AIL_3D_4_SPEAKER 3 - - -DXDEC S32 AILCALL AIL_3D_speaker_type (HPROVIDER lib); - -DXDEC void AILCALL AIL_set_3D_speaker_type (HPROVIDER lib, - S32 speaker_type); - - -// -// Changed the definition of distances to only be max and min, vs. front -// min/max and back min/max. Only RSX supported the concept of different -// front and distances, so we changed the API to make it more orthogonal -// to most of the 3D providers. Sorry in advance. -// - -DXDEC void AILCALL AIL_set_3D_sample_distances (H3DSAMPLE S, - F32 max_dist, - F32 min_dist); - - -DXDEC void AILCALL AIL_3D_sample_distances (H3DSAMPLE S, - F32 FAR * max_dist, - F32 FAR * min_dist); - -DXDEC S32 AILCALL AIL_active_3D_sample_count (HPROVIDER lib); - -DXDEC S32 AILCALL AIL_enumerate_3D_sample_attributes - (HPROVIDER lib, - HINTENUM FAR * next, - RIB_INTERFACE_ENTRY FAR * dest); - -DXDEC void AILCALL AIL_3D_sample_attribute (H3DSAMPLE samp, - C8 const FAR* name, - void FAR * val); - - -DXDEC void AILCALL AIL_set_3D_sample_preference (H3DSAMPLE samp, - C8 const FAR* name, - void const FAR* val); - -DXDEC void AILCALL AIL_set_3D_sample_obstruction (H3DSAMPLE S, - F32 obstruction); - -DXDEC void AILCALL AIL_set_3D_sample_occlusion (H3DSAMPLE S, - F32 occlusion); - -DXDEC void AILCALL AIL_set_3D_sample_cone (H3DSAMPLE S, - F32 inner_angle, - F32 outer_angle, - S32 outer_volume); - -DXDEC void AILCALL AIL_set_3D_sample_effects_level - (H3DSAMPLE S, - F32 effects_level); - -DXDEC F32 AILCALL AIL_3D_sample_obstruction (H3DSAMPLE S); - -DXDEC F32 AILCALL AIL_3D_sample_occlusion (H3DSAMPLE S); - -DXDEC void AILCALL AIL_3D_sample_cone (H3DSAMPLE S, - F32 FAR* inner_angle, - F32 FAR* outer_angle, - S32 FAR* outer_volume); - -DXDEC F32 AILCALL AIL_3D_sample_effects_level (H3DSAMPLE S); - - -DXDEC AIL3DSAMPLECB AILCALL AIL_register_3D_EOS_callback - (H3DSAMPLE S, - AIL3DSAMPLECB EOS); - - -// -// Positioning-object allocation calls -// - -DXDEC H3DPOBJECT AILCALL AIL_open_3D_listener (HPROVIDER lib); - -DXDEC void AILCALL AIL_close_3D_listener (H3DPOBJECT listener); - -DXDEC H3DPOBJECT AILCALL AIL_open_3D_object (HPROVIDER lib); - -DXDEC void AILCALL AIL_close_3D_object (H3DPOBJECT obj); - -// -// 3D object calls -// - -DXDEC void AILCALL AIL_set_3D_position (H3DPOBJECT obj, - F32 X, - F32 Y, - F32 Z); - -DXDEC void AILCALL AIL_set_3D_velocity (H3DPOBJECT obj, - F32 dX_per_ms, - F32 dY_per_ms, - F32 dZ_per_ms, - F32 magnitude); - -DXDEC void AILCALL AIL_set_3D_velocity_vector (H3DPOBJECT obj, - F32 dX_per_ms, - F32 dY_per_ms, - F32 dZ_per_ms); - -DXDEC void AILCALL AIL_set_3D_orientation (H3DPOBJECT obj, - F32 X_face, - F32 Y_face, - F32 Z_face, - F32 X_up, - F32 Y_up, - F32 Z_up); - -DXDEC void AILCALL AIL_3D_position (H3DPOBJECT obj, - F32 FAR *X, - F32 FAR *Y, - F32 FAR *Z); - -DXDEC void AILCALL AIL_3D_velocity (H3DPOBJECT obj, - F32 FAR *dX_per_ms, - F32 FAR *dY_per_ms, - F32 FAR *dZ_per_ms); - -DXDEC void AILCALL AIL_3D_orientation (H3DPOBJECT obj, - F32 FAR *X_face, - F32 FAR *Y_face, - F32 FAR *Z_face, - F32 FAR *X_up, - F32 FAR *Y_up, - F32 FAR *Z_up); - -DXDEC void AILCALL AIL_update_3D_position (H3DPOBJECT obj, - F32 dt_milliseconds); - -DXDEC void AILCALL AIL_auto_update_3D_position (H3DPOBJECT obj, - S32 enable); - -DXDEC void AILCALL AIL_set_3D_user_data (H3DPOBJECT obj, - U32 index, - S32 value); - -DXDEC S32 AILCALL AIL_3D_user_data (H3DPOBJECT obj, - U32 index); - -// Obsolete 3D function names: -#define AIL_set_3D_object_user_data AIL_set_3D_user_data -#define AIL_3D_object_user_data AIL_3D_user_data -#define AIL_3D_open_listener AIL_open_3D_listener -#define AIL_3D_close_listener AIL_close_3D_listener -#define AIL_3D_open_object AIL_open_3D_object -#define AIL_3D_close_object AIL_close_3D_object - -// -// RAD room types - currently the same as EAX -// - -enum -{ - ENVIRONMENT_GENERIC, // factory default - ENVIRONMENT_PADDEDCELL, - ENVIRONMENT_ROOM, // standard environments - ENVIRONMENT_BATHROOM, - ENVIRONMENT_LIVINGROOM, - ENVIRONMENT_STONEROOM, - ENVIRONMENT_AUDITORIUM, - ENVIRONMENT_CONCERTHALL, - ENVIRONMENT_CAVE, - ENVIRONMENT_ARENA, - ENVIRONMENT_HANGAR, - ENVIRONMENT_CARPETEDHALLWAY, - ENVIRONMENT_HALLWAY, - ENVIRONMENT_STONECORRIDOR, - ENVIRONMENT_ALLEY, - ENVIRONMENT_FOREST, - ENVIRONMENT_CITY, - ENVIRONMENT_MOUNTAINS, - ENVIRONMENT_QUARRY, - ENVIRONMENT_PLAIN, - ENVIRONMENT_PARKINGLOT, - ENVIRONMENT_SEWERPIPE, - ENVIRONMENT_UNDERWATER, - ENVIRONMENT_DRUGGED, - ENVIRONMENT_DIZZY, - ENVIRONMENT_PSYCHOTIC, - - ENVIRONMENT_COUNT // total number of environments -}; - -// -// enumerated values for EAX -// - -#ifndef EAX_H_INCLUDED - -enum -{ - EAX_ENVIRONMENT_GENERIC, // factory default - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, // standard environments - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_COUNT // total number of environments -}; - -#define EAX_REVERBMIX_USEDISTANCE (-1.0F) - -#endif - -#else - -typedef struct _FLTPROVIDER -{ - U32 junk; -} FLTPROVIDER; - -#endif - -#ifdef __cplusplus -} -#endif - - -#if defined(_PUSHPOP_SUPPORTED) || PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#else - #pragma pack() -#endif - - -#endif + S32 format; + void const *data_ptr; + U32 data_len; + U32 rate; + S32 bits; + S32 channels; + U32 samples; + U32 block_size; + void const *initial_ptr; +} AILSOUNDINFO; + +#define DLLEXPORT extern "C" __declspec(dllexport) + +DLLEXPORT S32 WINAPI AIL_enumerate_3D_providers(HPROENUM *next, HPROVIDER *dest, C8 **name); +DLLEXPORT void WINAPI AIL_release_3D_sample_handle(H3DSAMPLE S); +DLLEXPORT void WINAPI AIL_close_3D_provider(HPROVIDER lib); +DLLEXPORT void WINAPI AIL_set_3D_provider_preference(HPROVIDER lib, C8 const *name, void const *val); +DLLEXPORT M3DRESULT WINAPI AIL_open_3D_provider(HPROVIDER lib); +DLLEXPORT C8 *WINAPI AIL_last_error(void); +DLLEXPORT S32 WINAPI AIL_3D_room_type(HPROVIDER lib); +DLLEXPORT void WINAPI AIL_set_3D_room_type(HPROVIDER lib, S32 room_type); +DLLEXPORT void WINAPI AIL_3D_provider_attribute(HPROVIDER lib, C8 const *name, void *val); +DLLEXPORT H3DSAMPLE WINAPI AIL_allocate_3D_sample_handle(HPROVIDER lib); +DLLEXPORT void WINAPI AIL_set_3D_sample_effects_level(H3DSAMPLE S, F32 effects_level); +DLLEXPORT void WINAPI AIL_set_3D_speaker_type(HPROVIDER lib, S32 speaker_type); +DLLEXPORT HSTREAM WINAPI AIL_open_stream(HDIGDRIVER dig, C8 const *filename, S32 stream_mem); +DLLEXPORT void WINAPI AIL_stream_ms_position(HSTREAM S, S32 *total_milliseconds, S32 *current_milliseconds); +DLLEXPORT void WINAPI AIL_close_stream(HSTREAM stream); +DLLEXPORT S32 WINAPI AIL_digital_handle_release(HDIGDRIVER drvr); +DLLEXPORT S32 WINAPI AIL_digital_handle_reacquire(HDIGDRIVER drvr); +DLLEXPORT C8 *WINAPI AIL_set_redist_directory(C8 const *dir); +DLLEXPORT S32 WINAPI AIL_startup(void); +DLLEXPORT S32 WINAPI AIL_set_preference(U32 number, S32 value); +DLLEXPORT HDIGDRIVER WINAPI AIL_open_digital_driver(U32 frequency, S32 bits, S32 channel, U32 flags); +DLLEXPORT void *WINAPI AIL_mem_alloc_lock(U32 size); +DLLEXPORT HSAMPLE WINAPI AIL_allocate_sample_handle(HDIGDRIVER dig); +DLLEXPORT void WINAPI AIL_init_sample(HSAMPLE S); +DLLEXPORT void WINAPI AIL_set_sample_type(HSAMPLE S, S32 format, U32 flags); +DLLEXPORT void WINAPI AIL_pause_stream(HSTREAM stream, S32 onoff); +DLLEXPORT void WINAPI AIL_release_sample_handle(HSAMPLE S); +DLLEXPORT void WINAPI AIL_mem_free_lock(void *ptr); +DLLEXPORT void WINAPI AIL_close_digital_driver(HDIGDRIVER dig); +DLLEXPORT void WINAPI AIL_shutdown(void); +DLLEXPORT void WINAPI AIL_set_3D_sample_volume(H3DSAMPLE S, S32 volume); +DLLEXPORT void WINAPI AIL_set_sample_volume(HSAMPLE S, S32 volume); +DLLEXPORT void WINAPI AIL_set_sample_address(HSAMPLE S, void const *start, U32 len); +DLLEXPORT S32 WINAPI AIL_set_3D_sample_info(H3DSAMPLE S, AILSOUNDINFO const *info); +DLLEXPORT void WINAPI AIL_set_3D_position(H3DPOBJECT obj, F32 X, F32 Y, F32 Z); +DLLEXPORT void WINAPI AIL_set_3D_sample_distances(H3DSAMPLE S, F32 max_dist, F32 min_dist); +DLLEXPORT void WINAPI AIL_set_sample_pan(HSAMPLE S, S32 pan); +DLLEXPORT void WINAPI AIL_set_sample_playback_rate(HSAMPLE S, S32 playback_rate); +DLLEXPORT void WINAPI AIL_set_3D_sample_playback_rate(H3DSAMPLE S, S32 playback_rate); +DLLEXPORT void WINAPI AIL_set_sample_loop_block(HSAMPLE S, S32 loop_start_offset, S32 loop_end_offset); +DLLEXPORT void WINAPI AIL_set_3D_sample_loop_block(H3DSAMPLE S, S32 loop_start_offset, S32 loop_end_offset); +DLLEXPORT void WINAPI AIL_set_sample_loop_count(HSAMPLE S, S32 loop_count); +DLLEXPORT void WINAPI AIL_set_3D_sample_loop_count(H3DSAMPLE S, S32 loops); +DLLEXPORT U32 WINAPI AIL_sample_status(HSAMPLE S); +DLLEXPORT U32 WINAPI AIL_3D_sample_status(H3DSAMPLE S); +DLLEXPORT void WINAPI AIL_start_sample(HSAMPLE S); +DLLEXPORT void WINAPI AIL_start_3D_sample(H3DSAMPLE S); +DLLEXPORT void WINAPI AIL_end_sample(HSAMPLE S); +DLLEXPORT void WINAPI AIL_end_3D_sample(H3DSAMPLE S); +DLLEXPORT void WINAPI AIL_set_stream_loop_count(HSTREAM stream, S32 count); +DLLEXPORT S32 WINAPI AIL_service_stream(HSTREAM stream, S32 fillup); +DLLEXPORT void WINAPI AIL_start_stream(HSTREAM stream); +DLLEXPORT void WINAPI AIL_set_stream_ms_position(HSTREAM S, S32 milliseconds); +DLLEXPORT void WINAPI AIL_set_stream_volume(HSTREAM stream, S32 volume); +DLLEXPORT void WINAPI AIL_set_stream_pan(HSTREAM stream, S32 pan); +DLLEXPORT S32 WINAPI AIL_stream_status(HSTREAM stream); diff --git a/milessdk/lib/mss32.lib b/milessdk/lib/mss32.lib index 031fd1bd1fb9a99f565c2db10248ed4ce340d9c5..f97091c75ff9988cd906e5e43e56b538c951a428 100644 GIT binary patch literal 15316 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 i23q>*k*v%nS}`yWsVXGb;q6vX1FOCgZF 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 Date: Tue, 21 Apr 2020 22:52:42 +0300 Subject: [PATCH 102/123] fix RenderExtraPlayerShadows --- src/render/Shadows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index 319cdd3c..f14b6ec1 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -1642,7 +1642,7 @@ CShadows::RenderExtraPlayerShadows(void) int32 nColorStrength; if ( fLightDist < fRadius*0.5f ) - nColorStrength = CTimeCycle::GetLightShadowStrength(); + nColorStrength = (5*CTimeCycle::GetLightShadowStrength()/8); else nColorStrength = int32(CTimeCycle::GetLightShadowStrength() * fMult); From 828dc85be5a7a24bdcf6aaca2eeda1756de63bfd Mon Sep 17 00:00:00 2001 From: Fire_Head Date: Tue, 21 Apr 2020 22:53:55 +0300 Subject: [PATCH 103/123] fix RenderExtraPlayerShadows 2 --- src/render/Shadows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp index f14b6ec1..d5970ebe 100644 --- a/src/render/Shadows.cpp +++ b/src/render/Shadows.cpp @@ -1644,7 +1644,7 @@ CShadows::RenderExtraPlayerShadows(void) if ( fLightDist < fRadius*0.5f ) nColorStrength = (5*CTimeCycle::GetLightShadowStrength()/8); else - nColorStrength = int32(CTimeCycle::GetLightShadowStrength() * fMult); + nColorStrength = int32((5*CTimeCycle::GetLightShadowStrength()/8) * fMult); float fInv = 1.0f / fLightDist; vecLight.x *= fInv; From c80403a2e0aa337968d77f5d4bcc33cdc91eeac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Tue, 21 Apr 2020 13:28:06 +0300 Subject: [PATCH 104/123] Crossplatform work continues --- src/animation/CutsceneMgr.cpp | 3 +- src/audio/sampman.cpp | 1 - src/control/Script.cpp | 1 - src/core/CdStream.cpp | 2 +- src/core/Game.cpp | 2 - src/core/Timer.cpp | 2 +- src/core/re3.cpp | 2 +- src/rw/TexRead.cpp | 3 -- src/save/GenericGameStorage.cpp | 3 +- src/save/PCSave.cpp | 9 ++-- src/skel/crossplatform.cpp | 81 +++++++++++++++++++++++++++++++++ src/skel/crossplatform.h | 65 ++++++++++++++++++++++++++ src/skel/events.cpp | 6 --- src/skel/win/win.cpp | 4 +- src/skel/win/win.h | 11 +++++ 15 files changed, 170 insertions(+), 25 deletions(-) create mode 100644 src/skel/crossplatform.cpp create mode 100644 src/skel/crossplatform.h diff --git a/src/animation/CutsceneMgr.cpp b/src/animation/CutsceneMgr.cpp index 6d9b9755..334fe471 100644 --- a/src/animation/CutsceneMgr.cpp +++ b/src/animation/CutsceneMgr.cpp @@ -1,4 +1,3 @@ -#define WITHWINDOWS // just for VK_SPACE #include "common.h" #include "General.h" @@ -416,7 +415,7 @@ CCutsceneMgr::Update(void) || (CGame::playingIntro && CPad::GetPad(0)->GetStartJustDown()) || CPad::GetPad(0)->GetLeftMouseJustDown() || CPad::GetPad(0)->GetEnterJustDown() - || CPad::GetPad(0)->GetCharJustDown(VK_SPACE)) + || CPad::GetPad(0)->GetCharJustDown(' ')) FinishCutscene(); } } diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index a375b847..43d3835d 100644 --- a/src/audio/sampman.cpp +++ b/src/audio/sampman.cpp @@ -11,7 +11,6 @@ #include "sampman.h" #include "AudioManager.h" #include "MusicManager.h" -#include "Frontend.h" #include "Timer.h" diff --git a/src/control/Script.cpp b/src/control/Script.cpp index ca676f52..073cb661 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1,7 +1,6 @@ #define WITHWINDOWS // for our script loading hack #include "common.h" - #include "Script.h" #include "ScriptCommands.h" diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp index 1ab1c8b0..ea79fb9a 100644 --- a/src/core/CdStream.cpp +++ b/src/core/CdStream.cpp @@ -1,4 +1,4 @@ -#include +#define WITHWINDOWS #include "common.h" #include "CdStream.h" diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 6f3eee29..bfe6eee3 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -1,7 +1,5 @@ #pragma warning( push ) #pragma warning( disable : 4005) -#define DIRECTINPUT_VERSION 0x0800 -#include #pragma warning( pop ) #include "common.h" #include "win.h" diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index 8f8570d7..aca7c1dc 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -1,4 +1,4 @@ -#include +#define WITHWINDOWS #include "common.h" #include "DMAudio.h" diff --git a/src/core/re3.cpp b/src/core/re3.cpp index e5f42696..0c96b262 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -1,6 +1,6 @@ #include #include -#include +#define WITHWINDOWS #include "common.h" #include "patcher.h" #include "Renderer.h" diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 258d520d..d1ff3dc0 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -1,9 +1,6 @@ #pragma warning( push ) #pragma warning( disable : 4005) -#define DIRECTINPUT_VERSION 0x0800 -#include #pragma warning( pop ) -#define WITHWINDOWS #include "common.h" #include "win.h" diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 5e483dc7..29f666df 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -1,5 +1,6 @@ -#define WITHWINDOWS #include "common.h" +#define USEALTERNATIVEWINFUNCS +#include "crossplatform.h" #include "main.h" #include "AudioScriptObject.h" diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 46185850..6f1b1b45 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -1,5 +1,6 @@ -#define WITHWINDOWS #include "common.h" +#define USEALTERNATIVEWINFUNCS +#include "crossplatform.h" #include "FileMgr.h" #include "GenericGameStorage.h" @@ -94,7 +95,7 @@ C_PcSave::PopulateSlotInfo() struct { int size; wchar FileName[24]; - _SYSTEMTIME SaveDateTime; + SYSTEMTIME SaveDateTime; } header; sprintf(savename, "%s%i%s", DefaultPCSaveFileName, i + 1, ".b"); int file = CFileMgr::OpenFile(savename, "rb"); @@ -110,8 +111,8 @@ C_PcSave::PopulateSlotInfo() } if (Slots[i + 1] == SLOT_OK) { if (CheckDataNotCorrupt(i, savename)) { - _SYSTEMTIME st; - memcpy(&st, &header.SaveDateTime, sizeof(_SYSTEMTIME)); + SYSTEMTIME st; + memcpy(&st, &header.SaveDateTime, sizeof(SYSTEMTIME)); const char *month; switch (st.wMonth) { diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp new file mode 100644 index 00000000..f9464bb6 --- /dev/null +++ b/src/skel/crossplatform.cpp @@ -0,0 +1,81 @@ +#include "common.h" +#define USEALTERNATIVEWINFUNCS +#include "crossplatform.h" + +// For internal use +// wMilliseconds is not needed +void tmToSystemTime(const tm *tm, SYSTEMTIME *out) { + out->wYear = tm->tm_year + 1900; + out->wMonth = tm->tm_mon + 1; + out->wDayOfWeek = tm->tm_wday; + out->wDay = tm->tm_mday; + out->wHour = tm->tm_hour; + out->wMinute = tm->tm_min; + out->wSecond = tm->tm_sec; +} + +void GetLocalTime_CP(SYSTEMTIME *out) { + time_t timestamp = time(nil); + tm *localTm = localtime(×tamp); + tmToSystemTime(localTm, out); +} + +#if !defined _WIN32 || defined __MINGW32__ +HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) { + char newpathname[32]; + strncpy(newpathname, pathname, 32); + char* path = strtok(newpathname, "\\*"); + strncpy(firstfile->folder, path, sizeof(firstfile->folder)); + + // Both w/ extension and w/o extension is ok + if (strlen(path) + 2 != strlen(pathname)) + strncpy(firstfile->extension, strtok(NULL, "\\*"), sizeof(firstfile->extension)); + else + strncpy(firstfile->extension, "", sizeof(firstfile->extension)); + + HANDLE d; + if ((d = opendir(path)) == NULL || !FindNextFile(d, firstfile)) + return NULL; + + return d; +} + +bool FindNextFile(HANDLE d, WIN32_FIND_DATA* finddata) { + dirent *file; + static struct stat fileStats; + static char path[PATH_MAX], relativepath[NAME_MAX + sizeof(finddata->folder) + 1]; + int extensionLen = strlen(finddata->extension); + while ((file = readdir(d)) != NULL) { + + // We only want "DT_REG"ular Files, but reportedly some FS and OSes gives DT_UNKNOWN as type. + if ((file->d_type == DT_UNKNOWN || file->d_type == DT_REG) && + (extensionLen == 0 || strncmp(&file->d_name[strlen(file->d_name) - extensionLen], finddata->extension, extensionLen) == 0)) { + + sprintf(relativepath, "%s/%s", finddata->folder, file->d_name); + realpath(relativepath, path); + stat(path, &fileStats); + strncpy(finddata->cFileName, file->d_name, sizeof(finddata->cFileName)); + finddata->ftLastWriteTime = fileStats.st_mtime; + return true; + } + } + return false; +} + +void GetDateFormat(int unused1, int unused2, SYSTEMTIME* in, int unused3, char* out, int size) { + tm linuxTime; + linuxTime.tm_year = in->wYear - 1900; + linuxTime.tm_mon = in->wMonth - 1; + linuxTime.tm_wday = in->wDayOfWeek; + linuxTime.tm_mday = in->wDay; + linuxTime.tm_hour = in->wHour; + linuxTime.tm_min = in->wMinute; + linuxTime.tm_sec = in->wSecond; + strftime(out, size, nl_langinfo(D_FMT), &linuxTime); +} + +void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) { + tm *ptm = gmtime(writeTime); + tmToSystemTime(ptm, out); +} +#endif \ No newline at end of file diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h new file mode 100644 index 00000000..1b3ad7d6 --- /dev/null +++ b/src/skel/crossplatform.h @@ -0,0 +1,65 @@ +#include + +#ifndef MAX_PATH + #if !defined _WIN32 || defined __MINGW32__ + #define MAX_PATH PATH_MAX + #else + #define MAX_PATH 260 + #endif +#endif + +// Mostly wrappers around Windows functions + +// TODO: Remove USEALTERNATIVEWINFUNCS and don't use it anywhere when re3 becomes fully cross-platform, this is for testing +// Codes compatible with Windows and Linux +#if defined USEALTERNATIVEWINFUNCS || !defined _WIN32 || defined __MINGW32__ +#define DeleteFile unlink + +// Needed for save games +struct SYSTEMTIME { + uint16 wYear; + uint16 wMonth; + uint16 wDayOfWeek; + uint16 wDay; + uint16 wHour; + uint16 wMinute; + uint16 wSecond; + uint16 wMilliseconds; +}; + +#define GetLocalTime GetLocalTime_CP +#else +#include +#endif + +void GetLocalTime_CP(SYSTEMTIME* out); + + +// Only runs on GNU/POSIX/etc. +#if !defined _WIN32 || defined __MINGW32__ +#define OutputDebugString(s) re3_debug("[DBG-2]: " s "\n") + +#include +#include +#include +#include +#include + +typedef DIR* HANDLE; +#define INVALID_HANDLE_VALUE NULL +#define FindClose closedir +#define LOCALE_USER_DEFAULT 0 +#define DATE_SHORTDATE 0 + +struct WIN32_FIND_DATA { + char extension[32]; // for searching + char folder[32]; // for searching + char cFileName[256]; // because tSkinInfo has it 256 + time_t ftLastWriteTime; +}; + +HANDLE FindFirstFile(char*, WIN32_FIND_DATA*); +bool FindNextFile(HANDLE, WIN32_FIND_DATA*); +void FileTimeToSystemTime(time_t*, SYSTEMTIME*); +void GetDateFormat(int, int, SYSTEMTIME*, int, char*, int); +#endif \ No newline at end of file diff --git a/src/skel/events.cpp b/src/skel/events.cpp index 5d16d5b0..7116833d 100644 --- a/src/skel/events.cpp +++ b/src/skel/events.cpp @@ -2,18 +2,12 @@ #include "skeleton.h" #include "events.h" -//#include "main.h" - #define DIRECTINPUT_VERSION 0x0800 - #include #include "common.h" #include "Pad.h" #include "ControllerConfig.h" #include "Frontend.h" #include "Camera.h" - - - /* ***************************************************************************** */ diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index a534e903..d13d3c52 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1986,7 +1986,7 @@ WinMain(HINSTANCE instance, ++gGameState; else if ( CPad::GetPad(0)->GetEnterJustDown() ) ++gGameState; - else if ( CPad::GetPad(0)->GetCharJustDown(VK_SPACE) ) + else if ( CPad::GetPad(0)->GetCharJustDown(' ') ) ++gGameState; else if ( CPad::GetPad(0)->GetAltJustDown() ) ++gGameState; @@ -2022,7 +2022,7 @@ WinMain(HINSTANCE instance, ++gGameState; else if ( CPad::GetPad(0)->GetEnterJustDown() ) ++gGameState; - else if ( CPad::GetPad(0)->GetCharJustDown(VK_SPACE) ) + else if ( CPad::GetPad(0)->GetCharJustDown(' ') ) ++gGameState; else if ( CPad::GetPad(0)->GetAltJustDown() ) ++gGameState; diff --git a/src/skel/win/win.h b/src/skel/win/win.h index ca16c4a0..d6326294 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -5,6 +5,11 @@ #define RSREGSETBREAKALLOC(_name) /* No op */ #endif /* (!defined(RSREGSETBREAKALLOC)) */ +#ifndef _INC_WINDOWS +#define _X86_ +#include +#endif + enum eGameState { GS_START_UP = 0, @@ -17,7 +22,9 @@ enum eGameState GS_FRONTEND, GS_INIT_PLAYING_GAME, GS_PLAYING_GAME, +#ifndef MASTER GS_ANIMVIEWER, +#endif }; enum eWinVersion @@ -33,6 +40,7 @@ extern DWORD _dwOperatingSystemVersion; extern RwUInt32 gGameState; +#ifdef __DINPUT_INCLUDED__ /* platform specfic global data */ typedef struct { @@ -86,6 +94,7 @@ public: }; extern CJoySticks AllValidWinJoys; +#endif #ifdef __cplusplus extern "C" @@ -97,6 +106,7 @@ MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam); RwBool IsForegroundApp(); +#ifdef __DINPUT_INCLUDED__ HRESULT _InputInitialise(); HRESULT _InputInitialiseMouse(); HRESULT CapturePad(RwInt32 padID); @@ -110,6 +120,7 @@ BOOL _InputTranslateKey(RsKeyCodes *rs, UINT flag, UINT key); void _InputTranslateShiftKeyUpDown(RsKeyCodes *rs);; BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown); BOOL _InputIsExtended(INT flag); +#endif void InitialiseLanguage(); RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode); From 75acd781909378ba0395b0c52acee464c8221e72 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Thu, 23 Apr 2020 11:24:03 +0300 Subject: [PATCH 105/123] ps2 particles, sampman oal started --- gamefiles/{ => TEXT}/JAPANESE.gxt | Bin gamefiles/{ => TEXT}/american.gxt | Bin gamefiles/{ => TEXT}/french.gxt | Bin gamefiles/{ => TEXT}/german.gxt | Bin gamefiles/{ => TEXT}/italian.gxt | Bin gamefiles/{ => TEXT}/polish.gxt | Bin gamefiles/{ => TEXT}/russian.gxt | Bin gamefiles/{ => TEXT}/spanish.gxt | Bin gamefiles/data/PARTICLE.CFG | 363 ++++ gamefiles/{ => data}/main_d.scm | Bin gamefiles/{ => data}/main_freeroam.scm | Bin gamefiles/{ => models}/fonts_j.txd | Bin gamefiles/{ => models}/fonts_p.txd | Bin gamefiles/{ => models}/fonts_r.txd | Bin gamefiles/{ => models}/menu.txd | Bin src/audio/AudioManager.cpp | 8 +- src/audio/AudioManager.h | 2 +- src/audio/miles/sampman_mss.cpp | 2257 +++++++++++++++++++++++ src/audio/miles/sampman_mss.h | 339 ++++ src/audio/openal/samp_oal.cpp | 1404 +++++++++++++++ src/audio/openal/samp_oal.h | 340 ++++ src/audio/sampman.cpp | 2262 +----------------------- src/audio/sampman.h | 342 +--- src/core/config.h | 5 + src/core/re3.cpp | 1 - src/objects/ParticleObject.cpp | 148 ++ src/peds/Ped.cpp | 113 +- src/render/Particle.cpp | 42 +- src/render/Particle.h | 4 - src/render/ParticleMgr.cpp | 3 +- src/render/ParticleMgr.h | 4 +- src/vehicles/Automobile.cpp | 86 +- src/vehicles/Boat.cpp | 55 +- 33 files changed, 5139 insertions(+), 2639 deletions(-) rename gamefiles/{ => TEXT}/JAPANESE.gxt (100%) rename gamefiles/{ => TEXT}/american.gxt (100%) rename gamefiles/{ => TEXT}/french.gxt (100%) rename gamefiles/{ => TEXT}/german.gxt (100%) rename gamefiles/{ => TEXT}/italian.gxt (100%) rename gamefiles/{ => TEXT}/polish.gxt (100%) rename gamefiles/{ => TEXT}/russian.gxt (100%) rename gamefiles/{ => TEXT}/spanish.gxt (100%) create mode 100644 gamefiles/data/PARTICLE.CFG rename gamefiles/{ => data}/main_d.scm (100%) rename gamefiles/{ => data}/main_freeroam.scm (100%) rename gamefiles/{ => models}/fonts_j.txd (100%) rename gamefiles/{ => models}/fonts_p.txd (100%) rename gamefiles/{ => models}/fonts_r.txd (100%) rename gamefiles/{ => models}/menu.txd (100%) create mode 100644 src/audio/miles/sampman_mss.cpp create mode 100644 src/audio/miles/sampman_mss.h create mode 100644 src/audio/openal/samp_oal.cpp create mode 100644 src/audio/openal/samp_oal.h diff --git a/gamefiles/JAPANESE.gxt b/gamefiles/TEXT/JAPANESE.gxt similarity index 100% rename from gamefiles/JAPANESE.gxt rename to gamefiles/TEXT/JAPANESE.gxt diff --git a/gamefiles/american.gxt b/gamefiles/TEXT/american.gxt similarity index 100% rename from gamefiles/american.gxt rename to gamefiles/TEXT/american.gxt diff --git a/gamefiles/french.gxt b/gamefiles/TEXT/french.gxt similarity index 100% rename from gamefiles/french.gxt rename to gamefiles/TEXT/french.gxt diff --git a/gamefiles/german.gxt b/gamefiles/TEXT/german.gxt similarity index 100% rename from gamefiles/german.gxt rename to gamefiles/TEXT/german.gxt diff --git a/gamefiles/italian.gxt b/gamefiles/TEXT/italian.gxt similarity index 100% rename from gamefiles/italian.gxt rename to gamefiles/TEXT/italian.gxt diff --git a/gamefiles/polish.gxt b/gamefiles/TEXT/polish.gxt similarity index 100% rename from gamefiles/polish.gxt rename to gamefiles/TEXT/polish.gxt diff --git a/gamefiles/russian.gxt b/gamefiles/TEXT/russian.gxt similarity index 100% rename from gamefiles/russian.gxt rename to gamefiles/TEXT/russian.gxt diff --git a/gamefiles/spanish.gxt b/gamefiles/TEXT/spanish.gxt similarity index 100% rename from gamefiles/spanish.gxt rename to gamefiles/TEXT/spanish.gxt diff --git a/gamefiles/data/PARTICLE.CFG b/gamefiles/data/PARTICLE.CFG new file mode 100644 index 00000000..8bb6d30b --- /dev/null +++ b/gamefiles/data/PARTICLE.CFG @@ -0,0 +1,363 @@ +; Author: Alexander Roger +; Date: 21/12/2000 +; +; Author: Andrzej Madajczyk +; Date: 26/02/2001 +; 14/03/2001 - Alpha (opacity) support added; +; 10/05/2001 - Drag/Friction Decceleration changed to constants; +; 28/08/2001 - Initial Color Variation added; +; +; +; +; +; Note! Last line of the file MUST BE ";the end\n", otherwise you'll get parsing error(s) of the file; +; +; +; +;Particle Systems Configuration Data:: Format +; +; +;A: Particle Type Name (max 20 chars) +; +;B/C/D: Render Colouring (r,g,b) (0-255) +; +;CV: Initial Color Variation (for r,g,b only, in %) (0-100); +; (i.e. Color=(100,100,100) and CV=20, then v=random(-20,20), real_color=(100+v, 100+v, 100+v)); +; +; +; +;B2/C2/D2: Fade Destination Color (r,g,b) (0-255) +; +;FT: Color Fade Time for (B,C,D)->(B2,C2,D2), (0 for none); +; +; +; +; +;E: Default Initial Radius (float) +;F: Expansion Rate (float) +; +; +; Color "Fade-to-Black" options: +;G: Initial Intensity (0-255) +;H: Fade Time (time between fade steps in frames) +;I: Fade Amount (-255 to 255) can get brighter or dimmer +; +; "Fade Alpha" options: +;GA: Initial Intensity (0-255) +;HA: Fade Time (time between fade steps in frames) +;IA: Fade Amount +; +; "Z Rotation" options: +;GZA: Initial Angle (0-1023) +;HZA: Change Time (time between steps in frames) +;IZA: Angle Change Amount +; +;GZR: Initial Z Radius +;HZR: Change Time (time between steps in frames) +;IZR: Z Radius Change Amount +; +; +;J: Animation Speed (0=no animation)(time between steps msec) +;K: Start Animation Frame ( 0 -> ) +;L: Final Animation Frame ( H -> ) +; +; +;M: Rotation Speed (0=None,i-deg/frame) +;N: Gravitational Acceleration (0=none, float) +;O: Drag/Friction Decceleration (int: 0=none, 50=0.50, 80=0.80, 90=0.90, 95=0.95, 96=0.96, 99=0.99) +; +;P: Default Life-Span of Particle (msec) +; +;Q: Position Random Error [position += (+/-)rand(a)] +;R: Velocity Random Error [velocity += (+/-)rand(b)] +;S: Expansion Rate Error [exp_rate += (+)rand(c)] +;T: Rotation Rate Error [rot_speed = (+/-)rand(d)] +;U: Life-Span Error Shape [shape distribution, e=0->all at default, e->Inf then shape->0] (max=255!!) +;V: Trail Length Multiplier [length *= (float) multiplier] (only used if trail flag active) +; +;CR:Particle Create Range (in meters: 0=no check); if particles are created enough far away from camera, they are deleted (not added to particle system); +; +; +;Z: Flags! Guide: 1=ZCHECK_FIRST, 2=ZCHECK_STEP, 4=DRAW_OPAQUE, 8=SCREEN_TRAIL, +; 16=SPEED_TRAIL, 32=RAND_VERT_V, 64=CYCLE_ANIM, 128=DRAW_DARK, 256=VERT_TRAIL +; 1024=DRAWTOP2D, 2048=CLIPOUT2D +; 4096=ZCHECK_BUMP, 8192=ZCHECK_BUMP_FIRST +; +; +; +;default: +;GUNFLASH 255 255 255 0 0.1 0.0 255 0 128 0 0 0 0 0.0 1.0 250 0.0 0.0 0.0 0 0 1.0 0 +; +;good idea for fire-smudge? +;GUNFLASH 255 255 255 0 1.0 0.0 255 0 32 100 0 3 0 0.0 1.0 400 0.0 0.0 0.0 0 0 1.0 0 +; +;current: +;GUNFLASH 255 255 255 0 1.0 0.0 255 0 32 100 0 3 0 0.0 1.0 400 0.0 0.0 0.0 0 0 1.0 0 +; +; +;SPARK_SMALL 255 255 128 0 0.005 0.0 255 0 0 0 0 0 0 0.0 1.0 500 0.0 0.05 0.0 0 0 0.5 40 +; +; +; +; +; +; +; +; A B C D CV B2 C2 D2 FT E F G H I GA HA IA GZA HZA IZA GZR HZR IZR J K L M N O P Q R S T U V CR Z +; +SPARK 255 128 64 0 0 0 0 0 0.005 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.001 1 300 0.0 0.07 0.0 0 0 1.0 20.0 48 +SPARK_SMALL 255 255 128 0 0 0 0 0 0.005 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.001 1 500 0.0 0.05 0.0 0 0 0.6 20.0 40 +; +WHEEL_DIRT 8 24 8 0 0 0 0 0 0.05 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.002 1 1000 0.15 0.015 0.0 0 0 1.0 30.0 4 +; +; +;WHEEL_WATER 24 24 24 0 0 0 0 0 0.05 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.002 1 1000 0.15 0.015 0.0 0 0 1.0 20.0 0 +WHEEL_WATER 24 24 32 0 0 0 0 0 0.05 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.004 1 1000 0.15 0.015 0.0 0 0 1.0 20.0 1 +; +; +BLOOD 128 128 128 0 0 0 0 0 0.02 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.03 1 2000 0.3 0.05 0.0 0 0 1.0 50.0 5 +BLOOD_SMALL 255 32 32 0 0 0 0 0 0.007 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.005 1 2000 0.05 0.05 0.0 0 0 1.0 50.0 53 +;BLOOD_SPLAT 128 128 128 0 0 0 0 0 0.1 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 200 0.3 0.0 0.0 0 0 1.0 400.0 36 +BLOOD_SPURT 255 32 32 0 0 0 0 0 0.008 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.005 1 2000 0.0 0.01 0.0 0 0 2.0 50.0 52 +DEBRIS 64 64 64 0 0 0 0 0 0.5 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.01 95 1000 0.2 0.0 0.0 0 0 1.0 50.0 4 +DEBRIS2 64 64 64 0 0 0 0 0 0.04 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 5 0.01 99 1000 0.03 0.04 0.0 0 0 1.0 50.0 38 +WATER 64 64 128 0 0 0 0 0 0.01 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 2000 0.0 0.0 0.0 0 0 1.0 100.0 0 +; +; +;FLAME 255 74 30 0 0 0 0 0 0.2 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 32 0 4 0 0.0 1 100 0.05 0.0 0.0 0 0 1.0 400.0 0 +;FLAME 255 74 30 0 0 255 0 400 0.8 -0.02 255 0 10 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 -0.005 1 2000 0.02 0.01 0.01 0 0 1.0 200.0 0 +FLAME 255 74 30 0 0 0 0 0 0.8 -0.02 255 0 10 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 -0.005 1 2000 0.02 0.01 0.01 0 0 1.0 200.0 0 +; +; +; +;FIREBALL 255 74 30 0 0 0 0 0 0.1 0.04 255 1 8 255 0 0 0 0 0 0.0 0 0.0 32 0 7 0 0.0 96 1000 0.1 0.0 0.0 0 0 1.0 400.0 0 +; +;FIREBALL 255 74 30 0 0 0 0 0 0.1 0.05 255 0 6 255 0 0 0 0 0 0.0 0 0.0 1 0 7 0 -0.002 96 2000 0.1 0.02 0.02 3 0 1.0 200.0 0 +FIREBALL 255 74 30 0 0 0 0 0 0.1 0.02 255 0 6 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 -0.003 96 2000 0.1 0.03 0.014 2.5 0 1.0 200.0 0 +; +; +; +GUNFLASH 170 170 170 0 0 0 0 0 0.1 0.0 255 1 50 255 0 0 0 0 0 0.0 0 0.0 51 0 3 0 0.0 1 250 0.0 0.0 0.0 0 0 1.0 35.0 0 +GUNFLASH_NOANIM 128 128 128 0 0 0 0 0 0.1 0.0 255 1 128 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 25 0.0 0.0 0.0 0 0 1.0 35.0 0 +; +GUNSMOKE 64 64 64 0 0 0 0 0 0.15 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 2 0 7 0 -0.002 95 1000 0.0 0.0 0.0 0 0 1.0 60.0 0 +GUNSMOKE2 255 255 255 0 0 0 0 0 0.05 0.02 255 0 0 255 0 8 0 0 0 0.0 0 0.0 0 0 3 4 -0.001 80 1400 0.05 0.05 0.01 3 0 1.0 60.0 4 +; +; +SMOKE 32 32 32 0 0 0 0 0 0.15 0.015 255 5 25 255 0 0 0 0 0 0.0 0 0.0 32 0 4 0 -0.01 95 1000 0.05 0.05 0.01 3 0 1.0 150.0 0 +;SMOKE_SLOWMOTION 32 32 32 0 0 0 0 0 0.15 0.015 255 5 15 255 0 0 0 0 0 0.0 0 0.0 32 0 4 0 -0.003 95 1000 0.05 0.05 0.01 3 0 1.0 400.0 0 +SMOKE_SLOWMOTION 32 32 32 0 0 0 0 0 0.15 0.015 128 5 11 255 0 0 0 0 0 0.0 0 0.0 32 0 4 0 -0.003 95 3000 0.05 0.05 0.01 3 0 1.0 150.0 0 +; +; +; +;GARAGEPAINT_SPRAY 32 32 32 0 0 0 0 0 0.15 0.015 255 0 5 255 0 0 0 0 0 0.0 0 0.0 0 0 4 0 -0.001 95 2000 0.05 0.05 0.01 3 0 1.0 400.0 0 +GARAGEPAINT_SPRAY 32 32 32 0 0 0 0 0 0.15 0.015 255 0 5 255 0 0 0 0 0 0.0 0 0.0 0 0 4 0 -0.0005 95 4000 0.05 0.05 0.01 3 0 1.0 100.0 0 +SHARD 255 255 255 0 0 0 0 0 0.03 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 96 300 0.0 0.0 0.0 0 0 1.0 100.0 0 +SPLASH 64 64 128 0 0 0 0 0 0.1 0.007 255 1 10 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 1000 0.0 0.0 0.0 0 0 1.0 100.0 0 +;BLOOD_SPLASH 24 64 0 0 0 0 0 0 0.1 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 96 300 0.0 0.0 0.0 0 0 1.0 100.0 0 +; +; +;CARFLAME 255 74 30 0 0 0 0 0 0.5 0.04 255 2 20 255 0 0 0 0 0 0.0 0 0.0 32 0 4 0 0.0 1 1000 0.4 0.0 0.0 0 0 1.0 400.0 64 +;CARFLAME 255 74 30 0 0 0 0 0 0.8 -0.02 255 0 10 255 0 0 0 0 0 0.0 0 0.0 32 0 4 0 -0.001 1 2000 0.4 0.01 0.01 0 0 1.0 400.0 64 +;CARFLAME 255 74 30 0 0 0 0 0 0.8 -0.02 255 0 10 255 0 0 0 0 0 0.0 0 0.0 32 0 4 0 -0.001 1 2000 0.4 0.01 0.01 0 0 1.0 400.0 64 +; +CARFLAME 255 74 30 0 0 0 0 0 0.8 -0.02 255 0 10 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 -0.005 1 2000 0.02 0.01 0.01 0 0 1.0 100.0 0 +; +; +STEAM 64 64 64 0 0 0 0 0 0.5 0.05 255 1 16 255 0 0 0 0 0 0.0 0 0.0 32 0 4 0 -0.005 95 2000 0.01 0.03 0.0 0 0 1.0 85.0 0 +; +;default: +;STEAM2 255 255 255 0 0 0 0 0 0.5 0.05 255 0 0 128 2 8 0 0 0 0.0 0 0.0 32 0 4 0 -0.005 95 2000 0.01 0.03 0.0 0 0 1.0 400.0 4 +STEAM2 255 255 255 0 0 0 0 0 0.5 0.015 255 0 0 192 0 1 0 0 10 0.5 1 0.02 32 0 4 0 -0.002 95 8000 0.01 0.03 0.0 0 0 1.0 85.0 4 +; +; +;STEAM_NY 255 255 255 0 0 0 0 0 0.5 0.05 255 0 0 128 2 8 0 0 0 0.0 0 0.0 32 0 4 0 -0.005 95 2000 0.01 0.03 0.0 0 0 1.0 400.0 4 +STEAM_NY 255 255 255 0 0 0 0 0 0.5 0.05 255 0 0 96 2 8 0 0 0 0.0 0 0.0 32 0 4 0 -0.005 95 1400 0.01 0.03 0.0 0 0 1.0 85.0 4 +STEAM_NY_SLOWMOTION 255 255 255 0 0 0 0 0 0.5 0.05 255 0 0 96 2 8 0 0 0 0.0 0 0.0 32 0 4 0 -0.0015 95 1400 0.01 0.03 0.0 0 0 1.0 85.0 4 +; +; +;ENGINE_STEAM 210 210 210 0 0 0 0 0 0.5 0.05 255 0 0 192 2 16 0 0 0 0.0 0 0.0 32 0 4 0 -0.005 95 2000 0.01 0.03 0.0 0 0 1.0 250.0 4 +ENGINE_STEAM 210 210 210 0 0 0 0 0 0.5 0.05 255 0 0 192 0 10 0 0 0 0.0 0 0.0 32 0 4 1 -0.005 95 4000 0.03 0.03 0.02 0 0 1.0 85.0 4 +; +; +;RAINDROP 32 32 32 0 0 0 0 0 0.6 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.025 1 1000 0.0 0.0 0.0 0 0 1.0 15.0 1 +RAINDROP 64 64 64 0 0 0 0 0 0.4 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 3 0 0.05 1 1000 0.0 0.0 0.0 0 0 1.0 15.0 1 +RAINDROP_SMALL 16 16 16 0 0 0 0 0 0.3 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.05 1 1000 0.0 0.0 0.0 0 0 1.0 15.0 1 +RAIN_SPLASH 32 32 32 0 0 0 0 0 0.08 0.0 255 0 5 255 0 0 0 0 0 0.0 0 0.0 1 0 4 0 0.0 1 500 0.0 0.0 0.0 0 0 1.0 15.0 0 +RAIN_SPLASH_BIGGROW 128 128 128 0 0 0 0 0 0.5 0.06 255 0 2 255 0 0 0 0 0 0.0 0 0.0 2 1 4 0 0.0 1 5500 0.0 0.0 0.0 0 0 1.0 15.0 0 +RAIN_SPLASHUP 48 48 48 0 0 0 0 0 0.1 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 1 0 0.0 1 50 0.0 0.0 0.0 0 0 1.0 15.0 0 +; +WATERSPRAY 64 64 64 0 0 0 0 0 0.2 0.0 255 0 25 255 0 0 0 0 0 0.0 0 0.0 3 0 2 0 0.002 1 800 0.05 0.0 0.01 0 0 1.0 20.0 0 +; +; +; +;EXPLOSION_MEDIUM 80 80 80 0 0 0 0 0 0.6 0.04 255 5 8 255 0 0 0 0 0 0.0 0 0.0 8 0 11 0 0.0 96 15000 0.2 0.0 0.0 3 0 1.0 400.0 0 +;EXPLOSION_LARGE 80 80 80 0 0 0 0 0 1.1 0.04 255 5 8 255 0 0 0 0 0 0.0 0 0.0 8 0 11 0 0.0 96 15000 0.8 0.0 0.0 3 0 1.0 400.0 0 +;EXPLOSION_MEDIUM 80 80 80 0 0 0 0 0 0.6 0.04 255 1 4 255 0 0 0 0 0 0.0 0 0.0 1 0 11 0 0.0 96 7000 0.2 0.0 0.0 0 0 1.0 400.0 0 +;EXPLOSION_LARGE 80 80 80 0 0 0 0 0 1.1 0.04 255 1 4 255 0 0 0 0 0 0.0 0 0.0 1 0 11 0 0.0 96 7000 0.8 0.0 0.0 0 0 1.0 400.0 0 +; +;EXPLOSION_MEDIUM 80 80 80 0 0 0 0 0 0.6 0.04 255 0 3 255 0 0 0 0 0 0.0 0 0.0 1 0 11 0 -0.001 96 6000 0.2 0.0 0.0 0 0 1.0 400.0 0 +;EXPLOSION_LARGE 80 80 80 0 0 0 0 0 1.1 0.04 255 0 3 255 0 0 0 0 0 0.0 0 0.0 1 0 11 0 -0.001 96 6000 0.8 0.0 0.0 0 0 1.0 400.0 0 +EXPLOSION_MEDIUM 80 80 80 0 0 0 0 0 0.6 0.04 255 0 3 255 0 0 0 0 0 0.0 0 0.0 2 0 5 0 -0.001 96 6000 0.2 0.0 0.0 0 0 1.0 200.0 0 +EXPLOSION_LARGE 80 80 80 0 0 0 0 0 1.1 0.04 255 0 3 255 0 0 0 0 0 0.0 0 0.0 2 0 5 0 -0.001 96 6000 0.8 0.0 0.0 0 0 1.0 200.0 0 +EXPLOSION_MFAST 80 80 80 0 0 0 0 0 0.6 0.04 255 0 6 255 0 0 0 0 0 0.0 0 0.0 2 0 5 0 -0.001 96 3500 0.2 0.0 0.0 0 0 1.0 200.0 0 +EXPLOSION_LFAST 80 80 80 0 0 0 0 0 1.1 0.04 255 0 6 255 0 0 0 0 0 0.0 0 0.0 2 0 5 0 -0.001 96 3500 0.8 0.0 0.0 0 0 1.0 200.0 0 +; +; +; +; +;BOAT_SPLASH 32 64 32 0 0 0 0 0 0.2 0.2 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.01 1 2000 0.0 0.0 0.0 0 0 1.0 200.0 0 +;BOAT_THRUSTJET 24 32 24 0 0 0 0 0 0.5 0.1 255 0 0 255 0 0 0 0 0 0.0 0 0.0 250 0 4 0 0.01 50 1000 0.0 0.0 0.0 0 4 1.0 200.0 8 +;BOAT_SPLASH 16 32 32 0 0 0 0 0 0.2 0.2 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.01 1 2000 0.0 0.0 0.0 0 0 1.0 200.0 0 +;BOAT_THRUSTJET 8 24 24 0 0 0 0 0 0.5 0.1 255 0 0 255 0 0 0 0 0 0.0 0 0.0 250 0 4 0 0.01 50 1000 0.0 0.0 0.0 0 4 1.0 200.0 8 +;CAR_SPLASH 64 64 64 0 0 0 0 0 2.0 0.25 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.02 1 2000 0.0 0.0 0.0 0 0 1.0 250.0 0 +;CAR_SPLASH 64 64 64 0 0 0 0 0 2.0 0.25 255 0 0 200 0 8 0 0 0 0.0 0 0.0 0 0 0 0 0.04 1 2000 0.0 0.0 0.0 0 0 1.0 150.0 4 +;CAR_SPLASH 64 64 64 0 0 0 0 0 2.0 0.35 255 0 0 200 0 8 0 0 0 0.0 0 0.0 0 0 0 0 0.05 1 2000 0.0 0.0 0.0 0 0 1.0 150.0 4 +;CAR_SPLASH 64 64 64 0 0 0 0 0 1.0 0.25 255 0 0 180 0 5 0 0 0 0.0 0 0.0 2 1 3 0 0.05 1 1000 0.0 0.0 0.0 0 0 1.0 150.0 12 +; +; +;CAR_SPLASH 64 64 64 0 0 0 0 0 1.0 0.15 255 0 0 180 0 2 0 0 0 0.0 0 0.0 2 0 3 0 0.02 1 2000 0.0 0.0 0.0 0 0 1.0 150.0 12 +;CAR_SPLASH 48 48 64 0 0 0 0 0 1.0 0.15 96 0 0 255 0 0 0 0 0 0.0 0 0.0 6 0 2 0 0.01 1 2000 0.5 0.04 0.0 0 0 2.0 150.0 288 +;CAR_SPLASH 48 48 64 0 0 0 0 0 1.0 0.05 96 0 0 255 0 0 0 0 0 0.0 0 0.0 0 1 2 0 0.01 1 2000 0.5 0.04 0.0 0 0 2.0 150.0 288 +; A B C D CV B2 C2 D2 FT E F G H I GA HA IA GZA HZA IZA GZR HZR IZR J K L M N O P Q R S T U V CR Z +CAR_SPLASH 48 48 60 0 0 0 0 0 1.0 0.00 128 1 4 128 0 0 0 0 0 0.0 0 0.0 0 0 2 0 0.01 1 2000 0.5 0.04 0.0 0 0 1.4 150.0 272 +; +; +; +;BOAT_SPLASH 70 70 70 0 0 0 0 0 0.2 0.2 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.01 1 1000 0.0 0.0 0.0 0 0 1.0 150.0 0 +BOAT_SPLASH 64 64 64 0 0 0 0 0 0.2 0.2 255 0 2 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.01 1 1000 0.0 0.0 0.0 0 0 1.0 150.0 0 +; +; +;BOAT_THRUSTJET 90 90 90 0 0 0 0 0 1.8 0.1 255 0 0 120 0 1 0 0 0 0.0 0 0.0 0 1 4 0 0.01 50 1600 0.8 0.4 0.02 0 4 1.0 150.0 4 +BOAT_THRUSTJET 90 90 90 0 0 0 0 0 1.4 0.06 255 0 0 96 0 1 0 0 0 0.0 0 0.0 0 1 4 0 0.01 50 1600 0.8 0.4 0.02 0 4 1.0 150.0 4 +; +; +;BOAT_WAKE 255 255 255 0 0 0 0 0 2.0 0.2 255 0 0 128 0 1 0 0 0 0.0 0 0.0 0 0 0 0 0.03 50 1600 0.8 0.4 0.02 0 4 1.0 150.0 4 +BOAT_WAKE 255 255 255 0 0 0 0 0 1.5 0.45 255 0 0 192 0 2 0 0 0 0.0 0 0.0 0 0 0 0 0.0 50 1600 0.8 0.4 0.02 0 4 1.0 150.0 4 +; +; +; +; +; +; A B C D CV B2 C2 D2 FT E F G H I GA HA IA GZA HZA IZA GZR HZR IZR J K L M N O P Q R S T U V CR Z +WATER_HYDRANT 64 64 64 0 0 0 0 0 0.8 0.01 255 1 16 255 1 16 0 0 0 0.0 0 0.0 0 0 2 0 0.007 99 500 0.02 0.08 0.0 0 4 1.0 85.0 16 +WATER_CANNON 64 64 128 0 0 0 0 0 0.03 0.03 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 1000 0.0 0.0 0.0 0 0 1.0 85.0 0 +EXTINGUISH_STEAM 32 32 32 0 0 0 0 0 0.1 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 1000 0.0 0.0 0.0 0 0 1.0 85.0 0 +; +; +; +;PED_SPLASH 32 32 64 0 0 0 0 0 0.1 0.05 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 1000 0.0 0.0 0.0 0 0 1.0 85.0 0 +PED_SPLASH 48 48 60 0 0 0 0 0 0.1 0.06 96 0 0 255 0 0 0 0 0 0.0 0 0.0 0 1 2 0 0.01 1 2000 0.5 0.04 0.0 0 0 1.4 50.0 256 +; +; +PEDFOOT_DUST 170 166 150 0 0 0 0 0 0.01 0.015 255 0 0 63 0 4 0 0 0 0.0 0 0.0 0 0 0 0 -0.0005 1 1000 0.0 0.0 0.0 0 0 1.0 6.0 4 +; +HELI_DUST 17 15 9 0 0 0 0 0 0.2 0.1 255 1 8 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 -0.001 1 1000 0.2 0.05 0.0 0 0 1.0 85.0 0 +HELI_ATTACK 255 255 128 0 0 0 0 0 0.01 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 500 0.0 0.0 0.0 0 0 0.5 85.0 10 +; +; +;ENGINE_SMOKE 16 16 16 0 0 0 0 0 0.5 0.04 255 0 0 63 0 0 0 0 0 0.0 0 0.0 0 0 0 0 -0.005 95 2000 0.01 0.03 0.0 0 0 1.0 150.0 4 +;ENGINE_SMOKE2 8 8 8 0 0 0 0 0 1.0 0.2 128 2 4 63 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.001 1 1000 0.0 0.0 0.0 0 3 1.0 150.0 4 +ENGINE_SMOKE 16 16 16 0 0 0 0 0 0.5 0.04 255 0 0 52 0 2 10 0 80 0.0 0 0.0 0 0 5 2 -0.009 95 2000 0.11 0.03 0.01 1 0 1.0 85.0 4 +ENGINE_SMOKE2 9 9 9 80 0 0 0 0 1.0 0.06 128 0 1 140 0 5 10 0 80 0.0 0 0.0 0 0 0 2 0.002 1 1300 0.0 0.01 0.0 3 3 1.0 85.0 4 +; +; +CARFLAME_SMOKE 32 32 32 0 0 0 0 0 0.05 0.01 255 0 0 64 0 2 0 0 0 0.0 0 0.0 0 0 0 0 -0.008 95 2000 0.01 0.03 0.01 0 0 1.0 85.0 4 +FIREBALL_SMOKE 32 32 32 0 0 0 0 0 0.05 0.03 255 0 0 128 0 2 0 0 0 0.0 0 0.0 0 0 0 0 -0.004 95 2000 0.01 0.03 0.01 0 0 1.0 85.0 4 +; +PAINT_SMOKE 255 0 0 0 0 0 0 0 0.1 0.01 255 1 8 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 95 3000 0.0 0.005 0.0 0 0 1.0 85.0 0 +TREE_LEAVES 64 64 64 0 0 0 0 0 0.2 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 1000 0.0 0.0 0.0 0 0 1.0 85.0 0 +; +; +;CARCOLLISION_DUST 224 224 224 0 0 0 0 0 0.15 0.04 255 0 0 127 1 8 0 0 0 0.0 0 0.0 0 0 0 0 -0.002 90 2000 0.02 0.02 0.0 0 0 1.0 80.0 4 +CARCOLLISION_DUST 76 76 76 0 0 0 0 0 0.10 0.02 255 0 0 160 0 4 0 0 0 0.0 0 0.0 0 0 0 0 -0.0015 90 2000 0.02 0.02 0.0 0 0 1.0 30.0 4 +; +; +CAR_DEBRIS 32 32 32 0 0 0 0 0 0.5 0.0 224 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 4 0 0.010 90 1000 0.02 0.02 0.0 0 0 1.0 50.0 4 +HELI_DEBRIS 32 32 32 0 0 0 0 0 1.5 0.0 224 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 4 0 0.065 90 1500 0.02 0.02 0.0 0 0 1.0 150.0 4 +; +; +; +;EXHAUST_FUMES 80 80 80 0 0 0 0 0 0.03 0.03 255 0 0 122 0 4 0 0 0 0.0 0 0.0 2 0 4 0 -0.001 95 1500 0.01 0.03 0.0 0 0 1.0 50.0 4 +EXHAUST_FUMES 98 98 108 0 0 0 0 0 0.03 0.06 255 0 0 152 0 12 0 0 0 0.0 0 0.0 2 0 4 0 -0.002 96 1000 0.01 0.03 0.0 0 0 1.0 25.0 4 +; +; +;RUBBER 40 40 40 0 0 0 0 0 0.4 0.005 255 21 20 255 0 0 0 0 0 0.0 0 0.0 3 0 4 0 -0.0005 1 1000 0.02 0.0 0.0 0 0 1.0 400.0 4 +RUBBER_SMOKE 255 255 255 0 0 0 0 0 0.4 0.005 255 0 0 127 1 8 0 0 0 0.0 0 0.0 3 0 4 0 -0.0005 1 1000 0.02 0.0 0.0 0 0 1.0 50.0 4 +;BURNINGRUBBER_SMOKE128 128 128 0 0 0 0 0 0.35 0.06 255 0 0 192 1 6 0 0 0 0.0 0 0.0 0 0 0 0 -0.002 90 4000 0.02 0.02 0.0 0 0 1.0 400.0 4 +BURNINGRUBBER_SMOKE 128 128 128 0 0 0 0 0 0.35 0.06 255 0 0 128 0 4 0 0 0 0.0 0 0.0 0 0 0 0 -0.002 90 2000 0.02 0.02 0.0 0 0 1.0 50.0 4 +; +; +BULLETHIT_SMOKE 192 192 192 0 0 0 0 0 0.15 0.03 70 0 2 255 1 10 0 0 0 0.0 0 0.0 0 0 0 0 -0.001 90 2000 0.04 0.02 0.0 0 0 1.0 150.0 0 +; +; +GUNSHELL_FIRST 108 108 108 0 0 0 0 0 0.015 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 4 0 0.010 90 1000 0.02 0.02 0.0 0 0 1.0 0.0 12292 +GUNSHELL 108 108 108 0 0 0 0 0 0.015 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 4 0 0.010 90 1000 0.02 0.02 0.0 0 0 1.0 12.0 4100 +GUNSHELL_BUMP1 108 108 108 0 0 0 0 0 0.015 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 4 0 0.010 90 1000 0.02 0.02 0.0 0 0 1.0 8.0 4100 +GUNSHELL_BUMP2 108 108 108 0 0 0 0 0 0.015 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 0 4 0 0.010 90 400 0.02 0.02 0.0 0 0 1.0 8.0 4100 +; +; +TEST 255 64 64 0 0 0 0 0 0.2 0.025 255 1 20 255 0 0 0 0 0 0.0 0 0.0 0 0 0 0 0.0 1 3000 0.0 0.0 0.0 0 0 1.0 400.0 128 +; +; +;Particles with flag DRAWTOP2D should be placed last and VR (Visibility Range) set to 0! +; +;BIRD_FRONT 8 8 8 0 0 0 0 0 0.05 0.0 255 0 0 255 2 1 0 0 0 0.0 0 0.0 1 0 3 0 0.0 1 10000 0.0 0.0 0.0 0 0 1.0 0.0 3140 +BIRD_FRONT 8 8 8 0 0 0 0 0 1.05 0.0 255 0 0 255 2 2 0 0 0 0.0 0 0.0 1 0 3 0 0.0 1 8000 0.0 0.0 0.0 0 0 1.0 0.0 68 +; +RAINDROP_2D 32 32 32 0 0 0 0 0 0.5 0.0 255 0 0 255 0 0 0 0 0 0.0 0 0.0 0 1 0 0 0.0 1 1000 0.0 0.0 0.0 0 0 1.0 0.0 3072 +; +; +; +; +; +; +; +; +; +; +; +; +; below is just backup of above values: +; +;SPARK 255 128 64 0.005 0.0 255 0 0 0 0 0 0 0.0 1.0 300 0.0 0.07 0.0 0 0 1.0 48 +;SPARK_SMALL 255 255 128 0.005 0.0 255 0 0 0 0 0 0 0.0 1.0 500 0.0 0.05 0.0 0 0 0.6 40 +;BLOOD 128 128 128 0.02 0.0 255 0 0 0 0 0 0 0.03 1.0 2000 0.3 0.05 0.0 0 0 1.0 6 +;BLOOD_SMALL 255 32 32 0.007 0.0 255 0 0 0 0 0 0 0.005 1.0 2000 0.05 0.05 0.0 0 0 1.0 54 +;BLOOD_SPLAT 128 128 128 0.1 0.0 255 0 0 0 0 0 0 0.0 1.0 200 0.3 0.0 0.0 0 0 1.0 36 +;BLOOD_SPURT 255 32 32 0.008 0.0 255 0 0 0 0 0 0 0.005 1.0 2000 0.0 0.01 0.0 0 0 2.0 52 +;DEBRIS 64 64 64 0.5 0.0 255 0 0 0 0 0 0 0.01 0.95 1000 0.2 0.0 0.0 0 0 1.0 4 +;DEBRIS2 64 64 64 0.04 0.0 255 0 0 0 0 0 5 0.01 0.99 1000 0.03 0.04 0.0 0 0 1.0 38 +;WATER 64 64 128 0.01 0.0 255 0 0 0 0 0 0 0.0 1.0 2000 0.0 0.0 0.0 0 0 1.0 0 +;FLAME 255 74 30 0.2 0.0 255 0 0 31 0 5 0 0.0 1.0 100 0.05 0.0 0.0 0 0 1.0 0 +;FIREBALL 255 74 30 0.1 0.04 255 0 8 31 0 8 0 0.0 0.96 1000 0.1 0.0 0.0 0 0 1.0 0 +;GUNFLASH 255 255 255 0.1 0.0 255 0 50 50 0 3 0 0.0 1.0 250 0.0 0.0 0.0 0 0 1.0 0 +;GUNFLASHSTATIC 255 255 255 0.1 0.0 255 0 128 0 0 0 0 0.0 1.0 25 0.0 0.0 0.0 0 0 1.0 0 +;SMOKE 32 32 32 0.15 0.015 255 4 25 31 0 5 0 -0.01 0.95 1000 0.05 0.05 0.01 3 0 1.0 0 +;SHARD 255 255 255 0.03 0.0 255 0 0 0 0 0 0 0.0 0.96 300 0.0 0.0 0.0 0 0 1.0 0 +;SPLASH 64 64 128 0.1 0.007 255 0 10 0 0 0 0 0.0 1.0 1000 0.0 0.0 0.0 0 0 1.0 0 +;BLOOD_SPLASH 24 64 0 0.1 0.0 255 0 0 0 0 0 0 0.0 0.96 300 0.0 0.0 0.0 0 0 1.0 0 +;RUBBER 40 40 40 0.4 0.005 255 1 25 31 0 5 0 0.0 1.0 1000 0.02 0.0 0.0 0 0 1.0 0 +;CARFLAME 255 74 30 0.5 0.04 255 1 20 31 0 5 0 0.0 1.0 1000 0.4 0.0 0.0 0 0 1.0 64 +;STEAM 64 64 64 0.5 0.05 255 0 16 31 0 5 0 -0.005 0.95 2000 0.01 0.03 0.0 0 0 1.0 0 +;RAINDROP 32 32 32 0.6 0.0 255 0 0 0 0 0 0 0.1 1.0 1000 0.0 0.0 0.0 0 0 1.0 1 +;RAIN_SPLASH 32 32 32 0.08 0.0 255 0 0 1 0 4 0 0.0 1.0 1000 0.0 0.0 0.0 0 0 1.0 0 +;RAINDROP_SMALL 32 32 32 0.3 0.0 255 0 0 0 0 0 0 0.1 1.0 1000 0.0 0.0 0.0 0 0 1.0 1 +;EXPLOSION_MEDIUM 80 80 80 0.6 0.04 255 4 8 7 0 11 0 0.0 0.96 30000 0.2 0.0 0.0 3 0 1.0 0 +;EXPLOSION_LARGE 80 80 80 1.1 0.04 255 4 8 7 0 11 0 0.0 0.96 30000 0.8 0.0 0.0 3 0 1.0 0 +;BOAT_SPLASH 32 64 32 0.2 0.2 255 0 0 0 0 0 0 0.01 1.0 2000 0.0 0.0 0.0 0 0 1.0 0 +;BOAT_THRUSTJET 24 32 24 0.5 0.1 255 0 0 250 0 5 0 0.01 0.5 1000 0.0 0.0 0.0 0 4 1.0 8 +;WATER_HYDRANT 64 64 128 0.4 0.01 255 1 2 20 0 5 0 0.007 0.99 500 0.02 0.05 0.0 0 4 1.0 256 +;WATER_CANNON 64 64 128 0.03 0.03 255 0 0 0 0 0 0 0.0 1.0 1000 0.0 0.0 0.0 0 0 1.0 0 +;EXTINGUISH_STEAM 32 32 32 0.1 0.0 255 0 0 0 0 0 0 0.0 1.0 1000 0.0 0.0 0.0 0 0 1.0 0 +;PED_SPLASH 32 32 64 0.1 0.05 255 0 0 0 0 0 0 0.0 1.0 1000 0.0 0.0 0.0 0 0 1.0 0 +;HELI_DUST 17 15 9 0.2 0.1 255 0 8 0 0 0 0 -0.001 1.0 1000 0.2 0.05 0.0 0 0 1.0 0 +;HELI_ATTACK 255 255 128 0.01 0.0 255 0 0 0 0 0 0 0.0 1.0 500 0.0 0.0 0.0 0 0 0.5 10 +;ENGINE_SMOKE 16 16 16 0.5 0.04 255 0 0 0 0 0 0 -0.005 0.95 2000 0.01 0.03 0.0 0 0 1.0 4 +;ENGINE_SMOKE2 4 4 4 1.0 0.2 255 1 4 0 0 0 0 0.001 1.0 1000 0.0 0.0 0.0 0 3 1.0 4 +;PAINT_SMOKE 255 0 0 0.1 0.01 255 0 8 0 0 0 0 0.0 0.95 3000 0.0 0.005 0.0 0 0 1.0 0 +;TREE_LEAVES 64 64 64 0.2 0.0 255 0 0 0 0 0 0 0.0 1.0 1000 0.0 0.0 0.0 0 0 1.0 0 +;TEST 255 64 64 0.2 0.05 255 0 16 0 0 0 0 0.0 1.0 3000 0.0 0.0 0.0 0 0 1.0 128 +; +; +;the end diff --git a/gamefiles/main_d.scm b/gamefiles/data/main_d.scm similarity index 100% rename from gamefiles/main_d.scm rename to gamefiles/data/main_d.scm diff --git a/gamefiles/main_freeroam.scm b/gamefiles/data/main_freeroam.scm similarity index 100% rename from gamefiles/main_freeroam.scm rename to gamefiles/data/main_freeroam.scm diff --git a/gamefiles/fonts_j.txd b/gamefiles/models/fonts_j.txd similarity index 100% rename from gamefiles/fonts_j.txd rename to gamefiles/models/fonts_j.txd diff --git a/gamefiles/fonts_p.txd b/gamefiles/models/fonts_p.txd similarity index 100% rename from gamefiles/fonts_p.txd rename to gamefiles/models/fonts_p.txd diff --git a/gamefiles/fonts_r.txd b/gamefiles/models/fonts_r.txd similarity index 100% rename from gamefiles/fonts_r.txd rename to gamefiles/models/fonts_r.txd diff --git a/gamefiles/menu.txd b/gamefiles/models/menu.txd similarity index 100% rename from gamefiles/menu.txd rename to gamefiles/models/menu.txd diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index f836f1c4..02bf532c 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -9548,6 +9548,9 @@ cAudioManager::ResetTimers(uint32 time) SampleManager.SetEffectsFadeVolume(0); SampleManager.SetMusicFadeVolume(0); MusicManager.ResetMusicAfterReload(); +#ifdef OPENAL + SampleManager.Service(); +#endif } } @@ -9603,6 +9606,9 @@ cAudioManager::ServiceSoundEffects() ProcessMissionAudio(); AdjustSamplesVolume(); ProcessActiveQueues(); +#ifdef WITHMILES + SampleManager.Service(); +#endif for(int32 i = 0; i < m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal; ++i) { cAudioScriptObject *object = (cAudioScriptObject *)m_asAudioEntities[m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]] @@ -9983,7 +9989,7 @@ cAudioManager::Terminate() m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0; PreTerminateGameSpecificShutdown(); - for(uint32 i = 0; i < DIGITALCHANNELS; i++) { + for(uint32 i = 0; i < MAX_SAMPLEBANKS; i++) { if(SampleManager.IsSampleBankLoaded(i)) SampleManager.UnloadSampleBank(i); } diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 01fa055d..72d8ba41 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -581,6 +581,6 @@ public: uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); }; -static_assert(sizeof(cAudioManager) == 19220, "cAudioManager: error"); +//dstatic_assert(sizeof(cAudioManager) == 19220, "cAudioManager: error"); extern cAudioManager AudioManager; diff --git a/src/audio/miles/sampman_mss.cpp b/src/audio/miles/sampman_mss.cpp new file mode 100644 index 00000000..f3a6ba80 --- /dev/null +++ b/src/audio/miles/sampman_mss.cpp @@ -0,0 +1,2257 @@ +#include +#include +#include + +#include + +#include "eax.h" +#include "eax-util.h" +#include "mss.h" + +#include "sampman_mss.h" +#include "AudioManager.h" +#include "MusicManager.h" +#include "Frontend.h" +#include "Timer.h" + + +#pragma comment( lib, "mss32.lib" ) + +cSampleManager SampleManager; +int32 BankStartOffset[MAX_SAMPLEBANKS]; +/////////////////////////////////////////////////////////////// + +char SampleBankDescFilename[] = "AUDIO\\SFX.SDT"; +char SampleBankDataFilename[] = "AUDIO\\SFX.RAW"; + +FILE *fpSampleDescHandle; +FILE *fpSampleDataHandle; +bool bSampleBankLoaded [MAX_SAMPLEBANKS]; +int32 nSampleBankDiscStartOffset [MAX_SAMPLEBANKS]; +int32 nSampleBankSize [MAX_SAMPLEBANKS]; +int32 nSampleBankMemoryStartAddress[MAX_SAMPLEBANKS]; +int32 _nSampleDataEndOffset; + +int32 nPedSlotSfx [MAX_PEDSFX]; +int32 nPedSlotSfxAddr[MAX_PEDSFX]; +uint8 nCurrentPedSlot; + +uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS]; + +uint32 nStreamLength[TOTAL_STREAMED_SOUNDS]; + +/////////////////////////////////////////////////////////////// +struct tMP3Entry +{ + char aFilename[MAX_PATH]; + + uint32 nTrackLength; + uint32 nTrackStreamPos; + + tMP3Entry *pNext; + char *pLinkPath; +}; + +uint32 nNumMP3s; +tMP3Entry *_pMP3List; +char _mp3DirectoryPath[MAX_PATH]; +HSTREAM mp3Stream [MAX_MP3STREAMS]; +int8 nStreamPan [MAX_MP3STREAMS]; +int8 nStreamVolume[MAX_MP3STREAMS]; +uint32 _CurMP3Index; +int32 _CurMP3Pos; +bool _bIsMp3Active; + +#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) +bool _bUseHDDAudio; +char _aHDDPath[MAX_PATH]; +#endif +/////////////////////////////////////////////////////////////// + + +bool _bSampmanInitialised = false; + +// +// Miscellaneous globals / defines + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS + +EAXLISTENERPROPERTIES StartEAX3 = + {26, 1.7f, 0.8f, -1000, -1000, -100, 4.42f, 0.14f, 1.00f, 429, 0.014f, 0.00f,0.00f,0.00f, 1023, 0.021f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2727.1f, 250.0f, 0.00f, 0x3f }; + +EAXLISTENERPROPERTIES FinishEAX3 = + {26, 100.0f, 1.0f, 0, -1000, -2200, 20.0f, 1.39f, 1.00f, 1000, 0.069f, 0.00f,0.00f,0.00f, 400, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 3.982f, 0.000f, -18.0f, 3530.8f, 417.9f, 6.70f, 0x3f }; + +EAXLISTENERPROPERTIES EAX3Params; + +S32 prevprovider=-1; +S32 curprovider=-1; +S32 usingEAX=0; +S32 usingEAX3=0; +HPROVIDER opened_provider=0; +H3DSAMPLE opened_samples[MAXCHANNELS] = {0}; +HSAMPLE opened_2dsamples[MAX2DCHANNELS] = {0}; +HDIGDRIVER DIG; +S32 speaker_type=0; + +U32 _maxSamples; +float _fPrevEaxRatioDestination; +bool _usingMilesFast2D; +float _fEffectsLevel; + + +struct +{ + HPROVIDER id; + char name[80]; +}providers[MAXPROVIDERS]; + +typedef struct provider_stuff +{ + char* name; + HPROVIDER id; +} provider_stuff; + + +static int __cdecl comp(const provider_stuff*s1,const provider_stuff*s2) +{ + return( _stricmp(s1->name,s2->name) ); +} + +static void +add_providers() +{ + provider_stuff pi[MAXPROVIDERS]; + U32 n,i,j; + + SampleManager.SetNum3DProvidersAvailable(0); + + HPROENUM next = HPROENUM_FIRST; + + n=0; + while (AIL_enumerate_3D_providers(&next, &pi[n].id, &pi[n].name) && (n MAXCHANNELS ) + _maxSamples = MAXCHANNELS; + + SampleManager.SetSpeakerConfig(speaker_type); + + //obtain a 3D sample handles + for ( U32 i = 0; i < _maxSamples; ++i ) + { + opened_samples[i] = AIL_allocate_3D_sample_handle(opened_provider); + if ( opened_samples[i] != NULL ) + AIL_set_3D_sample_effects_level(opened_samples[i], 0.0f); + } + + return true; + } + } + + return false; +} + +void +cSampleManager::SetSpeakerConfig(int32 which) +{ + switch ( which ) + { + case 1: + speaker_type=AIL_3D_2_SPEAKER; + break; + + case 2: + speaker_type=AIL_3D_HEADPHONE; + break; + + case 3: + speaker_type=AIL_3D_4_SPEAKER; + break; + + default: + return; + break; + } + + if (opened_provider) + AIL_set_3D_speaker_type(opened_provider, speaker_type); +} + +uint32 +cSampleManager::GetMaximumSupportedChannels(void) +{ + if ( _maxSamples > MAXCHANNELS ) + return MAXCHANNELS; + + return _maxSamples; +} + +int8 +cSampleManager::GetCurrent3DProviderIndex(void) +{ + return curprovider; +} + +int8 +cSampleManager::SetCurrent3DProvider(uint8 nProvider) +{ + S32 savedprovider = curprovider; + + if ( nProvider < m_nNumberOfProviders ) + { + if ( set_new_provider(nProvider) ) + return curprovider; + else if ( savedprovider != -1 && savedprovider < m_nNumberOfProviders && set_new_provider(savedprovider) ) + return curprovider; + else + return -1; + } + else + return curprovider; +} + +static bool +_ResolveLink(char const *path, char *out) +{ + IShellLink* psl; + WIN32_FIND_DATA fd; + char filepath[MAX_PATH]; + + CoInitialize(NULL); + + if (SUCCEEDED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl ) )) + { + IPersistFile *ppf; + + if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf))) + { + WCHAR wpath[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH); + + if (SUCCEEDED(ppf->Load(wpath, STGM_READ))) + { + /* Resolve the link */ + if (SUCCEEDED(psl->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI|SLR_NOSEARCH))) + { + strcpy(filepath, path); + + if (SUCCEEDED(psl->GetPath(filepath, MAX_PATH, &fd, SLGP_UNCPRIORITY))) + { + OutputDebugString(fd.cFileName); + + strcpy(out, filepath); + // FIX: Release the objects. Taken from SA. +#ifdef FIX_BUGS + ppf->Release(); + psl->Release(); +#endif + return true; + } + } + } + + ppf->Release(); + } + psl->Release(); + } + + return false; +} + +static void +_FindMP3s(void) +{ + tMP3Entry *pList; + bool bShortcut; + bool bInitFirstEntry; + HANDLE hFind; + char path[MAX_PATH]; + char filepath[MAX_PATH*2]; + S32 total_ms; + WIN32_FIND_DATA fd; + + + if ( GetCurrentDirectory(MAX_PATH, _mp3DirectoryPath) == 0 ) + { + GetLastError(); + return; + } + + OutputDebugString("Finding MP3s..."); + strcpy(path, _mp3DirectoryPath); + strcat(path, "\\MP3\\"); + + strcpy(_mp3DirectoryPath, path); + OutputDebugString(_mp3DirectoryPath); + + strcat(path, "*"); + + hFind = FindFirstFile(path, &fd); + + if ( hFind == INVALID_HANDLE_VALUE ) + { + GetLastError(); + return; + } + + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + int32 filepathlen = strlen(filepath); + + if ( filepathlen <= 0) + { + FindClose(hFind); + return; + } + + FILE *f = fopen("MP3\\MP3Report.txt", "w"); + + if ( f ) + { + fprintf(f, "MP3 Report File\n\n"); + fprintf(f, "\"%s\"", fd.cFileName); + } + + + if ( filepathlen > 4 ) + { + if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) + { + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); + } + else + { + if ( f ) fprintf(f, " - couldn't resolve shortcut"); + } + + bShortcut = true; + } + else + bShortcut = false; + } + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + OutputDebugString(fd.cFileName); + + _pMP3List = new tMP3Entry; + + if ( _pMP3List == NULL ) + { + FindClose(hFind); + + if ( f ) + fclose(f); + + return; + } + + nNumMP3s = 1; + + strcpy(_pMP3List->aFilename, fd.cFileName); + + _pMP3List->nTrackLength = total_ms; + + _pMP3List->pNext = NULL; + + pList = _pMP3List; + + if ( bShortcut ) + { + _pMP3List->pLinkPath = new char[MAX_PATH*2]; + strcpy(_pMP3List->pLinkPath, filepath); + } + else + { + _pMP3List->pLinkPath = NULL; + } + + if ( f ) fprintf(f, " - OK\n"); + + bInitFirstEntry = false; + } + else + { + strcat(filepath, " - NOT A VALID MP3"); + + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); + + bInitFirstEntry = true; + } + + while ( true ) + { + if ( !FindNextFile(hFind, &fd) ) + break; + + if ( bInitFirstEntry ) + { + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + int32 filepathlen = strlen(filepath); + + if ( f ) fprintf(f, "\"%s\"", fd.cFileName); + + if ( filepathlen > 0 ) + { + if ( filepathlen > 4 ) + { + if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) + { + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); + } + else + { + if ( f ) fprintf(f, " - couldn't resolve shortcut"); + } + + bShortcut = true; + } + else + { + bShortcut = false; + + if ( filepathlen > MAX_PATH ) + { + if ( f ) fprintf(f, " - Filename and path too long - %s - IGNORED)\n", filepath); + + continue; + } + } + } + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + OutputDebugString(fd.cFileName); + + _pMP3List = new tMP3Entry; + + if ( _pMP3List == NULL) + break; + + nNumMP3s = 1; + + strcpy(_pMP3List->aFilename, fd.cFileName); + + _pMP3List->nTrackLength = total_ms; + _pMP3List->pNext = NULL; + + if ( bShortcut ) + { + _pMP3List->pLinkPath = new char [MAX_PATH*2]; + strcpy(_pMP3List->pLinkPath, filepath); + } + else + { + _pMP3List->pLinkPath = NULL; + } + + pList = _pMP3List; + + if ( f ) fprintf(f, " - OK\n"); + + bInitFirstEntry = false; + } + else + { + strcat(filepath, " - NOT A VALID MP3"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); + } + } + } + else + { + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + int32 filepathlen = strlen(filepath); + + if ( filepathlen > 0 ) + { + if ( f ) fprintf(f, "\"%s\"", fd.cFileName); + + if ( filepathlen > 4 ) + { + if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) + { + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); + } + else + { + if ( f ) fprintf(f, " - couldn't resolve shortcut"); + } + + bShortcut = true; + } + else + { + bShortcut = false; + } + } + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + pList->pNext = new tMP3Entry; + + tMP3Entry *e = pList->pNext; + + if ( e == NULL ) + break; + + pList = pList->pNext; + + strcpy(e->aFilename, fd.cFileName); + e->nTrackLength = total_ms; + e->pNext = NULL; + + if ( bShortcut ) + { + e->pLinkPath = new char [MAX_PATH*2]; + strcpy(e->pLinkPath, filepath); + } + else + { + e->pLinkPath = NULL; + } + + nNumMP3s++; + + OutputDebugString(fd.cFileName); + + if ( f ) fprintf(f, " - OK\n"); + } + else + { + strcat(filepath, " - NOT A VALID MP3"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); + } + } + } + } + + if ( f ) + { + fprintf(f, "\nTOTAL SUPPORTED MP3s: %d\n", nNumMP3s); + fclose(f); + } + + FindClose(hFind); +} + +static void +_DeleteMP3Entries(void) +{ + tMP3Entry *e = _pMP3List; + + while ( e != NULL ) + { + tMP3Entry *next = e->pNext; + + if ( next == NULL ) + next = NULL; + + if ( e->pLinkPath != NULL ) + { +#ifndef FIX_BUGS + delete e->pLinkPath; // BUG: should be delete [] +#else + delete[] e->pLinkPath; +#endif + e->pLinkPath = NULL; + } + + delete e; + + if ( next ) + e = next; + else + e = NULL; + + nNumMP3s--; + } + + + if ( nNumMP3s != 0 ) + { + OutputDebugString("Not all MP3 entries were deleted"); + nNumMP3s = 0; + } + + _pMP3List = NULL; +} + +static tMP3Entry * +_GetMP3EntryByIndex(uint32 idx) +{ + uint32 n = ( idx < nNumMP3s ) ? idx : 0; + + if ( _pMP3List != NULL ) + { + tMP3Entry *e = _pMP3List; + + for ( uint32 i = 0; i < n; i++ ) + e = e->pNext; + + return e; + + } + + return NULL; +} + +static inline bool +_GetMP3PosFromStreamPos(uint32 *pPosition, tMP3Entry **pEntry) +{ + _CurMP3Index = 0; + + for ( *pEntry = _pMP3List; *pEntry != NULL; *pEntry = (*pEntry)->pNext ) + { + if ( *pPosition >= (*pEntry)->nTrackStreamPos + && *pPosition < (*pEntry)->nTrackLength + (*pEntry)->nTrackStreamPos ) + { + *pPosition -= (*pEntry)->nTrackStreamPos; + _CurMP3Pos = *pPosition; + + return true; + } + + _CurMP3Index++; + } + + *pPosition = 0; + *pEntry = _pMP3List; + _CurMP3Pos = 0; + _CurMP3Index = 0; + + return false; +} + +bool +cSampleManager::IsMP3RadioChannelAvailable(void) +{ + return nNumMP3s != 0; +} + +void +cSampleManager::ReleaseDigitalHandle(void) +{ + if ( DIG ) + { + prevprovider = curprovider; + release_existing(); + curprovider = -1; + AIL_digital_handle_release(DIG); + } +} + +void +cSampleManager::ReacquireDigitalHandle(void) +{ + if ( DIG ) + { + AIL_digital_handle_reacquire(DIG); + if ( prevprovider != -1 ) + set_new_provider(prevprovider); + } +} + +bool +cSampleManager::Initialise(void) +{ + TRACE("start"); + + if ( _bSampmanInitialised ) + return true; + + { + for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) + { + m_aSamples[i].nOffset = 0; + m_aSamples[i].nSize = 0; + m_aSamples[i].nFrequency = 22050; + m_aSamples[i].nLoopStart = 0; + m_aSamples[i].nLoopEnd = -1; + } + + m_nEffectsVolume = MAX_VOLUME; + m_nMusicVolume = MAX_VOLUME; + m_nEffectsFadeVolume = MAX_VOLUME; + m_nMusicFadeVolume = MAX_VOLUME; + + m_nMonoMode = 0; + } + + // miles + TRACE("MILES"); + { + curprovider = -1; + prevprovider = -1; + + _usingMilesFast2D = false; + usingEAX=0; + usingEAX3=0; + + _fEffectsLevel = 0.0f; + + _maxSamples = 0; + + opened_provider = NULL; + DIG = NULL; + + for ( int32 i = 0; i < MAXCHANNELS; i++ ) + opened_samples[i] = NULL; + } + + // banks + TRACE("banks"); + { + fpSampleDescHandle = NULL; + fpSampleDataHandle = NULL; + + _nSampleDataEndOffset = 0; + + for ( int32 i = 0; i < MAX_SAMPLEBANKS; i++ ) + { + bSampleBankLoaded[i] = false; + nSampleBankDiscStartOffset[i] = 0; + nSampleBankSize[i] = 0; + nSampleBankMemoryStartAddress[i] = 0; + } + } + + // pedsfx + TRACE("pedsfx"); + { + for ( int32 i = 0; i < MAX_PEDSFX; i++ ) + { + nPedSlotSfx[i] = NO_SAMPLE; + nPedSlotSfxAddr[i] = 0; + } + + nCurrentPedSlot = 0; + } + + // channel volume + TRACE("vol"); + { + for ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ ) + nChannelVolume[i] = 0; + } + + TRACE("mss"); + { + AIL_set_redist_directory( "mss" ); + + AIL_startup(); + + AIL_set_preference(DIG_MIXER_CHANNELS, MAX_DIGITAL_MIXER_CHANNELS); + + DIG = AIL_open_digital_driver(DIGITALRATE, DIGITALBITS, DIGITALCHANNELS, 0); + if ( DIG == NULL ) + { + OutputDebugString(AIL_last_error()); + Terminate(); + return false; + } + + add_providers(); + + if ( !InitialiseSampleBanks() ) + { + Terminate(); + return false; + } + + nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = (int32)AIL_mem_alloc_lock(nSampleBankSize[SAMPLEBANK_MAIN]); + if ( !nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] ) + { + Terminate(); + return false; + } + + nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = (int32)AIL_mem_alloc_lock(PED_BLOCKSIZE*MAX_PEDSFX); + + } + + TRACE("cdrom"); + + S32 tatalms; + char filepath[MAX_PATH]; + + { + m_bInitialised = false; + + while (true) + { + int32 drive = 'C'; + + do + { + char latter[2]; + + latter[0] = drive; + latter[1] = '\0'; + + strcpy(m_szCDRomRootPath, latter); + strcat(m_szCDRomRootPath, ":\\"); + + if ( GetDriveType(m_szCDRomRootPath) == DRIVE_CDROM ) + { + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[0]); + + FILE *f = fopen(filepath, "rb"); + + if ( f ) + { + fclose(f); + + bool bFileNotFound = false; + + for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) + { + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[i]); + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &tatalms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + nStreamLength[i] = tatalms; + } + else + { + bFileNotFound = true; + break; + } + } + + if ( !bFileNotFound ) + { + m_bInitialised = true; + break; + } + else + { + m_bInitialised = false; + continue; + } + } + } + + } while ( ++drive <= 'Z' ); + + if ( !m_bInitialised ) + { +#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) + FrontEndMenuManager.WaitForUserCD(); + if ( FrontEndMenuManager.m_bQuitGameNoCD ) + { + Terminate(); + return false; + } + continue; +#else + m_bInitialised = true; +#endif + } + + break; + } + } + +#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) + // hddaudio + /** + Option for user to play audio files directly from hard disk. + Copy the contents of the PLAY discs Audio directory into your installed Grand Theft Auto III Audio directory. + Grand Theft Auto III still requires the presence of the PLAY disc when started. + This may give better performance on some machines (though worse on others). + **/ + TRACE("hddaudio 1.1 patch"); + { + int32 streamLength[TOTAL_STREAMED_SOUNDS]; + + bool bFileNotFound = false; + char rootpath[MAX_PATH]; + + strcpy(_aHDDPath, m_szCDRomRootPath); + rootpath[0] = '\0'; + + FILE *f = fopen(StreamedNameTable[0], "rb"); + + if ( f ) + { + fclose(f); + + for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) + { + strcpy(filepath, rootpath); + strcat(filepath, StreamedNameTable[i]); + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &tatalms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + streamLength[i] = tatalms; + } + else + { + bFileNotFound = true; + break; + } + } + + } + else + bFileNotFound = true; + + if ( !bFileNotFound ) + { + strcpy(m_szCDRomRootPath, rootpath); + + for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) + nStreamLength[i] = streamLength[i]; + + _bUseHDDAudio = true; + } + else + _bUseHDDAudio = false; + } +#endif + + TRACE("stream"); + { + for ( int32 i = 0; i < MAX_MP3STREAMS; i++ ) + { + mp3Stream [i] = NULL; + nStreamPan [i] = 63; + nStreamVolume[i] = 100; + } + } + + for ( int32 i = 0; i < MAX2DCHANNELS; i++ ) + { + opened_2dsamples[i] = AIL_allocate_sample_handle(DIG); + if ( opened_2dsamples[i] ) + { + AIL_init_sample(opened_2dsamples[i]); + AIL_set_sample_type(opened_2dsamples[i], DIG_F_MONO_16, DIG_PCM_SIGN); + } + } + + TRACE("providerset"); + { + _bSampmanInitialised = true; + + U32 n = 0; + + while ( n < m_nNumberOfProviders ) + { + if ( !strcmp(providers[n].name, "Miles Fast 2D Positional Audio") ) + { + set_new_provider(n); + break; + } + n++; + } + + if ( n == m_nNumberOfProviders ) + { + Terminate(); + return false; + } + } + + TRACE("bank"); + + LoadSampleBank(SAMPLEBANK_MAIN); + + // mp3 + TRACE("mp3"); + { + nNumMP3s = 0; + + _pMP3List = NULL; + + _FindMP3s(); + + if ( nNumMP3s != 0 ) + { + nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] = 0; + + for ( tMP3Entry *e = _pMP3List; e != NULL; e = e->pNext ) + { + e->nTrackStreamPos = nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER]; + nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] += e->nTrackLength; + } + + time_t t = time(NULL); + tm *localtm; + bool bUseRandomTable; + + if ( t == -1 ) + bUseRandomTable = true; + else + { + bUseRandomTable = false; + localtm = localtime(&t); + } + + int32 randval; + if ( bUseRandomTable ) + randval = AudioManager.GetRandomNumber(1); + else + randval = localtm->tm_sec * localtm->tm_min; + + _CurMP3Index = randval % nNumMP3s; + + tMP3Entry *randmp3 = _pMP3List; + for ( int32 i = randval % nNumMP3s; i > 0; --i) + randmp3 = randmp3->pNext; + + if ( bUseRandomTable ) + _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + else + { + if ( localtm->tm_sec > 0 ) + { + int32 s = localtm->tm_sec; + _CurMP3Pos = s*s*s*s*s*s*s*s % randmp3->nTrackLength; + } + else + _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + } + } + else + _CurMP3Pos = 0; + + _bIsMp3Active = false; + } + + TRACE("end"); + + return true; +} + +void +cSampleManager::Terminate(void) +{ + for ( int32 i = 0; i < MAX_MP3STREAMS; i++ ) + { + if ( mp3Stream[i] ) + { + AIL_pause_stream(mp3Stream[i], 1); + AIL_close_stream(mp3Stream[i]); + mp3Stream[i] = NULL; + } + } + + for ( int32 i = 0; i < MAX2DCHANNELS; i++ ) + { + if ( opened_2dsamples[i] ) + { + AIL_release_sample_handle(opened_2dsamples[i]); + opened_2dsamples[i] = NULL; + } + } + + release_existing(); + + _DeleteMP3Entries(); + + if ( nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] != 0 ) + { + AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN]); + nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = 0; + } + + if ( nSampleBankMemoryStartAddress[SAMPLEBANK_PED] != 0 ) + { + AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_PED]); + nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = 0; + } + + if ( DIG ) + { + AIL_close_digital_driver(DIG); + DIG = NULL; + } + + AIL_shutdown(); + + _bSampmanInitialised = false; +} + +bool +cSampleManager::CheckForAnAudioFileOnCD(void) +{ +#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) + char filepath[MAX_PATH]; + +#if defined(GTA3_1_1_PATCH) + if (_bUseHDDAudio) + strcpy(filepath, _aHDDPath); + else + strcpy(filepath, m_szCDRomRootPath); +#else + strcpy(filepath, m_szCDRomRootPath); +#endif // #if defined(GTA3_1_1_PATCH) + + strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]); + + FILE *f = fopen(filepath, "rb"); + + if ( f ) + { + fclose(f); + + return true; + } + + return false; + +#else + return true; +#endif // #if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) +} + +char +cSampleManager::GetCDAudioDriveLetter(void) +{ +#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) + if (_bUseHDDAudio) + { + if ( strlen(_aHDDPath) != 0 ) + return _aHDDPath[0]; + else + return '\0'; + } + else + { + if ( strlen(m_szCDRomRootPath) != 0 ) + return m_szCDRomRootPath[0]; + else + return '\0'; + } +#else + if ( strlen(m_szCDRomRootPath) != 0 ) + return m_szCDRomRootPath[0]; + else + return '\0'; +#endif +} + +void +cSampleManager::UpdateEffectsVolume(void) //[Y], cSampleManager::UpdateSoundBuffers ? +{ + if ( _bSampmanInitialised ) + { + for ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ ) + { + if ( i < MAXCHANNELS ) + { + if ( opened_samples[i] && GetChannelUsedFlag(i) ) + { + if ( nChannelVolume[i] ) + { + AIL_set_3D_sample_volume(opened_samples[i], + m_nEffectsFadeVolume * nChannelVolume[i] * m_nEffectsVolume >> 14); + } + } + } + else + { + if ( opened_2dsamples[i - MAXCHANNELS] ) + { + if ( GetChannelUsedFlag(i - MAXCHANNELS) ) + { + if ( nChannelVolume[i - MAXCHANNELS] ) + { + AIL_set_sample_volume(opened_2dsamples[i - MAXCHANNELS], + m_nEffectsFadeVolume * nChannelVolume[i - MAXCHANNELS] * m_nEffectsVolume >> 14); + } + } + } + } + } + } +} + +void +cSampleManager::SetEffectsMasterVolume(uint8 nVolume) +{ + m_nEffectsVolume = nVolume; + UpdateEffectsVolume(); +} + +void +cSampleManager::SetMusicMasterVolume(uint8 nVolume) +{ + m_nMusicVolume = nVolume; +} + +void +cSampleManager::SetEffectsFadeVolume(uint8 nVolume) +{ + m_nEffectsFadeVolume = nVolume; + UpdateEffectsVolume(); +} + +void +cSampleManager::SetMusicFadeVolume(uint8 nVolume) +{ + m_nMusicFadeVolume = nVolume; +} + +bool +cSampleManager::LoadSampleBank(uint8 nBank) +{ + if ( CTimer::GetIsCodePaused() ) + return false; + + if ( MusicManager.IsInitialised() + && MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && nBank != SAMPLEBANK_MAIN ) + { + return false; + } + + if ( fseek(fpSampleDataHandle, nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 ) + return false; + + if ( fread((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank],fpSampleDataHandle) != nSampleBankSize[nBank] ) + return false; + + bSampleBankLoaded[nBank] = true; + + return true; +} + +void +cSampleManager::UnloadSampleBank(uint8 nBank) +{ + bSampleBankLoaded[nBank] = false; +} + +bool +cSampleManager::IsSampleBankLoaded(uint8 nBank) +{ + return bSampleBankLoaded[nBank]; +} + +bool +cSampleManager::IsPedCommentLoaded(uint32 nComment) +{ + uint8 slot; + + for ( int32 i = 0; i < _TODOCONST(3); i++ ) + { + slot = nCurrentPedSlot - i - 1; + if ( nComment == nPedSlotSfx[slot] ) + return true; + } + + return false; +} + +int32 +cSampleManager::_GetPedCommentSlot(uint32 nComment) +{ + uint8 slot; + + for ( int32 i = 0; i < _TODOCONST(3); i++ ) + { + slot = nCurrentPedSlot - i - 1; + if ( nComment == nPedSlotSfx[slot] ) + return slot; + } + + return -1; +} + +bool +cSampleManager::LoadPedComment(uint32 nComment) +{ + if ( CTimer::GetIsCodePaused() ) + return false; + + // no talking peds during cutsenes or the game end + if ( MusicManager.IsInitialised() ) + { + switch ( MusicManager.GetMusicMode() ) + { + case MUSICMODE_CUTSCENE: + { + return false; + + break; + } + + case MUSICMODE_FRONTEND: + { + if ( MusicManager.GetCurrentTrack() == STREAMED_SOUND_GAME_COMPLETED ) + return false; + + break; + } + } + } + + if ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 ) + return false; + + if ( fread((void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize ) + return false; + + nPedSlotSfxAddr[nCurrentPedSlot] = nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot; + nPedSlotSfx [nCurrentPedSlot] = nComment; + + if ( ++nCurrentPedSlot >= MAX_PEDSFX ) + nCurrentPedSlot = 0; + + return true; +} + +int32 +cSampleManager::GetSampleBaseFrequency(uint32 nSample) +{ + return m_aSamples[nSample].nFrequency; +} + +int32 +cSampleManager::GetSampleLoopStartOffset(uint32 nSample) +{ + return m_aSamples[nSample].nLoopStart; +} + +int32 +cSampleManager::GetSampleLoopEndOffset(uint32 nSample) +{ + return m_aSamples[nSample].nLoopEnd; +} + +uint32 +cSampleManager::GetSampleLength(uint32 nSample) +{ + return m_aSamples[nSample].nSize >> 1; +} + +bool +cSampleManager::UpdateReverb(void) +{ + if ( !usingEAX ) + return false; + + if ( AudioManager.GetFrameCounter() & 15 ) + return false; + + float y = AudioManager.GetReflectionsDistance(REFLECTION_TOP) + AudioManager.GetReflectionsDistance(REFLECTION_BOTTOM); + float x = AudioManager.GetReflectionsDistance(REFLECTION_LEFT) + AudioManager.GetReflectionsDistance(REFLECTION_RIGHT); + float z = AudioManager.GetReflectionsDistance(REFLECTION_UP); + + float normy = norm(y, 5.0f, 40.0f); + float normx = norm(x, 5.0f, 40.0f); + float normz = norm(z, 5.0f, 40.0f); + + float fRatio; + + if ( normy == 0.0f ) + { + if ( normx == 0.0f ) + { + if ( normz == 0.0f ) + fRatio = 0.3f; + else + fRatio = 0.5f; + } + else + { + fRatio = 0.3f; + } + } + else + { + if ( normx == 0.0f ) + { + if ( normz == 0.0f ) + fRatio = 0.3f; + else + fRatio = 0.5f; + } + else + { + if ( normz == 0.0f ) + fRatio = 0.3f; + else + fRatio = (normy+normx+normz) / 3.0f; + } + } + + fRatio = clamp(fRatio, usingEAX3==1 ? 0.0f : 0.30f, 1.0f); + + if ( fRatio == _fPrevEaxRatioDestination ) + return false; + + if ( usingEAX3 ) + { + if ( EAX3ListenerInterpolate(&StartEAX3, &FinishEAX3, fRatio, &EAX3Params, false) ) + { + AIL_set_3D_provider_preference(opened_provider, "EAX all parameters", &EAX3Params); + _fEffectsLevel = 1.0f - fRatio * 0.5f; + } + } + else + { + if ( _usingMilesFast2D ) + _fEffectsLevel = (1.0f - fRatio) * 0.4f; + else + _fEffectsLevel = (1.0f - fRatio) * 0.7f; + } + + _fPrevEaxRatioDestination = fRatio; + + return true; +} + +void +cSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( usingEAX ) + { + if ( nReverbFlag != 0 ) + { + if ( !b2d ) + AIL_set_3D_sample_effects_level(opened_samples[nChannel], _fEffectsLevel); + } + else + { + if ( !b2d ) + AIL_set_3D_sample_effects_level(opened_samples[nChannel], 0.0f); + } + } +} + +bool +cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + int32 addr; + + if ( nSfx < SAMPLEBANK_MAX ) + { + if ( !IsSampleBankLoaded(nBank) ) + return false; + + addr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset; + } + else + { + if ( !IsPedCommentLoaded(nSfx) ) + return false; + + int32 slot = _GetPedCommentSlot(nSfx); + + addr = nPedSlotSfxAddr[slot]; + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + { + AIL_set_sample_address(opened_2dsamples[nChannel - MAXCHANNELS], (void *)addr, m_aSamples[nSfx].nSize); + return true; + } + else + return false; + } + else + { + AILSOUNDINFO info; + + info.format = WAVE_FORMAT_PCM; + info.data_ptr = (void *)addr; + info.channels = 1; + info.data_len = m_aSamples[nSfx].nSize; + info.rate = m_aSamples[nSfx].nFrequency; + info.bits = 16; + + if ( AIL_set_3D_sample_info(opened_samples[nChannel], &info) == 0 ) + { + OutputDebugString(AIL_last_error()); + return false; + } + + return true; + } +} + +void +cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume) +{ + uint32 vol = nVolume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + nChannelVolume[nChannel] = vol; + + // increase the volume for JB.MP3 and S4_BDBD.MP3 + if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD ) + { + nChannelVolume[nChannel] >>= 2; + } + + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_volume(opened_samples[nChannel], m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14); + +} + +void +cSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ) +{ + if ( opened_samples[nChannel] ) + AIL_set_3D_position(opened_samples[nChannel], -fX, fY, fZ); +} + +void +cSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin) +{ + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_distances(opened_samples[nChannel], fMax, fMin); +} + +void +cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume) +{ + uint32 vol = nVolume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + switch ( nChannel ) + { + case CHANNEL2D: + { + nChannelVolume[nChannel] = vol; + + // increase the volume for JB.MP3 and S4_BDBD.MP3 + if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD ) + { + nChannelVolume[nChannel] >>= 2; + } + + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + { + AIL_set_sample_volume(opened_2dsamples[nChannel - MAXCHANNELS], + m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14); + } + + break; + } + } +} + +void +cSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan) +{ + switch ( nChannel ) + { + case CHANNEL2D: + { +#ifndef FIX_BUGS + if ( opened_samples[nChannel - MAXCHANNELS] ) // BUG +#else + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) +#endif + AIL_set_sample_pan(opened_2dsamples[nChannel - MAXCHANNELS], nPan); + + break; + } + } +} + +void +cSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_set_sample_playback_rate(opened_2dsamples[nChannel - MAXCHANNELS], nFreq); + } + else + { + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_playback_rate(opened_samples[nChannel], nFreq); + } +} + +void +cSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_set_sample_loop_block(opened_2dsamples[nChannel - MAXCHANNELS], nLoopStart, nLoopEnd); + } + else + { + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_loop_block(opened_samples[nChannel], nLoopStart, nLoopEnd); + } +} + +void +cSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_set_sample_loop_count(opened_2dsamples[nChannel - MAXCHANNELS], nLoopCount); + } + else + { + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_loop_count(opened_samples[nChannel], nLoopCount); + } +} + +bool +cSampleManager::GetChannelUsedFlag(uint32 nChannel) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + return AIL_sample_status(opened_2dsamples[nChannel - MAXCHANNELS]) == SMP_PLAYING; + else + return false; + } + else + { + if ( opened_samples[nChannel] ) + return AIL_3D_sample_status(opened_samples[nChannel]) == SMP_PLAYING; + else + return false; + } + +} + +void +cSampleManager::StartChannel(uint32 nChannel) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_start_sample(opened_2dsamples[nChannel - MAXCHANNELS]); + } + else + { + if ( opened_samples[nChannel] ) + AIL_start_3D_sample(opened_samples[nChannel]); + } +} + +void +cSampleManager::StopChannel(uint32 nChannel) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_end_sample(opened_2dsamples[nChannel - MAXCHANNELS]); + } + else + { + if ( opened_samples[nChannel] ) + { + if ( AIL_3D_sample_status(opened_samples[nChannel]) == SMP_PLAYING ) + AIL_end_3D_sample(opened_samples[nChannel]); + } + } +} + +void +cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( nFile < TOTAL_STREAMED_SOUNDS ) + { + if ( mp3Stream[nStream] ) + { + AIL_pause_stream(mp3Stream[nStream], 1); + AIL_close_stream(mp3Stream[nStream]); + } + + char filepath[MAX_PATH]; + + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[nFile]); + + mp3Stream[nStream] = AIL_open_stream(DIG, filepath, 0); + + if ( mp3Stream[nStream] ) + { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_service_stream(mp3Stream[nStream], 1); + } + else + OutputDebugString(AIL_last_error()); + } + } +} + +void +cSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + AIL_pause_stream(mp3Stream[nStream], nPauseFlag != 0); + } +} + +void +cSampleManager::StartPreloadedStreamedFile(uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + AIL_start_stream(mp3Stream[nStream]); + } +} + +bool +cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) +{ + uint32 position = nPos; + char filename[MAX_PATH]; + + if ( m_bInitialised && nFile < TOTAL_STREAMED_SOUNDS ) + { + if ( mp3Stream[nStream] ) + { + AIL_pause_stream(mp3Stream[nStream], 1); + AIL_close_stream(mp3Stream[nStream]); + } + + if ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER ) + { + uint32 i = 0; + do { + if(i != 0 || _bIsMp3Active) { + if(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0; + + _CurMP3Pos = 0; + + tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); + + if(mp3) { + mp3 = _pMP3List; + if(mp3 == NULL) { + _bIsMp3Active = false; + nFile = 0; + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count( + mp3Stream[nStream], 1); + AIL_set_stream_ms_position( + mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], + 0); + return true; + } + + return false; + } + } + + if(mp3->pLinkPath != NULL) + mp3Stream[nStream] = + AIL_open_stream(DIG, mp3->pLinkPath, 0); + else { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, mp3->aFilename); + + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + } + + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], 0); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + _bIsMp3Active = false; + continue; + } + if ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] ) + position = 0; + + tMP3Entry *e; + if ( !_GetMP3PosFromStreamPos(&position, &e) ) + { + if ( e == NULL ) + { + nFile = 0; + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count( + mp3Stream[nStream], 1); + AIL_set_stream_ms_position( + mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + return false; + } + } + + if ( e->pLinkPath != NULL ) + mp3Stream[nStream] = AIL_open_stream(DIG, e->pLinkPath, 0); + else + { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, e->aFilename); + + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + } + + if ( mp3Stream[nStream] ) + { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], 0); + + _bIsMp3Active = true; + + return true; + } + + _bIsMp3Active = false; + + } while(++i < nNumMP3s); + + position = 0; + nFile = 0; + } + + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + if ( mp3Stream[nStream] ) + { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + } + + return false; +} + +void +cSampleManager::StopStreamedFile(uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + { + AIL_pause_stream(mp3Stream[nStream], 1); + + AIL_close_stream(mp3Stream[nStream]); + mp3Stream[nStream] = NULL; + + if ( nStream == 0 ) + _bIsMp3Active = false; + } + } +} + +int32 +cSampleManager::GetStreamedFilePosition(uint8 nStream) +{ + S32 currentms; + + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + { + if ( _bIsMp3Active ) + { + tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); + + if ( mp3 != NULL ) + { + AIL_stream_ms_position(mp3Stream[nStream], NULL, ¤tms); + return currentms + mp3->nTrackStreamPos; + } + else + return 0; + } + else + { + AIL_stream_ms_position(mp3Stream[nStream], NULL, ¤tms); + return currentms; + } + } + } + + return 0; +} + +void +cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream) +{ + uint8 vol = nVolume; + + if ( m_bInitialised ) + { + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + nStreamVolume[nStream] = vol; + nStreamPan[nStream] = nPan; + + if ( mp3Stream[nStream] ) + { + if ( nEffectFlag ) + AIL_set_stream_volume(mp3Stream[nStream], m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14); + else + AIL_set_stream_volume(mp3Stream[nStream], m_nMusicFadeVolume*vol*m_nMusicVolume >> 14); + + AIL_set_stream_pan(mp3Stream[nStream], nPan); + } + } +} + +int32 +cSampleManager::GetStreamedFileLength(uint8 nStream) +{ + if ( m_bInitialised ) + return nStreamLength[nStream]; + + return 0; +} + +bool +cSampleManager::IsStreamPlaying(uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + { + if ( AIL_stream_status(mp3Stream[nStream]) == SMP_PLAYING ) + return true; + else + return false; + } + } + + return false; +} + +bool +cSampleManager::InitialiseSampleBanks(void) +{ + int32 nBank = SAMPLEBANK_MAIN; + + fpSampleDescHandle = fopen(SampleBankDescFilename, "rb"); + if ( fpSampleDescHandle == NULL ) + return false; + + fpSampleDataHandle = fopen(SampleBankDataFilename, "rb"); + if ( fpSampleDataHandle == NULL ) + { + fclose(fpSampleDescHandle); + fpSampleDescHandle = NULL; + + return false; + } + + fseek(fpSampleDataHandle, 0, SEEK_END); + _nSampleDataEndOffset = ftell(fpSampleDataHandle); + rewind(fpSampleDataHandle); + + fread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle); + + fclose(fpSampleDescHandle); + fpSampleDescHandle = NULL; + + for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) + { +#ifdef FIX_BUGS + if (nBank >= MAX_SAMPLEBANKS) break; +#endif + if ( BankStartOffset[nBank] == BankStartOffset[SAMPLEBANK_MAIN] + i ) + { + nSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset; + nBank++; + } + } + + nSampleBankSize[SAMPLEBANK_MAIN] = nSampleBankDiscStartOffset[SAMPLEBANK_PED] - nSampleBankDiscStartOffset[SAMPLEBANK_MAIN]; + nSampleBankSize[SAMPLEBANK_PED] = _nSampleDataEndOffset - nSampleBankDiscStartOffset[SAMPLEBANK_PED]; + + return true; +} diff --git a/src/audio/miles/sampman_mss.h b/src/audio/miles/sampman_mss.h new file mode 100644 index 00000000..ebedfb63 --- /dev/null +++ b/src/audio/miles/sampman_mss.h @@ -0,0 +1,339 @@ +#pragma once +#include "common.h" +#include "AudioSamples.h" + +#define MAX_VOLUME 127 + +struct tSample { + int32 nOffset; + uint32 nSize; + int32 nFrequency; + int32 nLoopStart; + int32 nLoopEnd; +}; + +enum +{ + SAMPLEBANK_MAIN, + SAMPLEBANK_PED, + MAX_SAMPLEBANKS, + SAMPLEBANK_INVALID +}; + +#define MAX_PEDSFX 7 +#define PED_BLOCKSIZE 79000 + +#define MAXPROVIDERS 64 + +#define MAXCHANNELS 28 +#define MAXCHANNELS_SURROUND 24 +#define MAX2DCHANNELS 1 +#define CHANNEL2D MAXCHANNELS + +#define MAX_MP3STREAMS 2 + +#define DIGITALRATE 32000 +#define DIGITALBITS 16 +#define DIGITALCHANNELS 2 + +#define MAX_DIGITAL_MIXER_CHANNELS 32 + +class cSampleManager +{ + uint8 m_nEffectsVolume; + uint8 m_nMusicVolume; + uint8 m_nEffectsFadeVolume; + uint8 m_nMusicFadeVolume; + uint8 m_nMonoMode; + char unk; + char m_szCDRomRootPath[80]; + bool m_bInitialised; + uint8 m_nNumberOfProviders; + char *m_aAudioProviders[MAXPROVIDERS]; + tSample m_aSamples[TOTAL_AUDIO_SAMPLES]; + +public: + + + + cSampleManager(void) : + m_nNumberOfProviders(0) + { } + + ~cSampleManager(void) + { } + + void SetSpeakerConfig(int32 nConfig); + uint32 GetMaximumSupportedChannels(void); + + uint32 GetNum3DProvidersAvailable() { return m_nNumberOfProviders; } + void SetNum3DProvidersAvailable(uint32 num) { m_nNumberOfProviders = num; } + + char *Get3DProviderName(uint8 id) { return m_aAudioProviders[id]; } + void Set3DProviderName(uint8 id, char *name) { m_aAudioProviders[id] = name; } + + int8 GetCurrent3DProviderIndex(void); + int8 SetCurrent3DProvider(uint8 which); + + bool IsMP3RadioChannelAvailable(void); + + void ReleaseDigitalHandle (void); + void ReacquireDigitalHandle(void); + + bool Initialise(void); + void Terminate (void); + + bool CheckForAnAudioFileOnCD(void); + char GetCDAudioDriveLetter (void); + + void UpdateEffectsVolume(void); + + void SetEffectsMasterVolume(uint8 nVolume); + void SetMusicMasterVolume (uint8 nVolume); + void SetEffectsFadeVolume (uint8 nVolume); + void SetMusicFadeVolume (uint8 nVolume); + + bool LoadSampleBank (uint8 nBank); + void UnloadSampleBank (uint8 nBank); + bool IsSampleBankLoaded(uint8 nBank); + + bool IsPedCommentLoaded(uint32 nComment); + bool LoadPedComment (uint32 nComment); + + int32 _GetPedCommentSlot(uint32 nComment); + + int32 GetSampleBaseFrequency (uint32 nSample); + int32 GetSampleLoopStartOffset(uint32 nSample); + int32 GetSampleLoopEndOffset (uint32 nSample); + uint32 GetSampleLength (uint32 nSample); + + bool UpdateReverb(void); + + void SetChannelReverbFlag (uint32 nChannel, uint8 nReverbFlag); + bool InitialiseChannel (uint32 nChannel, uint32 nSfx, uint8 nBank); + void SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume); + void SetChannel3DPosition (uint32 nChannel, float fX, float fY, float fZ); + void SetChannel3DDistances (uint32 nChannel, float fMax, float fMin); + void SetChannelVolume (uint32 nChannel, uint32 nVolume); + void SetChannelPan (uint32 nChannel, uint32 nPan); + void SetChannelFrequency (uint32 nChannel, uint32 nFreq); + void SetChannelLoopPoints (uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd); + void SetChannelLoopCount (uint32 nChannel, uint32 nLoopCount); + bool GetChannelUsedFlag (uint32 nChannel); + void StartChannel (uint32 nChannel); + void StopChannel (uint32 nChannel); + + void PreloadStreamedFile (uint8 nFile, uint8 nStream); + void PauseStream (uint8 nPauseFlag, uint8 nStream); + void StartPreloadedStreamedFile (uint8 nStream); + bool StartStreamedFile (uint8 nFile, uint32 nPos, uint8 nStream); + void StopStreamedFile (uint8 nStream); + int32 GetStreamedFilePosition (uint8 nStream); + void SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream); + int32 GetStreamedFileLength (uint8 nStream); + bool IsStreamPlaying (uint8 nStream); + bool InitialiseSampleBanks(void); +}; + +extern cSampleManager SampleManager; +extern int32 BankStartOffset[MAX_SAMPLEBANKS]; + +static char StreamedNameTable[][25]= +{ + "AUDIO\\HEAD.WAV", + "AUDIO\\CLASS.WAV", + "AUDIO\\KJAH.WAV", + "AUDIO\\RISE.WAV", + "AUDIO\\LIPS.WAV", + "AUDIO\\GAME.WAV", + "AUDIO\\MSX.WAV", + "AUDIO\\FLASH.WAV", + "AUDIO\\CHAT.WAV", + "AUDIO\\HEAD.WAV", + "AUDIO\\POLICE.WAV", + "AUDIO\\CITY.WAV", + "AUDIO\\WATER.WAV", + "AUDIO\\COMOPEN.WAV", + "AUDIO\\SUBOPEN.WAV", + "AUDIO\\JB.MP3", + "AUDIO\\BET.MP3", + "AUDIO\\L1_LG.MP3", + "AUDIO\\L2_DSB.MP3", + "AUDIO\\L3_DM.MP3", + "AUDIO\\L4_PAP.MP3", + "AUDIO\\L5_TFB.MP3", + "AUDIO\\J0_DM2.MP3", + "AUDIO\\J1_LFL.MP3", + "AUDIO\\J2_KCL.MP3", + "AUDIO\\J3_VH.MP3", + "AUDIO\\J4_ETH.MP3", + "AUDIO\\J5_DST.MP3", + "AUDIO\\J6_TBJ.MP3", + "AUDIO\\T1_TOL.MP3", + "AUDIO\\T2_TPU.MP3", + "AUDIO\\T3_MAS.MP3", + "AUDIO\\T4_TAT.MP3", + "AUDIO\\T5_BF.MP3", + "AUDIO\\S0_MAS.MP3", + "AUDIO\\S1_PF.MP3", + "AUDIO\\S2_CTG.MP3", + "AUDIO\\S3_RTC.MP3", + "AUDIO\\S5_LRQ.MP3", + "AUDIO\\S4_BDBA.MP3", + "AUDIO\\S4_BDBB.MP3", + "AUDIO\\S2_CTG2.MP3", + "AUDIO\\S4_BDBD.MP3", + "AUDIO\\S5_LRQB.MP3", + "AUDIO\\S5_LRQC.MP3", + "AUDIO\\A1_SSO.WAV", + "AUDIO\\A2_PP.WAV", + "AUDIO\\A3_SS.WAV", + "AUDIO\\A4_PDR.WAV", + "AUDIO\\A5_K2FT.WAV", + "AUDIO\\K1_KBO.MP3", + "AUDIO\\K2_GIS.MP3", + "AUDIO\\K3_DS.MP3", + "AUDIO\\K4_SHI.MP3", + "AUDIO\\K5_SD.MP3", + "AUDIO\\R0_PDR2.MP3", + "AUDIO\\R1_SW.MP3", + "AUDIO\\R2_AP.MP3", + "AUDIO\\R3_ED.MP3", + "AUDIO\\R4_GF.MP3", + "AUDIO\\R5_PB.MP3", + "AUDIO\\R6_MM.MP3", + "AUDIO\\D1_STOG.MP3", + "AUDIO\\D2_KK.MP3", + "AUDIO\\D3_ADO.MP3", + "AUDIO\\D5_ES.MP3", + "AUDIO\\D7_MLD.MP3", + "AUDIO\\D4_GTA.MP3", + "AUDIO\\D4_GTA2.MP3", + "AUDIO\\D6_STS.MP3", + "AUDIO\\A6_BAIT.WAV", + "AUDIO\\A7_ETG.WAV", + "AUDIO\\A8_PS.WAV", + "AUDIO\\A9_ASD.WAV", + "AUDIO\\K4_SHI2.MP3", + "AUDIO\\C1_TEX.MP3", + "AUDIO\\EL_PH1.MP3", + "AUDIO\\EL_PH2.MP3", + "AUDIO\\EL_PH3.MP3", + "AUDIO\\EL_PH4.MP3", + "AUDIO\\YD_PH1.MP3", + "AUDIO\\YD_PH2.MP3", + "AUDIO\\YD_PH3.MP3", + "AUDIO\\YD_PH4.MP3", + "AUDIO\\HD_PH1.MP3", + "AUDIO\\HD_PH2.MP3", + "AUDIO\\HD_PH3.MP3", + "AUDIO\\HD_PH4.MP3", + "AUDIO\\HD_PH5.MP3", + "AUDIO\\MT_PH1.MP3", + "AUDIO\\MT_PH2.MP3", + "AUDIO\\MT_PH3.MP3", + "AUDIO\\MT_PH4.MP3", + "AUDIO\\MISCOM.WAV", + "AUDIO\\END.MP3", + "AUDIO\\lib_a1.WAV", + "AUDIO\\lib_a2.WAV", + "AUDIO\\lib_a.WAV", + "AUDIO\\lib_b.WAV", + "AUDIO\\lib_c.WAV", + "AUDIO\\lib_d.WAV", + "AUDIO\\l2_a.WAV", + "AUDIO\\j4t_1.WAV", + "AUDIO\\j4t_2.WAV", + "AUDIO\\j4t_3.WAV", + "AUDIO\\j4t_4.WAV", + "AUDIO\\j4_a.WAV", + "AUDIO\\j4_b.WAV", + "AUDIO\\j4_c.WAV", + "AUDIO\\j4_d.WAV", + "AUDIO\\j4_e.WAV", + "AUDIO\\j4_f.WAV", + "AUDIO\\j6_1.WAV", + "AUDIO\\j6_a.WAV", + "AUDIO\\j6_b.WAV", + "AUDIO\\j6_c.WAV", + "AUDIO\\j6_d.WAV", + "AUDIO\\t4_a.WAV", + "AUDIO\\s1_a.WAV", + "AUDIO\\s1_a1.WAV", + "AUDIO\\s1_b.WAV", + "AUDIO\\s1_c.WAV", + "AUDIO\\s1_c1.WAV", + "AUDIO\\s1_d.WAV", + "AUDIO\\s1_e.WAV", + "AUDIO\\s1_f.WAV", + "AUDIO\\s1_g.WAV", + "AUDIO\\s1_h.WAV", + "AUDIO\\s1_i.WAV", + "AUDIO\\s1_j.WAV", + "AUDIO\\s1_k.WAV", + "AUDIO\\s1_l.WAV", + "AUDIO\\s3_a.WAV", + "AUDIO\\s3_b.WAV", + "AUDIO\\el3_a.WAV", + "AUDIO\\mf1_a.WAV", + "AUDIO\\mf2_a.WAV", + "AUDIO\\mf3_a.WAV", + "AUDIO\\mf3_b.WAV", + "AUDIO\\mf3_b1.WAV", + "AUDIO\\mf3_c.WAV", + "AUDIO\\mf4_a.WAV", + "AUDIO\\mf4_b.WAV", + "AUDIO\\mf4_c.WAV", + "AUDIO\\a1_a.WAV", + "AUDIO\\a3_a.WAV", + "AUDIO\\a5_a.WAV", + "AUDIO\\a4_a.WAV", + "AUDIO\\a4_b.WAV", + "AUDIO\\a4_c.WAV", + "AUDIO\\a4_d.WAV", + "AUDIO\\k1_a.WAV", + "AUDIO\\k3_a.WAV", + "AUDIO\\r1_a.WAV", + "AUDIO\\r2_a.WAV", + "AUDIO\\r2_b.WAV", + "AUDIO\\r2_c.WAV", + "AUDIO\\r2_d.WAV", + "AUDIO\\r2_e.WAV", + "AUDIO\\r2_f.WAV", + "AUDIO\\r2_g.WAV", + "AUDIO\\r2_h.WAV", + "AUDIO\\r5_a.WAV", + "AUDIO\\r6_a.WAV", + "AUDIO\\r6_a1.WAV", + "AUDIO\\r6_b.WAV", + "AUDIO\\lo2_a.WAV", + "AUDIO\\lo6_a.WAV", + "AUDIO\\yd2_a.WAV", + "AUDIO\\yd2_b.WAV", + "AUDIO\\yd2_c.WAV", + "AUDIO\\yd2_c1.WAV", + "AUDIO\\yd2_d.WAV", + "AUDIO\\yd2_e.WAV", + "AUDIO\\yd2_f.WAV", + "AUDIO\\yd2_g.WAV", + "AUDIO\\yd2_h.WAV", + "AUDIO\\yd2_ass.WAV", + "AUDIO\\yd2_ok.WAV", + "AUDIO\\h5_a.WAV", + "AUDIO\\h5_b.WAV", + "AUDIO\\h5_c.WAV", + "AUDIO\\ammu_a.WAV", + "AUDIO\\ammu_b.WAV", + "AUDIO\\ammu_c.WAV", + "AUDIO\\door_1.WAV", + "AUDIO\\door_2.WAV", + "AUDIO\\door_3.WAV", + "AUDIO\\door_4.WAV", + "AUDIO\\door_5.WAV", + "AUDIO\\door_6.WAV", + "AUDIO\\t3_a.WAV", + "AUDIO\\t3_b.WAV", + "AUDIO\\t3_c.WAV", + "AUDIO\\k1_b.WAV", + "AUDIO\\cat1.WAV" +}; diff --git a/src/audio/openal/samp_oal.cpp b/src/audio/openal/samp_oal.cpp new file mode 100644 index 00000000..e8213cd9 --- /dev/null +++ b/src/audio/openal/samp_oal.cpp @@ -0,0 +1,1404 @@ +#include +#include +#include +//#include +#include +#include +#include "samp_oal.h" +#include "AudioManager.h" +#include "MusicManager.h" +#include "Frontend.h" +#include "Timer.h" + +#pragma comment( lib, "libmpg123.lib" ) +#pragma comment( lib, "OpenAL32.lib" ) + +cSampleManager SampleManager; +int32 BankStartOffset[MAX_SAMPLEBANKS]; + + +/////////////////////////////////////////////////////////////// +class MP3Stream +{ +public: + mpg123_handle *m_pMPG; + FILE *m_fpFile; + unsigned char *m_pBuf; + char m_aFilename[128]; + size_t m_nBufSize; + size_t m_nLengthInBytes; + long m_nRate; + int m_nBitRate; + int m_nChannels; + int m_nEncoding; + int m_nLength; + int m_nBlockSize; + int m_nNumBlocks; + ALuint m_alSource; + ALuint m_alBuffers[5]; + unsigned char *m_pBlocks; + bool m_bIsFree; + bool m_bIsOpened; + bool m_bIsPaused; + int m_nVolume; + + void Initialize(void); + bool FillBuffer(ALuint alBuffer); + void Update(void); + void SetPos(uint32 nPos); + int32 FillBuffers(); + MP3Stream(char *filename, ALuint source, ALuint *buffers); + ~MP3Stream() { Delete(); } + void Delete(); + +}; +/////////////////////////////////////////////////////////////// + +char SampleBankDescFilename[] = "AUDIO\\SFX.SDT"; +char SampleBankDataFilename[] = "AUDIO\\SFX.RAW"; + +FILE *fpSampleDescHandle; +FILE *fpSampleDataHandle; +bool bSampleBankLoaded [MAX_SAMPLEBANKS]; +int32 nSampleBankDiscStartOffset [MAX_SAMPLEBANKS]; +int32 nSampleBankSize [MAX_SAMPLEBANKS]; +int32 nSampleBankMemoryStartAddress[MAX_SAMPLEBANKS]; +int32 _nSampleDataEndOffset; + +int32 nPedSlotSfx [MAX_PEDSFX]; +int32 nPedSlotSfxAddr[MAX_PEDSFX]; +uint8 nCurrentPedSlot; + + + +uint32 nStreamLength[TOTAL_STREAMED_SOUNDS]; + +/////////////////////////////////////////////////////////////// +ALuint alChannel[MAXCHANNELS+MAX2DCHANNELS]; +ALuint ALStreamSources[MAX_STREAMS]; +ALuint ALStreamBuffers[MAX_STREAMS][5]; +struct +{ + ALuint buffer; + ALuint timer; +}ALBuffers[SAMPLEBANK_MAX]; + +ALuint pedBuffers[MAX_PEDSFX]; +//bank0Buffers + +uint32 nNumMP3s; + +MP3Stream *mp3Stream[MAX_STREAMS]; +int8 nStreamPan [MAX_STREAMS]; +int8 nStreamVolume[MAX_STREAMS]; + +float ChannelPitch[MAXCHANNELS+MAX2DCHANNELS]; +uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS]; +uint32 ChannelSample[MAXCHANNELS+MAX2DCHANNELS]; +int32 currentChannelMaxFrontDistance[MAXCHANNELS+MAX2DCHANNELS]; +int32 currentChannelFrequency[MAXCHANNELS+MAX2DCHANNELS]; +int32 currentChannelVolume[MAXCHANNELS+MAX2DCHANNELS]; + + +cSampleManager::cSampleManager(void) +{ + ; +} + +cSampleManager::~cSampleManager(void) +{ + ASSERT((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_PED] == NULL); + free((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_PED]); + + if ( fpSampleDescHandle != NULL ) + { + fclose(fpSampleDescHandle); + fpSampleDescHandle = NULL; + } + + if ( fpSampleDataHandle != NULL ) + { + fclose(fpSampleDataHandle); + fpSampleDataHandle = NULL; + } +} + +void cSampleManager::SetSpeakerConfig(int32 nConfig) +{ + +} + +uint32 cSampleManager::GetMaximumSupportedChannels(void) +{ + return 20; +} + +uint32 cSampleManager::GetNum3DProvidersAvailable() +{ + return 1; +} + +void cSampleManager::SetNum3DProvidersAvailable(uint32 num) +{ + ; +} + +char *cSampleManager::Get3DProviderName(uint8 id) +{ + static char PROVIDER[256] = "OpenAL"; + return PROVIDER; +} + +void cSampleManager::Set3DProviderName(uint8 id, char *name) +{ + ; +} + +int8 cSampleManager::GetCurrent3DProviderIndex(void) +{ + return 0; +} + +int8 cSampleManager::SetCurrent3DProvider(uint8 which) +{ + return 0; +} + +bool +cSampleManager::IsMP3RadioChannelAvailable(void) +{ + return nNumMP3s != 0; +} + + +void cSampleManager::ReleaseDigitalHandle(void) +{ + +} + +void cSampleManager::ReacquireDigitalHandle(void) +{ + +} + +bool +cSampleManager::Initialise(void) +{ + ALCint attr[] = {ALC_FREQUENCY,MAX_FREQ,0}; + + m_pDevice = alcOpenDevice(NULL); + ASSERT(m_pDevice != NULL); + + m_pContext = alcCreateContext(m_pDevice, attr); + ASSERT(m_pContext != NULL); + + alcMakeContextCurrent(m_pContext); + + mpg123_init(); + + + + for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) + { + m_aSamples[i].nOffset = 0; + m_aSamples[i].nSize = 0; + m_aSamples[i].nFrequency = MAX_FREQ; + m_aSamples[i].nLoopStart = 0; + m_aSamples[i].nLoopEnd = -1; + } + + for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) + nStreamLength[i] = 3600000; + + for ( int32 i = 0; i < MAX_STREAMS; i++ ) + { + mp3Stream[i] = NULL; + nStreamVolume[i] = 100; + nStreamPan[i] = 63; + } + + alGenSources(MAX_STREAMS, (ALuint *)ALStreamSources); + alGenBuffers(MAX_STREAMS*5, (ALuint *)ALStreamBuffers); + + m_nMonoMode = 0; + + m_nEffectsVolume = MAX_VOLUME; + m_nMusicVolume = MAX_VOLUME; + m_nEffectsFadeVolume = MAX_VOLUME; + m_nMusicFadeVolume = MAX_VOLUME; + + + memset(alChannel, 0, sizeof(alChannel)); + memset(nChannelVolume, 0, sizeof(nChannelVolume)); + memset(ChannelSample, 0, sizeof(ChannelSample)); + + for ( int32 i = 0; i < ARRAY_SIZE(ChannelPitch); i++ ) + ChannelPitch[i] = 1.0f; + + + fpSampleDescHandle = NULL; + fpSampleDataHandle = NULL; + + for ( int32 i = 0; i < MAX_SAMPLEBANKS; i++ ) + { + bSampleBankLoaded[i] = false; + nSampleBankDiscStartOffset[i] = 0; + nSampleBankSize[i] = 0; + nSampleBankMemoryStartAddress[i] = 0; + } + + alGenBuffers(MAX_PEDSFX, pedBuffers); + + for ( int32 i = 0; i < MAX_PEDSFX; i++ ) + { + nPedSlotSfx[i] = NO_SAMPLE; + nPedSlotSfxAddr[i] = 0; + } + + nCurrentPedSlot = 0; + + for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ ) + { + ALBuffers[i].buffer = 0; + ALBuffers[i].timer = 0; + } + + alListenerf (AL_GAIN, 1.0f); + alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f); + alListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f); + ALfloat orientation[6] = { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; + alListenerfv(AL_ORIENTATION, orientation); + + if ( !InitialiseSampleBanks() ) + { + Terminate(); + return false; + } + + nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = (int32)malloc(nSampleBankSize[SAMPLEBANK_MAIN]); + ASSERT(nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] != NULL); + + if ( nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] == NULL ) + { + Terminate(); + return false; + } + + nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = (int32)malloc(PED_BLOCKSIZE*MAX_PEDSFX); + ASSERT(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] != NULL); + + alGenSources(MAXCHANNELS, alChannel); + for ( int32 i = 0; i < MAXCHANNELS; i++ ) + { + if ( alChannel[i] ) + alSourcei(alChannel[i], AL_SOURCE_RELATIVE, AL_TRUE); + } + + alGenSources(MAX2DCHANNELS, &alChannel[CHANNEL2D]); + if ( alChannel[CHANNEL2D] ) + { + alSourcei (alChannel[CHANNEL2D], AL_SOURCE_RELATIVE, AL_TRUE); + alSource3f(alChannel[CHANNEL2D], AL_POSITION, 0.0f, 0.0f, 0.0f); + alSourcef (alChannel[CHANNEL2D], AL_GAIN, 1.0f); + } + + LoadSampleBank(SAMPLEBANK_MAIN); + + return true; +} + +void +cSampleManager::Terminate(void) +{ + mpg123_exit(); + alcMakeContextCurrent(NULL); + alcDestroyContext(m_pContext); + alcCloseDevice(m_pDevice); +} + +void +cSampleManager::UpdateSoundBuffers(void) +{ + for ( int32 i = 0; i < SAMPLEBANK_MAX; i++ ) + { + if ( ALBuffers[i].timer > 0 ) + { + ALBuffers[i].timer -= ALuint(CTimer::GetTimeStep() * 20.0f); + + if ( ALBuffers[i].timer <= 0 ) + { + if ( ALBuffers[i].buffer != 0 && alIsBuffer(ALBuffers[i].buffer) ) + { + alDeleteBuffers(1, &ALBuffers[i].buffer); + + if ( alGetError() == AL_NO_ERROR ) + ALBuffers[i].buffer = 0; + else + ALBuffers[i].buffer = 120000; + } + } + } + } +} + +bool cSampleManager::CheckForAnAudioFileOnCD(void) +{ + return true; +} + +char cSampleManager::GetCDAudioDriveLetter(void) +{ + return '\0'; +} + +void +cSampleManager::SetEffectsMasterVolume(uint8 nVolume) +{ + m_nEffectsVolume = nVolume; +} + +void +cSampleManager::SetMusicMasterVolume(uint8 nVolume) +{ + m_nMusicVolume = nVolume; +} + +void +cSampleManager::SetEffectsFadeVolume(uint8 nVolume) +{ + m_nEffectsFadeVolume = nVolume; +} + +void +cSampleManager::SetMusicFadeVolume(uint8 nVolume) +{ + m_nMusicFadeVolume = nVolume; +} + +void +cSampleManager::SetMonoMode(uint8 nMode) +{ + m_nMonoMode = nMode; +} + +bool +cSampleManager::LoadSampleBank(uint8 nBank) +{ + ASSERT( nBank < MAX_SAMPLEBANKS ); + + if ( CTimer::GetIsCodePaused() ) + return false; + + if ( MusicManager.IsInitialised() + && MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && nBank != SAMPLEBANK_MAIN ) + { + return false; + } + + if ( fseek(fpSampleDataHandle, nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 ) + return false; + + if ( fread((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank], fpSampleDataHandle) != nSampleBankSize[nBank] ) + return false; + + bSampleBankLoaded[nBank] = true; + + return true; +} + +void +cSampleManager::UnloadSampleBank(uint8 nBank) +{ + ASSERT( nBank < MAX_SAMPLEBANKS ); + + ; // NOIMP +} + +bool +cSampleManager::IsSampleBankLoaded(uint8 nBank) +{ + ASSERT( nBank < MAX_SAMPLEBANKS ); + return true; +} + +bool +cSampleManager::IsPedCommentLoaded(uint32 nComment) +{ + ASSERT( nComment < TOTAL_AUDIO_SAMPLES ); + + uint8 slot; + + for ( int32 i = 0; i < _TODOCONST(3); i++ ) + { + slot = nCurrentPedSlot - i - 1; + if ( nComment == nPedSlotSfx[slot] ) + return true; + } + + return false; +} + + +int32 +cSampleManager::_GetPedCommentSlot(uint32 nComment) +{ + uint8 slot; + + for (int32 i = 0; i < _TODOCONST(3); i++) + { + slot = nCurrentPedSlot - i - 1; + if (nComment == nPedSlotSfx[slot]) + return slot; + } + + return -1; +} + +bool +cSampleManager::LoadPedComment(uint32 nComment) +{ + ASSERT( nComment < TOTAL_AUDIO_SAMPLES ); + + if ( CTimer::GetIsCodePaused() ) + return false; + + // no talking peds during cutsenes or the game end + if ( MusicManager.IsInitialised() ) + { + switch ( MusicManager.GetMusicMode() ) + { + case MUSICMODE_CUTSCENE: + { + return false; + + break; + } + + case MUSICMODE_FRONTEND: + { + if ( MusicManager.GetCurrentTrack() == STREAMED_SOUND_GAME_COMPLETED ) + return false; + + break; + } + } + } + + if ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 ) + return false; + + if ( fread((void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize ) + return false; + + nPedSlotSfx[nCurrentPedSlot] = nComment; + + alBufferData(pedBuffers[nCurrentPedSlot], + AL_FORMAT_MONO16, + (void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot), + m_aSamples[nComment].nSize, + MAX_FREQ); + + if ( ++nCurrentPedSlot >= MAX_PEDSFX ) + nCurrentPedSlot = 0; + + return true; +} + +int32 +cSampleManager::GetBankContainingSound(uint32 offset) +{ + if ( offset >= BankStartOffset[SAMPLEBANK_PED] ) + return SAMPLEBANK_PED; + + if ( offset >= BankStartOffset[SAMPLEBANK_MAIN] ) + return SAMPLEBANK_MAIN; + + return SAMPLEBANK_INVALID; +} + +int32 +cSampleManager::GetSampleBaseFrequency(uint32 nSample) +{ + ASSERT( nSample < TOTAL_AUDIO_SAMPLES ); + return m_aSamples[nSample].nFrequency; +} + +int32 +cSampleManager::GetSampleLoopStartOffset(uint32 nSample) +{ + ASSERT( nSample < TOTAL_AUDIO_SAMPLES ); + return m_aSamples[nSample].nLoopStart; +} + +int32 +cSampleManager::GetSampleLoopEndOffset(uint32 nSample) +{ + ASSERT( nSample < TOTAL_AUDIO_SAMPLES ); + return m_aSamples[nSample].nLoopEnd; +} + +uint32 +cSampleManager::GetSampleLength(uint32 nSample) +{ + ASSERT( nSample < TOTAL_AUDIO_SAMPLES ); + return m_aSamples[nSample].nSize >> 1; +} + +bool cSampleManager::UpdateReverb(void) +{ + return false; +} + +void +cSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag) +{ + ; // NOIMP +} + +bool +cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + ALuint buffer; + + if ( nSfx < SAMPLEBANK_MAX ) + { + int32 offset = (m_aSamples[nSfx].nLoopStart > 0) ? (m_aSamples[nSfx].nOffset - m_aSamples[nSfx].nLoopStart) : m_aSamples[nSfx].nOffset; + int32 size = (m_aSamples[nSfx].nLoopStart > 0) ? (m_aSamples[nSfx].nLoopEnd - m_aSamples[nSfx].nLoopStart) : m_aSamples[nSfx].nSize; + + void *data = malloc(size); + ASSERT(data != NULL); + + if ( fseek(fpSampleDataHandle, offset + nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 ) + { + free(data); + return false; + } + + if ( fread(data, 1, size, fpSampleDataHandle) != size ) + { + free(data); + return false; + } + + ALuint buf; + alGenBuffers(1, &buf); + alBufferData(buf, AL_FORMAT_MONO16, data, size, MAX_FREQ); + free(data); + + if ( !IsSampleBankLoaded(nBank) ) + return false; + + ALBuffers[nSfx].buffer = buf; + ALBuffers[nSfx].timer = 120000; + + buffer = ALBuffers[nSfx].buffer; + + ChannelSample[nChannel] = nSfx; + } + else + { + if ( !IsPedCommentLoaded(nSfx) ) + return false; + + int32 slot = _GetPedCommentSlot(nSfx); + + buffer = pedBuffers[slot]; + } + + if ( buffer == 0 ) + { + TRACE("No buffer to play id %d", nSfx); + return false; + } + + if ( GetChannelUsedFlag(nChannel) ) + { + TRACE("Stopping channel %d - really!!!", nChannel); + StopChannel(nChannel); + } + + alSourcei(alChannel[nChannel], AL_BUFFER, 0); + currentChannelVolume [nChannel] = -1; + currentChannelFrequency [nChannel] = -1; + currentChannelMaxFrontDistance[nChannel] = -1; + + if ( alChannel[nChannel] ) + { + alSourcei(alChannel[nChannel], AL_BUFFER, buffer); + alSourcef(alChannel[nChannel], AL_PITCH, 1.0f); + ChannelPitch[nChannel] = 1.0f; + return true; + } + + return false; +} + +void +cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + uint32 vol = nVolume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + nChannelVolume[nChannel] = vol; + + // reduce the volume for JB.MP3 and S4_BDBD.MP3 + if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD ) + { + nChannelVolume[nChannel] >>= 2; + } + + uint32 channelVol = m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14; + if ( ChannelSample[nChannel] >= SFX_CAR_REV_1 && SFX_CAR_REV_10 >= ChannelSample[nChannel] ) // nice hack + channelVol >>= 1; + + if ( alChannel[nChannel] ) + { + if ( currentChannelVolume[nChannel] != channelVol ) + { + ALfloat gain = ALfloat(channelVol) / MAX_VOLUME; + alSourcef(alChannel[nChannel], AL_GAIN, gain); + currentChannelVolume[nChannel] = channelVol; + } + } +} + +void +cSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + if ( alChannel[nChannel] ) + { + alSource3f(alChannel[nChannel], AL_POSITION, -fX, fY, fZ); + } +} + +void +cSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + if ( alChannel[nChannel] ) + { + if ( float(currentChannelMaxFrontDistance[nChannel]) != fMax ) + { + alSourcef(alChannel[nChannel], AL_MAX_DISTANCE, fMax); + alSourcef(alChannel[nChannel], AL_REFERENCE_DISTANCE, 5.0f); + alSourcef(alChannel[nChannel], AL_MAX_GAIN, 1.0f); + currentChannelMaxFrontDistance[nChannel] = int32(fMax); + } + } +} + +void +cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + if ( nChannel == CHANNEL2D ) + { + uint32 vol = nVolume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + nChannelVolume[nChannel] = vol; + + // increase the volume for JB.MP3 and S4_BDBD.MP3 + if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD ) + { + nChannelVolume[nChannel] >>= 2; + } + + uint32 channelVol = m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14; + if ( ChannelSample[nChannel] >= SFX_CAR_REV_1 && SFX_CAR_IDLE_10 >= ChannelSample[nChannel] ) // nice hack + channelVol >>= 1; + + if ( alChannel[nChannel] ) + { + if ( currentChannelVolume[nChannel] != channelVol ) + { + ALfloat gain = ALfloat(channelVol) / MAX_VOLUME; + alSourcef(alChannel[nChannel], AL_GAIN, gain); + currentChannelVolume[nChannel] = channelVol; + } + } + } +} + +void +cSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + ; // NOIMP +} + +void +cSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + if ( alChannel[nChannel] ) + { + if ( currentChannelFrequency[nChannel] != nFreq ) + { + ALfloat pitch = ALfloat(nFreq) / MAX_FREQ; + alSourcef(alChannel[nChannel], AL_PITCH, pitch); + currentChannelFrequency[nChannel] = nFreq; + + if ( Abs(1.0f - pitch) < 0.01f ) + ChannelPitch[nChannel] = 1.0f; + else + ChannelPitch[nChannel] = pitch; + } + } +} + +void +cSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + ; // NOIMP +} + +void +cSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + if ( nLoopCount != 0 ) + alSourcei(alChannel[nChannel], AL_LOOPING, AL_FALSE); + else + alSourcei(alChannel[nChannel], AL_LOOPING, AL_TRUE); +} + +bool +cSampleManager::GetChannelUsedFlag(uint32 nChannel) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + if ( alChannel[nChannel] ) + { + ALint sourceState; + alGetSourcei(alChannel[nChannel], AL_SOURCE_STATE, &sourceState); + return sourceState == AL_PLAYING; + } + + return false; +} + +void +cSampleManager::StartChannel(uint32 nChannel) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + if ( alChannel[nChannel] ) + { + if ( ChannelSample[nChannel] > SAMPLEBANK_END ) // PED's Bank + { + if ( ChannelPitch[nChannel] != 1.0f ) + ChannelPitch[nChannel] = 1.0f; + } + + alSourcef (alChannel[nChannel], AL_PITCH, ChannelPitch[nChannel]); + alSourcePlay(alChannel[nChannel]); + } +} + +void +cSampleManager::StopChannel(uint32 nChannel) +{ + ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS ); + + if ( alChannel[nChannel] ) + { + alSourceStop(alChannel[nChannel]); + + currentChannelVolume [nChannel] = -1; + currentChannelFrequency [nChannel] = -1; + currentChannelMaxFrontDistance[nChannel] = -1; + ChannelPitch [nChannel] = 1.0f; + } +} + +void +cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) +{ + char filename[256]; + + ASSERT( nStream < MAX_STREAMS ); + + if ( nFile < TOTAL_STREAMED_SOUNDS ) + { + if ( mp3Stream[nStream] ) + { + delete mp3Stream[nStream]; + mp3Stream[nStream] = NULL; + } + + strcpy(filename, StreamedNameTable[nFile]); + + MP3Stream *stream = new MP3Stream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); + ASSERT(stream != NULL); + + mp3Stream[nStream] = stream; + + if ( stream->m_bIsOpened ) + { + ; + } + else + { + delete stream; + mp3Stream[nStream] = NULL; + } + } +} + +void +cSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + MP3Stream *stream = mp3Stream[nStream]; + + if ( stream ) + { + if ( nPauseFlag != 0 ) + { + if ( !stream->m_bIsPaused ) + { + alSourcePause(stream->m_alSource); + stream->m_bIsPaused = true; + } + } + else + { + if ( stream->m_bIsPaused ) + { + alSourcef(stream->m_alSource, AL_PITCH, 1.0f); + alSourcePlay(stream->m_alSource); + stream->m_bIsPaused = false; + } + } + } +} + +void +cSampleManager::StartPreloadedStreamedFile(uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + MP3Stream *stream = mp3Stream[nStream]; + + if ( stream ) + { + stream->Initialize(); + if ( stream->m_bIsOpened ) + { + //NOTE: set pos here on mobile + + if ( stream->FillBuffers() != 0 ) + { + alSourcef(stream->m_alSource, AL_PITCH, 1.0f); + alSourcePlay(stream->m_alSource); + stream->m_bIsFree = false; + } + } + } +} + +bool +cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) +{ + char filename[256]; + + ASSERT( nStream < MAX_STREAMS ); + + if ( nFile < TOTAL_STREAMED_SOUNDS ) + { + if ( mp3Stream[nStream] ) + { + delete mp3Stream[nStream]; + mp3Stream[nStream] = NULL; + } + + strcpy(filename, StreamedNameTable[nFile]); + + MP3Stream *stream = new MP3Stream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); + ASSERT(stream != NULL); + + mp3Stream[nStream] = stream; + + if ( stream->m_bIsOpened ) + { + stream->Initialize(); + nStreamLength[nFile] = stream->m_nLength; + //MusicManager.SetTrackInfoLength(nFile, stream->m_nLength); + + if ( stream->m_bIsOpened ) + { + if ( nPos != 0 ) + { + stream->SetPos(nPos); + } + + if ( stream->FillBuffers() != 0 ) + { + alSourcef(stream->m_alSource, AL_PITCH, 1.0f); + alSourcePlay(stream->m_alSource); + stream->m_bIsFree = false; + } + } + + return true; + } + else + { + delete stream; + mp3Stream[nStream] = NULL; + } + } + + return false; +} + +void +cSampleManager::StopStreamedFile(uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + MP3Stream *stream = mp3Stream[nStream]; + + if ( stream ) + { + delete stream; + mp3Stream[nStream] = NULL; + } +} + +int32 +cSampleManager::GetStreamedFilePosition(uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + MP3Stream *stream = mp3Stream[nStream]; + + if ( stream ) + { + return (ftell(stream->m_fpFile) * 8) / stream->m_nBitRate; + } + + return 0; +} + +void +cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + if ( nVolume > MAX_VOLUME ) + nVolume = MAX_VOLUME; + + if ( nPan > MAX_VOLUME ) + nPan = MAX_VOLUME; + + nStreamVolume[nStream] = m_nMusicFadeVolume * nVolume; + nStreamPan [nStream] = nPan; + + MP3Stream *stream = mp3Stream[nStream]; + + if ( stream ) + { + uint32 vol; + if ( nEffectFlag ) + vol = m_nEffectsFadeVolume*nVolume*m_nEffectsVolume >> 14; + else + vol = m_nMusicFadeVolume*nVolume*m_nMusicVolume >> 14; + + if ( stream->m_nVolume != vol ) + { + if ( stream->m_bIsOpened ) + { + ALuint source = stream->m_alSource; + if ( source ) + { + ALfloat gain = ALfloat(vol) / MAX_VOLUME; + alSourcef(source, AL_GAIN, gain); + stream = mp3Stream[nStream]; + } + } + + stream->m_nVolume = vol; + } + } +} + +int32 +cSampleManager::GetStreamedFileLength(uint8 nStream) +{ + ASSERT( nStream < TOTAL_STREAMED_SOUNDS ); + + return nStreamLength[nStream]; +} + +bool +cSampleManager::IsStreamPlaying(uint8 nStream) +{ + ASSERT( nStream < MAX_STREAMS ); + + MP3Stream *stream = mp3Stream[nStream]; + + if ( stream && stream->m_bIsOpened && !stream->m_bIsPaused ) + { + ALint sourceState; + alGetSourcei(stream->m_alSource, AL_SOURCE_STATE, &sourceState); + if ( !stream->m_bIsFree || sourceState == AL_PLAYING ) + return true; + } + + return false; +} + +void +cSampleManager::Service(void) +{ + for ( int32 i = 0; i < MAX_STREAMS; i++ ) + { + if ( mp3Stream[i] ) + mp3Stream[i]->Update(); + } + + UpdateSoundBuffers(); +} + +bool +cSampleManager::InitialiseSampleBanks(void) +{ + int32 nBank = SAMPLEBANK_MAIN; + + fpSampleDescHandle = fopen(SampleBankDescFilename, "rb"); + if ( fpSampleDescHandle == NULL ) + return false; + + fpSampleDataHandle = fopen(SampleBankDataFilename, "rb"); + if ( fpSampleDataHandle == NULL ) + { + fclose(fpSampleDescHandle); + fpSampleDescHandle = NULL; + + return false; + } + + fseek(fpSampleDataHandle, 0, SEEK_END); + int32 _nSampleDataEndOffset = ftell(fpSampleDataHandle); + rewind(fpSampleDataHandle); + + fread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle); + + fclose(fpSampleDescHandle); + fpSampleDescHandle = NULL; + + for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) + { + if ( BankStartOffset[nBank] == BankStartOffset[SAMPLEBANK_MAIN] + i ) + { + nSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset; + nBank++; + } + } + + nSampleBankSize[SAMPLEBANK_MAIN] = nSampleBankDiscStartOffset[SAMPLEBANK_PED] - nSampleBankDiscStartOffset[SAMPLEBANK_MAIN]; + nSampleBankSize[SAMPLEBANK_PED] = _nSampleDataEndOffset - nSampleBankDiscStartOffset[SAMPLEBANK_PED]; + + return true; +} + +/* +sub_1D8D40 +PreloadSoundBank(tSample *,uchar) +CheckOpenALChannels(void) +*/ + +void MP3Stream::Initialize(void) +{ + if ( !m_bIsOpened ) + return; + + mpg123_format_none(m_pMPG); + + mpg123_format(m_pMPG, 11000, MPG123_MONO|MPG123_STEREO, MPG123_ENC_SIGNED_16); + mpg123_format(m_pMPG, 24000, MPG123_MONO|MPG123_STEREO, MPG123_ENC_SIGNED_16); + mpg123_format(m_pMPG, 32000, MPG123_MONO|MPG123_STEREO, MPG123_ENC_SIGNED_16); + mpg123_format(m_pMPG, 44100, MPG123_MONO|MPG123_STEREO, MPG123_ENC_SIGNED_16); + + if ( mpg123_open_feed(m_pMPG) != MPG123_OK ) + return; + + const uint32 CHUNK_SIZE = 1024*5; + + if ( fread(m_pBuf, 1, CHUNK_SIZE, m_fpFile) != CHUNK_SIZE ) + { + Delete(); + return; + } + + m_nBufSize -= CHUNK_SIZE; + + mpg123_feed(m_pMPG, m_pBuf, CHUNK_SIZE); + + if ( mpg123_getformat(m_pMPG, &m_nRate, &m_nChannels, &m_nEncoding) != MPG123_OK ) + { + Delete(); + return; + } + + mpg123_frameinfo info; + if ( mpg123_info(m_pMPG, &info) != MPG123_OK ) + { + Delete(); + return; + } + + m_nBitRate = info.bitrate; + m_nLength = 8 * m_nLengthInBytes / info.bitrate; + m_nBlockSize = mpg123_outblock(m_pMPG); + m_nNumBlocks = 5; + m_pBlocks = (unsigned char *)malloc(m_nNumBlocks * m_nBlockSize); +} + +bool MP3Stream::FillBuffer(ALuint alBuffer) +{ + size_t done; + + uint8 *pBlockBuff = (uint8 *)m_pBlocks; + + bool fail = !(m_nBufSize > 1); + + int err = mpg123_read(m_pMPG, m_pBlocks, m_nBlockSize, &done); + if ( alBuffer == 0 ) + { + if ( err == MPG123_OK ) + { + while ( mpg123_read(m_pMPG, pBlockBuff, m_nBlockSize, &done) == MPG123_OK ) + ; + } + + return true; + } + + int32 blocks = 0; + for ( blocks = 0; blocks < m_nNumBlocks; blocks++ ) + { + if ( err == MPG123_NEED_MORE ) + { + if ( fail ) + break; + + size_t readSize = m_nBufSize; + if ( readSize > 0x4000 ) + { + if ( fread(m_pBuf, 1, 0x4000, m_fpFile) != 0x4000 ) + { + fail = true; + TRACE("MP3 ************* : MP3 read unsuccessful mid file, stopping queuing"); + break; + } + + m_nBufSize -= 0x4000; + mpg123_feed(m_pMPG, m_pBuf, 0x4000); + } + else + { + if ( fread(m_pBuf, 1, readSize, m_fpFile) != readSize ) + { + fail = true; + break; + } + + m_nBufSize -= readSize; + mpg123_feed(m_pMPG, m_pBuf, readSize); + } + } + else if ( err == MPG123_OK ) + { + pBlockBuff += m_nBlockSize; + } + else + { + fail = true; + break; + } + + err = mpg123_read(m_pMPG, pBlockBuff, m_nBlockSize, &done); + } + + if ( blocks != 0 ) + { + if ( m_nChannels == 1 ) + alBufferData(alBuffer, AL_FORMAT_MONO16, m_pBlocks, m_nBlockSize*blocks, m_nRate); + else + alBufferData(alBuffer, AL_FORMAT_STEREO16, m_pBlocks, m_nBlockSize*blocks, m_nRate); + } + + if ( fail && blocks < m_nNumBlocks ) + m_bIsFree = true; + + return blocks != 0; +} + +void MP3Stream::Update(void) +{ + if ( !m_bIsOpened ) + return; + + if ( m_bIsFree ) + return; + + if ( !m_bIsPaused ) + { + ALint sourceState; + ALint buffersProcessed = 0; + + alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState); + alGetSourcei(m_alSource, AL_BUFFERS_PROCESSED, &buffersProcessed); + + ALint looping = AL_FALSE; + alGetSourcei(m_alSource, AL_LOOPING, &looping); + + if ( looping == AL_TRUE ) + { + TRACE("stream set looping"); + alSourcei(m_alSource, AL_LOOPING, AL_TRUE); + } + + while( buffersProcessed-- ) + { + ALuint buffer; + + alSourceUnqueueBuffers(m_alSource, 1, &buffer); + + if ( !m_bIsFree && FillBuffer(buffer) ) + alSourceQueueBuffers(m_alSource, 1, &buffer); + } + + if ( sourceState != AL_PLAYING ) + { + alSourcef(m_alSource, AL_PITCH, 1.0f); + alSourcePlay(m_alSource); + } + } +} + +void MP3Stream::SetPos(uint32 nPos) +{ + uint32 pos = nPos; + if ( nPos > m_nLength ) + pos %= m_nLength; + + uint32 blockPos = m_nBitRate * pos / 8; + if ( blockPos > m_nLengthInBytes ) + blockPos %= m_nLengthInBytes; + + fseek(m_fpFile, blockPos, SEEK_SET); + + size_t done; + while ( mpg123_read(m_pMPG, m_pBlocks, m_nBlockSize, &done) == MPG123_OK ) + ; +} + +int32 MP3Stream::FillBuffers() +{ + int32 i = 0; + for ( i = 0; i < ARRAY_SIZE(m_alBuffers); i++ ) + { + if ( !FillBuffer(m_alBuffers[i]) ) + break; + alSourceQueueBuffers(m_alSource, 1, &m_alBuffers[i]); + } + + return i; +} + +MP3Stream::MP3Stream(char *filename, ALuint source, ALuint *buffers) +{ + strcpy(m_aFilename, filename); + memset(m_alBuffers, 0, sizeof(m_alBuffers)); + m_alSource = source; + memcpy(m_alBuffers, buffers, sizeof(m_alBuffers)); + m_nVolume = -1; + m_pBlocks = NULL; + m_pBuf = NULL; + m_pMPG = NULL; + m_bIsPaused = false; + m_bIsOpened = true; + m_bIsFree = true; + m_fpFile = fopen(m_aFilename, "rb"); + + if ( m_fpFile ) + { + m_nBufSize = filelength(fileno(m_fpFile)); + m_nLengthInBytes = m_nBufSize; + m_pMPG = mpg123_new(NULL, NULL); + m_pBuf = (unsigned char *)malloc(0x4000); + } + else + { + m_bIsOpened = false; + Delete(); + } +} + +void MP3Stream::Delete() +{ + if ( m_pMPG ) + { + mpg123_delete(m_pMPG); + m_pMPG = NULL; + } + + if ( m_fpFile ) + { + fclose(m_fpFile); + m_fpFile = NULL; + } + + if ( m_alSource ) + { + ALint sourceState = AL_STOPPED; + alGetSourcei(m_alSource, AL_SOURCE_STATE, &sourceState); + if (sourceState != AL_STOPPED ) + alSourceStop(m_alSource); + + ALint buffersQueued; + alGetSourcei(m_alSource, AL_BUFFERS_QUEUED, &buffersQueued); + + ALuint value; + while (buffersQueued--) + alSourceUnqueueBuffers(m_alSource, 1, &value); + + m_alSource = 0; + } + + if ( m_pBlocks ) + { + free(m_pBlocks); + m_pBlocks = NULL; + } + + if ( m_pBuf ) + { + free(m_pBuf); + m_pBuf = NULL; + } + + m_bIsOpened = false; +} \ No newline at end of file diff --git a/src/audio/openal/samp_oal.h b/src/audio/openal/samp_oal.h new file mode 100644 index 00000000..8bbdbcc9 --- /dev/null +++ b/src/audio/openal/samp_oal.h @@ -0,0 +1,340 @@ +#pragma once +#include "common.h" +#include "AudioSamples.h" + +#define MAX_VOLUME 127 +//#define MAX_FREQ 22050 +#define MAX_FREQ 32000 + +struct tSample { + int32 nOffset; + uint32 nSize; + int32 nFrequency; + int32 nLoopStart; + int32 nLoopEnd; +}; + +enum +{ + SAMPLEBANK_MAIN, + SAMPLEBANK_PED, + MAX_SAMPLEBANKS, + SAMPLEBANK_INVALID +}; + +#define MAX_PEDSFX 7 +#define PED_BLOCKSIZE 79000 + + +//#define MAXCHANNELS 21 android +#define MAXCHANNELS 28 +#define MAX2DCHANNELS 1 +#define CHANNEL2D MAXCHANNELS + +#define MAX_STREAMS 2 + +struct ALCdevice_struct; +struct ALCcontext_struct; +typedef struct ALCdevice_struct ALCdevice; +typedef struct ALCcontext_struct ALCcontext; + +class cSampleManager +{ + int field_0; + ALCdevice *m_pDevice; + ALCcontext *m_pContext; + + uint8 m_nEffectsVolume; + uint8 m_nMusicVolume; + uint8 m_nEffectsFadeVolume; + uint8 m_nMusicFadeVolume; + uint8 m_nMonoMode; + char _pad0[3]; + tSample m_aSamples[TOTAL_AUDIO_SAMPLES]; + +public: + + + + cSampleManager(void); + ~cSampleManager(void); + + void SetSpeakerConfig(int32 nConfig); + uint32 GetMaximumSupportedChannels(void); + + uint32 GetNum3DProvidersAvailable(); + void SetNum3DProvidersAvailable(uint32 num); + + char *Get3DProviderName(uint8 id); + void Set3DProviderName(uint8 id, char *name); + + int8 GetCurrent3DProviderIndex(void); + int8 SetCurrent3DProvider(uint8 which); + + bool IsMP3RadioChannelAvailable(void); + + void ReleaseDigitalHandle (void); + void ReacquireDigitalHandle(void); + + bool Initialise(void); + void Terminate (void); + + void UpdateSoundBuffers(void); + + bool CheckForAnAudioFileOnCD(void); + char GetCDAudioDriveLetter (void); + + void UpdateEffectsVolume(void); + + void SetEffectsMasterVolume(uint8 nVolume); + void SetMusicMasterVolume (uint8 nVolume); + void SetEffectsFadeVolume (uint8 nVolume); + void SetMusicFadeVolume (uint8 nVolume); + void SetMonoMode (uint8 nMode); + + bool LoadSampleBank (uint8 nBank); + void UnloadSampleBank (uint8 nBank); + bool IsSampleBankLoaded(uint8 nBank); + + bool IsPedCommentLoaded(uint32 nComment); + bool LoadPedComment (uint32 nComment); + int32 GetBankContainingSound(uint32 offset); + + int32 _GetPedCommentSlot(uint32 nComment); + + int32 GetSampleBaseFrequency (uint32 nSample); + int32 GetSampleLoopStartOffset(uint32 nSample); + int32 GetSampleLoopEndOffset (uint32 nSample); + uint32 GetSampleLength (uint32 nSample); + + bool UpdateReverb(void); + + void SetChannelReverbFlag (uint32 nChannel, uint8 nReverbFlag); + bool InitialiseChannel (uint32 nChannel, uint32 nSfx, uint8 nBank); + void SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume); + void SetChannel3DPosition (uint32 nChannel, float fX, float fY, float fZ); + void SetChannel3DDistances (uint32 nChannel, float fMax, float fMin); + void SetChannelVolume (uint32 nChannel, uint32 nVolume); + void SetChannelPan (uint32 nChannel, uint32 nPan); + void SetChannelFrequency (uint32 nChannel, uint32 nFreq); + void SetChannelLoopPoints (uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd); + void SetChannelLoopCount (uint32 nChannel, uint32 nLoopCount); + bool GetChannelUsedFlag (uint32 nChannel); + void StartChannel (uint32 nChannel); + void StopChannel (uint32 nChannel); + + void PreloadStreamedFile (uint8 nFile, uint8 nStream); + void PauseStream (uint8 nPauseFlag, uint8 nStream); + void StartPreloadedStreamedFile (uint8 nStream); + bool StartStreamedFile (uint8 nFile, uint32 nPos, uint8 nStream); + void StopStreamedFile (uint8 nStream); + int32 GetStreamedFilePosition (uint8 nStream); + void SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream); + int32 GetStreamedFileLength (uint8 nStream); + bool IsStreamPlaying (uint8 nStream); + void Service(void); + bool InitialiseSampleBanks(void); +}; + +extern cSampleManager SampleManager; +extern int32 BankStartOffset[MAX_SAMPLEBANKS]; + +static char StreamedNameTable[][25]= +{ + "AUDIO\\HEAD.MP3", + "AUDIO\\CLASS.MP3", + "AUDIO\\KJAH.MP3", + "AUDIO\\RISE.MP3", + "AUDIO\\LIPS.MP3", + "AUDIO\\GAME.MP3", + "AUDIO\\MSX.MP3", + "AUDIO\\FLASH.MP3", + "AUDIO\\CHAT.MP3", + "AUDIO\\HEAD.MP3", + "AUDIO\\POLICE.MP3", + "AUDIO\\CITY.MP3", + "AUDIO\\WATER.MP3", + "AUDIO\\COMOPEN.MP3", + "AUDIO\\SUBOPEN.MP3", + "AUDIO\\JB.MP3", + "AUDIO\\BET.MP3", + "AUDIO\\L1_LG.MP3", + "AUDIO\\L2_DSB.MP3", + "AUDIO\\L3_DM.MP3", + "AUDIO\\L4_PAP.MP3", + "AUDIO\\L5_TFB.MP3", + "AUDIO\\J0_DM2.MP3", + "AUDIO\\J1_LFL.MP3", + "AUDIO\\J2_KCL.MP3", + "AUDIO\\J3_VH.MP3", + "AUDIO\\J4_ETH.MP3", + "AUDIO\\J5_DST.MP3", + "AUDIO\\J6_TBJ.MP3", + "AUDIO\\T1_TOL.MP3", + "AUDIO\\T2_TPU.MP3", + "AUDIO\\T3_MAS.MP3", + "AUDIO\\T4_TAT.MP3", + "AUDIO\\T5_BF.MP3", + "AUDIO\\S0_MAS.MP3", + "AUDIO\\S1_PF.MP3", + "AUDIO\\S2_CTG.MP3", + "AUDIO\\S3_RTC.MP3", + "AUDIO\\S5_LRQ.MP3", + "AUDIO\\S4_BDBA.MP3", + "AUDIO\\S4_BDBB.MP3", + "AUDIO\\S2_CTG2.MP3", + "AUDIO\\S4_BDBD.MP3", + "AUDIO\\S5_LRQB.MP3", + "AUDIO\\S5_LRQC.MP3", + "AUDIO\\A1_SSO.MP3", + "AUDIO\\A2_PP.MP3", + "AUDIO\\A3_SS.MP3", + "AUDIO\\A4_PDR.MP3", + "AUDIO\\A5_K2FT.MP3", + "AUDIO\\K1_KBO.MP3", + "AUDIO\\K2_GIS.MP3", + "AUDIO\\K3_DS.MP3", + "AUDIO\\K4_SHI.MP3", + "AUDIO\\K5_SD.MP3", + "AUDIO\\R0_PDR2.MP3", + "AUDIO\\R1_SW.MP3", + "AUDIO\\R2_AP.MP3", + "AUDIO\\R3_ED.MP3", + "AUDIO\\R4_GF.MP3", + "AUDIO\\R5_PB.MP3", + "AUDIO\\R6_MM.MP3", + "AUDIO\\D1_STOG.MP3", + "AUDIO\\D2_KK.MP3", + "AUDIO\\D3_ADO.MP3", + "AUDIO\\D5_ES.MP3", + "AUDIO\\D7_MLD.MP3", + "AUDIO\\D4_GTA.MP3", + "AUDIO\\D4_GTA2.MP3", + "AUDIO\\D6_STS.MP3", + "AUDIO\\A6_BAIT.MP3", + "AUDIO\\A7_ETG.MP3", + "AUDIO\\A8_PS.MP3", + "AUDIO\\A9_ASD.MP3", + "AUDIO\\K4_SHI2.MP3", + "AUDIO\\C1_TEX.MP3", + "AUDIO\\EL_PH1.MP3", + "AUDIO\\EL_PH2.MP3", + "AUDIO\\EL_PH3.MP3", + "AUDIO\\EL_PH4.MP3", + "AUDIO\\YD_PH1.MP3", + "AUDIO\\YD_PH2.MP3", + "AUDIO\\YD_PH3.MP3", + "AUDIO\\YD_PH4.MP3", + "AUDIO\\HD_PH1.MP3", + "AUDIO\\HD_PH2.MP3", + "AUDIO\\HD_PH3.MP3", + "AUDIO\\HD_PH4.MP3", + "AUDIO\\HD_PH5.MP3", + "AUDIO\\MT_PH1.MP3", + "AUDIO\\MT_PH2.MP3", + "AUDIO\\MT_PH3.MP3", + "AUDIO\\MT_PH4.MP3", + "AUDIO\\MISCOM.MP3", + "AUDIO\\END.MP3", + "AUDIO\\lib_a1.MP3", + "AUDIO\\lib_a2.MP3", + "AUDIO\\lib_a.MP3", + "AUDIO\\lib_b.MP3", + "AUDIO\\lib_c.MP3", + "AUDIO\\lib_d.MP3", + "AUDIO\\l2_a.MP3", + "AUDIO\\j4t_1.MP3", + "AUDIO\\j4t_2.MP3", + "AUDIO\\j4t_3.MP3", + "AUDIO\\j4t_4.MP3", + "AUDIO\\j4_a.MP3", + "AUDIO\\j4_b.MP3", + "AUDIO\\j4_c.MP3", + "AUDIO\\j4_d.MP3", + "AUDIO\\j4_e.MP3", + "AUDIO\\j4_f.MP3", + "AUDIO\\j6_1.MP3", + "AUDIO\\j6_a.MP3", + "AUDIO\\j6_b.MP3", + "AUDIO\\j6_c.MP3", + "AUDIO\\j6_d.MP3", + "AUDIO\\t4_a.MP3", + "AUDIO\\s1_a.MP3", + "AUDIO\\s1_a1.MP3", + "AUDIO\\s1_b.MP3", + "AUDIO\\s1_c.MP3", + "AUDIO\\s1_c1.MP3", + "AUDIO\\s1_d.MP3", + "AUDIO\\s1_e.MP3", + "AUDIO\\s1_f.MP3", + "AUDIO\\s1_g.MP3", + "AUDIO\\s1_h.MP3", + "AUDIO\\s1_i.MP3", + "AUDIO\\s1_j.MP3", + "AUDIO\\s1_k.MP3", + "AUDIO\\s1_l.MP3", + "AUDIO\\s3_a.MP3", + "AUDIO\\s3_b.MP3", + "AUDIO\\el3_a.MP3", + "AUDIO\\mf1_a.MP3", + "AUDIO\\mf2_a.MP3", + "AUDIO\\mf3_a.MP3", + "AUDIO\\mf3_b.MP3", + "AUDIO\\mf3_b1.MP3", + "AUDIO\\mf3_c.MP3", + "AUDIO\\mf4_a.MP3", + "AUDIO\\mf4_b.MP3", + "AUDIO\\mf4_c.MP3", + "AUDIO\\a1_a.MP3", + "AUDIO\\a3_a.MP3", + "AUDIO\\a5_a.MP3", + "AUDIO\\a4_a.MP3", + "AUDIO\\a4_b.MP3", + "AUDIO\\a4_c.MP3", + "AUDIO\\a4_d.MP3", + "AUDIO\\k1_a.MP3", + "AUDIO\\k3_a.MP3", + "AUDIO\\r1_a.MP3", + "AUDIO\\r2_a.MP3", + "AUDIO\\r2_b.MP3", + "AUDIO\\r2_c.MP3", + "AUDIO\\r2_d.MP3", + "AUDIO\\r2_e.MP3", + "AUDIO\\r2_f.MP3", + "AUDIO\\r2_g.MP3", + "AUDIO\\r2_h.MP3", + "AUDIO\\r5_a.MP3", + "AUDIO\\r6_a.MP3", + "AUDIO\\r6_a1.MP3", + "AUDIO\\r6_b.MP3", + "AUDIO\\lo2_a.MP3", + "AUDIO\\lo6_a.MP3", + "AUDIO\\yd2_a.MP3", + "AUDIO\\yd2_b.MP3", + "AUDIO\\yd2_c.MP3", + "AUDIO\\yd2_c1.MP3", + "AUDIO\\yd2_d.MP3", + "AUDIO\\yd2_e.MP3", + "AUDIO\\yd2_f.MP3", + "AUDIO\\yd2_g.MP3", + "AUDIO\\yd2_h.MP3", + "AUDIO\\yd2_ass.MP3", + "AUDIO\\yd2_ok.MP3", + "AUDIO\\h5_a.MP3", + "AUDIO\\h5_b.MP3", + "AUDIO\\h5_c.MP3", + "AUDIO\\ammu_a.MP3", + "AUDIO\\ammu_b.MP3", + "AUDIO\\ammu_c.MP3", + "AUDIO\\door_1.MP3", + "AUDIO\\door_2.MP3", + "AUDIO\\door_3.MP3", + "AUDIO\\door_4.MP3", + "AUDIO\\door_5.MP3", + "AUDIO\\door_6.MP3", + "AUDIO\\t3_a.MP3", + "AUDIO\\t3_b.MP3", + "AUDIO\\t3_c.MP3", + "AUDIO\\k1_b.MP3", + "AUDIO\\cat1.MP3" +}; diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp index a375b847..aa6b67dc 100644 --- a/src/audio/sampman.cpp +++ b/src/audio/sampman.cpp @@ -1,2257 +1,7 @@ -#include -#include -#include - -#include - -#include "eax.h" -#include "eax-util.h" -#include "mss.h" - -#include "sampman.h" -#include "AudioManager.h" -#include "MusicManager.h" -#include "Frontend.h" -#include "Timer.h" - - -#pragma comment( lib, "mss32.lib" ) - -cSampleManager SampleManager; -int32 BankStartOffset[MAX_SAMPLEBANKS]; -/////////////////////////////////////////////////////////////// - -char SampleBankDescFilename[] = "AUDIO\\SFX.SDT"; -char SampleBankDataFilename[] = "AUDIO\\SFX.RAW"; - -FILE *fpSampleDescHandle; -FILE *fpSampleDataHandle; -bool bSampleBankLoaded [MAX_SAMPLEBANKS]; -int32 nSampleBankDiscStartOffset [MAX_SAMPLEBANKS]; -int32 nSampleBankSize [MAX_SAMPLEBANKS]; -int32 nSampleBankMemoryStartAddress[MAX_SAMPLEBANKS]; -int32 _nSampleDataEndOffset; - -int32 nPedSlotSfx [MAX_PEDSFX]; -int32 nPedSlotSfxAddr[MAX_PEDSFX]; -uint8 nCurrentPedSlot; - -uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS]; - -uint32 nStreamLength[TOTAL_STREAMED_SOUNDS]; - -/////////////////////////////////////////////////////////////// -struct tMP3Entry -{ - char aFilename[MAX_PATH]; - - uint32 nTrackLength; - uint32 nTrackStreamPos; - - tMP3Entry *pNext; - char *pLinkPath; -}; - -uint32 nNumMP3s; -tMP3Entry *_pMP3List; -char _mp3DirectoryPath[MAX_PATH]; -HSTREAM mp3Stream [MAX_MP3STREAMS]; -int8 nStreamPan [MAX_MP3STREAMS]; -int8 nStreamVolume[MAX_MP3STREAMS]; -uint32 _CurMP3Index; -int32 _CurMP3Pos; -bool _bIsMp3Active; - -#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) -bool _bUseHDDAudio; -char _aHDDPath[MAX_PATH]; -#endif -/////////////////////////////////////////////////////////////// - - -bool _bSampmanInitialised = false; - -// -// Miscellaneous globals / defines - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS - -EAXLISTENERPROPERTIES StartEAX3 = - {26, 1.7f, 0.8f, -1000, -1000, -100, 4.42f, 0.14f, 1.00f, 429, 0.014f, 0.00f,0.00f,0.00f, 1023, 0.021f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2727.1f, 250.0f, 0.00f, 0x3f }; - -EAXLISTENERPROPERTIES FinishEAX3 = - {26, 100.0f, 1.0f, 0, -1000, -2200, 20.0f, 1.39f, 1.00f, 1000, 0.069f, 0.00f,0.00f,0.00f, 400, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 3.982f, 0.000f, -18.0f, 3530.8f, 417.9f, 6.70f, 0x3f }; - -EAXLISTENERPROPERTIES EAX3Params; - -S32 prevprovider=-1; -S32 curprovider=-1; -S32 usingEAX=0; -S32 usingEAX3=0; -HPROVIDER opened_provider=0; -H3DSAMPLE opened_samples[MAXCHANNELS] = {0}; -HSAMPLE opened_2dsamples[MAX2DCHANNELS] = {0}; -HDIGDRIVER DIG; -S32 speaker_type=0; - -U32 _maxSamples; -float _fPrevEaxRatioDestination; -bool _usingMilesFast2D; -float _fEffectsLevel; - - -struct -{ - HPROVIDER id; - char name[80]; -}providers[MAXPROVIDERS]; - -typedef struct provider_stuff -{ - char* name; - HPROVIDER id; -} provider_stuff; - - -static int __cdecl comp(const provider_stuff*s1,const provider_stuff*s2) -{ - return( _stricmp(s1->name,s2->name) ); -} - -static void -add_providers() -{ - provider_stuff pi[MAXPROVIDERS]; - U32 n,i,j; - - SampleManager.SetNum3DProvidersAvailable(0); - - HPROENUM next = HPROENUM_FIRST; - - n=0; - while (AIL_enumerate_3D_providers(&next, &pi[n].id, &pi[n].name) && (n MAXCHANNELS ) - _maxSamples = MAXCHANNELS; - - SampleManager.SetSpeakerConfig(speaker_type); - - //obtain a 3D sample handles - for ( U32 i = 0; i < _maxSamples; ++i ) - { - opened_samples[i] = AIL_allocate_3D_sample_handle(opened_provider); - if ( opened_samples[i] != NULL ) - AIL_set_3D_sample_effects_level(opened_samples[i], 0.0f); - } - - return true; - } - } - - return false; -} - -void -cSampleManager::SetSpeakerConfig(int32 which) -{ - switch ( which ) - { - case 1: - speaker_type=AIL_3D_2_SPEAKER; - break; - - case 2: - speaker_type=AIL_3D_HEADPHONE; - break; - - case 3: - speaker_type=AIL_3D_4_SPEAKER; - break; - - default: - return; - break; - } - - if (opened_provider) - AIL_set_3D_speaker_type(opened_provider, speaker_type); -} - -uint32 -cSampleManager::GetMaximumSupportedChannels(void) -{ - if ( _maxSamples > MAXCHANNELS ) - return MAXCHANNELS; - - return _maxSamples; -} - -int8 -cSampleManager::GetCurrent3DProviderIndex(void) -{ - return curprovider; -} - -int8 -cSampleManager::SetCurrent3DProvider(uint8 nProvider) -{ - S32 savedprovider = curprovider; - - if ( nProvider < m_nNumberOfProviders ) - { - if ( set_new_provider(nProvider) ) - return curprovider; - else if ( savedprovider != -1 && savedprovider < m_nNumberOfProviders && set_new_provider(savedprovider) ) - return curprovider; - else - return -1; - } - else - return curprovider; -} - -static bool -_ResolveLink(char const *path, char *out) -{ - IShellLink* psl; - WIN32_FIND_DATA fd; - char filepath[MAX_PATH]; - - CoInitialize(NULL); - - if (SUCCEEDED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl ) )) - { - IPersistFile *ppf; - - if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf))) - { - WCHAR wpath[MAX_PATH]; - - MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH); - - if (SUCCEEDED(ppf->Load(wpath, STGM_READ))) - { - /* Resolve the link */ - if (SUCCEEDED(psl->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI|SLR_NOSEARCH))) - { - strcpy(filepath, path); - - if (SUCCEEDED(psl->GetPath(filepath, MAX_PATH, &fd, SLGP_UNCPRIORITY))) - { - OutputDebugString(fd.cFileName); - - strcpy(out, filepath); - // FIX: Release the objects. Taken from SA. -#ifdef FIX_BUGS - ppf->Release(); - psl->Release(); -#endif - return true; - } - } - } - - ppf->Release(); - } - psl->Release(); - } - - return false; -} - -static void -_FindMP3s(void) -{ - tMP3Entry *pList; - bool bShortcut; - bool bInitFirstEntry; - HANDLE hFind; - char path[MAX_PATH]; - char filepath[MAX_PATH*2]; - S32 total_ms; - WIN32_FIND_DATA fd; - - - if ( GetCurrentDirectory(MAX_PATH, _mp3DirectoryPath) == 0 ) - { - GetLastError(); - return; - } - - OutputDebugString("Finding MP3s..."); - strcpy(path, _mp3DirectoryPath); - strcat(path, "\\MP3\\"); - - strcpy(_mp3DirectoryPath, path); - OutputDebugString(_mp3DirectoryPath); - - strcat(path, "*"); - - hFind = FindFirstFile(path, &fd); - - if ( hFind == INVALID_HANDLE_VALUE ) - { - GetLastError(); - return; - } - - strcpy(filepath, _mp3DirectoryPath); - strcat(filepath, fd.cFileName); - - int32 filepathlen = strlen(filepath); - - if ( filepathlen <= 0) - { - FindClose(hFind); - return; - } - - FILE *f = fopen("MP3\\MP3Report.txt", "w"); - - if ( f ) - { - fprintf(f, "MP3 Report File\n\n"); - fprintf(f, "\"%s\"", fd.cFileName); - } - - - if ( filepathlen > 4 ) - { - if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) - { - if ( _ResolveLink(filepath, filepath) ) - { - OutputDebugString("Resolving Link"); - OutputDebugString(filepath); - - if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); - } - else - { - if ( f ) fprintf(f, " - couldn't resolve shortcut"); - } - - bShortcut = true; - } - else - bShortcut = false; - } - - mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); - if ( mp3Stream[0] ) - { - AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); - - AIL_close_stream(mp3Stream[0]); - mp3Stream[0] = NULL; - - OutputDebugString(fd.cFileName); - - _pMP3List = new tMP3Entry; - - if ( _pMP3List == NULL ) - { - FindClose(hFind); - - if ( f ) - fclose(f); - - return; - } - - nNumMP3s = 1; - - strcpy(_pMP3List->aFilename, fd.cFileName); - - _pMP3List->nTrackLength = total_ms; - - _pMP3List->pNext = NULL; - - pList = _pMP3List; - - if ( bShortcut ) - { - _pMP3List->pLinkPath = new char[MAX_PATH*2]; - strcpy(_pMP3List->pLinkPath, filepath); - } - else - { - _pMP3List->pLinkPath = NULL; - } - - if ( f ) fprintf(f, " - OK\n"); - - bInitFirstEntry = false; - } - else - { - strcat(filepath, " - NOT A VALID MP3"); - - OutputDebugString(filepath); - - if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); - - bInitFirstEntry = true; - } - - while ( true ) - { - if ( !FindNextFile(hFind, &fd) ) - break; - - if ( bInitFirstEntry ) - { - strcpy(filepath, _mp3DirectoryPath); - strcat(filepath, fd.cFileName); - - int32 filepathlen = strlen(filepath); - - if ( f ) fprintf(f, "\"%s\"", fd.cFileName); - - if ( filepathlen > 0 ) - { - if ( filepathlen > 4 ) - { - if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) - { - if ( _ResolveLink(filepath, filepath) ) - { - OutputDebugString("Resolving Link"); - OutputDebugString(filepath); - - if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); - } - else - { - if ( f ) fprintf(f, " - couldn't resolve shortcut"); - } - - bShortcut = true; - } - else - { - bShortcut = false; - - if ( filepathlen > MAX_PATH ) - { - if ( f ) fprintf(f, " - Filename and path too long - %s - IGNORED)\n", filepath); - - continue; - } - } - } - - mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); - if ( mp3Stream[0] ) - { - AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); - - AIL_close_stream(mp3Stream[0]); - mp3Stream[0] = NULL; - - OutputDebugString(fd.cFileName); - - _pMP3List = new tMP3Entry; - - if ( _pMP3List == NULL) - break; - - nNumMP3s = 1; - - strcpy(_pMP3List->aFilename, fd.cFileName); - - _pMP3List->nTrackLength = total_ms; - _pMP3List->pNext = NULL; - - if ( bShortcut ) - { - _pMP3List->pLinkPath = new char [MAX_PATH*2]; - strcpy(_pMP3List->pLinkPath, filepath); - } - else - { - _pMP3List->pLinkPath = NULL; - } - - pList = _pMP3List; - - if ( f ) fprintf(f, " - OK\n"); - - bInitFirstEntry = false; - } - else - { - strcat(filepath, " - NOT A VALID MP3"); - OutputDebugString(filepath); - - if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); - } - } - } - else - { - strcpy(filepath, _mp3DirectoryPath); - strcat(filepath, fd.cFileName); - - int32 filepathlen = strlen(filepath); - - if ( filepathlen > 0 ) - { - if ( f ) fprintf(f, "\"%s\"", fd.cFileName); - - if ( filepathlen > 4 ) - { - if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) - { - if ( _ResolveLink(filepath, filepath) ) - { - OutputDebugString("Resolving Link"); - OutputDebugString(filepath); - - if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); - } - else - { - if ( f ) fprintf(f, " - couldn't resolve shortcut"); - } - - bShortcut = true; - } - else - { - bShortcut = false; - } - } - - mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); - if ( mp3Stream[0] ) - { - AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); - - AIL_close_stream(mp3Stream[0]); - mp3Stream[0] = NULL; - - pList->pNext = new tMP3Entry; - - tMP3Entry *e = pList->pNext; - - if ( e == NULL ) - break; - - pList = pList->pNext; - - strcpy(e->aFilename, fd.cFileName); - e->nTrackLength = total_ms; - e->pNext = NULL; - - if ( bShortcut ) - { - e->pLinkPath = new char [MAX_PATH*2]; - strcpy(e->pLinkPath, filepath); - } - else - { - e->pLinkPath = NULL; - } - - nNumMP3s++; - - OutputDebugString(fd.cFileName); - - if ( f ) fprintf(f, " - OK\n"); - } - else - { - strcat(filepath, " - NOT A VALID MP3"); - OutputDebugString(filepath); - - if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); - } - } - } - } - - if ( f ) - { - fprintf(f, "\nTOTAL SUPPORTED MP3s: %d\n", nNumMP3s); - fclose(f); - } - - FindClose(hFind); -} - -static void -_DeleteMP3Entries(void) -{ - tMP3Entry *e = _pMP3List; - - while ( e != NULL ) - { - tMP3Entry *next = e->pNext; - - if ( next == NULL ) - next = NULL; - - if ( e->pLinkPath != NULL ) - { -#ifndef FIX_BUGS - delete e->pLinkPath; // BUG: should be delete [] +#pragma once +#include "common.h" +#ifndef OPENAL +#include "miles\sampman_mss.cpp" #else - delete[] e->pLinkPath; -#endif - e->pLinkPath = NULL; - } - - delete e; - - if ( next ) - e = next; - else - e = NULL; - - nNumMP3s--; - } - - - if ( nNumMP3s != 0 ) - { - OutputDebugString("Not all MP3 entries were deleted"); - nNumMP3s = 0; - } - - _pMP3List = NULL; -} - -static tMP3Entry * -_GetMP3EntryByIndex(uint32 idx) -{ - uint32 n = ( idx < nNumMP3s ) ? idx : 0; - - if ( _pMP3List != NULL ) - { - tMP3Entry *e = _pMP3List; - - for ( uint32 i = 0; i < n; i++ ) - e = e->pNext; - - return e; - - } - - return NULL; -} - -static inline bool -_GetMP3PosFromStreamPos(uint32 *pPosition, tMP3Entry **pEntry) -{ - _CurMP3Index = 0; - - for ( *pEntry = _pMP3List; *pEntry != NULL; *pEntry = (*pEntry)->pNext ) - { - if ( *pPosition >= (*pEntry)->nTrackStreamPos - && *pPosition < (*pEntry)->nTrackLength + (*pEntry)->nTrackStreamPos ) - { - *pPosition -= (*pEntry)->nTrackStreamPos; - _CurMP3Pos = *pPosition; - - return true; - } - - _CurMP3Index++; - } - - *pPosition = 0; - *pEntry = _pMP3List; - _CurMP3Pos = 0; - _CurMP3Index = 0; - - return false; -} - -bool -cSampleManager::IsMP3RadioChannelAvailable(void) -{ - return nNumMP3s != 0; -} - -void -cSampleManager::ReleaseDigitalHandle(void) -{ - if ( DIG ) - { - prevprovider = curprovider; - release_existing(); - curprovider = -1; - AIL_digital_handle_release(DIG); - } -} - -void -cSampleManager::ReacquireDigitalHandle(void) -{ - if ( DIG ) - { - AIL_digital_handle_reacquire(DIG); - if ( prevprovider != -1 ) - set_new_provider(prevprovider); - } -} - -bool -cSampleManager::Initialise(void) -{ - TRACE("start"); - - if ( _bSampmanInitialised ) - return true; - - { - for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) - { - m_aSamples[i].nOffset = 0; - m_aSamples[i].nSize = 0; - m_aSamples[i].nFrequency = 22050; - m_aSamples[i].nLoopStart = 0; - m_aSamples[i].nLoopEnd = -1; - } - - m_nEffectsVolume = MAX_VOLUME; - m_nMusicVolume = MAX_VOLUME; - m_nEffectsFadeVolume = MAX_VOLUME; - m_nMusicFadeVolume = MAX_VOLUME; - - m_nMonoMode = 0; - } - - // miles - TRACE("MILES"); - { - curprovider = -1; - prevprovider = -1; - - _usingMilesFast2D = false; - usingEAX=0; - usingEAX3=0; - - _fEffectsLevel = 0.0f; - - _maxSamples = 0; - - opened_provider = NULL; - DIG = NULL; - - for ( int32 i = 0; i < MAXCHANNELS; i++ ) - opened_samples[i] = NULL; - } - - // banks - TRACE("banks"); - { - fpSampleDescHandle = NULL; - fpSampleDataHandle = NULL; - - _nSampleDataEndOffset = 0; - - for ( int32 i = 0; i < MAX_SAMPLEBANKS; i++ ) - { - bSampleBankLoaded[i] = false; - nSampleBankDiscStartOffset[i] = 0; - nSampleBankSize[i] = 0; - nSampleBankMemoryStartAddress[i] = 0; - } - } - - // pedsfx - TRACE("pedsfx"); - { - for ( int32 i = 0; i < MAX_PEDSFX; i++ ) - { - nPedSlotSfx[i] = NO_SAMPLE; - nPedSlotSfxAddr[i] = 0; - } - - nCurrentPedSlot = 0; - } - - // channel volume - TRACE("vol"); - { - for ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ ) - nChannelVolume[i] = 0; - } - - TRACE("mss"); - { - AIL_set_redist_directory( "mss" ); - - AIL_startup(); - - AIL_set_preference(DIG_MIXER_CHANNELS, MAX_DIGITAL_MIXER_CHANNELS); - - DIG = AIL_open_digital_driver(DIGITALRATE, DIGITALBITS, DIGITALCHANNELS, 0); - if ( DIG == NULL ) - { - OutputDebugString(AIL_last_error()); - Terminate(); - return false; - } - - add_providers(); - - if ( !InitialiseSampleBanks() ) - { - Terminate(); - return false; - } - - nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = (int32)AIL_mem_alloc_lock(nSampleBankSize[SAMPLEBANK_MAIN]); - if ( !nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] ) - { - Terminate(); - return false; - } - - nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = (int32)AIL_mem_alloc_lock(PED_BLOCKSIZE*MAX_PEDSFX); - - } - - TRACE("cdrom"); - - S32 tatalms; - char filepath[MAX_PATH]; - - { - m_bInitialised = false; - - while (true) - { - int32 drive = 'C'; - - do - { - char latter[2]; - - latter[0] = drive; - latter[1] = '\0'; - - strcpy(m_szCDRomRootPath, latter); - strcat(m_szCDRomRootPath, ":\\"); - - if ( GetDriveType(m_szCDRomRootPath) == DRIVE_CDROM ) - { - strcpy(filepath, m_szCDRomRootPath); - strcat(filepath, StreamedNameTable[0]); - - FILE *f = fopen(filepath, "rb"); - - if ( f ) - { - fclose(f); - - bool bFileNotFound = false; - - for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) - { - strcpy(filepath, m_szCDRomRootPath); - strcat(filepath, StreamedNameTable[i]); - - mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); - - if ( mp3Stream[0] ) - { - AIL_stream_ms_position(mp3Stream[0], &tatalms, NULL); - - AIL_close_stream(mp3Stream[0]); - mp3Stream[0] = NULL; - - nStreamLength[i] = tatalms; - } - else - { - bFileNotFound = true; - break; - } - } - - if ( !bFileNotFound ) - { - m_bInitialised = true; - break; - } - else - { - m_bInitialised = false; - continue; - } - } - } - - } while ( ++drive <= 'Z' ); - - if ( !m_bInitialised ) - { -#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) - FrontEndMenuManager.WaitForUserCD(); - if ( FrontEndMenuManager.m_bQuitGameNoCD ) - { - Terminate(); - return false; - } - continue; -#else - m_bInitialised = true; -#endif - } - - break; - } - } - -#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) - // hddaudio - /** - Option for user to play audio files directly from hard disk. - Copy the contents of the PLAY discs Audio directory into your installed Grand Theft Auto III Audio directory. - Grand Theft Auto III still requires the presence of the PLAY disc when started. - This may give better performance on some machines (though worse on others). - **/ - TRACE("hddaudio 1.1 patch"); - { - int32 streamLength[TOTAL_STREAMED_SOUNDS]; - - bool bFileNotFound = false; - char rootpath[MAX_PATH]; - - strcpy(_aHDDPath, m_szCDRomRootPath); - rootpath[0] = '\0'; - - FILE *f = fopen(StreamedNameTable[0], "rb"); - - if ( f ) - { - fclose(f); - - for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) - { - strcpy(filepath, rootpath); - strcat(filepath, StreamedNameTable[i]); - - mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); - - if ( mp3Stream[0] ) - { - AIL_stream_ms_position(mp3Stream[0], &tatalms, NULL); - - AIL_close_stream(mp3Stream[0]); - mp3Stream[0] = NULL; - - streamLength[i] = tatalms; - } - else - { - bFileNotFound = true; - break; - } - } - - } - else - bFileNotFound = true; - - if ( !bFileNotFound ) - { - strcpy(m_szCDRomRootPath, rootpath); - - for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) - nStreamLength[i] = streamLength[i]; - - _bUseHDDAudio = true; - } - else - _bUseHDDAudio = false; - } -#endif - - TRACE("stream"); - { - for ( int32 i = 0; i < MAX_MP3STREAMS; i++ ) - { - mp3Stream [i] = NULL; - nStreamPan [i] = 63; - nStreamVolume[i] = 100; - } - } - - for ( int32 i = 0; i < MAX2DCHANNELS; i++ ) - { - opened_2dsamples[i] = AIL_allocate_sample_handle(DIG); - if ( opened_2dsamples[i] ) - { - AIL_init_sample(opened_2dsamples[i]); - AIL_set_sample_type(opened_2dsamples[i], DIG_F_MONO_16, DIG_PCM_SIGN); - } - } - - TRACE("providerset"); - { - _bSampmanInitialised = true; - - U32 n = 0; - - while ( n < m_nNumberOfProviders ) - { - if ( !strcmp(providers[n].name, "Miles Fast 2D Positional Audio") ) - { - set_new_provider(n); - break; - } - n++; - } - - if ( n == m_nNumberOfProviders ) - { - Terminate(); - return false; - } - } - - TRACE("bank"); - - LoadSampleBank(SAMPLEBANK_MAIN); - - // mp3 - TRACE("mp3"); - { - nNumMP3s = 0; - - _pMP3List = NULL; - - _FindMP3s(); - - if ( nNumMP3s != 0 ) - { - nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] = 0; - - for ( tMP3Entry *e = _pMP3List; e != NULL; e = e->pNext ) - { - e->nTrackStreamPos = nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER]; - nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] += e->nTrackLength; - } - - time_t t = time(NULL); - tm *localtm; - bool bUseRandomTable; - - if ( t == -1 ) - bUseRandomTable = true; - else - { - bUseRandomTable = false; - localtm = localtime(&t); - } - - int32 randval; - if ( bUseRandomTable ) - randval = AudioManager.GetRandomNumber(1); - else - randval = localtm->tm_sec * localtm->tm_min; - - _CurMP3Index = randval % nNumMP3s; - - tMP3Entry *randmp3 = _pMP3List; - for ( int32 i = randval % nNumMP3s; i > 0; --i) - randmp3 = randmp3->pNext; - - if ( bUseRandomTable ) - _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; - else - { - if ( localtm->tm_sec > 0 ) - { - int32 s = localtm->tm_sec; - _CurMP3Pos = s*s*s*s*s*s*s*s % randmp3->nTrackLength; - } - else - _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; - } - } - else - _CurMP3Pos = 0; - - _bIsMp3Active = false; - } - - TRACE("end"); - - return true; -} - -void -cSampleManager::Terminate(void) -{ - for ( int32 i = 0; i < MAX_MP3STREAMS; i++ ) - { - if ( mp3Stream[i] ) - { - AIL_pause_stream(mp3Stream[i], 1); - AIL_close_stream(mp3Stream[i]); - mp3Stream[i] = NULL; - } - } - - for ( int32 i = 0; i < MAX2DCHANNELS; i++ ) - { - if ( opened_2dsamples[i] ) - { - AIL_release_sample_handle(opened_2dsamples[i]); - opened_2dsamples[i] = NULL; - } - } - - release_existing(); - - _DeleteMP3Entries(); - - if ( nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] != 0 ) - { - AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN]); - nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = 0; - } - - if ( nSampleBankMemoryStartAddress[SAMPLEBANK_PED] != 0 ) - { - AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_PED]); - nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = 0; - } - - if ( DIG ) - { - AIL_close_digital_driver(DIG); - DIG = NULL; - } - - AIL_shutdown(); - - _bSampmanInitialised = false; -} - -bool -cSampleManager::CheckForAnAudioFileOnCD(void) -{ -#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) - char filepath[MAX_PATH]; - -#if defined(GTA3_1_1_PATCH) - if (_bUseHDDAudio) - strcpy(filepath, _aHDDPath); - else - strcpy(filepath, m_szCDRomRootPath); -#else - strcpy(filepath, m_szCDRomRootPath); -#endif // #if defined(GTA3_1_1_PATCH) - - strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]); - - FILE *f = fopen(filepath, "rb"); - - if ( f ) - { - fclose(f); - - return true; - } - - return false; - -#else - return true; -#endif // #if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) -} - -char -cSampleManager::GetCDAudioDriveLetter(void) -{ -#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) - if (_bUseHDDAudio) - { - if ( strlen(_aHDDPath) != 0 ) - return _aHDDPath[0]; - else - return '\0'; - } - else - { - if ( strlen(m_szCDRomRootPath) != 0 ) - return m_szCDRomRootPath[0]; - else - return '\0'; - } -#else - if ( strlen(m_szCDRomRootPath) != 0 ) - return m_szCDRomRootPath[0]; - else - return '\0'; -#endif -} - -void -cSampleManager::UpdateEffectsVolume(void) //[Y], cSampleManager::UpdateSoundBuffers ? -{ - if ( _bSampmanInitialised ) - { - for ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ ) - { - if ( i < MAXCHANNELS ) - { - if ( opened_samples[i] && GetChannelUsedFlag(i) ) - { - if ( nChannelVolume[i] ) - { - AIL_set_3D_sample_volume(opened_samples[i], - m_nEffectsFadeVolume * nChannelVolume[i] * m_nEffectsVolume >> 14); - } - } - } - else - { - if ( opened_2dsamples[i - MAXCHANNELS] ) - { - if ( GetChannelUsedFlag(i - MAXCHANNELS) ) - { - if ( nChannelVolume[i - MAXCHANNELS] ) - { - AIL_set_sample_volume(opened_2dsamples[i - MAXCHANNELS], - m_nEffectsFadeVolume * nChannelVolume[i - MAXCHANNELS] * m_nEffectsVolume >> 14); - } - } - } - } - } - } -} - -void -cSampleManager::SetEffectsMasterVolume(uint8 nVolume) -{ - m_nEffectsVolume = nVolume; - UpdateEffectsVolume(); -} - -void -cSampleManager::SetMusicMasterVolume(uint8 nVolume) -{ - m_nMusicVolume = nVolume; -} - -void -cSampleManager::SetEffectsFadeVolume(uint8 nVolume) -{ - m_nEffectsFadeVolume = nVolume; - UpdateEffectsVolume(); -} - -void -cSampleManager::SetMusicFadeVolume(uint8 nVolume) -{ - m_nMusicFadeVolume = nVolume; -} - -bool -cSampleManager::LoadSampleBank(uint8 nBank) -{ - if ( CTimer::GetIsCodePaused() ) - return false; - - if ( MusicManager.IsInitialised() - && MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE - && nBank != SAMPLEBANK_MAIN ) - { - return false; - } - - if ( fseek(fpSampleDataHandle, nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 ) - return false; - - if ( fread((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank],fpSampleDataHandle) != nSampleBankSize[nBank] ) - return false; - - bSampleBankLoaded[nBank] = true; - - return true; -} - -void -cSampleManager::UnloadSampleBank(uint8 nBank) -{ - bSampleBankLoaded[nBank] = false; -} - -bool -cSampleManager::IsSampleBankLoaded(uint8 nBank) -{ - return bSampleBankLoaded[nBank]; -} - -bool -cSampleManager::IsPedCommentLoaded(uint32 nComment) -{ - uint8 slot; - - for ( int32 i = 0; i < _TODOCONST(3); i++ ) - { - slot = nCurrentPedSlot - i - 1; - if ( nComment == nPedSlotSfx[slot] ) - return true; - } - - return false; -} - -int32 -cSampleManager::_GetPedCommentSlot(uint32 nComment) -{ - uint8 slot; - - for ( int32 i = 0; i < _TODOCONST(3); i++ ) - { - slot = nCurrentPedSlot - i - 1; - if ( nComment == nPedSlotSfx[slot] ) - return slot; - } - - return -1; -} - -bool -cSampleManager::LoadPedComment(uint32 nComment) -{ - if ( CTimer::GetIsCodePaused() ) - return false; - - // no talking peds during cutsenes or the game end - if ( MusicManager.IsInitialised() ) - { - switch ( MusicManager.GetMusicMode() ) - { - case MUSICMODE_CUTSCENE: - { - return false; - - break; - } - - case MUSICMODE_FRONTEND: - { - if ( MusicManager.GetCurrentTrack() == STREAMED_SOUND_GAME_COMPLETED ) - return false; - - break; - } - } - } - - if ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 ) - return false; - - if ( fread((void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize ) - return false; - - nPedSlotSfxAddr[nCurrentPedSlot] = nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot; - nPedSlotSfx [nCurrentPedSlot] = nComment; - - if ( ++nCurrentPedSlot >= MAX_PEDSFX ) - nCurrentPedSlot = 0; - - return true; -} - -int32 -cSampleManager::GetSampleBaseFrequency(uint32 nSample) -{ - return m_aSamples[nSample].nFrequency; -} - -int32 -cSampleManager::GetSampleLoopStartOffset(uint32 nSample) -{ - return m_aSamples[nSample].nLoopStart; -} - -int32 -cSampleManager::GetSampleLoopEndOffset(uint32 nSample) -{ - return m_aSamples[nSample].nLoopEnd; -} - -uint32 -cSampleManager::GetSampleLength(uint32 nSample) -{ - return m_aSamples[nSample].nSize >> 1; -} - -bool -cSampleManager::UpdateReverb(void) -{ - if ( !usingEAX ) - return false; - - if ( AudioManager.GetFrameCounter() & 15 ) - return false; - - float y = AudioManager.GetReflectionsDistance(REFLECTION_TOP) + AudioManager.GetReflectionsDistance(REFLECTION_BOTTOM); - float x = AudioManager.GetReflectionsDistance(REFLECTION_LEFT) + AudioManager.GetReflectionsDistance(REFLECTION_RIGHT); - float z = AudioManager.GetReflectionsDistance(REFLECTION_UP); - - float normy = norm(y, 5.0f, 40.0f); - float normx = norm(x, 5.0f, 40.0f); - float normz = norm(z, 5.0f, 40.0f); - - float fRatio; - - if ( normy == 0.0f ) - { - if ( normx == 0.0f ) - { - if ( normz == 0.0f ) - fRatio = 0.3f; - else - fRatio = 0.5f; - } - else - { - fRatio = 0.3f; - } - } - else - { - if ( normx == 0.0f ) - { - if ( normz == 0.0f ) - fRatio = 0.3f; - else - fRatio = 0.5f; - } - else - { - if ( normz == 0.0f ) - fRatio = 0.3f; - else - fRatio = (normy+normx+normz) / 3.0f; - } - } - - fRatio = clamp(fRatio, usingEAX3==1 ? 0.0f : 0.30f, 1.0f); - - if ( fRatio == _fPrevEaxRatioDestination ) - return false; - - if ( usingEAX3 ) - { - if ( EAX3ListenerInterpolate(&StartEAX3, &FinishEAX3, fRatio, &EAX3Params, false) ) - { - AIL_set_3D_provider_preference(opened_provider, "EAX all parameters", &EAX3Params); - _fEffectsLevel = 1.0f - fRatio * 0.5f; - } - } - else - { - if ( _usingMilesFast2D ) - _fEffectsLevel = (1.0f - fRatio) * 0.4f; - else - _fEffectsLevel = (1.0f - fRatio) * 0.7f; - } - - _fPrevEaxRatioDestination = fRatio; - - return true; -} - -void -cSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag) -{ - bool b2d = false; - - switch ( nChannel ) - { - case CHANNEL2D: - { - b2d = true; - break; - } - } - - if ( usingEAX ) - { - if ( nReverbFlag != 0 ) - { - if ( !b2d ) - AIL_set_3D_sample_effects_level(opened_samples[nChannel], _fEffectsLevel); - } - else - { - if ( !b2d ) - AIL_set_3D_sample_effects_level(opened_samples[nChannel], 0.0f); - } - } -} - -bool -cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank) -{ - bool b2d = false; - - switch ( nChannel ) - { - case CHANNEL2D: - { - b2d = true; - break; - } - } - - int32 addr; - - if ( nSfx < SAMPLEBANK_MAX ) - { - if ( !IsSampleBankLoaded(nBank) ) - return false; - - addr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset; - } - else - { - if ( !IsPedCommentLoaded(nSfx) ) - return false; - - int32 slot = _GetPedCommentSlot(nSfx); - - addr = nPedSlotSfxAddr[slot]; - } - - if ( b2d ) - { - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) - { - AIL_set_sample_address(opened_2dsamples[nChannel - MAXCHANNELS], (void *)addr, m_aSamples[nSfx].nSize); - return true; - } - else - return false; - } - else - { - AILSOUNDINFO info; - - info.format = WAVE_FORMAT_PCM; - info.data_ptr = (void *)addr; - info.channels = 1; - info.data_len = m_aSamples[nSfx].nSize; - info.rate = m_aSamples[nSfx].nFrequency; - info.bits = 16; - - if ( AIL_set_3D_sample_info(opened_samples[nChannel], &info) == 0 ) - { - OutputDebugString(AIL_last_error()); - return false; - } - - return true; - } -} - -void -cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume) -{ - uint32 vol = nVolume; - if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; - - nChannelVolume[nChannel] = vol; - - // increase the volume for JB.MP3 and S4_BDBD.MP3 - if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE - && MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO - && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD ) - { - nChannelVolume[nChannel] >>= 2; - } - - if ( opened_samples[nChannel] ) - AIL_set_3D_sample_volume(opened_samples[nChannel], m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14); - -} - -void -cSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ) -{ - if ( opened_samples[nChannel] ) - AIL_set_3D_position(opened_samples[nChannel], -fX, fY, fZ); -} - -void -cSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin) -{ - if ( opened_samples[nChannel] ) - AIL_set_3D_sample_distances(opened_samples[nChannel], fMax, fMin); -} - -void -cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume) -{ - uint32 vol = nVolume; - if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; - - switch ( nChannel ) - { - case CHANNEL2D: - { - nChannelVolume[nChannel] = vol; - - // increase the volume for JB.MP3 and S4_BDBD.MP3 - if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE - && MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO - && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD ) - { - nChannelVolume[nChannel] >>= 2; - } - - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) - { - AIL_set_sample_volume(opened_2dsamples[nChannel - MAXCHANNELS], - m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14); - } - - break; - } - } -} - -void -cSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan) -{ - switch ( nChannel ) - { - case CHANNEL2D: - { -#ifndef FIX_BUGS - if ( opened_samples[nChannel - MAXCHANNELS] ) // BUG -#else - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) -#endif - AIL_set_sample_pan(opened_2dsamples[nChannel - MAXCHANNELS], nPan); - - break; - } - } -} - -void -cSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq) -{ - bool b2d = false; - - switch ( nChannel ) - { - case CHANNEL2D: - { - b2d = true; - break; - } - } - - if ( b2d ) - { - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) - AIL_set_sample_playback_rate(opened_2dsamples[nChannel - MAXCHANNELS], nFreq); - } - else - { - if ( opened_samples[nChannel] ) - AIL_set_3D_sample_playback_rate(opened_samples[nChannel], nFreq); - } -} - -void -cSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd) -{ - bool b2d = false; - - switch ( nChannel ) - { - case CHANNEL2D: - { - b2d = true; - break; - } - } - - if ( b2d ) - { - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) - AIL_set_sample_loop_block(opened_2dsamples[nChannel - MAXCHANNELS], nLoopStart, nLoopEnd); - } - else - { - if ( opened_samples[nChannel] ) - AIL_set_3D_sample_loop_block(opened_samples[nChannel], nLoopStart, nLoopEnd); - } -} - -void -cSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount) -{ - bool b2d = false; - - switch ( nChannel ) - { - case CHANNEL2D: - { - b2d = true; - break; - } - } - - if ( b2d ) - { - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) - AIL_set_sample_loop_count(opened_2dsamples[nChannel - MAXCHANNELS], nLoopCount); - } - else - { - if ( opened_samples[nChannel] ) - AIL_set_3D_sample_loop_count(opened_samples[nChannel], nLoopCount); - } -} - -bool -cSampleManager::GetChannelUsedFlag(uint32 nChannel) -{ - bool b2d = false; - - switch ( nChannel ) - { - case CHANNEL2D: - { - b2d = true; - break; - } - } - - if ( b2d ) - { - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) - return AIL_sample_status(opened_2dsamples[nChannel - MAXCHANNELS]) == SMP_PLAYING; - else - return false; - } - else - { - if ( opened_samples[nChannel] ) - return AIL_3D_sample_status(opened_samples[nChannel]) == SMP_PLAYING; - else - return false; - } - -} - -void -cSampleManager::StartChannel(uint32 nChannel) -{ - bool b2d = false; - - switch ( nChannel ) - { - case CHANNEL2D: - { - b2d = true; - break; - } - } - - if ( b2d ) - { - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) - AIL_start_sample(opened_2dsamples[nChannel - MAXCHANNELS]); - } - else - { - if ( opened_samples[nChannel] ) - AIL_start_3D_sample(opened_samples[nChannel]); - } -} - -void -cSampleManager::StopChannel(uint32 nChannel) -{ - bool b2d = false; - - switch ( nChannel ) - { - case CHANNEL2D: - { - b2d = true; - break; - } - } - - if ( b2d ) - { - if ( opened_2dsamples[nChannel - MAXCHANNELS] ) - AIL_end_sample(opened_2dsamples[nChannel - MAXCHANNELS]); - } - else - { - if ( opened_samples[nChannel] ) - { - if ( AIL_3D_sample_status(opened_samples[nChannel]) == SMP_PLAYING ) - AIL_end_3D_sample(opened_samples[nChannel]); - } - } -} - -void -cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) -{ - if ( m_bInitialised ) - { - if ( nFile < TOTAL_STREAMED_SOUNDS ) - { - if ( mp3Stream[nStream] ) - { - AIL_pause_stream(mp3Stream[nStream], 1); - AIL_close_stream(mp3Stream[nStream]); - } - - char filepath[MAX_PATH]; - - strcpy(filepath, m_szCDRomRootPath); - strcat(filepath, StreamedNameTable[nFile]); - - mp3Stream[nStream] = AIL_open_stream(DIG, filepath, 0); - - if ( mp3Stream[nStream] ) - { - AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_service_stream(mp3Stream[nStream], 1); - } - else - OutputDebugString(AIL_last_error()); - } - } -} - -void -cSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream) -{ - if ( m_bInitialised ) - { - if ( mp3Stream[nStream] ) - AIL_pause_stream(mp3Stream[nStream], nPauseFlag != 0); - } -} - -void -cSampleManager::StartPreloadedStreamedFile(uint8 nStream) -{ - if ( m_bInitialised ) - { - if ( mp3Stream[nStream] ) - AIL_start_stream(mp3Stream[nStream]); - } -} - -bool -cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) -{ - uint32 position = nPos; - char filename[MAX_PATH]; - - if ( m_bInitialised && nFile < TOTAL_STREAMED_SOUNDS ) - { - if ( mp3Stream[nStream] ) - { - AIL_pause_stream(mp3Stream[nStream], 1); - AIL_close_stream(mp3Stream[nStream]); - } - - if ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER ) - { - uint32 i = 0; - do { - if(i != 0 || _bIsMp3Active) { - if(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0; - - _CurMP3Pos = 0; - - tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); - - if(mp3) { - mp3 = _pMP3List; - if(mp3 == NULL) { - _bIsMp3Active = false; - nFile = 0; - strcpy(filename, m_szCDRomRootPath); - strcat(filename, StreamedNameTable[nFile]); - - mp3Stream[nStream] = - AIL_open_stream(DIG, filename, 0); - if(mp3Stream[nStream]) { - AIL_set_stream_loop_count( - mp3Stream[nStream], 1); - AIL_set_stream_ms_position( - mp3Stream[nStream], position); - AIL_pause_stream(mp3Stream[nStream], - 0); - return true; - } - - return false; - } - } - - if(mp3->pLinkPath != NULL) - mp3Stream[nStream] = - AIL_open_stream(DIG, mp3->pLinkPath, 0); - else { - strcpy(filename, _mp3DirectoryPath); - strcat(filename, mp3->aFilename); - - mp3Stream[nStream] = - AIL_open_stream(DIG, filename, 0); - } - - if(mp3Stream[nStream]) { - AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_set_stream_ms_position(mp3Stream[nStream], 0); - AIL_pause_stream(mp3Stream[nStream], 0); - return true; - } - - _bIsMp3Active = false; - continue; - } - if ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] ) - position = 0; - - tMP3Entry *e; - if ( !_GetMP3PosFromStreamPos(&position, &e) ) - { - if ( e == NULL ) - { - nFile = 0; - strcpy(filename, m_szCDRomRootPath); - strcat(filename, StreamedNameTable[nFile]); - mp3Stream[nStream] = - AIL_open_stream(DIG, filename, 0); - if(mp3Stream[nStream]) { - AIL_set_stream_loop_count( - mp3Stream[nStream], 1); - AIL_set_stream_ms_position( - mp3Stream[nStream], position); - AIL_pause_stream(mp3Stream[nStream], 0); - return true; - } - - return false; - } - } - - if ( e->pLinkPath != NULL ) - mp3Stream[nStream] = AIL_open_stream(DIG, e->pLinkPath, 0); - else - { - strcpy(filename, _mp3DirectoryPath); - strcat(filename, e->aFilename); - - mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); - } - - if ( mp3Stream[nStream] ) - { - AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_set_stream_ms_position(mp3Stream[nStream], position); - AIL_pause_stream(mp3Stream[nStream], 0); - - _bIsMp3Active = true; - - return true; - } - - _bIsMp3Active = false; - - } while(++i < nNumMP3s); - - position = 0; - nFile = 0; - } - - strcpy(filename, m_szCDRomRootPath); - strcat(filename, StreamedNameTable[nFile]); - - mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); - if ( mp3Stream[nStream] ) - { - AIL_set_stream_loop_count(mp3Stream[nStream], 1); - AIL_set_stream_ms_position(mp3Stream[nStream], position); - AIL_pause_stream(mp3Stream[nStream], 0); - return true; - } - } - - return false; -} - -void -cSampleManager::StopStreamedFile(uint8 nStream) -{ - if ( m_bInitialised ) - { - if ( mp3Stream[nStream] ) - { - AIL_pause_stream(mp3Stream[nStream], 1); - - AIL_close_stream(mp3Stream[nStream]); - mp3Stream[nStream] = NULL; - - if ( nStream == 0 ) - _bIsMp3Active = false; - } - } -} - -int32 -cSampleManager::GetStreamedFilePosition(uint8 nStream) -{ - S32 currentms; - - if ( m_bInitialised ) - { - if ( mp3Stream[nStream] ) - { - if ( _bIsMp3Active ) - { - tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); - - if ( mp3 != NULL ) - { - AIL_stream_ms_position(mp3Stream[nStream], NULL, ¤tms); - return currentms + mp3->nTrackStreamPos; - } - else - return 0; - } - else - { - AIL_stream_ms_position(mp3Stream[nStream], NULL, ¤tms); - return currentms; - } - } - } - - return 0; -} - -void -cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream) -{ - uint8 vol = nVolume; - - if ( m_bInitialised ) - { - if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; - if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; - - nStreamVolume[nStream] = vol; - nStreamPan[nStream] = nPan; - - if ( mp3Stream[nStream] ) - { - if ( nEffectFlag ) - AIL_set_stream_volume(mp3Stream[nStream], m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14); - else - AIL_set_stream_volume(mp3Stream[nStream], m_nMusicFadeVolume*vol*m_nMusicVolume >> 14); - - AIL_set_stream_pan(mp3Stream[nStream], nPan); - } - } -} - -int32 -cSampleManager::GetStreamedFileLength(uint8 nStream) -{ - if ( m_bInitialised ) - return nStreamLength[nStream]; - - return 0; -} - -bool -cSampleManager::IsStreamPlaying(uint8 nStream) -{ - if ( m_bInitialised ) - { - if ( mp3Stream[nStream] ) - { - if ( AIL_stream_status(mp3Stream[nStream]) == SMP_PLAYING ) - return true; - else - return false; - } - } - - return false; -} - -bool -cSampleManager::InitialiseSampleBanks(void) -{ - int32 nBank = SAMPLEBANK_MAIN; - - fpSampleDescHandle = fopen(SampleBankDescFilename, "rb"); - if ( fpSampleDescHandle == NULL ) - return false; - - fpSampleDataHandle = fopen(SampleBankDataFilename, "rb"); - if ( fpSampleDataHandle == NULL ) - { - fclose(fpSampleDescHandle); - fpSampleDescHandle = NULL; - - return false; - } - - fseek(fpSampleDataHandle, 0, SEEK_END); - _nSampleDataEndOffset = ftell(fpSampleDataHandle); - rewind(fpSampleDataHandle); - - fread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle); - - fclose(fpSampleDescHandle); - fpSampleDescHandle = NULL; - - for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) - { -#ifdef FIX_BUGS - if (nBank >= MAX_SAMPLEBANKS) break; -#endif - if ( BankStartOffset[nBank] == BankStartOffset[SAMPLEBANK_MAIN] + i ) - { - nSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset; - nBank++; - } - } - - nSampleBankSize[SAMPLEBANK_MAIN] = nSampleBankDiscStartOffset[SAMPLEBANK_PED] - nSampleBankDiscStartOffset[SAMPLEBANK_MAIN]; - nSampleBankSize[SAMPLEBANK_PED] = _nSampleDataEndOffset - nSampleBankDiscStartOffset[SAMPLEBANK_PED]; - - return true; -} +#include "openal\samp_oal.cpp" +#endif \ No newline at end of file diff --git a/src/audio/sampman.h b/src/audio/sampman.h index ebedfb63..f454d236 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -1,339 +1,7 @@ #pragma once #include "common.h" -#include "AudioSamples.h" - -#define MAX_VOLUME 127 - -struct tSample { - int32 nOffset; - uint32 nSize; - int32 nFrequency; - int32 nLoopStart; - int32 nLoopEnd; -}; - -enum -{ - SAMPLEBANK_MAIN, - SAMPLEBANK_PED, - MAX_SAMPLEBANKS, - SAMPLEBANK_INVALID -}; - -#define MAX_PEDSFX 7 -#define PED_BLOCKSIZE 79000 - -#define MAXPROVIDERS 64 - -#define MAXCHANNELS 28 -#define MAXCHANNELS_SURROUND 24 -#define MAX2DCHANNELS 1 -#define CHANNEL2D MAXCHANNELS - -#define MAX_MP3STREAMS 2 - -#define DIGITALRATE 32000 -#define DIGITALBITS 16 -#define DIGITALCHANNELS 2 - -#define MAX_DIGITAL_MIXER_CHANNELS 32 - -class cSampleManager -{ - uint8 m_nEffectsVolume; - uint8 m_nMusicVolume; - uint8 m_nEffectsFadeVolume; - uint8 m_nMusicFadeVolume; - uint8 m_nMonoMode; - char unk; - char m_szCDRomRootPath[80]; - bool m_bInitialised; - uint8 m_nNumberOfProviders; - char *m_aAudioProviders[MAXPROVIDERS]; - tSample m_aSamples[TOTAL_AUDIO_SAMPLES]; - -public: - - - - cSampleManager(void) : - m_nNumberOfProviders(0) - { } - - ~cSampleManager(void) - { } - - void SetSpeakerConfig(int32 nConfig); - uint32 GetMaximumSupportedChannels(void); - - uint32 GetNum3DProvidersAvailable() { return m_nNumberOfProviders; } - void SetNum3DProvidersAvailable(uint32 num) { m_nNumberOfProviders = num; } - - char *Get3DProviderName(uint8 id) { return m_aAudioProviders[id]; } - void Set3DProviderName(uint8 id, char *name) { m_aAudioProviders[id] = name; } - - int8 GetCurrent3DProviderIndex(void); - int8 SetCurrent3DProvider(uint8 which); - - bool IsMP3RadioChannelAvailable(void); - - void ReleaseDigitalHandle (void); - void ReacquireDigitalHandle(void); - - bool Initialise(void); - void Terminate (void); - - bool CheckForAnAudioFileOnCD(void); - char GetCDAudioDriveLetter (void); - - void UpdateEffectsVolume(void); - - void SetEffectsMasterVolume(uint8 nVolume); - void SetMusicMasterVolume (uint8 nVolume); - void SetEffectsFadeVolume (uint8 nVolume); - void SetMusicFadeVolume (uint8 nVolume); - - bool LoadSampleBank (uint8 nBank); - void UnloadSampleBank (uint8 nBank); - bool IsSampleBankLoaded(uint8 nBank); - - bool IsPedCommentLoaded(uint32 nComment); - bool LoadPedComment (uint32 nComment); - - int32 _GetPedCommentSlot(uint32 nComment); - - int32 GetSampleBaseFrequency (uint32 nSample); - int32 GetSampleLoopStartOffset(uint32 nSample); - int32 GetSampleLoopEndOffset (uint32 nSample); - uint32 GetSampleLength (uint32 nSample); - - bool UpdateReverb(void); - - void SetChannelReverbFlag (uint32 nChannel, uint8 nReverbFlag); - bool InitialiseChannel (uint32 nChannel, uint32 nSfx, uint8 nBank); - void SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume); - void SetChannel3DPosition (uint32 nChannel, float fX, float fY, float fZ); - void SetChannel3DDistances (uint32 nChannel, float fMax, float fMin); - void SetChannelVolume (uint32 nChannel, uint32 nVolume); - void SetChannelPan (uint32 nChannel, uint32 nPan); - void SetChannelFrequency (uint32 nChannel, uint32 nFreq); - void SetChannelLoopPoints (uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd); - void SetChannelLoopCount (uint32 nChannel, uint32 nLoopCount); - bool GetChannelUsedFlag (uint32 nChannel); - void StartChannel (uint32 nChannel); - void StopChannel (uint32 nChannel); - - void PreloadStreamedFile (uint8 nFile, uint8 nStream); - void PauseStream (uint8 nPauseFlag, uint8 nStream); - void StartPreloadedStreamedFile (uint8 nStream); - bool StartStreamedFile (uint8 nFile, uint32 nPos, uint8 nStream); - void StopStreamedFile (uint8 nStream); - int32 GetStreamedFilePosition (uint8 nStream); - void SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream); - int32 GetStreamedFileLength (uint8 nStream); - bool IsStreamPlaying (uint8 nStream); - bool InitialiseSampleBanks(void); -}; - -extern cSampleManager SampleManager; -extern int32 BankStartOffset[MAX_SAMPLEBANKS]; - -static char StreamedNameTable[][25]= -{ - "AUDIO\\HEAD.WAV", - "AUDIO\\CLASS.WAV", - "AUDIO\\KJAH.WAV", - "AUDIO\\RISE.WAV", - "AUDIO\\LIPS.WAV", - "AUDIO\\GAME.WAV", - "AUDIO\\MSX.WAV", - "AUDIO\\FLASH.WAV", - "AUDIO\\CHAT.WAV", - "AUDIO\\HEAD.WAV", - "AUDIO\\POLICE.WAV", - "AUDIO\\CITY.WAV", - "AUDIO\\WATER.WAV", - "AUDIO\\COMOPEN.WAV", - "AUDIO\\SUBOPEN.WAV", - "AUDIO\\JB.MP3", - "AUDIO\\BET.MP3", - "AUDIO\\L1_LG.MP3", - "AUDIO\\L2_DSB.MP3", - "AUDIO\\L3_DM.MP3", - "AUDIO\\L4_PAP.MP3", - "AUDIO\\L5_TFB.MP3", - "AUDIO\\J0_DM2.MP3", - "AUDIO\\J1_LFL.MP3", - "AUDIO\\J2_KCL.MP3", - "AUDIO\\J3_VH.MP3", - "AUDIO\\J4_ETH.MP3", - "AUDIO\\J5_DST.MP3", - "AUDIO\\J6_TBJ.MP3", - "AUDIO\\T1_TOL.MP3", - "AUDIO\\T2_TPU.MP3", - "AUDIO\\T3_MAS.MP3", - "AUDIO\\T4_TAT.MP3", - "AUDIO\\T5_BF.MP3", - "AUDIO\\S0_MAS.MP3", - "AUDIO\\S1_PF.MP3", - "AUDIO\\S2_CTG.MP3", - "AUDIO\\S3_RTC.MP3", - "AUDIO\\S5_LRQ.MP3", - "AUDIO\\S4_BDBA.MP3", - "AUDIO\\S4_BDBB.MP3", - "AUDIO\\S2_CTG2.MP3", - "AUDIO\\S4_BDBD.MP3", - "AUDIO\\S5_LRQB.MP3", - "AUDIO\\S5_LRQC.MP3", - "AUDIO\\A1_SSO.WAV", - "AUDIO\\A2_PP.WAV", - "AUDIO\\A3_SS.WAV", - "AUDIO\\A4_PDR.WAV", - "AUDIO\\A5_K2FT.WAV", - "AUDIO\\K1_KBO.MP3", - "AUDIO\\K2_GIS.MP3", - "AUDIO\\K3_DS.MP3", - "AUDIO\\K4_SHI.MP3", - "AUDIO\\K5_SD.MP3", - "AUDIO\\R0_PDR2.MP3", - "AUDIO\\R1_SW.MP3", - "AUDIO\\R2_AP.MP3", - "AUDIO\\R3_ED.MP3", - "AUDIO\\R4_GF.MP3", - "AUDIO\\R5_PB.MP3", - "AUDIO\\R6_MM.MP3", - "AUDIO\\D1_STOG.MP3", - "AUDIO\\D2_KK.MP3", - "AUDIO\\D3_ADO.MP3", - "AUDIO\\D5_ES.MP3", - "AUDIO\\D7_MLD.MP3", - "AUDIO\\D4_GTA.MP3", - "AUDIO\\D4_GTA2.MP3", - "AUDIO\\D6_STS.MP3", - "AUDIO\\A6_BAIT.WAV", - "AUDIO\\A7_ETG.WAV", - "AUDIO\\A8_PS.WAV", - "AUDIO\\A9_ASD.WAV", - "AUDIO\\K4_SHI2.MP3", - "AUDIO\\C1_TEX.MP3", - "AUDIO\\EL_PH1.MP3", - "AUDIO\\EL_PH2.MP3", - "AUDIO\\EL_PH3.MP3", - "AUDIO\\EL_PH4.MP3", - "AUDIO\\YD_PH1.MP3", - "AUDIO\\YD_PH2.MP3", - "AUDIO\\YD_PH3.MP3", - "AUDIO\\YD_PH4.MP3", - "AUDIO\\HD_PH1.MP3", - "AUDIO\\HD_PH2.MP3", - "AUDIO\\HD_PH3.MP3", - "AUDIO\\HD_PH4.MP3", - "AUDIO\\HD_PH5.MP3", - "AUDIO\\MT_PH1.MP3", - "AUDIO\\MT_PH2.MP3", - "AUDIO\\MT_PH3.MP3", - "AUDIO\\MT_PH4.MP3", - "AUDIO\\MISCOM.WAV", - "AUDIO\\END.MP3", - "AUDIO\\lib_a1.WAV", - "AUDIO\\lib_a2.WAV", - "AUDIO\\lib_a.WAV", - "AUDIO\\lib_b.WAV", - "AUDIO\\lib_c.WAV", - "AUDIO\\lib_d.WAV", - "AUDIO\\l2_a.WAV", - "AUDIO\\j4t_1.WAV", - "AUDIO\\j4t_2.WAV", - "AUDIO\\j4t_3.WAV", - "AUDIO\\j4t_4.WAV", - "AUDIO\\j4_a.WAV", - "AUDIO\\j4_b.WAV", - "AUDIO\\j4_c.WAV", - "AUDIO\\j4_d.WAV", - "AUDIO\\j4_e.WAV", - "AUDIO\\j4_f.WAV", - "AUDIO\\j6_1.WAV", - "AUDIO\\j6_a.WAV", - "AUDIO\\j6_b.WAV", - "AUDIO\\j6_c.WAV", - "AUDIO\\j6_d.WAV", - "AUDIO\\t4_a.WAV", - "AUDIO\\s1_a.WAV", - "AUDIO\\s1_a1.WAV", - "AUDIO\\s1_b.WAV", - "AUDIO\\s1_c.WAV", - "AUDIO\\s1_c1.WAV", - "AUDIO\\s1_d.WAV", - "AUDIO\\s1_e.WAV", - "AUDIO\\s1_f.WAV", - "AUDIO\\s1_g.WAV", - "AUDIO\\s1_h.WAV", - "AUDIO\\s1_i.WAV", - "AUDIO\\s1_j.WAV", - "AUDIO\\s1_k.WAV", - "AUDIO\\s1_l.WAV", - "AUDIO\\s3_a.WAV", - "AUDIO\\s3_b.WAV", - "AUDIO\\el3_a.WAV", - "AUDIO\\mf1_a.WAV", - "AUDIO\\mf2_a.WAV", - "AUDIO\\mf3_a.WAV", - "AUDIO\\mf3_b.WAV", - "AUDIO\\mf3_b1.WAV", - "AUDIO\\mf3_c.WAV", - "AUDIO\\mf4_a.WAV", - "AUDIO\\mf4_b.WAV", - "AUDIO\\mf4_c.WAV", - "AUDIO\\a1_a.WAV", - "AUDIO\\a3_a.WAV", - "AUDIO\\a5_a.WAV", - "AUDIO\\a4_a.WAV", - "AUDIO\\a4_b.WAV", - "AUDIO\\a4_c.WAV", - "AUDIO\\a4_d.WAV", - "AUDIO\\k1_a.WAV", - "AUDIO\\k3_a.WAV", - "AUDIO\\r1_a.WAV", - "AUDIO\\r2_a.WAV", - "AUDIO\\r2_b.WAV", - "AUDIO\\r2_c.WAV", - "AUDIO\\r2_d.WAV", - "AUDIO\\r2_e.WAV", - "AUDIO\\r2_f.WAV", - "AUDIO\\r2_g.WAV", - "AUDIO\\r2_h.WAV", - "AUDIO\\r5_a.WAV", - "AUDIO\\r6_a.WAV", - "AUDIO\\r6_a1.WAV", - "AUDIO\\r6_b.WAV", - "AUDIO\\lo2_a.WAV", - "AUDIO\\lo6_a.WAV", - "AUDIO\\yd2_a.WAV", - "AUDIO\\yd2_b.WAV", - "AUDIO\\yd2_c.WAV", - "AUDIO\\yd2_c1.WAV", - "AUDIO\\yd2_d.WAV", - "AUDIO\\yd2_e.WAV", - "AUDIO\\yd2_f.WAV", - "AUDIO\\yd2_g.WAV", - "AUDIO\\yd2_h.WAV", - "AUDIO\\yd2_ass.WAV", - "AUDIO\\yd2_ok.WAV", - "AUDIO\\h5_a.WAV", - "AUDIO\\h5_b.WAV", - "AUDIO\\h5_c.WAV", - "AUDIO\\ammu_a.WAV", - "AUDIO\\ammu_b.WAV", - "AUDIO\\ammu_c.WAV", - "AUDIO\\door_1.WAV", - "AUDIO\\door_2.WAV", - "AUDIO\\door_3.WAV", - "AUDIO\\door_4.WAV", - "AUDIO\\door_5.WAV", - "AUDIO\\door_6.WAV", - "AUDIO\\t3_a.WAV", - "AUDIO\\t3_b.WAV", - "AUDIO\\t3_c.WAV", - "AUDIO\\k1_b.WAV", - "AUDIO\\cat1.WAV" -}; +#ifndef OPENAL +#include "miles\sampman_mss.h" +#else +#include "openal\samp_oal.h" +#endif \ No newline at end of file diff --git a/src/core/config.h b/src/core/config.h index b5022b9f..c52a708d 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -193,6 +193,11 @@ enum Config { #define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) //#define USE_TXD_CDIMAGE // generate and load textures from txd.img //#define USE_TEXTURE_POOL +//#define OPENAL + +// Particle +//#define PC_PARTICLE +//#define PS2_ALTERNATIVE_CARSPLASH // unused on PS2 // Pad #define XINPUT diff --git a/src/core/re3.cpp b/src/core/re3.cpp index e5f42696..3c2bc31f 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -372,7 +372,6 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil); DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); #ifdef TOGGLEABLE_BETA_FEATURES - DebugMenuAddVarBool8("Debug", "Toggle banned particles", (int8*)&CParticle::bEnableBannedParticles, nil); DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil); DebugMenuAddVarBool8("Debug", "Toggle peds running to phones to report crimes", (int8*)&CPed::bMakePedsRunToPhonesToReportCrimes, nil); #endif diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp index fe448966..932a0b8a 100644 --- a/src/objects/ParticleObject.cpp +++ b/src/objects/ParticleObject.cpp @@ -169,7 +169,11 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe { pobj->m_ParticleType = PARTICLE_STEAM_NY; pobj->m_nNumEffectCycles = 1; +#ifdef PC_PARTICLE pobj->m_nSkipFrames = 3; +#else + pobj->m_nSkipFrames = 1; +#endif pobj->m_nCreationChance = 8; break; } @@ -187,7 +191,11 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe { pobj->m_ParticleType = PARTICLE_STEAM_NY; pobj->m_nNumEffectCycles = 1; +#ifdef PC_PARTICLE pobj->m_nSkipFrames = 3; +#else + pobj->m_nSkipFrames = 1; +#endif pobj->m_nCreationChance = 8; break; } @@ -205,7 +213,11 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe { pobj->m_ParticleType = PARTICLE_STEAM_NY; pobj->m_nNumEffectCycles = 1; +#ifdef PC_PARTICLE pobj->m_nSkipFrames = 3; +#else + pobj->m_nSkipFrames = 1; +#endif pobj->m_nCreationChance = 8; pobj->m_Color = CRGBA(16, 16, 16, 255); break; @@ -228,7 +240,11 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe { pobj->m_ParticleType = PARTICLE_CAR_SPLASH; pobj->m_nNumEffectCycles = 0; +#ifdef PC_PARTICLE pobj->m_nSkipFrames = 1; +#else + pobj->m_nSkipFrames = 3; +#endif pobj->m_nCreationChance = 0; break; } @@ -236,7 +252,11 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe case POBJECT_SPLASHES_AROUND: { pobj->m_ParticleType = PARTICLE_SPLASH; +#ifdef PC_PARTICLE pobj->m_nNumEffectCycles = 15; +#else + pobj->m_nNumEffectCycles = 30; +#endif pobj->m_nSkipFrames = 2; pobj->m_nCreationChance = 0; break; @@ -246,7 +266,11 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe { pobj->m_ParticleType = PARTICLE_FLAME; pobj->m_nNumEffectCycles = 1; +#ifdef PC_PARTICLE pobj->m_nSkipFrames = 2; +#else + pobj->m_nSkipFrames = 1; +#endif pobj->m_nCreationChance = 2; pobj->m_vecTarget = CVector(0.0f, 0.0f, 0.0f); break; @@ -256,7 +280,11 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe { pobj->m_ParticleType = PARTICLE_FLAME; pobj->m_nNumEffectCycles = 1; +#ifdef PC_PARTICLE pobj->m_nSkipFrames = 2; +#else + pobj->m_nSkipFrames = 1; +#endif pobj->m_nCreationChance = 4; pobj->m_vecTarget = CVector(0.0f, 0.0f, 0.0f); break; @@ -286,7 +314,11 @@ CParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &targe { pobj->m_ParticleType = PARTICLE_EXPLOSION_MEDIUM; pobj->m_nNumEffectCycles = 1; +#ifdef PC_PARTICLE pobj->m_nSkipFrames = 3; +#else + pobj->m_nSkipFrames = 1; +#endif pobj->m_nCreationChance = 2; pobj->m_fRandVal = 0.01f; break; @@ -598,6 +630,7 @@ void CParticleObject::UpdateClose(void) case POBJECT_PED_WATER_SPLASH: { +#ifdef PC_PARTICLE CRGBA colorsmoke(255, 255, 255, 196); CVector pos = this->GetPosition(); @@ -699,12 +732,69 @@ void CParticleObject::UpdateClose(void) CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, CGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color); } +#else + CVector pos; + CVector vel; + + for ( int32 i = -2; i < 2; i++ ) + { + pos = this->GetPosition(); + pos += CVector(-0.75f, 0.5f * float(i), 0.0f); + vel = this->m_vecTarget; + vel.x += -1.5 * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.y += float(i) * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_PED_SPLASH, pos, vel, NULL, 0.8f, this->m_Color); + + pos = this->GetPosition(); + pos += CVector(0.75f, 0.5f * float(i), 0.0f); + + vel = this->m_vecTarget; + vel.x += 1.5f * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.y += float(i) * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_PED_SPLASH, pos, vel, NULL, 0.8f, this->m_Color); + + pos = this->GetPosition(); + pos += CVector(0.5f * float(i), -0.75, 0.0f); + + vel = this->m_vecTarget; + vel.x += float(i) * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.y += -1.5f * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_PED_SPLASH, pos, vel, NULL, 0.8f, this->m_Color); + + + pos = this->GetPosition(); + pos += CVector(0.5f * float(i), 0.75, 0.0f); + + vel = this->m_vecTarget; + vel.x += float(i) * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.y += 1.5f * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_PED_SPLASH, pos, vel, NULL, 0.8f, this->m_Color); + } + + + for ( int32 i = 0; i < 4; i++ ) + { + pos = this->GetPosition(); + + pos.x += CGeneral::GetRandomNumberInRange(-1.5f, 1.5f); + pos.y += CGeneral::GetRandomNumberInRange(-1.5f, 1.5f); + pos.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + + vel = this->m_vecTarget; + CParticle::AddParticle(PARTICLE_PED_SPLASH, pos, vel, NULL, 0.8f, this->m_Color); + } +#endif break; } case POBJECT_CAR_WATER_SPLASH: { +#ifdef PC_PARTICLE CRGBA colorsmoke(255, 255, 255, 196); CVector pos = this->GetPosition(); @@ -799,7 +889,65 @@ void CParticleObject::UpdateClose(void) splashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f); CParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, NULL, 0.0f, this->m_Color); } +#else + CVector pos; + CVector vel; + + for ( int32 i = -3; i < 4; i++ ) + { + pos = this->GetPosition(); + pos += CVector(-1.5f, 0.5f * float(i), 0.0f); + + + vel = this->m_vecTarget; + vel.x += -3.0f * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.y += float(i) * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, vel, NULL, 0.0f, this->m_Color); + + pos = this->GetPosition(); + pos += CVector(1.5f, 0.5f * float(i), 0.0f); + + vel = this->m_vecTarget; + vel.x += 3.0f * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.y += float(i) * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, vel, NULL, 0.0f, this->m_Color); + + + pos = this->GetPosition(); + pos += CVector(0.5f * float(i), -1.5f, 0.0f); + + vel = this->m_vecTarget; + vel.x += float(i) * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.y += -3.0f * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, vel, NULL, 0.0f, this->m_Color); + + + pos = this->GetPosition(); + pos += CVector(0.5f * float(i), 1.5f, 0.0f); + + + vel = this->m_vecTarget; + vel.x += float(i) * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.y += 3.0f * CGeneral::GetRandomNumberInRange(0.001f, 0.006f); + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, vel, NULL, 0.0f, this->m_Color); + } + + for ( int32 i = 0; i < 8; i++ ) + { + pos = this->GetPosition(); + pos.x += CGeneral::GetRandomNumberInRange(-3.0f, 3.0f); + pos.y += CGeneral::GetRandomNumberInRange(-3.0f, 3.0f); + + vel = this->m_vecTarget; + vel.z += CGeneral::GetRandomNumberInRange(0.03f, 0.06f); + CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, vel, NULL, 0.0f, this->m_Color); + } +#endif break; } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 1f15aa6c..f4cdff70 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -2019,7 +2019,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) } static void -particleProduceFootDust(CPed *ped, CVector *pos, float size, int times) +particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times) { switch (ped->m_nSurfaceTouched) { @@ -2028,7 +2028,7 @@ particleProduceFootDust(CPed *ped, CVector *pos, float size, int times) case SURFACE_PAVEMENT: case SURFACE_SAND: for (int i = 0; i < times; ++i) { - CVector adjustedPos = *pos; + CVector adjustedPos = pos; adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); CParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0); @@ -2040,16 +2040,27 @@ particleProduceFootDust(CPed *ped, CVector *pos, float size, int times) } static void -particleProduceFootSplash(CPed *ped, CVector *pos, float size, int times) +particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times) { +#ifdef PC_PARTICLE for (int i = 0; i < times; i++) { - CVector adjustedPos = *pos; + CVector adjustedPos = pos; adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); CVector direction = ped->GetForward() * -0.05f; CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200); } +#else + for ( int32 i = 0; i < times; i++ ) + { + CVector adjustedPos = pos; + adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + + CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 200); + } +#endif } void @@ -2080,6 +2091,50 @@ CPed::PlayFootSteps(void) } } +#ifdef GTA_PS2_STUFF + CAnimBlendAssociation *runStopAsoc = NULL; + + if ( IsPlayer() ) + { + runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP); + + if ( runStopAsoc == NULL ) + runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R); + } + + if ( runStopAsoc != NULL && runStopAsoc->blendAmount > 0.1f ) + { + { + CVector pos(0.0f, 0.0f, 0.0f); + RwFrame *parent = m_pFrames[PED_FOOTL]->frame; + while( parent ) + { + RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(parent)); + parent = RwFrameGetParent(parent); + } + + pos.z -= 0.1f; + pos += GetForward()*0.2f; + particleProduceFootDust(this, pos, 0.02f, 1); + } + + { + CVector pos(0.0f, 0.0f, 0.0f); + RwFrame *parent = m_pFrames[PED_FOOTR]->frame; + while( parent ) + { + RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(parent)); + parent = RwFrameGetParent(parent); + } + + pos.z -= 0.1f; + pos += GetForward()*0.2f; + particleProduceFootDust(this, pos, 0.02f, 1); + } + } +#endif + + if (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) { float stepStart = 1 / 15.0f; float stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart; @@ -2121,9 +2176,15 @@ CPed::PlayFootSteps(void) } if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) { if(IsPlayer()) - particleProduceFootDust(this, &footPos, 0.0f, 4); - } else if(stepPart == 2) { - particleProduceFootSplash(this, &footPos, 0.15f, 4); + particleProduceFootDust(this, footPos, 0.0f, 4); + } +#ifdef PC_PARTICLE + else if(stepPart == 2) +#else + else +#endif + { + particleProduceFootSplash(this, footPos, 0.15f, 4); } } } @@ -2131,6 +2192,7 @@ CPed::PlayFootSteps(void) if (m_nSurfaceTouched == SURFACE_PUDDLE) { float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude(); if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) { +#ifdef PC_PARTICLE float particleSize = pedSpeed * 2.0f; if (particleSize < 0.25f) @@ -2149,6 +2211,12 @@ CPed::PlayFootSteps(void) particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f); CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, CRGBA(255,255,255,255), 0, 0, 0, 0); +#else + CVector particlePos = (GetPosition() - 0.3f * GetUp()) + GetForward()*0.3f; + CVector particleDir = m_vecMoveSpeed * 0.45f; + particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f); + CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos-CVector(0.0f, 0.0f, 1.2f), particleDir, nil, 0.0f, CRGBA(155, 185, 155, 255)); +#endif } } } @@ -15114,7 +15182,11 @@ CPed::ProcessBuoyancy(void) bIsInTheAir = false; } pos.z = pos.z - 0.8f; +#ifdef PC_PARTICLE CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true); +#else + CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true); +#endif m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); m_nPedState = PED_IDLE; return; @@ -15143,6 +15215,7 @@ CPed::ProcessBuoyancy(void) } else { m_vecMoveSpeed.z = -0.01f; DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f); +#ifdef PC_PARTICLE CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition(); float level = 0.0f; if (CWaterLevel::GetWaterLevel(aBitForward, &level, false)) @@ -15151,6 +15224,18 @@ CPed::ProcessBuoyancy(void) CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true); nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80; nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100; +#else + CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition(); + float level = 0.0f; + if (CWaterLevel::GetWaterLevel(aBitForward, &level, false)) + aBitForward.z = level + 0.5f; + + CVector vel = m_vecMoveSpeed * 0.1f; + vel.z = 0.18f; + CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, vel, 0.0f, 350, CRGBA(0, 0, 0, 0), true); + nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300; + nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60; +#endif } } } else @@ -15167,9 +15252,15 @@ CPed::ProcessBuoyancy(void) if (pos.z != 0.0f) { nGenerateWaterCircles = 0; for(int i = 0; i < 4; i++) { +#ifdef PC_PARTICLE pos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f); pos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f); CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0); +#else + pos.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); + pos.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); + CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos+CVector(0.0f, 0.0f, 1.0f), CVector(0.0f, 0.0f, 0.0f)); +#endif } } } @@ -15181,9 +15272,17 @@ CPed::ProcessBuoyancy(void) pos.z = level; if (pos.z >= 0.0f) { +#ifdef PC_PARTICLE pos.z += 0.25f; +#else + pos.z += 0.5f; +#endif nGenerateRaindrops = 0; +#ifdef PC_PARTICLE CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true); +#else + CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 2500, CRGBA(0,0,0,0), true); +#endif } } } diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp index 0388e779..c855c860 100644 --- a/src/render/Particle.cpp +++ b/src/render/Particle.cpp @@ -12,9 +12,6 @@ #include "ParticleObject.h" #include "Particle.h" -#ifdef TOGGLEABLE_BETA_FEATURES -bool CParticle::bEnableBannedParticles = false; -#endif #define MAX_PARTICLES_ON_SCREEN (1000) @@ -388,8 +385,12 @@ void CParticle::Initialise() gpFlame5Tex = RwTextureRead("flame5", nil); +#ifdef FIX_BUGS + gpFlame5Raster = RwTextureGetRaster(gpFlame5Tex); +#else gpFlame5Raster = RwTextureGetRaster(gpFlame1Tex); // copy-paste bug ? - +#endif + gpRainDropSmallTex = RwTextureRead("rainsmall", nil); gpRainDropSmallRaster = RwTextureGetRaster(gpRainDropSmallTex); @@ -767,9 +768,8 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe { if ( CTimer::GetIsPaused() ) return NULL; -#ifdef TOGGLEABLE_BETA_FEATURES - if(!bEnableBannedParticles) -#endif + +#ifdef PC_PARTICLE if ( ( type == PARTICLE_ENGINE_SMOKE || type == PARTICLE_ENGINE_SMOKE2 || type == PARTICLE_ENGINE_STEAM @@ -782,6 +782,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe { return nil; } +#endif CParticle *pParticle = m_pUnusedListHead; @@ -853,6 +854,7 @@ CParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVe pParticle->m_nRotation = nRotation; +// PC only if ( pParticle->m_nRotation >= 360 ) pParticle->m_nRotation -= 360; else if ( pParticle->m_nRotation < 0 ) @@ -1348,12 +1350,13 @@ void CParticle::Update() particle->m_nAlpha = clamp(particle->m_nAlpha - psystem->m_nFadeAlphaAmount, 0, 255); - +#ifdef PC_PARTICLE if ( particle->m_nAlpha == 0 ) { bRemoveParticle = true; continue; } +#endif } else ++particle->m_nFadeAlphaTimer; @@ -1448,18 +1451,15 @@ void CParticle::Render() for ( int32 i = 0; i < MAX_PARTICLES; i++ ) { tParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[i]; - +#ifdef PC_PARTICLE bool particleBanned = false; - +#endif CParticle *particle = psystem->m_pParticles; RwRaster **frames = psystem->m_ppRaster; - +#ifdef PC_PARTICLE tParticleType type = psystem->m_Type; -#ifdef TOGGLEABLE_BETA_FEATURES - if (!bEnableBannedParticles) -#endif if ( type == PARTICLE_ENGINE_SMOKE || type == PARTICLE_ENGINE_SMOKE2 || type == PARTICLE_ENGINE_STEAM @@ -1471,7 +1471,8 @@ void CParticle::Render() { particleBanned = true; } - +#endif + if ( particle ) { if ( (flags & DRAW_OPAQUE) != (psystem->Flags & DRAW_OPAQUE) @@ -1512,10 +1513,11 @@ void CParticle::Render() while ( particle != nil ) { bool canDraw = true; +#ifdef PC_PARTICLE if ( particle->m_nAlpha == 0 ) canDraw = false; - +#endif if ( canDraw && psystem->m_nFinalAnimationFrame != 0 && frames != nil ) { RwRaster *curFrame = frames[particle->m_nCurrentFrame]; @@ -1538,7 +1540,7 @@ void CParticle::Render() particle->m_fSize * 63.0f, particle->m_Color, particle->m_nColorIntensity, - (float)particle->m_nRotation, + (float)particle->m_nRotation, //DEGTORAD((float)particle->m_nRotation) ps2 particle->m_nAlpha); } else @@ -1564,8 +1566,10 @@ void CParticle::Render() if ( CSprite::CalcScreenCoors(particle->m_vecPosition, coors, &w, &h, true) ) { +#ifdef PC_PARTICLE if ( (!particleBanned || SCREEN_WIDTH * fParticleScaleLimit >= w) && SCREEN_HEIGHT * fParticleScaleLimit >= h ) +#endif { if ( particle->m_nRotation != 0 ) { @@ -1576,7 +1580,7 @@ void CParticle::Render() particle->m_Color.blue, particle->m_nColorIntensity, 1.0f / coors.z, - float(particle->m_nRotation), + float(particle->m_nRotation), // DEGTORAD((float)particle->m_nRotation) ps2 particle->m_nAlpha); } else if ( psystem->Flags & SCREEN_TRAIL ) @@ -1601,7 +1605,6 @@ void CParticle::Render() fTrailLength = fDist; - //Float fRot = Atan2( vecDist.x / fDist, Sqrt(1.0f - vecDist.x / fDist * (vecDist.x / fDist)) ); float fRot = Asin(vecDist.x / fDist); fRotation = fRot; @@ -1653,7 +1656,6 @@ void CParticle::Render() fTrailLength = fDist; - //Float fRot = Atan2(vecDist.x / fDist, Sqrt(1.0f - vecDist.x / fDist * (vecDist.x / fDist))); float fRot = Asin(vecDist.x / fDist); fRotation = fRot; diff --git a/src/render/Particle.h b/src/render/Particle.h index 8999f4f6..b71dc717 100644 --- a/src/render/Particle.h +++ b/src/render/Particle.h @@ -89,10 +89,6 @@ public: static void AddJetExplosion(CVector const &vecPos, float fPower, float fSize); static void AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatrix); - -#ifdef TOGGLEABLE_BETA_FEATURES - static bool bEnableBannedParticles; -#endif }; VALIDATE_SIZE(CParticle, 0x68); \ No newline at end of file diff --git a/src/render/ParticleMgr.cpp b/src/render/ParticleMgr.cpp index 00391ac5..3387d471 100644 --- a/src/render/ParticleMgr.cpp +++ b/src/render/ParticleMgr.cpp @@ -8,8 +8,7 @@ cParticleSystemMgr mod_ParticleSystemManager; const char *ParticleFilename = "PARTICLE.CFG"; -//cParticleSystemMgr::cParticleSystemMgr() -void cParticleSystemMgr::ctor() +cParticleSystemMgr::cParticleSystemMgr() { memset(this, 0, sizeof(*this)); } diff --git a/src/render/ParticleMgr.h b/src/render/ParticleMgr.h index 0b4091de..70845a56 100644 --- a/src/render/ParticleMgr.h +++ b/src/render/ParticleMgr.h @@ -118,11 +118,11 @@ class cParticleSystemMgr public: tParticleSystemData m_aParticles[MAX_PARTICLES]; - cParticleSystemMgr() { ctor(); } void ctor(); + cParticleSystemMgr(); void Initialise(); void LoadParticleData(); - //void RangeCheck(tParticleSystemData *pData); + void RangeCheck(tParticleSystemData *pData) { } }; VALIDATE_SIZE(cParticleSystemMgr, 0x2420); diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 1b14e7a2..74609e15 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -2848,6 +2848,7 @@ CAutomobile::ProcessBuoyancy(void) static uint32 nGenerateWaterCircles = 0; if(initialSpeed.z < -0.3f && impulse.z > 0.3f){ +#if defined(PC_PARTICLE) || defined (PS2_ALTERNATIVE_CARSPLASH) RwRGBA color; color.red = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed())*0.45f*255; color.green = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen())*0.45f*255; @@ -2856,6 +2857,30 @@ CAutomobile::ProcessBuoyancy(void) CParticleObject::AddObject(POBJECT_CAR_WATER_SPLASH, GetPosition(), CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.15f, 0.3f)), 0.0f, 75, color, true); +#else + CVector pos = (initialSpeed * 2.0f) + (GetPosition() + point); + + for ( int32 i = 0; i < 360; i += 4 ) + { + float fSin = Sin(float(i)); + float fCos = Cos(float(i)); + + CVector dir(fSin*0.01f, fCos*0.01f, CGeneral::GetRandomNumberInRange(0.25f, 0.45f)); + + CParticle::AddParticle(PARTICLE_CAR_SPLASH, + pos + CVector(fSin*4.5f, fCos*4.5f, 0.0f), + dir, NULL, 0.0f, CRGBA(225, 225, 255, 180)); + + for ( int32 j = 0; j < 3; j++ ) + { + float fMul = 1.5f * float(j + 1); + + CParticle::AddParticle(PARTICLE_CAR_SPLASH, + pos + CVector(fSin * fMul, fCos * fMul, 0.0f), + dir, NULL, 0.0f, CRGBA(225, 225, 255, 180)); + } + } +#endif nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300; nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60; @@ -2909,9 +2934,16 @@ CAutomobile::ProcessBuoyancy(void) CVector pos = m_aWheelColPoints[i].point + 0.3f*GetUp() - GetPosition(); CVector vSpeed = GetSpeed(pos); vSpeed.z = 0.0f; +#ifdef GTA_PS2_STUFF + // ps2 puddle physics + CVector moveForce = CTimer::GetTimeStep() * (m_fMass * (vSpeed * -0.003f)); + ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); +#endif float fSpeed = vSpeed.MagnitudeSqr(); +#ifdef PC_PARTICLE if(fSpeed > sq(0.05f)){ fSpeed = Sqrt(fSpeed); + float size = Min((fSpeed < 0.15f ? 0.25f : 0.75f)*fSpeed, 0.6f); CVector right = 0.2f*fSpeed*GetRight() + 0.2f*vSpeed; @@ -2924,10 +2956,39 @@ CAutomobile::ProcessBuoyancy(void) CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, pos + GetPosition(), -0.6f*right, nil, size, smokeCol, 0, 0, 0, 0); - + if((CTimer::GetFrameCounter() & 0xF) == 0) DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, 2000.0f*fSpeed); } +#else + if ( ( (CTimer::GetFrameCounter() + i) & 3 ) == 0 ) + { + if(fSpeed > sq(0.05f)) + { + fSpeed = Sqrt(fSpeed); + CRGBA color(155, 185, 155, 255); + float boxY = GetColModel()->boundingBox.max.y; + CVector right = 0.5f * GetRight(); + + if ( i == 2 ) + { + CParticle::AddParticle(PARTICLE_PED_SPLASH, + GetPosition() + (boxY * GetForward()) + right, + 0.75f*m_vecMoveSpeed, NULL, 0.0f, color); + + } + else if ( i == 0 ) + { + CParticle::AddParticle(PARTICLE_PED_SPLASH, + GetPosition() + (boxY * GetForward()) - right, + 0.75f*m_vecMoveSpeed, NULL, 0.0f, color); + } + + if((CTimer::GetFrameCounter() & 0xF) == 0) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, 2000.0f*fSpeed); + } + } +#endif } } } @@ -3486,14 +3547,29 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) } return 0; default: - // Is this even visible? - if(CWeather::WetRoads > 0.01f && CTimer::GetFrameCounter() & 1){ - CParticle::AddParticle(PARTICLE_WATERSPRAY, + if ( CWeather::WetRoads > 0.01f +#ifdef PC_PARTICLE + && CTimer::GetFrameCounter() & 1 +#endif + ) + { + CParticle::AddParticle( +#ifdef FIX_BUGS + PARTICLE_WHEEL_WATER, +#else + PARTICLE_WATERSPRAY, +#endif colpoint->point + CVector(0.0f, 0.0f, 0.25f+0.25f), - CVector(0.0f, 0.0f, 1.0f), nil, +#ifdef PC_PARTICLE + CVector(0.0f, 0.0f, 1.0f), +#else + CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.005f, 0.04f)), +#endif + nil, CGeneral::GetRandomNumberInRange(0.1f, 0.5f), waterCol); return 0; } + return 1; } } diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 42beeb6c..d31182cd 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -340,27 +340,46 @@ CBoat::ProcessControl(void) else jetPos.z = 0.0f; +#ifdef PC_PARTICLE CVector wakePos = GetPosition() + sternPos; wakePos.z -= 0.65f; +#else + CVector wakePos = GetPosition() + sternPos; + wakePos.z = -0.3f; +#endif CVector wakeDir = 0.75f * jetDir; CParticle::AddParticle(PARTICLE_BOAT_THRUSTJET, jetPos, jetDir, nil, 0.0f, jetColor); +#ifdef PC_PARTICLE CParticle::AddParticle(PARTICLE_CAR_SPLASH, jetPos, 0.25f * jetDir, nil, 1.0f, splashColor, CGeneral::GetRandomNumberInRange(0, 30), CGeneral::GetRandomNumberInRange(0, 90), 3); +#endif if(!cameraHack) CParticle::AddParticle(PARTICLE_BOAT_WAKE, wakePos, wakeDir, nil, 0.0f, jetColor); }else if((CTimer::GetFrameCounter() + m_randomSeed) & 1){ +#ifdef PC_PARTICLE jetDir.z = 0.018f; jetDir.x *= 0.01f; jetDir.y *= 0.01f; propellerWorld.z += 1.5f; - + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, propellerWorld, jetDir, nil, 1.5f, jetColor); +#else + jetDir.z = 0.018f; + jetDir.x *= 0.03f; + jetDir.y *= 0.03f; + propellerWorld.z += 1.0f; + + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, propellerWorld, jetDir, nil, 0.0f, jetColor); +#endif + +#ifdef PC_PARTICLE CParticle::AddParticle(PARTICLE_CAR_SPLASH, propellerWorld, 0.1f * jetDir, nil, 0.5f, splashColor, CGeneral::GetRandomNumberInRange(0, 30), CGeneral::GetRandomNumberInRange(0, 90), 3); +#endif } } }else if(!onLand){ @@ -416,36 +435,66 @@ CBoat::ProcessControl(void) } // Spray particles on sides of boat - if(m_nDeltaVolumeUnderWater > 75){ +#ifdef PC_PARTICLE + if(m_nDeltaVolumeUnderWater > 75) +#else + if(m_nDeltaVolumeUnderWater > 120) +#endif + { float speed = m_vecMoveSpeed.Magnitude(); float splash1Size = speed; - float splash2Size = m_nDeltaVolumeUnderWater * 0.005f * 0.2f; + float splash2Size = float(m_nDeltaVolumeUnderWater) * 0.005f * 0.2f; float front = 0.9f * GetColModel()->boundingBox.max.y; if(splash1Size > 0.75f) splash1Size = 0.75f; CVector dir, pos; // right +#ifdef PC_PARTICLE dir = -0.5f*m_vecMoveSpeed; dir.z += 0.1f*speed; dir += 0.5f*GetRight()*speed; pos = front*GetForward() + 0.5f*GetRight() + GetPosition() + m_vecBuoyancePoint; CWaterLevel::GetWaterLevel(pos, &pos.z, true); +#else + dir = 0.3f*m_vecMoveSpeed; + dir.z += 0.05f*speed; + dir += 0.5f*GetRight()*speed; + pos = (GetPosition() + m_vecBuoyancePoint) + (1.5f*GetRight()); +#endif + +#ifdef PC_PARTICLE CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, 0.75f * dir, nil, splash1Size, splashColor, CGeneral::GetRandomNumberInRange(0, 30), CGeneral::GetRandomNumberInRange(0, 90), 1); CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size, jetColor); +#else + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size); +#endif + // left +#ifdef PC_PARTICLE dir = -0.5f*m_vecMoveSpeed; dir.z += 0.1f*speed; dir -= 0.5f*GetRight()*speed; pos = front*GetForward() - 0.5f*GetRight() + GetPosition() + m_vecBuoyancePoint; CWaterLevel::GetWaterLevel(pos, &pos.z, true); +#else + dir = 0.3f*m_vecMoveSpeed; + dir.z += 0.05f*speed; + dir -= 0.5f*GetRight()*speed; + pos = (GetPosition() + m_vecBuoyancePoint) - (1.5f*GetRight()); +#endif + +#ifdef PC_PARTICLE CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, 0.75f * dir, nil, splash1Size, splashColor, CGeneral::GetRandomNumberInRange(0, 30), CGeneral::GetRandomNumberInRange(0, 90), 1); CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size, jetColor); +#else + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size); +#endif } m_fPrevVolumeUnderWater = m_fVolumeUnderWater; From 2925b7e0c391f2d44e1e3641e2387be6fb0be491 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Thu, 23 Apr 2020 11:35:42 +0300 Subject: [PATCH 106/123] fix #ifdef --- src/audio/AudioManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 02bf532c..0c4b007f 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -9606,7 +9606,7 @@ cAudioManager::ServiceSoundEffects() ProcessMissionAudio(); AdjustSamplesVolume(); ProcessActiveQueues(); -#ifdef WITHMILES +#ifdef OPENAL SampleManager.Service(); #endif for(int32 i = 0; i < m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal; ++i) { From 458eb3a4f079af4c118357fb3bd0594626151e9d Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 23 Apr 2020 16:40:19 +0300 Subject: [PATCH 107/123] removed fix that made no sense --- src/vehicles/Vehicle.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index c09375cc..57c5f3af 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -1002,21 +1002,15 @@ void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle) { if (pVehicle->pDriver) { -#ifndef FIX_BUGS - // this just isn't fair CDarkel::RegisterKillByPlayer(pVehicle->pDriver, WEAPONTYPE_UNIDENTIFIED); -#endif pVehicle->pDriver->FlagToDestroyWhenNextProcessed(); } for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) { if (pVehicle->pPassengers[i]) { -#ifndef FIX_BUGS - // this just isn't fair CDarkel::RegisterKillByPlayer(pVehicle->pPassengers[i], WEAPONTYPE_UNIDENTIFIED); -#endif pVehicle->pPassengers[i]->FlagToDestroyWhenNextProcessed(); } } CWorld::Remove(pVehicle); delete pVehicle; -} \ No newline at end of file +} From f03b4eec4c37eab75a5bd639279cfcc615105b01 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 23 Apr 2020 22:25:18 +0200 Subject: [PATCH 108/123] implemented skinned peds, no cutscene hands yet --- librw | 2 +- premake5.lua | 2 +- src/animation/AnimBlendClumpData.h | 4 +- src/animation/Bones.cpp | 52 ++++ src/animation/Bones.h | 24 ++ src/animation/FrameUpdate.cpp | 243 ++++++++++++++-- src/animation/RpAnimBlend.cpp | 114 +++++++- src/animation/RpAnimBlend.h | 5 +- src/control/Script.cpp | 8 +- src/core/AnimViewer.cpp | 7 +- src/core/Cam.cpp | 13 +- src/core/Debug.cpp | 37 ++- src/core/Debug.h | 11 + src/core/World.cpp | 5 + src/core/common.h | 11 + src/core/config.h | 1 + src/core/main.cpp | 1 + src/entities/Entity.cpp | 70 ++++- src/entities/Entity.h | 4 + src/fakerw/fake.cpp | 46 ++- src/fakerw/rphanim.h | 36 +++ src/fakerw/rpskin.h | 18 ++ src/fakerw/rtcharse.h | 14 + src/fakerw/rtquat.h | 10 + src/math/Quaternion.h | 12 + src/modelinfo/ClumpModelInfo.cpp | 72 ++++- src/modelinfo/PedModelInfo.cpp | 164 ++++++++++- src/modelinfo/PedModelInfo.h | 17 +- src/objects/CutsceneHead.cpp | 95 ++++++- src/objects/CutsceneHead.h | 9 + src/objects/CutsceneObject.cpp | 65 ++++- src/objects/CutsceneObject.h | 16 ++ src/peds/CivilianPed.h | 2 + src/peds/CopPed.cpp | 3 +- src/peds/CopPed.h | 2 + src/peds/EmergencyPed.h | 2 + src/peds/Ped.cpp | 246 +++++++++++----- src/peds/Ped.h | 57 +++- src/peds/PedIK.cpp | 433 +++++++++++++++++++++-------- src/peds/PedIK.h | 2 + src/peds/PlayerPed.cpp | 6 + src/peds/PlayerPed.h | 2 + src/render/SpecialFX.cpp | 10 +- src/rw/RwHelper.cpp | 179 +++++++++++- src/rw/RwHelper.h | 9 + src/rw/VisibilityPlugins.cpp | 15 + src/rw/VisibilityPlugins.h | 3 + src/skel/win/win.cpp | 8 + src/weapons/Weapon.cpp | 3 +- 49 files changed, 1869 insertions(+), 301 deletions(-) create mode 100644 src/animation/Bones.cpp create mode 100644 src/animation/Bones.h create mode 100644 src/fakerw/rtcharse.h create mode 100644 src/fakerw/rtquat.h diff --git a/librw b/librw index 752fceb1..374f951d 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 752fceb1e3c4ce06b6f20b9c4471927821469bf2 +Subproject commit 374f951d7cee353914059d8ddf9c5aff7d764984 diff --git a/premake5.lua b/premake5.lua index 6037b01c..14aab9d8 100644 --- a/premake5.lua +++ b/premake5.lua @@ -62,7 +62,7 @@ workspace "re3" filter "configurations:DebugRW or ReleaseRW" includedirs { "rwsdk/include/d3d8" } libdirs { "rwsdk/lib/d3d8/release" } - links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp" } + links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp", "rtquat", "rtcharse" } filter {} diff --git a/src/animation/AnimBlendClumpData.h b/src/animation/AnimBlendClumpData.h index 1c8c391d..a537425a 100644 --- a/src/animation/AnimBlendClumpData.h +++ b/src/animation/AnimBlendClumpData.h @@ -18,7 +18,7 @@ struct AnimBlendFrameData #ifdef PED_SKIN union { RwFrame *frame; - RpHAnimStdKeyFrame *hanimframe; + RpHAnimStdKeyFrame *hanimFrame; }; int32 nodeID; #else @@ -50,4 +50,6 @@ public: #endif void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg); }; +#ifndef PED_SKIN static_assert(sizeof(CAnimBlendClumpData) == 0x14, "CAnimBlendClumpData: error"); +#endif diff --git a/src/animation/Bones.cpp b/src/animation/Bones.cpp new file mode 100644 index 00000000..1608449d --- /dev/null +++ b/src/animation/Bones.cpp @@ -0,0 +1,52 @@ +#include "common.h" +#include "PedModelInfo.h" +#include "Bones.h" + +#ifdef PED_SKIN + +int +ConvertPedNode2BoneTag(int node) +{ + switch(node){ + case PED_TORSO: return BONE_waist; + case PED_MID: return BONE_torso; // this is what Xbox/Mobile use + // return BONE_mid; // this is what PS2/PC use + case PED_HEAD: return BONE_head; + case PED_UPPERARML: return BONE_upperarml; + case PED_UPPERARMR: return BONE_upperarmr; + case PED_HANDL: return BONE_Lhand; + case PED_HANDR: return BONE_Rhand; + case PED_UPPERLEGL: return BONE_upperlegl; + case PED_UPPERLEGR: return BONE_upperlegr; + case PED_FOOTL: return BONE_footl; + case PED_FOOTR: return BONE_footr; + case PED_LOWERLEGR: return BONE_lowerlegl; + } + return -1; +} + +const char* +ConvertBoneTag2BoneName(int tag) +{ + switch(tag){ + case BONE_waist: return "Swaist"; + case BONE_upperlegr: return "Supperlegr"; + case BONE_lowerlegr: return "Slowerlegr"; + case BONE_footr: return "Sfootr"; + case BONE_upperlegl: return "Supperlegl"; + case BONE_lowerlegl: return "Slowerlegl"; + case BONE_footl: return "Sfootl"; + case BONE_mid: return "Smid"; + case BONE_torso: return "Storso"; + case BONE_head: return "Shead"; + case BONE_upperarmr: return "Supperarmr"; + case BONE_lowerarmr: return "Slowerarmr"; + case BONE_Rhand: return "SRhand"; + case BONE_upperarml: return "Supperarml"; + case BONE_lowerarml: return "Slowerarml"; + case BONE_Lhand: return "SLhand"; + } + return nil; +} + +#endif diff --git a/src/animation/Bones.h b/src/animation/Bones.h new file mode 100644 index 00000000..38d91ba3 --- /dev/null +++ b/src/animation/Bones.h @@ -0,0 +1,24 @@ +#pragma once + +enum BoneTag +{ + BONE_waist, + BONE_upperlegr, + BONE_lowerlegr, + BONE_footr, + BONE_upperlegl, + BONE_lowerlegl, + BONE_footl, + BONE_mid, + BONE_torso, + BONE_head, + BONE_upperarmr, + BONE_lowerarmr, + BONE_Rhand, + BONE_upperarml, + BONE_lowerarml, + BONE_Lhand, +}; + +int ConvertPedNode2BoneTag(int node); +const char *ConvertBoneTag2BoneName(int tag); diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp index df45bfb5..a38ebc74 100644 --- a/src/animation/FrameUpdate.cpp +++ b/src/animation/FrameUpdate.cpp @@ -8,12 +8,18 @@ CAnimBlendClumpData *gpAnimBlendClump; -void FrameUpdateCallBack(AnimBlendFrameData *frame, void *arg); -void FrameUpdateCallBackWithVelocityExtraction(AnimBlendFrameData *frame, void *arg); -void FrameUpdateCallBackWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg); +// PS2 names without "NonSkinned" +void FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackNonSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackNonSkinnedWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg); + +void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackSkinnedWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg); + void -FrameUpdateCallBack(AnimBlendFrameData *frame, void *arg) +FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg) { CVector vec, pos(0.0f, 0.0f, 0.0f); CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); @@ -25,9 +31,9 @@ FrameUpdateCallBack(AnimBlendFrameData *frame, void *arg) if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && gpAnimBlendClump->velocity){ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION_3D) - FrameUpdateCallBackWith3dVelocityExtraction(frame, arg); + FrameUpdateCallBackNonSkinnedWith3dVelocityExtraction(frame, arg); else - FrameUpdateCallBackWithVelocityExtraction(frame, arg); + FrameUpdateCallBackNonSkinnedWithVelocityExtraction(frame, arg); return; } @@ -48,12 +54,7 @@ FrameUpdateCallBack(AnimBlendFrameData *frame, void *arg) if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ RwMatrixSetIdentity(mat); - - float norm = rot.MagnitudeSqr(); - if(norm == 0.0f) - rot.w = 1.0f; - else - rot *= 1.0f/Sqrt(norm); + rot.Normalise(); rot.Get(mat); } @@ -69,7 +70,7 @@ FrameUpdateCallBack(AnimBlendFrameData *frame, void *arg) } void -FrameUpdateCallBackWithVelocityExtraction(AnimBlendFrameData *frame, void *arg) +FrameUpdateCallBackNonSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void *arg) { CVector vec, pos(0.0f, 0.0f, 0.0f); CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); @@ -122,12 +123,7 @@ FrameUpdateCallBackWithVelocityExtraction(AnimBlendFrameData *frame, void *arg) if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ RwMatrixSetIdentity(mat); - - float norm = rot.MagnitudeSqr(); - if(norm == 0.0f) - rot.w = 1.0f; - else - rot *= 1.0f/Sqrt(norm); + rot.Normalise(); rot.Get(mat); } @@ -154,7 +150,7 @@ FrameUpdateCallBackWithVelocityExtraction(AnimBlendFrameData *frame, void *arg) // original code uses do loops? void -FrameUpdateCallBackWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg) +FrameUpdateCallBackNonSkinnedWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg) { CVector vec, pos(0.0f, 0.0f, 0.0f); CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); @@ -201,12 +197,7 @@ FrameUpdateCallBackWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ RwMatrixSetIdentity(mat); - - float norm = rot.MagnitudeSqr(); - if(norm == 0.0f) - rot.w = 1.0f; - else - rot *= 1.0f/Sqrt(norm); + rot.Normalise(); rot.Get(mat); } @@ -220,3 +211,203 @@ FrameUpdateCallBackWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg } RwMatrixUpdate(mat); } + +#ifdef PED_SKIN + +void +FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg) +{ + CVector vec, pos(0.0f, 0.0f, 0.0f); + CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); + float totalBlendAmount = 0.0f; + RpHAnimStdKeyFrame *xform = frame->hanimFrame; + CAnimBlendNode **node; + AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg; + + if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && + gpAnimBlendClump->velocity){ + if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION_3D) + FrameUpdateCallBackSkinnedWith3dVelocityExtraction(frame, arg); + else + FrameUpdateCallBackSkinnedWithVelocityExtraction(frame, arg); + return; + } + + if(updateData->foobar) + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->association->IsPartial()) + totalBlendAmount += (*node)->association->blendAmount; + + for(node = updateData->nodes; *node; node++){ + if((*node)->sequence){ + (*node)->Update(vec, q, 1.0f-totalBlendAmount); + if((*node)->sequence->HasTranslation()) + pos += vec; + rot += q; + } + ++*node; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ + rot.Normalise(); + xform->q.imag.x = rot.x; + xform->q.imag.y = rot.y; + xform->q.imag.z = rot.z; + xform->q.real = rot.w; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){ + xform->t.x = pos.x; + xform->t.y = pos.y; + xform->t.z = pos.z; + xform->t.x += frame->resetPos.x; + xform->t.y += frame->resetPos.y; + xform->t.z += frame->resetPos.z; + } +} + +void +FrameUpdateCallBackSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void *arg) +{ + CVector vec, pos(0.0f, 0.0f, 0.0f); + CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); + float totalBlendAmount = 0.0f; + float transx = 0.0f, transy = 0.0f; + float curx = 0.0f, cury = 0.0f; + float endx = 0.0f, endy = 0.0f; + bool looped = false; + RpHAnimStdKeyFrame *xform = frame->hanimFrame; + CAnimBlendNode **node; + AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg; + + if(updateData->foobar) + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->association->IsPartial()) + totalBlendAmount += (*node)->association->blendAmount; + + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->sequence->HasTranslation()){ + if((*node)->association->HasTranslation()){ + (*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount); + cury += vec.y; + if((*node)->association->HasXTranslation()) + curx += vec.x; + } + } + + for(node = updateData->nodes; *node; node++){ + if((*node)->sequence){ + bool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount); + rot += q; + if((*node)->sequence->HasTranslation()){ + pos += vec; + if((*node)->association->HasTranslation()){ + transy += vec.y; + if((*node)->association->HasXTranslation()) + transx += vec.x; + looped |= nodelooped; + if(nodelooped){ + (*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount); + endy += vec.y; + if((*node)->association->HasXTranslation()) + endx += vec.x; + } + } + } + } + ++*node; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ + rot.Normalise(); + xform->q.imag.x = rot.x; + xform->q.imag.y = rot.y; + xform->q.imag.z = rot.z; + xform->q.real = rot.w; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){ + gpAnimBlendClump->velocity->x = transx - curx; + gpAnimBlendClump->velocity->y = transy - cury; + if(looped){ + gpAnimBlendClump->velocity->x += endx; + gpAnimBlendClump->velocity->y += endy; + } + xform->t.x = pos.x - transx; + xform->t.y = pos.y - transy; + xform->t.z = pos.z; + if(xform->t.z >= -0.8f) + if(xform->t.z < -0.4f) + xform->t.z += (2.5f * xform->t.z + 2.0f) * frame->resetPos.z; + else + xform->t.z += frame->resetPos.z; + xform->t.x += frame->resetPos.x; + xform->t.y += frame->resetPos.y; + } +} + +void +FrameUpdateCallBackSkinnedWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg) +{ + CVector vec, pos(0.0f, 0.0f, 0.0f); + CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); + float totalBlendAmount = 0.0f; + CVector trans(0.0f, 0.0f, 0.0f); + CVector cur(0.0f, 0.0f, 0.0f); + CVector end(0.0f, 0.0f, 0.0f); + bool looped = false; + RpHAnimStdKeyFrame *xform = frame->hanimFrame; + CAnimBlendNode **node; + AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg; + + if(updateData->foobar) + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->association->IsPartial()) + totalBlendAmount += (*node)->association->blendAmount; + + for(node = updateData->nodes; *node; node++) + if((*node)->sequence && (*node)->sequence->HasTranslation()){ + if((*node)->association->HasTranslation()){ + (*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount); + cur += vec; + } + } + + for(node = updateData->nodes; *node; node++){ + if((*node)->sequence){ + bool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount); + rot += q; + if((*node)->sequence->HasTranslation()){ + pos += vec; + if((*node)->association->HasTranslation()){ + trans += vec; + looped |= nodelooped; + if(nodelooped){ + (*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount); + end += vec; + } + } + } + } + ++*node; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){ + rot.Normalise(); + xform->q.imag.x = rot.x; + xform->q.imag.y = rot.y; + xform->q.imag.z = rot.z; + xform->q.real = rot.w; + } + + if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){ + *gpAnimBlendClump->velocity = trans - cur; + if(looped) + *gpAnimBlendClump->velocity += end; + xform->t.x = (pos - trans).x + frame->resetPos.x; + xform->t.y = (pos - trans).y + frame->resetPos.y; + xform->t.z = (pos - trans).z + frame->resetPos.z; + } +} + +#endif diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp index 20290666..d3e10889 100644 --- a/src/animation/RpAnimBlend.cpp +++ b/src/animation/RpAnimBlend.cpp @@ -1,12 +1,17 @@ #include "common.h" +#include "RwHelper.h" #include "General.h" #include "NodeName.h" #include "VisibilityPlugins.h" +#include "Bones.h" #include "AnimBlendClumpData.h" #include "AnimBlendHierarchy.h" #include "AnimBlendAssociation.h" #include "RpAnimBlend.h" +#ifdef PED_SKIN +#include "PedModelInfo.h" +#endif RwInt32 ClumpOffset; @@ -122,19 +127,59 @@ FrameForAllChildrenFillFrameArrayCallBack(RwFrame *frame, void *data) return frame; } +// FrameInitCallBack on PS2 void -FrameInitCallBack(AnimBlendFrameData *frameData, void*) +FrameInitCBnonskin(AnimBlendFrameData *frameData, void*) { frameData->flag = 0; frameData->resetPos = *RwMatrixGetPos(RwFrameGetMatrix(frameData->frame)); } void -RpAnimBlendClumpInit(RpClump *clump) +FrameInitCBskin(AnimBlendFrameData *frameData, void*) { + frameData->flag = 0; +} + #ifdef PED_SKIN - TODO -#else +void +RpAnimBlendClumpInitSkinned(RpClump *clump) +{ + int i; + RwV3d boneTab[64]; + CAnimBlendClumpData *clumpData; + RpAtomic *atomic; + RpSkin *skin; + RpHAnimHierarchy *hier; + int numBones; + + RpAnimBlendAllocateData(clump); + clumpData = *RPANIMBLENDCLUMPDATA(clump); + atomic = IsClumpSkinned(clump); + assert(atomic); + skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)); + assert(skin); + numBones = RpSkinGetNumBones(skin); + clumpData->SetNumberOfBones(numBones); + hier = GetAnimHierarchyFromSkinClump(clump); + assert(hier); + memset(boneTab, 0, sizeof(boneTab)); + SkinGetBonePositionsToTable(clump, boneTab); + + AnimBlendFrameData *frames = clumpData->frames; + for(i = 0; i < numBones; i++){ + frames[i].nodeID = HIERNODEID(hier, i); + frames[i].resetPos = boneTab[i]; + frames[i].hanimFrame = (RpHAnimStdKeyFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i); + } + clumpData->ForAllFrames(FrameInitCBskin, nil); + clumpData->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION; +} +#endif + +void +RpAnimBlendClumpInitNotSkinned(RpClump *clump) +{ int numFrames = 0; CAnimBlendClumpData *clumpData; RwFrame *root; @@ -147,9 +192,19 @@ RpAnimBlendClumpInit(RpClump *clump) clumpData->SetNumberOfFrames(numFrames); frames = clumpData->frames; RwFrameForAllChildren(root, FrameForAllChildrenFillFrameArrayCallBack, &frames); - clumpData->ForAllFrames(FrameInitCallBack, nil); + clumpData->ForAllFrames(FrameInitCBnonskin, nil); clumpData->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION; +} + +void +RpAnimBlendClumpInit(RpClump *clump) +{ +#ifdef PED_SKIN + if(IsClumpSkinned(clump)) + RpAnimBlendClumpInitSkinned(clump); + else #endif + RpAnimBlendClumpInitNotSkinned(clump); } bool @@ -298,42 +353,68 @@ RpAnimBlendClumpGetFirstAssociation(RpClump *clump) return CAnimBlendAssociation::FromLink(clumpData->link.next); } +// FillFrameArrayCallBack on PS2 void -FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg) +FillFrameArrayCBnonskin(AnimBlendFrameData *frame, void *arg) { AnimBlendFrameData **frames = (AnimBlendFrameData**)arg; frames[CVisibilityPlugins::GetFrameHierarchyId(frame->frame)] = frame; } +#ifdef PED_SKIN +void +RpAnimBlendClumpFillFrameArraySkin(RpClump *clump, AnimBlendFrameData **frames) +{ + int i; + CAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump); + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump); + for(i = PED_MID; i < PED_NODE_MAX; i++) + frames[i] = &clumpData->frames[RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(i))]; +} +#endif + void RpAnimBlendClumpFillFrameArray(RpClump *clump, AnimBlendFrameData **frames) { #ifdef PED_SKIN - TODO -#else - (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FillFrameArrayCallBack, frames); + if(IsClumpSkinned(clump)) + RpAnimBlendClumpFillFrameArraySkin(clump, frames); + else #endif + (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FillFrameArrayCBnonskin, frames); } AnimBlendFrameData *pFrameDataFound; +// FrameFindCallBack on PS2 void -FrameFindCallBack(AnimBlendFrameData *frame, void *arg) +FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg) { char *nodename = GetFrameNodeName(frame->frame); if(!CGeneral::faststricmp(nodename, (char*)arg)) pFrameDataFound = frame; } +#ifdef PED_SKIN +void +FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg) +{ + const char *name = ConvertBoneTag2BoneName(frame->nodeID); + if(name && CGeneral::faststricmp(name, (char*)arg) == 0) + pFrameDataFound = frame; +} +#endif + AnimBlendFrameData* RpAnimBlendClumpFindFrame(RpClump *clump, const char *name) { pFrameDataFound = nil; #ifdef PED_SKIN - TODO -#else - (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindCallBack, (void*)name); + if(IsClumpSkinned(clump)) + (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBskin, (void*)name); + else #endif + (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBnonskin, (void*)name); return pFrameDataFound; } @@ -369,7 +450,12 @@ RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta) } updateData.nodes[i] = nil; - clumpData->ForAllFrames(FrameUpdateCallBack, &updateData); +#ifdef PED_SKIN + if(IsClumpSkinned(clump)) + clumpData->ForAllFrames(FrameUpdateCallBackSkinned, &updateData); + else +#endif + clumpData->ForAllFrames(FrameUpdateCallBackNonSkinned, &updateData); for(link = clumpData->link.next; link; link = link->next){ CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link); diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h index ccfa5872..838c8816 100644 --- a/src/animation/RpAnimBlend.h +++ b/src/animation/RpAnimBlend.h @@ -7,7 +7,7 @@ struct AnimBlendFrameData; struct AnimBlendFrameUpdateData { - int foobar; + int foobar; // TODO: figure out what this actually means CAnimBlendNode *nodes[16]; }; @@ -38,4 +38,5 @@ void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta); extern CAnimBlendClumpData *gpAnimBlendClump; -void FrameUpdateCallBack(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 073cb661..7ab40847 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -6435,9 +6435,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->FlagToDestroyWhenNextProcessed(); } else if (CGame::nastyGame && pPed->IsPedInControl()) { - RwMatrix tmp_rw; - CPedIK::GetWorldMatrix(pPed->m_pFrames[PED_HEAD]->frame, &tmp_rw); - pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, tmp_rw.pos, true); + pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true); } else { pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); @@ -6450,9 +6448,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) CPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed; assert(pPed); if (CGame::nastyGame) { - RwMatrix tmp_rw; - CPedIK::GetWorldMatrix(pPed->m_pFrames[PED_HEAD]->frame, &tmp_rw); - pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, tmp_rw.pos, true); + pPed->ApplyHeadShot(WEAPONTYPE_SNIPERRIFLE, pPed->GetNodePosition(PED_HEAD), true); } else { pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp index 20e94bf4..cf3ec5bf 100644 --- a/src/core/AnimViewer.cpp +++ b/src/core/AnimViewer.cpp @@ -367,7 +367,12 @@ CAnimViewer::Update(void) } else { // Originally it was GetPad(1)->LeftShoulder2 if (pad->NewState.Triangle) { - CPedModelInfo::AnimatePedColModel(((CPedModelInfo*)CModelInfo::GetModelInfo(pTarget->m_modelIndex))->GetHitColModel(), RpClumpGetFrame(pTarget->GetClump())); +#ifdef PED_SKIN + if(IsClumpSkinned(pTarget->GetClump())) + ((CPedModelInfo*)CModelInfo::GetModelInfo(pTarget->m_modelIndex))->AnimatePedColModelSkinned(pTarget->GetClump()); + else +#endif + CPedModelInfo::AnimatePedColModel(((CPedModelInfo*)CModelInfo::GetModelInfo(pTarget->m_modelIndex))->GetHitColModel(), RpClumpGetFrame(pTarget->GetClump())); AsciiToUnicode("Ped Col model will be animated as long as you hold the button", gUString); CMessages::AddMessage(gUString, 100, 0); } diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp index f0a60093..5cf1c8f3 100644 --- a/src/core/Cam.cpp +++ b/src/core/Cam.cpp @@ -2776,17 +2776,20 @@ CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, if(CamTargetEntity->IsPed()){ // static bool FailedTestTwelveFramesAgo = false; // unused - RwV3d HeadPos = vecHeadCamOffset; + CVector HeadPos = vecHeadCamOffset; CVector TargetCoors; - // needs fix for SKINNING - RwFrame *frm = ((CPed*)CamTargetEntity)->GetNodeFrame(PED_HEAD); + ((CPed*)CamTargetEntity)->TransformToNode(HeadPos, PED_HEAD); + // This is done on PC, but checking for the clump frame is not necessary apparently +/* + RwFrame *frm = ((CPed*)CamTargetEntity)->m_pFrames[PED_HEAD]->frame; while(frm){ RwV3dTransformPoints(&HeadPos, &HeadPos, 1, RwFrameGetMatrix(frm)); frm = RwFrameGetParent(frm); if(frm == RpClumpGetFrame(CamTargetEntity->GetClump())) frm = nil; } +*/ if(ResetStatics){ Beta = TargetOrientation; @@ -2813,13 +2816,13 @@ CCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, m_vecBufferedPlayerBodyOffset.z = TheCamera.m_fGaitSwayBuffer * m_vecBufferedPlayerBodyOffset.z + (1.0f-TheCamera.m_fGaitSwayBuffer) * HeadPos.z; - HeadPos = (CamTargetEntity->GetMatrix() * m_vecBufferedPlayerBodyOffset).toRwV3d(); + HeadPos = (CamTargetEntity->GetMatrix() * m_vecBufferedPlayerBodyOffset); }else{ float HeadDelta = (HeadPos - InitialHeadPos).Magnitude2D(); CVector Fwd = CamTargetEntity->GetForward(); Fwd.z = 0.0f; Fwd.Normalise(); - HeadPos = (HeadDelta*1.23f*Fwd + CamTargetEntity->GetPosition()).toRwV3d(); + HeadPos = (HeadDelta*1.23f*Fwd + CamTargetEntity->GetPosition()); HeadPos.z += 0.59f; } Source = HeadPos; diff --git a/src/core/Debug.cpp b/src/core/Debug.cpp index 917c99ab..e794dcaf 100644 --- a/src/core/Debug.cpp +++ b/src/core/Debug.cpp @@ -1,5 +1,7 @@ #include "common.h" +#include "RwHelper.h" #include "Debug.h" +#include "Lines.h" #include "Font.h" #include "main.h" #include "Text.h" @@ -114,11 +116,14 @@ CDebug::DisplayScreenStrings() 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); +*/ + ObrsPrintfString(ms_aScreenStrs[i].str, ms_aScreenStrs[i].x, ms_aScreenStrs[i].y); } CFont::DrawFonts(); @@ -131,7 +136,35 @@ 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_aScreenStrs[ms_nScreenStrs].x = x;//*12; + ms_aScreenStrs[ms_nScreenStrs].y = y;//*22; ms_nScreenStrs++; } + +CDebug::Line CDebug::ms_aLines[MAX_DEBUG_LINES]; +int CDebug::ms_nLines; + +void +CDebug::AddLine(CVector p1, CVector p2, uint32 c1, uint32 c2) +{ + if(ms_nLines >= MAX_DEBUG_LINES) + return; + ms_aLines[ms_nLines].p1 = p1; + ms_aLines[ms_nLines].p2 = p2; + ms_aLines[ms_nLines].c1 = c1; + ms_aLines[ms_nLines].c2 = c2; + ms_nLines++; +} + +void +CDebug::DrawLines(void) +{ + int i; + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + for(i = 0; i < ms_nLines; i++){ + Line *l = &ms_aLines[i]; + CLines::RenderLineWithClipping(l->p1.x, l->p1.y, l->p1.z, l->p2.x, l->p2.y, l->p2.z, l->c1, l->c2); + } + ms_nLines = 0; +} diff --git a/src/core/Debug.h b/src/core/Debug.h index d169a0b4..4a25bf41 100644 --- a/src/core/Debug.h +++ b/src/core/Debug.h @@ -8,6 +8,7 @@ class CDebug MAX_STR_LEN = 80, MAX_SCREEN_STRS = 100, + MAX_DEBUG_LINES = 100, }; static int16 ms_nCurrentTextLine; @@ -21,6 +22,13 @@ class CDebug static ScreenStr ms_aScreenStrs[MAX_SCREEN_STRS]; static int ms_nScreenStrs; + struct Line { + CVector p1, p2; + uint32 c1, c2; + }; + static Line ms_aLines[MAX_DEBUG_LINES]; + static int ms_nLines; + public: static void DebugInitTextBuffer(); static void DebugDisplayTextBuffer(); @@ -29,6 +37,9 @@ public: // custom static void PrintAt(const char *str, int x, int y); static void DisplayScreenStrings(); + + static void AddLine(CVector p1, CVector p2, uint32 c1, uint32 c2); + static void DrawLines(void); }; extern bool gbDebugStuffInRelease; diff --git a/src/core/World.cpp b/src/core/World.cpp index 404b92c0..b2a01b80 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -339,6 +339,11 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP if(e->IsPed()) { if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) { +#ifdef PED_SKIN + if(IsClumpSkinned(e->GetClump())) + colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump()); + else +#endif if(((CPed *)e)->UseGroundColModel()) colmodel = &CTempColModels::ms_colModelPedGroundHit; else diff --git a/src/core/common.h b/src/core/common.h index 46b4d03a..8b057efa 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -27,9 +27,15 @@ #ifdef LIBRW #define STREAMPOS(str) ((str)->tell()) #define STREAMFILE(str) (((rw::StreamFile*)(str))->file) +#define HIERNODEINFO(hier) ((hier)->nodeInfo) +#define HIERNODEID(hier, i) ((hier)->nodeInfo[i].id) +#define HANIMFRAMES(anim) ((anim)->keyframes) #else #define STREAMPOS(str) ((str)->Type.memory.position) #define STREAMFILE(str) ((str)->Type.file.fpFile) +#define HIERNODEINFO(hier) ((hier)->pNodeInfo) +#define HIERNODEID(hier, i) ((hier)->pNodeInfo[i].nodeID) +#define HANIMFRAMES(anim) ((anim)->pFrames) #endif #define rwVENDORID_ROCKSTAR 0x0253F2 @@ -63,6 +69,11 @@ typedef uint16_t wchar; #include "config.h" +#ifdef PED_SKIN +#include +#include +#endif + #define ALIGNPTR(p) (void*)((((uintptr)(void*)p) + sizeof(void*)-1) & ~(sizeof(void*)-1)) // PDP-10 like byte functions diff --git a/src/core/config.h b/src/core/config.h index c52a708d..84712af3 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -234,6 +234,7 @@ enum Config { #define CAMERA_PICKUP // Peds +#define PED_SKIN // support for skinned geometry on 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 diff --git a/src/core/main.cpp b/src/core/main.cpp index 77daaa01..7013b10f 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -794,6 +794,7 @@ RenderDebugShit(void) if(gbShowCollisionLines) CRenderer::RenderCollisionLines(); ThePaths.DisplayPathData(); + CDebug::DrawLines(); #endif } diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 3dce53da..756e1232 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "General.h" +#include "RwHelper.h" #include "ModelIndices.h" #include "Timer.h" #include "Placeable.h" @@ -24,6 +25,8 @@ #include "References.h" #include "TxdStore.h" #include "Zones.h" +#include "Bones.h" +#include "Debug.h" int gBuildings; @@ -282,6 +285,28 @@ CEntity::CreateRwObject(void) } } +#ifdef PED_SKIN +RpAtomic* +AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data) +{ + if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))){ + RpHAnimHierarchy *hier = RpSkinAtomicGetHAnimHierarchy(atomic); +#ifdef LIBRW + if(hier && hier->interpolator->currentAnim){ + RpHAnimAnimationDestroy(hier->interpolator->currentAnim); + hier->interpolator->currentAnim = nil; + } +#else + if(hier && hier->pCurrentAnim){ + RpHAnimAnimationDestroy(hier->pCurrentAnim); + hier->pCurrentAnim = nil; + } +#endif + } + return atomic; +} +#endif + void CEntity::DeleteRwObject(void) { @@ -293,8 +318,13 @@ CEntity::DeleteRwObject(void) f = RpAtomicGetFrame((RpAtomic*)m_rwObject); RpAtomicDestroy((RpAtomic*)m_rwObject); RwFrameDestroy(f); - }else if(RwObjectGetType(m_rwObject) == rpCLUMP) + }else if(RwObjectGetType(m_rwObject) == rpCLUMP){ +#ifdef PED_SKIN + if(IsClumpSkinned((RpClump*)m_rwObject)) + RpClumpForAllAtomics((RpClump*)m_rwObject, AtomicRemoveAnimFromSkinCB, nil); +#endif RpClumpDestroy((RpClump*)m_rwObject); + } m_rwObject = nil; CModelInfo::GetModelInfo(m_modelIndex)->RemoveRef(); if(IsBuilding()) @@ -558,6 +588,44 @@ CEntity::PruneReferences(void) } } +#ifdef PED_SKIN +void +CEntity::UpdateRpHAnim(void) +{ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + RpHAnimHierarchyUpdateMatrices(hier); + +#if 0 + int i; + char buf[256]; + if(this == (CEntity*)FindPlayerPed()) + for(i = 0; i < hier->numNodes; i++){ + RpHAnimStdKeyFrame *kf = (RpHAnimStdKeyFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i); + sprintf(buf, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %d %s", + kf->q.imag.x, kf->q.imag.y, kf->q.imag.z, kf->q.real, + kf->t.x, kf->t.y, kf->t.z, + HIERNODEID(hier, i), + ConvertBoneTag2BoneName(HIERNODEID(hier, i))); + CDebug::PrintAt(buf, 10, 1+i*3); + + RwMatrix *m = &RpHAnimHierarchyGetMatrixArray(hier)[i]; + sprintf(buf, "%6.3f %6.3f %6.3f %6.3f", + m->right.x, m->up.x, m->at.x, m->pos.x); + CDebug::PrintAt(buf, 80, 1+i*3+0); + sprintf(buf, "%6.3f %6.3f %6.3f %6.3f", + m->right.y, m->up.y, m->at.y, m->pos.y); + CDebug::PrintAt(buf, 80, 1+i*3+1); + sprintf(buf, "%6.3f %6.3f %6.3f %6.3f", + m->right.z, m->up.z, m->at.z, m->pos.z); + CDebug::PrintAt(buf, 80, 1+i*3+2); + } + + void RenderSkeleton(RpHAnimHierarchy *hier); + RenderSkeleton(hier); +#endif +} +#endif + void CEntity::AddSteamsFromGround(CVector *unused) { diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 8c2634f3..ee9e6490 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -148,6 +148,10 @@ public: void ResolveReferences(void); void PruneReferences(void); +#ifdef PED_SKIN + void UpdateRpHAnim(void); +#endif + void PreRenderForGlassWindow(void); void AddSteamsFromGround(CVector *unused); void ModifyMatrixForTreeInWind(void); diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 3977007f..59c01c91 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -4,14 +4,10 @@ #include #include #include +#include #include #include -// TODO: split image<->raster functions in two -// implement raster context -// BMP reader -// geometry locking - using namespace rw; RwUInt8 RwObjectGetType(const RwObject *obj) { return obj->type; } @@ -55,7 +51,7 @@ RwMatrix *RwMatrixMultiply(RwMatrix * matrixOut, const RwMatrix * MatrixIn1, con RwMatrix *RwMatrixTransform(RwMatrix * matrix, const RwMatrix * transform, RwOpCombineType combineOp) { matrix->transform(transform, (rw::CombineOp)combineOp); return matrix; } //RwMatrix *RwMatrixOrthoNormalize(RwMatrix * matrixOut, const RwMatrix * matrixIn); -//RwMatrix *RwMatrixInvert(RwMatrix * matrixOut, const RwMatrix * matrixIn); +RwMatrix *RwMatrixInvert(RwMatrix * matrixOut, const RwMatrix * matrixIn) { Matrix::invert(matrixOut, matrixIn); return matrixOut; } RwMatrix *RwMatrixScale(RwMatrix * matrix, const RwV3d * scale, RwOpCombineType combineOp) { matrix->scale(scale, (rw::CombineOp)combineOp); return matrix; } RwMatrix *RwMatrixTranslate(RwMatrix * matrix, const RwV3d * translation, RwOpCombineType combineOp) @@ -742,14 +738,24 @@ RwBool RpHAnimPluginAttach(void) { return true; } +RwInt32 RpHAnimFrameGetID(RwFrame *frame) { return HAnimData::get(frame)->id; } + +RwInt32 RpHAnimIDGetIndex(RpHAnimHierarchy *hierarchy, RwInt32 ID) { return hierarchy->getIndex(ID); } + RwBool RpHAnimFrameSetHierarchy(RwFrame *frame, RpHAnimHierarchy *hierarchy) { HAnimData::get(frame)->hierarchy = hierarchy; return true; } RpHAnimHierarchy *RpHAnimFrameGetHierarchy(RwFrame *frame) { return HAnimHierarchy::get(frame); } -RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim) { hierarchy->currentAnim->setCurrentAnim(anim); return true; } -RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time) { hierarchy->currentAnim->addTime(time); return true; } +RpHAnimHierarchy *RpHAnimHierarchySetFlags(RpHAnimHierarchy *hierarchy, RpHAnimHierarchyFlag flags) { hierarchy->flags = flags; return hierarchy; } +RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim) { hierarchy->interpolator->setCurrentAnim(anim); return true; } +RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time) { hierarchy->interpolator->addTime(time); return true; } + +RwMatrix *RpHAnimHierarchyGetMatrixArray(RpHAnimHierarchy *hierarchy) { return hierarchy->matrices; } RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy) { hierarchy->updateMatrices(); return true; } +RpHAnimAnimation *RpHAnimAnimationCreate(RwInt32 typeID, RwInt32 numFrames, RwInt32 flags, RwReal duration) + { return Animation::create(AnimInterpolatorInfo::find(typeID), numFrames, flags, duration); } +RpHAnimAnimation *RpHAnimAnimationDestroy(RpHAnimAnimation *animation) { animation->destroy(); return animation; } RpHAnimAnimation *RpHAnimAnimationStreamRead(RwStream *stream) { return Animation::streamRead(stream); } @@ -762,6 +768,13 @@ RwBool RpSkinPluginAttach(void) { return true; } +RwUInt32 RpSkinGetNumBones( RpSkin *skin ) { return skin->numBones; } +const RwMatrixWeights *RpSkinGetVertexBoneWeights( RpSkin *skin ) { return (RwMatrixWeights*)skin->weights; } +const RwUInt32 *RpSkinGetVertexBoneIndices( RpSkin *skin ) { return (RwUInt32*)skin->indices; } +const RwMatrix *RpSkinGetSkinToBoneMatrices( RpSkin *skin ) { return (const RwMatrix*)skin->inverseMatrices; } + +RpSkin *RpSkinGeometryGetSkin( RpGeometry *geometry ) { return Skin::get(geometry); } + RpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy ) { Skin::setHierarchy(atomic, hierarchy); return atomic; } RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ) { return Skin::getHierarchy(atomic); } @@ -772,6 +785,23 @@ RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ) { retu RwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName) { rw::writeBMP(image, imageName); return image; } RwImage *RtBMPImageRead(const RwChar * imageName) { return rw::readBMP(imageName); } +#include "rtquat.h" + +RtQuat *RtQuatRotate(RtQuat * quat, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp) { return quat->rotate(axis, angle/180.0f*3.14159f, (CombineOp)combineOp); } +void RtQuatConvertToMatrix(const RtQuat * const qpQuat, RwMatrix * const mpMatrix) { mpMatrix->rotate(*qpQuat, COMBINEREPLACE); } + + +#include "rtcharse.h" + +RwBool RtCharsetOpen(void) { return Charset::open(); } +void RtCharsetClose(void) { return Charset::close(); } +RtCharset *RtCharsetPrint(RtCharset * charSet, const RwChar * string, RwInt32 x, RwInt32 y) { charSet->print(string, x, y, true); return charSet; } +RtCharset *RtCharsetPrintBuffered(RtCharset * charSet, const RwChar * string, RwInt32 x, RwInt32 y, RwBool hideSpaces) { charSet->printBuffered(string, x, y, hideSpaces); return charSet; } +RwBool RtCharsetBufferFlush(void) { Charset::flushBuffer(); return true; } +RtCharset *RtCharsetSetColors(RtCharset * charSet, const RwRGBA * foreGround, const RwRGBA * backGround) { return charSet->setColors(foreGround, backGround); } +RtCharset *RtCharsetGetDesc(RtCharset * charset, RtCharsetDesc * desc) { *desc = charset->desc; return charset; } +RtCharset *RtCharsetCreate(const RwRGBA * foreGround, const RwRGBA * backGround) { return Charset::create(foreGround, backGround); } +RwBool RtCharsetDestroy(RtCharset * charSet) { charSet->destroy(); return true; } diff --git a/src/fakerw/rphanim.h b/src/fakerw/rphanim.h index 665e03f8..34dfeb09 100644 --- a/src/fakerw/rphanim.h +++ b/src/fakerw/rphanim.h @@ -1,20 +1,56 @@ #pragma once +#include "rtquat.h" + //struct RpHAnimHierarchy; typedef rw::HAnimHierarchy RpHAnimHierarchy; //struct RpHAnimAnimation; typedef rw::Animation RpHAnimAnimation; +#define rpHANIMSTDKEYFRAMETYPEID 0x1 + +typedef rw::HAnimKeyFrame RpHAnimStdKeyFrame; + +enum RpHAnimHierarchyFlag +{ + rpHANIMHIERARCHYSUBHIERARCHY = rw::HAnimHierarchy::SUBHIERARCHY, + rpHANIMHIERARCHYNOMATRICES = rw::HAnimHierarchy::NOMATRICES, + + rpHANIMHIERARCHYUPDATEMODELLINGMATRICES = rw::HAnimHierarchy::UPDATEMODELLINGMATRICES, + rpHANIMHIERARCHYUPDATELTMS = rw::HAnimHierarchy::UPDATELTMS, + rpHANIMHIERARCHYLOCALSPACEMATRICES = rw::HAnimHierarchy::LOCALSPACEMATRICES +}; + +#define rpHANIMPOPPARENTMATRIX rw::HAnimHierarchy::POP +#define rpHANIMPUSHPARENTMATRIX rw::HAnimHierarchy::PUSH + RwBool RpHAnimPluginAttach(void); +RwBool RpHAnimFrameSetID(RwFrame *frame, RwInt32 id); +RwInt32 RpHAnimFrameGetID(RwFrame *frame); + +RwInt32 RpHAnimIDGetIndex(RpHAnimHierarchy *hierarchy, RwInt32 ID); + RwBool RpHAnimFrameSetHierarchy(RwFrame *frame, RpHAnimHierarchy *hierarchy); RpHAnimHierarchy *RpHAnimFrameGetHierarchy(RwFrame *frame); +RpHAnimHierarchy *RpHAnimHierarchySetFlags(RpHAnimHierarchy *hierarchy, RpHAnimHierarchyFlag flags); +RpHAnimHierarchyFlag RpHAnimHierarchyGetFlags(RpHAnimHierarchy *hierarchy); + RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim); RwBool RpHAnimHierarchySetCurrentAnimTime(RpHAnimHierarchy *hierarchy, RwReal time); RwBool RpHAnimHierarchySubAnimTime(RpHAnimHierarchy *hierarchy, RwReal time); RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time); +RwMatrix *RpHAnimHierarchyGetMatrixArray(RpHAnimHierarchy *hierarchy); RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy); +#define rpHANIMHIERARCHYGETINTERPFRAME( hierarchy, nodeIndex ) \ + ( (void *)( ( (RwUInt8 *)&(hierarchy->interpolator[1]) + \ + ((nodeIndex) * \ + hierarchy->interpolator->currentAnimKeyFrameSize) ) ) ) + + +RpHAnimAnimation *RpHAnimAnimationCreate(RwInt32 typeID, RwInt32 numFrames, RwInt32 flags, RwReal duration); +RpHAnimAnimation *RpHAnimAnimationDestroy(RpHAnimAnimation *animation); RpHAnimAnimation *RpHAnimAnimationStreamRead(RwStream *stream); diff --git a/src/fakerw/rpskin.h b/src/fakerw/rpskin.h index dd8551ae..1ffc9f27 100644 --- a/src/fakerw/rpskin.h +++ b/src/fakerw/rpskin.h @@ -2,7 +2,25 @@ #include +//struct RpSkin; +typedef rw::Skin RpSkin; + +struct RwMatrixWeights +{ + RwReal w0; + RwReal w1; + RwReal w2; + RwReal w3; +}; + RwBool RpSkinPluginAttach(void); +RwUInt32 RpSkinGetNumBones( RpSkin *skin ); +const RwMatrixWeights *RpSkinGetVertexBoneWeights( RpSkin *skin ); +const RwUInt32 *RpSkinGetVertexBoneIndices( RpSkin *skin ); +const RwMatrix *RpSkinGetSkinToBoneMatrices( RpSkin *skin ); + +RpSkin *RpSkinGeometryGetSkin( RpGeometry *geometry ); + RpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy ); RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ); diff --git a/src/fakerw/rtcharse.h b/src/fakerw/rtcharse.h new file mode 100644 index 00000000..10eb1f32 --- /dev/null +++ b/src/fakerw/rtcharse.h @@ -0,0 +1,14 @@ +#pragma once + +typedef rw::Charset RtCharset; +typedef rw::Charset::Desc RtCharsetDesc; + +RwBool RtCharsetOpen(void); +void RtCharsetClose(void); +RtCharset *RtCharsetPrint(RtCharset * charSet, const RwChar * string, RwInt32 x, RwInt32 y); +RtCharset *RtCharsetPrintBuffered(RtCharset * charSet, const RwChar * string, RwInt32 x, RwInt32 y, RwBool hideSpaces); +RwBool RtCharsetBufferFlush(void); +RtCharset *RtCharsetSetColors(RtCharset * charSet, const RwRGBA * foreGround, const RwRGBA * backGround); +RtCharset *RtCharsetGetDesc(RtCharset * charset, RtCharsetDesc * desc); +RtCharset *RtCharsetCreate(const RwRGBA * foreGround, const RwRGBA * backGround); +RwBool RtCharsetDestroy(RtCharset * charSet); diff --git a/src/fakerw/rtquat.h b/src/fakerw/rtquat.h new file mode 100644 index 00000000..3cf15f5a --- /dev/null +++ b/src/fakerw/rtquat.h @@ -0,0 +1,10 @@ +#pragma once + +typedef rw::Quat RtQuat; + +RwBool RtQuatConvertFromMatrix(RtQuat * const qpQuat, const RwMatrix * const mpMatrix); +RtQuat *RtQuatRotate(RtQuat * quat, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp); +const RtQuat *RtQuatQueryRotate(const RtQuat *quat, RwV3d * unitAxis, RwReal * angle); +RwV3d *RtQuatTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, const RwInt32 numPoints, const RtQuat *quat); + +void RtQuatConvertToMatrix(const RtQuat * const qpQuat, RwMatrix * const mpMatrix); diff --git a/src/math/Quaternion.h b/src/math/Quaternion.h index fb37dc10..1d04bdff 100644 --- a/src/math/Quaternion.h +++ b/src/math/Quaternion.h @@ -10,6 +10,18 @@ public: float Magnitude(void) const { return Sqrt(x*x + y*y + z*z + w*w); } float MagnitudeSqr(void) const { return x*x + y*y + z*z + w*w; } + void Normalise(void) { + float sq = MagnitudeSqr(); + if(sq == 0.0f) + w = 1.0f; + else{ + float invsqrt = RecipSqrt(sq); + x *= invsqrt; + y *= invsqrt; + z *= invsqrt; + w *= invsqrt; + } + } const CQuaternion &operator+=(CQuaternion const &right) { x += right.x; diff --git a/src/modelinfo/ClumpModelInfo.cpp b/src/modelinfo/ClumpModelInfo.cpp index 464bda61..44faf3c5 100644 --- a/src/modelinfo/ClumpModelInfo.cpp +++ b/src/modelinfo/ClumpModelInfo.cpp @@ -1,5 +1,6 @@ #include "common.h" +#include "RwHelper.h" #include "General.h" #include "NodeName.h" #include "VisibilityPlugins.h" @@ -15,12 +16,40 @@ CClumpModelInfo::DeleteRwObject(void) } } +#ifdef PED_SKIN +static RpAtomic* +SetHierarchyForSkinAtomic(RpAtomic *atomic, void *data) +{ + RpSkinAtomicSetHAnimHierarchy(atomic, (RpHAnimHierarchy*)data); + return nil; +} +#endif + RwObject* CClumpModelInfo::CreateInstance(void) { - if(m_clump) - return (RwObject*)RpClumpClone(m_clump); - return nil; + if(m_clump == nil) + return nil; + RpClump *clone = RpClumpClone(m_clump); +#ifdef PED_SKIN + if(IsClumpSkinned(clone)){ + RpHAnimHierarchy *hier; + RpHAnimAnimation *anim; + + hier = GetAnimHierarchyFromClump(clone); + assert(hier); + // This seems dangerous as only the first atomic will get a hierarchy + // can we guarantee this if hands and head are also in the clump? + RpClumpForAllAtomics(clone, SetHierarchyForSkinAtomic, hier); + anim = HAnimAnimationCreateForHierarchy(hier); + RpHAnimHierarchySetCurrentAnim(hier, anim); +// RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS)); + // the rest is xbox only: + // RpSkinGetNumBones(RpSkinGeometryGetSkin(RpAtomicGetGeometry(IsClumpSkinned(clone)))); + RpHAnimHierarchyUpdateMatrices(hier); + } +#endif + return (RwObject*)clone; } RwObject* @@ -48,8 +77,45 @@ CClumpModelInfo::SetClump(RpClump *clump) CVisibilityPlugins::SetClumpModelInfo(m_clump, this); AddTexDictionaryRef(); RpClumpForAllAtomics(clump, SetAtomicRendererCB, nil); + + // TODO: also set for player? if(strncmp(GetName(), "playerh", 8) == 0) RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); + +#ifdef PED_SKIN + if(IsClumpSkinned(clump)){ + int i; + RpHAnimHierarchy *hier; + RpAtomic *skinAtomic; + RpSkin *skin; + + // mobile: +// hier = nil; +// RwFrameForAllChildren(RpClumpGetFrame(clump), GetHierarchyFromChildNodesCB, &hier); +// assert(hier); +// RpClumpForAllAtomics(clump, SetHierarchyForSkinAtomic, hier); +// skinAtomic = GetFirstAtomic(clump); + + // xbox: + hier = GetAnimHierarchyFromClump(clump); + assert(hier); + RpSkinAtomicSetHAnimHierarchy(IsClumpSkinned(clump), hier); + skinAtomic = IsClumpSkinned(clump); + + assert(skinAtomic); + skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(skinAtomic)); + // ignore const + for(i = 0; i < RpGeometryGetNumVertices(RpAtomicGetGeometry(skinAtomic)); i++){ + RwMatrixWeights *weights = (RwMatrixWeights*)&RpSkinGetVertexBoneWeights(skin)[i]; + float sum = weights->w0 + weights->w1 + weights->w2 + weights->w3; + weights->w0 /= sum; + weights->w1 /= sum; + weights->w2 /= sum; + weights->w3 /= sum; + } +// RpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS)); + } +#endif } void diff --git a/src/modelinfo/PedModelInfo.cpp b/src/modelinfo/PedModelInfo.cpp index 5c801a2b..47080e23 100644 --- a/src/modelinfo/PedModelInfo.cpp +++ b/src/modelinfo/PedModelInfo.cpp @@ -1,6 +1,9 @@ #include "common.h" +#include "RwHelper.h" #include "General.h" +#include "Bones.h" +#include "SurfaceTable.h" #include "Ped.h" #include "NodeName.h" #include "VisibilityPlugins.h" @@ -9,13 +12,31 @@ void CPedModelInfo::DeleteRwObject(void) { - CClumpModelInfo::DeleteRwObject(); if(m_hitColModel) delete m_hitColModel; m_hitColModel = nil; +#ifdef PED_SKIN + RwFrame *frame; + if(m_head){ + frame = RpAtomicGetFrame(m_head); + RpAtomicDestroy(m_head); + RwFrameDestroy(frame); + } + if(m_lhand){ + frame = RpAtomicGetFrame(m_lhand); + RpAtomicDestroy(m_lhand); + RwFrameDestroy(frame); + } + if(m_rhand){ + frame = RpAtomicGetFrame(m_rhand); + RpAtomicDestroy(m_rhand); + RwFrameDestroy(frame); + } +#endif + CClumpModelInfo::DeleteRwObject(); // PC calls this first } -RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[12] = { +RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = { { "Smid", PED_MID, 0, }, // that is strange... { "Shead", PED_HEAD, 0, }, { "Supperarml", PED_UPPERARML, 0, }, @@ -30,15 +51,70 @@ RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[12] = { { nil, 0, 0, }, }; +#ifdef PED_SKIN +struct LimbCBarg +{ + CPedModelInfo *mi; + RpClump *clump; + int32 frameIDs[3]; +}; + +RpAtomic* +CPedModelInfo::findLimbsCb(RpAtomic *atomic, void *data) +{ + LimbCBarg *limbs = (LimbCBarg*)data; + RwFrame *frame = RpAtomicGetFrame(atomic); + const char *name = GetFrameNodeName(frame); + if(CGeneral::faststricmp(name, "Shead01") == 0){ + limbs->frameIDs[0] = RpHAnimFrameGetID(frame); + limbs->mi->m_head = atomic; + RpClumpRemoveAtomic(limbs->clump, atomic); + RwFrameRemoveChild(frame); + }else if(CGeneral::faststricmp(name, "SLhand01") == 0){ + limbs->frameIDs[1] = RpHAnimFrameGetID(frame); + limbs->mi->m_lhand = atomic; + RpClumpRemoveAtomic(limbs->clump, atomic); + RwFrameRemoveChild(frame); + }else if(CGeneral::faststricmp(name, "SRhand01") == 0){ + limbs->frameIDs[2] = RpHAnimFrameGetID(frame); + limbs->mi->m_rhand = atomic; + RpClumpRemoveAtomic(limbs->clump, atomic); + RwFrameRemoveChild(frame); + } + return atomic; +} +#endif + void CPedModelInfo::SetClump(RpClump *clump) { +#ifdef PED_SKIN + + // CB has to be set here before atomics are detached from clump + if(strncmp(GetName(), "player", 7) == 0) + RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); + if(IsClumpSkinned(clump)){ + LimbCBarg limbs = { this, clump, { 0, 0, 0 } }; + RpClumpForAllAtomics(clump, findLimbsCb, &limbs); + } + CClumpModelInfo::SetClump(clump); + SetFrameIds(m_pPedIds); + if(m_hitColModel == nil && !IsClumpSkinned(clump)) + CreateHitColModel(); + // And again because CClumpModelInfo resets it + if(strncmp(GetName(), "player", 7) == 0) + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); + else if(IsClumpSkinned(clump)) + // skinned peds have no low detail version, so they don't have the right render Cb + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedCB); +#else CClumpModelInfo::SetClump(clump); SetFrameIds(m_pPedIds); if(m_hitColModel == nil) CreateHitColModel(); if(strncmp(GetName(), "player", 7) == 0) RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); +#endif } RpAtomic* @@ -157,7 +233,7 @@ CPedModelInfo::CreateHitColModel(void) } if(nodeFrame){ float radius = m_pColNodeInfos[i].radius; - if(m_pColNodeInfos[i].pieceType == 6) + if(m_pColNodeInfos[i].pieceType == PEDPIECE_HEAD) RwFrameForAllObjects(nodeFrame, FindHeadRadiusCB, &radius); RwMatrixTransform(mat, RwFrameGetMatrix(nodeFrame), rwCOMBINEREPLACE); const char *name = GetFrameNodeName(nodeFrame); @@ -172,7 +248,7 @@ CPedModelInfo::CreateHitColModel(void) center.x = mat->pos.x + m_pColNodeInfos[i].x; center.y = mat->pos.y + 0.0f; center.z = mat->pos.z + m_pColNodeInfos[i].z; - spheres[i].Set(radius, center, 17, m_pColNodeInfos[i].pieceType); + spheres[i].Set(radius, center, SURFACE_FLESH, m_pColNodeInfos[i].pieceType); } } RwMatrixDestroy(mat); @@ -186,7 +262,7 @@ CPedModelInfo::CreateHitColModel(void) max.x = max.y = 0.5f; max.z = 1.2f; colmodel->boundingBox.Set(min, max, 0, 0); - colmodel->level = 0; + colmodel->level = LEVEL_NONE; m_hitColModel = colmodel; } @@ -229,3 +305,81 @@ CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame) return colmodel; } + +#ifdef PED_SKIN +void +CPedModelInfo::CreateHitColModelSkinned(RpClump *clump) +{ + CVector center; + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump); + CColModel *colmodel = new CColModel; + CColSphere *spheres = (CColSphere*)RwMalloc(NUMPEDINFONODES*sizeof(CColSphere)); + RwFrame *root = RpClumpGetFrame(m_clump); + RwMatrix *invmat = RwMatrixCreate(); + RwMatrix *mat = RwMatrixCreate(); + RwMatrixInvert(invmat, RwFrameGetMatrix(RpClumpGetFrame(clump))); + + for(int i = 0; i < NUMPEDINFONODES; i++){ + *mat = *invmat; + int id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode); // this is wrong, wtf R* ??? + int idx = RpHAnimIDGetIndex(hier, id); + + // This doesn't really work as the positions are not initialized yet + RwMatrixTransform(mat, &RpHAnimHierarchyGetMatrixArray(hier)[idx], rwCOMBINEPRECONCAT); + RwV3d pos = { 0.0f, 0.0f, 0.0f }; + RwV3dTransformPoints(&pos, &pos, 1, mat); + + center.x = pos.x + m_pColNodeInfos[i].x; + center.y = pos.y + 0.0f; + center.z = pos.z + m_pColNodeInfos[i].z; + spheres[i].Set(m_pColNodeInfos[i].radius, center, SURFACE_FLESH, m_pColNodeInfos[i].pieceType); + } + RwMatrixDestroy(invmat); + RwMatrixDestroy(mat); + colmodel->spheres = spheres; + colmodel->numSpheres = NUMPEDINFONODES; + center.x = center.y = center.z = 0.0f; + colmodel->boundingSphere.Set(2.0f, center, 0, 0); + CVector min, max; + min.x = min.y = -0.5f; + min.z = -1.2f; + max.x = max.y = 0.5f; + max.z = 1.2f; + colmodel->boundingBox.Set(min, max, 0, 0); + colmodel->level = LEVEL_NONE; + m_hitColModel = colmodel; +} + +CColModel* +CPedModelInfo::AnimatePedColModelSkinned(RpClump *clump) +{ + if(m_hitColModel == nil){ + CreateHitColModelSkinned(clump); + return m_hitColModel; + } + RwMatrix *invmat, *mat; + CColSphere *spheres = m_hitColModel->spheres; + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump); + invmat = RwMatrixCreate(); + mat = RwMatrixCreate(); + RwMatrixInvert(invmat, RwFrameGetMatrix(RpClumpGetFrame(clump))); + + for(int i = 0; i < NUMPEDINFONODES; i++){ + *mat = *invmat; + int id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode); + int idx = RpHAnimIDGetIndex(hier, id); + + RwMatrixTransform(mat, &RpHAnimHierarchyGetMatrixArray(hier)[idx], rwCOMBINEPRECONCAT); + RwV3d pos = { 0.0f, 0.0f, 0.0f }; + RwV3dTransformPoints(&pos, &pos, 1, mat); + + spheres[i].center.x = pos.x + m_pColNodeInfos[i].x; + spheres[i].center.y = pos.y + 0.0f; + spheres[i].center.z = pos.z + m_pColNodeInfos[i].z; + } + RwMatrixDestroy(invmat); + RwMatrixDestroy(mat); + return m_hitColModel; +} + +#endif diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h index 0336fa9b..a2bfd122 100644 --- a/src/modelinfo/PedModelInfo.h +++ b/src/modelinfo/PedModelInfo.h @@ -28,11 +28,13 @@ public: ePedStats m_pedStatType; uint32 m_carsCanDrive; CColModel *m_hitColModel; +#ifdef PED_SKIN RpAtomic *m_head; RpAtomic *m_lhand; RpAtomic *m_rhand; +#endif - static RwObjectNameIdAssocation m_pPedIds[12]; + static RwObjectNameIdAssocation m_pPedIds[PED_NODE_MAX]; CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { } void DeleteRwObject(void); @@ -40,7 +42,18 @@ public: void SetLowDetailClump(RpClump*); void CreateHitColModel(void); + void CreateHitColModelSkinned(RpClump *clump); CColModel *GetHitColModel(void) { return m_hitColModel; } static CColModel *AnimatePedColModel(CColModel* colmodel, RwFrame* frame); + CColModel *AnimatePedColModelSkinned(RpClump *clump); + +#ifdef PED_SKIN + static RpAtomic *findLimbsCb(RpAtomic *atomic, void *data); + RpAtomic *getHead(void) { return m_head; } + RpAtomic *getLeftHand(void) { return m_lhand; } + RpAtomic *getRightHand(void) { return m_rhand; } +#endif }; -static_assert(sizeof(CPedModelInfo) == 0x54, "CPedModelInfo: error"); +#ifndef PED_SKIN +static_assert(sizeof(CPedModelInfo) == 0x48, "CPedModelInfo: error"); +#endif \ No newline at end of file diff --git a/src/objects/CutsceneHead.cpp b/src/objects/CutsceneHead.cpp index b716e17e..3ef257d2 100644 --- a/src/objects/CutsceneHead.cpp +++ b/src/objects/CutsceneHead.cpp @@ -5,6 +5,7 @@ #include "RwHelper.h" #include "RpAnimBlend.h" #include "AnimBlendClumpData.h" +#include "Bones.h" #include "Directory.h" #include "CutsceneMgr.h" #include "Streaming.h" @@ -17,11 +18,23 @@ CCutsceneHead::CCutsceneHead(CObject *obj) RpAtomic *atm; assert(RwObjectGetType(obj->m_rwObject) == rpCLUMP); - m_pHeadNode = RpAnimBlendClumpFindFrame((RpClump*)obj->m_rwObject, "Shead")->frame; - atm = (RpAtomic*)GetFirstObject(m_pHeadNode); - if(atm){ - assert(RwObjectGetType((RwObject*)atm) == rpATOMIC); - RpAtomicSetFlags(atm, RpAtomicGetFlags(atm) & ~rpATOMICRENDER); +#ifdef PED_SKIN + unk1 = 0; + bIsSkinned = false; + m_parentObject = (CCutsceneObject*)obj; + // Hide original head + if(IsClumpSkinned(obj->GetClump())){ + m_parentObject->SetRenderHead(false); + bIsSkinned = true; + }else +#endif + { + m_pHeadNode = RpAnimBlendClumpFindFrame((RpClump*)obj->m_rwObject, "Shead")->frame; + atm = (RpAtomic*)GetFirstObject(m_pHeadNode); + if(atm){ + assert(RwObjectGetType((RwObject*)atm) == rpATOMIC); + RpAtomicSetFlags(atm, RpAtomicGetFlags(atm) & ~rpATOMICRENDER); + } } } @@ -48,11 +61,28 @@ CCutsceneHead::ProcessControl(void) RpAtomic *atm; RpHAnimHierarchy *hier; + // android/xbox calls is at the end CPhysical::ProcessControl(); - m_matrix.SetRotateY(PI/2); - m_matrix = CMatrix(RwFrameGetLTM(m_pHeadNode)) * m_matrix; - UpdateRwFrame(); +#ifdef PED_SKIN + if(bIsSkinned){ + UpdateRpHAnim(); + UpdateRwFrame(); + + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump()); + int idx = RpHAnimIDGetIndex(hier, BONE_head); + RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + if(RwV3dLength(&mat->pos) > 100.0f){ + m_matrix.SetRotateY(PI/2); + m_matrix = CMatrix(mat) * m_matrix; + } + }else +#endif + { + m_matrix.SetRotateY(PI/2); + m_matrix = CMatrix(RwFrameGetLTM(m_pHeadNode)) * m_matrix; + UpdateRwFrame(); // android/xbox don't call this + } assert(RwObjectGetType(m_rwObject) == rpCLUMP); atm = GetFirstAtomic((RpClump*)m_rwObject); @@ -65,8 +95,25 @@ CCutsceneHead::Render(void) { RpAtomic *atm; - m_matrix.SetRotateY(PI/2); - m_matrix = CMatrix(RwFrameGetLTM(m_pHeadNode)) * m_matrix; +#ifdef PED_SKIN + if(bIsSkinned){ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump()); + RpHAnimHierarchyUpdateMatrices(hier); + int idx = RpHAnimIDGetIndex(hier, BONE_head); + RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + if(RwV3dLength(&mat->pos) > 100.0f){ + m_matrix.SetRotateY(PI/2); + m_matrix = CMatrix(mat) * m_matrix; + } + RenderLimb(BONE_Lhand); + RenderLimb(BONE_Rhand); + }else +#endif + { + m_matrix.SetRotateY(PI/2); + m_matrix = CMatrix(RwFrameGetLTM(m_pHeadNode)) * m_matrix; + } + UpdateRwFrame(); assert(RwObjectGetType(m_rwObject) == rpCLUMP); @@ -76,6 +123,34 @@ CCutsceneHead::Render(void) CObject::Render(); } +#ifdef PED_SKIN +void +CCutsceneHead::RenderLimb(int32 bone) +{ + RpAtomic *atomic; + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump()); + int idx = RpHAnimIDGetIndex(hier, bone); + RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier); + CPedModelInfo *mi = (CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex); + switch(bone){ + case BONE_Lhand: + atomic = mi->getLeftHand(); + break; + case BONE_Rhand: + atomic = mi->getRightHand(); + break; + default: + return; + } + if(atomic){ + RwFrame *frame = RpAtomicGetFrame(atomic); + RwMatrixTransform(RwFrameGetMatrix(frame), &mats[idx], rwCOMBINEREPLACE); + RwFrameUpdateObjects(frame); + RpAtomicRender(atomic); + } +} +#endif + void CCutsceneHead::PlayAnimation(const char *animName) { diff --git a/src/objects/CutsceneHead.h b/src/objects/CutsceneHead.h index 52b66ede..0a70353d 100644 --- a/src/objects/CutsceneHead.h +++ b/src/objects/CutsceneHead.h @@ -6,6 +6,12 @@ class CCutsceneHead : public CCutsceneObject { public: RwFrame *m_pHeadNode; +#ifdef PED_SKIN + int32 unk1; + CCutsceneObject *m_parentObject; + int32 unk2; + int32 bIsSkinned; +#endif CCutsceneHead(CObject *obj); @@ -13,7 +19,10 @@ public: void DeleteRwObject(void); void ProcessControl(void); void Render(void); + void RenderLimb(int32 bone); void PlayAnimation(const char *animName); }; +#ifndef PED_SKIN static_assert(sizeof(CCutsceneHead) == 0x19C, "CCutsceneHead: error"); +#endif diff --git a/src/objects/CutsceneObject.cpp b/src/objects/CutsceneObject.cpp index cee83848..7b4ae02b 100644 --- a/src/objects/CutsceneObject.cpp +++ b/src/objects/CutsceneObject.cpp @@ -1,10 +1,12 @@ #include "common.h" #include "main.h" +#include "RwHelper.h" #include "Lights.h" #include "PointLights.h" #include "RpAnimBlend.h" #include "AnimBlendClumpData.h" +#include "Bones.h" #include "Renderer.h" #include "ModelIndices.h" #include "Shadows.h" @@ -19,6 +21,12 @@ CCutsceneObject::CCutsceneObject(void) ObjectCreatedBy = CUTSCENE_OBJECT; m_fMass = 1.0f; m_fTurnMass = 1.0f; + +#ifdef PED_SKIN + bRenderHead = true; + bRenderRightHand = true; + bRenderLeftHand = true; +#endif } void @@ -42,12 +50,24 @@ CCutsceneObject::ProcessControl(void) m_vecMoveSpeed *= 1.0f/CTimer::GetTimeStep(); ApplyMoveSpeed(); + +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())) + UpdateRpHAnim(); +#endif +} + +static RpMaterial* +MaterialSetAlpha(RpMaterial *material, void *data) +{ + ((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uintptr)data; + return material; } void CCutsceneObject::PreRender(void) { - if(IsPedModel(GetModelIndex())) + if(IsPedModel(GetModelIndex())){ CShadows::StoreShadowForPedObject(this, CTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue], @@ -55,14 +75,57 @@ CCutsceneObject::PreRender(void) CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]); + // For some reason xbox/android limbs are transparent here... + RpGeometry *geometry = RpAtomicGetGeometry(GetFirstAtomic(GetClump())); + RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR); + RpGeometryForAllMaterials(geometry, MaterialSetAlpha, (void*)255); + } } void CCutsceneObject::Render(void) { +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + if(bRenderLeftHand) RenderLimb(BONE_Lhand); + if(bRenderRightHand) RenderLimb(BONE_Rhand); + if(bRenderHead) RenderLimb(BONE_head); + } +#endif CObject::Render(); } +#ifdef PED_SKIN +void +CCutsceneObject::RenderLimb(int32 bone) +{ + RpAtomic *atomic; + CPedModelInfo *mi = (CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex); + switch(bone){ + case BONE_head: + atomic = mi->getHead(); + break; + case BONE_Lhand: + atomic = mi->getLeftHand(); + break; + case BONE_Rhand: + atomic = mi->getRightHand(); + break; + default: + return; + } + if(atomic){ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int idx = RpHAnimIDGetIndex(hier, bone); + RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwFrame *frame = RpAtomicGetFrame(atomic); + *RwFrameGetMatrix(frame) = *mat; + RwFrameUpdateObjects(frame); + RpAtomicRender(atomic); + } +} +#endif + bool CCutsceneObject::SetupLighting(void) { diff --git a/src/objects/CutsceneObject.h b/src/objects/CutsceneObject.h index 31c3a528..9c4036bf 100644 --- a/src/objects/CutsceneObject.h +++ b/src/objects/CutsceneObject.h @@ -5,13 +5,29 @@ class CCutsceneObject : public CObject { public: +#ifdef PED_SKIN + bool bRenderHead; + bool bRenderRightHand; + bool bRenderLeftHand; + + bool GetRenderHead(void) { return bRenderHead; } + bool GetRenderRightHand(void) { return bRenderRightHand; } + bool GetRenderLeftHand(void) { return bRenderLeftHand; } + void SetRenderHead(bool render) { bRenderHead = render; } + void SetRenderRightHand(bool render) { bRenderRightHand = render; } + void SetRenderLeftHand(bool render) { bRenderLeftHand = render; } +#endif + CCutsceneObject(void); void SetModelIndex(uint32 id); void ProcessControl(void); void PreRender(void); void Render(void); + void RenderLimb(int32 bone); bool SetupLighting(void); void RemoveLighting(bool reset); }; +#ifndef PED_SKIN static_assert(sizeof(CCutsceneObject) == 0x198, "CCutsceneObject: error"); +#endif diff --git a/src/peds/CivilianPed.h b/src/peds/CivilianPed.h index 6082c6ab..88d034c8 100644 --- a/src/peds/CivilianPed.h +++ b/src/peds/CivilianPed.h @@ -11,4 +11,6 @@ public: void CivilianAI(void); void ProcessControl(void); }; +#ifndef PED_SKIN static_assert(sizeof(CCivilianPed) == 0x53C, "CCivilianPed: error"); +#endif diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 98a07316..3fc8b8ca 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -465,8 +465,7 @@ CCopPed::CopAI(void) 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)); + TransformToNode(gunPos, PED_HANDR); CColPoint foundCol; CEntity *foundEnt; diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index e3454875..e9780035 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -36,4 +36,6 @@ public: void CopAI(void); }; +#ifndef PED_SKIN static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error"); +#endif diff --git a/src/peds/EmergencyPed.h b/src/peds/EmergencyPed.h index 6546e902..6d3dac79 100644 --- a/src/peds/EmergencyPed.h +++ b/src/peds/EmergencyPed.h @@ -36,4 +36,6 @@ public: void FiremanAI(void); void MedicAI(void); }; +#ifndef PED_SKIN static_assert(sizeof(CEmergencyPed) == 0x554, "CEmergencyPed: error"); +#endif diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index f4cdff70..dcb167f0 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -6,6 +6,7 @@ #include "Stats.h" #include "World.h" #include "RpAnimBlend.h" +#include "Bones.h" #include "Ped.h" #include "Wanted.h" #include "PlayerPed.h" @@ -642,6 +643,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_collPoly.valid = false; m_fCollisionSpeed = 0.0f; m_wepModelID = -1; +#ifdef PED_SKIN + m_pWeaponModel = nil; +#endif CPopulation::UpdatePedCount((ePedType)m_nPedType, false); } @@ -818,10 +822,17 @@ CPed::AddWeaponModel(int id) RpAtomic *atm; if (id != -1) { - atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); - RwFrameDestroy(RpAtomicGetFrame(atm)); - RpAtomicSetFrame(atm, GetNodeFrame(PED_HANDR)); - RpClumpAddAtomic(GetClump(), atm); +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())) + m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); + else +#endif + { + atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance(); + RwFrameDestroy(RpAtomicGetFrame(atm)); + RpAtomicSetFrame(atm, m_pFrames[PED_HANDR]->frame); + RpClumpAddAtomic(GetClump(), atm); + } m_wepModelID = id; } } @@ -915,25 +926,28 @@ void CPed::RemoveBodyPart(PedNode nodeId, int8 direction) { RwFrame *frame; - RwV3d pos; + CVector pos; - frame = GetNodeFrame(nodeId); + frame = m_pFrames[nodeId]->frame; if (frame) { if (CGame::nastyGame) { -#ifdef TOGGLEABLE_BETA_FEATURES - if (bPopHeadsOnHeadshot || nodeId != PED_HEAD) -#else - if (nodeId != PED_HEAD) +#ifdef PED_SKIN + if(!IsClumpSkinned(GetClump())) #endif - SpawnFlyingComponent(nodeId, direction); + { +#ifdef TOGGLEABLE_BETA_FEATURES + if (bPopHeadsOnHeadshot || nodeId != PED_HEAD) +#else + if (nodeId != PED_HEAD) +#endif + SpawnFlyingComponent(nodeId, direction); - RecurseFrameChildrenVisibilityCB(frame, nil); + RecurseFrameChildrenVisibilityCB(frame, nil); + } pos.x = 0.0f; pos.y = 0.0f; pos.z = 0.0f; - - for (; frame; frame = RwFrameGetParent(frame)) - RwV3dTransformPoints(&pos, &pos, 1, RwFrameGetMatrix(frame)); + TransformToNode(pos, PED_HEAD); if (CEntity::GetIsOnScreen()) { CParticle::AddParticle(PARTICLE_TEST, pos, @@ -1102,10 +1116,7 @@ CPed::ClearLookFlag(void) { bool CPed::IsPedHeadAbovePos(float zOffset) { - RwMatrix mat; - - CPedIK::GetWorldMatrix(GetNodeFrame(PED_HEAD), &mat); - return zOffset + GetPosition().z < RwMatrixGetPos(&mat)->z; + return zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z; } void @@ -1158,7 +1169,6 @@ CPed::Attack(void) CAnimBlendAssociation *weaponAnimAssoc; int32 weaponAnim; float animStart; - RwFrame *frame; eWeaponType ourWeaponType; float weaponAnimTime; eWeaponFire ourWeaponFire; @@ -1260,13 +1270,7 @@ CPed::Attack(void) firePos = GetMatrix() * firePos; } else if (ourWeaponType != WEAPONTYPE_UNARMED) { - if (weaponAnimAssoc->animId == ANIM_KICK_FLOOR) - frame = GetNodeFrame(PED_FOOTR); - else - frame = GetNodeFrame(PED_HANDR); - - for (; frame; frame = RwFrameGetParent(frame)) - RwV3dTransformPoints((RwV3d*)firePos, (RwV3d*)firePos, 1, RwFrameGetMatrix(frame)); + TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_KICK_FLOOR ? PED_FOOTR : PED_HANDR); } else { firePos = GetMatrix() * firePos; } @@ -1314,8 +1318,7 @@ CPed::Attack(void) firePos = ourWeapon->m_vecFireOffset; if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) { - for (frame = GetNodeFrame(PED_HANDR); frame; frame = RwFrameGetParent(frame)) - RwV3dTransformPoints((RwV3d*)firePos, (RwV3d*)firePos, 1, RwFrameGetMatrix(frame)); + TransformToNode(firePos, PED_HANDR); CVector gunshellPos( firePos.x - 0.6f * GetForward().x, @@ -1415,7 +1418,17 @@ void CPed::RemoveWeaponModel(int modelId) { // modelId is not used!! This function just removes the current weapon. - RwFrameForAllObjects(GetNodeFrame(PED_HANDR),RemoveAllModelCB,nil); +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + if(m_pWeaponModel){ + RwFrame *frm = RpAtomicGetFrame(m_pWeaponModel); + RpAtomicDestroy(m_pWeaponModel); + RwFrameDestroy(frm); + m_pWeaponModel = nil; + } + }else +#endif + RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil); m_wepModelID = -1; } @@ -2106,12 +2119,7 @@ CPed::PlayFootSteps(void) { { CVector pos(0.0f, 0.0f, 0.0f); - RwFrame *parent = m_pFrames[PED_FOOTL]->frame; - while( parent ) - { - RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(parent)); - parent = RwFrameGetParent(parent); - } + TransformToNode(pos, PED_FOOTL); pos.z -= 0.1f; pos += GetForward()*0.2f; @@ -2120,12 +2128,7 @@ CPed::PlayFootSteps(void) { CVector pos(0.0f, 0.0f, 0.0f); - RwFrame *parent = m_pFrames[PED_FOOTR]->frame; - while( parent ) - { - RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(parent)); - parent = RwFrameGetParent(parent); - } + TransformToNode(pos, PED_FOOTR); pos.z -= 0.1f; pos += GetForward()*0.2f; @@ -2149,9 +2152,7 @@ CPed::PlayFootSteps(void) if (stepPart != 0) { DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f); CVector footPos(0.0f, 0.0f, 0.0f); - - for (RwFrame *frame = GetNodeFrame(stepPart == 1 ? PED_FOOTL : PED_FOOTR); frame; frame = RwFrameGetParent(frame)) - RwV3dTransformPoints(footPos, footPos, 1, RwFrameGetMatrix(frame)); + TransformToNode(footPos, stepPart == 1 ? PED_FOOTL : PED_FOOTR); CVector forward = GetForward(); @@ -2358,6 +2359,11 @@ CPed::SetModelIndex(uint32 mi) // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D. (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta; + +#ifdef PED_SKIN + if(modelInfo->GetHitColModel() == nil) + modelInfo->CreateHitColModelSkinned(GetClump()); +#endif } void @@ -2517,9 +2523,31 @@ CPed::CalculateNewVelocity(void) } if (newUpperLegs.phi > -DEGTORAD(50.0f) && newUpperLegs.phi < DEGTORAD(50.0f)) { - newUpperLegs.theta = 0.0f; - m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGL], &newUpperLegs, false); - m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGR], &newUpperLegs, false); +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ +/* + // this looks shit + newUpperLegs.theta = 0.0f; + RwV3d axis = { -1.0f, 0.0f, 0.0f }; + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.phi), rwCOMBINEPRECONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.phi), rwCOMBINEPRECONCAT); +*/ + newUpperLegs.theta = 0.1f; + RwV3d Xaxis = { 1.0f, 0.0f, 0.0f }; + RwV3d Zaxis = { 0.0f, 0.0f, 1.0f }; + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.theta), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.phi), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.theta), rwCOMBINEPOSTCONCAT); + RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.phi), rwCOMBINEPOSTCONCAT); + + bDontAcceptIKLookAts = true; + }else +#endif + { + newUpperLegs.theta = 0.0f; + m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGL], &newUpperLegs, false); + m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGR], &newUpperLegs, false); + } } } } @@ -5118,6 +5146,12 @@ CPed::FightStrike(CVector &touchedNodePos) // He can beat us if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) { +#ifdef PED_SKIN + // Have to animate a skinned clump because the initial col model is useless + if(IsClumpSkinned(GetClump())) + ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->AnimatePedColModelSkinned(GetClump()); + else +#endif if (nearPed->m_nPedState == PED_FALL || nearPed->m_nPedState == PED_DEAD || nearPed->m_nPedState == PED_DIE || !nearPed->IsPedHeadAbovePos(-0.3f)) { @@ -6153,11 +6187,9 @@ CPed::Die(void) uint8 CPed::DoesLOSBulletHitPed(CColPoint &colPoint) { - RwMatrix mat; uint8 retVal = 2; - CPedIK::GetWorldMatrix(GetNodeFrame(PED_HEAD), &mat); - float headZ = RwMatrixGetPos(&mat)->z; + float headZ = GetNodePosition(PED_HEAD).z; if (m_nPedState == PED_FALL) retVal = 1; @@ -6579,37 +6611,32 @@ CPed::Fight(void) if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) { CVector touchingNodePos(0.0f, 0.0f, 0.0f); - RwFrame *touchingFrame = nil; switch (m_lastFightMove) { case FIGHTMOVE_STDPUNCH: case FIGHTMOVE_PUNCHHOOK: case FIGHTMOVE_BODYBLOW: - touchingFrame = GetNodeFrame(PED_HANDR); + TransformToNode(touchingNodePos, PED_HANDR); break; case FIGHTMOVE_IDLE: case FIGHTMOVE_SHUFFLE_F: break; case FIGHTMOVE_KNEE: - touchingFrame = GetNodeFrame(PED_LOWERLEGR); + TransformToNode(touchingNodePos, PED_LOWERLEGR); break; case FIGHTMOVE_HEADBUTT: - touchingFrame = GetNodeFrame(PED_HEAD); + TransformToNode(touchingNodePos, PED_HEAD); break; case FIGHTMOVE_PUNCHJAB: - touchingFrame = GetNodeFrame(PED_HANDL); + TransformToNode(touchingNodePos, PED_HANDL); break; case FIGHTMOVE_KICK: case FIGHTMOVE_LONGKICK: case FIGHTMOVE_ROUNDHOUSE: case FIGHTMOVE_GROUNDKICK: - touchingFrame = GetNodeFrame(PED_FOOTR); + TransformToNode(touchingNodePos, PED_FOOTR); break; } - while (touchingFrame) { - RwV3dTransformPoints(touchingNodePos, touchingNodePos, 1, RwFrameGetMatrix(touchingFrame)); - touchingFrame = RwFrameGetParent(touchingFrame); - } if (m_lastFightMove == FIGHTMOVE_PUNCHJAB) { touchingNodePos += 0.1f * GetForward(); @@ -7091,8 +7118,7 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg) if (ped->bDoBloodyFootprints) { CVector bloodPos(0.0f, 0.0f, 0.0f); - for (RwFrame *i = ped->GetNodeFrame(PED_FOOTL); i; i = RwFrameGetParent(i)) - RwV3dTransformPoints(bloodPos, bloodPos, 1, RwFrameGetMatrix(i)); + ped->TransformToNode(bloodPos, PED_FOOTL); bloodPos.z -= 0.1f; bloodPos += 0.2f * ped->GetForward(); @@ -7105,8 +7131,7 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg) 255, 255, 0, 0, 4.0f, 3000, 1.0f); bloodPos = CVector(0.0f, 0.0f, 0.0f); - for (RwFrame *j = ped->GetNodeFrame(PED_FOOTR); j; j = RwFrameGetParent(j)) - RwV3dTransformPoints(bloodPos, bloodPos, 1, RwFrameGetMatrix(j)); + ped->TransformToNode(bloodPos, PED_FOOTR); bloodPos.z -= 0.1f; bloodPos += 0.2f * ped->GetForward(); @@ -12647,9 +12672,67 @@ CPed::Render(void) if (!bInVehicle || m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR || bRenderPedInCar && sq(25.0f * TheCamera.LODDistMultiplier) >= (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr()) { CEntity::Render(); + +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + renderLimb(PED_HEAD); + renderLimb(PED_HANDL); + renderLimb(PED_HANDR); + } + if(m_pWeaponModel && IsClumpSkinned(GetClump())){ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID); + RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel); + *RwFrameGetMatrix(frame) = *mat; + RwFrameUpdateObjects(frame); + RpAtomicRender(m_pWeaponModel); + } +#endif } } +#ifdef PED_SKIN +static RpMaterial* +SetLimbAlphaCB(RpMaterial *material, void *data) +{ + ((RwRGBA*)RpMaterialGetColor(material))->alpha = *(uint8*)data; + return material; +} + +void +CPed::renderLimb(int node) +{ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID); + RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + CPedModelInfo *mi = (CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex); + RpAtomic *atomic; + switch(node){ + case PED_HEAD: + atomic = mi->getHead(); + break; + case PED_HANDL: + atomic = mi->getLeftHand(); + break; + case PED_HANDR: + atomic = mi->getRightHand(); + break; + default: + return; + } + if(atomic == nil) + return; + + RwFrame *frame = RpAtomicGetFrame(atomic); + *RwFrameGetMatrix(frame) = *mat; + RwFrameUpdateObjects(frame); + int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump()); + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetLimbAlphaCB, &alpha); + RpAtomicRender(atomic); +} +#endif + void CPed::ProcessObjective(void) { @@ -15065,12 +15148,26 @@ CPed::PreRender(void) CTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]); +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + UpdateRpHAnim(); + + if(bBodyPartJustCameOff && m_bodyPartBleeding == PED_HEAD){ + // scale head to 0 if shot off + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD)); + RwMatrix *head = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; + RwV3d zero = { 0.0f, 0.0f, 0.0f }; + RwMatrixScale(head, &zero, rwCOMBINEPRECONCAT); + } + } +#endif + if (bBodyPartJustCameOff && bIsPedDieAnimPlaying && m_bodyPartBleeding != -1 && (CTimer::GetFrameCounter() & 7) > 3) { CVector bloodDir(0.0f, 0.0f, 0.0f); CVector bloodPos(0.0f, 0.0f, 0.0f); - for (RwFrame *frame = GetNodeFrame(m_bodyPartBleeding); frame; frame = RwFrameGetParent(frame)) - RwV3dTransformPoints(bloodPos, bloodPos, 1, RwFrameGetMatrix(frame)); + TransformToNode(bloodPos, m_bodyPartBleeding); switch (m_bodyPartBleeding) { case PED_HEAD: @@ -16216,11 +16313,10 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk) } } if (CGame::nastyGame) { - RwMatrix headMat; - CPedIK::GetWorldMatrix(GetNodeFrame(PED_HEAD), &headMat); + CVector headPos = GetNodePosition(PED_HEAD); for(int i = 0; i < 4; ++i) { CVector bloodDir(0.0f, 0.0f, 0.1f); - CVector bloodPos = headMat.pos - 0.2f * GetForward(); + CVector bloodPos = headPos - 0.2f * GetForward(); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0); } } @@ -16792,6 +16888,10 @@ CPed::SpawnFlyingComponent(int pedNode, int8 direction) if (CObject::nNoTempObjects >= NUMTEMPOBJECTS) return nil; +#ifdef PED_SKIN + assert(!IsClumpSkinned(GetClump())); +#endif + CObject *obj = new CObject(); if (!obj) return nil; @@ -16799,12 +16899,12 @@ CPed::SpawnFlyingComponent(int pedNode, int8 direction) RwFrame *frame = RwFrameCreate(); RpClump *clump = RpClumpCreate(); RpClumpSetFrame(clump, frame); - RwMatrix *matrix = RwFrameGetLTM(GetNodeFrame(pedNode)); + RwMatrix *matrix = RwFrameGetLTM(m_pFrames[pedNode]->frame); *RwFrameGetMatrix(frame) = *matrix; flyingClumpTemp = clump; - RwFrameForAllObjects(GetNodeFrame(pedNode), CloneAtomicToFrameCB, frame); - RwFrameForAllChildren(GetNodeFrame(pedNode), RecurseFrameChildrenToCloneCB, frame); + RwFrameForAllObjects(m_pFrames[pedNode]->frame, CloneAtomicToFrameCB, frame); + RwFrameForAllChildren(m_pFrames[pedNode]->frame, RecurseFrameChildrenToCloneCB, frame); flyingClumpTemp = nil; switch (pedNode) { case PED_HEAD: diff --git a/src/peds/Ped.h b/src/peds/Ped.h index fd454528..f4caafd8 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -1,5 +1,6 @@ #pragma once +#include "RwHelper.h" #include "AnimManager.h" #include "Crime.h" #include "EventList.h" @@ -380,9 +381,11 @@ public: uint32 bFallenDown : 1; #ifdef VC_PED_PORTS uint32 bSomeVCflag1 : 1; -#else - uint32 m_ped_flagI20 : 1; #endif +#ifdef PED_SKIN + uint32 bDontAcceptIKLookAts : 1; // TODO: find uses of this +#endif + // our own flags uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle @@ -401,6 +404,10 @@ public: CEntity* m_pEventEntity; float m_fAngleToEvent; AnimBlendFrameData *m_pFrames[PED_NODE_MAX]; +#ifdef PED_SKIN + // stored inside the clump with non-skin ped + RpAtomic *m_pWeaponModel; +#endif AssocGroupId m_animGroup; CAnimBlendAssociation *m_pVehicleAnim; CVector2D m_vecAnimMoveDelta; @@ -730,7 +737,6 @@ public: static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); - // functions that I see unnecessary to hook bool IsPlayer(void); bool UseGroundColModel(void); bool CanSetPedState(void); @@ -780,7 +786,6 @@ public: bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } - RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; } PedState GetPedState(void) { return m_nPedState; } void SetPedState(PedState state) { m_nPedState = state; } @@ -815,6 +820,44 @@ public: SetMoveState(PEDMOVE_WALK); } + // Using this to abstract nodes of skinned and non-skinned meshes + CVector GetNodePosition(int32 node) + { +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + RwV3d pos = { 0.0f, 0.0f, 0.0f }; + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID); + RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier); + // this is just stupid + //RwV3dTransformPoints(&pos, &pos, 1, &mats[idx]); + pos = mats[idx].pos; + return pos; + }else +#endif + { + RwMatrix mat; + CPedIK::GetWorldMatrix(m_pFrames[node]->frame, &mat); + return mat.pos; + } + } + void TransformToNode(CVector &pos, int32 node) + { +#ifdef PED_SKIN + if(IsClumpSkinned(GetClump())){ + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); + int32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID); + RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier); + RwV3dTransformPoints((RwV3d*)&pos, (RwV3d*)&pos, 1, &mats[idx]); + }else +#endif + { + RwFrame *frame; + for (frame = m_pFrames[node]->frame; frame; frame = RwFrameGetParent(frame)) + RwV3dTransformPoints((RwV3d*)&pos, (RwV3d*)&pos, 1, RwFrameGetMatrix(frame)); + } + } + // set by 0482:set_threat_reaction_range_multiplier opcode static uint16 nThreatReactionRangeMultiplier; @@ -836,6 +879,10 @@ public: static void SwitchDebugDisplay(void); void DebugRenderOnePedText(void); #endif + +#ifdef PED_SKIN + void renderLimb(int node); +#endif }; class cPedParams @@ -849,6 +896,7 @@ public: void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg); +#ifndef PED_SKIN static_assert(offsetof(CPed, m_nPedState) == 0x224, "CPed: error"); static_assert(offsetof(CPed, m_pCurSurface) == 0x2FC, "CPed: error"); static_assert(offsetof(CPed, m_pMyVehicle) == 0x310, "CPed: error"); @@ -861,3 +909,4 @@ static_assert(offsetof(CPed, m_bodyPartBleeding) == 0x4F2, "CPed: error"); static_assert(offsetof(CPed, m_pedInObjective) == 0x16C, "CPed: error"); static_assert(offsetof(CPed, m_pEventEntity) == 0x19C, "CPed: error"); static_assert(sizeof(CPed) == 0x53C, "CPed: error"); +#endif diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index 1464c4e8..3db3dc0f 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -1,5 +1,6 @@ #include "common.h" +#include "Bones.h" #include "Camera.h" #include "PedIK.h" #include "Ped.h" @@ -12,6 +13,10 @@ LimbMovementInfo CPedIK::ms_headRestoreInfo = { DEGTORAD(90.0f), DEGTORAD(-90.0f LimbMovementInfo CPedIK::ms_upperArmInfo = { DEGTORAD(20.0f), DEGTORAD(-100.0f), DEGTORAD(20.0f), DEGTORAD(70.0f), DEGTORAD(-70.0f), DEGTORAD(10.0f) }; LimbMovementInfo CPedIK::ms_lowerArmInfo = { DEGTORAD(80.0f), DEGTORAD(0.0f), DEGTORAD(20.0f), DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(5.0f) }; +const RwV3d XaxisIK = { 1.0f, 0.0f, 0.0f}; +const RwV3d YaxisIK = { 0.0f, 1.0f, 0.0f}; +const RwV3d ZaxisIK = { 0.0f, 0.0f, 1.0f}; + CPedIK::CPedIK(CPed *ped) { m_ped = ped; @@ -26,57 +31,104 @@ CPedIK::CPedIK(CPed *ped) m_lowerArmOrient.theta = 0.0f; } -void -CPedIK::RotateTorso(AnimBlendFrameData *animBlend, LimbOrientation *limb, bool changeRoll) +#ifdef PED_SKIN +inline RwMatrix* +GetComponentMatrix(CPed *ped, int32 node) { - RwFrame *f = animBlend->frame; - RwMatrix *mat = CPedIK::GetWorldMatrix(RwFrameGetParent(f), RwMatrixCreate()); + RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(ped->GetClump()); + int idx = RpHAnimIDGetIndex(hier, ped->m_pFrames[node]->nodeID); + RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier); + return &mats[idx]; +} +#endif - RwV3d upVector = { mat->right.z, mat->up.z, mat->at.z }; - RwV3d rightVector; - RwV3d pos = RwFrameGetMatrix(f)->pos; +void +CPedIK::RotateTorso(AnimBlendFrameData *node, LimbOrientation *limb, bool changeRoll) +{ +#ifdef PED_SKIN + if(IsClumpSkinned(m_ped->GetClump())){ + RtQuat *q = &node->hanimFrame->q; +#ifndef FIX_BUGS + // this is what the game does (also VC), but it does not look great + RtQuatRotate(q, &XaxisIK, RADTODEG(limb->phi), rwCOMBINEPRECONCAT); + RtQuatRotate(q, &ZaxisIK, RADTODEG(limb->theta), rwCOMBINEPRECONCAT); // pitch +#else + // copied the code from the non-skinned case + // this seems to work ok - // rotation == 0 -> looking in y direction - // left? vector - float c = Cos(m_ped->m_fRotationCur); - float s = Sin(m_ped->m_fRotationCur); - rightVector.x = -(c*mat->right.x + s*mat->right.y); - rightVector.y = -(c*mat->up.x + s*mat->up.y); - rightVector.z = -(c*mat->at.x + s*mat->at.y); + // We can't get the parent matrix of an hanim frame but + // this function is always called with PED_MID, so we know the parent frame. + // Trouble is that PED_MID is "Smid" on PS2/PC but BONE_torso on mobile/xbox... + // so this doesn't exactly do what we'd like anyway + RwMatrix *mat = GetComponentMatrix(m_ped, PED_MID); - if(changeRoll){ - // Used when aiming only involves over the legs.(canAimWithArm) - // Automatically changes roll(forward rotation) axis of the parts above upper legs while moving, based on position of upper legs. - // Not noticeable in normal conditions... + RwV3d vec1, vec2; + vec1.x = mat->right.z; + vec1.y = mat->up.z; + vec1.z = mat->at.z; + float c = Cos(m_ped->m_fRotationCur); + float s = Sin(m_ped->m_fRotationCur); + vec2.x = -(c*mat->right.x + s*mat->right.y); + vec2.y = -(c*mat->up.x + s*mat->up.y); + vec2.z = -(c*mat->at.x + s*mat->at.y); - RwV3d forwardVector; - CVector inversedForward = CrossProduct(CVector(0.0f, 0.0f, 1.0f), mat->up); - inversedForward.Normalise(); - float dotProduct = DotProduct(mat->at, inversedForward); - if(dotProduct > 1.0f) dotProduct = 1.0f; - if(dotProduct < -1.0f) dotProduct = -1.0f; - float alpha = Acos(dotProduct); + // Not sure what exactly to do here + RtQuatRotate(q, &vec1, RADTODEG(limb->phi), rwCOMBINEPRECONCAT); + RtQuatRotate(q, &vec2, RADTODEG(limb->theta), rwCOMBINEPRECONCAT); +#endif + m_ped->bDontAcceptIKLookAts = true; + }else +#endif + { + RwFrame *f = node->frame; + RwMatrix *mat = GetWorldMatrix(RwFrameGetParent(f), RwMatrixCreate()); - if(mat->at.z < 0.0f) - alpha = -alpha; + RwV3d upVector = { mat->right.z, mat->up.z, mat->at.z }; + RwV3d rightVector; + RwV3d pos = RwFrameGetMatrix(f)->pos; - forwardVector.x = s * mat->right.x - c * mat->right.y; - forwardVector.y = s * mat->up.x - c * mat->up.y; - forwardVector.z = s * mat->at.x - c * mat->at.y; + // rotation == 0 -> looking in y direction + // left? vector + float c = Cos(m_ped->m_fRotationCur); + float s = Sin(m_ped->m_fRotationCur); + rightVector.x = -(c*mat->right.x + s*mat->right.y); + rightVector.y = -(c*mat->up.x + s*mat->up.y); + rightVector.z = -(c*mat->at.x + s*mat->at.y); - float curYaw, curPitch; - CPedIK::ExtractYawAndPitchWorld(mat, &curYaw, &curPitch); - RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->theta), rwCOMBINEPOSTCONCAT); - RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->phi - (curYaw - m_ped->m_fRotationCur)), rwCOMBINEPOSTCONCAT); - RwMatrixRotate(RwFrameGetMatrix(f), &forwardVector, RADTODEG(alpha), rwCOMBINEPOSTCONCAT); - }else{ - // pitch - RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->theta), rwCOMBINEPOSTCONCAT); - // yaw - RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->phi), rwCOMBINEPOSTCONCAT); + if(changeRoll){ + // Used when aiming only involves over the legs.(canAimWithArm) + // Automatically changes roll(forward rotation) axis of the parts above upper legs while moving, based on position of upper legs. + // Not noticeable in normal conditions... + + RwV3d forwardVector; + CVector inversedForward = CrossProduct(CVector(0.0f, 0.0f, 1.0f), mat->up); + inversedForward.Normalise(); + float dotProduct = DotProduct(mat->at, inversedForward); + if(dotProduct > 1.0f) dotProduct = 1.0f; + if(dotProduct < -1.0f) dotProduct = -1.0f; + float alpha = Acos(dotProduct); + + if(mat->at.z < 0.0f) + alpha = -alpha; + + forwardVector.x = s * mat->right.x - c * mat->right.y; + forwardVector.y = s * mat->up.x - c * mat->up.y; + forwardVector.z = s * mat->at.x - c * mat->at.y; + + float curYaw, curPitch; + ExtractYawAndPitchWorld(mat, &curYaw, &curPitch); + RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->theta), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->phi - (curYaw - m_ped->m_fRotationCur)), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(f), &forwardVector, RADTODEG(alpha), rwCOMBINEPOSTCONCAT); + }else{ + // pitch + RwMatrixRotate(RwFrameGetMatrix(f), &rightVector, RADTODEG(limb->theta), rwCOMBINEPOSTCONCAT); + // yaw + RwMatrixRotate(RwFrameGetMatrix(f), &upVector, RADTODEG(limb->phi), rwCOMBINEPOSTCONCAT); + } + RwFrameGetMatrix(f)->pos = pos; + RwMatrixDestroy(mat); } - RwFrameGetMatrix(f)->pos = pos; - RwMatrixDestroy(mat); } void @@ -85,12 +137,24 @@ CPedIK::GetComponentPosition(RwV3d *pos, uint32 node) RwFrame *f; RwMatrix *mat; - f = m_ped->GetNodeFrame(node); - mat = RwFrameGetMatrix(f); - *pos = mat->pos; +#ifdef PED_SKIN + if(IsClumpSkinned(m_ped->GetClump())){ + pos->x = 0.0f; + pos->y = 0.0f; + pos->z = 0.0f; + mat = GetComponentMatrix(m_ped, node); + // could just copy the position out of the matrix... + RwV3dTransformPoints(pos, pos, 1, mat); + }else +#endif + { + f = m_ped->m_pFrames[node]->frame; + mat = RwFrameGetMatrix(f); + *pos = mat->pos; - for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) - RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(f)); + for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) + RwV3dTransformPoints(pos, pos, 1, RwFrameGetMatrix(f)); + } } RwMatrix* @@ -157,50 +221,94 @@ CPedIK::RestoreGunPosn(void) return limbStatus == ANGLES_SET_EXACTLY; } +#ifdef PED_SKIN +void +CPedIK::RotateHead(void) +{ + RtQuat *q = &m_ped->m_pFrames[PED_HEAD]->hanimFrame->q; + RtQuatRotate(q, &XaxisIK, RADTODEG(m_headOrient.phi), rwCOMBINEREPLACE); + RtQuatRotate(q, &ZaxisIK, RADTODEG(m_headOrient.theta), rwCOMBINEPOSTCONCAT); + m_ped->bDontAcceptIKLookAts = true; +} +#endif + bool CPedIK::LookInDirection(float phi, float theta) { bool success = true; - RwFrame *frame = m_ped->GetNodeFrame(PED_HEAD); - RwMatrix *frameMat = RwFrameGetMatrix(frame); + float yaw, pitch; +#ifdef PED_SKIN + if(IsClumpSkinned(m_ped->GetClump())){ + if (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) { + m_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION; + ExtractYawAndPitchLocalSkinned(m_ped->m_pFrames[PED_HEAD], &m_headOrient.phi, &m_headOrient.theta); + } + + // parent of head is torso + RwMatrix worldMat = *GetComponentMatrix(m_ped, BONE_torso); + ExtractYawAndPitchWorld(&worldMat, &yaw, &pitch); + + LimbMoveStatus headStatus = MoveLimb(m_headOrient, CGeneral::LimitRadianAngle(phi - yaw), + CGeneral::LimitRadianAngle(DEGTORAD(10.0f)), ms_headInfo); + if (headStatus == ANGLES_SET_TO_MAX) + success = false; + + if (headStatus != ANGLES_SET_EXACTLY){ + if (!(m_flags & LOOKAROUND_HEAD_ONLY)){ + if (MoveLimb(m_torsoOrient, CGeneral::LimitRadianAngle(phi), theta, ms_torsoInfo)) + success = true; + }else{ + RotateHead(); + return success; + } + } + + if (!(m_flags & LOOKAROUND_HEAD_ONLY)) + RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false); + RotateHead(); + }else +#endif + { + RwFrame *frame = m_ped->m_pFrames[PED_HEAD]->frame; + RwMatrix *frameMat = RwFrameGetMatrix(frame); + + if (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) { + m_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION; + ExtractYawAndPitchLocal(frameMat, &m_headOrient.phi, &m_headOrient.theta); + } + + RwMatrix *worldMat = RwMatrixCreate(); + worldMat = GetWorldMatrix(RwFrameGetParent(frame), worldMat); + + ExtractYawAndPitchWorld(worldMat, &yaw, &pitch); + RwMatrixDestroy(worldMat); + + yaw += m_torsoOrient.phi; + float neededPhiTurn = CGeneral::LimitRadianAngle(phi - yaw); + pitch *= Cos(neededPhiTurn); + + float neededThetaTurn = CGeneral::LimitRadianAngle(theta - pitch); + LimbMoveStatus headStatus = MoveLimb(m_headOrient, neededPhiTurn, neededThetaTurn, ms_headInfo); + if (headStatus == ANGLES_SET_TO_MAX) + success = false; + + if (headStatus != ANGLES_SET_EXACTLY && !(m_flags & LOOKAROUND_HEAD_ONLY)) { + float remainingTurn = CGeneral::LimitRadianAngle(phi - m_ped->m_fRotationCur); + if (MoveLimb(m_torsoOrient, remainingTurn, theta, ms_torsoInfo)) + success = true; + } + CMatrix nextFrame = CMatrix(frameMat); + CVector framePos = nextFrame.GetPosition(); + + nextFrame.SetRotateZ(m_headOrient.theta); + nextFrame.RotateX(m_headOrient.phi); + nextFrame.GetPosition() += framePos; + nextFrame.UpdateRW(); + + if (!(m_flags & LOOKAROUND_HEAD_ONLY)) + RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false); - if (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) { - m_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION; - CPedIK::ExtractYawAndPitchLocal(frameMat, &m_headOrient.phi, &m_headOrient.theta); } - - RwMatrix *worldMat = RwMatrixCreate(); - worldMat = CPedIK::GetWorldMatrix(RwFrameGetParent(frame), worldMat); - - float alpha, beta; - CPedIK::ExtractYawAndPitchWorld(worldMat, &alpha, &beta); - RwMatrixDestroy(worldMat); - - alpha += m_torsoOrient.phi; - float neededPhiTurn = CGeneral::LimitRadianAngle(phi - alpha); - beta *= cos(neededPhiTurn); - - float neededThetaTurn = CGeneral::LimitRadianAngle(theta - beta); - LimbMoveStatus headStatus = CPedIK::MoveLimb(m_headOrient, neededPhiTurn, neededThetaTurn, ms_headInfo); - if (headStatus == ANGLES_SET_TO_MAX) - success = false; - - if (headStatus != ANGLES_SET_EXACTLY && !(m_flags & LOOKAROUND_HEAD_ONLY)) { - float remainingTurn = CGeneral::LimitRadianAngle(phi - m_ped->m_fRotationCur); - if (CPedIK::MoveLimb(m_torsoOrient, remainingTurn, theta, ms_torsoInfo)) - success = true; - } - CMatrix nextFrame = CMatrix(frameMat); - CVector framePos = nextFrame.GetPosition(); - - nextFrame.SetRotateZ(m_headOrient.theta); - nextFrame.RotateX(m_headOrient.phi); - nextFrame.GetPosition() += framePos; - nextFrame.UpdateRW(); - - if (!(m_flags & LOOKAROUND_HEAD_ONLY)) - RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false); - return success; } @@ -234,10 +342,24 @@ CPedIK::PointGunInDirection(float phi, float theta) if (m_flags & AIMS_WITH_ARM && m_torsoOrient.phi * m_upperArmOrient.phi < 0.0f) MoveLimb(m_torsoOrient, 0.0f, m_torsoOrient.theta, ms_torsoInfo); } else { - RwMatrix *matrix = GetWorldMatrix(RwFrameGetParent(m_ped->GetNodeFrame(PED_UPPERARMR)), RwMatrixCreate()); + // Unused code + RwMatrix *matrix; float yaw, pitch; - ExtractYawAndPitchWorld(matrix, &yaw, &pitch); - RwMatrixDestroy(matrix); +#ifdef PED_SKIN + if(IsClumpSkinned(m_ped->GetClump())){ + matrix = RwMatrixCreate(); + *matrix = *GetComponentMatrix(m_ped, PED_UPPERARMR); + ExtractYawAndPitchWorld(matrix, &yaw, &pitch); + RwMatrixDestroy(matrix); + }else +#endif + { + matrix = GetWorldMatrix(RwFrameGetParent(m_ped->m_pFrames[PED_UPPERARMR]->frame), RwMatrixCreate()); + ExtractYawAndPitchWorld(matrix, &yaw, &pitch); + RwMatrixDestroy(matrix); + } + // + LimbMoveStatus status = MoveLimb(m_torsoOrient, angle, theta, ms_torsoInfo); if (status == ANGLES_SET_TO_MAX) result = false; @@ -255,24 +377,56 @@ bool CPedIK::PointGunInDirectionUsingArm(float phi, float theta) { bool result = false; - RwFrame *frame = m_ped->GetNodeFrame(PED_UPPERARMR); - RwMatrix *matrix = GetWorldMatrix(RwFrameGetParent(frame), RwMatrixCreate()); - - RwV3d upVector = { matrix->right.z, matrix->up.z, matrix->at.z }; + RwV3d upVector; // only for non-skinned + RwMatrix *matrix; float yaw, pitch; - ExtractYawAndPitchWorld(matrix, &yaw, &pitch); - RwMatrixDestroy(matrix); +#ifdef PED_SKIN + if(IsClumpSkinned(m_ped->GetClump())){ + matrix = RwMatrixCreate(); + *matrix = *GetComponentMatrix(m_ped, PED_UPPERARMR); + ExtractYawAndPitchWorld(matrix, &yaw, &pitch); + RwMatrixDestroy(matrix); + }else +#endif + { + RwFrame *frame = m_ped->m_pFrames[PED_UPPERARMR]->frame; + matrix = GetWorldMatrix(RwFrameGetParent(frame), RwMatrixCreate()); + + // with PED_SKIN this is actually done below (with a memory leak) + upVector.x = matrix->right.z; + upVector.y = matrix->up.z; + upVector.z = matrix->at.z; + + ExtractYawAndPitchWorld(matrix, &yaw, &pitch); + RwMatrixDestroy(matrix); + } RwV3d rightVector = { 0.0f, 0.0f, 1.0f }; RwV3d forwardVector = { 1.0f, 0.0f, 0.0f }; - float uaPhi = phi - m_torsoOrient.phi - DEGTORAD(15.0f); - LimbMoveStatus uaStatus = MoveLimb(m_upperArmOrient, uaPhi, CGeneral::LimitRadianAngle(theta - pitch), ms_upperArmInfo); + float uaPhi, uaTheta; +#ifdef PED_SKIN + if(IsClumpSkinned(m_ped->GetClump())){ + uaPhi = phi; + uaTheta = theta + DEGTORAD(10.0f); + }else +#endif + { + uaPhi = phi - m_torsoOrient.phi - DEGTORAD(15.0f); + uaTheta = CGeneral::LimitRadianAngle(theta - pitch); + } + LimbMoveStatus uaStatus = MoveLimb(m_upperArmOrient, uaPhi, uaTheta, ms_upperArmInfo); if (uaStatus == ANGLES_SET_EXACTLY) { m_flags |= GUN_POINTED_SUCCESSFULLY; result = true; } + +#ifdef PED_SKIN + // this code is completely missing on xbox & android, but we can keep it with the check + // TODO? implement it for skinned geometry? + if(!IsClumpSkinned(m_ped->GetClump())) +#endif if (uaStatus == ANGLES_SET_TO_MAX) { float laPhi = uaPhi - m_upperArmOrient.phi; @@ -286,17 +440,29 @@ CPedIK::PointGunInDirectionUsingArm(float phi, float theta) m_flags |= GUN_POINTED_SUCCESSFULLY; result = true; } - RwFrame *child = GetFirstChild(frame); + RwFrame *child = GetFirstChild(m_ped->m_pFrames[PED_UPPERARMR]->frame); RwV3d pos = RwFrameGetMatrix(child)->pos; RwMatrixRotate(RwFrameGetMatrix(child), &forwardVector, RADTODEG(m_lowerArmOrient.theta), rwCOMBINEPOSTCONCAT); RwMatrixRotate(RwFrameGetMatrix(child), &rightVector, RADTODEG(-m_lowerArmOrient.phi), rwCOMBINEPOSTCONCAT); RwFrameGetMatrix(child)->pos = pos; } - RwV3d pos = RwFrameGetMatrix(frame)->pos; - RwMatrixRotate(RwFrameGetMatrix(frame), &rightVector, RADTODEG(m_upperArmOrient.theta), rwCOMBINEPOSTCONCAT); - RwMatrixRotate(RwFrameGetMatrix(frame), &upVector, RADTODEG(m_upperArmOrient.phi), rwCOMBINEPOSTCONCAT); - RwFrameGetMatrix(frame)->pos = pos; +#ifdef PED_SKIN + if(IsClumpSkinned(m_ped->GetClump())){ + RtQuat *q = &m_ped->m_pFrames[PED_UPPERARMR]->hanimFrame->q; + RtQuatRotate(q, &XaxisIK, RADTODEG(m_upperArmOrient.phi), rwCOMBINEPOSTCONCAT); + RtQuatRotate(q, &ZaxisIK, RADTODEG(m_upperArmOrient.theta), rwCOMBINEPOSTCONCAT); + m_ped->bDontAcceptIKLookAts = true; + }else +#endif + { + RwFrame *frame = m_ped->m_pFrames[PED_UPPERARMR]->frame; + // with PED_SKIN we're also getting upVector here + RwV3d pos = RwFrameGetMatrix(frame)->pos; + RwMatrixRotate(RwFrameGetMatrix(frame), &rightVector, RADTODEG(m_upperArmOrient.theta), rwCOMBINEPOSTCONCAT); + RwMatrixRotate(RwFrameGetMatrix(frame), &upVector, RADTODEG(m_upperArmOrient.phi), rwCOMBINEPOSTCONCAT); + RwFrameGetMatrix(frame)->pos = pos; + } return result; } @@ -314,28 +480,42 @@ bool CPedIK::RestoreLookAt(void) { bool result = false; - RwMatrix *mat = RwFrameGetMatrix(m_ped->GetNodeFrame(PED_HEAD)); - if (m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION) { - m_ped->m_pFrames[PED_HEAD]->flag &= (~AnimBlendFrameData::IGNORE_ROTATION); - } else { - float yaw, pitch; - ExtractYawAndPitchLocal(mat, &yaw, &pitch); - if (MoveLimb(m_headOrient, yaw, pitch, ms_headRestoreInfo) == ANGLES_SET_EXACTLY) - result = true; + float yaw, pitch; + +#ifdef PED_SKIN + if(IsClumpSkinned(m_ped->GetClump())){ + if (m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION) { + m_ped->m_pFrames[PED_HEAD]->flag &= (~AnimBlendFrameData::IGNORE_ROTATION); + } else { + ExtractYawAndPitchLocalSkinned(m_ped->m_pFrames[PED_HEAD], &yaw, &pitch); + if (MoveLimb(m_headOrient, yaw, pitch, ms_headRestoreInfo) == ANGLES_SET_EXACTLY) + result = true; + } + RotateHead(); + }else +#endif + { + RwMatrix *mat = RwFrameGetMatrix(m_ped->m_pFrames[PED_HEAD]->frame); + if (m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION) { + m_ped->m_pFrames[PED_HEAD]->flag &= (~AnimBlendFrameData::IGNORE_ROTATION); + } else { + ExtractYawAndPitchLocal(mat, &yaw, &pitch); + if (MoveLimb(m_headOrient, yaw, pitch, ms_headRestoreInfo) == ANGLES_SET_EXACTLY) + result = true; + } + + CMatrix matrix(mat); + CVector pos = matrix.GetPosition(); + matrix.SetRotateZ(m_headOrient.theta); + matrix.RotateX(m_headOrient.phi); + matrix.Translate(pos); + matrix.UpdateRW(); } - - CMatrix matrix(mat); - CVector pos = matrix.GetPosition(); - matrix.SetRotateZ(m_headOrient.theta); - matrix.RotateX(m_headOrient.phi); - matrix.Translate(pos); - matrix.UpdateRW(); - - if (!(m_flags & LOOKAROUND_HEAD_ONLY)) + if (!(m_flags & LOOKAROUND_HEAD_ONLY)){ MoveLimb(m_torsoOrient, 0.0f, 0.0f, ms_torsoInfo); - if (!(m_flags & LOOKAROUND_HEAD_ONLY)) - RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false); - + if (!(m_flags & LOOKAROUND_HEAD_ONLY)) + RotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false); + } return result; } @@ -362,3 +542,14 @@ CPedIK::ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch) *pitch = Acos(f); if (mat->up.x > 0.0f) *pitch = -*pitch; } + +#ifdef PED_SKIN +void +CPedIK::ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch) +{ + RwMatrix *mat = RwMatrixCreate(); + RtQuatConvertToMatrix(&node->hanimFrame->q, mat); + ExtractYawAndPitchLocal(mat, yaw, pitch); + RwMatrixDestroy(mat); +} +#endif diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h index 7b82d1ac..fd9e4702 100644 --- a/src/peds/PedIK.h +++ b/src/peds/PedIK.h @@ -55,9 +55,11 @@ public: static RwMatrix *GetWorldMatrix(RwFrame *source, RwMatrix *destination); void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll); void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch); + void ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch); void ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch); LimbMoveStatus MoveLimb(LimbOrientation &limb, float approxPhi, float approxTheta, LimbMovementInfo &moveInfo); bool RestoreGunPosn(void); + void RotateHead(void); bool LookInDirection(float phi, float theta); bool LookAtPosition(CVector const& pos); bool RestoreLookAt(void); diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index 0163c12c..664fff18 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -1,5 +1,6 @@ #include "common.h" +#include "RwHelper.h" #include "PlayerPed.h" #include "Wanted.h" #include "Fire.h" @@ -1497,4 +1498,9 @@ CPlayerPed::ProcessControl(void) m_nSpeedTimer = 0; m_bSpeedTimerFlag = false; } + +#ifdef PED_SKIN + if (!bIsVisible && IsClumpSkinned(GetClump())) + UpdateRpHAnim(); +#endif } diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index 81f8e4d7..b8bd57e4 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -77,4 +77,6 @@ public: static void ReactivatePlayerPed(int32); }; +#ifndef PED_SKIN static_assert(sizeof(CPlayerPed) == 0x5F0, "CPlayerPed: error"); +#endif diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp index 16057420..fc081fa3 100644 --- a/src/render/SpecialFX.cpp +++ b/src/render/SpecialFX.cpp @@ -117,8 +117,14 @@ CSpecialFX::Update(void) if(FindPlayerPed() && FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && - FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING) - RwFrameForAllObjects(FindPlayerPed()->GetNodeFrame(PED_HANDR), LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); + FindPlayerPed()->GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING){ +#ifdef PED_SKIN + if(IsClumpSkinned(FindPlayerPed()->GetClump())){ + LookForBatCB((RwObject*)FindPlayerPed()->m_pWeaponModel, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); + }else +#endif + RwFrameForAllObjects(FindPlayerPed()->m_pFrames[PED_HANDR]->frame, LookForBatCB, CModelInfo::GetModelInfo(MI_BASEBALL_BAT)); + } } void diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index acf811ad..5aa4475f 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -3,16 +3,15 @@ #include "Timecycle.h" #include "skeleton.h" -#if defined(RWLIBS) && !defined(FINAL) +#include "Debug.h" +#ifndef FINAL #include "rtcharse.h" -#pragma comment( lib, "rtcharse.lib" ) - RtCharset *debugCharset; #endif void CreateDebugFont() { -#if defined(RWLIBS) && !defined(FINAL) +#ifndef FINAL RwRGBA color = { 255, 255, 128, 255 }; RwRGBA colorbg = { 0, 0, 0, 0 }; RtCharsetOpen(); @@ -22,7 +21,7 @@ void CreateDebugFont() void DestroyDebugFont() { -#if defined(RWLIBS) && !defined(FINAL) +#ifndef FINAL RtCharsetDestroy(debugCharset); RtCharsetClose(); #endif @@ -30,14 +29,14 @@ void DestroyDebugFont() void ObrsPrintfString(const char *str, short x, short y) { -#if defined(RWLIBS) && !defined(FINAL) - RtCharsetPrintBuffered(debugCharset, str, x, y, true); +#ifndef FINAL + RtCharsetPrintBuffered(debugCharset, str, x*8, y*16, true); #endif } void FlushObrsPrintfs() { -#if defined(RWLIBS) && !defined(FINAL) +#ifndef FINAL RtCharsetBufferFlush(); #endif } @@ -168,6 +167,170 @@ GetFirstTexture(RwTexDictionary *txd) return tex; } +#ifdef PED_SKIN +static RpAtomic* +isSkinnedCb(RpAtomic *atomic, void *data) +{ + RpAtomic **pAtomic = (RpAtomic**)data; + if(*pAtomic) + return nil; // already found one + if(RpSkinGeometryGetSkin(atomic->geometry)) + *pAtomic = atomic; // we could just return nil here directly... + return atomic; +} + +RpAtomic* +IsClumpSkinned(RpClump *clump) +{ + RpAtomic *atomic = nil; + RpClumpForAllAtomics(clump, isSkinnedCb, &atomic); + return atomic; +} + +static RpAtomic* +GetAnimHierarchyCallback(RpAtomic *atomic, void *data) +{ + *(RpHAnimHierarchy**)data = RpSkinAtomicGetHAnimHierarchy(atomic); + return nil; +} + +RpHAnimHierarchy* +GetAnimHierarchyFromSkinClump(RpClump *clump) +{ + RpHAnimHierarchy *hier = nil; + RpClumpForAllAtomics(clump, GetAnimHierarchyCallback, &hier); + return hier; +} + +static RwFrame* +GetAnimHierarchyFromClumpCB(RwFrame *frame, void *data) +{ + RpHAnimHierarchy *hier = RpHAnimFrameGetHierarchy(frame); + if(hier){ + *(RpHAnimHierarchy**)data = hier; + return nil; + } + RwFrameForAllChildren(frame, GetAnimHierarchyFromClumpCB, data); + return frame; +} + +RpHAnimHierarchy* +GetAnimHierarchyFromClump(RpClump *clump) +{ + RpHAnimHierarchy *hier = nil; + RwFrameForAllChildren(RpClumpGetFrame(clump), GetAnimHierarchyFromClumpCB, &hier); + return hier; +} + +RwFrame* +GetHierarchyFromChildNodesCB(RwFrame *frame, void *data) +{ + RpHAnimHierarchy **pHier = (RpHAnimHierarchy**)data; + RpHAnimHierarchy *hier = RpHAnimFrameGetHierarchy(frame); + if(hier == nil) + RwFrameForAllChildren(frame, GetHierarchyFromChildNodesCB, &hier); + *pHier = hier; + return nil; +} + +void +SkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable) +{ + int i, parent; + RpAtomic *atomic; + RpSkin *skin; + RpHAnimHierarchy *hier; + int numBones; + RwMatrix m, invmat; + int stack[32]; + int sp; + + if(boneTable == nil) + return; + +// atomic = GetFirstAtomic(clump); // mobile, also VC + atomic = IsClumpSkinned(clump); // xbox, seems safer + assert(atomic); + skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)); + assert(skin); + hier = GetAnimHierarchyFromSkinClump(clump); + assert(hier); + boneTable[0].x = 0.0f; + boneTable[0].y = 0.0f; + boneTable[0].z = 0.0f; + numBones = RpSkinGetNumBones(skin); + parent = 0; + sp = 0; +#ifdef FIX_BUGS + stack[0] = 0; // i think this is ok +#endif + for(i = 1; i < numBones; i++){ + RwMatrixCopy(&m, &RpSkinGetSkinToBoneMatrices(skin)[i]); + RwMatrixInvert(&invmat, &m); + const RwMatrix *x = RpSkinGetSkinToBoneMatrices(skin); + RwV3dTransformPoints(&boneTable[i], &invmat.pos, 1, &x[parent]); + if(HIERNODEINFO(hier)[i].flags & rpHANIMPUSHPARENTMATRIX) + stack[++sp] = parent; + if(HIERNODEINFO(hier)[i].flags & rpHANIMPOPPARENTMATRIX) + parent = stack[sp--]; + else + parent = i; + assert(parent >= 0 && parent < numBones); + } +} + +RpHAnimAnimation* +HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier) +{ + int i; +#ifdef FIX_BUGS + int numNodes = hier->numNodes*2; // you're supposed to have at least two KFs per node +#else + int numNodes = hier->numNodes; +#endif + RpHAnimAnimation *anim = RpHAnimAnimationCreate(rpHANIMSTDKEYFRAMETYPEID, numNodes, 0, 0.0f); + if(anim == nil) + return nil; + RpHAnimStdKeyFrame *frame = (RpHAnimStdKeyFrame*)HANIMFRAMES(anim); + for(i = 0; i < numNodes; i++){ + frame->q.real = 1.0f; + frame->q.imag.x = frame->q.imag.y = frame->q.imag.z = 0.0f; + frame->t.x = frame->t.y = frame->t.z = 0.0f; + frame->time = 0.0f; + frame->prevFrame = nil; + frame++; + } + return anim; +} + +void +RenderSkeleton(RpHAnimHierarchy *hier) +{ + int i; + int sp; + int stack[32]; + int par; + CVector p1, p2; + int numNodes = hier->numNodes; + RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier); + p1 = mats[0].pos; + + par = 0; + sp = 0; + stack[sp++] = par; + for(i = 1; i < numNodes; i++){ + p1 = mats[par].pos; + p2 = mats[i].pos; + CDebug::AddLine(p1, p2, 0xFFFFFFFF, 0xFFFFFFFF); + if(HIERNODEINFO(hier)[i].flags & rpHANIMPUSHPARENTMATRIX) + stack[sp++] = par; + par = i; + if(HIERNODEINFO(hier)[i].flags & rpHANIMPOPPARENTMATRIX) + par = stack[--sp]; + } +} +#endif + void CameraSize(RwCamera * camera, RwRect * rect, RwReal viewWindow, RwReal aspectRatio) diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index 5b47cb6f..9f178ec2 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -13,6 +13,15 @@ RwObject *GetFirstObject(RwFrame *frame); RpAtomic *GetFirstAtomic(RpClump *clump); RwTexture *GetFirstTexture(RwTexDictionary *txd); +#ifdef PED_SKIN +RpAtomic *IsClumpSkinned(RpClump *clump); +RpHAnimHierarchy *GetAnimHierarchyFromSkinClump(RpClump *clump); // get from atomic +RpHAnimHierarchy *GetAnimHierarchyFromClump(RpClump *clump); // get from frame +RwFrame *GetHierarchyFromChildNodesCB(RwFrame *frame, void *data); +void SkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable); +RpHAnimAnimation *HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier); +#endif + RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream); RwTexDictionary *RwTexDictionaryGtaStreamRead1(RwStream *stream); RwTexDictionary *RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict); diff --git a/src/rw/VisibilityPlugins.cpp b/src/rw/VisibilityPlugins.cpp index 89bd13a6..7dc27f48 100644 --- a/src/rw/VisibilityPlugins.cpp +++ b/src/rw/VisibilityPlugins.cpp @@ -543,6 +543,21 @@ CVisibilityPlugins::RenderPedHiDetailCB(RpAtomic *atomic) return atomic; } +// This is needed for peds with only one clump, i.e. skinned models +// strangely even the xbox version has no such thing +RpAtomic* +CVisibilityPlugins::RenderPedCB(RpAtomic *atomic) +{ + int32 alpha; + + alpha = GetClumpAlpha(RpAtomicGetClump(atomic)); + if(alpha == 255) + AtomicDefaultRenderCallBack(atomic); + else + RenderAlphaAtomic(atomic, alpha); + return atomic; +} + float CVisibilityPlugins::GetDistanceSquaredFromCamera(RwFrame *frame) { diff --git a/src/rw/VisibilityPlugins.h b/src/rw/VisibilityPlugins.h index 63bc95e4..b367d7ee 100644 --- a/src/rw/VisibilityPlugins.h +++ b/src/rw/VisibilityPlugins.h @@ -63,6 +63,7 @@ public: static RpAtomic *RenderPlayerCB(RpAtomic *atomic); static RpAtomic *RenderPedLowDetailCB(RpAtomic *atomic); static RpAtomic *RenderPedHiDetailCB(RpAtomic *atomic); + static RpAtomic *RenderPedCB(RpAtomic *atomic); // for skinned models with only one clump static void RenderAlphaAtomics(void); static void RenderFadingEntities(void); @@ -131,3 +132,5 @@ public: static bool PluginAttach(void); }; + +RpMaterial *SetAlphaCB(RpMaterial *material, void *data); diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index d13d3c52..cde9f9e5 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1766,6 +1766,14 @@ WinMain(HINSTANCE instance, StaticPatcher::Apply(); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); +/* + // TODO: make this an option somewhere + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); +*/ + /* * Initialize the platform independent data. * This will in turn initialize the platform specific data... diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index b7ccb455..54e73a41 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -566,8 +566,7 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) target.y = 0.0f; target.z = 0.0f; - for (RwFrame *i = shooterPed->GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i)) - RwV3dTransformPoints(target, target, 1, RwFrameGetMatrix(i)); + shooterPed->TransformToNode(target, PED_HANDR); ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); } From 5bb4e9992679c9e8767d4eb6de54da1892ec13c6 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 24 Apr 2020 13:27:02 +0200 Subject: [PATCH 109/123] implemented debugmenu --- premake5.lua | 6 +- src/core/AnimViewer.cpp | 2 +- src/core/Game.cpp | 2 +- src/core/debugmenu_public.h | 154 ----- src/core/main.cpp | 5 +- src/core/re3.cpp | 40 +- src/extras/arrow.inc | 16 + src/extras/cursor.inc | 16 + src/extras/debugmenu.cpp | 1268 +++++++++++++++++++++++++++++++++++ src/extras/debugmenu.h | 80 +++ src/extras/inttypes.h | 216 ++++++ src/fakerw/fake.cpp | 4 +- src/rw/RwHelper.cpp | 11 +- src/rw/RwHelper.h | 1 + 14 files changed, 1621 insertions(+), 200 deletions(-) delete mode 100644 src/core/debugmenu_public.h create mode 100644 src/extras/arrow.inc create mode 100644 src/extras/cursor.inc create mode 100644 src/extras/debugmenu.cpp create mode 100644 src/extras/debugmenu.h create mode 100644 src/extras/inttypes.h diff --git a/premake5.lua b/premake5.lua index 14aab9d8..baf26a42 100644 --- a/premake5.lua +++ b/premake5.lua @@ -22,6 +22,7 @@ workspace "re3" files { "src/text/*.*" } files { "src/vehicles/*.*" } files { "src/weapons/*.*" } + files { "src/extras/*.*" } files { "eax/*.*" } includedirs { "src" } @@ -42,6 +43,7 @@ workspace "re3" includedirs { "src/text" } includedirs { "src/vehicles" } includedirs { "src/weapons" } + includedirs { "src/extras" } includedirs { "eax" } includedirs { "dxsdk/include" } @@ -73,7 +75,7 @@ workspace "re3" "set filename=%%~ni", "set fileextension=%%~xi", "set target=!path!!filename!!fileextension!", - "if exist \"!target!\" copy /y \"!file!\" \"!target!\"", + "copy /y \"!file!\" \"!target!\"", ")" } function setpaths (gamepath, exepath, scriptspath) @@ -106,7 +108,7 @@ project "re3" staticruntime "off" filter "configurations:not *RW" - prebuildcommands { "cd \"../librw\" && premake5 " .. _ACTION .. " && msbuild \"build/librw.sln\" /property:Configuration=%{cfg.longname} /property:Platform=\"win-x86-d3d9\"" } + -- prebuildcommands { "cd \"../librw\" && premake5 " .. _ACTION .. " && msbuild \"build/librw.sln\" /property:Configuration=%{cfg.longname} /property:Platform=\"win-x86-d3d9\"" } defines { "LIBRW", "RW_D3D9" } filter "configurations:*RW" diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp index cf3ec5bf..36ea20b7 100644 --- a/src/core/AnimViewer.cpp +++ b/src/core/AnimViewer.cpp @@ -37,6 +37,7 @@ #include "Shadows.h" #include "Radar.h" #include "Hud.h" +#include "debugmenu.h" int CAnimViewer::animTxdSlot = 0; CEntity *CAnimViewer::pTarget = nil; @@ -208,7 +209,6 @@ PlayAnimation(RpClump *clump, AssocGroupId animGroup, AnimationId anim) animAssoc->SetRun(); } -extern void (*DebugMenuProcess)(void); void CAnimViewer::Update(void) { diff --git a/src/core/Game.cpp b/src/core/Game.cpp index bfe6eee3..f72d342f 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -84,6 +84,7 @@ #include "World.h" #include "ZoneCull.h" #include "Zones.h" +#include "debugmenu.h" @@ -618,7 +619,6 @@ void CGame::InitialiseWhenRestarting(void) DMAudio.ChangeMusicMode(MUSICMODE_GAME); } -extern void (*DebugMenuProcess)(void); void CGame::Process(void) { CPad::UpdatePads(); diff --git a/src/core/debugmenu_public.h b/src/core/debugmenu_public.h deleted file mode 100644 index 778e7afe..00000000 --- a/src/core/debugmenu_public.h +++ /dev/null @@ -1,154 +0,0 @@ - -extern "C" { - -typedef void (*TriggerFunc)(void); - -struct DebugMenuEntry; - -typedef DebugMenuEntry *(*DebugMenuAddInt8_TYPE)(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc, int8_t step, int8_t lowerBound, int8_t upperBound, const char **strings); -typedef DebugMenuEntry *(*DebugMenuAddInt16_TYPE)(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc, int16_t step, int16_t lowerBound, int16_t upperBound, const char **strings); -typedef DebugMenuEntry *(*DebugMenuAddInt32_TYPE)(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc, int32_t step, int32_t lowerBound, int32_t upperBound, const char **strings); -typedef DebugMenuEntry *(*DebugMenuAddInt64_TYPE)(const char *path, const char *name, int64_t *ptr, TriggerFunc triggerFunc, int64_t step, int64_t lowerBound, int64_t upperBound, const char **strings); -typedef DebugMenuEntry *(*DebugMenuAddUInt8_TYPE)(const char *path, const char *name, uint8_t *ptr, TriggerFunc triggerFunc, uint8_t step, uint8_t lowerBound, uint8_t upperBound, const char **strings); -typedef DebugMenuEntry *(*DebugMenuAddUInt16_TYPE)(const char *path, const char *name, uint16_t *ptr, TriggerFunc triggerFunc, uint16_t step, uint16_t lowerBound, uint16_t upperBound, const char **strings); -typedef DebugMenuEntry *(*DebugMenuAddUInt32_TYPE)(const char *path, const char *name, uint32_t *ptr, TriggerFunc triggerFunc, uint32_t step, uint32_t lowerBound, uint32_t upperBound, const char **strings); -typedef DebugMenuEntry *(*DebugMenuAddUInt64_TYPE)(const char *path, const char *name, uint64_t *ptr, TriggerFunc triggerFunc, uint64_t step, uint64_t lowerBound, uint64_t upperBound, const char **strings); -typedef DebugMenuEntry *(*DebugMenuAddFloat32_TYPE)(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound); -typedef DebugMenuEntry *(*DebugMenuAddFloat64_TYPE)(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound); -typedef DebugMenuEntry *(*DebugMenuAddCmd_TYPE)(const char *path, const char *name, TriggerFunc triggerFunc); -typedef void (*DebugMenuEntrySetWrap_TYPE)(DebugMenuEntry *e, bool wrap); -typedef void (*DebugMenuEntrySetStrings_TYPE)(DebugMenuEntry *e, const char **strings); -typedef void (*DebugMenuEntrySetAddress_TYPE)(DebugMenuEntry *e, void *addr); - -struct DebugMenuAPI -{ - bool isLoaded; - HMODULE module; - DebugMenuAddInt8_TYPE addint8; - DebugMenuAddInt16_TYPE addint16; - DebugMenuAddInt32_TYPE addint32; - DebugMenuAddInt64_TYPE addint64; - DebugMenuAddUInt8_TYPE adduint8; - DebugMenuAddUInt16_TYPE adduint16; - DebugMenuAddUInt32_TYPE adduint32; - DebugMenuAddUInt64_TYPE adduint64; - DebugMenuAddFloat32_TYPE addfloat32; - DebugMenuAddFloat64_TYPE addfloat64; - DebugMenuAddCmd_TYPE addcmd; - DebugMenuEntrySetWrap_TYPE setwrap; - DebugMenuEntrySetStrings_TYPE setstrings; - DebugMenuEntrySetAddress_TYPE setaddress; -}; -extern DebugMenuAPI gDebugMenuAPI; - -inline DebugMenuEntry *DebugMenuAddInt8(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc, int8_t step, int8_t lowerBound, int8_t upperBound, const char **strings) -{ return gDebugMenuAPI.addint8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddInt16(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc, int16_t step, int16_t lowerBound, int16_t upperBound, const char **strings) -{ return gDebugMenuAPI.addint16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddInt32(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc, int32_t step, int32_t lowerBound, int32_t upperBound, const char **strings) -{ return gDebugMenuAPI.addint32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddInt64(const char *path, const char *name, int64_t *ptr, TriggerFunc triggerFunc, int64_t step, int64_t lowerBound, int64_t upperBound, const char **strings) -{ return gDebugMenuAPI.addint64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddUInt8(const char *path, const char *name, uint8_t *ptr, TriggerFunc triggerFunc, uint8_t step, uint8_t lowerBound, uint8_t upperBound, const char **strings) -{ return gDebugMenuAPI.adduint8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddUInt16(const char *path, const char *name, uint16_t *ptr, TriggerFunc triggerFunc, uint16_t step, uint16_t lowerBound, uint16_t upperBound, const char **strings) -{ return gDebugMenuAPI.adduint16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddUInt32(const char *path, const char *name, uint32_t *ptr, TriggerFunc triggerFunc, uint32_t step, uint32_t lowerBound, uint32_t upperBound, const char **strings) -{ return gDebugMenuAPI.adduint32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddUInt64(const char *path, const char *name, uint64_t *ptr, TriggerFunc triggerFunc, uint64_t step, uint64_t lowerBound, uint64_t upperBound, const char **strings) -{ return gDebugMenuAPI.adduint64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddFloat32(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound) -{ return gDebugMenuAPI.addfloat32(path, name, ptr, triggerFunc, step, lowerBound, upperBound); } -inline DebugMenuEntry *DebugMenuAddFloat64(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound) -{ return gDebugMenuAPI.addfloat64(path, name, ptr, triggerFunc, step, lowerBound, upperBound); } -inline DebugMenuEntry *DebugMenuAddCmd(const char *path, const char *name, TriggerFunc triggerFunc) -{ return gDebugMenuAPI.addcmd(path, name, triggerFunc); } -inline void DebugMenuEntrySetWrap(DebugMenuEntry *e, bool wrap) -{ gDebugMenuAPI.setwrap(e, wrap); } -inline void DebugMenuEntrySetStrings(DebugMenuEntry *e, const char **strings) -{ gDebugMenuAPI.setstrings(e, strings); } -inline void DebugMenuEntrySetAddress(DebugMenuEntry *e, void *addr) -{ gDebugMenuAPI.setaddress(e, addr); } - -inline bool DebugMenuLoad(void) -{ - if(gDebugMenuAPI.isLoaded) - return true; - HMODULE mod = LoadLibraryA("debugmenu"); - if(mod == nil){ - char modulePath[MAX_PATH]; - HMODULE dllModule; - GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)&gDebugMenuAPI, &dllModule); - GetModuleFileNameA(dllModule, modulePath, MAX_PATH); - char *p = strchr(modulePath, '\\'); - if(p) p[1] = '\0'; - strcat(modulePath, "debugmenu"); - mod = LoadLibraryA(modulePath); - } - if(mod == nil) - return false; - gDebugMenuAPI.addint8 = (DebugMenuAddInt8_TYPE)GetProcAddress(mod, "DebugMenuAddInt8"); - gDebugMenuAPI.addint16 = (DebugMenuAddInt16_TYPE)GetProcAddress(mod, "DebugMenuAddInt16"); - gDebugMenuAPI.addint32 = (DebugMenuAddInt32_TYPE)GetProcAddress(mod, "DebugMenuAddInt32"); - gDebugMenuAPI.addint64 = (DebugMenuAddInt64_TYPE)GetProcAddress(mod, "DebugMenuAddInt64"); - gDebugMenuAPI.adduint8 = (DebugMenuAddUInt8_TYPE)GetProcAddress(mod, "DebugMenuAddUInt8"); - gDebugMenuAPI.adduint16 = (DebugMenuAddUInt16_TYPE)GetProcAddress(mod, "DebugMenuAddUInt16"); - gDebugMenuAPI.adduint32 = (DebugMenuAddUInt32_TYPE)GetProcAddress(mod, "DebugMenuAddUInt32"); - gDebugMenuAPI.adduint64 = (DebugMenuAddUInt64_TYPE)GetProcAddress(mod, "DebugMenuAddUInt64"); - gDebugMenuAPI.addfloat32 = (DebugMenuAddFloat32_TYPE)GetProcAddress(mod, "DebugMenuAddFloat32"); - gDebugMenuAPI.addfloat64 = (DebugMenuAddFloat64_TYPE)GetProcAddress(mod, "DebugMenuAddFloat64"); - gDebugMenuAPI.addcmd = (DebugMenuAddCmd_TYPE)GetProcAddress(mod, "DebugMenuAddCmd"); - gDebugMenuAPI.setwrap = (DebugMenuEntrySetWrap_TYPE)GetProcAddress(mod, "DebugMenuEntrySetWrap"); - gDebugMenuAPI.setstrings = (DebugMenuEntrySetStrings_TYPE)GetProcAddress(mod, "DebugMenuEntrySetStrings"); - gDebugMenuAPI.setaddress = (DebugMenuEntrySetAddress_TYPE)GetProcAddress(mod, "DebugMenuEntrySetAddress"); - gDebugMenuAPI.isLoaded = true; - gDebugMenuAPI.module = mod; - return true; -} - -} - -// Also overload them for simplicity - -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc, int8_t step, int8_t lowerBound, int8_t upperBound, const char **strings) -{ return gDebugMenuAPI.addint8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc, int16_t step, int16_t lowerBound, int16_t upperBound, const char **strings) -{ return gDebugMenuAPI.addint16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc, int32_t step, int32_t lowerBound, int32_t upperBound, const char **strings) -{ return gDebugMenuAPI.addint32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int64_t *ptr, TriggerFunc triggerFunc, int64_t step, int64_t lowerBound, int64_t upperBound, const char **strings) -{ return gDebugMenuAPI.addint64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint8_t *ptr, TriggerFunc triggerFunc, uint8_t step, uint8_t lowerBound, uint8_t upperBound, const char **strings) -{ return gDebugMenuAPI.adduint8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint16_t *ptr, TriggerFunc triggerFunc, uint16_t step, uint16_t lowerBound, uint16_t upperBound, const char **strings) -{ return gDebugMenuAPI.adduint16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint32_t *ptr, TriggerFunc triggerFunc, uint32_t step, uint32_t lowerBound, uint32_t upperBound, const char **strings) -{ return gDebugMenuAPI.adduint32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint64_t *ptr, TriggerFunc triggerFunc, uint64_t step, uint64_t lowerBound, uint64_t upperBound, const char **strings) -{ return gDebugMenuAPI.adduint64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound) -{ return gDebugMenuAPI.addfloat32(path, name, ptr, triggerFunc, step, lowerBound, upperBound); } -inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound) -{ return gDebugMenuAPI.addfloat64(path, name, ptr, triggerFunc, step, lowerBound, upperBound); } - -inline DebugMenuEntry *DebugMenuAddVarBool32(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc) -{ - static const char *boolstr[] = { "Off", "On" }; - DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr); - DebugMenuEntrySetWrap(e, true); - return e; -} -inline DebugMenuEntry *DebugMenuAddVarBool16(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc) -{ - static const char *boolstr[] = { "Off", "On" }; - DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr); - DebugMenuEntrySetWrap(e, true); - return e; -} -inline DebugMenuEntry *DebugMenuAddVarBool8(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc) -{ - static const char *boolstr[] = { "Off", "On" }; - DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr); - DebugMenuEntrySetWrap(e, true); - return e; -} diff --git a/src/core/main.cpp b/src/core/main.cpp index 7013b10f..7c1f7938 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -59,6 +59,7 @@ #include "timebars.h" #include "GenericGameStorage.h" #include "SceneEdit.h" +#include "debugmenu.h" GlobalScene Scene; @@ -90,9 +91,7 @@ void GameInit(void); void SystemInit(void); void TheGame(void); -extern void (*DebugMenuProcess)(void); -extern void (*DebugMenuRender)(void); -void DebugMenuInit(void); +void DebugMenuInit(void) {} void DebugMenuPopulate(void); diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 4cec5773..d4d2c208 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -17,7 +17,6 @@ #include "Heli.h" #include "Automobile.h" #include "Ped.h" -#include "debugmenu_public.h" #include "Particle.h" #include "Console.h" #include "Debug.h" @@ -26,6 +25,7 @@ #include "Pad.h" #include "PlayerPed.h" #include "Radar.h" +#include "debugmenu.h" #include @@ -33,8 +33,6 @@ extern "C" int vsprintf(char* const _Buffer, char const* const _Format, va_list _ArgList); #endif -DebugMenuAPI gDebugMenuAPI; - #ifdef USE_PS2_RAND unsigned __int64 myrand_seed = 1; @@ -62,24 +60,6 @@ mysrand(unsigned int seed) myrand_seed = seed; } -void (*DebugMenuProcess)(void); -void (*DebugMenuRender)(void); -static void stub(void) { } - -void -DebugMenuInit(void) -{ - if(DebugMenuLoad()){ - DebugMenuProcess = (void(*)(void))GetProcAddress(gDebugMenuAPI.module, "DebugMenuProcess"); - DebugMenuRender = (void(*)(void))GetProcAddress(gDebugMenuAPI.module, "DebugMenuRender"); - } - if(DebugMenuProcess == nil || DebugMenuRender == nil){ - DebugMenuProcess = stub; - DebugMenuRender = stub; - } - -} - void WeaponCheat(); void HealthCheat(); void TankCheat(); @@ -269,7 +249,7 @@ TWEAKSWITCH(CWeather::NewWeatherType, 0, 3, wt, NULL); void DebugMenuPopulate(void) { - if(DebugMenuLoad()){ + if(1){ static const char *weathers[] = { "Sunny", "Cloudy", "Rainy", "Foggy" }; @@ -284,7 +264,7 @@ DebugMenuPopulate(void) e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 3, weathers); DebugMenuEntrySetWrap(e, true); DebugMenuAddVar("Time & Weather", "Wind", (float*)&CWeather::Wind, nil, 0.1f, 0.0f, 1.0f); - DebugMenuAddVar("Time & Weather", "Time scale", (float*)0x8F2C20, nil, 0.1f, 0.0f, 10.0f); + DebugMenuAddVar("Time & Weather", "Time scale", (float*)&CTimer::GetTimeScale(), nil, 0.1f, 0.0f, 10.0f); DebugMenuAddCmd("Cheats", "Weapons", WeaponCheat); DebugMenuAddCmd("Cheats", "Money", MoneyCheat); @@ -357,7 +337,7 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Catalina Fly By", CHeli::StartCatalinaFlyBy); DebugMenuAddCmd("Debug", "Catalina Take Off", CHeli::CatalinaTakeOff); DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway); - DebugMenuAddVarBool8("Debug", "Script Heli On", (int8*)0x95CD43, nil); + DebugMenuAddVarBool8("Debug", "Script Heli On", (int8*)&CHeli::ScriptHeliOn, nil); DebugMenuAddVarBool8("Debug", "Show Ped Paths", (int8*)&gbShowPedPaths, nil); DebugMenuAddVarBool8("Debug", "Show Car Paths", (int8*)&gbShowCarPaths, nil); @@ -397,18 +377,6 @@ DebugMenuPopulate(void) } } -/* -int (*RsEventHandler_orig)(int a, int b); -int -delayedPatches10(int a, int b) -{ - DebugMenuInit(); - DebugMenuPopulate(); - - return RsEventHandler_orig(a, b); -} -*/ - const int re3_buffsize = 1024; static char re3_buff[re3_buffsize]; diff --git a/src/extras/arrow.inc b/src/extras/arrow.inc new file mode 100644 index 00000000..8ea78283 --- /dev/null +++ b/src/extras/arrow.inc @@ -0,0 +1,16 @@ +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/extras/cursor.inc b/src/extras/cursor.inc new file mode 100644 index 00000000..e8afd394 --- /dev/null +++ b/src/extras/cursor.inc @@ -0,0 +1,16 @@ +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 255, 255, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 255, 255, 255, 255, 0, 0, 0, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, +255, 255, 255, 255, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 255, 255, 255, 255, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, 119, 119, 119, 0, diff --git a/src/extras/debugmenu.cpp b/src/extras/debugmenu.cpp new file mode 100644 index 00000000..d6ee18ab --- /dev/null +++ b/src/extras/debugmenu.cpp @@ -0,0 +1,1268 @@ +#include "common.h" +#include "RwHelper.h" +#include "Pad.h" +#include "ControllerConfig.h" +#include "Timer.h" +#include "rtcharse.h" +#include "inttypes.h" +#include "debugmenu.h" + +#define snprintf _snprintf + +#define strdup _strdup + + + +// Font stuff +struct Pt +{ + int x, y; +}; + +enum MenuFontStyle +{ + MENUFONT_NORMAL, + MENUFONT_SEL_ACTIVE, + MENUFONT_SEL_INACTIVE, + MENUFONT_MOUSE +}; + +RtCharset *fontStyles[4]; +RtCharsetDesc fontDesc; +int fontscale = 1; // not supported right now + +Pt +fontGetStringSize(const char *s) +{ + Pt sz = { 0, 0 }; + int x; + char c; + sz.y = fontDesc.height*fontscale; // always assume one line; + x = 0; + while(c = *s++){ + if(c == '\n'){ + sz.y += fontDesc.height*fontscale; + if(x > sz.x) + sz.x = x; + x = 0; + }else + x += fontDesc.width*fontscale; + } + if(x > sz.x) + sz.x = x; + return sz; +} + +Pt +fontPrint(const char *s, float x, float y, int style) +{ + RtCharsetPrintBuffered(fontStyles[style], s, x, y, false); + return fontGetStringSize(s); +} + +int +fontGetLen(int len) +{ + return len*fontDesc.width*fontscale; +} + + +void +createMenuFont(void) +{ + OpenCharsetSafe(); + + RwRGBA fg_normal = { 255, 255, 255, 255 }; + RwRGBA bg_normal = { 255, 255, 255, 0 }; + fontStyles[MENUFONT_NORMAL] = RtCharsetCreate(&fg_normal, &bg_normal); + assert(fontStyles[MENUFONT_NORMAL]); + + RwRGBA fg_sel_active = { 200, 200, 200, 255 }; + RwRGBA bg_sel_active = { 132, 132, 132, 255 }; + fontStyles[MENUFONT_SEL_ACTIVE] = RtCharsetCreate(&fg_sel_active, &bg_sel_active); + assert(fontStyles[MENUFONT_SEL_ACTIVE]); + + RwRGBA fg_sel_inactive = { 200, 200, 200, 255 }; + RwRGBA bg_sel_inactive = { 200, 200, 200, 0 }; + fontStyles[MENUFONT_SEL_INACTIVE] = RtCharsetCreate(&fg_sel_inactive, &bg_sel_inactive); + assert(fontStyles[MENUFONT_SEL_INACTIVE]); + + RwRGBA fg_mouse = { 255, 255, 255, 255 }; + RwRGBA bg_mouse = { 132, 132, 132, 255 }; + fontStyles[MENUFONT_MOUSE] = RtCharsetCreate(&fg_mouse, &bg_mouse); + assert(fontStyles[MENUFONT_MOUSE]); + + RtCharsetGetDesc(fontStyles[MENUFONT_NORMAL], &fontDesc); +} + + + + + + + +enum EntryType +{ + MENUEMPTY = 0, + MENUSUB, + MENUVAR, + + MENUVAR_INT, + MENUVAR_FLOAT, + MENUVAR_CMD, + + MENUSCROLL // dummy +}; + +struct Menu +{ + Menu *parent; + RwRect r; + MenuEntry *entries; + int numEntries; + int maxNameWidth, maxValWidth; + + MenuEntry *findEntry(const char *entryname); + void insertEntrySorted(MenuEntry *entry); + void appendEntry(MenuEntry *entry); + + bool isScrollingUp, isScrollingDown; + int scrollStart; + int numVisible; + RwRect scrollUpR, scrollDownR; + void scroll(int off); + + int selection; + MenuEntry *selectedEntry; // updated by update + void changeSelection(int newsel); + void changeSelection(MenuEntry *e); + + void update(void); + void draw(void); + Menu(void){ memset(this, 0, sizeof(Menu)); } +}; +extern Menu toplevel; + +struct MenuEntry_Sub : MenuEntry +{ + Menu *submenu; + + MenuEntry_Sub(const char *name, Menu *menu); +}; + +struct MenuEntry_Var : MenuEntry +{ + int maxvallen; + int vartype; + bool wrapAround; + + virtual void processInput(bool mouseOver, bool selected) = 0; + int getValWidth(void) { return maxvallen; } + virtual void getValStr(char *str, int len) = 0; + MenuEntry_Var(const char *name, int type); +}; + +struct MenuEntry_Int : MenuEntry_Var +{ + virtual void setStrings(const char **strings) = 0; + virtual int findStringLen(void) = 0; + MenuEntry_Int(const char *name); +}; + +#define INTTYPES \ + X(Int8, int8, 4, "%4" PRId8) \ + X(Int16, int16, 6, "%6" PRId16) \ + X(Int32, int32, 11, "%11" PRId32) \ + X(Int64, int64, 21, "%21" PRId64) \ + X(UInt8, uint8, 4, "%4" PRIu8) \ + X(UInt16, uint16, 6, "%6" PRIu16) \ + X(UInt32, uint32, 11, "%11" PRIu32) \ + X(UInt64, uint64, 21, "%21" PRIu64) +#define FLOATTYPES \ + X(Float32, float, 11, "%11.3f") \ + X(Float64, double, 11, "%11.3lf") + +#define X(NAME, TYPE, MAXLEN, FMT) \ +struct MenuEntry_##NAME : MenuEntry_Int \ +{ \ + TYPE *variable; \ + TYPE lowerBound, upperBound; \ + TYPE step; \ + TriggerFunc triggerFunc; \ + const char *fmt; \ + const char **strings; \ + \ + void processInput(bool mouseOver, bool selected); \ + void getValStr(char *str, int len); \ + \ + void setStrings(const char **strings); \ + int findStringLen(void); \ + MenuEntry_##NAME(const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound, const char **strings); \ +}; +INTTYPES +#undef X + +#define X(NAME, TYPE, MAXLEN, FMT) \ +struct MenuEntry_##NAME : MenuEntry_Var \ +{ \ + TYPE *variable; \ + TYPE lowerBound, upperBound; \ + TYPE step; \ + TriggerFunc triggerFunc; \ + const char *fmt; \ + \ + void processInput(bool mouseOver, bool selected); \ + void getValStr(char *str, int len); \ + \ + MenuEntry_##NAME(const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound); \ +}; +FLOATTYPES +#undef X + +struct MenuEntry_Cmd : MenuEntry_Var +{ + TriggerFunc triggerFunc; + + void processInput(bool mouseOver, bool selected); + void getValStr(char *str, int len); + + MenuEntry_Cmd(const char *name, TriggerFunc triggerFunc); +}; + + +Menu *findMenu(const char *name); + + + +#define MUHKEYS \ + X(leftjustdown, rsLEFT) \ + X(rightjustdown, rsRIGHT) \ + X(upjustdown, rsUP) \ + X(downjustdown, rsDOWN) \ + X(pgupjustdown, rsPGUP) \ + X(pgdnjustdown, rsPGDN) + +#define MUHBUTTONS \ + X(button1justdown, 1) \ + X(button2justdown, 2) \ + X(button3justdown, 3) + +#define REPEATDELAY 700 +#define REPEATINTERVAL 50 +#define X(var, keycode) static int var; +MUHKEYS +#undef X +static int downtime; +static int repeattime; +static int lastkeydown; +static int *keyptr; + +static int buttondown[3]; +static int lastbuttondown; +static int *buttonptr; +static int button1justdown, button2justdown, button3justdown; +static float mouseX, mouseY; + +static int menuOn; +static int menuInitialized; +static int screenWidth, screenHeight; +static RwRaster *cursor, *arrow; + +static int firstBorder = 10; +static int topBorder = 40; //10; +static int leading = 4; +static int gap = 10; +static int minwidth = 100; + +void drawMouse(void); +void drawArrow(RwRect r, int direction, int style); + +Menu toplevel; +Menu *activeMenu = &toplevel; +Menu *deepestMenu = &toplevel; +Menu *mouseOverMenu; +MenuEntry *mouseOverEntry; +MenuEntry scrollUpEntry("SCROLLUP"), scrollDownEntry("SCROLLDOWN"); // dummies + + +#define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k) +#define KEYDOWN(k) ControlsManager.GetIsKeyboardKeyDown((RsKeyCodes)k) +#define CTRLJUSTDOWN(key) \ + ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYJUSTDOWN((RsKeyCodes)key) || \ + (KEYJUSTDOWN(rsLCTRL) || KEYJUSTDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key)) +#define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key)) + + +bool +isMouseInRect(RwRect r) +{ + return (mouseX >= r.x && mouseX < r.x+r.w && + mouseY >= r.y && mouseY < r.y+r.h); +} + +/* + * MenuEntry + */ + +MenuEntry::MenuEntry(const char *name) +{ + this->type = MENUEMPTY; + this->name = strdup(name); + this->next = nil; + this->menu = nil; +} + +MenuEntry_Sub::MenuEntry_Sub(const char *name, Menu *menu) +: MenuEntry(name) +{ + this->type = MENUSUB; + this->submenu = menu; +} + +MenuEntry_Var::MenuEntry_Var(const char *name, int vartype) +: MenuEntry(name) +{ + this->type = MENUVAR; + this->vartype = vartype; + this->maxvallen = 0; + this->wrapAround = false; +} + +/* + * ***************************** + * MenuEntry_Int + * ***************************** + */ + +MenuEntry_Int::MenuEntry_Int(const char *name) +: MenuEntry_Var(name, MENUVAR_INT) +{ +} + +#define X(NAME, TYPE, MAXLEN, FMT) \ +int \ +MenuEntry_##NAME::findStringLen(void){ \ + TYPE i; \ + int len, maxlen = 0; \ + for(i = this->lowerBound; i <= this->upperBound; i++){ \ + len = strlen(this->strings[i-this->lowerBound]); \ + if(len > maxlen) \ + maxlen = len; \ + } \ + return maxlen; \ +} \ +void \ +MenuEntry_##NAME::processInput(bool mouseOver, bool selected) \ +{ \ + TYPE v, oldv; \ + int overflow = 0; \ + int underflow = 0; \ + \ + v = *this->variable; \ + oldv = v; \ + \ + if((selected && leftjustdown) || (mouseOver && button3justdown)){ \ + v -= this->step; \ + if(v > oldv) \ + underflow = 1; \ + } \ + if((selected && rightjustdown) || (mouseOver && button1justdown)){ \ + v += this->step; \ + if(v < oldv) \ + overflow = 1; \ + } \ + if(this->wrapAround){ \ + if(v > this->upperBound || overflow) v = this->lowerBound; \ + if(v < this->lowerBound || underflow) v = this->upperBound; \ + }else{ \ + if(v > this->upperBound || overflow) v = this->upperBound; \ + if(v < this->lowerBound || underflow) v = this->lowerBound; \ + } \ + \ + *this->variable = v; \ + if(oldv != v && this->triggerFunc) \ + this->triggerFunc(); \ +} \ +void \ +MenuEntry_##NAME::getValStr(char *str, int len) \ +{ \ + static char tmp[20]; \ + if(this->strings){ \ + snprintf(tmp, 20, "%%%ds", this->maxvallen); \ + if(*this->variable < this->lowerBound || *this->variable > this->upperBound){ \ + snprintf(str, len, "ERROR"); \ + return; \ + } \ + snprintf(str, len, tmp, this->strings[*this->variable-this->lowerBound]); \ + }else \ + snprintf(str, len, this->fmt, *this->variable); \ +} \ +void \ +MenuEntry_##NAME::setStrings(const char **strings) \ +{ \ + this->strings = strings; \ + if(this->strings) \ + this->maxvallen = findStringLen(); \ +} \ +MenuEntry_##NAME::MenuEntry_##NAME(const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound, const char **strings) \ +: MenuEntry_Int(name) \ +{ \ + this->variable = ptr; \ + this->step = step; \ + this->lowerBound = lowerBound; \ + this->upperBound = upperBound; \ + this->triggerFunc = triggerFunc; \ + this->maxvallen = MAXLEN; \ + this->fmt = FMT; \ + this->setStrings(strings); \ +} +INTTYPES +#undef X + +/* + * ***************************** + * MenuEntry_Float + * ***************************** + */ + +#define X(NAME, TYPE, MAXLEN, FMT) \ +MenuEntry_##NAME::MenuEntry_##NAME(const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound) \ +: MenuEntry_Var(name, MENUVAR_FLOAT) \ +{ \ + this->variable = ptr; \ + this->step = step; \ + this->lowerBound = lowerBound; \ + this->upperBound = upperBound; \ + this->triggerFunc = triggerFunc; \ + this->maxvallen = MAXLEN; \ + this->fmt = FMT; \ +} \ +void \ +MenuEntry_##NAME::getValStr(char *str, int len) \ +{ \ + snprintf(str, len, this->fmt, *this->variable); \ +} \ +void \ +MenuEntry_##NAME::processInput(bool mouseOver, bool selected) \ +{ \ + float v, oldv; \ + int overflow = 0; \ + int underflow = 0; \ + \ + v = *this->variable; \ + oldv = v; \ + \ + if((selected && leftjustdown) || (mouseOver && button3justdown)){ \ + v -= this->step; \ + if(v > oldv) \ + underflow = 1; \ + } \ + if((selected && rightjustdown) || (mouseOver && button1justdown)){ \ + v += this->step; \ + if(v < oldv) \ + overflow = 1; \ + } \ + if(this->wrapAround){ \ + if(v > this->upperBound || overflow) v = this->lowerBound; \ + if(v < this->lowerBound || underflow) v = this->upperBound; \ + }else{ \ + if(v > this->upperBound || overflow) v = this->upperBound; \ + if(v < this->lowerBound || underflow) v = this->lowerBound; \ + } \ + \ + *this->variable = v; \ + if(oldv != v && this->triggerFunc) \ + this->triggerFunc(); \ +} + +FLOATTYPES +#undef X + +/* + * ***************************** + * MenuEntry_Cmd + * ***************************** + */ + +void +MenuEntry_Cmd::processInput(bool mouseOver, bool selected) +{ + // Don't execute on button3 + if(this->triggerFunc && (selected && (leftjustdown || rightjustdown) || (mouseOver && button1justdown))) + this->triggerFunc(); +} + +void +MenuEntry_Cmd::getValStr(char *str, int len) +{ + strncpy(str, "<", len); +} + +MenuEntry_Cmd::MenuEntry_Cmd(const char *name, TriggerFunc triggerFunc) +: MenuEntry_Var(name, MENUVAR_CMD) +{ + this->maxvallen = 1; + this->triggerFunc = triggerFunc; +} + + +/* + * ***************************** + * Menu + * ***************************** + */ + +void +Menu::scroll(int off) { + if(isScrollingUp && off < 0) + scrollStart += off; + if(isScrollingDown && off > 0) + scrollStart += off; + if(scrollStart < 0) scrollStart = 0; + if(scrollStart > numEntries-numVisible) scrollStart = numEntries-numVisible; +} + +void +Menu::changeSelection(int newsel){ + selection = newsel; + if(selection < 0) selection = 0; + if(selection >= numEntries) selection = numEntries-1; + if(selection < scrollStart) scrollStart = selection; + if(selection >= scrollStart+numVisible) scrollStart = selection-numVisible+1; +} + +void +Menu::changeSelection(MenuEntry *sel) +{ + MenuEntry *e; + int i = 0; + for(e = this->entries; e; e = e->next){ + if(e == sel){ + this->selection = i; + this->selectedEntry = sel; + break; + } + i++; + } +} + + + +MenuEntry* +Menu::findEntry(const char *entryname) +{ + MenuEntry *m; + for(m = this->entries; m; m = m->next) + if(strcmp(entryname, m->name) == 0) + return m; + return nil; +} + +void +Menu::insertEntrySorted(MenuEntry *entry) +{ + MenuEntry **mp; + int cmp; + for(mp = &this->entries; *mp; mp = &(*mp)->next){ + cmp = strcmp(entry->name, (*mp)->name); + if(cmp == 0) + return; + if(cmp < 0) + break; + } + entry->next = *mp; + *mp = entry; + entry->menu = this; + this->numEntries++; +} + +void +Menu::appendEntry(MenuEntry *entry) +{ + MenuEntry **mp; + for(mp = &this->entries; *mp; mp = &(*mp)->next); + entry->next = *mp; + *mp = entry; + entry->menu = this; + this->numEntries++; +} + +void +Menu::update(void) +{ + int i; + int x, y; + Pt sz; + MenuEntry *e; + int onscreen; + x = this->r.x; + y = this->r.y + 18; + int end = this->r.y+this->r.h - 18; + this->numVisible = 0; + + deepestMenu = this; + + int bottomy = end; + onscreen = 1; + i = 0; + this->maxNameWidth = 0; + this->maxValWidth = 0; + this->isScrollingUp = this->scrollStart > 0; + this->isScrollingDown = false; + this->selectedEntry = nil; + for(e = this->entries; e; e = e->next){ + sz = fontGetStringSize(e->name); + e->r.x = x; + e->r.y = y; + e->r.w = sz.x; + e->r.h = sz.y; + + if(i == this->selection) + this->selectedEntry = e; + + if(i >= this->scrollStart) + y += sz.y + leading*fontscale; + if(y >= end){ + this->isScrollingDown = true; + onscreen = 0; + }else + bottomy = y; + if(i >= this->scrollStart && onscreen) + this->numVisible++; + + if(e->type == MENUVAR){ + int valwidth = fontGetLen(((MenuEntry_Var*)e)->getValWidth()); + if(valwidth > maxValWidth) + maxValWidth = valwidth; + } + if(e->r.w > maxNameWidth) + maxNameWidth = e->r.w; + i++; + } + if(this->r.w < maxNameWidth + maxValWidth + gap*fontscale) + this->r.w = maxNameWidth + maxValWidth + gap*fontscale; + + this->scrollUpR = this->r; + this->scrollUpR.h = 16; + this->scrollDownR = this->scrollUpR; + this->scrollDownR.y = bottomy; + + // Update active submenu + if(this->selectedEntry && this->selectedEntry->type == MENUSUB){ + Menu *submenu = ((MenuEntry_Sub*)this->selectedEntry)->submenu; + submenu->r.x = this->r.x+this->r.w + 10; + submenu->r.y = this->r.y; + submenu->r.w = minwidth; // update menu will expand + submenu->r.h = this->r.h; + submenu->update(); + } +} + +void +Menu::draw(void) +{ + static char val[100]; + int i; + MenuEntry *e; + i = 0; + for(e = this->entries; e; e = e->next){ + if(i >= this->scrollStart+this->numVisible) + break; + if(i >= this->scrollStart){ + int style = MENUFONT_NORMAL; + if(i == this->selection) + style = this == activeMenu ? MENUFONT_SEL_ACTIVE : MENUFONT_SEL_INACTIVE; + if(style != MENUFONT_SEL_ACTIVE && e == mouseOverEntry) + style = MENUFONT_MOUSE; + fontPrint(e->name, e->r.x, e->r.y, style); + if(e->type == MENUVAR){ + int valw = fontGetLen(((MenuEntry_Var*)e)->getValWidth()); + ((MenuEntry_Var*)e)->getValStr(val, 100); + fontPrint(val, e->r.x+this->r.w-valw, e->r.y, style); + } + } + i++; + } + + if(this->isScrollingUp) + drawArrow(this->scrollUpR, -1, isMouseInRect(this->scrollUpR)); + if(this->isScrollingDown) + drawArrow(this->scrollDownR, 1, isMouseInRect(this->scrollDownR)); + + if(this->selectedEntry && this->selectedEntry->type == MENUSUB) + ((MenuEntry_Sub*)this->selectedEntry)->submenu->draw(); +} + +Menu* +findMenu(const char *name) +{ + Menu *m; + MenuEntry *e; + char *tmppath = strdup(name); + char *next, *curname; + + curname = tmppath; + next = curname; + + m = &toplevel; + while(*next){ + curname = next; + while(*next){ + if(*next == '|'){ + *next++ = '\0'; + break; + } + next++; + } + e = m->findEntry(curname); + if(e){ + // return an error if the entry exists but isn't a menu + if(e->type != MENUSUB){ + free(tmppath); + return nil; + } + m = ((MenuEntry_Sub*)e)->submenu; + }else{ + // Create submenus that don't exist yet + Menu *submenu = new Menu(); + submenu->parent = m; + MenuEntry *me = new MenuEntry_Sub(curname, submenu); + // Don't sort submenus outside the toplevel menu + if(m == &toplevel) + m->insertEntrySorted(me); + else + m->appendEntry(me); + m = submenu; + } + } + + free(tmppath); + return m; +} + +/* + * **************** + * debug menu + * **************** + */ + +static uint8 cursorPx[] = { +#include "cursor.inc" +}; + +static uint8 arrowPx[] = { +#include "arrow.inc" +}; + +void +initDebug(void) +{ + createMenuFont(); + + RwInt32 w, h, d, flags; + RwImage *img = RwImageCreate(16, 16, 32); + assert(img); + RwImageSetPixels(img, cursorPx); + RwImageSetStride(img, RwImageGetWidth(img)*4); + RwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &w, &h, &d, &flags); + cursor = RwRasterCreate(w, h, d, flags); + cursor = RwRasterSetFromImage(cursor, img); + assert(cursor); + RwImageDestroy(img); + + img = RwImageCreate(32, 16, 32); + assert(img); + RwImageSetPixels(img, arrowPx); + RwImageSetStride(img, RwImageGetWidth(img)*4); + RwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &w, &h, &d, &flags); + arrow = RwRasterCreate(w, h, d, flags); + arrow = RwRasterSetFromImage(arrow, img); + assert(arrow); + RwImageDestroy(img); +} + +void +processInput(void) +{ + int shift = KEYDOWN(rsRSHIFT) || KEYDOWN(rsLSHIFT); +#define X(var, keycode) var = KEYJUSTDOWN(keycode); + MUHKEYS +#undef X + + // Implement auto-repeat +#define X(var, keycode) \ + if(var){ \ + repeattime = downtime = CTimer::GetTimeInMilliseconds(); \ + lastkeydown = keycode; \ + keyptr = &var; \ + } + MUHKEYS +#undef X + if(lastkeydown){ + if(KEYDOWN(lastkeydown)){ + int curtime = CTimer::GetTimeInMilliseconds(); + if(curtime - downtime > REPEATDELAY){ + if(curtime - repeattime > REPEATINTERVAL){ + repeattime = curtime; + *keyptr = 1; + } + } + }else{ + lastkeydown = 0; + } + } + + // Also for mouse buttons +#define X(var, num) \ + if(var){ \ + repeattime = downtime = CTimer::GetTimeInMilliseconds(); \ + lastbuttondown = num; \ + buttonptr = &var; \ + } + MUHBUTTONS +#undef X + if(lastbuttondown){ + if(buttondown[lastbuttondown-1]){ + int curtime = CTimer::GetTimeInMilliseconds(); + if(curtime - downtime > REPEATDELAY){ + if(curtime - repeattime > REPEATINTERVAL){ + repeattime = curtime; + *buttonptr = 1; + } + } + }else{ + lastbuttondown = 0; + } + } + + // Walk through all visible menus and figure out which one the mouse is over + mouseOverMenu = nil; + mouseOverEntry = nil; + Menu *menu; + for(menu = deepestMenu; menu; menu = menu->parent) + if(isMouseInRect(menu->r)){ + mouseOverMenu = menu; + break; + } + if(mouseOverMenu){ + // Walk all visibile entries and figure out which one the mouse is over + MenuEntry *e; + int i = 0; + for(e = mouseOverMenu->entries; e; e = e->next){ + if(i >= mouseOverMenu->scrollStart+mouseOverMenu->numVisible) + break; + if(i >= mouseOverMenu->scrollStart){ + RwRect r = e->r; + r.w = mouseOverMenu->r.w; // span the whole menu + if(isMouseInRect(r)){ + mouseOverEntry = e; + break; + } + } + i++; + } + if(mouseOverMenu->isScrollingUp && isMouseInRect(mouseOverMenu->scrollUpR)){ + mouseOverEntry = &scrollUpEntry; + mouseOverEntry->r = mouseOverMenu->scrollUpR; + mouseOverEntry->menu = mouseOverMenu; + mouseOverEntry->type = MENUSCROLL; + } + if(mouseOverMenu->isScrollingDown && isMouseInRect(mouseOverMenu->scrollDownR)){ + mouseOverEntry = &scrollDownEntry; + mouseOverEntry->r = mouseOverMenu->scrollDownR; + mouseOverEntry->menu = mouseOverMenu; + mouseOverEntry->type = MENUSCROLL; + } + } + + if(pgupjustdown) + activeMenu->scroll(shift ? -5 : -1); + if(pgdnjustdown) + activeMenu->scroll(shift ? 5 : 1); + if(downjustdown) + activeMenu->changeSelection(activeMenu->selection + (shift ? 5 : 1)); + if(upjustdown) + activeMenu->changeSelection(activeMenu->selection - (shift ? 5 : 1)); + + if(CPad::NewMouseControllerState.WHEELUP){ + if(mouseOverMenu) + activeMenu = mouseOverMenu; + activeMenu->scroll(shift ? -5 : -1); + } + if(CPad::NewMouseControllerState.WHEELDN){ + if(mouseOverMenu) + activeMenu = mouseOverMenu; + activeMenu->scroll(shift ? 5 : 1); + } + + if(mouseOverEntry == &scrollUpEntry){ + if(button1justdown){ + activeMenu = mouseOverEntry->menu; + activeMenu->scroll(shift ? -5 : -1); + } + } + if(mouseOverEntry == &scrollDownEntry){ + if(button1justdown){ + activeMenu = mouseOverEntry->menu; + activeMenu->scroll(shift ? 5 : 1); + } + } + + // Have to call this before processInput below because menu entry can change + if((button1justdown || button3justdown) && mouseOverEntry){ + activeMenu = mouseOverEntry->menu; + activeMenu->changeSelection(mouseOverEntry); + } + if(KEYJUSTDOWN(rsENTER)){ + if(activeMenu->selectedEntry && activeMenu->selectedEntry->type == MENUSUB) + activeMenu = ((MenuEntry_Sub*)activeMenu->selectedEntry)->submenu; + }else if(KEYJUSTDOWN(rsBACKSP)){ + if(activeMenu->parent) + activeMenu = activeMenu->parent; + }else{ + if(mouseOverEntry && mouseOverEntry->type == MENUVAR) + ((MenuEntry_Var*)mouseOverEntry)->processInput(true, mouseOverEntry == activeMenu->selectedEntry); + if(activeMenu->selectedEntry && activeMenu->selectedEntry->type == MENUVAR && + mouseOverEntry != activeMenu->selectedEntry) + ((MenuEntry_Var*)activeMenu->selectedEntry)->processInput(false, true); + } +} + +void +updateMouse(void) +{ + CPad *pad = CPad::GetPad(0); + int dirX = 1; + int dirY = 1; + + if(MousePointerStateHelper.bInvertHorizontally) dirX = -1; + if(MousePointerStateHelper.bInvertVertically) dirY = -1; + + mouseX += pad->NewMouseControllerState.x*dirX; + mouseY += pad->NewMouseControllerState.y*dirY; + + if(mouseX < 0.0f) mouseX = 0.0f; + if(mouseY < 0.0f) mouseY = 0.0f; + if(mouseX >= screenWidth) mouseX = screenWidth; + if(mouseY >= screenHeight) mouseY = screenHeight; + + button1justdown = pad->NewMouseControllerState.LMB && !pad->OldMouseControllerState.LMB; + button2justdown = pad->NewMouseControllerState.MMB && !pad->OldMouseControllerState.MMB; + button3justdown = pad->NewMouseControllerState.RMB && !pad->OldMouseControllerState.RMB; + buttondown[0] = pad->NewMouseControllerState.LMB; + buttondown[1] = pad->NewMouseControllerState.MMB; + buttondown[2] = pad->NewMouseControllerState.RMB; + + // Zero the mouse position so the camera won't move + pad->NewMouseControllerState.x = 0.0f; + pad->NewMouseControllerState.y = 0.0f; +} + +void +DebugMenuProcess(void) +{ + // We only process some input here + + CPad *pad = CPad::GetPad(0); + if(CTRLJUSTDOWN('M')) + menuOn = !menuOn; + if(!menuOn) + return; + + pad->DisablePlayerControls = 1; + // TODO: this could happen earlier + if(!menuInitialized){ + initDebug(); + menuInitialized = 1; + } + updateMouse(); + +} + +#ifdef LIBRW +#define CURRENTCAM (rw::engine->currentCamera) +#else +#define CURRENTCAM ((RwCamera*)RWSRCGLOBAL(curCamera)) +#endif + +void +DebugMenuRender(void) +{ + if(!menuOn) + return; + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, 0); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, 0); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, 0); + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); + + RwCamera *cam = CURRENTCAM; + screenWidth = RwRasterGetWidth(RwCameraGetRaster(cam)); + screenHeight = RwRasterGetHeight(RwCameraGetRaster(cam)); + +// if(screenHeight > 1080) +// fontscale = 2; +// else + fontscale = 1; + + Pt sz; + sz = fontPrint("Debug Menu", firstBorder*fontscale+30, topBorder, 0); + + toplevel.r.x = firstBorder*fontscale; + toplevel.r.y = topBorder + sz.y + 10; + toplevel.r.w = minwidth; // update menu will expand + toplevel.r.h = screenHeight - 10 - toplevel.r.y; + toplevel.update(); + toplevel.draw(); + processInput(); + RtCharsetBufferFlush(); + + drawMouse(); +} + + + +void +drawArrow(RwRect r, int direction, int style) +{ + static RwImVertexIndex indices[] = { 0, 1, 2, 2, 1, 3 }; + static RwIm2DVertex arrowVerts[4]; + + RwCamera *cam = CURRENTCAM; + float recipz = 1.0f/RwCameraGetNearClipPlane(cam); + + int width = RwRasterGetWidth(arrow); + int height = RwRasterGetHeight(arrow); + + int left = r.x + (r.w - width)/2; + int right = left + width; + int top = r.y; + int bottom = r.y+r.h; + + float umin = 0.5f / width; + float vmin = 0.5f / height; + float umax = (width + 0.5f) / width; + float vmax = (height + 0.5f) / height; + if(direction < 0){ + vmin = (height - 0.5f) / height; + vmax = -0.5f / height; + } + + if(style){ + RwIm2DVertexSetScreenX(&arrowVerts[0], r.x); + RwIm2DVertexSetScreenY(&arrowVerts[0], r.y-1); + RwIm2DVertexSetScreenZ(&arrowVerts[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&arrowVerts[0], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&arrowVerts[0], recipz); + RwIm2DVertexSetIntRGBA(&arrowVerts[0], 132, 132, 132, 255); + + RwIm2DVertexSetScreenX(&arrowVerts[1], r.x+r.w); + RwIm2DVertexSetScreenY(&arrowVerts[1], r.y-1); + RwIm2DVertexSetScreenZ(&arrowVerts[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&arrowVerts[1], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&arrowVerts[1], recipz); + RwIm2DVertexSetIntRGBA(&arrowVerts[1], 132, 132, 132, 255); + + RwIm2DVertexSetScreenX(&arrowVerts[2], r.x); + RwIm2DVertexSetScreenY(&arrowVerts[2], r.y+r.h+1); + RwIm2DVertexSetScreenZ(&arrowVerts[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&arrowVerts[2], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&arrowVerts[2], recipz); + RwIm2DVertexSetIntRGBA(&arrowVerts[2], 132, 132, 132, 255); + + RwIm2DVertexSetScreenX(&arrowVerts[3], r.x+r.w); + RwIm2DVertexSetScreenY(&arrowVerts[3], r.y+r.h+1); + RwIm2DVertexSetScreenZ(&arrowVerts[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&arrowVerts[3], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&arrowVerts[3], recipz); + RwIm2DVertexSetIntRGBA(&arrowVerts[3], 132, 132, 132, 255); + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, arrowVerts, 4, indices, 6); + } + + + RwIm2DVertexSetScreenX(&arrowVerts[0], left); + RwIm2DVertexSetScreenY(&arrowVerts[0], top); + RwIm2DVertexSetScreenZ(&arrowVerts[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&arrowVerts[0], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&arrowVerts[0], recipz); + RwIm2DVertexSetIntRGBA(&arrowVerts[0], 255, 255, 255, 255); + RwIm2DVertexSetU(&arrowVerts[0], umin, recipz); + RwIm2DVertexSetV(&arrowVerts[0], vmin, recipz); + + RwIm2DVertexSetScreenX(&arrowVerts[1], right); + RwIm2DVertexSetScreenY(&arrowVerts[1], top); + RwIm2DVertexSetScreenZ(&arrowVerts[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&arrowVerts[1], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&arrowVerts[1], recipz); + RwIm2DVertexSetIntRGBA(&arrowVerts[1], 255, 255, 255, 255); + RwIm2DVertexSetU(&arrowVerts[1], umax, recipz); + RwIm2DVertexSetV(&arrowVerts[1], vmin, recipz); + + RwIm2DVertexSetScreenX(&arrowVerts[2], left); + RwIm2DVertexSetScreenY(&arrowVerts[2], bottom); + RwIm2DVertexSetScreenZ(&arrowVerts[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&arrowVerts[2], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&arrowVerts[2], recipz); + RwIm2DVertexSetIntRGBA(&arrowVerts[2], 255, 255, 255, 255); + RwIm2DVertexSetU(&arrowVerts[2], umin, recipz); + RwIm2DVertexSetV(&arrowVerts[2], vmax, recipz); + + RwIm2DVertexSetScreenX(&arrowVerts[3], right); + RwIm2DVertexSetScreenY(&arrowVerts[3], bottom); + RwIm2DVertexSetScreenZ(&arrowVerts[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&arrowVerts[3], RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(&arrowVerts[3], recipz); + RwIm2DVertexSetIntRGBA(&arrowVerts[3], 255, 255, 255, 255); + RwIm2DVertexSetU(&arrowVerts[3], umax, recipz); + RwIm2DVertexSetV(&arrowVerts[3], vmax, recipz); + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, arrow); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, arrowVerts, 4, indices, 6); +} + +void +drawMouse(void) +{ + static RwImVertexIndex indices[] = { 0, 1, 2, 2, 1, 3 }; + static RwIm2DVertex vertices[4]; + RwIm2DVertex *vert; + RwCamera *cam; + cam = CURRENTCAM; + float x = mouseX; + float y = mouseY; + float w = RwRasterGetWidth(cursor); + float h = RwRasterGetHeight(cursor); + float recipz = 1.0f/RwCameraGetNearClipPlane(cam); + + float umin = 0.5f / w; + float vmin = 0.5f / h; + float umax = (w + 0.5f) / w; + float vmax = (h + 0.5f) / h; + + vert = vertices; + RwIm2DVertexSetScreenX(vert, x); + RwIm2DVertexSetScreenY(vert, y); + RwIm2DVertexSetScreenZ(vert, RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(vert, RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(vert, recipz); + RwIm2DVertexSetIntRGBA(vert, 255, 255, 255, 255); + RwIm2DVertexSetU(vert, umin, recipz); + RwIm2DVertexSetV(vert, vmin, recipz); + vert++; + + RwIm2DVertexSetScreenX(vert, x+w); + RwIm2DVertexSetScreenY(vert, y); + RwIm2DVertexSetScreenZ(vert, RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(vert, RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(vert, recipz); + RwIm2DVertexSetIntRGBA(vert, 255, 255, 255, 255); + RwIm2DVertexSetU(vert, umax, recipz); + RwIm2DVertexSetV(vert, vmin, recipz); + vert++; + + RwIm2DVertexSetScreenX(vert, x); + RwIm2DVertexSetScreenY(vert, y+h); + RwIm2DVertexSetScreenZ(vert, RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(vert, RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(vert, recipz); + RwIm2DVertexSetIntRGBA(vert, 255, 255, 255, 255); + RwIm2DVertexSetU(vert, umin, recipz); + RwIm2DVertexSetV(vert, vmax, recipz); + vert++; + + RwIm2DVertexSetScreenX(vert, x+w); + RwIm2DVertexSetScreenY(vert, y+h); + RwIm2DVertexSetScreenZ(vert, RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(vert, RwCameraGetNearClipPlane(cam)); + RwIm2DVertexSetRecipCameraZ(vert, recipz); + RwIm2DVertexSetIntRGBA(vert, 255, 255, 255, 255); + RwIm2DVertexSetU(vert, umax, recipz); + RwIm2DVertexSetV(vert, vmax, recipz); + vert++; + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, cursor); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, vertices, 4, indices, 6); +} + + + + +/* + * Generate interfaces + */ + + +#define X(NAME, TYPE, unused1, unused2) \ +MenuEntry* \ +DebugMenuAdd##NAME(const char *path, const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound, const char **strings) \ +{ \ + Menu *m = findMenu(path); \ + if(m == nil) \ + return nil; \ + MenuEntry *e = new MenuEntry_##NAME(name, ptr, triggerFunc, step, lowerBound, upperBound, strings); \ + m->appendEntry(e); \ + return e; \ +} +INTTYPES +#undef X + +#define X(NAME, TYPE, unused1, unused2) \ +MenuEntry* \ +DebugMenuAdd##NAME(const char *path, const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound) \ +{ \ + Menu *m = findMenu(path); \ + if(m == nil) \ + return nil; \ + MenuEntry *e = new MenuEntry_##NAME(name, ptr, triggerFunc, step, lowerBound, upperBound); \ + m->appendEntry(e); \ + return e; \ +} +FLOATTYPES +#undef X + +MenuEntry* \ +DebugMenuAddCmd(const char *path, const char *name, TriggerFunc triggerFunc) +{ + Menu *m = findMenu(path); + if(m == nil) + return nil; + MenuEntry *e = new MenuEntry_Cmd(name, triggerFunc); + m->appendEntry(e); + return e; +} + +void +DebugMenuEntrySetWrap(MenuEntry *e, bool wrap) +{ + if(e && e->type == MENUVAR) + ((MenuEntry_Var*)e)->wrapAround = wrap; +} + +void +DebugMenuEntrySetStrings(MenuEntry *e, const char **strings) +{ + if(e && e->type == MENUVAR_INT) + ((MenuEntry_Int*)e)->setStrings(strings); +} + +void +DebugMenuEntrySetAddress(MenuEntry *e, void *addr) +{ + if(e && e->type == MENUVAR){ + MenuEntry_Var *ev = (MenuEntry_Var*)e; + // HACK - we know the variable field is at the same address + // for all int/float classes. let's hope it stays that way. + if(ev->vartype = MENUVAR_INT) + ((MenuEntry_Int32*)e)->variable = (int32*)addr; + else if(ev->vartype = MENUVAR_FLOAT) + ((MenuEntry_Float32*)e)->variable = (float*)addr; + } +} diff --git a/src/extras/debugmenu.h b/src/extras/debugmenu.h new file mode 100644 index 00000000..29bbd972 --- /dev/null +++ b/src/extras/debugmenu.h @@ -0,0 +1,80 @@ +#pragma once + +typedef void (*TriggerFunc)(void); + +struct Menu; + +struct MenuEntry +{ + int type; + const char *name; + MenuEntry *next; + RwRect r; + Menu *menu; + + MenuEntry(const char *name); +}; + +typedef MenuEntry DebugMenuEntry; + +MenuEntry *DebugMenuAddInt8(const char *path, const char *name, int8 *ptr, TriggerFunc triggerFunc, int8 step, int8 lowerBound, int8 upperBound, const char **strings); +MenuEntry *DebugMenuAddInt16(const char *path, const char *name, int16 *ptr, TriggerFunc triggerFunc, int16 step, int16 lowerBound, int16 upperBound, const char **strings); +MenuEntry *DebugMenuAddInt32(const char *path, const char *name, int32 *ptr, TriggerFunc triggerFunc, int32 step, int32 lowerBound, int32 upperBound, const char **strings); +MenuEntry *DebugMenuAddInt64(const char *path, const char *name, int64 *ptr, TriggerFunc triggerFunc, int64 step, int64 lowerBound, int64 upperBound, const char **strings); +MenuEntry *DebugMenuAddUInt8(const char *path, const char *name, uint8 *ptr, TriggerFunc triggerFunc, uint8 step, uint8 lowerBound, uint8 upperBound, const char **strings); +MenuEntry *DebugMenuAddUInt16(const char *path, const char *name, uint16 *ptr, TriggerFunc triggerFunc, uint16 step, uint16 lowerBound, uint16 upperBound, const char **strings); +MenuEntry *DebugMenuAddUInt32(const char *path, const char *name, uint32 *ptr, TriggerFunc triggerFunc, uint32 step, uint32 lowerBound, uint32 upperBound, const char **strings); +MenuEntry *DebugMenuAddUInt64(const char *path, const char *name, uint64 *ptr, TriggerFunc triggerFunc, uint64 step, uint64 lowerBound, uint64 upperBound, const char **strings); +MenuEntry *DebugMenuAddFloat32(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound); +MenuEntry *DebugMenuAddFloat64(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound); +MenuEntry *DebugMenuAddCmd(const char *path, const char *name, TriggerFunc triggerFunc); +void DebugMenuEntrySetWrap(MenuEntry *e, bool wrap); +void DebugMenuEntrySetStrings(MenuEntry *e, const char **strings); +void DebugMenuEntrySetAddress(MenuEntry *e, void *addr); +void DebugMenuProcess(void); +void DebugMenuRender(void); + + +// Some overloads for simplicity +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc, int8_t step, int8_t lowerBound, int8_t upperBound, const char **strings) +{ return DebugMenuAddInt8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc, int16_t step, int16_t lowerBound, int16_t upperBound, const char **strings) +{ return DebugMenuAddInt16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc, int32_t step, int32_t lowerBound, int32_t upperBound, const char **strings) +{ return DebugMenuAddInt32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int64_t *ptr, TriggerFunc triggerFunc, int64_t step, int64_t lowerBound, int64_t upperBound, const char **strings) +{ return DebugMenuAddInt64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint8_t *ptr, TriggerFunc triggerFunc, uint8_t step, uint8_t lowerBound, uint8_t upperBound, const char **strings) +{ return DebugMenuAddUInt8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint16_t *ptr, TriggerFunc triggerFunc, uint16_t step, uint16_t lowerBound, uint16_t upperBound, const char **strings) +{ return DebugMenuAddUInt16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint32_t *ptr, TriggerFunc triggerFunc, uint32_t step, uint32_t lowerBound, uint32_t upperBound, const char **strings) +{ return DebugMenuAddUInt32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint64_t *ptr, TriggerFunc triggerFunc, uint64_t step, uint64_t lowerBound, uint64_t upperBound, const char **strings) +{ return DebugMenuAddUInt64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound) +{ return DebugMenuAddFloat32(path, name, ptr, triggerFunc, step, lowerBound, upperBound); } +inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound) +{ return DebugMenuAddFloat64(path, name, ptr, triggerFunc, step, lowerBound, upperBound); } + +inline DebugMenuEntry *DebugMenuAddVarBool32(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc) +{ + static const char *boolstr[] = { "Off", "On" }; + DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr); + DebugMenuEntrySetWrap(e, true); + return e; +} +inline DebugMenuEntry *DebugMenuAddVarBool16(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc) +{ + static const char *boolstr[] = { "Off", "On" }; + DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr); + DebugMenuEntrySetWrap(e, true); + return e; +} +inline DebugMenuEntry *DebugMenuAddVarBool8(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc) +{ + static const char *boolstr[] = { "Off", "On" }; + DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr); + DebugMenuEntrySetWrap(e, true); + return e; +} diff --git a/src/extras/inttypes.h b/src/extras/inttypes.h new file mode 100644 index 00000000..bf0c53e2 --- /dev/null +++ b/src/extras/inttypes.h @@ -0,0 +1,216 @@ +#define PRId8 "hhd" +#define PRId16 "hd" +#define PRId32 "ld" +#define PRId64 "lld" + +#define PRIdFAST8 "hhd" +#define PRIdFAST16 "hd" +#define PRIdFAST32 "ld" +#define PRIdFAST64 "lld" + +#define PRIdLEAST8 "hhd" +#define PRIdLEAST16 "hd" +#define PRIdLEAST32 "ld" +#define PRIdLEAST64 "lld" + +#define PRIdMAX "lld" +#define PRIdPTR "lld" + +#define PRIi8 "hhi" +#define PRIi16 "hi" +#define PRIi32 "li" +#define PRIi64 "lli" + +#define PRIiFAST8 "hhi" +#define PRIiFAST16 "hi" +#define PRIiFAST32 "li" +#define PRIiFAST64 "lli" + +#define PRIiLEAST8 "hhi" +#define PRIiLEAST16 "hi" +#define PRIiLEAST32 "li" +#define PRIiLEAST64 "lli" + +#define PRIiMAX "lli" +#define PRIiPTR "lli" + +#define PRIo8 "hho" +#define PRIo16 "ho" +#define PRIo32 "lo" +#define PRIo64 "llo" + +#define PRIoFAST8 "hho" +#define PRIoFAST16 "ho" +#define PRIoFAST32 "lo" +#define PRIoFAST64 "llo" + +#define PRIoLEAST8 "hho" +#define PRIoLEAST16 "ho" +#define PRIoLEAST32 "lo" +#define PRIoLEAST64 "llo" + +#define PRIoMAX "llo" +#define PRIoPTR "llo" + +#define PRIu8 "hhu" +#define PRIu16 "hu" +#define PRIu32 "lu" +#define PRIu64 "llu" + +#define PRIuFAST8 "hhu" +#define PRIuFAST16 "hu" +#define PRIuFAST32 "lu" +#define PRIuFAST64 "llu" + +#define PRIuLEAST8 "hhu" +#define PRIuLEAST16 "hu" +#define PRIuLEAST32 "lu" +#define PRIuLEAST64 "llu" + +#define PRIuMAX "llu" +#define PRIuPTR "llu" + +#define PRIx8 "hhx" +#define PRIx16 "hx" +#define PRIx32 "lx" +#define PRIx64 "llx" + +#define PRIxFAST8 "hhx" +#define PRIxFAST16 "hx" +#define PRIxFAST32 "lx" +#define PRIxFAST64 "llx" + +#define PRIxLEAST8 "hhx" +#define PRIxLEAST16 "hx" +#define PRIxLEAST32 "lx" +#define PRIxLEAST64 "llx" + +#define PRIxMAX "llx" +#define PRIxPTR "llx" + +#define PRIX8 "hhX" +#define PRIX16 "hX" +#define PRIX32 "lX" +#define PRIX64 "llX" + +#define PRIXFAST8 "hhX" +#define PRIXFAST16 "hX" +#define PRIXFAST32 "lX" +#define PRIXFAST64 "llX" + +#define PRIXLEAST8 "hhX" +#define PRIXLEAST16 "hX" +#define PRIXLEAST32 "lX" +#define PRIXLEAST64 "llX" + +#define PRIXMAX "llX" +#define PRIXPTR "llX" + + /* SCAN FORMAT MACROS */ +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "ld" +#define SCNd64 "lld" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 "hd" +#define SCNdFAST32 "ld" +#define SCNdFAST64 "lld" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "ld" +#define SCNdLEAST64 "lld" + +#define SCNdMAX "lld" +#define SCNdPTR "lld" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "li" +#define SCNi64 "lli" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 "hi" +#define SCNiFAST32 "li" +#define SCNiFAST64 "lli" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "li" +#define SCNiLEAST64 "lli" + +#define SCNiMAX "lli" +#define SCNiPTR "lli" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "lo" +#define SCNo64 "llo" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 "ho" +#define SCNoFAST32 "lo" +#define SCNoFAST64 "llo" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "lo" +#define SCNoLEAST64 "llo" + +#define SCNoMAX "llo" +#define SCNoPTR "llo" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "lu" +#define SCNu64 "llu" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 "hu" +#define SCNuFAST32 "lu" +#define SCNuFAST64 "llu" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "lu" +#define SCNuLEAST64 "llu" + +#define SCNuMAX "llu" +#define SCNuPTR "llu" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "lx" +#define SCNx64 "llx" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 "hx" +#define SCNxFAST32 "lx" +#define SCNxFAST64 "llx" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "lx" +#define SCNxLEAST64 "llx" + +#define SCNxMAX "llx" +#define SCNxPTR "llx" + +#define SCNX8 "hhX" +#define SCNX16 "hX" +#define SCNX32 "lX" +#define SCNX64 "llX" + +#define SCNXFAST8 "hhX" +#define SCNXFAST16 "hX" +#define SCNXFAST32 "lX" +#define SCNXFAST64 "llX" + +#define SCNXLEAST8 "hhX" +#define SCNXLEAST16 "hX" +#define SCNXLEAST32 "lX" +#define SCNXLEAST64 "llX" + +#define SCNXMAX "llX" +#define SCNXPTR "llX" \ No newline at end of file diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 59c01c91..b86e9214 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -176,8 +176,8 @@ const RwChar *RwImageSetPath(const RwChar * path) { Image::setSearchPath(path); RwImage *RwImageSetStride(RwImage * image, RwInt32 stride) { image->stride = stride; return image; } RwImage *RwImageSetPixels(RwImage * image, RwUInt8 * pixels) { image->pixels = pixels; return image; } RwImage *RwImageSetPalette(RwImage * image, RwRGBA * palette) { image->palette = (uint8*)palette; return image; } -RwInt32 RwImageGetWidth(const RwImage * image); -RwInt32 RwImageGetHeight(const RwImage * image); +RwInt32 RwImageGetWidth(const RwImage * image) { return image->width; } +RwInt32 RwImageGetHeight(const RwImage * image) { return image->height; } RwInt32 RwImageGetDepth(const RwImage * image); RwInt32 RwImageGetStride(const RwImage * image); RwUInt8 *RwImageGetPixels(const RwImage * image); diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 5aa4475f..02a07558 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -9,12 +9,20 @@ RtCharset *debugCharset; #endif +static bool charsetOpen; +void OpenCharsetSafe() +{ + if(!charsetOpen) + RtCharsetOpen(); + charsetOpen = true; +} + void CreateDebugFont() { #ifndef FINAL RwRGBA color = { 255, 255, 128, 255 }; RwRGBA colorbg = { 0, 0, 0, 0 }; - RtCharsetOpen(); + OpenCharsetSafe(); debugCharset = RtCharsetCreate(&color, &colorbg); #endif } @@ -24,6 +32,7 @@ void DestroyDebugFont() #ifndef FINAL RtCharsetDestroy(debugCharset); RtCharsetClose(); + charsetOpen = false; #endif } diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index 9f178ec2..e6740031 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -3,6 +3,7 @@ void *RwMallocAlign(RwUInt32 size, RwUInt32 align); void RwFreeAlign(void *mem); +void OpenCharsetSafe(); void CreateDebugFont(); void DestroyDebugFont(); void ObrsPrintfString(const char *str, short x, short y); From 4b883f2b40f488a67479e3c83d9c1c5686375364 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 24 Apr 2020 20:50:00 +0300 Subject: [PATCH 110/123] disable mouse steering by default --- src/vehicles/Vehicle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 57c5f3af..06894447 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -24,7 +24,7 @@ bool CVehicle::bAllDodosCheat; bool CVehicle::bCheat3; bool CVehicle::bCheat4; bool CVehicle::bCheat5; -bool CVehicle::m_bDisableMouseSteering; +bool CVehicle::m_bDisableMouseSteering = true; void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); } void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); } From ac19de45b88123b2284ecc3ab44cedcaa7ca496d Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 25 Apr 2020 00:40:14 +0200 Subject: [PATCH 111/123] few fixes --- librw | 2 +- src/animation/AnimManager.cpp | 6 ++++++ src/core/Streaming.cpp | 3 ++- src/core/main.cpp | 4 +++- src/entities/Entity.cpp | 22 --------------------- src/extras/debugmenu.cpp | 36 ++++++++++++++++++++++++++++++----- src/extras/debugmenu.h | 2 ++ src/fakerw/fake.cpp | 6 +++--- src/rw/RwHelper.cpp | 20 +++++++++++++++++++ src/rw/RwHelper.h | 2 ++ src/rw/TexRead.cpp | 5 +---- 11 files changed, 71 insertions(+), 37 deletions(-) diff --git a/librw b/librw index 374f951d..c4ffa362 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 374f951d7cee353914059d8ddf9c5aff7d764984 +Subproject commit c4ffa3622ae02f56168a1e93b978987981f3b68d diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp index 7c09b0dd..ebd2e1fb 100644 --- a/src/animation/AnimManager.cpp +++ b/src/animation/AnimManager.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "General.h" +#include "RwHelper.h" #include "ModelInfo.h" #include "ModelIndices.h" #include "FileMgr.h" @@ -754,6 +755,11 @@ CAnimManager::LoadAnimFiles(void) group->CreateAssociations(def->blockName, clump, def->animNames, def->numAnims); for(j = 0; j < group->numAssociations; j++) group->GetAnimation(j)->flags |= def->animDescs[j].flags; +#ifdef PED_SKIN + // forgot on xbox/android + if(IsClumpSkinned(clump)) + RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil); +#endif RpClumpDestroy(clump); } } diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index 8124d11c..a76e9038 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -754,7 +754,8 @@ CStreaming::RequestSpecialModel(int32 modelId, const char *modelName, int32 flag }else RemoveModel(modelId); - ms_pExtraObjectsDir->FindItem(modelName, pos, size); + bool found = ms_pExtraObjectsDir->FindItem(modelName, pos, size); + assert(found); mi->ClearTexDictionary(); if(CTxdStore::FindTxdSlot(modelName) == -1) mi->SetTexDictionary("generic"); diff --git a/src/core/main.cpp b/src/core/main.cpp index 7c1f7938..ec37fa28 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -91,7 +91,6 @@ void GameInit(void); void SystemInit(void); void TheGame(void); -void DebugMenuInit(void) {} void DebugMenuPopulate(void); @@ -344,6 +343,8 @@ static void Terminate3D(void) { CGame::ShutdownRenderWare(); + + DebugMenuShutdown(); RsRwTerminate(); @@ -794,6 +795,7 @@ RenderDebugShit(void) CRenderer::RenderCollisionLines(); ThePaths.DisplayPathData(); CDebug::DrawLines(); + DefinedState(); #endif } diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 756e1232..ee4faa82 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -285,28 +285,6 @@ CEntity::CreateRwObject(void) } } -#ifdef PED_SKIN -RpAtomic* -AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data) -{ - if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))){ - RpHAnimHierarchy *hier = RpSkinAtomicGetHAnimHierarchy(atomic); -#ifdef LIBRW - if(hier && hier->interpolator->currentAnim){ - RpHAnimAnimationDestroy(hier->interpolator->currentAnim); - hier->interpolator->currentAnim = nil; - } -#else - if(hier && hier->pCurrentAnim){ - RpHAnimAnimationDestroy(hier->pCurrentAnim); - hier->pCurrentAnim = nil; - } -#endif - } - return atomic; -} -#endif - void CEntity::DeleteRwObject(void) { diff --git a/src/extras/debugmenu.cpp b/src/extras/debugmenu.cpp index d6ee18ab..f419e76f 100644 --- a/src/extras/debugmenu.cpp +++ b/src/extras/debugmenu.cpp @@ -95,6 +95,18 @@ createMenuFont(void) RtCharsetGetDesc(fontStyles[MENUFONT_NORMAL], &fontDesc); } +void +destroyMenuFont(void) +{ + RtCharsetDestroy(fontStyles[MENUFONT_NORMAL]); + fontStyles[MENUFONT_NORMAL] = nil; + RtCharsetDestroy(fontStyles[MENUFONT_SEL_ACTIVE]); + fontStyles[MENUFONT_SEL_ACTIVE] = nil; + RtCharsetDestroy(fontStyles[MENUFONT_SEL_INACTIVE]); + fontStyles[MENUFONT_SEL_INACTIVE] = nil; + RtCharsetDestroy(fontStyles[MENUFONT_MOUSE]); + fontStyles[MENUFONT_MOUSE] = nil; +} @@ -755,7 +767,7 @@ static uint8 arrowPx[] = { }; void -initDebug(void) +DebugMenuInit(void) { createMenuFont(); @@ -779,6 +791,22 @@ initDebug(void) arrow = RwRasterSetFromImage(arrow, img); assert(arrow); RwImageDestroy(img); + + menuInitialized = true; +} + +void +DebugMenuShutdown(void) +{ + if(menuInitialized){ + destroyMenuFont(); + RwRasterDestroy(cursor); + cursor = nil; + RwRasterDestroy(arrow); + arrow = nil; + // TODO: the menus ... + } + menuInitialized = false; } void @@ -971,10 +999,8 @@ DebugMenuProcess(void) pad->DisablePlayerControls = 1; // TODO: this could happen earlier - if(!menuInitialized){ - initDebug(); - menuInitialized = 1; - } + if(!menuInitialized) + DebugMenuInit(); updateMouse(); } diff --git a/src/extras/debugmenu.h b/src/extras/debugmenu.h index 29bbd972..3ef8c742 100644 --- a/src/extras/debugmenu.h +++ b/src/extras/debugmenu.h @@ -31,6 +31,8 @@ MenuEntry *DebugMenuAddCmd(const char *path, const char *name, TriggerFunc trigg void DebugMenuEntrySetWrap(MenuEntry *e, bool wrap); void DebugMenuEntrySetStrings(MenuEntry *e, const char **strings); void DebugMenuEntrySetAddress(MenuEntry *e, void *addr); +void DebugMenuInit(void); +void DebugMenuShutdown(void); void DebugMenuProcess(void); void DebugMenuRender(void); diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index b86e9214..dca15dd0 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -241,7 +241,7 @@ RwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image) { return raster RwTexture *RwTextureCreate(RwRaster * raster) { return Texture::create(raster); } RwBool RwTextureDestroy(RwTexture * texture) { texture->destroy(); return true; } -RwTexture *RwTextureAddRef(RwTexture *texture) { texture->refCount++; return texture; } +RwTexture *RwTextureAddRef(RwTexture *texture) { texture->addRef(); return texture; } // TODO RwBool RwTextureSetMipmapping(RwBool enable) { return true; } RwBool RwTextureGetMipmapping(void); @@ -410,11 +410,11 @@ RwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2) { RwImVertexIndex indices[2]; indices[0] = vert1; indices[1] = vert2; - im3d::RenderIndexed((PrimitiveType)PRIMTYPELINELIST, indices, 2); + im3d::RenderIndexedPrimitive((PrimitiveType)PRIMTYPELINELIST, indices, 2); return true; } RwBool RwIm3DRenderTriangle(RwInt32 vert1, RwInt32 vert2, RwInt32 vert3); -RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices) { im3d::RenderIndexed((PrimitiveType)primType, indices, numIndices); return true; } +RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices) { im3d::RenderIndexedPrimitive((PrimitiveType)primType, indices, numIndices); return true; } RwBool RwIm3DRenderPrimitive(RwPrimitiveType primType); diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 02a07558..42e62105 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -312,6 +312,26 @@ HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier) return anim; } +RpAtomic* +AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data) +{ + if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))){ + RpHAnimHierarchy *hier = RpSkinAtomicGetHAnimHierarchy(atomic); +#ifdef LIBRW + if(hier && hier->interpolator->currentAnim){ + RpHAnimAnimationDestroy(hier->interpolator->currentAnim); + hier->interpolator->currentAnim = nil; + } +#else + if(hier && hier->pCurrentAnim){ + RpHAnimAnimationDestroy(hier->pCurrentAnim); + hier->pCurrentAnim = nil; + } +#endif + } + return atomic; +} + void RenderSkeleton(RpHAnimHierarchy *hier) { diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index e6740031..8a55a832 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -21,6 +21,8 @@ RpHAnimHierarchy *GetAnimHierarchyFromClump(RpClump *clump); // get from frame RwFrame *GetHierarchyFromChildNodesCB(RwFrame *frame, void *data); void SkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable); RpHAnimAnimation *HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier); +RpAtomic *AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data); +void RenderSkeleton(RpHAnimHierarchy *hier); #endif RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream); diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index d1ff3dc0..9f0cae3c 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -66,10 +66,7 @@ RwTexDictionaryGtaStreamRead(RwStream *stream) if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version)) return nil; - assert(size == 4); -int foo = RwStreamRead(stream, &numTextures, size); -if(foo != size) -// if(RwStreamRead(stream, &numTextures, size) != size) + if(RwStreamRead(stream, &numTextures, size) != size) return nil; texDict = RwTexDictionaryCreate(); From dbc810044e5a20f3cee5e3d9f5b04766b52a9d57 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 25 Apr 2020 11:25:46 +0200 Subject: [PATCH 112/123] librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index c4ffa362..5ffbde38 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit c4ffa3622ae02f56168a1e93b978987981f3b68d +Subproject commit 5ffbde3890d1f959490c3ce16721c2a263415d8d From f15a5ac0f9e5b9ae4144f58f95f74c498ea9a7f3 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 25 Apr 2020 12:16:50 +0200 Subject: [PATCH 113/123] using librw GS alpha test emulation --- librw | 2 +- src/core/re3.cpp | 46 +++++++++++++++++++++++------------------- src/extras/debugmenu.h | 4 ++++ src/rw/RwHelper.cpp | 4 ++++ src/rw/RwHelper.h | 2 ++ 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/librw b/librw index 5ffbde38..d8d13d44 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 5ffbde3890d1f959490c3ce16721c2a263415d8d +Subproject commit d8d13d44293a58b58d51c3a8e91e3ea76c6d6feb diff --git a/src/core/re3.cpp b/src/core/re3.cpp index d4d2c208..2a9cbc77 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -322,8 +322,12 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); }); DebugMenuAddCmd("Spawn", "Spawn Predator", [](){ SpawnCar(MI_PREDATOR); }); - DebugMenuAddVarBool8("Debug", "Draw hud", (int8*)&CHud::m_Wants_To_Draw_Hud, nil); - DebugMenuAddVarBool8("Debug", "Edit on", (int8*)&CSceneEdit::m_bEditOn, nil); +#ifdef LIBRW + DebugMenuAddVarBool8("Render", "PS2 Alpha test Emu", &gPS2alphaTest, nil); +#endif + + DebugMenuAddVarBool8("Debug", "Draw hud", &CHud::m_Wants_To_Draw_Hud, nil); + DebugMenuAddVarBool8("Debug", "Edit on", &CSceneEdit::m_bEditOn, nil); #ifdef MENU_MAP DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); #endif @@ -333,27 +337,27 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Toggle Comedy Controls", ToggleComedy); DebugMenuAddCmd("Debug", "Place Car on Road", PlaceOnRoad); - DebugMenuAddVarBool8("Debug", "Catalina Heli On", (int8*)&CHeli::CatalinaHeliOn, nil); + DebugMenuAddVarBool8("Debug", "Catalina Heli On", &CHeli::CatalinaHeliOn, nil); DebugMenuAddCmd("Debug", "Catalina Fly By", CHeli::StartCatalinaFlyBy); DebugMenuAddCmd("Debug", "Catalina Take Off", CHeli::CatalinaTakeOff); DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway); - DebugMenuAddVarBool8("Debug", "Script Heli On", (int8*)&CHeli::ScriptHeliOn, nil); + DebugMenuAddVarBool8("Debug", "Script Heli On", &CHeli::ScriptHeliOn, nil); - DebugMenuAddVarBool8("Debug", "Show Ped Paths", (int8*)&gbShowPedPaths, nil); - DebugMenuAddVarBool8("Debug", "Show Car Paths", (int8*)&gbShowCarPaths, nil); - DebugMenuAddVarBool8("Debug", "Show Car Path Links", (int8*)&gbShowCarPathsLinks, nil); - DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil); - DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil); - DebugMenuAddVarBool8("Debug", "Show Collision Lines", (int8*)&gbShowCollisionLines, nil); - DebugMenuAddVarBool8("Debug", "Show Collision Polys", (int8*)&gbShowCollisionPolys, nil); - DebugMenuAddVarBool8("Debug", "Don't render Buildings", (int8*)&gbDontRenderBuildings, nil); - DebugMenuAddVarBool8("Debug", "Don't render Big Buildings", (int8*)&gbDontRenderBigBuildings, nil); - DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil); - DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil); - DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); + DebugMenuAddVarBool8("Debug", "Show Ped Paths", &gbShowPedPaths, nil); + DebugMenuAddVarBool8("Debug", "Show Car Paths", &gbShowCarPaths, nil); + DebugMenuAddVarBool8("Debug", "Show Car Path Links", &gbShowCarPathsLinks, nil); + DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", &gbShowPedRoadGroups, nil); + DebugMenuAddVarBool8("Debug", "Show Car Road Groups", &gbShowCarRoadGroups, nil); + DebugMenuAddVarBool8("Debug", "Show Collision Lines", &gbShowCollisionLines, nil); + DebugMenuAddVarBool8("Debug", "Show Collision Polys", &gbShowCollisionPolys, nil); + DebugMenuAddVarBool8("Debug", "Don't render Buildings", &gbDontRenderBuildings, nil); + DebugMenuAddVarBool8("Debug", "Don't render Big Buildings", &gbDontRenderBigBuildings, nil); + DebugMenuAddVarBool8("Debug", "Don't render Peds", &gbDontRenderPeds, nil); + DebugMenuAddVarBool8("Debug", "Don't render Vehicles", &gbDontRenderVehicles, nil); + DebugMenuAddVarBool8("Debug", "Don't render Objects", &gbDontRenderObjects, nil); #ifdef TOGGLEABLE_BETA_FEATURES - DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil); - DebugMenuAddVarBool8("Debug", "Toggle peds running to phones to report crimes", (int8*)&CPed::bMakePedsRunToPhonesToReportCrimes, nil); + DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil); + DebugMenuAddVarBool8("Debug", "Toggle peds running to phones to report crimes", &CPed::bMakePedsRunToPhonesToReportCrimes, nil); #endif DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start); @@ -361,11 +365,11 @@ DebugMenuPopulate(void) extern bool PrintDebugCode; extern int16 DebugCamMode; - DebugMenuAddVarBool8("Cam", "Use mouse Cam", (int8*)&CCamera::m_bUseMouse3rdPerson, nil); + DebugMenuAddVarBool8("Cam", "Use mouse Cam", &CCamera::m_bUseMouse3rdPerson, nil); #ifdef FREE_CAM - DebugMenuAddVarBool8("Cam", "Free Cam", (int8*)&CCamera::bFreeCam, nil); + DebugMenuAddVarBool8("Cam", "Free Cam", &CCamera::bFreeCam, nil); #endif - DebugMenuAddVarBool8("Cam", "Print Debug Code", (int8*)&PrintDebugCode, nil); + DebugMenuAddVarBool8("Cam", "Print Debug Code", &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; }); diff --git a/src/extras/debugmenu.h b/src/extras/debugmenu.h index 3ef8c742..462b59c4 100644 --- a/src/extras/debugmenu.h +++ b/src/extras/debugmenu.h @@ -80,3 +80,7 @@ inline DebugMenuEntry *DebugMenuAddVarBool8(const char *path, const char *name, DebugMenuEntrySetWrap(e, true); return e; } +inline DebugMenuEntry *DebugMenuAddVarBool8(const char *path, const char *name, bool *ptr, TriggerFunc triggerFunc) +{ + return DebugMenuAddVarBool8(path, name, (int8_t*)ptr, triggerFunc); +} diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 42e62105..707f1b44 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -9,6 +9,8 @@ RtCharset *debugCharset; #endif +bool gPS2alphaTest = 1; + static bool charsetOpen; void OpenCharsetSafe() { @@ -101,6 +103,8 @@ DefinedState(void) #ifdef LIBRW rw::SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL); rw::SetRenderState(rw::ALPHATESTREF, 3); + + rw::SetRenderState(rw::GSALPHATEST, gPS2alphaTest); #else // D3D stuff RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index 8a55a832..a751ee39 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -1,5 +1,7 @@ #pragma once +extern bool gPS2alphaTest; + void *RwMallocAlign(RwUInt32 size, RwUInt32 align); void RwFreeAlign(void *mem); From 241352e3127f499d43dd45ef7e913c4fc2806fe7 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 25 Apr 2020 14:03:20 +0200 Subject: [PATCH 114/123] real names (from LCS) --- src/animation/FrameUpdate.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp index a38ebc74..a1121282 100644 --- a/src/animation/FrameUpdate.cpp +++ b/src/animation/FrameUpdate.cpp @@ -10,12 +10,12 @@ CAnimBlendClumpData *gpAnimBlendClump; // PS2 names without "NonSkinned" void FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg); -void FrameUpdateCallBackNonSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void *arg); -void FrameUpdateCallBackNonSkinnedWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackWithVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg); void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg); -void FrameUpdateCallBackSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void *arg); -void FrameUpdateCallBackSkinnedWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg); +void FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg); void @@ -31,9 +31,9 @@ FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg) if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && gpAnimBlendClump->velocity){ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION_3D) - FrameUpdateCallBackNonSkinnedWith3dVelocityExtraction(frame, arg); + FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(frame, arg); else - FrameUpdateCallBackNonSkinnedWithVelocityExtraction(frame, arg); + FrameUpdateCallBackWithVelocityExtractionNonSkinned(frame, arg); return; } @@ -70,7 +70,7 @@ FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg) } void -FrameUpdateCallBackNonSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void *arg) +FrameUpdateCallBackWithVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg) { CVector vec, pos(0.0f, 0.0f, 0.0f); CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); @@ -150,7 +150,7 @@ FrameUpdateCallBackNonSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, v // original code uses do loops? void -FrameUpdateCallBackNonSkinnedWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg) +FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg) { CVector vec, pos(0.0f, 0.0f, 0.0f); CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); @@ -227,9 +227,9 @@ FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg) if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && gpAnimBlendClump->velocity){ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION_3D) - FrameUpdateCallBackSkinnedWith3dVelocityExtraction(frame, arg); + FrameUpdateCallBackWith3dVelocityExtractionSkinned(frame, arg); else - FrameUpdateCallBackSkinnedWithVelocityExtraction(frame, arg); + FrameUpdateCallBackWithVelocityExtractionSkinned(frame, arg); return; } @@ -267,7 +267,7 @@ FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg) } void -FrameUpdateCallBackSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void *arg) +FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg) { CVector vec, pos(0.0f, 0.0f, 0.0f); CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); @@ -347,7 +347,7 @@ FrameUpdateCallBackSkinnedWithVelocityExtraction(AnimBlendFrameData *frame, void } void -FrameUpdateCallBackSkinnedWith3dVelocityExtraction(AnimBlendFrameData *frame, void *arg) +FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg) { CVector vec, pos(0.0f, 0.0f, 0.0f); CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f); From 8289b42c9e41c5370723438e5eff9b2fa27e6069 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 25 Apr 2020 14:37:58 +0200 Subject: [PATCH 115/123] fixed shooting target --- src/weapons/Weapon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 54e73a41..a3d52f69 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -600,8 +600,8 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) rotOffset.Normalise(); target = *fireSource; - target.x = rotOffset.x * info->m_fRange; - target.y = rotOffset.y * info->m_fRange; + target.x += rotOffset.x * info->m_fRange; + target.y += rotOffset.y * info->m_fRange; if ( shooter->IsPed() ) DoDoomAiming(shooter, fireSource, &target); From ea79cc4469dbe377e2da9e5019c1d709e95140d0 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 25 Apr 2020 15:56:20 +0200 Subject: [PATCH 116/123] update librw --- librw | 2 +- src/fakerw/fake.cpp | 4 ++-- src/fakerw/rphanim.h | 10 +++++++++- src/fakerw/rtquat.h | 7 ++++++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/librw b/librw index d8d13d44..43190a51 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit d8d13d44293a58b58d51c3a8e91e3ea76c6d6feb +Subproject commit 43190a51f799a3ef315c0b6245b70ee3a09a64ac diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index dca15dd0..c4ff2dd2 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -787,8 +787,8 @@ RwImage *RtBMPImageRead(const RwChar * imageName) { return rw::readBMP(imageName #include "rtquat.h" -RtQuat *RtQuatRotate(RtQuat * quat, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp) { return quat->rotate(axis, angle/180.0f*3.14159f, (CombineOp)combineOp); } -void RtQuatConvertToMatrix(const RtQuat * const qpQuat, RwMatrix * const mpMatrix) { mpMatrix->rotate(*qpQuat, COMBINEREPLACE); } +RtQuat *RtQuatRotate(RtQuat * quat, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp) { return (RtQuat*)((rw::Quat*)quat)->rotate(axis, angle/180.0f*3.14159f, (CombineOp)combineOp); } +void RtQuatConvertToMatrix(const RtQuat * const qpQuat, RwMatrix * const mpMatrix) { mpMatrix->rotate(*(rw::Quat*)qpQuat, COMBINEREPLACE); } #include "rtcharse.h" diff --git a/src/fakerw/rphanim.h b/src/fakerw/rphanim.h index 34dfeb09..6ece8306 100644 --- a/src/fakerw/rphanim.h +++ b/src/fakerw/rphanim.h @@ -9,7 +9,15 @@ typedef rw::Animation RpHAnimAnimation; #define rpHANIMSTDKEYFRAMETYPEID 0x1 -typedef rw::HAnimKeyFrame RpHAnimStdKeyFrame; +// same as rw::HAnimKeyFrame, but we need RtQuat in this one +struct RpHAnimStdKeyFrame +{ + RpHAnimStdKeyFrame *prevFrame; + RwReal time; + RtQuat q; + RwV3d t; +}; + enum RpHAnimHierarchyFlag { diff --git a/src/fakerw/rtquat.h b/src/fakerw/rtquat.h index 3cf15f5a..450342b2 100644 --- a/src/fakerw/rtquat.h +++ b/src/fakerw/rtquat.h @@ -1,6 +1,11 @@ #pragma once -typedef rw::Quat RtQuat; +// Same layout as rw::Quat but with ugly imag,real separation which i don't want in librw +struct RtQuat +{ + rw::V3d imag; + rw::float32 real; +}; RwBool RtQuatConvertFromMatrix(RtQuat * const qpQuat, const RwMatrix * const mpMatrix); RtQuat *RtQuatRotate(RtQuat * quat, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp); From 6c1a1f7cd20a2674f33b5318e6e07a3a28d016f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sun, 26 Apr 2020 13:25:03 +0300 Subject: [PATCH 117/123] Initial GLFW support --- premake5.lua | 27 +- src/core/ControllerConfig.cpp | 98 +- src/core/ControllerConfig.h | 17 +- src/core/Frontend.cpp | 24 +- src/core/Game.cpp | 2 +- src/core/Pad.cpp | 58 +- src/core/common.h | 4 +- src/core/config.h | 2 +- src/core/patcher.cpp | 3 +- src/fakerw/fake.cpp | 8 +- src/rw/RwHelper.cpp | 2 + src/rw/TexRead.cpp | 2 +- src/rw/TxdStore.cpp | 35 + src/skel/crossplatform.h | 69 +- src/skel/events.cpp | 9 +- src/skel/glfw/glfw.cpp | 1651 +++++++++++++++++++++++++++++++++ src/skel/skeleton.cpp | 2 +- src/skel/win/win.cpp | 5 +- src/skel/win/win.h | 37 +- src/text/Messages.cpp | 3 - src/vehicles/Boat.cpp | 8 +- 21 files changed, 1983 insertions(+), 83 deletions(-) create mode 100644 src/skel/glfw/glfw.cpp diff --git a/premake5.lua b/premake5.lua index baf26a42..f2a58880 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,7 +1,7 @@ Librw = os.getenv("LIBRW") or "librw" workspace "re3" - configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW" } + configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW", "ReleaseGLFW" } location "build" files { "src/*.*" } @@ -19,6 +19,7 @@ workspace "re3" files { "src/save/*.*" } files { "src/skel/*.*" } files { "src/skel/win/*.*" } + files { "src/skel/glfw/*.*" } files { "src/text/*.*" } files { "src/vehicles/*.*" } files { "src/weapons/*.*" } @@ -40,6 +41,7 @@ workspace "re3" includedirs { "src/save/" } includedirs { "src/skel/" } includedirs { "src/skel/win" } + includedirs { "src/skel/glfw" } includedirs { "src/text" } includedirs { "src/vehicles" } includedirs { "src/weapons" } @@ -67,6 +69,21 @@ workspace "re3" links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp", "rtquat", "rtcharse" } filter {} + filter "configurations:ReleaseGLFW" + defines { "GLEW_STATIC", "GLFW_DLL" } + files { "src/fakerw/*.*" } + includedirs { "src/fakerw" } + includedirs { Librw } + includedirs { "glfw-3.3.2.bin.WIN32/include" } + includedirs { "glew-2.1.0/include" } + libdirs { path.join(Librw, "lib/win-x86-gl3/Release") } + libdirs { "glew-2.1.0/lib/Release/Win32" } + libdirs { "glfw-3.3.2.bin.WIN32/lib-vc2015" } + links { "opengl32" } + links { "glew32s" } + links { "glfw3dll" } + links { "rw" } + filter {} pbcommands = { "setlocal EnableDelayedExpansion", @@ -107,14 +124,18 @@ project "re3" symbols "Full" staticruntime "off" - filter "configurations:not *RW" - -- prebuildcommands { "cd \"../librw\" && premake5 " .. _ACTION .. " && msbuild \"build/librw.sln\" /property:Configuration=%{cfg.longname} /property:Platform=\"win-x86-d3d9\"" } + filter "configurations:Debug or Release or ReleaseFH" + prebuildcommands { "cd \"../librw\" && premake5 " .. _ACTION .. " && msbuild \"build/librw.sln\" /property:Configuration=%{cfg.longname} /property:Platform=\"win-x86-d3d9\"" } defines { "LIBRW", "RW_D3D9" } filter "configurations:*RW" defines { "RWLIBS" } staticruntime "on" linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text" + + filter "configurations:*GLFW" + prebuildcommands { "cd \"../librw\" && premake5 " .. _ACTION .. " && msbuild \"build/librw.sln\" /property:Configuration=Release /property:Platform=\"win-x86-gl3\"" } + defines { "LIBRW", "RW_GL3" } filter "configurations:Debug*" defines { "DEBUG" } diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index a2382c12..f55568be 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -1,7 +1,10 @@ +#if defined RW_D3D9 || defined RWLIBS #define DIRECTINPUT_VERSION 0x0800 #include -#include "common.h" +#endif +#include "common.h" +#include "crossplatform.h" #include "ControllerConfig.h" #include "Pad.h" #include "FileMgr.h" @@ -15,7 +18,6 @@ #include "World.h" #include "ModelIndices.h" #include "Camera.h" -#include "win.h" #include "GenericGameStorage.h" CControllerConfigManager ControlsManager; @@ -41,14 +43,72 @@ void CControllerConfigManager::MakeControllerActionsBlank() } } +#ifdef RW_GL3 +int MapIdToButtonId(int mapId) { + switch (mapId) { + case GLFW_GAMEPAD_BUTTON_A: // Cross + return 2; + case GLFW_GAMEPAD_BUTTON_B: // Circle + return 1; + case GLFW_GAMEPAD_BUTTON_X: // Square + return 3; + case GLFW_GAMEPAD_BUTTON_Y: // Triangle + return 4; + case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER: + return 7; + case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER: + return 8; + case GLFW_GAMEPAD_BUTTON_BACK: + return 9; + case GLFW_GAMEPAD_BUTTON_START: + return 12; + case GLFW_GAMEPAD_BUTTON_LEFT_THUMB: + return 10; + case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB: + return 11; + case GLFW_GAMEPAD_BUTTON_DPAD_UP: + return 13; + case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT: + return 14; + case GLFW_GAMEPAD_BUTTON_DPAD_DOWN: + return 15; + case GLFW_GAMEPAD_BUTTON_DPAD_LEFT: + return 16; + // GLFW sends those as axes, so I added them here manually. + case 15: // Left trigger + return 5; + case 16: // Right trigger + return 6; + default: + return 0; + } +} +#endif + int32 CControllerConfigManager::GetJoyButtonJustDown() { #ifdef __DINPUT_INCLUDED__ +#ifdef FIX_BUGS + for (int32 i = 0; i < MAX_BUTTONS; i++) +#else for (int32 i = 0; i < JOY_BUTTONS; i++) +#endif { if (m_NewState.rgbButtons[i] & 0x80 && !(m_OldState.rgbButtons[i] & 0x80)) return i + 1; } +#elif defined RW_GL3 + if (m_NewState.isGamepad) { + for (int32 i = 0; i < MAX_BUTTONS; i++) { + if (m_NewState.mappedButtons[i] && !(m_OldState.mappedButtons[i])) + return MapIdToButtonId(i); + } + } else { + for (int32 i = 0; i < Min(m_NewState.numButtons, MAX_BUTTONS); i++) { + if (m_NewState.buttons[i] && !(m_OldState.buttons[i])) + return i + 1; + } + } #endif return 0; } @@ -249,8 +309,13 @@ void CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons) if (buttons > 16) btn = 16; + // Now we use SDL Game Controller DB +#if defined RW_D3D9 || defined RWLIBS if ( AllValidWinJoys.m_aJoys[JOYSTICK1].m_nVendorID == 0x3427 && AllValidWinJoys.m_aJoys[JOYSTICK1].m_nProductID == 0x1190) +#else + if (0) +#endif { //GIC USB Joystick, PS2 Gamepad ? @@ -445,8 +510,13 @@ void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonDown(int32 button, i break; } - if ( AllValidWinJoys.m_aJoys[JOYSTICK1].m_nVendorID == 0x3427 + // Now we use SDL Game Controller DB +#if defined RW_D3D9 || defined RWLIBS + if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_nVendorID == 0x3427 && AllValidWinJoys.m_aJoys[JOYSTICK1].m_nProductID == 0x1190) +#else + if (0) +#endif { //GIC USB Joystick, PS2 Gamepad ? @@ -872,8 +942,13 @@ void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonUp(int32 button, int break; } - if ( AllValidWinJoys.m_aJoys[JOYSTICK1].m_nVendorID == 0x3427 + // Now we use SDL Game Controller DB +#if defined RW_D3D9 || defined RWLIBS + if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_nVendorID == 0x3427 && AllValidWinJoys.m_aJoys[JOYSTICK1].m_nProductID == 0x1190) +#else + if (0) +#endif { //GIC USB Joystick, PS2 Gamepad ? @@ -1809,7 +1884,7 @@ wchar *CControllerConfigManager::GetControllerSettingTextKeyBoard(e_ControllerAc static wchar ActionText[50]; static wchar NewStringWithNumber[30]; - for (int32 i = 0; i < ARRAYSIZE(ActionText); i++) + for (int32 i = 0; i < ARRAY_SIZE(ActionText); i++) ActionText[i] = '\0'; if (GetControllerKeyAssociatedWithAction(action, type) != rsNULL) @@ -2266,6 +2341,19 @@ void CControllerConfigManager::UpdateJoyButtonState(int32 padnumber) else m_aButtonStates[i] = false; } +#elif defined RW_GL3 + if (m_NewState.isGamepad) { + for (int32 i = 0; i < MAX_BUTTONS; i++) { + if (i == GLFW_GAMEPAD_BUTTON_GUIDE) + continue; + + m_aButtonStates[MapIdToButtonId(i)-1] = m_NewState.mappedButtons[i]; + } + } else { + for (int32 i = 0; i < Min(m_NewState.numButtons, MAX_BUTTONS); i++) { + m_aButtonStates[i] = m_NewState.buttons[i]; + } + } #endif } diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index 82174343..76f9882b 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -96,6 +96,16 @@ class CControllerState; #define ACTIONNAME_LENGTH 40 +#ifdef RW_GL3 +struct GlfwJoyState { + int8 id; + bool isGamepad; + uint8 numButtons; + uint8* buttons; + bool mappedButtons[17]; +}; +#endif + class CControllerConfigManager { public: @@ -115,8 +125,9 @@ public: #ifdef __DINPUT_INCLUDED__ DIJOYSTATE2 m_OldState; DIJOYSTATE2 m_NewState; -#else - uint32 ___padd[0x110 / 4 * 2]; +#elif defined RW_GL3 + GlfwJoyState m_OldState; + GlfwJoyState m_NewState; #endif wchar m_aActionNames[MAX_CONTROLLERACTIONS][ACTIONNAME_LENGTH]; bool m_aButtonStates[MAX_BUTTONS]; @@ -193,6 +204,6 @@ public: void ResetSettingOrder (e_ControllerAction action); }; -VALIDATE_SIZE(CControllerConfigManager, 0x143C); +//VALIDATE_SIZE(CControllerConfigManager, 0x143C); extern CControllerConfigManager ControlsManager; \ No newline at end of file diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index c7e7d26e..cc076057 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -1,8 +1,11 @@ +#if defined RW_D3D9 || defined RWLIBS #define DIRECTINPUT_VERSION 0x0800 #include -#include "common.h" +#endif -#include "win.h" +#define WITHWINDOWS +#include "common.h" +#include "crossplatform.h" #include "Frontend.h" #include "Font.h" #include "Pad.h" @@ -430,13 +433,16 @@ CMenuManager::BuildStatLine(char *text, void *stat, bool itsFloat, void *stat2) void CMenuManager::CentreMousePointer() { - tagPOINT Point; - if (SCREEN_WIDTH * 0.5f != 0.0f && 0.0f != SCREEN_HEIGHT * 0.5f) { +#if defined RW_D3D9 || defined RWLIBS + tagPOINT Point; Point.x = SCREEN_WIDTH / 2; Point.y = SCREEN_HEIGHT / 2; ClientToScreen(PSGLOBAL(window), &Point); SetCursorPos(Point.x, Point.y); +#elif defined RW_GL3 + glfwSetCursorPos(PSGLOBAL(window), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); +#endif PSGLOBAL(lastMousePos.x) = SCREEN_WIDTH / 2; PSGLOBAL(lastMousePos.y) = SCREEN_HEIGHT / 2; @@ -4474,12 +4480,20 @@ CMenuManager::ProcessButtonPresses(void) ControlsManager.MakeControllerActionsBlank(); ControlsManager.InitDefaultControlConfiguration(); ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); - if (AllValidWinJoys.m_aJoys[0].m_bInitialised) { +#if !defined RW_GL3 + if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { DIDEVCAPS devCaps; devCaps.dwSize = sizeof(DIDEVCAPS); PSGLOBAL(joy1)->GetCapabilities(&devCaps); ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons); } +#else + if (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) { + int count; + glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); + ControlsManager.InitDefaultControlConfigJoyPad(count); + } +#endif m_ControlMethod = CONTROL_STANDARD; MousePointerStateHelper.bInvertVertically = false; TheCamera.m_fMouseAccelHorzntl = 0.0025f; diff --git a/src/core/Game.cpp b/src/core/Game.cpp index f72d342f..8633d222 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -2,7 +2,7 @@ #pragma warning( disable : 4005) #pragma warning( pop ) #include "common.h" -#include "win.h" +#include "crossplatform.h" #include "Game.h" #include "main.h" diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 8a3fc7cb..84bb1526 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -1,10 +1,13 @@ #pragma warning( push ) #pragma warning( disable : 4005) +#if defined RW_D3D9 || defined RWLIBS #define DIRECTINPUT_VERSION 0x0800 #include +#endif #pragma warning( pop ) #include "common.h" +#include "crossplatform.h" #ifdef XINPUT #include #pragma comment( lib, "Xinput9_1_0.lib" ) @@ -29,7 +32,6 @@ #include "Record.h" #include "Replay.h" #include "Weather.h" -#include "win.h" #include "Streaming.h" #include "PathFind.h" #include "Wanted.h" @@ -423,6 +425,7 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() { CMouseControllerState state; +#if defined RW_D3D9 || defined RWLIBS if ( PSGLOBAL(mouse) == nil ) _InputInitialiseMouse(); @@ -432,7 +435,6 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() devCaps.dwSize = sizeof(DIDEVCAPS); PSGLOBAL(mouse)->GetCapabilities(&devCaps); - switch ( devCaps.dwButtons ) { case 3: @@ -456,6 +458,19 @@ CMouseControllerState CMousePointerStateHelper::GetMouseSetUp() state.WHEELUP = true; } } +#else + // It seems there is no way to get number of buttons on mouse, so assign all buttons if we have mouse. + double xpos = 1.0f, ypos; + glfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos); + + if (xpos != NULL) { + state.MMB = true; + state.RMB = true; + state.LMB = true; + state.WHEELDN = true; + state.WHEELUP = true; + } +#endif return state; } @@ -464,6 +479,7 @@ void CPad::UpdateMouse() { if ( IsForegroundApp() ) { +#if defined RW_D3D9 || defined RWLIBS if ( PSGLOBAL(mouse) == nil ) _InputInitialiseMouse(); @@ -500,6 +516,44 @@ void CPad::UpdateMouse() OldMouseControllerState = NewMouseControllerState; NewMouseControllerState = PCTempMouseControllerState; } +#else + double xpos = 1.0f, ypos; + glfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos); + if (xpos == NULL) + return; + + int32 signX = 1; + int32 signy = 1; + + if (!FrontEndMenuManager.m_bMenuActive) + { + if (MousePointerStateHelper.bInvertVertically) + signy = -1; + if (MousePointerStateHelper.bInvertHorizontally) + signX = -1; + } + + PCTempMouseControllerState.Clear(); + + PCTempMouseControllerState.x = (float)(signX * (xpos - PSGLOBAL(lastMousePos.x))); + PCTempMouseControllerState.y = (float)(signy * (ypos - PSGLOBAL(lastMousePos.y))); + PCTempMouseControllerState.LMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_LEFT); + PCTempMouseControllerState.RMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_RIGHT); + PCTempMouseControllerState.MMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_MIDDLE); + PCTempMouseControllerState.MXB1 = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_4); + PCTempMouseControllerState.MXB2 = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_5); + + PSGLOBAL(lastMousePos.x) = xpos; + PSGLOBAL(lastMousePos.y) = ypos; + + if (PSGLOBAL(mouseWheel) > 0) + PCTempMouseControllerState.WHEELUP = 1; + else if (PSGLOBAL(mouseWheel) < 0) + PCTempMouseControllerState.WHEELDN = 1; + + OldMouseControllerState = NewMouseControllerState; + NewMouseControllerState = PCTempMouseControllerState; +#endif } } diff --git a/src/core/common.h b/src/core/common.h index 8b057efa..2cc3d98c 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -11,11 +11,11 @@ #include #include -#ifdef WITHWINDOWS +#if defined _WIN32 && defined WITHWINDOWS #include #endif -#ifdef WITHD3D +#if defined _WIN32 && defined WITHD3D #include #include #endif diff --git a/src/core/config.h b/src/core/config.h index 84712af3..80e2ff19 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -200,7 +200,7 @@ enum Config { //#define PS2_ALTERNATIVE_CARSPLASH // unused on PS2 // Pad -#define XINPUT +// #define XINPUT #define KANGAROO_CHEAT #define REGISTER_START_BUTTON diff --git a/src/core/patcher.cpp b/src/core/patcher.cpp index 58f19767..e5242e9d 100644 --- a/src/core/patcher.cpp +++ b/src/core/patcher.cpp @@ -1,11 +1,10 @@ +#define WITHWINDOWS #include "common.h" #include "patcher.h" #include #include -#include - StaticPatcher *StaticPatcher::ms_head; StaticPatcher::StaticPatcher(Patcher func) diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index c4ff2dd2..3d4ddf5d 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -460,13 +460,17 @@ RwBool RwRenderStateSet(RwRenderState state, void *value) } } - -static EngineOpenParams openParams; // WARNING: unused parameters RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { Engine::init(); return true; } // TODO: this is platform dependent RwBool RwEngineOpen(RwEngineOpenParams *initParams) { +#if defined RW_D3D9 || defined RWLIBS + static EngineOpenParams openParams; openParams.window = (HWND)initParams->displayID; +#else + extern EngineOpenParams openParams; + openParams.window = (GLFWwindow**)initParams->displayID; +#endif return Engine::open(&openParams); } RwBool RwEngineStart(void) { diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp index 707f1b44..ed618dd8 100644 --- a/src/rw/RwHelper.cpp +++ b/src/rw/RwHelper.cpp @@ -1,4 +1,6 @@ +#if defined RW_D3D9 || defined RWLIBS #define WITHD3D +#endif #include "common.h" #include "Timecycle.h" diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index 9f0cae3c..60945665 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -2,7 +2,7 @@ #pragma warning( disable : 4005) #pragma warning( pop ) #include "common.h" -#include "win.h" +#include "crossplatform.h" #include "Timer.h" #ifdef GTA_PC diff --git a/src/rw/TxdStore.cpp b/src/rw/TxdStore.cpp index 51d018f6..bb7386d5 100644 --- a/src/rw/TxdStore.cpp +++ b/src/rw/TxdStore.cpp @@ -127,6 +127,38 @@ CTxdStore::RemoveRefWithoutDelete(int slot) GetSlot(slot)->refCount--; } +#ifdef RW_GL3 +rw::Raster* +convertTexRaster(rw::Raster* ras) +{ + rw::Image* img = ras->toImage(); +// ras->destroy(); + img->unindex(); + ras = rw::Raster::createFromImage(img); + img->destroy(); + return ras; +} + +void +convertTxd(rw::TexDictionary* txd) +{ + rw::Texture* tex; + FORLIST(lnk, txd->textures) { + tex = rw::Texture::fromDict(lnk); + rw::Raster* ras = tex->raster; + if (ras && ras->platform != rw::platform) { + if (!(ras->platform == rw::PLATFORM_D3D8 && rw::platform == rw::PLATFORM_D3D9 || + ras->platform == rw::PLATFORM_D3D9 && rw::platform == rw::PLATFORM_D3D8)) { + tex->raster = convertTexRaster(ras); + ras->destroy(); + } + } + tex->setFilter(rw::Texture::LINEAR); + } + +} +#endif + bool CTxdStore::LoadTxd(int slot, RwStream *stream) { @@ -134,6 +166,9 @@ CTxdStore::LoadTxd(int slot, RwStream *stream) if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)){ def->texDict = RwTexDictionaryGtaStreamRead(stream); +#ifdef RW_GL3 + convertTxd(def->texDict); +#endif return def->texDict != nil; } printf("Failed to load TXD\n"); diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index 1b3ad7d6..342aab4e 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -1,5 +1,61 @@ #include +// This is the common include for platform/renderer specific skeletons(glfw, win etc.) and cross platform things (like Windows directories wrapper, platform specific global arrays etc.) + +// This only has as Win header. +#ifdef _WIN32 +#include "win.h" +#endif + +#ifdef RW_GL3 +typedef struct +{ + GLFWwindow* window; + RwBool fullScreen; + RwV2d lastMousePos; + double mouseWheel; // glfw doesn't cache it + int8 joy1id; + int8 joy2id; +} +psGlobalType; + +#define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var) + +void CapturePad(RwInt32 padID); +void joysChangeCB(int jid, int event); +#endif + +enum eGameState +{ + GS_START_UP = 0, + GS_INIT_LOGO_MPEG, + GS_LOGO_MPEG, + GS_INIT_INTRO_MPEG, + GS_INTRO_MPEG, + GS_INIT_ONCE, + GS_INIT_FRONTEND, + GS_FRONTEND, + GS_INIT_PLAYING_GAME, + GS_PLAYING_GAME, +#ifndef MASTER + GS_ANIMVIEWER, +#endif +}; +extern RwUInt32 gGameState; + +RwBool IsForegroundApp(); +void InitialiseLanguage(); +RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode); + +RwChar** _psGetVideoModeList(); +RwInt32 _psGetNumVideModes(); + +void _psSelectScreenVM(RwInt32 videoMode); +void HandleExit(); +void _InputTranslateShiftKeyUpDown(RsKeyCodes* rs); + +// Mostly wrappers around Windows functions + #ifndef MAX_PATH #if !defined _WIN32 || defined __MINGW32__ #define MAX_PATH PATH_MAX @@ -8,8 +64,6 @@ #endif #endif -// Mostly wrappers around Windows functions - // TODO: Remove USEALTERNATIVEWINFUNCS and don't use it anywhere when re3 becomes fully cross-platform, this is for testing // Codes compatible with Windows and Linux #if defined USEALTERNATIVEWINFUNCS || !defined _WIN32 || defined __MINGW32__ @@ -27,18 +81,13 @@ struct SYSTEMTIME { uint16 wMilliseconds; }; -#define GetLocalTime GetLocalTime_CP -#else -#include -#endif - void GetLocalTime_CP(SYSTEMTIME* out); - +#define GetLocalTime GetLocalTime_CP +#define OutputDebugString(s) re3_debug("[DBG-2]: " s "\n") +#endif // Only runs on GNU/POSIX/etc. #if !defined _WIN32 || defined __MINGW32__ -#define OutputDebugString(s) re3_debug("[DBG-2]: " s "\n") - #include #include #include diff --git a/src/skel/events.cpp b/src/skel/events.cpp index 7116833d..3e1e95b3 100644 --- a/src/skel/events.cpp +++ b/src/skel/events.cpp @@ -1,13 +1,14 @@ -#include "rwcore.h" -#include "skeleton.h" -#include "events.h" - #include "common.h" #include "Pad.h" #include "ControllerConfig.h" #include "Frontend.h" #include "Camera.h" +#include "rwcore.h" +#include "skeleton.h" +#include "events.h" + + /* ***************************************************************************** */ diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp new file mode 100644 index 00000000..0d7dc384 --- /dev/null +++ b/src/skel/glfw/glfw.cpp @@ -0,0 +1,1651 @@ +#if defined RW_GL3 && !defined LIBRW_SDL2 + +#define WITHWINDOWS +#include "common.h" + +#pragma warning( push ) +#pragma warning( disable : 4005) +#pragma warning( pop ) + +#pragma comment( lib, "Winmm.lib" ) // Needed for time + +#if (defined(_MSC_VER)) +#include +#endif /* (defined(_MSC_VER)) */ +#include +#include "rwcore.h" +#include "resource.h" +#include "skeleton.h" +#include "platform.h" +#include "crossplatform.h" + +#define MAX_SUBSYSTEMS (16) + + +using namespace rw; +EngineOpenParams openParams; + +static RwBool ForegroundApp = TRUE; + +static RwBool RwInitialised = FALSE; + +static RwSubSystemInfo GsubSysInfo[MAX_SUBSYSTEMS]; +static RwInt32 GnumSubSystems = 0; +static RwInt32 GcurSel = 0, GcurSelVM = 0; + +static RwBool useDefault; + +static RwBool defaultFullscreenRes = TRUE; + +static psGlobalType PsGlobal; + + +#define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var) + +#undef MAKEPOINTS +#define MAKEPOINTS(l) (*((POINTS /*FAR*/ *)&(l))) + +#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; } +#define JIF(x) if (FAILED(hr=(x))) \ + {debug(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n"), hr); return;} + +#include "patcher.h" +#include "main.h" +#include "FileMgr.h" +#include "Text.h" +#include "Pad.h" +#include "Timer.h" +#include "DMAudio.h" +#include "ControllerConfig.h" +#include "Frontend.h" +#include "Game.h" +#include "PCSave.h" +#include "Sprite2d.h" +#include "AnimViewer.h" + +// TODO: This is used on selecting video mode, so either think something or remove it completely +DWORD _dwMemTotalVideo = 1024 * (1024 * 1024); // 1024 MB as placeholder +DWORD _dwMemAvailPhys; + +DWORD _dwOperatingSystemVersion; + +RwUInt32 gGameState; +/* + ***************************************************************************** + */ +void _psCreateFolder(const char *path) +{ +#ifdef _WIN32 + HANDLE hfle = CreateFile(path, GENERIC_READ, + FILE_SHARE_READ, + nil, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, + nil); + + if ( hfle == INVALID_HANDLE_VALUE ) + CreateDirectory(path, nil); + else + CloseHandle(hfle); +#else + struct stat info; + char fullpath[PATH_MAX]; + realpath(path, fullpath); + + if (lstat(fullpath, &info) != 0) { + if (errno == ENOENT || (errno != EACCES && !S_ISDIR(info.st_mode))) { + mkdir(fullpath, 0755); + } + } +#endif +} + +/* + ***************************************************************************** + */ +const char *_psGetUserFilesFolder() +{ +#if defined USE_MY_DOCUMENTS && defined _WIN32 + HKEY hKey = NULL; + + static CHAR szUserFiles[256]; + + if ( RegOpenKeyEx(HKEY_CURRENT_USER, + REGSTR_PATH_SPECIAL_FOLDERS, + REG_OPTION_RESERVED, + KEY_READ, + &hKey) == ERROR_SUCCESS ) + { + DWORD KeyType; + DWORD KeycbData = sizeof(szUserFiles); + if ( RegQueryValueEx(hKey, + "Personal", + NULL, + &KeyType, + (LPBYTE)szUserFiles, + &KeycbData) == ERROR_SUCCESS ) + { + RegCloseKey(hKey); + strcat(szUserFiles, "\\GTA3 User Files"); + _psCreateFolder(szUserFiles); + return szUserFiles; + } + + RegCloseKey(hKey); + } + + strcpy(szUserFiles, "data"); + return szUserFiles; +#else + static CHAR szUserFiles[256]; + strcpy(szUserFiles, "userfiles"); + _psCreateFolder(szUserFiles); + return szUserFiles; +#endif +} + +/* + ***************************************************************************** + */ +RwBool +psCameraBeginUpdate(RwCamera *camera) +{ + if ( !RwCameraBeginUpdate(Scene.camera) ) + { + ForegroundApp = FALSE; + RsEventHandler(rsACTIVATE, (void *)FALSE); + return FALSE; + } + + return TRUE; +} + +/* + ***************************************************************************** + */ +void +psCameraShowRaster(RwCamera *camera) +{ + if (CMenuManager::m_PrefsVsync) + RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPWAITVSYNC); + else + RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPDONTWAIT); + + return; +} + + +/* + ***************************************************************************** + */ +RwUInt32 +psTimer(void) +{ + RwUInt32 time; + + TIMECAPS TimeCaps; + + timeGetDevCaps(&TimeCaps, sizeof(TIMECAPS)); + + timeBeginPeriod(TimeCaps.wPeriodMin); + + time = (RwUInt32) timeGetTime(); + + timeEndPeriod(TimeCaps.wPeriodMin); + + return time; +} + +/* + ***************************************************************************** + */ +void +psMouseSetPos(RwV2d *pos) +{ + POINT point; + + point.x = (RwInt32) pos->x; + point.y = (RwInt32) pos->y; + + glfwSetCursorPos(PSGLOBAL(window), point.x, point.y); + + PSGLOBAL(lastMousePos.x) = (RwInt32)pos->x; + + PSGLOBAL(lastMousePos.y) = (RwInt32)pos->y; + + return; +} + +/* + ***************************************************************************** + */ +RwMemoryFunctions* +psGetMemoryFunctions(void) +{ + return nil; +} + +/* + ***************************************************************************** + */ +RwBool +psInstallFileSystem(void) +{ + return (TRUE); +} + + +/* + ***************************************************************************** + */ +RwBool +psNativeTextureSupport(void) +{ + return true; +} + +/* + ***************************************************************************** + */ +static char cpuvendor[16] = "UnknownVendr"; +__declspec(naked) const char * _psGetCpuVendr() +{ + __asm + { + push ebx + xor eax, eax + cpuid + mov dword ptr [cpuvendor+0], ebx + mov dword ptr [cpuvendor+4], edx + mov dword ptr [cpuvendor+8], ecx + mov eax, offset cpuvendor + pop ebx + retn + } +} + +/* + ***************************************************************************** + */ +__declspec(naked) RwUInt32 _psGetCpuFeatures() +{ + __asm + { + mov eax, 1 + cpuid + mov eax, edx + retn + } +} + +/* + ***************************************************************************** + */ +__declspec(naked) RwUInt32 _psGetCpuFeaturesEx() +{ + __asm + { + mov eax, 80000000h + cpuid + + cmp eax, 80000000h + jbe short _NOEX + + mov eax, 80000001h + cpuid + + mov eax, edx + jmp short _RETEX + +_NOEX: + xor eax, eax + mov eax, eax + +_RETEX: + retn + } +} + +void _psPrintCpuInfo() +{ + RwUInt32 features = _psGetCpuFeatures(); + RwUInt32 FeaturesEx = _psGetCpuFeaturesEx(); + + debug("Running on a %s", _psGetCpuVendr()); + + if ( features & 0x800000 ) + debug("with MMX"); + if ( features & 0x2000000 ) + debug("with SSE"); + if ( FeaturesEx & 0x80000000 ) + debug("with 3DNow"); +} + +/* + ***************************************************************************** + */ +#ifdef UNDER_CE +#define CMDSTR LPWSTR +#else +#define CMDSTR LPSTR +#endif + +/* + ***************************************************************************** + */ +RwBool +psInitialise(void) +{ + PsGlobal.lastMousePos.x = PsGlobal.lastMousePos.y = 0.0f; + + RsGlobal.ps = &PsGlobal; + + PsGlobal.fullScreen = FALSE; + + PsGlobal.joy1id = -1; + PsGlobal.joy2id = -1; + + CFileMgr::Initialise(); + + C_PcSave::SetSaveDirectory(_psGetUserFilesFolder()); + + InitialiseLanguage(); + + FrontEndMenuManager.LoadSettings(); + + gGameState = GS_START_UP; + TRACE("gGameState = GS_START_UP"); + + _psPrintCpuInfo(); + + OSVERSIONINFO verInfo; + verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&verInfo); + + _dwOperatingSystemVersion = OS_WIN95; + + if ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) + { + if ( verInfo.dwMajorVersion == 4 ) + { + debug("Operating System is WinNT\n"); + _dwOperatingSystemVersion = OS_WINNT; + } + else if ( verInfo.dwMajorVersion == 5 ) + { + debug("Operating System is Win2000\n"); + _dwOperatingSystemVersion = OS_WIN2000; + } + else if ( verInfo.dwMajorVersion > 5 ) + { + debug("Operating System is WinXP or greater\n"); + _dwOperatingSystemVersion = OS_WINXP; + } + } + else if ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) + { + if ( verInfo.dwMajorVersion > 4 || verInfo.dwMajorVersion == 4 && verInfo.dwMinorVersion == 1 ) + { + debug("Operating System is Win98\n"); + _dwOperatingSystemVersion = OS_WIN98; + } + else + { + debug("Operating System is Win95\n"); + _dwOperatingSystemVersion = OS_WIN95; + } + } + + MEMORYSTATUS memstats; + GlobalMemoryStatus(&memstats); + + _dwMemAvailPhys = memstats.dwAvailPhys; + +#ifdef FIX_BUGS + debug("Physical memory size %u\n", memstats.dwTotalPhys); + debug("Available physical memory %u\n", memstats.dwAvailPhys); +#else + debug("Physical memory size %d\n", memstats.dwTotalPhys); + debug("Available physical memory %d\n", memstats.dwAvailPhys); +#endif + + TheText.Unload(); + + return TRUE; +} + + +/* + ***************************************************************************** + */ +void +psTerminate(void) +{ + return; +} + +/* + ***************************************************************************** + */ +static RwChar **_VMList; + +RwInt32 _psGetNumVideModes() +{ + return RwEngineGetNumVideoModes(); +} + +/* + ***************************************************************************** + */ +RwBool _psFreeVideoModeList() +{ + RwInt32 numModes; + RwInt32 i; + + numModes = _psGetNumVideModes(); + + if ( _VMList == nil ) + return TRUE; + + for ( i = 0; i < numModes; i++ ) + { + RwFree(_VMList[i]); + } + + RwFree(_VMList); + + _VMList = nil; + + return TRUE; +} + +/* + ***************************************************************************** + */ +RwChar **_psGetVideoModeList() +{ + RwInt32 numModes; + RwInt32 i; + + if ( _VMList != nil ) + { + return _VMList; + } + + numModes = RwEngineGetNumVideoModes(); + + _VMList = (RwChar **)RwCalloc(numModes, sizeof(RwChar*)); + + for ( i = 0; i < numModes; i++ ) + { + RwVideoMode vm; + + RwEngineGetVideoModeInfo(&vm, i); + + if ( vm.flags & rwVIDEOMODEEXCLUSIVE ) + { + if ( vm.width >= 640 + && vm.height >= 480 + && (vm.width == 640 + && vm.height == 480) + || !(vm.flags & rwVIDEOMODEEXCLUSIVE) + || (_dwMemTotalVideo - vm.depth * vm.height * vm.width / 8) > (12 * 1024 * 1024)/*12 MB*/ ) + { + _VMList[i] = (RwChar*)RwCalloc(100, sizeof(RwChar)); + rwsprintf(_VMList[i],"%lu X %lu X %lu", vm.width, vm.height, vm.depth); + } + else + _VMList[i] = nil; + } + else + _VMList[i] = nil; + } + + return _VMList; +} + +/* + ***************************************************************************** + */ +void _psSelectScreenVM(RwInt32 videoMode) +{ + RwTexDictionarySetCurrent( nil ); + + FrontEndMenuManager.UnloadTextures(); + + if ( !_psSetVideoMode(RwEngineGetCurrentSubSystem(), videoMode) ) + { + RsGlobal.quit = TRUE; + } + else + FrontEndMenuManager.LoadAllTextures(); +} + +/* + ***************************************************************************** + */ + +RwBool IsForegroundApp() +{ + return !!ForegroundApp; +} +/* +UINT GetBestRefreshRate(UINT width, UINT height, UINT depth) +{ + LPDIRECT3D8 d3d = Direct3DCreate8(D3D_SDK_VERSION); + + ASSERT(d3d != nil); + + UINT refreshRate = INT_MAX; + D3DFORMAT format; + + if ( depth == 32 ) + format = D3DFMT_X8R8G8B8; + else if ( depth == 24 ) + format = D3DFMT_R8G8B8; + else + format = D3DFMT_R5G6B5; + + UINT modeCount = d3d->GetAdapterModeCount(GcurSel); + + for ( UINT i = 0; i < modeCount; i++ ) + { + D3DDISPLAYMODE mode; + + d3d->EnumAdapterModes(GcurSel, i, &mode); + + if ( mode.Width == width && mode.Height == height && mode.Format == format ) + { + if ( mode.RefreshRate == 0 ) + return 0; + + if ( mode.RefreshRate < refreshRate && mode.RefreshRate >= 60 ) + refreshRate = mode.RefreshRate; + } + } + +#ifdef FIX_BUGS + d3d->Release(); +#endif + + if ( refreshRate == -1 ) + return -1; + + return refreshRate; +} +*/ +/* + ***************************************************************************** + */ +RwBool +psSelectDevice() +{ + RwVideoMode vm; + RwInt32 subSysNum; + RwInt32 AutoRenderer = 0; + + + RwBool modeFound = FALSE; + + if ( !useDefault ) + { + GnumSubSystems = RwEngineGetNumSubSystems(); + if ( !GnumSubSystems ) + { + return FALSE; + } + + /* Just to be sure ... */ + GnumSubSystems = (GnumSubSystems > MAX_SUBSYSTEMS) ? MAX_SUBSYSTEMS : GnumSubSystems; + + /* Get the names of all the sub systems */ + for (subSysNum = 0; subSysNum < GnumSubSystems; subSysNum++) + { + RwEngineGetSubSystemInfo(&GsubSysInfo[subSysNum], subSysNum); + } + + /* Get the default selection */ + GcurSel = RwEngineGetCurrentSubSystem(); + } + + /* Set the driver to use the correct sub system */ + if (!RwEngineSetSubSystem(GcurSel)) + { + return FALSE; + } + + + if ( !useDefault ) + { + if ( _psGetVideoModeList()[FrontEndMenuManager.m_nDisplayVideoMode] && FrontEndMenuManager.m_nDisplayVideoMode ) + { + FrontEndMenuManager.m_nPrefsVideoMode = FrontEndMenuManager.m_nDisplayVideoMode; + GcurSelVM = FrontEndMenuManager.m_nDisplayVideoMode; + } + else + { +#ifdef DEFAULT_NATIVE_RESOLUTION + // get the native video mode + HDC hDevice = GetDC(NULL); + int w = GetDeviceCaps(hDevice, HORZRES); + int h = GetDeviceCaps(hDevice, VERTRES); + int d = GetDeviceCaps(hDevice, BITSPIXEL); +#else + const int w = 640; + const int h = 480; + const int d = 16; +#endif + while ( !modeFound && GcurSelVM < RwEngineGetNumVideoModes() ) + { + RwEngineGetVideoModeInfo(&vm, GcurSelVM); + if ( defaultFullscreenRes && vm.width != w + || vm.height != h + || vm.depth != d + || !(vm.flags & rwVIDEOMODEEXCLUSIVE) ) + ++GcurSelVM; + else + modeFound = TRUE; + } + + if ( !modeFound ) + { +#ifdef DEFAULT_NATIVE_RESOLUTION + GcurSelVM = 1; +#else + MessageBox(nil, "Cannot find 640x480 video mode", "GTA3", MB_OK); + return FALSE; +#endif + } + } + } + + RwEngineGetVideoModeInfo(&vm, GcurSelVM); + + FrontEndMenuManager.m_nCurrOption = 0; + + /* Set up the video mode and set the apps window + * dimensions to match */ + if (!RwEngineSetVideoMode(GcurSelVM)) + { + return FALSE; + } + /* + TODO + if (vm.flags & rwVIDEOMODEEXCLUSIVE) + { + debug("%dx%dx%d", vm.width, vm.height, vm.depth); + + UINT refresh = GetBestRefreshRate(vm.width, vm.height, vm.depth); + + if ( refresh != (UINT)-1 ) + { + debug("refresh %d", refresh); + RwD3D8EngineSetRefreshRate((RwUInt32)refresh); + } + } + */ + if (vm.flags & rwVIDEOMODEEXCLUSIVE) + { + RsGlobal.maximumWidth = vm.width; + RsGlobal.maximumHeight = vm.height; + RsGlobal.width = vm.width; + RsGlobal.height = vm.height; + + PSGLOBAL(fullScreen) = TRUE; + } + + return TRUE; +} + +/* + ***************************************************************************** + */ +RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode) +{ + RwInitialised = FALSE; + + RsEventHandler(rsRWTERMINATE, nil); + + GcurSel = subSystem; + GcurSelVM = videoMode; + + useDefault = TRUE; + + if ( RsEventHandler(rsRWINITIALISE, &PSGLOBAL(window)) == rsEVENTERROR ) + return FALSE; + + RwInitialised = TRUE; + useDefault = FALSE; + + RwRect r; + + r.x = 0; + r.y = 0; + r.w = RsGlobal.maximumWidth; + r.h = RsGlobal.maximumHeight; + + RsEventHandler(rsCAMERASIZE, &r); + + return TRUE; +} + + +/* + ***************************************************************************** + */ +static RwChar ** +CommandLineToArgv(RwChar *cmdLine, RwInt32 *argCount) +{ + RwInt32 numArgs = 0; + RwBool inArg, inString; + RwInt32 i, len; + RwChar *res, *str, **aptr; + + len = strlen(cmdLine); + + /* + * Count the number of arguments... + */ + inString = FALSE; + inArg = FALSE; + + for(i=0; i<=len; i++) + { + if( cmdLine[i] == '"' ) + { + inString = !inString; + } + + if( (cmdLine[i] <= ' ' && !inString) || i == len ) + { + if( inArg ) + { + inArg = FALSE; + + numArgs++; + } + } + else if( !inArg ) + { + inArg = TRUE; + } + } + + /* + * Allocate memory for result... + */ + res = (RwChar *)malloc(sizeof(RwChar *) * numArgs + len + 1); + str = res + sizeof(RwChar *) * numArgs; + aptr = (RwChar **)res; + + strcpy(str, cmdLine); + + /* + * Walk through cmdLine again this time setting pointer to each arg... + */ + inArg = FALSE; + inString = FALSE; + + for(i=0; i<=len; i++) + { + if( cmdLine[i] == '"' ) + { + inString = !inString; + } + + if( (cmdLine[i] <= ' ' && !inString) || i == len ) + { + if( inArg ) + { + if( str[i-1] == '"' ) + { + str[i-1] = '\0'; + } + else + { + str[i] = '\0'; + } + + inArg = FALSE; + } + } + else if( !inArg && cmdLine[i] != '"' ) + { + inArg = TRUE; + + *aptr++ = &str[i]; + } + } + + *argCount = numArgs; + + return (RwChar **)res; +} + +/* + ***************************************************************************** + */ +void InitialiseLanguage() +{ + WORD primUserLCID = PRIMARYLANGID(GetSystemDefaultLCID()); + WORD primSystemLCID = PRIMARYLANGID(GetUserDefaultLCID()); + WORD primLayout = PRIMARYLANGID((DWORD)GetKeyboardLayout(0)); + + WORD subUserLCID = SUBLANGID(GetSystemDefaultLCID()); + WORD subSystemLCID = SUBLANGID(GetUserDefaultLCID()); + WORD subLayout = SUBLANGID((DWORD)GetKeyboardLayout(0)); + + if ( primUserLCID == LANG_GERMAN + || primSystemLCID == LANG_GERMAN + || primLayout == LANG_GERMAN ) + { + CGame::nastyGame = false; + CMenuManager::m_PrefsAllowNastyGame = false; + CGame::germanGame = true; + } + + if ( primUserLCID == LANG_FRENCH + || primSystemLCID == LANG_FRENCH + || primLayout == LANG_FRENCH ) + { + CGame::nastyGame = false; + CMenuManager::m_PrefsAllowNastyGame = false; + CGame::frenchGame = true; + } + + if ( subUserLCID == SUBLANG_ENGLISH_AUS + || subSystemLCID == SUBLANG_ENGLISH_AUS + || subLayout == SUBLANG_ENGLISH_AUS ) + CGame::noProstitutes = true; + +#ifdef NASTY_GAME + CGame::nastyGame = true; + CMenuManager::m_PrefsAllowNastyGame = true; + CGame::noProstitutes = false; +#endif + + int32 lang; + + switch ( primSystemLCID ) + { + case LANG_GERMAN: + { + lang = LANG_GERMAN; + break; + } + case LANG_FRENCH: + { + lang = LANG_FRENCH; + break; + } + case LANG_SPANISH: + { + lang = LANG_SPANISH; + break; + } + case LANG_ITALIAN: + { + lang = LANG_ITALIAN; + break; + } + default: + { + lang = ( subSystemLCID == SUBLANG_ENGLISH_AUS ) ? -99 : LANG_ENGLISH; + break; + } + } + + CMenuManager::OS_Language = primUserLCID; + + switch ( lang ) + { + case LANG_GERMAN: + { + CMenuManager::m_PrefsLanguage = LANGUAGE_GERMAN; + break; + } + case LANG_SPANISH: + { + CMenuManager::m_PrefsLanguage = LANGUAGE_SPANISH; + break; + } + case LANG_FRENCH: + { + CMenuManager::m_PrefsLanguage = LANGUAGE_FRENCH; + break; + } + case LANG_ITALIAN: + { + CMenuManager::m_PrefsLanguage = LANGUAGE_ITALIAN; + break; + } + default: + { + CMenuManager::m_PrefsLanguage = LANGUAGE_AMERICAN; + break; + } + } + + TheText.Unload(); + TheText.Load(); +} + +/* + ***************************************************************************** + */ +void HandleExit() +{ + MSG message; + while ( PeekMessage(&message, nil, 0U, 0U, PM_REMOVE|PM_NOYIELD) ) + { + if( message.message == WM_QUIT ) + { + RsGlobal.quit = TRUE; + } + else + { + TranslateMessage(&message); + DispatchMessage(&message); + } + } +} + +void resizeCB(GLFWwindow* window, int width, int height) { + /* + * Handle event to ensure window contents are displayed during re-size + * as this can be disabled by the user, then if there is not enough + * memory things don't work. + */ + /* redraw window */ + if (RwInitialised && (gGameState == GS_PLAYING_GAME || gGameState == GS_ANIMVIEWER)) + { + RsEventHandler((gGameState == GS_PLAYING_GAME ? rsIDLE : rsANIMVIEWER), (void*)TRUE); + } + + if (RwInitialised && height > 0 && width > 0) { + RwRect r; + + r.x = 0; + r.y = 0; + r.w = RsGlobal.maximumWidth; + r.h = RsGlobal.maximumHeight; + + RsEventHandler(rsCAMERASIZE, &r); + } + glfwSetWindowPos(window, 0, 0); +} + +void scrollCB(GLFWwindow* window, double xoffset, double yoffset) { + PSGLOBAL(mouseWheel) = yoffset; +} + +int keymap[GLFW_KEY_LAST + 1]; + +static void +initkeymap(void) +{ + int i; + for (i = 0; i < GLFW_KEY_LAST + 1; i++) + keymap[i] = rsNULL; + + keymap[GLFW_KEY_SPACE] = ' '; + keymap[GLFW_KEY_APOSTROPHE] = '\''; + keymap[GLFW_KEY_COMMA] = ','; + keymap[GLFW_KEY_MINUS] = '-'; + keymap[GLFW_KEY_PERIOD] = '.'; + keymap[GLFW_KEY_SLASH] = '/'; + keymap[GLFW_KEY_0] = '0'; + keymap[GLFW_KEY_1] = '1'; + keymap[GLFW_KEY_2] = '2'; + keymap[GLFW_KEY_3] = '3'; + keymap[GLFW_KEY_4] = '4'; + keymap[GLFW_KEY_5] = '5'; + keymap[GLFW_KEY_6] = '6'; + keymap[GLFW_KEY_7] = '7'; + keymap[GLFW_KEY_8] = '8'; + keymap[GLFW_KEY_9] = '9'; + keymap[GLFW_KEY_SEMICOLON] = ';'; + keymap[GLFW_KEY_EQUAL] = '='; + keymap[GLFW_KEY_A] = 'A'; + keymap[GLFW_KEY_B] = 'B'; + keymap[GLFW_KEY_C] = 'C'; + keymap[GLFW_KEY_D] = 'D'; + keymap[GLFW_KEY_E] = 'E'; + keymap[GLFW_KEY_F] = 'F'; + keymap[GLFW_KEY_G] = 'G'; + keymap[GLFW_KEY_H] = 'H'; + keymap[GLFW_KEY_I] = 'I'; + keymap[GLFW_KEY_J] = 'J'; + keymap[GLFW_KEY_K] = 'K'; + keymap[GLFW_KEY_L] = 'L'; + keymap[GLFW_KEY_M] = 'M'; + keymap[GLFW_KEY_N] = 'N'; + keymap[GLFW_KEY_O] = 'O'; + keymap[GLFW_KEY_P] = 'P'; + keymap[GLFW_KEY_Q] = 'Q'; + keymap[GLFW_KEY_R] = 'R'; + keymap[GLFW_KEY_S] = 'S'; + keymap[GLFW_KEY_T] = 'T'; + keymap[GLFW_KEY_U] = 'U'; + keymap[GLFW_KEY_V] = 'V'; + keymap[GLFW_KEY_W] = 'W'; + keymap[GLFW_KEY_X] = 'X'; + keymap[GLFW_KEY_Y] = 'Y'; + keymap[GLFW_KEY_Z] = 'Z'; + keymap[GLFW_KEY_LEFT_BRACKET] = '['; + keymap[GLFW_KEY_BACKSLASH] = '\\'; + keymap[GLFW_KEY_RIGHT_BRACKET] = ']'; + keymap[GLFW_KEY_GRAVE_ACCENT] = '`'; + keymap[GLFW_KEY_ESCAPE] = rsESC; + keymap[GLFW_KEY_ENTER] = rsENTER; + keymap[GLFW_KEY_TAB] = rsTAB; + keymap[GLFW_KEY_BACKSPACE] = rsBACKSP; + keymap[GLFW_KEY_INSERT] = rsINS; + keymap[GLFW_KEY_DELETE] = rsDEL; + keymap[GLFW_KEY_RIGHT] = rsRIGHT; + keymap[GLFW_KEY_LEFT] = rsLEFT; + keymap[GLFW_KEY_DOWN] = rsDOWN; + keymap[GLFW_KEY_UP] = rsUP; + keymap[GLFW_KEY_PAGE_UP] = rsPGUP; + keymap[GLFW_KEY_PAGE_DOWN] = rsPGDN; + keymap[GLFW_KEY_HOME] = rsHOME; + keymap[GLFW_KEY_END] = rsEND; + keymap[GLFW_KEY_CAPS_LOCK] = rsCAPSLK; + keymap[GLFW_KEY_SCROLL_LOCK] = rsSCROLL; + keymap[GLFW_KEY_NUM_LOCK] = rsNUMLOCK; + keymap[GLFW_KEY_PRINT_SCREEN] = rsNULL; + keymap[GLFW_KEY_PAUSE] = rsPAUSE; + + keymap[GLFW_KEY_F1] = rsF1; + keymap[GLFW_KEY_F2] = rsF2; + keymap[GLFW_KEY_F3] = rsF3; + keymap[GLFW_KEY_F4] = rsF4; + keymap[GLFW_KEY_F5] = rsF5; + keymap[GLFW_KEY_F6] = rsF6; + keymap[GLFW_KEY_F7] = rsF7; + keymap[GLFW_KEY_F8] = rsF8; + keymap[GLFW_KEY_F9] = rsF9; + keymap[GLFW_KEY_F10] = rsF10; + keymap[GLFW_KEY_F11] = rsF11; + keymap[GLFW_KEY_F12] = rsF12; + keymap[GLFW_KEY_F13] = rsNULL; + keymap[GLFW_KEY_F14] = rsNULL; + keymap[GLFW_KEY_F15] = rsNULL; + keymap[GLFW_KEY_F16] = rsNULL; + keymap[GLFW_KEY_F17] = rsNULL; + keymap[GLFW_KEY_F18] = rsNULL; + keymap[GLFW_KEY_F19] = rsNULL; + keymap[GLFW_KEY_F20] = rsNULL; + keymap[GLFW_KEY_F21] = rsNULL; + keymap[GLFW_KEY_F22] = rsNULL; + keymap[GLFW_KEY_F23] = rsNULL; + keymap[GLFW_KEY_F24] = rsNULL; + keymap[GLFW_KEY_F25] = rsNULL; + keymap[GLFW_KEY_KP_0] = rsPADINS; + keymap[GLFW_KEY_KP_1] = rsPADEND; + keymap[GLFW_KEY_KP_2] = rsPADDOWN; + keymap[GLFW_KEY_KP_3] = rsPADPGDN; + keymap[GLFW_KEY_KP_4] = rsPADLEFT; + keymap[GLFW_KEY_KP_5] = rsPAD5; + keymap[GLFW_KEY_KP_6] = rsPADRIGHT; + keymap[GLFW_KEY_KP_7] = rsPADHOME; + keymap[GLFW_KEY_KP_8] = rsPADUP; + keymap[GLFW_KEY_KP_9] = rsPADPGUP; + keymap[GLFW_KEY_KP_DECIMAL] = rsPADDEL; + keymap[GLFW_KEY_KP_DIVIDE] = rsDIVIDE; + keymap[GLFW_KEY_KP_MULTIPLY] = rsTIMES; + keymap[GLFW_KEY_KP_SUBTRACT] = rsMINUS; + keymap[GLFW_KEY_KP_ADD] = rsPLUS; + keymap[GLFW_KEY_KP_ENTER] = rsPADENTER; + keymap[GLFW_KEY_KP_EQUAL] = rsNULL; + keymap[GLFW_KEY_LEFT_SHIFT] = rsLSHIFT; + keymap[GLFW_KEY_LEFT_CONTROL] = rsLCTRL; + keymap[GLFW_KEY_LEFT_ALT] = rsLALT; + keymap[GLFW_KEY_LEFT_SUPER] = rsLWIN; + keymap[GLFW_KEY_RIGHT_SHIFT] = rsRSHIFT; + keymap[GLFW_KEY_RIGHT_CONTROL] = rsRCTRL; + keymap[GLFW_KEY_RIGHT_ALT] = rsRALT; + keymap[GLFW_KEY_RIGHT_SUPER] = rsRWIN; + keymap[GLFW_KEY_MENU] = rsNULL; +} + +bool lshiftStatus = false; +bool rshiftStatus = false; + +void +keypressCB(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (key >= 0 && key <= GLFW_KEY_LAST) { + RsKeyCodes ks = (RsKeyCodes)keymap[key]; + + if (key == GLFW_KEY_LEFT_SHIFT) + lshiftStatus = action != GLFW_RELEASE; + + if (key == GLFW_KEY_RIGHT_SHIFT) + rshiftStatus = action != GLFW_RELEASE; + + if (action == GLFW_RELEASE) RsKeyboardEventHandler(rsKEYUP, &ks); + else if (action == GLFW_PRESS) RsKeyboardEventHandler(rsKEYDOWN, &ks); + else if (action == GLFW_REPEAT) RsKeyboardEventHandler(rsKEYDOWN, &ks); + } +} + +// R* calls that in ControllerConfig, idk why +void +_InputTranslateShiftKeyUpDown(RsKeyCodes *rs) { + RsKeyboardEventHandler(lshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsLSHIFT)); + RsKeyboardEventHandler(rshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsRSHIFT)); +} + +// TODO this only works in frontend(and luckily only frontend use this), maybe because of glfw knows that mouse pos is > 32000 in game?? +void +cursorCB(GLFWwindow* window, double xpos, double ypos) { + FrontEndMenuManager.m_nMouseTempPosX = xpos; + FrontEndMenuManager.m_nMouseTempPosY = ypos; +} + +void _InputInitialiseJoys() +{ + for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { + if (glfwJoystickPresent(i)) { + if (PSGLOBAL(joy1id) == -1) + PSGLOBAL(joy1id) = i; + else if (PSGLOBAL(joy2id) == -1) + PSGLOBAL(joy2id) = i; + else + break; + } + } + + if (PSGLOBAL(joy1id) != -1) { + int count; + glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); + ControlsManager.InitDefaultControlConfigJoyPad(count); + } +} + +void _InputInitialiseMouse() +{ + glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); +} + +/* + ***************************************************************************** + */ +int PASCAL +WinMain(HINSTANCE instance, + HINSTANCE prevInstance __RWUNUSED__, + CMDSTR cmdLine, + int cmdShow) +{ + RwV2d pos; + RwInt32 argc, i; + RwChar** argv; + StaticPatcher::Apply(); + SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE); + + /* + * Initialize the platform independent data. + * This will in turn initialize the platform specific data... + */ + if( RsEventHandler(rsINITIALISE, nil) == rsEVENTERROR ) + { + return FALSE; + } + + + /* + * Get proper command line params, cmdLine passed to us does not + * work properly under all circumstances... + */ + cmdLine = GetCommandLine(); + + /* + * Parse command line into standard (argv, argc) parameters... + */ + argv = CommandLineToArgv(cmdLine, &argc); + + + /* + * Parse command line parameters (except program name) one at + * a time BEFORE RenderWare initialization... + */ + for(i=1; i -0.8f; + ControlsManager.m_NewState.mappedButtons[16] = gamepadState.axes[5] > -0.8f; + } + // TODO I'm not sure how to find/what to do with L2-R2, if joystick isn't registered in SDL database. + + if (ControlsManager.m_bFirstCapture == true) { + memcpy(&ControlsManager.m_OldState, &ControlsManager.m_NewState, sizeof(ControlsManager.m_NewState)); + + ControlsManager.m_bFirstCapture = false; + } + + RsPadButtonStatus bs; + bs.padID = padID; + + RsPadEventHandler(rsPADBUTTONUP, (void *)&bs); + + // Gamepad axes are guaranteed to return 0.0f if that particular gamepad doesn't have that axis. + if ( glfwPad != -1 ) { + leftStickPos.x = ControlsManager.m_NewState.isGamepad ? gamepadState.axes[0] : numAxes >= 0 ? axes[0] : 0.0f; + leftStickPos.y = ControlsManager.m_NewState.isGamepad ? gamepadState.axes[1] : numAxes >= 1 ? axes[1] : 0.0f; + + rightStickPos.x = ControlsManager.m_NewState.isGamepad ? gamepadState.axes[2] : numAxes >= 2 ? axes[2] : 0.0f; + rightStickPos.y = ControlsManager.m_NewState.isGamepad ? gamepadState.axes[3] : numAxes >= 3 ? axes[3] : 0.0f; + } + + { + if (CPad::m_bMapPadOneToPadTwo) + bs.padID = 1; + + RsPadEventHandler(rsPADBUTTONUP, (void *)&bs); + RsPadEventHandler(rsPADBUTTONDOWN, (void *)&bs); + } + + { + if (CPad::m_bMapPadOneToPadTwo) + bs.padID = 1; + + CPad *pad = CPad::GetPad(bs.padID); + + if ( Abs(leftStickPos.x) > 0.3f ) + pad->PCTempJoyState.LeftStickX = (int32)(leftStickPos.x * 128.0f); + + if ( Abs(leftStickPos.y) > 0.3f ) + pad->PCTempJoyState.LeftStickY = (int32)(leftStickPos.y * 128.0f); + + if ( Abs(rightStickPos.x) > 0.3f ) + pad->PCTempJoyState.RightStickX = (int32)(rightStickPos.x * 128.0f); + + if ( Abs(rightStickPos.y) > 0.3f ) + pad->PCTempJoyState.RightStickY = (int32)(rightStickPos.y * 128.0f); + } + + return; +} + +void joysChangeCB(int jid, int event) +{ + if (event == GLFW_CONNECTED) + { + if (PSGLOBAL(joy1id) == -1) + PSGLOBAL(joy1id) = jid; + else if (PSGLOBAL(joy2id) == -1) + PSGLOBAL(joy2id) = jid; + } + else if (event == GLFW_DISCONNECTED) + { + if (PSGLOBAL(joy1id) == jid) + PSGLOBAL(joy1id) = -1; + else if (PSGLOBAL(joy2id) == jid) + PSGLOBAL(joy2id) = -1; + } +} + +#if (defined(_MSC_VER)) +int strcasecmp(const char* str1, const char* str2) +{ + return _strcmpi(str1, str2); +} +#endif +#endif \ No newline at end of file diff --git a/src/skel/skeleton.cpp b/src/skel/skeleton.cpp index f48089cb..b5ce744a 100644 --- a/src/skel/skeleton.cpp +++ b/src/skel/skeleton.cpp @@ -293,7 +293,7 @@ RwBool RsRwInitialise(void *displayID) { RwEngineOpenParams openParams; - + /* * Start RenderWare... */ diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp index cde9f9e5..e623defb 100644 --- a/src/skel/win/win.cpp +++ b/src/skel/win/win.cpp @@ -1,3 +1,5 @@ +#if defined RW_D3D9 || defined RWLIBS + #define _WIN32_WINDOWS 0x0500 #define WINVER 0x0500 #define DIRECTINPUT_VERSION 0x0800 @@ -40,7 +42,7 @@ #include "resource.h" #include "skeleton.h" #include "platform.h" -#include "win.h" +#include "crossplatform.h" #define MAX_SUBSYSTEMS (16) @@ -3033,3 +3035,4 @@ int strcasecmp(const char *str1, const char *str2) return _strcmpi(str1, str2); } #endif +#endif \ No newline at end of file diff --git a/src/skel/win/win.h b/src/skel/win/win.h index d6326294..0e63502e 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -1,3 +1,6 @@ + +// DON'T include directly. crossplatform.h includes this if you're on Windows. + #if (!defined(_PLATFORM_WIN_H)) #define _PLATFORM_WIN_H @@ -10,23 +13,6 @@ #include #endif -enum eGameState -{ - GS_START_UP = 0, - GS_INIT_LOGO_MPEG, - GS_LOGO_MPEG, - GS_INIT_INTRO_MPEG, - GS_INTRO_MPEG, - GS_INIT_ONCE, - GS_INIT_FRONTEND, - GS_FRONTEND, - GS_INIT_PLAYING_GAME, - GS_PLAYING_GAME, -#ifndef MASTER - GS_ANIMVIEWER, -#endif -}; - enum eWinVersion { OS_WIN95 = 0, @@ -38,8 +24,6 @@ enum eWinVersion extern DWORD _dwOperatingSystemVersion; -extern RwUInt32 gGameState; - #ifdef __DINPUT_INCLUDED__ /* platform specfic global data */ typedef struct @@ -101,12 +85,10 @@ extern "C" { #endif /* __cplusplus */ +#ifdef __DINPUT_INCLUDED__ extern LRESULT CALLBACK MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam); -RwBool IsForegroundApp(); - -#ifdef __DINPUT_INCLUDED__ HRESULT _InputInitialise(); HRESULT _InputInitialiseMouse(); HRESULT CapturePad(RwInt32 padID); @@ -117,26 +99,15 @@ HRESULT _InputGetMouseState(DIMOUSESTATE2 *state); void _InputShutdown(); BOOL CALLBACK _InputEnumDevicesCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ); BOOL _InputTranslateKey(RsKeyCodes *rs, UINT flag, UINT key); -void _InputTranslateShiftKeyUpDown(RsKeyCodes *rs);; BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown); BOOL _InputIsExtended(INT flag); #endif -void InitialiseLanguage(); -RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode); void CenterVideo(void); void CloseClip(void); -RwChar **_psGetVideoModeList(); -RwInt32 _psGetNumVideModes(); - -void _psSelectScreenVM(RwInt32 videoMode); -void HandleExit(); - #ifdef __cplusplus } #endif /* __cplusplus */ - -extern DWORD _dwOperatingSystemVersion; #endif /* (!defined(_PLATFORM_WIN_H)) */ diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp index 3233ebc4..5abaa7ae 100644 --- a/src/text/Messages.cpp +++ b/src/text/Messages.cpp @@ -1,6 +1,3 @@ -#define DIRECTINPUT_VERSION 0x0800 -#include "dinput.h" - #include "common.h" #include "Messages.h" diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index d31182cd..b93ab35e 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -707,13 +707,13 @@ CBoat::Render() ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->SetVehicleColour(m_currentColour1, m_currentColour2); if (!CVehicle::bWheelsOnlyCheat) CEntity::Render(); - KeepWaterOutVertices[0].color = -1; + KeepWaterOutVertices[0].setColor(255, 255, 255, 255); KeepWaterOutIndices[0] = 0; - KeepWaterOutVertices[1].color = -1; + KeepWaterOutVertices[1].setColor(255, 255, 255, 255); KeepWaterOutIndices[1] = 2; - KeepWaterOutVertices[2].color = -1; + KeepWaterOutVertices[2].setColor(255, 255, 255, 255); KeepWaterOutIndices[2] = 1; - KeepWaterOutVertices[3].color = -1; + KeepWaterOutVertices[3].setColor(255, 255, 255, 255); KeepWaterOutIndices[3] = 1; KeepWaterOutIndices[4] = 2; KeepWaterOutIndices[5] = 3; From 4f763cba4901ed20e46e8ff15106c23574374777 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 26 Apr 2020 13:59:06 +0300 Subject: [PATCH 118/123] Fix compilation error --- src/vehicles/Boat.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index b93ab35e..14eb2f05 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -707,13 +707,13 @@ CBoat::Render() ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->SetVehicleColour(m_currentColour1, m_currentColour2); if (!CVehicle::bWheelsOnlyCheat) CEntity::Render(); - KeepWaterOutVertices[0].setColor(255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[0], 255, 255, 255, 255); KeepWaterOutIndices[0] = 0; - KeepWaterOutVertices[1].setColor(255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[1], 255, 255, 255, 255); KeepWaterOutIndices[1] = 2; - KeepWaterOutVertices[2].setColor(255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[2], 255, 255, 255, 255); KeepWaterOutIndices[2] = 1; - KeepWaterOutVertices[3].setColor(255, 255, 255, 255); + RwIm3DVertexSetRGBA(&KeepWaterOutVertices[3], 255, 255, 255, 255); KeepWaterOutIndices[3] = 1; KeepWaterOutIndices[4] = 2; KeepWaterOutIndices[5] = 3; From 1a44bcccd5a30306456e6abb36a9a754cee3c7f2 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 26 Apr 2020 14:18:34 +0300 Subject: [PATCH 119/123] A few fixes --- src/core/ControllerConfig.h | 18 +++++++++++++----- src/core/config.h | 4 +++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index 76f9882b..f117c047 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -122,12 +122,18 @@ public: }; bool m_bFirstCapture; -#ifdef __DINPUT_INCLUDED__ - DIJOYSTATE2 m_OldState; - DIJOYSTATE2 m_NewState; -#elif defined RW_GL3 +#if defined RW_GL3 GlfwJoyState m_OldState; GlfwJoyState m_NewState; +#else + #ifdef __DINPUT_INCLUDED__ + DIJOYSTATE2 m_OldState; + DIJOYSTATE2 m_NewState; + #else + // this is here to fix the size of a struct + // TODO: find a better was a remove this + uint32 ___padd[0x110 / 4 * 2]; + #endif #endif wchar m_aActionNames[MAX_CONTROLLERACTIONS][ACTIONNAME_LENGTH]; bool m_aButtonStates[MAX_BUTTONS]; @@ -204,6 +210,8 @@ public: void ResetSettingOrder (e_ControllerAction action); }; -//VALIDATE_SIZE(CControllerConfigManager, 0x143C); +#ifndef RW_GL3 +VALIDATE_SIZE(CControllerConfigManager, 0x143C); +#endif extern CControllerConfigManager ControlsManager; \ No newline at end of file diff --git a/src/core/config.h b/src/core/config.h index 80e2ff19..2cf8ec88 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -200,7 +200,9 @@ enum Config { //#define PS2_ALTERNATIVE_CARSPLASH // unused on PS2 // Pad -// #define XINPUT +#ifndef RW_GL3 +#define XINPUT +#endif #define KANGAROO_CHEAT #define REGISTER_START_BUTTON From b7ee3792df72826b351a6fac86d7aad9caeea632 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 26 Apr 2020 20:11:19 +0300 Subject: [PATCH 120/123] Remove struct workaround in CControllerConfigManager --- src/core/ControllerConfig.h | 14 ++++++-------- src/skel/win/win.h | 1 - 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index f117c047..7d0e1073 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -1,5 +1,9 @@ #pragma once +#if defined RW_D3D9 || defined RWLIBS +#define DIRECTINPUT_VERSION 0x0800 +#include +#endif // based on x-gtasa @@ -126,14 +130,8 @@ public: GlfwJoyState m_OldState; GlfwJoyState m_NewState; #else - #ifdef __DINPUT_INCLUDED__ - DIJOYSTATE2 m_OldState; - DIJOYSTATE2 m_NewState; - #else - // this is here to fix the size of a struct - // TODO: find a better was a remove this - uint32 ___padd[0x110 / 4 * 2]; - #endif + DIJOYSTATE2 m_OldState; + DIJOYSTATE2 m_NewState; #endif wchar m_aActionNames[MAX_CONTROLLERACTIONS][ACTIONNAME_LENGTH]; bool m_aButtonStates[MAX_BUTTONS]; diff --git a/src/skel/win/win.h b/src/skel/win/win.h index 0e63502e..d05e3951 100644 --- a/src/skel/win/win.h +++ b/src/skel/win/win.h @@ -63,7 +63,6 @@ struct tJoy bool m_bInitialised; bool m_bHasAxisZ; bool m_bHasAxisR; - char _pad0; int m_nVendorID; int m_nProductID; }; From 41586c7cda403291be80f414082d16b5333933a5 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 26 Apr 2020 20:16:31 +0200 Subject: [PATCH 121/123] fixes for glfw --- src/fakerw/fake.cpp | 22 +++++++++++++++++++++- src/rw/TxdStore.cpp | 35 ----------------------------------- src/skel/glfw/glfw.cpp | 31 ++++++++++++++++--------------- 3 files changed, 37 insertions(+), 51 deletions(-) diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp index 3d4ddf5d..26b5ae3d 100644 --- a/src/fakerw/fake.cpp +++ b/src/fakerw/fake.cpp @@ -290,9 +290,29 @@ RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture); // TODO void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { } +static rw::Raster* +ConvertTexRaster(rw::Raster *ras) +{ + using namespace rw; + Image *img = ras->toImage(); + ras->destroy(); + img->unindex(); + ras = Raster::createFromImage(img); + img->destroy(); + return ras; +} + // hack for reading native textures RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size) - { *tex = Texture::streamReadNative(stream); return *tex != nil; } +{ + *tex = Texture::streamReadNative(stream); +#ifdef RW_GL3 + if(strcmp((*tex)->name, "copnu") == 0) + tex = tex; + (*tex)->raster = ConvertTexRaster((*tex)->raster); +#endif + return *tex != nil; +} diff --git a/src/rw/TxdStore.cpp b/src/rw/TxdStore.cpp index bb7386d5..51d018f6 100644 --- a/src/rw/TxdStore.cpp +++ b/src/rw/TxdStore.cpp @@ -127,38 +127,6 @@ CTxdStore::RemoveRefWithoutDelete(int slot) GetSlot(slot)->refCount--; } -#ifdef RW_GL3 -rw::Raster* -convertTexRaster(rw::Raster* ras) -{ - rw::Image* img = ras->toImage(); -// ras->destroy(); - img->unindex(); - ras = rw::Raster::createFromImage(img); - img->destroy(); - return ras; -} - -void -convertTxd(rw::TexDictionary* txd) -{ - rw::Texture* tex; - FORLIST(lnk, txd->textures) { - tex = rw::Texture::fromDict(lnk); - rw::Raster* ras = tex->raster; - if (ras && ras->platform != rw::platform) { - if (!(ras->platform == rw::PLATFORM_D3D8 && rw::platform == rw::PLATFORM_D3D9 || - ras->platform == rw::PLATFORM_D3D9 && rw::platform == rw::PLATFORM_D3D8)) { - tex->raster = convertTexRaster(ras); - ras->destroy(); - } - } - tex->setFilter(rw::Texture::LINEAR); - } - -} -#endif - bool CTxdStore::LoadTxd(int slot, RwStream *stream) { @@ -166,9 +134,6 @@ CTxdStore::LoadTxd(int slot, RwStream *stream) if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)){ def->texDict = RwTexDictionaryGtaStreamRead(stream); -#ifdef RW_GL3 - convertTxd(def->texDict); -#endif return def->texDict != nil; } printf("Failed to load TXD\n"); diff --git a/src/skel/glfw/glfw.cpp b/src/skel/glfw/glfw.cpp index 0d7dc384..db6be3a2 100644 --- a/src/skel/glfw/glfw.cpp +++ b/src/skel/glfw/glfw.cpp @@ -19,11 +19,25 @@ #include "platform.h" #include "crossplatform.h" +#include "patcher.h" +#include "main.h" +#include "FileMgr.h" +#include "Text.h" +#include "Pad.h" +#include "Timer.h" +#include "DMAudio.h" +#include "ControllerConfig.h" +#include "Frontend.h" +#include "Game.h" +#include "PCSave.h" +#include "Sprite2d.h" +#include "AnimViewer.h" + + #define MAX_SUBSYSTEMS (16) -using namespace rw; -EngineOpenParams openParams; +rw::EngineOpenParams openParams; static RwBool ForegroundApp = TRUE; @@ -49,19 +63,6 @@ static psGlobalType PsGlobal; #define JIF(x) if (FAILED(hr=(x))) \ {debug(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n"), hr); return;} -#include "patcher.h" -#include "main.h" -#include "FileMgr.h" -#include "Text.h" -#include "Pad.h" -#include "Timer.h" -#include "DMAudio.h" -#include "ControllerConfig.h" -#include "Frontend.h" -#include "Game.h" -#include "PCSave.h" -#include "Sprite2d.h" -#include "AnimViewer.h" // TODO: This is used on selecting video mode, so either think something or remove it completely DWORD _dwMemTotalVideo = 1024 * (1024 * 1024); // 1024 MB as placeholder From c076998ba308b79041af0672137c231581778ad3 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 26 Apr 2020 20:18:10 +0200 Subject: [PATCH 122/123] update librw --- librw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librw b/librw index 43190a51..09b0b36e 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 43190a51f799a3ef315c0b6245b70ee3a09a64ac +Subproject commit 09b0b36e7de9866a92a504728f78c780c0d7b8e1 From 4dc2f307910c6d5dcf3c910b3da2e2d943ac1003 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Sun, 26 Apr 2020 21:58:12 +0300 Subject: [PATCH 123/123] Remove little hack --- src/core/common.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/core/common.h b/src/core/common.h index 2cc3d98c..955225cc 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -88,13 +88,6 @@ inline uint32 ldb(uint32 p, uint32 s, uint32 w) return w>>p & (1<