summaryrefslogtreecommitdiffstats
path: root/src/control
diff options
context:
space:
mode:
Diffstat (limited to 'src/control')
-rw-r--r--src/control/CarGen.cpp312
-rw-r--r--src/control/CarGen.h56
-rw-r--r--src/control/Cranes.cpp679
-rw-r--r--src/control/Cranes.h98
-rw-r--r--src/control/Gangs.cpp89
-rw-r--r--src/control/Gangs.h44
-rw-r--r--src/control/Garages.cpp2
-rw-r--r--src/control/Pickups.cpp1
-rw-r--r--src/control/Record.cpp13
-rw-r--r--src/control/RoadBlocks.cpp200
-rw-r--r--src/control/RoadBlocks.h2
11 files changed, 192 insertions, 1304 deletions
diff --git a/src/control/CarGen.cpp b/src/control/CarGen.cpp
deleted file mode 100644
index 721ac35a..00000000
--- a/src/control/CarGen.cpp
+++ /dev/null
@@ -1,312 +0,0 @@
-#include "common.h"
-#include "patcher.h"
-#include "CarGen.h"
-
-#include "Automobile.h"
-#include "Boat.h"
-#include "Camera.h"
-#include "CarCtrl.h"
-#include "CutsceneMgr.h"
-#include "General.h"
-#include "Pools.h"
-#include "Streaming.h"
-#include "Timer.h"
-#include "Vehicle.h"
-#include "World.h"
-
-uint8 &CTheCarGenerators::ProcessCounter = *(uint8*)0x95CDAF;
-uint32 &CTheCarGenerators::NumOfCarGenerators = *(uint32*)0x8E2C1C;
-CCarGenerator (&CTheCarGenerators::CarGeneratorArray)[NUM_CARGENS] = *(CCarGenerator(*)[NUM_CARGENS])*(uintptr*)0x87CB18;
-uint8 &CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = *(uint8*)0x95CDC6;
-uint32 &CTheCarGenerators::CurrentActiveCount = *(uint32*)0x8F2C5C;
-
-void CCarGenerator::SwitchOff()
-{
- m_nUsesRemaining = 0;
- --CTheCarGenerators::CurrentActiveCount;
-}
-
-void CCarGenerator::SwitchOn()
-{
- m_nUsesRemaining = -1;
- m_nTimer = CalcNextGen();
- ++CTheCarGenerators::CurrentActiveCount;
-}
-
-uint32 CCarGenerator::CalcNextGen()
-{
- return CTimer::GetTimeInMilliseconds() + 4;
-}
-
-void CCarGenerator::DoInternalProcessing()
-{
- if (CheckForBlockage()) {
- m_nTimer += 4;
- if (m_nUsesRemaining == 0)
- --CTheCarGenerators::CurrentActiveCount;
- return;
- }
- if (CCarCtrl::NumParkedCars >= 10)
- return;
- CStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY);
- if (!CStreaming::HasModelLoaded(m_nModelIndex))
- return;
- if (CModelInfo::IsBoatModel(m_nModelIndex)){
- CBoat* pBoat = new CBoat(m_nModelIndex, PARKED_VEHICLE);
- pBoat->bIsStatic = false;
- pBoat->bEngineOn = false;
- CVector pos = m_vecPos;
- if (pos.z <= -100.0f)
- pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
- pos.z += pBoat->GetDistanceFromCentreOfMassToBaseOfModel();
- pBoat->GetPosition() = pos;
- pBoat->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle));
- pBoat->m_status = STATUS_ABANDONED;
- pBoat->m_nDoorLock = CARLOCK_UNLOCKED;
- CWorld::Add(pBoat);
- if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm)
- pBoat->m_nAlarmState = -1;
- if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock)
- pBoat->m_nDoorLock = CARLOCK_LOCKED;
- if (m_nColor1 != -1 && m_nColor2){
- pBoat->m_currentColour1 = m_nColor1;
- pBoat->m_currentColour2 = m_nColor2;
- }
- m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pBoat);
- }else{
- bool groundFound = false;
- CVector pos = m_vecPos;
- if (pos.z > -100.0f){
- pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound);
- }else{
- CColPoint cp;
- CEntity* pEntity;
- groundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f,
- cp, pEntity, true, false, false, false, false, false, nil);
- if (groundFound)
- pos.z = cp.point.z;
- }
- if (!groundFound) {
- debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y);
- }else{
- CAutomobile* pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE);
- pCar->bIsStatic = false;
- pCar->bEngineOn = false;
- pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel();
- pCar->GetPosition() = pos;
- pCar->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle));
- pCar->m_status = STATUS_ABANDONED;
- pCar->bLightsOn = false;
- pCar->m_nDoorLock = CARLOCK_UNLOCKED;
- CWorld::Add(pCar);
- if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm)
- pCar->m_nAlarmState = -1;
- if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock)
- pCar->m_nDoorLock = CARLOCK_LOCKED;
- if (m_nColor1 != -1 && m_nColor2) {
- pCar->m_currentColour1 = m_nColor1;
- pCar->m_currentColour2 = m_nColor2;
- }
- m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pCar);
- }
- }
- if (m_nUsesRemaining < -1) /* I don't think this is a correct comparasion */
- --m_nUsesRemaining;
- m_nTimer = CalcNextGen();
- if (m_nUsesRemaining == 0)
- --CTheCarGenerators::CurrentActiveCount;
-}
-
-void CCarGenerator::Process()
-{
- if (m_nVehicleHandle == -1 &&
- (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter || CTimer::GetTimeInMilliseconds() >= m_nTimer) &&
- m_nUsesRemaining != 0 && CheckIfWithinRangeOfAnyPlayer())
- DoInternalProcessing();
- if (m_nVehicleHandle == -1)
- return;
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_nVehicleHandle);
- if (!pVehicle){
- m_nVehicleHandle = -1;
- return;
- }
- if (pVehicle->m_status != STATUS_PLAYER)
- return;
- m_nTimer += 60000;
- m_nVehicleHandle = -1;
- m_bIsBlocking = true;
- pVehicle->bExtendedRange = false;
-}
-
-void CCarGenerator::Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay)
-{
- CMatrix m1, m2, m3; /* Unused but present on stack, so I'll leave them. */
- m_vecPos = CVector(x, y, z);
- m_fAngle = angle;
- m_nModelIndex = mi;
- m_nColor1 = color1;
- m_nColor2 = color2;
- m_bForceSpawn = force;
- m_nAlarm = alarm;
- m_nDoorlock = lock;
- m_nMinDelay = min_delay;
- m_nMaxDelay = max_delay;
- m_nVehicleHandle = -1;
- m_nTimer = CTimer::GetTimeInMilliseconds() + 1;
- m_nUsesRemaining = 0;
- m_bIsBlocking = false;
- m_vecInf = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.min;
- m_vecSup = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.max;
- m_fSize = max(m_vecInf.Magnitude(), m_vecSup.Magnitude());
-}
-
-bool CCarGenerator::CheckForBlockage()
-{
- int16 entities;
- CWorld::FindObjectsKindaColliding(CVector(m_vecPos), m_fSize, 1, &entities, 2, nil, false, true, true, false, false);
- return entities > 0;
-}
-
-bool CCarGenerator::CheckIfWithinRangeOfAnyPlayer()
-{
- CVector2D direction = FindPlayerCentreOfWorld(CWorld::PlayerInFocus) - m_vecPos;
- float distance = direction.Magnitude();
- float farclip = 120.0f * TheCamera.GenerationDistMultiplier;
- float nearclip = farclip - 20.0f;
- if (distance >= farclip){
- if (m_bIsBlocking)
- m_bIsBlocking = false;
- return false;
- }
- if (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter)
- return true;
- if (m_bIsBlocking)
- return false;
- if (distance < nearclip)
- return false;
- return DotProduct2D(direction, FindPlayerSpeed()) <= 0;
-}
-
-void CCarGenerator::Save(uint8 *&buffer)
-{
- WriteSaveBuf(buffer, m_nModelIndex);
- WriteSaveBuf(buffer, m_vecPos);
- WriteSaveBuf(buffer, m_fAngle);
- WriteSaveBuf(buffer, m_nColor1);
- WriteSaveBuf(buffer, m_nColor2);
- WriteSaveBuf(buffer, m_bForceSpawn);
- WriteSaveBuf(buffer, m_nAlarm);
- WriteSaveBuf(buffer, m_nDoorlock);
- WriteSaveBuf(buffer, (uint8)0);
- WriteSaveBuf(buffer, m_nMinDelay);
- WriteSaveBuf(buffer, m_nMaxDelay);
- WriteSaveBuf(buffer, m_nTimer);
- WriteSaveBuf(buffer, m_nVehicleHandle);
- WriteSaveBuf(buffer, m_nUsesRemaining);
- WriteSaveBuf(buffer, m_bIsBlocking);
- WriteSaveBuf(buffer, (uint8)0);
- WriteSaveBuf(buffer, m_vecInf);
- WriteSaveBuf(buffer, m_vecSup);
- WriteSaveBuf(buffer, m_fSize);
-
- // or
- //WriteSaveBuf(buffer, *this);
-
-}
-
-void CCarGenerator::Load(uint8 *&buffer)
-{
- m_nModelIndex = ReadSaveBuf<uint32>(buffer);
- m_vecPos = ReadSaveBuf<CVector>(buffer);
- m_fAngle = ReadSaveBuf<float>(buffer);
- m_nColor1 = ReadSaveBuf<int16>(buffer);
- m_nColor2 = ReadSaveBuf<int16>(buffer);
- m_bForceSpawn = ReadSaveBuf<uint8>(buffer);
- m_nAlarm = ReadSaveBuf<uint8>(buffer);
- m_nDoorlock = ReadSaveBuf<uint8>(buffer);
- ReadSaveBuf<uint8>(buffer);
- m_nMinDelay = ReadSaveBuf<uint16>(buffer);
- m_nMaxDelay = ReadSaveBuf<uint16>(buffer);
- m_nTimer = ReadSaveBuf<uint32>(buffer);
- m_nVehicleHandle = ReadSaveBuf<int32>(buffer);
- m_nUsesRemaining = ReadSaveBuf<uint16>(buffer);
- m_bIsBlocking = ReadSaveBuf<bool>(buffer);
- ReadSaveBuf<uint8>(buffer);
- m_vecInf = ReadSaveBuf<CVector>(buffer);
- m_vecSup = ReadSaveBuf<CVector>(buffer);
- m_fSize = ReadSaveBuf<float>(buffer);
-
- // or
- //*this = ReadSaveBuf<CCarGenerator>(buffer);
-}
-
-void CTheCarGenerators::Process()
-{
- if (FindPlayerTrain() || CCutsceneMgr::IsCutsceneProcessing())
- return;
- if (++CTheCarGenerators::ProcessCounter == 4)
- CTheCarGenerators::ProcessCounter = 0;
- for (uint32 i = ProcessCounter; i < NumOfCarGenerators; i += 4)
- CTheCarGenerators::CarGeneratorArray[i].Process();
- if (GenerateEvenIfPlayerIsCloseCounter)
- GenerateEvenIfPlayerIsCloseCounter--;
-}
-
-int32 CTheCarGenerators::CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay)
-{
- CarGeneratorArray[NumOfCarGenerators].Setup(x, y, z, angle, mi, color1, color2, force, alarm, lock, min_delay, max_delay);
- return NumOfCarGenerators++;
-}
-
-void CTheCarGenerators::Init()
-{
- GenerateEvenIfPlayerIsCloseCounter = 0;
- NumOfCarGenerators = 0;
- ProcessCounter = 0;
- CurrentActiveCount = 0;
-}
-
-void CTheCarGenerators::SaveAllCarGenerators(uint8 *buffer, uint32 *size)
-{
- *size = 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE;
-INITSAVEBUF
- WriteSaveHeader(buffer, 'C','G','N','\0', *size - SAVE_HEADER_SIZE);
-
- WriteSaveBuf(buffer, 12); /* what is this? */
- WriteSaveBuf(buffer, NumOfCarGenerators);
- WriteSaveBuf(buffer, CurrentActiveCount);
- WriteSaveBuf(buffer, ProcessCounter);
- WriteSaveBuf(buffer, GenerateEvenIfPlayerIsCloseCounter);
- WriteSaveBuf(buffer, (int16)0);
- WriteSaveBuf(buffer, sizeof(CarGeneratorArray));
- for (int i = 0; i < NUM_CARGENS; i++){
- CarGeneratorArray[i].Save(buffer);
- }
-VALIDATESAVEBUF(*size)
-}
-
-void CTheCarGenerators::LoadAllCarGenerators(uint8* buffer, uint32 size)
-{
- Init();
-INITSAVEBUF
- assert(size == 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE);
- CheckSaveHeader(buffer, 'C','G','N','\0', size - SAVE_HEADER_SIZE);
- ReadSaveBuf<uint32>(buffer);
- NumOfCarGenerators = ReadSaveBuf<uint32>(buffer);
- CurrentActiveCount = ReadSaveBuf<uint32>(buffer);
- ProcessCounter = ReadSaveBuf<uint8>(buffer);
- GenerateEvenIfPlayerIsCloseCounter = ReadSaveBuf<uint8>(buffer);
- ReadSaveBuf<int16>(buffer);
- assert(ReadSaveBuf<uint32>(buffer) == sizeof(CarGeneratorArray));
- for (int i = 0; i < NUM_CARGENS; i++) {
- CarGeneratorArray[i].Load(buffer);
- }
-VALIDATESAVEBUF(size)
-}
-
-STARTPATCHES
-InjectHook(0x543020, CTheCarGenerators::Init, PATCH_JUMP);
-InjectHook(0x542F40, CTheCarGenerators::Process, PATCH_JUMP);
-InjectHook(0x543050, CTheCarGenerators::SaveAllCarGenerators, PATCH_JUMP);
-InjectHook(0x5431E0, CTheCarGenerators::LoadAllCarGenerators, PATCH_JUMP);
-ENDPATCHES
diff --git a/src/control/CarGen.h b/src/control/CarGen.h
deleted file mode 100644
index 75acdd56..00000000
--- a/src/control/CarGen.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#pragma once
-#include "common.h"
-#include "config.h"
-
-enum {
- CARGEN_MAXACTUALLIMIT = 100
-};
-
-class CCarGenerator
-{
- int32 m_nModelIndex;
- CVector m_vecPos;
- float m_fAngle;
- int16 m_nColor1;
- int16 m_nColor2;
- uint8 m_bForceSpawn;
- uint8 m_nAlarm;
- uint8 m_nDoorlock;
- int16 m_nMinDelay;
- int16 m_nMaxDelay;
- uint32 m_nTimer;
- int32 m_nVehicleHandle;
- uint16 m_nUsesRemaining;
- bool m_bIsBlocking;
- CVector m_vecInf;
- CVector m_vecSup;
- float m_fSize;
-public:
- void SwitchOff();
- void SwitchOn();
- uint32 CalcNextGen();
- void DoInternalProcessing();
- void Process();
- void Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);
- bool CheckForBlockage();
- bool CheckIfWithinRangeOfAnyPlayer();
- void Save(uint8*&);
- void Load(uint8*&);
- void SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; }
-};
-
-class CTheCarGenerators
-{
-public:
- static uint8 &ProcessCounter;
- static uint32 &NumOfCarGenerators;
- static CCarGenerator (&CarGeneratorArray)[NUM_CARGENS];
- static uint8 &GenerateEvenIfPlayerIsCloseCounter;
- static uint32 &CurrentActiveCount;
-
- static void Process();
- static int32 CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);
- static void Init();
- static void SaveAllCarGenerators(uint8 *, uint32 *);
- static void LoadAllCarGenerators(uint8 *, uint32);
-};
diff --git a/src/control/Cranes.cpp b/src/control/Cranes.cpp
deleted file mode 100644
index 33385dae..00000000
--- a/src/control/Cranes.cpp
+++ /dev/null
@@ -1,679 +0,0 @@
-#include "common.h"
-#include "patcher.h"
-#include "Cranes.h"
-
-#include "Camera.h"
-#include "DMAudio.h"
-#include "Garages.h"
-#include "General.h"
-#include "Entity.h"
-#include "ModelIndices.h"
-#include "Replay.h"
-#include "Object.h"
-#include "World.h"
-
-#define MAX_DISTANCE_TO_FIND_CRANE (10.0f)
-#define CRANE_UPDATE_RADIUS (300.0f)
-#define CRANE_MOVEMENT_PROCESSING_RADIUS (150.0f)
-#define CRUSHER_Z (-0.951f)
-#define MILITARY_Z (10.7862f)
-#define DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE (5.0f)
-#define DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT (0.5f)
-#define CAR_REWARD_MILITARY_CRANE (1500)
-#define CAR_MOVING_SPEED_THRESHOLD (0.01f)
-#define CRANE_SLOWDOWN_MULTIPLIER (0.3f)
-
-#define OSCILLATION_SPEED (0.002f)
-#define CAR_ROTATION_SPEED (0.0035f)
-#define CRANE_MOVEMENT_SPEED (0.001f)
-#define HOOK_ANGLE_MOVEMENT_SPEED (0.004f)
-#define HOOK_OFFSET_MOVEMENT_SPEED (0.1f)
-#define HOOK_HEIGHT_MOVEMENT_SPEED (0.06f)
-
-#define MESSAGE_SHOW_DURATION (4000)
-
-#define MAX_DISTANCE (99999.9f)
-#define MIN_VALID_POSITION (-10000.0f)
-#define DEFAULT_OFFSET (20.0f)
-
-uint32 TimerForCamInterpolation;
-
-uint32& CCranes::CarsCollectedMilitaryCrane = *(uint32*)0x8F6248;
-int32& CCranes::NumCranes = *(int32*)0x8E28AC;
-CCrane(&CCranes::aCranes)[NUM_CRANES] = *(CCrane(*)[NUM_CRANES])*(uintptr*)0x6FA4E0;
-
-void CCranes::InitCranes(void)
-{
- CarsCollectedMilitaryCrane = 0;
- NumCranes = 0;
- for (int i = 0; i < NUMSECTORS_X; i++) {
- for (int j = 0; j < NUMSECTORS_Y; j++) {
- for (CPtrNode* pNode = CWorld::GetSector(i, j)->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) {
- CEntity* pEntity = (CEntity*)pNode->item;
- if (MODELID_CRANE_1 == pEntity->GetModelIndex() ||
- MODELID_CRANE_2 == pEntity->GetModelIndex() ||
- MODELID_CRANE_3 == pEntity->GetModelIndex())
- AddThisOneCrane(pEntity);
- }
- }
- }
- for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode = pNode->next) {
- CEntity* pEntity = (CEntity*)pNode->item;
- if (MODELID_CRANE_1 == pEntity->GetModelIndex() ||
- MODELID_CRANE_2 == pEntity->GetModelIndex() ||
- MODELID_CRANE_3 == pEntity->GetModelIndex())
- AddThisOneCrane(pEntity);
- }
-}
-
-void CCranes::AddThisOneCrane(CEntity* pEntity)
-{
- pEntity->GetMatrix().ResetOrientation();
- if (NumCranes >= NUM_CRANES)
- return;
- CCrane* pCrane = &aCranes[NumCranes];
- pCrane->Init();
- pCrane->m_pCraneEntity = (CBuilding*)pEntity;
- pCrane->m_nCraneStatus = CCrane::NONE;
- pCrane->m_fHookAngle = NumCranes; // lol wtf
- while (pCrane->m_fHookAngle > TWOPI)
- pCrane->m_fHookAngle -= TWOPI;
- pCrane->m_fHookOffset = DEFAULT_OFFSET;
- pCrane->m_fHookHeight = DEFAULT_OFFSET;
- pCrane->m_nTimeForNextCheck = 0;
- pCrane->m_nCraneState = CCrane::IDLE;
- pCrane->m_bWasMilitaryCrane = false;
- pCrane->m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &aCranes[NumCranes]);
- if (pCrane->m_nAudioEntity >= 0)
- DMAudio.SetEntityStatus(pCrane->m_nAudioEntity, 1);
- pCrane->m_bIsTop = (MODELID_CRANE_1 != pEntity->GetModelIndex());
- // Is this used to avoid military crane?
- if (pCrane->m_bIsTop || pEntity->GetPosition().y > 0.0f) {
- CObject* pHook = new CObject(MI_MAGNET, false);
- pHook->ObjectCreatedBy = MISSION_OBJECT;
- pHook->bUsesCollision = false;
- pHook->bExplosionProof = true;
- pHook->bAffectedByGravity = false;
- pCrane->m_pHook = pHook;
- pCrane->CalcHookCoordinates(&pCrane->m_vecHookCurPos.x, &pCrane->m_vecHookCurPos.y, &pCrane->m_vecHookCurPos.z);
- pCrane->SetHookMatrix();
- }
- else
- pCrane->m_pHook = nil;
- NumCranes++;
-}
-
-void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY)
-{
- float fMinDistance = MAX_DISTANCE;
- float X = fPosX, Y = fPosY;
- if (X <= MIN_VALID_POSITION || Y <= MIN_VALID_POSITION) {
- X = fDropOffX;
- Y = fDropOffY;
- }
- int index = 0;
- for (int i = 0; i < NumCranes; i++) {
- float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude();
- if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) {
- fMinDistance = distance;
- index = i;
- }
- }
-#ifdef FIX_BUGS // classic
- if (fMinDistance == MAX_DISTANCE)
- return;
-#endif
- CCrane* pCrane = &aCranes[index];
- pCrane->m_fPickupX1 = fInfX;
- pCrane->m_fPickupX2 = fSupX;
- pCrane->m_fPickupY1 = fInfY;
- pCrane->m_fPickupY2 = fSupY;
- pCrane->m_vecDropoffTarget.x = fDropOffX;
- pCrane->m_vecDropoffTarget.y = fDropOffY;
- pCrane->m_vecDropoffTarget.z = fDropOffZ;
- pCrane->m_nCraneStatus = CCrane::ACTIVATED;
- pCrane->m_pVehiclePickedUp = nil;
- pCrane->m_nVehiclesCollected = 0;
- pCrane->m_fDropoffHeading = fHeading;
- pCrane->m_bIsCrusher = bIsCrusher;
- pCrane->m_bIsMilitaryCrane = bIsMilitary;
- bool military = true;
- if (!bIsMilitary && !pCrane->m_bWasMilitaryCrane)
- military = false;
- pCrane->m_bWasMilitaryCrane = military;
- pCrane->m_nTimeForNextCheck = 0;
- pCrane->m_nCraneState = CCrane::IDLE;
- float Z;
- if (bIsCrusher)
- Z = CRUSHER_Z;
- else if (bIsMilitary)
- Z = MILITARY_Z;
- else
- Z = CWorld::FindGroundZForCoord((fInfX + fSupX) / 2, (fInfY + fSupY) / 2);
- pCrane->FindParametersForTarget((fInfX + fSupX) / 2, (fInfY + fSupY) / 2, Z, &pCrane->m_fPickupAngle, &pCrane->m_fPickupDistance, &pCrane->m_fPickupHeight);
- pCrane->FindParametersForTarget(fDropOffX, fDropOffY, fDropOffZ, &pCrane->m_fDropoffAngle, &pCrane->m_fDropoffDistance, &pCrane->m_fDropoffHeight);
-}
-
-void CCranes::DeActivateCrane(float X, float Y)
-{
- float fMinDistance = MAX_DISTANCE;
- int index = 0;
- for (int i = 0; i < NumCranes; i++) {
- float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude();
- if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) {
- fMinDistance = distance;
- index = i;
- }
- }
-#ifdef FIX_BUGS // classic
- if (fMinDistance == MAX_DISTANCE)
- return;
-#endif
- aCranes[index].m_nCraneStatus = CCrane::DEACTIVATED;
- aCranes[index].m_nCraneState = CCrane::IDLE;
-}
-
-bool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle)
-{
- int index = 0;
- bool result = false;
- for (int i = 0; i < NumCranes; i++) {
- float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude();
- if (distance < MAX_DISTANCE_TO_FIND_CRANE && aCranes[i].m_pVehiclePickedUp == pVehicle) {
- if (aCranes[i].m_nCraneStatus == CCrane::LIFTING_TARGET || aCranes[i].m_nCraneStatus == CCrane::ROTATING_TARGET)
- result = true;
- }
- }
- return true;
-}
-
-void CCranes::UpdateCranes(void)
-{
- for (int i = 0; i < NumCranes; i++) {
- if (aCranes[i].m_bIsTop || aCranes[i].m_bIsCrusher ||
- (TheCamera.GetPosition().x + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().x &&
- TheCamera.GetPosition().x - CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().x &&
- TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().y &&
- TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().y))
- aCranes[i].Update();
- }
-}
-
-void CCrane::Update(void)
-{
- if (CReplay::IsPlayingBack())
- return;
- if (((m_nCraneStatus == ACTIVATED || m_nCraneStatus == DEACTIVATED) &&
- Abs(TheCamera.GetGameCamPosition().x - m_pCraneEntity->GetPosition().x) < CRANE_MOVEMENT_PROCESSING_RADIUS &&
- Abs(TheCamera.GetGameCamPosition().y - m_pCraneEntity->GetPosition().y) < CRANE_MOVEMENT_PROCESSING_RADIUS) ||
- m_nCraneState != IDLE) {
- switch (m_nCraneState) {
- case IDLE:
- if (GoTowardsTarget(m_fPickupAngle, m_fPickupDistance, GetHeightToPickup()) &&
- CTimer::GetTimeInMilliseconds() > m_nTimeForNextCheck) {
- CWorld::AdvanceCurrentScanCode();
-#ifdef FIX_BUGS
- int xstart = max(0, CWorld::GetSectorIndexX(m_fPickupX1));
- int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fPickupX2));
- int ystart = max(0, CWorld::GetSectorIndexY(m_fPickupY1));
- int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fPickupY2));
-#else
- int xstart = CWorld::GetSectorIndexX(m_fPickupX1);
- int xend = CWorld::GetSectorIndexX(m_fPickupX2);
- int ystart = CWorld::GetSectorIndexY(m_fPickupY1);
- int yend = CWorld::GetSectorIndexY(m_fPickupY1);
-#endif
- assert(xstart <= xend);
- assert(ystart <= yend);
- for (int i = xstart; i <= xend; i++) {
- for (int j = ystart; j <= yend; j++) {
- FindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES]);
- FindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);
- }
- }
- }
- break;
- case GOING_TOWARDS_TARGET:
- if (m_pVehiclePickedUp){
- if (m_pVehiclePickedUp->GetPosition().x < m_fPickupX1 ||
- m_pVehiclePickedUp->GetPosition().x > m_fPickupX2 ||
- m_pVehiclePickedUp->GetPosition().y < m_fPickupY1 ||
- m_pVehiclePickedUp->GetPosition().y > m_fPickupY2 ||
- m_pVehiclePickedUp->pDriver ||
- Abs(m_pVehiclePickedUp->GetMoveSpeed().x) > CAR_MOVING_SPEED_THRESHOLD ||
- Abs(m_pVehiclePickedUp->GetMoveSpeed().y) > CAR_MOVING_SPEED_THRESHOLD ||
- Abs(m_pVehiclePickedUp->GetMoveSpeed().z) > CAR_MOVING_SPEED_THRESHOLD ||
- FindPlayerPed()->GetPedState() == PED_ENTER_CAR && // TODO: fix carjack bug
- FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) {
- m_pVehiclePickedUp = nil;
- m_nCraneState = IDLE;
- }
- else {
- float fAngle, fOffset, fHeight;
- FindParametersForTarget(
- m_pVehiclePickedUp->GetPosition().x,
- m_pVehiclePickedUp->GetPosition().y,
- m_pVehiclePickedUp->GetPosition().z + m_pVehiclePickedUp->GetColModel()->boundingBox.max.z,
- &fAngle, &fOffset, &fHeight);
- if (GoTowardsTarget(fAngle, fOffset, fHeight)) {
- CVector distance = m_pVehiclePickedUp->GetPosition() - m_vecHookCurPos;
- distance.z += m_pVehiclePickedUp->GetColModel()->boundingBox.max.z;
- if (distance.MagnitudeSqr() < SQR(DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT)) {
- m_nCraneState = GOING_TOWARDS_TARGET_ONLY_HEIGHT;
- m_vecHookVelocity *= 0.4f;
- m_pVehiclePickedUp->bLightsOn = false;
- m_pVehiclePickedUp->bUsesCollision = false;
- if (m_bIsCrusher)
- m_pVehiclePickedUp->bCollisionProof = true;
- DMAudio.PlayOneShot(m_nAudioEntity, SOUND_CRANE_PICKUP, 0.0f);
- }
- }
- }
- }
- else
- m_nCraneState = IDLE;
- break;
- case LIFTING_TARGET:
- RotateCarriedCarProperly();
- if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoff(), CRANE_SLOWDOWN_MULTIPLIER))
- m_nCraneState = ROTATING_TARGET;
- if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) {
- m_pVehiclePickedUp = nil;
- m_nCraneState = IDLE;
- }
- break;
- case GOING_TOWARDS_TARGET_ONLY_HEIGHT:
- RotateCarriedCarProperly();
- if (GoTowardsHeightTarget(GetHeightToPickupHeight(), CRANE_SLOWDOWN_MULTIPLIER))
- m_nCraneState = LIFTING_TARGET;
- TimerForCamInterpolation = CTimer::GetTimeInMilliseconds();
- if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) {
- m_pVehiclePickedUp = nil;
- m_nCraneState = IDLE;
- }
- break;
- case ROTATING_TARGET:
- {
- bool bRotateFinished = RotateCarriedCarProperly();
- bool bMovementFinished = GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, m_fDropoffHeight, 0.3f);
- if (bMovementFinished && bRotateFinished) {
- float fDistanceFromPlayer = m_pVehiclePickedUp ? ((CVector2D)FindPlayerCoors() - (CVector2D)m_pVehiclePickedUp->GetPosition()).Magnitude() : 0.0f;
- if (fDistanceFromPlayer > DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE || !m_bWasMilitaryCrane) {
- m_nCraneState = DROPPING_TARGET;
- if (m_pVehiclePickedUp) {
- m_pVehiclePickedUp->bUsesCollision = true;
- m_pVehiclePickedUp->m_nStaticFrames = 0;
- ++m_nVehiclesCollected;
- if (m_bIsMilitaryCrane) {
- CCranes::RegisterCarForMilitaryCrane(m_pVehiclePickedUp->GetModelIndex());
- if (!CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()) {
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += CAR_REWARD_MILITARY_CRANE;
- CGarages::TriggerMessage("GA_10", CAR_REWARD_MILITARY_CRANE, MESSAGE_SHOW_DURATION, -1);
- }
- CWorld::Remove(m_pVehiclePickedUp);
- delete m_pVehiclePickedUp;
- }
- }
- m_pVehiclePickedUp = nil;
- }
- }
- break;
- }
- case DROPPING_TARGET:
- if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoffHeight(), CRANE_SLOWDOWN_MULTIPLIER)) {
- m_nCraneState = IDLE;
- m_nTimeForNextCheck = CTimer::GetTimeInMilliseconds() + 10000;
- }
- break;
- default:
- break;
- }
- CVector vecHook;
- CalcHookCoordinates(&vecHook.x, &vecHook.y, &vecHook.z);
- m_vecHookVelocity += ((CVector2D)vecHook - (CVector2D)m_vecHookCurPos) * CTimer::GetTimeStep() * CRANE_MOVEMENT_SPEED;
- m_vecHookVelocity *= Pow(0.98f, CTimer::GetTimeStep());
- m_vecHookCurPos.x += m_vecHookVelocity.x * CTimer::GetTimeStep();
- m_vecHookCurPos.y += m_vecHookVelocity.y * CTimer::GetTimeStep();
- m_vecHookCurPos.z = vecHook.z;
- switch (m_nCraneState) {
- case LIFTING_TARGET:
- case GOING_TOWARDS_TARGET_ONLY_HEIGHT:
- case ROTATING_TARGET:
- if (m_pVehiclePickedUp) {
- m_pVehiclePickedUp->GetPosition() = CVector(m_vecHookCurPos.x, m_vecHookCurPos.y, m_vecHookCurPos.z - m_pVehiclePickedUp->GetColModel()->boundingBox.max.z);
- m_pVehiclePickedUp->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- CVector up(vecHook.x - m_vecHookCurPos.x, vecHook.y - m_vecHookCurPos.y, 20.0f);
- up.Normalise();
- m_pVehiclePickedUp->GetRight() = CrossProduct(m_pVehiclePickedUp->GetForward(), up);
- m_pVehiclePickedUp->GetForward() = CrossProduct(up, m_pVehiclePickedUp->GetRight());
- m_pVehiclePickedUp->GetUp() = up;
- }
- break;
- default:
- break;
- }
- }
- else {
- int16 rnd = (m_pCraneEntity->m_randomSeed + (CTimer::GetTimeInMilliseconds() >> 11)) & 0xF;
- // 16 options, lasting 2048 ms each
- // a bit awkward: why there are 4 periods for -= and 6 for +=? is it a bug?
- if (rnd < 4) {
- m_fHookAngle -= OSCILLATION_SPEED * CTimer::GetTimeStep();
- if (m_fHookAngle < 0.0f)
- m_fHookAngle += TWOPI;
- }
- else if (rnd > 5 && rnd < 12) {
- m_fHookAngle += OSCILLATION_SPEED * CTimer::GetTimeStep();
- if (m_fHookAngle > TWOPI)
- m_fHookAngle -= TWOPI;
- }
- CalcHookCoordinates(&m_vecHookCurPos.x, &m_vecHookCurPos.y, &m_vecHookCurPos.z);
- m_vecHookVelocity.x = m_vecHookVelocity.y = 0.0f;
- }
- float fCos = Cos(m_fHookAngle);
- float fSin = Sin(m_fHookAngle);
- m_pCraneEntity->GetRight().x = fCos;
- m_pCraneEntity->GetForward().y = fCos;
- m_pCraneEntity->GetRight().y = fSin;
- m_pCraneEntity->GetForward().x = -fSin;
- m_pCraneEntity->GetMatrix().UpdateRW();
- m_pCraneEntity->UpdateRwFrame();
- SetHookMatrix();
-}
-
-bool CCrane::RotateCarriedCarProperly()
-{
- if (m_fDropoffHeading <= 0.0f)
- return true;
- if (!m_pVehiclePickedUp)
- return true;
- float fAngleDelta = m_fDropoffHeading - CGeneral::GetATanOfXY(m_pVehiclePickedUp->GetForward().x, m_pVehiclePickedUp->GetForward().y);
- while (fAngleDelta < -HALFPI)
- fAngleDelta += PI;
- while (fAngleDelta > HALFPI)
- fAngleDelta -= PI;
- float fDeltaThisFrame = CAR_ROTATION_SPEED * CTimer::GetTimeStep();
- if (Abs(fAngleDelta) <= fDeltaThisFrame) // no rotation is actually applied?
- return true;
- m_pVehiclePickedUp->GetMatrix().RotateZ(Abs(fDeltaThisFrame));
- return false;
-}
-
-void CCrane::FindCarInSectorList(CPtrList* pList)
-{
- CPtrNode* node;
- for (node = pList->first; node; node = node->next) {
- CVehicle* pVehicle = (CVehicle*)node->item;
- if (pVehicle->m_scanCode == CWorld::GetCurrentScanCode())
- continue;
- pVehicle->m_scanCode = CWorld::GetCurrentScanCode();
- if (pVehicle->GetPosition().x < m_fPickupX1 || pVehicle->GetPosition().x > m_fPickupX2 ||
- pVehicle->GetPosition().y < m_fPickupY1 || pVehicle->GetPosition().y > m_fPickupY2)
- continue;
- if (pVehicle->pDriver)
- continue;
- if (Abs(pVehicle->GetMoveSpeed().x) >= CAR_MOVING_SPEED_THRESHOLD ||
- Abs(pVehicle->GetMoveSpeed().y) >= CAR_MOVING_SPEED_THRESHOLD ||
- Abs(pVehicle->GetMoveSpeed().z) >= CAR_MOVING_SPEED_THRESHOLD)
- continue;
- if (!pVehicle->IsCar() || pVehicle->m_status == STATUS_WRECKED || pVehicle->m_fHealth < 250.0f)
- continue;
- if (!DoesCranePickUpThisCarType(pVehicle->GetModelIndex()) ||
- m_bIsMilitaryCrane && CCranes::DoesMilitaryCraneHaveThisOneAlready(pVehicle->GetModelIndex())) {
- if (!pVehicle->bCraneMessageDone) {
- pVehicle->bCraneMessageDone = true;
- if (!m_bIsMilitaryCrane)
- CGarages::TriggerMessage("CR_1", -1, MESSAGE_SHOW_DURATION, -1); // Crane cannot lift this vehicle.
- else if (DoesCranePickUpThisCarType(pVehicle->GetModelIndex()))
- CGarages::TriggerMessage("GA_20", -1, MESSAGE_SHOW_DURATION, -1); // We got more of these than we can shift. Sorry man, no deal.
- else
- CGarages::TriggerMessage("GA_19", -1, MESSAGE_SHOW_DURATION, -1); // We're not interested in that model.
- }
- }
- else {
- m_pVehiclePickedUp = pVehicle;
- pVehicle->RegisterReference((CEntity**)&m_pVehiclePickedUp);
- m_nCraneState = GOING_TOWARDS_TARGET;
- }
- }
-}
-
-bool CCrane::DoesCranePickUpThisCarType(uint32 mi)
-{
- if (m_bIsCrusher) {
- return mi != MI_FIRETRUCK &&
- mi != MI_TRASH &&
-#ifndef FIX_BUGS // why
- mi != MI_BLISTA &&
-#endif
- mi != MI_SECURICA &&
- mi != MI_BUS &&
- mi != MI_DODO &&
- mi != MI_RHINO;
- }
- if (m_bIsMilitaryCrane) {
- return mi == MI_FIRETRUCK ||
- mi == MI_AMBULAN ||
- mi == MI_ENFORCER ||
- mi == MI_FBICAR ||
- mi == MI_RHINO ||
- mi == MI_BARRACKS ||
- mi == MI_POLICE;
- }
- return true;
-}
-
-bool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi)
-{
- switch (mi) {
- case MI_FIRETRUCK: return (CCranes::CarsCollectedMilitaryCrane & 1);
- case MI_AMBULAN: return (CCranes::CarsCollectedMilitaryCrane & 2);
- case MI_ENFORCER: return (CCranes::CarsCollectedMilitaryCrane & 4);
- case MI_FBICAR: return (CCranes::CarsCollectedMilitaryCrane & 8);
- case MI_RHINO: return (CCranes::CarsCollectedMilitaryCrane & 0x10);
- case MI_BARRACKS: return (CCranes::CarsCollectedMilitaryCrane & 0x20);
- case MI_POLICE: return (CCranes::CarsCollectedMilitaryCrane & 0x40);
- default: break;
- }
- return false;
-}
-
-void CCranes::RegisterCarForMilitaryCrane(uint32 mi)
-{
- switch (mi) {
- case MI_FIRETRUCK: CCranes::CarsCollectedMilitaryCrane |= 1; break;
- case MI_AMBULAN: CCranes::CarsCollectedMilitaryCrane |= 2; break;
- case MI_ENFORCER: CCranes::CarsCollectedMilitaryCrane |= 4; break;
- case MI_FBICAR: CCranes::CarsCollectedMilitaryCrane |= 8; break;
- case MI_RHINO: CCranes::CarsCollectedMilitaryCrane |= 0x10; break;
- case MI_BARRACKS: CCranes::CarsCollectedMilitaryCrane |= 0x20; break;
- case MI_POLICE: CCranes::CarsCollectedMilitaryCrane |= 0x40; break;
- default: break;
- }
-}
-
-bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()
-{
- return (CCranes::CarsCollectedMilitaryCrane & 0x7F) == 0x7F;
-}
-
-bool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier)
-{
- bool bAngleMovementFinished, bOffsetMovementFinished, bHeightMovementFinished;
- float fHookAngleDelta = fAngleToTarget - m_fHookAngle;
- while (fHookAngleDelta > PI)
- fHookAngleDelta -= TWOPI;
- while (fHookAngleDelta < -PI)
- fHookAngleDelta += TWOPI;
- float fHookAngleChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_ANGLE_MOVEMENT_SPEED;
- if (Abs(fHookAngleDelta) < fHookAngleChangeThisFrame) {
- m_fHookAngle = fAngleToTarget;
- bAngleMovementFinished = true;
- }
- else {
- if (fHookAngleDelta < 0.0f) {
- m_fHookAngle -= fHookAngleChangeThisFrame;
- if (m_fHookAngle < 0.0f)
- m_fHookAngle += TWOPI;
- }
- else {
- m_fHookAngle += fHookAngleChangeThisFrame;
- if (m_fHookAngle > TWOPI)
- m_fHookAngle -= TWOPI;
- }
- bAngleMovementFinished = false;
- }
- float fHookOffsetDelta = fDistanceToTarget - m_fHookOffset;
- float fHookOffsetChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_OFFSET_MOVEMENT_SPEED;
- if (Abs(fHookOffsetDelta) < fHookOffsetChangeThisFrame) {
- m_fHookOffset = fDistanceToTarget;
- bOffsetMovementFinished = true;
- }
- else {
- if (fHookOffsetDelta < 0.0f)
- m_fHookOffset -= fHookOffsetChangeThisFrame;
- else
- m_fHookOffset += fHookOffsetChangeThisFrame;
- bOffsetMovementFinished = false;
- }
- float fHookHeightDelta = fTargetHeight - m_fHookHeight;
- float fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED;
- if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) {
- m_fHookHeight = fTargetHeight;
- bHeightMovementFinished = true;
- }
- else {
- if (fHookHeightDelta < 0.0f)
- m_fHookHeight -= fHookHeightChangeThisFrame;
- else
- m_fHookHeight += fHookHeightChangeThisFrame;
- bHeightMovementFinished = false;
- }
- return bAngleMovementFinished && bOffsetMovementFinished && bHeightMovementFinished;
-}
-
-bool CCrane::GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier)
-{
- bool bHeightMovementFinished;
- float fHookHeightDelta = fTargetHeight - m_fHookHeight;
- float fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED;
- if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) {
- m_fHookHeight = fTargetHeight;
- bHeightMovementFinished = true;
- }
- else {
- if (fHookHeightDelta < 0.0f)
- m_fHookHeight -= fHookHeightChangeThisFrame;
- else
- m_fHookHeight += fHookHeightChangeThisFrame;
- bHeightMovementFinished = false;
- }
- return bHeightMovementFinished;
-}
-
-void CCrane::FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight)
-{
- *pAngle = CGeneral::GetATanOfXY(X - m_pCraneEntity->GetPosition().x, Y - m_pCraneEntity->GetPosition().y);
- *pDistance = ((CVector2D(X, Y) - (CVector2D)m_pCraneEntity->GetPosition())).Magnitude();
- *pHeight = Z;
-}
-
-void CCrane::CalcHookCoordinates(float* pX, float* pY, float* pZ)
-{
- *pX = Cos(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().x;
- *pY = Sin(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().y;
- *pZ = m_fHookHeight;
-}
-
-void CCrane::SetHookMatrix()
-{
- if (!m_pHook)
- return;
- m_pHook->GetPosition() = m_vecHookCurPos;
- CVector up(m_vecHookInitPos.x - m_vecHookCurPos.x, m_vecHookInitPos.y - m_vecHookCurPos.y, 20.0f);
- up.Normalise();
- m_pHook->GetRight() = CrossProduct(CVector(0.0f, 1.0f, 0.0f), up);
- m_pHook->GetForward() = CrossProduct(up, m_pHook->GetRight());
- m_pHook->GetUp() = up;
- m_pHook->SetOrientation(0.0f, 0.0f, -HALFPI);
- m_pHook->GetMatrix().UpdateRW();
- m_pHook->UpdateRwFrame();
- CWorld::Remove(m_pHook);
- CWorld::Add(m_pHook);
-}
-
-bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle)
-{
- for (int i = 0; i < NumCranes; i++) {
- if (pVehicle == aCranes[i].m_pVehiclePickedUp) {
- switch (aCranes[i].m_nCraneState) {
- case CCrane::GOING_TOWARDS_TARGET_ONLY_HEIGHT:
- case CCrane::LIFTING_TARGET:
- case CCrane::ROTATING_TARGET:
- return true;
- default:
- break;
- }
- }
- }
- return false;
-}
-
-bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle)
-{
- for (int i = 0; i < NumCranes; i++) {
- if (pVehicle == aCranes[i].m_pVehiclePickedUp)
- return true;
- }
- return false;
-}
-
-void CCranes::Save(uint8* buf, uint32* size)
-{
- INITSAVEBUF
-
- *size = 2 * sizeof(uint32) + NUM_CRANES * sizeof(CCrane);
- WriteSaveBuf(buf, NumCranes);
- WriteSaveBuf(buf, CarsCollectedMilitaryCrane);
- for (int i = 0; i < NUM_CRANES; i++) {
- CCrane* pCrane = WriteSaveBuf(buf, aCranes[i]);
- if (pCrane->m_pCraneEntity)
- pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pCrane->m_pCraneEntity) + 1);
- if (pCrane->m_pHook)
- pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex((CObject*)pCrane->m_pHook) + 1);
- if (pCrane->m_pVehiclePickedUp)
- pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex((CVehicle*)pCrane->m_pVehiclePickedUp) + 1);
- }
-
- VALIDATESAVEBUF(*size);
-}
-
-void CranesLoad(uint8* buf, uint32 size)
-{
- INITSAVEBUF
-
- CCranes::NumCranes = ReadSaveBuf<int32>(buf);
- CCranes::CarsCollectedMilitaryCrane = ReadSaveBuf<uint32>(buf);
- for (int i = 0; i < NUM_CRANES; i++)
- CCranes::aCranes[i] = ReadSaveBuf<CCrane>(buf);
- for (int i = 0; i < NUM_CRANES; i++) {
- CCrane* pCrane = &CCranes::aCranes[i];
- if (pCrane->m_pCraneEntity)
- pCrane->m_pCraneEntity = CPools::GetBuildingPool()->GetSlot((uint32)pCrane->m_pCraneEntity - 1);
- if (pCrane->m_pHook)
- pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uint32)pCrane->m_pHook - 1);
- if (pCrane->m_pVehiclePickedUp)
- pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uint32)pCrane->m_pVehiclePickedUp + 1);
- }
- for (int i = 0; i < NUM_CRANES; i++) {
- CCranes::aCranes[i].m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &CCranes::aCranes[i]);
- if (CCranes::aCranes[i].m_nAudioEntity)
- DMAudio.SetEntityStatus(CCranes::aCranes[i].m_nAudioEntity, 1);
- }
-
- VALIDATESAVEBUF(size);
-}
-
-STARTPATCHES
- InjectHook(0x5454D0, CranesLoad, PATCH_JUMP); // GenericLoad
-ENDPATCHES
diff --git a/src/control/Cranes.h b/src/control/Cranes.h
deleted file mode 100644
index d9817282..00000000
--- a/src/control/Cranes.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#pragma once
-#include "common.h"
-
-#include "World.h"
-
-class CVehicle;
-class CEntity;
-class CObject;
-class CBuilding;
-
-class CCrane
-{
-public:
- enum CraneState : uint8 {
- IDLE = 0,
- GOING_TOWARDS_TARGET = 1,
- LIFTING_TARGET = 2,
- GOING_TOWARDS_TARGET_ONLY_HEIGHT = 3,
- ROTATING_TARGET = 4,
- DROPPING_TARGET = 5
- };
- enum CraneStatus : uint8 {
- NONE = 0,
- ACTIVATED = 1,
- DEACTIVATED = 2
- };
- CBuilding *m_pCraneEntity;
- CObject *m_pHook;
- int32 m_nAudioEntity;
- float m_fPickupX1;
- float m_fPickupX2;
- float m_fPickupY1;
- float m_fPickupY2;
- CVector m_vecDropoffTarget;
- float m_fDropoffHeading;
- float m_fPickupAngle;
- float m_fDropoffAngle;
- float m_fPickupDistance;
- float m_fDropoffDistance;
- float m_fPickupHeight;
- float m_fDropoffHeight;
- float m_fHookAngle;
- float m_fHookOffset;
- float m_fHookHeight;
- CVector m_vecHookInitPos;
- CVector m_vecHookCurPos;
- CVector2D m_vecHookVelocity;
- CVehicle *m_pVehiclePickedUp;
- uint32 m_nTimeForNextCheck;
- CraneStatus m_nCraneStatus;
- CraneState m_nCraneState;
- uint8 m_nVehiclesCollected;
- bool m_bIsCrusher;
- bool m_bIsMilitaryCrane;
- bool m_bWasMilitaryCrane;
- bool m_bIsTop;
-
- void Init(void) { memset(this, 0, sizeof(*this)); }
- void Update(void);
- bool RotateCarriedCarProperly(void);
- void FindCarInSectorList(CPtrList* pList);
- bool DoesCranePickUpThisCarType(uint32 mi);
- bool GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier = 1.0f);
- bool GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier = 1.0f);
- void FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight);
- void CalcHookCoordinates(float* pX, float* pY, float* pZ);
- void SetHookMatrix(void);
-
- float GetHeightToPickup() { return 4.0f + m_fPickupHeight + (m_bIsCrusher ? 4.5f : 0.0f); };
- float GetHeightToDropoff() { return m_bIsCrusher ? (2.0f + m_fDropoffHeight + 3.0f) : (2.0f + m_fDropoffHeight); }
- float GetHeightToPickupHeight() { return m_fPickupHeight + (m_bIsCrusher ? 7.0f : 4.0f); }
- float GetHeightToDropoffHeight() { return m_fDropoffHeight + (m_bIsCrusher ? 7.0f : 2.0f); }
-};
-
-static_assert(sizeof(CCrane) == 128, "CCrane: error");
-
-class CCranes
-{
-public:
- static void InitCranes(void);
- static void AddThisOneCrane(CEntity* pCraneEntity);
- static void ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY);
- static void DeActivateCrane(float fX, float fY);
- static bool IsThisCarPickedUp(float fX, float fY, CVehicle* pVehicle);
- static void UpdateCranes(void);
- static bool DoesMilitaryCraneHaveThisOneAlready(uint32 mi);
- static void RegisterCarForMilitaryCrane(uint32 mi);
- static bool HaveAllCarsBeenCollectedByMilitaryCrane(void);
- static bool IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle);
- static bool IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle);
- static void Save(uint8* buf, uint32* size);
-
- static uint32& CarsCollectedMilitaryCrane;
- static int32& NumCranes;
- static CCrane(&aCranes)[NUM_CRANES];
-};
-
-void CranesLoad(uint8*, uint32); // is this really outside CCranes?
diff --git a/src/control/Gangs.cpp b/src/control/Gangs.cpp
deleted file mode 100644
index 57d9c67e..00000000
--- a/src/control/Gangs.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "common.h"
-#include "patcher.h"
-#include "ModelIndices.h"
-#include "Gangs.h"
-#include "Weapon.h"
-
-//CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
-CGangInfo CGangs::Gang[NUM_GANGS];
-
-CGangInfo::CGangInfo() :
- m_nVehicleMI(MI_BUS),
- m_nPedModelOverride(-1),
- m_Weapon1(WEAPONTYPE_UNARMED),
- m_Weapon2(WEAPONTYPE_UNARMED)
-{}
-
-void CGangs::Initialise(void)
-{
- Gang[GANG_MAFIA].m_nVehicleMI = MI_MAFIA;
- Gang[GANG_TRIAD].m_nVehicleMI = MI_BELLYUP;
- Gang[GANG_DIABLOS].m_nVehicleMI = MI_DIABLOS;
- Gang[GANG_YAKUZA].m_nVehicleMI = MI_YAKUZA;
- Gang[GANG_YARDIE].m_nVehicleMI = MI_YARDIE;
- Gang[GANG_COLUMB].m_nVehicleMI = MI_COLUMB;
- Gang[GANG_HOODS].m_nVehicleMI = MI_HOODS;
- Gang[GANG_7].m_nVehicleMI = -1;
- Gang[GANG_8].m_nVehicleMI = -1;
-#ifdef FIX_BUGS
- for (int i = 0; i < NUM_GANGS; i++)
- Gang[i].m_nPedModelOverride = -1;
-#endif
-}
-
-void CGangs::SetGangVehicleModel(int16 gang, int32 model)
-{
- GetGangInfo(gang)->m_nVehicleMI = model;
-}
-
-void CGangs::SetGangWeapons(int16 gang, int32 weapon1, int32 weapon2)
-{
- CGangInfo *gi = GetGangInfo(gang);
- gi->m_Weapon1 = weapon1;
- gi->m_Weapon2 = weapon2;
-}
-
-void CGangs::SetGangPedModelOverride(int16 gang, int8 ovrd)
-{
- GetGangInfo(gang)->m_nPedModelOverride = ovrd;
-}
-
-int8 CGangs::GetGangPedModelOverride(int16 gang)
-{
- return GetGangInfo(gang)->m_nPedModelOverride;
-}
-
-void CGangs::SaveAllGangData(uint8 *buf, uint32 *size)
-{
-INITSAVEBUF
-
- *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]);
-
-VALIDATESAVEBUF(*size);
-}
-
-void CGangs::LoadAllGangData(uint8 *buf, uint32 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++)
- Gang[i] = ReadSaveBuf<CGangInfo>(buf);
-VALIDATESAVEBUF(size);
-}
-
-STARTPATCHES
- InjectHook(0x4C3FB0, CGangs::Initialise, PATCH_JUMP);
- InjectHook(0x4C4010, CGangs::SetGangVehicleModel, PATCH_JUMP);
- InjectHook(0x4C4030, CGangs::SetGangWeapons, PATCH_JUMP);
- InjectHook(0x4C4050, CGangs::SetGangPedModelOverride, PATCH_JUMP);
- InjectHook(0x4C4070, CGangs::GetGangPedModelOverride, PATCH_JUMP);
- InjectHook(0x4C4080, CGangs::SaveAllGangData, PATCH_JUMP);
- InjectHook(0x4C4100, CGangs::LoadAllGangData, PATCH_JUMP);
-ENDPATCHES
diff --git a/src/control/Gangs.h b/src/control/Gangs.h
deleted file mode 100644
index dd7a7f93..00000000
--- a/src/control/Gangs.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#pragma once
-
-struct CGangInfo
-{
- int32 m_nVehicleMI;
- int8 m_nPedModelOverride;
- int32 m_Weapon1;
- int32 m_Weapon2;
-
- CGangInfo();
-};
-
-static_assert(sizeof(CGangInfo) == 0x10, "CGangInfo: error");
-
-enum {
- GANG_MAFIA = 0,
- GANG_TRIAD,
- GANG_DIABLOS,
- GANG_YAKUZA,
- GANG_YARDIE,
- GANG_COLUMB,
- GANG_HOODS,
- GANG_7,
- GANG_8,
- NUM_GANGS
-};
-
-class CGangs
-{
-public:
- static void Initialise(void);
- static void SetGangVehicleModel(int16, int32);
- static void SetGangWeapons(int16, int32, int32);
- static void SetGangPedModelOverride(int16, int8);
- static int8 GetGangPedModelOverride(int16);
- static void SaveAllGangData(uint8 *, uint32 *);
- static void LoadAllGangData(uint8 *, uint32);
-
- static int32 GetGangVehicleModel(int16 gang) { return Gang[gang].m_nVehicleMI; }
- static CGangInfo *GetGangInfo(int16 gang) { return &Gang[gang]; }
-
-private:
- static CGangInfo Gang[NUM_GANGS];
-};
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index 84d49bee..d971d453 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -2108,7 +2108,7 @@ void CGarages::CloseHideOutGaragesBeforeSave()
aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE)
continue;
if (aGarages[i].m_eGarageState != GS_FULLYCLOSED &&
- aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor()) {
+ (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor())) {
aGarages[i].m_eGarageState = GS_FULLYCLOSED;
switch (aGarages[i].m_eGarageType) {
case GARAGE_HIDEOUT_ONE:
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 80e89ee8..eb561670 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -1016,6 +1016,7 @@ CPacManPickup::Update()
FindPlayerPed()->m_pWanted->m_nChaos += 10;
FindPlayerPed()->m_pWanted->UpdateWantedLevel();
DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PACKAGE, 0);
+ break;
}
case PACMAN_RACE:
CPacManPickups::PillsEatenInRace++;
diff --git a/src/control/Record.cpp b/src/control/Record.cpp
index aead1720..ca4128e3 100644
--- a/src/control/Record.cpp
+++ b/src/control/Record.cpp
@@ -21,8 +21,7 @@ tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0;
void CRecordDataForGame::Init(void)
{
RecordingState = STATE_NONE;
- if (pDataBuffer)
- delete[] pDataBuffer;
+ delete[] pDataBuffer;
pDataBufferPointer = nil;
pDataBuffer = nil;
#ifndef GTA_PS2 // this stuff is not present on PS2
@@ -42,7 +41,7 @@ void CRecordDataForGame::Init(void)
if (RecordingState == STATE_PLAYBACK) {
pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD];
pDataBuffer = pDataBufferPointer;
- pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = -1;
+ pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1;
CFileMgr::CloseFile(FId);
}
#else
@@ -71,7 +70,7 @@ void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
break;
}
case STATE_PLAYBACK:
- if (pDataBufferPointer[8] == -1)
+ if (pDataBufferPointer[8] == (uint8)-1)
CPad::GetPad(0)->NewState.Clear();
else {
tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer;
@@ -92,7 +91,7 @@ void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \
do { \
- if (os->field != os->field){ \
+ if (os->field != ns->field){ \
*buf++ = id; \
*buf++ = ns->field; \
} \
@@ -102,7 +101,7 @@ uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os
{
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickX, 0);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickY, 1);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 2);
+ PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickX, 2);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickY, 3);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 4);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder2, 5);
@@ -132,7 +131,7 @@ uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CCont
switch (*buf++) {
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 2);
+ PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickX, 2);
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickY, 3);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 4);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder2, 5);
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index e39fe481..9548bc0a 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -2,36 +2,202 @@
#include "patcher.h"
#include "RoadBlocks.h"
#include "PathFind.h"
+#include "ModelIndices.h"
+#include "Streaming.h"
+#include "World.h"
+#include "PedPlacement.h"
+#include "Automobile.h"
+#include "CopPed.h"
+#include "VisibilityPlugins.h"
+#include "PlayerPed.h"
+#include "Wanted.h"
+#include "Camera.h"
+#include "CarCtrl.h"
+#include "General.h"
int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34;
int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8;
bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810;
-WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); }
-WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); }
-
void
CRoadBlocks::Init(void)
{
- NumRoadBlocks = 0;
- for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) {
- if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) {
- if (NumRoadBlocks < 600) {
- InOrOut[NumRoadBlocks] = true;
- RoadBlockObjects[NumRoadBlocks] = objId;
- NumRoadBlocks++;
- } else {
+ NumRoadBlocks = 0;
+ for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) {
+ if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) {
+ if (NumRoadBlocks < NUMROADBLOCKS) {
+ InOrOut[NumRoadBlocks] = true;
+ RoadBlockObjects[NumRoadBlocks] = objId;
+ NumRoadBlocks++;
+ } else {
#ifndef MASTER
- printf("Not enough room for the potential roadblocks\n");
+ printf("Not enough room for the potential roadblocks\n");
#endif
- // FIX: Don't iterate loop after NUMROADBLOCKS
- return;
- }
- }
- }
+ // FIX: Don't iterate loop after NUMROADBLOCKS
+ return;
+ }
+ }
+ }
+
+}
+
+void
+CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode)
+{
+ static const CVector vecRoadBlockOffets[6] = { {-1.5, 1.8f, 0.0f}, {-1.5f, -1.8f, 0.0f}, {1.5f, 1.8f, 0.0f},
+ {1.5f, -1.8f, 0.0f}, {-1.5f, 0.0f, 0.0f}, {1.5, 0.0, 0.0} };
+ CEntity* pEntityToAttack = (CEntity*)FindPlayerVehicle();
+ if (!pEntityToAttack)
+ pEntityToAttack = (CEntity*)FindPlayerPed();
+ CColModel* pPoliceColModel = CModelInfo::GetModelInfo(MI_POLICE)->GetColModel();
+ float fRadius = pVehicle->GetBoundRadius() / pPoliceColModel->boundingSphere.radius;
+ for (int32 i = 0; i < 2; i++) {
+ const int32 roadBlockIndex = i + 2 * roadBlockType;
+ CVector posForZ = pVehicle->m_matrix * (fRadius * vecRoadBlockOffets[roadBlockIndex]);
+ int32 modelInfoId = MI_COP;
+ eCopType copType = COP_STREET;
+ switch (pVehicle->GetModelIndex())
+ {
+ case MI_FBICAR:
+ modelInfoId = MI_FBI;
+ copType = COP_FBI;
+ break;
+ case MI_ENFORCER:
+ modelInfoId = MI_SWAT;
+ copType = COP_SWAT;
+ break;
+ case MI_BARRACKS:
+ modelInfoId = MI_ARMY;
+ copType = COP_ARMY;
+ break;
+ }
+ if (!CStreaming::HasModelLoaded(modelInfoId))
+ copType = COP_STREET;
+ CCopPed* pCopPed = new CCopPed(copType);
+ if (copType == COP_STREET)
+ pCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45);
+ CPedPlacement::FindZCoorForPed(&posForZ);
+ pCopPed->m_matrix.GetPosition() = posForZ;
+ CVector vecSavedPos = pCopPed->m_matrix.GetPosition();
+ pCopPed->m_matrix.SetRotate(0.0f, 0.0f, -HALFPI);
+ pCopPed->m_matrix.GetPosition() += vecSavedPos;
+ pCopPed->m_bIsDisabledCop = true;
+ pCopPed->SetIdle();
+ pCopPed->bKindaStayInSamePlace = true;
+ pCopPed->bNotAllowedToDuck = false;
+ pCopPed->m_wRoadblockNode = roadBlockNode;
+ pCopPed->bCrouchWhenShooting = roadBlockType != 2;
+ if (pEntityToAttack) {
+ pCopPed->m_pPointGunAt = pEntityToAttack;
+ pEntityToAttack->RegisterReference(&pCopPed->m_pPointGunAt);
+ pCopPed->SetAttack(pEntityToAttack);
+ }
+ pCopPed->m_pMyVehicle = pVehicle;
+ pVehicle->RegisterReference((CEntity**)&pCopPed->m_pMyVehicle);
+ pCopPed->bCullExtraFarAway = true;
+ CVisibilityPlugins::SetClumpAlpha(pCopPed->GetClump(), 0);
+ CWorld::Add(pCopPed);
+ }
+}
+void
+CRoadBlocks::GenerateRoadBlocks(void)
+{
+ CMatrix offsetMatrix;
+ uint32 frame = CTimer::GetFrameCounter() & 0xF;
+ int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
+ const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
+ int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks;
+ if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks)
+ numRoadBlocks = maxRoadBlocks;
+ for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) {
+ CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]];
+ CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
+ if (vecDistance.x > -80.0f && vecDistance.x < 80.0f &&
+ vecDistance.y > -80.0f && vecDistance.y < 80.0f &&
+ vecDistance.Magnitude() < 80.0f) {
+ if (!CRoadBlocks::InOrOut[nRoadblockNode]) {
+ CRoadBlocks::InOrOut[nRoadblockNode] = true;
+ if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
+ CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted;
+ float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x;
+ int32 vehicleId = MI_POLICE;
+ if (pPlayerWanted->AreArmyRequired())
+ vehicleId = MI_BARRACKS;
+ else if (pPlayerWanted->AreFbiRequired())
+ vehicleId = MI_FBICAR;
+ else if (pPlayerWanted->AreSwatRequired())
+ vehicleId = MI_ENFORCER;
+ if (!CStreaming::HasModelLoaded(vehicleId))
+ vehicleId = MI_POLICE;
+ CColModel *pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel();
+ float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f;
+ int16 radius = (int16)(fMapObjectRadius / fModelRadius);
+ if (radius > 0 && radius < 6) {
+ CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->m_matrix.GetPosition();
+ float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->m_matrix.GetUp());
+ float fOffset = 0.5f * fModelRadius * (float)(radius - 1);
+ for (int16 i = 0; i < radius; i++) {
+ uint8 nRoadblockType = fDotProduct < 0.0f;
+ if (CGeneral::GetRandomNumber() & 1) {
+ offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI);
+ }
+ else {
+ nRoadblockType = !nRoadblockType;
+ offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI);
+ }
+ if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest)
+ offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f);
+ else
+ offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f);
+ CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix;
+ float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f;
+ int16 colliding = 0;
+ CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false);
+ if (!colliding) {
+ CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE);
+ pVehicle->m_status = STATUS_ABANDONED;
+ // pVehicle->GetHeightAboveRoad(); // called but return value is ignored?
+ vehicleMatrix.GetPosition().z += fModelRadius - 0.6f;
+ pVehicle->m_matrix = vehicleMatrix;
+ pVehicle->PlaceOnRoadProperly();
+ pVehicle->bIsStatic = false;
+ pVehicle->m_matrix.UpdateRW();
+ pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
+ CCarCtrl::JoinCarWithRoadSystem(pVehicle);
+ pVehicle->bIsLocked = false;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nCurrentLane = 0;
+ pVehicle->AutoPilot.m_nNextLane = 0;
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f;
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f;
+ pVehicle->bExtendedRange = true;
+ if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1)
+ pVehicle->m_bSirenOrAlarm = true;
+ if (pVehicle->m_matrix.GetForward().z > 0.94f) {
+ CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
+ CWorld::Add(pVehicle);
+ pVehicle->bCreateRoadBlockPeds = true;
+ pVehicle->m_nRoadblockType = nRoadblockType;
+ pVehicle->m_nRoadblockNode = nRoadblockNode;
+ }
+ else {
+ delete pVehicle;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ CRoadBlocks::InOrOut[nRoadblockNode] = false;
+ }
+ }
}
STARTPATCHES
InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP);
+ InjectHook(0x4376A0, &CRoadBlocks::GenerateRoadBlockCopsForCar, PATCH_JUMP);
+ InjectHook(0x436FA0, &CRoadBlocks::GenerateRoadBlocks, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h
index 3f5868e7..16e3a362 100644
--- a/src/control/RoadBlocks.h
+++ b/src/control/RoadBlocks.h
@@ -11,6 +11,6 @@ public:
static bool (&InOrOut)[NUMROADBLOCKS];
static void Init(void);
- static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16);
+ static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode);
static void GenerateRoadBlocks(void);
};