mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'ranking' into 'podium'
Ranking See merge request KartKrew/Kart!1017
This commit is contained in:
commit
fa430a6d41
18 changed files with 869 additions and 115 deletions
|
|
@ -135,6 +135,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
|||
k_specialstage.c
|
||||
k_roulette.c
|
||||
k_podium.c
|
||||
k_rank.c
|
||||
)
|
||||
|
||||
if(SRB2_CONFIG_ENABLE_WEBM_MOVIES)
|
||||
|
|
|
|||
|
|
@ -453,6 +453,7 @@ consvar_t cv_kartdebugcolorize = CVAR_INIT ("debugcolorize", "Off", CV_CHEAT, CV
|
|||
consvar_t cv_kartdebugdirector = CVAR_INIT ("debugdirector", "Off", CV_CHEAT, CV_OnOff, NULL);
|
||||
consvar_t cv_spbtest = CVAR_INIT ("spbtest", "Off", CV_CHEAT|CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_gptest = CVAR_INIT ("gptest", "Off", CV_CHEAT|CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_debugrank = CVAR_INIT ("debugrank", "Off", CV_CHEAT, CV_OnOff, NULL);
|
||||
|
||||
static CV_PossibleValue_t capsuletest_cons_t[] = {
|
||||
{CV_CAPSULETEST_OFF, "Off"},
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugdistribution,
|
|||
extern consvar_t cv_kartdebugnodes, cv_kartdebugcolorize, cv_kartdebugdirector;
|
||||
extern consvar_t cv_spbtest, cv_gptest, cv_reducevfx;
|
||||
extern consvar_t cv_kartdebugwaypoints, cv_kartdebugbotpredict;
|
||||
extern consvar_t cv_debugrank;
|
||||
|
||||
typedef enum {
|
||||
CV_CAPSULETEST_OFF,
|
||||
|
|
|
|||
|
|
@ -634,6 +634,7 @@ struct player_t
|
|||
tic_t realtime; // integer replacement for leveltime
|
||||
UINT8 laps; // Number of laps (optional)
|
||||
UINT8 latestlap;
|
||||
UINT32 lapPoints; // Points given from laps
|
||||
INT32 starpostnum; // The number of the last starpost you hit
|
||||
|
||||
UINT8 ctfteam; // 0 == Spectator, 1 == Red, 2 == Blue
|
||||
|
|
|
|||
37
src/g_game.c
37
src/g_game.c
|
|
@ -63,6 +63,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "k_director.h"
|
||||
#include "k_podium.h"
|
||||
#include "k_rank.h"
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
#include "discord.h"
|
||||
|
|
@ -1471,8 +1472,6 @@ void G_DoLoadLevelEx(boolean resetplayer, gamestate_t newstate)
|
|||
if (gamestate == GS_VOTING)
|
||||
Y_EndVote();
|
||||
|
||||
K_ResetCeremony();
|
||||
|
||||
// cleanup
|
||||
// Is this actually necessary? Doesn't F_StartTitleScreen already do a significantly more comprehensive check?
|
||||
if (newstate == GS_TITLESCREEN)
|
||||
|
|
@ -1499,6 +1498,8 @@ void G_DoLoadLevelEx(boolean resetplayer, gamestate_t newstate)
|
|||
M_ClearMenus(true);
|
||||
I_UpdateMouseGrab();
|
||||
|
||||
K_ResetCeremony();
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (resetplayer || (playeringame[i] && players[i].playerstate == PST_DEAD))
|
||||
|
|
@ -2388,6 +2389,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
INT16 totalring;
|
||||
UINT8 laps;
|
||||
UINT8 latestlap;
|
||||
UINT32 lapPoints;
|
||||
UINT16 skincolor;
|
||||
INT32 skin;
|
||||
UINT8 availabilities[MAXAVAILABILITY];
|
||||
|
|
@ -2497,6 +2499,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
nocontrol = 0;
|
||||
laps = 0;
|
||||
latestlap = 0;
|
||||
lapPoints = 0;
|
||||
roundscore = 0;
|
||||
exiting = 0;
|
||||
khudfinish = 0;
|
||||
|
|
@ -2532,6 +2535,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
|
||||
laps = players[player].laps;
|
||||
latestlap = players[player].latestlap;
|
||||
lapPoints = players[player].lapPoints;
|
||||
|
||||
roundscore = players[player].roundscore;
|
||||
|
||||
|
|
@ -2604,6 +2608,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
|
||||
p->laps = laps;
|
||||
p->latestlap = latestlap;
|
||||
p->lapPoints = lapPoints;
|
||||
p->totalring = totalring;
|
||||
|
||||
p->bot = bot;
|
||||
|
|
@ -3882,20 +3887,9 @@ static void G_GetNextMap(void)
|
|||
// Special stage
|
||||
else if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels)
|
||||
{
|
||||
INT16 totaltotalring = 0;
|
||||
gp_rank_e grade = K_CalculateGPGrade(&grandprixinfo.rank);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].spectator)
|
||||
continue;
|
||||
if (players[i].bot)
|
||||
continue;
|
||||
totaltotalring += players[i].totalring;
|
||||
}
|
||||
|
||||
if (totaltotalring >= 50)
|
||||
if (grade >= GRADE_A) // On A rank pace? Then you get a chance for S rank!
|
||||
{
|
||||
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[CUPCACHE_SPECIAL];
|
||||
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum])
|
||||
|
|
@ -4123,6 +4117,9 @@ static void G_DoCompleted(void)
|
|||
G_SetGamestate(GS_NULL);
|
||||
wipegamestate = GS_NULL;
|
||||
|
||||
grandprixinfo.rank.capsules += numtargets;
|
||||
grandprixinfo.rank.position = MAXPLAYERS;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
|
|
@ -4148,6 +4145,11 @@ static void G_DoCompleted(void)
|
|||
}
|
||||
|
||||
G_PlayerFinishLevel(i); // take away cards and stuff
|
||||
|
||||
if (players[i].bot == false)
|
||||
{
|
||||
grandprixinfo.rank.position = min(grandprixinfo.rank.position, K_GetPodiumPosition(&players[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5485,6 +5487,11 @@ boolean G_GetExitGameFlag(void)
|
|||
// Same deal with retrying.
|
||||
void G_SetRetryFlag(void)
|
||||
{
|
||||
if (retrying == false)
|
||||
{
|
||||
grandprixinfo.rank.continuesUsed++;
|
||||
}
|
||||
|
||||
retrying = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "k_boss.h" // bossinfo.valid
|
||||
#include "p_spec.h"
|
||||
#include "k_objects.h"
|
||||
#include "k_rank.h"
|
||||
|
||||
// Battle overtime info
|
||||
struct battleovertime battleovertime;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,24 @@ UINT8 K_BotDefaultSkin(void)
|
|||
return (UINT8)defaultbotskin;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_GetGPPlayerCount(UINT8 humans)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
UINT8 K_GetGPPlayerCount(UINT8 humans)
|
||||
{
|
||||
UINT8 playerCount = 8;
|
||||
|
||||
if (humans > 2)
|
||||
{
|
||||
// Add 3 bots per player beyond 2P
|
||||
playerCount += (humans - 2) * 3;
|
||||
}
|
||||
|
||||
return playerCount;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitGrandPrixBots(void)
|
||||
|
||||
|
|
@ -198,12 +216,7 @@ void K_InitGrandPrixBots(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (numplayers > 2)
|
||||
{
|
||||
// Add 3 bots per player beyond 2P
|
||||
playercount += (numplayers-2) * 3;
|
||||
}
|
||||
|
||||
playercount = K_GetGPPlayerCount(numplayers);
|
||||
wantedbots = playercount - numplayers;
|
||||
|
||||
// Create rival list
|
||||
|
|
|
|||
|
|
@ -15,14 +15,18 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "k_rank.h" // gpRank_t
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GPEVENT_NONE 0
|
||||
#define GPEVENT_BONUS 1
|
||||
#define GPEVENT_SPECIAL 2
|
||||
typedef enum
|
||||
{
|
||||
GPEVENT_NONE = 0,
|
||||
GPEVENT_BONUS,
|
||||
GPEVENT_SPECIAL,
|
||||
} gpEvent_e;
|
||||
|
||||
extern struct grandprixinfo
|
||||
{
|
||||
|
|
@ -34,10 +38,10 @@ extern struct grandprixinfo
|
|||
boolean masterbots; ///< If true, all bots should be max difficulty (Master Mode)
|
||||
boolean initalize; ///< If true, we need to initialize a new session.
|
||||
boolean wonround; ///< If false, then we retry the map instead of going to the next.
|
||||
UINT8 eventmode; ///< See GPEVENT_ constants
|
||||
gpEvent_e eventmode; ///< Special event mode, bots are set to spectate and a special gametype is played
|
||||
gpRank_t rank; ///< Struct containing grading information. (See also: k_rank.h)
|
||||
} grandprixinfo;
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_BotStartingDifficulty(SINT8 value);
|
||||
|
||||
|
|
@ -81,6 +85,23 @@ INT16 K_CalculateGPRankPoints(UINT8 position, UINT8 numplayers);
|
|||
UINT8 K_BotDefaultSkin(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_GetGPPlayerCount(UINT8 humans)
|
||||
|
||||
Counts the number of total players,
|
||||
including humans and bots, to put into
|
||||
a GP session.
|
||||
|
||||
Input Arguments:-
|
||||
humans - Number of human players.
|
||||
|
||||
Return:-
|
||||
Number of both human players and CPU.
|
||||
--------------------------------------------------*/
|
||||
|
||||
UINT8 K_GetGPPlayerCount(UINT8 humans);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitGrandPrixBots(void);
|
||||
|
||||
|
|
@ -170,6 +191,7 @@ void K_PlayerLoseLife(player_t *player);
|
|||
|
||||
boolean K_CanChangeRules(boolean allowdemos);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
55
src/k_hud.c
55
src/k_hud.c
|
|
@ -37,6 +37,8 @@
|
|||
#include "r_fps.h"
|
||||
#include "m_random.h"
|
||||
#include "k_roulette.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_rank.h"
|
||||
|
||||
//{ Patch Definitions
|
||||
static patch_t *kp_nodraw;
|
||||
|
|
@ -4796,6 +4798,58 @@ static void K_DrawWaypointDebugger(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void K_DrawGPRankDebugger(void)
|
||||
{
|
||||
gp_rank_e grade = GRADE_E;
|
||||
char gradeChar = '?';
|
||||
|
||||
if (cv_debugrank.value == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (stplyr != &players[displayplayers[0]]) // only for p1
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (grandprixinfo.gp == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
grade = K_CalculateGPGrade(&grandprixinfo.rank);
|
||||
|
||||
V_DrawThinString(0, 0, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||
va("POS: %d / %d", grandprixinfo.rank.position, RANK_NEUTRAL_POSITION));
|
||||
V_DrawThinString(0, 10, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||
va("PTS: %d / %d", grandprixinfo.rank.winPoints, grandprixinfo.rank.totalPoints));
|
||||
V_DrawThinString(0, 20, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||
va("LAPS: %d / %d", grandprixinfo.rank.laps, grandprixinfo.rank.totalLaps));
|
||||
V_DrawThinString(0, 30, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||
va("CONTINUES: %d", grandprixinfo.rank.continuesUsed));
|
||||
V_DrawThinString(0, 40, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||
va("CAPSULES: %d / %d", grandprixinfo.rank.capsules, grandprixinfo.rank.totalCapsules));
|
||||
V_DrawThinString(0, 50, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||
va("RINGS: %d / %d", grandprixinfo.rank.rings, grandprixinfo.rank.totalRings));
|
||||
V_DrawThinString(0, 60, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||
va("EMERALD: %s", (grandprixinfo.rank.specialWon == true) ? "YES" : "NO"));
|
||||
|
||||
switch (grade)
|
||||
{
|
||||
case GRADE_E: { gradeChar = 'E'; break; }
|
||||
case GRADE_D: { gradeChar = 'D'; break; }
|
||||
case GRADE_C: { gradeChar = 'C'; break; }
|
||||
case GRADE_B: { gradeChar = 'B'; break; }
|
||||
case GRADE_A: { gradeChar = 'A'; break; }
|
||||
case GRADE_S: { gradeChar = 'S'; break; }
|
||||
default: { break; }
|
||||
}
|
||||
|
||||
V_DrawThinString(0, 80, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE|V_YELLOWMAP,
|
||||
va(" ** FINAL GRADE: %c", gradeChar));
|
||||
}
|
||||
|
||||
void K_drawKartHUD(void)
|
||||
{
|
||||
boolean islonesome = false;
|
||||
|
|
@ -5067,4 +5121,5 @@ void K_drawKartHUD(void)
|
|||
|
||||
K_DrawWaypointDebugger();
|
||||
K_DrawDirectorDebugger();
|
||||
K_DrawGPRankDebugger();
|
||||
}
|
||||
|
|
|
|||
121
src/k_kart.c
121
src/k_kart.c
|
|
@ -347,6 +347,7 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_kartdebugnodes);
|
||||
CV_RegisterVar(&cv_kartdebugcolorize);
|
||||
CV_RegisterVar(&cv_kartdebugdirector);
|
||||
CV_RegisterVar(&cv_debugrank);
|
||||
CV_RegisterVar(&cv_spbtest);
|
||||
CV_RegisterVar(&cv_gptest);
|
||||
CV_RegisterVar(&cv_capsuletest);
|
||||
|
|
@ -9318,85 +9319,79 @@ void K_KartUpdatePosition(player_t *player)
|
|||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (K_PodiumSequence() == true)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || !players[i].mo)
|
||||
continue;
|
||||
position = K_GetPodiumPosition(player);
|
||||
|
||||
realplayers++;
|
||||
|
||||
if (K_PodiumSequence() == true)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (players[i].score > player->score)
|
||||
{
|
||||
// Final score is the important part.
|
||||
position++;
|
||||
}
|
||||
else if (players[i].score == player->score)
|
||||
{
|
||||
if (players[i].bot == false && player->bot == true)
|
||||
{
|
||||
// Bots are never as important as players.
|
||||
position++;
|
||||
}
|
||||
else if (i < player - players)
|
||||
{
|
||||
// Port priority is the final tie breaker.
|
||||
position++;
|
||||
}
|
||||
}
|
||||
if (!playeringame[i] || players[i].spectator || !players[i].mo)
|
||||
continue;
|
||||
|
||||
realplayers++;
|
||||
}
|
||||
else if (gametyperules & GTR_CIRCUIT)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (player->exiting) // End of match standings
|
||||
{
|
||||
// Only time matters
|
||||
if (players[i].realtime < player->realtime)
|
||||
position++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// I'm a lap behind this player OR
|
||||
// My distance to the finish line is higher, so I'm behind
|
||||
if ((players[i].laps > player->laps)
|
||||
|| (players[i].distancetofinish < player->distancetofinish))
|
||||
{
|
||||
position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->exiting) // End of match standings
|
||||
{
|
||||
// Only score matters
|
||||
if (players[i].roundscore > player->roundscore)
|
||||
position++;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT8 myEmeralds = K_NumEmeralds(player);
|
||||
UINT8 yourEmeralds = K_NumEmeralds(&players[i]);
|
||||
if (!playeringame[i] || players[i].spectator || !players[i].mo)
|
||||
continue;
|
||||
|
||||
// First compare all points
|
||||
if (players[i].roundscore > player->roundscore)
|
||||
realplayers++;
|
||||
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
if (player->exiting) // End of match standings
|
||||
{
|
||||
position++;
|
||||
// Only time matters
|
||||
if (players[i].realtime < player->realtime)
|
||||
position++;
|
||||
}
|
||||
else if (players[i].roundscore == player->roundscore)
|
||||
else
|
||||
{
|
||||
// Emeralds are a tie breaker
|
||||
if (yourEmeralds > myEmeralds)
|
||||
// I'm a lap behind this player OR
|
||||
// My distance to the finish line is higher, so I'm behind
|
||||
if ((players[i].laps > player->laps)
|
||||
|| (players[i].distancetofinish < player->distancetofinish))
|
||||
{
|
||||
position++;
|
||||
}
|
||||
else if (yourEmeralds == myEmeralds)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->exiting) // End of match standings
|
||||
{
|
||||
// Only score matters
|
||||
if (players[i].roundscore > player->roundscore)
|
||||
position++;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT8 myEmeralds = K_NumEmeralds(player);
|
||||
UINT8 yourEmeralds = K_NumEmeralds(&players[i]);
|
||||
|
||||
// First compare all points
|
||||
if (players[i].roundscore > player->roundscore)
|
||||
{
|
||||
// Bumpers are the second tier tie breaker
|
||||
if (players[i].bumpers > player->bumpers)
|
||||
position++;
|
||||
}
|
||||
else if (players[i].roundscore == player->roundscore)
|
||||
{
|
||||
// Emeralds are a tie breaker
|
||||
if (yourEmeralds > myEmeralds)
|
||||
{
|
||||
position++;
|
||||
}
|
||||
else if (yourEmeralds == myEmeralds)
|
||||
{
|
||||
// Bumpers are the second tier tie breaker
|
||||
if (players[i].bumpers > player->bumpers)
|
||||
{
|
||||
position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
119
src/k_podium.c
119
src/k_podium.c
|
|
@ -45,13 +45,20 @@
|
|||
|
||||
#include "k_menu.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_rank.h"
|
||||
|
||||
static struct podiumData_s
|
||||
{
|
||||
boolean ranking;
|
||||
gpRank_t rank;
|
||||
gp_rank_e grade;
|
||||
UINT8 state;
|
||||
UINT8 delay;
|
||||
UINT8 fade;
|
||||
} podiumData;
|
||||
|
||||
#define PODIUM_STATES (9) // TODO: enum when this actually gets made
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_PodiumSequence(void)
|
||||
|
||||
|
|
@ -267,6 +274,14 @@ void K_FinishCeremony(void)
|
|||
void K_ResetCeremony(void)
|
||||
{
|
||||
memset(&podiumData, 0, sizeof(struct podiumData_s));
|
||||
|
||||
if (K_PodiumSequence() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
podiumData.rank = grandprixinfo.rank;
|
||||
podiumData.grade = K_CalculateGPGrade(&podiumData.rank);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -305,6 +320,19 @@ void K_CeremonyTicker(boolean run)
|
|||
{
|
||||
podiumData.fade++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (podiumData.state < PODIUM_STATES)
|
||||
{
|
||||
podiumData.delay++;
|
||||
|
||||
if (podiumData.delay > TICRATE/2)
|
||||
{
|
||||
podiumData.state++;
|
||||
podiumData.delay = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -317,7 +345,7 @@ boolean K_CeremonyResponder(event_t *event)
|
|||
{
|
||||
INT32 key = event->data1;
|
||||
|
||||
if (podiumData.ranking == false || podiumData.fade < 16)
|
||||
if (podiumData.ranking == false || podiumData.state < PODIUM_STATES)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -377,8 +405,95 @@ void K_CeremonyDrawer(void)
|
|||
{
|
||||
if (podiumData.ranking == true)
|
||||
{
|
||||
char gradeChar = '?';
|
||||
INT32 x = 64;
|
||||
INT32 y = 48;
|
||||
INT32 i;
|
||||
|
||||
switch (podiumData.grade)
|
||||
{
|
||||
case GRADE_E: { gradeChar = 'E'; break; }
|
||||
case GRADE_D: { gradeChar = 'D'; break; }
|
||||
case GRADE_C: { gradeChar = 'C'; break; }
|
||||
case GRADE_B: { gradeChar = 'B'; break; }
|
||||
case GRADE_A: { gradeChar = 'A'; break; }
|
||||
case GRADE_S: { gradeChar = 'S'; break; }
|
||||
default: { break; }
|
||||
}
|
||||
|
||||
V_DrawFadeScreen(0xFF00, podiumData.fade);
|
||||
V_DrawCenteredString(BASEVIDWIDTH / 2, 64, 0, "STUFF GOES HERE");
|
||||
|
||||
for (i = 0; i <= podiumData.state; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||
va("POS: %d / %d", podiumData.rank.position, RANK_NEUTRAL_POSITION)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||
va("PTS: %d / %d", podiumData.rank.winPoints, podiumData.rank.totalPoints)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||
va("LAPS: %d / %d", podiumData.rank.laps, podiumData.rank.totalLaps)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||
va("CONTINUES: %d", podiumData.rank.continuesUsed)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||
va("CAPSULES: %d / %d", podiumData.rank.capsules, podiumData.rank.totalCapsules)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||
va("RINGS: %d / %d", podiumData.rank.rings, podiumData.rank.totalRings)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||
va("EMERALD: %s", (podiumData.rank.specialWon == true) ? "YES" : "NO")
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
V_DrawString(x, y + 10, V_YELLOWMAP|V_ALLOWLOWERCASE,
|
||||
va(" ** FINAL GRADE: %c", gradeChar)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
V_DrawThinString(2, BASEVIDHEIGHT - 10, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||
"Press some button type deal to continue"
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
y += 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeinmap < 16)
|
||||
|
|
|
|||
416
src/k_rank.c
Normal file
416
src/k_rank.c
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 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_rank.c
|
||||
/// \brief Grand Prix mode ranking
|
||||
|
||||
#include "k_rank.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_specialstage.h"
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h"
|
||||
#include "g_game.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_kart.h"
|
||||
#include "m_random.h"
|
||||
#include "r_things.h"
|
||||
#include "fastcmp.h"
|
||||
#include "byteptr.h"
|
||||
|
||||
// I was ALMOST tempted to start tearing apart all
|
||||
// of the map loading code and turning it into C++
|
||||
// and making it properly split between read-only
|
||||
// and true level loading and clean up all of the
|
||||
// global variable garbage it uses ... but I stopped
|
||||
// myself. So here's code duplication hell instead.
|
||||
static UINT32 g_rankCapsules_mapthingsPos[UINT16_MAX];
|
||||
static size_t g_rankCapsules_nummapthings = 0;
|
||||
static boolean g_rankCapsules_udmf = false;
|
||||
static UINT32 g_rankCapsules_count = 0;
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void RankCapsules_TextmapCount(size_t size)
|
||||
|
||||
Counts the number of map things and records
|
||||
the structure positions, for the result of
|
||||
RankCapsules_CountFromMap.
|
||||
|
||||
Input Arguments:-
|
||||
size - Length of the TEXTMAP lump.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
static UINT32 RankCapsules_TextmapCount(size_t size)
|
||||
{
|
||||
const char *tkn = M_TokenizerRead(0);
|
||||
UINT8 brackets = 0;
|
||||
|
||||
g_rankCapsules_nummapthings = 0;
|
||||
|
||||
// Look for namespace at the beginning.
|
||||
if (!fastcmp(tkn, "namespace"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if namespace is valid.
|
||||
tkn = M_TokenizerRead(0);
|
||||
|
||||
while ((tkn = M_TokenizerRead(0)) && M_TokenizerGetEndPos() < size)
|
||||
{
|
||||
// Avoid anything inside bracketed stuff, only look for external keywords.
|
||||
if (brackets)
|
||||
{
|
||||
if (fastcmp(tkn, "}"))
|
||||
brackets--;
|
||||
}
|
||||
else if (fastcmp(tkn, "{"))
|
||||
brackets++;
|
||||
// Check for valid fields.
|
||||
else if (fastcmp(tkn, "thing"))
|
||||
g_rankCapsules_mapthingsPos[g_rankCapsules_nummapthings++] = M_TokenizerGetEndPos();
|
||||
}
|
||||
|
||||
if (brackets)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void RankCapsules_LoadTextmap(void)
|
||||
|
||||
Loads UDMF map data for the result of
|
||||
RankCapsules_CountFromMap.
|
||||
--------------------------------------------------*/
|
||||
static void RankCapsules_LoadTextmap(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < g_rankCapsules_nummapthings; i++)
|
||||
{
|
||||
const char *param, *val;
|
||||
|
||||
M_TokenizerSetEndPos(g_rankCapsules_mapthingsPos[i]);
|
||||
param = M_TokenizerRead(0);
|
||||
|
||||
if (!fastcmp(param, "{"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
param = M_TokenizerRead(0);
|
||||
|
||||
if (fastcmp(param, "}"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
val = M_TokenizerRead(1);
|
||||
|
||||
if (fastcmp(param, "type"))
|
||||
{
|
||||
UINT16 type = atol(val);
|
||||
|
||||
if (type == mobjinfo[MT_BATTLECAPSULE].doomednum)
|
||||
{
|
||||
g_rankCapsules_count++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void RankCapsules_LoadThingsLump(UINT8 *data)
|
||||
|
||||
Loads binary map data for the result of
|
||||
RankCapsules_CountFromMap.
|
||||
|
||||
Input Arguments:-
|
||||
data - Pointer to a THINGS lump.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
static void RankCapsules_LoadThingsLump(UINT8 *data)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < g_rankCapsules_nummapthings; i++)
|
||||
{
|
||||
UINT16 type = 0;
|
||||
|
||||
data += 2; // x
|
||||
data += 2; // y
|
||||
|
||||
data += 2; // angle
|
||||
type = READUINT16(data); // type
|
||||
type &= 4095;
|
||||
|
||||
data += 2; // options
|
||||
|
||||
if (type == mobjinfo[MT_BATTLECAPSULE].doomednum)
|
||||
{
|
||||
g_rankCapsules_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static boolean RankCapsules_LoadMapData(const virtres_t *virt)
|
||||
|
||||
Loads either UDMF or binary map data, for the
|
||||
result of RankCapsules_CountFromMap.
|
||||
|
||||
Input Arguments:-
|
||||
virt - Pointer to the map's virtual resource.
|
||||
|
||||
Return:-
|
||||
true if we could successfully load the map data,
|
||||
otherwise false.
|
||||
--------------------------------------------------*/
|
||||
static boolean RankCapsules_LoadMapData(const virtres_t *virt)
|
||||
{
|
||||
virtlump_t *virtthings = NULL;
|
||||
|
||||
// Count map data.
|
||||
if (g_rankCapsules_udmf) // Count how many entries for each type we got in textmap.
|
||||
{
|
||||
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
|
||||
M_TokenizerOpen((char *)textmap->data);
|
||||
if (!RankCapsules_TextmapCount(textmap->size))
|
||||
{
|
||||
M_TokenizerClose();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
virtthings = vres_Find(virt, "THINGS");
|
||||
|
||||
if (!virtthings)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Traditional doom map format just assumes the number of elements from the lump sizes.
|
||||
g_rankCapsules_nummapthings = virtthings->size / (5 * sizeof (INT16));
|
||||
}
|
||||
|
||||
// Load map data.
|
||||
if (g_rankCapsules_udmf)
|
||||
{
|
||||
RankCapsules_LoadTextmap();
|
||||
M_TokenizerClose();
|
||||
}
|
||||
else
|
||||
{
|
||||
RankCapsules_LoadThingsLump(virtthings->data);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static UINT32 RankCapsules_CountFromMap(const virtres_t *virt)
|
||||
|
||||
Counts the number of capsules in a map, without
|
||||
needing to fully load it.
|
||||
|
||||
Input Arguments:-
|
||||
virt - Pointer to the map's virtual resource.
|
||||
|
||||
Return:-
|
||||
Number of MT_BATTLECAPSULE instances found.
|
||||
--------------------------------------------------*/
|
||||
static UINT32 RankCapsules_CountFromMap(const virtres_t *virt)
|
||||
{
|
||||
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
|
||||
|
||||
g_rankCapsules_udmf = (textmap != NULL);
|
||||
g_rankCapsules_count = 0;
|
||||
|
||||
if (RankCapsules_LoadMapData(virt) == true)
|
||||
{
|
||||
return g_rankCapsules_count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitGrandPrixRank(gpRank_t *rankData)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_InitGrandPrixRank(gpRank_t *rankData)
|
||||
{
|
||||
UINT8 numHumans = 0;
|
||||
UINT32 laps = 0;
|
||||
INT32 i;
|
||||
|
||||
memset(rankData, 0, sizeof(gpRank_t));
|
||||
|
||||
if (grandprixinfo.cup == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
if (numHumans < MAXSPLITSCREENPLAYERS && players[i].spectator == false)
|
||||
{
|
||||
numHumans++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate players
|
||||
rankData->players = numHumans;
|
||||
rankData->totalPlayers = K_GetGPPlayerCount(numHumans);
|
||||
|
||||
// Initialize to the neutral value.
|
||||
rankData->position = RANK_NEUTRAL_POSITION;
|
||||
|
||||
// Calculate total of points
|
||||
// (Should this account for all coop players?)
|
||||
for (i = 0; i < numHumans; i++)
|
||||
{
|
||||
rankData->totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(i + 1, rankData->totalPlayers);
|
||||
}
|
||||
|
||||
rankData->totalRings = grandprixinfo.cup->numlevels * numHumans * 20;
|
||||
|
||||
for (i = 0; i < grandprixinfo.cup->numlevels; i++)
|
||||
{
|
||||
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[i];
|
||||
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum] != NULL)
|
||||
{
|
||||
laps += mapheaderinfo[cupLevelNum]->numlaps;
|
||||
}
|
||||
}
|
||||
|
||||
// +1, since 1st place laps are worth 2 pts.
|
||||
for (i = 0; i < numHumans+1; i++)
|
||||
{
|
||||
rankData->totalLaps += laps;
|
||||
}
|
||||
|
||||
// Search through all of the cup's bonus levels
|
||||
// for an accurate count of how many capsules they have.
|
||||
for (i = 0; i < grandprixinfo.cup->numbonus; i++)
|
||||
{
|
||||
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[CUPCACHE_BONUS + i];
|
||||
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum] != NULL)
|
||||
{
|
||||
lumpnum_t lp = mapheaderinfo[cupLevelNum]->lumpnum;
|
||||
virtres_t *virt = NULL;
|
||||
|
||||
if (lp == LUMPERROR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
virt = vres_GetMap(lp);
|
||||
if (virt == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rankData->totalCapsules += RankCapsules_CountFromMap(virt);
|
||||
vres_Free(virt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||
{
|
||||
static const fixed_t gradePercents[GRADE_A] = {
|
||||
7*FRACUNIT/20, // D: 35% or higher
|
||||
10*FRACUNIT/20, // C: 50% or higher
|
||||
14*FRACUNIT/20, // B: 70% or higher
|
||||
17*FRACUNIT/20 // A: 85% or higher
|
||||
};
|
||||
|
||||
gp_rank_e retGrade = GRADE_E;
|
||||
|
||||
const INT32 positionWeight = 150;
|
||||
const INT32 pointsWeight = 100;
|
||||
const INT32 lapsWeight = 100;
|
||||
const INT32 capsulesWeight = 100;
|
||||
const INT32 ringsWeight = 50;
|
||||
const INT32 total = positionWeight + pointsWeight + lapsWeight + capsulesWeight + ringsWeight;
|
||||
const INT32 continuesPenalty = 20;
|
||||
|
||||
INT32 ours = 0;
|
||||
fixed_t percent = 0;
|
||||
|
||||
if (rankData->position > 0)
|
||||
{
|
||||
const INT32 sc = (rankData->position - 1);
|
||||
const INT32 loser = (RANK_NEUTRAL_POSITION - 1);
|
||||
ours += ((loser - sc) * positionWeight) / loser;
|
||||
}
|
||||
|
||||
if (rankData->totalPoints > 0)
|
||||
{
|
||||
ours += (rankData->winPoints * pointsWeight) / rankData->totalPoints;
|
||||
}
|
||||
|
||||
if (rankData->totalLaps > 0)
|
||||
{
|
||||
ours += (rankData->laps * lapsWeight) / rankData->totalLaps;
|
||||
}
|
||||
|
||||
if (rankData->totalCapsules > 0)
|
||||
{
|
||||
ours += (rankData->capsules * capsulesWeight) / rankData->totalCapsules;
|
||||
}
|
||||
|
||||
if (rankData->totalRings > 0)
|
||||
{
|
||||
ours += (rankData->rings * ringsWeight) / rankData->totalRings;
|
||||
}
|
||||
|
||||
ours -= rankData->continuesUsed * continuesPenalty;
|
||||
|
||||
percent = FixedDiv(ours, total);
|
||||
|
||||
for (retGrade = 0; retGrade < GRADE_A; retGrade++)
|
||||
{
|
||||
if (percent < gradePercents[retGrade])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rankData->specialWon == true)
|
||||
{
|
||||
// Winning the Special Stage gives you
|
||||
// a free grade increase.
|
||||
retGrade++;
|
||||
}
|
||||
|
||||
return retGrade;
|
||||
}
|
||||
96
src/k_rank.h
Normal file
96
src/k_rank.h
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 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_rank.h
|
||||
/// \brief Grand Prix mode ranking
|
||||
|
||||
#ifndef __K_RANK__
|
||||
#define __K_RANK__
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct gpRank_t
|
||||
{
|
||||
UINT8 players;
|
||||
UINT8 totalPlayers;
|
||||
|
||||
UINT8 position;
|
||||
|
||||
UINT32 winPoints;
|
||||
UINT32 totalPoints;
|
||||
|
||||
UINT32 laps;
|
||||
UINT32 totalLaps;
|
||||
|
||||
UINT32 continuesUsed;
|
||||
|
||||
UINT32 capsules;
|
||||
UINT32 totalCapsules;
|
||||
|
||||
UINT32 rings;
|
||||
UINT32 totalRings;
|
||||
|
||||
boolean specialWon;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GRADE_E,
|
||||
GRADE_D,
|
||||
GRADE_C,
|
||||
GRADE_B,
|
||||
GRADE_A,
|
||||
GRADE_S
|
||||
} gp_rank_e;
|
||||
|
||||
// 3rd place is neutral, anything below is a penalty
|
||||
#define RANK_NEUTRAL_POSITION (3)
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitGrandPrixRank(gpRank_t *rankData);
|
||||
|
||||
Calculates rank requirements for a GP session.
|
||||
|
||||
Input Arguments:-
|
||||
rankData - Pointer to struct that contains all
|
||||
of the information required to calculate GP rank.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_InitGrandPrixRank(gpRank_t *rankData);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
gp_rank_e K_CalculateGPGrade(gpRank_t *rankData);
|
||||
|
||||
Calculates the player's grade using the
|
||||
variables from gpRank.
|
||||
|
||||
Input Arguments:-
|
||||
rankData - struct containing existing rank data.
|
||||
|
||||
Return:-
|
||||
gp_rank_e representing the total grade.
|
||||
--------------------------------------------------*/
|
||||
|
||||
gp_rank_e K_CalculateGPGrade(gpRank_t *rankData);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -178,6 +178,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT32(save->p, players[i].realtime);
|
||||
WRITEUINT8(save->p, players[i].laps);
|
||||
WRITEUINT8(save->p, players[i].latestlap);
|
||||
WRITEUINT32(save->p, players[i].lapPoints);
|
||||
WRITEINT32(save->p, players[i].starpostnum);
|
||||
|
||||
WRITEUINT8(save->p, players[i].ctfteam);
|
||||
|
|
@ -567,6 +568,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].realtime = READUINT32(save->p); // integer replacement for leveltime
|
||||
players[i].laps = READUINT8(save->p); // Number of laps (optional)
|
||||
players[i].latestlap = READUINT8(save->p);
|
||||
players[i].lapPoints = READUINT32(save->p);
|
||||
players[i].starpostnum = READINT32(save->p);
|
||||
|
||||
players[i].ctfteam = READUINT8(save->p); // 1 == Red, 2 == Blue
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@
|
|||
#include "acs/interface.h"
|
||||
#include "doomstat.h" // MAXMUSNAMES
|
||||
#include "k_podium.h"
|
||||
#include "k_rank.h"
|
||||
|
||||
// Replay names have time
|
||||
#if !defined (UNDER_CE)
|
||||
|
|
@ -7388,6 +7389,7 @@ static void P_InitGametype(void)
|
|||
{
|
||||
if (grandprixinfo.initalize == true)
|
||||
{
|
||||
K_InitGrandPrixRank(&grandprixinfo.rank);
|
||||
K_InitGrandPrixBots();
|
||||
grandprixinfo.initalize = false;
|
||||
}
|
||||
|
|
|
|||
58
src/p_spec.c
58
src/p_spec.c
|
|
@ -2000,6 +2000,40 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
if (player->laps > player->latestlap)
|
||||
{
|
||||
if (player->laps > 1)
|
||||
{
|
||||
// save best lap for record attack
|
||||
if (modeattacking && player == &players[consoleplayer])
|
||||
{
|
||||
if (curlap < bestlap || bestlap == 0)
|
||||
{
|
||||
bestlap = curlap;
|
||||
}
|
||||
|
||||
curlap = 0;
|
||||
}
|
||||
|
||||
// Update power levels for this lap.
|
||||
K_UpdatePowerLevels(player, player->laps, false);
|
||||
|
||||
if (nump > 1 && K_IsPlayerLosing(player) == false)
|
||||
{
|
||||
if (nump > 2 && player->position == 1) // 1st place in 1v1 uses thumbs up
|
||||
{
|
||||
player->lapPoints += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->lapPoints++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player->latestlap = player->laps;
|
||||
}
|
||||
|
||||
// finished race exit setup
|
||||
if (player->laps > numlaps)
|
||||
{
|
||||
|
|
@ -2027,32 +2061,8 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
SetRandomFakePlayerSkin(player, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (player->laps > player->latestlap)
|
||||
{
|
||||
if (player->laps > 1)
|
||||
{
|
||||
// save best lap for record attack
|
||||
if (modeattacking && player == &players[consoleplayer])
|
||||
{
|
||||
if (curlap < bestlap || bestlap == 0)
|
||||
{
|
||||
bestlap = curlap;
|
||||
}
|
||||
|
||||
curlap = 0;
|
||||
}
|
||||
|
||||
// Update power levels for this lap.
|
||||
K_UpdatePowerLevels(player, player->laps, false);
|
||||
}
|
||||
|
||||
player->latestlap = player->laps;
|
||||
}
|
||||
|
||||
thwompsactive = true; // Lap 2 effects
|
||||
|
||||
lowestLap = P_FindLowestLap();
|
||||
|
||||
for (i = 0; i < numlines; i++)
|
||||
|
|
|
|||
13
src/p_user.c
13
src/p_user.c
|
|
@ -58,6 +58,8 @@
|
|||
#include "k_terrain.h" // K_SpawnSplashForMobj
|
||||
#include "k_color.h"
|
||||
#include "k_follower.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_rank.h"
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
|
@ -1353,6 +1355,7 @@ void P_DoPlayerExit(player_t *player)
|
|||
if (RINGTOTAL(player) > 0)
|
||||
{
|
||||
player->totalring += RINGTOTAL(player);
|
||||
grandprixinfo.rank.rings += RINGTOTAL(player);
|
||||
|
||||
extra = player->totalring / lifethreshold;
|
||||
|
||||
|
|
@ -1363,6 +1366,16 @@ void P_DoPlayerExit(player_t *player)
|
|||
player->xtralife = extra;
|
||||
}
|
||||
}
|
||||
|
||||
if (grandprixinfo.eventmode == GPEVENT_NONE)
|
||||
{
|
||||
grandprixinfo.rank.winPoints += K_CalculateGPRankPoints(player->position, grandprixinfo.rank.totalPlayers);
|
||||
grandprixinfo.rank.laps += player->lapPoints;
|
||||
}
|
||||
else if (grandprixinfo.eventmode == GPEVENT_SPECIAL)
|
||||
{
|
||||
grandprixinfo.rank.specialWon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,9 @@ TYPEDEF (t_floor_t);
|
|||
// k_waypoint.h
|
||||
TYPEDEF (waypoint_t);
|
||||
|
||||
// k_rank.h
|
||||
TYPEDEF (gpRank_t);
|
||||
|
||||
// lua_hudlib_drawlist.h
|
||||
typedef struct huddrawlist_s *huddrawlist_h;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue