Merge branch 'master' into tumble-no-last-bounce

This commit is contained in:
Sally Coolatta 2021-02-02 01:30:20 -05:00
commit 8de53f909b
13 changed files with 315 additions and 12 deletions

View file

@ -9398,6 +9398,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SPINDASHDUST",
"S_SPINDASHWIND",
// Finish line beam
"S_FINISHBEAM1",
"S_FINISHBEAM2",
"S_FINISHBEAM3",
"S_FINISHBEAM4",
"S_FINISHBEAM5",
"S_FINISHBEAMEND1",
"S_FINISHBEAMEND2",
#ifdef SEENAMES
"S_NAMECHECK",
#endif

View file

@ -686,6 +686,7 @@ extern tic_t indirectitemcooldown;
extern tic_t hyubgone;
extern tic_t mapreset;
extern boolean thwompsactive;
extern UINT8 lastLowestLap;
extern SINT8 spbplace;
extern boolean rainbowstartavailable;

View file

@ -315,6 +315,7 @@ tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any othe
tic_t hyubgone; // Cooldown before hyudoro is allowed to be rerolled
tic_t mapreset; // Map reset delay when enough players have joined an empty game
boolean thwompsactive; // Thwomps activate on lap 2
UINT8 lastLowestLap; // Last lowest lap, for activating race lap executors
SINT8 spbplace; // SPB exists, give the person behind better items
boolean rainbowstartavailable; // Boolean, keeps track of if the rainbow start was gotten

View file

@ -732,15 +732,17 @@ char sprnames[NUMSPRITES + 1][5] =
"GCHA", // follower: generic chao
"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
"DBNC", // Drift boost clip's sparks
"DBST", // Drift boost plume
"SDDS", // Spindash dust
"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] =
@ -5115,6 +5117,15 @@ state_t states[NUMSTATES] =
{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
// 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
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif

View file

@ -1003,9 +1003,6 @@ typedef enum sprite
SPR_GCHA, // follower: generic chao
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_DBNC, // Drift boost clip's sparks
SPR_DBST, // Drift boost plume
@ -1013,6 +1010,11 @@ typedef enum sprite
SPR_SDDS, // Spindash dust
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_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1,
NUMSPRITES
@ -5271,6 +5273,14 @@ typedef enum state
S_SPINDASHDUST,
S_SPINDASHWIND,
S_FINISHBEAM1,
S_FINISHBEAM2,
S_FINISHBEAM3,
S_FINISHBEAM4,
S_FINISHBEAM5,
S_FINISHBEAMEND1,
S_FINISHBEAMEND2,
#ifdef SEENAMES
S_NAMECHECK,
#endif

View file

@ -3106,6 +3106,250 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
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)
{
INT32 ds = K_GetKartDriftSparkValue(player);

View file

@ -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_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_RunFinishLineBeam(void);
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
void K_SpawnBoostTrail(player_t *player);
void K_SpawnSparkleTrail(mobj_t *mo);

View file

@ -357,6 +357,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word,"thwompsactive")) {
lua_pushboolean(L, thwompsactive);
return 1;
} else if (fastcmp(word,"lastLowestLap")) {
lua_pushinteger(L, lastLowestLap);
return 1;
} else if (fastcmp(word,"spbplace")) {
lua_pushinteger(L, spbplace);
return 1;

View file

@ -4162,6 +4162,7 @@ static void P_NetArchiveMisc(void)
WRITEINT16(save_p, nospectategrief[i]);
WRITEUINT8(save_p, thwompsactive);
WRITEUINT8(save_p, lastLowestLap);
WRITESINT8(save_p, spbplace);
WRITEUINT8(save_p, rainbowstartavailable);
@ -4295,6 +4296,7 @@ static inline boolean P_NetUnArchiveMisc(void)
nospectategrief[i] = READINT16(save_p);
thwompsactive = (boolean)READUINT8(save_p);
lastLowestLap = READUINT8(save_p);
spbplace = READSINT8(save_p);
rainbowstartavailable = (boolean)READUINT8(save_p);

View file

@ -4098,6 +4098,7 @@ boolean P_LoadLevel(boolean fromnetsave)
nospectategrief[i] = -1;
thwompsactive = false;
lastLowestLap = 0;
spbplace = -1;
// clear special respawning que

View file

@ -1836,7 +1836,6 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|| specialtype == 336 // Dye - Once
|| specialtype == 399 // Level Load
|| specialtype == 328 // SRB2Kart Encore Load
|| specialtype == 2002 // SRB2Kart Race Lap
)
triggerline->special = 0; // Clear it out
@ -1999,6 +1998,7 @@ static void K_HandleLapIncrement(player_t *player)
{
size_t i = 0;
UINT8 nump = 0;
UINT8 lowestLap;
for (i = 0; i < MAXPLAYERS; i++)
{
@ -2082,6 +2082,8 @@ static void K_HandleLapIncrement(player_t *player)
thwompsactive = true; // Lap 2 effects
lowestLap = P_FindLowestLap();
for (i = 0; i < numlines; i++)
{
if (lines[i].special == 2002) // Race lap trigger
@ -2094,7 +2096,13 @@ static void K_HandleLapIncrement(player_t *player)
}
else
{
lap = P_FindLowestLap();
lap = lowestLap;
if (lap <= lastLowestLap)
{
// Need to be able to search for E4 linedefs
continue;
}
}
if (lines[i].flags & ML_NOCLIMB) // Need higher than or equal to
@ -2116,6 +2124,8 @@ static void K_HandleLapIncrement(player_t *player)
P_RunTriggerLinedef(&lines[i], player->mo, NULL);
}
}
lastLowestLap = lowestLap;
}
else if (player->starpostnum)
{

View file

@ -332,6 +332,9 @@ static inline void P_RunThinkers(void)
ps_thlist_times[i] = I_GetTimeMicros() - ps_thlist_times[i];
}
if (gametyperules & GTR_CIRCUIT)
K_RunFinishLineBeam();
if (gametyperules & GTR_PAPERITEMS)
K_RunPaperItemSpawners();

View file

@ -409,7 +409,7 @@ UINT8 P_FindLowestLap(void)
INT32 i;
UINT8 lowest = UINT8_MAX;
if (gametyperules & GTR_CIRCUIT)
if (!(gametyperules & GTR_CIRCUIT))
return 0;
for (i = 0; i < MAXPLAYERS; i++)
@ -417,10 +417,10 @@ UINT8 P_FindLowestLap(void)
if (!playeringame[i] || players[i].spectator)
continue;
if (lowest == 255)
lowest = players[i].laps;
else if (players[i].laps < lowest)
if (lowest == UINT8_MAX || players[i].laps < lowest)
{
lowest = players[i].laps;
}
}
CONS_Debug(DBG_GAMELOGIC, "Lowest laps found: %d\n", lowest);
@ -3075,6 +3075,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
mo = player->mo;
if (mo->hitlag > 0)
{
// Do not move the camera while in hitlag!
// The camera zooming out after you got hit makes it hard to focus on the vibration.
return true;
}
#ifndef NOCLIPCAM
cameranoclip = ((player->pflags & PF_NOCLIP)
|| (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!!