Merge branch 'next' into gl-dropshadows

This commit is contained in:
Sally Cochenour 2020-01-17 22:19:51 -05:00
commit ba51f83aaf
34 changed files with 732 additions and 438 deletions

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"
@ -806,6 +807,33 @@ boolean CON_Responder(event_t *ev)
|| key == KEY_LALT || key == KEY_RALT) || key == KEY_LALT || key == KEY_RALT)
return true; return true;
if (key == KEY_LEFTARROW)
{
if (input_cur != 0)
{
if (ctrldown)
input_cur = M_JumpWordReverse(inputlines[inputline], input_cur);
else
--input_cur;
}
if (!shiftdown)
input_sel = input_cur;
return true;
}
else if (key == KEY_RIGHTARROW)
{
if (input_cur < input_len)
{
if (ctrldown)
input_cur += M_JumpWord(&inputlines[inputline][input_cur]);
else
++input_cur;
}
if (!shiftdown)
input_sel = input_cur;
return true;
}
// ctrl modifier -- changes behavior, adds shortcuts // ctrl modifier -- changes behavior, adds shortcuts
if (ctrldown) if (ctrldown)
{ {
@ -958,23 +986,6 @@ boolean CON_Responder(event_t *ev)
con_scrollup--; con_scrollup--;
return true; return true;
} }
if (key == KEY_LEFTARROW)
{
if (input_cur != 0)
--input_cur;
if (!shiftdown)
input_sel = input_cur;
return true;
}
else if (key == KEY_RIGHTARROW)
{
if (input_cur < input_len)
++input_cur;
if (!shiftdown)
input_sel = input_cur;
return true;
}
else if (key == KEY_HOME) else if (key == KEY_HOME)
{ {
input_cur = 0; input_cur = 0;

View File

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

View File

@ -1045,10 +1045,8 @@ void D_SRB2Main(void)
I_OutputMsg("setvbuf didnt work\n"); I_OutputMsg("setvbuf didnt work\n");
#endif #endif
#ifdef GETTEXT
// initialise locale code // initialise locale code
M_StartupLocale(); M_StartupLocale();
#endif
// get parameters from a response file (eg: srb2 @parms.txt) // get parameters from a response file (eg: srb2 @parms.txt)
M_FindResponseFile(); M_FindResponseFile();

View File

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

View File

@ -1629,6 +1629,11 @@ static void readlevelheader(MYFILE *f, INT32 num)
mapheaderinfo[num-1]->typeoflevel = tol; mapheaderinfo[num-1]->typeoflevel = tol;
} }
} }
else if (fastcmp(word, "KEYWORDS"))
{
deh_strlcpy(mapheaderinfo[num-1]->keywords, word2,
sizeof(mapheaderinfo[num-1]->keywords), va("Level header %d: keywords", num));
}
else if (fastcmp(word, "MUSIC")) else if (fastcmp(word, "MUSIC"))
{ {
if (fastcmp(word2, "NONE")) if (fastcmp(word2, "NONE"))
@ -6015,6 +6020,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SIGNSTOP", "S_SIGNSTOP",
"S_SIGNBOARD", "S_SIGNBOARD",
"S_EGGMANSIGN", "S_EGGMANSIGN",
"S_CLEARSIGN",
// Spike Ball // Spike Ball
"S_SPIKEBALL1", "S_SPIKEBALL1",
@ -9664,7 +9670,7 @@ 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_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).

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

@ -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!
@ -1021,9 +1016,6 @@ void HU_Ticker(void)
#ifndef NONET #ifndef NONET
static boolean teamtalk = false; static boolean teamtalk = false;
/*static char chatchars[QUEUESIZE];
static INT32 head = 0, tail = 0;*/
// WHY DO YOU OVERCOMPLICATE EVERYTHING?????????
// Clear spaces so we don't end up with messages only made out of emptiness // Clear spaces so we don't end up with messages only made out of emptiness
static boolean HU_clearChatSpaces(void) static boolean HU_clearChatSpaces(void)
@ -1082,11 +1074,11 @@ static void HU_queueChatChar(char c)
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
{ {
INT32 spc = 1; // used if nodenum[1] is a space. INT32 spc = 1; // used if playernum[1] is a space.
char *nodenum = (char*) malloc(3); char playernum[3];
const char *newmsg; const char *newmsg;
// what we're gonna do now is check if the node exists // what we're gonna do now is check if the player exists
// with that logic, characters 4 and 5 are our numbers: // with that logic, characters 4 and 5 are our numbers:
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko. // teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
@ -1096,18 +1088,17 @@ static void HU_queueChatChar(char c)
return; return;
} }
strncpy(nodenum, msg+3, 3); strncpy(playernum, msg+3, 3);
// check for undesirable characters in our "number" // check for undesirable characters in our "number"
if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
{ {
// check if nodenum[1] is a space // check if playernum[1] is a space
if (nodenum[1] == ' ') if (playernum[1] == ' ')
spc = 0; spc = 0;
// let it slide // let it slide
else else
{ {
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false); HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
free(nodenum);
return; return;
} }
} }
@ -1116,14 +1107,12 @@ static void HU_queueChatChar(char c)
{ {
if (msg[5] != ' ') if (msg[5] != ' ')
{ {
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false); HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
free(nodenum);
return; return;
} }
} }
target = atoi((const char*) nodenum); // turn that into a number target = atoi(playernum); // turn that into a number
free(nodenum);
//CONS_Printf("%d\n", target); //CONS_Printf("%d\n", target);
// check for target player, if it doesn't exist then we can't send the message! // check for target player, if it doesn't exist then we can't send the message!
@ -1135,7 +1124,7 @@ static void HU_queueChatChar(char c)
return; return;
} }
// we need to get rid of the /pm<node> // we need to get rid of the /pm<player num>
newmsg = msg+5+spc; newmsg = msg+5+spc;
strlcpy(msg, newmsg, 255); strlcpy(msg, newmsg, 255);
} }
@ -1337,9 +1326,19 @@ boolean HU_Responder(event_t *ev)
chat_scrolltime = 4; chat_scrolltime = 4;
} }
else if (c == KEY_LEFTARROW && c_input != 0 && !OLDCHAT) // i said go back else if (c == KEY_LEFTARROW && c_input != 0 && !OLDCHAT) // i said go back
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
@ -1648,12 +1647,9 @@ static void HU_drawChatLog(INT32 offset)
} }
chat_scrollmedown = false; chat_scrollmedown = false;
// getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P // getmaxscroll through a lazy hack. We do all these loops,
chat_maxscroll = (dy/charheight); // welcome to C, we don't know what min() and max() are. // so let's not do more loops that are gonna lag the game more. :P
if (chat_maxscroll <= (UINT32)cv_chatheight.value) chat_maxscroll = max(dy / charheight - cv_chatheight.value, 0);
chat_maxscroll = 0;
else
chat_maxscroll -= cv_chatheight.value;
// if we're not bound by the time, autoscroll for next frame: // if we're not bound by the time, autoscroll for next frame:
if (atbottom) if (atbottom)
@ -1794,21 +1790,17 @@ static void HU_DrawChat(void)
i = 0; i = 0;
for(i=0; (i<MAXPLAYERS); i++) for(i=0; (i<MAXPLAYERS); i++)
{ {
// filter: (code needs optimization pls help I'm bad with C) // filter: (code needs optimization pls help I'm bad with C)
if (w_chat[3]) if (w_chat[3])
{ {
char *nodenum; char playernum[3];
UINT32 n; UINT32 n;
// right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!) // right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!)
if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' '))
break; break;
strncpy(playernum, w_chat+3, 3);
nodenum = (char*) malloc(3); n = atoi(playernum); // turn that into a number
strncpy(nodenum, w_chat+3, 3);
n = atoi((const char*) nodenum); // turn that into a number
free(nodenum);
// special cases: // special cases:
if ((n == 0) && !(w_chat[4] == '0')) if ((n == 0) && !(w_chat[4] == '0'))
@ -1855,7 +1847,6 @@ static void HU_DrawChat(void)
} }
HU_drawChatLog(typelines-1); // typelines is the # of lines we're typing. If there's more than 1 then the log should scroll up to give us more space. HU_drawChatLog(typelines-1); // typelines is the # of lines we're typing. If there's more than 1 then the log should scroll up to give us more space.
} }

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

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,

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

