REDRIVER2/src_rebuild/GAME/C/COP_AI.C
Ilya Shurumov d424ae16f7 - implement HandleDrivingGames, SetSmashedCone
- fix DrawSmashedCones
2020-06-13 16:13:01 +06:00

1895 lines
40 KiB
C

#include "THISDUST.H"
#include "COP_AI.H"
#include "CIV_AI.H"
#include "AI.H"
#include "MISSION.H"
#include "SYSTEM.H"
#include "FELONY.H"
#include "CARS.H"
#include "PLAYERS.H"
#include "PATHFIND.H"
#include "GAMESND.H"
#include "CUTSCENE.H"
#include "CONVERT.H"
#include "MAP.H"
#include "CAMERA.H"
COP_DATA gCopData = { 0, 0, 0, 2048, 0, 4096, 2048, 3000000, { 0, 0, 0, 0, 0 } };
int speed1[] = { 0xCB, 0xD2, 0xD9 };
int speed2[] = { 0xEE, 0x10A, 0x126 };
char sqtbl[] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x81, 0x81, 0x81, 0x82, 0x82, 0x83, 0x83, 0x83, 0x84,
0x84, 0x85, 0x86, 0x86, 0x87, 0x88, 0x88, 0x89, 0x8A,
0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x90, 0x91,
0x92, 0x93, 0x94, 0x95, 0x96, 0x98, 0x99, 0x9A, 0x9B,
0x9C, 0x9D, 0x9E, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA6,
0xA7, 0xA8, 0xAA, 0xAB, 0xAC, 0xAE, 0xAF, 0xB0, 0xB2,
0xB3, 0xB5 };
int CopsCanSeePlayer = 0;
short pedestrianFelony = 0;
int numRoadblockCars = 0;
int roadblockCount = 0;
int copsAreInPursuit = 0;
int requestRoadblock = 0;
int roadblockDelay = 0xfa;
int roadblockDelayDiff[3] = { 1500, 1000, 800 };
int requestCopCar = 0;
int cop_respawn_timer = 0;
char first_offence = 0;
ROADBLOCK Roadblock;
VECTOR roadblockLoc;
static int said_picked_up = 0;
char last_cop_phrase = 0;
char CopWorkMem[444]; // PVS table
COP_SIGHT_DATA copSightData;
int player_position_known = 0;
VECTOR lastKnownPosition;
VECTOR CarTail;
_CAR_DATA *targetVehicle;
int numActiveCops = 0;
int pathStraight = 0;
int LastHeading = 0;
int OutOfSightCount = 0;
// decompiled code
// original method signature:
// void /*$ra*/ InitCopState(struct _CAR_DATA *cp /*$s0*/, char *extraData /*$a1*/)
// line 577, offset 0x0002f680
/* begin block 1 */
// Start line: 2675
/* end block 1 */
// End Line: 2676
/* begin block 2 */
// Start line: 1154
/* end block 2 */
// End Line: 1155
// [D]
void InitCopState(_CAR_DATA *cp, char *extraData)
{
ClearMem((char *)&cp->ai.p, sizeof(COP));
cp->controlType = 3;
cp->controlFlags = 0;
cp->ai.p.justPinged = 1;
if (gCopDifficultyLevel == 1)
{
cp->hndType = 3;
}
else
{
cp->hndType = 4;
if (gCopDifficultyLevel < 2)
{
if (gCopDifficultyLevel != 0)
{
cp->hndType = 4;
return;
}
cp->hndType = 2;
}
}
}
// decompiled code
// original method signature:
// int /*$ra*/ ReplayLog_Fnarr_He_Said_Log(int val /*$a0*/)
// line 2973, offset 0x0005c81c
/* begin block 1 */
// Start line: 5946
/* end block 1 */
// End Line: 5947
/* begin block 2 */
// Start line: 9921
/* end block 2 */
// End Line: 9922
int ReplayLog_Fnarr_He_Said_Log(int val)
{
return 0;
}
// decompiled code
// original method signature:
// void /*$ra*/ WibbleDownTheRoad(struct VECTOR *from /*$a0*/, int distance /*$s1*/, struct VECTOR *to /*$s5*/)
// line 593, offset 0x0002d78c
/* begin block 1 */
// Start line: 594
// Start offset: 0x0002D78C
// Variables:
// int th; // $s0
// int j; // $s3
// int thl[4]; // stack offset -136
// struct VECTOR pos; // stack offset -120
// struct VECTOR dir; // stack offset -104
/* begin block 1.1 */
// Start line: 604
// Start offset: 0x0002D810
// Variables:
// struct VECTOR p2; // stack offset -88
// struct VECTOR d2; // stack offset -72
// int colour[3]; // stack offset -56
/* end block 1.1 */
// End offset: 0x0002D89C
// End Line: 614
/* end block 1 */
// End offset: 0x0002D99C
// End Line: 639
/* begin block 2 */
// Start line: 1186
/* end block 2 */
// End Line: 1187
int distanceReturnedLog[8];
int distLogIndex;
int lastDistanceFound;
// [D]
void WibbleDownTheRoad(VECTOR *from, int distance, VECTOR *to)
{
uint val;
uint uVar1;
uint *puVar2;
int iVar3;
int thl[4];
VECTOR pos;
VECTOR dir;
pos.vx = from->vx;
pos.vy = from->vy;
pos.vz = from->vz;
pos.pad = from->pad;
iVar3 = 0;
puVar2 = (uint *)thl;
do {
ReplayLog_Fnarr_He_Said_Log(pos.vx);
ReplayLog_Fnarr_He_Said_Log(pos.vy);
ReplayLog_Fnarr_He_Said_Log(pos.vz);
val = getHeadingToPlayer(pos.vx, pos.vy, pos.vz);
ReplayLog_Fnarr_He_Said_Log(val);
if (iVar3 == 0)
{
uVar1 = distLogIndex & 7;
distLogIndex = distLogIndex + 1;
distanceReturnedLog[uVar1] = lastDistanceFound;
}
dir.vy = 0;
dir.vx = FIXED((distance >> 2) * rcossin_tbl[(val & 0xfff) * 2]);
dir.vz = FIXED((distance >> 2) * rcossin_tbl[(val & 0xfff) * 2 + 1]);
*puVar2 = val;
pos.vx = pos.vx + dir.vx;
puVar2 = puVar2 + 1;
pos.vy = pos.vy + dir.vy;
pos.vz = pos.vz + dir.vz;
iVar3++;
} while (iVar3 < 4);
to->vx = pos.vx;
to->vy = pos.vy;
to->vz = pos.vz;
to->pad = pos.pad;
if (((thl[3] - thl[0]) + 200U & 0xfff) < 400)
{
pathStraight = 1;
}
}
// decompiled code
// original method signature:
// void /*$ra*/ InitCops()
// line 643, offset 0x0002d99c
/* begin block 1 */
// Start line: 1381
/* end block 1 */
// End Line: 1382
/* begin block 2 */
// Start line: 1386
/* end block 2 */
// End Line: 1387
/* begin block 3 */
// Start line: 1387
/* end block 3 */
// End Line: 1388
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
void InitCops(void)
{
targetVehicle = &car_data[0];
requestCopCar = 0;
InitFelonySystem();
InitPathFinding();
felonyData.pursuitFelonyScale = 3000;
gCopDesiredSpeedScale = 0x1000;
gCopMaxPowerScale = 0x1000;
gPuppyDogCop = 0;
copsAreInPursuit = 0;
player_position_known = 2;
OutOfSightCount = 0;
UpdateCopSightData();
gCopData.autoMaxPowerScaleLimit = 0;
gCopData.autoDesiredSpeedScaleLimit = 0;
if (GameType == GAME_GETAWAY)
{
gCopRespawnTime = 10000;
}
else if (GameType == GAME_SURVIVAL)
{
gCopRespawnTime = 0;
gCopDesiredSpeedScale = 4596;
gCopMaxPowerScale = 4596;
gCopData.autoMaxPowerScaleLimit = 1024;
gCopData.autoDesiredSpeedScaleLimit = 1024;
}
else
{
gCopRespawnTime = 320;
if (gCurrentMissionNumber < 0x28)
gCopRespawnTime = gCurrentMissionNumber * -4 + 0x140;
}
LastHeading = -1;
pathStraight = 0;
numActiveCops = 0;
OutOfSightCount = 0;
cop_respawn_timer = 0;
CopsCanSeePlayer = 0;
CarTail.vx = 0;
CarTail.vy = 0;
CarTail.vz = 0;
lastKnownPosition.vx = 0x7fffffff;
lastKnownPosition.vy = 0x7fffffff;
lastKnownPosition.vz = 0x7fffffff;
InitCopData(&gCopData);
copsAreInPursuit = 0;
}
// decompiled code
// original method signature:
// void /*$ra*/ ControlCops()
// line 708, offset 0x0002dad8
/* begin block 1 */
// Start line: 710
// Start offset: 0x0002DAD8
/* begin block 1.1 */
// Start line: 726
// Start offset: 0x0002DB34
// Variables:
// int playerID; // $v1
/* end block 1.1 */
// End offset: 0x0002DB74
// End Line: 729
/* begin block 1.2 */
// Start line: 749
// Start offset: 0x0002DC6C
// Variables:
// int heading; // $s1
// int rnd; // $s0
/* end block 1.2 */
// End offset: 0x0002DD9C
// End Line: 774
/* begin block 1.3 */
// Start line: 784
// Start offset: 0x0002DDFC
// Variables:
// int copsWereInPursuit; // $a1
/* end block 1.3 */
// End offset: 0x0002DE9C
// End Line: 798
/* begin block 1.4 */
// Start line: 801
// Start offset: 0x0002DEAC
/* end block 1.4 */
// End offset: 0x0002DEE0
// End Line: 807
/* end block 1 */
// End offset: 0x0002DEE0
// End Line: 809
/* begin block 2 */
// Start line: 1551
/* end block 2 */
// End Line: 1552
/* begin block 3 */
// Start line: 1552
/* end block 3 */
// End Line: 1553
/* begin block 4 */
// Start line: 1555
/* end block 4 */
// End Line: 1556
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
void ControlCops(void)
{
char cVar1;
long lVar2;
long lVar3;
short *psVar4;
int direction;
int iVar5;
gCopData.autoBatterPlayerTrigger = 0x800;
if (CopsAllowed == 0 || gInGameCutsceneActive != 0)
{
player_position_known = 0;
CopsCanSeePlayer = 0;
requestCopCar = 0;
direction = copsAreInPursuit;
}
else
{
if (-1 < player[0].playerCarId)
targetVehicle = car_data + player[0].playerCarId;
if (0 < player_position_known)
{
lastKnownPosition.vx = player[0].pos[0];
lastKnownPosition.vy = player[0].pos[1];
lastKnownPosition.vz = player[0].pos[2];
lastKnownPosition.pad = player[0].pos[3];
}
UpdateCopMap();
direction = LastHeading;
if (first_offence == 0 && CopsCanSeePlayer != 0 && numActiveCops != 0)
{
if (player[0].playerCarId < 0)
{
psVar4 = &pedestrianFelony;
}
else
{
psVar4 = &car_data[player[0].playerCarId].felonyRating;
}
if (658 < *psVar4 && 720 < TimeSinceLastSpeech && 20 < targetVehicle->hd.speed)
{
cVar1 = GetCarDirectionOfTravel(targetVehicle);
direction = cVar1;
lVar2 = Random2(1);
if (direction != LastHeading)
{
iVar5 = MaxPlayerDamage[0] * 3;
if (iVar5 >> 2 < car_data[player[0].playerCarId].totalDamage)
{
lVar3 = lVar2;
iVar5 = (lVar3 >> 2) * -4;
}
else
{
iVar5 = (lVar2 / 3) * -3;
}
iVar5 = lVar2 + iVar5;
if (first_offence == 0 && last_cop_phrase != iVar5 && (720 < TimeSinceLastSpeech))
{
if (iVar5 < 3)
{
CopSay(iVar5 + 0xf, direction);
last_cop_phrase = iVar5;
}
else
{
CopSay(6, 0);
last_cop_phrase = iVar5;
}
}
}
}
}
LastHeading = direction;
if (player[0].playerCarId < 0)
psVar4 = &pedestrianFelony;
else
psVar4 = &car_data[(int)player[0].playerCarId].felonyRating;
if (gCopData.autoBatterPlayerTrigger <= *psVar4)
gBatterPlayer = 1;
ControlCopDetection();
AdjustFelony(&felonyData);
ControlNumberOfCops();
direction = 0;
if (0 < player_position_known)
{
if (player[0].playerCarId < 0)
psVar4 = &pedestrianFelony;
else
psVar4 = &car_data[(int)player[0].playerCarId].felonyRating;
if (0x292 < *psVar4)
{
direction = 1;
}
}
if (direction != 0)
{
if (copsAreInPursuit == 0)
Pads[0].alarmShakeCounter = 12;
if ((direction != 0) && (copsAreInPursuit = direction, FunkUpDaBGMTunez(1), direction = copsAreInPursuit, first_offence != 0))
{
CopSay(9, 0);
first_offence = 0;
said_picked_up = 1;
direction = copsAreInPursuit;
}
}
}
copsAreInPursuit = direction;
}
// decompiled code
// original method signature:
// void /*$ra*/ CopControl(struct _CAR_DATA *cp /*$s1*/)
// line 824, offset 0x0002f60c
/* begin block 1 */
// Start line: 825
// Start offset: 0x0002F60C
/* end block 1 */
// End offset: 0x0002F680
// End Line: 842
/* begin block 2 */
// Start line: 2903
/* end block 2 */
// End Line: 2904
/* begin block 3 */
// Start line: 1648
/* end block 3 */
// End Line: 1649
// [D]
void CopControl(_CAR_DATA *cp)
{
CopControl1(cp);
CheckPingOut(cp);
if (cp->ai.p.dying == 0 && cp->controlType == 0)
{
numActiveCops--;
numCopCars--;
}
}
// decompiled code
// original method signature:
// void /*$ra*/ CopControl1(struct _CAR_DATA *cp /*$s1*/)
// line 845, offset 0x0002defc
/* begin block 1 */
// Start line: 846
// Start offset: 0x0002DEFC
// Variables:
// int currentSpeed; // $s7
// int desiredSteerAngle; // $s4
/* begin block 1.1 */
// Start line: 893
// Start offset: 0x0002DFC4
// Variables:
// int dx; // $a1
// int dz; // $a0
/* begin block 1.1.1 */
// Start line: 897
// Start offset: 0x0002E018
/* end block 1.1.1 */
// End offset: 0x0002E058
// End Line: 905
/* end block 1.1 */
// End offset: 0x0002E058
// End Line: 906
/* begin block 1.2 */
// Start line: 912
// Start offset: 0x0002E070
// Variables:
// struct VECTOR pos; // stack offset -88
/* end block 1.2 */
// End offset: 0x0002E23C
// End Line: 922
/* begin block 1.3 */
// Start line: 935
// Start offset: 0x0002E23C
// Variables:
// enum AIZone targetZone; // $a0
// struct VECTOR doordir; // stack offset -72
// int targetFound; // $a1
// int cx; // $s5
// int cz; // $s6
// int dvx; // $s0
// int dvz; // $s3
// int dist; // $s2
// int framesToImpact; // $a1
/* begin block 1.3.1 */
// Start line: 984
// Start offset: 0x0002E360
// Variables:
// int dz; // $a1
// int idvx; // $v1
// int idvz; // $v0
/* end block 1.3.1 */
// End offset: 0x0002E360
// End Line: 984
/* begin block 1.3.2 */
// Start line: 1049
// Start offset: 0x0002E5E4
// Variables:
// struct iVectNT path[2]; // stack offset -56
// int slidevel; // $a3
/* begin block 1.3.2.1 */
// Start line: 1105
// Start offset: 0x0002E8E8
// Variables:
// int plcrspd; // $a1
/* end block 1.3.2.1 */
// End offset: 0x0002E954
// End Line: 1108
/* end block 1.3.2 */
// End offset: 0x0002EA28
// End Line: 1124
/* begin block 1.3.3 */
// Start line: 1140
// Start offset: 0x0002EA78
// Variables:
// int b; // $a0
/* end block 1.3.3 */
// End offset: 0x0002EAC0
// End Line: 1145
/* begin block 1.3.4 */
// Start line: 1149
// Start offset: 0x0002EAC0
// Variables:
// int steerdif; // $v1
// int speeddif; // $a2
// int maxPower; // $a1
/* begin block 1.3.4.1 */
// Start line: 1175
// Start offset: 0x0002EBB8
// Variables:
// int sf; // $v1
/* end block 1.3.4.1 */
// End offset: 0x0002EBD0
// End Line: 1177
/* end block 1.3.4 */
// End offset: 0x0002EC64
// End Line: 1188
/* end block 1.3 */
// End offset: 0x0002EC64
// End Line: 1188
/* begin block 1.4 */
// Start line: 1197
// Start offset: 0x0002EC84
/* end block 1.4 */
// End offset: 0x0002ECAC
// End Line: 1201
/* end block 1 */
// End offset: 0x0002ECAC
// End Line: 1203
/* begin block 2 */
// Start line: 1831
/* end block 2 */
// End Line: 1832
void CopControl1(_CAR_DATA *cp)
{
UNIMPLEMENTED();
/*
byte bVar1;
short sVar2;
bool bVar3;
char cVar4;
short sVar5;
int dvx;
undefined3 extraout_var;
undefined3 extraout_var_00;
int iVar6;
int *piVar7;
short *psVar8;
uint uVar9;
int iVar10;
undefined2 uVar11;
int x;
int dvz;
int unaff_s4;
int z;
uint uVar12;
VECTOR local_58;
int local_48;
int local_44;
int local_40;
uint local_30;
int local_2c;
dvx = (cp->hd).wheel_speed;
cp->wheelspin = '\0';
uVar12 = dvx + 0x800 >> 0xc;
if (CopsAllowed == 0) {
LAB_0002e048:
cp->thrust = 0;
cp->handbrake = '\x01';
return;
}
bVar1 = cp->ai[0x13];
if ((bVar1 != 0) || ((27000 < cp->totalDamage && (gCopData.immortal == 0)))) {
cp->thrust = 0;
if (0x55 < bVar1) {
return;
}
if (bVar1 == 0) {
numActiveCops = numActiveCops + -1;
}
cp->ai[0x13] = cp->ai[0x13] + 1;
return;
}
if (DAT_000d7c84 != 0) {
dvx = (cp->hd).where.t[0];
dvz = dvx - gStopCops;
if (dvz < 0) {
dvz = gStopCops - dvx;
}
dvx = (cp->hd).where.t[2];
x = dvx - DAT_000d7c80;
if (x < 0) {
x = DAT_000d7c80 - dvx;
}
if ((dvz + x < DAT_000d7c84 * 3 >> 1) &&
(dvx = SquareRoot0(dvz * dvz + x * x), dvx < DAT_000d7c84)) goto LAB_0002e048;
}
if ((CameraCnt & 7U) == 0) {
local_58.vx = (cp->hd).where.t[0] +
((int)(cp->hd).where.m[2] * 400 + (int)(cp->hd).where.m[0] * -0x96 + 0x800 >> 0xc)
;
local_58.vy = (cp->hd).where.t[1] +
((int)(cp->hd).where.m[5] * 400 + (int)(cp->hd).where.m[3] * -0x96 + 0x800 >> 0xc)
;
local_58.vz = (cp->hd).where.t[2] +
((int)(cp->hd).where.m[8] * 400 + (int)(cp->hd).where.m[6] * -0x96 + 0x800 >> 0xc)
;
cVar4 = CellAtPositionEmpty(&local_58, 0x50);
sVar5 = (cp->hd).where.m[2];
sVar2 = (cp->hd).where.m[0];
*(short *)(cp->ai + 0x22) = (short)CONCAT31(extraout_var, cVar4);
local_58.vx = (cp->hd).where.t[0] + ((int)sVar5 * 400 + (int)sVar2 * 0x96 + 0x800 >> 0xc);
local_58.vy = (cp->hd).where.t[1] +
((int)(cp->hd).where.m[5] * 400 + (int)(cp->hd).where.m[3] * 0x96 + 0x800 >> 0xc);
local_58.vz = (cp->hd).where.t[2] +
((int)(cp->hd).where.m[8] * 400 + (int)(cp->hd).where.m[6] * 0x96 + 0x800 >> 0xc);
cVar4 = CellAtPositionEmpty(&local_58, 0x50);
*(short *)(cp->ai + 0x24) = (short)CONCAT31(extraout_var_00, cVar4);
}
local_48 = (int)(cp->hd).where.m[0];
x = (cp->hd).where.t[0];
z = (cp->hd).where.t[2];
local_40 = (int)(cp->hd).where.m[6];
local_44 = (int)(cp->hd).where.m[3];
pathStraight = 0;
dvx = *(int *)(targetVehicle->st + 0x1c) - *(int *)(cp->st + 0x1c);
dvz = *(int *)(targetVehicle->st + 0x24) - *(int *)(cp->st + 0x24);
if (((cp->hd).speed < 6) && (*(short *)(cp->ai + 0x16) != 0)) {
*(short *)(cp->ai + 0x1a) = *(short *)(cp->ai + 0x1a) + 1;
}
else {
*(undefined2 *)(cp->ai + 0x1a) = 0;
}
if ((10 < *(short *)(cp->ai + 0x1a)) && (*(short *)(cp->ai + 0x1e) == 0)) {
uVar11 = 0xff38;
*(undefined2 *)(cp->ai + 0x1e) = 0x16;
uVar9 = (uint)*(ushort *)(cp->ai + 0x1c) & 7;
*(short *)(cp->ai + 0x1c) = (short)uVar9;
if (*(short *)(cp->ai + 0x16) < 0) {
uVar11 = 200;
}
unaff_s4 = ((uVar9 * 5 & 6) - 3) * 0x80;
*(undefined2 *)(cp->ai + 0x16) = uVar11;
*(undefined2 *)(cp->ai + 0x1a) = 0;
}
iVar6 = FindCost(x, z, dvx, dvz);
*(bool *)(cp->ai + 0x12) = iVar6 < 0xaf0;
bVar3 = false;
if (*(short *)(cp->ai + 0x1e) < 1) {
if (iVar6 < 0x20d0) {
iVar10 = dvx + 0x800 >> 0xc;
dvx = dvz + 0x800 >> 0xc;
dvz = iVar10 * iVar10 + dvx * dvx + 1;
dvx = ((x - (targetVehicle->hd).where.t[0]) * iVar10 -
((targetVehicle->hd).where.t[2] - z) * dvx) / dvz;
if (dvz == 0) {
trap(7);
}
if (gBatterPlayer == 0) {
dvz = dvx * 3;
dvx = dvz >> 2;
if (dvz < 0) {
dvx = dvz + 3 >> 2;
}
}
if (dvx < 0) {
dvx = 0;
}
else {
if (0x3c < dvx) {
dvx = 0x3c;
}
}
dvz = (targetVehicle->hd).where.t[0] +
(*(int *)(targetVehicle->st + 0x1c) * dvx + 0x800 >> 0xc);
dvx = (targetVehicle->hd).where.t[2] +
(*(int *)(targetVehicle->st + 0x24) * dvx + 0x800 >> 0xc);
if (gBatterPlayer == 0) {
iVar10 = (int)(targetVehicle->hd).where.m[2] * 5;
if (iVar10 < 0) {
iVar10 = iVar10 + 0x7f;
}
CarTail.vx = dvz - (iVar10 >> 7);
dvz = (int)(targetVehicle->hd).where.m[8] * 5;
if (dvz < 0) {
dvz = dvz + 0x7f;
}
CarTail.vz = dvx - (dvz >> 7);
}
else {
iVar10 = (int)(targetVehicle->hd).where.m[0] * 5;
if (iVar10 < 0) {
iVar10 = iVar10 + 0xff;
}
CarTail.vx = dvz + (iVar10 >> 8);
dvz = (int)(targetVehicle->hd).where.m[6] * 5;
if (dvz < 0) {
dvz = dvz + 0xff;
}
CarTail.vz = dvx + (dvz >> 8);
}
}
else {
CarTail.vx = (targetVehicle->hd).where.t[0];
CarTail.vz = (targetVehicle->hd).where.t[2];
}
if (cp->ai[0x12] == 0) {
WibbleDownTheRoad((VECTOR *)(cp->hd).where.t, (cp->hd).speed * 10 + 0x2a8, &targetPoint);
}
else {
targetPoint.vx = CarTail.vx;
targetPoint.vz = CarTail.vz;
}
bVar3 = true;
*(undefined4 *)(cp->ai + 8) = *(undefined4 *)cp->ai;
*(undefined4 *)(cp->ai + 0xc) = *(undefined4 *)(cp->ai + 4);
*(long *)cp->ai = targetPoint.vx;
*(long *)(cp->ai + 4) = targetPoint.vz;
}
else {
*(short *)(cp->ai + 0x1e) = *(short *)(cp->ai + 0x1e) + -1;
}
if (gTimeInWater == 0) {
bVar3 = false;
}
if (bVar3) {
dvz = local_48 * *(int *)(cp->st + 0x1c) + local_40 * *(int *)(cp->st + 0x24) + 0x800 >> 0xc;
local_2c = (x - targetPoint.vx) * local_40 + (targetPoint.vz - z) * local_48 >> 0xc;
dvx = ((targetPoint.vx - x) * local_48 + (targetPoint.vz - z) * local_40 >> 0xc) - dvz / 0x8c;
if (dvx < 1) {
if ((dvx * -2 < local_2c) && (*(short *)(cp->ai + 0x22) != 0)) goto LAB_0002e728;
uVar9 = 2;
bVar3 = -dvx < local_2c << 2;
LAB_0002e708:
if ((bVar3) && (cp->ai[0x12] != 0)) {
uVar9 = 1;
}
}
else {
if ((local_2c <= dvx * 2) || (*(short *)(cp->ai + 0x24) == 0)) {
uVar9 = 3;
bVar3 = dvx < local_2c << 2;
goto LAB_0002e708;
}
LAB_0002e728:
uVar9 = 0;
}
local_30 = dvx + dvz / 0x8c;
if (uVar9 == 1) {
*(undefined2 *)(cp->ai + 0x16) = 0xffba;
unaff_s4 = 0x11c;
if ((int)(local_30 ^ uVar12) < 0) {
unaff_s4 = -0x11c;
}
}
else {
if (uVar9 < 2) {
if (uVar9 == 0) {
if (pathStraight == 0) {
piVar7 = &speed1;
}
else {
piVar7 = &speed2;
}
*(undefined2 *)(cp->ai + 0x16) = *(undefined2 *)(piVar7 + gCopDifficultyLevel);
if (gCopData.cutOffDistance < (int)(uint)*(ushort *)(cp->ai + 0x14)) {
sVar5 = *(short *)(cp->ai + 0x16);
if ((int)player.playerCarId < 0) {
psVar8 = &pedestrianFelony;
}
else {
psVar8 = &car_data[(int)player.playerCarId].felonyRating;
}
sVar2 = *psVar8;
dvx = gCopData.cutOffPowerScale;
}
else {
sVar5 = *(short *)(cp->ai + 0x16);
if ((int)player.playerCarId < 0) {
psVar8 = &pedestrianFelony;
}
else {
psVar8 = &car_data[(int)player.playerCarId].felonyRating;
}
sVar2 = *psVar8;
dvx = gCopDesiredSpeedScale;
}
*(short *)(cp->ai + 0x16) =
(short)((int)sVar5 * (dvx + (sVar2 * gCopData.autoDesiredSpeedScaleLimit >> 0xc)) >>
0xc);
if ((gPuppyDogCop != 0) && (cp->ai[0x12] != 0)) {
dvx = (targetVehicle->hd).speed + 10;
if (iVar6 < 0xfa1) {
*(short *)(cp->ai + 0x16) = *(short *)&(targetVehicle->hd).speed + 10;
}
else {
dvz = (*(short *)(cp->ai + 0x16) - dvx) * (iVar6 + -4000);
*(short *)(cp->ai + 0x16) =
(short)dvx +
((short)((ulonglong)((longlong)dvz * 0x10624dd3) >> 0x28) - (short)(dvz >> 0x1f))
;
}
}
unaff_s4 = (int)(local_30 * 0x200) / local_2c;
if (local_2c == 0) {
trap(7);
}
}
}
else {
if (uVar9 < 4) {
*(undefined2 *)(cp->ai + 0x16) = 0x6e;
if ((*(short *)(cp->ai + 0x22) == 0) || (*(short *)(cp->ai + 0x24) == 0)) {
*(undefined2 *)(cp->ai + 0x16) = 0xff88;
}
else {
if (((uVar9 == 2) && (-0x82 < *(int *)(cp->st + 0x2c))) ||
((uVar9 == 3 && (*(int *)(cp->st + 0x2c) < 0x82)))) {
cp->wheelspin = '\x01';
}
}
unaff_s4 = 0x200;
if ((int)(local_30 ^ uVar12) < 0) {
unaff_s4 = -0x200;
}
}
}
}
}
else {
if (*(short *)(cp->ai + 0x1e) < 1) {
*(undefined2 *)(cp->ai + 0x16) = 0;
unaff_s4 = 0;
}
}
if (((iVar6 < 0x1000) && (0 < (int)*(short *)(cp->ai + 0x16))) && (gBatterPlayer == 0)) {
dvx = (targetVehicle->hd).speed + -0x14;
if (dvx < 0x14) {
dvx = 0x14;
}
*(short *)(cp->ai + 0x16) =
(short)(iVar6 * (int)*(short *)(cp->ai + 0x16) + (0x1000 - iVar6) * dvx + 0x800 >> 0xc);
}
dvx = (gCopDifficultyLevel + 8) * 0x400;
dvz = (int)*(short *)(cp->ai + 0x16) - uVar12;
if (pathStraight != 0) {
dvx = dvx + (gCopDifficultyLevel + 4) * 0x400;
}
if ((int)player.playerCarId < 0) {
psVar8 = &pedestrianFelony;
}
else {
psVar8 = &car_data[(int)player.playerCarId].felonyRating;
}
dvx = dvx * (gCopMaxPowerScale + (*psVar8 * gCopData.autoMaxPowerScaleLimit >> 0xc)) >> 0xc;
sVar5 = (short)dvx;
if (dvz < -0x32) {
sVar5 = -sVar5;
}
else {
if (0x32 < dvz) {
cp->thrust = sVar5;
goto LAB_0002eba4;
}
sVar5 = (short)((dvz * dvx) / 0x32);
}
cp->thrust = sVar5;
LAB_0002eba4:
dvx = (cp->hd).speed;
if (dvx < 0x30) {
cp->thrust = (short)((int)cp->thrust * (dvx + 0x50) >> 7);
}
if (handlingType[cp->hndType].fourWheelDrive == '\x01') {
cp->thrust = cp->thrust >> 1;
}
cp->thrust = (short)(((int)cp->thrust * 7) / 10);
dvx = ((unaff_s4 + 0x800U & 0xfff) - 0x800) - (int)cp->wheel_angle;
sVar5 = (short)dvx;
if (dvx < -200) {
sVar5 = -200;
}
else {
if (200 < dvx) {
sVar5 = 200;
}
}
bVar1 = cp->ai[0x11];
cp->wheel_angle = cp->wheel_angle + sVar5;
if (bVar1 == 1) {
dvx = getHeadingToPlayer((cp->hd).where.t[0], (cp->hd).where.t[1], (cp->hd).where.t[2]);
(cp->hd).direction = dvx;
TempBuildHandlingMatrix(cp, 0);
cp->ai[0x11] = 0;
}
return;*/
}
// decompiled code
// original method signature:
// int /*$ra*/ FindCost(int x /*$a0*/, int z /*$a1*/, int dvx /*$a2*/, int dvz /*$a3*/)
// line 1231, offset 0x0002f8dc
/* begin block 1 */
// Start line: 1232
// Start offset: 0x0002F8DC
// Variables:
// int tx; // $v0
// int tz; // $v0
// int dx; // $a2
// int dz; // $v1
// int d; // $v0
/* end block 1 */
// End offset: 0x0002F994
// End Line: 1244
/* begin block 2 */
// Start line: 2048
/* end block 2 */
// End Line: 2049
/* begin block 3 */
// Start line: 4800
/* end block 3 */
// End Line: 4801
/* begin block 4 */
// Start line: 4802
/* end block 4 */
// End Line: 4803
// [D]
int FindCost(int x, int z, int dvx, int dvz)
{
int iVar1;
x = x - (targetVehicle->hd.where.t[0] + (dvx >> 8));
if (x < 0)
x = -x;
z = z - (targetVehicle->hd.where.t[2] + (dvz >> 8));
if (z < 0)
z = -z;
iVar1 = z;
if (x < z)
{
iVar1 = x;
x = z;
}
if (x != 0)
{
x = x * sqtbl[(iVar1 << 6) / x];
return x >> 7;
}
return 0;
}
// decompiled code
// original method signature:
// void /*$ra*/ InitCopData(struct COP_DATA *pCopData /*$a0*/)
// line 1267, offset 0x0002f7f8
/* begin block 1 */
// Start line: 1268
// Start offset: 0x0002F7F8
// Variables:
// short *pTrigger; // $v1
// short trigger; // $a2
/* end block 1 */
// End offset: 0x0002F844
// End Line: 1281
/* begin block 2 */
// Start line: 4374
/* end block 2 */
// End Line: 4375
/* begin block 3 */
// Start line: 2534
/* end block 3 */
// End Line: 2535
/* begin block 4 */
// Start line: 4378
/* end block 4 */
// End Line: 4379
// [D]
void InitCopData(COP_DATA *pCopData)
{
short *psVar1;
int iVar2;
int iVar3;
psVar1 = pCopData->trigger;
iVar3 = 0;
if (psVar1 < pCopData->trigger + 4)
{
iVar2 = 0x3330000;
do {
*psVar1 = iVar3;
iVar3 = iVar2 >> 0x10;
psVar1++;
iVar2 += 0x3330000;
} while (psVar1 < pCopData->trigger + 4);
}
*psVar1 = 0x7fff;
said_picked_up = 0;
}
// decompiled code
// original method signature:
// void /*$ra*/ UpdateCopSightData()
// line 1308, offset 0x0002f844
/* begin block 1 */
// Start line: 1310
// Start offset: 0x0002F844
// Variables:
// int angry; // $v1
/* end block 1 */
// End offset: 0x0002F8DC
// End Line: 1314
/* begin block 2 */
// Start line: 4431
/* end block 2 */
// End Line: 4432
/* begin block 3 */
// Start line: 4459
/* end block 3 */
// End Line: 4460
/* begin block 4 */
// Start line: 4460
/* end block 4 */
// End Line: 4461
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
void UpdateCopSightData(void)
{
short *psVar1;
if (player[0].playerCarId < 0)
psVar1 = &pedestrianFelony;
else
psVar1 = &car_data[player[0].playerCarId].felonyRating;
if (*psVar1 < 0x293)
{
copSightData.surroundViewDistance = 0xaa0;
copSightData.frontViewDistance = 0x1e8c;
copSightData.frontViewAngle = 0x200;
return;
}
copSightData.surroundViewDistance = 0x1540;
copSightData.frontViewDistance = 0x3fc0;
copSightData.frontViewAngle = 0x400;
}
// decompiled code
// original method signature:
// void /*$ra*/ ControlCopDetection()
// line 1368, offset 0x0002ecd8
/* begin block 1 */
// Start line: 1382
// Start offset: 0x0002ECD8
// Variables:
// int dx; // $v1
// int dz; // $a0
// struct VECTOR vec; // stack offset -64
// int ccx; // stack offset -32
// int ccz; // stack offset -28
// char *scratch; // $s4
// struct _CAR_DATA *lcp; // $s1
/* begin block 1.1 */
// Start line: 1385
// Start offset: 0x0002ECD8
/* begin block 1.1.1 */
// Start line: 1385
// Start offset: 0x0002ECD8
// Variables:
// int angry; // $v1
/* end block 1.1.1 */
// End offset: 0x0002EDA8
// End Line: 1391
/* end block 1.1 */
// End offset: 0x0002EDA8
// End Line: 1391
/* begin block 1.2 */
// Start line: 1416
// Start offset: 0x0002EDFC
// Variables:
// int dx; // $v1
// int dz; // $v0
/* end block 1.2 */
// End offset: 0x0002EE7C
// End Line: 1426
/* begin block 1.3 */
// Start line: 1434
// Start offset: 0x0002EED0
// Variables:
// int distanceToPlayer; // $s0
// int active; // $s2
/* begin block 1.3.1 */
// Start line: 1369
// Start offset: 0x0002EF70
// Variables:
// struct _CAR_DATA *cp; // $s1
// int distanceToPlayer; // $s0
/* begin block 1.3.1.1 */
// Start line: 1369
// Start offset: 0x0002EF70
// Variables:
// int farDist; // $v1
// int nearDist; // $v0
// char result; // $s2
/* begin block 1.3.1.1.1 */
// Start line: 1369
// Start offset: 0x0002EF90
// Variables:
// int theta; // $v1
// struct VECTOR delta; // stack offset -48
/* begin block 1.3.1.1.1.1 */
// Start line: 1369
// Start offset: 0x0002F030
/* end block 1.3.1.1.1.1 */
// End offset: 0x0002F034
// End Line: 1369
/* end block 1.3.1.1.1 */
// End offset: 0x0002F034
// End Line: 1369
/* end block 1.3.1.1 */
// End offset: 0x0002F034
// End Line: 1369
/* end block 1.3.1 */
// End offset: 0x0002F034
// End Line: 1369
/* end block 1.3 */
// End offset: 0x0002F050
// End Line: 1452
/* begin block 1.4 */
// Start line: 1478
// Start offset: 0x0002F164
/* end block 1.4 */
// End offset: 0x0002F164
// End Line: 1478
/* begin block 1.5 */
// Start line: 1491
// Start offset: 0x0002F190
/* begin block 1.5.1 */
// Start line: 1498
// Start offset: 0x0002F1B8
/* end block 1.5.1 */
// End offset: 0x0002F228
// End Line: 1518
/* end block 1.5 */
// End offset: 0x0002F238
// End Line: 1520
/* begin block 1.6 */
// Start line: 1525
// Start offset: 0x0002F25C
// Variables:
// int rnd; // $s0
// int dir; // $s1
/* end block 1.6 */
// End offset: 0x0002F2C8
// End Line: 1529
/* begin block 1.7 */
// Start line: 1534
// Start offset: 0x0002F2FC
// Variables:
// int rnd; // $s0
// int dir; // $s1
/* end block 1.7 */
// End offset: 0x0002F394
// End Line: 1536
/* end block 1 */
// End offset: 0x0002F3CC
// End Line: 1542
/* begin block 2 */
// Start line: 3020
/* end block 2 */
// End Line: 3021
/* begin block 3 */
// Start line: 3033
/* end block 3 */
// End Line: 3034
/* begin block 4 */
// Start line: 3036
/* end block 4 */
// End Line: 3037
/* begin block 5 */
// Start line: 3042
/* end block 5 */
// End Line: 3043
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
void ControlCopDetection(void)
{
unsigned char uVar1;
bool bVar2;
char cVar3;
short sVar4;
int y;
short *psVar5;
long lVar6;
int x;
int iVar7;
_CAR_DATA *cp;
VECTOR vec;
VECTOR delta;
int ccx;
int ccz;
vec.vx = player[0].pos[0];
vec.vz = player[0].pos[2];
GetVisSetAtPosition(&vec, CopWorkMem, &ccx, &ccz);
if (player[0].playerCarId < 0)
psVar5 = &pedestrianFelony;
else
psVar5 = &car_data[player[0].playerCarId].felonyRating;
bVar2 = 0x292 < *psVar5;
copSightData.surroundViewDistance = 0xaa0;
if (bVar2)
copSightData.surroundViewDistance = 0x1540;
copSightData.frontViewDistance = 0x1e8c;
if (bVar2)
copSightData.frontViewDistance = 0x3fc0;
copSightData.frontViewAngle = 0x200;
if (bVar2)
copSightData.frontViewAngle = 0x400;
bVar2 = player_position_known < 1;
player_position_known = 2;
if (bVar2)
player_position_known = 1;
CopsCanSeePlayer = 0;
if (player[0].playerType != 2 && -1 < player[0].playerCarId)
{
if (numRoadblockCars != 0)
{
x = roadblockLoc.vx - player[0].pos[0];
if (x < 0)
x = -x;
y = roadblockLoc.vz - player[0].pos[2];
if (y < 0)
y = -y;
if (((x >> 8) * (x >> 8) + (y >> 8) * (y >> 8) < 0x668) && newPositionVisible(&roadblockLoc, CopWorkMem, ccx, ccz) != 0)
CopsCanSeePlayer = 1;
}
if (CopsCanSeePlayer == 0)
{
cp = &car_data[19];
while (car_data <= cp)
{
uVar1 = cp->controlType;
if (uVar1 == 3)
{
if (cp->ai.p.dying == 0)
goto LAB_0002eed0;
}
else
{
if ((cp->controlFlags & 1) != 0)
{
LAB_0002eed0:
vec.vx = (cp->hd).where.t[0];
vec.vz = (cp->hd).where.t[2];
y = (cp->hd).where.t[0];
x = y - player[0].pos[0];
if (x < 0)
x = player[0].pos[0] - y;
iVar7 = (cp->hd).where.t[2];
y = iVar7 - player[0].pos[2];
if (y < 0)
y = player[0].pos[2] - iVar7;
lVar6 = SquareRoot0(x * x + y * y);
if ((uVar1 == 3) && (cp->ai.p.DistanceToPlayer = lVar6, cp->ai.p.close_pursuit != 0))
{
LAB_0002f040:
CopsCanSeePlayer = 1;
break;
}
if (newPositionVisible(&vec, CopWorkMem, ccx, ccz) != 0)
{
if (lVar6 < copSightData.surroundViewDistance)
{
LAB_0002f030:
bVar2 = true;
}
else
{
bVar2 = false;
if (lVar6 < copSightData.frontViewDistance)
{
y = (targetVehicle->hd).where.t[0] - (cp->hd).where.t[0];
x = (targetVehicle->hd).where.t[2] -(cp->hd).where.t[2];
lVar6 = ratan2(y, x);
if (lVar6 - (cp->hd).direction < 0)
{
lVar6 = ratan2(y, x);
x = (cp->hd).direction - lVar6;
}
else
{
lVar6 = ratan2(y, x);
x = lVar6 - (cp->hd).direction;
}
if ((x < copSightData.frontViewAngle) || (bVar2 = false, x < copSightData.frontViewAngle + 0x200))
goto LAB_0002f030;
}
}
if (bVar2)
goto LAB_0002f040;
}
}
}
cp = cp + -1;
}
}
}
if (numActiveCops == 0 && OutOfSightCount < 0x100 && 8 < CameraCnt)
{
OutOfSightCount = 0x100;
}
if (CopsCanSeePlayer == 0)
{
x = OutOfSightCount + 1;
if (0xff < OutOfSightCount)
{
if (OutOfSightCount == 0x100)
{
player_position_known = -1;
OutOfSightCount = 0x101;
if (player[0].playerCarId < 0)
psVar5 = &pedestrianFelony;
else
psVar5 = &car_data[player[0].playerCarId].felonyRating;
x = OutOfSightCount;
if ((0x292 < *psVar5) && (first_offence == '\0'))
{
CopSay(0xc, 0);
FunkUpDaBGMTunez(0);
x = OutOfSightCount;
}
}
else
{
player_position_known = 0;
x = OutOfSightCount;
}
}
}
else
{
OutOfSightCount = 0;
x = OutOfSightCount;
}
OutOfSightCount = x;
if (player_position_known < 1)
{
cp = &car_data[19];
do {
if (cp->controlType == 3)
{
vec.vx = (cp->hd).where.t[0];
vec.vz = (cp->hd).where.t[2];
// make cop lose target if target is hidden
if (newPositionVisible(&vec, CopWorkMem, ccx, ccz) == 0 && cp->ai.p.hiddenTimer++ > 0x32)
{
cp->controlType = 0;
cp->ai.p.hiddenTimer = 0;
cp->thrust = 0;
numCopCars--;
}
}
cp--;
} while (car_data <= cp);
}
x = player_position_known;
if ((player_position_known == 1) && (first_offence == 0))
{
lVar6 = Random2(2);
cVar3 = GetCarDirectionOfTravel(car_data + player[0].playerCarId);
CopSay(lVar6 % 2 + 10, cVar3);
said_picked_up = x;
LastHeading = cVar3;
}
if (CopsCanSeePlayer == 0)
said_picked_up = 0;
else if ((first_offence == 0) && (said_picked_up == 0))
{
lVar6 = Random2(2);
x = GetCarDirectionOfTravel(&car_data[player[0].playerCarId]);
if ((lVar6 == (lVar6 / 5) * 5) && (x != LastHeading))
CopSay(lVar6 % 2 + 10, x);
said_picked_up = 1;
LastHeading = x;
}
return;
}
// decompiled code
// original method signature:
// void /*$ra*/ PassiveCopTasks(struct _CAR_DATA *cp /*$s0*/)
// line 1562, offset 0x0002f6fc
/* begin block 1 */
// Start line: 1563
// Start offset: 0x0002F6FC
/* begin block 1.1 */
// Start line: 1563
// Start offset: 0x0002F76C
// Variables:
// struct _CAR_DATA *cp; // $s0
/* end block 1.1 */
// End offset: 0x0002F7C4
// End Line: 1563
/* end block 1 */
// End offset: 0x0002F7F8
// End Line: 1576
/* begin block 2 */
// Start line: 4648
/* end block 2 */
// End Line: 4649
/* begin block 3 */
// Start line: 4654
/* end block 3 */
// End Line: 4655
// [D]
void PassiveCopTasks(_CAR_DATA *cp)
{
short *psVar2;
if (player[0].playerCarId < 0)
psVar2 = &pedestrianFelony;
else
psVar2 = &car_data[player[0].playerCarId].felonyRating;
if (*psVar2 < 0x293)
return;
if (player_position_known < 1)
return;
ClearMem((char *)&cp->ai.p, sizeof(COP));
cp->controlType = 3;
cp->controlFlags = 0;
cp->ai.p.justPinged = 1;
if (gCopDifficultyLevel == 1)
{
cp->hndType = 3;
}
else
{
cp->hndType = 4;
if (gCopDifficultyLevel < 2)
{
if (gCopDifficultyLevel != 0)
{
cp->hndType = 4;
goto LAB_0002f7c4;
}
cp->hndType = 2;
}
}
LAB_0002f7c4:
cp->ai.p.justPinged = 0;
numCivCars--;
numActiveCops++;
}
// decompiled code
// original method signature:
// void /*$ra*/ ControlNumberOfCops()
// line 1583, offset 0x0002f3cc
/* begin block 1 */
// Start line: 1585
// Start offset: 0x0002F3CC
// Variables:
// int numWantedCops; // $t2
/* begin block 1.1 */
// Start line: 1588
// Start offset: 0x0002F3CC
// Variables:
// short *pTrigger; // $a2
/* end block 1.1 */
// End offset: 0x0002F454
// End Line: 1596
/* begin block 1.2 */
// Start line: 1609
// Start offset: 0x0002F4A0
// Variables:
// int temp; // $a1
/* end block 1.2 */
// End offset: 0x0002F54C
// End Line: 1624
/* begin block 1.3 */
// Start line: 1633
// Start offset: 0x0002F570
// Variables:
// int num_closer; // $a2
// int cutOffDistance; // $a1
/* begin block 1.3.1 */
// Start line: 1638
// Start offset: 0x0002F580
// Variables:
// struct _CAR_DATA *lcp; // $a0
// int tempDist; // $a3
/* begin block 1.3.1.1 */
// Start line: 1647
// Start offset: 0x0002F5AC
// Variables:
// int copDist; // $v1
/* end block 1.3.1.1 */
// End offset: 0x0002F5CC
// End Line: 1658
/* end block 1.3.1 */
// End offset: 0x0002F5DC
// End Line: 1661
/* end block 1.3 */
// End offset: 0x0002F5E8
// End Line: 1664
/* end block 1 */
// End offset: 0x0002F60C
// End Line: 1671
/* begin block 2 */
// Start line: 3514
/* end block 2 */
// End Line: 3515
/* begin block 3 */
// Start line: 3556
/* end block 3 */
// End Line: 3557
/* begin block 4 */
// Start line: 3557
/* end block 4 */
// End Line: 3558
/* begin block 5 */
// Start line: 3560
/* end block 5 */
// End Line: 3561
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
void ControlNumberOfCops(void)
{
short sVar1;
short *psVar2;
short *psVar3;
uint uVar4;
_CAR_DATA *p_Var5;
int iVar6;
uint uVar7;
int iVar8;
psVar2 = gCopData.trigger;
iVar8 = 0;
while (true)
{
sVar1 = *psVar2;
psVar2++;
if (player[0].playerCarId < 0)
psVar3 = &pedestrianFelony;
else
psVar3 = &car_data[player[0].playerCarId].felonyRating;
if (*psVar3 < sVar1)
break;
iVar8++;
}
iVar6 = gMinimumCops;
if ((iVar8 < gMinimumCops) || (iVar6 = maxCopCars, maxCopCars < iVar8))
{
iVar8 = iVar6;
}
if (numCopCars < iVar8 && gDontPingInCops == 0)
{
iVar8 = gCopRespawnTime;
if (Roadblock.status == 2)
iVar8 = Roadblock.copRespawnTime;
if (player[0].playerCarId < 0)
psVar2 = &pedestrianFelony;
else
psVar2 = &car_data[(int)player[0].playerCarId].felonyRating;
if (iVar8 * FIXED(0x1000 - FIXED(*psVar2 * gCopData.autoRespawnScaleLimit)) < cop_respawn_timer + 1)
requestCopCar = 1;
cop_respawn_timer++;
return;
}
if (numCopCars <= iVar8)
{
gCopData.cutOffDistance = 0x7fffffff;
cop_respawn_timer = 0;
return;
}
gCopData.cutOffDistance = 0x7fffffff;
do {
uVar7 = 0;
p_Var5 = car_data;
iVar6 = 0;
if (true) {
do {
if (p_Var5->controlType == 3)
{
uVar4 = p_Var5->ai.p.DistanceToPlayer;
if ((uVar4 < gCopData.cutOffDistance) && (iVar6 = iVar6 + 1, uVar7 < uVar4))
{
uVar7 = uVar4;
}
}
p_Var5++;
} while (p_Var5 < &car_data[20]);
}
gCopData.cutOffDistance = uVar7;
} while (iVar8 < iVar6);
cop_respawn_timer = 0;
}