mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-17 05:22:30 +00:00
Merge branch 'master' into the-scary-22-merge
This commit is contained in:
commit
f9ca40e673
96 changed files with 11067 additions and 6981 deletions
|
|
@ -568,7 +568,7 @@ matrix:
|
|||
- p7zip-full
|
||||
- gcc-4.8
|
||||
compiler: gcc-4.8
|
||||
dist: xenial
|
||||
dist: trusty
|
||||
if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
|
||||
AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
|
||||
AND env(DPL_TERMINATE_MAIN) != "1"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
# Core sources
|
||||
set(SRB2_CORE_SOURCES
|
||||
am_map.c
|
||||
b_bot.c
|
||||
command.c
|
||||
comptime.c
|
||||
console.c
|
||||
|
|
@ -20,6 +19,7 @@ set(SRB2_CORE_SOURCES
|
|||
g_game.c
|
||||
g_input.c
|
||||
g_splitscreen.c
|
||||
font.c
|
||||
hu_stuff.c
|
||||
i_tcp.c
|
||||
info.c
|
||||
|
|
@ -37,6 +37,7 @@ set(SRB2_CORE_SOURCES
|
|||
m_random.c
|
||||
md5.c
|
||||
mserv.c
|
||||
http-mserv.c
|
||||
s_sound.c
|
||||
screen.c
|
||||
sounds.c
|
||||
|
|
@ -51,7 +52,6 @@ set(SRB2_CORE_SOURCES
|
|||
|
||||
set(SRB2_CORE_HEADERS
|
||||
am_map.h
|
||||
b_bot.h
|
||||
byteptr.h
|
||||
command.h
|
||||
console.h
|
||||
|
|
@ -77,6 +77,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
|
||||
|
|
@ -102,6 +103,7 @@ set(SRB2_CORE_HEADERS
|
|||
m_swap.h
|
||||
md5.h
|
||||
mserv.h
|
||||
http-mserv.h
|
||||
p5prof.h
|
||||
s_sound.h
|
||||
screen.h
|
||||
|
|
@ -176,6 +178,9 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
k_bot.c
|
||||
k_botitem.c
|
||||
k_botsearch.c
|
||||
k_respawn.c
|
||||
k_grandprix.c
|
||||
k_hud.c
|
||||
|
||||
p_local.h
|
||||
p_maputl.h
|
||||
|
|
@ -196,6 +201,9 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
k_waypoint.h
|
||||
k_color.h
|
||||
k_bot.h
|
||||
k_respawn.h
|
||||
k_grandprix.h
|
||||
k_hud.h
|
||||
)
|
||||
|
||||
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
|
|
|
|||
26
src/Makefile
26
src/Makefile
|
|
@ -446,17 +446,10 @@ 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 \
|
||||
$(OBJDIR)/k_kart.o \
|
||||
$(OBJDIR)/k_collide.o\
|
||||
$(OBJDIR)/k_color.o \
|
||||
$(OBJDIR)/k_battle.o \
|
||||
$(OBJDIR)/k_pwrlv.o \
|
||||
$(OBJDIR)/k_waypoint.o\
|
||||
$(OBJDIR)/k_pathfind.o\
|
||||
$(OBJDIR)/k_bheap.o \
|
||||
$(OBJDIR)/m_aatree.o \
|
||||
$(OBJDIR)/m_anigif.o \
|
||||
$(OBJDIR)/m_argv.o \
|
||||
|
|
@ -510,9 +503,20 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/i_tcp.o \
|
||||
$(OBJDIR)/lzf.o \
|
||||
$(OBJDIR)/vid_copy.o \
|
||||
$(OBJDIR)/k_bot.o \
|
||||
$(OBJDIR)/k_botitem.o \
|
||||
$(OBJDIR)/k_botsearch.o \
|
||||
$(OBJDIR)/k_kart.o \
|
||||
$(OBJDIR)/k_respawn.o\
|
||||
$(OBJDIR)/k_collide.o\
|
||||
$(OBJDIR)/k_color.o \
|
||||
$(OBJDIR)/k_battle.o \
|
||||
$(OBJDIR)/k_pwrlv.o \
|
||||
$(OBJDIR)/k_waypoint.o\
|
||||
$(OBJDIR)/k_pathfind.o\
|
||||
$(OBJDIR)/k_bheap.o \
|
||||
$(OBJDIR)/k_bot.o \
|
||||
$(OBJDIR)/k_botitem.o\
|
||||
$(OBJDIR)/k_botsearch.o\
|
||||
$(OBJDIR)/k_grandprix.o\
|
||||
$(OBJDIR)/k_hud.o \
|
||||
$(i_cdmus_o) \
|
||||
$(i_net_o) \
|
||||
$(i_system_o) \
|
||||
|
|
|
|||
|
|
@ -228,6 +228,9 @@ endif
|
|||
ifndef GCC295
|
||||
WFLAGS+=-Wendif-labels
|
||||
endif
|
||||
ifdef GCC40
|
||||
WFLAGS+=-std=gnu89
|
||||
endif
|
||||
ifdef GCC41
|
||||
WFLAGS+=-Wshadow
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1472,6 +1472,8 @@ void CONS_Printf(const char *fmt, ...)
|
|||
|
||||
Lock_state();
|
||||
|
||||
Lock_state();
|
||||
|
||||
// make sure new text is visible
|
||||
con_scrollup = 0;
|
||||
startup = con_startup;
|
||||
|
|
|
|||
109
src/d_clisrv.c
109
src/d_clisrv.c
|
|
@ -51,6 +51,7 @@
|
|||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifndef NONET
|
||||
// cl loading screen
|
||||
|
|
@ -532,14 +533,11 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
|||
|
||||
for (j = 0; j < NUMPOWERS; ++j)
|
||||
rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]);
|
||||
for (j = 0; j < NUMKARTSTUFF; ++j)
|
||||
rsp->kartstuff[j] = LONG(players[i].kartstuff[j]); // SRB2kart
|
||||
|
||||
rsp->frameangle = (angle_t)LONG(players[i].frameangle); // SRB2kart
|
||||
|
||||
// Score is resynched in the rspfirm resync packet
|
||||
rsp->rings = SHORT(players[i].rings);
|
||||
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;
|
||||
|
|
@ -574,13 +572,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
|||
rsp->weapondelay = LONG(players[i].weapondelay);
|
||||
rsp->tossdelay = LONG(players[i].tossdelay);
|
||||
|
||||
rsp->starpostx = SHORT(players[i].starpostx);
|
||||
rsp->starposty = SHORT(players[i].starposty);
|
||||
rsp->starpostz = SHORT(players[i].starpostz);
|
||||
rsp->starpostnum = LONG(players[i].starpostnum);
|
||||
rsp->starposttime = (tic_t)LONG(players[i].starposttime);
|
||||
rsp->starpostangle = (angle_t)LONG(players[i].starpostangle);
|
||||
rsp->starpostscale = (fixed_t)LONG(players[i].starpostscale);
|
||||
|
||||
rsp->maxlink = LONG(players[i].maxlink);
|
||||
rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed);
|
||||
|
|
@ -608,8 +600,28 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
|||
|
||||
rsp->splitscreenindex = players[i].splitscreenindex;
|
||||
|
||||
// SRB2kart
|
||||
for (j = 0; j < NUMKARTSTUFF; ++j)
|
||||
rsp->kartstuff[j] = LONG(players[i].kartstuff[j]);
|
||||
|
||||
rsp->frameangle = (angle_t)LONG(players[i].frameangle);
|
||||
rsp->airtime = (tic_t)LONG(players[i].airtime);
|
||||
|
||||
// respawnvars_t
|
||||
rsp->respawn_state = players[i].respawn.state;
|
||||
rsp->respawn_pointx = (fixed_t)LONG(players[i].respawn.pointx);
|
||||
rsp->respawn_pointy = (fixed_t)LONG(players[i].respawn.pointy);
|
||||
rsp->respawn_pointz = (fixed_t)LONG(players[i].respawn.pointz);
|
||||
rsp->respawn_flip = players[i].respawn.flip;
|
||||
rsp->respawn_timer = (tic_t)LONG(players[i].respawn.timer);
|
||||
rsp->respawn_distanceleft = (UINT32)LONG(players[i].respawn.distanceleft);
|
||||
rsp->respawn_dropdash = (tic_t)LONG(players[i].respawn.dropdash);
|
||||
|
||||
// botvars_t
|
||||
rsp->bot = players[i].bot;
|
||||
rsp->bot_difficulty = players[i].botvars.difficulty;
|
||||
rsp->bot_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;
|
||||
|
|
@ -668,14 +680,11 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
|
||||
for (j = 0; j < NUMPOWERS; ++j)
|
||||
players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]);
|
||||
for (j = 0; j < NUMKARTSTUFF; ++j)
|
||||
players[i].kartstuff[j] = LONG(rsp->kartstuff[j]); // SRB2kart
|
||||
|
||||
players[i].frameangle = (angle_t)LONG(rsp->frameangle); // SRB2kart
|
||||
|
||||
// Score is resynched in the rspfirm resync packet
|
||||
players[i].rings = SHORT(rsp->rings);
|
||||
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;
|
||||
|
|
@ -709,13 +718,7 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
players[i].weapondelay = LONG(rsp->weapondelay);
|
||||
players[i].tossdelay = LONG(rsp->tossdelay);
|
||||
|
||||
players[i].starpostx = SHORT(rsp->starpostx);
|
||||
players[i].starposty = SHORT(rsp->starposty);
|
||||
players[i].starpostz = SHORT(rsp->starpostz);
|
||||
players[i].starpostnum = LONG(rsp->starpostnum);
|
||||
players[i].starposttime = (tic_t)LONG(rsp->starposttime);
|
||||
players[i].starpostangle = (angle_t)LONG(rsp->starpostangle);
|
||||
players[i].starpostscale = (fixed_t)LONG(rsp->starpostscale);
|
||||
|
||||
players[i].maxlink = LONG(rsp->maxlink);
|
||||
players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed);
|
||||
|
|
@ -743,8 +746,28 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
|
||||
players[i].splitscreenindex = rsp->splitscreenindex;
|
||||
|
||||
// SRB2kart
|
||||
for (j = 0; j < NUMKARTSTUFF; ++j)
|
||||
players[i].kartstuff[j] = LONG(rsp->kartstuff[j]);
|
||||
|
||||
players[i].frameangle = (angle_t)LONG(rsp->frameangle);
|
||||
players[i].airtime = (tic_t)LONG(rsp->airtime);
|
||||
|
||||
// respawnvars_t
|
||||
players[i].respawn.state = rsp->respawn_state;
|
||||
players[i].respawn.pointx = (fixed_t)LONG(rsp->respawn_pointx);
|
||||
players[i].respawn.pointy = (fixed_t)LONG(rsp->respawn_pointy);
|
||||
players[i].respawn.pointz = (fixed_t)LONG(rsp->respawn_pointz);
|
||||
players[i].respawn.flip = (boolean)rsp->respawn_flip;
|
||||
players[i].respawn.timer = (tic_t)LONG(rsp->respawn_timer);
|
||||
players[i].respawn.distanceleft = (UINT32)LONG(rsp->respawn_distanceleft);
|
||||
players[i].respawn.dropdash = (tic_t)LONG(rsp->respawn_dropdash);
|
||||
|
||||
// botvars_t
|
||||
players[i].bot = rsp->bot;
|
||||
players[i].botvars.difficulty = rsp->bot_difficulty;
|
||||
players[i].botvars.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;
|
||||
|
|
@ -1269,7 +1292,7 @@ static boolean CL_AskFileList(INT32 firstfile)
|
|||
netbuffer->packettype = PT_TELLFILESNEEDED;
|
||||
netbuffer->u.filesneedednum = firstfile;
|
||||
|
||||
return HSendPacket(servernode, true, 0, sizeof (INT32));
|
||||
return HSendPacket(servernode, false, 0, sizeof (INT32));
|
||||
}
|
||||
|
||||
/** Sends a special packet to declare how many players in local
|
||||
|
|
@ -2043,11 +2066,11 @@ static boolean CL_FinishedFileList(void)
|
|||
CL_Reset();
|
||||
D_StartTitle();
|
||||
M_StartMessage(M_GetText(
|
||||
"You have WAD files loaded or have\n"
|
||||
"modified the game in some way, and\n"
|
||||
"your file list does not match\n"
|
||||
"the server's file list.\n"
|
||||
"Please restart SRB2Kart before connecting.\n\n"
|
||||
"You have the wrong addons loaded.\n\n"
|
||||
"To play on this server, restart\n"
|
||||
"the game and don't load any addons.\n"
|
||||
"SRB2Kart will automatically add\n"
|
||||
"everything you need when you join.\n\n"
|
||||
"Press ESC\n"
|
||||
), NULL, MM_NOTHING);
|
||||
return false;
|
||||
|
|
@ -2068,11 +2091,12 @@ static boolean CL_FinishedFileList(void)
|
|||
CL_Reset();
|
||||
D_StartTitle();
|
||||
M_StartMessage(M_GetText(
|
||||
"You cannot connect to this server\n"
|
||||
"because you cannot download the files\n"
|
||||
"that you are missing from the server.\n\n"
|
||||
"See the console or log file for\n"
|
||||
"more details.\n\n"
|
||||
"An error occured when trying to\n"
|
||||
"download missing addons.\n"
|
||||
"(This is almost always a problem\n"
|
||||
"with the server, not your game.)\n\n"
|
||||
"See the console or log file\n"
|
||||
"for additional details.\n\n"
|
||||
"Press ESC\n"
|
||||
), NULL, MM_NOTHING);
|
||||
return false;
|
||||
|
|
@ -2798,8 +2822,8 @@ void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
|
|||
RemoveAdminPlayer(playernum); // don't stay admin after you're gone
|
||||
}
|
||||
|
||||
if (playernum == g_localplayers[0] && !demo.playback)
|
||||
g_localplayers[0] = consoleplayer; // don't look through someone's view who isn't there
|
||||
if (playernum == displayplayers[0] && !demo.playback)
|
||||
displayplayers[0] = consoleplayer; // don't look through someone's view who isn't there
|
||||
|
||||
LUA_InvalidatePlayer(&players[playernum]);
|
||||
|
||||
|
|
@ -4458,7 +4482,6 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
static boolean CheckForSpeedHacks(UINT8 p)
|
||||
{
|
||||
if (netcmds[maketic%TICQUEUE][p].forwardmove > MAXPLMOVE || netcmds[maketic%TICQUEUE][p].forwardmove < -MAXPLMOVE
|
||||
|| netcmds[maketic%TICQUEUE][p].sidemove > MAXPLMOVE || netcmds[maketic%TICQUEUE][p].sidemove < -MAXPLMOVE
|
||||
|| netcmds[maketic%TICQUEUE][p].driftturn > KART_FULLTURN || netcmds[maketic%TICQUEUE][p].driftturn < -KART_FULLTURN)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), playernode[p]);
|
||||
|
|
@ -5450,6 +5473,12 @@ static void SV_Maketic(void)
|
|||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (K_PlayerUsesBotMovement(&players[i]))
|
||||
{
|
||||
K_BuildBotTiccmd(&players[i], &netcmds[maketic%TICQUEUE][i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We didn't receive this tic
|
||||
if ((netcmds[maketic % TICQUEUE][i].angleturn & TICCMD_RECEIVED) == 0)
|
||||
{
|
||||
|
|
@ -5909,6 +5938,18 @@ INT32 D_NumPlayers(void)
|
|||
return num;
|
||||
}
|
||||
|
||||
/** Return whether a player is a real person (not a CPU) and not spectating.
|
||||
*/
|
||||
boolean D_IsPlayerHumanAndGaming (INT32 player_number)
|
||||
{
|
||||
player_t * player = &players[player_number];
|
||||
return (
|
||||
playeringame[player_number] &&
|
||||
! player->spectator &&
|
||||
! player->bot
|
||||
);
|
||||
}
|
||||
|
||||
tic_t GetLag(INT32 node)
|
||||
{
|
||||
return gametic - nettics[node];
|
||||
|
|
|
|||
|
|
@ -214,12 +214,10 @@ typedef struct
|
|||
angle_t aiming;
|
||||
UINT16 powers[NUMPOWERS];
|
||||
|
||||
INT32 kartstuff[NUMKARTSTUFF]; // SRB2kart
|
||||
angle_t frameangle; // SRB2kart
|
||||
|
||||
// Score is resynched in the confirm resync packet
|
||||
INT16 rings;
|
||||
SINT8 lives;
|
||||
boolean lostlife;
|
||||
SINT8 continues;
|
||||
UINT8 scoreadd;
|
||||
SINT8 xtralife;
|
||||
|
|
@ -254,13 +252,7 @@ typedef struct
|
|||
INT32 weapondelay;
|
||||
INT32 tossdelay;
|
||||
|
||||
INT16 starpostx;
|
||||
INT16 starposty;
|
||||
INT16 starpostz;
|
||||
INT32 starpostnum;
|
||||
tic_t starposttime;
|
||||
angle_t starpostangle;
|
||||
fixed_t starpostscale;
|
||||
|
||||
INT32 maxlink;
|
||||
fixed_t dashspeed;
|
||||
|
|
@ -287,8 +279,26 @@ typedef struct
|
|||
|
||||
UINT8 splitscreenindex;
|
||||
|
||||
// SRB2kart
|
||||
INT32 kartstuff[NUMKARTSTUFF];
|
||||
angle_t frameangle;
|
||||
tic_t airtime;
|
||||
|
||||
// respawnvars_t
|
||||
UINT8 respawn_state;
|
||||
fixed_t respawn_pointx;
|
||||
fixed_t respawn_pointy;
|
||||
fixed_t respawn_pointz;
|
||||
boolean respawn_flip;
|
||||
tic_t respawn_timer;
|
||||
UINT32 respawn_distanceleft;
|
||||
tic_t respawn_dropdash;
|
||||
|
||||
// botvars_t
|
||||
boolean bot;
|
||||
UINT8 bot_difficulty;
|
||||
UINT8 bot_diffincrease;
|
||||
boolean bot_rival;
|
||||
tic_t bot_itemdelay;
|
||||
tic_t bot_itemconfirm;
|
||||
SINT8 bot_turnconfirm;
|
||||
|
|
@ -664,6 +674,7 @@ extern UINT8 playernode[MAXPLAYERS];
|
|||
extern UINT8 playerconsole[MAXPLAYERS];
|
||||
|
||||
INT32 D_NumPlayers(void);
|
||||
boolean D_IsPlayerHumanAndGaming(INT32 player_number);
|
||||
void D_ResetTiccmds(void);
|
||||
|
||||
tic_t GetLag(INT32 node);
|
||||
|
|
|
|||
118
src/d_main.c
118
src/d_main.c
|
|
@ -65,9 +65,12 @@
|
|||
#include "m_cond.h" // condition initialization
|
||||
#include "fastcmp.h"
|
||||
#include "keys.h"
|
||||
#include "filesrch.h" // refreshdirmenu, mainwadstally
|
||||
#include "filesrch.h" // refreshdirmenu
|
||||
#include "g_input.h" // tutorial mode control scheming
|
||||
|
||||
// SRB2Kart
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifdef CMAKECONFIG
|
||||
#include "config.h"
|
||||
#else
|
||||
|
|
@ -166,35 +169,6 @@ UINT8 shiftdown = 0; // 0x1 left, 0x2 right
|
|||
UINT8 ctrldown = 0; // 0x1 left, 0x2 right
|
||||
UINT8 altdown = 0; // 0x1 left, 0x2 right
|
||||
boolean capslock = 0; // gee i wonder what this does.
|
||||
//
|
||||
// D_ModifierKeyResponder
|
||||
// Sets global shift/ctrl/alt variables, never actually eats events
|
||||
//
|
||||
static inline void D_ModifierKeyResponder(event_t *ev)
|
||||
{
|
||||
if (ev->type == ev_keydown || ev->type == ev_console) switch (ev->data1)
|
||||
{
|
||||
case KEY_LSHIFT: shiftdown |= 0x1; return;
|
||||
case KEY_RSHIFT: shiftdown |= 0x2; return;
|
||||
case KEY_LCTRL: ctrldown |= 0x1; return;
|
||||
case KEY_RCTRL: ctrldown |= 0x2; return;
|
||||
case KEY_LALT: altdown |= 0x1; return;
|
||||
case KEY_RALT: altdown |= 0x2; return;
|
||||
case KEY_CAPSLOCK: capslock = !capslock; return;
|
||||
|
||||
default: return;
|
||||
}
|
||||
else if (ev->type == ev_keyup) switch (ev->data1)
|
||||
{
|
||||
case KEY_LSHIFT: shiftdown &= ~0x1; return;
|
||||
case KEY_RSHIFT: shiftdown &= ~0x2; return;
|
||||
case KEY_LCTRL: ctrldown &= ~0x1; return;
|
||||
case KEY_RCTRL: ctrldown &= ~0x2; return;
|
||||
case KEY_LALT: altdown &= ~0x1; return;
|
||||
case KEY_RALT: altdown &= ~0x2; return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// D_ProcessEvents
|
||||
|
|
@ -1000,6 +974,9 @@ void D_StartTitle(void)
|
|||
modeattacking = ATTACKING_NONE;
|
||||
marathonmode = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
|
|
@ -1382,6 +1359,43 @@ void D_SRB2Main(void)
|
|||
if (M_CheckParm("-server") || dedicated)
|
||||
netgame = server = true;
|
||||
|
||||
if (M_CheckParm("-warp") && M_IsNextParm())
|
||||
{
|
||||
const char *word = M_GetNextParm();
|
||||
char ch; // use this with sscanf to catch non-digits with
|
||||
if (fastncmp(word, "MAP", 3)) // MAPxx name
|
||||
pstartmap = M_MapNumber(word[3], word[4]);
|
||||
else if (sscanf(word, "%d%c", &pstartmap, &ch) != 1) // a plain number
|
||||
I_Error("Cannot warp to map %s (invalid map name)\n", word);
|
||||
// Don't check if lump exists just yet because the wads haven't been loaded!
|
||||
// Just do a basic range check here.
|
||||
if (pstartmap < 1 || pstartmap > NUMMAPS)
|
||||
I_Error("Cannot warp to map %d (out of range)\n", pstartmap);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// adapt tables to SRB2's needs, including extra slots for dehacked file support
|
||||
P_PatchInfoTables();
|
||||
|
||||
|
|
@ -1803,18 +1817,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)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@
|
|||
#define __D_NET__
|
||||
|
||||
// Max computers in a game
|
||||
#define MAXNETNODES 64
|
||||
// 127 is probably as high as this can go, because
|
||||
// SINT8 is used for nodes sometimes >:(
|
||||
#define MAXNETNODES 127
|
||||
#define BROADCASTADDR MAXNETNODES
|
||||
#define NETSPLITSCREEN // Kart's splitscreen netgame feature
|
||||
|
||||
|
|
|
|||
446
src/d_netcmd.c
446
src/d_netcmd.c
|
|
@ -54,6 +54,8 @@
|
|||
#include "k_pwrlv.h"
|
||||
#include "y_inter.h"
|
||||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
#define CV_RESTRICT CV_NETVAR
|
||||
|
|
@ -112,6 +114,16 @@ static void Skin_OnChange(void);
|
|||
static void Skin2_OnChange(void);
|
||||
static void Skin3_OnChange(void);
|
||||
static void Skin4_OnChange(void);
|
||||
|
||||
static void Follower_OnChange(void);
|
||||
static void Follower2_OnChange(void);
|
||||
static void Follower3_OnChange(void);
|
||||
static void Follower4_OnChange(void);
|
||||
static void Followercolor_OnChange(void);
|
||||
static void Followercolor2_OnChange(void);
|
||||
static void Followercolor3_OnChange(void);
|
||||
static void Followercolor4_OnChange(void);
|
||||
|
||||
static void Color_OnChange(void);
|
||||
static void Color2_OnChange(void);
|
||||
static void Color3_OnChange(void);
|
||||
|
|
@ -270,6 +282,23 @@ consvar_t cv_skin[MAXSPLITSCREENPLAYERS] = {
|
|||
{"skin4", DEFAULTSKIN4, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin4_OnChange, 0, NULL, NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
// player's followers. Also saved.
|
||||
consvar_t cv_follower = {"follower", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_follower2 = {"follower2", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_follower3 = {"follower3", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower3_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_follower4 = {"follower4", "-1", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Follower4_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// player's follower colors... Also saved...
|
||||
consvar_t cv_followercolor = {"followercolor", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_followercolor2 = {"followercolor2", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_followercolor3 = {"followercolor3", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor3_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_followercolor4 = {"followercolor4", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
||||
// Follower toggle
|
||||
static CV_PossibleValue_t followers_cons_t[] = {{0, "Yours only"}, {1, "Everyone's"}, {0, NULL}};
|
||||
consvar_t cv_showfollowers = {"showfollowers", "Everyone's", CV_SAVE, followers_cons_t, 0, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_skipmapcheck = {"skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
INT32 cv_debug;
|
||||
|
|
@ -330,6 +359,7 @@ consvar_t cv_hyudoro = {"hyudoro", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NU
|
|||
consvar_t cv_pogospring = {"pogospring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_kitchensink = {"kitchensink", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_dualsneaker = {"dualsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_triplesneaker = {"triplesneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_triplebanana = {"triplebanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_decabanana = {"decabanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
|
@ -732,16 +762,22 @@ void D_RegisterClientCommands(void)
|
|||
|
||||
for (i = 0; i < numskincolors; i++)
|
||||
{
|
||||
Color_cons_t[i].value = i;
|
||||
Color_cons_t[i].strvalue = skincolors[i].name;
|
||||
Color_cons_t[i].value = Followercolor_cons_t[i].value = i;
|
||||
Color_cons_t[i].strvalue = Followercolor_cons_t[i].strvalue = skincolors[i].name;
|
||||
}
|
||||
Color_cons_t[numskincolors].value = 0;
|
||||
Color_cons_t[numskincolors].strvalue = NULL;
|
||||
Color_cons_t[MAXSKINCOLORS].value = Followercolor_cons_t[MAXSKINCOLORS+2].value = 0;
|
||||
Color_cons_t[MAXSKINCOLORS].strvalue = Followercolor_cons_t[MAXSKINCOLORS+2].strvalue = NULL;
|
||||
|
||||
Followercolor_cons_t[MAXSKINCOLORS].value = MAXSKINCOLORS;
|
||||
Followercolor_cons_t[MAXSKINCOLORS].strvalue = "Match"; // Add "Match" option, which will make the follower color match the player's
|
||||
|
||||
Followercolor_cons_t[MAXSKINCOLORS+1].value = MAXSKINCOLORS+1;
|
||||
Followercolor_cons_t[MAXSKINCOLORS+1].strvalue = "Opposite"; // Add "Opposite" option, ...which is like "Match", but for coloropposite.
|
||||
|
||||
// Set default player names
|
||||
// Monster Iestyn (12/08/19): not sure where else I could have actually put this, but oh well
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
sprintf(player_names[i], "Player %d", 1 + i);
|
||||
sprintf(player_names[i], "Player %c", 'A' + i); // SRB2Kart: Letters like Sonic 3!
|
||||
|
||||
if (dedicated)
|
||||
return;
|
||||
|
|
@ -816,11 +852,16 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_playername[i]);
|
||||
CV_RegisterVar(&cv_playercolor[i]);
|
||||
CV_RegisterVar(&cv_skin[i]);
|
||||
CV_RegisterVar(&cv_follower[i]);
|
||||
CV_RegisterVar(&cv_followercolor[i]);
|
||||
}
|
||||
|
||||
// preferred number of players
|
||||
CV_RegisterVar(&cv_splitplayers);
|
||||
|
||||
// Display other players' followers
|
||||
CV_RegisterVar(&cv_showfollowers);
|
||||
|
||||
#ifdef SEENAMES
|
||||
CV_RegisterVar(&cv_seenames);
|
||||
#endif
|
||||
|
|
@ -1326,7 +1367,7 @@ static void SendNameAndColor(UINT8 n)
|
|||
const INT32 playernum = g_localplayers[n];
|
||||
player_t *player = &players[playernum];
|
||||
|
||||
char buf[MAXPLAYERNAME+6];
|
||||
char buf[MAXPLAYERNAME+9];
|
||||
char *p;
|
||||
|
||||
if (splitscreen < playernum)
|
||||
|
|
@ -1353,6 +1394,14 @@ static void SendNameAndColor(UINT8 n)
|
|||
}
|
||||
}
|
||||
|
||||
// ditto for follower colour:
|
||||
if (!cv_followercolor[n].value)
|
||||
CV_StealthSet(&cv_followercolor[n], "Match"); // set it to "Match". I don't care about your stupidity!
|
||||
|
||||
// so like, this is sent before we even use anything like cvars or w/e so it's possible that follower is set to a pretty yikes value, so let's fix that before we send garbage that could crash the game:
|
||||
if (cv_follower[n].value > numfollowers-1 || cv_follower[n].value < -1)
|
||||
CV_StealthSet(&cv_follower[n], "-1");
|
||||
|
||||
if (!strcmp(cv_playername[n].string, player_names[playernum])
|
||||
&& cv_playercolor[n].value == player->skincolor
|
||||
&& !strcmp(cv_skin[n].string, skins[player->skin].name))
|
||||
|
|
@ -1377,6 +1426,10 @@ static void SendNameAndColor(UINT8 n)
|
|||
if (player->mo && !player->powers[pw_dye])
|
||||
player->mo->color = player->skincolor;
|
||||
|
||||
// Update follower for local games:
|
||||
if (cv_follower[n].value >= -1 && cv_follower[n].value != player->followerskin)
|
||||
SetFollower(playernum, cv_follower[n].value);
|
||||
|
||||
if (metalrecording && n == 0)
|
||||
{ // Starring Metal Sonic as themselves, obviously.
|
||||
SetPlayerSkinByNum(playernum, 5);
|
||||
|
|
@ -1425,6 +1478,8 @@ static void SendNameAndColor(UINT8 n)
|
|||
WRITEUINT32(p, (UINT32)player->availabilities);
|
||||
WRITEUINT16(p, (UINT16)cv_playercolor[n].value);
|
||||
WRITEUINT8(p, (UINT8)cv_skin[n].value);
|
||||
WRITESINT8(p, (UINT8)cv_follower[n].value);
|
||||
WRITESINT8(p, (UINT8)cv_followercolor[n].value);
|
||||
SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf);
|
||||
}
|
||||
|
||||
|
|
@ -2259,6 +2314,12 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
|
|||
if ((netgame || multiplayer) && !((gametype == newgametype) && (gametypedefaultrules[newgametype] & GTR_CAMPAIGN)))
|
||||
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;
|
||||
|
|
@ -2297,6 +2358,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
|
|||
}
|
||||
|
||||
chmappending++;
|
||||
|
||||
if (netgame)
|
||||
WRITEUINT32(buf_p, M_RandomizedSeed()); // random seed
|
||||
SendNetXCmd(XD_MAP, buf, buf_p - buf);
|
||||
|
|
@ -2469,7 +2531,7 @@ static void Command_Map_f(void)
|
|||
|
||||
mustmodifygame = !(netgame || multiplayer) && !majormods;
|
||||
|
||||
if (mustmodifygame && !option_force)
|
||||
if (mustmodifygame)
|
||||
{
|
||||
/* May want to be more descriptive? */
|
||||
CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n"));
|
||||
|
|
@ -2526,6 +2588,7 @@ static void Command_Map_f(void)
|
|||
if (mustmodifygame && option_force)
|
||||
{
|
||||
G_SetGameModified(multiplayer, true);
|
||||
startgp = true;
|
||||
}
|
||||
|
||||
// new gametype value
|
||||
|
|
@ -2580,6 +2643,69 @@ static void Command_Map_f(void)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!option_force && newgametype == gametype) // SRB2Kart
|
||||
newresetplayers = false; // if not forcing and gametypes is the same
|
||||
|
||||
|
|
@ -4087,14 +4213,16 @@ static void PointLimit_OnChange(void)
|
|||
|
||||
static void NumLaps_OnChange(void)
|
||||
{
|
||||
if (!(gametyperules & GTR_CIRCUIT) || (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
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
|
|
@ -4636,14 +4764,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);
|
||||
|
|
@ -4898,6 +5026,198 @@ static void Name4_OnChange(void)
|
|||
SendNameAndColor(3);
|
||||
}
|
||||
|
||||
// sends the follower change for players
|
||||
static void Follower_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
char set[10]; // This isn't Lua and mixed declarations in the middle of code make caveman compilers scream.
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower.string);
|
||||
strcpy(cpy, cv_follower.string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower, "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor();
|
||||
return;
|
||||
}
|
||||
|
||||
num = R_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
sprintf(set, "%d", num);
|
||||
CV_StealthSet(&cv_follower, set); // set it to a number. It's easier for us to send later :)
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor();
|
||||
}
|
||||
|
||||
// About the same as Color_OnChange but for followers.
|
||||
static void Followercolor_OnChange(void)
|
||||
{
|
||||
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(consoleplayer))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor();
|
||||
}
|
||||
}
|
||||
|
||||
// repeat for the 3 other players
|
||||
|
||||
static void Follower2_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
if (!Playing() || !splitscreen)
|
||||
return; // do whatever you want
|
||||
|
||||
strcpy(str, cv_follower2.string);
|
||||
strcpy(cpy, cv_follower2.string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower2, "-1");
|
||||
SendNameAndColor2();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
INT32 num = R_FollowerAvailable(str);
|
||||
char set[10];
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
sprintf(set, "%d", num);
|
||||
CV_StealthSet(&cv_follower2, set); // set it to a number. It's easier for us to send later :)
|
||||
}
|
||||
}
|
||||
SendNameAndColor2();
|
||||
}
|
||||
|
||||
static void Followercolor2_OnChange(void)
|
||||
{
|
||||
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[1]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor2();
|
||||
}
|
||||
}
|
||||
|
||||
static void Follower3_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
if (!Playing() || !splitscreen)
|
||||
return; // do whatever you want
|
||||
|
||||
strcpy(str, cv_follower3.string);
|
||||
strcpy(cpy, cv_follower3.string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower3, "-1");
|
||||
SendNameAndColor3();
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
INT32 num = R_FollowerAvailable(str);
|
||||
char set[10];
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
sprintf(set, "%d", num);
|
||||
CV_StealthSet(&cv_follower3, set); // set it to a number. It's easier for us to send later :)
|
||||
}
|
||||
}
|
||||
SendNameAndColor3();
|
||||
}
|
||||
|
||||
static void Followercolor3_OnChange(void)
|
||||
{
|
||||
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[2]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor3();
|
||||
}
|
||||
}
|
||||
|
||||
static void Follower4_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
if (!Playing() || !splitscreen)
|
||||
return; // do whatever you want
|
||||
|
||||
strcpy(str, cv_follower4.string);
|
||||
strcpy(cpy, cv_follower4.string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower4, "-1");
|
||||
SendNameAndColor4();
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
INT32 num = R_FollowerAvailable(str);
|
||||
char set[10];
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
sprintf(set, "%d", num);
|
||||
CV_StealthSet(&cv_follower4, set); // set it to a number. It's easier for us to send later :)
|
||||
}
|
||||
}
|
||||
SendNameAndColor4();
|
||||
}
|
||||
|
||||
static void Followercolor4_OnChange(void)
|
||||
{
|
||||
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[3]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor4();
|
||||
}
|
||||
}
|
||||
|
||||
/** Sends a skin change for the console player, unless that player is moving.
|
||||
* \sa cv_skin, Skin2_OnChange, Color_OnChange
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
|
|
@ -5156,24 +5476,35 @@ static void Command_ShowTime_f(void)
|
|||
// SRB2Kart: On change messages
|
||||
static void BaseNumLaps_OnChange(void)
|
||||
{
|
||||
if (gametyperules & GTR_CIRCUIT && 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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5186,47 +5517,56 @@ static void KartSpeed_OnChange(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((gametyperules & GTR_CIRCUIT))
|
||||
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 ((gametyperules & GTR_CIRCUIT))
|
||||
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 (gametyperules & GTR_KARMA)
|
||||
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 ((gametyperules & GTR_CIRCUIT) && cv_karteliminatelast.value)
|
||||
P_CheckRacers();
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
CV_StealthSet(&cv_karteliminatelast, cv_karteliminatelast.defaultvalue);
|
||||
}
|
||||
|
||||
P_CheckRacers();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,14 @@
|
|||
extern consvar_t cv_playername[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_playercolor[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_skin[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_follower[MAXSPLITSCREENPLAYERS];
|
||||
extern consvar_t cv_followercolor[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
// preferred number of players
|
||||
extern consvar_t cv_splitplayers;
|
||||
|
||||
extern consvar_t cv_showfollowers;
|
||||
|
||||
#ifdef SEENAMES
|
||||
extern consvar_t cv_seenames, cv_allowseenames;
|
||||
#endif
|
||||
|
|
@ -69,7 +74,7 @@ extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink;
|
|||
extern consvar_t cv_thundershield, cv_bubbleshield, cv_flameshield;
|
||||
extern consvar_t cv_hyudoro, cv_pogospring, cv_kitchensink;
|
||||
|
||||
extern consvar_t cv_triplesneaker, cv_triplebanana, cv_decabanana;
|
||||
extern consvar_t cv_dualsneaker, cv_triplesneaker, cv_triplebanana, cv_decabanana;
|
||||
extern consvar_t cv_tripleorbinaut, cv_quadorbinaut, cv_dualjawz;
|
||||
|
||||
extern consvar_t cv_kartminimap;
|
||||
|
|
|
|||
|
|
@ -1651,7 +1651,7 @@ void CURLPrepareFile(const char* url, int dfilenum)
|
|||
// Only allow HTTP and HTTPS
|
||||
curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
|
||||
|
||||
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents.
|
||||
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d", VERSION, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents.
|
||||
|
||||
// Follow a redirect request, if sent by the server.
|
||||
curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
|
|
|||
|
|
@ -270,7 +270,8 @@ typedef enum
|
|||
NUMKARTITEMS,
|
||||
|
||||
// Additional roulette numbers, only used for K_KartGetItemResult
|
||||
KRITEM_TRIPLESNEAKER = NUMKARTITEMS,
|
||||
KRITEM_DUALSNEAKER = NUMKARTITEMS,
|
||||
KRITEM_TRIPLESNEAKER,
|
||||
KRITEM_TRIPLEBANANA,
|
||||
KRITEM_TENFOLDBANANA,
|
||||
KRITEM_TRIPLEORBINAUT,
|
||||
|
|
@ -297,9 +298,6 @@ typedef enum
|
|||
k_position, // Used for Kart positions, mostly for deterministic stuff
|
||||
k_oldposition, // Used for taunting when you pass someone
|
||||
k_positiondelay, // Used for position number, so it can grow when passing/being passed
|
||||
k_starpostflip, // the last starpost we hit requires flipping?
|
||||
k_respawn, // Timer for the DEZ laser respawn effect
|
||||
k_dropdash, // Charge up for respawn Drop Dash
|
||||
|
||||
k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir")
|
||||
k_instashield, // Instashield no-damage animation timer
|
||||
|
|
@ -323,13 +321,16 @@ typedef enum
|
|||
k_jmp, // In Mario Kart, letting go of the jump button stops the drift
|
||||
k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed
|
||||
k_pogospring, // Pogo spring bounce effect
|
||||
k_brakestop, // Wait until you've made a complete stop for a few tics before letting brake go in reverse.
|
||||
k_spindash, // Spindash charge timer
|
||||
k_spindashspeed, // Spindash release speed
|
||||
k_spindashboost, // Spindash release boost timer
|
||||
k_waterskip, // Water skipping counter
|
||||
k_dashpadcooldown, // Separate the vanilla SA-style dash pads from using pw_flashing
|
||||
k_numboosts, // Count of how many boosts are being stacked, for after image spawning
|
||||
k_boostpower, // Base boost value, for offroad
|
||||
k_speedboost, // Boost value smoothing for max speed
|
||||
k_accelboost, // Boost value smoothing for acceleration
|
||||
k_handleboost, // Boost value smoothing for handling
|
||||
k_draftpower, // Drafting power (from 0 to FRACUNIT), doubles your top speed & acceleration at max
|
||||
k_draftleeway, // Leniency timer before removing draft power
|
||||
k_lastdraft, // Last player being drafted
|
||||
|
|
@ -352,8 +353,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
|
||||
|
|
@ -410,6 +411,9 @@ typedef enum
|
|||
khud_lapanimation, // Used to show the lap start wing logo animation
|
||||
khud_laphand, // Lap hand gfx to use; 0 = none, 1 = :ok_hand:, 2 = :thumbs_up:, 3 = :thumps_down:
|
||||
|
||||
// Start
|
||||
khud_fault, // Set when faulting during the starting countdown
|
||||
|
||||
// Camera
|
||||
khud_boostcam, // Camera push forward on boost
|
||||
khud_destboostcam, // Ditto
|
||||
|
|
@ -427,9 +431,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])
|
||||
|
||||
|
|
@ -453,15 +454,31 @@ typedef enum
|
|||
RW_RAIL = 32
|
||||
} ringweapons_t;
|
||||
|
||||
// player_t struct for all respawn variables
|
||||
typedef struct respawnvars_s
|
||||
{
|
||||
UINT8 state; // 0: not respawning, 1: heading towards respawn point, 2: about to drop
|
||||
waypoint_t *wp; // Waypoint that we're going towards, NULL if the position isn't linked to one
|
||||
fixed_t pointx; // Respawn position coords to go towards
|
||||
fixed_t pointy;
|
||||
fixed_t pointz;
|
||||
boolean flip; // Flip upside down or not
|
||||
tic_t timer; // Time left on respawn animation once you're there
|
||||
UINT32 distanceleft; // How far along the course to respawn you
|
||||
tic_t dropdash; // Drop Dash charge timer
|
||||
} respawnvars_t;
|
||||
|
||||
// player_t struct for all bot variables
|
||||
typedef struct botvars_s
|
||||
{
|
||||
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;
|
||||
|
||||
// ========================================================================
|
||||
|
|
@ -514,6 +531,8 @@ typedef struct player_s
|
|||
INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right
|
||||
UINT32 distancetofinish;
|
||||
waypoint_t *nextwaypoint;
|
||||
respawnvars_t respawn; // Respawn info
|
||||
tic_t airtime; // Keep track of how long you've been in the air
|
||||
|
||||
// Bit flags.
|
||||
// See pflags_t, above.
|
||||
|
|
@ -538,6 +557,12 @@ typedef struct player_s
|
|||
// SRB2kart
|
||||
UINT8 kartspeed; // Kart speed stat between 1 and 9
|
||||
UINT8 kartweight; // Kart weight stat between 1 and 9
|
||||
|
||||
INT32 followerskin; // Kart: This player's follower "skin"
|
||||
boolean followerready; // Kart: Used to know when we can have a follower or not. (This is set on the first NameAndColor follower update)
|
||||
UINT8 followercolor; // Kart: Used to store the follower colour the player wishes to use
|
||||
mobj_t *follower; // Kart: This is the follower object we have. (If any)
|
||||
|
||||
//
|
||||
|
||||
UINT32 charflags; // Extra abilities/settings for skins (combinable stuff)
|
||||
|
|
@ -546,7 +571,8 @@ typedef struct player_s
|
|||
mobjtype_t followitem; // Object # to spawn for Smiles
|
||||
mobj_t *followmobj; // Smiles all around
|
||||
|
||||
SINT8 lives; // number of lives
|
||||
SINT8 lives;
|
||||
boolean lostlife;
|
||||
SINT8 continues; // continues that player has acquired
|
||||
|
||||
SINT8 xtralife; // Ring Extra Life counter
|
||||
|
|
@ -583,6 +609,7 @@ typedef struct player_s
|
|||
INT16 totalring; // Total number of rings obtained for Race Mode
|
||||
tic_t realtime; // integer replacement for leveltime
|
||||
UINT8 laps; // Number of laps (optional)
|
||||
INT32 starpostnum; // The number of the last starpost you hit
|
||||
|
||||
////////////////////
|
||||
// CTF Mode Stuff //
|
||||
|
|
@ -593,15 +620,6 @@ typedef struct player_s
|
|||
INT32 weapondelay; // Delay (if any) to fire the weapon again
|
||||
INT32 tossdelay; // Delay (if any) to toss a flag/emeralds again
|
||||
|
||||
// Starpost information
|
||||
INT16 starpostx;
|
||||
INT16 starposty;
|
||||
INT16 starpostz;
|
||||
INT32 starpostnum; // The number of the last starpost you hit
|
||||
tic_t starposttime; // Your time when you hit the starpost
|
||||
angle_t starpostangle; // Angle that the starpost is facing - you respawn facing this way
|
||||
fixed_t starpostscale; // Scale of the player; if negative, player is gravflipped
|
||||
|
||||
/////////////////
|
||||
// NiGHTS Stuff//
|
||||
/////////////////
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ typedef enum
|
|||
BT_BACKWARD = 1<<6, // Aim Item Backward
|
||||
BT_LOOKBACK = 1<<7, // Look Backward
|
||||
|
||||
BT_EBRAKEMASK = (BT_ACCELERATE|BT_BRAKE),
|
||||
|
||||
// free: 1<<8 to 1<<12
|
||||
|
||||
// Lua garbage
|
||||
|
|
@ -58,7 +60,6 @@ typedef enum
|
|||
typedef struct
|
||||
{
|
||||
SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50)
|
||||
SINT8 sidemove; // -MAXPLMOVE to MAXPLMOVE (50)
|
||||
INT16 angleturn; // <<16 for angle delta - saved as 1 byte into demos
|
||||
INT16 aiming; // vertical aiming, see G_BuildTicCmd
|
||||
UINT16 buttons;
|
||||
|
|
|
|||
557
src/dehacked.c
557
src/dehacked.c
|
|
@ -38,6 +38,7 @@
|
|||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "r_things.h" // for followers
|
||||
|
||||
#include "m_cond.h"
|
||||
|
||||
|
|
@ -634,6 +635,271 @@ static void readfreeslots(MYFILE *f)
|
|||
Z_Free(s);
|
||||
}
|
||||
|
||||
// This here is our current only way to make followers.
|
||||
INT32 numfollowers = 0;
|
||||
|
||||
static void readfollower(MYFILE *f)
|
||||
{
|
||||
char *s;
|
||||
char *word, *word2, dname[SKINNAMESIZE+1];
|
||||
char *tmp;
|
||||
char testname[SKINNAMESIZE];
|
||||
|
||||
boolean nameset;
|
||||
INT32 fallbackstate = 0;
|
||||
INT32 res;
|
||||
INT32 i;
|
||||
|
||||
if (numfollowers > MAXSKINS)
|
||||
{
|
||||
deh_warning("Error: Too many followers, cannot add anymore.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
||||
// Ready the default variables for followers. We will overwrite them as we go! We won't set the name or states RIGHT HERE as this is handled down instead.
|
||||
followers[numfollowers].scale = FRACUNIT;
|
||||
followers[numfollowers].bubblescale = 0; // No bubble by default
|
||||
followers[numfollowers].atangle = 230;
|
||||
followers[numfollowers].dist = 32; // changed from 16 to 32 to better account for ogl models
|
||||
followers[numfollowers].height = 16;
|
||||
followers[numfollowers].zoffs = 32;
|
||||
followers[numfollowers].horzlag = 2;
|
||||
followers[numfollowers].vertlag = 6;
|
||||
followers[numfollowers].bobspeed = TICRATE*2;
|
||||
followers[numfollowers].bobamp = 4;
|
||||
followers[numfollowers].hitconfirmtime = TICRATE;
|
||||
followers[numfollowers].defaultcolor = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if (myfgets(s, MAXLINELEN, f))
|
||||
{
|
||||
if (s[0] == '\n')
|
||||
break;
|
||||
|
||||
tmp = strchr(s, '#');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
if (s == tmp)
|
||||
continue; // Skip comment lines, but don't break.
|
||||
|
||||
word = strtok(s, " ");
|
||||
if (word)
|
||||
strupr(word);
|
||||
else
|
||||
break;
|
||||
|
||||
word2 = strtok(NULL, " = ");
|
||||
|
||||
if (!word2)
|
||||
break;
|
||||
|
||||
if (word2[strlen(word2)-1] == '\n')
|
||||
word2[strlen(word2)-1] = '\0';
|
||||
|
||||
if (fastcmp(word, "NAME"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%s", followers[numfollowers].name), UNDO_NONE);
|
||||
strcpy(followers[numfollowers].name, word2);
|
||||
nameset = true;
|
||||
}
|
||||
else if (fastcmp(word, "DEFAULTCOLOR"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].defaultcolor), UNDO_NONE);
|
||||
followers[numfollowers].defaultcolor = (UINT8)get_number(word2);
|
||||
}
|
||||
|
||||
else if (fastcmp(word, "SCALE"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].scale), UNDO_NONE);
|
||||
followers[numfollowers].scale = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "BUBBLESCALE"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].bubblescale), UNDO_NONE);
|
||||
followers[numfollowers].bubblescale = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "ATANGLE"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].atangle), UNDO_NONE);
|
||||
followers[numfollowers].atangle = (INT32)atoi(word2);
|
||||
}
|
||||
else if (fastcmp(word, "HORZLAG"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].horzlag), UNDO_NONE);
|
||||
followers[numfollowers].horzlag = (INT32)atoi(word2);
|
||||
}
|
||||
else if (fastcmp(word, "VERTLAG"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].vertlag), UNDO_NONE);
|
||||
followers[numfollowers].vertlag = (INT32)atoi(word2);
|
||||
}
|
||||
else if (fastcmp(word, "BOBSPEED"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].bobspeed), UNDO_NONE);
|
||||
followers[numfollowers].bobspeed = (INT32)atoi(word2);
|
||||
}
|
||||
else if (fastcmp(word, "BOBAMP"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].bobamp), UNDO_NONE);
|
||||
followers[numfollowers].bobamp = (INT32)atoi(word2);
|
||||
}
|
||||
else if (fastcmp(word, "ZOFFSET") || (fastcmp(word, "ZOFFS")))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].zoffs), UNDO_NONE);
|
||||
followers[numfollowers].zoffs = (INT32)atoi(word2);
|
||||
}
|
||||
else if (fastcmp(word, "DISTANCE") || (fastcmp(word, "DIST")))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].dist), UNDO_NONE);
|
||||
followers[numfollowers].dist = (INT32)atoi(word2);
|
||||
}
|
||||
else if (fastcmp(word, "HEIGHT"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].height), UNDO_NONE);
|
||||
followers[numfollowers].height = (INT32)atoi(word2);
|
||||
}
|
||||
else if (fastcmp(word, "IDLESTATE"))
|
||||
{
|
||||
if (word2)
|
||||
strupr(word2);
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].idlestate), UNDO_NONE);
|
||||
followers[numfollowers].idlestate = get_number(word2);
|
||||
fallbackstate = followers[numfollowers].idlestate;
|
||||
}
|
||||
else if (fastcmp(word, "FOLLOWSTATE"))
|
||||
{
|
||||
if (word2)
|
||||
strupr(word2);
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].followstate), UNDO_NONE);
|
||||
followers[numfollowers].followstate = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "HURTSTATE"))
|
||||
{
|
||||
if (word2)
|
||||
strupr(word2);
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].hurtstate), UNDO_NONE);
|
||||
followers[numfollowers].hurtstate = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "LOSESTATE"))
|
||||
{
|
||||
if (word2)
|
||||
strupr(word2);
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].losestate), UNDO_NONE);
|
||||
followers[numfollowers].losestate = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "WINSTATE"))
|
||||
{
|
||||
if (word2)
|
||||
strupr(word2);
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].winstate), UNDO_NONE);
|
||||
followers[numfollowers].winstate = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "HITSTATE") || (fastcmp(word, "HITCONFIRMSTATE")))
|
||||
{
|
||||
if (word2)
|
||||
strupr(word2);
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].hitconfirmstate), UNDO_NONE);
|
||||
followers[numfollowers].hitconfirmstate = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "HITTIME") || (fastcmp(word, "HITCONFIRMTIME")))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%d", followers[numfollowers].hitconfirmtime), UNDO_NONE);
|
||||
followers[numfollowers].hitconfirmtime = (INT32)atoi(word2);
|
||||
}
|
||||
else
|
||||
deh_warning("Follower %d: unknown word '%s'", numfollowers, word);
|
||||
}
|
||||
} while (!myfeof(f)); // finish when the line is empty
|
||||
|
||||
if (!nameset) // well this is problematic.
|
||||
{
|
||||
strcpy(followers[numfollowers].name, va("Follower%d", numfollowers)); // this is lazy, so what
|
||||
}
|
||||
|
||||
// set skin name (this is just the follower's name in lowercases):
|
||||
// but before we do, let's... actually check if another follower isn't doing the same shit...
|
||||
|
||||
strcpy(testname, followers[numfollowers].name);
|
||||
|
||||
// lower testname for skin checks...
|
||||
strlwr(testname);
|
||||
res = R_FollowerAvailable(testname);
|
||||
if (res > -1) // yikes, someone else has stolen our name already
|
||||
{
|
||||
INT32 startlen = strlen(testname);
|
||||
char cpy[2];
|
||||
//deh_warning("There was already a follower with the same name. (%s)", testname); This warning probably isn't necessary anymore?
|
||||
sprintf(cpy, "%d", numfollowers);
|
||||
memcpy(&testname[startlen], cpy, 2);
|
||||
// in that case, we'll be very lazy and copy numfollowers to the end of our skin name.
|
||||
}
|
||||
|
||||
strcpy(followers[numfollowers].skinname, testname);
|
||||
strcpy(dname, followers[numfollowers].skinname); // display name, just used for printing succesful stuff or errors later down the line.
|
||||
|
||||
// now that the skin name is ready, post process the actual name to turn the underscores into spaces!
|
||||
for (i = 0; followers[numfollowers].name[i]; i++)
|
||||
{
|
||||
if (followers[numfollowers].name[i] == '_')
|
||||
followers[numfollowers].name[i] = ' ';
|
||||
}
|
||||
|
||||
// fallbacks for variables
|
||||
// Print a warning if the variable is on a weird value and set it back to the minimum available if that's the case.
|
||||
#define FALLBACK(field, field2, threshold, set) \
|
||||
if (followers[numfollowers].field < threshold) \
|
||||
{ \
|
||||
followers[numfollowers].field = set; \
|
||||
deh_warning("Follower '%s': Value for '%s' is too low! Minimum should be %d. Value was overwritten to %d.", dname, field2, set, set); \
|
||||
} \
|
||||
|
||||
FALLBACK(dist, "DIST", 0, 0);
|
||||
FALLBACK(height, "HEIGHT", 1, 1);
|
||||
FALLBACK(zoffs, "ZOFFS", 0, 0);
|
||||
FALLBACK(horzlag, "HORZLAG", 1, 1);
|
||||
FALLBACK(vertlag, "VERTLAG", 1, 1);
|
||||
FALLBACK(bobamp, "BOBAMP", 0, 0);
|
||||
FALLBACK(bobspeed, "BOBSPEED", 0, 0);
|
||||
FALLBACK(hitconfirmtime, "HITCONFIRMTIME", 1, 1);
|
||||
FALLBACK(scale, "SCALE", 1, 1); // No null/negative scale
|
||||
FALLBACK(bubblescale, "BUBBLESCALE", 0, 0); // No negative scale
|
||||
|
||||
// Special case for color I suppose
|
||||
if (followers[numfollowers].defaultcolor > MAXSKINCOLORS-1)
|
||||
{
|
||||
followers[numfollowers].defaultcolor = 1;
|
||||
deh_warning("Follower \'%s\': Value for 'color' should be between 1 and %d.\n", dname, MAXSKINCOLORS-1);
|
||||
}
|
||||
|
||||
#undef FALLBACK
|
||||
|
||||
// also check if we forgot states. If we did, we will set any missing state to the follower's idlestate.
|
||||
// Print a warning in case we don't have a fallback and set the state to S_INVISIBLE (rather than S_NULL) if unavailable.
|
||||
|
||||
#define NOSTATE(field, field2) \
|
||||
if (!followers[numfollowers].field) \
|
||||
{ \
|
||||
followers[numfollowers].field = fallbackstate ? fallbackstate : S_INVISIBLE; \
|
||||
if (!fallbackstate) \
|
||||
deh_warning("Follower '%s' is missing state definition for '%s', no idlestate fallback was found", dname, field2); \
|
||||
} \
|
||||
|
||||
NOSTATE(idlestate, "IDLESTATE");
|
||||
NOSTATE(followstate, "FOLLOWSTATE");
|
||||
NOSTATE(hurtstate, "HURTSTATE");
|
||||
NOSTATE(losestate, "LOSESTATE");
|
||||
NOSTATE(winstate, "WINSTATE");
|
||||
NOSTATE(hitconfirmstate, "HITCONFIRMSTATE");
|
||||
#undef NOSTATE
|
||||
|
||||
CONS_Printf("Added follower '%s'\n", dname);
|
||||
numfollowers++; // add 1 follower
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
static void readthing(MYFILE *f, INT32 num)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
|
@ -1875,6 +2141,113 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
|||
|
||||
#undef MAXFLICKIES
|
||||
|
||||
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);
|
||||
|
|
@ -4484,6 +4857,13 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
readwipes(f);
|
||||
continue;
|
||||
}
|
||||
else if (fastcmp(word, "FOLLOWER"))
|
||||
{
|
||||
readfollower(f); // at the same time this will be our only way to ADD followers for now. Yikes.
|
||||
DEH_WriteUndoline(word, "", UNDO_HEADER);
|
||||
// This is not a major mod either.
|
||||
continue; // continue so that we don't error.
|
||||
}
|
||||
word2 = strtok(NULL, " ");
|
||||
if (word2) {
|
||||
strupr(word2);
|
||||
|
|
@ -4682,6 +5062,42 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
|
@ -8143,6 +8559,39 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_DRIFTEXPLODE2",
|
||||
"S_DRIFTEXPLODE3",
|
||||
"S_DRIFTEXPLODE4",
|
||||
"S_DRIFTEXPLODE5",
|
||||
"S_DRIFTEXPLODE6",
|
||||
"S_DRIFTEXPLODE7",
|
||||
"S_DRIFTEXPLODE8",
|
||||
|
||||
// Drift boost clip
|
||||
"S_DRIFTCLIPA1",
|
||||
"S_DRIFTCLIPA2",
|
||||
"S_DRIFTCLIPA3",
|
||||
"S_DRIFTCLIPA4",
|
||||
"S_DRIFTCLIPA5",
|
||||
"S_DRIFTCLIPA6",
|
||||
"S_DRIFTCLIPA7",
|
||||
"S_DRIFTCLIPA8",
|
||||
"S_DRIFTCLIPA9",
|
||||
"S_DRIFTCLIPA10",
|
||||
"S_DRIFTCLIPA11",
|
||||
"S_DRIFTCLIPA12",
|
||||
"S_DRIFTCLIPA13",
|
||||
"S_DRIFTCLIPA14",
|
||||
"S_DRIFTCLIPA15",
|
||||
"S_DRIFTCLIPA16",
|
||||
"S_DRIFTCLIPB1",
|
||||
"S_DRIFTCLIPB2",
|
||||
"S_DRIFTCLIPB3",
|
||||
"S_DRIFTCLIPB4",
|
||||
"S_DRIFTCLIPB5",
|
||||
"S_DRIFTCLIPB6",
|
||||
"S_DRIFTCLIPB7",
|
||||
"S_DRIFTCLIPB8",
|
||||
|
||||
// Drift boost clip spark
|
||||
"S_DRIFTCLIPSPARK",
|
||||
|
||||
// Sneaker boost effect
|
||||
"S_BOOSTFLAME",
|
||||
|
|
@ -9038,6 +9487,31 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_OPAQUESMOKE4",
|
||||
"S_OPAQUESMOKE5",
|
||||
|
||||
"S_FOLLOWERBUBBLE_FRONT",
|
||||
"S_FOLLOWERBUBBLE_BACK",
|
||||
|
||||
"S_GCHAOIDLE",
|
||||
"S_GCHAOFLY",
|
||||
"S_GCHAOSAD1",
|
||||
"S_GCHAOSAD2",
|
||||
"S_GCHAOSAD3",
|
||||
"S_GCHAOSAD4",
|
||||
"S_GCHAOHAPPY1",
|
||||
"S_GCHAOHAPPY2",
|
||||
"S_GCHAOHAPPY3",
|
||||
"S_GCHAOHAPPY4",
|
||||
|
||||
"S_CHEESEIDLE",
|
||||
"S_CHEESEFLY",
|
||||
"S_CHEESESAD1",
|
||||
"S_CHEESESAD2",
|
||||
"S_CHEESESAD3",
|
||||
"S_CHEESESAD4",
|
||||
"S_CHEESEHAPPY1",
|
||||
"S_CHEESEHAPPY2",
|
||||
"S_CHEESEHAPPY3",
|
||||
"S_CHEESEHAPPY4",
|
||||
|
||||
"S_RINGDEBT",
|
||||
"S_RINGSPARKS1",
|
||||
"S_RINGSPARKS2",
|
||||
|
|
@ -9074,6 +9548,25 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_BATTLECAPSULE_SUPPORT",
|
||||
"S_BATTLECAPSULE_SUPPORTFLY",
|
||||
|
||||
"S_EGOORB",
|
||||
|
||||
"S_WATERTRAIL1",
|
||||
"S_WATERTRAIL2",
|
||||
"S_WATERTRAIL3",
|
||||
"S_WATERTRAIL4",
|
||||
"S_WATERTRAIL5",
|
||||
"S_WATERTRAIL6",
|
||||
"S_WATERTRAIL7",
|
||||
"S_WATERTRAIL8",
|
||||
"S_WATERTRAILUNDERLAY1",
|
||||
"S_WATERTRAILUNDERLAY2",
|
||||
"S_WATERTRAILUNDERLAY3",
|
||||
"S_WATERTRAILUNDERLAY4",
|
||||
"S_WATERTRAILUNDERLAY5",
|
||||
"S_WATERTRAILUNDERLAY6",
|
||||
"S_WATERTRAILUNDERLAY7",
|
||||
"S_WATERTRAILUNDERLAY8",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"S_NAMECHECK",
|
||||
#endif
|
||||
|
|
@ -9888,6 +10381,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_FASTLINE",
|
||||
"MT_FASTDUST",
|
||||
"MT_DRIFTEXPLODE",
|
||||
"MT_DRIFTCLIP",
|
||||
"MT_DRIFTCLIPSPARK",
|
||||
"MT_BOOSTFLAME",
|
||||
"MT_BOOSTSMOKE",
|
||||
"MT_SNEAKERTRAIL",
|
||||
|
|
@ -10167,6 +10662,13 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_BATTLECAPSULE",
|
||||
"MT_BATTLECAPSULE_PIECE",
|
||||
|
||||
"MT_FOLLOWER",
|
||||
"MT_FOLLOWERBUBBLE_FRONT",
|
||||
"MT_FOLLOWERBUBBLE_BACK",
|
||||
|
||||
"MT_WATERTRAIL",
|
||||
"MT_WATERTRAILUNDERLAY",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"MT_NAMECHECK",
|
||||
#endif
|
||||
|
|
@ -10212,7 +10714,7 @@ static const char *const MOBJFLAG2_LIST[] = {
|
|||
"AXIS", // It's a NiGHTS axis! (For faster checking)
|
||||
"TWOD", // Moves like it's in a 2D level
|
||||
"DONTRESPAWN", // Don't respawn this object!
|
||||
"DONTDRAW", // Don't generate a vissprite
|
||||
"\x01", // free: 1<<3 (name un-matchable)
|
||||
"AUTOMATIC", // Thrown ring has automatic properties
|
||||
"RAILRING", // Thrown ring has rail properties
|
||||
"BOUNCERING", // Thrown ring has bounce properties
|
||||
|
|
@ -10228,7 +10730,7 @@ static const char *const MOBJFLAG2_LIST[] = {
|
|||
"JUSTATTACKED", // can be pushed by other moving mobjs
|
||||
"FIRING", // turret fire
|
||||
"SUPERFIRE", // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it.
|
||||
"SHADOW", // Fuzzy draw, makes targeting harder.
|
||||
"\x01", // free: 1<<20 (name un-matchable)
|
||||
"STRONGBOX", // Flag used for "strong" random monitors.
|
||||
"OBJECTFLIP", // Flag for objects that always have flipped gravity.
|
||||
"SKULLFLY", // Special handling: skull in flight.
|
||||
|
|
@ -10256,10 +10758,6 @@ static const char *const MOBJEFLAG_LIST[] = {
|
|||
"APPLYPMOMZ", // Platform movement
|
||||
"TRACERANGLE", // Compute and trigger on mobj angle relative to tracer
|
||||
"JUSTBOUNCEDWALL",
|
||||
"DRAWONLYFORP1", // SRB2Kart: Splitscreen sprite draw flags
|
||||
"DRAWONLYFORP2",
|
||||
"DRAWONLYFORP3",
|
||||
"DRAWONLYFORP4",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -10607,9 +11105,6 @@ static const char *const KARTSTUFF_LIST[] = {
|
|||
"POSITION",
|
||||
"OLDPOSITION",
|
||||
"POSITIONDELAY",
|
||||
"STARPOSTFLIP",
|
||||
"RESPAWN",
|
||||
"DROPDASH",
|
||||
|
||||
"THROWDIR",
|
||||
"INSTASHIELD",
|
||||
|
|
@ -10633,13 +11128,16 @@ static const char *const KARTSTUFF_LIST[] = {
|
|||
"JMP",
|
||||
"OFFROAD",
|
||||
"POGOSPRING",
|
||||
"BRAKESTOP",
|
||||
"SPINDASH",
|
||||
"SPINDASHSPEED",
|
||||
"SPINDASHBOOST",
|
||||
"WATERSKIP",
|
||||
"DASHPADCOOLDOWN",
|
||||
"NUMBOOSTS",
|
||||
"BOOSTPOWER",
|
||||
"SPEEDBOOST",
|
||||
"ACCELBOOST",
|
||||
"HANDLEBOOST",
|
||||
"DRAFTPOWER",
|
||||
"DRAFTLEEWAY",
|
||||
"LASTDRAFT",
|
||||
|
|
@ -10661,7 +11159,7 @@ static const char *const KARTSTUFF_LIST[] = {
|
|||
"STOLENTIMER",
|
||||
"SUPERRING",
|
||||
"SNEAKERTIMER",
|
||||
"LEVELBOOSTER",
|
||||
"NUMSNEAKERS",
|
||||
"GROWSHRINKTIMER",
|
||||
"SQUISHEDTIMER",
|
||||
"ROCKETSNEAKERTIMER",
|
||||
|
|
@ -11248,7 +11746,6 @@ struct {
|
|||
{"DI_SOUTHEAST",DI_SOUTHEAST},
|
||||
{"NUMDIRS",NUMDIRS},
|
||||
|
||||
|
||||
// Sprite rotation axis (rotaxis_t)
|
||||
{"ROTAXIS_X",ROTAXIS_X},
|
||||
{"ROTAXIS_Y",ROTAXIS_Y},
|
||||
|
|
@ -11340,7 +11837,7 @@ struct {
|
|||
{"V_WRAPY",V_WRAPY},
|
||||
{"V_NOSCALESTART",V_NOSCALESTART},
|
||||
{"V_SPLITSCREEN",V_SPLITSCREEN},
|
||||
{"V_HORZSCREEN",V_HORZSCREEN},
|
||||
{"V_SLIDEIN",V_SLIDEIN},
|
||||
|
||||
{"V_PARAMMASK",V_PARAMMASK},
|
||||
{"V_SCALEPATCHMASK",V_SCALEPATCHMASK},
|
||||
|
|
@ -11380,7 +11877,8 @@ struct {
|
|||
KART_ITEM_ITERATOR, // Actual items (can be set for k_itemtype)
|
||||
#undef FOREACH
|
||||
{"NUMKARTITEMS",NUMKARTITEMS},
|
||||
{"KRITEM_TRIPLESNEAKER",KRITEM_TRIPLESNEAKER}, // Additional roulette IDs (not usable for much in Lua besides K_GetItemPatch)
|
||||
{"KRITEM_DUALSNEAKER",KRITEM_DUALSNEAKER}, // Additional roulette IDs (not usable for much in Lua besides K_GetItemPatch)
|
||||
{"KRITEM_TRIPLESNEAKER",KRITEM_TRIPLESNEAKER},
|
||||
{"KRITEM_TRIPLEBANANA",KRITEM_TRIPLEBANANA},
|
||||
{"KRITEM_TENFOLDBANANA",KRITEM_TENFOLDBANANA},
|
||||
{"KRITEM_TRIPLEORBINAUT",KRITEM_TRIPLEORBINAUT},
|
||||
|
|
@ -11395,6 +11893,37 @@ struct {
|
|||
{"KSHIELD_FLAME",KSHIELD_FLAME},
|
||||
{"NUMKARTSHIELDS",NUMKARTSHIELDS},
|
||||
|
||||
// translation colormaps
|
||||
{"TC_DEFAULT",TC_DEFAULT},
|
||||
{"TC_BOSS",TC_BOSS},
|
||||
{"TC_METALSONIC",TC_METALSONIC},
|
||||
{"TC_ALLWHITE",TC_ALLWHITE},
|
||||
{"TC_RAINBOW",TC_RAINBOW},
|
||||
{"TC_BLINK",TC_BLINK},
|
||||
|
||||
// MFD_ draw flag enum
|
||||
{"MFD_DONTDRAWP1",MFD_DONTDRAWP1},
|
||||
{"MFD_DONTDRAWP2",MFD_DONTDRAWP2},
|
||||
{"MFD_DONTDRAWP3",MFD_DONTDRAWP3},
|
||||
{"MFD_DONTDRAWP4",MFD_DONTDRAWP4},
|
||||
{"MFD_TRANS10",MFD_TRANS10},
|
||||
{"MFD_TRANS20",MFD_TRANS20},
|
||||
{"MFD_TRANS30",MFD_TRANS30},
|
||||
{"MFD_TRANS40",MFD_TRANS40},
|
||||
{"MFD_TRANS50",MFD_TRANS50},
|
||||
{"MFD_TRANS60",MFD_TRANS60},
|
||||
{"MFD_TRANS70",MFD_TRANS70},
|
||||
{"MFD_TRANS80",MFD_TRANS80},
|
||||
{"MFD_TRANS90",MFD_TRANS90},
|
||||
{"MFD_TRANSMASK",MFD_TRANSMASK},
|
||||
{"MFD_FULLBRIGHT",MFD_FULLBRIGHT},
|
||||
{"MFD_SEMIBRIGHT",MFD_SEMIBRIGHT},
|
||||
{"MFD_NOBRIGHT",MFD_NOBRIGHT},
|
||||
{"MFD_BRIGHTMASK",MFD_BRIGHTMASK},
|
||||
{"MFD_DONTDRAW",MFD_DONTDRAW},
|
||||
{"MFD_SHADOW",MFD_SHADOW},
|
||||
{"MFD_TRANSSHIFT",MFD_TRANSSHIFT},
|
||||
|
||||
{NULL,0}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -425,8 +425,30 @@ 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;
|
||||
|
||||
// Gametypes
|
||||
#define NUMGAMETYPEFREESLOTS 128
|
||||
|
||||
enum GameType
|
||||
{
|
||||
GT_RACE = 0,
|
||||
|
|
@ -590,8 +612,13 @@ extern UINT16 nightslinktics;
|
|||
// SRB2kart
|
||||
extern tic_t introtime;
|
||||
extern tic_t starttime;
|
||||
|
||||
extern const tic_t bulbtime;
|
||||
extern UINT8 numbulbs;
|
||||
|
||||
extern tic_t raceexittime;
|
||||
extern tic_t battleexittime;
|
||||
|
||||
extern INT32 hyudorotime;
|
||||
extern INT32 stealtime;
|
||||
extern INT32 sneakertime;
|
||||
|
|
@ -645,6 +672,7 @@ extern tic_t hyubgone;
|
|||
extern tic_t mapreset;
|
||||
extern boolean thwompsactive;
|
||||
extern SINT8 spbplace;
|
||||
extern boolean rainbowstartavailable;
|
||||
|
||||
extern tic_t bombflashtimer; // Used to avoid causing seizures if multiple mines explode close to you :)
|
||||
extern boolean legitimateexit;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "z_zone.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "i_threads.h"
|
||||
#include "m_menu.h"
|
||||
#include "console.h"
|
||||
#include "d_main.h"
|
||||
|
|
@ -477,7 +478,15 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu, const char *colormap, boolean r
|
|||
I_UpdateNoBlit();
|
||||
|
||||
if (drawMenu)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&m_menu_mutex);
|
||||
#endif
|
||||
M_Drawer(); // menu is drawn even on top of wipes
|
||||
#ifdef HAVE_THREADS
|
||||
I_unlock_mutex(m_menu_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
|
||||
|
|
|
|||
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
|
||||
414
src/g_game.c
414
src/g_game.c
|
|
@ -55,6 +55,8 @@
|
|||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
|
||||
gameaction_t gameaction;
|
||||
|
|
@ -185,6 +187,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;
|
||||
static boolean retryingmodeattack = false;
|
||||
|
|
@ -241,10 +247,15 @@ INT32 gameovertics = 15*TICRATE;
|
|||
UINT8 ammoremovaltics = 2*TICRATE;
|
||||
|
||||
// SRB2kart
|
||||
tic_t introtime = 108+5; // plus 5 for white fade
|
||||
tic_t starttime = 6*TICRATE + (3*TICRATE/4);
|
||||
tic_t introtime = 0;
|
||||
tic_t starttime = 0;
|
||||
|
||||
const tic_t bulbtime = TICRATE/2;
|
||||
UINT8 numbulbs = 0;
|
||||
|
||||
tic_t raceexittime = 5*TICRATE + (2*TICRATE/3);
|
||||
tic_t battleexittime = 8*TICRATE;
|
||||
|
||||
INT32 hyudorotime = 7*TICRATE;
|
||||
INT32 stealtime = TICRATE/2;
|
||||
INT32 sneakertime = TICRATE + (TICRATE/3);
|
||||
|
|
@ -306,6 +317,7 @@ tic_t hyubgone; // Cooldown before hyudoro is allowed to be rerolled
|
|||
tic_t mapreset; // Map reset delay when enough players have joined an empty game
|
||||
boolean thwompsactive; // Thwomps activate on lap 2
|
||||
SINT8 spbplace; // SPB exists, give the person behind better items
|
||||
boolean rainbowstartavailable; // Boolean, keeps track of if the rainbow start was gotten
|
||||
|
||||
// Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players)
|
||||
tic_t bombflashtimer = 0; // Cooldown before another FlashPal can be intialized by a bomb exploding near a displayplayer. Avoids seizures.
|
||||
|
|
@ -984,24 +996,24 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
cmd->buttons |= BT_BRAKE;
|
||||
axis = PlayerJoyAxis(ssplayer, AXISAIM);
|
||||
if (PlayerInputDown(ssplayer, gc_aimforward) || (usejoystick && axis < 0))
|
||||
forward += forwardmove[1];
|
||||
forward += forwardmove;
|
||||
if (PlayerInputDown(ssplayer, gc_aimbackward) || (usejoystick && axis > 0))
|
||||
forward -= forwardmove[1];
|
||||
forward -= forwardmove;
|
||||
}
|
||||
else
|
||||
{
|
||||
// forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward.
|
||||
axis = PlayerJoyAxis(ssplayer, AXISMOVE);
|
||||
if (PlayerInputDown(ssplayer, gc_accelerate) || (gamepadjoystickmove && axis > 0) || EITHERSNEAKER(player))
|
||||
if (PlayerInputDown(ssplayer, gc_accelerate) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer])
|
||||
{
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
forward = forwardmove[1]; // 50
|
||||
forward = forwardmove; // 50
|
||||
}
|
||||
else if (analogjoystickmove && axis > 0)
|
||||
{
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
// JOYAXISRANGE is supposed to be 1023 (divide by 1024)
|
||||
forward += ((axis * forwardmove[1]) >> 10)*2;
|
||||
forward += ((axis * forwardmove) >> 10);
|
||||
}
|
||||
|
||||
axis = PlayerJoyAxis(ssplayer, AXISBRAKE);
|
||||
|
|
@ -1009,14 +1021,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
{
|
||||
cmd->buttons |= BT_BRAKE;
|
||||
if (cmd->buttons & BT_ACCELERATE || cmd->forwardmove <= 0)
|
||||
forward -= forwardmove[0]; // 25 - Halved value so clutching is possible
|
||||
forward -= forwardmove;
|
||||
}
|
||||
else if (analogjoystickmove && axis > 0)
|
||||
{
|
||||
cmd->buttons |= BT_BRAKE;
|
||||
// JOYAXISRANGE is supposed to be 1023 (divide by 1024)
|
||||
if (cmd->buttons & BT_ACCELERATE || cmd->forwardmove <= 0)
|
||||
forward -= ((axis * forwardmove[0]) >> 10);
|
||||
forward -= ((axis * forwardmove) >> 10);
|
||||
}
|
||||
|
||||
// But forward/backward IS used for aiming.
|
||||
|
|
@ -1064,7 +1076,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
INT32 player_invert = invertmouse ? -1 : 1;
|
||||
INT32 screen_invert =
|
||||
(player->mo && (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
&& (!thiscam->chase || player->pflags & PF_FLIPCAM)) //because chasecam's not inverted
|
||||
&& (!thiscam->chase)) //because chasecam's not inverted
|
||||
? -1 : 1; // set to -1 or 1 to multiply
|
||||
INT32 configlookaxis = ssplayer == 1 ? cv_lookaxis.value : cv_lookaxis2.value;
|
||||
|
||||
|
|
@ -1111,15 +1123,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
|
||||
mousex = mousey = mlooky = 0;
|
||||
|
||||
if (forward > MAXPLMOVE)
|
||||
forward = MAXPLMOVE;
|
||||
else if (forward < -MAXPLMOVE)
|
||||
forward = -MAXPLMOVE;
|
||||
cmd->forwardmove += (SINT8)forward;
|
||||
|
||||
if (forward != 0)
|
||||
{
|
||||
cmd->forwardmove = (SINT8)(cmd->forwardmove + forward);
|
||||
}
|
||||
if (cmd->forwardmove > MAXPLMOVE)
|
||||
cmd->forwardmove = MAXPLMOVE;
|
||||
else if (cmd->forwardmove < -MAXPLMOVE)
|
||||
cmd->forwardmove = -MAXPLMOVE;
|
||||
|
||||
//{ SRB2kart - Drift support
|
||||
// Not grouped with the rest of turn stuff because it needs to know what buttons you're pressing for rubber-burn turn
|
||||
|
|
@ -1139,11 +1148,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
|
||||
cmd->angleturn *= realtics;
|
||||
|
||||
// SRB2kart - no additional angle if not moving
|
||||
if ((player->mo && player->speed > 0) // Moving
|
||||
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|
||||
|| (player->kartstuff[k_respawn]) // Respawning
|
||||
|| (player->spectator || objectplacing)) // Not a physical player
|
||||
*lang += (cmd->angleturn<<16);
|
||||
|
||||
cmd->angleturn = (INT16)(*lang >> 16);
|
||||
cmd->latency = modeattacking ? 0 : (leveltime & 0xFF); // Send leveltime when this tic was generated to the server for control lag calculations
|
||||
|
||||
if (!hu_stopped)
|
||||
{
|
||||
*lang += (cmd->angleturn<<16);
|
||||
}
|
||||
|
|
@ -1165,7 +1175,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
LUAh_PlayerCmd(player, cmd);
|
||||
|
||||
//Reset away view if a command is given.
|
||||
if ((cmd->forwardmove || cmd->sidemove || cmd->buttons)
|
||||
if ((cmd->forwardmove || cmd->buttons)
|
||||
&& !r_splitscreen && displayplayers[0] != consoleplayer && ssplayer == 1)
|
||||
{
|
||||
// Call ViewpointSwitch hooks here.
|
||||
|
|
@ -1252,14 +1262,6 @@ void G_DoLoadLevel(boolean resetplayer)
|
|||
|
||||
P_FindEmerald();
|
||||
|
||||
g_localplayers[0] = consoleplayer; // view the guy you are playing
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (i > 0 && r_splitscreen < i)
|
||||
g_localplayers[i] = consoleplayer;
|
||||
}
|
||||
|
||||
gameaction = ga_nothing;
|
||||
#ifdef PARANOIA
|
||||
Z_CheckHeap(-2);
|
||||
|
|
@ -1856,30 +1858,19 @@ void G_Ticker(boolean run)
|
|||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
// Or, alternatively, retry.
|
||||
if (!(netgame || multiplayer) && G_GetRetryFlag())
|
||||
if (G_GetRetryFlag())
|
||||
{
|
||||
G_ClearRetryFlag();
|
||||
|
||||
if (modeattacking)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
pausedelay = INT32_MIN;
|
||||
M_ModeAttackRetry(0);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
// Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
|
||||
if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
|
||||
if (playeringame[i])
|
||||
{
|
||||
marathonmode |= MA_INIT;
|
||||
marathontime = 0;
|
||||
K_PlayerLoseLife(&players[i]);
|
||||
}
|
||||
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
|
||||
players[consoleplayer].lives -= 1;
|
||||
|
||||
G_DoReborn(consoleplayer);
|
||||
}
|
||||
*/
|
||||
|
||||
D_MapChange(gamemap, gametype, (cv_kartencore.value == 1), false, 1, false, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -1911,16 +1902,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);
|
||||
}
|
||||
|
||||
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||
|
|
@ -1934,7 +1927,7 @@ void G_Ticker(boolean run)
|
|||
switch (gamestate)
|
||||
{
|
||||
case GS_LEVEL:
|
||||
if (titledemo)
|
||||
if (demo.title)
|
||||
F_TitleDemoTicker();
|
||||
P_Ticker(run); // tic the game
|
||||
ST_Ticker(run);
|
||||
|
|
@ -2058,15 +2051,11 @@ static inline void G_PlayerFinishLevel(INT32 player)
|
|||
memset(p->kartstuff, 0, sizeof (p->kartstuff)); // SRB2kart
|
||||
p->ringweapons = 0;
|
||||
|
||||
p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility
|
||||
p->mo->drawflags &= ~(MFD_TRANSMASK|MFD_BRIGHTMASK); // cancel invisibility
|
||||
P_FlashPal(p, 0, 0); // Resets
|
||||
p->starpostscale = 0;
|
||||
p->starpostangle = 0;
|
||||
p->starposttime = 0;
|
||||
p->starpostx = 0;
|
||||
p->starposty = 0;
|
||||
p->starpostz = 0;
|
||||
|
||||
p->starpostnum = 0;
|
||||
memset(&p->respawn, 0, sizeof (p->respawn));
|
||||
|
||||
// SRB2kart: Increment the "matches played" counter.
|
||||
if (player == consoleplayer)
|
||||
|
|
@ -2092,10 +2081,17 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
player_t *p;
|
||||
INT32 score, marescore;
|
||||
INT32 lives;
|
||||
boolean lostlife;
|
||||
INT32 continues;
|
||||
|
||||
UINT8 kartspeed;
|
||||
UINT8 kartweight;
|
||||
|
||||
boolean followerready;
|
||||
INT32 followerskin;
|
||||
UINT8 followercolor;
|
||||
mobj_t *follower; // old follower, will probably be removed by the time we're dead but you never know.
|
||||
|
||||
INT32 charflags;
|
||||
UINT32 followitem;
|
||||
|
||||
|
|
@ -2103,14 +2099,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
|
||||
INT32 ctfteam;
|
||||
|
||||
INT32 starposttime;
|
||||
INT16 starpostx;
|
||||
INT16 starposty;
|
||||
INT16 starpostz;
|
||||
INT32 starpostnum;
|
||||
INT32 starpostangle;
|
||||
fixed_t starpostscale;
|
||||
|
||||
INT32 exiting;
|
||||
tic_t dashmode;
|
||||
INT16 numboxes;
|
||||
|
|
@ -2133,7 +2122,13 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
INT16 playerangleturn;
|
||||
INT16 oldrelangleturn;
|
||||
|
||||
UINT8 botdiffincrease;
|
||||
boolean botrival;
|
||||
|
||||
SINT8 xtralife;
|
||||
|
||||
// SRB2kart
|
||||
respawnvars_t respawn;
|
||||
INT32 itemtype;
|
||||
INT32 itemamount;
|
||||
INT32 itemroulette;
|
||||
|
|
@ -2143,12 +2138,12 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
INT32 comebackpoints;
|
||||
INT32 wanted;
|
||||
INT32 rings;
|
||||
INT32 respawnflip;
|
||||
boolean songcredit = false;
|
||||
|
||||
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;
|
||||
|
|
@ -2184,25 +2179,27 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
kartspeed = players[player].kartspeed;
|
||||
kartweight = players[player].kartweight;
|
||||
|
||||
follower = players[player].follower;
|
||||
followerready = players[player].followerready;
|
||||
followercolor = players[player].followercolor;
|
||||
followerskin = players[player].followerskin;
|
||||
|
||||
availabilities = players[player].availabilities;
|
||||
|
||||
charflags = players[player].charflags;
|
||||
|
||||
starposttime = players[player].starposttime;
|
||||
starpostx = players[player].starpostx;
|
||||
starposty = players[player].starposty;
|
||||
starpostz = players[player].starpostz;
|
||||
starpostnum = players[player].starpostnum;
|
||||
respawnflip = players[player].kartstuff[k_starpostflip]; //SRB2KART
|
||||
starpostangle = players[player].starpostangle;
|
||||
starpostscale = players[player].starpostscale;
|
||||
|
||||
followitem = players[player].followitem;
|
||||
|
||||
mare = players[player].mare;
|
||||
bot = players[player].bot;
|
||||
botdifficulty = players[player].botvars.difficulty;
|
||||
|
||||
botdiffincrease = players[player].botvars.diffincrease;
|
||||
botrival = players[player].botvars.rival;
|
||||
|
||||
xtralife = players[player].xtralife;
|
||||
|
||||
// SRB2kart
|
||||
if (betweenmaps || leveltime < starttime)
|
||||
{
|
||||
|
|
@ -2244,12 +2241,18 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
wanted = players[player].kartstuff[k_wanted];
|
||||
}
|
||||
|
||||
// Obliterate follower from existence
|
||||
P_SetTarget(&players[player].follower, NULL);
|
||||
|
||||
memcpy(&respawn, &players[player].respawn, sizeof (respawn));
|
||||
|
||||
p = &players[player];
|
||||
memset(p, 0, sizeof (*p));
|
||||
|
||||
p->score = score;
|
||||
p->marescore = marescore;
|
||||
p->lives = lives;
|
||||
p->lostlife = lostlife;
|
||||
p->continues = continues;
|
||||
p->pflags = pflags;
|
||||
p->ctfteam = ctfteam;
|
||||
|
|
@ -2270,14 +2273,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->availabilities = availabilities;
|
||||
p->followitem = followitem;
|
||||
|
||||
p->starposttime = starposttime;
|
||||
p->starpostx = starpostx;
|
||||
p->starposty = starposty;
|
||||
p->starpostz = starpostz;
|
||||
p->starpostnum = starpostnum;
|
||||
p->starpostangle = starpostangle;
|
||||
p->starpostscale = starpostscale;
|
||||
|
||||
p->exiting = exiting;
|
||||
|
||||
p->dashmode = dashmode;
|
||||
|
|
@ -2290,6 +2286,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->bot = bot;
|
||||
p->botvars.difficulty = botdifficulty;
|
||||
p->rings = rings;
|
||||
p->botvars.diffincrease = botdiffincrease;
|
||||
p->botvars.rival = botrival;
|
||||
p->xtralife = xtralife;
|
||||
|
||||
// SRB2kart
|
||||
p->kartstuff[k_itemroulette] = itemroulette;
|
||||
|
|
@ -2304,7 +2303,18 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->kartstuff[k_wanted] = wanted;
|
||||
p->kartstuff[k_eggmanblame] = -1;
|
||||
p->kartstuff[k_lastdraft] = -1;
|
||||
p->kartstuff[k_starpostflip] = respawnflip;
|
||||
|
||||
memcpy(&p->respawn, &respawn, sizeof (p->respawn));
|
||||
|
||||
if (follower)
|
||||
P_RemoveMobj(follower);
|
||||
|
||||
p->followerready = followerready;
|
||||
p->followerskin = followerskin;
|
||||
p->followercolor = followercolor;
|
||||
//p->follower = NULL; // respawn a new one with you, it looks better.
|
||||
// ^ Not necessary anyway since it will be respawned regardless considering it doesn't exist anymore.
|
||||
|
||||
|
||||
// Don't do anything immediately
|
||||
p->pflags |= PF_USEDOWN;
|
||||
|
|
@ -2362,7 +2372,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
S_ShowMusicCredit();
|
||||
|
||||
if (leveltime > (starttime + (TICRATE/2)) && !p->spectator)
|
||||
p->kartstuff[k_respawn] = 48; // Respawn effect
|
||||
{
|
||||
K_DoIngameRespawn(p);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -2778,10 +2790,7 @@ void G_AddPlayer(INT32 playernum)
|
|||
|
||||
p->playerstate = PST_REBORN;
|
||||
|
||||
demo_extradata[playernum] |= DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN; // Set everything
|
||||
|
||||
if (G_GametypeUsesLives())
|
||||
p->lives = 3;
|
||||
demo_extradata[playernum] |= DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER; // Set everything
|
||||
|
||||
if ((countplayers && !notexiting) || G_IsSpecialStage(gamemap))
|
||||
P_DoPlayerExit(p);
|
||||
|
|
@ -2791,6 +2800,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;
|
||||
|
||||
|
|
@ -3073,11 +3123,13 @@ boolean G_IsSpecialStage(INT32 mapnum)
|
|||
//
|
||||
boolean G_GametypeUsesLives(void)
|
||||
{
|
||||
if ((gametyperules & GTR_LIVES)
|
||||
&& !(modeattacking || metalrecording) // No lives in Time Attack
|
||||
&& !battlecapsules // No lives in bonus game
|
||||
&& !G_IsSpecialStage(gamemap)) // No lives in special stage
|
||||
if ((grandprixinfo.gp == true) // In Grand Prix
|
||||
&& (gametype == GT_RACE) // NOT in bonus round
|
||||
&& !G_IsSpecialStage(gamemap) // NOT in special stage
|
||||
&& !(modeattacking || metalrecording)) // NOT in Record Attack
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -3460,11 +3512,7 @@ static void G_HandleSaveLevel(void)
|
|||
static void G_DoCompleted(void)
|
||||
{
|
||||
INT32 i, j = 0;
|
||||
boolean gottoken = false;
|
||||
SINT8 powertype = PWRLV_DISABLED;
|
||||
boolean spec = G_IsSpecialStage(gamemap);
|
||||
|
||||
tokenlist = 0; // Reset the list
|
||||
SINT8 powertype = K_UsingPowerLevels();
|
||||
|
||||
if (modeattacking && pausedelay)
|
||||
pausedelay = 0;
|
||||
|
|
@ -3482,10 +3530,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
|
||||
}
|
||||
|
||||
|
|
@ -3505,11 +3564,30 @@ static void G_DoCompleted(void)
|
|||
// go to next level
|
||||
// nextmap is 0-based, unlike gamemap
|
||||
if (nextmapoverride != 0)
|
||||
{
|
||||
nextmap = (INT16)(nextmapoverride-1);
|
||||
else if (marathonmode && mapheaderinfo[gamemap-1]->marathonnext)
|
||||
nextmap = (INT16)(mapheaderinfo[gamemap-1]->marathonnext-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);
|
||||
|
|
@ -3517,11 +3595,15 @@ static void G_DoCompleted(void)
|
|||
nextmap = 1100-1; // No infinite loop for you
|
||||
}
|
||||
|
||||
// Remember last map for when you come out of the special stage.
|
||||
if (!G_IsSpecialStage(gamemap))
|
||||
lastmap = nextmap;
|
||||
|
||||
// If nextmap is actually going to get used, make sure it points to
|
||||
// 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 (!spec)
|
||||
if (!modeattacking && grandprixinfo.gp == false && (nextmap >= 0 && nextmap < NUMMAPS))
|
||||
{
|
||||
if (nextmap >= 0 && nextmap < NUMMAPS)
|
||||
{
|
||||
|
|
@ -3576,35 +3658,18 @@ static void G_DoCompleted(void)
|
|||
lastmap = nextmap; // Remember last map for when you come out of the special stage.
|
||||
}
|
||||
|
||||
if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token)))
|
||||
{
|
||||
token--;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
if (!(emeralds & (1<<i)))
|
||||
{
|
||||
nextmap = ((netgame || multiplayer) ? smpstage_start : sstage_start) + i - 1; // to special stage!
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 7)
|
||||
{
|
||||
gottoken = false;
|
||||
token = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (spec && !gottoken)
|
||||
nextmap = lastmap; // Exiting from a special stage? Go back to the game. Tails 08-11-2001
|
||||
|
||||
automapactive = false;
|
||||
|
||||
if (!(gametyperules & GTR_CAMPAIGN))
|
||||
{
|
||||
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.
|
||||
|
|
@ -3614,14 +3679,6 @@ static void G_DoCompleted(void)
|
|||
P_AllocMapHeader(nextmap);
|
||||
|
||||
// Set up power level gametype scrambles
|
||||
if (netgame && cv_kartusepwrlv.value)
|
||||
{
|
||||
if ((gametyperules & GTR_CIRCUIT))
|
||||
powertype = PWRLV_RACE;
|
||||
else if ((gametyperules & GTR_BUMPERS))
|
||||
powertype = PWRLV_BATTLE;
|
||||
}
|
||||
|
||||
K_SetPowerLevelScrambles(powertype);
|
||||
|
||||
demointermission:
|
||||
|
|
@ -3702,7 +3759,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++)
|
||||
|
|
@ -3803,7 +3860,7 @@ static void G_DoContinued(void)
|
|||
G_SaveGameOver((UINT32)cursaveslot, true);
|
||||
|
||||
// Reset # of lives
|
||||
pl->lives = (ultimatemode) ? 1 : startinglivesbalance[numgameovers];
|
||||
pl->lives = 3;
|
||||
|
||||
D_MapChange(gamemap, gametype, false, false, 0, false, false);
|
||||
|
||||
|
|
@ -4382,6 +4439,7 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar
|
|||
{
|
||||
INT32 i;
|
||||
UINT16 color = SKINCOLOR_NONE;
|
||||
|
||||
paused = false;
|
||||
|
||||
if (demo.playback)
|
||||
|
|
@ -4395,11 +4453,7 @@ 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();
|
||||
|
|
@ -4444,62 +4498,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
|
||||
redscore = bluescore = lastmap = 0;
|
||||
racecountdown = exitcountdown = mapreset = exitfadestarted = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
// Clear a bunch of variables
|
||||
numgameovers = tokenlist = token = sstimer = redscore = bluescore = lastmap = 0;
|
||||
racecountdown = exitcountdown = mapreset = exitfadestarted = 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_GAMETYPEOVER|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].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
|
||||
players[i].starpostx = players[i].starposty = players[i].starpostz = 0;
|
||||
|
||||
#if 0
|
||||
if (netgame || multiplayer)
|
||||
{
|
||||
if (!FLS || (players[i].lives < 1))
|
||||
players[i].lives = cv_startinglives.value;
|
||||
players[i].continues = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
players[i].lives = (pultmode) ? 1 : startinglivesbalance[0];
|
||||
players[i].continues = (pultmode) ? 0 : 1;
|
||||
}
|
||||
|
||||
players[i].lives = 3;
|
||||
players[i].xtralife = 0;
|
||||
#else
|
||||
players[i].lives = 1; // SRB2Kart
|
||||
#endif
|
||||
|
||||
if (!((netgame || multiplayer) && (FLS)))
|
||||
players[i].score = 0;
|
||||
|
||||
// The latter two should clear by themselves, but just in case
|
||||
players[i].pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|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....
|
||||
|
|
|
|||
|
|
@ -187,7 +187,6 @@ void G_UpdateGametypeSelections(void);
|
|||
void G_AddTOL(UINT32 newtol, const char *tolname);
|
||||
void G_AddGametypeTOL(INT16 gtype, UINT32 newtol);
|
||||
void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor);
|
||||
|
||||
INT32 G_GetGametypeByName(const char *gametypestr);
|
||||
boolean G_IsSpecialStage(INT32 mapnum);
|
||||
boolean G_GametypeUsesLives(void);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "../st_stuff.h"
|
||||
#include "../p_local.h" // stplyr
|
||||
#include "../g_game.h" // players
|
||||
#include "../k_hud.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "../i_video.h" // for rendermode != render_glide
|
||||
|
|
@ -199,80 +200,6 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
|
|||
cy -= offsety;
|
||||
}
|
||||
|
||||
if (option & V_SPLITSCREEN)
|
||||
cy += FIXED_TO_FLOAT((BASEVIDHEIGHT/2)<<FRACBITS);
|
||||
|
||||
if (option & V_HORZSCREEN)
|
||||
cx += FIXED_TO_FLOAT((BASEVIDWIDTH/2)<<FRACBITS);
|
||||
|
||||
if (splitscreen && (option & V_PERPLAYER))
|
||||
{
|
||||
float adjusty = ((option & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
|
||||
fscaleh /= 2;
|
||||
cy /= 2;
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
float adjustx = ((option & V_NOSCALESTART) ? vid.width : BASEVIDWIDTH)/2.0f;
|
||||
fscalew /= 2;
|
||||
cx /= 2;
|
||||
if (stplyr == &players[displayplayers[0]])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
option &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||
}
|
||||
else if (stplyr == &players[displayplayers[1]])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
cx += adjustx;
|
||||
option &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
||||
}
|
||||
else if (stplyr == &players[displayplayers[2]])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
cy += adjusty;
|
||||
option &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
}
|
||||
else //if (stplyr == &players[displayplayers[3]])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
cx += adjustx;
|
||||
cy += adjusty;
|
||||
option &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// 2 players
|
||||
{
|
||||
if (stplyr == &players[displayplayers[0]])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle = 1;
|
||||
option &= ~V_SNAPTOBOTTOM;
|
||||
}
|
||||
else //if (stplyr == &players[displayplayers[1]])
|
||||
{
|
||||
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle = 2;
|
||||
cy += adjusty;
|
||||
option &= ~V_SNAPTOTOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(option & V_NOSCALESTART))
|
||||
{
|
||||
cx = cx * dupx;
|
||||
|
|
@ -280,44 +207,12 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
|
|||
|
||||
if (!(option & V_SCALEPATCHMASK))
|
||||
{
|
||||
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
|
||||
// cx and cy are possibly *slightly* off from float maths
|
||||
// This is done before here compared to software because we directly alter cx and cy to centre
|
||||
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
|
||||
{
|
||||
// Need to temporarily cache the real patch to get the colour of the top left pixel
|
||||
patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
|
||||
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
|
||||
if (!column->topdelta)
|
||||
{
|
||||
const UINT8 *source = (const UINT8 *)(column) + 3;
|
||||
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
|
||||
}
|
||||
Z_Free(realpatch);
|
||||
}
|
||||
// centre screen
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
{
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
|
||||
if (perplayershuffle & 4)
|
||||
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
|
||||
else if (perplayershuffle & 8)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
if (option & V_SNAPTOBOTTOM)
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
else if (!(option & V_SNAPTOTOP))
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
|
||||
if (perplayershuffle & 1)
|
||||
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
|
||||
else if (perplayershuffle & 2)
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
|
||||
}
|
||||
INT32 intx, inty;
|
||||
intx = (INT32)cx;
|
||||
inty = (INT32)cy;
|
||||
K_AdjustXYWithSnap(&intx, &inty, option, dupx, dupy);
|
||||
cx = (float)intx;
|
||||
cy = (float)inty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1263,40 +1158,18 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32
|
|||
if (!(color & V_NOSCALESTART))
|
||||
{
|
||||
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
|
||||
INT32 intx, inty;
|
||||
|
||||
fx *= dupx;
|
||||
fy *= dupy;
|
||||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
{
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
}
|
||||
if (options & V_SPLITSCREEN)
|
||||
fy += ((float)BASEVIDHEIGHT * dupy)/2;
|
||||
if (options & V_HORZSCREEN)
|
||||
fx += ((float)BASEVIDWIDTH * dupx)/2;
|
||||
|
||||
intx = (INT32)fx;
|
||||
inty = (INT32)fy;
|
||||
K_AdjustXYWithSnap(&intx, &inty, options, dupx, dupy);
|
||||
fx = (float)intx;
|
||||
fy = (float)inty;
|
||||
}
|
||||
|
||||
if (fx >= vid.width || fy >= vid.height)
|
||||
|
|
@ -1434,6 +1307,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
if (!(color & V_NOSCALESTART))
|
||||
{
|
||||
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
|
||||
INT32 intx, inty;
|
||||
|
||||
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
||||
{
|
||||
|
|
@ -1452,34 +1326,11 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
{
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
}
|
||||
if (color & V_SPLITSCREEN)
|
||||
fy += ((float)BASEVIDHEIGHT * dupy)/2;
|
||||
if (color & V_HORZSCREEN)
|
||||
fx += ((float)BASEVIDWIDTH * dupx)/2;
|
||||
|
||||
intx = (INT32)fx;
|
||||
inty = (INT32)fy;
|
||||
K_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy);
|
||||
fx = (float)intx;
|
||||
fy = (float)inty;
|
||||
}
|
||||
|
||||
if (fx >= vid.width || fy >= vid.height)
|
||||
|
|
|
|||
|
|
@ -3571,8 +3571,6 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
|
||||
groundz = R_GetShadowZ(thing, &groundslope);
|
||||
|
||||
//if (abs(groundz - gl_viewz) / tz > 4) return; // Prevent stretchy shadows and possible crashes
|
||||
|
||||
floordiff = abs((flip < 0 ? thing->height : 0) + thingzpos - groundz);
|
||||
|
||||
alpha = floordiff / (4*FRACUNIT) + 75;
|
||||
|
|
@ -3700,6 +3698,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
FBITFIELD occlusion;
|
||||
boolean use_linkdraw_hack = false;
|
||||
UINT8 alpha;
|
||||
UINT8 brightmode = 0;
|
||||
|
||||
INT32 i;
|
||||
float realtop, realbot, top, bot;
|
||||
|
|
@ -3799,17 +3798,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
else
|
||||
occlusion = PF_Occlude;
|
||||
|
||||
if (!cv_translucency.value) // translucency disabled
|
||||
{
|
||||
Surf.PolyColor.s.alpha = 0xFF;
|
||||
blend = PF_Translucent|occlusion;
|
||||
if (!occlusion) use_linkdraw_hack = true;
|
||||
}
|
||||
else if (spr->mobj->flags2 & MF2_SHADOW)
|
||||
{
|
||||
Surf.PolyColor.s.alpha = 0x40;
|
||||
blend = PF_Translucent;
|
||||
}
|
||||
if (spr->mobj->drawflags & MFD_TRANSMASK)
|
||||
blend = HWR_TranstableToAlpha((spr->mobj->drawflags & MFD_TRANSMASK)>>MFD_TRANSSHIFT, &Surf);
|
||||
else if (spr->mobj->frame & FF_TRANSMASK)
|
||||
blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
|
||||
else
|
||||
|
|
@ -3825,31 +3815,44 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
|
||||
alpha = Surf.PolyColor.s.alpha;
|
||||
|
||||
if (spr->mobj->drawflags & MFD_BRIGHTMASK)
|
||||
{
|
||||
if (spr->mobj->drawflags & MFD_FULLBRIGHT)
|
||||
brightmode = 1;
|
||||
else if (spr->mobj->drawflags & MFD_SEMIBRIGHT)
|
||||
brightmode = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spr->mobj->frame & FF_FULLBRIGHT)
|
||||
brightmode = 1;
|
||||
else if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
brightmode = 2;
|
||||
}
|
||||
|
||||
// Start with the lightlevel and colormap from the top of the sprite
|
||||
lightlevel = *list[sector->numlights - 1].lightlevel;
|
||||
colormap = *list[sector->numlights - 1].extra_colormap;
|
||||
i = 0;
|
||||
temp = FLOAT_TO_FIXED(realtop);
|
||||
|
||||
if (spr->mobj->frame & FF_FULLBRIGHT)
|
||||
lightlevel = 255;
|
||||
if (brightmode != 1)
|
||||
lightlevel = *list[sector->numlights - 1].lightlevel;
|
||||
|
||||
for (i = 1; i < sector->numlights; i++)
|
||||
{
|
||||
fixed_t h = P_GetLightZAt(§or->lightlist[i], spr->mobj->x, spr->mobj->y);
|
||||
if (h <= temp)
|
||||
{
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel;
|
||||
|
||||
if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
|
||||
if (brightmode != 1)
|
||||
lightlevel = *list[i-1].lightlevel;
|
||||
colormap = *list[i-1].extra_colormap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (brightmode == 2)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
|
||||
for (i = 0; i < sector->numlights; i++)
|
||||
{
|
||||
if (endtop < endrealbot && top < realbot)
|
||||
|
|
@ -3858,13 +3861,13 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
// even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite
|
||||
if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES))
|
||||
{
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel;
|
||||
|
||||
if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
|
||||
colormap = *list[i].extra_colormap;
|
||||
if (brightmode != 1)
|
||||
{
|
||||
lightlevel = *list[i].lightlevel;
|
||||
if (brightmode == 2)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
}
|
||||
colormap = list[i].extra_colormap;
|
||||
}
|
||||
|
||||
if (i + 1 < sector->numlights)
|
||||
|
|
@ -4076,12 +4079,28 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
{
|
||||
sector_t *sector = spr->mobj->subsector->sector;
|
||||
UINT8 lightlevel = 255;
|
||||
UINT8 brightmode = 0;
|
||||
extracolormap_t *colormap = sector->extra_colormap;
|
||||
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
|
||||
if (spr->mobj->drawflags & MFD_BRIGHTMASK)
|
||||
{
|
||||
if (spr->mobj->drawflags & MFD_FULLBRIGHT)
|
||||
brightmode = 1;
|
||||
else if (spr->mobj->drawflags & MFD_SEMIBRIGHT)
|
||||
brightmode = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spr->mobj->frame & FF_FULLBRIGHT)
|
||||
brightmode = 1;
|
||||
else if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
brightmode = 2;
|
||||
}
|
||||
|
||||
if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
if (brightmode != 1)
|
||||
lightlevel = sector->lightlevel;
|
||||
|
||||
if (brightmode == 2)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
|
||||
HWR_Lighting(&Surf, lightlevel, colormap);
|
||||
|
|
@ -4099,17 +4118,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
else
|
||||
occlusion = PF_Occlude;
|
||||
|
||||
if (!cv_translucency.value) // translucency disabled
|
||||
{
|
||||
Surf.PolyColor.s.alpha = 0xFF;
|
||||
blend = PF_Translucent|occlusion;
|
||||
if (!occlusion) use_linkdraw_hack = true;
|
||||
}
|
||||
else if (spr->mobj->flags2 & MF2_SHADOW)
|
||||
{
|
||||
Surf.PolyColor.s.alpha = 0x40;
|
||||
blend = PF_Translucent;
|
||||
}
|
||||
if (spr->mobj->drawflags & MFD_TRANSMASK)
|
||||
blend = HWR_TranstableToAlpha((spr->mobj->drawflags & MFD_TRANSMASK)>>MFD_TRANSSHIFT, &Surf);
|
||||
else if (spr->mobj->frame & FF_TRANSMASK)
|
||||
blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
|
||||
else
|
||||
|
|
@ -4182,43 +4192,53 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
|
|||
{
|
||||
sector_t *sector = spr->mobj->subsector->sector;
|
||||
UINT8 lightlevel = 255;
|
||||
UINT8 brightmode = 0;
|
||||
extracolormap_t *colormap = sector->extra_colormap;
|
||||
|
||||
if (spr->mobj->drawflags & MFD_BRIGHTMASK)
|
||||
{
|
||||
if (spr->mobj->drawflags & MFD_FULLBRIGHT)
|
||||
brightmode = 1;
|
||||
else if (spr->mobj->drawflags & MFD_SEMIBRIGHT)
|
||||
brightmode = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spr->mobj->frame & FF_FULLBRIGHT)
|
||||
brightmode = 1;
|
||||
else if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
brightmode = 2;
|
||||
}
|
||||
|
||||
if (sector->numlights)
|
||||
{
|
||||
INT32 light;
|
||||
|
||||
light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before
|
||||
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
|
||||
|
||||
if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
if (brightmode != 1)
|
||||
lightlevel = *sector->lightlist[light].lightlevel;
|
||||
|
||||
if (*sector->lightlist[light].extra_colormap)
|
||||
colormap = *sector->lightlist[light].extra_colormap;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
|
||||
|
||||
if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
if (brightmode != 1)
|
||||
lightlevel = sector->lightlevel;
|
||||
|
||||
if (sector->extra_colormap)
|
||||
colormap = sector->extra_colormap;
|
||||
}
|
||||
|
||||
if (brightmode == 2)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
|
||||
HWR_Lighting(&Surf, lightlevel, colormap);
|
||||
}
|
||||
|
||||
if (spr->mobj->flags2 & MF2_SHADOW)
|
||||
{
|
||||
Surf.PolyColor.s.alpha = 0x40;
|
||||
blend = PF_Translucent;
|
||||
}
|
||||
if (spr->mobj->drawflags & MFD_TRANSMASK)
|
||||
blend = HWR_TranstableToAlpha((spr->mobj->drawflags & MFD_TRANSMASK)>>MFD_TRANSSHIFT, &Surf);
|
||||
else if (spr->mobj->frame & FF_TRANSMASK)
|
||||
blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
|
||||
else
|
||||
|
|
@ -4259,6 +4279,12 @@ static int CompareVisSprites(const void *p1, const void *p2)
|
|||
int transparency1;
|
||||
int transparency2;
|
||||
|
||||
int drawflags1;
|
||||
int drawflags2;
|
||||
|
||||
int frame1;
|
||||
int frame2;
|
||||
|
||||
// check for precip first, because then sprX->mobj is actually a precipmobj_t and does not have flags2 or tracer
|
||||
int linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer;
|
||||
int linkdraw2 = !spr2->precip && (spr2->mobj->flags2 & MF2_LINKDRAW) && spr2->mobj->tracer;
|
||||
|
|
@ -4271,34 +4297,48 @@ static int CompareVisSprites(const void *p1, const void *p2)
|
|||
if (linkdraw1)
|
||||
{
|
||||
tz1 = spr1->tracertz;
|
||||
transparency1 = (spr1->mobj->tracer->flags2 & MF2_SHADOW) || (spr1->mobj->tracer->frame & FF_TRANSMASK);
|
||||
drawflags1 = spr1->mobj->tracer->drawflags;
|
||||
frame1 = spr1->mobj->tracer->frame;
|
||||
}
|
||||
else
|
||||
{
|
||||
tz1 = spr1->tz;
|
||||
transparency1 = (!spr1->precip && (spr1->mobj->flags2 & MF2_SHADOW)) || (spr1->mobj->frame & FF_TRANSMASK);
|
||||
drawflags1 = (spr1->precip ? 0 : spr1->mobj->drawflags);
|
||||
frame1 = spr1->mobj->frame;
|
||||
}
|
||||
if (linkdraw2)
|
||||
{
|
||||
tz2 = spr2->tracertz;
|
||||
transparency2 = (spr2->mobj->tracer->flags2 & MF2_SHADOW) || (spr2->mobj->tracer->frame & FF_TRANSMASK);
|
||||
drawflags2 = spr2->mobj->tracer->drawflags;
|
||||
frame2 = spr2->mobj->tracer->frame;
|
||||
}
|
||||
else
|
||||
{
|
||||
tz2 = spr2->tz;
|
||||
transparency2 = (!spr2->precip && (spr2->mobj->flags2 & MF2_SHADOW)) || (spr2->mobj->frame & FF_TRANSMASK);
|
||||
drawflags2 = (spr2->precip ? 0 : spr2->mobj->drawflags);
|
||||
frame2 = spr2->mobj->frame;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tz1 = spr1->tz;
|
||||
transparency1 = (!spr1->precip && (spr1->mobj->flags2 & MF2_SHADOW)) || (spr1->mobj->frame & FF_TRANSMASK);
|
||||
drawflags1 = (spr1->precip ? 0 : spr1->mobj->drawflags);
|
||||
frame1 = spr1->mobj->frame;
|
||||
tz2 = spr2->tz;
|
||||
transparency2 = (!spr2->precip && (spr2->mobj->flags2 & MF2_SHADOW)) || (spr2->mobj->frame & FF_TRANSMASK);
|
||||
drawflags2 = (spr2->precip ? 0 : spr2->mobj->drawflags);
|
||||
frame2 = spr2->mobj->frame;
|
||||
}
|
||||
|
||||
// first compare transparency flags, then compare tz, then compare dispoffset
|
||||
|
||||
transparency1 = (drawflags1 & FF_TRANSMASK) ?
|
||||
((drawflags1 & FF_TRANSMASK)>>MFD_TRANSSHIFT) :
|
||||
((frame1 & FF_TRANSMASK)>>FF_TRANSSHIFT);
|
||||
|
||||
transparency2 = (drawflags2 & FF_TRANSMASK) ?
|
||||
((drawflags2 & FF_TRANSMASK)>>MFD_TRANSSHIFT) :
|
||||
((frame2 & FF_TRANSMASK)>>FF_TRANSSHIFT);
|
||||
|
||||
idiff = transparency1 - transparency2;
|
||||
if (idiff != 0) return idiff;
|
||||
|
||||
|
|
|
|||
|
|
@ -1260,6 +1260,23 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
sector_t *sector = spr->mobj->subsector->sector;
|
||||
UINT8 lightlevel = 255;
|
||||
extracolormap_t *colormap = NULL;
|
||||
UINT8 brightmode = 0;
|
||||
|
||||
|
||||
if (spr->mobj->drawflags & MFD_BRIGHTMASK)
|
||||
{
|
||||
if (spr->mobj->drawflags & MFD_FULLBRIGHT)
|
||||
brightmode = 1;
|
||||
else if (spr->mobj->drawflags & MFD_SEMIBRIGHT)
|
||||
brightmode = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spr->mobj->frame & FF_FULLBRIGHT)
|
||||
brightmode = 1;
|
||||
else if (spr->mobj->frame & FF_SEMIBRIGHT)
|
||||
brightmode = 2;
|
||||
}
|
||||
|
||||
if (sector->numlights)
|
||||
{
|
||||
|
|
@ -1267,21 +1284,24 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
|
||||
light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before
|
||||
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
|
||||
if (brightmode != 1)
|
||||
lightlevel = *sector->lightlist[light].lightlevel;
|
||||
|
||||
if (*sector->lightlist[light].extra_colormap)
|
||||
colormap = *sector->lightlist[light].extra_colormap;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
||||
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
|
||||
if (brightmode != 1)
|
||||
lightlevel = sector->lightlevel;
|
||||
|
||||
if (sector->extra_colormap)
|
||||
colormap = sector->extra_colormap;
|
||||
}
|
||||
|
||||
if (brightmode == 2)
|
||||
lightlevel = 128 + (lightlevel>>1);
|
||||
|
||||
HWR_Lighting(&Surf, lightlevel, colormap);
|
||||
}
|
||||
else
|
||||
|
|
@ -1311,8 +1331,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
//if (tics > durs)
|
||||
//durs = tics;
|
||||
|
||||
if (spr->mobj->flags2 & MF2_SHADOW)
|
||||
Surf.PolyColor.s.alpha = 0x40;
|
||||
if (spr->mobj->drawflags & MFD_TRANSMASK)
|
||||
HWR_TranstableToAlpha((spr->mobj->drawflags & MFD_TRANSMASK)>>MFD_TRANSSHIFT, &Surf);
|
||||
else if (spr->mobj->frame & FF_TRANSMASK)
|
||||
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ static const GLfloat byte2float[256] = {
|
|||
// -----------------+
|
||||
|
||||
#ifdef DEBUG_TO_FILE
|
||||
FILE *gllogstream;
|
||||
FILE *gllogstream = NULL;
|
||||
#endif
|
||||
|
||||
FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
|
||||
|
|
@ -149,14 +149,14 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
|
|||
char str[4096] = "";
|
||||
va_list arglist;
|
||||
|
||||
if (!gllogstream)
|
||||
gllogstream = fopen("ogllog.txt", "w");
|
||||
if (gllogstream)
|
||||
{
|
||||
va_start(arglist, format);
|
||||
vsnprintf(str, 4096, format, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
va_start(arglist, format);
|
||||
vsnprintf(str, 4096, format, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
fwrite(str, strlen(str), 1, gllogstream);
|
||||
fwrite(str, strlen(str), 1, gllogstream);
|
||||
}
|
||||
#else
|
||||
(void)format;
|
||||
#endif
|
||||
|
|
|
|||
290
src/hu_stuff.c
290
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
|
||||
|
|
@ -52,6 +53,7 @@
|
|||
|
||||
#include "s_sound.h" // song credits
|
||||
#include "k_kart.h"
|
||||
#include "k_color.h"
|
||||
|
||||
// coords are scaled
|
||||
#define HU_INPUTX 0
|
||||
|
|
@ -63,24 +65,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];
|
||||
patch_t *ttlnum[10]; // act numbers (0-9)
|
||||
|
||||
// Name tag fonts
|
||||
patch_t *ntb_font[NT_FONTSIZE];
|
||||
patch_t *nto_font[NT_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
|
||||
|
||||
|
|
@ -193,128 +180,25 @@ 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX);
|
||||
|
||||
// cache act numbers for level titles
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
sprintf(buffer, "TTL%.2d", i);
|
||||
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// cache the base name tag font for entire game execution
|
||||
j = NT_FONTSTART;
|
||||
for (i = 0; i < NT_FONTSIZE; i++)
|
||||
{
|
||||
sprintf(buffer, "NTFNT%.3d", j);
|
||||
j++;
|
||||
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
ntb_font[i] = NULL;
|
||||
else
|
||||
ntb_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// cache the outline name tag font for entire game execution
|
||||
j = NT_FONTSTART;
|
||||
for (i = 0; i < NT_FONTSIZE; i++)
|
||||
{
|
||||
sprintf(buffer, "NTFNO%.3d", j);
|
||||
j++;
|
||||
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
nto_font[i] = NULL;
|
||||
else
|
||||
nto_font[i] = (patch_t *)W_CachePatchName(buffer, 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);
|
||||
|
||||
exiticon = W_CachePatchName("EXITICON", PU_HUDGFX);
|
||||
emblemicon = HU_CachePatch("EMBLICON");
|
||||
tokenicon = HU_CachePatch("TOKNICON");
|
||||
|
||||
emeraldpics[0][0] = W_CachePatchName("CHAOS1", PU_HUDGFX);
|
||||
emeraldpics[0][1] = W_CachePatchName("CHAOS2", PU_HUDGFX);
|
||||
|
|
@ -343,20 +227,18 @@ void HU_LoadGraphics(void)
|
|||
emeraldpics[2][6] = W_CachePatchName("EMBOX7", PU_HUDGFX);
|
||||
//emeraldpics[2][7] = W_CachePatchName("EMBOX8", PU_HUDGFX); -- unused
|
||||
|
||||
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
|
||||
|
|
@ -364,6 +246,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);
|
||||
|
|
@ -375,9 +259,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;
|
||||
|
|
@ -780,62 +733,40 @@ 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;
|
||||
char color_prefix[2];
|
||||
|
||||
// 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
|
||||
{
|
||||
UINT16 chatcolor = skincolors[players[playernum].skincolor].chatcolor;
|
||||
|
||||
if (!chatcolor || chatcolor%0x1000 || chatcolor>V_TANMAP)
|
||||
cstart = "\x80";
|
||||
else if (chatcolor == V_PURPLEMAP)
|
||||
cstart = "\x81";
|
||||
else if (chatcolor == V_YELLOWMAP)
|
||||
cstart = "\x82";
|
||||
else if (chatcolor == V_GREENMAP)
|
||||
cstart = "\x83";
|
||||
else if (chatcolor == V_BLUEMAP)
|
||||
cstart = "\x84";
|
||||
else if (chatcolor == V_REDMAP)
|
||||
cstart = "\x85";
|
||||
else if (chatcolor == V_GRAYMAP)
|
||||
cstart = "\x86";
|
||||
else if (chatcolor == V_ORANGEMAP)
|
||||
cstart = "\x87";
|
||||
else if (chatcolor == V_SKYMAP)
|
||||
cstart = "\x88";
|
||||
else if (chatcolor == V_LAVENDERMAP)
|
||||
cstart = "\x89";
|
||||
else if (chatcolor == V_GOLDMAP)
|
||||
cstart = "\x8a";
|
||||
else if (chatcolor == V_AQUAMAP)
|
||||
cstart = "\x8b";
|
||||
else if (chatcolor == V_MAGENTAMAP)
|
||||
cstart = "\x8c";
|
||||
else if (chatcolor == V_PINKMAP)
|
||||
cstart = "\x8d";
|
||||
else if (chatcolor == V_BROWNMAP)
|
||||
cstart = "\x8e";
|
||||
else if (chatcolor == V_TANMAP)
|
||||
cstart = "\x8f";
|
||||
if (chatcolor > V_TANMAP)
|
||||
{
|
||||
sprintf(color_prefix, "%c", '\x80');
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(color_prefix, "%c", '\x80' + (chatcolor >> V_CHARCOLORSHIFT));
|
||||
}
|
||||
|
||||
cstart = color_prefix;
|
||||
}
|
||||
prefix = cstart;
|
||||
|
||||
|
|
@ -844,6 +775,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)
|
||||
|
|
@ -911,7 +843,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);
|
||||
|
|
@ -1353,7 +1285,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;
|
||||
|
|
@ -2309,11 +2241,17 @@ void
|
|||
HU_drawMiniPing (INT32 x, INT32 y, UINT32 ping, INT32 flags)
|
||||
{
|
||||
patch_t *patch;
|
||||
INT32 w = BASEVIDWIDTH;
|
||||
|
||||
if (r_splitscreen > 1)
|
||||
{
|
||||
w /= 2;
|
||||
}
|
||||
|
||||
patch = mping[Ping_gfx_num(ping)];
|
||||
|
||||
if (( flags & V_SNAPTORIGHT ))
|
||||
x += ( BASEVIDWIDTH - SHORT (patch->width) );
|
||||
x += ( w - SHORT (patch->width) );
|
||||
|
||||
V_DrawScaledPatch(x, y, flags, patch);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "d_event.h"
|
||||
#include "w_wad.h"
|
||||
#include "r_defs.h"
|
||||
#include "font.h"
|
||||
|
||||
//------------------------------------
|
||||
// heads up font
|
||||
|
|
@ -42,11 +43,22 @@
|
|||
#define CRED_FONTEND 'Z' // the last font character
|
||||
#define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1)
|
||||
|
||||
// Name tag font
|
||||
// Used by base and outline font set
|
||||
#define NT_FONTSTART '!' // the first font character
|
||||
#define NT_FONTEND 'Z' // the last font character
|
||||
#define NT_FONTSIZE (NT_FONTEND - NT_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();
|
||||
|
||||
|
|
@ -84,19 +96,10 @@ 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 *ntb_font[NT_FONTSIZE];
|
||||
extern patch_t *nto_font[NT_FONTSIZE];
|
||||
extern patch_t *ttlnum[10];
|
||||
extern patch_t *emeraldpics[3][8];
|
||||
|
||||
extern patch_t *rflagico;
|
||||
extern patch_t *bflagico;
|
||||
extern patch_t *rmatcico;
|
||||
|
|
@ -114,6 +117,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);
|
||||
|
||||
|
|
|
|||
288
src/info.c
288
src/info.c
|
|
@ -532,7 +532,9 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"ICEB","CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS",
|
||||
"ZTCH","MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH",
|
||||
"BFRT","OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN",
|
||||
"FWRK","MXCL","RGSP","DRAF","GRES","OTFG","DBOS","XMS4","XMS5","VIEW"
|
||||
|
||||
"FWRK","MXCL","RGSP","DRAF","GRES","OTFG","DBOS","EGOO","WTRL","XMS4",
|
||||
"XMS5","FBUB","GCHA","CHEZ","VIEW","DBCL","DBNC","DBST",
|
||||
};
|
||||
|
||||
char spr2names[NUMPLAYERSPRITES][5] =
|
||||
|
|
@ -3849,10 +3851,42 @@ state_t states[NUMSTATES] =
|
|||
{SPR_DSHR, FF_PAPERSPRITE|5, 1, {NULL}, 0, 0, S_FASTDUST7}, // S_FASTDUST6
|
||||
{SPR_DSHR, FF_PAPERSPRITE|6, 1, {NULL}, 0, 0, S_NULL}, // S_FASTDUST7
|
||||
|
||||
{SPR_DBOS, FF_FULLBRIGHT, 2, {NULL}, 6, 1, S_DRIFTEXPLODE2}, // S_DRIFTEXPLODE1
|
||||
{SPR_DBOS, FF_FULLBRIGHT|1, 2, {NULL}, 6, 1, S_DRIFTEXPLODE3}, // S_DRIFTEXPLODE2
|
||||
{SPR_DBOS, FF_FULLBRIGHT|2, 2, {NULL}, 6, 1, S_DRIFTEXPLODE4}, // S_DRIFTEXPLODE3
|
||||
{SPR_DBOS, FF_FULLBRIGHT|3, 2, {NULL}, 6, 1, S_DRIFTEXPLODE1}, // S_DRIFTEXPLODE4
|
||||
{SPR_DBOS, FF_FULLBRIGHT, 1, {NULL}, 6, 1, S_DRIFTEXPLODE2}, // S_DRIFTEXPLODE1
|
||||
{SPR_DBST, FF_PAPERSPRITE|FF_FULLBRIGHT, 1, {NULL}, 6, 1, S_DRIFTEXPLODE3}, // S_DRIFTEXPLODE2
|
||||
{SPR_DBOS, FF_FULLBRIGHT|1, 1, {NULL}, 6, 1, S_DRIFTEXPLODE4}, // S_DRIFTEXPLODE3
|
||||
{SPR_DBST, FF_PAPERSPRITE|FF_FULLBRIGHT|1, 1, {NULL}, 6, 1, S_DRIFTEXPLODE5}, // S_DRIFTEXPLODE4
|
||||
{SPR_DBOS, FF_FULLBRIGHT|2, 1, {NULL}, 6, 1, S_DRIFTEXPLODE6}, // S_DRIFTEXPLODE5
|
||||
{SPR_DBST, FF_PAPERSPRITE|FF_FULLBRIGHT|2, 1, {NULL}, 6, 1, S_DRIFTEXPLODE7}, // S_DRIFTEXPLODE6
|
||||
{SPR_DBOS, FF_FULLBRIGHT|3, 1, {NULL}, 6, 1, S_DRIFTEXPLODE8}, // S_DRIFTEXPLODE7
|
||||
{SPR_DBST, FF_PAPERSPRITE|FF_FULLBRIGHT|3, 1, {NULL}, 6, 1, S_DRIFTEXPLODE1}, // S_DRIFTEXPLODE8
|
||||
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x0, 1, {NULL}, 6, 1, S_DRIFTCLIPA2}, // S_DRIFTCLIPA1
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x8, 1, {NULL}, 6, 1, S_DRIFTCLIPA3}, // S_DRIFTCLIPA2
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x1, 1, {NULL}, 6, 1, S_DRIFTCLIPA4}, // S_DRIFTCLIPA3
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x9, 1, {NULL}, 6, 1, S_DRIFTCLIPA5}, // S_DRIFTCLIPA4
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x2, 1, {NULL}, 6, 1, S_DRIFTCLIPA6}, // S_DRIFTCLIPA5
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0xA, 1, {NULL}, 6, 1, S_DRIFTCLIPA7}, // S_DRIFTCLIPA6
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x3, 1, {NULL}, 6, 1, S_DRIFTCLIPA8}, // S_DRIFTCLIPA7
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0xB, 1, {NULL}, 6, 1, S_DRIFTCLIPA9}, // S_DRIFTCLIPA8
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x4, 1, {NULL}, 6, 1, S_DRIFTCLIPA10}, // S_DRIFTCLIPA9
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0xC, 1, {NULL}, 6, 1, S_DRIFTCLIPA11}, // S_DRIFTCLIPA10
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x5, 1, {NULL}, 6, 1, S_DRIFTCLIPA12}, // S_DRIFTCLIPA11
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0xD, 1, {NULL}, 6, 1, S_DRIFTCLIPA13}, // S_DRIFTCLIPA12
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x6, 1, {NULL}, 6, 1, S_DRIFTCLIPA14}, // S_DRIFTCLIPA13
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0xE, 1, {NULL}, 6, 1, S_DRIFTCLIPA15}, // S_DRIFTCLIPA14
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0x7, 1, {NULL}, 6, 1, S_DRIFTCLIPA16}, // S_DRIFTCLIPA15
|
||||
{SPR_DBCL, FF_FULLBRIGHT|0xF, 1, {NULL}, 6, 1, S_DRIFTCLIPB1}, // S_DRIFTCLIPA16
|
||||
|
||||
{SPR_DBCL, FF_FULLBRIGHT, 2, {NULL}, 6, 1, S_DRIFTCLIPB2}, // S_DRIFTCLIPB1
|
||||
{SPR_DBCL, FF_FULLBRIGHT|1, 2, {NULL}, 6, 1, S_DRIFTCLIPB3}, // S_DRIFTCLIPB2
|
||||
{SPR_DBCL, FF_FULLBRIGHT|2, 2, {NULL}, 6, 1, S_DRIFTCLIPB4}, // S_DRIFTCLIPB3
|
||||
{SPR_DBCL, FF_FULLBRIGHT|3, 2, {NULL}, 6, 1, S_DRIFTCLIPB5}, // S_DRIFTCLIPB4
|
||||
{SPR_DBCL, FF_FULLBRIGHT|4, 2, {NULL}, 6, 1, S_DRIFTCLIPB6}, // S_DRIFTCLIPB5
|
||||
{SPR_DBCL, FF_FULLBRIGHT|5, 2, {NULL}, 6, 1, S_DRIFTCLIPB7}, // S_DRIFTCLIPB6
|
||||
{SPR_DBCL, FF_FULLBRIGHT|6, 2, {NULL}, 6, 1, S_DRIFTCLIPB8}, // S_DRIFTCLIPB7
|
||||
{SPR_DBCL, FF_FULLBRIGHT|7, 2, {NULL}, 6, 1, S_DRIFTCLIPB1}, // S_DRIFTCLIPB8
|
||||
|
||||
{SPR_DBNC, FF_FULLBRIGHT|FF_ANIMATE, 14, {NULL}, 6, 1, S_NULL}, // S_DRIFTCLIPSPARK
|
||||
|
||||
{SPR_BOST, FF_FULLBRIGHT|FF_ANIMATE, TICRATE, {NULL}, 6, 1, S_BOOSTSMOKESPAWNER}, // S_BOOSTFLAME
|
||||
{SPR_NULL, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_BOOSTSMOKESPAWNER
|
||||
|
|
@ -4752,6 +4786,37 @@ state_t states[NUMSTATES] =
|
|||
{SPR_SMOK, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4
|
||||
{SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5
|
||||
|
||||
|
||||
// followers:
|
||||
|
||||
// bubble
|
||||
{SPR_FBUB, 11|FF_ANIMATE|FF_TRANS70|FF_FULLBRIGHT, -1, {NULL}, 10, 3, S_FOLLOWERBUBBLE_FRONT}, // S_FOLLOWERBUBBLE_FRONT
|
||||
{SPR_FBUB, FF_ANIMATE|0|FF_FULLBRIGHT, -1, {NULL}, 10, 3, S_FOLLOWERBUBBLE_BACK}, // S_FOLLOWERBUBBLE_BACK
|
||||
|
||||
// generic chao:
|
||||
{SPR_GCHA, FF_ANIMATE, -1, {NULL}, 1, 4, S_GCHAOIDLE}, //S_GCHAOIDLE
|
||||
{SPR_GCHA, 2|FF_ANIMATE, -1, {NULL}, 1, 2, S_GCHAOFLY}, //S_GCHAOFLY
|
||||
{SPR_GCHA, 7, 5, {NULL}, 0, 0, S_GCHAOSAD2}, //S_GCHAOSAD1
|
||||
{SPR_GCHA, 8, 3, {NULL}, 0, 0, S_GCHAOSAD3}, //S_GCHAOSAD2
|
||||
{SPR_GCHA, 9, 6, {NULL}, 0, 0, S_GCHAOSAD4}, //S_GCHAOSAD3
|
||||
{SPR_GCHA, 8, 3, {NULL}, 0, 0, S_GCHAOSAD1}, //S_GCHAOSAD4
|
||||
{SPR_GCHA, 4, 8, {NULL}, 0, 0, S_GCHAOHAPPY2}, //S_GCHAOHAPPY1
|
||||
{SPR_GCHA, 5, 4, {NULL}, 0, 0, S_GCHAOHAPPY3}, //S_GCHAOHAPPY2
|
||||
{SPR_GCHA, 6, 8, {NULL}, 0, 0, S_GCHAOHAPPY4}, //S_GCHAOHAPPY3
|
||||
{SPR_GCHA, 5, 4, {NULL}, 0, 0, S_GCHAOHAPPY1}, //S_GCHAOHAPPY4
|
||||
|
||||
// cheese:
|
||||
{SPR_CHEZ, FF_ANIMATE, -1, {NULL}, 1, 4, S_CHEESEIDLE}, //S_CHEESEIDLE
|
||||
{SPR_CHEZ, 2|FF_ANIMATE, -1, {NULL}, 1, 2, S_CHEESEFLY}, //S_CHEESEFLY
|
||||
{SPR_CHEZ, 7, 5, {NULL}, 0, 0, S_CHEESESAD2}, //S_CHEESESAD1
|
||||
{SPR_CHEZ, 8, 3, {NULL}, 0, 0, S_CHEESESAD3}, //S_CHEESESAD2
|
||||
{SPR_CHEZ, 9, 6, {NULL}, 0, 0, S_CHEESESAD4}, //S_CHEESESAD3
|
||||
{SPR_CHEZ, 8, 3, {NULL}, 0, 0, S_CHEESESAD1}, //S_CHEESESAD4
|
||||
{SPR_CHEZ, 4, 8, {NULL}, 0, 0, S_CHEESEHAPPY2}, //S_CHEESEHAPPY1
|
||||
{SPR_CHEZ, 5, 4, {NULL}, 0, 0, S_CHEESEHAPPY3}, //S_CHEESEHAPPY2
|
||||
{SPR_CHEZ, 6, 8, {NULL}, 0, 0, S_CHEESEHAPPY4}, //S_CHEESEHAPPY3
|
||||
{SPR_CHEZ, 5, 4, {NULL}, 0, 0, S_CHEESEHAPPY1}, //S_CHEESEHAPPY4
|
||||
|
||||
{SPR_MXCL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_RINGDEBT
|
||||
|
||||
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_RINGSPARKS2}, // S_RINGSPARKS1
|
||||
|
|
@ -4789,6 +4854,26 @@ state_t states[NUMSTATES] =
|
|||
{SPR_CAPS, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BATTLECAPSULE_SUPPORT
|
||||
{SPR_CAPS, FF_ANIMATE|5, -1, {NULL}, 3, 1, S_NULL}, // S_BATTLECAPSULE_SUPPORTFLY
|
||||
|
||||
{SPR_EGOO, 0, 1, {NULL}, 0, 0, S_NULL}, // S_EGOORB
|
||||
|
||||
// Water Trail
|
||||
{SPR_WTRL, FF_PAPERSPRITE , 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL1
|
||||
{SPR_WTRL, FF_PAPERSPRITE|1, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL2
|
||||
{SPR_WTRL, FF_PAPERSPRITE|2, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL3
|
||||
{SPR_WTRL, FF_PAPERSPRITE|3, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL4
|
||||
{SPR_WTRL, FF_PAPERSPRITE|4, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL5
|
||||
{SPR_WTRL, FF_PAPERSPRITE|5, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL6
|
||||
{SPR_WTRL, FF_PAPERSPRITE|6, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL7
|
||||
{SPR_WTRL, FF_PAPERSPRITE|7, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAIL8
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|8, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY1
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|9, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY2
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|10, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY3
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|11, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY4
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|12, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY5
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|13, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY6
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|14, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY7
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|15, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY8
|
||||
|
||||
#ifdef SEENAMES
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
|
||||
#endif
|
||||
|
|
@ -22706,6 +22791,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_DRIFTCLIP
|
||||
-1, // doomednum
|
||||
S_DRIFTCLIPA1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
105, // speed
|
||||
32*FRACUNIT, // radius
|
||||
64*FRACUNIT, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_DONTENCOREMAP|MF_GRENADEBOUNCE|MF_BOUNCE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_DRIFTCLIPSPARK
|
||||
-1, // doomednum
|
||||
S_DRIFTCLIPSPARK, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
8, // speed
|
||||
32*FRACUNIT, // radius
|
||||
64*FRACUNIT, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BOOSTFLAME
|
||||
-1, // doomednum
|
||||
S_BOOSTFLAME, // spawnstate
|
||||
|
|
@ -27946,6 +28085,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
||||
{ // MT_RINGSPARKS
|
||||
-1, // doomednum
|
||||
S_RINGSPARKS1, // spawnstate
|
||||
|
|
@ -28189,6 +28329,144 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_FOLLOWER
|
||||
-1, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
8<<FRACBITS, // radius
|
||||
16<<FRACBITS, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
|
||||
MF_NOCLIPTHING|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL, // raisestate
|
||||
},
|
||||
|
||||
{ // MT_FOLLOWERBUBBLE_FRONT
|
||||
-1, // doomednum
|
||||
S_FOLLOWERBUBBLE_FRONT, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
8<<FRACBITS, // radius
|
||||
16<<FRACBITS, // height
|
||||
2, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
|
||||
MF_NOCLIPTHING|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL, // raisestate
|
||||
},
|
||||
|
||||
{ // MT_FOLLOWERBUBBLE_BACK
|
||||
-1, // doomednum
|
||||
S_FOLLOWERBUBBLE_BACK, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
8<<FRACBITS, // radius
|
||||
16<<FRACBITS, // height
|
||||
-2, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
|
||||
MF_NOCLIPTHING|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL, // raisestate
|
||||
},
|
||||
|
||||
{ // MT_WATERTRAIL
|
||||
-1, // doomednum
|
||||
S_WATERTRAIL1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
48*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_WATERTRAILUNDERLAY
|
||||
-1, // doomednum
|
||||
S_WATERTRAILUNDERLAY1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
48*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
// ============================================================================================================================//
|
||||
|
||||
#ifdef SEENAMES
|
||||
|
|
|
|||
103
src/info.h
103
src/info.h
|
|
@ -999,9 +999,21 @@ typedef enum sprite
|
|||
|
||||
SPR_DBOS, // Drift boost flame
|
||||
|
||||
SPR_EGOO,
|
||||
|
||||
SPR_WTRL, // Water Trail
|
||||
|
||||
SPR_FBUB, // follower bubble
|
||||
SPR_GCHA, // follower: generic chao
|
||||
SPR_CHEZ, // follower: cheese
|
||||
|
||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||
SPR_VIEW,
|
||||
|
||||
SPR_DBCL, // Drift boost clip
|
||||
SPR_DBNC, // Drift boost clip's sparks
|
||||
SPR_DBST, // Drift boost plume
|
||||
|
||||
SPR_FIRSTFREESLOT,
|
||||
SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1,
|
||||
NUMSPRITES
|
||||
|
|
@ -4153,6 +4165,39 @@ typedef enum state
|
|||
S_DRIFTEXPLODE2,
|
||||
S_DRIFTEXPLODE3,
|
||||
S_DRIFTEXPLODE4,
|
||||
S_DRIFTEXPLODE5,
|
||||
S_DRIFTEXPLODE6,
|
||||
S_DRIFTEXPLODE7,
|
||||
S_DRIFTEXPLODE8,
|
||||
|
||||
// Drift boost clip
|
||||
S_DRIFTCLIPA1,
|
||||
S_DRIFTCLIPA2,
|
||||
S_DRIFTCLIPA3,
|
||||
S_DRIFTCLIPA4,
|
||||
S_DRIFTCLIPA5,
|
||||
S_DRIFTCLIPA6,
|
||||
S_DRIFTCLIPA7,
|
||||
S_DRIFTCLIPA8,
|
||||
S_DRIFTCLIPA9,
|
||||
S_DRIFTCLIPA10,
|
||||
S_DRIFTCLIPA11,
|
||||
S_DRIFTCLIPA12,
|
||||
S_DRIFTCLIPA13,
|
||||
S_DRIFTCLIPA14,
|
||||
S_DRIFTCLIPA15,
|
||||
S_DRIFTCLIPA16,
|
||||
S_DRIFTCLIPB1,
|
||||
S_DRIFTCLIPB2,
|
||||
S_DRIFTCLIPB3,
|
||||
S_DRIFTCLIPB4,
|
||||
S_DRIFTCLIPB5,
|
||||
S_DRIFTCLIPB6,
|
||||
S_DRIFTCLIPB7,
|
||||
S_DRIFTCLIPB8,
|
||||
|
||||
// Drift boost clip sparks
|
||||
S_DRIFTCLIPSPARK,
|
||||
|
||||
// Sneaker boost effect
|
||||
S_BOOSTFLAME,
|
||||
|
|
@ -5057,6 +5102,36 @@ typedef enum state
|
|||
S_OPAQUESMOKE4,
|
||||
S_OPAQUESMOKE5,
|
||||
|
||||
// followers:
|
||||
|
||||
// bubble:
|
||||
S_FOLLOWERBUBBLE_FRONT,
|
||||
S_FOLLOWERBUBBLE_BACK,
|
||||
|
||||
// generic chao:
|
||||
S_GCHAOIDLE,
|
||||
S_GCHAOFLY,
|
||||
S_GCHAOSAD1,
|
||||
S_GCHAOSAD2,
|
||||
S_GCHAOSAD3,
|
||||
S_GCHAOSAD4,
|
||||
S_GCHAOHAPPY1,
|
||||
S_GCHAOHAPPY2,
|
||||
S_GCHAOHAPPY3,
|
||||
S_GCHAOHAPPY4,
|
||||
|
||||
// cheese:
|
||||
S_CHEESEIDLE,
|
||||
S_CHEESEFLY,
|
||||
S_CHEESESAD1,
|
||||
S_CHEESESAD2,
|
||||
S_CHEESESAD3,
|
||||
S_CHEESESAD4,
|
||||
S_CHEESEHAPPY1,
|
||||
S_CHEESEHAPPY2,
|
||||
S_CHEESEHAPPY3,
|
||||
S_CHEESEHAPPY4,
|
||||
|
||||
S_RINGDEBT,
|
||||
S_RINGSPARKS1,
|
||||
S_RINGSPARKS2,
|
||||
|
|
@ -5093,6 +5168,25 @@ typedef enum state
|
|||
S_BATTLECAPSULE_SUPPORT,
|
||||
S_BATTLECAPSULE_SUPPORTFLY,
|
||||
|
||||
S_EGOORB,
|
||||
|
||||
S_WATERTRAIL1,
|
||||
S_WATERTRAIL2,
|
||||
S_WATERTRAIL3,
|
||||
S_WATERTRAIL4,
|
||||
S_WATERTRAIL5,
|
||||
S_WATERTRAIL6,
|
||||
S_WATERTRAIL7,
|
||||
S_WATERTRAIL8,
|
||||
S_WATERTRAILUNDERLAY1,
|
||||
S_WATERTRAILUNDERLAY2,
|
||||
S_WATERTRAILUNDERLAY3,
|
||||
S_WATERTRAILUNDERLAY4,
|
||||
S_WATERTRAILUNDERLAY5,
|
||||
S_WATERTRAILUNDERLAY6,
|
||||
S_WATERTRAILUNDERLAY7,
|
||||
S_WATERTRAILUNDERLAY8,
|
||||
|
||||
#ifdef SEENAMES
|
||||
S_NAMECHECK,
|
||||
#endif
|
||||
|
|
@ -5910,6 +6004,8 @@ typedef enum mobj_type
|
|||
MT_FASTLINE,
|
||||
MT_FASTDUST,
|
||||
MT_DRIFTEXPLODE,
|
||||
MT_DRIFTCLIP,
|
||||
MT_DRIFTCLIPSPARK,
|
||||
MT_BOOSTFLAME,
|
||||
MT_BOOSTSMOKE,
|
||||
MT_SNEAKERTRAIL,
|
||||
|
|
@ -6186,6 +6282,13 @@ typedef enum mobj_type
|
|||
MT_BATTLECAPSULE,
|
||||
MT_BATTLECAPSULE_PIECE,
|
||||
|
||||
MT_FOLLOWER,
|
||||
MT_FOLLOWERBUBBLE_FRONT,
|
||||
MT_FOLLOWERBUBBLE_BACK,
|
||||
|
||||
MT_WATERTRAIL,
|
||||
MT_WATERTRAILUNDERLAY,
|
||||
|
||||
#ifdef SEENAMES
|
||||
MT_NAMECHECK,
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -256,7 +256,6 @@ void K_CheckBumpers(void)
|
|||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
players[i].pflags |= PF_TIMEOVER;
|
||||
//players[i].lives = 0;
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
}
|
||||
|
|
@ -397,7 +396,7 @@ static void K_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjty
|
|||
//mo->destscale = mo->scale/4;
|
||||
mo->frame += ((leveltime/4) % 8);
|
||||
/*if (battleovertime.enabled < 10*TICRATE)
|
||||
mo->flags2 |= MF2_SHADOW;*/
|
||||
mo->drawflags |= MFD_SHADOW;*/
|
||||
mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90;
|
||||
mo->z += P_RandomRange(0,48) * mo->scale;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -469,6 +469,10 @@ boolean K_BHeapPop(bheap_t *const heap, bheapitem_t *const returnitemstorage)
|
|||
heap->array[0] = heap->array[heap->count];
|
||||
heap->array[0].heapindex = 0U;
|
||||
memset(&heap->array[heap->count], 0x00, sizeof(bheapitem_t));
|
||||
if (heap->array[0].indexchanged != NULL)
|
||||
{
|
||||
heap->array[0].indexchanged(heap->array[0].data, heap->array[0].heapindex);
|
||||
}
|
||||
|
||||
K_BHeapSortDown(heap, &heap->array[0]);
|
||||
popsuccess = true;
|
||||
|
|
|
|||
80
src/k_bot.c
80
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,32 @@ 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;
|
||||
fixed_t newfrict;
|
||||
|
||||
if (rubberband <= 0)
|
||||
{
|
||||
// Never get stronger than normal friction
|
||||
return frict;
|
||||
}
|
||||
|
||||
newfrict = FixedDiv(frict, FRACUNIT + (rubberband / 2));
|
||||
|
||||
if (newfrict < 0)
|
||||
newfrict = 0;
|
||||
if (newfrict > FRACUNIT)
|
||||
newfrict = FRACUNIT;
|
||||
|
||||
return newfrict;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy)
|
||||
|
||||
|
|
@ -637,7 +682,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)
|
||||
{
|
||||
|
|
@ -658,13 +703,16 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
// Start boost handler
|
||||
if (leveltime <= starttime)
|
||||
{
|
||||
tic_t boosthold = starttime - TICRATE;
|
||||
tic_t length = (TICRATE/6);
|
||||
tic_t boosthold = starttime - K_GetSpindashChargeTime(player);
|
||||
|
||||
boosthold -= (MAXBOTDIFFICULTY - player->botvars.difficulty);
|
||||
cmd->buttons |= BT_EBRAKEMASK;
|
||||
|
||||
boosthold -= (MAXBOTDIFFICULTY - player->botvars.difficulty) * length;
|
||||
|
||||
if (leveltime >= boosthold)
|
||||
{
|
||||
cmd->buttons |= BT_ACCELERATE;
|
||||
cmd->buttons |= BT_DRIFT;
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -701,7 +749,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
if (anglediff > 90)
|
||||
{
|
||||
// Wrong way!
|
||||
cmd->forwardmove = -25;
|
||||
cmd->forwardmove = -MAXPLMOVE;
|
||||
cmd->buttons |= BT_BRAKE;
|
||||
}
|
||||
else
|
||||
|
|
@ -735,7 +783,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
cmd->buttons |= BT_ACCELERATE;
|
||||
|
||||
// Full speed ahead!
|
||||
cmd->forwardmove = 50;
|
||||
cmd->forwardmove = MAXPLMOVE;
|
||||
|
||||
if (dirdist <= rad)
|
||||
{
|
||||
|
|
|
|||
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
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b)
|
||||
{
|
||||
UINT32 redweight = 1063 * r;
|
||||
|
|
@ -48,7 +47,6 @@ UINT16 K_RainbowColor(tic_t time)
|
|||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
|
||||
{
|
||||
INT32 i;
|
||||
|
|
@ -92,14 +90,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;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,21 @@
|
|||
#define DEFAULT_STARTTRANSCOLOR 96
|
||||
#define NUM_PALETTE_ENTRIES 256
|
||||
|
||||
/*--------------------------------------------------
|
||||
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
|
||||
4122
src/k_hud.c
Normal file
4122
src/k_hud.c
Normal file
File diff suppressed because it is too large
Load diff
28
src/k_hud.h
Normal file
28
src/k_hud.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_hud.h
|
||||
/// \brief HUD drawing functions exclusive to Kart
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "doomstat.h"
|
||||
|
||||
#ifndef __K_HUD__
|
||||
#define __K_HUD__
|
||||
|
||||
#define RINGANIM_NUMFRAMES 10
|
||||
#define RINGANIM_DELAYMAX 5
|
||||
|
||||
void K_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 dupy);
|
||||
const char *K_GetItemPatch(UINT8 item, boolean tiny);
|
||||
void K_LoadKartHUDGraphics(void);
|
||||
void K_drawKartHUD(void);
|
||||
void K_drawKartFreePlay(UINT32 flashtime);
|
||||
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode);
|
||||
|
||||
#endif
|
||||
4676
src/k_kart.c
4676
src/k_kart.c
File diff suppressed because it is too large
Load diff
25
src/k_kart.h
25
src/k_kart.h
|
|
@ -13,22 +13,28 @@
|
|||
#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);
|
||||
|
||||
UINT16 K_GetPlayerDontDrawFlag(player_t *player);
|
||||
boolean K_IsPlayerLosing(player_t *player);
|
||||
fixed_t K_GetKartGameSpeedScalar(SINT8 value);
|
||||
|
||||
extern consvar_t *KartItemCVars[NUMKARTRESULTS-1];
|
||||
|
||||
UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush);
|
||||
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, boolean bot, boolean rival);
|
||||
INT32 K_GetShieldFromItem(INT32 item);
|
||||
fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against);
|
||||
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
|
||||
void K_KartPainEnergyFling(player_t *player);
|
||||
void K_FlipFromObject(mobj_t *mo, mobj_t *master);
|
||||
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
|
||||
void K_DoIngameRespawn(player_t *player);
|
||||
void K_RespawnChecker(player_t *player);
|
||||
void K_GenericExtraFlagsNoZAdjust(mobj_t *mo, mobj_t *master);
|
||||
void K_SpawnDashDustRelease(player_t *player);
|
||||
void K_SpawnDriftBoostClip(player_t *player);
|
||||
void K_SpawnDriftBoostClipSpark(mobj_t *clip);
|
||||
void K_KartMoveAnimation(player_t *player);
|
||||
void K_KartPlayerHUDUpdate(player_t *player);
|
||||
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
|
||||
|
|
@ -59,17 +65,23 @@ void K_UpdateDistanceFromFinishLine(player_t *const player);
|
|||
boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y);
|
||||
INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue);
|
||||
INT32 K_GetKartDriftSparkValue(player_t *player);
|
||||
void K_SpawnDriftBoostExplosion(player_t *player, int stage);
|
||||
void K_KartUpdatePosition(player_t *player);
|
||||
void K_DropItems(player_t *player);
|
||||
void K_DropRocketSneaker(player_t *player);
|
||||
void K_StripItems(player_t *player);
|
||||
void K_StripOther(player_t *player);
|
||||
void K_MomentumToFacing(player_t *player);
|
||||
boolean K_ApplyOffroad(player_t *player);
|
||||
tic_t K_GetSpindashChargeTime(player_t *player);
|
||||
fixed_t K_GetSpindashChargeSpeed(player_t *player);
|
||||
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
|
||||
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower);
|
||||
fixed_t K_GetKartAccel(player_t *player);
|
||||
UINT16 K_GetKartFlashing(player_t *player);
|
||||
fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove);
|
||||
SINT8 K_GetForwardMove(player_t *player);
|
||||
fixed_t K_3dKartMovement(player_t *player, boolean onground);
|
||||
boolean K_PlayerEBrake(player_t *player);
|
||||
void K_MoveKartPlayer(player_t *player, boolean onground);
|
||||
void K_CheckSpectateStatus(void);
|
||||
|
||||
|
|
@ -81,12 +93,5 @@ void K_PlayPainSound(mobj_t *source);
|
|||
void K_PlayHitEmSound(mobj_t *source);
|
||||
void K_PlayPowerGloatSound(mobj_t *source);
|
||||
|
||||
const char *K_GetItemPatch(UINT8 item, boolean tiny);
|
||||
INT32 K_calcSplitFlags(INT32 snapflags);
|
||||
void K_LoadKartHUDGraphics(void);
|
||||
void K_drawKartHUD(void);
|
||||
void K_drawKartFreePlay(UINT32 flashtime);
|
||||
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode);
|
||||
|
||||
// =========================================================================
|
||||
#endif // __K_KART__
|
||||
|
|
|
|||
|
|
@ -472,13 +472,44 @@ boolean K_PathfindAStar(path_t *const path, pathfindsetup_t *const pathfindsetup
|
|||
// Reallocate nodesarray if it's full
|
||||
if (nodesarraycount >= pathfindsetup->nodesarraycapacity)
|
||||
{
|
||||
pathfindnode_t *nodesarrayrealloc = NULL;
|
||||
pathfindsetup->nodesarraycapacity = pathfindsetup->nodesarraycapacity * 2;
|
||||
nodesarray = Z_Realloc(nodesarray, pathfindsetup->nodesarraycapacity * sizeof(pathfindnode_t), PU_STATIC, NULL);
|
||||
nodesarrayrealloc = Z_Realloc(nodesarray, pathfindsetup->nodesarraycapacity * sizeof(pathfindnode_t), PU_STATIC, NULL);
|
||||
|
||||
if (nodesarray == NULL)
|
||||
if (nodesarrayrealloc == NULL)
|
||||
{
|
||||
I_Error("K_PathfindAStar: Out of memory reallocating nodes array.");
|
||||
}
|
||||
|
||||
// Need to update pointers in closedset, openset, and node "camefrom" if nodesarray moved.
|
||||
if (nodesarray != nodesarrayrealloc)
|
||||
{
|
||||
size_t j = 0U;
|
||||
size_t arrayindex = 0U;
|
||||
for (j = 0U; j < closedsetcount; j++)
|
||||
{
|
||||
arrayindex = closedset[j] - nodesarray;
|
||||
closedset[j] = &nodesarrayrealloc[arrayindex];
|
||||
}
|
||||
for (j = 0U; j < openset.count; j++)
|
||||
{
|
||||
arrayindex = ((pathfindnode_t *)(openset.array[j].data)) - nodesarray;
|
||||
openset.array[j].data = &nodesarrayrealloc[arrayindex];
|
||||
}
|
||||
for (j = 0U; j < nodesarraycount; j++)
|
||||
{
|
||||
if (nodesarrayrealloc[j].camefrom != NULL)
|
||||
{
|
||||
arrayindex = nodesarrayrealloc[j].camefrom - nodesarray;
|
||||
nodesarrayrealloc[j].camefrom = &nodesarrayrealloc[arrayindex];
|
||||
}
|
||||
}
|
||||
|
||||
arrayindex = currentnode - nodesarray;
|
||||
currentnode = &nodesarrayrealloc[arrayindex];
|
||||
}
|
||||
|
||||
nodesarray = nodesarrayrealloc;
|
||||
}
|
||||
|
||||
// Create the new node and add it to the nodes array and open set
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
752
src/k_respawn.c
Normal file
752
src/k_respawn.c
Normal file
|
|
@ -0,0 +1,752 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_respawn.c
|
||||
/// \brief Respawning logic
|
||||
|
||||
#include "k_respawn.h"
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "g_game.h"
|
||||
#include "p_local.h"
|
||||
#include "p_tick.h"
|
||||
#include "p_setup.h"
|
||||
#include "r_main.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_slopes.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_RespawnOffset(player_t *player, boolean flip)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_RespawnOffset(player_t *player, boolean flip)
|
||||
{
|
||||
fixed_t z = 0;
|
||||
|
||||
if (flip == true)
|
||||
{
|
||||
// Lat 24/7/20: Okay so before we even think about applying this flag, check if the sector we're in doesn't already have reverse gravity for that.
|
||||
// Otherwise, we would reverse the reverse gravity and cancel it out. Yes, this is absolutely fucking dumb.
|
||||
// I'm honestly not sure if this flag is even necessary anymore but we'll keep it just in case.
|
||||
|
||||
if (P_GetMobjGravity(player->mo) < 0)
|
||||
player->mo->flags2 |= MF2_OBJECTFLIP;
|
||||
|
||||
player->mo->eflags |= MFE_VERTICALFLIP;
|
||||
z -= ((128 * mapobjectscale) + (player->mo->height));
|
||||
}
|
||||
else
|
||||
{
|
||||
player->mo->flags2 &= ~MF2_OBJECTFLIP;
|
||||
player->mo->eflags &= ~MFE_VERTICALFLIP;
|
||||
z += (128 * mapobjectscale);
|
||||
}
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint)
|
||||
|
||||
Updates a player's respawn variables to go to the provided waypoint.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to preform for.
|
||||
waypoint - Waypoint to respawn to.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint)
|
||||
{
|
||||
if (player == NULL || player->mo == NULL || P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (waypoint == NULL || waypoint->mobj == NULL || P_MobjWasRemoved(waypoint->mobj))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player->respawn.pointx = waypoint->mobj->x;
|
||||
player->respawn.pointy = waypoint->mobj->y;
|
||||
player->respawn.pointz = waypoint->mobj->z;
|
||||
player->respawn.flip = (waypoint->mobj->flags2 & MF2_OBJECTFLIP) ? true : false; // K_RespawnOffset wants a boolean!
|
||||
player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_DoIngameRespawn(player_t *player)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_DoIngameRespawn(player_t *player)
|
||||
{
|
||||
if (!player->mo || P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->respawn.state != RESPAWNST_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (leveltime < introtime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (leveltime < starttime) // FAULT
|
||||
{
|
||||
player->powers[pw_nocontrol] = (starttime - leveltime) + 50;
|
||||
player->pflags |= PF_SKIDDOWN; // cheeky pflag reuse
|
||||
S_StartSound(player->mo, sfx_s3k83);
|
||||
player->karthud[khud_fault] = 1;
|
||||
}
|
||||
|
||||
player->kartstuff[k_ringboost] = 0;
|
||||
player->kartstuff[k_driftboost] = 0;
|
||||
player->kartstuff[k_drift] = 0;
|
||||
player->kartstuff[k_driftcharge] = 0;
|
||||
player->kartstuff[k_pogospring] = 0;
|
||||
|
||||
// Set up respawn position if invalid
|
||||
if (player->respawn.wp != NULL && leveltime >= starttime)
|
||||
{
|
||||
const UINT32 dist = RESPAWN_DIST + (player->airtime * 48);
|
||||
player->respawn.distanceleft = (dist * mapobjectscale) / FRACUNIT;
|
||||
K_RespawnAtWaypoint(player, player->respawn.wp);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 bestdist = UINT32_MAX;
|
||||
mapthing_t *beststart = NULL;
|
||||
UINT8 numstarts = 0;
|
||||
|
||||
if (G_RaceGametype())
|
||||
{
|
||||
numstarts = numcoopstarts;
|
||||
}
|
||||
else if (G_BattleGametype())
|
||||
{
|
||||
numstarts = numdmstarts;
|
||||
}
|
||||
|
||||
if (numstarts > 0)
|
||||
{
|
||||
UINT8 i = 0;
|
||||
|
||||
for (i = 0; i < numstarts; i++)
|
||||
{
|
||||
UINT32 dist = UINT32_MAX;
|
||||
mapthing_t *checkstart = NULL;
|
||||
|
||||
if (G_RaceGametype())
|
||||
{
|
||||
checkstart = playerstarts[i];
|
||||
}
|
||||
else if (G_BattleGametype())
|
||||
{
|
||||
checkstart = deathmatchstarts[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
dist = (UINT32)P_AproxDistance((player->mo->x >> FRACBITS) - checkstart->x,
|
||||
(player->mo->y >> FRACBITS) - checkstart->y);
|
||||
|
||||
if (dist < bestdist)
|
||||
{
|
||||
beststart = checkstart;
|
||||
bestdist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (beststart == NULL)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "No respawn points!\n");
|
||||
player->respawn.pointx = 0;
|
||||
player->respawn.pointy = 0;
|
||||
player->respawn.pointz = 0;
|
||||
player->respawn.flip = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sector_t *s;
|
||||
fixed_t z = (beststart->options >> ZSHIFT) * FRACUNIT;
|
||||
|
||||
player->respawn.pointx = beststart->x << FRACBITS;
|
||||
player->respawn.pointy = beststart->y << FRACBITS;
|
||||
|
||||
s = R_PointInSubsector(beststart->x << FRACBITS, beststart->y << FRACBITS)->sector;
|
||||
|
||||
player->respawn.flip = (beststart->options & MTF_OBJECTFLIP);
|
||||
|
||||
if (player->respawn.flip == true)
|
||||
{
|
||||
player->respawn.pointz = (
|
||||
#ifdef ESLOPE
|
||||
s->c_slope ? P_GetZAt(s->c_slope, player->respawn.pointx, player->respawn.pointy) :
|
||||
#endif
|
||||
s->ceilingheight);
|
||||
|
||||
if (z != 0)
|
||||
{
|
||||
player->respawn.pointz -= z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player->respawn.pointz = (
|
||||
#ifdef ESLOPE
|
||||
s->f_slope ? P_GetZAt(s->f_slope, player->respawn.pointx, player->respawn.pointy) :
|
||||
#endif
|
||||
s->floorheight);
|
||||
|
||||
if (z)
|
||||
{
|
||||
player->respawn.pointz += z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip);
|
||||
player->respawn.distanceleft = 0;
|
||||
}
|
||||
|
||||
player->respawn.timer = RESPAWN_TIME;
|
||||
player->respawn.state = RESPAWNST_MOVE;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint)
|
||||
|
||||
Returns the index for the next respawn waypoint.
|
||||
|
||||
Input Arguments:-
|
||||
waypoint - Waypoint to look after.
|
||||
|
||||
Return:-
|
||||
An table index for waypoint_t -> nextwaypoints.
|
||||
--------------------------------------------------*/
|
||||
static size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint)
|
||||
{
|
||||
size_t i = 0U;
|
||||
size_t newwaypoint = SIZE_MAX;
|
||||
|
||||
// Set to the first valid nextwaypoint, for simplicity's sake.
|
||||
// If we reach the last waypoint and it's still not valid, just use it anyway. Someone needs to fix their map!
|
||||
for (i = 0U; i < waypoint->numnextwaypoints; i++)
|
||||
{
|
||||
newwaypoint = i;
|
||||
|
||||
if ((i == waypoint->numnextwaypoints - 1U)
|
||||
|| ((K_GetWaypointIsEnabled(waypoint->nextwaypoints[newwaypoint]) == true)
|
||||
&& (K_GetWaypointIsSpawnpoint(waypoint->nextwaypoints[newwaypoint]) == true)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return newwaypoint;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_MovePlayerToRespawnPoint(player_t *player)
|
||||
|
||||
Handles the movement state of the respawn animation.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to preform for.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_MovePlayerToRespawnPoint(player_t *player)
|
||||
{
|
||||
const fixed_t realstepamt = (64 * mapobjectscale);
|
||||
fixed_t stepamt = realstepamt;
|
||||
|
||||
vertex_t dest, step, laser;
|
||||
angle_t stepha, stepva;
|
||||
fixed_t dist, fulldist;
|
||||
|
||||
UINT8 lasersteps = 4;
|
||||
UINT32 laserdist;
|
||||
waypoint_t *laserwp;
|
||||
boolean laserflip;
|
||||
|
||||
player->mo->momx = player->mo->momy = player->mo->momz = 0;
|
||||
|
||||
player->powers[pw_flashing] = 2;
|
||||
player->powers[pw_nocontrol] = max(2, player->powers[pw_nocontrol]);
|
||||
|
||||
if (leveltime % 8 == 0 && !mapreset)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_s3kcas);
|
||||
}
|
||||
|
||||
dest.x = player->respawn.pointx;
|
||||
dest.y = player->respawn.pointy;
|
||||
dest.z = player->respawn.pointz;
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(
|
||||
player->mo->x - dest.x,
|
||||
player->mo->y - dest.y),
|
||||
player->mo->z - dest.z
|
||||
);
|
||||
|
||||
if (dist <= stepamt)
|
||||
{
|
||||
// Reduce by the amount we needed to get to this waypoint
|
||||
stepamt -= dist;
|
||||
|
||||
// We've reached the destination point,
|
||||
P_UnsetThingPosition(player->mo);
|
||||
player->mo->x = dest.x;
|
||||
player->mo->y = dest.y;
|
||||
player->mo->z = dest.z;
|
||||
P_SetThingPosition(player->mo);
|
||||
|
||||
// Find the next waypoint to head towards
|
||||
if (player->respawn.wp != NULL)
|
||||
{
|
||||
size_t nwp = K_NextRespawnWaypointIndex(player->respawn.wp);
|
||||
|
||||
if (nwp == SIZE_MAX)
|
||||
{
|
||||
player->respawn.state = RESPAWNST_DROP;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set angle, regardless of if we're done or not
|
||||
player->frameangle = R_PointToAngle2(
|
||||
player->mo->x, player->mo->y,
|
||||
dest.x, dest.y
|
||||
);
|
||||
|
||||
if ((player->respawn.distanceleft == 0 && K_GetWaypointIsSpawnpoint(player->respawn.wp) == true)
|
||||
|| (player->respawn.wp == K_GetFinishLineWaypoint()
|
||||
|| player->respawn.wp->nextwaypoints[nwp] == K_GetFinishLineWaypoint())) // Try not to allow you to pass the finish line while respawning, because it's janky
|
||||
{
|
||||
// Alright buddy, that's the end of the ride.
|
||||
player->respawn.state = RESPAWNST_DROP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->respawn.distanceleft > player->respawn.wp->nextwaypointdistances[nwp])
|
||||
{
|
||||
player->respawn.distanceleft -= player->respawn.wp->nextwaypointdistances[nwp];
|
||||
}
|
||||
else
|
||||
{
|
||||
player->respawn.distanceleft = 0;
|
||||
}
|
||||
|
||||
player->respawn.wp = player->respawn.wp->nextwaypoints[nwp];
|
||||
K_RespawnAtWaypoint(player, player->respawn.wp);
|
||||
|
||||
dest.x = player->respawn.pointx;
|
||||
dest.y = player->respawn.pointy;
|
||||
dest.z = player->respawn.pointz;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can now drop!
|
||||
player->respawn.state = RESPAWNST_DROP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
stepha = R_PointToAngle2(
|
||||
player->mo->x, player->mo->y,
|
||||
dest.x, dest.y
|
||||
);
|
||||
|
||||
stepva = R_PointToAngle2(
|
||||
0, player->mo->z,
|
||||
P_AproxDistance(player->mo->x - dest.x, player->mo->y - dest.y), dest.z
|
||||
);
|
||||
|
||||
// Move toward the respawn point
|
||||
player->frameangle = stepha;
|
||||
|
||||
step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
|
||||
step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
|
||||
step.z = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*stepamt);
|
||||
|
||||
if (stepamt > 0)
|
||||
{
|
||||
player->mo->momx = step.x;
|
||||
player->mo->momy = step.y;
|
||||
player->mo->momz = step.z;
|
||||
}
|
||||
|
||||
// NOW THEN, time for loads of dumb duplication!
|
||||
// "Emulate" the rest of the path, that way we can spawn a particle a certain distance ahead of you.
|
||||
|
||||
if (stepamt != realstepamt)
|
||||
{
|
||||
// Reset back to default
|
||||
stepamt = realstepamt;
|
||||
|
||||
step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
|
||||
step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
|
||||
step.z = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*stepamt);
|
||||
}
|
||||
|
||||
laserdist = player->respawn.distanceleft;
|
||||
laserwp = player->respawn.wp;
|
||||
laserflip = player->respawn.flip;
|
||||
|
||||
laser.x = player->mo->x + (step.x / 2);
|
||||
laser.y = player->mo->y + (step.y / 2);
|
||||
laser.z = player->mo->z + (step.z / 2);
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(
|
||||
laser.x - dest.x,
|
||||
laser.y - dest.y),
|
||||
laser.z - dest.z
|
||||
);
|
||||
fulldist = dist + (laserdist * FRACUNIT);
|
||||
|
||||
while (lasersteps > 0)
|
||||
{
|
||||
if (fulldist <= stepamt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (dist <= stepamt)
|
||||
{
|
||||
size_t lnwp;
|
||||
|
||||
laser.x = dest.x;
|
||||
laser.y = dest.y;
|
||||
laser.z = dest.z;
|
||||
|
||||
if (laserdist <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lnwp = K_NextRespawnWaypointIndex(laserwp);
|
||||
if (lnwp == SIZE_MAX)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (laserdist > laserwp->nextwaypointdistances[lnwp])
|
||||
{
|
||||
laserdist -= laserwp->nextwaypointdistances[lnwp];
|
||||
}
|
||||
else
|
||||
{
|
||||
laserdist = 0;
|
||||
}
|
||||
|
||||
laserwp = laserwp->nextwaypoints[lnwp];
|
||||
|
||||
dest.x = laserwp->mobj->x;
|
||||
dest.y = laserwp->mobj->y;
|
||||
dest.z = laserwp->mobj->z;
|
||||
laserflip = (laserwp->mobj->flags2 & MF2_OBJECTFLIP);
|
||||
|
||||
if (laserflip == true)
|
||||
{
|
||||
dest.z -= (128 * mapobjectscale) - (player->mo->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
dest.z += (128 * mapobjectscale);
|
||||
}
|
||||
|
||||
stepamt -= dist;
|
||||
|
||||
stepha = R_PointToAngle2(laser.x, laser.y, dest.x, dest.y);
|
||||
stepva = R_PointToAngle2(0, laser.z, P_AproxDistance(laser.x - dest.x, laser.y - dest.y), dest.z);
|
||||
|
||||
step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
|
||||
step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
|
||||
step.z = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*stepamt);
|
||||
}
|
||||
else if (stepamt != realstepamt)
|
||||
{
|
||||
// Reset back to default
|
||||
stepamt = realstepamt;
|
||||
|
||||
step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
|
||||
step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT));
|
||||
step.z = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*stepamt);
|
||||
}
|
||||
|
||||
if (stepamt > 0)
|
||||
{
|
||||
laser.x += step.x;
|
||||
laser.y += step.y;
|
||||
laser.z += step.z;
|
||||
}
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(
|
||||
laser.x - dest.x,
|
||||
laser.y - dest.y),
|
||||
laser.z - dest.z
|
||||
);
|
||||
fulldist = dist + (laserdist * FRACUNIT);
|
||||
|
||||
lasersteps--;
|
||||
}
|
||||
|
||||
if (lasersteps == 0) // Don't spawn them beyond the respawn point.
|
||||
{
|
||||
mobj_t *lasermo = P_SpawnMobj(laser.x, laser.y, laser.z + (player->mo->height / 2), MT_DEZLASER);
|
||||
|
||||
if (lasermo && !P_MobjWasRemoved(lasermo))
|
||||
{
|
||||
P_SetMobjState(lasermo, S_DEZLASER_TRAIL1);
|
||||
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
lasermo->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
|
||||
P_SetTarget(&lasermo->target, player->mo);
|
||||
|
||||
lasermo->angle = stepha + ANGLE_90;
|
||||
P_SetScale(lasermo, (lasermo->destscale = player->mo->scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_HandleDropDash(player_t *player)
|
||||
|
||||
Handles the visuals for the waiting period,
|
||||
before you're allowed to Drop Dash.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to preform for.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_DropDashWait(player_t *player)
|
||||
{
|
||||
if (player->powers[pw_nocontrol] == 0)
|
||||
player->respawn.timer--;
|
||||
|
||||
if (leveltime % 8 == 0)
|
||||
{
|
||||
const UINT8 ns = 8;
|
||||
const angle_t sidediff = FixedAngle((360 / ns) * FRACUNIT);
|
||||
UINT8 i;
|
||||
|
||||
if (!mapreset)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_s3kcas);
|
||||
}
|
||||
|
||||
for (i = 0; i < ns; i++)
|
||||
{
|
||||
const angle_t newangle = sidediff * i;
|
||||
vertex_t spawn;
|
||||
mobj_t *laser;
|
||||
|
||||
spawn.x = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31 * player->mo->scale);
|
||||
spawn.y = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31 * player->mo->scale);
|
||||
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
spawn.z = player->mo->z + player->mo->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
spawn.z = player->mo->z;
|
||||
}
|
||||
|
||||
laser = P_SpawnMobj(spawn.x, spawn.y, spawn.z, MT_DEZLASER);
|
||||
|
||||
if (laser && !P_MobjWasRemoved(laser))
|
||||
{
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
laser->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
|
||||
P_SetTarget(&laser->target, player->mo);
|
||||
|
||||
laser->angle = newangle + ANGLE_90;
|
||||
laser->momz = (8 * player->mo->scale) * P_MobjFlip(player->mo);
|
||||
P_SetScale(laser, (laser->destscale = player->mo->scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_HandleDropDash(player_t *player)
|
||||
|
||||
Handles input for the Drop Dash maneuver.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to preform for.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_HandleDropDash(player_t *player)
|
||||
{
|
||||
ticcmd_t *cmd = &player->cmd;
|
||||
|
||||
if (player->kartstuff[k_growshrinktimer] < 0)
|
||||
{
|
||||
player->mo->scalespeed = mapobjectscale/TICRATE;
|
||||
player->mo->destscale = (6*mapobjectscale)/8;
|
||||
|
||||
if (cv_kartdebugshrink.value && !modeattacking && !player->bot)
|
||||
{
|
||||
player->mo->destscale = (6*player->mo->destscale)/8;
|
||||
}
|
||||
}
|
||||
|
||||
if (!P_IsObjectOnGround(player->mo))
|
||||
{
|
||||
if (mapreset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player->powers[pw_flashing] = K_GetKartFlashing(player);
|
||||
|
||||
// The old behavior was stupid and prone to accidental usage.
|
||||
// Let's rip off Mania instead, and turn this into a Drop Dash!
|
||||
|
||||
if ((cmd->buttons & BT_ACCELERATE) && !player->kartstuff[k_spinouttimer]) // Since we're letting players spin out on respawn, don't let them charge a dropdash in this state. (It wouldn't work anyway)
|
||||
{
|
||||
player->respawn.dropdash++;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->respawn.dropdash = 0;
|
||||
}
|
||||
|
||||
if (player->respawn.dropdash == TICRATE/4)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_ddash);
|
||||
}
|
||||
|
||||
if ((player->respawn.dropdash >= TICRATE/4) && (player->respawn.dropdash & 1))
|
||||
{
|
||||
player->mo->colorized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->mo->colorized = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((cmd->buttons & BT_ACCELERATE) && (player->respawn.dropdash >= TICRATE/4))
|
||||
{
|
||||
S_StartSound(player->mo, sfx_s23c);
|
||||
player->kartstuff[k_startboost] = 50;
|
||||
K_SpawnDashDustRelease(player);
|
||||
}
|
||||
|
||||
player->mo->colorized = false;
|
||||
player->respawn.dropdash = 0;
|
||||
|
||||
//P_PlayRinglossSound(player->mo);
|
||||
P_PlayerRingBurst(player, 3);
|
||||
|
||||
if (G_BattleGametype())
|
||||
{
|
||||
if (player->kartstuff[k_bumper] > 0)
|
||||
{
|
||||
if (player->kartstuff[k_bumper] == 1)
|
||||
{
|
||||
mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!!
|
||||
P_SetTarget(&karmahitbox->target, player->mo);
|
||||
karmahitbox->destscale = player->mo->scale;
|
||||
P_SetScale(karmahitbox, player->mo->scale);
|
||||
CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]);
|
||||
}
|
||||
player->kartstuff[k_bumper]--;
|
||||
if (K_IsPlayerWanted(player))
|
||||
K_CalculateBattleWanted();
|
||||
}
|
||||
|
||||
if (!player->kartstuff[k_bumper])
|
||||
{
|
||||
player->kartstuff[k_comebacktimer] = comebacktime;
|
||||
if (player->kartstuff[k_comebackmode] == 2)
|
||||
{
|
||||
mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE);
|
||||
S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound);
|
||||
player->kartstuff[k_comebackmode] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
K_CheckBumpers();
|
||||
}
|
||||
|
||||
player->respawn.state = RESPAWNST_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RespawnChecker(player_t *player)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_RespawnChecker(player_t *player)
|
||||
{
|
||||
if (player->respawn.state == RESPAWNST_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->spectator)
|
||||
{
|
||||
player->respawn.state = RESPAWNST_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (player->respawn.state)
|
||||
{
|
||||
case RESPAWNST_MOVE:
|
||||
player->mo->momx = player->mo->momy = player->mo->momz = 0;
|
||||
K_MovePlayerToRespawnPoint(player);
|
||||
return;
|
||||
case RESPAWNST_DROP:
|
||||
player->mo->momx = player->mo->momy = 0;
|
||||
if (player->respawn.timer > 0)
|
||||
{
|
||||
player->mo->momz = 0;
|
||||
K_DropDashWait(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
K_HandleDropDash(player);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
player->respawn.state = RESPAWNST_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
71
src/k_respawn.h
Normal file
71
src/k_respawn.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2020 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_respawn.h
|
||||
/// \brief Respawning logic
|
||||
|
||||
#ifndef __K_RESPAWN__
|
||||
#define __K_RESPAWN__
|
||||
|
||||
#include "k_waypoint.h"
|
||||
#include "d_player.h"
|
||||
|
||||
#define RESPAWN_DIST 1024
|
||||
#define RESPAWN_TIME 48
|
||||
#define RESPAWNST_NONE 0
|
||||
#define RESPAWNST_MOVE 1
|
||||
#define RESPAWNST_DROP 2
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_RespawnOffset(player_t *player, boolean flip);
|
||||
|
||||
Updates the player's flip flags, and returns a
|
||||
Z offset for respawning.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to preform this for.
|
||||
flip - false for normal, true for gravity flip.
|
||||
|
||||
Return:-
|
||||
Z position offset.
|
||||
--------------------------------------------------*/
|
||||
|
||||
fixed_t K_RespawnOffset(player_t *player, boolean flip);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_DoIngameRespawn(player_t *player);
|
||||
|
||||
Starts the respawning animation for the specified player,
|
||||
updating their respawn variables in preparation.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to preform this for.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_DoIngameRespawn(player_t *player);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RespawnChecker(player_t *player);
|
||||
|
||||
Thinker for the respawning animation.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to preform this for.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_RespawnChecker(player_t *player);
|
||||
|
||||
#endif
|
||||
|
|
@ -474,7 +474,7 @@ static void K_DebugWaypointsSpawnLine(waypoint_t *const waypoint1, waypoint_t *c
|
|||
spawnedmobj->state->tics = 1;
|
||||
spawnedmobj->frame = spawnedmobj->frame & ~FF_TRANSMASK;
|
||||
spawnedmobj->color = linkcolours[linkcolour];
|
||||
spawnedmobj->scale = FixedMul(FRACUNIT/4, FixedDiv((15 - ((leveltime + n) % 16))*FRACUNIT, 15*FRACUNIT));
|
||||
spawnedmobj->scale = FixedMul(spawnedmobj->scale, FixedMul(FRACUNIT/4, FixedDiv((15 - ((leveltime + n) % 16))*FRACUNIT, 15*FRACUNIT)));
|
||||
}
|
||||
|
||||
x += stepx;
|
||||
|
|
@ -483,6 +483,48 @@ static void K_DebugWaypointsSpawnLine(waypoint_t *const waypoint1, waypoint_t *c
|
|||
} while (n--);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_DebugWaypointDrawRadius(waypoint_t *const waypoint)
|
||||
|
||||
Draw a debugging circle to represent a waypoint's radius
|
||||
|
||||
Input Arguments:-
|
||||
waypoint - A waypoint to draw the radius of
|
||||
--------------------------------------------------*/
|
||||
static void K_DebugWaypointDrawRadius(waypoint_t *const waypoint)
|
||||
{
|
||||
mobj_t *radiusOrb;
|
||||
mobj_t *waypointmobj;
|
||||
const INT32 numRadiusMobjs = 64;
|
||||
INT32 i = 0;
|
||||
angle_t spawnAngle = 0U;
|
||||
fixed_t spawnX= 0;
|
||||
fixed_t spawnY= 0;
|
||||
fixed_t spawnZ= 0;
|
||||
|
||||
I_Assert(waypoint != NULL);
|
||||
I_Assert(waypoint->mobj != NULL);
|
||||
|
||||
waypointmobj = waypoint->mobj;
|
||||
|
||||
for (i = 0; i < numRadiusMobjs; i++)
|
||||
{
|
||||
spawnAngle = (ANGLE_MAX / numRadiusMobjs) * i;
|
||||
|
||||
spawnZ = waypointmobj->z;
|
||||
spawnX = waypointmobj->x + P_ReturnThrustX(waypointmobj, spawnAngle, waypointmobj->radius);
|
||||
spawnY = waypointmobj->y + P_ReturnThrustY(waypointmobj, spawnAngle, waypointmobj->radius);
|
||||
|
||||
radiusOrb = P_SpawnMobj(spawnX, spawnY, spawnZ, MT_SPARK);
|
||||
P_SetMobjState(radiusOrb, S_THOK);
|
||||
radiusOrb->state->nextstate = S_NULL;
|
||||
radiusOrb->state->tics = 1;
|
||||
radiusOrb->frame = radiusOrb->frame & ~FF_TRANSMASK;
|
||||
radiusOrb->color = SKINCOLOR_PURPLE;
|
||||
radiusOrb->scale = radiusOrb->scale / 4;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_DebugWaypointsVisualise(void)
|
||||
|
||||
|
|
@ -523,15 +565,20 @@ void K_DebugWaypointsVisualise(void)
|
|||
{
|
||||
if (waypoint->numnextwaypoints == 0 && waypoint->numprevwaypoints == 0)
|
||||
{
|
||||
P_SetMobjState(debugmobj, S_EGOORB);
|
||||
debugmobj->color = SKINCOLOR_RED;
|
||||
debugmobj->colorized = true;
|
||||
}
|
||||
else if (waypoint->numnextwaypoints == 0 || waypoint->numprevwaypoints == 0)
|
||||
{
|
||||
P_SetMobjState(debugmobj, S_EGOORB);
|
||||
debugmobj->color = SKINCOLOR_YELLOW;
|
||||
debugmobj->colorized = true;
|
||||
}
|
||||
else if (waypoint == players[displayplayers[0]].nextwaypoint)
|
||||
{
|
||||
debugmobj->color = SKINCOLOR_GREEN;
|
||||
K_DebugWaypointDrawRadius(waypoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "k_kart.h" // SRB2Kart
|
||||
#include "k_battle.h"
|
||||
#include "k_color.h"
|
||||
#include "k_hud.h"
|
||||
#include "d_netcmd.h" // IsPlayerAdmin
|
||||
#include "m_menu.h" // Player Setup menu color stuff
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,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"
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ enum mobj_e {
|
|||
mobj_flags,
|
||||
mobj_flags2,
|
||||
mobj_eflags,
|
||||
mobj_drawflags,
|
||||
mobj_skin,
|
||||
mobj_color,
|
||||
mobj_bnext,
|
||||
|
|
@ -129,6 +130,7 @@ static const char *const mobj_opt[] = {
|
|||
"flags",
|
||||
"flags2",
|
||||
"eflags",
|
||||
"drawflags",
|
||||
"skin",
|
||||
"color",
|
||||
"bnext",
|
||||
|
|
@ -285,6 +287,9 @@ static int mobj_get(lua_State *L)
|
|||
case mobj_eflags:
|
||||
lua_pushinteger(L, mo->eflags);
|
||||
break;
|
||||
case mobj_drawflags:
|
||||
lua_pushinteger(L, mo->drawflags);
|
||||
break;
|
||||
case mobj_skin: // skin name or nil, not struct
|
||||
if (!mo->skin)
|
||||
return 0;
|
||||
|
|
@ -599,7 +604,10 @@ static int mobj_set(lua_State *L)
|
|||
mo->flags2 = (UINT32)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case mobj_eflags:
|
||||
mo->eflags = (UINT32)luaL_checkinteger(L, 3);
|
||||
mo->eflags = (UINT16)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case mobj_drawflags:
|
||||
mo->drawflags = (UINT16)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case mobj_skin: // set skin by name
|
||||
{
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ static int lib_iterateDisplayplayers(lua_State *L)
|
|||
|
||||
for (i++; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[displayplayers[i]] || i > splitscreen)
|
||||
if (i > splitscreen || !playeringame[displayplayers[i]])
|
||||
return 0; // Stop! There are no more players for us to go through. There will never be a player gap in displayplayers.
|
||||
|
||||
if (!players[displayplayers[i]].mo)
|
||||
|
|
@ -139,6 +139,8 @@ static int lib_getDisplayplayers(lua_State *L)
|
|||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
if (i < 0 || i >= MAXSPLITSCREENPLAYERS)
|
||||
return luaL_error(L, "displayplayers[] index %d out of range (0 - %d)", i, MAXSPLITSCREENPLAYERS-1);
|
||||
if (i > splitscreen)
|
||||
return 0;
|
||||
if (!playeringame[displayplayers[i]])
|
||||
return 0;
|
||||
if (!players[displayplayers[i]].mo)
|
||||
|
|
@ -217,6 +219,8 @@ static int player_get(lua_State *L)
|
|||
LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF);
|
||||
else if (fastcmp(field,"frameangle"))
|
||||
lua_pushangle(L, plr->frameangle);
|
||||
else if (fastcmp(field,"airtime"))
|
||||
lua_pushinteger(L, plr->airtime);
|
||||
else if (fastcmp(field,"pflags"))
|
||||
lua_pushinteger(L, plr->pflags);
|
||||
else if (fastcmp(field,"panim"))
|
||||
|
|
@ -238,6 +242,14 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->kartspeed);
|
||||
else if (fastcmp(field,"kartweight"))
|
||||
lua_pushinteger(L, plr->kartweight);
|
||||
else if (fastcmp(field,"followerskin"))
|
||||
lua_pushinteger(L, plr->followerskin);
|
||||
else if (fastcmp(field,"followerready"))
|
||||
lua_pushboolean(L, plr->followerready);
|
||||
else if (fastcmp(field,"followercolor"))
|
||||
lua_pushinteger(L, plr->followercolor);
|
||||
else if (fastcmp(field,"follower"))
|
||||
LUA_PushUserdata(L, plr->follower, META_MOBJ);
|
||||
//
|
||||
else if (fastcmp(field,"charflags"))
|
||||
lua_pushinteger(L, plr->charflags);
|
||||
|
|
@ -247,6 +259,8 @@ static int player_get(lua_State *L)
|
|||
LUA_PushUserdata(L, plr->followmobj, META_MOBJ);
|
||||
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"))
|
||||
|
|
@ -299,20 +313,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->weapondelay);
|
||||
else if (fastcmp(field,"tossdelay"))
|
||||
lua_pushinteger(L, plr->tossdelay);
|
||||
else if (fastcmp(field,"starpostx"))
|
||||
lua_pushinteger(L, plr->starpostx);
|
||||
else if (fastcmp(field,"starposty"))
|
||||
lua_pushinteger(L, plr->starposty);
|
||||
else if (fastcmp(field,"starpostz"))
|
||||
lua_pushinteger(L, plr->starpostz);
|
||||
else if (fastcmp(field,"starpostnum"))
|
||||
lua_pushinteger(L, plr->starpostnum);
|
||||
else if (fastcmp(field,"starposttime"))
|
||||
lua_pushinteger(L, plr->starposttime);
|
||||
else if (fastcmp(field,"starpostangle"))
|
||||
lua_pushangle(L, plr->starpostangle);
|
||||
else if (fastcmp(field,"starpostscale"))
|
||||
lua_pushfixed(L, plr->starpostscale);
|
||||
else if (fastcmp(field,"angle_pos"))
|
||||
lua_pushangle(L, plr->angle_pos);
|
||||
else if (fastcmp(field,"old_angle_pos"))
|
||||
|
|
@ -405,6 +407,7 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->awayviewtics);
|
||||
else if (fastcmp(field,"awayviewaiming"))
|
||||
lua_pushangle(L, plr->awayviewaiming);
|
||||
|
||||
else if (fastcmp(field,"spectator"))
|
||||
lua_pushboolean(L, plr->spectator);
|
||||
else if (fastcmp(field,"bot"))
|
||||
|
|
@ -514,10 +517,20 @@ static int player_set(lua_State *L)
|
|||
return NOSET;
|
||||
else if (fastcmp(field,"frameangle"))
|
||||
plr->frameangle = luaL_checkangle(L, 3);
|
||||
else if (fastcmp(field,"airtime"))
|
||||
plr->airtime = (tic_t)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"kartspeed"))
|
||||
plr->kartspeed = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"kartweight"))
|
||||
plr->kartweight = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"followerskin"))
|
||||
plr->followerskin = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"followercolor"))
|
||||
plr->followercolor = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"followerready"))
|
||||
plr->followerready = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"follower")) // it's probably best we don't allow the follower mobj to change.
|
||||
return NOSET;
|
||||
//
|
||||
else if (fastcmp(field,"charflags"))
|
||||
plr->charflags = (UINT32)luaL_checkinteger(L, 3);
|
||||
|
|
@ -532,6 +545,8 @@ static int player_set(lua_State *L)
|
|||
}
|
||||
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"))
|
||||
|
|
@ -584,20 +599,8 @@ static int player_set(lua_State *L)
|
|||
plr->weapondelay = (INT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"tossdelay"))
|
||||
plr->tossdelay = (INT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"starpostx"))
|
||||
plr->starpostx = (INT16)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"starposty"))
|
||||
plr->starposty = (INT16)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"starpostz"))
|
||||
plr->starpostz = (INT16)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"starpostnum"))
|
||||
plr->starpostnum = (INT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"starposttime"))
|
||||
plr->starposttime = (tic_t)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"starpostangle"))
|
||||
plr->starpostangle = luaL_checkangle(L, 3);
|
||||
else if (fastcmp(field,"starpostscale"))
|
||||
plr->starpostscale = luaL_checkfixed(L, 3);
|
||||
else if (fastcmp(field,"angle_pos"))
|
||||
plr->angle_pos = luaL_checkangle(L, 3);
|
||||
else if (fastcmp(field,"old_angle_pos"))
|
||||
|
|
@ -843,8 +846,6 @@ static int ticcmd_get(lua_State *L)
|
|||
|
||||
if (fastcmp(field,"forwardmove"))
|
||||
lua_pushinteger(L, cmd->forwardmove);
|
||||
else if (fastcmp(field,"sidemove"))
|
||||
lua_pushinteger(L, cmd->sidemove);
|
||||
else if (fastcmp(field,"angleturn"))
|
||||
lua_pushinteger(L, cmd->angleturn);
|
||||
else if (fastcmp(field,"aiming"))
|
||||
|
|
@ -873,8 +874,6 @@ static int ticcmd_set(lua_State *L)
|
|||
|
||||
if (fastcmp(field,"forwardmove"))
|
||||
cmd->forwardmove = (SINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"sidemove"))
|
||||
cmd->sidemove = (SINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"angleturn"))
|
||||
cmd->angleturn = (INT16)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"aiming"))
|
||||
|
|
|
|||
|
|
@ -833,19 +833,11 @@ void Command_Savecheckpoint_f(void)
|
|||
REQUIRE_INLEVEL;
|
||||
REQUIRE_SINGLEPLAYER;
|
||||
|
||||
players[consoleplayer].starposttime = players[consoleplayer].realtime;
|
||||
players[consoleplayer].starpostx = players[consoleplayer].mo->x>>FRACBITS;
|
||||
players[consoleplayer].starposty = players[consoleplayer].mo->y>>FRACBITS;
|
||||
players[consoleplayer].starpostz = players[consoleplayer].mo->floorz>>FRACBITS;
|
||||
players[consoleplayer].starpostangle = players[consoleplayer].mo->angle;
|
||||
players[consoleplayer].starpostscale = players[consoleplayer].mo->destscale;
|
||||
if (players[consoleplayer].mo->flags2 & MF2_OBJECTFLIP)
|
||||
{
|
||||
players[consoleplayer].starpostscale *= -1;
|
||||
players[consoleplayer].starpostz += players[consoleplayer].mo->height;
|
||||
}
|
||||
players[consoleplayer].respawn.pointx = players[consoleplayer].mo->x;
|
||||
players[consoleplayer].respawn.pointy = players[consoleplayer].mo->y;
|
||||
players[consoleplayer].respawn.pointz = players[consoleplayer].mo->floorz;
|
||||
|
||||
CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].starpostx, players[consoleplayer].starposty, players[consoleplayer].starpostz);
|
||||
CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].respawn.pointx, players[consoleplayer].respawn.pointy, players[consoleplayer].respawn.pointz);
|
||||
}
|
||||
|
||||
// Like M_GetAllEmeralds() but for console devmode junkies.
|
||||
|
|
|
|||
231
src/m_menu.c
231
src/m_menu.c
|
|
@ -32,6 +32,7 @@
|
|||
#include "sounds.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_system.h"
|
||||
#include "i_threads.h"
|
||||
|
||||
// Addfile
|
||||
#include "filesrch.h"
|
||||
|
|
@ -126,6 +127,12 @@ typedef enum
|
|||
NUM_QUITMESSAGES
|
||||
} text_enum;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
I_mutex m_menu_mutex;
|
||||
#endif
|
||||
|
||||
M_waiting_mode_t m_waiting_mode = M_NOT_WAITING;
|
||||
|
||||
const char *quitmsg[NUM_QUITMESSAGES];
|
||||
|
||||
// Stuff for customizing the player select screen Tails 09-22-2003
|
||||
|
|
@ -1073,7 +1080,7 @@ enum
|
|||
FIRSTSERVERLINE
|
||||
};
|
||||
|
||||
static menuitem_t MP_RoomMenu[] =
|
||||
menuitem_t MP_RoomMenu[] =
|
||||
{
|
||||
{IT_STRING | IT_CALL, NULL, "<Offline Mode>", M_ChooseRoom, 9},
|
||||
{IT_DISABLED, NULL, "", M_ChooseRoom, 18},
|
||||
|
|
@ -2893,7 +2900,6 @@ boolean M_Responder(event_t *ev)
|
|||
//make sure the game doesn't still think we're in a netgame.
|
||||
if (!Playing() && netgame && multiplayer)
|
||||
{
|
||||
MSCloseUDPSocket(); // Clean up so we can re-open the connection later.
|
||||
netgame = false;
|
||||
multiplayer = false;
|
||||
}
|
||||
|
|
@ -3305,6 +3311,30 @@ void M_SetupNextMenu(menu_t *menudef)
|
|||
{
|
||||
INT16 i;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
if (currentMenu == &MP_RoomDef || currentMenu == &MP_ConnectDef)
|
||||
{
|
||||
I_lock_mutex(&ms_QueryId_mutex);
|
||||
{
|
||||
ms_QueryId++;
|
||||
}
|
||||
I_unlock_mutex(ms_QueryId_mutex);
|
||||
}
|
||||
|
||||
if (currentMenu == &MP_ConnectDef)
|
||||
{
|
||||
I_lock_mutex(&ms_ServerList_mutex);
|
||||
{
|
||||
if (ms_ServerList)
|
||||
{
|
||||
free(ms_ServerList);
|
||||
ms_ServerList = NULL;
|
||||
}
|
||||
}
|
||||
I_unlock_mutex(ms_ServerList_mutex);
|
||||
}
|
||||
#endif/*HAVE_THREADS*/
|
||||
|
||||
if (currentMenu->quitroutine)
|
||||
{
|
||||
// If you're going from a menu to itself, why are you running the quitroutine? You're not quitting it! -SH
|
||||
|
|
@ -3364,6 +3394,19 @@ void M_Ticker(void)
|
|||
if (--vidm_testingmode == 0)
|
||||
setmodeneeded = vidm_previousmode + 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&ms_ServerList_mutex);
|
||||
{
|
||||
if (ms_ServerList)
|
||||
{
|
||||
CL_QueryServerList(ms_ServerList);
|
||||
free(ms_ServerList);
|
||||
ms_ServerList = NULL;
|
||||
}
|
||||
}
|
||||
I_unlock_mutex(ms_ServerList_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -4844,7 +4887,7 @@ static boolean M_AddonsRefresh(void)
|
|||
else if (majormods && !prevmajormods)
|
||||
{
|
||||
S_StartSound(NULL, sfx_s221);
|
||||
message = va("%c%s\x80\nGameplay has now been modified.\nIf you wish to play Record Attack mode, restart the game to clear existing addons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
message = va("%c%s\x80\nYou've loaded a gameplay-modifying addon.\n\nRecord Attack has been disabled, but you\ncan still play alone in local Multiplayer.\n\nIf you wish to play Record Attack mode, restart the game to disable loaded addons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
prevmajormods = majormods;
|
||||
}
|
||||
|
||||
|
|
@ -8455,22 +8498,65 @@ static INT32 menuRoomIndex = 0;
|
|||
|
||||
static void M_DrawRoomMenu(void)
|
||||
{
|
||||
static int frame = -12;
|
||||
int dot_frame;
|
||||
char text[4];
|
||||
|
||||
const char *rmotd;
|
||||
const char *waiting_message;
|
||||
|
||||
int dots;
|
||||
|
||||
if (m_waiting_mode)
|
||||
{
|
||||
dot_frame = frame / 4;
|
||||
dots = dot_frame + 3;
|
||||
|
||||
strcpy(text, " ");
|
||||
|
||||
if (dots > 0)
|
||||
{
|
||||
if (dot_frame < 0)
|
||||
dot_frame = 0;
|
||||
|
||||
strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame));
|
||||
}
|
||||
|
||||
if (++frame == 12)
|
||||
frame = -12;
|
||||
|
||||
currentMenu->menuitems[0].text = text;
|
||||
}
|
||||
|
||||
// use generic drawer for cursor, items and title
|
||||
M_DrawGenericMenu();
|
||||
|
||||
V_DrawString(currentMenu->x - 16, currentMenu->y, highlightflags, M_GetText("Select a room"));
|
||||
|
||||
M_DrawTextBox(144, 24, 20, 20);
|
||||
if (m_waiting_mode == M_NOT_WAITING)
|
||||
{
|
||||
M_DrawTextBox(144, 24, 20, 20);
|
||||
|
||||
if (itemOn == 0)
|
||||
rmotd = M_GetText("Don't connect to the Master Server.");
|
||||
else
|
||||
rmotd = room_list[itemOn-1].motd;
|
||||
if (itemOn == 0)
|
||||
rmotd = M_GetText("Don't connect to the Master Server.");
|
||||
else
|
||||
rmotd = room_list[itemOn-1].motd;
|
||||
|
||||
rmotd = V_WordWrap(0, 20*8, 0, rmotd);
|
||||
V_DrawString(144+8, 32, V_ALLOWLOWERCASE|V_RETURN8, rmotd);
|
||||
rmotd = V_WordWrap(0, 20*8, 0, rmotd);
|
||||
V_DrawString(144+8, 32, V_ALLOWLOWERCASE|V_RETURN8, rmotd);
|
||||
}
|
||||
|
||||
if (m_waiting_mode)
|
||||
{
|
||||
// Display a little "please wait" message.
|
||||
M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3);
|
||||
if (m_waiting_mode == M_WAITING_VERSION)
|
||||
waiting_message = "Checking for updates...";
|
||||
else
|
||||
waiting_message = "Fetching room info...";
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, waiting_message);
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait.");
|
||||
}
|
||||
}
|
||||
|
||||
static void M_DrawConnectMenu(void)
|
||||
|
|
@ -8550,6 +8636,14 @@ static void M_DrawConnectMenu(void)
|
|||
localservercount = serverlistcount;
|
||||
|
||||
M_DrawGenericMenu();
|
||||
|
||||
if (m_waiting_mode)
|
||||
{
|
||||
// Display a little "please wait" message.
|
||||
M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3);
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Searching for servers...");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait.");
|
||||
}
|
||||
}
|
||||
|
||||
static boolean M_CancelConnect(void)
|
||||
|
|
@ -8631,10 +8725,10 @@ void M_SortServerList(void)
|
|||
|
||||
#ifndef NONET
|
||||
#ifdef UPDATE_ALERT
|
||||
static boolean M_CheckMODVersion(void)
|
||||
static boolean M_CheckMODVersion(int id)
|
||||
{
|
||||
char updatestring[500];
|
||||
const char *updatecheck = GetMODVersion();
|
||||
const char *updatecheck = GetMODVersion(id);
|
||||
if(updatecheck)
|
||||
{
|
||||
sprintf(updatestring, UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck);
|
||||
|
|
@ -8643,7 +8737,62 @@ static boolean M_CheckMODVersion(void)
|
|||
} else
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static void
|
||||
Check_new_version_thread (int *id)
|
||||
{
|
||||
int hosting;
|
||||
int okay;
|
||||
|
||||
okay = 0;
|
||||
|
||||
if (M_CheckMODVersion(*id))
|
||||
{
|
||||
I_lock_mutex(&ms_QueryId_mutex);
|
||||
{
|
||||
okay = ( *id == ms_QueryId );
|
||||
}
|
||||
I_unlock_mutex(ms_QueryId_mutex);
|
||||
|
||||
if (okay)
|
||||
{
|
||||
I_lock_mutex(&m_menu_mutex);
|
||||
{
|
||||
m_waiting_mode = M_WAITING_ROOMS;
|
||||
hosting = ( currentMenu->prevMenu == &MP_ServerDef );
|
||||
}
|
||||
I_unlock_mutex(m_menu_mutex);
|
||||
|
||||
GetRoomsList(hosting, *id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
I_lock_mutex(&ms_QueryId_mutex);
|
||||
{
|
||||
okay = ( *id == ms_QueryId );
|
||||
}
|
||||
I_unlock_mutex(ms_QueryId_mutex);
|
||||
}
|
||||
|
||||
if (okay)
|
||||
{
|
||||
I_lock_mutex(&m_menu_mutex);
|
||||
{
|
||||
if (m_waiting_mode)
|
||||
{
|
||||
m_waiting_mode = M_NOT_WAITING;
|
||||
MP_RoomMenu[0].text = "<Offline Mode>";
|
||||
}
|
||||
}
|
||||
I_unlock_mutex(m_menu_mutex);
|
||||
}
|
||||
|
||||
free(id);
|
||||
}
|
||||
#endif/*HAVE_THREADS*/
|
||||
#endif/*UPDATE_ALERT*/
|
||||
|
||||
static void M_ConnectMenu(INT32 choice)
|
||||
{
|
||||
|
|
@ -8672,18 +8821,21 @@ static void M_ConnectMenuModChecks(INT32 choice)
|
|||
|
||||
if (modifiedgame)
|
||||
{
|
||||
M_StartMessage(M_GetText("Addons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing addons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER);
|
||||
M_StartMessage(M_GetText("You have addons loaded.\nYou won't be able to join netgames!\n\nTo play online, restart the game\nand don't load any addons.\nSRB2Kart will automatically add\neverything you need when you join.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER);
|
||||
return;
|
||||
}
|
||||
|
||||
M_ConnectMenu(-1);
|
||||
}
|
||||
|
||||
static UINT32 roomIds[NUM_LIST_ROOMS];
|
||||
UINT32 roomIds[NUM_LIST_ROOMS];
|
||||
|
||||
static void M_RoomMenu(INT32 choice)
|
||||
{
|
||||
INT32 i;
|
||||
#ifdef HAVE_THREADS
|
||||
int *id;
|
||||
#endif
|
||||
|
||||
(void)choice;
|
||||
|
||||
|
|
@ -8696,34 +8848,47 @@ static void M_RoomMenu(INT32 choice)
|
|||
if (rendermode == render_soft)
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
|
||||
if (GetRoomsList(currentMenu == &MP_ServerDef) < 0)
|
||||
return;
|
||||
|
||||
#ifdef UPDATE_ALERT
|
||||
if (!M_CheckMODVersion())
|
||||
return;
|
||||
#endif
|
||||
|
||||
for (i = 1; i < NUM_LIST_ROOMS+1; ++i)
|
||||
MP_RoomMenu[i].status = IT_DISABLED;
|
||||
memset(roomIds, 0, sizeof(roomIds));
|
||||
|
||||
for (i = 0; room_list[i].header.buffer[0]; i++)
|
||||
{
|
||||
if(*room_list[i].name != '\0')
|
||||
{
|
||||
MP_RoomMenu[i+1].text = room_list[i].name;
|
||||
roomIds[i] = room_list[i].id;
|
||||
MP_RoomMenu[i+1].status = IT_STRING|IT_CALL;
|
||||
}
|
||||
}
|
||||
|
||||
MP_RoomDef.prevMenu = currentMenu;
|
||||
M_SetupNextMenu(&MP_RoomDef);
|
||||
|
||||
#ifdef UPDATE_ALERT
|
||||
#ifdef HAVE_THREADS
|
||||
m_waiting_mode = M_WAITING_VERSION;
|
||||
MP_RoomMenu[0].text = "";
|
||||
|
||||
id = malloc(sizeof *id);
|
||||
|
||||
I_lock_mutex(&ms_QueryId_mutex);
|
||||
{
|
||||
*id = ms_QueryId;
|
||||
}
|
||||
I_unlock_mutex(ms_QueryId_mutex);
|
||||
|
||||
I_spawn_thread("check-new-version",
|
||||
(I_thread_fn)Check_new_version_thread, id);
|
||||
#else/*HAVE_THREADS*/
|
||||
if (M_CheckMODVersion(0))
|
||||
{
|
||||
GetRoomsList(currentMenu->prevMenu == &MP_ServerDef, 0);
|
||||
}
|
||||
#endif/*HAVE_THREADS*/
|
||||
#endif/*UPDATE_ALERT*/
|
||||
}
|
||||
|
||||
static void M_ChooseRoom(INT32 choice)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&ms_QueryId_mutex);
|
||||
{
|
||||
ms_QueryId++;
|
||||
}
|
||||
I_unlock_mutex(ms_QueryId_mutex);
|
||||
#endif
|
||||
|
||||
if (choice == 0)
|
||||
ms_RoomId = -1;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include "f_finale.h" // for ttmode_enum
|
||||
#include "i_threads.h"
|
||||
#include "mserv.h"
|
||||
#include "r_things.h" // for SKINNAMESIZE
|
||||
#include "r_skins.h" // for SKINNAMESIZE
|
||||
|
||||
// Compatibility with old-style named NiGHTS replay files.
|
||||
#define OLDNREPLAYNAME
|
||||
|
|
@ -339,6 +339,9 @@ typedef struct menuitem_s
|
|||
extern menuitem_t MP_RoomMenu[];
|
||||
extern UINT32 roomIds[NUM_LIST_ROOMS];
|
||||
|
||||
extern menuitem_t MP_RoomMenu[];
|
||||
extern UINT32 roomIds[NUM_LIST_ROOMS];
|
||||
|
||||
typedef struct menu_s
|
||||
{
|
||||
UINT32 menuid; // ID to encode menu type and hierarchy
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_waypoint.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_respawn.h"
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
|
@ -943,10 +944,10 @@ void A_Look(mobj_t *actor)
|
|||
if (LUA_CallAction("A_Look", actor))
|
||||
return;
|
||||
|
||||
if (!P_LookForPlayers(actor, locvar1 & 65535, false , FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale)))
|
||||
if (leveltime < starttime) // SRB2kart - no looking before race starts
|
||||
return;
|
||||
|
||||
if (leveltime < starttime) // SRB2kart - no looking before race starts
|
||||
if (!P_LookForPlayers(actor, locvar1 & 65535, false , FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale)))
|
||||
return;
|
||||
|
||||
// go into chase state
|
||||
|
|
@ -4478,10 +4479,10 @@ void A_BubbleSpawn(mobj_t *actor)
|
|||
if (!(actor->eflags & MFE_UNDERWATER))
|
||||
{
|
||||
// Don't draw or spawn bubbles above water
|
||||
actor->flags2 |= MF2_DONTDRAW;
|
||||
actor->drawflags |= MFD_DONTDRAW;
|
||||
return;
|
||||
}
|
||||
actor->flags2 &= ~MF2_DONTDRAW;
|
||||
actor->drawflags &= ~MFD_DONTDRAW;
|
||||
|
||||
if (!(actor->flags2 & MF2_AMBUSH))
|
||||
{
|
||||
|
|
@ -4611,9 +4612,9 @@ void A_BubbleCheck(mobj_t *actor)
|
|||
return;
|
||||
|
||||
if (actor->eflags & MFE_UNDERWATER)
|
||||
actor->flags2 &= ~MF2_DONTDRAW; // underwater so draw
|
||||
actor->drawflags &= ~MFD_DONTDRAW; // underwater so draw
|
||||
else
|
||||
actor->flags2 |= MF2_DONTDRAW; // above water so don't draw
|
||||
actor->drawflags |= MFD_DONTDRAW; // above water so don't draw
|
||||
}
|
||||
|
||||
// Function: A_AttractChase
|
||||
|
|
@ -4716,9 +4717,9 @@ void A_AttractChase(mobj_t *actor)
|
|||
|
||||
// Rings flicker before disappearing
|
||||
if (actor->fuse && actor->fuse < 5*TICRATE && (leveltime & 1))
|
||||
actor->flags2 |= MF2_DONTDRAW;
|
||||
actor->drawflags |= MFD_DONTDRAW;
|
||||
else
|
||||
actor->flags2 &= ~MF2_DONTDRAW;
|
||||
actor->drawflags &= ~MFD_DONTDRAW;
|
||||
|
||||
// spilled rings have ghost trails and get capped to a certain speed
|
||||
if (actor->type == (mobjtype_t)actor->info->reactiontime)
|
||||
|
|
@ -4952,9 +4953,9 @@ void A_ThrownRing(mobj_t *actor)
|
|||
// spilled rings (and thrown bounce) flicker before disappearing
|
||||
if (leveltime & 1 && actor->fuse > 0 && actor->fuse < 2*TICRATE
|
||||
&& actor->type != MT_THROWNGRENADE)
|
||||
actor->flags2 |= MF2_DONTDRAW;
|
||||
actor->drawflags |= MFD_DONTDRAW;
|
||||
else
|
||||
actor->flags2 &= ~MF2_DONTDRAW;
|
||||
actor->drawflags &= ~MFD_DONTDRAW;
|
||||
|
||||
if (actor->tracer && actor->tracer->health <= 0)
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
|
|
@ -6665,11 +6666,8 @@ void A_MixUp(mobj_t *actor)
|
|||
INT32 transspeed; //player speed
|
||||
|
||||
// Starpost stuff
|
||||
INT16 starpostx, starposty, starpostz;
|
||||
fixed_t starpostx, starposty, starpostz;
|
||||
INT32 starpostnum;
|
||||
tic_t starposttime;
|
||||
angle_t starpostangle;
|
||||
fixed_t starpostscale;
|
||||
|
||||
INT32 mflags2;
|
||||
|
||||
|
|
@ -6713,24 +6711,21 @@ void A_MixUp(mobj_t *actor)
|
|||
angle = players[one].mo->angle;
|
||||
drawangle = players[one].drawangle;
|
||||
|
||||
starpostx = players[one].starpostx;
|
||||
starposty = players[one].starposty;
|
||||
starpostz = players[one].starpostz;
|
||||
starpostangle = players[one].starpostangle;
|
||||
starpostscale = players[one].starpostscale;
|
||||
starpostx = players[one].respawn.pointx;
|
||||
starposty = players[one].respawn.pointy;
|
||||
starpostz = players[one].respawn.pointz;
|
||||
starpostnum = players[one].starpostnum;
|
||||
starposttime = players[one].starposttime;
|
||||
|
||||
mflags2 = players[one].mo->flags2;
|
||||
|
||||
P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle,
|
||||
players[two].starpostx, players[two].starposty, players[two].starpostz,
|
||||
players[two].starpostnum, players[two].starposttime, players[two].starpostangle,
|
||||
players[two].starpostscale, players[two].drawangle, players[two].mo->flags2);
|
||||
players[two].respawn.pointx, players[two].respawn.pointy, players[two].respawn.pointz,
|
||||
players[two].starpostnum, 0, 0,
|
||||
FRACUNIT, players[two].drawangle, players[two].mo->flags2);
|
||||
|
||||
P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz,
|
||||
starpostnum, starposttime, starpostangle,
|
||||
starpostscale, drawangle, mflags2);
|
||||
starpostnum, 0, 0,
|
||||
FRACUNIT, drawangle, mflags2);
|
||||
|
||||
//carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for...
|
||||
//but not all of it! So we need to make sure they aren't set wrong or anything.
|
||||
|
|
@ -6753,11 +6748,8 @@ void A_MixUp(mobj_t *actor)
|
|||
INT32 transspeed[MAXPLAYERS]; //player speed
|
||||
|
||||
// Star post stuff
|
||||
INT16 spposition[MAXPLAYERS][3];
|
||||
fixed_t spposition[MAXPLAYERS][3];
|
||||
INT32 starpostnum[MAXPLAYERS];
|
||||
tic_t starposttime[MAXPLAYERS];
|
||||
angle_t starpostangle[MAXPLAYERS];
|
||||
fixed_t starpostscale[MAXPLAYERS];
|
||||
|
||||
INT32 flags2[MAXPLAYERS];
|
||||
|
||||
|
|
@ -6789,13 +6781,10 @@ void A_MixUp(mobj_t *actor)
|
|||
transspeed[counter] = players[i].speed;
|
||||
transtracer[counter] = players[i].mo->tracer;
|
||||
|
||||
spposition[counter][0] = players[i].starpostx;
|
||||
spposition[counter][1] = players[i].starposty;
|
||||
spposition[counter][2] = players[i].starpostz;
|
||||
spposition[counter][0] = players[i].respawn.pointx;
|
||||
spposition[counter][1] = players[i].respawn.pointy;
|
||||
spposition[counter][2] = players[i].respawn.pointz;
|
||||
starpostnum[counter] = players[i].starpostnum;
|
||||
starposttime[counter] = players[i].starposttime;
|
||||
starpostangle[counter] = players[i].starpostangle;
|
||||
starpostscale[counter] = players[i].starpostscale;
|
||||
|
||||
flags2[counter] = players[i].mo->flags2;
|
||||
|
||||
|
|
@ -6835,8 +6824,8 @@ void A_MixUp(mobj_t *actor)
|
|||
|
||||
P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom][0],
|
||||
spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2],
|
||||
starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom],
|
||||
starpostscale[teleportfrom], anglepos[teleportfrom][1], flags2[teleportfrom]);
|
||||
starpostnum[teleportfrom], 0, 0,
|
||||
FRACUNIT, anglepos[teleportfrom][1], flags2[teleportfrom]);
|
||||
|
||||
//...carry after. same reasoning.
|
||||
players[i].powers[pw_carry] = transcarry[teleportfrom];
|
||||
|
|
@ -9812,7 +9801,7 @@ void A_SPBChase(mobj_t *actor)
|
|||
if (players[i].mo->health <= 0)
|
||||
continue; // dead
|
||||
|
||||
if (players[i].kartstuff[k_respawn])
|
||||
if (players[i].respawn.state != RESPAWNST_NONE)
|
||||
continue;*/ // respawning
|
||||
|
||||
if (players[i].kartstuff[k_position] < bestrank)
|
||||
|
|
@ -9989,7 +9978,7 @@ void A_SPBChase(mobj_t *actor)
|
|||
|
||||
actor->lastlook = -1; // Just make sure this is reset
|
||||
|
||||
if (!player || !player->mo || player->mo->health <= 0 || player->kartstuff[k_respawn])
|
||||
if (!player || !player->mo || player->mo->health <= 0 || (player->respawn.state != RESPAWNST_NONE))
|
||||
{
|
||||
// No one there? Completely STOP.
|
||||
actor->momx = actor->momy = actor->momz = 0;
|
||||
|
|
@ -10274,7 +10263,7 @@ void A_RandomShadowFrame(mobj_t *actor)
|
|||
fake->destscale = FRACUNIT*3/2;
|
||||
fake->angle = actor->angle;
|
||||
fake->tics = -1;
|
||||
actor->flags2 |= MF2_DONTDRAW;
|
||||
actor->drawflags |= MFD_DONTDRAW;
|
||||
actor->extravalue1 = 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
198
src/p_inter.c
198
src/p_inter.c
|
|
@ -33,6 +33,7 @@
|
|||
#include "k_kart.h"
|
||||
#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") : ""
|
||||
|
|
@ -902,71 +903,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;
|
||||
}
|
||||
|
||||
|
|
@ -1068,7 +1144,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
{
|
||||
if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
|
||||
G_StopMetalRecording(true);
|
||||
target->flags2 &= ~MF2_DONTDRAW;
|
||||
|
||||
target->drawflags &= ~MFD_DONTDRAW;
|
||||
}
|
||||
|
||||
// if killed by a player
|
||||
|
|
@ -1076,12 +1153,28 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1096,44 +1189,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
target->standingslope = NULL;
|
||||
target->pmomz = 0;
|
||||
|
||||
if (!target->player->bot && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives())
|
||||
{
|
||||
if (!(target->player->pflags & PF_FINISHED))
|
||||
target->player->lives -= 1; // Lose a life Tails 03-11-2000
|
||||
|
||||
if (target->player->lives <= 0) // Tails 03-14-2000
|
||||
{
|
||||
boolean gameovermus = false;
|
||||
if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value != 1))
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAXPLAYERS)
|
||||
gameovermus = true;
|
||||
}
|
||||
else if (P_IsLocalPlayer(target->player))
|
||||
gameovermus = true;
|
||||
|
||||
if (gameovermus) // Yousa dead now, Okieday? Tails 03-14-2000
|
||||
S_ChangeMusicEx("_gover", 0, 0, 0, (2*MUSICRATE) - (MUSICRATE/25), 0); // 1.96 seconds
|
||||
//P_PlayJingle(target->player, JT_GOVER); // can't be used because incompatible with track fadeout
|
||||
|
||||
if (!(netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking) && numgameovers < maxgameovers)
|
||||
{
|
||||
numgameovers++;
|
||||
if ((!modifiedgame || savemoddata) && cursaveslot > 0)
|
||||
G_SaveGameOver((UINT32)cursaveslot, (target->player->continues <= 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target->player->playerstate = PST_DEAD;
|
||||
|
||||
if (target->player == &players[consoleplayer])
|
||||
|
|
@ -1619,7 +1674,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
|
|||
{
|
||||
mobj_t *boom;
|
||||
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
|
||||
player->mo->flags2 |= MF2_DONTDRAW;
|
||||
player->mo->drawflags |= MFD_DONTDRAW;
|
||||
boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM);
|
||||
boom->scale = player->mo->scale;
|
||||
boom->angle = player->mo->angle;
|
||||
|
|
@ -1783,6 +1838,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);
|
||||
|
|
|
|||
132
src/p_map.c
132
src/p_map.c
|
|
@ -26,6 +26,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "k_kart.h" // SRB2kart 011617
|
||||
#include "k_collide.h"
|
||||
#include "k_respawn.h"
|
||||
|
||||
#include "hu_stuff.h" // SRB2kart
|
||||
#include "i_system.h" // SRB2kart
|
||||
|
|
@ -329,39 +330,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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2823,6 +2795,100 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
|
|||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// PTR_GetSpecialLines
|
||||
//
|
||||
static boolean PTR_GetSpecialLines(intercept_t *in)
|
||||
{
|
||||
line_t *ld;
|
||||
|
||||
I_Assert(in->isaline);
|
||||
|
||||
ld = in->d.line;
|
||||
|
||||
if (!ld->backsector)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (P_SpecialIsLinedefCrossType(ld->special))
|
||||
{
|
||||
add_spechit(ld);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// P_HitSpecialLines
|
||||
// Finds all special lines in the provided path and tries to cross them.
|
||||
// For zoom tubes and respawning, which noclip but need to cross finish lines.
|
||||
//
|
||||
void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_t momy)
|
||||
{
|
||||
fixed_t leadx, leady;
|
||||
fixed_t trailx, traily;
|
||||
line_t *ld = NULL;
|
||||
INT32 side = 0, oldside = 0;
|
||||
|
||||
I_Assert(thing != NULL);
|
||||
#ifdef PARANOIA
|
||||
if (P_MobjWasRemoved(thing))
|
||||
I_Error("Previously-removed Thing of type %u crashes P_CheckPosition!", thing->type);
|
||||
#endif
|
||||
|
||||
// reset special lines
|
||||
numspechitint = 0U;
|
||||
numspechit = 0U;
|
||||
|
||||
// trace along the three leading corners
|
||||
if (momx > 0)
|
||||
{
|
||||
leadx = x + thing->radius;
|
||||
trailx = x - thing->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leadx = x - thing->radius;
|
||||
trailx = x + thing->radius;
|
||||
}
|
||||
|
||||
if (momy > 0)
|
||||
{
|
||||
leady = y + thing->radius;
|
||||
traily = y - thing->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leady = y - thing->radius;
|
||||
traily = y + thing->radius;
|
||||
}
|
||||
|
||||
P_PathTraverse(leadx, leady, leadx + momx, leady + momy, PT_ADDLINES, PTR_GetSpecialLines);
|
||||
P_PathTraverse(trailx, leady, trailx + momx, leady + momy, PT_ADDLINES, PTR_GetSpecialLines);
|
||||
P_PathTraverse(leadx, traily, leadx + momx, traily + momy, PT_ADDLINES, PTR_GetSpecialLines);
|
||||
|
||||
spechitint_copyinto();
|
||||
|
||||
// remove any duplicates that may be in spechitint
|
||||
spechitint_removedups();
|
||||
|
||||
// handle any of the special lines that were crossed
|
||||
while (numspechitint--)
|
||||
{
|
||||
ld = &lines[spechitint[numspechitint]];
|
||||
side = P_PointOnLineSide(x + momx, y + momy, ld);
|
||||
oldside = P_PointOnLineSide(x, y, ld);
|
||||
if (side != oldside)
|
||||
{
|
||||
if (ld->special)
|
||||
{
|
||||
P_CrossSpecialLine(ld, oldside, thing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_ThingHeightClip
|
||||
// Takes a valid thing and adjusts the thing->floorz,
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ void P_UnsetPrecipThingPosition(precipmobj_t *thing);
|
|||
void P_SetPrecipitationThingPosition(precipmobj_t *thing);
|
||||
void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y);
|
||||
boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y);
|
||||
void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_t momy);
|
||||
|
||||
extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
|
||||
extern pslope_t *opentopslope, *openbottomslope;
|
||||
|
|
|
|||
126
src/p_mobj.c
126
src/p_mobj.c
|
|
@ -38,6 +38,7 @@
|
|||
#include "k_kart.h"
|
||||
#include "k_battle.h"
|
||||
#include "k_color.h"
|
||||
#include "k_respawn.h"
|
||||
#include "k_bot.h"
|
||||
|
||||
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
|
||||
|
|
@ -1278,8 +1279,8 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
|
|||
player = mo->player;
|
||||
if (player) // valid only if player avatar
|
||||
{
|
||||
if (FixedHypot(player->rmomx, player->rmomy) < FixedMul(STOPSPEED, mo->scale) && player->cmd.forwardmove == 0
|
||||
&& !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)))
|
||||
if (FixedHypot(player->rmomx, player->rmomy) < FixedMul(STOPSPEED, mo->scale) && K_GetForwardMove(player) == 0
|
||||
&& !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) /*&& (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)*/))
|
||||
{
|
||||
// if in a walking frame, stop moving
|
||||
if (player->panim == PA_WALK)
|
||||
|
|
@ -1292,16 +1293,8 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
|
|||
}
|
||||
else if (!(mo->eflags & MFE_SPRUNG))
|
||||
{
|
||||
if (oldx == mo->x && oldy == mo->y) // didn't go anywhere
|
||||
{
|
||||
mo->momx = FixedMul(mo->momx, ORIG_FRICTION);
|
||||
mo->momy = FixedMul(mo->momy, ORIG_FRICTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
mo->momx = FixedMul(mo->momx, mo->friction);
|
||||
mo->momy = FixedMul(mo->momy, mo->friction);
|
||||
}
|
||||
mo->momx = FixedMul(mo->momx, mo->friction);
|
||||
mo->momy = FixedMul(mo->momy, mo->friction);
|
||||
|
||||
mo->friction = ORIG_FRICTION;
|
||||
}
|
||||
|
|
@ -1785,7 +1778,7 @@ void P_XYMovement(mobj_t *mo)
|
|||
if (mo->type == MT_FLINGRING || mo->type == MT_BALLHOG || mo->type == MT_BUBBLESHIELDTRAP)
|
||||
return;
|
||||
|
||||
if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= K_GetKartSpeed(mo->player, false)/2)
|
||||
if (player && (player->kartstuff[k_spinouttimer] && !player->kartstuff[k_wipeoutslow]) && player->speed <= FixedDiv(20*mapobjectscale, player->kartstuff[k_offroad] + FRACUNIT))
|
||||
return;
|
||||
//}
|
||||
|
||||
|
|
@ -2293,6 +2286,17 @@ boolean P_ZMovement(mobj_t *mo)
|
|||
mom.z = P_MobjFlip(mo)*FixedMul(5*FRACUNIT, mo->scale);
|
||||
else if (mo->type == MT_SPINFIRE) // elemental shield fire is another exception here
|
||||
;
|
||||
else if (mo->type == MT_DRIFTCLIP)
|
||||
{
|
||||
mom.z = -mom.z/2;
|
||||
if (abs(mom.z) > 4 * mo->scale / 3)
|
||||
{
|
||||
K_SpawnDriftBoostClipSpark(mo);
|
||||
S_StartSound(mo, sfx_tink);
|
||||
}
|
||||
else
|
||||
mo->flags2 ^= MFD_DONTDRAW;
|
||||
}
|
||||
else if (mo->flags & MF_MISSILE)
|
||||
{
|
||||
if (!(mo->flags & MF_NOCLIP))
|
||||
|
|
@ -2673,7 +2677,6 @@ void P_PlayerZMovement(mobj_t *mo)
|
|||
boolean clipmomz = !(P_CheckDeathPitCollide(mo));
|
||||
|
||||
mo->pmomz = 0; // We're on a new floor, don't keep doing platform movement.
|
||||
|
||||
mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack
|
||||
|
||||
clipmomz = P_PlayerHitFloor(mo->player, true);
|
||||
|
|
@ -3503,14 +3506,12 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
|
|||
// momentum movement
|
||||
mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN;
|
||||
|
||||
if (mobj->state-states == S_PLAY_BOUNCE_LANDING)
|
||||
goto animonly; // no need for checkposition - doesn't move at ALL
|
||||
|
||||
// Zoom tube
|
||||
if (mobj->tracer)
|
||||
if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer))
|
||||
{
|
||||
if (mobj->player->powers[pw_carry] == CR_ZOOMTUBE || mobj->player->powers[pw_carry] == CR_ROPEHANG)
|
||||
if (mobj->player->powers[pw_carry] == CR_ZOOMTUBE || mobj->player->respawn.state == RESPAWNST_MOVE)
|
||||
{
|
||||
P_HitSpecialLines(mobj, mobj->x, mobj->y, mobj->momx, mobj->momy);
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->x += mobj->momx;
|
||||
mobj->y += mobj->momy;
|
||||
|
|
@ -3521,13 +3522,6 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
|
|||
mobj->ceilingz = tmceilingz;
|
||||
goto animonly;
|
||||
}
|
||||
else if (mobj->player->powers[pw_carry] == CR_MACESPIN)
|
||||
{
|
||||
P_CheckPosition(mobj, mobj->x, mobj->y);
|
||||
mobj->floorz = tmfloorz;
|
||||
mobj->ceilingz = tmceilingz;
|
||||
goto animonly;
|
||||
}
|
||||
}
|
||||
|
||||
// Needed for gravity boots
|
||||
|
|
@ -3703,16 +3697,16 @@ static void P_RingThinker(mobj_t *mobj)
|
|||
if (mobj->fuse < TICRATE*3)
|
||||
{
|
||||
if (leveltime & 1)
|
||||
mobj->flags2 |= MF2_DONTDRAW;
|
||||
mobj->drawflags |= MFD_DONTDRAW;
|
||||
else
|
||||
mobj->flags2 &= ~MF2_DONTDRAW;
|
||||
mobj->drawflags &= ~MFD_DONTDRAW;
|
||||
}
|
||||
|
||||
if (!mobj->fuse)
|
||||
{
|
||||
if (!LUAh_MobjFuse(mobj))
|
||||
{
|
||||
mobj->flags2 &= ~MF2_DONTDRAW;
|
||||
mobj->drawflags &= ~MFD_DONTDRAW;
|
||||
spark = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SIGNSPARKLE); // Spawn a fancy sparkle
|
||||
K_MatchGenericExtraFlags(spark, mobj);
|
||||
spark->colorized = true;
|
||||
|
|
@ -7606,6 +7600,26 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
if (mobj->tics > 0)
|
||||
mobj->flags2 ^= MF2_DONTDRAW;
|
||||
break;
|
||||
case MT_FOLLOWER:
|
||||
// small thinker for follower:
|
||||
// We cleanse ourselves from existence if our target player doesn't exist for whatever reason. (generally players leaving)
|
||||
if (!mobj->target || P_MobjWasRemoved(mobj->target) || !mobj->target->player || mobj->target->player->spectator || mobj->target->player->followerskin < 0)
|
||||
{
|
||||
// Remove possible hnext list (bubble)
|
||||
mobj_t *bub = mobj->hnext;
|
||||
mobj_t *tmp;
|
||||
|
||||
while (bub && !P_MobjWasRemoved(bub))
|
||||
{
|
||||
tmp = bub->hnext;
|
||||
P_RemoveMobj(bub);
|
||||
bub = tmp;
|
||||
}
|
||||
|
||||
P_RemoveMobj(mobj);
|
||||
}
|
||||
|
||||
return;
|
||||
case MT_VWREF:
|
||||
case MT_VWREB:
|
||||
{
|
||||
|
|
@ -11425,13 +11439,13 @@ void P_SceneryThinker(mobj_t *mobj)
|
|||
&& mobj->extravalue1 > 0 && mobj->extravalue2 >= 2)
|
||||
{
|
||||
if (mobj->extravalue2 == 2) // I don't know why the normal logic doesn't work for this.
|
||||
mobj->flags2 ^= MF2_DONTDRAW;
|
||||
mobj->drawflags ^= MFD_DONTDRAW;
|
||||
else
|
||||
{
|
||||
if (mobj->fuse == mobj->extravalue2)
|
||||
mobj->flags2 &= ~MF2_DONTDRAW;
|
||||
mobj->drawflags &= ~MFD_DONTDRAW;
|
||||
else
|
||||
mobj->flags2 |= MF2_DONTDRAW;
|
||||
mobj->drawflags |= MFD_DONTDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -11564,6 +11578,9 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
|||
case MT_FLOATINGITEM:
|
||||
thing->shadowscale = FRACUNIT/2;
|
||||
break;
|
||||
case MT_DRIFTCLIP:
|
||||
thing->shadowscale = FRACUNIT/3;
|
||||
break;
|
||||
default:
|
||||
if (thing->flags & (MF_ENEMY|MF_BOSS))
|
||||
thing->shadowscale = FRACUNIT;
|
||||
|
|
@ -12633,18 +12650,20 @@ void P_RespawnSpecials(void)
|
|||
return;
|
||||
else if (pcount > 1)
|
||||
{
|
||||
time = (180 - (pcount * 10))*TICRATE;
|
||||
time = (120 - ((pcount-2) * 10))*TICRATE;
|
||||
|
||||
// If the map is longer or shorter than 3 laps, then adjust ring respawn to account for this.
|
||||
// 5 lap courses would have more retreaded ground, while 2 lap courses would have less.
|
||||
if ((mapheaderinfo[gamemap-1]->numlaps != 3)
|
||||
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
|
||||
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;
|
||||
if (time < 10*TICRATE)
|
||||
{
|
||||
// Ensure it doesn't go into absurdly low values
|
||||
time = 10*TICRATE;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing left to respawn?
|
||||
if (iquehead == iquetail)
|
||||
|
|
@ -12801,6 +12820,8 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
p->awayviewmobj = NULL;
|
||||
p->awayviewtics = 0;
|
||||
|
||||
P_SetTarget(&p->follower, NULL); // cleanse follower from existence
|
||||
|
||||
// set the scale to the mobj's destscale so settings get correctly set. if we don't, they sometimes don't.
|
||||
if (cv_kartdebugshrink.value && !modeattacking && !p->bot)
|
||||
mobj->destscale = 6*mobj->destscale/8;
|
||||
|
|
@ -12824,14 +12845,11 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
p->nightstime = sstimer;
|
||||
}
|
||||
|
||||
if (p->kartstuff[k_respawn] != 0)
|
||||
p->mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY;
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS)) // SRB2kart
|
||||
{
|
||||
mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height + 16*FRACUNIT, MT_PLAYERARROW);
|
||||
P_SetTarget(&overheadarrow->target, mobj);
|
||||
overheadarrow->flags2 |= MF2_DONTDRAW;
|
||||
overheadarrow->drawflags |= MFD_DONTDRAW;
|
||||
P_SetScale(overheadarrow, mobj->destscale);
|
||||
|
||||
if (p->spectator && pcount > 1) // HEY! No being cheap...
|
||||
|
|
@ -12857,10 +12875,10 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
P_SetTarget(&mo->target, mobj);
|
||||
mo->angle = (diff * (i-1));
|
||||
mo->color = mobj->color;
|
||||
if (mobj->flags2 & MF2_DONTDRAW)
|
||||
mo->flags2 |= MF2_DONTDRAW;
|
||||
if (mobj->drawflags & MFD_DONTDRAW)
|
||||
mo->drawflags |= MFD_DONTDRAW;
|
||||
else
|
||||
mo->flags2 &= ~MF2_DONTDRAW;
|
||||
mo->drawflags &= ~MFD_DONTDRAW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12970,6 +12988,11 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
|
|||
else
|
||||
z = floor;
|
||||
|
||||
if (p->respawn.state != RESPAWNST_NONE)
|
||||
{
|
||||
z += K_RespawnOffset(p, (mthing->options & MTF_OBJECTFLIP));
|
||||
}
|
||||
|
||||
if (z < floor)
|
||||
z = floor;
|
||||
else if (z > ceilingspawn)
|
||||
|
|
@ -13007,18 +13030,18 @@ void P_MovePlayerToStarpost(INT32 playernum)
|
|||
mobj_t *mobj = p->mo;
|
||||
I_Assert(mobj != NULL);
|
||||
|
||||
K_DoIngameRespawn(p);
|
||||
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->x = p->starpostx << FRACBITS;
|
||||
mobj->y = p->starposty << FRACBITS;
|
||||
mobj->x = p->respawn.pointx;
|
||||
mobj->y = p->respawn.pointy;
|
||||
P_SetThingPosition(mobj);
|
||||
sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
|
||||
|
||||
floor = P_GetSectorFloorZAt (sector, mobj->x, mobj->y);
|
||||
ceiling = P_GetSectorCeilingZAt(sector, mobj->x, mobj->y);
|
||||
|
||||
z = p->starpostz << FRACBITS;
|
||||
|
||||
P_SetScale(mobj, (mobj->destscale = abs(p->starpostscale)));
|
||||
z = p->respawn.pointz;
|
||||
|
||||
if (p->starpostscale < 0)
|
||||
{
|
||||
|
|
@ -13041,12 +13064,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
|
|||
|
||||
mobj->z = z;
|
||||
|
||||
mobj->angle = p->starpostangle;
|
||||
|
||||
P_AfterPlayerSpawn(playernum);
|
||||
|
||||
if (!(netgame || multiplayer))
|
||||
leveltime = p->starposttime;
|
||||
}
|
||||
|
||||
fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale)
|
||||
|
|
|
|||
48
src/p_mobj.h
48
src/p_mobj.h
|
|
@ -108,7 +108,7 @@ typedef enum
|
|||
// Don't use the blocklinks (inert but displayable)
|
||||
MF_NOBLOCKMAP = 1<<4,
|
||||
// Thin, paper-like collision bound (for visual equivalent, see FF_PAPERSPRITE)
|
||||
MF_PAPERCOLLISION = 1<<5,
|
||||
MF_PAPERCOLLISION = 1<<5,
|
||||
// You can push this object. It can activate switches and things by pushing it on top.
|
||||
MF_PUSHABLE = 1<<6,
|
||||
// Object is a boss.
|
||||
|
|
@ -159,7 +159,7 @@ typedef enum
|
|||
MF_GRENADEBOUNCE = 1<<28,
|
||||
// Run the action thinker on spawn.
|
||||
MF_RUNSPAWNFUNC = 1<<29,
|
||||
// Don't remap in Encore mode.
|
||||
// Don't remap in Encore mode. (Not a drawflag so that it's settable by mobjinfo.)
|
||||
MF_DONTENCOREMAP = 1<<30,
|
||||
// free: 1<<31
|
||||
} mobjflag_t;
|
||||
|
|
@ -169,7 +169,7 @@ typedef enum
|
|||
MF2_AXIS = 1, // It's a NiGHTS axis! (For faster checking)
|
||||
MF2_TWOD = 1<<1, // Moves like it's in a 2D level
|
||||
MF2_DONTRESPAWN = 1<<2, // Don't respawn this object!
|
||||
MF2_DONTDRAW = 1<<3, // Don't generate a vissprite
|
||||
// free: 1<<3
|
||||
MF2_AUTOMATIC = 1<<4, // Thrown ring has automatic properties
|
||||
MF2_RAILRING = 1<<5, // Thrown ring has rail properties
|
||||
MF2_BOUNCERING = 1<<6, // Thrown ring has bounce properties
|
||||
|
|
@ -185,7 +185,7 @@ typedef enum
|
|||
MF2_JUSTATTACKED = 1<<16, // can be pushed by other moving mobjs
|
||||
MF2_FIRING = 1<<17, // turret fire
|
||||
MF2_SUPERFIRE = 1<<18, // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it.
|
||||
MF2_SHADOW = 1<<19, // Fuzzy draw, makes targeting harder.
|
||||
// free: 1<<19
|
||||
MF2_STRONGBOX = 1<<20, // Flag used for "strong" random monitors.
|
||||
MF2_OBJECTFLIP = 1<<21, // Flag for objects that always have flipped gravity.
|
||||
MF2_SKULLFLY = 1<<22, // Special handling: skull in flight.
|
||||
|
|
@ -248,14 +248,43 @@ typedef enum
|
|||
MFE_TRACERANGLE = 1<<11,
|
||||
// SRB2Kart: The mobj just hit & bounced off a wall, this is cleared on next frame
|
||||
MFE_JUSTBOUNCEDWALL = 1<<12,
|
||||
// SRB2Kart: Splitscreen sprite display; very wasteful but I couldn't think of another way to do it...
|
||||
MFE_DRAWONLYFORP1 = 1<<13,
|
||||
MFE_DRAWONLYFORP2 = 1<<14,
|
||||
MFE_DRAWONLYFORP3 = 1<<15,
|
||||
MFE_DRAWONLYFORP4 = 1<<15, // WELP, just merge drawflags later so this isn't a problem :V
|
||||
// free: to and including 1<<15
|
||||
} mobjeflag_t;
|
||||
|
||||
//
|
||||
// Mobj drawing flags
|
||||
// Set by hex, to make masking shenanigans easier to keep track of.
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
// Don't generate a vissprite for individual screens
|
||||
MFD_DONTDRAWP1 = 0x0001,
|
||||
MFD_DONTDRAWP2 = 0x0002,
|
||||
MFD_DONTDRAWP3 = 0x0004,
|
||||
MFD_DONTDRAWP4 = 0x0008,
|
||||
// Transparency override flags
|
||||
MFD_TRANS10 = 0x0010,
|
||||
MFD_TRANS20 = 0x0020,
|
||||
MFD_TRANS30 = 0x0030,
|
||||
MFD_TRANS40 = 0x0040,
|
||||
MFD_TRANS50 = 0x0050,
|
||||
MFD_TRANS60 = 0x0060,
|
||||
MFD_TRANS70 = 0x0070,
|
||||
MFD_TRANS80 = 0x0080,
|
||||
MFD_TRANS90 = 0x0090,
|
||||
MFD_TRANSMASK = 0x00F0,
|
||||
// Brightness override flags
|
||||
MFD_FULLBRIGHT = 0x0100,
|
||||
MFD_SEMIBRIGHT = 0x0200,
|
||||
MFD_NOBRIGHT = 0x0300,
|
||||
MFD_BRIGHTMASK = 0x0F00,
|
||||
// Shortcuts
|
||||
MFD_DONTDRAW = MFD_DONTDRAWP1|MFD_DONTDRAWP2|MFD_DONTDRAWP3|MFD_DONTDRAWP4,
|
||||
MFD_SHADOW = MFD_TRANS80|MFD_FULLBRIGHT,
|
||||
MFD_TRANSSHIFT = 4,
|
||||
// free: to and including 0x8000
|
||||
} mobjdflag_t;
|
||||
|
||||
//
|
||||
// PRECIPITATION flags ?! ?! ?!
|
||||
//
|
||||
|
|
@ -315,6 +344,7 @@ typedef struct mobj_s
|
|||
UINT32 flags; // flags from mobjinfo tables
|
||||
UINT32 flags2; // MF2_ flags
|
||||
UINT16 eflags; // extra flags
|
||||
UINT16 drawflags; // Rendering-related flags. These should not be used for game logic.
|
||||
|
||||
void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin)
|
||||
// Player and mobj sprites in multiplayer modes are modified
|
||||
|
|
|
|||
231
src/p_saveg.c
231
src/p_saveg.c
|
|
@ -54,14 +54,9 @@ UINT8 *save_p;
|
|||
// than an UINT16
|
||||
typedef enum
|
||||
{
|
||||
// RFLAGPOINT = 0x01,
|
||||
// BFLAGPOINT = 0x02,
|
||||
CAPSULE = 0x04,
|
||||
AWAYVIEW = 0x08,
|
||||
FIRSTAXIS = 0x10,
|
||||
SECONDAXIS = 0x20,
|
||||
FOLLOW = 0x40,
|
||||
DRONE = 0x80,
|
||||
AWAYVIEW = 0x01,
|
||||
FOLLOWITEM = 0x02,
|
||||
FOLLOWER = 0x04,
|
||||
} player_saveflags;
|
||||
|
||||
static inline void P_ArchivePlayer(void)
|
||||
|
|
@ -119,10 +114,6 @@ static void P_NetArchivePlayers(void)
|
|||
|
||||
for (j = 0; j < NUMPOWERS; j++)
|
||||
WRITEUINT16(save_p, players[i].powers[j]);
|
||||
for (j = 0; j < NUMKARTSTUFF; j++)
|
||||
WRITEINT32(save_p, players[i].kartstuff[j]);
|
||||
|
||||
WRITEANGLE(save_p, players[i].frameangle);
|
||||
|
||||
WRITEUINT8(save_p, players[i].playerstate);
|
||||
WRITEUINT32(save_p, players[i].pflags);
|
||||
|
|
@ -135,6 +126,7 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEUINT32(save_p, players[i].score);
|
||||
WRITEFIXED(save_p, players[i].dashspeed);
|
||||
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);
|
||||
|
|
@ -165,6 +157,7 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEINT16(save_p, players[i].totalring);
|
||||
WRITEUINT32(save_p, players[i].realtime);
|
||||
WRITEUINT8(save_p, players[i].laps);
|
||||
WRITEINT32(save_p, players[i].starpostnum);
|
||||
|
||||
////////////////////
|
||||
// CTF Mode Stuff //
|
||||
|
|
@ -172,17 +165,6 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEINT32(save_p, players[i].ctfteam);
|
||||
WRITEUINT16(save_p, players[i].gotflag);
|
||||
|
||||
WRITEINT32(save_p, players[i].weapondelay);
|
||||
WRITEINT32(save_p, players[i].tossdelay);
|
||||
|
||||
WRITEUINT32(save_p, players[i].starposttime);
|
||||
WRITEINT16(save_p, players[i].starpostx);
|
||||
WRITEINT16(save_p, players[i].starposty);
|
||||
WRITEINT16(save_p, players[i].starpostz);
|
||||
WRITEINT32(save_p, players[i].starpostnum);
|
||||
WRITEANGLE(save_p, players[i].starpostangle);
|
||||
WRITEFIXED(save_p, players[i].starpostscale);
|
||||
|
||||
WRITEANGLE(save_p, players[i].angle_pos);
|
||||
WRITEANGLE(save_p, players[i].old_angle_pos);
|
||||
|
||||
|
|
@ -219,23 +201,14 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEUINT8(save_p, players[i].texttimer);
|
||||
WRITEUINT8(save_p, players[i].textvar);
|
||||
|
||||
if (players[i].capsule)
|
||||
flags |= CAPSULE;
|
||||
|
||||
if (players[i].awayviewmobj)
|
||||
flags |= AWAYVIEW;
|
||||
|
||||
if (players[i].axis1)
|
||||
flags |= FIRSTAXIS;
|
||||
|
||||
if (players[i].axis2)
|
||||
flags |= SECONDAXIS;
|
||||
|
||||
if (players[i].followmobj)
|
||||
flags |= FOLLOW;
|
||||
flags |= FOLLOWITEM;
|
||||
|
||||
if (players[i].drone)
|
||||
flags |= DRONE;
|
||||
if (players[i].follower)
|
||||
flags |= FOLLOWER;
|
||||
|
||||
WRITEINT16(save_p, players[i].lastsidehit);
|
||||
WRITEINT16(save_p, players[i].lastlinehit);
|
||||
|
|
@ -269,18 +242,45 @@ static void P_NetArchivePlayers(void)
|
|||
// SRB2kart
|
||||
WRITEUINT8(save_p, players[i].kartspeed);
|
||||
WRITEUINT8(save_p, players[i].kartweight);
|
||||
|
||||
WRITEUINT8(save_p, players[i].followerskin);
|
||||
WRITEUINT8(save_p, players[i].followerready); // booleans are really just numbers eh??
|
||||
WRITEUINT8(save_p, players[i].followercolor);
|
||||
if (flags & FOLLOWER)
|
||||
WRITEUINT32(save_p, players[i].follower->mobjnum);
|
||||
|
||||
|
||||
//
|
||||
|
||||
for (j = 0; j < NUMKARTSTUFF; j++)
|
||||
WRITEINT32(save_p, players[i].kartstuff[j]);
|
||||
|
||||
for (j = 0; j < MAXPREDICTTICS; j++)
|
||||
{
|
||||
WRITEINT16(save_p, players[i].lturn_max[j]);
|
||||
WRITEINT16(save_p, players[i].rturn_max[j]);
|
||||
}
|
||||
|
||||
WRITEANGLE(save_p, players[i].frameangle);
|
||||
WRITEUINT32(save_p, players[i].distancetofinish);
|
||||
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].nextwaypoint));
|
||||
WRITEUINT32(save_p, players[i].airtime);
|
||||
|
||||
// respawnvars_t
|
||||
WRITEUINT8(save_p, players[i].respawn.state);
|
||||
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp));
|
||||
WRITEFIXED(save_p, players[i].respawn.pointx);
|
||||
WRITEFIXED(save_p, players[i].respawn.pointy);
|
||||
WRITEFIXED(save_p, players[i].respawn.pointz);
|
||||
WRITEUINT8(save_p, players[i].respawn.flip);
|
||||
WRITEUINT32(save_p, players[i].respawn.timer);
|
||||
WRITEUINT32(save_p, players[i].respawn.distanceleft);
|
||||
WRITEUINT32(save_p, players[i].respawn.dropdash);
|
||||
|
||||
// botvars_t
|
||||
WRITEUINT8(save_p, players[i].botvars.difficulty);
|
||||
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);
|
||||
|
|
@ -323,10 +323,6 @@ static void P_NetUnArchivePlayers(void)
|
|||
|
||||
for (j = 0; j < NUMPOWERS; j++)
|
||||
players[i].powers[j] = READUINT16(save_p);
|
||||
for (j = 0; j < NUMKARTSTUFF; j++)
|
||||
players[i].kartstuff[j] = READINT32(save_p);
|
||||
|
||||
players[i].frameangle = READANGLE(save_p);
|
||||
|
||||
players[i].playerstate = READUINT8(save_p);
|
||||
players[i].pflags = READUINT32(save_p);
|
||||
|
|
@ -339,6 +335,7 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].score = READUINT32(save_p);
|
||||
players[i].dashspeed = READFIXED(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
|
||||
|
|
@ -369,6 +366,7 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].totalring = READINT16(save_p); // Total number of rings obtained for Race Mode
|
||||
players[i].realtime = READUINT32(save_p); // integer replacement for leveltime
|
||||
players[i].laps = READUINT8(save_p); // Number of laps (optional)
|
||||
players[i].starpostnum = READINT32(save_p);
|
||||
|
||||
////////////////////
|
||||
// CTF Mode Stuff //
|
||||
|
|
@ -379,14 +377,6 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].weapondelay = READINT32(save_p);
|
||||
players[i].tossdelay = READINT32(save_p);
|
||||
|
||||
players[i].starposttime = READUINT32(save_p);
|
||||
players[i].starpostx = READINT16(save_p);
|
||||
players[i].starposty = READINT16(save_p);
|
||||
players[i].starpostz = READINT16(save_p);
|
||||
players[i].starpostnum = READINT32(save_p);
|
||||
players[i].starpostangle = READANGLE(save_p);
|
||||
players[i].starpostscale = READFIXED(save_p);
|
||||
|
||||
players[i].angle_pos = READANGLE(save_p);
|
||||
players[i].old_angle_pos = READANGLE(save_p);
|
||||
|
||||
|
|
@ -465,18 +455,44 @@ static void P_NetUnArchivePlayers(void)
|
|||
// SRB2kart
|
||||
players[i].kartspeed = READUINT8(save_p);
|
||||
players[i].kartweight = READUINT8(save_p);
|
||||
|
||||
players[i].followerskin = READUINT8(save_p);
|
||||
players[i].followerready = READUINT8(save_p);
|
||||
players[i].followercolor = READUINT8(save_p);
|
||||
if (flags & FOLLOWER)
|
||||
players[i].follower = (mobj_t *)(size_t)READUINT32(save_p);
|
||||
|
||||
//
|
||||
|
||||
for (j = 0; j < NUMKARTSTUFF; j++)
|
||||
players[i].kartstuff[j] = READINT32(save_p);
|
||||
|
||||
for (j = 0; j < MAXPREDICTTICS; j++)
|
||||
{
|
||||
players[i].lturn_max[j] = READINT16(save_p);
|
||||
players[i].rturn_max[j] = READINT16(save_p);
|
||||
}
|
||||
|
||||
players[i].frameangle = READANGLE(save_p);
|
||||
players[i].distancetofinish = READUINT32(save_p);
|
||||
players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save_p);
|
||||
players[i].airtime = READUINT32(save_p);
|
||||
|
||||
// respawnvars_t
|
||||
players[i].respawn.state = READUINT8(save_p);
|
||||
players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p);
|
||||
players[i].respawn.pointx = READFIXED(save_p);
|
||||
players[i].respawn.pointy = READFIXED(save_p);
|
||||
players[i].respawn.pointz = READFIXED(save_p);
|
||||
players[i].respawn.flip = (boolean)READUINT8(save_p);
|
||||
players[i].respawn.timer = READUINT32(save_p);
|
||||
players[i].respawn.distanceleft = READUINT32(save_p);
|
||||
players[i].respawn.dropdash = READUINT32(save_p);
|
||||
|
||||
// botvars_t
|
||||
players[i].botvars.difficulty = READUINT8(save_p);
|
||||
players[i].botvars.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);
|
||||
|
|
@ -1391,9 +1407,10 @@ typedef enum
|
|||
MD2_MIRRORED = 1<<13,
|
||||
MD2_ROLLANGLE = 1<<14,
|
||||
MD2_SHADOWSCALE = 1<<15,
|
||||
MD2_WAYPOINTCAP = 1<<16,
|
||||
MD2_KITEMCAP = 1<<17,
|
||||
MD2_ITNEXT = 1<<18,
|
||||
MD2_DRAWFLAGS = 1<<16,
|
||||
MD2_WAYPOINTCAP = 1<<17,
|
||||
MD2_KITEMCAP = 1<<18,
|
||||
MD2_ITNEXT = 1<<19,
|
||||
} mobj_diff2_t;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -1606,6 +1623,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
diff2 |= MD2_ROLLANGLE;
|
||||
if (mobj->shadowscale)
|
||||
diff2 |= MD2_SHADOWSCALE;
|
||||
if (mobj->drawflags)
|
||||
diff2 |= MD2_DRAWFLAGS;
|
||||
if (mobj == waypointcap)
|
||||
diff2 |= MD2_WAYPOINTCAP;
|
||||
if (mobj == kitemcap)
|
||||
|
|
@ -1755,7 +1774,21 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
if (diff2 & MD2_ROLLANGLE)
|
||||
WRITEANGLE(save_p, mobj->rollangle);
|
||||
if (diff2 & MD2_SHADOWSCALE)
|
||||
{
|
||||
WRITEFIXED(save_p, mobj->shadowscale);
|
||||
WRITEUINT8(save_p, mobj->whiteshadow);
|
||||
}
|
||||
if (diff2 & MD2_DRAWFLAGS)
|
||||
{
|
||||
UINT16 df = mobj->drawflags;
|
||||
|
||||
if ((mobj->drawflags & MFD_DONTDRAW) != MFD_DONTDRAW)
|
||||
{
|
||||
df = (mobj->drawflags & ~MFD_DONTDRAW);
|
||||
}
|
||||
|
||||
WRITEUINT16(save_p, df);
|
||||
}
|
||||
|
||||
WRITEUINT32(save_p, mobj->mobjnum);
|
||||
}
|
||||
|
|
@ -2814,7 +2847,12 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
|||
if (diff2 & MD2_ROLLANGLE)
|
||||
mobj->rollangle = READANGLE(save_p);
|
||||
if (diff2 & MD2_SHADOWSCALE)
|
||||
{
|
||||
mobj->shadowscale = READFIXED(save_p);
|
||||
mobj->whiteshadow = READUINT8(save_p);
|
||||
}
|
||||
if (diff2 & MD2_DRAWFLAGS)
|
||||
mobj->drawflags = READUINT16(save_p);
|
||||
|
||||
if (diff & MD_REDFLAG)
|
||||
{
|
||||
|
|
@ -3843,56 +3881,47 @@ static void P_RelinkPointers(void)
|
|||
if (!(mobj->itnext = P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player && mobj->player->capsule)
|
||||
if (mobj->player)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->capsule;
|
||||
mobj->player->capsule = NULL;
|
||||
if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player && mobj->player->axis1)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->axis1;
|
||||
mobj->player->axis1 = NULL;
|
||||
if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player && mobj->player->axis2)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->axis2;
|
||||
mobj->player->axis2 = NULL;
|
||||
if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player && mobj->player->awayviewmobj)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->awayviewmobj;
|
||||
mobj->player->awayviewmobj = NULL;
|
||||
if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player && mobj->player->nextwaypoint)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->nextwaypoint;
|
||||
mobj->player->nextwaypoint = K_GetWaypointFromIndex(temp);
|
||||
if (mobj->player->nextwaypoint == NULL)
|
||||
if ( mobj->player->awayviewmobj)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "nextwaypoint not found on %d\n", mobj->type);
|
||||
temp = (UINT32)(size_t)mobj->player->awayviewmobj;
|
||||
mobj->player->awayviewmobj = NULL;
|
||||
if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player->followmobj)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->followmobj;
|
||||
mobj->player->followmobj = NULL;
|
||||
if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player->follower)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->follower;
|
||||
mobj->player->follower = NULL;
|
||||
if (!P_SetTarget(&mobj->player->follower, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "follower not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player->nextwaypoint)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->nextwaypoint;
|
||||
mobj->player->nextwaypoint = K_GetWaypointFromIndex(temp);
|
||||
if (mobj->player->nextwaypoint == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "nextwaypoint not found on %d\n", mobj->type);
|
||||
}
|
||||
}
|
||||
if (mobj->player->respawn.wp)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->respawn.wp;
|
||||
mobj->player->respawn.wp = K_GetWaypointFromIndex(temp);
|
||||
if (mobj->player->respawn.wp == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "respawn.wp not found on %d\n", mobj->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mobj->player && mobj->player->followmobj)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->followmobj;
|
||||
mobj->player->followmobj = NULL;
|
||||
if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player && mobj->player->drone)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->drone;
|
||||
mobj->player->drone = NULL;
|
||||
if (!P_SetTarget(&mobj->player->drone, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "drone not found on %d\n", mobj->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4144,6 +4173,10 @@ static void P_NetArchiveMisc(void)
|
|||
|
||||
WRITEUINT8(save_p, thwompsactive);
|
||||
WRITESINT8(save_p, spbplace);
|
||||
WRITEUINT8(save_p, rainbowstartavailable);
|
||||
|
||||
WRITEUINT32(save_p, introtime);
|
||||
WRITEUINT32(save_p, starttime);
|
||||
|
||||
// Is it paused?
|
||||
if (paused)
|
||||
|
|
@ -4274,6 +4307,10 @@ static inline boolean P_NetUnArchiveMisc(void)
|
|||
|
||||
thwompsactive = (boolean)READUINT8(save_p);
|
||||
spbplace = READSINT8(save_p);
|
||||
rainbowstartavailable = (boolean)READUINT8(save_p);
|
||||
|
||||
introtime = READUINT32(save_p);
|
||||
starttime = READUINT32(save_p);
|
||||
|
||||
// Is it paused?
|
||||
if (READUINT8(save_p) == 0x2f)
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@
|
|||
#include "k_pwrlv.h"
|
||||
#include "k_waypoint.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_grandprix.h"
|
||||
|
||||
//
|
||||
// Map MD5, calculated on level load.
|
||||
|
|
@ -3294,7 +3295,7 @@ lumpnum_t lastloadedmaplumpnum; // for comparative savegame
|
|||
static void P_InitLevelSettings(void)
|
||||
{
|
||||
INT32 i;
|
||||
boolean canresetlives = true;
|
||||
UINT8 p = 0;
|
||||
|
||||
leveltime = 0;
|
||||
|
||||
|
|
@ -3355,14 +3356,24 @@ static void P_InitLevelSettings(void)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
players[i].lives = 1; // SRB2Kart
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
p++;
|
||||
|
||||
if (grandprixinfo.gp == false)
|
||||
{
|
||||
players[i].lives = 3;
|
||||
players[i].xtralife = 0;
|
||||
players[i].totalring = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -3388,11 +3399,52 @@ static void P_InitLevelSettings(void)
|
|||
|
||||
// hit these too
|
||||
players[i].pflags &= ~(PF_GAMETYPEOVER);
|
||||
|
||||
// Wipe follower from existence to avoid crashes
|
||||
players[i].follower = NULL;
|
||||
}
|
||||
|
||||
// SRB2Kart: map load variables
|
||||
if (modeattacking) // Just play it safe and set everything
|
||||
rainbowstartavailable = false;
|
||||
|
||||
if (p >= 2)
|
||||
rainbowstartavailable = true;
|
||||
|
||||
if (p <= 2)
|
||||
{
|
||||
introtime = 0; // No intro in Record Attack / 1v1
|
||||
}
|
||||
else
|
||||
{
|
||||
introtime = (108) + 5; // 108 for rotation, + 5 for white fade
|
||||
}
|
||||
|
||||
numbulbs = 5;
|
||||
|
||||
if (p > 2)
|
||||
{
|
||||
numbulbs += (p-2);
|
||||
}
|
||||
|
||||
starttime = (introtime + (3*TICRATE)) + ((2*TICRATE) + (numbulbs * bulbtime)); // Start countdown time, + buffer time
|
||||
|
||||
// SRB2Kart: map load variables
|
||||
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;
|
||||
|
|
@ -3417,11 +3469,6 @@ static void P_InitLevelSettings(void)
|
|||
|
||||
memset(&battleovertime, 0, sizeof(struct battleovertime));
|
||||
speedscramble = encorescramble = -1;
|
||||
|
||||
if (!modeattacking)
|
||||
{
|
||||
K_UpdateMatchRaceBots();
|
||||
}
|
||||
}
|
||||
|
||||
// Respawns all the mapthings and mobjs in the map from the already loaded map data.
|
||||
|
|
@ -4195,6 +4242,17 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
// clear special respawning que
|
||||
iquehead = iquetail = 0;
|
||||
|
||||
// Fab : 19-07-98 : start cd music for this level (note: can be remapped)
|
||||
I_PlayCD((UINT8)(gamemap), false);
|
||||
|
||||
// preload graphics
|
||||
#ifdef HWRENDER // not win32 only 19990829 by Kin
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
HWR_PrepLevelCache(numtextures);
|
||||
}
|
||||
#endif
|
||||
|
||||
P_MapEnd();
|
||||
|
||||
// Remove the loading shit from the screen
|
||||
|
|
@ -4247,6 +4305,25 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
// 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();
|
||||
}
|
||||
|
||||
// No render mode, stop here.
|
||||
if (rendermode == render_none)
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "r_main.h"
|
||||
#include "p_maputl.h"
|
||||
#include "w_wad.h"
|
||||
#include "k_kart.h" // K_PlayerEBrake
|
||||
|
||||
pslope_t *slopelist = NULL;
|
||||
UINT16 slopecount = 0;
|
||||
|
|
@ -883,6 +884,10 @@ void P_ButteredSlope(mobj_t *mo)
|
|||
return; // don't slide down slopes if you can't touch them or you're not affected by gravity
|
||||
|
||||
if (mo->player) {
|
||||
// SRB2Kart - spindash negates slopes
|
||||
if (K_PlayerEBrake(mo->player))
|
||||
return;
|
||||
|
||||
// Changed in kart to only not apply physics on very slight slopes (I think about 4 degree angles)
|
||||
if (abs(mo->standingslope->zdelta) < FRACUNIT/21 && !(mo->player->pflags & PF_SPINNING))
|
||||
return; // Don't slide on non-steep slopes unless spinning
|
||||
|
|
|
|||
64
src/p_spec.c
64
src/p_spec.c
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "console.h" // CON_LogMessage
|
||||
#include "k_respawn.h"
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
|
@ -2071,7 +2072,12 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
{
|
||||
if (player)
|
||||
{
|
||||
if ((player->starpostnum == numstarposts) || (player->laps == 0))
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
// Will fault the player
|
||||
K_DoIngameRespawn(player);
|
||||
}
|
||||
else if ((player->starpostnum == numstarposts) || (player->laps == 0))
|
||||
{
|
||||
size_t i = 0;
|
||||
UINT8 nump = 0;
|
||||
|
|
@ -2106,6 +2112,14 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
player->karthud[khud_lapanimation] = 80;
|
||||
}
|
||||
|
||||
if (rainbowstartavailable == true)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_s23c);
|
||||
player->kartstuff[k_startboost] = 125;
|
||||
K_SpawnDriftBoostExplosion(player, 3);
|
||||
rainbowstartavailable = false;
|
||||
}
|
||||
|
||||
if (netgame && player->laps >= (UINT8)cv_numlaps.value)
|
||||
CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players]));
|
||||
|
||||
|
|
@ -2117,7 +2131,6 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
curlap = 0;
|
||||
}
|
||||
|
||||
player->starposttime = player->realtime;
|
||||
player->starpostnum = 0;
|
||||
|
||||
if (P_IsDisplayPlayer(player))
|
||||
|
|
@ -4715,19 +4728,19 @@ DoneSection2:
|
|||
break;
|
||||
|
||||
case 5: // Speed pad
|
||||
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;
|
||||
fixed_t sfxnum;
|
||||
|
||||
lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
||||
linespeed = sides[lines[i].sidenum[0]].textureoffset;
|
||||
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);
|
||||
|
||||
if (linespeed == 0)
|
||||
{
|
||||
|
|
@ -4738,36 +4751,21 @@ DoneSection2:
|
|||
// 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
|||
const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP;
|
||||
UINT8 i;
|
||||
|
||||
(void)starposttime;
|
||||
(void)starpostangle;
|
||||
|
||||
// the move is ok,
|
||||
// so link the thing into its new position
|
||||
P_UnsetThingPosition(thing);
|
||||
|
|
@ -80,12 +83,9 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
|||
thing->player->speed = 0;
|
||||
|
||||
// Starpost information
|
||||
thing->player->starpostx = starpostx;
|
||||
thing->player->starposty = starposty;
|
||||
thing->player->starpostz = starpostz;
|
||||
thing->player->starposttime = starposttime;
|
||||
thing->player->starpostangle = starpostangle;
|
||||
thing->player->starpostscale = starpostscale;
|
||||
thing->player->respawn.pointx = starpostx;
|
||||
thing->player->respawn.pointy = starposty;
|
||||
thing->player->respawn.pointz = starpostz;
|
||||
thing->player->starpostnum = starpostnum;
|
||||
|
||||
thing->player->drawangle = drawangle;
|
||||
|
|
|
|||
|
|
@ -641,9 +641,9 @@ void P_Ticker(boolean run)
|
|||
if (exitcountdown > 1)
|
||||
exitcountdown--;
|
||||
|
||||
if (indirectitemcooldown > 1)
|
||||
if (indirectitemcooldown > 0)
|
||||
indirectitemcooldown--;
|
||||
if (hyubgone > 1)
|
||||
if (hyubgone > 0)
|
||||
hyubgone--;
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS))
|
||||
|
|
|
|||
693
src/p_user.c
693
src/p_user.c
File diff suppressed because it is too large
Load diff
|
|
@ -93,6 +93,7 @@ extern INT16 color8to16[256]; // remap color index to highcolor
|
|||
extern INT16 *hicolormaps; // remap high colors to high colors..
|
||||
|
||||
extern CV_PossibleValue_t Color_cons_t[];
|
||||
extern CV_PossibleValue_t Followercolor_cons_t[]; // follower colours table, not a duplicate because of the "Match" option.
|
||||
|
||||
// Load TEXTURES definitions, create lookup tables
|
||||
void R_LoadTextures(void);
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ static UINT8** translationtablecache[TT_CACHE_SIZE] = {NULL};
|
|||
UINT8 skincolor_modified[MAXSKINCOLORS];
|
||||
|
||||
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
|
||||
CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for "Match", "Opposite" & NULL
|
||||
|
||||
/** \brief The R_InitTranslationTables
|
||||
|
||||
|
|
|
|||
36
src/r_main.c
36
src/r_main.c
|
|
@ -166,10 +166,6 @@ static void ChaseCam_OnChange(void);
|
|||
static void ChaseCam2_OnChange(void);
|
||||
static void ChaseCam3_OnChange(void);
|
||||
static void ChaseCam4_OnChange(void);
|
||||
static void FlipCam_OnChange(void);
|
||||
static void FlipCam2_OnChange(void);
|
||||
static void FlipCam3_OnChange(void);
|
||||
static void FlipCam4_OnChange(void);
|
||||
void SendWeaponPref(void);
|
||||
void SendWeaponPref2(void);
|
||||
void SendWeaponPref3(void);
|
||||
|
|
@ -180,10 +176,6 @@ consvar_t cv_chasecam = {"chasecam", "On", CV_CALL, CV_OnOff, ChaseCam_OnChange,
|
|||
consvar_t cv_chasecam2 = {"chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_chasecam3 = {"chasecam3", "On", CV_CALL, CV_OnOff, ChaseCam3_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_chasecam4 = {"chasecam4", "On", CV_CALL, CV_OnOff, ChaseCam4_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_flipcam3 = {"flipcam3", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam3_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_flipcam4 = {"flipcam4", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam4_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
|
@ -191,8 +183,6 @@ consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NU
|
|||
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_drawdist = {"drawdist", "8192", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
|
@ -284,26 +274,6 @@ static void ChaseCam4_OnChange(void)
|
|||
;
|
||||
}
|
||||
|
||||
static void FlipCam_OnChange(void)
|
||||
{
|
||||
SendWeaponPref();
|
||||
}
|
||||
|
||||
static void FlipCam2_OnChange(void)
|
||||
{
|
||||
SendWeaponPref2();
|
||||
}
|
||||
|
||||
static void FlipCam3_OnChange(void)
|
||||
{
|
||||
SendWeaponPref3();
|
||||
}
|
||||
|
||||
static void FlipCam4_OnChange(void)
|
||||
{
|
||||
SendWeaponPref4();
|
||||
}
|
||||
|
||||
//
|
||||
// R_PointOnSide
|
||||
// Traverse BSP (sub) tree,
|
||||
|
|
@ -1675,16 +1645,10 @@ void R_RegisterEngineStuff(void)
|
|||
CV_RegisterVar(&cv_tailspickup);
|
||||
CV_RegisterVar(&cv_allowmlook);
|
||||
CV_RegisterVar(&cv_homremoval);
|
||||
CV_RegisterVar(&cv_flipcam);
|
||||
CV_RegisterVar(&cv_flipcam2);
|
||||
CV_RegisterVar(&cv_flipcam3);
|
||||
CV_RegisterVar(&cv_flipcam4);
|
||||
|
||||
// Enough for dedicated server
|
||||
if (dedicated)
|
||||
return;
|
||||
|
||||
CV_RegisterVar(&cv_translucency);
|
||||
CV_RegisterVar(&cv_drawdist);
|
||||
CV_RegisterVar(&cv_drawdist_precip);
|
||||
CV_RegisterVar(&cv_fov);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ extern consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS];
|
|||
extern consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
extern consvar_t cv_shadow;
|
||||
extern consvar_t cv_translucency;
|
||||
extern consvar_t cv_drawdist, v_drawdist_precip;
|
||||
extern consvar_t cv_fov;
|
||||
extern consvar_t cv_skybox;
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ static visplane_t *new_visplane(unsigned hash)
|
|||
visplane_t *check = freetail;
|
||||
if (!check)
|
||||
{
|
||||
check = calloc(2, sizeof (*check));
|
||||
check = calloc(1, sizeof (*check));
|
||||
if (check == NULL) I_Error("%s: Out of memory", "new_visplane"); // FIXME: ugly
|
||||
}
|
||||
else
|
||||
|
|
|
|||
10
src/r_segs.c
10
src/r_segs.c
|
|
@ -176,14 +176,8 @@ static void R_DrawWallSplats(void)
|
|||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
break;
|
||||
case SPLATDRAWMODE_TRANS:
|
||||
if (!cv_translucency.value)
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
else
|
||||
{
|
||||
dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT);
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
}
|
||||
|
||||
dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT);
|
||||
colfunc = fuzzcolfunc;
|
||||
break;
|
||||
case SPLATDRAWMODE_SHADE:
|
||||
colfunc = colfuncs[COLDRAWFUNC_SHADE];
|
||||
|
|
|
|||
|
|
@ -1150,6 +1150,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
|
|||
continue;
|
||||
|
||||
z = isflipped ? P_GetFFloorBottomZAt(rover, thing->x, thing->y) : P_GetFFloorTopZAt(rover, thing->x, thing->y);
|
||||
|
||||
if CHECKZ
|
||||
{
|
||||
groundz = z;
|
||||
|
|
@ -1227,8 +1228,9 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
|
|||
if (shadowslope != NULL)
|
||||
*shadowslope = groundslope;
|
||||
|
||||
return groundz;
|
||||
#undef CHECKZ
|
||||
|
||||
return groundz;
|
||||
}
|
||||
|
||||
static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz)
|
||||
|
|
@ -1865,19 +1867,27 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
vis->transmap = NULL;
|
||||
|
||||
// specific translucency
|
||||
if (!cv_translucency.value)
|
||||
; // no translucency
|
||||
else if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility)
|
||||
vis->transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT); // because now the translucency is set through FF_TRANSMASK
|
||||
else if (oldthing->frame & FF_TRANSMASK)
|
||||
vis->transmap = transtables + (oldthing->frame & FF_TRANSMASK) - 0x10000;
|
||||
if (thing->drawflags & MFD_TRANSMASK) // Object is forcing transparency to a specific value
|
||||
vis->transmap = transtables + ((((thing->drawflags & MFD_TRANSMASK) - MFD_TRANS10) >> MFD_TRANSSHIFT) << FF_TRANSSHIFT);
|
||||
else if (thing->frame & FF_TRANSMASK)
|
||||
vis->transmap = transtables + ((thing->frame & FF_TRANSMASK) - FF_TRANS10);
|
||||
|
||||
if (oldthing->frame & FF_FULLBRIGHT || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW)
|
||||
vis->cut |= SC_FULLBRIGHT;
|
||||
else if (oldthing->frame & FF_SEMIBRIGHT)
|
||||
vis->cut |= SC_SEMIBRIGHT;
|
||||
if (thing->drawflags & MFD_BRIGHTMASK)
|
||||
{
|
||||
if (thing->drawflags & MFD_FULLBRIGHT)
|
||||
vis->cut |= SC_FULLBRIGHT;
|
||||
else if (thing->drawflags & MFD_SEMIBRIGHT)
|
||||
vis->cut |= SC_SEMIBRIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thing->frame & FF_FULLBRIGHT)
|
||||
vis->cut |= SC_FULLBRIGHT;
|
||||
else if (thing->frame & FF_SEMIBRIGHT)
|
||||
vis->cut |= SC_SEMIBRIGHT;
|
||||
}
|
||||
|
||||
if (vis->cut & SC_FULLBRIGHT
|
||||
if ((vis->cut & SC_FULLBRIGHT)
|
||||
&& (!vis->extra_colormap || !(vis->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES)))
|
||||
{
|
||||
// full bright: goggles
|
||||
|
|
@ -2047,8 +2057,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
vis->patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
|
||||
|
||||
// specific translucency
|
||||
// (no draw flags)
|
||||
if (thing->frame & FF_TRANSMASK)
|
||||
vis->transmap = (thing->frame & FF_TRANSMASK) - 0x10000 + transtables;
|
||||
vis->transmap = ((thing->frame & FF_TRANSMASK) - FF_TRANS10) + transtables;
|
||||
else
|
||||
vis->transmap = NULL;
|
||||
|
||||
|
|
@ -2078,7 +2089,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
|
|||
mobj_t *thing;
|
||||
precipmobj_t *precipthing; // Tails 08-25-2002
|
||||
INT32 lightnum;
|
||||
fixed_t limit_dist, hoop_limit_dist;
|
||||
fixed_t limit_dist;
|
||||
|
||||
if (rendermode != render_soft)
|
||||
return;
|
||||
|
|
@ -2809,37 +2820,19 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
|
|||
/* Check if thing may be drawn from our current view. */
|
||||
boolean R_ThingVisible (mobj_t *thing)
|
||||
{
|
||||
boolean split_drawsprite = true;
|
||||
UINT16 splitflags = 0;
|
||||
|
||||
if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW
|
||||
|| (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing))))
|
||||
if (thing->sprite == SPR_NULL)
|
||||
return false;
|
||||
|
||||
splitflags = thing->eflags & (MFE_DRAWONLYFORP1|MFE_DRAWONLYFORP2|MFE_DRAWONLYFORP3|MFE_DRAWONLYFORP4);
|
||||
if (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing)))
|
||||
return false;
|
||||
|
||||
if (r_splitscreen && splitflags)
|
||||
{
|
||||
split_drawsprite = false;
|
||||
if ((viewssnum == 0 && (thing->drawflags & MFD_DONTDRAWP1))
|
||||
|| (viewssnum == 1 && (thing->drawflags & MFD_DONTDRAWP2))
|
||||
|| (viewssnum == 2 && (thing->drawflags & MFD_DONTDRAWP3))
|
||||
|| (viewssnum == 3 && (thing->drawflags & MFD_DONTDRAWP4)))
|
||||
return false;
|
||||
|
||||
if (thing->eflags & MFE_DRAWONLYFORP1)
|
||||
if (viewssnum == 0)
|
||||
split_drawsprite = true;
|
||||
|
||||
if (thing->eflags & MFE_DRAWONLYFORP2)
|
||||
if (viewssnum == 1)
|
||||
split_drawsprite = true;
|
||||
|
||||
if (thing->eflags & MFE_DRAWONLYFORP3 && splitscreen > 1)
|
||||
if (viewssnum == 2)
|
||||
split_drawsprite = true;
|
||||
|
||||
if (thing->eflags & MFE_DRAWONLYFORP4 && splitscreen > 2)
|
||||
if (viewssnum == 3)
|
||||
split_drawsprite = true;
|
||||
}
|
||||
|
||||
return split_drawsprite;
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean R_ThingVisibleWithinDist (mobj_t *thing,
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ typedef struct vissprite_s
|
|||
lighttable_t *colormap; // for color translation and shadow draw
|
||||
// maxbright frames as well
|
||||
|
||||
UINT8 *transmap; // for MF2_SHADOW sprites, which translucency table to use
|
||||
UINT8 *transmap; // which translucency table to use
|
||||
|
||||
INT32 mobjflags;
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ ifndef NOTHREADS
|
|||
OBJS+=$(OBJDIR)/i_threads.o
|
||||
endif
|
||||
|
||||
ifndef NOTHREADS
|
||||
OPTS+=-DHAVE_THREADS
|
||||
OBJS+=$(OBJDIR)/i_threads.o
|
||||
endif
|
||||
|
||||
ifdef SDL_TTF
|
||||
OPTS+=-DHAVE_TTF
|
||||
SDL_LDFLAGS+=-lSDL2_ttf -lfreetype -lz
|
||||
|
|
|
|||
|
|
@ -234,6 +234,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" />
|
||||
|
|
@ -252,6 +253,7 @@
|
|||
<ClInclude Include="..\lzf.h" />
|
||||
<ClInclude Include="..\md5.h" />
|
||||
<ClInclude Include="..\mserv.h" />
|
||||
<ClInclude Include="..\http-mserv.h" />
|
||||
<ClInclude Include="..\m_aatree.h" />
|
||||
<ClInclude Include="..\m_anigif.h" />
|
||||
<ClInclude Include="..\m_argv.h" />
|
||||
|
|
@ -384,6 +386,7 @@
|
|||
<ClCompile Include="..\hardware\hw_model.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">
|
||||
|
|
@ -407,6 +410,7 @@
|
|||
<ClCompile Include="..\lzf.c" />
|
||||
<ClCompile Include="..\md5.c" />
|
||||
<ClCompile Include="..\mserv.c" />
|
||||
<ClCompile Include="..\http-mserv.c" />
|
||||
<ClCompile Include="..\m_aatree.c" />
|
||||
<ClCompile Include="..\m_anigif.c" />
|
||||
<ClCompile Include="..\m_argv.c" />
|
||||
|
|
|
|||
|
|
@ -297,6 +297,9 @@
|
|||
<ClInclude Include="..\mserv.h">
|
||||
<Filter>I_Interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\http-mserv.h">
|
||||
<Filter>I_Interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\lua_hook.h">
|
||||
<Filter>LUA</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -693,6 +696,9 @@
|
|||
<ClCompile Include="..\mserv.c">
|
||||
<Filter>I_Interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\http-mserv.c">
|
||||
<Filter>I_Interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lua_baselib.c">
|
||||
<Filter>LUA</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
|
|
@ -2742,6 +2786,50 @@
|
|||
RelativePath="..\mserv.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\http-mserv.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="..\http-mserv.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="M_Misc"
|
||||
|
|
|
|||
|
|
@ -1412,6 +1412,8 @@ static inline boolean I_SkipFrame(void)
|
|||
//
|
||||
void I_FinishUpdate(void)
|
||||
{
|
||||
int player;
|
||||
|
||||
if (rendermode == render_none)
|
||||
return; //Alam: No software or OpenGl surface
|
||||
|
||||
|
|
@ -1426,7 +1428,25 @@ void I_FinishUpdate(void)
|
|||
if (cv_showping.value && netgame &&
|
||||
( consoleplayer != serverplayer || ! server_lagless ))
|
||||
{
|
||||
SCR_DisplayLocalPing();
|
||||
if (server_lagless)
|
||||
{
|
||||
if (consoleplayer != serverplayer)
|
||||
SCR_DisplayLocalPing();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (
|
||||
player = 1;
|
||||
player < MAXPLAYERS;
|
||||
player++
|
||||
){
|
||||
if (D_IsPlayerHumanAndGaming(player))
|
||||
{
|
||||
SCR_DisplayLocalPing();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#endif
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../d_main.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "../hardware/r_opengl/r_opengl.h"
|
||||
|
|
@ -155,11 +156,26 @@ boolean OglSdlSurface(INT32 w, INT32 h)
|
|||
{
|
||||
INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value;
|
||||
static boolean first_init = false;
|
||||
const char *gllogdir = NULL;
|
||||
|
||||
oglflags = 0;
|
||||
|
||||
if (!first_init)
|
||||
{
|
||||
if (!gllogstream)
|
||||
{
|
||||
gllogdir = D_Home();
|
||||
|
||||
#ifdef DEBUG_TO_FILE
|
||||
#ifdef DEFAULTDIR
|
||||
if (gllogdir)
|
||||
gllogstream = fopen(va("%s/"DEFAULTDIR"/ogllog.txt",gllogdir), "wt");
|
||||
else
|
||||
#endif
|
||||
gllogstream = fopen("./ogllog.txt", "wt");
|
||||
#endif
|
||||
}
|
||||
|
||||
gl_version = pglGetString(GL_VERSION);
|
||||
gl_renderer = pglGetString(GL_RENDERER);
|
||||
gl_extensions = pglGetString(GL_EXTENSIONS);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -877,8 +877,8 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"bfare", false, 128, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pleasure Castle fanfare
|
||||
{"merry", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pleasure Castle merry-go-round ambient
|
||||
{"bowlh", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pleasure Castle pins
|
||||
{"tppop", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},// Pleasure Castle bombs
|
||||
{"hsdoor", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},// Red Barrage Area door
|
||||
{"tppop", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pleasure Castle bombs
|
||||
{"hsdoor", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Red Barrage Area door
|
||||
{"hstrn", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Red Barrage Area train
|
||||
{"aspkb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Red Barrage Area spikeballs
|
||||
{"wind1", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Midnight Channel monsters
|
||||
|
|
@ -891,6 +891,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"sploss", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Down to yellow sparks
|
||||
{"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // :shitsfree:
|
||||
{"dbgsal", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Debug notification
|
||||
{"cock", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Hammer cocks, bang bang
|
||||
|
||||
// SRB2Kart - Engine sounds
|
||||
// Engine class A
|
||||
|
|
|
|||
|
|
@ -954,6 +954,7 @@ typedef enum
|
|||
sfx_sploss,
|
||||
sfx_itfree,
|
||||
sfx_dbgsal,
|
||||
sfx_cock,
|
||||
|
||||
// Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy...
|
||||
// Engine class A - Low Speed, Low Weight
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include "m_misc.h" // moviemode
|
||||
#include "m_anigif.h" // cv_gif_downscale
|
||||
#include "p_setup.h" // NiGHTS grading
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_hud.h" // SRB2kart
|
||||
|
||||
//random index
|
||||
#include "m_random.h"
|
||||
|
|
@ -884,11 +884,11 @@ static void ST_overlayDrawer(void)
|
|||
|
||||
INT32 y = (stplyr == &players[displayplayers[0]]) ? 4 : BASEVIDHEIGHT/2-12;
|
||||
sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]);
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT), name);
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN, name);
|
||||
}
|
||||
else if (r_splitscreen)
|
||||
{
|
||||
V_DrawCenteredThinString((vid.width/vid.dupx)/4, BASEVIDHEIGHT/2 - 12, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT), player_names[stplyr-players]);
|
||||
V_DrawCenteredThinString((vid.width/vid.dupx)/4, BASEVIDHEIGHT/2 - 12, V_HUDTRANSHALF|V_ALLOWLOWERCASE|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN, player_names[stplyr-players]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -933,16 +933,15 @@ static void ST_overlayDrawer(void)
|
|||
// SRB2kart: changed positions & text
|
||||
if (r_splitscreen)
|
||||
{
|
||||
INT32 splitflags = K_calcSplitFlags(0);
|
||||
V_DrawThinString(2, (BASEVIDHEIGHT/2)-20, V_YELLOWMAP|V_HUDTRANSHALF|splitflags, M_GetText("- SPECTATING -"));
|
||||
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, itemtxt);
|
||||
V_DrawThinString(2, (BASEVIDHEIGHT/2)-20, V_YELLOWMAP|V_HUDTRANSHALF|V_SPLITSCREEN, M_GetText("- SPECTATING -"));
|
||||
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|V_SPLITSCREEN, itemtxt);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, itemtxt);
|
||||
V_DrawString(2, BASEVIDHEIGHT-20, V_HUDTRANSHALF, M_GetText("Accelerate - Float"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-10, V_HUDTRANSHALF, M_GetText("Brake - Sink"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_SPLITSCREEN|V_YELLOWMAP, M_GetText("- SPECTATING -"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF|V_SPLITSCREEN, itemtxt);
|
||||
V_DrawString(2, BASEVIDHEIGHT-20, V_HUDTRANSHALF|V_SPLITSCREEN, M_GetText("Accelerate - Float"));
|
||||
V_DrawString(2, BASEVIDHEIGHT-10, V_HUDTRANSHALF|V_SPLITSCREEN, M_GetText("Brake - Sink"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ extern INT32 st_translucency;
|
|||
|
||||
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;
|
||||
|
|
|
|||
1637
src/v_video.c
1637
src/v_video.c
File diff suppressed because it is too large
Load diff
|
|
@ -135,9 +135,9 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
|
|||
#define V_WRAPX 0x08000000 // Don't clamp texture on X (for HW mode)
|
||||
#define V_WRAPY 0x10000000 // Don't clamp texture on Y (for HW mode)
|
||||
|
||||
#define V_NOSCALESTART 0x20000000 // don't scale x, y, start coords
|
||||
#define V_SPLITSCREEN 0x40000000
|
||||
#define V_HORZSCREEN 0x80000000
|
||||
#define V_NOSCALESTART 0x20000000 // don't scale x, y, start coords
|
||||
#define V_SPLITSCREEN 0x40000000 // Add half of screen width or height automatically depending on player number
|
||||
#define V_SLIDEIN 0x80000000 // Slide in from the sides on level load, depending on snap flags
|
||||
|
||||
// defines for old functions
|
||||
#define V_DrawPatch(x,y,s,p) V_DrawFixedPatch((x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, s|V_NOSCALESTART|V_NOSCALEPATCH, p, NULL)
|
||||
|
|
@ -187,6 +187,12 @@ void V_EncoreInvertScreen(void);
|
|||
|
||||
void V_DrawPromptBack(INT32 boxheight, INT32 color);
|
||||
|
||||
/* 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
|
||||
|
|
@ -194,51 +200,48 @@ 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_DrawCenteredSmallString(INT32 x, INT32 y, INT32 option, const char *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);
|
||||
|
||||
// draw a string using the tny_font, 0.5x scale
|
||||
void V_DrawSmallThinString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
void V_DrawCenteredSmallThinString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
void V_DrawRightAlignedSmallThinString(INT32 x, INT32 y, INT32 option, const char *string);
|
||||
#define V_DrawStringAtFixed( x,y,option,string ) \
|
||||
V__DrawOneScaleString (x,y,FRACUNIT,option,HU_FONT,string)
|
||||
|
||||
// draw a string using the hu_font at fixed_t coordinates
|
||||
void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
|
||||
// draw a string using the hu_font at fixed_t coordinates, 0.5x scale
|
||||
void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
void V_DrawCenteredSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
void V_DrawRightAlignedSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
|
||||
// draw a string using the tny_font at fixed_t coordinates
|
||||
void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
|
||||
// draw a string using the tny_font at fixed_t coordinates, 0.5x scale
|
||||
void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
void V_DrawCenteredSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
|
||||
void V_DrawRightAlignedSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *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);
|
||||
|
|
@ -254,7 +257,8 @@ INT32 V_LevelNameWidth(const char *string);
|
|||
INT32 V_LevelNameHeight(const char *string);
|
||||
INT16 V_LevelActNumWidth(UINT8 num); // act number width
|
||||
|
||||
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);
|
||||
|
||||
// Draw a string using the nt_font
|
||||
|
|
|
|||
|
|
@ -1473,7 +1473,6 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
|||
size = 0;
|
||||
zerr(zErr);
|
||||
}
|
||||
|
||||
(void)inflateEnd(&strm);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@
|
|||
<ClCompile Include="..\hardware\hw_md3load.c" />
|
||||
<ClCompile Include="..\hardware\hw_model.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">
|
||||
|
|
@ -406,6 +407,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" />
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
|
|
|
|||
194
src/y_inter.c
194
src/y_inter.c
|
|
@ -45,6 +45,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"
|
||||
|
|
@ -197,7 +198,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;
|
||||
|
|
@ -301,18 +307,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],
|
||||
|
|
@ -320,6 +334,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++;
|
||||
}
|
||||
|
|
@ -507,9 +522,36 @@ dontdrawbg:
|
|||
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_battle && battlecapsules)) ? "TIME" : "SCORE");
|
||||
{
|
||||
switch (intertype)
|
||||
{
|
||||
default:
|
||||
case int_race:
|
||||
timeheader = "TIME";
|
||||
break;
|
||||
case int_battle:
|
||||
if (battlecapsules)
|
||||
{
|
||||
timeheader = "TIME";
|
||||
}
|
||||
else
|
||||
{
|
||||
timeheader = "SCORE";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the level name
|
||||
V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12, 0, data.match.levelstring);
|
||||
|
|
@ -600,8 +642,11 @@ dontdrawbg:
|
|||
|
||||
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)
|
||||
|
|
@ -670,7 +715,7 @@ skiptallydrawer:
|
|||
if (!LUA_HudEnabled(hud_intermissionmessages))
|
||||
return;
|
||||
|
||||
if (timer)
|
||||
if (timer && grandprixinfo.gp == false)
|
||||
{
|
||||
char *string;
|
||||
INT32 tickdown = (timer+1)/TICRATE;
|
||||
|
|
@ -774,74 +819,73 @@ void Y_Ticker(void)
|
|||
|
||||
if (intertype == int_race || intertype == int_battle)
|
||||
{
|
||||
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 if (!(intertic & 1))
|
||||
|
|
@ -1159,19 +1203,11 @@ void Y_StartIntermission(void)
|
|||
#endif
|
||||
|
||||
// set player Power Level type
|
||||
powertype = PWRLV_DISABLED;
|
||||
|
||||
if (netgame && cv_kartusepwrlv.value)
|
||||
{
|
||||
if ((gametyperules & GTR_CIRCUIT))
|
||||
powertype = PWRLV_RACE;
|
||||
else if ((gametyperules & GTR_BUMPERS))
|
||||
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
|
||||
{
|
||||
|
|
@ -1190,7 +1226,7 @@ void Y_StartIntermission(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (cv_inttime.value == 0 && ((intertype == int_coop) || (intertype == int_spec)))
|
||||
if (cv_inttime.value == 0)
|
||||
timer = 0;
|
||||
else if (demo.playback) // Override inttime (which is pulled from the replay anyway
|
||||
timer = 10*TICRATE;
|
||||
|
|
@ -1205,10 +1241,8 @@ void Y_StartIntermission(void)
|
|||
|
||||
if (intermissiontypes[gametype] != int_none)
|
||||
intertype = intermissiontypes[gametype];
|
||||
else if (gametype == GT_RACE)
|
||||
intertype = int_race;
|
||||
else if (gametype == GT_BATTLE)
|
||||
intertype = int_battle;
|
||||
|
||||
sorttic = max((timer/2) - 2*TICRATE, 2*TICRATE); // 8 second pause after match results
|
||||
|
||||
// We couldn't display the intermission even if we wanted to.
|
||||
// But we still need to give the players their score bonuses, dummy.
|
||||
|
|
@ -1250,7 +1284,9 @@ void Y_StartIntermission(void)
|
|||
}
|
||||
|
||||
if (powertype != PWRLV_DISABLED)
|
||||
{
|
||||
K_UpdatePowerLevels();
|
||||
}
|
||||
|
||||
//if (intertype == int_race || intertype == int_battle)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue