mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-01-09 16:32:33 +00:00
Merge branch 'v2-master' into followme-internal
This commit is contained in:
commit
cab9c2a139
51 changed files with 3470 additions and 1592 deletions
|
|
@ -18,6 +18,7 @@ set(SRB2_CORE_SOURCES
|
|||
g_game.c
|
||||
g_input.c
|
||||
g_splitscreen.c
|
||||
font.c
|
||||
hu_stuff.c
|
||||
i_tcp.c
|
||||
info.c
|
||||
|
|
@ -73,6 +74,7 @@ set(SRB2_CORE_HEADERS
|
|||
g_game.h
|
||||
g_input.h
|
||||
g_state.h
|
||||
font.h
|
||||
hu_stuff.h
|
||||
i_joy.h
|
||||
i_net.h
|
||||
|
|
@ -167,6 +169,7 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
k_botitem.c
|
||||
k_botsearch.c
|
||||
k_respawn.c
|
||||
k_grandprix.c
|
||||
|
||||
p_local.h
|
||||
p_maputl.h
|
||||
|
|
@ -188,6 +191,7 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
k_color.h
|
||||
k_bot.h
|
||||
k_respawn.h
|
||||
k_grandprix.h
|
||||
)
|
||||
|
||||
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
|
|
|
|||
|
|
@ -502,6 +502,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/am_map.o \
|
||||
$(OBJDIR)/command.o \
|
||||
$(OBJDIR)/console.o \
|
||||
$(OBJDIR)/font.o \
|
||||
$(OBJDIR)/hu_stuff.o \
|
||||
$(OBJDIR)/y_inter.o \
|
||||
$(OBJDIR)/st_stuff.o \
|
||||
|
|
@ -566,6 +567,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/k_bot.o \
|
||||
$(OBJDIR)/k_botitem.o \
|
||||
$(OBJDIR)/k_botsearch.o \
|
||||
$(OBJDIR)/k_grandprix.o\
|
||||
$(i_cdmus_o) \
|
||||
$(i_net_o) \
|
||||
$(i_system_o) \
|
||||
|
|
@ -813,7 +815,7 @@ $(OBJDIR)/v_video.o: v_video.c doomdef.h doomtype.h g_state.h m_swap.h r_local.h
|
|||
tables.h m_fixed.h screen.h command.h m_bbox.h r_main.h d_player.h \
|
||||
p_pspr.h info.h d_think.h sounds.h p_mobj.h doomdata.h d_ticcmd.h \
|
||||
r_data.h r_defs.h r_state.h r_bsp.h r_segs.h r_plane.h r_sky.h \
|
||||
r_things.h r_draw.h v_video.h hu_stuff.h d_event.h w_wad.h console.h \
|
||||
r_things.h r_draw.h v_video.h font.h hu_stuff.h d_event.h w_wad.h console.h \
|
||||
i_video.h z_zone.h doomstat.h d_clisrv.h d_netcmd.h
|
||||
$(CC) $(CFLAGS) -fno-omit-frame-pointer $(WFLAGS) -c $< -o $@
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifdef CLIENT_LOADINGSCREEN
|
||||
// cl loading screen
|
||||
|
|
@ -575,6 +576,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;
|
||||
|
|
@ -657,6 +659,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
|||
// botvars_t
|
||||
rsp->bot = players[i].bot;
|
||||
rsp->bot_difficulty = players[i].botvars.difficulty;
|
||||
rsp->bot_diffincrease = players[i].botvars.diffincrease;
|
||||
rsp->bot_rival = players[i].botvars.rival;
|
||||
rsp->bot_itemdelay = players[i].botvars.itemdelay;
|
||||
rsp->bot_itemconfirm = players[i].botvars.itemconfirm;
|
||||
rsp->bot_turnconfirm = players[i].botvars.turnconfirm;
|
||||
|
|
@ -714,6 +718,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;
|
||||
|
|
@ -795,6 +800,8 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
// botvars_t
|
||||
players[i].bot = rsp->bot;
|
||||
players[i].botvars.difficulty = rsp->bot_difficulty;
|
||||
players[i].botvars.diffincrease = rsp->bot_diffincrease;
|
||||
players[i].botvars.rival = rsp->bot_rival;
|
||||
players[i].botvars.itemdelay = rsp->bot_itemdelay;
|
||||
players[i].botvars.itemconfirm = rsp->bot_itemconfirm;
|
||||
players[i].botvars.turnconfirm = rsp->bot_turnconfirm;
|
||||
|
|
@ -5267,20 +5274,29 @@ static void Local_Maketic(INT32 realtics)
|
|||
// game responder calls HU_Responder, AM_Responder, F_Responder,
|
||||
// and G_MapEventsToControls
|
||||
if (!dedicated) rendergametic = gametic;
|
||||
|
||||
// translate inputs (keyboard/mouse/joystick) into game controls
|
||||
|
||||
G_BuildTiccmd(&localcmds, realtics, 1);
|
||||
localcmds.angleturn |= TICCMD_RECEIVED;
|
||||
|
||||
if (splitscreen)
|
||||
{
|
||||
G_BuildTiccmd(&localcmds2, realtics, 2);
|
||||
localcmds2.angleturn |= TICCMD_RECEIVED;
|
||||
|
||||
if (splitscreen > 1)
|
||||
{
|
||||
G_BuildTiccmd(&localcmds3, realtics, 3);
|
||||
localcmds3.angleturn |= TICCMD_RECEIVED;
|
||||
|
||||
if (splitscreen > 2)
|
||||
{
|
||||
G_BuildTiccmd(&localcmds4, realtics, 4);
|
||||
localcmds4.angleturn |= TICCMD_RECEIVED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
localcmds.angleturn |= TICCMD_RECEIVED;
|
||||
}
|
||||
|
||||
void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
|
||||
|
|
@ -5317,11 +5333,30 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
|
|||
static void SV_Maketic(void)
|
||||
{
|
||||
INT32 j;
|
||||
boolean b[MAXPLAYERS];
|
||||
|
||||
memset(b, false, sizeof (b));
|
||||
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
if (K_PlayerUsesBotMovement(&players[j]))
|
||||
{
|
||||
b[j] = true;
|
||||
K_BuildBotTiccmd(&players[j], &netcmds[maketic%TICQUEUE][j]);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < MAXNETNODES; j++)
|
||||
{
|
||||
if (playerpernode[j])
|
||||
{
|
||||
INT32 player = nodetoplayer[j];
|
||||
|
||||
if (b[player])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((netcmds[maketic%TICQUEUE][player].angleturn & TICCMD_RECEIVED) == 0)
|
||||
{ // we didn't receive this tic
|
||||
INT32 i;
|
||||
|
|
@ -5342,6 +5377,7 @@ static void SV_Maketic(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// all tic are now proceed make the next
|
||||
maketic++;
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ typedef struct
|
|||
// Score is resynched in the confirm resync packet
|
||||
INT32 health;
|
||||
SINT8 lives;
|
||||
boolean lostlife;
|
||||
SINT8 continues;
|
||||
UINT8 scoreadd;
|
||||
SINT8 xtralife;
|
||||
|
|
@ -295,6 +296,8 @@ typedef struct
|
|||
// botvars_t
|
||||
boolean bot;
|
||||
UINT8 bot_difficulty;
|
||||
UINT8 bot_diffincrease;
|
||||
boolean bot_rival;
|
||||
tic_t bot_itemdelay;
|
||||
tic_t bot_itemconfirm;
|
||||
SINT8 bot_turnconfirm;
|
||||
|
|
|
|||
65
src/d_main.c
65
src/d_main.c
|
|
@ -75,6 +75,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#include "fastcmp.h"
|
||||
#include "keys.h"
|
||||
#include "filesrch.h" // refreshdirmenu
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifdef CMAKECONFIG
|
||||
#include "config.h"
|
||||
|
|
@ -753,6 +754,9 @@ void D_StartTitle(void)
|
|||
// reset modeattacking
|
||||
modeattacking = ATTACKING_NONE;
|
||||
|
||||
// Reset GP
|
||||
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
|
||||
|
||||
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
|
||||
maptol = 0;
|
||||
|
||||
|
|
@ -1132,7 +1136,24 @@ void D_SRB2Main(void)
|
|||
else
|
||||
{
|
||||
if (!M_CheckParm("-server"))
|
||||
{
|
||||
G_SetGameModified(true, true);
|
||||
|
||||
// Start up a "minor" grand prix session
|
||||
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
|
||||
|
||||
grandprixinfo.gamespeed = KARTSPEED_NORMAL;
|
||||
grandprixinfo.encore = false;
|
||||
grandprixinfo.masterbots = false;
|
||||
|
||||
grandprixinfo.gp = true;
|
||||
grandprixinfo.roundnum = 0;
|
||||
grandprixinfo.cup = NULL;
|
||||
grandprixinfo.wonround = false;
|
||||
|
||||
grandprixinfo.initalize = true;
|
||||
}
|
||||
|
||||
autostart = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1515,18 +1536,46 @@ void D_SRB2Main(void)
|
|||
INT16 newskill = -1;
|
||||
const char *sskill = M_GetNextParm();
|
||||
|
||||
for (j = 0; kartspeed_cons_t[j].strvalue; j++)
|
||||
if (!strcasecmp(kartspeed_cons_t[j].strvalue, sskill))
|
||||
const UINT8 master = KARTSPEED_HARD+1;
|
||||
const char *masterstr = "Master";
|
||||
|
||||
if (!strcasecmp(masterstr, sskill))
|
||||
{
|
||||
newskill = master;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; kartspeed_cons_t[j].strvalue; j++)
|
||||
{
|
||||
newskill = (INT16)kartspeed_cons_t[j].value;
|
||||
break;
|
||||
if (!strcasecmp(kartspeed_cons_t[j].strvalue, sskill))
|
||||
{
|
||||
newskill = (INT16)kartspeed_cons_t[j].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match
|
||||
if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match
|
||||
{
|
||||
j = atoi(sskill); // assume they gave us a skill number, which is okay too
|
||||
if (j >= KARTSPEED_EASY && j <= master)
|
||||
newskill = (INT16)j;
|
||||
}
|
||||
}
|
||||
|
||||
if (grandprixinfo.gp == true)
|
||||
{
|
||||
j = atoi(sskill); // assume they gave us a skill number, which is okay too
|
||||
if (j >= KARTSPEED_EASY && j <= KARTSPEED_HARD)
|
||||
newskill = (INT16)j;
|
||||
if (newskill == master)
|
||||
{
|
||||
grandprixinfo.masterbots = true;
|
||||
newskill = KARTSPEED_HARD;
|
||||
}
|
||||
|
||||
grandprixinfo.gamespeed = newskill;
|
||||
}
|
||||
else if (newskill == master)
|
||||
{
|
||||
grandprixinfo.masterbots = true;
|
||||
newskill = KARTSPEED_HARD;
|
||||
}
|
||||
|
||||
if (newskill != -1)
|
||||
|
|
|
|||
206
src/d_netcmd.c
206
src/d_netcmd.c
|
|
@ -52,6 +52,7 @@
|
|||
#include "y_inter.h"
|
||||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
#define CV_RESTRICT CV_NETVAR
|
||||
|
|
@ -717,8 +718,6 @@ void D_RegisterServerCommands(void)
|
|||
AddMServCommands();
|
||||
|
||||
// p_mobj.c
|
||||
CV_RegisterVar(&cv_itemrespawntime);
|
||||
CV_RegisterVar(&cv_itemrespawn);
|
||||
CV_RegisterVar(&cv_flagtime);
|
||||
CV_RegisterVar(&cv_suddendeath);
|
||||
|
||||
|
|
@ -2873,6 +2872,12 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
|
|||
if (netgame || multiplayer)
|
||||
FLS = false;
|
||||
|
||||
if (grandprixinfo.gp == true)
|
||||
{
|
||||
// Too lazy to change the input value for every instance of this function.......
|
||||
pencoremode = grandprixinfo.encore;
|
||||
}
|
||||
|
||||
if (delay != 2)
|
||||
{
|
||||
UINT8 flags = 0;
|
||||
|
|
@ -3021,6 +3026,7 @@ static void Command_Map_f(void)
|
|||
INT32 newmapnum;
|
||||
boolean newresetplayers, newencoremode;
|
||||
INT32 newgametype = gametype;
|
||||
boolean startgp = false;
|
||||
|
||||
// max length of command: map map03 -gametype race -noresetplayers -force -encore
|
||||
// 1 2 3 4 5 6 7
|
||||
|
|
@ -3051,6 +3057,7 @@ static void Command_Map_f(void)
|
|||
if (COM_CheckParm("-force"))
|
||||
{
|
||||
G_SetGameModified(false, true);
|
||||
startgp = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3097,7 +3104,6 @@ static void Command_Map_f(void)
|
|||
|
||||
// new encoremode value
|
||||
// use cvar by default
|
||||
|
||||
newencoremode = (cv_kartencore.value == 1);
|
||||
|
||||
if (COM_CheckParm("-encore"))
|
||||
|
|
@ -3144,6 +3150,69 @@ static void Command_Map_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (startgp)
|
||||
{
|
||||
i = COM_CheckParm("-skill");
|
||||
|
||||
grandprixinfo.gamespeed = (cv_kartspeed.value == KARTSPEED_AUTO ? KARTSPEED_NORMAL : cv_kartspeed.value);
|
||||
grandprixinfo.masterbots = false;
|
||||
|
||||
if (i)
|
||||
{
|
||||
const UINT8 master = KARTSPEED_HARD+1;
|
||||
const char *masterstr = "Master";
|
||||
const char *skillname = COM_Argv(i+1);
|
||||
INT32 newskill = -1;
|
||||
INT32 j;
|
||||
|
||||
if (!strcasecmp(masterstr, skillname))
|
||||
{
|
||||
newskill = master;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; kartspeed_cons_t[j].strvalue; j++)
|
||||
{
|
||||
if (!strcasecmp(kartspeed_cons_t[j].strvalue, skillname))
|
||||
{
|
||||
newskill = (INT16)kartspeed_cons_t[j].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!kartspeed_cons_t[j].strvalue) // reached end of the list with no match
|
||||
{
|
||||
j = atoi(COM_Argv(i+1)); // assume they gave us a skill number, which is okay too
|
||||
if (j >= KARTSPEED_EASY && j <= master)
|
||||
newskill = (INT16)j;
|
||||
}
|
||||
}
|
||||
|
||||
if (newskill != -1)
|
||||
{
|
||||
if (newskill == master)
|
||||
{
|
||||
grandprixinfo.gamespeed = KARTSPEED_HARD;
|
||||
grandprixinfo.masterbots = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
grandprixinfo.gamespeed = newskill;
|
||||
grandprixinfo.masterbots = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grandprixinfo.encore = newencoremode;
|
||||
|
||||
grandprixinfo.gp = true;
|
||||
grandprixinfo.roundnum = 0;
|
||||
grandprixinfo.cup = NULL;
|
||||
grandprixinfo.wonround = false;
|
||||
|
||||
grandprixinfo.initalize = true;
|
||||
}
|
||||
|
||||
fromlevelselect = false;
|
||||
D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false);
|
||||
}
|
||||
|
|
@ -5167,14 +5236,16 @@ static void PointLimit_OnChange(void)
|
|||
|
||||
static void NumLaps_OnChange(void)
|
||||
{
|
||||
if (!G_RaceGametype() || (modeattacking || demo.playback))
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (server && Playing()
|
||||
&& (netgame || multiplayer)
|
||||
&& (mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|
||||
&& (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps))
|
||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|
||||
&& (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps))
|
||||
{
|
||||
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
|
||||
}
|
||||
|
||||
// Just don't be verbose
|
||||
CONS_Printf(M_GetText("Number of laps set to %d\n"), cv_numlaps.value);
|
||||
|
|
@ -5259,11 +5330,6 @@ void D_GameTypeChanged(INT32 lastgametype)
|
|||
// There will always be a server, and this only needs to be done once.
|
||||
if (server && (multiplayer || netgame))
|
||||
{
|
||||
if (gametype == GT_COMPETITION || gametype == GT_COOP)
|
||||
CV_SetValue(&cv_itemrespawn, 0);
|
||||
else if (!cv_itemrespawn.changed)
|
||||
CV_SetValue(&cv_itemrespawn, 1);
|
||||
|
||||
switch (gametype)
|
||||
{
|
||||
case GT_MATCH:
|
||||
|
|
@ -5274,8 +5340,6 @@ void D_GameTypeChanged(INT32 lastgametype)
|
|||
CV_SetValue(&cv_pointlimit, 0);
|
||||
CV_SetValue(&cv_timelimit, 120);
|
||||
}
|
||||
if (!cv_itemrespawntime.changed)
|
||||
CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally
|
||||
break;
|
||||
case GT_TAG:
|
||||
case GT_HIDEANDSEEK:
|
||||
|
|
@ -5286,8 +5350,6 @@ void D_GameTypeChanged(INT32 lastgametype)
|
|||
CV_SetValue(&cv_timelimit, 5);
|
||||
CV_SetValue(&cv_pointlimit, 0);
|
||||
}
|
||||
if (!cv_itemrespawntime.changed)
|
||||
CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally
|
||||
break;
|
||||
case GT_CTF:
|
||||
if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits
|
||||
|
|
@ -5296,17 +5358,12 @@ void D_GameTypeChanged(INT32 lastgametype)
|
|||
CV_SetValue(&cv_timelimit, 0);
|
||||
CV_SetValue(&cv_pointlimit, 5);
|
||||
}
|
||||
if (!cv_itemrespawntime.changed)
|
||||
CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!multiplayer && !netgame)
|
||||
{
|
||||
gametype = GT_RACE; // SRB2kart
|
||||
// These shouldn't matter anymore
|
||||
//CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue);
|
||||
//CV_SetValue(&cv_itemrespawn, 0);
|
||||
gametype = GT_RACE;
|
||||
}
|
||||
|
||||
// reset timelimit and pointlimit in race/coop, prevent stupid cheats
|
||||
|
|
@ -5817,14 +5874,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 (grandprixinfo.gp == false)
|
||||
{
|
||||
CONS_Printf(M_GetText("This only works in Grand Prix.\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
M_ClearMenus(true);
|
||||
|
|
@ -6501,24 +6558,35 @@ static void Command_ShowTime_f(void)
|
|||
// SRB2Kart: On change messages
|
||||
static void BaseNumLaps_OnChange(void)
|
||||
{
|
||||
if (gamestate == GS_LEVEL)
|
||||
if (K_CanChangeRules() == true)
|
||||
{
|
||||
if (cv_basenumlaps.value)
|
||||
CONS_Printf(M_GetText("Number of laps will be changed to %d next round.\n"), cv_basenumlaps.value);
|
||||
else
|
||||
CONS_Printf(M_GetText("Number of laps will be changed to map defaults next round.\n"));
|
||||
const char *str = va("%d", cv_basenumlaps.value);
|
||||
|
||||
if (cv_basenumlaps.value == 0)
|
||||
{
|
||||
str = "map defaults";
|
||||
}
|
||||
|
||||
CONS_Printf(M_GetText("Number of laps will be changed to %s next round.\n"), str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void KartFrantic_OnChange(void)
|
||||
{
|
||||
if ((boolean)cv_kartfrantic.value != franticitems && gamestate == GS_LEVEL && leveltime > starttime)
|
||||
CONS_Printf(M_GetText("Frantic items will be turned %s next round.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
CONS_Printf(M_GetText("Frantic items has been set to %s.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
|
||||
franticitems = (boolean)cv_kartfrantic.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Frantic items has been turned %s.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
|
||||
franticitems = (boolean)cv_kartfrantic.value;
|
||||
CONS_Printf(M_GetText("Frantic items will be turned %s next round.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6531,47 +6599,59 @@ static void KartSpeed_OnChange(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (G_RaceGametype())
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
if ((gamestate == GS_LEVEL && leveltime < starttime) && (cv_kartspeed.value != KARTSPEED_AUTO))
|
||||
{
|
||||
CONS_Printf(M_GetText("Game speed has been changed to \"%s\".\n"), cv_kartspeed.string);
|
||||
gamespeed = (UINT8)cv_kartspeed.value;
|
||||
}
|
||||
else if (cv_kartspeed.value != (signed)gamespeed)
|
||||
{
|
||||
CONS_Printf(M_GetText("Game speed will be changed to \"%s\" next round.\n"), cv_kartspeed.string);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (leveltime < starttime && cv_kartspeed.value != KARTSPEED_AUTO)
|
||||
{
|
||||
CONS_Printf(M_GetText("Game speed has been changed to \"%s\".\n"), cv_kartspeed.string);
|
||||
gamespeed = (UINT8)cv_kartspeed.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Game speed will be changed to \"%s\" next round.\n"), cv_kartspeed.string);
|
||||
}
|
||||
}
|
||||
|
||||
static void KartEncore_OnChange(void)
|
||||
{
|
||||
if (G_RaceGametype())
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
if ((cv_kartencore.value == 1) != encoremode && gamestate == GS_LEVEL /*&& leveltime > starttime*/)
|
||||
CONS_Printf(M_GetText("Encore Mode will be set to %s next round.\n"), cv_kartencore.string);
|
||||
else
|
||||
CONS_Printf(M_GetText("Encore Mode has been set to %s.\n"), cv_kartencore.string);
|
||||
return;
|
||||
}
|
||||
|
||||
CONS_Printf(M_GetText("Encore Mode will be set to %s next round.\n"), cv_kartencore.string);
|
||||
}
|
||||
|
||||
static void KartComeback_OnChange(void)
|
||||
{
|
||||
if (G_BattleGametype())
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
if ((boolean)cv_kartcomeback.value != comeback && gamestate == GS_LEVEL && leveltime > starttime)
|
||||
CONS_Printf(M_GetText("Karma Comeback will be turned %s next round.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off"));
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Karma Comeback has been turned %s.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off"));
|
||||
comeback = (boolean)cv_kartcomeback.value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
CONS_Printf(M_GetText("Karma Comeback has been turned %s.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off"));
|
||||
comeback = (boolean)cv_kartcomeback.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Karma Comeback will be turned %s next round.\n"), cv_kartcomeback.value ? M_GetText("on") : M_GetText("off"));
|
||||
}
|
||||
}
|
||||
|
||||
static void KartEliminateLast_OnChange(void)
|
||||
{
|
||||
if (G_RaceGametype() && cv_karteliminatelast.value)
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
CV_StealthSet(&cv_karteliminatelast, cv_karteliminatelast.defaultvalue);
|
||||
}
|
||||
|
||||
if (G_RaceGametype())
|
||||
{
|
||||
P_CheckRacers();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,10 +65,6 @@ extern consvar_t cv_usemouse2;
|
|||
extern consvar_t cv_mouse2opt;
|
||||
#endif
|
||||
|
||||
// normally in p_mobj but the .h is not read
|
||||
extern consvar_t cv_itemrespawntime;
|
||||
extern consvar_t cv_itemrespawn;
|
||||
|
||||
extern consvar_t cv_flagtime;
|
||||
extern consvar_t cv_suddendeath;
|
||||
|
||||
|
|
|
|||
|
|
@ -316,8 +316,8 @@ typedef enum
|
|||
k_stealingtimer, // You are stealing an item, this is your timer
|
||||
k_stolentimer, // You are being stolen from, this is your timer
|
||||
k_superring, // Spawn rings on top of you every tic!
|
||||
k_sneakertimer, // Duration of the Sneaker Boost itself
|
||||
k_levelbooster, // Duration of a level booster's boost (same as sneaker, but separated for boost stacking)
|
||||
k_sneakertimer, // Duration of a Sneaker Boost (from Sneakers or level boosters)
|
||||
k_numsneakers, // Number of stacked sneaker effects
|
||||
k_growshrinktimer, // > 0 = Big, < 0 = small
|
||||
k_squishedtimer, // Squished frame timer
|
||||
k_rocketsneakertimer, // Rocket Sneaker duration timer
|
||||
|
|
@ -391,9 +391,6 @@ typedef enum
|
|||
NUMKARTHUD
|
||||
} karthudtype_t;
|
||||
|
||||
// QUICKLY GET EITHER SNEAKER OR LEVEL BOOSTER SINCE THEY ARE FUNCTIONALLY IDENTICAL
|
||||
#define EITHERSNEAKER(p) (p->kartstuff[k_sneakertimer] || p->kartstuff[k_levelbooster])
|
||||
|
||||
// QUICKLY GET RING TOTAL, INCLUDING RINGS CURRENTLY IN THE PICKUP ANIMATION
|
||||
#define RINGTOTAL(p) (p->kartstuff[k_rings] + p->kartstuff[k_pickuprings])
|
||||
|
||||
|
|
@ -434,12 +431,14 @@ typedef struct respawnvars_s
|
|||
// player_t struct for all bot variables
|
||||
typedef struct botvars_s
|
||||
{
|
||||
UINT8 difficulty;
|
||||
UINT8 difficulty; // Bot's difficulty setting
|
||||
UINT8 diffincrease; // In GP: bot difficulty will increase this much next round
|
||||
boolean rival; // If true, they're the GP rival
|
||||
|
||||
tic_t itemdelay;
|
||||
tic_t itemconfirm;
|
||||
tic_t itemdelay; // Delay before using item at all
|
||||
tic_t itemconfirm; // When high enough, they will use their item
|
||||
|
||||
SINT8 turnconfirm;
|
||||
SINT8 turnconfirm; // Confirm turn direction
|
||||
} botvars_t;
|
||||
|
||||
// ========================================================================
|
||||
|
|
@ -525,6 +524,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
|
||||
|
|
|
|||
145
src/dehacked.c
145
src/dehacked.c
|
|
@ -1521,6 +1521,113 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
|||
Z_Free(s);
|
||||
}
|
||||
|
||||
static void readcupheader(MYFILE *f, cupheader_t *cup)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
char *word;
|
||||
char *word2;
|
||||
char *tmp;
|
||||
INT32 i;
|
||||
|
||||
do
|
||||
{
|
||||
if (myfgets(s, MAXLINELEN, f))
|
||||
{
|
||||
if (s[0] == '\n')
|
||||
break;
|
||||
|
||||
// First remove trailing newline, if there is one
|
||||
tmp = strchr(s, '\n');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
|
||||
tmp = strchr(s, '#');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
if (s == tmp)
|
||||
continue; // Skip comment lines, but don't break.
|
||||
|
||||
// Set / reset word, because some things (Lua.) move it
|
||||
word = s;
|
||||
|
||||
// Get the part before the " = "
|
||||
tmp = strchr(s, '=');
|
||||
if (tmp)
|
||||
*(tmp-1) = '\0';
|
||||
else
|
||||
break;
|
||||
strupr(word);
|
||||
|
||||
// Now get the part after
|
||||
word2 = tmp += 2;
|
||||
i = atoi(word2); // used for numerical settings
|
||||
strupr(word2);
|
||||
|
||||
if (fastcmp(word, "ICON"))
|
||||
{
|
||||
deh_strlcpy(cup->icon, word2,
|
||||
sizeof(cup->icon), va("%s Cup: icon", cup->name));
|
||||
}
|
||||
else if (fastcmp(word, "LEVELLIST"))
|
||||
{
|
||||
cup->numlevels = 0;
|
||||
|
||||
tmp = strtok(word2,",");
|
||||
do {
|
||||
INT32 map = atoi(tmp);
|
||||
|
||||
if (tmp[0] >= 'A' && tmp[0] <= 'Z' && tmp[2] == '\0')
|
||||
map = M_MapNumber(tmp[0], tmp[1]);
|
||||
|
||||
if (!map)
|
||||
break;
|
||||
|
||||
if (cup->numlevels >= MAXLEVELLIST)
|
||||
{
|
||||
deh_warning("%s Cup: reached max levellist (%d)\n", cup->name, MAXLEVELLIST);
|
||||
break;
|
||||
}
|
||||
|
||||
cup->levellist[cup->numlevels] = map - 1;
|
||||
cup->numlevels++;
|
||||
} while((tmp = strtok(NULL,",")) != NULL);
|
||||
}
|
||||
else if (fastcmp(word, "BONUSGAME"))
|
||||
{
|
||||
// Convert to map number
|
||||
if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0')
|
||||
i = M_MapNumber(word2[0], word2[1]);
|
||||
cup->bonusgame = (INT16)i - 1;
|
||||
}
|
||||
else if (fastcmp(word, "SPECIALSTAGE"))
|
||||
{
|
||||
// Convert to map number
|
||||
if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0')
|
||||
i = M_MapNumber(word2[0], word2[1]);
|
||||
cup->specialstage = (INT16)i - 1;
|
||||
}
|
||||
else if (fastcmp(word, "EMERALDNUM"))
|
||||
{
|
||||
if (i >= 0 && i <= 14)
|
||||
cup->emeraldnum = (UINT8)i;
|
||||
else
|
||||
deh_warning("%s Cup: invalid emerald number %d", cup->name, i);
|
||||
}
|
||||
else if (fastcmp(word, "UNLOCKABLE"))
|
||||
{
|
||||
if (i >= 0 && i <= MAXUNLOCKABLES) // 0 for no unlock required, anything else requires something
|
||||
cup->unlockrequired = (SINT8)i - 1;
|
||||
else
|
||||
deh_warning("%s Cup: invalid unlockable number %d", cup->name, i);
|
||||
}
|
||||
else
|
||||
deh_warning("%s Cup: unknown word '%s'", cup->name, word);
|
||||
}
|
||||
} while (!myfeof(f)); // finish when the line is empty
|
||||
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
|
||||
{
|
||||
char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
|
@ -3669,6 +3776,42 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
|
|||
}
|
||||
DEH_WriteUndoline(word, word2, UNDO_HEADER);
|
||||
}
|
||||
else if (fastcmp(word, "CUP"))
|
||||
{
|
||||
cupheader_t *cup = kartcupheaders;
|
||||
cupheader_t *prev = NULL;
|
||||
|
||||
while (cup)
|
||||
{
|
||||
if (fastcmp(cup->name, word2))
|
||||
{
|
||||
// mark as a major mod if it replaces an already-existing cup
|
||||
G_SetGameModified(multiplayer, true);
|
||||
break;
|
||||
}
|
||||
|
||||
prev = cup;
|
||||
cup = cup->next;
|
||||
}
|
||||
|
||||
// Nothing found, add to the end.
|
||||
if (!cup)
|
||||
{
|
||||
cup = Z_Calloc(sizeof (cupheader_t), PU_STATIC, NULL);
|
||||
cup->id = numkartcupheaders;
|
||||
deh_strlcpy(cup->name, word2,
|
||||
sizeof(cup->name), va("Cup header %s: name", word2));
|
||||
if (prev != NULL)
|
||||
prev->next = cup;
|
||||
if (kartcupheaders == NULL)
|
||||
kartcupheaders = cup;
|
||||
numkartcupheaders++;
|
||||
CONS_Printf("Added cup %d ('%s')\n", cup->id, cup->name);
|
||||
}
|
||||
|
||||
readcupheader(f, cup);
|
||||
DEH_WriteUndoline(word, word2, UNDO_HEADER);
|
||||
}
|
||||
else if (fastcmp(word, "CUTSCENE"))
|
||||
{
|
||||
if (i > 0 && i < 129)
|
||||
|
|
@ -8691,7 +8834,7 @@ static const char *const KARTSTUFF_LIST[] = {
|
|||
"STOLENTIMER",
|
||||
"SUPERRING",
|
||||
"SNEAKERTIMER",
|
||||
"LEVELBOOSTER",
|
||||
"NUMSNEAKERS",
|
||||
"GROWSHRINKTIMER",
|
||||
"SQUISHEDTIMER",
|
||||
"ROCKETSNEAKERTIMER",
|
||||
|
|
|
|||
|
|
@ -325,6 +325,27 @@ typedef struct
|
|||
|
||||
extern mapheader_t* mapheaderinfo[NUMMAPS];
|
||||
|
||||
// This could support more, but is that a good idea?
|
||||
// Keep in mind that it may encourage people making overly long cups just because they "can", and would be a waste of memory.
|
||||
#define MAXLEVELLIST 5
|
||||
|
||||
typedef struct cupheader_s
|
||||
{
|
||||
UINT16 id; ///< Cup ID
|
||||
char name[15]; ///< Cup title (14 chars)
|
||||
char icon[9]; ///< Name of the icon patch
|
||||
INT16 levellist[MAXLEVELLIST]; ///< List of levels that belong to this cup
|
||||
UINT8 numlevels; ///< Number of levels defined in levellist
|
||||
INT16 bonusgame; ///< Map number to use for bonus game
|
||||
INT16 specialstage; ///< Map number to use for special stage
|
||||
UINT8 emeraldnum; ///< ID of Emerald to use for special stage (1-7 for Chaos Emeralds, 8-14 for Super Emeralds, 0 for no emerald)
|
||||
SINT8 unlockrequired; ///< An unlockable is required to select this cup. -1 for no unlocking required.
|
||||
struct cupheader_s *next; ///< Next cup in linked list
|
||||
} cupheader_t;
|
||||
|
||||
extern cupheader_t *kartcupheaders; // Start of cup linked list
|
||||
extern UINT16 numkartcupheaders;
|
||||
|
||||
enum TypeOfLevel
|
||||
{
|
||||
TOL_SP = 0x01, ///< Single Player
|
||||
|
|
|
|||
77
src/font.c
Normal file
77
src/font.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1999-2018 by Sonic Team Junior.
|
||||
// Copyright (C) 2019 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 font.c
|
||||
/// \brief Font setup
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "font.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
font_t fontv[MAX_FONTS];
|
||||
int fontc;
|
||||
|
||||
static void
|
||||
FontCache (font_t *fnt)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
c = fnt->start;
|
||||
for (i = 0; i < fnt->size; ++i, ++c)
|
||||
{
|
||||
fnt->font[i] = HU_CachePatch(
|
||||
"%s%.*d",
|
||||
fnt->prefix,
|
||||
fnt->digits,
|
||||
c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Font_Load (void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < fontc; ++i)
|
||||
{
|
||||
FontCache(&fontv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Font_DumbRegister (const font_t *sfnt)
|
||||
{
|
||||
font_t *fnt;
|
||||
|
||||
if (fontc == MAX_FONTS)
|
||||
return -1;
|
||||
|
||||
fnt = &fontv[fontc];
|
||||
|
||||
memcpy(fnt, sfnt, sizeof (font_t));
|
||||
|
||||
if (!( fnt->font = ZZ_Alloc(sfnt->size * sizeof (patch_t *)) ))
|
||||
return -1;
|
||||
|
||||
return fontc++;
|
||||
}
|
||||
|
||||
int
|
||||
Font_Register (const font_t *sfnt)
|
||||
{
|
||||
int d;
|
||||
|
||||
d = Font_DumbRegister(sfnt);
|
||||
|
||||
if (d >= 0)
|
||||
FontCache(&fontv[d]);
|
||||
|
||||
return d;
|
||||
}
|
||||
49
src/font.h
Normal file
49
src/font.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1999-2018 by Sonic Team Junior.
|
||||
// Copyright (C) 2019 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 font.h
|
||||
/// \brief Font setup
|
||||
|
||||
#ifndef __FONT_H__
|
||||
#define __FONT_H__
|
||||
|
||||
#define MAX_FONTS 32
|
||||
|
||||
typedef struct font font_t;
|
||||
|
||||
struct font
|
||||
{
|
||||
patch_t **font;
|
||||
|
||||
UINT8 start;
|
||||
UINT8 size;
|
||||
|
||||
char prefix[8];/* 7 used at most */
|
||||
unsigned digits : 2;
|
||||
};
|
||||
|
||||
extern font_t fontv[MAX_FONTS];
|
||||
extern int fontc;
|
||||
|
||||
/*
|
||||
Reloads already registered fonts.
|
||||
*/
|
||||
void Font_Load (void);
|
||||
|
||||
/*
|
||||
Registers and loads a new font.
|
||||
*/
|
||||
int Font_Register (const font_t *);
|
||||
|
||||
/*
|
||||
Register a new font, but do not load it yet.
|
||||
*/
|
||||
int Font_DumbRegister (const font_t *);
|
||||
|
||||
#endif
|
||||
298
src/g_game.c
298
src/g_game.c
|
|
@ -54,6 +54,7 @@
|
|||
#include "k_pwrlv.h"
|
||||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
gameaction_t gameaction;
|
||||
gamestate_t gamestate = GS_NULL;
|
||||
|
|
@ -170,6 +171,10 @@ struct quake quake;
|
|||
// Map Header Information
|
||||
mapheader_t* mapheaderinfo[NUMMAPS] = {NULL};
|
||||
|
||||
// Kart cup definitions
|
||||
cupheader_t *kartcupheaders = NULL;
|
||||
UINT16 numkartcupheaders = 0;
|
||||
|
||||
static boolean exitgame = false;
|
||||
static boolean retrying = false;
|
||||
|
||||
|
|
@ -1430,7 +1435,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
{
|
||||
// forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward.
|
||||
axis = JoyAxis(AXISMOVE, ssplayer);
|
||||
if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || EITHERSNEAKER(player))
|
||||
if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer])
|
||||
{
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
forward = forwardmove[1]; // 50
|
||||
|
|
@ -2352,17 +2357,19 @@ 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;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
K_PlayerLoseLife(&players[i]);
|
||||
}
|
||||
}
|
||||
|
||||
G_DoReborn(consoleplayer);*/
|
||||
|
||||
D_MapChange(gamemap, gametype, (cv_kartencore.value == 1), true, 1, false, false);
|
||||
D_MapChange(gamemap, gametype, (cv_kartencore.value == 1), false, 1, false, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -2394,16 +2401,18 @@ void G_Ticker(boolean run)
|
|||
|
||||
if (playeringame[i])
|
||||
{
|
||||
if (K_PlayerUsesBotMovement(&players[i]))
|
||||
G_CopyTiccmd(cmd, &netcmds[buf][i], 1);
|
||||
|
||||
// Use the leveltime sent in the player's ticcmd to determine control lag
|
||||
if (modeattacking || K_PlayerUsesBotMovement(&players[i]))
|
||||
{
|
||||
K_BuildBotTiccmd(&players[i], cmd);
|
||||
// Never has lag
|
||||
cmd->latency = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
G_CopyTiccmd(cmd, &netcmds[buf][i], 1);
|
||||
// Use the leveltime sent in the player's ticcmd to determine control lag
|
||||
cmd->latency = modeattacking ? 0 : min(((leveltime & 0xFF) - cmd->latency) & 0xFF, MAXPREDICTTICS-1); //@TODO add a cvar to allow setting this max
|
||||
//@TODO add a cvar to allow setting this max
|
||||
cmd->latency = min(((leveltime & 0xFF) - cmd->latency) & 0xFF, MAXPREDICTTICS-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2564,6 +2573,7 @@ void G_PlayerReborn(INT32 player)
|
|||
player_t *p;
|
||||
INT32 score, marescore;
|
||||
INT32 lives;
|
||||
boolean lostlife;
|
||||
INT32 continues;
|
||||
// SRB2kart
|
||||
UINT8 kartspeed;
|
||||
|
|
@ -2589,7 +2599,10 @@ void G_PlayerReborn(INT32 player)
|
|||
boolean spectator;
|
||||
boolean bot;
|
||||
UINT8 botdifficulty;
|
||||
UINT8 botdiffincrease;
|
||||
boolean botrival;
|
||||
SINT8 pity;
|
||||
SINT8 xtralife;
|
||||
|
||||
// SRB2kart
|
||||
respawnvars_t respawn;
|
||||
|
|
@ -2607,6 +2620,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;
|
||||
|
|
@ -2640,7 +2654,10 @@ void G_PlayerReborn(INT32 player)
|
|||
mare = players[player].mare;
|
||||
bot = players[player].bot;
|
||||
botdifficulty = players[player].botvars.difficulty;
|
||||
botdiffincrease = players[player].botvars.diffincrease;
|
||||
botrival = players[player].botvars.rival;
|
||||
pity = players[player].pity;
|
||||
xtralife = players[player].xtralife;
|
||||
|
||||
// SRB2kart
|
||||
if (leveltime <= starttime)
|
||||
|
|
@ -2691,6 +2708,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;
|
||||
|
|
@ -2717,7 +2735,10 @@ void G_PlayerReborn(INT32 player)
|
|||
p->mare = mare;
|
||||
p->bot = bot;
|
||||
p->botvars.difficulty = botdifficulty;
|
||||
p->botvars.diffincrease = botdiffincrease;
|
||||
p->botvars.rival = botrival;
|
||||
p->pity = pity;
|
||||
p->xtralife = xtralife;
|
||||
|
||||
// SRB2kart
|
||||
p->kartstuff[k_itemroulette] = itemroulette;
|
||||
|
|
@ -3218,6 +3239,47 @@ void G_ExitLevel(void)
|
|||
{
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
if (grandprixinfo.gp == true && 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;
|
||||
|
||||
|
|
@ -3293,18 +3355,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.gp == true) // 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
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -3640,8 +3699,7 @@ void G_AddMapToBuffer(INT16 map)
|
|||
static void G_DoCompleted(void)
|
||||
{
|
||||
INT32 i, j = 0;
|
||||
boolean gottoken = false;
|
||||
SINT8 powertype = PWRLV_DISABLED;
|
||||
SINT8 powertype = K_UsingPowerLevels();
|
||||
|
||||
tokenlist = 0; // Reset the list
|
||||
|
||||
|
|
@ -3658,10 +3716,21 @@ static void G_DoCompleted(void)
|
|||
// SRB2Kart: exitlevel shouldn't get you the points
|
||||
if (!players[i].exiting && !(players[i].pflags & PF_TIMEOVER))
|
||||
{
|
||||
players[i].pflags |= PF_TIMEOVER;
|
||||
if (P_IsLocalPlayer(&players[i]))
|
||||
j++;
|
||||
if (players[i].bot)
|
||||
{
|
||||
K_FakeBotResults(&players[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
players[i].pflags |= PF_TIMEOVER;
|
||||
|
||||
if (P_IsLocalPlayer(&players[i]))
|
||||
{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
G_PlayerFinishLevel(i); // take away cards and stuff
|
||||
}
|
||||
|
||||
|
|
@ -3681,11 +3750,33 @@ static void G_DoCompleted(void)
|
|||
// go to next level
|
||||
// nextmap is 0-based, unlike gamemap
|
||||
if (nextmapoverride != 0)
|
||||
{
|
||||
nextmap = (INT16)(nextmapoverride-1);
|
||||
else if (mapheaderinfo[gamemap-1]->nextlevel == 1101) // SRB2Kart: !!! WHENEVER WE GET GRAND PRIX, GO TO AWARDS MAP INSTEAD !!!
|
||||
nextmap = (INT16)(mapheaderinfo[gamemap] ? gamemap : (spstage_start-1)); // (gamemap-1)+1 == gamemap :V
|
||||
}
|
||||
else if (grandprixinfo.gp == true)
|
||||
{
|
||||
if (grandprixinfo.roundnum == 0 || grandprixinfo.cup == NULL) // Single session
|
||||
{
|
||||
nextmap = prevmap; // Same map
|
||||
}
|
||||
else
|
||||
{
|
||||
if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels) // On final map
|
||||
{
|
||||
nextmap = 1101; // ceremonymap
|
||||
}
|
||||
else
|
||||
{
|
||||
// Proceed to next map
|
||||
nextmap = grandprixinfo.cup->levellist[grandprixinfo.roundnum];
|
||||
grandprixinfo.roundnum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1);
|
||||
}
|
||||
|
||||
// Remember last map for when you come out of the special stage.
|
||||
if (!G_IsSpecialStage(gamemap))
|
||||
|
|
@ -3695,8 +3786,7 @@ static void G_DoCompleted(void)
|
|||
// a map of the proper gametype -- skip levels that don't support
|
||||
// the current gametype. (Helps avoid playing boss levels in Race,
|
||||
// for instance).
|
||||
if (!token && !G_IsSpecialStage(gamemap) && !modeattacking
|
||||
&& (nextmap >= 0 && nextmap < NUMMAPS))
|
||||
if (!modeattacking && grandprixinfo.gp == false && (nextmap >= 0 && nextmap < NUMMAPS))
|
||||
{
|
||||
register INT16 cm = nextmap;
|
||||
INT16 tolflag = G_TOLFlag(gametype);
|
||||
|
|
@ -3740,44 +3830,18 @@ static void G_DoCompleted(void)
|
|||
if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1102-1)
|
||||
I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
|
||||
|
||||
// wrap around in race
|
||||
if (nextmap >= 1100-1 && nextmap <= 1102-1 && G_RaceGametype())
|
||||
nextmap = (INT16)(spstage_start-1);
|
||||
|
||||
if (gametype == GT_COOP && token)
|
||||
{
|
||||
token--;
|
||||
gottoken = true;
|
||||
|
||||
if (!(emeralds & EMERALD1))
|
||||
nextmap = (INT16)(sstage_start - 1); // Special Stage 1
|
||||
else if (!(emeralds & EMERALD2))
|
||||
nextmap = (INT16)(sstage_start); // Special Stage 2
|
||||
else if (!(emeralds & EMERALD3))
|
||||
nextmap = (INT16)(sstage_start + 1); // Special Stage 3
|
||||
else if (!(emeralds & EMERALD4))
|
||||
nextmap = (INT16)(sstage_start + 2); // Special Stage 4
|
||||
else if (!(emeralds & EMERALD5))
|
||||
nextmap = (INT16)(sstage_start + 3); // Special Stage 5
|
||||
else if (!(emeralds & EMERALD6))
|
||||
nextmap = (INT16)(sstage_start + 4); // Special Stage 6
|
||||
else if (!(emeralds & EMERALD7))
|
||||
nextmap = (INT16)(sstage_start + 5); // Special Stage 7
|
||||
else
|
||||
gottoken = false;
|
||||
}
|
||||
|
||||
if (G_IsSpecialStage(gamemap) && !gottoken)
|
||||
nextmap = lastmap; // Exiting from a special stage? Go back to the game. Tails 08-11-2001
|
||||
|
||||
automapactive = false;
|
||||
|
||||
if (gametype != GT_COOP)
|
||||
{
|
||||
if (cv_advancemap.value == 0) // Stay on same map.
|
||||
{
|
||||
nextmap = prevmap;
|
||||
}
|
||||
else if (cv_advancemap.value == 2) // Go to random map.
|
||||
{
|
||||
nextmap = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// We are committed to this map now.
|
||||
|
|
@ -3787,14 +3851,6 @@ static void G_DoCompleted(void)
|
|||
P_AllocMapHeader(nextmap);
|
||||
|
||||
// Set up power level gametype scrambles
|
||||
if (netgame && cv_kartusepwrlv.value)
|
||||
{
|
||||
if (G_RaceGametype())
|
||||
powertype = PWRLV_RACE;
|
||||
else if (G_BattleGametype())
|
||||
powertype = PWRLV_BATTLE;
|
||||
}
|
||||
|
||||
K_SetPowerLevelScrambles(powertype);
|
||||
|
||||
demointermission:
|
||||
|
|
@ -3854,7 +3910,7 @@ void G_NextLevel(void)
|
|||
{
|
||||
if (gamestate != GS_VOTING)
|
||||
{
|
||||
if ((cv_advancemap.value == 3) && !modeattacking && !skipstats && (multiplayer || netgame))
|
||||
if ((cv_advancemap.value == 3) && grandprixinfo.gp == false && !modeattacking && !skipstats && (multiplayer || netgame))
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -3951,7 +4007,7 @@ static void G_DoContinued(void)
|
|||
token = 0;
|
||||
|
||||
// Reset # of lives
|
||||
pl->lives = (ultimatemode) ? 1 : 3;
|
||||
pl->lives = 3;
|
||||
|
||||
D_MapChange(gamemap, gametype, false, false, 0, false, false);
|
||||
|
||||
|
|
@ -4520,7 +4576,7 @@ void G_SaveGame(UINT32 savegameslot)
|
|||
void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar, UINT8 ssplayers, boolean FLS)
|
||||
{
|
||||
INT32 i;
|
||||
UINT8 color = 0;
|
||||
//UINT8 color = 0;
|
||||
paused = false;
|
||||
|
||||
if (demo.playback)
|
||||
|
|
@ -4540,23 +4596,20 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar
|
|||
// this leave the actual game if needed
|
||||
SV_StartSinglePlayerServer();
|
||||
|
||||
if (savedata.lives > 0)
|
||||
{
|
||||
color = savedata.skincolor;
|
||||
}
|
||||
else if (splitscreen != ssplayers)
|
||||
if (splitscreen != ssplayers)
|
||||
{
|
||||
splitscreen = ssplayers;
|
||||
SplitScreen_OnChange();
|
||||
}
|
||||
|
||||
if (!color && !modeattacking)
|
||||
color = skins[pickedchar].prefcolor;
|
||||
//if (!color)
|
||||
//color = skins[pickedchar].prefcolor;
|
||||
|
||||
SetPlayerSkinByNum(consoleplayer, pickedchar);
|
||||
CV_StealthSet(&cv_skin, skins[pickedchar].name);
|
||||
|
||||
if (color)
|
||||
CV_StealthSetValue(&cv_playercolor, color);
|
||||
//if (color)
|
||||
//CV_StealthSetValue(&cv_playercolor, color);
|
||||
|
||||
if (mapname)
|
||||
D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pencoremode, true, 1, false, FLS);
|
||||
|
|
@ -4585,63 +4638,40 @@ 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].starpostnum = 0;
|
||||
memset(&players[i].respawn, 0, sizeof (players[i].respawn));
|
||||
|
||||
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].starpostnum = 0;
|
||||
memset(&players[i].respawn, 0, sizeof (players[i].respawn));
|
||||
|
||||
#if 0
|
||||
if (netgame || multiplayer)
|
||||
{
|
||||
players[i].lives = cv_startinglives.value;
|
||||
players[i].continues = 0;
|
||||
}
|
||||
else if (pultmode)
|
||||
{
|
||||
players[i].lives = 1;
|
||||
players[i].continues = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
players[i].lives = 3;
|
||||
players[i].continues = 1;
|
||||
}
|
||||
|
||||
players[i].lives = 3;
|
||||
players[i].xtralife = 0;
|
||||
#else
|
||||
players[i].lives = 1; // SRB2Kart
|
||||
#endif
|
||||
|
||||
// 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].score = 0;
|
||||
}
|
||||
players[i].totalring = 0;
|
||||
players[i].score = 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);
|
||||
}
|
||||
|
||||
// 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....
|
||||
|
|
@ -5156,7 +5186,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
|||
|| (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
|
||||
&& players[displayplayers[0]].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout
|
||||
localangle[0] += (cmd->angleturn<<16);
|
||||
|
||||
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
|
||||
|
|
@ -8152,7 +8182,7 @@ boolean G_DemoTitleResponder(event_t *ev)
|
|||
return true;
|
||||
}
|
||||
|
||||
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART])
|
||||
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && fontv[HU_FONT].font[ch-HU_FONTSTART])
|
||||
|| ch == ' ') // Allow spaces, of course
|
||||
{
|
||||
len = strlen(demo.titlename);
|
||||
|
|
|
|||
383
src/hu_stuff.c
383
src/hu_stuff.c
|
|
@ -14,6 +14,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "byteptr.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "font.h"
|
||||
|
||||
#include "m_menu.h" // gametype_cons_t
|
||||
#include "m_cond.h" // emblems
|
||||
|
|
@ -53,6 +54,7 @@
|
|||
|
||||
#include "s_sound.h" // song credits
|
||||
#include "k_kart.h"
|
||||
#include "k_color.h"
|
||||
|
||||
// coords are scaled
|
||||
#define HU_INPUTX 0
|
||||
|
|
@ -64,19 +66,9 @@
|
|||
//-------------------------------------------
|
||||
// heads up font
|
||||
//-------------------------------------------
|
||||
patch_t *hu_font[HU_FONTSIZE];
|
||||
patch_t *kart_font[KART_FONTSIZE]; // SRB2kart
|
||||
patch_t *tny_font[HU_FONTSIZE];
|
||||
patch_t *tallnum[10]; // 0-9
|
||||
patch_t *nightsnum[10]; // 0-9
|
||||
|
||||
// Level title and credits fonts
|
||||
patch_t *lt_font[LT_FONTSIZE];
|
||||
patch_t *cred_font[CRED_FONTSIZE];
|
||||
|
||||
// ping font
|
||||
// Note: I'd like to adress that at this point we might *REALLY* want to work towards a common drawString function that can take any font we want because this is really turning into a MESS. :V -Lat'
|
||||
patch_t *pingnum[10];
|
||||
patch_t *pinggfx[5]; // small ping graphic
|
||||
patch_t *mping[5]; // smaller ping graphic
|
||||
|
||||
|
|
@ -188,137 +180,53 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum);
|
|||
|
||||
void HU_LoadGraphics(void)
|
||||
{
|
||||
char buffer[9];
|
||||
INT32 i, j;
|
||||
INT32 i;
|
||||
|
||||
if (dedicated)
|
||||
return;
|
||||
|
||||
j = HU_FONTSTART;
|
||||
for (i = 0; i < HU_FONTSIZE; i++, j++)
|
||||
{
|
||||
// cache the heads-up font for entire game execution
|
||||
sprintf(buffer, "STCFN%.3d", j);
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
hu_font[i] = NULL;
|
||||
else
|
||||
hu_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
|
||||
// tiny version of the heads-up font
|
||||
sprintf(buffer, "TNYFN%.3d", j);
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
tny_font[i] = NULL;
|
||||
else
|
||||
tny_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// cache the level title font for entire game execution
|
||||
lt_font[0] = (patch_t *)W_CachePatchName("LTFNT039", PU_HUDGFX); /// \note fake start hack
|
||||
|
||||
// Number support
|
||||
lt_font[9] = (patch_t *)W_CachePatchName("LTFNT048", PU_HUDGFX);
|
||||
lt_font[10] = (patch_t *)W_CachePatchName("LTFNT049", PU_HUDGFX);
|
||||
lt_font[11] = (patch_t *)W_CachePatchName("LTFNT050", PU_HUDGFX);
|
||||
lt_font[12] = (patch_t *)W_CachePatchName("LTFNT051", PU_HUDGFX);
|
||||
lt_font[13] = (patch_t *)W_CachePatchName("LTFNT052", PU_HUDGFX);
|
||||
lt_font[14] = (patch_t *)W_CachePatchName("LTFNT053", PU_HUDGFX);
|
||||
lt_font[15] = (patch_t *)W_CachePatchName("LTFNT054", PU_HUDGFX);
|
||||
lt_font[16] = (patch_t *)W_CachePatchName("LTFNT055", PU_HUDGFX);
|
||||
lt_font[17] = (patch_t *)W_CachePatchName("LTFNT056", PU_HUDGFX);
|
||||
lt_font[18] = (patch_t *)W_CachePatchName("LTFNT057", PU_HUDGFX);
|
||||
|
||||
// SRB2kart
|
||||
j = KART_FONTSTART;
|
||||
for (i = 0; i < KART_FONTSIZE; i++, j++)
|
||||
{
|
||||
// cache the heads-up font for entire game execution
|
||||
sprintf(buffer, "MKFNT%.3d", j);
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
kart_font[i] = NULL;
|
||||
else
|
||||
kart_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
//
|
||||
|
||||
j = LT_FONTSTART;
|
||||
for (i = 0; i < LT_FONTSIZE; i++)
|
||||
{
|
||||
sprintf(buffer, "LTFNT%.3d", j);
|
||||
j++;
|
||||
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
lt_font[i] = NULL;
|
||||
else
|
||||
lt_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// cache the credits font for entire game execution (why not?)
|
||||
j = CRED_FONTSTART;
|
||||
for (i = 0; i < CRED_FONTSIZE; i++)
|
||||
{
|
||||
sprintf(buffer, "CRFNT%.3d", j);
|
||||
j++;
|
||||
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
cred_font[i] = NULL;
|
||||
else
|
||||
cred_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
//cache numbers too!
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
sprintf(buffer, "STTNUM%d", i);
|
||||
tallnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
sprintf(buffer, "NGTNUM%d", i);
|
||||
nightsnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
|
||||
sprintf(buffer, "PINGN%d", i);
|
||||
pingnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
Font_Load();
|
||||
|
||||
// minus for negative tallnums
|
||||
tallminus = (patch_t *)W_CachePatchName("STTMINUS", PU_HUDGFX);
|
||||
tallminus = HU_CachePatch("STTMINUS");
|
||||
|
||||
// cache the crosshairs, don't bother to know which one is being used,
|
||||
// just cache all 3, they're so small anyway.
|
||||
for (i = 0; i < HU_CROSSHAIRS; i++)
|
||||
{
|
||||
sprintf(buffer, "CROSHAI%c", '1'+i);
|
||||
crosshair[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
crosshair[i] = HU_CachePatch("CROSHAI%c", '1'+i);
|
||||
}
|
||||
|
||||
emblemicon = W_CachePatchName("EMBLICON", PU_HUDGFX);
|
||||
tokenicon = W_CachePatchName("TOKNICON", PU_HUDGFX);
|
||||
emblemicon = HU_CachePatch("EMBLICON");
|
||||
tokenicon = HU_CachePatch("TOKNICON");
|
||||
|
||||
emeraldpics[0] = W_CachePatchName("CHAOS1", PU_HUDGFX);
|
||||
emeraldpics[1] = W_CachePatchName("CHAOS2", PU_HUDGFX);
|
||||
emeraldpics[2] = W_CachePatchName("CHAOS3", PU_HUDGFX);
|
||||
emeraldpics[3] = W_CachePatchName("CHAOS4", PU_HUDGFX);
|
||||
emeraldpics[4] = W_CachePatchName("CHAOS5", PU_HUDGFX);
|
||||
emeraldpics[5] = W_CachePatchName("CHAOS6", PU_HUDGFX);
|
||||
emeraldpics[6] = W_CachePatchName("CHAOS7", PU_HUDGFX);
|
||||
tinyemeraldpics[0] = W_CachePatchName("TEMER1", PU_HUDGFX);
|
||||
tinyemeraldpics[1] = W_CachePatchName("TEMER2", PU_HUDGFX);
|
||||
tinyemeraldpics[2] = W_CachePatchName("TEMER3", PU_HUDGFX);
|
||||
tinyemeraldpics[3] = W_CachePatchName("TEMER4", PU_HUDGFX);
|
||||
tinyemeraldpics[4] = W_CachePatchName("TEMER5", PU_HUDGFX);
|
||||
tinyemeraldpics[5] = W_CachePatchName("TEMER6", PU_HUDGFX);
|
||||
tinyemeraldpics[6] = W_CachePatchName("TEMER7", PU_HUDGFX);
|
||||
emeraldpics[0] = HU_CachePatch("CHAOS1");
|
||||
emeraldpics[1] = HU_CachePatch("CHAOS2");
|
||||
emeraldpics[2] = HU_CachePatch("CHAOS3");
|
||||
emeraldpics[3] = HU_CachePatch("CHAOS4");
|
||||
emeraldpics[4] = HU_CachePatch("CHAOS5");
|
||||
emeraldpics[5] = HU_CachePatch("CHAOS6");
|
||||
emeraldpics[6] = HU_CachePatch("CHAOS7");
|
||||
tinyemeraldpics[0] = HU_CachePatch("TEMER1");
|
||||
tinyemeraldpics[1] = HU_CachePatch("TEMER2");
|
||||
tinyemeraldpics[2] = HU_CachePatch("TEMER3");
|
||||
tinyemeraldpics[3] = HU_CachePatch("TEMER4");
|
||||
tinyemeraldpics[4] = HU_CachePatch("TEMER5");
|
||||
tinyemeraldpics[5] = HU_CachePatch("TEMER6");
|
||||
tinyemeraldpics[6] = HU_CachePatch("TEMER7");
|
||||
|
||||
songcreditbg = W_CachePatchName("K_SONGCR", PU_HUDGFX);
|
||||
songcreditbg = HU_CachePatch("K_SONGCR");
|
||||
|
||||
// cache ping gfx:
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
sprintf(buffer, "PINGGFX%d", i+1);
|
||||
pinggfx[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
sprintf(buffer, "MPING%d", i+1);
|
||||
mping[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
pinggfx[i] = HU_CachePatch("PINGGFX%d", i+1);
|
||||
mping[i] = HU_CachePatch("MPING%d", i+1);
|
||||
}
|
||||
|
||||
// fps stuff
|
||||
framecounter = W_CachePatchName("FRAMER", PU_HUDGFX);
|
||||
frameslash = W_CachePatchName("FRAMESL", PU_HUDGFX);;
|
||||
framecounter = HU_CachePatch("FRAMER");
|
||||
frameslash = HU_CachePatch("FRAMESL");;
|
||||
}
|
||||
|
||||
// Initialise Heads up
|
||||
|
|
@ -326,6 +234,8 @@ void HU_LoadGraphics(void)
|
|||
//
|
||||
void HU_Init(void)
|
||||
{
|
||||
font_t font;
|
||||
|
||||
#ifndef NONET
|
||||
COM_AddCommand("say", Command_Say_f);
|
||||
COM_AddCommand("sayto", Command_Sayto_f);
|
||||
|
|
@ -337,9 +247,78 @@ void HU_Init(void)
|
|||
// set shift translation table
|
||||
shiftxform = english_shiftxform;
|
||||
|
||||
/*
|
||||
Setup fonts
|
||||
*/
|
||||
|
||||
if (!dedicated)
|
||||
{
|
||||
#define DIM( s, n ) ( font.start = s, font.size = n )
|
||||
#define ADIM( name ) DIM (name ## _FONTSTART, name ## _FONTSIZE)
|
||||
#define PR( s ) strcpy(font.prefix, s)
|
||||
#define DIG( n ) ( font.digits = n )
|
||||
#define REG Font_DumbRegister(&font)
|
||||
|
||||
DIG (3);
|
||||
|
||||
ADIM (HU);
|
||||
|
||||
PR ("STCFN");
|
||||
REG;
|
||||
|
||||
PR ("TNYFN");
|
||||
REG;
|
||||
|
||||
ADIM (KART);
|
||||
PR ("MKFNT");
|
||||
REG;
|
||||
|
||||
ADIM (LT);
|
||||
PR ("LTFNT");
|
||||
REG;
|
||||
|
||||
ADIM (CRED);
|
||||
PR ("CRFNT");
|
||||
REG;
|
||||
|
||||
DIG (1);
|
||||
|
||||
DIM (0, 10);
|
||||
|
||||
PR ("STTNUM");
|
||||
REG;
|
||||
|
||||
PR ("NGTNUM");
|
||||
REG;
|
||||
|
||||
PR ("PINGN");
|
||||
REG;
|
||||
|
||||
#undef REG
|
||||
#undef DIG
|
||||
#undef PR
|
||||
#undef ADMIN
|
||||
#undef DIM
|
||||
}
|
||||
|
||||
HU_LoadGraphics();
|
||||
}
|
||||
|
||||
patch_t *HU_CachePatch(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[9];
|
||||
|
||||
va_start (ap, format);
|
||||
vsprintf(buffer, format, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
return NULL;
|
||||
else
|
||||
return (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
static inline void HU_Stop(void)
|
||||
{
|
||||
headsupactive = false;
|
||||
|
|
@ -761,168 +740,27 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt2, *textcolor = "\x80";
|
||||
char *tempchar = NULL;
|
||||
|
||||
// player is a spectator?
|
||||
if (players[playernum].spectator)
|
||||
if (players[playernum].spectator)
|
||||
{
|
||||
cstart = "\x86"; // grey name
|
||||
textcolor = "\x86";
|
||||
// grey text
|
||||
cstart = textcolor = "\x86";
|
||||
}
|
||||
else if (target == -1) // say team
|
||||
{
|
||||
if (players[playernum].ctfteam == 1) // red
|
||||
if (players[playernum].ctfteam == 1)
|
||||
{
|
||||
cstart = "\x85";
|
||||
textcolor = "\x85";
|
||||
// red text
|
||||
cstart = textcolor = "\x85";
|
||||
}
|
||||
else // blue
|
||||
else
|
||||
{
|
||||
cstart = "\x84";
|
||||
textcolor = "\x84";
|
||||
// blue text
|
||||
cstart = textcolor = "\x84";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const UINT8 color = players[playernum].skincolor;
|
||||
|
||||
cstart = "\x83";
|
||||
|
||||
switch (color)
|
||||
{
|
||||
case SKINCOLOR_WHITE:
|
||||
case SKINCOLOR_SILVER:
|
||||
case SKINCOLOR_SLATE:
|
||||
cstart = "\x80"; // White
|
||||
break;
|
||||
case SKINCOLOR_GREY:
|
||||
case SKINCOLOR_NICKEL:
|
||||
case SKINCOLOR_BLACK:
|
||||
case SKINCOLOR_SKUNK:
|
||||
case SKINCOLOR_PLATINUM:
|
||||
case SKINCOLOR_JET:
|
||||
cstart = "\x86"; // V_GRAYMAP
|
||||
break;
|
||||
case SKINCOLOR_SEPIA:
|
||||
case SKINCOLOR_BEIGE:
|
||||
case SKINCOLOR_CARAMEL:
|
||||
case SKINCOLOR_PEACH:
|
||||
case SKINCOLOR_BROWN:
|
||||
case SKINCOLOR_LEATHER:
|
||||
case SKINCOLOR_RUST:
|
||||
case SKINCOLOR_WRISTWATCH:
|
||||
cstart = "\x8e"; // V_BROWNMAP
|
||||
break;
|
||||
case SKINCOLOR_FAIRY:
|
||||
case SKINCOLOR_PINK:
|
||||
case SKINCOLOR_ROSE:
|
||||
case SKINCOLOR_LEMONADE:
|
||||
case SKINCOLOR_LILAC:
|
||||
case SKINCOLOR_BLOSSOM:
|
||||
case SKINCOLOR_TAFFY:
|
||||
cstart = "\x8d"; // V_PINKMAP
|
||||
break;
|
||||
case SKINCOLOR_CINNAMON:
|
||||
case SKINCOLOR_RUBY:
|
||||
case SKINCOLOR_RASPBERRY:
|
||||
case SKINCOLOR_RED:
|
||||
case SKINCOLOR_CRIMSON:
|
||||
case SKINCOLOR_MAROON:
|
||||
case SKINCOLOR_SCARLET:
|
||||
case SKINCOLOR_KETCHUP:
|
||||
cstart = "\x85"; // V_REDMAP
|
||||
break;
|
||||
case SKINCOLOR_DAWN:
|
||||
case SKINCOLOR_SUNSLAM:
|
||||
case SKINCOLOR_CREAMSICLE:
|
||||
case SKINCOLOR_ORANGE:
|
||||
case SKINCOLOR_ROSEWOOD:
|
||||
case SKINCOLOR_TANGERINE:
|
||||
cstart = "\x87"; // V_ORANGEMAP
|
||||
break;
|
||||
case SKINCOLOR_TAN:
|
||||
case SKINCOLOR_CREAM:
|
||||
cstart = "\x8f"; // V_TANMAP
|
||||
break;
|
||||
case SKINCOLOR_GOLD:
|
||||
case SKINCOLOR_ROYAL:
|
||||
case SKINCOLOR_BRONZE:
|
||||
case SKINCOLOR_COPPER:
|
||||
case SKINCOLOR_THUNDER:
|
||||
cstart = "\x8A"; // V_GOLDMAP
|
||||
break;
|
||||
case SKINCOLOR_POPCORN:
|
||||
case SKINCOLOR_YELLOW:
|
||||
case SKINCOLOR_MUSTARD:
|
||||
case SKINCOLOR_BANANA:
|
||||
case SKINCOLOR_OLIVE:
|
||||
case SKINCOLOR_CROCODILE:
|
||||
cstart = "\x82"; // V_YELLOWMAP
|
||||
break;
|
||||
case SKINCOLOR_ARTICHOKE:
|
||||
case SKINCOLOR_PERIDOT:
|
||||
case SKINCOLOR_VOMIT:
|
||||
case SKINCOLOR_GARDEN:
|
||||
case SKINCOLOR_LIME:
|
||||
case SKINCOLOR_HANDHELD:
|
||||
case SKINCOLOR_TEA:
|
||||
case SKINCOLOR_PISTACHIO:
|
||||
case SKINCOLOR_MOSS:
|
||||
case SKINCOLOR_CAMOUFLAGE:
|
||||
case SKINCOLOR_MINT:
|
||||
case SKINCOLOR_GREEN:
|
||||
case SKINCOLOR_PINETREE:
|
||||
case SKINCOLOR_TURTLE:
|
||||
case SKINCOLOR_SWAMP:
|
||||
case SKINCOLOR_DREAM:
|
||||
case SKINCOLOR_PLAGUE:
|
||||
case SKINCOLOR_EMERALD:
|
||||
case SKINCOLOR_ALGAE:
|
||||
cstart = "\x83"; // V_GREENMAP
|
||||
break;
|
||||
case SKINCOLOR_AQUAMARINE:
|
||||
case SKINCOLOR_TURQUOISE:
|
||||
case SKINCOLOR_TEAL:
|
||||
cstart = "\x8b"; // V_AQUAMAP
|
||||
break;
|
||||
case SKINCOLOR_PIGEON:
|
||||
case SKINCOLOR_ROBIN:
|
||||
case SKINCOLOR_CYAN:
|
||||
case SKINCOLOR_JAWZ:
|
||||
case SKINCOLOR_CERULEAN:
|
||||
case SKINCOLOR_NAVY:
|
||||
case SKINCOLOR_SAPPHIRE:
|
||||
cstart = "\x88"; // V_SKYMAP
|
||||
break;
|
||||
case SKINCOLOR_STEEL:
|
||||
case SKINCOLOR_ULTRAMARINE:
|
||||
case SKINCOLOR_PERIWINKLE:
|
||||
case SKINCOLOR_BLUE:
|
||||
case SKINCOLOR_MIDNIGHT:
|
||||
case SKINCOLOR_BLUEBERRY:
|
||||
case SKINCOLOR_NOVA:
|
||||
cstart = "\x84"; // V_BLUEMAP
|
||||
break;
|
||||
case SKINCOLOR_THISTLE:
|
||||
case SKINCOLOR_PURPLE:
|
||||
case SKINCOLOR_PASTEL:
|
||||
cstart = "\x81"; // V_PURPLEMAP
|
||||
break;
|
||||
case SKINCOLOR_MAGENTA:
|
||||
case SKINCOLOR_FUCHSIA:
|
||||
case SKINCOLOR_MOONSET:
|
||||
case SKINCOLOR_VIOLET:
|
||||
cstart = "\x8c"; // V_MAGENTAMAP
|
||||
break;
|
||||
case SKINCOLOR_DUSK:
|
||||
case SKINCOLOR_TOXIC:
|
||||
case SKINCOLOR_MAUVE:
|
||||
case SKINCOLOR_LAVENDER:
|
||||
case SKINCOLOR_BYZANTIUM:
|
||||
case SKINCOLOR_POMEGRANATE:
|
||||
cstart = "\x89"; // V_LAVENDERMAP
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cstart = "\x80" + (K_SkincolorToTextColor(players[playernum].skincolor) >> V_CHARCOLORSHIFT);
|
||||
}
|
||||
|
||||
prefix = cstart;
|
||||
|
|
@ -932,6 +770,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
tempchar = (char *)Z_Calloc(strlen(cstart) + strlen(adminchar) + 1, PU_STATIC, NULL);
|
||||
else if (IsPlayerAdmin(playernum))
|
||||
tempchar = (char *)Z_Calloc(strlen(cstart) + strlen(remotechar) + 1, PU_STATIC, NULL);
|
||||
|
||||
if (tempchar)
|
||||
{
|
||||
if (playernum == serverplayer)
|
||||
|
|
@ -999,7 +838,7 @@ static inline boolean HU_keyInChatString(char *s, char ch)
|
|||
{
|
||||
size_t l;
|
||||
|
||||
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART])
|
||||
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && fontv[HU_FONT].font[ch-HU_FONTSTART])
|
||||
|| ch == ' ') // Allow spaces, of course
|
||||
{
|
||||
l = strlen(s);
|
||||
|
|
@ -1433,7 +1272,7 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
|
|||
c = toupper(c);
|
||||
c -= HU_FONTSTART;
|
||||
|
||||
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
|
||||
if (c < 0 || c >= HU_FONTSIZE || !fontv[HU_FONT].font[c])
|
||||
{
|
||||
chw = spacewidth;
|
||||
lastusablespace = i;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "d_event.h"
|
||||
#include "w_wad.h"
|
||||
#include "r_defs.h"
|
||||
#include "font.h"
|
||||
|
||||
//------------------------------------
|
||||
// heads up font
|
||||
|
|
@ -42,6 +43,23 @@
|
|||
#define CRED_FONTEND 'Z' // the last font character
|
||||
#define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1)
|
||||
|
||||
#define X( name ) name ## _FONT
|
||||
/* fonts */
|
||||
enum
|
||||
{
|
||||
X (HU),
|
||||
X (TINY),
|
||||
X (KART),
|
||||
|
||||
X (LT),
|
||||
X (CRED),
|
||||
|
||||
X (TALLNUM),
|
||||
X (NIGHTSNUM),
|
||||
X (PINGNUM),
|
||||
};
|
||||
#undef X
|
||||
|
||||
#define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init();
|
||||
|
||||
extern char *shiftxform; // english translation shift table
|
||||
|
|
@ -78,15 +96,9 @@ void HU_AddChatText(const char *text, boolean playsound);
|
|||
// set true when entering a chat message
|
||||
extern boolean chat_on;
|
||||
|
||||
extern patch_t *hu_font[HU_FONTSIZE], *kart_font[KART_FONTSIZE], *tny_font[HU_FONTSIZE]; // SRB2kart
|
||||
extern patch_t *tallnum[10];
|
||||
extern patch_t *pingnum[10];
|
||||
extern patch_t *pinggfx[5];
|
||||
extern patch_t *nightsnum[10];
|
||||
extern patch_t *framecounter;
|
||||
extern patch_t *frameslash;
|
||||
extern patch_t *lt_font[LT_FONTSIZE];
|
||||
extern patch_t *cred_font[CRED_FONTSIZE];
|
||||
extern patch_t *emeraldpics[7];
|
||||
extern patch_t *tinyemeraldpics[7];
|
||||
extern patch_t *rflagico;
|
||||
|
|
@ -104,6 +116,9 @@ void HU_Init(void);
|
|||
|
||||
void HU_LoadGraphics(void);
|
||||
|
||||
// Load a HUDGFX patch or NULL.
|
||||
patch_t *HU_CachePatch(const char *format, ...);
|
||||
|
||||
// reset heads up when consoleplayer respawns.
|
||||
void HU_Start(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -254,7 +254,6 @@ void K_CheckBumpers(void)
|
|||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
players[i].pflags |= PF_TIMEOVER;
|
||||
//players[i].lives = 0;
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
60
src/k_bot.c
60
src/k_bot.c
|
|
@ -1,5 +1,6 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
|
|
@ -295,11 +296,17 @@ boolean K_BotCanTakeCut(player_t *player)
|
|||
--------------------------------------------------*/
|
||||
static UINT32 K_BotRubberbandDistance(player_t *player)
|
||||
{
|
||||
const UINT32 spacing = 2048;
|
||||
const UINT32 spacing = FixedDiv(512 * FRACUNIT, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT;
|
||||
const UINT8 portpriority = player - players;
|
||||
UINT8 pos = 0;
|
||||
UINT8 i;
|
||||
|
||||
if (player->botvars.rival)
|
||||
{
|
||||
// The rival should always try to be the front runner for the race.
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (i == portpriority)
|
||||
|
|
@ -312,15 +319,15 @@ static UINT32 K_BotRubberbandDistance(player_t *player)
|
|||
// First check difficulty levels, then score, then settle it with port priority!
|
||||
if (player->botvars.difficulty < players[i].botvars.difficulty)
|
||||
{
|
||||
pos++;
|
||||
pos += 3;
|
||||
}
|
||||
else if (player->score < players[i].score)
|
||||
{
|
||||
pos++;
|
||||
pos += 2;
|
||||
}
|
||||
else if (i < portpriority)
|
||||
{
|
||||
pos++;
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -336,11 +343,13 @@ static UINT32 K_BotRubberbandDistance(player_t *player)
|
|||
fixed_t K_BotRubberband(player_t *player)
|
||||
{
|
||||
fixed_t rubberband = FRACUNIT;
|
||||
fixed_t max, min;
|
||||
player_t *firstplace = NULL;
|
||||
UINT8 i;
|
||||
|
||||
if (player->exiting)
|
||||
{
|
||||
// You're done, we don't need to rubberband anymore.
|
||||
return FRACUNIT;
|
||||
}
|
||||
|
||||
|
|
@ -372,8 +381,8 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
|
||||
if (wanteddist > player->distancetofinish)
|
||||
{
|
||||
// Whoa, you're too far ahead!
|
||||
rubberband += (MAXBOTDIFFICULTY - player->botvars.difficulty) * distdiff;
|
||||
// Whoa, you're too far ahead! Slow back down a little.
|
||||
rubberband += (MAXBOTDIFFICULTY - player->botvars.difficulty) * (distdiff / 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -382,13 +391,23 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
if (rubberband > 2*FRACUNIT)
|
||||
// Lv. 1: x1.0 max
|
||||
// Lv. 5: x1.5 max
|
||||
// Lv. 9: x2.0 max
|
||||
max = FRACUNIT + ((FRACUNIT * (player->botvars.difficulty - 1)) / (MAXBOTDIFFICULTY - 1));
|
||||
|
||||
// Lv. 1: x0.75 min
|
||||
// Lv. 5: x0.875 min
|
||||
// Lv. 9: x1.0 min
|
||||
min = FRACUNIT - (((FRACUNIT/4) * (MAXBOTDIFFICULTY - player->botvars.difficulty)) / (MAXBOTDIFFICULTY - 1));
|
||||
|
||||
if (rubberband > max)
|
||||
{
|
||||
rubberband = 2*FRACUNIT;
|
||||
rubberband = max;
|
||||
}
|
||||
else if (rubberband < 7*FRACUNIT/8)
|
||||
else if (rubberband < min)
|
||||
{
|
||||
rubberband = 7*FRACUNIT/8;
|
||||
rubberband = min;
|
||||
}
|
||||
|
||||
return rubberband;
|
||||
|
|
@ -447,6 +466,25 @@ fixed_t K_BotTopSpeedRubberband(player_t *player)
|
|||
return rubberband;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict)
|
||||
{
|
||||
fixed_t rubberband = K_BotRubberband(player) - FRACUNIT;
|
||||
|
||||
if (rubberband <= 0)
|
||||
{
|
||||
// Never get stronger than normal friction
|
||||
return frict;
|
||||
}
|
||||
|
||||
// 128 is a magic number that felt good in-game
|
||||
return FixedDiv(frict, FRACUNIT + (rubberband / 2));
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy)
|
||||
|
||||
|
|
@ -637,7 +675,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
// Remove any existing controls
|
||||
memset(cmd, 0, sizeof(ticcmd_t));
|
||||
cmd->angleturn = (player->mo->angle >> 16) | TICCMD_RECEIVED;
|
||||
cmd->angleturn = (player->mo->angle >> 16);
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
|
|
|
|||
19
src/k_bot.h
19
src/k_bot.h
|
|
@ -1,5 +1,6 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
|
|
@ -95,6 +96,23 @@ fixed_t K_BotRubberband(player_t *player);
|
|||
fixed_t K_BotTopSpeedRubberband(player_t *player);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict);
|
||||
|
||||
Gives a multiplier for a bot's rubberbanding.
|
||||
Adjusted from K_BotRubberband to be used for friction.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to check.
|
||||
frict - Friction value to adjust.
|
||||
|
||||
Return:-
|
||||
The new friction value.
|
||||
--------------------------------------------------*/
|
||||
|
||||
fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy);
|
||||
|
||||
|
|
@ -228,5 +246,4 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd);
|
|||
|
||||
void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
|
|
|
|||
171
src/k_color.c
171
src/k_color.c
|
|
@ -380,12 +380,160 @@ UINT8 colortranslations[MAXTRANSLATIONS][16] = {
|
|||
{ 0, 0, 96, 96, 97, 98, 98, 99, 81, 81, 69, 71, 73, 75, 77, 79}, // SKINCOLOR_CSUPER5
|
||||
};
|
||||
|
||||
/*--------------------------------------------------
|
||||
INT32 K_SkincolorToTextColor(UINT8 skincolor)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
INT32 K_SkincolorToTextColor(UINT8 skincolor)
|
||||
{
|
||||
INT32 textcolor = 0;
|
||||
|
||||
switch (skincolor)
|
||||
{
|
||||
default: // default to white?
|
||||
case SKINCOLOR_WHITE:
|
||||
case SKINCOLOR_SILVER:
|
||||
case SKINCOLOR_SLATE:
|
||||
textcolor = 0; // No color is white
|
||||
break;
|
||||
case SKINCOLOR_GREY:
|
||||
case SKINCOLOR_NICKEL:
|
||||
case SKINCOLOR_BLACK:
|
||||
case SKINCOLOR_SKUNK:
|
||||
case SKINCOLOR_PLATINUM:
|
||||
case SKINCOLOR_JET:
|
||||
textcolor = V_GRAYMAP;
|
||||
break;
|
||||
case SKINCOLOR_SEPIA:
|
||||
case SKINCOLOR_BEIGE:
|
||||
case SKINCOLOR_CARAMEL:
|
||||
case SKINCOLOR_PEACH:
|
||||
case SKINCOLOR_BROWN:
|
||||
case SKINCOLOR_LEATHER:
|
||||
case SKINCOLOR_RUST:
|
||||
case SKINCOLOR_WRISTWATCH:
|
||||
textcolor = V_BROWNMAP;
|
||||
break;
|
||||
case SKINCOLOR_FAIRY:
|
||||
case SKINCOLOR_PINK:
|
||||
case SKINCOLOR_ROSE:
|
||||
case SKINCOLOR_LEMONADE:
|
||||
case SKINCOLOR_LILAC:
|
||||
case SKINCOLOR_BLOSSOM:
|
||||
case SKINCOLOR_TAFFY:
|
||||
textcolor = V_PINKMAP;
|
||||
break;
|
||||
case SKINCOLOR_CINNAMON:
|
||||
case SKINCOLOR_RUBY:
|
||||
case SKINCOLOR_RASPBERRY:
|
||||
case SKINCOLOR_RED:
|
||||
case SKINCOLOR_CRIMSON:
|
||||
case SKINCOLOR_MAROON:
|
||||
case SKINCOLOR_SCARLET:
|
||||
case SKINCOLOR_KETCHUP:
|
||||
textcolor = V_REDMAP;
|
||||
break;
|
||||
case SKINCOLOR_DAWN:
|
||||
case SKINCOLOR_SUNSLAM:
|
||||
case SKINCOLOR_CREAMSICLE:
|
||||
case SKINCOLOR_ORANGE:
|
||||
case SKINCOLOR_ROSEWOOD:
|
||||
case SKINCOLOR_TANGERINE:
|
||||
textcolor = V_ORANGEMAP;
|
||||
break;
|
||||
case SKINCOLOR_TAN:
|
||||
case SKINCOLOR_CREAM:
|
||||
textcolor = V_TANMAP;
|
||||
break;
|
||||
case SKINCOLOR_GOLD:
|
||||
case SKINCOLOR_ROYAL:
|
||||
case SKINCOLOR_BRONZE:
|
||||
case SKINCOLOR_COPPER:
|
||||
case SKINCOLOR_THUNDER:
|
||||
textcolor = V_GOLDMAP;
|
||||
break;
|
||||
case SKINCOLOR_POPCORN:
|
||||
case SKINCOLOR_YELLOW:
|
||||
case SKINCOLOR_MUSTARD:
|
||||
case SKINCOLOR_BANANA:
|
||||
case SKINCOLOR_OLIVE:
|
||||
case SKINCOLOR_CROCODILE:
|
||||
textcolor = V_YELLOWMAP;
|
||||
break;
|
||||
case SKINCOLOR_ARTICHOKE:
|
||||
case SKINCOLOR_PERIDOT:
|
||||
case SKINCOLOR_VOMIT:
|
||||
case SKINCOLOR_GARDEN:
|
||||
case SKINCOLOR_LIME:
|
||||
case SKINCOLOR_HANDHELD:
|
||||
case SKINCOLOR_TEA:
|
||||
case SKINCOLOR_PISTACHIO:
|
||||
case SKINCOLOR_MOSS:
|
||||
case SKINCOLOR_CAMOUFLAGE:
|
||||
case SKINCOLOR_MINT:
|
||||
case SKINCOLOR_GREEN:
|
||||
case SKINCOLOR_PINETREE:
|
||||
case SKINCOLOR_TURTLE:
|
||||
case SKINCOLOR_SWAMP:
|
||||
case SKINCOLOR_DREAM:
|
||||
case SKINCOLOR_PLAGUE:
|
||||
case SKINCOLOR_EMERALD:
|
||||
case SKINCOLOR_ALGAE:
|
||||
textcolor = V_GREENMAP;
|
||||
break;
|
||||
case SKINCOLOR_AQUAMARINE:
|
||||
case SKINCOLOR_TURQUOISE:
|
||||
case SKINCOLOR_TEAL:
|
||||
textcolor = V_AQUAMAP;
|
||||
break;
|
||||
case SKINCOLOR_PIGEON:
|
||||
case SKINCOLOR_ROBIN:
|
||||
case SKINCOLOR_CYAN:
|
||||
case SKINCOLOR_JAWZ:
|
||||
case SKINCOLOR_CERULEAN:
|
||||
case SKINCOLOR_NAVY:
|
||||
case SKINCOLOR_SAPPHIRE:
|
||||
textcolor = V_SKYMAP;
|
||||
break;
|
||||
case SKINCOLOR_STEEL:
|
||||
case SKINCOLOR_ULTRAMARINE:
|
||||
case SKINCOLOR_PERIWINKLE:
|
||||
case SKINCOLOR_BLUE:
|
||||
case SKINCOLOR_MIDNIGHT:
|
||||
case SKINCOLOR_BLUEBERRY:
|
||||
case SKINCOLOR_NOVA:
|
||||
textcolor = V_BLUEMAP;
|
||||
break;
|
||||
case SKINCOLOR_THISTLE:
|
||||
case SKINCOLOR_PURPLE:
|
||||
case SKINCOLOR_PASTEL:
|
||||
textcolor = V_PURPLEMAP;
|
||||
break;
|
||||
case SKINCOLOR_MAGENTA:
|
||||
case SKINCOLOR_FUCHSIA:
|
||||
case SKINCOLOR_MOONSET:
|
||||
case SKINCOLOR_VIOLET:
|
||||
textcolor = V_MAGENTAMAP;
|
||||
break;
|
||||
case SKINCOLOR_DUSK:
|
||||
case SKINCOLOR_TOXIC:
|
||||
case SKINCOLOR_MAUVE:
|
||||
case SKINCOLOR_LAVENDER:
|
||||
case SKINCOLOR_BYZANTIUM:
|
||||
case SKINCOLOR_POMEGRANATE:
|
||||
textcolor = V_LAVENDERMAP;
|
||||
break;
|
||||
}
|
||||
|
||||
return textcolor;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b)
|
||||
{
|
||||
UINT32 redweight = 1063 * r;
|
||||
|
|
@ -400,7 +548,6 @@ UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b)
|
|||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
|
||||
{
|
||||
INT32 i;
|
||||
|
|
@ -444,14 +591,11 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
|
|||
}
|
||||
}
|
||||
|
||||
/** \brief Generates a translation colormap for Kart, to replace R_GenerateTranslationColormap in r_draw.c
|
||||
/*--------------------------------------------------
|
||||
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
|
||||
|
||||
\param dest_colormap colormap to populate
|
||||
\param skinnum number of skin, TC_DEFAULT or TC_BOSS
|
||||
\param color translation color
|
||||
|
||||
\return void
|
||||
*/
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
|
||||
{
|
||||
INT32 i;
|
||||
|
|
@ -505,12 +649,11 @@ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
|
|||
}
|
||||
}
|
||||
|
||||
/** \brief Pulls kart color by name, to replace R_GetColorByName in r_draw.c
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_GetKartColorByName(const char *name)
|
||||
|
||||
\param name color name
|
||||
|
||||
\return 0
|
||||
*/
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
UINT8 K_GetKartColorByName(const char *name)
|
||||
{
|
||||
UINT8 color = (UINT8)atoi(name);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,21 @@ extern UINT8 colortranslations[MAXTRANSLATIONS][16];
|
|||
extern const char *KartColor_Names[MAXSKINCOLORS];
|
||||
extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2];
|
||||
|
||||
/*--------------------------------------------------
|
||||
INT32 K_SkincolorToTextColor(UINT8 skincolor);
|
||||
|
||||
Gives you the "text" color (V_ constants) from a skincolor (SKINCOLOR_ constants).
|
||||
Used primarily by the chat system.
|
||||
|
||||
Input Arguments:-
|
||||
skincolor - SKINCOLOR_ constant
|
||||
|
||||
Return:-
|
||||
V_ constant for font coloring
|
||||
--------------------------------------------------*/
|
||||
INT32 K_SkincolorToTextColor(UINT8 skincolor);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b);
|
||||
|
||||
|
|
|
|||
605
src/k_grandprix.c
Normal file
605
src/k_grandprix.c
Normal file
|
|
@ -0,0 +1,605 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour
|
||||
// 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_grandprix.c
|
||||
/// \brief Grand Prix mode game logic & bot behaviors
|
||||
|
||||
#include "k_grandprix.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"
|
||||
|
||||
struct grandprixinfo grandprixinfo;
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_BotStartingDifficulty(SINT8 value)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
UINT8 K_BotStartingDifficulty(SINT8 value)
|
||||
{
|
||||
// startingdifficulty: Easy = 3, Normal = 6, Hard = 9
|
||||
SINT8 difficulty = (value + 1) * 3;
|
||||
|
||||
if (difficulty > MAXBOTDIFFICULTY)
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY;
|
||||
}
|
||||
else if (difficulty < 1)
|
||||
{
|
||||
difficulty = 1;
|
||||
}
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
INT16 K_CalculateGPRankPoints(UINT8 position, UINT8 numplayers)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
INT16 K_CalculateGPRankPoints(UINT8 position, UINT8 numplayers)
|
||||
{
|
||||
INT16 points;
|
||||
|
||||
if (position >= numplayers || position == 0)
|
||||
{
|
||||
// Invalid position, no points
|
||||
return 0;
|
||||
}
|
||||
|
||||
points = numplayers - position;
|
||||
|
||||
// Give bonus to high-ranking players, depending on player count
|
||||
// This rounds out the point gain when you get 1st every race,
|
||||
// and gives bots able to catch up in points if a player gets an early lead.
|
||||
// The maximum points you can get in a cup is: ((number of players - 1) + (max extra points)) * (number of races)
|
||||
// 8P: (7 + 5) * 5 = 60 maximum points
|
||||
// 12P: (11 + 5) * 5 = 80 maximum points
|
||||
// 16P: (15 + 5) * 5 = 100 maximum points
|
||||
switch (numplayers)
|
||||
{
|
||||
case 0: case 1: case 2: // 1v1
|
||||
break; // No bonus needed.
|
||||
case 3: case 4: // 3-4P
|
||||
if (position == 1) { points += 1; } // 1st gets +1 extra point
|
||||
break;
|
||||
case 5: case 6: // 5-6P
|
||||
if (position == 1) { points += 3; } // 1st gets +3 extra points
|
||||
else if (position == 2) { points += 1; } // 2nd gets +1 extra point
|
||||
break;
|
||||
default: // Normal matches
|
||||
if (position == 1) { points += 5; } // 1st gets +5 extra points
|
||||
else if (position == 2) { points += 3; } // 2nd gets +3 extra points
|
||||
else if (position == 3) { points += 1; } // 3rd gets +1 extra point
|
||||
break;
|
||||
}
|
||||
|
||||
// somehow underflowed?
|
||||
if (points < 0)
|
||||
{
|
||||
points = 0;
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitGrandPrixBots(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_InitGrandPrixBots(void)
|
||||
{
|
||||
const char *defaultbotskinname = "eggrobo";
|
||||
SINT8 defaultbotskin = R_SkinAvailable(defaultbotskinname);
|
||||
|
||||
const UINT8 startingdifficulty = K_BotStartingDifficulty(grandprixinfo.gamespeed);
|
||||
UINT8 difficultylevels[MAXPLAYERS];
|
||||
|
||||
UINT8 playercount = 8;
|
||||
UINT8 wantedbots = 0;
|
||||
|
||||
UINT8 numplayers = 0;
|
||||
UINT8 competitors[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
boolean skinusable[MAXSKINS];
|
||||
UINT8 botskinlist[MAXPLAYERS];
|
||||
UINT8 botskinlistpos = 0;
|
||||
|
||||
UINT8 newplayernum = 0;
|
||||
UINT8 i, j;
|
||||
|
||||
if (defaultbotskin == -1)
|
||||
{
|
||||
// This shouldn't happen, but just in case
|
||||
defaultbotskin = 0;
|
||||
}
|
||||
|
||||
memset(competitors, MAXPLAYERS, sizeof (competitors));
|
||||
memset(botskinlist, defaultbotskin, sizeof (botskinlist));
|
||||
|
||||
// init usable bot skins list
|
||||
for (i = 0; i < MAXSKINS; i++)
|
||||
{
|
||||
if (i < numskins)
|
||||
{
|
||||
skinusable[i] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
skinusable[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
#if MAXPLAYERS != 16
|
||||
I_Error("GP bot difficulty levels need rebalacned for the new player count!\n");
|
||||
#endif
|
||||
|
||||
if (grandprixinfo.masterbots)
|
||||
{
|
||||
// Everyone is max difficulty!!
|
||||
memset(difficultylevels, MAXBOTDIFFICULTY, sizeof (difficultylevels));
|
||||
}
|
||||
else
|
||||
{
|
||||
// init difficulty levels list
|
||||
difficultylevels[0] = max(1, startingdifficulty);
|
||||
difficultylevels[1] = max(1, startingdifficulty-1);
|
||||
difficultylevels[2] = max(1, startingdifficulty-2);
|
||||
difficultylevels[3] = max(1, startingdifficulty-3);
|
||||
difficultylevels[4] = max(1, startingdifficulty-3);
|
||||
difficultylevels[5] = max(1, startingdifficulty-4);
|
||||
difficultylevels[6] = max(1, startingdifficulty-4);
|
||||
difficultylevels[7] = max(1, startingdifficulty-4);
|
||||
difficultylevels[8] = max(1, startingdifficulty-5);
|
||||
difficultylevels[9] = max(1, startingdifficulty-5);
|
||||
difficultylevels[10] = max(1, startingdifficulty-5);
|
||||
difficultylevels[11] = max(1, startingdifficulty-6);
|
||||
difficultylevels[12] = max(1, startingdifficulty-6);
|
||||
difficultylevels[13] = max(1, startingdifficulty-6);
|
||||
difficultylevels[14] = max(1, startingdifficulty-7);
|
||||
difficultylevels[15] = max(1, startingdifficulty-7);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
if (numplayers < MAXSPLITSCREENPLAYERS && !players[i].spectator)
|
||||
{
|
||||
competitors[numplayers] = i;
|
||||
skinusable[players[i].skin] = false;
|
||||
numplayers++;
|
||||
}
|
||||
else
|
||||
{
|
||||
players[i].spectator = true; // force spectate for all other players, if they happen to exist?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numplayers > 2)
|
||||
{
|
||||
// Add 3 bots per player beyond 2P
|
||||
playercount += (numplayers-2) * 3;
|
||||
}
|
||||
|
||||
wantedbots = playercount - numplayers;
|
||||
|
||||
// Create rival list
|
||||
if (numplayers > 0)
|
||||
{
|
||||
for (i = 0; i < SKINRIVALS; i++)
|
||||
{
|
||||
for (j = 0; j < numplayers; j++)
|
||||
{
|
||||
player_t *p = &players[competitors[j]];
|
||||
char *rivalname = skins[p->skin].rivals[i];
|
||||
SINT8 rivalnum = R_SkinAvailable(rivalname);
|
||||
|
||||
if (rivalnum != -1 && skinusable[rivalnum])
|
||||
{
|
||||
botskinlist[botskinlistpos] = rivalnum;
|
||||
skinusable[rivalnum] = false;
|
||||
botskinlistpos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pad the remaining list with random skins if we need to
|
||||
if (botskinlistpos < wantedbots)
|
||||
{
|
||||
for (i = botskinlistpos; i < wantedbots; i++)
|
||||
{
|
||||
UINT8 val = M_RandomKey(numskins);
|
||||
UINT8 loops = 0;
|
||||
|
||||
while (!skinusable[val])
|
||||
{
|
||||
if (loops >= numskins)
|
||||
{
|
||||
// no more skins
|
||||
break;
|
||||
}
|
||||
|
||||
val++;
|
||||
|
||||
if (val >= numskins)
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
|
||||
loops++;
|
||||
}
|
||||
|
||||
if (loops >= numskins)
|
||||
{
|
||||
// leave the rest of the table as the default skin
|
||||
break;
|
||||
}
|
||||
|
||||
botskinlist[i] = val;
|
||||
skinusable[val] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < wantedbots; i++)
|
||||
{
|
||||
if (!K_AddBot(botskinlist[i], difficultylevels[i], &newplayernum))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static INT16 K_RivalScore(player_t *bot)
|
||||
|
||||
Creates a "rival score" for a bot, used to determine which bot is the
|
||||
most deserving of the rival status.
|
||||
|
||||
Input Arguments:-
|
||||
bot - Player to check.
|
||||
|
||||
Return:-
|
||||
"Rival score" value.
|
||||
--------------------------------------------------*/
|
||||
static INT16 K_RivalScore(player_t *bot)
|
||||
{
|
||||
const UINT16 difficulty = bot->botvars.difficulty;
|
||||
const UINT16 score = bot->score;
|
||||
SINT8 roundnum = 1, roundsleft = 1;
|
||||
UINT16 lowestscore = UINT16_MAX;
|
||||
UINT8 lowestdifficulty = MAXBOTDIFFICULTY;
|
||||
UINT8 i;
|
||||
|
||||
if (grandprixinfo.cup != NULL)
|
||||
{
|
||||
roundnum = grandprixinfo.roundnum;
|
||||
roundsleft = grandprixinfo.cup->numlevels - grandprixinfo.roundnum;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (players[i].score < lowestscore)
|
||||
{
|
||||
lowestscore = players[i].score;
|
||||
}
|
||||
|
||||
if (players[i].bot == true && players[i].botvars.difficulty < lowestdifficulty)
|
||||
{
|
||||
lowestdifficulty = players[i].botvars.difficulty;
|
||||
}
|
||||
}
|
||||
|
||||
// In the early game, difficulty is more important.
|
||||
// This will try to influence the higher difficulty bots to get rival more often & get even more points.
|
||||
// However, when we're running low on matches left, we need to focus more on raw score!
|
||||
|
||||
return ((difficulty - lowestdifficulty) * roundsleft) + ((score - lowestscore) * roundnum);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_UpdateGrandPrixBots(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_UpdateGrandPrixBots(void)
|
||||
{
|
||||
player_t *oldrival = NULL;
|
||||
player_t *newrival = NULL;
|
||||
UINT16 newrivalscore = 0;
|
||||
UINT8 i;
|
||||
|
||||
// Find the rival.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || !players[i].bot)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (players[i].botvars.diffincrease)
|
||||
{
|
||||
players[i].botvars.difficulty += players[i].botvars.diffincrease;
|
||||
|
||||
if (players[i].botvars.difficulty > MAXBOTDIFFICULTY)
|
||||
{
|
||||
players[i].botvars.difficulty = MAXBOTDIFFICULTY;
|
||||
}
|
||||
|
||||
players[i].botvars.diffincrease = 0;
|
||||
}
|
||||
|
||||
if (players[i].botvars.rival)
|
||||
{
|
||||
if (oldrival == NULL)
|
||||
{
|
||||
// Record the old rival to compare with our calculated new rival
|
||||
oldrival = &players[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Somehow 2 rivals were set?!
|
||||
// Let's quietly fix our mess...
|
||||
players[i].botvars.rival = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the bot with the best average of score & difficulty.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
UINT16 ns = 0;
|
||||
|
||||
if (!playeringame[i] || players[i].spectator || !players[i].bot)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ns = K_RivalScore(&players[i]);
|
||||
|
||||
if (ns > newrivalscore)
|
||||
{
|
||||
newrival = &players[i];
|
||||
newrivalscore = ns;
|
||||
}
|
||||
}
|
||||
|
||||
// Even if there's a new rival, we want to make sure that they're a better fit than the current one.
|
||||
if (oldrival != newrival)
|
||||
{
|
||||
if (oldrival != NULL)
|
||||
{
|
||||
UINT16 os = K_RivalScore(oldrival);
|
||||
|
||||
if (newrivalscore < os + 5)
|
||||
{
|
||||
// This rival's only *slightly* better, no need to fire the old one.
|
||||
// Our current rival's just fine, thank you very much.
|
||||
return;
|
||||
}
|
||||
|
||||
// Hand over your badge.
|
||||
oldrival->botvars.rival = false;
|
||||
}
|
||||
|
||||
// Set our new rival!
|
||||
newrival->botvars.rival = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static UINT8 K_BotExpectedStanding(player_t *bot)
|
||||
|
||||
Predicts what placement a bot was expected to be in.
|
||||
Used for determining if a bot's difficulty should raise.
|
||||
|
||||
Input Arguments:-
|
||||
bot - Player to check.
|
||||
|
||||
Return:-
|
||||
Position number the bot was expected to be in.
|
||||
--------------------------------------------------*/
|
||||
static UINT8 K_BotExpectedStanding(player_t *bot)
|
||||
{
|
||||
UINT8 pos = 1;
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (i == (bot - players))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
{
|
||||
if (players[i].bot)
|
||||
{
|
||||
if (players[i].botvars.difficulty > bot->botvars.difficulty)
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
else if (players[i].score > bot->score)
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Human player, always increment
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_IncreaseBotDifficulty(player_t *bot)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_IncreaseBotDifficulty(player_t *bot)
|
||||
{
|
||||
UINT8 expectedstanding;
|
||||
INT16 standingdiff;
|
||||
|
||||
if (bot->botvars.difficulty >= MAXBOTDIFFICULTY)
|
||||
{
|
||||
// Already at max difficulty, don't need to increase
|
||||
return;
|
||||
}
|
||||
|
||||
// Increment bot difficulty based on what position you were meant to come in!
|
||||
expectedstanding = K_BotExpectedStanding(bot);
|
||||
standingdiff = expectedstanding - bot->kartstuff[k_position];
|
||||
|
||||
if (standingdiff >= -2)
|
||||
{
|
||||
UINT8 increase;
|
||||
|
||||
if (standingdiff > 5)
|
||||
{
|
||||
increase = 3;
|
||||
}
|
||||
else if (standingdiff > 2)
|
||||
{
|
||||
increase = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
increase = 1;
|
||||
}
|
||||
|
||||
bot->botvars.diffincrease = increase;
|
||||
}
|
||||
else
|
||||
{
|
||||
bot->botvars.diffincrease = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_FakeBotResults(player_t *bot)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_FakeBotResults(player_t *bot)
|
||||
{
|
||||
const UINT32 distfactor = FixedMul(32 * bot->mo->scale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT;
|
||||
UINT32 worstdist = 0;
|
||||
tic_t besttime = UINT32_MAX;
|
||||
UINT8 numplayers = 0;
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
{
|
||||
numplayers++;
|
||||
|
||||
if (players[i].exiting && players[i].realtime < besttime)
|
||||
{
|
||||
besttime = players[i].realtime;
|
||||
}
|
||||
|
||||
if (players[i].distancetofinish > worstdist)
|
||||
{
|
||||
worstdist = players[i].distancetofinish;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (besttime == UINT32_MAX // No one finished, so you don't finish either.
|
||||
|| bot->distancetofinish >= worstdist) // Last place, you aren't going to finish.
|
||||
{
|
||||
bot->pflags |= PF_TIMEOVER;
|
||||
return;
|
||||
}
|
||||
|
||||
// hey, you "won"
|
||||
bot->exiting = 2;
|
||||
bot->realtime += (bot->distancetofinish / distfactor);
|
||||
bot->distancetofinish = 0;
|
||||
K_IncreaseBotDifficulty(bot);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_PlayerLoseLife(player_t *player)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
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
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_CanChangeRules(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
boolean K_CanChangeRules(void)
|
||||
{
|
||||
if (demo.playback)
|
||||
{
|
||||
// We've already got our important settings!
|
||||
return false;
|
||||
}
|
||||
|
||||
if (grandprixinfo.gp == true && grandprixinfo.roundnum > 0)
|
||||
{
|
||||
// Don't cheat the rules of the GP!
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modeattacking == true)
|
||||
{
|
||||
// Don't cheat the rules of Time Trials!
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
144
src/k_grandprix.h
Normal file
144
src/k_grandprix.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour
|
||||
// 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_grandprix.h
|
||||
/// \brief Grand Prix mode game logic & bot behaviors
|
||||
|
||||
#ifndef __K_GRANDPRIX__
|
||||
#define __K_GRANDPRIX__
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
extern struct grandprixinfo
|
||||
{
|
||||
boolean gp; ///< If true, then we are in a Grand Prix.
|
||||
UINT8 roundnum; ///< Round number. If 0, this is a single session from the warp command.
|
||||
cupheader_t *cup; ///< Which cup are we playing?
|
||||
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 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.
|
||||
} grandprixinfo;
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_BotStartingDifficulty(SINT8 value);
|
||||
|
||||
Determines the starting difficulty of the bots
|
||||
for a specific game speed.
|
||||
|
||||
Input Arguments:-
|
||||
value - Game speed value to use.
|
||||
|
||||
Return:-
|
||||
Bot difficulty level.
|
||||
--------------------------------------------------*/
|
||||
|
||||
UINT8 K_BotStartingDifficulty(SINT8 value);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
INT16 K_CalculateGPRankPoints(UINT8 position, UINT8 numplayers);
|
||||
|
||||
Calculates the number of points that a player would
|
||||
recieve if they won the round.
|
||||
|
||||
Input Arguments:-
|
||||
position - Finishing position.
|
||||
numplayers - Number of players in the game.
|
||||
|
||||
Return:-
|
||||
Number of points to give.
|
||||
--------------------------------------------------*/
|
||||
|
||||
INT16 K_CalculateGPRankPoints(UINT8 position, UINT8 numplayers);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitGrandPrixBots(void);
|
||||
|
||||
Spawns bots specifically tailored for Grand Prix mode.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_InitGrandPrixBots(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_UpdateGrandPrixBots(void);
|
||||
|
||||
Updates bot settings based on the the results of the race.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_UpdateGrandPrixBots(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_IncreaseBotDifficulty(player_t *bot);
|
||||
|
||||
Increases the difficulty of this bot when they finish the race.
|
||||
|
||||
Input Arguments:-
|
||||
bot - Player to do this for.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_IncreaseBotDifficulty(player_t *bot);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_FakeBotResults(player_t *bot);
|
||||
|
||||
Fakes the results of the race, when all human players have
|
||||
already finished and only bots were remaining.
|
||||
|
||||
Input Arguments:-
|
||||
bot - Player to do this for.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_FakeBotResults(player_t *bot);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_PlayerLoseLife(player_t *player);
|
||||
|
||||
Removes a life from a human player.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to do this for.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_PlayerLoseLife(player_t *player);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_CanChangeRules(void);
|
||||
|
||||
Returns whenver or not the server is allowed
|
||||
to change the game rules.
|
||||
|
||||
Input Arguments:-
|
||||
None
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
boolean K_CanChangeRules(void);
|
||||
|
||||
#endif
|
||||
642
src/k_kart.c
642
src/k_kart.c
File diff suppressed because it is too large
Load diff
|
|
@ -13,6 +13,7 @@
|
|||
#define KART_FULLTURN 800
|
||||
|
||||
player_t *K_GetItemBoxPlayer(mobj_t *mobj);
|
||||
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
|
||||
|
||||
void K_RegisterKartStuff(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "m_random.h"
|
||||
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
|
||||
#include "p_tick.h" // leveltime
|
||||
#include "k_grandprix.h"
|
||||
|
||||
// Online rankings for the main gametypes.
|
||||
// This array is saved to the gamedata.
|
||||
|
|
@ -25,6 +26,27 @@ INT16 nospectategrief[MAXPLAYERS];
|
|||
SINT8 speedscramble = -1;
|
||||
SINT8 encorescramble = -1;
|
||||
|
||||
SINT8 K_UsingPowerLevels(void)
|
||||
{
|
||||
SINT8 pt = PWRLV_DISABLED;
|
||||
|
||||
if (!cv_kartusepwrlv.value || !netgame || grandprixinfo.gp == true)
|
||||
{
|
||||
return PWRLV_DISABLED;
|
||||
}
|
||||
|
||||
if (G_RaceGametype())
|
||||
{
|
||||
pt = PWRLV_RACE;
|
||||
}
|
||||
else if (G_BattleGametype())
|
||||
{
|
||||
pt = PWRLV_BATTLE;
|
||||
}
|
||||
|
||||
return pt;
|
||||
}
|
||||
|
||||
void K_ClearClientPowerLevels(void)
|
||||
{
|
||||
UINT8 i, j;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ extern UINT16 vspowerlevel[PWRLV_NUMTYPES];
|
|||
extern UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
|
||||
extern INT16 nospectategrief[MAXPLAYERS];
|
||||
|
||||
SINT8 K_UsingPowerLevels(void);
|
||||
void K_ClearClientPowerLevels(void);
|
||||
INT16 K_CalculatePowerLevelInc(INT16 diff);
|
||||
INT16 K_CalculatePowerLevelAvg(void);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ enum hud {
|
|||
hud_minimap,
|
||||
hud_item,
|
||||
hud_position,
|
||||
hud_names, // online nametags
|
||||
hud_check, // "CHECK" f-zero indicator
|
||||
hud_minirankings, // Rankings to the left
|
||||
hud_battlebumpers, // mini rankings battle bumpers.
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
#include "hu_stuff.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
|
|
|||
|
|
@ -252,6 +252,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"))
|
||||
|
|
@ -503,6 +505,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"))
|
||||
|
|
|
|||
149
src/m_menu.c
149
src/m_menu.c
|
|
@ -60,6 +60,7 @@
|
|||
#include "k_pwrlv.h"
|
||||
#include "d_player.h" // KITEM_ constants
|
||||
#include "k_color.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#include "i_joy.h" // for joystick menu controls
|
||||
|
||||
|
|
@ -227,7 +228,8 @@ menu_t SP_MainDef, MP_MainDef, OP_MainDef;
|
|||
menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef, MISC_ChangeSpectateDef;
|
||||
|
||||
// Single Player
|
||||
//static void M_LoadGame(INT32 choice);
|
||||
static void M_GrandPrixTemp(INT32 choice);
|
||||
static void M_StartGrandPrix(INT32 choice);
|
||||
static void M_TimeAttack(INT32 choice);
|
||||
static boolean M_QuitTimeAttackMenu(void);
|
||||
static void M_BreakTheCapsules(INT32 choice);
|
||||
|
|
@ -240,6 +242,7 @@ static void M_ModeAttackEndGame(INT32 choice);
|
|||
static void M_SetGuestReplay(INT32 choice);
|
||||
//static void M_ChoosePlayer(INT32 choice);
|
||||
menu_t SP_LevelStatsDef;
|
||||
static menu_t SP_GrandPrixTempDef;
|
||||
static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
|
||||
//static menu_t SP_NightsAttackDef, SP_NightsReplayDef, SP_NightsGuestReplayDef, SP_NightsGhostDef;
|
||||
|
||||
|
|
@ -463,6 +466,13 @@ static consvar_t cv_dummycontinues = {"dummycontinues", "0", CV_HIDEN, liveslimi
|
|||
//static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDEN|CV_CALL, dummystaff_cons_t, Dummystaff_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t dummygpdifficulty_cons_t[] = {{0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {3, "Master"}, {0, NULL}};
|
||||
static CV_PossibleValue_t dummygpcup_cons_t[50] = {{1, "TEMP"}}; // A REALLY BIG NUMBER, SINCE THIS IS TEMP UNTIL NEW MENUS
|
||||
|
||||
static consvar_t cv_dummygpdifficulty = {"dummygpdifficulty", "Normal", CV_HIDEN, dummygpdifficulty_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static consvar_t cv_dummygpencore = {"dummygpencore", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static consvar_t cv_dummygpcup = {"dummygpcup", "TEMP", CV_HIDEN, dummygpcup_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// ==========================================================================
|
||||
// ORGANIZATION START.
|
||||
// ==========================================================================
|
||||
|
|
@ -802,30 +812,30 @@ static menuitem_t SR_EmblemHintMenu[] =
|
|||
// Single Player Main
|
||||
static menuitem_t SP_MainMenu[] =
|
||||
{
|
||||
//{IT_CALL | IT_STRING, NULL, "Grand Prix", M_LoadGame, 92},
|
||||
{IT_SECRET, NULL, "Time Attack", M_TimeAttack, 100},
|
||||
{IT_SECRET, NULL, "Break the Capsules", M_BreakTheCapsules, 108},
|
||||
{IT_STRING|IT_CALL, NULL, "Grand Prix", M_GrandPrixTemp, 92},
|
||||
{IT_SECRET, NULL, "Time Attack", M_TimeAttack, 100},
|
||||
{IT_SECRET, NULL, "Break the Capsules", M_BreakTheCapsules, 108},
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
//spgrandprix,
|
||||
spgrandprix,
|
||||
sptimeattack,
|
||||
spbreakthecapsules
|
||||
};
|
||||
|
||||
// Single Player Load Game
|
||||
/*static menuitem_t SP_LoadGameMenu[] =
|
||||
static menuitem_t SP_GrandPrixPlaceholderMenu[] =
|
||||
{
|
||||
{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLoadSave, '\0'}, // dummy menuitem for the control func
|
||||
};
|
||||
{IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 10},
|
||||
{IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor, 20},
|
||||
|
||||
// Single Player Level Select
|
||||
static menuitem_t SP_LevelSelectMenu[] =
|
||||
{
|
||||
{IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78},
|
||||
{IT_WHITESTRING|IT_CALL, NULL, "Start", M_LevelSelectWarp, 130},
|
||||
};*/
|
||||
{IT_STRING|IT_CVAR, NULL, "Difficulty", &cv_dummygpdifficulty, 40},
|
||||
{IT_STRING|IT_CVAR, NULL, "Encore Mode", &cv_dummygpencore, 50},
|
||||
|
||||
{IT_STRING|IT_CVAR, NULL, "Cup", &cv_dummygpcup, 70},
|
||||
{IT_STRING|IT_CALL, NULL, "Start", M_StartGrandPrix, 80},
|
||||
};
|
||||
|
||||
// Single Player Time Attack
|
||||
static menuitem_t SP_TimeAttackMenu[] =
|
||||
|
|
@ -1810,6 +1820,8 @@ menu_t SP_LevelStatsDef =
|
|||
NULL
|
||||
};
|
||||
|
||||
static menu_t SP_GrandPrixTempDef = DEFAULTMENUSTYLE(NULL, SP_GrandPrixPlaceholderMenu, &MainDef, 60, 30);
|
||||
|
||||
static menu_t SP_TimeAttackDef =
|
||||
{
|
||||
"M_ATTACK",
|
||||
|
|
@ -3376,6 +3388,10 @@ void M_Init(void)
|
|||
//CV_RegisterVar(&cv_dummymares);
|
||||
CV_RegisterVar(&cv_dummystaff);
|
||||
|
||||
CV_RegisterVar(&cv_dummygpdifficulty);
|
||||
CV_RegisterVar(&cv_dummygpencore);
|
||||
CV_RegisterVar(&cv_dummygpcup);
|
||||
|
||||
quitmsg[QUITMSG] = M_GetText("Eggman's tied explosives\nto your girlfriend, and\nwill activate them if\nyou press the 'Y' key!\nPress 'N' to save her!\n\n(Press 'Y' to quit)");
|
||||
quitmsg[QUITMSG1] = M_GetText("What would Tails say if\nhe saw you quitting the game?\n\n(Press 'Y' to quit)");
|
||||
quitmsg[QUITMSG2] = M_GetText("Hey!\nWhere do ya think you're goin'?\n\n(Press 'Y' to quit)");
|
||||
|
|
@ -4221,6 +4237,35 @@ static void M_PatchSkinNameTable(void)
|
|||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// M_PrepareCupList
|
||||
//
|
||||
static void M_PrepareCupList(void)
|
||||
{
|
||||
cupheader_t *cup = kartcupheaders;
|
||||
INT32 i = 0;
|
||||
|
||||
memset(dummygpcup_cons_t, 0, sizeof (dummygpcup_cons_t));
|
||||
|
||||
while (cup != NULL)
|
||||
{
|
||||
dummygpcup_cons_t[i].strvalue = cup->name;
|
||||
dummygpcup_cons_t[i].value = i+1;
|
||||
// this will probably crash or do something stupid at over 50 cups,
|
||||
// but this is all behavior that gets completely overwritten in new-menus, so I'm not worried
|
||||
i++;
|
||||
cup = cup->next;
|
||||
}
|
||||
|
||||
for (; i < 50; i++)
|
||||
{
|
||||
dummygpcup_cons_t[i].strvalue = NULL;
|
||||
dummygpcup_cons_t[i].value = 0;
|
||||
}
|
||||
|
||||
CV_SetValue(&cv_dummygpcup, 1); // This causes crash sometimes?!
|
||||
}
|
||||
|
||||
// Call before showing any level-select menus
|
||||
static void M_PrepareLevelSelect(void)
|
||||
{
|
||||
|
|
@ -6666,6 +6711,8 @@ static void M_Credits(INT32 choice)
|
|||
static void M_SinglePlayerMenu(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
SP_MainMenu[spgrandprix].status = IT_CALL|IT_STRING;
|
||||
SP_MainMenu[sptimeattack].status =
|
||||
(M_SecretUnlocked(SECRET_TIMEATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
|
||||
SP_MainMenu[spbreakthecapsules].status =
|
||||
|
|
@ -7550,6 +7597,80 @@ static void M_HandleLevelStats(INT32 choice)
|
|||
}
|
||||
}
|
||||
|
||||
static void M_GrandPrixTemp(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
M_PatchSkinNameTable();
|
||||
M_PrepareCupList();
|
||||
M_SetupNextMenu(&SP_GrandPrixTempDef);
|
||||
}
|
||||
|
||||
// Start Grand Prix!
|
||||
static void M_StartGrandPrix(INT32 choice)
|
||||
{
|
||||
cupheader_t *gpcup = kartcupheaders;
|
||||
|
||||
(void)choice;
|
||||
|
||||
if (gpcup == NULL)
|
||||
{
|
||||
// welp
|
||||
I_Error("No cup definitions for GP\n");
|
||||
return;
|
||||
}
|
||||
|
||||
M_ClearMenus(true);
|
||||
|
||||
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
|
||||
|
||||
switch (cv_dummygpdifficulty.value)
|
||||
{
|
||||
case 0:
|
||||
grandprixinfo.gamespeed = KARTSPEED_EASY;
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
grandprixinfo.gamespeed = KARTSPEED_NORMAL;
|
||||
break;
|
||||
case 2:
|
||||
grandprixinfo.gamespeed = KARTSPEED_HARD;
|
||||
break;
|
||||
case 3:
|
||||
grandprixinfo.gamespeed = KARTSPEED_HARD;
|
||||
grandprixinfo.masterbots = true;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
grandprixinfo.encore = (boolean)(cv_dummygpencore.value);
|
||||
|
||||
while (gpcup != NULL && gpcup->id != cv_dummygpcup.value-1)
|
||||
{
|
||||
gpcup = gpcup->next;
|
||||
}
|
||||
|
||||
if (gpcup == NULL)
|
||||
{
|
||||
gpcup = kartcupheaders;
|
||||
}
|
||||
|
||||
grandprixinfo.cup = gpcup;
|
||||
|
||||
grandprixinfo.gp = true;
|
||||
grandprixinfo.roundnum = 1;
|
||||
grandprixinfo.wonround = false;
|
||||
|
||||
grandprixinfo.initalize = true;
|
||||
|
||||
G_DeferedInitNew(
|
||||
false,
|
||||
G_BuildMapName(grandprixinfo.cup->levellist[0] + 1),
|
||||
(UINT8)(cv_chooseskin.value - 1),
|
||||
(UINT8)(cv_splitplayers.value - 1),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// ===========
|
||||
// MODE ATTACK
|
||||
// ===========
|
||||
|
|
|
|||
170
src/p_inter.c
170
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") : ""
|
||||
|
|
@ -1968,71 +1969,146 @@ 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 everyonedone = true;
|
||||
boolean eliminatebots = false;
|
||||
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.)
|
||||
// Set this so that we can check for bots that need to get eliminated, though!
|
||||
eliminatebots = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
everyonedone = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAXPLAYERS) // finished
|
||||
// If we returned here with bots left, then the last place bot may have a chance to finish the map and NOT get time over.
|
||||
// Not that it affects anything, they didn't make the map take longer or even get any points from it. But... it's a bit inconsistent!
|
||||
// So if there's any bots, we'll let the game skip this, continue onto calculating eliminatelast, THEN we return true anyway.
|
||||
if (everyonedone && !eliminatebots)
|
||||
{
|
||||
// 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.gp == true)
|
||||
{
|
||||
// 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.
|
||||
if (everyonedone)
|
||||
{
|
||||
// See above: there might be bots that are still going, but all players are done, so we can exit now.
|
||||
racecountdown = exitcountdown = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
@ -2150,11 +2226,28 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
|||
{
|
||||
if (target->flags & MF_MONITOR || target->type == MT_RANDOMITEM)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
P_SetTarget(&target->target, source);
|
||||
source->player->numboxes++;
|
||||
if (cv_itemrespawn.value && (netgame || multiplayer))
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
target->fuse = cv_itemrespawntime.value*TICRATE + 2; // Random box generation
|
||||
if (&players[i] == source->player)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (playeringame[i] && !players[i].spectator && players[i].lives != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < MAXPLAYERS)
|
||||
{
|
||||
// Respawn items in multiplayer, don't respawn them when alone
|
||||
target->fuse = 2*TICRATE + 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2246,20 +2339,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])
|
||||
|
|
@ -3153,6 +3232,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
|| inflictor->type == MT_SMK_THWOMP || inflictor->player))
|
||||
{
|
||||
player->kartstuff[k_sneakertimer] = 0;
|
||||
player->kartstuff[k_numsneakers] = 0;
|
||||
|
||||
K_SpinPlayer(player, source, 1, inflictor, false);
|
||||
K_KartPainEnergyFling(player);
|
||||
|
|
|
|||
37
src/p_map.c
37
src/p_map.c
|
|
@ -324,39 +324,10 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
// This makes it a bit more interesting & unique than just being a speed boost in a pre-defined direction
|
||||
if (savemomx || savemomy)
|
||||
{
|
||||
angle_t momang;
|
||||
INT32 angoffset;
|
||||
boolean subtract = false;
|
||||
|
||||
momang = R_PointToAngle2(0, 0, savemomx, savemomy);
|
||||
|
||||
angoffset = momang;
|
||||
angoffset -= spring->angle; // Subtract
|
||||
|
||||
// Flip on wrong side
|
||||
if ((angle_t)angoffset > ANGLE_180)
|
||||
{
|
||||
angoffset = InvAngle((angle_t)angoffset);
|
||||
subtract = !subtract;
|
||||
}
|
||||
|
||||
// Fix going directly against the spring's angle sending you the wrong way
|
||||
if ((spring->angle - momang) > ANGLE_90)
|
||||
angoffset = ANGLE_180 - angoffset;
|
||||
|
||||
// Offset is reduced to cap it (90 / 2 = max of 45 degrees)
|
||||
angoffset /= 2;
|
||||
|
||||
// Reduce further based on how slow your speed is compared to the spring's speed
|
||||
if (finalSpeed > objectSpeed)
|
||||
angoffset = FixedDiv(angoffset, FixedDiv(finalSpeed, objectSpeed));
|
||||
|
||||
if (subtract)
|
||||
angoffset = (signed)(spring->angle) - angoffset;
|
||||
else
|
||||
angoffset = (signed)(spring->angle) + angoffset;
|
||||
|
||||
finalAngle = angoffset;
|
||||
finalAngle = K_ReflectAngle(
|
||||
R_PointToAngle2(0, 0, savemomx, savemomy), finalAngle,
|
||||
objectSpeed, finalSpeed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
12
src/p_mobj.c
12
src/p_mobj.c
|
|
@ -8369,10 +8369,9 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
|
||||
if (p)
|
||||
{
|
||||
if (p->kartstuff[k_sneakertimer] > mobj->movecount
|
||||
|| p->kartstuff[k_levelbooster] > mobj->movecount)
|
||||
if (p->kartstuff[k_sneakertimer] > mobj->movecount)
|
||||
P_SetMobjState(mobj, S_BOOSTFLAME);
|
||||
mobj->movecount = max(p->kartstuff[k_sneakertimer], p->kartstuff[k_levelbooster]);
|
||||
mobj->movecount = p->kartstuff[k_sneakertimer];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -11428,9 +11427,6 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
|
|||
P_RemoveThinker((thinker_t *)mobj);
|
||||
}
|
||||
|
||||
static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_itemrespawntime = {"respawnitemtime", "2", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_itemrespawn = {"respawnitem", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t flagtime_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, flagtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_suddendeath = {"suddendeath", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
|
@ -11701,10 +11697,6 @@ void P_RespawnSpecials(void)
|
|||
time = (time * 3) / max(1, mapheaderinfo[gamemap-1]->numlaps);
|
||||
}
|
||||
|
||||
// only respawn items when cv_itemrespawn is on
|
||||
//if (!cv_itemrespawn.value) // TODO: remove this cvar
|
||||
//return;
|
||||
|
||||
// nothing left to respawn?
|
||||
if (iquehead == iquetail)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -141,6 +141,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);
|
||||
|
|
@ -291,6 +292,8 @@ static void P_NetArchivePlayers(void)
|
|||
|
||||
// botvars_t
|
||||
WRITEUINT8(save_p, players[i].botvars.difficulty);
|
||||
WRITEUINT8(save_p, players[i].botvars.diffincrease);
|
||||
WRITEUINT8(save_p, players[i].botvars.rival);
|
||||
WRITEUINT32(save_p, players[i].botvars.itemdelay);
|
||||
WRITEUINT32(save_p, players[i].botvars.itemconfirm);
|
||||
WRITESINT8(save_p, players[i].botvars.turnconfirm);
|
||||
|
|
@ -346,6 +349,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
|
||||
|
|
@ -483,6 +487,8 @@ static void P_NetUnArchivePlayers(void)
|
|||
|
||||
// botvars_t
|
||||
players[i].botvars.difficulty = READUINT8(save_p);
|
||||
players[i].botvars.diffincrease = READUINT8(save_p);
|
||||
players[i].botvars.rival = (boolean)READUINT8(save_p);
|
||||
players[i].botvars.itemdelay = READUINT32(save_p);
|
||||
players[i].botvars.itemconfirm = READUINT32(save_p);
|
||||
players[i].botvars.turnconfirm = READSINT8(save_p);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@
|
|||
#include "k_pwrlv.h"
|
||||
#include "k_waypoint.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
//
|
||||
// Map MD5, calculated on level load.
|
||||
|
|
@ -2415,22 +2416,20 @@ static void P_LevelInitStuff(void)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
#if 0
|
||||
if ((netgame || multiplayer) && (gametype == GT_COMPETITION || players[i].lives <= 0))
|
||||
if (grandprixinfo.gp == false)
|
||||
{
|
||||
// In Co-Op, replenish a user's lives if they are depleted.
|
||||
players[i].lives = cv_startinglives.value;
|
||||
players[i].lives = 3;
|
||||
players[i].xtralife = 0;
|
||||
players[i].totalring = 0;
|
||||
}
|
||||
#else
|
||||
players[i].lives = 1; // SRB2Kart
|
||||
#endif
|
||||
|
||||
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;
|
||||
players[i].deadtimer = players[i].numboxes = players[i].laps = 0;
|
||||
players[i].health = 1;
|
||||
players[i].aiming = 0;
|
||||
players[i].pflags &= ~PF_TIMEOVER;
|
||||
|
|
@ -2467,8 +2466,23 @@ static void P_LevelInitStuff(void)
|
|||
}
|
||||
|
||||
// SRB2Kart: map load variables
|
||||
if (modeattacking) // Just play it safe and set everything
|
||||
if (grandprixinfo.gp == true)
|
||||
{
|
||||
if (G_BattleGametype())
|
||||
{
|
||||
gamespeed = KARTSPEED_EASY;
|
||||
}
|
||||
else
|
||||
{
|
||||
gamespeed = grandprixinfo.gamespeed;
|
||||
}
|
||||
|
||||
franticitems = false;
|
||||
comeback = true;
|
||||
}
|
||||
else if (modeattacking)
|
||||
{
|
||||
// Just play it safe and set everything
|
||||
gamespeed = KARTSPEED_HARD;
|
||||
franticitems = false;
|
||||
comeback = true;
|
||||
|
|
@ -2493,11 +2507,6 @@ static void P_LevelInitStuff(void)
|
|||
|
||||
memset(&battleovertime, 0, sizeof(struct battleovertime));
|
||||
speedscramble = encorescramble = -1;
|
||||
|
||||
if (!modeattacking)
|
||||
{
|
||||
K_UpdateMatchRaceBots();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -2682,12 +2691,6 @@ static void P_ForceCharacter(const char *forcecharskin)
|
|||
}
|
||||
|
||||
SetPlayerSkin(consoleplayer, forcecharskin);
|
||||
// normal player colors in single player
|
||||
if ((unsigned)cv_playercolor.value != skins[players[consoleplayer].skin].prefcolor && !modeattacking)
|
||||
{
|
||||
CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor);
|
||||
players[consoleplayer].skincolor = skins[players[consoleplayer].skin].prefcolor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3384,6 +3387,28 @@ 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.gp == true)
|
||||
{
|
||||
if (grandprixinfo.initalize == true)
|
||||
{
|
||||
K_InitGrandPrixBots();
|
||||
grandprixinfo.initalize = false;
|
||||
}
|
||||
else if (grandprixinfo.wonround == true)
|
||||
{
|
||||
K_UpdateGrandPrixBots();
|
||||
grandprixinfo.wonround = 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
|
||||
|
|
@ -3435,9 +3460,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();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
46
src/p_spec.c
46
src/p_spec.c
|
|
@ -4052,52 +4052,38 @@ DoneSection2:
|
|||
|
||||
case 5: // Speed pad w/o spin
|
||||
case 6: // Speed pad w/ spin
|
||||
if (player->kartstuff[k_dashpadcooldown] != 0)
|
||||
if (player->kartstuff[k_floorboost] != 0)
|
||||
{
|
||||
player->kartstuff[k_floorboost] = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
i = P_FindSpecialLineFromTag(4, sector->tag, -1);
|
||||
|
||||
if (i != -1)
|
||||
{
|
||||
angle_t lineangle;
|
||||
fixed_t linespeed;
|
||||
|
||||
lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
||||
linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y);
|
||||
angle_t lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
||||
fixed_t linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y);
|
||||
fixed_t playerspeed = P_AproxDistance(player->mo->momx, player->mo->momy);
|
||||
|
||||
// SRB2Kart: Scale the speed you get from them!
|
||||
// This is scaled differently from other horizontal speed boosts from stuff like springs, because of how this is used for some ramp jumps.
|
||||
if (player->mo->scale > mapobjectscale)
|
||||
linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale));
|
||||
|
||||
if (!(lines[i].flags & ML_EFFECT4))
|
||||
{
|
||||
P_UnsetThingPosition(player->mo);
|
||||
if (roversector) // make FOF speed pads work
|
||||
{
|
||||
player->mo->x = roversector->soundorg.x;
|
||||
player->mo->y = roversector->soundorg.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->mo->x = sector->soundorg.x;
|
||||
player->mo->y = sector->soundorg.y;
|
||||
}
|
||||
P_SetThingPosition(player->mo);
|
||||
linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale));
|
||||
}
|
||||
|
||||
P_InstaThrust(player->mo, lineangle, linespeed);
|
||||
lineangle = K_ReflectAngle(
|
||||
R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy), lineangle,
|
||||
playerspeed, linespeed
|
||||
);
|
||||
|
||||
P_InstaThrust(player->mo, lineangle, max(linespeed, 2*playerspeed));
|
||||
|
||||
player->kartstuff[k_dashpadcooldown] = TICRATE/3;
|
||||
player->kartstuff[k_pogospring] = 0;
|
||||
S_StartSound(player->mo, sfx_spdpad);
|
||||
|
||||
{
|
||||
sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons
|
||||
if (cv_kartvoices.value)
|
||||
S_StartSound(player->mo, sfx_kbost1+pick);
|
||||
//K_TauntVoiceTimers(player);
|
||||
}
|
||||
player->kartstuff[k_floorboost] = 2;
|
||||
S_StartSound(player->mo, sfx_cdfm62);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
165
src/p_user.c
165
src/p_user.c
|
|
@ -40,7 +40,6 @@
|
|||
#include "st_stuff.h"
|
||||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "k_bot.h"
|
||||
// Objectplace
|
||||
#include "m_cheat.h"
|
||||
// SRB2kart
|
||||
|
|
@ -49,6 +48,8 @@
|
|||
#include "k_color.h" // KartColor_Opposite
|
||||
#include "console.h" // CON_LogMessage
|
||||
#include "k_respawn.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
|
@ -950,7 +951,6 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
|
|||
return;
|
||||
|
||||
player->kartstuff[k_rings] += num_rings;
|
||||
//player->totalring += num_rings; // Used for GP lives later
|
||||
|
||||
if (player->kartstuff[k_rings] > 20)
|
||||
player->kartstuff[k_rings] = 20; // Caps at 20 rings, sorry!
|
||||
|
|
@ -968,8 +968,8 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
|
|||
{
|
||||
player->lives += numlives;
|
||||
|
||||
if (player->lives > 99)
|
||||
player->lives = 99;
|
||||
if (player->lives > 9)
|
||||
player->lives = 9;
|
||||
else if (player->lives < 1)
|
||||
player->lives = 1;
|
||||
}
|
||||
|
|
@ -1687,12 +1687,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;
|
||||
|
|
@ -1703,7 +1711,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];
|
||||
|
|
@ -1711,7 +1719,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);
|
||||
|
|
@ -1721,10 +1729,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;
|
||||
}
|
||||
|
|
@ -1736,24 +1740,44 @@ 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.gp == true)
|
||||
{
|
||||
player->climbing = 0;
|
||||
player->pflags |= PF_JUMPED;
|
||||
P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);
|
||||
if (player->bot)
|
||||
{
|
||||
// Bots are going to get harder... :)
|
||||
K_IncreaseBotDifficulty(player);
|
||||
}
|
||||
else if (!losing)
|
||||
{
|
||||
const UINT8 lifethreshold = 20;
|
||||
UINT8 extra = 0;
|
||||
|
||||
// YOU WIN
|
||||
grandprixinfo.wonround = true;
|
||||
|
||||
// Increase your total rings
|
||||
if (RINGTOTAL(player) > 0)
|
||||
{
|
||||
player->totalring += RINGTOTAL(player);
|
||||
|
||||
extra = player->totalring / lifethreshold;
|
||||
|
||||
if (extra > player->xtralife)
|
||||
{
|
||||
P_GivePlayerLives(player, extra - player->xtralife);
|
||||
S_StartSound(NULL, sfx_cdfm73);
|
||||
player->xtralife = extra;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
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
|
||||
|
|
@ -4165,23 +4189,21 @@ static void P_3dMovement(player_t *player)
|
|||
const fixed_t airspeedcap = (50*mapobjectscale);
|
||||
const fixed_t speed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy);
|
||||
|
||||
// If you're going too fast in the air, ease back down to a certain speed.
|
||||
// Helps lots of jumps from breaking when using speed items, since you can't move in the air.
|
||||
if (speed > airspeedcap)
|
||||
{
|
||||
fixed_t div = 32*FRACUNIT;
|
||||
fixed_t newspeed;
|
||||
|
||||
// Make rubberbanding bots slow down faster
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
fixed_t baserubberband = K_BotRubberband(player);
|
||||
fixed_t rubberband = FixedMul(baserubberband,
|
||||
FixedMul(baserubberband,
|
||||
FixedMul(baserubberband,
|
||||
baserubberband
|
||||
))); // This looks extremely goofy, but we need this really high, but at the same time, proportional.
|
||||
fixed_t rubberband = K_BotRubberband(player) - FRACUNIT;
|
||||
|
||||
if (rubberband > FRACUNIT)
|
||||
if (rubberband > 0)
|
||||
{
|
||||
div = FixedMul(div, rubberband);
|
||||
div = FixedDiv(div, FRACUNIT + (rubberband * 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6252,7 +6274,7 @@ static void P_MovePlayer(player_t *player)
|
|||
////////////////////////////
|
||||
|
||||
// SRB2kart - Drifting smoke and fire
|
||||
if ((EITHERSNEAKER(player) || player->kartstuff[k_flamedash])
|
||||
if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_flamedash])
|
||||
&& onground && (leveltime & 1))
|
||||
K_SpawnBoostTrail(player);
|
||||
|
||||
|
|
@ -7095,14 +7117,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
|
||||
|
|
@ -8356,13 +8373,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)
|
||||
{
|
||||
|
|
@ -8370,8 +8402,6 @@ void P_DoTimeOver(player_t *player)
|
|||
P_DamageMobj(player->mo, NULL, NULL, 10000);
|
||||
}
|
||||
|
||||
player->lives = 0;
|
||||
|
||||
P_EndingMusic(player);
|
||||
|
||||
if (!exitcountdown)
|
||||
|
|
@ -8770,7 +8800,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -8778,24 +8808,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8809,33 +8841,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8873,17 +8881,6 @@ 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2925,6 +2925,11 @@ static void Sk_SetDefaultValue(skin_t *skin)
|
|||
strncpy(skin->facewant, "PLAYWANT", 9);
|
||||
strncpy(skin->facemmap, "PLAYMMAP", 9);
|
||||
|
||||
for (i = 0; i < SKINRIVALS; i++)
|
||||
{
|
||||
strcpy(skin->rivals[i], "");
|
||||
}
|
||||
|
||||
skin->starttranscolor = 96;
|
||||
skin->prefcolor = SKINCOLOR_GREEN;
|
||||
|
||||
|
|
@ -3280,6 +3285,45 @@ void R_AddSkins(UINT16 wadnum)
|
|||
strupr(value);
|
||||
strncpy(skin->facemmap, value, sizeof skin->facemmap);
|
||||
}
|
||||
else if (!stricmp(stoken, "rivals"))
|
||||
{
|
||||
size_t len = strlen(value);
|
||||
size_t i;
|
||||
char rivalname[SKINNAMESIZE] = "";
|
||||
UINT8 pos = 0;
|
||||
UINT8 numrivals = 0;
|
||||
|
||||
// Can't use strtok, because this function's already using it.
|
||||
// Using it causes it to upset the saved pointer,
|
||||
// corrupting the reading for the rest of the file.
|
||||
|
||||
// So instead we get to crawl through the value, character by character,
|
||||
// and write it down as we go, until we hit a comma or the end of the string.
|
||||
// Yaaay.
|
||||
|
||||
for (i = 0; i <= len; i++)
|
||||
{
|
||||
if (numrivals >= SKINRIVALS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (value[i] == ',' || i == len)
|
||||
{
|
||||
STRBUFCPY(skin->rivals[numrivals], rivalname);
|
||||
strlwr(skin->rivals[numrivals]);
|
||||
numrivals++;
|
||||
|
||||
memset(rivalname, 0, sizeof (rivalname));
|
||||
pos = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
rivalname[pos] = value[i];
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value);
|
||||
// character type identification
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ void R_DrawMasked(void);
|
|||
// SKINS STUFF
|
||||
// -----------
|
||||
#define SKINNAMESIZE 16
|
||||
#define SKINRIVALS 3
|
||||
// should be all lowercase!! S_SKIN processing does a strlwr
|
||||
#define DEFAULTSKIN "sonic"
|
||||
#define DEFAULTSKIN2 "tails" // secondary player
|
||||
|
|
@ -95,6 +96,8 @@ typedef struct
|
|||
UINT8 prefcolor;
|
||||
fixed_t highresscale; // scale of highres, default is 0.5
|
||||
|
||||
char rivals[SKINRIVALS][SKINNAMESIZE+1]; // Your top 3 rivals for GP mode. Uses names so that you can reference skins that aren't added
|
||||
|
||||
// specific sounds per skin
|
||||
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
|
||||
} skin_t;
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@
|
|||
<ClInclude Include="..\hardware\hw_md3load.h" />
|
||||
<ClInclude Include="..\hardware\hw_model.h" />
|
||||
<ClInclude Include="..\hardware\u_list.h" />
|
||||
<ClInclude Include="..\font.h" />
|
||||
<ClInclude Include="..\hu_stuff.h" />
|
||||
<ClInclude Include="..\info.h" />
|
||||
<ClInclude Include="..\i_addrinfo.h" />
|
||||
|
|
@ -376,6 +377,7 @@
|
|||
<ClCompile Include="..\hardware\hw_trick.c" />
|
||||
<ClCompile Include="..\hardware\r_opengl\r_opengl.c" />
|
||||
<ClCompile Include="..\hardware\u_list.c" />
|
||||
<ClCompile Include="..\font.c" />
|
||||
<ClCompile Include="..\hu_stuff.c" />
|
||||
<ClCompile Include="..\info.c" />
|
||||
<ClCompile Include="..\i_addrinfo.c">
|
||||
|
|
|
|||
|
|
@ -2090,6 +2090,50 @@
|
|||
RelativePath="..\console.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\font.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\font.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\hu_stuff.c"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -655,6 +655,16 @@
|
|||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\font.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hu_stuff.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
|
@ -1366,6 +1376,7 @@
|
|||
<ClInclude Include="..\am_map.h" />
|
||||
<ClInclude Include="..\command.h" />
|
||||
<ClInclude Include="..\console.h" />
|
||||
<ClInclude Include="..\font.h" />
|
||||
<ClInclude Include="..\hu_stuff.h" />
|
||||
<ClInclude Include="..\st_stuff.h" />
|
||||
<ClInclude Include="..\y_inter.h" />
|
||||
|
|
|
|||
|
|
@ -2090,6 +2090,50 @@
|
|||
RelativePath="..\console.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\font.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\font.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\hu_stuff.c"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ extern INT32 st_palette; // 0 is default, any others are special palettes.
|
|||
|
||||
extern lumpnum_t st_borderpatchnum;
|
||||
// patches, also used in intermission
|
||||
extern patch_t *tallnum[10];
|
||||
extern patch_t *sboscore;
|
||||
extern patch_t *sbotime;
|
||||
extern patch_t *sbocolon;
|
||||
|
|
|
|||
923
src/v_video.c
923
src/v_video.c
File diff suppressed because it is too large
Load diff
|
|
@ -173,6 +173,12 @@ void V_DrawCustomFadeScreen(const char *lump, UINT8 strength);
|
|||
void V_DrawFadeConsBack(INT32 plines);
|
||||
void V_EncoreInvertScreen(void);
|
||||
|
||||
/* Convenience macros for leagacy string function macros. */
|
||||
#define V__DrawOneScaleString( x,y,scale,option,font,string ) \
|
||||
V_DrawStringScaled(x,y,scale,FRACUNIT,FRACUNIT,option,font,string)
|
||||
#define V__DrawDupxString( x,y,scale,option,font,string )\
|
||||
V__DrawOneScaleString ((x)<<FRACBITS,(y)<<FRACBITS,scale,option,font,string)
|
||||
|
||||
// draw a single character
|
||||
void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed);
|
||||
// draw a single character, but for the chat
|
||||
|
|
@ -180,27 +186,47 @@ void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UI
|
|||
|
||||
UINT8 *V_GetStringColormap(INT32 colorflags);
|
||||
|
||||
void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
#define V_DrawLevelTitle( x,y,option,string ) \
|
||||
V__DrawDupxString (x,y,FRACUNIT,option,LT_FONT,string)
|
||||
|
||||
// wordwrap a string using the hu_font
|
||||
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string);
|
||||
|
||||
// draw a string using a font
|
||||
void V_DrawStringScaled(
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
fixed_t scale,
|
||||
fixed_t space_scale,
|
||||
fixed_t linefeed_scale,
|
||||
INT32 flags,
|
||||
int font,
|
||||
const char *text);
|
||||
|
||||
// draw a string using the hu_font
|
||||
void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
void V_DrawKartString(INT32 x, INT32 y, INT32 option, const char *string); // SRB2kart
|
||||
#define V_DrawString( x,y,option,string ) \
|
||||
V__DrawDupxString (x,y,FRACUNIT,option,HU_FONT,string)
|
||||
#define V_DrawKartString( x,y,option,string ) \
|
||||
V__DrawDupxString (x,y,FRACUNIT,option,KART_FONT,string)
|
||||
void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
|
||||
// draw a string using the hu_font, 0.5x scale
|
||||
void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
#define V_DrawSmallString( x,y,option,string ) \
|
||||
V__DrawDupxString (x,y,FRACUNIT>>1,option,HU_FONT,string)
|
||||
void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
|
||||
// draw a string using the tny_font
|
||||
void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
#define V_DrawThinString( x,y,option,string ) \
|
||||
V__DrawDupxString (x,y,FRACUNIT,option,TINY_FONT,string)
|
||||
void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
|
||||
void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
#define V_DrawStringAtFixed( x,y,option,string ) \
|
||||
V__DrawOneScaleString (x,y,FRACUNIT,option,HU_FONT,string)
|
||||
|
||||
#define V_DrawThinStringAtFixed( x,y,option,string ) \
|
||||
V__DrawOneScaleString (x,y,FRACUNIT,option,TINY_FONT,string)
|
||||
|
||||
// Draw tall nums, used for menu, HUD, intermission
|
||||
void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num);
|
||||
|
|
@ -214,7 +240,8 @@ void V_DrawPingNum(INT32 x, INT32 y, INT32 flags, INT32 num, const UINT8 *colorm
|
|||
INT32 V_LevelNameWidth(const char *string);
|
||||
INT32 V_LevelNameHeight(const char *string);
|
||||
|
||||
void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
#define V_DrawCreditString( x,y,option,string ) \
|
||||
V__DrawOneScaleString (x,y,FRACUNIT,option,CRED_FONT,string)
|
||||
INT32 V_CreditStringWidth(const char *string);
|
||||
|
||||
// Find string width from hu_font chars
|
||||
|
|
|
|||
|
|
@ -223,6 +223,20 @@
|
|||
<ClCompile Include="..\f_wipe.c" />
|
||||
<ClCompile Include="..\g_game.c" />
|
||||
<ClCompile Include="..\g_input.c" />
|
||||
<ClCompile Include="..\hardware\hw3sound.c" />
|
||||
<ClCompile Include="..\hardware\hw_bsp.c" />
|
||||
<ClCompile Include="..\hardware\hw_cache.c" />
|
||||
<ClCompile Include="..\hardware\hw_clip.c" />
|
||||
<ClCompile Include="..\hardware\hw_draw.c" />
|
||||
<ClCompile Include="..\hardware\hw_light.c" />
|
||||
<ClCompile Include="..\hardware\hw_main.c" />
|
||||
<ClCompile Include="..\hardware\hw_md2.c" />
|
||||
<ClCompile Include="..\hardware\hw_md2load.c" />
|
||||
<ClCompile Include="..\hardware\hw_md3load.c" />
|
||||
<ClCompile Include="..\hardware\hw_model.c" />
|
||||
<ClCompile Include="..\hardware\hw_trick.c" />
|
||||
<ClCompile Include="..\hardware\u_list.c" />
|
||||
<ClCompile Include="..\font.c" />
|
||||
<ClCompile Include="..\hu_stuff.c" />
|
||||
<ClCompile Include="..\info.c" />
|
||||
<ClCompile Include="..\i_addrinfo.c">
|
||||
|
|
@ -376,6 +390,21 @@
|
|||
<ClInclude Include="..\hardware\hw3dsdrv.h" />
|
||||
<ClInclude Include="..\hardware\hw3sound.h" />
|
||||
<ClInclude Include="..\hardware\hws_data.h" />
|
||||
<ClInclude Include="..\hardware\hw_clip.h" />
|
||||
<ClInclude Include="..\hardware\hw_data.h" />
|
||||
<ClInclude Include="..\hardware\hw_defs.h" />
|
||||
<ClInclude Include="..\hardware\hw_dll.h" />
|
||||
<ClInclude Include="..\hardware\hw_drv.h" />
|
||||
<ClInclude Include="..\hardware\hw_glide.h" />
|
||||
<ClInclude Include="..\hardware\hw_glob.h" />
|
||||
<ClInclude Include="..\hardware\hw_light.h" />
|
||||
<ClInclude Include="..\hardware\hw_main.h" />
|
||||
<ClInclude Include="..\hardware\hw_md2.h" />
|
||||
<ClInclude Include="..\hardware\hw_md2load.h" />
|
||||
<ClInclude Include="..\hardware\hw_md3load.h" />
|
||||
<ClInclude Include="..\hardware\hw_model.h" />
|
||||
<ClInclude Include="..\hardware\u_list.h" />
|
||||
<ClInclude Include="..\font.h" />
|
||||
<ClInclude Include="..\hu_stuff.h" />
|
||||
<ClInclude Include="..\info.h" />
|
||||
<ClInclude Include="..\i_addrinfo.h" />
|
||||
|
|
|
|||
|
|
@ -1831,6 +1831,50 @@
|
|||
RelativePath="..\console.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\font.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\font.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\hu_stuff.c"
|
||||
>
|
||||
|
|
|
|||
190
src/y_inter.c
190
src/y_inter.c
|
|
@ -43,6 +43,7 @@
|
|||
#include "k_pwrlv.h"
|
||||
#include "console.h" // cons_menuhighlight
|
||||
#include "lua_hook.h" // IntermissionThinker hook
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
|
|
@ -198,7 +199,12 @@ static void Y_CompareScore(INT32 i)
|
|||
static void Y_CompareRank(INT32 i)
|
||||
{
|
||||
INT16 increase = ((data.match.increase[i] == INT16_MIN) ? 0 : data.match.increase[i]);
|
||||
UINT32 score = (powertype != -1 ? clientpowerlevels[i][powertype] : players[i].score);
|
||||
UINT32 score = players[i].score;
|
||||
|
||||
if (powertype != PWRLV_DISABLED)
|
||||
{
|
||||
score = clientpowerlevels[i][powertype];
|
||||
}
|
||||
|
||||
if (!(data.match.val[data.match.numplayers] == UINT32_MAX || (score - increase) > data.match.val[data.match.numplayers]))
|
||||
return;
|
||||
|
|
@ -302,18 +308,26 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
data.match.name[data.match.numplayers] = player_names[i];
|
||||
|
||||
if (data.match.numplayers && (data.match.val[data.match.numplayers] == data.match.val[data.match.numplayers-1]))
|
||||
data.match.pos[data.match.numplayers] = data.match.pos[data.match.numplayers-1];
|
||||
else
|
||||
data.match.pos[data.match.numplayers] = data.match.numplayers+1;
|
||||
|
||||
if ((!rankingsmode && powertype == -1) // Single player rankings (grand prix). Online rank is handled below.
|
||||
&& !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] < (numplayersingame + numgriefers)))
|
||||
{
|
||||
data.match.increase[i] = (numplayersingame + numgriefers) - data.match.pos[data.match.numplayers];
|
||||
data.match.pos[data.match.numplayers] = data.match.pos[data.match.numplayers-1];
|
||||
}
|
||||
else
|
||||
{
|
||||
data.match.pos[data.match.numplayers] = data.match.numplayers+1;
|
||||
}
|
||||
|
||||
if ((powertype == PWRLV_DISABLED)
|
||||
&& (!rankingsmode)
|
||||
&& !(players[i].pflags & PF_TIMEOVER)
|
||||
&& (data.match.pos[data.match.numplayers] < (numplayersingame + numgriefers)))
|
||||
{
|
||||
// Online rank is handled further below in this file.
|
||||
data.match.increase[i] = K_CalculateGPRankPoints(data.match.pos[data.match.numplayers], numplayersingame + numgriefers);
|
||||
players[i].score += data.match.increase[i];
|
||||
}
|
||||
|
||||
if (demo.recording && !rankingsmode)
|
||||
{
|
||||
G_WriteStanding(
|
||||
data.match.pos[data.match.numplayers],
|
||||
data.match.name[data.match.numplayers],
|
||||
|
|
@ -321,6 +335,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
*data.match.color[data.match.numplayers],
|
||||
data.match.val[data.match.numplayers]
|
||||
);
|
||||
}
|
||||
|
||||
data.match.numplayers++;
|
||||
}
|
||||
|
|
@ -440,9 +455,36 @@ void Y_IntermissionDrawer(void)
|
|||
int y2;
|
||||
|
||||
if (data.match.rankingsmode)
|
||||
timeheader = (powertype != -1 ? "PWR.LV" : "RANK");
|
||||
{
|
||||
if (powertype == PWRLV_DISABLED)
|
||||
{
|
||||
timeheader = "RANK";
|
||||
}
|
||||
else
|
||||
{
|
||||
timeheader = "PWR.LV";
|
||||
}
|
||||
}
|
||||
else
|
||||
timeheader = ((intertype == int_race || (intertype == int_match && battlecapsules)) ? "TIME" : "SCORE");
|
||||
{
|
||||
switch (intertype)
|
||||
{
|
||||
default:
|
||||
case int_race:
|
||||
timeheader = "TIME";
|
||||
break;
|
||||
case int_match:
|
||||
if (battlecapsules)
|
||||
{
|
||||
timeheader = "TIME";
|
||||
}
|
||||
else
|
||||
{
|
||||
timeheader = "SCORE";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the level name
|
||||
V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12, 0, data.match.levelstring);
|
||||
|
|
@ -533,8 +575,11 @@ void Y_IntermissionDrawer(void)
|
|||
|
||||
if (data.match.rankingsmode)
|
||||
{
|
||||
if (powertype != -1 && !clientpowerlevels[data.match.num[i]][powertype]) // No power level (splitscreen guests)
|
||||
if (powertype != PWRLV_DISABLED && !clientpowerlevels[data.match.num[i]][powertype])
|
||||
{
|
||||
// No power level (splitscreen guests)
|
||||
STRBUFCPY(strtime, "----");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data.match.increase[data.match.num[i]] != INT16_MIN)
|
||||
|
|
@ -600,7 +645,7 @@ void Y_IntermissionDrawer(void)
|
|||
}
|
||||
|
||||
dotimer:
|
||||
if (timer)
|
||||
if (timer && grandprixinfo.gp == false)
|
||||
{
|
||||
char *string;
|
||||
INT32 tickdown = (timer+1)/TICRATE;
|
||||
|
|
@ -705,74 +750,73 @@ void Y_Ticker(void)
|
|||
|
||||
if (intertype == int_race || intertype == int_match)
|
||||
{
|
||||
if (netgame || multiplayer)
|
||||
if (!(multiplayer && demo.playback)) // Don't advance to rankings in replays
|
||||
{
|
||||
if (sorttic == -1)
|
||||
sorttic = intertic + max((cv_inttime.value/2)-2, 2)*TICRATE; // 8 second pause after match results
|
||||
else if (!(multiplayer && demo.playback)) // Don't advance to rankings in replays
|
||||
if (!data.match.rankingsmode && (intertic >= sorttic + 8))
|
||||
{
|
||||
if (!data.match.rankingsmode && (intertic >= sorttic + 8))
|
||||
Y_CalculateMatchData(1, Y_CompareRank);
|
||||
Y_CalculateMatchData(1, Y_CompareRank);
|
||||
}
|
||||
|
||||
if (data.match.rankingsmode && intertic > sorttic+16+(2*TICRATE))
|
||||
if (data.match.rankingsmode && intertic > sorttic+16+(2*TICRATE))
|
||||
{
|
||||
INT32 q=0,r=0;
|
||||
boolean kaching = true;
|
||||
|
||||
for (q = 0; q < data.match.numplayers; q++)
|
||||
{
|
||||
INT32 q=0,r=0;
|
||||
boolean kaching = true;
|
||||
|
||||
for (q = 0; q < data.match.numplayers; q++)
|
||||
{
|
||||
if (data.match.num[q] == MAXPLAYERS
|
||||
if (data.match.num[q] == MAXPLAYERS
|
||||
|| !data.match.increase[data.match.num[q]]
|
||||
|| data.match.increase[data.match.num[q]] == INT16_MIN)
|
||||
continue;
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
r++;
|
||||
data.match.jitter[data.match.num[q]] = 1;
|
||||
r++;
|
||||
data.match.jitter[data.match.num[q]] = 1;
|
||||
|
||||
if (powertype != -1)
|
||||
if (powertype != PWRLV_DISABLED)
|
||||
{
|
||||
// Power Levels
|
||||
if (abs(data.match.increase[data.match.num[q]]) < 10)
|
||||
{
|
||||
// Power Levels
|
||||
if (abs(data.match.increase[data.match.num[q]]) < 10)
|
||||
{
|
||||
// Not a lot of point increase left, just set to 0 instantly
|
||||
data.match.increase[data.match.num[q]] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SINT8 remove = 0; // default (should not happen)
|
||||
|
||||
if (data.match.increase[data.match.num[q]] < 0)
|
||||
remove = -10;
|
||||
else if (data.match.increase[data.match.num[q]] > 0)
|
||||
remove = 10;
|
||||
|
||||
// Remove 10 points at a time
|
||||
data.match.increase[data.match.num[q]] -= remove;
|
||||
|
||||
// Still not zero, no kaching yet
|
||||
if (data.match.increase[data.match.num[q]] != 0)
|
||||
kaching = false;
|
||||
}
|
||||
// Not a lot of point increase left, just set to 0 instantly
|
||||
data.match.increase[data.match.num[q]] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Basic bitch points
|
||||
if (data.match.increase[data.match.num[q]])
|
||||
{
|
||||
if (--data.match.increase[data.match.num[q]])
|
||||
kaching = false;
|
||||
}
|
||||
SINT8 remove = 0; // default (should not happen)
|
||||
|
||||
if (data.match.increase[data.match.num[q]] < 0)
|
||||
remove = -10;
|
||||
else if (data.match.increase[data.match.num[q]] > 0)
|
||||
remove = 10;
|
||||
|
||||
// Remove 10 points at a time
|
||||
data.match.increase[data.match.num[q]] -= remove;
|
||||
|
||||
// Still not zero, no kaching yet
|
||||
if (data.match.increase[data.match.num[q]] != 0)
|
||||
kaching = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (r)
|
||||
{
|
||||
S_StartSound(NULL, (kaching ? sfx_chchng : sfx_ptally));
|
||||
Y_CalculateMatchData(2, Y_CompareRank);
|
||||
}
|
||||
else
|
||||
endtic = intertic + 3*TICRATE; // 3 second pause after end of tally
|
||||
{
|
||||
// Basic bitch points
|
||||
if (data.match.increase[data.match.num[q]])
|
||||
{
|
||||
if (--data.match.increase[data.match.num[q]])
|
||||
kaching = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r)
|
||||
{
|
||||
S_StartSound(NULL, (kaching ? sfx_chchng : sfx_ptally));
|
||||
Y_CalculateMatchData(2, Y_CompareRank);
|
||||
}
|
||||
else
|
||||
endtic = intertic + 3*TICRATE; // 3 second pause after end of tally
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1047,19 +1091,11 @@ void Y_StartIntermission(void)
|
|||
#endif
|
||||
|
||||
// set player Power Level type
|
||||
powertype = PWRLV_DISABLED;
|
||||
|
||||
if (netgame && cv_kartusepwrlv.value)
|
||||
{
|
||||
if (G_RaceGametype())
|
||||
powertype = PWRLV_RACE;
|
||||
else if (G_BattleGametype())
|
||||
powertype = PWRLV_BATTLE;
|
||||
}
|
||||
powertype = K_UsingPowerLevels();
|
||||
|
||||
if (!multiplayer)
|
||||
{
|
||||
timer = 0;
|
||||
timer = 20*TICRATE;
|
||||
|
||||
if (!majormods && !multiplayer && !demo.playback) // move this once we have a proper time attack screen
|
||||
{
|
||||
|
|
@ -1078,7 +1114,7 @@ void Y_StartIntermission(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (cv_inttime.value == 0 && gametype == GT_COOP)
|
||||
if (cv_inttime.value == 0)
|
||||
timer = 0;
|
||||
else if (demo.playback) // Override inttime (which is pulled from the replay anyway
|
||||
timer = 10*TICRATE;
|
||||
|
|
@ -1091,6 +1127,8 @@ void Y_StartIntermission(void)
|
|||
}
|
||||
}
|
||||
|
||||
sorttic = max((timer/2) - 2*TICRATE, 2*TICRATE); // 8 second pause after match results
|
||||
|
||||
if (gametype == GT_MATCH)
|
||||
intertype = int_match;
|
||||
else //if (gametype == GT_RACE)
|
||||
|
|
@ -1136,7 +1174,9 @@ void Y_StartIntermission(void)
|
|||
}
|
||||
|
||||
if (powertype != PWRLV_DISABLED)
|
||||
{
|
||||
K_UpdatePowerLevels();
|
||||
}
|
||||
|
||||
//if (intertype == int_race || intertype == int_match)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue