From c16849d4a256a757c535a58a9fab118f03013d61 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sat, 17 Aug 2019 15:44:25 +0300 Subject: [PATCH] more CCarCtrl --- src/control/CarCtrl.cpp | 126 ++++++++++++++++++++++++++++++++++++++-- src/peds/Ped.cpp | 28 ++++----- src/peds/Ped.h | 4 +- src/vehicles/Vehicle.h | 2 + 4 files changed, 138 insertions(+), 22 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 0df42397..064eab98 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -30,8 +30,11 @@ #include "World.h" #include "Zones.h" +#define GAME_SPEED_TO_METERS_PER_SECOND 50.0f + #define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS 51.0f #define DISTANCE_TO_SCAN_FOR_DANGER 11.0f +#define SAFE_DISTANCE_TO_PED 3.0f #define INFINITE_Z 1000000000.0f int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38; @@ -60,7 +63,6 @@ WRAPPER void CCarCtrl::GenerateEmergencyServicesCar(void) { EAXJMP(0x41FC50); } WRAPPER void CCarCtrl::PickNextNodeAccordingStrategy(CVehicle*) { EAXJMP(0x41BA50); } WRAPPER void CCarCtrl::DragCarToPoint(CVehicle*, CVector*) { EAXJMP(0x41D450); } WRAPPER void CCarCtrl::SlowCarDownForCarsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float) { EAXJMP(0x419B40); } -WRAPPER void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float) { EAXJMP(0x419300); } void CCarCtrl::GenerateRandomCars() @@ -293,8 +295,8 @@ CCarCtrl::GenerateOneRandomCar() pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18); else if (carClass == POOR || carClass == SPECIAL) pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10); - CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(pCar->GetModelIndex()); - if (pVehicleInfo->GetColModel()->boundingBox.max.y - pVehicleInfo->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) { + 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; } @@ -481,7 +483,7 @@ CCarCtrl::GenerateOneRandomCar() delete pCar; return; } - CVehicleModelInfo* pVehicleModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(pCar->GetModelIndex()); + CVehicleModelInfo* pVehicleModel = pCar->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); @@ -783,8 +785,8 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle) float CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle) { - if (pVehicle->AutoPilot.m_nDrivingStyle == MISSION_RAMPLAYER_FARAWAY || - pVehicle->AutoPilot.m_nDrivingStyle == MISSION_RAMPLAYER_CLOSE) + if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || + pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) return pVehicle->AutoPilot.m_nCruiseSpeed; float left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_DANGER; float right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER; @@ -869,6 +871,118 @@ CCarCtrl::SlowCarOnRailsDownForTrafficAndLights(CVehicle* pVehicle) pVehicle->AutoPilot.ModifySpeed(0.0f); } } +#if 0 +WRAPPER void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float) { EAXJMP(0x419300); } +#else +void CCarCtrl::SlowCarDownForPedsSectorList(CPtrList& lst, CVehicle* pVehicle, float x_inf, float y_inf, float x_sup, float y_sup, float* pSpeed, float curSpeed) +{ + float frontOffset = pVehicle->GetModelInfo()->GetColModel()->boundingBox.max.y; + float frontSafe = frontOffset + SAFE_DISTANCE_TO_PED; + for (CPtrNode* pNode = lst.first; pNode != nil; pNode = pNode->next){ + CPed* pPed = (CPed*)pNode->item; + if (pPed->m_scanCode == CWorld::GetCurrentScanCode()) + continue; + if (!pPed->bUsesCollision) + continue; + pPed->m_scanCode = CWorld::GetCurrentScanCode(); + CVector vecPedPos = pPed->GetPosition(); + if (vecPedPos.x < x_inf || vecPedPos.x > x_sup) + continue; + if (vecPedPos.y < y_inf || vecPedPos.y > y_sup) + continue; + if (ABS(vecPedPos.z - pVehicle->GetPosition().z) >= 4.0f) + continue; + CVector vecToPed = vecPedPos - pVehicle->GetPosition(); + float dotDirection = DotProduct(pVehicle->GetForward(), vecToPed); + float dotVelocity = DotProduct(pVehicle->GetForward(), pVehicle->GetMoveSpeed()); + if (dotDirection <= frontOffset) /* If already run him over, don't care */ + continue; + float distanceUntilHit = dotDirection - frontOffset; + float movementTowardsPedPerSecond = GAME_SPEED_TO_METERS_PER_SECOND * dotVelocity; + if (4 * movementTowardsPedPerSecond <= distanceUntilHit) + /* If car isn't projected to hit a ped in 4 seconds, don't care */ + continue; + float sidewaysDistance = ABS(DotProduct(pVehicle->GetRight(), vecToPed)); + float sideLength = pVehicle->GetModelInfo()->GetColModel()->boundingBox.max.x; + if (pVehicle->m_vehType == VEHICLE_TYPE_BIKE) + sideLength *= 1.6f; + 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->GetPedState() != PED_STEP_AWAY && pPed->GetPedState() != PED_DIVE_AWAY){ + if (distanceUntilHit < movementTowardsPedPerSecond){ + /* Very close. Time to evade. */ + if (pVehicle->GetModelIndex() == MI_RCBANDIT){ + if (dotVelocity * GAME_SPEED_TO_METERS_PER_SECOND / 2 > distanceUntilHit) + pPed->SetEvasiveStep(pVehicle, 0); + }else if (dotVelocity > 0.3f){ + if (sideLength - 0.5f < sidewaysDistance) + pPed->SetEvasiveStep(pVehicle, 0); + else + pPed->SetEvasiveDive(pVehicle, 0); + }else{ + if (sideLength + 0.1f < sidewaysDistance) + pPed->SetEvasiveStep(pVehicle, 0); + else + pPed->SetEvasiveDive(pVehicle, 0); + } + }else{ + /* Relatively safe but annoying. */ + if (pVehicle->m_status == STATUS_PLAYER && + pPed->GetPedState() != PED_FLEE_ENTITY && + pPed->CharCreatedBy == RANDOM_CHAR){ + float angleCarToPed = CGeneral::GetRadianAngleBetweenPoints( + pVehicle->GetPosition().x, pVehicle->GetPosition().y, + pPed->GetPosition().x, pPed->GetPosition().y + ); + angleCarToPed = CGeneral::LimitRadianAngle(angleCarToPed); + pPed->m_headingRate = CGeneral::LimitRadianAngle(pPed->m_headingRate); + float visibilityAngle = ABS(angleCarToPed - pPed->m_headingRate); + if (visibilityAngle > PI) + visibilityAngle = TWOPI - visibilityAngle; + if (visibilityAngle < HALFPI || pVehicle->m_nCarHornTimer){ + /* if ped sees the danger of if car horn is on */ + pPed->SetFlee(pVehicle, 2000); + pPed->bUsePedNodeSeek = false; + pPed->SetMoveState(PEDMOVE_RUN); + } + }else{ + CPlayerPed* pPlayerPed = (CPlayerPed*)pPed; + if (pPlayerPed->IsPlayer() && dotDirection < frontSafe && + pPlayerPed->IsPedInControl() && + pPlayerPed->m_fMoveSpeed < 0.1f && pPlayerPed->bIsLooking && + CTimer::GetTimeInMilliseconds() > pPlayerPed->m_lookTimer) { + pPlayerPed->AnnoyPlayerPed(false); + pPlayerPed->SetLookFlag(pVehicle, true); + pPlayerPed->SetLookTimer(1500); + if (pPlayerPed->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || + pPlayerPed->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT || + pPlayerPed->GetWeapon()->m_eWeaponType == WEAPONTYPE_COLT45 || + pPlayerPed->GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) { + pPlayerPed->bShakeFist = true; + } + } + } + } + } + } + /* Ped stuff done. Now vehicle stuff. */ + if (distanceUntilHit < 10.0f){ + if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || + pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_SLOW_DOWN_FOR_CARS){ + *pSpeed = min(*pSpeed, ABS(distanceUntilHit - 1.0f) * 0.1f * curSpeed); + pVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds = true; + if (distanceUntilHit < 2.0f){ + pVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT; + pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 3000; + } + } + } + } +} +#endif + bool CCarCtrl::MapCouldMoveInThisArea(float x, float y) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 2a62288d..b8f9f35b 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -419,7 +419,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_ped_flagD4 = false; m_ped_flagD8 = false; bIsPedDieAnimPlaying = false; - bIsFleeing = false; + bUsePedNodeSeek = false; m_ped_flagD40 = false; bScriptObjectiveCompleted = false; @@ -459,7 +459,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_ped_flagH40 = false; m_ped_flagH80 = false; - m_ped_flagI1 = false; + bShakeFist = false; bNoCriticalHits = false; m_ped_flagI4 = false; bHasAlreadyBeenRecorded = false; @@ -945,7 +945,7 @@ CPed::ClearLookFlag(void) { if (bIsLooking) { bIsLooking = false; bIsRestoringLook = true; - m_ped_flagI1 = false; + bShakeFist = false; m_pedIK.m_flags &= ~CPedIK::FLAG_2; if (IsPlayer()) @@ -2495,7 +2495,7 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_KILL_CHAR_ANY_MEANS: case OBJECTIVE_MUG_CHAR: m_pNextPathNode = nil; - bIsFleeing = false; + bUsePedNodeSeek = false; m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_pedInObjective = (CPed*)entity; m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); @@ -3682,7 +3682,7 @@ void CPed::ClearFlee(void) { RestorePreviousState(); - bIsFleeing = false; + bUsePedNodeSeek = false; m_standardTimer = 0; m_fleeTimer = 0; } @@ -4781,7 +4781,7 @@ CPed::SetFlee(CEntity* fleeFrom, int time) SetStoredState(); m_nPedState = PED_FLEE_ENTITY; - bIsFleeing = true; + bUsePedNodeSeek = true; SetMoveState(PEDMOVE_RUN); m_fleeFrom = fleeFrom; m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom); @@ -4817,7 +4817,7 @@ CPed::SetFlee(CVector2D &from, int time) m_fleeFromPosY = from.y; } - bIsFleeing = true; + bUsePedNodeSeek = true; m_pNextPathNode = nil; m_fleeTimer = CTimer::GetTimeInMilliseconds() + time; @@ -5289,7 +5289,7 @@ CPed::CollideWithPed(CPed *collideWith) doWeRun = false; SetFlee(collideWith, 5000); - bIsFleeing = true; + bUsePedNodeSeek = true; m_pNextPathNode = nil; if (!doWeRun) SetMoveState(PEDMOVE_WALK); @@ -6321,7 +6321,7 @@ SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVecto bool CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords) { - if (m_pNextPathNode || !bIsFleeing) + if (m_pNextPathNode || !bUsePedNodeSeek) return false; CVector ourPos = GetPosition(); @@ -6713,7 +6713,7 @@ CPed::Wait(void) SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget); if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) { - bIsFleeing = true; + bUsePedNodeSeek = true; m_pNextPathNode = nil; } if (m_nMoveState != PEDMOVE_RUN) @@ -6731,7 +6731,7 @@ CPed::Wait(void) SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget); if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) { - bIsFleeing = true; + bUsePedNodeSeek = true; m_pNextPathNode = nil; } SetMoveState(PEDMOVE_RUN); @@ -6939,7 +6939,7 @@ CPed::Seek(void) else bScriptObjectiveCompleted = true; - bIsFleeing = true; + bUsePedNodeSeek = true; } if (SeekFollowingPath(nil)) @@ -6979,7 +6979,7 @@ CPed::Flee(void) m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000; } - if (bIsFleeing) { + if (bUsePedNodeSeek) { CPathNode *realLastNode = nil; uint8 nextDirection = 0; uint8 curDirectionShouldBe = 9; // means not defined yet @@ -7032,7 +7032,7 @@ CPed::Flee(void) m_nPathState = nextDirection; m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000; } else { - bIsFleeing = false; + bUsePedNodeSeek = false; SetMoveState(PEDMOVE_RUN); Flee(); } diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 264a67a8..82423529 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -285,7 +285,7 @@ public: uint8 m_ped_flagD4 : 1; uint8 m_ped_flagD8 : 1; uint8 bIsPedDieAnimPlaying : 1; - uint8 bIsFleeing : 1; + uint8 bUsePedNodeSeek : 1; uint8 m_ped_flagD40 : 1; // reset when objective changes uint8 bScriptObjectiveCompleted : 1; @@ -325,7 +325,7 @@ public: uint8 m_ped_flagH40 : 1; uint8 m_ped_flagH80 : 1; - uint8 m_ped_flagI1 : 1; + uint8 bShakeFist : 1; // test shake hand at look entity uint8 bNoCriticalHits : 1; // if set, limbs won't came off uint8 m_ped_flagI4 : 1; uint8 bHasAlreadyBeenRecorded : 1; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 357e5603..accc6936 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -269,6 +269,8 @@ public: bool ShufflePassengersToMakeSpace(void); bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; } + + CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); } static bool &bWheelsOnlyCheat; static bool &bAllDodosCheat;