summaryrefslogtreecommitdiffstats
path: root/src/control
diff options
context:
space:
mode:
authoraap <aap@papnet.eu>2020-04-09 20:50:24 +0200
committeraap <aap@papnet.eu>2020-04-09 20:50:24 +0200
commit34349c4df2683fca35be37ec626aaa8eef2ddaee (patch)
tree6a86b547819f30ab784d00891ee99b8924580093 /src/control
parentMerge remote-tracking branch 'Fire-Head/master' (diff)
downloadre3-34349c4df2683fca35be37ec626aaa8eef2ddaee.tar
re3-34349c4df2683fca35be37ec626aaa8eef2ddaee.tar.gz
re3-34349c4df2683fca35be37ec626aaa8eef2ddaee.tar.bz2
re3-34349c4df2683fca35be37ec626aaa8eef2ddaee.tar.lz
re3-34349c4df2683fca35be37ec626aaa8eef2ddaee.tar.xz
re3-34349c4df2683fca35be37ec626aaa8eef2ddaee.tar.zst
re3-34349c4df2683fca35be37ec626aaa8eef2ddaee.zip
Diffstat (limited to 'src/control')
-rw-r--r--src/control/GameLogic.cpp572
-rw-r--r--src/control/GameLogic.h24
-rw-r--r--src/control/Gangs.cpp18
-rw-r--r--src/control/OnscreenTimer.h96
-rw-r--r--src/control/Pickups.cpp2098
-rw-r--r--src/control/Pickups.h248
-rw-r--r--src/control/PowerPoints.cpp42
-rw-r--r--src/control/PowerPoints.h50
-rw-r--r--src/control/Restart.cpp434
9 files changed, 1791 insertions, 1791 deletions
diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp
index 0abae7d6..8e0ea02d 100644
--- a/src/control/GameLogic.cpp
+++ b/src/control/GameLogic.cpp
@@ -1,294 +1,294 @@
#include "common.h"
#include "patcher.h"
-#include "GameLogic.h"
-#include "Clock.h"
-#include "Stats.h"
-#include "Pickups.h"
-#include "Timer.h"
-#include "Streaming.h"
-#include "CutsceneMgr.h"
-#include "World.h"
-#include "PlayerPed.h"
-#include "Wanted.h"
-#include "Camera.h"
-#include "Messages.h"
-#include "CarCtrl.h"
-#include "Restart.h"
-#include "Pad.h"
-#include "References.h"
-#include "Fire.h"
-#include "Script.h"
-#include "Garages.h"
-
-uint8 CGameLogic::ActivePlayers; // 0x95CD5E
-
-void
-CGameLogic::InitAtStartOfGame()
-{
- ActivePlayers = 1;
-}
-
-void
-CGameLogic::PassTime(uint32 time)
-{
- int32 minutes, hours, days;
-
- minutes = time + CClock::GetMinutes();
- hours = CClock::GetHours();
-
- for (; minutes >= 60; minutes -= 60)
- hours++;
-
- if (hours > 23) {
- days = CStats::DaysPassed;
- for (; hours >= 24; hours -= 24)
- days++;
- CStats::DaysPassed = days;
- }
-
- CClock::SetGameClock(hours, minutes);
- CPickups::PassTime(time * 1000);
-}
-
-void
-CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
-{
- CTimer::Stop();
- CStreaming::FlushRequestList();
- CStreaming::DeleteRwObjectsAfterDeath(pos);
- CStreaming::RemoveUnusedModelsInLoadedList();
- CGame::DrasticTidyUpMemory(true);
- CStreaming::LoadScene(pos);
- CTimer::Update();
-}
-
-void
-CGameLogic::Update()
-{
- CVector vecRestartPos;
- float fRestartFloat;
-
- if (CCutsceneMgr::IsCutsceneProcessing()) return;
-
- CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
- switch (pPlayerInfo.m_WBState) {
- case WBSTATE_PLAYING:
- if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
- pPlayerInfo.m_pPed->ClearAdrenaline();
- pPlayerInfo.KillPlayer();
- }
- if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
- pPlayerInfo.m_pPed->ClearAdrenaline();
- pPlayerInfo.ArrestPlayer();
- }
- break;
- case WBSTATE_WASTED:
- if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
- TheCamera.SetFadeColour(200, 200, 200);
- TheCamera.Fade(2.0f, FADE_OUT);
- }
-
- if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
- pPlayerInfo.m_WBState = WBSTATE_PLAYING;
- if (pPlayerInfo.m_bGetOutOfHospitalFree) {
- pPlayerInfo.m_bGetOutOfHospitalFree = false;
- } else {
- pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
- pPlayerInfo.m_pPed->ClearWeapons();
- }
-
- if (pPlayerInfo.m_pPed->bInVehicle) {
- CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
- if (pVehicle != nil) {
- if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
- pVehicle->pDriver = nil;
- if (pVehicle->m_status != STATUS_WRECKED)
- pVehicle->m_status = STATUS_ABANDONED;
- } else
- pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
- }
- }
- CEventList::Initialise();
- CMessages::ClearMessages();
- CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
- CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
- CRestart::OverrideHospitalLevel = LEVEL_NONE;
- CRestart::OverridePoliceStationLevel = LEVEL_NONE;
- PassTime(720);
- RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
- SortOutStreamingAndMemory(pPlayerInfo.GetPos());
- TheCamera.m_fCamShakeForce = 0.0f;
- TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
- CPad::GetPad(0)->StopShaking(0);
- CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
- CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
- if (CRestart::bFadeInAfterNextDeath) {
- TheCamera.SetFadeColour(200, 200, 200);
- TheCamera.Fade(4.0f, FADE_IN);
- } else CRestart::bFadeInAfterNextDeath = true;
- }
- break;
- case WBSTATE_BUSTED:
- if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(2.0f, FADE_OUT);
- }
- if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
- pPlayerInfo.m_WBState = WBSTATE_PLAYING;
- int takeMoney;
-
- switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
- case 0:
- case 1:
- takeMoney = 100;
- break;
- case 2:
- takeMoney = 200;
- break;
- case 3:
- takeMoney = 400;
- break;
- case 4:
- takeMoney = 600;
- break;
- case 5:
- takeMoney = 900;
- break;
- case 6:
- takeMoney = 1500;
- break;
- }
- if (pPlayerInfo.m_bGetOutOfJailFree) {
- pPlayerInfo.m_bGetOutOfJailFree = false;
- } else {
- pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
- pPlayerInfo.m_pPed->ClearWeapons();
- }
-
- if (pPlayerInfo.m_pPed->bInVehicle) {
- CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
- if (pVehicle != nil) {
- if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
- pVehicle->pDriver = nil;
- if (pVehicle->m_status != STATUS_WRECKED)
- pVehicle->m_status = STATUS_ABANDONED;
- }
- else
- pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
- }
- }
- CEventList::Initialise();
- CMessages::ClearMessages();
- CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
- CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
- CRestart::OverrideHospitalLevel = LEVEL_NONE;
- CRestart::OverridePoliceStationLevel = LEVEL_NONE;
- PassTime(720);
- RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
- pPlayerInfo.m_pPed->ClearWeapons();
- SortOutStreamingAndMemory(pPlayerInfo.GetPos());
- TheCamera.m_fCamShakeForce = 0.0f;
- TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
- CPad::GetPad(0)->StopShaking(0);
- CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
- CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
- if (CRestart::bFadeInAfterNextArrest) {
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(4.0f, FADE_IN);
- } else CRestart::bFadeInAfterNextArrest = true;
- }
- break;
- case WBSTATE_FAILED_CRITICAL_MISSION:
- if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(2.0f, FADE_OUT);
- }
- if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
- pPlayerInfo.m_WBState = WBSTATE_PLAYING;
- if (pPlayerInfo.m_pPed->bInVehicle) {
- CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
- if (pVehicle != nil) {
- if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
- pVehicle->pDriver = nil;
- if (pVehicle->m_status != STATUS_WRECKED)
- pVehicle->m_status = STATUS_ABANDONED;
- } else
- pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
- }
- }
- CEventList::Initialise();
- CMessages::ClearMessages();
- CCarCtrl::ClearInterestingVehicleList();
- CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
- CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
- CRestart::OverridePoliceStationLevel = LEVEL_NONE;
- CRestart::OverrideHospitalLevel = LEVEL_NONE;
- RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
- SortOutStreamingAndMemory(pPlayerInfo.GetPos());
- TheCamera.m_fCamShakeForce = 0.0f;
- TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
- CPad::GetPad(0)->StopShaking(0);
- CReferences::RemoveReferencesToPlayer();
- CCarCtrl::CountDownToCarsAtStart = 2;
- CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
- TheCamera.SetFadeColour(0, 0, 0);
- TheCamera.Fade(4.0f, FADE_IN);
- }
- break;
- case 4:
- return;
- }
-}
-
-void
-CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
-{
- pPlayerPed->m_fHealth = 100.0f;
- pPlayerPed->m_fArmour = 0.0f;
- pPlayerPed->bIsVisible = true;
- pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
- pPlayerPed->bDoBloodyFootprints = false;
- pPlayerPed->ClearAdrenaline();
- pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
- if (pPlayerPed->m_pFire)
- pPlayerPed->m_pFire->Extinguish();
- pPlayerPed->bInVehicle = false;
- pPlayerPed->m_pMyVehicle = nil;
- pPlayerPed->m_pVehicleAnim = nil;
- pPlayerPed->m_pWanted->Reset();
- pPlayerPed->RestartNonPartialAnims();
- pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
- pPlayerPed->bRemoveFromWorld = false;
- pPlayerPed->ClearWeaponTarget();
- pPlayerPed->SetInitialState();
- CCarCtrl::ClearInterestingVehicleList();
-
- pos.z += 1.0f;
- pPlayerPed->Teleport(pos);
- pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
-
- pPlayerPed->m_fRotationCur = DEGTORAD(angle);
- pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
- pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
- CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
- CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
- pPlayerPed->RestoreHeadingRate();
- TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
- CReferences::RemoveReferencesToPlayer();
- CGarages::PlayerArrestedOrDied();
- CStats::CheckPointReachedUnsuccessfully();
- CWorld::Remove(pPlayerPed);
- CWorld::Add(pPlayerPed);
-}
-
+#include "GameLogic.h"
+#include "Clock.h"
+#include "Stats.h"
+#include "Pickups.h"
+#include "Timer.h"
+#include "Streaming.h"
+#include "CutsceneMgr.h"
+#include "World.h"
+#include "PlayerPed.h"
+#include "Wanted.h"
+#include "Camera.h"
+#include "Messages.h"
+#include "CarCtrl.h"
+#include "Restart.h"
+#include "Pad.h"
+#include "References.h"
+#include "Fire.h"
+#include "Script.h"
+#include "Garages.h"
+
+uint8 CGameLogic::ActivePlayers; // 0x95CD5E
+
+void
+CGameLogic::InitAtStartOfGame()
+{
+ ActivePlayers = 1;
+}
+
+void
+CGameLogic::PassTime(uint32 time)
+{
+ int32 minutes, hours, days;
+
+ minutes = time + CClock::GetMinutes();
+ hours = CClock::GetHours();
+
+ for (; minutes >= 60; minutes -= 60)
+ hours++;
+
+ if (hours > 23) {
+ days = CStats::DaysPassed;
+ for (; hours >= 24; hours -= 24)
+ days++;
+ CStats::DaysPassed = days;
+ }
+
+ CClock::SetGameClock(hours, minutes);
+ CPickups::PassTime(time * 1000);
+}
+
+void
+CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
+{
+ CTimer::Stop();
+ CStreaming::FlushRequestList();
+ CStreaming::DeleteRwObjectsAfterDeath(pos);
+ CStreaming::RemoveUnusedModelsInLoadedList();
+ CGame::DrasticTidyUpMemory(true);
+ CStreaming::LoadScene(pos);
+ CTimer::Update();
+}
+
+void
+CGameLogic::Update()
+{
+ CVector vecRestartPos;
+ float fRestartFloat;
+
+ if (CCutsceneMgr::IsCutsceneProcessing()) return;
+
+ CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
+ switch (pPlayerInfo.m_WBState) {
+ case WBSTATE_PLAYING:
+ if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
+ pPlayerInfo.m_pPed->ClearAdrenaline();
+ pPlayerInfo.KillPlayer();
+ }
+ if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
+ pPlayerInfo.m_pPed->ClearAdrenaline();
+ pPlayerInfo.ArrestPlayer();
+ }
+ break;
+ case WBSTATE_WASTED:
+ if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
+ TheCamera.SetFadeColour(200, 200, 200);
+ TheCamera.Fade(2.0f, FADE_OUT);
+ }
+
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
+ pPlayerInfo.m_WBState = WBSTATE_PLAYING;
+ if (pPlayerInfo.m_bGetOutOfHospitalFree) {
+ pPlayerInfo.m_bGetOutOfHospitalFree = false;
+ } else {
+ pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
+ pPlayerInfo.m_pPed->ClearWeapons();
+ }
+
+ if (pPlayerInfo.m_pPed->bInVehicle) {
+ CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
+ if (pVehicle != nil) {
+ if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
+ pVehicle->pDriver = nil;
+ if (pVehicle->m_status != STATUS_WRECKED)
+ pVehicle->m_status = STATUS_ABANDONED;
+ } else
+ pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
+ }
+ }
+ CEventList::Initialise();
+ CMessages::ClearMessages();
+ CCarCtrl::ClearInterestingVehicleList();
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
+ CRestart::OverrideHospitalLevel = LEVEL_NONE;
+ CRestart::OverridePoliceStationLevel = LEVEL_NONE;
+ PassTime(720);
+ RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ SortOutStreamingAndMemory(pPlayerInfo.GetPos());
+ TheCamera.m_fCamShakeForce = 0.0f;
+ TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
+ CPad::GetPad(0)->StopShaking(0);
+ CReferences::RemoveReferencesToPlayer();
+ CCarCtrl::CountDownToCarsAtStart = 2;
+ CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
+ if (CRestart::bFadeInAfterNextDeath) {
+ TheCamera.SetFadeColour(200, 200, 200);
+ TheCamera.Fade(4.0f, FADE_IN);
+ } else CRestart::bFadeInAfterNextDeath = true;
+ }
+ break;
+ case WBSTATE_BUSTED:
+ if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(2.0f, FADE_OUT);
+ }
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
+ pPlayerInfo.m_WBState = WBSTATE_PLAYING;
+ int takeMoney;
+
+ switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
+ case 0:
+ case 1:
+ takeMoney = 100;
+ break;
+ case 2:
+ takeMoney = 200;
+ break;
+ case 3:
+ takeMoney = 400;
+ break;
+ case 4:
+ takeMoney = 600;
+ break;
+ case 5:
+ takeMoney = 900;
+ break;
+ case 6:
+ takeMoney = 1500;
+ break;
+ }
+ if (pPlayerInfo.m_bGetOutOfJailFree) {
+ pPlayerInfo.m_bGetOutOfJailFree = false;
+ } else {
+ pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
+ pPlayerInfo.m_pPed->ClearWeapons();
+ }
+
+ if (pPlayerInfo.m_pPed->bInVehicle) {
+ CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
+ if (pVehicle != nil) {
+ if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
+ pVehicle->pDriver = nil;
+ if (pVehicle->m_status != STATUS_WRECKED)
+ pVehicle->m_status = STATUS_ABANDONED;
+ }
+ else
+ pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
+ }
+ }
+ CEventList::Initialise();
+ CMessages::ClearMessages();
+ CCarCtrl::ClearInterestingVehicleList();
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
+ CRestart::OverrideHospitalLevel = LEVEL_NONE;
+ CRestart::OverridePoliceStationLevel = LEVEL_NONE;
+ PassTime(720);
+ RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ pPlayerInfo.m_pPed->ClearWeapons();
+ SortOutStreamingAndMemory(pPlayerInfo.GetPos());
+ TheCamera.m_fCamShakeForce = 0.0f;
+ TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
+ CPad::GetPad(0)->StopShaking(0);
+ CReferences::RemoveReferencesToPlayer();
+ CCarCtrl::CountDownToCarsAtStart = 2;
+ CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
+ if (CRestart::bFadeInAfterNextArrest) {
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(4.0f, FADE_IN);
+ } else CRestart::bFadeInAfterNextArrest = true;
+ }
+ break;
+ case WBSTATE_FAILED_CRITICAL_MISSION:
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(2.0f, FADE_OUT);
+ }
+ if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
+ pPlayerInfo.m_WBState = WBSTATE_PLAYING;
+ if (pPlayerInfo.m_pPed->bInVehicle) {
+ CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
+ if (pVehicle != nil) {
+ if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
+ pVehicle->pDriver = nil;
+ if (pVehicle->m_status != STATUS_WRECKED)
+ pVehicle->m_status = STATUS_ABANDONED;
+ } else
+ pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
+ }
+ }
+ CEventList::Initialise();
+ CMessages::ClearMessages();
+ CCarCtrl::ClearInterestingVehicleList();
+ CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
+ CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
+ CRestart::OverridePoliceStationLevel = LEVEL_NONE;
+ CRestart::OverrideHospitalLevel = LEVEL_NONE;
+ RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
+ SortOutStreamingAndMemory(pPlayerInfo.GetPos());
+ TheCamera.m_fCamShakeForce = 0.0f;
+ TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
+ CPad::GetPad(0)->StopShaking(0);
+ CReferences::RemoveReferencesToPlayer();
+ CCarCtrl::CountDownToCarsAtStart = 2;
+ CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
+ TheCamera.SetFadeColour(0, 0, 0);
+ TheCamera.Fade(4.0f, FADE_IN);
+ }
+ break;
+ case 4:
+ return;
+ }
+}
+
+void
+CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
+{
+ pPlayerPed->m_fHealth = 100.0f;
+ pPlayerPed->m_fArmour = 0.0f;
+ pPlayerPed->bIsVisible = true;
+ pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
+ pPlayerPed->bDoBloodyFootprints = false;
+ pPlayerPed->ClearAdrenaline();
+ pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
+ if (pPlayerPed->m_pFire)
+ pPlayerPed->m_pFire->Extinguish();
+ pPlayerPed->bInVehicle = false;
+ pPlayerPed->m_pMyVehicle = nil;
+ pPlayerPed->m_pVehicleAnim = nil;
+ pPlayerPed->m_pWanted->Reset();
+ pPlayerPed->RestartNonPartialAnims();
+ pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
+ pPlayerPed->bRemoveFromWorld = false;
+ pPlayerPed->ClearWeaponTarget();
+ pPlayerPed->SetInitialState();
+ CCarCtrl::ClearInterestingVehicleList();
+
+ pos.z += 1.0f;
+ pPlayerPed->Teleport(pos);
+ pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
+
+ pPlayerPed->m_fRotationCur = DEGTORAD(angle);
+ pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
+ pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
+ CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
+ CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
+ pPlayerPed->RestoreHeadingRate();
+ TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
+ CReferences::RemoveReferencesToPlayer();
+ CGarages::PlayerArrestedOrDied();
+ CStats::CheckPointReachedUnsuccessfully();
+ 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);
+ InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/control/GameLogic.h b/src/control/GameLogic.h
index db626558..43e244a3 100644
--- a/src/control/GameLogic.h
+++ b/src/control/GameLogic.h
@@ -1,13 +1,13 @@
-#pragma once
-
-class CGameLogic
-{
-public:
- static void InitAtStartOfGame();
- static void PassTime(uint32 time);
- static void SortOutStreamingAndMemory(const CVector &pos);
- static void Update();
- static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
-
- static uint8 ActivePlayers;
+#pragma once
+
+class CGameLogic
+{
+public:
+ static void InitAtStartOfGame();
+ static void PassTime(uint32 time);
+ static void SortOutStreamingAndMemory(const CVector &pos);
+ static void Update();
+ static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
+
+ static uint8 ActivePlayers;
}; \ No newline at end of file
diff --git a/src/control/Gangs.cpp b/src/control/Gangs.cpp
index ac32ad98..57d9c67e 100644
--- a/src/control/Gangs.cpp
+++ b/src/control/Gangs.cpp
@@ -1,7 +1,7 @@
#include "common.h"
#include "patcher.h"
#include "ModelIndices.h"
-#include "Gangs.h"
+#include "Gangs.h"
#include "Weapon.h"
//CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
@@ -57,20 +57,20 @@ void CGangs::SaveAllGangData(uint8 *buf, uint32 *size)
{
INITSAVEBUF
- *size = SAVE_HEADER_SIZE + sizeof(Gang);
+ *size = SAVE_HEADER_SIZE + sizeof(Gang);
WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE);
- for (int i = 0; i < NUM_GANGS; i++)
- WriteSaveBuf(buf, Gang[i]);
-
+ for (int i = 0; i < NUM_GANGS; i++)
+ WriteSaveBuf(buf, Gang[i]);
+
VALIDATESAVEBUF(*size);
}
void CGangs::LoadAllGangData(uint8 *buf, uint32 size)
{
- Initialise();
-
-INITSAVEBUF
- // original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
+ Initialise();
+
+INITSAVEBUF
+ // original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_GANGS; i++)
diff --git a/src/control/OnscreenTimer.h b/src/control/OnscreenTimer.h
index b1e0e622..fb139266 100644
--- a/src/control/OnscreenTimer.h
+++ b/src/control/OnscreenTimer.h
@@ -1,49 +1,49 @@
-#pragma once
-
-enum
-{
- COUNTER_DISPLAY_NUMBER,
- COUNTER_DISPLAY_BAR,
-};
-
-class COnscreenTimerEntry
-{
-public:
- uint32 m_nTimerOffset;
- uint32 m_nCounterOffset;
- char m_aTimerText[10];
- char m_aCounterText[10];
- uint16 m_nType;
- char m_bCounterBuffer[42];
- char m_bTimerBuffer[42];
- bool m_bTimerProcessed;
- bool m_bCounterProcessed;
-
- void Process();
- bool ProcessForDisplay();
-
- void ProcessForDisplayClock();
- void ProcessForDisplayCounter();
-};
-
-static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
-
-class COnscreenTimer
-{
-public:
- COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
- bool m_bProcessed;
- bool m_bDisabled;
-
- void Init();
- void Process();
- void ProcessForDisplay();
-
- void ClearCounter(uint32 offset);
- void ClearClock(uint32 offset);
-
- void AddCounter(uint32 offset, uint16 type, char* text);
- void AddClock(uint32 offset, char* text);
-};
-
+#pragma once
+
+enum
+{
+ COUNTER_DISPLAY_NUMBER,
+ COUNTER_DISPLAY_BAR,
+};
+
+class COnscreenTimerEntry
+{
+public:
+ uint32 m_nTimerOffset;
+ uint32 m_nCounterOffset;
+ char m_aTimerText[10];
+ char m_aCounterText[10];
+ uint16 m_nType;
+ char m_bCounterBuffer[42];
+ char m_bTimerBuffer[42];
+ bool m_bTimerProcessed;
+ bool m_bCounterProcessed;
+
+ void Process();
+ bool ProcessForDisplay();
+
+ void ProcessForDisplayClock();
+ void ProcessForDisplayCounter();
+};
+
+static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
+
+class COnscreenTimer
+{
+public:
+ COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
+ bool m_bProcessed;
+ bool m_bDisabled;
+
+ void Init();
+ void Process();
+ void ProcessForDisplay();
+
+ void ClearCounter(uint32 offset);
+ void ClearClock(uint32 offset);
+
+ void AddCounter(uint32 offset, uint16 type, char* text);
+ void AddClock(uint32 offset, char* text);
+};
+
static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error"); \ No newline at end of file
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 3e3c2a48..774abd8c 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -1,1049 +1,1049 @@
-#include "common.h"
-#include "patcher.h"
-#include "main.h"
-
-#include "Camera.h"
-#include "Coronas.h"
-#include "Darkel.h"
-#include "Entity.h"
-#include "Explosion.h"
-#include "Font.h"
-#include "Garages.h"
-#include "General.h"
-#include "ModelIndices.h"
-#include "Object.h"
-#include "Pad.h"
-#include "Pickups.h"
-#include "PlayerPed.h"
-#include "Wanted.h"
-#include "DMAudio.h"
-#include "Fire.h"
-#include "PointLights.h"
-#include "Pools.h"
-#ifdef FIX_BUGS
-#include "Replay.h"
-#endif
-#include "Script.h"
-#include "Shadows.h"
-#include "SpecialFX.h"
-#include "Sprite.h"
-#include "Timer.h"
-#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;
-
-// unused
-bool &CPickups::bPickUpcamActivated = *(bool*)0x95CD71;
-CVehicle *&CPickups::pPlayerVehicle = *(CVehicle**)0x8F29E8;
-CVector &CPickups::StaticCamCoors = *(CVector*)0x9404C8;
-uint32 &CPickups::StaticCamStartTime = *(uint32*)0x8E289C;
-
-tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES];
-
-// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4)
-uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 };
-uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 };
-uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 };
-
-uint8 aWeaponReds[] = { 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 255, 128, 0, 255, 0 };
-uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0 };
-uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
-float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
-
-WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); }
-WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); }
-WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); }
-WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); }
-WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); }
-WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
-WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); }
-WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); }
-WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); }
-WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); }
-WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); }
-WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); }
-WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); }
-WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); }
-WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); }
-
-
-void
-CPickup::RemoveKeepType()
-{
- CWorld::Remove(m_pObject);
- delete m_pObject;
-
- m_bRemoved = true;
- m_pObject = nil;
-}
-
-void
-CPickup::Remove()
-{
- RemoveKeepType();
- m_eType = PICKUP_NONE;
-}
-
-CObject *
-CPickup::GiveUsAPickUpObject(int32 handle)
-{
- CObject *object;
-
- if (handle <= 0) object = new CObject(m_eModelIndex, false);
- else {
- CPools::MakeSureSlotInObjectPoolIsEmpty(handle);
- object = new(handle) CObject(m_eModelIndex, false);
- }
-
- if (object == nil) return nil;
- object->ObjectCreatedBy = MISSION_OBJECT;
- object->GetPosition() = m_vecPos;
- object->SetOrientation(0.0f, 0.0f, -HALFPI);
- object->GetMatrix().UpdateRW();
- object->UpdateRwFrame();
-
- object->bAffectedByGravity = false;
- object->bExplosionProof = true;
- object->bUsesCollision = false;
- object->bIsPickup = true;
-
- object->field_172 = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0;
-
- switch (m_eType)
- {
- case PICKUP_IN_SHOP:
- object->m_obj_flag2 = true;
- object->bOutOfStock = false;
- break;
- case PICKUP_ON_STREET:
- case PICKUP_ONCE:
- case PICKUP_ONCE_TIMEOUT:
- case PICKUP_COLLECTABLE1:
- case PICKUP_MONEY:
- case PICKUP_MINE_INACTIVE:
- case PICKUP_MINE_ARMED:
- case PICKUP_NAUTICAL_MINE_INACTIVE:
- case PICKUP_NAUTICAL_MINE_ARMED:
- case PICKUP_FLOATINGPACKAGE:
- case PICKUP_ON_STREET_SLOW:
- object->m_obj_flag2 = false;
- object->bOutOfStock = false;
- break;
- case PICKUP_IN_SHOP_OUT_OF_STOCK:
- object->m_obj_flag2 = false;
- object->bOutOfStock = true;
- object->bRenderScorched = true;
- break;
- case PICKUP_FLOATINGPACKAGE_FLOATING:
- default:
- break;
- }
- return object;
-}
-
-bool
-CPickup::CanBePickedUp(CPlayerPed *player)
-{
- assert(m_pObject != nil);
- bool cannotBePickedUp =
- (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f)
- || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f)
- || (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0)
- || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame));
- return !cannotBePickedUp;
-}
-
-bool
-CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
-{
- float waterLevel;
-
- if (m_bRemoved) {
- if (CTimer::GetTimeInMilliseconds() > m_nTimer) {
- // respawn pickup if we're far enough
- float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y);
- if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) {
- m_pObject = GiveUsAPickUpObject(-1);
- if (m_pObject) {
- CWorld::Add(m_pObject);
- m_bRemoved = false;
- }
- }
- }
- return false;
- }
-
- if (!m_pObject) return false;
-
- if (!IsMine()) {
- // let's check if we touched the pickup
- bool isPickupTouched = false;
- if (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) {
- if (vehicle != nil) {
- if (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f))
- isPickupTouched = true;
- }
- else {
- if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
- if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
- (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
- isPickupTouched = true;
- }
- }
- } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) {
- if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
- isPickupTouched = true;
- }
- } else if (vehicle == nil) {
- if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
- if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
- (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
- isPickupTouched = true;
- }
- }
-
- // if we didn't then we've got nothing to do
- if (isPickupTouched && CanBePickedUp(player)) {
- CPad::GetPad(0)->StartShake(120, 100);
- switch (m_eType)
- {
- case PICKUP_IN_SHOP:
- if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]) {
- CGarages::TriggerMessage("PU_MONY", -1, 6000, -1);
- } else {
- CWorld::Players[playerId].m_nMoney -= CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())];
- if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE);
- }
- RemoveKeepType();
- m_nTimer = CTimer::GetTimeInMilliseconds() + 5000;
- return true;
- }
- break;
- case PICKUP_ON_STREET:
- case PICKUP_ON_STREET_SLOW:
- if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon_OnStreet[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
- if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) {
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
- }
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
- } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) {
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- CPickups::bPickUpcamActivated = true;
- CPickups::pPlayerVehicle = FindPlayerVehicle();
- CPickups::StaticCamCoors = m_pObject->GetPosition();
- CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds();
- }
- }
- if (m_eType == PICKUP_ON_STREET) {
- m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
- } else if (m_eType == PICKUP_ON_STREET_SLOW) {
- if (MI_PICKUP_BRIBE == m_pObject->m_modelIndex)
- m_nTimer = CTimer::GetTimeInMilliseconds() + 300000;
- else
- m_nTimer = CTimer::GetTimeInMilliseconds() + 720000;
- }
-
- RemoveKeepType();
- return true;
- case PICKUP_ONCE:
- case PICKUP_ONCE_TIMEOUT:
- if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
- if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
- player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
- if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED))
- player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
- }
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
- }
- Remove();
- return true;
- case PICKUP_COLLECTABLE1:
- CWorld::Players[playerId].m_nCollectedPackages++;
- CWorld::Players[playerId].m_nMoney += 1000;
-
- if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) {
- printf("All collectables have been picked up\n");
- CGarages::TriggerMessage("CO_ALL", -1, 5000, -1);
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000;
- } else
- CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
-
- Remove();
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0);
- return true;
- case PICKUP_MONEY:
- CWorld::Players[playerId].m_nMoney += m_nQuantity;
- sprintf(gString, "$%d", m_nQuantity);
-#ifdef MONEY_MESSAGES
- CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f);
-#endif
- Remove();
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
- return true;
- //case PICKUP_IN_SHOP_OUT_OF_STOCK:
- //case PICKUP_MINE_INACTIVE:
- //case PICKUP_MINE_ARMED:
- //case PICKUP_NAUTICAL_MINE_INACTIVE:
- //case PICKUP_NAUTICAL_MINE_ARMED:
- //case PICKUP_FLOATINGPACKAGE:
- //case PICKUP_FLOATINGPACKAGE_FLOATING:
- default:
- break;
- }
- }
- } else {
- switch (m_eType)
- {
- case PICKUP_MINE_INACTIVE:
- if (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
- m_eType = PICKUP_MINE_ARMED;
- m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
- }
- break;
- case PICKUP_NAUTICAL_MINE_INACTIVE:
- {
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
- m_pObject->GetPosition().z = waterLevel + 0.6f;
-
- m_pObject->GetMatrix().UpdateRW();
- m_pObject->UpdateRwFrame();
-
- bool touched = false;
- for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
- CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
- touched = true;
- break; // added break here
- }
- }
-
- if (!touched) {
- m_eType = PICKUP_NAUTICAL_MINE_ARMED;
- m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
- }
- break;
- }
- case PICKUP_NAUTICAL_MINE_ARMED:
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
- m_pObject->GetPosition().z = waterLevel + 0.6f;
-
- m_pObject->GetMatrix().UpdateRW();
- m_pObject->UpdateRwFrame();
- // no break here
- case PICKUP_MINE_ARMED:
- {
- bool explode = false;
- if (CTimer::GetTimeInMilliseconds() > m_nTimer)
- explode = true;
- else {// added else here since vehicle lookup is useless
- for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
- CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
- explode = true;
- break; // added break here
- }
- }
- }
- if (explode) {
- CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0);
- Remove();
- }
- break;
- }
- case PICKUP_FLOATINGPACKAGE:
- m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep();
- m_pObject->GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep();
-
- m_pObject->GetMatrix().UpdateRW();
- m_pObject->UpdateRwFrame();
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z)
- m_eType = PICKUP_FLOATINGPACKAGE_FLOATING;
- break;
- case PICKUP_FLOATINGPACKAGE_FLOATING:
- if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0))
- m_pObject->GetPosition().z = waterLevel;
-
- m_pObject->GetMatrix().UpdateRW();
- m_pObject->UpdateRwFrame();
- if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
- Remove();
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0);
- return true;
- }
- break;
- }
- }
- if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)
- Remove();
- return false;
-}
-
-void
-CPickups::Init(void)
-{
- NumMessages = 0;
- for (int i = 0; i < NUMPICKUPS; i++) {
- aPickUps[i].m_eType = PICKUP_NONE;
- aPickUps[i].m_nIndex = 1;
- aPickUps[i].m_pObject = nil;
- }
-
- for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++)
- aPickUpsCollected[i] = 0;
-
- CollectedPickUpIndex = 0;
-}
-
-bool
-CPickups::IsPickUpPickedUp(int32 pickupId)
-{
- for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
- if (pickupId == aPickUpsCollected[i]) {
- aPickUpsCollected[i] = 0;
- return true;
- }
- }
- return false;
-}
-
-void
-CPickups::PassTime(uint32 time)
-{
- for (int i = 0; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType != PICKUP_NONE) {
- if (aPickUps[i].m_nTimer <= time)
- aPickUps[i].m_nTimer = 0;
- else
- aPickUps[i].m_nTimer -= time;
- }
- }
-}
-
-int32
-CPickups::GetActualPickupIndex(int32 index)
-{
- if (index == -1) return -1;
-
- // doesn't look nice
- if ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1;
- return (uint16)index;
-}
-
-bool
-CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
-{
- CPlayerPed *player;
-
- if (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
- else player = CWorld::Players[playerIndex].m_pPed;
-
- if (modelIndex == MI_PICKUP_ADRENALINE) {
- player->m_bAdrenalineActive = true;
- player->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000;
- player->m_fCurrentStamina = player->m_fMaxStamina;
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_BODYARMOUR) {
- player->m_fArmour = 100.0f;
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_INFO) {
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_HEALTH) {
- player->m_fHealth = 100.0f;
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_BONUS) {
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_BRIBE) {
- int32 level = FindPlayerPed()->m_pWanted->m_nWantedLevel - 1;
- if (level < 0) level = 0;
- player->SetWantedLevel(level);
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- return true;
- } else if (modelIndex == MI_PICKUP_KILLFRENZY) {
- DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
- return true;
- }
- return false;
-}
-
-void
-CPickups::RemoveAllFloatingPickups()
-{
- for (int i = 0; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE || aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE_FLOATING) {
- if (aPickUps[i].m_pObject) {
- CWorld::Remove(aPickUps[i].m_pObject);
- delete aPickUps[i].m_pObject;
- aPickUps[i].m_pObject = nil;
- }
- }
- }
-}
-
-void
-CPickups::RemovePickUp(int32 pickupIndex)
-{
- int32 index = CPickups::GetActualPickupIndex(pickupIndex);
- if (index == -1) return;
-
- if (aPickUps[index].m_pObject) {
- CWorld::Remove(aPickUps[index].m_pObject);
- delete aPickUps[index].m_pObject;
- aPickUps[index].m_pObject = nil;
- }
- aPickUps[index].m_eType = PICKUP_NONE;
- aPickUps[index].m_bRemoved = true;
-}
-
-int32
-CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity)
-{
- bool bFreeFound = false;
- int32 slot = 0;
-
- if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) {
- for (slot = NUMPICKUPS; slot >= 0; slot--) {
- if (aPickUps[slot].m_eType == PICKUP_NONE) {
- bFreeFound = true;
- break;
- }
- }
- } else {
- for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
- if (aPickUps[slot].m_eType == PICKUP_NONE) {
- bFreeFound = true;
- break;
- }
- }
- }
-
- if (!bFreeFound)
- {
- for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
- if (aPickUps[slot].m_eType == PICKUP_MONEY) break;
- }
-
- if (slot >= NUMGENERALPICKUPS)
- {
- for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
- if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break;
- }
-
- if (slot >= NUMGENERALPICKUPS) return -1;
- }
- }
-
- if (slot >= NUMPICKUPS) return -1;
-
- aPickUps[slot].m_eType = (ePickupType)type;
- aPickUps[slot].m_bRemoved = false;
- aPickUps[slot].m_nQuantity = quantity;
- if (type == PICKUP_ONCE_TIMEOUT)
- aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000;
- else if (type == PICKUP_MONEY)
- aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
- else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) {
- aPickUps[slot].m_eType = PICKUP_MINE_INACTIVE;
- aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
- } else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) {
- aPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE;
- aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
- }
- aPickUps[slot].m_eModelIndex = modelIndex;
- aPickUps[slot].m_vecPos = pos;
- aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(-1);
- if (aPickUps[slot].m_pObject)
- CWorld::Add(aPickUps[slot].m_pObject);
- return GetNewUniquePickupIndex(slot);
-}
-
-int32
-CPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity)
-{
- return GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity);
-}
-
-int32
-CPickups::GetNewUniquePickupIndex(int32 slot)
-{
- if (aPickUps[slot].m_nIndex >= 0xFFFE)
- aPickUps[slot].m_nIndex = 1;
- else
- aPickUps[slot].m_nIndex++;
- return slot | (aPickUps[slot].m_nIndex << 16);
-}
-
-int32
-CPickups::ModelForWeapon(eWeaponType weaponType)
-{
- switch (weaponType)
- {
- case WEAPONTYPE_BASEBALLBAT: return MI_BASEBALL_BAT;
- case WEAPONTYPE_COLT45: return MI_COLT;
- case WEAPONTYPE_UZI: return MI_UZI;
- case WEAPONTYPE_SHOTGUN: return MI_SHOTGUN;
- case WEAPONTYPE_AK47: return MI_AK47;
- case WEAPONTYPE_M16: return MI_M16;
- case WEAPONTYPE_SNIPERRIFLE: return MI_SNIPER;
- case WEAPONTYPE_ROCKETLAUNCHER: return MI_ROCKETLAUNCHER;
- case WEAPONTYPE_FLAMETHROWER: return MI_FLAMETHROWER;
- case WEAPONTYPE_MOLOTOV: return MI_MOLOTOV;
- case WEAPONTYPE_GRENADE: return MI_GRENADE;
- }
- return 0;
-}
-
-eWeaponType
-CPickups::WeaponForModel(int32 model)
-{
- if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR;
- switch (model)
- {
- case MI_GRENADE: return WEAPONTYPE_GRENADE;
- case MI_AK47: return WEAPONTYPE_AK47;
- case MI_BASEBALL_BAT: return WEAPONTYPE_BASEBALLBAT;
- case MI_COLT: return WEAPONTYPE_COLT45;
- case MI_MOLOTOV: return WEAPONTYPE_MOLOTOV;
- case MI_ROCKETLAUNCHER: return WEAPONTYPE_ROCKETLAUNCHER;
- case MI_SHOTGUN: return WEAPONTYPE_SHOTGUN;
- case MI_SNIPER: return WEAPONTYPE_SNIPERRIFLE;
- case MI_UZI: return WEAPONTYPE_UZI;
- case MI_MISSILE: return WEAPONTYPE_UNARMED;
- case MI_M16: return WEAPONTYPE_M16;
- case MI_FLAMETHROWER: return WEAPONTYPE_FLAMETHROWER;
- }
- return WEAPONTYPE_UNARMED;
-}
-
-int32
-CPickups::FindColourIndexForWeaponMI(int32 model)
-{
- return WeaponForModel(model) - 1;
-}
-
-void
-CPickups::AddToCollectedPickupsArray(int32 index)
-{
- aPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16);
- if (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS)
- CollectedPickUpIndex = 0;
-}
-
-void
-CPickups::Update()
-{
-#ifdef FIX_BUGS // RIP speedrunning (solution from SA)
- if (CReplay::IsPlayingBack())
- return;
-#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++) {
-#else // BUG: this code can only reach 318 out of 320 pickups
- for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) {
-#endif
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
- AddToCollectedPickupsArray(i);
- }
- }
-#undef PICKUPS_FRAME_SPAN
- for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) {
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
- AddToCollectedPickupsArray(i);
- }
- }
-}
-
-void
-CPickups::DoPickUpEffects(CEntity *entity)
-{
- if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
- entity->m_flagD80 = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame;
-
- if (!entity->m_flagD80) {
- float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
- float modifiedSin = 0.3f * (s + 1.0f);
-
-
- int16 colorId;
-
- if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA)
- colorId = 11;
- else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE)
- colorId = 12;
- else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
- colorId = 13;
- else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS)
- colorId = 14;
- else
- colorId = FindColourIndexForWeaponMI(entity->GetModelIndex());
-
- assert(colorId >= 0);
-
- CVector &pos = entity->GetPosition();
-
- float colorModifier = ((CGeneral::GetRandomNumber() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f;
- CShadows::StoreStaticShadow(
- (uintptr)entity,
- SHADOWTYPE_ADDITIVE,
- gpShadowExplosionTex,
- &pos,
- 2.0f, 0.0f, 0.0f, -2.0f,
- 255, // this is 0 on PC which results in no shadow
- aWeaponReds[colorId] * colorModifier, aWeaponGreens[colorId] * colorModifier, aWeaponBlues[colorId] * colorModifier,
- 4.0f, 1.0f, 40.0f, false, 0.0f);
-
- float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f;
- CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aWeaponReds[colorId] * modifiedSin / 256.0f, aWeaponGreens[colorId] * modifiedSin / 256.0f, aWeaponBlues[colorId] * modifiedSin / 256.0f, CPointLights::FOG_NONE, true);
- float size = (CGeneral::GetRandomNumber() & 0xF) * 0.0005f + 0.6f;
- CCoronas::RegisterCorona( (uintptr)entity,
- aWeaponReds[colorId] * modifiedSin / 2.0f, aWeaponGreens[colorId] * modifiedSin / 2.0f, aWeaponBlues[colorId] * modifiedSin / 2.0f,
- 255,
- pos,
- 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->field_172) {
- float dist = (TheCamera.GetPosition() - pos).Magnitude();
- const float MAXDIST = 12.0f;
-
- if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) {
- RwV3d vecOut;
- float fDistX, fDistY;
- if (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) {
- aMessages[NumMessages].m_pos.x = vecOut.x;
- aMessages[NumMessages].m_pos.y = vecOut.y;
- aMessages[NumMessages].m_dist.x = fDistX;
- aMessages[NumMessages].m_dist.y = fDistY;
- aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex());
- aMessages[NumMessages].m_color.red = aWeaponReds[colorId];
- aMessages[NumMessages].m_color.green = aWeaponGreens[colorId];
- aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId];
- aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f;
- aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock;
- aMessages[NumMessages].m_quantity = object->field_172;
- NumMessages++;
- }
- }
- }
-
- entity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), aWeaponScale[colorId]);
- }
-}
-
-void
-CPickups::DoMineEffects(CEntity *entity)
-{
- CVector &pos = entity->GetPosition();
- float dist = (TheCamera.GetPosition() - pos).Magnitude();
- const float MAXDIST = 20.0f;
-
- if (dist < MAXDIST) {
- float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200));
-
- int32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f;
- CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
- 2.0f, 0.0f, 0.0f, -2.0f,
- 255, // this is 0 on PC which results in no shadow
- red, 0, 0,
- 4.0f, 1.0f, 40.0f, false, 0.0f);
- CCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- }
-
- entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400));
-}
-
-void
-CPickups::DoMoneyEffects(CEntity *entity)
-{
- CVector &pos = entity->GetPosition();
- float dist = (TheCamera.GetPosition() - pos).Magnitude();
- const float MAXDIST = 20.0f;
-
- if (dist < MAXDIST) {
- float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400));
-
- int32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f;
- CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
- 2.0f, 0.0f, 0.0f, -2.0f,
- 255, // this is 0 on PC which results in no shadow
- 0, green, 0,
- 4.0f, 1.0f, 40.0f, false, 0.0f);
- CCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- }
-
- entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800));
-}
-
-void
-CPickups::DoCollectableEffects(CEntity *entity)
-{
- CVector &pos = entity->GetPosition();
- float dist = (TheCamera.GetPosition() - pos).Magnitude();
- const float MAXDIST = 14.0f;
-
- if (dist < MAXDIST) {
- float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
-
- int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f;
- CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
- 2.0f, 0.0f, 0.0f, -2.0f,
- 255, // this is 0 on PC which results in no shadow
- color, color, color,
- 4.0f, 1.0f, 40.0f, false, 0.0f);
- CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- }
-
- entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000));
-}
-
-void
-CPickups::RenderPickUpText()
-{
- wchar *strToPrint;
- for (int32 i = 0; i < NumMessages; i++) {
- if (aMessages[i].m_quantity <= 39) {
- switch (aMessages[i].m_quantity) // could use some enum maybe
- {
- case 0:
- if (aMessages[i].m_weaponType == WEAPONTYPE_TOTALWEAPONS) { // unreachable code?
- // what is this??
- sprintf(gString, "%d/%d", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 2903);
- } else {
- if (aMessages[i].m_bOutOfStock)
- strToPrint = TheText.Get("STOCK");
- else {
- sprintf(gString, "$%d", CostOfWeapon[aMessages[i].m_weaponType]);
- AsciiToUnicode(gString, gUString);
- strToPrint = gUString;
- }
- }
- break;
- case 1:
- strToPrint = TheText.Get("SECURI");
- break;
- case 2:
- strToPrint = TheText.Get("MOONBM");
- break;
- case 3:
- strToPrint = TheText.Get("COACH");
- break;
- case 4:
- strToPrint = TheText.Get("FLATBED");
- break;
- case 5:
- strToPrint = TheText.Get("LINERUN");
- break;
- case 6:
- strToPrint = TheText.Get("TRASHM");
- break;
- case 7:
- strToPrint = TheText.Get("PATRIOT");
- break;
- case 8:
- strToPrint = TheText.Get("WHOOPEE");
- break;
- case 9:
- strToPrint = TheText.Get("BLISTA");
- break;
- case 10:
- strToPrint = TheText.Get("MULE");
- break;
- case 11:
- strToPrint = TheText.Get("YANKEE");
- break;
- case 12:
- strToPrint = TheText.Get("BOBCAT");
- break;
- case 13:
- strToPrint = TheText.Get("DODO");
- break;
- case 14:
- strToPrint = TheText.Get("BUS");
- break;
- case 15:
- strToPrint = TheText.Get("RUMPO");
- break;
- case 16:
- strToPrint = TheText.Get("PONY");
- break;
- case 17:
- strToPrint = TheText.Get("SENTINL");
- break;
- case 18:
- strToPrint = TheText.Get("CHEETAH");
- break;
- case 19:
- strToPrint = TheText.Get("BANSHEE");
- break;
- case 20:
- strToPrint = TheText.Get("IDAHO");
- break;
- case 21:
- strToPrint = TheText.Get("INFERNS");
- break;
- case 22:
- strToPrint = TheText.Get("TAXI");
- break;
- case 23:
- strToPrint = TheText.Get("KURUMA");
- break;
- case 24:
- strToPrint = TheText.Get("STRETCH");
- break;
- case 25:
- strToPrint = TheText.Get("PEREN");
- break;
- case 26:
- strToPrint = TheText.Get("STINGER");
- break;
- case 27:
- strToPrint = TheText.Get("MANANA");
- break;
- case 28:
- strToPrint = TheText.Get("LANDSTK");
- break;
- case 29:
- strToPrint = TheText.Get("STALION");
- break;
- case 30:
- strToPrint = TheText.Get("BFINJC");
- break;
- case 31:
- strToPrint = TheText.Get("CABBIE");
- break;
- case 32:
- strToPrint = TheText.Get("ESPERAN");
- break;
- case 33:
- strToPrint = TheText.Get("FIRETRK");
- break;
- case 34:
- strToPrint = TheText.Get("AMBULAN");
- break;
- case 35:
- strToPrint = TheText.Get("ENFORCR");
- break;
- case 36:
- strToPrint = TheText.Get("FBICAR");
- break;
- case 37:
- strToPrint = TheText.Get("RHINO");
- break;
- case 38:
- strToPrint = TheText.Get("BARRCKS");
- break;
- case 39:
- strToPrint = TheText.Get("POLICAR");
- break;
- default:
- break;
- }
- }
- CFont::SetPropOn();
- CFont::SetBackgroundOff();
-
- const float MAX_SCALE = 1.0f;
-
- float fScaleY = aMessages[i].m_dist.y / 100.0f;
- if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
-
- float fScaleX = aMessages[i].m_dist.x / 100.0f;
- if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
-
- CFont::SetScale(fScaleX, fScaleY);
- CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_WIDTH);
- CFont::SetJustifyOff();
-
- CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha));
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_BANK);
- CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint);
- }
- NumMessages = 0;
-}
-
-void
-CPickups::Load(uint8 *buf, uint32 size)
-{
-INITSAVEBUF
-
- for (int32 i = 0; i < NUMPICKUPS; i++) {
- aPickUps[i] = ReadSaveBuf<CPickup>(buf);
-
- if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil)
- aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((int32)aPickUps[i].m_pObject - 1);
- }
-
- CollectedPickUpIndex = ReadSaveBuf<uint16>(buf);
- ReadSaveBuf<uint16>(buf);
- NumMessages = 0;
-
- for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
- aPickUpsCollected[i] = ReadSaveBuf<int32>(buf);
-
-VALIDATESAVEBUF(size)
-}
-
-void
-CPickups::Save(uint8 *buf, uint32 *size)
-{
- *size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
-
-INITSAVEBUF
-
- for (int32 i = 0; i < NUMPICKUPS; i++) {
- CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
- if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
- buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1);
- }
-
- WriteSaveBuf(buf, CollectedPickUpIndex);
- WriteSaveBuf(buf, (uint16)0); // possibly was NumMessages
-
- for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
- WriteSaveBuf(buf, aPickUpsCollected[i]);
-
-VALIDATESAVEBUF(*size)
-}
-
-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);
-ENDPATCHES
+#include "common.h"
+#include "patcher.h"
+#include "main.h"
+
+#include "Camera.h"
+#include "Coronas.h"
+#include "Darkel.h"
+#include "Entity.h"
+#include "Explosion.h"
+#include "Font.h"
+#include "Garages.h"
+#include "General.h"
+#include "ModelIndices.h"
+#include "Object.h"
+#include "Pad.h"
+#include "Pickups.h"
+#include "PlayerPed.h"
+#include "Wanted.h"
+#include "DMAudio.h"
+#include "Fire.h"
+#include "PointLights.h"
+#include "Pools.h"
+#ifdef FIX_BUGS
+#include "Replay.h"
+#endif
+#include "Script.h"
+#include "Shadows.h"
+#include "SpecialFX.h"
+#include "Sprite.h"
+#include "Timer.h"
+#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;
+
+// unused
+bool &CPickups::bPickUpcamActivated = *(bool*)0x95CD71;
+CVehicle *&CPickups::pPlayerVehicle = *(CVehicle**)0x8F29E8;
+CVector &CPickups::StaticCamCoors = *(CVector*)0x9404C8;
+uint32 &CPickups::StaticCamStartTime = *(uint32*)0x8E289C;
+
+tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES];
+
+// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4)
+uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 };
+uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 };
+uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 };
+
+uint8 aWeaponReds[] = { 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 255, 128, 0, 255, 0 };
+uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0 };
+uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
+float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
+
+WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); }
+WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); }
+WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); }
+WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); }
+WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); }
+WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
+WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); }
+WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); }
+WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); }
+WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); }
+WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); }
+WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); }
+WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); }
+WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); }
+WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); }
+
+
+void
+CPickup::RemoveKeepType()
+{
+ CWorld::Remove(m_pObject);
+ delete m_pObject;
+
+ m_bRemoved = true;
+ m_pObject = nil;
+}
+
+void
+CPickup::Remove()
+{
+ RemoveKeepType();
+ m_eType = PICKUP_NONE;
+}
+
+CObject *
+CPickup::GiveUsAPickUpObject(int32 handle)
+{
+ CObject *object;
+
+ if (handle <= 0) object = new CObject(m_eModelIndex, false);
+ else {
+ CPools::MakeSureSlotInObjectPoolIsEmpty(handle);
+ object = new(handle) CObject(m_eModelIndex, false);
+ }
+
+ if (object == nil) return nil;
+ object->ObjectCreatedBy = MISSION_OBJECT;
+ object->GetPosition() = m_vecPos;
+ object->SetOrientation(0.0f, 0.0f, -HALFPI);
+ object->GetMatrix().UpdateRW();
+ object->UpdateRwFrame();
+
+ object->bAffectedByGravity = false;
+ object->bExplosionProof = true;
+ object->bUsesCollision = false;
+ object->bIsPickup = true;
+
+ object->field_172 = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0;
+
+ switch (m_eType)
+ {
+ case PICKUP_IN_SHOP:
+ object->m_obj_flag2 = true;
+ object->bOutOfStock = false;
+ break;
+ case PICKUP_ON_STREET:
+ case PICKUP_ONCE:
+ case PICKUP_ONCE_TIMEOUT:
+ case PICKUP_COLLECTABLE1:
+ case PICKUP_MONEY:
+ case PICKUP_MINE_INACTIVE:
+ case PICKUP_MINE_ARMED:
+ case PICKUP_NAUTICAL_MINE_INACTIVE:
+ case PICKUP_NAUTICAL_MINE_ARMED:
+ case PICKUP_FLOATINGPACKAGE:
+ case PICKUP_ON_STREET_SLOW:
+ object->m_obj_flag2 = false;
+ object->bOutOfStock = false;
+ break;
+ case PICKUP_IN_SHOP_OUT_OF_STOCK:
+ object->m_obj_flag2 = false;
+ object->bOutOfStock = true;
+ object->bRenderScorched = true;
+ break;
+ case PICKUP_FLOATINGPACKAGE_FLOATING:
+ default:
+ break;
+ }
+ return object;
+}
+
+bool
+CPickup::CanBePickedUp(CPlayerPed *player)
+{
+ assert(m_pObject != nil);
+ bool cannotBePickedUp =
+ (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame));
+ return !cannotBePickedUp;
+}
+
+bool
+CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
+{
+ float waterLevel;
+
+ if (m_bRemoved) {
+ if (CTimer::GetTimeInMilliseconds() > m_nTimer) {
+ // respawn pickup if we're far enough
+ float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y);
+ if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) {
+ m_pObject = GiveUsAPickUpObject(-1);
+ if (m_pObject) {
+ CWorld::Add(m_pObject);
+ m_bRemoved = false;
+ }
+ }
+ }
+ return false;
+ }
+
+ if (!m_pObject) return false;
+
+ if (!IsMine()) {
+ // let's check if we touched the pickup
+ bool isPickupTouched = false;
+ if (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) {
+ if (vehicle != nil) {
+ if (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f))
+ isPickupTouched = true;
+ }
+ else {
+ if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
+ if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
+ (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
+ isPickupTouched = true;
+ }
+ }
+ } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) {
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ isPickupTouched = true;
+ }
+ } else if (vehicle == nil) {
+ if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
+ if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
+ (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
+ isPickupTouched = true;
+ }
+ }
+
+ // if we didn't then we've got nothing to do
+ if (isPickupTouched && CanBePickedUp(player)) {
+ CPad::GetPad(0)->StartShake(120, 100);
+ switch (m_eType)
+ {
+ case PICKUP_IN_SHOP:
+ if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]) {
+ CGarages::TriggerMessage("PU_MONY", -1, 6000, -1);
+ } else {
+ CWorld::Players[playerId].m_nMoney -= CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())];
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE);
+ }
+ RemoveKeepType();
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ return true;
+ }
+ break;
+ case PICKUP_ON_STREET:
+ case PICKUP_ON_STREET_SLOW:
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon_OnStreet[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) {
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ }
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
+ } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ CPickups::bPickUpcamActivated = true;
+ CPickups::pPlayerVehicle = FindPlayerVehicle();
+ CPickups::StaticCamCoors = m_pObject->GetPosition();
+ CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds();
+ }
+ }
+ if (m_eType == PICKUP_ON_STREET) {
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ } else if (m_eType == PICKUP_ON_STREET_SLOW) {
+ if (MI_PICKUP_BRIBE == m_pObject->m_modelIndex)
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 300000;
+ else
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 720000;
+ }
+
+ RemoveKeepType();
+ return true;
+ case PICKUP_ONCE:
+ case PICKUP_ONCE_TIMEOUT:
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED))
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ }
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
+ }
+ Remove();
+ return true;
+ case PICKUP_COLLECTABLE1:
+ CWorld::Players[playerId].m_nCollectedPackages++;
+ CWorld::Players[playerId].m_nMoney += 1000;
+
+ if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) {
+ printf("All collectables have been picked up\n");
+ CGarages::TriggerMessage("CO_ALL", -1, 5000, -1);
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000;
+ } else
+ CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
+
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0);
+ return true;
+ case PICKUP_MONEY:
+ CWorld::Players[playerId].m_nMoney += m_nQuantity;
+ sprintf(gString, "$%d", m_nQuantity);
+#ifdef MONEY_MESSAGES
+ CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f);
+#endif
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
+ return true;
+ //case PICKUP_IN_SHOP_OUT_OF_STOCK:
+ //case PICKUP_MINE_INACTIVE:
+ //case PICKUP_MINE_ARMED:
+ //case PICKUP_NAUTICAL_MINE_INACTIVE:
+ //case PICKUP_NAUTICAL_MINE_ARMED:
+ //case PICKUP_FLOATINGPACKAGE:
+ //case PICKUP_FLOATINGPACKAGE_FLOATING:
+ default:
+ break;
+ }
+ }
+ } else {
+ switch (m_eType)
+ {
+ case PICKUP_MINE_INACTIVE:
+ if (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ m_eType = PICKUP_MINE_ARMED;
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ }
+ break;
+ case PICKUP_NAUTICAL_MINE_INACTIVE:
+ {
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
+ m_pObject->GetPosition().z = waterLevel + 0.6f;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+
+ bool touched = false;
+ for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
+ CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
+ touched = true;
+ break; // added break here
+ }
+ }
+
+ if (!touched) {
+ m_eType = PICKUP_NAUTICAL_MINE_ARMED;
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ }
+ break;
+ }
+ case PICKUP_NAUTICAL_MINE_ARMED:
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
+ m_pObject->GetPosition().z = waterLevel + 0.6f;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ // no break here
+ case PICKUP_MINE_ARMED:
+ {
+ bool explode = false;
+ if (CTimer::GetTimeInMilliseconds() > m_nTimer)
+ explode = true;
+ else {// added else here since vehicle lookup is useless
+ for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
+ CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
+ explode = true;
+ break; // added break here
+ }
+ }
+ }
+ if (explode) {
+ CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0);
+ Remove();
+ }
+ break;
+ }
+ case PICKUP_FLOATINGPACKAGE:
+ m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep();
+ m_pObject->GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep();
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z)
+ m_eType = PICKUP_FLOATINGPACKAGE_FLOATING;
+ break;
+ case PICKUP_FLOATINGPACKAGE_FLOATING:
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0))
+ m_pObject->GetPosition().z = waterLevel;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0);
+ return true;
+ }
+ break;
+ }
+ }
+ if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)
+ Remove();
+ return false;
+}
+
+void
+CPickups::Init(void)
+{
+ NumMessages = 0;
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ aPickUps[i].m_eType = PICKUP_NONE;
+ aPickUps[i].m_nIndex = 1;
+ aPickUps[i].m_pObject = nil;
+ }
+
+ for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ aPickUpsCollected[i] = 0;
+
+ CollectedPickUpIndex = 0;
+}
+
+bool
+CPickups::IsPickUpPickedUp(int32 pickupId)
+{
+ for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
+ if (pickupId == aPickUpsCollected[i]) {
+ aPickUpsCollected[i] = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+CPickups::PassTime(uint32 time)
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE) {
+ if (aPickUps[i].m_nTimer <= time)
+ aPickUps[i].m_nTimer = 0;
+ else
+ aPickUps[i].m_nTimer -= time;
+ }
+ }
+}
+
+int32
+CPickups::GetActualPickupIndex(int32 index)
+{
+ if (index == -1) return -1;
+
+ // doesn't look nice
+ if ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1;
+ return (uint16)index;
+}
+
+bool
+CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
+{
+ CPlayerPed *player;
+
+ if (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ else player = CWorld::Players[playerIndex].m_pPed;
+
+ if (modelIndex == MI_PICKUP_ADRENALINE) {
+ player->m_bAdrenalineActive = true;
+ player->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000;
+ player->m_fCurrentStamina = player->m_fMaxStamina;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BODYARMOUR) {
+ player->m_fArmour = 100.0f;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_INFO) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_HEALTH) {
+ player->m_fHealth = 100.0f;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BONUS) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BRIBE) {
+ int32 level = FindPlayerPed()->m_pWanted->m_nWantedLevel - 1;
+ if (level < 0) level = 0;
+ player->SetWantedLevel(level);
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_KILLFRENZY) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ }
+ return false;
+}
+
+void
+CPickups::RemoveAllFloatingPickups()
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE || aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE_FLOATING) {
+ if (aPickUps[i].m_pObject) {
+ CWorld::Remove(aPickUps[i].m_pObject);
+ delete aPickUps[i].m_pObject;
+ aPickUps[i].m_pObject = nil;
+ }
+ }
+ }
+}
+
+void
+CPickups::RemovePickUp(int32 pickupIndex)
+{
+ int32 index = CPickups::GetActualPickupIndex(pickupIndex);
+ if (index == -1) return;
+
+ if (aPickUps[index].m_pObject) {
+ CWorld::Remove(aPickUps[index].m_pObject);
+ delete aPickUps[index].m_pObject;
+ aPickUps[index].m_pObject = nil;
+ }
+ aPickUps[index].m_eType = PICKUP_NONE;
+ aPickUps[index].m_bRemoved = true;
+}
+
+int32
+CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity)
+{
+ bool bFreeFound = false;
+ int32 slot = 0;
+
+ if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) {
+ for (slot = NUMPICKUPS; slot >= 0; slot--) {
+ if (aPickUps[slot].m_eType == PICKUP_NONE) {
+ bFreeFound = true;
+ break;
+ }
+ }
+ } else {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_NONE) {
+ bFreeFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!bFreeFound)
+ {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_MONEY) break;
+ }
+
+ if (slot >= NUMGENERALPICKUPS)
+ {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break;
+ }
+
+ if (slot >= NUMGENERALPICKUPS) return -1;
+ }
+ }
+
+ if (slot >= NUMPICKUPS) return -1;
+
+ aPickUps[slot].m_eType = (ePickupType)type;
+ aPickUps[slot].m_bRemoved = false;
+ aPickUps[slot].m_nQuantity = quantity;
+ if (type == PICKUP_ONCE_TIMEOUT)
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000;
+ else if (type == PICKUP_MONEY)
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) {
+ aPickUps[slot].m_eType = PICKUP_MINE_INACTIVE;
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ } else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) {
+ aPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE;
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ }
+ aPickUps[slot].m_eModelIndex = modelIndex;
+ aPickUps[slot].m_vecPos = pos;
+ aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(-1);
+ if (aPickUps[slot].m_pObject)
+ CWorld::Add(aPickUps[slot].m_pObject);
+ return GetNewUniquePickupIndex(slot);
+}
+
+int32
+CPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity)
+{
+ return GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity);
+}
+
+int32
+CPickups::GetNewUniquePickupIndex(int32 slot)
+{
+ if (aPickUps[slot].m_nIndex >= 0xFFFE)
+ aPickUps[slot].m_nIndex = 1;
+ else
+ aPickUps[slot].m_nIndex++;
+ return slot | (aPickUps[slot].m_nIndex << 16);
+}
+
+int32
+CPickups::ModelForWeapon(eWeaponType weaponType)
+{
+ switch (weaponType)
+ {
+ case WEAPONTYPE_BASEBALLBAT: return MI_BASEBALL_BAT;
+ case WEAPONTYPE_COLT45: return MI_COLT;
+ case WEAPONTYPE_UZI: return MI_UZI;
+ case WEAPONTYPE_SHOTGUN: return MI_SHOTGUN;
+ case WEAPONTYPE_AK47: return MI_AK47;
+ case WEAPONTYPE_M16: return MI_M16;
+ case WEAPONTYPE_SNIPERRIFLE: return MI_SNIPER;
+ case WEAPONTYPE_ROCKETLAUNCHER: return MI_ROCKETLAUNCHER;
+ case WEAPONTYPE_FLAMETHROWER: return MI_FLAMETHROWER;
+ case WEAPONTYPE_MOLOTOV: return MI_MOLOTOV;
+ case WEAPONTYPE_GRENADE: return MI_GRENADE;
+ }
+ return 0;
+}
+
+eWeaponType
+CPickups::WeaponForModel(int32 model)
+{
+ if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR;
+ switch (model)
+ {
+ case MI_GRENADE: return WEAPONTYPE_GRENADE;
+ case MI_AK47: return WEAPONTYPE_AK47;
+ case MI_BASEBALL_BAT: return WEAPONTYPE_BASEBALLBAT;
+ case MI_COLT: return WEAPONTYPE_COLT45;
+ case MI_MOLOTOV: return WEAPONTYPE_MOLOTOV;
+ case MI_ROCKETLAUNCHER: return WEAPONTYPE_ROCKETLAUNCHER;
+ case MI_SHOTGUN: return WEAPONTYPE_SHOTGUN;
+ case MI_SNIPER: return WEAPONTYPE_SNIPERRIFLE;
+ case MI_UZI: return WEAPONTYPE_UZI;
+ case MI_MISSILE: return WEAPONTYPE_UNARMED;
+ case MI_M16: return WEAPONTYPE_M16;
+ case MI_FLAMETHROWER: return WEAPONTYPE_FLAMETHROWER;
+ }
+ return WEAPONTYPE_UNARMED;
+}
+
+int32
+CPickups::FindColourIndexForWeaponMI(int32 model)
+{
+ return WeaponForModel(model) - 1;
+}
+
+void
+CPickups::AddToCollectedPickupsArray(int32 index)
+{
+ aPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16);
+ if (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS)
+ CollectedPickUpIndex = 0;
+}
+
+void
+CPickups::Update()
+{
+#ifdef FIX_BUGS // RIP speedrunning (solution from SA)
+ if (CReplay::IsPlayingBack())
+ return;
+#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++) {
+#else // BUG: this code can only reach 318 out of 320 pickups
+ for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) {
+#endif
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ AddToCollectedPickupsArray(i);
+ }
+ }
+#undef PICKUPS_FRAME_SPAN
+ for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ AddToCollectedPickupsArray(i);
+ }
+ }
+}
+
+void
+CPickups::DoPickUpEffects(CEntity *entity)
+{
+ if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
+ entity->m_flagD80 = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame;
+
+ if (!entity->m_flagD80) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
+ float modifiedSin = 0.3f * (s + 1.0f);
+
+
+ int16 colorId;
+
+ if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA)
+ colorId = 11;
+ else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE)
+ colorId = 12;
+ else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
+ colorId = 13;
+ else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS)
+ colorId = 14;
+ else
+ colorId = FindColourIndexForWeaponMI(entity->GetModelIndex());
+
+ assert(colorId >= 0);
+
+ CVector &pos = entity->GetPosition();
+
+ float colorModifier = ((CGeneral::GetRandomNumber() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f;
+ CShadows::StoreStaticShadow(
+ (uintptr)entity,
+ SHADOWTYPE_ADDITIVE,
+ gpShadowExplosionTex,
+ &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ aWeaponReds[colorId] * colorModifier, aWeaponGreens[colorId] * colorModifier, aWeaponBlues[colorId] * colorModifier,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+
+ float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f;
+ CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aWeaponReds[colorId] * modifiedSin / 256.0f, aWeaponGreens[colorId] * modifiedSin / 256.0f, aWeaponBlues[colorId] * modifiedSin / 256.0f, CPointLights::FOG_NONE, true);
+ float size = (CGeneral::GetRandomNumber() & 0xF) * 0.0005f + 0.6f;
+ CCoronas::RegisterCorona( (uintptr)entity,
+ aWeaponReds[colorId] * modifiedSin / 2.0f, aWeaponGreens[colorId] * modifiedSin / 2.0f, aWeaponBlues[colorId] * modifiedSin / 2.0f,
+ 255,
+ pos,
+ 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->field_172) {
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 12.0f;
+
+ if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) {
+ RwV3d vecOut;
+ float fDistX, fDistY;
+ if (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) {
+ aMessages[NumMessages].m_pos.x = vecOut.x;
+ aMessages[NumMessages].m_pos.y = vecOut.y;
+ aMessages[NumMessages].m_dist.x = fDistX;
+ aMessages[NumMessages].m_dist.y = fDistY;
+ aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex());
+ aMessages[NumMessages].m_color.red = aWeaponReds[colorId];
+ aMessages[NumMessages].m_color.green = aWeaponGreens[colorId];
+ aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId];
+ aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f;
+ aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock;
+ aMessages[NumMessages].m_quantity = object->field_172;
+ NumMessages++;
+ }
+ }
+ }
+
+ entity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), aWeaponScale[colorId]);
+ }
+}
+
+void
+CPickups::DoMineEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 20.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200));
+
+ int32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ red, 0, 0,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400));
+}
+
+void
+CPickups::DoMoneyEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 20.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400));
+
+ int32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ 0, green, 0,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800));
+}
+
+void
+CPickups::DoCollectableEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 14.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
+
+ int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ color, color, color,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000));
+}
+
+void
+CPickups::RenderPickUpText()
+{
+ wchar *strToPrint;
+ for (int32 i = 0; i < NumMessages; i++) {
+ if (aMessages[i].m_quantity <= 39) {
+ switch (aMessages[i].m_quantity) // could use some enum maybe
+ {
+ case 0:
+ if (aMessages[i].m_weaponType == WEAPONTYPE_TOTALWEAPONS) { // unreachable code?
+ // what is this??
+ sprintf(gString, "%d/%d", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 2903);
+ } else {
+ if (aMessages[i].m_bOutOfStock)
+ strToPrint = TheText.Get("STOCK");
+ else {
+ sprintf(gString, "$%d", CostOfWeapon[aMessages[i].m_weaponType]);
+ AsciiToUnicode(gString, gUString);
+ strToPrint = gUString;
+ }
+ }
+ break;
+ case 1:
+ strToPrint = TheText.Get("SECURI");
+ break;
+ case 2:
+ strToPrint = TheText.Get("MOONBM");
+ break;
+ case 3:
+ strToPrint = TheText.Get("COACH");
+ break;
+ case 4:
+ strToPrint = TheText.Get("FLATBED");
+ break;
+ case 5:
+ strToPrint = TheText.Get("LINERUN");
+ break;
+ case 6:
+ strToPrint = TheText.Get("TRASHM");
+ break;
+ case 7:
+ strToPrint = TheText.Get("PATRIOT");
+ break;
+ case 8:
+ strToPrint = TheText.Get("WHOOPEE");
+ break;
+ case 9:
+ strToPrint = TheText.Get("BLISTA");
+ break;
+ case 10:
+ strToPrint = TheText.Get("MULE");
+ break;
+ case 11:
+ strToPrint = TheText.Get("YANKEE");
+ break;
+ case 12:
+ strToPrint = TheText.Get("BOBCAT");
+ break;
+ case 13:
+ strToPrint = TheText.Get("DODO");
+ break;
+ case 14:
+ strToPrint = TheText.Get("BUS");
+ break;
+ case 15:
+ strToPrint = TheText.Get("RUMPO");
+ break;
+ case 16:
+ strToPrint = TheText.Get("PONY");
+ break;
+ case 17:
+ strToPrint = TheText.Get("SENTINL");
+ break;
+ case 18:
+ strToPrint = TheText.Get("CHEETAH");
+ break;
+ case 19:
+ strToPrint = TheText.Get("BANSHEE");
+ break;
+ case 20:
+ strToPrint = TheText.Get("IDAHO");
+ break;
+ case 21:
+ strToPrint = TheText.Get("INFERNS");
+ break;
+ case 22:
+ strToPrint = TheText.Get("TAXI");
+ break;
+ case 23:
+ strToPrint = TheText.Get("KURUMA");
+ break;
+ case 24:
+ strToPrint = TheText.Get("STRETCH");
+ break;
+ case 25:
+ strToPrint = TheText.Get("PEREN");
+ break;
+ case 26:
+ strToPrint = TheText.Get("STINGER");
+ break;
+ case 27:
+ strToPrint = TheText.Get("MANANA");
+ break;
+ case 28:
+ strToPrint = TheText.Get("LANDSTK");
+ break;
+ case 29:
+ strToPrint = TheText.Get("STALION");
+ break;
+ case 30:
+ strToPrint = TheText.Get("BFINJC");
+ break;
+ case 31:
+ strToPrint = TheText.Get("CABBIE");
+ break;
+ case 32:
+ strToPrint = TheText.Get("ESPERAN");
+ break;
+ case 33:
+ strToPrint = TheText.Get("FIRETRK");
+ break;
+ case 34:
+ strToPrint = TheText.Get("AMBULAN");
+ break;
+ case 35:
+ strToPrint = TheText.Get("ENFORCR");
+ break;
+ case 36:
+ strToPrint = TheText.Get("FBICAR");
+ break;
+ case 37:
+ strToPrint = TheText.Get("RHINO");
+ break;
+ case 38:
+ strToPrint = TheText.Get("BARRCKS");
+ break;
+ case 39:
+ strToPrint = TheText.Get("POLICAR");
+ break;
+ default:
+ break;
+ }
+ }
+ CFont::SetPropOn();
+ CFont::SetBackgroundOff();
+
+ const float MAX_SCALE = 1.0f;
+
+ float fScaleY = aMessages[i].m_dist.y / 100.0f;
+ if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
+
+ float fScaleX = aMessages[i].m_dist.x / 100.0f;
+ if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
+
+ CFont::SetScale(fScaleX, fScaleY);
+ CFont::SetCentreOn();
+ CFont::SetCentreSize(SCREEN_WIDTH);
+ CFont::SetJustifyOff();
+
+ CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha));
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint);
+ }
+ NumMessages = 0;
+}
+
+void
+CPickups::Load(uint8 *buf, uint32 size)
+{
+INITSAVEBUF
+
+ for (int32 i = 0; i < NUMPICKUPS; i++) {
+ aPickUps[i] = ReadSaveBuf<CPickup>(buf);
+
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil)
+ aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((int32)aPickUps[i].m_pObject - 1);
+ }
+
+ CollectedPickUpIndex = ReadSaveBuf<uint16>(buf);
+ ReadSaveBuf<uint16>(buf);
+ NumMessages = 0;
+
+ for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ aPickUpsCollected[i] = ReadSaveBuf<int32>(buf);
+
+VALIDATESAVEBUF(size)
+}
+
+void
+CPickups::Save(uint8 *buf, uint32 *size)
+{
+ *size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
+
+INITSAVEBUF
+
+ for (int32 i = 0; i < NUMPICKUPS; i++) {
+ CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
+ if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
+ buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1);
+ }
+
+ WriteSaveBuf(buf, CollectedPickUpIndex);
+ WriteSaveBuf(buf, (uint16)0); // possibly was NumMessages
+
+ for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ WriteSaveBuf(buf, aPickUpsCollected[i]);
+
+VALIDATESAVEBUF(*size)
+}
+
+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);
+ENDPATCHES
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index 4bb0ddff..3e075b24 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -1,124 +1,124 @@
-#pragma once
-#include "Weapon.h"
-
-enum ePickupType : uint8
-{
- PICKUP_NONE = 0,
- PICKUP_IN_SHOP,
- PICKUP_ON_STREET,
- PICKUP_ONCE,
- PICKUP_ONCE_TIMEOUT,
- PICKUP_COLLECTABLE1,
- PICKUP_IN_SHOP_OUT_OF_STOCK,
- PICKUP_MONEY,
- PICKUP_MINE_INACTIVE,
- PICKUP_MINE_ARMED,
- PICKUP_NAUTICAL_MINE_INACTIVE,
- PICKUP_NAUTICAL_MINE_ARMED,
- PICKUP_FLOATINGPACKAGE,
- PICKUP_FLOATINGPACKAGE_FLOATING,
- PICKUP_ON_STREET_SLOW,
- PICKUP_NUMOFTYPES
-};
-
-class CEntity;
-class CObject;
-class CVehicle;
-class CPlayerPed;
-
-class CPickup
-{
-public:
- ePickupType m_eType;
- bool m_bRemoved;
- uint16 m_nQuantity;
- CObject *m_pObject;
- uint32 m_nTimer;
- int16 m_eModelIndex;
- uint16 m_nIndex;
- CVector m_vecPos;
-
- CObject *GiveUsAPickUpObject(int32 handle);
- bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
-private:
- bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
- inline bool CanBePickedUp(CPlayerPed *player);
- void RemoveKeepType();
- void Remove();
-};
-
-static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
-
-struct tPickupMessage
-{
- CVector2D m_pos;
- eWeaponType m_weaponType;
- CVector2D m_dist;
- CRGBA m_color;
- uint8 m_bOutOfStock : 1;
- uint8 m_quantity;
-};
-
-class CPickups
-{
- static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
- static int16 CollectedPickUpIndex;
- static int16 NumMessages;
- static tPickupMessage aMessages[NUMPICKUPMESSAGES];
-public:
- static void Init();
- static void Update();
- static void RenderPickUpText();
- static void DoCollectableEffects(CEntity *ent);
- static void DoMoneyEffects(CEntity *ent);
- static void DoMineEffects(CEntity *ent);
- static void DoPickUpEffects(CEntity *ent);
- static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
- static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
- static void RemovePickUp(int32 pickupIndex);
- static void RemoveAllFloatingPickups();
- static void AddToCollectedPickupsArray(int32 index);
- static bool IsPickUpPickedUp(int32 pickupId);
- static int32 ModelForWeapon(eWeaponType weaponType);
- static enum eWeaponType WeaponForModel(int32 model);
- static int32 FindColourIndexForWeaponMI(int32 model);
- static int32 GetActualPickupIndex(int32 index);
- static int32 GetNewUniquePickupIndex(int32 slot);
- static void PassTime(uint32 time);
- static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
- static void Load(uint8 *buf, uint32 size);
- static void Save(uint8 *buf, uint32 *size);
-
- static CPickup(&aPickUps)[NUMPICKUPS];
-
- // unused
- static bool &bPickUpcamActivated;
- static CVehicle *&pPlayerVehicle;
- static CVector &StaticCamCoors;
- static uint32 &StaticCamStartTime;
-};
-
-extern uint16 AmmoForWeapon[20];
-extern uint16 AmmoForWeapon_OnStreet[20];
-extern uint16 CostOfWeapon[20];
-
-class CPacManPickups
-{
-public:
- static void Init(void);
- static void Update(void);
- static void GeneratePMPickUps(CVector, float, int16, uint8);
- static void GeneratePMPickUpsForRace(int32);
- static void GenerateOnePMPickUp(CVector);
- static void Render(void);
- static void DoCleanUpPacManStuff(void);
- static void StartPacManRace(int32);
- static void StartPacManRecord(void);
- static uint32 QueryPowerPillsEatenInRace(void);
- static void ResetPowerPillsEatenInRace(void);
- static void CleanUpPacManStuff(void);
- static void StartPacManScramble(CVector, float, int16);
- static uint32 QueryPowerPillsCarriedByPlayer(void);
- static void ResetPowerPillsCarriedByPlayer(void);
-
-};
+#pragma once
+#include "Weapon.h"
+
+enum ePickupType : uint8
+{
+ PICKUP_NONE = 0,
+ PICKUP_IN_SHOP,
+ PICKUP_ON_STREET,
+ PICKUP_ONCE,
+ PICKUP_ONCE_TIMEOUT,
+ PICKUP_COLLECTABLE1,
+ PICKUP_IN_SHOP_OUT_OF_STOCK,
+ PICKUP_MONEY,
+ PICKUP_MINE_INACTIVE,
+ PICKUP_MINE_ARMED,
+ PICKUP_NAUTICAL_MINE_INACTIVE,
+ PICKUP_NAUTICAL_MINE_ARMED,
+ PICKUP_FLOATINGPACKAGE,
+ PICKUP_FLOATINGPACKAGE_FLOATING,
+ PICKUP_ON_STREET_SLOW,
+ PICKUP_NUMOFTYPES
+};
+
+class CEntity;
+class CObject;
+class CVehicle;
+class CPlayerPed;
+
+class CPickup
+{
+public:
+ ePickupType m_eType;
+ bool m_bRemoved;
+ uint16 m_nQuantity;
+ CObject *m_pObject;
+ uint32 m_nTimer;
+ int16 m_eModelIndex;
+ uint16 m_nIndex;
+ CVector m_vecPos;
+
+ CObject *GiveUsAPickUpObject(int32 handle);
+ bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
+private:
+ bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
+ inline bool CanBePickedUp(CPlayerPed *player);
+ void RemoveKeepType();
+ void Remove();
+};
+
+static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
+
+struct tPickupMessage
+{
+ CVector2D m_pos;
+ eWeaponType m_weaponType;
+ CVector2D m_dist;
+ CRGBA m_color;
+ uint8 m_bOutOfStock : 1;
+ uint8 m_quantity;
+};
+
+class CPickups
+{
+ static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
+ static int16 CollectedPickUpIndex;
+ static int16 NumMessages;
+ static tPickupMessage aMessages[NUMPICKUPMESSAGES];
+public:
+ static void Init();
+ static void Update();
+ static void RenderPickUpText();
+ static void DoCollectableEffects(CEntity *ent);
+ static void DoMoneyEffects(CEntity *ent);
+ static void DoMineEffects(CEntity *ent);
+ static void DoPickUpEffects(CEntity *ent);
+ static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
+ static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
+ static void RemovePickUp(int32 pickupIndex);
+ static void RemoveAllFloatingPickups();
+ static void AddToCollectedPickupsArray(int32 index);
+ static bool IsPickUpPickedUp(int32 pickupId);
+ static int32 ModelForWeapon(eWeaponType weaponType);
+ static enum eWeaponType WeaponForModel(int32 model);
+ static int32 FindColourIndexForWeaponMI(int32 model);
+ static int32 GetActualPickupIndex(int32 index);
+ static int32 GetNewUniquePickupIndex(int32 slot);
+ static void PassTime(uint32 time);
+ static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
+ static void Load(uint8 *buf, uint32 size);
+ static void Save(uint8 *buf, uint32 *size);
+
+ static CPickup(&aPickUps)[NUMPICKUPS];
+
+ // unused
+ static bool &bPickUpcamActivated;
+ static CVehicle *&pPlayerVehicle;
+ static CVector &StaticCamCoors;
+ static uint32 &StaticCamStartTime;
+};
+
+extern uint16 AmmoForWeapon[20];
+extern uint16 AmmoForWeapon_OnStreet[20];
+extern uint16 CostOfWeapon[20];
+
+class CPacManPickups
+{
+public:
+ static void Init(void);
+ static void Update(void);
+ static void GeneratePMPickUps(CVector, float, int16, uint8);
+ static void GeneratePMPickUpsForRace(int32);
+ static void GenerateOnePMPickUp(CVector);
+ static void Render(void);
+ static void DoCleanUpPacManStuff(void);
+ static void StartPacManRace(int32);
+ static void StartPacManRecord(void);
+ static uint32 QueryPowerPillsEatenInRace(void);
+ static void ResetPowerPillsEatenInRace(void);
+ static void CleanUpPacManStuff(void);
+ static void StartPacManScramble(CVector, float, int16);
+ static uint32 QueryPowerPillsCarriedByPlayer(void);
+ static void ResetPowerPillsCarriedByPlayer(void);
+
+};
diff --git a/src/control/PowerPoints.cpp b/src/control/PowerPoints.cpp
index 4bc773a9..9a74e8d9 100644
--- a/src/control/PowerPoints.cpp
+++ b/src/control/PowerPoints.cpp
@@ -1,22 +1,22 @@
-#include "common.h"
-#include "PowerPoints.h"
-
-// Some cut beta feature
-
-void CPowerPoint::Update()
-{}
-
-void CPowerPoints::Init()
-{}
-
-void CPowerPoints::Update()
-{}
-
-void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
-{}
-
-void CPowerPoints::Save(uint8**, uint32*)
-{}
-
-void CPowerPoints::Load(uint8*, uint32)
+#include "common.h"
+#include "PowerPoints.h"
+
+// Some cut beta feature
+
+void CPowerPoint::Update()
+{}
+
+void CPowerPoints::Init()
+{}
+
+void CPowerPoints::Update()
+{}
+
+void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
+{}
+
+void CPowerPoints::Save(uint8**, uint32*)
+{}
+
+void CPowerPoints::Load(uint8*, uint32)
{} \ No newline at end of file
diff --git a/src/control/PowerPoints.h b/src/control/PowerPoints.h
index d7478076..ee3750cd 100644
--- a/src/control/PowerPoints.h
+++ b/src/control/PowerPoints.h
@@ -1,26 +1,26 @@
-#pragma once
-
-enum
-{
- POWERPOINT_NONE = 0,
- POWERPOINT_HEALTH,
- POWERPOINT_HIDEOUT_INDUSTRIAL,
- POWERPOINT_HIDEOUT_COMMERCIAL,
- POWERPOINT_HIDEOUT_SUBURBAN
-};
-
-class CPowerPoint
-{
-public:
- void Update();
-};
-
-class CPowerPoints
-{
-public:
- static void Init();
- static void Update();
- static void GenerateNewOne(float, float, float, float, float, float, uint8);
- static void Save(uint8**, uint32*);
- static void Load(uint8*, uint32);
+#pragma once
+
+enum
+{
+ POWERPOINT_NONE = 0,
+ POWERPOINT_HEALTH,
+ POWERPOINT_HIDEOUT_INDUSTRIAL,
+ POWERPOINT_HIDEOUT_COMMERCIAL,
+ POWERPOINT_HIDEOUT_SUBURBAN
+};
+
+class CPowerPoint
+{
+public:
+ void Update();
+};
+
+class CPowerPoints
+{
+public:
+ static void Init();
+ static void Update();
+ static void GenerateNewOne(float, float, float, float, float, float, uint8);
+ static void Save(uint8**, uint32*);
+ static void Load(uint8*, uint32);
}; \ No newline at end of file
diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp
index 8e983555..788a054a 100644
--- a/src/control/Restart.cpp
+++ b/src/control/Restart.cpp
@@ -21,234 +21,234 @@ CVector(&CRestart::PoliceRestartPoints)[NUM_RESTART_POINTS] = *(CVector(*)[NUM_R
float(&CRestart::PoliceRestartHeadings)[NUM_RESTART_POINTS] = *(float(*)[NUM_RESTART_POINTS])*(uintptr*)0x6F1D20;
uint16 &CRestart::NumberOfPoliceRestarts = *(uint16*)0x95CC44;
-void
-CRestart::Initialise()
-{
- OverridePoliceStationLevel = LEVEL_NONE;
- OverrideHospitalLevel = LEVEL_NONE;
- bFadeInAfterNextArrest = true;
- bFadeInAfterNextDeath = true;
- OverrideHeading = 0.0f;
- OverridePosition = CVector(0.0f, 0.0f, 0.0f);
- bOverrideRestart = false;
- NumberOfPoliceRestarts = 0;
- NumberOfHospitalRestarts = 0;
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
- HospitalRestartHeadings[i] = 0.0f;
- PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
- PoliceRestartHeadings[i] = 0.0f;
- }
+void
+CRestart::Initialise()
+{
+ OverridePoliceStationLevel = LEVEL_NONE;
+ OverrideHospitalLevel = LEVEL_NONE;
+ bFadeInAfterNextArrest = true;
+ bFadeInAfterNextDeath = true;
+ OverrideHeading = 0.0f;
+ OverridePosition = CVector(0.0f, 0.0f, 0.0f);
+ bOverrideRestart = false;
+ NumberOfPoliceRestarts = 0;
+ NumberOfHospitalRestarts = 0;
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
+ HospitalRestartHeadings[i] = 0.0f;
+ PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
+ PoliceRestartHeadings[i] = 0.0f;
+ }
+}
+
+void
+CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
+{
+ HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
+ HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
+}
+
+void
+CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
+{
+ PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
+ PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
+}
+
+void
+CRestart::OverrideNextRestart(const CVector &pos, float heading)
+{
+ bOverrideRestart = true;
+ OverridePosition = pos;
+ OverrideHeading = heading;
}
-void
-CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
-{
- HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
- HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
+void
+CRestart::CancelOverrideRestart()
+{
+ bOverrideRestart = false;
}
-void
-CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
-{
- PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
- PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
+void
+CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
+{
+ if (bOverrideRestart) {
+ *outPos = OverridePosition;
+ *outHeading = OverrideHeading;
+ CancelOverrideRestart();
+ return;
+ }
+
+ eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ float fMinDist = 16000000.0f;
+ int closestPoint = NUM_RESTART_POINTS;
+
+ // find closest point on this level
+ for (int i = 0; i < NumberOfHospitalRestarts; i++) {
+ if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
+ float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
+ if (fMinDist >= dist) {
+ fMinDist = dist;
+ closestPoint = i;
+ }
+ }
+ }
+
+ // if we didn't find anything, find closest point on any level
+ if (closestPoint == NUM_RESTART_POINTS) {
+ for (int i = 0; i < NumberOfHospitalRestarts; i++) {
+ float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
+ if (fMinDist >= dist) {
+ fMinDist = dist;
+ closestPoint = i;
+ }
+ }
+ }
+
+ // if we still didn't find anything, find closest path node
+ if (closestPoint == NUM_RESTART_POINTS) {
+ *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
+ *outHeading = 0.0f;
+ printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z);
+ } else {
+ *outPos = HospitalRestartPoints[closestPoint];
+ *outHeading = HospitalRestartHeadings[closestPoint];
+ }
}
-void
-CRestart::OverrideNextRestart(const CVector &pos, float heading)
-{
- bOverrideRestart = true;
- OverridePosition = pos;
- OverrideHeading = heading;
+void
+CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
+{
+ if (bOverrideRestart) {
+ *outPos = OverridePosition;
+ *outHeading = OverrideHeading;
+ CancelOverrideRestart();
+ return;
+ }
+
+ eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ float fMinDist = 16000000.0f;
+ int closestPoint = NUM_RESTART_POINTS;
+
+ // find closest point on this level
+ for (int i = 0; i < NumberOfPoliceRestarts; i++) {
+ if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
+ float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
+ if (fMinDist >= dist) {
+ fMinDist = dist;
+ closestPoint = i;
+ }
+ }
+ }
+
+ // if we didn't find anything, find closest point on any level
+ if (closestPoint == NUM_RESTART_POINTS) {
+ for (int i = 0; i < NumberOfPoliceRestarts; i++) {
+ float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
+ if (fMinDist >= dist) {
+ fMinDist = dist;
+ closestPoint = i;
+ }
+ }
+ }
+
+ // if we still didn't find anything, find closest path node
+ if (closestPoint == NUM_RESTART_POINTS) {
+ printf("Couldn't find a police restart zone near the player\n");
+ *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
+ *outHeading = 0.0f;
+ } else {
+ *outPos = PoliceRestartPoints[closestPoint];
+ *outHeading = PoliceRestartHeadings[closestPoint];
+ }
}
-void
-CRestart::CancelOverrideRestart()
-{
- bOverrideRestart = false;
+void
+CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
+{
+ Initialise();
+
+INITSAVEBUF
+ CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
+ HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
+ }
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
+ PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
+ }
+
+ NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
+ NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
+ bOverrideRestart = ReadSaveBuf<bool>(buf);
+
+ // skip something unused
+ ReadSaveBuf<uint8>(buf);
+ ReadSaveBuf<uint16>(buf);
+
+ OverridePosition = ReadSaveBuf<CVector>(buf);
+ OverrideHeading = ReadSaveBuf<float>(buf);
+ bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
+ bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
+ OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
+ OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
+VALIDATESAVEBUF(size);
}
-void
-CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
-{
- if (bOverrideRestart) {
- *outPos = OverridePosition;
- *outHeading = OverrideHeading;
- CancelOverrideRestart();
- return;
- }
-
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
- float fMinDist = 16000000.0f;
- int closestPoint = NUM_RESTART_POINTS;
-
- // find closest point on this level
- for (int i = 0; i < NumberOfHospitalRestarts; i++) {
- if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
- float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
- if (fMinDist >= dist) {
- fMinDist = dist;
- closestPoint = i;
- }
- }
- }
-
- // if we didn't find anything, find closest point on any level
- if (closestPoint == NUM_RESTART_POINTS) {
- for (int i = 0; i < NumberOfHospitalRestarts; i++) {
- float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
- if (fMinDist >= dist) {
- fMinDist = dist;
- closestPoint = i;
- }
- }
- }
-
- // if we still didn't find anything, find closest path node
- if (closestPoint == NUM_RESTART_POINTS) {
- *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
- *outHeading = 0.0f;
- printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z);
- } else {
- *outPos = HospitalRestartPoints[closestPoint];
- *outHeading = HospitalRestartHeadings[closestPoint];
- }
+void
+CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
+{
+ *size = SAVE_HEADER_SIZE
+ + sizeof(HospitalRestartPoints)
+ + sizeof(HospitalRestartHeadings)
+ + sizeof(PoliceRestartPoints)
+ + sizeof(PoliceRestartHeadings)
+ + sizeof(NumberOfHospitalRestarts)
+ + sizeof(NumberOfPoliceRestarts)
+ + sizeof(bOverrideRestart)
+ + sizeof(uint8)
+ + sizeof(uint16)
+ + sizeof(OverridePosition)
+ + sizeof(OverrideHeading)
+ + sizeof(bFadeInAfterNextDeath)
+ + sizeof(bFadeInAfterNextArrest)
+ + sizeof(OverrideHospitalLevel)
+ + sizeof(OverridePoliceStationLevel); // == 292
+
+INITSAVEBUF
+ WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ WriteSaveBuf(buf, HospitalRestartPoints[i]);
+ WriteSaveBuf(buf, HospitalRestartHeadings[i]);
+ }
+
+ for (int i = 0; i < NUM_RESTART_POINTS; i++) {
+ WriteSaveBuf(buf, PoliceRestartPoints[i]);
+ WriteSaveBuf(buf, PoliceRestartHeadings[i]);
+ }
+
+ WriteSaveBuf(buf, NumberOfHospitalRestarts);
+ WriteSaveBuf(buf, NumberOfPoliceRestarts);
+ WriteSaveBuf(buf, bOverrideRestart);
+
+ WriteSaveBuf(buf, (uint8)0);
+ WriteSaveBuf(buf, (uint16)0);
+
+ WriteSaveBuf(buf, OverridePosition);
+ WriteSaveBuf(buf, OverrideHeading);
+ WriteSaveBuf(buf, bFadeInAfterNextDeath);
+ WriteSaveBuf(buf, bFadeInAfterNextArrest);
+ WriteSaveBuf(buf, OverrideHospitalLevel);
+ WriteSaveBuf(buf, OverridePoliceStationLevel);
+VALIDATESAVEBUF(*size);
}
-void
-CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
-{
- if (bOverrideRestart) {
- *outPos = OverridePosition;
- *outHeading = OverrideHeading;
- CancelOverrideRestart();
- return;
- }
-
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
- float fMinDist = 16000000.0f;
- int closestPoint = NUM_RESTART_POINTS;
-
- // find closest point on this level
- for (int i = 0; i < NumberOfPoliceRestarts; i++) {
- if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
- float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
- if (fMinDist >= dist) {
- fMinDist = dist;
- closestPoint = i;
- }
- }
- }
-
- // if we didn't find anything, find closest point on any level
- if (closestPoint == NUM_RESTART_POINTS) {
- for (int i = 0; i < NumberOfPoliceRestarts; i++) {
- float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
- if (fMinDist >= dist) {
- fMinDist = dist;
- closestPoint = i;
- }
- }
- }
-
- // if we still didn't find anything, find closest path node
- if (closestPoint == NUM_RESTART_POINTS) {
- printf("Couldn't find a police restart zone near the player\n");
- *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
- *outHeading = 0.0f;
- } else {
- *outPos = PoliceRestartPoints[closestPoint];
- *outHeading = PoliceRestartHeadings[closestPoint];
- }
-}
-
-void
-CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
-{
- Initialise();
-
-INITSAVEBUF
- CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
- HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
- }
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
- PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
- }
-
- NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
- NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
- bOverrideRestart = ReadSaveBuf<bool>(buf);
-
- // skip something unused
- ReadSaveBuf<uint8>(buf);
- ReadSaveBuf<uint16>(buf);
-
- OverridePosition = ReadSaveBuf<CVector>(buf);
- OverrideHeading = ReadSaveBuf<float>(buf);
- bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
- bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
- OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
- OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
-VALIDATESAVEBUF(size);
-}
-
-void
-CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
-{
- *size = SAVE_HEADER_SIZE
- + sizeof(HospitalRestartPoints)
- + sizeof(HospitalRestartHeadings)
- + sizeof(PoliceRestartPoints)
- + sizeof(PoliceRestartHeadings)
- + sizeof(NumberOfHospitalRestarts)
- + sizeof(NumberOfPoliceRestarts)
- + sizeof(bOverrideRestart)
- + sizeof(uint8)
- + sizeof(uint16)
- + sizeof(OverridePosition)
- + sizeof(OverrideHeading)
- + sizeof(bFadeInAfterNextDeath)
- + sizeof(bFadeInAfterNextArrest)
- + sizeof(OverrideHospitalLevel)
- + sizeof(OverridePoliceStationLevel); // == 292
-
-INITSAVEBUF
- WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- WriteSaveBuf(buf, HospitalRestartPoints[i]);
- WriteSaveBuf(buf, HospitalRestartHeadings[i]);
- }
-
- for (int i = 0; i < NUM_RESTART_POINTS; i++) {
- WriteSaveBuf(buf, PoliceRestartPoints[i]);
- WriteSaveBuf(buf, PoliceRestartHeadings[i]);
- }
-
- WriteSaveBuf(buf, NumberOfHospitalRestarts);
- WriteSaveBuf(buf, NumberOfPoliceRestarts);
- WriteSaveBuf(buf, bOverrideRestart);
-
- WriteSaveBuf(buf, (uint8)0);
- WriteSaveBuf(buf, (uint16)0);
-
- WriteSaveBuf(buf, OverridePosition);
- WriteSaveBuf(buf, OverrideHeading);
- WriteSaveBuf(buf, bFadeInAfterNextDeath);
- WriteSaveBuf(buf, bFadeInAfterNextArrest);
- WriteSaveBuf(buf, OverrideHospitalLevel);
- WriteSaveBuf(buf, OverridePoliceStationLevel);
-VALIDATESAVEBUF(*size);
-}
-
-
+
STARTPATCHES
InjectHook(0x435E20, &CRestart::Initialise, PATCH_JUMP);
InjectHook(0x436100, &CRestart::AddHospitalRestartPoint, PATCH_JUMP);
@@ -258,5 +258,5 @@ STARTPATCHES
InjectHook(0x4361A0, &CRestart::FindClosestHospitalRestartPoint, PATCH_JUMP);
InjectHook(0x436450, &CRestart::FindClosestPoliceRestartPoint, PATCH_JUMP);
InjectHook(0x436B20, &CRestart::LoadAllRestartPoints, PATCH_JUMP);
- InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
+ InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
ENDPATCHES \ No newline at end of file