mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'master' of https://git.do.srb2.org/KartKrew/Kart into ironman
# Conflicts: # src/g_demo.c
This commit is contained in:
commit
e65d17cd4d
54 changed files with 2017 additions and 1057 deletions
|
|
@ -1080,9 +1080,10 @@ static void COM_Toggle_f(void)
|
|||
for (i = 2; i < COM_Argc() - 1; ++i)
|
||||
{
|
||||
const char *str = COM_Argv(i);
|
||||
INT32 val;
|
||||
INT32 val = 0;
|
||||
|
||||
if (CV_CompleteValue(cvar, &str, &val))
|
||||
if (!cvar->PossibleValue ||
|
||||
CV_CompleteValue(cvar, &str, &val))
|
||||
{
|
||||
if (str ? !stricmp(cvar->string, str)
|
||||
: cvar->value == val)
|
||||
|
|
|
|||
|
|
@ -531,8 +531,10 @@ typedef enum
|
|||
CL_SEARCHING,
|
||||
CL_CHECKFILES,
|
||||
CL_DOWNLOADFILES,
|
||||
CL_DOWNLOADFAILED,
|
||||
CL_ASKJOIN,
|
||||
CL_LOADFILES,
|
||||
CL_SETUPFILES,
|
||||
CL_WAITJOINRESPONSE,
|
||||
CL_DOWNLOADSAVEGAME,
|
||||
CL_CONNECTED,
|
||||
|
|
@ -615,8 +617,12 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
break;
|
||||
case CL_ASKFULLFILELIST:
|
||||
case CL_CONFIRMCONNECT:
|
||||
case CL_DOWNLOADFAILED:
|
||||
cltext = "";
|
||||
break;
|
||||
case CL_SETUPFILES:
|
||||
cltext = M_GetText("Configuring addons...");
|
||||
break;
|
||||
case CL_ASKJOIN:
|
||||
case CL_WAITJOINRESPONSE:
|
||||
if (serverisfull)
|
||||
|
|
@ -655,8 +661,8 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, "Checking server addons...");
|
||||
totalfileslength = (INT32)((checkednum/(double)(fileneedednum)) * 256);
|
||||
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 96);
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
||||
va(" %2u/%2u Files",checkednum,fileneedednum));
|
||||
}
|
||||
|
|
@ -677,8 +683,8 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, "Loading server addons...");
|
||||
totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum)) * 256);
|
||||
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 96);
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
||||
va(" %2u/%2u Files",loadcompletednum,fileneedednum));
|
||||
}
|
||||
|
|
@ -719,8 +725,10 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
strncpy(tempname, filename, sizeof(tempname)-1);
|
||||
}
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-30, 0,
|
||||
va(M_GetText("%s downloading"), ((cl_mode == CL_DOWNLOADHTTPFILES) ? "\x82""HTTP" : "\x85""Direct")));
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-58-22, V_YELLOWMAP,
|
||||
va(M_GetText("Downloading \"%s\""), tempname));
|
||||
va(M_GetText("\"%s\""), tempname));
|
||||
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-58, V_20TRANS|V_MONOSPACE,
|
||||
va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10));
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-58, V_20TRANS|V_MONOSPACE,
|
||||
|
|
@ -736,8 +744,8 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-14, V_YELLOWMAP, "Overall Download Progress");
|
||||
totalfileslength = (INT32)((totaldldsize/(double)totalfilesrequestedsize) * 256);
|
||||
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 160);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, totalfileslength, 8, 96);
|
||||
|
||||
if (totalfilesrequestedsize>>20 >= 10) //display in MB if over 10MB
|
||||
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
|
||||
|
|
@ -1497,6 +1505,10 @@ static void M_ConfirmConnect(void)
|
|||
{
|
||||
cl_mode = CL_DOWNLOADFILES;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl_mode = CL_DOWNLOADFAILED;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_CURL
|
||||
else
|
||||
|
|
@ -1645,6 +1657,10 @@ static boolean CL_FinishedFileList(void)
|
|||
{
|
||||
cl_mode = CL_DOWNLOADFILES;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl_mode = CL_DOWNLOADFAILED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1850,8 +1866,28 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
|
||||
cl_mode = CL_LOADFILES;
|
||||
break;
|
||||
case CL_DOWNLOADFAILED:
|
||||
{
|
||||
CONS_Printf(M_GetText("Legacy downloader request packet failed.\n"));
|
||||
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
M_StartMessage(M_GetText(
|
||||
"The direct download encountered an error.\n"
|
||||
"See the logfile for more info.\n"
|
||||
"\n"
|
||||
"Press (B)\n"
|
||||
), NULL, MM_NOTHING);
|
||||
return false;
|
||||
}
|
||||
case CL_LOADFILES:
|
||||
if (CL_LoadServerFiles())
|
||||
if (CL_LoadServerFiles())
|
||||
cl_mode = CL_SETUPFILES;
|
||||
|
||||
break;
|
||||
case CL_SETUPFILES:
|
||||
if (P_PartialAddGetStage() < 0 || P_MultiSetupWadFiles(false))
|
||||
{
|
||||
*asksent = 0; //This ensure the first join ask is right away
|
||||
firstconnectattempttime = I_GetTime();
|
||||
|
|
@ -2079,7 +2115,12 @@ static void CL_ConnectToServer(void)
|
|||
{
|
||||
// If the connection was aborted for some reason, leave
|
||||
if (!CL_ServerConnectionTicker(tmpsave, &oldtic, &asksent))
|
||||
{
|
||||
if (P_PartialAddGetStage() >= 0)
|
||||
P_MultiSetupWadFiles(true); // in case any partial adds were done
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (server)
|
||||
{
|
||||
|
|
@ -2487,6 +2528,11 @@ void CL_ClearPlayer(INT32 playernum)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (players[playernum].follower)
|
||||
{
|
||||
K_RemoveFollower(&players[playernum]);
|
||||
}
|
||||
|
||||
if (players[playernum].mo)
|
||||
{
|
||||
P_RemoveMobj(players[playernum].mo);
|
||||
|
|
@ -3927,6 +3973,11 @@ static void HandleConnect(SINT8 node)
|
|||
// If a server filled out, then it'd overwrite the host and turn everyone into weird husks.....
|
||||
// It's too much effort to legimately fix right now. Just prevent it from reaching that state.
|
||||
UINT8 maxplayers = min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxconnections.value);
|
||||
UINT8 connectedplayers = 0;
|
||||
|
||||
for (i = dedicated ? 1 : 0; i < MAXPLAYERS; i++)
|
||||
if (playernode[i] != UINT8_MAX) // We use this to count players because it is affected by SV_AddWaitingPlayers when more than one client joins on the same tic, unlike playeringame and D_NumPlayers. UINT8_MAX denotes no node for that player
|
||||
connectedplayers++;
|
||||
|
||||
if (bannednode && bannednode[node].banid != SIZE_MAX)
|
||||
{
|
||||
|
|
@ -3984,7 +4035,7 @@ static void HandleConnect(SINT8 node)
|
|||
{
|
||||
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment."));
|
||||
}
|
||||
else if (D_NumPlayers() >= maxplayers)
|
||||
else if (connectedplayers >= maxplayers)
|
||||
{
|
||||
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), maxplayers));
|
||||
}
|
||||
|
|
@ -3992,7 +4043,7 @@ static void HandleConnect(SINT8 node)
|
|||
{
|
||||
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
|
||||
}
|
||||
else if (netgame && D_NumPlayers() + netbuffer->u.clientcfg.localplayers > maxplayers)
|
||||
else if (netgame && connectedplayers + netbuffer->u.clientcfg.localplayers > maxplayers)
|
||||
{
|
||||
SV_SendRefuse(node, va(M_GetText("Number of local players\nwould exceed maximum: %d"), maxplayers));
|
||||
}
|
||||
|
|
@ -5475,14 +5526,6 @@ boolean TryRunTics(tic_t realtics)
|
|||
|
||||
if (ticking)
|
||||
{
|
||||
if (advancedemo)
|
||||
{
|
||||
if (timedemo_quit)
|
||||
COM_ImmedExecute("quit");
|
||||
else
|
||||
D_StartTitle();
|
||||
}
|
||||
else
|
||||
{
|
||||
// run the count * tics
|
||||
while (neededtic > gametic)
|
||||
|
|
|
|||
20
src/d_main.c
20
src/d_main.c
|
|
@ -131,7 +131,6 @@ INT32 postimgparam[MAXSPLITSCREENPLAYERS];
|
|||
boolean sound_disabled = false;
|
||||
boolean digital_disabled = false;
|
||||
|
||||
boolean advancedemo;
|
||||
#ifdef DEBUGFILE
|
||||
INT32 debugload = 0;
|
||||
#endif
|
||||
|
|
@ -913,15 +912,6 @@ void D_SRB2Loop(void)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// D_AdvanceDemo
|
||||
// Called after each demo or intro demosequence finishes
|
||||
//
|
||||
void D_AdvanceDemo(void)
|
||||
{
|
||||
advancedemo = true;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// D_SRB2Main
|
||||
// =========================================================================
|
||||
|
|
@ -997,13 +987,13 @@ void D_StartTitle(void)
|
|||
//demosequence = -1;
|
||||
G_SetGametype(GT_RACE); // SRB2kart
|
||||
paused = false;
|
||||
advancedemo = false;
|
||||
|
||||
// clear cmd building stuff
|
||||
memset(gamekeydown, 0, sizeof (gamekeydown));
|
||||
memset(deviceResponding, false, sizeof (deviceResponding));
|
||||
|
||||
F_StartTitleScreen();
|
||||
M_ClearMenus(false);
|
||||
|
||||
// Reset the palette
|
||||
if (rendermode != render_none)
|
||||
|
|
@ -1214,8 +1204,6 @@ void D_SRB2Main(void)
|
|||
{
|
||||
INT32 i, p;
|
||||
|
||||
INT32 numbasemapheaders;
|
||||
|
||||
INT32 pstartmap = 1;
|
||||
boolean autostart = false;
|
||||
|
||||
|
|
@ -1472,9 +1460,7 @@ void D_SRB2Main(void)
|
|||
//
|
||||
// search for mainwad maps
|
||||
//
|
||||
P_InitMapData(0);
|
||||
|
||||
numbasemapheaders = nummapheaders;
|
||||
P_InitMapData(false);
|
||||
|
||||
CON_SetLoadingProgress(LOADED_IWAD);
|
||||
|
||||
|
|
@ -1485,7 +1471,7 @@ void D_SRB2Main(void)
|
|||
//
|
||||
// search for pwad maps
|
||||
//
|
||||
P_InitMapData(numbasemapheaders);
|
||||
P_InitMapData(true);
|
||||
|
||||
CON_SetLoadingProgress(LOADED_PWAD);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
#include "d_event.h"
|
||||
#include "w_wad.h" // for MAX_WADFILES
|
||||
|
||||
extern boolean advancedemo;
|
||||
|
||||
// make sure not to write back the config until it's been correctly loaded
|
||||
extern tic_t rendergametic;
|
||||
|
||||
|
|
@ -52,7 +50,6 @@ const char *D_Home(void);
|
|||
//
|
||||
// BASE LEVEL
|
||||
//
|
||||
void D_AdvanceDemo(void);
|
||||
void D_StartTitle(void);
|
||||
|
||||
#endif //__D_MAIN__
|
||||
|
|
|
|||
271
src/d_netcmd.c
271
src/d_netcmd.c
|
|
@ -295,10 +295,10 @@ consvar_t cv_follower[MAXSPLITSCREENPLAYERS] = {
|
|||
|
||||
// player's follower colors... Also saved...
|
||||
consvar_t cv_followercolor[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("followercolor", "1", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor_OnChange),
|
||||
CVAR_INIT ("followercolor2", "1", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor2_OnChange),
|
||||
CVAR_INIT ("followercolor3", "1", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor3_OnChange),
|
||||
CVAR_INIT ("followercolor4", "1", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange)
|
||||
CVAR_INIT ("followercolor", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor_OnChange),
|
||||
CVAR_INIT ("followercolor2", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor2_OnChange),
|
||||
CVAR_INIT ("followercolor3", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor3_OnChange),
|
||||
CVAR_INIT ("followercolor4", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange)
|
||||
};
|
||||
|
||||
// last selected profile, unaccessible cvar only set internally but is saved.
|
||||
|
|
@ -386,7 +386,6 @@ consvar_t cv_gardentop = CVAR_INIT ("gardentop", "On", CV_NETVAR, CV_OnOff,
|
|||
consvar_t cv_dualsneaker = CVAR_INIT ("dualsneaker", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_triplesneaker = CVAR_INIT ("triplesneaker", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_triplebanana = CVAR_INIT ("triplebanana", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_decabanana = CVAR_INIT ("decabanana", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_tripleorbinaut = CVAR_INIT ("tripleorbinaut", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_quadorbinaut = CVAR_INIT ("quadorbinaut", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_dualjawz = CVAR_INIT ("dualjawz", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
|
@ -831,27 +830,6 @@ void D_RegisterClientCommands(void)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
||||
{
|
||||
Color_cons_t[i].value = i;
|
||||
Color_cons_t[i].strvalue = skincolors[i].name;
|
||||
}
|
||||
|
||||
for (i = 2; i < MAXSKINCOLORS; i++)
|
||||
{
|
||||
Followercolor_cons_t[i].value = i-2;
|
||||
Followercolor_cons_t[i].strvalue = skincolors[i-2].name;
|
||||
}
|
||||
|
||||
Followercolor_cons_t[1].value = FOLLOWERCOLOR_MATCH;
|
||||
Followercolor_cons_t[1].strvalue = "Match"; // Add "Match" option, which will make the follower color match the player's
|
||||
|
||||
Followercolor_cons_t[0].value = FOLLOWERCOLOR_OPPOSITE;
|
||||
Followercolor_cons_t[0].strvalue = "Opposite"; // Add "Opposite" option, ...which is like "Match", but for coloropposite.
|
||||
|
||||
Color_cons_t[MAXSKINCOLORS].value = Followercolor_cons_t[MAXSKINCOLORS+2].value = 0;
|
||||
Color_cons_t[MAXSKINCOLORS].strvalue = Followercolor_cons_t[MAXSKINCOLORS+2].strvalue = NULL;
|
||||
|
||||
// Set default player names
|
||||
// Monster Iestyn (12/08/19): not sure where else I could have actually put this, but oh well
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -986,6 +964,9 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_bsaturation);
|
||||
CV_RegisterVar(&cv_msaturation);
|
||||
|
||||
CV_RegisterVar(&cv_palette);
|
||||
CV_RegisterVar(&cv_palettenum);
|
||||
|
||||
// k_menu.c
|
||||
//CV_RegisterVar(&cv_compactscoreboard);
|
||||
CV_RegisterVar(&cv_chatheight);
|
||||
|
|
@ -1089,6 +1070,7 @@ void D_RegisterClientCommands(void)
|
|||
COM_AddCommand("rteleport", Command_RTeleport_f);
|
||||
COM_AddCommand("skynum", Command_Skynum_f);
|
||||
COM_AddCommand("weather", Command_Weather_f);
|
||||
COM_AddCommand("grayscale", Command_Grayscale_f);
|
||||
#ifdef _DEBUG
|
||||
COM_AddCommand("causecfail", Command_CauseCfail_f);
|
||||
#endif
|
||||
|
|
@ -1489,7 +1471,7 @@ static void SendNameAndColor(UINT8 n)
|
|||
const INT32 playernum = g_localplayers[n];
|
||||
player_t *player = &players[playernum];
|
||||
|
||||
char buf[MAXPLAYERNAME+9];
|
||||
char buf[MAXPLAYERNAME+12];
|
||||
char *p;
|
||||
|
||||
if (splitscreen < n)
|
||||
|
|
@ -1520,14 +1502,11 @@ static void SendNameAndColor(UINT8 n)
|
|||
if (!cv_followercolor[n].value)
|
||||
CV_StealthSet(&cv_followercolor[n], "Match"); // set it to "Match". I don't care about your stupidity!
|
||||
|
||||
// so like, this is sent before we even use anything like cvars or w/e so it's possible that follower is set to a pretty yikes value, so let's fix that before we send garbage that could crash the game:
|
||||
if (cv_follower[n].value >= numfollowers || cv_follower[n].value < -1)
|
||||
CV_StealthSet(&cv_follower[n], "-1");
|
||||
|
||||
if (!strcmp(cv_playername[n].string, player_names[playernum])
|
||||
&& cv_playercolor[n].value == player->skincolor
|
||||
&& !strcmp(cv_skin[n].string, skins[player->skin].name)
|
||||
&& cv_follower[n].value == player->followerskin
|
||||
&& !stricmp(cv_skin[n].string, skins[player->skin].name)
|
||||
&& !stricmp(cv_follower[n].string,
|
||||
(player->followerskin < 0 ? "None" : followers[player->followerskin].name))
|
||||
&& cv_followercolor[n].value == player->followercolor)
|
||||
return;
|
||||
|
||||
|
|
@ -1549,31 +1528,28 @@ static void SendNameAndColor(UINT8 n)
|
|||
|
||||
K_KartResetPlayerColor(player);
|
||||
|
||||
// Update follower for local games:
|
||||
if (cv_follower[n].value >= -1 && cv_follower[n].value != player->followerskin)
|
||||
K_SetFollowerByNum(playernum, cv_follower[n].value);
|
||||
|
||||
player->followercolor = cv_followercolor[n].value;
|
||||
|
||||
if (metalrecording && n == 0)
|
||||
{ // Starring Metal Sonic as themselves, obviously.
|
||||
SetPlayerSkinByNum(playernum, 5);
|
||||
CV_StealthSet(&cv_skin[n], skins[5].name);
|
||||
}
|
||||
else if ((foundskin = R_SkinAvailable(cv_skin[n].string)) != -1 && R_SkinUsable(playernum, foundskin))
|
||||
if ((foundskin = R_SkinAvailable(cv_skin[n].string)) != -1 && R_SkinUsable(playernum, foundskin))
|
||||
{
|
||||
cv_skin[n].value = foundskin;
|
||||
SetPlayerSkin(playernum, cv_skin[n].string);
|
||||
CV_StealthSet(&cv_skin[n], skins[cv_skin[n].value].name);
|
||||
CV_StealthSet(&cv_skin[n], skins[foundskin].name);
|
||||
cv_skin[n].value = foundskin;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv_skin[n].value = players[playernum].skin;
|
||||
CV_StealthSet(&cv_skin[n], skins[player->skin].name);
|
||||
cv_skin[n].value = player->skin;
|
||||
// will always be same as current
|
||||
SetPlayerSkin(playernum, cv_skin[n].string);
|
||||
}
|
||||
|
||||
player->followercolor = cv_followercolor[n].value;
|
||||
|
||||
// Update follower for local games:
|
||||
foundskin = K_FollowerAvailable(cv_follower[n].string);
|
||||
CV_StealthSet(&cv_follower[n], (foundskin == -1) ? "None" : followers[foundskin].name);
|
||||
cv_follower[n].value = foundskin;
|
||||
K_SetFollowerByNum(playernum, foundskin);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1603,12 +1579,20 @@ static void SendNameAndColor(UINT8 n)
|
|||
cv_skin[n].value = 0;
|
||||
}
|
||||
|
||||
cv_follower[n].value = K_FollowerAvailable(cv_follower[n].string);
|
||||
if (cv_follower[n].value < 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[n], "None");
|
||||
cv_follower[n].value = -1;
|
||||
}
|
||||
|
||||
// Finally write out the complete packet and send it off.
|
||||
WRITESTRINGN(p, cv_playername[n].zstring, MAXPLAYERNAME);
|
||||
WRITEUINT32(p, (UINT32)player->availabilities);
|
||||
WRITEUINT16(p, (UINT16)cv_playercolor[n].value);
|
||||
WRITEUINT8(p, (UINT8)cv_skin[n].value);
|
||||
WRITESINT8(p, (SINT8)cv_follower[n].value);
|
||||
WRITEINT16(p, (INT16)cv_follower[n].value);
|
||||
//CONS_Printf("Sending follower id %d\n", (INT16)cv_follower[n].value);
|
||||
WRITEUINT16(p, (UINT16)cv_followercolor[n].value);
|
||||
|
||||
SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf);
|
||||
|
|
@ -1620,7 +1604,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
char name[MAXPLAYERNAME+1];
|
||||
UINT16 color, followercolor;
|
||||
UINT8 skin;
|
||||
SINT8 follower;
|
||||
INT16 follower;
|
||||
SINT8 localplayer = -1;
|
||||
UINT8 i;
|
||||
|
||||
|
|
@ -1649,7 +1633,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
p->availabilities = READUINT32(*cp);
|
||||
color = READUINT16(*cp);
|
||||
skin = READUINT8(*cp);
|
||||
follower = READSINT8(*cp);
|
||||
follower = READINT16(*cp);
|
||||
//CONS_Printf("Recieved follower id %d\n", follower);
|
||||
followercolor = READUINT16(*cp);
|
||||
|
||||
// set name
|
||||
|
|
@ -6075,6 +6060,7 @@ static void Name_OnChange(void)
|
|||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
|
||||
CV_StealthSet(&cv_playername[0], player_names[consoleplayer]);
|
||||
return;
|
||||
}
|
||||
else
|
||||
SendNameAndColor(0);
|
||||
|
|
@ -6115,207 +6101,56 @@ static void Name4_OnChange(void)
|
|||
}
|
||||
|
||||
// sends the follower change for players
|
||||
static void Follower_OnChange(void)
|
||||
static void FollowerAny_OnChange(UINT8 pnum)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower[0].string);
|
||||
strcpy(cpy, cv_follower[0].string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[0], "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(0);
|
||||
return;
|
||||
}
|
||||
|
||||
num = K_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
CV_StealthSet(&cv_follower[0], str);
|
||||
cv_follower[0].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(0);
|
||||
SendNameAndColor(pnum);
|
||||
}
|
||||
|
||||
// sends the follower change for players
|
||||
static void Follower_OnChange(void)
|
||||
{
|
||||
FollowerAny_OnChange(0);
|
||||
}
|
||||
|
||||
// About the same as Color_OnChange but for followers.
|
||||
static void Followercolor_OnChange(void)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(consoleplayer))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(0);
|
||||
}
|
||||
FollowerAny_OnChange(0);
|
||||
}
|
||||
|
||||
// repeat for the 3 other players
|
||||
|
||||
static void Follower2_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower[1].string);
|
||||
strcpy(cpy, cv_follower[1].string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[1], "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(1);
|
||||
return;
|
||||
}
|
||||
|
||||
num = K_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
CV_StealthSet(&cv_follower[1], str);
|
||||
cv_follower[1].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(1);
|
||||
FollowerAny_OnChange(1);
|
||||
}
|
||||
|
||||
static void Followercolor2_OnChange(void)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[1]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(1);
|
||||
}
|
||||
FollowerAny_OnChange(1);
|
||||
}
|
||||
|
||||
static void Follower3_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower[2].string);
|
||||
strcpy(cpy, cv_follower[2].string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[2], "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(2);
|
||||
return;
|
||||
}
|
||||
|
||||
num = K_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
CV_StealthSet(&cv_follower[2], str);
|
||||
cv_follower[2].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(2);
|
||||
FollowerAny_OnChange(2);
|
||||
}
|
||||
|
||||
static void Followercolor3_OnChange(void)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[2]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(2);
|
||||
}
|
||||
FollowerAny_OnChange(2);
|
||||
}
|
||||
|
||||
static void Follower4_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower[3].string);
|
||||
strcpy(cpy, cv_follower[3].string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[3], "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(3);
|
||||
return;
|
||||
}
|
||||
|
||||
num = K_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
CV_StealthSet(&cv_follower[3], str);
|
||||
cv_follower[3].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(3);
|
||||
FollowerAny_OnChange(3);
|
||||
}
|
||||
|
||||
static void Followercolor4_OnChange(void)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[3]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(3);
|
||||
}
|
||||
FollowerAny_OnChange(3);
|
||||
}
|
||||
|
||||
/** Sends a skin change for the console player, unless that player is moving. Also forces them to spectate if the change is done during gameplay
|
||||
|
|
@ -6335,7 +6170,9 @@ static void Skin_OnChange(void)
|
|||
}
|
||||
|
||||
if (CanChangeSkinWhilePlaying(consoleplayer))
|
||||
{
|
||||
SendNameAndColor(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ extern consvar_t
|
|||
cv_dualsneaker,
|
||||
cv_triplesneaker,
|
||||
cv_triplebanana,
|
||||
cv_decabanana,
|
||||
cv_tripleorbinaut,
|
||||
cv_quadorbinaut,
|
||||
cv_dualjawz;
|
||||
|
|
|
|||
164
src/d_netfil.c
164
src/d_netfil.c
|
|
@ -354,6 +354,9 @@ void CL_AbortDownloadResume(void)
|
|||
pauseddownload = NULL;
|
||||
}
|
||||
|
||||
// The following was written and, against all odds, works.
|
||||
#define MORELEGACYDOWNLOADER
|
||||
|
||||
/** Sends requests for files in the ::fileneeded table with a status of
|
||||
* ::FS_NOTFOUND.
|
||||
*
|
||||
|
|
@ -366,42 +369,135 @@ boolean CL_SendFileRequest(void)
|
|||
char *p;
|
||||
INT32 i;
|
||||
INT64 totalfreespaceneeded = 0, availablefreespace;
|
||||
INT32 skippedafile = -1;
|
||||
#ifdef MORELEGACYDOWNLOADER
|
||||
boolean firstloop = true;
|
||||
#endif
|
||||
|
||||
#ifdef PARANOIA
|
||||
if (M_CheckParm("-nodownload"))
|
||||
I_Error("Attempted to download files in -nodownload mode");
|
||||
{
|
||||
CONS_Printf("Direct download - Attempted to download files in -nodownload mode");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
|
||||
&& (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
|
||||
{
|
||||
I_Error("Attempted to download files that were not sendable");
|
||||
CONS_Printf("Direct download - attempted to download files that were not sendable\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK))
|
||||
{
|
||||
// Error check for the first time around.
|
||||
totalfreespaceneeded += fileneeded[i].totalsize;
|
||||
}
|
||||
}
|
||||
|
||||
I_GetDiskFreeSpace(&availablefreespace);
|
||||
if (totalfreespaceneeded > availablefreespace)
|
||||
{
|
||||
CONS_Printf("Direct download -\n"
|
||||
" To play on this server you must download %s KB,\n"
|
||||
" but you have only %s KB free space on this drive\n",
|
||||
sizeu1((size_t)(totalfreespaceneeded>>10)), sizeu2((size_t)(availablefreespace>>10)));
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MORELEGACYDOWNLOADER
|
||||
tryagain:
|
||||
skippedafile = -1;
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSEREQUESTFILE
|
||||
CONS_Printf("Preparing packet\n");
|
||||
#endif
|
||||
|
||||
netbuffer->packettype = PT_REQUESTFILE;
|
||||
p = (char *)netbuffer->u.textcmd;
|
||||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK))
|
||||
{
|
||||
totalfreespaceneeded += fileneeded[i].totalsize;
|
||||
// Pre-prepare.
|
||||
size_t checklen;
|
||||
nameonly(fileneeded[i].filename);
|
||||
|
||||
// Figure out if we'd overrun our buffer.
|
||||
checklen = strlen(fileneeded[i].filename)+2; // plus the fileid (and terminator, in case this is last)
|
||||
if ((UINT8 *)(p + checklen) >= netbuffer->u.textcmd + MAXTEXTCMD)
|
||||
{
|
||||
skippedafile = i;
|
||||
// we might have a shorter file that can fit in the remaining space, and file ID permits out-of-order data
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now write.
|
||||
WRITEUINT8(p, i); // fileid
|
||||
WRITESTRINGN(p, fileneeded[i].filename, MAX_WADPATH);
|
||||
|
||||
#ifdef VERBOSEREQUESTFILE
|
||||
CONS_Printf(" file \"%s\" (id %d)\n", i, fileneeded[i].filename);
|
||||
#endif
|
||||
|
||||
// put it in download dir
|
||||
strcatbf(fileneeded[i].filename, downloaddir, "/");
|
||||
fileneeded[i].status = FS_REQUESTED;
|
||||
}
|
||||
WRITEUINT8(p, 0xFF);
|
||||
I_GetDiskFreeSpace(&availablefreespace);
|
||||
if (totalfreespaceneeded > availablefreespace)
|
||||
I_Error("To play on this server you must download %s KB,\n"
|
||||
"but you have only %s KB free space on this drive\n",
|
||||
sizeu1((size_t)(totalfreespaceneeded>>10)), sizeu2((size_t)(availablefreespace>>10)));
|
||||
}
|
||||
|
||||
// prepare to download
|
||||
I_mkdir(downloaddir, 0755);
|
||||
return HSendPacket(servernode, true, 0, p - (char *)netbuffer->u.textcmd);
|
||||
#ifdef MORELEGACYDOWNLOADER
|
||||
if (firstloop)
|
||||
#else
|
||||
// If we're not trying extralong legacy download requests, gotta bail.
|
||||
if (skippedafile != -1)
|
||||
{
|
||||
CONS_Printf("Direct download - missing files are as follows:\n");
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK || fileneeded[i].status == FS_REQUESTED)) // FS_REQUESTED added
|
||||
CONS_Printf(" %s\n", fileneeded[i].filename);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
I_mkdir(downloaddir, 0755);
|
||||
|
||||
#ifdef PARANOIA
|
||||
// Couldn't fit a single one in?
|
||||
if (p == (char *)netbuffer->u.textcmd)
|
||||
{
|
||||
CONS_Printf("Direct download - fileneeded name for %s (fileneeded[%d]) too long??\n", (skippedafile != -1 ? fileneeded[skippedafile].filename : NULL), skippedafile);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
WRITEUINT8(p, 0xFF); // terminator
|
||||
if (!HSendPacket(servernode, true, 0, p - (char *)netbuffer->u.textcmd))
|
||||
{
|
||||
CONS_Printf("Direct download - unable to send packet.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MORELEGACYDOWNLOADER
|
||||
if (skippedafile != -1)
|
||||
{
|
||||
firstloop = false;
|
||||
goto tryagain;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSEREQUESTFILE
|
||||
CONS_Printf("Returning true\n");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// get request filepak and put it on the send queue
|
||||
|
|
@ -411,16 +507,18 @@ boolean PT_RequestFile(INT32 node)
|
|||
char wad[MAX_WADPATH+1];
|
||||
UINT8 *p = netbuffer->u.textcmd;
|
||||
UINT8 id;
|
||||
while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow
|
||||
while (p < netbuffer->u.textcmd + MAXTEXTCMD) // Don't allow hacked client to overflow
|
||||
{
|
||||
id = READUINT8(p);
|
||||
if (id == 0xFF)
|
||||
break;
|
||||
READSTRINGN(p, wad, MAX_WADPATH);
|
||||
if (!AddFileToSendQueue(node, wad, id))
|
||||
if (p >= netbuffer->u.textcmd + MAXTEXTCMD || !AddFileToSendQueue(node, wad, id))
|
||||
{
|
||||
if (cv_noticedownload.value)
|
||||
CONS_Printf("Bad PT_REQUESTFILE from node %d!\n", node);
|
||||
SV_AbortSendFiles(node);
|
||||
return false; // don't read the rest of the files
|
||||
return false; // don't read any more
|
||||
}
|
||||
}
|
||||
return true; // no problems with any files
|
||||
|
|
@ -552,7 +650,7 @@ boolean CL_LoadServerFiles(void)
|
|||
continue; // Already loaded
|
||||
else if (fileneeded[i].status == FS_FOUND)
|
||||
{
|
||||
P_AddWadFile(fileneeded[i].filename);
|
||||
P_PartialAddWadFile(fileneeded[i].filename);
|
||||
G_SetGameModified(true, false);
|
||||
fileneeded[i].status = FS_OPEN;
|
||||
return false;
|
||||
|
|
@ -798,7 +896,7 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid
|
|||
char wadfilename[MAX_WADPATH];
|
||||
|
||||
if (cv_noticedownload.value)
|
||||
CONS_Printf("Sending file \"%s\" to node %d (%s)\n", filename, node, I_GetNodeAddress(node));
|
||||
CONS_Printf("Sending file \"%s\" (id %d) to node %d (%s)\n", filename, fileid, node, I_GetNodeAddress(node));
|
||||
|
||||
// Find the last file in the list and set a pointer to its "next" field
|
||||
q = &transfer[node].txlist;
|
||||
|
|
@ -972,7 +1070,7 @@ static void SV_EndFileSend(INT32 node)
|
|||
{
|
||||
case SF_FILE: // It's a file, close it and free its filename
|
||||
if (cv_noticedownload.value)
|
||||
CONS_Printf("Ending file transfer for node %d\n", node);
|
||||
CONS_Printf("Ending file transfer (id %d) for node %d\n", p->fileid, node);
|
||||
if (transfer[node].currentfile)
|
||||
fclose(transfer[node].currentfile);
|
||||
free(p->id.filename);
|
||||
|
|
@ -1750,6 +1848,7 @@ void CURLGetFile(void)
|
|||
int msgs_left; /* how many messages are left */
|
||||
const char *easy_handle_error;
|
||||
long response_code = 0;
|
||||
static char *filename;
|
||||
|
||||
if (curl_runninghandles)
|
||||
{
|
||||
|
|
@ -1774,6 +1873,8 @@ void CURLGetFile(void)
|
|||
{
|
||||
e = m->easy_handle;
|
||||
easyres = m->data.result;
|
||||
filename = Z_StrDup(curl_realname);
|
||||
nameonly(filename);
|
||||
if (easyres != CURLE_OK)
|
||||
{
|
||||
if (easyres == CURLE_HTTP_RETURNED_ERROR)
|
||||
|
|
@ -1786,21 +1887,30 @@ void CURLGetFile(void)
|
|||
curl_failedwebdownload = true;
|
||||
fclose(curl_curfile->file);
|
||||
remove(curl_curfile->filename);
|
||||
curl_curfile->file = NULL;
|
||||
//nameonly(curl_curfile->filename);
|
||||
nameonly(curl_realname);
|
||||
CONS_Printf(M_GetText("Failed to download %s (%s)\n"), curl_realname, easy_handle_error);
|
||||
CONS_Printf(M_GetText("Failed to download %s (%s)\n"), filename, easy_handle_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
nameonly(curl_realname);
|
||||
CONS_Printf(M_GetText("Finished downloading %s\n"), curl_realname);
|
||||
downloadcompletednum++;
|
||||
downloadcompletedsize += curl_curfile->totalsize;
|
||||
curl_curfile->status = FS_FOUND;
|
||||
fclose(curl_curfile->file);
|
||||
|
||||
if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename);
|
||||
curl_curfile->status = FS_FALLBACK;
|
||||
curl_failedwebdownload = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Finished HTTP download of %s\n"), filename);
|
||||
downloadcompletednum++;
|
||||
downloadcompletedsize += curl_curfile->totalsize;
|
||||
curl_curfile->status = FS_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Z_Free(filename);
|
||||
curl_curfile->file = NULL;
|
||||
curl_running = false;
|
||||
curl_transfers--;
|
||||
curl_multi_remove_handle(multi_handle, e);
|
||||
|
|
|
|||
|
|
@ -168,7 +168,6 @@ typedef enum
|
|||
KRITEM_DUALSNEAKER = NUMKARTITEMS,
|
||||
KRITEM_TRIPLESNEAKER,
|
||||
KRITEM_TRIPLEBANANA,
|
||||
KRITEM_TENFOLDBANANA,
|
||||
KRITEM_TRIPLEORBINAUT,
|
||||
KRITEM_QUADORBINAUT,
|
||||
KRITEM_DUALJAWZ,
|
||||
|
|
@ -415,7 +414,7 @@ typedef struct player_s
|
|||
// Basic gameplay things
|
||||
UINT8 position; // Used for Kart positions, mostly for deterministic stuff
|
||||
UINT8 oldposition; // Used for taunting when you pass someone
|
||||
UINT8 positiondelay; // Used for position number, so it can grow when passing/being passed
|
||||
UINT8 positiondelay; // Used for position number, so it can grow when passing
|
||||
UINT32 distancetofinish;
|
||||
waypoint_t *nextwaypoint;
|
||||
respawnvars_t respawn; // Respawn info
|
||||
|
|
|
|||
162
src/deh_soc.c
162
src/deh_soc.c
|
|
@ -224,7 +224,10 @@ void readfreeslots(MYFILE *f)
|
|||
// TODO: Out-of-slots warnings/errors.
|
||||
// TODO: Name too long (truncated) warnings.
|
||||
if (fastcmp(type, "SFX"))
|
||||
{
|
||||
CONS_Printf("Sound sfx_%s allocated.\n",word);
|
||||
S_AddSoundFx(word, false, 0, false);
|
||||
}
|
||||
else if (fastcmp(type, "SPR"))
|
||||
{
|
||||
for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++)
|
||||
|
|
@ -238,39 +241,54 @@ void readfreeslots(MYFILE *f)
|
|||
// Found a free slot!
|
||||
strncpy(sprnames[i],word,4);
|
||||
//sprnames[i][4] = 0;
|
||||
CONS_Printf("Sprite SPR_%s allocated.\n",word);
|
||||
used_spr[(i-SPR_FIRSTFREESLOT)/8] |= 1<<(i%8); // Okay, this sprite slot has been named now.
|
||||
break;
|
||||
}
|
||||
if (i > SPR_LASTFREESLOT)
|
||||
I_Error("Out of Sprite Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
|
||||
|
||||
}
|
||||
else if (fastcmp(type, "S"))
|
||||
{
|
||||
for (i = 0; i < NUMSTATEFREESLOTS; i++)
|
||||
if (!FREE_STATES[i]) {
|
||||
CONS_Printf("State S_%s allocated.\n",word);
|
||||
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
|
||||
strcpy(FREE_STATES[i],word);
|
||||
freeslotusage[0][0]++;
|
||||
break;
|
||||
}
|
||||
if (i == NUMSTATEFREESLOTS)
|
||||
I_Error("Out of State Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
|
||||
|
||||
}
|
||||
else if (fastcmp(type, "MT"))
|
||||
{
|
||||
for (i = 0; i < NUMMOBJFREESLOTS; i++)
|
||||
if (!FREE_MOBJS[i]) {
|
||||
CONS_Printf("MobjType MT_%s allocated.\n",word);
|
||||
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
|
||||
strcpy(FREE_MOBJS[i],word);
|
||||
freeslotusage[1][0]++;
|
||||
break;
|
||||
}
|
||||
if (i == NUMMOBJFREESLOTS)
|
||||
I_Error("Out of Mobj Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
|
||||
|
||||
}
|
||||
else if (fastcmp(type, "SKINCOLOR"))
|
||||
{
|
||||
for (i = 0; i < NUMCOLORFREESLOTS; i++)
|
||||
if (!FREE_SKINCOLORS[i]) {
|
||||
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
|
||||
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
|
||||
strcpy(FREE_SKINCOLORS[i],word);
|
||||
M_AddMenuColor(numskincolors++);
|
||||
break;
|
||||
}
|
||||
if (i == NUMCOLORFREESLOTS)
|
||||
I_Error("Out of Skincolor Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
|
||||
}
|
||||
else if (fastcmp(type, "SPR2"))
|
||||
{
|
||||
|
|
@ -287,7 +305,7 @@ void readfreeslots(MYFILE *f)
|
|||
spr2defaults[free_spr2] = 0;
|
||||
spr2names[free_spr2++][4] = 0;
|
||||
} else
|
||||
deh_warning("Ran out of free SPR2 slots!\n");
|
||||
I_Error("Out of SPR2 Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
|
||||
}
|
||||
else if (fastcmp(type, "TOL"))
|
||||
{
|
||||
|
|
@ -302,7 +320,7 @@ void readfreeslots(MYFILE *f)
|
|||
|
||||
// We don't, so freeslot it.
|
||||
if (lastcustomtol == (UINT32)MAXTOL) // Unless you have way too many, since they're flags.
|
||||
deh_warning("Ran out of free typeoflevel slots!\n");
|
||||
I_Error("Out of Typeoflevel Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
|
||||
else
|
||||
{
|
||||
G_AddTOL(lastcustomtol, word);
|
||||
|
|
@ -326,7 +344,7 @@ void readfreeslots(MYFILE *f)
|
|||
precipprops[i].name = Z_StrDup(word);
|
||||
precip_freeslot++;
|
||||
} else
|
||||
deh_warning("Ran out of free PRECIP slots!\n");
|
||||
I_Error("Out of Precipitation Freeslots while allocating \"%s\"\nLoad less addons to fix this.", word);
|
||||
}
|
||||
else
|
||||
deh_warning("Freeslots: unknown enum class '%s' for '%s_%s'", type, type, word);
|
||||
|
|
@ -3112,7 +3130,7 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
|
|||
void readfollower(MYFILE *f)
|
||||
{
|
||||
char *s;
|
||||
char *word, *word2, dname[SKINNAMESIZE+1];
|
||||
char *word, *word2;
|
||||
char *tmp;
|
||||
char testname[SKINNAMESIZE+1];
|
||||
|
||||
|
|
@ -3121,10 +3139,9 @@ void readfollower(MYFILE *f)
|
|||
INT32 res;
|
||||
INT32 i;
|
||||
|
||||
if (numfollowers > MAXSKINS)
|
||||
if (numfollowers >= MAXSKINS)
|
||||
{
|
||||
deh_warning("Error: Too many followers, cannot add anymore.\n");
|
||||
return;
|
||||
I_Error("Out of Followers\nLoad less addons to fix this.");
|
||||
}
|
||||
|
||||
s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
|
@ -3143,8 +3160,9 @@ void readfollower(MYFILE *f)
|
|||
followers[numfollowers].bobspeed = TICRATE*2;
|
||||
followers[numfollowers].bobamp = 4*FRACUNIT;
|
||||
followers[numfollowers].hitconfirmtime = TICRATE;
|
||||
followers[numfollowers].defaultcolor = SKINCOLOR_GREEN;
|
||||
strcpy(followers[numfollowers].icon, "M_NORANK");
|
||||
followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH;
|
||||
followers[numfollowers].category = UINT8_MAX;
|
||||
strcpy(followers[numfollowers].icon, "MISSING");
|
||||
|
||||
do
|
||||
{
|
||||
|
|
@ -3183,6 +3201,23 @@ void readfollower(MYFILE *f)
|
|||
strcpy(followers[numfollowers].icon, word2);
|
||||
nameset = true;
|
||||
}
|
||||
else if (fastcmp(word, "CATEGORY"))
|
||||
{
|
||||
INT32 j;
|
||||
for (j = 0; j < numfollowercategories; j++)
|
||||
{
|
||||
if (!stricmp(followercategories[j].name, word2))
|
||||
{
|
||||
followers[numfollowers].category = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == numfollowercategories)
|
||||
{
|
||||
deh_warning("Follower %d: unknown follower category '%s'", numfollowers, word2);
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "MODE"))
|
||||
{
|
||||
if (word2)
|
||||
|
|
@ -3197,7 +3232,20 @@ void readfollower(MYFILE *f)
|
|||
}
|
||||
else if (fastcmp(word, "DEFAULTCOLOR"))
|
||||
{
|
||||
followers[numfollowers].defaultcolor = get_number(word2);
|
||||
INT32 j;
|
||||
for (j = 0; j < numskincolors +2; j++) // +2 because of Match and Opposite
|
||||
{
|
||||
if (!stricmp(Followercolor_cons_t[j].strvalue, word2))
|
||||
{
|
||||
followers[numfollowers].defaultcolor = Followercolor_cons_t[j].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == numskincolors+2)
|
||||
{
|
||||
deh_warning("Follower %d: unknown follower color '%s'", numfollowers, word2);
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "SCALE"))
|
||||
{
|
||||
|
|
@ -3300,10 +3348,6 @@ void readfollower(MYFILE *f)
|
|||
// set skin name (this is just the follower's name in lowercases):
|
||||
// but before we do, let's... actually check if another follower isn't doing the same shit...
|
||||
|
||||
strcpy(testname, followers[numfollowers].name);
|
||||
|
||||
// lower testname for skin checks...
|
||||
strlwr(testname);
|
||||
res = K_FollowerAvailable(testname);
|
||||
if (res > -1) // yikes, someone else has stolen our name already
|
||||
{
|
||||
|
|
@ -3315,8 +3359,7 @@ void readfollower(MYFILE *f)
|
|||
// in that case, we'll be very lazy and copy numfollowers to the end of our skin name.
|
||||
}
|
||||
|
||||
strcpy(followers[numfollowers].skinname, testname);
|
||||
strcpy(dname, followers[numfollowers].skinname); // display name, just used for printing succesful stuff or errors later down the line.
|
||||
strcpy(testname, followers[numfollowers].name);
|
||||
|
||||
// now that the skin name is ready, post process the actual name to turn the underscores into spaces!
|
||||
for (i = 0; followers[numfollowers].name[i]; i++)
|
||||
|
|
@ -3331,14 +3374,14 @@ void readfollower(MYFILE *f)
|
|||
if (followers[numfollowers].mode < FOLLOWERMODE_FLOAT || followers[numfollowers].mode >= FOLLOWERMODE__MAX)
|
||||
{
|
||||
followers[numfollowers].mode = FOLLOWERMODE_FLOAT;
|
||||
deh_warning("Follower '%s': Value for 'mode' should be between %d and %d.", dname, FOLLOWERMODE_FLOAT, FOLLOWERMODE__MAX-1);
|
||||
deh_warning("Follower '%s': Value for 'mode' should be between %d and %d.", testname, FOLLOWERMODE_FLOAT, FOLLOWERMODE__MAX-1);
|
||||
}
|
||||
|
||||
#define FALLBACK(field, field2, threshold, set) \
|
||||
if ((signed)followers[numfollowers].field < threshold) \
|
||||
{ \
|
||||
followers[numfollowers].field = set; \
|
||||
deh_warning("Follower '%s': Value for '%s' is too low! Minimum should be %d. Value was overwritten to %d.", dname, field2, threshold, set); \
|
||||
deh_warning("Follower '%s': Value for '%s' is too low! Minimum should be %d. Value was overwritten to %d.", testname, field2, threshold, set); \
|
||||
} \
|
||||
|
||||
FALLBACK(dist, "DIST", 0, 0);
|
||||
|
|
@ -3355,13 +3398,6 @@ if ((signed)followers[numfollowers].field < threshold) \
|
|||
|
||||
#undef FALLBACK
|
||||
|
||||
// Special case for color I suppose
|
||||
if (followers[numfollowers].defaultcolor > (unsigned)(numskincolors-1))
|
||||
{
|
||||
followers[numfollowers].defaultcolor = SKINCOLOR_GREEN;
|
||||
deh_warning("Follower \'%s\': Value for 'color' should be between 1 and %d.\n", dname, numskincolors-1);
|
||||
}
|
||||
|
||||
// also check if we forgot states. If we did, we will set any missing state to the follower's idlestate.
|
||||
// Print a warning in case we don't have a fallback and set the state to S_INVISIBLE (rather than S_NULL) if unavailable.
|
||||
|
||||
|
|
@ -3370,7 +3406,7 @@ if (!followers[numfollowers].field) \
|
|||
{ \
|
||||
followers[numfollowers].field = fallbackstate ? fallbackstate : S_INVISIBLE; \
|
||||
if (!fallbackstate) \
|
||||
deh_warning("Follower '%s' is missing state definition for '%s', no idlestate fallback was found", dname, field2); \
|
||||
deh_warning("Follower '%s' is missing state definition for '%s', no idlestate fallback was found", testname, field2); \
|
||||
} \
|
||||
|
||||
NOSTATE(idlestate, "IDLESTATE");
|
||||
|
|
@ -3381,11 +3417,83 @@ if (!followers[numfollowers].field) \
|
|||
NOSTATE(hitconfirmstate, "HITCONFIRMSTATE");
|
||||
#undef NOSTATE
|
||||
|
||||
CONS_Printf("Added follower '%s'\n", dname);
|
||||
CONS_Printf("Added follower '%s'\n", testname);
|
||||
if (followers[numfollowers].category < numfollowercategories)
|
||||
followercategories[followers[numfollowers].category].numincategory++;
|
||||
numfollowers++; // add 1 follower
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
void readfollowercategory(MYFILE *f)
|
||||
{
|
||||
char *s;
|
||||
char *word, *word2;
|
||||
char *tmp;
|
||||
|
||||
boolean nameset;
|
||||
|
||||
if (numfollowercategories == MAXFOLLOWERCATEGORIES)
|
||||
{
|
||||
I_Error("Out of Follower categories\nLoad less addons to fix this.");
|
||||
}
|
||||
|
||||
s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
||||
// Ready the default variables for followers. We will overwrite them as we go! We won't set the name or states RIGHT HERE as this is handled down instead.
|
||||
strcpy(followercategories[numfollowercategories].icon, "MISSING");
|
||||
followercategories[numfollowercategories].numincategory = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (myfgets(s, MAXLINELEN, f))
|
||||
{
|
||||
if (s[0] == '\n')
|
||||
break;
|
||||
|
||||
tmp = strchr(s, '#');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
if (s == tmp)
|
||||
continue; // Skip comment lines, but don't break.
|
||||
|
||||
word = strtok(s, " ");
|
||||
if (word)
|
||||
strupr(word);
|
||||
else
|
||||
break;
|
||||
|
||||
word2 = strtok(NULL, " = ");
|
||||
|
||||
if (!word2)
|
||||
break;
|
||||
|
||||
if (word2[strlen(word2)-1] == '\n')
|
||||
word2[strlen(word2)-1] = '\0';
|
||||
|
||||
if (fastcmp(word, "NAME"))
|
||||
{
|
||||
strcpy(followercategories[numfollowercategories].name, word2);
|
||||
nameset = true;
|
||||
}
|
||||
else if (fastcmp(word, "ICON"))
|
||||
{
|
||||
strcpy(followercategories[numfollowercategories].icon, word2);
|
||||
nameset = true;
|
||||
}
|
||||
}
|
||||
} while (!myfeof(f)); // finish when the line is empty
|
||||
|
||||
if (!nameset)
|
||||
{
|
||||
// well this is problematic.
|
||||
strcpy(followercategories[numfollowercategories].name, va("Followercategory%d", numfollowercategories)); // this is lazy, so what
|
||||
}
|
||||
|
||||
CONS_Printf("Added follower category '%s'\n", followercategories[numfollowercategories].name);
|
||||
numfollowercategories++; // add 1 follower
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
void readweather(MYFILE *f, INT32 num)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ void clear_conditionsets(void);
|
|||
|
||||
void readcupheader(MYFILE *f, cupheader_t *cup);
|
||||
void readfollower(MYFILE *f);
|
||||
void readfollowercategory(MYFILE *f);
|
||||
preciptype_t get_precip(const char *word);
|
||||
void readweather(MYFILE *f, INT32 num);
|
||||
|
||||
|
|
|
|||
|
|
@ -3271,6 +3271,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_ITEM_DEBRIS_CLOUD_SPAWNER2",
|
||||
|
||||
"S_ITEMICON",
|
||||
"S_ITEMBACKDROP",
|
||||
|
||||
// Item capsules
|
||||
"S_ITEMCAPSULE",
|
||||
|
|
@ -3491,6 +3492,11 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_BANANA",
|
||||
"S_BANANA_DEAD",
|
||||
|
||||
"S_BANANA_SPARK",
|
||||
"S_BANANA_SPARK2",
|
||||
"S_BANANA_SPARK3",
|
||||
"S_BANANA_SPARK4",
|
||||
|
||||
//{ Orbinaut
|
||||
"S_ORBINAUT1",
|
||||
"S_ORBINAUT2",
|
||||
|
|
@ -5315,6 +5321,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
|
||||
"MT_BANANA", // Banana Stuff
|
||||
"MT_BANANA_SHIELD",
|
||||
"MT_BANANA_SPARK",
|
||||
|
||||
"MT_ORBINAUT", // Orbinaut stuff
|
||||
"MT_ORBINAUT_SHIELD",
|
||||
|
|
@ -5632,7 +5639,7 @@ const char *const MOBJFLAG_LIST[] = {
|
|||
"SLIDEME",
|
||||
"NOCLIP",
|
||||
"FLOAT",
|
||||
"BOXICON",
|
||||
"SLOPE",
|
||||
"MISSILE",
|
||||
"SPRING",
|
||||
"MONITOR",
|
||||
|
|
@ -6761,14 +6768,13 @@ struct int_const_s const INT_CONST[] = {
|
|||
|
||||
// SRB2Kart
|
||||
// kartitems_t
|
||||
#define FOREACH( name, n ) { #name, KITEM_ ## name }
|
||||
#define FOREACH( name, n ) { TOSTR (KITEM_ ## name), KITEM_ ## name }
|
||||
KART_ITEM_ITERATOR, // Actual items (can be set for k_itemtype)
|
||||
#undef FOREACH
|
||||
{"NUMKARTITEMS",NUMKARTITEMS},
|
||||
{"KRITEM_DUALSNEAKER",KRITEM_DUALSNEAKER}, // Additional roulette IDs (not usable for much in Lua besides K_GetItemPatch)
|
||||
{"KRITEM_TRIPLESNEAKER",KRITEM_TRIPLESNEAKER},
|
||||
{"KRITEM_TRIPLEBANANA",KRITEM_TRIPLEBANANA},
|
||||
{"KRITEM_TENFOLDBANANA",KRITEM_TENFOLDBANANA},
|
||||
{"KRITEM_TRIPLEORBINAUT",KRITEM_TRIPLEORBINAUT},
|
||||
{"KRITEM_QUADORBINAUT",KRITEM_QUADORBINAUT},
|
||||
{"KRITEM_DUALJAWZ",KRITEM_DUALJAWZ},
|
||||
|
|
|
|||
|
|
@ -235,6 +235,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
readfollower(f);
|
||||
continue;
|
||||
}
|
||||
else if (fastcmp(word, "FOLLOWERCATEGORY"))
|
||||
{
|
||||
// This is not a major mod.
|
||||
readfollowercategory(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
word2 = strtok(NULL, " ");
|
||||
if (word2) {
|
||||
|
|
|
|||
|
|
@ -398,6 +398,19 @@ typedef enum
|
|||
SKINCOLOR_CHAOSEMERALD7,
|
||||
|
||||
SKINCOLOR_INVINCFLASH,
|
||||
SKINCOLOR_POSNUM,
|
||||
SKINCOLOR_POSNUM_WIN1,
|
||||
SKINCOLOR_POSNUM_WIN2,
|
||||
SKINCOLOR_POSNUM_WIN3,
|
||||
SKINCOLOR_POSNUM_LOSE1,
|
||||
SKINCOLOR_POSNUM_LOSE2,
|
||||
SKINCOLOR_POSNUM_LOSE3,
|
||||
SKINCOLOR_POSNUM_BEST1,
|
||||
SKINCOLOR_POSNUM_BEST2,
|
||||
SKINCOLOR_POSNUM_BEST3,
|
||||
SKINCOLOR_POSNUM_BEST4,
|
||||
SKINCOLOR_POSNUM_BEST5,
|
||||
SKINCOLOR_POSNUM_BEST6,
|
||||
|
||||
SKINCOLOR_FIRSTFREESLOT,
|
||||
SKINCOLOR_LASTFREESLOT = SKINCOLOR_FIRSTFREESLOT + NUMCOLORFREESLOTS - 1,
|
||||
|
|
|
|||
61
src/g_demo.c
61
src/g_demo.c
|
|
@ -316,11 +316,11 @@ void G_ReadDemoExtraData(void)
|
|||
demo_p += 16;
|
||||
for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite
|
||||
{
|
||||
if (!stricmp(Followercolor_cons_t[i].strvalue, name))
|
||||
{
|
||||
players[p].followercolor = Followercolor_cons_t[i].value;
|
||||
break;
|
||||
}
|
||||
if (!stricmp(Followercolor_cons_t[i].strvalue, name))
|
||||
{
|
||||
players[p].followercolor = Followercolor_cons_t[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (extradata & DXD_PLAYSTATE)
|
||||
|
|
@ -410,7 +410,7 @@ void G_ReadDemoExtraData(void)
|
|||
|
||||
void G_WriteDemoExtraData(void)
|
||||
{
|
||||
INT32 i;
|
||||
INT32 i, j;
|
||||
char name[16];
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -456,13 +456,18 @@ void G_WriteDemoExtraData(void)
|
|||
if (players[i].followerskin == -1)
|
||||
strncpy(name, "None", 16);
|
||||
else
|
||||
strncpy(name, followers[players[i].followerskin].skinname, 16);
|
||||
strncpy(name, followers[players[i].followerskin].name, 16);
|
||||
M_Memcpy(demo_p, name, 16);
|
||||
demo_p += 16;
|
||||
|
||||
// write follower color
|
||||
memset(name, 0, 16);
|
||||
strncpy(name, Followercolor_cons_t[(UINT16)(players[i].followercolor+2)].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
|
||||
for (j = (numskincolors+2)-1; j > 0; j--)
|
||||
{
|
||||
if (Followercolor_cons_t[j].value == players[i].followercolor)
|
||||
break;
|
||||
}
|
||||
strncpy(name, Followercolor_cons_t[j].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
|
||||
M_Memcpy(demo_p,name,16);
|
||||
demo_p += 16;
|
||||
|
||||
|
|
@ -1954,7 +1959,7 @@ void G_RecordMetal(void)
|
|||
|
||||
void G_BeginRecording(void)
|
||||
{
|
||||
UINT8 i, p;
|
||||
UINT8 i, j, p;
|
||||
char name[MAXCOLORNAME+1];
|
||||
player_t *player = &players[consoleplayer];
|
||||
|
||||
|
|
@ -2009,7 +2014,7 @@ void G_BeginRecording(void)
|
|||
if (wadfiles[i]->important)
|
||||
{
|
||||
nameonly(( filename = va("%s", wadfiles[i]->filename) ));
|
||||
WRITESTRINGN(demo_p, filename, 64);
|
||||
WRITESTRINGL(demo_p, filename, MAX_WADPATH);
|
||||
WRITEMEM(demo_p, wadfiles[i]->md5sum, 16);
|
||||
|
||||
totalfiles++;
|
||||
|
|
@ -2091,7 +2096,7 @@ void G_BeginRecording(void)
|
|||
|
||||
memset(name, 0, 16);
|
||||
if (player->follower)
|
||||
strncpy(name, followers[player->followerskin].skinname, 16);
|
||||
strncpy(name, followers[player->followerskin].name, 16);
|
||||
else
|
||||
strncpy(name, "None", 16); // Say we don't have one, then.
|
||||
|
||||
|
|
@ -2100,7 +2105,12 @@ void G_BeginRecording(void)
|
|||
|
||||
// Save follower's colour
|
||||
memset(name, 0, 16);
|
||||
strncpy(name, Followercolor_cons_t[(UINT16)(player->followercolor+2)].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
|
||||
for (j = (numskincolors+2)-1; j > 0; j--)
|
||||
{
|
||||
if (Followercolor_cons_t[j].value == players[i].followercolor)
|
||||
break;
|
||||
}
|
||||
strncpy(name, Followercolor_cons_t[j].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
|
||||
M_Memcpy(demo_p, name, 16);
|
||||
demo_p += 16;
|
||||
|
||||
|
|
@ -2299,10 +2309,13 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
|
|||
}
|
||||
else
|
||||
{
|
||||
P_AddWadFile(filename);
|
||||
P_PartialAddWadFile(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (P_PartialAddGetStage() >= 0)
|
||||
P_MultiSetupWadFiles(true); // in case any partial adds were done
|
||||
}
|
||||
|
||||
static void G_SkipDemoExtraFiles(UINT8 **pp)
|
||||
|
|
@ -3076,11 +3089,11 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
demo_p += 16;
|
||||
for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite
|
||||
{
|
||||
if (!stricmp(Followercolor_cons_t[i].strvalue, color))
|
||||
{
|
||||
players[p].followercolor = i;
|
||||
break;
|
||||
}
|
||||
if (!stricmp(Followercolor_cons_t[i].strvalue, color))
|
||||
{
|
||||
players[p].followercolor = Followercolor_cons_t[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Score, since Kart uses this to determine where you start on the map
|
||||
|
|
@ -3739,7 +3752,11 @@ static void G_StopTimingDemo(void)
|
|||
|
||||
if (restorecv_vidwait != cv_vidwait.value)
|
||||
CV_SetValue(&cv_vidwait, restorecv_vidwait);
|
||||
D_AdvanceDemo();
|
||||
|
||||
if (timedemo_quit)
|
||||
COM_ImmedExecute("quit");
|
||||
else
|
||||
D_StartTitle();
|
||||
}
|
||||
|
||||
// reset engine variable set for the demos
|
||||
|
|
@ -3798,10 +3815,12 @@ boolean G_CheckDemoStatus(void)
|
|||
{
|
||||
G_StopDemo();
|
||||
|
||||
if (modeattacking)
|
||||
if (timedemo_quit)
|
||||
COM_ImmedExecute("quit");
|
||||
else if (modeattacking)
|
||||
M_EndModeAttackRun();
|
||||
else
|
||||
D_AdvanceDemo();
|
||||
D_StartTitle();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
18
src/g_game.c
18
src/g_game.c
|
|
@ -4280,8 +4280,26 @@ void G_EndGame(void)
|
|||
// Sets a tad of default info we need.
|
||||
void G_LoadGameSettings(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
// initialize free sfx slots for skin sounds
|
||||
S_InitRuntimeSounds();
|
||||
|
||||
// Prepare skincolor material.
|
||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
||||
{
|
||||
Color_cons_t[i].value = Followercolor_cons_t[i+2].value = i;
|
||||
Color_cons_t[i].strvalue = Followercolor_cons_t[i+2].strvalue = skincolors[i].name;
|
||||
}
|
||||
|
||||
Followercolor_cons_t[1].value = FOLLOWERCOLOR_MATCH;
|
||||
Followercolor_cons_t[1].strvalue = "Match"; // Add "Match" option, which will make the follower color match the player's
|
||||
|
||||
Followercolor_cons_t[0].value = FOLLOWERCOLOR_OPPOSITE;
|
||||
Followercolor_cons_t[0].strvalue = "Opposite"; // Add "Opposite" option, ...which is like "Match", but for coloropposite.
|
||||
|
||||
Color_cons_t[MAXSKINCOLORS].value = Followercolor_cons_t[MAXSKINCOLORS+2].value = 0;
|
||||
Color_cons_t[MAXSKINCOLORS].strvalue = Followercolor_cons_t[MAXSKINCOLORS+2].strvalue = NULL;
|
||||
}
|
||||
|
||||
#define GD_VERSIONCHECK 0xBA5ED444 // Change every major version, as usual
|
||||
|
|
|
|||
|
|
@ -326,22 +326,28 @@ patch_t *HU_UpdateOrBlankPatch(patch_t **user, boolean required, const char *for
|
|||
va_list ap;
|
||||
char buffer[9];
|
||||
|
||||
lumpnum_t lump;
|
||||
lumpnum_t lump = INT16_MAX;
|
||||
patch_t *patch;
|
||||
|
||||
va_start (ap, format);
|
||||
vsnprintf(buffer, sizeof buffer, format, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (user && p_adding_file != INT16_MAX)
|
||||
if (user && partadd_earliestfile != UINT16_MAX)
|
||||
{
|
||||
lump = W_CheckNumForNamePwad(buffer, p_adding_file, 0);
|
||||
UINT16 fileref = numwadfiles;
|
||||
lump = INT16_MAX;
|
||||
|
||||
while ((lump == INT16_MAX) && ((--fileref) >= partadd_earliestfile))
|
||||
{
|
||||
lump = W_CheckNumForNamePwad(buffer, fileref, 0);
|
||||
}
|
||||
|
||||
/* no update in this wad */
|
||||
if (lump == INT16_MAX)
|
||||
if (fileref < partadd_earliestfile)
|
||||
return *user;
|
||||
|
||||
lump |= (p_adding_file << 16);
|
||||
lump |= (fileref << 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1251,7 +1257,7 @@ boolean HU_Responder(event_t *ev)
|
|||
if (chatlen+pastelen > HU_MAXMSGLEN)
|
||||
return true; // we can't paste this!!
|
||||
|
||||
memmove(&w_chat[c_input + pastelen], &w_chat[c_input], pastelen);
|
||||
memmove(&w_chat[c_input + pastelen], &w_chat[c_input], (chatlen - c_input) + 1); // +1 for '\0'
|
||||
memcpy(&w_chat[c_input], paste, pastelen); // copy all of that.
|
||||
c_input += pastelen;
|
||||
return true;
|
||||
|
|
|
|||
119
src/info.c
119
src/info.c
|
|
@ -531,6 +531,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"SBOX", // Sphere Box (for Battle)
|
||||
"RPOP", // Random Item Box Pop
|
||||
"ITRI", // Item Box Debris
|
||||
"ITPA", // Paper item backdrop
|
||||
"SGNS", // Signpost sparkle
|
||||
"FAST", // Speed boost trail
|
||||
"DSHR", // Speed boost dust release
|
||||
|
|
@ -559,6 +560,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"RSHE", // Rocket sneaker
|
||||
"FITM", // Eggman Monitor
|
||||
"BANA", // Banana Peel
|
||||
"BAND", // Banana Peel death particles
|
||||
"ORBN", // Orbinaut
|
||||
"JAWZ", // Jawz
|
||||
"SSMN", // SS Mine
|
||||
|
|
@ -3882,6 +3884,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_NULL, 0, 7, {A_SpawnItemDebrisCloud}, 20, 0, S_ITEM_DEBRIS_CLOUD_SPAWNER1}, // S_ITEM_DEBRIS_CLOUD_SPAWNER2
|
||||
|
||||
{SPR_NULL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMICON
|
||||
{SPR_ITPA, FF_FULLBRIGHT, -1, {NULL}, 1, 0, S_NULL}, // S_ITEMBACKDROP
|
||||
|
||||
{SPR_ICAP, FF_ADD|0, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE
|
||||
{SPR_ICAP, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_ITEMCAPSULE_TOP_SIDE
|
||||
|
|
@ -4082,7 +4085,12 @@ state_t states[NUMSTATES] =
|
|||
{SPR_FITM, 24|FF_FULLBRIGHT, 175, {NULL}, 0, 0, S_NULL}, // S_EGGMANITEM_DEAD
|
||||
|
||||
{SPR_BANA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BANANA
|
||||
{SPR_BANA, 0, 175, {NULL}, 0, 0, S_NULL}, // S_BANANA_DEAD
|
||||
{SPR_BANA, 1, 175, {NULL}, 0, 0, S_NULL}, // S_BANANA_DEAD
|
||||
|
||||
{SPR_BAND, 0, -1, {NULL}, 0, 0, S_BANANA_SPARK2}, // S_BANANA_SPARK
|
||||
{SPR_BAND, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BANANA_SPARK3}, // S_BANANA_SPARK2
|
||||
{SPR_BAND, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BANANA_SPARK4}, // S_BANANA_SPARK3
|
||||
{SPR_BAND, 3|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BANANA_SPARK4
|
||||
|
||||
{SPR_ORBN, 0, 1, {NULL}, 0, 0, S_ORBINAUT2}, // S_ORBINAUT1
|
||||
{SPR_ORBN, 1, 1, {NULL}, 0, 0, S_ORBINAUT3}, // S_ORBINAUT2
|
||||
|
|
@ -5294,7 +5302,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
1000, // mass
|
||||
MT_THOK, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SOLID|MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
(statenum_t)MT_THOK // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -5321,7 +5329,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
1000, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SOLID|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -9991,7 +9999,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10018,7 +10026,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10045,7 +10053,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10072,7 +10080,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10099,7 +10107,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10126,7 +10134,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10153,7 +10161,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10180,7 +10188,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10207,7 +10215,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10234,7 +10242,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10261,7 +10269,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10288,7 +10296,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10315,7 +10323,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10342,7 +10350,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10369,7 +10377,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10396,7 +10404,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10423,7 +10431,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10450,7 +10458,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -10477,7 +10485,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
62*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23122,7 +23130,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_peel, // activesound
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23149,7 +23157,34 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BANANA_SPARK
|
||||
-1, // doomednum
|
||||
S_BANANA_SPARK, // 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_BANANA_SPARK2,// deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
4*FRACUNIT, // radius
|
||||
8*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_DONTENCOREMAP|MF_NOCLIPTHING|MF_NOSQUISH, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23176,7 +23211,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_s3k96, // activesound
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23203,7 +23238,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23230,7 +23265,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_s3kc0s, // activesound
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23257,7 +23292,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23311,7 +23346,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_s3k5c, // activesound
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23338,7 +23373,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23446,7 +23481,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
0, // mass
|
||||
0, // damage
|
||||
sfx_s3k5c, // activesound
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SHOOTABLE|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23473,7 +23508,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_s3k96, // activesound
|
||||
MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -23500,7 +23535,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_SPECIAL|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -24121,7 +24156,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
100, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP|MF_APPLYTERRAIN|MF_SLOPE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -29158,7 +29193,21 @@ skincolor_t skincolors[MAXSKINCOLORS] = {
|
|||
{"Chaos Emerald 6", { 0, 208, 50, 32, 34, 37, 40, 44, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_CHAOSEMERALD6
|
||||
{"Chaos Emerald 7", { 0, 120, 121, 140, 133, 135, 149, 156, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_CHAOSEMERALD7
|
||||
|
||||
{"Invinc Flash", { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, SKINCOLOR_NONE, 0, 0, false} // SKINCOLOR_INVINCFLASH
|
||||
{"Invinc Flash", { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_INVINCFLASH
|
||||
|
||||
{"Position", { 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23, 24, 26, 27, 29, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM
|
||||
{"Position Win 1", {152, 152, 153, 153, 154, 154, 155, 155, 156, 156, 157, 158, 159, 253, 254, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_WIN1
|
||||
{"Position Win 2", {134, 134, 135, 135, 135, 136, 136, 136, 137, 137, 138, 138, 139, 139, 254, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_WIN2
|
||||
{"Position Win 3", {255, 255, 122, 122, 123, 123, 141, 141, 142, 142, 143, 143, 138, 139, 254, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_WIN3
|
||||
{"Position Lose 1", { 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 71, 46, 47, 29, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_LOSE1
|
||||
{"Position Lose 2", { 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 63, 44, 45, 46, 47, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_LOSE2
|
||||
{"Position Lose 3", { 73, 74, 75, 76, 76, 77, 77, 78, 78, 79, 79, 236, 237, 238, 239, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_LOSE3
|
||||
{"Position Best 1", { 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 71, 46, 47, 29, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST1
|
||||
{"Position Best 2", { 73, 74, 75, 76, 76, 77, 77, 78, 78, 79, 79, 236, 237, 238, 239, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST2
|
||||
{"Position Best 3", {112, 112, 113, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 110, 111, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST3
|
||||
{"Position Best 4", {255, 255, 122, 122, 123, 123, 141, 141, 142, 142, 143, 143, 138, 139, 254, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST4
|
||||
{"Position Best 5", {152, 152, 153, 153, 154, 154, 155, 155, 156, 156, 157, 158, 159, 253, 254, 30}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_POSNUM_BEST5
|
||||
{"Position Best 6", {181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 29, 30}, SKINCOLOR_NONE, 0, 0, false} // SKINCOLOR_POSNUM_BEST6
|
||||
};
|
||||
|
||||
/** Patches the mobjinfo, state, and skincolor tables.
|
||||
|
|
|
|||
|
|
@ -1077,6 +1077,7 @@ typedef enum sprite
|
|||
SPR_SBOX, // Sphere Box (for Battle)
|
||||
SPR_RPOP, // Random Item Box Pop
|
||||
SPR_ITRI, // Item Box Debris
|
||||
SPR_ITPA, // Paper item backdrop
|
||||
SPR_SGNS, // Signpost sparkle
|
||||
SPR_FAST, // Speed boost trail
|
||||
SPR_DSHR, // Speed boost dust release
|
||||
|
|
@ -1105,6 +1106,7 @@ typedef enum sprite
|
|||
SPR_RSHE, // Rocket sneaker
|
||||
SPR_FITM, // Eggman Monitor
|
||||
SPR_BANA, // Banana Peel
|
||||
SPR_BAND, // Banana Peel death particles
|
||||
SPR_ORBN, // Orbinaut
|
||||
SPR_JAWZ, // Jawz
|
||||
SPR_SSMN, // SS Mine
|
||||
|
|
@ -4285,6 +4287,7 @@ typedef enum state
|
|||
S_ITEM_DEBRIS_CLOUD_SPAWNER2,
|
||||
|
||||
S_ITEMICON,
|
||||
S_ITEMBACKDROP,
|
||||
|
||||
// Item capsules
|
||||
S_ITEMCAPSULE,
|
||||
|
|
@ -4505,6 +4508,11 @@ typedef enum state
|
|||
S_BANANA,
|
||||
S_BANANA_DEAD,
|
||||
|
||||
S_BANANA_SPARK,
|
||||
S_BANANA_SPARK2,
|
||||
S_BANANA_SPARK3,
|
||||
S_BANANA_SPARK4,
|
||||
|
||||
//{ Orbinaut
|
||||
S_ORBINAUT1,
|
||||
S_ORBINAUT2,
|
||||
|
|
@ -6365,6 +6373,7 @@ typedef enum mobj_type
|
|||
|
||||
MT_BANANA, // Banana Stuff
|
||||
MT_BANANA_SHIELD,
|
||||
MT_BANANA_SPARK,
|
||||
|
||||
MT_ORBINAUT, // Orbinaut stuff
|
||||
MT_ORBINAUT_SHIELD,
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(t2, 24*FRACUNIT, false);
|
||||
P_InstaThrust(t2, bounceangle, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
|
||||
|
|
@ -122,7 +122,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
S_StartSound(t1, t1->info->deathsound);
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t1, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(t1, 24*FRACUNIT, false);
|
||||
P_InstaThrust(t1, bounceangle, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
|
|
@ -351,7 +351,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
|||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(t2, 24*FRACUNIT, false);
|
||||
P_InstaThrust(t2, bounceangle, 16*FRACUNIT);
|
||||
}
|
||||
else if (t2->flags & MF_SHOOTABLE)
|
||||
|
|
@ -414,7 +414,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
|
|||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(t2, 24*FRACUNIT, false);
|
||||
P_InstaThrust(t2, bounceangle, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@
|
|||
INT32 numfollowers = 0;
|
||||
follower_t followers[MAXSKINS];
|
||||
|
||||
INT32 numfollowercategories;
|
||||
followercategory_t followercategories[MAXFOLLOWERCATEGORIES];
|
||||
|
||||
CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for "Match", "Opposite" & NULL
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -28,7 +31,7 @@ INT32 K_FollowerAvailable(const char *name)
|
|||
|
||||
for (i = 0; i < numfollowers; i++)
|
||||
{
|
||||
if (stricmp(followers[i].skinname, name) == 0)
|
||||
if (stricmp(followers[i].name, name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +57,7 @@ boolean K_SetFollowerByName(INT32 playernum, const char *skinname)
|
|||
for (i = 0; i < numfollowers; i++)
|
||||
{
|
||||
// search in the skin list
|
||||
if (stricmp(followers[i].skinname, skinname) == 0)
|
||||
if (stricmp(followers[i].name, skinname) == 0)
|
||||
{
|
||||
K_SetFollowerByNum(playernum, i);
|
||||
return true;
|
||||
|
|
@ -74,6 +77,31 @@ boolean K_SetFollowerByName(INT32 playernum, const char *skinname)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RemoveFollower(player_t *player)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_RemoveFollower(player_t *player)
|
||||
{
|
||||
mobj_t *bub, *tmp;
|
||||
if (player->follower && !P_MobjWasRemoved(player->follower)) // this is also called when we change colour so don't respawn the follower unless we changed skins
|
||||
{
|
||||
// Remove follower's possible hnext list (bubble)
|
||||
bub = player->follower->hnext;
|
||||
|
||||
while (bub && !P_MobjWasRemoved(bub))
|
||||
{
|
||||
tmp = bub->hnext;
|
||||
P_RemoveMobj(bub);
|
||||
bub = tmp;
|
||||
}
|
||||
|
||||
P_RemoveMobj(player->follower);
|
||||
P_SetTarget(&player->follower, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_SetFollowerByNum(INT32 playernum, INT32 skinnum)
|
||||
|
||||
|
|
@ -82,8 +110,6 @@ boolean K_SetFollowerByName(INT32 playernum, const char *skinname)
|
|||
void K_SetFollowerByNum(INT32 playernum, INT32 skinnum)
|
||||
{
|
||||
player_t *player = &players[playernum];
|
||||
mobj_t *bub;
|
||||
mobj_t *tmp;
|
||||
|
||||
player->followerready = true; // we are ready to perform follower related actions in the player thinker, now.
|
||||
|
||||
|
|
@ -94,21 +120,8 @@ void K_SetFollowerByNum(INT32 playernum, INT32 skinnum)
|
|||
However, we will despawn it right here if there's any to make it easy for the player thinker to replace it or delete it.
|
||||
*/
|
||||
|
||||
if (player->follower && skinnum != player->followerskin) // this is also called when we change colour so don't respawn the follower unless we changed skins
|
||||
{
|
||||
// Remove follower's possible hnext list (bubble)
|
||||
bub = player->follower->hnext;
|
||||
|
||||
while (bub && !P_MobjWasRemoved(bub))
|
||||
{
|
||||
tmp = bub->hnext;
|
||||
P_RemoveMobj(bub);
|
||||
bub = tmp;
|
||||
}
|
||||
|
||||
P_RemoveMobj(player->follower);
|
||||
P_SetTarget(&player->follower, NULL);
|
||||
}
|
||||
if (skinnum != player->followerskin)
|
||||
K_RemoveFollower(player);
|
||||
|
||||
player->followerskin = skinnum;
|
||||
|
||||
|
|
@ -253,18 +266,16 @@ void K_HandleFollower(player_t *player)
|
|||
{
|
||||
//CONS_Printf("Follower skin invlaid. Setting to -1.\n");
|
||||
player->followerskin = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// don't do anything if we can't have a follower to begin with.
|
||||
// (It gets removed under those conditions)
|
||||
if (player->spectator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->followerskin < 0)
|
||||
if (player->spectator || player->followerskin < 0)
|
||||
{
|
||||
if (player->follower)
|
||||
{
|
||||
K_RemoveFollower(player);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,10 +45,11 @@ typedef enum
|
|||
//
|
||||
typedef struct follower_s
|
||||
{
|
||||
char skinname[SKINNAMESIZE+1]; // Skin Name. This is what to refer to when asking the commands anything.
|
||||
char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this.
|
||||
char name[SKINNAMESIZE+1]; // Skin Name. This is what to refer to when asking the commands anything..
|
||||
char icon[8+1]; // Lump names are only 8 characters. (+1 for \0)
|
||||
|
||||
UINT8 category; // Category
|
||||
|
||||
skincolornum_t defaultcolor; // default color for menus.
|
||||
followermode_t mode; // Follower behavior modifier.
|
||||
|
||||
|
|
@ -85,6 +86,18 @@ typedef struct follower_s
|
|||
extern INT32 numfollowers;
|
||||
extern follower_t followers[MAXSKINS];
|
||||
|
||||
#define MAXFOLLOWERCATEGORIES 32
|
||||
|
||||
typedef struct followercategory_s
|
||||
{
|
||||
char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this.
|
||||
char icon[8+1]; // Lump names are only 8 characters. (+1 for \0)
|
||||
UINT8 numincategory;
|
||||
} followercategory_t;
|
||||
|
||||
extern INT32 numfollowercategories;
|
||||
extern followercategory_t followercategories[MAXFOLLOWERCATEGORIES];
|
||||
|
||||
/*--------------------------------------------------
|
||||
INT32 K_FollowerAvailable(const char *name)
|
||||
|
||||
|
|
@ -168,5 +181,19 @@ UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, UINT16 playercolor);
|
|||
|
||||
void K_HandleFollower(player_t *player);
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RemoveFollower(player_t *player)
|
||||
|
||||
Removes Follower object
|
||||
|
||||
Input Arguments:-
|
||||
player - The player who we want to remove the follower of.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_RemoveFollower(player_t *player);
|
||||
|
||||
|
||||
#endif // __K_FOLLOWER__
|
||||
|
|
|
|||
|
|
@ -676,7 +676,7 @@ void K_PlayerLoseLife(player_t *player)
|
|||
return;
|
||||
}
|
||||
|
||||
if (player->spectator || player->exiting || player->bot || (player->pflags & PF_LOSTLIFE))
|
||||
if (player->spectator || player->exiting || player->bot || player->lives <= 0 || (player->pflags & PF_LOSTLIFE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
297
src/k_hud.c
297
src/k_hud.c
|
|
@ -37,10 +37,6 @@
|
|||
#include "r_fps.h"
|
||||
#include "m_random.h"
|
||||
|
||||
#define NUMPOSNUMS 10
|
||||
#define NUMPOSFRAMES 7 // White, three blues, three reds
|
||||
#define NUMWINFRAMES 6 // Red, yellow, green, cyan, blue, purple
|
||||
|
||||
//{ Patch Definitions
|
||||
static patch_t *kp_nodraw;
|
||||
|
||||
|
|
@ -70,8 +66,7 @@ static patch_t *kp_startcountdown[20];
|
|||
static patch_t *kp_racefault[6];
|
||||
static patch_t *kp_racefinish[6];
|
||||
|
||||
static patch_t *kp_positionnum[NUMPOSNUMS][NUMPOSFRAMES];
|
||||
static patch_t *kp_winnernum[NUMPOSFRAMES];
|
||||
static patch_t *kp_positionnum[10][2][2]; // number, overlay or underlay, splitscreen
|
||||
|
||||
static patch_t *kp_facenum[MAXPLAYERS+1];
|
||||
static patch_t *kp_facehighlight[8];
|
||||
|
|
@ -179,7 +174,7 @@ static patch_t *kp_trickcool[2];
|
|||
|
||||
void K_LoadKartHUDGraphics(void)
|
||||
{
|
||||
INT32 i, j;
|
||||
INT32 i, j, k;
|
||||
char buffer[9];
|
||||
|
||||
// Null Stuff
|
||||
|
|
@ -280,23 +275,29 @@ void K_LoadKartHUDGraphics(void)
|
|||
HU_UpdatePatch(&kp_racefinish[5], "K_2PFINB");
|
||||
|
||||
// Position numbers
|
||||
sprintf(buffer, "K_POSNxx");
|
||||
for (i = 0; i < NUMPOSNUMS; i++)
|
||||
sprintf(buffer, "KRNKxyz");
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
buffer[6] = '0'+i;
|
||||
for (j = 0; j < NUMPOSFRAMES; j++)
|
||||
{
|
||||
//sprintf(buffer, "K_POSN%d%d", i, j);
|
||||
buffer[7] = '0'+j;
|
||||
HU_UpdatePatch(&kp_positionnum[i][j], "%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(buffer, "K_POSNWx");
|
||||
for (i = 0; i < NUMWINFRAMES; i++)
|
||||
{
|
||||
buffer[7] = '0'+i;
|
||||
HU_UpdatePatch(&kp_winnernum[i], "%s", buffer);
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
buffer[5] = 'A'+j;
|
||||
|
||||
for (k = 0; k < 2; k++)
|
||||
{
|
||||
if (k > 0)
|
||||
{
|
||||
buffer[4] = 'S';
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[4] = 'B';
|
||||
}
|
||||
|
||||
HU_UpdatePatch(&kp_positionnum[i][j][k], "%s", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(buffer, "OPPRNKxx");
|
||||
|
|
@ -659,7 +660,6 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny)
|
|||
return (tiny ? "K_ISINV1" : "K_ITINV1");
|
||||
case KITEM_BANANA:
|
||||
case KRITEM_TRIPLEBANANA:
|
||||
case KRITEM_TENFOLDBANANA:
|
||||
return (tiny ? "K_ISBANA" : "K_ITBANA");
|
||||
case KITEM_EGGMAN:
|
||||
return (tiny ? "K_ISEGGM" : "K_ITEGGM");
|
||||
|
|
@ -950,6 +950,11 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean revers
|
|||
h = R_PointToDist2(point->x, point->y, viewx, viewy);
|
||||
da = AngleDeltaSigned(viewpointAngle, R_PointToAngle2(point->x, point->y, viewx, viewy));
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
da = -(da);
|
||||
}
|
||||
|
||||
// Set results relative to top left!
|
||||
result->x = FixedMul(NEWTAN(da), fg);
|
||||
result->y = FixedMul((NEWTAN(viewpointAiming) - FixedDiv((viewz - point->z), 1 + FixedMul(NEWCOS(da), h))), fg);
|
||||
|
|
@ -1545,146 +1550,187 @@ bademblem:
|
|||
}
|
||||
}
|
||||
|
||||
static void K_DrawKartPositionNum(INT32 num)
|
||||
static fixed_t K_DrawKartPositionNumPatch(UINT8 num, UINT8 *color, fixed_t x, fixed_t y, fixed_t scale, INT32 flags)
|
||||
{
|
||||
// POSI_X = BASEVIDWIDTH - 51; // 269
|
||||
// POSI_Y = BASEVIDHEIGHT- 64; // 136
|
||||
UINT8 splitIndex = (r_splitscreen > 0) ? 1 : 0;
|
||||
fixed_t w = FRACUNIT;
|
||||
fixed_t h = FRACUNIT;
|
||||
INT32 overlayFlags[2];
|
||||
INT32 i;
|
||||
|
||||
boolean win = (stplyr->exiting && num == 1);
|
||||
//INT32 X = POSI_X;
|
||||
INT32 W = SHORT(kp_positionnum[0][0]->width);
|
||||
fixed_t scale = FRACUNIT;
|
||||
patch_t *localpatch = kp_positionnum[0][0];
|
||||
INT32 fx = 0, fy = 0, fflags = 0;
|
||||
INT32 addOrSub = V_ADD;
|
||||
boolean flipdraw = false; // flip the order we draw it in for MORE splitscreen bs. fun.
|
||||
boolean flipvdraw = false; // used only for 2p splitscreen so overtaking doesn't make 1P's position fly off the screen.
|
||||
boolean overtake = false;
|
||||
if (num >= 10)
|
||||
{
|
||||
return x; // invalid input
|
||||
}
|
||||
|
||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SUBTRACTNUM) == LF_SUBTRACTNUM)
|
||||
{
|
||||
addOrSub = V_SUBTRACT;
|
||||
overlayFlags[0] = V_SUBTRACT;
|
||||
overlayFlags[1] = V_ADD;
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayFlags[0] = V_ADD;
|
||||
overlayFlags[1] = V_SUBTRACT;
|
||||
}
|
||||
|
||||
w = kp_positionnum[num][0][splitIndex]->width * scale;
|
||||
h = kp_positionnum[num][0][splitIndex]->height * scale;
|
||||
|
||||
if (flags & V_SNAPTORIGHT)
|
||||
{
|
||||
x -= w;
|
||||
}
|
||||
|
||||
if (flags & V_SNAPTOBOTTOM)
|
||||
{
|
||||
y -= h;
|
||||
}
|
||||
|
||||
for (i = 1; i >= 0; i--)
|
||||
{
|
||||
V_DrawFixedPatch(
|
||||
x, y, scale,
|
||||
flags | overlayFlags[i],
|
||||
kp_positionnum[num][i][splitIndex],
|
||||
color
|
||||
);
|
||||
}
|
||||
|
||||
return (x - w);
|
||||
}
|
||||
|
||||
static void K_DrawKartPositionNum(INT32 num)
|
||||
{
|
||||
const tic_t counter = (leveltime / 3); // Alternate colors every three frames
|
||||
fixed_t scale = FRACUNIT;
|
||||
fixed_t fx = 0, fy = 0;
|
||||
transnum_t trans = 0;
|
||||
INT32 fflags = 0;
|
||||
UINT8 *color = NULL;
|
||||
|
||||
if (leveltime < (starttime + NUMTRANSMAPS))
|
||||
{
|
||||
trans = (starttime + NUMTRANSMAPS) - leveltime;
|
||||
}
|
||||
|
||||
if (trans >= NUMTRANSMAPS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (stplyr->positiondelay || stplyr->exiting)
|
||||
{
|
||||
scale *= 2;
|
||||
overtake = true; // this is used for splitscreen stuff in conjunction with flipdraw.
|
||||
const UINT8 delay = (stplyr->exiting) ? POS_DELAY_TIME : stplyr->positiondelay;
|
||||
const fixed_t add = (scale * 3) >> ((r_splitscreen == 1) ? 1 : 2);
|
||||
scale += min((add * (delay * delay)) / (POS_DELAY_TIME * POS_DELAY_TIME), add);
|
||||
}
|
||||
|
||||
if (r_splitscreen)
|
||||
{
|
||||
scale /= 2;
|
||||
}
|
||||
|
||||
W = FixedMul(W<<FRACBITS, scale)>>FRACBITS;
|
||||
|
||||
// pain and suffering defined below
|
||||
if (!r_splitscreen)
|
||||
{
|
||||
fx = POSI_X;
|
||||
fy = BASEVIDHEIGHT - 8;
|
||||
fflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN;
|
||||
fx = BASEVIDWIDTH << FRACBITS;
|
||||
fy = BASEVIDHEIGHT << FRACBITS;
|
||||
fflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||
}
|
||||
else if (r_splitscreen == 1) // for this splitscreen, we'll use case by case because it's a bit different.
|
||||
{
|
||||
fx = POSI_X;
|
||||
if (stplyr == &players[displayplayers[0]]) // for player 1: display this at the top right, above the minimap.
|
||||
fx = BASEVIDWIDTH << FRACBITS;
|
||||
|
||||
if (stplyr == &players[displayplayers[0]])
|
||||
{
|
||||
fy = 30;
|
||||
fflags = V_SNAPTOTOP|V_SNAPTORIGHT|V_SPLITSCREEN;
|
||||
if (overtake)
|
||||
flipvdraw = true; // make sure overtaking doesn't explode us
|
||||
// for player 1: display this at the top right, above the minimap.
|
||||
fy = 0;
|
||||
fflags = V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
}
|
||||
else // if we're not p1, that means we're p2. display this at the bottom right, below the minimap.
|
||||
else
|
||||
{
|
||||
fy = (BASEVIDHEIGHT/2) - 8;
|
||||
fflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN;
|
||||
// if we're not p1, that means we're p2. display this at the bottom right, below the minimap.
|
||||
fy = BASEVIDHEIGHT << FRACBITS;
|
||||
fflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||
}
|
||||
|
||||
fy >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fy = BASEVIDHEIGHT << FRACBITS;
|
||||
|
||||
if (stplyr == &players[displayplayers[0]]
|
||||
|| stplyr == &players[displayplayers[2]])
|
||||
{
|
||||
// If we are P1 or P3...
|
||||
fx = 0;
|
||||
fflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
// else, that means we're P2 or P4.
|
||||
fx = BASEVIDWIDTH << FRACBITS;
|
||||
fflags = V_SNAPTORIGHT|V_SNAPTOBOTTOM;
|
||||
}
|
||||
|
||||
fx >>= 1;
|
||||
fy >>= 1;
|
||||
}
|
||||
|
||||
if (trans > 0)
|
||||
{
|
||||
fflags |= (trans << V_ALPHASHIFT);
|
||||
}
|
||||
|
||||
if (stplyr->exiting && num == 1)
|
||||
{
|
||||
// 1st place winner? You get rainbows!!
|
||||
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_BEST1 + (counter % 6), GTC_CACHE);
|
||||
}
|
||||
else if (stplyr->laps >= numlaps || stplyr->exiting)
|
||||
{
|
||||
// On the final lap, or already won.
|
||||
boolean useRedNums = K_IsPlayerLosing(stplyr);
|
||||
|
||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SUBTRACTNUM) == LF_SUBTRACTNUM)
|
||||
{
|
||||
// Subtracting RED will look BLUE, and vice versa.
|
||||
useRedNums = !useRedNums;
|
||||
}
|
||||
|
||||
if (useRedNums == true)
|
||||
{
|
||||
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_LOSE1 + (counter % 3), GTC_CACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_WIN1 + (counter % 3), GTC_CACHE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stplyr == &players[displayplayers[0]] || stplyr == &players[displayplayers[2]]) // If we are P1 or P3...
|
||||
{
|
||||
fx = POSI_X;
|
||||
fy = POSI_Y;
|
||||
fflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
|
||||
flipdraw = true;
|
||||
if (num && num >= 10)
|
||||
fx += W; // this seems dumb, but we need to do this in order for positions above 10 going off screen.
|
||||
}
|
||||
else // else, that means we're P2 or P4.
|
||||
{
|
||||
fx = POSI2_X;
|
||||
fy = POSI2_Y;
|
||||
fflags = V_SNAPTORIGHT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
|
||||
}
|
||||
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM, GTC_CACHE);
|
||||
}
|
||||
|
||||
// Special case for 0
|
||||
if (num <= 0)
|
||||
{
|
||||
V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, scale, addOrSub|V_SLIDEIN|fflags, kp_positionnum[0][0], NULL);
|
||||
K_DrawKartPositionNumPatch(
|
||||
0, color,
|
||||
fx, fy, scale, V_SLIDEIN|V_SPLITSCREEN|fflags
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw the number
|
||||
while (num)
|
||||
{
|
||||
if (win) // 1st place winner? You get rainbows!!
|
||||
{
|
||||
localpatch = kp_winnernum[(leveltime % (NUMWINFRAMES*3)) / 3];
|
||||
}
|
||||
else if (stplyr->laps >= numlaps || stplyr->exiting) // Check for the final lap, or won
|
||||
{
|
||||
boolean useRedNums = K_IsPlayerLosing(stplyr);
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
if (addOrSub == V_SUBTRACT)
|
||||
{
|
||||
// Subtracting RED will look BLUE, and vice versa.
|
||||
useRedNums = !useRedNums;
|
||||
}
|
||||
|
||||
// Alternate frame every three frames
|
||||
switch ((leveltime % 9) / 3)
|
||||
{
|
||||
case 0:
|
||||
if (useRedNums == true)
|
||||
localpatch = kp_positionnum[num % 10][4];
|
||||
else
|
||||
localpatch = kp_positionnum[num % 10][1];
|
||||
break;
|
||||
case 1:
|
||||
if (useRedNums == true)
|
||||
localpatch = kp_positionnum[num % 10][5];
|
||||
else
|
||||
localpatch = kp_positionnum[num % 10][2];
|
||||
break;
|
||||
case 2:
|
||||
if (useRedNums == true)
|
||||
localpatch = kp_positionnum[num % 10][6];
|
||||
else
|
||||
localpatch = kp_positionnum[num % 10][3];
|
||||
break;
|
||||
default:
|
||||
localpatch = kp_positionnum[num % 10][0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
localpatch = kp_positionnum[num % 10][0];
|
||||
}
|
||||
|
||||
V_DrawFixedPatch(
|
||||
(fx<<FRACBITS) + ((overtake && flipdraw) ? (SHORT(localpatch->width)*scale/2) : 0),
|
||||
(fy<<FRACBITS) + ((overtake && flipvdraw) ? (SHORT(localpatch->height)*scale/2) : 0),
|
||||
scale, addOrSub|V_SLIDEIN|fflags, localpatch, NULL
|
||||
fx = K_DrawKartPositionNumPatch(
|
||||
(num % 10), color,
|
||||
fx, fy, scale, V_SLIDEIN|V_SPLITSCREEN|fflags
|
||||
);
|
||||
// ^ if we overtake as p1 or p3 in splitscren, we shift it so that it doesn't go off screen.
|
||||
// ^ if we overtake as p1 in 2p splits, shift vertically so that this doesn't happen either.
|
||||
|
||||
fx -= W;
|
||||
num /= 10;
|
||||
}
|
||||
}
|
||||
|
|
@ -4514,7 +4560,6 @@ static void K_drawDistributionDebugger(void)
|
|||
kp_sneaker[1],
|
||||
kp_sneaker[1],
|
||||
kp_banana[1],
|
||||
kp_banana[1],
|
||||
kp_orbinaut[4],
|
||||
kp_orbinaut[4],
|
||||
kp_jawz[1]
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#define RINGANIM_NUMFRAMES 10
|
||||
#define RINGANIM_DELAYMAX 5
|
||||
|
||||
#define POS_DELAY_TIME 10
|
||||
|
||||
void K_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 dupy);
|
||||
|
||||
typedef struct trackingResult_s
|
||||
|
|
|
|||
72
src/k_kart.c
72
src/k_kart.c
|
|
@ -305,7 +305,6 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_dualsneaker);
|
||||
CV_RegisterVar(&cv_triplesneaker);
|
||||
CV_RegisterVar(&cv_triplebanana);
|
||||
CV_RegisterVar(&cv_decabanana);
|
||||
CV_RegisterVar(&cv_tripleorbinaut);
|
||||
CV_RegisterVar(&cv_quadorbinaut);
|
||||
CV_RegisterVar(&cv_dualjawz);
|
||||
|
|
@ -409,7 +408,6 @@ consvar_t *KartItemCVars[NUMKARTRESULTS-1] =
|
|||
&cv_dualsneaker,
|
||||
&cv_triplesneaker,
|
||||
&cv_triplebanana,
|
||||
&cv_decabanana,
|
||||
&cv_tripleorbinaut,
|
||||
&cv_quadorbinaut,
|
||||
&cv_dualjawz
|
||||
|
|
@ -428,7 +426,7 @@ static UINT8 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
|
|||
{ 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
|
||||
{ 5, 5, 2, 2, 0, 0, 0, 0 }, // Orbinaut
|
||||
{ 0, 4, 2, 1, 0, 0, 0, 0 }, // Jawz
|
||||
{ 0, 3, 3, 1, 0, 0, 0, 0 }, // Mine
|
||||
{ 0, 3, 3, 2, 0, 0, 0, 0 }, // Mine
|
||||
{ 3, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine
|
||||
{ 0, 0, 2, 2, 0, 0, 0, 0 }, // Ballhog
|
||||
{ 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb
|
||||
|
|
@ -446,7 +444,6 @@ static UINT8 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
|
|||
{ 0, 0, 2, 2, 2, 0, 0, 0 }, // Sneaker x2
|
||||
{ 0, 0, 0, 0, 4, 4, 4, 0 }, // Sneaker x3
|
||||
{ 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3
|
||||
{ 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10
|
||||
{ 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3
|
||||
{ 0, 0, 0, 2, 0, 0, 0, 0 }, // Orbinaut x4
|
||||
{ 0, 0, 1, 2, 1, 0, 0, 0 } // Jawz x2
|
||||
|
|
@ -480,7 +477,6 @@ static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
|
|||
{ 0, 0 }, // Sneaker x2
|
||||
{ 0, 1 }, // Sneaker x3
|
||||
{ 0, 0 }, // Banana x3
|
||||
{ 1, 1 }, // Banana x10
|
||||
{ 2, 0 }, // Orbinaut x3
|
||||
{ 1, 1 }, // Orbinaut x4
|
||||
{ 5, 1 } // Jawz x2
|
||||
|
|
@ -516,7 +512,6 @@ static UINT8 K_KartItemOddsSpecial[NUMKARTRESULTS-1][4] =
|
|||
{ 0, 1, 1, 0 }, // Sneaker x2
|
||||
{ 0, 0, 1, 1 }, // Sneaker x3
|
||||
{ 0, 0, 0, 0 }, // Banana x3
|
||||
{ 0, 0, 0, 0 }, // Banana x10
|
||||
{ 0, 1, 1, 0 }, // Orbinaut x3
|
||||
{ 0, 0, 1, 1 }, // Orbinaut x4
|
||||
{ 0, 0, 1, 1 } // Jawz x2
|
||||
|
|
@ -577,7 +572,6 @@ SINT8 K_ItemResultToType(SINT8 getitem)
|
|||
return KITEM_SNEAKER;
|
||||
|
||||
case KRITEM_TRIPLEBANANA:
|
||||
case KRITEM_TENFOLDBANANA:
|
||||
return KITEM_BANANA;
|
||||
|
||||
case KRITEM_TRIPLEORBINAUT:
|
||||
|
|
@ -615,9 +609,6 @@ UINT8 K_ItemResultToAmount(SINT8 getitem)
|
|||
case KITEM_BALLHOG: // Not a special result, but has a special amount
|
||||
return 5;
|
||||
|
||||
case KRITEM_TENFOLDBANANA:
|
||||
return 10;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -891,7 +882,6 @@ INT32 K_KartGetItemOdds(
|
|||
break;
|
||||
|
||||
case KRITEM_TRIPLEBANANA:
|
||||
case KRITEM_TENFOLDBANANA:
|
||||
powerItem = true;
|
||||
notNearEnd = true;
|
||||
break;
|
||||
|
|
@ -3471,7 +3461,7 @@ boolean K_TripwirePass(player_t *player)
|
|||
|
||||
boolean K_MovingHorizontally(mobj_t *mobj)
|
||||
{
|
||||
return (P_AproxDistance(mobj->momx, mobj->momy) / 5 > abs(mobj->momz));
|
||||
return (P_AproxDistance(mobj->momx, mobj->momy) / 4 > abs(mobj->momz));
|
||||
}
|
||||
|
||||
boolean K_WaterRun(mobj_t *mobj)
|
||||
|
|
@ -6174,6 +6164,7 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
|
|||
{
|
||||
// Shoot forward
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, mapthing);
|
||||
mo->angle = player->mo->angle;
|
||||
|
||||
// These are really weird so let's make it a very specific case to make SURE it works...
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
|
|
@ -6188,7 +6179,6 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
|
|||
|
||||
S_StartSound(player->mo, mo->info->seesound);
|
||||
|
||||
if (mo)
|
||||
{
|
||||
angle_t fa = player->mo->angle>>ANGLETOFINESHIFT;
|
||||
fixed_t HEIGHT = ((20 + (dir*10)) * FRACUNIT) + (FixedDiv(player->mo->momz, mapobjectscale)*P_MobjFlip(player->mo)); // Also intentionally not player scale
|
||||
|
|
@ -6196,14 +6186,20 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
|
|||
P_SetObjectMomZ(mo, HEIGHT, false);
|
||||
mo->momx = player->mo->momx + FixedMul(FINECOSINE(fa), PROJSPEED*dir);
|
||||
mo->momy = player->mo->momy + FixedMul(FINESINE(fa), PROJSPEED*dir);
|
||||
}
|
||||
|
||||
mo->extravalue2 = dir;
|
||||
mo->extravalue2 = dir;
|
||||
|
||||
if (mo->eflags & MFE_UNDERWATER)
|
||||
mo->momz = (117 * mo->momz) / 200;
|
||||
if (mo->eflags & MFE_UNDERWATER)
|
||||
mo->momz = (117 * mo->momz) / 200;
|
||||
|
||||
P_SetScale(mo, finalscale);
|
||||
mo->destscale = finalscale;
|
||||
P_SetScale(mo, finalscale);
|
||||
mo->destscale = finalscale;
|
||||
|
||||
if (mapthing == MT_BANANA)
|
||||
{
|
||||
mo->angle = FixedAngle(P_RandomRange(PR_DECORATION, -180, 180) << FRACBITS);
|
||||
mo->rollangle = FixedAngle(P_RandomRange(PR_DECORATION, -180, 180) << FRACBITS);
|
||||
}
|
||||
|
||||
// this is the small graphic effect that plops in you when you throw an item:
|
||||
|
|
@ -6288,6 +6284,8 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
|
|||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
mo->eflags |= MFE_VERTICALFLIP;
|
||||
|
||||
mo->angle = newangle;
|
||||
|
||||
if (mapthing == MT_SSMINE)
|
||||
mo->extravalue1 = 49; // Pads the start-up length from 21 frames to a full 2 seconds
|
||||
else if (mapthing == MT_BUBBLESHIELDTRAP)
|
||||
|
|
@ -6609,6 +6607,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound)
|
|||
mo->player->tricktime = 0; // Reset post-hitlag timer
|
||||
// Setup the boost for potential upwards trick, at worse, make it your regular max speed. (boost = curr speed*1.25)
|
||||
mo->player->trickboostpower = max(FixedDiv(mo->player->speed, K_GetKartSpeed(mo->player, false, false)) - FRACUNIT, 0)*125/100;
|
||||
mo->player->trickboostpower = FixedDiv(mo->player->trickboostpower, K_GrowShrinkSpeedMul(mo->player));
|
||||
//CONS_Printf("Got boost: %d%\n", mo->player->trickboostpower*100 / FRACUNIT);
|
||||
}
|
||||
|
||||
|
|
@ -6703,7 +6702,7 @@ killnext:
|
|||
S_StartSound(banana, banana->info->deathsound);
|
||||
P_KillMobj(banana, inflictor, source, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(banana, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(banana, 24*FRACUNIT, false);
|
||||
if (inflictor)
|
||||
P_InstaThrust(banana, R_PointToAngle2(inflictor->x, inflictor->y, banana->x, banana->y)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
|
|
@ -6965,9 +6964,14 @@ void K_DropHnextList(player_t *player, boolean keepshields)
|
|||
mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount)
|
||||
{
|
||||
mobj_t *drop = P_SpawnMobj(x, y, z, MT_FLOATINGITEM);
|
||||
mobj_t *backdrop = P_SpawnMobjFromMobj(drop, 0, 0, 0, MT_OVERLAY);
|
||||
|
||||
P_SetTarget(&backdrop->target, drop);
|
||||
P_SetMobjState(backdrop, S_ITEMBACKDROP);
|
||||
|
||||
P_SetScale(drop, drop->scale>>4);
|
||||
drop->destscale = (3*drop->destscale)/2;
|
||||
|
||||
|
||||
drop->angle = angle;
|
||||
P_Thrust(drop,
|
||||
FixedAngle(P_RandomFixed(PR_ITEM_ROULETTE) * 180) + angle,
|
||||
|
|
@ -7043,6 +7047,9 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
|
|||
}
|
||||
|
||||
drop->flags |= MF_NOCLIPTHING;
|
||||
backdrop->dispoffset = 1;
|
||||
P_SetTarget(&backdrop->tracer, drop);
|
||||
backdrop->flags2 |= MF2_LINKDRAW;
|
||||
|
||||
return drop;
|
||||
}
|
||||
|
|
@ -7096,7 +7103,7 @@ void K_DropRocketSneaker(player_t *player)
|
|||
flingangle = ANG60;
|
||||
|
||||
S_StartSound(shoe, shoe->info->deathsound);
|
||||
P_SetObjectMomZ(shoe, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(shoe, 24*FRACUNIT, false);
|
||||
P_InstaThrust(shoe, R_PointToAngle2(shoe->target->x, shoe->target->y, shoe->x, shoe->y)+flingangle, 16*FRACUNIT);
|
||||
shoe->momx += shoe->target->momx;
|
||||
shoe->momy += shoe->target->momy;
|
||||
|
|
@ -9898,8 +9905,16 @@ void K_KartUpdatePosition(player_t *player)
|
|||
if (leveltime < starttime || oldposition == 0)
|
||||
oldposition = position;
|
||||
|
||||
if (oldposition != position) // Changed places?
|
||||
player->positiondelay = 10; // Position number growth
|
||||
if (position != oldposition) // Changed places?
|
||||
{
|
||||
if (position < oldposition && P_IsDisplayPlayer(player) == true)
|
||||
{
|
||||
// Play sound when getting closer to 1st.
|
||||
S_StartSound(player->mo, sfx_mbs41);
|
||||
}
|
||||
|
||||
player->positiondelay = POS_DELAY_TIME + 4; // Position number growth
|
||||
}
|
||||
|
||||
/* except in FREE PLAY */
|
||||
if (player->curshield == KSHIELD_TOP &&
|
||||
|
|
@ -11394,9 +11409,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
{
|
||||
const angle_t lr = ANGLE_45;
|
||||
fixed_t momz = FixedDiv(player->mo->momz, mapobjectscale); // bring momz back to scale...
|
||||
fixed_t invertscale = FixedDiv(FRACUNIT, K_GrowShrinkSpeedMul(player));
|
||||
fixed_t speedmult = max(0, FRACUNIT - abs(momz)/TRICKMOMZRAMP); // TRICKMOMZRAMP momz is minimum speed (Should be 20)
|
||||
fixed_t basespeed = K_GetKartSpeed(player, false, false); // at WORSE, keep your normal speed when tricking.
|
||||
fixed_t speed = FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy));
|
||||
fixed_t basespeed = FixedMul(invertscale, K_GetKartSpeed(player, false, false)); // at WORSE, keep your normal speed when tricking.
|
||||
fixed_t speed = FixedMul(invertscale, FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy)));
|
||||
|
||||
K_trickPanelTimingVisual(player, momz);
|
||||
|
||||
|
|
@ -11483,14 +11499,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
}
|
||||
else if (cmd->throwdir < 0)
|
||||
{
|
||||
boolean relative = true;
|
||||
|
||||
player->mo->momx /= 3;
|
||||
player->mo->momy /= 3;
|
||||
|
||||
if (player->mo->momz * P_MobjFlip(player->mo) <= 0)
|
||||
{
|
||||
relative = false;
|
||||
player->mo->momz = 0; // relative = false;
|
||||
}
|
||||
|
||||
// Calculate speed boost decay:
|
||||
|
|
@ -11499,7 +11513,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
player->trickboostdecay = min(TICRATE*3/4, abs(momz/FRACUNIT));
|
||||
//CONS_Printf("decay: %d\n", player->trickboostdecay);
|
||||
|
||||
P_SetObjectMomZ(player->mo, 48*FRACUNIT, relative);
|
||||
player->mo->momz += P_MobjFlip(player->mo)*48*mapobjectscale;
|
||||
player->trickpanel = 4;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -410,6 +410,8 @@ typedef enum
|
|||
{
|
||||
mpause_addons = 0,
|
||||
mpause_switchmap,
|
||||
mpause_restartmap,
|
||||
mpause_tryagain,
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
mpause_discordrequests,
|
||||
#endif
|
||||
|
|
@ -599,6 +601,7 @@ typedef enum
|
|||
CSSTEP_CHARS,
|
||||
CSSTEP_ALTS,
|
||||
CSSTEP_COLORS,
|
||||
CSSTEP_FOLLOWERCATEGORY,
|
||||
CSSTEP_FOLLOWER,
|
||||
CSSTEP_FOLLOWERCOLORS,
|
||||
CSSTEP_READY
|
||||
|
|
@ -614,6 +617,7 @@ typedef struct setup_player_s
|
|||
UINT8 delay;
|
||||
UINT16 color;
|
||||
UINT8 mdepth;
|
||||
boolean hitlag;
|
||||
|
||||
// Hack, save player 1's original device even if they init charsel with keyboard.
|
||||
// If they play ALONE, allow them to retain that original device, otherwise, ignore this.
|
||||
|
|
@ -622,7 +626,8 @@ typedef struct setup_player_s
|
|||
|
||||
UINT8 changeselect;
|
||||
|
||||
INT32 followern;
|
||||
INT16 followercategory;
|
||||
INT16 followern;
|
||||
UINT16 followercolor;
|
||||
tic_t follower_tics;
|
||||
tic_t follower_timer;
|
||||
|
|
@ -975,6 +980,8 @@ extern consvar_t cv_dummymenuplayer;
|
|||
extern consvar_t cv_dummyspectator;
|
||||
|
||||
// Bunch of funny functions for the pause menu...~
|
||||
void M_RestartMap(INT32 choice); // Restart level (MP)
|
||||
void M_TryAgain(INT32 choice); // Try again (SP)
|
||||
void M_ConfirmSpectate(INT32 choice); // Spectate confirm when you're alone
|
||||
void M_ConfirmEnterGame(INT32 choice); // Enter game confirm when you're alone
|
||||
void M_ConfirmSpectateChange(INT32 choice); // Splitscreen spectate/play menu func
|
||||
|
|
|
|||
|
|
@ -1071,7 +1071,6 @@ menuitem_t OPTIONS_GameplayItems[] =
|
|||
|
||||
{IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas", NULL, {.routine = M_HandleItemToggles}, KITEM_BANANA, 0},
|
||||
{IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x3", NULL, {.routine = M_HandleItemToggles}, KRITEM_TRIPLEBANANA, 0},
|
||||
{IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x10", NULL, {.routine = M_HandleItemToggles}, KRITEM_TENFOLDBANANA, 0},
|
||||
{IT_KEYHANDLER | IT_NOTHING, NULL, "Proximity Mines", NULL, {.routine = M_HandleItemToggles}, KITEM_MINE, 0},
|
||||
|
||||
{IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts", NULL, {.routine = M_HandleItemToggles}, KITEM_ORBINAUT, 0},
|
||||
|
|
@ -1594,6 +1593,12 @@ menuitem_t PAUSE_Main[] =
|
|||
{IT_STRING | IT_SUBMENU, "CHANGE MAP", "M_ICOMAP",
|
||||
NULL, {.submenu = &PAUSE_GamemodesDef}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "RESTART MAP", "M_ICORE",
|
||||
NULL, {.routine = M_RestartMap}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "TRY AGAIN", "M_ICORE",
|
||||
NULL, {.routine = M_TryAgain}, 0, 0},
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
{IT_STRING | IT_CALL, "DISCORD REQUESTS", "M_ICODIS",
|
||||
NULL, {NULL}, 0, 0},
|
||||
|
|
|
|||
272
src/k_menudraw.c
272
src/k_menudraw.c
|
|
@ -969,7 +969,8 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
{
|
||||
angle_t angamt = ANGLE_MAX;
|
||||
UINT16 i, numoptions = 0;
|
||||
UINT16 l = 0, r = 0;
|
||||
INT16 l = 0, r = 0;
|
||||
INT16 subtractcheck;
|
||||
|
||||
switch (p->mdepth)
|
||||
{
|
||||
|
|
@ -979,8 +980,11 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
case CSSTEP_COLORS:
|
||||
numoptions = nummenucolors;
|
||||
break;
|
||||
case CSSTEP_FOLLOWERCATEGORY:
|
||||
numoptions = numfollowercategories+1;
|
||||
break;
|
||||
case CSSTEP_FOLLOWER:
|
||||
numoptions = numfollowers+1;
|
||||
numoptions = followercategories[p->followercategory].numincategory;
|
||||
break;
|
||||
case CSSTEP_FOLLOWERCOLORS:
|
||||
numoptions = nummenucolors+2;
|
||||
|
|
@ -994,17 +998,19 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
return;
|
||||
}
|
||||
|
||||
subtractcheck = 1 ^ (numoptions & 1);
|
||||
|
||||
angamt /= numoptions;
|
||||
|
||||
for (i = 0; i < numoptions; i++)
|
||||
{
|
||||
fixed_t cx = x << FRACBITS, cy = y << FRACBITS;
|
||||
boolean subtract = (i & 1);
|
||||
boolean subtract = (i & 1) == subtractcheck;
|
||||
angle_t ang = ((i+1)/2) * angamt;
|
||||
patch_t *patch = NULL;
|
||||
UINT8 *colormap = NULL;
|
||||
fixed_t radius = 28<<FRACBITS;
|
||||
UINT16 n = 0;
|
||||
INT16 n = 0;
|
||||
|
||||
switch (p->mdepth)
|
||||
{
|
||||
|
|
@ -1017,7 +1023,7 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
n -= ((i+1)/2);
|
||||
else
|
||||
n += ((i+1)/2);
|
||||
n %= numoptions;
|
||||
n = (n + numoptions) % numoptions;
|
||||
|
||||
skin = setup_chargrid[p->gridx][p->gridy].skinlist[n];
|
||||
patch = faceprefix[skin][FACE_RANK];
|
||||
|
|
@ -1061,16 +1067,16 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
break;
|
||||
}
|
||||
|
||||
case CSSTEP_FOLLOWER:
|
||||
case CSSTEP_FOLLOWERCATEGORY:
|
||||
{
|
||||
follower_t *fl = NULL;
|
||||
followercategory_t *fc = NULL;
|
||||
|
||||
n = (p->followern + 1) + numoptions/2;
|
||||
n = (p->followercategory + 1) + numoptions/2;
|
||||
if (subtract)
|
||||
n -= ((i+1)/2);
|
||||
else
|
||||
n += ((i+1)/2);
|
||||
n %= numoptions;
|
||||
n = (n + numoptions) % numoptions;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
|
|
@ -1078,11 +1084,71 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
}
|
||||
else
|
||||
{
|
||||
fl = &followers[n - 1];
|
||||
fc = &followercategories[n - 1];
|
||||
patch = W_CachePatchName(fc->icon, PU_CACHE);
|
||||
}
|
||||
|
||||
radius = 24<<FRACBITS;
|
||||
|
||||
cx -= (SHORT(patch->width) << FRACBITS) >> 1;
|
||||
cy -= (SHORT(patch->height) << FRACBITS) >> 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case CSSTEP_FOLLOWER:
|
||||
{
|
||||
follower_t *fl = NULL;
|
||||
INT16 startfollowern = p->followern;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
n = p->followern;
|
||||
r = (numoptions+1)/2;
|
||||
while (r)
|
||||
{
|
||||
n--;
|
||||
if (n < 0)
|
||||
n = numfollowers-1;
|
||||
if (n == startfollowern)
|
||||
break;
|
||||
if (followers[n].category == p->followercategory)
|
||||
r--;
|
||||
}
|
||||
l = r = n;
|
||||
}
|
||||
else if (subtract)
|
||||
{
|
||||
do
|
||||
{
|
||||
l--;
|
||||
if (l < 0)
|
||||
l = numfollowers-1;
|
||||
if (l == startfollowern)
|
||||
break;
|
||||
}
|
||||
while (followers[l].category != p->followercategory);
|
||||
n = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
r++;
|
||||
if (r >= numfollowers)
|
||||
r = 0;
|
||||
if (r == startfollowern)
|
||||
break;
|
||||
}
|
||||
while (followers[r].category != p->followercategory);
|
||||
n = r;
|
||||
}
|
||||
|
||||
{
|
||||
fl = &followers[n];
|
||||
patch = W_CachePatchName(fl->icon, PU_CACHE);
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT,
|
||||
K_GetEffectiveFollowerColor(p->followercolor, p->color),
|
||||
K_GetEffectiveFollowerColor(fl->defaultcolor, p->color),
|
||||
GTC_MENUCACHE
|
||||
);
|
||||
}
|
||||
|
|
@ -1142,7 +1208,12 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
ang = (signed)(ang - (angamt/2));
|
||||
|
||||
if (p->rotate)
|
||||
ang = (signed)(ang + ((angamt / CSROTATETICS) * p->rotate));
|
||||
{
|
||||
SINT8 rotate = p->rotate;
|
||||
if ((p->hitlag == true) && (setup_animcounter & 1))
|
||||
rotate = -rotate;
|
||||
ang = (signed)(ang + ((angamt / CSROTATETICS) * rotate));
|
||||
}
|
||||
|
||||
cx += FixedMul(radius, FINECOSINE(ang >> ANGLETOFINESHIFT));
|
||||
cy -= FixedMul(radius, FINESINE(ang >> ANGLETOFINESHIFT)) / 3;
|
||||
|
|
@ -1154,41 +1225,40 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
}
|
||||
|
||||
// returns false if the character couldn't be rendered
|
||||
static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, INT32 addflags, UINT8 *colormap)
|
||||
static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, boolean charflip, boolean animate, INT32 addflags, UINT8 *colormap)
|
||||
{
|
||||
UINT8 spr;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
patch_t *sprpatch;
|
||||
UINT8 rotation = (charflip ? 1 : 7);
|
||||
UINT32 frame = animate ? setup_animcounter : 0;
|
||||
|
||||
UINT32 flags = 0;
|
||||
UINT32 frame;
|
||||
|
||||
spr = P_GetSkinSprite2(&skins[skin], SPR2_FSTN, NULL);
|
||||
spr = P_GetSkinSprite2(&skins[skin], SPR2_STIN, NULL);
|
||||
sprdef = &skins[skin].sprites[spr];
|
||||
|
||||
if (!sprdef->numframes) // No frames ??
|
||||
return false; // Can't render!
|
||||
|
||||
frame = states[S_KART_FAST].frame & FF_FRAMEMASK;
|
||||
if (frame >= sprdef->numframes) // Walking animation missing
|
||||
frame = 0; // Try to use standing frame
|
||||
frame %= sprdef->numframes;
|
||||
|
||||
sprframe = &sprdef->spriteframes[frame];
|
||||
sprpatch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE);
|
||||
sprpatch = W_CachePatchNum(sprframe->lumppat[rotation], PU_CACHE);
|
||||
|
||||
if (sprframe->flip & 1) // Only for first sprite
|
||||
flags |= V_FLIP; // This sprite is left/right flipped!
|
||||
if (sprframe->flip & (1<<rotation)) // Only for first sprite
|
||||
{
|
||||
addflags ^= V_FLIP; // This sprite is left/right flipped!
|
||||
}
|
||||
|
||||
if (skins[skin].highresscale != FRACUNIT)
|
||||
{
|
||||
V_DrawFixedPatch(x<<FRACBITS,
|
||||
y<<FRACBITS,
|
||||
skins[skin].highresscale,
|
||||
flags, sprpatch, colormap);
|
||||
addflags, sprpatch, colormap);
|
||||
}
|
||||
else
|
||||
V_DrawMappedPatch(x, y, addflags|flags, sprpatch, colormap);
|
||||
V_DrawMappedPatch(x, y, addflags, sprpatch, colormap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1196,7 +1266,7 @@ static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, INT32 addflag
|
|||
// Returns false is the follower shouldn't be rendered.
|
||||
// 'num' can be used to directly specify the follower number, but doing this will not animate it.
|
||||
// if a setup_player_t is specified instead, its data will be used to animate the follower sprite.
|
||||
static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, INT32 addflags, UINT16 color, setup_player_t *p)
|
||||
static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, boolean charflip, INT32 addflags, UINT16 color, setup_player_t *p)
|
||||
{
|
||||
|
||||
spritedef_t *sprdef;
|
||||
|
|
@ -1207,6 +1277,7 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, INT32 addflags,
|
|||
UINT32 useframe;
|
||||
follower_t fl;
|
||||
UINT8 *colormap = NULL;
|
||||
UINT8 rotation = (charflip ? 1 : 7);
|
||||
|
||||
if (p != NULL)
|
||||
followernum = p->followern;
|
||||
|
|
@ -1238,14 +1309,11 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, INT32 addflags,
|
|||
useframe = 0; // frame doesn't exist, we went beyond it... what?
|
||||
|
||||
sprframe = &sprdef->spriteframes[useframe];
|
||||
patch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE);
|
||||
patch = W_CachePatchNum(sprframe->lumppat[rotation], PU_CACHE);
|
||||
|
||||
if (sprframe->flip & 2) // Only for first sprite
|
||||
if (sprframe->flip & (1<<rotation)) // Only for first sprite
|
||||
{
|
||||
if (addflags & V_FLIP)
|
||||
addflags &= ~V_FLIP;
|
||||
else
|
||||
addflags |= V_FLIP; // This sprite is left/right flipped!
|
||||
addflags ^= V_FLIP; // This sprite is left/right flipped!
|
||||
}
|
||||
|
||||
fixed_t sine = 0;
|
||||
|
|
@ -1253,35 +1321,33 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, INT32 addflags,
|
|||
if (p != NULL)
|
||||
{
|
||||
sine = FixedMul(fl.bobamp, FINESINE(((FixedMul(4 * M_TAU_FIXED, fl.bobspeed) * p->follower_timer)>>ANGLETOFINESHIFT) & FINEMASK));
|
||||
color = K_GetEffectiveFollowerColor(p->followercolor, p->color);
|
||||
color = K_GetEffectiveFollowerColor(
|
||||
(p->mdepth < CSSTEP_FOLLOWERCOLORS) ? fl.defaultcolor : p->followercolor,
|
||||
p->color);
|
||||
}
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, color, GTC_MENUCACHE);
|
||||
V_DrawFixedPatch((x)*FRACUNIT, ((y-12)*FRACUNIT) + sine - fl.zoffs, fl.scale, addflags, patch, colormap);
|
||||
V_DrawFixedPatch((x*FRACUNIT), ((y-12)*FRACUNIT) + sine, fl.scale, addflags, patch, colormap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void M_DrawCharSelectSprite(UINT8 num, INT16 x, INT16 y)
|
||||
static void M_DrawCharSelectSprite(UINT8 num, INT16 x, INT16 y, boolean charflip)
|
||||
{
|
||||
setup_player_t *p = &setup_player[num];
|
||||
UINT8 cnum = p->clonenum;
|
||||
UINT8 color;
|
||||
UINT8 *colormap;
|
||||
|
||||
// for p1 alone don't try to preview things on pages that don't exist lol.
|
||||
if (p->mdepth == CSSTEP_CHARS && setup_numplayers == 1)
|
||||
cnum = setup_page;
|
||||
if (p->skin < 0)
|
||||
return;
|
||||
|
||||
INT16 skin = setup_chargrid[p->gridx][p->gridy].skinlist[cnum];
|
||||
UINT8 color = p->color;
|
||||
UINT8 *colormap = R_GetTranslationColormap(skin, color, GTC_MENUCACHE);
|
||||
INT32 flags = 0;
|
||||
if (p->mdepth < CSSTEP_COLORS)
|
||||
color = skins[p->skin].prefcolor;
|
||||
else
|
||||
color = p->color;
|
||||
colormap = R_GetTranslationColormap(p->skin, color, GTC_MENUCACHE);
|
||||
|
||||
// Flip for left-side players
|
||||
if (!(num & 1))
|
||||
flags ^= V_FLIP;
|
||||
|
||||
if (skin >= 0)
|
||||
M_DrawCharacterSprite(x, y, skin, flags, colormap);
|
||||
M_DrawCharacterSprite(x, y, p->skin, charflip, (p->mdepth == CSSTEP_READY), 0, colormap);
|
||||
}
|
||||
|
||||
static void M_DrawCharSelectPreview(UINT8 num)
|
||||
|
|
@ -1289,6 +1355,7 @@ static void M_DrawCharSelectPreview(UINT8 num)
|
|||
INT16 x = 11, y = 5;
|
||||
char letter = 'A' + num;
|
||||
setup_player_t *p = &setup_player[num];
|
||||
boolean charflip = !!(num & 1);
|
||||
|
||||
if (num & 1)
|
||||
x += 233;
|
||||
|
|
@ -1300,28 +1367,10 @@ static void M_DrawCharSelectPreview(UINT8 num)
|
|||
|
||||
if (p->mdepth >= CSSTEP_CHARS)
|
||||
{
|
||||
M_DrawCharSelectSprite(num, x+32, y+75);
|
||||
|
||||
if (p->mdepth >= CSSTEP_FOLLOWER)
|
||||
{
|
||||
M_DrawFollowerSprite(x+16, y+75, -1, !(num & 1) ? V_FLIP : 0, 0, p);
|
||||
}
|
||||
|
||||
M_DrawCharSelectSprite(num, x+32, y+75, charflip);
|
||||
M_DrawCharSelectCircle(p, x+32, y+64);
|
||||
}
|
||||
|
||||
if ((setup_animcounter/10) & 1 && gamestate == GS_MENU) // Not drawn outside of GS_MENU.
|
||||
{
|
||||
if (p->mdepth == CSSTEP_NONE && num == setup_numplayers)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PSTART", PU_CACHE));
|
||||
}
|
||||
else if (p->mdepth >= CSSTEP_READY)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PREADY", PU_CACHE));
|
||||
}
|
||||
}
|
||||
|
||||
V_DrawScaledPatch(x+9, y+2, 0, W_CachePatchName("FILEBACK", PU_CACHE));
|
||||
V_DrawScaledPatch(x, y+2, 0, W_CachePatchName(va("CHARSEL%c", letter), PU_CACHE));
|
||||
if (p->mdepth > CSSTEP_PROFILE)
|
||||
|
|
@ -1334,6 +1383,23 @@ static void M_DrawCharSelectPreview(UINT8 num)
|
|||
V_DrawFileString(x+16, y+2, 0, "PLAYER");
|
||||
}
|
||||
|
||||
if (p->mdepth >= CSSTEP_FOLLOWER)
|
||||
{
|
||||
M_DrawFollowerSprite(x+32+((charflip ? 1 : -1)*16), y+75, -1, charflip, 0, 0, p);
|
||||
}
|
||||
|
||||
if ((setup_animcounter/10) & 1 && gamestate == GS_MENU) // Not drawn outside of GS_MENU.
|
||||
{
|
||||
if (p->mdepth == CSSTEP_NONE && num == setup_numplayers)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PSTART", PU_CACHE));
|
||||
}
|
||||
else if (p->mdepth >= CSSTEP_READY)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PREADY", PU_CACHE));
|
||||
}
|
||||
}
|
||||
|
||||
// Profile selection
|
||||
if (p->mdepth == CSSTEP_PROFILE)
|
||||
{
|
||||
|
|
@ -1549,39 +1615,38 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
|
|||
// check what setup_player is doing in priority.
|
||||
if (sp->mdepth >= CSSTEP_CHARS)
|
||||
{
|
||||
|
||||
skinnum = setup_chargrid[sp->gridx][sp->gridy].skinlist[sp->clonenum];
|
||||
|
||||
if (skinnum >= 0)
|
||||
{
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, V_FLIP, colormap))
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, false, false, 0, colormap))
|
||||
V_DrawMappedPatch(x+14, y+66, 0, faceprefix[skinnum][FACE_RANK], colormap);
|
||||
|
||||
if (sp->mdepth >= CSSTEP_FOLLOWER)
|
||||
{
|
||||
if (M_DrawFollowerSprite(x-44 +12, y+119, 0, V_FLIP, 0, sp))
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(sp->followercolor, sp->color);;
|
||||
patch_t *ico = W_CachePatchName(followers[sp->followern].icon, PU_CACHE);
|
||||
UINT8 *fcolormap;
|
||||
|
||||
fcolormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
V_DrawMappedPatch(x+14+18, y+66, 0, ico, fcolormap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
M_DrawCharSelectCircle(sp, x-22, y+104);
|
||||
|
||||
if (sp->mdepth >= CSSTEP_FOLLOWER)
|
||||
{
|
||||
if (M_DrawFollowerSprite(x-22 - 16, y+119, 0, false, 0, 0, sp))
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(sp->followercolor, sp->color);;
|
||||
patch_t *ico = W_CachePatchName(followers[sp->followern].icon, PU_CACHE);
|
||||
UINT8 *fcolormap;
|
||||
|
||||
fcolormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
V_DrawMappedPatch(x+14+18, y+66, 0, ico, fcolormap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (skinnum > -1) // otherwise, read from profile.
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(p->followercolor, p->color);;
|
||||
UINT8 fln = K_FollowerAvailable(p->follower);
|
||||
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, V_FLIP, colormap))
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, false, false, 0, colormap))
|
||||
V_DrawMappedPatch(x+14, y+66, 0, faceprefix[skinnum][FACE_RANK], colormap);
|
||||
|
||||
if (M_DrawFollowerSprite(x-44 +12, y+119, fln, V_FLIP, col, NULL))
|
||||
if (M_DrawFollowerSprite(x-22 - 16, y+119, fln, false, 0, col, NULL))
|
||||
{
|
||||
patch_t *ico = W_CachePatchName(followers[fln].icon, PU_CACHE);
|
||||
UINT8 *fcolormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
|
|
@ -3594,19 +3659,29 @@ void M_DrawPause(void)
|
|||
{
|
||||
case IT_STRING:
|
||||
{
|
||||
|
||||
char iconame[9]; // 8 chars + \0
|
||||
patch_t *pp;
|
||||
|
||||
if (i == itemOn)
|
||||
{
|
||||
strcpy(iconame, currentMenu->menuitems[i].tooltip);
|
||||
iconame[7] = '2'; // Yes this is a stupid hack. Replace the last character with a 2 when we're selecting this graphic.
|
||||
if (i == mpause_restartmap || i == mpause_tryagain)
|
||||
{
|
||||
pp = W_CachePatchName(
|
||||
va("M_ICOR2%c", ('A'+(pausemenu.ticker & 1))),
|
||||
PU_CACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
char iconame[9]; // 8 chars + \0
|
||||
strcpy(iconame, currentMenu->menuitems[i].tooltip);
|
||||
iconame[7] = '2'; // Yes this is a stupid hack. Replace the last character with a 2 when we're selecting this graphic.
|
||||
|
||||
pp = W_CachePatchName(iconame, PU_CACHE);
|
||||
pp = W_CachePatchName(iconame, PU_CACHE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pp = W_CachePatchName(currentMenu->menuitems[i].tooltip, PU_CACHE);
|
||||
}
|
||||
|
||||
// 294 - 261 = 33
|
||||
// We need to move 33 px in 50 tics which means we move 33/50 = 0.66 px every tic = 2/3 of the offset.
|
||||
|
|
@ -3898,6 +3973,18 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
|
|||
if (demoref->gametype == GT_RACE)
|
||||
{
|
||||
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "TIME");
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "SCORE");
|
||||
}
|
||||
|
||||
if (demoref->standings[0].timeorscore == (UINT32_MAX-1))
|
||||
{
|
||||
V_DrawThinString(x+32, y+39, V_SNAPTOTOP, "NO CONTEST");
|
||||
}
|
||||
else if (demoref->gametype == GT_RACE)
|
||||
{
|
||||
V_DrawRightAlignedString(x+84, y+40, V_SNAPTOTOP, va("%d'%02d\"%02d",
|
||||
G_TicsToMinutes(demoref->standings[0].timeorscore, true),
|
||||
G_TicsToSeconds(demoref->standings[0].timeorscore),
|
||||
|
|
@ -3906,7 +3993,6 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
|
|||
}
|
||||
else
|
||||
{
|
||||
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "SCORE");
|
||||
V_DrawString(x+32, y+40, V_SNAPTOTOP, va("%d", demoref->standings[0].timeorscore));
|
||||
}
|
||||
|
||||
|
|
@ -3915,7 +4001,7 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
|
|||
// Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this)
|
||||
// and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid.
|
||||
|
||||
if (demoref->standings[0].skin != 0xFF)
|
||||
if (demoref->standings[0].skin < numskins)
|
||||
{
|
||||
patch = faceprefix[demoref->standings[0].skin][FACE_WANTED];
|
||||
colormap = R_GetTranslationColormap(
|
||||
|
|
@ -4116,7 +4202,7 @@ void M_DrawReplayStartMenu(void)
|
|||
// Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this)
|
||||
// and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid.
|
||||
|
||||
if (demoref->standings[i].skin != 0xFF)
|
||||
if (demoref->standings[i].skin < numskins)
|
||||
{
|
||||
patch = faceprefix[demoref->standings[i].skin][FACE_RANK];
|
||||
colormap = R_GetTranslationColormap(
|
||||
|
|
|
|||
339
src/k_menufunc.c
339
src/k_menufunc.c
|
|
@ -357,7 +357,7 @@ static void M_EraseDataResponse(INT32 ch)
|
|||
|
||||
void M_EraseData(INT32 choice)
|
||||
{
|
||||
const char *eschoice, *esstr = M_GetText("Are you sure you want to erase\n%s?\n\n(Press A to confirm)\n");
|
||||
const char *eschoice, *esstr = M_GetText("Are you sure you want to erase\n%s?\n\nPress (A) to confirm or (B) to cancel\n");
|
||||
|
||||
optionsmenu.erasecontext = (UINT8)choice;
|
||||
|
||||
|
|
@ -1517,7 +1517,7 @@ static void M_HandleMenuInput(void)
|
|||
{
|
||||
if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && majormods)
|
||||
{
|
||||
M_StartMessage(M_GetText("This cannot be done with complex addons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING);
|
||||
M_StartMessage(M_GetText("This cannot be done with complex addons\nor in a cheated game.\n\nPress (B)\n"), NULL, MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1583,6 +1583,12 @@ void M_Ticker(void)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
if (!menuactive)
|
||||
{
|
||||
noFurtherInput = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (menutransition.tics != 0 || menutransition.dest != 0)
|
||||
{
|
||||
noFurtherInput = true;
|
||||
|
|
@ -2035,7 +2041,7 @@ void M_QuitSRB2(INT32 choice)
|
|||
// We pick index 0 which is language sensitive, or one at random,
|
||||
// between 1 and maximum number.
|
||||
(void)choice;
|
||||
M_StartMessage("Are you sure you want to quit playing?\n\n(Press A to exit)", FUNCPTRCAST(M_QuitResponse), MM_YESNO);
|
||||
M_StartMessage("Are you sure you want to quit playing?\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_QuitResponse), MM_YESNO);
|
||||
}
|
||||
|
||||
// =========
|
||||
|
|
@ -2063,6 +2069,12 @@ static void M_SetupProfileGridPos(setup_player_t *p)
|
|||
|
||||
// While we're here, read follower values.
|
||||
p->followern = K_FollowerAvailable(pr->follower);
|
||||
|
||||
if (p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories)
|
||||
p->followercategory = -1;
|
||||
else
|
||||
p->followercategory = followers[p->followern].category;
|
||||
|
||||
p->followercolor = pr->followercolor;
|
||||
|
||||
// Now position the grid for skin
|
||||
|
|
@ -2150,6 +2162,7 @@ void M_CharacterSelectInit(void)
|
|||
{
|
||||
// Default to no follower / match colour.
|
||||
setup_player[i].followern = -1;
|
||||
setup_player[i].followercategory = -1;
|
||||
setup_player[i].followercolor = FOLLOWERCOLOR_MATCH;
|
||||
|
||||
// Set default selected profile to the last used profile for each player:
|
||||
|
|
@ -2486,6 +2499,16 @@ static boolean M_HandleCSelectProfile(setup_player_t *p, UINT8 num)
|
|||
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
UINT8 yourprofile = min(cv_lastprofile[realnum].value, PR_GetNumProfiles());
|
||||
if (p->profilen == yourprofile)
|
||||
p->profilen = PROFILE_GUEST;
|
||||
else
|
||||
p->profilen = yourprofile;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
|
|
@ -2578,6 +2601,15 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
|
|||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
p->gridx /= 3;
|
||||
p->gridx = (3*p->gridx) + 1;
|
||||
p->gridy /= 3;
|
||||
p->gridy = (3*p->gridy) + 1;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
|
||||
// try to set the clone num to the page # if possible.
|
||||
p->clonenum = setup_page;
|
||||
|
|
@ -2692,6 +2724,14 @@ static void M_HandleCharRotate(setup_player_t *p, UINT8 num)
|
|||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
p->clonenum = 0;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
||||
|
|
@ -2716,8 +2756,7 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
|||
|
||||
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
|
||||
{
|
||||
p->mdepth = CSSTEP_FOLLOWER;
|
||||
M_GetFollowerState(p);
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
|
|
@ -2734,6 +2773,17 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
|||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
if (p->skin >= 0)
|
||||
{
|
||||
p->color = skins[p->skin].prefcolor;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void M_AnimateFollower(setup_player_t *p)
|
||||
|
|
@ -2764,16 +2814,103 @@ static void M_AnimateFollower(setup_player_t *p)
|
|||
p->follower_timer++;
|
||||
}
|
||||
|
||||
static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
||||
static void M_HandleFollowerCategoryRotate(setup_player_t *p, UINT8 num)
|
||||
{
|
||||
if (cv_splitdevice.value)
|
||||
num = 0;
|
||||
|
||||
if (menucmd[num].dpad_lr > 0)
|
||||
{
|
||||
p->followern++;
|
||||
if (p->followern >= numfollowers)
|
||||
p->followercategory++;
|
||||
if (p->followercategory >= numfollowercategories)
|
||||
p->followercategory = -1;
|
||||
|
||||
p->rotate = CSROTATETICS;
|
||||
p->delay = CSROTATETICS;
|
||||
S_StartSound(NULL, sfx_s3kc3s);
|
||||
}
|
||||
else if (menucmd[num].dpad_lr < 0)
|
||||
{
|
||||
p->followercategory--;
|
||||
if (p->followercategory < -1)
|
||||
p->followercategory = numfollowercategories-1;
|
||||
|
||||
p->rotate = -CSROTATETICS;
|
||||
p->delay = CSROTATETICS;
|
||||
S_StartSound(NULL, sfx_s3kc3s);
|
||||
}
|
||||
|
||||
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
|
||||
{
|
||||
if (p->followercategory < 0)
|
||||
{
|
||||
p->followern = -1;
|
||||
p->mdepth = CSSTEP_READY;
|
||||
p->delay = TICRATE;
|
||||
M_SetupReadyExplosions(p);
|
||||
S_StartSound(NULL, sfx_s3k4e);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->followern < 0 || followers[p->followern].category != p->followercategory)
|
||||
{
|
||||
p->followern = 0;
|
||||
while (p->followern < numfollowers && followers[p->followern].category != p->followercategory)
|
||||
p->followern++;
|
||||
}
|
||||
|
||||
if (p->followern >= numfollowers)
|
||||
{
|
||||
p->followern = -1;
|
||||
S_StartSound(NULL, sfx_s3kb2);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_GetFollowerState(p);
|
||||
p->mdepth = CSSTEP_FOLLOWER;
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
}
|
||||
}
|
||||
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
if (p->followercategory >= 0 || p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories)
|
||||
p->followercategory = -1;
|
||||
else
|
||||
p->followercategory = followers[p->followern].category;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
||||
{
|
||||
INT16 startfollowern = p->followern;
|
||||
|
||||
if (cv_splitdevice.value)
|
||||
num = 0;
|
||||
|
||||
if (menucmd[num].dpad_lr > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
p->followern++;
|
||||
if (p->followern >= numfollowers)
|
||||
p->followern = 0;
|
||||
if (p->followern == startfollowern)
|
||||
break;
|
||||
}
|
||||
while (followers[p->followern].category != p->followercategory);
|
||||
|
||||
M_GetFollowerState(p);
|
||||
|
||||
|
|
@ -2783,9 +2920,17 @@ static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
|||
}
|
||||
else if (menucmd[num].dpad_lr < 0)
|
||||
{
|
||||
p->followern--;
|
||||
if (p->followern < -1)
|
||||
p->followern = numfollowers-1;
|
||||
do
|
||||
{
|
||||
p->followern--;
|
||||
if (p->followern < 0)
|
||||
p->followern = numfollowers-1;
|
||||
if (p->followern == startfollowern)
|
||||
break;
|
||||
}
|
||||
while (followers[p->followern].category != p->followercategory);
|
||||
|
||||
M_GetFollowerState(p);
|
||||
|
||||
p->rotate = -CSROTATETICS;
|
||||
p->delay = CSROTATETICS;
|
||||
|
|
@ -2811,10 +2956,19 @@ static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
|||
}
|
||||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS;
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
p->followercategory = -1;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
|
||||
|
|
@ -2849,10 +3003,24 @@ static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
|
|||
}
|
||||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
M_GetFollowerState(p);
|
||||
p->mdepth = CSSTEP_FOLLOWER;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
if (p->followercolor == FOLLOWERCOLOR_MATCH)
|
||||
p->followercolor = FOLLOWERCOLOR_OPPOSITE;
|
||||
else if (p->followercolor == followers[p->followern].defaultcolor)
|
||||
p->followercolor = FOLLOWERCOLOR_MATCH;
|
||||
else
|
||||
p->followercolor = followers[p->followern].defaultcolor;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
|
||||
boolean M_CharacterSelectHandler(INT32 choice)
|
||||
|
|
@ -2901,6 +3069,9 @@ boolean M_CharacterSelectHandler(INT32 choice)
|
|||
case CSSTEP_COLORS: // Select color
|
||||
M_HandleColorRotate(p, i);
|
||||
break;
|
||||
case CSSTEP_FOLLOWERCATEGORY:
|
||||
M_HandleFollowerCategoryRotate(p, i);
|
||||
break;
|
||||
case CSSTEP_FOLLOWER:
|
||||
M_HandleFollowerRotate(p, i);
|
||||
break;
|
||||
|
|
@ -2956,33 +3127,27 @@ static void M_MPConfirmCharacterSelection(void)
|
|||
UINT8 i;
|
||||
INT16 col;
|
||||
|
||||
char commandnames[][MAXSTRINGLENGTH] = { "skin ", "skin2 ", "skin3 ", "skin4 "};
|
||||
// ^ laziness 100 (we append a space directly so that we don't have to do it later too!!!!)
|
||||
|
||||
for (i = 0; i < splitscreen +1; i++)
|
||||
{
|
||||
char cmd[MAXSTRINGLENGTH];
|
||||
|
||||
// colour
|
||||
// (convert the number that's saved to a string we can use)
|
||||
col = setup_player[i].color;
|
||||
CV_StealthSetValue(&cv_playercolor[i], col);
|
||||
|
||||
// follower
|
||||
CV_StealthSetValue(&cv_follower[i], setup_player[i].followern);
|
||||
|
||||
// follower color
|
||||
CV_StealthSetValue(&cv_followercolor[i], setup_player[i].followercolor);
|
||||
if (setup_player[i].followern < 0)
|
||||
CV_StealthSet(&cv_follower[i], "None");
|
||||
else
|
||||
CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name);
|
||||
|
||||
// finally, call the skin[x] console command.
|
||||
// This will call SendNameAndColor which will synch everything we sent here and apply the changes!
|
||||
|
||||
// This is a hack to make sure we call Skin[x]_OnChange afterwards
|
||||
CV_StealthSetValue(&cv_skin[i], -1);
|
||||
CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name);
|
||||
|
||||
strcpy(cmd, commandnames[i]);
|
||||
strcat(cmd, skins[setup_player[i].skin].name);
|
||||
COM_ImmedExecute(cmd);
|
||||
// ...actually, let's do this last - Skin_OnChange has some return-early occasions
|
||||
// follower color
|
||||
CV_SetValue(&cv_followercolor[i], setup_player[i].followercolor);
|
||||
|
||||
}
|
||||
M_ClearMenus(true);
|
||||
|
|
@ -3004,6 +3169,8 @@ void M_CharacterSelectTick(void)
|
|||
setup_player[i].rotate--;
|
||||
else if (setup_player[i].rotate < 0)
|
||||
setup_player[i].rotate++;
|
||||
else
|
||||
setup_player[i].hitlag = false;
|
||||
|
||||
if (i >= setup_numplayers)
|
||||
continue;
|
||||
|
|
@ -3034,7 +3201,7 @@ void M_CharacterSelectTick(void)
|
|||
optionsmenu.profile->color = setup_player[0].color;
|
||||
|
||||
// save follower
|
||||
strcpy(optionsmenu.profile->follower, followers[setup_player[0].followern].skinname);
|
||||
strcpy(optionsmenu.profile->follower, followers[setup_player[0].followern].name);
|
||||
optionsmenu.profile->followercolor = setup_player[0].followercolor;
|
||||
|
||||
// reset setup_player
|
||||
|
|
@ -3051,7 +3218,10 @@ void M_CharacterSelectTick(void)
|
|||
CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name);
|
||||
CV_StealthSetValue(&cv_playercolor[i], setup_player[i].color);
|
||||
|
||||
CV_StealthSetValue(&cv_follower[i], setup_player[i].followern);
|
||||
if (setup_player[i].followern < 0)
|
||||
CV_StealthSet(&cv_follower[i], "None");
|
||||
else
|
||||
CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name);
|
||||
CV_StealthSetValue(&cv_followercolor[i], setup_player[i].followercolor);
|
||||
}
|
||||
|
||||
|
|
@ -3269,7 +3439,15 @@ static void M_LevelListFromGametype(INT16 gt)
|
|||
while (cup)
|
||||
{
|
||||
if (cup->unlockrequired == -1 || unlockables[cup->unlockrequired].unlocked)
|
||||
{
|
||||
highestid = cup->id;
|
||||
if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == cup)
|
||||
{
|
||||
cupgrid.x = cup->id % CUPMENU_COLUMNS;
|
||||
cupgrid.y = (cup->id / CUPMENU_COLUMNS) % CUPMENU_ROWS;
|
||||
cupgrid.pageno = cup->id / (CUPMENU_COLUMNS * CUPMENU_ROWS);
|
||||
}
|
||||
}
|
||||
cup = cup->next;
|
||||
}
|
||||
|
||||
|
|
@ -4775,7 +4953,7 @@ void M_HandleProfileSelect(INT32 ch)
|
|||
#if 0
|
||||
if (optionsmenu.profilen == 0)
|
||||
{
|
||||
M_StartMessage(M_GetText("Are you sure you wish\nto use the Guest Profile?\nThis profile cannot be customised.\nIt is recommended to create\na new Profile instead.\n\n(Press A to confirm)"), FUNCPTRCAST(M_FirstPickProfile), MM_YESNO);
|
||||
M_StartMessage(M_GetText("Are you sure you wish\nto use the Guest Profile?\nThis profile cannot be customised.\nIt is recommended to create\na new Profile instead.\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_FirstPickProfile), MM_YESNO);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -4917,7 +5095,7 @@ void M_ConfirmProfile(INT32 choice)
|
|||
}
|
||||
else
|
||||
{
|
||||
M_StartMessage(M_GetText("Are you sure you wish to\nselect this profile?\n\n(Press A to confirm)"), FUNCPTRCAST(M_FirstPickProfile), MM_YESNO);
|
||||
M_StartMessage(M_GetText("Are you sure you wish to\nselect this profile?\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_FirstPickProfile), MM_YESNO);
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
}
|
||||
|
|
@ -5123,7 +5301,7 @@ void M_ProfileControlsConfirm(INT32 choice)
|
|||
{
|
||||
(void)choice;
|
||||
|
||||
//M_StartMessage(M_GetText("Exiting will save the control changes\nfor this Profile.\nIs this okay?\n\n(Press A to confirm)"), FUNCPTRCAST(M_ProfileControlSaveResponse), MM_YESNO);
|
||||
//M_StartMessage(M_GetText("Exiting will save the control changes\nfor this Profile.\nIs this okay?\n\nPress (A) to confirm or (B) to cancel"), FUNCPTRCAST(M_ProfileControlSaveResponse), MM_YESNO);
|
||||
// TODO: Add a graphic for controls saving, instead of obnoxious prompt.
|
||||
|
||||
M_ProfileControlSaveResponse(MA_YES);
|
||||
|
|
@ -5500,7 +5678,7 @@ void M_CheckProfileData(INT32 choice)
|
|||
if (np < 2)
|
||||
{
|
||||
S_StartSound(NULL, sfx_s3k7b);
|
||||
M_StartMessage("There are no custom profiles.\n\n(Press any button)", NULL, MM_NOTHING);
|
||||
M_StartMessage("There are no custom profiles.\n\nPress (B)", NULL, MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -5564,9 +5742,9 @@ void M_HandleProfileErase(INT32 choice)
|
|||
else if (M_MenuConfirmPressed(pid))
|
||||
{
|
||||
if (optionsmenu.eraseprofilen == cv_currprofile.value)
|
||||
M_StartMessage("Your ""\x85""current profile""\x80"" will be erased.\nAre you sure you want to proceed?\nDeleting this profile will also\nreturn you to the title screen.\n\n(Press A to confirm)", FUNCPTRCAST(M_EraseProfileResponse), MM_YESNO);
|
||||
M_StartMessage("Your ""\x85""current profile""\x80"" will be erased.\nAre you sure you want to proceed?\nDeleting this profile will also\nreturn you to the title screen.\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_EraseProfileResponse), MM_YESNO);
|
||||
else
|
||||
M_StartMessage("This profile will be erased.\nAre you sure you want to proceed?\n\n(Press A to confirm)", FUNCPTRCAST(M_EraseProfileResponse), MM_YESNO);
|
||||
M_StartMessage("This profile will be erased.\nAre you sure you want to proceed?\n\nPress (A) to confirm or (B) to cancel", FUNCPTRCAST(M_EraseProfileResponse), MM_YESNO);
|
||||
|
||||
M_SetMenuDelay(pid);
|
||||
}
|
||||
|
|
@ -5700,6 +5878,8 @@ struct pausemenu_s pausemenu;
|
|||
// Pause menu!
|
||||
void M_OpenPauseMenu(void)
|
||||
{
|
||||
INT32 i = 0;
|
||||
|
||||
currentMenu = &PAUSE_MainDef;
|
||||
|
||||
// Ready the variables
|
||||
|
|
@ -5716,6 +5896,8 @@ void M_OpenPauseMenu(void)
|
|||
|
||||
PAUSE_Main[mpause_addons].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_switchmap].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_restartmap].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_tryagain].status = IT_DISABLED;
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
PAUSE_Main[mpause_discordrequests].status = IT_DISABLED;
|
||||
#endif
|
||||
|
|
@ -5735,9 +5917,36 @@ void M_OpenPauseMenu(void)
|
|||
if (server || IsPlayerAdmin(consoleplayer))
|
||||
{
|
||||
PAUSE_Main[mpause_switchmap].status = IT_STRING | IT_SUBMENU;
|
||||
for (i = 0; i < PAUSE_GamemodesDef.numitems; i++)
|
||||
{
|
||||
if (PAUSE_GamemodesMenu[i].mvar2 != gametype)
|
||||
continue;
|
||||
PAUSE_GamemodesDef.lastOn = i;
|
||||
break;
|
||||
}
|
||||
PAUSE_Main[mpause_restartmap].status = IT_STRING | IT_CALL;
|
||||
PAUSE_Main[mpause_addons].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
}
|
||||
else if (!netgame && !demo.playback)
|
||||
{
|
||||
boolean retryallowed = (modeattacking != ATTACKING_NONE);
|
||||
if (G_GametypeUsesLives())
|
||||
{
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (players[g_localplayers[i]].lives <= 1)
|
||||
continue;
|
||||
retryallowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retryallowed)
|
||||
{
|
||||
PAUSE_Main[mpause_tryagain].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (G_GametypeHasSpectators())
|
||||
{
|
||||
|
|
@ -5766,6 +5975,7 @@ void M_QuitPauseMenu(INT32 choice)
|
|||
void M_PauseTick(void)
|
||||
{
|
||||
pausemenu.offset /= 2;
|
||||
pausemenu.ticker++;
|
||||
|
||||
if (pausemenu.closing)
|
||||
{
|
||||
|
|
@ -5814,6 +6024,37 @@ boolean M_PauseInputs(INT32 ch)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Restart map
|
||||
void M_RestartMap(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
M_ClearMenus(false);
|
||||
COM_ImmedExecute("restartlevel");
|
||||
}
|
||||
|
||||
// Try again
|
||||
void M_TryAgain(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
if (demo.playback)
|
||||
return;
|
||||
|
||||
if (netgame || !Playing()) // Should never happen!
|
||||
return;
|
||||
|
||||
M_ClearMenus(false);
|
||||
|
||||
if (modeattacking != ATTACKING_NONE)
|
||||
{
|
||||
G_CheckDemoStatus(); // Cancel recording
|
||||
M_StartTimeAttack(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
G_SetRetryFlag();
|
||||
}
|
||||
}
|
||||
|
||||
// Pause spectate / join functions
|
||||
void M_ConfirmSpectate(INT32 choice)
|
||||
{
|
||||
|
|
@ -5828,7 +6069,7 @@ void M_ConfirmEnterGame(INT32 choice)
|
|||
(void)choice;
|
||||
if (!cv_allowteamchange.value)
|
||||
{
|
||||
M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\nPress a key.\n"), NULL, MM_NOTHING);
|
||||
M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\n\nPress (B)\n"), NULL, MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
M_QuitPauseMenu(-1);
|
||||
|
|
@ -5860,7 +6101,7 @@ void M_EndGame(INT32 choice)
|
|||
if (!Playing())
|
||||
return;
|
||||
|
||||
M_StartMessage(M_GetText("Are you sure you want to return\nto the title screen?\n(Press A to confirm)\n"), FUNCPTRCAST(M_ExitGameResponse), MM_YESNO);
|
||||
M_StartMessage(M_GetText("Are you sure you want to return\nto the title screen?\nPress (A) to confirm or (B) to cancel\n"), FUNCPTRCAST(M_ExitGameResponse), MM_YESNO);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -6042,7 +6283,7 @@ void M_ReplayHut(INT32 choice)
|
|||
}
|
||||
if (!preparefilemenu(false, true))
|
||||
{
|
||||
M_StartMessage("No replays found.\n\n(Press a key)\n", NULL, MM_NOTHING);
|
||||
M_StartMessage("No replays found.\n\nPress (B)\n", NULL, MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
else if (!demo.inreplayhut)
|
||||
|
|
@ -6118,7 +6359,7 @@ void M_HandleReplayHutList(INT32 choice)
|
|||
if (!preparefilemenu(false, true))
|
||||
{
|
||||
S_StartSound(NULL, sfx_s224);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
menupath[menupathindex[++menudepthleft]] = 0;
|
||||
|
||||
if (!preparefilemenu(true, true))
|
||||
|
|
@ -6137,7 +6378,7 @@ void M_HandleReplayHutList(INT32 choice)
|
|||
else
|
||||
{
|
||||
S_StartSound(NULL, sfx_s26d);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -6264,7 +6505,7 @@ void M_Addons(INT32 choice)
|
|||
|
||||
if (!preparefilemenu(false, false))
|
||||
{
|
||||
M_StartMessage(va("No files/folders found.\n\n%s\n\n(Press a key)\n", LOCATIONSTRING1),NULL,MM_NOTHING);
|
||||
M_StartMessage(va("No files/folders found.\n\n%s\n\nPress (B)\n", LOCATIONSTRING1),NULL,MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
|
@ -6297,7 +6538,7 @@ char *M_AddonsHeaderPath(void)
|
|||
|
||||
#define UNEXIST S_StartSound(NULL, sfx_s26d);\
|
||||
M_SetupNextMenu(MISC_AddonsDef.prevMenu, false);\
|
||||
M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING)
|
||||
M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\nPress (B)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING)
|
||||
|
||||
#define CLEARNAME Z_Free(refreshdirname);\
|
||||
refreshdirname = NULL
|
||||
|
|
@ -6341,19 +6582,19 @@ void M_AddonsRefresh(void)
|
|||
{
|
||||
S_StartSound(NULL, sfx_s26d);
|
||||
if (refreshdirmenu & REFRESHDIR_MAX)
|
||||
message = va("%c%s\x80\nMaximum number of addons reached.\nA file could not be loaded.\nIf you wish to play with this addon, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
message = va("%c%s\x80\nMaximum number of addons reached.\nA file could not be loaded.\nIf you wish to play with this addon, restart the game to clear existing ones.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
else
|
||||
message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more info.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more info.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
}
|
||||
else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
|
||||
{
|
||||
S_StartSound(NULL, sfx_s224);
|
||||
message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more info.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings"));
|
||||
message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more info.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings"));
|
||||
}
|
||||
else if (majormods && !prevmajormods)
|
||||
{
|
||||
S_StartSound(NULL, sfx_s221);
|
||||
message = va("%c%s\x80\nYou've loaded a gameplay-modifying addon.\n\nRecord Attack has been disabled, but you\ncan still play alone in local Multiplayer.\n\nIf you wish to play Record Attack mode, restart the game to disable loaded addons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
message = va("%c%s\x80\nYou've loaded a gameplay-modifying addon.\n\nRecord Attack has been disabled, but you\ncan still play alone in local Multiplayer.\n\nIf you wish to play Record Attack mode, restart the game to disable loaded addons.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
|
||||
prevmajormods = majormods;
|
||||
}
|
||||
|
||||
|
|
@ -6472,7 +6713,7 @@ void M_HandleAddons(INT32 choice)
|
|||
if (!preparefilemenu(false, false))
|
||||
{
|
||||
S_StartSound(NULL, sfx_s224);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
menupath[menupathindex[++menudepthleft]] = 0;
|
||||
|
||||
if (!preparefilemenu(true, false))
|
||||
|
|
@ -6491,7 +6732,7 @@ void M_HandleAddons(INT32 choice)
|
|||
else
|
||||
{
|
||||
S_StartSound(NULL, sfx_s26d);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\nPress (B)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||
menupath[menupathindex[menudepthleft]] = 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -6507,11 +6748,11 @@ void M_HandleAddons(INT32 choice)
|
|||
break;
|
||||
|
||||
case EXT_TXT:
|
||||
M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press A to confirm)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),FUNCPTRCAST(M_AddonExec),MM_YESNO);
|
||||
M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\nPress (A) to confirm or (B) to cancel\n\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),FUNCPTRCAST(M_AddonExec),MM_YESNO);
|
||||
break;
|
||||
|
||||
case EXT_CFG:
|
||||
M_StartMessage(va("%c%s\x80\nThis file may modify your settings.\nAttempt to run anyways? \n\n(Press A to confirm)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),FUNCPTRCAST(M_AddonExec),MM_YESNO);
|
||||
M_StartMessage(va("%c%s\x80\nThis file may modify your settings.\nAttempt to run anyways? \n\nPress (A) to confirm or (B) to cancel\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),FUNCPTRCAST(M_AddonExec),MM_YESNO);
|
||||
break;
|
||||
|
||||
case EXT_LUA:
|
||||
|
|
|
|||
|
|
@ -402,10 +402,7 @@ static int lib_pRandomByte(lua_State *L)
|
|||
static int lib_pRandomKey(lua_State *L)
|
||||
{
|
||||
INT32 a = (INT32)luaL_checkinteger(L, 1);
|
||||
|
||||
NOHUD
|
||||
if (a > 65536)
|
||||
LUA_UsageWarning(L, "P_RandomKey: range > 65536 is undefined behavior");
|
||||
lua_pushinteger(L, P_RandomKey(PR_UNDEFINED, a));
|
||||
demo_writerng = 2;
|
||||
return 1;
|
||||
|
|
@ -415,15 +412,13 @@ static int lib_pRandomRange(lua_State *L)
|
|||
{
|
||||
INT32 a = (INT32)luaL_checkinteger(L, 1);
|
||||
INT32 b = (INT32)luaL_checkinteger(L, 2);
|
||||
|
||||
NOHUD
|
||||
if (b < a) {
|
||||
if (b < a)
|
||||
{
|
||||
INT32 c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
if ((b-a+1) > 65536)
|
||||
LUA_UsageWarning(L, "P_RandomRange: range > 65536 is undefined behavior");
|
||||
lua_pushinteger(L, P_RandomRange(PR_UNDEFINED, a, b));
|
||||
demo_writerng = 2;
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -762,6 +762,13 @@ void Command_Setlives_f(void)
|
|||
D_Cheat(consoleplayer, CHEAT_LIVES, atoi(COM_Argv(1)));
|
||||
}
|
||||
|
||||
void Command_Grayscale_f(void)
|
||||
{
|
||||
REQUIRE_CHEATS;
|
||||
|
||||
COM_ImmedExecute("toggle palette \"\" GRAYPAL");
|
||||
}
|
||||
|
||||
//
|
||||
// OBJECTPLACE (and related variables)
|
||||
//
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ void Command_Teleport_f(void);
|
|||
void Command_RTeleport_f(void);
|
||||
void Command_Skynum_f(void);
|
||||
void Command_Weather_f(void);
|
||||
void Command_Grayscale_f(void);
|
||||
#ifdef _DEBUG
|
||||
void Command_CauseCfail_f(void);
|
||||
#endif
|
||||
|
|
|
|||
126
src/m_random.c
126
src/m_random.c
|
|
@ -25,20 +25,56 @@
|
|||
// RNG functions (not synched)
|
||||
// ---------------------------
|
||||
|
||||
ATTRINLINE static UINT32 FUNCINLINE __external_prng__(void)
|
||||
{
|
||||
UINT32 rnd = rand();
|
||||
|
||||
#if RAND_MAX < 65535
|
||||
// Compensate for especially bad randomness.
|
||||
UINT32 rndv = (rand() & 1) << 15;
|
||||
rnd ^= rndv;
|
||||
#endif
|
||||
|
||||
// Shuffle like we do for our own PRNG, since RAND_MAX
|
||||
// tends to be [0, INT32_MAX] instead of [0, UINT32_MAX].
|
||||
rnd ^= rnd >> 13;
|
||||
rnd ^= rnd >> 11;
|
||||
rnd ^= rnd << 21;
|
||||
return (rnd * 36548569);
|
||||
}
|
||||
|
||||
ATTRINLINE static UINT32 FUNCINLINE __external_prng_bound__(UINT32 bound)
|
||||
{
|
||||
// Do rejection sampling to remove the modulo bias.
|
||||
UINT32 threshold = -bound % bound;
|
||||
for (;;)
|
||||
{
|
||||
UINT32 r = __external_prng__();
|
||||
if (r >= threshold)
|
||||
{
|
||||
return r % bound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides a random 32-bit number. Distribution is uniform.
|
||||
* As with all M_Random functions, not synched in netgames.
|
||||
*
|
||||
* \return A random 32-bit number.
|
||||
*/
|
||||
UINT32 M_Random(void)
|
||||
{
|
||||
return __external_prng__();
|
||||
}
|
||||
|
||||
/** Provides a random fixed point number. Distribution is uniform.
|
||||
* As with all M_Random functions, not synched in netgames.
|
||||
*
|
||||
* \return A random fixed point number from [0,1).
|
||||
* \return A random fixed point number from [0,1].
|
||||
*/
|
||||
fixed_t M_RandomFixed(void)
|
||||
{
|
||||
#if RAND_MAX < 65535
|
||||
// Compensate for insufficient randomness.
|
||||
fixed_t rndv = (rand()&1)<<15;
|
||||
return rand()^rndv;
|
||||
#else
|
||||
return (rand() & 0xFFFF);
|
||||
#endif
|
||||
return (fixed_t)(__external_prng_bound__(FRACUNIT));
|
||||
}
|
||||
|
||||
/** Provides a random byte. Distribution is uniform.
|
||||
|
|
@ -48,7 +84,7 @@ fixed_t M_RandomFixed(void)
|
|||
*/
|
||||
UINT8 M_RandomByte(void)
|
||||
{
|
||||
return (rand() & 0xFF);
|
||||
return (UINT8)(__external_prng_bound__(UINT8_MAX));
|
||||
}
|
||||
|
||||
/** Provides a random integer for picking random elements from an array.
|
||||
|
|
@ -58,9 +94,9 @@ UINT8 M_RandomByte(void)
|
|||
* \param a Number of items in array.
|
||||
* \return A random integer from [0,a).
|
||||
*/
|
||||
INT32 M_RandomKey(INT32 a)
|
||||
UINT32 M_RandomKey(UINT32 a)
|
||||
{
|
||||
return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*a);
|
||||
return __external_prng_bound__(a);
|
||||
}
|
||||
|
||||
/** Provides a random integer in a given range.
|
||||
|
|
@ -73,7 +109,7 @@ INT32 M_RandomKey(INT32 a)
|
|||
*/
|
||||
INT32 M_RandomRange(INT32 a, INT32 b)
|
||||
{
|
||||
return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*(b-a+1))+a;
|
||||
return (INT32)(__external_prng_bound__((b - a) + 1)) + a;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -92,23 +128,56 @@ typedef struct
|
|||
|
||||
static rng_t rng; // The entire PRNG state
|
||||
|
||||
/** Provides a random fixed point number.
|
||||
/** Provides a random 32 bit integer.
|
||||
* This is a variant of an xorshift PRNG; state fits in a 32 bit integer structure.
|
||||
*
|
||||
* \return A random fixed point number from [0,1).
|
||||
* \return A random, uniformly distributed number from [0,UINT32_MAX].
|
||||
*/
|
||||
ATTRINLINE static fixed_t FUNCINLINE __internal_prng__(pr_class_t pr_class)
|
||||
ATTRINLINE static UINT32 FUNCINLINE __internal_prng__(pr_class_t pr_class)
|
||||
{
|
||||
rng.seed[pr_class] ^= rng.seed[pr_class] >> 13;
|
||||
rng.seed[pr_class] ^= rng.seed[pr_class] >> 11;
|
||||
rng.seed[pr_class] ^= rng.seed[pr_class] << 21;
|
||||
return ( (rng.seed[pr_class] * 36548569) >> 4) & (FRACUNIT-1);
|
||||
return (rng.seed[pr_class] * 36548569);
|
||||
}
|
||||
|
||||
/** Provides a random number within a specified range.
|
||||
*
|
||||
* \return A random, uniformly distributed number from [0,bound].
|
||||
*/
|
||||
ATTRINLINE static UINT32 FUNCINLINE __internal_prng_bound__(pr_class_t pr_class, UINT32 bound)
|
||||
{
|
||||
// Do rejection sampling to remove the modulo bias.
|
||||
UINT32 threshold = -bound % bound;
|
||||
for (;;)
|
||||
{
|
||||
UINT32 r = __internal_prng__(pr_class);
|
||||
if (r >= threshold)
|
||||
{
|
||||
return r % bound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides a random fixed point number. Distribution is uniform.
|
||||
* Literally a wrapper for the internal PRNG function.
|
||||
*
|
||||
* \return A random fixed point number from [0,1).
|
||||
* \return A random fixed point number from [0,UINT32_MAX].
|
||||
*/
|
||||
#ifndef DEBUGRANDOM
|
||||
UINT32 P_Random(pr_class_t pr_class)
|
||||
{
|
||||
#else
|
||||
UINT32 P_RandomD(const char *rfile, INT32 rline, pr_class_t pr_class)
|
||||
{
|
||||
CONS_Printf("P_Random(%u) at: %sp %d\n", pr_class, rfile, rline);
|
||||
#endif
|
||||
return __internal_prng__(pr_class);
|
||||
}
|
||||
|
||||
/** Provides a random fixed point number. Distribution is uniform.
|
||||
*
|
||||
* \return A random fixed point number from [0,1].
|
||||
*/
|
||||
#ifndef DEBUGRANDOM
|
||||
fixed_t P_RandomFixed(pr_class_t pr_class)
|
||||
|
|
@ -118,14 +187,14 @@ fixed_t P_RandomFixedD(const char *rfile, INT32 rline, pr_class_t pr_class)
|
|||
{
|
||||
CONS_Printf("P_RandomFixed(%u) at: %sp %d\n", pr_class, rfile, rline);
|
||||
#endif
|
||||
return __internal_prng__(pr_class);
|
||||
return (fixed_t)(__internal_prng_bound__(pr_class, FRACUNIT));
|
||||
}
|
||||
|
||||
/** Provides a random byte. Distribution is uniform.
|
||||
* If you're curious, (&0xFF00) >> 8 gives the same result
|
||||
* as a fixed point multiplication by 256.
|
||||
*
|
||||
* \return Random integer from [0, 255].
|
||||
* \return Random integer from [0,255].
|
||||
* \sa __internal_prng__
|
||||
*/
|
||||
#ifndef DEBUGRANDOM
|
||||
|
|
@ -136,7 +205,7 @@ UINT8 P_RandomByteD(const char *rfile, INT32 rline, pr_class_t pr_class)
|
|||
{
|
||||
CONS_Printf("P_RandomByte(%u) at: %sp %d\n", pr_class, rfile, rline);
|
||||
#endif
|
||||
return (UINT8)((__internal_prng__(pr_class) & 0xFF00) >> 8);
|
||||
return (UINT8)(__internal_prng_bound__(pr_class, UINT8_MAX));
|
||||
}
|
||||
|
||||
/** Provides a random integer for picking random elements from an array.
|
||||
|
|
@ -144,23 +213,22 @@ UINT8 P_RandomByteD(const char *rfile, INT32 rline, pr_class_t pr_class)
|
|||
* NOTE: Maximum range is 65536.
|
||||
*
|
||||
* \param a Number of items in array.
|
||||
* \return A random integer from [0,a).
|
||||
* \return A random integer from [0,a].
|
||||
* \sa __internal_prng__
|
||||
*/
|
||||
#ifndef DEBUGRANDOM
|
||||
INT32 P_RandomKey(pr_class_t pr_class, INT32 a)
|
||||
UINT32 P_RandomKey(pr_class_t pr_class, UINT32 a)
|
||||
{
|
||||
#else
|
||||
INT32 P_RandomKeyD(const char *rfile, INT32 rline, pr_class_t pr_class, INT32 a)
|
||||
UINT32 P_RandomKeyD(const char *rfile, INT32 rline, pr_class_t pr_class, UINT32 a)
|
||||
{
|
||||
CONS_Printf("P_RandomKey(%u) at: %sp %d\n", pr_class, rfile, rline);
|
||||
#endif
|
||||
return (INT32)(((INT64)__internal_prng__(pr_class) * a) >> FRACBITS);
|
||||
return __internal_prng_bound__(pr_class, a);
|
||||
}
|
||||
|
||||
/** Provides a random integer in a given range.
|
||||
* Distribution is uniform.
|
||||
* NOTE: Maximum range is 65536.
|
||||
*
|
||||
* \param a Lower bound.
|
||||
* \param b Upper bound.
|
||||
|
|
@ -175,7 +243,7 @@ INT32 P_RandomRangeD(const char *rfile, INT32 rline, pr_class_t pr_class, INT32
|
|||
{
|
||||
CONS_Printf("P_RandomRange(%u) at: %sp %d\n", pr_class, rfile, rline);
|
||||
#endif
|
||||
return (INT32)(((INT64)__internal_prng__(pr_class) * (b - a + 1)) >> FRACBITS) + a;
|
||||
return (INT32)(__internal_prng_bound__(pr_class, (b - a) + 1)) + a;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -187,13 +255,13 @@ INT32 P_RandomRangeD(const char *rfile, INT32 rline, pr_class_t pr_class, INT32
|
|||
/** Peeks to see what the next result from the PRNG will be.
|
||||
* Used for debugging.
|
||||
*
|
||||
* \return A 'random' fixed point number from [0,1).
|
||||
* \return A 'random' number from [0,UINT32_MAX]
|
||||
* \sa __internal_prng__
|
||||
*/
|
||||
fixed_t P_RandomPeek(pr_class_t pr_class)
|
||||
UINT32 P_RandomPeek(pr_class_t pr_class)
|
||||
{
|
||||
UINT32 r = rng.seed[pr_class];
|
||||
fixed_t ret = __internal_prng__(pr_class);
|
||||
UINT32 ret = __internal_prng__(pr_class);
|
||||
rng.seed[pr_class] = r;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,37 +70,41 @@ typedef enum
|
|||
// P_Random functions pulls random bytes from a PRNG that is network synced.
|
||||
|
||||
// RNG functions
|
||||
UINT32 M_Random(void);
|
||||
fixed_t M_RandomFixed(void);
|
||||
UINT8 M_RandomByte(void);
|
||||
INT32 M_RandomKey(INT32 a);
|
||||
UINT32 M_RandomKey(UINT32 a);
|
||||
INT32 M_RandomRange(INT32 a, INT32 b);
|
||||
|
||||
// PRNG functions
|
||||
#ifdef DEBUGRANDOM
|
||||
#define P_Random(c) P_RandomD(__FILE__, __LINE__, c)
|
||||
#define P_RandomFixed(c) P_RandomFixedD(__FILE__, __LINE__, c)
|
||||
#define P_RandomByte(c) P_RandomByteD(__FILE__, __LINE__, c)
|
||||
#define P_RandomKey(c, d) P_RandomKeyD(__FILE__, __LINE__, c, d)
|
||||
#define P_RandomRange(c, d, e) P_RandomRangeD(__FILE__, __LINE__, c, d, e)
|
||||
UINT32 P_RandomD(const char *rfile, INT32 rline, pr_class_t pr_class);
|
||||
fixed_t P_RandomFixedD(const char *rfile, INT32 rline, pr_class_t pr_class);
|
||||
UINT8 P_RandomByteD(const char *rfile, INT32 rline, pr_class_t pr_class);
|
||||
INT32 P_RandomKeyD(const char *rfile, INT32 rline, pr_class_t pr_class, INT32 a);
|
||||
UINT32 P_RandomKeyD(const char *rfile, INT32 rline, pr_class_t pr_class, UINT32 a);
|
||||
INT32 P_RandomRangeD(const char *rfile, INT32 rline, pr_class_t pr_class, INT32 a, INT32 b);
|
||||
#else
|
||||
UINT32 P_Random(pr_class_t pr_class);
|
||||
fixed_t P_RandomFixed(pr_class_t pr_class);
|
||||
UINT8 P_RandomByte(pr_class_t pr_class);
|
||||
INT32 P_RandomKey(pr_class_t pr_class, INT32 a);
|
||||
UINT32 P_RandomKey(pr_class_t pr_class, UINT32 a);
|
||||
INT32 P_RandomRange(pr_class_t pr_class, INT32 a, INT32 b);
|
||||
#endif
|
||||
|
||||
// Macros for other functions
|
||||
#define M_SignedRandom() ((INT32)M_RandomByte() - 128) // [-128, 127] signed byte, originally a
|
||||
#define P_SignedRandom(pr) ((INT32)P_RandomByte(pr) - 128) // function of its own, moved to a macro
|
||||
#define M_SignedRandom() ((INT32)M_RandomByte() + INT8_MIN) // [-128, 127] signed byte, originally a
|
||||
#define P_SignedRandom(pr) ((INT32)P_RandomByte(pr) + INT8_MIN) // function of its own, moved to a macro
|
||||
|
||||
#define M_RandomChance(p) (M_RandomFixed() < p) // given fixed point probability, p, between 0 (0%)
|
||||
#define P_RandomChance(pr, p) (P_RandomFixed(pr) < p) // and FRACUNIT (100%), returns true p% of the time
|
||||
|
||||
// Debugging
|
||||
fixed_t P_RandomPeek(pr_class_t pr_class);
|
||||
UINT32 P_RandomPeek(pr_class_t pr_class);
|
||||
|
||||
// Working with the seed for PRNG
|
||||
#ifdef DEBUGRANDOM
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(t2, 24*FRACUNIT, false);
|
||||
P_InstaThrust(t2, bounceangle, 16*FRACUNIT);
|
||||
|
||||
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
|
||||
|
|
@ -254,7 +254,7 @@ boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
S_StartSound(t1, t1->info->deathsound);
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(t1, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(t1, 24*FRACUNIT, false);
|
||||
P_InstaThrust(t1, bounceangle, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1585,6 +1585,32 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
target->fuse = 1;
|
||||
break;
|
||||
|
||||
case MT_BANANA:
|
||||
case MT_BANANA_SHIELD:
|
||||
{
|
||||
const UINT8 numParticles = 8;
|
||||
const angle_t diff = ANGLE_MAX / numParticles;
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < numParticles; i++)
|
||||
{
|
||||
mobj_t *spark = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_BANANA_SPARK);
|
||||
spark->angle = (diff * i) - (diff / 2);
|
||||
|
||||
if (inflictor != NULL && P_MobjWasRemoved(inflictor) == false)
|
||||
{
|
||||
spark->angle += K_MomentumAngle(inflictor);
|
||||
spark->momx += inflictor->momx / 2;
|
||||
spark->momy += inflictor->momy / 2;
|
||||
spark->momz += inflictor->momz / 2;
|
||||
}
|
||||
|
||||
P_SetObjectMomZ(spark, (12 + P_RandomRange(PR_DECORATION, -4, 4)) * FRACUNIT, true);
|
||||
P_Thrust(spark, spark->angle, (12 + P_RandomRange(PR_DECORATION, -4, 4)) * spark->scale);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1997,9 +2023,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
|
||||
// Check if the player is allowed to be damaged!
|
||||
// If not, then spawn the instashield effect instead.
|
||||
// NB: "allowcombo", "hardhit" and related checks are here to disallow HITLAG COMBOS, not loss-of-control combos
|
||||
// DMG_EXPLODE bypasses this check to prevent blocking eggbox/SPB with spinout flashtics
|
||||
if (!force && (type != DMG_EXPLODE))
|
||||
if (!force)
|
||||
{
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
|
|
@ -2039,7 +2063,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
allowcombo = false;
|
||||
}
|
||||
|
||||
if ((target->hitlag == 0 || allowcombo == false) && player->flashing > 0)
|
||||
// DMG_EXPLODE excluded from flashtic checks to prevent dodging eggbox/SPB with weak spinout
|
||||
if ((target->hitlag == 0 || allowcombo == false) && player->flashing > 0 && type != DMG_EXPLODE)
|
||||
{
|
||||
// Post-hit invincibility
|
||||
K_DoInstashield(player);
|
||||
|
|
@ -2257,6 +2282,9 @@ static void P_FlingBurst
|
|||
mo->fuse = objFuse;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
|
||||
// We want everything from P_SpawnMobjFromMobj except scale.
|
||||
objScale = FixedMul(objScale, FixedDiv(mapobjectscale, player->mo->scale));
|
||||
|
||||
if (objScale != FRACUNIT)
|
||||
{
|
||||
P_SetScale(mo, FixedMul(objScale, mo->scale));
|
||||
|
|
|
|||
|
|
@ -2618,7 +2618,7 @@ increment_move
|
|||
if (!(thing->flags & MF_NOCLIP))
|
||||
{
|
||||
//All things are affected by their scale.
|
||||
fixed_t maxstep = P_GetThingStepUp(thing, x, y);
|
||||
fixed_t maxstep = P_GetThingStepUp(thing, tryx, tryy);
|
||||
|
||||
if (tmceilingz - tmfloorz < thing->height)
|
||||
{
|
||||
|
|
|
|||
339
src/p_mobj.c
339
src/p_mobj.c
|
|
@ -1158,66 +1158,68 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
|
|||
gravityadd = -gravityadd;
|
||||
}
|
||||
}
|
||||
else //Otherwise, sort through the other exceptions.
|
||||
|
||||
// Sort through the other exceptions.
|
||||
switch (mo->type)
|
||||
{
|
||||
switch (mo->type)
|
||||
{
|
||||
case MT_FLINGRING:
|
||||
case MT_FLINGCOIN:
|
||||
case MT_FLINGBLUESPHERE:
|
||||
case MT_FLINGNIGHTSCHIP:
|
||||
case MT_BOUNCERING:
|
||||
case MT_RAILRING:
|
||||
case MT_INFINITYRING:
|
||||
case MT_AUTOMATICRING:
|
||||
case MT_EXPLOSIONRING:
|
||||
case MT_SCATTERRING:
|
||||
case MT_GRENADERING:
|
||||
case MT_BOUNCEPICKUP:
|
||||
case MT_RAILPICKUP:
|
||||
case MT_AUTOPICKUP:
|
||||
case MT_EXPLODEPICKUP:
|
||||
case MT_SCATTERPICKUP:
|
||||
case MT_GRENADEPICKUP:
|
||||
case MT_REDFLAG:
|
||||
case MT_BLUEFLAG:
|
||||
if (mo->target)
|
||||
case MT_FLINGRING:
|
||||
case MT_FLINGCOIN:
|
||||
case MT_FLINGBLUESPHERE:
|
||||
case MT_FLINGNIGHTSCHIP:
|
||||
case MT_BOUNCERING:
|
||||
case MT_RAILRING:
|
||||
case MT_INFINITYRING:
|
||||
case MT_AUTOMATICRING:
|
||||
case MT_EXPLOSIONRING:
|
||||
case MT_SCATTERRING:
|
||||
case MT_GRENADERING:
|
||||
case MT_BOUNCEPICKUP:
|
||||
case MT_RAILPICKUP:
|
||||
case MT_AUTOPICKUP:
|
||||
case MT_EXPLODEPICKUP:
|
||||
case MT_SCATTERPICKUP:
|
||||
case MT_GRENADEPICKUP:
|
||||
case MT_REDFLAG:
|
||||
case MT_BLUEFLAG:
|
||||
if (mo->target)
|
||||
{
|
||||
// Flung items copy the gravity of their tosser.
|
||||
if ((mo->target->eflags & MFE_VERTICALFLIP) && !(mo->eflags & MFE_VERTICALFLIP))
|
||||
{
|
||||
// Flung items copy the gravity of their tosser.
|
||||
if ((mo->target->eflags & MFE_VERTICALFLIP) && !(mo->eflags & MFE_VERTICALFLIP))
|
||||
{
|
||||
gravityadd = -gravityadd;
|
||||
mo->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
gravityadd = -gravityadd;
|
||||
mo->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
break;
|
||||
case MT_WATERDROP:
|
||||
case MT_BATTLEBUMPER:
|
||||
gravityadd /= 2;
|
||||
break;
|
||||
case MT_BANANA:
|
||||
case MT_EGGMANITEM:
|
||||
case MT_SSMINE:
|
||||
case MT_LANDMINE:
|
||||
case MT_DROPTARGET:
|
||||
case MT_SINK:
|
||||
case MT_EMERALD:
|
||||
}
|
||||
break;
|
||||
case MT_WATERDROP:
|
||||
case MT_BATTLEBUMPER:
|
||||
gravityadd /= 2;
|
||||
break;
|
||||
case MT_BANANA:
|
||||
case MT_EGGMANITEM:
|
||||
case MT_SSMINE:
|
||||
case MT_LANDMINE:
|
||||
case MT_DROPTARGET:
|
||||
case MT_SINK:
|
||||
case MT_EMERALD:
|
||||
if (mo->health > 0)
|
||||
{
|
||||
if (mo->extravalue2 > 0)
|
||||
{
|
||||
gravityadd *= mo->extravalue2;
|
||||
}
|
||||
|
||||
gravityadd = (5*gravityadd)/2;
|
||||
break;
|
||||
case MT_KARMAFIREWORK:
|
||||
gravityadd /= 3;
|
||||
break;
|
||||
case MT_ITEM_DEBRIS:
|
||||
gravityadd *= 6;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MT_KARMAFIREWORK:
|
||||
gravityadd /= 3;
|
||||
break;
|
||||
case MT_ITEM_DEBRIS:
|
||||
gravityadd *= 6;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1261,6 +1263,11 @@ void P_CheckGravity(mobj_t *mo, boolean affect)
|
|||
//
|
||||
void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope)
|
||||
{
|
||||
if (!(mo->flags & MF_SLOPE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (slope)
|
||||
{
|
||||
fixed_t tempz = slope->normal.z;
|
||||
|
|
@ -1764,7 +1771,7 @@ void P_XYMovement(mobj_t *mo)
|
|||
S_StartSound(mo, mo->info->deathsound);
|
||||
P_KillMobj(mo, NULL, NULL, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(mo, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(mo, 24*FRACUNIT, false);
|
||||
P_InstaThrust(mo, R_PointToAngle2(mo->x, mo->y, mo->x + xmove, mo->y + ymove)+ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
break;
|
||||
|
|
@ -3119,16 +3126,14 @@ boolean P_CanRunOnWater(mobj_t *mobj, ffloor_t *rover)
|
|||
fixed_t surfaceheight = INT32_MAX;
|
||||
fixed_t surfDiff = INT32_MAX;
|
||||
|
||||
fixed_t floorheight = INT32_MAX;
|
||||
fixed_t floorDiff = INT32_MAX;
|
||||
|
||||
fixed_t mobjbottom = INT32_MAX;
|
||||
fixed_t maxStep = INT32_MAX;
|
||||
boolean doifit = false;
|
||||
|
||||
pslope_t *waterSlope = NULL;
|
||||
angle_t ourZAng = 0;
|
||||
angle_t waterZAng = 0;
|
||||
angle_t moveDir = 0;
|
||||
fixed_t ourZAng = 0;
|
||||
fixed_t waterZAng = 0;
|
||||
|
||||
if (rover == NULL)
|
||||
{
|
||||
|
|
@ -3162,20 +3167,36 @@ boolean P_CanRunOnWater(mobj_t *mobj, ffloor_t *rover)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mobj->standingslope != NULL)
|
||||
moveDir = K_MomentumAngle(mobj);
|
||||
|
||||
if (mobj->standingslope != NULL && mobj->standingslope->zangle != 0)
|
||||
{
|
||||
ourZAng = mobj->standingslope->zangle;
|
||||
angle_t dir = mobj->standingslope->xydirection;
|
||||
angle_t workang = mobj->standingslope->zangle;
|
||||
if (workang >= ANGLE_180)
|
||||
{
|
||||
workang = InvAngle(workang);
|
||||
dir = InvAngle(dir);
|
||||
}
|
||||
ourZAng = P_ReturnThrustX(mobj, dir - moveDir, AngleFixed(workang));
|
||||
}
|
||||
|
||||
waterSlope = (flip ? *rover->b_slope : *rover->t_slope);
|
||||
if (waterSlope != NULL)
|
||||
if (waterSlope != NULL && waterSlope->zangle != 0)
|
||||
{
|
||||
waterZAng = waterSlope->zangle;
|
||||
angle_t dir = waterSlope->xydirection;
|
||||
angle_t workang = waterSlope->zangle;
|
||||
if (workang >= ANGLE_180)
|
||||
{
|
||||
workang = InvAngle(workang);
|
||||
dir = InvAngle(dir);
|
||||
}
|
||||
waterZAng = P_ReturnThrustX(mobj, dir - moveDir, AngleFixed(workang));
|
||||
}
|
||||
|
||||
if (ourZAng != waterZAng)
|
||||
if (abs(ourZAng - waterZAng) > 11*FRACUNIT)
|
||||
{
|
||||
// The surface slopes are different.
|
||||
// The surface slopes are too different.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -3193,16 +3214,20 @@ boolean P_CanRunOnWater(mobj_t *mobj, ffloor_t *rover)
|
|||
maxStep = P_GetThingStepUp(mobj, mobj->x, mobj->y);
|
||||
|
||||
surfDiff = flip ? (surfaceheight - mobjbottom) : (mobjbottom - surfaceheight);
|
||||
|
||||
// We start water run IF we can step onto it!
|
||||
if (surfDiff <= maxStep && surfDiff >= 0)
|
||||
{
|
||||
// We start water run IF we can step-down!
|
||||
floorheight = flip ? P_GetSectorCeilingZAt(mobj->subsector->sector, mobj->x, mobj->y) : P_GetSectorFloorZAt(mobj->subsector->sector, mobj->x, mobj->y);
|
||||
floorDiff = flip ? (floorheight - mobjbottom) : (mobjbottom - floorheight);
|
||||
if (floorDiff <= maxStep && floorDiff >= 0)
|
||||
if (ourZAng < 0)
|
||||
{
|
||||
// ... but NOT if real floor is in range.
|
||||
// FIXME: Count solid FOFs in this check
|
||||
return false;
|
||||
fixed_t floorheight = flip ? P_GetSectorCeilingZAt(mobj->subsector->sector, mobj->x, mobj->y) : P_GetSectorFloorZAt(mobj->subsector->sector, mobj->x, mobj->y);
|
||||
fixed_t floorDiff = flip ? (floorheight - mobjbottom) : (mobjbottom - floorheight);
|
||||
if (floorDiff <= maxStep && floorDiff >= -maxStep)
|
||||
{
|
||||
// ... but NOT if going down and real floor is in range.
|
||||
// FIXME: Count solid FOFs in this check
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -5257,27 +5282,8 @@ void P_RunOverlays(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!r_splitscreen /*&& rendermode != render_soft*/)
|
||||
{
|
||||
angle_t viewingangle;
|
||||
|
||||
if (players[displayplayers[0]].awayviewtics)
|
||||
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y);
|
||||
else if (!camera[0].chase && players[displayplayers[0]].mo)
|
||||
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y);
|
||||
else
|
||||
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera[0].x, camera[0].y);
|
||||
|
||||
if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1)
|
||||
viewingangle += ANGLE_180;
|
||||
destx = mo->target->x + P_ReturnThrustX(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
|
||||
desty = mo->target->y + P_ReturnThrustY(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
|
||||
}
|
||||
else
|
||||
{
|
||||
destx = mo->target->x;
|
||||
desty = mo->target->y;
|
||||
}
|
||||
destx = mo->target->x;
|
||||
desty = mo->target->y;
|
||||
|
||||
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
|
||||
mo->scale = mo->destscale = FixedMul(mo->target->scale, mo->movefactor);
|
||||
|
|
@ -5289,12 +5295,27 @@ void P_RunOverlays(void)
|
|||
if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP))
|
||||
mo->flags ^= MF_DONTENCOREMAP;
|
||||
|
||||
mo->dispoffset = mo->target->dispoffset + mo->info->dispoffset;
|
||||
|
||||
if (!(mo->state->frame & FF_ANIMATE))
|
||||
{
|
||||
zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
|
||||
// if you're using FF_ANIMATE on an overlay,
|
||||
// then you're on your own.
|
||||
|
||||
if (mo->state->var1)
|
||||
{
|
||||
mo->dispoffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
mo->dispoffset++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if you're using FF_ANIMATE on an overlay,
|
||||
// then you're on your own.
|
||||
zoffs = 0;
|
||||
}
|
||||
|
||||
P_UnsetThingPosition(mo);
|
||||
mo->x = destx;
|
||||
|
|
@ -6490,8 +6511,26 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
|
|||
P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true);
|
||||
}
|
||||
break;
|
||||
case MT_ORBINAUT:
|
||||
case MT_BANANA:
|
||||
{
|
||||
angle_t spin = FixedMul(FixedDiv(abs(mobj->momz), 8 * mobj->scale), ANGLE_67h);
|
||||
mobj->angle -= spin;
|
||||
mobj->rollangle += spin;
|
||||
|
||||
if (P_IsObjectOnGround(mobj) && mobj->momz * P_MobjFlip(mobj) <= 0)
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MT_BANANA_SPARK:
|
||||
{
|
||||
angle_t spin = FixedMul(FixedDiv(abs(mobj->momz), 8 * mobj->scale), ANGLE_22h);
|
||||
mobj->rollangle += spin;
|
||||
}
|
||||
break;
|
||||
case MT_ORBINAUT:
|
||||
case MT_EGGMANITEM:
|
||||
case MT_LANDMINE:
|
||||
//case MT_DROPTARGET:
|
||||
|
|
@ -6786,6 +6825,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
break;
|
||||
case MT_FLOATINGITEM:
|
||||
{
|
||||
mobj->pitch = mobj->roll = 0;
|
||||
if (mobj->flags & MF_NOCLIPTHING)
|
||||
{
|
||||
if (P_CheckDeathPitCollide(mobj))
|
||||
|
|
@ -6930,16 +6970,61 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
}
|
||||
}
|
||||
|
||||
if (P_IsObjectOnGround(mobj) && mobj->health > 1)
|
||||
if (P_IsObjectOnGround(mobj))
|
||||
{
|
||||
S_StartSound(mobj, mobj->info->activesound);
|
||||
mobj->momx = mobj->momy = 0;
|
||||
mobj->health = 1;
|
||||
//mobj->rollangle = 0;
|
||||
|
||||
if (mobj->health > 1)
|
||||
{
|
||||
S_StartSound(mobj, mobj->info->activesound);
|
||||
mobj->momx = mobj->momy = 0;
|
||||
mobj->health = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// tilt n tumble
|
||||
angle_t spin = FixedMul(FixedDiv(abs(mobj->momz), 8 * mobj->scale), ANGLE_67h);
|
||||
mobj->angle += spin;
|
||||
mobj->rollangle -= spin;
|
||||
}
|
||||
|
||||
if (mobj->threshold > 0)
|
||||
mobj->threshold--;
|
||||
break;
|
||||
case MT_BANANA_SPARK:
|
||||
{
|
||||
if (leveltime & 1)
|
||||
{
|
||||
mobj->spritexscale = mobj->spriteyscale = FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((leveltime / 2) & 1)
|
||||
{
|
||||
mobj->spriteyscale = 3*FRACUNIT/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->spritexscale = 3*FRACUNIT/2;
|
||||
}
|
||||
}
|
||||
|
||||
if (P_IsObjectOnGround(mobj) == true && mobj->momz * P_MobjFlip(mobj) <= 0)
|
||||
{
|
||||
P_SetObjectMomZ(mobj, 8*FRACUNIT, false);
|
||||
|
||||
if (mobj->health > 0)
|
||||
{
|
||||
mobj->tics = 1;
|
||||
mobj->destscale = 0;
|
||||
mobj->spritexscale = mobj->spriteyscale = FRACUNIT;
|
||||
mobj->health = 0;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MT_SPB:
|
||||
{
|
||||
Obj_SPBThink(mobj);
|
||||
|
|
@ -9579,7 +9664,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
S_StartSound(mobj, mobj->info->deathsound);
|
||||
P_KillMobj(mobj, NULL, NULL, DMG_NORMAL);
|
||||
|
||||
P_SetObjectMomZ(mobj, 8*FRACUNIT, false);
|
||||
P_SetObjectMomZ(mobj, 24*FRACUNIT, false);
|
||||
P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_90, 16*FRACUNIT);
|
||||
}
|
||||
|
||||
|
|
@ -9806,24 +9891,6 @@ void P_PushableThinker(mobj_t *mobj)
|
|||
// Quick, optimized function for scenery
|
||||
void P_SceneryThinker(mobj_t *mobj)
|
||||
{
|
||||
if (mobj->flags & MF_BOXICON)
|
||||
{
|
||||
if (!(mobj->eflags & MFE_VERTICALFLIP))
|
||||
{
|
||||
if (mobj->z < mobj->floorz + FixedMul(mobj->info->damage, mobj->scale))
|
||||
mobj->momz = FixedMul(mobj->info->speed, mobj->scale);
|
||||
else
|
||||
mobj->momz = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mobj->z + FixedMul(mobj->info->height, mobj->scale) > mobj->ceilingz - FixedMul(mobj->info->damage, mobj->scale))
|
||||
mobj->momz = -FixedMul(mobj->info->speed, mobj->scale);
|
||||
else
|
||||
mobj->momz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// momentum movement
|
||||
if (mobj->momx || mobj->momy)
|
||||
{
|
||||
|
|
@ -10872,21 +10939,41 @@ void P_RemovePrecipMobj(precipmobj_t *mobj)
|
|||
void P_RemoveSavegameMobj(mobj_t *mobj)
|
||||
{
|
||||
// unlink from sector and block lists
|
||||
P_UnsetThingPosition(mobj);
|
||||
|
||||
// Remove touching_sectorlist from mobj.
|
||||
if (sector_list)
|
||||
if (((thinker_t *)mobj)->function.acp1 == (actionf_p1)P_NullPrecipThinker)
|
||||
{
|
||||
P_DelSeclist(sector_list);
|
||||
sector_list = NULL;
|
||||
P_UnsetPrecipThingPosition((precipmobj_t *)mobj);
|
||||
|
||||
if (precipsector_list)
|
||||
{
|
||||
P_DelPrecipSeclist(precipsector_list);
|
||||
precipsector_list = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// unlink from sector and block lists
|
||||
P_UnsetThingPosition(mobj);
|
||||
|
||||
// Remove touching_sectorlist from mobj.
|
||||
if (sector_list)
|
||||
{
|
||||
P_DelSeclist(sector_list);
|
||||
sector_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// stop any playing sound
|
||||
S_StopSound(mobj);
|
||||
R_RemoveMobjInterpolator(mobj);
|
||||
|
||||
// free block
|
||||
P_RemoveThinker((thinker_t *)mobj);
|
||||
R_RemoveMobjInterpolator(mobj);
|
||||
// Here we use the same code as R_RemoveThinkerDelayed, but without reference counting (we're removing everything so it shouldn't matter) and without touching currentthinker since we aren't in P_RunThinkers
|
||||
{
|
||||
thinker_t *thinker = (thinker_t *)mobj;
|
||||
thinker_t *next = thinker->next;
|
||||
(next->prev = thinker->prev)->next = next;
|
||||
Z_Free(thinker);
|
||||
}
|
||||
}
|
||||
|
||||
static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
|
||||
|
|
@ -13767,6 +13854,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
|
|||
if (!newmobj)
|
||||
return NULL;
|
||||
|
||||
newmobj->hitlag = mobj->hitlag;
|
||||
|
||||
newmobj->destscale = P_ScaleFromMap(mobj->destscale, newmobj->destscale);
|
||||
P_SetScale(newmobj, P_ScaleFromMap(mobj->scale, newmobj->scale));
|
||||
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@ typedef enum
|
|||
MF_NOCLIP = 1<<12,
|
||||
// Allow moves to any height, no gravity. For active floaters.
|
||||
MF_FLOAT = 1<<13,
|
||||
// Monitor powerup icon. These rise a bit.
|
||||
MF_BOXICON = 1<<14,
|
||||
// Change pitch/roll when touching slopes.
|
||||
MF_SLOPE = 1<<14,
|
||||
// Don't hit same species, explode on block.
|
||||
// Player missiles as well as fireballs of various kinds.
|
||||
MF_MISSILE = 1<<15,
|
||||
|
|
@ -163,7 +163,7 @@ typedef enum
|
|||
MF_NOSQUISH = 1<<30,
|
||||
// Disable hitlag for this object
|
||||
MF_NOHITLAGFORME = (INT32)(1U<<31),
|
||||
// no more free slots, next up I suppose we can get rid of shit like MF_BOXICON?
|
||||
// no more free slots, gotta get rid of more crusty base SRB2 flags
|
||||
} mobjflag_t;
|
||||
|
||||
typedef enum
|
||||
|
|
|
|||
|
|
@ -3345,6 +3345,19 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
|||
mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight;
|
||||
}
|
||||
|
||||
if (mobj->type == MT_SKYBOX)
|
||||
{
|
||||
mtag_t tag = mobj->movedir;
|
||||
if (tag < 0 || tag > 15)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "LoadMobjThinker: Skybox ID %d of netloaded object is not between 0 and 15!\n", tag);
|
||||
}
|
||||
else if (mobj->flags2 & MF2_AMBUSH)
|
||||
skyboxcenterpnts[tag] = mobj;
|
||||
else
|
||||
skyboxviewpnts[tag] = mobj;
|
||||
}
|
||||
|
||||
if (diff2 & MD2_WAYPOINTCAP)
|
||||
P_SetTarget(&waypointcap, mobj);
|
||||
|
||||
|
|
@ -3972,10 +3985,14 @@ static void P_NetUnArchiveThinkers(void)
|
|||
{
|
||||
next = currentthinker->next;
|
||||
|
||||
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker || currentthinker->function.acp1 == (actionf_p1)P_NullPrecipThinker)
|
||||
P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it
|
||||
else
|
||||
{
|
||||
(next->prev = currentthinker->prev)->next = next;
|
||||
R_DestroyLevelInterpolators(currentthinker);
|
||||
Z_Free(currentthinker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
204
src/p_setup.c
204
src/p_setup.c
|
|
@ -170,6 +170,13 @@ mapthing_t *playerstarts[MAXPLAYERS];
|
|||
mapthing_t *bluectfstarts[MAXPLAYERS];
|
||||
mapthing_t *redctfstarts[MAXPLAYERS];
|
||||
|
||||
// Global state for PartialAddWadFile/MultiSetupWadFiles
|
||||
// Might be replacable with parameters, but non-trivial when the functions are called on separate tics
|
||||
static SINT8 partadd_stage = -1;
|
||||
static boolean partadd_important = false;
|
||||
UINT16 partadd_earliestfile = UINT16_MAX;
|
||||
|
||||
|
||||
// Maintain *ZOOM TUBE* waypoints
|
||||
// Renamed because SRB2Kart owns real waypoints.
|
||||
mobj_t *tubewaypoints[NUMTUBEWAYPOINTSEQUENCES][TUBEWAYPOINTSEQUENCESIZE];
|
||||
|
|
@ -2624,6 +2631,7 @@ static void P_ProcessLinedefsAfterSidedefs(void)
|
|||
{
|
||||
size_t i = numlines;
|
||||
register line_t *ld = lines;
|
||||
const boolean subtractTripwire = ((mapheaderinfo[gamemap - 1]->levelflags & LF_SUBTRACTNUM) == LF_SUBTRACTNUM);
|
||||
|
||||
for (; i--; ld++)
|
||||
{
|
||||
|
|
@ -2638,7 +2646,7 @@ static void P_ProcessLinedefsAfterSidedefs(void)
|
|||
|
||||
if (ld->tripwire)
|
||||
{
|
||||
ld->blendmode = AST_ADD;
|
||||
ld->blendmode = (subtractTripwire ? AST_SUBTRACT : AST_ADD);
|
||||
ld->alpha = 0xff;
|
||||
}
|
||||
|
||||
|
|
@ -7350,7 +7358,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
|
||||
// Reset the palette now all fades have been done
|
||||
if (rendermode != render_none)
|
||||
V_SetPaletteLump(GetPalette()); // Set the level palette
|
||||
V_ReloadPalette(); // Set the level palette
|
||||
|
||||
if (!(reloadinggamestate || titlemapinaction))
|
||||
{
|
||||
|
|
@ -7745,7 +7753,7 @@ lumpnum_t wadnamelump = LUMPERROR;
|
|||
INT16 wadnamemap = 0; // gamemap based
|
||||
|
||||
// Initialising map data (and catching replacements)...
|
||||
UINT8 P_InitMapData(INT32 numexistingmapheaders)
|
||||
UINT8 P_InitMapData(boolean existingmapheaders)
|
||||
{
|
||||
UINT8 ret = 0;
|
||||
INT32 i;
|
||||
|
|
@ -7759,20 +7767,9 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders)
|
|||
name = mapheaderinfo[i]->lumpname;
|
||||
maplump = W_CheckNumForMap(name);
|
||||
|
||||
// Doesn't exist?
|
||||
if (maplump == INT16_MAX)
|
||||
{
|
||||
#ifndef DEVELOP
|
||||
if (!numexistingmapheaders)
|
||||
{
|
||||
I_Error("P_InitMapData: Base map %s has a header but no level\n", name);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// Always check for cup cache reassociations.
|
||||
// (The core assumption is that cups < headers.)
|
||||
if (maplump != LUMPERROR || mapheaderinfo[i]->lumpnum != LUMPERROR)
|
||||
{
|
||||
cupheader_t *cup = kartcupheaders;
|
||||
INT32 j;
|
||||
|
|
@ -7807,6 +7804,18 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders)
|
|||
}
|
||||
}
|
||||
|
||||
// Doesn't exist in this set of files?
|
||||
if (maplump == LUMPERROR)
|
||||
{
|
||||
#ifndef DEVELOP
|
||||
if (!existingmapheaders)
|
||||
{
|
||||
I_Error("P_InitMapData: Base map %s has a header but no level\n", name);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// No change?
|
||||
if (mapheaderinfo[i]->lumpnum == maplump)
|
||||
continue;
|
||||
|
|
@ -7816,7 +7825,7 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders)
|
|||
ret |= MAPRET_ADDED;
|
||||
CONS_Printf("%s\n", name);
|
||||
|
||||
if (numexistingmapheaders && mapheaderinfo[i]->lumpnum != LUMPERROR)
|
||||
if (existingmapheaders && mapheaderinfo[i]->lumpnum != LUMPERROR)
|
||||
{
|
||||
G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you
|
||||
|
||||
|
|
@ -7866,23 +7875,32 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders)
|
|||
return ret;
|
||||
}
|
||||
|
||||
UINT16 p_adding_file = INT16_MAX;
|
||||
|
||||
//
|
||||
// Add a wadfile to the active wad files,
|
||||
// replace sounds, musics, patches, textures, sprites and maps
|
||||
//
|
||||
boolean P_AddWadFile(const char *wadfilename)
|
||||
{
|
||||
UINT16 wadnum;
|
||||
|
||||
if ((wadnum = P_PartialAddWadFile(wadfilename)) == UINT16_MAX)
|
||||
return false;
|
||||
|
||||
P_MultiSetupWadFiles(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Add a WAD file and do the per-WAD setup stages.
|
||||
// Call P_MultiSetupWadFiles as soon as possible after any number of these.
|
||||
//
|
||||
UINT16 P_PartialAddWadFile(const char *wadfilename)
|
||||
{
|
||||
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
|
||||
INT32 numexistingmapheaders = nummapheaders;
|
||||
UINT16 numlumps, wadnum;
|
||||
char *name;
|
||||
lumpinfo_t *lumpinfo;
|
||||
|
||||
//boolean texturechange = false; ///\todo Useless; broken when back-frontporting PK3 changes?
|
||||
UINT8 mapsadded = 0;
|
||||
|
||||
// Vars to help us with the position start and amount of each resource type.
|
||||
// Useful for PK3s since they use folders.
|
||||
// WADs use markers for some resources, but others such as sounds are checked lump-by-lump anyway.
|
||||
|
|
@ -7902,10 +7920,19 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
wadnum = (UINT16)(numwadfiles-1);
|
||||
|
||||
p_adding_file = wadnum;
|
||||
wadnum = (UINT16)(numwadfiles-1);
|
||||
|
||||
// Init partadd.
|
||||
if (wadfiles[wadnum]->important)
|
||||
{
|
||||
partadd_important = true;
|
||||
}
|
||||
if (partadd_stage != 0)
|
||||
{
|
||||
partadd_earliestfile = wadnum;
|
||||
}
|
||||
partadd_stage = 0;
|
||||
|
||||
switch(wadfiles[wadnum]->type)
|
||||
{
|
||||
|
|
@ -7939,8 +7966,6 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
// R_LoadSpritsRange(wadnum, sprPos, sprNum);
|
||||
// if (texNum) // Textures. TODO: R_LoadTextures() does the folder positioning once again. New function maybe?
|
||||
// R_LoadTextures();
|
||||
// if (mapNum) // Maps. TODO: Actually implement the map WAD loading code, lulz.
|
||||
// P_LoadWadMapRange(wadnum, mapPos, mapNum);
|
||||
break;
|
||||
default:
|
||||
lumpinfo = wadfiles[wadnum]->lumpinfo;
|
||||
|
|
@ -8005,23 +8030,14 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
// TEXTURES/etc. list.
|
||||
R_LoadTexturesPwad(wadnum); // numtexture changes
|
||||
|
||||
// Reload ANIMDEFS
|
||||
P_InitPicAnims();
|
||||
|
||||
// Reload BRIGHT
|
||||
K_InitBrightmapsPwad(wadnum);
|
||||
|
||||
// Flush and reload HUD graphics
|
||||
//ST_UnloadGraphics();
|
||||
HU_LoadGraphics();
|
||||
ST_LoadGraphics();
|
||||
|
||||
//
|
||||
// look for skins
|
||||
//
|
||||
R_AddSkins(wadnum); // faB: wadfile index in wadfiles[]
|
||||
R_PatchSkins(wadnum); // toast: PATCH PATCH
|
||||
ST_ReloadSkinFaceGraphics();
|
||||
|
||||
//
|
||||
// edit music defs
|
||||
|
|
@ -8029,37 +8045,99 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
S_LoadMusicDefs(wadnum);
|
||||
|
||||
//
|
||||
// search for maps
|
||||
// extra sprite/skin data
|
||||
//
|
||||
mapsadded = P_InitMapData(numexistingmapheaders);
|
||||
|
||||
if (!mapsadded)
|
||||
CONS_Printf(M_GetText("No maps added\n"));
|
||||
|
||||
R_LoadSpriteInfoLumps(wadnum, numlumps);
|
||||
|
||||
#ifdef HWRENDER
|
||||
HWR_ReloadModels();
|
||||
#endif
|
||||
// For anything that has to be done over every wadfile at once, see P_MultiSetupWadFiles.
|
||||
|
||||
// reload status bar (warning should have valid player!)
|
||||
if (gamestate == GS_LEVEL)
|
||||
ST_Start();
|
||||
|
||||
// Prevent savefile cheating
|
||||
if (cursaveslot > 0)
|
||||
cursaveslot = 0;
|
||||
|
||||
if ((mapsadded & MAPRET_CURRENTREPLACED) && gamestate == GS_LEVEL && (netgame || multiplayer))
|
||||
{
|
||||
CONS_Printf(M_GetText("Current map %d replaced by added file, ending the level to ensure consistency.\n"), gamemap);
|
||||
if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
}
|
||||
|
||||
refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_GAMEDATA to disappear the next frame, but it's a bit too dangerous for that...
|
||||
|
||||
p_adding_file = INT16_MAX;
|
||||
refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_ flags to disappear the next frame, but this one's a bit too dangerous for that...
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only exists to make sure there's no way to overwrite partadd_stage externally
|
||||
// unless you really push yourself.
|
||||
SINT8 P_PartialAddGetStage(void)
|
||||
{
|
||||
return partadd_stage;
|
||||
}
|
||||
|
||||
//
|
||||
// Set up a series of partially added WAD files.
|
||||
// Setup functions that iterate over every loaded WAD go here.
|
||||
// If fullsetup false, only do one stage per call.
|
||||
//
|
||||
boolean P_MultiSetupWadFiles(boolean fullsetup)
|
||||
{
|
||||
if (partadd_stage < 0)
|
||||
I_Error(M_GetText("P_MultiSetupWadFiles: Post-load addon setup attempted without loading any addons first"));
|
||||
|
||||
if (partadd_stage == 0)
|
||||
{
|
||||
// Flush and reload HUD graphics
|
||||
//ST_UnloadGraphics();
|
||||
HU_LoadGraphics();
|
||||
ST_LoadGraphics();
|
||||
ST_ReloadSkinFaceGraphics();
|
||||
|
||||
if (!partadd_important)
|
||||
partadd_stage = -1; // everything done
|
||||
else if (fullsetup)
|
||||
partadd_stage++;
|
||||
}
|
||||
|
||||
if (partadd_stage == 1)
|
||||
{
|
||||
// Prevent savefile cheating
|
||||
if (cursaveslot >= 0)
|
||||
cursaveslot = 0;
|
||||
|
||||
// Reload ANIMATED / ANIMDEFS
|
||||
P_InitPicAnims();
|
||||
|
||||
// reload status bar (warning should have valid player!)
|
||||
if (gamestate == GS_LEVEL)
|
||||
ST_Start();
|
||||
|
||||
#ifdef HWRENDER
|
||||
HWR_ReloadModels();
|
||||
#endif
|
||||
|
||||
if (fullsetup)
|
||||
partadd_stage++;
|
||||
}
|
||||
|
||||
if (partadd_stage == 2)
|
||||
{
|
||||
UINT8 mapsadded = P_InitMapData(true);
|
||||
|
||||
if (!mapsadded)
|
||||
CONS_Printf(M_GetText("No maps added\n"));
|
||||
|
||||
if ((mapsadded & MAPRET_CURRENTREPLACED)
|
||||
&& (gamestate == GS_LEVEL)
|
||||
&& (netgame || multiplayer))
|
||||
{
|
||||
CONS_Printf(M_GetText("Current map %d replaced by added file, ending the level to ensure consistency.\n"), gamemap);
|
||||
if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
}
|
||||
|
||||
//if (fullsetup)
|
||||
//partadd_stage++;
|
||||
partadd_stage = -1;
|
||||
}
|
||||
|
||||
I_Assert(!fullsetup || partadd_stage < 0);
|
||||
|
||||
if (partadd_stage < 0)
|
||||
{
|
||||
partadd_important = false;
|
||||
partadd_earliestfile = UINT16_MAX;
|
||||
return true;
|
||||
}
|
||||
|
||||
partadd_stage++;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,8 +96,6 @@ INT32 P_CheckLevelFlat(const char *flatname);
|
|||
extern size_t nummapthings;
|
||||
extern mapthing_t *mapthings;
|
||||
|
||||
extern UINT16 p_adding_file;
|
||||
|
||||
void P_SetupLevelSky(const char *skytexname, boolean global);
|
||||
void P_RespawnThings(void);
|
||||
boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
|
||||
|
|
@ -108,11 +106,29 @@ boolean P_AddWadFile(const char *wadfilename);
|
|||
|
||||
#define MAPRET_ADDED (1)
|
||||
#define MAPRET_CURRENTREPLACED (1<<1)
|
||||
UINT8 P_InitMapData(INT32 numexistingmapheaders);
|
||||
UINT8 P_InitMapData(boolean existingmapheaders);
|
||||
extern lumpnum_t wadnamelump;
|
||||
extern INT16 wadnamemap;
|
||||
#define WADNAMECHECK(name) (!strncmp(name, "WADNAME", 7))
|
||||
|
||||
// WARNING: The following functions should be grouped as follows:
|
||||
// any amount of PartialAdds followed by MultiSetups until returned true,
|
||||
// as soon as possible.
|
||||
UINT16 P_PartialAddWadFile(const char *wadfilename);
|
||||
// Run a single stage of multisetup, or all of them if fullsetup set.
|
||||
// fullsetup true: run everything
|
||||
// otherwise multiple stages
|
||||
// returns true if setup finished on this call, false otherwise (always true on fullsetup)
|
||||
// throws I_Error if called without any partial adds started as a safeguard
|
||||
boolean P_MultiSetupWadFiles(boolean fullsetup);
|
||||
// Get the current setup stage.
|
||||
// if negative, no PartialAdds done since last MultiSetup
|
||||
// if 0, partial adds done but MultiSetup not called yet
|
||||
// if positive, setup's partway done
|
||||
SINT8 P_PartialAddGetStage(void);
|
||||
extern UINT16 partadd_earliestfile;
|
||||
|
||||
|
||||
boolean P_RunSOC(const char *socfilename);
|
||||
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
|
|
|
|||
64
src/p_spec.c
64
src/p_spec.c
|
|
@ -148,7 +148,7 @@ static void GrowAnimDefs(void)
|
|||
|
||||
// A prototype; here instead of p_spec.h, so they're "private"
|
||||
void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum);
|
||||
void P_ParseAnimationDefintion(SINT8 istexture);
|
||||
void P_ParseAnimationDefintion(void);
|
||||
|
||||
/** Sets up texture and flat animations.
|
||||
*
|
||||
|
|
@ -161,8 +161,6 @@ void P_ParseAnimationDefintion(SINT8 istexture);
|
|||
* \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs), JTE (had to rewrite it to handle multiple WADs _correctly_)
|
||||
*/
|
||||
|
||||
static boolean animdeftempflats = false; // only until ANIMDEFS flats are removed
|
||||
|
||||
void P_InitPicAnims(void)
|
||||
{
|
||||
// Init animation
|
||||
|
|
@ -182,7 +180,6 @@ void P_InitPicAnims(void)
|
|||
|
||||
while (animdefsLumpNum != INT16_MAX)
|
||||
{
|
||||
animdeftempflats = ((p_adding_file == INT16_MAX) || p_adding_file == w);
|
||||
P_ParseANIMDEFSLump(w, animdefsLumpNum);
|
||||
animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1);
|
||||
}
|
||||
|
|
@ -204,31 +201,14 @@ void P_InitPicAnims(void)
|
|||
lastanim = anims;
|
||||
for (i = 0; animdefs[i].istexture != -1; i++)
|
||||
{
|
||||
if (animdefs[i].istexture == 1)
|
||||
{
|
||||
if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
|
||||
continue;
|
||||
|
||||
lastanim->picnum = R_TextureNumForName(animdefs[i].endname);
|
||||
lastanim->basepic = R_TextureNumForName(animdefs[i].startname);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (animdefs[i].istexture == 2)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "ANIMDEFS flats are disabled; flat support in general will be removed soon! (%s, %s)\n", animdefs[i].startname, animdefs[i].endname);
|
||||
}
|
||||
if (animdefs[i].istexture != 1)
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR)
|
||||
continue;
|
||||
|
||||
lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname);
|
||||
lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname);
|
||||
}
|
||||
#endif
|
||||
if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
|
||||
continue;
|
||||
|
||||
lastanim->picnum = R_TextureNumForName(animdefs[i].endname);
|
||||
lastanim->basepic = R_TextureNumForName(animdefs[i].startname);
|
||||
|
||||
lastanim->istexture = animdefs[i].istexture;
|
||||
lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
|
||||
|
|
@ -285,21 +265,20 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum)
|
|||
if (stricmp(animdefsToken, "TEXTURE") == 0)
|
||||
{
|
||||
Z_Free(animdefsToken);
|
||||
P_ParseAnimationDefintion(1);
|
||||
P_ParseAnimationDefintion();
|
||||
}
|
||||
else if (stricmp(animdefsToken, "FLAT") == 0)
|
||||
{
|
||||
Z_Free(animdefsToken);
|
||||
P_ParseAnimationDefintion(0);
|
||||
I_Error("Error parsing ANIMDEFS lump: FLats are no longer supported by Ring Racers");
|
||||
}
|
||||
else if (stricmp(animdefsToken, "OSCILLATE") == 0)
|
||||
{
|
||||
// This probably came off the tail of an earlier definition. It's technically legal syntax, but we don't support it.
|
||||
I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"OSCILLATE\" (the animation plays in reverse when it reaches the end) are not supported by SRB2");
|
||||
I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"OSCILLATE\" (the animation plays in reverse when it reaches the end) are not supported by Ring Racers");
|
||||
}
|
||||
else
|
||||
{
|
||||
I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\" or \"FLAT\", got \"%s\"",animdefsToken);
|
||||
I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\", got \"%s\"",animdefsToken);
|
||||
}
|
||||
// parse next line
|
||||
while (*p != '\0' && *p != '\n') ++p;
|
||||
|
|
@ -310,7 +289,7 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum)
|
|||
Z_Free((void *)animdefsText);
|
||||
}
|
||||
|
||||
void P_ParseAnimationDefintion(SINT8 istexture)
|
||||
void P_ParseAnimationDefintion(void)
|
||||
{
|
||||
char *animdefsToken;
|
||||
size_t animdefsTokenLength;
|
||||
|
|
@ -353,8 +332,7 @@ void P_ParseAnimationDefintion(SINT8 istexture)
|
|||
|
||||
// Search for existing animdef
|
||||
for (i = 0; i < maxanims; i++)
|
||||
if (animdefs[i].istexture == istexture // Check if it's the same type!
|
||||
&& stricmp(animdefsToken, animdefs[i].startname) == 0)
|
||||
if (stricmp(animdefsToken, animdefs[i].startname) == 0)
|
||||
{
|
||||
//CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken);
|
||||
|
||||
|
|
@ -376,10 +354,7 @@ void P_ParseAnimationDefintion(SINT8 istexture)
|
|||
Z_Free(animdefsToken);
|
||||
|
||||
// set texture type
|
||||
if (istexture)
|
||||
animdefs[i].istexture = 1;
|
||||
else
|
||||
animdefs[i].istexture = (animdeftempflats ? 2 : 0);
|
||||
animdefs[i].istexture = 1;
|
||||
|
||||
// "RANGE"
|
||||
animdefsToken = M_GetToken(NULL);
|
||||
|
|
@ -457,16 +432,6 @@ void P_ParseAnimationDefintion(SINT8 istexture)
|
|||
}
|
||||
animdefs[i].speed = animSpeed;
|
||||
Z_Free(animdefsToken);
|
||||
|
||||
#ifdef WALLFLATS
|
||||
// hehe... uhh.....
|
||||
if (!istexture)
|
||||
{
|
||||
GrowAnimDefs();
|
||||
M_Memcpy(&animdefs[maxanims-1], &animdefs[i], sizeof(animdef_t));
|
||||
animdefs[maxanims-1].istexture = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Checks for flats in levelflats that are part of a flat animation sequence
|
||||
|
|
@ -2391,6 +2356,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
camera[i].y += y;
|
||||
camera[i].z += z;
|
||||
camera[i].subsector = R_PointInSubsector(camera[i].x, camera[i].y);
|
||||
R_RelativeTeleportViewInterpolation(i, x, y, z, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "r_state.h"
|
||||
#include "s_sound.h"
|
||||
#include "r_main.h"
|
||||
#include "r_fps.h"
|
||||
|
||||
/** \brief The P_MixUp function
|
||||
|
||||
|
|
@ -73,8 +74,12 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
|||
// move chasecam at new player location
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
if (thing->player == &players[displayplayers[i]] && camera[i].chase)
|
||||
if (thing->player != &players[displayplayers[i]])
|
||||
continue;
|
||||
if (camera[i].chase)
|
||||
P_ResetCamera(thing->player, &camera[i]);
|
||||
R_ResetViewInterpolation(i + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
// don't run in place after a teleport
|
||||
|
|
|
|||
18
src/p_tick.c
18
src/p_tick.c
|
|
@ -24,6 +24,7 @@
|
|||
#include "lua_hook.h"
|
||||
#include "m_perfstats.h"
|
||||
#include "i_system.h" // I_GetPreciseTime
|
||||
#include "i_video.h" // rendermode
|
||||
#include "r_main.h"
|
||||
#include "r_fps.h"
|
||||
|
||||
|
|
@ -787,15 +788,20 @@ void P_Ticker(boolean run)
|
|||
// Hack: ensure newview is assigned every tic.
|
||||
// Ensures view interpolation is T-1 to T in poor network conditions
|
||||
// We need a better way to assign view state decoupled from game logic
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
player_t *player = &players[displayplayers[i]];
|
||||
const boolean skybox = (player->skybox.viewpoint && cv_skybox.value); // True if there's a skybox object and skyboxes are on
|
||||
if (skybox)
|
||||
for (i = 0; i <= r_splitscreen; i++)
|
||||
{
|
||||
R_SkyboxFrame(i);
|
||||
player_t *player = &players[displayplayers[i]];
|
||||
if (!player->mo)
|
||||
continue;
|
||||
const boolean skybox = (player->skybox.viewpoint && cv_skybox.value); // True if there's a skybox object and skyboxes are on
|
||||
if (skybox)
|
||||
{
|
||||
R_SkyboxFrame(i);
|
||||
}
|
||||
R_SetupFrame(i);
|
||||
}
|
||||
R_SetupFrame(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -216,6 +216,14 @@ void R_ResetViewInterpolation(UINT8 p)
|
|||
}
|
||||
}
|
||||
|
||||
void R_RelativeTeleportViewInterpolation(UINT8 p, fixed_t xdiff, fixed_t ydiff, fixed_t zdiff, angle_t angdiff)
|
||||
{
|
||||
pview_old[p].x += xdiff;
|
||||
pview_old[p].y += ydiff;
|
||||
pview_old[p].z += zdiff;
|
||||
pview_old[p].angle += angdiff;
|
||||
}
|
||||
|
||||
void R_SetViewContext(enum viewcontext_e _viewcontext)
|
||||
{
|
||||
UINT8 i = 0;
|
||||
|
|
|
|||
|
|
@ -126,6 +126,8 @@ void R_InterpolateViewRollAngle(fixed_t frac);
|
|||
void R_UpdateViewInterpolation(void);
|
||||
// Reset the view states (e.g. after level load) so R_InterpolateView doesn't interpolate invalid data
|
||||
void R_ResetViewInterpolation(UINT8 p);
|
||||
// Update old view for seamless relative teleport
|
||||
void R_RelativeTeleportViewInterpolation(UINT8 p, fixed_t xdiff, fixed_t ydiff, fixed_t zdiff, angle_t angdiff);
|
||||
// Set the current view context (the viewvars pointed to by newview)
|
||||
void R_SetViewContext(enum viewcontext_e _viewcontext);
|
||||
|
||||
|
|
|
|||
|
|
@ -106,10 +106,9 @@ rendermode_t chosenrendermode = render_none; // set by command line arguments
|
|||
|
||||
boolean highcolor = false;
|
||||
|
||||
static void Impl_SetVsync(void);
|
||||
|
||||
// synchronize page flipping with screen refresh
|
||||
consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Impl_SetVsync);
|
||||
consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
static consvar_t cv_stretch = CVAR_INIT ("stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL);
|
||||
static consvar_t cv_alwaysgrabmouse = CVAR_INIT ("alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
|
|
@ -185,6 +184,20 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen);
|
|||
//static void Impl_SetWindowName(const char *title);
|
||||
static void Impl_SetWindowIcon(void);
|
||||
|
||||
static void Impl_SetSoftwareVsync(int vsync)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2,0,18)
|
||||
static int oldvsync = 0;
|
||||
if (oldvsync != vsync)
|
||||
{
|
||||
SDL_RenderSetVSync(renderer, vsync);
|
||||
}
|
||||
oldvsync = vsync;
|
||||
#else
|
||||
(void)vsync;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition)
|
||||
{
|
||||
static SDL_bool wasfullscreen = SDL_FALSE;
|
||||
|
|
@ -277,6 +290,7 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool
|
|||
}
|
||||
SDL_PixelFormatEnumToMasks(sw_texture_format, &bpp, &rmask, &gmask, &bmask, &amask);
|
||||
vidSurface = SDL_CreateRGBSurface(0, width, height, bpp, rmask, gmask, bmask, amask);
|
||||
Impl_SetSoftwareVsync(cv_vidwait.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1254,6 +1268,7 @@ void I_FinishUpdate(void)
|
|||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, texture, &src_rect, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
Impl_SetSoftwareVsync(cv_vidwait.value);
|
||||
}
|
||||
#ifdef HWRENDER
|
||||
else if (rendermode == render_opengl)
|
||||
|
|
@ -1478,15 +1493,6 @@ static SDL_bool Impl_CreateContext(void)
|
|||
int flags = 0; // Use this to set SDL_RENDERER_* flags now
|
||||
if (usesdl2soft)
|
||||
flags |= SDL_RENDERER_SOFTWARE;
|
||||
#if 0
|
||||
// This shit is BROKEN.
|
||||
// - The version of SDL we're using cannot toggle VSync at runtime. We'll need a new SDL version implemented to have this work properly.
|
||||
// - cv_vidwait is initialized before config is loaded, so it's forced to default value at runtime, and forced off when switching. The config loading code would need restructured.
|
||||
// - With both this & frame interpolation on, I_FinishUpdate takes x10 longer. At this point, it is simpler to use a standard FPS cap.
|
||||
// So you can probably guess why I'm kinda over this, I'm just disabling it.
|
||||
else if (cv_vidwait.value)
|
||||
flags |= SDL_RENDERER_PRESENTVSYNC;
|
||||
#endif
|
||||
|
||||
// 3 August 2022
|
||||
// Possibly a Windows 11 issue; the default
|
||||
|
|
@ -2006,11 +2012,3 @@ UINT32 I_GetRefreshRate(void)
|
|||
// trouble querying mode over and over again.
|
||||
return refresh_rate;
|
||||
}
|
||||
|
||||
static void Impl_SetVsync(void)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2,0,18)
|
||||
if (renderer)
|
||||
SDL_RenderSetVSync(renderer, cv_vidwait.value);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
10
src/sounds.c
10
src/sounds.c
|
|
@ -1089,10 +1089,10 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"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
|
||||
{"sploss", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Down to yellow sparks
|
||||
{"join", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player joined server
|
||||
{"leave", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player left server
|
||||
{"requst", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Got a Discord join request
|
||||
{"syfail", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Funny sync failure
|
||||
{"join", true, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player joined server
|
||||
{"leave", true, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player left server
|
||||
{"requst", true, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Got a Discord join request
|
||||
{"syfail", true, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Funny sync failure
|
||||
{"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // :shitsfree:
|
||||
{"dbgsal", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Debug notification
|
||||
{"cock", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Hammer cocks, bang bang
|
||||
|
|
@ -1353,7 +1353,7 @@ sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean
|
|||
|
||||
return i;
|
||||
}
|
||||
CONS_Alert(CONS_WARNING, M_GetText("No more free sound slots\n"));
|
||||
I_Error("Out of Sound Freeslots while allocating \"%s\"\nLoad less addons to fix this.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -411,12 +411,10 @@ static void ST_drawDebugInfo(void)
|
|||
// Figure out some other way to display all of the RNG classes.
|
||||
|
||||
fixed_t peekres = P_RandomPeek(PR_UNDEFINED);
|
||||
peekres *= 10000; // Change from fixed point
|
||||
peekres >>= FRACBITS; // to displayable decimal
|
||||
|
||||
V_DrawRightAlignedString(320, height - 16, V_MONOSPACE, va("Init: %08x", P_GetInitSeed(PR_UNDEFINED)));
|
||||
V_DrawRightAlignedString(320, height - 8, V_MONOSPACE, va("Seed: %08x", P_GetRandSeed(PR_UNDEFINED)));
|
||||
V_DrawRightAlignedString(320, height, V_MONOSPACE, va("== : .%04d", peekres));
|
||||
V_DrawRightAlignedString(320, height, V_MONOSPACE, va("== : %08x", peekres));
|
||||
|
||||
height -= 32;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,11 +86,16 @@ static CV_PossibleValue_t constextsize_cons_t[] = {
|
|||
static void CV_constextsize_OnChange(void);
|
||||
consvar_t cv_constextsize = CVAR_INIT ("con_textsize", "Medium", CV_SAVE|CV_CALL, constextsize_cons_t, CV_constextsize_OnChange);
|
||||
|
||||
consvar_t cv_palette = CVAR_INIT ("palette", "", CV_CHEAT|CV_CALL|CV_NOINIT, NULL, CV_palette_OnChange);
|
||||
consvar_t cv_palettenum = CVAR_INIT ("palettenum", "0", CV_CHEAT|CV_CALL|CV_NOINIT, CV_Unsigned, CV_palette_OnChange);
|
||||
|
||||
// local copy of the palette for V_GetColor()
|
||||
RGBA_t *pLocalPalette = NULL;
|
||||
RGBA_t *pMasterPalette = NULL;
|
||||
RGBA_t *pGammaCorrectedPalette = NULL;
|
||||
|
||||
static size_t currentPaletteSize;
|
||||
|
||||
/*
|
||||
The following was an extremely helpful resource when developing my Colour Cube LUT.
|
||||
http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter24.html
|
||||
|
|
@ -311,9 +316,12 @@ UINT32 V_GammaCorrect(UINT32 input, double power)
|
|||
static void LoadPalette(const char *lumpname)
|
||||
{
|
||||
lumpnum_t lumpnum = W_GetNumForName(lumpname);
|
||||
size_t i, palsize = W_LumpLength(lumpnum)/3;
|
||||
size_t i, palsize;
|
||||
UINT8 *pal;
|
||||
|
||||
currentPaletteSize = W_LumpLength(lumpnum);
|
||||
palsize = currentPaletteSize / 3;
|
||||
|
||||
Cubeapply = InitCube();
|
||||
|
||||
if (pLocalPalette != pMasterPalette)
|
||||
|
|
@ -400,8 +408,24 @@ const char *R_GetPalname(UINT16 num)
|
|||
|
||||
const char *GetPalette(void)
|
||||
{
|
||||
const char *user = cv_palette.string;
|
||||
|
||||
if (user && user[0])
|
||||
{
|
||||
if (W_CheckNumForName(user) == LUMPERROR)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
"cv_palette %s lump does not exist\n", user);
|
||||
}
|
||||
else
|
||||
{
|
||||
return cv_palette.string;
|
||||
}
|
||||
}
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
return R_GetPalname((encoremode ? mapheaderinfo[gamemap-1]->encorepal : mapheaderinfo[gamemap-1]->palette));
|
||||
|
||||
return "PLAYPAL";
|
||||
}
|
||||
|
||||
|
|
@ -419,6 +443,19 @@ void V_SetPalette(INT32 palettenum)
|
|||
if (!pLocalPalette)
|
||||
V_ReloadPalette();
|
||||
|
||||
if (palettenum == 0)
|
||||
{
|
||||
palettenum = cv_palettenum.value;
|
||||
|
||||
if (palettenum * 256U > currentPaletteSize - 256)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
"cv_palettenum %d out of range\n",
|
||||
palettenum);
|
||||
palettenum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
HWR_SetPalette(&pLocalPalette[palettenum*256]);
|
||||
|
|
@ -433,23 +470,12 @@ void V_SetPalette(INT32 palettenum)
|
|||
void V_SetPaletteLump(const char *pal)
|
||||
{
|
||||
LoadPalette(pal);
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
HWR_SetPalette(pLocalPalette);
|
||||
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
if (rendermode != render_none)
|
||||
I_SetPalette(pLocalPalette);
|
||||
#ifdef HASINVERT
|
||||
R_MakeInvertmap();
|
||||
#endif
|
||||
V_SetPalette(0);
|
||||
}
|
||||
|
||||
static void CV_palette_OnChange(void)
|
||||
{
|
||||
// reload palette
|
||||
// recalculate Color Cube
|
||||
V_ReloadPalette();
|
||||
V_SetPalette(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ extern consvar_t cv_ticrate, cv_constextsize,
|
|||
cv_globalgamma, cv_globalsaturation,
|
||||
cv_rhue, cv_yhue, cv_ghue, cv_chue, cv_bhue, cv_mhue,
|
||||
cv_rgamma, cv_ygamma, cv_ggamma, cv_cgamma, cv_bgamma, cv_mgamma,
|
||||
cv_rsaturation, cv_ysaturation, cv_gsaturation, cv_csaturation, cv_bsaturation, cv_msaturation;
|
||||
cv_rsaturation, cv_ysaturation, cv_gsaturation, cv_csaturation, cv_bsaturation, cv_msaturation,
|
||||
cv_palette, cv_palettenum;
|
||||
|
||||
// Allocates buffer screens, call before R_Init.
|
||||
void V_Init(void);
|
||||
|
|
|
|||
|
|
@ -1324,6 +1324,7 @@ lumpnum_t W_CheckNumForMap(const char *name)
|
|||
lumpnum_t check = INT16_MAX;
|
||||
UINT32 uhash, hash = quickncasehash(name, LUMPNUMCACHENAME);
|
||||
INT32 i;
|
||||
UINT16 firstfile = (partadd_earliestfile == UINT16_MAX) ? 0 : partadd_earliestfile;
|
||||
|
||||
// Check the lumpnumcache first. Loop backwards so that we check
|
||||
// most recent entries first
|
||||
|
|
@ -1339,7 +1340,7 @@ lumpnum_t W_CheckNumForMap(const char *name)
|
|||
|
||||
uhash = quickncasehash(name, 8); // Not a mistake, legacy system for short lumpnames
|
||||
|
||||
for (i = numwadfiles - 1; i >= 0; i--)
|
||||
for (i = numwadfiles - 1; i >= firstfile; i--)
|
||||
{
|
||||
check = W_CheckNumForMapPwad(name, uhash, (UINT16)i, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -99,9 +99,10 @@ void* vres_GetPatch(virtlump_t *vlump, INT32 tag);
|
|||
// =========================================================================
|
||||
|
||||
#define MAX_WADPATH 512
|
||||
#define MAX_WADFILES 127 // maximum of wad files used at the same time
|
||||
// Replay code relies on it being an UINT8 and, just to be safe, in case some wad counter somewhere is a SINT8, you should NOT go above 127 here if you're lazy like me.
|
||||
// Besides, are there truly 127 wads worth your interrest?
|
||||
#define MAX_WADFILES 255 // maximum of wad files used at the same time
|
||||
// Replay code relies on it being an UINT8. There are no SINT8s handling WAD indices, though.
|
||||
// Can be set all the way up to 255 but not 256,
|
||||
// because an UINT8 will never be >= 256, probably breaking some conditionals.
|
||||
|
||||
#define lumpcache_t void *
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue