diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index bd53f0e5..720c269d 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -2593,6 +2593,54 @@ float CCarCtrl::FindMaxSteerAngle(CVehicle* pVehicle) return pVehicle->GetModelIndex() == MI_ENFORCER ? 0.7f : DEFAULT_MAX_STEER_ANGLE; } +void CCarCtrl::SteerAIHeliTowardsTargetCoors(CAutomobile* pHeli) +{ + if (pHeli->m_aWheelSpeed[1] < 0.22f) + pHeli->m_aWheelSpeed[1] += 0.001f; + if (pHeli->m_aWheelSpeed[1] < 0.22f) + return; + CVector2D vecToTarget = pHeli->AutoPilot.m_vecDestinationCoors - pHeli->GetPosition(); + float distanceToTarget = vecToTarget.Magnitude(); +#ifdef FIX_BUGS + float speed = pHeli->AutoPilot.GetCruiseSpeed() * 0.01f; +#else + float speed = pHeli->AutoPilot.m_nCruiseSpeed * 0.01f; +#endif + if (distanceToTarget >= 100.0f) + { + if (distanceToTarget > 75.0f) + speed *= 0.7f; + else if (distanceToTarget > 10.0f) + speed *= 0.4f; + else + speed *= 0.2f; + } + CVector2D vecAdvanceThisFrame = vecToTarget; + vecAdvanceThisFrame.Normalise(); + vecAdvanceThisFrame *= speed; + float resistance = Pow(0.997f, CTimer::GetTimeStep()); + pHeli->m_vecMoveSpeed.x *= resistance; + pHeli->m_vecMoveSpeed.y *= resistance; + vecAdvanceThisFrame -= pHeli->m_vecMoveSpeed; + CVector2D vecSpeedChange = vecAdvanceThisFrame - pHeli->m_vecMoveSpeed; + float vecSpeedChangeLength = vecSpeedChange.Magnitude(); + vecSpeedChange.Normalise(); + float changeMultiplier = 0.002f * CTimer::GetTimeStep(); + if (distanceToTarget < 5.0f) + changeMultiplier /= 5.0f; + if (vecSpeedChangeLength < changeMultiplier) { + pHeli->m_vecMoveSpeed.x = vecAdvanceThisFrame.x; + pHeli->m_vecMoveSpeed.y = vecAdvanceThisFrame.y; + } + else { + pHeli->m_vecMoveSpeed.x += vecSpeedChange.x * changeMultiplier; + pHeli->m_vecMoveSpeed.y += vecSpeedChange.y * changeMultiplier; + } + pHeli->SetPosition(pHeli->GetPosition() + CVector(CTimer::GetTimeStep() * pHeli->m_vecMoveSpeed.x, CTimer::GetTimeStep() * pHeli->m_vecMoveSpeed.y, 0.0f)); + assert(0); + // This is not finished yet. Heli fields in CAutomobile required +} + void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake) { CVector2D forward = pVehicle->GetForward(); @@ -2620,18 +2668,12 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv if (PickNextNodeAccordingStrategy(pVehicle)) { switch (pVehicle->AutoPilot.m_nCarMission){ case MISSION_GOTOCOORDS: - pVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT; - *pSwerve = 0.0f; - *pAccel = 0.0f; - *pBrake = 0.0f; - *pHandbrake = false; + SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x, + pVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake); return; case MISSION_GOTOCOORDS_ACCURATE: - pVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE; - *pSwerve = 0.0f; - *pAccel = 0.0f; - *pBrake = 0.0f; - *pHandbrake = false; + SteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x, + pVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake); return; } } @@ -2667,6 +2709,7 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv switch (pVehicle->AutoPilot.m_nDrivingStyle) { case DRIVINGSTYLE_STOP_FOR_CARS: case DRIVINGSTYLE_SLOW_DOWN_FOR_CARS: + case DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS: speedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle) / pVehicle->AutoPilot.m_nCruiseSpeed; break; default: @@ -2933,8 +2976,6 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar return false; } - -//TODO void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle) { if (pVehicle->m_nRouteSeed) @@ -2952,11 +2993,21 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle) curLink = 0; curConnection = ThePaths.m_carPathConnections[pCurNode->firstLink]; }else{ - curConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo; - while (curConnection == pVehicle->AutoPilot.m_nNextPathNodeInfo){ - curLink = CGeneral::GetRandomNumber() % pCurNode->numLinks; - curConnection = ThePaths.m_carPathConnections[curLink + pCurNode->firstLink]; + int closestLink = -1; + float md = 999999.9f; + + for (curLink = 0; curLink < pCurNode->numLinks; curLink++) { + int node = ThePaths.ConnectedNode(curLink + pCurNode->firstLink); + CPathNode* pNode = &ThePaths.m_pathNodes[node]; + if (node == pVehicle->AutoPilot.m_nNextRouteNode) + continue; + float dist = CCollision::DistToLine(&pCurNode->GetPosition(), &pNode->GetPosition(), &pVehicle->GetPosition()); + if (dist < md) { + md = dist; + closestLink = curLink; + } } + curConnection = ThePaths.m_carPathConnections[closestLink + pCurNode->firstLink]; } pVehicle->AutoPilot.m_nCurrentPathNodeInfo = curConnection; pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(curLink + pCurNode->firstLink) >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index d54d004a..a762ed63 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -205,12 +205,19 @@ int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X } CGarage* pGarage = &aGarages[NumGarages]; // TODO(MIAMI): proper! - pGarage->m_fX1 = Min(Min(X1, X2), X3); - pGarage->m_fX2 = Max(Max(X1, X2), X3); - pGarage->m_fY1 = Min(Min(Y1, Y2), Y3); - pGarage->m_fY2 = Max(Max(Y1, Y2), Y3); - pGarage->m_fZ1 = Min(Z1, Z2); - pGarage->m_fZ2 = Max(Z1, Z2); + pGarage->m_fInfX = Min(Min(X1, X2), X3, X2 + X3 - X1); + pGarage->m_fSupX = Max(Max(X1, X2), X3); + pGarage->m_fInfY = Min(Min(Y1, Y2), Y3, Y2 + Y3 - Y1); + pGarage->m_fSupY = Max(Max(Y1, Y2), Y3); + pGarage->m_vecCorner1 = CVector(X1, Y1, Z1); + pGarage->m_vDir1 = CVector2D(X2 - X1, Y2 - Y1); + pGarage->m_vDir1 = CVector2D(X3 - X1, Y3 - Y1); + pGarage->m_fSupZ = Z2; + pGarage->m_nMaxStoredCars = 4; + pGarage->m_fDir1Len = pGarage->m_vDir1.Magnitude(); + pGarage->m_fDir2Len = pGarage->m_vDir1.Magnitude(); + pGarage->m_vDir1 /= pGarage->m_fDir1Len; + pGarage->m_vDir2 /= pGarage->m_fDir2Len; pGarage->m_pDoor1 = nil; pGarage->m_pDoor2 = nil; pGarage->m_fDoor1Z = Z1; @@ -257,6 +264,17 @@ int16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X case GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE: case GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR: case GARAGE_MISSION_KEEPCAR_REMAINCLOSED: + case GARAGE_COLLECTCARS_4: + case GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR: + case GARAGE_HIDEOUT_FOUR: + case GARAGE_HIDEOUT_FIVE: + case GARAGE_HIDEOUT_SIX: + case GARAGE_HIDEOUT_SEVEN: + case GARAGE_HIDEOUT_EIGHT: + case GARAGE_HIDEOUT_NINE: + case GARAGE_HIDEOUT_TEN: + case GARAGE_HIDEOUT_ELEVEN: + case GARAGE_HIDEOUT_TWELVE: pGarage->m_eGarageState = GS_FULLYCLOSED; pGarage->m_fDoorPos = 0.0f; break; diff --git a/src/control/Garages.h b/src/control/Garages.h index c54c41df..3e66dc32 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -94,6 +94,7 @@ class CGarage { eGarageType m_eGarageType; eGarageState m_eGarageState; + uint8 m_nMaxStoredCars; bool field_2; // unused bool m_bClosingWithoutTargetCar; bool m_bDeactivated; @@ -108,12 +109,16 @@ class CGarage bool m_bRecreateDoorOnNextRefresh; bool m_bRotatedDoor; bool m_bCameraFollowsPlayer; - float m_fX1; - float m_fX2; - float m_fY1; - float m_fY2; - float m_fZ1; - float m_fZ2; + CVector m_vecCorner1; + CVector2D m_vDir1; + CVector2D m_vDir2; + float m_fSupZ; + float m_fDir1Len; + float m_fDir2Len; + float m_fInfX; + float m_fSupX; + float m_fInfY; + float m_fSupY; float m_fDoorPos; float m_fDoorHeight; float m_fDoor1X; @@ -183,8 +188,6 @@ class CGarage friend class CCamera; }; -static_assert(sizeof(CGarage) == 140, "CGarage"); - class CGarages { enum {