From a55e738dfad92ae7e23e45c3593384b9469f1177 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 9 May 2020 20:21:13 +0300 Subject: [PATCH 1/2] ccarctrl big fix --- src/control/AutoPilot.h | 2 + src/control/CarCtrl.cpp | 197 ++++++++++++++++++++++++++++++++------- src/control/CarCtrl.h | 1 + src/control/Curves.cpp | 2 +- src/control/Script.cpp | 8 ++ src/core/General.h | 2 + src/core/Placeable.h | 2 +- src/core/templates.h | 3 +- src/vehicles/Vehicle.cpp | 1 + src/vehicles/Vehicle.h | 2 +- 10 files changed, 184 insertions(+), 36 deletions(-) diff --git a/src/control/AutoPilot.h b/src/control/AutoPilot.h index 24e7cc53..282f1418 100644 --- a/src/control/AutoPilot.h +++ b/src/control/AutoPilot.h @@ -130,4 +130,6 @@ public: void Load(uint8*& buf); #endif + float GetCruiseSpeed(void) { return m_nCruiseSpeed * m_fCruiseSpeedMultiplier; } + }; diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 8be39a86..266a750b 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -74,6 +74,8 @@ #define DISTANCE_BETWEEN_CAR_AND_DEAD_PED 6.0f #define PROBABILITY_OF_PASSENGER_IN_VEHICLE 0.125f +#define FARAWAY_DISTANCE_REMOVAL 120.0f + int CCarCtrl::NumLawEnforcerCars; int CCarCtrl::NumAmbulancesOnDuty; int CCarCtrl::NumFiretrucksOnDuty; @@ -429,6 +431,73 @@ CCarCtrl::GenerateOneRandomCar() pVehicle->GetRight() = CVector(forwardY, -forwardX, 0.0f); pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); +#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); + + 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(); @@ -455,20 +524,10 @@ CCarCtrl::GenerateOneRandomCar() directionCurrentLinkX, directionCurrentLinkY, directionNextLinkX, directionNextLinkY ) * (1000.0f / pVehicle->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). */ - - /* Second fix: adding 0.5f is a mistake. It should be between 0 and 1. It was fixed in SA.*/ - /* It is also correct in CAutoPilot::ModifySpeed. */ - - /* It seems like design decisions in VC were made based on this 0.5f addition. Can't remove it anymore. */ - pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - - (uint32)((0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); -#else 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); CVector positionIncludingCurve; @@ -539,7 +598,7 @@ CCarCtrl::GenerateOneRandomCar() return; } }else{ - if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? 1.5f : 1.0f) * 120.0f || + if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? 1.5f : 1.0f) * FARAWAY_DISTANCE_REMOVAL || (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 100.0f) { delete pVehicle; return; @@ -854,6 +913,36 @@ CCarCtrl::RemoveDistantCars() } } +void +CCarCtrl::RemoveCarsIfThePoolGetsFull(void) +{ + if ((CTimer::GetFrameCounter() & 7) != 3) + return; + if (CPools::GetVehiclePool()->GetNoOfFreeSpaces() >= 8) + return; + int i = CPools::GetVehiclePool()->GetSize(); + float md = 999999.9f; + CVehicle* pClosestVehicle = nil; + while (i--) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (!pVehicle) + continue; + if (IsThisVehicleInteresting(pVehicle) || pVehicle->bIsLocked) + continue; + if (!pVehicle->CanBeDeleted() || CCranes::IsThisCarBeingTargettedByAnyCrane(pVehicle)) + continue; + float distance = (TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude(); + if (distance < md) { + md = distance; + pClosestVehicle = pVehicle; + } + } + if (pClosestVehicle) { + CWorld::Remove(pClosestVehicle); + delete pClosestVehicle; + } +} + void CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) { @@ -879,7 +968,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) pVehicle->bIsLawEnforcer || pVehicle->bIsCarParkVehicle ){ - threshold = 120.0f * TheCamera.GenerationDistMultiplier; + threshold = FARAWAY_DISTANCE_REMOVAL * TheCamera.GenerationDistMultiplier; } if (TheCamera.GetForward().z < -0.9f) threshold = 70.0f; @@ -937,6 +1026,16 @@ CCarCtrl::CountCarsOfType(int32 mi) return total; } +static CVector GetRandomOffsetForVehicle(CVehicle* pVehicle, bool bNext) +{ + CVector offset; + int32 seed = ((bNext ? pVehicle->AutoPilot.m_nNextPathNodeInfo : pVehicle->AutoPilot.m_nCurrentPathNodeInfo) + pVehicle->m_randomSeed) & 7; + offset.x = (seed - 3) * 0.009f; + offset.y = ((seed >> 3) - 3) * 0.009f; + offset.z = 0.0f; + return offset; +} + void CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle) { @@ -969,8 +1068,12 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle) 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); + CVector directionCurrentLink = GetRandomOffsetForVehicle(pVehicle, false); + directionCurrentLink += CVector(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f); + directionCurrentLink.Normalise(); + CVector directionNextLink = GetRandomOffsetForVehicle(pVehicle, true); + directionNextLink += CVector(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f); + directionNextLink.Normalise(); CVector positionIncludingCurve; CVector directionIncludingCurve; CCurves::CalcCurvePoint( @@ -993,7 +1096,7 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle) { if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_PLOUGH_THROUGH) - return pVehicle->AutoPilot.m_nCruiseSpeed; + return pVehicle->AutoPilot.GetCruiseSpeed(); float left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_DANGER; float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER; float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER; @@ -1005,23 +1108,23 @@ CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle) assert(xstart <= xend); assert(ystart <= yend); - float maxSpeed = pVehicle->AutoPilot.m_nCruiseSpeed; + float maxSpeed = pVehicle->AutoPilot.GetCruiseSpeed(); CWorld::AdvanceCurrentScanCode(); for (int y = ystart; y <= yend; y++){ for (int x = xstart; x <= xend; x++){ CSector* s = CWorld::GetSector(x, y); - SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed); - SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed); - SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed); - SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed); + SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed()); + SlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed()); + SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed()); + SlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed()); } } pVehicle->bWarnedPeds = true; if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS) return maxSpeed; - return (maxSpeed + pVehicle->AutoPilot.m_nCruiseSpeed) / 2; + return (maxSpeed + pVehicle->AutoPilot.GetCruiseSpeed()) / 2; } void @@ -1223,8 +1326,8 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float proximityA = TestCollisionBetween2MovingRects(pOtherVehicle, pVehicle, projectionX, projectionY, &forwardA, &forwardB, 0); float proximityB = TestCollisionBetween2MovingRects(pVehicle, pOtherVehicle, -projectionX, -projectionY, &forwardB, &forwardA, 1); float minProximity = Min(proximityA, proximityB); - if (minProximity >= 0.0f && minProximity < 1.0f){ - minProximity = Max(0.0f, (minProximity - 0.2f) * 1.25f); + if (minProximity >= 0.0f && minProximity < 1.5f){ + minProximity = Max(0.0f, (minProximity - 0.2f) / 1.3f); pVehicle->AutoPilot.m_bSlowedDownBecauseOfCars = true; *pSpeed = Min(*pSpeed, minProximity * curSpeed); } @@ -1233,7 +1336,7 @@ 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->GetStatus() == STATUS_SIMPLE){ @@ -1450,6 +1553,7 @@ void CCarCtrl::WeaveThroughCarsSectorList(CPtrList& lst, CVehicle* pVehicle, CPh void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAngleToWeaveLeft, float* pAngleToWeaveRight) { + // TODO(MIAMI): if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE && pOtherEntity == FindPlayerVehicle()) return; if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMCAR_CLOSE && pOtherEntity == pVehicle->AutoPilot.m_pTargetCar) @@ -1461,8 +1565,8 @@ void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float if (distance < 1.0f) return; if (DotProduct2D(pVehicle->GetMoveSpeed() - pOtherCar->GetMoveSpeed(), vecDiff) * 110.0f - - pOtherCar->GetModelInfo()->GetColModel()->boundingSphere.radius - - pVehicle->GetModelInfo()->GetColModel()->boundingSphere.radius < distance) + pOtherCar->GetColModel()->boundingSphere.radius - + pVehicle->GetColModel()->boundingSphere.radius < distance) return; CVector2D forward = pVehicle->GetForward(); forward.Normalise(); @@ -1636,18 +1740,30 @@ bool CCarCtrl::PickNextNodeAccordingStrategy(CVehicle* pVehicle) return false; default: PickNextNodeRandomly(pVehicle); + if (ThePaths.GetNode(pVehicle->AutoPilot.m_nNextRouteNode)->bOnlySmallBoats && BoatWithTallMast(pVehicle->GetModelIndex())) + pVehicle->AutoPilot.m_nCruiseSpeed = 0; return false; } } void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) { + if (pVehicle->m_nRouteSeed) + CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed); int32 prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode; int32 curNode = pVehicle->AutoPilot.m_nNextRouteNode; uint8 totalLinks = ThePaths.m_pathNodes[curNode].numLinks; CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - uint8 lanesOnCurrentPath = pCurLink->pathNodeIndex == curNode ? - pCurLink->numRightLanes : pCurLink->numLeftLanes; + uint8 lanesOnCurrentPath; + bool isOnOneWayRoad; + if (pCurLink->pathNodeIndex == curNode) { + lanesOnCurrentPath = pCurLink->numLeftLanes; + isOnOneWayRoad = pCurLink->numRightLanes == 0; + } + else { + lanesOnCurrentPath = pCurLink->numRightLanes; + isOnOneWayRoad = pCurLink->numLeftLanes == 0; + } uint8 allowedDirections = PATH_DIRECTION_NONE; uint8 nextLane = pVehicle->AutoPilot.m_nNextLane; if (nextLane == 0) @@ -1669,6 +1785,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) CCarPathLink* pNextLink; CPathNode* pNextPathNode; bool goingAgainstOneWayRoad; + bool nextNodeIsOneWayRoad; uint8 direction; for(attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++){ if (attempt != 0){ @@ -1678,7 +1795,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) if ((!pNextPathNode->bDeadEnd || pPrevPathNode->bDeadEnd) && (!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) && (!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel) && - !goingAgainstOneWayRoad) + !goingAgainstOneWayRoad && (!isOnOneWayRoad || !nextNodeIsOneWayRoad)) break; } } @@ -1688,9 +1805,10 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) 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; + nextNodeIsOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numLeftLanes == 0 : pNextLink->numRightLanes == 0; } if (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) { - /* If we failed 15 times, then remove dead end and current lane limitations */ + /* If we failed 15 times, then remove dead end, one way road and current lane limitations */ for (attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++) { if (attempt != 0) { if (pVehicle->AutoPilot.m_nNextRouteNode != prevNode) { @@ -1749,6 +1867,10 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) } 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 */ @@ -1767,14 +1889,25 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) } if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; +#ifdef FIX_BUGS CVector positionOnCurrentLinkIncludingLane( - pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ + 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->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + 0.0f); +#else + CVector positionOnCurrentLinkIncludingLane( + pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); +#endif float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index f66b9232..f30d0720 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -126,6 +126,7 @@ public: static void RemoveFromLoadedVehicleArray(int32 mi, int32 rating); static int32 ChooseCarModelToLoad(int32 rating); static bool BoatWithTallMast(int32 mi); + static void RemoveCarsIfThePoolGetsFull(void); static float GetPositionAlongCurrentCurve(CVehicle* pVehicle) { 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/Script.cpp b/src/control/Script.cpp index b6729486..6e0923d7 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -9729,7 +9729,15 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) case COMMAND_IS_MODEL_AVAILABLE: case COMMAND_SHUT_CHAR_UP: case COMMAND_SET_ENABLE_RC_DETONATE: + assert(0); case COMMAND_SET_CAR_RANDOM_ROUTE_SEED: + { + CollectParameters(&m_nIp, 2); + CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); + assert(pVehicle); + pVehicle->m_nRouteSeed = ScriptParams[1]; + return 0; + } case COMMAND_IS_ANY_PICKUP_AT_COORDS: case COMMAND_GET_FIRST_PICKUP_COORDS: case COMMAND_GET_NEXT_PICKUP_COORDS: diff --git a/src/core/General.h b/src/core/General.h index 7ffa99de..3188d82b 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -145,4 +145,6 @@ public: static int32 GetRandomNumberInRange(int32 low, int32 high) { return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); } + static void SetRandomSeed(int32 seed) + { mysrand(seed); } }; diff --git a/src/core/Placeable.h b/src/core/Placeable.h index 7e858283..26a2291a 100644 --- a/src/core/Placeable.h +++ b/src/core/Placeable.h @@ -16,7 +16,7 @@ public: m_matrix.GetPosition().y = y; m_matrix.GetPosition().z = z; } - void SetPosition(const CVector &pos) { m_matrix.GetPosition() = pos; } + void SetPosition(const CVector& pos) { m_matrix.GetPosition() = pos; } CVector &GetRight(void) { return m_matrix.GetRight(); } CVector &GetForward(void) { return m_matrix.GetForward(); } CVector &GetUp(void) { return m_matrix.GetUp(); } diff --git a/src/core/templates.h b/src/core/templates.h index aa71fe5d..465e3bef 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -133,7 +133,7 @@ public: // TODO: the cast is unsafe return (int)((U*)entry - m_entries); } - int GetNoOfUsedSpaces(void){ + int GetNoOfUsedSpaces(void) const { int i; int n = 0; for(i = 0; i < m_size; i++) @@ -164,6 +164,7 @@ public: memcpy(entries, m_entries, sizeof(U)*m_size); debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */ } + int32 GetNoOfFreeSpaces() const { return GetSize() - GetNoOfUsedSpaces(); } }; template diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 1cf41435..496a72de 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -55,6 +55,7 @@ CVehicle::CVehicle(uint8 CreatedBy) m_fSteerRatio = 0.0f; m_type = ENTITY_TYPE_VEHICLE; VehicleCreatedBy = CreatedBy; + m_nRouteSeed = 0; bIsLocked = false; bIsLawEnforcer = false; bIsAmbulanceOnDuty = false; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 7711e445..c03e9209 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -132,7 +132,7 @@ public: uint8 m_currentColour2; uint8 m_aExtras[2]; int16 m_nAlarmState; - int16 m_nMissionValue; + int16 m_nRouteSeed; CPed *pDriver; CPed *pPassengers[8]; uint8 m_nNumPassengers; From 3de003a8e7c99d0488b16ccaf8b441af8d8a87e7 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 9 May 2020 22:11:40 +0300 Subject: [PATCH 2/2] new curves + boat fix --- src/control/Curves.cpp | 18 ++++++++++++++++-- src/vehicles/Boat.cpp | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/control/Curves.cpp b/src/control/Curves.cpp index 0a01a7aa..31a2767a 100644 --- a/src/control/Curves.cpp +++ b/src/control/Curves.cpp @@ -11,7 +11,7 @@ float CCurves::CalcSpeedScaleFactor(CVector* pPoint1, CVector* pPoint2, float di if (dp > 0.9f) return distance + Abs((pPoint1->x * dir1Y - pPoint1->y * dir1X) - (pPoint2->x * dir1Y - pPoint2->y * dir1X)); else - return ((1.0f - dp) * 0.2f + 1.0f) * distance; + return ((1.0f - dp) * 0.25f + 1.0f) * distance; } void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVector* pDir2, float between, int32 timeOnCurve, CVector* pOutPos, CVector* pOutDir) @@ -19,7 +19,21 @@ 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 t1 = Abs(DotProduct2D(*pPos1 - *pPos2, *pDir1)); + float t2 = Abs(DotProduct2D(*pPos2 - *pPos1, *pDir2)); + float curveCoef; + if (t1 > t2) { + if (between < (t1 - t2) / (t1 + t2)) + curveCoef = 0.0f; + else + curveCoef = 0.5f - 0.5f * Cos(3.1415f * (t1 + t2) / (2 * t2) * (between - (t1 - t2) / (t1 + t2))); + } + else { + if (2 * t1 / (t1 + t2) < between) + curveCoef = 1.0f; + else + curveCoef = 0.5f - 0.5f * Cos(3.1415f * between * (t1 + t2) / (2 * t1)); + } *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/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 87b8a212..5879717a 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -431,7 +431,7 @@ CBoat::ProcessControl(void) speedUp = pHandling->fBrakeDeceleration - m_vecMoveSpeed.z; if(speedUp < 0.0f) speedUp = 0.0f; float speedFwd = DotProduct(m_vecMoveSpeed, GetForward()); - speedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fTractionLoss; + speedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fBrakeBias; CVector speed = speedFwd*GetForward() + CVector(0.0f, 0.0f, speedUp); CVector splashImpulse = speed * m_fMass; ApplyMoveForce(splashImpulse);