Merge remote-tracking branch 'origin/next' into pictureformats

This commit is contained in:
Jaime Passos 2020-01-20 16:53:41 -03:00
commit f4a976f3be
52 changed files with 1901 additions and 1157 deletions

View file

@ -1457,15 +1457,8 @@ 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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
netid = READUINT16(*p); netid = READUINT16(*p);

View file

@ -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"
@ -612,15 +613,6 @@ void CON_Ticker(void)
con_tick++; con_tick++;
con_tick &= 7; con_tick &= 7;
// if the menu is open then close the console.
if (menuactive && con_destlines)
{
consoletoggle = false;
con_destlines = 0;
CON_ClearHUD();
I_UpdateMouseGrab();
}
// console key was pushed // console key was pushed
if (consoletoggle) if (consoletoggle)
{ {
@ -777,7 +769,7 @@ boolean CON_Responder(event_t *ev)
// check for console toggle key // check for console toggle key
if (ev->type != ev_console) if (ev->type != ev_console)
{ {
if (modeattacking || metalrecording) if (modeattacking || metalrecording || menuactive)
return false; return false;
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1]) if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
@ -792,7 +784,7 @@ boolean CON_Responder(event_t *ev)
// check other keys only if console prompt is active // check other keys only if console prompt is active
if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!! if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!!
{ {
if (bindtable[key]) if (! menuactive && bindtable[key])
{ {
COM_BufAddText(bindtable[key]); COM_BufAddText(bindtable[key]);
COM_BufAddText("\n"); COM_BufAddText("\n");
@ -815,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)
{ {
@ -967,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;
@ -1551,9 +1553,14 @@ static void CON_DrawConsole(void)
if (cons_backpic.value || con_forcepic) if (cons_backpic.value || con_forcepic)
{ {
patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH); patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
int h;
h = con_curlines/vid.dupy;
// Jimita: CON_DrawBackpic just called V_DrawScaledPatch // Jimita: CON_DrawBackpic just called V_DrawScaledPatch
V_DrawScaledPatch(0, 0, 0, con_backpic); //V_DrawScaledPatch(0, 0, 0, con_backpic);
V_DrawCroppedPatch(0, 0, FRACUNIT, 0, con_backpic,
0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h);
W_UnlockCachedPatch(con_backpic); W_UnlockCachedPatch(con_backpic);
} }

View file

@ -391,11 +391,7 @@ static void ExtraDataTicker(void)
{ {
if (server) if (server)
{ {
UINT8 buf[3]; SendKick(i, KICK_MSG_CON_FAIL);
buf[0] = (UINT8)i;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
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 +433,15 @@ void D_ResetTiccmds(void)
D_Clearticcmd(textcmds[i]->tic); D_Clearticcmd(textcmds[i]->tic);
} }
void SendKick(UINT8 playernum, UINT8 msg)
{
UINT8 buf[2];
buf[0] = playernum;
buf[1] = msg;
SendNetXCmd(XD_KICK, &buf, 2);
}
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// end of extra data function // end of extra data function
// ----------------------------------------------------------------- // -----------------------------------------------------------------
@ -1053,10 +1058,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)
{ {
UINT8 buf[2]; SendKick(nodetoplayer[node], KICK_MSG_CON_FAIL);
buf[0] = (UINT8)nodetoplayer[node];
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
resynch_score[node] = 0; resynch_score[node] = 0;
} }
} }
@ -1346,11 +1348,11 @@ static void SV_SendPlayerInfo(INT32 node)
{ {
if (!playeringame[i]) if (!playeringame[i])
{ {
netbuffer->u.playerinfo[i].node = 255; // This slot is empty. netbuffer->u.playerinfo[i].num = 255; // This slot is empty.
continue; continue;
} }
netbuffer->u.playerinfo[i].node = i; netbuffer->u.playerinfo[i].num = i;
strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1);
netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0'; netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0';
@ -1625,6 +1627,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;
@ -3216,13 +3219,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -3405,14 +3402,10 @@ void CL_AddSplitscreenPlayer(void)
void CL_RemoveSplitscreenPlayer(void) void CL_RemoveSplitscreenPlayer(void)
{ {
UINT8 buf[2];
if (cl_mode != CL_CONNECTED) if (cl_mode != CL_CONNECTED)
return; return;
buf[0] = (UINT8)secondarydisplayplayer; SendKick(secondarydisplayplayer, KICK_MSG_PLAYER_QUIT);
buf[1] = KICK_MSG_PLAYER_QUIT;
SendNetXCmd(XD_KICK, &buf, 2);
} }
// is there a game running // is there a game running
@ -3951,13 +3944,10 @@ static void HandlePacketFromPlayer(SINT8 node)
if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE
|| netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE)
{ {
char buf[2];
CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole);
//D_Clearticcmd(k); //D_Clearticcmd(k);
buf[0] = (char)netconsole; SendKick(netconsole, KICK_MSG_CON_FAIL);
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
break; break;
} }
@ -3994,11 +3984,7 @@ static void HandlePacketFromPlayer(SINT8 node)
} }
else else
{ {
UINT8 buf[3]; SendKick(netconsole, KICK_MSG_CON_FAIL);
buf[0] = (UINT8)netconsole;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
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)));
@ -4111,19 +4097,20 @@ static void HandlePacketFromPlayer(SINT8 node)
nodewaiting[node] = 0; nodewaiting[node] = 0;
if (netconsole != -1 && playeringame[netconsole]) if (netconsole != -1 && playeringame[netconsole])
{ {
UINT8 buf[2]; UINT8 kickmsg;
buf[0] = (UINT8)netconsole;
if (netbuffer->packettype == PT_NODETIMEOUT) if (netbuffer->packettype == PT_NODETIMEOUT)
buf[1] = KICK_MSG_TIMEOUT; kickmsg = KICK_MSG_TIMEOUT;
else else
buf[1] = KICK_MSG_PLAYER_QUIT; kickmsg = KICK_MSG_PLAYER_QUIT;
SendNetXCmd(XD_KICK, &buf, 2);
SendKick(netconsole, kickmsg);
nodetoplayer[node] = -1; nodetoplayer[node] = -1;
if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
&& playeringame[(UINT8)nodetoplayer2[node]]) && playeringame[(UINT8)nodetoplayer2[node]])
{ {
buf[0] = nodetoplayer2[node]; SendKick(nodetoplayer2[node], kickmsg);
SendNetXCmd(XD_KICK, &buf, 2);
nodetoplayer2[node] = -1; nodetoplayer2[node] = -1;
} }
} }
@ -4136,15 +4123,8 @@ static void HandlePacketFromPlayer(SINT8 node)
if (node != servernode) if (node != servernode)
{ {
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);
UINT8 buf[2];
buf[0] = (UINT8)node;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
break; break;
} }
resynch_local_inprogress = false; resynch_local_inprogress = false;
@ -4161,15 +4141,8 @@ static void HandlePacketFromPlayer(SINT8 node)
if (node != servernode) if (node != servernode)
{ {
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);
UINT8 buf[2];
buf[0] = (UINT8)node;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
break; break;
} }
@ -4228,15 +4201,8 @@ static void HandlePacketFromPlayer(SINT8 node)
if (node != servernode) if (node != servernode)
{ {
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);
char buf[2];
buf[0] = (char)node;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
break; break;
} }
resynch_local_inprogress = true; resynch_local_inprogress = true;
@ -4247,15 +4213,8 @@ static void HandlePacketFromPlayer(SINT8 node)
if (node != servernode) if (node != servernode)
{ {
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);
char buf[2];
buf[0] = (char)node;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
break; break;
} }
@ -4278,15 +4237,8 @@ static void HandlePacketFromPlayer(SINT8 node)
if (node != servernode) if (node != servernode)
{ {
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);
UINT8 buf[2];
buf[0] = (UINT8)node;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
break; break;
} }
if (client) if (client)
@ -4833,13 +4785,8 @@ static inline void PingUpdate(void)
if (pingtimeout[i] > cv_pingtimeout.value) if (pingtimeout[i] > cv_pingtimeout.value)
// 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.
{ {
char buf[2];
pingtimeout[i] = 0; pingtimeout[i] = 0;
SendKick(i, KICK_MSG_PING_HIGH);
buf[0] = (char)i;
buf[1] = KICK_MSG_PING_HIGH;
SendNetXCmd(XD_KICK, &buf, 2);
} }
} }
/* /*

View file

@ -27,7 +27,7 @@ This version is independent of the mod name, and standard
version and subversion. It should only account for the version and subversion. It should only account for the
basic fields of the packet, and change infrequently. basic fields of the packet, and change infrequently.
*/ */
#define PACKETVERSION 1 #define PACKETVERSION 2
// Network play related stuff. // Network play related stuff.
// There is a data struct that stores network // There is a data struct that stores network
@ -366,7 +366,6 @@ typedef struct
UINT8 cheatsenabled; UINT8 cheatsenabled;
UINT8 isdedicated; UINT8 isdedicated;
UINT8 fileneedednum; UINT8 fileneedednum;
SINT8 adminplayer;
tic_t time; tic_t time;
tic_t leveltime; tic_t leveltime;
char servername[MAXSERVERNAME]; char servername[MAXSERVERNAME];
@ -398,7 +397,7 @@ typedef struct
// Shorter player information for external use. // Shorter player information for external use.
typedef struct typedef struct
{ {
UINT8 node; UINT8 num;
char name[MAXPLAYERNAME+1]; char name[MAXPLAYERNAME+1];
UINT8 address[4]; // sending another string would run us up against MAXPACKETLENGTH UINT8 address[4]; // sending another string would run us up against MAXPACKETLENGTH
UINT8 team; UINT8 team;
@ -523,6 +522,7 @@ void D_ClientServerInit(void);
void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)); void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum));
void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam); void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam);
void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player
void SendKick(UINT8 playernum, UINT8 msg);
// Create any new ticcmds and broadcast to other players. // Create any new ticcmds and broadcast to other players.
void NetUpdate(void); void NetUpdate(void);

View file

@ -188,14 +188,14 @@ void D_ProcessEvents(void)
continue; continue;
} }
// Menu input
if (M_Responder(ev))
continue; // menu ate the event
// console input // console input
if (CON_Responder(ev)) if (CON_Responder(ev))
continue; // ate the event continue; // ate the event
// Menu input
if (M_Responder(ev))
continue; // menu ate the event
G_Responder(ev); G_Responder(ev);
} }
} }
@ -502,13 +502,12 @@ static void D_Display(void)
// vid size change is now finished if it was on... // vid size change is now finished if it was on...
vid.recalc = 0; vid.recalc = 0;
// FIXME: draw either console or menu, not the two
if (gamestate != GS_TIMEATTACK)
CON_Drawer();
M_Drawer(); // menu is drawn even on top of everything M_Drawer(); // menu is drawn even on top of everything
// focus lost moved to M_Drawer // focus lost moved to M_Drawer
if (gamestate != GS_TIMEATTACK)
CON_Drawer();
// //
// wipe update // wipe update
// //
@ -1046,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();

View file

@ -1124,13 +1124,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
} }
} }
@ -1205,7 +1199,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;
@ -1487,12 +1481,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
if (kick) if (kick)
{ {
UINT8 buf[2];
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);
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
return; return;
} }
} }
@ -2032,13 +2022,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -2149,13 +2133,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -2230,13 +2208,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -2299,13 +2271,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -2652,13 +2618,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
} }
if (NetPacket.packet.verification) // Special marker that the server sent the request if (NetPacket.packet.verification) // Special marker that the server sent the request
@ -2667,13 +2627,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
playernum = NetPacket.packet.playernum; playernum = NetPacket.packet.playernum;
@ -2706,13 +2660,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
} }
return; return;
} }
@ -2770,12 +2718,8 @@ 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))
{ {
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
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]);
SendNetXCmd(XD_KICK, &buf, 2); SendKick(playernum, KICK_MSG_CON_FAIL);
} }
//Safety first! //Safety first!
@ -3067,13 +3011,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -3123,13 +3061,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -3203,14 +3135,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
Z_Free(mymotd); Z_Free(mymotd);
return; return;
} }
@ -3266,13 +3191,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -3429,13 +3348,8 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick) if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick)
{ {
UINT8 buf[2];
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);
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
return; return;
} }
@ -3484,13 +3398,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -4283,13 +4191,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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }

View file

@ -1630,6 +1630,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"))
@ -3431,6 +3436,8 @@ static void readextraemblemdata(MYFILE *f, INT32 num)
sizeof (extraemblems[num-1].description), va("Extra emblem %d: objective", num)); sizeof (extraemblems[num-1].description), va("Extra emblem %d: objective", num));
else if (fastcmp(word, "CONDITIONSET")) else if (fastcmp(word, "CONDITIONSET"))
extraemblems[num-1].conditionset = (UINT8)value; extraemblems[num-1].conditionset = (UINT8)value;
else if (fastcmp(word, "SHOWCONDITIONSET"))
extraemblems[num-1].showconditionset = (UINT8)value;
else else
{ {
strupr(word2); strupr(word2);
@ -3517,6 +3524,8 @@ static void readunlockable(MYFILE *f, INT32 num)
unlockables[num].height = (UINT16)i; unlockables[num].height = (UINT16)i;
else if (fastcmp(word, "CONDITIONSET")) else if (fastcmp(word, "CONDITIONSET"))
unlockables[num].conditionset = (UINT8)i; unlockables[num].conditionset = (UINT8)i;
else if (fastcmp(word, "SHOWCONDITIONSET"))
unlockables[num].showconditionset = (UINT8)i;
else if (fastcmp(word, "NOCECHO")) else if (fastcmp(word, "NOCECHO"))
unlockables[num].nocecho = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y'); unlockables[num].nocecho = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
else if (fastcmp(word, "NOCHECKLIST")) else if (fastcmp(word, "NOCHECKLIST"))
@ -6012,6 +6021,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",
@ -8670,6 +8680,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_NIGHTSCHIP", // NiGHTS Chip "MT_NIGHTSCHIP", // NiGHTS Chip
"MT_FLINGNIGHTSCHIP", // Lost NiGHTS Chip "MT_FLINGNIGHTSCHIP", // Lost NiGHTS Chip
"MT_NIGHTSSTAR", // NiGHTS Star "MT_NIGHTSSTAR", // NiGHTS Star
"MT_FLINGNIGHTSSTAR", // Lost NiGHTS Star
"MT_NIGHTSSUPERLOOP", "MT_NIGHTSSUPERLOOP",
"MT_NIGHTSDRILLREFILL", "MT_NIGHTSDRILLREFILL",
"MT_NIGHTSHELPER", "MT_NIGHTSHELPER",
@ -8837,7 +8848,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.
@ -9417,7 +9428,7 @@ struct {
{"SH_FORCE",SH_FORCE}, {"SH_FORCE",SH_FORCE},
{"SH_FORCEHP",SH_FORCEHP}, // to be used as a bitmask only {"SH_FORCEHP",SH_FORCEHP}, // to be used as a bitmask only
// Mostly for use with Mario mode. // Mostly for use with Mario mode.
{"SH_FIREFLOWER", SH_FIREFLOWER}, {"SH_FIREFLOWER",SH_FIREFLOWER},
{"SH_STACK",SH_STACK}, {"SH_STACK",SH_STACK},
{"SH_NOSTACK",SH_NOSTACK}, {"SH_NOSTACK",SH_NOSTACK},
@ -9432,7 +9443,7 @@ struct {
{"CR_ROPEHANG",CR_ROPEHANG}, {"CR_ROPEHANG",CR_ROPEHANG},
{"CR_MACESPIN",CR_MACESPIN}, {"CR_MACESPIN",CR_MACESPIN},
{"CR_MINECART",CR_MINECART}, {"CR_MINECART",CR_MINECART},
{"CR_ROLLOUT", CR_ROLLOUT}, {"CR_ROLLOUT",CR_ROLLOUT},
{"CR_PTERABYTE",CR_PTERABYTE}, {"CR_PTERABYTE",CR_PTERABYTE},
// Ring weapons (ringweapons_t) // Ring weapons (ringweapons_t)
@ -9599,7 +9610,7 @@ struct {
{"NUM_WEAPONS",NUM_WEAPONS}, {"NUM_WEAPONS",NUM_WEAPONS},
// Value for infinite lives // Value for infinite lives
{"INFLIVES", INFLIVES}, {"INFLIVES",INFLIVES},
// Got Flags, for player->gotflag! // Got Flags, for player->gotflag!
// Used to be MF_ for some stupid reason, now they're GF_ to stop them looking like mobjflags // Used to be MF_ for some stupid reason, now they're GF_ to stop them looking like mobjflags
@ -9660,10 +9671,11 @@ 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).
{"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats {"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats
{"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel
{"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.

View file

@ -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;

View file

@ -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.

View file

@ -1233,6 +1233,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\"",

View file

@ -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}};
@ -4761,6 +4761,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++;
} }

View file

@ -72,6 +72,7 @@
#include "../v_video.h" #include "../v_video.h"
#include "hw_clip.h" #include "hw_clip.h"
#include "hw_glob.h" #include "hw_glob.h"
#include "../r_main.h"
#include "../r_state.h" #include "../r_state.h"
#include "../tables.h" #include "../tables.h"
#include "r_opengl/r_opengl.h" #include "r_opengl/r_opengl.h"
@ -328,7 +329,7 @@ angle_t gld_FrustumAngle(void)
// NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
float render_fov = FIXED_TO_FLOAT(cv_grfov.value); float render_fov = FIXED_TO_FLOAT(cv_fov.value);
float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right? float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right?
float render_multiplier = 64.0f / render_fovratio / RMUL; float render_multiplier = 64.0f / render_fovratio / RMUL;

View file

@ -1031,6 +1031,34 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
} }
#endif #endif
static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y)
{
INT16 finallight = lightnum;
if (cv_grfakecontrast.value != 0)
{
const UINT8 contrast = 8;
fixed_t extralight = 0;
if (v1y == v2y)
extralight = -contrast;
else if (v1x == v2x)
extralight = contrast;
if (extralight != 0)
{
finallight += extralight;
if (finallight < 0)
finallight = 0;
if (finallight > 255)
finallight = 255;
}
}
return (FUINT)finallight;
}
// //
// HWR_SplitWall // HWR_SplitWall
// //
@ -1049,19 +1077,20 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
float endpegt, endpegb, endpegmul; float endpegt, endpegb, endpegmul;
float endheight = 0.0f, endbheight = 0.0f; float endheight = 0.0f, endbheight = 0.0f;
fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x);
fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo
fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x);
fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo
// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetZAt's return value each time // use this as a temp var to store P_GetZAt's return value each time
fixed_t temp; fixed_t temp;
#endif #endif
INT32 solid, i; fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x);
fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo
fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x);
fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo
INT32 solid, i;
lightlist_t * list = sector->lightlist; lightlist_t * list = sector->lightlist;
const UINT8 alpha = Surf->FlatColor.s.alpha; const UINT8 alpha = Surf->FlatColor.s.alpha;
FUINT lightnum = sector->lightlevel; FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y);
extracolormap_t *colormap = NULL; extracolormap_t *colormap = NULL;
realtop = top = wallVerts[3].y; realtop = top = wallVerts[3].y;
@ -1091,12 +1120,12 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
{ {
if (pfloor && (pfloor->flags & FF_FOG)) if (pfloor && (pfloor->flags & FF_FOG))
{ {
lightnum = pfloor->master->frontsector->lightlevel; lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y);
colormap = pfloor->master->frontsector->extra_colormap; colormap = pfloor->master->frontsector->extra_colormap;
} }
else else
{ {
lightnum = *list[i].lightlevel; lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y);
colormap = *list[i].extra_colormap; colormap = *list[i].extra_colormap;
} }
} }
@ -1400,7 +1429,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT));
} }
lightnum = gr_frontsector->lightlevel; lightnum = HWR_CalcWallLight(gr_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
colormap = gr_frontsector->extra_colormap; colormap = gr_frontsector->extra_colormap;
if (gr_frontsector) if (gr_frontsector)
@ -2155,7 +2184,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
blendmode = PF_Fog|PF_NoTexture; blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel; lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
colormap = rover->master->frontsector->extra_colormap; colormap = rover->master->frontsector->extra_colormap;
if (rover->master->frontsector->extra_colormap) if (rover->master->frontsector->extra_colormap)
@ -2275,7 +2304,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
blendmode = PF_Fog|PF_NoTexture; blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel; lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
colormap = rover->master->frontsector->extra_colormap; colormap = rover->master->frontsector->extra_colormap;
if (rover->master->frontsector->extra_colormap) if (rover->master->frontsector->extra_colormap)
@ -5128,7 +5157,12 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo
planeinfo[numplanes].isceiling = isceiling; planeinfo[numplanes].isceiling = isceiling;
planeinfo[numplanes].fixedheight = fixedheight; planeinfo[numplanes].fixedheight = fixedheight;
planeinfo[numplanes].lightlevel = lightlevel;
if (planecolormap && (planecolormap->fog & 1))
planeinfo[numplanes].lightlevel = lightlevel;
else
planeinfo[numplanes].lightlevel = 255;
planeinfo[numplanes].levelflat = levelflat; planeinfo[numplanes].levelflat = levelflat;
planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha; planeinfo[numplanes].alpha = alpha;
@ -5160,7 +5194,12 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse
polyplaneinfo[numpolyplanes].isceiling = isceiling; polyplaneinfo[numpolyplanes].isceiling = isceiling;
polyplaneinfo[numpolyplanes].fixedheight = fixedheight; polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
if (planecolormap && (planecolormap->fog & 1))
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
else
polyplaneinfo[numpolyplanes].lightlevel = 255;
polyplaneinfo[numpolyplanes].levelflat = levelflat; polyplaneinfo[numpolyplanes].levelflat = levelflat;
polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha; polyplaneinfo[numpolyplanes].alpha = alpha;
@ -5501,6 +5540,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
spriteinfo_t *sprinfo; spriteinfo_t *sprinfo;
md2_t *md2;
size_t lumpoff; size_t lumpoff;
unsigned rot; unsigned rot;
UINT16 flip; UINT16 flip;
@ -5532,8 +5572,21 @@ static void HWR_ProjectSprite(mobj_t *thing)
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin); tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
// thing is behind view plane? // thing is behind view plane?
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmodels.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear if (tz < ZCLIP_PLANE && !papersprite)
return; {
if (cv_grmodels.value) //Yellow: Only MD2's dont disappear
{
if (thing->skin && thing->sprite == SPR_PLAY)
md2 = &md2_playermodels[( (skin_t *)thing->skin - skins )];
else
md2 = &md2_models[thing->sprite];
if (md2->notfound || md2->scale < 0.0f)
return;
}
else
return;
}
// The above can stay as it works for cutting sprites that are too close // The above can stay as it works for cutting sprites that are too close
tr_x = FIXED_TO_FLOAT(thing->x); tr_x = FIXED_TO_FLOAT(thing->x);
@ -5901,7 +5954,7 @@ static void HWR_DrawSkyBackground(player_t *player)
if (cv_grskydome.value) if (cv_grskydome.value)
{ {
FTransform dometransform; FTransform dometransform;
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type; postimg_t *type;
if (splitscreen && player == &players[secondarydisplayplayer]) if (splitscreen && player == &players[secondarydisplayplayer])
@ -6079,7 +6132,7 @@ void HWR_SetViewSize(void)
// ========================================================================== // ==========================================================================
void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
{ {
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type; postimg_t *type;
if (splitscreen && player == &players[secondarydisplayplayer]) if (splitscreen && player == &players[secondarydisplayplayer])
@ -6205,7 +6258,7 @@ if (0)
viewangle = localaiming2; viewangle = localaiming2;
// Handle stuff when you are looking farther up or down. // Handle stuff when you are looking farther up or down.
if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT)) if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{ {
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
HWR_ClearClipSegs(); HWR_ClearClipSegs();
@ -6283,7 +6336,7 @@ if (0)
// ========================================================================== // ==========================================================================
void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
{ {
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type; postimg_t *type;
const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on
@ -6425,7 +6478,7 @@ if (0)
viewangle = localaiming2; viewangle = localaiming2;
// Handle stuff when you are looking farther up or down. // Handle stuff when you are looking farther up or down.
if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT)) if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{ {
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
HWR_ClearClipSegs(); HWR_ClearClipSegs();
@ -6554,9 +6607,7 @@ static void CV_grmodellighting_OnChange(void);
static void CV_grfiltermode_OnChange(void); static void CV_grfiltermode_OnChange(void);
static void CV_granisotropic_OnChange(void); static void CV_granisotropic_OnChange(void);
static void CV_grfogdensity_OnChange(void); static void CV_grfogdensity_OnChange(void);
static void CV_grfov_OnChange(void);
static CV_PossibleValue_t grfov_cons_t[] = {{0, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}};
static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"},
{HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"},
{HWD_SET_TEXTUREFILTER_MIXED1, "Linear_Nearest"}, {HWD_SET_TEXTUREFILTER_MIXED1, "Linear_Nearest"},
@ -6565,7 +6616,7 @@ static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA
{0, NULL}}; {0, NULL}};
CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}}; CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}};
consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grsoftwarefog = {"gr_softwarefog", "Off", CV_SAVE, grsoftwarefog_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grsoftwarefog = {"gr_softwarefog", "Off", CV_SAVE, grsoftwarefog_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -6583,9 +6634,9 @@ consvar_t cv_grmodellighting = {"gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_O
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfakecontrast = {"gr_fakecontrast", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfov = {"gr_fov", "90", CV_FLOAT|CV_CALL, grfov_cons_t, CV_grfov_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned, consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned,
CV_grfogdensity_OnChange, 0, NULL, NULL, 0, 0, NULL}; CV_grfogdensity_OnChange, 0, NULL, NULL, 0, 0, NULL};
@ -6621,17 +6672,10 @@ static void CV_granisotropic_OnChange(void)
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value);
} }
static void CV_grfov_OnChange(void)
{
if ((netgame || multiplayer) && !cv_debug && cv_grfov.value != 90*FRACUNIT)
CV_Set(&cv_grfov, cv_grfov.defaultvalue);
}
//added by Hurdler: console varibale that are saved //added by Hurdler: console varibale that are saved
void HWR_AddCommands(void) void HWR_AddCommands(void)
{ {
CV_RegisterVar(&cv_grfovchange); CV_RegisterVar(&cv_fovchange);
CV_RegisterVar(&cv_grfov);
CV_RegisterVar(&cv_grfogdensity); CV_RegisterVar(&cv_grfogdensity);
CV_RegisterVar(&cv_grfogcolor); CV_RegisterVar(&cv_grfogcolor);
@ -6651,6 +6695,7 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_grskydome); CV_RegisterVar(&cv_grskydome);
CV_RegisterVar(&cv_grspritebillboarding); CV_RegisterVar(&cv_grspritebillboarding);
CV_RegisterVar(&cv_grfakecontrast);
CV_RegisterVar(&cv_grfiltermode); CV_RegisterVar(&cv_grfiltermode);
CV_RegisterVar(&cv_grrounddown); CV_RegisterVar(&cv_grrounddown);

View file

@ -84,7 +84,6 @@ extern consvar_t cv_grstaticlighting;
extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronas;
extern consvar_t cv_grcoronasize; extern consvar_t cv_grcoronasize;
#endif #endif
extern consvar_t cv_grfov;
extern consvar_t cv_grmodels; extern consvar_t cv_grmodels;
extern consvar_t cv_grmodelinterpolation; extern consvar_t cv_grmodelinterpolation;
extern consvar_t cv_grmodellighting; extern consvar_t cv_grmodellighting;
@ -95,10 +94,11 @@ extern consvar_t cv_grsoftwarefog;
extern consvar_t cv_grfiltermode; extern consvar_t cv_grfiltermode;
extern consvar_t cv_granisotropicmode; extern consvar_t cv_granisotropicmode;
extern consvar_t cv_grcorrecttricks; extern consvar_t cv_grcorrecttricks;
extern consvar_t cv_grfovchange; extern consvar_t cv_fovchange;
extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding; extern consvar_t cv_grspritebillboarding;
extern consvar_t cv_grskydome; extern consvar_t cv_grskydome;
extern consvar_t cv_grfakecontrast;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy; extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;

View file

@ -654,10 +654,14 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
UINT16 w = gpatch->width, h = gpatch->height; UINT16 w = gpatch->width, h = gpatch->height;
UINT32 size = w*h; UINT32 size = w*h;
RGBA_t *image, *blendimage, *cur, blendcolor; RGBA_t *image, *blendimage, *cur, blendcolor;
UINT8 translation[16]; // First the color index
UINT8 cutoff[16]; // Brightness cutoff before using the next color
UINT8 translen = 0;
UINT8 i;
// vanilla port blendcolor = V_GetColor(0); // initialize
UINT8 translation[16];
memset(translation, 0, sizeof(translation)); memset(translation, 0, sizeof(translation));
memset(cutoff, 0, sizeof(cutoff));
if (grmip->width == 0) if (grmip->width == 0)
{ {
@ -681,17 +685,46 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
image = gpatch->mipmap->grInfo.data; image = gpatch->mipmap->grInfo.data;
blendimage = blendgpatch->mipmap->grInfo.data; blendimage = blendgpatch->mipmap->grInfo.data;
blendcolor = V_GetColor(0); // initialize
// TC_METALSONIC includes an actual skincolor translation, on top of its flashing.
if (skinnum == TC_METALSONIC)
color = SKINCOLOR_COBALT;
if (color != SKINCOLOR_NONE) if (color != SKINCOLOR_NONE)
memcpy(&translation, &Color_Index[color - 1], 16); {
UINT8 numdupes = 1;
translation[translen] = Color_Index[color-1][0];
cutoff[translen] = 255;
for (i = 1; i < 16; i++)
{
if (translation[translen] == Color_Index[color-1][i])
{
numdupes++;
continue;
}
if (translen > 0)
{
cutoff[translen] = cutoff[translen-1] - (256 / (16 / numdupes));
}
numdupes = 1;
translen++;
translation[translen] = (UINT8)Color_Index[color-1][i];
}
translen++;
}
while (size--) while (size--)
{ {
if (skinnum == TC_BOSS) if (skinnum == TC_BOSS)
{ {
// Turn everything below a certain threshold white // Turn everything below a certain threshold white
if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue <= 82) if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue < 127)
{ {
// Lactozilla: Invert the colors // Lactozilla: Invert the colors
cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue); cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue);
@ -705,53 +738,6 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
cur->s.alpha = image->s.alpha; cur->s.alpha = image->s.alpha;
} }
else if (skinnum == TC_METALSONIC)
{
// Turn everything below a certain blue threshold white
if (image->s.red == 0 && image->s.green == 0 && image->s.blue <= 82)
{
cur->s.red = cur->s.green = cur->s.blue = 255;
}
else
{
cur->s.red = image->s.red;
cur->s.green = image->s.green;
cur->s.blue = image->s.blue;
}
cur->s.alpha = image->s.alpha;
}
else if (skinnum == TC_DASHMODE)
{
if (image->s.alpha == 0 && blendimage->s.alpha == 0)
{
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur->rgba = image->rgba;
}
else
{
UINT8 ialpha = 255 - blendimage->s.alpha, balpha = blendimage->s.alpha;
RGBA_t icolor = *image, bcolor;
memset(&bcolor, 0x00, sizeof(RGBA_t));
if (blendimage->s.alpha)
{
bcolor.s.blue = 0;
bcolor.s.red = 255;
bcolor.s.green = (blendimage->s.red + blendimage->s.green + blendimage->s.blue) / 3;
}
if (image->s.alpha && image->s.red > image->s.green << 1) // this is pretty arbitrary, but it works well for Metal Sonic
{
icolor.s.red = image->s.blue;
icolor.s.blue = image->s.red;
}
cur->s.red = (ialpha * icolor.s.red + balpha * bcolor.s.red)/255;
cur->s.green = (ialpha * icolor.s.green + balpha * bcolor.s.green)/255;
cur->s.blue = (ialpha * icolor.s.blue + balpha * bcolor.s.blue)/255;
cur->s.alpha = image->s.alpha;
}
}
else if (skinnum == TC_ALLWHITE) else if (skinnum == TC_ALLWHITE)
{ {
// Turn everything white // Turn everything white
@ -760,185 +746,268 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
} }
else else
{ {
UINT16 brightness; // Everything below requires a blend image
if (blendimage == NULL)
{
cur->rgba = image->rgba;
goto skippixel;
}
// Don't bother with blending the pixel if the alpha of the blend pixel is 0 // Metal Sonic dash mode
if (skinnum == TC_RAINBOW) if (skinnum == TC_DASHMODE)
{ {
if (image->s.alpha == 0 && blendimage->s.alpha == 0) if (image->s.alpha == 0 && blendimage->s.alpha == 0)
{ {
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur->rgba = image->rgba; cur->rgba = image->rgba;
cur++; image++; blendimage++;
continue;
} }
else else
{ {
UINT16 imagebright, blendbright; UINT8 ialpha = 255 - blendimage->s.alpha, balpha = blendimage->s.alpha;
SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); RGBA_t icolor = *image, bcolor;
SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
// slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway memset(&bcolor, 0x00, sizeof(RGBA_t));
brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255;
if (blendimage->s.alpha)
{
bcolor.s.blue = 0;
bcolor.s.red = 255;
bcolor.s.green = (blendimage->s.red + blendimage->s.green + blendimage->s.blue) / 3;
}
if (image->s.alpha && image->s.red > image->s.green << 1) // this is pretty arbitrary, but it works well for Metal Sonic
{
icolor.s.red = image->s.blue;
icolor.s.blue = image->s.red;
}
cur->s.red = (ialpha * icolor.s.red + balpha * bcolor.s.red)/255;
cur->s.green = (ialpha * icolor.s.green + balpha * bcolor.s.green)/255;
cur->s.blue = (ialpha * icolor.s.blue + balpha * bcolor.s.blue)/255;
cur->s.alpha = image->s.alpha;
} }
} }
else else
{ {
if (blendimage->s.alpha == 0) // All settings that use skincolors!
UINT16 brightness;
if (translen <= 0)
{ {
cur->rgba = image->rgba; cur->rgba = image->rgba;
cur++; image++; blendimage++; goto skippixel;
continue;
} }
else
{
SETBRIGHTNESS(brightness,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
}
}
// Calculate a sort of "gradient" for the skincolor // Don't bother with blending the pixel if the alpha of the blend pixel is 0
// (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...)
{
RGBA_t nextcolor;
UINT8 firsti, secondi, mul;
UINT32 r, g, b;
// Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors.
// Ensue horrible mess.
if (skinnum == TC_RAINBOW) if (skinnum == TC_RAINBOW)
{ {
UINT16 brightdif = 256; if (image->s.alpha == 0 && blendimage->s.alpha == 0)
UINT8 colorbrightnesses[16];
INT32 compare, m, d;
UINT8 i;
// Ignore pure white & pitch black
if (brightness > 253 || brightness < 2)
{ {
cur->rgba = image->rgba; cur->rgba = image->rgba;
cur++; image++; blendimage++; goto skippixel;
continue;
}
firsti = 0;
mul = 0;
for (i = 0; i < 16; i++)
{
RGBA_t tempc = V_GetColor(translation[i]);
SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison
}
for (i = 0; i < 16; i++)
{
if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is)
continue;
compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness));
if (compare < brightdif)
{
brightdif = (UINT16)compare;
firsti = i; // best matching color that's equal brightness or darker
}
}
secondi = firsti+1; // next color in line
if (secondi == 16)
{
m = (INT16)brightness; // - 0;
d = (INT16)colorbrightnesses[firsti]; // - 0;
} }
else else
{ {
m = (INT16)brightness - (INT16)colorbrightnesses[secondi]; UINT16 imagebright, blendbright;
d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi]; SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue);
SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
// slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway
brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255;
} }
if (m >= d)
m = d-1;
// calculate the "gradient" multiplier based on how close this color is to the one next in line
if (m <= 0 || d <= 0)
mul = 0;
else
mul = 15 - ((m * 16) / d);
} }
else else
{ {
// Thankfully, it's normally way more simple. if (blendimage->s.alpha == 0)
// Just convert brightness to a skincolor value, use remainder to find the gradient multipler {
firsti = ((UINT8)(255-brightness) / 16); cur->rgba = image->rgba;
secondi = firsti+1; goto skippixel; // for metal sonic blend
mul = ((UINT8)(255-brightness) % 16); }
}
blendcolor = V_GetColor(translation[firsti]);
if (mul > 0 // If it's 0, then we only need the first color.
&& translation[firsti] != translation[secondi]) // Some colors have duplicate colors in a row, so let's just save the process
{
if (secondi == 16) // blend to black
nextcolor = V_GetColor(31);
else else
nextcolor = V_GetColor(translation[secondi]); {
SETBRIGHTNESS(brightness,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
// Find difference between points }
r = (UINT32)(nextcolor.s.red - blendcolor.s.red);
g = (UINT32)(nextcolor.s.green - blendcolor.s.green);
b = (UINT32)(nextcolor.s.blue - blendcolor.s.blue);
// Find the gradient of the two points
r = ((mul * r) / 16);
g = ((mul * g) / 16);
b = ((mul * b) / 16);
// Add gradient value to color
blendcolor.s.red += r;
blendcolor.s.green += g;
blendcolor.s.blue += b;
} }
}
if (skinnum == TC_RAINBOW) // Calculate a sort of "gradient" for the skincolor
{ // (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...)
UINT32 tempcolor; {
UINT16 colorbright; RGBA_t nextcolor;
UINT8 firsti, secondi, mul, mulmax;
INT32 r, g, b;
SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); // Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors.
if (colorbright == 0) // Ensue horrible mess.
colorbright = 1; // no dividing by 0 please if (skinnum == TC_RAINBOW)
{
UINT16 brightdif = 256;
UINT8 colorbrightnesses[16];
INT32 compare, m, d;
tempcolor = (brightness * blendcolor.s.red) / colorbright; // Ignore pure white & pitch black
tempcolor = min(255, tempcolor); if (brightness > 253 || brightness < 2)
cur->s.red = (UINT8)tempcolor; {
cur->rgba = image->rgba;
cur++; image++; blendimage++;
continue;
}
tempcolor = (brightness * blendcolor.s.green) / colorbright; firsti = 0;
tempcolor = min(255, tempcolor); mul = 0;
cur->s.green = (UINT8)tempcolor; mulmax = 1;
tempcolor = (brightness * blendcolor.s.blue) / colorbright; for (i = 0; i < translen; i++)
tempcolor = min(255, tempcolor); {
cur->s.blue = (UINT8)tempcolor; RGBA_t tempc = V_GetColor(translation[i]);
cur->s.alpha = image->s.alpha; SETBRIGHTNESS(colorbrightnesses[i], tempc.s.red, tempc.s.green, tempc.s.blue); // store brightnesses for comparison
} }
else
{
// Color strength depends on image alpha
INT32 tempcolor;
tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255); for (i = 0; i < translen; i++)
tempcolor = min(255, tempcolor); {
cur->s.red = (UINT8)tempcolor; if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is)
continue;
tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255); compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness));
tempcolor = min(255, tempcolor);
cur->s.green = (UINT8)tempcolor;
tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255); if (compare < brightdif)
tempcolor = min(255, tempcolor); {
cur->s.blue = (UINT8)tempcolor; brightdif = (UINT16)compare;
cur->s.alpha = image->s.alpha; firsti = i; // best matching color that's equal brightness or darker
}
}
secondi = firsti+1; // next color in line
if (secondi >= translen)
{
m = (INT16)brightness; // - 0;
d = (INT16)colorbrightnesses[firsti]; // - 0;
}
else
{
m = (INT16)brightness - (INT16)colorbrightnesses[secondi];
d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi];
}
if (m >= d)
m = d-1;
mulmax = 16;
// calculate the "gradient" multiplier based on how close this color is to the one next in line
if (m <= 0 || d <= 0)
mul = 0;
else
mul = (mulmax-1) - ((m * mulmax) / d);
}
else
{
// Just convert brightness to a skincolor value, use distance to next position to find the gradient multipler
firsti = 0;
for (i = 1; i < translen; i++)
{
if (brightness >= cutoff[i])
break;
firsti = i;
}
secondi = firsti+1;
mulmax = cutoff[firsti];
if (secondi < translen)
mulmax -= cutoff[secondi];
mul = cutoff[firsti] - brightness;
}
blendcolor = V_GetColor(translation[firsti]);
if (mul > 0) // If it's 0, then we only need the first color.
{
if (secondi >= translen) // blend to black
nextcolor = V_GetColor(31);
else
nextcolor = V_GetColor(translation[secondi]);
// Find difference between points
r = (INT32)(nextcolor.s.red - blendcolor.s.red);
g = (INT32)(nextcolor.s.green - blendcolor.s.green);
b = (INT32)(nextcolor.s.blue - blendcolor.s.blue);
// Find the gradient of the two points
r = ((mul * r) / mulmax);
g = ((mul * g) / mulmax);
b = ((mul * b) / mulmax);
// Add gradient value to color
blendcolor.s.red += r;
blendcolor.s.green += g;
blendcolor.s.blue += b;
}
}
if (skinnum == TC_RAINBOW)
{
UINT32 tempcolor;
UINT16 colorbright;
SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue);
if (colorbright == 0)
colorbright = 1; // no dividing by 0 please
tempcolor = (brightness * blendcolor.s.red) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.red = (UINT8)tempcolor;
tempcolor = (brightness * blendcolor.s.green) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.green = (UINT8)tempcolor;
tempcolor = (brightness * blendcolor.s.blue) / colorbright;
tempcolor = min(255, tempcolor);
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
}
else
{
// Color strength depends on image alpha
INT32 tempcolor;
tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.red = (UINT8)tempcolor;
tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.green = (UINT8)tempcolor;
tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255);
tempcolor = min(255, tempcolor);
cur->s.blue = (UINT8)tempcolor;
cur->s.alpha = image->s.alpha;
}
skippixel:
// *Now* we can do Metal Sonic's flashing
if (skinnum == TC_METALSONIC)
{
// Blend dark blue into white
if (cur->s.alpha > 0 && cur->s.red == 0 && cur->s.green == 0 && cur->s.blue < 255 && cur->s.blue > 31)
{
// Sal: Invert non-blue
cur->s.red = cur->s.green = (255 - cur->s.blue);
cur->s.blue = 255;
}
cur->s.alpha = image->s.alpha;
}
} }
} }
cur++; image++; blendimage++; cur++; image++;
if (blendimage != NULL)
blendimage++;
} }
return; return;
@ -977,6 +1046,14 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT
// If here, the blended texture has not been created // If here, the blended texture has not been created
// So we create it // So we create it
if ((blendgpatch && blendgpatch->mipmap->grInfo.format)
&& (gpatch->width != blendgpatch->width || gpatch->height != blendgpatch->height))
{
// Blend image exists, but it's bad.
HWD.pfnSetTexture(gpatch->mipmap);
return;
}
//BP: WARNING: don't free it manually without clearing the cache of harware renderer //BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap) // (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache // this malloc is cleared in HWR_FreeTextureCache
@ -1221,50 +1298,44 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
{ {
if (md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format INT32 skinnum = INT32_MAX;
&& gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height)
{
INT32 skinnum = INT32_MAX;
if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized)
skinnum = TC_ALLWHITE;
else if (spr->mobj->type == MT_METALSONIC_BATTLE)
skinnum = TC_METALSONIC;
else
skinnum = TC_BOSS;
}
else if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE)
{
if (spr->mobj->colorized)
skinnum = TC_RAINBOW;
else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (spr->mobj->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{
if (spr->mobj->player->charflags & SF_MACHINE)
skinnum = TC_DASHMODE;
else
skinnum = TC_RAINBOW;
}
else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
else
skinnum = TC_DEFAULT;
}
// Translation or skin number found if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
if (skinnum != INT32_MAX) {
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color); if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized)
skinnum = TC_ALLWHITE;
else if (spr->mobj->type == MT_METALSONIC_BATTLE)
skinnum = TC_METALSONIC;
else else
skinnum = TC_BOSS;
}
else if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE)
{
if (spr->mobj->colorized)
skinnum = TC_RAINBOW;
else if (spr->mobj->player && spr->mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (spr->mobj->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{ {
// Sorry nothing if (spr->mobj->player->charflags & SF_MACHINE)
HWD.pfnSetTexture(gpatch->mipmap); skinnum = TC_DASHMODE;
else
skinnum = TC_RAINBOW;
} }
else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
else
skinnum = TC_DEFAULT;
}
// Translation or skin number found
if (skinnum != INT32_MAX)
{
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
} }
else else
{ {
// This is safe, since we know the texture has been downloaded // Sorry nothing
HWD.pfnSetTexture(gpatch->mipmap); HWD.pfnSetTexture(gpatch->mipmap);
} }
} }

View file

@ -2222,11 +2222,11 @@ EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration,
EXPORT void HWRAPI(SetTransform) (FTransform *stransform) EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
{ {
static boolean special_splitscreen; static boolean special_splitscreen;
float used_fov;
pglLoadIdentity(); pglLoadIdentity();
if (stransform) if (stransform)
{ {
boolean fovx90; used_fov = stransform->fovxangle;
#ifdef USE_FTRANSFORM_MIRROR #ifdef USE_FTRANSFORM_MIRROR
// mirroring from Kart // mirroring from Kart
if (stransform->mirror) if (stransform->mirror)
@ -2242,32 +2242,28 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f); pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f);
pglTranslatef(-stransform->x, -stransform->z, -stransform->y); pglTranslatef(-stransform->x, -stransform->z, -stransform->y);
pglMatrixMode(GL_PROJECTION); special_splitscreen = stransform->splitscreen;
pglLoadIdentity();
fovx90 = stransform->fovxangle > 0.0f && fabsf(stransform->fovxangle - 90.0f) < 0.5f;
special_splitscreen = (stransform->splitscreen && fovx90);
if (special_splitscreen)
GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5)
else
GLPerspective(stransform->fovxangle, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
} }
else else
{ {
used_fov = fov;
pglScalef(1.0f, 1.0f, -1.0f); pglScalef(1.0f, 1.0f, -1.0f);
pglMatrixMode(GL_PROJECTION);
pglLoadIdentity();
if (special_splitscreen)
GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5)
else
//Hurdler: is "fov" correct?
GLPerspective(fov, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
} }
pglMatrixMode(GL_PROJECTION);
pglLoadIdentity();
if (special_splitscreen)
{
used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI;
GLPerspective(used_fov, 2*ASPECT_RATIO);
}
else
GLPerspective(used_fov, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer)
} }

View file

@ -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,37 +502,31 @@ 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);
// check for undesirable characters in our "number" // check for undesirable characters in our "number"
if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9'))) if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
{ {
// check if playernum[1] is a space // check if playernum[1] is a space
if (playernum[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<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);
{ return;
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false); }
free(playernum);
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,13 +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);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
@ -679,13 +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);
char buf[2];
buf[0] = (char)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return; return;
} }
} }
@ -1033,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)
@ -1094,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.
@ -1108,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;
} }
} }
@ -1128,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!
@ -1147,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);
} }
@ -1349,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
c_input--; {
if (ctrldown)
c_input = M_JumpWordReverse(w_chat, c_input);
else
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.
c_input++; {
if (ctrldown)
c_input += M_JumpWord(&w_chat[c_input]);
else
c_input++;
}
return true; return true;
} }
#endif #endif
@ -1660,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)
@ -1806,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'))
@ -1867,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.
} }

View file

@ -1849,18 +1849,19 @@ state_t states[NUMSTATES] =
{SPR_BBLS, 3, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES1}, // S_BUBBLES4 {SPR_BBLS, 3, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES1}, // S_BUBBLES4
// Level End Sign // Level End Sign
{SPR_SIGN, 0, -1, {A_SignPlayer}, -3, 0, S_NULL}, // S_SIGN {SPR_SIGN, 0, -1, {A_SignPlayer}, -3, 0, S_NULL}, // S_SIGN
{SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN2}, // S_SIGNSPIN1 {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN2}, // S_SIGNSPIN1
{SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN1, S_SIGNSPIN3}, // S_SIGNSPIN2 {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN1, S_SIGNSPIN3}, // S_SIGNSPIN2
{SPR_SIGN, 0, 0, {A_SignPlayer}, -2, 0, S_SIGNSPIN4}, // S_SIGNSPIN3 {SPR_SIGN, 0, 0, {A_SignPlayer}, -2, 0, S_SIGNSPIN4}, // S_SIGNSPIN3
{SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN5}, // S_SIGNSPIN4 {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN5}, // S_SIGNSPIN4
{SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN4, S_SIGNSPIN6}, // S_SIGNSPIN5 {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN4, S_SIGNSPIN6}, // S_SIGNSPIN5
{SPR_SIGN, 0, 0, {A_SignPlayer}, -3, 0, S_SIGNSPIN1}, // S_SIGNSPIN6 {SPR_SIGN, 0, 0, {A_SignPlayer}, -3, 0, S_SIGNSPIN1}, // S_SIGNSPIN6
{SPR_SIGN, 0, 1, {A_SignPlayer}, -1, 0, S_SIGNSLOW}, // S_SIGNPLAYER {SPR_SIGN, 0, 1, {A_SignPlayer}, -1, 0, S_SIGNSLOW}, // S_SIGNPLAYER
{SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSLOW}, // S_SIGNSLOW {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSLOW}, // S_SIGNSLOW
{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
@ -5734,7 +5735,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass 0, // mass
0, // damage 0, // damage
sfx_spring, // activesound sfx_spring, // activesound
MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING, // flags MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT, // flags
S_EGGMOBILE2_POGO5 // raisestate S_EGGMOBILE2_POGO5 // raisestate
}, },
@ -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
@ -19760,14 +19761,14 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_FLINGNIGHTSCHIP { // MT_FLINGNIGHTSCHIP
-1, // doomednum -1, // doomednum
S_NIGHTSCHIP, // spawnstate S_NIGHTSCHIP, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
MT_FLINGNIGHTSCHIP, // reactiontime MT_FLINGNIGHTSCHIP, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
MT_NIGHTSCHIP, // painchance MT_NIGHTSCHIP, // painchance
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
@ -19791,7 +19792,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1000, // spawnhealth 1000, // spawnhealth
S_NIGHTSSTARXMAS, // seestate S_NIGHTSSTARXMAS, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime MT_FLINGNIGHTSSTAR, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
0, // painchance 0, // painchance
@ -19811,6 +19812,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_FLINGNIGHTSSTAR
-1, // doomednum
S_NIGHTSSTAR, // spawnstate
1000, // spawnhealth
S_NIGHTSSTARXMAS, // seestate
sfx_None, // seesound
MT_FLINGNIGHTSSTAR, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
MT_NIGHTSSTAR, // painchance
sfx_s3k33, // painsound
S_RING, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_ncitem, // deathsound
38*FRACUNIT, // speed
16*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL, // flags
S_NULL // raisestate
},
{ // MT_NIGHTSSUPERLOOP { // MT_NIGHTSSUPERLOOP
1707, // doomednum 1707, // doomednum

View file

@ -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,
@ -4702,6 +4703,7 @@ typedef enum mobj_type
MT_NIGHTSCHIP, // NiGHTS Chip MT_NIGHTSCHIP, // NiGHTS Chip
MT_FLINGNIGHTSCHIP, // Lost NiGHTS Chip MT_FLINGNIGHTSCHIP, // Lost NiGHTS Chip
MT_NIGHTSSTAR, // NiGHTS Star MT_NIGHTSSTAR, // NiGHTS Star
MT_FLINGNIGHTSSTAR, // Lost NiGHTS Star
MT_NIGHTSSUPERLOOP, MT_NIGHTSSUPERLOOP,
MT_NIGHTSDRILLREFILL, MT_NIGHTSDRILLREFILL,
MT_NIGHTSHELPER, MT_NIGHTSHELPER,

View file

@ -2193,6 +2193,20 @@ static int lib_rPointInSubsector(lua_State *L)
return 1; return 1;
} }
static int lib_rIsPointInSubsector(lua_State *L)
{
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
subsector_t *sub = R_IsPointInSubsector(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_IsPointInSubsector",lib_rIsPointInSubsector},
// r_things (sprite) // r_things (sprite)
{"R_Char2Frame",lib_rChar2Frame}, {"R_Char2Frame",lib_rChar2Frame},

View file

@ -87,13 +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);
UINT8 bufn[2];
bufn[0] = (UINT8)playernum;
bufn[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &bufn, 2);
}
} }
// Wrapper for COM_AddCommand commands // Wrapper for COM_AddCommand commands

View file

@ -57,6 +57,7 @@ enum hook {
hook_TeamSwitch, hook_TeamSwitch,
hook_ViewpointSwitch, hook_ViewpointSwitch,
hook_SeenPlayer, hook_SeenPlayer,
hook_PlayerThink,
hook_MAX // last hook hook_MAX // last hook
}; };
@ -108,5 +109,6 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
#ifdef SEENAMES #ifdef SEENAMES
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
#endif #endif
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
#endif #endif

View file

@ -68,6 +68,7 @@ const char *const hookNames[hook_MAX+1] = {
"TeamSwitch", "TeamSwitch",
"ViewpointSwitch", "ViewpointSwitch",
"SeenPlayer", "SeenPlayer",
"PlayerThink",
NULL NULL
}; };
@ -216,6 +217,7 @@ static int lib_addHook(lua_State *L)
case hook_SeenPlayer: case hook_SeenPlayer:
case hook_ShieldSpawn: case hook_ShieldSpawn:
case hook_ShieldSpecial: case hook_ShieldSpecial:
case hook_PlayerThink:
lastp = &playerhooks; lastp = &playerhooks;
break; break;
case hook_LinedefExecute: case hook_LinedefExecute:

View file

@ -157,13 +157,21 @@ static const char *const side_opt[] = {
enum vertex_e { enum vertex_e {
vertex_valid = 0, vertex_valid = 0,
vertex_x, vertex_x,
vertex_y vertex_y,
vertex_floorz,
vertex_floorzset,
vertex_ceilingz,
vertex_ceilingzset
}; };
static const char *const vertex_opt[] = { static const char *const vertex_opt[] = {
"valid", "valid",
"x", "x",
"y", "y",
"floorz",
"floorzset",
"ceilingz",
"ceilingzset",
NULL}; NULL};
enum ffloor_e { enum ffloor_e {
@ -968,6 +976,18 @@ static int vertex_get(lua_State *L)
case vertex_y: case vertex_y:
lua_pushfixed(L, vertex->y); lua_pushfixed(L, vertex->y);
return 1; return 1;
case vertex_floorzset:
lua_pushboolean(L, vertex->floorzset);
return 1;
case vertex_ceilingzset:
lua_pushboolean(L, vertex->ceilingzset);
return 1;
case vertex_floorz:
lua_pushfixed(L, vertex->floorz);
return 1;
case vertex_ceilingz:
lua_pushfixed(L, vertex->ceilingz);
return 1;
} }
return 0; return 0;
} }
@ -2014,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"))

View file

@ -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));

View file

@ -274,12 +274,6 @@ int LUA_PushGlobals(lua_State *L, const char *word)
return 0; return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1; return 1;
} else if (fastcmp(word,"admin")) { // BACKWARDS COMPATIBILITY HACK: This was replaced with IsPlayerAdmin(), but some 2.1 Lua scripts still use the admin variable. It now points to the first admin player in the array.
LUA_Deprecated(L, "admin", "IsPlayerAdmin(player)");
if (!playeringame[adminplayers[0]] || IsPlayerAdmin(serverplayer))
return 0;
LUA_PushUserdata(L, &players[adminplayers[0]], META_PLAYER);
return 1;
} else if (fastcmp(word,"emeralds")) { } else if (fastcmp(word,"emeralds")) {
lua_pushinteger(L, emeralds); lua_pushinteger(L, emeralds);
return 1; return 1;

View file

@ -97,12 +97,13 @@ typedef struct
} emblem_t; } emblem_t;
typedef struct typedef struct
{ {
char name[20]; ///< Name of the goal (used in the "emblem awarded" cecho) char name[20]; ///< Name of the goal (used in the "emblem awarded" cecho)
char description[40];///< Description of goal (used in statistics) char description[40]; ///< Description of goal (used in statistics)
UINT8 conditionset; ///< Condition set that awards this emblem. UINT8 conditionset; ///< Condition set that awards this emblem.
UINT8 sprite; ///< emblem sprite to use, 0 - 25 UINT8 showconditionset; ///< Condition set that shows this emblem.
UINT8 color; ///< skincolor to use UINT8 sprite; ///< emblem sprite to use, 0 - 25
UINT8 collected; ///< Do you have this emblem? UINT8 color; ///< skincolor to use
UINT8 collected; ///< Do you have this emblem?
} extraemblem_t; } extraemblem_t;
// Unlockable information // Unlockable information
@ -112,6 +113,7 @@ typedef struct
char objective[64]; char objective[64];
UINT16 height; // menu height UINT16 height; // menu height
UINT8 conditionset; UINT8 conditionset;
UINT8 showconditionset;
INT16 type; INT16 type;
INT16 variable; INT16 variable;
UINT8 nocecho; UINT8 nocecho;

View file

@ -1397,7 +1397,7 @@ static menuitem_t OP_OpenGLOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Model lighting", &cv_grmodellighting, 32}, {IT_STRING|IT_CVAR, NULL, "Model lighting", &cv_grmodellighting, 32},
{IT_HEADER, NULL, "General", NULL, 51}, {IT_HEADER, NULL, "General", NULL, 51},
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 63}, {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 63},
{IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 73}, {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 73},
{IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 83}, {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 83},
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,93}, {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,93},
@ -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
}; };
@ -6897,6 +6899,8 @@ static void M_HandleChecklist(INT32 choice)
continue; continue;
if (unlockables[j].conditionset > MAXCONDITIONSETS) if (unlockables[j].conditionset > MAXCONDITIONSETS)
continue; continue;
if (!unlockables[j].unlocked && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset))
continue;
if (unlockables[j].conditionset == unlockables[check_on].conditionset) if (unlockables[j].conditionset == unlockables[check_on].conditionset)
continue; continue;
break; break;
@ -6920,6 +6924,8 @@ static void M_HandleChecklist(INT32 choice)
continue; continue;
if (unlockables[j].conditionset > MAXCONDITIONSETS) if (unlockables[j].conditionset > MAXCONDITIONSETS)
continue; continue;
if (!unlockables[j].unlocked && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset))
continue;
if (j && unlockables[j].conditionset == unlockables[j-1].conditionset) if (j && unlockables[j].conditionset == unlockables[j-1].conditionset)
continue; continue;
break; break;
@ -6957,7 +6963,8 @@ static void M_DrawChecklist(void)
while (i < MAXUNLOCKABLES) while (i < MAXUNLOCKABLES)
{ {
if (unlockables[i].name[0] == 0 //|| unlockables[i].nochecklist if (unlockables[i].name[0] == 0 //|| unlockables[i].nochecklist
|| !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS) || !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS
|| (!unlockables[i].unlocked && unlockables[i].showconditionset && !M_Achieved(unlockables[i].showconditionset)))
{ {
i += 1; i += 1;
continue; continue;
@ -6983,10 +6990,11 @@ static void M_DrawChecklist(void)
if (unlockables[i].objective[0] != '/') if (unlockables[i].objective[0] != '/')
{ {
addy(8); addy(16);
V_DrawString(currentMenu->x, y, V_DrawString(currentMenu->x, y-8,
V_ALLOWLOWERCASE, V_ALLOWLOWERCASE,
va("\x1E %s", unlockables[i].objective)); va("\x1E %s", unlockables[i].objective));
y -= 8;
} }
else else
{ {
@ -7227,12 +7235,31 @@ static void M_EmblemHints(INT32 choice)
static void M_DrawEmblemHints(void) static void M_DrawEmblemHints(void)
{ {
INT32 i, j = 0; INT32 i, j = 0, x, y, left_hints = NUMHINTS;
UINT32 collected = 0; UINT32 collected = 0, local = 0;
emblem_t *emblem; emblem_t *emblem;
const char *hint; const char *hint;
for (i = 0; i < numemblems; i++) for (i = 0; i < numemblems; i++)
{
emblem = &emblemlocations[i];
if (emblem->level != gamemap || emblem->type > ET_SKIN)
continue;
if (++local >= NUMHINTS*2)
break;
}
x = (local > NUMHINTS ? 4 : 12);
y = 8;
// If there are more than 1 page's but less than 2 pages' worth of emblems,
// put half (rounded up) of the hints on the left, and half (rounded down) on the right
if (local > NUMHINTS && local < (NUMHINTS*2)-1)
left_hints = (local + 1) / 2;
if (!local)
V_DrawCenteredString(160, 48, V_YELLOWMAP, "No hidden emblems on this map.");
else for (i = 0; i < numemblems; i++)
{ {
emblem = &emblemlocations[i]; emblem = &emblemlocations[i];
if (emblem->level != gamemap || emblem->type > ET_SKIN) if (emblem->level != gamemap || emblem->type > ET_SKIN)
@ -7241,27 +7268,35 @@ static void M_DrawEmblemHints(void)
if (emblem->collected) if (emblem->collected)
{ {
collected = V_GREENMAP; collected = V_GREENMAP;
V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), V_DrawMappedPatch(x, y+4, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE));
} }
else else
{ {
collected = 0; collected = 0;
V_DrawScaledPatch(12, 12+(28*j), 0, W_CachePatchName("NEEDIT", PU_PATCH)); V_DrawScaledPatch(x, y+4, 0, W_CachePatchName("NEEDIT", PU_PATCH));
} }
if (emblem->hint[0]) if (emblem->hint[0])
hint = emblem->hint; hint = emblem->hint;
else else
hint = M_GetText("No hints available."); hint = M_GetText("No hint available for this emblem.");
hint = V_WordWrap(40, BASEVIDWIDTH-12, 0, hint); hint = V_WordWrap(40, BASEVIDWIDTH-12, 0, hint);
V_DrawString(40, 8+(28*j), V_RETURN8|V_ALLOWLOWERCASE|collected, hint); if (local > NUMHINTS)
V_DrawThinString(x+28, y, V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
else
V_DrawString(x+28, y, V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
if (++j >= NUMHINTS) y += 28;
if (++j == left_hints)
{
x = 4+(BASEVIDWIDTH/2);
y = 8;
}
else if (j >= NUMHINTS*2)
break; break;
} }
if (!j)
V_DrawCenteredString(160, 48, V_YELLOWMAP, "No hidden emblems on this map.");
M_DrawGenericMenu(); M_DrawGenericMenu();
} }
@ -9196,7 +9231,10 @@ static void M_DrawStatsMaps(int location)
else else
V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_PATCH)); V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_PATCH));
V_DrawString(20, y, V_YELLOWMAP|V_ALLOWLOWERCASE, va("%s", exemblem->description)); V_DrawString(20, y, V_YELLOWMAP|V_ALLOWLOWERCASE,
(!exemblem->collected && exemblem->showconditionset && !M_Achieved(exemblem->showconditionset))
? M_CreateSecretMenuOption(exemblem->description)
: exemblem->description);
} }
y += 8; y += 8;
@ -10595,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
{ {
@ -10604,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

View file

@ -1594,16 +1594,19 @@ boolean M_ScreenshotResponder(event_t *ev)
// M_StartupLocale. // M_StartupLocale.
// Sets up gettext to translate SRB2's strings. // Sets up gettext to translate SRB2's strings.
#ifdef GETTEXT #ifdef GETTEXT
#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
#define GETTEXTDOMAIN1 "/usr/share/locale" #define GETTEXTDOMAIN1 "/usr/share/locale"
#define GETTEXTDOMAIN2 "/usr/local/share/locale" #define GETTEXTDOMAIN2 "/usr/local/share/locale"
#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;
}

View file

@ -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);

View file

@ -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;
@ -356,50 +352,100 @@ 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 (async) // do asynchronous connection if (!bindaddr || bind(socket_fd, bindaddr, bindaddrlen) == 0)
{ {
if (async) // do asynchronous connection
{
#ifdef FIONBIO #ifdef FIONBIO
#ifdef WATTCP #ifdef WATTCP
char res = 1; char res = 1;
#else #else
unsigned long res = 1; unsigned long res = 1;
#endif #endif
ioctl(socket_fd, FIONBIO, &res); ioctl(socket_fd, FIONBIO, &res);
#endif #endif
if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET) if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET)
{
#ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows)
if (WSAGetLastError() != WSAEWOULDBLOCK)
#else
if (errno != EINPROGRESS)
#endif
{ {
con_state = MSCS_FAILED; #ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows)
CloseConnection(); if (WSAGetLastError() != WSAEWOULDBLOCK)
I_freeaddrinfo(ai); #else
return MS_CONNECT_ERROR; if (errno != EINPROGRESS)
#endif
{
con_state = MSCS_FAILED;
CloseConnection();
I_freeaddrinfo(ai);
return MS_CONNECT_ERROR;
}
} }
con_state = MSCS_WAITING;
FD_ZERO(&wset);
FD_SET(socket_fd, &wset);
select_timeout.tv_sec = 0, select_timeout.tv_usec = 0;
I_freeaddrinfo(ai);
return 0;
}
else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET)
{
I_freeaddrinfo(ai);
return 0;
} }
con_state = MSCS_WAITING;
FD_ZERO(&wset);
FD_SET(socket_fd, &wset);
select_timeout.tv_sec = 0, select_timeout.tv_usec = 0;
I_freeaddrinfo(ai);
return 0;
} }
else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET) close(socket_fd);
}
runp = runp->ai_next;
}
I_freeaddrinfo(ai);
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); I_freeaddrinfo(ai);
return 0; return 0;
} }
} }
runp = runp->ai_next; I_freeaddrinfo(ai);
return c;
} }
I_freeaddrinfo(ai); else
#endif return MS_SubConnect(ip_addr, str_port, async, 0, 0);
return MS_CONNECT_ERROR; #endif/*NONET xd*/
} }
#define NUM_LIST_SERVER MAXSERVERLIST #define NUM_LIST_SERVER MAXSERVERLIST

View file

@ -5177,6 +5177,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,33 +5189,25 @@ 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) UINT8 skincount = 0;
if (ov->skin == NULL) // pick a random skin to start with! for (skincount = 0; skincount < numskins; skincount++)
if (!skincheck(skincount))
skincount++;
skinnum = P_RandomKey(skincount);
for (skincount = 0; skincount < numskins; skincount++)
{ {
UINT8 skincount = 0; if (skincount > skinnum)
for (skincount = 0; skincount < numskins; skincount++) break;
if (!skincheck(skincount)) if (skincheck(skincount))
skincount++; skinnum++;
skinnum = P_RandomKey(skincount);
for (skincount = 0; skincount < numskins; skincount++)
{
if (skincount > skinnum)
break;
if (skincheck(skincount))
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 +5215,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)
{ {
ov->color = facecolor; if (skin->sprites[SPR2_SIGN].numframes) // player face
ov->skin = skin; {
P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN ov->color = facecolor;
ov->skin = skin;
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;

View file

@ -433,7 +433,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|| special->state == &states[S_FANG_BOUNCE4] || special->state == &states[S_FANG_BOUNCE4]
|| special->state == &states[S_FANG_PINCHBOUNCE3] || special->state == &states[S_FANG_PINCHBOUNCE3]
|| special->state == &states[S_FANG_PINCHBOUNCE4]) || special->state == &states[S_FANG_PINCHBOUNCE4])
&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > (special->height/4)) && P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z + toucher->height/2)) > (toucher->height/2))
{ {
P_DamageMobj(toucher, special, special, 1, 0); P_DamageMobj(toucher, special, special, 1, 0);
P_SetTarget(&special->tracer, toucher); P_SetTarget(&special->tracer, toucher);
@ -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.

View file

@ -644,7 +644,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;
@ -657,7 +657,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;
@ -690,7 +690,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;
@ -703,7 +703,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;

View file

@ -3127,7 +3127,7 @@ nightsdone:
{ {
// DO THE MARIO! // DO THE MARIO!
if (rover->flags & FF_SHATTERBOTTOM) // Brick block! if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
EV_CrumbleChain(NULL, rover); // node->m_sector EV_CrumbleChain(node->m_sector, rover);
else // Question block! else // Question block!
EV_MarioBlock(rover, node->m_sector, mo); EV_MarioBlock(rover, node->m_sector, mo);
} }
@ -3902,11 +3902,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;
} }
} }
@ -10553,6 +10557,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!

View file

@ -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;

View file

@ -223,6 +223,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;
@ -853,6 +854,8 @@ static void P_LoadVertices(UINT8 *data)
{ {
v->x = SHORT(mv->x)<<FRACBITS; v->x = SHORT(mv->x)<<FRACBITS;
v->y = SHORT(mv->y)<<FRACBITS; v->y = SHORT(mv->y)<<FRACBITS;
v->floorzset = v->ceilingzset = false;
v->floorz = v->ceilingz = 0;
} }
} }
@ -1112,8 +1115,8 @@ static void P_LoadSidedefs(UINT8 *data)
if (((sd->line->flags & (ML_TWOSIDED|ML_EFFECT5)) == (ML_TWOSIDED|ML_EFFECT5)) if (((sd->line->flags & (ML_TWOSIDED|ML_EFFECT5)) == (ML_TWOSIDED|ML_EFFECT5))
&& !(sd->special >= 300 && sd->special < 500)) // exempt linedef exec specials && !(sd->special >= 300 && sd->special < 500)) // exempt linedef exec specials
{ {
sd->repeatcnt = (INT16)(((unsigned)textureoffset) >> 12); sd->repeatcnt = (INT16)(((UINT16)textureoffset) >> 12);
sd->textureoffset = (((unsigned)textureoffset) & 2047) << FRACBITS; sd->textureoffset = (((UINT16)textureoffset) & 2047) << FRACBITS;
} }
else else
{ {
@ -1373,6 +1376,16 @@ static void ParseTextmapVertexParameter(UINT32 i, char *param, char *val)
vertexes[i].x = FLOAT_TO_FIXED(atof(val)); vertexes[i].x = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "y")) else if (fastcmp(param, "y"))
vertexes[i].y = FLOAT_TO_FIXED(atof(val)); vertexes[i].y = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "zfloor"))
{
vertexes[i].floorz = FLOAT_TO_FIXED(atof(val));
vertexes[i].floorzset = true;
}
else if (fastcmp(param, "zceiling"))
{
vertexes[i].ceilingz = FLOAT_TO_FIXED(atof(val));
vertexes[i].ceilingzset = true;
}
} }
static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
@ -1580,6 +1593,8 @@ static void P_LoadTextmap(void)
{ {
// Defaults. // Defaults.
vt->x = vt->y = INT32_MAX; vt->x = vt->y = INT32_MAX;
vt->floorzset = vt->ceilingzset = false;
vt->floorz = vt->ceilingz = 0;
TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter);
@ -3574,11 +3589,11 @@ boolean P_LoadLevel(boolean fromnetsave)
return false; return false;
// init gravity, tag lists, // init gravity, tag lists,
// anything that P_ResetDynamicSlopes/P_LoadThings needs to know // anything that P_SpawnSlopes/P_LoadThings needs to know
P_InitSpecials(); P_InitSpecials();
#ifdef ESLOPE #ifdef ESLOPE
P_ResetDynamicSlopes(fromnetsave); P_SpawnSlopes(fromnetsave);
#endif #endif
P_SpawnMapThings(!fromnetsave); P_SpawnMapThings(!fromnetsave);

View file

@ -458,8 +458,8 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
return ret; return ret;
} }
/// Create vertex based slopes. /// Create vertex based slopes using tagged mapthings.
static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker) static void line_SpawnViaMapthingVertexes(const int linenum, const boolean spawnthinker)
{ {
line_t *line = lines + linenum; line_t *line = lines + linenum;
side_t *side; side_t *side;
@ -507,6 +507,55 @@ static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker)
side->sector->hasslope = true; side->sector->hasslope = true;
} }
/// Spawn textmap vertex slopes.
static void SpawnVertexSlopes(void)
{
line_t *l1, *l2;
sector_t* sc;
vertex_t *v1, *v2, *v3;
size_t i;
for (i = 0, sc = sectors; i < numsectors; i++, sc++)
{
// The vertex slopes only work for 3-vertex sectors (and thus 3-sided sectors).
if (sc->linecount != 3)
continue;
l1 = sc->lines[0];
l2 = sc->lines[1];
// Determine the vertexes.
v1 = l1->v1;
v2 = l1->v2;
if ((l2->v1 != v1) && (l2->v1 != v2))
v3 = l2->v1;
else
v3 = l2->v2;
if (v1->floorzset || v2->floorzset || v3->floorzset)
{
vector3_t vtx[3] = {
{v1->x, v1->y, v1->floorzset ? v1->floorz : sc->floorheight},
{v2->x, v2->y, v2->floorzset ? v2->floorz : sc->floorheight},
{v3->x, v3->y, v3->floorzset ? v3->floorz : sc->floorheight}};
pslope_t *slop = Slope_Add(0);
sc->f_slope = slop;
sc->hasslope = true;
ReconfigureViaVertexes(slop, vtx[0], vtx[1], vtx[2]);
}
if (v1->ceilingzset || v2->ceilingzset || v3->ceilingzset)
{
vector3_t vtx[3] = {
{v1->x, v1->y, v1->ceilingzset ? v1->ceilingz : sc->ceilingheight},
{v2->x, v2->y, v2->ceilingzset ? v2->ceilingz : sc->ceilingheight},
{v3->x, v3->y, v3->ceilingzset ? v3->ceilingz : sc->ceilingheight}};
pslope_t *slop = Slope_Add(0);
sc->c_slope = slop;
sc->hasslope = true;
ReconfigureViaVertexes(slop, vtx[0], vtx[1], vtx[2]);
}
}
}
// //
// P_CopySectorSlope // P_CopySectorSlope
@ -551,12 +600,16 @@ pslope_t *P_SlopeById(UINT16 id)
return ret; return ret;
} }
/// Reset slopes and read them from special lines. /// Initializes and reads the slopes from the map data.
void P_ResetDynamicSlopes(const boolean fromsave) { void P_SpawnSlopes(const boolean fromsave) {
size_t i; size_t i;
slopelist = NULL; slopelist = NULL;
slopecount = 0; slopecount = 0;
/// Generates vertex slopes.
SpawnVertexSlopes();
/// Generates line special-defined slopes. /// Generates line special-defined slopes.
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
{ {
@ -577,7 +630,7 @@ void P_ResetDynamicSlopes(const boolean fromsave) {
case 705: case 705:
case 714: case 714:
case 715: case 715:
line_SpawnViaVertexes(i, !fromsave); line_SpawnViaMapthingVertexes(i, !fromsave);
break; break;
default: default:

View file

@ -23,7 +23,7 @@ extern UINT16 slopecount;
void P_LinkSlopeThinkers (void); void P_LinkSlopeThinkers (void);
void P_CalculateSlopeNormal(pslope_t *slope); void P_CalculateSlopeNormal(pslope_t *slope);
void P_ResetDynamicSlopes(const boolean fromsave); void P_SpawnSlopes(const boolean fromsave);
// //
// P_CopySectorSlope // P_CopySectorSlope

View file

@ -6354,7 +6354,7 @@ static void P_RunLevelLoadExecutors(void)
} }
/** Before things are loaded, initialises certain stuff in case they're needed /** Before things are loaded, initialises certain stuff in case they're needed
* by P_ResetDynamicSlopes or P_LoadThings. This was split off from * by P_SpawnSlopes or P_LoadThings. This was split off from
* P_SpawnSpecials, in case you couldn't tell. * P_SpawnSpecials, in case you couldn't tell.
* *
* \sa P_SpawnSpecials, P_InitTagLists * \sa P_SpawnSpecials, P_InitTagLists
@ -6932,7 +6932,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

View file

@ -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);
@ -8672,7 +8679,7 @@ static void P_MovePlayer(player_t *player)
} }
#ifdef HWRENDER #ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none && cv_grfovchange.value) if (rendermode != render_soft && rendermode != render_none && cv_fovchange.value)
{ {
fixed_t speed; fixed_t speed;
const fixed_t runnyspeed = 20*FRACUNIT; const fixed_t runnyspeed = 20*FRACUNIT;
@ -9185,7 +9192,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!
@ -9203,7 +9210,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
@ -9279,6 +9286,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction,
// If nonenemies is true, includes monitors and springs! // If nonenemies is true, includes monitors and springs!
// If bullet is true, you can look up and the distance is further, // If bullet is true, you can look up and the distance is further,
// but your total angle span you can look is limited to compensate. (Also, allows monitors.) // but your total angle span you can look is limited to compensate. (Also, allows monitors.)
// If you modify this, please also modify P_HomingAttack.
// //
mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
{ {
@ -9374,15 +9382,18 @@ boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
if (!enemy) if (!enemy)
return false; return false;
if (!enemy->health) if (enemy->flags & MF_NOCLIPTHING)
return false;
if (enemy->health <= 0) // dead
return false;
if (!((enemy->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (enemy->flags & MF_SHOOTABLE)) || (enemy->flags & MF_SPRING)) == !(enemy->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
return false; return false;
if (enemy->flags2 & MF2_FRET) if (enemy->flags2 & MF2_FRET)
return false; return false;
if (!(enemy->flags & (MF_SHOOTABLE|MF_SPRING)) == !(enemy->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
return false;
// change angle // change angle
source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y); source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y);
if (source->player) if (source->player)
@ -10105,13 +10116,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{ {
dist = camdist; dist = camdist;
// x1.5 dist for splitscreen
if (splitscreen)
{
dist = FixedMul(dist, 3*FRACUNIT/2);
camheight = FixedMul(camheight, 3*FRACUNIT/2);
}
if (sign) // signpost camera has specific placement if (sign) // signpost camera has specific placement
{ {
camheight = mo->scale << 7; camheight = mo->scale << 7;
@ -10511,13 +10515,17 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (!(multiplayer || netgame) && !splitscreen) if (!(multiplayer || netgame) && !splitscreen)
{ {
fixed_t vx = thiscam->x, vy = thiscam->y; fixed_t vx = thiscam->x, vy = thiscam->y;
fixed_t vz = thiscam->z + thiscam->height / 2;
if (player->awayviewtics && player->awayviewmobj != NULL && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist if (player->awayviewtics && player->awayviewmobj != NULL && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist
{ {
vx = player->awayviewmobj->x; vx = player->awayviewmobj->x;
vy = player->awayviewmobj->y; vy = player->awayviewmobj->y;
vz = player->awayviewmobj->z + player->awayviewmobj->height / 2;
} }
if (P_AproxDistance(vx - mo->x, vy - mo->y) < FixedMul(48*FRACUNIT, mo->scale)) /* check z distance too for orbital camera */
if (P_AproxDistance(P_AproxDistance(vx - mo->x, vy - mo->y),
vz - ( mo->z + mo->height / 2 )) < FixedMul(48*FRACUNIT, mo->scale))
mo->flags2 |= MF2_SHADOW; mo->flags2 |= MF2_SHADOW;
else else
mo->flags2 &= ~MF2_SHADOW; mo->flags2 &= ~MF2_SHADOW;
@ -11572,7 +11580,12 @@ void P_PlayerThink(player_t *player)
player->playerstate = PST_REBORN; player->playerstate = PST_REBORN;
} }
if (player->playerstate == PST_REBORN) if (player->playerstate == PST_REBORN)
{
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return; return;
}
} }
#ifdef SEENAMES #ifdef SEENAMES
@ -11673,7 +11686,12 @@ void P_PlayerThink(player_t *player)
player->lives = 0; player->lives = 0;
if (player->playerstate == PST_DEAD) if (player->playerstate == PST_DEAD)
{
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return; return;
}
} }
} }
@ -11792,7 +11810,9 @@ void P_PlayerThink(player_t *player)
{ {
player->mo->flags2 &= ~MF2_SHADOW; player->mo->flags2 &= ~MF2_SHADOW;
P_DeathThink(player); P_DeathThink(player);
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return; return;
} }
@ -11833,7 +11853,12 @@ void P_PlayerThink(player_t *player)
if (player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing] && G_GametypeHasSpectators()) if (player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing] && G_GametypeHasSpectators())
{ {
if (P_SpectatorJoinGame(player)) if (P_SpectatorJoinGame(player))
{
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return; // player->mo was removed. return; // player->mo was removed.
}
} }
// Even if not NiGHTS, pull in nearby objects when walking around as John Q. Elliot. // Even if not NiGHTS, pull in nearby objects when walking around as John Q. Elliot.
@ -11935,7 +11960,12 @@ void P_PlayerThink(player_t *player)
} }
if (!player->mo) if (!player->mo)
{
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
return; // P_MovePlayer removed player->mo. return; // P_MovePlayer removed player->mo.
}
// deez New User eXperiences. // deez New User eXperiences.
{ {
@ -12367,6 +12397,11 @@ void P_PlayerThink(player_t *player)
dashmode = 0; dashmode = 0;
} }
#undef dashmode #undef dashmode
#ifdef HAVE_BLUA
LUAh_PlayerThink(player);
#endif
/* /*
// Colormap verification // Colormap verification
{ {

View file

@ -84,6 +84,8 @@ typedef struct extracolormap_s
typedef struct typedef struct
{ {
fixed_t x, y; fixed_t x, y;
boolean floorzset, ceilingzset;
fixed_t floorz, ceilingz;
} vertex_t; } vertex_t;
// Forward of linedefs, for sectors. // Forward of linedefs, for sectors.
@ -142,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).

View file

@ -59,6 +59,7 @@ INT32 centerx, centery;
fixed_t centerxfrac, centeryfrac; fixed_t centerxfrac, centeryfrac;
fixed_t projection; fixed_t projection;
fixed_t projectiony; // aspect ratio fixed_t projectiony; // aspect ratio
fixed_t fovtan; // field of view
// just for profiling purposes // just for profiling purposes
size_t framecount; size_t framecount;
@ -108,10 +109,12 @@ static CV_PossibleValue_t drawdist_precip_cons_t[] = {
{1024, "1024"}, {1536, "1536"}, {2048, "2048"}, {1024, "1024"}, {1536, "1536"}, {2048, "2048"},
{0, "None"}, {0, NULL}}; {0, "None"}, {0, NULL}};
static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}};
static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}};
static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card
static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}}; static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}};
static void Fov_OnChange(void);
static void ChaseCam_OnChange(void); static void ChaseCam_OnChange(void);
static void ChaseCam2_OnChange(void); static void ChaseCam2_OnChange(void);
static void FlipCam_OnChange(void); static void FlipCam_OnChange(void);
@ -125,9 +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 #ifdef GLBADSHADOWS
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif //#ifdef GLBADSHADOWS #endif //#ifdef GLBADSHADOWS
@ -141,6 +142,7 @@ consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL,
consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
//consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; //consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
// Okay, whoever said homremoval causes a performance hit should be shot. // Okay, whoever said homremoval causes a performance hit should be shot.
consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -184,6 +186,14 @@ void SplitScreen_OnChange(void)
} }
} }
} }
static void Fov_OnChange(void)
{
// Shouldn't be needed with render parity?
//if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT)
// CV_Set(&cv_fov, cv_fov.defaultvalue);
R_SetViewSize();
}
static void ChaseCam_OnChange(void) static void ChaseCam_OnChange(void)
{ {
@ -448,8 +458,8 @@ static void R_InitTextureMapping(void)
// //
// Calc focallength // Calc focallength
// so FIELDOFVIEW angles covers SCREENWIDTH. // so FIELDOFVIEW angles covers SCREENWIDTH.
focallength = FixedDiv(centerxfrac, focallength = FixedDiv(projection,
FINETANGENT(FINEANGLES/4+/*cv_fov.value*/ FIELDOFVIEW/2)); FINETANGENT(FINEANGLES/4+FIELDOFVIEW/2));
#ifdef ESLOPE #ifdef ESLOPE
focallengthf = FIXED_TO_FLOAT(focallength); focallengthf = FIXED_TO_FLOAT(focallength);
@ -457,9 +467,9 @@ static void R_InitTextureMapping(void)
for (i = 0; i < FINEANGLES/2; i++) for (i = 0; i < FINEANGLES/2; i++)
{ {
if (FINETANGENT(i) > FRACUNIT*2) if (FINETANGENT(i) > fovtan*2)
t = -1; t = -1;
else if (FINETANGENT(i) < -FRACUNIT*2) else if (FINETANGENT(i) < -fovtan*2)
t = viewwidth+1; t = viewwidth+1;
else else
{ {
@ -563,6 +573,7 @@ void R_ExecuteSetViewSize(void)
INT32 j; INT32 j;
INT32 level; INT32 level;
INT32 startmapl; INT32 startmapl;
angle_t fov;
setsizeneeded = false; setsizeneeded = false;
@ -585,9 +596,12 @@ void R_ExecuteSetViewSize(void)
centerxfrac = centerx<<FRACBITS; centerxfrac = centerx<<FRACBITS;
centeryfrac = centery<<FRACBITS; centeryfrac = centery<<FRACBITS;
projection = centerxfrac; fov = FixedAngle(cv_fov.value/2) + ANGLE_90;
//projectiony = (((vid.height*centerx*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width)<<FRACBITS; fovtan = FINETANGENT(fov >> ANGLETOFINESHIFT);
projectiony = centerxfrac; if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view
fovtan = 17*fovtan/10;
projection = projectiony = FixedDiv(centerxfrac, fovtan);
R_InitViewBuffer(scaledviewwidth, viewheight); R_InitViewBuffer(scaledviewwidth, viewheight);
@ -613,7 +627,7 @@ void R_ExecuteSetViewSize(void)
for (i = 0; i < j; i++) for (i = 0; i < j; i++)
{ {
dy = ((i - viewheight*8)<<FRACBITS) + FRACUNIT/2; dy = ((i - viewheight*8)<<FRACBITS) + FRACUNIT/2;
dy = abs(dy); dy = FixedMul(abs(dy), fovtan);
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy); yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
} }
} }
@ -734,7 +748,7 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
static mobj_t *viewmobj; static mobj_t *viewmobj;
// WARNING: a should be unsigned but to add with 2048, it isn't! // WARNING: a should be unsigned but to add with 2048, it isn't!
#define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS) #define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS, fovtan)
// recalc necessary stuff for mouseaiming // recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight). // slopes are already calculated for the full possible view (which is 4*viewheight).
@ -1203,12 +1217,11 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_drawdist); CV_RegisterVar(&cv_drawdist);
CV_RegisterVar(&cv_drawdist_nights); CV_RegisterVar(&cv_drawdist_nights);
CV_RegisterVar(&cv_drawdist_precip); CV_RegisterVar(&cv_drawdist_precip);
CV_RegisterVar(&cv_fov);
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 #ifdef GLBADSHADOWS
CV_RegisterVar(&cv_shadowoffs); CV_RegisterVar(&cv_shadowoffs);
#endif //#ifdef GLBADSHADOWS #endif //#ifdef GLBADSHADOWS

View file

@ -77,14 +77,13 @@ 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 #ifdef GLBADSHADOWS
extern conscar_t cv_shadowoffs; extern conscar_t cv_shadowoffs;
#endif //#ifdef GLBADSHADOWS #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_skybox; extern consvar_t cv_skybox;
extern consvar_t cv_tailspickup; extern consvar_t cv_tailspickup;

View file

@ -707,254 +707,28 @@ 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 (wadfiles[w]->type == RET_PK3)
if (numtextures)
{ {
for (i = 0; i < numtextures; i++) texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
{ texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
if (textures[i]->flat) }
Z_Free(textures[i]->flat); else
Z_Free(textures[i]); {
Z_Free(texturecache[i]); texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0);
} texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
Z_Free(texturetranslation);
Z_Free(textures);
} }
// Load patches and textures. if (!( texstart == INT16_MAX || texend == INT16_MAX ))
// 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);
// 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 (Picture_IsLumpPNG((UINT8 *)patchlump, lumplength))
{
INT16 width = 0, height = 0;
Picture_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
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 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.
@ -1037,7 +811,246 @@ 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 (Picture_IsLumpPNG((UINT8 *)patchlump, lumplength))
{
INT16 width = 0, height = 0;
Picture_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);
}
// 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);
// 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

View file

@ -760,9 +760,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
static void R_DrawVisSprite(vissprite_t *vis) static void R_DrawVisSprite(vissprite_t *vis)
{ {
column_t *column; column_t *column;
#ifdef RANGECHECK
INT32 texturecolumn; INT32 texturecolumn;
#endif
fixed_t frac; fixed_t frac;
patch_t *patch = vis->patch; patch_t *patch = vis->patch;
fixed_t this_scale = vis->mobj->scale; fixed_t this_scale = vis->mobj->scale;
@ -895,6 +893,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);
} }
@ -910,28 +909,51 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (vis->x2 >= vid.width) if (vis->x2 >= vid.width)
vis->x2 = vid.width-1; vis->x2 = vid.width-1;
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) // Split drawing loops for paper and non-paper to reduce conditional checks per sprite
if (vis->scalestep)
{ {
#ifdef RANGECHECK // Papersprite drawing loop
texturecolumn = frac>>FRACBITS; for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep)
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x);
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
#else
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
#endif
if (vis->scalestep)
{ {
angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF;
texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale;
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
continue;
if (vis->xiscale < 0) // Flipped sprite
texturecolumn = SHORT(patch->width) - 1 - texturecolumn;
sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
dc_iscale = (0xffffffffu / (unsigned)spryscale); dc_iscale = (0xffffffffu / (unsigned)spryscale);
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
if (vis->cut & SC_VFLIP)
R_DrawFlippedMaskedColumn(column, patch->height);
else
R_DrawMaskedColumn(column);
}
}
else
{
// Non-paper drawing loop
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
{
#ifdef RANGECHECK
texturecolumn = frac>>FRACBITS;
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x);
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
#else
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
#endif
if (vis->cut & SC_VFLIP)
R_DrawFlippedMaskedColumn(column, patch->height);
else
R_DrawMaskedColumn(column);
} }
if (vis->cut & SC_VFLIP)
R_DrawFlippedMaskedColumn(column, patch->height);
else
R_DrawMaskedColumn(column);
spryscale += vis->scalestep;
} }
colfunc = colfuncs[BASEDRAWFUNC]; colfunc = colfuncs[BASEDRAWFUNC];
@ -1090,7 +1112,264 @@ static void R_SplitSprite(vissprite_t *sprite)
} }
} }
//#define PROPERPAPER // This was reverted less than 7 hours before 2.2's release because of very strange, frequent crashes. //
// 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
@ -1128,7 +1407,11 @@ static void R_ProjectSprite(mobj_t *thing)
fixed_t iscale; fixed_t iscale;
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;
INT32 dispoffset = thing->info->dispoffset; INT32 dispoffset = thing->info->dispoffset;
@ -1146,10 +1429,6 @@ static void R_ProjectSprite(mobj_t *thing)
INT32 rollangle = 0; INT32 rollangle = 0;
#endif #endif
#ifndef PROPERPAPER
fixed_t ang_scale = FRACUNIT;
#endif
// transform the origin point // transform the origin point
tr_x = thing->x - viewx; tr_x = thing->x - viewx;
tr_y = thing->y - viewy; tr_y = thing->y - viewy;
@ -1160,15 +1439,15 @@ static void R_ProjectSprite(mobj_t *thing)
tz = gxt-gyt; tz = gxt-gyt;
// thing is behind view plane? // thing is behind view plane?
if (!(papersprite) && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later
return; return;
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 (abs(tx) > tz<<2) if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later
return; return;
// aspect ratio stuff // aspect ratio stuff
@ -1232,13 +1511,7 @@ static void R_ProjectSprite(mobj_t *thing)
#endif #endif
if (sprframe->rotate != SRF_SINGLE || papersprite) if (sprframe->rotate != SRF_SINGLE || papersprite)
{
ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle); ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle);
#ifndef PROPERPAPER
if (papersprite)
ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT));
#endif
}
if (sprframe->rotate == SRF_SINGLE) if (sprframe->rotate == SRF_SINGLE)
{ {
@ -1304,31 +1577,11 @@ static void R_ProjectSprite(mobj_t *thing)
else else
offset = -spr_offset; offset = -spr_offset;
offset = FixedMul(offset, this_scale); offset = FixedMul(offset, this_scale);
#ifndef PROPERPAPER
tx += FixedMul(offset, ang_scale);
x1 = (centerxfrac + FixedMul (tx,xscale)) >>FRACBITS;
// off the right side?
if (x1 > viewwidth)
return;
#endif
offset2 = FixedMul(spr_width, this_scale); offset2 = FixedMul(spr_width, this_scale);
#ifndef PROPERPAPER
tx += FixedMul(offset2, ang_scale);
x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - (papersprite ? 2 : 1);
// off the left side
if (x2 < 0)
return;
#endif
if (papersprite) if (papersprite)
{ {
fixed_t fixed_t xscale2, yscale2, cosmul, sinmul, tx2, tz2;
#ifdef PROPERPAPER
xscale2,
#endif
yscale2, cosmul, sinmul, tz2;
INT32 range; INT32 range;
if (ang >= ANGLE_180) if (ang >= ANGLE_180)
@ -1346,19 +1599,23 @@ static void R_ProjectSprite(mobj_t *thing)
gyt = -FixedMul(tr_y, viewsin); gyt = -FixedMul(tr_y, viewsin);
tz = gxt-gyt; tz = gxt-gyt;
yscale = FixedDiv(projectiony, tz); yscale = FixedDiv(projectiony, tz);
if (yscale < 64) return; // Fix some funky visuals //if (yscale < 64) return; // Fix some funky visuals
#ifdef PROPERPAPER
gxt = -FixedMul(tr_x, viewsin); gxt = -FixedMul(tr_x, viewsin);
gyt = FixedMul(tr_y, viewcos); gyt = FixedMul(tr_y, viewcos);
tx = -(gyt + gxt); tx = -(gyt + gxt);
xscale = FixedDiv(projection, tz); xscale = FixedDiv(projection, tz);
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
// off the right side? // Get paperoffset (offset) and paperoffset (distance)
if (x1 > viewwidth) paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul);
return; paperdistance = -FixedMul(tr_x, sinmul) + FixedMul(tr_y, cosmul);
#endif if (paperdistance < 0)
{
paperoffset = -paperoffset;
paperdistance = -paperdistance;
}
centerangle = viewangle - thing->angle;
tr_x += FixedMul(offset2, cosmul); tr_x += FixedMul(offset2, cosmul);
tr_y += FixedMul(offset2, sinmul); tr_y += FixedMul(offset2, sinmul);
@ -1366,38 +1623,52 @@ static void R_ProjectSprite(mobj_t *thing)
gyt = -FixedMul(tr_y, viewsin); gyt = -FixedMul(tr_y, viewsin);
tz2 = gxt-gyt; tz2 = gxt-gyt;
yscale2 = FixedDiv(projectiony, tz2); yscale2 = FixedDiv(projectiony, tz2);
if (yscale2 < 64) return; // ditto //if (yscale2 < 64) return; // ditto
#ifdef PROPERPAPER
gxt = -FixedMul(tr_x, viewsin); gxt = -FixedMul(tr_x, viewsin);
gyt = FixedMul(tr_y, viewcos); gyt = FixedMul(tr_y, viewcos);
tx = -(gyt + gxt); tx2 = -(gyt + gxt);
xscale2 = FixedDiv(projection, tz2); xscale2 = FixedDiv(projection, tz2);
x2 = (centerxfrac + FixedMul(tx,xscale2))>>FRACBITS; x2--; x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS);
if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
return;
// Needs partially clipped
if (tz < FixedMul(MINZ, this_scale))
{
fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz);
tx += FixedDiv(tx2-tx, div);
tz = FixedMul(MINZ, this_scale);
yscale = FixedDiv(projectiony, tz);
xscale = FixedDiv(projection, tz);
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
}
else if (tz2 < FixedMul(MINZ, this_scale))
{
fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2);
tx2 += FixedDiv(tx-tx2, div);
tz2 = FixedMul(MINZ, this_scale);
yscale2 = FixedDiv(projectiony, tz2);
xscale2 = FixedDiv(projection, tz2);
x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS;
}
// off the right side?
if (x1 > viewwidth)
return;
// off the left side // off the left side
if (x2 < 0) if (x2 < 0)
return; return;
#endif
if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
return;
if ((range = x2 - x1) <= 0) if ((range = x2 - x1) <= 0)
return; return;
#ifdef PROPERPAPER
range++; // fencepost problem range++; // fencepost problem
#endif
scalestep = (yscale2 - yscale)/range; scalestep = ((yscale2 - yscale)/range) ?: 1;
xscale = xscale = FixedDiv(range<<FRACBITS, abs(offset2));
#ifdef PROPERPAPER
FixedDiv(range<<FRACBITS, abs(offset2))+1
#else
FixedMul(xscale, ang_scale)
#endif
;
// The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2? // The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2?
// sortscale = max(yscale, yscale2); // sortscale = max(yscale, yscale2);
@ -1407,7 +1678,6 @@ static void R_ProjectSprite(mobj_t *thing)
{ {
scalestep = 0; scalestep = 0;
yscale = sortscale; yscale = sortscale;
#ifdef PROPERPAPER
tx += offset; tx += offset;
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
@ -1421,7 +1691,6 @@ static void R_ProjectSprite(mobj_t *thing)
// off the left side // off the left side
if (x2 < 0) if (x2 < 0)
return; return;
#endif
} }
if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY) if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY)
@ -1542,6 +1811,11 @@ static void R_ProjectSprite(mobj_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 = scalestep; vis->scalestep = scalestep;
vis->paperoffset = paperoffset;
vis->paperdistance = paperdistance;
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
@ -1634,6 +1908,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;
} }
@ -1757,6 +2034,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;
@ -1949,6 +2229,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)
{ {
@ -1956,6 +2239,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;

View file

@ -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
@ -177,8 +180,16 @@ typedef struct vissprite_s
fixed_t startfrac; // horizontal position of x1 fixed_t startfrac; // horizontal position of x1
fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW
fixed_t scalestep; // only for paper sprites, 0 otherwise fixed_t scalestep; // only for paper sprites, 0 otherwise
fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle
fixed_t xiscale; // negative if flipped fixed_t xiscale; // negative if flipped
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;

View file

@ -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);
@ -1466,31 +1474,38 @@ static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid)
void S_LoadMusicDefs(UINT16 wadnum) void S_LoadMusicDefs(UINT16 wadnum)
{ {
UINT16 lump; UINT16 lumpnum;
char *buf; char *lump, *buf;
char *buf2; char *musdeftext;
char *stoken; char *stoken;
char *value; char *value;
char *textline;
size_t size; size_t size;
INT32 i; INT32 i;
musicdef_t *def = NULL; musicdef_t *def = NULL;
UINT16 line = 1; // for better error msgs UINT16 line = 1; // for better error msgs
lump = W_CheckForMusicDefInPwad(wadnum); lumpnum = W_CheckForMusicDefInPwad(wadnum);
if (lump == INT16_MAX) if (lumpnum == INT16_MAX)
return; return;
buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); lump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
size = W_LumpLengthPwad(wadnum, lump); 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';
// for strtok // for strtok
buf2 = malloc(size+1); buf = malloc(size+1);
if (!buf2) if (!buf)
I_Error("S_LoadMusicDefs: No more free memory\n"); I_Error("S_LoadMusicDefs: No more free memory for the parser\n");
M_Memcpy(buf2,buf,size); M_Memcpy(buf, musdeftext, size+1);
buf2[size] = '\0';
stoken = strtok (buf2, "\r\n "); stoken = strtok(buf, "\r\n ");
// Find music def // Find music def
while (stoken) while (stoken)
{ {
@ -1562,9 +1577,47 @@ skip_lump:
} }
else else
{ {
value = strtok(NULL, "\r\n= "); // If this is set true, the line was invalid.
boolean brokenline = false;
// Delimit only by line break.
value = strtok(NULL, "\r\n");
// Find the equals sign.
value = strchr(value, '=');
// It's not there?!
if (!value) if (!value)
brokenline = true;
else
{
// Skip the equals sign.
value++;
// Now skip funny whitespace.
if (value[0] == '\0') // :NOTHING:
brokenline = true;
else
value += strspn(value, "\t ");
}
// If the line is valid, copy the text line from the lump data.
if (!brokenline)
{
// strtok returns memory that already belongs to the input string.
value = musdeftext + (value - buf);
// Find the length of the line.
size = strcspn(value, "\r\n");
// Copy the line.
textline = malloc(size+1);
if (!textline)
I_Error("S_LoadMusicDefs: No more free memory for text line\n");
M_Memcpy(textline, value, size);
textline[size] = '\0';
}
else
{ {
CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
stoken = strtok(NULL, "\r\n"); // skip end of line stoken = strtok(NULL, "\r\n"); // skip end of line
@ -1574,53 +1627,45 @@ skip_lump:
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, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
free(buf2); free(textline);
free(buf);
free(musdeftext);
return; return;
} }
i = atoi(value); i = atoi(textline);
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); //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); //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); STRBUFCPY(def->title, textline);
for (value = def->title; *value; value++)
if (*value == '_') *value = ' '; // turn _ into spaces.
//CONS_Printf("S_LoadMusicDefs: Set title to '%s'\n", def->source); //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); STRBUFCPY(def->alttitle, textline);
for (value = def->alttitle; *value; value++)
if (*value == '_') *value = ' '; // turn _ into spaces.
//CONS_Printf("S_LoadMusicDefs: Set alttitle to '%s'\n", def->source); //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); STRBUFCPY(def->authors, textline);
for (value = def->authors; *value; value++)
if (*value == '_') *value = ' '; // turn _ into spaces.
//CONS_Printf("S_LoadMusicDefs: Set authors to '%s'\n", def->source); //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);
@ -1628,13 +1673,17 @@ skip_lump:
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);
} }
// Free the temporary text line from memory.
free(textline);
skip_field: skip_field:
stoken = strtok(NULL, "\r\n= "); stoken = strtok(NULL, "\r\n= ");
line++; line++;
} }
} }
free(buf2); free(buf);
free(musdeftext);
return; return;
} }

View file

@ -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) \

View file

@ -2208,7 +2208,7 @@ static void ST_drawTextHUD(void)
#define textHUDdraw(str) \ #define textHUDdraw(str) \
{\ {\
V_DrawThinString(16, y, V_PERPLAYER|V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM, str);\ V_DrawThinString(16, y, V_PERPLAYER|V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP, str);\
y += 8;\ y += 8;\
} }

View file

@ -0,0 +1 @@
musicdef-2.2.1:

View 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;
}