mirror of
https://github.com/OpenDriver2/REDRIVER2.git
synced 2024-11-22 18:32:42 +01:00
739 lines
15 KiB
C
739 lines
15 KiB
C
#include "driver2.h"
|
|
#include "objanim.h"
|
|
#include "map.h"
|
|
#include "models.h"
|
|
#include "texture.h"
|
|
#include "debris.h"
|
|
#include "civ_ai.h"
|
|
#include "main.h"
|
|
#include "mission.h"
|
|
#include "cars.h"
|
|
#include "players.h"
|
|
#include "cop_ai.h"
|
|
#include "felony.h"
|
|
#include "spool.h"
|
|
#include "system.h"
|
|
#include "pause.h"
|
|
|
|
struct ANIMATED_OBJECT
|
|
{
|
|
int internal_id;
|
|
int model_num;
|
|
char* name;
|
|
char LitPoly;
|
|
};
|
|
|
|
struct GARAGE_DOOR
|
|
{
|
|
CELL_OBJECT* cop;
|
|
VECTOR_NOPAD old_pos;
|
|
VECTOR_NOPAD pos;
|
|
short rotation;
|
|
char yang;
|
|
};
|
|
|
|
struct CYCLE_OBJECT
|
|
{
|
|
char* name;
|
|
short vx, vy;
|
|
short start1, stop1, speed1;
|
|
short start2, stop2, speed2;
|
|
};
|
|
|
|
CYCLE_OBJECT Lev0[2] =
|
|
{
|
|
{ "REDRVR", 0, 0, 6, 10, 2, 11, 15, 2 },
|
|
{ "NAVPIR34", 0, 0, 0, 6, 0, 7, 13, 0 }
|
|
};
|
|
|
|
CYCLE_OBJECT Lev1[] = {
|
|
{ "DOOR11", 0, 0, 1, 7, 2, 8, 14, 3 },
|
|
};
|
|
|
|
CYCLE_OBJECT Lev2[12] =
|
|
{
|
|
{ "DTSYN01", 0, 0, 0, 3, 0, 4, 14, 0 },
|
|
{ "DTSYN02", 0, 0, 0, 15, 0, -1, -1, 0 },
|
|
{ "F-MTSYN2", 0, 0, 0, 3, 0, 10, 14, 0 },
|
|
{ "DTSYN03", 0, 0, 0, 3, 0, -1, -1, 0 },
|
|
{ "SYN-CAS1", 0, 0, 0, 3, 0, 4, 14, 0 },
|
|
{ "SYNSLOT", 0, 0, 0, 3, 0, 4, 7, 0 },
|
|
{ "ENT1B", 0, 0, 0, 15, 0, -1, -1, 0 },
|
|
{ "FLAMINGO", 0, 0, 0, 3, 0, 9, 12, 0 },
|
|
{ "CYCLE-01", 0, 0, 0, 5, 1, 6, 11, 1 },
|
|
{ "CYCLE-02", 0, 0, 0, 3, 3, -1, -1, 0 },
|
|
{ "CYCLE-03", 0, 0, 0, 6, 7, 7, 13, 7 },
|
|
{ "CYCLE-04", 0, 0, 0, 6, 15, 7, 13, 15 }
|
|
};
|
|
|
|
CYCLE_OBJECT Lev3[] = {
|
|
{ "FWING11", 0, 0, 1, 7, 2, 8, 14, 3 }
|
|
};
|
|
|
|
|
|
CYCLE_OBJECT* Lev_CycleObjPtrs[] = {
|
|
Lev0,
|
|
Lev1,
|
|
Lev2,
|
|
Lev3
|
|
};
|
|
|
|
int Num_LevCycleObjs[] = { 2, 0, 12, 0 };
|
|
|
|
ANIMATED_OBJECT Lev0AnimObjects[9] =
|
|
{
|
|
{ 0, 0, "TLIGHT01", 0 },
|
|
{ 1, 0, "TLIGHT02", 0 },
|
|
{ 2, 0, "SLIGHT01", 1 },
|
|
{ 3, 0, "LOW_SLIGHT01", 1 },
|
|
{ 4, 0, "DLIGHT01", 1 },
|
|
{ 5, 0, "STRUT", 0 },
|
|
{ 6, 0, "NPLIGHT", 0 },
|
|
{ 7, 0, "TLIGHT01_LOW", 0 },
|
|
{ 8, 0, "TLIGHT02_LOW", 0 }
|
|
};
|
|
|
|
ANIMATED_OBJECT Lev1AnimObjects[5] =
|
|
{
|
|
{ 0, 0, "TLIGHT1", 0 },
|
|
{ 1, 0, "TLIGHT2", 0 },
|
|
{ 2, 0, "SLIGHT1", 1 },
|
|
{ 3, 0, "SLIGHT2", 1 },
|
|
{ 4, 0, "DLIGHT1", 1 }
|
|
};
|
|
|
|
ANIMATED_OBJECT Lev2AnimObjects[5] =
|
|
{
|
|
{ 0, 0, "TLIGHT01", 0 },
|
|
{ 1, 0, "TLIGHT02", 0 },
|
|
{ 2, 0, "SLIGHT01", 1 },
|
|
{ 3, 0, "DLIGHT01", 1 },
|
|
{ 4, 0, "SLIGHT02", 1 }
|
|
};
|
|
|
|
ANIMATED_OBJECT Lev3AnimObjects[4] =
|
|
{
|
|
{ 0, 0, "TLIGHT01", 0 },
|
|
{ 1, 0, "TLIGHT02", 0 },
|
|
{ 2, 0, "SLIGHT01", 0 },
|
|
{ 3, 0, "MLIGHT01", 0 }
|
|
};
|
|
|
|
ANIMATED_OBJECT* Level_AnimatingObjectPtrs[] = {
|
|
Lev0AnimObjects,
|
|
Lev1AnimObjects,
|
|
Lev2AnimObjects,
|
|
Lev3AnimObjects
|
|
};
|
|
|
|
int Level_NumAnimatedObjects[] = {
|
|
numberOf(Lev0AnimObjects),
|
|
numberOf(Lev1AnimObjects),
|
|
numberOf(Lev2AnimObjects),
|
|
numberOf(Lev3AnimObjects)
|
|
};
|
|
|
|
// sound ids for SOUND_BANK_SFX
|
|
SMASHABLE_OBJECT smashable[] =
|
|
{
|
|
{ 0, "", 1, 0, 800 }, // default
|
|
{ 0, "CONE_TASTIC", 1, 0, 1400 },
|
|
{ 0, "CONE1_TASTIC", 1, 0, 1400 },
|
|
{ 0, "CONE2_TASTIC", 1, 0, 1400 },
|
|
{ 0, "BOX_TASTIC", 0, -6000, 4096 },
|
|
{ 0, "BOX2_TASTIC", 0, -6000, 4096 },
|
|
{ 0, "BOX3_TASTIC", 0, -6000, 4096 },
|
|
{ 0, "BIN_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "BARRIER_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "BARRIER1_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "BARREL_TASTIC", 2, -3300, 2400 },
|
|
{ 0, "BARREL1_TASTIC", 2, -3300, 2400 },
|
|
{ 0, "BARREL2_TASTIC", 2, -3300, 2400 },
|
|
{ 0, "TABLE_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "BENCH_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "CHAIR_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "CHAIR1_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "CHAIR2_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "UMBRELLA_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "UMBRELLA1_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "PHONE_TASTIC", 2, -3300, 3600 },
|
|
{ 0, "PHONE1_TASTIC", 2, -3300, 3600 },
|
|
{ 0, "SIGN00_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "NEWS_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "PARKING_TASTIC", 2, -7500, 4096 },
|
|
{ 0, "DRINKS_TASTIC", 2, -3300, 3600 },
|
|
{ 0, "FENCE_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "FENCE00_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "FENCE01_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "FENCE02_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "FENCE03_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "FENCE04_TASTIC", 3, -6500, 3200 },
|
|
{ 0, "CONE_TASTIC1", 1, 0, 800 },
|
|
{ 0, "CONE_TASTIC2", 1, 0, 800 },
|
|
{ 0, "CONE_TASTIC3", 1, 0, 800 },
|
|
{ 0, "CONE_TASTIC4", 1, 0, 800 },
|
|
{ 0, 0, 0, 0, 0 }
|
|
};
|
|
|
|
|
|
int num_anim_objects = 0;
|
|
int num_cycle_obj = 0;
|
|
|
|
TEXTURE_DETAILS cycle_tex[12];
|
|
DR_LOAD cyclecluts[12];
|
|
|
|
int cycle_phase = 0;
|
|
int cycle_timer = 0;
|
|
|
|
// [D] [T]
|
|
void InitCyclingPals(void)
|
|
{
|
|
int i;
|
|
|
|
// only enabled at Night
|
|
if (gTimeOfDay != 3)
|
|
{
|
|
num_cycle_obj = 0;
|
|
return;
|
|
}
|
|
|
|
num_cycle_obj = Num_LevCycleObjs[GameLevel];
|
|
CYCLE_OBJECT* cyc = Lev_CycleObjPtrs[GameLevel];
|
|
|
|
for (i = 0; i < num_cycle_obj; i++)
|
|
{
|
|
GetTextureDetails(cyc->name, &cycle_tex[i]);
|
|
cyc++;
|
|
}
|
|
|
|
cycle_phase = 0;
|
|
cycle_timer = 0;
|
|
}
|
|
|
|
// [D] [T]
|
|
void ColourCycle(void)
|
|
{
|
|
ushort temp;
|
|
ushort* bufaddr;
|
|
CYCLE_OBJECT* cyc;
|
|
int i;
|
|
RECT16 vram;
|
|
|
|
if (!num_cycle_obj)
|
|
return;
|
|
|
|
if (LoadingArea != 0)
|
|
{
|
|
cycle_phase = 0;
|
|
return;
|
|
}
|
|
|
|
vram.w = 16;
|
|
vram.h = 1;
|
|
cyc = Lev_CycleObjPtrs[GameLevel];
|
|
|
|
for (i = 0; i < num_cycle_obj; i++)
|
|
{
|
|
bufaddr = (u_short*)cyclecluts[i].p;
|
|
|
|
if (tpageloaded[cycle_tex[i].texture_page] != 0)
|
|
{
|
|
if (cycle_phase == 0)
|
|
{
|
|
// initialize
|
|
temp = texture_cluts[cycle_tex[i].texture_page][cycle_tex[i].texture_number];
|
|
|
|
cyc->vx = vram.x = (temp & 0x3f) << 4;
|
|
cyc->vy = vram.y = (temp >> 6);
|
|
|
|
StoreImage(&vram, (u_long*)bufaddr);
|
|
}
|
|
else
|
|
{
|
|
if ((cycle_timer & cyc->speed1) == 0)
|
|
{
|
|
if (cyc->start1 != -1)
|
|
{
|
|
temp = bufaddr[cyc->start1];
|
|
memmove((u_char*)(bufaddr + cyc->start1), (u_char*)(bufaddr + cyc->start1 + 1), (cyc->stop1 - cyc->start1) << 1);
|
|
|
|
bufaddr[cyc->stop1] = temp;
|
|
}
|
|
}
|
|
|
|
if ((cycle_timer & cyc->speed2) == 0)
|
|
{
|
|
if (cyc->start2 != -1)
|
|
{
|
|
temp = bufaddr[cyc->start2];
|
|
memmove((u_char*)(bufaddr + cyc->start2), (u_char*)(bufaddr + cyc->start2 + 1), (cyc->stop2 - cyc->start2) << 1);
|
|
|
|
bufaddr[cyc->stop2] = temp;
|
|
}
|
|
}
|
|
|
|
vram.x = cyc->vx;
|
|
vram.y = cyc->vy;
|
|
|
|
SetDrawLoad(&cyclecluts[i], &vram);
|
|
|
|
addPrim(current->ot, &cyclecluts[i]);
|
|
}
|
|
}
|
|
|
|
cyc++;
|
|
}
|
|
|
|
if (cycle_phase != 0)
|
|
cycle_timer++;
|
|
|
|
cycle_phase ^= 1;
|
|
}
|
|
|
|
|
|
// [D] [T]
|
|
void FindSmashableObjects(void)
|
|
{
|
|
SMASHABLE_OBJECT* sip;
|
|
|
|
sip = smashable;
|
|
while (sip->name != NULL)
|
|
{
|
|
sip->modelIdx = FindModelIdxWithName(sip->name);
|
|
sip++;
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void InitAnimatingObjects(void)
|
|
{
|
|
ANIMATED_OBJECT* aop;
|
|
|
|
int loop;
|
|
MODEL* modelPtr;
|
|
|
|
num_anim_objects = Level_NumAnimatedObjects[GameLevel];
|
|
aop = Level_AnimatingObjectPtrs[GameLevel];
|
|
|
|
for (loop = 0; loop < num_anim_objects; loop++)
|
|
{
|
|
// My way
|
|
int model_idx = FindModelIdxWithName(aop->name);
|
|
|
|
if (model_idx != -1 && modelpointers[model_idx] != &dummyModel)
|
|
{
|
|
modelPtr = modelpointers[model_idx];
|
|
modelPtr->flags2 |= MODEL_FLAG_ANIMOBJ;
|
|
|
|
if (aop->LitPoly)
|
|
modelPtr->flags2 |= MODEL_FLAG_LAMP;
|
|
|
|
aop->model_num = model_idx;
|
|
|
|
// [A] store animated object number in normals pointer
|
|
// after all it was always unused
|
|
modelPtr->normals = loop;
|
|
|
|
if (modelPtr->instance_number != -1 &&
|
|
modelpointers[modelPtr->instance_number] != &dummyModel)
|
|
{
|
|
modelPtr = modelpointers[modelPtr->instance_number];
|
|
modelPtr->flags2 |= MODEL_FLAG_ANIMOBJ;
|
|
|
|
if (aop->LitPoly)
|
|
modelPtr->flags2 |= MODEL_FLAG_LAMP;
|
|
|
|
// [A] store animated object number in normals pointer
|
|
// after all it was always unused
|
|
modelPtr->normals = loop;
|
|
}
|
|
}
|
|
else
|
|
aop->model_num = -1;
|
|
|
|
aop++;
|
|
}
|
|
|
|
FindSmashableObjects();
|
|
}
|
|
|
|
// [D] [T]
|
|
void InitSpooledAnimObj(int model_number)
|
|
{
|
|
int i;
|
|
ANIMATED_OBJECT* aop;
|
|
MODEL* modelPtr;
|
|
|
|
if (model_number == -1)
|
|
return;
|
|
|
|
aop = Level_AnimatingObjectPtrs[GameLevel];
|
|
|
|
// Reflections way
|
|
for (i = 0; i < num_anim_objects; i++)
|
|
{
|
|
if (aop->model_num == model_number)
|
|
{
|
|
modelPtr = modelpointers[model_number];
|
|
modelPtr->flags2 |= MODEL_FLAG_ANIMOBJ;
|
|
|
|
if (aop->LitPoly)
|
|
modelPtr->flags2 |= MODEL_FLAG_LAMP;
|
|
|
|
// [A] store animated object number in normals pointer
|
|
// after all it was always unused
|
|
modelPtr->normals = i;
|
|
|
|
break;
|
|
}
|
|
aop++;
|
|
}
|
|
}
|
|
|
|
GARAGE_DOOR CurrentGarage;
|
|
|
|
// [D] [T]
|
|
void int_garage_door(void)
|
|
{
|
|
CurrentGarage.cop = NULL;
|
|
}
|
|
|
|
// [A] [T]
|
|
void DrawAllAnimatingObjects(CELL_OBJECT** objects, int num_animated)
|
|
{
|
|
ANIMATED_OBJECT* aop;
|
|
CELL_OBJECT* cop;
|
|
MODEL* model;
|
|
int i, j;
|
|
int type;
|
|
|
|
aop = Level_AnimatingObjectPtrs[GameLevel];
|
|
|
|
for (i = 0; i < num_animated; i++)
|
|
{
|
|
cop = objects[i];
|
|
type = cop->type;
|
|
model = modelpointers[type];
|
|
|
|
// [A] optimized
|
|
animate_object(cop, aop[model->normals].internal_id);
|
|
|
|
#if 0
|
|
type = model->instance_number == -1 ? type : model->instance_number;
|
|
for (j = 0; j < num_anim_objects; j++)
|
|
{
|
|
if (type == aop->model_num)
|
|
{
|
|
animate_object(cop, aop->internal_id);
|
|
aop -= j;
|
|
break;
|
|
}
|
|
|
|
aop++;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void animate_object(CELL_OBJECT* cop, int type)
|
|
{
|
|
char phase;
|
|
int yang;
|
|
|
|
yang = cop->yang * 64;
|
|
|
|
// [A] Rev 1.1 has less of those types
|
|
|
|
if (GameLevel == 0)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 0:
|
|
case 7:
|
|
yang += 1024;
|
|
phase = junctionLightsPhase[yang + 128 >> 10 & 1];
|
|
|
|
if (phase == 1)
|
|
{
|
|
AddTrafficLight(cop, 0, -0x2c4, -0x2d, 0x200, yang);
|
|
}
|
|
else if (phase == 2)
|
|
{
|
|
AddTrafficLight(cop, 0, -0x284, -0x2d, 0x400, yang);
|
|
}
|
|
else if (phase == 3)
|
|
{
|
|
AddTrafficLight(cop, 0, -0x244, -0x2d, 0x800, yang);
|
|
}
|
|
break;
|
|
case 1:
|
|
case 8:
|
|
phase = junctionLightsPhase[yang + 128 >> 10 & 1];
|
|
|
|
if (phase == 1)
|
|
{
|
|
AddTrafficLight(cop, 0x196, -0x2c4, -0x2e, 0x200, yang);
|
|
}
|
|
else if (phase == 2)
|
|
{
|
|
AddTrafficLight(cop, 0x196, -0x292, -0x2e, 0x400, yang);
|
|
}
|
|
else if (phase == 3)
|
|
{
|
|
AddTrafficLight(cop, 0x196, -0x252, -0x2e, 0x800, yang);
|
|
}
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, 0x1ad, -0x4d2, 0, 0, 3);
|
|
break;
|
|
case 4:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, -0x1b0, -0x4d9, 0, 0, 3);
|
|
AddLightEffect(cop, 0x1b0, -0x4d9, 0, 0, 3);
|
|
break;
|
|
case 5:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, 0, -0x50, 0, 2, 2);
|
|
break;
|
|
case 6:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, 0xea, -0x47a, 0, 0, 3);
|
|
AddLightEffect(cop, -0xea, -0x47a, 0, 0, 3);
|
|
}
|
|
}
|
|
else if (GameLevel == 1)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 0:
|
|
phase = junctionLightsPhase[yang + 128 >> 10 & 1];
|
|
|
|
if (phase == 2)
|
|
{
|
|
AddTrafficLight(cop, -0x1a1, -800, -0x1e, 0x400, yang);
|
|
}
|
|
else if (phase == 1)
|
|
{
|
|
AddTrafficLight(cop, -0x1ea, -800, -0x1e, 0x200, yang);
|
|
}
|
|
else if (phase == 3)
|
|
{
|
|
AddTrafficLight(cop, -0x157, -800, -0x1e, 0x800, yang);
|
|
}
|
|
|
|
break;
|
|
case 2:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddSmallStreetLight(cop, 0xe6, -0x442, 0, 0);
|
|
break;
|
|
case 3:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, -0x265, -0x7d2, 0, 0, 3);
|
|
break;
|
|
case 4:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, -0x250, -2000, 0, 0, 3);
|
|
AddLightEffect(cop, 0x252, -2000, 0, 0, 3);
|
|
break;
|
|
}
|
|
}
|
|
else if (GameLevel == 2)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 0:
|
|
phase = junctionLightsPhase[yang + 128 >> 10 & 1];
|
|
|
|
if (phase == 1)
|
|
{
|
|
AddTrafficLight(cop, -0x857, -0x458, -0x44, 0x200, yang);
|
|
AddTrafficLight(cop, -0x520, -0x421, -0x44, 0x200, yang);
|
|
AddTrafficLight(cop, -0x202, -0x400, -0x44, 0x200, yang);
|
|
}
|
|
else if (phase == 2)
|
|
{
|
|
AddTrafficLight(cop, -0x85c, -0x3fd, -0x41, 0x400, yang);
|
|
AddTrafficLight(cop, -0x51e, -0x3d4, -0x41, 0x400, yang);
|
|
AddTrafficLight(cop, -0x208, -0x3ab, -0x41, 0x400, yang);
|
|
}
|
|
else if (phase == 3)
|
|
{
|
|
AddTrafficLight(cop, -0x85a, -0x3a9, -0x3e, 0x800, yang);
|
|
AddTrafficLight(cop, -0x51d, -0x381, -0x3e, 0x800, yang);
|
|
AddTrafficLight(cop, -0x206, -0x353, -0x3e, 0x800, yang);
|
|
}
|
|
break;
|
|
case 1:
|
|
phase = junctionLightsPhase[yang + 128 >> 10 & 1];
|
|
|
|
if (phase == 1)
|
|
{
|
|
AddTrafficLight(cop, -4, -0x219, -0x29, 0x200, yang);
|
|
}
|
|
else if (phase == 2)
|
|
{
|
|
AddTrafficLight(cop, -4, -0x1d2, -0x29, 0x400, yang);
|
|
}
|
|
else if (phase == 3)
|
|
{
|
|
AddTrafficLight(cop, -4, -0x18b, -0x29, 0x800, yang);
|
|
}
|
|
break;
|
|
case 2:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, -0x348, -0x7b4, -0x3d, 0, 3);
|
|
break;
|
|
case 3:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, -0x361, -0x8c9, 0, 0, 3);
|
|
AddLightEffect(cop, 0x361, -0x8c9, 0, 0, 3);
|
|
break;
|
|
case 4:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
if (cop->pos.vx - 137190U < 50687 && cop->pos.vz > 713372 && cop->pos.vz < 719516)
|
|
{
|
|
AddSmallStreetLight(cop, -0x26c, -0x65, 0, 0);
|
|
break;
|
|
}
|
|
|
|
AddLightEffect(cop, -0x26c, -0x652, 0, 0, 3);
|
|
break;
|
|
}
|
|
}
|
|
else if (GameLevel == 3)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 0:
|
|
phase = junctionLightsPhase[yang + 128 >> 10 & 1];
|
|
|
|
if (phase == 1)
|
|
{
|
|
AddTrafficLight(cop, -0x2cf, -0x38a, -0x16, 0x200, yang);
|
|
}
|
|
else if (phase == 2)
|
|
{
|
|
AddTrafficLight(cop, -0x2cf, -0x345, -0x16, 0x400, yang);
|
|
}
|
|
else if (phase == 3)
|
|
{
|
|
AddTrafficLight(cop, -0x2cf, -0x2fa, -0x16, 0x800, yang);
|
|
}
|
|
break;
|
|
case 1:
|
|
phase = junctionLightsPhase[yang + 128 >> 10 & 1];
|
|
|
|
if (phase == 1)
|
|
{
|
|
AddTrafficLight(cop, 0, -0x28e, -0x15, 0x200, yang);
|
|
}
|
|
else if (phase == 2)
|
|
{
|
|
AddTrafficLight(cop, 0, -0x242, -0x15, 0x400, yang);
|
|
}
|
|
else if (phase == 3)
|
|
{
|
|
AddTrafficLight(cop, 0, -0x1fd, -0x15, 0x800, yang);
|
|
}
|
|
break;
|
|
case 2:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, -0x1f1, -0x59d, 0, 0, 3);
|
|
|
|
break;
|
|
case 3:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddLightEffect(cop, 0, -0xaa7, 0, 0, 3);
|
|
|
|
break;
|
|
case 4:
|
|
if (gLightsOn == 0)
|
|
break;
|
|
|
|
AddSmallStreetLight(cop, 0, -0x492, 0, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// [D] [T]
|
|
void animate_garage_door(void)
|
|
{
|
|
short* felony;
|
|
int dz;
|
|
int dx;
|
|
|
|
if (CurrentGarage.cop == NULL)
|
|
return;
|
|
|
|
int playerCarId = player[0].playerCarId;
|
|
|
|
if (gCurrentMissionNumber != 53 && CopsCanSeePlayer)
|
|
{
|
|
if (playerCarId < 0)
|
|
felony = &pedestrianFelony;
|
|
else
|
|
felony = &car_data[playerCarId].felonyRating;
|
|
|
|
if (*felony > FELONY_PURSUIT_MIN_VALUE)
|
|
{
|
|
CurrentGarage.cop->pos = CurrentGarage.old_pos;
|
|
CurrentGarage.cop = NULL;
|
|
return;
|
|
}
|
|
}
|
|
|
|
dx = ABS(CurrentGarage.old_pos.vx - car_data[playerCarId].hd.where.t[0]); // [A] bug fix
|
|
dz = ABS(CurrentGarage.old_pos.vz - car_data[playerCarId].hd.where.t[2]);
|
|
|
|
if (dx + dz > 6000 || gStopPadReads != 0)
|
|
{
|
|
if (CurrentGarage.pos.vy < CurrentGarage.old_pos.vy)
|
|
{
|
|
CurrentGarage.rotation -= 25;
|
|
CurrentGarage.pos.vy += 12;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dx + dz < 4000 && CurrentGarage.pos.vy > CurrentGarage.old_pos.vy - 400)
|
|
{
|
|
CurrentGarage.rotation += 25;
|
|
CurrentGarage.pos.vy -= 12;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|