mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-02-08 22:56:00 +00:00
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:
commit
6a2c5368ee
10 changed files with 531 additions and 244 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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\
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
27
src/info.c
27
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
|
||||
|
|
|
|||
|
|
@ -6383,6 +6383,8 @@ typedef enum mobj_type
|
|||
|
||||
MT_PAPERITEMSPOT,
|
||||
|
||||
MT_BEAMPOINT,
|
||||
|
||||
#ifdef SEENAMES
|
||||
MT_NAMECHECK,
|
||||
#endif
|
||||
|
|
|
|||
244
src/k_kart.c
244
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);
|
||||
|
|
|
|||
421
src/k_race.c
Normal file
421
src/k_race.c
Normal 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
67
src/k_race.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
// SRB2Kart
|
||||
#include "k_kart.h"
|
||||
#include "k_race.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_waypoint.h"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue