Merge branch 'respawn-updates' into 'master'

Respawn updates

See merge request KartKrew/Kart!273
This commit is contained in:
Sal 2020-06-04 02:55:58 -04:00
commit d6806b863e
24 changed files with 1191 additions and 645 deletions

View file

@ -166,6 +166,7 @@ set(SRB2_CORE_GAME_SOURCES
k_bot.c
k_botitem.c
k_botsearch.c
k_respawn.c
p_local.h
p_maputl.h
@ -186,6 +187,7 @@ set(SRB2_CORE_GAME_SOURCES
k_waypoint.h
k_color.h
k_bot.h
k_respawn.h
)
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))

View file

@ -505,14 +505,6 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/hu_stuff.o \
$(OBJDIR)/y_inter.o \
$(OBJDIR)/st_stuff.o \
$(OBJDIR)/k_kart.o \
$(OBJDIR)/k_collide.o\
$(OBJDIR)/k_color.o \
$(OBJDIR)/k_battle.o \
$(OBJDIR)/k_pwrlv.o \
$(OBJDIR)/k_waypoint.o\
$(OBJDIR)/k_pathfind.o\
$(OBJDIR)/k_bheap.o \
$(OBJDIR)/m_aatree.o \
$(OBJDIR)/m_anigif.o \
$(OBJDIR)/m_argv.o \
@ -562,6 +554,15 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/i_tcp.o \
$(OBJDIR)/lzf.o \
$(OBJDIR)/vid_copy.o \
$(OBJDIR)/k_kart.o \
$(OBJDIR)/k_respawn.o\
$(OBJDIR)/k_collide.o\
$(OBJDIR)/k_color.o \
$(OBJDIR)/k_battle.o \
$(OBJDIR)/k_pwrlv.o \
$(OBJDIR)/k_waypoint.o\
$(OBJDIR)/k_pathfind.o\
$(OBJDIR)/k_bheap.o \
$(OBJDIR)/k_bot.o \
$(OBJDIR)/k_botitem.o \
$(OBJDIR)/k_botsearch.o \

View file

@ -571,10 +571,6 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
for (j = 0; j < NUMPOWERS; ++j)
rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]);
for (j = 0; j < NUMKARTSTUFF; ++j)
rsp->kartstuff[j] = LONG(players[i].kartstuff[j]); // SRB2kart
rsp->frameangle = (angle_t)LONG(players[i].frameangle); // SRB2kart
// Score is resynched in the rspfirm resync packet
rsp->health = 0; // resynched with mo health
@ -612,12 +608,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->weapondelay = LONG(players[i].weapondelay);
rsp->tossdelay = LONG(players[i].tossdelay);
rsp->starpostx = SHORT(players[i].starpostx);
rsp->starposty = SHORT(players[i].starposty);
rsp->starpostz = SHORT(players[i].starpostz);
rsp->starpostnum = LONG(players[i].starpostnum);
rsp->starposttime = (tic_t)LONG(players[i].starposttime);
rsp->starpostangle = (angle_t)LONG(players[i].starpostangle);
rsp->maxlink = LONG(players[i].maxlink);
rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed);
@ -646,6 +637,24 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->splitscreenindex = players[i].splitscreenindex;
// SRB2kart
for (j = 0; j < NUMKARTSTUFF; ++j)
rsp->kartstuff[j] = LONG(players[i].kartstuff[j]);
rsp->frameangle = (angle_t)LONG(players[i].frameangle);
rsp->airtime = (tic_t)LONG(players[i].airtime);
// respawnvars_t
rsp->respawn_state = players[i].respawn.state;
rsp->respawn_pointx = (fixed_t)LONG(players[i].respawn.pointx);
rsp->respawn_pointy = (fixed_t)LONG(players[i].respawn.pointy);
rsp->respawn_pointz = (fixed_t)LONG(players[i].respawn.pointz);
rsp->respawn_flip = players[i].respawn.flip;
rsp->respawn_timer = (tic_t)LONG(players[i].respawn.timer);
rsp->respawn_distanceleft = (UINT32)LONG(players[i].respawn.distanceleft);
rsp->respawn_dropdash = (tic_t)LONG(players[i].respawn.dropdash);
// botvars_t
rsp->bot = players[i].bot;
rsp->bot_difficulty = players[i].botvars.difficulty;
rsp->bot_itemdelay = players[i].botvars.itemdelay;
@ -701,10 +710,6 @@ static void resynch_read_player(resynch_pak *rsp)
for (j = 0; j < NUMPOWERS; ++j)
players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]);
for (j = 0; j < NUMKARTSTUFF; ++j)
players[i].kartstuff[j] = LONG(rsp->kartstuff[j]); // SRB2kart
players[i].frameangle = (angle_t)LONG(rsp->frameangle); // SRB2kart
// Score is resynched in the rspfirm resync packet
players[i].health = rsp->health;
@ -741,12 +746,7 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].weapondelay = LONG(rsp->weapondelay);
players[i].tossdelay = LONG(rsp->tossdelay);
players[i].starpostx = SHORT(rsp->starpostx);
players[i].starposty = SHORT(rsp->starposty);
players[i].starpostz = SHORT(rsp->starpostz);
players[i].starpostnum = LONG(rsp->starpostnum);
players[i].starposttime = (tic_t)LONG(rsp->starposttime);
players[i].starpostangle = (angle_t)LONG(rsp->starpostangle);
players[i].maxlink = LONG(rsp->maxlink);
players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed);
@ -775,6 +775,24 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].splitscreenindex = rsp->splitscreenindex;
// SRB2kart
for (j = 0; j < NUMKARTSTUFF; ++j)
players[i].kartstuff[j] = LONG(rsp->kartstuff[j]);
players[i].frameangle = (angle_t)LONG(rsp->frameangle);
players[i].airtime = (tic_t)LONG(rsp->airtime);
// respawnvars_t
players[i].respawn.state = rsp->respawn_state;
players[i].respawn.pointx = (fixed_t)LONG(rsp->respawn_pointx);
players[i].respawn.pointy = (fixed_t)LONG(rsp->respawn_pointy);
players[i].respawn.pointz = (fixed_t)LONG(rsp->respawn_pointz);
players[i].respawn.flip = (boolean)rsp->respawn_flip;
players[i].respawn.timer = (tic_t)LONG(rsp->respawn_timer);
players[i].respawn.distanceleft = (UINT32)LONG(rsp->respawn_distanceleft);
players[i].respawn.dropdash = (tic_t)LONG(rsp->respawn_dropdash);
// botvars_t
players[i].bot = rsp->bot;
players[i].botvars.difficulty = rsp->bot_difficulty;
players[i].botvars.itemdelay = rsp->bot_itemdelay;

View file

@ -213,9 +213,6 @@ typedef struct
UINT16 powers[NUMPOWERS];
INT32 kartstuff[NUMKARTSTUFF]; // SRB2kart
angle_t frameangle; // SRB2kart
// Score is resynched in the confirm resync packet
INT32 health;
SINT8 lives;
@ -252,12 +249,7 @@ typedef struct
INT32 weapondelay;
INT32 tossdelay;
INT16 starpostx;
INT16 starposty;
INT16 starpostz;
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
INT32 maxlink;
fixed_t dashspeed;
@ -285,6 +277,22 @@ typedef struct
UINT8 splitscreenindex;
// SRB2kart
INT32 kartstuff[NUMKARTSTUFF];
angle_t frameangle;
tic_t airtime;
// respawnvars_t
UINT8 respawn_state;
fixed_t respawn_pointx;
fixed_t respawn_pointy;
fixed_t respawn_pointz;
boolean respawn_flip;
tic_t respawn_timer;
UINT32 respawn_distanceleft;
tic_t respawn_dropdash;
// botvars_t
boolean bot;
UINT8 bot_difficulty;
tic_t bot_itemdelay;

View file

@ -51,6 +51,7 @@
#include "k_pwrlv.h"
#include "y_inter.h"
#include "k_color.h"
#include "k_respawn.h"
#ifdef NETGAME_DEVMODE
#define CV_RESTRICT CV_NETVAR

View file

@ -264,9 +264,6 @@ typedef enum
k_position, // Used for Kart positions, mostly for deterministic stuff
k_oldposition, // Used for taunting when you pass someone
k_positiondelay, // Used for position number, so it can grow when passing/being passed
k_starpostflip, // the last starpost we hit requires flipping?
k_respawn, // Timer for the DEZ laser respawn effect
k_dropdash, // Charge up for respawn Drop Dash
k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir")
k_instashield, // Instashield no-damage animation timer
@ -420,6 +417,20 @@ typedef enum
RW_RAIL = 32
} ringweapons_t;
// player_t struct for all respawn variables
typedef struct respawnvars_s
{
UINT8 state; // 0: not respawning, 1: heading towards respawn point, 2: about to drop
waypoint_t *wp; // Waypoint that we're going towards, NULL if the position isn't linked to one
fixed_t pointx; // Respawn position coords to go towards
fixed_t pointy;
fixed_t pointz;
boolean flip; // Flip upside down or not
tic_t timer; // Time left on respawn animation once you're there
UINT32 distanceleft; // How far along the course to respawn you
tic_t dropdash; // Drop Dash charge timer
} respawnvars_t;
// player_t struct for all bot variables
typedef struct botvars_s
{
@ -477,6 +488,8 @@ typedef struct player_s
INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right
UINT32 distancetofinish;
waypoint_t *nextwaypoint;
respawnvars_t respawn; // Respawn info
tic_t airtime; // Keep track of how long you've been in the air
// Bit flags.
// See pflags_t, above.
@ -542,6 +555,7 @@ typedef struct player_s
INT16 totalring; // Total number of rings obtained for Race Mode
tic_t realtime; // integer replacement for leveltime
UINT8 laps; // Number of laps (optional)
INT32 starpostnum; // The number of the last starpost you hit
////////////////////
// CTF Mode Stuff //
@ -552,14 +566,6 @@ typedef struct player_s
INT32 weapondelay; // Delay (if any) to fire the weapon again
INT32 tossdelay; // Delay (if any) to toss a flag/emeralds again
// Starpost information
INT16 starpostx;
INT16 starposty;
INT16 starpostz;
INT32 starpostnum; // The number of the last starpost you hit
tic_t starposttime; // Your time when you hit the starpost
angle_t starpostangle; // Angle that the starpost is facing - you respawn facing this way
/////////////////
// NiGHTS Stuff//
/////////////////

View file

@ -8338,9 +8338,6 @@ static const char *const KARTSTUFF_LIST[] = {
"POSITION",
"OLDPOSITION",
"POSITIONDELAY",
"STARPOSTFLIP",
"RESPAWN",
"DROPDASH",
"THROWDIR",
"INSTASHIELD",

View file

@ -53,6 +53,7 @@
#include "k_battle.h"
#include "k_pwrlv.h"
#include "k_color.h"
#include "k_respawn.h"
gameaction_t gameaction;
gamestate_t gamestate = GS_NULL;
@ -1585,7 +1586,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// SRB2kart - no additional angle if not moving
if ((player->mo && player->speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (player->kartstuff[k_respawn]) // Respawning
|| (player->respawn.state != RESPAWNST_NONE) // Respawning
|| (player->spectator || objectplacing)) // Not a physical player
lang += (cmd->angleturn<<16);
@ -2535,12 +2536,9 @@ static inline void G_PlayerFinishLevel(INT32 player)
p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility
P_FlashPal(p, 0, 0); // Resets
p->starpostangle = 0;
p->starposttime = 0;
p->starpostx = 0;
p->starposty = 0;
p->starpostz = 0;
p->starpostnum = 0;
memset(&p->respawn, 0, sizeof (p->respawn));
// SRB2kart: Increment the "matches played" counter.
if (player == consoleplayer)
@ -2574,12 +2572,7 @@ void G_PlayerReborn(INT32 player)
INT32 charflags;
INT32 pflags;
INT32 ctfteam;
INT32 starposttime;
INT16 starpostx;
INT16 starposty;
INT16 starpostz;
INT32 starpostnum;
INT32 starpostangle;
INT32 exiting;
INT16 numboxes;
INT16 totalring;
@ -2595,6 +2588,7 @@ void G_PlayerReborn(INT32 player)
SINT8 pity;
// SRB2kart
respawnvars_t respawn;
INT32 itemtype;
INT32 itemamount;
INT32 itemroulette;
@ -2604,7 +2598,6 @@ void G_PlayerReborn(INT32 player)
INT32 comebackpoints;
INT32 wanted;
INT32 rings;
INT32 respawnflip;
boolean songcredit = false;
score = players[player].score;
@ -2634,13 +2627,7 @@ void G_PlayerReborn(INT32 player)
//
charflags = players[player].charflags;
starposttime = players[player].starposttime;
starpostx = players[player].starpostx;
starposty = players[player].starposty;
starpostz = players[player].starpostz;
starpostnum = players[player].starpostnum;
respawnflip = players[player].kartstuff[k_starpostflip]; //SRB2KART
starpostangle = players[player].starpostangle;
mare = players[player].mare;
bot = players[player].bot;
@ -2688,6 +2675,8 @@ void G_PlayerReborn(INT32 player)
wanted = players[player].kartstuff[k_wanted];
}
memcpy(&respawn, &players[player].respawn, sizeof (respawn));
p = &players[player];
memset(p, 0, sizeof (*p));
@ -2710,12 +2699,7 @@ void G_PlayerReborn(INT32 player)
//
p->charflags = charflags;
p->starposttime = starposttime;
p->starpostx = starpostx;
p->starposty = starposty;
p->starpostz = starpostz;
p->starpostnum = starpostnum;
p->starpostangle = starpostangle;
p->exiting = exiting;
p->numboxes = numboxes;
@ -2740,7 +2724,8 @@ void G_PlayerReborn(INT32 player)
p->kartstuff[k_wanted] = wanted;
p->kartstuff[k_eggmanblame] = -1;
p->kartstuff[k_lastdraft] = -1;
p->kartstuff[k_starpostflip] = respawnflip;
memcpy(&p->respawn, &respawn, sizeof (p->respawn));
// Don't do anything immediately
p->pflags |= PF_USEDOWN;
@ -2773,7 +2758,9 @@ void G_PlayerReborn(INT32 player)
S_ShowMusicCredit();
if (leveltime > (starttime + (TICRATE/2)) && !p->spectator)
p->kartstuff[k_respawn] = 48; // Respawn effect
{
K_DoIngameRespawn(p);
}
if (gametype == GT_COOP)
P_FindEmerald(); // scan for emeralds to hunt for
@ -4591,8 +4578,8 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
for (i = 0; i < MAXPLAYERS; i++)
{
players[i].playerstate = PST_REBORN;
players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
players[i].starpostx = players[i].starposty = players[i].starpostz = 0;
players[i].starpostnum = 0;
memset(&players[i].respawn, 0, sizeof (players[i].respawn));
#if 0
if (netgame || multiplayer)
@ -5114,7 +5101,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
// SRB2kart: Copy-pasted from ticcmd building, removes that crappy demo cam
if (((players[displayplayers[0]].mo && players[displayplayers[0]].speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (players[displayplayers[0]].kartstuff[k_respawn]) // Respawning
|| (players[displayplayers[0]].respawn.state != RESPAWNST_NONE) // Respawning
|| (players[displayplayers[0]].spectator || objectplacing)) // Not a physical player
&& !(players[displayplayers[0]].kartstuff[k_spinouttimer]
&& (players[displayplayers[0]].kartstuff[k_sneakertimer] || players[displayplayers[0]].kartstuff[k_levelbooster]))) // Spinning and boosting cancels out spinout

View file

@ -8,6 +8,7 @@
#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"
@ -1007,8 +1008,8 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
|| (mobj2->player && mobj2->player->playerstate != PST_LIVE))
return;
if ((mobj1->player && mobj1->player->kartstuff[k_respawn])
|| (mobj2->player && mobj2->player->kartstuff[k_respawn]))
if ((mobj1->player && mobj1->player->respawn.state != RESPAWNST_NONE)
|| (mobj2->player && mobj2->player->respawn.state != RESPAWNST_NONE))
return;
{ // Don't bump if you're flashing
@ -1506,7 +1507,6 @@ void K_FlipFromObject(mobj_t *mo, mobj_t *master)
mo->z += master->height - FixedMul(master->scale, mo->height);
}
// These have to go earlier than its sisters because of K_RespawnChecker...
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master)
{
// flipping
@ -1521,7 +1521,7 @@ void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master)
mo->eflags = (mo->eflags & ~MFE_DRAWONLYFORP4)|(master->eflags & MFE_DRAWONLYFORP4);
}
static void K_SpawnDashDustRelease(player_t *player)
void K_SpawnDashDustRelease(player_t *player)
{
fixed_t newx;
fixed_t newy;
@ -1580,362 +1580,6 @@ static void K_SpawnBrakeDriftSparks(player_t *player) // Be sure to update the m
sparks->flags2 |= MF2_DONTDRAW;
}
/** \brief Preps a player to respawn
\param player player to respawn
\return void
*/
void K_DoIngameRespawn(player_t *player)
{
if (!player->mo || P_MobjWasRemoved(player->mo))
return;
if (player->kartstuff[k_respawn])
return;
if (leveltime <= starttime)
return;
if (player->nextwaypoint == NULL) // Starpost xyz not initalized(?)
{
UINT32 bestdist = UINT32_MAX;
mapthing_t *beststart = NULL;
UINT8 numstarts = 0;
if (G_RaceGametype())
{
numstarts = numcoopstarts;
}
else if (G_BattleGametype())
{
numstarts = numdmstarts;
}
if (numstarts > 0)
{
UINT8 i = 0;
for (i = 0; i < numstarts; i++)
{
UINT32 dist = UINT32_MAX;
mapthing_t *checkstart = NULL;
if (G_RaceGametype())
{
checkstart = playerstarts[i];
}
else if (G_BattleGametype())
{
checkstart = deathmatchstarts[i];
}
else
{
break;
}
dist = (UINT32)P_AproxDistance((player->mo->x >> FRACBITS) - checkstart->x,
(player->mo->y >> FRACBITS) - checkstart->y);
if (dist < bestdist)
{
beststart = checkstart;
bestdist = dist;
}
}
}
if (beststart == NULL)
{
CONS_Alert(CONS_WARNING, "No respawn points!\n");
}
else
{
sector_t *s;
fixed_t z = (beststart->options >> ZSHIFT);
player->starpostx = beststart->x;
player->starposty = beststart->y;
s = R_PointInSubsector(beststart->x << FRACBITS, beststart->y << FRACBITS)->sector;
if (beststart->options & MTF_OBJECTFLIP)
{
player->starpostz = (
#ifdef ESLOPE
s->c_slope ? P_GetZAt(s->c_slope, beststart->x << FRACBITS, beststart->y << FRACBITS) :
#endif
s->ceilingheight) >> FRACBITS;
if (z)
player->starpostz -= z;
player->starpostz -= mobjinfo[MT_PLAYER].height;
player->kartstuff[k_starpostflip] = 1;
}
else
{
player->starpostz = (
#ifdef ESLOPE
s->f_slope ? P_GetZAt(s->f_slope, beststart->x << FRACBITS, beststart->y << FRACBITS) :
#endif
s->floorheight) >> FRACBITS;
if (z)
player->starpostz += z;
player->kartstuff[k_starpostflip] = 0;
}
}
}
player->mo->flags &= ~(MF_SOLID|MF_SHOOTABLE);
player->mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY;
player->mo->flags2 &= ~MF2_DONTDRAW;
player->kartstuff[k_respawn] = 48;
}
/** \brief Calculates the respawn timer and drop-boosting
\param player player object passed from K_KartPlayerThink
\return void
*/
void K_RespawnChecker(player_t *player)
{
ticcmd_t *cmd = &player->cmd;
if (player->spectator)
return;
if (player->kartstuff[k_respawn] > 1)
{
fixed_t destx = 0, desty = 0, destz = 0;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
player->powers[pw_flashing] = 2;
player->powers[pw_nocontrol] = 2;
if (leveltime % 8 == 0 && !mapreset)
S_StartSound(player->mo, sfx_s3kcas);
destx = (player->starpostx << FRACBITS);
desty = (player->starposty << FRACBITS);
destz = (player->starpostz << FRACBITS);
if (player->kartstuff[k_starpostflip])
{
// This variable is set from the settings of the best waypoint, thus this waypoint is FLIPPED as well.
// So we should flip the player in advance for it as well.
player->mo->flags2 |= MF2_OBJECTFLIP;
player->mo->eflags |= MFE_VERTICALFLIP;
destz -= (128 * mapobjectscale) + (player->mo->height);
}
else
{
// Ditto, but this waypoint isn't flipped, so make sure the player also isn't flipped!
player->mo->flags2 &= ~MF2_OBJECTFLIP;
player->mo->eflags &= ~MFE_VERTICALFLIP;
destz += (128 * mapobjectscale);
}
if (player->mo->x != destx || player->mo->y != desty || player->mo->z != destz)
{
fixed_t step = 64*mapobjectscale;
fixed_t dist = P_AproxDistance(P_AproxDistance(player->mo->x - destx, player->mo->y - desty), player->mo->z - destz);
if (dist <= step) // You're ready to respawn
{
P_TryMove(player->mo, destx, desty, true);
player->mo->z = destz;
}
else
{
fixed_t stepx = 0, stepy = 0, stepz = 0;
angle_t stepha = R_PointToAngle2(player->mo->x, player->mo->y, destx, desty);
angle_t stepva = R_PointToAngle2(0, player->mo->z, P_AproxDistance(player->mo->x - destx, player->mo->y - desty), destz);
fixed_t laserx = 0, lasery = 0, laserz = 0;
UINT8 lasersteps = 4;
// Move toward the respawn point
stepx = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), step), FINECOSINE(stepva >> ANGLETOFINESHIFT));
stepy = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), step), FINECOSINE(stepva >> ANGLETOFINESHIFT));
stepz = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*step);
P_TryMove(player->mo, player->mo->x + stepx, player->mo->y + stepy, true);
player->mo->z += stepz;
// Spawn lasers along the path
laserx = player->mo->x + (stepx / 2);
lasery = player->mo->y + (stepy / 2);
laserz = player->mo->z + (stepz / 2);
dist = P_AproxDistance(P_AproxDistance(laserx - destx, lasery - desty), laserz - destz);
if (dist > step/2)
{
while (lasersteps)
{
stepha = R_PointToAngle2(laserx, lasery, destx, desty);
stepva = R_PointToAngle2(0, laserz, P_AproxDistance(laserx - destx, lasery - desty), destz);
stepx = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), step), FINECOSINE(stepva >> ANGLETOFINESHIFT));
stepy = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), step), FINECOSINE(stepva >> ANGLETOFINESHIFT));
stepz = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*step);
laserx += stepx;
lasery += stepy;
laserz += stepz;
dist = P_AproxDistance(P_AproxDistance(laserx - destx, lasery - desty), laserz - destz);
if (dist <= step/2)
break;
lasersteps--;
}
}
if (lasersteps == 0) // Don't spawn them beyond the respawn point.
{
mobj_t *laser;
laser = P_SpawnMobj(laserx, lasery, laserz + (player->mo->height / 2), MT_DEZLASER);
if (laser && !P_MobjWasRemoved(laser))
{
P_SetMobjState(laser, S_DEZLASER_TRAIL1);
if (player->mo->eflags & MFE_VERTICALFLIP)
laser->eflags |= MFE_VERTICALFLIP;
P_SetTarget(&laser->target, player->mo);
laser->angle = stepha + ANGLE_90;
P_SetScale(laser, (laser->destscale = FRACUNIT));
}
}
}
}
else
{
player->kartstuff[k_respawn]--;
player->mo->flags |= MF_SOLID|MF_SHOOTABLE;
player->mo->flags &= ~(MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY);
if (!(player->pflags & PF_NOCLIP))
player->mo->flags &= ~MF_NOCLIP;
if (leveltime % 8 == 0)
{
INT32 i;
for (i = 0; i < 8; i++)
{
mobj_t *laser;
angle_t newangle;
fixed_t newx, newy, newz;
newangle = FixedAngle(((360/8)*i)*FRACUNIT);
newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31 * player->mo->scale);
newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31 * player->mo->scale);
if (player->mo->eflags & MFE_VERTICALFLIP)
newz = player->mo->z + player->mo->height;
else
newz = player->mo->z;
laser = P_SpawnMobj(newx, newy, newz, MT_DEZLASER);
if (laser && !P_MobjWasRemoved(laser))
{
if (player->mo->eflags & MFE_VERTICALFLIP)
laser->eflags |= MFE_VERTICALFLIP;
P_SetTarget(&laser->target, player->mo);
laser->angle = newangle+ANGLE_90;
laser->momz = (8 * player->mo->scale) * P_MobjFlip(player->mo);
P_SetScale(laser, (laser->destscale = player->mo->scale));
}
}
}
}
}
else if (player->kartstuff[k_respawn] == 1)
{
if (player->kartstuff[k_growshrinktimer] < 0)
{
player->mo->scalespeed = mapobjectscale/TICRATE;
player->mo->destscale = (6*mapobjectscale)/8;
if (cv_kartdebugshrink.value && !modeattacking && !player->bot)
player->mo->destscale = (6*player->mo->destscale)/8;
}
if (!P_IsObjectOnGround(player->mo) && !mapreset)
{
player->powers[pw_flashing] = K_GetKartFlashing(player);
// Sal: The old behavior was stupid and prone to accidental usage.
// Let's rip off Mania instead, and turn this into a Drop Dash!
if (cmd->buttons & BT_ACCELERATE && !player->kartstuff[k_spinouttimer]) // Lat: Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway)
player->kartstuff[k_dropdash]++;
else
player->kartstuff[k_dropdash] = 0;
if (player->kartstuff[k_dropdash] == TICRATE/4)
S_StartSound(player->mo, sfx_ddash);
if ((player->kartstuff[k_dropdash] >= TICRATE/4)
&& (player->kartstuff[k_dropdash] & 1))
player->mo->colorized = true;
else
player->mo->colorized = false;
}
else
{
if ((cmd->buttons & BT_ACCELERATE) && (player->kartstuff[k_dropdash] >= TICRATE/4))
{
S_StartSound(player->mo, sfx_s23c);
player->kartstuff[k_startboost] = 50;
K_SpawnDashDustRelease(player);
}
player->mo->colorized = false;
player->kartstuff[k_dropdash] = 0;
player->kartstuff[k_respawn] = 0;
//P_PlayRinglossSound(player->mo);
P_PlayerRingBurst(player, 3);
if (G_BattleGametype())
{
if (player->kartstuff[k_bumper] > 0)
{
if (player->kartstuff[k_bumper] == 1)
{
mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!!
P_SetTarget(&karmahitbox->target, player->mo);
karmahitbox->destscale = player->mo->scale;
P_SetScale(karmahitbox, player->mo->scale);
CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]);
}
player->kartstuff[k_bumper]--;
if (K_IsPlayerWanted(player))
K_CalculateBattleWanted();
}
if (!player->kartstuff[k_bumper])
{
player->kartstuff[k_comebacktimer] = comebacktime;
if (player->kartstuff[k_comebackmode] == 2)
{
mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE);
S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound);
player->kartstuff[k_comebackmode] = 0;
}
}
K_CheckBumpers();
}
}
}
}
/** \brief Handles the state changing for moving players, moved here to eliminate duplicate code
\param player player data
@ -5272,7 +4916,7 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd)
#endif
return;
if ((leveltime >= starttime-(2*TICRATE) && leveltime <= starttime) || (player->kartstuff[k_respawn] == 1)) // Startup boosts
if ((leveltime >= starttime-(2*TICRATE) && leveltime <= starttime) || (player->respawn.state == RESPAWNST_DROP)) // Startup boosts
targetsnd = ((cmd->buttons & BT_ACCELERATE) ? 12 : 0);
else
targetsnd = (((6*cmd->forwardmove)/25) + ((player->speed / mapobjectscale)/5))/2;
@ -5673,7 +5317,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
}
}
if (player->playerstate == PST_DEAD || player->kartstuff[k_respawn] > 1) // Ensure these are set correctly here
if (player->playerstate == PST_DEAD || (player->respawn.state == RESPAWNST_MOVE)) // Ensure these are set correctly here
{
player->mo->colorized = false;
player->mo->color = player->skincolor;
@ -5849,7 +5493,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->kartstuff[k_invincibilitytimer])
player->kartstuff[k_invincibilitytimer]--;
if (!player->kartstuff[k_respawn] && player->kartstuff[k_growshrinktimer] != 0)
if ((player->respawn.state == RESPAWNST_NONE) && player->kartstuff[k_growshrinktimer] != 0)
{
if (player->kartstuff[k_growshrinktimer] > 0)
player->kartstuff[k_growshrinktimer]--;
@ -5919,7 +5563,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (G_BattleGametype() && player->kartstuff[k_bumper] > 0
&& !player->kartstuff[k_spinouttimer] && !player->kartstuff[k_squishedtimer]
&& !player->kartstuff[k_respawn] && !player->powers[pw_flashing])
&& (player->respawn.state == RESPAWNST_DROP) && !player->powers[pw_flashing])
{
player->kartstuff[k_wanted]++;
if (battleovertime.enabled >= 10*TICRATE)
@ -6005,10 +5649,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
else
player->kartstuff[k_jmp] = 0;
// Respawn Checker
if (player->kartstuff[k_respawn])
K_RespawnChecker(player);
// Roulette Code
K_KartItemRoulette(player, cmd);
@ -6265,36 +5905,13 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
// Respawn point should only be updated when we're going to a nextwaypoint
if ((updaterespawn) &&
(player->respawn.state == RESPAWNST_NONE) &&
(bestwaypoint != NULL) &&
(bestwaypoint != player->nextwaypoint) &&
(player->kartstuff[k_respawn] == 0) &&
(K_GetWaypointIsSpawnpoint(bestwaypoint)) && // Don't try to respawn on waypoints that are marked with no respawn
(K_GetWaypointIsShortcut(bestwaypoint) == false) && (K_GetWaypointIsEnabled(bestwaypoint) == true))
(K_GetWaypointIsSpawnpoint(bestwaypoint)) &&
(K_GetWaypointIsEnabled(bestwaypoint) == true))
{
size_t i = 0U;
waypoint_t *aimwaypoint = NULL;
player->starpostx = bestwaypoint->mobj->x >> FRACBITS;
player->starposty = bestwaypoint->mobj->y >> FRACBITS;
player->starpostz = bestwaypoint->mobj->z >> FRACBITS;
player->kartstuff[k_starpostflip] = (bestwaypoint->mobj->flags2 & MF2_OBJECTFLIP);
// starpostangle is to the first valid nextwaypoint for simplicity
// if we reach the last waypoint and it's still not valid, just use it anyway. Someone needs to fix
// their map!
for (i = 0U; i < bestwaypoint->numnextwaypoints; i++)
{
aimwaypoint = bestwaypoint->nextwaypoints[i];
if ((i == bestwaypoint->numnextwaypoints - 1U)
|| ((K_GetWaypointIsEnabled(aimwaypoint) == true)
&& (K_GetWaypointIsSpawnpoint(aimwaypoint) == true)))
{
player->starpostangle = R_PointToAngle2(
bestwaypoint->mobj->x, bestwaypoint->mobj->y, aimwaypoint->mobj->x, aimwaypoint->mobj->y);
break;
}
}
player->respawn.wp = bestwaypoint;
}
}
@ -6378,7 +5995,17 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
if ((player != NULL) && (player->mo != NULL))
{
waypoint_t *finishline = K_GetFinishLineWaypoint();
waypoint_t *nextwaypoint = K_GetPlayerNextWaypoint(player);
waypoint_t *nextwaypoint = NULL;
if (player->spectator)
{
// Don't update waypoints while spectating
nextwaypoint = finishline;
}
else
{
nextwaypoint = K_GetPlayerNextWaypoint(player);
}
if (nextwaypoint != NULL)
{
@ -6388,7 +6015,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
}
// nextwaypoint is now the waypoint that is in front of us
if (player->exiting)
if (player->exiting || player->spectator)
{
// Player has finished, we don't need to calculate this
player->distancetofinish = 0U;
@ -7000,7 +6627,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
player->pflags |= PF_ATTACKDOWN;
if (player && player->mo && player->mo->health > 0 && !player->spectator && !mapreset && leveltime > starttime
&& player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_squishedtimer] == 0 && player->kartstuff[k_respawn] == 0)
&& player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_squishedtimer] == 0 && (player->respawn.state == RESPAWNST_NONE))
{
// First, the really specific, finicky items that function without the item being directly in your item slot.
// Karma item dropping

View file

@ -27,8 +27,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
void K_KartPainEnergyFling(player_t *player);
void K_FlipFromObject(mobj_t *mo, mobj_t *master);
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
void K_DoIngameRespawn(player_t *player);
void K_RespawnChecker(player_t *player);
void K_SpawnDashDustRelease(player_t *player);
void K_KartMoveAnimation(player_t *player);
void K_KartPlayerHUDUpdate(player_t *player);
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);

736
src/k_respawn.c Normal file
View file

@ -0,0 +1,736 @@
// 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_respawn.c
/// \brief Respawning logic
#include "k_respawn.h"
#include "doomdef.h"
#include "d_player.h"
#include "k_kart.h"
#include "k_battle.h"
#include "g_game.h"
#include "p_local.h"
#include "p_tick.h"
#include "p_setup.h"
#include "r_main.h"
#include "s_sound.h"
#include "p_slopes.h"
#include "r_defs.h"
/*--------------------------------------------------
fixed_t K_RespawnOffset(player_t *player, boolean flip)
See header file for description.
--------------------------------------------------*/
fixed_t K_RespawnOffset(player_t *player, boolean flip)
{
fixed_t z = 0;
if (flip == true)
{
player->mo->flags2 |= MF2_OBJECTFLIP;
player->mo->eflags |= MFE_VERTICALFLIP;
z -= (128 * mapobjectscale) - (player->mo->height);
}
else
{
player->mo->flags2 &= ~MF2_OBJECTFLIP;
player->mo->eflags &= ~MFE_VERTICALFLIP;
z += (128 * mapobjectscale);
}
return z;
}
/*--------------------------------------------------
static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint)
Updates a player's respawn variables to go to the provided waypoint.
Input Arguments:-
player - Player to preform for.
waypoint - Waypoint to respawn to.
Return:-
None
--------------------------------------------------*/
static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint)
{
if (player == NULL || player->mo == NULL || P_MobjWasRemoved(player->mo))
{
return;
}
if (waypoint == NULL || waypoint->mobj == NULL || P_MobjWasRemoved(waypoint->mobj))
{
return;
}
player->respawn.pointx = waypoint->mobj->x;
player->respawn.pointy = waypoint->mobj->y;
player->respawn.pointz = waypoint->mobj->z;
player->respawn.flip = (waypoint->mobj->flags2 & MF2_OBJECTFLIP);
player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip);
}
/*--------------------------------------------------
void K_DoIngameRespawn(player_t *player)
See header file for description.
--------------------------------------------------*/
void K_DoIngameRespawn(player_t *player)
{
if (!player->mo || P_MobjWasRemoved(player->mo))
{
return;
}
if (player->respawn.state != RESPAWNST_NONE)
{
return;
}
if (leveltime <= starttime)
{
return;
}
player->kartstuff[k_ringboost] = 0;
player->kartstuff[k_driftboost] = 0;
player->kartstuff[k_drift] = 0;
player->kartstuff[k_driftcharge] = 0;
player->kartstuff[k_pogospring] = 0;
// Set up respawn position if invalid
if (player->respawn.wp != NULL)
{
const UINT32 dist = RESPAWN_DIST + (player->airtime * 48);
player->respawn.distanceleft = (dist * mapobjectscale) / FRACUNIT;
K_RespawnAtWaypoint(player, player->respawn.wp);
}
else
{
UINT32 bestdist = UINT32_MAX;
mapthing_t *beststart = NULL;
UINT8 numstarts = 0;
if (G_RaceGametype())
{
numstarts = numcoopstarts;
}
else if (G_BattleGametype())
{
numstarts = numdmstarts;
}
if (numstarts > 0)
{
UINT8 i = 0;
for (i = 0; i < numstarts; i++)
{
UINT32 dist = UINT32_MAX;
mapthing_t *checkstart = NULL;
if (G_RaceGametype())
{
checkstart = playerstarts[i];
}
else if (G_BattleGametype())
{
checkstart = deathmatchstarts[i];
}
else
{
break;
}
dist = (UINT32)P_AproxDistance((player->mo->x >> FRACBITS) - checkstart->x,
(player->mo->y >> FRACBITS) - checkstart->y);
if (dist < bestdist)
{
beststart = checkstart;
bestdist = dist;
}
}
}
if (beststart == NULL)
{
CONS_Alert(CONS_WARNING, "No respawn points!\n");
player->respawn.pointx = 0;
player->respawn.pointy = 0;
player->respawn.pointz = 0;
player->respawn.flip = false;
}
else
{
sector_t *s;
fixed_t z = (beststart->options >> ZSHIFT) * FRACUNIT;
player->respawn.pointx = beststart->x << FRACBITS;
player->respawn.pointy = beststart->y << FRACBITS;
s = R_PointInSubsector(beststart->x << FRACBITS, beststart->y << FRACBITS)->sector;
player->respawn.flip = (beststart->options & MTF_OBJECTFLIP);
if (player->respawn.flip == true)
{
player->respawn.pointz = (
#ifdef ESLOPE
s->c_slope ? P_GetZAt(s->c_slope, player->respawn.pointx, player->respawn.pointy) :
#endif
s->ceilingheight);
if (z != 0)
{
player->respawn.pointz -= z;
}
}
else
{
player->respawn.pointz = (
#ifdef ESLOPE
s->f_slope ? P_GetZAt(s->f_slope, player->respawn.pointx, player->respawn.pointy) :
#endif
s->floorheight);
if (z)
{
player->respawn.pointz += z;
}
}
}
player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip);
player->respawn.distanceleft = 0;
}
player->respawn.timer = RESPAWN_TIME;
player->respawn.state = RESPAWNST_MOVE;
}
/*--------------------------------------------------
static size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint)
Returns the index for the next respawn waypoint.
Input Arguments:-
waypoint - Waypoint to look after.
Return:-
An table index for waypoint_t -> nextwaypoints.
--------------------------------------------------*/
static size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint)
{
size_t i = 0U;
size_t newwaypoint = SIZE_MAX;
// Set to the first valid nextwaypoint, for simplicity's sake.
// If we reach the last waypoint and it's still not valid, just use it anyway. Someone needs to fix their map!
for (i = 0U; i < waypoint->numnextwaypoints; i++)
{
newwaypoint = i;
if ((i == waypoint->numnextwaypoints - 1U)
|| ((K_GetWaypointIsEnabled(waypoint->nextwaypoints[newwaypoint]) == true)
&& (K_GetWaypointIsSpawnpoint(waypoint->nextwaypoints[newwaypoint]) == true)))
{
break;
}
}
return newwaypoint;
}
/*--------------------------------------------------
static void K_MovePlayerToRespawnPoint(player_t *player)
Handles the movement state of the respawn animation.
Input Arguments:-
player - Player to preform for.
Return:-
None
--------------------------------------------------*/
static void K_MovePlayerToRespawnPoint(player_t *player)
{
const fixed_t realstepamt = (64 * mapobjectscale);
fixed_t stepamt = realstepamt;
vertex_t dest, step, laser;
angle_t stepha, stepva;
fixed_t dist, fulldist;
UINT8 lasersteps = 4;
UINT32 laserdist;
waypoint_t *laserwp;
boolean laserflip;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
player->powers[pw_flashing] = 2;
player->powers[pw_nocontrol] = 2;
if (leveltime % 8 == 0 && !mapreset)
{
S_StartSound(player->mo, sfx_s3kcas);
}
dest.x = player->respawn.pointx;
dest.y = player->respawn.pointy;
dest.z = player->respawn.pointz;
dist = P_AproxDistance(P_AproxDistance(
player->mo->x - dest.x,
player->mo->y - dest.y),
player->mo->z - dest.z
);
if (dist <= stepamt)
{
// Reduce by the amount we needed to get to this waypoint
stepamt -= dist;
// We've reached the destination point,
P_UnsetThingPosition(player->mo);
player->mo->x = dest.x;
player->mo->y = dest.y;
player->mo->z = dest.z;
P_SetThingPosition(player->mo);
// Find the next waypoint to head towards
if (player->respawn.wp != NULL)
{
size_t nwp = K_NextRespawnWaypointIndex(player->respawn.wp);
if (nwp == SIZE_MAX)
{
player->respawn.state = RESPAWNST_DROP;
return;
}
// Set angle, regardless of if we're done or not
player->frameangle = R_PointToAngle2(
player->mo->x, player->mo->y,
dest.x, dest.y
);
if ((player->respawn.distanceleft == 0)
&& (K_GetWaypointIsSpawnpoint(player->respawn.wp) == true))
{
// Alright buddy, that's the end of the ride.
player->respawn.state = RESPAWNST_DROP;
return;
}
if (player->respawn.distanceleft > player->respawn.wp->nextwaypointdistances[nwp])
{
player->respawn.distanceleft -= player->respawn.wp->nextwaypointdistances[nwp];
}
else
{
player->respawn.distanceleft = 0;
}
player->respawn.wp = player->respawn.wp->nextwaypoints[nwp];
K_RespawnAtWaypoint(player, player->respawn.wp);
dest.x = player->respawn.pointx;
dest.y = player->respawn.pointy;
dest.z = player->respawn.pointz;
}
else
{
// We can now drop!
player->respawn.state = RESPAWNST_DROP;
return;
}
}
stepha = R_PointToAngle2(
player->mo->x, player->mo->y,
dest.x, dest.y
);
stepva = R_PointToAngle2(
0, player->mo->z,
P_AproxDistance(player->mo->x - dest.x, player->mo->y - dest.y), dest.z
);
// Move toward the respawn point
player->frameangle = stepha;
step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
step.z = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*stepamt);
if (stepamt > 0)
{
player->mo->momx = step.x;
player->mo->momy = step.y;
player->mo->momz = step.z;
}
// NOW THEN, time for loads of dumb duplication!
// "Emulate" the rest of the path, that way we can spawn a particle a certain distance ahead of you.
if (stepamt != realstepamt)
{
// Reset back to default
stepamt = realstepamt;
step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
step.z = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*stepamt);
}
laserdist = player->respawn.distanceleft;
laserwp = player->respawn.wp;
laserflip = player->respawn.flip;
laser.x = player->mo->x + (step.x / 2);
laser.y = player->mo->y + (step.y / 2);
laser.z = player->mo->z + (step.z / 2);
dist = P_AproxDistance(P_AproxDistance(
laser.x - dest.x,
laser.y - dest.y),
laser.z - dest.z
);
fulldist = dist + (laserdist * FRACUNIT);
while (lasersteps > 0)
{
if (fulldist <= stepamt)
{
break;
}
if (dist <= stepamt)
{
size_t lnwp;
laser.x = dest.x;
laser.y = dest.y;
laser.z = dest.z;
if (laserdist <= 0)
{
break;
}
lnwp = K_NextRespawnWaypointIndex(laserwp);
if (lnwp == SIZE_MAX)
{
break;
}
if (laserdist > laserwp->nextwaypointdistances[lnwp])
{
laserdist -= laserwp->nextwaypointdistances[lnwp];
}
else
{
laserdist = 0;
}
laserwp = laserwp->nextwaypoints[lnwp];
dest.x = laserwp->mobj->x;
dest.y = laserwp->mobj->y;
dest.z = laserwp->mobj->z;
laserflip = (laserwp->mobj->flags2 & MF2_OBJECTFLIP);
if (laserflip == true)
{
dest.z -= (128 * mapobjectscale) - (player->mo->height);
}
else
{
dest.z += (128 * mapobjectscale);
}
stepamt -= dist;
stepha = R_PointToAngle2(laser.x, laser.y, dest.x, dest.y);
stepva = R_PointToAngle2(0, laser.z, P_AproxDistance(laser.x - dest.x, laser.y - dest.y), dest.z);
step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
step.z = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*stepamt);
}
else if (stepamt != realstepamt)
{
// Reset back to default
stepamt = realstepamt;
step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
step.z = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*stepamt);
}
if (stepamt > 0)
{
laser.x += step.x;
laser.y += step.y;
laser.z += step.z;
}
dist = P_AproxDistance(P_AproxDistance(
laser.x - dest.x,
laser.y - dest.y),
laser.z - dest.z
);
fulldist = dist + (laserdist * FRACUNIT);
lasersteps--;
}
if (lasersteps == 0) // Don't spawn them beyond the respawn point.
{
mobj_t *lasermo = P_SpawnMobj(laser.x, laser.y, laser.z + (player->mo->height / 2), MT_DEZLASER);
if (lasermo && !P_MobjWasRemoved(lasermo))
{
P_SetMobjState(lasermo, S_DEZLASER_TRAIL1);
if (player->mo->eflags & MFE_VERTICALFLIP)
{
lasermo->eflags |= MFE_VERTICALFLIP;
}
P_SetTarget(&lasermo->target, player->mo);
lasermo->angle = stepha + ANGLE_90;
P_SetScale(lasermo, (lasermo->destscale = player->mo->scale));
}
}
}
/*--------------------------------------------------
static void K_HandleDropDash(player_t *player)
Handles the visuals for the waiting period,
before you're allowed to Drop Dash.
Input Arguments:-
player - Player to preform for.
Return:-
None
--------------------------------------------------*/
static void K_DropDashWait(player_t *player)
{
player->respawn.timer--;
if (leveltime % 8 == 0)
{
const UINT8 ns = 8;
const angle_t sidediff = FixedAngle((360 / ns) * FRACUNIT);
UINT8 i;
if (!mapreset)
{
S_StartSound(player->mo, sfx_s3kcas);
}
for (i = 0; i < ns; i++)
{
const angle_t newangle = sidediff * i;
vertex_t spawn;
mobj_t *laser;
spawn.x = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31 * player->mo->scale);
spawn.y = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31 * player->mo->scale);
if (player->mo->eflags & MFE_VERTICALFLIP)
{
spawn.z = player->mo->z + player->mo->height;
}
else
{
spawn.z = player->mo->z;
}
laser = P_SpawnMobj(spawn.x, spawn.y, spawn.z, MT_DEZLASER);
if (laser && !P_MobjWasRemoved(laser))
{
if (player->mo->eflags & MFE_VERTICALFLIP)
{
laser->eflags |= MFE_VERTICALFLIP;
}
P_SetTarget(&laser->target, player->mo);
laser->angle = newangle + ANGLE_90;
laser->momz = (8 * player->mo->scale) * P_MobjFlip(player->mo);
P_SetScale(laser, (laser->destscale = player->mo->scale));
}
}
}
}
/*--------------------------------------------------
static void K_HandleDropDash(player_t *player)
Handles input for the Drop Dash maneuver.
Input Arguments:-
player - Player to preform for.
Return:-
None
--------------------------------------------------*/
static void K_HandleDropDash(player_t *player)
{
ticcmd_t *cmd = &player->cmd;
if (player->kartstuff[k_growshrinktimer] < 0)
{
player->mo->scalespeed = mapobjectscale/TICRATE;
player->mo->destscale = (6*mapobjectscale)/8;
if (cv_kartdebugshrink.value && !modeattacking && !player->bot)
{
player->mo->destscale = (6*player->mo->destscale)/8;
}
}
if (!P_IsObjectOnGround(player->mo))
{
if (mapreset)
{
return;
}
player->powers[pw_flashing] = K_GetKartFlashing(player);
// The old behavior was stupid and prone to accidental usage.
// Let's rip off Mania instead, and turn this into a Drop Dash!
if ((cmd->buttons & BT_ACCELERATE) && !player->kartstuff[k_spinouttimer]) // Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway)
{
player->respawn.dropdash++;
}
else
{
player->respawn.dropdash = 0;
}
if (player->respawn.dropdash == TICRATE/4)
{
S_StartSound(player->mo, sfx_ddash);
}
if ((player->respawn.dropdash >= TICRATE/4) && (player->respawn.dropdash & 1))
{
player->mo->colorized = true;
}
else
{
player->mo->colorized = false;
}
}
else
{
if ((cmd->buttons & BT_ACCELERATE) && (player->respawn.dropdash >= TICRATE/4))
{
S_StartSound(player->mo, sfx_s23c);
player->kartstuff[k_startboost] = 50;
K_SpawnDashDustRelease(player);
}
player->mo->colorized = false;
player->respawn.dropdash = 0;
//P_PlayRinglossSound(player->mo);
P_PlayerRingBurst(player, 3);
if (G_BattleGametype())
{
if (player->kartstuff[k_bumper] > 0)
{
if (player->kartstuff[k_bumper] == 1)
{
mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!!
P_SetTarget(&karmahitbox->target, player->mo);
karmahitbox->destscale = player->mo->scale;
P_SetScale(karmahitbox, player->mo->scale);
CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]);
}
player->kartstuff[k_bumper]--;
if (K_IsPlayerWanted(player))
K_CalculateBattleWanted();
}
if (!player->kartstuff[k_bumper])
{
player->kartstuff[k_comebacktimer] = comebacktime;
if (player->kartstuff[k_comebackmode] == 2)
{
mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE);
S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound);
player->kartstuff[k_comebackmode] = 0;
}
}
K_CheckBumpers();
}
player->respawn.state = RESPAWNST_NONE;
}
}
/*--------------------------------------------------
void K_RespawnChecker(player_t *player)
See header file for description.
--------------------------------------------------*/
void K_RespawnChecker(player_t *player)
{
if (player->respawn.state == RESPAWNST_NONE)
{
return;
}
if (player->spectator)
{
player->respawn.state = RESPAWNST_NONE;
return;
}
switch (player->respawn.state)
{
case RESPAWNST_MOVE:
player->mo->momx = player->mo->momy = player->mo->momz = 0;
K_MovePlayerToRespawnPoint(player);
return;
case RESPAWNST_DROP:
player->mo->momx = player->mo->momy = 0;
if (player->respawn.timer > 0)
{
player->mo->momz = 0;
K_DropDashWait(player);
}
else
{
K_HandleDropDash(player);
}
return;
default:
player->respawn.state = RESPAWNST_NONE;
return;
}
}

71
src/k_respawn.h Normal file
View file

@ -0,0 +1,71 @@
// 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_respawn.h
/// \brief Respawning logic
#ifndef __K_RESPAWN__
#define __K_RESPAWN__
#include "k_waypoint.h"
#include "d_player.h"
#define RESPAWN_DIST 1024
#define RESPAWN_TIME 48
#define RESPAWNST_NONE 0
#define RESPAWNST_MOVE 1
#define RESPAWNST_DROP 2
/*--------------------------------------------------
fixed_t K_RespawnOffset(player_t *player, boolean flip);
Updates the player's flip flags, and returns a
Z offset for respawning.
Input Arguments:-
player - Player to preform this for.
flip - false for normal, true for gravity flip.
Return:-
Z position offset.
--------------------------------------------------*/
fixed_t K_RespawnOffset(player_t *player, boolean flip);
/*--------------------------------------------------
void K_DoIngameRespawn(player_t *player);
Starts the respawning animation for the specified player,
updating their respawn variables in preparation.
Input Arguments:-
player - Player to preform this for.
Return:-
None
--------------------------------------------------*/
void K_DoIngameRespawn(player_t *player);
/*--------------------------------------------------
void K_RespawnChecker(player_t *player);
Thinker for the respawning animation.
Input Arguments:-
player - Player to preform this for.
Return:-
None
--------------------------------------------------*/
void K_RespawnChecker(player_t *player);
#endif

View file

@ -216,6 +216,8 @@ static int player_get(lua_State *L)
LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF);
else if (fastcmp(field,"frameangle"))
lua_pushangle(L, plr->frameangle);
else if (fastcmp(field,"airtime"))
lua_pushinteger(L, plr->airtime);
else if (fastcmp(field,"pflags"))
lua_pushinteger(L, plr->pflags);
else if (fastcmp(field,"panim"))
@ -294,18 +296,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->weapondelay);
else if (fastcmp(field,"tossdelay"))
lua_pushinteger(L, plr->tossdelay);
else if (fastcmp(field,"starpostx"))
lua_pushinteger(L, plr->starpostx);
else if (fastcmp(field,"starposty"))
lua_pushinteger(L, plr->starposty);
else if (fastcmp(field,"starpostz"))
lua_pushinteger(L, plr->starpostz);
else if (fastcmp(field,"starpostnum"))
lua_pushinteger(L, plr->starpostnum);
else if (fastcmp(field,"starposttime"))
lua_pushinteger(L, plr->starposttime);
else if (fastcmp(field,"starpostangle"))
lua_pushangle(L, plr->starpostangle);
else if (fastcmp(field,"angle_pos"))
lua_pushangle(L, plr->angle_pos);
else if (fastcmp(field,"old_angle_pos"))
@ -483,6 +475,8 @@ static int player_set(lua_State *L)
return NOSET;
else if (fastcmp(field,"frameangle"))
plr->frameangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"airtime"))
plr->airtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"kartspeed"))
plr->kartspeed = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"kartweight"))
@ -544,18 +538,8 @@ static int player_set(lua_State *L)
plr->weapondelay = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"tossdelay"))
plr->tossdelay = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"starpostx"))
plr->starpostx = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"starposty"))
plr->starposty = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"starpostz"))
plr->starpostz = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"starpostnum"))
plr->starpostnum = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"starposttime"))
plr->starposttime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"starpostangle"))
plr->starpostangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"angle_pos"))
plr->angle_pos = luaL_checkangle(L, 3);
else if (fastcmp(field,"old_angle_pos"))

View file

@ -682,13 +682,11 @@ void Command_Savecheckpoint_f(void)
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
players[consoleplayer].starposttime = players[consoleplayer].realtime;
players[consoleplayer].starpostx = players[consoleplayer].mo->x>>FRACBITS;
players[consoleplayer].starposty = players[consoleplayer].mo->y>>FRACBITS;
players[consoleplayer].starpostz = players[consoleplayer].mo->floorz>>FRACBITS;
players[consoleplayer].starpostangle = players[consoleplayer].mo->angle;
players[consoleplayer].respawn.pointx = players[consoleplayer].mo->x;
players[consoleplayer].respawn.pointy = players[consoleplayer].mo->y;
players[consoleplayer].respawn.pointz = players[consoleplayer].mo->floorz;
CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].starpostx, players[consoleplayer].starposty, players[consoleplayer].starpostz);
CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].respawn.pointx, players[consoleplayer].respawn.pointy, players[consoleplayer].respawn.pointz);
}
// Like M_GetAllEmeralds() but for console devmode junkies.

View file

@ -26,6 +26,7 @@
#include "k_kart.h" // SRB2kart
#include "k_waypoint.h"
#include "k_battle.h"
#include "k_respawn.h"
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
@ -5636,10 +5637,8 @@ void A_MixUp(mobj_t *actor)
INT32 transspeed; //player speed
// Starpost stuff
INT16 starpostx, starposty, starpostz;
fixed_t starpostx, starposty, starpostz;
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
INT32 mflags2;
@ -5678,22 +5677,20 @@ void A_MixUp(mobj_t *actor)
z = players[one].mo->z;
angle = players[one].mo->angle;
starpostx = players[one].starpostx;
starposty = players[one].starposty;
starpostz = players[one].starpostz;
starpostangle = players[one].starpostangle;
starpostx = players[one].respawn.pointx;
starposty = players[one].respawn.pointy;
starpostz = players[one].respawn.pointz;
starpostnum = players[one].starpostnum;
starposttime = players[one].starposttime;
mflags2 = players[one].mo->flags2;
P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle,
players[two].starpostx, players[two].starposty, players[two].starpostz,
players[two].starpostnum, players[two].starposttime, players[two].starpostangle,
players[two].respawn.pointx, players[two].respawn.pointy, players[two].respawn.pointz,
players[two].starpostnum, 0, 0,
players[two].mo->flags2);
P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz,
starpostnum, starposttime, starpostangle,
starpostnum, 0, 0,
mflags2);
//flags set after mixup. Stupid P_ResetPlayer() takes away some of the flags we look for...
@ -5718,10 +5715,8 @@ void A_MixUp(mobj_t *actor)
INT32 transspeed[MAXPLAYERS]; //player speed
// Star post stuff
INT16 spposition[MAXPLAYERS][3];
fixed_t spposition[MAXPLAYERS][3];
INT32 starpostnum[MAXPLAYERS];
tic_t starposttime[MAXPLAYERS];
angle_t starpostangle[MAXPLAYERS];
INT32 flags2[MAXPLAYERS];
@ -5752,12 +5747,10 @@ void A_MixUp(mobj_t *actor)
transspeed[counter] = players[i].speed;
transtracer[counter] = players[i].mo->tracer;
spposition[counter][0] = players[i].starpostx;
spposition[counter][1] = players[i].starposty;
spposition[counter][2] = players[i].starpostz;
spposition[counter][0] = players[i].respawn.pointx;
spposition[counter][1] = players[i].respawn.pointy;
spposition[counter][2] = players[i].respawn.pointz;
starpostnum[counter] = players[i].starpostnum;
starposttime[counter] = players[i].starposttime;
starpostangle[counter] = players[i].starpostangle;
flags2[counter] = players[i].mo->flags2;
@ -5797,7 +5790,7 @@ void A_MixUp(mobj_t *actor)
P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom],
spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2],
starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom],
starpostnum[teleportfrom], 0, 0,
flags2[teleportfrom]);
//...flags after. same reasoning.
@ -8610,7 +8603,7 @@ void A_SPBChase(mobj_t *actor)
if (players[i].mo->health <= 0)
continue; // dead
if (players[i].kartstuff[k_respawn])
if (players[i].respawn.state != RESPAWNST_NONE)
continue;*/ // respawning
if (players[i].kartstuff[k_position] < bestrank)
@ -8787,7 +8780,7 @@ void A_SPBChase(mobj_t *actor)
actor->lastlook = -1; // Just make sure this is reset
if (!player || !player->mo || player->mo->health <= 0 || player->kartstuff[k_respawn])
if (!player || !player->mo || player->mo->health <= 0 || (player->respawn.state != RESPAWNST_NONE))
{
// No one there? Completely STOP.
actor->momx = actor->momy = actor->momz = 0;

View file

@ -1401,7 +1401,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Misc touchables //
// *************** //
case MT_STARPOST:
// SRB2kart: make sure the player will have enough checkpoints to touch
if (circuitmap && special->health - player->starpostnum > 1)
{
// blatant reuse of a variable that's normally unused in circuit
@ -1421,11 +1420,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->starpostnum >= special->health)
return; // Already hit this post
// Save the player's time and position.
player->starposttime = player->realtime; //this makes race mode's timers work correctly whilst not affecting sp -x
player->starpostnum = special->health;
//S_StartSound(toucher, special->info->painsound);
return;
case MT_FAKEMOBILE:

View file

@ -26,6 +26,7 @@
#include "w_wad.h"
#include "k_kart.h" // SRB2kart 011617
#include "k_collide.h"
#include "k_respawn.h"
#include "hu_stuff.h" // SRB2kart
#include "i_system.h" // SRB2kart
@ -2906,6 +2907,100 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
return true;
}
//
// PTR_GetSpecialLines
//
static boolean PTR_GetSpecialLines(intercept_t *in)
{
line_t *ld;
I_Assert(in->isaline);
ld = in->d.line;
if (!ld->backsector)
{
return true;
}
if (P_SpecialIsLinedefCrossType(ld->special))
{
add_spechit(ld);
}
return true;
}
//
// P_HitSpecialLines
// Finds all special lines in the provided path and tries to cross them.
// For zoom tubes and respawning, which noclip but need to cross finish lines.
//
void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_t momy)
{
fixed_t leadx, leady;
fixed_t trailx, traily;
line_t *ld = NULL;
INT32 side = 0, oldside = 0;
I_Assert(thing != NULL);
#ifdef PARANOIA
if (P_MobjWasRemoved(thing))
I_Error("Previously-removed Thing of type %u crashes P_CheckPosition!", thing->type);
#endif
// reset special lines
numspechitint = 0U;
numspechit = 0U;
// trace along the three leading corners
if (momx > 0)
{
leadx = x + thing->radius;
trailx = x - thing->radius;
}
else
{
leadx = x - thing->radius;
trailx = x + thing->radius;
}
if (momy > 0)
{
leady = y + thing->radius;
traily = y - thing->radius;
}
else
{
leady = y - thing->radius;
traily = y + thing->radius;
}
P_PathTraverse(leadx, leady, leadx + momx, leady + momy, PT_ADDLINES, PTR_GetSpecialLines);
P_PathTraverse(trailx, leady, trailx + momx, leady + momy, PT_ADDLINES, PTR_GetSpecialLines);
P_PathTraverse(leadx, traily, leadx + momx, traily + momy, PT_ADDLINES, PTR_GetSpecialLines);
spechitint_copyinto();
// remove any duplicates that may be in spechitint
spechitint_removedups();
// handle any of the special lines that were crossed
while (numspechitint--)
{
ld = &lines[spechitint[numspechitint]];
side = P_PointOnLineSide(x + momx, y + momy, ld);
oldside = P_PointOnLineSide(x, y, ld);
if (side != oldside)
{
if (ld->special)
{
P_CrossSpecialLine(ld, oldside, thing);
}
}
}
}
//
// P_ThingHeightClip
// Takes a valid thing and adjusts the thing->floorz,

