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)
500 lines
11 KiB
C
500 lines
11 KiB
C
#include "driver2.h"
|
|
#include "bomberman.h"
|
|
#include "convert.h"
|
|
#include "overmap.h"
|
|
#include "players.h"
|
|
#include "cars.h"
|
|
#include "glaunch.h"
|
|
#include "job_fx.h"
|
|
#include "dr2roads.h"
|
|
#include "pad.h"
|
|
#include "camera.h"
|
|
#include "draw.h"
|
|
#include "debris.h"
|
|
#include "mission.h"
|
|
#include "denting.h"
|
|
#include "cosmetic.h"
|
|
#include "bcollide.h"
|
|
#include "pedest.h"
|
|
|
|
#include "ASM/rndrasm.h"
|
|
|
|
MODEL* gBombModel;
|
|
|
|
static BOMB ThrownBombs[MAX_THROWN_BOMBS];
|
|
|
|
static int ThrownBombDelay = 0;
|
|
static int CurrentBomb = 0;
|
|
static int gWantFlash = 0;
|
|
CAR_DATA *gBombTargetVehicle = NULL;
|
|
static int flashval;
|
|
|
|
// [D] [T]
|
|
void InitThrownBombs(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_THROWN_BOMBS; i++)
|
|
ThrownBombs[i].flags = 0;
|
|
|
|
ThrownBombDelay = Random2(0) % 45 + 8;
|
|
CurrentBomb = 0;
|
|
gWantFlash = 0;
|
|
gBombTargetVehicle = NULL;
|
|
}
|
|
|
|
// [D] [T]
|
|
void DrawThrownBombs(void)
|
|
{
|
|
BOMB *bomb;
|
|
int i;
|
|
MATRIX object_matrix;
|
|
VECTOR pos;
|
|
|
|
if (gBombModel == NULL)
|
|
return;
|
|
|
|
bomb = ThrownBombs;
|
|
i = 0;
|
|
while (i < MAX_THROWN_BOMBS)
|
|
{
|
|
if ((bomb->flags & 1) != 0)
|
|
{
|
|
InitMatrix(object_matrix);
|
|
|
|
RotMatrixY(bomb->rot_speed * bomb->active * 3 & 0xfff, &object_matrix);
|
|
RotMatrixZ(bomb->rot_speed * bomb->active & 0xfff, &object_matrix);
|
|
|
|
pos.vx = bomb->position.vx - camera_position.vx;
|
|
pos.vy = bomb->position.vy - camera_position.vy;
|
|
pos.vz = bomb->position.vz - camera_position.vz;
|
|
|
|
Apply_Inv_CameraMatrix(&pos);
|
|
|
|
gte_SetRotMatrix(&object_matrix);
|
|
gte_SetTransVector(&pos);
|
|
|
|
pos.vx = bomb->position.vx;
|
|
pos.vy = bomb->position.vy;
|
|
pos.vz = bomb->position.vz;
|
|
|
|
SetFrustrumMatrix();
|
|
|
|
if (FrustrumCheck(&pos, gBombModel->bounding_sphere) != -1)
|
|
{
|
|
PlotMDL_less_than_128(gBombModel);
|
|
}
|
|
}
|
|
|
|
i++;
|
|
bomb++;
|
|
}
|
|
|
|
if (gWantFlash != 0)
|
|
{
|
|
add_haze(flashval, flashval, 7);
|
|
|
|
flashval -= 10;
|
|
|
|
if (flashval < 1)
|
|
gWantFlash = 0;
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void BombThePlayerToHellAndBack(int car)
|
|
{
|
|
CAR_DATA* cp;
|
|
BOMB *bomb;
|
|
|
|
if (car == -1)
|
|
return;
|
|
|
|
cp = &car_data[car];
|
|
|
|
cp->ap.damage[0] = 0xfff;
|
|
cp->ap.damage[1] = 0xfff;
|
|
cp->ap.damage[2] = 0xfff;
|
|
cp->ap.damage[3] = 0xfff;
|
|
cp->ap.damage[4] = 0xfff;
|
|
cp->ap.damage[5] = 0xfff;
|
|
|
|
cp->ap.needsDenting = 1;
|
|
cp->totalDamage = MaxPlayerDamage[0];
|
|
|
|
DentCar(&car_data[car]);
|
|
|
|
if (maxCivCars == 0)
|
|
{
|
|
trap(7);
|
|
}
|
|
|
|
gBombTargetVehicle = &car_data[(car + 1) % maxCivCars];
|
|
|
|
bomb = &ThrownBombs[CurrentBomb++];
|
|
CurrentBomb = CurrentBomb % MAX_THROWN_BOMBS;
|
|
|
|
bomb->flags = 1;
|
|
bomb->active = 1;
|
|
|
|
bomb->position.vx = cp->hd.where.t[0];
|
|
bomb->position.vy = cp->hd.where.t[1];
|
|
bomb->position.vz = cp->hd.where.t[2];
|
|
|
|
bomb->velocity.vx = 0;
|
|
bomb->velocity.vy = 0;
|
|
bomb->velocity.vz = 0;
|
|
|
|
bomb = &ThrownBombs[CurrentBomb++];
|
|
CurrentBomb = CurrentBomb % MAX_THROWN_BOMBS;
|
|
|
|
bomb->flags = 1;
|
|
bomb->active = 1;
|
|
|
|
bomb->position.vx = cp->hd.where.t[0] + 170;
|
|
bomb->position.vy = cp->hd.where.t[1];
|
|
bomb->position.vz = cp->hd.where.t[2] + 73;
|
|
|
|
bomb->velocity.vx = 0;
|
|
bomb->velocity.vy = 0;
|
|
bomb->velocity.vz = 0;
|
|
|
|
bomb = &ThrownBombs[CurrentBomb++];
|
|
CurrentBomb = CurrentBomb % MAX_THROWN_BOMBS;
|
|
|
|
bomb->flags = 1;
|
|
bomb->active = 1;
|
|
bomb->position.vx = cp->hd.where.t[0] - 109;
|
|
bomb->position.vy = cp->hd.where.t[1];
|
|
bomb->position.vz = cp->hd.where.t[2] - 147;
|
|
|
|
bomb->velocity.vx = 0;
|
|
bomb->velocity.vy = 0;
|
|
bomb->velocity.vz = 0;
|
|
}
|
|
|
|
// [D] [T]
|
|
int BombCollisionCheck(CAR_DATA *cp, VECTOR *pPos)
|
|
{
|
|
CDATA2D cd[2] = {0};
|
|
|
|
cd[1].theta = cp->hd.direction;
|
|
cd[1].length[0] = car_cosmetics[cp->ap.model].colBox.vz;
|
|
cd[1].length[1] = car_cosmetics[cp->ap.model].colBox.vx;
|
|
cd[1].x.vx = cp->hd.where.t[0];
|
|
cd[1].x.vz = cp->hd.where.t[2];
|
|
|
|
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 = 0;
|
|
cd[0].avel = 0;
|
|
cd[0].vel.vx = 0;
|
|
cd[0].vel.vy = 0;
|
|
cd[0].vel.vz = 0;
|
|
|
|
return bcollided2d(cd);
|
|
}
|
|
|
|
const int minBoxSize = 90;
|
|
const int littleBoxRange = 400;
|
|
const int halfStrike = 0x32000;
|
|
const int fullStrike = 0x32000;
|
|
|
|
// [D] [T]
|
|
void ExplosionCollisionCheck(CAR_DATA *cp, EXOBJECT *pE)
|
|
{
|
|
static int setUsed = 0;
|
|
|
|
int temp;
|
|
int strikeVel;
|
|
bool isCar;
|
|
VECTOR *pos;
|
|
int displacement;
|
|
int denom;
|
|
int debrisColour;
|
|
CDATA2D cd[2];
|
|
int carLength[2];
|
|
CRET2D collisionResult;
|
|
VECTOR velocity;
|
|
LONGVECTOR4 pointVel;
|
|
LONGVECTOR4 reaction;
|
|
LONGVECTOR4 lever;
|
|
|
|
isCar = (cp != &car_data[TANNER_COLLIDER_CARID]);
|
|
|
|
if (player[0].playerType == 2 || isCar)
|
|
{
|
|
cd[1].x.vx = cp->hd.where.t[0];
|
|
cd[1].length[0] = car_cosmetics[cp->ap.model].colBox.vz;
|
|
cd[1].length[1] = car_cosmetics[cp->ap.model].colBox.vx;
|
|
cd[1].theta = cp->hd.direction;
|
|
cd[1].x.vz = cp->hd.where.t[2];
|
|
|
|
if (pE->type <= LITTLE_BANG)
|
|
{
|
|
cd[0].length[1] = minBoxSize + ((pE->time / pE->speed) * littleBoxRange) / (4096 / pE->speed);
|
|
}
|
|
else if (pE->type == HEY_MOMMA) // biggest bang that might kill Tanner
|
|
{
|
|
pos = (VECTOR*)cp->hd.where.t;
|
|
|
|
if (!isCar)
|
|
pos = (VECTOR*)player->pos;
|
|
|
|
if (cd[0].length[1] < 0)
|
|
cd[0].length[1] = pos->vx - pE->pos.vx;
|
|
else
|
|
cd[0].length[1] = pE->pos.vx - pos->vx;
|
|
|
|
temp = pE->pos.vz - pos->vz;
|
|
|
|
if (temp < 0)
|
|
temp = pos->vz - pE->pos.vz;
|
|
|
|
if (cd[0].length[1] < temp)
|
|
cd[0].length[1] = temp;
|
|
|
|
if (cd[0].length[1] < 3000)
|
|
{
|
|
if (isCar)
|
|
{
|
|
if (CAR_INDEX(cp) == player[0].playerCarId)
|
|
{
|
|
cp->totalDamage = MaxPlayerDamage[0];
|
|
player[0].dying = 1;
|
|
lockAllTheDoors = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bKillTanner = 1;
|
|
player[0].dying = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cd[0].length[1] = 10;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cd[0].length[1] = 0;
|
|
}
|
|
|
|
cd[0].x.vx = (pE->pos).vx;
|
|
cd[0].x.vz = (pE->pos).vz;
|
|
cd[0].theta = 0;
|
|
cd[0].avel = 0;
|
|
cd[0].vel.vx = 0;
|
|
cd[0].vel.vy = 0;
|
|
cd[0].vel.vz = 0;
|
|
cd[0].length[0] = cd[0].length[1];
|
|
|
|
if (bcollided2d(cd))
|
|
{
|
|
bFindCollisionPoint(cd, &collisionResult);
|
|
|
|
cp->hd.where.t[2] += FIXEDH(collisionResult.penetration * collisionResult.surfNormal.vz);
|
|
cp->hd.where.t[0] += FIXEDH(collisionResult.penetration * collisionResult.surfNormal.vx);
|
|
|
|
lever[0] = collisionResult.hit.vx - cp->hd.where.t[0];
|
|
lever[1] = 60;
|
|
lever[2] = collisionResult.hit.vz - cp->hd.where.t[2];
|
|
|
|
collisionResult.surfNormal.vy = 0;
|
|
|
|
if (pE->type == LITTLE_BANG)
|
|
strikeVel = halfStrike - ((pE->time / pE->speed) * halfStrike) / (0x1000 / pE->speed);
|
|
else if (pE->type == BIG_BANG)
|
|
strikeVel = fullStrike;
|
|
else if (pE->type == HEY_MOMMA)
|
|
strikeVel = fullStrike << 1;
|
|
else
|
|
strikeVel = 0;
|
|
|
|
setUsed = 1;
|
|
|
|
if (strikeVel > 0)
|
|
{
|
|
collisionResult.hit.vy = -(cp->hd.where.t[1] + 60);
|
|
|
|
velocity.vx = cp->st.n.linearVelocity[0] >> 0xc;
|
|
velocity.vy = -17;
|
|
velocity.vz = cp->st.n.linearVelocity[2] >> 0xc;
|
|
|
|
if (strikeVel > 0x3600)
|
|
{
|
|
collisionResult.hit.vy += 30;
|
|
velocity.vy = -37;
|
|
Setup_Sparks(&collisionResult.hit, &velocity, 4, 0);
|
|
collisionResult.hit.vy -= 30;
|
|
velocity.vy += 20;
|
|
|
|
if (strikeVel > 0x1b000)
|
|
{
|
|
debrisColour = GetDebrisColour(cp);
|
|
Setup_Debris(&collisionResult.hit, &velocity, 6, debrisColour << 0x10);
|
|
|
|
if (cp->controlType == CONTROL_TYPE_PLAYER)
|
|
SetPadVibration(*cp->ai.padid, 1);
|
|
}
|
|
}
|
|
|
|
if(isCar)
|
|
DamageCar(cp, cd, &collisionResult, strikeVel);
|
|
|
|
displacement = FIXEDH(lever[0] * collisionResult.surfNormal.vx + lever[1] * collisionResult.surfNormal.vy + lever[2] * collisionResult.surfNormal.vz);
|
|
displacement = FIXEDH(((lever[0] * lever[0] + lever[2] * lever[2]) - displacement * displacement) * car_cosmetics[cp->ap.model].twistRateY) + 4096;
|
|
|
|
if (strikeVel < 0x7f001)
|
|
denom = (strikeVel * 4096) / displacement;
|
|
else
|
|
denom = (strikeVel / displacement) * 4096;
|
|
|
|
denom >>= 6;
|
|
|
|
pointVel[0] = denom * (collisionResult.surfNormal.vx >> 6);
|
|
pointVel[1] = denom * (collisionResult.surfNormal.vy >> 6);
|
|
pointVel[2] = denom * (collisionResult.surfNormal.vz >> 6);
|
|
|
|
cp->st.n.linearVelocity[0] += pointVel[0];
|
|
cp->st.n.linearVelocity[1] += pointVel[1];
|
|
cp->st.n.linearVelocity[2] += pointVel[2];
|
|
|
|
cp->hd.aacc[0] += FIXEDH(lever[1] * pointVel[2]) - FIXEDH(lever[2] * pointVel[1]);
|
|
cp->hd.aacc[1] += FIXEDH(lever[2] * pointVel[0]) - FIXEDH(lever[0] * pointVel[2]);
|
|
cp->hd.aacc[2] += FIXEDH(lever[0] * pointVel[1]) - FIXEDH(lever[1] * pointVel[0]);
|
|
}
|
|
}
|
|
|
|
if (isCar)
|
|
return;
|
|
}
|
|
|
|
if (setUsed != 0)
|
|
{
|
|
pE->type = BANG_USED;
|
|
setUsed = 0;
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void AddFlash(VECTOR *pos)
|
|
{
|
|
int dist;
|
|
|
|
dist = Long2DDistance(pos, NoPlayerControl ? &player[0].cameraPos : (VECTOR*)player[0].pos);
|
|
|
|
if (dist < 2500)
|
|
{
|
|
gWantFlash = 1;
|
|
flashval = 150 - dist / 20;
|
|
}
|
|
}
|
|
|
|
// [D] [T]
|
|
void HandleThrownBombs(void)
|
|
{
|
|
CAR_DATA* cp;
|
|
BOMB* bomb;
|
|
int i;
|
|
int y;
|
|
|
|
int dx, dz;
|
|
VECTOR velocity;
|
|
|
|
// throw bombs if we have vehicle
|
|
if (gBombTargetVehicle)
|
|
{
|
|
ThrownBombDelay--;
|
|
|
|
if (ThrownBombDelay == -1)
|
|
{
|
|
ThrownBombDelay = Random2(0) % 45 + 8;
|
|
|
|
bomb = &ThrownBombs[CurrentBomb++];
|
|
CurrentBomb = CurrentBomb % MAX_THROWN_BOMBS;
|
|
|
|
bomb->flags = 1;
|
|
bomb->active = 1;
|
|
|
|
bomb->position.vx = gBombTargetVehicle->hd.where.t[0];
|
|
bomb->position.vy = gBombTargetVehicle->hd.where.t[1] - 200;
|
|
bomb->position.vz = gBombTargetVehicle->hd.where.t[2];
|
|
|
|
velocity.vx = FIXEDH(gBombTargetVehicle->st.n.linearVelocity[0]);
|
|
velocity.vz = FIXEDH(gBombTargetVehicle->st.n.linearVelocity[2]);
|
|
|
|
bomb->velocity.vx = velocity.vx >> 10;
|
|
bomb->velocity.vz = velocity.vz >> 10;
|
|
bomb->velocity.vy = -(Long2DDistance(&bomb->position, (VECTOR*)player[0].pos) >> 7);
|
|
|
|
if ((rand() & 1) == 0)
|
|
bomb->rot_speed = -bomb->velocity.vy;
|
|
else
|
|
bomb->rot_speed = bomb->velocity.vy;
|
|
|
|
if (bomb->velocity.vy < -100)
|
|
bomb->velocity.vy = -100;
|
|
}
|
|
}
|
|
|
|
bomb = ThrownBombs;
|
|
|
|
for (i = 0; i < MAX_THROWN_BOMBS; i++)
|
|
{
|
|
if (bomb->flags & 1)
|
|
{
|
|
bomb->position.vx += bomb->velocity.vx;
|
|
bomb->position.vy += bomb->velocity.vy;
|
|
bomb->position.vz += bomb->velocity.vz;
|
|
|
|
bomb->velocity.vy += 10;
|
|
|
|
bomb->active++;
|
|
|
|
y = -MapHeight(&bomb->position);
|
|
|
|
if (y < bomb->position.vy)
|
|
{
|
|
if ((bomb->flags & 2) == 0)
|
|
{
|
|
bomb->flags |= 2;
|
|
bomb->position.vy = y;
|
|
bomb->velocity.vy = -bomb->velocity.vy / 2; // bounce
|
|
}
|
|
else
|
|
{
|
|
bomb->flags = 0;
|
|
bomb->position.vy = y;
|
|
|
|
AddExplosion(bomb->position, LITTLE_BANG);
|
|
AddFlash(&bomb->position);
|
|
|
|
dx = (bomb->position.vx - player[0].pos[0]);
|
|
dz = (bomb->position.vz - player[0].pos[2]);
|
|
|
|
if (FIXEDH(dx * dx + dz * dz) < 1024)
|
|
SetPadVibration(player[0].padid, 3); // [A] bug fix
|
|
}
|
|
}
|
|
|
|
cp = car_data;
|
|
|
|
while (cp < &car_data[MAX_CARS])
|
|
{
|
|
if (cp != gBombTargetVehicle && cp->controlType != CONTROL_TYPE_NONE && BombCollisionCheck(cp, &bomb->position) != 0)
|
|
{
|
|
bomb->flags = 0;
|
|
|
|
AddExplosion(bomb->position, BIG_BANG);
|
|
AddFlash(&bomb->position);
|
|
}
|
|
cp++;
|
|
}
|
|
}
|
|
bomb++;
|
|
}
|
|
} |