diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1d461a820..42006e423 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/Makefile b/src/Makefile index de857fd1d..3499dd24a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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\ diff --git a/src/dehacked.c b/src/dehacked.c index e6a63fac3..c63339bfc 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -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 diff --git a/src/info.c b/src/info.c index d804c5978..5e6060dd6 100644 --- a/src/info.c +++ b/src/info.c @@ -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 diff --git a/src/info.h b/src/info.h index 099f9c412..2c7a3ed23 100644 --- a/src/info.h +++ b/src/info.h @@ -6383,6 +6383,8 @@ typedef enum mobj_type MT_PAPERITEMSPOT, + MT_BEAMPOINT, + #ifdef SEENAMES MT_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index 5b259a050..fd485a5cf 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -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); diff --git a/src/k_race.c b/src/k_race.c new file mode 100644 index 000000000..7d65ee2e6 --- /dev/null +++ b/src/k_race.c @@ -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); + } +} diff --git a/src/k_race.h b/src/k_race.h new file mode 100644 index 000000000..13d870f8e --- /dev/null +++ b/src/k_race.h @@ -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 diff --git a/src/p_setup.c b/src/p_setup.c index 13c0170a8..6cd4ffd72 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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 diff --git a/src/p_tick.c b/src/p_tick.c index 4d4ba4b26..71ded772c 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -30,6 +30,7 @@ // SRB2Kart #include "k_kart.h" +#include "k_race.h" #include "k_battle.h" #include "k_waypoint.h"