diff options
Diffstat (limited to 'src/control')
-rw-r--r-- | src/control/AutoPilot.cpp | 97 | ||||
-rw-r--r-- | src/control/AutoPilot.h | 15 | ||||
-rw-r--r-- | src/control/Bridge.cpp | 11 | ||||
-rw-r--r-- | src/control/CarAI.cpp | 57 | ||||
-rw-r--r-- | src/control/CarAI.h | 3 | ||||
-rw-r--r-- | src/control/CarCtrl.cpp | 485 | ||||
-rw-r--r-- | src/control/CarCtrl.h | 3 | ||||
-rw-r--r-- | src/control/Curves.cpp | 2 | ||||
-rw-r--r-- | src/control/GameLogic.cpp | 12 | ||||
-rw-r--r-- | src/control/Garages.cpp | 59 | ||||
-rw-r--r-- | src/control/Garages.h | 8 | ||||
-rw-r--r-- | src/control/OnscreenTimer.h | 4 | ||||
-rw-r--r-- | src/control/PathFind.cpp | 352 | ||||
-rw-r--r-- | src/control/PathFind.h | 69 | ||||
-rw-r--r-- | src/control/Phones.cpp | 4 | ||||
-rw-r--r-- | src/control/Phones.h | 2 | ||||
-rw-r--r-- | src/control/Pickups.cpp | 24 | ||||
-rw-r--r-- | src/control/Pickups.h | 2 | ||||
-rw-r--r-- | src/control/Record.cpp | 14 | ||||
-rw-r--r-- | src/control/Remote.cpp | 6 | ||||
-rw-r--r-- | src/control/Replay.cpp | 20 | ||||
-rw-r--r-- | src/control/Replay.h | 19 | ||||
-rw-r--r-- | src/control/Restart.cpp | 4 | ||||
-rw-r--r-- | src/control/RoadBlocks.cpp | 45 | ||||
-rw-r--r-- | src/control/SceneEdit.cpp | 33 | ||||
-rw-r--r-- | src/control/Script.cpp | 198 | ||||
-rw-r--r-- | src/control/Script.h | 18 | ||||
-rw-r--r-- | src/control/TrafficLights.cpp | 30 |
28 files changed, 942 insertions, 654 deletions
diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index 69511bc8..b1fce95f 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -12,17 +12,17 @@ void CAutoPilot::ModifySpeed(float speed) float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo]; - float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.x; - float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.y; - float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.x; - float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.y; + float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].GetDirX(); + float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].GetDirY(); + float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].GetDirX(); + float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].GetDirY(); CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->pos.x + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->pos.y - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX, + pCurrentLink->GetX() + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->GetY() - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -44,4 +44,83 @@ void CAutoPilot::RemoveOnePathNode() --m_nPathFindNodesCount; for (int i = 0; i < m_nPathFindNodesCount; i++) m_aPathFindNodesInfo[i] = m_aPathFindNodesInfo[i + 1]; -}
\ No newline at end of file +} + +#ifdef COMPATIBLE_SAVES +void CAutoPilot::Save(uint8*& buf) +{ + WriteSaveBuf<int32>(buf, m_nCurrentRouteNode); + WriteSaveBuf<int32>(buf, m_nNextRouteNode); + WriteSaveBuf<int32>(buf, m_nPrevRouteNode); + WriteSaveBuf<uint32>(buf, m_nTimeEnteredCurve); + WriteSaveBuf<uint32>(buf, m_nTimeToSpendOnCurrentCurve); + WriteSaveBuf<uint32>(buf, m_nCurrentPathNodeInfo); + WriteSaveBuf<uint32>(buf, m_nNextPathNodeInfo); + WriteSaveBuf<uint32>(buf, m_nPreviousPathNodeInfo); + WriteSaveBuf<uint32>(buf, m_nAntiReverseTimer); + WriteSaveBuf<uint32>(buf, m_nTimeToStartMission); + WriteSaveBuf<int8>(buf, m_nPreviousDirection); + WriteSaveBuf<int8>(buf, m_nCurrentDirection); + WriteSaveBuf<int8>(buf, m_nNextDirection); + WriteSaveBuf<int8>(buf, m_nCurrentLane); + WriteSaveBuf<int8>(buf, m_nNextLane); + WriteSaveBuf<uint8>(buf, m_nDrivingStyle); + WriteSaveBuf<uint8>(buf, m_nCarMission); + WriteSaveBuf<uint8>(buf, m_nTempAction); + WriteSaveBuf<uint32>(buf, m_nTimeTempAction); + WriteSaveBuf<float>(buf, m_fMaxTrafficSpeed); + WriteSaveBuf<uint8>(buf, m_nCruiseSpeed); + uint8 flags = 0; + if (m_bSlowedDownBecauseOfCars) flags |= BIT(0); + if (m_bSlowedDownBecauseOfPeds) flags |= BIT(1); + if (m_bStayInCurrentLevel) flags |= BIT(2); + if (m_bStayInFastLane) flags |= BIT(3); + if (m_bIgnorePathfinding) flags |= BIT(4); + WriteSaveBuf<uint8>(buf, flags); + SkipSaveBuf(buf, 2); + WriteSaveBuf<float>(buf, m_vecDestinationCoors.x); + WriteSaveBuf<float>(buf, m_vecDestinationCoors.y); + WriteSaveBuf<float>(buf, m_vecDestinationCoors.z); + SkipSaveBuf(buf, 32); + WriteSaveBuf<int16>(buf, m_nPathFindNodesCount); + SkipSaveBuf(buf, 6); +} + +void CAutoPilot::Load(uint8*& buf) +{ + m_nCurrentRouteNode = ReadSaveBuf<int32>(buf); + m_nNextRouteNode = ReadSaveBuf<int32>(buf); + m_nPrevRouteNode = ReadSaveBuf<int32>(buf); + m_nTimeEnteredCurve = ReadSaveBuf<uint32>(buf); + m_nTimeToSpendOnCurrentCurve = ReadSaveBuf<uint32>(buf); + m_nCurrentPathNodeInfo = ReadSaveBuf<uint32>(buf); + m_nNextPathNodeInfo = ReadSaveBuf<uint32>(buf); + m_nPreviousPathNodeInfo = ReadSaveBuf<uint32>(buf); + m_nAntiReverseTimer = ReadSaveBuf<uint32>(buf); + m_nTimeToStartMission = ReadSaveBuf<uint32>(buf); + m_nPreviousDirection = ReadSaveBuf<int8>(buf); + m_nCurrentDirection = ReadSaveBuf<int8>(buf); + m_nNextDirection = ReadSaveBuf<int8>(buf); + m_nCurrentLane = ReadSaveBuf<int8>(buf); + m_nNextLane = ReadSaveBuf<int8>(buf); + m_nDrivingStyle = (eCarDrivingStyle)ReadSaveBuf<uint8>(buf); + m_nCarMission = (eCarMission)ReadSaveBuf<uint8>(buf); + m_nTempAction = (eCarTempAction)ReadSaveBuf<uint8>(buf); + m_nTimeTempAction = ReadSaveBuf<uint32>(buf); + m_fMaxTrafficSpeed = ReadSaveBuf<float>(buf); + m_nCruiseSpeed = ReadSaveBuf<uint8>(buf); + uint8 flags = ReadSaveBuf<uint8>(buf); + m_bSlowedDownBecauseOfCars = !!(flags & BIT(0)); + m_bSlowedDownBecauseOfPeds = !!(flags & BIT(1)); + m_bStayInCurrentLevel = !!(flags & BIT(2)); + m_bStayInFastLane = !!(flags & BIT(3)); + m_bIgnorePathfinding = !!(flags & BIT(4)); + SkipSaveBuf(buf, 2); + m_vecDestinationCoors.x = ReadSaveBuf<float>(buf); + m_vecDestinationCoors.y = ReadSaveBuf<float>(buf); + m_vecDestinationCoors.z = ReadSaveBuf<float>(buf); + SkipSaveBuf(buf, 32); + m_nPathFindNodesCount = ReadSaveBuf<int16>(buf); + SkipSaveBuf(buf, 6); +} +#endif
\ No newline at end of file diff --git a/src/control/AutoPilot.h b/src/control/AutoPilot.h index e1066071..337a93c1 100644 --- a/src/control/AutoPilot.h +++ b/src/control/AutoPilot.h @@ -26,13 +26,6 @@ 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 @@ -120,5 +113,11 @@ public: void ModifySpeed(float); void RemoveOnePathNode(); +#ifdef COMPATIBLE_SAVES + void Save(uint8*& buf); + void Load(uint8*& buf); +#endif + }; -static_assert(sizeof(CAutoPilot) == 0x70, "CAutoPilot: error"); + +VALIDATE_SIZE(CAutoPilot, 0x70); diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp index 8514ef9e..e873062b 100644 --- a/src/control/Bridge.cpp +++ b/src/control/Bridge.cpp @@ -93,16 +93,16 @@ void CBridge::Update() // Move bridge part if (liftHeight != OldLift) { - pLiftPart->GetPosition().z = DefaultZLiftPart + liftHeight; + pLiftPart->GetMatrix().GetPosition().z = DefaultZLiftPart + liftHeight; pLiftPart->GetMatrix().UpdateRW(); pLiftPart->UpdateRwFrame(); if (pLiftRoad) { - pLiftRoad->GetPosition().z = DefaultZLiftRoad + liftHeight; + pLiftRoad->GetMatrix().GetPosition().z = DefaultZLiftRoad + liftHeight; pLiftRoad->GetMatrix().UpdateRW(); pLiftRoad->UpdateRwFrame(); } - pWeight->GetPosition().z = DefaultZLiftWeight - liftHeight; + pWeight->GetMatrix().GetPosition().z = DefaultZLiftWeight - liftHeight; pWeight->GetMatrix().UpdateRW(); pWeight->UpdateRwFrame(); @@ -115,7 +115,10 @@ void CBridge::Update() ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, false); } -bool CBridge::ShouldLightsBeFlashing() { return State != STATE_LIFT_PART_IS_DOWN; } +bool CBridge::ShouldLightsBeFlashing() +{ + return State != STATE_LIFT_PART_IS_DOWN; +} void CBridge::FindBridgeEntities() { diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index a8e77fc2..3e22ee77 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -21,19 +21,25 @@ #define DISTANCE_TO_SWITCH_DISTANCE_GOTO 20.0f -float CCarAI::FindSwitchDistanceClose(CVehicle*) +float CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle) { return 30.0f; } +float CCarAI::FindSwitchDistanceFarNormalVehicle(CVehicle* pVehicle) +{ + return FindSwitchDistanceClose(pVehicle) + 5.0f; +} + float CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle) { - return pVehicle->bIsLawEnforcer ? 50.0f : 35.0f; + if (pVehicle->bIsLawEnforcer) + return 50.0f; + return FindSwitchDistanceFarNormalVehicle(pVehicle); } void CCarAI::UpdateCarAI(CVehicle* pVehicle) { - //return; if (pVehicle->bIsLawEnforcer){ if (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_FARAWAY || pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || @@ -41,7 +47,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle); } - switch (pVehicle->m_status){ + switch (pVehicle->GetStatus()){ case STATUS_PLAYER: case STATUS_PLAYER_PLAYBACKFROMBUFFER: case STATUS_TRAIN_MOVING: @@ -65,6 +71,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) (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; @@ -117,10 +124,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) (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); break; @@ -135,6 +144,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) (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; @@ -172,11 +182,12 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) (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); break; case MISSION_GOTOCOORDS: @@ -193,7 +204,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; } - 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; @@ -249,7 +260,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; } - 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; @@ -330,12 +341,13 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) if (ABS(FindPlayerCoors().x - pVehicle->GetPosition().x) > 10.0f || ABS(FindPlayerCoors().y - pVehicle->GetPosition().y) > 10.0f){ pVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle); - pVehicle->m_status = STATUS_PHYSICS; - pVehicle->AutoPilot.m_nCarMission = FindPoliceCarMissionForWantedLevel(); + pVehicle->SetStatus(STATUS_PHYSICS); + pVehicle->AutoPilot.m_nCarMission = + FindPoliceCarMissionForWantedLevel(); pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; }else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){ - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); TellOccupantsToLeaveCar(pVehicle); pVehicle->AutoPilot.m_nCruiseSpeed = 0; pVehicle->AutoPilot.m_nCarMission = MISSION_NONE; @@ -357,12 +369,13 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) pVehicle->AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds(); pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); } - if (pVehicle->m_status == STATUS_PHYSICS && pVehicle->AutoPilot.m_nTempAction == TEMPACT_NONE){ + 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_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 + ) { 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){ @@ -386,7 +399,7 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle) CTimer::GetPreviousTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission <= 30000 && pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE && !CTrafficLights::ShouldCarStopForBridge(pVehicle)){ - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); CCarCtrl::SwitchVehicleToRealPhysics(pVehicle); pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; pVehicle->AutoPilot.m_nTempAction = TEMPACT_REVERSE; @@ -446,7 +459,7 @@ float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget) pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; pVehicle->AutoPilot.m_nCruiseSpeed = 20; pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); pVehicle->AutoPilot.m_nCarMission = (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, *pTarget, false)) ? MISSION_GOTOCOORDS_STRAIGHT : MISSION_GOTOCOORDS; }else if (Abs(pTarget->x - pVehicle->AutoPilot.m_vecDestinationCoors.x) > 2.0f || @@ -456,10 +469,11 @@ float CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget) return (pVehicle->GetPosition() - *pTarget).Magnitude2D(); } -void CCarAI::AddPoliceOccupants(CVehicle* pVehicle) +void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle) { if (pVehicle->bOccupantsHaveBeenGenerated) return; + pVehicle->bOccupantsHaveBeenGenerated = true; switch (pVehicle->GetModelIndex()){ case MI_FBICAR: case MI_ENFORCER: @@ -495,12 +509,14 @@ 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]) { pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle); + } } } @@ -521,6 +537,7 @@ void CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget) pVehicle->bEngineOn = true; pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); } + eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() { switch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel){ @@ -601,9 +618,9 @@ 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->m_status != STATUS_SIMPLE && vehicle->m_status != STATUS_PHYSICS) + if (vehicle->GetStatus() != STATUS_SIMPLE && vehicle->GetStatus() != STATUS_PHYSICS) continue; if (vehicle->VehicleCreatedBy != RANDOM_VEHICLE) continue; @@ -627,7 +644,7 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle) TEMPACT_SWERVELEFT : TEMPACT_SWERVERIGHT; vehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; } - vehicle->m_status = STATUS_PHYSICS; + vehicle->SetStatus(STATUS_PHYSICS); }else{ if (DotProduct2D(vehicle->GetMoveSpeed(), distance) < 0.0f && vehicle->AutoPilot.m_nTempAction != TEMPACT_WAIT){ vehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; diff --git a/src/control/CarAI.h b/src/control/CarAI.h index fbd46e95..e88807c8 100644 --- a/src/control/CarAI.h +++ b/src/control/CarAI.h @@ -8,11 +8,12 @@ class CCarAI { public: static float FindSwitchDistanceClose(CVehicle*); + static float FindSwitchDistanceFarNormalVehicle(CVehicle*); static float FindSwitchDistanceFar(CVehicle*); static void UpdateCarAI(CVehicle*); static void CarHasReasonToStop(CVehicle*); static float GetCarToGoToCoors(CVehicle*, CVector*); - static void AddPoliceOccupants(CVehicle*); + static void AddPoliceCarOccupants(CVehicle*); static void AddAmbulanceOccupants(CVehicle*); static void AddFiretruckOccupants(CVehicle*); static void TellOccupantsToLeaveCar(CVehicle*); diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index f347b2c9..71236580 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -281,7 +281,7 @@ CCarCtrl::GenerateOneRandomCar() CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId]; CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId]; while (idInNode < pCurNode->numLinks && - ThePaths.m_connections[idInNode + pCurNode->firstLink] != nextNodeId) + ThePaths.ConnectedNode(idInNode + pCurNode->firstLink) != nextNodeId) idInNode++; int16 connectionId = ThePaths.m_carPathConnections[idInNode + pCurNode->firstLink]; CCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId]; @@ -291,10 +291,10 @@ CCarCtrl::GenerateOneRandomCar() /* Not spawning vehicle if road is one way and intended direction is opposide to that way. */ /* Also not spawning bikes but they don't exist in final game. */ return; - CAutomobile* pCar = new CAutomobile(carModel, RANDOM_VEHICLE); - pCar->AutoPilot.m_nPrevRouteNode = 0; - pCar->AutoPilot.m_nCurrentRouteNode = curNodeId; - pCar->AutoPilot.m_nNextRouteNode = nextNodeId; + CAutomobile* pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE); + pVehicle->AutoPilot.m_nPrevRouteNode = 0; + pVehicle->AutoPilot.m_nCurrentRouteNode = curNodeId; + pVehicle->AutoPilot.m_nNextRouteNode = nextNodeId; switch (carClass) { case POOR: case RICH: @@ -313,71 +313,71 @@ CCarCtrl::GenerateOneRandomCar() case GANG8: case GANG9: { - pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14); + pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14); if (carClass == EXEC) - pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18); + pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18); else if (carClass == POOR || carClass == SPECIAL) - pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10); - CVehicleModelInfo* pVehicleInfo = pCar->GetModelInfo(); - if (pVehicleInfo->GetColModel()->boundingBox.max.y - pCar->GetModelInfo()->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) { - pCar->AutoPilot.m_nCruiseSpeed *= 3; - pCar->AutoPilot.m_nCruiseSpeed /= 4; + pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10); + CVehicleModelInfo* pVehicleInfo = pVehicle->GetModelInfo(); + if (pVehicleInfo->GetColModel()->boundingBox.max.y - pVehicle->GetModelInfo()->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) { + pVehicle->AutoPilot.m_nCruiseSpeed *= 3; + pVehicle->AutoPilot.m_nCruiseSpeed /= 4; } - pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed; - pCar->AutoPilot.m_nCarMission = MISSION_CRUISE; - pCar->AutoPilot.m_nTempAction = TEMPACT_NONE; - pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; + pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed; + pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; + pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; + pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; break; } case COPS: - pCar->AutoPilot.m_nTempAction = TEMPACT_NONE; + pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel != 0){ - pCar->AutoPilot.m_nCruiseSpeed = CCarAI::FindPoliceCarSpeedForWantedLevel(pCar); - pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed / 2; - pCar->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel(); - pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + pVehicle->AutoPilot.m_nCruiseSpeed = CCarAI::FindPoliceCarSpeedForWantedLevel(pVehicle); + pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed / 2; + pVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel(); + pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; }else{ - pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 16); - pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed; - pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; - pCar->AutoPilot.m_nCarMission = MISSION_CRUISE; + pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 16); + pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed; + pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; + pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; } if (carModel == MI_FBICAR){ - pCar->m_currentColour1 = 0; - pCar->m_currentColour2 = 0; + pVehicle->m_currentColour1 = 0; + pVehicle->m_currentColour2 = 0; /* FBI cars are gray in carcols, but we want them black if they going after player. */ } default: break; } - if (pCar && pCar->GetModelIndex() == MI_MRWHOOP) - 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; + if (pVehicle && pVehicle->GetModelIndex() == MI_MRWHOOP) + pVehicle->m_bSirenOrAlarm = true; + pVehicle->AutoPilot.m_nNextPathNodeInfo = connectionId; + pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad; + CColBox* boundingBox = &CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel()->boundingBox; float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2; - float distanceBetweenNodes = (pCurNode->pos - pNextNode->pos).Magnitude2D(); + 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. */ /* Otherwise put it at least in a way that full vehicle length fits between two nodes. */ if (distanceBetweenNodes / 2 < carLength) positionBetweenNodes = 0.5f; else positionBetweenNodes = Min(1.0f - carLength / distanceBetweenNodes, Max(carLength / distanceBetweenNodes, positionBetweenNodes)); - pCar->AutoPilot.m_nNextDirection = (curNodeId >= nextNodeId) ? 1 : -1; + pVehicle->AutoPilot.m_nNextDirection = (curNodeId >= nextNodeId) ? 1 : -1; if (pCurNode->numLinks == 1){ /* Do not create vehicle if there is nowhere to go. */ - delete pCar; + delete pVehicle; return; } - int16 nextConnection = pCar->AutoPilot.m_nNextPathNodeInfo; + int16 nextConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo; int16 newLink; - while (nextConnection == pCar->AutoPilot.m_nNextPathNodeInfo){ + while (nextConnection == pVehicle->AutoPilot.m_nNextPathNodeInfo){ newLink = CGeneral::GetRandomNumber() % pCurNode->numLinks; nextConnection = ThePaths.m_carPathConnections[newLink + pCurNode->firstLink]; } - pCar->AutoPilot.m_nCurrentPathNodeInfo = nextConnection; - pCar->AutoPilot.m_nCurrentDirection = (ThePaths.m_connections[newLink + pCurNode->firstLink] >= curNodeId) ? 1 : -1; - CVector2D vecBetweenNodes = pNextNode->pos - pCurNode->pos; + pVehicle->AutoPilot.m_nCurrentPathNodeInfo = nextConnection; + pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(newLink + pCurNode->firstLink) >= curNodeId) ? 1 : -1; + CVector2D vecBetweenNodes = pNextNode->GetPosition() - pCurNode->GetPosition(); float forwardX, forwardY; float distBetweenNodes = vecBetweenNodes.Magnitude(); if (distanceBetweenNodes == 0.0f){ @@ -389,44 +389,110 @@ CCarCtrl::GenerateOneRandomCar() } /* I think the following might be some form of SetRotateZOnly. */ /* Setting up direction between two car nodes. */ - pCar->GetForward() = CVector(forwardX, forwardY, 0.0f); - pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f); - pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f); + pVehicle->GetForward() = CVector(forwardX, forwardY, 0.0f); + pVehicle->GetRight() = CVector(forwardY, -forwardX, 0.0f); + pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); - float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.x; - float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.y; - float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.x; - float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.y; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX(); + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY(); + +#ifdef FIX_BUGS + CCarPathLink* pCurrentLink; + CCarPathLink* pNextLink; + CVector positionOnCurrentLinkIncludingLane; + CVector positionOnNextLinkIncludingLane; + float directionCurrentLinkX; + float directionCurrentLinkY; + float directionNextLinkX; + float directionNextLinkY; + if (positionBetweenNodes < 0.5f) { + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX(); + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY(); + + pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; + pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; + positionOnCurrentLinkIncludingLane = CVector( + pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + 0.0f); + positionOnNextLinkIncludingLane = CVector( + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + 0.0f); + directionCurrentLinkX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + directionCurrentLinkY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; + /* We want to make a path between two links that may not have the same forward directions a curve. */ + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( + &positionOnCurrentLinkIncludingLane, + &positionOnNextLinkIncludingLane, + directionCurrentLinkX, directionCurrentLinkY, + directionNextLinkX, directionNextLinkY + ) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed); + pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - + (uint32)((0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); + } + else { + PickNextNodeRandomly(pVehicle); + pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - + (uint32)((positionBetweenNodes - 0.5f) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); - CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo]; - CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo]; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX(); + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY(); + + pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; + pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; + positionOnCurrentLinkIncludingLane = CVector( + pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + 0.0f); + positionOnNextLinkIncludingLane = CVector( + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + 0.0f); + directionCurrentLinkX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + directionCurrentLinkY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; + pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode]; + pNextNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode]; + } +#else + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX(); + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY(); + + CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; + CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->pos.x + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->pos.y - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurrentLink->dir.x * pCar->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurrentLink->dir.y * pCar->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dir.x * pCar->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dir.y * pCar->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + float directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; /* We want to make a path between two links that may not have the same forward directions a curve. */ - pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, &positionOnNextLinkIncludingLane, directionCurrentLinkX, directionCurrentLinkY, directionNextLinkX, directionNextLinkY - ) * (1000.0f / pCar->AutoPilot.m_fMaxTrafficSpeed); -#ifdef FIX_BUGS - /* Casting timer to float is very unwanted. In this case it's not awful */ - /* but in CAutoPilot::ModifySpeed it can even cause crashes (see SilentPatch). */ - pCar->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - - (uint32)((0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve); -#else - pCar->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - - (0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve; + ) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed); + pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - + (0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve; #endif CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f); CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f); @@ -437,15 +503,15 @@ CCarCtrl::GenerateOneRandomCar() &positionOnNextLinkIncludingLane, &directionCurrentLink, &directionNextLink, - GetPositionAlongCurrentCurve(pCar), - pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve, + GetPositionAlongCurrentCurve(pVehicle), + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve, &positionIncludingCurve, &directionIncludingCurve ); - CVector vectorBetweenNodes = pCurNode->pos - pNextNode->pos; + CVector vectorBetweenNodes = pCurNode->GetPosition() - pNextNode->GetPosition(); CVector finalPosition = positionIncludingCurve + vectorBetweenNodes * 2.0f / vectorBetweenNodes.Magnitude(); - finalPosition.z = positionBetweenNodes * pNextNode->pos.z + - (1.0f - positionBetweenNodes) * pCurNode->pos.z; + finalPosition.z = positionBetweenNodes * pNextNode->GetZ() + + (1.0f - positionBetweenNodes) * pCurNode->GetZ(); float groundZ = INFINITE_Z; CColPoint colPoint; CEntity* pEntity; @@ -457,13 +523,13 @@ CCarCtrl::GenerateOneRandomCar() } if (groundZ == INFINITE_Z || ABS(groundZ - finalPosition.z) > 7.0f) { /* Failed to find ground or too far from expected position. */ - delete pCar; + delete pVehicle; return; } - finalPosition.z = groundZ + pCar->GetHeightAboveRoad(); - pCar->GetPosition() = finalPosition; - pCar->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED); - CVector2D speedDifferenceWithTarget = (CVector2D)pCar->GetMoveSpeed() - vecPlayerSpeed; + finalPosition.z = groundZ + pVehicle->GetHeightAboveRoad(); + pVehicle->SetPosition(finalPosition); + pVehicle->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED); + CVector2D speedDifferenceWithTarget = (CVector2D)pVehicle->GetMoveSpeed() - vecPlayerSpeed; CVector2D distanceToTarget = positionIncludingCurve - vecTargetPos; switch (carClass) { case POOR: @@ -482,59 +548,59 @@ CCarCtrl::GenerateOneRandomCar() case NINES: case GANG8: case GANG9: - pCar->m_status = STATUS_SIMPLE; + pVehicle->SetStatus(STATUS_SIMPLE); break; case COPS: - pCar->m_status = (pCar->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS; - pCar->ChangeLawEnforcerState(1); + pVehicle->SetStatus((pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS); + pVehicle->ChangeLawEnforcerState(1); break; default: break; } - CVisibilityPlugins::SetClumpAlpha(pCar->GetClump(), 0); - if (!pCar->GetIsOnScreen()){ - if ((vecTargetPos - pCar->GetPosition()).Magnitude2D() > 50.0f) { + CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); + if (!pVehicle->GetIsOnScreen()){ + if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > 50.0f) { /* Too far away cars that are not visible aren't needed. */ - delete pCar; + delete pVehicle; return; } - }else if((vecTargetPos - pCar->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * 130.0f || - (vecTargetPos - pCar->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 110.0f){ - delete pCar; + }else if((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * 130.0f || + (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 110.0f){ + delete pVehicle; return; - }else if((TheCamera.GetPosition() - pCar->GetPosition()).Magnitude2D() < 90.0f * TheCamera.GenerationDistMultiplier){ - delete pCar; + }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 90.0f * TheCamera.GenerationDistMultiplier){ + delete pVehicle; return; } - CVehicleModelInfo* pVehicleModel = pCar->GetModelInfo(); + CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo(); float radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius; if (testForCollision){ - CWorld::FindObjectsKindaColliding(pCar->GetPosition(), radiusToTest + 20.0f, true, &colliding, 2, nil, false, true, false, false, false); + CWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest + 20.0f, true, &colliding, 2, nil, false, true, false, false, false); if (colliding){ - delete pCar; + delete pVehicle; return; } } - CWorld::FindObjectsKindaColliding(pCar->GetPosition(), radiusToTest, true, &colliding, 2, nil, false, true, false, false, false); + CWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest, true, &colliding, 2, nil, false, true, false, false, false); if (colliding){ - delete pCar; + delete pVehicle; return; } if (speedDifferenceWithTarget.x * distanceToTarget.x + speedDifferenceWithTarget.y * distanceToTarget.y >= 0.0f){ - delete pCar; + delete pVehicle; return; } - pVehicleModel->AvoidSameVehicleColour(&pCar->m_currentColour1, &pCar->m_currentColour2); - CWorld::Add(pCar); + pVehicleModel->AvoidSameVehicleColour(&pVehicle->m_currentColour1, &pVehicle->m_currentColour2); + CWorld::Add(pVehicle); if (carClass == COPS) - CCarAI::AddPoliceOccupants(pCar); + CCarAI::AddPoliceCarOccupants(pVehicle); else - pCar->SetUpDriver(); + pVehicle->SetUpDriver(); if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */ - pCar->m_status = STATUS_PHYSICS; - pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; - pCar->AutoPilot.m_nCruiseSpeed += 10; + pVehicle->SetStatus(STATUS_PHYSICS); + pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + pVehicle->AutoPilot.m_nCruiseSpeed += 10; } if (carClass == COPS) LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds(); @@ -693,7 +759,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() && CRenderer::IsEntityCullZoneVisible(pVehicle)) { pVehicle->bFadeOut = true; }else{ CWorld::Remove(pVehicle); @@ -702,7 +768,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) return; } } - if ((pVehicle->m_status == STATUS_SIMPLE || pVehicle->m_status == STATUS_PHYSICS && pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS) && + if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS) && CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 5000 && !pVehicle->GetIsOnScreen() && (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D() > 25.0f && @@ -716,10 +782,10 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) delete pVehicle; return; } - if (pVehicle->m_status != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0) + if (pVehicle->GetStatus() != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0) return; if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 && - (!pVehicle->GetIsOnScreen() || !CRenderer::IsEntityCullZoneVisible(pVehicle))){ + !(pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) ){ if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){ if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){ CWorld::Remove(pVehicle); @@ -759,21 +825,21 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle) SlowCarOnRailsDownForTrafficAndLights(pVehicle); if (pVehicle->AutoPilot.m_nTimeEnteredCurve + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve <= CTimer::GetTimeInMilliseconds()) PickNextNodeAccordingStrategy(pVehicle); - if (pVehicle->m_status == STATUS_PHYSICS) + if (pVehicle->GetStatus() == STATUS_PHYSICS) return; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - float currentPathLinkForwardX = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - float currentPathLinkForwardY = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + float currentPathLinkForwardX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float currentPathLinkForwardY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + float nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + float nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f); CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f); @@ -917,7 +983,7 @@ void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList& lst, CVehicle* pVehicle, f if (sideLength + 0.5f < sidewaysDistance) /* If car is far enough taking side into account, don't care */ continue; - if (pPed->m_type == ENTITY_TYPE_PED){ /* ...how can it not be? */ + if (pPed->IsPed()){ /* ...how can it not be? */ if (pPed->GetPedState() != PED_STEP_AWAY && pPed->GetPedState() != PED_DIVE_AWAY){ if (distanceUntilHit < movementTowardsPedPerSecond){ /* Very close. Time to evade. */ @@ -937,7 +1003,7 @@ void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList& lst, CVehicle* pVehicle, f } }else{ /* Relatively safe but annoying. */ - if (pVehicle->m_status == STATUS_PLAYER && + if (pVehicle->GetStatus() == STATUS_PLAYER && pPed->GetPedState() != PED_FLEE_ENTITY && pPed->CharCreatedBy == RANDOM_CHAR){ float angleCarToPed = CGeneral::GetRadianAngleBetweenPoints( @@ -1039,11 +1105,11 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, CTimer::GetTimeInMilliseconds() - pOtherVehicle->AutoPilot.m_nTimeToStartMission > 15000){ /* If cars are standing for 15 seconds, annoy one of them and make avoid cars. */ if (pOtherEntity != FindPlayerVehicle() && - DotProduct2D(pVehicle->GetForward(), pOtherVehicle->GetForward()) < 0.5f && + DotProduct2D(pVehicle->GetForward(), pOtherVehicle->GetForward()) < -0.5f && pVehicle < pOtherVehicle){ /* that comparasion though... */ *pSpeed = Max(curSpeed / 5, *pSpeed); - if (pVehicle->m_status == STATUS_SIMPLE){ - pVehicle->m_status = STATUS_PHYSICS; + if (pVehicle->GetStatus() == STATUS_SIMPLE){ + pVehicle->SetStatus(STATUS_PHYSICS); SwitchVehicleToRealPhysics(pVehicle); } pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; @@ -1452,8 +1518,13 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) int32 curNode = pVehicle->AutoPilot.m_nNextRouteNode; uint8 totalLinks = ThePaths.m_pathNodes[curNode].numLinks; CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; +#ifdef FIX_BUGS + uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ? + pCurLink->numLeftLanes : pCurLink->numRightLanes; +#else uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ? pCurLink->numRightLanes : pCurLink->numLeftLanes; +#endif uint8 allowedDirections = PATH_DIRECTION_NONE; uint8 nextLane = pVehicle->AutoPilot.m_nNextLane; if (nextLane == 0) @@ -1490,7 +1561,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) } } nextLink = CGeneral::GetRandomNumber() % totalLinks; - pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.m_connections[nextLink + pCurPathNode->firstLink]; + pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink); direction = FindPathDirection(prevNode, curNode, pVehicle->AutoPilot.m_nNextRouteNode); pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; @@ -1508,7 +1579,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) } } nextLink = CGeneral::GetRandomNumber() % totalLinks; - pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.m_connections[nextLink + pCurPathNode->firstLink]; + pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink); pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; } @@ -1516,7 +1587,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) if (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) { /* If we failed again, remove no U-turn limitation and remove randomness */ for (nextLink = 0; nextLink < totalLinks; nextLink++) { - pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.m_connections[nextLink + pCurPathNode->firstLink]; + pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink); pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; if (!goingAgainstOneWayRoad) { @@ -1535,7 +1606,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; if (prevNode == pVehicle->AutoPilot.m_nNextRouteNode){ /* We can no longer shift vehicle without physics if we have to turn it around. */ - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); SwitchVehicleToRealPhysics(pVehicle); } pVehicle->AutoPilot.m_nTimeEnteredCurve += pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve; @@ -1553,12 +1624,16 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX(); +#ifdef FIX_BUGS + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY(); +#endif if (lanesOnNextNode >= 0){ if ((CGeneral::GetRandomNumber() & 0x600) == 0){ /* 25% chance vehicle will try to switch lane */ - CVector2D dist = pNextPathNode->pos - pCurPathNode->pos; + CVector2D dist = pNextPathNode->GetPosition() - pCurPathNode->GetPosition(); if (dist.MagnitudeSqr() >= SQR(14.0f)){ if (CGeneral::GetRandomTrueFalse()) pVehicle->AutoPilot.m_nNextLane += 1; @@ -1574,17 +1649,17 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ - pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), - pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + float directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; /* We want to make a path between two links that may not have the same forward directions a curve. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -1600,8 +1675,8 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) uint8 CCarCtrl::FindPathDirection(int32 prevNode, int32 curNode, int32 nextNode) { - CVector2D prevToCur = ThePaths.m_pathNodes[curNode].pos - ThePaths.m_pathNodes[prevNode].pos; - CVector2D curToNext = ThePaths.m_pathNodes[nextNode].pos - ThePaths.m_pathNodes[curNode].pos; + CVector2D prevToCur = ThePaths.m_pathNodes[curNode].GetPosition() - ThePaths.m_pathNodes[prevNode].GetPosition(); + CVector2D curToNext = ThePaths.m_pathNodes[nextNode].GetPosition() - ThePaths.m_pathNodes[curNode].GetPosition(); float distPrevToCur = prevToCur.Magnitude(); if (distPrevToCur == 0.0f) return PATH_DIRECTION_NONE; @@ -1638,9 +1713,8 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t CPathNode* pTargetNode; int16 numNodes; float distanceToTargetNode; -#ifndef REMOVE_TREADABLE_PATHFIND if (pTarget && pTarget->m_pCurGroundEntity && - pTarget->m_pCurGroundEntity->m_type == ENTITY_TYPE_BUILDING && + pTarget->m_pCurGroundEntity->IsBuilding() && ((CBuilding*)pTarget->m_pCurGroundEntity)->GetIsATreadable() && ((CTreadable*)pTarget->m_pCurGroundEntity)->m_nodeIndices[0][0] >= 0){ CTreadable* pCurrentMapObject = (CTreadable*)pTarget->m_pCurGroundEntity; @@ -1650,31 +1724,31 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t int node = pCurrentMapObject->m_nodeIndices[0][i]; if (node < 0) break; - float dist = (ThePaths.m_pathNodes[node].pos - pTarget->GetPosition()).Magnitude(); + float dist = (ThePaths.m_pathNodes[node].GetPosition() - pTarget->GetPosition()).Magnitude(); if (dist < minDist){ minDist = dist; closestNode = node; } } - ThePaths.DoPathSearch(0, pCurNode->pos, curNode, + 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{ -#endif - ThePaths.DoPathSearch(0, pCurNode->pos, curNode, + }else + { + + ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode, #ifdef FIX_PATHFIND_BUG CVector(targetX, targetY, targetZ), #else CVector(targetX, targetY, 0.0f), #endif &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1); -#ifndef REMOVE_TREADABLE_PATHFIND } -#endif + int newNextNode; int nextLink; if (numNodes != 1 || pTargetNode == pCurNode){ @@ -1684,11 +1758,11 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t int numLinks = pCurNode->numLinks; newNextNode = 0; for (int i = 0; i < numLinks; i++){ - int conNode = ThePaths.m_connections[i + pCurNode->firstLink]; + int conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink); if (conNode == prevNode && i > 1) continue; CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode]; - float angle = CGeneral::GetATanOfXY(pTestNode->pos.x - pCurNode->pos.x, pTestNode->pos.y - pCurNode->pos.y); + float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY()); angle = LimitRadianAngle(angle - currentAngle); angle = ABS(angle); if (angle < lowestAngleChange){ @@ -1700,7 +1774,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t }else{ nextLink = 0; newNextNode = pTargetNode - ThePaths.m_pathNodes; - for (int i = pCurNode->firstLink; ThePaths.m_connections[i] != newNextNode; i++, nextLink++) + for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++) ; } CPathNode* pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode]; @@ -1725,12 +1799,12 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX(); + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY(); if (lanesOnNextNode >= 0) { - CVector2D dist = pNextPathNode->pos - pCurNode->pos; + CVector2D dist = pNextPathNode->GetPosition() - pCurNode->GetPosition(); if (dist.MagnitudeSqr() >= SQR(7.0f)){ /* 25% chance vehicle will try to switch lane */ /* No lane switching if following car from far away */ @@ -1755,17 +1829,17 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + float directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; /* We want to make a path between two links that may not have the same forward directions a curve. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -1801,7 +1875,7 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCurrentDirection = pVehicle->AutoPilot.m_nNextDirection; pVehicle->AutoPilot.m_nCurrentLane = pVehicle->AutoPilot.m_nNextLane; int nextLink = 0; - for (int i = pCurNode->firstLink; ThePaths.m_connections[i] != pVehicle->AutoPilot.m_nNextRouteNode; i++, nextLink++) + for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != pVehicle->AutoPilot.m_nNextRouteNode; i++, nextLink++) ; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]]; pVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]; @@ -1814,12 +1888,12 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX(); + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY(); if (lanesOnNextNode >= 0) { - CVector2D dist = pNextPathNode->pos - pCurNode->pos; + CVector2D dist = pNextPathNode->GetPosition() - pCurNode->GetPosition(); if (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) { if (CGeneral::GetRandomTrueFalse()) pVehicle->AutoPilot.m_nNextLane += 1; @@ -1835,17 +1909,17 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + float directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; /* We want to make a path between two links that may not have the same forward directions a curve. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -1964,9 +2038,8 @@ void CCarCtrl::DragCarToPoint(CVehicle* pVehicle, CVector* pPoint) pVehicle->GetRight() = CVector(posTarget.y - midPos.y, -(posTarget.x - midPos.x), 0.0f) / 3; pVehicle->GetForward() = CVector(-cosZ * pVehicle->GetRight().y, cosZ * pVehicle->GetRight().x, sinZ); pVehicle->GetUp() = CrossProduct(pVehicle->GetRight(), pVehicle->GetForward()); - pVehicle->GetPosition() = (CVector(midPos.x, midPos.y, actualBehindZ) - + CVector(posTarget.x, posTarget.y, actualAheadZ)) / 2; - pVehicle->GetPosition().z += pVehicle->GetHeightAboveRoad(); + pVehicle->SetPosition((CVector(midPos.x, midPos.y, actualBehindZ) + CVector(posTarget.x, posTarget.y, actualAheadZ)) / 2); + pVehicle->GetMatrix().GetPosition().z += pVehicle->GetHeightAboveRoad(); } float CCarCtrl::FindSpeedMultiplier(float angleChange, float minAngle, float maxAngle, float coef) @@ -2200,16 +2273,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv forward.Normalise(); CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - CVector2D currentPathLinkForward(pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection, - pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection); - float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + CVector2D currentPathLinkForward(pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection, + pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection); + float nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + float nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; CVector2D positionOnCurrentLinkIncludingLane( - pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, - pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); + pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); CVector2D positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX); + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX); CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane; float scalarDistanceToNextNode = distanceToNextNode.Magnitude(); CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane; @@ -2238,16 +2311,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv } pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; scalarDistanceToNextNode = CVector2D( - pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, - pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude(); + pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude(); pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - currentPathLinkForward.x = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - currentPathLinkForward.y = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + currentPathLinkForward.x = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + currentPathLinkForward.y = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; } - positionOnCurrentLinkIncludingLane.x = pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y; - positionOnCurrentLinkIncludingLane.y = pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x; + positionOnCurrentLinkIncludingLane.x = pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y; + positionOnCurrentLinkIncludingLane.y = pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x; CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f; if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){ projectedPosition.x = positionOnCurrentLinkIncludingLane.x; @@ -2289,8 +2362,8 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv CCarAI::CarHasReasonToStop(pVehicle); speedStyleMultiplier = 0.0f; } - CVector2D trajectory(pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, - pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); + CVector2D trajectory(pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); trajectory -= pVehicle->GetPosition(); float speedAngleMultiplier = FindSpeedMultiplier( CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward, @@ -2504,9 +2577,9 @@ void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle) int prevNodeId = -1; float minDistance = 999999.9f; for (int i = 0; i < pNode->numLinks; i++){ - int candidateId = ThePaths.m_connections[i + pNode->firstLink]; + int candidateId = ThePaths.ConnectedNode(i + pNode->firstLink); CPathNode* pCandidateNode = &ThePaths.m_pathNodes[candidateId]; - float distance = (pCandidateNode->pos - pNode->pos).Magnitude2D(); + float distance = (pCandidateNode->GetPosition() - pNode->GetPosition()).Magnitude2D(); if (distance < minDistance){ minDistance = distance; prevNodeId = candidateId; @@ -2518,7 +2591,7 @@ void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle) CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNodeId]; if (forward.x == 0.0f && forward.y == 0.0f) forward.x = 1.0f; - if (DotProduct2D(pNode->pos - pPrevNode->pos, forward) < 0.0f){ + if (DotProduct2D(pNode->GetPosition() - pPrevNode->GetPosition(), forward) < 0.0f){ int tmp; tmp = prevNodeId; prevNodeId = nodeId; @@ -2558,7 +2631,7 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle) int nextLink; CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode]; for (nextLink = 0; nextLink < 12; nextLink++) - if (ThePaths.m_connections[nextLink + pCurNode->firstLink] == pVehicle->AutoPilot.m_nNextRouteNode) + if (ThePaths.ConnectedNode(nextLink + pCurNode->firstLink) == pVehicle->AutoPilot.m_nNextRouteNode) break; pVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]; pVehicle->AutoPilot.m_nNextDirection = (pVehicle->AutoPilot.m_nCurrentRouteNode >= pVehicle->AutoPilot.m_nNextRouteNode) ? 1 : -1; @@ -2575,7 +2648,7 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle) } } pVehicle->AutoPilot.m_nCurrentPathNodeInfo = curConnection; - pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.m_connections[curLink + pCurNode->firstLink] >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1; + pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(curLink + pCurNode->firstLink) >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1; } void CCarCtrl::GenerateEmergencyServicesCar(void) @@ -2647,7 +2720,7 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos) return nil; CAutomobile* pVehicle = new CAutomobile(mi, RANDOM_VEHICLE); pVehicle->AutoPilot.m_vecDestinationCoors = vecPos; - pVehicle->GetPosition() = spawnPos; + pVehicle->SetPosition(spawnPos); pVehicle->AutoPilot.m_nCarMission = (JoinCarWithRoadSystemGotoCoors(pVehicle, vecPos, false)) ? MISSION_GOTOCOORDS_STRAIGHT : MISSION_GOTOCOORDS; pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed = 25; pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; @@ -2657,7 +2730,7 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos) pVehicle->GetForward() = CVector(direction.x, direction.y, 0.0f); pVehicle->GetRight() = CVector(direction.y, -direction.x, 0.0f); pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); - spawnPos.z = posBetweenNodes * ThePaths.m_pathNodes[curNode].pos.z + (1.0f - posBetweenNodes) * ThePaths.m_pathNodes[nextNode].pos.z; + spawnPos.z = posBetweenNodes * ThePaths.m_pathNodes[curNode].GetZ() + (1.0f - posBetweenNodes) * ThePaths.m_pathNodes[nextNode].GetZ(); float groundZ = INFINITE_Z; CColPoint colPoint; CEntity* pEntity; @@ -2672,9 +2745,9 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos) return false; } spawnPos.z = groundZ + pVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); - pVehicle->GetPosition() = spawnPos; + pVehicle->SetPosition(spawnPos); pVehicle->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f)); - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); switch (mi){ case MI_FIRETRUCK: pVehicle->bIsFireTruckOnDuty = true; diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 44ef9ab6..457224fb 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -23,6 +23,7 @@ enum{ class CCarCtrl { +public: enum eCarClass { POOR = 0, RICH, @@ -43,7 +44,7 @@ class CCarCtrl GANG9, COPS }; -public: + static void SwitchVehicleToRealPhysics(CVehicle*); static void AddToCarArray(int32 id, int32 vehclass); static void UpdateCarCount(CVehicle*, bool); diff --git a/src/control/Curves.cpp b/src/control/Curves.cpp index 623ab040..0a01a7aa 100644 --- a/src/control/Curves.cpp +++ b/src/control/Curves.cpp @@ -19,7 +19,7 @@ void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVe float actualFactor = CalcSpeedScaleFactor(pPos1, pPos2, pDir1->x, pDir1->y, pDir2->x, pDir2->y); CVector2D dir1 = *pDir1 * actualFactor; CVector2D dir2 = *pDir2 * actualFactor; - float curveCoef = 0.5f - 0.5f * cos(3.1415f * between); + float curveCoef = 0.5f - 0.5f * Cos(3.1415f * between); *pOutPos = CVector( (pPos1->x + between * dir1.x) * (1.0f - curveCoef) + (pPos2->x - (1 - between) * dir2.x) * curveCoef, (pPos1->y + between * dir1.y) * (1.0f - curveCoef) + (pPos2->y - (1 - between) * dir2.y) * curveCoef, diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp index f8c8fa69..abb5c5f3 100644 --- a/src/control/GameLogic.cpp +++ b/src/control/GameLogic.cpp @@ -102,8 +102,8 @@ CGameLogic::Update() if (pVehicle != nil) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) { pVehicle->pDriver = nil; - if (pVehicle->m_status != STATUS_WRECKED) - pVehicle->m_status = STATUS_ABANDONED; + if (pVehicle->GetStatus() != STATUS_WRECKED) + pVehicle->SetStatus(STATUS_ABANDONED); } else pVehicle->RemovePassenger(pPlayerInfo.m_pPed); } @@ -172,8 +172,8 @@ CGameLogic::Update() if (pVehicle != nil) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) { pVehicle->pDriver = nil; - if (pVehicle->m_status != STATUS_WRECKED) - pVehicle->m_status = STATUS_ABANDONED; + if (pVehicle->GetStatus() != STATUS_WRECKED) + pVehicle->SetStatus(STATUS_ABANDONED); } else pVehicle->RemovePassenger(pPlayerInfo.m_pPed); @@ -214,8 +214,8 @@ CGameLogic::Update() if (pVehicle != nil) { if (pVehicle->pDriver == pPlayerInfo.m_pPed) { pVehicle->pDriver = nil; - if (pVehicle->m_status != STATUS_WRECKED) - pVehicle->m_status = STATUS_ABANDONED; + if (pVehicle->GetStatus() != STATUS_WRECKED) + pVehicle->SetStatus(STATUS_ABANDONED); } else pVehicle->RemovePassenger(pPlayerInfo.m_pPed); } diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index a4aa3729..b6786598 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -528,9 +528,14 @@ void CGarage::Update() CGarages::GivePlayerDetonator(); CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB; } +#ifdef DETECT_PAD_INPUT_SWITCH + int16 Mode = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0; +#else + int16 Mode = CPad::GetPad(0)->Mode; +#endif switch (m_eGarageType) { case GARAGE_BOMBSHOP1: - switch (CPad::GetPad(0)->Mode) { + switch (Mode) { case 0: case 1: case 2: @@ -542,7 +547,7 @@ void CGarage::Update() } break; case GARAGE_BOMBSHOP2: - switch (CPad::GetPad(0)->Mode) { + switch (Mode) { case 0: case 1: case 2: @@ -749,7 +754,7 @@ void CGarage::Update() if (((CAutomobile*)(m_pTarget))->Damage.GetEngineStatus() <= ENGINE_STATUS_ON_FIRE && ((CAutomobile*)(m_pTarget))->m_fFireBlowUpTimer == 0.0f) { #endif - if (m_pTarget->m_status != STATUS_WRECKED) { + if (m_pTarget->GetStatus() != STATUS_WRECKED) { CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE); FindPlayerPed()->m_pWanted->m_bIgnoredByCops = true; m_eGarageState = GS_CLOSING; @@ -1390,7 +1395,7 @@ void CGarages::PrintMessages() CFont::SetBackgroundOff(); CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(50.0f)); CFont::SetCentreOn(); - CFont::SetFontStyle(FONT_BANK); + CFont::SetFontStyle(FONT_LOCALE(FONT_BANK)); CFont::SetColor(CRGBA(0, 0, 0, 255)); #if defined(PS2) || defined (FIX_BUGS) @@ -1448,14 +1453,14 @@ void CGarage::UpdateDoorsHeight() { RefreshDoorPointers(false); if (m_pDoor1) { - m_pDoor1->GetPosition().z = m_fDoorPos + m_fDoor1Z; + m_pDoor1->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor1Z; if (m_bRotatedDoor) BuildRotatedDoorMatrix(m_pDoor1, m_fDoorPos / m_fDoorHeight); m_pDoor1->GetMatrix().UpdateRW(); m_pDoor1->UpdateRwFrame(); } if (m_pDoor2) { - m_pDoor2->GetPosition().z = m_fDoorPos + m_fDoor2Z; + m_pDoor2->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor2Z; if (m_bRotatedDoor) BuildRotatedDoorMatrix(m_pDoor2, m_fDoorPos / m_fDoorHeight); m_pDoor2->GetMatrix().UpdateRW(); @@ -1482,18 +1487,18 @@ void CGarage::UpdateCrusherAngle() void CGarage::UpdateCrusherShake(float X, float Y) { RefreshDoorPointers(false); - m_pDoor1->GetPosition().x += X; - m_pDoor1->GetPosition().y += Y; + m_pDoor1->GetMatrix().GetPosition().x += X; + m_pDoor1->GetMatrix().GetPosition().y += Y; m_pDoor1->GetMatrix().UpdateRW(); m_pDoor1->UpdateRwFrame(); - m_pDoor1->GetPosition().x -= X; - m_pDoor1->GetPosition().y -= Y; - m_pDoor2->GetPosition().x += X; - m_pDoor2->GetPosition().y += Y; + m_pDoor1->GetMatrix().GetPosition().x -= X; + m_pDoor1->GetMatrix().GetPosition().y -= Y; + m_pDoor2->GetMatrix().GetPosition().x += X; + m_pDoor2->GetMatrix().GetPosition().y += Y; m_pDoor2->GetMatrix().UpdateRW(); m_pDoor2->UpdateRwFrame(); - m_pDoor2->GetPosition().x -= X; - m_pDoor2->GetPosition().y -= Y; + m_pDoor2->GetMatrix().GetPosition().x -= X; + m_pDoor2->GetMatrix().GetPosition().y -= Y; } // This is dumb but there is no way to avoid goto. What was there originally even? @@ -1854,8 +1859,8 @@ CVehicle* CStoredCar::RestoreCar() #else CVehicle* pVehicle = new CAutomobile(m_nModelIndex, RANDOM_VEHICLE); #endif - pVehicle->GetPosition() = m_vecPos; - pVehicle->m_status = STATUS_ABANDONED; + pVehicle->SetPosition(m_vecPos); + pVehicle->SetStatus(STATUS_ABANDONED); pVehicle->GetForward() = m_vecAngle; pVehicle->GetRight() = CVector(m_vecAngle.y, -m_vecAngle.x, 0.0f); pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); @@ -1975,7 +1980,7 @@ void CGarage::TidyUpGarage() if (pVehicle->GetPosition().x > m_fX1 && pVehicle->GetPosition().x < m_fX2 && pVehicle->GetPosition().y > m_fY1 && pVehicle->GetPosition().y < m_fY2 && pVehicle->GetPosition().z > m_fZ1 && pVehicle->GetPosition().z < m_fZ2) { - if (pVehicle->m_status == STATUS_WRECKED || pVehicle->GetUp().z < 0.5f) { + if (pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->GetUp().z < 0.5f) { CWorld::Remove(pVehicle); delete pVehicle; } @@ -1990,7 +1995,7 @@ void CGarage::TidyUpGarageClose() CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); if (!pVehicle || !pVehicle->IsCar()) continue; - if (!pVehicle->IsCar() || pVehicle->m_status != STATUS_WRECKED || !IsEntityTouching3D(pVehicle)) + if (!pVehicle->IsCar() || pVehicle->GetStatus() != STATUS_WRECKED || !IsEntityTouching3D(pVehicle)) continue; bool bRemove = false; if (m_eGarageState != GS_FULLYCLOSED) { @@ -2089,15 +2094,15 @@ void CGarage::CenterCarInGarage(CVehicle* pVehicle) float offsetZ = pos.z - pos.z; float distance = CVector(offsetX, offsetY, offsetZ).Magnitude(); if (distance < RESPRAY_CENTERING_COEFFICIENT) { - pVehicle->GetPosition().x = GetGarageCenterX(); - pVehicle->GetPosition().y = GetGarageCenterY(); + pVehicle->GetMatrix().GetPosition().x = GetGarageCenterX(); + pVehicle->GetMatrix().GetPosition().y = GetGarageCenterY(); } else { - pVehicle->GetPosition().x += offsetX * RESPRAY_CENTERING_COEFFICIENT / distance; - pVehicle->GetPosition().y += offsetY * RESPRAY_CENTERING_COEFFICIENT / distance; + pVehicle->GetMatrix().GetPosition().x += offsetX * RESPRAY_CENTERING_COEFFICIENT / distance; + pVehicle->GetMatrix().GetPosition().y += offsetY * RESPRAY_CENTERING_COEFFICIENT / distance; } if (!IsEntityEntirelyInside3D(pVehicle, 0.1f)) - pVehicle->GetPosition() = pos; + pVehicle->SetPosition(pos); } void CGarages::CloseHideOutGaragesBeforeSave() @@ -2164,7 +2169,7 @@ int32 CGarages::FindMaxNumStoredCarsForGarage(eGarageType type) return 0; } -bool CGarages::IsPointWithinHideOutGarage(CVector& point) +bool CGarages::IsPointWithinHideOutGarage(Const CVector& point) { for (int i = 0; i < NUM_GARAGES; i++) { switch (aGarages[i].m_eGarageType) { @@ -2180,7 +2185,7 @@ bool CGarages::IsPointWithinHideOutGarage(CVector& point) return false; } -bool CGarages::IsPointWithinAnyGarage(CVector& point) +bool CGarages::IsPointWithinAnyGarage(Const CVector& point) { for (int i = 0; i < NUM_GARAGES; i++) { switch (aGarages[i].m_eGarageType) { @@ -2205,7 +2210,7 @@ void CGarages::SetAllDoorsBackToOriginalHeight() default: aGarages[i].RefreshDoorPointers(true); if (aGarages[i].m_pDoor1) { - aGarages[i].m_pDoor1->GetPosition().z = aGarages[i].m_fDoor1Z; + aGarages[i].m_pDoor1->GetMatrix().GetPosition().z = aGarages[i].m_fDoor1Z; if (aGarages[i].m_pDoor1->IsObject()) ((CObject*)aGarages[i].m_pDoor1)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor1Z; if (aGarages[i].m_bRotatedDoor) @@ -2214,7 +2219,7 @@ void CGarages::SetAllDoorsBackToOriginalHeight() aGarages[i].m_pDoor1->UpdateRwFrame(); } if (aGarages[i].m_pDoor2) { - aGarages[i].m_pDoor2->GetPosition().z = aGarages[i].m_fDoor2Z; + aGarages[i].m_pDoor2->GetMatrix().GetPosition().z = aGarages[i].m_fDoor2Z; if (aGarages[i].m_pDoor2->IsObject()) ((CObject*)aGarages[i].m_pDoor2)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor2Z; if (aGarages[i].m_bRotatedDoor) diff --git a/src/control/Garages.h b/src/control/Garages.h index 65193b32..00020eb3 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -75,7 +75,7 @@ public: CVehicle* RestoreCar(); }; -static_assert(sizeof(CStoredCar) == 0x28, "CStoredCar"); +VALIDATE_SIZE(CStoredCar, 0x28); #define SWITCH_GARAGE_DISTANCE_CLOSE 40.0f @@ -172,7 +172,7 @@ class CGarage friend class CCamera; }; -static_assert(sizeof(CGarage) == 140, "CGarage"); +VALIDATE_SIZE(CGarage, 140); class CGarages { @@ -232,8 +232,8 @@ public: static bool CameraShouldBeOutside(void); static void GivePlayerDetonator(void); static void PlayerArrestedOrDied(void); - static bool IsPointWithinHideOutGarage(CVector&); - static bool IsPointWithinAnyGarage(CVector&); + static bool IsPointWithinHideOutGarage(Const CVector&); + static bool IsPointWithinAnyGarage(Const CVector&); static void SetAllDoorsBackToOriginalHeight(void); static void Save(uint8* buf, uint32* size); static void Load(uint8* buf, uint32 size); diff --git a/src/control/OnscreenTimer.h b/src/control/OnscreenTimer.h index fb139266..3ef7764a 100644 --- a/src/control/OnscreenTimer.h +++ b/src/control/OnscreenTimer.h @@ -26,7 +26,7 @@ public: void ProcessForDisplayCounter(); }; -static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error"); +VALIDATE_SIZE(COnscreenTimerEntry, 0x74); class COnscreenTimer { @@ -46,4 +46,4 @@ public: void AddClock(uint32 offset, char* text); }; -static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error");
\ No newline at end of file +VALIDATE_SIZE(COnscreenTimer, 0x78); diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 44062b38..ee15b82f 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -17,12 +17,19 @@ CPathFind ThePaths; #define MAX_DIST INT16_MAX-1 #define MIN_PED_ROUTE_DISTANCE 23.8f + +#define NUMTEMPNODES 4000 +#define NUMDETACHED_CARS 100 +#define NUMDETACHED_PEDS 50 + + // object flags: // 1 UseInRoadBlock // 2 east/west road(?) CPathInfoForObject *InfoForTileCars; CPathInfoForObject *InfoForTilePeds; + // unused CTempDetachedNode *DetachedNodesCars; CTempDetachedNode *DetachedNodesPeds; @@ -243,6 +250,7 @@ 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]; @@ -253,10 +261,10 @@ CPathFind::AllocatePathFindInfoMem(int16 numPathGroups) DetachedNodesCars = nil; delete[] DetachedNodesPeds; DetachedNodesPeds = nil; - DetachedNodesCars = new CTempDetachedNode[100]; - memset(DetachedNodesCars, 0, 100*sizeof(CTempDetachedNode)); - DetachedNodesPeds = new CTempDetachedNode[50]; - memset(DetachedNodesPeds, 0, 50*sizeof(CTempDetachedNode)); + DetachedNodesCars = new CTempDetachedNode[NUMDETACHED_CARS]; + memset(DetachedNodesCars, 0, NUMDETACHED_CARS*sizeof(CTempDetachedNode)); + DetachedNodesPeds = new CTempDetachedNode[NUMDETACHED_PEDS]; + memset(DetachedNodesPeds, 0, NUMDETACHED_PEDS*sizeof(CTempDetachedNode)); } void @@ -306,6 +314,7 @@ CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, InfoForTileCars[i].numLeftLanes = numLeft; InfoForTileCars[i].numRightLanes = numRight; + if(type) for(i = 0; i < node; i++){ j = id*12 + i; @@ -346,10 +355,12 @@ CPathFind::PreparePathData(void) printf("PreparePathData\n"); if(!CPathFind::LoadPathFindData() && // empty InfoForTileCars && InfoForTilePeds && - DetachedNodesCars && DetachedNodesPeds){ - tempNodes = new CTempNode[4000]; + DetachedNodesCars && DetachedNodesPeds + ){ + tempNodes = new CTempNode[NUMTEMPNODES]; m_numConnections = 0; + for(i = 0; i < PATHNODESIZE; i++) m_pathNodes[i].unkBits = 0; @@ -369,6 +380,7 @@ CPathFind::PreparePathData(void) for(i = 0; i < PATHNODESIZE; i++) for(j = 0; j < 12; j++) if(InfoForTileCars[i*12 + j].type == NodeTypeExtern){ + // MIAMI has MI:%d here but no argument for it if(InfoForTileCars[i*12 + j].numLeftLanes < 0) printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i); if(InfoForTileCars[i*12 + j].numRightLanes < 0) @@ -378,9 +390,9 @@ CPathFind::PreparePathData(void) } m_numPathNodes = 0; - PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, 100); + PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, NUMDETACHED_CARS); m_numCarPathNodes = m_numPathNodes; - PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, 50); + PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, NUMDETACHED_PEDS); m_numPedPathNodes = m_numPathNodes - m_numCarPathNodes; // TODO: figure out what exactly is going on here @@ -431,6 +443,7 @@ CPathFind::PreparePathData(void) InfoForTileCars = nil; delete[] InfoForTilePeds; InfoForTilePeds = nil; + delete[] DetachedNodesCars; DetachedNodesCars = nil; delete[] DetachedNodesPeds; @@ -476,29 +489,28 @@ CPathFind::CountFloodFillGroups(uint8 type) break; node = &m_pathNodes[i]; - node->next = nil; + node->SetNext(nil); node->group = n; if(node->numLinks == 0){ if(type == PATH_CAR) printf("Single car node: %f %f %f (%d)\n", - node->pos.x, node->pos.y, node->pos.z, - m_mapObjects[node->objectIndex]->m_modelIndex); + node->GetX(), node->GetY(), node->GetZ(), m_mapObjects[node->objectIndex]->GetModelIndex()); else printf("Single ped node: %f %f %f\n", - node->pos.x, node->pos.y, node->pos.z); + node->GetX(), node->GetY(), node->GetZ()); } while(node){ prev = node; - node = node->next; + node = node->GetNext(); for(i = 0; i < prev->numLinks; i++){ - l = m_connections[prev->firstLink + i]; + l = ConnectedNode(prev->firstLink + i); if(m_pathNodes[l].group == 0){ m_pathNodes[l].group = n; if(m_pathNodes[l].group == 0) m_pathNodes[l].group = INT8_MIN; - m_pathNodes[l].next = node; + m_pathNodes[l].SetNext(node); node = &m_pathNodes[l]; } } @@ -513,7 +525,7 @@ int32 TempListLength; void CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, - float maxdist, CTempDetachedNode *detachednodes, int unused) + float maxdist, CTempDetachedNode *detachednodes, int numDetached) { static CVector CoorsXFormed; int i, j, k, l; @@ -525,14 +537,16 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor int nearestId; int next; int oldNumPathNodes, oldNumLinks; - CVector dist; + 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++) @@ -540,28 +554,30 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor // Calculate internal nodes, store them and connect them to defining object for(i = 0; i < m_numMapObjects; i++){ - start = 12*m_mapObjects[i]->m_modelIndex; + tileStart = m_numPathNodes; + start = 12 * m_mapObjects[i]->GetModelIndex(); for(j = 0; j < 12; j++){ - if(objectpathinfo[start + j].type != NodeTypeIntern) - continue; - CalcNodeCoors( - objectpathinfo[start + j].x, - objectpathinfo[start + j].y, - objectpathinfo[start + j].z, - i, - &CoorsXFormed); - m_pathNodes[m_numPathNodes].pos = CoorsXFormed; - m_pathNodes[m_numPathNodes].objectIndex = i; - m_pathNodes[m_numPathNodes].unkBits = 1; - m_mapObjects[i]->m_nodeIndices[type][j] = m_numPathNodes++; + if(objectpathinfo[start + j].type == NodeTypeIntern){ + CalcNodeCoors( + objectpathinfo[start + j].x, + objectpathinfo[start + j].y, + objectpathinfo[start + j].z, + i, + &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_numPathNodes++; + } } } + // Insert external nodes into TempList TempListLength = 0; for(i = 0; i < m_numMapObjects; i++){ - start = 12*m_mapObjects[i]->m_modelIndex; - + start = 12 * m_mapObjects[i]->GetModelIndex(); for(j = 0; j < 12; j++){ if(objectpathinfo[start + j].type != NodeTypeExtern) continue; @@ -618,8 +634,8 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor tempnodes[nearestId].linkState = 2; // collapse this node with nearest we found - dx = m_pathNodes[tempnodes[nearestId].link1].pos.x - m_pathNodes[tempnodes[nearestId].link2].pos.x; - dy = m_pathNodes[tempnodes[nearestId].link1].pos.y - m_pathNodes[tempnodes[nearestId].link2].pos.y; + 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; @@ -648,6 +664,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor continue; // Add link to other side of the external + // NB this clears the flags in MIAMI if(tempnodes[j].link1 == i) m_connections[m_numConnections] = tempnodes[j].link2; else if(tempnodes[j].link2 == i) @@ -655,8 +672,8 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor else continue; - dist = m_pathNodes[i].pos - m_pathNodes[m_connections[m_numConnections]].pos; - m_distances[m_numConnections] = dist.Magnitude(); + dist = (m_pathNodes[i].GetPosition() - m_pathNodes[ConnectedNode(m_numConnections)].GetPosition()).Magnitude(); + m_distances[m_numConnections] = dist; m_connectionFlags[m_numConnections].flags = 0; if(type == PATH_CAR){ @@ -681,6 +698,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes; m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes; m_carPathLinks[m_numCarPathLinks].trafficLightType = 0; + assert(m_numCarPathLinks <= NUM_CARPATHLINKS); m_carPathConnections[m_numConnections] = m_numCarPathLinks++; } } @@ -689,33 +707,35 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor m_numConnections++; } + // Find i inside path segment iseg = 0; for(j = Max(oldNumPathNodes, i-12); j < i; j++) - if(m_pathNodes[j].objectIndex == m_pathNodes[i].objectIndex) + if(OBJECTINDEX(j) == OBJECTINDEX(i)) iseg++; - istart = 12*m_mapObjects[m_pathNodes[i].objectIndex]->m_modelIndex; + 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(m_pathNodes[i].objectIndex != m_pathNodes[j].objectIndex || i == j) + if(OBJECTINDEX(i) != OBJECTINDEX(j) || i == j) continue; // 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]->m_modelIndex; + jstart = 12 * m_mapObjects[m_pathNodes[j].objectIndex]->GetModelIndex(); if(objectpathinfo[istart + iseg].next == jseg || objectpathinfo[jstart + jseg].next == iseg){ - // Found a link between i and j + // Found a link between i and jConnectionSetCrossesRoad + // NB this clears the flags in MIAMI m_connections[m_numConnections] = j; - dist = m_pathNodes[i].pos - m_pathNodes[j].pos; - m_distances[m_numConnections] = dist.Magnitude(); + dist = (m_pathNodes[i].GetPosition() - m_pathNodes[j].GetPosition()).Magnitude(); + m_distances[m_numConnections] = dist; if(type == PATH_CAR){ - posx = (m_pathNodes[i].pos.x + m_pathNodes[j].pos.x)*0.5f; - posy = (m_pathNodes[i].pos.y + m_pathNodes[j].pos.y)*0.5f; - dx = m_pathNodes[j].pos.x - m_pathNodes[i].pos.x; - dy = m_pathNodes[j].pos.y - m_pathNodes[i].pos.y; + posx = (m_pathNodes[i].GetX() + m_pathNodes[j].GetX())*0.5f; + posy = (m_pathNodes[i].GetY() + m_pathNodes[j].GetY())*0.5f; + dx = m_pathNodes[j].GetX() - m_pathNodes[i].GetX(); + dy = m_pathNodes[j].GetY() - m_pathNodes[i].GetY(); mag = Sqrt(dx*dx + dy*dy); dx /= mag; dy /= mag; @@ -744,6 +764,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1; m_carPathLinks[m_numCarPathLinks].numRightLanes = -1; m_carPathLinks[m_numCarPathLinks].trafficLightType = 0; + assert(m_numCarPathLinks <= NUM_CARPATHLINKS); m_carPathConnections[m_numConnections] = m_numCarPathLinks++; } }else{ @@ -825,7 +846,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor if(!m_pathNodes[i].bDeadEnd){ k = 0; for(j = 0; j < m_pathNodes[i].numLinks; j++) - if(!m_pathNodes[m_connections[m_pathNodes[i].firstLink + j]].bDeadEnd) + if(!m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].bDeadEnd) k++; if(k < 2){ m_pathNodes[i].bDeadEnd = true; @@ -847,9 +868,11 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor m_pathNodes[j] = m_pathNodes[j+1]; // Fix links - for(j = oldNumLinks; j < m_numConnections; j++) - if(m_connections[j] >= i) - m_connections[j]--; + for(j = oldNumLinks; j < m_numConnections; j++){ + int node = ConnectedNode(j); + if(node >= i) + m_connections[j] = node-1; + } // Also in treadables for(j = 0; j < m_numMapObjects; j++) @@ -875,12 +898,12 @@ CPathFind::CalcRoadDensity(float x, float y) float density = 0.0f; for(i = 0; i < m_numCarPathNodes; i++){ - if(Abs(m_pathNodes[i].pos.x - x) < 80.0f && - Abs(m_pathNodes[i].pos.y - y) < 80.0f && + if(Abs(m_pathNodes[i].GetX() - x) < 80.0f && + Abs(m_pathNodes[i].GetY() - y) < 80.0f && m_pathNodes[i].numLinks > 0){ for(j = 0; j < m_pathNodes[i].numLinks; j++){ - int next = m_connections[m_pathNodes[i].firstLink + j]; - float dist = (m_pathNodes[i].pos - m_pathNodes[next].pos).Magnitude2D(); + int next = ConnectedNode(m_pathNodes[i].firstLink + j); + float dist = (m_pathNodes[i].GetPosition() - m_pathNodes[next].GetPosition()).Magnitude2D(); next = m_carPathConnections[m_pathNodes[i].firstLink + j]; density += m_carPathLinks[next].numLeftLanes * dist; density += m_carPathLinks[next].numRightLanes * dist; @@ -888,11 +911,11 @@ CPathFind::CalcRoadDensity(float x, float y) 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[m_connections[m_pathNodes[i].firstLink + j]].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[m_connections[m_pathNodes[i].firstLink + j]].objectIndex]->GetModelIndex()); + m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex()); } } } @@ -904,8 +927,8 @@ CPathFind::TestForPedTrafficLight(CPathNode *n1, CPathNode *n2) { int i; for(i = 0; i < n1->numLinks; i++) - if(&m_pathNodes[m_connections[n1->firstLink + i]] == n2) - return m_connectionFlags[n1->firstLink + i].bTrafficLight; + if(&m_pathNodes[ConnectedNode(n1->firstLink + i)] == n2) + return ConnectionHasTrafficLight(n1->firstLink + i); return false; } @@ -914,8 +937,8 @@ CPathFind::TestCrossesRoad(CPathNode *n1, CPathNode *n2) { int i; for(i = 0; i < n1->numLinks; i++) - if(&m_pathNodes[m_connections[n1->firstLink + i]] == n2) - return m_connectionFlags[n1->firstLink + i].bCrossesRoad; + if(&m_pathNodes[ConnectedNode(n1->firstLink + i)] == n2) + return ConnectionCrossesRoad(n1->firstLink + i); return false; } @@ -923,20 +946,20 @@ void CPathFind::AddNodeToList(CPathNode *node, int32 listId) { int i = listId & 0x1FF; - node->next = m_searchNodes[i].next; - node->prev = &m_searchNodes[i]; - if(m_searchNodes[i].next) - m_searchNodes[i].next->prev = node; - m_searchNodes[i].next = node; + node->SetNext(m_searchNodes[i].GetNext()); + node->SetPrev(&m_searchNodes[i]); + if(m_searchNodes[i].GetNext()) + m_searchNodes[i].GetNext()->SetPrev(node); + m_searchNodes[i].SetNext(node); node->distance = listId; } void CPathFind::RemoveNodeFromList(CPathNode *node) { - node->prev->next = node->next; - if(node->next) - node->next->prev = node->prev; + node->GetPrev()->SetNext(node->GetNext()); + if(node->GetNext()) + node->GetNext()->SetPrev(node->GetPrev()); } void @@ -945,7 +968,7 @@ CPathFind::RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n) int i; if(*n < 2) return; - if(DotProduct2D(nodes[1]->pos - pos, nodes[0]->pos - pos) < 0.0f){ + if(DotProduct2D(nodes[1]->GetPosition() - pos, nodes[0]->GetPosition() - pos) < 0.0f){ (*n)--; for(i = 0; i < *n; i++) nodes[i] = nodes[i+1]; @@ -956,10 +979,12 @@ void CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool enable) { int i; - for(i = 0; i < m_numCarPathLinks; i++) - if(x1 < m_carPathLinks[i].pos.x && m_carPathLinks[i].pos.x < x2 && - y1 < m_carPathLinks[i].pos.y && m_carPathLinks[i].pos.y < y2) + for(i = 0; i < m_numCarPathLinks; i++){ + CVector2D pos = m_carPathLinks[i].GetPosition(); + if(x1 < pos.x && pos.x < x2 && + y1 < pos.y && pos.y < y2) m_carPathLinks[i].bBridgeLights = enable; + } } void @@ -970,7 +995,7 @@ CPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable) m_pathNodes[nodeId].bDisabled = disable; if(m_pathNodes[nodeId].numLinks < 3) for(i = 0; i < m_pathNodes[nodeId].numLinks; i++){ - next = m_connections[m_pathNodes[nodeId].firstLink + i]; + next = ConnectedNode(m_pathNodes[nodeId].firstLink + i); if(m_pathNodes[next].bDisabled != disable && m_pathNodes[next].numLinks < 3) SwitchOffNodeAndNeighbours(next, disable); @@ -982,12 +1007,14 @@ CPathFind::SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1 { int i; - for(i = 0; i < m_numCarPathNodes; i++) - if (x1 <= m_pathNodes[i].pos.x && m_pathNodes[i].pos.x <= x2 && - y1 <= m_pathNodes[i].pos.y && m_pathNodes[i].pos.y <= y2 && - z1 <= m_pathNodes[i].pos.z && m_pathNodes[i].pos.z <= z2 && + for(i = 0; i < m_numCarPathNodes; i++){ + CVector pos = m_pathNodes[i].GetPosition(); + if(x1 <= pos.x && pos.x <= x2 && + y1 <= pos.y && pos.y <= y2 && + z1 <= pos.z && pos.z <= z2 && disable != m_pathNodes[i].bDisabled) SwitchOffNodeAndNeighbours(i, disable); + } } void @@ -995,12 +1022,14 @@ CPathFind::SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float { int i; - for(i = m_numCarPathNodes; i < m_numPathNodes; i++) - if(x1 <= m_pathNodes[i].pos.x && m_pathNodes[i].pos.x <= x2 && - y1 <= m_pathNodes[i].pos.y && m_pathNodes[i].pos.y <= y2 && - z1 <= m_pathNodes[i].pos.z && m_pathNodes[i].pos.z <= z2 && + for(i = m_numCarPathNodes; i < m_numPathNodes; i++){ + CVector pos = m_pathNodes[i].GetPosition(); + if(x1 <= pos.x && pos.x <= x2 && + y1 <= pos.y && pos.y <= y2 && + z1 <= pos.z && pos.z <= z2 && disable != m_pathNodes[i].bDisabled) SwitchOffNodeAndNeighbours(i, disable); + } } void @@ -1039,9 +1068,10 @@ CPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float bool disable = mode == SWITCH_OFF; for(i = firstNode; i < lastNode; i++){ - if(m_pathNodes[i].pos.z < z1 || m_pathNodes[i].pos.z > z2) + CVector pos = m_pathNodes[i].GetPosition(); + if(pos.z < z1 || pos.z > z2) continue; - CVector2D d(m_pathNodes[i].pos.x - x1, m_pathNodes[i].pos.y - y1); + CVector2D d(pos.x - x1, pos.y - y1); float dot = DotProduct2D(d, v12); if(dot < 0.0f || dot > len12) continue; @@ -1061,7 +1091,7 @@ CPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId) m_pathNodes[nodeId].bBetweenLevels = true; if(m_pathNodes[nodeId].numLinks < 3) for(i = 0; i < m_pathNodes[nodeId].numLinks; i++){ - next = m_connections[m_pathNodes[nodeId].firstLink + i]; + next = ConnectedNode(m_pathNodes[nodeId].firstLink + i); if(!m_pathNodes[next].bBetweenLevels && m_pathNodes[next].numLinks < 3) MarkRoadsBetweenLevelsNodeAndNeighbours(next); @@ -1073,11 +1103,13 @@ CPathFind::MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, { int i; - for(i = 0; i < m_numPathNodes; i++) - if(x1 < m_pathNodes[i].pos.x && m_pathNodes[i].pos.x < x2 && - y1 < m_pathNodes[i].pos.y && m_pathNodes[i].pos.y < y2 && - z1 < m_pathNodes[i].pos.z && m_pathNodes[i].pos.z < z2) + for(i = 0; i < m_numPathNodes; i++){ + CVector pos = m_pathNodes[i].GetPosition(); + if(x1 < pos.x && pos.x < x2 && + y1 < pos.y && pos.y < y2 && + z1 < pos.z && pos.z < z2) MarkRoadsBetweenLevelsNodeAndNeighbours(i); + } } void @@ -1085,11 +1117,13 @@ CPathFind::PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y { int i; - for(i = m_numCarPathNodes; i < m_numPathNodes; i++) - if(x1 < m_pathNodes[i].pos.x && m_pathNodes[i].pos.x < x2 && - y1 < m_pathNodes[i].pos.y && m_pathNodes[i].pos.y < y2 && - z1 < m_pathNodes[i].pos.z && m_pathNodes[i].pos.z < z2) + for(i = m_numCarPathNodes; i < m_numPathNodes; i++){ + CVector pos = m_pathNodes[i].GetPosition(); + if(x1 < pos.x && pos.x < x2 && + y1 < pos.y && pos.y < y2 && + z1 < pos.z && pos.z < z2) MarkRoadsBetweenLevelsNodeAndNeighbours(i); + } } int32 @@ -1118,9 +1152,9 @@ CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bo switch(m_pathNodes[i].unkBits){ case 1: case 2: - dist = Abs(m_pathNodes[i].pos.x - coors.x) + - Abs(m_pathNodes[i].pos.y - coors.y) + - 3.0f*Abs(m_pathNodes[i].pos.z - coors.z); + 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; @@ -1156,10 +1190,10 @@ CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, floa switch(m_pathNodes[i].unkBits){ case 1: case 2: - dX = m_pathNodes[i].pos.x - coors.x; - dY = m_pathNodes[i].pos.y - coors.y; + 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].pos.z - coors.z); + 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z); if(dist < closestDist){ NormalizeXY(dX, dY); dist -= (dX*dirX + dY*dirY - 1.0f)*20.0f; @@ -1174,13 +1208,12 @@ CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, floa return closestNode; } - float CPathFind::FindNodeOrientationForCarPlacement(int32 nodeId) { if(m_pathNodes[nodeId].numLinks == 0) return 0.0f; - CVector dir = m_pathNodes[m_connections[m_pathNodes[nodeId].firstLink]].pos - m_pathNodes[nodeId].pos; + CVector dir = m_pathNodes[ConnectedNode(m_pathNodes[nodeId].firstLink)].GetPosition() - m_pathNodes[nodeId].GetPosition(); dir.z = 0.0f; dir.Normalise(); return RADTODEG(dir.Heading()); @@ -1191,14 +1224,14 @@ CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, flo { int i; - CVector targetDir(x - m_pathNodes[nodeId].pos.x, y - m_pathNodes[nodeId].pos.y, 0.0f); + CVector targetDir(x - m_pathNodes[nodeId].GetX(), y - m_pathNodes[nodeId].GetY(), 0.0f); targetDir.Normalise(); CVector dir; if(m_pathNodes[nodeId].numLinks == 0) return 0.0f; - int bestNode = m_connections[m_pathNodes[nodeId].firstLink]; + int bestNode = ConnectedNode(m_pathNodes[nodeId].firstLink); #ifdef FIX_BUGS float bestDot = towards ? -2.0f : 2.0f; #else @@ -1206,24 +1239,24 @@ CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, flo #endif for(i = 0; i < m_pathNodes[nodeId].numLinks; i++){ - dir = m_pathNodes[m_connections[m_pathNodes[nodeId].firstLink + i]].pos - m_pathNodes[nodeId].pos; + dir = m_pathNodes[ConnectedNode(m_pathNodes[nodeId].firstLink + i)].GetPosition() - m_pathNodes[nodeId].GetPosition(); dir.z = 0.0f; dir.Normalise(); float angle = DotProduct2D(dir, targetDir); if(towards){ if(angle > bestDot){ bestDot = angle; - bestNode = m_connections[m_pathNodes[nodeId].firstLink + i]; + bestNode = ConnectedNode(m_pathNodes[nodeId].firstLink + i); } }else{ if(angle < bestDot){ bestDot = angle; - bestNode = m_connections[m_pathNodes[nodeId].firstLink + i]; + bestNode = ConnectedNode(m_pathNodes[nodeId].firstLink + i); } } } - dir = m_pathNodes[bestNode].pos - m_pathNodes[nodeId].pos; + dir = m_pathNodes[bestNode].GetPosition() - m_pathNodes[nodeId].GetPosition(); dir.z = 0.0f; dir.Normalise(); return RADTODEG(dir.Heading()); @@ -1243,21 +1276,21 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, node1 = (CGeneral::GetRandomNumber()>>3) % m_numCarPathNodes; if(m_pathNodes[node1].bDisabled && !ignoreDisabled) continue; - dist1 = Distance2D(m_pathNodes[node1].pos, x, y); + dist1 = Distance2D(m_pathNodes[node1].GetPosition(), x, y); if(dist1 < spawnDist + 60.0f){ d1 = dist1 - spawnDist; for(j = 0; j < m_pathNodes[node1].numLinks; j++){ - node2 = m_connections[m_pathNodes[node1].firstLink + j]; + node2 = ConnectedNode(m_pathNodes[node1].firstLink + j); if(m_pathNodes[node2].bDisabled && !ignoreDisabled) continue; - dist2 = Distance2D(m_pathNodes[node2].pos, x, y); + dist2 = Distance2D(m_pathNodes[node2].GetPosition(), x, y); d2 = dist2 - spawnDist; if(d1*d2 < 0.0f){ // nodes are on different sides of spawn distance float f2 = Abs(d1)/(Abs(d1) + Abs(d2)); float f1 = 1.0f - f2; *pPositionBetweenNodes = f2; - CVector pos = m_pathNodes[node1].pos*f1 + m_pathNodes[node2].pos*f2; + CVector pos = m_pathNodes[node1].GetPosition()*f1 + m_pathNodes[node2].GetPosition()*f2; CVector2D dist2d(pos.x - x, pos.y - y); dist2d.Normalise(); // done manually in the game float dot = DotProduct2D(dist2d, CVector2D(dirX, dirY)); @@ -1294,20 +1327,20 @@ CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDi for(i = 0; i < 400; i++){ node1 = m_numCarPathNodes + CGeneral::GetRandomNumber() % m_numPedPathNodes; - if(DistanceSqr2D(m_pathNodes[node1].pos, x, y) < sq(maxDist+30.0f)){ + if(DistanceSqr2D(m_pathNodes[node1].GetPosition(), x, y) < sq(maxDist+30.0f)){ if(m_pathNodes[node1].numLinks == 0) continue; int link = m_pathNodes[node1].firstLink + CGeneral::GetRandomNumber() % m_pathNodes[node1].numLinks; - if(m_connectionFlags[link].bCrossesRoad) + if(ConnectionCrossesRoad(link)) continue; - node2 = m_connections[link]; + node2 = ConnectedNode(link); if(m_pathNodes[node1].bDisabled || m_pathNodes[node2].bDisabled) continue; float f2 = (CGeneral::GetRandomNumber()&0xFF)/256.0f; float f1 = 1.0f - f2; *pPositionBetweenNodes = f2; - CVector pos = m_pathNodes[node1].pos*f1 + m_pathNodes[node2].pos*f2; + CVector pos = m_pathNodes[node1].GetPosition()*f1 + m_pathNodes[node2].GetPosition()*f2; if(Distance2D(pos, x, y) < maxDist+20.0f){ pos.x += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f; pos.y += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f; @@ -1363,11 +1396,11 @@ CPathFind::FindRoadObjectClosestToCoors(CVector coors, uint8 type) break; // FIX: game uses ThePaths here explicitly for(k = 0; k < m_pathNodes[node1].numLinks; k++){ - node2 = m_connections[m_pathNodes[node1].firstLink + k]; - float lineDist = CCollision::DistToLine(&m_pathNodes[node1].pos, &m_pathNodes[node2].pos, &coors); + 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].pos).MagnitudeSqr() < (coors - m_pathNodes[node2].pos).MagnitudeSqr()) + 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]; @@ -1384,7 +1417,7 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode int i; CPathNode *node; - if(lastNode == nil || (node = *lastNode) == nil || (coors - (*lastNode)->pos).MagnitudeSqr() > 7.0f){ + 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); @@ -1392,7 +1425,7 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode for(i = 0; i < 12; i++){ if(obj->m_nodeIndices[type][i] < 0) break; - float dist = (coors - m_pathNodes[obj->m_nodeIndices[type][i]].pos).MagnitudeSqr(); + 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]]; @@ -1404,16 +1437,16 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode *nextNode = 0; float bestDot = -999999.0f; for(i = 0; i < node->numLinks; i++){ - int next = m_connections[node->firstLink+i]; + int next = ConnectedNode(node->firstLink+i); if(!node->bDisabled && m_pathNodes[next].bDisabled) continue; CVector pedCoors = coors; pedCoors.z += 1.0f; - CVector nodeCoors = m_pathNodes[next].pos; + CVector nodeCoors = m_pathNodes[next].GetPosition(); nodeCoors.z += 1.0f; if(!CWorld::GetIsLineOfSightClear(pedCoors, nodeCoors, true, false, false, false, false, false)) continue; - CVector2D nodeDir = m_pathNodes[next].pos - node->pos; + CVector2D nodeDir = m_pathNodes[next].GetPosition() - node->GetPosition(); nodeDir.Normalise(); float dot = DotProduct2D(nodeDir, vCurDir); if(dot >= bestDot){ @@ -1421,7 +1454,7 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode bestDot = dot; // direction is 0, 2, 4, 6 for north, east, south, west - // this could be sone simpler... + // this could be done simpler... if(nodeDir.x < 0.0f){ if(2.0f*Abs(nodeDir.y) < -nodeDir.x) *nextDir = 6; // west @@ -1456,17 +1489,14 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode static CPathNode *apNodesToBeCleared[4995]; void -CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *pNumNodes, int16 maxNumNodes, CVehicle *vehicle, float *pDist, float distLimit, int32 forcedTargetNode) +CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *pNumNodes, int16 maxNumNodes, CVehicle *vehicle, float *pDist, float distLimit, int32 targetNodeId) { int i, j; // Find target - int targetNode; - if(forcedTargetNode < 0) - targetNode = FindNodeClosestToCoors(target, type, distLimit); - else - targetNode = forcedTargetNode; - if(targetNode < 0) { + if(targetNodeId < 0) + targetNodeId = FindNodeClosestToCoors(target, type, distLimit); + if(targetNodeId < 0) { *pNumNodes = 0; if(pDist) *pDist = 100000.0f; return; @@ -1482,7 +1512,7 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta 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[targetNode].group) + if(m_pathNodes[startObj->m_nodeIndices[type][i]].group == m_pathNodes[targetNodeId].group) numPathsToTry++; } }else{ @@ -1498,39 +1528,39 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta if(startNodeId < 0){ // why only check node 0? if(m_pathNodes[startObj->m_nodeIndices[type][0]].group != - m_pathNodes[targetNode].group) { + m_pathNodes[targetNodeId].group) { *pNumNodes = 0; if(pDist) *pDist = 100000.0f; return; } }else{ - if(m_pathNodes[startNodeId].group != m_pathNodes[targetNode].group) { + if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) { *pNumNodes = 0; if(pDist) *pDist = 100000.0f; return; } } - for(i = 0; i < 512; i++) - m_searchNodes[i].next = nil; - AddNodeToList(&m_pathNodes[targetNode], 0); + for(i = 0; i < ARRAY_SIZE(m_searchNodes); i++) + m_searchNodes[i].SetNext(nil); + AddNodeToList(&m_pathNodes[targetNodeId], 0); int numNodesToBeCleared = 0; - apNodesToBeCleared[numNodesToBeCleared++] = &m_pathNodes[targetNode]; + apNodesToBeCleared[numNodesToBeCleared++] = &m_pathNodes[targetNodeId]; // Dijkstra's algorithm // Find distances int numPathsFound = 0; - if(startNodeId < 0 && m_mapObjects[m_pathNodes[targetNode].objectIndex] == startObj) + if(startNodeId < 0 && m_mapObjects[m_pathNodes[targetNodeId].objectIndex] == startObj) numPathsFound++; for(i = 0; numPathsFound < numPathsToTry; i = (i+1) & 0x1FF){ CPathNode *node; - for(node = m_searchNodes[i].next; node; node = node->next){ + for(node = m_searchNodes[i].GetNext(); node; node = node->GetNext()){ if(m_mapObjects[node->objectIndex] == startObj && (startNodeId < 0 || node == &m_pathNodes[startNodeId])) numPathsFound++; for(j = 0; j < node->numLinks; j++){ - int next = m_connections[node->firstLink + j]; + int next = ConnectedNode(node->firstLink + j); int dist = node->distance + m_distances[node->firstLink + j]; if(dist < m_pathNodes[next].distance){ if(m_pathNodes[next].distance != MAX_DIST) @@ -1553,7 +1583,7 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta for(i = 0; i < 12; i++){ if(startObj->m_nodeIndices[type][i] < 0) break; - int dist = (m_pathNodes[startObj->m_nodeIndices[type][i]].pos - start).Magnitude(); + 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]]; @@ -1567,7 +1597,8 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta } if(pDist) *pDist = minDist; - }else{ + }else + { curNode = &m_pathNodes[startNodeId]; *pNumNodes = 0; if(pDist) @@ -1575,9 +1606,9 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta } // Trace back to target and update list of nodes - while(*pNumNodes < maxNumNodes && curNode != &m_pathNodes[targetNode]) + while(*pNumNodes < maxNumNodes && curNode != &m_pathNodes[targetNodeId]) for(i = 0; i < curNode->numLinks; i++){ - int next = m_connections[curNode->firstLink + i]; + int next = ConnectedNode(curNode->firstLink + i); if(curNode->distance - m_distances[curNode->firstLink + i] == m_pathNodes[next].distance){ curNode = &m_pathNodes[next]; nodes[(*pNumNodes)++] = curNode; @@ -1598,6 +1629,7 @@ bool CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start) { float dist; + if(type == PATH_CAR) DoPathSearch(type, start, -1, target, pNodeList, &DummyResult, 32, nil, &dist, 999999.88f, -1); else @@ -1661,10 +1693,10 @@ CPathFind::DisplayPathData(void) // Render car path nodes if(gbShowCarPaths) for(i = 0; i < m_numCarPathNodes; i++){ - if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist)) + if((m_pathNodes[i].GetPosition() - pos).MagnitudeSqr() > SQR(maxDist)) continue; - CVector n1 = m_pathNodes[i].pos; + CVector n1 = m_pathNodes[i].GetPosition(); n1.z += 0.3f; // Draw node itself @@ -1673,8 +1705,8 @@ CPathFind::DisplayPathData(void) 0xFFFFFFFF, 0xFFFFFFFF); for(j = 0; j < m_pathNodes[i].numLinks; j++){ - k = m_connections[m_pathNodes[i].firstLink + j]; - CVector n2 = m_pathNodes[k].pos; + k = ConnectedNode(m_pathNodes[i].firstLink + j); + CVector n2 = m_pathNodes[k].GetPosition(); n2.z += 0.3f; // Draw links to neighbours CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, @@ -1686,12 +1718,12 @@ CPathFind::DisplayPathData(void) // Render car path nodes if(gbShowCarPathsLinks) for(i = 0; i < m_numCarPathLinks; i++){ - CVector2D n1_2d = m_carPathLinks[i].pos; + CVector2D n1_2d = m_carPathLinks[i].GetPosition(); if((n1_2d - pos).MagnitudeSqr() > SQR(maxDist)) continue; int ni = m_carPathLinks[i].pathNodeIndex; - CVector pn1 = m_pathNodes[ni].pos; + CVector pn1 = m_pathNodes[ni].GetPosition(); pn1.z += 0.3f; CVector n1(n1_2d.x, n1_2d.y, pn1.z); n1.z += 0.3f; @@ -1701,7 +1733,7 @@ CPathFind::DisplayPathData(void) n1.x, n1.y, n1.z + 1.0f, 0xFFFFFFFF, 0xFFFFFFFF); CLines::RenderLineWithClipping(n1.x, n1.y, n1.z + 0.5f, - n1.x+m_carPathLinks[i].dir.x, n1.y+m_carPathLinks[i].dir.y, n1.z + 0.5f, + n1.x+m_carPathLinks[i].GetDirX(), n1.y+m_carPathLinks[i].GetDirY(), n1.z + 0.5f, 0xFFFFFFFF, 0xFFFFFFFF); // Draw connection to car path node @@ -1723,9 +1755,9 @@ CPathFind::DisplayPathData(void) for(j = 0; j < m_pathNodes[ni].numLinks; j++){ k = m_carPathConnections[m_pathNodes[ni].firstLink + j]; - CVector2D n2_2d = m_carPathLinks[k].pos; + CVector2D n2_2d = m_carPathLinks[k].GetPosition(); int nk = m_carPathLinks[k].pathNodeIndex; - CVector pn2 = m_pathNodes[nk].pos; + CVector pn2 = m_pathNodes[nk].GetPosition(); pn2.z += 0.3f; CVector n2(n2_2d.x, n2_2d.y, pn2.z); n2.z += 0.3f; @@ -1740,10 +1772,10 @@ CPathFind::DisplayPathData(void) // Render ped path nodes if(gbShowPedPaths) for(i = m_numCarPathNodes; i < m_numPathNodes; i++){ - if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist)) + if((m_pathNodes[i].GetPosition() - pos).MagnitudeSqr() > SQR(maxDist)) continue; - CVector n1 = m_pathNodes[i].pos; + CVector n1 = m_pathNodes[i].GetPosition(); n1.z += 0.3f; // Draw node itself @@ -1752,8 +1784,8 @@ CPathFind::DisplayPathData(void) 0xFFFFFFFF, 0xFFFFFFFF); for(j = 0; j < m_pathNodes[i].numLinks; j++){ - k = m_connections[m_pathNodes[i].firstLink + j]; - CVector n2 = m_pathNodes[k].pos; + k = ConnectedNode(m_pathNodes[i].firstLink + j); + CVector n2 = m_pathNodes[k].GetPosition(); n2.z += 0.3f; // Draw links to neighbours CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, @@ -1763,9 +1795,9 @@ CPathFind::DisplayPathData(void) // Draw connection flags CVector mid = (n1+n2)/2.0f; uint32 col = 0xFF; - if(m_connectionFlags[m_pathNodes[i].firstLink + j].bCrossesRoad) + if(ConnectionCrossesRoad(m_pathNodes[i].firstLink + j)) col += 0x00FF0000; - if(m_connectionFlags[m_pathNodes[i].firstLink + j].bTrafficLight) + if(ConnectionHasTrafficLight(m_pathNodes[i].firstLink + j)) col += 0xFF000000; CLines::RenderLineWithClipping(mid.x, mid.y, mid.z, mid.x, mid.y, mid.z + 1.0f, diff --git a/src/control/PathFind.h b/src/control/PathFind.h index 64c12d5b..bbfdf7b7 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -41,7 +41,8 @@ struct CPedPathNode CPedPathNode* prev; CPedPathNode* next; }; -static_assert(sizeof(CPedPathNode) == 0x10, "CPedPathNode: error"); + +VALIDATE_SIZE(CPedPathNode, 0x10); class CPedPath { public: @@ -69,31 +70,17 @@ struct CPathNode uint8 bBetweenLevels : 1; int8 group; -/* For reference VC: - int16 prevIndex; - int16 nextIndex; - int16 x; - int16 y; - int16 z; - int16 distance; - int16 firstLink; - int8 width; - int8 group; - int8 numLinks : 4; - int8 bDeadEnd : 1; - int8 bTurnedOff : 1; // flag 8 in node info - int8 flagA40 : 1; // flag 20 in node info - int8 flagA80 : 1; // flag 4 in node info - int8 flagB1 : 1; // flag 10 in node info - int8 flagB2 : 1; // flag 2 in node info - int8 flagB4 : 1; - int8 speedLimit : 2; // speed limit - int8 flagB20 : 1; - int8 flagB40 : 1; - int8 flagB80 : 1; - int8 spawnRate : 4; - int8 flagsC : 4; -*/ + + CVector &GetPosition(void) { return pos; } + void SetPosition(const CVector &p) { pos = p; } + float GetX(void) { return pos.x; } + float GetY(void) { return pos.y; } + float GetZ(void) { return pos.z; } + + CPathNode *GetPrev(void) { return prev; } + CPathNode *GetNext(void) { return next; } + void SetPrev(CPathNode *node) { prev = node; } + void SetNext(CPathNode *node) { next = node; } }; union CConnectionFlags @@ -112,11 +99,18 @@ struct CCarPathLink int16 pathNodeIndex; int8 numLeftLanes; int8 numRightLanes; - int8 trafficLightType; + uint8 trafficLightType; uint8 bBridgeLights : 1; // more? + CVector2D &GetPosition(void) { return pos; } + CVector2D &GetDirection(void) { return dir; } + float GetX(void) { return pos.x; } + float GetY(void) { return pos.y; } + float GetDirX(void) { return dir.x; } + float GetDirY(void) { return dir.y; } + float OneWayLaneOffset() { if (numLeftLanes == 0) @@ -127,6 +121,7 @@ struct CCarPathLink } }; +// This is what we're reading from the files, only temporary struct CPathInfoForObject { int16 x; @@ -161,16 +156,6 @@ struct CTempDetachedNode // unused class CPathFind { public: -/* For reference VC: - CPathNode pathNodes[9650]; - CCarPathLink m_carPathLinks[3500]; - CBuilding *m_mapObjects[1250]; - // 0x8000 is cross road flag - // 0x4000 is traffic light flag - uint16 m_connections[20400]; - uint8 m_distances[20400]; - int16 m_carPathConnections[20400]; -*/ CPathNode m_pathNodes[NUM_PATHNODES]; CCarPathLink m_carPathLinks[NUM_CARPATHLINKS]; CTreadable *m_mapObjects[NUM_MAPOBJECTS]; @@ -179,6 +164,7 @@ public: int16 m_distances[NUM_PATHCONNECTIONS]; CConnectionFlags m_connectionFlags[NUM_PATHCONNECTIONS]; int16 m_carPathConnections[NUM_PATHCONNECTIONS]; + int32 m_numPathNodes; int32 m_numCarPathNodes; int32 m_numPedPathNodes; @@ -199,7 +185,7 @@ public: void PreparePathData(void); void CountFloodFillGroups(uint8 type); void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, - float unk, CTempDetachedNode *detachednodes, int unused); + float maxdist, CTempDetachedNode *detachednodes, int32 numDetached); bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); } @@ -229,10 +215,15 @@ public: 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; } void DisplayPathData(void); }; -static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error"); + +VALIDATE_SIZE(CPathFind, 0x49bf4); extern CPathFind ThePaths; diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index 15e9f9f1..136ef7db 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -298,10 +298,10 @@ CPhoneInfo::Initialise(void) for (int i = pool->GetSize() - 1; i >= 0; i--) { CBuilding *building = pool->GetSlot(i); if (building) { - if (building->m_modelIndex == MI_PHONEBOOTH1) { + if (building->GetModelIndex() == MI_PHONEBOOTH1) { CPhone *maxPhone = &m_aPhones[m_nMax]; maxPhone->m_nState = PHONE_STATE_FREE; - maxPhone->m_vecPos = *(building->GetPosition()); + maxPhone->m_vecPos = building->GetPosition(); maxPhone->m_pEntity = building; m_nMax++; } diff --git a/src/control/Phones.h b/src/control/Phones.h index 7fbf403f..14d47ed1 100644 --- a/src/control/Phones.h +++ b/src/control/Phones.h @@ -32,7 +32,7 @@ public: ~CPhone() { } }; -static_assert(sizeof(CPhone) == 0x34, "CPhone: error"); +VALIDATE_SIZE(CPhone, 0x34); class CPhoneInfo { public: diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index d5db4ad8..6b56cd8f 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -84,7 +84,7 @@ CPickup::GiveUsAPickUpObject(int32 handle) if (object == nil) return nil; object->ObjectCreatedBy = MISSION_OBJECT; - object->GetPosition() = m_vecPos; + object->SetPosition(m_vecPos); object->SetOrientation(0.0f, 0.0f, -HALFPI); object->GetMatrix().UpdateRW(); object->UpdateRwFrame(); @@ -229,7 +229,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) if (m_eType == PICKUP_ON_STREET) { m_nTimer = CTimer::GetTimeInMilliseconds() + 30000; } else if (m_eType == PICKUP_ON_STREET_SLOW) { - if (MI_PICKUP_BRIBE == m_pObject->m_modelIndex) + if (MI_PICKUP_BRIBE == m_pObject->GetModelIndex()) m_nTimer = CTimer::GetTimeInMilliseconds() + 300000; else m_nTimer = CTimer::GetTimeInMilliseconds() + 720000; @@ -288,7 +288,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) case PICKUP_NAUTICAL_MINE_INACTIVE: { if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) - m_pObject->GetPosition().z = waterLevel + 0.6f; + m_pObject->GetMatrix().GetPosition().z = waterLevel + 0.6f; m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); @@ -310,7 +310,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) } case PICKUP_NAUTICAL_MINE_ARMED: if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) - m_pObject->GetPosition().z = waterLevel + 0.6f; + m_pObject->GetMatrix().GetPosition().z = waterLevel + 0.6f; m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); @@ -337,7 +337,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) } case PICKUP_FLOATINGPACKAGE: m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep(); - m_pObject->GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep(); + m_pObject->GetMatrix().GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep(); m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); @@ -346,7 +346,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) break; case PICKUP_FLOATINGPACKAGE_FLOATING: if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0)) - m_pObject->GetPosition().z = waterLevel; + m_pObject->GetMatrix().GetPosition().z = waterLevel; m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); @@ -695,7 +695,7 @@ CPickups::DoPickUpEffects(CEntity *entity) assert(colorId >= 0); - CVector &pos = entity->GetPosition(); + const CVector &pos = entity->GetPosition(); float colorModifier = ((CGeneral::GetRandomNumber() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f; CShadows::StoreStaticShadow( @@ -749,7 +749,7 @@ CPickups::DoPickUpEffects(CEntity *entity) void CPickups::DoMineEffects(CEntity *entity) { - CVector &pos = entity->GetPosition(); + const CVector &pos = entity->GetPosition(); float dist = (TheCamera.GetPosition() - pos).Magnitude(); const float MAXDIST = 20.0f; @@ -771,7 +771,7 @@ CPickups::DoMineEffects(CEntity *entity) void CPickups::DoMoneyEffects(CEntity *entity) { - CVector &pos = entity->GetPosition(); + const CVector &pos = entity->GetPosition(); float dist = (TheCamera.GetPosition() - pos).Magnitude(); const float MAXDIST = 20.0f; @@ -793,7 +793,7 @@ CPickups::DoMoneyEffects(CEntity *entity) void CPickups::DoCollectableEffects(CEntity *entity) { - CVector &pos = entity->GetPosition(); + const CVector &pos = entity->GetPosition(); float dist = (TheCamera.GetPosition() - pos).Magnitude(); const float MAXDIST = 14.0f; @@ -1145,7 +1145,7 @@ CPacManPickups::GeneratePMPickUps(CVector pos, float scrambleMult, int16 count, CObject *obj = new CObject(MI_BULLION, true); if (obj != nil) { obj->ObjectCreatedBy = MISSION_OBJECT; - obj->GetPosition() = aPMPickUps[i].m_vecPosn; + obj->SetPosition(aPMPickUps[i].m_vecPosn); obj->SetOrientation(0.0f, 0.0f, -HALFPI); obj->GetMatrix().UpdateRW(); obj->UpdateRwFrame(); @@ -1296,7 +1296,7 @@ CPacManPickups::GeneratePMPickUpsForRace(int32 race) if (obj != nil) { obj->ObjectCreatedBy = MISSION_OBJECT; - obj->GetPosition() = aPMPickUps[i].m_vecPosn; + obj->SetPosition(aPMPickUps[i].m_vecPosn); obj->SetOrientation(0.0f, 0.0f, -HALFPI); obj->GetMatrix().UpdateRW(); obj->UpdateRwFrame(); diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 11da5f54..b05f5db7 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -47,7 +47,7 @@ private: void Remove(); }; -static_assert(sizeof(CPickup) == 0x1C, "CPickup: error"); +VALIDATE_SIZE(CPickup, 0x1C); struct tPickupMessage { diff --git a/src/control/Record.cpp b/src/control/Record.cpp index b9e8f8da..d086543f 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -279,14 +279,14 @@ void CRecordDataForChase::SaveOrRetrieveCarPositions(void) } if (CPad::GetPad(0)->GetLeftShockJustDown() && CPad::GetPad(0)->GetRightShockJustDown()) { if (!CPad::GetPad(0)->GetRightShockJustDown()) { - pChaseCars[CurrentCar]->GetPosition() = NewCoorsForRecordedCars[PositionChanges].pos; + 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]->m_status = STATUS_PLAYER; + pChaseCars[CurrentCar]->SetStatus(STATUS_PLAYER); } } break; @@ -311,12 +311,12 @@ void CRecordDataForChase::SaveOrRetrieveCarPositions(void) 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]->GetPosition() += (tmp.GetPosition() - pChaseCars[i]->GetPosition()) * 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]->GetPosition().z += 0.2f; + pChaseCars[i]->GetMatrix().GetPosition().z += 0.2f; } pChaseCars[i]->GetMatrix().UpdateRW(); pChaseCars[i]->UpdateRwFrame(); @@ -407,8 +407,8 @@ void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomo if (!CStreaming::HasModelLoaded(mi)) return; CAutomobile* pCar = new CAutomobile(mi, MISSION_VEHICLE); - pCar->GetPosition() = pos; - pCar->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER; + pCar->SetPosition(pos); + pCar->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER); pCar->GetMatrix().SetRotateZOnly(DEGTORAD(angle)); pCar->pDriver = nil; pCar->m_currentColour1 = colour1; @@ -517,7 +517,7 @@ CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32 i) { CVehicle* pVehicle = pChaseCars[i]; pChaseCars[i] = nil; - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); return pVehicle; } diff --git a/src/control/Remote.cpp b/src/control/Remote.cpp index 9c749bd9..904e9023 100644 --- a/src/control/Remote.cpp +++ b/src/control/Remote.cpp @@ -18,8 +18,8 @@ CRemote::GivePlayerRemoteControlledCar(float x, float y, float z, float rot, uin z = car->GetDistanceFromCentreOfMassToBaseOfModel() + CWorld::FindGroundZFor3DCoord(x, y, z + 2.0f, &found); car->GetMatrix().SetRotateZOnly(rot); - car->GetPosition() = CVector(x, y, z); - car->m_status = STATUS_PLAYER_REMOTE; + car->SetPosition(x, y, z); + car->SetStatus(STATUS_PLAYER_REMOTE); car->bIsLocked = true; CCarCtrl::JoinCarWithRoadSystem(car); @@ -31,7 +31,7 @@ CRemote::GivePlayerRemoteControlledCar(float x, float y, float z, float rot, uin car->bEngineOn = true; CWorld::Add(car); if (FindPlayerVehicle() != nil) - FindPlayerVehicle()->m_status = STATUS_PLAYER_DISABLED; + FindPlayerVehicle()->SetStatus(STATUS_PLAYER_DISABLED); CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = car; CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->RegisterReference((CEntity**)&CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle); diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index da350660..707f1d87 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -850,7 +850,7 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo else{ new_v = new(vp->index << 8) CAutomobile(mi, 2); } - new_v->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER; + new_v->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER); vp->matrix.DecompressIntoFullMatrix(new_v->GetMatrix()); new_v->m_currentColour1 = vp->primary_color; new_v->m_currentColour2 = vp->secondary_color; @@ -870,7 +870,7 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo } else { CPed* new_p = new(ph->index << 8) CCivilianPed((ePedType)ph->pedtype, ph->mi); - new_p->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER; + new_p->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER); new_p->GetMatrix().SetUnity(); CWorld::Add(new_p); } @@ -900,10 +900,10 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo TheCamera.GetMatrix().GetPosition() *= split; TheCamera.GetMatrix() += CMatrix(interpolation) * pg->camera_pos; RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); - pm->pos = *(RwV3d*)TheCamera.GetPosition(); - pm->at = *(RwV3d*)TheCamera.GetForward(); - pm->up = *(RwV3d*)TheCamera.GetUp(); - pm->right = *(RwV3d*)TheCamera.GetRight(); + pm->pos = TheCamera.GetPosition(); + pm->at = TheCamera.GetForward(); + pm->up = TheCamera.GetUp(); + pm->right = TheCamera.GetRight(); CameraFocusX = split * CameraFocusX + interpolation * pg->player_pos.x; CameraFocusY = split * CameraFocusY + interpolation * pg->player_pos.y; CameraFocusZ = split * CameraFocusZ + interpolation * pg->player_pos.z; @@ -987,7 +987,7 @@ void CReplay::FinishPlayback(void) Mode = MODE_RECORD; if (bDoLoadSceneWhenDone){ CVector v_ls(LoadSceneX, LoadSceneY, LoadSceneZ); - CGame::currLevel = CTheZones::GetLevelFromPosition(v_ls); + CGame::currLevel = CTheZones::GetLevelFromPosition(&v_ls); CCollision::SortOutCollisionAfterLoad(); CStreaming::LoadScene(v_ls); } @@ -1020,7 +1020,7 @@ void CReplay::ProcessReplayCamera(void) switch (CameraMode) { case REPLAYCAMMODE_TOPDOWN: { - TheCamera.GetPosition() = CVector(CameraFocusX, CameraFocusY, CameraFocusZ + 15.0f); + TheCamera.SetPosition(CameraFocusX, CameraFocusY, CameraFocusZ + 15.0f); TheCamera.GetForward() = CVector(0.0f, 0.0f, -1.0f); TheCamera.GetUp() = CVector(0.0f, 1.0f, 0.0f); TheCamera.GetRight() = CVector(1.0f, 0.0f, 0.0f); @@ -1101,7 +1101,7 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca LoadSceneZ = TheCamera.GetPosition().z; CVector ff_coord; FindFirstFocusCoordinate(&ff_coord); - CGame::currLevel = CTheZones::GetLevelFromPosition(ff_coord); + CGame::currLevel = CTheZones::GetLevelFromPosition(&ff_coord); CCollision::SortOutCollisionAfterLoad(); CStreaming::LoadScene(ff_coord); } @@ -1539,7 +1539,7 @@ void CReplay::ProcessLookAroundCam(void) TheCamera.GetForward() = forward; TheCamera.GetUp() = up; TheCamera.GetRight() = right; - TheCamera.GetPosition() = camera_pt; + TheCamera.SetPosition(camera_pt); RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); pm->pos = *(RwV3d*)&TheCamera.GetPosition(); pm->at = *(RwV3d*)&TheCamera.GetForward(); diff --git a/src/control/Replay.h b/src/control/Replay.h index bf70a28a..66bee3bf 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -108,7 +108,8 @@ class CReplay CMatrix camera_pos; CVector player_pos; }; - static_assert(sizeof(tGeneralPacket) == 88, "tGeneralPacket: error"); + + VALIDATE_SIZE(tGeneralPacket, 88); struct tClockPacket { @@ -118,7 +119,7 @@ class CReplay private: uint8 __align; }; - static_assert(sizeof(tClockPacket) == 4, "tClockPacket: error"); + VALIDATE_SIZE(tClockPacket, 4); struct tWeatherPacket { @@ -127,14 +128,14 @@ class CReplay uint8 new_weather; float interpolation; }; - static_assert(sizeof(tWeatherPacket) == 8, "tWeatherPacket: error"); + VALIDATE_SIZE(tWeatherPacket, 8); struct tTimerPacket { uint8 type; uint32 timer; }; - static_assert(sizeof(tTimerPacket) == 8, "tTimerPacket: error"); + VALIDATE_SIZE(tTimerPacket, 8); struct tPedHeaderPacket { @@ -145,7 +146,7 @@ class CReplay private: uint8 __align[3]; }; - static_assert(sizeof(tPedHeaderPacket) == 8, "tPedHeaderPacket: error"); + VALIDATE_SIZE(tPedHeaderPacket, 8); struct tBulletTracePacket { @@ -156,7 +157,7 @@ class CReplay CVector inf; CVector sup; }; - static_assert(sizeof(tBulletTracePacket) == 28, "tBulletTracePacket: error"); + VALIDATE_SIZE(tBulletTracePacket, 28); struct tEndOfFramePacket { @@ -164,7 +165,7 @@ class CReplay private: uint8 __align[3]; }; - static_assert(sizeof(tEndOfFramePacket) == 4, "tEndOfFramePacket: error"); + VALIDATE_SIZE(tEndOfFramePacket, 4); struct tPedUpdatePacket { @@ -177,7 +178,7 @@ class CReplay int8 assoc_group_id; uint8 weapon_model; }; - static_assert(sizeof(tPedUpdatePacket) == 40, "tPedUpdatePacket: error"); + VALIDATE_SIZE(tPedUpdatePacket, 40); struct tVehicleUpdatePacket { @@ -202,7 +203,7 @@ class CReplay uint8 primary_color; uint8 secondary_color; }; - static_assert(sizeof(tVehicleUpdatePacket) == 48, "tVehicleUpdatePacket: error"); + VALIDATE_SIZE(tVehicleUpdatePacket, 48); private: static uint8 Mode; diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp index 2a31f8f1..5a322cdb 100644 --- a/src/control/Restart.cpp +++ b/src/control/Restart.cpp @@ -108,7 +108,7 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f // if we still didn't find anything, find closest path node if (closestPoint == NUM_RESTART_POINTS) { - *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; + *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].GetPosition(); *outHeading = 0.0f; printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z); } else { @@ -156,7 +156,7 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo // if we still didn't find anything, find closest path node if (closestPoint == NUM_RESTART_POINTS) { printf("Couldn't find a police restart zone near the player\n"); - *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; + *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].GetPosition(); *outHeading = 0.0f; } else { *outPos = PoliceRestartPoints[closestPoint]; diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 7fb0c211..572f8134 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -15,6 +15,8 @@ #include "CarCtrl.h" #include "General.h" +#define ROADBLOCKDIST (80.0f) + int16 CRoadBlocks::NumRoadBlocks; int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS]; bool CRoadBlocks::InOrOut[NUMROADBLOCKS]; @@ -22,12 +24,13 @@ bool CRoadBlocks::InOrOut[NUMROADBLOCKS]; void CRoadBlocks::Init(void) { + int i; NumRoadBlocks = 0; - for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) { - if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) { + for (i = 0; i < ThePaths.m_numMapObjects; i++) { + if (ThePaths.m_objectFlags[i] & UseInRoadBlock) { if (NumRoadBlocks < NUMROADBLOCKS) { InOrOut[NumRoadBlocks] = true; - RoadBlockObjects[NumRoadBlocks] = objId; + RoadBlockObjects[NumRoadBlocks] = i; NumRoadBlocks++; } else { #ifndef MASTER @@ -38,7 +41,6 @@ CRoadBlocks::Init(void) } } } - } void @@ -77,15 +79,15 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType if (copType == COP_STREET) pCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45); CPedPlacement::FindZCoorForPed(&posForZ); - pCopPed->m_matrix.GetPosition() = posForZ; - CVector vecSavedPos = pCopPed->m_matrix.GetPosition(); + pCopPed->SetPosition(posForZ); + CVector vecSavedPos = pCopPed->GetPosition(); pCopPed->m_matrix.SetRotate(0.0f, 0.0f, -HALFPI); pCopPed->m_matrix.GetPosition() += vecSavedPos; pCopPed->m_bIsDisabledCop = true; pCopPed->SetIdle(); pCopPed->bKindaStayInSamePlace = true; pCopPed->bNotAllowedToDuck = false; - pCopPed->m_wRoadblockNode = roadBlockNode; + pCopPed->m_nRoadblockNode = roadBlockNode; pCopPed->bCrouchWhenShooting = roadBlockType != 2; if (pEntityToAttack) { pCopPed->m_pPointGunAt = pEntityToAttack; @@ -107,17 +109,14 @@ CRoadBlocks::GenerateRoadBlocks(void) uint32 frame = CTimer::GetFrameCounter() & 0xF; int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16; const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16; - int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks; - if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks) - numRoadBlocks = maxRoadBlocks; - for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) { - CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]]; + for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) { + CTreadable *mapObject = ThePaths.m_mapObjects[RoadBlockObjects[nRoadblockNode]]; CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition(); - if (vecDistance.x > -80.0f && vecDistance.x < 80.0f && - vecDistance.y > -80.0f && vecDistance.y < 80.0f && - vecDistance.Magnitude() < 80.0f) { - if (!CRoadBlocks::InOrOut[nRoadblockNode]) { - CRoadBlocks::InOrOut[nRoadblockNode] = true; + if (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) { CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; @@ -134,8 +133,8 @@ CRoadBlocks::GenerateRoadBlocks(void) float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f; int16 radius = (int16)(fMapObjectRadius / fModelRadius); if (radius > 0 && radius < 6) { - CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->m_matrix.GetPosition(); - float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->m_matrix.GetUp()); + CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->GetPosition(); + float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->GetForward()); float fOffset = 0.5f * fModelRadius * (float)(radius - 1); for (int16 i = 0; i < radius; i++) { uint8 nRoadblockType = fDotProduct < 0.0f; @@ -146,7 +145,7 @@ CRoadBlocks::GenerateRoadBlocks(void) nRoadblockType = !nRoadblockType; offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); } - if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) + if (ThePaths.m_objectFlags[RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f); else offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); @@ -156,7 +155,7 @@ CRoadBlocks::GenerateRoadBlocks(void) CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false); if (!colliding) { CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE); - pVehicle->m_status = STATUS_ABANDONED; + pVehicle->SetStatus(STATUS_ABANDONED); // pVehicle->GetHeightAboveRoad(); // called but return value is ignored? vehicleMatrix.GetPosition().z += fModelRadius - 0.6f; pVehicle->m_matrix = vehicleMatrix; @@ -175,7 +174,7 @@ CRoadBlocks::GenerateRoadBlocks(void) pVehicle->bExtendedRange = true; if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1) pVehicle->m_bSirenOrAlarm = true; - if (pVehicle->m_matrix.GetForward().z > 0.94f) { + if (pVehicle->GetForward().z > 0.94f) { CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0); CWorld::Add(pVehicle); pVehicle->bCreateRoadBlockPeds = true; @@ -191,7 +190,7 @@ CRoadBlocks::GenerateRoadBlocks(void) } } } else { - CRoadBlocks::InOrOut[nRoadblockNode] = false; + InOrOut[nRoadblockNode] = false; } } } diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp index 7f914a76..6aa64a3c 100644 --- a/src/control/SceneEdit.cpp +++ b/src/control/SceneEdit.cpp @@ -68,7 +68,9 @@ static const char* pCommandStrings[] = { "Save Movie", "Load Movie", "Play Movie", "END" }; +#ifdef CHECK_STRUCT_SIZES static_assert(ARRAY_SIZE(pCommandStrings) == CSceneEdit::MOVIE_TOTAL_COMMANDS, "Scene edit: not all commands have names"); +#endif static int32 NextValidModelId(int32 mi, int32 step) { @@ -76,7 +78,7 @@ static int32 NextValidModelId(int32 mi, int32 step) int32 i = mi; while (result == -1) { i += step; - if (i < 0 || i > 5500) { + if (i < 0 || i > MODELINFOSIZE) { step = -step; continue; } @@ -84,12 +86,11 @@ static int32 NextValidModelId(int32 mi, int32 step) CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo; if (!pInfo) continue; - if (pInfo->m_type == MITYPE_PED + if (pInfo->GetModelType() == MITYPE_PED #ifdef FIX_BUGS && !(i >= MI_SPECIAL01 && i <= MI_SPECIAL04) #endif - || - pInfo->m_type == MITYPE_VEHICLE && + || pInfo->GetModelType() == MITYPE_VEHICLE && #ifdef FIX_BUGS (pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR || pVehicleInfo->m_vehicleType == VEHICLE_TYPE_BOAT)) #else // && and || priority failure it seems, also crashes on special models @@ -349,7 +350,7 @@ void CSceneEdit::ProcessCommand(void) } CPed* pPed = new CCivilianPed(PEDTYPE_SPECIAL, m_nPedmodelId); pPed->CharCreatedBy = MISSION_CHAR; - pPed->GetPosition() = m_vecCurrentPosition; + pPed->SetPosition(m_vecCurrentPosition); pPed->SetOrientation(0.0f, 0.0f, 0.0f); CWorld::Add(pPed); pPed->bUsesCollision = false; @@ -363,7 +364,7 @@ void CSceneEdit::ProcessCommand(void) } } else { - pActors[m_nActor]->GetPosition() = m_vecCurrentPosition; + pActors[m_nActor]->SetPosition(m_vecCurrentPosition); pActors[m_nActor]->SetOrientation(0.0f, 0.0f, 0.0f); int32 mi = m_nPedmodelId; if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) @@ -405,7 +406,7 @@ void CSceneEdit::ProcessCommand(void) SelectActor(); if (m_bCommandActive) break; - pActors[m_nActor]->GetPosition() = m_vecCurrentPosition; + pActors[m_nActor]->SetPosition(m_vecCurrentPosition); if (CPad::GetPad(1)->GetTriangleJustDown()) { m_bCommandActive = false; #ifndef FIX_BUGS // why? it crashes, also makes no sense @@ -450,8 +451,8 @@ void CSceneEdit::ProcessCommand(void) break; } CVehicle* pVehicle = new CAutomobile(m_nVehiclemodelId, MISSION_VEHICLE); - pVehicle->m_status = STATUS_PHYSICS; - pVehicle->GetPosition() = m_vecCurrentPosition; + pVehicle->SetStatus(STATUS_PHYSICS); + pVehicle->SetPosition(m_vecCurrentPosition); pVehicle->SetOrientation(0.0f, 0.0f, 0.0f); CWorld::Add(pVehicle); pVehicle->bUsesCollision = false; @@ -465,7 +466,7 @@ void CSceneEdit::ProcessCommand(void) } } else { - pVehicles[m_nVehicle]->GetPosition() = m_vecCurrentPosition; + pVehicles[m_nVehicle]->SetPosition(m_vecCurrentPosition); pVehicles[m_nVehicle]->SetOrientation(0.0f, 0.0f, 0.0f); int32 mi = m_nVehiclemodelId; if (CPad::GetPad(1)->GetLeftShoulder1JustDown()) @@ -507,7 +508,7 @@ void CSceneEdit::ProcessCommand(void) SelectVehicle(); if (m_bCommandActive) break; - pVehicles[m_nVehicle]->GetPosition() = m_vecCurrentPosition; + pVehicles[m_nVehicle]->SetPosition(m_vecCurrentPosition); if (CPad::GetPad(1)->GetTriangleJustDown()) { m_bCommandActive = false; #ifndef FIX_BUGS // again, why? works wrong @@ -567,7 +568,7 @@ void CSceneEdit::ProcessCommand(void) pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT; else pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS; - pActors[m_nActor]->m_pMyVehicle->m_status = STATUS_PHYSICS; + pActors[m_nActor]->m_pMyVehicle->SetStatus(STATUS_PHYSICS); pActors[m_nActor]->m_pMyVehicle->bEngineOn = true; pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = Max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed); pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); @@ -785,7 +786,7 @@ void CSceneEdit::PlayBack(void) CPed* pPed = new CCivilianPed(PEDTYPE_SPECIAL, m_nPedmodelId); pPed->CharCreatedBy = MISSION_CHAR; CWorld::Add(pPed); - pPed->GetPosition() = m_vecCurrentPosition; + pPed->SetPosition(m_vecCurrentPosition); pPed->SetOrientation(0.0f, 0.0f, 0.0f); for (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) { if (pActors[i] == nil) { @@ -810,8 +811,8 @@ void CSceneEdit::PlayBack(void) break; } CVehicle* pVehicle = new CAutomobile(m_nVehiclemodelId, MISSION_VEHICLE); - pVehicle->m_status = STATUS_PHYSICS; - pVehicle->GetPosition() = m_vecCurrentPosition; + pVehicle->SetStatus(STATUS_PHYSICS); + pVehicle->SetPosition(m_vecCurrentPosition); pVehicle->SetOrientation(0.0f, 0.0f, 0.0f); CWorld::Add(pVehicle); for (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) { @@ -845,7 +846,7 @@ void CSceneEdit::PlayBack(void) pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT; else pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS; - pActors[m_nActor]->m_pMyVehicle->m_status = STATUS_PHYSICS; + pActors[m_nActor]->m_pMyVehicle->SetStatus(STATUS_PHYSICS); pActors[m_nActor]->m_pMyVehicle->bEngineOn = true; pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = Max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed); pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 1f65ce6e..df3a489a 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -128,6 +128,14 @@ uint16 CTheScripts::CommandsExecuted; uint16 CTheScripts::ScriptsUpdated; int32 ScriptParams[32]; + +const uint32 CRunningScript::nSaveStructSize = +#ifdef COMPATIBLE_SAVES + 136; +#else + sizeof(CRunningScript); +#endif + CMissionCleanup::CMissionCleanup() { Init(); @@ -1293,7 +1301,7 @@ int8 CRunningScript::ProcessCommands0To99(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z += CWorld::Players[index].m_pPed->GetDistanceFromCentreOfMassToBaseOfModel(); - CWorld::Players[index].m_pPed->GetPosition() = pos; + CWorld::Players[index].m_pPed->SetPosition(pos); CTheScripts::ClearSpaceForMissionEntity(pos, CWorld::Players[index].m_pPed); CPlayerPed::ReactivatePlayerPed(index); ScriptParams[0] = index; @@ -1717,11 +1725,11 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z += 1.0f; - ped->GetPosition() = pos; + ped->SetPosition(pos); ped->SetOrientation(0.0f, 0.0f, 0.0f); CTheScripts::ClearSpaceForMissionEntity(pos, ped); CWorld::Add(ped); - ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(pos); + ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); CPopulation::ms_nTotalMissionPeds++; ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped); StoreParameters(&m_nIp, 1); @@ -1737,7 +1745,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) if (ped->InVehicle()) { if (ped->m_pMyVehicle->pDriver == ped) { ped->m_pMyVehicle->RemoveDriver(); - ped->m_pMyVehicle->m_status = STATUS_ABANDONED; + ped->m_pMyVehicle->SetStatus(STATUS_ABANDONED); if (ped->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) ped->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED; if (ped->m_nPedType == PEDTYPE_COP && ped->m_pMyVehicle->IsLawEnforcementVehicle()) @@ -1931,9 +1939,9 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z += boat->GetDistanceFromCentreOfMassToBaseOfModel(); - boat->GetPosition() = pos; + boat->SetPosition(pos); CTheScripts::ClearSpaceForMissionEntity(pos, boat); - boat->m_status = STATUS_ABANDONED; + boat->SetStatus(STATUS_ABANDONED); boat->bIsLocked = true; boat->AutoPilot.m_nCarMission = MISSION_NONE; boat->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */ @@ -1949,9 +1957,9 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel(); - car->GetPosition() = pos; + car->SetPosition(pos); CTheScripts::ClearSpaceForMissionEntity(pos, car); - car->m_status = STATUS_ABANDONED; + car->SetStatus(STATUS_ABANDONED); car->bIsLocked = true; CCarCtrl::JoinCarWithRoadSystem(car); car->AutoPilot.m_nCarMission = MISSION_NONE; @@ -1960,7 +1968,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f; car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0; car->bEngineOn = false; - car->m_nZoneLevel = CTheZones::GetLevelFromPosition(pos); + car->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); car->bHasBeenOwnedByPlayer = true; CWorld::Add(car); handle = CPools::GetVehiclePool()->GetIndex(car); @@ -1997,7 +2005,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) car->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT; else car->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS; - car->m_status = STATUS_PHYSICS; + car->SetStatus(STATUS_PHYSICS); car->bEngineOn = true; car->AutoPilot.m_nCruiseSpeed = Max(car->AutoPilot.m_nCruiseSpeed, 6); car->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); @@ -2087,7 +2095,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) { CollectParameters(&m_nIp, 1); CVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(car && car->m_status != STATUS_WRECKED && (car->IsBoat() || !car->bIsInWater)); + UpdateCompareFlag(car && car->GetStatus() != STATUS_WRECKED && (car->IsBoat() || !car->bIsInWater)); return 0; } case COMMAND_SET_CAR_CRUISE_SPEED: @@ -2523,7 +2531,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z += pObj->GetDistanceFromCentreOfMassToBaseOfModel(); - pObj->GetPosition() = pos; + pObj->SetPosition(pos); pObj->SetOrientation(0.0f, 0.0f, 0.0f); pObj->GetMatrix().UpdateRW(); pObj->UpdateRwFrame(); @@ -2626,7 +2634,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) { CollectParameters(&m_nIp, 1); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); - UpdateCompareFlag(!pVehicle || pVehicle->m_status == STATUS_WRECKED || !pVehicle->IsBoat() && pVehicle->bIsInWater); + UpdateCompareFlag(!pVehicle || pVehicle->GetStatus() == STATUS_WRECKED || !pVehicle->IsBoat() && pVehicle->bIsInWater); return 0; } case COMMAND_SET_CHAR_THREAT_SEARCH: @@ -2666,7 +2674,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) m_nIp += KEY_LENGTH_IN_SCRIPT; /* why only if zone != 1? */ CVector pos = pPlayer->GetPos(); CZone* pZone = CTheZones::GetZone(zoneToCheck); - UpdateCompareFlag(CTheZones::PointLiesWithinZone(pos, pZone)); + UpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, pZone)); return 0; } case COMMAND_IS_PLAYER_PRESSING_HORN: @@ -2743,7 +2751,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pPed->CharCreatedBy = MISSION_CHAR; pPed->bRespondsToThreats = false; pPed->bAllowMedicsToReviveMe = false; - pPed->GetPosition() = pVehicle->GetPosition(); + pPed->SetPosition(pVehicle->GetPosition()); pPed->SetOrientation(0.0f, 0.0f, 0.0f); pPed->SetPedState(PED_DRIVING); CPopulation::ms_nTotalMissionPeds++; @@ -2753,7 +2761,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pPed->m_pMyVehicle = pVehicle; pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); pPed->bInVehicle = true; - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); if (!pVehicle->IsBoat()) pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; pVehicle->bEngineOn = true; @@ -2765,7 +2773,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) #endif pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f); pPed->StopNonPartialAnims(); - pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(pPed->GetPosition()); + pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); CWorld::Add(pPed); ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); StoreParameters(&m_nIp, 1); @@ -2786,7 +2794,7 @@ int8 CRunningScript::ProcessCommands200To299(int32 command) pPlayer->m_pPed->bRenderPedInCar = true; if (pPlayer->m_pPed->m_pMyVehicle->pDriver == pPlayer->m_pPed){ pPlayer->m_pPed->m_pMyVehicle->RemoveDriver(); - pPlayer->m_pPed->m_pMyVehicle->m_status = STATUS_ABANDONED; + pPlayer->m_pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); pPlayer->m_pPed->m_pMyVehicle->bEngineOn = false; pPlayer->m_pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; }else{ @@ -2878,7 +2886,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) float y1 = *(float*)&ScriptParams[2]; float x2 = *(float*)&ScriptParams[3]; float y2 = *(float*)&ScriptParams[4]; - UpdateCompareFlag(pVehicle->m_status == STATUS_WRECKED && + UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && pVehicle->IsWithinArea(x1, y1, x2, y2)); if (!ScriptParams[5]) return 0; @@ -2898,7 +2906,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) float x2 = *(float*)&ScriptParams[4]; float y2 = *(float*)&ScriptParams[5]; float z2 = *(float*)&ScriptParams[6]; - UpdateCompareFlag(pVehicle->m_status == STATUS_WRECKED && + UpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED && pVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2)); if (!ScriptParams[7]) return 0; @@ -3018,7 +3026,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command) 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::GetZone(zone))); return 0; } case COMMAND_SET_CAR_DENSITY: @@ -3935,7 +3943,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->CharCreatedBy = MISSION_CHAR; pPed->bRespondsToThreats = false; pPed->bAllowMedicsToReviveMe = false; - pPed->GetPosition() = pVehicle->GetPosition(); + pPed->SetPosition(pVehicle->GetPosition()); pPed->SetOrientation(0.0f, 0.0f, 0.0f); pPed->SetPedState(PED_DRIVING); CPopulation::ms_nTotalMissionPeds++; @@ -3947,7 +3955,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) pPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle); pPed->bInVehicle = true; pPed->SetPedState(PED_DRIVING); - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); pPed->bUsesCollision = false; #ifdef FIX_BUGS AnimationId anim = pVehicle->GetDriverAnim(); @@ -3956,7 +3964,7 @@ int8 CRunningScript::ProcessCommands400To499(int32 command) #endif pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f); pPed->StopNonPartialAnims(); - pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(pPed->GetPosition()); + pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); CWorld::Add(pPed); ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); StoreParameters(&m_nIp, 1); @@ -5153,7 +5161,7 @@ int8 CRunningScript::ProcessCommands500To599(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); CRestart::OverrideNextRestart(pos, *(float*)&ScriptParams[3]); - if (CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING) //TODO: enum + if (CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING) printf("RESTART_CRITICAL_MISSION - Player state is not PLAYING\n"); CWorld::Players[CWorld::PlayerInFocus].PlayerFailedCriticalMission(); return 0; @@ -5250,7 +5258,11 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) return 0; } case COMMAND_GET_CONTROLLER_MODE: +#if defined(GTA_PC) && !defined(DETECT_PAD_INPUT_SWITCH) ScriptParams[0] = 0; +#else + ScriptParams[0] = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0; +#endif StoreParameters(&m_nIp, 1); return 0; case COMMAND_SET_CAN_RESPRAY_CAR: @@ -5307,7 +5319,7 @@ int8 CRunningScript::ProcessCommands600To699(int32 command) CVector pos = *(CVector*)&ScriptParams[1]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); - pObj->GetPosition() = pos; + pObj->SetPosition(pos); pObj->SetOrientation(0.0f, 0.0f, 0.0f); pObj->GetMatrix().UpdateRW(); pObj->UpdateRwFrame(); @@ -5555,7 +5567,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)]; - *(CVector*)&ScriptParams[0] = pNode->pos; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); StoreParameters(&m_nIp, 3); return 0; } @@ -5566,7 +5578,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)]; - *(CVector*)&ScriptParams[0] = pNode->pos; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); StoreParameters(&m_nIp, 3); return 0; } @@ -5583,7 +5595,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE; else pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE; - pVehicle->m_status = STATUS_PHYSICS; + pVehicle->SetStatus(STATUS_PHYSICS); pVehicle->bEngineOn = true; pVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed); pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); @@ -5699,7 +5711,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &pos.z, false); pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS; pBoat->AutoPilot.m_vecDestinationCoors = pos; - pBoat->m_status = STATUS_PHYSICS; + pBoat->SetStatus(STATUS_PHYSICS); pBoat->AutoPilot.m_nCruiseSpeed = Max(6, pBoat->AutoPilot.m_nCruiseSpeed); pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); return 0; @@ -5712,7 +5724,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT); CBoat* pBoat = (CBoat*)pVehicle; pBoat->AutoPilot.m_nCarMission = MISSION_NONE; - pBoat->m_status = STATUS_PHYSICS; + pBoat->SetStatus(STATUS_PHYSICS); pBoat->bEngineOn = false; pBoat->AutoPilot.m_nCruiseSpeed = 0; return 0; @@ -5868,7 +5880,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) continue; if (pPed->bIsLeader || pPed->m_leader) continue; - if (!CTheZones::PointLiesWithinZone(pPed->GetPosition(), pZone)) + if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone)) continue; if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) continue; @@ -6524,7 +6536,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) continue; if (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE) continue; - if (!CTheZones::PointLiesWithinZone(pVehicle->GetPosition(), pZone)) + if (!CTheZones::PointLiesWithinZone(&pVehicle->GetPosition(), pZone)) continue; handle = CPools::GetVehiclePool()->GetIndex(pVehicle); pVehicle->VehicleCreatedBy = MISSION_VEHICLE; @@ -6911,7 +6923,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) if (pPed->m_pMyVehicle){ if (pPed == pPed->m_pMyVehicle->pDriver){ pPed->m_pMyVehicle->RemoveDriver(); - pPed->m_pMyVehicle->m_status = STATUS_ABANDONED; + pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); if (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY) pPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED; if (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle()) @@ -7108,7 +7120,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) pPed->bRenderPedInCar = true; if (pPed->m_pMyVehicle->pDriver == pPed){ pPed->m_pMyVehicle->RemoveDriver(); - pPed->m_pMyVehicle->m_status = STATUS_ABANDONED; + pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED); pPed->m_pMyVehicle->bEngineOn = false; pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; }else{ @@ -7331,11 +7343,11 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z += 1.0f; - ped->GetPosition() = pos; + ped->SetPosition(pos); ped->SetOrientation(0.0f, 0.0f, 0.0f); CTheScripts::ClearSpaceForMissionEntity(pos, ped); CWorld::Add(ped); - ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(pos); + ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); CPopulation::ms_nTotalMissionPeds++; ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped); StoreParameters(&m_nIp, 1); @@ -7779,7 +7791,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CollectParameters(&m_nIp, 2); CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); - pVehicle->m_status = ScriptParams[1]; + pVehicle->SetStatus((eEntityStatus)ScriptParams[1]); return 0; } case COMMAND_IS_CHAR_MALE: @@ -8062,7 +8074,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) continue; // desperatly want to believe this was inlined :| CBaseModelInfo* pInfo = CModelInfo::GetModelInfo(model); - assert(pInfo->m_type == MITYPE_VEHICLE); + assert(pInfo->GetModelType() == MITYPE_VEHICLE); CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo; if (pVehicleInfo->m_vehicleType != VEHICLE_TYPE_CAR) { switch (model) { @@ -8153,10 +8165,10 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) car = new CAutomobile(model, MISSION_VEHICLE); CVector pos = *(CVector*)&ScriptParams[0]; pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel(); - car->GetPosition() = pos; + car->SetPosition(pos); car->SetHeading(DEGTORAD(*(float*)&ScriptParams[3])); CTheScripts::ClearSpaceForMissionEntity(pos, car); - car->m_status = STATUS_ABANDONED; + car->SetStatus(STATUS_ABANDONED); car->bIsLocked = true; car->bIsCarParkVehicle = true; CCarCtrl::JoinCarWithRoadSystem(car); @@ -8166,7 +8178,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f; car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0; car->bEngineOn = false; - car->m_nZoneLevel = CTheZones::GetLevelFromPosition(pos); + car->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos); CWorld::Add(car); return 0; } @@ -8243,7 +8255,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); - *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].pos; + *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].GetPosition(); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node); StoreParameters(&m_nIp, 4); return 0; @@ -8492,7 +8504,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); if (ScriptParams[1]) - pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(pVehicle->GetPosition()); + pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); else pVehicle->m_nZoneLevel = LEVEL_NONE; return 0; @@ -8503,7 +8515,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); assert(pPed); if (ScriptParams[1]) - pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(pPed->GetPosition()); + pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); else pPed->m_nZoneLevel = LEVEL_NONE; return 0; @@ -8908,7 +8920,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) if (ScriptParams[1]) pPed->m_nZoneLevel = LEVEL_IGNORE; else - pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(pPed->GetPosition()); + pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition()); return 0; } case COMMAND_GET_CHASE_CAR: @@ -9107,7 +9119,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) if (ScriptParams[1]) pVehicle->m_nZoneLevel = LEVEL_IGNORE; else - pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(pVehicle->GetPosition()); + pVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition()); return 0; } case COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER: @@ -9325,7 +9337,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) float destY = *(float*)&ScriptParams[4]; int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); CPathNode* pNode = &ThePaths.m_pathNodes[nid]; - *(CVector*)&ScriptParams[0] = pNode->pos; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, true); StoreParameters(&m_nIp, 4); return 0; @@ -9340,7 +9352,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) float destY = *(float*)&ScriptParams[4]; int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); CPathNode* pNode = &ThePaths.m_pathNodes[nid]; - *(CVector*)&ScriptParams[0] = pNode->pos; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, false); StoreParameters(&m_nIp, 4); return 0; @@ -9453,7 +9465,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) continue; if (pPed->bIsLeader || pPed->m_leader) continue; - if (!CTheZones::PointLiesWithinZone(pPed->GetPosition(), pZone)) + if (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone)) continue; if (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z) continue; @@ -11188,12 +11200,14 @@ INITSAVEBUF uint32 runningScripts = 0; for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) runningScripts++; - *size = sizeof(CRunningScript) * runningScripts + varSpace + SCRIPT_DATA_SIZE + SAVE_HEADER_SIZE + 3 * sizeof(uint32); + *size = CRunningScript::nSaveStructSize * runningScripts + varSpace + SCRIPT_DATA_SIZE + SAVE_HEADER_SIZE + 3 * sizeof(uint32); WriteSaveHeader(buf, 'S', 'C', 'R', '\0', *size - SAVE_HEADER_SIZE); WriteSaveBuf(buf, varSpace); for (uint32 i = 0; i < varSpace; i++) WriteSaveBuf(buf, ScriptSpace[i]); +#ifdef CHECK_STRUCT_SIZES static_assert(SCRIPT_DATA_SIZE == 968, "CTheScripts::SaveAllScripts"); +#endif uint32 script_data_size = SCRIPT_DATA_SIZE; WriteSaveBuf(buf, script_data_size); WriteSaveBuf(buf, OnAMissionFlag); @@ -11229,7 +11243,7 @@ INITSAVEBUF type = 0; handle = 0; } else { - switch (pEntity->m_type) { + switch (pEntity->GetType()) { case ENTITY_TYPE_BUILDING: if (((CBuilding*)pEntity)->GetIsATreadable()) { type = 1; @@ -11260,7 +11274,7 @@ INITSAVEBUF WriteSaveBuf(buf, (uint16)0); WriteSaveBuf(buf, runningScripts); for (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext()) - WriteSaveBuf(buf, *pScript); + pScript->Save(buf); VALIDATESAVEBUF(*size) } @@ -11336,7 +11350,7 @@ INITSAVEBUF ReadSaveBuf<uint16>(buf); uint32 runningScripts = ReadSaveBuf<uint32>(buf); for (uint32 i = 0; i < runningScripts; i++) - StartNewScript(0)->BuildFromSaved(ReadSaveBuf<CRunningScript>(buf)); + StartNewScript(0)->Load(buf); VALIDATESAVEBUF(size) } @@ -11371,7 +11385,7 @@ void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntit } if (cols <= 0) continue; - switch (pFound->m_type) { + switch (pFound->GetType()) { case ENTITY_TYPE_VEHICLE: { printf("Will try to delete a vehicle where a mission entity should be\n"); @@ -11611,3 +11625,77 @@ void CTheScripts::ReadMultiScriptFileOffsetsFromScript() MultiScriptArray[i] = Read4BytesFromScript(&ip); } } + +void CRunningScript::Save(uint8*& buf) +{ +#ifdef COMPATIBLE_SAVES + SkipSaveBuf(buf, 8); + for (int i = 0; i < 8; i++) + WriteSaveBuf<char>(buf, m_abScriptName[i]); + WriteSaveBuf<uint32>(buf, m_nIp); +#ifdef CHECK_STRUCT_SIZES + static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6"); +#endif + for (int i = 0; i < MAX_STACK_DEPTH; i++) + WriteSaveBuf<uint32>(buf, m_anStack[i]); + WriteSaveBuf<uint16>(buf, m_nStackPointer); + SkipSaveBuf(buf, 2); +#ifdef CHECK_STRUCT_SIZES + static_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18"); +#endif + for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++) + WriteSaveBuf<int32>(buf, m_anLocalVariables[i]); + WriteSaveBuf<bool>(buf, m_bCondResult); + WriteSaveBuf<bool>(buf, m_bIsMissionScript); + WriteSaveBuf<bool>(buf, m_bSkipWakeTime); + SkipSaveBuf(buf, 1); + WriteSaveBuf<uint32>(buf, m_nWakeTime); + WriteSaveBuf<uint16>(buf, m_nAndOrState); + WriteSaveBuf<bool>(buf, m_bNotFlag); + WriteSaveBuf<bool>(buf, m_bDeatharrestEnabled); + WriteSaveBuf<bool>(buf, m_bDeatharrestExecuted); + WriteSaveBuf<bool>(buf, m_bMissionFlag); + SkipSaveBuf(buf, 2); +#else + WriteSaveBuf(buf, *this); +#endif +} + +void CRunningScript::Load(uint8*& buf) +{ +#ifdef COMPATIBLE_SAVES + SkipSaveBuf(buf, 8); + for (int i = 0; i < 8; i++) + m_abScriptName[i] = ReadSaveBuf<char>(buf); + m_nIp = ReadSaveBuf<uint32>(buf); +#ifdef CHECK_STRUCT_SIZES + static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6"); +#endif + for (int i = 0; i < MAX_STACK_DEPTH; i++) + m_anStack[i] = ReadSaveBuf<uint32>(buf); + m_nStackPointer = ReadSaveBuf<uint16>(buf); + SkipSaveBuf(buf, 2); +#ifdef CHECK_STRUCT_SIZES + static_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18"); +#endif + for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++) + m_anLocalVariables[i] = ReadSaveBuf<int32>(buf); + m_bCondResult = ReadSaveBuf<bool>(buf); + m_bIsMissionScript = ReadSaveBuf<bool>(buf); + m_bSkipWakeTime = ReadSaveBuf<bool>(buf); + SkipSaveBuf(buf, 1); + m_nWakeTime = ReadSaveBuf<uint32>(buf); + m_nAndOrState = ReadSaveBuf<uint16>(buf); + m_bNotFlag = ReadSaveBuf<bool>(buf); + m_bDeatharrestEnabled = ReadSaveBuf<bool>(buf); + m_bDeatharrestExecuted = ReadSaveBuf<bool>(buf); + m_bMissionFlag = ReadSaveBuf<bool>(buf); + SkipSaveBuf(buf, 2); +#else + CRunningScript* n = next; + CRunningScript* p = prev; + *this = ReadSaveBuf<CRunningScript>(buf); + next = n; + prev = p; +#endif +} diff --git a/src/control/Script.h b/src/control/Script.h index 2eed29fe..acab66cc 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -27,7 +27,7 @@ struct intro_script_rectangle ~intro_script_rectangle() { } }; -static_assert(sizeof(intro_script_rectangle) == 0x18, "Script.h: error"); +VALIDATE_SIZE(intro_script_rectangle, 0x18); enum { SCRIPT_TEXT_MAX_LENGTH = 500 @@ -78,7 +78,7 @@ struct intro_text_line } }; -static_assert(sizeof(intro_text_line) == 0x414, "Script.h: error"); +VALIDATE_SIZE(intro_text_line, 0x414); struct script_sphere_struct { @@ -423,14 +423,10 @@ class CRunningScript public: void SetIP(uint32 ip) { m_nIp = ip; } CRunningScript* GetNext() const { return next; } - void BuildFromSaved(const CRunningScript& pSaved) - { - CRunningScript* n = next; - CRunningScript* p = prev; - *this = pSaved; - next = n; - prev = p; - } + + void Save(uint8*& buf); + void Load(uint8*& buf); + void UpdateTimers(float timeStep) { m_anLocalVariables[NUM_LOCAL_VARS] += timeStep; m_anLocalVariables[NUM_LOCAL_VARS + 1] += timeStep; @@ -442,6 +438,8 @@ public: void RemoveScriptFromList(CRunningScript**); void AddScriptToList(CRunningScript**); + static const uint32 nSaveStructSize; + private: void CollectParameters(uint32*, int16); int32 CollectNextParameterWithoutIncreasingPC(uint32); diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index c8d3f79f..b2f0900e 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -150,12 +150,12 @@ CTrafficLights::ScanForLightsOnMap(void) // Check cars for(i = 0; i < ThePaths.m_numCarPathLinks; i++){ - CVector2D dist = ThePaths.m_carPathLinks[i].pos - light->GetPosition(); + CVector2D dist = ThePaths.m_carPathLinks[i].GetPosition() - light->GetPosition(); float dotY = Abs(DotProduct2D(dist, light->GetForward())); // forward is direction of car light float dotX = DotProduct2D(dist, light->GetRight()); // towards base of light // it has to be on the correct side of the node and also not very far away if(dotX < 0.0f && dotX > -15.0f && dotY < 3.0f){ - float dz = ThePaths.m_pathNodes[ThePaths.m_carPathLinks[i].pathNodeIndex].pos.z - + float dz = ThePaths.m_pathNodes[ThePaths.m_carPathLinks[i].pathNodeIndex].GetZ() - light->GetPosition().z; if(dz < 15.0f){ ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light); @@ -182,16 +182,16 @@ CTrafficLights::ScanForLightsOnMap(void) // Check peds for(i = ThePaths.m_numCarPathNodes; i < ThePaths.m_numPathNodes; i++){ float dist1, dist2; - dist1 = Abs(ThePaths.m_pathNodes[i].pos.x - light->GetPosition().x) + - Abs(ThePaths.m_pathNodes[i].pos.y - light->GetPosition().y); + dist1 = Abs(ThePaths.m_pathNodes[i].GetX() - light->GetPosition().x) + + Abs(ThePaths.m_pathNodes[i].GetY() - light->GetPosition().y); if(dist1 < 50.0f){ for(l = 0; l < ThePaths.m_pathNodes[i].numLinks; l++){ j = ThePaths.m_pathNodes[i].firstLink + l; - if(ThePaths.m_connectionFlags[j].bCrossesRoad){ - dist2 = Abs(ThePaths.m_pathNodes[j].pos.x - light->GetPosition().x) + - Abs(ThePaths.m_pathNodes[j].pos.y - light->GetPosition().y); + if(ThePaths.ConnectionCrossesRoad(j)){ + dist2 = Abs(ThePaths.m_pathNodes[j].GetX() - light->GetPosition().x) + + Abs(ThePaths.m_pathNodes[j].GetY() - light->GetPosition().y); if(dist1 < 15.0f || dist2 < 15.0f) - ThePaths.m_connectionFlags[j].bTrafficLight = true; + ThePaths.ConnectionSetTrafficLight(j); } } } @@ -213,8 +213,8 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) if(alwaysStop || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ - float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, - ThePaths.m_carPathLinks[node].dir); + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(), + ThePaths.m_carPathLinks[node].GetDirection()); if(vehicle->AutoPilot.m_nNextDirection == -1){ if(dist > 0.0f && dist < 8.0f) return true; @@ -233,8 +233,8 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) if(alwaysStop || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ - float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, - ThePaths.m_carPathLinks[node].dir); + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(), + ThePaths.m_carPathLinks[node].GetDirection()); if(vehicle->AutoPilot.m_nCurrentDirection == -1){ if(dist > 0.0f && dist < 8.0f) return true; @@ -245,7 +245,7 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) } } - if(vehicle->m_status == STATUS_PHYSICS){ + if(vehicle->GetStatus() == STATUS_PHYSICS){ node = vehicle->AutoPilot.m_nPreviousPathNodeInfo; type = ThePaths.m_carPathLinks[node].trafficLightType; if(type){ @@ -254,8 +254,8 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) if(alwaysStop || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ - float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, - ThePaths.m_carPathLinks[node].dir); + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(), + ThePaths.m_carPathLinks[node].GetDirection()); if(vehicle->AutoPilot.m_nPreviousDirection == -1){ if(dist > 0.0f && dist < 6.0f) return true; |