mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Implement lives system
Lose a life & restart the current race if you place below the top half. Lose all of your lives, and you get kicked to the title screen.
This commit is contained in:
parent
63797b35f7
commit
fa5fccffc5
16 changed files with 303 additions and 219 deletions
|
|
@ -580,6 +580,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
|||
// Score is resynched in the rspfirm resync packet
|
||||
rsp->health = 0; // resynched with mo health
|
||||
rsp->lives = players[i].lives;
|
||||
rsp->lostlife = players[i].lostlife;
|
||||
rsp->continues = players[i].continues;
|
||||
rsp->scoreadd = players[i].scoreadd;
|
||||
rsp->xtralife = players[i].xtralife;
|
||||
|
|
@ -710,6 +711,7 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
// Score is resynched in the rspfirm resync packet
|
||||
players[i].health = rsp->health;
|
||||
players[i].lives = rsp->lives;
|
||||
players[i].lostlife = rsp->lostlife;
|
||||
players[i].continues = rsp->continues;
|
||||
players[i].scoreadd = rsp->scoreadd;
|
||||
players[i].xtralife = rsp->xtralife;
|
||||
|
|
|
|||
|
|
@ -219,6 +219,7 @@ typedef struct
|
|||
// Score is resynched in the confirm resync packet
|
||||
INT32 health;
|
||||
SINT8 lives;
|
||||
boolean lostlife;
|
||||
SINT8 continues;
|
||||
UINT8 scoreadd;
|
||||
SINT8 xtralife;
|
||||
|
|
|
|||
|
|
@ -5710,14 +5710,14 @@ void Command_ExitGame_f(void)
|
|||
|
||||
void Command_Retry_f(void)
|
||||
{
|
||||
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING))
|
||||
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
|
||||
{
|
||||
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
|
||||
else if (netgame || multiplayer)
|
||||
CONS_Printf(M_GetText("This only works in single player.\n"));
|
||||
/*else if (!&players[consoleplayer] || players[consoleplayer].lives <= 1)
|
||||
CONS_Printf(M_GetText("You can't retry without any lives remaining!\n"));
|
||||
else if (G_IsSpecialStage(gamemap))
|
||||
CONS_Printf(M_GetText("You can't retry special stages!\n"));*/
|
||||
}
|
||||
else if (netgame || grandprixinfo.roundnum == 0)
|
||||
{
|
||||
CONS_Printf(M_GetText("This only works in Grand Prix.\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
M_ClearMenus(true);
|
||||
|
|
|
|||
|
|
@ -506,6 +506,7 @@ typedef struct player_s
|
|||
UINT32 charflags; // Extra abilities/settings for skins (combinable stuff)
|
||||
// See SF_ flags
|
||||
SINT8 lives;
|
||||
boolean lostlife;
|
||||
SINT8 continues; // continues that player has acquired
|
||||
|
||||
SINT8 xtralife; // Ring Extra Life counter
|
||||
|
|
|
|||
130
src/g_game.c
130
src/g_game.c
|
|
@ -2354,15 +2354,17 @@ void G_Ticker(boolean run)
|
|||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
// Or, alternatively, retry.
|
||||
if (!(netgame || multiplayer) && G_GetRetryFlag())
|
||||
if (G_GetRetryFlag())
|
||||
{
|
||||
G_ClearRetryFlag();
|
||||
|
||||
// Costs a life to retry ... unless the player in question is dead already.
|
||||
/*if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE)
|
||||
players[consoleplayer].lives -= 1;
|
||||
|
||||
G_DoReborn(consoleplayer);*/
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
K_PlayerLoseLife(&players[i]);
|
||||
}
|
||||
}
|
||||
|
||||
D_MapChange(gamemap, gametype, (cv_kartencore.value == 1), true, 1, false, false);
|
||||
}
|
||||
|
|
@ -2569,6 +2571,7 @@ void G_PlayerReborn(INT32 player)
|
|||
player_t *p;
|
||||
INT32 score, marescore;
|
||||
INT32 lives;
|
||||
boolean lostlife;
|
||||
INT32 continues;
|
||||
// SRB2kart
|
||||
UINT8 kartspeed;
|
||||
|
|
@ -2613,6 +2616,7 @@ void G_PlayerReborn(INT32 player)
|
|||
score = players[player].score;
|
||||
marescore = players[player].marescore;
|
||||
lives = players[player].lives;
|
||||
lostlife = players[player].lostlife;
|
||||
continues = players[player].continues;
|
||||
ctfteam = players[player].ctfteam;
|
||||
exiting = players[player].exiting;
|
||||
|
|
@ -2697,6 +2701,7 @@ void G_PlayerReborn(INT32 player)
|
|||
p->score = score;
|
||||
p->marescore = marescore;
|
||||
p->lives = lives;
|
||||
p->lostlife = lostlife;
|
||||
p->continues = continues;
|
||||
p->pflags = pflags;
|
||||
p->ctfteam = ctfteam;
|
||||
|
|
@ -3217,6 +3222,47 @@ void G_ExitLevel(void)
|
|||
{
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
if (grandprixinfo.roundnum > 0 && grandprixinfo.wonround != true)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
// You didn't win...
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator && !players[i].bot)
|
||||
{
|
||||
if (players[i].lives > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
{
|
||||
// GAME OVER, try again from the start!
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
; // restart cup here if we do online GP
|
||||
}
|
||||
else
|
||||
{
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Go redo this course.
|
||||
G_SetRetryFlag();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gameaction = ga_completed;
|
||||
lastdraw = true;
|
||||
|
||||
|
|
@ -3292,18 +3338,15 @@ boolean G_IsSpecialStage(INT32 mapnum)
|
|||
//
|
||||
boolean G_GametypeUsesLives(void)
|
||||
{
|
||||
// SRB2kart NEEDS no lives
|
||||
#if 0
|
||||
// Coop, Competitive
|
||||
if ((gametype == GT_COOP || gametype == GT_COMPETITION)
|
||||
&& !modeattacking // No lives in Time Attack
|
||||
//&& !G_IsSpecialStage(gamemap)
|
||||
&& !(maptol & TOL_NIGHTS)) // No lives in NiGHTS
|
||||
if ((grandprixinfo.roundnum > 0) // In Grand Prix
|
||||
&& (gametype == GT_RACE) // NOT in bonus round
|
||||
&& !(modeattacking) // NOT in Record Attack
|
||||
&& !G_IsSpecialStage(gamemap)) // NOT in special stage
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -4570,43 +4613,42 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
|
|||
if (!demo.playback && !netgame) // Netgame sets random seed elsewhere, demo playback sets seed just before us!
|
||||
P_SetRandSeed(M_RandomizedSeed()); // Use a more "Random" random seed
|
||||
|
||||
//SRB2Kart - Score is literally the only thing you SHOULDN'T reset at all times
|
||||
//if (resetplayer)
|
||||
// Clear a bunch of variables
|
||||
tokenlist = token = sstimer = redscore = bluescore = lastmap = 0;
|
||||
racecountdown = exitcountdown = mapreset = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
// Clear a bunch of variables
|
||||
tokenlist = token = sstimer = redscore = bluescore = lastmap = 0;
|
||||
racecountdown = exitcountdown = mapreset = 0;
|
||||
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;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
// The latter two should clear by themselves, but just in case
|
||||
players[i].pflags &= ~(PF_TAGIT|PF_TAGGED|PF_FULLSTASIS);
|
||||
|
||||
// Clear cheatcodes too, just in case.
|
||||
players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
|
||||
|
||||
players[i].marescore = 0;
|
||||
|
||||
if (resetplayer && !(multiplayer && demo.playback)) // SRB2Kart
|
||||
{
|
||||
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].score = 0;
|
||||
|
||||
players[i].lives = 3; // SRB2Kart
|
||||
|
||||
// The latter two should clear by themselves, but just in case
|
||||
players[i].pflags &= ~(PF_TAGIT|PF_TAGGED|PF_FULLSTASIS);
|
||||
|
||||
// Clear cheatcodes too, just in case.
|
||||
players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
|
||||
|
||||
players[i].marescore = 0;
|
||||
|
||||
if (resetplayer && !(multiplayer && demo.playback)) // SRB2Kart
|
||||
if (grandprixinfo.roundnum == 0 || grandprixinfo.initalize == true)
|
||||
{
|
||||
players[i].score = 0;
|
||||
players[i].lives = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset unlockable triggers
|
||||
unlocktriggers = 0;
|
||||
|
||||
// clear itemfinder, just in case
|
||||
if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds
|
||||
CV_StealthSetValue(&cv_itemfinder, 0);
|
||||
}
|
||||
|
||||
// Reset unlockable triggers
|
||||
unlocktriggers = 0;
|
||||
|
||||
// clear itemfinder, just in case
|
||||
if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds
|
||||
CV_StealthSetValue(&cv_itemfinder, 0);
|
||||
|
||||
// internal game map
|
||||
// well this check is useless because it is done before (d_netcmd.c::command_map_f)
|
||||
// but in case of for demos....
|
||||
|
|
|
|||
12
src/k_bot.c
12
src/k_bot.c
|
|
@ -1,15 +1,3 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2007-2016 by John "JTE" Muniz.
|
||||
// Copyright (C) 2011-2018 by Sonic Team Junior.
|
||||
//
|
||||
// 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_bot.c
|
||||
/// \brief Basic bot handling
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h"
|
||||
#include "g_game.h"
|
||||
|
|
|
|||
15
src/k_bot.h
15
src/k_bot.h
|
|
@ -1,14 +1,5 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2007-2016 by John "JTE" Muniz.
|
||||
// Copyright (C) 2012-2018 by Sonic Team Junior.
|
||||
//
|
||||
// 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_bot.h
|
||||
/// \brief Basic bot handling
|
||||
#ifndef __K_BOT__
|
||||
#define __K_BOT__
|
||||
|
||||
#include "k_waypoint.h"
|
||||
#include "d_player.h"
|
||||
|
|
@ -28,3 +19,5 @@ boolean K_PlayerUsesBotMovement(player_t *player);
|
|||
boolean K_BotCanTakeCut(player_t *player);
|
||||
fixed_t K_BotRubberband(player_t *player);
|
||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -230,3 +230,30 @@ void K_FakeBotResults(player_t *bot)
|
|||
bot->realtime = bot->realtime + (bot->distancetofinish / distfactor);
|
||||
bot->distancetofinish = 0;
|
||||
}
|
||||
|
||||
void K_PlayerLoseLife(player_t *player)
|
||||
{
|
||||
if (!G_GametypeUsesLives())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->spectator || player->exiting || player->bot || player->lostlife)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player->lives--;
|
||||
player->lostlife = true;
|
||||
|
||||
#if 0
|
||||
if (player->lives <= 0)
|
||||
{
|
||||
if (P_IsLocalPlayer(player))
|
||||
{
|
||||
S_StopMusic();
|
||||
S_ChangeMusicInternal("gmover", false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@ extern struct grandprixinfo
|
|||
UINT8 gamespeed; ///< Copy of gamespeed, just to make sure you can't cheat it with cvars
|
||||
boolean encore; ///< Ditto, but for encore mode
|
||||
boolean masterbots; ///< If true, all bots should be max difficulty (Master Mode)
|
||||
boolean initbots; ///< If true, we need to initialize the bots that are competing.
|
||||
boolean initalize; ///< If true, we need to initialize a new cup.
|
||||
boolean wonround; ///< If false, then we retry the map instead of going to the next.
|
||||
} grandprixinfo;
|
||||
|
||||
void K_InitGrandPrixBots(void);
|
||||
void K_FakeBotResults(player_t *bot);
|
||||
void K_PlayerLoseLife(player_t *player);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -9891,6 +9891,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
|
||||
static void K_drawKartLapsAndRings(void)
|
||||
{
|
||||
const boolean uselives = G_GametypeUsesLives();
|
||||
SINT8 ringanim_realframe = stplyr->karthud[khud_ringframe];
|
||||
INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT);
|
||||
UINT8 rn[2];
|
||||
|
|
@ -9975,7 +9976,7 @@ static void K_drawKartLapsAndRings(void)
|
|||
}
|
||||
|
||||
// Rings
|
||||
if (netgame)
|
||||
if (!uselives)
|
||||
{
|
||||
V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy-10, V_HUDTRANS|splitflags|flipflag, kp_ringstickersplit[1]);
|
||||
if (flipflag)
|
||||
|
|
@ -9997,7 +9998,7 @@ static void K_drawKartLapsAndRings(void)
|
|||
V_DrawScaledPatch(fr-12, fy-23, V_HUDTRANS|splitflags, kp_ringspblocksmall[stplyr->karthud[khud_ringspblock]]);
|
||||
|
||||
// Lives
|
||||
if (!netgame)
|
||||
if (uselives)
|
||||
{
|
||||
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE);
|
||||
V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|splitflags, facemmapprefix[stplyr->skin], colormap);
|
||||
|
|
@ -10015,7 +10016,7 @@ static void K_drawKartLapsAndRings(void)
|
|||
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->laps, cv_numlaps.value));
|
||||
|
||||
// Rings
|
||||
if (netgame)
|
||||
if (!uselives)
|
||||
V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]);
|
||||
else
|
||||
V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]);
|
||||
|
|
@ -10039,7 +10040,7 @@ static void K_drawKartLapsAndRings(void)
|
|||
V_DrawScaledPatch(LAPS_X-5, LAPS_Y-28, V_HUDTRANS|splitflags, kp_ringspblock[stplyr->karthud[khud_ringspblock]]);
|
||||
|
||||
// Lives
|
||||
if (!netgame)
|
||||
if (uselives)
|
||||
{
|
||||
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE);
|
||||
V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|splitflags, facerankprefix[stplyr->skin], colormap);
|
||||
|
|
|
|||
|
|
@ -241,6 +241,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->charflags);
|
||||
else if (fastcmp(field,"lives"))
|
||||
lua_pushinteger(L, plr->lives);
|
||||
else if (fastcmp(field,"lostlife"))
|
||||
lua_pushboolean(L, plr->lostlife);
|
||||
else if (fastcmp(field,"continues"))
|
||||
lua_pushinteger(L, plr->continues);
|
||||
else if (fastcmp(field,"xtralife"))
|
||||
|
|
@ -489,6 +491,8 @@ static int player_set(lua_State *L)
|
|||
plr->charflags = (UINT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"lives"))
|
||||
plr->lives = (SINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"lostlife"))
|
||||
plr->lostlife = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"continues"))
|
||||
plr->continues = (SINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"xtralife"))
|
||||
|
|
|
|||
|
|
@ -7649,7 +7649,9 @@ static void M_StartGrandPrix(INT32 choice)
|
|||
grandprixinfo.cup = gpcup;
|
||||
|
||||
grandprixinfo.roundnum = 1;
|
||||
grandprixinfo.initbots = true;
|
||||
grandprixinfo.wonround = false;
|
||||
|
||||
grandprixinfo.initalize = true;
|
||||
|
||||
G_DeferedInitNew(
|
||||
false,
|
||||
|
|
|
|||
135
src/p_inter.c
135
src/p_inter.c
|
|
@ -29,6 +29,7 @@
|
|||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
// CTF player names
|
||||
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
|
||||
|
|
@ -1972,71 +1973,133 @@ void P_CheckPointLimit(void)
|
|||
// Checks whether or not to end a race netgame.
|
||||
boolean P_CheckRacers(void)
|
||||
{
|
||||
INT32 i, j, numplayersingame = 0, numexiting = 0;
|
||||
UINT8 i;
|
||||
UINT8 numplayersingame = 0;
|
||||
UINT8 numexiting = 0;
|
||||
boolean eliminatelast = cv_karteliminatelast.value;
|
||||
boolean canexit = true;
|
||||
boolean griefed = false;
|
||||
|
||||
// Check if all the players in the race have finished. If so, end the level.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || players[i].exiting || players[i].bot || !players[i].lives)
|
||||
continue;
|
||||
if (nospectategrief[i] != -1) // prevent spectate griefing
|
||||
{
|
||||
griefed = true;
|
||||
}
|
||||
|
||||
break;
|
||||
if (!playeringame[i] || players[i].spectator || players[i].lives <= 0) // Not playing
|
||||
{
|
||||
// Y'all aren't even playing
|
||||
continue;
|
||||
}
|
||||
|
||||
numplayersingame++;
|
||||
|
||||
if (players[i].exiting || (players[i].pflags & PF_TIMEOVER))
|
||||
{
|
||||
numexiting++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (players[i].bot)
|
||||
{
|
||||
// Isn't a human, thus doesn't matter. (Sorry, robots.)
|
||||
continue;
|
||||
}
|
||||
|
||||
canexit = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS) // finished
|
||||
if (canexit)
|
||||
{
|
||||
// Everyone's finished, we're done here!
|
||||
racecountdown = exitcountdown = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
if (numplayersingame <= 1)
|
||||
{
|
||||
if (nospectategrief[j] != -1) // prevent spectate griefing
|
||||
griefed = true;
|
||||
if (!playeringame[j] || players[j].spectator)
|
||||
continue;
|
||||
numplayersingame++;
|
||||
if (players[j].exiting)
|
||||
numexiting++;
|
||||
// Never do this without enough players.
|
||||
eliminatelast = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (grandprixinfo.roundnum > 0)
|
||||
{
|
||||
// Always do this in GP
|
||||
eliminatelast = true;
|
||||
}
|
||||
else if (griefed)
|
||||
{
|
||||
// Don't do this if someone spectated
|
||||
eliminatelast = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cv_karteliminatelast.value && numplayersingame > 1 && !griefed)
|
||||
if (eliminatelast == true && (numplayersingame <= numexiting-1))
|
||||
{
|
||||
// check if we just got unlucky and there was only one guy who was a problem
|
||||
for (j = i+1; j < MAXPLAYERS; j++)
|
||||
// Everyone's done playing but one guy apparently.
|
||||
// Just kill everyone who is still playing.
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[j] || players[j].spectator || players[j].exiting || !players[j].lives)
|
||||
if (!playeringame[i] || players[i].spectator || players[i].lives <= 0) // Not playing
|
||||
{
|
||||
// Y'all aren't even playing
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (players[i].exiting || (players[i].pflags & PF_TIMEOVER))
|
||||
{
|
||||
// You're done, you're free to go.
|
||||
continue;
|
||||
}
|
||||
|
||||
P_DoTimeOver(&players[i]);
|
||||
}
|
||||
|
||||
if (j == MAXPLAYERS) // finish anyways, force a time over
|
||||
{
|
||||
P_DoTimeOver(&players[i]);
|
||||
racecountdown = exitcountdown = 0;
|
||||
return true;
|
||||
}
|
||||
// Everyone should be done playing at this point now.
|
||||
racecountdown = exitcountdown = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!racecountdown) // Check to see if the winners have finished, to set countdown.
|
||||
// SO, we're not done playing.
|
||||
// Let's see if it's time to start the death counter!
|
||||
|
||||
if (!racecountdown)
|
||||
{
|
||||
// If the winners are all done, then start the death timer.
|
||||
UINT8 winningpos = 1;
|
||||
|
||||
winningpos = max(1, numplayersingame/2);
|
||||
if (numplayersingame % 2) // any remainder?
|
||||
{
|
||||
winningpos++;
|
||||
}
|
||||
|
||||
if (numexiting >= winningpos)
|
||||
racecountdown = (((netgame || multiplayer) ? cv_countdowntime.value : 30)*TICRATE) + 1; // 30 seconds to finish, get going!
|
||||
{
|
||||
tic_t countdown = 30*TICRATE; // 30 seconds left to finish, get going!
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
// Custom timer
|
||||
countdown = cv_countdowntime.value * TICRATE;
|
||||
}
|
||||
|
||||
racecountdown = countdown + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (numplayersingame < 2) // reset nospectategrief in free play
|
||||
// We're still playing, but no one else is, so we need to reset spectator griefing.
|
||||
if (numplayersingame <= 1)
|
||||
{
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
nospectategrief[j] = -1;
|
||||
memset(nospectategrief, -1, sizeof (nospectategrief));
|
||||
}
|
||||
|
||||
// Turns out we're still having a good time & playing the game, we didn't have to do anything :)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2250,20 +2313,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
|||
target->flags |= MF_NOBLOCKMAP|MF_NOCLIPHEIGHT;
|
||||
P_SetThingPosition(target);
|
||||
|
||||
if (!target->player->bot && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives())
|
||||
{
|
||||
target->player->lives -= 1; // Lose a life Tails 03-11-2000
|
||||
|
||||
if (target->player->lives <= 0) // Tails 03-14-2000
|
||||
{
|
||||
if (P_IsLocalPlayer(target->player)/* && target->player == &players[consoleplayer] */)
|
||||
{
|
||||
S_StopMusic(); // Stop the Music! Tails 03-14-2000
|
||||
S_ChangeMusicInternal("gmover", false); // Yousa dead now, Okieday? Tails 03-14-2000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target->player->playerstate = PST_DEAD;
|
||||
|
||||
if (target->player == &players[consoleplayer])
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEFIXED(save_p, players[i].dashspeed);
|
||||
WRITEINT32(save_p, players[i].dashtime);
|
||||
WRITESINT8(save_p, players[i].lives);
|
||||
WRITEUINT8(save_p, players[i].lostlife);
|
||||
WRITESINT8(save_p, players[i].continues);
|
||||
WRITESINT8(save_p, players[i].xtralife);
|
||||
WRITEUINT8(save_p, players[i].gotcontinue);
|
||||
|
|
@ -327,6 +328,7 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].dashspeed = READFIXED(save_p); // dashing speed
|
||||
players[i].dashtime = READINT32(save_p); // dashing speed
|
||||
players[i].lives = READSINT8(save_p);
|
||||
players[i].lostlife = (boolean)READUINT8(save_p);
|
||||
players[i].continues = READSINT8(save_p); // continues that player has acquired
|
||||
players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter
|
||||
players[i].gotcontinue = READUINT8(save_p); // got continue from stage
|
||||
|
|
|
|||
|
|
@ -2350,6 +2350,8 @@ static void P_LevelInitStuff(void)
|
|||
|
||||
memset(localaiming, 0, sizeof(localaiming));
|
||||
|
||||
grandprixinfo.wonround = false;
|
||||
|
||||
// special stage tokens, emeralds, and ring total
|
||||
tokenbits = 0;
|
||||
runemeraldmanager = false;
|
||||
|
|
@ -2399,6 +2401,7 @@ static void P_LevelInitStuff(void)
|
|||
players[i].realtime = racecountdown = exitcountdown = 0;
|
||||
curlap = bestlap = 0; // SRB2Kart
|
||||
|
||||
players[i].lostlife = false;
|
||||
players[i].gotcontinue = false;
|
||||
|
||||
players[i].xtralife = players[i].deadtimer = players[i].numboxes = players[i].totalring = players[i].laps = 0;
|
||||
|
|
@ -3362,6 +3365,23 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
}
|
||||
#endif
|
||||
|
||||
// NOW you can try to spawn in the Battle capsules, if there's not enough players for a match
|
||||
K_SpawnBattleCapsules();
|
||||
|
||||
if (grandprixinfo.roundnum != 0)
|
||||
{
|
||||
if (grandprixinfo.initalize == true)
|
||||
{
|
||||
K_InitGrandPrixBots();
|
||||
grandprixinfo.initalize = false;
|
||||
}
|
||||
}
|
||||
else if (!modeattacking)
|
||||
{
|
||||
// We're in a Match Race, use simplistic randomized bots.
|
||||
K_UpdateMatchRaceBots();
|
||||
}
|
||||
|
||||
P_MapEnd();
|
||||
|
||||
// Remove the loading shit from the screen
|
||||
|
|
@ -3413,23 +3433,6 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
#endif
|
||||
}
|
||||
|
||||
// NOW you can try to spawn in the Battle capsules, if there's not enough players for a match
|
||||
K_SpawnBattleCapsules();
|
||||
|
||||
if (grandprixinfo.roundnum != 0)
|
||||
{
|
||||
if (grandprixinfo.initbots == true)
|
||||
{
|
||||
K_InitGrandPrixBots();
|
||||
grandprixinfo.initbots = false;
|
||||
}
|
||||
}
|
||||
else if (!modeattacking)
|
||||
{
|
||||
// We're in a Match Race, use simplistic randomized bots.
|
||||
K_UpdateMatchRaceBots();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
124
src/p_user.c
124
src/p_user.c
|
|
@ -40,13 +40,14 @@
|
|||
#include "st_stuff.h"
|
||||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "k_bot.h"
|
||||
// Objectplace
|
||||
#include "m_cheat.h"
|
||||
// SRB2kart
|
||||
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
|
||||
#include "k_kart.h"
|
||||
#include "console.h" // CON_LogMessage
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
|
@ -1681,12 +1682,20 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
|
|||
// Player exits the map via sector trigger
|
||||
void P_DoPlayerExit(player_t *player)
|
||||
{
|
||||
const boolean losing = K_IsPlayerLosing(player);
|
||||
|
||||
if (player->exiting || mapreset)
|
||||
return;
|
||||
|
||||
if (P_IsLocalPlayer(player) && (!player->spectator && !demo.playback))
|
||||
legitimateexit = true;
|
||||
|
||||
if (G_GametypeUsesLives() && losing)
|
||||
{
|
||||
// Remove a life from the losing player
|
||||
K_PlayerLoseLife(player);
|
||||
}
|
||||
|
||||
if (G_RaceGametype()) // If in Race Mode, allow
|
||||
{
|
||||
player->exiting = raceexittime+2;
|
||||
|
|
@ -1697,7 +1706,7 @@ void P_DoPlayerExit(player_t *player)
|
|||
if (P_IsDisplayPlayer(player))
|
||||
{
|
||||
sfxenum_t sfx_id;
|
||||
if (K_IsPlayerLosing(player))
|
||||
if (losing)
|
||||
sfx_id = ((skin_t *)player->mo->skin)->soundsid[S_sfx[sfx_klose].skinsound];
|
||||
else
|
||||
sfx_id = ((skin_t *)player->mo->skin)->soundsid[S_sfx[sfx_kwin].skinsound];
|
||||
|
|
@ -1705,7 +1714,7 @@ void P_DoPlayerExit(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (K_IsPlayerLosing(player))
|
||||
if (losing)
|
||||
S_StartSound(player->mo, sfx_klose);
|
||||
else
|
||||
S_StartSound(player->mo, sfx_kwin);
|
||||
|
|
@ -1715,10 +1724,6 @@ void P_DoPlayerExit(player_t *player)
|
|||
if (cv_inttime.value > 0)
|
||||
P_EndingMusic(player);
|
||||
|
||||
// SRB2kart 120217
|
||||
//if (!exitcountdown)
|
||||
//exitcountdown = racecountdown + 8*TICRATE;
|
||||
|
||||
if (P_CheckRacers())
|
||||
player->exiting = raceexittime+1;
|
||||
}
|
||||
|
|
@ -1730,24 +1735,18 @@ void P_DoPlayerExit(player_t *player)
|
|||
else
|
||||
player->exiting = raceexittime+2; // Accidental death safeguard???
|
||||
|
||||
//player->pflags &= ~PF_GLIDING;
|
||||
/* // SRB2kart - don't need
|
||||
if (player->climbing)
|
||||
if (grandprixinfo.roundnum > 0 && !losing && !player->bot)
|
||||
{
|
||||
player->climbing = 0;
|
||||
player->pflags |= PF_JUMPED;
|
||||
P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);
|
||||
// YOU WIN
|
||||
grandprixinfo.wonround = true;
|
||||
}
|
||||
*/
|
||||
|
||||
player->powers[pw_underwater] = 0;
|
||||
player->powers[pw_spacetime] = 0;
|
||||
player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation
|
||||
|
||||
if (player == &players[consoleplayer])
|
||||
demo.savebutton = leveltime;
|
||||
|
||||
/*if (playeringame[player-players] && netgame && !circuitmap)
|
||||
CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);*/
|
||||
}
|
||||
|
||||
#define SPACESPECIAL 12
|
||||
|
|
@ -6995,14 +6994,9 @@ static void P_DeathThink(player_t *player)
|
|||
|
||||
K_KartPlayerHUDUpdate(player);
|
||||
|
||||
// Force respawn if idle for more than 30 seconds in shooter modes.
|
||||
if (player->lives > 0 /*&& leveltime >= starttime*/) // *could* you respawn?
|
||||
if (player->lives > 0 && !(player->pflags & PF_TIMEOVER) && player->deadtimer > TICRATE)
|
||||
{
|
||||
// SRB2kart - spawn automatically after 1 second
|
||||
if (player->deadtimer > ((netgame || multiplayer)
|
||||
? cv_respawntime.value*TICRATE
|
||||
: TICRATE)) // don't let them change it in record attack
|
||||
player->playerstate = PST_REBORN;
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
|
||||
// Keep time rolling
|
||||
|
|
@ -8256,13 +8250,28 @@ static void P_CalcPostImg(player_t *player)
|
|||
|
||||
void P_DoTimeOver(player_t *player)
|
||||
{
|
||||
if (netgame && player->health > 0)
|
||||
if (player->pflags & PF_TIMEOVER)
|
||||
{
|
||||
// NO! Don't do this!
|
||||
return;
|
||||
}
|
||||
|
||||
if (P_IsLocalPlayer(player) && !demo.playback)
|
||||
{
|
||||
legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p
|
||||
}
|
||||
|
||||
if (netgame && !player->bot)
|
||||
{
|
||||
CON_LogMessage(va(M_GetText("%s ran out of time.\n"), player_names[player-players]));
|
||||
}
|
||||
|
||||
player->pflags |= PF_TIMEOVER;
|
||||
|
||||
if (P_IsLocalPlayer(player) && !demo.playback)
|
||||
legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p
|
||||
if (G_GametypeUsesLives())
|
||||
{
|
||||
K_PlayerLoseLife(player);
|
||||
}
|
||||
|
||||
if (player->mo)
|
||||
{
|
||||
|
|
@ -8384,7 +8393,7 @@ void P_PlayerThink(player_t *player)
|
|||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
{
|
||||
if (!players[i].exiting && players[i].lives > 0)
|
||||
if (!players[i].exiting && !(players[i].pflags & PF_TIMEOVER) && players[i].lives > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -8392,24 +8401,26 @@ void P_PlayerThink(player_t *player)
|
|||
if (i == MAXPLAYERS && player->exiting == raceexittime+2) // finished
|
||||
player->exiting = raceexittime+1;
|
||||
|
||||
#if 0
|
||||
// If 10 seconds are left on the timer,
|
||||
// begin the drown music for countdown!
|
||||
|
||||
// SRB2Kart: despite how perfect this is, it's disabled FOR A REASON
|
||||
/*if (racecountdown == 11*TICRATE - 1)
|
||||
if (racecountdown == 11*TICRATE - 1)
|
||||
{
|
||||
if (P_IsLocalPlayer(player))
|
||||
S_ChangeMusicInternal("drown", false);
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
// If you've hit the countdown and you haven't made
|
||||
// it to the exit, you're a goner!
|
||||
else if (racecountdown == 1 && !player->exiting && !player->spectator && player->lives > 0)
|
||||
if (racecountdown == 1 && !player->spectator && !player->exiting && !(player->pflags & PF_TIMEOVER) && player->lives > 0)
|
||||
{
|
||||
P_DoTimeOver(player);
|
||||
|
||||
if (player->playerstate == PST_DEAD)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8423,33 +8434,9 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
if (player->exiting == 2 || exitcountdown == 2)
|
||||
{
|
||||
if (cv_playersforexit.value) // Count to be sure everyone's exited
|
||||
if (server)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || players[i].bot)
|
||||
continue;
|
||||
if (players[i].lives <= 0)
|
||||
continue;
|
||||
|
||||
if (!players[i].exiting || players[i].exiting > 3)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
{
|
||||
if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
}
|
||||
else
|
||||
player->exiting = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8487,28 +8474,9 @@ void P_PlayerThink(player_t *player)
|
|||
player->health = 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ((netgame || multiplayer) && player->lives <= 0)
|
||||
{
|
||||
// In Co-Op, replenish a user's lives if they are depleted.
|
||||
// of course, this is just a cheap hack, meh...
|
||||
player->lives = cv_startinglives.value;
|
||||
}
|
||||
#else
|
||||
player->lives = 1; // SRB2Kart
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
}
|
||||
*/
|
||||
|
||||
// Synchronizes the "real" amount of time spent in the level.
|
||||
if (!player->exiting)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue