From ae0c83fa01b05dc2ee70acb2bd4d0e8a3945630c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 5 May 2020 14:40:35 +0300 Subject: [PATCH] CAutoPilot + CCarAI + fixes --- src/audio/AudioManager.cpp | 4 +- src/control/AutoPilot.cpp | 4 + src/control/AutoPilot.h | 14 +- src/control/CarAI.cpp | 309 +++++++++++++++++++++++++++++++++++-- src/control/CarAI.h | 18 ++- src/control/CarCtrl.cpp | 14 +- src/control/CarCtrl.h | 3 + src/core/ZoneCull.h | 5 + src/vehicles/Automobile.h | 2 - src/vehicles/Boat.h | 2 - src/vehicles/Heli.h | 1 - src/vehicles/Plane.h | 1 - src/vehicles/Train.h | 1 - src/vehicles/Vehicle.cpp | 28 +++- src/vehicles/Vehicle.h | 27 +++- 15 files changed, 402 insertions(+), 31 deletions(-) diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 523092fd..c30d6ecc 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -8277,8 +8277,8 @@ cAudioManager::ProcessVehicleHorn(cVehicleParams *params) if (params->m_pVehicle->GetStatus() != STATUS_PLAYER) { automobile->m_nCarHornTimer = Min(44, automobile->m_nCarHornTimer); if (automobile->m_nCarHornTimer == 44) - automobile->field_22D = (m_FrameCounter + m_sQueueSample.m_nEntityIndex) & 7; - if (!hornPatternsArray[automobile->field_22D][44 - automobile->m_nCarHornTimer]) + automobile->m_nCarHornPattern = (m_FrameCounter + m_sQueueSample.m_nEntityIndex) & 7; + if (!hornPatternsArray[automobile->m_nCarHornPattern][44 - automobile->m_nCarHornTimer]) return; } 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(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(buf); diff --git a/src/control/AutoPilot.h b/src/control/AutoPilot.h index 4c356f96..48a0c4de 100644 --- a/src/control/AutoPilot.h +++ b/src/control/AutoPilot.h @@ -26,6 +26,7 @@ enum eCarMission : uint8 MISSION_BLOCKCAR_FARAWAY, MISSION_BLOCKCAR_CLOSE, MISSION_BLOCKCAR_HANDBRAKESTOP, +#ifdef MIAMI MISSION_HELI_FLYTOCOORS, MISSION_ATTACKPLAYER, MISSION_PLANE_FLYTOCOORS, @@ -33,6 +34,7 @@ enum eCarMission : uint8 MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1, MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2, MISSION_BLOCKPLAYER_FORWARDANDBACK +#endif }; enum eCarTempAction : uint8 @@ -82,11 +84,18 @@ public: uint32 m_nTimeTempAction; float m_fMaxTrafficSpeed; uint8 m_nCruiseSpeed; +#ifdef MIAMI + uint8 m_nCruiseSpeedMultiplierType; + float m_fCruiseSpeedMultiplier; +#endif uint8 m_bSlowedDownBecauseOfCars : 1; uint8 m_bSlowedDownBecauseOfPeds : 1; uint8 m_bStayInCurrentLevel : 1; uint8 m_bStayInFastLane : 1; uint8 m_bIgnorePathfinding : 1; +#ifdef MIAMI + uint8 m_nSwitchDistance; +#endif CVector m_vecDestinationCoors; CPathNode *m_aPathFindNodesInfo[NUM_PATH_NODES_IN_AUTOPILOT]; int16 m_nPathFindNodesCount; @@ -116,6 +125,10 @@ public: m_nTimeToStartMission = CTimer::GetTimeInMilliseconds(); m_nAntiReverseTimer = m_nTimeToStartMission; m_bStayInFastLane = false; +#ifdef MIAMI + m_nCruiseSpeedMultiplierType = 0; + m_fCruiseSpeedMultiplier = 1.0f; +#endif } void ModifySpeed(float); @@ -126,4 +139,3 @@ public: #endif }; -static_assert(sizeof(CAutoPilot) == 0x70, "CAutoPilot: error"); diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index f0df1ed2..d595feaf 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -21,19 +21,49 @@ #define DISTANCE_TO_SWITCH_DISTANCE_GOTO 20.0f -float CCarAI::FindSwitchDistanceClose(CVehicle*) +//--MIAMI: done +float CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle) { +#ifndef MIAMI return 30.0f; +#else + return pVehicle->AutoPilot.m_nSwitchDistance; +#endif } +//--MIAMI: done +float CCarAI::FindSwitchDistanceFarNormalVehicle(CVehicle* pVehicle) +{ + return FindSwitchDistanceClose(pVehicle) + 5.0f; +} + +//--MIAMI: done float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle) { - return pVehicle->bIsLawEnforcer ? 50.0f : 35.0f; + if (pVehicle->bIsLawEnforcer) + return 50.0f; + return FindSwitchDistanceFarNormalVehicle(pVehicle); } +#ifdef MIAMI +//--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; + } +} +#endif + +//--MIAMI: done void CCarAI::UpdateCarAI(CVehicle* pVehicle) { - //return; if (pVehicle->bIsLawEnforcer){ if (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_FARAWAY || pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || @@ -61,14 +91,19 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (pVehicle->UsesSiren(pVehicle->GetModelIndex())) pVehicle->m_bSirenOrAlarm = true; } +#ifndef MIAMI 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 + BackToCruisingIfNoWantedLevel(pVehicle); +#endif break; case MISSION_RAMPLAYER_CLOSE: if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() || @@ -113,16 +148,24 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->m_bSirenOrAlarm = false; pVehicle->m_nCarHornTimer = 0; } +#ifdef MIAMI + if (pVehicle->bIsLawEnforcer) + MellowOutChaseSpeed(pVehicle); + BackToCruisingIfNoWantedLevel(pVehicle); +#else 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) MellowOutChaseSpeed(pVehicle); +#endif break; case MISSION_BLOCKPLAYER_FARAWAY: if (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() || @@ -131,14 +174,19 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (pVehicle->UsesSiren(pVehicle->GetModelIndex())) pVehicle->m_bSirenOrAlarm = true; } +#ifndef MIAMI 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 + BackToCruisingIfNoWantedLevel(pVehicle); +#endif break; case MISSION_BLOCKPLAYER_CLOSE: if (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() || @@ -168,19 +216,30 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->m_bSirenOrAlarm = false; pVehicle->m_nCarHornTimer = 0; } +#ifdef MIAMI + if (pVehicle->bIsLawEnforcer) + MellowOutChaseSpeed(pVehicle); + BackToCruisingIfNoWantedLevel(pVehicle); +#else 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); +#endif break; case MISSION_GOTOCOORDS: +#ifdef MIAMI + if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) || +#else if ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < DISTANCE_TO_SWITCH_DISTANCE_GOTO || +#endif pVehicle->AutoPilot.m_bIgnorePathfinding) pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT; break; @@ -192,8 +251,14 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (distance < 5.0f){ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; +#ifdef MIAMI + if (pVehicle->bParking) { + TellOccupantsToLeaveCar(pVehicle); + pVehicle->bParking = false; + } +#endif } - else if (distance > 35.0f && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0){ + else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0){ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; pVehicle->AutoPilot.m_nCarMission = (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pVehicle->AutoPilot.m_vecDestinationCoors, true)) ? MISSION_GOTOCOORDS_STRAIGHT : MISSION_GOTOCOORDS; @@ -248,8 +313,14 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (distance < 1.0f) { pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; +#ifdef MIAMI + if (pVehicle->bParking) { + TellOccupantsToLeaveCar(pVehicle); + pVehicle->bParking = false; + } +#endif } - else if (distance > 35.0f && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0) { + else if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0) { pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; pVehicle->AutoPilot.m_nCarMission = (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pVehicle->AutoPilot.m_vecDestinationCoors, true)) ? MISSION_GOTO_COORDS_STRAIGHT_ACCURATE : MISSION_GOTOCOORDS_ACCURATE; @@ -267,6 +338,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) break; case MISSION_RAMCAR_CLOSE: if (pVehicle->AutoPilot.m_pTargetCar){ +#ifndef MIAMI if #ifdef FIX_BUGS (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar && @@ -284,6 +356,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (CCullZones::NoPolice()) pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; } +#else +#ifdef FIX_BUGS // btw fixed in SA + if (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar) +#endif + BackToCruisingIfNoWantedLevel(pVehicle); +#endif if ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() <= FindSwitchDistanceFar(pVehicle) || pVehicle->AutoPilot.m_bIgnorePathfinding){ if (pVehicle->GetHasCollidedWith(pVehicle->AutoPilot.m_pTargetCar)){ @@ -325,13 +403,53 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; } break; +#ifdef MIAMI + 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); + } +#endif default: if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel > 0 && !CCullZones::NoPolice()){ if (ABS(FindPlayerCoors().x - pVehicle->GetPosition().x) > 10.0f || ABS(FindPlayerCoors().y - pVehicle->GetPosition().y) > 10.0f){ pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle); pVehicle->SetStatus(STATUS_PHYSICS); - pVehicle->AutoPilot.m_nCarMission = FindPoliceCarMissionForWantedLevel(); + pVehicle->AutoPilot.m_nCarMission = +#ifdef MIAMI + pVehicle->GetVehicleAppearance() == VEHICLE_BOAT ? FindPoliceBoatMissionForWantedLevel() : +#endif + FindPoliceCarMissionForWantedLevel(); pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; }else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){ @@ -352,6 +470,13 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCruiseSpeed = 0; break; } +#ifdef MIAMI + if (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->m_nWantedLevel >= 1 && CCullZones::PoliceAbandonCars()) { + TellOccupantsToLeaveCar(pVehicle); + pVehicle->AutoPilot.m_nCruiseSpeed = 0; + pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + } +#endif float flatSpeed = pVehicle->GetMoveSpeed().MagnitudeSqr2D(); if (flatSpeed > SQR(0.018f)){ pVehicle->AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds(); @@ -360,9 +485,17 @@ 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 && +#ifdef MIAMI + pVehicle->AutoPilot.m_nCarMission != MISSION_BLOCKPLAYER_HANDBRAKESTOP && +#endif pVehicle->AutoPilot.m_nCruiseSpeed != 0 && (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE || pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE)){ - if (pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS){ + if (pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS +#ifdef MIAMI + && pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS || + pVehicle->VehicleCreatedBy == MISSION_VEHICLE +#endif + ) { if (CTimer::GetTimeInMilliseconds() - pVehicle->m_nLastTimeCollided > 500) pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); if (flatSpeed < SQR(0.018f) && CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nAntiReverseTimer > 2000){ @@ -393,6 +526,15 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 400; } } +#ifdef MIAMI + 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; + } + } +#endif if (pVehicle->GetUp().z < 0.7f){ pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000; @@ -432,13 +574,45 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if ((uint8)(pVehicle->m_randomSeed ^ CGeneral::GetRandomNumber()) == 0xAD) pVehicle->m_nCarHornTimer = 45; } +#ifdef MIAMI + 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; + } + } + } +#endif } +//--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){ @@ -456,10 +630,23 @@ float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget) return (pVehicle->GetPosition() - *pTarget).Magnitude2D(); } -void CCarAI::AddPoliceOccupants(CVehicle* pVehicle) +#ifdef MIAMI +//--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(); +} +#endif + +//--MIAMI: TODO: MI_VICECHEE +void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle) { if (pVehicle->bOccupantsHaveBeenGenerated) return; + pVehicle->bOccupantsHaveBeenGenerated = true; switch (pVehicle->GetModelIndex()){ case MI_FBICAR: case MI_ENFORCER: @@ -474,36 +661,85 @@ void CCarAI::AddPoliceOccupants(CVehicle* pVehicle) if (FindPlayerPed()->m_pWanted->m_nWantedLevel > 1) pVehicle->SetupPassenger(0); return; +#ifdef MIAMI + 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; + } +*/ +#endif 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){ pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); - if (pVehicle->GetModelIndex()) + if (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]) + if (pVehicle->pPassengers[i]) { +#ifdef MIAMI + pVehicle->pPassengers[i]->m_leaveCarTimer = timer; pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); + timer += CGeneral::GetRandomNumberInRange(200, 400); +#else + pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); +#endif + } } } +#ifdef MIAMI +//--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); + } + } +} +#endif + +//--MIAMI: done void CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget) { pVehicle->AutoPilot.m_pTargetCar = pTarget; @@ -513,6 +749,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; @@ -521,6 +758,8 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget) pVehicle->bEngineOn = true; 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){ @@ -535,6 +774,24 @@ eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() } } +#ifdef MIAMI +//--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; + } +} +#endif + +//--MIAMI: done int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle) { switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel) { @@ -549,6 +806,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){ @@ -587,8 +845,31 @@ void CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCruiseSpeed = 34; } } +#ifdef MIAMI + if (!FindPlayerVehicle() && FindPlayerPed()->GetMoveSpeed().Magnitude() < 0.07f) { + if ((FindPlayerCoors() - pVehicle->GetPosition()).Magnitude() < 30.0f) + pVehicle->AutoPilot.m_nCruiseSpeed = Min(10, pVehicle->AutoPilot.m_nCruiseSpeed); + } +#endif } +#ifdef MIAMI +//--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; + } +} +#endif + +//--MIAMI: done void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle) { float flatSpeed = pVehicle->GetMoveSpeed().Magnitude2D(); @@ -601,7 +882,7 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle) CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i); if (!vehicle) continue; - if (vehicle->m_vehType != VEHICLE_TYPE_CAR && vehicle->m_vehType != VEHICLE_TYPE_BIKE) + if (!vehicle->IsCar() && !vehicle->IsBike()) continue; if (vehicle->GetStatus() != STATUS_SIMPLE && vehicle->GetStatus() != STATUS_PHYSICS) continue; @@ -611,6 +892,10 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle) continue; if (vehicle == pVehicle) continue; +#ifdef MIAMI + if (vehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS) + return; +#endif 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 fbd46e95..9c3cb196 100644 --- a/src/control/CarAI.h +++ b/src/control/CarAI.h @@ -8,18 +8,34 @@ class CCarAI { public: static float FindSwitchDistanceClose(CVehicle*); + static float FindSwitchDistanceFarNormalVehicle(CVehicle*); static float FindSwitchDistanceFar(CVehicle*); +#ifdef MIAMI + static void BackToCruisingIfNoWantedLevel(CVehicle*); +#endif static void UpdateCarAI(CVehicle*); static void CarHasReasonToStop(CVehicle*); static float GetCarToGoToCoors(CVehicle*, CVector*); - static void AddPoliceOccupants(CVehicle*); +#ifdef MIAMI + static float GetCarToParkAtCoors(CVehicle*, CVector*); +#endif + static void AddPoliceCarOccupants(CVehicle*); static void AddAmbulanceOccupants(CVehicle*); static void AddFiretruckOccupants(CVehicle*); static void TellOccupantsToLeaveCar(CVehicle*); +#ifdef MIAMI + static void TellOccupantsToFleeCar(CVehicle*); +#endif static void TellCarToRamOtherCar(CVehicle*, CVehicle*); static void TellCarToBlockOtherCar(CVehicle*, CVehicle*); static eCarMission FindPoliceCarMissionForWantedLevel(); +#ifdef MIAMI + static eCarMission FindPoliceBoatMissionForWantedLevel(); +#endif static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*); static void MellowOutChaseSpeed(CVehicle*); +#ifdef MIAMI + static void MellowOutChaseSpeedBoat(CVehicle*); +#endif static void MakeWayForCarWithSiren(CVehicle *veh); }; diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index bfa33f27..809e6f90 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -531,7 +531,7 @@ CCarCtrl::GenerateOneRandomCar() pVehicleModel->AvoidSameVehicleColour(&pCar->m_currentColour1, &pCar->m_currentColour2); CWorld::Add(pCar); if (carClass == COPS) - CCarAI::AddPoliceOccupants(pCar); + CCarAI::AddPoliceCarOccupants(pCar); else pCar->SetUpDriver(); if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */ @@ -2751,3 +2751,15 @@ bool CCarCtrl::MapCouldMoveInThisArea(float x, float y) return false; #endif } + +#ifdef MIAMI +float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type) +{ + switch (type) + { + case 1: return 1.5f; + case 2: return 2.0f; + } + return 1.0f; +} +#endif diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 44ef9ab6..8ac8664a 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -104,6 +104,9 @@ public: static void ClearInterestingVehicleList(); static void FindLinksToGoWithTheseNodes(CVehicle*); static bool GenerateOneEmergencyServicesCar(uint32, CVector); +#ifdef MIAMI + static float FindSpeedMultiplierWithSpeedFromNodes(int8); +#endif static float GetPositionAlongCurrentCurve(CVehicle* pVehicle) { diff --git a/src/core/ZoneCull.h b/src/core/ZoneCull.h index 9bc07b8c..3659bca7 100644 --- a/src/core/ZoneCull.h +++ b/src/core/ZoneCull.h @@ -122,4 +122,9 @@ public: static bool DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set); static void CompressIndicesArray() {};// todo + +#ifdef MIAMI + //--MIAMI: TODO + static bool PoliceAbandonCars(void) { return false; } +#endif }; diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 041302bf..0356a9f2 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -197,8 +197,6 @@ public: static void SetAllTaxiLights(bool set); }; -static_assert(sizeof(CAutomobile) == 0x5A8, "CAutomobile: error"); - inline uint8 GetCarDoorFlag(int32 carnode) { switch (carnode) { case CAR_DOOR_LF: diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h index 70407ab9..cde5de84 100644 --- a/src/vehicles/Boat.h +++ b/src/vehicles/Boat.h @@ -72,8 +72,6 @@ public: }; -static_assert(sizeof(CBoat) == 0x484, "CBoat: error"); - extern float MAX_WAKE_LENGTH; extern float MIN_WAKE_INTERVAL; extern float WAKE_LIFETIME; \ No newline at end of file diff --git a/src/vehicles/Heli.h b/src/vehicles/Heli.h index 39e4cbcf..a8f604aa 100644 --- a/src/vehicles/Heli.h +++ b/src/vehicles/Heli.h @@ -95,4 +95,3 @@ public: static void ActivateHeli(bool activate); }; -static_assert(sizeof(CHeli) == 0x33C, "CHeli: error"); diff --git a/src/vehicles/Plane.h b/src/vehicles/Plane.h index 79738858..6fa6776b 100644 --- a/src/vehicles/Plane.h +++ b/src/vehicles/Plane.h @@ -63,7 +63,6 @@ public: static bool HasCesnaBeenDestroyed(void); static bool HasDropOffCesnaBeenShotDown(void); }; -static_assert(sizeof(CPlane) == 0x29C, "CPlane: error"); extern float LandingPoint; extern float TakeOffPoint; diff --git a/src/vehicles/Train.h b/src/vehicles/Train.h index bf541250..e20a08fd 100644 --- a/src/vehicles/Train.h +++ b/src/vehicles/Train.h @@ -91,4 +91,3 @@ public: float *totalLength, float *totalDuration, CTrainInterpolationLine *interpLines, bool rightRail); static void UpdateTrains(void); }; -static_assert(sizeof(CTrain) == 0x2E4, "CTrain: error"); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 75f43515..67024782 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -98,7 +98,10 @@ CVehicle::CVehicle(uint8 CreatedBy) bHasAlreadyBeenRecorded = false; m_bSirenOrAlarm = 0; m_nCarHornTimer = 0; - field_22D = 0; + m_nCarHornPattern = 0; +#ifdef MIAMI + bParking = false; +#endif m_nAlarmState = 0; m_nDoorLock = CARLOCK_UNLOCKED; m_nLastWeaponDamage = -1; @@ -118,6 +121,9 @@ CVehicle::CVehicle(uint8 CreatedBy) AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds(); AutoPilot.m_bStayInCurrentLevel = false; AutoPilot.m_bIgnorePathfinding = false; +#ifdef MIAMI + AutoPilot.m_nSwitchDistance = 20; +#endif } CVehicle::~CVehicle() @@ -1347,3 +1353,23 @@ CVehicle::Load(uint8*& buf) SkipSaveBuf(buf, 99); } #endif + +#ifdef MIAMI +eVehicleAppearance +//--MIAMI: TODO, implement VC version, appearance != type +// This would work for cars, boats and bikes but not for planes and helis +CVehicle::GetVehicleAppearance(void) +{ + if (IsCar()) + return VEHICLE_CAR; + if (IsBoat()) + return VEHICLE_BOAT; + if (IsBike()) + return VEHICLE_BIKE; + if (IsPlane()) + return VEHICLE_PLANE; + if (IsHeli()) + return VEHICLE_HELI; + return VEHICLE_NONE; +} +#endif diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index d8f90d92..bff5d578 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -109,6 +109,18 @@ enum eFlightModel FLIGHT_MODEL_SEAPLANE }; +#ifdef MIAMI +enum eVehicleAppearance +{ + VEHICLE_NONE, + VEHICLE_CAR, + VEHICLE_BIKE, + VEHICLE_HELI, + VEHICLE_BOAT, + VEHICLE_PLANE, +}; +#endif + // Or Weapon.h? void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage); @@ -172,6 +184,10 @@ public: uint8 bIsCarParkVehicle : 1; // Car has been created using the special CAR_PARK script command uint8 bHasAlreadyBeenRecorded : 1; // Used for replays +#ifdef MIAMI + uint8 bParking : 1; +#endif; + int8 m_numPedsUseItAsCover; uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default) int8 m_nPacManPickupsCarried; @@ -193,7 +209,7 @@ public: uint8 m_bRainAudioCounter; uint8 m_bRainSamplesCounter; uint8 m_nCarHornTimer; - uint8 field_22D; // last horn? + uint8 m_nCarHornPattern; // last horn? bool m_bSirenOrAlarm; int8 m_comedyControlState; CStoredCollPoly m_aCollPolys[2]; // poly which is under front/rear part of car @@ -236,6 +252,9 @@ public: virtual void Load(uint8*& buf); #endif +#ifdef MIAMI + eVehicleAppearance GetVehicleAppearance(void); +#endif bool IsCar(void) { return m_vehType == VEHICLE_TYPE_CAR; } bool IsBoat(void) { return m_vehType == VEHICLE_TYPE_BOAT; } bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; } @@ -274,6 +293,7 @@ public: void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage); void DoFixedMachineGuns(void); + bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; } CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); } bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE; } @@ -290,9 +310,4 @@ public: static bool m_bDisableMouseSteering; }; -static_assert(sizeof(CVehicle) == 0x288, "CVehicle: error"); -static_assert(offsetof(CVehicle, m_pCurGroundEntity) == 0x1E0, "CVehicle: error"); -static_assert(offsetof(CVehicle, m_nAlarmState) == 0x1A0, "CVehicle: error"); -static_assert(offsetof(CVehicle, m_nLastWeaponDamage) == 0x228, "CVehicle: error"); - void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);