Store where the finish line beam should be displayed

Instead of figuring out where it should be every tick while it's visible, store where it'll be at the start of the map.

Also moved finish line beam into a new file, k_race.c/h, for any Race-specific code.

A few unused variables for sprint map support later too
This commit is contained in:
Sally Coolatta 2021-02-05 01:24:23 -05:00
parent 090daaac02
commit 90ca38acb0
7 changed files with 474 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

@ -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);

387
src/k_race.c Normal file
View file

@ -0,0 +1,387 @@
// 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;
mobj_t *beamPoints[2];
UINT8 numBeamPoints = 0;
/*--------------------------------------------------
void K_ClearFinishBeamLine(void)
See header file for description.
--------------------------------------------------*/
void K_ClearFinishBeamLine(void)
{
finishBeamLine = NULL;
}
/*--------------------------------------------------
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)
{
INT64 bounds[4];
angle_t angle;
boolean valid = false;
size_t i;
// Ensure everything's freed by this time.
K_FreeFinishBeamLine();
//
// TODO: create from beam point objs before resorting to auto generate
//
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);
}
}

70
src/k_race.h Normal file
View file

@ -0,0 +1,70 @@
// 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"
extern mobj_t *beamPoints[2];
extern UINT8 numBeamPoints;
#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"
@ -3609,6 +3610,11 @@ static void P_ResetSpawnpoints(void)
for (i = 0; i < 16; i++)
skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL;
// SRB2Kart
numBeamPoints = 0;
for (i = 0; i < 2; i++)
beamPoints[i] = NULL;
}
static void P_LoadRecordGhosts(void)
@ -4059,6 +4065,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 +4074,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"