View file

@ -53,6 +53,7 @@ void P_UnsetPrecipThingPosition(precipmobj_t *thing);
void P_SetPrecipitationThingPosition(precipmobj_t *thing);
void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y);
boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y);
void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_t momy);
extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
#ifdef ESLOPE

View file

@ -38,6 +38,7 @@
#include "k_kart.h"
#include "k_battle.h"
#include "k_color.h"
#include "k_respawn.h"
// protos.
//static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}};
@ -3745,8 +3746,10 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN;
// Zoom tube
if (mobj->tracer && mobj->tracer->type == MT_TUBEWAYPOINT)
if ((mobj->tracer && mobj->tracer->type == MT_TUBEWAYPOINT)
|| (mobj->player->respawn.state == RESPAWNST_MOVE))
{
P_HitSpecialLines(mobj, mobj->x, mobj->y, mobj->momx, mobj->momy);
P_UnsetThingPosition(mobj);
mobj->x += mobj->momx;
mobj->y += mobj->momy;
@ -11884,9 +11887,6 @@ void P_SpawnPlayer(INT32 playernum)
// Spawn with a pity shield if necessary.
//P_DoPityCheck(p);
if (p->kartstuff[k_respawn] != 0)
p->mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY;
if (G_BattleGametype()) // SRB2kart
{
mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + P_GetPlayerHeight(p)+16*FRACUNIT, MT_PLAYERARROW);
@ -12032,16 +12032,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
z = ceiling - mobjinfo[MT_PLAYER].height;
if (mthing->options >> ZSHIFT)
z -= ((mthing->options >> ZSHIFT) << FRACBITS);
if (p->kartstuff[k_respawn])
z -= 128*mapobjectscale;
}
else
{
z = floor;
if (mthing->options >> ZSHIFT)
z += ((mthing->options >> ZSHIFT) << FRACBITS);
if (p->kartstuff[k_respawn])
z += 128*mapobjectscale;
}
if (mthing->options & MTF_OBJECTFLIP) // flip the player!
@ -12053,6 +12049,11 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
else
z = floor;
if (p->respawn.state != RESPAWNST_NONE)
{
z += K_RespawnOffset(p, (mthing->options & MTF_OBJECTFLIP));
}
if (z < floor)
z = floor;
else if (z > ceiling - mobjinfo[MT_PLAYER].height)
@ -12085,9 +12086,11 @@ void P_MovePlayerToStarpost(INT32 playernum)
mobj_t *mobj = p->mo;
I_Assert(mobj != NULL);
K_DoIngameRespawn(p);
P_UnsetThingPosition(mobj);
mobj->x = p->starpostx << FRACBITS;
mobj->y = p->starposty << FRACBITS;
mobj->x = p->respawn.pointx;
mobj->y = p->respawn.pointy;
P_SetThingPosition(mobj);
sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
@ -12102,12 +12105,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
#endif
sector->ceilingheight;
if (mobj->player->kartstuff[k_starpostflip])
z = (p->starpostz<<FRACBITS) - (128 * mapobjectscale) - mobj->height;
else
z = (p->starpostz<<FRACBITS) + (128 * mapobjectscale);
mobj->player->kartstuff[k_starpostflip] = 0;
z = p->respawn.pointz;
if (z < floor)
z = floor;
@ -12121,12 +12119,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
if (mobj->z == mobj->floorz)
mobj->eflags |= MFE_ONGROUND;
mobj->angle = p->starpostangle;
P_AfterPlayerSpawn(playernum);
//if (!(netgame || multiplayer))
// leveltime = p->starposttime;
}
#define MAXHUNTEMERALDS 64

