REDRIVER2/src_rebuild/Game/C/denting.c

506 lines
11 KiB
C
Raw Normal View History

#include "driver2.h"
#include "denting.h"
#include "system.h"
#include "mission.h"
#include "cars.h"
#include "convert.h"
#include "pause.h"
#include "camera.h"
#include "draw.h"
#include "dr2roads.h"
#include "debris.h"
#include "players.h"
#include "main.h"
char* DentingFiles[] =
{
"LEVELS\\CHICAGO.DEN",
"LEVELS\\HAVANA.DEN",
"LEVELS\\VEGAS.DEN",
"LEVELS\\RIO.DEN",
};
2020-12-06 10:56:36 +01:00
// DO NOT CHANGE THIS!
#define NUM_DAMAGE_ZONES 6
#define MAX_FILE_DAMAGE_ZONE_VERTS 50
#define MAX_FILE_DAMAGE_ZONE_POLYS 70
2020-12-11 20:29:45 +01:00
#define MAX_FILE_DAMAGE_LEVELS 256
2020-12-06 10:56:36 +01:00
2021-04-25 22:47:53 +02:00
u_char gCarDamageZoneVerts[MAX_CAR_MODELS][NUM_DAMAGE_ZONES][MAX_DAMAGE_ZONE_VERTS];
u_char gHDCarDamageZonePolys[MAX_CAR_MODELS][NUM_DAMAGE_ZONES][MAX_DAMAGE_ZONE_POLYS];
u_char gHDCarDamageLevels[MAX_CAR_MODELS][MAX_DAMAGE_LEVELS];
2020-09-07 20:36:26 +02:00
// [D] [T]
void InitialiseDenting(void)
{
LoadDenting(GameLevel);
InitHubcap();
}
2020-09-07 20:36:26 +02:00
// [D] [T]
void DentCar(CAR_DATA *cp)
{
2020-09-07 20:36:26 +02:00
int Zone;
int Damage;
int MaxDamage;
DENTUVS *dentptr;
SVECTOR *CleanVertPtr;
2020-09-07 20:36:26 +02:00
int VertNo;
unsigned char *DamPtr;
SVECTOR *DamVertPtr;
2020-09-07 20:36:26 +02:00
MODEL *pCleanModel;
int model;
int Poly;
2020-12-28 11:07:24 +01:00
short tempDamage[256];
memset((u_char*)tempDamage, 0, sizeof(tempDamage));
2020-09-07 20:36:26 +02:00
MaxDamage = 0;
model = cp->ap.model;
cp->lowDetail = -1;
cp->ap.qy = 0;
cp->ap.qw = 0;
2020-09-07 20:36:26 +02:00
pCleanModel = gCarCleanModelPtr[model];
2020-09-07 20:36:26 +02:00
// collect vertices from zones
if (pCleanModel != NULL)
{
VertNo = 0;
while (VertNo < pCleanModel->num_vertices)
tempDamage[VertNo++] = 0;
2020-09-07 20:36:26 +02:00
Zone = 0;
do {
2020-09-07 20:36:26 +02:00
Damage = cp->ap.damage[Zone];
2020-09-07 20:36:26 +02:00
if (Damage > MaxDamage)
MaxDamage = Damage;
2020-09-07 20:36:26 +02:00
DamPtr = gCarDamageZoneVerts[cp->ap.model][Zone];
2020-09-07 20:36:26 +02:00
VertNo = 0;
2020-12-06 10:56:36 +01:00
while (VertNo < MAX_DAMAGE_ZONE_VERTS && *DamPtr != 0xFF)
{
2020-09-07 20:36:26 +02:00
if (tempDamage[*DamPtr] == 0)
tempDamage[*DamPtr] += Damage;
else
2020-09-07 20:36:26 +02:00
tempDamage[*DamPtr] += Damage / 2;
DamPtr++;
2020-09-07 20:36:26 +02:00
VertNo++;
}
2020-09-07 20:36:26 +02:00
Zone++;
2020-12-06 10:56:36 +01:00
} while (Zone < NUM_DAMAGE_ZONES);
}
2020-09-07 20:36:26 +02:00
// update vertices positon
if (gCarCleanModelPtr[model] != NULL && gCarDamModelPtr[model] != NULL)
{
2020-09-07 20:36:26 +02:00
DamVertPtr = (SVECTOR *)gCarDamModelPtr[model]->vertices;
CleanVertPtr = (SVECTOR *)gCarCleanModelPtr[model]->vertices;
2020-05-13 11:56:41 +02:00
2020-09-07 20:36:26 +02:00
VertNo = 0;
while (VertNo < pCleanModel->num_vertices)
{
gTempCarVertDump[cp->id][VertNo].vx = CleanVertPtr->vx + FIXEDH((DamVertPtr->vx - CleanVertPtr->vx) * tempDamage[VertNo] / 2);
gTempCarVertDump[cp->id][VertNo].vy = CleanVertPtr->vy + FIXEDH((DamVertPtr->vy - CleanVertPtr->vy) * tempDamage[VertNo] / 2);
gTempCarVertDump[cp->id][VertNo].vz = CleanVertPtr->vz + FIXEDH((DamVertPtr->vz - CleanVertPtr->vz) * tempDamage[VertNo] / 2);
DamVertPtr++;
CleanVertPtr++;
2020-09-07 20:36:26 +02:00
VertNo++;
}
}
2020-09-07 20:36:26 +02:00
// update polygon UVs
if (pCleanModel != NULL)
{
2020-09-07 20:36:26 +02:00
dentptr = gTempHDCarUVDump[cp->id];
// reset UV coordinates
2020-09-07 20:36:26 +02:00
Poly = 0;
while (Poly < pCleanModel->num_polys)
{
2020-09-07 20:36:26 +02:00
dentptr->u3 = 0;
Poly++;
dentptr++;
}
2020-09-07 20:36:26 +02:00
Zone = 0;
do {
2020-09-07 20:36:26 +02:00
Damage = cp->ap.damage[Zone];
2020-09-07 20:36:26 +02:00
Poly = 0;
2020-12-06 10:56:36 +01:00
while (Poly < MAX_DAMAGE_ZONE_POLYS && gHDCarDamageZonePolys[cp->ap.model][Zone][Poly] != 0xFF)
{
2020-09-07 20:36:26 +02:00
dentptr = gTempHDCarUVDump[cp->id] + gHDCarDamageZonePolys[cp->ap.model][Zone][Poly];
// add a damage level
dentptr->u3 += (Damage >> 0xA);
// clamp level
2020-09-07 20:36:26 +02:00
if (dentptr->u3 > 2)
dentptr->u3 = 2;
2020-09-07 20:36:26 +02:00
Poly++;
}
2020-09-07 20:36:26 +02:00
Zone++;
2020-12-06 10:56:36 +01:00
} while (Zone < NUM_DAMAGE_ZONES);
2020-09-07 20:36:26 +02:00
Poly = 0;
2020-09-07 20:36:26 +02:00
DamPtr = gHDCarDamageLevels[model];
dentptr = gTempHDCarUVDump[cp->id];
while (Poly < pCleanModel->num_polys)
{
// calculate the UV offset with strange XORs
if(dentptr->u3 > 0)
dentptr->u3 = (*DamPtr ^ 1 ^ (*DamPtr ^ 1 | dentptr->u3)) * 64;
2020-09-07 20:36:26 +02:00
dentptr++;
2020-09-07 20:36:26 +02:00
DamPtr++;
Poly++;
}
}
}
2020-09-07 20:36:26 +02:00
// [D] [T]
void CreateDentableCar(CAR_DATA *cp)
{
MODEL *srcModel;
SVECTOR *dst;
int count;
SVECTOR *src;
2020-06-06 16:39:09 +02:00
int vcount;
int model;
model = cp->ap.model;
2020-04-21 13:06:40 +02:00
srcModel = gCarCleanModelPtr[model];
if (srcModel != NULL)
2020-04-21 13:06:40 +02:00
{
src = (SVECTOR *)srcModel->vertices;
dst = gTempCarVertDump[cp->id];
2020-04-21 13:06:40 +02:00
2020-06-06 16:39:09 +02:00
vcount = srcModel->num_vertices;
2020-04-21 13:06:40 +02:00
2020-06-06 16:39:09 +02:00
while (vcount-- != -1)
*dst++ = *src++;
count = 0;
while (count < srcModel->num_polys)
2020-04-21 13:06:40 +02:00
{
2020-06-06 16:39:09 +02:00
gTempHDCarUVDump[cp->id][count].u3 = 0;
count++;
}
}
2020-12-12 08:39:44 +01:00
else
{
printError("gCarCleanModelPtr is NULL in CreateDentableCar\n");
}
2020-04-21 13:06:40 +02:00
srcModel = gCarLowModelPtr[model];
if (srcModel != NULL)
2020-04-21 13:06:40 +02:00
{
count = 0;
2020-06-06 16:39:09 +02:00
while (count < srcModel->num_polys)
2020-04-21 13:06:40 +02:00
{
2020-06-06 16:39:09 +02:00
gTempLDCarUVDump[cp->id][count].u3 = 0;
count++;
}
}
2020-12-12 08:39:44 +01:00
else
{
printError("gCarLowModelPtr is NULL in CreateDentableCar\n");
}
2020-06-06 16:39:09 +02:00
if (gDontResetCarDamage == 0)
2020-04-21 13:06:40 +02:00
{
2020-06-06 16:39:09 +02:00
count = 0;
2020-12-06 10:56:36 +01:00
while (count < NUM_DAMAGE_ZONES)
2020-06-06 16:39:09 +02:00
{
cp->ap.damage[count] = 0;
2020-06-06 16:39:09 +02:00
count++;
}
2020-04-21 13:06:40 +02:00
cp->totalDamage = 0;
}
}
2020-04-21 17:29:28 +02:00
extern HUBCAP gHubcap;
2020-12-08 18:12:17 +01:00
int gHubcapTime = 0;
2020-04-21 17:29:28 +02:00
2020-09-07 20:36:26 +02:00
// [D] [T]
void InitHubcap(void)
{
2020-06-06 16:39:09 +02:00
gHubcapTime = Random2(1) & 0x7ff;
}
// [D] [T]
2020-07-07 15:29:37 +02:00
void LoseHubcap(int car, int Hubcap, int Velocity)
{
2020-07-05 20:33:38 +02:00
SVECTOR InitialLocalAngle = { 0, 0, 10 };
CAR_DATA* cp;
2020-07-05 20:33:38 +02:00
SVECTOR* wheelDisp;
2020-07-07 15:29:37 +02:00
cp = &car_data[car];
2020-11-29 13:39:43 +01:00
// check speed and if hubcap lost
if (cp->hd.wheel_speed < 0 || (cp->ap.flags & 1 << Hubcap))
return;
2020-07-05 20:33:38 +02:00
wheelDisp = &cp->ap.carCos->wheelDisp[Hubcap];
2020-11-29 13:39:43 +01:00
cp->ap.flags |= (1 << Hubcap); // [A] cars now hold hubcaps
2020-07-05 20:33:38 +02:00
gHubcap.Position.vx = wheelDisp->vx;
gHubcap.Position.vy = wheelDisp->vy;
gHubcap.Position.vz = wheelDisp->vz;
2020-07-05 20:33:38 +02:00
2020-11-29 13:39:43 +01:00
SetRotMatrix(&cp->hd.where);
_MatrixRotate(&gHubcap.Position);
2020-07-05 20:33:38 +02:00
2021-03-25 13:42:57 +01:00
gHubcap.Position.vx += cp->hd.where.t[0];
gHubcap.Position.vy -= cp->hd.where.t[1];
gHubcap.Position.vz += cp->hd.where.t[2];
2020-07-05 20:33:38 +02:00
2020-11-29 13:39:43 +01:00
gHubcap.Orientation = cp->hd.where;
2021-03-25 13:42:57 +01:00
gHubcap.Rotation = 0;
2020-11-29 13:39:43 +01:00
if (Hubcap > 1)
{
gHubcap.Orientation.m[0][0] = -gHubcap.Orientation.m[0][0];
gHubcap.Orientation.m[1][0] = -gHubcap.Orientation.m[1][0];
2020-07-05 20:33:38 +02:00
2020-11-29 13:39:43 +01:00
gHubcap.Orientation.m[2][0] = -gHubcap.Orientation.m[2][0];
gHubcap.Orientation.m[0][2] = -gHubcap.Orientation.m[0][2];
2020-07-05 20:33:38 +02:00
2020-11-29 13:39:43 +01:00
gHubcap.Orientation.m[1][2] = -gHubcap.Orientation.m[1][2];
gHubcap.Orientation.m[2][2] = -gHubcap.Orientation.m[2][2];
}
2020-11-29 13:39:43 +01:00
gHubcap.Duration = 100;
gHubcap.Direction.vx = FIXEDH(FIXEDH(cp->st.n.angularVelocity[1]) * wheelDisp->vz) + FIXEDH(cp->st.n.linearVelocity[0]);
2020-11-29 13:39:43 +01:00
gHubcap.Direction.vy = FIXEDH(cp->st.n.linearVelocity[1]);
gHubcap.Direction.vz = FIXEDH(-FIXEDH(cp->st.n.angularVelocity[1]) * wheelDisp->vx) + FIXEDH(cp->st.n.linearVelocity[2]);
}
// [A]
void HandlePlayerHubcaps(int playerId)
{
2020-07-05 20:33:38 +02:00
int VelocityMagnitude;
CAR_DATA* cp;
2020-07-07 15:29:37 +02:00
int playerCarId;
2020-07-05 20:33:38 +02:00
2020-07-07 15:29:37 +02:00
playerCarId = player[playerId].playerCarId;
if (playerCarId < 0)
return;
2020-07-07 15:29:37 +02:00
cp = &car_data[playerCarId];
if (gHubcap.Duration < 1 && gHubcapTime == 0)
2020-07-05 20:33:38 +02:00
{
2020-07-07 15:29:37 +02:00
VelocityMagnitude = cp->st.n.angularVelocity[0] + cp->st.n.angularVelocity[1] + cp->st.n.angularVelocity[2];
2020-07-05 20:33:38 +02:00
if (VelocityMagnitude < -1000000)
2020-07-05 20:33:38 +02:00
{
2020-07-07 15:29:37 +02:00
LoseHubcap(playerCarId, Random2(2) & 1, VelocityMagnitude);
2020-07-05 20:33:38 +02:00
VelocityMagnitude = 3;
}
2020-07-05 20:33:38 +02:00
else if (VelocityMagnitude > 1000001)
{
2020-07-07 15:29:37 +02:00
LoseHubcap(playerCarId, Random2(4) & 1 | 2, VelocityMagnitude);
2020-07-05 20:33:38 +02:00
VelocityMagnitude = 5;
}
2020-07-05 20:33:38 +02:00
else
return;
gHubcapTime = Random2(VelocityMagnitude) & 0x417;
}
}
// [D] [T]
void MoveHubcap()
{
int CurrentMapHeight;
int savecombo;
int cmb;
VECTOR ShadowPos;
VECTOR Position;
MATRIX Orientation;
CVECTOR col = {72,72,72};
2021-05-15 21:58:23 +02:00
InitMatrix(Orientation);
2021-03-25 13:42:57 +01:00
if (pauseflag == 0)
{
if(gHubcapTime > 0)
gHubcapTime--;
}
// draw current hubcap
if (gHubcap.Duration > 0)
2020-07-05 20:33:38 +02:00
{
if (pauseflag == 0 && CurrentPlayerView == 0)
{
2020-07-05 20:33:38 +02:00
gHubcap.Duration--;
// move hubcap
gHubcap.Position.vx += gHubcap.Direction.vx;
gHubcap.Position.vy += gHubcap.Direction.vy;
gHubcap.Position.vz += gHubcap.Direction.vz;
2020-07-05 20:33:38 +02:00
2021-03-25 13:42:57 +01:00
gHubcap.Rotation -= 220;
_RotMatrixX(&Orientation, gHubcap.Rotation);
2020-07-05 20:33:38 +02:00
gHubcap.Direction.vy += 5;
2020-07-05 20:33:38 +02:00
CurrentMapHeight = MapHeight(&gHubcap.Position);
2020-07-05 20:33:38 +02:00
2020-12-01 13:06:24 +01:00
if (gHubcap.Position.vy >= -40 - CurrentMapHeight)
{
gHubcap.Direction.vy = -(gHubcap.Direction.vy / 2);
2020-12-01 13:06:24 +01:00
gHubcap.Position.vy = -40 - CurrentMapHeight;
}
}
2020-07-05 20:33:38 +02:00
2021-03-25 13:42:57 +01:00
MulMatrix0(&gHubcap.Orientation, &Orientation, &Orientation);
2020-07-05 20:33:38 +02:00
ShadowPos.vx = gHubcap.Position.vx - camera_position.vx;
ShadowPos.vy = -MapHeight(&gHubcap.Position);
ShadowPos.vz = gHubcap.Position.vz - camera_position.vz;
2020-07-05 20:33:38 +02:00
Position.vx = ShadowPos.vx;
Position.vy = gHubcap.Position.vy - camera_position.vy;
Position.vz = ShadowPos.vz;
2020-07-05 20:33:38 +02:00
SetRotMatrix(&inv_camera_matrix);
2020-07-05 20:33:38 +02:00
_MatrixRotate(&Position);
savecombo = combointensity;
2020-07-05 20:33:38 +02:00
if (gTimeOfDay == 3)
{
cmb = (combointensity & 0xffU) / 3;
combointensity = cmb << 0x10 | cmb << 8 | cmb;
}
2020-07-05 20:33:38 +02:00
RenderModel(gHubcapModelPtr, &Orientation, &Position, 0, 0, 0, 0);
ShadowPos.vy -= camera_position.vy;
2020-07-05 20:33:38 +02:00
combointensity = savecombo;
2020-07-05 20:33:38 +02:00
RoundShadow(&ShadowPos, &col, 65);
}
}
#ifndef PSX
// [A] loads car model from file
char* LoadCarDentingFromFile(char* dest, int modelNumber)
{
char* mem;
char filename[64];
sprintf(filename, "LEVELS\\%s\\CARMODEL_%d.DEN", LevelNames[GameLevel], modelNumber);
if(FileExists(filename))
{
2021-04-04 11:24:16 +02:00
mem = dest ? dest : ((char*)_other_buffer + modelNumber * 4096);
// get model from file
Loadfile(filename, mem);
return mem;
}
return NULL;
}
#endif
2020-09-07 20:36:26 +02:00
// [D] [T]
void ProcessDentLump(char *lump_ptr, int lump_size)
{
2020-06-06 16:39:09 +02:00
int model;
int i;
2020-04-20 15:04:17 +02:00
int offset;
2020-12-28 11:07:24 +01:00
u_char* mem;
2020-04-12 13:40:27 +02:00
2020-06-06 16:39:09 +02:00
i = 0;
while (i < MAX_CAR_MODELS)
2020-06-06 16:39:09 +02:00
{
model = MissionHeader->residentModels[i];
if (model == 13)
{
2020-06-06 16:39:09 +02:00
model = 10 - (MissionHeader->residentModels[0] + MissionHeader->residentModels[1] + MissionHeader->residentModels[2]);
2020-04-20 15:04:17 +02:00
2020-06-06 16:39:09 +02:00
if (model < 1)
model = 1;
else if(model > 4)
model = 4;
}
2020-06-06 16:39:09 +02:00
if (model != -1)
{
2020-06-06 16:39:09 +02:00
offset = *(int *)(lump_ptr + model * 4);
2020-12-28 11:07:24 +01:00
mem = (u_char*)lump_ptr;
#ifndef PSX
char* newDenting = LoadCarDentingFromFile(NULL, model);
if(newDenting)
{
2020-12-28 11:07:24 +01:00
mem = (u_char*)newDenting;
offset = 0;
}
#endif
2020-04-20 15:04:17 +02:00
2020-12-28 11:07:24 +01:00
memcpy((u_char*)gCarDamageZoneVerts[i], mem + offset, NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_VERTS);
2020-12-06 10:56:36 +01:00
offset += NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_VERTS;
2020-12-28 11:07:24 +01:00
memcpy((u_char*)gHDCarDamageZonePolys[i], mem + offset, NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_POLYS);
2020-12-06 10:56:36 +01:00
offset += NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_POLYS;
2020-12-28 11:07:24 +01:00
memcpy((u_char*)gHDCarDamageLevels[i], mem + offset, MAX_FILE_DAMAGE_LEVELS);
}
2020-06-06 16:39:09 +02:00
i++;
}
}
2020-09-07 20:36:26 +02:00
// [D] [T]
void SetupSpecDenting(char *loadbuffer)
{
2020-12-06 10:56:36 +01:00
int offset;
// [A] this is better
2020-12-28 11:07:24 +01:00
memcpy((u_char*)gCarDamageZoneVerts[4], (u_char*)loadbuffer, NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_VERTS);
2020-12-06 10:56:36 +01:00
offset = NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_VERTS;
2020-12-28 11:07:24 +01:00
memcpy((u_char*)gHDCarDamageZonePolys[4], (u_char*)loadbuffer + offset, NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_POLYS);
2020-12-06 10:56:36 +01:00
offset += NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_POLYS;
2020-12-28 11:07:24 +01:00
memcpy((u_char*)gHDCarDamageLevels[4], (u_char*)loadbuffer + offset, MAX_FILE_DAMAGE_LEVELS);
}
// [D] [T]
void LoadDenting(int level)
{
2021-04-04 11:24:16 +02:00
LoadfileSeg(DentingFiles[level], (char*)_other_buffer, 0, 12727);
ProcessDentLump((char*)_other_buffer, 0);
}