mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-01-11 17:22:17 +00:00
Merge branch 'master' into sal-waypoints
This commit is contained in:
commit
e7d0fde5fd
45 changed files with 2158 additions and 1020 deletions
|
|
@ -60,6 +60,7 @@
|
|||
# Compile with GCC 4.6x version, add 'GCC46=1'
|
||||
# Compile a profile version, add 'PROFILEMODE=1'
|
||||
# Compile a debug version, add 'DEBUGMODE=1'
|
||||
# Compile for the testers group (they don't get to play unless we're watching *wink*), add 'TESTERS=1'
|
||||
# Compile with extra warnings, add 'WARNINGMODE=1'
|
||||
# Compile without NASM's tmap.nas, add 'NOASM=1'
|
||||
# Compile without 3D hardware support, add 'NOHW=1'
|
||||
|
|
@ -434,6 +435,10 @@ else
|
|||
endif
|
||||
CFLAGS+=-g $(OPTS) $(ARCHOPTS) $(WINDRESFLAGS)
|
||||
|
||||
ifdef TESTERS
|
||||
OPTS+=-DTESTERS
|
||||
endif
|
||||
|
||||
ifdef YASM
|
||||
ifdef STABS
|
||||
NASMOPTS?= -g stabs
|
||||
|
|
@ -492,6 +497,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/k_waypoint.o\
|
||||
$(OBJDIR)/k_pathfind.o\
|
||||
$(OBJDIR)/k_bheap.o \
|
||||
$(OBJDIR)/k_pwrlv.o \
|
||||
$(OBJDIR)/m_aatree.o \
|
||||
$(OBJDIR)/m_anigif.o \
|
||||
$(OBJDIR)/m_argv.o \
|
||||
|
|
|
|||
|
|
@ -70,8 +70,12 @@ CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
|
|||
|
||||
//SRB2kart
|
||||
CV_PossibleValue_t kartspeed_cons_t[] = {
|
||||
{0, "Easy"}, {1, "Normal"}, {2, "Hard"},
|
||||
{0, NULL}};
|
||||
{-1, "Auto"},
|
||||
{0, "Easy"},
|
||||
{1, "Normal"},
|
||||
{2, "Hard"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
// Filter consvars by EXECVERSION
|
||||
// First implementation is 2 (1.0.2), so earlier configs default at 1 (1.0.0)
|
||||
|
|
@ -1769,7 +1773,7 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
{
|
||||
newvalue = var->value + 1;
|
||||
if (newvalue > maxspeed)
|
||||
newvalue = 0;
|
||||
newvalue = -1;
|
||||
var->value = newvalue;
|
||||
var->string = var->PossibleValue[var->value].strvalue;
|
||||
var->func();
|
||||
|
|
@ -1778,7 +1782,7 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
else if (increment < 0) // Going down!
|
||||
{
|
||||
newvalue = var->value - 1;
|
||||
if (newvalue < 0)
|
||||
if (newvalue < -1)
|
||||
newvalue = maxspeed;
|
||||
var->value = newvalue;
|
||||
var->string = var->PossibleValue[var->value].strvalue;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
#ifdef CLIENT_LOADINGSCREEN
|
||||
// cl loading screen
|
||||
|
|
@ -1350,7 +1351,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
|
||||
|
||||
netbuffer->u.serverinfo.kartvars = (UINT8) (
|
||||
(cv_kartspeed.value & SV_SPEEDMASK) |
|
||||
(gamespeed & SV_SPEEDMASK) |
|
||||
(dedicated ? SV_DEDICATED : 0) |
|
||||
(D_IsJoinPasswordOn() ? SV_PASSWORD : 0)
|
||||
);
|
||||
|
|
@ -1420,6 +1421,11 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
|
||||
p = PutFileNeeded(0);
|
||||
|
||||
if (cv_kartusepwrlv.value)
|
||||
netbuffer->u.serverinfo.avgpwrlv = K_CalculatePowerLevelAvg();
|
||||
else
|
||||
netbuffer->u.serverinfo.avgpwrlv = -1;
|
||||
|
||||
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u));
|
||||
}
|
||||
|
||||
|
|
@ -1494,7 +1500,7 @@ static void SV_SendPlayerInfo(INT32 node)
|
|||
*/
|
||||
static boolean SV_SendServerConfig(INT32 node)
|
||||
{
|
||||
INT32 i;
|
||||
INT32 i, j;
|
||||
UINT8 *p, *op;
|
||||
boolean waspacketsent;
|
||||
|
||||
|
|
@ -1517,10 +1523,13 @@ static boolean SV_SendServerConfig(INT32 node)
|
|||
memset(netbuffer->u.servercfg.playercolor, 0xFF, sizeof(netbuffer->u.servercfg.playercolor));
|
||||
|
||||
memset(netbuffer->u.servercfg.adminplayers, -1, sizeof(netbuffer->u.servercfg.adminplayers));
|
||||
memset(netbuffer->u.servercfg.powerlevels, 0, sizeof(netbuffer->u.servercfg.powerlevels));
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
netbuffer->u.servercfg.adminplayers[i] = (SINT8)adminplayers[i];
|
||||
for (j = 0; j < PWRLV_NUMTYPES; j++)
|
||||
netbuffer->u.servercfg.powerlevels[i][j] = clientpowerlevels[i][j];
|
||||
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
|
@ -2306,6 +2315,7 @@ static void CL_ConnectToServer(boolean viams)
|
|||
wipegamestate = GS_WAITINGPLAYERS;
|
||||
|
||||
ClearAdminPlayers();
|
||||
K_ClearClientPowerLevels();
|
||||
pnumnodes = 1;
|
||||
oldtic = I_GetTime() - 1;
|
||||
#ifndef NONET
|
||||
|
|
@ -3156,6 +3166,21 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
break;
|
||||
}
|
||||
|
||||
// SRB2Kart: kicks count as forfeit
|
||||
switch (kickreason)
|
||||
{
|
||||
case KR_KICK:
|
||||
case KR_BAN:
|
||||
case KR_LEAVE:
|
||||
// Intentional removals should be hit with a true forfeit.
|
||||
K_PlayerForfeit(pnum, true);
|
||||
break;
|
||||
default:
|
||||
// Otherwise, give remaining players the point compensation, but doesn't penalize who left.
|
||||
K_PlayerForfeit(pnum, false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (playernode[pnum] == playernode[consoleplayer])
|
||||
{
|
||||
#ifdef DUMPCONSISTENCY
|
||||
|
|
@ -3324,6 +3349,7 @@ void SV_ResetServer(void)
|
|||
playernode[i] = UINT8_MAX;
|
||||
sprintf(player_names[i], "Player %d", i + 1);
|
||||
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
|
||||
K_ClearClientPowerLevels();
|
||||
}
|
||||
|
||||
mynode = 0;
|
||||
|
|
@ -3399,6 +3425,7 @@ void D_QuitNetGame(void)
|
|||
|
||||
D_CloseConnection();
|
||||
ClearAdminPlayers();
|
||||
K_ClearClientPowerLevels();
|
||||
|
||||
DEBFILE("===========================================================================\n"
|
||||
" Log finish\n"
|
||||
|
|
@ -3445,11 +3472,12 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
node = READUINT8(*p);
|
||||
newplayernum = READUINT8(*p);
|
||||
splitscreenplayer = newplayernum/MAXPLAYERS;
|
||||
newplayernum %= MAXPLAYERS;
|
||||
node = (UINT8)READUINT8(*p);
|
||||
newplayernum = (UINT8)READUINT8(*p);
|
||||
splitscreenplayer = (UINT8)READUINT8(*p);
|
||||
|
||||
CONS_Debug(DBG_NETPLAY, "addplayer: %d %d %d\n", node, newplayernum, splitscreenplayer);
|
||||
|
||||
// Clear player before joining, lest some things get set incorrectly
|
||||
CL_ClearPlayer(newplayernum);
|
||||
|
||||
|
|
@ -3466,7 +3494,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
if (splitscreenplayer)
|
||||
{
|
||||
displayplayers[splitscreenplayer] = newplayernum;
|
||||
DEBFILE(va("spawning one of my sister number %d\n", splitscreenplayer));
|
||||
DEBFILE(va("spawning sister # %d\n", splitscreenplayer));
|
||||
if (splitscreenplayer == 1 && botingame)
|
||||
players[newplayernum].bot = 1;
|
||||
}
|
||||
|
|
@ -3477,6 +3505,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
displayplayers[i] = newplayernum;
|
||||
DEBFILE("spawning me\n");
|
||||
}
|
||||
|
||||
D_SendPlayerConfig();
|
||||
addedtogame = true;
|
||||
}
|
||||
|
|
@ -3532,7 +3561,6 @@ static void Got_RemovePlayer(UINT8 **p, INT32 playernum)
|
|||
static boolean SV_AddWaitingPlayers(void)
|
||||
{
|
||||
INT32 node, n, newplayer = false;
|
||||
XBOXSTATIC UINT8 buf[2];
|
||||
UINT8 newplayernum = 0;
|
||||
|
||||
// What is the reason for this? Why can't newplayernum always be 0?
|
||||
|
|
@ -3545,6 +3573,9 @@ static boolean SV_AddWaitingPlayers(void)
|
|||
// splitscreen can allow 2+ players in one node
|
||||
for (; nodewaiting[node] > 0; nodewaiting[node]--)
|
||||
{
|
||||
UINT8 buf[3];
|
||||
UINT8 *buf_p = buf;
|
||||
|
||||
newplayer = true;
|
||||
|
||||
// search for a free playernum
|
||||
|
|
@ -3552,8 +3583,10 @@ static boolean SV_AddWaitingPlayers(void)
|
|||
for (; newplayernum < MAXPLAYERS; newplayernum++)
|
||||
{
|
||||
for (n = 0; n < MAXNETNODES; n++)
|
||||
if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum
|
||||
|| nodetoplayer3[n] == newplayernum || nodetoplayer4[n] == newplayernum)
|
||||
if (nodetoplayer[n] == newplayernum
|
||||
|| nodetoplayer2[n] == newplayernum
|
||||
|| nodetoplayer3[n] == newplayernum
|
||||
|| nodetoplayer4[n] == newplayernum)
|
||||
break;
|
||||
if (n == MAXNETNODES)
|
||||
break;
|
||||
|
|
@ -3565,28 +3598,23 @@ static boolean SV_AddWaitingPlayers(void)
|
|||
|
||||
playernode[newplayernum] = (UINT8)node;
|
||||
|
||||
buf[0] = (UINT8)node;
|
||||
buf[1] = newplayernum;
|
||||
WRITEUINT8(buf_p, (UINT8)node);
|
||||
WRITEUINT8(buf_p, newplayernum);
|
||||
|
||||
if (playerpernode[node] < 1)
|
||||
nodetoplayer[node] = newplayernum;
|
||||
else if (playerpernode[node] < 2)
|
||||
{
|
||||
nodetoplayer2[node] = newplayernum;
|
||||
buf[1] += MAXPLAYERS;
|
||||
}
|
||||
else if (playerpernode[node] < 3)
|
||||
{
|
||||
nodetoplayer3[node] = newplayernum;
|
||||
buf[1] += MAXPLAYERS*2;
|
||||
}
|
||||
else
|
||||
{
|
||||
else if (playerpernode[node] < 4)
|
||||
nodetoplayer4[node] = newplayernum;
|
||||
buf[1] += MAXPLAYERS*3;
|
||||
}
|
||||
|
||||
WRITEUINT8(buf_p, playerpernode[node]); // splitscreen num
|
||||
|
||||
playerpernode[node]++;
|
||||
|
||||
SendNetXCmd(XD_ADDPLAYER, &buf, 2);
|
||||
SendNetXCmd(XD_ADDPLAYER, buf, buf_p - buf);
|
||||
|
||||
DEBFILE(va("Server added player %d node %d\n", newplayernum, node));
|
||||
// use the next free slot (we can't put playeringame[newplayernum] = true here)
|
||||
|
|
@ -3623,6 +3651,11 @@ boolean Playing(void)
|
|||
|
||||
boolean SV_SpawnServer(void)
|
||||
{
|
||||
#ifdef TESTERS
|
||||
/* Just don't let the testers play. Easy. */
|
||||
I_Error("What do you think you're doing?");
|
||||
return false;
|
||||
#else
|
||||
if (demo.playback)
|
||||
G_StopDemo(); // reset engine parameter
|
||||
if (metalplayback)
|
||||
|
|
@ -3649,6 +3682,7 @@ boolean SV_SpawnServer(void)
|
|||
}
|
||||
|
||||
return SV_AddWaitingPlayers();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SV_StopServer(void)
|
||||
|
|
@ -4075,7 +4109,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
|
||||
case PT_SERVERCFG: // Positive response of client join request
|
||||
{
|
||||
INT32 j;
|
||||
INT32 j, k;
|
||||
UINT8 *scp;
|
||||
|
||||
if (server && serverrunning && node != servernode)
|
||||
|
|
@ -4098,7 +4132,11 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
I_Error("Bad gametype in cliserv!");
|
||||
modifiedgame = netbuffer->u.servercfg.modifiedgame;
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
adminplayers[j] = netbuffer->u.servercfg.adminplayers[j];
|
||||
for (k = 0; k < PWRLV_NUMTYPES; k++)
|
||||
clientpowerlevels[j][k] = netbuffer->u.servercfg.powerlevels[j][k];
|
||||
}
|
||||
memcpy(server_context, netbuffer->u.servercfg.server_context, 8);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "d_netcmd.h"
|
||||
#include "tables.h"
|
||||
#include "d_player.h"
|
||||
#include "k_pwrlv.h" // PWRLV_NUMTYPES
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
|
|
@ -325,6 +326,7 @@ typedef struct
|
|||
UINT8 gametype;
|
||||
UINT8 modifiedgame;
|
||||
SINT8 adminplayers[MAXPLAYERS]; // Needs to be signed
|
||||
UINT16 powerlevels[MAXPLAYERS][PWRLV_NUMTYPES]; // SRB2kart: player power levels
|
||||
|
||||
char server_context[8]; // Unique context id, generated at server startup.
|
||||
|
||||
|
|
@ -387,6 +389,10 @@ typedef struct
|
|||
UINT8 actnum;
|
||||
UINT8 iszone;
|
||||
UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
|
||||
// Anything beyond this point won't be read by the normal SRB2 Master Server display.
|
||||
// The MS uses a simple unpack, so the size of the packet above shouldn't be changed, either.
|
||||
// As long as those two conditions are met, we can add as much information as we want to the end.
|
||||
INT16 avgpwrlv; // Kart avg power level
|
||||
} ATTRPACK serverinfo_pak;
|
||||
|
||||
typedef struct
|
||||
|
|
|
|||
13
src/d_main.c
13
src/d_main.c
|
|
@ -308,13 +308,6 @@ static void D_Display(void)
|
|||
wipedefindex = gamestate; // wipe_xxx_toblack
|
||||
if (gamestate == GS_TITLESCREEN && wipegamestate != GS_INTRO)
|
||||
wipedefindex = wipe_timeattack_toblack;
|
||||
else if (gamestate == GS_INTERMISSION)
|
||||
{
|
||||
if (intertype == int_spec) // Special Stage
|
||||
wipedefindex = wipe_specinter_toblack;
|
||||
else //if (intertype != int_coop) // Multiplayer
|
||||
wipedefindex = wipe_multinter_toblack;
|
||||
}
|
||||
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
|
|
@ -325,7 +318,7 @@ static void D_Display(void)
|
|||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK, "FADEMAP0", false, false);
|
||||
}
|
||||
|
||||
if (gamestate != GS_LEVEL && rendermode != render_none)
|
||||
|
|
@ -556,7 +549,7 @@ static void D_Display(void)
|
|||
if (rendermode != render_none)
|
||||
{
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
||||
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK, "FADEMAP0", true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1566,7 +1559,7 @@ void D_SRB2Main(void)
|
|||
else if (!dedicated && M_MapLocked(pstartmap))
|
||||
I_Error("You need to unlock this level before you can warp to it!\n");
|
||||
else
|
||||
D_MapChange(pstartmap, gametype, (boolean)cv_kartencore.value, true, 0, false, false);
|
||||
D_MapChange(pstartmap, gametype, (cv_kartencore.value == 1), true, 0, false, false);
|
||||
}
|
||||
}
|
||||
else if (M_CheckParm("-skipintro"))
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "m_cond.h"
|
||||
#include "m_anigif.h"
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_pwrlv.h"
|
||||
#include "y_inter.h"
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
|
|
@ -61,6 +62,7 @@
|
|||
|
||||
static void Got_NameAndColor(UINT8 **cp, INT32 playernum);
|
||||
static void Got_WeaponPref(UINT8 **cp, INT32 playernum);
|
||||
static void Got_PowerLevel(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Mapcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum);
|
||||
|
|
@ -358,12 +360,13 @@ consvar_t cv_kartminimap = {"kartminimap", "4", CV_SAVE, kartminimap_cons_t, NUL
|
|||
consvar_t cv_kartcheck = {"kartcheck", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartinvinsfx_cons_t[] = {{0, "Music"}, {1, "SFX"}, {0, NULL}};
|
||||
consvar_t cv_kartinvinsfx = {"kartinvinsfx", "SFX", CV_SAVE, kartinvinsfx_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_kartspeed = {"kartspeed", "Normal", CV_NETVAR|CV_CALL|CV_NOINIT, kartspeed_cons_t, KartSpeed_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_kartspeed = {"kartspeed", "Auto", CV_NETVAR|CV_CALL|CV_NOINIT, kartspeed_cons_t, KartSpeed_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartbumpers_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_kartbumpers = {"kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartencore_cons_t[] = {{-1, "Auto"}, {0, "Off"}, {1, "On"}, {0, NULL}};
|
||||
consvar_t cv_kartencore = {"kartencore", "Auto", CV_NETVAR|CV_CALL|CV_NOINIT, kartencore_cons_t, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}};
|
||||
consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Percentage"}, {2, "Kilometers"}, {3, "Miles"}, {4, "Fracunits"}, {0, NULL}};
|
||||
|
|
@ -373,6 +376,8 @@ consvar_t cv_kartvoices = {"kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t,
|
|||
|
||||
consvar_t cv_karteliminatelast = {"karteliminatelast", "Yes", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOSHOWHELP, CV_YesNo, KartEliminateLast_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_kartusepwrlv = {"kartusepwrlv", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t kartdebugitem_cons_t[] = {{-1, "MIN"}, {NUMKARTITEMS-1, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_kartdebugitem = {"kartdebugitem", "0", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, kartdebugitem_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t kartdebugamount_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}};
|
||||
|
|
@ -411,7 +416,8 @@ consvar_t cv_itemfinder = {"itemfinder", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff,
|
|||
|
||||
// Scoring type options
|
||||
consvar_t cv_match_scoring = {"matchscoring", "Normal", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, match_scoring_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t overtime_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Super"}, {0, NULL}};
|
||||
consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR|CV_CHEAT, overtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
|
@ -501,6 +507,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
|
|||
"MODIFYVOTE",
|
||||
"PICKVOTE",
|
||||
"REMOVEPLAYER",
|
||||
"POWERLEVEL",
|
||||
#ifdef HAVE_BLUA
|
||||
"LUACMD",
|
||||
"LUAVAR"
|
||||
|
|
@ -538,6 +545,7 @@ void D_RegisterServerCommands(void)
|
|||
}
|
||||
RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor);
|
||||
RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref);
|
||||
RegisterNetXCmd(XD_POWERLEVEL, Got_PowerLevel);
|
||||
RegisterNetXCmd(XD_MAP, Got_Mapcmd);
|
||||
RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd);
|
||||
RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd);
|
||||
|
|
@ -1915,6 +1923,17 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum)
|
|||
players[playernum].pflags |= PF_FLIPCAM;
|
||||
}
|
||||
|
||||
static void Got_PowerLevel(UINT8 **cp,INT32 playernum)
|
||||
{
|
||||
UINT16 race = (UINT16)READUINT16(*cp);
|
||||
UINT16 battle = (UINT16)READUINT16(*cp);
|
||||
|
||||
clientpowerlevels[playernum][PWRLV_RACE] = min(PWRLVRECORD_MAX, race);
|
||||
clientpowerlevels[playernum][PWRLV_BATTLE] = min(PWRLVRECORD_MAX, battle);
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "set player %d to power %d\n", playernum, race);
|
||||
}
|
||||
|
||||
void D_SendPlayerConfig(void)
|
||||
{
|
||||
SendNameAndColor();
|
||||
|
|
@ -1931,6 +1950,31 @@ void D_SendPlayerConfig(void)
|
|||
SendWeaponPref3();
|
||||
if (splitscreen > 2)
|
||||
SendWeaponPref4();
|
||||
|
||||
{
|
||||
UINT8 buf[4];
|
||||
UINT8 *buf_p = buf;
|
||||
|
||||
WRITEUINT16(buf_p, vspowerlevel[PWRLV_RACE]);
|
||||
WRITEUINT16(buf_p, vspowerlevel[PWRLV_BATTLE]);
|
||||
|
||||
SendNetXCmd(XD_POWERLEVEL, buf, 4);
|
||||
}
|
||||
|
||||
if (splitscreen)
|
||||
{
|
||||
UINT8 buf[4];
|
||||
UINT8 *buf_p = buf;
|
||||
|
||||
WRITEUINT16(buf_p, 0);
|
||||
WRITEUINT16(buf_p, 0);
|
||||
|
||||
SendNetXCmd2(XD_POWERLEVEL, buf, 4);
|
||||
if (splitscreen > 1)
|
||||
SendNetXCmd3(XD_POWERLEVEL, buf, 4);
|
||||
if (splitscreen > 2)
|
||||
SendNetXCmd4(XD_POWERLEVEL, buf, 4);
|
||||
}
|
||||
}
|
||||
|
||||
// Only works for displayplayer, sorry!
|
||||
|
|
@ -2343,7 +2387,7 @@ void D_SetupVote(void)
|
|||
UINT8 secondgt = G_SometimesGetDifferentGametype();
|
||||
INT16 votebuffer[3] = {-1,-1,-1};
|
||||
|
||||
if (cv_kartencore.value && G_RaceGametype())
|
||||
if ((cv_kartencore.value == 1) && G_RaceGametype())
|
||||
WRITEUINT8(p, (gametype|0x80));
|
||||
else
|
||||
WRITEUINT8(p, gametype);
|
||||
|
|
@ -2514,7 +2558,7 @@ static void Command_Map_f(void)
|
|||
// new encoremode value
|
||||
// use cvar by default
|
||||
|
||||
newencoremode = (boolean)cv_kartencore.value;
|
||||
newencoremode = (cv_kartencore.value == 1);
|
||||
|
||||
if (COM_CheckParm("-encore"))
|
||||
{
|
||||
|
|
@ -3641,6 +3685,9 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
|||
if (K_IsPlayerWanted(&players[playernum]))
|
||||
K_CalculateBattleWanted();
|
||||
}
|
||||
|
||||
K_PlayerForfeit(playernum, true);
|
||||
|
||||
players[playernum].health = 1;
|
||||
if (players[playernum].mo)
|
||||
players[playernum].mo->health = 1;
|
||||
|
|
@ -4735,8 +4782,8 @@ static void TimeLimit_OnChange(void)
|
|||
|
||||
if (cv_timelimit.value != 0)
|
||||
{
|
||||
CONS_Printf(M_GetText("Levels will end after %d minute%s.\n"),cv_timelimit.value,cv_timelimit.value == 1 ? "" : "s"); // Graue 11-17-2003
|
||||
timelimitintics = cv_timelimit.value * 60 * TICRATE;
|
||||
CONS_Printf(M_GetText("Levels will end after %d second%s.\n"),cv_timelimit.value,cv_timelimit.value == 1 ? "" : "s"); // Graue 11-17-2003
|
||||
timelimitintics = cv_timelimit.value * TICRATE;
|
||||
|
||||
//add hidetime for tag too!
|
||||
if (G_TagGametype())
|
||||
|
|
@ -4786,9 +4833,9 @@ void D_GameTypeChanged(INT32 lastgametype)
|
|||
case GT_TEAMMATCH:
|
||||
if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits
|
||||
{
|
||||
// default settings for match: no timelimit, no pointlimit
|
||||
CV_SetValue(&cv_pointlimit, 0);
|
||||
CV_SetValue(&cv_timelimit, 0);
|
||||
// default settings for match: 2 mins, no pointlimit
|
||||
CV_SetValue(&cv_pointlimit, 0);
|
||||
CV_SetValue(&cv_timelimit, 120);
|
||||
}
|
||||
if (!cv_itemrespawntime.changed)
|
||||
CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally
|
||||
|
|
@ -5094,7 +5141,7 @@ static void Hidetime_OnChange(void)
|
|||
|
||||
//uh oh, gotta change timelimitintics now too
|
||||
if (G_TagGametype())
|
||||
timelimitintics = (cv_timelimit.value * 60 * TICRATE) + (hidetime * TICRATE);
|
||||
timelimitintics = (cv_timelimit.value * TICRATE) + (hidetime * TICRATE);
|
||||
}
|
||||
|
||||
static void Command_Showmap_f(void)
|
||||
|
|
@ -5727,7 +5774,7 @@ static void KartSpeed_OnChange(void)
|
|||
if (!M_SecretUnlocked(SECRET_HARDSPEED) && cv_kartspeed.value == 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("You haven't earned this yet.\n"));
|
||||
CV_StealthSetValue(&cv_kartspeed, 1);
|
||||
CV_StealthSet(&cv_kartspeed, cv_kartspeed.defaultvalue);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -5747,10 +5794,10 @@ static void KartEncore_OnChange(void)
|
|||
{
|
||||
if (G_RaceGametype())
|
||||
{
|
||||
if ((boolean)cv_kartencore.value != encoremode && gamestate == GS_LEVEL /*&& leveltime > starttime*/)
|
||||
CONS_Printf(M_GetText("Encore Mode will be turned %s next round.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off"));
|
||||
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 turned %s.\n"), cv_kartencore.value ? M_GetText("on") : M_GetText("off"));
|
||||
CONS_Printf(M_GetText("Encore Mode has been set to %s.\n"), cv_kartencore.string);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,8 +120,8 @@ extern consvar_t cv_kartencore;
|
|||
extern consvar_t cv_kartvoterulechanges;
|
||||
extern consvar_t cv_kartspeedometer;
|
||||
extern consvar_t cv_kartvoices;
|
||||
|
||||
extern consvar_t cv_karteliminatelast;
|
||||
extern consvar_t cv_kartusepwrlv;
|
||||
|
||||
extern consvar_t cv_votetime;
|
||||
|
||||
|
|
@ -179,9 +179,10 @@ typedef enum
|
|||
XD_MODIFYVOTE, // 23
|
||||
XD_PICKVOTE, // 24
|
||||
XD_REMOVEPLAYER,// 25
|
||||
XD_POWERLEVEL, // 26
|
||||
#ifdef HAVE_BLUA
|
||||
XD_LUACMD, // 26
|
||||
XD_LUAVAR, // 27
|
||||
XD_LUACMD, // 27
|
||||
XD_LUAVAR, // 28
|
||||
#endif
|
||||
MAXNETXCMD
|
||||
} netxcmd_t;
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ typedef enum
|
|||
k_tiregrease, // Reduced friction timer after hitting a horizontal spring
|
||||
k_springstars, // Spawn stars around a player when they hit a spring
|
||||
k_springcolor, // Color of spring stars
|
||||
k_killfield, // How long have you been in the kill field, stay in too long and lose a bumper
|
||||
|
||||
NUMKARTSTUFF
|
||||
} kartstufftype_t;
|
||||
|
|
|
|||
|
|
@ -2553,6 +2553,19 @@ static void readcondition(UINT8 set, UINT32 id, char *word2)
|
|||
ty = UC_PLAYTIME + offset;
|
||||
re = atoi(params[1]);
|
||||
}
|
||||
else if ((offset=0) || fastcmp(params[0], "POWERLEVEL"))
|
||||
{
|
||||
PARAMCHECK(2);
|
||||
ty = UC_POWERLEVEL;
|
||||
re = atoi(params[1]);
|
||||
x1 = atoi(params[2]);
|
||||
|
||||
if (x1 < 0 || x1 >= PWRLV_NUMTYPES)
|
||||
{
|
||||
deh_warning("Power level type %d out of range (0 - %d)", x1, PWRLV_NUMTYPES-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ((offset=0) || fastcmp(params[0], "GAMECLEAR")
|
||||
|| (++offset && fastcmp(params[0], "ALLEMERALDS")))
|
||||
//|| (++offset && fastcmp(params[0], "ULTIMATECLEAR")))
|
||||
|
|
@ -2605,7 +2618,7 @@ static void readcondition(UINT8 set, UINT32 id, char *word2)
|
|||
|
||||
if (x1 < 0 || x1 >= NUMMAPS)
|
||||
{
|
||||
deh_warning("Level number %d out of range (1 - %d)", re, NUMMAPS);
|
||||
deh_warning("Level number %d out of range (1 - %d)", x1, NUMMAPS);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -3257,29 +3270,13 @@ static void readwipes(MYFILE *f)
|
|||
else if (fastcmp(pword, "FINAL"))
|
||||
wipeoffset = wipe_intermission_final;
|
||||
}
|
||||
else if (fastncmp(word, "SPECINTER_", 10))
|
||||
{
|
||||
pword = word + 10;
|
||||
if (fastcmp(pword, "TOBLACK"))
|
||||
wipeoffset = wipe_specinter_toblack;
|
||||
else if (fastcmp(pword, "FINAL"))
|
||||
wipeoffset = wipe_specinter_final;
|
||||
}
|
||||
else if (fastncmp(word, "VOTING_", 7))
|
||||
{
|
||||
pword = word + 7;
|
||||
if (fastcmp(pword, "TOBLACK"))
|
||||
wipeoffset = wipe_specinter_toblack;
|
||||
wipeoffset = wipe_voting_toblack;
|
||||
else if (fastcmp(pword, "FINAL"))
|
||||
wipeoffset = wipe_specinter_final;
|
||||
}
|
||||
else if (fastncmp(word, "MULTINTER_", 10))
|
||||
{
|
||||
pword = word + 10;
|
||||
if (fastcmp(pword, "TOBLACK"))
|
||||
wipeoffset = wipe_multinter_toblack;
|
||||
else if (fastcmp(pword, "FINAL"))
|
||||
wipeoffset = wipe_multinter_final;
|
||||
wipeoffset = wipe_voting_final;
|
||||
}
|
||||
else if (fastncmp(word, "CONTINUING_", 11))
|
||||
{
|
||||
|
|
@ -3331,11 +3328,13 @@ static void readwipes(MYFILE *f)
|
|||
else if (fastcmp(pword, "FINAL"))
|
||||
wipeoffset = wipe_gameend_final;
|
||||
}
|
||||
else if (fastncmp(word, "SPECLEVEL_", 10))
|
||||
else if (fastncmp(word, "ENCORE_", 7))
|
||||
{
|
||||
pword = word + 10;
|
||||
if (fastcmp(pword, "TOWHITE"))
|
||||
wipeoffset = wipe_speclevel_towhite;
|
||||
pword = word + 7;
|
||||
if (fastcmp(pword, "TOINVERT"))
|
||||
wipeoffset = wipe_encore_toinvert;
|
||||
else if (fastcmp(pword, "TOWHITE"))
|
||||
wipeoffset = wipe_encore_towhite;
|
||||
}
|
||||
|
||||
if (wipeoffset < 0)
|
||||
|
|
@ -3345,10 +3344,10 @@ static void readwipes(MYFILE *f)
|
|||
}
|
||||
|
||||
if (value == UINT8_MAX
|
||||
&& (wipeoffset <= wipe_level_toblack || wipeoffset >= wipe_speclevel_towhite))
|
||||
&& (wipeoffset <= wipe_level_toblack || wipeoffset >= wipe_encore_toinvert))
|
||||
{
|
||||
// Cannot disable non-toblack wipes
|
||||
// (or the level toblack wipe, or the special towhite wipe)
|
||||
// (or the level toblack wipe, or the special encore wipe)
|
||||
deh_warning("Wipes: can't disable wipe of type '%s'", word);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -7215,6 +7214,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
|
||||
"S_TIREGREASE",
|
||||
|
||||
"S_OVERTIMEFOG",
|
||||
"S_OVERTIMEORB",
|
||||
"S_OVERTIMEBEAM",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"S_NAMECHECK",
|
||||
#endif
|
||||
|
|
@ -8009,6 +8012,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_DRAFTDUST",
|
||||
"MT_TIREGREASE",
|
||||
|
||||
"MT_OVERTIMEFOG",
|
||||
"MT_OVERTIMEORB",
|
||||
"MT_OVERTIMEBEAM",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"MT_NAMECHECK",
|
||||
#endif
|
||||
|
|
@ -8493,7 +8500,8 @@ static const char *const KARTSTUFF_LIST[] = {
|
|||
"GROWCANCEL",
|
||||
"TIREGREASE",
|
||||
"SPRINGSTARS",
|
||||
"SPRINGCOLOR"
|
||||
"SPRINGCOLOR",
|
||||
"KILLFIELD"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@
|
|||
#include "../z_zone.h"
|
||||
#include "../g_input.h"
|
||||
|
||||
#include "../k_pwrlv.h"
|
||||
|
||||
#include "../console.h"
|
||||
|
||||
#ifdef __GNUG__
|
||||
|
|
@ -618,6 +620,11 @@ void I_Quit (void)
|
|||
#ifndef NONET
|
||||
D_SaveBan(); // save the ban list
|
||||
#endif
|
||||
|
||||
// Make sure you lose points for ALT-F4
|
||||
if (Playing())
|
||||
K_PlayerForfeit(consoleplayer, true);
|
||||
|
||||
G_SaveGameData(); // Tails 12-08-2002
|
||||
if (demorecording)
|
||||
G_CheckDemoStatus();
|
||||
|
|
|
|||
|
|
@ -158,9 +158,6 @@ extern FILE *logstream;
|
|||
// AND appveyor.yml, for the build bots!
|
||||
#endif
|
||||
|
||||
// Maintain compatibility with 1.0.x record attack replays?
|
||||
//#define DEMO_COMPAT_100
|
||||
|
||||
// Does this version require an added patch file?
|
||||
// Comment or uncomment this as necessary.
|
||||
#define USE_PATCH_FILE
|
||||
|
|
|
|||
|
|
@ -475,7 +475,6 @@ extern tic_t wantedcalcdelay;
|
|||
extern tic_t indirectitemcooldown;
|
||||
extern tic_t hyubgone;
|
||||
extern tic_t mapreset;
|
||||
extern UINT8 nospectategrief;
|
||||
extern boolean thwompsactive;
|
||||
extern SINT8 spbplace;
|
||||
|
||||
|
|
@ -487,6 +486,15 @@ extern INT16 votelevels[5][2];
|
|||
extern SINT8 votes[MAXPLAYERS];
|
||||
extern SINT8 pickedvote;
|
||||
|
||||
/** Battle overtime information
|
||||
*/
|
||||
extern struct battleovertime
|
||||
{
|
||||
UINT16 enabled; ///< Has this been initalized yet?
|
||||
fixed_t radius, minradius; ///< Radius of kill field
|
||||
fixed_t x, y, z; ///< Position to center on
|
||||
} battleovertime;
|
||||
|
||||
extern tic_t hidetime;
|
||||
|
||||
extern UINT32 timesBeaten; // # of times the game has been beaten.
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ void F_StartIntro(void)
|
|||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipe_level_final], false);
|
||||
F_RunWipe(wipedefs[wipe_intro_toblack], false, "FADEMAP0", false, false);
|
||||
}
|
||||
|
||||
if (introtoplay)
|
||||
|
|
@ -306,7 +306,7 @@ void F_IntroDrawer(void)
|
|||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(99,true);
|
||||
F_RunWipe(99, true, "FADEMAP0", false, false);
|
||||
}
|
||||
|
||||
// Stay on black for a bit. =)
|
||||
|
|
@ -1420,7 +1420,7 @@ void F_CutsceneDrawer(void)
|
|||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, cutscenes[cutnum]->scene[scenenum].fadecolor);
|
||||
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true);
|
||||
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true, NULL, false, false);
|
||||
|
||||
F_WipeStartScreen();
|
||||
}
|
||||
|
|
@ -1440,7 +1440,7 @@ void F_CutsceneDrawer(void)
|
|||
if (dofadenow && rendermode != render_none)
|
||||
{
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true);
|
||||
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true, NULL, false, false);
|
||||
}
|
||||
|
||||
V_DrawString(textxpos, textypos, 0, cutscene_disptext);
|
||||
|
|
|
|||
|
|
@ -74,12 +74,13 @@ extern INT32 lastwipetic;
|
|||
|
||||
void F_WipeStartScreen(void);
|
||||
void F_WipeEndScreen(void);
|
||||
void F_RunWipe(UINT8 wipetype, boolean drawMenu);
|
||||
void F_RunWipe(UINT8 wipetype, boolean drawMenu, const char *colormap, boolean reverse, boolean encorewiggle);
|
||||
|
||||
enum
|
||||
{
|
||||
wipe_credits_intermediate, // makes a good 0 I guess.
|
||||
|
||||
// Gamestate wipes
|
||||
wipe_level_toblack,
|
||||
wipe_intermission_toblack,
|
||||
wipe_voting_toblack,
|
||||
|
|
@ -92,11 +93,11 @@ enum
|
|||
wipe_intro_toblack,
|
||||
wipe_cutscene_toblack,
|
||||
|
||||
// custom intermissions
|
||||
wipe_specinter_toblack,
|
||||
wipe_multinter_toblack,
|
||||
wipe_speclevel_towhite,
|
||||
// Specialized wipes
|
||||
wipe_encore_toinvert,
|
||||
wipe_encore_towhite,
|
||||
|
||||
// "From black" wipes
|
||||
wipe_level_final,
|
||||
wipe_intermission_final,
|
||||
wipe_voting_final,
|
||||
|
|
@ -109,10 +110,6 @@ enum
|
|||
wipe_intro_final,
|
||||
wipe_cutscene_final,
|
||||
|
||||
// custom intermissions
|
||||
wipe_specinter_final,
|
||||
wipe_multinter_final,
|
||||
|
||||
NUMWIPEDEFS,
|
||||
WIPEFINALSHIFT = wipe_level_final - wipe_level_toblack
|
||||
};
|
||||
|
|
|
|||
149
src/f_wipe.c
149
src/f_wipe.c
|
|
@ -16,8 +16,10 @@
|
|||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
|
||||
#include "r_data.h" // NearestColor
|
||||
#include "r_draw.h" // transtable
|
||||
#include "p_pspr.h" // tr_transxxx
|
||||
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
|
|
@ -47,35 +49,31 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
|
|||
99, // wipe_credits_intermediate (0)
|
||||
|
||||
0, // wipe_level_toblack
|
||||
UINT8_MAX, // wipe_intermission_toblack
|
||||
0, // wipe_intermission_toblack
|
||||
0, // wipe_voting_toblack,
|
||||
UINT8_MAX, // wipe_continuing_toblack
|
||||
3, // wipe_titlescreen_toblack
|
||||
0, // wipe_continuing_toblack
|
||||
0, // wipe_titlescreen_toblack
|
||||
0, // wipe_timeattack_toblack
|
||||
99, // wipe_credits_toblack
|
||||
0, // wipe_evaluation_toblack
|
||||
0, // wipe_gameend_toblack
|
||||
UINT8_MAX, // wipe_intro_toblack (hardcoded)
|
||||
UINT8_MAX, // wipe_cutscene_toblack (hardcoded)
|
||||
99, // wipe_cutscene_toblack (hardcoded)
|
||||
|
||||
UINT8_MAX, // wipe_specinter_toblack
|
||||
UINT8_MAX, // wipe_multinter_toblack
|
||||
99, // wipe_speclevel_towhite
|
||||
72, // wipe_encore_toinvert
|
||||
99, // wipe_encore_towhite
|
||||
|
||||
3, // wipe_level_final
|
||||
UINT8_MAX, // wipe_level_final
|
||||
0, // wipe_intermission_final
|
||||
0, // wipe_voting_final
|
||||
0, // wipe_continuing_final
|
||||
3, // wipe_titlescreen_final
|
||||
0, // wipe_titlescreen_final
|
||||
0, // wipe_timeattack_final
|
||||
99, // wipe_credits_final
|
||||
0, // wipe_evaluation_final
|
||||
0, // wipe_gameend_final
|
||||
99, // wipe_intro_final (hardcoded)
|
||||
99, // wipe_cutscene_final (hardcoded)
|
||||
|
||||
0, // wipe_specinter_final
|
||||
0 // wipe_multinter_final
|
||||
99 // wipe_cutscene_final (hardcoded)
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
@ -86,9 +84,13 @@ boolean WipeInAction = false;
|
|||
INT32 lastwipetic = 0;
|
||||
|
||||
#ifndef NOWIPE
|
||||
|
||||
#define GENLEN 31
|
||||
|
||||
static UINT8 *wipe_scr_start; //screen 3
|
||||
static UINT8 *wipe_scr_end; //screen 4
|
||||
static UINT8 *wipe_scr; //screen 0 (main drawing)
|
||||
static UINT8 pallen;
|
||||
static fixed_t paldiv;
|
||||
|
||||
/** Create fademask_t from lump
|
||||
|
|
@ -181,7 +183,7 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
|
|||
*
|
||||
* \param fademask pixels to change
|
||||
*/
|
||||
static void F_DoWipe(fademask_t *fademask)
|
||||
static void F_DoWipe(fademask_t *fademask, lighttable_t *fadecolormap, boolean reverse)
|
||||
{
|
||||
// Software mask wipe -- optimized; though it might not look like it!
|
||||
// Okay, to save you wondering *how* this is more optimized than the simpler
|
||||
|
|
@ -199,6 +201,10 @@ static void F_DoWipe(fademask_t *fademask)
|
|||
// look a little messy; sorry!) but it simultaneously runs at twice the speed.
|
||||
// In addition, we precalculate all the X and Y positions that we need to draw
|
||||
// from and to, so it uses a little extra memory, but again, helps it run faster.
|
||||
// ---
|
||||
// Sal: I kinda destroyed some of this code by introducing Genesis-style fades.
|
||||
// A colormap can be provided in F_RunWipe, which the white/black values will be
|
||||
// remapped to the appropriate entry in the fade colormap.
|
||||
{
|
||||
// wipe screen, start, end
|
||||
UINT8 *w = wipe_scr;
|
||||
|
|
@ -242,6 +248,8 @@ static void F_DoWipe(fademask_t *fademask)
|
|||
maskx = masky = 0;
|
||||
do
|
||||
{
|
||||
UINT8 m = *mask;
|
||||
|
||||
draw_rowstart = scrxpos[maskx];
|
||||
draw_rowend = scrxpos[maskx + 1];
|
||||
draw_linestart = scrypos[masky];
|
||||
|
|
@ -250,28 +258,31 @@ static void F_DoWipe(fademask_t *fademask)
|
|||
relativepos = (draw_linestart * vid.width) + draw_rowstart;
|
||||
draw_linestogo = draw_lineend - draw_linestart;
|
||||
|
||||
if (*mask == 0)
|
||||
if (reverse)
|
||||
m = ((pallen-1) - m);
|
||||
|
||||
if (m == 0)
|
||||
{
|
||||
// shortcut - memcpy source to work
|
||||
while (draw_linestogo--)
|
||||
{
|
||||
M_Memcpy(w_base+relativepos, s_base+relativepos, draw_rowend-draw_rowstart);
|
||||
M_Memcpy(w_base+relativepos, (reverse ? e_base : s_base)+relativepos, draw_rowend-draw_rowstart);
|
||||
relativepos += vid.width;
|
||||
}
|
||||
}
|
||||
else if (*mask == 10)
|
||||
else if (m >= (pallen-1))
|
||||
{
|
||||
// shortcut - memcpy target to work
|
||||
while (draw_linestogo--)
|
||||
{
|
||||
M_Memcpy(w_base+relativepos, e_base+relativepos, draw_rowend-draw_rowstart);
|
||||
M_Memcpy(w_base+relativepos, (reverse ? s_base : e_base)+relativepos, draw_rowend-draw_rowstart);
|
||||
relativepos += vid.width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pointer to transtable that this mask would use
|
||||
transtbl = transtables + ((9 - *mask)<<FF_TRANSSHIFT);
|
||||
transtbl = transtables + ((9 - m)<<FF_TRANSSHIFT);
|
||||
|
||||
// DRAWING LOOP
|
||||
while (draw_linestogo--)
|
||||
|
|
@ -282,7 +293,17 @@ static void F_DoWipe(fademask_t *fademask)
|
|||
draw_rowstogo = draw_rowend - draw_rowstart;
|
||||
|
||||
while (draw_rowstogo--)
|
||||
*w++ = transtbl[ ( *e++ << 8 ) + *s++ ];
|
||||
{
|
||||
if (fadecolormap != NULL)
|
||||
{
|
||||
if (reverse)
|
||||
*w++ = fadecolormap[ ( m << 8 ) + *e++ ];
|
||||
else
|
||||
*w++ = fadecolormap[ ( m << 8 ) + *s++ ];
|
||||
}
|
||||
else
|
||||
*w++ = transtbl[ ( *e++ << 8 ) + *s++ ];
|
||||
}
|
||||
|
||||
relativepos += vid.width;
|
||||
}
|
||||
|
|
@ -334,20 +355,86 @@ void F_WipeEndScreen(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Wiggle post processor for encore wipes
|
||||
*/
|
||||
static void F_DoEncoreWiggle(UINT8 time)
|
||||
{
|
||||
UINT8 *tmpscr = wipe_scr_start;
|
||||
UINT8 *srcscr = wipe_scr;
|
||||
angle_t disStart = (time * 128) & FINEMASK;
|
||||
INT32 y, sine, newpix, scanline;
|
||||
|
||||
for (y = 0; y < vid.height; y++)
|
||||
{
|
||||
sine = (FINESINE(disStart) * (time*12))>>FRACBITS;
|
||||
scanline = y / vid.dupy;
|
||||
if (scanline & 1)
|
||||
sine = -sine;
|
||||
newpix = abs(sine);
|
||||
|
||||
if (sine < 0)
|
||||
{
|
||||
M_Memcpy(&tmpscr[(y*vid.width)+newpix], &srcscr[(y*vid.width)], vid.width-newpix);
|
||||
|
||||
// Cleanup edge
|
||||
while (newpix)
|
||||
{
|
||||
tmpscr[(y*vid.width)+newpix] = srcscr[(y*vid.width)];
|
||||
newpix--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
M_Memcpy(&tmpscr[(y*vid.width)], &srcscr[(y*vid.width) + sine], vid.width-newpix);
|
||||
|
||||
// Cleanup edge
|
||||
while (newpix)
|
||||
{
|
||||
tmpscr[(y*vid.width) + vid.width - newpix] = srcscr[(y*vid.width) + (vid.width-1)];
|
||||
newpix--;
|
||||
}
|
||||
}
|
||||
|
||||
disStart += (time*8); //the offset into the displacement map, increment each game loop
|
||||
disStart &= FINEMASK; //clip it to FINEMASK
|
||||
}
|
||||
}
|
||||
|
||||
/** After setting up the screens you want to wipe,
|
||||
* calling this will do a 'typical' wipe.
|
||||
*/
|
||||
void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
||||
void F_RunWipe(UINT8 wipetype, boolean drawMenu, const char *colormap, boolean reverse, boolean encorewiggle)
|
||||
{
|
||||
#ifdef NOWIPE
|
||||
(void)wipetype;
|
||||
(void)drawMenu;
|
||||
(void)colormap;
|
||||
(void)reverse;
|
||||
(void)encorewiggle;
|
||||
#else
|
||||
tic_t nowtime;
|
||||
UINT8 wipeframe = 0;
|
||||
fademask_t *fmask;
|
||||
|
||||
paldiv = FixedDiv(257<<FRACBITS, 11<<FRACBITS);
|
||||
lumpnum_t clump = LUMPERROR;
|
||||
lighttable_t *fcolor = NULL;
|
||||
|
||||
if (colormap != NULL)
|
||||
clump = W_GetNumForName(colormap);
|
||||
|
||||
if (clump != LUMPERROR && wipetype != UINT8_MAX)
|
||||
{
|
||||
pallen = 32;
|
||||
fcolor = Z_MallocAlign((256 * pallen), PU_STATIC, NULL, 8);
|
||||
W_ReadLump(clump, fcolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
pallen = 11;
|
||||
reverse = false;
|
||||
}
|
||||
|
||||
paldiv = FixedDiv(257<<FRACBITS, pallen<<FRACBITS);
|
||||
|
||||
// Init the wipe
|
||||
WipeInAction = true;
|
||||
|
|
@ -372,7 +459,16 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
|||
HWR_DoWipe(wipetype, wipeframe-1); // send in the wipe type and wipeframe because we need to cache the graphic
|
||||
else
|
||||
#endif
|
||||
F_DoWipe(fmask);
|
||||
F_DoWipe(fmask, fcolor, reverse);
|
||||
|
||||
if (encorewiggle)
|
||||
{
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_opengl)
|
||||
#endif
|
||||
F_DoEncoreWiggle(wipeframe);
|
||||
}
|
||||
|
||||
I_OsPolling();
|
||||
I_UpdateNoBlit();
|
||||
|
||||
|
|
@ -386,6 +482,13 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
|||
|
||||
NetKeepAlive(); // Update the network so we don't cause timeouts
|
||||
}
|
||||
|
||||
WipeInAction = false;
|
||||
|
||||
if (fcolor)
|
||||
{
|
||||
Z_Free(fcolor);
|
||||
fcolor = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
450
src/g_game.c
450
src/g_game.c
|
|
@ -48,6 +48,7 @@
|
|||
#include "m_cond.h" // condition sets
|
||||
#include "md5.h" // demo checksums
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
gameaction_t gameaction;
|
||||
gamestate_t gamestate = GS_NULL;
|
||||
|
|
@ -261,13 +262,15 @@ INT16 votelevels[5][2]; // Levels that were rolled by the host
|
|||
SINT8 votes[MAXPLAYERS]; // Each player's vote
|
||||
SINT8 pickedvote; // What vote the host rolls
|
||||
|
||||
// Battle overtime system
|
||||
struct battleovertime battleovertime;
|
||||
|
||||
// Server-sided, synched variables
|
||||
SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
|
||||
tic_t wantedcalcdelay; // Time before it recalculates WANTED
|
||||
tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
|
||||
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
|
||||
UINT8 nospectategrief; // How many players need to be in-game to eliminate last; for preventing spectate griefing
|
||||
boolean thwompsactive; // Thwomps activate on lap 2
|
||||
SINT8 spbplace; // SPB exists, give the person behind better items
|
||||
|
||||
|
|
@ -2337,7 +2340,7 @@ void G_Ticker(boolean run)
|
|||
|
||||
G_DoReborn(consoleplayer);*/
|
||||
|
||||
D_MapChange(gamemap, gametype, cv_kartencore.value, true, 1, false, false);
|
||||
D_MapChange(gamemap, gametype, (cv_kartencore.value == 1), true, 1, false, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -2369,21 +2372,7 @@ void G_Ticker(boolean run)
|
|||
|
||||
if (playeringame[i])
|
||||
{
|
||||
//@TODO all this throwdir stuff shouldn't be here! But it stays for now to maintain 1.0.4 compat...
|
||||
// Remove for 1.1!
|
||||
|
||||
// SRB2kart
|
||||
// Save the dir the player is holding
|
||||
// to allow items to be thrown forward or backward.
|
||||
if (cmd->buttons & BT_FORWARD)
|
||||
players[i].kartstuff[k_throwdir] = 1;
|
||||
else if (cmd->buttons & BT_BACKWARD)
|
||||
players[i].kartstuff[k_throwdir] = -1;
|
||||
else
|
||||
players[i].kartstuff[k_throwdir] = 0;
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -3042,8 +3031,17 @@ mapthing_t *G_FindRaceStart(INT32 playernum)
|
|||
continue;
|
||||
if (j == i)
|
||||
continue;
|
||||
if (players[j].score == players[i].score)
|
||||
num++;
|
||||
|
||||
if (netgame && cv_kartusepwrlv.value)
|
||||
{
|
||||
if (clientpowerlevels[j][PWRLV_RACE] == clientpowerlevels[i][PWRLV_RACE])
|
||||
num++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (players[j].score == players[i].score)
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num > 1) // found dupes
|
||||
|
|
@ -3051,8 +3049,21 @@ mapthing_t *G_FindRaceStart(INT32 playernum)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (players[i].score > players[playernum].score || i < playernum)
|
||||
if (i < playernum)
|
||||
pos++;
|
||||
else
|
||||
{
|
||||
if (netgame && cv_kartusepwrlv.value)
|
||||
{
|
||||
if (clientpowerlevels[i][PWRLV_RACE] > clientpowerlevels[playernum][PWRLV_RACE])
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (players[i].score > players[playernum].score)
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3382,9 +3393,10 @@ boolean G_BattleGametype(void)
|
|||
//
|
||||
INT16 G_SometimesGetDifferentGametype(void)
|
||||
{
|
||||
boolean encorepossible = (M_SecretUnlocked(SECRET_ENCORE) && G_RaceGametype());
|
||||
boolean encorepossible = ((M_SecretUnlocked(SECRET_ENCORE) || encorescramble == 1) && G_RaceGametype());
|
||||
|
||||
if (!cv_kartvoterulechanges.value) // never
|
||||
if (!cv_kartvoterulechanges.value // never
|
||||
&& encorescramble != 1) // destroying the code for this one instance
|
||||
return gametype;
|
||||
|
||||
if (randmapbuffer[NUMMAPS] > 0 && (encorepossible || cv_kartvoterulechanges.value != 3))
|
||||
|
|
@ -3392,25 +3404,33 @@ INT16 G_SometimesGetDifferentGametype(void)
|
|||
randmapbuffer[NUMMAPS]--;
|
||||
if (encorepossible)
|
||||
{
|
||||
switch (cv_kartvoterulechanges.value)
|
||||
if (encorescramble != -1)
|
||||
encorepossible = (boolean)encorescramble; // FORCE to what was scrambled on intermission
|
||||
else
|
||||
{
|
||||
case 3: // always
|
||||
randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set
|
||||
break;
|
||||
case 2: // frequent
|
||||
encorepossible = M_RandomChance(FRACUNIT>>1);
|
||||
break;
|
||||
case 1: // sometimes
|
||||
default:
|
||||
encorepossible = M_RandomChance(FRACUNIT>>2);
|
||||
break;
|
||||
switch (cv_kartvoterulechanges.value)
|
||||
{
|
||||
case 3: // always
|
||||
randmapbuffer[NUMMAPS] = 0; // gotta prep this in case it isn't already set
|
||||
break;
|
||||
case 2: // frequent
|
||||
encorepossible = M_RandomChance(FRACUNIT>>1);
|
||||
break;
|
||||
case 1: // sometimes
|
||||
default:
|
||||
encorepossible = M_RandomChance(FRACUNIT>>2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (encorepossible != (boolean)cv_kartencore.value)
|
||||
if (encorepossible != (cv_kartencore.value == 1))
|
||||
return (gametype|0x80);
|
||||
}
|
||||
return gametype;
|
||||
}
|
||||
|
||||
if (!cv_kartvoterulechanges.value) // never (again)
|
||||
return gametype;
|
||||
|
||||
switch (cv_kartvoterulechanges.value) // okay, we're having a gametype change! when's the next one, luv?
|
||||
{
|
||||
case 3: // always
|
||||
|
|
@ -3879,7 +3899,7 @@ void G_NextLevel(void)
|
|||
}
|
||||
|
||||
forceresetplayers = false;
|
||||
deferencoremode = (boolean)cv_kartencore.value;
|
||||
deferencoremode = (cv_kartencore.value == 1);
|
||||
}
|
||||
|
||||
gameaction = ga_worlddone;
|
||||
|
|
@ -4042,9 +4062,13 @@ void G_LoadGameData(void)
|
|||
// to new gamedata
|
||||
G_ClearRecords(); // main and nights records
|
||||
M_ClearSecrets(); // emblems, unlocks, maps visited, etc
|
||||
|
||||
totalplaytime = 0; // total play time (separate from all)
|
||||
matchesplayed = 0; // SRB2Kart: matches played & finished
|
||||
|
||||
for (i = 0; i < PWRLV_NUMTYPES; i++) // SRB2Kart: online rank system
|
||||
vspowerlevel[i] = PWRLVRECORD_START;
|
||||
|
||||
if (M_CheckParm("-nodata"))
|
||||
return; // Don't load.
|
||||
|
||||
|
|
@ -4075,6 +4099,9 @@ void G_LoadGameData(void)
|
|||
totalplaytime = READUINT32(save_p);
|
||||
matchesplayed = READUINT32(save_p);
|
||||
|
||||
for (i = 0; i < PWRLV_NUMTYPES; i++)
|
||||
vspowerlevel[i] = READUINT16(save_p);
|
||||
|
||||
modded = READUINT8(save_p);
|
||||
|
||||
// Aha! Someone's been screwing with the save file!
|
||||
|
|
@ -4220,6 +4247,9 @@ void G_SaveGameData(boolean force)
|
|||
WRITEUINT32(save_p, totalplaytime);
|
||||
WRITEUINT32(save_p, matchesplayed);
|
||||
|
||||
for (i = 0; i < PWRLV_NUMTYPES; i++)
|
||||
WRITEUINT16(save_p, vspowerlevel[i]);
|
||||
|
||||
btemp = (UINT8)(savemoddata); // what used to be here was profoundly dunderheaded
|
||||
WRITEUINT8(save_p, btemp);
|
||||
|
||||
|
|
@ -4732,7 +4762,7 @@ char *G_BuildMapTitle(INT32 mapnum)
|
|||
// DEMO RECORDING
|
||||
//
|
||||
|
||||
#define DEMOVERSION 0x0002
|
||||
#define DEMOVERSION 0x0003
|
||||
#define DEMOHEADER "\xF0" "KartReplay" "\x0F"
|
||||
|
||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||
|
|
@ -4743,12 +4773,6 @@ char *G_BuildMapTitle(INT32 mapnum)
|
|||
#define DF_ENCORE 0x40
|
||||
#define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode!
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
#define DF_FILELIST 0x08 // This demo contains an extra files list
|
||||
#define DF_GAMETYPEMASK 0x30
|
||||
#define DF_GAMESHIFT 4
|
||||
#endif
|
||||
|
||||
#define DEMO_SPECTATOR 0x40
|
||||
|
||||
// For demos
|
||||
|
|
@ -4890,7 +4914,6 @@ void G_ReadDemoExtraData(void)
|
|||
kartspeed = READUINT8(demo_p);
|
||||
kartweight = READUINT8(demo_p);
|
||||
|
||||
|
||||
if (stricmp(skins[players[p].skin].name, name) != 0)
|
||||
FindClosestSkinForStats(p, kartspeed, kartweight);
|
||||
|
||||
|
|
@ -5608,16 +5631,9 @@ void G_ConsGhostTic(INT32 playernum)
|
|||
else
|
||||
ghostext[playernum].desyncframes = 0;
|
||||
|
||||
if (
|
||||
#ifdef DEMO_COMPAT_100
|
||||
demo.version != 0x0001 &&
|
||||
#endif
|
||||
(
|
||||
players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem ||
|
||||
players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount ||
|
||||
players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers
|
||||
)
|
||||
)
|
||||
if (players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem
|
||||
|| players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount
|
||||
|| players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers)
|
||||
{
|
||||
if (demosynced)
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
|
||||
|
|
@ -5645,10 +5661,6 @@ void G_GhostTicker(void)
|
|||
// Skip normal demo data.
|
||||
UINT8 ziptic = READUINT8(g->p);
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (g->version != 0x0001)
|
||||
{
|
||||
#endif
|
||||
while (ziptic != DW_END) // Get rid of extradata stuff
|
||||
{
|
||||
if (ziptic == 0) // Only support player 0 info for now
|
||||
|
|
@ -5672,9 +5684,6 @@ void G_GhostTicker(void)
|
|||
}
|
||||
|
||||
ziptic = READUINT8(g->p); // Back to actual ziptic stuff
|
||||
#ifdef DEMO_COMPAT_100
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ziptic & ZT_FWD)
|
||||
g->p++;
|
||||
|
|
@ -5694,18 +5703,12 @@ void G_GhostTicker(void)
|
|||
// Grab ghost data.
|
||||
ziptic = READUINT8(g->p);
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (g->version != 0x0001)
|
||||
{
|
||||
#endif
|
||||
if (ziptic == 0xFF)
|
||||
goto skippedghosttic; // Didn't write ghost info this frame
|
||||
else if (ziptic != 0)
|
||||
I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this
|
||||
ziptic = READUINT8(g->p);
|
||||
#ifdef DEMO_COMPAT_100
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ziptic & GZT_XYZ)
|
||||
{
|
||||
g->oldmo.x = READFIXED(g->p);
|
||||
|
|
@ -5846,15 +5849,8 @@ void G_GhostTicker(void)
|
|||
g->p += 12; // kartitem, kartamount, kartbumpers
|
||||
}
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (g->version != 0x0001)
|
||||
{
|
||||
#endif
|
||||
if (READUINT8(g->p) != 0xFF) // Make sure there isn't other ghost data here.
|
||||
I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this
|
||||
#ifdef DEMO_COMPAT_100
|
||||
}
|
||||
#endif
|
||||
|
||||
skippedghosttic:
|
||||
// Tick ghost colors (Super and Mario Invincibility flashing)
|
||||
|
|
@ -6364,20 +6360,15 @@ void G_BeginRecording(void)
|
|||
|
||||
switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
|
||||
{
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
demotime_p = demo_p;
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // lap
|
||||
break;
|
||||
/*case ATTACKING_NIGHTS: // 2
|
||||
demotime_p = demo_p;
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
WRITEUINT32(demo_p,0); // score
|
||||
break;*/
|
||||
default: // 3
|
||||
break;
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
demotime_p = demo_p;
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // lap
|
||||
break;
|
||||
default: // 3
|
||||
break;
|
||||
}
|
||||
|
||||
WRITEUINT32(demo_p,P_GetInitSeed());
|
||||
|
|
@ -6417,6 +6408,9 @@ void G_BeginRecording(void)
|
|||
// Score, since Kart uses this to determine where you start on the map
|
||||
WRITEUINT32(demo_p, player->score);
|
||||
|
||||
// Power Levels
|
||||
WRITEUINT16(demo_p, clientpowerlevels[p][G_BattleGametype() ? PWRLV_BATTLE : PWRLV_RACE]);
|
||||
|
||||
// Kart speed and weight
|
||||
WRITEUINT8(demo_p, skins[player->skin].kartspeed);
|
||||
WRITEUINT8(demo_p, skins[player->skin].kartweight);
|
||||
|
|
@ -6515,18 +6509,13 @@ void G_SetDemoTime(UINT32 ptime, UINT32 plap)
|
|||
{
|
||||
if (!demo.recording || !demotime_p)
|
||||
return;
|
||||
|
||||
if (demoflags & DF_RECORDATTACK)
|
||||
{
|
||||
WRITEUINT32(demotime_p, ptime);
|
||||
WRITEUINT32(demotime_p, plap);
|
||||
demotime_p = NULL;
|
||||
}
|
||||
/*else if (demoflags & DF_NIGHTSATTACK)
|
||||
{
|
||||
WRITEUINT32(demotime_p, ptime);
|
||||
WRITEUINT32(demotime_p, pscore);
|
||||
demotime_p = NULL;
|
||||
}*/
|
||||
}
|
||||
|
||||
static void G_LoadDemoExtraFiles(UINT8 **pp)
|
||||
|
|
@ -6769,13 +6758,6 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
case DEMOVERSION: // latest always supported
|
||||
p += 64; // full demo title
|
||||
break;
|
||||
#ifdef DEMO_COMPAT_100
|
||||
case 0x0001:
|
||||
// Old replays gotta go :]
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' outdated version. It will be overwritten. Nyeheheh.\n"), oldname);
|
||||
Z_Free(buffer);
|
||||
return UINT8_MAX;
|
||||
#endif
|
||||
// too old, cannot support.
|
||||
default:
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
|
||||
|
|
@ -6867,12 +6849,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
|
|||
info_p += 64;
|
||||
|
||||
break;
|
||||
#ifdef DEMO_COMPAT_100
|
||||
case 0x0001:
|
||||
pdemo->type = MD_OUTDATED;
|
||||
sprintf(pdemo->title, "Legacy Replay");
|
||||
break;
|
||||
#endif
|
||||
// too old, cannot support.
|
||||
default:
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath);
|
||||
|
|
@ -6907,16 +6883,6 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
|
|||
Z_Free(infobuffer);
|
||||
return;
|
||||
}
|
||||
#ifdef DEMO_COMPAT_100
|
||||
else if (pdemoversion == 0x0001)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is a legacy multiplayer replay and cannot be played.\n"), pdemo->filepath);
|
||||
pdemo->type = MD_INVALID;
|
||||
sprintf(pdemo->title, "INVALID REPLAY");
|
||||
Z_Free(infobuffer);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
pdemo->gametype = READUINT8(info_p);
|
||||
|
||||
|
|
@ -7117,10 +7083,6 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
demo_p += 64;
|
||||
|
||||
break;
|
||||
#ifdef DEMO_COMPAT_100
|
||||
case 0x0001:
|
||||
break;
|
||||
#endif
|
||||
// too old, cannot support.
|
||||
default:
|
||||
snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname);
|
||||
|
|
@ -7149,24 +7111,6 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
demo_p += 16; // mapmd5
|
||||
|
||||
demoflags = READUINT8(demo_p);
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (demo.version == 0x0001)
|
||||
{
|
||||
if (demoflags & DF_MULTIPLAYER)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("%s is an alpha multiplayer replay and cannot be played.\n"), pdemoname);
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(demobuffer);
|
||||
demo.playback = false;
|
||||
demo.title = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
gametype = READUINT8(demo_p);
|
||||
|
||||
if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running.
|
||||
|
|
@ -7224,9 +7168,6 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
return;
|
||||
}
|
||||
}
|
||||
#ifdef DEMO_COMPAT_100
|
||||
}
|
||||
#endif
|
||||
|
||||
modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT;
|
||||
multiplayer = !!(demoflags & DF_MULTIPLAYER);
|
||||
|
|
@ -7254,109 +7195,20 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
// Random seed
|
||||
randseed = READUINT32(demo_p);
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (demo.version != 0x0001)
|
||||
#endif
|
||||
demo_p += 4; // Extrainfo location
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (demo.version == 0x0001)
|
||||
// ...*map* not loaded?
|
||||
if (!gamemap || (gamemap > NUMMAPS) || !mapheaderinfo[gamemap-1] || !(mapheaderinfo[gamemap-1]->menuflags & LF2_EXISTSHACK))
|
||||
{
|
||||
// Player name
|
||||
M_Memcpy(player_names[0],demo_p,16);
|
||||
demo_p += 16;
|
||||
|
||||
// Skin
|
||||
M_Memcpy(skin,demo_p,16);
|
||||
demo_p += 16;
|
||||
|
||||
// Color
|
||||
M_Memcpy(color,demo_p,16);
|
||||
demo_p += 16;
|
||||
|
||||
demo_p += 5; // Backwards compat - some stats
|
||||
// SRB2kart
|
||||
kartspeed[0] = READUINT8(demo_p);
|
||||
kartweight[0] = READUINT8(demo_p);
|
||||
//
|
||||
demo_p += 9; // Backwards compat - more stats
|
||||
|
||||
// Skin not loaded?
|
||||
if (!SetPlayerSkin(0, skin))
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("%s features a character that is not currently loaded.\n"), pdemoname);
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(demobuffer);
|
||||
demo.playback = false;
|
||||
demo.title = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// ...*map* not loaded?
|
||||
if (!gamemap || (gamemap > NUMMAPS) || !mapheaderinfo[gamemap-1] || !(mapheaderinfo[gamemap-1]->menuflags & LF2_EXISTSHACK))
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname);
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(demobuffer);
|
||||
demo.playback = false;
|
||||
demo.title = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set color
|
||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
||||
if (!stricmp(KartColor_Names[i],color)) // SRB2kart
|
||||
{
|
||||
players[0].skincolor = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// net var data
|
||||
CV_LoadNetVars(&demo_p);
|
||||
|
||||
// Sigh ... it's an empty demo.
|
||||
if (*demo_p == DEMOMARKER)
|
||||
{
|
||||
snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname);
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(demobuffer);
|
||||
demo.playback = false;
|
||||
demo.title = false;
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname);
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
Z_Free(pdemoname);
|
||||
|
||||
memset(&oldcmd,0,sizeof(oldcmd));
|
||||
memset(&oldghost,0,sizeof(oldghost));
|
||||
memset(&ghostext,0,sizeof(ghostext));
|
||||
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Demo version does not match game version. Desyncs may occur.\n"));
|
||||
|
||||
// console warning messages
|
||||
#if defined(SKIPERRORS) && !defined(DEVELOP)
|
||||
demosynced = (!skiperrors);
|
||||
#else
|
||||
demosynced = true;
|
||||
#endif
|
||||
|
||||
// didn't start recording right away.
|
||||
demo.deferstart = false;
|
||||
|
||||
consoleplayer = 0;
|
||||
memset(displayplayers, 0, sizeof(displayplayers));
|
||||
memset(playeringame, 0, sizeof(playeringame));
|
||||
playeringame[0] = true;
|
||||
|
||||
goto post_compat;
|
||||
Z_Free(demobuffer);
|
||||
demo.playback = false;
|
||||
demo.title = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// net var data
|
||||
CV_LoadNetVars(&demo_p);
|
||||
|
|
@ -7471,6 +7323,9 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
// Score, since Kart uses this to determine where you start on the map
|
||||
players[p].score = READUINT32(demo_p);
|
||||
|
||||
// Power Levels
|
||||
clientpowerlevels[p][G_BattleGametype() ? PWRLV_BATTLE : PWRLV_RACE] = READUINT16(demo_p);
|
||||
|
||||
// Kart stats, temporarily
|
||||
kartspeed[p] = READUINT8(demo_p);
|
||||
kartweight[p] = READUINT8(demo_p);
|
||||
|
|
@ -7495,10 +7350,6 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
R_ExecuteSetViewSize();
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
post_compat:
|
||||
#endif
|
||||
|
||||
P_SetRandSeed(randseed);
|
||||
G_InitNew(demoflags & DF_ENCORE, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer.
|
||||
|
||||
|
|
@ -7589,10 +7440,6 @@ void G_AddGhost(char *defdemoname)
|
|||
case DEMOVERSION: // latest always supported
|
||||
p += 64; // title
|
||||
break;
|
||||
#ifdef DEMO_COMPAT_100
|
||||
case 0x0001:
|
||||
break;
|
||||
#endif
|
||||
// too old, cannot support.
|
||||
default:
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname);
|
||||
|
|
@ -7633,15 +7480,9 @@ void G_AddGhost(char *defdemoname)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (ghostversion != 0x0001)
|
||||
#endif
|
||||
p++; // gametype
|
||||
p++; // gametype
|
||||
G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts.
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (ghostversion != 0x0001)
|
||||
#endif
|
||||
G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts.
|
||||
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
|
||||
{
|
||||
case ATTACKING_NONE: // 0
|
||||
|
|
@ -7657,41 +7498,6 @@ void G_AddGhost(char *defdemoname)
|
|||
}
|
||||
|
||||
p += 4; // random seed
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (ghostversion == 0x0001)
|
||||
{
|
||||
// Player name (TODO: Display this somehow if it doesn't match cv_playername!)
|
||||
M_Memcpy(name, p,16);
|
||||
p += 16;
|
||||
|
||||
// Skin
|
||||
M_Memcpy(skin, p,16);
|
||||
p += 16;
|
||||
|
||||
// Color
|
||||
M_Memcpy(color, p,16);
|
||||
p += 16;
|
||||
|
||||
// Ghosts do not have a player structure to put this in.
|
||||
p++; // charability
|
||||
p++; // charability2
|
||||
p++; // actionspd
|
||||
p++; // mindash
|
||||
p++; // maxdash
|
||||
// SRB2kart
|
||||
p++; // kartspeed
|
||||
p++; // kartweight
|
||||
//
|
||||
p++; // normalspeed
|
||||
p++; // runspeed
|
||||
p++; // thrustfactor
|
||||
p++; // accelstart
|
||||
p++; // acceleration
|
||||
p += 4; // jumpfactor
|
||||
}
|
||||
else
|
||||
#endif
|
||||
p += 4; // Extra data location reference
|
||||
|
||||
// net var data
|
||||
|
|
@ -7711,10 +7517,6 @@ void G_AddGhost(char *defdemoname)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (ghostversion != 0x0001)
|
||||
{
|
||||
#endif
|
||||
if (READUINT8(p) != 0)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname);
|
||||
|
|
@ -7736,6 +7538,7 @@ void G_AddGhost(char *defdemoname)
|
|||
p += 16;
|
||||
|
||||
p += 4; // score
|
||||
p += 2; // powerlevel
|
||||
|
||||
kartspeed = READUINT8(p);
|
||||
kartweight = READUINT8(p);
|
||||
|
|
@ -7747,9 +7550,6 @@ void G_AddGhost(char *defdemoname)
|
|||
Z_Free(buffer);
|
||||
return;
|
||||
}
|
||||
#ifdef DEMO_COMPAT_100
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
if (!stricmp(skins[i].name,skin))
|
||||
|
|
@ -7849,18 +7649,13 @@ void G_UpdateStaffGhostName(lumpnum_t l)
|
|||
ghostversion = READUINT16(p);
|
||||
switch(ghostversion)
|
||||
{
|
||||
case DEMOVERSION: // latest always supported
|
||||
p += 64; // full demo title
|
||||
break;
|
||||
case DEMOVERSION: // latest always supported
|
||||
p += 64; // full demo title
|
||||
break;
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
case 0x0001:
|
||||
break;
|
||||
#endif
|
||||
|
||||
// too old, cannot support.
|
||||
default:
|
||||
goto fail;
|
||||
// too old, cannot support.
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
p += 16; // demo checksum
|
||||
|
|
@ -7880,43 +7675,22 @@ void G_UpdateStaffGhostName(lumpnum_t l)
|
|||
goto fail; // we don't NEED to do it here, but whatever
|
||||
}
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (ghostversion != 0x0001)
|
||||
#endif
|
||||
p++; // Gametype
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (ghostversion != 0x0001)
|
||||
#endif
|
||||
G_SkipDemoExtraFiles(&p);
|
||||
|
||||
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
|
||||
{
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
p += 8; // demo time, lap
|
||||
break;
|
||||
/*case ATTACKING_NIGHTS: // 2
|
||||
p += 8; // demo time left, score
|
||||
break;*/
|
||||
default: // 3
|
||||
break;
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
p += 8; // demo time, lap
|
||||
break;
|
||||
default: // 3
|
||||
break;
|
||||
}
|
||||
|
||||
p += 4; // random seed
|
||||
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (ghostversion == 0x0001)
|
||||
{
|
||||
// Player name
|
||||
M_Memcpy(dummystaffname, p,16);
|
||||
dummystaffname[16] = '\0';
|
||||
goto fail; // Not really a failure but whatever
|
||||
}
|
||||
#endif
|
||||
|
||||
p += 4; // Extrainfo location marker
|
||||
|
||||
// Ehhhh don't need ghostversion here (?) so I'll reuse the var here
|
||||
|
|
@ -8001,10 +7775,6 @@ void G_DoPlayMetal(void)
|
|||
{
|
||||
case DEMOVERSION: // latest always supported
|
||||
break;
|
||||
#ifdef DEMO_COMPAT_100
|
||||
case 0x0001:
|
||||
I_Error("You need to implement demo compat here, doofus! %s:%d", __FILE__, __LINE__);
|
||||
#endif
|
||||
// too old, cannot support.
|
||||
default:
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n"));
|
||||
|
|
|
|||
|
|
@ -3017,7 +3017,7 @@ static void HU_DrawRankings(void)
|
|||
}
|
||||
|
||||
V_DrawCenteredString(256, 8, 0, "GAME SPEED");
|
||||
V_DrawCenteredString(256, 16, hilicol, cv_kartspeed.string);
|
||||
V_DrawCenteredString(256, 16, hilicol, kartspeed_cons_t[gamespeed].strvalue);
|
||||
}
|
||||
|
||||
// When you play, you quickly see your score because your name is displayed in white.
|
||||
|
|
|
|||
87
src/info.c
87
src/info.c
|
|
@ -70,7 +70,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"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","XMS4","XMS5","VIEW"
|
||||
"DRAF","GRES","OTFG","XMS4","XMS5","VIEW"
|
||||
};
|
||||
|
||||
// Doesn't work with g++, needs actionf_p1 (don't modify this comment)
|
||||
|
|
@ -3454,6 +3454,10 @@ state_t states[NUMSTATES] =
|
|||
|
||||
{SPR_GRES, FF_ANIMATE|FF_PAPERSPRITE, -1, {NULL}, 2, 4, S_NULL}, // S_TIREGREASE
|
||||
|
||||
{SPR_OTFG, FF_FULLBRIGHT|FF_TRANS50, TICRATE, {NULL}, 0, 0, S_NULL}, // S_OVERTIMEFOG
|
||||
{SPR_OTFG, 2|FF_FULLBRIGHT|FF_PAPERSPRITE, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIMEORB
|
||||
{SPR_OTFG, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_OVERTIMEBEAM
|
||||
|
||||
#ifdef SEENAMES
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
|
||||
#endif
|
||||
|
|
@ -20300,6 +20304,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_OVERTIMEFOG
|
||||
-1, // doomednum
|
||||
S_OVERTIMEFOG, // 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
|
||||
16<<FRACBITS, // radius
|
||||
32<<FRACBITS, // height
|
||||
-1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_OVERTIMEORB
|
||||
-1, // doomednum
|
||||
S_OVERTIMEORB, // 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
|
||||
16<<FRACBITS, // radius
|
||||
48<<FRACBITS, // height
|
||||
-1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_OVERTIMEBEAM
|
||||
-1, // doomednum
|
||||
S_OVERTIMEBEAM, // 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<<FRACBITS, // radius
|
||||
48<<FRACBITS, // height
|
||||
-1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
// ============================================================================================================================//
|
||||
|
||||
#ifdef SEENAMES
|
||||
|
|
|
|||
10
src/info.h
10
src/info.h
|
|
@ -784,6 +784,8 @@ typedef enum sprite
|
|||
SPR_DRAF,
|
||||
SPR_GRES,
|
||||
|
||||
SPR_OTFG,
|
||||
|
||||
// Xmas-specific sprites that don't fit aboxe
|
||||
SPR_XMS4,
|
||||
SPR_XMS5,
|
||||
|
|
@ -4116,6 +4118,10 @@ typedef enum state
|
|||
|
||||
S_TIREGREASE,
|
||||
|
||||
S_OVERTIMEFOG,
|
||||
S_OVERTIMEORB,
|
||||
S_OVERTIMEBEAM,
|
||||
|
||||
#ifdef SEENAMES
|
||||
S_NAMECHECK,
|
||||
#endif
|
||||
|
|
@ -4927,6 +4933,10 @@ typedef enum mobj_type
|
|||
MT_DRAFTDUST,
|
||||
MT_TIREGREASE,
|
||||
|
||||
MT_OVERTIMEFOG,
|
||||
MT_OVERTIMEORB,
|
||||
MT_OVERTIMEBEAM,
|
||||
|
||||
#ifdef SEENAMES
|
||||
MT_NAMECHECK,
|
||||
#endif
|
||||
|
|
|
|||
547
src/k_kart.c
547
src/k_kart.c
|
|
@ -4,6 +4,8 @@
|
|||
/// \brief SRB2kart general.
|
||||
/// All of the SRB2kart-unique stuff.
|
||||
|
||||
#include "k_kart.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "doomdef.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "g_game.h"
|
||||
|
|
@ -18,7 +20,6 @@
|
|||
#include "z_zone.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_cond.h"
|
||||
#include "k_kart.h"
|
||||
#include "f_finale.h"
|
||||
#include "lua_hud.h" // For Lua hud checks
|
||||
#include "lua_hook.h" // For MobjDamage and ShouldDamage
|
||||
|
|
@ -33,8 +34,6 @@
|
|||
// battlewanted is an array of the WANTED player nums, -1 for no player in that slot
|
||||
// indirectitemcooldown is timer before anyone's allowed another Shrink/SPB
|
||||
// mapreset is set when enough players fill an empty server
|
||||
// nospectategrief is the players in-game needed to eliminate the person in last
|
||||
|
||||
|
||||
//{ SRB2kart Color Code
|
||||
|
||||
|
|
@ -582,6 +581,7 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_kartspeedometer);
|
||||
CV_RegisterVar(&cv_kartvoices);
|
||||
CV_RegisterVar(&cv_karteliminatelast);
|
||||
CV_RegisterVar(&cv_kartusepwrlv);
|
||||
CV_RegisterVar(&cv_votetime);
|
||||
|
||||
CV_RegisterVar(&cv_kartdebugitem);
|
||||
|
|
@ -5140,6 +5140,25 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->mo->colorized = false;
|
||||
player->mo->color = player->skincolor;
|
||||
}
|
||||
}
|
||||
else if (player->kartstuff[k_killfield]) // You're gonna REALLY diiiiie
|
||||
{
|
||||
const INT32 flashtime = 4<<(4-(player->kartstuff[k_killfield]/TICRATE));
|
||||
if (player->kartstuff[k_killfield] == 1 || (player->kartstuff[k_killfield] % (flashtime/2) != 0))
|
||||
{
|
||||
player->mo->colorized = false;
|
||||
player->mo->color = player->skincolor;
|
||||
}
|
||||
else if (player->kartstuff[k_killfield] % flashtime == 0)
|
||||
{
|
||||
player->mo->colorized = true;
|
||||
player->mo->color = SKINCOLOR_BYZANTIUM;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->mo->colorized = true;
|
||||
player->mo->color = SKINCOLOR_RUBY;
|
||||
}
|
||||
}
|
||||
else if (player->kartstuff[k_ringboost] && (leveltime & 1)) // ring boosting
|
||||
{
|
||||
|
|
@ -5312,8 +5331,28 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
K_KartPlayerHUDUpdate(player);
|
||||
|
||||
if (G_BattleGametype() && player->kartstuff[k_bumper] > 0)
|
||||
player->kartstuff[k_wanted]++;
|
||||
if (G_BattleGametype() && player->kartstuff[k_bumper] > 0
|
||||
&& !player->kartstuff[k_spinouttimer] && !player->kartstuff[k_squishedtimer]
|
||||
&& !player->kartstuff[k_respawn] && !player->powers[pw_flashing])
|
||||
{
|
||||
player->kartstuff[k_wanted]++;
|
||||
if (battleovertime.enabled >= 10*TICRATE)
|
||||
{
|
||||
if (P_AproxDistance(player->mo->x - battleovertime.x, player->mo->y - battleovertime.y) > battleovertime.radius)
|
||||
{
|
||||
player->kartstuff[k_killfield]++;
|
||||
if (player->kartstuff[k_killfield] > 4*TICRATE)
|
||||
{
|
||||
K_SpinPlayer(player, NULL, 0, NULL, false);
|
||||
//player->kartstuff[k_killfield] = 1;
|
||||
}
|
||||
}
|
||||
else if (player->kartstuff[k_killfield] > 0)
|
||||
player->kartstuff[k_killfield]--;
|
||||
}
|
||||
}
|
||||
else if (player->kartstuff[k_killfield] > 0)
|
||||
player->kartstuff[k_killfield]--;
|
||||
|
||||
if (P_IsObjectOnGround(player->mo))
|
||||
player->kartstuff[k_waterskip] = 0;
|
||||
|
|
@ -6175,7 +6214,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
&& NO_HYUDORO && !(HOLDING_ITEM
|
||||
|| player->kartstuff[k_itemamount]
|
||||
|| player->kartstuff[k_itemroulette]
|
||||
|| player->kartstuff[k_growshrinktimer] // Being disabled during Shrink was unintended but people seemed to be okay with it sooo...
|
||||
|| player->kartstuff[k_growshrinktimer] > 0
|
||||
|| player->kartstuff[k_rocketsneakertimer]
|
||||
|| player->kartstuff[k_eggmanexplode]))
|
||||
player->kartstuff[k_userings] = 1;
|
||||
|
|
@ -7265,7 +7304,8 @@ static patch_t *kp_lapanim_number[10][3];
|
|||
static patch_t *kp_lapanim_emblem[2];
|
||||
static patch_t *kp_lapanim_hand[3];
|
||||
|
||||
static patch_t *kp_yougotem;
|
||||
static patch_t *kp_yougotem;
|
||||
static patch_t *kp_itemminimap;
|
||||
|
||||
void K_LoadKartHUDGraphics(void)
|
||||
{
|
||||
|
|
@ -7565,7 +7605,8 @@ void K_LoadKartHUDGraphics(void)
|
|||
kp_lapanim_hand[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
kp_yougotem = (patch_t *) W_CachePatchName("YOUGOTEM", PU_HUDGFX);
|
||||
kp_yougotem = (patch_t *) W_CachePatchName("YOUGOTEM", PU_HUDGFX);
|
||||
kp_itemminimap = (patch_t *) W_CachePatchName("MMAPITEM", PU_HUDGFX);
|
||||
}
|
||||
|
||||
// For the item toggle menu
|
||||
|
|
@ -9089,229 +9130,279 @@ static void K_drawKartPlayerCheck(void)
|
|||
V_DrawMappedPatch(x, CHEK_Y, V_HUDTRANS|splitflags, kp_check[pnum], colormap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags, patch_t *AutomapPic)
|
||||
{
|
||||
// amnum xpos & ypos are the icon's speed around the HUD.
|
||||
// The number being divided by is for how fast it moves.
|
||||
// The higher the number, the slower it moves.
|
||||
static void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, patch_t *icon, UINT8 *colormap, patch_t *AutomapPic)
|
||||
{
|
||||
// amnum xpos & ypos are the icon's speed around the HUD.
|
||||
// The number being divided by is for how fast it moves.
|
||||
// The higher the number, the slower it moves.
|
||||
|
||||
// am xpos & ypos are the icon's starting position. Withouht
|
||||
// it, they wouldn't 'spawn' on the top-right side of the HUD.
|
||||
|
||||
fixed_t amnumxpos, amnumypos;
|
||||
INT32 amxpos, amypos;
|
||||
|
||||
node_t *bsp = &nodes[numnodes-1];
|
||||
fixed_t maxx, minx, maxy, miny;
|
||||
|
||||
fixed_t mapwidth, mapheight;
|
||||
fixed_t xoffset, yoffset;
|
||||
fixed_t xscale, yscale, zoom;
|
||||
|
||||
maxx = maxy = INT32_MAX;
|
||||
minx = miny = INT32_MIN;
|
||||
minx = bsp->bbox[0][BOXLEFT];
|
||||
maxx = bsp->bbox[0][BOXRIGHT];
|
||||
miny = bsp->bbox[0][BOXBOTTOM];
|
||||
maxy = bsp->bbox[0][BOXTOP];
|
||||
|
||||
if (bsp->bbox[1][BOXLEFT] < minx)
|
||||
minx = bsp->bbox[1][BOXLEFT];
|
||||
if (bsp->bbox[1][BOXRIGHT] > maxx)
|
||||
maxx = bsp->bbox[1][BOXRIGHT];
|
||||
if (bsp->bbox[1][BOXBOTTOM] < miny)
|
||||
miny = bsp->bbox[1][BOXBOTTOM];
|
||||
if (bsp->bbox[1][BOXTOP] > maxy)
|
||||
maxy = bsp->bbox[1][BOXTOP];
|
||||
|
||||
// You might be wondering why these are being bitshift here
|
||||
// it's because mapwidth and height would otherwise overflow for maps larger than half the size possible...
|
||||
// map boundaries and sizes will ALWAYS be whole numbers thankfully
|
||||
// later calculations take into consideration that these are actually not in terms of FRACUNIT though
|
||||
minx >>= FRACBITS;
|
||||
maxx >>= FRACBITS;
|
||||
miny >>= FRACBITS;
|
||||
maxy >>= FRACBITS;
|
||||
|
||||
mapwidth = maxx - minx;
|
||||
mapheight = maxy - miny;
|
||||
|
||||
// These should always be small enough to be bitshift back right now
|
||||
xoffset = (minx + mapwidth/2)<<FRACBITS;
|
||||
yoffset = (miny + mapheight/2)<<FRACBITS;
|
||||
|
||||
xscale = FixedDiv(AutomapPic->width, mapwidth);
|
||||
yscale = FixedDiv(AutomapPic->height, mapheight);
|
||||
zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20);
|
||||
|
||||
amnumxpos = (FixedMul(objx, zoom) - FixedMul(xoffset, zoom));
|
||||
amnumypos = -(FixedMul(objy, zoom) - FixedMul(yoffset, zoom));
|
||||
|
||||
if (encoremode)
|
||||
amnumxpos = -amnumxpos;
|
||||
|
||||
amxpos = amnumxpos + ((hudx + AutomapPic->width/2 - (icon->width/2))<<FRACBITS);
|
||||
amypos = amnumypos + ((hudy + AutomapPic->height/2 - (icon->height/2))<<FRACBITS);
|
||||
|
||||
// do we want this? it feels unnecessary. easier to just modify the amnumxpos?
|
||||
/*if (encoremode)
|
||||
{
|
||||
flags |= V_FLIP;
|
||||
amxpos = -amnumxpos + ((hudx + AutomapPic->width/2 + (icon->width/2))<<FRACBITS);
|
||||
}*/
|
||||
|
||||
V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, icon, colormap);
|
||||
}
|
||||
|
||||
static void K_drawKartMinimap(void)
|
||||
{
|
||||
INT32 lumpnum;
|
||||
patch_t *AutomapPic;
|
||||
INT32 i = 0;
|
||||
INT32 x, y;
|
||||
INT32 minimaptrans, splitflags = (splitscreen == 3 ? 0 : V_SNAPTORIGHT); // flags should only be 0 when it's centered (4p split)
|
||||
UINT8 skin = 0;
|
||||
UINT8 *colormap = NULL;
|
||||
SINT8 localplayers[4];
|
||||
SINT8 numlocalplayers = 0;
|
||||
|
||||
// Draw the HUD only when playing in a level.
|
||||
// hu_stuff needs this, unlike st_stuff.
|
||||
if (gamestate != GS_LEVEL)
|
||||
return;
|
||||
|
||||
// am xpos & ypos are the icon's starting position. Withouht
|
||||
// it, they wouldn't 'spawn' on the top-right side of the HUD.
|
||||
// Only draw for the first player
|
||||
// Maybe move this somewhere else where this won't be a concern?
|
||||
if (stplyr != &players[displayplayers[0]])
|
||||
return;
|
||||
|
||||
lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap)));
|
||||
|
||||
if (lumpnum != -1)
|
||||
AutomapPic = W_CachePatchName(va("%sR", G_BuildMapName(gamemap)), PU_HUDGFX);
|
||||
else
|
||||
return; // no pic, just get outta here
|
||||
|
||||
x = MINI_X - (AutomapPic->width/2);
|
||||
y = MINI_Y - (AutomapPic->height/2);
|
||||
|
||||
if (timeinmap > 105)
|
||||
{
|
||||
minimaptrans = cv_kartminimap.value;
|
||||
if (timeinmap <= 113)
|
||||
minimaptrans = ((((INT32)timeinmap) - 105)*minimaptrans)/(113-105);
|
||||
if (!minimaptrans)
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT);
|
||||
splitflags |= minimaptrans;
|
||||
|
||||
if (encoremode)
|
||||
V_DrawScaledPatch(x+(AutomapPic->width), y, splitflags|V_FLIP, AutomapPic);
|
||||
else
|
||||
V_DrawScaledPatch(x, y, splitflags, AutomapPic);
|
||||
|
||||
if (!(splitscreen == 2))
|
||||
{
|
||||
splitflags &= ~minimaptrans;
|
||||
splitflags |= V_HUDTRANSHALF;
|
||||
}
|
||||
|
||||
// let offsets transfer to the heads, too!
|
||||
if (encoremode)
|
||||
x += SHORT(AutomapPic->leftoffset);
|
||||
else
|
||||
x -= SHORT(AutomapPic->leftoffset);
|
||||
y -= SHORT(AutomapPic->topoffset);
|
||||
|
||||
// Draw the super item in Battle
|
||||
if (G_BattleGametype() && battleovertime.enabled)
|
||||
{
|
||||
if (battleovertime.enabled >= 10*TICRATE || (battleovertime.enabled & 1))
|
||||
{
|
||||
const INT32 prevsplitflags = splitflags;
|
||||
splitflags &= ~V_HUDTRANSHALF;
|
||||
splitflags |= V_HUDTRANS;
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))), GTC_CACHE);
|
||||
K_drawKartMinimapIcon(battleovertime.x, battleovertime.y, x, y, splitflags, kp_itemminimap, colormap, AutomapPic);
|
||||
splitflags = prevsplitflags;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize
|
||||
for (i = 0; i < 4; i++)
|
||||
localplayers[i] = -1;
|
||||
|
||||
// Player's tiny icons on the Automap. (drawn opposite direction so player 1 is drawn last in splitscreen)
|
||||
if (ghosts)
|
||||
{
|
||||
demoghost *g = ghosts;
|
||||
while (g)
|
||||
{
|
||||
if (g->mo->skin)
|
||||
skin = ((skin_t*)g->mo->skin)-skins;
|
||||
else
|
||||
skin = 0;
|
||||
if (g->mo->color)
|
||||
{
|
||||
if (g->mo->colorized)
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, g->mo->color, GTC_CACHE);
|
||||
else
|
||||
colormap = R_GetTranslationColormap(skin, g->mo->color, GTC_CACHE);
|
||||
}
|
||||
else
|
||||
colormap = NULL;
|
||||
K_drawKartMinimapIcon(g->mo->x, g->mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
|
||||
g = g->next;
|
||||
}
|
||||
|
||||
if (!stplyr->mo || stplyr->spectator) // do we need the latter..?
|
||||
return;
|
||||
|
||||
localplayers[numlocalplayers] = stplyr-players;
|
||||
numlocalplayers++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = MAXPLAYERS-1; i >= 0; i--)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (!players[i].mo || players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (i != displayplayers[0] || splitscreen)
|
||||
{
|
||||
if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0)
|
||||
continue;
|
||||
|
||||
if (players[i].kartstuff[k_hyudorotimer] > 0)
|
||||
{
|
||||
if (!((players[i].kartstuff[k_hyudorotimer] < 1*TICRATE/2
|
||||
|| players[i].kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2))
|
||||
&& !(leveltime & 1)))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == displayplayers[0] || i == displayplayers[1] || i == displayplayers[2] || i == displayplayers[3])
|
||||
{
|
||||
// Draw display players on top of everything else
|
||||
localplayers[numlocalplayers] = i;
|
||||
numlocalplayers++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (players[i].mo->skin)
|
||||
skin = ((skin_t*)players[i].mo->skin)-skins;
|
||||
else
|
||||
skin = 0;
|
||||
|
||||
if (players[i].mo->color)
|
||||
{
|
||||
if (players[i].mo->colorized)
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, players[i].mo->color, GTC_CACHE);
|
||||
else
|
||||
colormap = R_GetTranslationColormap(skin, players[i].mo->color, GTC_CACHE);
|
||||
}
|
||||
else
|
||||
colormap = NULL;
|
||||
|
||||
K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
|
||||
// Target reticule
|
||||
if ((G_RaceGametype() && players[i].kartstuff[k_position] == spbplace)
|
||||
|| (G_BattleGametype() && K_IsPlayerWanted(&players[i])))
|
||||
K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic);
|
||||
}
|
||||
}
|
||||
|
||||
// draw our local players here, opaque.
|
||||
splitflags &= ~V_HUDTRANSHALF;
|
||||
splitflags |= V_HUDTRANS;
|
||||
|
||||
for (i = 0; i < numlocalplayers; i++)
|
||||
{
|
||||
if (i == -1)
|
||||
continue; // this doesn't interest us
|
||||
|
||||
if (players[localplayers[i]].mo->skin)
|
||||
skin = ((skin_t*)players[localplayers[i]].mo->skin)-skins;
|
||||
else
|
||||
skin = 0;
|
||||
|
||||
if (players[localplayers[i]].mo->color)
|
||||
{
|
||||
if (players[localplayers[i]].mo->colorized)
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, players[localplayers[i]].mo->color, GTC_CACHE);
|
||||
else
|
||||
colormap = R_GetTranslationColormap(skin, players[localplayers[i]].mo->color, GTC_CACHE);
|
||||
}
|
||||
else
|
||||
colormap = NULL;
|
||||
|
||||
K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
|
||||
|
||||
UINT8 skin = 0;
|
||||
|
||||
fixed_t amnumxpos, amnumypos;
|
||||
INT32 amxpos, amypos;
|
||||
|
||||
node_t *bsp = &nodes[numnodes-1];
|
||||
fixed_t maxx, minx, maxy, miny;
|
||||
|
||||
fixed_t mapwidth, mapheight;
|
||||
fixed_t xoffset, yoffset;
|
||||
fixed_t xscale, yscale, zoom;
|
||||
|
||||
if (mo->skin)
|
||||
skin = ((skin_t*)mo->skin)-skins;
|
||||
|
||||
maxx = maxy = INT32_MAX;
|
||||
minx = miny = INT32_MIN;
|
||||
minx = bsp->bbox[0][BOXLEFT];
|
||||
maxx = bsp->bbox[0][BOXRIGHT];
|
||||
miny = bsp->bbox[0][BOXBOTTOM];
|
||||
maxy = bsp->bbox[0][BOXTOP];
|
||||
|
||||
if (bsp->bbox[1][BOXLEFT] < minx)
|
||||
minx = bsp->bbox[1][BOXLEFT];
|
||||
if (bsp->bbox[1][BOXRIGHT] > maxx)
|
||||
maxx = bsp->bbox[1][BOXRIGHT];
|
||||
if (bsp->bbox[1][BOXBOTTOM] < miny)
|
||||
miny = bsp->bbox[1][BOXBOTTOM];
|
||||
if (bsp->bbox[1][BOXTOP] > maxy)
|
||||
maxy = bsp->bbox[1][BOXTOP];
|
||||
|
||||
// You might be wondering why these are being bitshift here
|
||||
// it's because mapwidth and height would otherwise overflow for maps larger than half the size possible...
|
||||
// map boundaries and sizes will ALWAYS be whole numbers thankfully
|
||||
// later calculations take into consideration that these are actually not in terms of FRACUNIT though
|
||||
minx >>= FRACBITS;
|
||||
maxx >>= FRACBITS;
|
||||
miny >>= FRACBITS;
|
||||
maxy >>= FRACBITS;
|
||||
|
||||
mapwidth = maxx - minx;
|
||||
mapheight = maxy - miny;
|
||||
|
||||
// These should always be small enough to be bitshift back right now
|
||||
xoffset = (minx + mapwidth/2)<<FRACBITS;
|
||||
yoffset = (miny + mapheight/2)<<FRACBITS;
|
||||
|
||||
xscale = FixedDiv(AutomapPic->width, mapwidth);
|
||||
yscale = FixedDiv(AutomapPic->height, mapheight);
|
||||
zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20);
|
||||
|
||||
amnumxpos = (FixedMul(mo->x, zoom) - FixedMul(xoffset, zoom));
|
||||
amnumypos = -(FixedMul(mo->y, zoom) - FixedMul(yoffset, zoom));
|
||||
|
||||
if (encoremode)
|
||||
amnumxpos = -amnumxpos;
|
||||
|
||||
amxpos = amnumxpos + ((x + AutomapPic->width/2 - (facemmapprefix[skin]->width/2))<<FRACBITS);
|
||||
amypos = amnumypos + ((y + AutomapPic->height/2 - (facemmapprefix[skin]->height/2))<<FRACBITS);
|
||||
|
||||
// do we want this? it feels unnecessary. easier to just modify the amnumxpos?
|
||||
/*if (encoremode)
|
||||
{
|
||||
flags |= V_FLIP;
|
||||
amxpos = -amnumxpos + ((x + AutomapPic->width/2 + (facemmapprefix[skin]->width/2))<<FRACBITS);
|
||||
}*/
|
||||
|
||||
if (!mo->color) // 'default' color
|
||||
V_DrawSciencePatch(amxpos, amypos, flags, facemmapprefix[skin], FRACUNIT);
|
||||
else
|
||||
{
|
||||
UINT8 *colormap;
|
||||
if (mo->colorized)
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, mo->color, GTC_CACHE);
|
||||
else
|
||||
colormap = R_GetTranslationColormap(skin, mo->color, GTC_CACHE);
|
||||
V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, facemmapprefix[skin], colormap);
|
||||
if (mo->player
|
||||
&& ((G_RaceGametype() && mo->player->kartstuff[k_position] == spbplace)
|
||||
|| (G_BattleGametype() && K_IsPlayerWanted(mo->player))))
|
||||
{
|
||||
V_DrawFixedPatch(amxpos - (4<<FRACBITS), amypos - (4<<FRACBITS), FRACUNIT, flags, kp_wantedreticle, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void K_drawKartMinimap(void)
|
||||
{
|
||||
INT32 lumpnum;
|
||||
patch_t *AutomapPic;
|
||||
INT32 i = 0;
|
||||
INT32 x, y;
|
||||
INT32 minimaptrans, splitflags = (splitscreen == 3 ? 0 : V_SNAPTORIGHT); // flags should only be 0 when it's centered (4p split)
|
||||
SINT8 localplayers[4];
|
||||
SINT8 numlocalplayers = 0;
|
||||
|
||||
// Draw the HUD only when playing in a level.
|
||||
// hu_stuff needs this, unlike st_stuff.
|
||||
if (gamestate != GS_LEVEL)
|
||||
return;
|
||||
|
||||
if (stplyr != &players[displayplayers[0]])
|
||||
return;
|
||||
|
||||
lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap)));
|
||||
|
||||
if (lumpnum != -1)
|
||||
AutomapPic = W_CachePatchName(va("%sR", G_BuildMapName(gamemap)), PU_HUDGFX);
|
||||
else
|
||||
return; // no pic, just get outta here
|
||||
|
||||
x = MINI_X - (AutomapPic->width/2);
|
||||
y = MINI_Y - (AutomapPic->height/2);
|
||||
|
||||
if (timeinmap > 105)
|
||||
{
|
||||
minimaptrans = cv_kartminimap.value;
|
||||
if (timeinmap <= 113)
|
||||
minimaptrans = ((((INT32)timeinmap) - 105)*minimaptrans)/(113-105);
|
||||
if (!minimaptrans)
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT);
|
||||
splitflags |= minimaptrans;
|
||||
|
||||
if (encoremode)
|
||||
V_DrawScaledPatch(x+(AutomapPic->width), y, splitflags|V_FLIP, AutomapPic);
|
||||
else
|
||||
V_DrawScaledPatch(x, y, splitflags, AutomapPic);
|
||||
|
||||
if (!(splitscreen == 2))
|
||||
{
|
||||
splitflags &= ~minimaptrans;
|
||||
splitflags |= V_HUDTRANSHALF;
|
||||
}
|
||||
|
||||
// let offsets transfer to the heads, too!
|
||||
if (encoremode)
|
||||
x += SHORT(AutomapPic->leftoffset);
|
||||
else
|
||||
x -= SHORT(AutomapPic->leftoffset);
|
||||
y -= SHORT(AutomapPic->topoffset);
|
||||
|
||||
// initialize
|
||||
for (i = 0; i < 4; i++)
|
||||
localplayers[i] = -1;
|
||||
|
||||
// Player's tiny icons on the Automap. (drawn opposite direction so player 1 is drawn last in splitscreen)
|
||||
if (ghosts)
|
||||
{
|
||||
demoghost *g = ghosts;
|
||||
while (g)
|
||||
{
|
||||
K_drawKartMinimapHead(g->mo, x, y, splitflags, AutomapPic);
|
||||
g = g->next;
|
||||
}
|
||||
|
||||
if (!stplyr->mo || stplyr->spectator) // do we need the latter..?
|
||||
return;
|
||||
|
||||
localplayers[numlocalplayers] = stplyr-players;
|
||||
numlocalplayers++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = MAXPLAYERS-1; i >= 0; i--)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (!players[i].mo || players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (i != displayplayers[0] || splitscreen)
|
||||
{
|
||||
if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0)
|
||||
continue;
|
||||
|
||||
if (players[i].kartstuff[k_hyudorotimer] > 0)
|
||||
{
|
||||
if (!((players[i].kartstuff[k_hyudorotimer] < 1*TICRATE/2
|
||||
|| players[i].kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2))
|
||||
&& !(leveltime & 1)))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (P_IsDisplayPlayer(&players[i]))
|
||||
{
|
||||
// Draw display players on top of everything else
|
||||
localplayers[numlocalplayers] = i;
|
||||
numlocalplayers++;
|
||||
continue;
|
||||
}
|
||||
|
||||
K_drawKartMinimapHead(players[i].mo, x, y, splitflags, AutomapPic);
|
||||
}
|
||||
}
|
||||
|
||||
// draw our local players here, opaque.
|
||||
splitflags &= ~V_HUDTRANSHALF;
|
||||
splitflags |= V_HUDTRANS;
|
||||
|
||||
for (i = 0; i < numlocalplayers; i++)
|
||||
{
|
||||
if (i == -1)
|
||||
continue; // this doesn't interest us
|
||||
K_drawKartMinimapHead(players[localplayers[i]].mo, x, y, splitflags, AutomapPic);
|
||||
}
|
||||
}
|
||||
// Target reticule
|
||||
if ((G_RaceGametype() && players[localplayers[i]].kartstuff[k_position] == spbplace)
|
||||
|| (G_BattleGametype() && K_IsPlayerWanted(&players[localplayers[i]])))
|
||||
K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic);
|
||||
}
|
||||
}
|
||||
|
||||
static void K_drawKartStartCountdown(void)
|
||||
{
|
||||
|
|
|
|||
301
src/k_pwrlv.c
Normal file
301
src/k_pwrlv.c
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
/// \file k_pwrlv.c
|
||||
/// \brief SRB2Kart Power Levels
|
||||
|
||||
#include "k_pwrlv.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "g_game.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
|
||||
#include "p_tick.h" // leveltime
|
||||
|
||||
// Online rankings for the main gametypes.
|
||||
// This array is saved to the gamedata.
|
||||
UINT16 vspowerlevel[PWRLV_NUMTYPES];
|
||||
|
||||
// Client-sided calculations done for Power Levels.
|
||||
// This is done so that clients will never be able to hack someone else's score over the server.
|
||||
UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
|
||||
|
||||
// Which players spec-scummed, and their power level before scumming.
|
||||
// On race finish, everyone is considered to have "won" against these people.
|
||||
INT16 nospectategrief[MAXPLAYERS];
|
||||
|
||||
// Game setting scrambles based on server Power Level
|
||||
SINT8 speedscramble = -1;
|
||||
SINT8 encorescramble = -1;
|
||||
|
||||
void K_ClearClientPowerLevels(void)
|
||||
{
|
||||
UINT8 i, j;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
for (j = 0; j < PWRLV_NUMTYPES; j++)
|
||||
clientpowerlevels[i][j] = 0;
|
||||
}
|
||||
|
||||
// Adapted from this: http://wiki.tockdom.com/wiki/Player_Rating
|
||||
INT16 K_CalculatePowerLevelInc(INT16 diff)
|
||||
{
|
||||
INT16 control[10] = {0,0,0,1,8,50,125,125,125,125};
|
||||
fixed_t increment = 0;
|
||||
fixed_t x;
|
||||
UINT8 j;
|
||||
|
||||
#define MAXDIFF (PWRLVRECORD_MAX - 1)
|
||||
if (diff > MAXDIFF)
|
||||
diff = MAXDIFF;
|
||||
if (diff < -MAXDIFF)
|
||||
diff = -MAXDIFF;
|
||||
#undef MAXDIFF
|
||||
|
||||
x = ((diff-2)<<FRACBITS) / PWRLVRECORD_DEF;
|
||||
|
||||
for (j = 3; j < 10; j++) // Just skipping to 3 since 0 thru 2 will always just add 0...
|
||||
{
|
||||
fixed_t f = abs(x - ((j-4)<<FRACBITS));
|
||||
fixed_t add;
|
||||
|
||||
if (f >= (2<<FRACBITS))
|
||||
{
|
||||
continue; //add = 0;
|
||||
}
|
||||
else if (f >= (1<<FRACBITS))
|
||||
{
|
||||
fixed_t f2 = (2<<FRACBITS) - f;
|
||||
add = FixedMul(FixedMul(f2, f2), f2) / 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
add = ((3*FixedMul(FixedMul(f, f), f)) - (6*FixedMul(f, f)) + (4<<FRACBITS)) / 6;
|
||||
}
|
||||
|
||||
increment += (add * control[j]);
|
||||
}
|
||||
|
||||
return (INT16)(increment >> FRACBITS);
|
||||
}
|
||||
|
||||
INT16 K_CalculatePowerLevelAvg(void)
|
||||
{
|
||||
fixed_t avg = 0;
|
||||
UINT8 div = 0;
|
||||
SINT8 t = PWRLV_DISABLED;
|
||||
UINT8 i;
|
||||
|
||||
if (!netgame || !cv_kartusepwrlv.value)
|
||||
return 0; // No average.
|
||||
|
||||
if (G_RaceGametype())
|
||||
t = PWRLV_RACE;
|
||||
else if (G_BattleGametype())
|
||||
t = PWRLV_BATTLE;
|
||||
|
||||
if (t == PWRLV_DISABLED)
|
||||
return 0; // Hmm?!
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator
|
||||
|| clientpowerlevels[i][t] == 0) // splitscreen player
|
||||
continue;
|
||||
|
||||
avg += clientpowerlevels[i][t];
|
||||
div++;
|
||||
}
|
||||
|
||||
if (!div)
|
||||
return 0; // No average.
|
||||
|
||||
avg /= div;
|
||||
|
||||
return (INT16)(avg >> FRACBITS);
|
||||
}
|
||||
|
||||
// -- K_UpdatePowerLevels could not be moved here due to usage of y_data, unfortunately. --
|
||||
|
||||
void K_SetPowerLevelScrambles(SINT8 powertype)
|
||||
{
|
||||
switch (powertype)
|
||||
{
|
||||
case PWRLV_RACE:
|
||||
if (cv_kartspeed.value == -1 || cv_kartencore.value == -1)
|
||||
{
|
||||
UINT8 speed = atoi(cv_kartspeed.defaultvalue);
|
||||
boolean encore = false;
|
||||
INT16 avg = 0, min = 0;
|
||||
UINT8 i, t = 0;
|
||||
|
||||
avg = K_CalculatePowerLevelAvg();
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (min == 0 || clientpowerlevels[i][0] < min)
|
||||
min = clientpowerlevels[i][0];
|
||||
}
|
||||
|
||||
if (min >= 7800)
|
||||
{
|
||||
if (avg >= 8200)
|
||||
t = 5;
|
||||
else
|
||||
t = 4;
|
||||
}
|
||||
else if (min >= 6800)
|
||||
{
|
||||
if (avg >= 7200)
|
||||
t = 4;
|
||||
else
|
||||
t = 3;
|
||||
}
|
||||
else if (min >= 5800)
|
||||
{
|
||||
if (avg >= 6200)
|
||||
t = 3;
|
||||
else
|
||||
t = 2;
|
||||
}
|
||||
else if (min >= 3800)
|
||||
{
|
||||
if (avg >= 4200)
|
||||
t = 2;
|
||||
else
|
||||
t = 1;
|
||||
}
|
||||
else if (min >= 1800)
|
||||
{
|
||||
if (avg >= 2200)
|
||||
t = 1;
|
||||
else
|
||||
t = 0;
|
||||
}
|
||||
else
|
||||
t = 0;
|
||||
|
||||
switch (t)
|
||||
{
|
||||
case 5:
|
||||
speed = 2;
|
||||
encore = true;
|
||||
break;
|
||||
case 4:
|
||||
speed = M_RandomChance((7<<FRACBITS)/10) ? 2 : 1;
|
||||
encore = M_RandomChance(FRACUNIT>>1);
|
||||
break;
|
||||
case 3:
|
||||
speed = M_RandomChance((3<<FRACBITS)/10) ? 2 : 1;
|
||||
encore = M_RandomChance(FRACUNIT>>2);
|
||||
break;
|
||||
case 2:
|
||||
speed = 1;
|
||||
encore = M_RandomChance(FRACUNIT>>3);
|
||||
break;
|
||||
case 1: default:
|
||||
speed = 1;
|
||||
encore = false;
|
||||
break;
|
||||
case 0:
|
||||
speed = M_RandomChance((3<<FRACBITS)/10) ? 0 : 1;
|
||||
encore = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cv_kartspeed.value == -1)
|
||||
speedscramble = speed;
|
||||
else
|
||||
speedscramble = -1;
|
||||
|
||||
if (cv_kartencore.value == -1)
|
||||
encorescramble = (encore ? 1 : 0);
|
||||
else
|
||||
encorescramble = -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void K_PlayerForfeit(UINT8 playernum, boolean pointloss)
|
||||
{
|
||||
UINT8 p = 0;
|
||||
INT32 powertype = PWRLV_DISABLED;
|
||||
UINT16 yourpower = PWRLVRECORD_DEF;
|
||||
UINT16 theirpower = PWRLVRECORD_DEF;
|
||||
INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV
|
||||
INT16 inc = 0;
|
||||
UINT8 i;
|
||||
|
||||
// power level & spectating is netgames only
|
||||
if (!netgame)
|
||||
return;
|
||||
|
||||
// This server isn't using power levels anyway!
|
||||
if (!cv_kartusepwrlv.value)
|
||||
return;
|
||||
|
||||
// Hey, I just got here!
|
||||
if (players[playernum].jointime <= 1)
|
||||
return;
|
||||
|
||||
// 20 sec into the match counts as a forfeit -- automatic loss against every other player in the match.
|
||||
if (gamestate != GS_LEVEL || leveltime <= starttime+(20*TICRATE))
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
p++;
|
||||
}
|
||||
|
||||
if (p < 2) // no players
|
||||
return;
|
||||
|
||||
if (G_RaceGametype())
|
||||
powertype = PWRLV_RACE;
|
||||
else if (G_BattleGametype())
|
||||
powertype = PWRLV_BATTLE;
|
||||
|
||||
if (powertype == PWRLV_DISABLED) // No power type?!
|
||||
return;
|
||||
|
||||
if (clientpowerlevels[playernum][powertype] == 0) // splitscreen guests don't record power level changes
|
||||
return;
|
||||
yourpower = clientpowerlevels[playernum][powertype];
|
||||
|
||||
// Set up the point compensation.
|
||||
nospectategrief[playernum] = yourpower;
|
||||
|
||||
if (!pointloss) // This is set for stuff like sync-outs, which shouldn't be so harsh on the victim!
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (i == playernum)
|
||||
continue;
|
||||
|
||||
theirpower = PWRLVRECORD_DEF;
|
||||
if (clientpowerlevels[i][powertype] != 0) // No power level acts as 5000 (used for splitscreen guests)
|
||||
theirpower = clientpowerlevels[i][powertype];
|
||||
|
||||
diff = yourpower - theirpower;
|
||||
inc -= K_CalculatePowerLevelInc(diff);
|
||||
}
|
||||
|
||||
if (inc == 0) // No change.
|
||||
return;
|
||||
|
||||
if (yourpower + inc > PWRLVRECORD_MAX) // I mean... we're subtracting... but y'know how it is :V
|
||||
inc -= ((yourpower + inc) - PWRLVRECORD_MAX);
|
||||
if (yourpower + inc < PWRLVRECORD_MIN)
|
||||
inc -= ((yourpower + inc) - PWRLVRECORD_MIN);
|
||||
|
||||
clientpowerlevels[playernum][powertype] += inc;
|
||||
|
||||
if (playernum == consoleplayer)
|
||||
{
|
||||
vspowerlevel[powertype] = clientpowerlevels[playernum][powertype];
|
||||
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||
S_StartSound(NULL, sfx_ncitem);
|
||||
G_SaveGameData(true); // save your punishment!
|
||||
}
|
||||
}
|
||||
31
src/k_pwrlv.h
Normal file
31
src/k_pwrlv.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef __K_PWRLV__
|
||||
#define __K_PWRLV__
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "doomdef.h"
|
||||
|
||||
#define PWRLV_DISABLED -1
|
||||
#define PWRLV_RACE 0
|
||||
#define PWRLV_BATTLE 1
|
||||
#define PWRLV_NUMTYPES 2
|
||||
|
||||
#define PWRLVRECORD_START 1000 // 5000?
|
||||
#define PWRLVRECORD_DEF 5000
|
||||
#define PWRLVRECORD_MIN 1
|
||||
#define PWRLVRECORD_MAX 9999
|
||||
|
||||
extern SINT8 speedscramble;
|
||||
extern SINT8 encorescramble;
|
||||
|
||||
extern UINT16 vspowerlevel[PWRLV_NUMTYPES];
|
||||
extern UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
|
||||
extern INT16 nospectategrief[MAXPLAYERS];
|
||||
|
||||
void K_ClearClientPowerLevels(void);
|
||||
INT16 K_CalculatePowerLevelInc(INT16 diff);
|
||||
INT16 K_CalculatePowerLevelAvg(void);
|
||||
//void K_UpdatePowerLevels(void);
|
||||
void K_SetPowerLevelScrambles(SINT8 powertype);
|
||||
void K_PlayerForfeit(UINT8 playernum, boolean nopointloss);
|
||||
|
||||
#endif
|
||||
|
|
@ -422,7 +422,7 @@ static void GIF_headwrite(void)
|
|||
WRITEUINT16(p, rheight);
|
||||
|
||||
// colors, aspect, etc
|
||||
WRITEUINT8(p, 0xF7);
|
||||
WRITEUINT8(p, 0xFF); // TRANSPARENTPIXEL
|
||||
WRITEUINT8(p, 0x00);
|
||||
WRITEUINT8(p, 0x00);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "r_things.h" // numskins
|
||||
//#include "r_draw.h" // R_GetColorByName
|
||||
#include "k_kart.h" // K_GetKartColorByName
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
// Map triggers for linedef executors
|
||||
// 32 triggers, one bit each
|
||||
|
|
@ -289,6 +290,8 @@ UINT8 M_CheckCondition(condition_t *cn)
|
|||
return (totalplaytime >= (unsigned)cn->requirement);
|
||||
case UC_MATCHESPLAYED: // Requires any level completed >= x times
|
||||
return (matchesplayed >= (unsigned)cn->requirement);
|
||||
case UC_POWERLEVEL: // Requires power level >= x on a certain gametype
|
||||
return (vspowerlevel[cn->extrainfo1] >= (unsigned)cn->requirement);
|
||||
case UC_GAMECLEAR: // Requires game beaten >= x times
|
||||
return (timesBeaten >= (unsigned)cn->requirement);
|
||||
case UC_ALLEMERALDS: // Requires game beaten with all 7 emeralds >= x times
|
||||
|
|
|
|||
45
src/m_cond.h
45
src/m_cond.h
|
|
@ -22,28 +22,29 @@ typedef enum
|
|||
{
|
||||
UC_PLAYTIME, // PLAYTIME [tics]
|
||||
UC_MATCHESPLAYED, // SRB2Kart: MATCHESPLAYED [x played]
|
||||
UC_GAMECLEAR, // GAMECLEAR <x times>
|
||||
UC_ALLEMERALDS, // ALLEMERALDS <x times>
|
||||
//UC_ULTIMATECLEAR, // ULTIMATECLEAR <x times>
|
||||
//UC_OVERALLSCORE, // OVERALLSCORE [score to beat]
|
||||
UC_OVERALLTIME, // OVERALLTIME [time to beat, tics]
|
||||
//UC_OVERALLRINGS, // OVERALLRINGS [rings to beat]
|
||||
UC_MAPVISITED, // MAPVISITED [map number]
|
||||
UC_MAPBEATEN, // MAPBEATEN [map number]
|
||||
UC_MAPALLEMERALDS, // MAPALLEMERALDS [map number]
|
||||
//UC_MAPULTIMATE, // MAPULTIMATE [map number]
|
||||
//UC_MAPPERFECT, // MAPPERFECT [map number]
|
||||
//UC_MAPSCORE, // MAPSCORE [map number] [score to beat]
|
||||
UC_MAPTIME, // MAPTIME [map number] [time to beat, tics]
|
||||
//UC_MAPRINGS, // MAPRINGS [map number] [rings to beat]
|
||||
//UC_NIGHTSSCORE, // NIGHTSSCORE [map number] <mare, omit or "0" for overall> [score to beat]
|
||||
//UC_NIGHTSTIME, // NIGHTSTIME [map number] <mare, omit "0" overall> [time to beat, tics]
|
||||
//UC_NIGHTSGRADE, // NIGHTSGRADE [map number] <mare, omit "0" overall> [grade]
|
||||
UC_TRIGGER, // TRIGGER [trigger number]
|
||||
UC_TOTALEMBLEMS, // TOTALEMBLEMS [number of emblems]
|
||||
UC_EMBLEM, // EMBLEM [emblem number]
|
||||
UC_EXTRAEMBLEM, // EXTRAEMBLEM [extra emblem number]
|
||||
UC_CONDITIONSET, // CONDITIONSET [condition set number]
|
||||
UC_POWERLEVEL, // SRB2Kart: POWERLEVEL [power level to reach] [gametype, "0" for race, "1" for battle]
|
||||
UC_GAMECLEAR, // GAMECLEAR <x times>
|
||||
UC_ALLEMERALDS, // ALLEMERALDS <x times>
|
||||
//UC_ULTIMATECLEAR, // ULTIMATECLEAR <x times>
|
||||
//UC_OVERALLSCORE, // OVERALLSCORE [score to beat]
|
||||
UC_OVERALLTIME, // OVERALLTIME [time to beat, tics]
|
||||
//UC_OVERALLRINGS, // OVERALLRINGS [rings to beat]
|
||||
UC_MAPVISITED, // MAPVISITED [map number]
|
||||
UC_MAPBEATEN, // MAPBEATEN [map number]
|
||||
UC_MAPALLEMERALDS, // MAPALLEMERALDS [map number]
|
||||
//UC_MAPULTIMATE, // MAPULTIMATE [map number]
|
||||
//UC_MAPPERFECT, // MAPPERFECT [map number]
|
||||
//UC_MAPSCORE, // MAPSCORE [map number] [score to beat]
|
||||
UC_MAPTIME, // MAPTIME [map number] [time to beat, tics]
|
||||
//UC_MAPRINGS, // MAPRINGS [map number] [rings to beat]
|
||||
//UC_NIGHTSSCORE, // NIGHTSSCORE [map number] <mare, omit or "0" for overall> [score to beat]
|
||||
//UC_NIGHTSTIME, // NIGHTSTIME [map number] <mare, omit "0" overall> [time to beat, tics]
|
||||
//UC_NIGHTSGRADE, // NIGHTSGRADE [map number] <mare, omit "0" overall> [grade]
|
||||
UC_TRIGGER, // TRIGGER [trigger number]
|
||||
UC_TOTALEMBLEMS, // TOTALEMBLEMS [number of emblems]
|
||||
UC_EMBLEM, // EMBLEM [emblem number]
|
||||
UC_EXTRAEMBLEM, // EXTRAEMBLEM [extra emblem number]
|
||||
UC_CONDITIONSET, // CONDITIONSET [condition set number]
|
||||
} conditiontype_t;
|
||||
|
||||
// Condition Set information
|
||||
|
|
|
|||
110
src/m_menu.c
110
src/m_menu.c
|
|
@ -57,6 +57,7 @@
|
|||
#include "st_stuff.h"
|
||||
#include "i_sound.h"
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_pwrlv.h"
|
||||
#include "d_player.h" // KITEM_ constants
|
||||
|
||||
#include "i_joy.h" // for joystick menu controls
|
||||
|
|
@ -89,6 +90,10 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#define SLIDER_WIDTH (8*SLIDER_RANGE+6)
|
||||
#define SERVERS_PER_PAGE 11
|
||||
|
||||
#if defined (NONET) || defined (TESTERS)
|
||||
#define NOMENUHOST
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
QUITMSG = 0,
|
||||
|
|
@ -241,14 +246,18 @@ static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
|
|||
|
||||
// Multiplayer
|
||||
#ifndef NONET
|
||||
#ifndef TESTERS
|
||||
static void M_StartServerMenu(INT32 choice);
|
||||
#endif
|
||||
static void M_ConnectMenu(INT32 choice);
|
||||
static void M_ConnectMenuModChecks(INT32 choice);
|
||||
static void M_Refresh(INT32 choice);
|
||||
static void M_Connect(INT32 choice);
|
||||
static void M_ChooseRoom(INT32 choice);
|
||||
#endif
|
||||
#ifndef TESTERS
|
||||
static void M_StartOfflineServerMenu(INT32 choice);
|
||||
#endif
|
||||
static void M_StartServer(INT32 choice);
|
||||
static void M_SetupMultiPlayer(INT32 choice);
|
||||
static void M_SetupMultiPlayer2(INT32 choice);
|
||||
|
|
@ -474,9 +483,14 @@ static menuitem_t MainMenu[] =
|
|||
{
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Extras", &SR_MainDef, 76},
|
||||
//{IT_CALL |IT_STRING, NULL, "1 Player", M_SinglePlayerMenu, 84},
|
||||
#ifdef TESTERS
|
||||
{IT_GRAYEDOUT, NULL, "Time Attack", NULL, 84},
|
||||
#else
|
||||
{IT_CALL |IT_STRING, NULL, "Time Attack", M_TimeAttack, 84},
|
||||
#endif
|
||||
{IT_SUBMENU|IT_STRING, NULL, "Multiplayer", &MP_MainDef, 92},
|
||||
{IT_CALL |IT_STRING, NULL, "Options", M_Options, 100},
|
||||
/* I don't think is useful at all... */
|
||||
{IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 108},
|
||||
{IT_CALL |IT_STRING, NULL, "Quit Game", M_QuitSRB2, 116},
|
||||
};
|
||||
|
|
@ -727,7 +741,9 @@ static menuitem_t SR_PandorasBox[] =
|
|||
// Sky Room Custom Unlocks
|
||||
static menuitem_t SR_MainMenu[] =
|
||||
{
|
||||
#ifndef TESTERS
|
||||
{IT_STRING|IT_SUBMENU, NULL, "Unlockables", &SR_UnlockChecklistDef, 100},
|
||||
#endif
|
||||
{IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 108},
|
||||
{IT_CALL|IT_STRING, NULL, "Replay Hut", M_ReplayHut, 116},
|
||||
{IT_DISABLED, NULL, "", NULL, 0}, // Custom1
|
||||
|
|
@ -961,12 +977,16 @@ static menuitem_t MP_MainMenu[] =
|
|||
{IT_STRING|IT_KEYHANDLER,NULL, "Player setup...", M_SetupMultiHandler,18},
|
||||
|
||||
{IT_HEADER, NULL, "Host a game", NULL, 100-24},
|
||||
#ifndef NONET
|
||||
#ifndef NOMENUHOST
|
||||
{IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 110-24},
|
||||
#else
|
||||
{IT_GRAYEDOUT, NULL, "Internet/LAN...", NULL, 110-24},
|
||||
#endif
|
||||
#ifdef TESTERS
|
||||
{IT_GRAYEDOUT, NULL, "Offline...", NULL, 118-24},
|
||||
#else
|
||||
{IT_STRING|IT_CALL, NULL, "Offline...", M_StartOfflineServerMenu, 118-24},
|
||||
#endif
|
||||
|
||||
{IT_HEADER, NULL, "Join a game", NULL, 132-24},
|
||||
#ifndef NONET
|
||||
|
|
@ -1482,8 +1502,7 @@ static menuitem_t OP_GameOptionsMenu[] =
|
|||
{IT_STRING | IT_CVAR, NULL, "Starting Bumpers", &cv_kartbumpers, 110},
|
||||
{IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 120},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Force Character", &cv_forceskin, 140},
|
||||
{IT_STRING | IT_CVAR, NULL, "Restrict Character Changes", &cv_restrictskinchange, 150},
|
||||
{IT_STRING | IT_CVAR, NULL, "Track Power Levels", &cv_kartusepwrlv, 140},
|
||||
};
|
||||
|
||||
static menuitem_t OP_ServerOptionsMenu[] =
|
||||
|
|
@ -3029,7 +3048,11 @@ void M_StartControlPanel(void)
|
|||
//MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
|
||||
|
||||
currentMenu = &MainDef;
|
||||
#ifdef TESTERS
|
||||
itemOn = multiplr;
|
||||
#else
|
||||
itemOn = singleplr;
|
||||
#endif
|
||||
}
|
||||
else if (modeattacking)
|
||||
{
|
||||
|
|
@ -4092,6 +4115,14 @@ static void M_DrawCenteredMenu(void)
|
|||
W_CachePatchName(currentMenu->menuitems[i].patch,PU_CACHE), graymap);
|
||||
y += LINEHEIGHT;
|
||||
break;
|
||||
case IT_TRANSTEXT:
|
||||
if (currentMenu->menuitems[i].alphaKey)
|
||||
y = currentMenu->y+currentMenu->menuitems[i].alphaKey;
|
||||
/* FALLTHRU */
|
||||
case IT_TRANSTEXT2:
|
||||
V_DrawCenteredString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text);
|
||||
y += SMALLLINEHEIGHT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6210,6 +6241,8 @@ static char *M_GetConditionString(condition_t cond)
|
|||
G_TicsToSeconds(cond.requirement));
|
||||
case UC_MATCHESPLAYED:
|
||||
return va("Play %d matches", cond.requirement);
|
||||
case UC_POWERLEVEL:
|
||||
return va("Reach power level %d in %s", cond.requirement, (cond.extrainfo1 == PWRLV_BATTLE ? "Battle" : "Race"));
|
||||
case UC_GAMECLEAR:
|
||||
if (cond.requirement > 1)
|
||||
return va("Beat game %d times", cond.requirement);
|
||||
|
|
@ -7294,7 +7327,7 @@ static void M_Statistics(INT32 choice)
|
|||
|
||||
static void M_DrawStatsMaps(int location)
|
||||
{
|
||||
INT32 y = 80, i = -1;
|
||||
INT32 y = 88, i = -1;
|
||||
INT16 mnum;
|
||||
extraemblem_t *exemblem;
|
||||
boolean dotopname = true, dobottomarrow = (location < statsMax);
|
||||
|
|
@ -7403,9 +7436,14 @@ static void M_DrawLevelStats(void)
|
|||
G_TicsToHours(totalplaytime),
|
||||
G_TicsToMinutes(totalplaytime, false),
|
||||
G_TicsToSeconds(totalplaytime)));
|
||||
|
||||
V_DrawString(20, 42, highlightflags, "Total Matches:");
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 42, 0, va("%i played", matchesplayed));
|
||||
|
||||
V_DrawString(20, 52, highlightflags, "Online Power Level:");
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 52, 0, va("Race: %i", vspowerlevel[PWRLV_RACE]));
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 60, 0, va("Battle: %i", vspowerlevel[PWRLV_BATTLE]));
|
||||
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
{
|
||||
if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK))
|
||||
|
|
@ -7420,18 +7458,18 @@ static void M_DrawLevelStats(void)
|
|||
besttime += mainrecords[i]->time;
|
||||
}
|
||||
|
||||
V_DrawString(20, 62, highlightflags, "Combined time records:");
|
||||
V_DrawString(20, 70, highlightflags, "Combined time records:");
|
||||
|
||||
sprintf(beststr, "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime));
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 62, (mapsunfinished ? warningflags : 0), beststr);
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 70, (mapsunfinished ? warningflags : 0), beststr);
|
||||
|
||||
if (mapsunfinished)
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 70, warningflags, va("(%d unfinished)", mapsunfinished));
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 78, warningflags, va("(%d unfinished)", mapsunfinished));
|
||||
else
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 70, recommendedflags, "(complete)");
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-16, 78, recommendedflags, "(complete)");
|
||||
|
||||
V_DrawString(32, 70, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems));
|
||||
V_DrawSmallScaledPatch(20, 70, 0, W_CachePatchName("GOTITA", PU_STATIC));
|
||||
V_DrawString(32, 78, V_ALLOWLOWERCASE, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems));
|
||||
V_DrawSmallScaledPatch(20, 78, 0, W_CachePatchName("GOTITA", PU_STATIC));
|
||||
|
||||
M_DrawStatsMaps(statsLocation);
|
||||
}
|
||||
|
|
@ -8261,6 +8299,7 @@ static void M_DrawConnectMenu(void)
|
|||
UINT16 i;
|
||||
const char *gt = "Unknown";
|
||||
const char *spd = "";
|
||||
const char *pwr = "----";
|
||||
INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE;
|
||||
|
||||
for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++)
|
||||
|
|
@ -8295,33 +8334,38 @@ static void M_DrawConnectMenu(void)
|
|||
|
||||
V_DrawString(currentMenu->x, S_LINEY(i), globalflags, serverlist[slindex].info.servername);
|
||||
|
||||
// Don't use color flags intentionally, the global yellow color will auto override the text color code
|
||||
if (serverlist[slindex].info.modifiedgame)
|
||||
V_DrawSmallString(currentMenu->x+202, S_LINEY(i)+8, globalflags, "\x85" "Mod");
|
||||
if (serverlist[slindex].info.cheatsenabled)
|
||||
V_DrawSmallString(currentMenu->x+222, S_LINEY(i)+8, globalflags, "\x83" "Cheats");
|
||||
if (serverlist[slindex].info.kartvars & SV_PASSWORD)
|
||||
V_DrawFixedPatch((currentMenu->x - 9) << FRACBITS, (S_LINEY(i)) << FRACBITS, FRACUNIT, globalflags & (~V_ALLOWLOWERCASE), W_CachePatchName("SERVLOCK", PU_CACHE), NULL);
|
||||
|
||||
V_DrawSmallString(currentMenu->x, S_LINEY(i)+8, globalflags,
|
||||
va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time)));
|
||||
|
||||
V_DrawSmallString(currentMenu->x+44,S_LINEY(i)+8, globalflags,
|
||||
va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer));
|
||||
|
||||
gt = "Unknown";
|
||||
if (serverlist[slindex].info.gametype < NUMGAMETYPES)
|
||||
gt = Gametype_Names[serverlist[slindex].info.gametype];
|
||||
|
||||
V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags,
|
||||
va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer));
|
||||
|
||||
V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, gt);
|
||||
V_DrawSmallString(currentMenu->x+108, S_LINEY(i)+8, globalflags, gt);
|
||||
|
||||
if (serverlist[slindex].info.gametype == GT_RACE)
|
||||
{
|
||||
spd = kartspeed_cons_t[serverlist[slindex].info.kartvars & SV_SPEEDMASK].strvalue;
|
||||
|
||||
V_DrawSmallString(currentMenu->x+132, S_LINEY(i)+8, globalflags, va("(%s Speed)", spd));
|
||||
V_DrawSmallString(currentMenu->x+128, S_LINEY(i)+8, globalflags, va("(%s)", spd));
|
||||
}
|
||||
|
||||
if (serverlist[slindex].info.kartvars & SV_PASSWORD)
|
||||
V_DrawFixedPatch((currentMenu->x - 9) << FRACBITS, (S_LINEY(i)) << FRACBITS, FRACUNIT, globalflags & (~V_ALLOWLOWERCASE), W_CachePatchName("SERVLOCK", PU_CACHE), NULL);
|
||||
pwr = "----";
|
||||
if (serverlist[slindex].info.avgpwrlv == -1)
|
||||
pwr = "Off";
|
||||
else if (serverlist[slindex].info.avgpwrlv > 0)
|
||||
pwr = va("%04d", serverlist[slindex].info.avgpwrlv);
|
||||
V_DrawSmallString(currentMenu->x+171, S_LINEY(i)+8, globalflags, va("Power Level: %s", pwr));
|
||||
|
||||
// Don't use color flags intentionally, the global yellow color will auto override the text color code
|
||||
if (serverlist[slindex].info.modifiedgame)
|
||||
V_DrawSmallString(currentMenu->x+245, S_LINEY(i)+8, globalflags, "\x85" "Mod");
|
||||
if (serverlist[slindex].info.cheatsenabled)
|
||||
V_DrawSmallString(currentMenu->x+265, S_LINEY(i)+8, globalflags, "\x83" "Cheats");
|
||||
|
||||
MP_ConnectMenu[i+FIRSTSERVERLINE].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
|
|
@ -8600,11 +8644,11 @@ static void M_StartServer(INT32 choice)
|
|||
paused = false;
|
||||
SV_StartSinglePlayerServer();
|
||||
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
||||
D_MapChange(cv_nextmap.value, cv_newgametype.value, (boolean)cv_kartencore.value, 1, 1, false, false);
|
||||
D_MapChange(cv_nextmap.value, cv_newgametype.value, (cv_kartencore.value == 1), 1, 1, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
D_MapChange(cv_nextmap.value, cv_newgametype.value, (boolean)cv_kartencore.value, 1, 1, false, false);
|
||||
D_MapChange(cv_nextmap.value, cv_newgametype.value, (cv_kartencore.value == 1), 1, 1, false, false);
|
||||
COM_BufAddText("dummyconsvar 1\n");
|
||||
}
|
||||
|
||||
|
|
@ -8641,7 +8685,7 @@ static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade)
|
|||
|
||||
V_DrawFill(x-1, y-1, w+2, i+2, trans); // variable reuse...
|
||||
|
||||
if (!cv_kartencore.value || gamestate == GS_TIMEATTACK || cv_newgametype.value != GT_RACE)
|
||||
if ((cv_kartencore.value != 1) || gamestate == GS_TIMEATTACK || cv_newgametype.value != GT_RACE)
|
||||
V_DrawSmallScaledPatch(x, y, 0, PictureOfLevel);
|
||||
else
|
||||
{
|
||||
|
|
@ -8774,6 +8818,7 @@ static void M_MapChange(INT32 choice)
|
|||
M_SetupNextMenu(&MISC_ChangeLevelDef);
|
||||
}
|
||||
|
||||
#ifndef TESTERS
|
||||
static void M_StartOfflineServerMenu(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
|
@ -8781,8 +8826,10 @@ static void M_StartOfflineServerMenu(INT32 choice)
|
|||
M_PrepareLevelSelect();
|
||||
M_SetupNextMenu(&MP_OfflineServerDef);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NONET
|
||||
#ifndef TESTERS
|
||||
static void M_StartServerMenu(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
|
@ -8792,6 +8839,7 @@ static void M_StartServerMenu(INT32 choice)
|
|||
M_SetupNextMenu(&MP_ServerDef);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// ==============
|
||||
// CONNECT VIA IP
|
||||
|
|
@ -8811,7 +8859,7 @@ static void M_DrawMPMainMenu(void)
|
|||
// use generic drawer for cursor, items and title
|
||||
M_DrawGenericMenu();
|
||||
|
||||
#ifndef NONET
|
||||
#ifndef NOMENUHOST
|
||||
#if MAXPLAYERS != 16
|
||||
Update the maxplayers label...
|
||||
#endif
|
||||
|
|
@ -8819,10 +8867,12 @@ Update the maxplayers label...
|
|||
((itemOn == 4) ? highlightflags : 0), "(2-16 players)");
|
||||
#endif
|
||||
|
||||
#ifndef TESTERS
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+MP_MainMenu[5].alphaKey,
|
||||
((itemOn == 5) ? highlightflags : 0),
|
||||
"(2-4 players)"
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifndef NONET
|
||||
y += MP_MainMenu[8].alphaKey;
|
||||
|
|
@ -9583,6 +9633,8 @@ static UINT8 erasecontext = 0;
|
|||
|
||||
static void M_EraseDataResponse(INT32 ch)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
if (ch != 'y' && ch != KEY_ENTER)
|
||||
return;
|
||||
|
||||
|
|
@ -9594,6 +9646,8 @@ static void M_EraseDataResponse(INT32 ch)
|
|||
// SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets
|
||||
totalplaytime = 0;
|
||||
matchesplayed = 0;
|
||||
for (i = 0; i < PWRLV_NUMTYPES; i++)
|
||||
vspowerlevel[i] = PWRLVRECORD_START;
|
||||
F_StartIntro();
|
||||
}
|
||||
if (erasecontext != 1)
|
||||
|
|
|
|||
|
|
@ -3559,8 +3559,6 @@ void A_BubbleCheck(mobj_t *actor)
|
|||
//
|
||||
void A_AttractChase(mobj_t *actor)
|
||||
{
|
||||
fixed_t z;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_AttractChase", actor))
|
||||
return;
|
||||
|
|
@ -3604,12 +3602,11 @@ void A_AttractChase(mobj_t *actor)
|
|||
{
|
||||
fixed_t offz = FixedMul(80*actor->target->scale, FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT));
|
||||
//P_SetScale(actor, (actor->destscale = actor->target->scale));
|
||||
z = actor->target->z;
|
||||
if (( actor->eflags & MFE_VERTICALFLIP ))
|
||||
z -= actor->height + offz;
|
||||
else
|
||||
z += actor->target->height + offz;
|
||||
P_TeleportMove(actor, actor->target->x, actor->target->y, z);
|
||||
actor->z = actor->target->z;
|
||||
K_MatchGenericExtraFlags(actor, actor->target);
|
||||
P_TeleportMove(actor, actor->target->x, actor->target->y,
|
||||
actor->z +
|
||||
( actor->target->height + offz )* P_MobjFlip(actor));
|
||||
actor->extravalue1++;
|
||||
}
|
||||
}
|
||||
|
|
@ -3636,15 +3633,12 @@ void A_AttractChase(mobj_t *actor)
|
|||
fixed_t dist = (actor->target->radius/4) * (16 - actor->extravalue1);
|
||||
|
||||
P_SetScale(actor, (actor->destscale = actor->target->scale - ((actor->target->scale/14) * actor->extravalue1)));
|
||||
z = actor->target->z;
|
||||
if (( actor->eflags & MFE_VERTICALFLIP ))
|
||||
z += actor->target->height - actor->height - 24 * actor->target->scale;
|
||||
else
|
||||
z += 24 * actor->target->scale;
|
||||
actor->z = actor->target->z;
|
||||
K_MatchGenericExtraFlags(actor, actor->target);
|
||||
P_TeleportMove(actor,
|
||||
actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)),
|
||||
actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)),
|
||||
z);
|
||||
actor->z + actor->target->scale * 24 * P_MobjFlip(actor));
|
||||
|
||||
actor->angle += ANG30;
|
||||
actor->extravalue1++;
|
||||
|
|
@ -8300,7 +8294,7 @@ void A_ItemPop(mobj_t *actor)
|
|||
remains->flags = actor->flags; // Transfer flags
|
||||
remains->flags2 = actor->flags2; // Transfer flags2
|
||||
remains->fuse = actor->fuse; // Transfer respawn timer
|
||||
remains->threshold = (actor->threshold == 69 ? 69 : 68);
|
||||
remains->threshold = (actor->threshold == 70 ? 70 : (actor->threshold == 69 ? 69 : 68));
|
||||
remains->skin = NULL;
|
||||
remains->spawnpoint = actor->spawnpoint;
|
||||
|
||||
|
|
@ -8314,7 +8308,7 @@ void A_ItemPop(mobj_t *actor)
|
|||
|
||||
remains->flags2 &= ~MF2_AMBUSH;
|
||||
|
||||
if (G_BattleGametype() && actor->threshold != 69)
|
||||
if (G_BattleGametype() && (actor->threshold != 69 && actor->threshold != 70))
|
||||
numgotboxes++;
|
||||
|
||||
P_RemoveMobj(actor);
|
||||
|
|
|
|||
175
src/p_inter.c
175
src/p_inter.c
|
|
@ -27,6 +27,7 @@
|
|||
#include "m_misc.h"
|
||||
#include "v_video.h" // video flags for CEchos
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
// CTF player names
|
||||
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
|
||||
|
|
@ -1763,6 +1764,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
}
|
||||
|
||||
// Easily make it so that overtime works offline
|
||||
//#define TESTOVERTIMEINFREEPLAY
|
||||
|
||||
/** Checks if the level timer is over the timelimit and the round should end,
|
||||
* unless you are in overtime. In which case leveltime may stretch out beyond
|
||||
* timelimitintics and overtime's status will be checked here each tick.
|
||||
|
|
@ -1773,7 +1777,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
*/
|
||||
void P_CheckTimeLimit(void)
|
||||
{
|
||||
INT32 i, k;
|
||||
INT32 i;
|
||||
|
||||
if (!cv_timelimit.value)
|
||||
return;
|
||||
|
|
@ -1807,71 +1811,76 @@ void P_CheckTimeLimit(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
else*/
|
||||
|
||||
//Optional tie-breaker for Match/CTF
|
||||
else*/ if (cv_overtime.value)
|
||||
if (cv_overtime.value)
|
||||
{
|
||||
INT32 playerarray[MAXPLAYERS];
|
||||
INT32 tempplayer = 0;
|
||||
INT32 spectators = 0;
|
||||
INT32 playercount = 0;
|
||||
|
||||
//Figure out if we have enough participating players to care.
|
||||
#ifndef TESTOVERTIMEINFREEPLAY
|
||||
boolean foundone = false; // Overtime is used for closing off down to a specific item.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (players[i].exiting)
|
||||
return;
|
||||
if (playeringame[i] && players[i].spectator)
|
||||
spectators++;
|
||||
}
|
||||
|
||||
if ((D_NumPlayers() - spectators) > 1)
|
||||
{
|
||||
// Play the starpost sfx after the first second of overtime.
|
||||
if (gamestate == GS_LEVEL && (leveltime == (timelimitintics + TICRATE)))
|
||||
S_StartSound(NULL, sfx_strpst);
|
||||
|
||||
// Normal Match
|
||||
if (!G_GametypeHasTeams())
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
if (foundone)
|
||||
{
|
||||
//Store the nodes of participating players in an array.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
#endif
|
||||
// Initiate the kill zone
|
||||
if (!battleovertime.enabled)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
INT32 b = 0;
|
||||
thinker_t *th;
|
||||
mobj_t *item = NULL;
|
||||
|
||||
P_RespawnBattleBoxes(); // FORCE THESE TO BE RESPAWNED FOR THIS!!!!!!!
|
||||
|
||||
// Find us an item box to center on.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
playerarray[playercount] = i;
|
||||
playercount++;
|
||||
mobj_t *thismo;
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
thismo = (mobj_t *)th;
|
||||
|
||||
if (thismo->type != MT_RANDOMITEM)
|
||||
continue;
|
||||
if (thismo->threshold == 69) // Disappears
|
||||
continue;
|
||||
|
||||
b++;
|
||||
|
||||
// Only select items that are on the ground, ignore ones in the air. Ambush flag inverts this rule.
|
||||
if ((!P_IsObjectOnGround(thismo)) != (thismo->flags2 & MF2_AMBUSH))
|
||||
continue;
|
||||
|
||||
if (item == NULL || (b < nummapboxes && P_RandomChance(((nummapboxes-b)*FRACUNIT)/nummapboxes))) // This is to throw off the RNG some
|
||||
item = thismo;
|
||||
if (b >= nummapboxes) // end early if we've found them all already
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (playercount > MAXPLAYERS)
|
||||
playercount = MAXPLAYERS;
|
||||
|
||||
//Sort 'em.
|
||||
for (i = 1; i < playercount; i++)
|
||||
{
|
||||
for (k = i; k < playercount; k++)
|
||||
if (item == NULL) // no item found, could happen if every item is in the air or has ambush flag, or the map has none
|
||||
{
|
||||
if (players[playerarray[i-1]].marescore < players[playerarray[k]].marescore)
|
||||
{
|
||||
tempplayer = playerarray[i-1];
|
||||
playerarray[i-1] = playerarray[k];
|
||||
playerarray[k] = tempplayer;
|
||||
}
|
||||
CONS_Alert(CONS_WARNING, "No usuable items for Battle overtime!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//End the round if the top players aren't tied.
|
||||
if (players[playerarray[0]].marescore == players[playerarray[1]].marescore)
|
||||
return;
|
||||
item->threshold = 70; // Set constant respawn
|
||||
battleovertime.x = item->x;
|
||||
battleovertime.y = item->y;
|
||||
battleovertime.z = item->z;
|
||||
battleovertime.radius = 4096*mapobjectscale;
|
||||
battleovertime.minradius = (cv_overtime.value == 2 ? 40 : 512) * mapobjectscale;
|
||||
battleovertime.enabled = 1;
|
||||
S_StartSound(NULL, sfx_kc47);
|
||||
}
|
||||
return;
|
||||
#ifndef TESTOVERTIMEINFREEPLAY
|
||||
}
|
||||
else
|
||||
{
|
||||
//In team match and CTF, determining a tie is much simpler. =P
|
||||
if (redscore == bluescore)
|
||||
return;
|
||||
}
|
||||
foundone = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -1882,9 +1891,6 @@ void P_CheckTimeLimit(void)
|
|||
return;
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
|
||||
/*if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);*/
|
||||
}
|
||||
|
||||
/** Checks if a player's score is over the pointlimit and the round should end.
|
||||
|
|
@ -2030,7 +2036,8 @@ void P_CheckPointLimit(void)
|
|||
// Checks whether or not to end a race netgame.
|
||||
boolean P_CheckRacers(void)
|
||||
{
|
||||
INT32 i, j, numplayersingame = 0;
|
||||
INT32 i, j, numplayersingame = 0, numexiting = 0;
|
||||
boolean griefed = false;
|
||||
|
||||
// Check if all the players in the race have finished. If so, end the level.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -2047,57 +2054,53 @@ boolean P_CheckRacers(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cv_karteliminatelast.value)
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
{
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
if (nospectategrief[j] != -1) // prevent spectate griefing
|
||||
griefed = true;
|
||||
if (!playeringame[j] || players[j].spectator)
|
||||
continue;
|
||||
numplayersingame++;
|
||||
if (players[j].exiting)
|
||||
numexiting++;
|
||||
}
|
||||
|
||||
if (cv_karteliminatelast.value && numplayersingame > 1 && !griefed)
|
||||
{
|
||||
// check if we just got unlucky and there was only one guy who was a problem
|
||||
for (j = i+1; j < MAXPLAYERS; j++)
|
||||
{
|
||||
if (!playeringame[j] || players[j].spectator)
|
||||
if (!playeringame[j] || players[j].spectator || players[j].exiting || !players[j].lives)
|
||||
continue;
|
||||
numplayersingame++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (numplayersingame > 1 && nospectategrief > 0 && numplayersingame >= nospectategrief) // prevent spectate griefing
|
||||
if (j == MAXPLAYERS) // finish anyways, force a time over
|
||||
{
|
||||
// check if we just got unlucky and there was only one guy who was a problem
|
||||
for (j = i+1; j < MAXPLAYERS; j++)
|
||||
{
|
||||
if (!playeringame[j] || players[j].spectator || players[j].exiting || !players[j].lives)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == MAXPLAYERS) // finish anyways, force a time over
|
||||
{
|
||||
P_DoTimeOver(&players[i]);
|
||||
countdown = countdown2 = 0;
|
||||
return true;
|
||||
}
|
||||
P_DoTimeOver(&players[i]);
|
||||
countdown = countdown2 = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!countdown) // Check to see if the winners have finished, to set countdown.
|
||||
{
|
||||
UINT8 numingame = 0, numexiting = 0;
|
||||
UINT8 winningpos = 1;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
numingame++;
|
||||
if (players[i].exiting)
|
||||
numexiting++;
|
||||
}
|
||||
|
||||
winningpos = max(1, numingame/2);
|
||||
if (numingame % 2) // any remainder?
|
||||
winningpos = max(1, numplayersingame/2);
|
||||
if (numplayersingame % 2) // any remainder?
|
||||
winningpos++;
|
||||
|
||||
if (numexiting >= winningpos)
|
||||
countdown = (((netgame || multiplayer) ? cv_countdowntime.value : 30)*TICRATE) + 1; // 30 seconds to finish, get going!
|
||||
}
|
||||
|
||||
if (numplayersingame < 2) // reset nospectategrief in free play
|
||||
{
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
nospectategrief[j] = -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ extern tic_t itemrespawntime[ITEMQUESIZE];
|
|||
extern size_t iquehead, iquetail;
|
||||
extern consvar_t cv_gravity/*, cv_viewheight*/;
|
||||
|
||||
void P_RespawnBattleBoxes(void);
|
||||
void P_RespawnSpecials(void);
|
||||
|
||||
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
|
||||
|
|
@ -228,6 +229,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
|
|||
void P_RunOverlays(void);
|
||||
fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player);
|
||||
void P_RunShadows(void);
|
||||
void P_RunBattleOvertime(void);
|
||||
void P_MobjThinker(mobj_t *mobj);
|
||||
boolean P_RailThinker(mobj_t *mobj);
|
||||
void P_PushableThinker(mobj_t *mobj);
|
||||
|
|
|
|||
360
src/p_mobj.c
360
src/p_mobj.c
|
|
@ -6486,6 +6486,216 @@ static void P_RemoveShadow(mobj_t *thing)
|
|||
}
|
||||
}
|
||||
|
||||
// SAL'S KART BATTLE MODE OVERTIME HANDLER
|
||||
#define MAXPLANESPERSECTOR (MAXFFLOORS+1)*2
|
||||
static void P_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjtype_t type, boolean ceiling)
|
||||
{
|
||||
UINT8 i;
|
||||
fixed_t flatz[MAXPLANESPERSECTOR];
|
||||
boolean flip[MAXPLANESPERSECTOR];
|
||||
UINT8 numflats = 0;
|
||||
mobj_t *mo;
|
||||
subsector_t *ss = R_IsPointInSubsector(x, y);
|
||||
sector_t *sec;
|
||||
|
||||
if (!ss)
|
||||
return;
|
||||
sec = ss->sector;
|
||||
|
||||
// convoluted stuff JUST to get all of the planes we need to draw orbs on :V
|
||||
|
||||
for (i = 0; i < MAXPLANESPERSECTOR; i++)
|
||||
flip[i] = false;
|
||||
|
||||
if (sec->floorpic != skyflatnum)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight);
|
||||
#else
|
||||
flatz[numflats] = (sec->floorheight);
|
||||
#endif
|
||||
numflats++;
|
||||
}
|
||||
if (sec->ceilingpic != skyflatnum && ceiling)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#else
|
||||
flatz[numflats] = (sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#endif
|
||||
flip[numflats] = true;
|
||||
numflats++;
|
||||
}
|
||||
|
||||
if (sec->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
|
||||
continue;
|
||||
if (*rover->toppic != skyflatnum)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight);
|
||||
#else
|
||||
flatz[numflats] = (*rover->topheight);
|
||||
#endif
|
||||
numflats++;
|
||||
}
|
||||
if (*rover->bottompic != skyflatnum && ceiling)
|
||||
{
|
||||
#ifdef ESLOPE
|
||||
flatz[numflats] = (*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : *rover->bottomheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#else
|
||||
flatz[numflats] = (*rover->bottomheight) - FixedMul(mobjinfo[type].height, scale);
|
||||
#endif
|
||||
flip[numflats] = true;
|
||||
numflats++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numflats <= 0) // no flats
|
||||
return;
|
||||
|
||||
for (i = 0; i < numflats; i++)
|
||||
{
|
||||
mo = P_SpawnMobj(x, y, flatz[i], type);
|
||||
|
||||
// Lastly, if this can see the skybox mobj, then... we just wasted our time :V
|
||||
if (skyboxmo[0] && !P_MobjWasRemoved(skyboxmo[0]))
|
||||
{
|
||||
const fixed_t sbz = skyboxmo[0]->z;
|
||||
fixed_t checkz = sec->floorheight;
|
||||
|
||||
while (checkz < sec->ceilingheight)
|
||||
{
|
||||
P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, checkz);
|
||||
if (P_CheckSight(skyboxmo[0], mo))
|
||||
{
|
||||
P_RemoveMobj(mo);
|
||||
break;
|
||||
}
|
||||
else
|
||||
checkz += 32*mapobjectscale;
|
||||
}
|
||||
|
||||
P_TeleportMove(skyboxmo[0], skyboxmo[0]->x, skyboxmo[0]->y, sbz);
|
||||
|
||||
if (P_MobjWasRemoved(mo))
|
||||
continue;
|
||||
}
|
||||
|
||||
P_SetScale(mo, scale);
|
||||
|
||||
if (flip[i])
|
||||
{
|
||||
mo->flags2 |= MF2_OBJECTFLIP;
|
||||
mo->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case MT_OVERTIMEFOG:
|
||||
mo->destscale = 8*mo->scale;
|
||||
mo->momz = P_RandomRange(1,8)*mo->scale;
|
||||
break;
|
||||
case MT_OVERTIMEORB:
|
||||
//mo->destscale = mo->scale/4;
|
||||
mo->frame += ((leveltime/4) % 8);
|
||||
/*if (battleovertime.enabled < 10*TICRATE)
|
||||
mo->flags2 |= MF2_SHADOW;*/
|
||||
mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90;
|
||||
mo->z += P_RandomRange(0,48) * mo->scale;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef MAXPLANESPERSECTOR
|
||||
|
||||
void P_RunBattleOvertime(void)
|
||||
{
|
||||
UINT16 i, j;
|
||||
|
||||
if (battleovertime.enabled < 10*TICRATE)
|
||||
{
|
||||
battleovertime.enabled++;
|
||||
if (battleovertime.enabled == TICRATE)
|
||||
S_StartSound(NULL, sfx_bhurry);
|
||||
if (battleovertime.enabled == 10*TICRATE)
|
||||
S_StartSound(NULL, sfx_kc40);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (battleovertime.radius > battleovertime.minradius)
|
||||
battleovertime.radius -= mapobjectscale;
|
||||
else
|
||||
battleovertime.radius = battleovertime.minradius;
|
||||
}
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
UINT8 transparency = tr_trans50;
|
||||
|
||||
if (!splitscreen && players[displayplayers[0]].mo)
|
||||
{
|
||||
INT32 dist = P_AproxDistance(battleovertime.x-players[displayplayers[0]].mo->x, battleovertime.y-players[displayplayers[0]].mo->y);
|
||||
transparency = max(0, NUMTRANSMAPS - ((256 + (dist>>FRACBITS)) / 256));
|
||||
}
|
||||
|
||||
if (transparency < NUMTRANSMAPS)
|
||||
{
|
||||
mobj_t *beam = P_SpawnMobj(battleovertime.x, battleovertime.y, battleovertime.z + (mobjinfo[MT_RANDOMITEM].height/2), MT_OVERTIMEBEAM);
|
||||
P_SetScale(beam, beam->scale*2);
|
||||
if (transparency > 0)
|
||||
beam->frame |= transparency<<FF_TRANSSHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
// 16 orbs at the normal minimum size of 512
|
||||
{
|
||||
const fixed_t pi = (22<<FRACBITS) / 7; // loose approximation, this doesn't need to be incredibly precise
|
||||
fixed_t scale = mapobjectscale + (battleovertime.radius/2048);
|
||||
fixed_t sprwidth = 32*scale;
|
||||
fixed_t circumference = FixedMul(pi, battleovertime.radius<<1);
|
||||
UINT16 orbs = circumference / sprwidth;
|
||||
angle_t angoff = ANGLE_MAX / orbs;
|
||||
|
||||
for (i = 0; i < orbs; i++)
|
||||
{
|
||||
angle_t ang = (i * angoff) + FixedAngle((leveltime/2)<<FRACBITS);
|
||||
fixed_t x = battleovertime.x + P_ReturnThrustX(NULL, ang, battleovertime.radius - FixedMul(mobjinfo[MT_OVERTIMEORB].radius, scale));
|
||||
fixed_t y = battleovertime.y + P_ReturnThrustY(NULL, ang, battleovertime.radius - FixedMul(mobjinfo[MT_OVERTIMEORB].radius, scale));
|
||||
P_SpawnOvertimeParticles(x, y, scale, MT_OVERTIMEORB, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (battleovertime.enabled < 10*TICRATE)
|
||||
return;
|
||||
|
||||
/*if (!S_IdPlaying(sfx_s3kd4s)) // global ambience
|
||||
S_StartSoundAtVolume(NULL, sfx_s3kd4s, min(255, ((4096*mapobjectscale) - battleovertime.radius)>>FRACBITS / 2));*/
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
j = 0;
|
||||
while (j < 32) // max attempts
|
||||
{
|
||||
fixed_t x = battleovertime.x + ((P_RandomRange(-64,64) * 128)<<FRACBITS);
|
||||
fixed_t y = battleovertime.y + ((P_RandomRange(-64,64) * 128)<<FRACBITS);
|
||||
fixed_t closestdist = battleovertime.radius + (8*mobjinfo[MT_OVERTIMEFOG].radius);
|
||||
j++;
|
||||
if (P_AproxDistance(x-battleovertime.x, y-battleovertime.y) < closestdist)
|
||||
continue;
|
||||
P_SpawnOvertimeParticles(x, y, 4*mapobjectscale, MT_OVERTIMEFOG, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void A_BossDeath(mobj_t *mo);
|
||||
// AI for the Koopa boss.
|
||||
static void P_KoopaThinker(mobj_t *koopa)
|
||||
|
|
@ -7097,7 +7307,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
mobj->x = mobj->target->x;
|
||||
mobj->y = mobj->target->y;
|
||||
|
||||
if (!splitscreen)
|
||||
if (!splitscreen && players[displayplayers[0]].mo)
|
||||
{
|
||||
scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x,
|
||||
players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale);
|
||||
|
|
@ -8534,18 +8744,13 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
return;
|
||||
}
|
||||
|
||||
mobj->z = mobj->target->z;
|
||||
|
||||
K_MatchGenericExtraFlags(mobj, mobj->target);
|
||||
{
|
||||
fixed_t z;
|
||||
z = mobj->target->z;
|
||||
if (( mobj->eflags & MFE_VERTICALFLIP ))
|
||||
z -= mobj->height;
|
||||
else
|
||||
z += mobj->target->height;
|
||||
P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT),
|
||||
mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT),
|
||||
z);
|
||||
}
|
||||
|
||||
P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT),
|
||||
mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT),
|
||||
mobj->z + mobj->target->height * P_MobjFlip(mobj));
|
||||
break;
|
||||
case MT_TIREGREASE:
|
||||
if (!mobj->target || P_MobjWasRemoved(mobj->target) || !mobj->target->player
|
||||
|
|
@ -9317,6 +9522,40 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
trail->color = mobj->color;
|
||||
}
|
||||
break;
|
||||
case MT_RANDOMITEM:
|
||||
if (G_BattleGametype() && mobj->threshold == 70)
|
||||
{
|
||||
mobj->color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1)));
|
||||
mobj->colorized = true;
|
||||
|
||||
if (battleovertime.enabled)
|
||||
{
|
||||
angle_t ang = FixedAngle((leveltime % 360) << FRACBITS);
|
||||
fixed_t z = battleovertime.z;
|
||||
fixed_t dist;
|
||||
mobj_t *ghost;
|
||||
|
||||
/*if (z < mobj->subsector->sector->floorheight)
|
||||
z = mobj->subsector->sector->floorheight;*/
|
||||
|
||||
if (mobj->extravalue1 < 512)
|
||||
mobj->extravalue1++;
|
||||
dist = mobj->extravalue1 * mapobjectscale;
|
||||
|
||||
P_TeleportMove(mobj, battleovertime.x + P_ReturnThrustX(NULL, ang, dist),
|
||||
battleovertime.y + P_ReturnThrustY(NULL, ang, dist), z);
|
||||
|
||||
ghost = P_SpawnGhostMobj(mobj);
|
||||
ghost->fuse = 4;
|
||||
ghost->frame |= FF_FULLBRIGHT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->color = SKINCOLOR_NONE;
|
||||
mobj->colorized = false;
|
||||
}
|
||||
break;
|
||||
//}
|
||||
case MT_TURRET:
|
||||
P_MobjCheckWater(mobj);
|
||||
|
|
@ -9581,7 +9820,7 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
|
|||
P_RemoveMobj(mobj); // make sure they disappear
|
||||
return;
|
||||
case MT_RANDOMITEM:
|
||||
if (G_BattleGametype())
|
||||
if (G_BattleGametype() && (mobj->threshold != 70))
|
||||
{
|
||||
if (mobj->threshold != 69)
|
||||
break;
|
||||
|
|
@ -9597,8 +9836,11 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
|
|||
else
|
||||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type);
|
||||
|
||||
P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_EXPLODE); // poof into existance
|
||||
// Transfer flags2 (strongbox, objectflip)
|
||||
newmobj->flags2 = mobj->flags2 & ~MF2_DONTDRAW;
|
||||
if (mobj->threshold == 70)
|
||||
newmobj->threshold = 70;
|
||||
}
|
||||
P_RemoveMobj(mobj); // make sure they disappear
|
||||
return;
|
||||
|
|
@ -10958,6 +11200,50 @@ void P_PrecipitationEffects(void)
|
|||
}
|
||||
}
|
||||
|
||||
void P_RespawnBattleBoxes(void)
|
||||
{
|
||||
thinker_t *th;
|
||||
|
||||
if (!G_BattleGametype())
|
||||
return;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
mobj_t *box;
|
||||
mobj_t *newmobj;
|
||||
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // not a mobj
|
||||
continue;
|
||||
|
||||
box = (mobj_t *)th;
|
||||
|
||||
if (box->type != MT_RANDOMITEM || box->threshold != 68 || box->fuse) // only popped items
|
||||
continue;
|
||||
|
||||
// Respawn from mapthing if you have one!
|
||||
if (box->spawnpoint)
|
||||
{
|
||||
P_SpawnMapThing(box->spawnpoint);
|
||||
newmobj = box->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing
|
||||
P_SpawnMobj(box->spawnpoint->mobj->x, box->spawnpoint->mobj->y, box->spawnpoint->mobj->z, MT_EXPLODE); // poof into existance
|
||||
}
|
||||
else
|
||||
{
|
||||
newmobj = P_SpawnMobj(box->x, box->y, box->z, box->type);
|
||||
P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_EXPLODE); // poof into existance
|
||||
}
|
||||
|
||||
// Transfer flags2 (strongbox, objectflip)
|
||||
newmobj->flags2 = box->flags2;
|
||||
P_RemoveMobj(box); // make sure they disappear
|
||||
numgotboxes--; // you've restored a box, remove it from the count
|
||||
//continue; -- irrelevant?
|
||||
}
|
||||
|
||||
if (numgotboxes < 0)
|
||||
numgotboxes = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// P_RespawnSpecials
|
||||
//
|
||||
|
|
@ -10971,45 +11257,7 @@ void P_RespawnSpecials(void)
|
|||
mapthing_t *mthing = NULL;
|
||||
|
||||
if (G_BattleGametype() && numgotboxes >= (4*nummapboxes/5)) // Battle Mode respawns all boxes in a different way
|
||||
{
|
||||
thinker_t *th;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
mobj_t *box;
|
||||
mobj_t *newmobj;
|
||||
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // not a mobj
|
||||
continue;
|
||||
|
||||
box = (mobj_t *)th;
|
||||
|
||||
if (box->type != MT_RANDOMITEM || box->threshold != 68 || box->fuse) // only popped items
|
||||
continue;
|
||||
|
||||
// Respawn from mapthing if you have one!
|
||||
if (box->spawnpoint)
|
||||
{
|
||||
P_SpawnMapThing(box->spawnpoint);
|
||||
newmobj = box->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing
|
||||
P_SpawnMobj(box->spawnpoint->mobj->x, box->spawnpoint->mobj->y, box->spawnpoint->mobj->z, MT_EXPLODE); // poof into existance
|
||||
}
|
||||
else
|
||||
{
|
||||
newmobj = P_SpawnMobj(box->x, box->y, box->z, box->type);
|
||||
P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_EXPLODE); // poof into existance
|
||||
}
|
||||
|
||||
// Transfer flags2 (strongbox, objectflip)
|
||||
newmobj->flags2 = box->flags2;
|
||||
P_RemoveMobj(box); // make sure they disappear
|
||||
numgotboxes--; // you've restored a box, remove it from the count
|
||||
//continue; -- irrelevant?
|
||||
}
|
||||
|
||||
if (numgotboxes < 0)
|
||||
numgotboxes = 0;
|
||||
}
|
||||
P_RespawnBattleBoxes();
|
||||
|
||||
// wait time depends on player count
|
||||
for (p = 0; p < MAXPLAYERS; p++)
|
||||
|
|
@ -11021,8 +11269,16 @@ void P_RespawnSpecials(void)
|
|||
if (pcount == 1) // No respawn when alone
|
||||
return;
|
||||
else if (pcount > 1)
|
||||
{
|
||||
time = (180 - (pcount * 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;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@
|
|||
#include "p_slopes.h"
|
||||
#endif
|
||||
|
||||
// SRB2Kart
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
savedata_t savedata;
|
||||
UINT8 *save_p;
|
||||
|
||||
|
|
@ -953,8 +956,8 @@ typedef enum
|
|||
MD2_EXTVAL2 = 1<<6,
|
||||
MD2_HNEXT = 1<<7,
|
||||
MD2_HPREV = 1<<8,
|
||||
MD2_COLORIZED = 1<<9,
|
||||
MD2_WAYPOINTCAP = 1<<10
|
||||
MD2_COLORIZED = 1<<9,
|
||||
MD2_WAYPOINTCAP = 1<<10
|
||||
#ifdef ESLOPE
|
||||
, MD2_SLOPE = 1<<11
|
||||
#endif
|
||||
|
|
@ -3305,11 +3308,22 @@ static void P_NetArchiveMisc(void)
|
|||
for (i = 0; i < 4; i++)
|
||||
WRITESINT8(save_p, battlewanted[i]);
|
||||
|
||||
// battleovertime_t
|
||||
WRITEUINT16(save_p, battleovertime.enabled);
|
||||
WRITEFIXED(save_p, battleovertime.radius);
|
||||
WRITEFIXED(save_p, battleovertime.minradius);
|
||||
WRITEFIXED(save_p, battleovertime.x);
|
||||
WRITEFIXED(save_p, battleovertime.y);
|
||||
WRITEFIXED(save_p, battleovertime.z);
|
||||
|
||||
WRITEUINT32(save_p, wantedcalcdelay);
|
||||
WRITEUINT32(save_p, indirectitemcooldown);
|
||||
WRITEUINT32(save_p, hyubgone);
|
||||
WRITEUINT32(save_p, mapreset);
|
||||
WRITEUINT8(save_p, nospectategrief);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
WRITEINT16(save_p, nospectategrief[i]);
|
||||
|
||||
WRITEUINT8(save_p, thwompsactive);
|
||||
WRITESINT8(save_p, spbplace);
|
||||
|
||||
|
|
@ -3414,11 +3428,22 @@ static inline boolean P_NetUnArchiveMisc(void)
|
|||
for (i = 0; i < 4; i++)
|
||||
battlewanted[i] = READSINT8(save_p);
|
||||
|
||||
// battleovertime_t
|
||||
battleovertime.enabled = READUINT16(save_p);
|
||||
battleovertime.radius = READFIXED(save_p);
|
||||
battleovertime.minradius = READFIXED(save_p);
|
||||
battleovertime.x = READFIXED(save_p);
|
||||
battleovertime.y = READFIXED(save_p);
|
||||
battleovertime.z = READFIXED(save_p);
|
||||
|
||||
wantedcalcdelay = READUINT32(save_p);
|
||||
indirectitemcooldown = READUINT32(save_p);
|
||||
hyubgone = READUINT32(save_p);
|
||||
mapreset = READUINT32(save_p);
|
||||
nospectategrief = READUINT8(save_p);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
nospectategrief[i] = READINT16(save_p);
|
||||
|
||||
thwompsactive = (boolean)READUINT8(save_p);
|
||||
spbplace = READSINT8(save_p);
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@
|
|||
// SRB2Kart
|
||||
#include "k_kart.h"
|
||||
#include "k_waypoint.h"
|
||||
#include "k_pwrlv.h"
|
||||
|
||||
//
|
||||
// Map MD5, calculated on level load.
|
||||
|
|
@ -2397,13 +2398,21 @@ static void P_LevelInitStuff(void)
|
|||
if (G_BattleGametype())
|
||||
gamespeed = 0;
|
||||
else
|
||||
gamespeed = (UINT8)cv_kartspeed.value;
|
||||
{
|
||||
if (cv_kartspeed.value == -1)
|
||||
gamespeed = ((speedscramble == -1) ? atoi(cv_kartspeed.defaultvalue) : (UINT8)speedscramble);
|
||||
else
|
||||
gamespeed = (UINT8)cv_kartspeed.value;
|
||||
}
|
||||
franticitems = (boolean)cv_kartfrantic.value;
|
||||
comeback = (boolean)cv_kartcomeback.value;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
battlewanted[i] = -1;
|
||||
|
||||
memset(&battleovertime, 0, sizeof(struct battleovertime));
|
||||
speedscramble = encorescramble = -1;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -2781,7 +2790,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
// use gamemap to get map number.
|
||||
// 99% of the things already did, so.
|
||||
// Map header should always be in place at this point
|
||||
INT32 i, loadprecip = 1, ranspecialwipe = 0;
|
||||
INT32 i, loadprecip = 1;
|
||||
INT32 loademblems = 1;
|
||||
INT32 fromnetsave = 0;
|
||||
boolean loadedbm = false;
|
||||
|
|
@ -2860,36 +2869,50 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
|
||||
S_StartSound(NULL, sfx_ruby1);
|
||||
|
||||
// Fade to an inverted screen, with a circle fade...
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 209);
|
||||
|
||||
V_EncoreInvertScreen();
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
|
||||
|
||||
F_RunWipe(wipedefs[wipe_encore_toinvert], false, NULL, false, false);
|
||||
|
||||
// Hold on invert for extra effect.
|
||||
// (This define might be useful for other areas of code? Not sure)
|
||||
#define WAIT(timetowait) \
|
||||
locstarttime = nowtime = lastwipetic; \
|
||||
endtime = locstarttime + timetowait; \
|
||||
while (nowtime < endtime) \
|
||||
{ \
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic)) \
|
||||
I_Sleep(); \
|
||||
lastwipetic = nowtime; \
|
||||
if (moviemode) \
|
||||
M_SaveFrame(); \
|
||||
NetKeepAlive(); \
|
||||
} \
|
||||
|
||||
WAIT((3*TICRATE)/2);
|
||||
S_StartSound(NULL, sfx_ruby2);
|
||||
|
||||
// Then fade to a white screen
|
||||
F_WipeStartScreen();
|
||||
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0);
|
||||
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipe_level_final], false);
|
||||
|
||||
locstarttime = nowtime = lastwipetic;
|
||||
endtime = locstarttime + (3*TICRATE)/2;
|
||||
F_RunWipe(wipedefs[wipe_encore_towhite], false, "FADEMAP1", false, true); // wiggle the screen during this!
|
||||
|
||||
// Hold on white for extra effect.
|
||||
while (nowtime < endtime)
|
||||
{
|
||||
// wait loop
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic))
|
||||
I_Sleep();
|
||||
lastwipetic = nowtime;
|
||||
if (moviemode) // make sure we save frames for the white hold too
|
||||
M_SaveFrame();
|
||||
// THEN fade to a black screen.
|
||||
F_WipeStartScreen();
|
||||
|
||||
// Keep the network alive
|
||||
NetKeepAlive();
|
||||
}
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
|
||||
ranspecialwipe = 1;
|
||||
F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false);
|
||||
|
||||
// Wait a bit longer.
|
||||
WAIT((3*TICRATE)/4);
|
||||
}
|
||||
|
||||
// Make sure all sounds are stopped before Z_FreeTags.
|
||||
|
|
@ -2900,17 +2923,18 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
// We should be fine starting it here.
|
||||
S_Start();
|
||||
|
||||
levelfadecol = (encoremode && !ranspecialwipe ? 209 : 0);
|
||||
levelfadecol = (encoremode ? 0 : 31);
|
||||
|
||||
// Let's fade to white here
|
||||
// But only if we didn't do the encore startup wipe
|
||||
if (rendermode != render_none && !ranspecialwipe && !demo.rewinding)
|
||||
if (rendermode != render_none && !demo.rewinding)
|
||||
{
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
|
||||
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
|
||||
|
||||
F_RunWipe(wipedefs[wipe_level_toblack], false, ((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), false, false);
|
||||
}
|
||||
|
||||
// Reset the palette now all fades have been done
|
||||
|
|
@ -3285,7 +3309,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
indirectitemcooldown = 0;
|
||||
hyubgone = 0;
|
||||
mapreset = 0;
|
||||
nospectategrief = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
nospectategrief[i] = -1;
|
||||
|
||||
thwompsactive = false;
|
||||
spbplace = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -3788,10 +3788,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
|
|||
break;
|
||||
case 9: // Ring Drainer (Floor Touch)
|
||||
case 10: // Ring Drainer (No Floor Touch)
|
||||
if (leveltime % (TICRATE/2) == 0 && player->mo->health > 1)
|
||||
if (leveltime % (TICRATE/2) == 0 && player->kartstuff[k_rings] > 0)
|
||||
{
|
||||
player->mo->health--;
|
||||
player->health--;
|
||||
player->kartstuff[k_rings]--;
|
||||
S_StartSound(player->mo, sfx_itemup);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
40
src/p_tick.c
40
src/p_tick.c
|
|
@ -618,33 +618,10 @@ void P_Ticker(boolean run)
|
|||
}
|
||||
if (demo.playback)
|
||||
{
|
||||
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (demo.version == 0x0001)
|
||||
{
|
||||
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
G_ReadDemoExtraData();
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i])
|
||||
{
|
||||
//@TODO all this throwdir stuff shouldn't be here! But it's added to maintain 1.0.4 compat for now...
|
||||
// Remove for 1.1!
|
||||
if (players[i].cmd.buttons & BT_FORWARD)
|
||||
players[i].kartstuff[k_throwdir] = 1;
|
||||
else if (players[i].cmd.buttons & BT_BACKWARD)
|
||||
players[i].kartstuff[k_throwdir] = -1;
|
||||
else
|
||||
players[i].kartstuff[k_throwdir] = 0;
|
||||
|
||||
G_ReadDemoTiccmd(&players[i].cmd, i);
|
||||
}
|
||||
#ifdef DEMO_COMPAT_100
|
||||
}
|
||||
#endif
|
||||
G_ReadDemoExtraData();
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i])
|
||||
G_ReadDemoTiccmd(&players[i].cmd, i);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -665,6 +642,8 @@ void P_Ticker(boolean run)
|
|||
if (run)
|
||||
{
|
||||
P_RunThinkers();
|
||||
if (G_BattleGametype() && battleovertime.enabled)
|
||||
P_RunBattleOvertime();
|
||||
|
||||
// Run any "after all the other thinkers" stuff
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -760,11 +739,6 @@ void P_Ticker(boolean run)
|
|||
}
|
||||
else if (demo.playback) // Use Ghost data for consistency checks.
|
||||
{
|
||||
#ifdef DEMO_COMPAT_100
|
||||
if (demo.version == 0x0001)
|
||||
G_ConsGhostTic(0);
|
||||
else
|
||||
#endif
|
||||
G_ConsAllGhostTics();
|
||||
}
|
||||
|
||||
|
|
@ -827,6 +801,8 @@ void P_PreTicker(INT32 frames)
|
|||
}
|
||||
|
||||
P_RunThinkers();
|
||||
if (G_BattleGametype() && battleovertime.enabled)
|
||||
P_RunBattleOvertime();
|
||||
|
||||
// Run any "after all the other thinkers" stuff
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
|
|||
|
|
@ -8055,8 +8055,6 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
cmd = &player->cmd;
|
||||
|
||||
//@TODO This fixes a one-tic latency on direction handling, AND makes behavior consistent while paused, but is not BC with 1.0.4. Do this for 1.1!
|
||||
#if 0
|
||||
// SRB2kart
|
||||
// Save the dir the player is holding
|
||||
// to allow items to be thrown forward or backward.
|
||||
|
|
@ -8066,7 +8064,6 @@ void P_PlayerThink(player_t *player)
|
|||
player->kartstuff[k_throwdir] = -1;
|
||||
else
|
||||
player->kartstuff[k_throwdir] = 0;
|
||||
#endif
|
||||
|
||||
// Add some extra randomization.
|
||||
if (cmd->forwardmove)
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
|||
texturememory += blocksize;
|
||||
block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]);
|
||||
|
||||
memset(block, 0xF7, blocksize+1); // Transparency hack
|
||||
memset(block, 0xFF, blocksize+1); // TRANSPARENTPIXEL
|
||||
|
||||
// columns lookup table
|
||||
colofs = (UINT32 *)(void *)block;
|
||||
|
|
@ -1177,7 +1177,6 @@ void R_ClearColormaps(void)
|
|||
//
|
||||
static double deltas[256][3], map[256][3];
|
||||
|
||||
static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
|
||||
static int RoundUp(double number);
|
||||
|
||||
#ifdef HASINVERT
|
||||
|
|
@ -1403,7 +1402,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
|
|||
|
||||
// Thanks to quake2 source!
|
||||
// utils3/qdata/images.c
|
||||
static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
|
||||
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
|
||||
{
|
||||
int dr, dg, db;
|
||||
int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i;
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap);
|
|||
void R_ClearColormaps(void);
|
||||
INT32 R_ColormapNumForName(char *name);
|
||||
INT32 R_CreateColormap(char *p1, char *p2, char *p3);
|
||||
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
|
||||
#ifdef HASINVERT
|
||||
void R_MakeInvertmap(void);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ static char returnWadPath[256];
|
|||
#include "../d_net.h"
|
||||
#include "../g_game.h"
|
||||
#include "../filesrch.h"
|
||||
#include "../k_pwrlv.h"
|
||||
#include "endtxt.h"
|
||||
#include "sdlmain.h"
|
||||
|
||||
|
|
@ -3056,6 +3057,11 @@ void I_Quit(void)
|
|||
#ifndef NONET
|
||||
D_SaveBan(); // save the ban list
|
||||
#endif
|
||||
|
||||
// Make sure you lose points for ALT-F4
|
||||
if (Playing())
|
||||
K_PlayerForfeit(consoleplayer, true);
|
||||
|
||||
G_SaveGameData(false); // Tails 12-08-2002
|
||||
//added:16-02-98: when recording a demo, should exit using 'q' key,
|
||||
// but sometimes we forget and use 'F10'.. so save here too.
|
||||
|
|
@ -3177,11 +3183,14 @@ void I_Error(const char *error, ...)
|
|||
#endif
|
||||
G_SaveGameData(false); // Tails 12-08-2002
|
||||
|
||||
/* Prevent segmentation fault if testers go to Record Attack... */
|
||||
#ifndef TESTERS
|
||||
// Shutdown. Here might be other errors.
|
||||
if (demo.recording)
|
||||
G_CheckDemoStatus();
|
||||
if (metalrecording)
|
||||
G_StopMetalRecording();
|
||||
#endif
|
||||
|
||||
D_QuitNetGame();
|
||||
I_ShutdownMusic();
|
||||
|
|
|
|||
|
|
@ -233,6 +233,7 @@ static char returnWadPath[256];
|
|||
#include "../d_net.h"
|
||||
#include "../g_game.h"
|
||||
#include "../filesrch.h"
|
||||
#include "../k_pwrlv.h"
|
||||
#include "endtxt.h"
|
||||
#include "sdlmain.h"
|
||||
|
||||
|
|
@ -2977,6 +2978,11 @@ void I_Quit(void)
|
|||
#ifndef NONET
|
||||
D_SaveBan(); // save the ban list
|
||||
#endif
|
||||
|
||||
// Make sure you lose points for ALT-F4
|
||||
if (Playing())
|
||||
K_PlayerForfeit(consoleplayer, true);
|
||||
|
||||
G_SaveGameData(); // Tails 12-08-2002
|
||||
//added:16-02-98: when recording a demo, should exit using 'q' key,
|
||||
// but sometimes we forget and use 'F10'.. so save here too.
|
||||
|
|
|
|||
|
|
@ -815,6 +815,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"chain", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Mementos Reaper
|
||||
{"mkuma", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Trigger Happy Havoc Monokuma
|
||||
{"toada", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Arid Sands Toad scream
|
||||
{"bhurry", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // v1.0.2 Battle overtime
|
||||
{"bsnipe", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Banana sniping
|
||||
{"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // :shitsfree:
|
||||
{"dbgsal", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Debug notification
|
||||
|
|
|
|||
|
|
@ -890,6 +890,7 @@ typedef enum
|
|||
sfx_chain,
|
||||
sfx_mkuma,
|
||||
sfx_toada,
|
||||
sfx_bhurry,
|
||||
sfx_bsnipe,
|
||||
sfx_itfree,
|
||||
sfx_dbgsal,
|
||||
|
|
|
|||
|
|
@ -2134,12 +2134,7 @@ void ST_Drawer(void)
|
|||
ST_MayonakaStatic();
|
||||
}
|
||||
|
||||
// Draw a white fade on level opening
|
||||
if (timeinmap < 15)
|
||||
{
|
||||
if (timeinmap <= 5)
|
||||
V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,0); // Pure white on first few frames, to hide SRB2's awful level load artifacts
|
||||
else
|
||||
V_DrawFadeScreen(0, 15-timeinmap); // Then gradually fade out from there
|
||||
}
|
||||
// Draw a fade on level opening
|
||||
if (timeinmap < 16)
|
||||
V_DrawCustomFadeScreen(((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), 32-(timeinmap*2)); // Then gradually fade out from there
|
||||
}
|
||||
|
|
|
|||
103
src/v_video.c
103
src/v_video.c
|
|
@ -1287,28 +1287,75 @@ void V_DrawVhsEffect(boolean rewind)
|
|||
void V_DrawFadeScreen(UINT16 color, UINT8 strength)
|
||||
{
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
HWR_FadeScreenMenuBack(color, strength);
|
||||
return;
|
||||
}
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
HWR_FadeScreenMenuBack(color, strength);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
const UINT8 *fadetable =
|
||||
{
|
||||
const UINT8 *fadetable =
|
||||
(color > 0xFFF0) // Grab a specific colormap palette?
|
||||
? R_GetTranslationColormap(color | 0xFFFF0000, strength, GTC_CACHE)
|
||||
: ((color & 0xFF00) // Color is not palette index?
|
||||
? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
|
||||
: ((UINT8 *)transtables + ((9-strength)<<FF_TRANSSHIFT) + color*256)); // Else, do TRANSMAP** fade.
|
||||
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
|
||||
UINT8 *buf = screens[0];
|
||||
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
|
||||
UINT8 *buf = screens[0];
|
||||
|
||||
// heavily simplified -- we don't need to know x or y
|
||||
// position when we're doing a full screen fade
|
||||
for (; buf < deststop; ++buf)
|
||||
*buf = fadetable[*buf];
|
||||
}
|
||||
// heavily simplified -- we don't need to know x or y
|
||||
// position when we're doing a full screen fade
|
||||
for (; buf < deststop; ++buf)
|
||||
*buf = fadetable[*buf];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Fade the screen buffer, using a custom COLORMAP lump.
|
||||
// Split from V_DrawFadeScreen, because that function has
|
||||
// WAY too many options piled on top of it as is. :V
|
||||
//
|
||||
void V_DrawCustomFadeScreen(const char *lump, UINT8 strength)
|
||||
{
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
//HWR_DrawCustomFadeScreen(color, strength);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
lumpnum_t lumpnum = LUMPERROR;
|
||||
lighttable_t *clm = NULL;
|
||||
|
||||
if (lump != NULL)
|
||||
lumpnum = W_GetNumForName(lump);
|
||||
else
|
||||
return;
|
||||
|
||||
if (lumpnum != LUMPERROR)
|
||||
{
|
||||
clm = Z_MallocAlign((256 * 32), PU_STATIC, NULL, 8);
|
||||
W_ReadLump(lumpnum, clm);
|
||||
|
||||
if (clm != NULL)
|
||||
{
|
||||
const UINT8 *fadetable = ((UINT8 *)clm + strength*256);
|
||||
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
|
||||
UINT8 *buf = screens[0];
|
||||
|
||||
// heavily simplified -- we don't need to know x or y
|
||||
// position when we're doing a full screen fade
|
||||
for (; buf < deststop; ++buf)
|
||||
*buf = fadetable[*buf];
|
||||
|
||||
Z_Free(clm);
|
||||
clm = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Simple translucency with one color, over a set number of lines starting from the top.
|
||||
|
|
@ -1332,6 +1379,34 @@ void V_DrawFadeConsBack(INT32 plines)
|
|||
*buf = consolebgmap[*buf];
|
||||
}
|
||||
|
||||
//
|
||||
// Invert the entire screen, for Encore fades
|
||||
//
|
||||
void V_EncoreInvertScreen(void)
|
||||
{
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
//HWR_EncoreInvertScreen();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
|
||||
UINT8 *buf = screens[0];
|
||||
|
||||
for (; buf < deststop; ++buf)
|
||||
{
|
||||
*buf = NearestColor(
|
||||
256 - pLocalPalette[*buf].s.red,
|
||||
256 - pLocalPalette[*buf].s.green,
|
||||
256 - pLocalPalette[*buf].s.blue
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gets string colormap, used for 0x80 color codes
|
||||
//
|
||||
UINT8 *V_GetStringColormap(INT32 colorflags)
|
||||
|
|
|
|||
|
|
@ -158,8 +158,9 @@ void V_DrawVhsEffect(boolean rewind);
|
|||
|
||||
// fade down the screen buffer before drawing the menu over
|
||||
void V_DrawFadeScreen(UINT16 color, UINT8 strength);
|
||||
|
||||
void V_DrawCustomFadeScreen(const char *lump, UINT8 strength);
|
||||
void V_DrawFadeConsBack(INT32 plines);
|
||||
void V_EncoreInvertScreen(void);
|
||||
|
||||
// draw a single character
|
||||
void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed);
|
||||
|
|
|
|||
267
src/y_inter.c
267
src/y_inter.c
|
|
@ -39,6 +39,7 @@
|
|||
#include "m_random.h" // M_RandomKey
|
||||
#include "g_input.h" // PLAYER1INPUTDOWN
|
||||
#include "k_kart.h" // colortranslations
|
||||
#include "k_pwrlv.h"
|
||||
#include "console.h" // cons_menuhighlight
|
||||
#include "lua_hook.h" // IntermissionThinker hook
|
||||
|
||||
|
|
@ -90,7 +91,7 @@ typedef union
|
|||
INT32 numplayers; // Number of players being displayed
|
||||
char levelstring[64]; // holds levelnames up to 64 characters
|
||||
// SRB2kart
|
||||
UINT8 increase[MAXPLAYERS]; // how much did the score increase by?
|
||||
INT16 increase[MAXPLAYERS]; // how much did the score increase by?
|
||||
UINT8 jitter[MAXPLAYERS]; // wiggle
|
||||
UINT32 val[MAXPLAYERS]; // Gametype-specific value
|
||||
UINT8 pos[MAXPLAYERS]; // player positions. used for ties
|
||||
|
|
@ -110,6 +111,7 @@ static boolean usetile;
|
|||
boolean usebuffer = false;
|
||||
static boolean useinterpic;
|
||||
static INT32 timer;
|
||||
static INT32 powertype = PWRLV_DISABLED;
|
||||
|
||||
static INT32 intertic;
|
||||
static INT32 endtic = -1;
|
||||
|
|
@ -193,11 +195,13 @@ static void Y_CompareBattle(INT32 i)
|
|||
|
||||
static void Y_CompareRank(INT32 i)
|
||||
{
|
||||
UINT8 increase = ((data.match.increase[i] == UINT8_MAX) ? 0 : data.match.increase[i]);
|
||||
if (!(data.match.val[data.match.numplayers] == UINT32_MAX || (players[i].score - increase) > data.match.val[data.match.numplayers]))
|
||||
INT16 increase = ((data.match.increase[i] == INT16_MIN) ? 0 : data.match.increase[i]);
|
||||
UINT32 score = (powertype != -1 ? clientpowerlevels[i][powertype] : players[i].score);
|
||||
|
||||
if (!(data.match.val[data.match.numplayers] == UINT32_MAX || (score - increase) > data.match.val[data.match.numplayers]))
|
||||
return;
|
||||
|
||||
data.match.val[data.match.numplayers] = (players[i].score - increase);
|
||||
data.match.val[data.match.numplayers] = (score - increase);
|
||||
data.match.num[data.match.numplayers] = i;
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +209,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
{
|
||||
INT32 i, j;
|
||||
boolean completed[MAXPLAYERS];
|
||||
INT32 numplayersingame = 0;
|
||||
INT32 numplayersingame = 0, numgriefers = 0;
|
||||
|
||||
// Initialize variables
|
||||
if (rankingsmode > 1)
|
||||
|
|
@ -257,14 +261,17 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
{
|
||||
data.match.val[i] = UINT32_MAX;
|
||||
|
||||
if (nospectategrief[i] != -1)
|
||||
numgriefers++;
|
||||
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
data.match.increase[i] = UINT8_MAX;
|
||||
data.match.increase[i] = INT16_MIN;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rankingsmode)
|
||||
data.match.increase[i] = UINT8_MAX;
|
||||
data.match.increase[i] = INT16_MIN;
|
||||
|
||||
numplayersingame++;
|
||||
}
|
||||
|
|
@ -276,8 +283,6 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
|
||||
for (j = 0; j < numplayersingame; j++)
|
||||
{
|
||||
INT32 nump = ((G_RaceGametype() && nospectategrief > 0) ? nospectategrief : numplayersingame);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || completed[i])
|
||||
|
|
@ -299,9 +304,10 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
else
|
||||
data.match.pos[data.match.numplayers] = data.match.numplayers+1;
|
||||
|
||||
if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] < nump))
|
||||
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] = nump - data.match.pos[data.match.numplayers];
|
||||
data.match.increase[i] = (numplayersingame + numgriefers) - data.match.pos[data.match.numplayers];
|
||||
players[i].score += data.match.increase[i];
|
||||
}
|
||||
|
||||
|
|
@ -431,7 +437,7 @@ void Y_IntermissionDrawer(void)
|
|||
const char *timeheader;
|
||||
|
||||
if (data.match.rankingsmode)
|
||||
timeheader = "RANK";
|
||||
timeheader = "PWR.LV";
|
||||
else
|
||||
timeheader = (intertype == int_race ? "TIME" : "SCORE");
|
||||
|
||||
|
|
@ -493,21 +499,23 @@ void Y_IntermissionDrawer(void)
|
|||
|
||||
if (data.match.rankingsmode)
|
||||
{
|
||||
if (data.match.increase[data.match.num[i]] != UINT8_MAX)
|
||||
if (!clientpowerlevels[data.match.num[i]][powertype]) // No power level (splitscreen guests)
|
||||
STRBUFCPY(strtime, "----");
|
||||
else
|
||||
{
|
||||
if (data.match.increase[data.match.num[i]] > 9)
|
||||
snprintf(strtime, sizeof strtime, "(+%02d)", data.match.increase[data.match.num[i]]);
|
||||
else
|
||||
snprintf(strtime, sizeof strtime, "(+ %d)", data.match.increase[data.match.num[i]]);
|
||||
if (data.match.increase[data.match.num[i]] != INT16_MIN)
|
||||
{
|
||||
snprintf(strtime, sizeof strtime, "(%d)", data.match.increase[data.match.num[i]]);
|
||||
|
||||
if (data.match.numplayers > NUMFORNEWCOLUMN)
|
||||
V_DrawRightAlignedThinString(x+135+gutter, y-1, V_6WIDTHSPACE, strtime);
|
||||
else
|
||||
V_DrawRightAlignedString(x+120+gutter, y, 0, strtime);
|
||||
if (data.match.numplayers > NUMFORNEWCOLUMN)
|
||||
V_DrawRightAlignedThinString(x+133+gutter, y-1, V_6WIDTHSPACE, strtime);
|
||||
else
|
||||
V_DrawRightAlignedString(x+118+gutter, y, 0, strtime);
|
||||
}
|
||||
|
||||
snprintf(strtime, sizeof strtime, "%d", data.match.val[i]);
|
||||
}
|
||||
|
||||
snprintf(strtime, sizeof strtime, "%d", data.match.val[i]);
|
||||
|
||||
if (data.match.numplayers > NUMFORNEWCOLUMN)
|
||||
V_DrawRightAlignedThinString(x+152+gutter, y-1, V_6WIDTHSPACE, strtime);
|
||||
else
|
||||
|
|
@ -591,9 +599,14 @@ dotimer:
|
|||
break;
|
||||
}
|
||||
|
||||
// Make it obvious that scrambling is happening next round.
|
||||
if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0))
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!"));
|
||||
//if ((intertic/TICRATE) & 1) // Make it obvious that scrambling is happening next round. (OR NOT, I GUESS)
|
||||
//{
|
||||
/*if (cv_scrambleonchange.value && cv_teamscramble.value)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!"));*/
|
||||
if (speedscramble != -1 && speedscramble != gamespeed)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, hilicol|V_ALLOWLOWERCASE|V_SNAPTOBOTTOM,
|
||||
va(M_GetText("Next race will be %s Speed!"), kartspeed_cons_t[speedscramble].strvalue));
|
||||
//}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -676,13 +689,46 @@ void Y_Ticker(void)
|
|||
{
|
||||
if (data.match.num[q] == MAXPLAYERS
|
||||
|| !data.match.increase[data.match.num[q]]
|
||||
|| data.match.increase[data.match.num[q]] == UINT8_MAX)
|
||||
|| data.match.increase[data.match.num[q]] == INT16_MIN)
|
||||
continue;
|
||||
|
||||
r++;
|
||||
data.match.jitter[data.match.num[q]] = 1;
|
||||
if (--data.match.increase[data.match.num[q]])
|
||||
kaching = false;
|
||||
|
||||
if (powertype != -1)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Basic bitch points
|
||||
if (data.match.increase[data.match.num[q]])
|
||||
{
|
||||
if (--data.match.increase[data.match.num[q]])
|
||||
kaching = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r)
|
||||
|
|
@ -782,6 +828,153 @@ static void Y_UpdateRecordReplays(void)
|
|||
CV_AddValue(&cv_nextmap, -1);
|
||||
}
|
||||
|
||||
static void K_UpdatePowerLevels(void)
|
||||
{
|
||||
INT32 i, j;
|
||||
INT32 numplayersingame = 0, numgriefers = 0;
|
||||
INT16 increment[MAXPLAYERS];
|
||||
|
||||
// Compare every single player against each other for power level increases.
|
||||
// Every player you won against gives you more points, and vice versa.
|
||||
// The amount of points won per match-up depends on the difference between the loser's power and the winner's power.
|
||||
// See K_CalculatePowerLevelInc for more info.
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
increment[i] = 0;
|
||||
|
||||
if (nospectategrief[i] != -1)
|
||||
numgriefers++;
|
||||
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
|
||||
numplayersingame++;
|
||||
}
|
||||
|
||||
for (i = 0; i < numplayersingame; i++)
|
||||
{
|
||||
UINT16 yourpower = PWRLVRECORD_DEF;
|
||||
UINT16 theirpower = PWRLVRECORD_DEF;
|
||||
INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV
|
||||
INT16 inc = 0; // Total pt increment
|
||||
UINT8 ipnum = data.match.num[i];
|
||||
UINT8 jpnum;
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Power Level Gain for player %d:\n", ipnum);
|
||||
|
||||
if (clientpowerlevels[ipnum][powertype] == 0) // splitscreen guests don't record power level changes
|
||||
continue;
|
||||
yourpower = clientpowerlevels[ipnum][powertype];
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", ipnum, yourpower);
|
||||
|
||||
for (j = 0; j < numplayersingame; j++)
|
||||
{
|
||||
boolean won = false;
|
||||
|
||||
jpnum = data.match.num[j];
|
||||
|
||||
if (i == j || ipnum == jpnum) // Same person
|
||||
continue;
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Player %d VS Player %d:\n", ipnum, jpnum);
|
||||
|
||||
if (data.match.val[i] == data.match.val[j]) // Tie -- neither get any points for this match up.
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "TIE, no change.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
theirpower = PWRLVRECORD_DEF;
|
||||
if (clientpowerlevels[jpnum][powertype] != 0) // No power level acts as 5000 (used for splitscreen guests)
|
||||
theirpower = clientpowerlevels[jpnum][powertype];
|
||||
CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower);
|
||||
|
||||
if (G_RaceGametype())
|
||||
{
|
||||
if (data.match.val[i] < data.match.val[j])
|
||||
won = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data.match.val[i] > data.match.val[j])
|
||||
won = true;
|
||||
}
|
||||
|
||||
if (won) // This player won!
|
||||
{
|
||||
diff = theirpower - yourpower;
|
||||
inc += K_CalculatePowerLevelInc(diff);
|
||||
CONS_Debug(DBG_GAMELOGIC, "WON! Diff is %d, total increment is %d\n", diff, inc);
|
||||
}
|
||||
else // This player lost...
|
||||
{
|
||||
diff = yourpower - theirpower;
|
||||
inc -= K_CalculatePowerLevelInc(diff);
|
||||
CONS_Debug(DBG_GAMELOGIC, "LOST... Diff is %d, total increment is %d\n", diff, inc);
|
||||
}
|
||||
}
|
||||
|
||||
if (numgriefers != 0) // Automatic win against quitters.
|
||||
{
|
||||
for (jpnum = 0; jpnum < MAXPLAYERS; jpnum++)
|
||||
{
|
||||
if (nospectategrief[jpnum] == -1) // Empty slot
|
||||
continue;
|
||||
|
||||
if (ipnum == jpnum) // Same person
|
||||
continue;
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Player %d VS Player %d (griefer):\n", ipnum, jpnum);
|
||||
|
||||
theirpower = PWRLVRECORD_DEF;
|
||||
if (nospectategrief[jpnum] != 0) // No power level acts as 5000 (used for splitscreen guests)
|
||||
theirpower = nospectategrief[jpnum];
|
||||
CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower);
|
||||
|
||||
diff = theirpower - yourpower;
|
||||
inc += K_CalculatePowerLevelInc(diff);
|
||||
CONS_Debug(DBG_GAMELOGIC, "AUTO-WON! Diff is %d, total increment is %d\n", diff, inc);
|
||||
}
|
||||
}
|
||||
|
||||
if (inc == 0)
|
||||
{
|
||||
data.match.increase[ipnum] = INT16_MIN;
|
||||
CONS_Debug(DBG_GAMELOGIC, "Total Result: No increment, no change.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (yourpower + inc > PWRLVRECORD_MAX)
|
||||
inc -= ((yourpower + inc) - PWRLVRECORD_MAX);
|
||||
if (yourpower + inc < PWRLVRECORD_MIN)
|
||||
inc -= ((yourpower + inc) - PWRLVRECORD_MIN);
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Total Result: Increment of %d.\n", inc);
|
||||
increment[ipnum] = inc;
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Setting final power levels...\n");
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (increment[i] == 0)
|
||||
continue;
|
||||
|
||||
data.match.increase[i] = increment[i];
|
||||
clientpowerlevels[i][powertype] += data.match.increase[i];
|
||||
|
||||
if (i == consoleplayer)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Player %d is you! Saving...\n", i);
|
||||
vspowerlevel[powertype] = clientpowerlevels[i][powertype];
|
||||
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||
S_StartSound(NULL, sfx_ncitem);
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Y_StartIntermission
|
||||
//
|
||||
|
|
@ -796,6 +989,19 @@ void Y_StartIntermission(void)
|
|||
I_Error("endtic is dirty");
|
||||
#endif
|
||||
|
||||
// set player Power Level type
|
||||
powertype = PWRLV_DISABLED;
|
||||
|
||||
if (netgame && cv_kartusepwrlv.value)
|
||||
{
|
||||
if (G_RaceGametype())
|
||||
powertype = PWRLV_RACE;
|
||||
else if (G_BattleGametype())
|
||||
powertype = PWRLV_BATTLE;
|
||||
}
|
||||
|
||||
K_SetPowerLevelScrambles(powertype);
|
||||
|
||||
if (!multiplayer)
|
||||
{
|
||||
timer = 0;
|
||||
|
|
@ -872,6 +1078,9 @@ void Y_StartIntermission(void)
|
|||
break;
|
||||
}
|
||||
|
||||
if (powertype != -1)
|
||||
K_UpdatePowerLevels();
|
||||
|
||||
//if (intertype == int_race || intertype == int_match)
|
||||
{
|
||||
//bgtile = W_CachePatchName("SRB2BACK", PU_STATIC);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue