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.h13
-rw-r--r--src/control/Bridge.cpp14
-rw-r--r--src/control/CarAI.cpp262
-rw-r--r--src/control/CarAI.h5
-rw-r--r--src/control/CarCtrl.cpp54
-rw-r--r--src/control/CarCtrl.h1
-rw-r--r--src/control/Garages.cpp5
-rw-r--r--src/control/PathFind.cpp909
-rw-r--r--src/control/PathFind.h150
-rw-r--r--src/control/Record.cpp426
-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/Script.cpp69
-rw-r--r--src/control/Script.h1
-rw-r--r--src/control/TrafficLights.cpp4
17 files changed, 905 insertions, 1045 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 345f4cb4..24e7cc53 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);
@@ -119,4 +131,3 @@ public:
#endif
};
-static_assert(sizeof(CAutoPilot) == 0x70, "CAutoPilot: error"); \ No newline at end of file
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 3e22ee77..571a62d2 100644
--- a/src/control/CarAI.cpp
+++ b/src/control/CarAI.cpp
@@ -21,16 +21,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 +41,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 +85,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 +130,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,15 +141,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_BLOCKPLAYER_CLOSE:
if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||
@@ -178,20 +171,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 +188,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 +248,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 +271,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 &&
+#ifdef FIX_BUGS // btw fixed in SA
+ if (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
- )
-#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 +316,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 +357,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 +378,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 +391,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 +428,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;
@@ -445,13 +474,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){
@@ -469,6 +528,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)
@@ -488,23 +557,41 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
if (FindPlayerPed()->m_pWanted->m_nWantedLevel > 1)
pVehicle->SetupPassenger(0);
return;
+ case MI_PREDATOR:
+ pVehicle->SetUpDriver();
+ return;
+//TODO(MIAMI) uncomment this when we have MI_VICECHEE
+/*
+ case MI_VICECHEE:
+ {
+ pVehicle->SetUpDriver()->bIsMiamiViceCop = true;
+ pVehicle->SetUpPassenger(0)->bIsMiamiViceCop = 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){
@@ -515,11 +602,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;
@@ -529,6 +637,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;
@@ -538,6 +647,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){
@@ -552,6 +662,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) {
@@ -566,6 +692,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){
@@ -604,8 +731,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();
@@ -628,6 +774,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 9b2bd4f0..6a5d37f3 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -696,7 +696,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
if (pVehicle->bExtendedRange)
threshold *= 1.5f;
if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
- if (pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) {
+ if (pVehicle->GetIsOnScreen()){
pVehicle->bFadeOut = true;
}else{
CWorld::Remove(pVehicle);
@@ -722,7 +722,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);
@@ -1641,41 +1641,13 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
CPathNode* pTargetNode;
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, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1);
int newNextNode;
int nextLink;
@@ -2741,7 +2713,21 @@ bool CCarCtrl::ThisRoadObjectCouldMove(int16 mi)
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 44ef9ab6..4f92bdcf 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -104,6 +104,7 @@ public:
static void ClearInterestingVehicleList();
static void FindLinksToGoWithTheseNodes(CVehicle*);
static bool GenerateOneEmergencyServicesCar(uint32, CVector);
+ static float FindSpeedMultiplierWithSpeedFromNodes(int8);
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index b6786598..249b91ef 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -156,10 +156,7 @@ void CGarages::Init(void)
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);
+ // MIAMI: removed crusher
}
#ifndef PS2
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp
index ee15b82f..a5493a8f 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)
@@ -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].flag02 = 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].flag02 = 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].flag02 = 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 unk)
+{
+ 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].flag02 = unk;
+ 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(DetachedInfoForTilePeds[i*12 + j].type == NodeTypeExtern){
+ // MI:%d here but no argument for it
+ if(DetachedInfoForTilePeds[i*12 + j].numLeftLanes < 0)
+ printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i);
+ if(DetachedInfoForTilePeds[i*12 + j].numRightLanes < 0)
+ printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i);
+ if(DetachedInfoForTilePeds[i*12 + j].numLeftLanes + DetachedInfoForTilePeds[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].flagB2 = objectpathinfo[start + j].flag02;
+ 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].flagB2 = detachednodes[start + j].flag02;
+ 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)
{
@@ -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 8049ea52..a83f97ae 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
@@ -55,31 +52,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;
+ uint8 bUseInRoadBlock : 1;
- int8 group;
+ uint8 bWaterPath : 1;
+ uint8 flagB2 : 1; // flag 2 in node info, always zero
+ uint8 flagB4 : 1; // where is this set?
+ uint8 speedLimit : 2;
+ //uint8 flagB20 : 1;
+ //uint8 flagB40 : 1;
+ //uint8 flagB80 : 1;
- 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; }
+ uint8 spawnRate : 4;
+ uint8 flagsC : 4;
- CPathNode *GetPrev(void) { return prev; }
- CPathNode *GetNext(void) { return next; }
- void SetPrev(CPathNode *node) { prev = node; }
- void SetNext(CPathNode *node) { next = node; }
+ 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
@@ -93,22 +101,24 @@ union CConnectionFlags
struct CCarPathLink
{
- CVector2D pos;
- CVector2D dir;
+ int16 x;
+ int16 y;
int16 pathNodeIndex;
- int8 numLeftLanes;
- int8 numRightLanes;
- uint8 trafficLightType;
-
- uint8 bBridgeLights : 1;
- // more?
+ 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 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; }
+ 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 OneWayLaneOffset()
{
@@ -123,14 +133,26 @@ struct CCarPathLink
// 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 flag02 : 1; // always zero
+ uint8 roadBlock : 1;
+ uint8 disabled : 1;
+ uint8 waterPath : 1;
+ uint8 betweenLevels : 1;
+
+ uint8 spawnRate : 4;
+
+ void SwapConnectionsToBeRightWayRound(void);
};
extern CPathInfoForObject *InfoForTileCars;
extern CPathInfoForObject *InfoForTilePeds;
@@ -138,18 +160,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
@@ -158,10 +187,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;
@@ -177,14 +204,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); }
@@ -202,29 +234,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);
};
-static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error");
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/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/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 1c0d9f96..3a271170 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/Script.cpp b/src/control/Script.cpp
index a274c289..8db2db81 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -506,7 +506,7 @@ void CRunningScript::Init()
#ifdef USE_DEBUG_SCRIPT_LOADER
int open_script()
{
- static int scriptToLoad = 0;
+ static int scriptToLoad = 1;
if (GetAsyncKeyState('G') & 0x8000)
scriptToLoad = 0;
@@ -517,7 +517,7 @@ int open_script()
switch (scriptToLoad) {
case 0: return CFileMgr::OpenFile("main.scm", "rb");
- case 1: return CFileMgr::OpenFile("main_freeroam.scm", "rb");
+ case 1: return CFileMgr::OpenFile("freeroam_miami.scm", "rb");
case 2: return CFileMgr::OpenFile("main_d.scm", "rb");
}
return CFileMgr::OpenFile("main.scm", "rb");
@@ -2669,11 +2669,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;
}
@@ -3001,7 +3001,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
m_nIp += KEY_LENGTH_IN_SCRIPT;
CollectParameters(&m_nIp, 16);
- int zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ int zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
if (zone < 0) {
debug("Couldn't find zone - %s\n", label);
return 0;
@@ -3022,41 +3022,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);
@@ -3092,7 +3068,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
m_nIp += KEY_LENGTH_IN_SCRIPT;
CollectParameters(&m_nIp, 10);
- int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label);
+ int16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);
if (zone < 0) {
debug("Couldn't find zone - %s\n", label);
return 0;
@@ -5853,10 +5829,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();
@@ -6461,7 +6437,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;
@@ -6521,10 +6497,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();
@@ -7027,10 +7004,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;
@@ -7162,7 +7140,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++) {
@@ -7914,7 +7892,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++) {
@@ -9440,10 +9418,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();
diff --git a/src/control/Script.h b/src/control/Script.h
index 01cad269..a44fc7c1 100644
--- a/src/control/Script.h
+++ b/src/control/Script.h
@@ -372,6 +372,7 @@ private:
friend class CRunningScript;
friend class CHud;
friend void CMissionCleanup::Process();
+ friend class CColStore;
};
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