View file

@ -125,10 +125,6 @@ static void P_NetArchivePlayers(void)
for (j = 0; j < NUMPOWERS; j++)
WRITEUINT16(save_p, players[i].powers[j]);
for (j = 0; j < NUMKARTSTUFF; j++)
WRITEINT32(save_p, players[i].kartstuff[j]);
WRITEANGLE(save_p, players[i].frameangle);
WRITEUINT8(save_p, players[i].playerstate);
WRITEUINT32(save_p, players[i].pflags);
@ -172,6 +168,7 @@ static void P_NetArchivePlayers(void)
WRITEINT16(save_p, players[i].totalring);
WRITEUINT32(save_p, players[i].realtime);
WRITEUINT8(save_p, players[i].laps);
WRITEINT32(save_p, players[i].starpostnum);
////////////////////
// CTF Mode Stuff //
@ -182,13 +179,6 @@ static void P_NetArchivePlayers(void)
WRITEINT32(save_p, players[i].weapondelay);
WRITEINT32(save_p, players[i].tossdelay);
WRITEUINT32(save_p, players[i].starposttime);
WRITEINT16(save_p, players[i].starpostx);
WRITEINT16(save_p, players[i].starposty);
WRITEINT16(save_p, players[i].starpostz);
WRITEINT32(save_p, players[i].starpostnum);
WRITEANGLE(save_p, players[i].starpostangle);
WRITEANGLE(save_p, players[i].angle_pos);
WRITEANGLE(save_p, players[i].old_angle_pos);
@ -260,15 +250,32 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].kartweight);
//
for (j = 0; j < NUMKARTSTUFF; j++)
WRITEINT32(save_p, players[i].kartstuff[j]);
for (j = 0; j < MAXPREDICTTICS; j++)
{
WRITEINT16(save_p, players[i].lturn_max[j]);
WRITEINT16(save_p, players[i].rturn_max[j]);
}
WRITEANGLE(save_p, players[i].frameangle);
WRITEUINT32(save_p, players[i].distancetofinish);
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].nextwaypoint));
WRITEUINT32(save_p, players[i].airtime);
// respawnvars_t
WRITEUINT8(save_p, players[i].respawn.state);
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp));
WRITEFIXED(save_p, players[i].respawn.pointx);
WRITEFIXED(save_p, players[i].respawn.pointy);
WRITEFIXED(save_p, players[i].respawn.pointz);
WRITEUINT8(save_p, players[i].respawn.flip);
WRITEUINT32(save_p, players[i].respawn.timer);
WRITEUINT32(save_p, players[i].respawn.distanceleft);
WRITEUINT32(save_p, players[i].respawn.dropdash);
// botvars_t
WRITEUINT8(save_p, players[i].botvars.difficulty);
WRITEUINT32(save_p, players[i].botvars.itemdelay);
WRITEUINT32(save_p, players[i].botvars.itemconfirm);
@ -310,10 +317,6 @@ static void P_NetUnArchivePlayers(void)
for (j = 0; j < NUMPOWERS; j++)
players[i].powers[j] = READUINT16(save_p);
for (j = 0; j < NUMKARTSTUFF; j++)
players[i].kartstuff[j] = READINT32(save_p);
players[i].frameangle = READANGLE(save_p);
players[i].playerstate = READUINT8(save_p);
players[i].pflags = READUINT32(save_p);
@ -357,6 +360,7 @@ static void P_NetUnArchivePlayers(void)
players[i].totalring = READINT16(save_p); // Total number of rings obtained for Race Mode
players[i].realtime = READUINT32(save_p); // integer replacement for leveltime
players[i].laps = READUINT8(save_p); // Number of laps (optional)
players[i].starpostnum = READINT32(save_p);
////////////////////
// CTF Mode Stuff //
@ -367,13 +371,6 @@ static void P_NetUnArchivePlayers(void)
players[i].weapondelay = READINT32(save_p);
players[i].tossdelay = READINT32(save_p);
players[i].starposttime = READUINT32(save_p);
players[i].starpostx = READINT16(save_p);
players[i].starposty = READINT16(save_p);
players[i].starpostz = READINT16(save_p);
players[i].starpostnum = READINT32(save_p);
players[i].starpostangle = READANGLE(save_p);
players[i].angle_pos = READANGLE(save_p);
players[i].old_angle_pos = READANGLE(save_p);
@ -436,15 +433,32 @@ static void P_NetUnArchivePlayers(void)
players[i].kartweight = READUINT8(save_p);
//
for (j = 0; j < NUMKARTSTUFF; j++)
players[i].kartstuff[j] = READINT32(save_p);
for (j = 0; j < MAXPREDICTTICS; j++)
{
players[i].lturn_max[j] = READINT16(save_p);
players[i].rturn_max[j] = READINT16(save_p);
}
players[i].frameangle = READANGLE(save_p);
players[i].distancetofinish = READUINT32(save_p);
players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save_p);
players[i].airtime = READUINT32(save_p);
// respawnvars_t
players[i].respawn.state = READUINT8(save_p);
players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p);
players[i].respawn.pointx = READFIXED(save_p);
players[i].respawn.pointy = READFIXED(save_p);
players[i].respawn.pointz = READFIXED(save_p);
players[i].respawn.flip = (boolean)READUINT8(save_p);
players[i].respawn.timer = READUINT32(save_p);
players[i].respawn.distanceleft = READUINT32(save_p);
players[i].respawn.dropdash = READUINT32(save_p);
// botvars_t
players[i].botvars.difficulty = READUINT8(save_p);
players[i].botvars.itemdelay = READUINT32(save_p);
players[i].botvars.itemconfirm = READUINT32(save_p);
@ -3110,35 +3124,37 @@ static void P_RelinkPointers(void)
if (!(mobj->itnext = P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->capsule)
if (mobj->player)
{
if (mobj->player->capsule)
{
temp = (UINT32)(size_t)mobj->player->capsule;
mobj->player->capsule = NULL;
if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->axis1)
if (mobj->player->axis1)
{
temp = (UINT32)(size_t)mobj->player->axis1;
mobj->player->axis1 = NULL;
if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->axis2)
if (mobj->player->axis2)
{
temp = (UINT32)(size_t)mobj->player->axis2;
mobj->player->axis2 = NULL;
if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->awayviewmobj)
if (mobj->player->awayviewmobj)
{
temp = (UINT32)(size_t)mobj->player->awayviewmobj;
mobj->player->awayviewmobj = NULL;
if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type);
}
if (mobj->player && mobj->player->nextwaypoint)
if (mobj->player->nextwaypoint)
{
temp = (UINT32)(size_t)mobj->player->nextwaypoint;
mobj->player->nextwaypoint = K_GetWaypointFromIndex(temp);
@ -3147,6 +3163,16 @@ static void P_RelinkPointers(void)
CONS_Debug(DBG_GAMELOGIC, "nextwaypoint not found on %d\n", mobj->type);
}
}
if (mobj->player->respawn.wp)
{
temp = (UINT32)(size_t)mobj->player->respawn.wp;
mobj->player->respawn.wp = K_GetWaypointFromIndex(temp);
if (mobj->player->respawn.wp == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "respawn.wp not found on %d\n", mobj->type);
}
}
}
}
}
}