@ -2034,6 +2034,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->typeoflevel); lua_pushinteger(L, header->typeoflevel);
else if (fastcmp(field,"nextlevel")) else if (fastcmp(field,"nextlevel"))
lua_pushinteger(L, header->nextlevel); lua_pushinteger(L, header->nextlevel);
else if (fastcmp(field,"keywords"))
lua_pushstring(L, header->keywords);
else if (fastcmp(field,"musname")) else if (fastcmp(field,"musname"))
lua_pushstring(L, header->musname); lua_pushstring(L, header->musname);
else if (fastcmp(field,"mustrack")) else if (fastcmp(field,"mustrack"))

View File

@ -726,6 +726,7 @@ static int mobj_set(lua_State *L)
break; break;
case mobj_shadowscale: case mobj_shadowscale:
mo->shadowscale = luaL_checkfixed(L, 3); 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

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

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

@ -643,7 +643,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
if (delta1 >= delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_PLATFORM) // thing is below FOF if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF
{ {
if (bottomheight < opentop) { if (bottomheight < opentop) {
opentop = bottomheight; opentop = bottomheight;
@ -656,7 +656,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
highceiling = bottomheight; highceiling = bottomheight;
} }
if (delta1 < delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
{ {
if (topheight > openbottom) { if (topheight > openbottom) {
openbottom = topheight; openbottom = topheight;
@ -689,7 +689,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
if (delta1 >= delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_PLATFORM) // thing is below FOF if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF
{ {
if (bottomheight < opentop) { if (bottomheight < opentop) {
opentop = bottomheight; opentop = bottomheight;
@ -702,7 +702,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
highceiling = bottomheight; highceiling = bottomheight;
} }
if (delta1 < delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
{ {
if (topheight > openbottom) { if (topheight > openbottom) {
openbottom = topheight; openbottom = topheight;

View File

@ -10563,7 +10563,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
type == MT_ROLLOUTROCK || type == MT_ROLLOUTROCK ||
type == MT_EGGMOBILE4_MACE || type == MT_EGGMOBILE4_MACE ||
(type >= MT_SMALLMACE && type <= MT_REDSPRINGBALL) || (type >= MT_SMALLMACE && type <= MT_REDSPRINGBALL) ||
(mobj->flags & MF_ENEMY) (mobj->flags & (MF_ENEMY|MF_BOSS))
) )
mobj->shadowscale = FRACUNIT; mobj->shadowscale = FRACUNIT;
else if ( else if (

View File

@ -222,6 +222,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->typeoflevel = 0; mapheaderinfo[num]->typeoflevel = 0;
mapheaderinfo[num]->nextlevel = (INT16)(i + 1); mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
mapheaderinfo[num]->startrings = 0; mapheaderinfo[num]->startrings = 0;
mapheaderinfo[num]->keywords[0] = '\0';
snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i)); snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
mapheaderinfo[num]->musname[6] = 0; mapheaderinfo[num]->musname[6] = 0;
mapheaderinfo[num]->mustrack = 0; mapheaderinfo[num]->mustrack = 0;

View File

@ -6931,7 +6931,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);
@ -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

View File

@ -699,254 +699,29 @@ 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. // Yes
if (numtextures) if (wadfiles[w]->type == RET_PK3)
{ {
for (i = 0; i < numtextures; i++) texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
{ texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
Z_Free(textures[i]); }
Z_Free(texturecache[i]); else
} {
Z_Free(texturetranslation); texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0);
Z_Free(textures); texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
Z_Free(texflats);
} }
// 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);
texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL);
// Allocate texture column offset table.
texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
// Allocate texture referencing cache.
texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
// Allocate texture width table.
texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
// Allocate texture height table.
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
// Create translation table for global animation.
texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);
for (i = 0; i < numtextures; i++)
texturetranslation[i] = i;
for (i = 0, w = 0; w < numwadfiles; w++)
{
// Get the lump numbers for the markers in the WAD, if they exist.
if (wadfiles[w]->type == RET_PK3)
{
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
while (texturesLumpPos != INT16_MAX)
{
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
}
}
else
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
if (texturesLumpPos != INT16_MAX)
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
}
if (texstart == INT16_MAX || texend == INT16_MAX)
#ifdef WALLFLATS
goto checkflats;
#else
continue;
#endif
texstart++; // Do not count the first marker
// Work through each lump between the markers in the WAD.
for (j = 0; j < (texend - texstart); j++)
{
UINT16 wadnum = (UINT16)w;
lumpnum_t lumpnum = texstart + j;
#ifndef NO_PNG_LUMPS
size_t lumplength;
#endif
if (wadfiles[w]->type == RET_PK3)
{
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
continue; // If it is then SKIP IT
}
patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
#ifndef NO_PNG_LUMPS
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
#endif
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
// Set texture properties.
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)patchlump, lumplength))
{
INT16 width, height;
R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength);
texture->width = width;
texture->height = height;
}
else
#endif
{
texture->width = SHORT(patchlump->width);
texture->height = SHORT(patchlump->height);
}
texture->type = TEXTURETYPE_SINGLEPATCH;
texture->patchcount = 1;
texture->holes = false;
texture->flip = 0;
// Allocate information for the texture's patches.
patch = &texture->patches[0];
patch->originx = patch->originy = 0;
patch->wad = (UINT16)w;
patch->lump = texstart + j;
patch->flip = 0;
Z_Unlock(patchlump);
texturewidth[i] = texture->width;
textureheight[i] = texture->height << FRACBITS;
i++;
}
#ifdef WALLFLATS
checkflats:
// Yes
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.
@ -1029,7 +804,248 @@ checkflats:
textureheight[i] = texture->height << FRACBITS; textureheight[i] = texture->height << FRACBITS;
i++; i++;
} }
}
return i;
}
#endif/*WALLFLATS*/
#define TX_START "TX_START"
#define TX_END "TX_END"
static INT32
Rloadtextures (INT32 i, INT32 w)
{
UINT16 j;
UINT16 texstart, texend, texturesLumpPos;
texture_t *texture;
patch_t *patchlump;
texpatch_t *patch;
// Get the lump numbers for the markers in the WAD, if they exist.
if (wadfiles[w]->type == RET_PK3)
{
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
while (texturesLumpPos != INT16_MAX)
{
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
}
}
else
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
if (texturesLumpPos != INT16_MAX)
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
}
if (!( texstart == INT16_MAX || texend == INT16_MAX ))
{
texstart++; // Do not count the first marker
// Work through each lump between the markers in the WAD.
for (j = 0; j < (texend - texstart); j++)
{
UINT16 wadnum = (UINT16)w;
lumpnum_t lumpnum = texstart + j;
#ifndef NO_PNG_LUMPS
size_t lumplength;
#endif #endif
if (wadfiles[w]->type == RET_PK3)
{
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
continue; // If it is then SKIP IT
}
patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
#ifndef NO_PNG_LUMPS
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
#endif
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
// Set texture properties.
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)patchlump, lumplength))
{
INT16 width, height;
R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength);
texture->width = width;
texture->height = height;
}
else
#endif
{
texture->width = SHORT(patchlump->width);
texture->height = SHORT(patchlump->height);
}
texture->type = TEXTURETYPE_SINGLEPATCH;
texture->patchcount = 1;
texture->holes = false;
texture->flip = 0;
// Allocate information for the texture's patches.
patch = &texture->patches[0];
patch->originx = patch->originy = 0;
patch->wad = (UINT16)w;
patch->lump = texstart + j;
patch->flip = 0;
Z_Unlock(patchlump);
texturewidth[i] = texture->width;
textureheight[i] = texture->height << FRACBITS;
i++;
}
}
return i;
}
//
// R_LoadTextures
// Initializes the texture list with the textures from the world map.
//
void R_LoadTextures(void)
{
INT32 i, w;
UINT16 j;
UINT16 texstart, texend, texturesLumpPos;
// Free previous memory before numtextures change.
if (numtextures)
{
for (i = 0; i < numtextures; i++)
{
Z_Free(textures[i]);
Z_Free(texturecache[i]);
}
Z_Free(texturetranslation);
Z_Free(textures);
Z_Free(texflats);
}
// Load patches and textures.
// Get the number of textures to check.
// NOTE: Make SURE the system does not process
// the markers.
// This system will allocate memory for all duplicate/patched textures even if it never uses them,
// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
for (w = 0, numtextures = 0; w < numwadfiles; w++)
{
#ifdef WALLFLATS
// Count flats
if (wadfiles[w]->type == RET_PK3)
{
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
}
else
{
texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0);
texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
}
if (!( texstart == INT16_MAX || texend == INT16_MAX ))
{
texstart++; // Do not count the first marker
// PK3s have subfolders, so we can't just make a simple sum
if (wadfiles[w]->type == RET_PK3)
{
for (j = texstart; j < texend; j++)
{
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
numtextures++;
}
}
else // Add all the textures between F_START and F_END
{
numtextures += (UINT32)(texend - texstart);
}
}
#endif/*WALLFLATS*/
// Count the textures from TEXTURES lumps
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
while (texturesLumpPos != INT16_MAX)
{
numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
}
// Count single-patch textures
if (wadfiles[w]->type == RET_PK3)
{
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
}
else
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
}
if (texstart == INT16_MAX || texend == INT16_MAX)
continue;
texstart++; // Do not count the first marker
// PK3s have subfolders, so we can't just make a simple sum
if (wadfiles[w]->type == RET_PK3)
{
for (j = texstart; j < texend; j++)
{
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
numtextures++;
}
}
else // Add all the textures between TX_START and TX_END
{
numtextures += (UINT32)(texend - texstart);
}
}
// If no textures found by this point, bomb out
if (!numtextures)
I_Error("No textures detected in any WADs!\n");
// Allocate memory and initialize to 0 for all the textures we are initialising.
// There are actually 5 buffers allocated in one for convenience.
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
texflats = Z_Calloc((numtextures * sizeof(*texflats)), PU_STATIC, NULL);
// Allocate texture column offset table.
texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
// Allocate texture referencing cache.
texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
// Allocate texture width table.
texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
// Allocate texture height table.
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
// Create translation table for global animation.
texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);
for (i = 0; i < numtextures; i++)
texturetranslation[i] = i;
for (i = 0, w = 0; w < numwadfiles; w++)
{
#ifdef WALLFLATS
i = Rloadflats(i, w);
#endif
i = Rloadtextures(i, w);
} }
#ifdef HWRENDER #ifdef HWRENDER

View File

@ -144,7 +144,7 @@ typedef enum
FF_QUICKSAND = 0x1000000, ///< Quicksand! FF_QUICKSAND = 0x1000000, ///< Quicksand!
FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top. FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top.
FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity. FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
FF_INTANGABLEFLATS = 0x6000000, ///< Both flats are intangable, but the sides are still solid. FF_INTANGIBLEFLATS = 0x6000000, ///< Both flats are intangible, but the sides are still solid.
FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch. FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch.
FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames.
FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee).

View File

@ -128,6 +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};
consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
@ -1217,6 +1218,8 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_chasecam); CV_RegisterVar(&cv_chasecam);
CV_RegisterVar(&cv_chasecam2); CV_RegisterVar(&cv_chasecam2);
CV_RegisterVar(&cv_shadow);
CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_skybox);
CV_RegisterVar(&cv_cam_dist); CV_RegisterVar(&cv_cam_dist);

View File

@ -76,6 +76,8 @@ extern consvar_t cv_showhud, cv_translucenthud;
extern consvar_t cv_homremoval; extern consvar_t cv_homremoval;
extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_chasecam, cv_chasecam2;
extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_flipcam, cv_flipcam2;
extern consvar_t cv_shadow;
extern consvar_t cv_translucency; extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
extern consvar_t cv_fov; extern consvar_t cv_fov;

View File

@ -1335,7 +1335,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
// reusing x1 variable // reusing x1 variable
x1 += (x2-x1)/2; x1 += (x2-x1)/2;
shadow->shear.offset = (vis->x1-x1)/2; shadow->shear.offset = shadow->x1-x1;
if (thing->subsector->sector->numlights) if (thing->subsector->sector->numlights)
{ {
@ -1904,7 +1904,7 @@ 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 && !papersprite) if (oldthing->shadowscale && cv_shadow.value)
R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz); R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz);
// Debug // Debug

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

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