diff --git a/src/Camera.cpp b/src/Camera.cpp index e5e50ef2..d20ef5bb 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -20,6 +20,8 @@ bool &CCamera::m_bUseMouse3rdPerson = *(bool *)0x5F03D8; WRAPPER void CCamera::DrawBordersForWideScreen(void) { EAXJMP(0x46B430); } WRAPPER void CCamera::CalculateDerivedValues(void) { EAXJMP(0x46EEA0); } +WRAPPER void CCamera::Restore(void) { EAXJMP(0x46F990); } +WRAPPER void CCamera::SetWidescreenOff(void) { EAXJMP(0x46FF10); } bool CCamera::IsSphereVisible(const CVector ¢er, float radius, const CMatrix *mat) diff --git a/src/Camera.h b/src/Camera.h index 6d20de72..5c5f8a73 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -459,6 +459,8 @@ int m_iModeObbeCamIsInForCar; void CalculateDerivedValues(void); void DrawBordersForWideScreen(void); + void Restore(void); + void SetWidescreenOff(void); void dtor(void) { this->CCamera::~CCamera(); } }; diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 824d5c39..60454bdd 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -33,3 +33,4 @@ WRAPPER int32 cDMAudio::CreateEntity(int, void*) { EAXJMP(0x57C7C0); } WRAPPER void cDMAudio::SetEntityStatus(int32 id, uint8 enable) { EAXJMP(0x57C810); } WRAPPER void cDMAudio::SetRadioInCar(int32) { EAXJMP(0x57CE60); } WRAPPER void cDMAudio::DestroyEntity(int32) { EAXJMP(0x57C7F0); } +WRAPPER void cDMAudio::ClearMissionAudio(void) { EAXJMP(0x57CE20); } \ No newline at end of file diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 46914aaa..72e8d316 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -203,5 +203,6 @@ public: void SetRadioInCar(int32); uint8 IsMP3RadioChannelAvailable(); void DestroyEntity(int32); + void ClearMissionAudio(void); }; extern cDMAudio &DMAudio; diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 1b389631..b0f4c1ed 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -6,6 +6,7 @@ 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; WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); } WRAPPER void CCarCtrl::AddToCarArray(int32 id, int32 vehclass) { EAXJMP(0x4182F0); } diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 0195219e..c54f747f 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -14,4 +14,5 @@ public: static int32 &NumAmbulancesOnDuty; static int32 &NumFiretrucksOnDuty; static bool &bCarsGeneratedAroundCamera; + static float &CarDensityMultiplier; }; diff --git a/src/control/Population.cpp b/src/control/Population.cpp index 7b1acaaf..9af68670 100644 --- a/src/control/Population.cpp +++ b/src/control/Population.cpp @@ -5,6 +5,8 @@ PedGroup *CPopulation::ms_pPedGroups = (PedGroup*)0x6E9248; bool &CPopulation::ms_bGivePedsWeapons = *(bool*)0x95CCF6; +int32 &CPopulation::m_AllRandomPedsThisType = *(int32*)0x5FA570; +float &CPopulation::PedDensityMultiplier = *(float*)0x5FA56C; WRAPPER void CPopulation::UpdatePedCount(uint32, bool) { EAXJMP(0x4F5A60); } WRAPPER void CPopulation::DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool) { EAXJMP(0x4F6200); } diff --git a/src/control/Population.h b/src/control/Population.h index e93e14fc..4169261a 100644 --- a/src/control/Population.h +++ b/src/control/Population.h @@ -12,6 +12,8 @@ class CPopulation public: static PedGroup *ms_pPedGroups; //[31] static bool &ms_bGivePedsWeapons; + static int32 &m_AllRandomPedsThisType; + static float &PedDensityMultiplier; static void UpdatePedCount(uint32, bool); static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool); diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index b80b04ba..a2164f6b 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1572,7 +1572,7 @@ void CReplay::Display() if (Mode == MODE_RECORD) return; counter = (counter + 1) % 65536; - if (counter & 0x20 == 0) + if ((counter & 0x20) == 0) return; CFont::SetPropOn(); CFont::SetBackgroundOff(); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 153e98b5..e7f64541 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -3,12 +3,161 @@ #include "Script.h" -uint8 *CTheScripts::ScriptSpace = (uint8*)0x74B248; -CTextLine* CTheScripts::IntroTextLines = (CTextLine*)0x70EA74; -CScriptRectangle* CTheScripts::IntroRectangles = (CScriptRectangle*)0x72D109; -CSprite2d* CTheScripts::ScriptSprites = (CSprite2d*)0x72B090; -bool CTheScripts::DbgFlag = *(bool*)0x95CD87; -uint32 CTheScripts::OnAMissionFlag = *(uint32*)0x8F1B64; +#include "Camera.h" +#include "CarCtrl.h" +#include "DMAudio.h" +#include "Hud.h" +#include "ModelIndices.h" +#include "PlayerInfo.h" +#include "PlayerPed.h" +#include "Pools.h" +#include "Population.h" +#include "Streaming.h" +#include "User.h" +#include "Weather.h" +#include "World.h" +uint8 (&CTheScripts::ScriptSpace)[160 * 1024] = *(uint8(*)[160 * 1024])*(uintptr*)0x74B248; +CTextLine (&CTheScripts::IntroTextLines)[2] = *(CTextLine (*)[2])*(uintptr*)0x70EA74; +CScriptRectangle (&CTheScripts::IntroRectangles)[16] = *(CScriptRectangle (*)[16])*(uintptr*)0x72D108; +CSprite2d (&CTheScripts::ScriptSprites)[16] = *(CSprite2d(*)[16])*(uintptr*)0x72B090; +bool &CTheScripts::DbgFlag = *(bool*)0x95CD87; +uint32 &CTheScripts::OnAMissionFlag = *(uint32*)0x8F2A24; +int32 &CTheScripts::StoreVehicleIndex = *(int32*)0x8F5F3C; +bool &CTheScripts::StoreVehicleWasRandom = *(bool*)0x95CDBC; + +CMissionCleanup(&CTheScripts::MissionCleanup) = *(CMissionCleanup*)0x8F2AD8; +CUpsideDownCarCheck(&CTheScripts::UpsideDownCars) = *(CUpsideDownCarCheck*)0x6EE450; +CStuckCarCheck(&CTheScripts::StuckCars) = *(CStuckCarCheck*)0x87C588; + +CMissionCleanup::CMissionCleanup() +{ + Init(); +} + +void CMissionCleanup::Init() +{ + for (int i = 0; i < MAX_CLEANUP; i++){ + m_sEntities[i].type = CLEANUP_UNUSED; + m_sEntities[i].id = 0; + } +} + +CMissionCleanupEntity* CMissionCleanup::FindFree() +{ + for (int i = 0; i < MAX_CLEANUP; i++){ + if (m_sEntities[i].type == CLEANUP_UNUSED) + return &m_sEntities[i]; + } + assert(0); + return nil; +} + +void CMissionCleanup::AddEntityToList(int32 id, uint8 type) +{ + CMissionCleanupEntity* pNew = FindFree(); + if (!pNew) + return; + pNew->id = id; + pNew->type = type; + m_bCount++; +} + +void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type) +{ + for (int i = 0; i < MAX_CLEANUP; i++){ + if (m_sEntities[i].type == type && m_sEntities[i].id == 0){ + m_sEntities[i].id = 0; + m_sEntities[i].type = CLEANUP_UNUSED; + } + } +} + +void CMissionCleanup::Process() +{ + CPopulation::m_AllRandomPedsThisType = -1; + CPopulation::PedDensityMultiplier = 1.0f; + CCarCtrl::CarDensityMultiplier = 1.0; + FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f; + TheCamera.Restore(); + TheCamera.SetWidescreenOff(); + DMAudio.ClearMissionAudio(); + CWeather::ReleaseWeather(); + for (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++) + CStreaming::SetMissionDoesntRequireSpecialChar(i); + for (int i = 0; i < NUM_OF_CUTSCENE_OBJECTS; i++) + CStreaming::SetMissionDoesntRequireModel(MI_CUTOBJ01 + i); + CStreaming::ms_disableStreaming = false; + CHud::m_ItemToFlash = -1; + CHud::SetHelpMessage(nil, false); + CUserDisplay::OnscnTimer.m_bDisabled = false; + CWorld::Players[0].m_pPed->m_pWanted->m_IsIgnoredByCops = false; + CWorld::Players[0].m_pPed->m_pWanted->m_IsIgnoredByEveryOne = false; + CWorld::Players[0].MakePlayerSafe(false); + CTheScripts::StoreVehicleIndex = -1; + CTheScripts::StoreVehicleWasRandom = true; + CTheScripts::UpsideDownCars.Init(); + CTheScripts::StuckCars.Init(); + for (int i = 0; i < MAX_CLEANUP; i++){ + if (m_sEntities[i].type == CLEANUP_UNUSED) + continue; + switch (m_sEntities[i].type) { + case CLEANUP_CAR: + { + CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id); + if (v) + CTheScripts::CleanUpThisVehicle(v); + break; + } + case CLEANUP_CHAR: + { + CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id); + if (p) + CTheScripts::CleanUpThisPed(p); + break; + } + case CLEANUP_OBJECT: + { + CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id); + if (o) + CTheScripts::CleanUpThisObject(o); + break; + } + default: + break; + } + } +} + +void CUpsideDownCarCheck::Init() +{ + for (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){ + m_sCars[i].m_nVehicleIndex = -1; + m_sCars[i].m_nVehicleIndex = 0; + } +} + +void CStuckCarCheck::Init() +{ + for (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++) { + m_sCars[i].m_nVehicleIndex = -1; + m_sCars[i].m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f); + m_sCars[i].m_nStartTime = -1; + m_sCars[i].m_fDistance = 0.0f; + m_sCars[i].m_nStuckTime = 0; + m_sCars[i].m_bStuck = false; + } +} + +WRAPPER void CTheScripts::CleanUpThisVehicle(CVehicle*) { EAXJMP(0x4548D0); } +WRAPPER void CTheScripts::CleanUpThisPed(CPed*) { EAXJMP(0x4547A0); } +WRAPPER void CTheScripts::CleanUpThisObject(CObject*) { EAXJMP(0x454910); } WRAPPER bool CTheScripts::IsPlayerOnAMission() { EAXJMP(0x439410); } WRAPPER void CTheScripts::ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, int col, int col2) { EAXJMP(0x4534E0); } + +STARTPATCHES +InjectHook(0x437AE0, &CMissionCleanup::Init, PATCH_JUMP); +InjectHook(0x437BA0, &CMissionCleanup::AddEntityToList, PATCH_JUMP); +InjectHook(0x437BD0, &CMissionCleanup::RemoveEntityFromList, PATCH_JUMP); +InjectHook(0x437C10, &CMissionCleanup::Process, PATCH_JUMP); +ENDPATCHES \ No newline at end of file diff --git a/src/control/Script.h b/src/control/Script.h index 1eb02c1b..7b62a1b0 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -1,5 +1,8 @@ #pragma once +#include "Ped.h" +#include "Object.h" #include "Sprite2d.h" +#include "Vehicle.h" struct CScriptRectangle { @@ -32,17 +35,111 @@ struct CTextLine wchar m_awText[500]; }; +struct CRunningScript +{ + CRunningScript *next; + CRunningScript *prev; + uint8 m_abScriptName[8]; + uint32 m_nIp; + uint32 m_anStack[6]; + uint16 m_nStackPointer; + void* m_anLocalVariables[18]; + bool m_bCondResult; + bool m_bIsMissionThread; + bool m_bSkipWakeTime; + uint32 m_nWakeTime; + uint16 m_wIfOp; + bool m_bNotFlag; + bool m_bWBCheck; + bool m_bWastedOrBusted; + bool m_bMissionFlag; +}; + +enum { + CLEANUP_UNUSED = 0, + CLEANUP_CAR, + CLEANUP_CHAR, + CLEANUP_OBJECT +}; + +struct CMissionCleanupEntity +{ + uint8 type; + int32 id; +}; + +enum { + MAX_CLEANUP = 50, + MAX_UPSIDEDOWN_CAR_CHECKS = 6, + MAX_STUCK_CAR_CHECKS = 6 +}; + +class CMissionCleanup +{ + CMissionCleanupEntity m_sEntities[MAX_CLEANUP]; + uint8 m_bCount; + +public: + CMissionCleanup(); + + void Init(); + CMissionCleanupEntity* FindFree(); + void AddEntityToList(int32, uint8); + void RemoveEntityFromList(int32, uint8); + void Process(); +}; + +struct CUpsideDownCarCheckEntry +{ + int32 m_nVehicleIndex; + uint32 m_nUpsideDownTimer; +}; + +class CUpsideDownCarCheck +{ + CUpsideDownCarCheckEntry m_sCars[MAX_UPSIDEDOWN_CAR_CHECKS]; + +public: + void Init(); +}; + +struct CStuckCarCheckEntry +{ + int32 m_nVehicleIndex; + CVector m_vecPos; + int32 m_nStartTime; + float m_fDistance; + uint32 m_nStuckTime; + bool m_bStuck; +}; + +class CStuckCarCheck +{ + CStuckCarCheckEntry m_sCars[MAX_STUCK_CAR_CHECKS]; + +public: + void Init(); +}; + class CTheScripts { public: - static uint8 *ScriptSpace;//[160*1024] - static CTextLine* IntroTextLines; - static CScriptRectangle* IntroRectangles; - static CSprite2d* ScriptSprites; - static bool DbgFlag; - static uint32 OnAMissionFlag; + static uint8(&ScriptSpace)[160 * 1024]; + static CTextLine(&IntroTextLines)[2]; + static CScriptRectangle(&IntroRectangles)[16]; + static CSprite2d(&ScriptSprites)[16]; + static bool &DbgFlag; + static uint32 &OnAMissionFlag; + static CMissionCleanup &MissionCleanup; + static CStuckCarCheck &StuckCars; + static CUpsideDownCarCheck &UpsideDownCars; + static int32 &StoreVehicleIndex; + static bool &StoreVehicleWasRandom; public: static bool IsPlayerOnAMission(); static void ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, int col, int col2); + static void CleanUpThisVehicle(CVehicle*); + static void CleanUpThisPed(CPed*); + static void CleanUpThisObject(CObject*); }; diff --git a/src/entities/PlayerInfo.cpp b/src/entities/PlayerInfo.cpp index 796481a4..59efe2ae 100644 --- a/src/entities/PlayerInfo.cpp +++ b/src/entities/PlayerInfo.cpp @@ -1,3 +1,5 @@ #include "common.h" #include "patcher.h" #include "PlayerInfo.h" + +WRAPPER void CPlayerInfo::MakePlayerSafe(bool) { EAXJMP(0x4A1400); } \ No newline at end of file diff --git a/src/entities/PlayerInfo.h b/src/entities/PlayerInfo.h index 79f379d5..e2b42fe7 100644 --- a/src/entities/PlayerInfo.h +++ b/src/entities/PlayerInfo.h @@ -65,6 +65,8 @@ public: bool m_bGetOutOfHospitalFree; uint8 m_aSkinName[32]; RwTexture *m_pSkinTexture; + + void MakePlayerSafe(bool); }; static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error"); diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 3a37ac23..ff350b55 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -330,6 +330,12 @@ enum MI_BOMB, MI_FINGERS, + MI_CUTOBJ01 = 185, + MI_CUTOBJ02, + MI_CUTOBJ03, + MI_CUTOBJ04, + MI_CUTOBJ05, + MI_CAR_DOOR = 190, MI_CAR_BUMPER, MI_CAR_PANEL, @@ -345,6 +351,11 @@ enum NUM_DEFAULT_MODELS, }; +enum{ + NUM_OF_SPECIAL_CHARS = 4, + NUM_OF_CUTSCENE_OBJECTS = 5 +}; + void InitModelIndices(void); void MatchModelString(const char *name, int16 id); diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp index 0e132392..d36675cf 100644 --- a/src/render/Hud.cpp +++ b/src/render/Hud.cpp @@ -47,7 +47,7 @@ wchar *CHud::m_PagerMessage = (wchar*)0x878840; bool &CHud::m_Wants_To_Draw_Hud = *(bool*)0x95CD89; bool &CHud::m_Wants_To_Draw_3dMarkers = *(bool*)0x95CD62; wchar(*CHud::m_BigMessage)[128] = (wchar(*)[128])0x664CE0; -int32 CHud::m_ItemToFlash = *(int32*)0x95CC82; +int32 &CHud::m_ItemToFlash = *(int32*)0x95CC82; // These aren't really in CHud float CHud::BigMessageInUse[6]; diff --git a/src/render/Hud.h b/src/render/Hud.h index 1c82b7df..df02b4d0 100644 --- a/src/render/Hud.h +++ b/src/render/Hud.h @@ -62,7 +62,7 @@ public: static bool &m_Wants_To_Draw_Hud; static bool &m_Wants_To_Draw_3dMarkers; static wchar(*m_BigMessage)[128]; - static int32 m_ItemToFlash; + static int32 &m_ItemToFlash; // These aren't really in CHud static float BigMessageInUse[6];