mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-06 08:02:55 +00:00
Merge branch 'finish-line-beam' into 'master'
Finish line beam See merge request KartKrew/Kart!312
This commit is contained in:
commit
df40ce6399
6 changed files with 284 additions and 6 deletions
|
|
@ -9398,6 +9398,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
||||||
"S_SPINDASHDUST",
|
"S_SPINDASHDUST",
|
||||||
"S_SPINDASHWIND",
|
"S_SPINDASHWIND",
|
||||||
|
|
||||||
|
// Finish line beam
|
||||||
|
"S_FINISHBEAM1",
|
||||||
|
"S_FINISHBEAM2",
|
||||||
|
"S_FINISHBEAM3",
|
||||||
|
"S_FINISHBEAM4",
|
||||||
|
"S_FINISHBEAM5",
|
||||||
|
"S_FINISHBEAMEND1",
|
||||||
|
"S_FINISHBEAMEND2",
|
||||||
|
|
||||||
#ifdef SEENAMES
|
#ifdef SEENAMES
|
||||||
"S_NAMECHECK",
|
"S_NAMECHECK",
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
17
src/info.c
17
src/info.c
|
|
@ -732,15 +732,17 @@ char sprnames[NUMSPRITES + 1][5] =
|
||||||
"GCHA", // follower: generic chao
|
"GCHA", // follower: generic chao
|
||||||
"CHEZ", // follower: cheese
|
"CHEZ", // follower: cheese
|
||||||
|
|
||||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
|
||||||
"VIEW",
|
|
||||||
|
|
||||||
"DBCL", // Drift boost clip
|
"DBCL", // Drift boost clip
|
||||||
"DBNC", // Drift boost clip's sparks
|
"DBNC", // Drift boost clip's sparks
|
||||||
"DBST", // Drift boost plume
|
"DBST", // Drift boost plume
|
||||||
|
|
||||||
"SDDS", // Spindash dust
|
"SDDS", // Spindash dust
|
||||||
"SDWN", // Spindash wind
|
"SDWN", // Spindash wind
|
||||||
|
|
||||||
|
"FLBM",
|
||||||
|
|
||||||
|
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||||
|
"VIEW",
|
||||||
};
|
};
|
||||||
|
|
||||||
char spr2names[NUMPLAYERSPRITES][5] =
|
char spr2names[NUMPLAYERSPRITES][5] =
|
||||||
|
|
@ -5115,6 +5117,15 @@ state_t states[NUMSTATES] =
|
||||||
{SPR_SDDS, FF_ANIMATE, 9, {NULL}, 9, 1, S_NULL}, // S_SPINDASHDUST
|
{SPR_SDDS, FF_ANIMATE, 9, {NULL}, 9, 1, S_NULL}, // S_SPINDASHDUST
|
||||||
{SPR_SDWN, FF_ANIMATE|FF_PAPERSPRITE, 18, {NULL}, 9, 2, S_NULL}, // S_SPINDASHWIND
|
{SPR_SDWN, FF_ANIMATE|FF_PAPERSPRITE, 18, {NULL}, 9, 2, S_NULL}, // S_SPINDASHWIND
|
||||||
|
|
||||||
|
// Finish line beam
|
||||||
|
{SPR_FLBM, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM1
|
||||||
|
{SPR_FLBM, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM2
|
||||||
|
{SPR_FLBM, FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM3
|
||||||
|
{SPR_FLBM, FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM4
|
||||||
|
{SPR_FLBM, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAM5
|
||||||
|
{SPR_FLBM, FF_PAPERSPRITE|5, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAMEND1
|
||||||
|
{SPR_FLBM, FF_PAPERSPRITE|6, 1, {NULL}, 0, 0, S_NULL}, // S_FINISHBEAMEND2
|
||||||
|
|
||||||
#ifdef SEENAMES
|
#ifdef SEENAMES
|
||||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
|
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
16
src/info.h
16
src/info.h
|
|
@ -1003,9 +1003,6 @@ typedef enum sprite
|
||||||
SPR_GCHA, // follower: generic chao
|
SPR_GCHA, // follower: generic chao
|
||||||
SPR_CHEZ, // follower: cheese
|
SPR_CHEZ, // follower: cheese
|
||||||
|
|
||||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
|
||||||
SPR_VIEW,
|
|
||||||
|
|
||||||
SPR_DBCL, // Drift boost clip
|
SPR_DBCL, // Drift boost clip
|
||||||
SPR_DBNC, // Drift boost clip's sparks
|
SPR_DBNC, // Drift boost clip's sparks
|
||||||
SPR_DBST, // Drift boost plume
|
SPR_DBST, // Drift boost plume
|
||||||
|
|
@ -1013,6 +1010,11 @@ typedef enum sprite
|
||||||
SPR_SDDS, // Spindash dust
|
SPR_SDDS, // Spindash dust
|
||||||
SPR_SDWN, // Spindash wind
|
SPR_SDWN, // Spindash wind
|
||||||
|
|
||||||
|
SPR_FLBM, // Finish line beam
|
||||||
|
|
||||||
|
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||||
|
SPR_VIEW,
|
||||||
|
|
||||||
SPR_FIRSTFREESLOT,
|
SPR_FIRSTFREESLOT,
|
||||||
SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1,
|
SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1,
|
||||||
NUMSPRITES
|
NUMSPRITES
|
||||||
|
|
@ -5271,6 +5273,14 @@ typedef enum state
|
||||||
S_SPINDASHDUST,
|
S_SPINDASHDUST,
|
||||||
S_SPINDASHWIND,
|
S_SPINDASHWIND,
|
||||||
|
|
||||||
|
S_FINISHBEAM1,
|
||||||
|
S_FINISHBEAM2,
|
||||||
|
S_FINISHBEAM3,
|
||||||
|
S_FINISHBEAM4,
|
||||||
|
S_FINISHBEAM5,
|
||||||
|
S_FINISHBEAMEND1,
|
||||||
|
S_FINISHBEAMEND2,
|
||||||
|
|
||||||
#ifdef SEENAMES
|
#ifdef SEENAMES
|
||||||
S_NAMECHECK,
|
S_NAMECHECK,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
244
src/k_kart.c
244
src/k_kart.c
|
|
@ -3106,6 +3106,250 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Spawns the finish line fault-indicator effect
|
||||||
|
#define FINISHLINEBEAM_SPACING (48*mapobjectscale)
|
||||||
|
static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *line, boolean reverse)
|
||||||
|
{
|
||||||
|
const fixed_t linelength = P_AproxDistance(line->dx, line->dy);
|
||||||
|
const fixed_t xstep = FixedDiv(line->dx, linelength);
|
||||||
|
const fixed_t ystep = FixedDiv(line->dy, linelength);
|
||||||
|
|
||||||
|
fixed_t linex = line->v1->x;
|
||||||
|
fixed_t liney = line->v1->y;
|
||||||
|
angle_t lineangle = R_PointToAngle2(0, 0, line->dx, line->dy) + ANGLE_90;
|
||||||
|
|
||||||
|
UINT8 i;
|
||||||
|
|
||||||
|
if (line->flags & ML_NOCLIMB)
|
||||||
|
{
|
||||||
|
// Line is flipped
|
||||||
|
lineangle += ANGLE_180;
|
||||||
|
}
|
||||||
|
|
||||||
|
linex += FixedMul(offset, xstep);
|
||||||
|
liney += FixedMul(offset, ystep);
|
||||||
|
|
||||||
|
while (offset < linelength)
|
||||||
|
{
|
||||||
|
#define COLORCYCLELEN 10
|
||||||
|
const UINT8 colorcycle[COLORCYCLELEN] = {
|
||||||
|
SKINCOLOR_PERIWINKLE,
|
||||||
|
SKINCOLOR_SLATE,
|
||||||
|
SKINCOLOR_BLOSSOM,
|
||||||
|
SKINCOLOR_RASPBERRY,
|
||||||
|
SKINCOLOR_ORANGE,
|
||||||
|
SKINCOLOR_YELLOW,
|
||||||
|
SKINCOLOR_LIME,
|
||||||
|
SKINCOLOR_TURTLE,
|
||||||
|
SKINCOLOR_ROBIN,
|
||||||
|
SKINCOLOR_JAWZ
|
||||||
|
};
|
||||||
|
|
||||||
|
const UINT8 numframes = 5;
|
||||||
|
const angle_t framethreshold = ANGLE_180 / (numframes-1);
|
||||||
|
const angle_t frameaim = aiming + (framethreshold / 2);
|
||||||
|
|
||||||
|
fixed_t x, y, z;
|
||||||
|
UINT8 spriteframe = 0;
|
||||||
|
|
||||||
|
x = linex + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINECOSINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT));
|
||||||
|
y = liney + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINESINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT));
|
||||||
|
z = FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT));
|
||||||
|
|
||||||
|
if (leveltime >= starttime)
|
||||||
|
{
|
||||||
|
spriteframe = 4; // Weakest sprite when passable
|
||||||
|
}
|
||||||
|
else if (frameaim > ANGLE_180)
|
||||||
|
{
|
||||||
|
spriteframe = (ANGLE_MAX - frameaim) / framethreshold;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spriteframe = frameaim / framethreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i <= r_splitscreen; i++)
|
||||||
|
{
|
||||||
|
if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo))
|
||||||
|
{
|
||||||
|
mobj_t *beam;
|
||||||
|
|
||||||
|
beam = P_SpawnMobj(x, y, players[displayplayers[i]].mo->z + z, MT_THOK);
|
||||||
|
P_SetMobjState(beam, S_FINISHBEAM1 + spriteframe);
|
||||||
|
|
||||||
|
beam->colorized = true;
|
||||||
|
beam->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]);
|
||||||
|
|
||||||
|
if (reverse)
|
||||||
|
{
|
||||||
|
beam->color = colorcycle[((leveltime / 4) + (COLORCYCLELEN/2)) % COLORCYCLELEN];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
beam->color = colorcycle[(leveltime / 4) % COLORCYCLELEN];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += FINISHLINEBEAM_SPACING;
|
||||||
|
linex += FixedMul(FINISHLINEBEAM_SPACING, xstep);
|
||||||
|
liney += FixedMul(FINISHLINEBEAM_SPACING, ystep);
|
||||||
|
|
||||||
|
if (reverse)
|
||||||
|
{
|
||||||
|
aiming -= ANGLE_45;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aiming += ANGLE_45;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i <= r_splitscreen; i++)
|
||||||
|
{
|
||||||
|
if (playeringame[displayplayers[i]] && players[displayplayers[i]].mo && !P_MobjWasRemoved(players[displayplayers[i]].mo))
|
||||||
|
{
|
||||||
|
UINT8 j;
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
vertex_t *v = line->v1;
|
||||||
|
mobj_t *end1, *end2;
|
||||||
|
angle_t a = R_PointToAngle2(0, 0, line->dx, line->dy);
|
||||||
|
fixed_t sx;
|
||||||
|
fixed_t sy;
|
||||||
|
|
||||||
|
//if (line->flags & ML_NOCLIMB)
|
||||||
|
//{
|
||||||
|
//a += ANGLE_180;
|
||||||
|
//}
|
||||||
|
|
||||||
|
sx = FixedMul(3*mapobjectscale, FINECOSINE(a >> ANGLETOFINESHIFT));
|
||||||
|
sy = FixedMul(3*mapobjectscale, FINESINE(a >> ANGLETOFINESHIFT));
|
||||||
|
|
||||||
|
if (j == 1)
|
||||||
|
{
|
||||||
|
v = line->v2;
|
||||||
|
sx = -sx;
|
||||||
|
sy = -sy;
|
||||||
|
}
|
||||||
|
|
||||||
|
end1 = P_SpawnMobj(
|
||||||
|
v->x + sx,
|
||||||
|
v->y + sy,
|
||||||
|
players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING,
|
||||||
|
MT_THOK
|
||||||
|
);
|
||||||
|
|
||||||
|
P_SetMobjState(end1, S_FINISHBEAMEND1);
|
||||||
|
end1->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]);
|
||||||
|
end1->angle = lineangle;
|
||||||
|
|
||||||
|
end2 = P_SpawnMobj(
|
||||||
|
v->x + (8*sx),
|
||||||
|
v->y + (8*sy),
|
||||||
|
players[displayplayers[i]].mo->z + FINISHLINEBEAM_SPACING,
|
||||||
|
MT_THOK
|
||||||
|
);
|
||||||
|
|
||||||
|
P_SetMobjState(end2, S_FINISHBEAMEND2);
|
||||||
|
end2->drawflags = MFD_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]);
|
||||||
|
end2->angle = lineangle;
|
||||||
|
|
||||||
|
P_SetTarget(&end2->tracer, end1);
|
||||||
|
end2->flags2 |= MF2_LINKDRAW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void K_RunFinishLineBeam(void)
|
||||||
|
{
|
||||||
|
INT64 bounds[4];
|
||||||
|
angle_t angle = 0;
|
||||||
|
UINT32 flags = 0;
|
||||||
|
boolean valid = false;
|
||||||
|
UINT32 i;
|
||||||
|
|
||||||
|
if (!(leveltime < starttime || rainbowstartavailable == true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this does NOT support finish lines that curve.
|
||||||
|
// I wanted to! But I have a headache from trying to code it for like, 3 hours!
|
||||||
|
// so I'm not!
|
||||||
|
|
||||||
|
bounds[0] = INT64_MAX; // min x
|
||||||
|
bounds[1] = INT64_MIN; // max x
|
||||||
|
bounds[2] = INT64_MAX; // min y
|
||||||
|
bounds[3] = INT64_MIN; // max y
|
||||||
|
|
||||||
|
for (i = 0; i < numlines; i++)
|
||||||
|
{
|
||||||
|
if (lines[i].special == 2001)
|
||||||
|
{
|
||||||
|
angle_t thisAngle = R_PointToAngle2(0, 0, lines[i].dx, lines[i].dy);
|
||||||
|
|
||||||
|
bounds[0] = min(bounds[0], min(lines[i].v1->x, lines[i].v2->x)); // min x
|
||||||
|
bounds[1] = max(bounds[1], max(lines[i].v1->x, lines[i].v2->x)); // max x
|
||||||
|
bounds[2] = min(bounds[2], min(lines[i].v1->y, lines[i].v2->y)); // min y
|
||||||
|
bounds[3] = max(bounds[3], max(lines[i].v1->y, lines[i].v2->y)); // max y
|
||||||
|
|
||||||
|
if (valid == false)
|
||||||
|
{
|
||||||
|
angle = thisAngle;
|
||||||
|
flags = lines[i].flags;
|
||||||
|
}
|
||||||
|
else if (angle != thisAngle)
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid == true)
|
||||||
|
{
|
||||||
|
fixed_t span = P_AproxDistance(bounds[1] - bounds[0], bounds[3] - bounds[2]) / 2;
|
||||||
|
|
||||||
|
fixed_t cx = (bounds[0] + bounds[1]) / 2;
|
||||||
|
fixed_t cy = (bounds[2] + bounds[3]) / 2;
|
||||||
|
|
||||||
|
vertex_t v1, v2; // fake vertexes
|
||||||
|
line_t junk; // fake linedef
|
||||||
|
|
||||||
|
const angle_t angoffset = ANGLE_45;
|
||||||
|
const angle_t angadd = ANGLE_11hh;
|
||||||
|
const fixed_t speed = 6 * mapobjectscale;
|
||||||
|
|
||||||
|
fixed_t offseta = (leveltime * speed) % FINISHLINEBEAM_SPACING;
|
||||||
|
angle_t aiminga = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) + (angadd * leveltime);
|
||||||
|
|
||||||
|
fixed_t offsetb = FINISHLINEBEAM_SPACING - offseta;
|
||||||
|
angle_t aimingb = (angoffset * -((leveltime * speed) / FINISHLINEBEAM_SPACING)) - (angadd * leveltime);
|
||||||
|
|
||||||
|
v1.x = cx - FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT));
|
||||||
|
v1.y = cy - FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT));
|
||||||
|
|
||||||
|
v2.x = cx + FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT));
|
||||||
|
v2.y = cy + FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT));
|
||||||
|
|
||||||
|
junk.v1 = &v1;
|
||||||
|
junk.v2 = &v2;
|
||||||
|
junk.dx = v2.x - v1.x;
|
||||||
|
junk.dy = v2.y - v1.y;
|
||||||
|
junk.flags = flags;
|
||||||
|
|
||||||
|
K_DrawFinishLineBeamForLine(offseta, aiminga, &junk, false);
|
||||||
|
K_DrawFinishLineBeamForLine(offsetb, aimingb, &junk, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef FINISHLINEBEAM_SPACING
|
||||||
|
|
||||||
UINT16 K_DriftSparkColor(player_t *player, INT32 charge)
|
UINT16 K_DriftSparkColor(player_t *player, INT32 charge)
|
||||||
{
|
{
|
||||||
INT32 ds = K_GetKartDriftSparkValue(player);
|
INT32 ds = K_GetKartDriftSparkValue(player);
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ void K_DestroyBumpers(player_t *player, UINT8 amount);
|
||||||
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
|
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
|
||||||
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
|
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
|
||||||
void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
|
void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
|
||||||
|
void K_RunFinishLineBeam(void);
|
||||||
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
|
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
|
||||||
void K_SpawnBoostTrail(player_t *player);
|
void K_SpawnBoostTrail(player_t *player);
|
||||||
void K_SpawnSparkleTrail(mobj_t *mo);
|
void K_SpawnSparkleTrail(mobj_t *mo);
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,9 @@ static inline void P_RunThinkers(void)
|
||||||
ps_thlist_times[i] = I_GetTimeMicros() - ps_thlist_times[i];
|
ps_thlist_times[i] = I_GetTimeMicros() - ps_thlist_times[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gametyperules & GTR_CIRCUIT)
|
||||||
|
K_RunFinishLineBeam();
|
||||||
|
|
||||||
if (gametyperules & GTR_PAPERITEMS)
|
if (gametyperules & GTR_PAPERITEMS)
|
||||||
K_RunPaperItemSpawners();
|
K_RunPaperItemSpawners();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue