diff options
Diffstat (limited to 'src/control')
-rw-r--r-- | src/control/AutoPilot.cpp | 4 | ||||
-rw-r--r-- | src/control/AutoPilot.h | 13 | ||||
-rw-r--r-- | src/control/Bridge.cpp | 14 | ||||
-rw-r--r-- | src/control/CarAI.cpp | 266 | ||||
-rw-r--r-- | src/control/CarAI.h | 5 | ||||
-rw-r--r-- | src/control/CarCtrl.cpp | 62 | ||||
-rw-r--r-- | src/control/CarCtrl.h | 1 | ||||
-rw-r--r-- | src/control/Garages.cpp | 5 | ||||
-rw-r--r-- | src/control/PathFind.cpp | 911 | ||||
-rw-r--r-- | src/control/PathFind.h | 150 | ||||
-rw-r--r-- | src/control/Record.cpp | 426 | ||||
-rw-r--r-- | src/control/Restart.cpp | 8 | ||||
-rw-r--r-- | src/control/RoadBlocks.cpp | 21 | ||||
-rw-r--r-- | src/control/RoadBlocks.h | 4 | ||||
-rw-r--r-- | src/control/Script.cpp | 161 | ||||
-rw-r--r-- | src/control/Script.h | 4 | ||||
-rw-r--r-- | src/control/TrafficLights.cpp | 4 |
17 files changed, 1008 insertions, 1051 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..0330d80d 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,20 +141,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (pVehicle->UsesSiren(pVehicle->GetModelIndex())) pVehicle->m_bSirenOrAlarm = true; } - if (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer && - (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) { - CCarCtrl::JoinCarWithRoadSystem(pVehicle); - pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; - pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; - pVehicle->m_bSirenOrAlarm = false; - if (CCullZones::NoPolice()) - pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - } + BackToCruisingIfNoWantedLevel(pVehicle); break; case MISSION_BLOCKPLAYER_CLOSE: if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() || pVehicle->AutoPilot.m_bIgnorePathfinding) { - if (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f) + if (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f) #ifdef FIX_BUGS pVehicle->m_nTimeBlocked += CTimer::GetTimeStepInMilliseconds(); #else @@ -162,7 +155,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) else pVehicle->m_nTimeBlocked = 0; if (!FindPlayerVehicle() || FindPlayerVehicle()->IsUpsideDown() || - FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) { + FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) { if (pVehicle->bIsLawEnforcer && (pVehicle->GetModelIndex() != MI_RHINO || pVehicle->m_randomSeed > 10000) && (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() < 10.0f) { @@ -178,20 +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 && -#endif - (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer && - (FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) -#ifdef FIX_BUGS - ) +#ifdef FIX_BUGS // btw fixed in SA + if (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar) #endif - { - CCarCtrl::JoinCarWithRoadSystem(pVehicle); - pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; - pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; - pVehicle->m_bSirenOrAlarm = false; - if (CCullZones::NoPolice()) - pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - } + BackToCruisingIfNoWantedLevel(pVehicle); if ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() <= FindSwitchDistanceFar(pVehicle) || pVehicle->AutoPilot.m_bIgnorePathfinding){ if (pVehicle->GetHasCollidedWith(pVehicle->AutoPilot.m_pTargetCar)){ @@ -336,6 +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..a4769d56 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -90,14 +90,16 @@ uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP]; void CCarCtrl::GenerateRandomCars() { - if (CCutsceneMgr::IsRunning()) + if (CCutsceneMgr::IsRunning()) { + CountDownToCarsAtStart = 2; return; + } if (NumRandomCars < 30){ if (CountDownToCarsAtStart == 0){ GenerateOneRandomCar(); } else if (--CountDownToCarsAtStart == 0) { - for (int i = 0; i < 50; i++) + for (int i = 0; i < 100; i++) GenerateOneRandomCar(); CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = 20; } @@ -354,7 +356,7 @@ CCarCtrl::GenerateOneRandomCar() pCar->m_bSirenOrAlarm = true; pCar->AutoPilot.m_nNextPathNodeInfo = connectionId; pCar->AutoPilot.m_nNextLane = pCar->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad; - CColBox* boundingBox = &CModelInfo::GetModelInfo(pCar->GetModelIndex())->GetColModel()->boundingBox; + CBox* boundingBox = &CModelInfo::GetModelInfo(pCar->GetModelIndex())->GetColModel()->boundingBox; float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2; float distanceBetweenNodes = (pCurNode->GetPosition() - pNextNode->GetPosition()).Magnitude2D(); /* If car is so long that it doesn't fit between two car nodes, place it directly in the middle. */ @@ -696,7 +698,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 +724,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 +1643,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, -#ifdef FIX_PATHFIND_BUG - CVector(targetX, targetY, targetZ), -#else - CVector(targetX, targetY, 0.0f), -#endif - &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode); - }else - { - - 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, -1); - } + &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1); int newNextNode; int nextLink; @@ -2741,7 +2715,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..22221e73 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -18,21 +18,21 @@ CPathFind ThePaths; #define MIN_PED_ROUTE_DISTANCE 23.8f -#define NUMTEMPNODES 4000 -#define NUMDETACHED_CARS 100 -#define NUMDETACHED_PEDS 50 +#define NUMTEMPNODES 5000 +#define NUMDETACHED_CARS 1024 +#define NUMDETACHED_PEDS 1214 +#define NUMTEMPEXTERNALNODES 4600 -// object flags: -// 1 UseInRoadBlock -// 2 east/west road(?) - CPathInfoForObject *InfoForTileCars; CPathInfoForObject *InfoForTilePeds; -// unused -CTempDetachedNode *DetachedNodesCars; -CTempDetachedNode *DetachedNodesPeds; +CPathInfoForObject *DetachedInfoForTileCars; +CPathInfoForObject *DetachedInfoForTilePeds; +CTempNodeExternal *TempExternalNodes; +int32 NumTempExternalNodes; +int32 NumDetachedPedNodeGroups; +int32 NumDetachedCarNodeGroups; bool CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints) @@ -197,7 +197,7 @@ CPedPath::AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CV void CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition) { - const CColBox& boundingBox = pEntity->GetColModel()->boundingBox; + const CBox& boundingBox = pEntity->GetColModel()->boundingBox; const float fBoundMaxY = boundingBox.max.y + 0.3f; const float fBoundMinY = boundingBox.min.y - 0.3f; const float fBoundMaxX = boundingBox.max.x + 0.3f; @@ -227,6 +227,27 @@ CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *p } } +//--MIAMI: done +// Make sure all externals link TO an internal +void +CPathInfoForObject::SwapConnectionsToBeRightWayRound(void) +{ + int e, i; + CPathInfoForObject *tile = this; + + for(e = 0; e < 12; e++) + if(tile[e].type == NodeTypeExtern && tile[e].next < 0) + for(i = 0; i < 12; i++) + if(tile[i].type == NodeTypeIntern && tile[i].next == e){ + tile[e].next = i; + tile[i].next = -1; + bool tmp = !!tile[e].crossing; + tile[e].crossing = tile[i].crossing; + tile[i].crossing = tmp; + } +} + +//--MIAMI: done void CPathFind::Init(void) { @@ -237,11 +258,13 @@ CPathFind::Init(void) m_numConnections = 0; m_numCarPathLinks = 0; unk = 0; + NumTempExternalNodes = 0; for(i = 0; i < NUM_PATHNODES; i++) m_pathNodes[i].distance = MAX_DIST; } +//--MIAMI: done void CPathFind::AllocatePathFindInfoMem(int16 numPathGroups) { @@ -250,93 +273,172 @@ CPathFind::AllocatePathFindInfoMem(int16 numPathGroups) delete[] InfoForTilePeds; InfoForTilePeds = nil; - // NB: MIAMI doesn't use numPathGroups here but hardcodes 4500 - InfoForTileCars = new CPathInfoForObject[12*numPathGroups]; - memset(InfoForTileCars, 0, 12*numPathGroups*sizeof(CPathInfoForObject)); - InfoForTilePeds = new CPathInfoForObject[12*numPathGroups]; - memset(InfoForTilePeds, 0, 12*numPathGroups*sizeof(CPathInfoForObject)); - - // unused - delete[] DetachedNodesCars; - DetachedNodesCars = nil; - delete[] DetachedNodesPeds; - DetachedNodesPeds = nil; - DetachedNodesCars = new CTempDetachedNode[NUMDETACHED_CARS]; - memset(DetachedNodesCars, 0, NUMDETACHED_CARS*sizeof(CTempDetachedNode)); - DetachedNodesPeds = new CTempDetachedNode[NUMDETACHED_PEDS]; - memset(DetachedNodesPeds, 0, NUMDETACHED_PEDS*sizeof(CTempDetachedNode)); + // NB: MIAMI doesn't use numPathGroups here but hardcodes PATHNODESIZE + InfoForTileCars = new CPathInfoForObject[12*PATHNODESIZE]; + memset(InfoForTileCars, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject)); + InfoForTilePeds = new CPathInfoForObject[12*PATHNODESIZE]; + memset(InfoForTilePeds, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject)); + + delete[] DetachedInfoForTileCars; + DetachedInfoForTileCars = nil; + delete[] DetachedInfoForTilePeds; + DetachedInfoForTilePeds = nil; + DetachedInfoForTileCars = new CPathInfoForObject[12*NUMDETACHED_CARS]; + memset(DetachedInfoForTileCars, 0, 12*NUMDETACHED_CARS*sizeof(CPathInfoForObject)); + DetachedInfoForTilePeds = new CPathInfoForObject[12*NUMDETACHED_PEDS]; + memset(DetachedInfoForTilePeds, 0, 12*NUMDETACHED_PEDS*sizeof(CPathInfoForObject)); + + TempExternalNodes = new CTempNodeExternal[NUMTEMPEXTERNALNODES]; + memset(TempExternalNodes, 0, NUMTEMPEXTERNALNODES*sizeof(CTempNodeExternal)); + NumTempExternalNodes = 0; + NumDetachedPedNodeGroups = 0; + NumDetachedCarNodeGroups = 0; } +//--MIAMI: done void CPathFind::RegisterMapObject(CTreadable *mapObject) { m_mapObjects[m_numMapObjects++] = mapObject; } +//--MIAMI: done void -CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing) +CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate) { - int i, j; + int i; i = id*12 + node; InfoForTilePeds[i].type = type; InfoForTilePeds[i].next = next; - InfoForTilePeds[i].x = x; - InfoForTilePeds[i].y = y; - InfoForTilePeds[i].z = z; + InfoForTilePeds[i].x = x/16.0f; + InfoForTilePeds[i].y = y/16.0f; + InfoForTilePeds[i].z = z/16.0f; + InfoForTilePeds[i].width = 8.0f*Min(width, 15.0f); InfoForTilePeds[i].numLeftLanes = 0; InfoForTilePeds[i].numRightLanes = 0; InfoForTilePeds[i].crossing = crossing; - - if(type) - for(i = 0; i < node; i++){ - j = id*12 + i; - if(x == InfoForTilePeds[j].x && y == InfoForTilePeds[j].y){ - printf("^^^^^^^^^^^^^ AARON IS TOO CHICKEN TO EAT MEAT!\n"); - printf("Several ped nodes on one road segment have identical coordinates (%d==%d && %d==%d)\n", - x, InfoForTilePeds[j].x, y, InfoForTilePeds[j].y); - printf("Modelindex of cullprit: %d\n\n", id); - } - } + InfoForTilePeds[i].speedLimit = 0; + InfoForTilePeds[i].roadBlock = false; + InfoForTilePeds[i].disabled = false; + InfoForTilePeds[i].waterPath = false; + InfoForTilePeds[i].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..3636e5e8 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -13,6 +13,7 @@ #include "CarGen.h" #include "CivilianPed.h" #include "Clock.h" +#include "ColStore.h" #include "CopPed.h" #include "Coronas.h" #include "Cranes.h" @@ -170,10 +171,46 @@ void CMissionCleanup::AddEntityToList(int32 id, uint8 type) m_nCount++; } +static void PossiblyWakeThisEntity(CPhysical* pEntity) +{ + if (!pEntity->bIsStaticWaitingForCollision) + return; + if (CColStore::HasCollisionLoaded(pEntity->GetPosition())) { + pEntity->bIsStaticWaitingForCollision = false; + if (!pEntity->IsStatic()) + pEntity->AddToMovingList(); + } +} + void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type) { for (int i = 0; i < MAX_CLEANUP; i++){ if (m_sEntities[i].type == type && m_sEntities[i].id == id){ + switch (m_sEntities[i].type) { + case CLEANUP_CAR: + { + CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id); + if (v) + PossiblyWakeThisEntity(v); + break; + } + case CLEANUP_CHAR: + { + CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id); + if (p) + PossiblyWakeThisEntity(p); + break; + } + case CLEANUP_OBJECT: + { + CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id); + if (o) + PossiblyWakeThisEntity(o); + break; + } + default: + break; + } m_sEntities[i].id = 0; m_sEntities[i].type = CLEANUP_UNUSED; m_nCount--; @@ -181,6 +218,52 @@ void CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type) } } +void CMissionCleanup::CheckIfCollisionHasLoadedForMissionObject() +{ + for (int i = 0; i < MAX_CLEANUP; i++) { + switch (m_sEntities[i].type) { + case CLEANUP_CAR: + { + CVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id); + if (v) + PossiblyWakeThisEntity(v); + break; + } + case CLEANUP_CHAR: + { + CPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id); + if (p) + PossiblyWakeThisEntity(p); + break; + } + case CLEANUP_OBJECT: + { + CObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id); + if (o) + PossiblyWakeThisEntity(o); + break; + } + default: + break; + } + } +} + +CPhysical* CMissionCleanup::DoesThisEntityWaitForCollision(int i) +{ + if (m_sEntities[i].type == CLEANUP_CAR) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id); + if (pVehicle && pVehicle->GetStatus() != STATUS_WRECKED) + return pVehicle; + } + else if (m_sEntities[i].type == CLEANUP_CHAR) { + CPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id); + if (pPed && !pPed->DyingOrDead()) + return pPed; + } + return nil; +} + void CMissionCleanup::Process() { CPopulation::m_AllRandomPedsThisType = -1; @@ -506,7 +589,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 +600,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"); @@ -646,6 +729,7 @@ void CTheScripts::Process() float timeStep = CTimer::GetTimeStepInMilliseconds(); UpsideDownCars.UpdateTimers(); StuckCars.Process(); + MissionCleanup.CheckIfCollisionHasLoadedForMissionObject(); DrawScriptSpheres(); if (FailCurrentMission) --FailCurrentMission; @@ -1728,6 +1812,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) ped->SetPosition(pos); ped->SetOrientation(0.0f, 0.0f, 0.0f); CTheScripts::ClearSpaceForMissionEntity(pos, ped); + if (m_bIsMissionScript) + ped->bIsStaticWaitingForCollision = true; CWorld::Add(ped); ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); CPopulation::ms_nTotalMissionPeds++; @@ -1946,6 +2032,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) boat->AutoPilot.m_nCarMission = MISSION_NONE; boat->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */ boat->AutoPilot.m_nCruiseSpeed = boat->AutoPilot.m_fMaxTrafficSpeed = 20.0f; + if (m_bIsMissionScript) + boat->bIsStaticWaitingForCollision = true; CWorld::Add(boat); handle = CPools::GetVehiclePool()->GetIndex(boat); } @@ -1970,6 +2058,8 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) car->bEngineOn = false; car->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); car->bHasBeenOwnedByPlayer = true; + if (m_bIsMissionScript) + car->bIsStaticWaitingForCollision = true; CWorld::Add(car); handle = CPools::GetVehiclePool()->GetIndex(car); } @@ -2669,11 +2759,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 +3091,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 +3112,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 +3158,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 +5919,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 +6527,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 +6587,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 +7094,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 +7230,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++) { @@ -7346,6 +7414,8 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) ped->SetPosition(pos); ped->SetOrientation(0.0f, 0.0f, 0.0f); CTheScripts::ClearSpaceForMissionEntity(pos, ped); + if (m_bIsMissionScript) + ped->bIsStaticWaitingForCollision = true; CWorld::Add(ped); ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); CPopulation::ms_nTotalMissionPeds++; @@ -7914,7 +7984,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 +9510,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..46c6ae20 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -6,6 +6,7 @@ class CEntity; class CBuilding; +class CPhysical; class CVehicle; class CPed; class CObject; @@ -131,6 +132,8 @@ public: void AddEntityToList(int32, uint8); void RemoveEntityFromList(int32, uint8); void Process(); + void CheckIfCollisionHasLoadedForMissionObject(); + CPhysical* DoesThisEntityWaitForCollision(int i); }; struct CUpsideDownCarCheckEntry @@ -372,6 +375,7 @@ private: friend class CRunningScript; friend class CHud; friend void CMissionCleanup::Process(); + friend class CColStore; }; 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 |