mirror of
https://github.com/OpenDriver2/REDRIVER2.git
synced 2024-11-22 10:22:48 +01:00
0cfa16e3d5
- some OD2 porting prepaprations - fix CreateRoadblock refactoring bug (missing noMoreCars setup)
552 lines
10 KiB
C
552 lines
10 KiB
C
#include "driver2.h"
|
|
#include "drivinggames.h"
|
|
#include "scores.h"
|
|
#include "mission.h"
|
|
#include "cutscene.h"
|
|
#include "main.h"
|
|
#include "system.h"
|
|
#include "draw.h"
|
|
#include "cars.h"
|
|
#include "players.h"
|
|
#include "cosmetic.h"
|
|
#include "bcollide.h"
|
|
#include "camera.h"
|
|
#include "convert.h"
|
|
#include "gamesnd.h"
|
|
#include "map.h"
|
|
#include "sound.h"
|
|
#include "glaunch.h"
|
|
|
|
#include "ASM/rndrasm.h"
|
|
|
|
struct TRAILBLAZER_DATA
|
|
{
|
|
int x, z;
|
|
short y, rot;
|
|
};
|
|
|
|
struct SMASHED_CONE
|
|
{
|
|
char cone;
|
|
u_char active : 7;
|
|
u_char side : 1;
|
|
short rot_speed;
|
|
VECTOR velocity;
|
|
};
|
|
|
|
MODEL* gTrailblazerConeModel;
|
|
SMASHED_CONE smashed_cones[MAX_SMASHED_CONES];
|
|
|
|
TRAILBLAZER_DATA *gTrailblazerData;
|
|
int gTrailblazerConeCount;
|
|
int gTrailblazerConeIndex;
|
|
static int gTrailblazerPrevConeDelay = 0;
|
|
|
|
static int wrongside[2][MAX_SMASHED_CONES];
|
|
static int current_smashed_cone = 0;
|
|
|
|
// [D] [T]
|
|
void InitDrivingGames(void)
|
|
{
|
|
char filename[64];
|
|
int i;
|
|
int j;
|
|
|
|
if (NewLevel)
|
|
gTrailblazerData = NULL;
|
|
|
|
gPlayerScore.time = 0;
|
|
gPlayerScore.items = 0;
|
|
gPlayerScore.P2time = 0;
|
|
gPlayerScore.P2items = 0;
|
|
|
|
if (GameType == GAME_GATERACE || GameType == GAME_TRAILBLAZER)
|
|
{
|
|
gTrailblazerConeCount = 0;
|
|
gTrailblazerConeIndex = 0;
|
|
|
|
if(NewLevel)
|
|
{
|
|
gTrailblazerData = (TRAILBLAZER_DATA*)D_MALLOC(1200); // [A] use malloc
|
|
|
|
sprintf(filename, "TRAILS\\TRAIL.%d", gCurrentMissionNumber);
|
|
|
|
if (FileExists(filename) != 0)
|
|
Loadfile(filename, (char*)gTrailblazerData);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
for (j = 0; j < MAX_SMASHED_CONES; j++)
|
|
wrongside[i][j] = 0;
|
|
}
|
|
|
|
for (i = 0; i < MAX_SMASHED_CONES; i++)
|
|
{
|
|
smashed_cones[i].cone = -1;
|
|
smashed_cones[i].active = 0;
|
|
smashed_cones[i].side = 0;
|
|
smashed_cones[i].rot_speed = 0;
|
|
}
|
|
|
|
current_smashed_cone = 0;
|
|
gTrailblazerPrevConeDelay = 0;
|
|
}
|
|
|
|
|
|
// [D] [T]
|
|
int CarConeCollision(VECTOR *pPos, int car)
|
|
{
|
|
int model;
|
|
CDATA2D cd[2];
|
|
CAR_DATA* cp1;
|
|
|
|
cd[0].x.vx = pPos->vx;
|
|
cd[0].x.vz = pPos->vz;
|
|
cd[0].length[0] = 40;
|
|
cd[0].length[1] = 40;
|
|
cd[0].theta = pPos->pad;
|
|
|
|
cp1 = &car_data[car];
|
|
|
|
if (cp1->controlType == CONTROL_TYPE_NONE)
|
|
return 0;
|
|
|
|
model = cp1->ap.model;
|
|
|
|
cd[1].x.vx = cp1->hd.where.t[0];
|
|
cd[1].length[0] = car_cosmetics[model].colBox.vz;
|
|
cd[1].length[1] = car_cosmetics[model].colBox.vx;
|
|
|
|
cd[1].theta = cp1->hd.direction;
|
|
cd[1].x.vz = cp1->hd.where.t[2];
|
|
|
|
return bcollided2d(cd);
|
|
}
|
|
|
|
|
|
|
|
// [D] [T]
|
|
void SetSmashedCone(int cone, VECTOR *velocity, int player, int side)
|
|
{
|
|
int chan;
|
|
TRAILBLAZER_DATA *tbd;
|
|
SMASHED_CONE *sc;
|
|
|
|
sc = smashed_cones + current_smashed_cone;
|
|
current_smashed_cone++;
|
|
|
|
if (current_smashed_cone > MAX_SMASHED_CONES-1)
|
|
current_smashed_cone = 0;
|
|
|
|
sc->rot_speed = 256;
|
|
sc->side = side;
|
|
sc->cone = cone;
|
|
|
|
sc->velocity.vx = velocity->vx >> 10;
|
|
sc->velocity.vz = velocity->vz >> 10;
|
|
|
|
if (sc->velocity.vx < 0)
|
|
sc->velocity.vy = velocity->vx;
|
|
else
|
|
sc->velocity.vy = -velocity->vx;
|
|
|
|
if (sc->velocity.vz < 0)
|
|
sc->velocity.vy += velocity->vz;
|
|
else
|
|
sc->velocity.vy -= velocity->vz;
|
|
|
|
sc->velocity.vy /= 2;
|
|
|
|
if ((rand() & 1) == 0)
|
|
sc->rot_speed = -sc->velocity.vy;
|
|
else
|
|
sc->rot_speed = sc->velocity.vy;
|
|
|
|
if (sc->velocity.vy < -67)
|
|
sc->velocity.vy = -67;
|
|
|
|
chan = GetFreeChannel();
|
|
|
|
if (chan != -1)
|
|
{
|
|
if (NumPlayers > 1 && NoPlayerControl == 0)
|
|
SetPlayerOwnsChannel(chan, player);
|
|
|
|
tbd = &gTrailblazerData[cone];
|
|
Start3DSoundVolPitch(chan, SOUND_BANK_SFX, 1, tbd->x, tbd->y, tbd->z, -2000, 800);
|
|
}
|
|
}
|
|
|
|
|
|
// [D] [T]
|
|
void MoveSmashedCones(void)
|
|
{
|
|
TRAILBLAZER_DATA *tbd;
|
|
SMASHED_CONE *sc;
|
|
int i;
|
|
|
|
if (gTrailblazerData == NULL)
|
|
return;
|
|
|
|
sc = smashed_cones;
|
|
|
|
for (i = 0; i < MAX_SMASHED_CONES; i++)
|
|
{
|
|
if (sc->cone != -1)
|
|
{
|
|
tbd = &gTrailblazerData[sc->cone];
|
|
|
|
if (tbd->y < 50 - player[0].pos[1])
|
|
{
|
|
tbd->x += sc->velocity.vx;
|
|
tbd->y += sc->velocity.vy;
|
|
tbd->z += sc->velocity.vz;
|
|
|
|
sc->velocity.vy += 10;
|
|
sc->active++;
|
|
|
|
}
|
|
else
|
|
{
|
|
sc->cone = -1;
|
|
sc->active = 0;
|
|
}
|
|
}
|
|
|
|
sc++;
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void DrawCone(VECTOR *position, int cone)
|
|
{
|
|
MATRIX matrix;
|
|
VECTOR pos;
|
|
|
|
if (gTrailblazerData == NULL)
|
|
return;
|
|
|
|
if (PositionVisible(position) == 0 || FrustrumCheck(position, gTrailblazerConeModel->bounding_sphere) == -1)
|
|
return;
|
|
|
|
InitMatrix(matrix);
|
|
_RotMatrixY(&matrix, gTrailblazerData[cone].rot);
|
|
|
|
pos.vx = position->vx - camera_position.vx;
|
|
pos.vy = position->vy - camera_position.vy;
|
|
pos.vz = position->vz - camera_position.vz;
|
|
|
|
gte_SetRotMatrix(&inv_camera_matrix);
|
|
|
|
_MatrixRotate(&pos);
|
|
RenderModel(gTrailblazerConeModel, &matrix, &pos, 0, 0, 0, 0);
|
|
}
|
|
|
|
// [D] [T]
|
|
void DrawSmashedCone(SMASHED_CONE *sc, VECTOR *wpos)
|
|
{
|
|
MATRIX object_matrix;
|
|
VECTOR pos;
|
|
|
|
InitMatrix(object_matrix);
|
|
|
|
RotMatrixY(sc->rot_speed * sc->active * 3 & 0xfff, &object_matrix);
|
|
RotMatrixZ(sc->rot_speed * sc->active & 0xfff, &object_matrix);
|
|
|
|
pos.vx = wpos->vx - camera_position.vx;
|
|
pos.vy = wpos->vy - camera_position.vy;
|
|
pos.vz = wpos->vz - camera_position.vz;
|
|
|
|
Apply_Inv_CameraMatrix(&pos);
|
|
SetRotMatrix(&object_matrix);
|
|
|
|
gte_SetTransVector(&pos);
|
|
|
|
SetFrustrumMatrix();
|
|
|
|
if (FrustrumCheck(wpos, gTrailblazerConeModel->bounding_sphere) != -1)
|
|
{
|
|
PlotMDL_less_than_128(gTrailblazerConeModel);
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void GetConePos(int cone, VECTOR *pos, int side)
|
|
{
|
|
TRAILBLAZER_DATA *tbd;
|
|
int x, z;
|
|
int radius;
|
|
|
|
tbd = &gTrailblazerData[cone];
|
|
|
|
if (side == -1)
|
|
{
|
|
pos->vx = tbd->x;
|
|
pos->vy = tbd->y;
|
|
pos->vz = tbd->z;
|
|
pos->pad = tbd->rot; // [A] store cone rotation
|
|
}
|
|
else
|
|
{
|
|
radius = cone * -4 + 600;
|
|
|
|
x = radius * RCOS(tbd->rot);
|
|
z = -radius * RSIN(tbd->rot);
|
|
|
|
if (side == 0)
|
|
{
|
|
pos->vx = tbd->x - FIXED(x);
|
|
pos->vy = tbd->y;
|
|
pos->vz = tbd->z - FIXED(z);
|
|
}
|
|
else
|
|
{
|
|
pos->vx = tbd->x + FIXED(x);
|
|
pos->vy = tbd->y;
|
|
pos->vz = tbd->z + FIXED(z);
|
|
}
|
|
|
|
pos->pad = tbd->rot; // [A] store cone rotation
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void DrawSmashedCones(void)
|
|
{
|
|
SMASHED_CONE* sc;
|
|
int i;
|
|
|
|
VECTOR wpos;
|
|
|
|
if (gTrailblazerData == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < MAX_SMASHED_CONES; i++)
|
|
{
|
|
sc = &smashed_cones[i];
|
|
|
|
if (sc->active)
|
|
{
|
|
if (GameType == GAME_GATERACE)
|
|
{
|
|
GetConePos(sc->cone, &wpos, sc->side);
|
|
DrawSmashedCone(sc, &wpos);
|
|
}
|
|
else
|
|
{
|
|
GetConePos(sc->cone, &wpos, -1);
|
|
DrawSmashedCone(sc, &wpos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void HandleDrivingGames(void)
|
|
{
|
|
char playerCarId;
|
|
TRAILBLAZER_DATA* tbd;
|
|
int id;
|
|
VECTOR vel;
|
|
VECTOR pos1;
|
|
VECTOR pos2;
|
|
int i, j, k;
|
|
int side;
|
|
int cone;
|
|
|
|
if (gTrailblazerPrevConeDelay > 0)
|
|
gTrailblazerPrevConeDelay--;
|
|
|
|
if (gTrailblazerData)
|
|
{
|
|
if (GameType == GAME_GATERACE)
|
|
{
|
|
MoveSmashedCones();
|
|
|
|
for (id = 0; id < NumPlayers; id++)
|
|
{
|
|
playerCarId = player[id].playerCarId;
|
|
|
|
for (i = 0; i < MAX_SMASHED_CONES; i++)
|
|
{
|
|
cone = gTrailblazerConeIndex + i;
|
|
|
|
if (cone < 100)
|
|
{
|
|
GetConePos(cone, &pos1, 0);
|
|
GetConePos(cone, &pos2, 1);
|
|
|
|
side = 0;
|
|
|
|
if (CarConeCollision(&pos1, playerCarId))
|
|
side = 1;
|
|
else if (CarConeCollision(&pos2, playerCarId))
|
|
side = 2;
|
|
|
|
if (side == 0)
|
|
{
|
|
int sn, cs;
|
|
int dx, dz;
|
|
int radius;
|
|
|
|
tbd = &gTrailblazerData[cone];
|
|
|
|
radius = (600 - (gTrailblazerConeIndex * 400 + i) / 100) * 4096;
|
|
|
|
sn = RSIN(tbd->rot);
|
|
cs = RCOS(tbd->rot);
|
|
|
|
dx = player[id].pos[0] - tbd->x;
|
|
dz = player[id].pos[2] - tbd->z;
|
|
|
|
if (dx * sn + dz * cs < 1)
|
|
{
|
|
wrongside[id][i] = 1;
|
|
continue;
|
|
}
|
|
|
|
if (wrongside[id][i] == 0)
|
|
continue;
|
|
|
|
wrongside[id][i] = 0;
|
|
|
|
if (ABS(dx * cs - dz * sn) < radius)
|
|
{
|
|
gTrailblazerConeCount++;
|
|
|
|
Mission.timer[id].count += 3000;
|
|
|
|
if (id == 0)
|
|
gPlayerScore.items++;
|
|
else
|
|
gPlayerScore.P2items++;
|
|
|
|
gTrailblazerConeIndex += i + 1;
|
|
gTrailblazerPrevConeDelay = 10;
|
|
}
|
|
|
|
// reset side
|
|
for (j = 0; j < 2; j++)
|
|
{
|
|
for (k = 0; k < MAX_SMASHED_CONES; k++)
|
|
wrongside[j][k] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vel.vx = FIXED(car_data[playerCarId].st.n.linearVelocity[0]);
|
|
vel.vy = -17;
|
|
vel.vz = FIXED(car_data[playerCarId].st.n.linearVelocity[2]);
|
|
|
|
SetSmashedCone(cone, &vel, id, side - 1);
|
|
gTrailblazerConeIndex += i + 1;
|
|
|
|
Mission.timer[id].count -= 3000;
|
|
SetPlayerMessage(id, G_LTXT(GTXT_Minus1second), 2, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gTrailblazerConeIndex == 100)
|
|
MissionTargets[NumPlayers - 1].s.target_flags |= TARGET_FLAG_COMPLETED_ALLP;
|
|
}
|
|
else if (GameType == GAME_TRAILBLAZER)
|
|
{
|
|
MoveSmashedCones();
|
|
|
|
for (id = 0; id < NumPlayers; id++)
|
|
{
|
|
playerCarId = player[id].playerCarId;
|
|
|
|
for (i = 0; i < MAX_SMASHED_CONES; i++)
|
|
{
|
|
cone = gTrailblazerConeIndex + i;
|
|
|
|
if (cone < 100)
|
|
{
|
|
GetConePos(cone, &pos1, -1);
|
|
|
|
if (CarConeCollision(&pos1, playerCarId))
|
|
{
|
|
Mission.timer[id].count += 3000;
|
|
|
|
vel.vx = FIXED(car_data[playerCarId].st.n.linearVelocity[0]);
|
|
vel.vy = -17;
|
|
vel.vz = FIXED(car_data[playerCarId].st.n.linearVelocity[2]);
|
|
|
|
SetSmashedCone(cone, &vel, id, 0);
|
|
|
|
gTrailblazerConeCount++;
|
|
gTrailblazerConeIndex += i + 1;
|
|
|
|
if (id == 0)
|
|
gPlayerScore.items++;
|
|
else
|
|
gPlayerScore.P2items++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gTrailblazerConeIndex == 100)
|
|
MissionTargets[NumPlayers - 1].s.target_flags |= TARGET_FLAG_COMPLETED_ALLP;
|
|
}
|
|
}
|
|
|
|
if (Mission.timer[0].count < 0)
|
|
Mission.timer[0].count = 0;
|
|
|
|
if (Mission.timer[1].count < 0)
|
|
Mission.timer[1].count = 0;
|
|
|
|
gPlayerScore.time = Mission.timer[0].count;
|
|
gPlayerScore.P2time = Mission.timer[1].count;
|
|
}
|
|
|
|
// [D] [T]
|
|
void DrawDrivingGames(void)
|
|
{
|
|
int cone;
|
|
int i;
|
|
VECTOR wpos;
|
|
|
|
if (GameType != GAME_GATERACE && GameType != GAME_TRAILBLAZER ||
|
|
gTrailblazerConeModel == NULL || gTrailblazerData == NULL)
|
|
return;
|
|
|
|
SetFrustrumMatrix();
|
|
|
|
if (gTrailblazerConeIndex < 100)
|
|
{
|
|
for (i = 0; i < MAX_SMASHED_CONES; i++)
|
|
{
|
|
cone = gTrailblazerConeIndex + i;
|
|
|
|
if (gTrailblazerPrevConeDelay)
|
|
cone -= 1;
|
|
|
|
if (GameType == GAME_GATERACE)
|
|
{
|
|
GetConePos(cone, &wpos, 0);
|
|
DrawCone(&wpos, cone);
|
|
|
|
GetConePos(cone, &wpos, 1);
|
|
DrawCone(&wpos, cone);
|
|
}
|
|
else
|
|
{
|
|
GetConePos(cone, &wpos, -1);
|
|
DrawCone(&wpos, cone);
|
|
}
|
|
}
|
|
}
|
|
|
|
DrawSmashedCones();
|
|
}
|
|
|
|
|
|
|