Merge branch 'next' into platform-fixes
This commit is contained in:
commit
cddc4e1500
|
@ -1458,7 +1458,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum)
|
||||||
// not from server or remote admin, must be hacked/buggy client
|
// not from server or remote admin, must be hacked/buggy client
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal netvar command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal netvar command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
netid = READUINT16(*p);
|
netid = READUINT16(*p);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "d_main.h"
|
#include "d_main.h"
|
||||||
#include "m_menu.h"
|
#include "m_menu.h"
|
||||||
#include "filesrch.h"
|
#include "filesrch.h"
|
||||||
|
#include "m_misc.h"
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#include "win32/win_main.h"
|
#include "win32/win_main.h"
|
||||||
|
@ -806,6 +807,33 @@ boolean CON_Responder(event_t *ev)
|
||||||
|| key == KEY_LALT || key == KEY_RALT)
|
|| key == KEY_LALT || key == KEY_RALT)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (key == KEY_LEFTARROW)
|
||||||
|
{
|
||||||
|
if (input_cur != 0)
|
||||||
|
{
|
||||||
|
if (ctrldown)
|
||||||
|
input_cur = M_JumpWordReverse(inputlines[inputline], input_cur);
|
||||||
|
else
|
||||||
|
--input_cur;
|
||||||
|
}
|
||||||
|
if (!shiftdown)
|
||||||
|
input_sel = input_cur;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (key == KEY_RIGHTARROW)
|
||||||
|
{
|
||||||
|
if (input_cur < input_len)
|
||||||
|
{
|
||||||
|
if (ctrldown)
|
||||||
|
input_cur += M_JumpWord(&inputlines[inputline][input_cur]);
|
||||||
|
else
|
||||||
|
++input_cur;
|
||||||
|
}
|
||||||
|
if (!shiftdown)
|
||||||
|
input_sel = input_cur;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// ctrl modifier -- changes behavior, adds shortcuts
|
// ctrl modifier -- changes behavior, adds shortcuts
|
||||||
if (ctrldown)
|
if (ctrldown)
|
||||||
{
|
{
|
||||||
|
@ -958,23 +986,6 @@ boolean CON_Responder(event_t *ev)
|
||||||
con_scrollup--;
|
con_scrollup--;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == KEY_LEFTARROW)
|
|
||||||
{
|
|
||||||
if (input_cur != 0)
|
|
||||||
--input_cur;
|
|
||||||
if (!shiftdown)
|
|
||||||
input_sel = input_cur;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (key == KEY_RIGHTARROW)
|
|
||||||
{
|
|
||||||
if (input_cur < input_len)
|
|
||||||
++input_cur;
|
|
||||||
if (!shiftdown)
|
|
||||||
input_sel = input_cur;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (key == KEY_HOME)
|
else if (key == KEY_HOME)
|
||||||
{
|
{
|
||||||
input_cur = 0;
|
input_cur = 0;
|
||||||
|
|
302
src/d_clisrv.c
302
src/d_clisrv.c
|
@ -21,6 +21,7 @@
|
||||||
#include "d_net.h"
|
#include "d_net.h"
|
||||||
#include "d_main.h"
|
#include "d_main.h"
|
||||||
#include "g_game.h"
|
#include "g_game.h"
|
||||||
|
#include "st_stuff.h"
|
||||||
#include "hu_stuff.h"
|
#include "hu_stuff.h"
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
#include "g_input.h" // JOY1
|
#include "g_input.h" // JOY1
|
||||||
|
@ -76,6 +77,7 @@ char motd[254], server_context[8]; // Message of the Day, Unique Context (even w
|
||||||
|
|
||||||
// Server specific vars
|
// Server specific vars
|
||||||
UINT8 playernode[MAXPLAYERS];
|
UINT8 playernode[MAXPLAYERS];
|
||||||
|
char playeraddress[MAXPLAYERS][64];
|
||||||
|
|
||||||
// Minimum timeout for sending the savegame
|
// Minimum timeout for sending the savegame
|
||||||
// The actual timeout will be longer depending on the savegame length
|
// The actual timeout will be longer depending on the savegame length
|
||||||
|
@ -391,7 +393,7 @@ static void ExtraDataTicker(void)
|
||||||
{
|
{
|
||||||
if (server)
|
if (server)
|
||||||
{
|
{
|
||||||
SendKick(i, KICK_MSG_CON_FAIL);
|
SendKick(i, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic));
|
DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic));
|
||||||
}
|
}
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]);
|
CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]);
|
||||||
|
@ -437,6 +439,9 @@ void SendKick(UINT8 playernum, UINT8 msg)
|
||||||
{
|
{
|
||||||
UINT8 buf[2];
|
UINT8 buf[2];
|
||||||
|
|
||||||
|
if (!(server && cv_rejointimeout.value))
|
||||||
|
msg &= ~KICK_MSG_KEEP_BODY;
|
||||||
|
|
||||||
buf[0] = playernum;
|
buf[0] = playernum;
|
||||||
buf[1] = msg;
|
buf[1] = msg;
|
||||||
SendNetXCmd(XD_KICK, &buf, 2);
|
SendNetXCmd(XD_KICK, &buf, 2);
|
||||||
|
@ -1058,7 +1063,7 @@ static void SV_SendResynch(INT32 node)
|
||||||
|
|
||||||
if (resynch_score[node] > (unsigned)cv_resynchattempts.value*250)
|
if (resynch_score[node] > (unsigned)cv_resynchattempts.value*250)
|
||||||
{
|
{
|
||||||
SendKick(nodetoplayer[node], KICK_MSG_CON_FAIL);
|
SendKick(nodetoplayer[node], KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
resynch_score[node] = 0;
|
resynch_score[node] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1627,6 +1632,7 @@ static void CL_LoadReceivedSavegame(void)
|
||||||
|
|
||||||
paused = false;
|
paused = false;
|
||||||
demoplayback = false;
|
demoplayback = false;
|
||||||
|
titlemapinaction = TITLEMAP_OFF;
|
||||||
titledemo = false;
|
titledemo = false;
|
||||||
automapactive = false;
|
automapactive = false;
|
||||||
|
|
||||||
|
@ -2412,6 +2418,7 @@ void CL_ClearPlayer(INT32 playernum)
|
||||||
if (players[playernum].mo)
|
if (players[playernum].mo)
|
||||||
P_RemoveMobj(players[playernum].mo);
|
P_RemoveMobj(players[playernum].mo);
|
||||||
memset(&players[playernum], 0, sizeof (player_t));
|
memset(&players[playernum], 0, sizeof (player_t));
|
||||||
|
memset(playeraddress[playernum], 0, sizeof(*playeraddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -2419,7 +2426,7 @@ void CL_ClearPlayer(INT32 playernum)
|
||||||
//
|
//
|
||||||
// Removes a player from the current game
|
// Removes a player from the current game
|
||||||
//
|
//
|
||||||
static void CL_RemovePlayer(INT32 playernum, INT32 reason)
|
static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
|
||||||
{
|
{
|
||||||
// Sanity check: exceptional cases (i.e. c-fails) can cause multiple
|
// Sanity check: exceptional cases (i.e. c-fails) can cause multiple
|
||||||
// kick commands to be issued for the same player.
|
// kick commands to be issued for the same player.
|
||||||
|
@ -2432,9 +2439,6 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
|
||||||
playerpernode[node]--;
|
playerpernode[node]--;
|
||||||
if (playerpernode[node] <= 0)
|
if (playerpernode[node] <= 0)
|
||||||
{
|
{
|
||||||
// If a resynch was in progress, well, it no longer needs to be.
|
|
||||||
SV_InitResynchVars(playernode[playernum]);
|
|
||||||
|
|
||||||
nodeingame[playernode[playernum]] = false;
|
nodeingame[playernode[playernum]] = false;
|
||||||
Net_CloseConnection(playernode[playernum]);
|
Net_CloseConnection(playernode[playernum]);
|
||||||
ResetNode(node);
|
ResetNode(node);
|
||||||
|
@ -2556,6 +2560,7 @@ void CL_Reset(void)
|
||||||
multiplayer = false;
|
multiplayer = false;
|
||||||
servernode = 0;
|
servernode = 0;
|
||||||
server = true;
|
server = true;
|
||||||
|
resynch_local_inprogress = false;
|
||||||
doomcom->numnodes = 1;
|
doomcom->numnodes = 1;
|
||||||
doomcom->numslots = 1;
|
doomcom->numslots = 1;
|
||||||
SV_StopServer();
|
SV_StopServer();
|
||||||
|
@ -2829,9 +2834,12 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
||||||
char buf[3 + MAX_REASONLENGTH];
|
char buf[3 + MAX_REASONLENGTH];
|
||||||
char *reason = buf;
|
char *reason = buf;
|
||||||
kickreason_t kickreason = KR_KICK;
|
kickreason_t kickreason = KR_KICK;
|
||||||
|
boolean keepbody;
|
||||||
|
|
||||||
pnum = READUINT8(*p);
|
pnum = READUINT8(*p);
|
||||||
msg = READUINT8(*p);
|
msg = READUINT8(*p);
|
||||||
|
keepbody = (msg & KICK_MSG_KEEP_BODY) != 0;
|
||||||
|
msg &= ~KICK_MSG_KEEP_BODY;
|
||||||
|
|
||||||
if (pnum == serverplayer && IsPlayerAdmin(playernum))
|
if (pnum == serverplayer && IsPlayerAdmin(playernum))
|
||||||
{
|
{
|
||||||
|
@ -2891,6 +2899,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
||||||
*/
|
*/
|
||||||
pnum = playernum;
|
pnum = playernum;
|
||||||
msg = KICK_MSG_CON_FAIL;
|
msg = KICK_MSG_CON_FAIL;
|
||||||
|
keepbody = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//CONS_Printf("\x82%s ", player_names[pnum]);
|
//CONS_Printf("\x82%s ", player_names[pnum]);
|
||||||
|
@ -2910,6 +2919,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
case KICK_MSG_GO_AWAY:
|
case KICK_MSG_GO_AWAY:
|
||||||
|
if (!players[pnum].quittime)
|
||||||
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
|
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
|
||||||
kickreason = KR_KICK;
|
kickreason = KR_KICK;
|
||||||
break;
|
break;
|
||||||
|
@ -2959,7 +2969,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
||||||
kickreason = KR_TIMEOUT;
|
kickreason = KR_TIMEOUT;
|
||||||
break;
|
break;
|
||||||
case KICK_MSG_PLAYER_QUIT:
|
case KICK_MSG_PLAYER_QUIT:
|
||||||
if (netgame) // not splitscreen/bots
|
if (netgame && !players[pnum].quittime) // not splitscreen/bots or soulless body
|
||||||
HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false);
|
HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false);
|
||||||
kickreason = KR_LEAVE;
|
kickreason = KR_LEAVE;
|
||||||
break;
|
break;
|
||||||
|
@ -3000,6 +3010,24 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
||||||
else
|
else
|
||||||
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
|
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||||
}
|
}
|
||||||
|
else if (keepbody)
|
||||||
|
{
|
||||||
|
if (server && !demoplayback)
|
||||||
|
{
|
||||||
|
INT32 node = playernode[pnum];
|
||||||
|
playerpernode[node]--;
|
||||||
|
if (playerpernode[node] <= 0)
|
||||||
|
{
|
||||||
|
nodeingame[node] = false;
|
||||||
|
Net_CloseConnection(node);
|
||||||
|
ResetNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playernode[pnum] = UINT8_MAX;
|
||||||
|
|
||||||
|
players[pnum].quittime = 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
CL_RemovePlayer(pnum, kickreason);
|
CL_RemovePlayer(pnum, kickreason);
|
||||||
}
|
}
|
||||||
|
@ -3008,6 +3036,9 @@ consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0,
|
||||||
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
|
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
|
||||||
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}};
|
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}};
|
||||||
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}};
|
||||||
|
consvar_t cv_rejointimeout = {"rejointimeout", "Off", CV_SAVE|CV_FLOAT, rejointimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}};
|
static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}};
|
||||||
consvar_t cv_resynchattempts = {"resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
consvar_t cv_resynchattempts = {"resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||||
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||||
|
@ -3077,6 +3108,7 @@ static void ResetNode(INT32 node)
|
||||||
nodewaiting[node] = 0;
|
nodewaiting[node] = 0;
|
||||||
playerpernode[node] = 0;
|
playerpernode[node] = 0;
|
||||||
sendingsavegame[node] = false;
|
sendingsavegame[node] = false;
|
||||||
|
SV_InitResynchVars(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SV_ResetServer(void)
|
void SV_ResetServer(void)
|
||||||
|
@ -3092,13 +3124,8 @@ void SV_ResetServer(void)
|
||||||
tictoclear = maketic;
|
tictoclear = maketic;
|
||||||
|
|
||||||
for (i = 0; i < MAXNETNODES; i++)
|
for (i = 0; i < MAXNETNODES; i++)
|
||||||
{
|
|
||||||
ResetNode(i);
|
ResetNode(i);
|
||||||
|
|
||||||
// Make sure resynch status doesn't get carried over!
|
|
||||||
SV_InitResynchVars(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_BLUA
|
#ifdef HAVE_BLUA
|
||||||
|
@ -3106,6 +3133,7 @@ void SV_ResetServer(void)
|
||||||
#endif
|
#endif
|
||||||
playeringame[i] = false;
|
playeringame[i] = false;
|
||||||
playernode[i] = UINT8_MAX;
|
playernode[i] = UINT8_MAX;
|
||||||
|
memset(playeraddress[i], 0, sizeof(*playeraddress));
|
||||||
sprintf(player_names[i], "Player %d", i + 1);
|
sprintf(player_names[i], "Player %d", i + 1);
|
||||||
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
|
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
|
||||||
}
|
}
|
||||||
|
@ -3196,6 +3224,37 @@ void D_QuitNetGame(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static INT32 FindRejoinerNum(SINT8 node)
|
||||||
|
{
|
||||||
|
char strippednodeaddress[64];
|
||||||
|
const char *nodeaddress;
|
||||||
|
char *port;
|
||||||
|
INT32 i;
|
||||||
|
|
||||||
|
// Make sure there is no dead dress before proceeding to the stripping
|
||||||
|
if (!I_GetNodeAddress)
|
||||||
|
return -1;
|
||||||
|
nodeaddress = I_GetNodeAddress(node);
|
||||||
|
if (!nodeaddress)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Strip the address of its port
|
||||||
|
strcpy(strippednodeaddress, nodeaddress);
|
||||||
|
port = strchr(strippednodeaddress, ':');
|
||||||
|
if (port)
|
||||||
|
*port = '\0';
|
||||||
|
|
||||||
|
// Check if any player matches the stripped address
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX
|
||||||
|
&& !strcmp(playeraddress[i], strippednodeaddress))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Adds a node to the game (player will follow at map change or at savegame....)
|
// Adds a node to the game (player will follow at map change or at savegame....)
|
||||||
static inline void SV_AddNode(INT32 node)
|
static inline void SV_AddNode(INT32 node)
|
||||||
{
|
{
|
||||||
|
@ -3212,13 +3271,16 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
{
|
{
|
||||||
INT16 node, newplayernum;
|
INT16 node, newplayernum;
|
||||||
boolean splitscreenplayer;
|
boolean splitscreenplayer;
|
||||||
|
boolean rejoined;
|
||||||
|
player_t *newplayer;
|
||||||
|
char *port;
|
||||||
|
|
||||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
||||||
{
|
{
|
||||||
// protect against hacked/buggy client
|
// protect against hacked/buggy client
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3227,16 +3289,35 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
splitscreenplayer = newplayernum & 0x80;
|
splitscreenplayer = newplayernum & 0x80;
|
||||||
newplayernum &= ~0x80;
|
newplayernum &= ~0x80;
|
||||||
|
|
||||||
|
rejoined = playeringame[newplayernum];
|
||||||
|
|
||||||
|
if (!rejoined)
|
||||||
|
{
|
||||||
// Clear player before joining, lest some things get set incorrectly
|
// Clear player before joining, lest some things get set incorrectly
|
||||||
// HACK: don't do this for splitscreen, it relies on preset values
|
// HACK: don't do this for splitscreen, it relies on preset values
|
||||||
if (!splitscreen && !botingame)
|
if (!splitscreen && !botingame)
|
||||||
CL_ClearPlayer(newplayernum);
|
CL_ClearPlayer(newplayernum);
|
||||||
playeringame[newplayernum] = true;
|
playeringame[newplayernum] = true;
|
||||||
READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME);
|
|
||||||
G_AddPlayer(newplayernum);
|
G_AddPlayer(newplayernum);
|
||||||
if (newplayernum+1 > doomcom->numslots)
|
if (newplayernum+1 > doomcom->numslots)
|
||||||
doomcom->numslots = (INT16)(newplayernum+1);
|
doomcom->numslots = (INT16)(newplayernum+1);
|
||||||
|
|
||||||
|
if (server && I_GetNodeAddress)
|
||||||
|
{
|
||||||
|
strcpy(playeraddress[newplayernum], I_GetNodeAddress(node));
|
||||||
|
port = strchr(playeraddress[newplayernum], ':');
|
||||||
|
if (port)
|
||||||
|
*port = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newplayer = &players[newplayernum];
|
||||||
|
|
||||||
|
newplayer->jointime = 0;
|
||||||
|
newplayer->quittime = 0;
|
||||||
|
|
||||||
|
READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME);
|
||||||
|
|
||||||
// the server is creating my player
|
// the server is creating my player
|
||||||
if (node == mynode)
|
if (node == mynode)
|
||||||
{
|
{
|
||||||
|
@ -3253,28 +3334,66 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
||||||
secondarydisplayplayer = newplayernum;
|
secondarydisplayplayer = newplayernum;
|
||||||
DEBFILE("spawning my brother\n");
|
DEBFILE("spawning my brother\n");
|
||||||
if (botingame)
|
if (botingame)
|
||||||
players[newplayernum].bot = 1;
|
newplayer->bot = 1;
|
||||||
}
|
}
|
||||||
D_SendPlayerConfig();
|
D_SendPlayerConfig();
|
||||||
addedtogame = true;
|
addedtogame = true;
|
||||||
|
|
||||||
|
if (rejoined)
|
||||||
|
{
|
||||||
|
if (newplayer->mo)
|
||||||
|
{
|
||||||
|
if (!splitscreenplayer)
|
||||||
|
localangle = newplayer->mo->angle;
|
||||||
|
else
|
||||||
|
localangle2 = newplayer->mo->angle;
|
||||||
|
|
||||||
|
newplayer->viewheight = 41*newplayer->height/48;
|
||||||
|
|
||||||
|
if (newplayer->mo->eflags & MFE_VERTICALFLIP)
|
||||||
|
newplayer->viewz = newplayer->mo->z + newplayer->mo->height - newplayer->viewheight;
|
||||||
|
else
|
||||||
|
newplayer->viewz = newplayer->mo->z + newplayer->viewheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wake up the status bar
|
||||||
|
ST_Start();
|
||||||
|
// wake up the heads up text
|
||||||
|
HU_Start();
|
||||||
|
|
||||||
|
if (camera.chase && !splitscreenplayer)
|
||||||
|
P_ResetCamera(newplayer, &camera);
|
||||||
|
if (camera2.chase && splitscreenplayer)
|
||||||
|
P_ResetCamera(newplayer, &camera2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netgame)
|
if (netgame)
|
||||||
{
|
{
|
||||||
if (server && cv_showjoinaddress.value)
|
char joinmsg[256];
|
||||||
{
|
|
||||||
const char *address;
|
if (rejoined)
|
||||||
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
|
strcpy(joinmsg, M_GetText("\x82*%s has rejoined the game (player %d)"));
|
||||||
HU_AddChatText(va("\x82*%s has joined the game (player %d) (%s)", player_names[newplayernum], newplayernum, address), false); // merge join notification + IP to avoid clogging console/chat.
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
HU_AddChatText(va("\x82*%s has joined the game (player %d)", player_names[newplayernum], newplayernum), false); // if you don't wanna see the join address.
|
strcpy(joinmsg, M_GetText("\x82*%s has joined the game (player %d)"));
|
||||||
|
strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum));
|
||||||
|
|
||||||
|
// Merge join notification + IP to avoid clogging console/chat
|
||||||
|
if (server && cv_showjoinaddress.value && I_GetNodeAddress)
|
||||||
|
{
|
||||||
|
const char *address = I_GetNodeAddress(node);
|
||||||
|
if (address)
|
||||||
|
strcat(joinmsg, va(" (%s)", address));
|
||||||
|
}
|
||||||
|
|
||||||
|
HU_AddChatText(joinmsg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server && multiplayer && motd[0] != '\0')
|
if (server && multiplayer && motd[0] != '\0')
|
||||||
COM_BufAddText(va("sayto %d %s\n", newplayernum, motd));
|
COM_BufAddText(va("sayto %d %s\n", newplayernum, motd));
|
||||||
|
|
||||||
#ifdef HAVE_BLUA
|
#ifdef HAVE_BLUA
|
||||||
|
if (!rejoined)
|
||||||
LUAh_PlayerJoin(newplayernum);
|
LUAh_PlayerJoin(newplayernum);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -3284,11 +3403,7 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2)
|
||||||
INT32 node, n, newplayer = false;
|
INT32 node, n, newplayer = false;
|
||||||
UINT8 buf[2 + MAXPLAYERNAME];
|
UINT8 buf[2 + MAXPLAYERNAME];
|
||||||
UINT8 *p;
|
UINT8 *p;
|
||||||
UINT8 newplayernum = 0;
|
INT32 newplayernum;
|
||||||
|
|
||||||
// What is the reason for this? Why can't newplayernum always be 0?
|
|
||||||
if (dedicated)
|
|
||||||
newplayernum = 1;
|
|
||||||
|
|
||||||
for (node = 0; node < MAXNETNODES; node++)
|
for (node = 0; node < MAXNETNODES; node++)
|
||||||
{
|
{
|
||||||
|
@ -3297,68 +3412,22 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2)
|
||||||
{
|
{
|
||||||
newplayer = true;
|
newplayer = true;
|
||||||
|
|
||||||
if (netgame)
|
newplayernum = FindRejoinerNum(node);
|
||||||
// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
|
if (newplayernum == -1)
|
||||||
//
|
{
|
||||||
// The line just after that comment is an awful, horrible, terrible, TERRIBLE hack.
|
|
||||||
//
|
|
||||||
// Basically, the fix I did in order to fix the download freezes happens
|
|
||||||
// to cause situations in which a player number does not match
|
|
||||||
// the node number associated to that player.
|
|
||||||
// That is totally normal, there is absolutely *nothing* wrong with that.
|
|
||||||
// Really. Player 7 being tied to node 29, for instance, is totally fine.
|
|
||||||
//
|
|
||||||
// HOWEVER. A few (broken) parts of the netcode do the TERRIBLE mistake
|
|
||||||
// of mixing up the concepts of node and player, resulting in
|
|
||||||
// incorrect handling of cases where a player is tied to a node that has
|
|
||||||
// a different number (which is a totally normal case, or at least should be).
|
|
||||||
// This incorrect handling can go as far as literally
|
|
||||||
// anyone from joining your server at all, forever.
|
|
||||||
//
|
|
||||||
// Given those two facts, there are two options available
|
|
||||||
// in order to let this download freeze fix be:
|
|
||||||
// 1) Fix the broken parts that assume a node is a player or similar bullshit.
|
|
||||||
// 2) Change the part this comment is located at, so that any player who joins
|
|
||||||
// is given the same number as their associated node.
|
|
||||||
//
|
|
||||||
// No need to say, 1) is by far the obvious best, whereas 2) is a terrible hack.
|
|
||||||
// Unfortunately, after trying 1), I most likely didn't manage to find all
|
|
||||||
// of those broken parts, and thus 2) has become the only safe option that remains.
|
|
||||||
//
|
|
||||||
// So I did this hack.
|
|
||||||
//
|
|
||||||
// If it isn't clear enough, in order to get rid of this ugly hack,
|
|
||||||
// you will have to fix all parts of the netcode that
|
|
||||||
// make a confusion between nodes and players.
|
|
||||||
//
|
|
||||||
// And if it STILL isn't clear enough, a node and a player
|
|
||||||
// is NOT the same thing. Never. NEVER. *NEVER*.
|
|
||||||
//
|
|
||||||
// And if someday you make the terrible mistake of
|
|
||||||
// daring to have the unforgivable idea to try thinking
|
|
||||||
// that a node might possibly be the same as a player,
|
|
||||||
// or that a player should have the same number as its node,
|
|
||||||
// be sure that I will somehow know about it and
|
|
||||||
// hunt you down tirelessly and make you regret it,
|
|
||||||
// even if you live on the other side of the world.
|
|
||||||
//
|
|
||||||
// TODO: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
|
||||||
// \todo >>>>>>>>>> Remove this horrible hack as soon as possible <<<<<<<<<<
|
|
||||||
// TODO: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
//
|
|
||||||
// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
|
|
||||||
newplayernum = node; // OMFG SAY WELCOME TO TEH NEW HACK FOR FIX FIL DOWNLOAD!!1!
|
|
||||||
else // Don't use the hack if we don't have to
|
|
||||||
// search for a free playernum
|
// search for a free playernum
|
||||||
// we can't use playeringame since it is not updated here
|
// we can't use playeringame since it is not updated here
|
||||||
for (; newplayernum < MAXPLAYERS; newplayernum++)
|
for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++)
|
||||||
{
|
{
|
||||||
|
if (playeringame[newplayernum])
|
||||||
|
continue;
|
||||||
for (n = 0; n < MAXNETNODES; n++)
|
for (n = 0; n < MAXNETNODES; n++)
|
||||||
if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum)
|
if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum)
|
||||||
break;
|
break;
|
||||||
if (n == MAXNETNODES)
|
if (n == MAXNETNODES)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// should never happen since we check the playernum
|
// should never happen since we check the playernum
|
||||||
// before accepting the join
|
// before accepting the join
|
||||||
|
@ -3385,8 +3454,6 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2)
|
||||||
SendNetXCmd(XD_ADDPLAYER, &buf, p - buf);
|
SendNetXCmd(XD_ADDPLAYER, &buf, p - buf);
|
||||||
|
|
||||||
DEBFILE(va("Server added player %d node %d\n", newplayernum, node));
|
DEBFILE(va("Server added player %d node %d\n", newplayernum, node));
|
||||||
// use the next free slot (we can't put playeringame[newplayernum] = true here)
|
|
||||||
newplayernum++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3512,8 +3579,11 @@ static size_t TotalTextCmdPerTic(tic_t tic)
|
||||||
static void HandleConnect(SINT8 node)
|
static void HandleConnect(SINT8 node)
|
||||||
{
|
{
|
||||||
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1];
|
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1];
|
||||||
|
INT32 rejoinernum;
|
||||||
INT32 i;
|
INT32 i;
|
||||||
|
|
||||||
|
rejoinernum = FindRejoinerNum(node);
|
||||||
|
|
||||||
if (bannednode && bannednode[node])
|
if (bannednode && bannednode[node])
|
||||||
SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
|
SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
|
||||||
else if (netbuffer->u.clientcfg._255 != 255 ||
|
else if (netbuffer->u.clientcfg._255 != 255 ||
|
||||||
|
@ -3525,9 +3595,9 @@ static void HandleConnect(SINT8 node)
|
||||||
else if (netbuffer->u.clientcfg.version != VERSION
|
else if (netbuffer->u.clientcfg.version != VERSION
|
||||||
|| netbuffer->u.clientcfg.subversion != SUBVERSION)
|
|| netbuffer->u.clientcfg.subversion != SUBVERSION)
|
||||||
SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION));
|
SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION));
|
||||||
else if (!cv_allownewplayer.value && node)
|
else if (!cv_allownewplayer.value && node && rejoinernum == -1)
|
||||||
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment"));
|
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment"));
|
||||||
else if (D_NumPlayers() >= cv_maxplayers.value)
|
else if (D_NumPlayers() >= cv_maxplayers.value && rejoinernum == -1)
|
||||||
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value));
|
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value));
|
||||||
else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client?
|
else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client?
|
||||||
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
|
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
|
||||||
|
@ -3542,7 +3612,7 @@ static void HandleConnect(SINT8 node)
|
||||||
for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++)
|
for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++)
|
||||||
{
|
{
|
||||||
strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1);
|
strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1);
|
||||||
if (!EnsurePlayerNameIsGood(names[i], -1))
|
if (!EnsurePlayerNameIsGood(names[i], rejoinernum))
|
||||||
{
|
{
|
||||||
SV_SendRefuse(node, "Bad player name");
|
SV_SendRefuse(node, "Bad player name");
|
||||||
return;
|
return;
|
||||||
|
@ -3983,7 +4053,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendKick(netconsole, KICK_MSG_CON_FAIL);
|
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
|
DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
|
||||||
netconsole, realstart, consistancy[realstart%BACKUPTICS],
|
netconsole, realstart, consistancy[realstart%BACKUPTICS],
|
||||||
SHORT(netbuffer->u.clientpak.consistancy)));
|
SHORT(netbuffer->u.clientpak.consistancy)));
|
||||||
|
@ -4102,6 +4172,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
kickmsg = KICK_MSG_TIMEOUT;
|
kickmsg = KICK_MSG_TIMEOUT;
|
||||||
else
|
else
|
||||||
kickmsg = KICK_MSG_PLAYER_QUIT;
|
kickmsg = KICK_MSG_PLAYER_QUIT;
|
||||||
|
kickmsg |= KICK_MSG_KEEP_BODY;
|
||||||
|
|
||||||
SendKick(netconsole, kickmsg);
|
SendKick(netconsole, kickmsg);
|
||||||
nodetoplayer[node] = -1;
|
nodetoplayer[node] = -1;
|
||||||
|
@ -4123,7 +4194,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHEND", node);
|
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHEND", node);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(netconsole, KICK_MSG_CON_FAIL);
|
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
resynch_local_inprogress = false;
|
resynch_local_inprogress = false;
|
||||||
|
@ -4141,7 +4212,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node);
|
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(netconsole, KICK_MSG_CON_FAIL);
|
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4201,7 +4272,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHING", node);
|
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHING", node);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(netconsole, KICK_MSG_CON_FAIL);
|
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
resynch_local_inprogress = true;
|
resynch_local_inprogress = true;
|
||||||
|
@ -4213,7 +4284,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node);
|
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(netconsole, KICK_MSG_CON_FAIL);
|
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4237,7 +4308,7 @@ static void HandlePacketFromPlayer(SINT8 node)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node);
|
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(netconsole, KICK_MSG_CON_FAIL);
|
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (client)
|
if (client)
|
||||||
|
@ -4433,7 +4504,7 @@ static void CL_SendClientCmd(void)
|
||||||
packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16);
|
packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16);
|
||||||
HSendPacket(servernode, false, 0, packetsize);
|
HSendPacket(servernode, false, 0, packetsize);
|
||||||
}
|
}
|
||||||
else if (gamestate != GS_NULL)
|
else if (gamestate != GS_NULL && addedtogame)
|
||||||
{
|
{
|
||||||
G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1);
|
G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1);
|
||||||
netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]);
|
netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]);
|
||||||
|
@ -4609,6 +4680,11 @@ static void Local_Maketic(INT32 realtics)
|
||||||
localcmds.angleturn |= TICCMD_RECEIVED;
|
localcmds.angleturn |= TICCMD_RECEIVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function is utter bullshit and is responsible for
|
||||||
|
// the random desynch that happens when a player spawns.
|
||||||
|
// This is because ticcmds are resent to clients if a packet
|
||||||
|
// was dropped, and thus modifying them can lead to several
|
||||||
|
// clients having their ticcmds set to different values.
|
||||||
void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
|
void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
|
||||||
{
|
{
|
||||||
tic_t tic;
|
tic_t tic;
|
||||||
|
@ -4642,25 +4718,33 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
|
||||||
// create missed tic
|
// create missed tic
|
||||||
static void SV_Maketic(void)
|
static void SV_Maketic(void)
|
||||||
{
|
{
|
||||||
INT32 j;
|
|
||||||
|
|
||||||
for (j = 0; j < MAXNETNODES; j++)
|
|
||||||
if (playerpernode[j])
|
|
||||||
{
|
|
||||||
INT32 player = nodetoplayer[j];
|
|
||||||
if ((netcmds[maketic%BACKUPTICS][player].angleturn & TICCMD_RECEIVED) == 0)
|
|
||||||
{ // we didn't receive this tic
|
|
||||||
INT32 i;
|
INT32 i;
|
||||||
|
|
||||||
DEBFILE(va("MISS tic%4d for node %d\n", maketic, j));
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
#if defined(PARANOIA) && 0
|
|
||||||
CONS_Debug(DBG_NETPLAY, "Client Misstic %d\n", maketic);
|
|
||||||
#endif
|
|
||||||
// copy the old tic
|
|
||||||
for (i = 0; i < playerpernode[j]; i++, player = nodetoplayer2[j])
|
|
||||||
{
|
{
|
||||||
netcmds[maketic%BACKUPTICS][player] = netcmds[(maketic-1)%BACKUPTICS][player];
|
if (!playeringame[i])
|
||||||
netcmds[maketic%BACKUPTICS][player].angleturn &= ~TICCMD_RECEIVED;
|
continue;
|
||||||
|
|
||||||
|
// We didn't receive this tic
|
||||||
|
if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0)
|
||||||
|
{
|
||||||
|
ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i];
|
||||||
|
ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i];
|
||||||
|
|
||||||
|
if (players[i].quittime)
|
||||||
|
{
|
||||||
|
// Copy the angle/aiming from the previous tic
|
||||||
|
// and empty the other inputs
|
||||||
|
memset(ticcmd, 0, sizeof(netcmds[0][0]));
|
||||||
|
ticcmd->angleturn = prevticcmd->angleturn | TICCMD_RECEIVED;
|
||||||
|
ticcmd->aiming = prevticcmd->aiming;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBFILE(va("MISS tic%4d for player %d\n", maketic, i));
|
||||||
|
// Copy the input from the previous tic
|
||||||
|
*ticcmd = *prevticcmd;
|
||||||
|
ticcmd->angleturn &= ~TICCMD_RECEIVED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4785,7 +4869,7 @@ static inline void PingUpdate(void)
|
||||||
// ok your net has been bad for too long, you deserve to die.
|
// ok your net has been bad for too long, you deserve to die.
|
||||||
{
|
{
|
||||||
pingtimeout[i] = 0;
|
pingtimeout[i] = 0;
|
||||||
SendKick(i, KICK_MSG_PING_HIGH);
|
SendKick(i, KICK_MSG_PING_HIGH | KICK_MSG_KEEP_BODY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -485,6 +485,7 @@ extern consvar_t cv_playbackspeed;
|
||||||
#define KICK_MSG_PING_HIGH 6
|
#define KICK_MSG_PING_HIGH 6
|
||||||
#define KICK_MSG_CUSTOM_KICK 7
|
#define KICK_MSG_CUSTOM_KICK 7
|
||||||
#define KICK_MSG_CUSTOM_BAN 8
|
#define KICK_MSG_CUSTOM_BAN 8
|
||||||
|
#define KICK_MSG_KEEP_BODY 0x80
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -512,7 +513,9 @@ extern UINT32 realpingtable[MAXPLAYERS];
|
||||||
extern UINT32 playerpingtable[MAXPLAYERS];
|
extern UINT32 playerpingtable[MAXPLAYERS];
|
||||||
extern tic_t servermaxping;
|
extern tic_t servermaxping;
|
||||||
|
|
||||||
extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;
|
extern consvar_t cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_rejointimeout;
|
||||||
|
extern consvar_t cv_resynchattempts, cv_blamecfail;
|
||||||
|
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
|
||||||
|
|
||||||
// Used in d_net, the only dependence
|
// Used in d_net, the only dependence
|
||||||
tic_t ExpandTics(INT32 low);
|
tic_t ExpandTics(INT32 low);
|
||||||
|
|
|
@ -1045,10 +1045,8 @@ void D_SRB2Main(void)
|
||||||
I_OutputMsg("setvbuf didnt work\n");
|
I_OutputMsg("setvbuf didnt work\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GETTEXT
|
|
||||||
// initialise locale code
|
// initialise locale code
|
||||||
M_StartupLocale();
|
M_StartupLocale();
|
||||||
#endif
|
|
||||||
|
|
||||||
// get parameters from a response file (eg: srb2 @parms.txt)
|
// get parameters from a response file (eg: srb2 @parms.txt)
|
||||||
M_FindResponseFile();
|
M_FindResponseFile();
|
||||||
|
|
|
@ -579,6 +579,7 @@ void D_RegisterServerCommands(void)
|
||||||
|
|
||||||
// d_clisrv
|
// d_clisrv
|
||||||
CV_RegisterVar(&cv_maxplayers);
|
CV_RegisterVar(&cv_maxplayers);
|
||||||
|
CV_RegisterVar(&cv_rejointimeout);
|
||||||
CV_RegisterVar(&cv_resynchattempts);
|
CV_RegisterVar(&cv_resynchattempts);
|
||||||
CV_RegisterVar(&cv_maxsend);
|
CV_RegisterVar(&cv_maxsend);
|
||||||
CV_RegisterVar(&cv_noticedownload);
|
CV_RegisterVar(&cv_noticedownload);
|
||||||
|
@ -1124,7 +1125,7 @@ static void SetPlayerName(INT32 playernum, char *newname)
|
||||||
{
|
{
|
||||||
CONS_Printf(M_GetText("Player %d sent a bad name change\n"), playernum+1);
|
CONS_Printf(M_GetText("Player %d sent a bad name change\n"), playernum+1);
|
||||||
if (server && netgame)
|
if (server && netgame)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1199,7 +1200,7 @@ static INT32 snacpending = 0, snac2pending = 0, chmappending = 0;
|
||||||
//
|
//
|
||||||
static void SendNameAndColor(void)
|
static void SendNameAndColor(void)
|
||||||
{
|
{
|
||||||
char buf[MAXPLAYERNAME+2];
|
char buf[MAXPLAYERNAME+6];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
|
@ -1482,7 +1483,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
||||||
if (kick)
|
if (kick)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal color change received from %s (team: %d), color: %d)\n"), player_names[playernum], p->ctfteam, p->skincolor);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal color change received from %s (team: %d), color: %d)\n"), player_names[playernum], p->ctfteam, p->skincolor);
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2022,7 +2023,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal map change received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal map change received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2133,7 +2134,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal pause command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal pause command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2208,7 +2209,7 @@ static void Got_Suicide(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal suicide command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal suicide command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2271,7 +2272,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal clear scores command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal clear scores command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2618,7 +2619,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
||||||
// this should never happen unless the client is hacked/buggy
|
// this should never happen unless the client is hacked/buggy
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetPacket.packet.verification) // Special marker that the server sent the request
|
if (NetPacket.packet.verification) // Special marker that the server sent the request
|
||||||
|
@ -2627,7 +2628,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
playernum = NetPacket.packet.playernum;
|
playernum = NetPacket.packet.playernum;
|
||||||
|
@ -2660,7 +2661,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2719,7 +2720,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
||||||
if (server && ((NetPacket.packet.newteam < 0 || NetPacket.packet.newteam > 3) || error))
|
if (server && ((NetPacket.packet.newteam < 0 || NetPacket.packet.newteam > 3) || error))
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Safety first!
|
//Safety first!
|
||||||
|
@ -3011,7 +3012,7 @@ static void Got_Verification(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal verification received from %s (serverplayer is %s)\n"), player_names[playernum], player_names[serverplayer]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal verification received from %s (serverplayer is %s)\n"), player_names[playernum], player_names[serverplayer]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3061,7 +3062,7 @@ static void Got_Removal(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal demotion received from %s (serverplayer is %s)\n"), player_names[playernum], player_names[serverplayer]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal demotion received from %s (serverplayer is %s)\n"), player_names[playernum], player_names[serverplayer]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3135,7 +3136,7 @@ static void Got_MotD_f(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal motd change received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal motd change received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
Z_Free(mymotd);
|
Z_Free(mymotd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3191,7 +3192,7 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal runsoc command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal runsoc command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3349,7 +3350,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
||||||
if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick)
|
if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfile command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfile command received from %s\n"), player_names[playernum]);
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3398,7 +3399,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfile command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfile command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4191,7 +4192,7 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal exitlevel command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal exitlevel command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -510,6 +510,7 @@ typedef struct player_s
|
||||||
UINT8 bot;
|
UINT8 bot;
|
||||||
|
|
||||||
tic_t jointime; // Timer when player joins game to change skin/color
|
tic_t jointime; // Timer when player joins game to change skin/color
|
||||||
|
tic_t quittime; // Time elapsed since user disconnected, zero if connected
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
fixed_t fovadd; // adjust FOV for hw rendering
|
fixed_t fovadd; // adjust FOV for hw rendering
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1629,6 +1629,11 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
||||||
mapheaderinfo[num-1]->typeoflevel = tol;
|
mapheaderinfo[num-1]->typeoflevel = tol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (fastcmp(word, "KEYWORDS"))
|
||||||
|
{
|
||||||
|
deh_strlcpy(mapheaderinfo[num-1]->keywords, word2,
|
||||||
|
sizeof(mapheaderinfo[num-1]->keywords), va("Level header %d: keywords", num));
|
||||||
|
}
|
||||||
else if (fastcmp(word, "MUSIC"))
|
else if (fastcmp(word, "MUSIC"))
|
||||||
{
|
{
|
||||||
if (fastcmp(word2, "NONE"))
|
if (fastcmp(word2, "NONE"))
|
||||||
|
@ -6015,6 +6020,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
||||||
"S_SIGNSTOP",
|
"S_SIGNSTOP",
|
||||||
"S_SIGNBOARD",
|
"S_SIGNBOARD",
|
||||||
"S_EGGMANSIGN",
|
"S_EGGMANSIGN",
|
||||||
|
"S_CLEARSIGN",
|
||||||
|
|
||||||
// Spike Ball
|
// Spike Ball
|
||||||
"S_SPIKEBALL1",
|
"S_SPIKEBALL1",
|
||||||
|
@ -8841,7 +8847,7 @@ static const char *const MOBJEFLAG_LIST[] = {
|
||||||
|
|
||||||
#ifdef HAVE_BLUA
|
#ifdef HAVE_BLUA
|
||||||
static const char *const MAPTHINGFLAG_LIST[4] = {
|
static const char *const MAPTHINGFLAG_LIST[4] = {
|
||||||
NULL,
|
"EXTRA", // Extra flag for objects.
|
||||||
"OBJECTFLIP", // Reverse gravity flag for objects.
|
"OBJECTFLIP", // Reverse gravity flag for objects.
|
||||||
"OBJECTSPECIAL", // Special flag used with certain objects.
|
"OBJECTSPECIAL", // Special flag used with certain objects.
|
||||||
"AMBUSH" // Deaf monsters/do not react to sound.
|
"AMBUSH" // Deaf monsters/do not react to sound.
|
||||||
|
@ -9664,7 +9670,8 @@ struct {
|
||||||
{"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand!
|
{"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand!
|
||||||
{"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top.
|
{"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top.
|
||||||
{"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
|
{"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
|
||||||
{"FF_INTANGABLEFLATS",FF_INTANGABLEFLATS}, ///< Both flats are intangable, but the sides are still solid.
|
{"FF_INTANGIBLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangible, but the sides are still solid.
|
||||||
|
{"FF_INTANGABLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangable, but the sides are still solid.
|
||||||
{"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Bustable on mere touch.
|
{"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Bustable on mere touch.
|
||||||
{"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames.
|
{"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames.
|
||||||
{"FF_STRONGBUST",FF_STRONGBUST}, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee).
|
{"FF_STRONGBUST",FF_STRONGBUST}, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee).
|
||||||
|
|
|
@ -98,8 +98,8 @@
|
||||||
|
|
||||||
#ifdef GETTEXT
|
#ifdef GETTEXT
|
||||||
#include <libintl.h>
|
#include <libintl.h>
|
||||||
#include <locale.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
#include <locale.h> // locale should not be dependent on GETTEXT -- 11/01/20 Monster Iestyn
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -454,12 +454,12 @@ char savegamename[256];
|
||||||
// m_misc.h
|
// m_misc.h
|
||||||
#ifdef GETTEXT
|
#ifdef GETTEXT
|
||||||
#define M_GetText(String) gettext(String)
|
#define M_GetText(String) gettext(String)
|
||||||
void M_StartupLocale(void);
|
|
||||||
#else
|
#else
|
||||||
// If no translations are to be used, make a stub
|
// If no translations are to be used, make a stub
|
||||||
// M_GetText function that just returns the string.
|
// M_GetText function that just returns the string.
|
||||||
#define M_GetText(x) (x)
|
#define M_GetText(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
void M_StartupLocale(void);
|
||||||
extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL;
|
extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL;
|
||||||
char *va(const char *format, ...) FUNCPRINTF;
|
char *va(const char *format, ...) FUNCPRINTF;
|
||||||
char *M_GetToken(const char *inputString);
|
char *M_GetToken(const char *inputString);
|
||||||
|
@ -546,6 +546,8 @@ INT32 I_GetKey(void);
|
||||||
#define PATHSEP "/"
|
#define PATHSEP "/"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define PUNCTUATION "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
||||||
|
|
||||||
// Compile date and time and revision.
|
// Compile date and time and revision.
|
||||||
extern const char *compdate, *comptime, *comprevision, *compbranch;
|
extern const char *compdate, *comptime, *comprevision, *compbranch;
|
||||||
|
|
||||||
|
|
|
@ -289,6 +289,7 @@ typedef struct
|
||||||
UINT8 actnum; ///< Act number or 0 for none.
|
UINT8 actnum; ///< Act number or 0 for none.
|
||||||
UINT32 typeoflevel; ///< Combination of typeoflevel flags.
|
UINT32 typeoflevel; ///< Combination of typeoflevel flags.
|
||||||
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
|
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
|
||||||
|
char keywords[33]; ///< Keywords separated by space to search for. 32 characters.
|
||||||
char musname[7]; ///< Music track to play. "" for no music.
|
char musname[7]; ///< Music track to play. "" for no music.
|
||||||
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
|
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
|
||||||
UINT32 muspos; ///< Music position to jump to.
|
UINT32 muspos; ///< Music position to jump to.
|
||||||
|
|
|
@ -1165,6 +1165,7 @@ static const char *credits[] = {
|
||||||
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
|
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
|
||||||
"Wessel \"sphere\" Smit",
|
"Wessel \"sphere\" Smit",
|
||||||
"Ben \"Cue\" Woodford",
|
"Ben \"Cue\" Woodford",
|
||||||
|
"Ikaro \"Tatsuru\" Vinhas",
|
||||||
// Git contributors with 5+ approved merges of substantive quality,
|
// Git contributors with 5+ approved merges of substantive quality,
|
||||||
// or contributors with at least one groundbreaking merge, may be named.
|
// or contributors with at least one groundbreaking merge, may be named.
|
||||||
// Everyone else is acknowledged under "Special Thanks > SRB2 Community Contributors".
|
// Everyone else is acknowledged under "Special Thanks > SRB2 Community Contributors".
|
||||||
|
@ -1233,6 +1234,7 @@ static const char *credits[] = {
|
||||||
"Thomas \"Shadow Hog\" Igoe",
|
"Thomas \"Shadow Hog\" Igoe",
|
||||||
"Alexander \"DrTapeworm\" Moench-Ford",
|
"Alexander \"DrTapeworm\" Moench-Ford",
|
||||||
"\"Kaito Sinclaire\"",
|
"\"Kaito Sinclaire\"",
|
||||||
|
"\"QueenDelta\"",
|
||||||
"Wessel \"sphere\" Smit",
|
"Wessel \"sphere\" Smit",
|
||||||
"\"Spazzo\"",
|
"\"Spazzo\"",
|
||||||
"\"SSNTails\"",
|
"\"SSNTails\"",
|
||||||
|
|
147
src/g_game.c
147
src/g_game.c
|
@ -352,8 +352,8 @@ static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NUL
|
||||||
consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
// chatwidth
|
// chatwidth
|
||||||
static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {150, "MAX"}, {0, NULL}};
|
static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {300, "MAX"}, {0, NULL}};
|
||||||
consvar_t cv_chatwidth = {"chatwidth", "128", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_chatwidth = {"chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
// chatheight
|
// chatheight
|
||||||
static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}};
|
static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}};
|
||||||
|
@ -1140,7 +1140,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
INT32 *myaiming = (ssplayer == 1 ? &localaiming : &localaiming2);
|
INT32 *myaiming = (ssplayer == 1 ? &localaiming : &localaiming2);
|
||||||
|
|
||||||
angle_t drawangleoffset = (player->powers[pw_carry] == CR_ROLLOUT) ? ANGLE_180 : 0;
|
angle_t drawangleoffset = (player->powers[pw_carry] == CR_ROLLOUT) ? ANGLE_180 : 0;
|
||||||
INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, mousemove;
|
INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, turnmultiplier, mousemove;
|
||||||
controlstyle_e controlstyle = G_ControlStyle(ssplayer);
|
controlstyle_e controlstyle = G_ControlStyle(ssplayer);
|
||||||
INT32 *mx; INT32 *my; INT32 *mly;
|
INT32 *mx; INT32 *my; INT32 *mly;
|
||||||
|
|
||||||
|
@ -1163,6 +1163,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
alwaysfreelook = cv_alwaysfreelook.value;
|
alwaysfreelook = cv_alwaysfreelook.value;
|
||||||
usejoystick = cv_usejoystick.value;
|
usejoystick = cv_usejoystick.value;
|
||||||
invertmouse = cv_invertmouse.value;
|
invertmouse = cv_invertmouse.value;
|
||||||
|
turnmultiplier = cv_cam_turnmultiplier.value;
|
||||||
mousemove = cv_mousemove.value;
|
mousemove = cv_mousemove.value;
|
||||||
mx = &mousex;
|
mx = &mousex;
|
||||||
my = &mousey;
|
my = &mousey;
|
||||||
|
@ -1176,6 +1177,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
alwaysfreelook = cv_alwaysfreelook2.value;
|
alwaysfreelook = cv_alwaysfreelook2.value;
|
||||||
usejoystick = cv_usejoystick2.value;
|
usejoystick = cv_usejoystick2.value;
|
||||||
invertmouse = cv_invertmouse2.value;
|
invertmouse = cv_invertmouse2.value;
|
||||||
|
turnmultiplier = cv_cam2_turnmultiplier.value;
|
||||||
mousemove = cv_mousemove2.value;
|
mousemove = cv_mousemove2.value;
|
||||||
mx = &mouse2x;
|
mx = &mouse2x;
|
||||||
my = &mouse2y;
|
my = &mouse2y;
|
||||||
|
@ -1293,14 +1295,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
{
|
{
|
||||||
if (turnright && turnleft);
|
if (turnright && turnleft);
|
||||||
else if (turnright)
|
else if (turnright)
|
||||||
cmd->angleturn = (INT16)(cmd->angleturn - ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS));
|
cmd->angleturn = (INT16)(cmd->angleturn - ((angleturn[tspeed] * turnmultiplier)>>FRACBITS));
|
||||||
else if (turnleft)
|
else if (turnleft)
|
||||||
cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS));
|
cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * turnmultiplier)>>FRACBITS));
|
||||||
|
|
||||||
if (analogjoystickmove && lookjoystickvector.xaxis != 0)
|
if (analogjoystickmove && lookjoystickvector.xaxis != 0)
|
||||||
{
|
{
|
||||||
// JOYAXISRANGE should be 1023 (divide by 1024)
|
// JOYAXISRANGE should be 1023 (divide by 1024)
|
||||||
cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * cv_cam_turnmultiplier.value)>>FRACBITS)); // ANALOG!
|
cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * turnmultiplier)>>FRACBITS)); // ANALOG!
|
||||||
}
|
}
|
||||||
|
|
||||||
if (turnright || turnleft || abs(cmd->angleturn) > angleturn[2])
|
if (turnright || turnleft || abs(cmd->angleturn) > angleturn[2])
|
||||||
|
@ -2412,6 +2414,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
INT32 skin;
|
INT32 skin;
|
||||||
UINT32 availabilities;
|
UINT32 availabilities;
|
||||||
tic_t jointime;
|
tic_t jointime;
|
||||||
|
tic_t quittime;
|
||||||
boolean spectator;
|
boolean spectator;
|
||||||
boolean outofcoop;
|
boolean outofcoop;
|
||||||
INT16 bot;
|
INT16 bot;
|
||||||
|
@ -2425,6 +2428,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
ctfteam = players[player].ctfteam;
|
ctfteam = players[player].ctfteam;
|
||||||
exiting = players[player].exiting;
|
exiting = players[player].exiting;
|
||||||
jointime = players[player].jointime;
|
jointime = players[player].jointime;
|
||||||
|
quittime = players[player].quittime;
|
||||||
spectator = players[player].spectator;
|
spectator = players[player].spectator;
|
||||||
outofcoop = players[player].outofcoop;
|
outofcoop = players[player].outofcoop;
|
||||||
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
|
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
|
||||||
|
@ -2496,6 +2500,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
||||||
p->pflags = pflags;
|
p->pflags = pflags;
|
||||||
p->ctfteam = ctfteam;
|
p->ctfteam = ctfteam;
|
||||||
p->jointime = jointime;
|
p->jointime = jointime;
|
||||||
|
p->quittime = quittime;
|
||||||
p->spectator = spectator;
|
p->spectator = spectator;
|
||||||
p->outofcoop = outofcoop;
|
p->outofcoop = outofcoop;
|
||||||
|
|
||||||
|
@ -2649,73 +2654,24 @@ static boolean G_CheckSpot(INT32 playernum, mapthing_t *mthing)
|
||||||
// or a not-so-appropriate spot, if it initially fails
|
// or a not-so-appropriate spot, if it initially fails
|
||||||
// due to a lack of starts open or something.
|
// due to a lack of starts open or something.
|
||||||
//
|
//
|
||||||
void G_SpawnPlayer(INT32 playernum, boolean starpost)
|
void G_SpawnPlayer(INT32 playernum)
|
||||||
{
|
{
|
||||||
mapthing_t *spawnpoint;
|
|
||||||
|
|
||||||
if (!playeringame[playernum])
|
if (!playeringame[playernum])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
P_SpawnPlayer(playernum);
|
P_SpawnPlayer(playernum);
|
||||||
|
G_MovePlayerToSpawnOrStarpost(playernum);
|
||||||
|
#ifdef HAVE_BLUA
|
||||||
|
LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (starpost) //Don't even bother with looking for a place to spawn.
|
void G_MovePlayerToSpawnOrStarpost(INT32 playernum)
|
||||||
{
|
{
|
||||||
|
if (players[playernum].starposttime)
|
||||||
P_MovePlayerToStarpost(playernum);
|
P_MovePlayerToStarpost(playernum);
|
||||||
#ifdef HAVE_BLUA
|
|
||||||
LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :)
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- CTF --
|
|
||||||
// Order: CTF->DM->Coop
|
|
||||||
if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam)
|
|
||||||
{
|
|
||||||
if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start
|
|
||||||
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
|
|
||||||
spawnpoint = G_FindCoopStart(playernum); // fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- DM/Tag/CTF-spectator/etc --
|
|
||||||
// Order: DM->CTF->Coop
|
|
||||||
else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT))
|
|
||||||
{
|
|
||||||
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
|
|
||||||
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
|
|
||||||
spawnpoint = G_FindCoopStart(playernum); // fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Other game modes --
|
|
||||||
// Order: Coop->DM->CTF
|
|
||||||
else
|
else
|
||||||
{
|
P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum));
|
||||||
if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start
|
|
||||||
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
|
|
||||||
spawnpoint = G_FindCTFStart(playernum); // fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
//No spawns found. ANYWHERE.
|
|
||||||
if (!spawnpoint)
|
|
||||||
{
|
|
||||||
if (nummapthings)
|
|
||||||
{
|
|
||||||
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
|
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n"));
|
|
||||||
spawnpoint = &mapthings[0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
|
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n"));
|
|
||||||
//P_MovePlayerToSpawn handles this fine if the spawnpoint is NULL.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
P_MovePlayerToSpawn(playernum, spawnpoint);
|
|
||||||
|
|
||||||
#ifdef HAVE_BLUA
|
|
||||||
LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mapthing_t *G_FindCTFStart(INT32 playernum)
|
mapthing_t *G_FindCTFStart(INT32 playernum)
|
||||||
|
@ -2812,6 +2768,59 @@ mapthing_t *G_FindCoopStart(INT32 playernum)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mapthing_t *G_FindMapStart(INT32 playernum)
|
||||||
|
{
|
||||||
|
mapthing_t *spawnpoint;
|
||||||
|
|
||||||
|
if (!playeringame[playernum])
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// -- CTF --
|
||||||
|
// Order: CTF->DM->Coop
|
||||||
|
if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam)
|
||||||
|
{
|
||||||
|
if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start
|
||||||
|
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
|
||||||
|
spawnpoint = G_FindCoopStart(playernum); // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- DM/Tag/CTF-spectator/etc --
|
||||||
|
// Order: DM->CTF->Coop
|
||||||
|
else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT))
|
||||||
|
{
|
||||||
|
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
|
||||||
|
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
|
||||||
|
spawnpoint = G_FindCoopStart(playernum); // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Other game modes --
|
||||||
|
// Order: Coop->DM->CTF
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start
|
||||||
|
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
|
||||||
|
spawnpoint = G_FindCTFStart(playernum); // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
//No spawns found. ANYWHERE.
|
||||||
|
if (!spawnpoint)
|
||||||
|
{
|
||||||
|
if (nummapthings)
|
||||||
|
{
|
||||||
|
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
|
||||||
|
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n"));
|
||||||
|
spawnpoint = &mapthings[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
|
||||||
|
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return spawnpoint;
|
||||||
|
}
|
||||||
|
|
||||||
// Go back through all the projectiles and remove all references to the old
|
// Go back through all the projectiles and remove all references to the old
|
||||||
// player mobj, replacing them with the new one.
|
// player mobj, replacing them with the new one.
|
||||||
void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
|
void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
|
||||||
|
@ -2990,7 +2999,7 @@ void G_DoReborn(INT32 playernum)
|
||||||
{
|
{
|
||||||
if (!playeringame[i])
|
if (!playeringame[i])
|
||||||
continue;
|
continue;
|
||||||
G_SpawnPlayer(i, (players[i].starposttime));
|
G_SpawnPlayer(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore time in netgame (see also p_setup.c)
|
// restore time in netgame (see also p_setup.c)
|
||||||
|
@ -3036,7 +3045,7 @@ void G_DoReborn(INT32 playernum)
|
||||||
P_RemoveMobj(player->mo);
|
P_RemoveMobj(player->mo);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_SpawnPlayer(playernum, (player->starposttime));
|
G_SpawnPlayer(playernum);
|
||||||
if (oldmo)
|
if (oldmo)
|
||||||
G_ChangePlayerReferences(oldmo, players[playernum].mo);
|
G_ChangePlayerReferences(oldmo, players[playernum].mo);
|
||||||
}
|
}
|
||||||
|
@ -3078,7 +3087,6 @@ void G_AddPlayer(INT32 playernum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p->jointime = 0;
|
|
||||||
p->playerstate = PST_REBORN;
|
p->playerstate = PST_REBORN;
|
||||||
|
|
||||||
p->height = mobjinfo[MT_PLAYER].height;
|
p->height = mobjinfo[MT_PLAYER].height;
|
||||||
|
@ -3101,6 +3109,8 @@ boolean G_EnoughPlayersFinished(void)
|
||||||
{
|
{
|
||||||
if (!playeringame[i] || players[i].spectator || players[i].bot)
|
if (!playeringame[i] || players[i].spectator || players[i].bot)
|
||||||
continue;
|
continue;
|
||||||
|
if (players[i].quittime > 30 * TICRATE)
|
||||||
|
continue;
|
||||||
if (players[i].lives <= 0)
|
if (players[i].lives <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -4761,6 +4771,9 @@ INT32 G_FindMap(const char *mapname, char **foundmapnamep,
|
||||||
measurekeywords(&freq[freqc],
|
measurekeywords(&freq[freqc],
|
||||||
&freq[freqc].matchd, &freq[freqc].matchc,
|
&freq[freqc].matchd, &freq[freqc].matchc,
|
||||||
realmapname, mapname, wanttable);
|
realmapname, mapname, wanttable);
|
||||||
|
measurekeywords(&freq[freqc],
|
||||||
|
&freq[freqc].keywhd, &freq[freqc].keywhc,
|
||||||
|
mapheaderinfo[i]->keywords, mapname, wanttable);
|
||||||
if (freq[freqc].total)
|
if (freq[freqc].total)
|
||||||
freqc++;
|
freqc++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,9 @@ INT32 G_FindMapByNameOrCode(const char *query, char **foundmapnamep);
|
||||||
mapthing_t *G_FindCTFStart(INT32 playernum);
|
mapthing_t *G_FindCTFStart(INT32 playernum);
|
||||||
mapthing_t *G_FindMatchStart(INT32 playernum);
|
mapthing_t *G_FindMatchStart(INT32 playernum);
|
||||||
mapthing_t *G_FindCoopStart(INT32 playernum);
|
mapthing_t *G_FindCoopStart(INT32 playernum);
|
||||||
void G_SpawnPlayer(INT32 playernum, boolean starpost);
|
mapthing_t *G_FindMapStart(INT32 playernum);
|
||||||
|
void G_MovePlayerToSpawnOrStarpost(INT32 playernum);
|
||||||
|
void G_SpawnPlayer(INT32 playernum);
|
||||||
|
|
||||||
// Can be called by the startup code or M_Responder.
|
// Can be called by the startup code or M_Responder.
|
||||||
// A normal game starts at map 1, but a warp test can start elsewhere
|
// A normal game starts at map 1, but a warp test can start elsewhere
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "../i_system.h"
|
#include "../i_system.h"
|
||||||
#include "../m_cheat.h"
|
#include "../m_cheat.h"
|
||||||
#include "../f_finale.h"
|
#include "../f_finale.h"
|
||||||
|
#include "../r_things.h" // R_GetShadowZ
|
||||||
#ifdef ESLOPE
|
#ifdef ESLOPE
|
||||||
#include "../p_slopes.h"
|
#include "../p_slopes.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -4050,39 +4051,6 @@ static gr_vissprite_t *HWR_NewVisSprite(void)
|
||||||
return HWR_GetVisSprite(gr_visspritecount++);
|
return HWR_GetVisSprite(gr_visspritecount++);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GLBADSHADOWS
|
|
||||||
// Finds a floor through which light does not pass.
|
|
||||||
static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
|
|
||||||
{
|
|
||||||
const sector_t *sec = R_PointInSubsector(x, y)->sector;
|
|
||||||
fixed_t floorz = sec->floorheight;
|
|
||||||
|
|
||||||
if (sec->ffloors)
|
|
||||||
{
|
|
||||||
ffloor_t *rover;
|
|
||||||
fixed_t delta1, delta2;
|
|
||||||
const fixed_t thingtop = z + height;
|
|
||||||
|
|
||||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
|
||||||
{
|
|
||||||
if (!(rover->flags & FF_EXISTS)
|
|
||||||
|| !(rover->flags & FF_RENDERPLANES)
|
|
||||||
|| rover->flags & FF_TRANSLUCENT
|
|
||||||
|| rover->flags & FF_FOG
|
|
||||||
|| rover->flags & FF_INVERTPLANES)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
delta1 = z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
|
|
||||||
delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
|
|
||||||
if (*rover->topheight > floorz && abs(delta1) < abs(delta2))
|
|
||||||
floorz = *rover->topheight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return floorz;
|
|
||||||
}
|
|
||||||
#endif //#ifdef GLBADSHADOWS
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// HWR_DoCulling
|
// HWR_DoCulling
|
||||||
// Hardware version of R_DoCulling
|
// Hardware version of R_DoCulling
|
||||||
|
@ -4123,180 +4091,123 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GLBADSHADOWS
|
static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale)
|
||||||
static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale)
|
|
||||||
{
|
{
|
||||||
FOutVector swallVerts[4];
|
GLPatch_t *gpatch;
|
||||||
|
FOutVector shadowVerts[4];
|
||||||
FSurfaceInfo sSurf;
|
FSurfaceInfo sSurf;
|
||||||
fixed_t floorheight, mobjfloor;
|
float fscale; float fx; float fy; float offset;
|
||||||
float offset = 0;
|
UINT8 lightlevel = 255;
|
||||||
|
extracolormap_t *colormap = NULL;
|
||||||
|
UINT8 i;
|
||||||
|
|
||||||
mobjfloor = HWR_OpaqueFloorAtPos(
|
INT32 light;
|
||||||
spr->mobj->x, spr->mobj->y,
|
fixed_t scalemul;
|
||||||
spr->mobj->z, spr->mobj->height);
|
UINT16 alpha;
|
||||||
if (cv_shadowoffs.value)
|
fixed_t floordiff;
|
||||||
{
|
|
||||||
angle_t shadowdir;
|
|
||||||
|
|
||||||
// Set direction
|
|
||||||
if (splitscreen && stplyr == &players[secondarydisplayplayer])
|
|
||||||
shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value);
|
|
||||||
else
|
|
||||||
shadowdir = localangle + FixedAngle(cv_cam_rotate.value);
|
|
||||||
|
|
||||||
// Find floorheight
|
|
||||||
floorheight = HWR_OpaqueFloorAtPos(
|
|
||||||
spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - mobjfloor),
|
|
||||||
spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - mobjfloor),
|
|
||||||
spr->mobj->z, spr->mobj->height);
|
|
||||||
|
|
||||||
// The shadow is falling ABOVE it's mobj?
|
|
||||||
// Don't draw it, then!
|
|
||||||
if (spr->mobj->z < floorheight)
|
|
||||||
return;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fixed_t floorz;
|
fixed_t floorz;
|
||||||
floorz = HWR_OpaqueFloorAtPos(
|
fixed_t slopez;
|
||||||
spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight),
|
pslope_t *floorslope;
|
||||||
spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight),
|
|
||||||
spr->mobj->z, spr->mobj->height);
|
|
||||||
// The shadow would be falling on a wall? Don't draw it, then.
|
|
||||||
// Would draw midair otherwise.
|
|
||||||
if (floorz < floorheight)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
floorheight = FixedInt(spr->mobj->z - floorheight);
|
floorz = R_GetShadowZ(thing, &floorslope);
|
||||||
|
|
||||||
offset = floorheight;
|
//if (abs(floorz - gr_viewz) / tz > 4) return; // Prevent stretchy shadows and possible crashes
|
||||||
}
|
|
||||||
else
|
floordiff = abs(thing->z - floorz);
|
||||||
floorheight = FixedInt(spr->mobj->z - mobjfloor);
|
|
||||||
|
alpha = floordiff / (4*FRACUNIT) + 75;
|
||||||
|
if (alpha >= 255) return;
|
||||||
|
alpha = 255 - alpha;
|
||||||
|
|
||||||
|
gpatch = (GLPatch_t *)W_CachePatchName("DSHADOW", PU_CACHE);
|
||||||
|
if (!(gpatch && gpatch->mipmap->grInfo.format)) return;
|
||||||
|
HWR_GetPatch(gpatch);
|
||||||
|
|
||||||
|
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
|
||||||
|
scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height);
|
||||||
|
|
||||||
|
fscale = FIXED_TO_FLOAT(scalemul);
|
||||||
|
fx = FIXED_TO_FLOAT(thing->x);
|
||||||
|
fy = FIXED_TO_FLOAT(thing->y);
|
||||||
|
|
||||||
// create the sprite billboard
|
|
||||||
//
|
|
||||||
// 3--2
|
// 3--2
|
||||||
// | /|
|
// | /|
|
||||||
// |/ |
|
// |/ |
|
||||||
// 0--1
|
// 0--1
|
||||||
|
|
||||||
// x1/x2 were already scaled in HWR_ProjectSprite
|
if (thing && fabsf(fscale - 1.0f) > 1.0E-36f)
|
||||||
// First match the normal sprite
|
offset = (gpatch->height/2) * fscale;
|
||||||
swallVerts[0].x = swallVerts[3].x = spr->x1;
|
else
|
||||||
swallVerts[2].x = swallVerts[1].x = spr->x2;
|
offset = (float)(gpatch->height/2);
|
||||||
swallVerts[0].z = swallVerts[3].z = spr->z1;
|
|
||||||
swallVerts[2].z = swallVerts[1].z = spr->z2;
|
|
||||||
|
|
||||||
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f)
|
shadowVerts[0].x = shadowVerts[3].x = fx - offset;
|
||||||
|
shadowVerts[2].x = shadowVerts[1].x = fx + offset;
|
||||||
|
shadowVerts[0].z = shadowVerts[1].z = fy - offset;
|
||||||
|
shadowVerts[3].z = shadowVerts[2].z = fy + offset;
|
||||||
|
|
||||||
|
if (floorslope)
|
||||||
{
|
{
|
||||||
// Always a pixel above the floor, perfectly flat.
|
for (i = 0; i < 4; i++)
|
||||||
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3);
|
{
|
||||||
|
slopez = P_GetZAt(floorslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z));
|
||||||
// Now transform the TOP vertices along the floor in the direction of the camera
|
shadowVerts[i].y = FIXED_TO_FLOAT(slopez) + 0.05f;
|
||||||
swallVerts[3].x = spr->x1 + ((gpatch->height * this_scale) + offset) * gr_viewcos;
|
}
|
||||||
swallVerts[2].x = spr->x2 + ((gpatch->height * this_scale) + offset) * gr_viewcos;
|
|
||||||
swallVerts[3].z = spr->z1 + ((gpatch->height * this_scale) + offset) * gr_viewsin;
|
|
||||||
swallVerts[2].z = spr->z2 + ((gpatch->height * this_scale) + offset) * gr_viewsin;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Always a pixel above the floor, perfectly flat.
|
for (i = 0; i < 4; i++)
|
||||||
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3);
|
shadowVerts[i].y = FIXED_TO_FLOAT(floorz) + 0.05f;
|
||||||
|
|
||||||
// Now transform the TOP vertices along the floor in the direction of the camera
|
|
||||||
swallVerts[3].x = spr->x1 + (gpatch->height + offset) * gr_viewcos;
|
|
||||||
swallVerts[2].x = spr->x2 + (gpatch->height + offset) * gr_viewcos;
|
|
||||||
swallVerts[3].z = spr->z1 + (gpatch->height + offset) * gr_viewsin;
|
|
||||||
swallVerts[2].z = spr->z2 + (gpatch->height + offset) * gr_viewsin;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We also need to move the bottom ones away when shadowoffs is on
|
|
||||||
if (cv_shadowoffs.value)
|
|
||||||
{
|
|
||||||
swallVerts[0].x = spr->x1 + offset * gr_viewcos;
|
|
||||||
swallVerts[1].x = spr->x2 + offset * gr_viewcos;
|
|
||||||
swallVerts[0].z = spr->z1 + offset * gr_viewsin;
|
|
||||||
swallVerts[1].z = spr->z2 + offset * gr_viewsin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spr->flip)
|
if (spr->flip)
|
||||||
{
|
{
|
||||||
swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s;
|
shadowVerts[0].sow = shadowVerts[3].sow = gpatch->max_s;
|
||||||
swallVerts[2].sow = swallVerts[1].sow = 0;
|
shadowVerts[2].sow = shadowVerts[1].sow = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
swallVerts[0].sow = swallVerts[3].sow = 0;
|
shadowVerts[0].sow = shadowVerts[3].sow = 0;
|
||||||
swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s;
|
shadowVerts[2].sow = shadowVerts[1].sow = gpatch->max_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// flip the texture coords (look familiar?)
|
// flip the texture coords (look familiar?)
|
||||||
if (spr->vflip)
|
if (spr->vflip)
|
||||||
{
|
{
|
||||||
swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t;
|
shadowVerts[3].tow = shadowVerts[2].tow = gpatch->max_t;
|
||||||
swallVerts[0].tow = swallVerts[1].tow = 0;
|
shadowVerts[0].tow = shadowVerts[1].tow = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
swallVerts[3].tow = swallVerts[2].tow = 0;
|
shadowVerts[3].tow = shadowVerts[2].tow = 0;
|
||||||
swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t;
|
shadowVerts[0].tow = shadowVerts[1].tow = gpatch->max_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
sSurf.FlatColor.s.red = 0x00;
|
if (thing->subsector->sector->numlights)
|
||||||
sSurf.FlatColor.s.blue = 0x00;
|
|
||||||
sSurf.FlatColor.s.green = 0x00;
|
|
||||||
|
|
||||||
/*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW)
|
|
||||||
{
|
{
|
||||||
sector_t *sector = spr->mobj->subsector->sector;
|
light = R_GetPlaneLight(thing->subsector->sector, floorz, false); // Always use the light at the top instead of whatever I was doing before
|
||||||
UINT8 lightlevel = 255;
|
|
||||||
extracolormap_t *colormap = sector->extra_colormap;
|
|
||||||
|
|
||||||
if (sector->numlights)
|
lightlevel = *thing->subsector->sector->lightlist[light].lightlevel;
|
||||||
{
|
|
||||||
INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false);
|
|
||||||
|
|
||||||
if (!(spr->mobj->frame & FF_FULLBRIGHT))
|
if (*thing->subsector->sector->lightlist[light].extra_colormap)
|
||||||
lightlevel = *sector->lightlist[light].lightlevel;
|
colormap = *thing->subsector->sector->lightlist[light].extra_colormap;
|
||||||
|
|
||||||
if (*sector->lightlist[light].extra_colormap)
|
|
||||||
colormap = *sector->lightlist[light].extra_colormap;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lightlevel = sector->lightlevel;
|
lightlevel = thing->subsector->sector->lightlevel;
|
||||||
|
|
||||||
if (sector->extra_colormap)
|
if (thing->subsector->sector->extra_colormap)
|
||||||
colormap = sector->extra_colormap;
|
colormap = thing->subsector->sector->extra_colormap;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colormap)
|
if (colormap)
|
||||||
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true);
|
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
|
||||||
else
|
else
|
||||||
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true);
|
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
|
||||||
}*/
|
|
||||||
|
|
||||||
// shadow is always half as translucent as the sprite itself
|
sSurf.FlatColor.s.alpha = alpha;
|
||||||
if (!cv_translucency.value) // use default translucency (main sprite won't have any translucency)
|
|
||||||
sSurf.FlatColor.s.alpha = 0x80; // default
|
|
||||||
else if (spr->mobj->flags2 & MF2_SHADOW)
|
|
||||||
sSurf.FlatColor.s.alpha = 0x20;
|
|
||||||
else if (spr->mobj->frame & FF_TRANSMASK)
|
|
||||||
{
|
|
||||||
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf);
|
|
||||||
sSurf.FlatColor.s.alpha /= 2; //cut alpha in half!
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sSurf.FlatColor.s.alpha = 0x80; // default
|
|
||||||
|
|
||||||
if (sSurf.FlatColor.s.alpha > floorheight/4)
|
HWD.pfnDrawPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
|
||||||
{
|
|
||||||
sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4);
|
|
||||||
HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif //#ifdef GLBADSHADOWS
|
|
||||||
|
|
||||||
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
|
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
|
||||||
static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts)
|
static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts)
|
||||||
|
@ -4372,24 +4283,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
||||||
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
||||||
HWR_GetMappedPatch(gpatch, spr->colormap);
|
HWR_GetMappedPatch(gpatch, spr->colormap);
|
||||||
|
|
||||||
#ifdef GLBADSHADOWS
|
|
||||||
// Draw shadow BEFORE sprite
|
|
||||||
if (cv_shadow.value // Shadows enabled
|
|
||||||
&& (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
|
|
||||||
&& !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow.
|
|
||||||
#ifdef ALAM_LIGHTING
|
|
||||||
&& !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow.
|
|
||||||
&& (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players.
|
|
||||||
#endif
|
|
||||||
&& (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground.
|
|
||||||
{
|
|
||||||
////////////////////
|
|
||||||
// SHADOW SPRITE! //
|
|
||||||
////////////////////
|
|
||||||
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
|
|
||||||
}
|
|
||||||
#endif //#ifdef GLBADSHADOWS
|
|
||||||
|
|
||||||
baseWallVerts[0].x = baseWallVerts[3].x = spr->x1;
|
baseWallVerts[0].x = baseWallVerts[3].x = spr->x1;
|
||||||
baseWallVerts[2].x = baseWallVerts[1].x = spr->x2;
|
baseWallVerts[2].x = baseWallVerts[1].x = spr->x2;
|
||||||
baseWallVerts[0].z = baseWallVerts[3].z = spr->z1;
|
baseWallVerts[0].z = baseWallVerts[3].z = spr->z1;
|
||||||
|
@ -4776,24 +4669,6 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
||||||
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
||||||
HWR_GetMappedPatch(gpatch, spr->colormap);
|
HWR_GetMappedPatch(gpatch, spr->colormap);
|
||||||
|
|
||||||
#ifdef GLBADSHADOWS
|
|
||||||
// Draw shadow BEFORE sprite
|
|
||||||
if (cv_shadow.value // Shadows enabled
|
|
||||||
&& (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
|
|
||||||
&& !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow.
|
|
||||||
#ifdef ALAM_LIGHTING
|
|
||||||
&& !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow.
|
|
||||||
&& (!spr->mobj->player || spr->mobj->player->powers[pw_super])) // Except for non-super players.
|
|
||||||
#endif
|
|
||||||
&& (spr->mobj->z >= spr->mobj->floorz)) // Without this, your shadow shows on the floor, even after you die and fall through the ground.
|
|
||||||
{
|
|
||||||
////////////////////
|
|
||||||
// SHADOW SPRITE! //
|
|
||||||
////////////////////
|
|
||||||
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
|
|
||||||
}
|
|
||||||
#endif //#ifdef GLBADSHADOWS
|
|
||||||
|
|
||||||
// if it has a dispoffset, push it a little towards the camera
|
// if it has a dispoffset, push it a little towards the camera
|
||||||
if (spr->dispoffset) {
|
if (spr->dispoffset) {
|
||||||
float co = -gr_viewcos*(0.05f*spr->dispoffset);
|
float co = -gr_viewcos*(0.05f*spr->dispoffset);
|
||||||
|
@ -5407,6 +5282,12 @@ static void HWR_DrawSprites(void)
|
||||||
HWR_DrawPrecipitationSprite(spr);
|
HWR_DrawPrecipitationSprite(spr);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value)
|
||||||
|
{
|
||||||
|
HWR_DrawDropShadow(spr->mobj, spr, spr->mobj->shadowscale);
|
||||||
|
}
|
||||||
|
|
||||||
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||||
{
|
{
|
||||||
if (!cv_grmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f)
|
if (!cv_grmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f)
|
||||||
|
@ -5430,6 +5311,7 @@ static void HWR_DrawSprites(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "m_menu.h" // gametype_cons_t
|
#include "m_menu.h" // gametype_cons_t
|
||||||
#include "m_cond.h" // emblems
|
#include "m_cond.h" // emblems
|
||||||
|
#include "m_misc.h" // word jumping
|
||||||
|
|
||||||
#include "d_clisrv.h"
|
#include "d_clisrv.h"
|
||||||
|
|
||||||
|
@ -501,7 +502,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
||||||
// what we're gonna do now is check if the player exists
|
// what we're gonna do now is check if the player exists
|
||||||
// with that logic, characters 4 and 5 are our numbers:
|
// with that logic, characters 4 and 5 are our numbers:
|
||||||
const char *newmsg;
|
const char *newmsg;
|
||||||
char *playernum = (char*) malloc(3);
|
char playernum[3];
|
||||||
INT32 spc = 1; // used if playernum[1] is a space.
|
INT32 spc = 1; // used if playernum[1] is a space.
|
||||||
|
|
||||||
strncpy(playernum, msg+3, 3);
|
strncpy(playernum, msg+3, 3);
|
||||||
|
@ -515,23 +516,17 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
|
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
|
||||||
free(playernum);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// I'm very bad at C, I swear I am, additional checks eww!
|
// I'm very bad at C, I swear I am, additional checks eww!
|
||||||
if (spc != 0)
|
if (spc != 0 && msg[5] != ' ')
|
||||||
{
|
|
||||||
if (msg[5] != ' ')
|
|
||||||
{
|
{
|
||||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
|
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
|
||||||
free(playernum);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
target = atoi((const char*) playernum); // turn that into a number
|
target = atoi(playernum); // turn that into a number
|
||||||
free(playernum);
|
|
||||||
//CONS_Printf("%d\n", target);
|
//CONS_Printf("%d\n", target);
|
||||||
|
|
||||||
// check for target player, if it doesn't exist then we can't send the message!
|
// check for target player, if it doesn't exist then we can't send the message!
|
||||||
|
@ -659,7 +654,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
||||||
M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"),
|
M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"),
|
||||||
player_names[playernum]);
|
player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,7 +668,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal say command received from %s containing invalid characters\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal say command received from %s containing invalid characters\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1021,9 +1016,6 @@ void HU_Ticker(void)
|
||||||
#ifndef NONET
|
#ifndef NONET
|
||||||
|
|
||||||
static boolean teamtalk = false;
|
static boolean teamtalk = false;
|
||||||
/*static char chatchars[QUEUESIZE];
|
|
||||||
static INT32 head = 0, tail = 0;*/
|
|
||||||
// WHY DO YOU OVERCOMPLICATE EVERYTHING?????????
|
|
||||||
|
|
||||||
// Clear spaces so we don't end up with messages only made out of emptiness
|
// Clear spaces so we don't end up with messages only made out of emptiness
|
||||||
static boolean HU_clearChatSpaces(void)
|
static boolean HU_clearChatSpaces(void)
|
||||||
|
@ -1082,11 +1074,11 @@ static void HU_queueChatChar(char c)
|
||||||
|
|
||||||
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
|
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
|
||||||
{
|
{
|
||||||
INT32 spc = 1; // used if nodenum[1] is a space.
|
INT32 spc = 1; // used if playernum[1] is a space.
|
||||||
char *nodenum = (char*) malloc(3);
|
char playernum[3];
|
||||||
const char *newmsg;
|
const char *newmsg;
|
||||||
|
|
||||||
// what we're gonna do now is check if the node exists
|
// what we're gonna do now is check if the player exists
|
||||||
// with that logic, characters 4 and 5 are our numbers:
|
// with that logic, characters 4 and 5 are our numbers:
|
||||||
|
|
||||||
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
|
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
|
||||||
|
@ -1096,18 +1088,17 @@ static void HU_queueChatChar(char c)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(nodenum, msg+3, 3);
|
strncpy(playernum, msg+3, 3);
|
||||||
// check for undesirable characters in our "number"
|
// check for undesirable characters in our "number"
|
||||||
if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9')))
|
if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
|
||||||
{
|
{
|
||||||
// check if nodenum[1] is a space
|
// check if playernum[1] is a space
|
||||||
if (nodenum[1] == ' ')
|
if (playernum[1] == ' ')
|
||||||
spc = 0;
|
spc = 0;
|
||||||
// let it slide
|
// let it slide
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
|
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
|
||||||
free(nodenum);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1116,14 +1107,12 @@ static void HU_queueChatChar(char c)
|
||||||
{
|
{
|
||||||
if (msg[5] != ' ')
|
if (msg[5] != ' ')
|
||||||
{
|
{
|
||||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
|
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
|
||||||
free(nodenum);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target = atoi((const char*) nodenum); // turn that into a number
|
target = atoi(playernum); // turn that into a number
|
||||||
free(nodenum);
|
|
||||||
//CONS_Printf("%d\n", target);
|
//CONS_Printf("%d\n", target);
|
||||||
|
|
||||||
// check for target player, if it doesn't exist then we can't send the message!
|
// check for target player, if it doesn't exist then we can't send the message!
|
||||||
|
@ -1135,7 +1124,7 @@ static void HU_queueChatChar(char c)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to get rid of the /pm<node>
|
// we need to get rid of the /pm<player num>
|
||||||
newmsg = msg+5+spc;
|
newmsg = msg+5+spc;
|
||||||
strlcpy(msg, newmsg, 255);
|
strlcpy(msg, newmsg, 255);
|
||||||
}
|
}
|
||||||
|
@ -1337,9 +1326,19 @@ boolean HU_Responder(event_t *ev)
|
||||||
chat_scrolltime = 4;
|
chat_scrolltime = 4;
|
||||||
}
|
}
|
||||||
else if (c == KEY_LEFTARROW && c_input != 0 && !OLDCHAT) // i said go back
|
else if (c == KEY_LEFTARROW && c_input != 0 && !OLDCHAT) // i said go back
|
||||||
|
{
|
||||||
|
if (ctrldown)
|
||||||
|
c_input = M_JumpWordReverse(w_chat, c_input);
|
||||||
|
else
|
||||||
c_input--;
|
c_input--;
|
||||||
|
}
|
||||||
else if (c == KEY_RIGHTARROW && c_input < strlen(w_chat) && !OLDCHAT) // don't need to check for admin or w/e here since the chat won't ever contain anything if it's muted.
|
else if (c == KEY_RIGHTARROW && c_input < strlen(w_chat) && !OLDCHAT) // don't need to check for admin or w/e here since the chat won't ever contain anything if it's muted.
|
||||||
|
{
|
||||||
|
if (ctrldown)
|
||||||
|
c_input += M_JumpWord(&w_chat[c_input]);
|
||||||
|
else
|
||||||
c_input++;
|
c_input++;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1648,12 +1647,9 @@ static void HU_drawChatLog(INT32 offset)
|
||||||
}
|
}
|
||||||
chat_scrollmedown = false;
|
chat_scrollmedown = false;
|
||||||
|
|
||||||
// getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P
|
// getmaxscroll through a lazy hack. We do all these loops,
|
||||||
chat_maxscroll = (dy/charheight); // welcome to C, we don't know what min() and max() are.
|
// so let's not do more loops that are gonna lag the game more. :P
|
||||||
if (chat_maxscroll <= (UINT32)cv_chatheight.value)
|
chat_maxscroll = max(dy / charheight - cv_chatheight.value, 0);
|
||||||
chat_maxscroll = 0;
|
|
||||||
else
|
|
||||||
chat_maxscroll -= cv_chatheight.value;
|
|
||||||
|
|
||||||
// if we're not bound by the time, autoscroll for next frame:
|
// if we're not bound by the time, autoscroll for next frame:
|
||||||
if (atbottom)
|
if (atbottom)
|
||||||
|
@ -1794,21 +1790,17 @@ static void HU_DrawChat(void)
|
||||||
i = 0;
|
i = 0;
|
||||||
for(i=0; (i<MAXPLAYERS); i++)
|
for(i=0; (i<MAXPLAYERS); i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
// filter: (code needs optimization pls help I'm bad with C)
|
// filter: (code needs optimization pls help I'm bad with C)
|
||||||
if (w_chat[3])
|
if (w_chat[3])
|
||||||
{
|
{
|
||||||
char *nodenum;
|
char playernum[3];
|
||||||
UINT32 n;
|
UINT32 n;
|
||||||
// right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!)
|
// right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!)
|
||||||
if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' '))
|
if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' '))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
strncpy(playernum, w_chat+3, 3);
|
||||||
nodenum = (char*) malloc(3);
|
n = atoi(playernum); // turn that into a number
|
||||||
strncpy(nodenum, w_chat+3, 3);
|
|
||||||
n = atoi((const char*) nodenum); // turn that into a number
|
|
||||||
free(nodenum);
|
|
||||||
// special cases:
|
// special cases:
|
||||||
|
|
||||||
if ((n == 0) && !(w_chat[4] == '0'))
|
if ((n == 0) && !(w_chat[4] == '0'))
|
||||||
|
@ -1855,7 +1847,6 @@ static void HU_DrawChat(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
HU_drawChatLog(typelines-1); // typelines is the # of lines we're typing. If there's more than 1 then the log should scroll up to give us more space.
|
HU_drawChatLog(typelines-1); // typelines is the # of lines we're typing. If there's more than 1 then the log should scroll up to give us more space.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2378,7 +2369,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
||||||
|
|
||||||
if (!splitscreen) // don't draw it on splitscreen,
|
if (!splitscreen) // don't draw it on splitscreen,
|
||||||
{
|
{
|
||||||
if (!(tab[i].num == serverplayer))
|
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
|
||||||
HU_drawPing(x+ 253, y, playerpingtable[tab[i].num], false, 0);
|
HU_drawPing(x+ 253, y, playerpingtable[tab[i].num], false, 0);
|
||||||
//else
|
//else
|
||||||
// V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER");
|
// V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER");
|
||||||
|
@ -2577,7 +2568,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer)
|
||||||
V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
|
V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
|
||||||
if (!splitscreen)
|
if (!splitscreen)
|
||||||
{
|
{
|
||||||
if (!(tab[i].num == serverplayer))
|
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
|
||||||
HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
|
HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
|
||||||
//else
|
//else
|
||||||
//V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
|
//V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
|
||||||
|
@ -2701,7 +2692,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
|
||||||
V_DrawRightAlignedThinString(x+100, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
|
V_DrawRightAlignedThinString(x+100, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
|
||||||
if (!splitscreen)
|
if (!splitscreen)
|
||||||
{
|
{
|
||||||
if (!(tab[i].num == serverplayer))
|
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
|
||||||
HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
|
HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
|
||||||
//else
|
//else
|
||||||
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
|
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
|
||||||
|
@ -2732,7 +2723,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
|
||||||
supercheck = supercheckdef;
|
supercheck = supercheckdef;
|
||||||
|
|
||||||
strlcpy(name, tab[i].name, 7);
|
strlcpy(name, tab[i].name, 7);
|
||||||
if (!(tab[i].num == serverplayer))
|
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
|
||||||
HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
|
HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
|
||||||
//else
|
//else
|
||||||
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
|
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
|
||||||
|
@ -2840,7 +2831,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor
|
||||||
strlcpy(name, tab[i].name, 7);
|
strlcpy(name, tab[i].name, 7);
|
||||||
if (!splitscreen) // don't draw it on splitscreen,
|
if (!splitscreen) // don't draw it on splitscreen,
|
||||||
{
|
{
|
||||||
if (!(tab[i].num == serverplayer))
|
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
|
||||||
HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
|
HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
|
||||||
//else
|
//else
|
||||||
// V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
|
// V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
|
||||||
|
|
|
@ -1861,6 +1861,7 @@ state_t states[NUMSTATES] =
|
||||||
{SPR_SIGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNSTOP
|
{SPR_SIGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNSTOP
|
||||||
{SPR_SIGN, FF_PAPERSPRITE| 2, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNBOARD
|
{SPR_SIGN, FF_PAPERSPRITE| 2, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNBOARD
|
||||||
{SPR_SIGN, FF_PAPERSPRITE| 1, -1, {NULL}, 0, 29, S_NULL}, // S_EGGMANSIGN
|
{SPR_SIGN, FF_PAPERSPRITE| 1, -1, {NULL}, 0, 29, S_NULL}, // S_EGGMANSIGN
|
||||||
|
{SPR_SIGN, FF_PAPERSPRITE|18, -1, {NULL}, 0, 29, S_NULL}, // S_CLEARSIGN
|
||||||
|
|
||||||
// Spike Ball
|
// Spike Ball
|
||||||
{SPR_SPIK, 0, 1, {NULL}, 0, 0, S_SPIKEBALL2}, // S_SPIKEBALL1
|
{SPR_SPIK, 0, 1, {NULL}, 0, 0, S_SPIKEBALL2}, // S_SPIKEBALL1
|
||||||
|
@ -7850,7 +7851,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
MT_SPARK, // painchance
|
MT_SPARK, // painchance
|
||||||
sfx_s3kb8, // painsound
|
sfx_s3kb8, // painsound
|
||||||
S_EGGMANSIGN, // meleestate
|
S_EGGMANSIGN, // meleestate
|
||||||
S_NULL, // missilestate
|
S_CLEARSIGN, // missilestate
|
||||||
S_SIGNSTOP, // deathstate
|
S_SIGNSTOP, // deathstate
|
||||||
S_NULL, // xdeathstate
|
S_NULL, // xdeathstate
|
||||||
sfx_s3k64, // deathsound
|
sfx_s3k64, // deathsound
|
||||||
|
|
|
@ -2021,6 +2021,7 @@ typedef enum state
|
||||||
S_SIGNSTOP,
|
S_SIGNSTOP,
|
||||||
S_SIGNBOARD,
|
S_SIGNBOARD,
|
||||||
S_EGGMANSIGN,
|
S_EGGMANSIGN,
|
||||||
|
S_CLEARSIGN,
|
||||||
|
|
||||||
// Spike Ball
|
// Spike Ball
|
||||||
S_SPIKEBALL1,
|
S_SPIKEBALL1,
|
||||||
|
|
|
@ -2193,6 +2193,20 @@ static int lib_rPointInSubsector(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lib_rPointInSubsectorOrNil(lua_State *L)
|
||||||
|
{
|
||||||
|
fixed_t x = luaL_checkfixed(L, 1);
|
||||||
|
fixed_t y = luaL_checkfixed(L, 2);
|
||||||
|
subsector_t *sub = R_PointInSubsectorOrNull(x, y);
|
||||||
|
//HUDSAFE
|
||||||
|
INLEVEL
|
||||||
|
if (sub)
|
||||||
|
LUA_PushUserdata(L, sub, META_SUBSECTOR);
|
||||||
|
else
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// R_THINGS
|
// R_THINGS
|
||||||
////////////
|
////////////
|
||||||
|
|
||||||
|
@ -3127,6 +3141,7 @@ static luaL_Reg lib[] = {
|
||||||
{"R_PointToDist",lib_rPointToDist},
|
{"R_PointToDist",lib_rPointToDist},
|
||||||
{"R_PointToDist2",lib_rPointToDist2},
|
{"R_PointToDist2",lib_rPointToDist2},
|
||||||
{"R_PointInSubsector",lib_rPointInSubsector},
|
{"R_PointInSubsector",lib_rPointInSubsector},
|
||||||
|
{"R_PointInSubsectorOrNil",lib_rPointInSubsectorOrNil},
|
||||||
|
|
||||||
// r_things (sprite)
|
// r_things (sprite)
|
||||||
{"R_Char2Frame",lib_rChar2Frame},
|
{"R_Char2Frame",lib_rChar2Frame},
|
||||||
|
|
|
@ -87,7 +87,7 @@ deny:
|
||||||
|
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
|
CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
|
||||||
if (server)
|
if (server)
|
||||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper for COM_AddCommand commands
|
// Wrapper for COM_AddCommand commands
|
||||||
|
|
|
@ -102,7 +102,7 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
|
||||||
boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type
|
boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type
|
||||||
boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following
|
boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following
|
||||||
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
|
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
|
||||||
void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
|
void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player quitting
|
||||||
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
|
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
|
||||||
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
|
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
|
||||||
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode
|
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode
|
||||||
|
|
|
@ -1439,7 +1439,7 @@ UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj)
|
||||||
return shouldCollide;
|
return shouldCollide;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LUAh_PlayerQuit(player_t *plr, int reason)
|
void LUAh_PlayerQuit(player_t *plr, kickreason_t reason)
|
||||||
{
|
{
|
||||||
hook_p hookp;
|
hook_p hookp;
|
||||||
if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8))))
|
if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8))))
|
||||||
|
|
|
@ -2034,6 +2034,8 @@ static int mapheaderinfo_get(lua_State *L)
|
||||||
lua_pushinteger(L, header->typeoflevel);
|
lua_pushinteger(L, header->typeoflevel);
|
||||||
else if (fastcmp(field,"nextlevel"))
|
else if (fastcmp(field,"nextlevel"))
|
||||||
lua_pushinteger(L, header->nextlevel);
|
lua_pushinteger(L, header->nextlevel);
|
||||||
|
else if (fastcmp(field,"keywords"))
|
||||||
|
lua_pushstring(L, header->keywords);
|
||||||
else if (fastcmp(field,"musname"))
|
else if (fastcmp(field,"musname"))
|
||||||
lua_pushstring(L, header->musname);
|
lua_pushstring(L, header->musname);
|
||||||
else if (fastcmp(field,"mustrack"))
|
else if (fastcmp(field,"mustrack"))
|
||||||
|
|
|
@ -88,7 +88,8 @@ enum mobj_e {
|
||||||
#ifdef ESLOPE
|
#ifdef ESLOPE
|
||||||
mobj_standingslope,
|
mobj_standingslope,
|
||||||
#endif
|
#endif
|
||||||
mobj_colorized
|
mobj_colorized,
|
||||||
|
mobj_shadowscale
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *const mobj_opt[] = {
|
static const char *const mobj_opt[] = {
|
||||||
|
@ -156,6 +157,7 @@ static const char *const mobj_opt[] = {
|
||||||
"standingslope",
|
"standingslope",
|
||||||
#endif
|
#endif
|
||||||
"colorized",
|
"colorized",
|
||||||
|
"shadowscale",
|
||||||
NULL};
|
NULL};
|
||||||
|
|
||||||
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
|
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
|
||||||
|
@ -390,6 +392,9 @@ static int mobj_get(lua_State *L)
|
||||||
case mobj_colorized:
|
case mobj_colorized:
|
||||||
lua_pushboolean(L, mo->colorized);
|
lua_pushboolean(L, mo->colorized);
|
||||||
break;
|
break;
|
||||||
|
case mobj_shadowscale:
|
||||||
|
lua_pushfixed(L, mo->shadowscale);
|
||||||
|
break;
|
||||||
default: // extra custom variables in Lua memory
|
default: // extra custom variables in Lua memory
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||||
I_Assert(lua_istable(L, -1));
|
I_Assert(lua_istable(L, -1));
|
||||||
|
@ -719,6 +724,9 @@ static int mobj_set(lua_State *L)
|
||||||
case mobj_colorized:
|
case mobj_colorized:
|
||||||
mo->colorized = luaL_checkboolean(L, 3);
|
mo->colorized = luaL_checkboolean(L, 3);
|
||||||
break;
|
break;
|
||||||
|
case mobj_shadowscale:
|
||||||
|
mo->shadowscale = luaL_checkfixed(L, 3);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||||
I_Assert(lua_istable(L, -1));
|
I_Assert(lua_istable(L, -1));
|
||||||
|
|
|
@ -362,6 +362,8 @@ static int player_get(lua_State *L)
|
||||||
lua_pushinteger(L, plr->bot);
|
lua_pushinteger(L, plr->bot);
|
||||||
else if (fastcmp(field,"jointime"))
|
else if (fastcmp(field,"jointime"))
|
||||||
lua_pushinteger(L, plr->jointime);
|
lua_pushinteger(L, plr->jointime);
|
||||||
|
else if (fastcmp(field,"quittime"))
|
||||||
|
lua_pushinteger(L, plr->quittime);
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
else if (fastcmp(field,"fovadd"))
|
else if (fastcmp(field,"fovadd"))
|
||||||
lua_pushfixed(L, plr->fovadd);
|
lua_pushfixed(L, plr->fovadd);
|
||||||
|
@ -701,6 +703,8 @@ static int player_set(lua_State *L)
|
||||||
return NOSET;
|
return NOSET;
|
||||||
else if (fastcmp(field,"jointime"))
|
else if (fastcmp(field,"jointime"))
|
||||||
plr->jointime = (tic_t)luaL_checkinteger(L, 3);
|
plr->jointime = (tic_t)luaL_checkinteger(L, 3);
|
||||||
|
else if (fastcmp(field,"quittime"))
|
||||||
|
plr->quittime = (tic_t)luaL_checkinteger(L, 3);
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
else if (fastcmp(field,"fovadd"))
|
else if (fastcmp(field,"fovadd"))
|
||||||
plr->fovadd = luaL_checkfixed(L, 3);
|
plr->fovadd = luaL_checkfixed(L, 3);
|
||||||
|
|
|
@ -452,7 +452,7 @@ void Command_RTeleport_f(void)
|
||||||
else
|
else
|
||||||
inty = 0;
|
inty = 0;
|
||||||
|
|
||||||
ss = R_IsPointInSubsector(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT);
|
ss = R_PointInSubsectorOrNull(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT);
|
||||||
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
|
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
|
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
|
||||||
|
@ -530,7 +530,7 @@ void Command_Teleport_f(void)
|
||||||
inty = mt->y<<FRACBITS;
|
inty = mt->y<<FRACBITS;
|
||||||
offset = mt->z<<FRACBITS;
|
offset = mt->z<<FRACBITS;
|
||||||
|
|
||||||
ss = R_IsPointInSubsector(intx, inty);
|
ss = R_PointInSubsectorOrNull(intx, inty);
|
||||||
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
|
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_NOTICE, M_GetText("Spawnpoint not in a valid location.\n"));
|
CONS_Alert(CONS_NOTICE, M_GetText("Spawnpoint not in a valid location.\n"));
|
||||||
|
@ -597,7 +597,7 @@ void Command_Teleport_f(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ss = R_IsPointInSubsector(mo2->x, mo2->y);
|
ss = R_PointInSubsectorOrNull(mo2->x, mo2->y);
|
||||||
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
|
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_NOTICE, M_GetText("Starpost not in a valid location.\n"));
|
CONS_Alert(CONS_NOTICE, M_GetText("Starpost not in a valid location.\n"));
|
||||||
|
@ -653,7 +653,7 @@ void Command_Teleport_f(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ss = R_IsPointInSubsector(intx, inty);
|
ss = R_PointInSubsectorOrNull(intx, inty);
|
||||||
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
|
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
|
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
|
||||||
|
|
50
src/m_menu.c
50
src/m_menu.c
|
@ -1446,8 +1446,9 @@ static menuitem_t OP_SoundOptionsMenu[] =
|
||||||
{IT_HEADER, NULL, "Miscellaneous", NULL, 102},
|
{IT_HEADER, NULL, "Miscellaneous", NULL, 102},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Closed Captioning", &cv_closedcaptioning, 114},
|
{IT_STRING | IT_CVAR, NULL, "Closed Captioning", &cv_closedcaptioning, 114},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Reset Music Upon Dying", &cv_resetmusic, 124},
|
{IT_STRING | IT_CVAR, NULL, "Reset Music Upon Dying", &cv_resetmusic, 124},
|
||||||
|
{IT_STRING | IT_CVAR, NULL, "Default 1-Up sound", &cv_1upsound, 134},
|
||||||
|
|
||||||
{IT_STRING | IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 144},
|
{IT_STRING | IT_SUBMENU, NULL, "Advanced Settings...", &OP_SoundAdvancedDef, 154},
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_OPENMPT
|
#ifdef HAVE_OPENMPT
|
||||||
|
@ -1583,32 +1584,33 @@ static menuitem_t OP_ServerOptionsMenu[] =
|
||||||
{IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96},
|
{IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101},
|
{IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106},
|
{IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106},
|
||||||
|
{IT_STRING | IT_CVAR, NULL, "Post-goal free roaming", &cv_exitmove, 111},
|
||||||
|
|
||||||
{IT_HEADER, NULL, "Race, Competition", NULL, 115},
|
{IT_HEADER, NULL, "Race, Competition", NULL, 120},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 121},
|
{IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 126},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 126},
|
{IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 131},
|
||||||
|
|
||||||
{IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 135},
|
{IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 140},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 141},
|
{IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 146},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 146},
|
{IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 151},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 151},
|
{IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 156},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 156},
|
{IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 161},
|
||||||
|
|
||||||
{IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 166},
|
{IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 171},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 171},
|
{IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 176},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 176},
|
{IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 181},
|
||||||
|
|
||||||
{IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 186},
|
{IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 191},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 191},
|
{IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 196},
|
||||||
|
|
||||||
{IT_HEADER, NULL, "Teams", NULL, 200},
|
{IT_HEADER, NULL, "Teams", NULL, 205},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 206},
|
{IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 211},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 211},
|
{IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 216},
|
||||||
|
|
||||||
#ifndef NONET
|
#ifndef NONET
|
||||||
{IT_HEADER, NULL, "Advanced", NULL, 220},
|
{IT_HEADER, NULL, "Advanced", NULL, 225},
|
||||||
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 226},
|
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 231},
|
||||||
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 240},
|
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 245},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10631,8 +10633,8 @@ static void M_ServerOptions(INT32 choice)
|
||||||
OP_ServerOptionsMenu[ 2].status = IT_GRAYEDOUT; // Max players
|
OP_ServerOptionsMenu[ 2].status = IT_GRAYEDOUT; // Max players
|
||||||
OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading
|
OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading
|
||||||
OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join
|
OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join
|
||||||
OP_ServerOptionsMenu[34].status = IT_GRAYEDOUT; // Master server
|
OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Master server
|
||||||
OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Attempts to resynchronise
|
OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Attempts to resynchronise
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -10640,10 +10642,10 @@ static void M_ServerOptions(INT32 choice)
|
||||||
OP_ServerOptionsMenu[ 2].status = IT_STRING | IT_CVAR;
|
OP_ServerOptionsMenu[ 2].status = IT_STRING | IT_CVAR;
|
||||||
OP_ServerOptionsMenu[ 3].status = IT_STRING | IT_CVAR;
|
OP_ServerOptionsMenu[ 3].status = IT_STRING | IT_CVAR;
|
||||||
OP_ServerOptionsMenu[ 4].status = IT_STRING | IT_CVAR;
|
OP_ServerOptionsMenu[ 4].status = IT_STRING | IT_CVAR;
|
||||||
OP_ServerOptionsMenu[34].status = (netgame
|
OP_ServerOptionsMenu[35].status = (netgame
|
||||||
? IT_GRAYEDOUT
|
? IT_GRAYEDOUT
|
||||||
: (IT_STRING | IT_CVAR | IT_CV_STRING));
|
: (IT_STRING | IT_CVAR | IT_CV_STRING));
|
||||||
OP_ServerOptionsMenu[35].status = IT_STRING | IT_CVAR;
|
OP_ServerOptionsMenu[36].status = IT_STRING | IT_CVAR;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
43
src/m_misc.c
43
src/m_misc.c
|
@ -1600,10 +1600,13 @@ boolean M_ScreenshotResponder(event_t *ev)
|
||||||
#elif defined (_WIN32)
|
#elif defined (_WIN32)
|
||||||
#define GETTEXTDOMAIN1 "."
|
#define GETTEXTDOMAIN1 "."
|
||||||
#endif
|
#endif
|
||||||
|
#endif // GETTEXT
|
||||||
|
|
||||||
void M_StartupLocale(void)
|
void M_StartupLocale(void)
|
||||||
{
|
{
|
||||||
|
#ifdef GETTEXT
|
||||||
char *textdomhandle = NULL;
|
char *textdomhandle = NULL;
|
||||||
|
#endif //GETTEXT
|
||||||
|
|
||||||
CONS_Printf("M_StartupLocale...\n");
|
CONS_Printf("M_StartupLocale...\n");
|
||||||
|
|
||||||
|
@ -1612,6 +1615,7 @@ void M_StartupLocale(void)
|
||||||
// Do not set numeric locale as that affects atof
|
// Do not set numeric locale as that affects atof
|
||||||
setlocale(LC_NUMERIC, "C");
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
|
||||||
|
#ifdef GETTEXT
|
||||||
// FIXME: global name define anywhere?
|
// FIXME: global name define anywhere?
|
||||||
#ifdef GETTEXTDOMAIN1
|
#ifdef GETTEXTDOMAIN1
|
||||||
textdomhandle = bindtextdomain("srb2", GETTEXTDOMAIN1);
|
textdomhandle = bindtextdomain("srb2", GETTEXTDOMAIN1);
|
||||||
|
@ -1632,8 +1636,8 @@ void M_StartupLocale(void)
|
||||||
textdomain("srb2");
|
textdomain("srb2");
|
||||||
else
|
else
|
||||||
CONS_Printf("Could not find locale text domain!\n");
|
CONS_Printf("Could not find locale text domain!\n");
|
||||||
|
#endif //GETTEXT
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// MISC STRING FUNCTIONS
|
// MISC STRING FUNCTIONS
|
||||||
|
@ -2571,3 +2575,40 @@ void M_MkdirEach(const char *path, int start, int mode)
|
||||||
{
|
{
|
||||||
M_MkdirEachUntil(path, start, -1, mode);
|
M_MkdirEachUntil(path, start, -1, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int M_JumpWord(const char *line)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = line[0];
|
||||||
|
|
||||||
|
if (isspace(c))
|
||||||
|
return strspn(line, " ");
|
||||||
|
else if (ispunct(c))
|
||||||
|
return strspn(line, PUNCTUATION);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isspace(line[1]))
|
||||||
|
return 1 + strspn(&line[1], " ");
|
||||||
|
else
|
||||||
|
return strcspn(line, " "PUNCTUATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_JumpWordReverse(const char *line, int offset)
|
||||||
|
{
|
||||||
|
int (*is)(int);
|
||||||
|
int c;
|
||||||
|
c = line[--offset];
|
||||||
|
if (isspace(c))
|
||||||
|
is = isspace;
|
||||||
|
else if (ispunct(c))
|
||||||
|
is = ispunct;
|
||||||
|
else
|
||||||
|
is = isalnum;
|
||||||
|
c = (*is)(line[offset]);
|
||||||
|
while (offset > 0 &&
|
||||||
|
(*is)(line[offset - 1]) == c)
|
||||||
|
offset--;
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
|
@ -101,6 +101,14 @@ boolean M_IsPathAbsolute (const char *path);
|
||||||
void M_MkdirEach (const char *path, int start, int mode);
|
void M_MkdirEach (const char *path, int start, int mode);
|
||||||
void M_MkdirEachUntil (const char *path, int start, int end, int mode);
|
void M_MkdirEachUntil (const char *path, int start, int end, int mode);
|
||||||
|
|
||||||
|
/* Return offset to the first word in a string. */
|
||||||
|
/* E.g. cursor += M_JumpWord(line + cursor); */
|
||||||
|
int M_JumpWord (const char *s);
|
||||||
|
|
||||||
|
/* Return index of the last word behind offset bytes in a string. */
|
||||||
|
/* E.g. cursor = M_JumpWordReverse(line, cursor); */
|
||||||
|
int M_JumpWordReverse (const char *line, int offset);
|
||||||
|
|
||||||
// counting bits, for weapon ammo code, usually
|
// counting bits, for weapon ammo code, usually
|
||||||
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
|
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
|
||||||
|
|
||||||
|
|
60
src/mserv.c
60
src/mserv.c
|
@ -323,13 +323,9 @@ static INT32 GetServersList(void)
|
||||||
//
|
//
|
||||||
// MS_Connect()
|
// MS_Connect()
|
||||||
//
|
//
|
||||||
static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
|
#ifndef NONET
|
||||||
|
static INT32 MS_SubConnect(const char *ip_addr, const char *str_port, INT32 async, struct sockaddr *bindaddr, socklen_t bindaddrlen)
|
||||||
{
|
{
|
||||||
#ifdef NONET
|
|
||||||
(void)ip_addr;
|
|
||||||
(void)str_port;
|
|
||||||
(void)async;
|
|
||||||
#else
|
|
||||||
struct my_addrinfo *ai, *runp, hints;
|
struct my_addrinfo *ai, *runp, hints;
|
||||||
int gaie;
|
int gaie;
|
||||||
|
|
||||||
|
@ -355,6 +351,8 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
|
||||||
{
|
{
|
||||||
socket_fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
|
socket_fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
|
||||||
if (socket_fd != (SOCKET_TYPE)ERRSOCKET)
|
if (socket_fd != (SOCKET_TYPE)ERRSOCKET)
|
||||||
|
{
|
||||||
|
if (!bindaddr || bind(socket_fd, bindaddr, bindaddrlen) == 0)
|
||||||
{
|
{
|
||||||
if (async) // do asynchronous connection
|
if (async) // do asynchronous connection
|
||||||
{
|
{
|
||||||
|
@ -395,12 +393,60 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(socket_fd);
|
||||||
|
}
|
||||||
runp = runp->ai_next;
|
runp = runp->ai_next;
|
||||||
}
|
}
|
||||||
I_freeaddrinfo(ai);
|
I_freeaddrinfo(ai);
|
||||||
#endif
|
|
||||||
return MS_CONNECT_ERROR;
|
return MS_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
|
#endif/*NONET xd*/
|
||||||
|
|
||||||
|
static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
|
||||||
|
{
|
||||||
|
#ifdef NONET
|
||||||
|
(void)ip_addr;
|
||||||
|
(void)str_port;
|
||||||
|
(void)async;
|
||||||
|
return MS_CONNECT_ERROR;
|
||||||
|
#else
|
||||||
|
const char *lhost;
|
||||||
|
struct my_addrinfo hints;
|
||||||
|
struct my_addrinfo *ai, *aip;
|
||||||
|
int c;
|
||||||
|
if (M_CheckParm("-bindaddr") && ( lhost = M_GetNextParm() ))
|
||||||
|
{
|
||||||
|
memset (&hints, 0x00, sizeof(hints));
|
||||||
|
#ifdef AI_ADDRCONFIG
|
||||||
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
|
#endif
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
|
if (( c = I_getaddrinfo(lhost, 0, &hints, &ai) ) != 0)
|
||||||
|
{
|
||||||
|
CONS_Printf(
|
||||||
|
"mserv.c: bind to %s: %s\n",
|
||||||
|
lhost,
|
||||||
|
gai_strerror(c));
|
||||||
|
return MS_GETHOSTBYNAME_ERROR;
|
||||||
|
}
|
||||||
|
for (aip = ai; aip; aip = aip->ai_next)
|
||||||
|
{
|
||||||
|
c = MS_SubConnect(ip_addr, str_port, async, aip->ai_addr, aip->ai_addrlen);
|
||||||
|
if (c == 0)
|
||||||
|
{
|
||||||
|
I_freeaddrinfo(ai);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
I_freeaddrinfo(ai);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return MS_SubConnect(ip_addr, str_port, async, 0, 0);
|
||||||
|
#endif/*NONET xd*/
|
||||||
|
}
|
||||||
|
|
||||||
#define NUM_LIST_SERVER MAXSERVERLIST
|
#define NUM_LIST_SERVER MAXSERVERLIST
|
||||||
const msg_server_t *GetShortServersList(INT32 room)
|
const msg_server_t *GetShortServersList(INT32 room)
|
||||||
|
|
|
@ -746,6 +746,9 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
|
||||||
if (player->bot)
|
if (player->bot)
|
||||||
continue; // ignore bots
|
continue; // ignore bots
|
||||||
|
|
||||||
|
if (player->quittime)
|
||||||
|
continue; // Ignore uncontrolled bodies
|
||||||
|
|
||||||
if (dist > 0
|
if (dist > 0
|
||||||
&& P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist)
|
&& P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist)
|
||||||
continue; // Too far away
|
continue; // Too far away
|
||||||
|
@ -5177,6 +5180,8 @@ void A_SignPlayer(mobj_t *actor)
|
||||||
|
|
||||||
if (signcolor)
|
if (signcolor)
|
||||||
;
|
;
|
||||||
|
else if (!skin->sprites[SPR2_SIGN].numframes)
|
||||||
|
signcolor = facecolor;
|
||||||
else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
|
else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
|
||||||
signcolor = skin->prefoppositecolor;
|
signcolor = skin->prefoppositecolor;
|
||||||
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
|
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
|
||||||
|
@ -5187,13 +5192,11 @@ void A_SignPlayer(mobj_t *actor)
|
||||||
else if (locvar1 != -3) // set to a defined skin
|
else if (locvar1 != -3) // set to a defined skin
|
||||||
{
|
{
|
||||||
// I turned this function into a fucking mess. I'm so sorry. -Lach
|
// I turned this function into a fucking mess. I'm so sorry. -Lach
|
||||||
if (locvar1 == -2) // next skin
|
if (locvar1 == -2) // random skin
|
||||||
{
|
{
|
||||||
|
#define skincheck(num) (player ? !R_SkinUsable(player-players, num) : skins[num].availability > 0)
|
||||||
player_t *player = actor->target ? actor->target->player : NULL;
|
player_t *player = actor->target ? actor->target->player : NULL;
|
||||||
UINT8 skinnum;
|
UINT8 skinnum;
|
||||||
#define skincheck(num) (player ? !R_SkinUsable(player-players, num) : skins[num].availability > 0)
|
|
||||||
if (ov->skin == NULL) // pick a random skin to start with!
|
|
||||||
{
|
|
||||||
UINT8 skincount = 0;
|
UINT8 skincount = 0;
|
||||||
for (skincount = 0; skincount < numskins; skincount++)
|
for (skincount = 0; skincount < numskins; skincount++)
|
||||||
if (!skincheck(skincount))
|
if (!skincheck(skincount))
|
||||||
|
@ -5206,14 +5209,8 @@ void A_SignPlayer(mobj_t *actor)
|
||||||
if (skincheck(skincount))
|
if (skincheck(skincount))
|
||||||
skinnum++;
|
skinnum++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else // otherwise, advance 1 skin
|
|
||||||
{
|
|
||||||
skinnum = (skin_t*)ov->skin-skins;
|
|
||||||
while ((skinnum = (skinnum + 1) % numskins) && skincheck(skinnum));
|
|
||||||
}
|
|
||||||
#undef skincheck
|
|
||||||
skin = &skins[skinnum];
|
skin = &skins[skinnum];
|
||||||
|
#undef skincheck
|
||||||
}
|
}
|
||||||
else // specific skin
|
else // specific skin
|
||||||
skin = &skins[locvar1];
|
skin = &skins[locvar1];
|
||||||
|
@ -5221,21 +5218,33 @@ void A_SignPlayer(mobj_t *actor)
|
||||||
facecolor = skin->prefcolor;
|
facecolor = skin->prefcolor;
|
||||||
if (signcolor)
|
if (signcolor)
|
||||||
;
|
;
|
||||||
|
else if (!skin->sprites[SPR2_SIGN].numframes)
|
||||||
|
signcolor = facecolor;
|
||||||
else if (skin->prefoppositecolor)
|
else if (skin->prefoppositecolor)
|
||||||
signcolor = skin->prefoppositecolor;
|
signcolor = skin->prefoppositecolor;
|
||||||
else if (facecolor)
|
else if (facecolor)
|
||||||
signcolor = Color_Opposite[facecolor - 1][0];
|
signcolor = Color_Opposite[facecolor - 1][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin && skin->sprites[SPR2_SIGN].numframes) // player face
|
if (skin)
|
||||||
|
{
|
||||||
|
if (skin->sprites[SPR2_SIGN].numframes) // player face
|
||||||
{
|
{
|
||||||
ov->color = facecolor;
|
ov->color = facecolor;
|
||||||
ov->skin = skin;
|
ov->skin = skin;
|
||||||
P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN
|
P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN
|
||||||
}
|
}
|
||||||
|
else // CLEAR! sign
|
||||||
|
{
|
||||||
|
ov->color = SKINCOLOR_NONE;
|
||||||
|
ov->skin = NULL; // needs to be NULL in the case of SF_HIRES characters
|
||||||
|
P_SetMobjState(ov, actor->info->missilestate); // S_CLEARSIGN
|
||||||
|
}
|
||||||
|
}
|
||||||
else // Eggman face
|
else // Eggman face
|
||||||
{
|
{
|
||||||
ov->color = SKINCOLOR_NONE;
|
ov->color = SKINCOLOR_NONE;
|
||||||
|
ov->skin = NULL;
|
||||||
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
|
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
|
||||||
if (!signcolor)
|
if (!signcolor)
|
||||||
signcolor = SKINCOLOR_CARBON;
|
signcolor = SKINCOLOR_CARBON;
|
||||||
|
|
|
@ -1869,6 +1869,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||||
|
|
||||||
S_StartSound(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings
|
S_StartSound(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings
|
||||||
P_KillMobj(special, NULL, toucher, 0);
|
P_KillMobj(special, NULL, toucher, 0);
|
||||||
|
special->shadowscale = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prints death messages relating to a dying or hit player.
|
/** Prints death messages relating to a dying or hit player.
|
||||||
|
@ -2256,9 +2257,9 @@ void P_CheckSurvivors(void)
|
||||||
{
|
{
|
||||||
if (players[i].spectator)
|
if (players[i].spectator)
|
||||||
spectators++;
|
spectators++;
|
||||||
else if (players[i].pflags & PF_TAGIT)
|
else if ((players[i].pflags & PF_TAGIT) && players[i].quittime < 30 * TICRATE)
|
||||||
taggers++;
|
taggers++;
|
||||||
else if (!(players[i].pflags & PF_GAMETYPEOVER))
|
else if (!(players[i].pflags & PF_GAMETYPEOVER) && players[i].quittime < 30 * TICRATE)
|
||||||
{
|
{
|
||||||
survivorarray[survivors] = i;
|
survivorarray[survivors] = i;
|
||||||
survivors++;
|
survivors++;
|
||||||
|
|
|
@ -643,7 +643,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
||||||
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
|
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
|
||||||
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
|
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
|
||||||
|
|
||||||
if (delta1 >= delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_PLATFORM) // thing is below FOF
|
if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF
|
||||||
{
|
{
|
||||||
if (bottomheight < opentop) {
|
if (bottomheight < opentop) {
|
||||||
opentop = bottomheight;
|
opentop = bottomheight;
|
||||||
|
@ -656,7 +656,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
||||||
highceiling = bottomheight;
|
highceiling = bottomheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delta1 < delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
|
if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
|
||||||
{
|
{
|
||||||
if (topheight > openbottom) {
|
if (topheight > openbottom) {
|
||||||
openbottom = topheight;
|
openbottom = topheight;
|
||||||
|
@ -689,7 +689,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
||||||
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
|
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
|
||||||
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
|
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
|
||||||
|
|
||||||
if (delta1 >= delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_PLATFORM) // thing is below FOF
|
if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF
|
||||||
{
|
{
|
||||||
if (bottomheight < opentop) {
|
if (bottomheight < opentop) {
|
||||||
opentop = bottomheight;
|
opentop = bottomheight;
|
||||||
|
@ -702,7 +702,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
||||||
highceiling = bottomheight;
|
highceiling = bottomheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delta1 < delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
|
if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
|
||||||
{
|
{
|
||||||
if (topheight > openbottom) {
|
if (topheight > openbottom) {
|
||||||
openbottom = topheight;
|
openbottom = topheight;
|
||||||
|
|
24
src/p_mobj.c
24
src/p_mobj.c
|
@ -3400,7 +3400,7 @@ void P_MobjCheckWater(mobj_t *mobj)
|
||||||
if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability])))
|
if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability])))
|
||||||
{
|
{
|
||||||
boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC);
|
boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC);
|
||||||
if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER)))
|
if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER) && !(mobj->eflags & MFE_TOUCHLAVA)))
|
||||||
{ // Water removes electric and non-water fire shields...
|
{ // Water removes electric and non-water fire shields...
|
||||||
P_FlashPal(p,
|
P_FlashPal(p,
|
||||||
electric
|
electric
|
||||||
|
@ -3906,11 +3906,15 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
|
||||||
mobj->z += mobj->momz;
|
mobj->z += mobj->momz;
|
||||||
P_SetThingPosition(mobj);
|
P_SetThingPosition(mobj);
|
||||||
P_CheckPosition(mobj, mobj->x, mobj->y);
|
P_CheckPosition(mobj, mobj->x, mobj->y);
|
||||||
|
mobj->floorz = tmfloorz;
|
||||||
|
mobj->ceilingz = tmceilingz;
|
||||||
goto animonly;
|
goto animonly;
|
||||||
}
|
}
|
||||||
else if (mobj->player->powers[pw_carry] == CR_MACESPIN)
|
else if (mobj->player->powers[pw_carry] == CR_MACESPIN)
|
||||||
{
|
{
|
||||||
P_CheckPosition(mobj, mobj->x, mobj->y);
|
P_CheckPosition(mobj, mobj->x, mobj->y);
|
||||||
|
mobj->floorz = tmfloorz;
|
||||||
|
mobj->ceilingz = tmceilingz;
|
||||||
goto animonly;
|
goto animonly;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10557,6 +10561,22 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
||||||
else
|
else
|
||||||
mobj->z = z;
|
mobj->z = z;
|
||||||
|
|
||||||
|
// Set shadowscale here, before spawn hook so that Lua can change it
|
||||||
|
if (
|
||||||
|
type == MT_PLAYER ||
|
||||||
|
type == MT_ROLLOUTROCK ||
|
||||||
|
type == MT_EGGMOBILE4_MACE ||
|
||||||
|
(type >= MT_SMALLMACE && type <= MT_REDSPRINGBALL) ||
|
||||||
|
(mobj->flags & (MF_ENEMY|MF_BOSS))
|
||||||
|
)
|
||||||
|
mobj->shadowscale = FRACUNIT;
|
||||||
|
else if (
|
||||||
|
type >= MT_RING && type <= MT_FLINGEMERALD && type != MT_EMERALDSPAWN
|
||||||
|
)
|
||||||
|
mobj->shadowscale = 2*FRACUNIT/3;
|
||||||
|
else
|
||||||
|
mobj->shadowscale = 0;
|
||||||
|
|
||||||
#ifdef HAVE_BLUA
|
#ifdef HAVE_BLUA
|
||||||
// DANGER! This can cause P_SpawnMobj to return NULL!
|
// DANGER! This can cause P_SpawnMobj to return NULL!
|
||||||
// Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks!
|
// Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks!
|
||||||
|
@ -11098,7 +11118,7 @@ void P_SpawnPrecipitation(void)
|
||||||
x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3);
|
x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3);
|
||||||
y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3);
|
y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3);
|
||||||
|
|
||||||
precipsector = R_IsPointInSubsector(x, y);
|
precipsector = R_PointInSubsectorOrNull(x, y);
|
||||||
|
|
||||||
// No sector? Stop wasting time,
|
// No sector? Stop wasting time,
|
||||||
// move on to the next entry in the blockmap
|
// move on to the next entry in the blockmap
|
||||||
|
|
|
@ -375,6 +375,7 @@ typedef struct mobj_s
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
boolean colorized; // Whether the mobj uses the rainbow colormap
|
boolean colorized; // Whether the mobj uses the rainbow colormap
|
||||||
|
fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius
|
||||||
|
|
||||||
// WARNING: New fields must be added separately to savegame and Lua.
|
// WARNING: New fields must be added separately to savegame and Lua.
|
||||||
} mobj_t;
|
} mobj_t;
|
||||||
|
|
|
@ -255,6 +255,7 @@ static void P_NetArchivePlayers(void)
|
||||||
WRITEINT32(save_p, players[i].onconveyor);
|
WRITEINT32(save_p, players[i].onconveyor);
|
||||||
|
|
||||||
WRITEUINT32(save_p, players[i].jointime);
|
WRITEUINT32(save_p, players[i].jointime);
|
||||||
|
WRITEUINT32(save_p, players[i].quittime);
|
||||||
|
|
||||||
WRITEUINT16(save_p, flags);
|
WRITEUINT16(save_p, flags);
|
||||||
|
|
||||||
|
@ -446,6 +447,7 @@ static void P_NetUnArchivePlayers(void)
|
||||||
players[i].onconveyor = READINT32(save_p);
|
players[i].onconveyor = READINT32(save_p);
|
||||||
|
|
||||||
players[i].jointime = READUINT32(save_p);
|
players[i].jointime = READUINT32(save_p);
|
||||||
|
players[i].quittime = READUINT32(save_p);
|
||||||
|
|
||||||
flags = READUINT16(save_p);
|
flags = READUINT16(save_p);
|
||||||
|
|
||||||
|
|
|
@ -222,6 +222,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
|
||||||
mapheaderinfo[num]->typeoflevel = 0;
|
mapheaderinfo[num]->typeoflevel = 0;
|
||||||
mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
|
mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
|
||||||
mapheaderinfo[num]->startrings = 0;
|
mapheaderinfo[num]->startrings = 0;
|
||||||
|
mapheaderinfo[num]->keywords[0] = '\0';
|
||||||
snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
|
snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
|
||||||
mapheaderinfo[num]->musname[6] = 0;
|
mapheaderinfo[num]->musname[6] = 0;
|
||||||
mapheaderinfo[num]->mustrack = 0;
|
mapheaderinfo[num]->mustrack = 0;
|
||||||
|
@ -3096,7 +3097,7 @@ static void P_InitTagGametype(void)
|
||||||
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
|
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && !players[i].spectator)
|
if (playeringame[i] && !(players[i].spectator && players[i].quittime))
|
||||||
{
|
{
|
||||||
playersactive[realnumplayers] = i; //stores the player's node in the array.
|
playersactive[realnumplayers] = i; //stores the player's node in the array.
|
||||||
realnumplayers++;
|
realnumplayers++;
|
||||||
|
@ -3118,7 +3119,7 @@ static void P_InitTagGametype(void)
|
||||||
if (players[playersactive[i]].mo)
|
if (players[playersactive[i]].mo)
|
||||||
P_RemoveMobj(players[playersactive[i]].mo);
|
P_RemoveMobj(players[playersactive[i]].mo);
|
||||||
|
|
||||||
G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location.
|
G_SpawnPlayer(playersactive[i]); //respawn the lucky player in his dedicated spawn location.
|
||||||
}
|
}
|
||||||
|
|
||||||
static void P_SetupCamera(void)
|
static void P_SetupCamera(void)
|
||||||
|
@ -3296,7 +3297,7 @@ static void P_InitPlayers(void)
|
||||||
G_DoReborn(i);
|
G_DoReborn(i);
|
||||||
else // gametype is GT_COOP or GT_RACE
|
else // gametype is GT_COOP or GT_RACE
|
||||||
{
|
{
|
||||||
G_SpawnPlayer(i, players[i].starposttime);
|
G_SpawnPlayer(i);
|
||||||
if (players[i].starposttime)
|
if (players[i].starposttime)
|
||||||
P_ClearStarPost(players[i].starpostnum);
|
P_ClearStarPost(players[i].starpostnum);
|
||||||
}
|
}
|
||||||
|
|
10
src/p_spec.c
10
src/p_spec.c
|
@ -4426,9 +4426,17 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
|
||||||
case 6: // Death Pit (Camera Mod)
|
case 6: // Death Pit (Camera Mod)
|
||||||
case 7: // Death Pit (No Camera Mod)
|
case 7: // Death Pit (No Camera Mod)
|
||||||
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
|
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
|
||||||
|
{
|
||||||
|
if (player->quittime)
|
||||||
|
G_MovePlayerToSpawnOrStarpost(player - players);
|
||||||
|
else
|
||||||
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
|
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 8: // Instant Kill
|
case 8: // Instant Kill
|
||||||
|
if (player->quittime)
|
||||||
|
G_MovePlayerToSpawnOrStarpost(player - players);
|
||||||
|
else
|
||||||
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
|
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
|
||||||
break;
|
break;
|
||||||
case 9: // Ring Drainer (Floor Touch)
|
case 9: // Ring Drainer (Floor Touch)
|
||||||
|
@ -6931,7 +6939,7 @@ void P_SpawnSpecials(boolean fromnetsave)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 146: // Intangible floor/ceiling with solid sides (fences/hoops maybe?)
|
case 146: // Intangible floor/ceiling with solid sides (fences/hoops maybe?)
|
||||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_ALLSIDES|FF_INTANGABLEFLATS, secthinkers);
|
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_ALLSIDES|FF_INTANGIBLEFLATS, secthinkers);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 150: // Air bobbing platform
|
case 150: // Air bobbing platform
|
||||||
|
|
18
src/p_tick.c
18
src/p_tick.c
|
@ -590,10 +590,24 @@ void P_Ticker(boolean run)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
|
|
||||||
//Increment jointime even if paused.
|
// Increment jointime and quittime even if paused
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
++players[i].jointime;
|
{
|
||||||
|
players[i].jointime++;
|
||||||
|
|
||||||
|
if (players[i].quittime)
|
||||||
|
{
|
||||||
|
players[i].quittime++;
|
||||||
|
|
||||||
|
if (players[i].quittime == 30 * TICRATE)
|
||||||
|
P_CheckSurvivors();
|
||||||
|
|
||||||
|
if (server && players[i].quittime >= (tic_t)FixedMul(cv_rejointimeout.value, 60 * TICRATE)
|
||||||
|
&& !(players[i].quittime % TICRATE))
|
||||||
|
SendKick(i, KICK_MSG_PLAYER_QUIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (objectplacing)
|
if (objectplacing)
|
||||||
{
|
{
|
||||||
|
|
26
src/p_user.c
26
src/p_user.c
|
@ -1466,6 +1466,13 @@ void P_PlayLivesJingle(player_t *player)
|
||||||
S_StartSound(NULL, sfx_oneup);
|
S_StartSound(NULL, sfx_oneup);
|
||||||
else if (mariomode)
|
else if (mariomode)
|
||||||
S_StartSound(NULL, sfx_marioa);
|
S_StartSound(NULL, sfx_marioa);
|
||||||
|
else if (cv_1upsound.value)
|
||||||
|
{
|
||||||
|
if (S_sfx[sfx_oneup].lumpnum != LUMPERROR)
|
||||||
|
S_StartSound(NULL, sfx_oneup);
|
||||||
|
else
|
||||||
|
S_StartSound(NULL, sfx_chchng);/* at least play something! */
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
P_PlayJingle(player, JT_1UP);
|
P_PlayJingle(player, JT_1UP);
|
||||||
|
@ -3153,7 +3160,7 @@ static void P_DoClimbing(player_t *player)
|
||||||
platx = P_ReturnThrustX(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
|
platx = P_ReturnThrustX(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
|
||||||
platy = P_ReturnThrustY(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
|
platy = P_ReturnThrustY(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
|
||||||
|
|
||||||
glidesector = R_IsPointInSubsector(player->mo->x + platx, player->mo->y + platy);
|
glidesector = R_PointInSubsectorOrNull(player->mo->x + platx, player->mo->y + platy);
|
||||||
|
|
||||||
{
|
{
|
||||||
boolean floorclimb = false;
|
boolean floorclimb = false;
|
||||||
|
@ -9183,7 +9190,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction,
|
||||||
case MT_TNTBARREL:
|
case MT_TNTBARREL:
|
||||||
if (lockonflags & LOCK_INTERESTS)
|
if (lockonflags & LOCK_INTERESTS)
|
||||||
break;
|
break;
|
||||||
/*fallthru*/
|
/*FALLTHRU*/
|
||||||
case MT_PLAYER: // Don't chase other players!
|
case MT_PLAYER: // Don't chase other players!
|
||||||
case MT_DETON:
|
case MT_DETON:
|
||||||
continue; // Don't be STUPID, Sonic!
|
continue; // Don't be STUPID, Sonic!
|
||||||
|
@ -9201,7 +9208,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction,
|
||||||
case MT_EGGSTATUE:
|
case MT_EGGSTATUE:
|
||||||
if (tutorialmode)
|
if (tutorialmode)
|
||||||
break; // Always focus egg statue in the tutorial
|
break; // Always focus egg statue in the tutorial
|
||||||
/*fallthru*/
|
/*FALLTHRU*/
|
||||||
default:
|
default:
|
||||||
|
|
||||||
if ((lockonflags & LOCK_BOSS) && ((mo->flags & (MF_BOSS|MF_SHOOTABLE)) == (MF_BOSS|MF_SHOOTABLE))) // allows if it has the flags desired XOR it has the invert aimable flag
|
if ((lockonflags & LOCK_BOSS) && ((mo->flags & (MF_BOSS|MF_SHOOTABLE)) == (MF_BOSS|MF_SHOOTABLE))) // allows if it has the flags desired XOR it has the invert aimable flag
|
||||||
|
@ -10226,7 +10233,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
||||||
}
|
}
|
||||||
|
|
||||||
// move camera down to move under lower ceilings
|
// move camera down to move under lower ceilings
|
||||||
newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1));
|
newsubsec = R_PointInSubsectorOrNull(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1));
|
||||||
|
|
||||||
if (!newsubsec)
|
if (!newsubsec)
|
||||||
newsubsec = thiscam->subsector;
|
newsubsec = thiscam->subsector;
|
||||||
|
@ -11747,6 +11754,8 @@ void P_PlayerThink(player_t *player)
|
||||||
{
|
{
|
||||||
if (!playeringame[i] || players[i].spectator || players[i].bot)
|
if (!playeringame[i] || players[i].spectator || players[i].bot)
|
||||||
continue;
|
continue;
|
||||||
|
if (players[i].quittime > 30 * TICRATE)
|
||||||
|
continue;
|
||||||
if (players[i].lives <= 0)
|
if (players[i].lives <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -12199,6 +12208,11 @@ void P_PlayerThink(player_t *player)
|
||||||
player->pflags &= ~PF_USEDOWN;
|
player->pflags &= ~PF_USEDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IF PLAYER NOT HERE THEN FLASH END IF
|
||||||
|
if (player->quittime && player->powers[pw_flashing] < flashingtics - 1
|
||||||
|
&& !(G_TagGametype() && !(player->pflags & PF_TAGIT)) && !player->gotflag)
|
||||||
|
player->powers[pw_flashing] = flashingtics - 1;
|
||||||
|
|
||||||
// Counters, time dependent power ups.
|
// Counters, time dependent power ups.
|
||||||
// Time Bonus & Ring Bonus count settings
|
// Time Bonus & Ring Bonus count settings
|
||||||
|
|
||||||
|
@ -12242,12 +12256,12 @@ void P_PlayerThink(player_t *player)
|
||||||
else
|
else
|
||||||
player->powers[pw_underwater] = 0;
|
player->powers[pw_underwater] = 0;
|
||||||
}
|
}
|
||||||
else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
|
else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && (player->spectator || player->quittime))) // underwater timer
|
||||||
player->powers[pw_underwater]--;
|
player->powers[pw_underwater]--;
|
||||||
|
|
||||||
if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER)))
|
if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER)))
|
||||||
player->powers[pw_spacetime] = 0;
|
player->powers[pw_spacetime] = 0;
|
||||||
else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
|
else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && (player->spectator || player->quittime))) // underwater timer
|
||||||
player->powers[pw_spacetime]--;
|
player->powers[pw_spacetime]--;
|
||||||
|
|
||||||
if (player->powers[pw_gravityboots] && player->powers[pw_gravityboots] < UINT16_MAX)
|
if (player->powers[pw_gravityboots] && player->powers[pw_gravityboots] < UINT16_MAX)
|
||||||
|
|
480
src/r_data.c
480
src/r_data.c
|
@ -699,239 +699,15 @@ void R_FlushTextureCache(void)
|
||||||
int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum);
|
int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum);
|
||||||
void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index);
|
void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index);
|
||||||
|
|
||||||
//
|
#ifdef WALLFLATS
|
||||||
// R_LoadTextures
|
static INT32
|
||||||
// Initializes the texture list with the textures from the world map.
|
Rloadflats (INT32 i, INT32 w)
|
||||||
//
|
|
||||||
#define TX_START "TX_START"
|
|
||||||
#define TX_END "TX_END"
|
|
||||||
void R_LoadTextures(void)
|
|
||||||
{
|
{
|
||||||
INT32 i, w;
|
|
||||||
UINT16 j;
|
UINT16 j;
|
||||||
UINT16 texstart, texend, texturesLumpPos;
|
UINT16 texstart, texend;
|
||||||
patch_t *patchlump;
|
|
||||||
texpatch_t *patch;
|
|
||||||
texture_t *texture;
|
texture_t *texture;
|
||||||
|
texpatch_t *patch;
|
||||||
|
|
||||||
// Free previous memory before numtextures change.
|
|
||||||
if (numtextures)
|
|
||||||
{
|
|
||||||
for (i = 0; i < numtextures; i++)
|
|
||||||
{
|
|
||||||
Z_Free(textures[i]);
|
|
||||||
Z_Free(texturecache[i]);
|
|
||||||
}
|
|
||||||
Z_Free(texturetranslation);
|
|
||||||
Z_Free(textures);
|
|
||||||
Z_Free(texflats);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load patches and textures.
|
|
||||||
|
|
||||||
// Get the number of textures to check.
|
|
||||||
// NOTE: Make SURE the system does not process
|
|
||||||
// the markers.
|
|
||||||
// This system will allocate memory for all duplicate/patched textures even if it never uses them,
|
|
||||||
// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
|
|
||||||
for (w = 0, numtextures = 0; w < numwadfiles; w++)
|
|
||||||
{
|
|
||||||
// Count the textures from TEXTURES lumps
|
|
||||||
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
|
|
||||||
while (texturesLumpPos != INT16_MAX)
|
|
||||||
{
|
|
||||||
numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos);
|
|
||||||
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count single-patch textures
|
|
||||||
if (wadfiles[w]->type == RET_PK3)
|
|
||||||
{
|
|
||||||
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
|
||||||
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
|
|
||||||
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texstart == INT16_MAX || texend == INT16_MAX)
|
|
||||||
#ifdef WALLFLATS
|
|
||||||
goto countflats;
|
|
||||||
#else
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
texstart++; // Do not count the first marker
|
|
||||||
|
|
||||||
// PK3s have subfolders, so we can't just make a simple sum
|
|
||||||
if (wadfiles[w]->type == RET_PK3)
|
|
||||||
{
|
|
||||||
for (j = texstart; j < texend; j++)
|
|
||||||
{
|
|
||||||
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
|
|
||||||
numtextures++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // Add all the textures between TX_START and TX_END
|
|
||||||
{
|
|
||||||
numtextures += (UINT32)(texend - texstart);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WALLFLATS
|
|
||||||
countflats:
|
|
||||||
// Count flats
|
|
||||||
if (wadfiles[w]->type == RET_PK3)
|
|
||||||
{
|
|
||||||
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
|
|
||||||
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0);
|
|
||||||
texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texstart == INT16_MAX || texend == INT16_MAX)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
texstart++; // Do not count the first marker
|
|
||||||
|
|
||||||
// PK3s have subfolders, so we can't just make a simple sum
|
|
||||||
if (wadfiles[w]->type == RET_PK3)
|
|
||||||
{
|
|
||||||
for (j = texstart; j < texend; j++)
|
|
||||||
{
|
|
||||||
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
|
|
||||||
numtextures++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // Add all the textures between F_START and F_END
|
|
||||||
{
|
|
||||||
numtextures += (UINT32)(texend - texstart);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no textures found by this point, bomb out
|
|
||||||
if (!numtextures)
|
|
||||||
I_Error("No textures detected in any WADs!\n");
|
|
||||||
|
|
||||||
// Allocate memory and initialize to 0 for all the textures we are initialising.
|
|
||||||
// There are actually 5 buffers allocated in one for convenience.
|
|
||||||
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
|
|
||||||
texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL);
|
|
||||||
|
|
||||||
// Allocate texture column offset table.
|
|
||||||
texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
|
|
||||||
// Allocate texture referencing cache.
|
|
||||||
texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
|
|
||||||
// Allocate texture width table.
|
|
||||||
texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
|
|
||||||
// Allocate texture height table.
|
|
||||||
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
|
|
||||||
// Create translation table for global animation.
|
|
||||||
texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < numtextures; i++)
|
|
||||||
texturetranslation[i] = i;
|
|
||||||
|
|
||||||
for (i = 0, w = 0; w < numwadfiles; w++)
|
|
||||||
{
|
|
||||||
// Get the lump numbers for the markers in the WAD, if they exist.
|
|
||||||
if (wadfiles[w]->type == RET_PK3)
|
|
||||||
{
|
|
||||||
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
|
||||||
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
|
||||||
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
|
|
||||||
while (texturesLumpPos != INT16_MAX)
|
|
||||||
{
|
|
||||||
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
|
|
||||||
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
|
|
||||||
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
|
|
||||||
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
|
|
||||||
if (texturesLumpPos != INT16_MAX)
|
|
||||||
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texstart == INT16_MAX || texend == INT16_MAX)
|
|
||||||
#ifdef WALLFLATS
|
|
||||||
goto checkflats;
|
|
||||||
#else
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
texstart++; // Do not count the first marker
|
|
||||||
|
|
||||||
// Work through each lump between the markers in the WAD.
|
|
||||||
for (j = 0; j < (texend - texstart); j++)
|
|
||||||
{
|
|
||||||
UINT16 wadnum = (UINT16)w;
|
|
||||||
lumpnum_t lumpnum = texstart + j;
|
|
||||||
#ifndef NO_PNG_LUMPS
|
|
||||||
size_t lumplength;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (wadfiles[w]->type == RET_PK3)
|
|
||||||
{
|
|
||||||
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
|
|
||||||
continue; // If it is then SKIP IT
|
|
||||||
}
|
|
||||||
|
|
||||||
patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
|
||||||
#ifndef NO_PNG_LUMPS
|
|
||||||
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
|
|
||||||
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
|
|
||||||
|
|
||||||
// Set texture properties.
|
|
||||||
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
|
|
||||||
|
|
||||||
#ifndef NO_PNG_LUMPS
|
|
||||||
if (R_IsLumpPNG((UINT8 *)patchlump, lumplength))
|
|
||||||
{
|
|
||||||
INT16 width, height;
|
|
||||||
R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength);
|
|
||||||
texture->width = width;
|
|
||||||
texture->height = height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
texture->width = SHORT(patchlump->width);
|
|
||||||
texture->height = SHORT(patchlump->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->type = TEXTURETYPE_SINGLEPATCH;
|
|
||||||
texture->patchcount = 1;
|
|
||||||
texture->holes = false;
|
|
||||||
texture->flip = 0;
|
|
||||||
|
|
||||||
// Allocate information for the texture's patches.
|
|
||||||
patch = &texture->patches[0];
|
|
||||||
|
|
||||||
patch->originx = patch->originy = 0;
|
|
||||||
patch->wad = (UINT16)w;
|
|
||||||
patch->lump = texstart + j;
|
|
||||||
patch->flip = 0;
|
|
||||||
|
|
||||||
Z_Unlock(patchlump);
|
|
||||||
|
|
||||||
texturewidth[i] = texture->width;
|
|
||||||
textureheight[i] = texture->height << FRACBITS;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WALLFLATS
|
|
||||||
checkflats:
|
|
||||||
// Yes
|
// Yes
|
||||||
if (wadfiles[w]->type == RET_PK3)
|
if (wadfiles[w]->type == RET_PK3)
|
||||||
{
|
{
|
||||||
|
@ -944,9 +720,8 @@ checkflats:
|
||||||
texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
|
texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texstart == INT16_MAX || texend == INT16_MAX)
|
if (!( texstart == INT16_MAX || texend == INT16_MAX ))
|
||||||
continue;
|
{
|
||||||
|
|
||||||
texstart++; // Do not count the first marker
|
texstart++; // Do not count the first marker
|
||||||
|
|
||||||
// Work through each lump between the markers in the WAD.
|
// Work through each lump between the markers in the WAD.
|
||||||
|
@ -1029,7 +804,248 @@ checkflats:
|
||||||
textureheight[i] = texture->height << FRACBITS;
|
textureheight[i] = texture->height << FRACBITS;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
#endif/*WALLFLATS*/
|
||||||
|
|
||||||
|
#define TX_START "TX_START"
|
||||||
|
#define TX_END "TX_END"
|
||||||
|
|
||||||
|
static INT32
|
||||||
|
Rloadtextures (INT32 i, INT32 w)
|
||||||
|
{
|
||||||
|
UINT16 j;
|
||||||
|
UINT16 texstart, texend, texturesLumpPos;
|
||||||
|
texture_t *texture;
|
||||||
|
patch_t *patchlump;
|
||||||
|
texpatch_t *patch;
|
||||||
|
|
||||||
|
// Get the lump numbers for the markers in the WAD, if they exist.
|
||||||
|
if (wadfiles[w]->type == RET_PK3)
|
||||||
|
{
|
||||||
|
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
||||||
|
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
||||||
|
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
|
||||||
|
while (texturesLumpPos != INT16_MAX)
|
||||||
|
{
|
||||||
|
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
|
||||||
|
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
|
||||||
|
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
|
||||||
|
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
|
||||||
|
if (texturesLumpPos != INT16_MAX)
|
||||||
|
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!( texstart == INT16_MAX || texend == INT16_MAX ))
|
||||||
|
{
|
||||||
|
texstart++; // Do not count the first marker
|
||||||
|
|
||||||
|
// Work through each lump between the markers in the WAD.
|
||||||
|
for (j = 0; j < (texend - texstart); j++)
|
||||||
|
{
|
||||||
|
UINT16 wadnum = (UINT16)w;
|
||||||
|
lumpnum_t lumpnum = texstart + j;
|
||||||
|
#ifndef NO_PNG_LUMPS
|
||||||
|
size_t lumplength;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (wadfiles[w]->type == RET_PK3)
|
||||||
|
{
|
||||||
|
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
|
||||||
|
continue; // If it is then SKIP IT
|
||||||
|
}
|
||||||
|
|
||||||
|
patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||||
|
#ifndef NO_PNG_LUMPS
|
||||||
|
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
|
||||||
|
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
|
||||||
|
|
||||||
|
// Set texture properties.
|
||||||
|
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
|
||||||
|
|
||||||
|
#ifndef NO_PNG_LUMPS
|
||||||
|
if (R_IsLumpPNG((UINT8 *)patchlump, lumplength))
|
||||||
|
{
|
||||||
|
INT16 width, height;
|
||||||
|
R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength);
|
||||||
|
texture->width = width;
|
||||||
|
texture->height = height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
texture->width = SHORT(patchlump->width);
|
||||||
|
texture->height = SHORT(patchlump->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
texture->type = TEXTURETYPE_SINGLEPATCH;
|
||||||
|
texture->patchcount = 1;
|
||||||
|
texture->holes = false;
|
||||||
|
texture->flip = 0;
|
||||||
|
|
||||||
|
// Allocate information for the texture's patches.
|
||||||
|
patch = &texture->patches[0];
|
||||||
|
|
||||||
|
patch->originx = patch->originy = 0;
|
||||||
|
patch->wad = (UINT16)w;
|
||||||
|
patch->lump = texstart + j;
|
||||||
|
patch->flip = 0;
|
||||||
|
|
||||||
|
Z_Unlock(patchlump);
|
||||||
|
|
||||||
|
texturewidth[i] = texture->width;
|
||||||
|
textureheight[i] = texture->height << FRACBITS;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// R_LoadTextures
|
||||||
|
// Initializes the texture list with the textures from the world map.
|
||||||
|
//
|
||||||
|
void R_LoadTextures(void)
|
||||||
|
{
|
||||||
|
INT32 i, w;
|
||||||
|
UINT16 j;
|
||||||
|
UINT16 texstart, texend, texturesLumpPos;
|
||||||
|
|
||||||
|
// Free previous memory before numtextures change.
|
||||||
|
if (numtextures)
|
||||||
|
{
|
||||||
|
for (i = 0; i < numtextures; i++)
|
||||||
|
{
|
||||||
|
Z_Free(textures[i]);
|
||||||
|
Z_Free(texturecache[i]);
|
||||||
|
}
|
||||||
|
Z_Free(texturetranslation);
|
||||||
|
Z_Free(textures);
|
||||||
|
Z_Free(texflats);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load patches and textures.
|
||||||
|
|
||||||
|
// Get the number of textures to check.
|
||||||
|
// NOTE: Make SURE the system does not process
|
||||||
|
// the markers.
|
||||||
|
// This system will allocate memory for all duplicate/patched textures even if it never uses them,
|
||||||
|
// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
|
||||||
|
for (w = 0, numtextures = 0; w < numwadfiles; w++)
|
||||||
|
{
|
||||||
|
#ifdef WALLFLATS
|
||||||
|
// Count flats
|
||||||
|
if (wadfiles[w]->type == RET_PK3)
|
||||||
|
{
|
||||||
|
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
|
||||||
|
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0);
|
||||||
|
texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!( texstart == INT16_MAX || texend == INT16_MAX ))
|
||||||
|
{
|
||||||
|
texstart++; // Do not count the first marker
|
||||||
|
|
||||||
|
// PK3s have subfolders, so we can't just make a simple sum
|
||||||
|
if (wadfiles[w]->type == RET_PK3)
|
||||||
|
{
|
||||||
|
for (j = texstart; j < texend; j++)
|
||||||
|
{
|
||||||
|
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
|
||||||
|
numtextures++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Add all the textures between F_START and F_END
|
||||||
|
{
|
||||||
|
numtextures += (UINT32)(texend - texstart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif/*WALLFLATS*/
|
||||||
|
|
||||||
|
// Count the textures from TEXTURES lumps
|
||||||
|
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
|
||||||
|
while (texturesLumpPos != INT16_MAX)
|
||||||
|
{
|
||||||
|
numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos);
|
||||||
|
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count single-patch textures
|
||||||
|
if (wadfiles[w]->type == RET_PK3)
|
||||||
|
{
|
||||||
|
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
||||||
|
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
|
||||||
|
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texstart == INT16_MAX || texend == INT16_MAX)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
texstart++; // Do not count the first marker
|
||||||
|
|
||||||
|
// PK3s have subfolders, so we can't just make a simple sum
|
||||||
|
if (wadfiles[w]->type == RET_PK3)
|
||||||
|
{
|
||||||
|
for (j = texstart; j < texend; j++)
|
||||||
|
{
|
||||||
|
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
|
||||||
|
numtextures++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Add all the textures between TX_START and TX_END
|
||||||
|
{
|
||||||
|
numtextures += (UINT32)(texend - texstart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no textures found by this point, bomb out
|
||||||
|
if (!numtextures)
|
||||||
|
I_Error("No textures detected in any WADs!\n");
|
||||||
|
|
||||||
|
// Allocate memory and initialize to 0 for all the textures we are initialising.
|
||||||
|
// There are actually 5 buffers allocated in one for convenience.
|
||||||
|
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
|
||||||
|
texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL);
|
||||||
|
|
||||||
|
// Allocate texture column offset table.
|
||||||
|
texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
|
||||||
|
// Allocate texture referencing cache.
|
||||||
|
texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
|
||||||
|
// Allocate texture width table.
|
||||||
|
texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
|
||||||
|
// Allocate texture height table.
|
||||||
|
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
|
||||||
|
// Create translation table for global animation.
|
||||||
|
texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < numtextures; i++)
|
||||||
|
texturetranslation[i] = i;
|
||||||
|
|
||||||
|
for (i = 0, w = 0; w < numwadfiles; w++)
|
||||||
|
{
|
||||||
|
#ifdef WALLFLATS
|
||||||
|
i = Rloadflats(i, w);
|
||||||
|
#endif
|
||||||
|
i = Rloadtextures(i, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
|
|
|
@ -144,7 +144,7 @@ typedef enum
|
||||||
FF_QUICKSAND = 0x1000000, ///< Quicksand!
|
FF_QUICKSAND = 0x1000000, ///< Quicksand!
|
||||||
FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top.
|
FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top.
|
||||||
FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
|
FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
|
||||||
FF_INTANGABLEFLATS = 0x6000000, ///< Both flats are intangable, but the sides are still solid.
|
FF_INTANGIBLEFLATS = 0x6000000, ///< Both flats are intangible, but the sides are still solid.
|
||||||
FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch.
|
FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch.
|
||||||
FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames.
|
FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames.
|
||||||
FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee).
|
FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee).
|
||||||
|
|
17
src/r_main.c
17
src/r_main.c
|
@ -128,12 +128,7 @@ consvar_t cv_chasecam2 = {"chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChan
|
||||||
consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
|
consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
|
||||||
#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
|
|
||||||
#ifdef GLBADSHADOWS
|
|
||||||
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
|
||||||
#endif //#ifdef GLBADSHADOWS
|
|
||||||
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
@ -706,9 +701,9 @@ subsector_t *R_PointInSubsector(fixed_t x, fixed_t y)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// R_IsPointInSubsector, same as above but returns 0 if not in subsector
|
// R_PointInSubsectorOrNull, same as above but returns 0 if not in subsector
|
||||||
//
|
//
|
||||||
subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
|
subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y)
|
||||||
{
|
{
|
||||||
node_t *node;
|
node_t *node;
|
||||||
INT32 side, i;
|
INT32 side, i;
|
||||||
|
@ -1223,12 +1218,8 @@ void R_RegisterEngineStuff(void)
|
||||||
|
|
||||||
CV_RegisterVar(&cv_chasecam);
|
CV_RegisterVar(&cv_chasecam);
|
||||||
CV_RegisterVar(&cv_chasecam2);
|
CV_RegisterVar(&cv_chasecam2);
|
||||||
#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
|
|
||||||
CV_RegisterVar(&cv_shadow);
|
CV_RegisterVar(&cv_shadow);
|
||||||
#endif //#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
|
|
||||||
#ifdef GLBADSHADOWS
|
|
||||||
CV_RegisterVar(&cv_shadowoffs);
|
|
||||||
#endif //#ifdef GLBADSHADOWS
|
|
||||||
CV_RegisterVar(&cv_skybox);
|
CV_RegisterVar(&cv_skybox);
|
||||||
|
|
||||||
CV_RegisterVar(&cv_cam_dist);
|
CV_RegisterVar(&cv_cam_dist);
|
||||||
|
|
|
@ -64,7 +64,7 @@ fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
|
||||||
|
|
||||||
fixed_t R_ScaleFromGlobalAngle(angle_t visangle);
|
fixed_t R_ScaleFromGlobalAngle(angle_t visangle);
|
||||||
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
|
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
|
||||||
subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y);
|
subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y);
|
||||||
|
|
||||||
boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph);
|
boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph);
|
||||||
|
|
||||||
|
@ -76,12 +76,8 @@ extern consvar_t cv_showhud, cv_translucenthud;
|
||||||
extern consvar_t cv_homremoval;
|
extern consvar_t cv_homremoval;
|
||||||
extern consvar_t cv_chasecam, cv_chasecam2;
|
extern consvar_t cv_chasecam, cv_chasecam2;
|
||||||
extern consvar_t cv_flipcam, cv_flipcam2;
|
extern consvar_t cv_flipcam, cv_flipcam2;
|
||||||
#if defined(FLOORSPLATS) || defined(GLBADSHADOWS)
|
|
||||||
extern consvar_t cv_shadow;
|
extern consvar_t cv_shadow;
|
||||||
#endif
|
|
||||||
#ifdef GLBADSHADOWS
|
|
||||||
extern conscar_t cv_shadowoffs;
|
|
||||||
#endif //#ifdef GLBADSHADOWS
|
|
||||||
extern consvar_t cv_translucency;
|
extern consvar_t cv_translucency;
|
||||||
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
|
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
|
||||||
extern consvar_t cv_fov;
|
extern consvar_t cv_fov;
|
||||||
|
|
281
src/r_things.c
281
src/r_things.c
|
@ -889,6 +889,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
||||||
if (!(vis->scalestep))
|
if (!(vis->scalestep))
|
||||||
{
|
{
|
||||||
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
|
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
|
||||||
|
sprtopscreen += vis->shear.tan * vis->shear.offset;
|
||||||
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
|
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,7 +935,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Non-paper drawing loop
|
// Non-paper drawing loop
|
||||||
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
|
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
|
||||||
{
|
{
|
||||||
#ifdef RANGECHECK
|
#ifdef RANGECHECK
|
||||||
texturecolumn = frac>>FRACBITS;
|
texturecolumn = frac>>FRACBITS;
|
||||||
|
@ -1107,6 +1108,265 @@ static void R_SplitSprite(vissprite_t *sprite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// R_GetShadowZ(thing, shadowslope)
|
||||||
|
// Get the first visible floor below the object for shadows
|
||||||
|
// shadowslope is filled with the floor's slope, if provided
|
||||||
|
//
|
||||||
|
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
|
||||||
|
{
|
||||||
|
fixed_t z, floorz = INT32_MIN;
|
||||||
|
pslope_t *slope, *floorslope = NULL;
|
||||||
|
msecnode_t *node;
|
||||||
|
sector_t *sector;
|
||||||
|
ffloor_t *rover;
|
||||||
|
|
||||||
|
for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||||
|
{
|
||||||
|
sector = node->m_sector;
|
||||||
|
|
||||||
|
slope = (sector->heightsec != -1) ? NULL : sector->f_slope;
|
||||||
|
z = slope ? P_GetZAt(slope, thing->x, thing->y) : (
|
||||||
|
(sector->heightsec != -1) ? sectors[sector->heightsec].floorheight : sector->floorheight
|
||||||
|
);
|
||||||
|
|
||||||
|
if (z < thing->z+thing->height/2 && z > floorz)
|
||||||
|
{
|
||||||
|
floorz = z;
|
||||||
|
floorslope = slope;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sector->ffloors)
|
||||||
|
for (rover = sector->ffloors; rover; rover = rover->next)
|
||||||
|
{
|
||||||
|
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight;
|
||||||
|
if (z < thing->z+thing->height/2 && z > floorz)
|
||||||
|
{
|
||||||
|
floorz = z;
|
||||||
|
floorslope = *rover->t_slope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thing->floorz > floorz + (!floorslope ? 0 : FixedMul(abs(floorslope->zdelta), thing->radius*3/2)))
|
||||||
|
{
|
||||||
|
floorz = thing->floorz;
|
||||||
|
floorslope = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7.
|
||||||
|
//#ifdef POLYOBJECTS
|
||||||
|
// Check polyobjects and see if floorz needs to be altered, for rings only because they don't update floorz
|
||||||
|
if (thing->type == MT_RING)
|
||||||
|
{
|
||||||
|
INT32 xl, xh, yl, yh, bx, by;
|
||||||
|
|
||||||
|
xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
|
||||||
|
xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
|
||||||
|
yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
|
||||||
|
yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
|
||||||
|
|
||||||
|
BMBOUNDFIX(xl, xh, yl, yh);
|
||||||
|
|
||||||
|
validcount++;
|
||||||
|
|
||||||
|
for (by = yl; by <= yh; by++)
|
||||||
|
for (bx = xl; bx <= xh; bx++)
|
||||||
|
{
|
||||||
|
INT32 offset;
|
||||||
|
polymaplink_t *plink; // haleyjd 02/22/06
|
||||||
|
|
||||||
|
if (bx < 0 || by < 0 || bx >= bmapwidth || by >= bmapheight)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
offset = by*bmapwidth + bx;
|
||||||
|
|
||||||
|
// haleyjd 02/22/06: consider polyobject lines
|
||||||
|
plink = polyblocklinks[offset];
|
||||||
|
|
||||||
|
while (plink)
|
||||||
|
{
|
||||||
|
polyobj_t *po = plink->po;
|
||||||
|
|
||||||
|
if (po->validcount != validcount) // if polyobj hasn't been checked
|
||||||
|
{
|
||||||
|
po->validcount = validcount;
|
||||||
|
|
||||||
|
if (!P_MobjInsidePolyobj(po, thing) || !(po->flags & POF_RENDERPLANES))
|
||||||
|
{
|
||||||
|
plink = (polymaplink_t *)(plink->link.next);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're inside it! Yess...
|
||||||
|
z = po->lines[0]->backsector->ceilingheight;
|
||||||
|
|
||||||
|
if (z < thing->z+thing->height/2 && z > floorz)
|
||||||
|
{
|
||||||
|
floorz = z;
|
||||||
|
floorslope = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plink = (polymaplink_t *)(plink->link.next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (shadowslope != NULL)
|
||||||
|
*shadowslope = floorslope;
|
||||||
|
|
||||||
|
return floorz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz)
|
||||||
|
{
|
||||||
|
vissprite_t *shadow;
|
||||||
|
patch_t *patch;
|
||||||
|
fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2;
|
||||||
|
INT32 light = 0;
|
||||||
|
fixed_t scalemul; UINT8 trans;
|
||||||
|
fixed_t floordiff;
|
||||||
|
fixed_t floorz;
|
||||||
|
pslope_t *floorslope;
|
||||||
|
|
||||||
|
floorz = R_GetShadowZ(thing, &floorslope);
|
||||||
|
|
||||||
|
if (abs(floorz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
|
||||||
|
|
||||||
|
floordiff = abs(thing->z - floorz);
|
||||||
|
|
||||||
|
trans = floordiff / (100*FRACUNIT) + 3;
|
||||||
|
if (trans >= 9) return;
|
||||||
|
|
||||||
|
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
|
||||||
|
|
||||||
|
patch = W_CachePatchName("DSHADOW", PU_CACHE);
|
||||||
|
xscale = FixedDiv(projection, tz);
|
||||||
|
yscale = FixedDiv(projectiony, tz);
|
||||||
|
shadowxscale = FixedMul(thing->radius*2, scalemul);
|
||||||
|
shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(floorz - viewz), tz));
|
||||||
|
shadowyscale = min(shadowyscale, shadowxscale) / patch->height;
|
||||||
|
shadowxscale /= patch->width;
|
||||||
|
shadowskew = 0;
|
||||||
|
|
||||||
|
if (floorslope)
|
||||||
|
{
|
||||||
|
// haha let's try some dumb stuff
|
||||||
|
fixed_t xslope, zslope;
|
||||||
|
angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - floorslope->xydirection) >> ANGLETOFINESHIFT;
|
||||||
|
|
||||||
|
xslope = FixedMul(FINESINE(sloperelang), floorslope->zdelta);
|
||||||
|
zslope = FixedMul(FINECOSINE(sloperelang), floorslope->zdelta);
|
||||||
|
|
||||||
|
//CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope);
|
||||||
|
|
||||||
|
if (viewz < floorz)
|
||||||
|
shadowyscale += FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope);
|
||||||
|
else
|
||||||
|
shadowyscale -= FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope);
|
||||||
|
|
||||||
|
shadowyscale = abs(shadowyscale);
|
||||||
|
|
||||||
|
shadowskew = xslope;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx -= patch->width * shadowxscale/2;
|
||||||
|
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
|
||||||
|
if (x1 >= viewwidth) return;
|
||||||
|
|
||||||
|
tx += patch->width * shadowxscale;
|
||||||
|
x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--;
|
||||||
|
if (x2 < 0 || x2 <= x1) return;
|
||||||
|
|
||||||
|
if (shadowyscale < FRACUNIT/patch->height) return; // fix some crashes?
|
||||||
|
|
||||||
|
shadow = R_NewVisSprite();
|
||||||
|
shadow->patch = patch;
|
||||||
|
shadow->heightsec = vis->heightsec;
|
||||||
|
|
||||||
|
shadow->thingheight = FRACUNIT;
|
||||||
|
shadow->pz = floorz;
|
||||||
|
shadow->pzt = shadow->pz + shadow->thingheight;
|
||||||
|
|
||||||
|
shadow->mobjflags = 0;
|
||||||
|
shadow->sortscale = vis->sortscale;
|
||||||
|
shadow->dispoffset = vis->dispoffset - 5;
|
||||||
|
shadow->gx = thing->x;
|
||||||
|
shadow->gy = thing->y;
|
||||||
|
shadow->gzt = shadow->pz + shadow->patch->height * shadowyscale / 2;
|
||||||
|
shadow->gz = shadow->gzt - shadow->patch->height * shadowyscale;
|
||||||
|
shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
|
||||||
|
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
|
||||||
|
shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale);
|
||||||
|
shadow->scalestep = 0;
|
||||||
|
shadow->shear.tan = shadowskew; // repurposed variable
|
||||||
|
|
||||||
|
shadow->mobj = thing; // Easy access! Tails 06-07-2002
|
||||||
|
|
||||||
|
shadow->x1 = x1 < 0 ? 0 : x1;
|
||||||
|
shadow->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
|
||||||
|
|
||||||
|
// PORTAL SEMI-CLIPPING
|
||||||
|
if (portalrender)
|
||||||
|
{
|
||||||
|
if (shadow->x1 < portalclipstart)
|
||||||
|
shadow->x1 = portalclipstart;
|
||||||
|
if (shadow->x2 >= portalclipend)
|
||||||
|
shadow->x2 = portalclipend-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000
|
||||||
|
shadow->scale = FixedMul(yscale, shadowyscale);
|
||||||
|
shadow->sector = vis->sector;
|
||||||
|
shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS);
|
||||||
|
shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS);
|
||||||
|
shadow->cut = SC_ISSCALED|SC_SHADOW; //check this
|
||||||
|
|
||||||
|
shadow->startfrac = 0;
|
||||||
|
//shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2);
|
||||||
|
shadow->xiscale = (patch->width<<FRACBITS)/(x2-x1+1); // fuck it
|
||||||
|
|
||||||
|
if (shadow->x1 > x1)
|
||||||
|
shadow->startfrac += shadow->xiscale*(shadow->x1-x1);
|
||||||
|
|
||||||
|
// reusing x1 variable
|
||||||
|
x1 += (x2-x1)/2;
|
||||||
|
shadow->shear.offset = shadow->x1-x1;
|
||||||
|
|
||||||
|
if (thing->subsector->sector->numlights)
|
||||||
|
{
|
||||||
|
INT32 lightnum;
|
||||||
|
#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights!
|
||||||
|
light = thing->subsector->sector->numlights - 1;
|
||||||
|
|
||||||
|
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
|
||||||
|
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
|
||||||
|
: thing->subsector->sector->lightlist[lightnum].height;
|
||||||
|
if (h <= shadow->gzt) {
|
||||||
|
light = lightnum - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thing->subsector->sector->numlights)
|
||||||
|
shadow->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap;
|
||||||
|
else
|
||||||
|
shadow->extra_colormap = thing->subsector->sector->extra_colormap;
|
||||||
|
|
||||||
|
shadow->transmap = transtables + (trans<<FF_TRANSSHIFT);
|
||||||
|
shadow->colormap = scalelight[0][0]; // full dark!
|
||||||
|
|
||||||
|
objectsdrawn++;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// R_ProjectSprite
|
// R_ProjectSprite
|
||||||
// Generates a vissprite for a thing
|
// Generates a vissprite for a thing
|
||||||
|
@ -1144,6 +1404,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
||||||
fixed_t scalestep;
|
fixed_t scalestep;
|
||||||
fixed_t offset, offset2;
|
fixed_t offset, offset2;
|
||||||
|
|
||||||
|
fixed_t basetx; // drop shadows
|
||||||
|
|
||||||
boolean papersprite = !!(thing->frame & FF_PAPERSPRITE);
|
boolean papersprite = !!(thing->frame & FF_PAPERSPRITE);
|
||||||
fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0;
|
fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0;
|
||||||
|
|
||||||
|
@ -1178,7 +1440,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
||||||
|
|
||||||
gxt = -FixedMul(tr_x, viewsin);
|
gxt = -FixedMul(tr_x, viewsin);
|
||||||
gyt = FixedMul(tr_y, viewcos);
|
gyt = FixedMul(tr_y, viewcos);
|
||||||
tx = -(gyt + gxt);
|
basetx = tx = -(gyt + gxt);
|
||||||
|
|
||||||
// too far off the side?
|
// too far off the side?
|
||||||
if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later
|
if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later
|
||||||
|
@ -1548,6 +1810,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
||||||
vis->paperoffset = paperoffset;
|
vis->paperoffset = paperoffset;
|
||||||
vis->paperdistance = paperdistance;
|
vis->paperdistance = paperdistance;
|
||||||
vis->centerangle = centerangle;
|
vis->centerangle = centerangle;
|
||||||
|
vis->shear.tan = 0;
|
||||||
|
vis->shear.offset = 0;
|
||||||
|
|
||||||
vis->mobj = thing; // Easy access! Tails 06-07-2002
|
vis->mobj = thing; // Easy access! Tails 06-07-2002
|
||||||
|
|
||||||
|
@ -1640,6 +1904,9 @@ static void R_ProjectSprite(mobj_t *thing)
|
||||||
if (thing->subsector->sector->numlights)
|
if (thing->subsector->sector->numlights)
|
||||||
R_SplitSprite(vis);
|
R_SplitSprite(vis);
|
||||||
|
|
||||||
|
if (oldthing->shadowscale && cv_shadow.value)
|
||||||
|
R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz);
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
++objectsdrawn;
|
++objectsdrawn;
|
||||||
}
|
}
|
||||||
|
@ -1763,6 +2030,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
||||||
vis->pzt = vis->pz + vis->thingheight;
|
vis->pzt = vis->pz + vis->thingheight;
|
||||||
vis->texturemid = vis->gzt - viewz;
|
vis->texturemid = vis->gzt - viewz;
|
||||||
vis->scalestep = 0;
|
vis->scalestep = 0;
|
||||||
|
vis->paperdistance = 0;
|
||||||
|
vis->shear.tan = 0;
|
||||||
|
vis->shear.offset = 0;
|
||||||
|
|
||||||
vis->x1 = x1 < 0 ? 0 : x1;
|
vis->x1 = x1 < 0 ? 0 : x1;
|
||||||
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
|
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
|
||||||
|
@ -1955,6 +2225,9 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
|
||||||
if (!(ds->cut & SC_LINKDRAW))
|
if (!(ds->cut & SC_LINKDRAW))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (ds->cut & SC_SHADOW)
|
||||||
|
continue;
|
||||||
|
|
||||||
// reuse dsfirst...
|
// reuse dsfirst...
|
||||||
for (dsfirst = unsorted.prev; dsfirst != &unsorted; dsfirst = dsfirst->prev)
|
for (dsfirst = unsorted.prev; dsfirst != &unsorted; dsfirst = dsfirst->prev)
|
||||||
{
|
{
|
||||||
|
@ -1962,6 +2235,10 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
|
||||||
if (dsfirst->cut & SC_LINKDRAW)
|
if (dsfirst->cut & SC_LINKDRAW)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// don't connect to your shadow!
|
||||||
|
if (dsfirst->cut & SC_SHADOW)
|
||||||
|
continue;
|
||||||
|
|
||||||
// don't connect if it's not the tracer
|
// don't connect if it's not the tracer
|
||||||
if (dsfirst->mobj != ds->mobj)
|
if (dsfirst->mobj != ds->mobj)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -51,6 +51,8 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight);
|
||||||
// (only sprites from namelist are added or replaced)
|
// (only sprites from namelist are added or replaced)
|
||||||
void R_AddSpriteDefs(UINT16 wadnum);
|
void R_AddSpriteDefs(UINT16 wadnum);
|
||||||
|
|
||||||
|
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
|
||||||
|
|
||||||
//SoM: 6/5/2000: Light sprites correctly!
|
//SoM: 6/5/2000: Light sprites correctly!
|
||||||
void R_AddSprites(sector_t *sec, INT32 lightlevel);
|
void R_AddSprites(sector_t *sec, INT32 lightlevel);
|
||||||
void R_InitSprites(void);
|
void R_InitSprites(void);
|
||||||
|
@ -149,7 +151,8 @@ typedef enum
|
||||||
SC_LINKDRAW = 1<<3,
|
SC_LINKDRAW = 1<<3,
|
||||||
SC_FULLBRIGHT = 1<<4,
|
SC_FULLBRIGHT = 1<<4,
|
||||||
SC_VFLIP = 1<<5,
|
SC_VFLIP = 1<<5,
|
||||||
SC_ISSCALED = 1>>6,
|
SC_ISSCALED = 1<<6,
|
||||||
|
SC_SHADOW = 1<<7,
|
||||||
// masks
|
// masks
|
||||||
SC_CUTMASK = SC_TOP|SC_BOTTOM,
|
SC_CUTMASK = SC_TOP|SC_BOTTOM,
|
||||||
SC_FLAGMASK = ~SC_CUTMASK
|
SC_FLAGMASK = ~SC_CUTMASK
|
||||||
|
@ -182,6 +185,11 @@ typedef struct vissprite_s
|
||||||
|
|
||||||
angle_t centerangle; // for paper sprites
|
angle_t centerangle; // for paper sprites
|
||||||
|
|
||||||
|
struct {
|
||||||
|
fixed_t tan; // The amount to shear the sprite vertically per row
|
||||||
|
INT32 offset; // The center of the shearing location offset from x1
|
||||||
|
} shear;
|
||||||
|
|
||||||
fixed_t texturemid;
|
fixed_t texturemid;
|
||||||
patch_t *patch;
|
patch_t *patch;
|
||||||
|
|
||||||
|
|
290
src/s_sound.c
290
src/s_sound.c
|
@ -117,6 +117,13 @@ static consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL
|
||||||
consvar_t cv_resetmusic = {"resetmusic", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_resetmusic = {"resetmusic", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_resetmusicbyheader = {"resetmusicbyheader", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_resetmusicbyheader = {"resetmusicbyheader", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
|
static CV_PossibleValue_t cons_1upsound_t[] = {
|
||||||
|
{0, "Jingle"},
|
||||||
|
{1, "Sound"},
|
||||||
|
{0, NULL}
|
||||||
|
};
|
||||||
|
consvar_t cv_1upsound = {"1upsound", "Jingle", CV_SAVE, cons_1upsound_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
// Sound system toggles, saved into the config
|
// Sound system toggles, saved into the config
|
||||||
consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_gamemidimusic = {"midimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameMIDIMusic_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_gamemidimusic = {"midimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameMIDIMusic_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
@ -287,6 +294,7 @@ void S_RegisterSoundStuff(void)
|
||||||
CV_RegisterVar(&cv_samplerate);
|
CV_RegisterVar(&cv_samplerate);
|
||||||
CV_RegisterVar(&cv_resetmusic);
|
CV_RegisterVar(&cv_resetmusic);
|
||||||
CV_RegisterVar(&cv_resetmusicbyheader);
|
CV_RegisterVar(&cv_resetmusicbyheader);
|
||||||
|
CV_RegisterVar(&cv_1upsound);
|
||||||
CV_RegisterVar(&cv_playsoundsifunfocused);
|
CV_RegisterVar(&cv_playsoundsifunfocused);
|
||||||
CV_RegisterVar(&cv_playmusicifunfocused);
|
CV_RegisterVar(&cv_playmusicifunfocused);
|
||||||
CV_RegisterVar(&cv_gamesounds);
|
CV_RegisterVar(&cv_gamesounds);
|
||||||
|
@ -1433,6 +1441,12 @@ static tic_t pause_starttic;
|
||||||
/// Music Definitions
|
/// Music Definitions
|
||||||
/// ------------------------
|
/// ------------------------
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MUSICDEF_220,
|
||||||
|
MUSICDEF_221,
|
||||||
|
};
|
||||||
|
|
||||||
musicdef_t soundtestsfx = {
|
musicdef_t soundtestsfx = {
|
||||||
"_STSFX", // prevents exactly one valid track name from being used on the sound test
|
"_STSFX", // prevents exactly one valid track name from being used on the sound test
|
||||||
"Sound Effects",
|
"Sound Effects",
|
||||||
|
@ -1464,67 +1478,39 @@ static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid)
|
||||||
return INT16_MAX; // not found
|
return INT16_MAX; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
void S_LoadMusicDefs(UINT16 wadnum)
|
static void
|
||||||
|
MusicDefStrcpy (char *p, const char *s, size_t n, int version)
|
||||||
{
|
{
|
||||||
UINT16 lump;
|
strlcpy(p, s, n);
|
||||||
char *buf;
|
if (version == MUSICDEF_220)
|
||||||
char *buf2;
|
|
||||||
char *stoken;
|
|
||||||
char *value;
|
|
||||||
size_t size;
|
|
||||||
INT32 i;
|
|
||||||
musicdef_t *def = NULL;
|
|
||||||
UINT16 line = 1; // for better error msgs
|
|
||||||
|
|
||||||
lump = W_CheckForMusicDefInPwad(wadnum);
|
|
||||||
if (lump == INT16_MAX)
|
|
||||||
return;
|
|
||||||
|
|
||||||
buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
|
|
||||||
size = W_LumpLengthPwad(wadnum, lump);
|
|
||||||
|
|
||||||
// for strtok
|
|
||||||
buf2 = malloc(size+1);
|
|
||||||
if (!buf2)
|
|
||||||
I_Error("S_LoadMusicDefs: No more free memory\n");
|
|
||||||
M_Memcpy(buf2,buf,size);
|
|
||||||
buf2[size] = '\0';
|
|
||||||
|
|
||||||
stoken = strtok (buf2, "\r\n ");
|
|
||||||
// Find music def
|
|
||||||
while (stoken)
|
|
||||||
{
|
{
|
||||||
/*if ((stoken[0] == '/' && stoken[1] == '/')
|
while (( p = strchr(p, '_') ))
|
||||||
|| (stoken[0] == '#')) // skip comments
|
*p++ = ' '; // turn _ into spaces.
|
||||||
{
|
}
|
||||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
|
||||||
if (def)
|
|
||||||
stoken = strtok(NULL, "\r\n= ");
|
|
||||||
else
|
|
||||||
stoken = strtok(NULL, "\r\n ");
|
|
||||||
line++;
|
|
||||||
}
|
}
|
||||||
else*/ if (!stricmp(stoken, "lump"))
|
|
||||||
{
|
|
||||||
value = strtok(NULL, "\r\n ");
|
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
ReadMusicDefFields (UINT16 wadnum, int line, boolean fields, char *stoken,
|
||||||
|
musicdef_t **defp, int *versionp)
|
||||||
|
{
|
||||||
|
musicdef_t *def;
|
||||||
|
int version;
|
||||||
|
|
||||||
|
char *value;
|
||||||
|
char *textline;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!stricmp(stoken, "lump"))
|
||||||
|
{
|
||||||
|
value = strtok(NULL, " ");
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, "MUSICDEF: Lump '%s' is missing name. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
|
CONS_Alert(CONS_WARNING,
|
||||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
"MUSICDEF: Field '%s' is missing name. (file %s, line %d)\n",
|
||||||
goto skip_lump;
|
stoken, wadfiles[wadnum]->filename, line);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// No existing musicdefs
|
|
||||||
/*if (!musicdefstart)
|
|
||||||
{
|
|
||||||
musicdefstart = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL);
|
|
||||||
STRBUFCPY(musicdefstart->name, value);
|
|
||||||
strlwr(musicdefstart->name);
|
|
||||||
def = musicdefstart;
|
|
||||||
//CONS_Printf("S_LoadMusicDefs: Initialized musicdef w/ song '%s'\n", def->name);
|
|
||||||
}
|
|
||||||
else*/
|
|
||||||
{
|
{
|
||||||
musicdef_t *prev = NULL;
|
musicdef_t *prev = NULL;
|
||||||
def = musicdefstart;
|
def = musicdefstart;
|
||||||
|
@ -1554,88 +1540,202 @@ void S_LoadMusicDefs(UINT16 wadnum)
|
||||||
prev->next = def;
|
prev->next = def;
|
||||||
//CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name);
|
//CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
skip_lump:
|
(*defp) = def;
|
||||||
stoken = strtok(NULL, "\r\n ");
|
}
|
||||||
line++;
|
}
|
||||||
|
else if (!stricmp(stoken, "version"))
|
||||||
|
{
|
||||||
|
if (fields)/* is this not the first field? */
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_WARNING,
|
||||||
|
"MUSICDEF: Field '%s' must come first. (file %s, line %d)\n",
|
||||||
|
stoken, wadfiles[wadnum]->filename, line);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = strtok(NULL, "\r\n= ");
|
value = strtok(NULL, " ");
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_WARNING,
|
||||||
|
"MUSICDEF: Field '%s' is missing version. (file %s, line %d)\n",
|
||||||
|
stoken, wadfiles[wadnum]->filename, line);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strcasecmp(value, "2.2.0"))
|
||||||
|
(*versionp) = MUSICDEF_221;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
version = (*versionp);
|
||||||
|
|
||||||
|
if (version == MUSICDEF_220)
|
||||||
|
value = strtok(NULL, " =");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = strtok(NULL, "");
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
// Find the equals sign.
|
||||||
|
value = strchr(value, '=');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
|
CONS_Alert(CONS_WARNING,
|
||||||
stoken = strtok(NULL, "\r\n"); // skip end of line
|
"MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n",
|
||||||
goto skip_field;
|
stoken, wadfiles[wadnum]->filename, line);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
def = (*defp);
|
||||||
|
|
||||||
if (!def)
|
if (!def)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
|
CONS_Alert(CONS_ERROR,
|
||||||
free(buf2);
|
"MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n",
|
||||||
return;
|
stoken, wadfiles[wadnum]->filename, line);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version != MUSICDEF_220)
|
||||||
|
{
|
||||||
|
// Skip the equals sign.
|
||||||
|
value++;
|
||||||
|
|
||||||
|
// Now skip funny whitespace.
|
||||||
|
value += strspn(value, "\t ");
|
||||||
|
}
|
||||||
|
|
||||||
|
textline = value;
|
||||||
i = atoi(value);
|
i = atoi(value);
|
||||||
|
|
||||||
|
/* based ignored lumps */
|
||||||
if (!stricmp(stoken, "usage")) {
|
if (!stricmp(stoken, "usage")) {
|
||||||
#if 0 // Ignore for now
|
#if 0 // Ignore for now
|
||||||
STRBUFCPY(def->usage, value);
|
STRBUFCPY(def->usage, textline);
|
||||||
for (value = def->usage; *value; value++)
|
|
||||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
|
||||||
//CONS_Printf("S_LoadMusicDefs: Set usage to '%s'\n", def->usage);
|
|
||||||
#endif
|
#endif
|
||||||
} else if (!stricmp(stoken, "source")) {
|
} else if (!stricmp(stoken, "source")) {
|
||||||
#if 0 // Ignore for now
|
#if 0 // Ignore for now
|
||||||
STRBUFCPY(def->source, value);
|
STRBUFCPY(def->source, textline);
|
||||||
for (value = def->source; *value; value++)
|
|
||||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
|
||||||
//CONS_Printf("S_LoadMusicDefs: Set source to '%s'\n", def->usage);
|
|
||||||
#endif
|
#endif
|
||||||
} else if (!stricmp(stoken, "title")) {
|
} else if (!stricmp(stoken, "title")) {
|
||||||
STRBUFCPY(def->title, value);
|
MusicDefStrcpy(def->title, textline,
|
||||||
for (value = def->title; *value; value++)
|
sizeof def->title, version);
|
||||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
|
||||||
//CONS_Printf("S_LoadMusicDefs: Set title to '%s'\n", def->source);
|
|
||||||
} else if (!stricmp(stoken, "alttitle")) {
|
} else if (!stricmp(stoken, "alttitle")) {
|
||||||
STRBUFCPY(def->alttitle, value);
|
MusicDefStrcpy(def->alttitle, textline,
|
||||||
for (value = def->alttitle; *value; value++)
|
sizeof def->alttitle, version);
|
||||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
|
||||||
//CONS_Printf("S_LoadMusicDefs: Set alttitle to '%s'\n", def->source);
|
|
||||||
} else if (!stricmp(stoken, "authors")) {
|
} else if (!stricmp(stoken, "authors")) {
|
||||||
STRBUFCPY(def->authors, value);
|
MusicDefStrcpy(def->authors, textline,
|
||||||
for (value = def->authors; *value; value++)
|
sizeof def->authors, version);
|
||||||
if (*value == '_') *value = ' '; // turn _ into spaces.
|
|
||||||
//CONS_Printf("S_LoadMusicDefs: Set authors to '%s'\n", def->source);
|
|
||||||
} else if (!stricmp(stoken, "soundtestpage")) {
|
} else if (!stricmp(stoken, "soundtestpage")) {
|
||||||
def->soundtestpage = (UINT8)i;
|
def->soundtestpage = (UINT8)i;
|
||||||
} else if (!stricmp(stoken, "soundtestcond")) {
|
} else if (!stricmp(stoken, "soundtestcond")) {
|
||||||
// Convert to map number
|
// Convert to map number
|
||||||
if (value[0] >= 'A' && value[0] <= 'Z' && value[2] == '\0')
|
if (textline[0] >= 'A' && textline[0] <= 'Z' && textline[2] == '\0')
|
||||||
i = M_MapNumber(value[0], value[1]);
|
i = M_MapNumber(textline[0], textline[1]);
|
||||||
def->soundtestcond = (INT16)i;
|
def->soundtestcond = (INT16)i;
|
||||||
} else if (!stricmp(stoken, "stoppingtime")) {
|
} else if (!stricmp(stoken, "stoppingtime")) {
|
||||||
double stoppingtime = atof(value)*TICRATE;
|
double stoppingtime = atof(textline)*TICRATE;
|
||||||
def->stoppingtics = (tic_t)stoppingtime;
|
def->stoppingtics = (tic_t)stoppingtime;
|
||||||
} else if (!stricmp(stoken, "bpm")) {
|
} else if (!stricmp(stoken, "bpm")) {
|
||||||
double bpm = atof(value);
|
double bpm = atof(textline);
|
||||||
fixed_t bpmf = FLOAT_TO_FIXED(bpm);
|
fixed_t bpmf = FLOAT_TO_FIXED(bpm);
|
||||||
if (bpmf > 0)
|
if (bpmf > 0)
|
||||||
def->bpm = FixedDiv((60*TICRATE)<<FRACBITS, bpmf);
|
def->bpm = FixedDiv((60*TICRATE)<<FRACBITS, bpmf);
|
||||||
} else {
|
} else {
|
||||||
CONS_Alert(CONS_WARNING, "MUSICDEF: Invalid field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
|
CONS_Alert(CONS_WARNING,
|
||||||
|
"MUSICDEF: Invalid field '%s'. (file %s, line %d)\n",
|
||||||
|
stoken, wadfiles[wadnum]->filename, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_field:
|
|
||||||
stoken = strtok(NULL, "\r\n= ");
|
|
||||||
line++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buf2);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void S_LoadMusicDefs(UINT16 wadnum)
|
||||||
|
{
|
||||||
|
UINT16 lumpnum;
|
||||||
|
char *lump;
|
||||||
|
char *musdeftext;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
char *lf;
|
||||||
|
char *stoken;
|
||||||
|
|
||||||
|
size_t nlf;
|
||||||
|
size_t ncr;
|
||||||
|
|
||||||
|
musicdef_t *def = NULL;
|
||||||
|
int version = MUSICDEF_220;
|
||||||
|
int line = 1; // for better error msgs
|
||||||
|
boolean fields = false;
|
||||||
|
|
||||||
|
lumpnum = W_CheckForMusicDefInPwad(wadnum);
|
||||||
|
if (lumpnum == INT16_MAX)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
lump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||||
|
size = W_LumpLengthPwad(wadnum, lumpnum);
|
||||||
|
|
||||||
|
// Null-terminated MUSICDEF lump.
|
||||||
|
musdeftext = malloc(size+1);
|
||||||
|
if (!musdeftext)
|
||||||
|
I_Error("S_LoadMusicDefs: No more free memory for the parser\n");
|
||||||
|
M_Memcpy(musdeftext, lump, size);
|
||||||
|
musdeftext[size] = '\0';
|
||||||
|
|
||||||
|
// Find music def
|
||||||
|
stoken = musdeftext;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
lf = strpbrk(stoken, "\r\n");
|
||||||
|
if (lf)
|
||||||
|
{
|
||||||
|
if (*lf == '\n')
|
||||||
|
nlf = 1;
|
||||||
|
else
|
||||||
|
nlf = 0;
|
||||||
|
*lf++ = '\0';/* now we can delimit to here */
|
||||||
|
}
|
||||||
|
|
||||||
|
stoken = strtok(stoken, " ");
|
||||||
|
if (stoken)
|
||||||
|
{
|
||||||
|
if (! ReadMusicDefFields(wadnum, line, fields, stoken,
|
||||||
|
&def, &version))
|
||||||
|
break;
|
||||||
|
fields = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lf)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
line += nlf;
|
||||||
|
ncr = strspn(lf, "\r");/* skip CR */
|
||||||
|
lf += ncr;
|
||||||
|
nlf = strspn(lf, "\n");
|
||||||
|
lf += nlf;
|
||||||
|
}
|
||||||
|
while (nlf || ncr) ;
|
||||||
|
|
||||||
|
stoken = lf;/* now the next nonempty line */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;/* EOF */
|
||||||
|
}
|
||||||
|
|
||||||
|
free(musdeftext);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -35,6 +35,8 @@ extern consvar_t cv_numChannels;
|
||||||
extern consvar_t cv_resetmusic;
|
extern consvar_t cv_resetmusic;
|
||||||
extern consvar_t cv_resetmusicbyheader;
|
extern consvar_t cv_resetmusicbyheader;
|
||||||
|
|
||||||
|
extern consvar_t cv_1upsound;
|
||||||
|
|
||||||
#define RESETMUSIC (!modeattacking && \
|
#define RESETMUSIC (!modeattacking && \
|
||||||
(cv_resetmusicbyheader.value ? \
|
(cv_resetmusicbyheader.value ? \
|
||||||
(mapheaderinfo[gamemap-1]->musforcereset != -1 ? mapheaderinfo[gamemap-1]->musforcereset : cv_resetmusic.value) \
|
(mapheaderinfo[gamemap-1]->musforcereset != -1 ? mapheaderinfo[gamemap-1]->musforcereset : cv_resetmusic.value) \
|
||||||
|
|
1
tools/musicdef-2.2.1/Makefile
Normal file
1
tools/musicdef-2.2.1/Makefile
Normal file
|
@ -0,0 +1 @@
|
||||||
|
musicdef-2.2.1:
|
77
tools/musicdef-2.2.1/musicdef-2.2.1.c
Normal file
77
tools/musicdef-2.2.1/musicdef-2.2.1.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 James R.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#else
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int ac, char **av)
|
||||||
|
{
|
||||||
|
char line[256];
|
||||||
|
char buf[256];
|
||||||
|
char *var;
|
||||||
|
char *val;
|
||||||
|
char *p;
|
||||||
|
int n;
|
||||||
|
(void)ac;
|
||||||
|
(void)av;
|
||||||
|
fputs(
|
||||||
|
"Copyright 2020 James R.\n"
|
||||||
|
"All rights reserved.\n"
|
||||||
|
"\n"
|
||||||
|
"Usage: musicdef-2.2.1 < old-MUSICDEF > new-MUSICDEF\n"
|
||||||
|
"\n"
|
||||||
|
,stderr);
|
||||||
|
while (fgets(line, sizeof line, stdin))
|
||||||
|
{
|
||||||
|
memcpy(buf, line, sizeof buf);
|
||||||
|
if (( var = strtok(buf, " =") ))
|
||||||
|
{
|
||||||
|
if (!(
|
||||||
|
strcasecmp(var, "TITLE") &&
|
||||||
|
strcasecmp(var, "ALTTITLE") &&
|
||||||
|
strcasecmp(var, "AUTHORS")
|
||||||
|
)){
|
||||||
|
if (( val = strtok(0, "") ))
|
||||||
|
{
|
||||||
|
for (p = val; ( p = strchr(p, '_') ); )
|
||||||
|
{
|
||||||
|
n = strspn(p, "_");
|
||||||
|
memset(p, ' ', n);
|
||||||
|
p += n;
|
||||||
|
}
|
||||||
|
printf("%s %s", var, val);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputs(line, stdout);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue