Merge pull request #186 from Nick007J/master

more CCarCtrl
This commit is contained in:
aap 2019-08-11 22:15:31 +02:00 committed by GitHub
commit b7471489fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 515 additions and 51 deletions

View File

@ -0,0 +1,5 @@
#include "common.h"
#include "patcher.h"
#include "AutoPilot.h"
WRAPPER void CAutoPilot::ModifySpeed(float) { EAXJMP(0x4137B0); }

View File

@ -64,25 +64,25 @@ public:
uint32 m_nNextRouteNode; uint32 m_nNextRouteNode;
uint32 m_nPrevRouteNode; uint32 m_nPrevRouteNode;
uint32 m_nTimeEnteredCurve; uint32 m_nTimeEnteredCurve;
uint32 m_nCurveSpeedScale; uint32 m_nTimeToSpendOnCurrentCurve;
uint32 m_nCurrentPathNodeInfo; uint32 m_nCurrentPathNodeInfo;
uint32 m_nNextPathNodeInfo; uint32 m_nNextPathNodeInfo;
uint32 m_nPreviousPathNodeInfo; uint32 m_nPreviousPathNodeInfo;
uint32 m_nTimeToStartMission; uint32 m_nTimeToStartMission;
uint32 m_nTimeSwitchedToRealPhysics; uint32 m_nAntiReverseTimer;
int8 m_nPreviousDirection; int8 m_nPreviousDirection;
int8 m_nCurrentDirection; int8 m_nCurrentDirection;
int8 m_nNextDirection; int8 m_nNextDirection;
int8 m_nPreviousLane;
int8 m_nCurrentLane; int8 m_nCurrentLane;
int8 m_nNextLane;
eCarDrivingStyle m_nDrivingStyle; eCarDrivingStyle m_nDrivingStyle;
eCarMission m_nCarMission; eCarMission m_nCarMission;
eCarTempAction m_nAnimationId; eCarTempAction m_nTempAction;
uint8 m_nAnimationTime; uint32 m_nTimeTempAction;
float m_fMaxTrafficSpeed; float m_fMaxTrafficSpeed;
uint8 m_nCruiseSpeed; uint8 m_nCruiseSpeed;
uint8 m_flag1 : 1; uint8 m_flag1 : 1;
uint8 m_flag2 : 1; uint8 m_bSlowedDownBecauseOfPeds : 1;
uint8 m_flag4 : 1; uint8 m_flag4 : 1;
uint8 m_flag8 : 1; uint8 m_flag8 : 1;
uint8 m_flag10 : 1; uint8 m_flag10 : 1;
@ -96,25 +96,27 @@ public:
m_nNextRouteNode = m_nPrevRouteNode; m_nNextRouteNode = m_nPrevRouteNode;
m_nCurrentRouteNode = m_nNextRouteNode; m_nCurrentRouteNode = m_nNextRouteNode;
m_nTimeEnteredCurve = 0; m_nTimeEnteredCurve = 0;
m_nCurveSpeedScale = 1000; m_nTimeToSpendOnCurrentCurve = 1000;
m_nPreviousPathNodeInfo = 0; m_nPreviousPathNodeInfo = 0;
m_nNextPathNodeInfo = m_nPreviousPathNodeInfo; m_nNextPathNodeInfo = m_nPreviousPathNodeInfo;
m_nCurrentPathNodeInfo = m_nNextPathNodeInfo; m_nCurrentPathNodeInfo = m_nNextPathNodeInfo;
m_nNextDirection = 1; m_nNextDirection = 1;
m_nCurrentDirection = m_nNextDirection; m_nCurrentDirection = m_nNextDirection;
m_nPreviousLane = m_nCurrentLane = 0; m_nCurrentLane = m_nNextLane = 0;
m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
m_nCarMission = MISSION_NONE; m_nCarMission = MISSION_NONE;
m_nAnimationId = TEMPACT_NONE; m_nTempAction = TEMPACT_NONE;
m_nCruiseSpeed = 10; m_nCruiseSpeed = 10;
m_fMaxTrafficSpeed = 10.0f; m_fMaxTrafficSpeed = 10.0f;
m_flag2 = false; m_bSlowedDownBecauseOfPeds = false;
m_flag1 = false; m_flag1 = false;
m_nPathFindNodesCount = 0; m_nPathFindNodesCount = 0;
m_pTargetCar = 0; m_pTargetCar = 0;
m_nTimeToStartMission = CTimer::GetTimeInMilliseconds(); m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
m_nTimeSwitchedToRealPhysics = m_nTimeToStartMission; m_nAntiReverseTimer = m_nTimeToStartMission;
m_flag8 = false; m_flag8 = false;
} }
void ModifySpeed(float);
}; };
static_assert(sizeof(CAutoPilot) == 0x70, "CAutoPilot: error"); static_assert(sizeof(CAutoPilot) == 0x70, "CAutoPilot: error");

View File

@ -2,8 +2,21 @@
#include "patcher.h" #include "patcher.h"
#include "CarAI.h" #include "CarAI.h"
#include "AutoPilot.h"
#include "Timer.h"
#include "Vehicle.h"
WRAPPER void CCarAI::UpdateCarAI(CVehicle*) { EAXJMP(0x413E50); } WRAPPER void CCarAI::UpdateCarAI(CVehicle*) { EAXJMP(0x413E50); }
WRAPPER void CCarAI::MakeWayForCarWithSiren(CVehicle *veh) { EAXJMP(0x416280); } WRAPPER void CCarAI::MakeWayForCarWithSiren(CVehicle *veh) { EAXJMP(0x416280); }
WRAPPER eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() { EAXJMP(0x415E30); } WRAPPER eCarMission CCarAI::FindPoliceCarMissionForWantedLevel() { EAXJMP(0x415E30); }
WRAPPER int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle*) { EAXJMP(0x415EB0); } WRAPPER int32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle*) { EAXJMP(0x415EB0); }
WRAPPER void CCarAI::AddPoliceOccupants(CVehicle*) { EAXJMP(0x415C60); } WRAPPER void CCarAI::AddPoliceOccupants(CVehicle*) { EAXJMP(0x415C60); }
void CCarAI::CarHasReasonToStop(CVehicle* pVehicle)
{
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
}
STARTPATCHES
InjectHook(0x415B00, &CCarAI::CarHasReasonToStop, PATCH_JUMP);
ENDPATCHES

View File

@ -12,4 +12,5 @@ public:
static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*); static int32 FindPoliceCarSpeedForWantedLevel(CVehicle*);
static eCarMission FindPoliceCarMissionForWantedLevel(); static eCarMission FindPoliceCarMissionForWantedLevel();
static void AddPoliceOccupants(CVehicle*); static void AddPoliceOccupants(CVehicle*);
static void CarHasReasonToStop(CVehicle*);
}; };

View File

@ -6,8 +6,11 @@
#include "Camera.h" #include "Camera.h"
#include "CarAI.h" #include "CarAI.h"
#include "CarGen.h" #include "CarGen.h"
#include "Cranes.h"
#include "Curves.h" #include "Curves.h"
#include "CutsceneMgr.h" #include "CutsceneMgr.h"
#include "Gangs.h"
#include "Garages.h"
#include "General.h" #include "General.h"
#include "IniFile.h" #include "IniFile.h"
#include "ModelIndices.h" #include "ModelIndices.h"
@ -15,14 +18,20 @@
#include "Ped.h" #include "Ped.h"
#include "PlayerInfo.h" #include "PlayerInfo.h"
#include "PlayerPed.h" #include "PlayerPed.h"
#include "Pools.h"
#include "Renderer.h"
#include "RoadBlocks.h"
#include "Timer.h" #include "Timer.h"
#include "TrafficLights.h"
#include "Streaming.h"
#include "VisibilityPlugins.h" #include "VisibilityPlugins.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "Wanted.h" #include "Wanted.h"
#include "World.h" #include "World.h"
#include "Zones.h" #include "Zones.h"
#define LANE_WIDTH 5.0f #define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS 51.0f
#define DISTANCE_TO_SCAN_FOR_DANGER 11.0f
#define INFINITE_Z 1000000000.0f #define INFINITE_Z 1000000000.0f
int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38; int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38;
@ -36,20 +45,22 @@ int32 &CCarCtrl::NumParkedCars = *(int32*)0x8F29E0;
int8 &CCarCtrl::CountDownToCarsAtStart = *(int8*)0x95CD63; int8 &CCarCtrl::CountDownToCarsAtStart = *(int8*)0x95CD63;
int32 &CCarCtrl::MaxNumberOfCarsInUse = *(int32*)0x5EC8B8; int32 &CCarCtrl::MaxNumberOfCarsInUse = *(int32*)0x5EC8B8;
uint32 &CCarCtrl::LastTimeLawEnforcerCreated = *(uint32*)0x8F5FF0; uint32 &CCarCtrl::LastTimeLawEnforcerCreated = *(uint32*)0x8F5FF0;
int32 (&CCarCtrl::TotalNumOfCarsOfRating)[7] = *(int32(*)[7])*(uintptr*)0x8F1A60;
int32 (&CCarCtrl::NextCarOfRating)[7] = *(int32(*)[7])*(uintptr*)0x9412AC;
int32 (&CCarCtrl::CarArrays)[7][256] = *(int32(*)[7][256])*(uintptr*)0x6EB860;
CVehicle* (&apCarsToKeep)[MAX_CARS_TO_KEEP] = *(CVehicle*(*)[MAX_CARS_TO_KEEP])0x70D830;
WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); } WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); }
WRAPPER void CCarCtrl::AddToCarArray(int32 id, int32 vehclass) { EAXJMP(0x4182F0); }
WRAPPER void CCarCtrl::UpdateCarCount(CVehicle*, bool) { EAXJMP(0x4202E0); } WRAPPER void CCarCtrl::UpdateCarCount(CVehicle*, bool) { EAXJMP(0x4202E0); }
WRAPPER int32 CCarCtrl::ChooseCarModel(int32 vehclass) { EAXJMP(0x418110); }
WRAPPER bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle*, CVector, bool) { EAXJMP(0x41FA00); } WRAPPER bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle*, CVector, bool) { EAXJMP(0x41FA00); }
WRAPPER void CCarCtrl::JoinCarWithRoadSystem(CVehicle*) { EAXJMP(0x41F820); } WRAPPER void CCarCtrl::JoinCarWithRoadSystem(CVehicle*) { EAXJMP(0x41F820); }
WRAPPER void CCarCtrl::SteerAICarWithPhysics(CVehicle*) { EAXJMP(0x41DA60); } WRAPPER void CCarCtrl::SteerAICarWithPhysics(CVehicle*) { EAXJMP(0x41DA60); }
WRAPPER void CCarCtrl::UpdateCarOnRails(CVehicle*) { EAXJMP(0x418880); }
WRAPPER void CCarCtrl::ScanForPedDanger(CVehicle *veh) { EAXJMP(0x418F40); }
WRAPPER void CCarCtrl::RemoveFromInterestingVehicleList(CVehicle* v) { EAXJMP(0x41F7A0); } WRAPPER void CCarCtrl::RemoveFromInterestingVehicleList(CVehicle* v) { EAXJMP(0x41F7A0); }
WRAPPER void CCarCtrl::GenerateEmergencyServicesCar(void) { EAXJMP(0x41FC50); } WRAPPER void CCarCtrl::GenerateEmergencyServicesCar(void) { EAXJMP(0x41FC50); }
WRAPPER int32 CCarCtrl::ChooseModel(CZoneInfo*, CVector*, int*) { EAXJMP(0x417EC0); } WRAPPER void CCarCtrl::PickNextNodeAccordingStrategy(CVehicle*) { EAXJMP(0x41BA50); }
WRAPPER int32 CCarCtrl::ChoosePoliceCarModel(void) { EAXJMP(0x4181F0); } 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 void
CCarCtrl::GenerateRandomCars() CCarCtrl::GenerateRandomCars()
@ -289,12 +300,12 @@ CCarCtrl::GenerateOneRandomCar()
} }
pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed; pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed;
pCar->AutoPilot.m_nCarMission = MISSION_CRUISE; pCar->AutoPilot.m_nCarMission = MISSION_CRUISE;
pCar->AutoPilot.m_nAnimationId = TEMPACT_NONE; pCar->AutoPilot.m_nTempAction = TEMPACT_NONE;
pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
break; break;
} }
case COPS: case COPS:
pCar->AutoPilot.m_nAnimationId = TEMPACT_NONE; pCar->AutoPilot.m_nTempAction = TEMPACT_NONE;
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel != 0){ if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel != 0){
pCar->AutoPilot.m_nCruiseSpeed = CCarAI::FindPoliceCarSpeedForWantedLevel(pCar); pCar->AutoPilot.m_nCruiseSpeed = CCarAI::FindPoliceCarSpeedForWantedLevel(pCar);
pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed / 2; pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed / 2;
@ -317,7 +328,7 @@ CCarCtrl::GenerateOneRandomCar()
if (pCar && pCar->GetModelIndex() == MI_MRWHOOP) if (pCar && pCar->GetModelIndex() == MI_MRWHOOP)
pCar->m_bSirenOrAlarm = true; pCar->m_bSirenOrAlarm = true;
pCar->AutoPilot.m_nNextPathNodeInfo = connectionId; pCar->AutoPilot.m_nNextPathNodeInfo = connectionId;
pCar->AutoPilot.m_nCurrentLane = pCar->AutoPilot.m_nPreviousLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad; pCar->AutoPilot.m_nNextLane = pCar->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;
CColBox* boundingBox = &CModelInfo::GetModelInfo(pCar->GetModelIndex())->GetColModel()->boundingBox; CColBox* boundingBox = &CModelInfo::GetModelInfo(pCar->GetModelIndex())->GetColModel()->boundingBox;
float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2; float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2;
float distanceBetweenNodes = (pCurNode->pos - pNextNode->pos).Magnitude2D(); float distanceBetweenNodes = (pCurNode->pos - pNextNode->pos).Magnitude2D();
@ -363,27 +374,21 @@ CCarCtrl::GenerateOneRandomCar()
float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dirY; float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dirY;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo];
float currentLaneCoefficient = (pCurrentLink->numLeftLanes == 0) ? (0.5f - 0.5f * pCurrentLink->numRightLanes) :
((pCurrentLink->numRightLanes == 0) ? (0.5f - 0.5f * pCurrentLink->numLeftLanes) : 0.5f);
float roadShiftAlongCurrentNode = (pCar->AutoPilot.m_nPreviousLane + currentLaneCoefficient) * LANE_WIDTH;
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo];
float nextLaneCoefficient = (pNextLink->numLeftLanes == 0) ? (0.5f - 0.5f * pNextLink->numRightLanes) :
((pNextLink->numRightLanes == 0) ? (0.5f - 0.5f * pNextLink->numLeftLanes) : 0.5f);
float roadShiftAlongNextNode = (pCar->AutoPilot.m_nCurrentLane + nextLaneCoefficient) * LANE_WIDTH;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + roadShiftAlongCurrentNode * currentPathLinkForwardY, pCurrentLink->posX + GetOffsetOfLaneFromCenterOfRoad(pCar->AutoPilot.m_nCurrentLane, pCurrentLink) * currentPathLinkForwardY,
pCurrentLink->posY - roadShiftAlongCurrentNode * currentPathLinkForwardX, pCurrentLink->posY - GetOffsetOfLaneFromCenterOfRoad(pCar->AutoPilot.m_nCurrentLane, pCurrentLink) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + roadShiftAlongNextNode * nextPathLinkForwardY, pNextLink->posX + GetOffsetOfLaneFromCenterOfRoad(pCar->AutoPilot.m_nNextLane, pNextLink) * nextPathLinkForwardY,
pNextLink->posY - roadShiftAlongNextNode * nextPathLinkForwardX, pNextLink->posY - GetOffsetOfLaneFromCenterOfRoad(pCar->AutoPilot.m_nNextLane, pNextLink) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurrentLink->dirX * pCar->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurrentLink->dirX * pCar->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurrentLink->dirY * pCar->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurrentLink->dirY * pCar->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pCar->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dirX * pCar->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pCar->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dirY * pCar->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pCar->AutoPilot.m_nCurveSpeedScale = CCurves::CalcSpeedScaleFactor( pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
&positionOnNextLinkIncludingLane, &positionOnNextLinkIncludingLane,
directionCurrentLinkX, directionCurrentLinkY, directionCurrentLinkX, directionCurrentLinkY,
@ -393,13 +398,11 @@ CCarCtrl::GenerateOneRandomCar()
/* Casting timer to float is very unwanted. In this case it's not awful */ /* 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). */ /* but in CAutoPilot::ModifySpeed it can even cause crashes (see SilentPatch). */
pCar->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - pCar->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
(uint32)((0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nCurveSpeedScale); (uint32)((0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve);
#else #else
pCar->AutoPilot.m_nTotalSpeedScaleFactor = CTimer::GetTimeInMilliseconds() - pCar->AutoPilot.m_nTotalSpeedScaleFactor = CTimer::GetTimeInMilliseconds() -
(0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nSpeedScaleFactor; (0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nSpeedScaleFactor;
#endif #endif
uint32 timeAlreadyInCurve = CTimer::GetTimeInMilliseconds() - pCar->AutoPilot.m_nTimeEnteredCurve;
float positionAlongCurve = (float)timeAlreadyInCurve / pCar->AutoPilot.m_nCurveSpeedScale;
CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f); CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f);
CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f); CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f);
CVector positionIncludingCurve; CVector positionIncludingCurve;
@ -409,8 +412,8 @@ CCarCtrl::GenerateOneRandomCar()
&positionOnNextLinkIncludingLane, &positionOnNextLinkIncludingLane,
&directionCurrentLink, &directionCurrentLink,
&directionNextLink, &directionNextLink,
positionAlongCurve, GetPositionAlongCurrentCurve(pCar),
pCar->AutoPilot.m_nCurveSpeedScale, pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve,
&positionIncludingCurve, &positionIncludingCurve,
&directionIncludingCurve &directionIncludingCurve
); );
@ -512,6 +515,361 @@ CCarCtrl::GenerateOneRandomCar()
LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds(); LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds();
} }
int32
CCarCtrl::ChooseModel(CZoneInfo* pZone, CVector* pPos, int* pClass) {
int32 model = -1;;
while (model == -1 || !CStreaming::HasModelLoaded(model)){
int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
if (rnd < pZone->carThreshold[0])
model = CCarCtrl::ChooseCarModel((*pClass = POOR));
else if (rnd < pZone->carThreshold[1])
model = CCarCtrl::ChooseCarModel((*pClass = RICH));
else if (rnd < pZone->carThreshold[2])
model = CCarCtrl::ChooseCarModel((*pClass = EXEC));
else if (rnd < pZone->carThreshold[3])
model = CCarCtrl::ChooseCarModel((*pClass = WORKER));
else if (rnd < pZone->carThreshold[4])
model = CCarCtrl::ChooseCarModel((*pClass = SPECIAL));
else if (rnd < pZone->carThreshold[5])
model = CCarCtrl::ChooseCarModel((*pClass = BIG));
else if (rnd < pZone->copThreshold)
*pClass = COPS, model = CCarCtrl::ChoosePoliceCarModel();
else if (rnd < pZone->gangThreshold[0])
model = CCarCtrl::ChooseGangCarModel((*pClass = MAFIA) - MAFIA);
else if (rnd < pZone->gangThreshold[1])
model = CCarCtrl::ChooseGangCarModel((*pClass = TRIAD) - MAFIA);
else if (rnd < pZone->gangThreshold[2])
model = CCarCtrl::ChooseGangCarModel((*pClass = DIABLO) - MAFIA);
else if (rnd < pZone->gangThreshold[3])
model = CCarCtrl::ChooseGangCarModel((*pClass = YAKUZA) - MAFIA);
else if (rnd < pZone->gangThreshold[4])
model = CCarCtrl::ChooseGangCarModel((*pClass = YARDIE) - MAFIA);
else if (rnd < pZone->gangThreshold[5])
model = CCarCtrl::ChooseGangCarModel((*pClass = COLOMB) - MAFIA);
else if (rnd < pZone->gangThreshold[6])
model = CCarCtrl::ChooseGangCarModel((*pClass = NINES) - MAFIA);
else if (rnd < pZone->gangThreshold[7])
model = CCarCtrl::ChooseGangCarModel((*pClass = GANG8) - MAFIA);
else if (rnd < pZone->gangThreshold[8])
model = CCarCtrl::ChooseGangCarModel((*pClass = GANG9) - MAFIA);
else
model = CCarCtrl::ChooseCarModel((*pClass = TAXI));
}
return model;
}
int32
CCarCtrl::ChooseCarModel(int32 vehclass)
{
int32 model = -1;
switch (vehclass) {
case POOR:
case RICH:
case EXEC:
case WORKER:
case SPECIAL:
case BIG:
case TAXI:
{
if (TotalNumOfCarsOfRating[vehclass] == 0)
debug("ChooseCarModel : No cars of type %d have been declared\n");
model = CarArrays[vehclass][NextCarOfRating[vehclass]];
int32 total = TotalNumOfCarsOfRating[vehclass];
NextCarOfRating[vehclass] += 1 + CGeneral::GetRandomNumberInRange(0, total - 1);
while (NextCarOfRating[vehclass] >= total)
NextCarOfRating[vehclass] -= total;
//NextCarOfRating[vehclass] %= total;
TotalNumOfCarsOfRating[vehclass] = total; /* why... */
}
default:
break;
}
return model;
}
int32
CCarCtrl::ChoosePoliceCarModel(void)
{
if (FindPlayerPed()->m_pWanted->AreSwatRequired() &&
CStreaming::HasModelLoaded(MI_ENFORCER) &&
CStreaming::HasModelLoaded(MI_POLICE))
return ((CGeneral::GetRandomNumber() & 0xF) == 0) ? MI_ENFORCER : MI_POLICE;
if (FindPlayerPed()->m_pWanted->AreFbiRequired() &&
CStreaming::HasModelLoaded(MI_FBICAR) &&
CStreaming::HasModelLoaded(MI_FBI))
return MI_FBICAR;
if (FindPlayerPed()->m_pWanted->AreArmyRequired() &&
CStreaming::HasModelLoaded(MI_RHINO) &&
CStreaming::HasModelLoaded(MI_BARRACKS) &&
CStreaming::HasModelLoaded(MI_RHINO))
return CGeneral::GetRandomTrueFalse() ? MI_BARRACKS : MI_RHINO;
return MI_POLICE;
}
int32
CCarCtrl::ChooseGangCarModel(int32 gang)
{
if (CStreaming::HasModelLoaded(MI_GANG01 + 2 * gang) &&
CStreaming::HasModelLoaded(MI_GANG02 + 2 * gang))
return CGangs::GetGangVehicleModel(gang);
return -1;
}
void
CCarCtrl::AddToCarArray(int32 id, int32 vehclass)
{
CarArrays[vehclass][TotalNumOfCarsOfRating[vehclass]++] = id;
}
void
CCarCtrl::RemoveDistantCars()
{
uint32 i = CPools::GetVehiclePool()->GetSize();
while (--i){
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
PossiblyRemoveVehicle(pVehicle);
if (pVehicle->bCreateRoadBlockPeds){
if ((pVehicle->GetPosition() - FindPlayerCentreOfWorld(CWorld::PlayerInFocus)).Magnitude2D() < DISTANCE_TO_SPAWN_ROADBLOCK_PEDS) {
CRoadBlocks::GenerateRoadBlockCopsForCar(pVehicle, pVehicle->m_nRoadblockType, pVehicle->m_nRoadblockNode);
pVehicle->bCreateRoadBlockPeds = false;
}
}
}
}
void
CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
{
CVector vecPlayerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
/* BUG: this variable is initialized only in if-block below but can be used outside of it. */
if (!IsThisVehicleInteresting(pVehicle) && !pVehicle->bIsLocked &&
pVehicle->CanBeDeleted() && !CCranes::IsThisCarBeingTargettedByAnyCrane(pVehicle)){
if (pVehicle->bFadeOut && CVisibilityPlugins::GetClumpAlpha(pVehicle->GetClump()) == 0){
CWorld::Remove(pVehicle);
delete pVehicle;
return;
}
float distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D();
float threshold = 50.0f;
if (pVehicle->GetIsOnScreen() ||
TheCamera.Cams[TheCamera.ActiveCam].LookingLeft ||
TheCamera.Cams[TheCamera.ActiveCam].LookingRight ||
TheCamera.Cams[TheCamera.ActiveCam].LookingBehind ||
TheCamera.GetLookDirection() == 0 ||
pVehicle->VehicleCreatedBy == PARKED_VEHICLE ||
pVehicle->GetModelIndex() == MI_AMBULAN ||
pVehicle->GetModelIndex() == MI_FIRETRUCK ||
pVehicle->bIsLawEnforcer ||
pVehicle->bIsCarParkVehicle
){
threshold = 130.0f * TheCamera.GenerationDistMultiplier;
}
if (pVehicle->bExtendedRange)
threshold *= 1.5f;
if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(&pVehicle->GetPosition())){
if (pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)){
pVehicle->bFadeOut = true;
}else{
CWorld::Remove(pVehicle);
delete pVehicle;
}
return;
}
}
if ((pVehicle->m_status == STATUS_SIMPLE || pVehicle->m_status == 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 &&
!IsThisVehicleInteresting(pVehicle) &&
!pVehicle->bIsLocked &&
!CTrafficLights::ShouldCarStopForLight(pVehicle, true) &&
!CTrafficLights::ShouldCarStopForBridge(pVehicle) &&
!CGarages::IsPointWithinHideOutGarage(&pVehicle->GetPosition())){
CWorld::Remove(pVehicle);
delete pVehicle;
return;
}
if (pVehicle->m_status != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0)
return;
if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&
(!pVehicle->GetIsOnScreen() || CRenderer::IsEntityCullZoneVisible(pVehicle))){
if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){
if (!CGarages::IsPointWithinHideOutGarage(&pVehicle->GetPosition())){
CWorld::Remove(pVehicle);
delete pVehicle;
}
}
}
}
int32
CCarCtrl::CountCarsOfType(int32 mi)
{
int32 total = 0;
uint32 i = CPools::GetVehiclePool()->GetSize();
while (i--){
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
if (pVehicle->GetModelIndex() == mi)
total++;
}
return total;
}
bool
CCarCtrl::IsThisVehicleInteresting(CVehicle* pVehicle)
{
for (int i = 0; i < MAX_CARS_TO_KEEP; i++) {
if (apCarsToKeep[i] == pVehicle)
return true;
}
return false;
}
void
CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
{
if (pVehicle->AutoPilot.m_nTempAction == TEMPACT_WAIT){
pVehicle->SetMoveSpeed(0.0f, 0.0f, 0.0f);
pVehicle->AutoPilot.ModifySpeed(0.0f);
if (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTempAction){
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nAntiReverseTimer = 0;
pVehicle->AutoPilot.m_nTimeToStartMission = 0;
}
return;
}
SlowCarOnRailsDownForTrafficAndLights(pVehicle);
if (pVehicle->AutoPilot.m_nTimeEnteredCurve + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve <= CTimer::GetTimeInMilliseconds())
PickNextNodeAccordingStrategy(pVehicle);
if (pVehicle->m_status == STATUS_PHYSICS)
return;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
float currentPathLinkForwardX = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection;
float currentPathLinkForwardY = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection;
float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection;
float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection;
CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + GetOffsetOfLaneFromCenterOfRoad(pVehicle->AutoPilot.m_nCurrentLane, pCurrentLink) * currentPathLinkForwardY,
pCurrentLink->posY - GetOffsetOfLaneFromCenterOfRoad(pVehicle->AutoPilot.m_nCurrentLane, pCurrentLink) * currentPathLinkForwardX,
0.0f);
CVector positionOnNextLinkIncludingLane(
pNextLink->posX + GetOffsetOfLaneFromCenterOfRoad(pVehicle->AutoPilot.m_nNextLane, pNextLink) * nextPathLinkForwardY,
pNextLink->posY - GetOffsetOfLaneFromCenterOfRoad(pVehicle->AutoPilot.m_nNextLane, pNextLink) * nextPathLinkForwardX,
0.0f);
CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
CVector positionIncludingCurve;
CVector directionIncludingCurve;
CCurves::CalcCurvePoint(
&positionOnCurrentLinkIncludingLane,
&positionOnNextLinkIncludingLane,
&directionCurrentLink,
&directionNextLink,
GetPositionAlongCurrentCurve(pVehicle),
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve,
&positionIncludingCurve,
&directionIncludingCurve
);
positionIncludingCurve.z = 15.0f;
DragCarToPoint(pVehicle, &positionIncludingCurve);
pVehicle->SetMoveSpeed(directionIncludingCurve / 60.0f);
}
float
CCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle)
{
if (pVehicle->AutoPilot.m_nDrivingStyle == MISSION_RAMPLAYER_FARAWAY ||
pVehicle->AutoPilot.m_nDrivingStyle == 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;
float top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER;
float bottom = pVehicle->GetPosition().y + DISTANCE_TO_SCAN_FOR_DANGER;
int xstart = max(0, CWorld::GetSectorIndexX(left));
int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));
int ystart = max(0, CWorld::GetSectorIndexY(top));
int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));
assert(xstart <= xend);
assert(ystart <= yend);
float maxSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
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);
}
}
pVehicle->bWarnedPeds = true;
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS)
return maxSpeed;
return (maxSpeed + pVehicle->AutoPilot.m_nDrivingStyle) / 2;
}
void
CCarCtrl::ScanForPedDanger(CVehicle* pVehicle)
{
bool storedSlowDownFlag = pVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds;
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;
float bottom = pVehicle->GetPosition().y + DISTANCE_TO_SCAN_FOR_DANGER;
int xstart = max(0, CWorld::GetSectorIndexX(left));
int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));
int ystart = max(0, CWorld::GetSectorIndexY(top));
int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));
assert(xstart <= xend);
assert(ystart <= yend);
float maxSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
CWorld::AdvanceCurrentScanCode();
for (int y = ystart; y <= yend; y++) {
for (int x = xstart; x <= xend; x++) {
CSector* s = CWorld::GetSector(x, y);
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);
}
}
pVehicle->bWarnedPeds = true;
pVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds = storedSlowDownFlag;
}
void
CCarCtrl::SlowCarOnRailsDownForTrafficAndLights(CVehicle* pVehicle)
{
float maxSpeed;
if (CTrafficLights::ShouldCarStopForLight(pVehicle, false) || CTrafficLights::ShouldCarStopForBridge(pVehicle)){
CCarAI::CarHasReasonToStop(pVehicle);
maxSpeed = 0.0f;
}else{
maxSpeed = FindMaximumSpeedForThisCarInTraffic(pVehicle);
}
float curSpeed = pVehicle->AutoPilot.m_fMaxTrafficSpeed;
if (maxSpeed >= curSpeed){
if (maxSpeed > curSpeed)
pVehicle->AutoPilot.ModifySpeed(min(maxSpeed, curSpeed + 0.05f * CTimer::GetTimeStep()));
}else{
if (curSpeed == 0.0f)
return;
if (curSpeed >= 0.1f)
pVehicle->AutoPilot.ModifySpeed(max(maxSpeed, curSpeed - 0.5f * CTimer::GetTimeStep()));
else if (curSpeed != 0.0f) /* no need to check */
pVehicle->AutoPilot.ModifySpeed(0.0f);
}
}
bool bool
CCarCtrl::MapCouldMoveInThisArea(float x, float y) CCarCtrl::MapCouldMoveInThisArea(float x, float y)
{ {
@ -522,4 +880,8 @@ CCarCtrl::MapCouldMoveInThisArea(float x, float y)
STARTPATCHES STARTPATCHES
InjectHook(0x416580, &CCarCtrl::GenerateRandomCars, PATCH_JUMP); InjectHook(0x416580, &CCarCtrl::GenerateRandomCars, PATCH_JUMP);
InjectHook(0x417EC0, &CCarCtrl::ChooseModel, PATCH_JUMP);
InjectHook(0x418320, &CCarCtrl::RemoveDistantCars, PATCH_JUMP);
InjectHook(0x418430, &CCarCtrl::PossiblyRemoveVehicle, PATCH_JUMP);
InjectHook(0x418C10, &CCarCtrl::FindMaximumSpeedForThisCarInTraffic, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -1,8 +1,16 @@
#pragma once #pragma once
#include "PathFind.h"
#include "Vehicle.h"
class CVehicle;
class CZoneInfo; class CZoneInfo;
enum{
MAX_CARS_TO_KEEP = 2,
MAX_CAR_MODELS_IN_ARRAY = 256,
};
#define LANE_WIDTH 5.0f
class CCarCtrl class CCarCtrl
{ {
enum eCarClass { enum eCarClass {
@ -42,6 +50,30 @@ public:
static void GenerateEmergencyServicesCar(void); static void GenerateEmergencyServicesCar(void);
static int32 ChooseModel(CZoneInfo*, CVector*, int*); static int32 ChooseModel(CZoneInfo*, CVector*, int*);
static int32 ChoosePoliceCarModel(void); static int32 ChoosePoliceCarModel(void);
static int32 ChooseGangCarModel(int32 gang);
static void RemoveDistantCars(void);
static void PossiblyRemoveVehicle(CVehicle*);
static bool IsThisVehicleInteresting(CVehicle*);
static int32 CountCarsOfType(int32 mi);
static void SlowCarOnRailsDownForTrafficAndLights(CVehicle*);
static void PickNextNodeAccordingStrategy(CVehicle*);
static void DragCarToPoint(CVehicle*, CVector*);
static float FindMaximumSpeedForThisCarInTraffic(CVehicle*);
static void SlowCarDownForCarsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float);
static void SlowCarDownForPedsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float);
static float GetOffsetOfLaneFromCenterOfRoad(int8 lane, CCarPathLink* pLink)
{
return (lane + ((pLink->numLeftLanes == 0) ? (0.5f - 0.5f * pLink->numRightLanes) :
((pLink->numRightLanes == 0) ? (0.5f - 0.5f * pLink->numLeftLanes) : 0.5f))) * LANE_WIDTH;
}
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{
uint32 timeInCurve = CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeEnteredCurve;
return (float)timeInCurve / pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;
}
static int32 &NumLawEnforcerCars; static int32 &NumLawEnforcerCars;
static int32 &NumAmbulancesOnDuty; static int32 &NumAmbulancesOnDuty;
@ -54,4 +86,9 @@ public:
static int8 &CountDownToCarsAtStart; static int8 &CountDownToCarsAtStart;
static int32 &MaxNumberOfCarsInUse; static int32 &MaxNumberOfCarsInUse;
static uint32 &LastTimeLawEnforcerCreated; static uint32 &LastTimeLawEnforcerCreated;
static int32 (&TotalNumOfCarsOfRating)[7];
static int32 (&NextCarOfRating)[7];
static int32 (&CarArrays)[7][MAX_CAR_MODELS_IN_ARRAY];
}; };
extern CVehicle* (&apCarsToKeep)[MAX_CARS_TO_KEEP];

5
src/control/Cranes.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "common.h"
#include "patcher.h"
#include "Cranes.h"
WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); }

10
src/control/Cranes.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "common.h"
class CVehicle;
class CCranes
{
public:
static bool IsThisCarBeingTargettedByAnyCrane(CVehicle*);
};

View File

@ -25,7 +25,7 @@ void CGangs::Initialize(void)
Gang[GANG_8].m_nVehicleMI = -1; Gang[GANG_8].m_nVehicleMI = -1;
} }
void CGangs::SetGangVehicleModel(int16 gang, int model) void CGangs::SetGangVehicleModel(int16 gang, int32 model)
{ {
GetGangInfo(gang)->m_nVehicleMI = model; GetGangInfo(gang)->m_nVehicleMI = model;
} }

View File

@ -33,7 +33,8 @@ class CGangs
{ {
public: public:
static void Initialize(void); static void Initialize(void);
static void SetGangVehicleModel(int16, int); static void SetGangVehicleModel(int16, int32);
static int32 GetGangVehicleModel(int16 gang) { return Gang[gang].m_nVehicleMI; }
static void SetGangWeapons(int16, eWeaponType, eWeaponType); static void SetGangWeapons(int16, eWeaponType, eWeaponType);
static void SetGangPedModelOverride(int16, int8); static void SetGangPedModelOverride(int16, int8);
static int8 GetGangPedModelOverride(int16); static int8 GetGangPedModelOverride(int16);

View File

@ -69,6 +69,7 @@ bool CGarages::HasCarBeenCrushed(int32 handle)
} }
WRAPPER void CGarages::TriggerMessage(char *text, int16, uint16 time, int16) { EAXJMP(0x426B20); } WRAPPER void CGarages::TriggerMessage(char *text, int16, uint16 time, int16) { EAXJMP(0x426B20); }
WRAPPER bool CGarages::IsPointWithinHideOutGarage(CVector*) { EAXJMP(0x428260); }
#if 0 #if 0
WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); } WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); }

View File

@ -25,4 +25,5 @@ public:
static void TriggerMessage(char *text, int16, uint16 time, int16); static void TriggerMessage(char *text, int16, uint16 time, int16);
static void PrintMessages(void); static void PrintMessages(void);
static bool HasCarBeenCrushed(int32); static bool HasCarBeenCrushed(int32);
static bool IsPointWithinHideOutGarage(CVector*);
}; };

View File

@ -2,6 +2,8 @@
#include "Treadable.h" #include "Treadable.h"
class CVehicle;
enum enum
{ {
PATH_CAR = 0, PATH_CAR = 0,

View File

@ -0,0 +1,5 @@
#include "common.h"
#include "patcher.h"
#include "RoadBlocks.h"
WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); }

10
src/control/RoadBlocks.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "common.h"
class CVehicle;
class CRoadBlocks
{
public:
static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16);
};

View File

@ -1924,7 +1924,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
boat->m_status = STATUS_ABANDONED; boat->m_status = STATUS_ABANDONED;
boat->bIsLocked = true; boat->bIsLocked = true;
boat->AutoPilot.m_nCarMission = MISSION_NONE; boat->AutoPilot.m_nCarMission = MISSION_NONE;
boat->AutoPilot.m_nAnimationId = TEMPACT_NONE; /* Animation ID? */ boat->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */
boat->AutoPilot.m_nCruiseSpeed = boat->AutoPilot.m_fMaxTrafficSpeed = 20.0f; boat->AutoPilot.m_nCruiseSpeed = boat->AutoPilot.m_fMaxTrafficSpeed = 20.0f;
CWorld::Add(boat); CWorld::Add(boat);
handle = CPools::GetVehiclePool()->GetIndex(boat); handle = CPools::GetVehiclePool()->GetIndex(boat);
@ -1943,10 +1943,10 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
car->bIsLocked = true; car->bIsLocked = true;
CCarCtrl::JoinCarWithRoadSystem(car); CCarCtrl::JoinCarWithRoadSystem(car);
car->AutoPilot.m_nCarMission = MISSION_NONE; car->AutoPilot.m_nCarMission = MISSION_NONE;
car->AutoPilot.m_nAnimationId = TEMPACT_NONE; /* Animation ID? */ car->AutoPilot.m_nTempAction = TEMPACT_NONE; /* Animation ID? */
car->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS; car->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f; car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f;
car->AutoPilot.m_nPreviousLane = car->AutoPilot.m_nCurrentLane = 0; car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0;
car->bEngineOn = false; car->bEngineOn = false;
car->m_level = CTheZones::GetLevelFromPosition(pos); car->m_level = CTheZones::GetLevelFromPosition(pos);
car->bHasBeenOwnedByPlayer = true; car->bHasBeenOwnedByPlayer = true;

View File

@ -2,8 +2,11 @@
#include "patcher.h" #include "patcher.h"
#include "TrafficLights.h" #include "TrafficLights.h"
#include "Timer.h" #include "Timer.h"
#include "Vehicle.h"
WRAPPER void CTrafficLights::DisplayActualLight(CEntity *ent) { EAXJMP(0x455800); } WRAPPER void CTrafficLights::DisplayActualLight(CEntity *ent) { EAXJMP(0x455800); }
WRAPPER bool CTrafficLights::ShouldCarStopForLight(CVehicle*, bool) { EAXJMP(0x455350); }
WRAPPER bool CTrafficLights::ShouldCarStopForBridge(CVehicle*) { EAXJMP(0x456460); }
uint8 uint8
CTrafficLights::LightForPeds(void) CTrafficLights::LightForPeds(void)

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
class CEntity; class CEntity;
class CVehicle;
enum { enum {
PED_LIGHTS_WALK, PED_LIGHTS_WALK,
@ -13,4 +14,6 @@ class CTrafficLights
public: public:
static void DisplayActualLight(CEntity *ent); static void DisplayActualLight(CEntity *ent);
static uint8 LightForPeds(void); static uint8 LightForPeds(void);
static bool ShouldCarStopForLight(CVehicle*, bool);
static bool ShouldCarStopForBridge(CVehicle*);
}; };

View File

@ -114,6 +114,8 @@ public:
// not too sure about all these... // not too sure about all these...
static uint16 GetRandomNumber(void) static uint16 GetRandomNumber(void)
{ return myrand() & MYRAND_MAX; } { return myrand() & MYRAND_MAX; }
static bool GetRandomTrueFalse(void)
{ return GetRandomNumber() < MYRAND_MAX / 2; }
// Probably don't want to ever reach high // Probably don't want to ever reach high
static float GetRandomNumberInRange(float low, float high) static float GetRandomNumberInRange(float low, float high)
{ return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); } { return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); }

View File

@ -312,7 +312,7 @@ CAutomobile::ProcessControl(void)
CVisibilityPlugins::SetClumpAlpha((RpClump*)m_rwObject, clumpAlpha); CVisibilityPlugins::SetClumpAlpha((RpClump*)m_rwObject, clumpAlpha);
AutoPilot.m_flag1 = false; AutoPilot.m_flag1 = false;
AutoPilot.m_flag2 = false; AutoPilot.m_bSlowedDownBecauseOfPeds = false;
// Set Center of Mass to make car more stable // Set Center of Mass to make car more stable
if(strongGrip1 || bCheat3) if(strongGrip1 || bCheat3)
@ -3930,7 +3930,7 @@ CAutomobile::PlayCarHorn(void)
void void
CAutomobile::PlayHornIfNecessary(void) CAutomobile::PlayHornIfNecessary(void)
{ {
if(AutoPilot.m_flag2 || if(AutoPilot.m_bSlowedDownBecauseOfPeds ||
AutoPilot.m_flag1) AutoPilot.m_flag1)
if(!HasCarStoppedBecauseOfLight()) if(!HasCarStoppedBecauseOfLight())
PlayCarHorn(); PlayCarHorn();

View File

@ -60,7 +60,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
pPassengers[i] = nil; pPassengers[i] = nil;
m_nBombTimer = 0; m_nBombTimer = 0;
m_pBlowUpEntity = nil; m_pBlowUpEntity = nil;
field_1FB = 0; m_nPacManPickupsCarried = 0;
bComedyControls = false; bComedyControls = false;
bCraneMessageDone = false; bCraneMessageDone = false;
bExtendedRange = false; bExtendedRange = false;
@ -71,7 +71,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_nTimeOfDeath = 0; m_nTimeOfDeath = 0;
m_pCarFire = nil; m_pCarFire = nil;
bHasBeenOwnedByPlayer = false; bHasBeenOwnedByPlayer = false;
m_veh_flagC20 = false; bCreateRoadBlockPeds = false;
bCanBeDamaged = true; bCanBeDamaged = true;
bUsingSpecialColModel = false; bUsingSpecialColModel = false;
m_veh_flagD1 = false; m_veh_flagD1 = false;
@ -102,7 +102,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_aCollPolys[0].valid = false; m_aCollPolys[0].valid = false;
m_aCollPolys[1].valid = false; m_aCollPolys[1].valid = false;
AutoPilot.m_nCarMission = MISSION_NONE; AutoPilot.m_nCarMission = MISSION_NONE;
AutoPilot.m_nAnimationId = TEMPACT_NONE; AutoPilot.m_nTempAction = TEMPACT_NONE;
AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds(); AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
AutoPilot.m_flag4 = false; AutoPilot.m_flag4 = false;
AutoPilot.m_flag10 = false; AutoPilot.m_flag10 = false;

View File

@ -159,7 +159,7 @@ public:
uint8 bHasBeenOwnedByPlayer : 1;// To work out whether stealing it is a crime uint8 bHasBeenOwnedByPlayer : 1;// To work out whether stealing it is a crime
uint8 bFadeOut : 1; // Fade vehicle out uint8 bFadeOut : 1; // Fade vehicle out
uint8 m_veh_flagC10 : 1; uint8 m_veh_flagC10 : 1;
uint8 m_veh_flagC20 : 1; uint8 bCreateRoadBlockPeds : 1; // If this vehicle gets close enough we will create peds (coppers or gang members) round it
uint8 bCanBeDamaged : 1; // Set to FALSE during cut scenes to avoid explosions uint8 bCanBeDamaged : 1; // Set to FALSE during cut scenes to avoid explosions
uint8 bUsingSpecialColModel : 1;// Is player vehicle using special collision model, stored in player strucure uint8 bUsingSpecialColModel : 1;// Is player vehicle using special collision model, stored in player strucure
@ -174,8 +174,9 @@ public:
int8 m_numPedsUseItAsCover; int8 m_numPedsUseItAsCover;
uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default) uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default)
int8 field_1FB; int8 m_nPacManPickupsCarried;
int8 field_1FC[4]; uint8 m_nRoadblockType;
int16 m_nRoadblockNode;
float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode
uint8 m_nCurrentGear; uint8 m_nCurrentGear;
int8 field_205[3]; int8 field_205[3];