View file

@ -3256,13 +3256,7 @@ boolean P_SetupLevel(boolean skipprecip)
else // gametype is GT_COOP or GT_RACE
{
players[i].mo = NULL;
if (players[i].starposttime)
{
G_SpawnPlayer(i, true);
}
else
G_SpawnPlayer(i, false);
G_SpawnPlayer(i, (players[i].starpostnum != 0));
}
}

View file

@ -37,6 +37,7 @@
#include "k_kart.h" // SRB2kart
#include "console.h" // CON_LogMessage
#include "k_respawn.h"
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
@ -2111,7 +2112,6 @@ static void K_HandleLapIncrement(player_t *player)
curlap = 0;
}
player->starposttime = player->realtime;
player->starpostnum = 0;
if (P_IsDisplayPlayer(player))

View file

@ -38,6 +38,9 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP;
UINT8 i;
(void)starposttime;
(void)starpostangle;
// the move is ok,
// so link the thing into its new position
P_UnsetThingPosition(thing);
@ -92,11 +95,9 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
thing->player->speed = 0;
// Starpost information
thing->player->starpostx = starpostx;
thing->player->starposty = starposty;
thing->player->starpostz = starpostz;
thing->player->starposttime = starposttime;
thing->player->starpostangle = starpostangle;
thing->player->respawn.pointx = starpostx;
thing->player->respawn.pointy = starposty;
thing->player->respawn.pointz = starpostz;
thing->player->starpostnum = starpostnum;
P_ResetPlayer(thing->player);

View file

@ -47,6 +47,7 @@
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
#include "k_kart.h"
#include "console.h" // CON_LogMessage
#include "k_respawn.h"
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
@ -5775,7 +5776,7 @@ static void P_MovePlayer(player_t *player)
// Kart: store the current turn range for later use
if ((player->mo && player->speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (player->kartstuff[k_respawn]) // Respawning
|| (player->respawn.state != RESPAWNST_NONE) // Respawning
|| (player->spectator || objectplacing)) // Not a physical player
{
player->lturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, KART_FULLTURN)+1;
@ -8430,16 +8431,6 @@ void P_PlayerThink(player_t *player)
player->awayviewtics = 0; // reset to zero
}
/*
if (player->pflags & PF_GLIDING)
{
if (player->panim != PA_ABILITY)
P_SetPlayerMobjState(player->mo, S_PLAY_ABL1);
}
else if ((player->pflags & PF_JUMPED) && !player->powers[pw_super] && player->panim != PA_ROLL && player->charability2 == CA2_SPINDASH)
P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);
*/
if (player->flashcount)
player->flashcount--;
@ -8452,21 +8443,33 @@ void P_PlayerThink(player_t *player)
// The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1.
}
// Track airtime
if (P_IsObjectOnGround(player->mo))
{
player->airtime = 0;
}
else
{
player->airtime++;
}
cmd = &player->cmd;
// SRB2kart
// Save the dir the player is holding
// to allow items to be thrown forward or backward.
if (cmd->buttons & BT_FORWARD)
{
player->kartstuff[k_throwdir] = 1;
}
else if (cmd->buttons & BT_BACKWARD)
{
player->kartstuff[k_throwdir] = -1;
}
else
{
player->kartstuff[k_throwdir] = 0;
// Add some extra randomization.
if (cmd->forwardmove)
P_RandomFixed();
}
#ifdef PARANOIA
if (player->playerstate == PST_REBORN)
@ -8600,15 +8603,9 @@ void P_PlayerThink(player_t *player)
// SRB2kart 010217
if (leveltime < starttime)
player->powers[pw_nocontrol] = 2;
/*
if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE)
{
cmd->buttons &= BT_BRAKE; // Remove all buttons except BT_BRAKE
cmd->forwardmove = 0;
cmd->sidemove = 0;
player->powers[pw_nocontrol] = 2;
}
*/
// Synchronizes the "real" amount of time spent in the level.
if (!player->exiting)
@ -8677,19 +8674,34 @@ void P_PlayerThink(player_t *player)
player->linkcount = 0;
}
// Move around.
if (player->respawn.state != RESPAWNST_NONE)
{
K_RespawnChecker(player);
player->rmomx = player->rmomy = 0;
if (player->respawn.state == RESPAWNST_DROP)
{
// Allows some turning
P_MovePlayer(player);
}
}
else if (player->mo->reactiontime)
{
// Reactiontime is used to prevent movement
// for a bit after a teleport.
if (player->mo->reactiontime)
player->mo->reactiontime--;
}
else if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT)
{
P_DoZoomTube(player);
player->rmomx = player->rmomy = 0; // no actual momentum from your controls
player->rmomx = player->rmomy = 0;
P_ResetScore(player);
}
else
{
// Move around.
P_MovePlayer(player);
}
if (!player->mo)
return; // P_MovePlayer removed player->mo.
@ -8866,7 +8878,7 @@ void P_PlayerThink(player_t *player)
if (!(//player->pflags & PF_NIGHTSMODE ||
player->kartstuff[k_hyudorotimer] // SRB2kart - fixes Hyudoro not flashing when it should.
|| player->kartstuff[k_growshrinktimer] > 0 // Grow doesn't flash either.
|| player->kartstuff[k_respawn] // Respawn timer (for drop dash effect)
|| (player->respawn.state != RESPAWNST_NONE) // Respawn timer (for drop dash effect)
|| (player->pflags & PF_TIMEOVER) // NO CONTEST explosion
|| (G_BattleGametype() && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer])
|| leveltime < starttime)) // Level intro