Merge branch 'finish-beam-in-sprints' into 'master'

Finish line beam for sprint maps

See merge request KartKrew/Kart!364
This commit is contained in:
Sal 2021-02-05 17:48:37 -05:00
commit 6a2c5368ee
10 changed files with 531 additions and 244 deletions

View file

@ -170,6 +170,7 @@ set(SRB2_CORE_GAME_SOURCES
p_telept.c
p_tick.c
p_user.c
k_race.c
k_battle.c
k_bheap.c
k_collide.c
@ -195,6 +196,7 @@ set(SRB2_CORE_GAME_SOURCES
p_slopes.h
p_spec.h
p_tick.h
k_race.h
k_battle.h
k_bheap.h
k_collide.h

View file

@ -558,6 +558,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/k_respawn.o\
$(OBJDIR)/k_collide.o\
$(OBJDIR)/k_color.o \
$(OBJDIR)/k_race.o \
$(OBJDIR)/k_battle.o \
$(OBJDIR)/k_pwrlv.o \
$(OBJDIR)/k_waypoint.o\

View file

@ -10489,6 +10489,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_PAPERITEMSPOT",
"MT_BEAMPOINT",
#ifdef SEENAMES
"MT_NAMECHECK",
#endif

View file

@ -28754,6 +28754,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_BEAMPOINT
2424, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
48*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
// ============================================================================================================================//
#ifdef SEENAMES

View file

@ -6383,6 +6383,8 @@ typedef enum mobj_type
MT_PAPERITEMSPOT,
MT_BEAMPOINT,
#ifdef SEENAMES
MT_NAMECHECK,
#endif

View file

@ -3106,250 +3106,6 @@ 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);

421
src/k_race.c Normal file
View file

@ -0,0 +1,421 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2018-2020 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_race.c
/// \brief Race Mode specific code.
#include "k_race.h"
#include "k_kart.h"
#include "k_battle.h"
#include "k_pwrlv.h"
#include "k_color.h"
#include "k_respawn.h"
#include "doomdef.h"
#include "hu_stuff.h"
#include "g_game.h"
#include "m_random.h"
#include "p_local.h"
#include "p_slopes.h"
#include "p_setup.h"
#include "r_draw.h"
#include "r_local.h"
#include "s_sound.h"
#include "st_stuff.h"
#include "v_video.h"
#include "z_zone.h"
#include "m_misc.h"
#include "m_cond.h"
#include "f_finale.h"
#include "lua_hud.h" // For Lua hud checks
#include "lua_hook.h" // For MobjDamage and ShouldDamage
#include "m_cheat.h" // objectplacing
#include "p_spec.h"
#include "k_waypoint.h"
#include "k_bot.h"
#include "k_hud.h"
static line_t *finishBeamLine = NULL;
static mobj_t *beamPoints[2];
static UINT8 numBeamPoints = 0;
/*--------------------------------------------------
void K_ClearFinishBeamLine(void)
See header file for description.
--------------------------------------------------*/
void K_ClearFinishBeamLine(void)
{
size_t i;
finishBeamLine = NULL;
for (i = 0; i < 2; i++)
{
beamPoints[i] = NULL;
}
numBeamPoints = 0;
}
/*--------------------------------------------------
static void K_FreeFinishBeamLine(void)
See header file for description.
--------------------------------------------------*/
static void K_FreeFinishBeamLine(void)
{
if (finishBeamLine != NULL)
{
if (finishBeamLine->v1 != NULL)
{
Z_Free(finishBeamLine->v1);
}
if (finishBeamLine->v2 != NULL)
{
Z_Free(finishBeamLine->v2);
}
Z_Free(finishBeamLine);
}
K_ClearFinishBeamLine();
}
/*--------------------------------------------------
static void K_CreateFinishLineFromPoints(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
See header file for description.
--------------------------------------------------*/
static void K_CreateFinishLineFromPoints(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
{
I_Assert(finishBeamLine == NULL); // Needs to be NULL
finishBeamLine = Z_Calloc(sizeof (*finishBeamLine), PU_LEVEL, NULL);
finishBeamLine->v1 = Z_Calloc(sizeof (*finishBeamLine->v1), PU_LEVEL, NULL);
finishBeamLine->v1->x = x1;
finishBeamLine->v1->y = y1;
finishBeamLine->v2 = Z_Calloc(sizeof (*finishBeamLine->v2), PU_LEVEL, NULL);
finishBeamLine->v2->x = x2;
finishBeamLine->v2->y = y2;
finishBeamLine->dx = x2 - x1;
finishBeamLine->dy = y2 - y1;
finishBeamLine->flags = 0;
}
/*--------------------------------------------------
boolean K_GenerateFinishBeamLine(void)
See header file for description.
--------------------------------------------------*/
boolean K_GenerateFinishBeamLine(void)
{
mapthing_t *mt;
INT64 bounds[4];
angle_t angle;
boolean valid = false;
size_t i;
// Ensure everything's freed by this time.
K_FreeFinishBeamLine();
// First: attempt to create from beam point objects
for (i = 0, mt = mapthings; i < nummapthings; i++, mt++)
{
if (numBeamPoints >= 2)
{
break;
}
if (mt->type == mobjinfo[MT_BEAMPOINT].doomednum)
{
beamPoints[numBeamPoints] = mt->mobj;
numBeamPoints++;
}
}
if (numBeamPoints == 2)
{
// Found 'em! Really easy to generate a line out of these :)
K_CreateFinishLineFromPoints(
beamPoints[0]->x, beamPoints[0]->y,
beamPoints[1]->x, beamPoints[1]->y
);
return true;
}
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++)
{
angle_t thisAngle;
if (lines[i].special != 2001)
{
continue;
}
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;
valid = true;
}
else if (angle != thisAngle)
{
// Do not even attempt to bother with curved finish lines.
// Will likely just crash.
valid = false;
break;
}
}
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;
fixed_t spanC = FixedMul(span, FINECOSINE(angle >> ANGLETOFINESHIFT));
fixed_t spanS = FixedMul(span, FINESINE(angle >> ANGLETOFINESHIFT));
K_CreateFinishLineFromPoints(
cx - spanC, cy - spanS,
cx + spanC, cy + spanS
);
return true;
}
return false;
}
/*--------------------------------------------------
static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *line, boolean reverse)
Draws a helix out of rainbow colored orbs along a line, unique for each display player.
Called twice for the finish line beam effect.
Input Arguments:-
offset - Offset value for positioning. Changed every tick to make it animate.
aiming - Starting vertical angle value. Changed every tick to make it animate.
line - Linedef to draw along.
reverse - Draw in reverse. Call twice with this toggled to make a double helix.
Return:-
None
--------------------------------------------------*/
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)
See header file for description.
--------------------------------------------------*/
void K_RunFinishLineBeam(void)
{
if (!(leveltime < starttime || rainbowstartavailable == true))
{
return;
}
if (finishBeamLine != NULL)
{
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);
K_DrawFinishLineBeamForLine(offseta, aiminga, finishBeamLine, false);
K_DrawFinishLineBeamForLine(offsetb, aimingb, finishBeamLine, true);
}
}

