summaryrefslogtreecommitdiffstats
path: root/src/control
diff options
context:
space:
mode:
Diffstat (limited to 'src/control')
-rw-r--r--src/control/AutoPilot.cpp4
-rw-r--r--src/control/AutoPilot.h14
-rw-r--r--src/control/Bridge.cpp14
-rw-r--r--src/control/CarAI.cpp264
-rw-r--r--src/control/CarAI.h5
-rw-r--r--src/control/CarCtrl.cpp1064
-rw-r--r--src/control/CarCtrl.h47
-rw-r--r--src/control/Curves.cpp18
-rw-r--r--src/control/Garages.cpp880
-rw-r--r--src/control/Garages.h90
-rw-r--r--src/control/PathFind.cpp917
-rw-r--r--src/control/PathFind.h162
-rw-r--r--src/control/Pickups.cpp2
-rw-r--r--src/control/Pickups.h6
-rw-r--r--src/control/Record.cpp426
-rw-r--r--src/control/Replay.cpp5
-rw-r--r--src/control/Replay.h2
-rw-r--r--src/control/Restart.cpp8
-rw-r--r--src/control/RoadBlocks.cpp21
-rw-r--r--src/control/RoadBlocks.h4
-rw-r--r--src/control/SceneEdit.cpp2
-rw-r--r--src/control/Script.cpp830
-rw-r--r--src/control/Script.h10
-rw-r--r--src/control/ScriptCommands.h301
-rw-r--r--src/control/TrafficLights.cpp4
25 files changed, 3054 insertions, 2046 deletions
diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp
index b1fce95f..da661b8c 100644
--- a/src/control/AutoPilot.cpp
+++ b/src/control/AutoPilot.cpp
@@ -6,6 +6,7 @@
#include "Curves.h"
#include "PathFind.h"
+//--MIAMI: done
void CAutoPilot::ModifySpeed(float speed)
{
m_fMaxTrafficSpeed = Max(0.01f, speed);
@@ -39,6 +40,7 @@ void CAutoPilot::ModifySpeed(float speed)
#endif
}
+//--MIAMI: done
void CAutoPilot::RemoveOnePathNode()
{
--m_nPathFindNodesCount;
@@ -47,6 +49,7 @@ void CAutoPilot::RemoveOnePathNode()
}
#ifdef COMPATIBLE_SAVES
+//--MIAMI: TODO
void CAutoPilot::Save(uint8*& buf)
{
WriteSaveBuf<int32>(buf, m_nCurrentRouteNode);
@@ -86,6 +89,7 @@ void CAutoPilot::Save(uint8*& buf)
SkipSaveBuf(buf, 6);
}
+//--MIAMI: TODO
void CAutoPilot::Load(uint8*& buf)
{
m_nCurrentRouteNode = ReadSaveBuf<int32>(buf);
diff --git a/src/control/AutoPilot.h b/src/control/AutoPilot.h
index 337a93c1..25feb72d 100644
--- a/src/control/AutoPilot.h
+++ b/src/control/AutoPilot.h
@@ -26,6 +26,13 @@ enum eCarMission : uint8
MISSION_BLOCKCAR_FARAWAY,
MISSION_BLOCKCAR_CLOSE,
MISSION_BLOCKCAR_HANDBRAKESTOP,
+ MISSION_HELI_FLYTOCOORS,
+ MISSION_ATTACKPLAYER,
+ MISSION_PLANE_FLYTOCOORS,
+ MISSION_HELI_LAND,
+ MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1,
+ MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2,
+ MISSION_BLOCKPLAYER_FORWARDANDBACK
};
enum eCarTempAction : uint8
@@ -75,11 +82,14 @@ public:
uint32 m_nTimeTempAction;
float m_fMaxTrafficSpeed;
uint8 m_nCruiseSpeed;
+ uint8 m_nCruiseSpeedMultiplierType;
+ float m_fCruiseSpeedMultiplier;
uint8 m_bSlowedDownBecauseOfCars : 1;
uint8 m_bSlowedDownBecauseOfPeds : 1;
uint8 m_bStayInCurrentLevel : 1;
uint8 m_bStayInFastLane : 1;
uint8 m_bIgnorePathfinding : 1;
+ uint8 m_nSwitchDistance;
CVector m_vecDestinationCoors;
CPathNode *m_aPathFindNodesInfo[NUM_PATH_NODES_IN_AUTOPILOT];
int16 m_nPathFindNodesCount;
@@ -109,6 +119,8 @@ public:
m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
m_nAntiReverseTimer = m_nTimeToStartMission;
m_bStayInFastLane = false;
+ m_nCruiseSpeedMultiplierType = 0;
+ m_fCruiseSpeedMultiplier = 1.0f;
}
void ModifySpeed(float);
@@ -118,6 +130,8 @@ public:
void Load(uint8*& buf);
#endif
+ float GetCruiseSpeed(void) { return m_nCruiseSpeed * m_fCruiseSpeedMultiplier; }
+
};
VALIDATE_SIZE(CAutoPilot, 0x70);
diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp
index e873062b..1e63cf30 100644
--- a/src/control/Bridge.cpp
+++ b/src/control/Bridge.cpp
@@ -23,6 +23,7 @@ uint32 CBridge::TimeOfBridgeBecomingOperational;
void CBridge::Init()
{
+#ifdef GTA_BRIDGE
FindBridgeEntities();
OldLift = -1.0f;
if (pLiftPart && pWeight)
@@ -35,10 +36,12 @@ void CBridge::Init()
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
}
+#endif
}
void CBridge::Update()
{
+#ifdef GTA_BRIDGE
if (!pLiftPart || !pWeight)
return;
@@ -113,15 +116,21 @@ void CBridge::Update()
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
else if (State == STATE_LIFT_PART_IS_DOWN && OldState == STATE_LIFT_PART_MOVING_DOWN)
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, false);
+#endif
}
bool CBridge::ShouldLightsBeFlashing()
{
+#ifdef GTA_BRIDGE
return State != STATE_LIFT_PART_IS_DOWN;
+#else
+ return false;
+#endif
}
void CBridge::FindBridgeEntities()
{
+#ifdef GTA_BRIDGE
pWeight = nil;
pLiftRoad = nil;
pLiftPart = nil;
@@ -138,12 +147,17 @@ void CBridge::FindBridgeEntities()
pWeight = entry;
}
}
+#endif
}
bool CBridge::ThisIsABridgeObjectMovingUp(int index)
{
+#ifdef GTA_BRIDGE
if (index != MI_BRIDGEROADSEGMENT && index != MI_BRIDGELIFT)
return false;
return State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP || State == STATE_LIFT_PART_MOVING_UP;
+#else
+ return false;
+#endif
}
diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp
index b3fc85ae..0f80954b 100644
--- a/src/control/CarAI.cpp
+++ b/src/control/CarAI.cpp
@@ -13,6 +13,7 @@
#include "DMAudio.h"
#include "Fire.h"
#include "Pools.h"
+#include "Population.h"
#include "Timer.h"
#include "TrafficLights.h"
#include "Vehicle.h"
@@ -21,16 +22,19 @@
#define DISTANCE_TO_SWITCH_DISTANCE_GOTO 20.0f
+//--MIAMI: done
float CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle)
{
- return 30.0f;
+ return pVehicle->AutoPilot.m_nSwitchDistance;
}
+//--MIAMI: done
float CCarAI::FindSwitchDistanceFarNormalVehicle(CVehicle* pVehicle)
{
return FindSwitchDistanceClose(pVehicle) + 5.0f;
}
+//--MIAMI: done
float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle)
{
if (pVehicle->bIsLawEnforcer)
@@ -38,6 +42,21 @@ float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle)
return FindSwitchDistanceFarNormalVehicle(pVehicle);
}
+//--MIAMI: done
+void CCarAI::BackToCruisingIfNoWantedLevel(CVehicle* pVehicle)
+{
+ if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
+ (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
+ CCarCtrl::JoinCarWithRoadSystem(pVehicle);
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
+ pVehicle->m_bSirenOrAlarm = false;
+ if (CCullZones::NoPolice())
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ }
+}
+
+//--MIAMI: done
void CCarAI::UpdateCarAI(CVehicle* pVehicle)
{
if (pVehicle->bIsLawEnforcer){
@@ -67,15 +86,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
pVehicle->m_bSirenOrAlarm = true;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_RAMPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@@ -120,18 +131,9 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->m_bSirenOrAlarm = false;
pVehicle->m_nCarHornTimer = 0;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())){
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
-
- else if (pVehicle->bIsLawEnforcer)
+ if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_BLOCKPLAYER_FARAWAY:
if (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@@ -140,20 +142,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->UsesSiren(pVehicle->GetModelIndex()))
pVehicle->m_bSirenOrAlarm = true;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_BLOCKPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
pVehicle->AutoPilot.m_bIgnorePathfinding) {
- if (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f)
+ if (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f)
#ifdef FIX_BUGS
pVehicle->m_nTimeBlocked += CTimer::GetTimeStepInMilliseconds();
#else
@@ -162,7 +156,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
else
pVehicle->m_nTimeBlocked = 0;
if (!FindPlayerVehicle() || FindPlayerVehicle()->IsUpsideDown() ||
- FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) {
+ FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) {
if (pVehicle->bIsLawEnforcer &&
(pVehicle->GetModelIndex() != MI_RHINO || pVehicle->m_randomSeed > 10000) &&
(FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() < 10.0f) {
@@ -178,20 +172,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->m_bSirenOrAlarm = false;
pVehicle->m_nCarHornTimer = 0;
}
- if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
if (pVehicle->bIsLawEnforcer)
MellowOutChaseSpeed(pVehicle);
+ BackToCruisingIfNoWantedLevel(pVehicle);
break;
case MISSION_GOTOCOORDS:
- if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < DISTANCE_TO_SWITCH_DISTANCE_GOTO ||
+ if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||
pVehicle->AutoPilot.m_bIgnorePathfinding)
pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;
break;
@@ -203,6 +189,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (distance < 5.0f){
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ if (pVehicle->bParking) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->bParking = false;
+ }
}
else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
@@ -259,6 +249,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (distance < 1.0f) {
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ if (pVehicle->bParking) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->bParking = false;
+ }
}
else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0) {
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
@@ -278,23 +272,10 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
break;
case MISSION_RAMCAR_CLOSE:
if (pVehicle->AutoPilot.m_pTargetCar){
- if
-#ifdef FIX_BUGS
- (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar &&
-#endif
- (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&
- (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice()))
-#ifdef FIX_BUGS
- )
+#ifdef FIX_BUGS // btw fixed in SA
+ if (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar)
#endif
- {
- CCarCtrl::JoinCarWithRoadSystem(pVehicle);
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pVehicle->m_bSirenOrAlarm = false;
- if (CCullZones::NoPolice())
- pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- }
+ BackToCruisingIfNoWantedLevel(pVehicle);
if ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() <= FindSwitchDistanceFar(pVehicle) ||
pVehicle->AutoPilot.m_bIgnorePathfinding){
if (pVehicle->GetHasCollidedWith(pVehicle->AutoPilot.m_pTargetCar)){
@@ -336,6 +317,40 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
}
break;
+ case MISSION_ATTACKPLAYER:
+ if (pVehicle->bIsLawEnforcer)
+ MellowOutChaseSpeedBoat(pVehicle);
+ BackToCruisingIfNoWantedLevel(pVehicle);
+ break;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1:
+ if (((CVector2D)(pVehicle->AutoPilot.m_vecDestinationCoors) - pVehicle->GetPosition()).Magnitude() < 1.5f)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2;
+ BackToCruisingIfNoWantedLevel(pVehicle);
+ break;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2:
+ {
+ float distance = ((CVector2D)FindPlayerCoors() - pVehicle->GetPosition()).Magnitude();
+ if (distance < 13.0f) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;
+ }
+ if (distance > 70.0f || FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone ||
+ (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;
+ }
+ break;
+ }
+ case MISSION_BLOCKPLAYER_FORWARDANDBACK:
+ {
+ CVector2D diff = (CVector2D)FindPlayerCoors() - pVehicle->GetPosition();
+ float distance = Max(0.001f, diff.Magnitude());
+ if (!FindPlayerVehicle() || DotProduct2D(CVector2D(diff.x / distance, diff.y / distance), FindPlayerSpeed()) > 0.05f)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_CLOSE;
+ BackToCruisingIfNoWantedLevel(pVehicle);
+ }
default:
if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 && !CCullZones::NoPolice()){
if (ABS(FindPlayerCoors().x - pVehicle->GetPosition().x) > 10.0f ||
@@ -343,7 +358,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle);
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nCarMission =
- FindPoliceCarMissionForWantedLevel();
+ pVehicle->GetVehicleAppearance() == VEHICLE_BOAT ? FindPoliceBoatMissionForWantedLevel() : FindPoliceCarMissionForWantedLevel();
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
}else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){
@@ -364,6 +379,11 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = 0;
break;
}
+ if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel >= 1 && CCullZones::PoliceAbandonCars()) {
+ TellOccupantsToLeaveCar(pVehicle);
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ }
float flatSpeed = pVehicle->GetMoveSpeed().MagnitudeSqr2D();
if (flatSpeed > SQR(0.018f)){
pVehicle->AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
@@ -372,9 +392,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if (pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nTempAction == TEMPACT_NONE){
if (pVehicle->AutoPilot.m_nCarMission != MISSION_NONE){
if (pVehicle->AutoPilot.m_nCarMission != MISSION_STOP_FOREVER &&
+ pVehicle->AutoPilot.m_nCarMission != MISSION_BLOCKPLAYER_HANDBRAKESTOP &&
pVehicle->AutoPilot.m_nCruiseSpeed != 0 &&
(pVehicle->VehicleCreatedBy != RANDOM_VEHICLE || pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE)){
if (pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS
+ && pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS ||
+ pVehicle->VehicleCreatedBy == MISSION_VEHICLE
) {
if (CTimer::GetTimeInMilliseconds() - pVehicle->m_nLastTimeCollided > 500)
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
@@ -406,6 +429,13 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 400;
}
}
+ if (pVehicle->bIsLawEnforcer) {
+ if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY ||
+ pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) {
+ if (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BIKE)
+ pVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY;
+ }
+ }
if (pVehicle->GetUp().z < 0.7f){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
@@ -446,13 +476,43 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
if ((uint8)(pVehicle->m_randomSeed ^ CGeneral::GetRandomNumber()) == 0xAD)
pVehicle->m_nCarHornTimer = 45;
}
+ float target = 1.0f;
+ if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE)
+ target = CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(pVehicle->AutoPilot.m_nCruiseSpeedMultiplierType);
+ float change = CTimer::GetTimeStep() * 0.01f;
+ if (Abs(pVehicle->AutoPilot.m_fCruiseSpeedMultiplier - target) < change)
+ pVehicle->AutoPilot.m_fCruiseSpeedMultiplier = target;
+ else if (pVehicle->AutoPilot.m_fCruiseSpeedMultiplier > target)
+ pVehicle->AutoPilot.m_fCruiseSpeedMultiplier -= change;
+ else
+ pVehicle->AutoPilot.m_fCruiseSpeedMultiplier += change;
+
+ if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0) {
+ if (!FindPlayerVehicle() ||
+ FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_CAR ||
+ FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BIKE) {
+ if (pVehicle->GetVehicleAppearance() == VEHICLE_BOAT) {
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
+ }
+ }
+ else if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_BOAT) {
+ if (pVehicle->GetVehicleAppearance() == VEHICLE_CAR ||
+ pVehicle->GetVehicleAppearance() == VEHICLE_BIKE) {
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;
+ }
+ }
+ }
}
+//--MIAMI: done
void CCarAI::CarHasReasonToStop(CVehicle* pVehicle)
{
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
}
+//--MIAMI: done
float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget)
{
if (pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS && pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS_STRAIGHT){
@@ -470,6 +530,16 @@ float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget)
return (pVehicle->GetPosition() - *pTarget).Magnitude2D();
}
+//--MIAMI: done
+float CCarAI::GetCarToParkAtCoors(CVehicle* pVehicle, CVector* pTarget)
+{
+ GetCarToGoToCoors(pVehicle, pTarget);
+ pVehicle->bParking = true;
+ pVehicle->AutoPilot.m_nCruiseSpeed = 10;
+ return (pVehicle->GetPosition() - *pTarget).Magnitude2D();
+}
+
+//--MIAMI: TODO: MI_VICECHEE
void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
{
if (pVehicle->bOccupantsHaveBeenGenerated)
@@ -489,23 +559,38 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
if (FindPlayerPed()->m_pWanted->m_nWantedLevel > 1)
pVehicle->SetupPassenger(0);
return;
+ case MI_PREDATOR:
+ pVehicle->SetUpDriver();
+ return;
+ case MI_VICECHEE:
+ {
+ pVehicle->SetUpDriver()->bMiamiViceCop = true;
+ pVehicle->SetupPassenger(0)->bMiamiViceCop = true;
+ CPopulation::NumMiamiViceCops += 2;
+ CCarCtrl::MiamiViceCycle = (CCarCtrl::MiamiViceCycle + 1) % 4;
+ CCarCtrl::LastTimeMiamiViceGenerated = CTimer::GetTimeInMilliseconds();
+ return;
+ }
default:
return;
}
}
+//--MIAMI: done
void CCarAI::AddAmbulanceOccupants(CVehicle* pVehicle)
{
pVehicle->SetUpDriver();
pVehicle->SetupPassenger(1);
}
+//--MIAMI: done
void CCarAI::AddFiretruckOccupants(CVehicle* pVehicle)
{
pVehicle->SetUpDriver();
pVehicle->SetupPassenger(0);
}
+//--MIAMI: done
void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)
{
if (pVehicle->pDriver){
@@ -516,11 +601,32 @@ void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)
int timer = 100;
for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++){
if (pVehicle->pPassengers[i]) {
+ pVehicle->pPassengers[i]->m_leaveCarTimer = timer;
pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
+ timer += CGeneral::GetRandomNumberInRange(200, 400);
+ }
+ }
+}
+
+//--MIAMI: done
+void CCarAI::TellOccupantsToFleeCar(CVehicle* pVehicle)
+{
+ if (pVehicle->pDriver && !pVehicle->pDriver->IsPlayer()) {
+ pVehicle->pDriver->SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
+ if (pVehicle->GetModelIndex() != MI_FIRETRUCK && pVehicle->GetModelIndex() == MI_AMBULAN)
+ pVehicle->pDriver->Say(SOUND_PED_LEAVE_VEHICLE);
+ }
+ int timer = 100;
+ for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {
+ if (pVehicle->pPassengers[i]) {
+ pVehicle->pPassengers[i]->m_leaveCarTimer = timer;
+ pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_FLEE_TILL_SAFE);
+ timer += CGeneral::GetRandomNumberInRange(200, 400);
}
}
}
+//--MIAMI: done
void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
{
pVehicle->AutoPilot.m_pTargetCar = pTarget;
@@ -530,6 +636,7 @@ void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
}
+//--MIAMI: done
void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
{
pVehicle->AutoPilot.m_pTargetCar = pTarget;
@@ -539,6 +646,7 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget)
pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);
}
+//--MIAMI: done
eCarMission CCarAI::FindPoliceCarMissionForWantedLevel()
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel){
@@ -553,6 +661,22 @@ eCarMission CCarAI::FindPoliceCarMissionForWantedLevel()
}
}
+//--MIAMI: done
+eCarMission CCarAI::FindPoliceBoatMissionForWantedLevel()
+{
+ switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
+ case 0:
+ case 1: return MISSION_BLOCKPLAYER_FARAWAY;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6: return MISSION_ATTACKPLAYER;
+ default: return MISSION_BLOCKPLAYER_FARAWAY;
+ }
+}
+
+//--MIAMI: done
int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle)
{
switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
@@ -567,6 +691,7 @@ int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle)
}
}
+//--MIAMI: done
void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle)
{
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel == 1){
@@ -605,8 +730,27 @@ void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCruiseSpeed = 34;
}
}
+ if (!FindPlayerVehicle() && FindPlayerPed()->GetMoveSpeed().Magnitude() < 0.07f) {
+ if ((FindPlayerCoors() - pVehicle->GetPosition()).Magnitude() < 30.0f)
+ pVehicle->AutoPilot.m_nCruiseSpeed = Min(10, pVehicle->AutoPilot.m_nCruiseSpeed);
+ }
+}
+
+//--MIAMI: done
+void CCarAI::MellowOutChaseSpeedBoat(CVehicle* pVehicle)
+{
+ switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) {
+ case 0: pVehicle->AutoPilot.m_nCruiseSpeed = 8; break;
+ case 1: pVehicle->AutoPilot.m_nCruiseSpeed = 10; break;
+ case 2: pVehicle->AutoPilot.m_nCruiseSpeed = 15; break;
+ case 3: pVehicle->AutoPilot.m_nCruiseSpeed = 20; break;
+ case 4: pVehicle->AutoPilot.m_nCruiseSpeed = 25; break;
+ case 5: pVehicle->AutoPilot.m_nCruiseSpeed = 30; break;
+ case 6: pVehicle->AutoPilot.m_nCruiseSpeed = 40; break;
+ }
}
+//--MIAMI: done
void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
{
float flatSpeed = pVehicle->GetMoveSpeed().Magnitude2D();
@@ -629,6 +773,8 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
continue;
if (vehicle == pVehicle)
continue;
+ if (vehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)
+ return;
if (Abs(pVehicle->GetPosition().z - vehicle->GetPosition().z) >= 5.0f)
continue;
CVector2D distance = vehicle->GetPosition() - pVehicle->GetPosition();
diff --git a/src/control/CarAI.h b/src/control/CarAI.h
index e88807c8..d4af1806 100644
--- a/src/control/CarAI.h
+++ b/src/control/CarAI.h
@@ -10,17 +10,22 @@ public:
static float FindSwitchDistanceClose(CVehicle*);
static float FindSwitchDistanceFarNormalVehicle(CVehicle*);
static float FindSwitchDistanceFar(CVehicle*);
+ static void BackToCruisingIfNoWantedLevel(CVehicle*);
static void UpdateCarAI(CVehicle*);
static void CarHasReasonToStop(CVehicle*);
static float GetCarToGoToCoors(CVehicle*, CVector*);
+ static float GetCarToParkAtCoors(CVehicle*, CVector*);
static void AddPoliceCarOccupants(CVehicle*);
static void AddAmbulanceOccupants(CVehicle*);
static void AddFiretruckOccupants(CVehicle*);
static void TellOccupantsToLeaveCar(CVehicle*);
+ static void TellOccupantsToFleeCar(CVehicle*);
static void TellCarToRamOtherCar(CVehicle*, CVehicle*);
static void TellCarToBlockOtherCar(CVehicle*, CVehicle*);
static eCarMission FindPoliceCarMissionForWantedLevel();
+ static eCarMission FindPoliceBoatMissionForWantedLevel();
static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*);
static void MellowOutChaseSpeed(CVehicle*);
+ static void MellowOutChaseSpeedBoat(CVehicle*);
static void MakeWayForCarWithSiren(CVehicle *veh);
};
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index d6ccc8bb..963ef693 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -11,6 +11,7 @@
#include "Curves.h"
#include "CutsceneMgr.h"
#include "Gangs.h"
+#include "Game.h"
#include "Garages.h"
#include "General.h"
#include "IniFile.h"
@@ -19,6 +20,7 @@
#include "Ped.h"
#include "PlayerInfo.h"
#include "PlayerPed.h"
+#include "Population.h"
#include "Wanted.h"
#include "Pools.h"
#include "Renderer.h"
@@ -29,43 +31,54 @@
#include "VisibilityPlugins.h"
#include "Vehicle.h"
#include "Fire.h"
+#include "WaterLevel.h"
#include "World.h"
#include "Zones.h"
-#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS 51.0f
-#define DISTANCE_TO_SCAN_FOR_DANGER 11.0f
-#define SAFE_DISTANCE_TO_PED 3.0f
-#define INFINITE_Z 1000000000.0f
-
-#define VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING 4.0f
-#define PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING 4.0f
-#define OBJECT_HEIGHT_DIFF_TO_CONSIDER_WEAVING 8.0f
-#define WIDTH_COEF_TO_WEAVE_SAFELY 1.2f
-#define OBJECT_WIDTH_TO_WEAVE 0.3f
-#define PED_WIDTH_TO_WEAVE 0.8f
-
-#define PATH_DIRECTION_NONE 0
-#define PATH_DIRECTION_STRAIGHT 1
-#define PATH_DIRECTION_RIGHT 2
-#define PATH_DIRECTION_LEFT 4
-
-#define ATTEMPTS_TO_FIND_NEXT_NODE 15
-
-#define DISTANCE_TO_SWITCH_FROM_BLOCK_TO_STOP 5.0f
-#define DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK 10.0f
-#define MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING 0.13f
-#define DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN 40.0f
-#define MAX_ANGLE_TO_STEER_AT_HIGH_SPEED 0.2f
-#define MIN_SPEED_TO_START_LIMITING_STEER 0.45f
-#define DISTANCE_TO_NEXT_NODE_TO_SELECT_NEW 5.0f
-#define DISTANCE_TO_FACING_NEXT_NODE_TO_SELECT_NEW 8.0f
-#define DEFAULT_MAX_STEER_ANGLE 0.5f
-#define MIN_LOWERING_SPEED_COEFFICIENT 0.4f
-#define MAX_ANGLE_FOR_SPEED_LIMITING 1.2f
-#define MIN_ANGLE_FOR_SPEED_LIMITING 0.4f
-#define MIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES 0.1f
-#define MIN_ANGLE_TO_APPLY_HANDBRAKE 0.7f
-#define MIN_SPEED_TO_APPLY_HANDBRAKE 0.3f
+#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS (51.0f)
+#define DISTANCE_TO_SCAN_FOR_DANGER (14.0f)
+#define SAFE_DISTANCE_TO_PED (3.0f)
+#define INFINITE_Z (1000000000.0f)
+
+#define VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING (4.0f)
+#define PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING (4.0f)
+#define OBJECT_HEIGHT_DIFF_TO_CONSIDER_WEAVING (8.0f)
+#define WIDTH_COEF_TO_WEAVE_SAFELY (1.2f)
+#define OBJECT_WIDTH_TO_WEAVE (0.3f)
+#define PED_WIDTH_TO_WEAVE (0.8f)
+
+#define PATH_DIRECTION_NONE (0)
+#define PATH_DIRECTION_STRAIGHT (1)
+#define PATH_DIRECTION_RIGHT (2)
+#define PATH_DIRECTION_LEFT (4)
+
+#define ATTEMPTS_TO_FIND_NEXT_NODE (15)
+
+#define DISTANCE_TO_SWITCH_FROM_BLOCK_TO_STOP (5.0f)
+#define DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK (10.0f)
+#define MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING (0.13f)
+#define DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN (40.0f)
+#define MAX_ANGLE_TO_STEER_AT_HIGH_SPEED (0.2f)
+#define MIN_SPEED_TO_START_LIMITING_STEER (0.45f)
+#define DISTANCE_TO_NEXT_NODE_TO_SELECT_NEW (5.0f)
+#define DISTANCE_TO_FACING_NEXT_NODE_TO_SELECT_NEW (8.0f)
+#define DEFAULT_MAX_STEER_ANGLE (0.5f)
+#define MIN_LOWERING_SPEED_COEFFICIENT (0.4f)
+#define MAX_ANGLE_FOR_SPEED_LIMITING (1.2f)
+#define MIN_ANGLE_FOR_SPEED_LIMITING (0.4f)
+#define MIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES (0.1f)
+#define MIN_ANGLE_TO_APPLY_HANDBRAKE (0.7f)
+#define MIN_SPEED_TO_APPLY_HANDBRAKE (0.3f)
+
+#define PROBABILITY_OF_DEAD_PED_ACCIDENT (0.005f)
+#define DISTANCE_BETWEEN_CAR_AND_DEAD_PED (6.0f)
+#define PROBABILITY_OF_PASSENGER_IN_VEHICLE (0.125f)
+
+#define ONSCREEN_DESPAWN_RANGE (120.0f)
+#define MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN (100.0f)
+#define REQUEST_ONSCREEN_DISTANCE ((ONSCREEN_DESPAWN_RANGE + MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) / 2)
+#define OFFSCREEN_DESPAWN_RANGE (40.0f)
+#define EXTENDED_RANGE_DESPAWN_MULTIPLIER (1.5f)
int CCarCtrl::NumLawEnforcerCars;
int CCarCtrl::NumAmbulancesOnDuty;
@@ -81,23 +94,29 @@ int32 CCarCtrl::MaxNumberOfCarsInUse = 12;
uint32 CCarCtrl::LastTimeLawEnforcerCreated;
uint32 CCarCtrl::LastTimeFireTruckCreated;
uint32 CCarCtrl::LastTimeAmbulanceCreated;
+int32 CCarCtrl::MiamiViceCycle;
+uint32 CCarCtrl::LastTimeMiamiViceGenerated;
int32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
-int32 CCarCtrl::NextCarOfRating[TOTAL_CUSTOM_CLASSES];
int32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+int32 CCarCtrl::NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
+int32 CCarCtrl::NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
+int32 CCarCtrl::CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+int32 CCarCtrl::LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];
uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP];
void
CCarCtrl::GenerateRandomCars()
{
- if (CCutsceneMgr::IsRunning())
+ if (CCutsceneMgr::IsRunning()) {
+ CountDownToCarsAtStart = 2;
return;
+ }
if (NumRandomCars < 30){
- if (CountDownToCarsAtStart == 0){
+ if (CountDownToCarsAtStart == 0)
GenerateOneRandomCar();
- }
else if (--CountDownToCarsAtStart == 0) {
- for (int i = 0; i < 50; i++)
+ for (int i = 0; i < 100; i++)
GenerateOneRandomCar();
CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = 20;
}
@@ -111,6 +130,7 @@ void
CCarCtrl::GenerateOneRandomCar()
{
static int32 unk = 0;
+ bool bTopDownCamera = false;
CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];
CVector vecTargetPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
CVector2D vecPlayerSpeed = FindPlayerSpeed();
@@ -125,7 +145,7 @@ CCarCtrl::GenerateOneRandomCar()
int carClass;
int carModel;
if (pWanted->m_nWantedLevel > 1 && NumLawEnforcerCars < pWanted->m_MaximumLawEnforcerVehicles &&
- pWanted->m_CurrentCops < pWanted->m_MaxCops && (
+ pWanted->m_CurrentCops < pWanted->m_MaxCops && !CGame::IsInInterior() && (
pWanted->m_nWantedLevel > 3 ||
pWanted->m_nWantedLevel > 2 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 5000 ||
pWanted->m_nWantedLevel > 1 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 8000)) {
@@ -135,7 +155,7 @@ CCarCtrl::GenerateOneRandomCar()
carModel = ChoosePoliceCarModel();
}else{
carModel = ChooseModel(&zone, &vecTargetPos, &carClass);
- if (carClass == COPS && pWanted->m_nWantedLevel >= 1)
+ if (carClass == COPS && pWanted->m_nWantedLevel >= 1 || carModel < 0)
/* All cop spawns with wanted level are handled by condition above. */
/* In particular it means that cop cars never spawn if player has wanted level of 1. */
return;
@@ -159,8 +179,9 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn essentially anywhere. */
frontX = frontY = 0.707f; /* 45 degrees */
angleLimit = -1.0f;
+ bTopDownCamera = true;
invertAngleLimitTest = true;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE + 15.0f;
/* BUG: testForCollision not initialized in original game. */
testForCollision = false;
}else if (!pPlayerVehicle){
@@ -174,14 +195,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else if (fPlayerVehicleSpeed > 0.4f){ /* 72 km/h */
@@ -196,21 +217,21 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn a vehicle in a very narrow gap in front of a player */
angleLimit = 0.85f; /* approx 30 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 2:
/* Spawn a vehicle relatively far away from player. */
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 3:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else if (fPlayerVehicleSpeed > 0.1f){ /* 18 km/h */
@@ -224,14 +245,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn a vehicle in a very narrow gap in front of a player */
angleLimit = 0.85f; /* approx 30 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle relatively far away from player. */
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 2:
case 3:
@@ -239,7 +260,7 @@ CCarCtrl::GenerateOneRandomCar()
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}else{
@@ -254,14 +275,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle close to player to his side. */
/* Kinda not within camera angle. */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = false;
- preferredDistance = 40.0f;
+ preferredDistance = OFFSCREEN_DESPAWN_RANGE;
break;
}
}
@@ -269,17 +290,45 @@ CCarCtrl::GenerateOneRandomCar()
preferredDistance, angleLimit, invertAngleLimitTest, &spawnPosition, &curNodeId, &nextNodeId,
&positionBetweenNodes, carClass == COPS && pWanted->m_nWantedLevel >= 1))
return;
+ CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
+ CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
+ bool bBoatGenerated = false;
+ if ((CGeneral::GetRandomNumber() & 0xF) > Min(pCurNode->spawnRate, pNextNode->spawnRate))
+ return;
+ if (pCurNode->bWaterPath) {
+ bBoatGenerated = true;
+ if (carClass == COPS) {
+ carModel = MI_PREDATOR;
+ carClass = COPS_BOAT;
+ if (!CStreaming::HasModelLoaded(MI_PREDATOR)) {
+ CStreaming::RequestModel(MI_PREDATOR, STREAMFLAGS_DEPENDENCY);
+ return;
+ }
+ }
+ else {
+ int i;
+ carModel = -1;
+ for (i = 10; i > 0 && (carModel == -1 || !CStreaming::HasModelLoaded(carModel)); i--) {
+ carModel = ChooseBoatModel(ChooseBoatRating(&zone));
+ }
+ if (i == 0)
+ return;
+ }
+ if (pCurNode->bOnlySmallBoats || pNextNode->bOnlySmallBoats) {
+ if (BoatWithTallMast(carModel))
+ return;
+ }
+ }
int16 colliding;
- CWorld::FindObjectsKindaColliding(spawnPosition, 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
+ CWorld::FindObjectsKindaColliding(spawnPosition, bBoatGenerated ? 40.0f : 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
if (colliding)
/* If something is already present in spawn position, do not create vehicle*/
return;
- if (!ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))
+ if (!bBoatGenerated && !ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))
/* Testing if spawn position can reach target position via valid path. */
return;
int16 idInNode = 0;
- CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
- CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
+
while (idInNode < pCurNode->numLinks &&
ThePaths.ConnectedNode(idInNode + pCurNode->firstLink) != nextNodeId)
idInNode++;
@@ -287,48 +336,20 @@ CCarCtrl::GenerateOneRandomCar()
CCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId];
int16 lanesOnCurrentRoad = pPathLink->pathNodeIndex == nextNodeId ? pPathLink->numLeftLanes : pPathLink->numRightLanes;
CVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(carModel);
- if (lanesOnCurrentRoad == 0 || pModelInfo->m_vehicleType == VEHICLE_TYPE_BIKE)
+ if (lanesOnCurrentRoad == 0)
/* Not spawning vehicle if road is one way and intended direction is opposide to that way. */
- /* Also not spawning bikes but they don't exist in final game. */
return;
- CAutomobile* pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
+ CVehicle* pVehicle;
+ if (CModelInfo::IsBoatModel(carModel))
+ pVehicle = new CBoat(carModel, RANDOM_VEHICLE);
+ else if (CModelInfo::IsBikeModel(carModel))
+ return; // TODO(MIAMI): spawn bikes
+ else
+ pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
pVehicle->AutoPilot.m_nPrevRouteNode = 0;
pVehicle->AutoPilot.m_nCurrentRouteNode = curNodeId;
pVehicle->AutoPilot.m_nNextRouteNode = nextNodeId;
switch (carClass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- case MAFIA:
- case TRIAD:
- case DIABLO:
- case YAKUZA:
- case YARDIE:
- case COLOMB:
- case NINES:
- case GANG8:
- case GANG9:
- {
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
- if (carClass == EXEC)
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);
- else if (carClass == POOR || carClass == SPECIAL)
- pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);
- CVehicleModelInfo* pVehicleInfo = pVehicle->GetModelInfo();
- if (pVehicleInfo->GetColModel()->boundingBox.max.y - pVehicle->GetModelInfo()->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {
- pVehicle->AutoPilot.m_nCruiseSpeed *= 3;
- pVehicle->AutoPilot.m_nCruiseSpeed /= 4;
- }
- pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
- pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
- pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- break;
- }
case COPS:
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel != 0){
@@ -345,16 +366,37 @@ CCarCtrl::GenerateOneRandomCar()
if (carModel == MI_FBICAR){
pVehicle->m_currentColour1 = 0;
pVehicle->m_currentColour2 = 0;
- /* FBI cars are gray in carcols, but we want them black if they going after player. */
}
+ pVehicle->bCreatedAsPoliceVehicle = true;
+ break;
+ case COPS_BOAT:
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(4.0f, 16.0f);
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ pVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceBoatMissionForWantedLevel();
+ pVehicle->bCreatedAsPoliceVehicle = true;
+ break;
default:
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
+ if (carClass == EXEC)
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);
+ else if (carClass == POOR)
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);
+ if (pVehicle->GetColModel()->boundingBox.max.y - pVehicle->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {
+ pVehicle->AutoPilot.m_nCruiseSpeed *= 3;
+ pVehicle->AutoPilot.m_nCruiseSpeed /= 4;
+ }
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
break;
}
if (pVehicle && pVehicle->GetModelIndex() == MI_MRWHOOP)
pVehicle->m_bSirenOrAlarm = true;
pVehicle->AutoPilot.m_nNextPathNodeInfo = connectionId;
pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;
- CColBox* boundingBox = &CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel()->boundingBox;
+ CBox* boundingBox = &CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel()->boundingBox;
float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2;
float distanceBetweenNodes = (pCurNode->GetPosition() - pNextNode->GetPosition()).Magnitude2D();
/* If car is so long that it doesn't fit between two car nodes, place it directly in the middle. */
@@ -393,11 +435,6 @@ CCarCtrl::GenerateOneRandomCar()
pVehicle->GetRight() = CVector(forwardY, -forwardX, 0.0f);
pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);
- float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX();
- float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY();
- float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX();
- float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY();
-
#ifdef FIX_BUGS
CCarPathLink* pCurrentLink;
CCarPathLink* pNextLink;
@@ -494,6 +531,7 @@ CCarCtrl::GenerateOneRandomCar()
pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
(0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;
#endif
+
CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f);
CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f);
CVector positionIncludingCurve;
@@ -515,62 +553,69 @@ CCarCtrl::GenerateOneRandomCar()
float groundZ = INFINITE_Z;
CColPoint colPoint;
CEntity* pEntity;
- if (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
- groundZ = colPoint.point.z;
- if (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)){
- if (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))
+ if (bBoatGenerated) {
+ if (!CWaterLevel::GetWaterLevel(finalPosition, &groundZ, true)) {
+ delete pVehicle;
+ return;
+ }
+ }
+ else {
+ if (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
groundZ = colPoint.point.z;
+ if (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)) {
+ if (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))
+ groundZ = colPoint.point.z;
+ }
}
if (groundZ == INFINITE_Z || ABS(groundZ - finalPosition.z) > 7.0f) {
/* Failed to find ground or too far from expected position. */
delete pVehicle;
return;
}
- finalPosition.z = groundZ + pVehicle->GetHeightAboveRoad();
+ if (CModelInfo::IsBoatModel(carModel)) {
+ finalPosition.z = groundZ;
+ pVehicle->bExtendedRange = true;
+ }
+ else
+ finalPosition.z = groundZ + pVehicle->GetHeightAboveRoad();
pVehicle->SetPosition(finalPosition);
pVehicle->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED);
CVector2D speedDifferenceWithTarget = (CVector2D)pVehicle->GetMoveSpeed() - vecPlayerSpeed;
CVector2D distanceToTarget = positionIncludingCurve - vecTargetPos;
switch (carClass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- case MAFIA:
- case TRIAD:
- case DIABLO:
- case YAKUZA:
- case YARDIE:
- case COLOMB:
- case NINES:
- case GANG8:
- case GANG9:
- pVehicle->SetStatus(STATUS_SIMPLE);
- break;
case COPS:
pVehicle->SetStatus((pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS);
pVehicle->ChangeLawEnforcerState(1);
break;
+ case COPS_BOAT:
+ pVehicle->ChangeLawEnforcerState(1);
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ break;
default:
+ bBoatGenerated ? pVehicle->SetStatus(STATUS_PHYSICS) : pVehicle->SetStatus(STATUS_SIMPLE);
break;
}
CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
if (!pVehicle->GetIsOnScreen()){
- if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > 50.0f) {
+ if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > OFFSCREEN_DESPAWN_RANGE * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f)) {
/* Too far away cars that are not visible aren't needed. */
delete pVehicle;
return;
}
- }else if((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * 130.0f ||
- (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 110.0f){
- delete pVehicle;
- return;
- }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 90.0f * TheCamera.GenerationDistMultiplier){
- delete pVehicle;
- return;
+ }else{
+ if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f) * ONSCREEN_DESPAWN_RANGE ||
+ (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) {
+ delete pVehicle;
+ return;
+ }
+ if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera) {
+ delete pVehicle;
+ return;
+ }
+ if (pVehicle->GetModelIndex() == MI_MARQUIS) { // so marquis can only spawn if player doesn't see it?
+ delete pVehicle;
+ return;
+ }
}
CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo();
float radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius;
@@ -593,58 +638,152 @@ CCarCtrl::GenerateOneRandomCar()
}
pVehicleModel->AvoidSameVehicleColour(&pVehicle->m_currentColour1, &pVehicle->m_currentColour2);
CWorld::Add(pVehicle);
- if (carClass == COPS)
+ if (carClass == COPS || carClass == COPS_BOAT)
CCarAI::AddPoliceCarOccupants(pVehicle);
- else
+ else {
pVehicle->SetUpDriver();
- if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */
+ int32 passengers = 0;
+ for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++)
+ passengers += (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < PROBABILITY_OF_PASSENGER_IN_VEHICLE) ? 1 : 0;
+ if (CModelInfo::IsCarModel(carModel) && (CModelInfo::GetModelInfo(carModel)->GetAnimFileIndex() == CAnimManager::GetAnimationBlockIndex("van") && passengers >= 1))
+ passengers = 1;
+ for (int i = 0; i < passengers; i++) {
+ CPed* pPassenger = pVehicle->SetupPassenger(i);
+ if (pPassenger) {
+ ++CPopulation::ms_nTotalCarPassengerPeds;
+ pPassenger->bCarPassenger = true;
+ }
+ }
+ }
+ int nMadDrivers;
+ switch (pVehicle->GetVehicleAppearance()) {
+ case VEHICLE_BIKE:
+ nMadDrivers = 30;
+ break;
+ case VEHICLE_BOAT:
+ nMadDrivers = 40;
+ break;
+ default:
+ nMadDrivers = 6;
+ break;
+ }
+ if ((CGeneral::GetRandomNumber() & 0x7F) < nMadDrivers /* TODO(MIAMI): || mad drivers cheat */) {
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
pVehicle->AutoPilot.m_nCruiseSpeed += 10;
}
if (carClass == COPS)
LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds();
+ if (pVehicle->GetModelIndex() == MI_CADDY) {
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ if (carClass == COPS && pVehicle->GetModelIndex() == MI_VICECHEE) {
+ CVehicleModelInfo* pVehicleModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_VICECHEE);
+ switch (MiamiViceCycle) {
+ case 0:
+ pVehicleModel->SetVehicleColour(53, 77);
+ break;
+ case 1:
+ pVehicleModel->SetVehicleColour(15, 77);
+ break;
+ case 2:
+ pVehicleModel->SetVehicleColour(41, 77);
+ break;
+ case 3:
+ pVehicleModel->SetVehicleColour(61, 77);
+ break;
+ default:
+ break;
+ }
+ }
+ if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) >= (1 - PROBABILITY_OF_DEAD_PED_ACCIDENT)) {
+ if (CModelInfo::IsCarModel(pVehicle->GetModelIndex()) && !pVehicle->bIsLawEnforcer) {
+ if (CPopulation::AddDeadPedInFrontOfCar(pVehicle->GetPosition() + pVehicle->GetForward() * DISTANCE_BETWEEN_CAR_AND_DEAD_PED, pVehicle)) {
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->SetMoveSpeed(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < pVehicle->m_nNumPassengers; i++) {
+ if (pVehicle->pPassengers[i]) {
+ pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
+ pVehicle->pPassengers[i]->m_nLastPedState = PED_WANDER_PATH;
+ pVehicle->pPassengers[i]->m_vehicleInAccident = pVehicle;
+ pVehicle->pPassengers[i]->bDeadPedInFrontOfCar = true;
+ pVehicle->RegisterReference((CEntity**)&pVehicle->pPassengers[i]->m_vehicleInAccident);
+ }
+ }
+ if (pVehicle->pDriver) {
+ pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
+ pVehicle->pDriver->m_nLastPedState = PED_WANDER_PATH;
+ pVehicle->pDriver->m_vehicleInAccident = pVehicle;
+ pVehicle->pDriver->bDeadPedInFrontOfCar = true;
+ pVehicle->RegisterReference((CEntity**)&pVehicle->pDriver->m_vehicleInAccident);
+ }
+ }
+ }
+ }
+}
+
+bool
+CCarCtrl::BoatWithTallMast(int32 mi)
+{
+ return mi == MI_RIO || mi == MI_TROPIC || mi == MI_MARQUIS;
+}
+
+int32
+CCarCtrl::ChooseBoatModel(int32 rating)
+{
+ ++NumRequestsOfCarRating[rating];
+ return ChooseCarModel(rating);
+}
+
+int32
+CCarCtrl::ChooseBoatRating(CZoneInfo* pZoneInfo)
+{
+ int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
+ for (int i = 0; i < NUM_BOAT_CLASSES - 1; i++) {
+ if (rnd < pZoneInfo->boatThreshold[i])
+ return FIRST_BOAT_RATING + i;
+ }
+ return FIRST_BOAT_RATING + NUM_BOAT_CLASSES - 1;
+}
+
+int32
+CCarCtrl::ChooseCarRating(CZoneInfo* pZoneInfo)
+{
+ int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
+ for (int i = 0; i < NUM_CAR_CLASSES - 1; i++) {
+ if (rnd < pZoneInfo->carThreshold[i])
+ return i;
+ }
+ return FIRST_CAR_RATING + NUM_CAR_CLASSES - 1;
}
int32
CCarCtrl::ChooseModel(CZoneInfo* pZone, CVector* pPos, int* pClass) {
int32 model = -1;
- while (model == -1 || !CStreaming::HasModelLoaded(model)){
+ for (int i = 0; i < 10 && (model == -1 || !CStreaming::HasModelLoaded(model)); i++) {
int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
- if (rnd < pZone->carThreshold[0])
- model = CCarCtrl::ChooseCarModel((*pClass = POOR));
- else if (rnd < pZone->carThreshold[1])
- model = CCarCtrl::ChooseCarModel((*pClass = RICH));
- else if (rnd < pZone->carThreshold[2])
- model = CCarCtrl::ChooseCarModel((*pClass = EXEC));
- else if (rnd < pZone->carThreshold[3])
- model = CCarCtrl::ChooseCarModel((*pClass = WORKER));
- else if (rnd < pZone->carThreshold[4])
- model = CCarCtrl::ChooseCarModel((*pClass = SPECIAL));
- else if (rnd < pZone->carThreshold[5])
- model = CCarCtrl::ChooseCarModel((*pClass = BIG));
- else if (rnd < pZone->copThreshold)
- *pClass = COPS, model = CCarCtrl::ChoosePoliceCarModel();
- else if (rnd < pZone->gangThreshold[0])
- model = CCarCtrl::ChooseGangCarModel((*pClass = MAFIA) - MAFIA);
- else if (rnd < pZone->gangThreshold[1])
- model = CCarCtrl::ChooseGangCarModel((*pClass = TRIAD) - MAFIA);
- else if (rnd < pZone->gangThreshold[2])
- model = CCarCtrl::ChooseGangCarModel((*pClass = DIABLO) - MAFIA);
- else if (rnd < pZone->gangThreshold[3])
- model = CCarCtrl::ChooseGangCarModel((*pClass = YAKUZA) - MAFIA);
- else if (rnd < pZone->gangThreshold[4])
- model = CCarCtrl::ChooseGangCarModel((*pClass = YARDIE) - MAFIA);
- else if (rnd < pZone->gangThreshold[5])
- model = CCarCtrl::ChooseGangCarModel((*pClass = COLOMB) - MAFIA);
- else if (rnd < pZone->gangThreshold[6])
- model = CCarCtrl::ChooseGangCarModel((*pClass = NINES) - MAFIA);
- else if (rnd < pZone->gangThreshold[7])
- model = CCarCtrl::ChooseGangCarModel((*pClass = GANG8) - MAFIA);
- else if (rnd < pZone->gangThreshold[8])
- model = CCarCtrl::ChooseGangCarModel((*pClass = GANG9) - MAFIA);
- else
- model = CCarCtrl::ChooseCarModel((*pClass = TAXI));
+
+ if (rnd < pZone->copThreshold) {
+ *pClass = COPS;
+ model = ChoosePoliceCarModel();
+ continue;
+ }
+
+ int j;
+ for (j = 0; j < NUM_GANG_CAR_CLASSES; j++) {
+ if (rnd < pZone->gangThreshold[i]) {
+ *pClass = j + FIRST_GANG_CAR_RATING;
+ model = ChooseGangCarModel(j);
+ break;
+ }
+ }
+
+ if (j != NUM_GANG_CAR_CLASSES)
+ continue;
+
+ *pClass = ChooseCarRating(pZone);
+ model = ChooseCarModel(*pClass);
}
return model;
}
@@ -653,34 +792,86 @@ int32
CCarCtrl::ChooseCarModel(int32 vehclass)
{
int32 model = -1;
- switch (vehclass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- {
- if (TotalNumOfCarsOfRating[vehclass] == 0)
- debug("ChooseCarModel : No cars of type %d have been declared\n", vehclass);
- model = CarArrays[vehclass][NextCarOfRating[vehclass]];
- int32 total = TotalNumOfCarsOfRating[vehclass];
- NextCarOfRating[vehclass] += CGeneral::GetRandomNumberInRange(1, total);
- while (NextCarOfRating[vehclass] >= total)
- NextCarOfRating[vehclass] -= total;
- //NextCarOfRating[vehclass] %= total;
- TotalNumOfCarsOfRating[vehclass] = total; /* why... */
- }
- default:
- break;
- }
- return model;
+ ++NumRequestsOfCarRating[vehclass];
+ if (NumOfLoadedCarsOfRating[vehclass] == 0)
+ return -1;
+ int32 rnd = CGeneral::GetRandomNumberInRange(0, CarFreqArrays[vehclass][NumOfLoadedCarsOfRating[vehclass] - 1]);
+ int32 index = 0;
+ while (rnd > CarFreqArrays[vehclass][index])
+ index++;
+ assert(LoadedCarsArray[vehclass][index]);
+ return LoadedCarsArray[vehclass][index];
+}
+
+void
+CCarCtrl::AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq)
+{
+ LoadedCarsArray[rating][NumOfLoadedCarsOfRating[rating]] = mi;
+ assert(mi >= 130);
+ CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] = freq;
+ if (NumOfLoadedCarsOfRating[rating])
+ CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] += CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating] - 1];
+ NumOfLoadedCarsOfRating[rating]++;
+}
+
+void
+CCarCtrl::RemoveFromLoadedVehicleArray(int mi, int32 rating)
+{
+ int index = 0;
+ while (LoadedCarsArray[rating][index] != -1) {
+ if (LoadedCarsArray[rating][index] == mi)
+ break;
+ index++;
+ }
+ assert(LoadedCarsArray[rating][index] == mi);
+ int32 freq = CarFreqArrays[rating][index];
+ if (index > 0)
+ freq -= CarFreqArrays[rating][index - 1];
+ while (LoadedCarsArray[rating][index + 1] != -1) {
+ LoadedCarsArray[rating][index] = LoadedCarsArray[rating][index + 1];
+ CarFreqArrays[rating][index] = CarFreqArrays[rating][index + 1] - freq;
+ index++;
+ }
+ --NumOfLoadedCarsOfRating[rating];
+}
+
+int32
+CCarCtrl::ChooseCarModelToLoad(int rating)
+{
+ return CarArrays[rating][CGeneral::GetRandomNumberInRange(0, TotalNumOfCarsOfRating[rating])];
}
int32
CCarCtrl::ChoosePoliceCarModel(void)
{
+ if (FindPlayerPed()->m_pWanted->AreMiamiViceRequired() &&
+#ifdef FIX_BUGS
+ (CTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 || LastTimeMiamiViceGenerated == 0) &&
+#else
+ CTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 &&
+#endif
+ CStreaming::HasModelLoaded(MI_VICECHEE)) {
+ switch (MiamiViceCycle) {
+ case 0:
+ if (CStreaming::HasModelLoaded(MI_VICE1) && CStreaming::HasModelLoaded(MI_VICE2))
+ return MI_VICECHEE;
+ break;
+ case 1:
+ if (CStreaming::HasModelLoaded(MI_VICE3) && CStreaming::HasModelLoaded(MI_VICE4))
+ return MI_VICECHEE;
+ break;
+ case 2:
+ if (CStreaming::HasModelLoaded(MI_VICE5) && CStreaming::HasModelLoaded(MI_VICE6))
+ return MI_VICECHEE;
+ break;
+ case 3:
+ if (CStreaming::HasModelLoaded(MI_VICE7) && CStreaming::HasModelLoaded(MI_VICE8))
+ return MI_VICECHEE;
+ break;
+ default:
+ break;
+ }
+ }
if (FindPlayerPed()->m_pWanted->AreSwatRequired() &&
CStreaming::HasModelLoaded(MI_ENFORCER) &&
CStreaming::HasModelLoaded(MI_POLICE))
@@ -701,7 +892,7 @@ int32
CCarCtrl::ChooseGangCarModel(int32 gang)
{
if (CStreaming::HasModelLoaded(MI_GANG01 + 2 * gang) &&
- CStreaming::HasModelLoaded(MI_GANG02 + 2 * gang))
+ CStreaming::HasModelLoaded(MI_GANG01+1 + 2 * gang))
return CGangs::GetGangVehicleModel(gang);
return -1;
}
@@ -709,6 +900,7 @@ CCarCtrl::ChooseGangCarModel(int32 gang)
void
CCarCtrl::AddToCarArray(int32 id, int32 vehclass)
{
+ assert(TotalNumOfCarsOfRating[vehclass] < MAX_CAR_MODELS_IN_ARRAY);
CarArrays[vehclass][TotalNumOfCarsOfRating[vehclass]++] = id;
}
@@ -730,6 +922,36 @@ CCarCtrl::RemoveDistantCars()
}
void
+CCarCtrl::RemoveCarsIfThePoolGetsFull(void)
+{
+ if ((CTimer::GetFrameCounter() & 7) != 3)
+ return;
+ if (CPools::GetVehiclePool()->GetNoOfFreeSpaces() >= 8)
+ return;
+ int i = CPools::GetVehiclePool()->GetSize();
+ float md = 999999.9f;
+ CVehicle* pClosestVehicle = nil;
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ if (IsThisVehicleInteresting(pVehicle) || pVehicle->bIsLocked)
+ continue;
+ if (!pVehicle->CanBeDeleted() || CCranes::IsThisCarBeingTargettedByAnyCrane(pVehicle))
+ continue;
+ float distance = (TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude();
+ if (distance < md) {
+ md = distance;
+ pClosestVehicle = pVehicle;
+ }
+ }
+ if (pClosestVehicle) {
+ CWorld::Remove(pClosestVehicle);
+ delete pClosestVehicle;
+ }
+}
+
+void
CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
{
CVector vecPlayerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
@@ -742,7 +964,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
return;
}
float distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D();
- float threshold = 50.0f;
+ float threshold = OFFSCREEN_DESPAWN_RANGE;
if (pVehicle->GetIsOnScreen() ||
TheCamera.Cams[TheCamera.ActiveCam].LookingLeft ||
TheCamera.Cams[TheCamera.ActiveCam].LookingRight ||
@@ -754,12 +976,14 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
pVehicle->bIsLawEnforcer ||
pVehicle->bIsCarParkVehicle
){
- threshold = 130.0f * TheCamera.GenerationDistMultiplier;
+ threshold = ONSCREEN_DESPAWN_RANGE * TheCamera.GenerationDistMultiplier;
}
+ if (TheCamera.GetForward().z < -0.9f)
+ threshold = 70.0f;
if (pVehicle->bExtendedRange)
- threshold *= 1.5f;
+ threshold *= EXTENDED_RANGE_DESPAWN_MULTIPLIER;
if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
- if (pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) {
+ if (pVehicle->GetIsOnScreen()){
pVehicle->bFadeOut = true;
}else{
CWorld::Remove(pVehicle);
@@ -768,7 +992,8 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
return;
}
}
- if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS) &&
+ if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS &&
+ (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS)) &&
CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 5000 &&
!pVehicle->GetIsOnScreen() &&
(pVehicle->GetPosition() - vecPlayerPos).Magnitude2D() > 25.0f &&
@@ -785,7 +1010,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
if (pVehicle->GetStatus() != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0)
return;
if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&
- !(pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) ){
+ !pVehicle->GetIsOnScreen()){
if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){
if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
CWorld::Remove(pVehicle);
@@ -809,6 +1034,16 @@ CCarCtrl::CountCarsOfType(int32 mi)
return total;
}
+static CVector GetRandomOffsetForVehicle(CVehicle* pVehicle, bool bNext)
+{
+ CVector offset;
+ int32 seed = ((bNext ? pVehicle->AutoPilot.m_nNextPathNodeInfo : pVehicle->AutoPilot.m_nCurrentPathNodeInfo) + pVehicle->m_randomSeed) & 7;
+ offset.x = (seed - 3) * 0.009f;
+ offset.y = ((seed >> 3) - 3) * 0.009f;
+ offset.z = 0.0f;
+ return offset;
+}
+
void
CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
{
@@ -841,8 +1076,12 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f);
- CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
- CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
+ CVector directionCurrentLink = GetRandomOffsetForVehicle(pVehicle, false);
+ directionCurrentLink += CVector(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
+ directionCurrentLink.Normalise();
+ CVector directionNextLink = GetRandomOffsetForVehicle(pVehicle, true);
+ directionNextLink += CVector(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
+ directionNextLink.Normalise();
CVector positionIncludingCurve;
CVector directionIncludingCurve;
CCurves::CalcCurvePoint(
@@ -865,7 +1104,7 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle)
{
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS ||
pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_PLOUGH_THROUGH)
- return pVehicle->AutoPilot.m_nCruiseSpeed;
+ return pVehicle->AutoPilot.GetCruiseSpeed();
float left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_DANGER;
float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER;
float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER;
@@ -877,23 +1116,23 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle)
assert(xstart <= xend);
assert(ystart <= yend);
- float maxSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ float maxSpeed = pVehicle->AutoPilot.GetCruiseSpeed();
CWorld::AdvanceCurrentScanCode();
for (int y = ystart; y <= yend; y++){
for (int x = xstart; x <= xend; x++){
CSector* s = CWorld::GetSector(x, y);
- SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
- SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);
+ SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
+ SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());
}
}
pVehicle->bWarnedPeds = true;
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS)
return maxSpeed;
- return (maxSpeed + pVehicle->AutoPilot.m_nCruiseSpeed) / 2;
+ return (maxSpeed + pVehicle->AutoPilot.GetCruiseSpeed()) / 2;
}
void
@@ -1095,8 +1334,8 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle,
float proximityA = TestCollisionBetween2MovingRects(pOtherVehicle, pVehicle, projectionX, projectionY, &forwardA, &forwardB, 0);
float proximityB = TestCollisionBetween2MovingRects(pVehicle, pOtherVehicle, -projectionX, -projectionY, &forwardB, &forwardA, 1);
float minProximity = Min(proximityA, proximityB);
- if (minProximity >= 0.0f && minProximity < 1.0f){
- minProximity = Max(0.0f, (minProximity - 0.2f) * 1.25f);
+ if (minProximity >= 0.0f && minProximity < 1.5f){
+ minProximity = Max(0.0f, (minProximity - 0.2f) / 1.3f);
pVehicle->AutoPilot.m_bSlowedDownBecauseOfCars = true;
*pSpeed = Min(*pSpeed, minProximity * curSpeed);
}
@@ -1322,19 +1561,21 @@ void CCarCtrl::WeaveThroughCarsSectorList(CPtrList& lst, CVehicle* pVehicle, CPh
void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)
{
+ CVehicle* pOtherCar = (CVehicle*)pOtherEntity;
+ if (pVehicle->bPartOfConvoy && pOtherCar->bPartOfConvoy)
+ return;
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE && pOtherEntity == FindPlayerVehicle())
return;
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMCAR_CLOSE && pOtherEntity == pVehicle->AutoPilot.m_pTargetCar)
return;
- CVehicle* pOtherCar = (CVehicle*)pOtherEntity;
CVector2D vecDiff = pOtherCar->GetPosition() - pVehicle->GetPosition();
float angleBetweenVehicles = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);
float distance = vecDiff.Magnitude();
if (distance < 1.0f)
return;
if (DotProduct2D(pVehicle->GetMoveSpeed() - pOtherCar->GetMoveSpeed(), vecDiff) * 110.0f -
- pOtherCar->GetModelInfo()->GetColModel()->boundingSphere.radius -
- pVehicle->GetModelInfo()->GetColModel()->boundingSphere.radius < distance)
+ pOtherCar->GetColModel()->boundingSphere.radius -
+ pVehicle->GetColModel()->boundingSphere.radius < distance)
return;
CVector2D forward = pVehicle->GetForward();
forward.Normalise();
@@ -1508,23 +1749,30 @@ bool CCarCtrl::PickNextNodeAccordingStrategy(CVehicle* pVehicle)
return false;
default:
PickNextNodeRandomly(pVehicle);
+ if (ThePaths.GetNode(pVehicle->AutoPilot.m_nNextRouteNode)->bOnlySmallBoats && BoatWithTallMast(pVehicle->GetModelIndex()))
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
return false;
}
}
void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int32 prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;
int32 curNode = pVehicle->AutoPilot.m_nNextRouteNode;
uint8 totalLinks = ThePaths.m_pathNodes[curNode].numLinks;
CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
-#ifdef FIX_BUGS
- uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ?
- pCurLink->numLeftLanes : pCurLink->numRightLanes;
-#else
- uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ?
- pCurLink->numRightLanes : pCurLink->numLeftLanes;
-#endif
+ uint8 lanesOnCurrentPath;
+ bool isOnOneWayRoad;
+ if (pCurLink->pathNodeIndex == curNode) {
+ lanesOnCurrentPath = pCurLink->numLeftLanes;
+ isOnOneWayRoad = pCurLink->numRightLanes == 0;
+ }
+ else {
+ lanesOnCurrentPath = pCurLink->numRightLanes;
+ isOnOneWayRoad = pCurLink->numLeftLanes == 0;
+ }
uint8 allowedDirections = PATH_DIRECTION_NONE;
uint8 nextLane = pVehicle->AutoPilot.m_nNextLane;
if (nextLane == 0)
@@ -1546,6 +1794,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
CCarPathLink* pNextLink;
CPathNode* pNextPathNode;
bool goingAgainstOneWayRoad;
+ bool nextNodeIsOneWayRoad;
uint8 direction;
for(attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++){
if (attempt != 0){
@@ -1555,7 +1804,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
if ((!pNextPathNode->bDeadEnd || pPrevPathNode->bDeadEnd) &&
(!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) &&
(!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel) &&
- !goingAgainstOneWayRoad)
+ !goingAgainstOneWayRoad && (!isOnOneWayRoad || !nextNodeIsOneWayRoad))
break;
}
}
@@ -1565,9 +1814,10 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
direction = FindPathDirection(prevNode, curNode, pVehicle->AutoPilot.m_nNextRouteNode);
pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];
goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0;
+ nextNodeIsOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numLeftLanes == 0 : pNextLink->numRightLanes == 0;
}
if (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) {
- /* If we failed 15 times, then remove dead end and current lane limitations */
+ /* If we failed 15 times, then remove dead end, one way road and current lane limitations */
for (attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++) {
if (attempt != 0) {
if (pVehicle->AutoPilot.m_nNextRouteNode != prevNode) {
@@ -1648,6 +1898,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
}
if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0;
+#ifdef FIX_BUGS
CVector positionOnCurrentLinkIncludingLane(
pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
@@ -1656,6 +1907,16 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f);
+#else
+ CVector positionOnCurrentLinkIncludingLane(
+ pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH),
+ pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
+ 0.0f);
+ CVector positionOnNextLinkIncludingLane(
+ pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
+ pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
+ 0.0f);
+#endif
float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
@@ -1706,74 +1967,57 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float targetY, CVehicle* pTarget)
#endif
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNode];
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];
- CPathNode* pTargetNode;
+ CPathNode* pTargetNode[2];
int16 numNodes;
float distanceToTargetNode;
- if (pTarget && pTarget->m_pCurGroundEntity &&
- pTarget->m_pCurGroundEntity->IsBuilding() &&
- ((CBuilding*)pTarget->m_pCurGroundEntity)->GetIsATreadable() &&
- ((CTreadable*)pTarget->m_pCurGroundEntity)->m_nodeIndices[0][0] >= 0){
- CTreadable* pCurrentMapObject = (CTreadable*)pTarget->m_pCurGroundEntity;
- int closestNode = -1;
- float minDist = 100000.0f;
- for (int i = 0; i < 12; i++){
- int node = pCurrentMapObject->m_nodeIndices[0][i];
- if (node < 0)
- break;
- float dist = (ThePaths.m_pathNodes[node].GetPosition() - pTarget->GetPosition()).Magnitude();
- if (dist < minDist){
- minDist = dist;
- closestNode = node;
- }
- }
- ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
+ ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
#ifdef FIX_PATHFIND_BUG
- CVector(targetX, targetY, targetZ),
+ CVector(targetX, targetY, targetZ),
#else
- CVector(targetX, targetY, 0.0f),
+ CVector(targetX, targetY, 0.0f),
#endif
- &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode);
- }else
- {
-
- ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
-#ifdef FIX_PATHFIND_BUG
- CVector(targetX, targetY, targetZ),
-#else
- CVector(targetX, targetY, 0.0f),
-#endif
- &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1);
- }
+ pTargetNode, &numNodes, 2, pVehicle, &distanceToTargetNode, 999999.9f, -1);
int newNextNode;
int nextLink;
- if (numNodes != 1 || pTargetNode == pCurNode){
- float currentAngle = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
- nextLink = 0;
- float lowestAngleChange = 10.0f;
- int numLinks = pCurNode->numLinks;
- newNextNode = 0;
- for (int i = 0; i < numLinks; i++){
- int conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink);
- if (conNode == prevNode && i > 1)
- continue;
- CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode];
- float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());
- angle = LimitRadianAngle(angle - currentAngle);
- angle = ABS(angle);
- if (angle < lowestAngleChange){
- lowestAngleChange = angle;
- newNextNode = conNode;
- nextLink = i;
+ if (numNodes != 1 && numNodes != 2 || pTargetNode[0] == pCurNode){
+ if (numNodes != 2 || pTargetNode[1] == pCurNode) {
+ float currentAngle = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ nextLink = 0;
+ float lowestAngleChange = 10.0f;
+ int numLinks = pCurNode->numLinks;
+ newNextNode = 0;
+ for (int i = 0; i < numLinks; i++) {
+ int conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink);
+ if (conNode == prevNode && i > 1)
+ continue;
+ CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode];
+ float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());
+ angle = LimitRadianAngle(angle - currentAngle);
+ angle = ABS(angle);
+ if (angle < lowestAngleChange) {
+ lowestAngleChange = angle;
+ newNextNode = conNode;
+ nextLink = i;
+ }
}
}
- }else{
+ else {
+ nextLink = 0;
+ newNextNode = pTargetNode[1] - ThePaths.m_pathNodes;
+ for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++)
+ ;
+ }
+ }
+ else {
nextLink = 0;
- newNextNode = pTargetNode - ThePaths.m_pathNodes;
+ newNextNode = pTargetNode[0] - ThePaths.m_pathNodes;
for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++)
;
}
@@ -1793,11 +2037,11 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
int8 lanesOnNextNode;
if (curNode >= pVehicle->AutoPilot.m_nNextRouteNode) {
pVehicle->AutoPilot.m_nNextDirection = 1;
- lanesOnNextNode = pNextLink->numLeftLanes;
+ lanesOnNextNode = pNextLink->numRightLanes;
}
else {
pVehicle->AutoPilot.m_nNextDirection = -1;
- lanesOnNextNode = pNextLink->numRightLanes;
+ lanesOnNextNode = pNextLink->numLeftLanes;
}
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY();
@@ -1852,6 +2096,8 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];
if (pVehicle->AutoPilot.m_nPathFindNodesCount == 0){
@@ -1944,6 +2190,7 @@ void CCarCtrl::Init(void)
LastTimeAmbulanceCreated = 0;
#ifdef FIX_BUGS
LastTimeLawEnforcerCreated = 0;
+ LastTimeMiamiViceGenerated = 0;
#endif
bCarsGeneratedAroundCamera = false;
CountDownToCarsAtStart = 2;
@@ -1951,9 +2198,11 @@ void CCarCtrl::Init(void)
for (int i = 0; i < MAX_CARS_TO_KEEP; i++)
apCarsToKeep[i] = nil;
for (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++){
- for (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++)
- CarArrays[i][j] = 0;
- NextCarOfRating[i] = 0;
+ for (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++) {
+ LoadedCarsArray[i][j] = -1;
+ }
+ NumOfLoadedCarsOfRating[i] = 0;
+ NumRequestsOfCarRating[i] = 0;
TotalNumOfCarsOfRating[i] = 0;
}
}
@@ -1971,13 +2220,14 @@ void CCarCtrl::ReInit(void)
LastTimeFireTruckCreated = 0;
LastTimeAmbulanceCreated = 0;
LastTimeLawEnforcerCreated = 0;
+ LastTimeMiamiViceGenerated = 0;
#endif
CountDownToCarsAtStart = 2;
CarDensityMultiplier = 1.0f;
for (int i = 0; i < MAX_CARS_TO_KEEP; i++)
apCarsToKeep[i] = nil;
for (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++)
- NextCarOfRating[i] = 0;
+ NumRequestsOfCarRating[i] = 0;
}
void CCarCtrl::DragCarToPoint(CVehicle* pVehicle, CVector* pPoint)
@@ -2087,7 +2337,7 @@ void CCarCtrl::SteerAICarWithPhysics(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
break;
case TEMPACT_HANDBRAKETURNLEFT:
- swerve = -1.0f; // It seems like this should be swerve = 1.0f (fixed in VC)
+ swerve = 1.0f;
accel = 0.0f;
brake = 0.0f;
handbrake = true;
@@ -2095,7 +2345,7 @@ void CCarCtrl::SteerAICarWithPhysics(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
break;
case TEMPACT_HANDBRAKETURNRIGHT:
- swerve = 1.0f; // It seems like this should be swerve = -1.0f (fixed in VC)
+ swerve = -1.0f;
accel = 0.0f;
brake = 0.0f;
handbrake = true;
@@ -2206,6 +2456,9 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
SteerAICarWithPhysicsTryingToBlockTarget_Stop(pVehicle, FindPlayerCoors().x, FindPlayerCoors().y,
FindPlayerSpeed().x, FindPlayerSpeed().y, pSwerve, pAccel, pBrake, pHandbrake);
return;
+ case MISSION_WAITFORDELETION:
+ case MISSION_HELI_LAND:
+ return;
case MISSION_GOTOCOORDS_STRAIGHT:
case MISSION_GOTO_COORDS_STRAIGHT_ACCURATE:
SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil,
@@ -2219,6 +2472,12 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
*pHandbrake = true;
*pBrake = 0.5f;
return;
+ case MISSION_GOTOCOORDS_ASTHECROWSWIMS:
+ SteerAIBoatWithPhysicsHeadingForTarget(pVehicle,
+ pVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,
+ pSwerve, pAccel, pBrake);
+ *pHandbrake = false;
+ return;
case MISSION_RAMCAR_CLOSE:
SteerAICarWithPhysicsHeadingForTarget(pVehicle, pVehicle->AutoPilot.m_pTargetCar,
pVehicle->AutoPilot.m_pTargetCar->GetPosition().x, pVehicle->AutoPilot.m_pTargetCar->GetPosition().y,
@@ -2240,26 +2499,93 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
pVehicle->AutoPilot.m_pTargetCar->GetMoveSpeed().y,
pSwerve, pAccel, pBrake, pHandbrake);
return;
+ case MISSION_HELI_FLYTOCOORS:
+ //SteerAIHeliTowardsTargetCoors((CAutomobile*)pVehicle);
+ return;
+ case MISSION_ATTACKPLAYER:
+ SteerAIBoatWithPhysicsAttackingPlayer(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_PLANE_FLYTOCOORS:
+ //SteerAIPlaneTowardsTargetCoors((CAutomobile*)pVehicle);
+ return;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1:
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil,
+ pVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,
+ pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2:
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, FindPlayerCoors().x, FindPlayerCoors().y,
+ pSwerve, pAccel, pBrake, pHandbrake);
+ return;
+ case MISSION_BLOCKPLAYER_FORWARDANDBACK:
+ //SteerAICarBlockingPlayerForwardAndBack(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);
+ return;
default:
+ assert(0);
return;
}
}
-void CCarCtrl::SteerAIBoatWithPhysics(CBoat* pBoat)
+void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CVehicle* pVehicle, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake)
{
- if (pBoat->AutoPilot.m_nCarMission == MISSION_GOTOCOORDS_ASTHECROWSWIMS){
- SteerAIBoatWithPhysicsHeadingForTarget(pBoat,
- pBoat->AutoPilot.m_vecDestinationCoors.x, pBoat->AutoPilot.m_vecDestinationCoors.y,
- &pBoat->m_fSteeringLeftRight, &pBoat->m_fAccelerate, &pBoat->m_fBrake);
- }else if (pBoat->AutoPilot.m_nCarMission == MISSION_NONE){
- pBoat->m_fSteeringLeftRight = 0.0f;
- pBoat->m_fAccelerate = 0.0f;
- pBoat->m_fBrake = 0.0f;
+ CVector2D forward = pVehicle->GetForward();
+ forward.Normalise();
+ float angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
+ float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
+ steerAngle = clamp(steerAngle, -DEFAULT_MAX_STEER_ANGLE, DEFAULT_MAX_STEER_ANGLE);
+#ifdef FIX_BUGS
+ float speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();
+#else
+ float speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed;
+#endif
+ float currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;
+ float speedDiff = speedTarget - currentSpeed;
+ if (speedDiff <= 0.0f) {
+ speedDiff < -5.0f ? *pAccel = -0.2f : *pAccel = -0.1f;
+ steerAngle *= -1;
+ }
+ else if (speedDiff / currentSpeed > 0.25f) {
+ *pAccel = 1.0f;
}
- pBoat->m_fSteerAngle = pBoat->m_fSteeringLeftRight;
- pBoat->m_fGasPedal = pBoat->m_fAccelerate;
- pBoat->m_fBrakePedal = pBoat->m_fBrake;
- pBoat->bIsHandbrakeOn = false;
+ else {
+ *pAccel = 1.0f - (0.25f - speedDiff / currentSpeed) * 4.0f;
+ }
+ *pBrake = 0.0f;
+ *pSwerve = steerAngle;
+}
+
+void CCarCtrl::SteerAIBoatWithPhysicsAttackingPlayer(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
+{
+ float distanceToPlayer = (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude();
+ float projection = Min(distanceToPlayer * 0.05f, 2.0f);
+ CVector2D forward = pVehicle->GetForward();
+ forward.Normalise();
+ CVector2D vecToProjection = FindPlayerCoors() + FindPlayerSpeed() * projection * GAME_SPEED_TO_CARAI_SPEED;
+ float angleToTarget = CGeneral::GetATanOfXY(vecToProjection.x - pVehicle->GetPosition().x, vecToProjection.y - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
+ float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
+#ifdef FIX_BUGS
+ float speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();
+#else
+ float speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed;
+#endif
+ float currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;
+ float speedDiff = speedTarget - currentSpeed;
+ if (speedDiff <= 0.0f) {
+ speedDiff < -5.0f ? *pAccel = -0.2f : *pAccel = -0.1f;
+ }
+ else if (speedDiff / currentSpeed > 0.25f) {
+ *pAccel = 1.0f;
+ }
+ else {
+ *pAccel = 1.0f - (0.25f - speedDiff / currentSpeed) * 4.0f;
+ }
+ *pBrake = 0.0f;
+ *pSwerve = steerAngle;
+ *pHandbrake = false;
+ if (pVehicle->GetModelIndex() == MI_PREDATOR && distanceToPlayer < 40.0f && steerAngle < 0.15f)
+ pVehicle->FireFixedMachineGuns();
}
float CCarCtrl::FindMaxSteerAngle(CVehicle* pVehicle)
@@ -2267,6 +2593,50 @@ float CCarCtrl::FindMaxSteerAngle(CVehicle* pVehicle)
return pVehicle->GetModelIndex() == MI_ENFORCER ? 0.7f : DEFAULT_MAX_STEER_ANGLE;
}
+void CCarCtrl::SteerAIHeliTowardsTargetCoors(CAutomobile* pHeli)
+{
+ if (pHeli->m_aWheelSpeed[1] < 0.22f)
+ pHeli->m_aWheelSpeed[1] += 0.001f;
+ if (pHeli->m_aWheelSpeed[1] < 0.22f)
+ return;
+ CVector2D vecToTarget = pHeli->AutoPilot.m_vecDestinationCoors - pHeli->GetPosition();
+ float distanceToTarget = vecToTarget.Magnitude();
+#ifdef FIX_BUGS
+ float speed = pHeli->AutoPilot.GetCruiseSpeed() * 0.01f;
+#else
+ float speed = pHeli->AutoPilot.m_nCruiseSpeed * 0.01f;
+#endif
+ if (distanceToTarget >= 100.0f)
+ {
+ if (distanceToTarget > 75.0f)
+ speed *= 0.7f;
+ else if (distanceToTarget > 10.0f)
+ speed *= 0.4f;
+ else
+ speed *= 0.2f;
+ }
+ CVector2D vecAdvanceThisFrame = vecToTarget;
+ vecAdvanceThisFrame.Normalise();
+ vecAdvanceThisFrame *= speed;
+ float resistance = Pow(0.997f, CTimer::GetTimeStep());
+ pHeli->m_vecMoveSpeed.x *= resistance;
+ pHeli->m_vecMoveSpeed.y *= resistance;
+ vecAdvanceThisFrame -= pHeli->m_vecMoveSpeed;
+ CVector2D vecSpeedChange = vecAdvanceThisFrame - pHeli->m_vecMoveSpeed;
+ float vecSpeedChangeLength = vecSpeedChange.Magnitude();
+ vecSpeedChange.Normalise();
+ float changeMultiplier = 0.002f * CTimer::GetTimeStep();
+ if (distanceToTarget < 5.0f)
+ changeMultiplier /= 5.0f;
+ if (vecSpeedChangeLength < changeMultiplier)
+ pHeli->AddToMoveSpeed(vecAdvanceThisFrame);
+ else
+ pHeli->AddToMoveSpeed(vecSpeedChange * changeMultiplier);
+ pHeli->SetPosition(pHeli->GetPosition() + CVector(CTimer::GetTimeStep() * pHeli->m_vecMoveSpeed.x, CTimer::GetTimeStep() * pHeli->m_vecMoveSpeed.y, 0.0f));
+ assert(0);
+ // This is not finished yet. Heli fields in CAutomobile required
+}
+
void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
{
CVector2D forward = pVehicle->GetForward();
@@ -2294,18 +2664,12 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
if (PickNextNodeAccordingStrategy(pVehicle)) {
switch (pVehicle->AutoPilot.m_nCarMission){
case MISSION_GOTOCOORDS:
- pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;
- *pSwerve = 0.0f;
- *pAccel = 0.0f;
- *pBrake = 0.0f;
- *pHandbrake = false;
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x,
+ pVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake);
return;
case MISSION_GOTOCOORDS_ACCURATE:
- pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;
- *pSwerve = 0.0f;
- *pAccel = 0.0f;
- *pBrake = 0.0f;
- *pHandbrake = false;
+ SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x,
+ pVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake);
return;
default: break;
}
@@ -2342,6 +2706,7 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
switch (pVehicle->AutoPilot.m_nDrivingStyle) {
case DRIVINGSTYLE_STOP_FOR_CARS:
case DRIVINGSTYLE_SLOW_DOWN_FOR_CARS:
+ case DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS:
speedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle) / pVehicle->AutoPilot.m_nCruiseSpeed;
break;
default:
@@ -2447,6 +2812,7 @@ void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget(CVehicle* pVehicle, floa
pVehicle->AutoPilot.m_nCarMission = (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_CLOSE) ?
MISSION_BLOCKCAR_HANDBRAKESTOP : MISSION_BLOCKPLAYER_HANDBRAKESTOP;
}
+
void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle* pVehicle, float targetX, float targetY, float targetSpeedX, float targetSpeedY, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)
{
*pSwerve = 0.0f;
@@ -2488,26 +2854,6 @@ void CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle* pVehicle,
}
}
-void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CBoat* pBoat, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake)
-{
- CVector2D forward(pBoat->GetForward());
- forward.Normalise();
- CVector2D distanceToTarget = CVector2D(targetX, targetY) - pBoat->GetPosition();
- float angleToTarget = CGeneral::GetATanOfXY(distanceToTarget.x, distanceToTarget.y);
- float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
- float angleDiff = LimitRadianAngle(angleToTarget - angleForward);
- angleDiff = Min(DEFAULT_MAX_STEER_ANGLE, Max(-DEFAULT_MAX_STEER_ANGLE, angleDiff));
- float currentSpeed = pBoat->GetMoveSpeed().Magnitude2D(); // +0.0f for some reason
- float speedDiff = pBoat->AutoPilot.m_nCruiseSpeed - currentSpeed * 60.0f;
- if (speedDiff > 0.0f){
- float accRemaining = speedDiff / pBoat->AutoPilot.m_nCruiseSpeed;
- *pAccel = (accRemaining > 0.25f) ? 1.0f : 1.0f - (0.25f - accRemaining) * 4.0f;
- }else
- *pAccel = (speedDiff < -5.0f) ? -0.2f : -0.1f;
- *pBrake = 0.0f;
- *pSwerve = angleDiff;
-}
-
void
CCarCtrl::RegisterVehicleOfInterest(CVehicle* pVehicle)
{
@@ -2629,6 +2975,8 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
{
+ if (pVehicle->m_nRouteSeed)
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
int nextLink;
CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode];
for (nextLink = 0; nextLink < 12; nextLink++)
@@ -2642,11 +2990,21 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
curLink = 0;
curConnection = ThePaths.m_carPathConnections[pCurNode->firstLink];
}else{
- curConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo;
- while (curConnection == pVehicle->AutoPilot.m_nNextPathNodeInfo){
- curLink = CGeneral::GetRandomNumber() % pCurNode->numLinks;
- curConnection = ThePaths.m_carPathConnections[curLink + pCurNode->firstLink];
+ int closestLink = -1;
+ float md = 999999.9f;
+
+ for (curLink = 0; curLink < pCurNode->numLinks; curLink++) {
+ int node = ThePaths.ConnectedNode(curLink + pCurNode->firstLink);
+ CPathNode* pNode = &ThePaths.m_pathNodes[node];
+ if (node == pVehicle->AutoPilot.m_nNextRouteNode)
+ continue;
+ float dist = CCollision::DistToLine(&pCurNode->GetPosition(), &pNode->GetPosition(), &pVehicle->GetPosition());
+ if (dist < md) {
+ md = dist;
+ closestLink = curLink;
+ }
}
+ curConnection = ThePaths.m_carPathConnections[closestLink + pCurNode->firstLink];
}
pVehicle->AutoPilot.m_nCurrentPathNodeInfo = curConnection;
pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(curLink + pCurNode->firstLink) >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1;
@@ -2656,6 +3014,8 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
{
if (FindPlayerPed()->m_pWanted->m_nWantedLevel > 3)
return;
+ if (CGame::IsInInterior())
+ return;
if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars +
NumLawEnforcerCars + NumRandomCars > MaxNumberOfCarsInUse)
return;
@@ -2711,9 +3071,11 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
if (ThePaths.NewGenerateCarCreationCoors(pPlayerPos.x, pPlayerPos.y, 0.707f, 0.707f,
120.0f, -1.0f, true, &spawnPos, &curNode, &nextNode, &posBetweenNodes, false)){
int16 colliding[2];
- CWorld::FindObjectsKindaColliding(spawnPos, 10.0f, true, colliding, 2, nil, false, true, true, false, false);
- if (colliding[0] == 0)
- created = true;
+ if (!ThePaths.GetNode(curNode)->bWaterPath) {
+ CWorld::FindObjectsKindaColliding(spawnPos, 10.0f, true, colliding, 2, nil, false, true, true, false, false);
+ if (colliding[0] == 0)
+ created = true;
+ }
}
attempts += 1;
}
@@ -2772,18 +3134,24 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
if (remove){
switch (pVehicle->VehicleCreatedBy){
case RANDOM_VEHICLE:
- if (pVehicle->bIsLawEnforcer)
- --NumLawEnforcerCars;
- --NumRandomCars;
+ if (pVehicle->bIsLawEnforcer) {
+ if (--NumLawEnforcerCars < 0)
+ NumLawEnforcerCars = 0;
+ }
+ if (--NumRandomCars < 0)
+ NumRandomCars = 0;
return;
case MISSION_VEHICLE:
- --NumMissionCars;
+ if (--NumMissionCars < 0)
+ NumMissionCars = 0;
return;
case PARKED_VEHICLE:
- --NumParkedCars;
+ if (--NumParkedCars < 0)
+ NumParkedCars = 0;
return;
case PERMANENT_VEHICLE:
- --NumPermanentCars;;
+ if (--NumPermanentCars < 0)
+ NumPermanentCars = 0;
return;
}
}
@@ -2801,7 +3169,7 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
++NumParkedCars;
return;
case PERMANENT_VEHICLE:
- ++NumPermanentCars;;
+ ++NumPermanentCars;
return;
}
}
@@ -2809,12 +3177,30 @@ void CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)
bool CCarCtrl::ThisRoadObjectCouldMove(int16 mi)
{
+#ifdef GTA_BRIDGE
return mi == MI_BRIDGELIFT || mi == MI_BRIDGEROADSEGMENT;
+#else
+ return false;
+#endif
}
bool CCarCtrl::MapCouldMoveInThisArea(float x, float y)
{
+#ifdef GTA_BRIDGE // actually they forgot that in VC...
// bridge moves up and down
return x > -342.0f && x < -219.0f &&
y > -677.0f && y < -580.0f;
+#else
+ return false;
+#endif
+}
+
+float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)
+{
+ switch (type)
+ {
+ case 1: return 1.5f;
+ case 2: return 2.0f;
+ }
+ return 1.0f;
}
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index 457224fb..8138266f 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -12,7 +12,7 @@ class CZoneInfo;
enum{
MAX_CARS_TO_KEEP = 2,
- MAX_CAR_MODELS_IN_ARRAY = 256,
+ MAX_CAR_MODELS_IN_ARRAY = 25,
};
#define LANE_WIDTH 5.0f
@@ -25,14 +25,20 @@ class CCarCtrl
{
public:
enum eCarClass {
- POOR = 0,
+ NORMAL = 0,
+ POOR,
RICH,
EXEC,
WORKER,
- SPECIAL,
BIG,
TAXI,
- TOTAL_CUSTOM_CLASSES,
+ MOPED,
+ MOTORBIKE,
+
+ LEISUREBOAT,
+ WORKERBOAT,
+
+ COPS,
MAFIA,
TRIAD,
DIABLO,
@@ -42,7 +48,14 @@ public:
NINES,
GANG8,
GANG9,
- COPS
+ COPS_BOAT,
+ FIRST_CAR_RATING = NORMAL,
+ FIRST_BOAT_RATING = LEISUREBOAT,
+ FIRST_GANG_CAR_RATING = MAFIA,
+ NUM_CAR_CLASSES = MOTORBIKE - FIRST_CAR_RATING + 1,
+ NUM_BOAT_CLASSES = WORKERBOAT - FIRST_BOAT_RATING + 1,
+ NUM_GANG_CAR_CLASSES = GANG9 - FIRST_GANG_CAR_RATING + 1,
+ TOTAL_CUSTOM_CLASSES = NUM_CAR_CLASSES + NUM_BOAT_CLASSES
};
static void SwitchVehicleToRealPhysics(CVehicle*);
@@ -94,17 +107,29 @@ public:
static float FindSpeedMultiplier(float, float, float, float);
static void SteerAICarWithPhysics(CVehicle*);
static void SteerAICarWithPhysics_OnlyMission(CVehicle*, float*, float*, float*, bool*);
- static void SteerAIBoatWithPhysics(CBoat*);
static float FindMaxSteerAngle(CVehicle*);
static void SteerAICarWithPhysicsFollowPath(CVehicle*, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsHeadingForTarget(CVehicle*, CPhysical*, float, float, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsTryingToBlockTarget(CVehicle*, float, float, float, float, float*, float*, float*, bool*);
static void SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle*, float, float, float, float, float*, float*, float*, bool*);
- static void SteerAIBoatWithPhysicsHeadingForTarget(CBoat*, float, float, float*, float*, float*);
static bool ThisRoadObjectCouldMove(int16);
static void ClearInterestingVehicleList();
static void FindLinksToGoWithTheseNodes(CVehicle*);
static bool GenerateOneEmergencyServicesCar(uint32, CVector);
+ static float FindSpeedMultiplierWithSpeedFromNodes(int8);
+ static int32 ChooseBoatModel(int32);
+ static int32 ChooseBoatRating(CZoneInfo* pZoneInfo);
+ static int32 ChooseCarRating(CZoneInfo* pZoneInfo);
+ static void AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq);
+ static void RemoveFromLoadedVehicleArray(int32 mi, int32 rating);
+ static int32 ChooseCarModelToLoad(int32 rating);
+ static bool BoatWithTallMast(int32 mi);
+ static void RemoveCarsIfThePoolGetsFull(void);
+ static void SteerAIBoatWithPhysicsHeadingForTarget(CVehicle*, float, float, float*, float*, float*);
+ static void SteerAIHeliTowardsTargetCoors(CAutomobile*);
+ static void SteerAIPlaneTowardsTargetCoors(CAutomobile*);
+ static void SteerAIBoatWithPhysicsAttackingPlayer(CVehicle*, float*, float*, float*, bool*);
+ static void SteerAICarBlockingPlayerForwardAndBack(CVehicle*, float*, float*, float*, bool*);
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{
@@ -136,8 +161,14 @@ public:
static uint32 LastTimeFireTruckCreated;
static uint32 LastTimeAmbulanceCreated;
static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
- static int32 NextCarOfRating[TOTAL_CUSTOM_CLASSES];
static int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+
+ static int32 MiamiViceCycle;
+ static uint32 LastTimeMiamiViceGenerated;
+ static int32 NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
+ static int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
+ static int32 CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+ static int32 LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
};
extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; \ No newline at end of file
diff --git a/src/control/Curves.cpp b/src/control/Curves.cpp
index 0a01a7aa..31a2767a 100644
--- a/src/control/Curves.cpp
+++ b/src/control/Curves.cpp
@@ -11,7 +11,7 @@ float CCurves::CalcSpeedScaleFactor(CVector* pPoint1, CVector* pPoint2, float di
if (dp > 0.9f)
return distance + Abs((pPoint1->x * dir1Y - pPoint1->y * dir1X) - (pPoint2->x * dir1Y - pPoint2->y * dir1X));
else
- return ((1.0f - dp) * 0.2f + 1.0f) * distance;
+ return ((1.0f - dp) * 0.25f + 1.0f) * distance;
}
void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVector* pDir2, float between, int32 timeOnCurve, CVector* pOutPos, CVector* pOutDir)
@@ -19,7 +19,21 @@ void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVe
float actualFactor = CalcSpeedScaleFactor(pPos1, pPos2, pDir1->x, pDir1->y, pDir2->x, pDir2->y);
CVector2D dir1 = *pDir1 * actualFactor;
CVector2D dir2 = *pDir2 * actualFactor;
- float curveCoef = 0.5f - 0.5f * Cos(3.1415f * between);
+ float t1 = Abs(DotProduct2D(*pPos1 - *pPos2, *pDir1));
+ float t2 = Abs(DotProduct2D(*pPos2 - *pPos1, *pDir2));
+ float curveCoef;
+ if (t1 > t2) {
+ if (between < (t1 - t2) / (t1 + t2))
+ curveCoef = 0.0f;
+ else
+ curveCoef = 0.5f - 0.5f * Cos(3.1415f * (t1 + t2) / (2 * t2) * (between - (t1 - t2) / (t1 + t2)));
+ }
+ else {
+ if (2 * t1 / (t1 + t2) < between)
+ curveCoef = 1.0f;
+ else
+ curveCoef = 0.5f - 0.5f * Cos(3.1415f * between * (t1 + t2) / (2 * t1));
+ }
*pOutPos = CVector(
(pPos1->x + between * dir1.x) * (1.0f - curveCoef) + (pPos2->x - (1 - between) * dir2.x) * curveCoef,
(pPos1->y + between * dir1.y) * (1.0f - curveCoef) + (pPos2->y - (1 - between) * dir2.y) * curveCoef,
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index 5fc44974..82003561 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -39,8 +39,8 @@
#define CRUSHER_CRANE_SPEED (0.005f)
// Prices
-#define BOMB_PRICE (1000)
-#define RESPRAY_PRICE (1000)
+#define BOMB_PRICE (500)
+#define RESPRAY_PRICE (100)
// Distances
#define DISTANCE_TO_CALL_OFF_CHASE (10.0f)
@@ -50,10 +50,10 @@
#define DISTANCE_TO_CLOSE_MISSION_GARAGE (30.0f)
#define DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE (25.0f)
#define DISTANCE_TO_CLOSE_COLLECTCARS_GARAGE (40.0f)
-#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT (2.2f)
+#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT (3.2f)
#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR (15.0f)
#define DISTANCE_TO_FORCE_CLOSE_HIDEOUT_GARAGE (70.0f)
-#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT (1.7f)
+#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT (2.8f)
#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_IN_CAR (10.0f)
#define DISTANCE_TO_SHOW_HIDEOUT_MESSAGE (5.0f)
@@ -68,7 +68,7 @@
// Respray stuff
#define FREE_RESPRAY_HEALTH_THRESHOLD (970.0f)
#define NUM_PARTICLES_IN_RESPRAY (200)
-#define RESPRAY_CENTERING_COEFFICIENT (0.75f)
+#define RESPRAY_CENTERING_COEFFICIENT (0.4f)
// Bomb stuff
#define KGS_OF_EXPLOSIVES_IN_BOMB (10)
@@ -81,8 +81,8 @@
// Collect cars stuff
#define MAX_SPEED_TO_SHOW_COLLECTED_MESSAGE (0.03f)
-#define IMPORT_REWARD (1000)
-#define IMPORT_ALLCARS_REWARD (200000)
+#define IMPORT_REWARD (500)
+#define IMPORT_ALLCARS_REWARD (20500)
// Crusher stuff
#define CRUSHER_VEHICLE_TEST_SPAN (8)
@@ -91,26 +91,23 @@
#define CRUSHER_REWARD_COEFFICIENT (1.0f/500000)
// Hideout stuff
-#define MAX_STORED_CARS_IN_INDUSTRIAL (1)
-#define MAX_STORED_CARS_IN_COMMERCIAL (NUM_GARAGE_STORED_CARS)
-#define MAX_STORED_CARS_IN_SUBURBAN (NUM_GARAGE_STORED_CARS)
-#define LIMIT_CARS_IN_INDUSTRIAL (1)
-#define LIMIT_CARS_IN_COMMERCIAL (2)
-#define LIMIT_CARS_IN_SUBURBAN (3)
#define HIDEOUT_DOOR_SPEED_COEFFICIENT (1.7f)
#define TIME_BETWEEN_HIDEOUT_MESSAGES (18000)
// Camera stuff
-#define MARGIN_FOR_CAMERA_COLLECTCARS (1.3f)
-#define MARGIN_FOR_CAMERA_DEFAULT (4.0f)
+#define MARGIN_FOR_CAMERA_COLLECTCARS (0.5f)
+#define MARGIN_FOR_CAMERA_DEFAULT (0.5f)
const int32 gaCarsToCollectInCraigsGarages[TOTAL_COLLECTCARS_GARAGES][TOTAL_COLLECTCARS_CARS] =
{
- { MI_SECURICA, MI_MOONBEAM, MI_COACH, MI_FLATBED, MI_LINERUN, MI_TRASH, MI_PATRIOT, MI_MRWHOOP, MI_BLISTA, MI_MULE, MI_YANKEE, MI_BOBCAT, MI_DODO, MI_BUS, MI_RUMPO, MI_PONY },
- { MI_SENTINEL, MI_CHEETAH, MI_BANSHEE, MI_IDAHO, MI_INFERNUS, MI_TAXI, MI_KURUMA, MI_STRETCH, MI_PEREN, MI_STINGER, MI_MANANA, MI_LANDSTAL, MI_STALLION, MI_BFINJECT, MI_CABBIE, MI_ESPERANT },
- { MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_LANDSTAL, MI_CHEETAH, MI_TAXI, MI_ESPERANT, MI_SENTINEL, MI_IDAHO }
+ { MI_LANDSTAL, MI_IDAHO, MI_ESPERANT, MI_STALLION, MI_RANCHER, MI_BLISTAC },
+ { MI_SABRE, MI_VIRGO, MI_SENTINEL, MI_STRETCH, MI_WASHING, MI_ADMIRAL },
+ { MI_CHEETAH, MI_INFERNUS, MI_BANSHEE, MI_PHEONIX, MI_COMET, MI_STINGER },
+ { MI_VOODOO, MI_CUBAN, MI_CADDY, MI_BAGGAGE, MI_MRWHOOP, MI_PIZZABOY }
};
+const int32 gaCarsToCollectIn60Seconds[] = { MI_CHEETAH, MI_TAXI, MI_ESPERANT, MI_SENTINEL, MI_IDAHO }; // what is this?
+
int32 CGarages::BankVansCollected;
bool CGarages::BombsAreFree;
bool CGarages::RespraysAreFree;
@@ -126,9 +123,7 @@ uint32 CGarages::MessageEndTime;
uint32 CGarages::NumGarages;
bool CGarages::PlayerInGarage;
int32 CGarages::PoliceCarsCollected;
-CStoredCar CGarages::aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
-CStoredCar CGarages::aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
-CStoredCar CGarages::aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
+CStoredCar CGarages::aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][CGarages::MAX_NUM_CARS_IN_HIDEOUT_GARAGE];
int32 CGarages::AudioEntity = AEHANDLE_NONE;
CGarage CGarages::aGarages[NUM_GARAGES];
bool CGarages::bCamShouldBeOutisde;
@@ -147,22 +142,15 @@ void CGarages::Init(void)
for (int i = 0; i < TOTAL_COLLECTCARS_GARAGES; i++)
CarTypesCollected[i] = 0;
LastTimeHelpMessage = 0;
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse1[i].Init();
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse2[i].Init();
- for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)
- aCarsInSafeHouse3[i].Init();
+ for (int i = 0; i < TOTAL_HIDEOUT_GARAGES; i++) {
+ for (int j = 0; j < MAX_NUM_CARS_IN_HIDEOUT_GARAGE; j++)
+ aCarsInSafeHouses[i][j].Init();
+ }
AudioEntity = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1);
if (AudioEntity >= 0)
DMAudio.SetEntityStatus(AudioEntity, 1);
- AddOne(
- CRUSHER_GARAGE_X1, CRUSHER_GARAGE_Y1, CRUSHER_GARAGE_Z1,
- CRUSHER_GARAGE_X2, CRUSHER_GARAGE_Y2, CRUSHER_GARAGE_Z2,
- GARAGE_CRUSHER, 0);
}
-#ifndef PS2
void CGarages::Shutdown(void)
{
NumGarages = 0;
@@ -171,7 +159,6 @@ void CGarages::Shutdown(void)
DMAudio.DestroyEntity(AudioEntity);
AudioEntity = AEHANDLE_NONE;
}
-#endif
void CGarages::Update(void)
{
@@ -199,19 +186,27 @@ void CGarages::Update(void)
aGarages[GarageToBeTidied].TidyUpGarage();
}
-int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z2, eGarageType type, int32 targetId)
+int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, eGarageType type, int32 targetId)
{
if (NumGarages >= NUM_GARAGES) {
assert(0);
return NumGarages++;
}
CGarage* pGarage = &aGarages[NumGarages];
- pGarage->m_fX1 = Min(X1, X2);
- pGarage->m_fX2 = Max(X1, X2);
- pGarage->m_fY1 = Min(Y1, Y2);
- pGarage->m_fY2 = Max(Y1, Y2);
- pGarage->m_fZ1 = Min(Z1, Z2);
- pGarage->m_fZ2 = Max(Z1, Z2);
+ pGarage->m_fInfX = Min(Min(Min(X1, X2), X3), X2 + X3 - X1);
+ pGarage->m_fSupX = Max(Max(X1, X2), X3);
+ pGarage->m_fInfY = Min(Min(Min(Y1, Y2), Y3), Y2 + Y3 - Y1);
+ pGarage->m_fSupY = Max(Max(Y1, Y2), Y3);
+ pGarage->m_vecCorner1 = CVector(X1, Y1, Z1);
+ pGarage->m_fInfZ = Z1;
+ pGarage->m_vDir1 = CVector2D(X2 - X1, Y2 - Y1);
+ pGarage->m_vDir2 = CVector2D(X3 - X1, Y3 - Y1);
+ pGarage->m_fSupZ = Z2;
+ pGarage->m_nMaxStoredCars = NUM_GARAGE_STORED_CARS;
+ pGarage->m_fDir1Len = pGarage->m_vDir1.Magnitude();
+ pGarage->m_fDir2Len = pGarage->m_vDir2.Magnitude();
+ pGarage->m_vDir1 /= pGarage->m_fDir1Len;
+ pGarage->m_vDir2 /= pGarage->m_fDir2Len;
pGarage->m_pDoor1 = nil;
pGarage->m_pDoor2 = nil;
pGarage->m_fDoor1Z = Z1;
@@ -258,6 +253,17 @@ int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z
case GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:
case GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
+ case GARAGE_COLLECTCARS_4:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
pGarage->m_eGarageState = GS_FULLYCLOSED;
pGarage->m_fDoorPos = 0.0f;
break;
@@ -311,10 +317,10 @@ void CGarage::Update()
TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = this;
if (pVehicle->GetModelIndex() == MI_MRWHOOP) {
if (pVehicle->IsWithinArea(
- m_fX1 - DISTANCE_FOR_MRWHOOP_HACK,
- m_fY1 + DISTANCE_FOR_MRWHOOP_HACK,
- m_fX2 - DISTANCE_FOR_MRWHOOP_HACK,
- m_fY2 + DISTANCE_FOR_MRWHOOP_HACK)) {
+ m_fInfX - DISTANCE_FOR_MRWHOOP_HACK,
+ m_fInfY - DISTANCE_FOR_MRWHOOP_HACK,
+ m_fSupX + DISTANCE_FOR_MRWHOOP_HACK,
+ m_fSupY + DISTANCE_FOR_MRWHOOP_HACK)) {
TheCamera.pToGarageWeAreIn = this;
CGarages::bCamShouldBeOutisde = true;
}
@@ -332,7 +338,7 @@ void CGarage::Update()
case GARAGE_RESPRAY:
switch (m_eGarageState) {
case GS_OPENED:
- if (IsStaticPlayerCarEntirelyInside() && !IsAnyOtherCarTouchingGarage(FindPlayerVehicle())) {
+ if (IsStaticPlayerCarEntirelyInside()) {
if (CGarages::IsCarSprayable(FindPlayerVehicle())) {
if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= RESPRAY_PRICE || CGarages::RespraysAreFree) {
m_eGarageState = GS_CLOSING;
@@ -354,13 +360,15 @@ void CGarage::Update()
if (FindPlayerVehicle()) {
if (CalcDistToGarageRectangleSquared(FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
}
break;
case GS_CLOSING:
+ if (FindPlayerVehicle())
+ ThrowCarsNearDoorOutOfGarage(FindPlayerVehicle());
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -376,19 +384,20 @@ void CGarage::Update()
#endif
((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
break;
case GS_FULLYCLOSED:
if (CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction) {
m_eGarageState = GS_OPENING;
DMAudio.PlayFrontEndSound(SOUND_GARAGE_OPENING, 1);
bool bTakeMoney = false;
- if (FindPlayerPed()->m_pWanted->m_nWantedLevel != 0)
+ if (FindPlayerPed()->m_pWanted->m_nWantedLevel != 0) {
bTakeMoney = true;
- FindPlayerPed()->m_pWanted->Reset();
+ FindPlayerPed()->m_pWanted->Suspend();
+ }
CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
#ifdef FIX_BUGS
@@ -396,18 +405,29 @@ void CGarage::Update()
#else
bool bChangedColour;
#endif
- if (FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) {
+ if (FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {
if (FindPlayerVehicle()->m_fHealth < FREE_RESPRAY_HEALTH_THRESHOLD)
bTakeMoney = true;
FindPlayerVehicle()->m_fHealth = 1000.0f;
- ((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
- ((CAutomobile*)(FindPlayerVehicle()))->Fix();
+ if (FindPlayerVehicle()->IsCar()) {
+ ((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;
+ ((CAutomobile*)(FindPlayerVehicle()))->Fix();
+ }
+ else {
+ // TODO(MIAMI): Bike Fix
+ }
+ FindPlayerVehicle()->m_nDoorLock = CARLOCK_UNLOCKED;
+ ++CStats::Sprayings;
if (FindPlayerVehicle()->GetUp().z < 0.0f) {
FindPlayerVehicle()->GetUp() = -FindPlayerVehicle()->GetUp();
FindPlayerVehicle()->GetRight() = -FindPlayerVehicle()->GetRight();
}
bChangedColour = false;
+#ifdef FIX_BUGS
+ if (!FindPlayerVehicle()->IsCar() || !((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
+#else
if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
+#endif
uint8 colour1, colour2;
uint16 attempt;
FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
@@ -422,16 +442,9 @@ void CGarage::Update()
if (bChangedColour) {
for (int i = 0; i < NUM_PARTICLES_IN_RESPRAY; i++) {
CVector pos;
-#ifdef FIX_BUGS
- pos.x = CGeneral::GetRandomNumberInRange(m_fX1 + 0.5f, m_fX2 - 0.5f);
- pos.y = CGeneral::GetRandomNumberInRange(m_fY1 + 0.5f, m_fY2 - 0.5f);
+ pos.x = CGeneral::GetRandomNumberInRange(m_fInfX + 0.5f, m_fSupX - 0.5f);
+ pos.y = CGeneral::GetRandomNumberInRange(m_fInfY + 0.5f, m_fSupY - 0.5f);
pos.z = CGeneral::GetRandomNumberInRange(m_fDoor1Z - 3.0f, m_fDoor1Z + 1.0f);
-#else
- // wtf is this
- pos.x = m_fX1 + 0.5f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * (m_fX2 - m_fX1 - 1.0f);
- pos.y = m_fY1 + 0.5f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * (m_fY2 - m_fY1 - 1.0f);
- pos.z = m_fDoor1Z - 3.0f + (uint8)(CGeneral::GetRandomNumber()) / 256.0f * 4.0f;
-#endif
CParticle::AddParticle(PARTICLE_GARAGEPAINT_SPRAY, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, CVehicleModelInfo::ms_vehicleColourTable[colour1]);
}
}
@@ -439,8 +452,10 @@ void CGarage::Update()
CenterCarInGarage(FindPlayerVehicle());
}
if (bTakeMoney) {
- if (!CGarages::RespraysAreFree)
+ if (!CGarages::RespraysAreFree) {
CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - RESPRAY_PRICE);
+ CStats::AutoPaintingBudget += RESPRAY_PRICE;
+ }
CGarages::TriggerMessage("GA_2", -1, 4000, -1); // New engine and paint job. The cops won't recognize you!
}
else if (bChangedColour) {
@@ -452,10 +467,10 @@ void CGarage::Update()
m_bResprayHappened = true;
}
CWorld::CallOffChaseForArea(
- m_fX1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fY1 - DISTANCE_TO_CALL_OFF_CHASE,
- m_fX2 + DISTANCE_TO_CALL_OFF_CHASE,
- m_fY2 + DISTANCE_TO_CALL_OFF_CHASE);
+ m_fInfX - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fInfY - DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupX + DISTANCE_TO_CALL_OFF_CHASE,
+ m_fSupY + DISTANCE_TO_CALL_OFF_CHASE);
break;
case GS_OPENING:
m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
@@ -480,12 +495,8 @@ void CGarage::Update()
case GARAGE_BOMBSHOP3:
switch (m_eGarageState) {
case GS_OPENED:
- if (IsStaticPlayerCarEntirelyInside() && !IsAnyOtherCarTouchingGarage(FindPlayerVehicle())) {
-#ifdef FIX_BUGS // FindPlayerVehicle() can never be NULL here because IsStaticPlayerCarEntirelyInside() is true, and there is no IsCar() check
- if (FindPlayerVehicle()->IsCar() && ((CAutomobile*)FindPlayerVehicle())->m_bombType) {
-#else
- if (!FindPlayerVehicle() || ((CAutomobile*)FindPlayerVehicle())->m_bombType) {
-#endif
+ if (IsStaticPlayerCarEntirelyInside()) {
+ if (!FindPlayerVehicle() || FindPlayerVehicle()->m_bombType) {
CGarages::TriggerMessage("GA_5", -1, 4000, -1); //"Your car is already fitted with a bomb"
m_eGarageState = GS_OPENEDCONTAINSCAR;
DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB_ALREADY_SET, 1);
@@ -503,6 +514,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (FindPlayerVehicle())
+ ThrowCarsNearDoorOutOfGarage(FindPlayerVehicle());
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -510,62 +523,69 @@ void CGarage::Update()
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
}
UpdateDoorsHeight();
+ if (m_eGarageType == GARAGE_BOMBSHOP3)
+ CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);
break;
case GS_FULLYCLOSED:
if (CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction) {
- switch (m_eGarageType) {
- case GARAGE_BOMBSHOP1: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB1_SET, 1); break;
- case GARAGE_BOMBSHOP2: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB2_SET, 1); break;
- case GARAGE_BOMBSHOP3: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB3_SET, 1); break;
+ if (m_eGarageType != GARAGE_BOMBSHOP3 || CStreaming::HasModelLoaded(MI_BOMB)) {
+ switch (m_eGarageType) {
+ case GARAGE_BOMBSHOP1: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB1_SET, 1); break;
+ case GARAGE_BOMBSHOP2: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB2_SET, 1); break;
+ case GARAGE_BOMBSHOP3: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB3_SET, 1); break;
default: break;
- }
- m_eGarageState = GS_OPENING;
- if (!CGarages::BombsAreFree)
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE);
- if (FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) {
- ((CAutomobile*)(FindPlayerVehicle()))->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);
- ((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();
- if (m_eGarageType == GARAGE_BOMBSHOP3)
- CGarages::GivePlayerDetonator();
- CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
- }
+ }
+ m_eGarageState = GS_OPENING;
+ if (!CGarages::BombsAreFree)
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE);
+ if (FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {
+ FindPlayerVehicle()->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);
+ FindPlayerVehicle()->m_pBombRigger = FindPlayerPed();
+ if (m_eGarageType == GARAGE_BOMBSHOP3)
+ CGarages::GivePlayerDetonator();
+ CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
+ }
#ifdef DETECT_PAD_INPUT_SWITCH
- int16 Mode = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;
+ int16 Mode = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;
#else
- int16 Mode = CPad::GetPad(0)->Mode;
+ int16 Mode = CPad::GetPad(0)->Mode;
#endif
- switch (m_eGarageType) {
- case GARAGE_BOMBSHOP1:
- switch (Mode) {
- case 0:
- case 1:
- case 2:
- CHud::SetHelpMessage(TheText.Get("GA_6"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
- break;
- case 3:
- CHud::SetHelpMessage(TheText.Get("GA_6B"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ switch (m_eGarageType) {
+ case GARAGE_BOMBSHOP1:
+ switch (Mode) {
+ case 0:
+ case 1:
+ case 2:
+ CHud::SetHelpMessage(TheText.Get("GA_6"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ break;
+ case 3:
+ CHud::SetHelpMessage(TheText.Get("GA_6B"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.
+ break;
+ }
break;
- }
- break;
- case GARAGE_BOMBSHOP2:
- switch (Mode) {
- case 0:
- case 1:
- case 2:
- CHud::SetHelpMessage(TheText.Get("GA_7"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ case GARAGE_BOMBSHOP2:
+ switch (Mode) {
+ case 0:
+ case 1:
+ case 2:
+ CHud::SetHelpMessage(TheText.Get("GA_7"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ break;
+ case 3:
+ CHud::SetHelpMessage(TheText.Get("GA_7B"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ break;
+ }
break;
- case 3:
- CHud::SetHelpMessage(TheText.Get("GA_7B"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!
+ case GARAGE_BOMBSHOP3:
+ CHud::SetHelpMessage(TheText.Get("GA_8"), false); // Use the detonator to activate the bomb.
break;
- }
- break;
- case GARAGE_BOMBSHOP3:
- CHud::SetHelpMessage(TheText.Get("GA_8"), false); // Use the detonator to activate the bomb.
- break;
default: break;
+ }
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
+ FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
+ }
+ else {
+ CStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);
}
- CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
}
break;
case GS_OPENING:
@@ -604,6 +624,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
@@ -648,92 +670,10 @@ void CGarage::Update()
}
break;
case GARAGE_COLLECTSPECIFICCARS:
- switch (m_eGarageState) {
- case GS_OPENED:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- m_pTarget = FindPlayerVehicle();
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- if (!FindPlayerVehicle()) {
- if (m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && !IsAnyOtherCarTouchingGarage(m_pTarget)) {
- if (IsEntityEntirelyOutside(FindPlayerPed(), 2.0f)) {
- CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;
- m_eGarageState = GS_CLOSING;
- }
- }
- else if (Abs(FindPlayerCoors().x - GetGarageCenterX()) > DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE ||
- Abs(FindPlayerCoors().y - GetGarageCenterY()) > DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE) {
- m_eGarageState = GS_CLOSING;
- m_pTarget = nil;
- }
- }
- break;
- case GS_CLOSING:
- m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
- if (m_fDoorPos == 0.0f) {
- m_eGarageState = GS_FULLYCLOSED;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
- if (m_pTarget) {
- DestroyVehicleAndDriverAndPassengers(m_pTarget);
- m_pTarget = nil;
- CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
- FindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;
- int16 reward;
- switch (m_nTargetModelIndex) {
- case MI_POLICE:
- reward = REWARD_FOR_FIRST_POLICE_CAR * (MAX_POLICE_CARS_TO_COLLECT - CGarages::PoliceCarsCollected++) / MAX_POLICE_CARS_TO_COLLECT;
- break;
- case MI_SECURICA:
- reward = REWARD_FOR_FIRST_BANK_VAN * (MAX_BANK_VANS_TO_COLLECT - CGarages::BankVansCollected++) / MAX_BANK_VANS_TO_COLLECT;
- break;
-#ifdef FIX_BUGS // not possible though
- default:
- reward = 0;
- break;
-#endif
- }
- if (reward > 0) {
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += reward;
- CGarages::TriggerMessage("GA_10", reward, 4000, -1); // Nice one. Here's your $~1~
- DMAudio.PlayFrontEndSound(SOUND_GARAGE_VEHICLE_ACCEPTED, 1);
- }
- else {
- CGarages::TriggerMessage("GA_11", -1, 4000, -1); // We got these wheels already. It's worthless to us!
- DMAudio.PlayFrontEndSound(SOUND_GARAGE_VEHICLE_DECLINED, 1);
- }
- }
- }
- UpdateDoorsHeight();
- break;
- case GS_FULLYCLOSED:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- if (CalcDistToGarageRectangleSquared(FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))
- m_eGarageState = GS_OPENING;
- }
- break;
- case GS_OPENING:
- if (FindPlayerVehicle() && m_nTargetModelIndex == FindPlayerVehicle()->GetModelIndex()) {
- m_pTarget = FindPlayerVehicle();
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
- if (m_fDoorPos == m_fDoorHeight) {
- m_eGarageState = GS_OPENED;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f);
- }
- UpdateDoorsHeight();
- break;
- //case GS_OPENEDCONTAINSCAR:
- //case GS_CLOSEDCONTAINSCAR:
- //case GS_AFTERDROPOFF:
- default:
- break;
- }
- break;
case GARAGE_COLLECTCARS_1:
case GARAGE_COLLECTCARS_2:
case GARAGE_COLLECTCARS_3:
+ case GARAGE_COLLECTCARS_4:
switch (m_eGarageState) {
case GS_OPENED:
if (FindPlayerVehicle() && DoesCraigNeedThisCar(FindPlayerVehicle()->GetModelIndex())) {
@@ -766,6 +706,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -853,75 +795,6 @@ void CGarage::Update()
}
break;
case GARAGE_CRUSHER:
- switch (m_eGarageState) {
- case GS_OPENED:
- {
- int i = CPools::GetVehiclePool()->GetSize() * (CTimer::GetFrameCounter() % CRUSHER_VEHICLE_TEST_SPAN) / CRUSHER_VEHICLE_TEST_SPAN;
- int end = CPools::GetVehiclePool()->GetSize() * (CTimer::GetFrameCounter() % CRUSHER_VEHICLE_TEST_SPAN + 1) / CRUSHER_VEHICLE_TEST_SPAN;
- for (; i < end; i++) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle)
- continue;
- if (pVehicle->IsCar() && IsEntityEntirelyInside3D(pVehicle, 0.0f)) {
- m_eGarageState = GS_CLOSING;
- m_pTarget = pVehicle;
- m_pTarget->RegisterReference((CEntity**)&m_pTarget);
- }
- }
- break;
- }
- case GS_CLOSING:
- if (m_pTarget) {
- m_fDoorPos = Max(0.0f, m_fDoorPos - CRUSHER_CRANE_SPEED * CTimer::GetTimeStep());
- if (m_fDoorPos < TWOPI / 5) {
- m_pTarget->bUsesCollision = false;
- m_pTarget->bAffectedByGravity = false;
- m_pTarget->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- }
- else {
- m_pTarget->SetMoveSpeed(m_pTarget->GetMoveSpeed() * Pow(0.8f, CTimer::GetTimeStep()));
- }
- if (m_fDoorPos == 0.0f) {
- CGarages::CrushedCarId = CPools::GetVehiclePool()->GetIndex(m_pTarget);
- float reward = Min(CRUSHER_MAX_REWARD, CRUSHER_MIN_REWARD + m_pTarget->pHandling->nMonetaryValue * m_pTarget->m_fHealth * CRUSHER_REWARD_COEFFICIENT);
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += reward;
- DestroyVehicleAndDriverAndPassengers(m_pTarget);
- ++CStats::CarsCrushed;
- m_pTarget = nil;
- m_eGarageState = GS_AFTERDROPOFF;
- m_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_CRUSH_CAR;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
- }
- }
- else
- m_eGarageState = GS_OPENING;
- UpdateCrusherAngle();
- break;
- case GS_AFTERDROPOFF:
- if (CTimer::GetTimeInMilliseconds() <= m_nTimeToStartAction) {
- UpdateCrusherShake((myrand() & 0xFF - 128) * 0.0002f, (myrand() & 0xFF - 128) * 0.0002f);
- }
- else {
- UpdateCrusherShake(0.0f, 0.0f);
- m_eGarageState = GS_OPENING;
- }
- break;
- case GS_OPENING:
- m_fDoorPos = Min(HALFPI, m_fDoorPos + CTimer::GetTimeStep() * CRUSHER_CRANE_SPEED);
- if (m_fDoorPos == HALFPI) {
- m_eGarageState = GS_OPENED;
- DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f);
- }
- UpdateCrusherAngle();
- break;
- //case GS_FULLYCLOSED:
- //case GS_CLOSEDCONTAINSCAR:
- //case GS_OPENEDCONTAINSCAR:
- default:
- break;
- }
- if (!FindPlayerVehicle() && (CTimer::GetFrameCounter() & 0x1F) == 0x17 && IsEntityEntirelyInside(FindPlayerPed()))
- FindPlayerPed()->InflictDamage(nil, WEAPONTYPE_RAMMEDBYCAR, 300.0f, PEDPIECE_TORSO, 0);
break;
case GARAGE_MISSION_KEEPCAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
@@ -940,6 +813,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
@@ -1035,6 +910,15 @@ void CGarage::Update()
case GARAGE_HIDEOUT_ONE:
case GARAGE_HIDEOUT_TWO:
case GARAGE_HIDEOUT_THREE:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
switch (m_eGarageState) {
case GS_OPENED:
{
@@ -1047,7 +931,7 @@ void CGarage::Update()
m_eGarageState = GS_CLOSING;
else if (FindPlayerVehicle() &&
CountCarsWithCenterPointWithinGarage(FindPlayerVehicle()) >=
- CGarages::FindMaxNumStoredCarsForGarage(m_eGarageType)) {
+ FindMaxNumStoredCarsForGarage()) {
m_eGarageState = GS_CLOSING;
}
else if (distance > SQR(DISTANCE_TO_FORCE_CLOSE_HIDEOUT_GARAGE)) {
@@ -1063,12 +947,7 @@ void CGarage::Update()
else if (m_fDoorPos == 0.0f) {
DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
m_eGarageState = GS_FULLYCLOSED;
- switch (m_eGarageType) {
- case GARAGE_HIDEOUT_ONE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse1, MAX_STORED_CARS_IN_INDUSTRIAL); break;
- case GARAGE_HIDEOUT_TWO: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse2, MAX_STORED_CARS_IN_COMMERCIAL); break;
- case GARAGE_HIDEOUT_THREE: StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouse3, MAX_STORED_CARS_IN_SUBURBAN); break;
- default: break;
- }
+ StoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouses[CGarages::FindSafeHouseIndexForGarageType(m_eGarageType)], NUM_GARAGE_STORED_CARS);
}
UpdateDoorsHeight();
break;
@@ -1077,30 +956,19 @@ void CGarage::Update()
float distance = CalcDistToGarageRectangleSquared(FindPlayerCoors().x, FindPlayerCoors().y);
if (distance < SQR(DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT) ||
distance < SQR(DISTANCE_TO_OPEN_HIDEOUT_GARAGE_IN_CAR) && FindPlayerVehicle()) {
- if (FindPlayerVehicle() && CGarages::CountCarsInHideoutGarage(m_eGarageType) >= CGarages::FindMaxNumStoredCarsForGarage(m_eGarageType)) {
+ if (FindPlayerVehicle() && CGarages::CountCarsInHideoutGarage(m_eGarageType) >= FindMaxNumStoredCarsForGarage()) {
if (m_pDoor1) {
if (((CVector2D)FindPlayerVehicle()->GetPosition() - (CVector2D)m_pDoor1->GetPosition()).MagnitudeSqr() < SQR(DISTANCE_TO_SHOW_HIDEOUT_MESSAGE) &&
CTimer::GetTimeInMilliseconds() - CGarages::LastTimeHelpMessage > TIME_BETWEEN_HIDEOUT_MESSAGES) {
- CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage.
- CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds();
+ if (FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_HELI && FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_PLANE) {
+ CHud::SetHelpMessage(TheText.Get("GA_21"), false); // You cannot store any more cars in this garage.
+ CGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds();
+ }
}
}
}
- else {
-#ifdef FIX_BUGS
- bool bCreatedAllCars = false;
-#else
- bool bCreatedAllCars;
-#endif
- switch (m_eGarageType) {
- case GARAGE_HIDEOUT_ONE: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse1); break;
- case GARAGE_HIDEOUT_TWO: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse2); break;
- case GARAGE_HIDEOUT_THREE: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse3); break;
- default: break;
- }
- if (bCreatedAllCars)
- m_eGarageState = GS_OPENING;
- }
+ else if (RestoreCarsForThisHideout(CGarages::aCarsInSafeHouses[CGarages::FindSafeHouseIndexForGarageType(m_eGarageType)]))
+ m_eGarageState = GS_OPENING;
}
break;
}
@@ -1130,6 +998,8 @@ void CGarage::Update()
}
break;
case GS_CLOSING:
+ if (m_pTarget)
+ ThrowCarsNearDoorOutOfGarage(m_pTarget);
m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
if (m_fDoorPos == 0.0f) {
m_eGarageState = GS_FULLYCLOSED;
@@ -1162,11 +1032,64 @@ void CGarage::Update()
break;
//case GARAGE_COLLECTORSITEMS:
//case GARAGE_60SECONDS:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ switch (m_eGarageState) {
+ case GS_OPENED:
+ if (m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && !IsAnyCarBlockingDoor() && IsPlayerOutsideGarage()) {
+ CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);
+ m_eGarageState = GS_CLOSING;
+ m_bClosingWithoutTargetCar = false;
+ }
+ case GS_CLOSING:
+ m_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());
+ if (m_fDoorPos == 0.0f) {
+ m_eGarageState = GS_FULLYCLOSED;
+ DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_CLOSED, 1.0f);
+ CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);
+ }
+ case GS_FULLYCLOSED:
+ break;
+ case GS_OPENING:
+ m_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());
+ if (m_fDoorPos == m_fDoorHeight) {
+ m_eGarageState = GS_OPENED;
+ DMAudio.PlayOneShot(CGarages::AudioEntity, SOUND_GARAGE_DOOR_OPENED, 1.0f);
+ }
+ UpdateDoorsHeight();
+ break;
+ //case GS_OPENEDCONTAINSCAR:
+ //case GS_CLOSEDCONTAINSCAR:
+ //case GS_AFTERDROPOFF:
+ default:
+ break;
+ }
default:
break;
}
}
+void CGarage::ThrowCarsNearDoorOutOfGarage(CVehicle* pException)
+{
+ uint32 i = CPools::GetVehiclePool()->GetSize();
+ while (i--) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (!pVehicle || pVehicle == pException)
+ continue;
+ if (!IsEntityTouching3D(pVehicle))
+ continue;
+ CColModel* pColModel = pVehicle->GetColModel();
+ for (int i = 0; i < pColModel->numSpheres; i++) {
+ CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
+ float radius = pColModel->spheres[i].radius;
+ if (!IsPointInsideGarage(pos, 0.0f)) {
+ CVector vecDirectionAway(pVehicle->GetPosition().x - GetGarageCenterX(), pVehicle->GetPosition().y - GetGarageCenterY(), 0.0f);
+ vecDirectionAway.Normalise();
+ pVehicle->AddToMoveSpeed(vecDirectionAway * CTimer::GetTimeStepInSeconds());
+ }
+ }
+ }
+}
+
bool CGarage::IsStaticPlayerCarEntirelyInside()
{
if (!FindPlayerVehicle())
@@ -1178,8 +1101,8 @@ bool CGarage::IsStaticPlayerCarEntirelyInside()
if (FindPlayerPed()->m_objective == OBJECTIVE_LEAVE_VEHICLE)
return false;
CVehicle* pVehicle = FindPlayerVehicle();
- if (pVehicle->GetPosition().x < m_fX1 || pVehicle->GetPosition().x > m_fX2 ||
- pVehicle->GetPosition().y < m_fY1 || pVehicle->GetPosition().y > m_fY2)
+ if (pVehicle->GetPosition().x < m_fInfX || pVehicle->GetPosition().x > m_fSupX ||
+ pVehicle->GetPosition().y < m_fInfY || pVehicle->GetPosition().y > m_fSupY)
return false;
if (Abs(pVehicle->GetSpeed().x) > 0.01f ||
Abs(pVehicle->GetSpeed().y) > 0.01f ||
@@ -1190,35 +1113,58 @@ bool CGarage::IsStaticPlayerCarEntirelyInside()
return IsEntityEntirelyInside3D(pVehicle, 0.0f);
}
-bool CGarage::IsEntityEntirelyInside(CEntity * pEntity)
+bool CGarage::IsPointInsideGarage(CVector pos)
{
- if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 ||
- pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2)
+ // is it IsPointInsideGarage(pos, 0.0f)?
+ if (pos.z < m_fInfZ)
+ return false;
+ if (pos.z > m_fSupZ)
+ return false;
+ CVector2D vecToTarget((CVector2D)pos - m_vecCorner1);
+ float dp = DotProduct2D(m_vDir1, vecToTarget);
+ if (dp < 0.0f)
+ return false;
+ if (m_fDir1Len < dp)
+ return false;
+ dp = DotProduct2D(m_vDir2, vecToTarget);
+ if (dp < 0.0f)
+ return false;
+ if (m_fDir2Len < dp)
+ return false;
+ return true;
+}
+
+bool CGarage::IsPointInsideGarage(CVector pos, float m_fMargin)
+{
+ if (pos.z < m_fInfZ - m_fMargin)
+ return false;
+ if (pos.z > m_fSupZ + m_fMargin)
+ return false;
+ CVector2D vecToTarget((CVector2D)pos - m_vecCorner1);
+ float dp = DotProduct2D(m_vDir1, vecToTarget);
+ if (dp < -m_fMargin)
+ return false;
+ if (m_fDir1Len + m_fMargin < dp)
+ return false;
+ dp = DotProduct2D(m_vDir2, vecToTarget);
+ if (dp < -m_fMargin)
+ return false;
+ if (m_fDir2Len + m_fMargin < dp)
return false;
- CColModel* pColModel = pEntity->GetColModel();
- for (int i = 0; i < pColModel->numSpheres; i++) {
- CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
- float radius = pColModel->spheres[i].radius;
- if (pos.x - radius < m_fX1 || pos.x + radius > m_fX2 ||
- pos.y - radius < m_fY1 || pos.y + radius > m_fY2)
- return false;
- }
return true;
}
bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
{
- if (pEntity->GetPosition().x < m_fX1 - fMargin || pEntity->GetPosition().x > m_fX2 + fMargin ||
- pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin ||
- pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin)
+ if (pEntity->GetPosition().x < m_fInfX - fMargin || pEntity->GetPosition().x > m_fSupX + fMargin ||
+ pEntity->GetPosition().y < m_fInfY - fMargin || pEntity->GetPosition().y > m_fSupY + fMargin ||
+ pEntity->GetPosition().z < m_fInfZ - fMargin || pEntity->GetPosition().z > m_fSupZ + fMargin)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 - fMargin || pos.x - radius > m_fX2 + fMargin ||
- pos.y + radius < m_fY1 - fMargin || pos.y - radius > m_fY2 + fMargin ||
- pos.z + radius < m_fZ1 - fMargin || pos.z - radius > m_fZ2 + fMargin)
+ if (!IsPointInsideGarage(pos, fMargin - radius))
return false;
}
return true;
@@ -1226,15 +1172,14 @@ bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
{
- if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin &&
- pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin)
+ if (pEntity->GetPosition().x > m_fInfX - fMargin && pEntity->GetPosition().x < m_fSupX + fMargin &&
+ pEntity->GetPosition().y > m_fInfY - fMargin && pEntity->GetPosition().y < m_fSupY + fMargin)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 - fMargin && pos.x - radius < m_fX2 + fMargin &&
- pos.y + radius > m_fY1 - fMargin && pos.y - radius < m_fY2 + fMargin)
+ if (IsPointInsideGarage(pos, fMargin + radius))
return false;
}
return true;
@@ -1243,8 +1188,15 @@ bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
bool CGarage::IsGarageEmpty()
{
int16 num;
- CWorld::FindObjectsIntersectingCube(CVector(m_fX1, m_fY1, m_fZ1), CVector(m_fX2, m_fY2, m_fZ2), &num, 2, nil, false, true, true, false, false);
- return num == 0;
+ CEntity* pEntities[16];
+ CWorld::FindObjectsIntersectingCube(CVector(m_fInfX, m_fInfY, m_fInfZ), CVector(m_fSupX, m_fSupY, m_fSupZ), &num, 16, pEntities, false, true, true, false, false);
+ if (num <= 0)
+ return true;
+ for (int i = 0; i < 16; i++) {
+ if (IsEntityTouching3D(pEntities[i]))
+ return false;
+ }
+ return true;
}
bool CGarage::IsPlayerOutsideGarage()
@@ -1257,20 +1209,18 @@ bool CGarage::IsPlayerOutsideGarage()
bool CGarage::IsEntityTouching3D(CEntity * pEntity)
{
float radius = pEntity->GetBoundRadius();
- if (pEntity->GetPosition().x - radius < m_fX1 || pEntity->GetPosition().x + radius > m_fX2 ||
- pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 ||
- pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2)
+ if (pEntity->GetPosition().x - radius < m_fInfX || pEntity->GetPosition().x + radius > m_fSupX ||
+ pEntity->GetPosition().y - radius < m_fInfY || pEntity->GetPosition().y + radius > m_fSupY ||
+ pEntity->GetPosition().z - radius < m_fInfZ || pEntity->GetPosition().z + radius > m_fSupZ)
return false;
CColModel* pColModel = pEntity->GetColModel();
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
- return false;
+ if (IsPointInsideGarage(pos, radius))
+ return true;
}
- return true;
+ return false;
}
bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
@@ -1279,9 +1229,7 @@ bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius + fMargin < m_fX1 || pos.x - radius - fMargin > m_fX2 ||
- pos.y + radius + fMargin < m_fY1 || pos.y - radius - fMargin > m_fY2 ||
- pos.z + radius + fMargin < m_fZ1 || pos.z - radius - fMargin > m_fZ2)
+ if (!IsPointInsideGarage(pos, fMargin + radius))
return true;
}
return false;
@@ -1300,9 +1248,7 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
+ if (IsPointInsideGarage(pos, radius))
return true;
}
}
@@ -1322,9 +1268,7 @@ bool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException)
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius > m_fX1 && pos.x - radius < m_fX2 &&
- pos.y + radius > m_fY1 && pos.y - radius < m_fY2 &&
- pos.z + radius > m_fZ1 && pos.z - radius < m_fZ2)
+ if (IsPointInsideGarage(pos, radius))
return true;
}
}
@@ -1344,9 +1288,7 @@ bool CGarage::IsAnyCarBlockingDoor()
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 || pos.x - radius > m_fX2 ||
- pos.y + radius < m_fY1 || pos.y - radius > m_fY2 ||
- pos.z + radius < m_fZ1 || pos.z - radius > m_fZ2)
+ if (!IsPointInsideGarage(pos, radius))
return true;
}
}
@@ -1361,9 +1303,7 @@ int32 CGarage::CountCarsWithCenterPointWithinGarage(CEntity * pException)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle || pVehicle == pException)
continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2)
+ if (IsPointInsideGarage(pVehicle->GetPosition()))
total++;
}
return total;
@@ -1378,9 +1318,7 @@ void CGarage::RemoveCarsBlockingDoorNotInside()
continue;
if (!IsEntityTouching3D(pVehicle))
continue;
- if (pVehicle->GetPosition().x < m_fX1 || pVehicle->GetPosition().x > m_fX2 ||
- pVehicle->GetPosition().y < m_fY1 || pVehicle->GetPosition().y > m_fY2 ||
- pVehicle->GetPosition().z < m_fZ1 || pVehicle->GetPosition().z > m_fZ2) {
+ if (!IsPointInsideGarage(pVehicle->GetPosition())) {
if (pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {
CWorld::Remove(pVehicle);
delete pVehicle;
@@ -1399,7 +1337,7 @@ void CGarages::PrintMessages()
CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f));
CFont::SetCentreOn();
- CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
+ CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); // TODO(MIAMI): redo it
CFont::SetColor(CRGBA(0, 0, 0, 255));
#if defined(PS2) || defined (FIX_BUGS)
@@ -1412,7 +1350,7 @@ void CGarages::PrintMessages()
if (MessageNumberInString < 0) {
CFont::PrintString(SCREEN_WIDTH / 2 - SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(2.0f), TheText.Get(MessageIDString));
- CFont::SetColor(CRGBA(89, 115, 150, 255));
+ CFont::SetColor(CRGBA(27, 89, 130, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString));
}
else {
@@ -1420,7 +1358,7 @@ void CGarages::PrintMessages()
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
- CFont::SetColor(CRGBA(89, 115, 150, 255));
+ CFont::SetColor(CRGBA(27, 89, 130, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
}
}
@@ -1428,7 +1366,7 @@ void CGarages::PrintMessages()
CMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);
CFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), y_offset - SCREEN_SCALE_Y(40.0f) + SCREEN_SCALE_Y(2.0f), gUString);
- CFont::SetColor(CRGBA(89, 115, 150, 255));
+ CFont::SetColor(CRGBA(27, 89, 130, 255));
CFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(40.0f), gUString);
}
}
@@ -1458,15 +1396,27 @@ void CGarage::UpdateDoorsHeight()
RefreshDoorPointers(false);
if (m_pDoor1) {
m_pDoor1->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor1Z;
- if (m_bRotatedDoor)
+ if (m_bRotatedDoor) {
+ CVector pos;
+ pos.x = m_fDoor1X + m_fDoorPos * m_pDoor1->GetForward().y * 5.0f / 6.0f;
+ pos.y = m_fDoor1Y - m_fDoorPos * m_pDoor1->GetForward().x * 5.0f / 6.0f;
+ pos.z = m_pDoor1->GetPosition().z;
+ m_pDoor1->SetPosition(pos);
BuildRotatedDoorMatrix(m_pDoor1, m_fDoorPos / m_fDoorHeight);
+ }
m_pDoor1->GetMatrix().UpdateRW();
m_pDoor1->UpdateRwFrame();
}
if (m_pDoor2) {
m_pDoor2->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor2Z;
- if (m_bRotatedDoor)
+ if (m_bRotatedDoor) {
+ CVector pos;
+ pos.x = m_fDoor2X + m_fDoorPos * m_pDoor2->GetForward().y * 5.0f / 6.0f;
+ pos.y = m_fDoor2Y - m_fDoorPos * m_pDoor2->GetForward().x * 5.0f / 6.0f;
+ pos.z = m_pDoor2->GetPosition().z;
+ m_pDoor2->SetPosition(pos);
BuildRotatedDoorMatrix(m_pDoor2, m_fDoorPos / m_fDoorHeight);
+ }
m_pDoor2->GetMatrix().UpdateRW();
m_pDoor2->UpdateRwFrame();
}
@@ -1568,6 +1518,7 @@ void CGarages::SetTargetCarForMissonGarage(int16 garage, CVehicle * pVehicle)
assert(garage >= 0 && garage < NUM_GARAGES);
if (pVehicle) {
aGarages[garage].m_pTarget = pVehicle;
+ aGarages[garage].m_pTarget->RegisterReference((CEntity**)&aGarages[garage].m_pTarget);
if (aGarages[garage].m_eGarageState == GS_CLOSEDCONTAINSCAR)
aGarages[garage].m_eGarageState = GS_FULLYCLOSED;
}
@@ -1619,11 +1570,9 @@ bool CGarages::HasThisCarBeenCollected(int16 garage, uint8 id)
bool CGarage::DoesCraigNeedThisCar(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
for (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][i])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][i] || (gaCarsToCollectInCraigsGarages[ct][i] == MI_CHEETAH && mi == MI_VICECHEE))
return (CGarages::CarTypesCollected[ct] & BIT(i)) == 0;
}
return false;
@@ -1631,11 +1580,9 @@ bool CGarage::DoesCraigNeedThisCar(int32 mi)
bool CGarage::HasCraigCollectedThisCar(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
for (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][i])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][i] || (gaCarsToCollectInCraigsGarages[ct][i] == MI_CHEETAH && mi == MI_VICECHEE))
return CGarages::CarTypesCollected[ct] & BIT(i);
}
return false;
@@ -1643,12 +1590,10 @@ bool CGarage::HasCraigCollectedThisCar(int32 mi)
bool CGarage::MarkThisCarAsCollectedForCraig(int32 mi)
{
- if (mi == MI_CORPSE)
- mi = MI_MANANA;
int ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);
int index;
for (index = 0; index < TOTAL_COLLECTCARS_CARS; index++) {
- if (mi == gaCarsToCollectInCraigsGarages[ct][index])
+ if (mi == gaCarsToCollectInCraigsGarages[ct][index] || (gaCarsToCollectInCraigsGarages[ct][index] == MI_CHEETAH && mi == MI_VICECHEE))
break;
}
if (index >= TOTAL_COLLECTCARS_CARS)
@@ -1681,16 +1626,16 @@ void CGarage::CloseThisGarage()
float CGarage::CalcDistToGarageRectangleSquared(float X, float Y)
{
float distX, distY;
- if (X < m_fX1)
- distX = m_fX1 - X;
- else if (X > m_fX2)
- distX = X - m_fX2;
+ if (X < m_fInfX)
+ distX = m_fInfX - X;
+ else if (X > m_fSupX)
+ distX = X - m_fSupX;
else
distX = 0.0f;
- if (Y < m_fY1)
- distY = m_fY1 - Y;
- else if (Y > m_fY2)
- distY = Y - m_fY2;
+ if (Y < m_fInfY)
+ distY = m_fInfY - Y;
+ else if (Y > m_fSupY)
+ distY = Y - m_fSupY;
else
distY = 0.0f;
return SQR(distX) + SQR(distY);
@@ -1711,10 +1656,10 @@ void CGarage::FindDoorsEntities()
{
m_pDoor1 = nil;
m_pDoor2 = nil;
- int xstart = Max(0, CWorld::GetSectorIndexX(m_fX1));
- int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2));
- int ystart = Max(0, CWorld::GetSectorIndexY(m_fY1));
- int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fY2));
+ int xstart = Max(0, CWorld::GetSectorIndexX(m_fInfX));
+ int xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fSupX));
+ int ystart = Max(0, CWorld::GetSectorIndexY(m_fInfY));
+ int yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fSupY));
assert(xstart <= xend);
assert(ystart <= yend);
@@ -1729,20 +1674,22 @@ void CGarage::FindDoorsEntities()
FindDoorsEntitiesSectorList(s->m_lists[ENTITYLIST_DUMMIES_OVERLAP], true);
}
}
- if (!m_pDoor1 || !m_pDoor2)
- return;
- if (m_pDoor1->GetModelIndex() == MI_CRUSHERBODY || m_pDoor1->GetModelIndex() == MI_CRUSHERLID)
- return;
- CVector2D vecDoor1ToGarage(m_pDoor1->GetPosition().x - GetGarageCenterX(), m_pDoor1->GetPosition().y - GetGarageCenterY());
- CVector2D vecDoor2ToGarage(m_pDoor2->GetPosition().x - GetGarageCenterX(), m_pDoor2->GetPosition().y - GetGarageCenterY());
- if (DotProduct2D(vecDoor1ToGarage, vecDoor2ToGarage) > 0.0f) {
- if (vecDoor1ToGarage.MagnitudeSqr() >= vecDoor2ToGarage.MagnitudeSqr()) {
- m_pDoor1 = m_pDoor2;
- m_bDoor1IsDummy = m_bDoor2IsDummy;
+ if (m_pDoor1 && m_pDoor2) {
+ CVector2D vecDoor1ToGarage(m_pDoor1->GetPosition().x - GetGarageCenterX(), m_pDoor1->GetPosition().y - GetGarageCenterY());
+ CVector2D vecDoor2ToGarage(m_pDoor2->GetPosition().x - GetGarageCenterX(), m_pDoor2->GetPosition().y - GetGarageCenterY());
+ if (DotProduct2D(vecDoor1ToGarage, vecDoor2ToGarage) > 0.0f) {
+ if (vecDoor1ToGarage.MagnitudeSqr() >= vecDoor2ToGarage.MagnitudeSqr()) {
+ m_pDoor1 = m_pDoor2;
+ m_bDoor1IsDummy = m_bDoor2IsDummy;
+ }
+ m_pDoor2 = nil;
+ m_bDoor2IsDummy = false;
}
- m_pDoor2 = nil;
- m_bDoor2IsDummy = false;
}
+ if (m_pDoor1)
+ m_pDoor1->bUsesCollision = true;
+ if (m_pDoor2)
+ m_pDoor2->bUsesCollision = true;
}
void CGarage::FindDoorsEntitiesSectorList(CPtrList& list, bool dummy)
@@ -1755,29 +1702,8 @@ void CGarage::FindDoorsEntitiesSectorList(CPtrList& list, bool dummy)
pEntity->m_scanCode = CWorld::GetCurrentScanCode();
if (!pEntity || !CGarages::IsModelIndexADoor(pEntity->GetModelIndex()))
continue;
- if (Abs(pEntity->GetPosition().x - GetGarageCenterX()) >= DISTANCE_TO_CONSIDER_DOOR_FOR_GARAGE)
- continue;
- if (Abs(pEntity->GetPosition().y - GetGarageCenterY()) >= DISTANCE_TO_CONSIDER_DOOR_FOR_GARAGE)
- continue;
- if (pEntity->GetModelIndex() == MI_CRUSHERBODY) {
- m_pDoor1 = pEntity;
- m_bDoor1IsDummy = dummy;
- // very odd pool operations, they could have used GetJustIndex
- if (dummy)
- m_bDoor1PoolIndex = (CPools::GetDummyPool()->GetIndex((CDummy*)pEntity)) & 0x7F;
- else
- m_bDoor1PoolIndex = (CPools::GetObjectPool()->GetIndex((CObject*)pEntity)) & 0x7F;
- continue;
- }
- if (pEntity->GetModelIndex() == MI_CRUSHERLID) {
- m_pDoor2 = pEntity;
- m_bDoor2IsDummy = dummy;
- if (dummy)
- m_bDoor2PoolIndex = (CPools::GetDummyPool()->GetIndex((CDummy*)pEntity)) & 0x7F;
- else
- m_bDoor2PoolIndex = (CPools::GetObjectPool()->GetIndex((CObject*)pEntity)) & 0x7F;
+ if (!IsPointInsideGarage(pEntity->GetPosition(), 2.0f))
continue;
- }
if (!m_pDoor1) {
m_pDoor1 = pEntity;
m_bDoor1IsDummy = dummy;
@@ -1812,6 +1738,8 @@ void CGarages::SetGarageDoorToRotate(int16 garage)
aGarages[garage].m_bRotatedDoor = true;
aGarages[garage].m_fDoorHeight /= 2.0f;
aGarages[garage].m_fDoorHeight -= 0.1f;
+ aGarages[garage].m_fDoorPos = Min(aGarages[garage].m_fDoorHeight, aGarages[garage].m_fDoorPos);
+ aGarages[garage].UpdateDoorsHeight();
}
void CGarages::SetLeaveCameraForThisGarage(int16 garage)
@@ -1854,15 +1782,12 @@ CVehicle* CStoredCar::RestoreCar()
if (!CStreaming::HasModelLoaded(m_nModelIndex))
return nil;
CVehicleModelInfo::SetComponentsToUse(m_nVariationA, m_nVariationB);
-#ifdef FIX_BUGS
CVehicle* pVehicle;
if (CModelInfo::IsBoatModel(m_nModelIndex))
pVehicle = new CBoat(m_nModelIndex, RANDOM_VEHICLE);
+ // else if bike - TODO(MIAMI)
else
pVehicle = new CAutomobile(m_nModelIndex, RANDOM_VEHICLE);
-#else
- CVehicle* pVehicle = new CAutomobile(m_nModelIndex, RANDOM_VEHICLE);
-#endif
pVehicle->SetPosition(m_vecPos);
pVehicle->SetStatus(STATUS_ABANDONED);
pVehicle->GetForward() = m_vecAngle;
@@ -1896,9 +1821,7 @@ void CGarage::StoreAndRemoveCarsForThisHideout(CStoredCar* aCars, int32 nMax)
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2) {
+ if (IsPointInsideGarage(pVehicle->GetPosition())) {
if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) {
if (index < Max(NUM_GARAGE_STORED_CARS, nMax) && !EntityHasASphereWayOutsideGarage(pVehicle, 1.0f))
aCars[index++].StoreCar(pVehicle);
@@ -1940,17 +1863,12 @@ bool CGarages::IsPointInAGarageCameraZone(CVector point)
case GARAGE_COLLECTCARS_1:
case GARAGE_COLLECTCARS_2:
case GARAGE_COLLECTCARS_3:
- if (aGarages[i].m_fX1 - MARGIN_FOR_CAMERA_COLLECTCARS <= point.x &&
- aGarages[i].m_fX2 + MARGIN_FOR_CAMERA_COLLECTCARS >= point.x &&
- aGarages[i].m_fY1 - MARGIN_FOR_CAMERA_COLLECTCARS <= point.y &&
- aGarages[i].m_fY2 + MARGIN_FOR_CAMERA_COLLECTCARS >= point.y)
+ case GARAGE_COLLECTCARS_4:
+ if (aGarages[i].IsPointInsideGarage(point, MARGIN_FOR_CAMERA_COLLECTCARS))
return true;
break;
default:
- if (aGarages[i].m_fX1 - MARGIN_FOR_CAMERA_DEFAULT <= point.x &&
- aGarages[i].m_fX2 + MARGIN_FOR_CAMERA_DEFAULT >= point.x &&
- aGarages[i].m_fY1 - MARGIN_FOR_CAMERA_DEFAULT <= point.y &&
- aGarages[i].m_fY2 + MARGIN_FOR_CAMERA_DEFAULT >= point.y)
+ if (aGarages[i].IsPointInsideGarage(point, MARGIN_FOR_CAMERA_DEFAULT))
return true;
break;
}
@@ -1981,9 +1899,7 @@ void CGarage::TidyUpGarage()
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle || !pVehicle->IsCar())
continue;
- if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 &&
- pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 &&
- pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2) {
+ if (IsPointInsideGarage(pVehicle->GetPosition())) {
if (pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->GetUp().z < 0.5f) {
CWorld::Remove(pVehicle);
delete pVehicle;
@@ -2007,11 +1923,8 @@ void CGarage::TidyUpGarageClose()
for (int i = 0; i < pColModel->numSpheres; i++) {
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
float radius = pColModel->spheres[i].radius;
- if (pos.x + radius < m_fX1 || pos.x - radius > m_fX2 ||
- pos.y + radius < m_fY1 || pos.y - radius > m_fY2 ||
- pos.z + radius < m_fZ1 || pos.z - radius > m_fZ2) {
+ if (!IsPointInsideGarage(pos, radius))
bRemove = true;
- }
}
}
else
@@ -2054,6 +1967,17 @@ void CGarage::PlayerArrestedOrDied()
case GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:
case GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:
case GARAGE_MISSION_KEEPCAR_REMAINCLOSED:
+ case GARAGE_COLLECTCARS_4:
+ case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:
+ case GARAGE_HIDEOUT_FOUR:
+ case GARAGE_HIDEOUT_FIVE:
+ case GARAGE_HIDEOUT_SIX:
+ case GARAGE_HIDEOUT_SEVEN:
+ case GARAGE_HIDEOUT_EIGHT:
+ case GARAGE_HIDEOUT_NINE:
+ case GARAGE_HIDEOUT_TEN:
+ case GARAGE_HIDEOUT_ELEVEN:
+ case GARAGE_HIDEOUT_TWELVE:
switch (m_eGarageState) {
case GS_OPENED:
case GS_CLOSING:
@@ -2105,36 +2029,19 @@ void CGarage::CenterCarInGarage(CVehicle* pVehicle)
pVehicle->GetMatrix().GetPosition().x += offsetX * RESPRAY_CENTERING_COEFFICIENT / distance;
pVehicle->GetMatrix().GetPosition().y += offsetY * RESPRAY_CENTERING_COEFFICIENT / distance;
}
- if (!IsEntityEntirelyInside3D(pVehicle, 0.1f))
+ if (!IsEntityEntirelyInside3D(pVehicle, 0.3f))
pVehicle->SetPosition(pos);
}
void CGarages::CloseHideOutGaragesBeforeSave()
{
for (int i = 0; i < NUM_GARAGES; i++) {
- if (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE &&
- aGarages[i].m_eGarageType != GARAGE_HIDEOUT_TWO &&
- aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE)
+ if (!IsThisGarageTypeSafehouse(aGarages[i].m_eGarageType))
continue;
- if (aGarages[i].m_eGarageState != GS_FULLYCLOSED &&
- (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor())) {
+ if (aGarages[i].m_eGarageState != GS_FULLYCLOSED) {
aGarages[i].m_eGarageState = GS_FULLYCLOSED;
- switch (aGarages[i].m_eGarageType) {
- case GARAGE_HIDEOUT_ONE:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse1, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- case GARAGE_HIDEOUT_TWO:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse2, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- case GARAGE_HIDEOUT_THREE:
- aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouse3, NUM_GARAGE_STORED_CARS);
- aGarages[i].RemoveCarsBlockingDoorNotInside();
- break;
- default:
- break;
- }
+ aGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouses[FindSafeHouseIndexForGarageType(aGarages[i].m_eGarageType)], NUM_GARAGE_STORED_CARS);
+ aGarages[i].RemoveCarsBlockingDoorNotInside();
}
aGarages[i].m_fDoorPos = 0.0f;
aGarages[i].UpdateDoorsHeight();
@@ -2145,36 +2052,11 @@ int32 CGarages::CountCarsInHideoutGarage(eGarageType type)
{
int32 total = 0;
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- switch (type) {
- case GARAGE_HIDEOUT_ONE:
- total += (aCarsInSafeHouse1[i].HasCar());
- break;
- case GARAGE_HIDEOUT_TWO:
- total += (aCarsInSafeHouse2[i].HasCar());
- break;
- case GARAGE_HIDEOUT_THREE:
- total += (aCarsInSafeHouse3[i].HasCar());
- break;
- default: break;
- }
+ total += aCarsInSafeHouses[FindSafeHouseIndexForGarageType(type)][i].HasCar();
}
return total;
}
-int32 CGarages::FindMaxNumStoredCarsForGarage(eGarageType type)
-{
- switch (type) {
- case GARAGE_HIDEOUT_ONE:
- return LIMIT_CARS_IN_INDUSTRIAL;
- case GARAGE_HIDEOUT_TWO:
- return LIMIT_CARS_IN_COMMERCIAL;
- case GARAGE_HIDEOUT_THREE:
- return LIMIT_CARS_IN_SUBURBAN;
- default: break;
- }
- return 0;
-}
-
bool CGarages::IsPointWithinHideOutGarage(Const CVector& point)
{
for (int i = 0; i < NUM_GARAGES; i++) {
@@ -2182,9 +2064,7 @@ bool CGarages::IsPointWithinHideOutGarage(Const CVector& point)
case GARAGE_HIDEOUT_ONE:
case GARAGE_HIDEOUT_TWO:
case GARAGE_HIDEOUT_THREE:
- if (point.x > aGarages[i].m_fX1 && point.x < aGarages[i].m_fX2 &&
- point.y > aGarages[i].m_fY1 && point.y < aGarages[i].m_fY2 &&
- point.z > aGarages[i].m_fZ1 && point.z < aGarages[i].m_fZ2)
+ if (aGarages[i].IsPointInsideGarage(point))
return true;
default: break;
}
@@ -2199,9 +2079,7 @@ bool CGarages::IsPointWithinAnyGarage(Const CVector& point)
case GARAGE_NONE:
continue;
default:
- if (point.x > aGarages[i].m_fX1 && point.x < aGarages[i].m_fX2 &&
- point.y > aGarages[i].m_fY1 && point.y < aGarages[i].m_fY2 &&
- point.z > aGarages[i].m_fZ1 && point.z < aGarages[i].m_fZ2)
+ if (aGarages[i].IsPointInsideGarage(point))
return true;
}
}
@@ -2238,6 +2116,7 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
}
}
+// TODO(MIAMI)
void CGarages::Save(uint8 * buf, uint32 * size)
{
#ifdef FIX_GARAGE_SIZE
@@ -2257,9 +2136,9 @@ void CGarages::Save(uint8 * buf, uint32 * size)
WriteSaveBuf(buf, CarTypesCollected[i]);
WriteSaveBuf(buf, LastTimeHelpMessage);
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- WriteSaveBuf(buf, aCarsInSafeHouse1[i]);
- WriteSaveBuf(buf, aCarsInSafeHouse2[i]);
- WriteSaveBuf(buf, aCarsInSafeHouse3[i]);
+ for (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) {
+ WriteSaveBuf(buf, aCarsInSafeHouses[j][i]);
+ }
}
for (int i = 0; i < NUM_GARAGES; i++)
WriteSaveBuf(buf, aGarages[i]);
@@ -2287,6 +2166,7 @@ const CStoredCar &CStoredCar::operator=(const CStoredCar & other)
return *this;
}
+//TODO(MIAMI)
void CGarages::Load(uint8* buf, uint32 size)
{
#ifdef FIX_GARAGE_SIZE
@@ -2306,9 +2186,9 @@ void CGarages::Load(uint8* buf, uint32 size)
CarTypesCollected[i] = ReadSaveBuf<uint32>(buf);
LastTimeHelpMessage = ReadSaveBuf<uint32>(buf);
for (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {
- aCarsInSafeHouse1[i] = ReadSaveBuf<CStoredCar>(buf);
- aCarsInSafeHouse2[i] = ReadSaveBuf<CStoredCar>(buf);
- aCarsInSafeHouse3[i] = ReadSaveBuf<CStoredCar>(buf);
+ for (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) {
+ aCarsInSafeHouses[j][i] = ReadSaveBuf<CStoredCar>(buf);
+ }
}
for (int i = 0; i < NUM_GARAGES; i++) {
aGarages[i] = ReadSaveBuf<CGarage>(buf);
@@ -2335,8 +2215,7 @@ void CGarages::Load(uint8* buf, uint32 size)
bool
CGarages::IsModelIndexADoor(uint32 id)
{
- return id == MI_GARAGEDOOR1 ||
- id == MI_GARAGEDOOR2 ||
+ return id == MI_GARAGEDOOR2 ||
id == MI_GARAGEDOOR3 ||
id == MI_GARAGEDOOR4 ||
id == MI_GARAGEDOOR5 ||
@@ -2350,7 +2229,6 @@ CGarages::IsModelIndexADoor(uint32 id)
id == MI_GARAGEDOOR14 ||
id == MI_GARAGEDOOR15 ||
id == MI_GARAGEDOOR16 ||
- id == MI_GARAGEDOOR17 ||
id == MI_GARAGEDOOR18 ||
id == MI_GARAGEDOOR19 ||
id == MI_GARAGEDOOR20 ||
@@ -2359,13 +2237,5 @@ CGarages::IsModelIndexADoor(uint32 id)
id == MI_GARAGEDOOR23 ||
id == MI_GARAGEDOOR24 ||
id == MI_GARAGEDOOR25 ||
- id == MI_GARAGEDOOR26 ||
- id == MI_GARAGEDOOR27 ||
- id == MI_GARAGEDOOR28 ||
- id == MI_GARAGEDOOR29 ||
- id == MI_GARAGEDOOR30 ||
- id == MI_GARAGEDOOR31 ||
- id == MI_GARAGEDOOR32 ||
- id == MI_CRUSHERBODY ||
- id == MI_CRUSHERLID;
+ id == MI_GARAGEDOOR26;
}
diff --git a/src/control/Garages.h b/src/control/Garages.h
index 00020eb3..c5bede2b 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -42,12 +42,24 @@ enum eGarageType : int8
GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE,
GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR,
GARAGE_MISSION_KEEPCAR_REMAINCLOSED,
+ GARAGE_COLLECTCARS_4,
+ GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR,
+ GARAGE_HIDEOUT_FOUR,
+ GARAGE_HIDEOUT_FIVE,
+ GARAGE_HIDEOUT_SIX,
+ GARAGE_HIDEOUT_SEVEN,
+ GARAGE_HIDEOUT_EIGHT,
+ GARAGE_HIDEOUT_NINE,
+ GARAGE_HIDEOUT_TEN,
+ GARAGE_HIDEOUT_ELEVEN,
+ GARAGE_HIDEOUT_TWELVE
};
enum
{
- TOTAL_COLLECTCARS_GARAGES = GARAGE_COLLECTCARS_3 - GARAGE_COLLECTCARS_1 + 1,
- TOTAL_COLLECTCARS_CARS = 16
+ TOTAL_COLLECTCARS_GARAGES = 4,
+ TOTAL_HIDEOUT_GARAGES = 12,
+ TOTAL_COLLECTCARS_CARS = 6
};
class CStoredCar
@@ -83,6 +95,7 @@ class CGarage
{
eGarageType m_eGarageType;
eGarageState m_eGarageState;
+ uint8 m_nMaxStoredCars;
bool field_2; // unused
bool m_bClosingWithoutTargetCar;
bool m_bDeactivated;
@@ -97,12 +110,17 @@ class CGarage
bool m_bRecreateDoorOnNextRefresh;
bool m_bRotatedDoor;
bool m_bCameraFollowsPlayer;
- float m_fX1;
- float m_fX2;
- float m_fY1;
- float m_fY2;
- float m_fZ1;
- float m_fZ2;
+ CVector2D m_vecCorner1;
+ float m_fInfZ;
+ CVector2D m_vDir1;
+ CVector2D m_vDir2;
+ float m_fSupZ;
+ float m_fDir1Len;
+ float m_fDir2Len;
+ float m_fInfX;
+ float m_fSupX;
+ float m_fInfY;
+ float m_fSupY;
float m_fDoorPos;
float m_fDoorHeight;
float m_fDoor1X;
@@ -123,8 +141,8 @@ class CGarage
bool IsClosed() { return m_eGarageState == GS_FULLYCLOSED; }
bool IsUsed() { return m_eGarageType != GARAGE_NONE; }
void Update();
- float GetGarageCenterX() { return (m_fX1 + m_fX2) / 2; }
- float GetGarageCenterY() { return (m_fY1 + m_fY2) / 2; }
+ float GetGarageCenterX() { return (m_fInfX + m_fSupX) / 2; }
+ float GetGarageCenterY() { return (m_fInfY + m_fSupY) / 2; }
bool IsFar()
{
#ifdef FIX_BUGS
@@ -142,7 +160,6 @@ class CGarage
void UpdateDoorsHeight();
bool IsEntityEntirelyInside3D(CEntity*, float);
bool IsEntityEntirelyOutside(CEntity*, float);
- bool IsEntityEntirelyInside(CEntity*);
float CalcDistToGarageRectangleSquared(float, float);
float CalcSmallestDistToGarageDoorSquared(float, float);
bool IsAnyOtherCarTouchingGarage(CVehicle* pException);
@@ -167,17 +184,22 @@ class CGarage
void FindDoorsEntitiesSectorList(CPtrList&, bool);
void PlayerArrestedOrDied();
+ bool IsPointInsideGarage(CVector);
+ bool IsPointInsideGarage(CVector, float);
+ void ThrowCarsNearDoorOutOfGarage(CVehicle*);
+
+ int32 FindMaxNumStoredCarsForGarage() { return Max(NUM_GARAGE_STORED_CARS, m_nMaxStoredCars); }
+
friend class CGarages;
friend class cAudioManager;
friend class CCamera;
};
-VALIDATE_SIZE(CGarage, 140);
-
class CGarages
{
enum {
- MESSAGE_LENGTH = 8
+ MESSAGE_LENGTH = 8,
+ MAX_NUM_CARS_IN_HIDEOUT_GARAGE = 4
};
static int32 BankVansCollected;
static bool BombsAreFree;
@@ -195,9 +217,7 @@ class CGarages
static bool PlayerInGarage;
static int32 PoliceCarsCollected;
static CGarage aGarages[NUM_GARAGES];
- static CStoredCar aCarsInSafeHouse1[NUM_GARAGE_STORED_CARS];
- static CStoredCar aCarsInSafeHouse2[NUM_GARAGE_STORED_CARS];
- static CStoredCar aCarsInSafeHouse3[NUM_GARAGE_STORED_CARS];
+ static CStoredCar aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][MAX_NUM_CARS_IN_HIDEOUT_GARAGE];
static int32 AudioEntity;
static bool bCamShouldBeOutisde;
@@ -208,7 +228,7 @@ public:
#endif
static void Update(void);
- static int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float Z2, eGarageType type, int32 targetId);
+ static int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, eGarageType type, int32 targetId);
static void ChangeGarageType(int16, eGarageType, int32);
static void PrintMessages(void);
static void TriggerMessage(const char* text, int16, uint16 time, int16);
@@ -240,15 +260,45 @@ public:
static bool IsModelIndexADoor(uint32 id);
static void SetFreeBombs(bool bValue) { BombsAreFree = bValue; }
static void SetFreeResprays(bool bValue) { RespraysAreFree = bValue; }
+ static void SetMaxNumStoredCarsForGarage(int16 garage, uint8 num) { aGarages[garage].m_nMaxStoredCars = num; }
private:
static bool IsCarSprayable(CVehicle*);
static float FindDoorHeightForMI(int32);
static void CloseHideOutGaragesBeforeSave(void);
static int32 CountCarsInHideoutGarage(eGarageType);
- static int32 FindMaxNumStoredCarsForGarage(eGarageType);
static int32 GetBombTypeForGarageType(eGarageType type) { return type - GARAGE_BOMBSHOP1 + 1; }
- static int32 GetCarsCollectedIndexForGarageType(eGarageType type) { return type - GARAGE_COLLECTCARS_1; }
+ static int32 GetCarsCollectedIndexForGarageType(eGarageType type)
+ {
+ switch (type) {
+ case GARAGE_COLLECTCARS_1: return 0;
+ case GARAGE_COLLECTCARS_2: return 1;
+ case GARAGE_COLLECTCARS_3: return 2;
+ case GARAGE_COLLECTCARS_4: return 3;
+ default: assert(0);
+ }
+ return 0;
+ }
+ static int32 FindSafeHouseIndexForGarageType(eGarageType type)
+ {
+ switch (type) {
+ case GARAGE_HIDEOUT_ONE: return 0;
+ case GARAGE_HIDEOUT_TWO: return 1;
+ case GARAGE_HIDEOUT_THREE: return 2;
+ case GARAGE_HIDEOUT_FOUR: return 3;
+ case GARAGE_HIDEOUT_FIVE: return 4;
+ case GARAGE_HIDEOUT_SIX: return 5;
+ case GARAGE_HIDEOUT_SEVEN: return 6;
+ case GARAGE_HIDEOUT_EIGHT: return 7;
+ case GARAGE_HIDEOUT_NINE: return 8;
+ case GARAGE_HIDEOUT_TEN: return 9;
+ case GARAGE_HIDEOUT_ELEVEN: return 10;
+ case GARAGE_HIDEOUT_TWELVE: return 11;
+ default: assert(0);
+ }
+ return -1;
+ }
+ static bool IsThisGarageTypeSafehouse(eGarageType type) { return FindSafeHouseIndexForGarageType(type) >= 0; }
friend class cAudioManager;
friend class CGarage;
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp
index ee15b82f..4a948032 100644
--- a/src/control/PathFind.cpp
+++ b/src/control/PathFind.cpp
@@ -18,21 +18,21 @@ CPathFind ThePaths;
#define MIN_PED_ROUTE_DISTANCE 23.8f
-#define NUMTEMPNODES 4000
-#define NUMDETACHED_CARS 100
-#define NUMDETACHED_PEDS 50
+#define NUMTEMPNODES 5000
+#define NUMDETACHED_CARS 1024
+#define NUMDETACHED_PEDS 1214
+#define NUMTEMPEXTERNALNODES 4600
-// object flags:
-// 1 UseInRoadBlock
-// 2 east/west road(?)
-
CPathInfoForObject *InfoForTileCars;
CPathInfoForObject *InfoForTilePeds;
-// unused
-CTempDetachedNode *DetachedNodesCars;
-CTempDetachedNode *DetachedNodesPeds;
+CPathInfoForObject *DetachedInfoForTileCars;
+CPathInfoForObject *DetachedInfoForTilePeds;
+CTempNodeExternal *TempExternalNodes;
+int32 NumTempExternalNodes;
+int32 NumDetachedPedNodeGroups;
+int32 NumDetachedCarNodeGroups;
bool
CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints)
@@ -197,7 +197,7 @@ CPedPath::AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CV
void
CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition)
{
- const CColBox& boundingBox = pEntity->GetColModel()->boundingBox;
+ const CBox& boundingBox = pEntity->GetColModel()->boundingBox;
const float fBoundMaxY = boundingBox.max.y + 0.3f;
const float fBoundMinY = boundingBox.min.y - 0.3f;
const float fBoundMaxX = boundingBox.max.x + 0.3f;
@@ -227,6 +227,27 @@ CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *p
}
}
+//--MIAMI: done
+// Make sure all externals link TO an internal
+void
+CPathInfoForObject::SwapConnectionsToBeRightWayRound(void)
+{
+ int e, i;
+ CPathInfoForObject *tile = this;
+
+ for(e = 0; e < 12; e++)
+ if(tile[e].type == NodeTypeExtern && tile[e].next < 0)
+ for(i = 0; i < 12; i++)
+ if(tile[i].type == NodeTypeIntern && tile[i].next == e){
+ tile[e].next = i;
+ tile[i].next = -1;
+ bool tmp = !!tile[e].crossing;
+ tile[e].crossing = tile[i].crossing;
+ tile[i].crossing = tmp;
+ }
+}
+
+//--MIAMI: done
void
CPathFind::Init(void)
{
@@ -237,11 +258,13 @@ CPathFind::Init(void)
m_numConnections = 0;
m_numCarPathLinks = 0;
unk = 0;
+ NumTempExternalNodes = 0;
for(i = 0; i < NUM_PATHNODES; i++)
m_pathNodes[i].distance = MAX_DIST;
}
+//--MIAMI: done
void
CPathFind::AllocatePathFindInfoMem(int16 numPathGroups)
{
@@ -250,93 +273,172 @@ CPathFind::AllocatePathFindInfoMem(int16 numPathGroups)
delete[] InfoForTilePeds;
InfoForTilePeds = nil;
- // NB: MIAMI doesn't use numPathGroups here but hardcodes 4500
- InfoForTileCars = new CPathInfoForObject[12*numPathGroups];
- memset(InfoForTileCars, 0, 12*numPathGroups*sizeof(CPathInfoForObject));
- InfoForTilePeds = new CPathInfoForObject[12*numPathGroups];
- memset(InfoForTilePeds, 0, 12*numPathGroups*sizeof(CPathInfoForObject));
-
- // unused
- delete[] DetachedNodesCars;
- DetachedNodesCars = nil;
- delete[] DetachedNodesPeds;
- DetachedNodesPeds = nil;
- DetachedNodesCars = new CTempDetachedNode[NUMDETACHED_CARS];
- memset(DetachedNodesCars, 0, NUMDETACHED_CARS*sizeof(CTempDetachedNode));
- DetachedNodesPeds = new CTempDetachedNode[NUMDETACHED_PEDS];
- memset(DetachedNodesPeds, 0, NUMDETACHED_PEDS*sizeof(CTempDetachedNode));
+ // NB: MIAMI doesn't use numPathGroups here but hardcodes PATHNODESIZE
+ InfoForTileCars = new CPathInfoForObject[12*PATHNODESIZE];
+ memset(InfoForTileCars, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject));
+ InfoForTilePeds = new CPathInfoForObject[12*PATHNODESIZE];
+ memset(InfoForTilePeds, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject));
+
+ delete[] DetachedInfoForTileCars;
+ DetachedInfoForTileCars = nil;
+ delete[] DetachedInfoForTilePeds;
+ DetachedInfoForTilePeds = nil;
+ DetachedInfoForTileCars = new CPathInfoForObject[12*NUMDETACHED_CARS];
+ memset(DetachedInfoForTileCars, 0, 12*NUMDETACHED_CARS*sizeof(CPathInfoForObject));
+ DetachedInfoForTilePeds = new CPathInfoForObject[12*NUMDETACHED_PEDS];
+ memset(DetachedInfoForTilePeds, 0, 12*NUMDETACHED_PEDS*sizeof(CPathInfoForObject));
+
+ TempExternalNodes = new CTempNodeExternal[NUMTEMPEXTERNALNODES];
+ memset(TempExternalNodes, 0, NUMTEMPEXTERNALNODES*sizeof(CTempNodeExternal));
+ NumTempExternalNodes = 0;
+ NumDetachedPedNodeGroups = 0;
+ NumDetachedCarNodeGroups = 0;
}
+//--MIAMI: done
void
CPathFind::RegisterMapObject(CTreadable *mapObject)
{
m_mapObjects[m_numMapObjects++] = mapObject;
}
+//--MIAMI: done
void
-CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing)
+CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate)
{
- int i, j;
+ int i;
i = id*12 + node;
InfoForTilePeds[i].type = type;
InfoForTilePeds[i].next = next;
- InfoForTilePeds[i].x = x;
- InfoForTilePeds[i].y = y;
- InfoForTilePeds[i].z = z;
+ InfoForTilePeds[i].x = x/16.0f;
+ InfoForTilePeds[i].y = y/16.0f;
+ InfoForTilePeds[i].z = z/16.0f;
+ InfoForTilePeds[i].width = 8.0f*Min(width, 15.0f);
InfoForTilePeds[i].numLeftLanes = 0;
InfoForTilePeds[i].numRightLanes = 0;
InfoForTilePeds[i].crossing = crossing;
-
- if(type)
- for(i = 0; i < node; i++){
- j = id*12 + i;
- if(x == InfoForTilePeds[j].x && y == InfoForTilePeds[j].y){
- printf("^^^^^^^^^^^^^ AARON IS TOO CHICKEN TO EAT MEAT!\n");
- printf("Several ped nodes on one road segment have identical coordinates (%d==%d && %d==%d)\n",
- x, InfoForTilePeds[j].x, y, InfoForTilePeds[j].y);
- printf("Modelindex of cullprit: %d\n\n", id);
- }
- }
+ InfoForTilePeds[i].speedLimit = 0;
+ InfoForTilePeds[i].roadBlock = false;
+ InfoForTilePeds[i].disabled = false;
+ InfoForTilePeds[i].waterPath = false;
+ InfoForTilePeds[i].onlySmallBoats = false;
+ InfoForTilePeds[i].betweenLevels = false;
+ InfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11)
+ InfoForTilePeds[id*12].SwapConnectionsToBeRightWayRound();
}
+//--MIAMI: done
void
-CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight)
+CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate)
{
- int i, j;
+ int i;
i = id*12 + node;
InfoForTileCars[i].type = type;
InfoForTileCars[i].next = next;
- InfoForTileCars[i].x = x;
- InfoForTileCars[i].y = y;
- InfoForTileCars[i].z = z;
+ InfoForTileCars[i].x = x/16.0f;
+ InfoForTileCars[i].y = y/16.0f;
+ InfoForTileCars[i].z = z/16.0f;
+ InfoForTilePeds[i].width = 8.0f*Min(width, 15.0f);
InfoForTileCars[i].numLeftLanes = numLeft;
InfoForTileCars[i].numRightLanes = numRight;
+ InfoForTilePeds[i].crossing = false;
+ InfoForTilePeds[i].speedLimit = 0;
+ InfoForTilePeds[i].roadBlock = false;
+ InfoForTilePeds[i].disabled = false;
+ InfoForTilePeds[i].waterPath = false;
+ InfoForTilePeds[i].onlySmallBoats = false;
+ InfoForTilePeds[i].betweenLevels = false;
+ InfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11)
+ InfoForTileCars[id*12].SwapConnectionsToBeRightWayRound();
+}
+
+//--MIAMI: done
+void
+CPathFind::StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,
+ bool disabled, bool betweenLevels, uint8 spawnRate)
+{
+ int i;
+ if(NumDetachedPedNodeGroups >= NUMDETACHED_PEDS)
+ return;
- if(type)
- for(i = 0; i < node; i++){
- j = id*12 + i;
- if(x == InfoForTileCars[j].x && y == InfoForTileCars[j].y){
- printf("^^^^^^^^^^^^^ AARON IS TOO CHICKEN TO EAT MEAT!\n");
- printf("Several car nodes on one road segment have identical coordinates (%d==%d && %d==%d)\n",
- x, InfoForTileCars[j].x, y, InfoForTileCars[j].y);
- printf("Modelindex of cullprit: %d\n\n", id);
- }
- }
+ i = NumDetachedPedNodeGroups*12 + node;
+ DetachedInfoForTilePeds[i].type = type;
+ DetachedInfoForTilePeds[i].next = next;
+ DetachedInfoForTilePeds[i].x = x/16.0f;
+ DetachedInfoForTilePeds[i].y = y/16.0f;
+ DetachedInfoForTilePeds[i].z = z/16.0f;
+ DetachedInfoForTilePeds[i].width = 8.0f*Min(width, 31.0f);
+ DetachedInfoForTilePeds[i].numLeftLanes = 0;
+ DetachedInfoForTilePeds[i].numRightLanes = 0;
+ DetachedInfoForTilePeds[i].crossing = crossing;
+ DetachedInfoForTilePeds[i].speedLimit = 0;
+ DetachedInfoForTilePeds[i].roadBlock = false;
+ DetachedInfoForTilePeds[i].disabled = disabled;
+ DetachedInfoForTilePeds[i].waterPath = false;
+ DetachedInfoForTilePeds[i].onlySmallBoats = false;
+ DetachedInfoForTilePeds[i].betweenLevels = betweenLevels;
+ DetachedInfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11){
+ DetachedInfoForTilePeds[NumDetachedPedNodeGroups*12].SwapConnectionsToBeRightWayRound();
+ NumDetachedPedNodeGroups++;
+ }
}
+//--MIAMI: done
void
-CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out)
+CPathFind::StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool onlySmallBoats)
+{
+ int i;
+
+ if(NumDetachedCarNodeGroups >= NUMDETACHED_CARS)
+ return;
+
+ i = NumDetachedCarNodeGroups*12 + node;
+ DetachedInfoForTileCars[i].type = type;
+ DetachedInfoForTileCars[i].next = next;
+ DetachedInfoForTileCars[i].x = x/16.0f;
+ DetachedInfoForTileCars[i].y = y/16.0f;
+ DetachedInfoForTileCars[i].z = z/16.0f;
+ DetachedInfoForTileCars[i].width = 8.0f*Min(width, 15.0f);
+ DetachedInfoForTileCars[i].numLeftLanes = numLeft;
+ DetachedInfoForTileCars[i].numRightLanes = numRight;
+ DetachedInfoForTileCars[i].crossing = false;
+ DetachedInfoForTileCars[i].speedLimit = speedLimit;
+ DetachedInfoForTileCars[i].roadBlock = roadBlock;
+ DetachedInfoForTileCars[i].disabled = disabled;
+ DetachedInfoForTileCars[i].waterPath = waterPath;
+ DetachedInfoForTileCars[i].onlySmallBoats = onlySmallBoats;
+ DetachedInfoForTileCars[i].betweenLevels = betweenLevels;
+ DetachedInfoForTileCars[i].spawnRate = Min(spawnRate, 15);
+
+ if(node == 11){
+ DetachedInfoForTileCars[NumDetachedCarNodeGroups*12].SwapConnectionsToBeRightWayRound();
+ NumDetachedCarNodeGroups++;
+ }
+}
+
+//--MIAMI: done
+void
+CPathFind::CalcNodeCoors(float x, float y, float z, int id, CVector *out)
{
CVector pos;
- pos.x = x / 16.0f;
- pos.y = y / 16.0f;
- pos.z = z / 16.0f;
+ pos.x = x;
+ pos.y = y;
+ pos.z = z;
*out = m_mapObjects[id]->GetMatrix() * pos;
}
+//--MIAMI: done
bool
CPathFind::LoadPathFindData(void)
{
@@ -344,26 +446,22 @@ CPathFind::LoadPathFindData(void)
return false;
}
+//--MIAMI: done
void
CPathFind::PreparePathData(void)
{
- int i, j, k;
- int numExtern, numIntern, numLanes;
- float maxX, maxY;
+ int i, j;
+ int numExtern, numIntern;
CTempNode *tempNodes;
printf("PreparePathData\n");
if(!CPathFind::LoadPathFindData() && // empty
InfoForTileCars && InfoForTilePeds &&
- DetachedNodesCars && DetachedNodesPeds
- ){
+ DetachedInfoForTileCars && DetachedInfoForTilePeds && TempExternalNodes){
tempNodes = new CTempNode[NUMTEMPNODES];
m_numConnections = 0;
- for(i = 0; i < PATHNODESIZE; i++)
- m_pathNodes[i].unkBits = 0;
-
for(i = 0; i < PATHNODESIZE; i++){
numExtern = 0;
numIntern = 0;
@@ -377,6 +475,19 @@ CPathFind::PreparePathData(void)
printf("ILLEGAL BLOCK. MORE THAN 1 INTERNALS AND NOT 2 EXTERNALS (Modelindex:%d)\n", i);
}
+ int numExternDetached, numInternDetached;
+ for(i = 0; i < NUMDETACHED_CARS; i++){
+ numExternDetached = 0;
+ numInternDetached = 0;
+ for(j = 0; j < 12; j++){
+ if(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern)
+ numExternDetached++;
+ if(DetachedInfoForTilePeds[i*12 + j].type == NodeTypeIntern)
+ numInternDetached++;
+ }
+ // no diagnostic here
+ }
+
for(i = 0; i < PATHNODESIZE; i++)
for(j = 0; j < 12; j++)
if(InfoForTileCars[i*12 + j].type == NodeTypeExtern){
@@ -388,52 +499,24 @@ CPathFind::PreparePathData(void)
if(InfoForTileCars[i*12 + j].numLeftLanes + InfoForTileCars[i*12 + j].numRightLanes <= 0)
printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i);
}
+ for(i = 0; i < NUMDETACHED_CARS; i++)
+ for(j = 0; j < 12; j++)
+ if(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern){
+ // MI:%d here but no argument for it
+ if(DetachedInfoForTileCars[i*12 + j].numLeftLanes < 0)
+ printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i);
+ if(DetachedInfoForTileCars[i*12 + j].numRightLanes < 0)
+ printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i);
+ if(DetachedInfoForTileCars[i*12 + j].numLeftLanes + DetachedInfoForTileCars[i*12 + j].numRightLanes <= 0)
+ printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i);
+ }
m_numPathNodes = 0;
- PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, NUMDETACHED_CARS);
+ PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedInfoForTileCars, NumDetachedCarNodeGroups);
m_numCarPathNodes = m_numPathNodes;
- PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, NUMDETACHED_PEDS);
+ PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedInfoForTilePeds, NumDetachedPedNodeGroups);
m_numPedPathNodes = m_numPathNodes - m_numCarPathNodes;
- // TODO: figure out what exactly is going on here
- // Some roads seem to get a west/east flag
- for(i = 0; i < m_numMapObjects; i++){
- numExtern = 0;
- numIntern = 0;
- numLanes = 0;
- maxX = 0.0f;
- maxY = 0.0f;
- for(j = 0; j < 12; j++){
- k = i*12 + j;
- if(InfoForTileCars[k].type == NodeTypeExtern){
- numExtern++;
- if(InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes > numLanes)
- numLanes = InfoForTileCars[k].numLeftLanes + InfoForTileCars[k].numRightLanes;
- maxX = Max(maxX, Abs(InfoForTileCars[k].x));
- maxY = Max(maxY, Abs(InfoForTileCars[k].y));
- }else if(InfoForTileCars[k].type == NodeTypeIntern)
- numIntern++;
- }
-
- if(numIntern == 1 && numExtern == 2){
- if(numLanes < 4){
- if((i & 7) == 4){ // WHAT?
- m_objectFlags[i] |= UseInRoadBlock;
- if(maxX > maxY)
- m_objectFlags[i] |= ObjectEastWest;
- else
- m_objectFlags[i] &= ~ObjectEastWest;
- }
- }else{
- m_objectFlags[i] |= UseInRoadBlock;
- if(maxX > maxY)
- m_objectFlags[i] |= ObjectEastWest;
- else
- m_objectFlags[i] &= ~ObjectEastWest;
- }
- }
- }
-
delete[] tempNodes;
CountFloodFillGroups(PATH_CAR);
@@ -444,14 +527,17 @@ CPathFind::PreparePathData(void)
delete[] InfoForTilePeds;
InfoForTilePeds = nil;
- delete[] DetachedNodesCars;
- DetachedNodesCars = nil;
- delete[] DetachedNodesPeds;
- DetachedNodesPeds = nil;
+ delete[] DetachedInfoForTileCars;
+ DetachedInfoForTileCars = nil;
+ delete[] DetachedInfoForTilePeds;
+ DetachedInfoForTilePeds = nil;
+ delete[] TempExternalNodes;
+ TempExternalNodes = nil;
}
printf("Done with PreparePathData\n");
}
+//--MIAMI: done
/* String together connected nodes in a list by a flood fill algorithm */
void
CPathFind::CountFloodFillGroups(uint8 type)
@@ -494,8 +580,8 @@ CPathFind::CountFloodFillGroups(uint8 type)
if(node->numLinks == 0){
if(type == PATH_CAR)
- printf("Single car node: %f %f %f (%d)\n",
- node->GetX(), node->GetY(), node->GetZ(), m_mapObjects[node->objectIndex]->GetModelIndex());
+ printf("Single car node: %f %f %f\n",
+ node->GetX(), node->GetY(), node->GetZ());
else
printf("Single ped node: %f %f %f\n",
node->GetX(), node->GetY(), node->GetZ());
@@ -523,34 +609,31 @@ CPathFind::CountFloodFillGroups(uint8 type)
int32 TempListLength;
+//--MIAMI: done
void
CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,
- float maxdist, CTempDetachedNode *detachednodes, int numDetached)
+ float maxdist, CPathInfoForObject *detachednodes, int numDetached)
{
static CVector CoorsXFormed;
- int i, j, k, l;
+ int i, j, k;
int l1, l2;
int start;
float posx, posy;
float dx, dy, mag;
float nearestDist;
int nearestId;
- int next;
int oldNumPathNodes, oldNumLinks;
float dist;
int iseg, jseg;
- int istart, jstart;
int done, cont;
int tileStart;
oldNumPathNodes = m_numPathNodes;
oldNumLinks = m_numConnections;
-#define OBJECTINDEX(n) (m_pathNodes[(n)].objectIndex)
- // Initialize map objects
- for(i = 0; i < m_numMapObjects; i++)
- for(j = 0; j < 12; j++)
- m_mapObjects[i]->m_nodeIndices[type][j] = -1;
+#define OBJECTINDEX(n) (mapObjIndices[(n)])
+ int16 *mapObjIndices = new int16[NUM_PATHNODES];
+ NumTempExternalNodes = 0;
// Calculate internal nodes, store them and connect them to defining object
for(i = 0; i < m_numMapObjects; i++){
@@ -566,89 +649,125 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
&CoorsXFormed);
m_pathNodes[m_numPathNodes].SetPosition(CoorsXFormed);
OBJECTINDEX(m_numPathNodes) = i;
- m_pathNodes[m_numPathNodes].unkBits = 1;
- m_mapObjects[i]->m_nodeIndices[type][j] = m_numPathNodes;
+ m_pathNodes[m_numPathNodes].width = objectpathinfo[start + j].width;
+ m_pathNodes[m_numPathNodes].speedLimit = objectpathinfo[start + j].speedLimit;
+ m_pathNodes[m_numPathNodes].spawnRate = objectpathinfo[start + j].spawnRate;
+ m_pathNodes[m_numPathNodes].bUseInRoadBlock = objectpathinfo[start + j].roadBlock;
+ m_pathNodes[m_numPathNodes].bDisabled = objectpathinfo[start + j].disabled;
+ m_pathNodes[m_numPathNodes].bWaterPath = objectpathinfo[start + j].waterPath;
+ m_pathNodes[m_numPathNodes].bOnlySmallBoats = objectpathinfo[start + j].onlySmallBoats;
+ m_pathNodes[m_numPathNodes].bBetweenLevels = objectpathinfo[start + j].betweenLevels;
m_numPathNodes++;
}
+ else if(objectpathinfo[start + j].type == NodeTypeExtern){
+ CalcNodeCoors(
+ objectpathinfo[start + j].x,
+ objectpathinfo[start + j].y,
+ objectpathinfo[start + j].z,
+ i,
+ &CoorsXFormed);
+ TempExternalNodes[NumTempExternalNodes].pos = CoorsXFormed;
+ assert(objectpathinfo[start + j].next >= 0);
+ TempExternalNodes[NumTempExternalNodes].next = tileStart + objectpathinfo[start + j].next;
+ TempExternalNodes[NumTempExternalNodes].numLeftLanes = objectpathinfo[start + j].numLeftLanes;
+ TempExternalNodes[NumTempExternalNodes].numRightLanes = objectpathinfo[start + j].numRightLanes;
+ TempExternalNodes[NumTempExternalNodes].width = objectpathinfo[start + j].width;
+ TempExternalNodes[NumTempExternalNodes].isCross = !!objectpathinfo[start + j].crossing;
+ NumTempExternalNodes++;
+ }
}
}
+ // Same thing for detached nodes
+ for(i = 0; i < numDetached; i++){
+ tileStart = m_numPathNodes;
+ start = 12*i;
+ for(j = 0; j < 12; j++){
+ if(detachednodes[start + j].type == NodeTypeIntern){
+ CVector pos;
+ pos.x = detachednodes[start + j].x;
+ pos.y = detachednodes[start + j].y;
+ pos.z = detachednodes[start + j].z;
+ m_pathNodes[m_numPathNodes].SetPosition(pos);
+ mapObjIndices[m_numPathNodes] = -(i+1);
+ m_pathNodes[m_numPathNodes].width = detachednodes[start + j].width;
+ m_pathNodes[m_numPathNodes].speedLimit = detachednodes[start + j].speedLimit;
+ m_pathNodes[m_numPathNodes].spawnRate = detachednodes[start + j].spawnRate;
+ m_pathNodes[m_numPathNodes].bUseInRoadBlock = detachednodes[start + j].roadBlock;
+ m_pathNodes[m_numPathNodes].bDisabled = detachednodes[start + j].disabled;
+ m_pathNodes[m_numPathNodes].bWaterPath = detachednodes[start + j].waterPath;
+ m_pathNodes[m_numPathNodes].bOnlySmallBoats = detachednodes[start + j].onlySmallBoats;
+ m_pathNodes[m_numPathNodes].bBetweenLevels = detachednodes[start + j].betweenLevels;
+ m_numPathNodes++;
+ }else if(detachednodes[start + j].type == NodeTypeExtern){
+ TempExternalNodes[NumTempExternalNodes].pos.x = detachednodes[start + j].x;
+ TempExternalNodes[NumTempExternalNodes].pos.y = detachednodes[start + j].y;
+ TempExternalNodes[NumTempExternalNodes].pos.z = detachednodes[start + j].z;
+ assert(detachednodes[start + j].next >= 0);
+ TempExternalNodes[NumTempExternalNodes].next = tileStart + detachednodes[start + j].next;
+ TempExternalNodes[NumTempExternalNodes].numLeftLanes = detachednodes[start + j].numLeftLanes;
+ TempExternalNodes[NumTempExternalNodes].numRightLanes = detachednodes[start + j].numRightLanes;
+ TempExternalNodes[NumTempExternalNodes].width = detachednodes[start + j].width;
+ TempExternalNodes[NumTempExternalNodes].isCross = !!detachednodes[start + j].crossing;
+ NumTempExternalNodes++;
+ }
+ }
+ }
// Insert external nodes into TempList
TempListLength = 0;
- for(i = 0; i < m_numMapObjects; i++){
- start = 12 * m_mapObjects[i]->GetModelIndex();
- for(j = 0; j < 12; j++){
- if(objectpathinfo[start + j].type != NodeTypeExtern)
+ for(i = 0; i < NumTempExternalNodes; i++){
+ // find closest unconnected node
+ nearestId = -1;
+ nearestDist = maxdist;
+ for(k = 0; k < TempListLength; k++){
+ if(tempnodes[k].linkState != 1)
continue;
- CalcNodeCoors(
- objectpathinfo[start + j].x,
- objectpathinfo[start + j].y,
- objectpathinfo[start + j].z,
- i,
- &CoorsXFormed);
-
- // find closest unconnected node
- nearestId = -1;
- nearestDist = maxdist;
- for(k = 0; k < TempListLength; k++){
- if(tempnodes[k].linkState != 1)
- continue;
- dx = tempnodes[k].pos.x - CoorsXFormed.x;
- if(Abs(dx) < nearestDist){
- dy = tempnodes[k].pos.y - CoorsXFormed.y;
- if(Abs(dy) < nearestDist){
- nearestDist = Max(Abs(dx), Abs(dy));
- nearestId = k;
- }
+ dx = tempnodes[k].pos.x - TempExternalNodes[i].pos.x;
+ if(Abs(dx) < nearestDist){
+ dy = tempnodes[k].pos.y - TempExternalNodes[i].pos.y;
+ if(Abs(dy) < nearestDist){
+ nearestDist = Max(Abs(dx), Abs(dy));
+ nearestId = k;
}
}
+ }
- if(nearestId < 0){
- // None found, add this one to temp list
- tempnodes[TempListLength].pos = CoorsXFormed;
- next = objectpathinfo[start + j].next;
- if(next < 0){
- // no link from this node, find link to this node
- next = 0;
- for(k = start; j != objectpathinfo[k].next; k++)
- next++;
- }
- // link to connecting internal node
- tempnodes[TempListLength].link1 = m_mapObjects[i]->m_nodeIndices[type][next];
- if(type == PATH_CAR){
- tempnodes[TempListLength].numLeftLanes = objectpathinfo[start + j].numLeftLanes;
- tempnodes[TempListLength].numRightLanes = objectpathinfo[start + j].numRightLanes;
- }
- tempnodes[TempListLength++].linkState = 1;
- }else{
- // Found nearest, connect it to our neighbour
- next = objectpathinfo[start + j].next;
- if(next < 0){
- // no link from this node, find link to this node
- next = 0;
- for(k = start; j != objectpathinfo[k].next; k++)
- next++;
- }
- tempnodes[nearestId].link2 = m_mapObjects[i]->m_nodeIndices[type][next];
- tempnodes[nearestId].linkState = 2;
-
- // collapse this node with nearest we found
- dx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX();
- dy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY();
- tempnodes[nearestId].pos = (tempnodes[nearestId].pos + CoorsXFormed)*0.5f;
- mag = Sqrt(dx*dx + dy*dy);
- tempnodes[nearestId].dirX = dx/mag;
- tempnodes[nearestId].dirY = dy/mag;
- // do something when number of lanes doesn't agree
- if(type == PATH_CAR)
- if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 &&
- (objectpathinfo[start + j].numLeftLanes == 0 || objectpathinfo[start + j].numRightLanes == 0)){
- // why switch left and right here?
- tempnodes[nearestId].numLeftLanes = objectpathinfo[start + j].numRightLanes;
- tempnodes[nearestId].numRightLanes = objectpathinfo[start + j].numLeftLanes;
- }
+ if(nearestId < 0){
+ // None found, add this one to temp list
+ tempnodes[TempListLength].pos = TempExternalNodes[i].pos;
+ // link to connecting internal node
+ tempnodes[TempListLength].link1 = TempExternalNodes[i].next;
+ if(type == PATH_CAR){
+ tempnodes[TempListLength].numLeftLanes = TempExternalNodes[i].numLeftLanes;
+ tempnodes[TempListLength].numRightLanes = TempExternalNodes[i].numRightLanes;
}
+ tempnodes[TempListLength].width = TempExternalNodes[i].width;
+ tempnodes[TempListLength].isCross = TempExternalNodes[i].isCross;
+ tempnodes[TempListLength++].linkState = 1;
+ }else{
+ // Found nearest, connect it to our neighbour
+ tempnodes[nearestId].link2 = TempExternalNodes[i].next;
+ tempnodes[nearestId].linkState = 2;
+
+ // collapse this node with nearest we found
+ dx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX();
+ dy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY();
+ tempnodes[nearestId].pos = (tempnodes[nearestId].pos + TempExternalNodes[i].pos)*0.5f;
+ mag = Sqrt(dx*dx + dy*dy);
+ tempnodes[nearestId].dirX = dx/mag * 100;
+ tempnodes[nearestId].dirY = dy/mag * 100;
+ tempnodes[nearestId].width = Max(tempnodes[nearestId].width, TempExternalNodes[i].width);
+ if(TempExternalNodes[i].isCross)
+ tempnodes[nearestId].isCross = true; // TODO: is this guaranteed to be false otherwise?
+ // do something when number of lanes doesn't agree
+ if(type == PATH_CAR)
+ if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 &&
+ (TempExternalNodes[i].numLeftLanes == 0 || TempExternalNodes[i].numRightLanes == 0)){
+ // why switch left and right here?
+ tempnodes[nearestId].numLeftLanes = TempExternalNodes[i].numRightLanes;
+ tempnodes[nearestId].numRightLanes = TempExternalNodes[i].numLeftLanes;
+ }
}
}
@@ -673,27 +792,30 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
continue;
dist = (m_pathNodes[i].GetPosition() - m_pathNodes[ConnectedNode(m_numConnections)].GetPosition()).Magnitude();
- m_distances[m_numConnections] = dist;
- m_connectionFlags[m_numConnections].flags = 0;
+ m_distances[m_numConnections] = Min(dist, 255);
+ if(tempnodes[j].isCross)
+ m_connections[j] |= 0x8000; // crosses road flag
if(type == PATH_CAR){
// IMPROVE: use a goto here
// Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){
- if(m_carPathLinks[k].dir.x == tempnodes[j].dirX &&
- m_carPathLinks[k].dir.y == tempnodes[j].dirY &&
- m_carPathLinks[k].pos.x == tempnodes[j].pos.x &&
- m_carPathLinks[k].pos.y == tempnodes[j].pos.y){
+ if(m_carPathLinks[k].dirX == tempnodes[j].dirX &&
+ m_carPathLinks[k].dirY == tempnodes[j].dirY &&
+ m_carPathLinks[k].x == (int)(tempnodes[j].pos.x*8.0f) &&
+ m_carPathLinks[k].y == (int)(tempnodes[j].pos.y*8.0f)){
m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks;
}
}
// k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){
- m_carPathLinks[m_numCarPathLinks].dir.x = tempnodes[j].dirX;
- m_carPathLinks[m_numCarPathLinks].dir.y = tempnodes[j].dirY;
- m_carPathLinks[m_numCarPathLinks].pos.x = tempnodes[j].pos.x;
- m_carPathLinks[m_numCarPathLinks].pos.y = tempnodes[j].pos.y;
+ m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX;
+ m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY;
+ m_carPathLinks[m_numCarPathLinks].x = tempnodes[j].pos.x*8.0f;
+ m_carPathLinks[m_numCarPathLinks].y = tempnodes[j].pos.y*8.0f;
+ m_carPathLinks[m_numCarPathLinks].flag1 = false;
+ m_carPathLinks[m_numCarPathLinks].width = tempnodes[j].width;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes;
m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes;
@@ -707,6 +829,18 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
m_numConnections++;
}
+ CPathInfoForObject *tile;
+ if(mapObjIndices[i] < 0){
+ if(type == PATH_CAR)
+ tile = &DetachedInfoForTileCars[12 * (-1 - mapObjIndices[i])];
+ else
+ tile = &DetachedInfoForTilePeds[12 * (-1 - mapObjIndices[i])];
+ }else{
+ if(type == PATH_CAR)
+ tile = &InfoForTileCars[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()];
+ else
+ tile = &InfoForTilePeds[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()];
+ }
// Find i inside path segment
iseg = 0;
@@ -714,7 +848,6 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
if(OBJECTINDEX(j) == OBJECTINDEX(i))
iseg++;
- istart = 12 * m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex();
// Add links to other internal nodes
for(j = Max(oldNumPathNodes, i-12); j < Min(m_numPathNodes, i+12); j++){
if(OBJECTINDEX(i) != OBJECTINDEX(j) || i == j)
@@ -722,14 +855,13 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// N.B.: in every path segment, the externals have to be at the end
jseg = j-i + iseg;
- jstart = 12 * m_mapObjects[m_pathNodes[j].objectIndex]->GetModelIndex();
- if(objectpathinfo[istart + iseg].next == jseg ||
- objectpathinfo[jstart + jseg].next == iseg){
+ if(tile[iseg].next == jseg ||
+ tile[jseg].next == iseg){
// Found a link between i and jConnectionSetCrossesRoad
// NB this clears the flags in MIAMI
m_connections[m_numConnections] = j;
dist = (m_pathNodes[i].GetPosition() - m_pathNodes[j].GetPosition()).Magnitude();
- m_distances[m_numConnections] = dist;
+ m_distances[m_numConnections] = Min(dist, 255);
if(type == PATH_CAR){
posx = (m_pathNodes[i].GetX() + m_pathNodes[j].GetX())*0.5f;
@@ -739,6 +871,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
mag = Sqrt(dx*dx + dy*dy);
dx /= mag;
dy /= mag;
+ int width = Max(m_pathNodes[i].width, m_pathNodes[j].width);
if(i < j){
dx = -dx;
dy = -dy;
@@ -746,20 +879,22 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// IMPROVE: use a goto here
// Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){
- if(m_carPathLinks[k].dir.x == dx &&
- m_carPathLinks[k].dir.y == dy &&
- m_carPathLinks[k].pos.x == posx &&
- m_carPathLinks[k].pos.y == posy){
+ if(m_carPathLinks[k].dirX == (int)(dx*100.0f) &&
+ m_carPathLinks[k].dirY == (int)(dy*100.0f) &&
+ m_carPathLinks[k].x == (int)(posx*8.0f) &&
+ m_carPathLinks[k].y == (int)(posy*8.0f)){
m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks;
}
}
// k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){
- m_carPathLinks[m_numCarPathLinks].dir.x = dx;
- m_carPathLinks[m_numCarPathLinks].dir.y = dy;
- m_carPathLinks[m_numCarPathLinks].pos.x = posx;
- m_carPathLinks[m_numCarPathLinks].pos.y = posy;
+ m_carPathLinks[m_numCarPathLinks].dirX = dx*100.0f;
+ m_carPathLinks[m_numCarPathLinks].dirY = dy*100.0f;
+ m_carPathLinks[m_numCarPathLinks].x = posx*8.0f;
+ m_carPathLinks[m_numCarPathLinks].y = posy*8.0f;
+ m_carPathLinks[m_numCarPathLinks].flag1 = false;
+ m_carPathLinks[m_numCarPathLinks].width = width;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1;
m_carPathLinks[m_numCarPathLinks].numRightLanes = -1;
@@ -769,11 +904,9 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
}
}else{
// Crosses road
- if(objectpathinfo[istart + iseg].next == jseg && objectpathinfo[istart + iseg].crossing ||
- objectpathinfo[jstart + jseg].next == iseg && objectpathinfo[jstart + jseg].crossing)
- m_connectionFlags[m_numConnections].bCrossesRoad = true;
- else
- m_connectionFlags[m_numConnections].bCrossesRoad = false;
+ if(tile[iseg].next == jseg && tile[iseg].crossing ||
+ tile[jseg].next == iseg && tile[jseg].crossing)
+ m_connections[m_numConnections] |= 0x8000; // crosses road flag
}
m_pathNodes[i].numLinks++;
@@ -786,7 +919,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
done = 0;
// Set number of lanes for all nodes somehow
// very strange code
- for(k = 0; !done && k < 10; k++){
+ for(k = 0; !done && k < 12; k++){
done = 1;
for(i = 0; i < m_numPathNodes; i++){
if(m_pathNodes[i].numLinks != 2)
@@ -794,33 +927,50 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
l1 = m_carPathConnections[m_pathNodes[i].firstLink];
l2 = m_carPathConnections[m_pathNodes[i].firstLink+1];
- if(m_carPathLinks[l1].numLeftLanes == -1 &&
- m_carPathLinks[l2].numLeftLanes != -1){
+ int8 l1Left = m_carPathLinks[l1].numLeftLanes;
+ int8 l1Right = m_carPathLinks[l1].numRightLanes;
+ int8 l2Left = m_carPathLinks[l2].numLeftLanes;
+ int8 l2Right = m_carPathLinks[l2].numRightLanes;
+ int8 *l1Leftp, *l1Rightp;
+ int8 *l2Leftp, *l2Rightp;
+ if(m_carPathLinks[l1].pathNodeIndex == i){
+ l1Leftp = &l1Left;
+ l1Rightp = &l1Right;
+ }else{
+ l1Leftp = &l1Right;
+ l1Rightp = &l1Left;
+ }
+ if(m_carPathLinks[l2].pathNodeIndex == i){
+ l2Leftp = &l2Left;
+ l2Rightp = &l2Right;
+ }else{
+ l2Leftp = &l2Right;
+ l2Rightp = &l2Left;
+ }
+ if(*l1Leftp == -1 && *l2Rightp != -1){
+ *l1Leftp = *l2Rightp;
done = 0;
- if(m_carPathLinks[l2].pathNodeIndex == i){
- // why switch left and right here?
- m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numRightLanes;
- m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numLeftLanes;
- }else{
- m_carPathLinks[l1].numLeftLanes = m_carPathLinks[l2].numLeftLanes;
- m_carPathLinks[l1].numRightLanes = m_carPathLinks[l2].numRightLanes;
- }
- m_carPathLinks[l1].pathNodeIndex = i;
- }else if(m_carPathLinks[l1].numLeftLanes != -1 &&
- m_carPathLinks[l2].numLeftLanes == -1){
+ }
+ if(*l1Rightp == -1 && *l2Leftp != -1){
+ *l1Rightp = *l2Leftp;
done = 0;
- if(m_carPathLinks[l1].pathNodeIndex == i){
- // why switch left and right here?
- m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numRightLanes;
- m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numLeftLanes;
- }else{
- m_carPathLinks[l2].numLeftLanes = m_carPathLinks[l1].numLeftLanes;
- m_carPathLinks[l2].numRightLanes = m_carPathLinks[l1].numRightLanes;
- }
- m_carPathLinks[l2].pathNodeIndex = i;
- }else if(m_carPathLinks[l1].numLeftLanes == -1 &&
- m_carPathLinks[l2].numLeftLanes == -1)
+ }
+ if(*l2Leftp == -1 && *l1Rightp != -1){
+ *l2Leftp = *l1Rightp;
+ done = 0;
+ }
+ if(*l2Rightp == -1 && *l1Leftp != -1){
+ *l2Rightp = *l1Leftp;
+ done = 0;
+ }
+ if(*l1Leftp == -1 && *l2Rightp == -1)
done = 0;
+ if(*l2Leftp == -1 && *l1Rightp == -1)
+ done = 0;
+ m_carPathLinks[l1].numLeftLanes = l1Left;
+ m_carPathLinks[l1].numRightLanes = l1Right;
+ m_carPathLinks[l2].numLeftLanes = l2Left;
+ m_carPathLinks[l2].numRightLanes = l2Right;
}
}
@@ -828,10 +978,10 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
for(i = 0; i < m_numPathNodes; i++)
for(j = 0; j < m_pathNodes[i].numLinks; j++){
k = m_carPathConnections[m_pathNodes[i].firstLink + j];
- if(m_carPathLinks[k].numLeftLanes < 0)
- m_carPathLinks[k].numLeftLanes = 1;
- if(m_carPathLinks[k].numRightLanes < 0)
- m_carPathLinks[k].numRightLanes = 1;
+ if(m_carPathLinks[k].numLeftLanes == -1)
+ m_carPathLinks[k].numLeftLanes = 0;
+ if(m_carPathLinks[k].numRightLanes == -1)
+ m_carPathLinks[k].numRightLanes = 0;
}
}
@@ -840,8 +990,6 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
do{
cont = 0;
for(i = 0; i < m_numPathNodes; i++){
- m_pathNodes[i].bDisabled = false;
- m_pathNodes[i].bBetweenLevels = false;
// See if node is a dead end, if so, we're not done yet
if(!m_pathNodes[i].bDeadEnd){
k = 0;
@@ -874,23 +1022,14 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
m_connections[j] = node-1;
}
- // Also in treadables
- for(j = 0; j < m_numMapObjects; j++)
- for(k = 0; k < 12; k++){
- if(m_mapObjects[j]->m_nodeIndices[PATH_PED][k] == i){
- // remove this one
- for(l = k; l < 12-1; l++)
- m_mapObjects[j]->m_nodeIndices[PATH_PED][l] = m_mapObjects[j]->m_nodeIndices[PATH_PED][l+1];
- m_mapObjects[j]->m_nodeIndices[PATH_PED][11] = -1;
- }else if(m_mapObjects[j]->m_nodeIndices[PATH_PED][k] > i)
- m_mapObjects[j]->m_nodeIndices[PATH_PED][k]--;
- }
-
i--;
m_numPathNodes--;
}
+
+ delete[] mapObjIndices;
}
+//--MIAMI: done
float
CPathFind::CalcRoadDensity(float x, float y)
{
@@ -907,21 +1046,13 @@ CPathFind::CalcRoadDensity(float x, float y)
next = m_carPathConnections[m_pathNodes[i].firstLink + j];
density += m_carPathLinks[next].numLeftLanes * dist;
density += m_carPathLinks[next].numRightLanes * dist;
-
- if(m_carPathLinks[next].numLeftLanes < 0)
- printf("Link from object %d to %d (MIs)\n",
- m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex(),
- m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex());
- if(m_carPathLinks[next].numRightLanes < 0)
- printf("Link from object %d to %d (MIs)\n",
- m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex(),
- m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex());
}
}
}
return density/2500.0f;
}
+//--MIAMI: done
bool
CPathFind::TestForPedTrafficLight(CPathNode *n1, CPathNode *n2)
{
@@ -932,6 +1063,7 @@ CPathFind::TestForPedTrafficLight(CPathNode *n1, CPathNode *n2)
return false;
}
+//--MIAMI: done
bool
CPathFind::TestCrossesRoad(CPathNode *n1, CPathNode *n2)
{
@@ -942,6 +1074,7 @@ CPathFind::TestCrossesRoad(CPathNode *n1, CPathNode *n2)
return false;
}
+//--MIAMI: done
void
CPathFind::AddNodeToList(CPathNode *node, int32 listId)
{
@@ -954,6 +1087,7 @@ CPathFind::AddNodeToList(CPathNode *node, int32 listId)
node->distance = listId;
}
+//--MIAMI: done
void
CPathFind::RemoveNodeFromList(CPathNode *node)
{
@@ -962,6 +1096,7 @@ CPathFind::RemoveNodeFromList(CPathNode *node)
node->GetNext()->SetPrev(node->GetPrev());
}
+//--MIAMI: done
void
CPathFind::RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n)
{
@@ -975,6 +1110,7 @@ CPathFind::RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n)
}
}
+#ifdef GTA_BRIDGE
void
CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool enable)
{
@@ -986,7 +1122,9 @@ CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool ena
m_carPathLinks[i].bBridgeLights = enable;
}
}
+#endif
+//--MIAMI: done
void
CPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable)
{
@@ -1002,6 +1140,7 @@ CPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable)
}
}
+//--MIAMI: done
void
CPathFind::SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable)
{
@@ -1017,6 +1156,7 @@ CPathFind::SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1
}
}
+//--MIAMI: done
void
CPathFind::SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable)
{
@@ -1032,6 +1172,7 @@ CPathFind::SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float
}
}
+//--MIAMI: unused (still needed for script here)
void
CPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float y2, float z2, float length, uint8 type, uint8 mode)
{
@@ -1083,6 +1224,7 @@ CPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float
}
}
+//--MIAMI: unused (still needed for script here)
void
CPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId)
{
@@ -1098,6 +1240,7 @@ CPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId)
}
}
+//--MIAMI: unused (still needed for script here)
void
CPathFind::MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2)
{
@@ -1112,6 +1255,7 @@ CPathFind::MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2,
}
}
+//--MIAMI: unused (still needed for script here)
void
CPathFind::PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2)
{
@@ -1126,8 +1270,9 @@ CPathFind::PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y
}
}
+//--MIAMI: done
int32
-CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels)
+CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, bool ignoreFlagB4, bool bWaterPath)
{
int i;
int firstNode, lastNode;
@@ -1149,22 +1294,20 @@ CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bo
for(i = firstNode; i < lastNode; i++){
if(ignoreDisabled && m_pathNodes[i].bDisabled) continue;
if(ignoreBetweenLevels && m_pathNodes[i].bBetweenLevels) continue;
- switch(m_pathNodes[i].unkBits){
- case 1:
- case 2:
- dist = Abs(m_pathNodes[i].GetX() - coors.x) +
- Abs(m_pathNodes[i].GetY() - coors.y) +
- 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
- if(dist < closestDist){
- closestDist = dist;
- closestNode = i;
- }
- break;
+ if(ignoreFlagB4 && m_pathNodes[i].flagB4) continue;
+ if(bWaterPath != m_pathNodes[i].bWaterPath) continue;
+ dist = Abs(m_pathNodes[i].GetX() - coors.x) +
+ Abs(m_pathNodes[i].GetY() - coors.y) +
+ 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ if(dist < closestDist){
+ closestDist = dist;
+ closestNode = i;
}
}
return closestDist < distLimit ? closestNode : -1;
}
+//--MIAMI: done
int32
CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY)
{
@@ -1187,27 +1330,23 @@ CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, floa
}
for(i = firstNode; i < lastNode; i++){
- switch(m_pathNodes[i].unkBits){
- case 1:
- case 2:
- dX = m_pathNodes[i].GetX() - coors.x;
- dY = m_pathNodes[i].GetY() - coors.y;
- dist = Abs(dX) + Abs(dY) +
- 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ dX = m_pathNodes[i].GetX() - coors.x;
+ dY = m_pathNodes[i].GetY() - coors.y;
+ dist = Abs(dX) + Abs(dY) +
+ 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);
+ if(dist < closestDist){
+ NormalizeXY(dX, dY);
+ dist -= (dX*dirX + dY*dirY - 1.0f)*20.0f;
if(dist < closestDist){
- NormalizeXY(dX, dY);
- dist -= (dX*dirX + dY*dirY - 1.0f)*20.0f;
- if(dist < closestDist){
- closestDist = dist;
- closestNode = i;
- }
+ closestDist = dist;
+ closestNode = i;
}
- break;
}
}
return closestNode;
}
+//--MIAMI: done
float
CPathFind::FindNodeOrientationForCarPlacement(int32 nodeId)
{
@@ -1219,6 +1358,7 @@ CPathFind::FindNodeOrientationForCarPlacement(int32 nodeId)
return RADTODEG(dir.Heading());
}
+//--MIAMI: unused (still needed for script here)
float
CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards)
{
@@ -1262,6 +1402,8 @@ CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, flo
return RADTODEG(dir.Heading());
}
+// no "New" in MIAMI
+//--MIAMI: TODO
bool
CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled)
{
@@ -1277,14 +1419,14 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY,
if(m_pathNodes[node1].bDisabled && !ignoreDisabled)
continue;
dist1 = Distance2D(m_pathNodes[node1].GetPosition(), x, y);
- if(dist1 < spawnDist + 60.0f){
- d1 = dist1 - spawnDist;
+ if(dist1 < Max(spawnDist + 70.0f, spawnDist * 1.7f)){
+ d1 = m_pathNodes[node1].bWaterPath ? (dist1 - spawnDist * 1.5f) : (dist1 - spawnDist);
for(j = 0; j < m_pathNodes[node1].numLinks; j++){
node2 = ConnectedNode(m_pathNodes[node1].firstLink + j);
if(m_pathNodes[node2].bDisabled && !ignoreDisabled)
continue;
dist2 = Distance2D(m_pathNodes[node2].GetPosition(), x, y);
- d2 = dist2 - spawnDist;
+ d2 = m_pathNodes[node2].bWaterPath ? (dist2 - spawnDist * 1.5f) : (dist2 - spawnDist);
if(d1*d2 < 0.0f){
// nodes are on different sides of spawn distance
float f2 = Abs(d1)/(Abs(d1) + Abs(d2));
@@ -1316,6 +1458,7 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY,
return false;
}
+//--MIAMI: TODO
bool
CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix)
{
@@ -1375,42 +1518,7 @@ CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDi
return false;
}
-CTreadable*
-CPathFind::FindRoadObjectClosestToCoors(CVector coors, uint8 type)
-{
- int i, j, k;
- int node1, node2;
- CTreadable *closestMapObj = nil;
- float closestDist = 10000.0f;
-
- for(i = 0; i < m_numMapObjects; i++){
- CTreadable *mapObj = m_mapObjects[i];
- if(mapObj->m_nodeIndices[type][0] < 0)
- continue;
- CVector vDist = mapObj->GetPosition() - coors;
- float fDist = Abs(vDist.x) + Abs(vDist.y) + Abs(vDist.z);
- if(fDist < 200.0f || fDist < closestDist)
- for(j = 0; j < 12; j++){
- node1 = mapObj->m_nodeIndices[type][j];
- if(node1 < 0)
- break;
- // FIX: game uses ThePaths here explicitly
- for(k = 0; k < m_pathNodes[node1].numLinks; k++){
- node2 = ConnectedNode(m_pathNodes[node1].firstLink + k);
- float lineDist = CCollision::DistToLine(&m_pathNodes[node1].GetPosition(), &m_pathNodes[node2].GetPosition(), &coors);
- if(lineDist < closestDist){
- closestDist = lineDist;
- if((coors - m_pathNodes[node1].GetPosition()).MagnitudeSqr() < (coors - m_pathNodes[node2].GetPosition()).MagnitudeSqr())
- closestMapObj = m_mapObjects[m_pathNodes[node1].objectIndex];
- else
- closestMapObj = m_mapObjects[m_pathNodes[node2].objectIndex];
- }
- }
- }
- }
- return closestMapObj;
-}
-
+//--MIAMI: done
void
CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode, CPathNode **nextNode, uint8 curDir, uint8 *nextDir)
{
@@ -1418,19 +1526,8 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode
CPathNode *node;
if(lastNode == nil || (node = *lastNode) == nil || (coors - (*lastNode)->GetPosition()).MagnitudeSqr() > 7.0f){
- // need to find the node we're coming from
- node = nil;
- CTreadable *obj = FindRoadObjectClosestToCoors(coors, type);
- float nodeDist = 1000000000.0f;
- for(i = 0; i < 12; i++){
- if(obj->m_nodeIndices[type][i] < 0)
- break;
- float dist = (coors - m_pathNodes[obj->m_nodeIndices[type][i]].GetPosition()).MagnitudeSqr();
- if(dist < nodeDist){
- nodeDist = dist;
- node = &m_pathNodes[obj->m_nodeIndices[type][i]];
- }
- }
+ int32 nodeIdx = FindNodeClosestToCoors(coors, type, 999999.88f);
+ node = &m_pathNodes[nodeIdx];
}
CVector2D vCurDir(Sin(curDir*PI/4.0f), Cos(curDir * PI / 4.0f));
@@ -1486,8 +1583,9 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode
}
}
-static CPathNode *apNodesToBeCleared[4995];
+static CPathNode *apNodesToBeCleared[6525];
+//--MIAMI: done
void
CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *pNumNodes, int16 maxNumNodes, CVehicle *vehicle, float *pDist, float distLimit, int32 targetNodeId)
{
@@ -1503,42 +1601,22 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
}
// Find start
- int numPathsToTry;
- CTreadable *startObj;
- if(startNodeId < 0){
- if(vehicle == nil || (startObj = vehicle->m_treadable[type]) == nil)
- startObj = FindRoadObjectClosestToCoors(start, type);
- numPathsToTry = 0;
- for(i = 0; i < 12; i++){
- if(startObj->m_nodeIndices[type][i] < 0)
- break;
- if(m_pathNodes[startObj->m_nodeIndices[type][i]].group == m_pathNodes[targetNodeId].group)
- numPathsToTry++;
- }
- }else{
- numPathsToTry = 1;
- startObj = m_mapObjects[m_pathNodes[startNodeId].objectIndex];
- }
- if(numPathsToTry == 0) {
+ if(startNodeId < 0)
+ startNodeId = FindNodeClosestToCoors(start, type, 999999.88f);
+ if(startNodeId < 0) {
*pNumNodes = 0;
if(pDist) *pDist = 100000.0f;
return;
}
-
- if(startNodeId < 0){
- // why only check node 0?
- if(m_pathNodes[startObj->m_nodeIndices[type][0]].group !=
- m_pathNodes[targetNodeId].group) {
- *pNumNodes = 0;
- if(pDist) *pDist = 100000.0f;
- return;
- }
- }else{
- if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) {
- *pNumNodes = 0;
- if(pDist) *pDist = 100000.0f;
- return;
- }
+ if(startNodeId == targetNodeId){
+ *pNumNodes = 0;
+ if(pDist) *pDist = 0.0f;
+ return;
+ }
+ if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) {
+ *pNumNodes = 0;
+ if(pDist) *pDist = 100000.0f;
+ return;
}
for(i = 0; i < ARRAY_SIZE(m_searchNodes); i++)
@@ -1550,14 +1628,11 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
// Dijkstra's algorithm
// Find distances
int numPathsFound = 0;
- if(startNodeId < 0 && m_mapObjects[m_pathNodes[targetNodeId].objectIndex] == startObj)
- numPathsFound++;
- for(i = 0; numPathsFound < numPathsToTry; i = (i+1) & 0x1FF){
+ for(i = 0; numPathsFound == 0; i = (i+1) & 0x1FF){
CPathNode *node;
for(node = m_searchNodes[i].GetNext(); node; node = node->GetNext()){
- if(m_mapObjects[node->objectIndex] == startObj &&
- (startNodeId < 0 || node == &m_pathNodes[startNodeId]))
- numPathsFound++;
+ if(node == &m_pathNodes[startNodeId])
+ numPathsFound = 1;
for(j = 0; j < node->numLinks; j++){
int next = ConnectedNode(node->firstLink + j);
@@ -1577,34 +1652,12 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
// Find out whence to start tracing back
CPathNode *curNode;
- if(startNodeId < 0){
- int minDist = MAX_DIST;
- *pNumNodes = 1;
- for(i = 0; i < 12; i++){
- if(startObj->m_nodeIndices[type][i] < 0)
- break;
- int dist = (m_pathNodes[startObj->m_nodeIndices[type][i]].GetPosition() - start).Magnitude();
- if(m_pathNodes[startObj->m_nodeIndices[type][i]].distance + dist < minDist){
- minDist = m_pathNodes[startObj->m_nodeIndices[type][i]].distance + dist;
- curNode = &m_pathNodes[startObj->m_nodeIndices[type][i]];
- }
- }
- if(maxNumNodes == 0){
- *pNumNodes = 0;
- }else{
- nodes[0] = curNode;
- *pNumNodes = 1;
- }
- if(pDist)
- *pDist = minDist;
- }else
- {
- curNode = &m_pathNodes[startNodeId];
- *pNumNodes = 0;
- if(pDist)
- *pDist = m_pathNodes[startNodeId].distance;
- }
+ curNode = &m_pathNodes[startNodeId];
+ *pNumNodes = 0;
+ if(pDist)
+ *pDist = m_pathNodes[startNodeId].distance;
+ nodes[(*pNumNodes)++] = curNode;
// Trace back to target and update list of nodes
while(*pNumNodes < maxNumNodes && curNode != &m_pathNodes[targetNodeId])
for(i = 0; i < curNode->numLinks; i++){
@@ -1618,13 +1671,13 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta
for(i = 0; i < numNodesToBeCleared; i++)
apNodesToBeCleared[i]->distance = MAX_DIST;
- return;
}
static CPathNode *pNodeList[32];
static int16 DummyResult;
static int16 DummyResult2;
+//--MIAMI: done
bool
CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)
{
@@ -1635,11 +1688,12 @@ CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)
else
DoPathSearch(type, start, -1, target, nil, &DummyResult2, 0, nil, &dist, 50.0f, -1);
if(type == PATH_CAR)
- return dist < 160.0f;
+ return dist < 150.0f;
else
return dist < 100.0f;
}
+//--MIAMI: done
void
CPathFind::Save(uint8 *buf, uint32 *size)
{
@@ -1661,6 +1715,7 @@ CPathFind::Save(uint8 *buf, uint32 *size)
buf[i/8 + n] &= ~(1 << i%8);
}
+//--MIAMI: done
void
CPathFind::Load(uint8 *buf, uint32 size)
{
@@ -1805,3 +1860,23 @@ CPathFind::DisplayPathData(void)
}
}
}
+
+CPathNode*
+CPathFind::GetNode(int16 index)
+{
+ if(index < 0)
+ return nil;
+ if(index < ARRAY_SIZE(ThePaths.m_searchNodes))
+ return &ThePaths.m_searchNodes[index];
+ return &ThePaths.m_pathNodes[index - ARRAY_SIZE(ThePaths.m_searchNodes)];
+}
+int16
+CPathFind::GetIndex(CPathNode *node)
+{
+ if(node == nil)
+ return -1;
+ if(node >= &ThePaths.m_searchNodes[0] && node < &ThePaths.m_searchNodes[ARRAY_SIZE(ThePaths.m_searchNodes)])
+ return node - ThePaths.m_searchNodes;
+ else
+ return (node - ThePaths.m_pathNodes) + ARRAY_SIZE(ThePaths.m_searchNodes);
+}
diff --git a/src/control/PathFind.h b/src/control/PathFind.h
index bbfdf7b7..7abc455a 100644
--- a/src/control/PathFind.h
+++ b/src/control/PathFind.h
@@ -9,9 +9,6 @@ enum
{
NodeTypeExtern = 1,
NodeTypeIntern = 2,
-
- UseInRoadBlock = 1,
- ObjectEastWest = 2,
};
enum
@@ -56,31 +53,42 @@ public:
struct CPathNode
{
- CVector pos;
- CPathNode *prev;
- CPathNode *next;
+ int16 prevIndex;
+ int16 nextIndex;
+ int16 x;
+ int16 y;
+ int16 z;
int16 distance; // in path search
- int16 objectIndex;
int16 firstLink;
- uint8 numLinks;
+ int8 width;
+ int8 group;
- uint8 unkBits : 2;
+ uint8 numLinks : 4;
uint8 bDeadEnd : 1;
uint8 bDisabled : 1;
uint8 bBetweenLevels : 1;
-
- int8 group;
-
- CVector &GetPosition(void) { return pos; }
- void SetPosition(const CVector &p) { pos = p; }
- float GetX(void) { return pos.x; }
- float GetY(void) { return pos.y; }
- float GetZ(void) { return pos.z; }
-
- CPathNode *GetPrev(void) { return prev; }
- CPathNode *GetNext(void) { return next; }
- void SetPrev(CPathNode *node) { prev = node; }
- void SetNext(CPathNode *node) { next = node; }
+ uint8 bUseInRoadBlock : 1;
+
+ uint8 bWaterPath : 1;
+ uint8 bOnlySmallBoats : 1;
+ uint8 flagB4 : 1; // where is this set?
+ uint8 speedLimit : 2;
+ //uint8 flagB20 : 1;
+ //uint8 flagB40 : 1;
+ //uint8 flagB80 : 1;
+
+ uint8 spawnRate : 4;
+ uint8 flagsC : 4;
+
+ CVector GetPosition(void) { return CVector(x/8.0f, y/8.0f, z/8.0f); }
+ void SetPosition(const CVector &p) { x = p.x*8.0f; y = p.y*8.0f; z = p.z*8.0f; }
+ float GetX(void) { return x/8.0f; }
+ float GetY(void) { return y/8.0f; }
+ float GetZ(void) { return z/8.0f; }
+ CPathNode *GetPrev(void);
+ CPathNode *GetNext(void);
+ void SetPrev(CPathNode *node);
+ void SetNext(CPathNode *node);
};
union CConnectionFlags
@@ -94,22 +102,25 @@ union CConnectionFlags
struct CCarPathLink
{
- CVector2D pos;
- CVector2D dir;
+ int16 x;
+ int16 y;
int16 pathNodeIndex;
- int8 numLeftLanes;
- int8 numRightLanes;
- uint8 trafficLightType;
-
- uint8 bBridgeLights : 1;
- // more?
-
- CVector2D &GetPosition(void) { return pos; }
- CVector2D &GetDirection(void) { return dir; }
- float GetX(void) { return pos.x; }
- float GetY(void) { return pos.y; }
- float GetDirX(void) { return dir.x; }
- float GetDirY(void) { return dir.y; }
+ int8 dirX;
+ int8 dirY;
+ int8 numLeftLanes : 3;
+ int8 numRightLanes : 3;
+ uint8 flag1 : 1;
+ uint8 trafficLightType : 2;
+ uint8 bBridgeLights : 1; // at least in LCS...
+ int8 width;
+
+ CVector2D GetPosition(void) { return CVector2D(x/8.0f, y/8.0f); }
+ CVector2D GetDirection(void) { return CVector2D(dirX/100.0f, dirY/100.0f); }
+ float GetX(void) { return x/8.0f; }
+ float GetY(void) { return y/8.0f; }
+ float GetDirX(void) { return dirX/100.0f; }
+ float GetDirY(void) { return dirY/100.0f; }
+ float GetLaneOffset(void) { return width/80.0f; }
float OneWayLaneOffset()
{
@@ -117,21 +128,33 @@ struct CCarPathLink
return 0.5f - 0.5f * numRightLanes;
if (numRightLanes == 0)
return 0.5f - 0.5f * numLeftLanes;
- return 0.5f;
+ return 0.5f + GetLaneOffset();
}
};
// This is what we're reading from the files, only temporary
struct CPathInfoForObject
{
- int16 x;
- int16 y;
- int16 z;
+ float x;
+ float y;
+ float z;
int8 type;
int8 next;
int8 numLeftLanes;
int8 numRightLanes;
+ int8 speedLimit;
+ int8 width;
+
uint8 crossing : 1;
+ uint8 onlySmallBoats : 1;
+ uint8 roadBlock : 1;
+ uint8 disabled : 1;
+ uint8 waterPath : 1;
+ uint8 betweenLevels : 1;
+
+ uint8 spawnRate : 4;
+
+ void SwapConnectionsToBeRightWayRound(void);
};
extern CPathInfoForObject *InfoForTileCars;
extern CPathInfoForObject *InfoForTilePeds;
@@ -139,18 +162,25 @@ extern CPathInfoForObject *InfoForTilePeds;
struct CTempNode
{
CVector pos;
- float dirX;
- float dirY;
+ int8 dirX; // *100
+ int8 dirY;
int16 link1;
int16 link2;
int8 numLeftLanes;
int8 numRightLanes;
+ int8 width;
+ bool isCross;
int8 linkState;
};
-struct CTempDetachedNode // unused
+struct CTempNodeExternal // made up name
{
- uint8 foo[20];
+ CVector pos;
+ int16 next;
+ int8 numLeftLanes;
+ int8 numRightLanes;
+ int8 width;
+ bool isCross;
};
class CPathFind
@@ -159,10 +189,8 @@ public:
CPathNode m_pathNodes[NUM_PATHNODES];
CCarPathLink m_carPathLinks[NUM_CARPATHLINKS];
CTreadable *m_mapObjects[NUM_MAPOBJECTS];
- uint8 m_objectFlags[NUM_MAPOBJECTS];
- int16 m_connections[NUM_PATHCONNECTIONS];
- int16 m_distances[NUM_PATHCONNECTIONS];
- CConnectionFlags m_connectionFlags[NUM_PATHCONNECTIONS];
+ uint16 m_connections[NUM_PATHCONNECTIONS]; // and flags
+ uint8 m_distances[NUM_PATHCONNECTIONS];
int16 m_carPathConnections[NUM_PATHCONNECTIONS];
int32 m_numPathNodes;
@@ -178,14 +206,19 @@ public:
void Init(void);
void AllocatePathFindInfoMem(int16 numPathGroups);
void RegisterMapObject(CTreadable *mapObject);
- void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing);
- void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight);
- void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out);
+ void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate);
+ void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate);
+ void StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,
+ bool disabled, bool betweenLevels, uint8 spawnRate);
+ void StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool unk);
+ void CalcNodeCoors(float x, float y, float z, int32 id, CVector *out);
bool LoadPathFindData(void);
void PreparePathData(void);
void CountFloodFillGroups(uint8 type);
void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,
- float maxdist, CTempDetachedNode *detachednodes, int32 numDetached);
+ float maxdist, CPathInfoForObject *detachednodes, int32 numDetached);
bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); }
@@ -203,30 +236,37 @@ public:
void MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId);
void MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);
void PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);
- int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false);
+// TODO(MIAMI): check callers for new arguments
+ int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool ignoreFlagB4 = false, bool bWaterPath = false);
int32 FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY);
float FindNodeOrientationForCarPlacement(int32 nodeId);
float FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards);
bool NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled = false);
bool GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix);
- CTreadable *FindRoadObjectClosestToCoors(CVector coors, uint8 type);
void FindNextNodeWandering(uint8, CVector, CPathNode**, CPathNode**, uint8, uint8*);
void DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *numNodes, int16 maxNumNodes, CVehicle *vehicle, float *dist, float distLimit, int32 forcedTargetNode);
bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
void Save(uint8 *buf, uint32 *size);
void Load(uint8 *buf, uint32 size);
- uint16 ConnectedNode(int id) { return m_connections[id]; }
- bool ConnectionCrossesRoad(int id) { return m_connectionFlags[id].bCrossesRoad; }
- bool ConnectionHasTrafficLight(int id) { return m_connectionFlags[id].bTrafficLight; }
- void ConnectionSetTrafficLight(int id) { m_connectionFlags[id].bTrafficLight = true; }
+
+ CPathNode *GetNode(int16 index);
+ int16 GetIndex(CPathNode *node);
+
+ uint16 ConnectedNode(int id) { return m_connections[id] & 0x3FFF; }
+ bool ConnectionCrossesRoad(int id) { return !!(m_connections[id] & 0x8000); }
+ bool ConnectionHasTrafficLight(int id) { return !!(m_connections[id] & 0x4000); }
+ void ConnectionSetTrafficLight(int id) { m_connections[id] |= 0x4000; }
void DisplayPathData(void);
};
-VALIDATE_SIZE(CPathFind, 0x49bf4);
-
extern CPathFind ThePaths;
+inline CPathNode *CPathNode::GetPrev(void) { return ThePaths.GetNode(prevIndex); }
+inline CPathNode *CPathNode::GetNext(void) { return ThePaths.GetNode(nextIndex); }
+inline void CPathNode::SetPrev(CPathNode *node) { prevIndex = ThePaths.GetIndex(node); }
+inline void CPathNode::SetNext(CPathNode *node) { nextIndex = ThePaths.GetIndex(node); }
+
extern bool gbShowPedPaths;
extern bool gbShowCarPaths;
extern bool gbShowCarPathsLinks;
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 32bffa17..330b5788 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -486,7 +486,7 @@ CPickups::RemovePickUp(int32 pickupIndex)
}
int32
-CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity)
+CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate, bool highPriority, wchar* pText)
{
bool bFreeFound = false;
int32 slot = 0;
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index b05f5db7..2842edfa 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -8,6 +8,7 @@ enum ePickupType : uint8
PICKUP_ON_STREET,
PICKUP_ONCE,
PICKUP_ONCE_TIMEOUT,
+ PICKUP_ONCE_TIMEOUT_SLOW,
PICKUP_COLLECTABLE1,
PICKUP_IN_SHOP_OUT_OF_STOCK,
PICKUP_MONEY,
@@ -18,6 +19,9 @@ enum ePickupType : uint8
PICKUP_FLOATINGPACKAGE,
PICKUP_FLOATINGPACKAGE_FLOATING,
PICKUP_ON_STREET_SLOW,
+ PICKUP_ASSET_REVENUE,
+ PICKUP_PROPERTY_LOCKED,
+ PICKUP_PROPERTY_FORSALE,
PICKUP_NUMOFTYPES
};
@@ -73,7 +77,7 @@ public:
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(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate = 0, bool highPriority = false, wchar* pText = nil);
static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
static void RemovePickUp(int32 pickupIndex);
static void RemoveAllFloatingPickups();
diff --git a/src/control/Record.cpp b/src/control/Record.cpp
index d086543f..5e6c7cdb 100644
--- a/src/control/Record.cpp
+++ b/src/control/Record.cpp
@@ -11,513 +11,97 @@
#include "World.h"
uint16 CRecordDataForGame::RecordingState;
-uint8* CRecordDataForGame::pDataBuffer;
-uint8* CRecordDataForGame::pDataBufferPointer;
-int CRecordDataForGame::FId;
-tGameBuffer CRecordDataForGame::pDataBufferForFrame;
-
-#define MEMORY_FOR_GAME_RECORD (150000)
void CRecordDataForGame::Init(void)
{
RecordingState = STATE_NONE;
- delete[] pDataBuffer;
- pDataBufferPointer = nil;
- pDataBuffer = nil;
-#ifndef GTA_PS2 // this stuff is not present on PS2
- FId = CFileMgr::OpenFile("playback.dat", "r");
- if (FId <= 0) {
- if ((FId = CFileMgr::OpenFile("record.dat", "r")) <= 0)
- RecordingState = STATE_NONE;
- else {
- CFileMgr::CloseFile(FId);
- FId = CFileMgr::OpenFileForWriting("record.dat");
- RecordingState = STATE_RECORD;
- }
- }
- else {
- RecordingState = STATE_PLAYBACK;
- }
- if (RecordingState == STATE_PLAYBACK) {
- pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD];
- pDataBuffer = pDataBufferPointer;
- pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1;
- CFileMgr::CloseFile(FId);
- }
-#else
- RecordingState = STATE_NONE; // second time to make sure
-#endif
}
void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
{
- switch (RecordingState) {
- case STATE_RECORD:
- {
- pDataBufferForFrame.m_fTimeStep = CTimer::GetTimeStep();
- pDataBufferForFrame.m_nTimeInMilliseconds = CTimer::GetTimeInMilliseconds();
- pDataBufferForFrame.m_nSizeOfPads[0] = 0;
- pDataBufferForFrame.m_nSizeOfPads[1] = 0;
- pDataBufferForFrame.m_nChecksum = CalcGameChecksum();
- uint8* pController1 = PackCurrentPadValues(pDataBufferForFrame.m_ControllerBuffer, &CPad::GetPad(0)->OldState, &CPad::GetPad(0)->NewState);
- pDataBufferForFrame.m_nSizeOfPads[0] = (pController1 - pDataBufferForFrame.m_ControllerBuffer) / 2;
- uint8* pController2 = PackCurrentPadValues(pController1, &CPad::GetPad(1)->OldState, &CPad::GetPad(1)->NewState);
- pDataBufferForFrame.m_nSizeOfPads[1] = (pController2 - pController1) / 2;
- uint8* pEndPtr = pController2;
- if ((pDataBufferForFrame.m_nSizeOfPads[0] + pDataBufferForFrame.m_nSizeOfPads[1]) & 1)
- pEndPtr += 2;
- CFileMgr::Write(FId, (char*)&pDataBufferForFrame, pEndPtr - (uint8*)&pDataBufferForFrame);
- break;
- }
- case STATE_PLAYBACK:
- if (pDataBufferPointer[8] == (uint8)-1)
- CPad::GetPad(0)->NewState.Clear();
- else {
- tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer;
- CTimer::SetTimeInMilliseconds(pData->m_nTimeInMilliseconds);
- CTimer::SetTimeStep(pData->m_fTimeStep);
- uint8 size1 = pData->m_nSizeOfPads[0];
- uint8 size2 = pData->m_nSizeOfPads[1];
- pDataBufferPointer = (uint8*)&pData->m_ControllerBuffer;
- pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size1, &CPad::GetPad(0)->NewState);
- pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size2, &CPad::GetPad(1)->NewState);
- if ((size1 + size2) & 1)
- pDataBufferPointer += 2;
- if (pData->m_nChecksum != CalcGameChecksum())
- printf("Playback out of sync\n");
- }
- }
}
-#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \
- do { \
- if (os->field != ns->field){ \
- *buf++ = id; \
- *buf++ = ns->field; \
- } \
- } while (0);
-
uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os, CControllerState* ns)
{
- 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, 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);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder1, 6);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder2, 7);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadUp, 8);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadDown, 9);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadLeft, 10);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadRight, 11);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Start, 12);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Select, 13);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Square, 14);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Triangle, 15);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Cross, 16);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, Circle, 17);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShock, 18);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShock, 19);
- return buf;
+ return nil;
}
-#undef PROCESS_BUTTON_STATE_STORE
-
-#define PROCESS_BUTTON_STATE_RESTORE(buf, state, field, id) case id: state->field = *buf++; break;
uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CControllerState* state)
{
- for (uint8 i = 0; i < total; i++) {
- switch (*buf++) {
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1);
- 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);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder1, 6);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder2, 7);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadUp, 8);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadDown, 9);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadLeft, 10);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadRight, 11);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Start, 12);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Select, 13);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Square, 14);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Triangle, 15);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Cross, 16);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, Circle, 17);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShock, 18);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShock, 19);
- }
- }
- return buf;
+ return nil;
}
-#undef PROCESS_BUTTON_STATE_RESTORE
-
uint16 CRecordDataForGame::CalcGameChecksum(void)
{
- uint32 checksum = 0;
- int i = CPools::GetPedPool()->GetSize();
- while (i--) {
- CPed* pPed = CPools::GetPedPool()->GetSlot(i);
- if (!pPed)
- continue;
- checksum ^= pPed->GetModelIndex() ^ *(uint32*)&pPed->GetPosition().z ^ *(uint32*)&pPed->GetPosition().y ^ *(uint32*)&pPed->GetPosition().x;
- }
- i = CPools::GetVehiclePool()->GetSize();
- while (i--) {
- CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
- if (!pVehicle)
- continue;
- checksum ^= pVehicle->GetModelIndex() ^ *(uint32*)&pVehicle->GetPosition().z ^ *(uint32*)&pVehicle->GetPosition().y ^ *(uint32*)&pVehicle->GetPosition().x;
- }
- return checksum ^ checksum >> 16;
+ return 0;
}
uint8 CRecordDataForChase::Status;
-int CRecordDataForChase::PositionChanges;
-uint8 CRecordDataForChase::CurrentCar;
-CAutomobile* CRecordDataForChase::pChaseCars[NUM_CHASE_CARS];
-uint32 CRecordDataForChase::AnimStartTime;
-float CRecordDataForChase::AnimTime;
-CCarStateEachFrame* CRecordDataForChase::pBaseMemForCar[NUM_CHASE_CARS];
-float CRecordDataForChase::TimeMultiplier;
-int CRecordDataForChase::FId2;
-
-#define CHASE_SCENE_LENGTH_IN_SECONDS (80)
-#define CHASE_SCENE_FRAMES_PER_SECOND (15) // skipping every second frame
-#define CHASE_SCENE_FRAMES_IN_RECORDING (CHASE_SCENE_LENGTH_IN_SECONDS * CHASE_SCENE_FRAMES_PER_SECOND)
-#define CHASE_SCENE_LENGTH_IN_FRAMES (CHASE_SCENE_FRAMES_IN_RECORDING * 2)
void CRecordDataForChase::Init(void)
{
Status = STATE_NONE;
- PositionChanges = 0;
- CurrentCar = 0;
- for (int i = 0; i < NUM_CHASE_CARS; i++)
- pChaseCars[i] = nil;
- AnimStartTime = 0;
}
void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void)
{
- switch (Status) {
- case STATE_NONE:
- return;
- case STATE_RECORD:
- {
- if ((CTimer::GetFrameCounter() & 1) == 0)
- StoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2]);
- if (CTimer::GetFrameCounter() < CHASE_SCENE_LENGTH_IN_FRAMES * 2)
- return;
- CFileMgr::SetDir("data\\paths");
- sprintf(gString, "chase%d.dat", CurrentCar);
- int fid = CFileMgr::OpenFileForWriting(gString);
- uint32 fs = CHASE_SCENE_LENGTH_IN_FRAMES * sizeof(CCarStateEachFrame);
- printf("FileSize:%d\n", fs);
- CFileMgr::Write(fid, (char*)pBaseMemForCar[CurrentCar], fs);
- CFileMgr::CloseFile(fid);
- CFileMgr::SetDir("");
- sprintf(gString, "car%d.max", CurrentCar);
- int fid2 = CFileMgr::OpenFileForWriting(gString);
- for (int i = 0; i < CHASE_SCENE_FRAMES_IN_RECORDING; i++) {
- // WTF? Was it ever used?
-#ifdef FIX_BUGS
- CCarStateEachFrame* pState = pBaseMemForCar[CurrentCar];
-#else
- CCarStateEachFrame* pState = (CCarStateEachFrame*)pChaseCars[CurrentCar];
-#endif
- CVector right = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
- CVector forward = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
- CVector up = CrossProduct(right, forward);
- sprintf(gString, "%f %f %f\n", pState->pos.x, pState->pos.y, pState->pos.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", right.x, right.y, right.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", forward.x, forward.y, forward.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- sprintf(gString, "%f %f %f\n", up.x, up.y, up.z);
- CFileMgr::Write(fid2, gString, strlen(gString) - 1);
- }
- CFileMgr::CloseFile(fid2);
- }
- case STATE_PLAYBACK:
- case STATE_PLAYBACK_BEFORE_RECORDING:
- case STATE_PLAYBACK_INIT:
- break;
- }
}
-struct tCoors {
- CVector pos;
- float angle;
-};
-
-// I guess developer was filling this with actual data before running the game
-tCoors NewCoorsForRecordedCars[7];
-
void CRecordDataForChase::SaveOrRetrieveCarPositions(void)
{
- switch (Status) {
- case STATE_NONE:
- return;
- case STATE_RECORD:
- case STATE_PLAYBACK_BEFORE_RECORDING:
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (i != CurrentCar && CTimer::GetFrameCounter()) {
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CTimer::GetFrameCounter() / 2], false);
- pChaseCars[i]->GetMatrix().UpdateRW();
- pChaseCars[i]->UpdateRwFrame();
- }
- }
- if (Status == STATE_PLAYBACK_BEFORE_RECORDING && CTimer::GetFrameCounter()) {
- RestoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2], false);
- pChaseCars[CurrentCar]->GetMatrix().UpdateRW();
- pChaseCars[CurrentCar]->UpdateRwFrame();
- }
- if (CPad::GetPad(0)->GetLeftShockJustDown() && CPad::GetPad(0)->GetRightShockJustDown()) {
- if (!CPad::GetPad(0)->GetRightShockJustDown()) {
- pChaseCars[CurrentCar]->SetPosition(NewCoorsForRecordedCars[PositionChanges].pos);
- pChaseCars[CurrentCar]->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pChaseCars[CurrentCar]->GetMatrix().SetRotateZOnly(DEGTORAD(NewCoorsForRecordedCars[PositionChanges].angle));
- ++PositionChanges;
- }
- if (Status == STATE_PLAYBACK_BEFORE_RECORDING) {
- Status = STATE_RECORD;
- pChaseCars[CurrentCar]->SetStatus(STATUS_PLAYER);
- }
- }
- break;
- case STATE_PLAYBACK_INIT:
- Status = STATE_PLAYBACK;
- break;
- case STATE_PLAYBACK:
- {
- TimeMultiplier += CTimer::GetTimeStepNonClippedInSeconds();
- float EndOfFrameTime = CHASE_SCENE_FRAMES_PER_SECOND * Min(CHASE_SCENE_LENGTH_IN_SECONDS, TimeMultiplier);
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (!pBaseMemForCar[i])
- continue;
- if (!pChaseCars[i])
- continue;
- if (EndOfFrameTime < CHASE_SCENE_FRAMES_IN_RECORDING - 1) {
- int FlooredEOFTime = EndOfFrameTime;
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][FlooredEOFTime], false);
- CMatrix tmp;
- float dp = EndOfFrameTime - FlooredEOFTime;
- RestoreInfoForMatrix(tmp, &pBaseMemForCar[i][FlooredEOFTime + 1]);
- pChaseCars[i]->GetRight() += (tmp.GetRight() - pChaseCars[i]->GetRight()) * dp;
- pChaseCars[i]->GetForward() += (tmp.GetForward() - pChaseCars[i]->GetForward()) * dp;
- pChaseCars[i]->GetUp() += (tmp.GetUp() - pChaseCars[i]->GetUp()) * dp;
- pChaseCars[i]->GetMatrix().GetPosition() += (tmp.GetPosition() - pChaseCars[i]->GetPosition()) * dp;
- }
- else{
- RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CHASE_SCENE_FRAMES_IN_RECORDING - 1], true);
- if (i == 0)
- pChaseCars[i]->GetMatrix().GetPosition().z += 0.2f;
- }
- pChaseCars[i]->GetMatrix().UpdateRW();
- pChaseCars[i]->UpdateRwFrame();
- pChaseCars[i]->RemoveAndAdd();
- }
- break;
- }
- }
}
void CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState)
{
- pState->rightX = INT8_MAX * pCar->GetRight().x;
- pState->rightY = INT8_MAX * pCar->GetRight().y;
- pState->rightZ = INT8_MAX * pCar->GetRight().z;
- pState->forwardX = INT8_MAX * pCar->GetForward().x;
- pState->forwardY = INT8_MAX * pCar->GetForward().y;
- pState->forwardZ = INT8_MAX * pCar->GetForward().z;
- pState->pos = pCar->GetPosition();
- pState->velX = 0.5f * INT16_MAX * pCar->GetMoveSpeed().x;
- pState->velY = 0.5f * INT16_MAX * pCar->GetMoveSpeed().y;
- pState->velZ = 0.5f * INT16_MAX * pCar->GetMoveSpeed().z;
- pState->wheel = 20 * pCar->m_fSteerAngle;
- pState->gas = 100 * pCar->m_fGasPedal;
- pState->brake = 100 * pCar->m_fBrakePedal;
- pState->handbrake = pCar->bIsHandbrakeOn;
}
void CRecordDataForChase::RestoreInfoForMatrix(CMatrix& matrix, CCarStateEachFrame* pState)
{
- matrix.GetRight() = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
- matrix.GetForward() = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
- matrix.GetUp() = CrossProduct(matrix.GetRight(), matrix.GetForward());
- matrix.GetPosition() = pState->pos;
}
void CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState, bool stop)
{
- CVector oldPos = pCar->GetPosition();
- RestoreInfoForMatrix(pCar->GetMatrix(), pState);
- pCar->SetMoveSpeed(CVector(pState->velX, pState->velY, pState->velZ) / INT16_MAX / 0.5f);
- pCar->SetTurnSpeed(0.0f, 0.0f, 0.0f);
- pCar->m_fSteerAngle = pState->wheel / 20.0f;
- pCar->m_fGasPedal = pState->gas / 100.0f;
- pCar->m_fBrakePedal = pState->brake / 100.0f;
- pCar->bIsHandbrakeOn = pState->handbrake;
- if ((oldPos - pCar->GetPosition()).Magnitude() > 15.0f) {
- if (pCar == pChaseCars[14]) {
- pCar->m_currentColour1 = 58;
- pCar->m_currentColour2 = 1;
- }
- else
- pCar->GetModelInfo()->ChooseVehicleColour(pCar->m_currentColour1, pCar->m_currentColour2);
- }
- pCar->m_fHealth = Min(pCar->m_fHealth, 500.0f);
- if (stop) {
- pCar->m_fGasPedal = 0.0f;
- pCar->m_fBrakePedal = 0.0f;
- pCar->SetMoveSpeed(0.0f, 0.0f, 0.0f);
- pCar->bIsHandbrakeOn = false;
- }
}
void CRecordDataForChase::ProcessControlCars(void)
{
- if (Status != STATE_PLAYBACK)
- return;
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (pChaseCars[i])
- pChaseCars[i]->ProcessControl();
- }
}
-#if (defined(GTA_PS2) || defined(FIX_BUGS))
bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad)
{
- // may be wrong
- if (Status == STATE_NONE || Status == STATE_PLAYBACK)
- return false;
- return pad != 0;
+ return false;
}
-#endif
void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2)
{
- CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);
- CStreaming::LoadAllRequestedModels(false);
- if (!CStreaming::HasModelLoaded(mi))
- return;
- CAutomobile* pCar = new CAutomobile(mi, MISSION_VEHICLE);
- pCar->SetPosition(pos);
- pCar->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);
- pCar->GetMatrix().SetRotateZOnly(DEGTORAD(angle));
- pCar->pDriver = nil;
- pCar->m_currentColour1 = colour1;
- pCar->m_currentColour2 = colour2;
- CWorld::Add(pCar);
- *ppCar = pCar;
}
void RemoveUnusedCollision(void)
{
- static const char* dontDeleteArray[] = {
- "rd_SrRoad2A50", "rd_SrRoad2A20", "rd_CrossRda1w22", "rd_CrossRda1rw22",
- "road_broadway02", "road_broadway01", "com_21way5", "com_21way50",
- "cm1waycrosscom", "com_21way20", "com_21way10", "road_broadway04",
- "com_rvroads52", "com_roadsrv", "com_roadkb23", "com_roadkb22"
- };
- for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
- CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_NONE;
- CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_NONE);
- for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
- CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL;
}
void CRecordDataForChase::StartChaseScene(float startTime)
{
- char filename[28];
- SetUpCarsForChaseScene();
- Status = STATE_PLAYBACK;
- AnimTime = startTime;
- AnimStartTime = CTimer::GetTimeInMilliseconds();
- RemoveUnusedCollision();
- CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
- CGame::TidyUpMemory(true, true);
- CStreaming::ImGonnaUseStreamingMemory();
- CFileMgr::SetDir("data\\paths");
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (!pChaseCars[i]) {
- pBaseMemForCar[i] = nil;
- continue;
- }
- sprintf(filename, "chase%d.dat", i);
- FId2 = CFileMgr::OpenFile(filename, "rb");
- if (FId2 <= 0) {
- pBaseMemForCar[i] = nil;
- continue;
- }
- pBaseMemForCar[i] = new CCarStateEachFrame[CHASE_SCENE_FRAMES_IN_RECORDING];
- for (int j = 0; j < CHASE_SCENE_FRAMES_IN_RECORDING; j++) {
- CFileMgr::Read(FId2, (char*)&pBaseMemForCar[i][j], sizeof(CCarStateEachFrame));
- CFileMgr::Seek(FId2, sizeof(CCarStateEachFrame), 1);
- }
- CFileMgr::CloseFile(FId2);
- }
- CFileMgr::SetDir("");
- CStreaming::IHaveUsedStreamingMemory();
- TimeMultiplier = 0.0f;
}
void CRecordDataForChase::CleanUpChaseScene(void)
{
- if (Status != STATE_PLAYBACK_INIT && Status != STATE_PLAYBACK)
- return;
- Status = STATE_NONE;
- CleanUpCarsForChaseScene();
- for (int i = 0; i < NUM_CHASE_CARS; i++) {
- if (pBaseMemForCar[i]) {
- delete[] pBaseMemForCar[i];
- pBaseMemForCar[i] = nil;
- }
- }
}
void CRecordDataForChase::SetUpCarsForChaseScene(void)
{
- GiveUsACar(MI_POLICE, CVector(273.54221f, -1167.1907f, 24.880601f), 63.0f, &pChaseCars[0], 2, 1);
- GiveUsACar(MI_ENFORCER, CVector(231.1783f, -1388.8322f, 25.978201f), 90.0f, &pChaseCars[1], 2, 1);
- GiveUsACar(MI_TAXI, CVector(184.3156f, -1473.251f, 25.978201f), 0.0f, &pChaseCars[4], 6, 6);
- GiveUsACar(MI_CHEETAH, CVector(173.8868f, -1377.6514f, 25.978201f), 0.0f, &pChaseCars[6], 4, 5);
- GiveUsACar(MI_STINGER, CVector(102.5946f, -943.93628f, 25.9781f), 270.0f, &pChaseCars[7], 53, 53);
- GiveUsACar(MI_CHEETAH, CVector(-177.7157f, -862.18652f, 25.978201f), 155.0f, &pChaseCars[10], 41, 1);
- GiveUsACar(MI_STINGER, CVector(-170.56979f, -889.02362f, 25.978201f), 154.0f, &pChaseCars[11], 10, 10);
- GiveUsACar(MI_KURUMA, CVector(402.60809f, -917.49628f, 37.381001f), 90.0f, &pChaseCars[14], 34, 1);
- GiveUsACar(MI_TAXI, CVector(-33.496201f, -938.4563f, 25.9781f), 266.0f, &pChaseCars[16], 6, 6);
- GiveUsACar(MI_KURUMA, CVector(49.363098f, -987.60498f, 25.9781f), 0.0f, &pChaseCars[18], 51, 1);
- GiveUsACar(MI_TAXI, CVector(179.0049f, -1154.6686f, 25.9781f), 0.0f, &pChaseCars[19], 6, 76);
- GiveUsACar(MI_RUMPO, CVector(-28.9762f, -1031.3367f, 25.990601f), 242.0f, &pChaseCars[2], 1, 75);
- GiveUsACar(MI_PATRIOT, CVector(114.1564f, -796.69379f, 24.978201f), 180.0f, &pChaseCars[3], 0, 0);
}
void CRecordDataForChase::CleanUpCarsForChaseScene(void)
{
- for (int i = 0; i < NUM_CHASE_CARS; i++)
- RemoveCarFromChase(i);
}
void CRecordDataForChase::RemoveCarFromChase(int32 i)
{
- if (!pChaseCars[i])
- return;
- CWorld::Remove(pChaseCars[i]);
- delete pChaseCars[i];
- pChaseCars[i] = nil;
}
CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32 i)
{
- CVehicle* pVehicle = pChaseCars[i];
- pChaseCars[i] = nil;
- pVehicle->SetStatus(STATUS_PHYSICS);
- return pVehicle;
+ return nil;
}
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index 707f1d87..ab187c10 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -47,7 +47,7 @@ CAutomobile *CReplay::pBuf1;
uint8 *CReplay::pBuf2;
CPlayerPed *CReplay::pBuf3;
uint8 *CReplay::pBuf4;
-CCutsceneHead *CReplay::pBuf5;
+CCutsceneObject *CReplay::pBuf5;
uint8 *CReplay::pBuf6;
CPtrNode *CReplay::pBuf7;
uint8 *CReplay::pBuf8;
@@ -835,13 +835,14 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo
CStreaming::RequestModel(mi, 0);
}
else {
+// TODO(MIAMI): don't hardcode model indices
if (mi == MI_DEADDODO || mi == MI_AIRTRAIN) {
new_v = new(vp->index << 8) CPlane(mi, 2);
}
else if (mi == MI_TRAIN) {
new_v = new(vp->index << 8) CTrain(mi, 2);
}
- else if (mi == MI_CHOPPER || mi == MI_ESCAPE) {
+ else if (mi == MI_CHOPPER) {
new_v = new(vp->index << 8) CHeli(mi, 2);
}
else if (CModelInfo::IsBoatModel(mi)){
diff --git a/src/control/Replay.h b/src/control/Replay.h
index 66bee3bf..09cf601e 100644
--- a/src/control/Replay.h
+++ b/src/control/Replay.h
@@ -214,7 +214,7 @@ private:
static uint8* pBuf2;
static CPlayerPed* pBuf3;
static uint8* pBuf4;
- static CCutsceneHead* pBuf5;
+ static CCutsceneObject* pBuf5;
static uint8* pBuf6;
static CPtrNode* pBuf7;
static uint8* pBuf8;
diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp
index 5a322cdb..64cabf5d 100644
--- a/src/control/Restart.cpp
+++ b/src/control/Restart.cpp
@@ -80,13 +80,13 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f
return;
}
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ eLevelName curlevel = CTheZones::GetLevelFromPosition(&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)) {
+ if (CTheZones::GetLevelFromPosition(&HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
@@ -127,13 +127,13 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo
return;
}
- eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
+ eLevelName curlevel = CTheZones::GetLevelFromPosition(&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)) {
+ if (CTheZones::GetLevelFromPosition(&PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
if (fMinDist >= dist) {
fMinDist = dist;
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index 572f8134..0261cd4a 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -15,22 +15,23 @@
#include "CarCtrl.h"
#include "General.h"
-#define ROADBLOCKDIST (80.0f)
+#define ROADBLOCKDIST (90.0f)
int16 CRoadBlocks::NumRoadBlocks;
-int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS];
+int16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS];
bool CRoadBlocks::InOrOut[NUMROADBLOCKS];
+//--MIAMI: TODO
void
CRoadBlocks::Init(void)
{
int i;
NumRoadBlocks = 0;
- for (i = 0; i < ThePaths.m_numMapObjects; i++) {
- if (ThePaths.m_objectFlags[i] & UseInRoadBlock) {
+ for(i = 0; i < ThePaths.m_numCarPathNodes; i++){
+ if(ThePaths.m_pathNodes[i].bUseInRoadBlock && ThePaths.m_pathNodes[i].numLinks == 2){
if (NumRoadBlocks < NUMROADBLOCKS) {
InOrOut[NumRoadBlocks] = true;
- RoadBlockObjects[NumRoadBlocks] = i;
+ RoadBlockNodes[NumRoadBlocks] = i;
NumRoadBlocks++;
} else {
#ifndef MASTER
@@ -41,6 +42,8 @@ CRoadBlocks::Init(void)
}
}
}
+
+ // TODO(MIAMI): script roadblocks
}
void
@@ -102,6 +105,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
}
}
+//--MIAMI: TODO: implement this
void
CRoadBlocks::GenerateRoadBlocks(void)
{
@@ -110,14 +114,14 @@ CRoadBlocks::GenerateRoadBlocks(void)
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) {
- CTreadable *mapObject = ThePaths.m_mapObjects[RoadBlockObjects[nRoadblockNode]];
- CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
+ CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[nRoadblockNode].GetPosition();
if (vecDistance.x > -ROADBLOCKDIST && vecDistance.x < ROADBLOCKDIST &&
vecDistance.y > -ROADBLOCKDIST && vecDistance.y < ROADBLOCKDIST &&
vecDistance.Magnitude() < ROADBLOCKDIST) {
if (!InOrOut[nRoadblockNode]) {
InOrOut[nRoadblockNode] = true;
if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
+#ifndef MIAMI
CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted;
float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x;
int32 vehicleId = MI_POLICE;
@@ -187,10 +191,13 @@ CRoadBlocks::GenerateRoadBlocks(void)
}
}
}
+#endif
}
}
} else {
InOrOut[nRoadblockNode] = false;
}
}
+
+ // TODO(MIAMI): script roadblocks
}
diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h
index 0f0c1882..439fd6e7 100644
--- a/src/control/RoadBlocks.h
+++ b/src/control/RoadBlocks.h
@@ -7,7 +7,11 @@ class CRoadBlocks
{
public:
static int16 NumRoadBlocks;
+#ifndef MIAMI
static int16 RoadBlockObjects[NUMROADBLOCKS];
+#else
+ static int16 RoadBlockNodes[NUMROADBLOCKS];
+#endif
static bool InOrOut[NUMROADBLOCKS];
static void Init(void);
diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp
index be8c5519..f7dcaa3c 100644
--- a/src/control/SceneEdit.cpp
+++ b/src/control/SceneEdit.cpp
@@ -88,7 +88,7 @@ static int32 NextValidModelId(int32 mi, int32 step)
continue;
if (pInfo->GetModelType() == MITYPE_PED
#ifdef FIX_BUGS
- && !(i >= MI_SPECIAL01 && i <= MI_SPECIAL04)
+ && !(i >= MI_SPECIAL01 && i <= MI_SPECIAL21)
#endif
|| pInfo->GetModelType() == MITYPE_VEHICLE &&
#ifdef FIX_BUGS
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 13000847..50dc6b7b 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -13,6 +13,7 @@
#include "CarGen.h"
#include "CivilianPed.h"
#include "Clock.h"
+#include "ColStore.h"
#include "CopPed.h"
#include "Coronas.h"
#include "Cranes.h"
@@ -170,10 +171,46 @@ void CMissionCleanup::AddEntityToList(int32 id, uint8 type)
m_nCount++;
}
+static void PossiblyWakeThisEntity(CPhysical* pEntity)
+{
+ if (!pEntity->bIsStaticWaitingForCollision)
+ return;
+ if (CColStore::HasCollisionLoaded(pEntity->GetPosition())) {
+ pEntity->bIsStaticWaitingForCollision = false;
+ if (!pEntity->IsStatic())
+ pEntity->AddToMovingList();
+ }
+}
+
void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
{
for (int i = 0; i < MAX_CLEANUP; i++){
if (m_sEntities[i].type == type && m_sEntities[i].id == id){
+ switch (m_sEntities[i].type) {
+ case CLEANUP_CAR:
+ {
+ CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (v)
+ PossiblyWakeThisEntity(v);
+ break;
+ }
+ case CLEANUP_CHAR:
+ {
+ CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (p)
+ PossiblyWakeThisEntity(p);
+ break;
+ }
+ case CLEANUP_OBJECT:
+ {
+ CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
+ if (o)
+ PossiblyWakeThisEntity(o);
+ break;
+ }
+ default:
+ break;
+ }
m_sEntities[i].id = 0;
m_sEntities[i].type = CLEANUP_UNUSED;
m_nCount--;
@@ -181,6 +218,52 @@ void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)
}
}
+void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObject()
+{
+ for (int i = 0; i < MAX_CLEANUP; i++) {
+ switch (m_sEntities[i].type) {
+ case CLEANUP_CAR:
+ {
+ CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (v)
+ PossiblyWakeThisEntity(v);
+ break;
+ }
+ case CLEANUP_CHAR:
+ {
+ CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (p)
+ PossiblyWakeThisEntity(p);
+ break;
+ }
+ case CLEANUP_OBJECT:
+ {
+ CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);
+ if (o)
+ PossiblyWakeThisEntity(o);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+CPhysical* CMissionCleanup::DoesThisEntityWaitForCollision(int i)
+{
+ if (m_sEntities[i].type == CLEANUP_CAR) {
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);
+ if (pVehicle && pVehicle->GetStatus() != STATUS_WRECKED)
+ return pVehicle;
+ }
+ else if (m_sEntities[i].type == CLEANUP_CHAR) {
+ CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);
+ if (pPed && !pPed->DyingOrDead())
+ return pPed;
+ }
+ return nil;
+}
+
void CMissionCleanup::Process()
{
CPopulation::m_AllRandomPedsThisType = -1;
@@ -391,11 +474,11 @@ bool CStuckCarCheck::HasCarBeenStuckForAWhile(int32 id)
void CRunningScript::CollectParameters(uint32* pIp, int16 total)
{
for (int16 i = 0; i < total; i++){
- float tmp;
uint16 varIndex;
switch (CTheScripts::Read1ByteFromScript(pIp))
{
case ARGUMENT_INT32:
+ case ARGUMENT_FLOAT:
ScriptParams[i] = CTheScripts::Read4BytesFromScript(pIp);
break;
case ARGUMENT_GLOBALVAR:
@@ -414,10 +497,6 @@ void CRunningScript::CollectParameters(uint32* pIp, int16 total)
case ARGUMENT_INT16:
ScriptParams[i] = CTheScripts::Read2BytesFromScript(pIp);
break;
- case ARGUMENT_FLOAT:
- tmp = CTheScripts::ReadFloatFromScript(pIp);
- ScriptParams[i] = *(int32*)&tmp;
- break;
default:
assert(0);
break;
@@ -504,9 +583,12 @@ void CRunningScript::Init()
}
#ifdef USE_DEBUG_SCRIPT_LOADER
+
+const char* scriptfile = "main.scm";
+
int open_script()
{
- static int scriptToLoad = 0;
+ static int scriptToLoad = 1;
#ifdef _WIN32
if (GetAsyncKeyState('G') & 0x8000)
@@ -517,11 +599,11 @@ int open_script()
scriptToLoad = 2;
#endif
switch (scriptToLoad) {
- case 0: return CFileMgr::OpenFile("main.scm", "rb");
- case 1: return CFileMgr::OpenFile("main_freeroam.scm", "rb");
- case 2: return CFileMgr::OpenFile("main_d.scm", "rb");
+ case 0: scriptfile = "main.scm"; break;
+ case 1: scriptfile = "freeroam_miami.scm"; break;
+ case 2: scriptfile = "main_d.scm"; break;
}
- return CFileMgr::OpenFile("main.scm", "rb");
+ return CFileMgr::OpenFile(scriptfile, "rb");
}
#endif
@@ -647,6 +729,7 @@ void CTheScripts::Process()
float timeStep = CTimer::GetTimeStepInMilliseconds();
UpsideDownCars.UpdateTimers();
StuckCars.Process();
+ MissionCleanup.CheckIfCollisionHasLoadedForMissionObject();
DrawScriptSpheres();
if (FailCurrentMission)
--FailCurrentMission;
@@ -737,15 +820,16 @@ int8 CRunningScript::ProcessOneCommand()
return ProcessCommands800To899(command);
if (command < 1000)
return ProcessCommands900To999(command);
-#ifdef GTA_PS2
- if (command < 1200)
- return ProcessCommands1000To1099(command);
-#else
if (command < 1100)
return ProcessCommands1000To1099(command);
if (command < 1200)
return ProcessCommands1100To1199(command);
-#endif
+ if (command < 1300)
+ return ProcessCommands1200To1299(command);
+ if (command < 1400)
+ return ProcessCommands1300To1399(command);
+ if (command < 1500)
+ return ProcessCommands1400To1499(command);
return -1;
}
@@ -1773,6 +1857,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ped->SetPosition(pos);
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (m_bIsMissionScript)
+ ped->bIsStaticWaitingForCollision = true;
CWorld::Add(ped);
ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
CPopulation::ms_nTotalMissionPeds++;
@@ -1991,6 +2077,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
boat->AutoPilot.m_nCarMission = MISSION_NONE;
boat->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */
boat->AutoPilot.m_nCruiseSpeed = boat->AutoPilot.m_fMaxTrafficSpeed = 20.0f;
+ if (m_bIsMissionScript)
+ boat->bIsStaticWaitingForCollision = true;
CWorld::Add(boat);
handle = CPools::GetVehiclePool()->GetIndex(boat);
}
@@ -2015,6 +2103,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
car->bEngineOn = false;
car->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
car->bHasBeenOwnedByPlayer = true;
+ if (m_bIsMissionScript)
+ car->bIsStaticWaitingForCollision = true;
CWorld::Add(car);
handle = CPools::GetVehiclePool()->GetIndex(car);
}
@@ -2714,11 +2804,11 @@ int8 CRunningScript::ProcessCommands200To299(int32 command)
CPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int zoneToCheck = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ int zoneToCheck = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_DEFAULT);
if (zoneToCheck != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT; /* why only if zone != 1? */
CVector pos = pPlayer->GetPos();
- CZone* pZone = CTheZones::GetZone(zoneToCheck);
+ CZone* pZone = CTheZones::GetNavigationZone(zoneToCheck);
UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, pZone));
return 0;
}
@@ -3043,18 +3133,27 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case COMMAND_SET_ZONE_CAR_INFO:
{
char label[12];
+ int16 gangDensities[NUM_GANGS] = { 0 };
+ int i;
+
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 16);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ CollectParameters(&m_nIp, 12);
+ for (i = 0; i < NUM_GANGS; i++)
+ gangDensities[i] = ScriptParams[i + 2];
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ for (int i = 0; i < NUM_GANGS; i++) {
+ if (gangDensities[i] != 0 && CGangs::GetGangInfo(i)->m_nVehicleMI == -1)
+ debug("SET_ZONE_CAR_INFO - Gang %d car ratio should be 0 in %s zone\n", i + 1, label);
+ }
if (zone < 0) {
debug("Couldn't find zone - %s\n", label);
return 0;
}
- CTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
- ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0,
- ScriptParams[9], ScriptParams[10], ScriptParams[11], ScriptParams[12],
- ScriptParams[13], ScriptParams[14], ScriptParams[15]);
+ while (zone >= 0) {
+ CTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[11], gangDensities);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
return 0;
}
/* Not implemented.
@@ -3067,41 +3166,17 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
assert(pPed);
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_DEFAULT);
if (zone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
CVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();
- UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetZone(zone)));
+ UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetNavigationZone(zone)));
return 0;
}
+ /* Not implemented.
case COMMAND_SET_CAR_DENSITY:
- {
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
- m_nIp += 8;
- CollectParameters(&m_nIp, 2);
- if (zone < 0) {
- debug("Couldn't find zone - %s\n", label);
- return 0;
- }
- CTheZones::SetCarDensity(zone, ScriptParams[0], ScriptParams[1]);
- return 0;
- }
case COMMAND_SET_PED_DENSITY:
- {
- char label[12];
- CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 2);
- if (zone < 0) {
- debug("Couldn't find zone - %s\n", label);
- return 0;
- }
- CTheZones::SetPedDensity(zone, ScriptParams[0], ScriptParams[1]);
- return 0;
- }
+ */
case COMMAND_POINT_CAMERA_AT_PLAYER:
{
CollectParameters(&m_nIp, 3);
@@ -3136,14 +3211,17 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
char label[12];
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CollectParameters(&m_nIp, 10);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ CollectParameters(&m_nIp, 12);
+ int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
if (zone < 0) {
debug("Couldn't find zone - %s\n", label);
return 0;
}
- CTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
- ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], 0, 0, ScriptParams[9]);
+ while (zone >= 0) {
+ CTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],
+ ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
return 0;
}
case COMMAND_SET_TIME_SCALE:
@@ -4636,51 +4714,34 @@ int8 CRunningScript::ProcessCommands500To599(int32 command)
}
case COMMAND_SET_GARAGE:
{
- CollectParameters(&m_nIp, 7);
+ CollectParameters(&m_nIp, 9);
float infX = *(float*)&ScriptParams[0];
float infY = *(float*)&ScriptParams[1];
float infZ = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- float supZ = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[0];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[1];
- }
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[2];
- }
- ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], 0);
+ float X2 = *(float*)&ScriptParams[3];
+ float Y2 = *(float*)&ScriptParams[4];
+ float supX = *(float*)&ScriptParams[5];
+ float supY = *(float*)&ScriptParams[6];
+ float supZ = *(float*)&ScriptParams[7];
+
+ // TODO(MIAMI): new 2 parameters, requires CGarage change
+ ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, (eGarageType)ScriptParams[8], 0);
StoreParameters(&m_nIp, 1);
return 0;
}
case COMMAND_SET_GARAGE_WITH_CAR_MODEL:
{
- CollectParameters(&m_nIp, 8);
+ CollectParameters(&m_nIp, 10);
float infX = *(float*)&ScriptParams[0];
float infY = *(float*)&ScriptParams[1];
float infZ = *(float*)&ScriptParams[2];
- float supX = *(float*)&ScriptParams[3];
- float supY = *(float*)&ScriptParams[4];
- float supZ = *(float*)&ScriptParams[5];
- if (infX > supX) {
- infX = *(float*)&ScriptParams[3];
- supX = *(float*)&ScriptParams[0];
- }
- if (infY > supY) {
- infY = *(float*)&ScriptParams[4];
- supY = *(float*)&ScriptParams[1];
- }
- if (infZ > supZ) {
- infZ = *(float*)&ScriptParams[5];
- supZ = *(float*)&ScriptParams[2];
- }
- ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, supX, supY, supZ, (eGarageType)ScriptParams[6], ScriptParams[7]);
+ float X2 = *(float*)&ScriptParams[3];
+ float Y2 = *(float*)&ScriptParams[4];
+ float supX = *(float*)&ScriptParams[5];
+ float supY = *(float*)&ScriptParams[6];
+ float supZ = *(float*)&ScriptParams[7];
+ // TODO(MIAMI): new 2 parameters, requires CGarage change
+ ScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, (eGarageType)ScriptParams[8], ScriptParams[9]);
StoreParameters(&m_nIp, 1);
return 0;
}
@@ -5324,8 +5385,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command)
CollectParameters(&m_nIp, 1);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
assert(pVehicle);
- int mi = pVehicle->GetModelIndex();
- UpdateCompareFlag(mi == MI_TAXI || mi == MI_CABBIE || mi == MI_BORGNINE);
+ UpdateCompareFlag(pVehicle->IsTaxi());
return 0;
}
case COMMAND_UNLOAD_SPECIAL_CHARACTER:
@@ -5870,8 +5930,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
continue;
if (pPed->bFadeOut)
continue;
- if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
- continue;
+// if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
+// continue;
if (!ThisIsAValidRandomPed(pPed->m_nPedType))
continue;
if (pPed->bIsLeader || pPed->m_leader)
@@ -5898,10 +5958,10 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
{
char zone[KEY_LENGTH_IN_SCRIPT];
strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (nZone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(nZone);
+ CZone* pZone = CTheZones::GetNavigationZone(nZone);
int ped_handle = -1;
CVector pos = FindPlayerCoors();
int i = CPools::GetPedPool()->GetSize();
@@ -5919,8 +5979,8 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
continue;
if (pPed->bFadeOut)
continue;
- if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
- continue;
+// if (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)
+// continue;
if (!ThisIsAValidRandomPed(pPed->m_nPedType))
continue;
if (pPed->bIsLeader || pPed->m_leader)
@@ -6142,25 +6202,12 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
}
case COMMAND_CREATE_CUTSCENE_HEAD:
{
- CollectParameters(&m_nIp, 2);
- CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- assert(pObject);
- CCutsceneHead* pCutHead = CCutsceneMgr::AddCutsceneHead(pObject, ScriptParams[1]);
- ScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutHead);
- StoreParameters(&m_nIp, 1);
+ assert(0);
return 0;
}
case COMMAND_SET_CUTSCENE_HEAD_ANIM:
{
- CollectParameters(&m_nIp, 1);
- CObject* pCutHead = CPools::GetObjectPool()->GetAt(ScriptParams[0]);
- assert(pCutHead);
- char name[KEY_LENGTH_IN_SCRIPT];
- strncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- m_nIp += KEY_LENGTH_IN_SCRIPT;
- CTimer::Stop();
- CCutsceneMgr::SetHeadAnim(name, pCutHead);
- CTimer::Update();
+ assert(0);
return 0;
}
case COMMAND_SIN:
@@ -6506,7 +6553,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
m_nIp += KEY_LENGTH_IN_SCRIPT;
CollectParameters(&m_nIp, 2);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_INFO);
if (zone_id < 0) {
printf("Couldn't find zone - %s\n", zone);
return 0;
@@ -6566,10 +6613,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
{
char zone[KEY_LENGTH_IN_SCRIPT];
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+// TODO(MIAMI): just getting this to compile with new argument
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (zone_id != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(zone_id);
+ CZone* pZone = CTheZones::GetNavigationZone(zone_id);
CollectParameters(&m_nIp, 1);
int handle = -1;
uint32 i = CPools::GetVehiclePool()->GetSize();
@@ -7072,10 +7120,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
CollectParameters(&m_nIp, 1);
char zone[KEY_LENGTH_IN_SCRIPT];
CTheScripts::ReadTextLabelFromScript(&m_nIp, zone);
- int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+// TODO(MIAMI): just getting this to compile with new argument
+ int zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (zone_id != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(zone_id);
+ CZone* pZone = CTheZones::GetNavigationZone(zone_id);
UpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],
pZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz));
return 0;
@@ -7207,7 +7256,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
if (total == 0)
CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_NONE), pos, range, true, &total, 16, apEntities);
if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, range, true, &total, 16, apEntities);
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::GetLevelFromPosition(&pos)), pos, range, true, &total, 16, apEntities);
CEntity* pClosestEntity = nil;
float min_dist = 2.0f * range;
for (int i = 0; i < total; i++) {
@@ -7391,6 +7440,8 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
ped->SetPosition(pos);
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CTheScripts::ClearSpaceForMissionEntity(pos, ped);
+ if (m_bIsMissionScript)
+ ped->bIsStaticWaitingForCollision = true;
CWorld::Add(ped);
ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);
CPopulation::ms_nTotalMissionPeds++;
@@ -7959,7 +8010,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
if (total == 0)
CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_NONE), pos, radius, true, &total, 16, apEntities);
if (total == 0)
- CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::FindZoneForPoint(pos)), pos, radius, true, &total, 16, apEntities);
+ CWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::GetLevelFromPosition(&pos)), pos, radius, true, &total, 16, apEntities);
CEntity* pClosestEntity = nil;
float min_dist = 2.0f * radius;
for (int i = 0; i < total; i++) {
@@ -8133,7 +8184,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case MI_FBICAR:
case MI_MRWHOOP:
case MI_BFINJECT:
- case MI_CORPSE:
+ // case MI_CORPSE:
case MI_POLICE:
case MI_ENFORCER:
case MI_SECURICA:
@@ -8146,27 +8197,27 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case MI_DODO:
case MI_COACH:
case MI_RCBANDIT:
- case MI_BELLYUP:
- case MI_MRWONGS:
- case MI_MAFIA:
- case MI_YARDIE:
- case MI_YAKUZA:
- case MI_DIABLOS:
- case MI_COLUMB:
- case MI_HOODS:
+ // case MI_BELLYUP:
+ // case MI_MRWONGS:
+ // case MI_MAFIA:
+ case MI_VOODOO:
+ // case MI_YAKUZA:
+ // case MI_DIABLOS:
+ // case MI_COLUMB:
+ // case MI_HOODS:
case MI_AIRTRAIN:
case MI_DEADDODO:
case MI_SPEEDER:
case MI_REEFER:
- case MI_PANLANT:
+ // case MI_PANLANT:
case MI_FLATBED:
case MI_YANKEE:
- case MI_ESCAPE:
- case MI_BORGNINE:
- case MI_TOYZ:
- case MI_GHOST:
- case MI_MIAMI_RCBARON:
- case MI_MIAMI_RCRAIDER:
+ // case MI_ESCAPE:
+ case MI_ZEBRA:
+ case MI_TOPFUN:
+ // case MI_GHOST:
+ case MI_RCBARON:
+ case MI_RCRAIDER:
model = -1;
break;
case MI_IDAHO:
@@ -8176,21 +8227,21 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
case MI_PATRIOT:
case MI_MANANA:
case MI_INFERNUS:
- case MI_BLISTA:
+ // case MI_BLISTA:
case MI_PONY:
case MI_CHEETAH:
case MI_MOONBEAM:
case MI_ESPERANT:
case MI_TAXI:
- case MI_KURUMA:
+ case MI_WASHING:
case MI_BOBCAT:
case MI_BANSHEE:
case MI_CABBIE:
case MI_STALLION:
case MI_RUMPO:
- case 151:
- case 152:
- case 153:
+// case 151:
+// case 152:
+// case 153:
break;
default:
printf("CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\n", CStreaming::ms_vehiclesLoaded[index]);
@@ -8387,10 +8438,15 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
ScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages;
StoreParameters(&m_nIp, 1);
return 0;
- case COMMAND_REGISTER_EL_BURRO_TIME:
+ case COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR:
+ {
CollectParameters(&m_nIp, 1);
- CStats::RegisterElBurroTime(ScriptParams[0]);
+ CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
+ assert(pPed);
+ pPed->bScriptObjectiveCompleted = false;
+ pPed->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pPed->m_pMyVehicle);
return 0;
+ }
case COMMAND_SET_SPRITES_DRAW_BEFORE_FADE:
CollectParameters(&m_nIp, 1);
CTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bBeforeFade = ScriptParams[0] != 0;
@@ -8565,21 +8621,17 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pPed->m_nZoneLevel = LEVEL_NONE;
return 0;
}
- case COMMAND_REGISTER_4X4_ONE_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4OneTime(ScriptParams[0]);
+ case COMMAND_SET_DRUNK_INPUT_DELAY:
+ assert(0 && "SET_DRUNK_INPUT_DELAY not yet implemented");
return 0;
- case COMMAND_REGISTER_4X4_TWO_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4TwoTime(ScriptParams[0]);
+ case COMMAND_SET_CHAR_MONEY:
+ assert(0 && "SET_CHAR_MONEY not yet implemented");
return 0;
- case COMMAND_REGISTER_4X4_THREE_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4ThreeTime(ScriptParams[0]);
+ case COMMAND_INCREASE_CHAR_MONEY:
+ assert(0 && "INCREASE_CHAR_MONEY not yet implemented");
return 0;
- case COMMAND_REGISTER_4X4_MAYHEM_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::Register4x4MayhemTime(ScriptParams[0]);
+ case COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS:
+ assert(0 && "GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS not yet implemented");
return 0;
case COMMAND_REGISTER_LIFE_SAVED:
CStats::AnotherLifeSavedWithAmbulance();
@@ -8602,9 +8654,8 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 1);
CStats::RegisterLongestFlightInDodo(ScriptParams[0]);
return 0;
- case COMMAND_REGISTER_DEFUSE_BOMB_TIME:
- CollectParameters(&m_nIp, 1);
- CStats::RegisterTimeTakenDefuseMission(ScriptParams[0]);
+ case COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS:
+ assert(0 && "GET_OFFSET_FROM_CAR_IN_WORLD_COORDS not yet implemented");
return 0;
case COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES:
CollectParameters(&m_nIp, 1);
@@ -8679,8 +8730,13 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
CollectParameters(&m_nIp, 1);
CTimer::Suspend();
int offset = CTheScripts::MultiScriptArray[ScriptParams[0]];
+#ifdef USE_DEBUG_SCRIPT_LOADER
+ CFileMgr::ChangeDir("\\data\\");
+ int handle = CFileMgr::OpenFile(scriptfile, "rb");
+#else
CFileMgr::ChangeDir("\\");
int handle = CFileMgr::OpenFile("data\\main.scm", "rb");
+#endif
CFileMgr::Seek(handle, offset, 0);
CFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT);
CFileMgr::CloseFile(handle);
@@ -9117,7 +9173,6 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);
return 0;
}
-#ifndef GTA_PS2
default:
assert(0);
}
@@ -9128,7 +9183,6 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
{
char tmp[48];
switch (command) {
-#endif
case COMMAND_LOAD_COLLISION_WITH_SCREEN:
CollectParameters(&m_nIp, 1);
CTimer::Stop();
@@ -9194,9 +9248,6 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
case COMMAND_ENABLE_PLAYER_CONTROL_CAMERA:
CPad::GetPad(0)->DisablePlayerControls &= PLAYERCONTROL_DISABLED_1;
return 0;
-#ifndef GTA_PS2
- // To be precise, on PS2 previous handlers were in 1000-1099 function
- // These are "beta" VC commands (with bugs)
case COMMAND_SET_OBJECT_ROTATION:
{
CollectParameters(&m_nIp, 4);
@@ -9485,10 +9536,11 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
{
char zone[KEY_LENGTH_IN_SCRIPT];
strncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);
- int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone);
+// TODO(MIAMI): just getting this to compile with new argument
+ int nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);
if (nZone != -1)
m_nIp += KEY_LENGTH_IN_SCRIPT;
- CZone* pZone = CTheZones::GetZone(nZone);
+ CZone* pZone = CTheZones::GetNavigationZone(nZone);
int ped_handle = -1;
CVector pos = FindPlayerCoors();
int i = CPools::GetPedPool()->GetSize();
@@ -9605,13 +9657,13 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
case COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:
LocateCharObjectCommand(command, &m_nIp);
return 0;
- case COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT: // this will be changed in final VC version to a more general SET_TEMP_ACTION
+ case COMMAND_SET_CAR_TEMP_ACTION:
{
- CollectParameters(&m_nIp, 2);
+ CollectParameters(&m_nIp, 3);
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
assert(pVehicle);
- pVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNLEFT;
- pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];
+ pVehicle->AutoPilot.m_nTempAction = (eCarTempAction)ScriptParams[1];
+ pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[2];
return 0;
}
case COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT:
@@ -9682,23 +9734,443 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
}
case COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER:
CollectParameters(&m_nIp, 1);
-#ifdef FIX_BUGS
CPed::nEnterCarRangeMultiplier = *(float*)&ScriptParams[0];
-#else
- CPed::nEnterCarRangeMultiplier = (float)ScriptParams[0];
-#endif
return 0;
-#endif
-#ifndef GTA3_1_1_PATCH
case COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER:
CollectParameters(&m_nIp, 1);
-#ifdef FIX_BUGS
CPed::nThreatReactionRangeMultiplier = *(float*)&ScriptParams[0];
-#else
- CPed::nThreatReactionRangeMultiplier = (float)ScriptParams[0];
-#endif
return 0;
-#endif
+ case COMMAND_SET_CHAR_CEASE_ATTACK_TIMER:
+ case COMMAND_GET_REMOTE_CONTROLLED_CAR:
+ case COMMAND_IS_PC_VERSION:
+ case COMMAND_REPLAY:
+ case COMMAND_IS_REPLAY_PLAYING:
+ case COMMAND_IS_MODEL_AVAILABLE:
+ case COMMAND_SHUT_CHAR_UP:
+ case COMMAND_SET_ENABLE_RC_DETONATE:
+ assert(0);
+ case COMMAND_SET_CAR_RANDOM_ROUTE_SEED:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ pVehicle->m_nRouteSeed = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_IS_ANY_PICKUP_AT_COORDS:
+ case COMMAND_GET_FIRST_PICKUP_COORDS:
+ case COMMAND_GET_NEXT_PICKUP_COORDS:
+ case COMMAND_REMOVE_ALL_CHAR_WEAPONS:
+ case COMMAND_HAS_PLAYER_GOT_WEAPON:
+ case COMMAND_HAS_CHAR_GOT_WEAPON:
+ case COMMAND_IS_PLAYER_FACING_CHAR:
+ case COMMAND_SET_TANK_DETONATE_CARS:
+ case COMMAND_GET_POSITION_OF_ANALOGUE_STICKS:
+ case COMMAND_IS_CAR_ON_FIRE:
+ case COMMAND_IS_CAR_TYRE_BURST:
+ case COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD:
+ case COMMAND_SET_CAR_WAIT:
+ case COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE:
+ case COMMAND_IS_PLAYER_FOOT_DOWN:
+ case COMMAND_IS_CHAR_FOOT_DOWN:
+ case COMMAND_INITIALISE_OBJECT_PATH:
+ case COMMAND_START_OBJECT_ON_PATH:
+ case COMMAND_SET_OBJECT_PATH_SPEED:
+ case COMMAND_SET_OBJECT_PATH_POSITION:
+ case COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH:
+ case COMMAND_CLEAR_OBJECT_PATH:
+ case COMMAND_HELI_GOTO_COORDS:
+ case COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT:
+ case COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT:
+ case COMMAND_GET_DEAD_CHAR_PICKUP_COORDS:
+ case COMMAND_CREATE_PROTECTION_PICKUP:
+ case COMMAND_IS_CHAR_IN_ANY_BOAT:
+ case COMMAND_IS_PLAYER_IN_ANY_BOAT:
+ case COMMAND_IS_CHAR_IN_ANY_HELI:
+ case COMMAND_IS_PLAYER_IN_ANY_HELI:
+ case COMMAND_IS_CHAR_IN_ANY_PLANE:
+ case COMMAND_IS_PLAYER_IN_ANY_PLANE:
+ case COMMAND_IS_CHAR_IN_WATER:
+ assert(0);
+ case COMMAND_SET_VAR_INT_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);
+ CollectParameters(&m_nIp, 1);
+ *ptr = ScriptParams[0];
+ return 0;
+ }
+ case COMMAND_SET_LVAR_INT_TO_CONSTANT:
+ {
+ int32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);
+ CollectParameters(&m_nIp, 1);
+ *ptr = ScriptParams[0];
+ return 0;
+ }
+ default:
+ assert(0);
+ }
+ return -1;
+}
+
+
+int8 CRunningScript::ProcessCommands1200To1299(int32 command)
+{
+ switch (command) {
+ case COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT:
+ case COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT:
+ case COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR:
+ case COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR:
+ case COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT:
+ case COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT:
+ case COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR:
+ case COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR:
+ case COMMAND_GET_CHAR_WEAPON_IN_SLOT:
+ case COMMAND_GET_CLOSEST_STRAIGHT_ROAD:
+ case COMMAND_SET_CAR_FORWARD_SPEED:
+ assert(0);
+ case COMMAND_SET_AREA_VISIBLE:
+ CollectParameters(&m_nIp, 1);
+ CGame::currArea = ScriptParams[0];
+ // TODO(MIAMI) !!
+ //CStreaming::RemoveBuildingsNotInArea(ScriptParams[0]);
+ return 0;
+ case COMMAND_SET_CUTSCENE_ANIM_TO_LOOP:
+ assert(0);
+ case COMMAND_MARK_CAR_AS_CONVOY_CAR:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);
+ assert(pVehicle);
+ pVehicle->bPartOfConvoy = ScriptParams[1];
+ return 0;
+ }
+ case COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER:
+ case COMMAND_GET_HAVOC_CAUSED_BY_PLAYER:
+ case COMMAND_CREATE_SCRIPT_ROADBLOCK:
+ case COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS:
+ case COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR:
+ case COMMAND_IS_PICKUP_IN_ZONE:
+ case COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS:
+ case COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED:
+ case COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR:
+ case COMMAND_SWITCH_SECURITY_CAMERA:
+ case COMMAND_IS_CHAR_IN_FLYING_VEHICLE:
+ case COMMAND_IS_PLAYER_IN_FLYING_VEHICLE:
+ case COMMAND_HAS_SONY_CD_BEEN_READ:
+ case COMMAND_GET_NUMBER_OF_SONY_CDS_READ:
+ case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD:
+ case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD:
+ assert(0);
+ case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetShortRangeCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[3]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_ADD_MONEY_SPENT_ON_CLOTHES:
+ case COMMAND_SET_HELI_ORIENTATION:
+ case COMMAND_CLEAR_HELI_ORIENTATION:
+ case COMMAND_PLANE_GOTO_COORDS:
+ case COMMAND_GET_NTH_CLOSEST_CAR_NODE:
+ case COMMAND_GET_NTH_CLOSEST_CHAR_NODE:
+ case COMMAND_DRAW_WEAPONSHOP_CORONA:
+ case COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT:
+ case COMMAND_FREEZE_CHAR_POSITION:
+ case COMMAND_SET_CHAR_DROWNS_IN_WATER:
+ case COMMAND_SET_OBJECT_RECORDS_COLLISIONS:
+ case COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING:
+ case COMMAND_REMOVE_RC_BUGGY:
+ case COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN:
+ case COMMAND_GET_CHAR_ARMOUR:
+ case COMMAND_SET_CHAR_ARMOUR:
+ case COMMAND_SET_HELI_STABILISER:
+ case COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE:
+ case COMMAND_POP_CAR_BOOT:
+ case COMMAND_SHUT_PLAYER_UP:
+ case COMMAND_SET_PLAYER_MOOD:
+ assert(0);
+ case COMMAND_REQUEST_COLLISION:
+ {
+ CollectParameters(&m_nIp, 2);
+ CVector2D pos;
+ pos.x = *(float*)&ScriptParams[0];
+ pos.y = *(float*)&ScriptParams[1];
+ CColStore::RequestCollision(pos);
+ return 0;
+ }
+ case COMMAND_LOCATE_OBJECT_2D:
+ case COMMAND_LOCATE_OBJECT_3D:
+ case COMMAND_IS_OBJECT_IN_WATER:
+ case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR:
+ case COMMAND_IS_OBJECT_IN_AREA_2D:
+ case COMMAND_IS_OBJECT_IN_AREA_3D:
+ case COMMAND_TASK_TOGGLE_DUCK:
+ assert(0);
+ case COMMAND_SET_ZONE_CIVILIAN_CAR_INFO:
+ {
+ char label[12];
+ int16 carDensities[CCarCtrl::NUM_CAR_CLASSES] = { 0 };
+ int16 boatDensities[CCarCtrl::NUM_BOAT_CLASSES] = { 0 };
+ int i;
+
+ CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
+ m_nIp += KEY_LENGTH_IN_SCRIPT;
+ CollectParameters(&m_nIp, 12);
+ for (i = 0; i < CCarCtrl::NUM_CAR_CLASSES; i++)
+ carDensities[i] = ScriptParams[i + 1];
+ for (i = 0; i < CCarCtrl::NUM_BOAT_CLASSES; i++)
+ boatDensities[i] = ScriptParams[i + 1 + CCarCtrl::NUM_CAR_CLASSES];
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ if (zone < 0) {
+ debug("Couldn't find zone - %s\n", label);
+ return 0;
+ }
+ while (zone >= 0) {
+ CTheZones::SetZoneCivilianCarInfo(zone, ScriptParams[0], carDensities, boatDensities);
+ zone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);
+ }
+ return 0;
+ }
+ case COMMAND_REQUEST_ANIMATION:
+ case COMMAND_HAS_ANIMATION_LOADED:
+ case COMMAND_REMOVE_ANIMATION:
+ case COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION:
+ case COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION:
+ case COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION:
+ case COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT:
+ case COMMAND_ATTACH_CHAR_TO_OBJECT:
+ case COMMAND_SET_CHAR_AS_PLAYER_FRIEND:
+ case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER:
+ case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING:
+ case COMMAND_ADD_SET_PIECE:
+ case COMMAND_SET_EXTRA_COLOURS:
+ case COMMAND_CLEAR_EXTRA_COLOURS:
+ case COMMAND_CLOSE_CAR_BOOT:
+ case COMMAND_GET_WHEELIE_STATS:
+ case COMMAND_DISARM_CHAR:
+ case COMMAND_BURST_CAR_TYRE:
+ case COMMAND_IS_CHAR_OBJ_NO_OBJ:
+ case COMMAND_IS_PLAYER_WEARING:
+ case COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY:
+ case COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD:
+ case COMMAND_CREATE_SWAT_ROPE:
+ case COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA:
+ case COMMAND_GET_NEAREST_TYRE_TO_POINT:
+ case COMMAND_SET_CAR_MODEL_COMPONENTS:
+ case COMMAND_SWITCH_LIFT_CAMERA:
+ case COMMAND_CLOSE_ALL_CAR_DOORS:
+ case COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D:
+ case COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D:
+ case COMMAND_POP_CAR_BOOT_USING_PHYSICS:
+ case COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA:
+ case COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE:
+ case COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR:
+ case COMMAND_GET_MAX_WANTED_LEVEL:
+ case COMMAND_IS_CHAR_WANDER_PATH_CLEAR:
+ case COMMAND_PRINT_HELP_WITH_NUMBER:
+ case COMMAND_PRINT_HELP_FOREVER:
+ case COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER:
+ default:
+ assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands1300To1399(int32 command)
+{
+ switch (command) {
+ case COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG:
+ case COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE:
+ case COMMAND_IS_MISSION_AUDIO_PLAYING:
+ case COMMAND_CREATE_LOCKED_PROPERTY_PICKUP:
+ {
+ CollectParameters(&m_nIp, 3);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ // TODO(MIAMI) - add text
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_PROPERTY, PICKUP_PROPERTY_LOCKED, 0, 0, false, text);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_CREATE_FORSALE_PROPERTY_PICKUP:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;
+ wchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);
+ // TODO(MIAMI) - add text
+ CPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ ScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_PROPERTY_FORSALE, PICKUP_PROPERTY_FORSALE, ScriptParams[3], 0, false, text);
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_FREEZE_CAR_POSITION:
+ case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR:
+ case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR:
+ case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR:
+ case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR:
+ case COMMAND_GET_RADIO_CHANNEL:
+ case COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS:
+ case COMMAND_IS_CAR_DROWNING_IN_WATER:
+ case COMMAND_IS_CHAR_DROWNING_IN_WATER:
+ case COMMAND_DISABLE_CUTSCENE_SHADOWS:
+ case COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY:
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE:
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT:
+ case COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED:
+ case COMMAND_IS_MISSION_AUDIO_LOADING:
+ case COMMAND_ADD_MONEY_SPENT_ON_WEAPONS:
+ case COMMAND_ADD_MONEY_SPENT_ON_PROPERTY:
+ case COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING:
+ case COMMAND_SET_CHAR_ANSWERING_MOBILE:
+ case COMMAND_SET_PLAYER_DRUNKENNESS:
+ case COMMAND_GET_PLAYER_DRUNKENNESS:
+ case COMMAND_SET_PLAYER_DRUG_LEVEL:
+ case COMMAND_GET_PLAYER_DRUG_LEVEL:
+ case COMMAND_ADD_LOAN_SHARK_VISITS:
+ case COMMAND_ADD_STORES_KNOCKED_OFF:
+ case COMMAND_ADD_MOVIE_STUNTS:
+ case COMMAND_ADD_NUMBER_OF_ASSASSINATIONS:
+ case COMMAND_ADD_PIZZAS_DELIVERED:
+ case COMMAND_ADD_GARBAGE_PICKUPS:
+ case COMMAND_ADD_ICE_CREAMS_SOLD:
+ case COMMAND_SET_TOP_SHOOTING_RANGE_SCORE:
+ case COMMAND_ADD_SHOOTING_RANGE_RANK:
+ case COMMAND_ADD_MONEY_SPENT_ON_GAMBLING:
+ case COMMAND_ADD_MONEY_WON_ON_GAMBLING:
+ case COMMAND_SET_LARGEST_GAMBLING_WIN:
+ case COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT:
+ case COMMAND_CLEAR_CHAR_WAIT_STATE:
+ case COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE:
+ case COMMAND_SET_CAN_BURST_CAR_TYRES:
+ case COMMAND_SET_PLAYER_AUTO_AIM:
+ case COMMAND_FIRE_HUNTER_GUN:
+ case COMMAND_SET_PROPERTY_AS_OWNED:
+ case COMMAND_ADD_BLOOD_RING_KILLS:
+ case COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING:
+ case COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE:
+ case COMMAND_IS_PLAYER_TOUCHING_VEHICLE:
+ case COMMAND_IS_CHAR_TOUCHING_VEHICLE:
+ case COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER:
+ case COMMAND_CLEAR_CHAR_FOLLOW_PATH:
+ case COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE:
+ case COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE:
+ case COMMAND_LOAD_MISSION_TEXT:
+ case COMMAND_SET_TONIGHTS_EVENT:
+ case COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY:
+ case COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY:
+ case COMMAND_FREEZE_OBJECT_POSITION:
+ case COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY:
+ case COMMAND_SET_RIOT_INTENSITY:
+ case COMMAND_IS_CAR_IN_ANGLED_AREA_2D:
+ case COMMAND_IS_CAR_IN_ANGLED_AREA_3D:
+ case COMMAND_REMOVE_WEAPON_FROM_CHAR:
+ case COMMAND_SET_UP_TAXI_SHORTCUT:
+ case COMMAND_CLEAR_TAXI_SHORTCUT:
+ case COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT:
+ case COMMAND_GET_CLOSEST_WATER_NODE:
+ case COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH:
+ case COMMAND_CREATE_CLOTHES_PICKUP:
+ case COMMAND_CHANGE_BLIP_THRESHOLD:
+ case COMMAND_MAKE_PLAYER_FIRE_PROOF:
+ case COMMAND_INCREASE_PLAYER_MAX_HEALTH:
+ case COMMAND_INCREASE_PLAYER_MAX_ARMOUR:
+ case COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER:
+ case COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER:
+ case COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS:
+ case COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON:
+ case COMMAND_MAKE_HELI_COME_CRASHING_DOWN:
+ case COMMAND_ADD_EXPLOSION_NO_SOUND:
+ case COMMAND_SET_OBJECT_AREA_VISIBLE:
+ case COMMAND_WAS_VEHICLE_EVER_POLICE:
+ case COMMAND_SET_CHAR_NEVER_TARGETTED:
+ case COMMAND_LOAD_UNCOMPRESSED_ANIM:
+ case COMMAND_WAS_CUTSCENE_SKIPPED:
+ case COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED:
+ case COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE:
+ case COMMAND_DOES_CHAR_EXIST:
+ case COMMAND_DOES_VEHICLE_EXIST:
+ case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT:
+ case COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT:
+ {
+ CollectParameters(&m_nIp, 4);
+ CVector pos = *(CVector*)&ScriptParams[0];
+ if (pos.z <= MAP_Z_LOW_LIMIT)
+ pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
+ CRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));
+ int id = CRadar::SetShortRangeCoordBlip(BLIP_COORD, pos, 2, BLIP_DISPLAY_BOTH);
+ CRadar::SetBlipSprite(id, ScriptParams[3]);
+ ScriptParams[0] = id;
+ StoreParameters(&m_nIp, 1);
+ return 0;
+ }
+ case COMMAND_IS_CHAR_STUCK:
+ case COMMAND_SET_ALL_TAXIS_HAVE_NITRO:
+ case COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY:
+ case COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION:
+ case COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION:
+ case COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION:
+ case COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION:
+ default:
+ assert(0);
+ }
+ return -1;
+}
+
+int8 CRunningScript::ProcessCommands1400To1499(int32 command)
+{
+ switch (command) {
+ case COMMAND_REGISTER_VIGILANTE_LEVEL:
+ case COMMAND_CLEAR_ALL_CHAR_ANIMS:
+ assert(0);
+ case COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE:
+ CollectParameters(&m_nIp, 2);
+ CGarages::SetMaxNumStoredCarsForGarage(ScriptParams[0], ScriptParams[1]);
+ break;
+ case COMMAND_WANTED_STARS_ARE_FLASHING:
+ case COMMAND_SET_ALLOW_HURRICANES:
+ case COMMAND_PLAY_ANNOUNCEMENT:
+ case COMMAND_SET_PLAYER_IS_IN_STADIUM:
+ case COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER:
+ case COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM:
+ case COMMAND_DISPLAY_RADAR:
+ case COMMAND_REGISTER_BEST_POSITION:
+ case COMMAND_IS_PLAYER_IN_INFO_ZONE:
+ case COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE:
+ case COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED:
+ case COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR:
+ case COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG:
+ case COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG:
+ case COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG:
+ case COMMAND_ADD_BIG_GUN_FLASH:
+ case COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM:
+ case COMMAND_GET_PROGRESS_PERCENTAGE:
+ case COMMAND_SET_SHORTCUT_PICKUP_POINT:
+ case COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION:
+ case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA:
+ case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE:
+ case COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA:
+ case COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS:
+ case COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR:
+ case COMMAND_SET_VEHICLE_TO_FADE_IN:
+ case COMMAND_REGISTER_ODDJOB_MISSION_PASSED:
+ case COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI:
+ case COMMAND_IS_CHAR_DUCKING:
+ case COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI:
+ case COMMAND_REGISTER_FIRE_LEVEL:
+ case COMMAND_IS_AUSTRALIAN_GAME:
+ case COMMAND_DISARM_CAR_BOMB:
default:
assert(0);
}
diff --git a/src/control/Script.h b/src/control/Script.h
index acab66cc..9931f13e 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -6,6 +6,7 @@
class CEntity;
class CBuilding;
+class CPhysical;
class CVehicle;
class CPed;
class CObject;
@@ -131,6 +132,8 @@ public:
void AddEntityToList(int32, uint8);
void RemoveEntityFromList(int32, uint8);
void Process();
+ void CheckIfCollisionHasLoadedForMissionObject();
+ CPhysical* DoesThisEntityWaitForCollision(int i);
};
struct CUpsideDownCarCheckEntry
@@ -372,6 +375,7 @@ private:
friend class CRunningScript;
friend class CHud;
friend void CMissionCleanup::Process();
+ friend class CColStore;
};
@@ -462,9 +466,11 @@ private:
int8 ProcessCommands800To899(int32);
int8 ProcessCommands900To999(int32);
int8 ProcessCommands1000To1099(int32);
-#ifndef GTA_PS2
int8 ProcessCommands1100To1199(int32);
-#endif
+ int8 ProcessCommands1200To1299(int32);
+ int8 ProcessCommands1300To1399(int32);
+ int8 ProcessCommands1400To1499(int32);
+
void LocatePlayerCommand(int32, uint32*);
void LocatePlayerCharCommand(int32, uint32*);
void LocatePlayerCarCommand(int32, uint32*);
diff --git a/src/control/ScriptCommands.h b/src/control/ScriptCommands.h
index 77cf3f0f..67b1b9bc 100644
--- a/src/control/ScriptCommands.h
+++ b/src/control/ScriptCommands.h
@@ -995,7 +995,7 @@ enum {
COMMAND_FORCE_RANDOM_PED_TYPE,
COMMAND_SET_TEXT_DRAW_BEFORE_FADE,
COMMAND_GET_COLLECTABLE1S_COLLECTED,
- COMMAND_REGISTER_EL_BURRO_TIME,
+ COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR,
COMMAND_SET_SPRITES_DRAW_BEFORE_FADE,
COMMAND_SET_TEXT_RIGHT_JUSTIFY,
COMMAND_PRINT_HELP,
@@ -1022,17 +1022,17 @@ enum {
COMMAND_MAKE_PLAYER_SAFE,
COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL,
COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL,
- COMMAND_REGISTER_4X4_ONE_TIME,
- COMMAND_REGISTER_4X4_TWO_TIME,
- COMMAND_REGISTER_4X4_THREE_TIME,
- COMMAND_REGISTER_4X4_MAYHEM_TIME,
+ COMMAND_SET_DRUNK_INPUT_DELAY,
+ COMMAND_SET_CHAR_MONEY,
+ COMMAND_INCREASE_CHAR_MONEY,
+ COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS,
COMMAND_REGISTER_LIFE_SAVED,
COMMAND_REGISTER_CRIMINAL_CAUGHT,
COMMAND_REGISTER_AMBULANCE_LEVEL,
COMMAND_REGISTER_FIRE_EXTINGUISHED,
COMMAND_TURN_PHONE_ON,
COMMAND_REGISTER_LONGEST_DODO_FLIGHT,
- COMMAND_REGISTER_DEFUSE_BOMB_TIME,
+ COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS,
COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES,
COMMAND_BLOW_UP_RC_BUGGY,
COMMAND_REMOVE_CAR_FROM_CHASE,
@@ -1108,7 +1108,6 @@ enum {
COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER,
COMMAND_LOAD_END_OF_GAME_TUNE,
COMMAND_ENABLE_PLAYER_CONTROL_CAMERA,
-#ifndef GTA_PS2
COMMAND_SET_OBJECT_ROTATION,
COMMAND_GET_DEBUG_CAMERA_COORDINATES,
COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR,
@@ -1145,7 +1144,7 @@ enum {
COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D,
COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D,
COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D,
- COMMAND_SET_CAR_HANDBRAKE_TURN_LEFT,
+ COMMAND_SET_CAR_TEMP_ACTION,
COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT,
COMMAND_SET_CAR_HANDBRAKE_STOP,
COMMAND_IS_CHAR_ON_ANY_BIKE,
@@ -1156,8 +1155,286 @@ enum {
COMMAND_IS_CHAR_LYING_DOWN,
COMMAND_CAN_CHAR_SEE_DEAD_CHAR,
COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER,
-#ifndef GTA3_1_1_PATCH
- COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER
-#endif
-#endif
+ COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER,
+ COMMAND_SET_CHAR_CEASE_ATTACK_TIMER,
+ COMMAND_GET_REMOTE_CONTROLLED_CAR,
+ COMMAND_IS_PC_VERSION,
+ COMMAND_REPLAY,
+ COMMAND_IS_REPLAY_PLAYING,
+ COMMAND_IS_MODEL_AVAILABLE,
+ COMMAND_SHUT_CHAR_UP,
+ COMMAND_SET_ENABLE_RC_DETONATE,
+ COMMAND_SET_CAR_RANDOM_ROUTE_SEED,
+ COMMAND_IS_ANY_PICKUP_AT_COORDS,
+ COMMAND_GET_FIRST_PICKUP_COORDS,
+ COMMAND_GET_NEXT_PICKUP_COORDS,
+ COMMAND_REMOVE_ALL_CHAR_WEAPONS,
+ COMMAND_HAS_PLAYER_GOT_WEAPON,
+ COMMAND_HAS_CHAR_GOT_WEAPON,
+ COMMAND_IS_PLAYER_FACING_CHAR,
+ COMMAND_SET_TANK_DETONATE_CARS,
+ COMMAND_GET_POSITION_OF_ANALOGUE_STICKS,
+ COMMAND_IS_CAR_ON_FIRE,
+ COMMAND_IS_CAR_TYRE_BURST,
+ COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD,
+ COMMAND_SET_CAR_WAIT,
+ COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE,
+ COMMAND_IS_PLAYER_FOOT_DOWN,
+ COMMAND_IS_CHAR_FOOT_DOWN,
+ COMMAND_INITIALISE_OBJECT_PATH,
+ COMMAND_START_OBJECT_ON_PATH,
+ COMMAND_SET_OBJECT_PATH_SPEED,
+ COMMAND_SET_OBJECT_PATH_POSITION,
+ COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH,
+ COMMAND_CLEAR_OBJECT_PATH,
+ COMMAND_HELI_GOTO_COORDS,
+ COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT,
+ COMMAND_GET_DEAD_CHAR_PICKUP_COORDS,
+ COMMAND_CREATE_PROTECTION_PICKUP,
+ COMMAND_IS_CHAR_IN_ANY_BOAT,
+ COMMAND_IS_PLAYER_IN_ANY_BOAT,
+ COMMAND_IS_CHAR_IN_ANY_HELI,
+ COMMAND_IS_PLAYER_IN_ANY_HELI,
+ COMMAND_IS_CHAR_IN_ANY_PLANE,
+ COMMAND_IS_PLAYER_IN_ANY_PLANE,
+ COMMAND_IS_CHAR_IN_WATER,
+ COMMAND_SET_VAR_INT_TO_CONSTANT,
+ COMMAND_SET_LVAR_INT_TO_CONSTANT,
+ COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT,
+ COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT,
+ COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR,
+ COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR,
+ COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT,
+ COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR,
+ COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR,
+ COMMAND_GET_CHAR_WEAPON_IN_SLOT,
+ COMMAND_GET_CLOSEST_STRAIGHT_ROAD,
+ COMMAND_SET_CAR_FORWARD_SPEED,
+ COMMAND_SET_AREA_VISIBLE,
+ COMMAND_SET_CUTSCENE_ANIM_TO_LOOP,
+ COMMAND_MARK_CAR_AS_CONVOY_CAR,
+ COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER,
+ COMMAND_GET_HAVOC_CAUSED_BY_PLAYER,
+ COMMAND_CREATE_SCRIPT_ROADBLOCK,
+ COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS,
+ COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR,
+ COMMAND_IS_PICKUP_IN_ZONE,
+ COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS,
+ COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED,
+ COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR,
+ COMMAND_SWITCH_SECURITY_CAMERA,
+ COMMAND_IS_CHAR_IN_FLYING_VEHICLE,
+ COMMAND_IS_PLAYER_IN_FLYING_VEHICLE,
+ COMMAND_HAS_SONY_CD_BEEN_READ,
+ COMMAND_GET_NUMBER_OF_SONY_CDS_READ,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD,
+ COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD,
+ COMMAND_ADD_MONEY_SPENT_ON_CLOTHES,
+ COMMAND_SET_HELI_ORIENTATION,
+ COMMAND_CLEAR_HELI_ORIENTATION,
+ COMMAND_PLANE_GOTO_COORDS,
+ COMMAND_GET_NTH_CLOSEST_CAR_NODE,
+ COMMAND_GET_NTH_CLOSEST_CHAR_NODE,
+ COMMAND_DRAW_WEAPONSHOP_CORONA,
+ COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT,
+ COMMAND_FREEZE_CHAR_POSITION,
+ COMMAND_SET_CHAR_DROWNS_IN_WATER,
+ COMMAND_SET_OBJECT_RECORDS_COLLISIONS,
+ COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING,
+ COMMAND_REMOVE_RC_BUGGY,
+ COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN,
+ COMMAND_GET_CHAR_ARMOUR,
+ COMMAND_SET_CHAR_ARMOUR,
+ COMMAND_SET_HELI_STABILISER,
+ COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE,
+ COMMAND_POP_CAR_BOOT,
+ COMMAND_SHUT_PLAYER_UP,
+ COMMAND_SET_PLAYER_MOOD,
+ COMMAND_REQUEST_COLLISION,
+ COMMAND_LOCATE_OBJECT_2D,
+ COMMAND_LOCATE_OBJECT_3D,
+ COMMAND_IS_OBJECT_IN_WATER,
+ COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR,
+ COMMAND_IS_OBJECT_IN_AREA_2D,
+ COMMAND_IS_OBJECT_IN_AREA_3D,
+ COMMAND_TASK_TOGGLE_DUCK,
+ COMMAND_SET_ZONE_CIVILIAN_CAR_INFO,
+ COMMAND_REQUEST_ANIMATION,
+ COMMAND_HAS_ANIMATION_LOADED,
+ COMMAND_REMOVE_ANIMATION,
+ COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION,
+ COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT,
+ COMMAND_ATTACH_CHAR_TO_OBJECT,
+ COMMAND_SET_CHAR_AS_PLAYER_FRIEND,
+ COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER,
+ COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING,
+ COMMAND_ADD_SET_PIECE,
+ COMMAND_SET_EXTRA_COLOURS,
+ COMMAND_CLEAR_EXTRA_COLOURS,
+ COMMAND_CLOSE_CAR_BOOT,
+ COMMAND_GET_WHEELIE_STATS,
+ COMMAND_DISARM_CHAR,
+ COMMAND_BURST_CAR_TYRE,
+ COMMAND_IS_CHAR_OBJ_NO_OBJ,
+ COMMAND_IS_PLAYER_WEARING,
+ COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY,
+ COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD,
+ COMMAND_CREATE_SWAT_ROPE,
+ COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA,
+ COMMAND_GET_NEAREST_TYRE_TO_POINT,
+ COMMAND_SET_CAR_MODEL_COMPONENTS,
+ COMMAND_SWITCH_LIFT_CAMERA,
+ COMMAND_CLOSE_ALL_CAR_DOORS,
+ COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D,
+ COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D,
+ COMMAND_POP_CAR_BOOT_USING_PHYSICS,
+ COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA,
+ COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE,
+ COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR,
+ COMMAND_GET_MAX_WANTED_LEVEL,
+ COMMAND_IS_CHAR_WANDER_PATH_CLEAR,
+ COMMAND_PRINT_HELP_WITH_NUMBER,
+ COMMAND_PRINT_HELP_FOREVER,
+ COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER,
+ COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG,
+ COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE,
+ COMMAND_IS_MISSION_AUDIO_PLAYING,
+ COMMAND_CREATE_LOCKED_PROPERTY_PICKUP,
+ COMMAND_CREATE_FORSALE_PROPERTY_PICKUP,
+ COMMAND_FREEZE_CAR_POSITION,
+ COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR,
+ COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR,
+ COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR,
+ COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR,
+ COMMAND_GET_RADIO_CHANNEL,
+ COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS,
+ COMMAND_IS_CAR_DROWNING_IN_WATER,
+ COMMAND_IS_CHAR_DROWNING_IN_WATER,
+ COMMAND_DISABLE_CUTSCENE_SHADOWS,
+ COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT,
+ COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED,
+ COMMAND_IS_MISSION_AUDIO_LOADING,
+ COMMAND_ADD_MONEY_SPENT_ON_WEAPONS,
+ COMMAND_ADD_MONEY_SPENT_ON_PROPERTY,
+ COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING,
+ COMMAND_SET_CHAR_ANSWERING_MOBILE,
+ COMMAND_SET_PLAYER_DRUNKENNESS,
+ COMMAND_GET_PLAYER_DRUNKENNESS,
+ COMMAND_SET_PLAYER_DRUG_LEVEL,
+ COMMAND_GET_PLAYER_DRUG_LEVEL,
+ COMMAND_ADD_LOAN_SHARK_VISITS,
+ COMMAND_ADD_STORES_KNOCKED_OFF,
+ COMMAND_ADD_MOVIE_STUNTS,
+ COMMAND_ADD_NUMBER_OF_ASSASSINATIONS,
+ COMMAND_ADD_PIZZAS_DELIVERED,
+ COMMAND_ADD_GARBAGE_PICKUPS,
+ COMMAND_ADD_ICE_CREAMS_SOLD,
+ COMMAND_SET_TOP_SHOOTING_RANGE_SCORE,
+ COMMAND_ADD_SHOOTING_RANGE_RANK,
+ COMMAND_ADD_MONEY_SPENT_ON_GAMBLING,
+ COMMAND_ADD_MONEY_WON_ON_GAMBLING,
+ COMMAND_SET_LARGEST_GAMBLING_WIN,
+ COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT,
+ COMMAND_CLEAR_CHAR_WAIT_STATE,
+ COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE,
+ COMMAND_SET_CAN_BURST_CAR_TYRES,
+ COMMAND_SET_PLAYER_AUTO_AIM,
+ COMMAND_FIRE_HUNTER_GUN,
+ COMMAND_SET_PROPERTY_AS_OWNED,
+ COMMAND_ADD_BLOOD_RING_KILLS,
+ COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING,
+ COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE,
+ COMMAND_IS_PLAYER_TOUCHING_VEHICLE,
+ COMMAND_IS_CHAR_TOUCHING_VEHICLE,
+ COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER,
+ COMMAND_CLEAR_CHAR_FOLLOW_PATH,
+ COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE,
+ COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE,
+ COMMAND_LOAD_MISSION_TEXT,
+ COMMAND_SET_TONIGHTS_EVENT,
+ COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY,
+ COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY,
+ COMMAND_FREEZE_OBJECT_POSITION,
+ COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY,
+ COMMAND_SET_RIOT_INTENSITY,
+ COMMAND_IS_CAR_IN_ANGLED_AREA_2D,
+ COMMAND_IS_CAR_IN_ANGLED_AREA_3D,
+ COMMAND_REMOVE_WEAPON_FROM_CHAR,
+ COMMAND_SET_UP_TAXI_SHORTCUT,
+ COMMAND_CLEAR_TAXI_SHORTCUT,
+ COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT,
+ COMMAND_GET_CLOSEST_WATER_NODE,
+ COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH,
+ COMMAND_CREATE_CLOTHES_PICKUP,
+ COMMAND_CHANGE_BLIP_THRESHOLD,
+ COMMAND_MAKE_PLAYER_FIRE_PROOF,
+ COMMAND_INCREASE_PLAYER_MAX_HEALTH,
+ COMMAND_INCREASE_PLAYER_MAX_ARMOUR,
+ COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER,
+ COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER,
+ COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS,
+ COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON,
+ COMMAND_MAKE_HELI_COME_CRASHING_DOWN,
+ COMMAND_ADD_EXPLOSION_NO_SOUND,
+ COMMAND_SET_OBJECT_AREA_VISIBLE,
+ COMMAND_WAS_VEHICLE_EVER_POLICE,
+ COMMAND_SET_CHAR_NEVER_TARGETTED,
+ COMMAND_LOAD_UNCOMPRESSED_ANIM,
+ COMMAND_WAS_CUTSCENE_SKIPPED,
+ COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED,
+ COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE,
+ COMMAND_DOES_CHAR_EXIST,
+ COMMAND_DOES_VEHICLE_EXIST,
+ COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT,
+ COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT,
+ COMMAND_IS_CHAR_STUCK,
+ COMMAND_SET_ALL_TAXIS_HAVE_NITRO,
+ COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY,
+ COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION,
+ COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION,
+ COMMAND_REGISTER_VIGILANTE_LEVEL,
+ COMMAND_CLEAR_ALL_CHAR_ANIMS,
+ COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE,
+ COMMAND_WANTED_STARS_ARE_FLASHING,
+ COMMAND_SET_ALLOW_HURRICANES,
+ COMMAND_PLAY_ANNOUNCEMENT,
+ COMMAND_SET_PLAYER_IS_IN_STADIUM,
+ COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER,
+ COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM,
+ COMMAND_DISPLAY_RADAR,
+ COMMAND_REGISTER_BEST_POSITION,
+ COMMAND_IS_PLAYER_IN_INFO_ZONE,
+ COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE,
+ COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED,
+ COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR,
+ COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG,
+ COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG,
+ COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG,
+ COMMAND_ADD_BIG_GUN_FLASH,
+ COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM,
+ COMMAND_GET_PROGRESS_PERCENTAGE,
+ COMMAND_SET_SHORTCUT_PICKUP_POINT,
+ COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION,
+ COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA,
+ COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE,
+ COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA,
+ COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS,
+ COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR,
+ COMMAND_SET_VEHICLE_TO_FADE_IN,
+ COMMAND_REGISTER_ODDJOB_MISSION_PASSED,
+ COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI,
+ COMMAND_IS_CHAR_DUCKING,
+ COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI,
+ COMMAND_REGISTER_FIRE_LEVEL,
+ COMMAND_IS_AUSTRALIAN_GAME,
+ COMMAND_DISARM_CAR_BOMB,
}; \ No newline at end of file
diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp
index b2f0900e..f2dd6814 100644
--- a/src/control/TrafficLights.cpp
+++ b/src/control/TrafficLights.cpp
@@ -273,8 +273,12 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
bool
CTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle)
{
+#ifdef GTA_BRIDGE
return ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights &&
!ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights;
+#else
+ return false;
+#endif
}
int