67
src/k_race.h Normal file
View file

@ -0,0 +1,67 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2018-2020 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_race.h
/// \brief Race Mode specific code.
#ifndef __K_RACE__
#define __K_RACE__
#include "r_defs.h"
#define FINISHLINEBEAM_SPACING (48*mapobjectscale)
/*--------------------------------------------------
void K_ClearFinishBeamLine(void);
Clears variables for finishBeamLine.
Separate from K_FreeFinishBeamLine since this
needs called when PU_LEVEL is freed.
Input Arguments:-
None
Return:-
None
--------------------------------------------------*/
void K_ClearFinishBeamLine(void);
/*--------------------------------------------------
boolean K_GenerateFinishBeamLine(void);
Finds pre-placed "beam points" to create a finish line out of,
or tries to automatically create it from a finish linedef in the map.
The result is stored in the "finishBeamLine" variable.
Input Arguments:-
None
Return:-
True if successful, otherwise false.
--------------------------------------------------*/
boolean K_GenerateFinishBeamLine(void);
/*--------------------------------------------------
void K_RunFinishLineBeam(void);
Updates the finish line beam effect.
Input Arguments:-
None
Return:-
None
--------------------------------------------------*/
void K_RunFinishLineBeam(void);
#endif

View file

@ -83,6 +83,7 @@
// SRB2Kart
#include "k_kart.h"
#include "k_race.h"
#include "k_battle.h" // K_SpawnBattleCapsules
#include "k_pwrlv.h"
#include "k_waypoint.h"
@ -4059,6 +4060,8 @@ boolean P_LoadLevel(boolean fromnetsave)
// The waypoint data that's in PU_LEVEL needs to be reset back to 0/NULL now since PU_LEVEL was cleared
K_ClearWaypoints();
K_ClearFinishBeamLine();
// Load the waypoints please!
if (gametyperules & GTR_CIRCUIT)
{
@ -4066,6 +4069,11 @@ boolean P_LoadLevel(boolean fromnetsave)
{
CONS_Alert(CONS_ERROR, "Waypoints were not able to be setup! Player positions will not work correctly.\n");
}
if (K_GenerateFinishBeamLine() == false)
{
CONS_Alert(CONS_ERROR, "No valid finish line beam setup could be found.\n");
}
}
#ifdef HWRENDER // not win32 only 19990829 by Kin

View file

@ -30,6 +30,7 @@
// SRB2Kart
#include "k_kart.h"
#include "k_race.h"
#include "k_battle.h"
#include "k_waypoint.h"