diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1bdfc94f5..486f4e913 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -245,6 +245,7 @@ target_compile_options(SRB2SDL2 PRIVATE # This is a direct translation from versions.mk $<$,$>: -Wall + -Wextra -Wno-trigraphs -W # Was controlled by RELAXWARNINGS -Wfloat-equal @@ -312,11 +313,7 @@ target_compile_options(SRB2SDL2 PRIVATE $<$,8.1.0>: -Wno-error=format-overflow - -Wno-error=stringop-truncation - -Wno-error=stringop-overflow -Wno-format-overflow - -Wno-stringop-truncation - -Wno-stringop-overflow -Wno-error=multistatement-macros > @@ -329,7 +326,9 @@ target_compile_options(SRB2SDL2 PRIVATE $<$,$,$>>: -Wall -Wno-absolute-value + -Wextra -Wno-trigraphs + -Wconditional-uninitialized -Wno-error=non-literal-null-conversion -Wno-error=constant-conversion -Wno-error=unused-but-set-variable @@ -346,6 +345,9 @@ target_compile_options(SRB2SDL2 PRIVATE # C++, GNU, Clang and Apple Clang $<$,$,$,$>>: -Wall + -Wextra + -Wno-trigraphs + -Wconditional-uninitialized > # C++, MSVC diff --git a/src/Makefile b/src/Makefile index 6dba19c24..40037834d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -47,8 +47,6 @@ # HAVE_MINIUPNPC=1 - Enable automated port forwarding. # Already enabled by default for 32-bit # Windows. -# NOPNG=1 - Disable PNG graphics support. (TODO: double -# check netplay compatible.) # NOCURL=1 - Disable libcurl--HTTP capability. # NOGME=1 - Disable game music emu, retro VGM support. # NOOPENMPT=1 - Disable module (tracker) music support. @@ -69,8 +67,6 @@ # NOEXECINFO=1 - Disable stack trace dump support # DEBUGMODE=1 - Enable various debugging capabilities. # Also disables optimizations. -# NOZLIB=1 - Disable some compression capability. Implies -# NOPNG=1. # # Development flags: # diff --git a/src/Makefile.d/features.mk b/src/Makefile.d/features.mk index d132ecc9e..59806862d 100644 --- a/src/Makefile.d/features.mk +++ b/src/Makefile.d/features.mk @@ -22,8 +22,6 @@ ifndef NOMD5 sources+=md5.c endif -ifndef NOZLIB -ifndef NOPNG ifdef PNG_PKGCONFIG $(eval $(call Use_pkg_config,PNG_PKGCONFIG)) else @@ -36,8 +34,6 @@ opts+=-D_LARGEFILE64_SOURCE endif opts+=-DHAVE_PNG sources+=apng.c -endif -endif ifndef NOCURL CURLCONFIG?=curl-config diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk index b639ad9a1..7c130d908 100644 --- a/src/Makefile.d/versions.mk +++ b/src/Makefile.d/versions.mk @@ -135,11 +135,7 @@ ifdef GCC71 endif ifdef GCC81 WFLAGS+=-Wno-error=format-overflow - WFLAGS+=-Wno-error=stringop-truncation - WFLAGS+=-Wno-error=stringop-overflow WFLAGS+=-Wno-format-overflow - WFLAGS+=-Wno-stringop-truncation - WFLAGS+=-Wno-stringop-overflow WFLAGS+=-Wno-error=multistatement-macros endif diff --git a/src/b_bot.c b/src/b_bot.c index c8228e840..af57d65ec 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -589,8 +589,9 @@ void B_RespawnBot(INT32 playernum) } else P_SetMobjState(tails, S_PLAY_FALL); - P_SetScale(tails, sonic->scale); + P_SetScale(tails, sonic->scale, false); tails->destscale = sonic->destscale; + tails->old_scale = sonic->old_scale; } void B_HandleFlightIndicator(player_t *player) diff --git a/src/blua/lvm.c b/src/blua/lvm.c index b74fef4ee..627685b38 100644 --- a/src/blua/lvm.c +++ b/src/blua/lvm.c @@ -134,7 +134,7 @@ void luaV_gettable (lua_State *L, TValue *t, TValue *key, StkId val) { void luaV_settable (lua_State *L, TValue *t, TValue *key, StkId val) { int loop; for (loop = 0; loop < MAXTAGLOOP; loop++) { - TValue *tm; + TValue *tm = NULL; if (ttistable(t)) { /* `t' is a table? */ Table *h = hvalue(t); TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ diff --git a/src/command.c b/src/command.c index 87d4f893f..a46cc98bc 100644 --- a/src/command.c +++ b/src/command.c @@ -2060,16 +2060,16 @@ void CV_StealthSet(consvar_t *var, const char *value) */ static void CV_SetValueMaybeStealth(consvar_t *var, INT32 value, boolean stealth) { - char val[SKINNAMESIZE+1]; + char val[SKINNAMESIZE+1] = "None"; if (var == &cv_forceskin) // Special handling. { const char *tmpskin = NULL; if ((value < 0) || (value >= numskins)) - tmpskin = "None"; + ; else tmpskin = skins[value]->name; - strncpy(val, tmpskin, SKINNAMESIZE); + memcpy(val, tmpskin, SKINNAMESIZE); } else sprintf(val, "%d", value); diff --git a/src/console.c b/src/console.c index 5ef0ce919..b12a1ab84 100644 --- a/src/console.c +++ b/src/console.c @@ -861,12 +861,6 @@ static void CON_InputDelSelection(void) Lock_state(); - if (!input_cur) - { - Unlock_state(); - return; - } - if (input_cur > input_sel) { start = input_sel; diff --git a/src/d_main.c b/src/d_main.c index 3886ad1ad..c139650d1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -476,6 +476,18 @@ static void D_Display(void) if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap))) { // draw the view directly + if (cv_debug) + { + r_renderwalls = cv_renderwalls.value; + r_renderfloors = cv_renderfloors.value; + r_renderthings = cv_renderthings.value; + } + else + { + r_renderwalls = true; + r_renderfloors = true; + r_renderthings = true; + } if (!automapactive && !dedicated && cv_renderview.value) { diff --git a/src/d_player.h b/src/d_player.h index 26f17a1a0..098b4485c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -603,6 +603,7 @@ typedef struct player_s boolean spectator; boolean outofcoop; boolean removing; + boolean muted; UINT8 bot; struct player_s *botleader; UINT16 lastbuttons; diff --git a/src/deh_lua.c b/src/deh_lua.c index 3600c3554..c056db82a 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -11,6 +11,7 @@ /// \brief Lua SOC library #include "deh_lua.h" +#include "g_input.h" // freeslot takes a name (string only!) // and allocates it to the appropriate free slot. @@ -596,12 +597,20 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) return luaL_error(L, "translation '%s' could not be found.\n", word); } - // TODO: 2.3: Delete this alias - if (fastcmp(word, "BT_USE")) + // TODO: 2.3: Delete these aliases + else if (fastcmp(word, "BT_USE")) { CacheAndPushConstant(L, word, (lua_Integer)BT_SPIN); return 1; - } + } + else if (fastcmp(word, "GC_WEPSLOT8") || fastcmp(word, "GC_WEPSLOT9") || fastcmp(word, "GC_WEPSLOT10")) + { + // Using GC_WEPSLOT7 isn't accurate, but ensures that "if x >= GC_WEPSLOT1 and x <= GC_WEPSLOT10" keeps the intended effect + CacheAndPushConstant(L, word, (lua_Integer)GC_WEPSLOT7); + if (!mathlib) + LUA_Deprecated(L, "GC_WEPSLOT8\"-\"GC_WEPSLOT10", "GC_WEPSLOT1\"-\"GC_WEPSLOT7"); + return 1; + } for (i = 0; INT_CONST[i].n; i++) if (fastcmp(word,INT_CONST[i].n)) { diff --git a/src/deh_soc.c b/src/deh_soc.c index 41eb28a90..beaf7cbf0 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -324,7 +324,7 @@ void readPlayer(MYFILE *f, INT32 num) if (fastcmp(word, "PICNAME")) { SLOTFOUND - strncpy(description[num].picname, word2, 8); + strncpy(description[num].picname, word2, sizeof(description[num].picname)-1); } else if (fastcmp(word, "DISPLAYNAME")) { @@ -355,7 +355,7 @@ void readPlayer(MYFILE *f, INT32 num) else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME")) { SLOTFOUND - strncpy(description[num].nametag, word2, 8); + strncpy(description[num].nametag, word2, sizeof(description[num].nametag)-1); } else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR")) { @@ -1163,7 +1163,7 @@ void readgametype(MYFILE *f, char *gtname) INT16 newgtrankingstype = -1; int newgtinttype = 0; char gtdescription[441]; - char gtconst[MAXLINELEN]; + char gtconst[MAXLINELEN+1]; // Empty strings. gtdescription[0] = '\0'; @@ -1677,7 +1677,7 @@ void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word, "SKYNUM")) mapheaderinfo[num-1]->skynum = (INT16)i; else if (fastcmp(word, "INTERSCREEN")) - strncpy(mapheaderinfo[num-1]->interscreen, word2, 8); + strncpy(mapheaderinfo[num-1]->interscreen, word2, sizeof(mapheaderinfo[num-1]->interscreen)-1); else if (fastcmp(word, "PRECUTSCENENUM")) mapheaderinfo[num-1]->precutscenenum = (UINT8)i; else if (fastcmp(word, "CUTSCENENUM")) @@ -2294,7 +2294,7 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) char name[34]; name[0] = '\x82'; // color yellow name[1] = 0; - strncat(name, word2, 33); + strncat(name, word2, 32); name[33] = 0; // Replace _ with ' ' @@ -2304,7 +2304,7 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) name[j] = ' '; } - strncpy(textprompts[num]->page[pagenum].name, name, 32); + strncpy(textprompts[num]->page[pagenum].name, name, sizeof(textprompts[num]->page[pagenum].name)); } else *textprompts[num]->page[pagenum].name = '\0'; @@ -3794,7 +3794,7 @@ void readmaincfg(MYFILE *f) } else if (fastcmp(word, "TITLEPICSNAME")) { - strncpy(ttname, word2, 9); + strncpy(ttname, word2, sizeof(ttname)-1); titlechanged = true; } else if (fastcmp(word, "TITLEPICSX")) @@ -3878,8 +3878,12 @@ void readmaincfg(MYFILE *f) savemoddata = true; // Also save a time attack folder - filenamelen = strlen(gamedatafilename)-4; // Strip off the extension - strncpy(timeattackfolder, gamedatafilename, min(filenamelen, sizeof (timeattackfolder))); + filenamelen = strlen(gamedatafilename); // Strip off the extension + if (filenamelen >= 4) + filenamelen -= 4; + if (filenamelen >= sizeof(timeattackfolder)) + filenamelen = sizeof(timeattackfolder)-1; + strncpy(timeattackfolder, gamedatafilename, filenamelen); timeattackfolder[min(filenamelen, sizeof (timeattackfolder) - 1)] = '\0'; strcpy(savegamename, timeattackfolder); diff --git a/src/deh_tables.c b/src/deh_tables.c index 8a3aae586..93a70b779 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5738,6 +5738,7 @@ struct int_const_s const INT_CONST[] = { {"JA_DIGITAL",JA_DIGITAL}, {"JA_JUMP",JA_JUMP}, {"JA_SPIN",JA_SPIN}, + {"JA_SHIELD",JA_SHIELD}, {"JA_FIRE",JA_FIRE}, {"JA_FIRENORMAL",JA_FIRENORMAL}, {"JOYAXISRANGE",JOYAXISRANGE}, diff --git a/src/doomdef.h b/src/doomdef.h index 60e7dc203..1b0e76314 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -82,6 +82,7 @@ #include "version.h" #include "doomtype.h" +#include #include #include #include @@ -648,6 +649,7 @@ UINT32 quickncasehash (const char *p, size_t n) #else #define I_Assert(e) ((void)0) #endif +#define I_StaticAssert(e) static_assert(e, "Static assertion failed: " #e) // The character that separates pathnames. Forward slash on // most systems, but reverse solidus (\) on Windows. diff --git a/src/doomstat.h b/src/doomstat.h index bb3bc0c24..c2fc96347 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -165,7 +165,7 @@ extern boolean exitfadestarted; typedef struct { UINT8 numpics; - char picname[8][8]; + char picname[8][8+1]; UINT8 pichires[8]; char *text; UINT16 xcoord[8]; @@ -296,69 +296,69 @@ typedef struct typedef struct { // The original eight, plus one. - char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway) - char subttl[33]; ///< Subtitle for level - UINT8 actnum; ///< Act number or 0 for none. - UINT32 typeoflevel; ///< Combination of typeoflevel flags. - INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. - INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI. - char keywords[33]; ///< Keywords separated by space to search for. 32 characters. - 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. - UINT32 muspos; ///< Music position to jump to. - char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable. - UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave. - INT16 skynum; ///< Sky number to use. - INT16 skybox_scalex; ///< Skybox X axis scale. (0 = no movement, 1 = 1:1 movement, 16 = 16:1 slow movement, -4 = 1:4 fast movement, etc.) - INT16 skybox_scaley; ///< Skybox Y axis scale. - INT16 skybox_scalez; ///< Skybox Z axis scale. + char lvlttl[21+1]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway) + char subttl[32+1]; ///< Subtitle for level + UINT8 actnum; ///< Act number or 0 for none. + UINT32 typeoflevel; ///< Combination of typeoflevel flags. + INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. + INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI. + char keywords[32+1]; ///< Keywords separated by space to search for. 32 characters. + 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. + UINT32 muspos; ///< Music position to jump to. + char forcecharacter[16+1]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable. + UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave. + INT16 skynum; ///< Sky number to use. + INT16 skybox_scalex; ///< Skybox X axis scale. (0 = no movement, 1 = 1:1 movement, 16 = 16:1 slow movement, -4 = 1:4 fast movement, etc.) + INT16 skybox_scaley; ///< Skybox Y axis scale. + INT16 skybox_scalez; ///< Skybox Z axis scale. // Extra information. - char interscreen[8]; ///< 320x200 patch to display at intermission. - char runsoc[33]; ///< SOC to execute at start of level (32 character limit instead of 63) - char scriptname[33]; ///< Script to use when the map is switched to. (32 character limit instead of 191) - UINT8 precutscenenum; ///< Cutscene number to play BEFORE a level starts. - UINT8 cutscenenum; ///< Cutscene number to use, 0 for none. - INT16 countdown; ///< Countdown until level end? - UINT16 palette; ///< PAL lump to use on this map - UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden. - SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. - UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? - SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) - SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.) + char interscreen[8+1]; ///< 320x200 patch to display at intermission. + char runsoc[32+1]; ///< SOC to execute at start of level (32 character limit instead of 63) + char scriptname[32+1]; ///< Script to use when the map is switched to. (32 character limit instead of 191) + UINT8 precutscenenum; ///< Cutscene number to play BEFORE a level starts. + UINT8 cutscenenum; ///< Cutscene number to use, 0 for none. + INT16 countdown; ///< Countdown until level end? + UINT16 palette; ///< PAL lump to use on this map + UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden. + SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. + UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? + SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) + SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.) - UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below - UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus + UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below + UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus - char selectheading[22]; ///< Level select heading. Allows for controllable grouping. - UINT16 startrings; ///< Number of rings players start with. - INT32 sstimer; ///< Timer for special stages. - UINT32 ssspheres; ///< Sphere requirement in special stages. - fixed_t gravity; ///< Map-wide gravity. + char selectheading[22]; ///< Level select heading. Allows for controllable grouping. + UINT16 startrings; ///< Number of rings players start with. + INT32 sstimer; ///< Timer for special stages. + UINT32 ssspheres; ///< Sphere requirement in special stages. + fixed_t gravity; ///< Map-wide gravity. // Title card. - char ltzzpatch[9]; ///< Zig zag patch. - char ltzztext[9]; ///< Zig zag text. - char ltactdiamond[9]; ///< Act diamond. + char ltzzpatch[8+1]; ///< Zig zag patch. + char ltzztext[8+1]; ///< Zig zag text. + char ltactdiamond[8+1]; ///< Act diamond. // Freed animals stuff. - UINT8 numFlickies; ///< Internal. For freed flicky support. - mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. + UINT8 numFlickies; ///< Internal. For freed flicky support. + mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. // NiGHTS stuff. - UINT8 numGradedMares; ///< Internal. For grade support. - nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. + UINT8 numGradedMares; ///< Internal. For grade support. + nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. // Music stuff. - UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds - char musintername[7]; ///< Intermission screen music. + UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds + char musintername[7]; ///< Intermission screen music. char muspostbossname[7]; ///< Post-bossdeath music. UINT16 muspostbosstrack; ///< Post-bossdeath track. UINT32 muspostbosspos; ///< Post-bossdeath position UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds. - SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on) + SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on) // Lua stuff. // (This is not ifdeffed so the map header structure can stay identical, just in case.) diff --git a/src/f_finale.c b/src/f_finale.c index 0b618a1e3..c221ed52f 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -4387,11 +4387,10 @@ void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum if (!tag || !tag[0]) return; - strncpy(suffixedtag, tag, 33); - suffixedtag[32] = 0; + strncpy(suffixedtag, tag, sizeof(suffixedtag)-1); if (tutorialmode) - suffixed = F_GetTextPromptTutorialTag(suffixedtag, 33); + suffixed = F_GetTextPromptTutorialTag(suffixedtag, sizeof(suffixedtag)-1); for (*promptnum = 0 + tutorialpromptnum; *promptnum < MAX_PROMPTS; (*promptnum)++) { diff --git a/src/f_finale.h b/src/f_finale.h index cb71775d0..4b777eb11 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -96,7 +96,7 @@ typedef enum extern ttmode_enum ttmode; extern UINT8 ttscale; // ttmode user vars -extern char ttname[9]; +extern char ttname[8+1]; extern INT16 ttx; extern INT16 tty; extern INT16 ttloop; diff --git a/src/g_demo.c b/src/g_demo.c index f64f34168..e445c4b5d 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -98,7 +98,7 @@ demoghost *ghosts = NULL; // DEMO RECORDING // -#define DEMOVERSION 0x0011 +#define DEMOVERSION 0x0012 #define DEMOHEADER "\xF0" "SRB2Replay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -183,7 +183,11 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) if (ziptic & ZT_ANGLE) oldcmd.angleturn = READINT16(demo_p); if (ziptic & ZT_BUTTONS) + { oldcmd.buttons = (oldcmd.buttons & (BT_CAMLEFT|BT_CAMRIGHT)) | (READUINT16(demo_p) & ~(BT_CAMLEFT|BT_CAMRIGHT)); + if (demoversion < 0x0012 && oldcmd.buttons & BT_SPIN) + oldcmd.buttons |= BT_SHIELD; // Copy BT_SPIN to BT_SHIELD for pre-Shield-button demos + } if (ziptic & ZT_AIMING) oldcmd.aiming = READINT16(demo_p); if (ziptic & ZT_LATENCY) @@ -771,7 +775,7 @@ void G_GhostTicker(void) { g->mo->destscale = READFIXED(g->p); if (g->mo->destscale != g->mo->scale) - P_SetScale(g->mo, g->mo->destscale); + P_SetScale(g->mo, g->mo->destscale, false); } if (xziptic & EZT_THOKMASK) { // Let's only spawn ONE of these per frame, thanks. @@ -810,7 +814,7 @@ void G_GhostTicker(void) mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<color = g->mo->color; mobj->skin = g->mo->skin; - P_SetScale(mobj, (mobj->destscale = g->mo->scale)); + P_SetScale(mobj, g->mo->scale, true); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -926,7 +930,7 @@ void G_GhostTicker(void) else follow->destscale = g->mo->destscale; if (follow->destscale != follow->scale) - P_SetScale(follow, follow->destscale); + P_SetScale(follow, follow->destscale, false); P_UnsetThingPosition(follow); temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p); @@ -1079,7 +1083,7 @@ void G_ReadMetalTic(mobj_t *metal) { metal->destscale = READFIXED(metal_p); if (metal->destscale != metal->scale) - P_SetScale(metal, metal->destscale); + P_SetScale(metal, metal->destscale, false); } if (xziptic & EZT_THOKMASK) { // Let's only spawn ONE of these per frame, thanks. @@ -1117,7 +1121,7 @@ void G_ReadMetalTic(mobj_t *metal) mobj->angle = metal->angle; mobj->color = metal->color; mobj->skin = metal->skin; - P_SetScale(mobj, (mobj->destscale = metal->scale)); + P_SetScale(mobj, metal->scale, true); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -1184,7 +1188,7 @@ void G_ReadMetalTic(mobj_t *metal) else follow->destscale = metal->destscale; if (follow->destscale != follow->scale) - P_SetScale(follow, follow->destscale); + P_SetScale(follow, follow->destscale, false); P_UnsetThingPosition(follow); temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p); @@ -1650,7 +1654,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp, UINT16 this_demo_version) UINT16 totalfiles; char filename[MAX_WADPATH]; UINT8 md5sum[16]; - filestatus_t ncs; + filestatus_t ncs = FS_NOTFOUND; boolean toomany = false; boolean alreadyloaded; UINT16 i, j; diff --git a/src/g_game.c b/src/g_game.c index 6a99381e7..8d19c9e7c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -403,27 +403,29 @@ consvar_t cv_cam_lockonboss[2] = { CVAR_INIT ("cam2_lockaimassist", "Full", CV_SAVE|CV_ALLOWLUA, lockedassist_cons_t, NULL), }; -consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_firenaxis = CVAR_INIT ("joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_deadzone = CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); -consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); +consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_shieldaxis = CVAR_INIT ("joyaxis_shield", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_firenaxis = CVAR_INIT ("joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_deadzone = CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); +consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); -consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); -consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); +consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_shieldaxis2 = CVAR_INIT ("joyaxis2_shield", "None", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); +consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); player_t *seenplayer; // player we're aiming at right now @@ -894,6 +896,9 @@ INT32 JoyAxis(joyaxis_e axissel) case JA_SPIN: axisval = cv_spinaxis.value; break; + case JA_SHIELD: + axisval = cv_shieldaxis.value; + break; case JA_FIRE: axisval = cv_fireaxis.value; break; @@ -967,6 +972,9 @@ INT32 Joy2Axis(joyaxis_e axissel) case JA_SPIN: axisval = cv_spinaxis2.value; break; + case JA_SHIELD: + axisval = cv_shieldaxis2.value; + break; case JA_FIRE: axisval = cv_fireaxis2.value; break; @@ -1334,8 +1342,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONPREV)) cmd->buttons |= BT_WEAPONPREV; // Previous Weapon -#if NUM_WEAPONS > 10 -"Add extra inputs to g_input.h/gamecontrols_e" +#if NUM_WEAPONS > 7 +"Add extra inputs to g_input.h/gamecontrols_e, and fix conflicts in d_ticcmd.h/ticcmd_t/buttons" #endif //use the three avaliable bits to determine the weapon. cmd->buttons &= ~BT_WEAPONMASK; @@ -1361,7 +1369,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->buttons |= BT_TOSSFLAG; // Shield button - if (PLAYERINPUTDOWN(ssplayer, GC_SHIELD)) + axis = PlayerJoyAxis(ssplayer, JA_SHIELD); + if (PLAYERINPUTDOWN(ssplayer, GC_SHIELD) || (usejoystick && axis > 0)) cmd->buttons |= BT_SHIELD; // Lua scriptable buttons @@ -5403,7 +5412,7 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc) INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep) { boolean usemapcode = false; - INT32 newmapnum; + INT32 newmapnum = -1; size_t mapnamelen = strlen(mapname); char *p; diff --git a/src/g_game.h b/src/g_game.h index 80a815f02..0d5fc7e37 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -71,8 +71,8 @@ typedef enum { #define P_ControlStyle(player) ((((player)->pflags & PF_ANALOGMODE) ? CS_LMAOGALOG : 0) | (((player)->pflags & PF_DIRECTIONCHAR) ? CS_STANDARD : 0)) extern consvar_t cv_autobrake, cv_autobrake2; -extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_jumpaxis,cv_spinaxis,cv_fireaxis,cv_firenaxis,cv_deadzone,cv_digitaldeadzone; -extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_jumpaxis2,cv_spinaxis2,cv_fireaxis2,cv_firenaxis2,cv_deadzone2,cv_digitaldeadzone2; +extern consvar_t cv_sideaxis, cv_turnaxis, cv_moveaxis, cv_lookaxis, cv_jumpaxis, cv_spinaxis, cv_shieldaxis, cv_fireaxis, cv_firenaxis, cv_deadzone, cv_digitaldeadzone; +extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_jumpaxis2,cv_spinaxis2,cv_shieldaxis2,cv_fireaxis2,cv_firenaxis2,cv_deadzone2,cv_digitaldeadzone2; extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest; // hi here's some new controls @@ -100,6 +100,7 @@ typedef enum JA_JUMP = JA_DIGITAL, JA_SPIN, + JA_SHIELD, JA_FIRE, JA_FIRENORMAL, } joyaxis_e; diff --git a/src/g_input.c b/src/g_input.c index 3f1be37ba..4a9692e88 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -743,34 +743,34 @@ void G_DefineDefaultControls(void) // Gamepad controls -- same for both schemes gamecontroldefault[i][GC_JUMP ][1] = KEY_JOY1+0; // A gamecontroldefault[i][GC_SPIN ][1] = KEY_JOY1+2; // X - gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+1; // B - gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+3; // Y - gamecontroldefault[i][GC_CUSTOM3 ][1] = KEY_JOY1+8; // Left Stick - gamecontroldefault[i][GC_SHIELD ][1] = KEY_JOY1+4; // LB + gamecontroldefault[i][GC_SHIELD ][1] = KEY_JOY1+1; // B + gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+3; // Y + gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+4; // LB gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+5; // RB + gamecontroldefault[i][GC_CUSTOM3 ][1] = KEY_JOY1+8; // Left Stick + gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_JOY1+9; // Right Stick gamecontroldefault[i][GC_SCORES ][1] = KEY_JOY1+6; // Back gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start + gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = KEY_HAT1+0; // D-Pad Up + gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+1; // D-Pad Down gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_HAT1+2; // D-Pad Left gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_HAT1+3; // D-Pad Right - gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = KEY_JOY1+9; // Right Stick - gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+0; // D-Pad Up - gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_HAT1+1; // D-Pad Down // Second player controls only have joypad defaults gamecontrolbisdefault[i][GC_JUMP ][1] = KEY_2JOY1+0; // A gamecontrolbisdefault[i][GC_SPIN ][1] = KEY_2JOY1+2; // X - gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+1; // B - gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+3; // Y - gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = KEY_2JOY1+8; // Left Stick - gamecontrolbisdefault[i][GC_SHIELD ][1] = KEY_2JOY1+4; // LB + gamecontrolbisdefault[i][GC_SHIELD ][1] = KEY_2JOY1+1; // B + gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+3; // Y + gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+4; // LB gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = KEY_2JOY1+5; // RB + gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = KEY_2JOY1+8; // Left Stick + gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2JOY1+9; // Right Stick //gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2JOY1+6; // Back //gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = KEY_2JOY1+7; // Start + gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = KEY_2HAT1+0; // D-Pad Up + gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+1; // D-Pad Down gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = KEY_2HAT1+2; // D-Pad Left gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = KEY_2HAT1+3; // D-Pad Right - gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = KEY_2JOY1+9; // Right Stick - gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+0; // D-Pad Up - gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2HAT1+1; // D-Pad Down } } @@ -1001,7 +1001,6 @@ static void setcontrol(INT32 (*gc)[2]) // TODO: 2.3: Delete the "use" alias namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin"; - for (numctrl = 0; numctrl < NUM_GAMECONTROLS && stricmp(namectrl, gamecontrolname[numctrl]); numctrl++) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 64f74b1f4..56f5416cf 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -98,13 +98,11 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm if (position + count >= pblockheight) count = pblockheight - position; - dest = block + (position*blockmodulo); - while (count > 0) + for (dest = block + (position*blockmodulo); count > 0; count--, dest += blockmodulo, yfrac += yfracstep) { - count--; - texel = source[yfrac>>FRACBITS]; alpha = 0xFF; + // Make pixel transparent if chroma keyed if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) alpha = 0x00; @@ -115,11 +113,20 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm switch (bpp) { case 2: + { + texelu16 = *((UINT16*)dest); if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + { + if (originPatch->style == AST_TRANSLUCENT && originPatch->alpha < ASTTextureBlendingThreshold[0]) + continue; + if (!(texelu16 & 0xFF00) && originPatch->alpha <= ASTTextureBlendingThreshold[1]) + continue; + texel = ASTBlendPaletteIndexes(texelu16 & 0xFF, texel, originPatch->style, originPatch->alpha); + } texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; + } case 3: colortemp = palette[texel]; if ((originPatch != NULL) && (originPatch->style != AST_COPY)) @@ -149,9 +156,6 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm *dest = texel; break; } - - dest += blockmodulo; - yfrac += yfracstep; } } } @@ -202,13 +206,11 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, if (position + count >= pblockheight) count = pblockheight - position; - dest = block + (position*blockmodulo); - while (count > 0) + for (dest = block + (position*blockmodulo); count > 0; count--, dest += blockmodulo, yfrac -= yfracstep) { - count--; - texel = source[yfrac>>FRACBITS]; alpha = 0xFF; + // Make pixel transparent if chroma keyed if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) alpha = 0x00; @@ -219,8 +221,15 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, switch (bpp) { case 2: + texelu16 = *((UINT16*)dest); if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + { + if (originPatch->style == AST_TRANSLUCENT && originPatch->alpha < ASTTextureBlendingThreshold[0]) + continue; + if (!(texelu16 & 0xFF00) && originPatch->alpha <= ASTTextureBlendingThreshold[1]) + continue; + texel = ASTBlendPaletteIndexes(texelu16 & 0xFF, texel, originPatch->style, originPatch->alpha); + } texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; @@ -253,9 +262,6 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, *dest = texel; break; } - - dest += blockmodulo; - yfrac -= yfracstep; } } } @@ -433,7 +439,7 @@ static UINT8 *MakeBlock(GLMipmap_t *grMipmap) // Create a composite texture from patches, adapt the texture size to a power of 2 // height and width for the hardware texture cache. // -static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) +static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t *mipmap) { UINT8 *block; texture_t *texture; @@ -441,57 +447,19 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) INT32 blockwidth, blockheight, blocksize; INT32 i; - boolean skyspecial = false; //poor hack for Legacy large skies.. - - RGBA_t *palette; - palette = HWR_GetTexturePalette(); texture = textures[texnum]; - // hack the Legacy skies.. - if (texture->name[0] == 'S' && - texture->name[1] == 'K' && - texture->name[2] == 'Y' && - (texture->name[4] == 0 || - texture->name[5] == 0) - ) - { - skyspecial = true; - grtex->mipmap.flags = TF_WRAPXY; // don't use the chromakey for sky - } - else - grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY; - - grtex->mipmap.width = (UINT16)texture->width; - grtex->mipmap.height = (UINT16)texture->height; - if (skyspecial) - grtex->mipmap.format = GL_TEXFMT_RGBA; // that skyspecial code below assumes this format ... - else - grtex->mipmap.format = textureformat; + mipmap->flags = TF_WRAPXY; + mipmap->width = (UINT16)texture->width; + mipmap->height = (UINT16)texture->height; + mipmap->format = textureformat; blockwidth = texture->width; blockheight = texture->height; blocksize = (blockwidth * blockheight); block = MakeBlock(&grtex->mipmap); - if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading) - { - INT32 j; - RGBA_t col; - - col = palette[HWR_PATCHES_CHROMAKEY_COLORINDEX]; - for (j = 0; j < blockheight; j++) - { - for (i = 0; i < blockwidth; i++) - { - block[4*(j*blockwidth+i)+0] = col.s.red; - block[4*(j*blockwidth+i)+1] = col.s.green; - block[4*(j*blockwidth+i)+2] = col.s.blue; - block[4*(j*blockwidth+i)+3] = 0xff; - } - } - } - // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { @@ -526,13 +494,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) Patch_Free(realpatch); } //Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :( - if (format2bpp(grtex->mipmap.format)==4) + if (format2bpp(mipmap->format)==4) { for (i = 3; i < blocksize*4; i += 4) // blocksize*4 because blocksize doesn't include the bpp { if (block[i] == 0) { - grtex->mipmap.flags |= TF_TRANSPARENT; + mipmap->flags |= TF_TRANSPARENT; break; } } @@ -661,8 +629,6 @@ void HWR_FreeTextureColormaps(patch_t *patch) Z_Free(next->data); if (next->colormap) Z_Free(next->colormap); - next->data = NULL; - next->colormap = NULL; HWD.pfnDeleteTexture(next); // Free the old colormap mipmap from memory. @@ -714,12 +680,25 @@ void HWR_InitMapTextures(void) gl_maptexturesloaded = false; } +static void DeleteTextureMipmap(GLMipmap_t *grMipmap) +{ + HWD.pfnDeleteTexture(grMipmap); + + // Chroma-keyed textures do not own their texture data, so do not free it + if (!(grMipmap->flags & TF_CHROMAKEYED)) + Z_Free(grMipmap->data); +} + static void FreeMapTexture(GLMapTexture_t *tex) { - HWD.pfnDeleteTexture(&tex->mipmap); - if (tex->mipmap.data) - Z_Free(tex->mipmap.data); - tex->mipmap.data = NULL; + if (tex->mipmap.nextcolormap) + { + DeleteTextureMipmap(tex->mipmap.nextcolormap); + free(tex->mipmap.nextcolormap); + tex->mipmap.nextcolormap = NULL; + } + + DeleteTextureMipmap(&tex->mipmap); } void HWR_FreeMapTextures(void) @@ -762,41 +741,47 @@ void HWR_LoadMapTextures(size_t pnumtextures) // -------------------------------------------------------------------------- // Make sure texture is downloaded and set it as the source // -------------------------------------------------------------------------- -GLMapTexture_t *HWR_GetTexture(INT32 tex) +static void GetMapTexture(INT32 tex, GLMapTexture_t *grtex, GLMipmap_t *mipmap) { - GLMapTexture_t *grtex; -#ifdef PARANOIA - if ((unsigned)tex >= gl_numtextures) - I_Error("HWR_GetTexture: tex >= numtextures\n"); -#endif - - // Every texture in memory, stored in the - // hardware renderer's bit depth format. Wow! - grtex = &gl_textures[tex]; - // Generate texture if missing from the cache - if (!grtex->mipmap.data && !grtex->mipmap.downloaded) - HWR_GenerateTexture(tex, grtex); + if (!mipmap->data && !mipmap->downloaded) + HWR_GenerateTexture(tex, grtex, mipmap); // If hardware does not have the texture, then call pfnSetTexture to upload it - if (!grtex->mipmap.downloaded) - HWD.pfnSetTexture(&grtex->mipmap); - HWR_SetCurrentTexture(&grtex->mipmap); + if (!mipmap->downloaded) + HWD.pfnSetTexture(mipmap); + HWR_SetCurrentTexture(mipmap); // The system-memory data can be purged now. - Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(mipmap->data, PU_HWRCACHE_UNLOCKED); +} + +GLMapTexture_t *HWR_GetTexture(INT32 tex) +{ + if (tex < 0 || tex >= (signed)gl_numtextures) + { +#ifdef PARANOIA + I_Error("HWR_GetTexture: Invalid texture ID %d", tex); +#else + tex = 0; +#endif + } + + GLMapTexture_t *grtex = &gl_textures[tex]; + + GetMapTexture(tex, grtex, &grtex->mipmap); return grtex; } -static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) +static void HWR_CacheRawFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { size_t size = W_LumpLength(flatlumpnum); UINT16 pflatsize = R_GetFlatSize(size); // setup the texture info grMipmap->format = GL_TEXFMT_P_8; - grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + grMipmap->flags = TF_WRAPXY; grMipmap->width = pflatsize; grMipmap->height = pflatsize; @@ -817,7 +802,7 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum) patch = HWR_GetCachedGLPatch(flatlumpnum); grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap; if (!grmip->downloaded && !grmip->data) - HWR_CacheFlat(grmip, flatlumpnum); + HWR_CacheRawFlat(grmip, flatlumpnum); // If hardware does not have the texture, then call pfnSetTexture to upload it if (!grmip->downloaded) @@ -828,7 +813,16 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum) Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); } -void HWR_GetLevelFlat(levelflat_t *levelflat) +static void MakeLevelFlatMipmap(GLMipmap_t *grMipmap, INT32 texturenum, UINT16 flags) +{ + grMipmap->format = GL_TEXFMT_P_8; + grMipmap->flags = flags; + + grMipmap->width = (UINT16)textures[texturenum]->width; + grMipmap->height = (UINT16)textures[texturenum]->height; +} + +void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed) { if (levelflat->type == LEVELFLAT_NONE || levelflat->texture_id < 0) { @@ -839,24 +833,50 @@ void HWR_GetLevelFlat(levelflat_t *levelflat) INT32 texturenum = texturetranslation[levelflat->texture_id]; GLMapTexture_t *grtex = &gl_flats[texturenum]; + GLMipmap_t *grMipmap = &grtex->mipmap; + GLMipmap_t *originalMipmap = grMipmap; - if (!grMipmap->data && !grMipmap->downloaded) + if (!originalMipmap->downloaded) + MakeLevelFlatMipmap(originalMipmap, texturenum, TF_WRAPXY); + + if (!originalMipmap->data) { - grMipmap->format = GL_TEXFMT_P_8; - grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + size_t size = originalMipmap->width * originalMipmap->height; + memcpy(Z_Malloc(size, PU_HWRCACHE, &originalMipmap->data), R_GetFlatForTexture(texturenum), size); + } - grMipmap->width = (UINT16)textures[texturenum]->width; - grMipmap->height = (UINT16)textures[texturenum]->height; + // If chroma-keyed, create or use a different mipmap for the variant + if (chromakeyed) + { + if (!originalMipmap->data) + { + HWR_SetCurrentTexture(NULL); + return; + } - size_t size = grMipmap->width * grMipmap->height; - memcpy(Z_Malloc(size, PU_HWRCACHE, &grMipmap->data), R_GetFlatForTexture(texturenum), size); + // Allocate it if it wasn't already + if (!originalMipmap->nextcolormap) + { + GLMipmap_t *newMipmap = calloc(1, sizeof (*grMipmap)); + if (newMipmap == NULL) + I_Error("%s: Out of memory", "HWR_GetLevelFlat"); + MakeLevelFlatMipmap(newMipmap, texturenum, TF_WRAPXY | TF_CHROMAKEYED); + originalMipmap->nextcolormap = newMipmap; + } + + // Upload and bind the variant texture instead of the original one + grMipmap = originalMipmap->nextcolormap; + + // Use the original texture's pixel data + // It can just be a pointer to it, since the r_opengl backend deals with the pixels + // that are supposed to be transparent. + grMipmap->data = originalMipmap->data; } if (!grMipmap->downloaded) - HWD.pfnSetTexture(&grtex->mipmap); - - HWR_SetCurrentTexture(&grtex->mipmap); + HWD.pfnSetTexture(grMipmap); + HWR_SetCurrentTexture(grMipmap); Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); } diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 2d55eef2d..7d06ceb60 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -246,7 +246,7 @@ enum ETextureFlags TF_WRAPX = 0x00000001, // wrap around X TF_WRAPY = 0x00000002, // wrap around Y TF_WRAPXY = TF_WRAPY|TF_WRAPX, // very common so use alias is more easy - TF_CHROMAKEYED = 0x00000010, + TF_CHROMAKEYED = 0x00000010, // Used only for flats with pixels that have palette index 255 TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0 }; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index e96ea6c78..807c70989 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -121,7 +121,7 @@ void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap); void HWR_GetFadeMask(lumpnum_t fademasklumpnum); GLMapTexture_t *HWR_GetTexture(INT32 tex); -void HWR_GetLevelFlat(levelflat_t *levelflat); +void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed); void HWR_GetRawFlat(lumpnum_t flatlumpnum); void HWR_FreeTexture(patch_t *patch); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5a0d997fa..bd8f31617 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -59,7 +59,7 @@ static void HWR_ProjectSprite(mobj_t *thing); static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); static void HWR_ProjectBoundingBox(mobj_t *thing); -void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, boolean chromakeyed, extracolormap_t *planecolormap); void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); @@ -339,6 +339,9 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + if (!r_renderfloors) + return; + // no convex poly were generated for this subsector if (!xsub->planepoly) return; @@ -483,9 +486,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool PolyFlags |= PF_ColorMapped; } - if (!cv_renderfloors.value) - return; - HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); if (subsector) @@ -668,7 +668,7 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL { INT32 shader = SHADER_NONE; - if (!cv_renderwalls.value) + if (!r_renderwalls) return; HWR_Lighting(pSurf, lightlevel, wallcolormap); @@ -709,7 +709,7 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; - if (!cv_renderwalls.value) + if (!r_renderwalls) return; realtop = top = wallVerts[3].y; @@ -914,6 +914,191 @@ static boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) return true; } +static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliphigh, fixed_t worldtop, fixed_t worldbottom, fixed_t worldhigh, fixed_t worldlow, fixed_t worldtopslope, fixed_t worldbottomslope, fixed_t worldhighslope, fixed_t worldlowslope, UINT32 lightnum, FOutVector *inWallVerts) +{ + FOutVector wallVerts[4]; + + FSurfaceInfo Surf; + Surf.PolyColor.s.alpha = 255; + + // Determine if it's visible + if (!HWR_BlendMidtextureSurface(&Surf)) + return; + + fixed_t texheight = FixedDiv(textureheight[gl_midtexture], abs(gl_sidedef->scaley_mid)); + INT32 repeats; + + if (gl_sidedef->repeatcnt) + repeats = 1 + gl_sidedef->repeatcnt; + else if (gl_linedef->flags & ML_WRAPMIDTEX) + { + fixed_t high, low; + + if (gl_frontsector->ceilingheight > gl_backsector->ceilingheight) + high = gl_backsector->ceilingheight; + else + high = gl_frontsector->ceilingheight; + + if (gl_frontsector->floorheight > gl_backsector->floorheight) + low = gl_frontsector->floorheight; + else + low = gl_backsector->floorheight; + + repeats = (high - low) / texheight; + if ((high - low) % texheight) + repeats++; // tile an extra time to fill the gap -- Monster Iestyn + } + else + repeats = 1; + + GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture); + float xscale = FixedToFloat(gl_sidedef->scalex_mid); + float yscale = FixedToFloat(gl_sidedef->scaley_mid); + + // SoM: a little note: popentop and popenbottom + // record the limits the texture can be displayed in. + // polytop and polybottom, are the ideal (i.e. unclipped) + // heights of the polygon, and h & l, are the final (clipped) + // poly coords. + fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut; + fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope; + + // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, + // you must use the linedef's backsector to be correct + // From CB + if (gl_curline->polyseg) + { + // Change this when polyobjects support slopes + popentop = popentopslope = gl_curline->backsector->ceilingheight; + popenbottom = popenbottomslope = gl_curline->backsector->floorheight; + } + else + { + popentop = min(worldtop, worldhigh); + popenbottom = max(worldbottom, worldlow); + popentopslope = min(worldtopslope, worldhighslope); + popenbottomslope = max(worldbottomslope, worldlowslope); + } + + // Find the wall's coordinates + fixed_t midtexheight = texheight * repeats; + + fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, abs(gl_sidedef->scaley_mid)); + + // Texture is not skewed + if (gl_linedef->flags & ML_NOSKEW) + { + // Peg it to the floor + if (gl_linedef->flags & ML_MIDPEG) + { + polybottom = max(gl_frontsector->floorheight, gl_backsector->floorheight) + rowoffset; + polytop = polybottom + midtexheight; + } + // Peg it to the ceiling + else + { + polytop = min(gl_frontsector->ceilingheight, gl_backsector->ceilingheight) + rowoffset; + polybottom = polytop - midtexheight; + } + + // The right side's coordinates are the the same as the left side + polytopslope = polytop; + polybottomslope = polybottom; + } + // Skew the texture, but peg it to the floor + else if (gl_linedef->flags & ML_MIDPEG) + { + polybottom = popenbottom + rowoffset; + polytop = polybottom + midtexheight; + polybottomslope = popenbottomslope + rowoffset; + polytopslope = polybottomslope + midtexheight; + } + // Skew it according to the ceiling's slope + else + { + polytop = popentop + rowoffset; + polybottom = polytop - midtexheight; + polytopslope = popentopslope + rowoffset; + polybottomslope = polytopslope - midtexheight; + } + + // The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector + if (gl_curline->polyseg) + { + lowcut = polybottom; + highcut = polytop; + lowcutslope = polybottomslope; + highcutslope = polytopslope; + } + else + { + lowcut = popenbottom; + highcut = popentop; + lowcutslope = popenbottomslope; + highcutslope = popentopslope; + } + + fixed_t h = min(highcut, polytop); + fixed_t l = max(polybottom, lowcut); + fixed_t hS = min(highcutslope, polytopslope); + fixed_t lS = max(polybottomslope, lowcutslope); + + // PEGGING + fixed_t texturevpeg, texturevpegslope; + + if (gl_linedef->flags & ML_MIDPEG) + { + texturevpeg = midtexheight - h + polybottom; + texturevpegslope = midtexheight - hS + polybottomslope; + } + else + { + texturevpeg = polytop - h; + texturevpegslope = polytopslope - hS; + } + + memcpy(wallVerts, inWallVerts, sizeof(wallVerts)); + + // Left side + wallVerts[3].t = texturevpeg * yscale * grTex->scaleY; + wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + + // Right side + wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY; + wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + + // set top/bottom coords + // Take the texture peg into account, rather than changing the offsets past + // where the polygon might not be. + wallVerts[3].y = FIXED_TO_FLOAT(h); + wallVerts[0].y = FIXED_TO_FLOAT(l); + wallVerts[2].y = FIXED_TO_FLOAT(hS); + wallVerts[1].y = FIXED_TO_FLOAT(lS); + + // TODO: Actually use the surface's flags so that I don't have to do this + FUINT blendmode = Surf.PolyFlags; + + // Render midtextures on two-sided lines with a z-buffer offset. + // This will cause the midtexture appear on top, if a FOF overlaps with it. + blendmode |= PF_Decal; + + extracolormap_t *colormap = gl_frontsector->extra_colormap; + + if (gl_frontsector->numlights) + { + if (!(blendmode & PF_Masked)) + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_TRANSLUCENT, NULL, blendmode); + else + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_CUTLEVEL, NULL, blendmode); + } + else if (!(blendmode & PF_Masked)) + HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); +} + // Sort of like GLWall::Process in GZDoom static void HWR_ProcessSeg(void) { @@ -979,9 +1164,8 @@ static void HWR_ProcessSeg(void) wallVerts[2].z = wallVerts[1].z = ve.y; // x offset the texture - fixed_t texturehpeg = gl_sidedef->textureoffset + gl_curline->offset; - float cliplow = (float)texturehpeg; - float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT)); + float cliplow = (float)gl_curline->offset; + float cliphigh = cliplow + (gl_curline->flength * FRACUNIT); FUINT lightnum = gl_frontsector->lightlevel; extracolormap_t *colormap = gl_frontsector->extra_colormap; @@ -997,6 +1181,7 @@ static void HWR_ProcessSeg(void) if (gl_backsector) { INT32 gl_toptexture = 0, gl_bottomtexture = 0; + fixed_t texturevpeg; SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight) @@ -1026,30 +1211,46 @@ static void HWR_ProcessSeg(void) if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture) { grTex = HWR_GetTexture(gl_toptexture); - xscale = FixedToFloat(gl_sidedef->scalex_top); - yscale = FixedToFloat(gl_sidedef->scaley_top); + xscale = FixedToFloat(abs(gl_sidedef->scalex_top)); + yscale = FixedToFloat(abs(gl_sidedef->scaley_top)); - fixed_t texheight = FixedDiv(textureheight[gl_toptexture], gl_sidedef->scaley_top); + fixed_t offsetx_top = gl_sidedef->textureoffset + gl_sidedef->offsetx_top; + + float left = cliplow * xscale; + float right = cliphigh * xscale; + if (gl_sidedef->scalex_top < 0) + { + left = -left; + right = -right; + offsetx_top = -offsetx_top; + } + + fixed_t texheight = textureheight[gl_toptexture]; + fixed_t texheightscaled = FixedDiv(texheight, abs(gl_sidedef->scaley_top)); // PEGGING + // FIXME: This is probably not correct? if (gl_linedef->flags & ML_DONTPEGTOP) texturevpeg = 0; else if (gl_linedef->flags & ML_SKEWTD) texturevpeg = worldhigh + texheight - worldtop; else - texturevpeg = gl_backsector->ceilingheight + texheight - gl_frontsector->ceilingheight; + texturevpeg = gl_backsector->ceilingheight + texheightscaled - gl_frontsector->ceilingheight; texturevpeg *= yscale; - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; + if (gl_sidedef->scaley_top < 0) + texturevpeg -= gl_sidedef->rowoffset + gl_sidedef->offsety_top; + else + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpeg %= texheight; + texturevpeg %= texheightscaled; wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + (gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * yscale) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_top) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_top) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (left + offsetx_top) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (right + offsetx_top) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1074,6 +1275,14 @@ static void HWR_ProcessSeg(void) wallVerts[2].t = wallVerts[1].t - (worldtopslope - worldhighslope) * yscale * grTex->scaleY; } + if (gl_sidedef->scaley_top < 0) + { + wallVerts[0].t = -wallVerts[0].t; + wallVerts[1].t = -wallVerts[1].t; + wallVerts[2].t = -wallVerts[2].t; + wallVerts[3].t = -wallVerts[3].t; + } + // set top/bottom coords wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); @@ -1092,8 +1301,19 @@ static void HWR_ProcessSeg(void) if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture) { grTex = HWR_GetTexture(gl_bottomtexture); - xscale = FixedToFloat(gl_sidedef->scalex_bottom); - yscale = FixedToFloat(gl_sidedef->scaley_bottom); + xscale = FixedToFloat(abs(gl_sidedef->scalex_bottom)); + yscale = FixedToFloat(abs(gl_sidedef->scaley_bottom)); + + fixed_t offsetx_bottom = gl_sidedef->textureoffset + gl_sidedef->offsetx_bottom; + + float left = cliplow * xscale; + float right = cliphigh * xscale; + if (gl_sidedef->scalex_bottom < 0) + { + left = -left; + right = -right; + offsetx_bottom = -offsetx_bottom; + } // PEGGING if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) @@ -1105,15 +1325,18 @@ static void HWR_ProcessSeg(void) texturevpeg *= yscale; - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; + if (gl_sidedef->scaley_bottom < 0) + texturevpeg -= gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; + else + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpeg %= FixedDiv(textureheight[gl_bottomtexture], gl_sidedef->scaley_bottom); + texturevpeg %= FixedDiv(textureheight[gl_bottomtexture], abs(gl_sidedef->scaley_bottom)); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + (gl_backsector->floorheight - gl_frontsector->floorheight) * yscale) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_bottom) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_bottom) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (left + offsetx_bottom) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (right + offsetx_bottom) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1137,6 +1360,14 @@ static void HWR_ProcessSeg(void) wallVerts[1].t = (texturevpeg + (worldlowslope - worldbottomslope) * yscale) * grTex->scaleY; } + if (gl_sidedef->scaley_bottom < 0) + { + wallVerts[0].t = -wallVerts[0].t; + wallVerts[1].t = -wallVerts[1].t; + wallVerts[2].t = -wallVerts[2].t; + wallVerts[3].t = -wallVerts[3].t; + } + // set top/bottom coords wallVerts[3].y = FIXED_TO_FLOAT(worldlow); wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); @@ -1151,196 +1382,14 @@ static void HWR_ProcessSeg(void) HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } - // Render midtexture if there's one. Determine if it's visible first, though - if (gl_midtexture && HWR_BlendMidtextureSurface(&Surf)) - { - sector_t *front, *back; - fixed_t texheight = FixedDiv(textureheight[gl_midtexture], gl_sidedef->scaley_mid); - INT32 repeats; + // Render midtexture if there's one + if (gl_midtexture) + HWR_RenderMidtexture(gl_midtexture, cliplow, cliphigh, worldtop, worldbottom, worldhigh, worldlow, worldtopslope, worldbottomslope, worldhighslope, worldlowslope, lightnum, wallVerts); - if (gl_linedef->frontsector->heightsec != -1) - front = §ors[gl_linedef->frontsector->heightsec]; - else - front = gl_linedef->frontsector; - - if (gl_linedef->backsector->heightsec != -1) - back = §ors[gl_linedef->backsector->heightsec]; - else - back = gl_linedef->backsector; - - if (gl_sidedef->repeatcnt) - repeats = 1 + gl_sidedef->repeatcnt; - else if (gl_linedef->flags & ML_WRAPMIDTEX) - { - fixed_t high, low; - - if (front->ceilingheight > back->ceilingheight) - high = back->ceilingheight; - else - high = front->ceilingheight; - - if (front->floorheight > back->floorheight) - low = front->floorheight; - else - low = back->floorheight; - - repeats = (high - low) / texheight; - if ((high - low) % texheight) - repeats++; // tile an extra time to fill the gap -- Monster Iestyn - } - else - repeats = 1; - - grTex = HWR_GetTexture(gl_midtexture); - xscale = FixedToFloat(gl_sidedef->scalex_mid); - yscale = FixedToFloat(gl_sidedef->scaley_mid); - - // SoM: a little note: popentop and popenbottom - // record the limits the texture can be displayed in. - // polytop and polybottom, are the ideal (i.e. unclipped) - // heights of the polygon, and h & l, are the final (clipped) - // poly coords. - fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut; - fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope; - - // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, - // you must use the linedef's backsector to be correct - // From CB - if (gl_curline->polyseg) - { - popentop = popentopslope = back->ceilingheight; - popenbottom = popenbottomslope = back->floorheight; - } - else - { - popentop = min(worldtop, worldhigh); - popenbottom = max(worldbottom, worldlow); - popentopslope = min(worldtopslope, worldhighslope); - popenbottomslope = max(worldbottomslope, worldlowslope); - } - - // Find the wall's coordinates - fixed_t midtexheight = texheight * repeats; - - fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, gl_sidedef->scaley_mid); - - // Texture is not skewed - if (gl_linedef->flags & ML_NOSKEW) - { - // Peg it to the floor - if (gl_linedef->flags & ML_MIDPEG) - { - polybottom = max(front->floorheight, back->floorheight) + rowoffset; - polytop = polybottom + midtexheight; - } - // Peg it to the ceiling - else - { - polytop = min(front->ceilingheight, back->ceilingheight) + rowoffset; - polybottom = polytop - midtexheight; - } - - // The right side's coordinates are the the same as the left side - polytopslope = polytop; - polybottomslope = polybottom; - } - // Skew the texture, but peg it to the floor - else if (gl_linedef->flags & ML_MIDPEG) - { - polybottom = popenbottom + rowoffset; - polytop = polybottom + midtexheight; - polybottomslope = popenbottomslope + rowoffset; - polytopslope = polybottomslope + midtexheight; - } - // Skew it according to the ceiling's slope - else - { - polytop = popentop + rowoffset; - polybottom = polytop - midtexheight; - polytopslope = popentopslope + rowoffset; - polybottomslope = polytopslope - midtexheight; - } - - // CB - // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, - // you must use the linedef's backsector to be correct - if (gl_curline->polyseg) - { - lowcut = polybottom; - highcut = polytop; - lowcutslope = polybottomslope; - highcutslope = polytopslope; - } - else - { - // The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector - lowcut = popenbottom; - highcut = popentop; - lowcutslope = popenbottomslope; - highcutslope = popentopslope; - } - - h = min(highcut, polytop); - l = max(polybottom, lowcut); - hS = min(highcutslope, polytopslope); - lS = max(polybottomslope, lowcutslope); - - // PEGGING - fixed_t texturevpegslope; - - if (gl_linedef->flags & ML_MIDPEG) - { - texturevpeg = midtexheight - h + polybottom; - texturevpegslope = midtexheight - hS + polybottomslope; - } - else - { - texturevpeg = polytop - h; - texturevpegslope = polytopslope - hS; - } - - // Left side - wallVerts[3].t = texturevpeg * yscale * grTex->scaleY; - wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - - // Right side - wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY; - wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - - // set top/bottom coords - // Take the texture peg into account, rather than changing the offsets past - // where the polygon might not be. - wallVerts[3].y = FIXED_TO_FLOAT(h); - wallVerts[0].y = FIXED_TO_FLOAT(l); - wallVerts[2].y = FIXED_TO_FLOAT(hS); - wallVerts[1].y = FIXED_TO_FLOAT(lS); - - // TODO: Actually use the surface's flags so that I don't have to do this - FUINT blendmode = Surf.PolyFlags; - - // Render midtextures on two-sided lines with a z-buffer offset. - // This will cause the midtexture appear on top, if a FOF overlaps with it. - blendmode |= PF_Decal; - - if (gl_frontsector->numlights) - { - if (!(blendmode & PF_Masked)) - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_TRANSLUCENT, NULL, blendmode); - else - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_CUTLEVEL, NULL, blendmode); - } - else if (!(blendmode & PF_Masked)) - HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); - } - - // Sky culling - // No longer so much a mess as before! if (!gl_curline->polyseg) // Don't do it for polyobjects { + // Sky culling + // No longer so much a mess as before! if (gl_frontsector->ceilingpic == skyflatnum && gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky { @@ -1384,8 +1433,8 @@ static void HWR_ProcessSeg(void) wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; // Texture correction for slopes if (gl_linedef->flags & ML_NOSKEW) { @@ -1448,8 +1497,9 @@ static void HWR_ProcessSeg(void) // Used for height comparisons and etc across FOFs and slopes fixed_t high1, highslope1, low1, lowslope1; + fixed_t texturehpeg = gl_sidedef->textureoffset + gl_sidedef->offsetx_mid; + INT32 texnum; - line_t * newline = NULL; // Multi-Property FOF lowcut = max(worldbottom, worldlow); highcut = min(worldtop, worldhigh); @@ -1483,16 +1533,14 @@ static void HWR_ProcessSeg(void) if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; - side_t *side = &sides[rover->master->sidenum[0]]; + side_t *side = R_GetFFloorSide(gl_curline, rover); boolean do_texture_skew; boolean dont_peg_bottom; if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; - newline = rover->master->frontsector->lines[0] + linenum; - side = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(gl_curline, rover); do_texture_skew = newline->flags & ML_SKEWTD; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; } @@ -1570,14 +1618,14 @@ static void HWR_ProcessSeg(void) } } - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + side->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + side->offsetx_mid) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; } + FBITFIELD blendmode; + if (rover->fofflags & FOF_FOG) { - FBITFIELD blendmode; - blendmode = PF_Fog|PF_NoTexture; lightnum = rover->master->frontsector->lightlevel; @@ -1593,7 +1641,7 @@ static void HWR_ProcessSeg(void) } else { - FBITFIELD blendmode = PF_Masked; + blendmode = PF_Masked; if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) { @@ -1641,13 +1689,21 @@ static void HWR_ProcessSeg(void) if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; - side_t *side = &sides[rover->master->sidenum[0]]; + side_t *side = R_GetFFloorSide(gl_curline, rover); + + boolean do_texture_skew; + boolean dont_peg_bottom; if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; - newline = rover->master->frontsector->lines[0] + linenum; - side = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(gl_curline, rover); + do_texture_skew = newline->flags & ML_SKEWTD; + dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; + } + else + { + do_texture_skew = rover->master->flags & ML_SKEWTD; + dont_peg_bottom = gl_curline->linedef->flags & ML_DONTPEGBOTTOM; } texnum = R_GetTextureNum(side->midtexture); @@ -1684,23 +1740,49 @@ static void HWR_ProcessSeg(void) } else { + // Wow, how was this missing from OpenGL for so long? + // ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software + // -- Monster Iestyn 26/06/18 + fixed_t texturevpeg = side->rowoffset + side->offsety_mid; + grTex = HWR_GetTexture(texnum); xscale = FixedToFloat(side->scalex_mid); yscale = FixedToFloat(side->scaley_mid); - fixed_t diff = (*rover->topheight - h) * yscale; + if (!do_texture_skew) // no skewing + { + if (dont_peg_bottom) + texturevpeg -= (*rover->topheight - *rover->bottomheight) * yscale; - wallVerts[3].t = wallVerts[2].t = (diff + side->rowoffset + side->offsety_mid) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (((h - l) * yscale) + (diff + side->rowoffset + side->offsety_mid)) * grTex->scaleY; + wallVerts[3].t = (((*rover->topheight - h) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[2].t = (((*rover->topheight - hS) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[0].t = (((*rover->topheight - l) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (((*rover->topheight - lS) * yscale) + texturevpeg) * grTex->scaleY; + } + else + { + if (!dont_peg_bottom) // skew by top + { + wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; + wallVerts[0].t = (((h - l) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (((hS - lS) * yscale) + texturevpeg) * grTex->scaleY; + } + else // skew by bottom + { + wallVerts[0].t = wallVerts[1].t = texturevpeg * grTex->scaleY; + wallVerts[3].t = wallVerts[0].t - ((h - l) * yscale) * grTex->scaleY; + wallVerts[2].t = wallVerts[1].t - ((hS - lS) * yscale) * grTex->scaleY; + } + } - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + side->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + side->offsetx_mid) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; } + FBITFIELD blendmode; + if (rover->fofflags & FOF_FOG) { - FBITFIELD blendmode; - blendmode = PF_Fog|PF_NoTexture; lightnum = rover->master->frontsector->lightlevel; @@ -1716,7 +1798,7 @@ static void HWR_ProcessSeg(void) } else { - FBITFIELD blendmode = PF_Masked; + blendmode = PF_Masked; if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) { @@ -1994,36 +2076,14 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord) static inline void HWR_AddPolyObjectSegs(void) { size_t i, j; - seg_t *gl_fakeline = Z_Calloc(sizeof(seg_t), PU_STATIC, NULL); - polyvertex_t *pv1 = Z_Calloc(sizeof(polyvertex_t), PU_STATIC, NULL); - polyvertex_t *pv2 = Z_Calloc(sizeof(polyvertex_t), PU_STATIC, NULL); // Sort through all the polyobjects for (i = 0; i < numpolys; ++i) { // Render the polyobject's lines for (j = 0; j < po_ptrs[i]->segCount; ++j) - { - // Copy the info of a polyobject's seg, then convert it to OpenGL floating point - M_Memcpy(gl_fakeline, po_ptrs[i]->segs[j], sizeof(seg_t)); - - // Now convert the line to float and add it to be rendered - pv1->x = FIXED_TO_FLOAT(gl_fakeline->v1->x); - pv1->y = FIXED_TO_FLOAT(gl_fakeline->v1->y); - pv2->x = FIXED_TO_FLOAT(gl_fakeline->v2->x); - pv2->y = FIXED_TO_FLOAT(gl_fakeline->v2->y); - - gl_fakeline->pv1 = pv1; - gl_fakeline->pv2 = pv2; - - HWR_AddLine(gl_fakeline); - } + HWR_AddLine(po_ptrs[i]->segs[j]); } - - // Free temporary data no longer needed - Z_Free(pv2); - Z_Free(pv1); - Z_Free(gl_fakeline); } static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, @@ -2048,13 +2108,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; - if (nrPlaneVerts < 3) // Not even a triangle? + if (!r_renderfloors || nrPlaneVerts < 3) // Not even a triangle? return; - else if (nrPlaneVerts > (size_t)UINT16_MAX) // FIXME: exceeds plVerts size - { - CONS_Debug(DBG_RENDER, "polygon size of %s exceeds max value of %d vertices\n", sizeu1(nrPlaneVerts), UINT16_MAX); - return; - } // Allocate plane-vertex buffer if we need to if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts) @@ -2197,7 +2252,7 @@ static void HWR_AddPolyObjectPlanes(void) } else { - HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic]); + HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic], false); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic], polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap)); @@ -2220,7 +2275,7 @@ static void HWR_AddPolyObjectPlanes(void) } else { - HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic]); + HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic], false); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->ceilingpic], polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap)); @@ -2350,7 +2405,7 @@ static void HWR_Subsector(size_t num) { if (sub->validcount != validcount) { - HWR_GetLevelFlat(&levelflats[gl_frontsector->floorpic]); + HWR_GetLevelFlat(&levelflats[gl_frontsector->floorpic], false); HWR_RenderPlane(sub, &extrasubsectors[num], false, // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight, @@ -2366,7 +2421,7 @@ static void HWR_Subsector(size_t num) { if (sub->validcount != validcount) { - HWR_GetLevelFlat(&levelflats[gl_frontsector->ceilingpic]); + HWR_GetLevelFlat(&levelflats[gl_frontsector->ceilingpic], false); HWR_RenderPlane(sub, &extrasubsectors[num], true, // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight, @@ -2424,7 +2479,7 @@ static void HWR_Subsector(size_t num) *rover->bottomheight, *gl_frontsector->lightlist[light].lightlevel, alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, - true, rover->master->frontsector->extra_colormap); + true, false, rover->master->frontsector->extra_colormap); } else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) // SoM: Flags are more efficient { @@ -2437,11 +2492,11 @@ static void HWR_Subsector(size_t num) *gl_frontsector->lightlist[light].lightlevel, max(0, min(rover->alpha, 255)), rover->master->frontsector, HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent), - false, *gl_frontsector->lightlist[light].extra_colormap); + false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap); } else { - HWR_GetLevelFlat(&levelflats[*rover->bottompic]); + HWR_GetLevelFlat(&levelflats[*rover->bottompic], rover->fofflags & FOF_SPLAT); light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); @@ -2469,7 +2524,7 @@ static void HWR_Subsector(size_t num) *rover->topheight, *gl_frontsector->lightlist[light].lightlevel, alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, - true, rover->master->frontsector->extra_colormap); + true, false, rover->master->frontsector->extra_colormap); } else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) { @@ -2482,11 +2537,11 @@ static void HWR_Subsector(size_t num) *gl_frontsector->lightlist[light].lightlevel, max(0, min(rover->alpha, 255)), rover->master->frontsector, HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent), - false, *gl_frontsector->lightlist[light].extra_colormap); + false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap); } else { - HWR_GetLevelFlat(&levelflats[*rover->toppic]); + HWR_GetLevelFlat(&levelflats[*rover->toppic], rover->fofflags & FOF_SPLAT); light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); @@ -3780,6 +3835,7 @@ typedef struct sector_t *FOFSector; FBITFIELD blend; boolean fogplane; + boolean chromakeyed; extracolormap_t *planecolormap; INT32 drawcount; } planeinfo_t; @@ -3821,7 +3877,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, boolean chromakeyed, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -3844,6 +3900,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo planeinfo[numplanes].FOFSector = FOFSector; planeinfo[numplanes].blend = blend; planeinfo[numplanes].fogplane = fogplane; + planeinfo[numplanes].chromakeyed = chromakeyed; planeinfo[numplanes].planecolormap = planecolormap; planeinfo[numplanes].drawcount = drawcount++; @@ -4010,7 +4067,7 @@ static void HWR_CreateDrawNodes(void) gl_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) - HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat); + HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->chromakeyed); HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->planecolormap); } @@ -4019,9 +4076,11 @@ static void HWR_CreateDrawNodes(void) // We aren't traversing the BSP tree, so make gl_frontsector null to avoid crashes. gl_frontsector = NULL; + polyobj_t *po = sortnode[sortindex[i]].polyplane->polysector; + if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) - HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat); - HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, + HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat, po->flags & POF_SPLAT); + HWR_RenderPolyObjectPlane(po, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, sortnode[sortindex[i]].polyplane->levelflat, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); } else if (sortnode[sortindex[i]].wall) @@ -4226,7 +4285,7 @@ static void HWR_ProjectSprite(mobj_t *thing) // uncapped/interpolation interpmobjstate_t interp = {0}; - if (!cv_renderthings.value) + if (!r_renderthings) return; if (!thing) @@ -5500,7 +5559,7 @@ static void HWR_TogglePaletteRendering(void) // The textures will still be converted to RGBA by r_opengl. // This however makes hw_cache use paletted blending for composite textures! // (patchformat is not touched) - textureformat = GL_TEXFMT_P_8; + textureformat = GL_TEXFMT_AP_88; HWR_SetMapPalette(); HWR_SetPalette(pLocalPalette); @@ -5771,7 +5830,7 @@ void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 te { static size_t allocedwalls = 0; - if (!cv_renderwalls.value) + if (!r_renderwalls) return; // Force realloc if buffer has been freed @@ -5802,7 +5861,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, INT32 shader = SHADER_NONE; - if (!cv_renderwalls.value) + if (!r_renderwalls) return; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index acd09f614..75a92c2fb 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -180,7 +180,7 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) // GL_MSG_Warning : Raises a warning. // -----------------+ -static void GL_MSG_Warning(const char *format, ...) +FUNCPRINTF static void GL_MSG_Warning(const char *format, ...) { char str[4096] = ""; va_list arglist; @@ -203,7 +203,7 @@ static void GL_MSG_Warning(const char *format, ...) // GL_MSG_Error : Raises an error. // -----------------+ -static void GL_MSG_Error(const char *format, ...) +FUNCPRINTF static void GL_MSG_Error(const char *format, ...) { char str[4096] = ""; va_list arglist; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index c9744e598..13d499495 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -465,9 +465,12 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) numwords = COM_Argc() - usedargs; I_Assert(numwords > 0); - if (CHAT_MUTE) // TODO: Per Player mute. + if (CHAT_MUTE) { - HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); + if (cv_mute.value) + HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); + else + HU_AddChatText(va("%s>ERROR: You have been muted. You can't say anything.", "\x85"), false); return; } @@ -496,10 +499,10 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) // what we're gonna do now is check if the player exists // with that logic, characters 4 and 5 are our numbers: const char *newmsg; - char playernum[3]; + char playernum[3+1]; INT32 spc = 1; // used if playernum[1] is a space. - strncpy(playernum, msg+3, 3); + strncpy(playernum, msg+3, sizeof(playernum)-1); // check for undesirable characters in our "number" if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9'))) { @@ -644,9 +647,9 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) msg = (char *)*p; SKIPSTRINGL(*p, HU_MAXMSGLEN + 1); - if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum))) + if ((cv_mute.value || players[playernum].muted || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum))) { - CONS_Alert(CONS_WARNING, cv_mute.value ? + CONS_Alert(CONS_WARNING, (cv_mute.value || players[playernum].muted) ? 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]); if (server) @@ -962,14 +965,17 @@ static void HU_sendChatMessage(void) // last minute mute check if (CHAT_MUTE) { - HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); + if (cv_mute.value) + HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); + else + HU_AddChatText(va("%s>ERROR: You have been muted. You can't say anything.", "\x85"), false); return; } if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { INT32 spc = 1; // used if playernum[1] is a space. - char playernum[3]; + char playernum[3+1]; const char *newmsg; // what we're gonna do now is check if the player exists @@ -982,7 +988,7 @@ static void HU_sendChatMessage(void) return; } - strncpy(playernum, msg+3, 3); + strncpy(playernum, msg+3, sizeof(playernum)-1); // check for undesirable characters in our "number" if (!(isdigit(playernum[0]) && isdigit(playernum[1]))) { @@ -1567,7 +1573,6 @@ static void HU_DrawChat(void) INT32 cflag = 0; const char *ntalk = "Say: ", *ttalk = "Team: "; const char *talk = ntalk; - const char *mute = "Chat has been muted."; #ifdef NETSPLITSCREEN if (splitscreen) @@ -1594,7 +1599,10 @@ static void HU_DrawChat(void) if (CHAT_MUTE) { - talk = mute; + if (cv_mute.value) + talk = "Chat has been muted."; + else + talk = "You have been muted."; typelines = 1; cflag = V_GRAYMAP; // set text in gray if chat is muted. } @@ -1679,13 +1687,14 @@ static void HU_DrawChat(void) // filter: (code needs optimization pls help I'm bad with C) if (w_chat[3]) { - char playernum[3]; + char playernum[3+1]; UINT32 n; // 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] != ' ')) break; - strncpy(playernum, w_chat+3, 3); + strncpy(playernum, w_chat+3, sizeof(playernum)-1); + playernum[3] = 0; n = atoi(playernum); // turn that into a number // special cases: @@ -2982,7 +2991,7 @@ void HU_DoCEcho(const char *msg) { I_OutputMsg("%s\n", msg); // print to log - strncpy(cechotext, msg, sizeof(cechotext)); + strncpy(cechotext, msg, sizeof(cechotext)-1); strncat(cechotext, "\\", sizeof(cechotext) - strlen(cechotext) - 1); cechotext[sizeof(cechotext) - 1] = '\0'; cechotimer = cechoduration; diff --git a/src/hu_stuff.h b/src/hu_stuff.h index b3069c215..9ca50e6e1 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -69,8 +69,8 @@ typedef struct #else #define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640 || splitscreen) #endif -#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot. -#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted. +#define CHAT_MUTE ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot. +#define OLD_MUTE (OLDCHAT && (cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted. // some functions void HU_AddChatText(const char *text, boolean playsound); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 680c6a2c3..e75a911ee 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -44,6 +44,21 @@ return luaL_error(L, "HUD rendering code should not call this function!");\ else if (hook_cmd_running)\ return luaL_error(L, "CMD building code should not call this function!"); +#define NOSPAWNNULL if (type >= NUMMOBJTYPES)\ +return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);\ +else if (type == MT_NULL)\ +{\ + if (!nospawnnull_seen) {\ + nospawnnull_seen = true;\ + CONS_Alert(CONS_WARNING,"Spawning an \"MT_NULL\" mobj is deprecated and will be removed.\nUse \"MT_RAY\" instead.\n");\ + }\ +type = MT_RAY;\ +} +static boolean nospawnnull_seen = false; // TODO: 2.3: Delete +// TODO: 2.3: Use the below NOSPAWNNULL define instead. P_SpawnMobj used to say "if MT_NULL, use MT_RAY instead", so the above define maintains Lua script compatibility until v2.3 +/*#define NOSPAWNNULL if (type <= MT_NULL || type >= NUMMOBJTYPES)\ +return luaL_error(L, "mobj type %d out of range (1 - %d)", type, NUMMOBJTYPES-1);*/ + boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); return lua_toboolean(L, narg); @@ -625,8 +640,7 @@ static int lib_pSpawnMobj(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 4); NOHUD INLEVEL - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); + NOSPAWNNULL LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ); return 1; } @@ -640,10 +654,9 @@ static int lib_pSpawnMobjFromMobj(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 5); NOHUD INLEVEL + NOSPAWNNULL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnMobjFromMobj(actor, x, y, z, type), META_MOBJ); return 1; } @@ -708,10 +721,9 @@ static int lib_pSpawnMissile(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 3); NOHUD INLEVEL + NOSPAWNNULL if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnMissile(source, dest, type), META_MOBJ); return 1; } @@ -726,10 +738,9 @@ static int lib_pSpawnXYZMissile(lua_State *L) fixed_t z = luaL_checkfixed(L, 6); NOHUD INLEVEL + NOSPAWNNULL if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnXYZMissile(source, dest, type, x, y, z), META_MOBJ); return 1; } @@ -746,10 +757,9 @@ static int lib_pSpawnPointMissile(lua_State *L) fixed_t z = luaL_checkfixed(L, 8); NOHUD INLEVEL + NOSPAWNNULL if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnPointMissile(source, xa, ya, za, type, x, y, z), META_MOBJ); return 1; } @@ -764,10 +774,9 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L) INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5); NOHUD INLEVEL + NOSPAWNNULL if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnAlteredDirectionMissile(source, type, x, y, z, shiftingAngle), META_MOBJ); return 1; } @@ -795,10 +804,9 @@ static int lib_pSPMAngle(lua_State *L) UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0); NOHUD INLEVEL + NOSPAWNNULL if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SPMAngle(source, type, angle, allowaim, flags2), META_MOBJ); return 1; } @@ -810,10 +818,9 @@ static int lib_pSpawnPlayerMissile(lua_State *L) UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0); NOHUD INLEVEL + NOSPAWNNULL if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnPlayerMissile(source, type, flags2), META_MOBJ); return 1; } @@ -844,8 +851,7 @@ static int lib_pWeaponOrPanel(lua_State *L) { mobjtype_t type = luaL_checkinteger(L, 1); //HUDSAFE - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); + NOSPAWNNULL lua_pushboolean(L, P_WeaponOrPanel(type)); return 1; } @@ -888,8 +894,7 @@ static int lib_pSpawnParaloop(lua_State *L) boolean spawncenter = lua_optboolean(L, 9); NOHUD INLEVEL - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); + NOSPAWNNULL if (nstate >= NUMSTATES) return luaL_error(L, "state %d out of range (0 - %d)", nstate, NUMSTATES-1); P_SpawnParaloop(x, y, z, radius, number, type, nstate, rotangle, spawncenter); @@ -924,13 +929,14 @@ static int lib_pSetScale(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t newscale = luaL_checkfixed(L, 2); + boolean instant = lua_optboolean(L, 3); NOHUD INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); if (newscale < FRACUNIT/100) newscale = FRACUNIT/100; - P_SetScale(mobj, newscale); + P_SetScale(mobj, newscale, instant); return 0; } @@ -1762,10 +1768,9 @@ static int lib_pSpawnSpinMobj(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 2); NOHUD INLEVEL + NOSPAWNNULL if (!player) return LUA_ErrInvalid(L, "player_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); P_SpawnSpinMobj(player, type); return 0; } @@ -2497,6 +2502,17 @@ static int lib_pDoSuperTransformation(lua_State *L) return 0; } +static int lib_pDoSuperDetransformation(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_DoSuperDetransformation(player); + return 0; +} + static int lib_pExplodeMissile(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2711,12 +2727,11 @@ static int lib_pFadeLight(lua_State *L) static int lib_pIsFlagAtBase(lua_State *L) { - mobjtype_t flag = luaL_checkinteger(L, 1); + mobjtype_t type = luaL_checkinteger(L, 1); //HUDSAFE INLEVEL - if (flag >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1); - lua_pushboolean(L, P_IsFlagAtBase(flag)); + NOSPAWNNULL + lua_pushboolean(L, P_IsFlagAtBase(type)); return 1; } @@ -4450,6 +4465,7 @@ static luaL_Reg lib[] = { {"P_VectorInstaThrust",lib_pVectorInstaThrust}, {"P_SetMobjStateNF",lib_pSetMobjStateNF}, {"P_DoSuperTransformation",lib_pDoSuperTransformation}, + {"P_DoSuperDetransformation",lib_pDoSuperDetransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, {"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial}, {"P_ThingOnSpecial3DFloor",lib_pThingOnSpecial3DFloor}, diff --git a/src/lua_hud.h b/src/lua_hud.h index 0ab1d0a25..36ce230ed 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -19,6 +19,7 @@ enum hud { hud_stagetitle = 0, hud_textspectator, hud_crosshair, + hud_powerups, // Singleplayer / Co-op hud_score, hud_time, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 52a875e50..08e0367f9 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -41,11 +41,13 @@ static const char *const hud_disable_options[] = { "stagetitle", "textspectator", "crosshair", + "powerups", "score", "time", "rings", "lives", + "input", "weaponrings", "powerstones", @@ -69,6 +71,10 @@ static const char *const hud_disable_options[] = { "intermissionemeralds", NULL}; +// you know, let's actually make sure that the table is synced. +// because fuck knows how many times this has happened at this point. :v +I_StaticAssert(sizeof(hud_disable_options) / sizeof(*hud_disable_options) == hud_MAX+1); + enum hudinfo { hudinfo_x = 0, hudinfo_y, diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 7fd16b32b..62b02ff3f 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -762,7 +762,7 @@ static int mobj_set(lua_State *L) return luaL_error(L, "mobj.type %d out of range (0 - %d).", newtype, NUMMOBJTYPES-1); mo->type = newtype; mo->info = &mobjinfo[newtype]; - P_SetScale(mo, mo->scale); + P_SetScale(mo, mo->scale, false); break; } case mobj_info: @@ -836,9 +836,7 @@ static int mobj_set(lua_State *L) fixed_t scale = luaL_checkfixed(L, 3); if (scale < FRACUNIT/100) scale = FRACUNIT/100; - mo->destscale = scale; - P_SetScale(mo, scale); - mo->old_scale = scale; + P_SetScale(mo, scale, true); break; } case mobj_destscale: diff --git a/src/m_menu.c b/src/m_menu.c index fcde0d148..7811a99ba 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1068,9 +1068,9 @@ static menuitem_t OP_ChangeControlsMenu[] = {IT_CALL | IT_STRING2, NULL, "Move Backward", M_ChangeControl, GC_BACKWARD }, {IT_CALL | IT_STRING2, NULL, "Move Left", M_ChangeControl, GC_STRAFELEFT }, {IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, GC_STRAFERIGHT }, - {IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, GC_JUMP }, - {IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, GC_SPIN }, - {IT_CALL | IT_STRING2, NULL, "Shield", M_ChangeControl, GC_SHIELD }, + {IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, GC_JUMP }, + {IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, GC_SPIN }, + {IT_CALL | IT_STRING2, NULL, "Shield Ability", M_ChangeControl, GC_SHIELD }, {IT_HEADER, NULL, "Camera", NULL, 0}, {IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, GC_LOOKUP }, @@ -1119,13 +1119,15 @@ static menuitem_t OP_ChangeControlsMenu[] = static menuitem_t OP_Joystick1Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Gamepad...", M_Setup1PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis , 30}, - {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis , 40}, - {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis , 50}, - {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis , 60}, - {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis , 70}, - {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis , 80}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad...", M_Setup1PJoystickMenu, 0}, + + {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis , 20}, + {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis , 30}, + {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis , 40}, + {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis , 50}, + {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis , 60}, + {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis , 70}, + {IT_STRING | IT_CVAR, NULL, "Shield Axis" , &cv_shieldaxis , 80}, {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis , 90}, {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis ,100}, @@ -1137,13 +1139,15 @@ static menuitem_t OP_Joystick1Menu[] = static menuitem_t OP_Joystick2Menu[] = { - {IT_STRING | IT_CALL, NULL, "Select Gamepad...", M_Setup2PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis2 , 30}, - {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis2 , 40}, - {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis2 , 50}, - {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis2 , 60}, - {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis2 , 70}, - {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis2 , 80}, + {IT_STRING | IT_CALL, NULL, "Select Gamepad...", M_Setup2PJoystickMenu, 0}, + + {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis2 , 20}, + {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis2 , 30}, + {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis2 , 40}, + {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis2 , 50}, + {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis2 , 60}, + {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis2 , 70}, + {IT_STRING | IT_CVAR, NULL, "Shield Axis" , &cv_shieldaxis2 , 80}, {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis2 , 90}, {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis2 ,100}, @@ -2692,7 +2696,7 @@ static boolean MIT_SetCurTitlePics(UINT32 menutype, INT32 level, INT32 *retval, curhidepics = menupres[menutype].hidetitlepics; curttmode = menupres[menutype].ttmode; curttscale = (menupres[menutype].ttscale != UINT8_MAX ? menupres[menutype].ttscale : ttscale); - strncpy(curttname, menupres[menutype].ttname, 9); + strncpy(curttname, menupres[menutype].ttname, sizeof(curttname)-1); curttx = (menupres[menutype].ttx != INT16_MAX ? menupres[menutype].ttx : ttx); curtty = (menupres[menutype].tty != INT16_MAX ? menupres[menutype].tty : tty); curttloop = (menupres[menutype].ttloop != INT16_MAX ? menupres[menutype].ttloop : ttloop); @@ -3426,7 +3430,7 @@ boolean M_Responder(event_t *ev) // ignore ev_keydown events if the key maps to a character, since // the ev_text event will follow immediately after in that case. if (ev->type == ev_keydown && ch >= 32 && ch <= 127) - return false; + return true; if (M_ChangeStringCvar(ch)) return true; @@ -11235,7 +11239,8 @@ static void M_DrawRoomMenu(void) if (dot_frame < 0) dot_frame = 0; - strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame)); + if (dot_frame != 3) + strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame)); } frame += renderdeltatics; diff --git a/src/m_menu.h b/src/m_menu.h index 3cd2f66d3..99a5b6de4 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -378,7 +378,7 @@ typedef struct char displayname[SKINNAMESIZE+1]; INT16 skinnum[2]; UINT16 oppositecolor; - char nametag[8]; + char nametag[8+1]; patch_t *namepic; UINT16 tagtextcolor; UINT16 tagoutlinecolor; diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index 36ed71826..917e32b59 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -307,7 +307,7 @@ boolean CL_SendJoin(void) else player2name = cv_playername2.zstring; - strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); + strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, sizeof(netbuffer->u.clientcfg.names[0])-1); strncpy(netbuffer->u.clientcfg.names[1], player2name, MAXPLAYERNAME); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); diff --git a/src/netcode/commands.c b/src/netcode/commands.c index 46dfbc741..f3bbc8a86 100644 --- a/src/netcode/commands.c +++ b/src/netcode/commands.c @@ -41,6 +41,8 @@ typedef struct banreason_s static banreason_t *reasontail = NULL; //last entry, use prev static banreason_t *reasonhead = NULL; //1st entry, use next +static boolean bans_loaded = false; + void Ban_Add(const char *reason) { banreason_t *reasonlist = malloc(sizeof(*reasonlist)); @@ -85,6 +87,8 @@ void Ban_Load_File(boolean warning) if (!I_ClearBans) return; + bans_loaded = true; + f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r"); if (!f) @@ -124,6 +128,12 @@ void D_SaveBan(void) const char *address, *mask; const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt"); + if (!bans_loaded) + { + // don't save bans if they were never loaded. + return; + } + if (!reasonhead) { remove(path); diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c index 5a2e229d3..b24409db1 100644 --- a/src/netcode/d_net.c +++ b/src/netcode/d_net.c @@ -940,7 +940,7 @@ void Command_Droprate(void) static boolean ShouldDropPacket(void) { return (packetdropquantity[netbuffer->packettype]) - || (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100; + || (packetdroprate != 0 && rand() < (((double)RAND_MAX) * (packetdroprate / 100.f))) || packetdroprate == 100; } #endif diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 5df2875fd..e073a863c 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -149,6 +149,10 @@ static void Command_Teamchange_f(void); static void Command_Teamchange2_f(void); static void Command_ServerTeamChange_f(void); +static void Command_MutePlayer_f(void); +static void Command_UnmutePlayer_f(void); +static void Got_MutePlayer(UINT8 **cp, INT32 playernum); + static void Command_Clearscores_f(void); // Remote Administration @@ -488,6 +492,10 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_TEAMCHANGE, Got_Teamchange); COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f, COM_LUA); + RegisterNetXCmd(XD_MUTEPLAYER, Got_MutePlayer); + COM_AddCommand("muteplayer", Command_MutePlayer_f, COM_LUA); + COM_AddCommand("unmuteplayer", Command_UnmutePlayer_f, COM_LUA); + RegisterNetXCmd(XD_CLEARSCORES, Got_Clearscores); COM_AddCommand("clearscores", Command_Clearscores_f, COM_LUA); COM_AddCommand("map", Command_Map_f, COM_LUA); @@ -663,6 +671,13 @@ void D_RegisterClientCommands(void) for (i = 0; i < MAXPLAYERS; i++) sprintf(player_names[i], "Player %d", 1 + i); + CV_RegisterVar(&cv_gravity); + CV_RegisterVar(&cv_tailspickup); + CV_RegisterVar(&cv_allowmlook); + CV_RegisterVar(&cv_flipcam); + CV_RegisterVar(&cv_flipcam2); + CV_RegisterVar(&cv_movebob); + if (dedicated) return; @@ -807,6 +822,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_jumpaxis2); CV_RegisterVar(&cv_spinaxis); CV_RegisterVar(&cv_spinaxis2); + CV_RegisterVar(&cv_shieldaxis); + CV_RegisterVar(&cv_shieldaxis2); CV_RegisterVar(&cv_fireaxis); CV_RegisterVar(&cv_fireaxis2); CV_RegisterVar(&cv_firenaxis); @@ -891,13 +908,6 @@ void D_RegisterClientCommands(void) // screen.c CV_RegisterVar(&cv_fullscreen); - CV_RegisterVar(&cv_renderview); - CV_RegisterVar(&cv_renderhitboxinterpolation); - CV_RegisterVar(&cv_renderhitboxgldepth); - CV_RegisterVar(&cv_renderhitbox); - CV_RegisterVar(&cv_renderwalls); - CV_RegisterVar(&cv_renderfloors); - CV_RegisterVar(&cv_renderthings); CV_RegisterVar(&cv_renderer); CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_width); @@ -918,8 +928,6 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_opflags); CV_RegisterVar(&cv_ophoopflags); CV_RegisterVar(&cv_mapthingnum); -// CV_RegisterVar(&cv_grid); -// CV_RegisterVar(&cv_snapto); CV_RegisterVar(&cv_freedemocamera); @@ -1315,7 +1323,7 @@ static void SendNameAndColor(void) CV_StealthSet(&cv_playername, player_names[consoleplayer]); HU_AddChatText("\x85*You must wait to change your name again", false); } - else if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) + else if ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer))) CV_StealthSet(&cv_playername, player_names[consoleplayer]); else // Cleanup name if changing it CleanupPlayerName(consoleplayer, cv_playername.zstring); @@ -2490,6 +2498,91 @@ static void Command_Teamchange2_f(void) SendNetXCmd2(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); } +static void MutePlayer(boolean mute) +{ + UINT8 data[2]; + if (!(server || (IsPlayerAdmin(consoleplayer)))) + { + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); + return; + } + + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("muteplayer : mute a player\n")); + return; + } + + data[0] = atoi(COM_Argv(1)); + if (data[0] >= MAXPLAYERS || !playeringame[data[0]]) + { + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %u!\n"), (unsigned int)data[0]); + return; + } + + if (players[data[0]].muted && mute) + { + CONS_Printf(M_GetText("%s is already muted!\n"), player_names[data[0]]); + return; + } + else if (!players[data[0]].muted && !mute) + { + CONS_Printf(M_GetText("%s is not muted!\n"), player_names[data[0]]); + return; + } + + data[1] = mute; + SendNetXCmd(XD_MUTEPLAYER, &data, sizeof(data)); +} + +static void Command_MutePlayer_f(void) +{ + MutePlayer(true); +} + +static void Command_UnmutePlayer_f(void) +{ + MutePlayer(false); +} + +static void Got_MutePlayer(UINT8 **cp, INT32 playernum) +{ + UINT8 player = READUINT8(*cp); + UINT8 muted = READUINT8(*cp); + if (playernum != serverplayer && !IsPlayerAdmin(playernum)) + { + CONS_Alert(CONS_WARNING, M_GetText("Illegal mute received from player %s\n"), player_names[playernum]); + if (server) + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + + if (player >= MAXPLAYERS || !playeringame[player]) + { + CONS_Alert(CONS_WARNING, M_GetText("Illegal mute received from player %s\n"), player_names[playernum]); + if (server) + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + + if (!players[player].muted && muted) + { + if (player == consoleplayer) + CONS_Printf(M_GetText("You have been muted.\n")); + else + CONS_Printf(M_GetText("%s has been muted.\n"), player_names[player]); + } + else if (players[player].muted && !muted) + { + if (player == consoleplayer) + CONS_Printf(M_GetText("You are no longer muted.\n")); + else + CONS_Printf(M_GetText("%s is no longer muted.\n"), player_names[player]); + } + + players[player].muted = muted; +} + static void Command_ServerTeamChange_f(void) { changeteam_union NetPacket; @@ -4787,7 +4880,7 @@ static void ForceSkin_OnChange(void) //Allows the player's name to be changed if cv_mute is off. static void Name_OnChange(void) { - if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) + if ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer))) { CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CV_StealthSet(&cv_playername, player_names[consoleplayer]); @@ -4798,7 +4891,7 @@ static void Name_OnChange(void) static void Name2_OnChange(void) { - if (cv_mute.value) //Secondary player can't be admin. + if (cv_mute.value || players[consoleplayer].muted) //Secondary player can't be admin. { CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]); diff --git a/src/netcode/d_netcmd.h b/src/netcode/d_netcmd.h index e30fa4a02..f92878a4e 100644 --- a/src/netcode/d_netcmd.h +++ b/src/netcode/d_netcmd.h @@ -94,7 +94,10 @@ extern consvar_t cv_inttime, cv_coopstarposts, cv_cooplives, cv_advancemap, cv_p extern consvar_t cv_overtime; extern consvar_t cv_startinglives; -// for F_finale.c +extern consvar_t cv_gravity, cv_movebob; +extern consvar_t cv_tailspickup; + +// for f_finale.c extern consvar_t cv_rollingdemos; extern consvar_t cv_ringslinger, cv_soundtest; @@ -105,7 +108,6 @@ extern consvar_t cv_maxping; extern consvar_t cv_pingtimeout; extern consvar_t cv_showping; - extern consvar_t cv_skipmapcheck; extern consvar_t cv_sleep; @@ -147,6 +149,7 @@ typedef enum XD_LUACMD, // 22 XD_LUAVAR, // 23 XD_LUAFILE, // 24 + XD_MUTEPLAYER, // 25 MAXNETXCMD } netxcmd_t; diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c index 2b52380cf..b8c662a51 100644 --- a/src/netcode/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -134,7 +134,7 @@ HMS_on_read (char *s, size_t _1, size_t n, void *userdata) return n; } -static struct HMS_buffer * +FUNCDEBUG static struct HMS_buffer * HMS_connect (int proto, const char *format, ...) { va_list ap; diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index bbabc8f1d..f4601e4ac 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -115,12 +115,12 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.refusereason = GetRefuseReason(node); strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], - sizeof netbuffer->u.serverinfo.gametypename); + sizeof(netbuffer->u.serverinfo.gametypename)-1); netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); netbuffer->u.serverinfo.flags = (dedicated ? SV_DEDICATED : 0); strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, - MAXSERVERNAME); + sizeof(netbuffer->u.serverinfo.servername)-1); strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16); @@ -184,7 +184,9 @@ static void SV_SendPlayerInfo(INT32 node) } netbuffer->u.playerinfo[i].num = i; - strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); + memset(netbuffer->u.playerinfo[i].name, 0x00, sizeof(netbuffer->u.playerinfo[i].name)); + memcpy(netbuffer->u.playerinfo[i].name, player_names[i], sizeof(player_names[i])); + netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0'; //fetch IP address diff --git a/src/p_enemy.c b/src/p_enemy.c index accc70073..428c023ff 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1222,8 +1222,7 @@ static void P_FaceStabFlume(mobj_t *actor) if (P_MobjWasRemoved(flume)) return; - flume->destscale = actor->scale*3; - P_SetScale(flume, flume->destscale); + P_SetScale(flume, 3*actor->scale, true); P_SetTarget(&flume->target, actor); flume->sprite = SPR_JETF; flume->frame = FF_FULLBRIGHT; @@ -1342,8 +1341,7 @@ void A_FaceStabHurl(mobj_t *actor) { hwork = hwork->hnext; hwork->angle = actor->angle + ANGLE_90; - hwork->destscale = FixedSqrt(step*basesize); - P_SetScale(hwork, hwork->destscale); + P_SetScale(hwork, FixedSqrt(step*basesize), true); hwork->fuse = 2; P_MoveOrigin(hwork, actor->x + xo*(15-step), actor->y + yo*(15-step), actor->z + (actor->height - hwork->height)/2 + (P_MobjFlip(actor)*(8<destscale = FRACUNIT; dust->scalespeed = 4*FRACUNIT/TICRATE; dust->fuse = TICRATE; @@ -2556,7 +2554,7 @@ void A_VultureFly(mobj_t *actor) dust = P_SpawnMobj(actor->x + P_RandomFixed() - FRACUNIT/2, actor->y + P_RandomFixed() - FRACUNIT/2, actor->z + actor->height/2 + P_RandomFixed() - FRACUNIT/2, MT_PARTICLE); if (!P_MobjWasRemoved(dust)) { - P_SetScale(dust, 2*FRACUNIT); + P_SetScale(dust, 2*FRACUNIT, true); dust->destscale = FRACUNIT/3; dust->scalespeed = FRACUNIT/40; dust->fuse = TICRATE*2; @@ -2765,15 +2763,9 @@ void A_LobShot(mobj_t *actor) return; if (actor->type == MT_BLACKEGGMAN) - { - shot->destscale = actor->scale/2; - P_SetScale(shot, actor->scale/2); - } + P_SetScale(shot, actor->scale/2, true); else - { - shot->destscale = actor->scale; - P_SetScale(shot, actor->scale); - } + P_SetScale(shot, actor->scale, true); P_SetTarget(&shot->target, actor); // where it came from @@ -3218,8 +3210,7 @@ void A_Boss1Laser(mobj_t *actor) if (!P_MobjWasRemoved(point)) { point->angle = actor->angle; - point->destscale = actor->scale; - P_SetScale(point, point->destscale); + P_SetScale(point, actor->scale, true); P_SetTarget(&point->target, actor); P_MobjCheckWater(point); if (point->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) @@ -3230,7 +3221,8 @@ void A_Boss1Laser(mobj_t *actor) mobj_t *steam = P_SpawnMobj(x, y, point->watertop - size*mobjinfo[MT_DUST].height, MT_DUST); if (P_MobjWasRemoved(steam)) continue; - P_SetScale(steam, size*actor->scale); + P_SetScale(steam, size*actor->scale, false); + steam->old_scale = steam->scale; P_SetObjectMomZ(steam, FRACUNIT + 2*P_RandomFixed(), true); P_InstaThrust(steam, FixedAngle(P_RandomKey(360)*FRACUNIT), 2*P_RandomFixed()); if (point->info->painsound) @@ -3603,8 +3595,7 @@ void A_BossScream(mobj_t *actor) return; if (actor->eflags & MFE_VERTICALFLIP) mo->flags2 |= MF2_OBJECTFLIP; - mo->destscale = actor->scale; - P_SetScale(mo, mo->destscale); + P_SetScale(mo, actor->scale, true); if (actor->info->deathsound) S_StartSound(mo, actor->info->deathsound); } @@ -4197,7 +4188,7 @@ static void P_DoBoss5Death(mobj_t *mo) MT_FSGNB); if (!P_MobjWasRemoved(pole)) { - P_SetScale(pole, (pole->destscale = 2*FRACUNIT)); + P_SetScale(pole, 2*FRACUNIT, true); pole->momx = P_ReturnThrustX(pole, pole->angle, speed); pole->momy = P_ReturnThrustY(pole, pole->angle, speed); P_SetTarget(&pole->tracer, P_SpawnMobj( @@ -4207,7 +4198,7 @@ static void P_DoBoss5Death(mobj_t *mo) if (!P_MobjWasRemoved(pole->tracer)) { pole->tracer->flags |= MF_NOCLIPTHING; - P_SetScale(pole->tracer, (pole->tracer->destscale = 2*FRACUNIT)); + P_SetScale(pole->tracer, 2*FRACUNIT, true); pole->angle = pole->tracer->angle = mo->tracer->angle; pole->tracer->momx = pole->momx; pole->tracer->momy = pole->momy; @@ -4746,10 +4737,7 @@ void A_BubbleSpawn(mobj_t *actor) bubble = P_SpawnMobj(actor->x, actor->y, actor->z + (actor->height / 2), MT_MEDIUMBUBBLE); if (bubble) - { - bubble->destscale = actor->scale; - P_SetScale(bubble, actor->scale); - } + P_SetScale(bubble, actor->scale, true); } // Function: A_FanBubbleSpawn @@ -4792,10 +4780,7 @@ void A_FanBubbleSpawn(mobj_t *actor) bubble = P_SpawnMobj(actor->x, actor->y, hz, MT_MEDIUMBUBBLE); if (bubble) - { - bubble->destscale = actor->scale; - P_SetScale(bubble, actor->scale); - } + P_SetScale(bubble, actor->scale, true); } // Function: A_BubbleRise @@ -5072,8 +5057,7 @@ void A_ThrownRing(mobj_t *actor) P_SetTarget(&ring->target, actor); ring->color = actor->color; //copy color */ - ring->destscale = actor->scale; - P_SetScale(ring, actor->scale); + P_SetScale(ring, actor->scale, true); } } @@ -5652,8 +5636,7 @@ void A_JetbThink(mobj_t *actor) if (!P_MobjWasRemoved(bomb)) { P_SetTarget(&bomb->target, actor); - bomb->destscale = actor->scale; - P_SetScale(bomb, actor->scale); + P_SetScale(bomb, actor->scale, true); actor->reactiontime = TICRATE; // one second S_StartSound(actor, actor->info->attacksound); } @@ -5833,7 +5816,8 @@ void A_MinusDigging(mobj_t *actor) P_SetMobjState(par, actor->info->raisestate); if (P_MobjWasRemoved(par)) return; - P_SetScale(par, actor->scale*2); + P_SetScale(par, actor->scale*2, false); + par->old_scale = par->scale; if (actor->eflags & MFE_VERTICALFLIP) par->eflags |= MFE_VERTICALFLIP; return; @@ -5905,7 +5889,8 @@ void A_MinusPopup(mobj_t *actor) continue; P_Thrust(rock, ani*i, FRACUNIT); P_SetObjectMomZ(rock, 3*FRACUNIT, false); - P_SetScale(rock, rock->scale/3); + P_SetScale(rock, rock->scale/3, false); + rock->old_scale = rock->scale; } P_RadiusAttack(actor, actor, 2*actor->radius, 0, true); if (actor->tracer) @@ -5944,7 +5929,8 @@ void A_MinusCheck(mobj_t *actor) continue; P_Thrust(rock, ani*i, FRACUNIT); P_SetObjectMomZ(rock, 3*FRACUNIT, false); - P_SetScale(rock, rock->scale/3); + P_SetScale(rock, rock->scale/3, false); + rock->old_scale = rock->scale; } } } @@ -8273,8 +8259,9 @@ void A_EggShield(mobj_t *actor) else actor->z = actor->target->z; + P_SetScale(actor, actor->target->scale, false); actor->destscale = actor->target->destscale; - P_SetScale(actor, actor->target->scale); + actor->old_scale = actor->target->old_scale; actor->floorz = actor->target->floorz; actor->ceilingz = actor->target->ceilingz; @@ -8555,7 +8542,7 @@ void A_Boss3ShockThink(mobj_t *actor) P_SetTarget(&snew->target, actor->target); snew->fuse = actor->fuse; - P_SetScale(snew, actor->scale); + P_SetScale(snew, actor->scale, true); snew->destscale = actor->destscale; snew->scalespeed = actor->scalespeed; @@ -8757,8 +8744,7 @@ void A_SmokeTrailer(mobj_t *actor) if (P_MobjWasRemoved(th)) return; P_SetObjectMomZ(th, FRACUNIT, false); - th->destscale = actor->scale; - P_SetScale(th, actor->scale); + P_SetScale(th, actor->scale, true); th->tics -= P_RandomByte() & 3; if (th->tics < 1) th->tics = 1; @@ -9522,8 +9508,7 @@ void A_BossJetFume(mobj_t *actor) if (!P_MobjWasRemoved(filler)) { P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->fuse = 56; @@ -9540,8 +9525,7 @@ void A_BossJetFume(mobj_t *actor) if (!P_MobjWasRemoved(filler)) { P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->fuse = 57; @@ -9554,7 +9538,7 @@ void A_BossJetFume(mobj_t *actor) { P_SetTarget(&filler->target, actor); filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->fuse = 58; @@ -9575,8 +9559,7 @@ void A_BossJetFume(mobj_t *actor) filler = P_SpawnMobj(jetx, jety, jetz, MT_PROPELLER); P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->angle = actor->angle - ANGLE_180; @@ -9591,7 +9574,7 @@ void A_BossJetFume(mobj_t *actor) P_SetTarget(&filler->target, actor); filler->fuse = 59; P_SetTarget(&actor->tracer, filler); - P_SetScale(filler, (filler->destscale = actor->scale/3)); + P_SetScale(filler, actor->scale/3, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->color = SKINCOLOR_ICY; @@ -9610,8 +9593,7 @@ void A_BossJetFume(mobj_t *actor) { P_SetTarget(&filler->target, actor); // Boss 4 already uses its tracer for other things - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; } @@ -9633,8 +9615,7 @@ void A_BossJetFume(mobj_t *actor) { filler->movefactor = movefactor; P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; } @@ -9880,12 +9861,13 @@ void A_ToggleFlameJet(mobj_t* actor) // var1 = Angle adjustment (aka orbit speed) // var2: // Bits 1-10: height offset, max 1023 -// Bits 11-16: X radius factor (max 63, default 20) +// Bits 11-16: X radius factor (max 63, default 32) // Bit 17: set if object is Nightopian Helper // Bit 18: set to define X/Y/Z rotation factor -// Bits 19-20: Unused +// Bit 19: set to not sync scale to player +// Bit 20: Unused // Bits 21-26: Y radius factor (max 63, default 32) -// Bits 27-32: Z radius factor (max 63, default 32) +// Bits 27-32: Z radius factor (max 63, default 20) // // If MF_GRENADEBOUNCE is flagged on mobj, use actor->threshold to define X/Y/Z radius factor, max 1023 each: // Bits 1-10: X factor @@ -9926,6 +9908,12 @@ void A_OrbitNights(mobj_t* actor) } else { + if (!donotrescale) + { + P_SetScale(actor, actor->target->scale, true); + actor->old_scale = actor->target->old_scale; + } + actor->extravalue1 += var1; P_UnsetThingPosition(actor); { @@ -9953,9 +9941,6 @@ void A_OrbitNights(mobj_t* actor) else actor->flags2 &= ~MF2_DONTDRAW; } - - if (!donotrescale && actor->destscale != actor->target->destscale) - actor->destscale = actor->target->destscale; } } @@ -11204,9 +11189,10 @@ void A_SetScale(mobj_t *actor) return; } - target->destscale = locvar1; // destination scale - if (!(locvar2 & 65535)) - P_SetScale(target, locvar1); // this instantly changes current scale to var1 if used, if not destscale will alter scale to var1 anyway + if ((locvar2 & 65535) == 0) + P_SetScale(target, locvar1, true); // this instantly changes current scale to var1 if used, if not destscale will alter scale to var1 over time + else + target->destscale = locvar1; // destination scale } // Function: A_RemoteDamage @@ -11350,8 +11336,7 @@ void A_TrapShot(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) missile->flags2 |= MF2_OBJECTFLIP; - missile->destscale = actor->scale; - P_SetScale(missile, actor->scale); + P_SetScale(missile, actor->scale, true); if (missile->info->seesound) S_StartSound(missile, missile->info->seesound); @@ -11425,8 +11410,7 @@ void A_VileTarget(mobj_t *actor) fog->eflags |= MFE_VERTICALFLIP; fog->flags2 |= MF2_OBJECTFLIP; } - fog->destscale = actor->target->scale; - P_SetScale(fog, fog->destscale); + P_SetScale(fog, actor->target->scale, true); P_SetTarget(&actor->tracer, fog); P_SetTarget(&fog->target, actor); @@ -11459,8 +11443,7 @@ void A_VileTarget(mobj_t *actor) fog->eflags |= MFE_VERTICALFLIP; fog->flags2 |= MF2_OBJECTFLIP; } - fog->destscale = players[i].mo->scale; - P_SetScale(fog, fog->destscale); + P_SetScale(fog, players[i].mo->scale, true); if (players[i].mo == actor->target) // We only care to track the fog targeting who we REALLY hate right now P_SetTarget(&actor->tracer, fog); @@ -11617,8 +11600,8 @@ void A_VileFire(mobj_t *actor) return; // keep to same scale and gravity as tracer ALWAYS - actor->destscale = dest->scale; - P_SetScale(actor, actor->destscale); + P_SetScale(actor, dest->scale, true); + actor->old_scale = dest->old_scale; if (dest->eflags & MFE_VERTICALFLIP) { actor->eflags |= MFE_VERTICALFLIP; @@ -12804,8 +12787,7 @@ void A_LightBeamReset(mobj_t *actor) if (LUA_CallAction(A_LIGHTBEAMRESET, actor)) return; - actor->destscale = FRACUNIT + P_SignedRandom()*FRACUNIT/256; - P_SetScale(actor, actor->destscale); + P_SetScale(actor, FRACUNIT + P_SignedRandom()*FRACUNIT/256, true); if (!actor->spawnpoint) return; // this can't work properly welp @@ -13392,7 +13374,7 @@ void A_DoNPCSkid(mobj_t *actor) { particle->tics = 10; - P_SetScale(particle, 2*actor->scale/3); + P_SetScale(particle, 2*actor->scale/3, true); particle->destscale = actor->scale; P_SetObjectMomZ(particle, FRACUNIT, false); } @@ -13815,7 +13797,7 @@ static void P_DustRing(mobjtype_t mobjtype, UINT32 div, fixed_t x, fixed_t y, fi continue; dust->angle = ang*i + ANGLE_90; - P_SetScale(dust, FixedMul(initscale, scale)); + P_SetScale(dust, FixedMul(initscale, scale), true); dust->destscale = FixedMul(4*FRACUNIT + P_RandomFixed(), scale); dust->scalespeed = scale/24; P_Thrust(dust, ang*i, speed + FixedMul(P_RandomFixed(), scale)); @@ -13956,7 +13938,8 @@ void A_DustDevilThink(mobj_t *actor) while (layer && !P_MobjWasRemoved(layer)) { angle_t fa = layer->angle >> ANGLETOFINESHIFT; P_MoveOrigin(layer, layer->x + 5 * FixedMul(scale, FINECOSINE(fa)), layer->y + 5 * FixedMul(scale, FINESINE(fa)), layer->z); - layer->scale = scale; + P_SetScale(layer, scale, true); + layer->old_scale = actor->old_scale; layer->angle += ANG10 / 2; layer->momx = actor->momx; layer->momy = actor->momy; @@ -13970,8 +13953,7 @@ void A_DustDevilThink(mobj_t *actor) if (!P_MobjWasRemoved(dust)) { P_SetMobjState(dust, dust->info->spawnstate + P_RandomRange(0, 2)); - dust->destscale = scale * 3; - P_SetScale(dust, dust->destscale); + P_SetScale(dust, 3 * scale, true); } } @@ -13990,6 +13972,7 @@ void A_DustDevilThink(mobj_t *actor) layer = P_SpawnMobj(px, py, pz, MT_DUSTLAYER); if (P_MobjWasRemoved(layer)) continue; + P_SetScale(layer, scale, true); layer->momz = 5 * scale; layer->angle = ANGLE_90 + ANGLE_90*i; layer->extravalue1 = TICRATE * 3; @@ -14610,8 +14593,7 @@ void A_MinecartSparkThink(mobj_t *actor) continue; trail->tics = 2; trail->sprite = actor->sprite; - P_SetScale(trail, trail->scale/4); - trail->destscale = trail->scale; + P_SetScale(trail, trail->scale/4, true); } } @@ -14734,8 +14716,16 @@ void A_FireShrink(mobj_t *actor) if (LUA_CallAction(A_FIRESHRINK, actor)) return; - actor->destscale = locvar1; - actor->scalespeed = FRACUNIT/locvar2; + if (locvar2 == 0) + { + P_SetScale(actor, locvar1, true); + actor->scalespeed = FRACUNIT/12; // Reset scalespeed to the default + } + else + { + actor->destscale = locvar1; + actor->scalespeed = FRACUNIT/locvar2; + } } // Function: A_SpawnPterabytes diff --git a/src/p_inter.c b/src/p_inter.c index 8584e168a..5534f7865 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2774,8 +2774,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget mo = P_SpawnMobj(target->x, target->y, target->z, MT_EXTRALARGEBUBBLE); if (P_MobjWasRemoved(mo)) break; - mo->destscale = target->scale; - P_SetScale(mo, mo->destscale); + P_SetScale(mo, target->scale, true); P_SetMobjState(mo, mo->info->raisestate); break; @@ -3966,8 +3965,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) mo->fuse = 8*TICRATE; P_SetTarget(&mo->target, player->mo); - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); + P_SetScale(mo, player->mo->scale, true); // Angle offset by player angle, then slightly offset by amount of rings fa = ((i*FINEANGLES/16) + va - ((num_rings-1)*FINEANGLES/32)) & FINEMASK; @@ -4103,8 +4101,7 @@ void P_PlayerWeaponPanelBurst(player_t *player) mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); P_SetTarget(&mo->target, player->mo); mo->fuse = 12*TICRATE; - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); + P_SetScale(mo, player->mo->scale, true); // Angle offset by player angle fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK; @@ -4192,8 +4189,7 @@ void P_PlayerWeaponAmmoBurst(player_t *player) player->powers[power] = 0; mo->fuse = 12*TICRATE; - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); + P_SetScale(mo, player->mo->scale, true); // Angle offset by player angle fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK; @@ -4240,8 +4236,7 @@ void P_PlayerWeaponPanelOrAmmoBurst(player_t *player) mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \ P_SetTarget(&mo->target, player->mo); \ mo->fuse = 12*TICRATE; \ - mo->destscale = player->mo->scale; \ - P_SetScale(mo, player->mo->scale); \ + P_SetScale(mo, player->mo->scale, true); \ mo->momx = FixedMul(FINECOSINE(fa),ns); \ if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \ mo->momy = FixedMul(FINESINE(fa),ns); \ @@ -4263,8 +4258,7 @@ void P_PlayerWeaponPanelOrAmmoBurst(player_t *player) mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \ P_SetTarget(&mo->target, player->mo); \ mo->fuse = 12*TICRATE; \ - mo->destscale = player->mo->scale; \ - P_SetScale(mo, player->mo->scale); \ + P_SetScale(mo, player->mo->scale, true); \ mo->momx = FixedMul(FINECOSINE(fa),ns); \ if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \ mo->momy = FixedMul(FINESINE(fa),ns); \ diff --git a/src/p_local.h b/src/p_local.h index 9644e7a24..0bcd6da1d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -283,7 +283,6 @@ void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, b extern mapthing_t *itemrespawnque[ITEMQUESIZE]; extern tic_t itemrespawntime[ITEMQUESIZE]; extern size_t iquehead, iquetail; -extern consvar_t cv_gravity, cv_movebob; mobjtype_t P_GetMobjtype(UINT16 mthingtype); @@ -552,6 +551,7 @@ void P_ThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); void P_VectorInstaThrust(fixed_t xa, fixed_t xb, fixed_t xc, fixed_t ya, fixed_t yb, fixed_t yc, fixed_t za, fixed_t zb, fixed_t zc, fixed_t momentum, mobj_t *mo); void P_DoSuperTransformation(player_t *player, boolean giverings); +void P_DoSuperDetransformation(player_t *player); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); diff --git a/src/p_mobj.c b/src/p_mobj.c index 715e87974..55be8e54f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -917,7 +917,7 @@ void P_ExplodeMissile(mobj_t *mo) explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); if (!P_MobjWasRemoved(explodemo)) { - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); explodemo->destscale = mo->destscale; explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); @@ -926,7 +926,7 @@ void P_ExplodeMissile(mobj_t *mo) explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); if (!P_MobjWasRemoved(explodemo)) { - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); explodemo->destscale = mo->destscale; explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); @@ -935,7 +935,7 @@ void P_ExplodeMissile(mobj_t *mo) explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); if (!P_MobjWasRemoved(explodemo)) { - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); explodemo->destscale = mo->destscale; explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); @@ -944,7 +944,7 @@ void P_ExplodeMissile(mobj_t *mo) explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); if (!P_MobjWasRemoved(explodemo)) { - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); explodemo->destscale = mo->destscale; explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); @@ -3113,8 +3113,7 @@ boolean P_SceneryZMovement(mobj_t *mo) continue; explodemo->momx += ((prandom & 0x0F) << (FRACBITS-2)) * (i & 2 ? -1 : 1); explodemo->momy += ((prandom & 0xF0) << (FRACBITS-6)) * (i & 1 ? -1 : 1); - explodemo->destscale = mo->scale; - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); } if (mo->threshold != 42) // Don't make pop sound if threshold is 42. @@ -3140,7 +3139,7 @@ boolean P_SceneryZMovement(mobj_t *mo) mobj_t *flower = P_SpawnMobjFromMobj(mo, 0, 0, 0, flowertype); if (flower) { - P_SetScale(flower, mo->scale/16); + P_SetScale(flower, mo->scale/16, true); flower->destscale = mo->scale; flower->scalespeed = mo->scale/8; } @@ -3380,10 +3379,7 @@ void P_MobjCheckWater(mobj_t *mobj) else splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); if (!P_MobjWasRemoved(splish)) - { - splish->destscale = mobj->scale; - P_SetScale(splish, mobj->scale); - } + P_SetScale(splish, mobj->scale, true); } // skipping stone! @@ -3422,10 +3418,7 @@ void P_MobjCheckWater(mobj_t *mobj) else splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); if (!P_MobjWasRemoved(splish)) - { - splish->destscale = mobj->scale; - P_SetScale(splish, mobj->scale); - } + P_SetScale(splish, mobj->scale, true); } } @@ -3476,8 +3469,7 @@ void P_MobjCheckWater(mobj_t *mobj) else bubble->momz = 0; - bubble->destscale = mobj->scale; - P_SetScale(bubble, mobj->scale); + P_SetScale(bubble, mobj->scale, true); } } } @@ -5147,8 +5139,7 @@ static void P_Boss7Thinker(mobj_t *mobj) mobj_t *smoke = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height, MT_SMOKE); if (!P_MobjWasRemoved(smoke)) { - smoke->destscale = mobj->destscale; - P_SetScale(smoke, smoke->destscale); + P_SetScale(smoke, mobj->destscale, true); smoke->momz = FixedMul(FRACUNIT, smoke->scale); } } @@ -5599,7 +5590,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->hprev) { mobj->hprev->destscale = FRACUNIT + (2*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); - P_SetScale(mobj->hprev, mobj->hprev->destscale); + P_SetScale(mobj->hprev, mobj->hprev->destscale, false); P_MoveOrigin(mobj->hprev, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->hprev->height/2); mobj->hprev->momx = mobj->momx; @@ -5625,8 +5616,8 @@ static void P_Boss9Thinker(mobj_t *mobj) { S_StopSound(missile); if (mobj->extravalue1 >= 2) - P_SetScale(missile, FRACUNIT>>1); - missile->destscale = missile->scale>>1; + P_SetScale(missile, FRACUNIT/2, true); + missile->destscale = missile->scale/2; missile->fuse = TICRATE/2; missile->scalespeed = abs(missile->destscale - missile->scale)/missile->fuse; missile->z -= missile->height/2; @@ -5649,7 +5640,7 @@ static void P_Boss9Thinker(mobj_t *mobj) spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2); P_InstaThrust(spread,spread->angle,-spread->info->speed); spread->momz = missile->momz; - P_SetScale(spread, missile->scale); + P_SetScale(spread, missile->scale, true); spread->destscale = missile->destscale; spread->scalespeed = missile->scalespeed; spread->fuse = missile->fuse; @@ -5673,7 +5664,7 @@ static void P_Boss9Thinker(mobj_t *mobj) spread = P_SpawnMissile(mobj, mobj->target, missile->type); if (P_MobjWasRemoved(spread)) continue; - P_SetScale(spread, missile->scale); + P_SetScale(spread, missile->scale, true); spread->destscale = missile->destscale; spread->fuse = missile->fuse; spread->z -= spread->height/2; @@ -5730,12 +5721,12 @@ static void P_Boss9Thinker(mobj_t *mobj) { if (mobj->health > mobj->info->damage) { - P_SetScale(missile, FRACUNIT/3); + P_SetScale(missile, FRACUNIT/3, true); missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power } else { - P_SetScale(missile, FRACUNIT/5); + P_SetScale(missile, FRACUNIT/5, true); missile->color = SKINCOLOR_SUNSET; // sonic cd electric power } missile->destscale = missile->scale*2; @@ -5798,10 +5789,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (!P_MobjWasRemoved(missile)) { if (mobj->extravalue1 >= 2) - { - missile->destscale = FRACUNIT>>1; - P_SetScale(missile, missile->destscale); - } + P_SetScale(missile, FRACUNIT/2, true); missile->fuse = 3*TICRATE; missile->z -= missile->height/2; @@ -5820,8 +5808,7 @@ static void P_Boss9Thinker(mobj_t *mobj) spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2); P_InstaThrust(spread,spread->angle,spread->info->speed); spread->momz = missile->momz; - spread->destscale = FRACUNIT>>1; - P_SetScale(spread, spread->destscale); + P_SetScale(spread, FRACUNIT/2, true); spread->fuse = missile->fuse; } P_InstaThrust(missile,missile->angle,missile->info->speed); @@ -5838,8 +5825,7 @@ static void P_Boss9Thinker(mobj_t *mobj) spread = P_SpawnMissile(mobj, mobj->target, missile->type); if (!P_MobjWasRemoved(spread)) { - spread->destscale = FRACUNIT>>1; - P_SetScale(spread, spread->destscale); + P_SetScale(spread, FRACUNIT/2, true); spread->fuse = missile->fuse; spread->z -= spread->height/2; } @@ -6103,8 +6089,12 @@ static void P_Boss9Thinker(mobj_t *mobj) whoosh->flags |= MF_NOCLIPHEIGHT; #endif - P_SetMobjState(mobj->tracer, S_JETFUMEFLASH); - P_SetScale(mobj->tracer, mobj->scale << 1); + if (!P_MobjWasRemoved(mobj->tracer)) + { + P_SetMobjState(mobj->tracer, S_JETFUMEFLASH); + P_SetScale(mobj->tracer, 2*mobj->scale, false); + mobj->tracer->old_scale = mobj->tracer->scale; + } } else { @@ -6439,28 +6429,24 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb // // Sets the sprite scaling // -void P_SetScale(mobj_t *mobj, fixed_t newscale) +void P_SetScale(mobj_t *mobj, fixed_t newscale, boolean instant) { - player_t *player; - fixed_t oldscale; - if (!mobj) return; - oldscale = mobj->scale; //keep for adjusting stuff below - - mobj->scale = newscale; - - mobj->radius = FixedMul(FixedDiv(mobj->radius, oldscale), newscale); - mobj->height = FixedMul(FixedDiv(mobj->height, oldscale), newscale); - - player = mobj->player; - - if (player) + if (mobj->player) { G_GhostAddScale(newscale); - player->viewheight = FixedMul(FixedDiv(player->viewheight, oldscale), newscale); // Nonono don't calculate viewheight elsewhere, this is the best place for it! + // Nonono don't calculate viewheight elsewhere, this is the best place for it! + mobj->player->viewheight = FixedMul(FixedDiv(mobj->player->viewheight, mobj->scale), newscale); } + + mobj->radius = FixedMul(FixedDiv(mobj->radius, mobj->scale), newscale); + mobj->height = FixedMul(FixedDiv(mobj->height, mobj->scale), newscale); + + mobj->scale = newscale; + if (instant) + mobj->destscale = mobj->old_scale = newscale; } void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on your target @@ -6815,8 +6801,7 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) thing->flags |= MF_NOCLIPHEIGHT; thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP); - P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale)); - thing->destscale = thing->scale; + P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale), true); thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale); #define NewMH(mobj) mobj->height // Ugly mobj-height and player-height defines, for the sake of prettier code @@ -7164,11 +7149,11 @@ static void P_MobjScaleThink(mobj_t *mobj) correctionType = 2; // Correct Z position by moving down if (abs(mobj->scale - mobj->destscale) < mobj->scalespeed) - P_SetScale(mobj, mobj->destscale); + P_SetScale(mobj, mobj->destscale, false); else if (mobj->scale < mobj->destscale) - P_SetScale(mobj, mobj->scale + mobj->scalespeed); + P_SetScale(mobj, mobj->scale + mobj->scalespeed, false); else if (mobj->scale > mobj->destscale) - P_SetScale(mobj, mobj->scale - mobj->scalespeed); + P_SetScale(mobj, mobj->scale - mobj->scalespeed, false); if (correctionType == 1) mobj->z -= (mobj->height - oldheight)/2; @@ -7261,8 +7246,9 @@ static boolean P_DrownNumbersSceneryThink(mobj_t *mobj) mobj->x = mobj->target->x; mobj->y = mobj->target->y; + P_SetScale(mobj, mobj->target->scale, false); mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); + mobj->old_scale = mobj->target->old_scale; if (mobj->target->eflags & MFE_VERTICALFLIP) { @@ -7423,10 +7409,10 @@ static boolean P_ParticleGenSceneryThink(mobj_t *mobj) (mobjtype_t)mobj->threshold); if (!P_MobjWasRemoved(spawn)) { - P_SetScale(spawn, mobj->scale); - spawn->momz = FixedMul(mobj->movefactor, spawn->scale); + P_SetScale(spawn, mobj->scale, true); spawn->destscale = spawn->scale/100; spawn->scalespeed = spawn->scale/mobj->health; + spawn->momz = FixedMul(mobj->movefactor, spawn->scale); spawn->tics = (tic_t)mobj->health; spawn->flags2 |= (mobj->flags2 & MF2_OBJECTFLIP); spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones @@ -7646,8 +7632,7 @@ static void P_RosySceneryThink(mobj_t *mobj) mobj_t *cdlhrt = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_CDLHRT); if (!P_MobjWasRemoved(cdlhrt)) { - cdlhrt->destscale = (5*mobj->scale) >> 4; - P_SetScale(cdlhrt, cdlhrt->destscale); + P_SetScale(cdlhrt, (5*mobj->scale) >> 4, true); cdlhrt->fuse = (5*TICRATE) >> 1; cdlhrt->momz = mobj->scale; P_SetTarget(&cdlhrt->target, mobj); @@ -7901,8 +7886,9 @@ static void P_MobjSceneryThink(mobj_t *mobj) mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); + P_SetScale(mobj, mobj->target->scale, false); mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); + mobj->old_scale = mobj->target->old_scale; if (!(mobj->eflags & MFE_VERTICALFLIP)) mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); @@ -8052,7 +8038,9 @@ static void P_MobjSceneryThink(mobj_t *mobj) } P_SetThingPosition(mobj); - P_SetScale(mobj, mobj->target->scale); + P_SetScale(mobj, mobj->target->scale, false); + mobj->destscale = mobj->target->destscale; + mobj->old_scale = mobj->target->old_scale; } break; case MT_TUTORIALFLOWER: @@ -8494,8 +8482,8 @@ static void P_ArrowThink(mobj_t *mobj) if (!P_MobjWasRemoved(dust)) { dust->tics = 18; - dust->scalespeed = 4096; dust->destscale = FRACUNIT/32; + dust->scalespeed = FRACUNIT/16; } } } @@ -9906,9 +9894,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) traindust->frame = P_RandomRange(0, 8)|FF_TRANS90; traindust->angle = mobj->angle; traindust->tics = TICRATE*4; + P_SetScale(traindust, FRACUNIT*6, true); traindust->destscale = FRACUNIT*64; traindust->scalespeed = FRACUNIT/24; - P_SetScale(traindust, FRACUNIT*6); } break; case MT_TRAINSTEAMSPAWNER: @@ -9919,9 +9907,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_SetMobjState(steam, S_TRAINSTEAM); steam->frame = P_RandomRange(0, 1)|FF_TRANS90; steam->tics = TICRATE*8; + P_SetScale(steam, FRACUNIT*16, true); steam->destscale = FRACUNIT*64; steam->scalespeed = FRACUNIT/8; - P_SetScale(steam, FRACUNIT*16); steam->momx = P_SignedRandom()*32; steam->momy = -64*FRACUNIT; steam->momz = 2*FRACUNIT; @@ -10927,7 +10915,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (titlemapinaction) mobj->flags &= ~MF_NOTHINK; break; case MT_LOCKONINF: - P_SetScale(mobj, (mobj->destscale = 3*mobj->scale)); + P_SetScale(mobj, 3*mobj->scale, true); break; case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: mobj->fuse = mobj->info->painchance; @@ -10938,8 +10926,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (P_MobjWasRemoved(spawn)) break; - spawn->destscale = mobj->scale; - P_SetScale(spawn, mobj->scale); + P_SetScale(spawn, mobj->scale, true); P_SetTarget(&spawn->target, mobj); } break; @@ -10956,8 +10943,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (P_MobjWasRemoved(spawn)) break; - spawn->destscale = mobj->scale; - P_SetScale(spawn, mobj->scale); + P_SetScale(spawn, mobj->scale, true); P_SetTarget(&mobj->tracer, spawn); P_SetTarget(&spawn->target, mobj); } @@ -10974,8 +10960,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (P_MobjWasRemoved(ball)) continue; - ball->destscale = mobj->scale; - P_SetScale(ball, mobj->scale); + P_SetScale(ball, mobj->scale, true); P_SetTarget(&ball->target, mobj); ball->movedir = FixedAngle(FixedMul(FixedDiv(i<info->damage<threshold = ball->radius + mobj->radius + FixedMul(ball->info->painchance, ball->scale); @@ -10996,8 +10981,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (P_MobjWasRemoved(ball)) continue; - ball->destscale = mobj->scale; - P_SetScale(ball, mobj->scale); + P_SetScale(ball, mobj->scale, true); P_SetTarget(&lastball->tracer, ball); P_SetTarget(&ball->target, mobj); lastball = ball; @@ -11856,7 +11840,7 @@ void P_SpawnPlayer(INT32 playernum) p->awayviewtics = 0; // set the scale to the mobj's destscale so settings get correctly set. if we don't, they sometimes don't. - P_SetScale(mobj, mobj->destscale); + P_SetScale(mobj, mobj->destscale, true); P_FlashPal(p, 0, 0); // Resets // Set bounds accurately. @@ -12030,7 +12014,7 @@ void P_MovePlayerToStarpost(INT32 playernum) z = p->starpostz << FRACBITS; - P_SetScale(mobj, (mobj->destscale = abs(p->starpostscale))); + P_SetScale(mobj, abs(p->starpostscale), true); if (p->starpostscale < 0) { @@ -13138,8 +13122,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (P_MobjWasRemoved(corona)) break; - P_SetScale(corona, (corona->destscale = mobj->scale*3)); P_SetTarget(&mobj->tracer, corona); + P_SetScale(corona, 3*mobj->scale, true); } break; case MT_FLAMEHOLDER: @@ -13157,8 +13141,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (P_MobjWasRemoved(corona)) break; - P_SetScale(corona, (corona->destscale = flame->scale*3)); P_SetTarget(&flame->tracer, corona); + P_SetScale(corona, 3*flame->scale, true); } } break; @@ -13246,10 +13230,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_DSZSTALAGMITE: case MT_DSZ2STALAGMITE: case MT_KELP: - if (mthing->args[0]) { // make mobj twice as big as normal - P_SetScale(mobj, 2*mobj->scale); // not 2*FRACUNIT in case of something like the old ERZ3 mode - mobj->destscale = mobj->scale; - } + if (mthing->args[0]) // make mobj twice as big as normal + P_SetScale(mobj, 2*mobj->scale, true); // not 2*FRACUNIT in case of something like the old ERZ3 mode break; case MT_THZTREE: { // Spawn the branches @@ -13328,10 +13310,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_LAVAFALL: mobj->fuse = 30 + mthing->args[0]; if (mthing->args[1]) - { - P_SetScale(mobj, 2*mobj->scale); - mobj->destscale = mobj->scale; - } + P_SetScale(mobj, 2*mobj->scale, true); break; case MT_PYREFLY: //start on fire if args[0], otherwise behave normally @@ -13394,8 +13373,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; P_SetTarget(&elecmobj->target, mobj); elecmobj->angle = FixedAngle(mthing->angle << FRACBITS); - elecmobj->destscale = mobj->scale*2; - P_SetScale(elecmobj, elecmobj->destscale); + P_SetScale(elecmobj, 2*mobj->scale, true); } break; case MT_STARPOST: @@ -13453,8 +13431,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return false; } base->angle = mobjangle + ANGLE_90; + P_SetScale(base, mobj->scale, true); base->destscale = mobj->destscale; - P_SetScale(base, mobj->scale); P_SetTarget(&base->target, mobj); P_SetTarget(&mobj->tracer, base); } @@ -13631,8 +13609,9 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, return NULL; mobj->spawnpoint = mthing; - P_SetScale(mobj, FixedMul(mobj->scale, mthing->scale)); + P_SetScale(mobj, FixedMul(mobj->scale, mthing->scale), false); mobj->destscale = FixedMul(mobj->destscale, mthing->scale); + mobj->old_scale = FixedMul(mobj->old_scale, mthing->scale); mobj->spritexscale = mthing->spritexscale; mobj->spriteyscale = mthing->spriteyscale; @@ -14086,8 +14065,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); speed = FixedMul(th->info->speed, th->scale); @@ -14150,8 +14128,7 @@ mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); speed = FixedMul(th->info->speed, th->scale); @@ -14217,8 +14194,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za, if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); speed = FixedMul(th->info->speed, th->scale); @@ -14289,8 +14265,7 @@ mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type) if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); if (source->type == MT_METALSONIC_BATTLE && source->health < 4) speed = FixedMul(FixedMul(th->info->speed, 3*FRACUNIT/2), th->scale); @@ -14392,8 +14367,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); th->flags2 |= flags2; @@ -14475,8 +14449,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo newmobj->old_z2 = mobj->old_z2 + zofs; } + P_SetScale(newmobj, mobj->scale, false); newmobj->destscale = mobj->destscale; - P_SetScale(newmobj, mobj->scale); newmobj->old_x2 = mobj->old_x2 + xofs; newmobj->old_y2 = mobj->old_y2 + yofs; @@ -14505,9 +14479,13 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo newmobj->old_scale2 = mobj->old_scale2; newmobj->old_scale = mobj->old_scale; + newmobj->old_spritexscale2 = mobj->old_spritexscale2; newmobj->old_spritexscale = mobj->old_spritexscale; + newmobj->old_spriteyscale2 = mobj->old_spriteyscale2; newmobj->old_spriteyscale = mobj->old_spriteyscale; + newmobj->old_spritexoffset2 = mobj->old_spritexoffset2; newmobj->old_spritexoffset = mobj->old_spritexoffset; + newmobj->old_spriteyoffset2 = mobj->old_spriteyoffset2; newmobj->old_spriteyoffset = mobj->old_spriteyoffset; return newmobj; diff --git a/src/p_mobj.h b/src/p_mobj.h index f833415ed..fd75f75c6 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -315,8 +315,8 @@ typedef struct mobj_s INT32 blendmode; // blend mode fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; - fixed_t old_spritexscale, old_spriteyscale; - fixed_t old_spritexoffset, old_spriteyoffset; + fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; + fixed_t old_spritexoffset, old_spriteyoffset, old_spritexoffset2, old_spriteyoffset2; struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears @@ -458,8 +458,8 @@ typedef struct precipmobj_s INT32 blendmode; // blend mode fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; - fixed_t old_spritexscale, old_spriteyscale; - fixed_t old_spritexoffset, old_spriteyoffset; + fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; + fixed_t old_spritexoffset, old_spriteyoffset, old_spritexoffset2, old_spriteyoffset2; struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears @@ -527,7 +527,7 @@ void P_SnowThinker(precipmobj_t *mobj); void P_RainThinker(precipmobj_t *mobj); void P_NullPrecipThinker(precipmobj_t *mobj); void P_RemovePrecipMobj(precipmobj_t *mobj); -void P_SetScale(mobj_t *mobj, fixed_t newscale); +void P_SetScale(mobj_t *mobj, fixed_t newscale, boolean instant); void P_XYMovement(mobj_t *mo); void P_RingXYMovement(mobj_t *mo); void P_SceneryXYMovement(mobj_t *mo); diff --git a/src/p_saveg.c b/src/p_saveg.c index 6c6548c56..c385bd8e1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -170,6 +170,7 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].panim); WRITEUINT8(save_p, players[i].stronganim); WRITEUINT8(save_p, players[i].spectator); + WRITEUINT8(save_p, players[i].muted); WRITEUINT16(save_p, players[i].flashpal); WRITEUINT16(save_p, players[i].flashcount); @@ -399,6 +400,7 @@ static void P_NetUnArchivePlayers(void) players[i].panim = READUINT8(save_p); players[i].stronganim = READUINT8(save_p); players[i].spectator = READUINT8(save_p); + players[i].muted = READUINT8(save_p); players[i].flashpal = READUINT16(save_p); players[i].flashcount = READUINT16(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 1cb3ccd21..93c4937c4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3328,8 +3328,6 @@ static void P_InitializeSeg(seg_t *seg) seg->lightmaps = NULL; // list of static lightmap for this seg #endif - seg->numlights = 0; - seg->rlights = NULL; seg->polyseg = NULL; seg->dontrenderme = false; } diff --git a/src/p_spec.c b/src/p_spec.c index 572258165..805817fb0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -363,7 +363,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) // Increase the size to make room for the new animation definition maxanims++; animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); - strncpy(animdefs[i].startname, animdefsToken, 9); + strncpy(animdefs[i].startname, animdefsToken, sizeof(animdefs[i].startname)-1); } // animdefs[i].startname is now set to animdefsToken either way. diff --git a/src/p_user.c b/src/p_user.c index 1db22a645..e33424385 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1378,7 +1378,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) // P_DoSuperDetransformation // // Detransform into regular Sonic! -static void P_DoSuperDetransformation(player_t *player) +void P_DoSuperDetransformation(player_t *player) { player->powers[pw_emeralds] = 0; // lost the power stones P_SpawnGhostMobj(player->mo); @@ -2038,8 +2038,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) P_SetTarget(&ghost->target, mobj); P_SetTarget(&ghost->dontdrawforviewmobj, mobj); // Hide the ghost in first-person - P_SetScale(ghost, mobj->scale); - ghost->destscale = mobj->scale; + P_SetScale(ghost, mobj->scale, true); if (mobj->eflags & MFE_VERTICALFLIP) { @@ -2098,6 +2097,11 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->old_pitch = mobj->old_pitch2; ghost->old_roll = mobj->old_roll2; ghost->old_spriteroll = mobj->old_spriteroll2; + ghost->old_spritexscale = mobj->old_spritexscale2; + ghost->old_spriteyscale = mobj->old_spriteyscale2; + ghost->old_spritexoffset = mobj->old_spritexoffset2; + ghost->old_spriteyoffset = mobj->old_spriteyoffset2; + ghost->old_scale = mobj->old_scale2; return ghost; } @@ -2153,7 +2157,7 @@ void P_SpawnThokMobj(player_t *player) mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP); // scale - P_SetScale(mobj, (mobj->destscale = player->mo->scale)); + P_SetScale(mobj, player->mo->scale, true); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -2217,8 +2221,7 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type) mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP); // scale - P_SetScale(mobj, player->mo->scale); - mobj->destscale = player->mo->scale; + P_SetScale(mobj, player->mo->scale, true); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -3041,9 +3044,8 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) P_SetMobjState(numbermobj, numbermobj->info->spawnstate+timeleft); P_SetTarget(&numbermobj->target, player->mo); + P_SetScale(numbermobj, player->mo->scale, true); numbermobj->threshold = 40; - numbermobj->destscale = player->mo->scale; - P_SetScale(numbermobj, player->mo->scale); } } } @@ -3105,10 +3107,7 @@ static void P_CheckInvincibilityTimer(player_t *player) { mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP); if (!P_MobjWasRemoved(sparkle)) - { - sparkle->destscale = player->mo->scale; - P_SetScale(sparkle, player->mo->scale); - } + P_SetScale(sparkle, player->mo->scale, true); } // Resume normal music stuff. @@ -3183,8 +3182,7 @@ static void P_DoBubbleBreath(player_t *player) if (bubble) { bubble->threshold = 42; - bubble->destscale = player->mo->scale; - P_SetScale(bubble, bubble->destscale); + P_SetScale(bubble, player->mo->scale, true); } // Tails stirs up the water while flying in it @@ -3206,20 +3204,14 @@ static void P_DoBubbleBreath(player_t *player) player->mo->y + stirwatery, stirwaterz, MT_SMALLBUBBLE); if (!P_MobjWasRemoved(bubble)) - { - bubble->destscale = player->mo->scale; - P_SetScale(bubble,bubble->destscale); - } + P_SetScale(bubble, player->mo->scale, true); bubble = P_SpawnMobj( player->mo->x - stirwaterx, player->mo->y - stirwatery, stirwaterz, MT_SMALLBUBBLE); if (!P_MobjWasRemoved(bubble)) - { - bubble->destscale = player->mo->scale; - P_SetScale(bubble,bubble->destscale); - } + P_SetScale(bubble, player->mo->scale, true); } } @@ -4189,16 +4181,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) I_Assert(player != NULL); I_Assert(!P_MobjWasRemoved(player->mo)); - - // Toss a flag - if (cmd->buttons & BT_TOSSFLAG && G_GametypeHasTeams() - && !(player->powers[pw_super]) && !(player->tossdelay)) - { - if (!(player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - P_PlayerEmeraldBurst(player, true); // Toss emeralds - else - P_PlayerFlagBurst(player, true); - } if (!(cmd->buttons & (BT_ATTACK|BT_FIRENORMAL))) { @@ -4208,7 +4190,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) return; } - if (player->pflags & PF_ATTACKDOWN || player->climbing) + if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT))) return; // Fire a fireball if we have the Fire Flower powerup! @@ -4224,7 +4206,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) } // No ringslinging outside of ringslinger! - if (!G_RingSlingerGametype() || player->weapondelay || (G_TagGametype() && !(player->pflags & PF_TAGIT))) + if (!G_RingSlingerGametype() || player->weapondelay) return; player->pflags |= PF_ATTACKDOWN; @@ -4424,10 +4406,7 @@ static void P_DoSuperStuff(player_t *player) { spark = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SUPERSPARK); if (!P_MobjWasRemoved(spark)) - { - spark->destscale = player->mo->scale; - P_SetScale(spark, player->mo->scale); - } + P_SetScale(spark, player->mo->scale, true); } // Ran out of rings while super! @@ -4452,14 +4431,14 @@ boolean P_SuperReady(player_t *player, boolean transform) || !ALL7EMERALDS(emeralds) || !(player->rings >= 50))) return false; - + if (player->mo && !player->powers[pw_tailsfly] && !player->powers[pw_carry] && (player->charflags & SF_SUPER) && !P_PlayerInPain(player) && !player->climbing - && !(player->pflags & (PF_FULLSTASIS|PF_THOKKED|PF_STARTDASH|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) + && !(player->pflags & (PF_JUMPSTASIS|PF_THOKKED|PF_STARTDASH|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) && ((player->pflags & PF_JUMPED) || (P_IsObjectOnGround(player->mo) && (player->panim == PA_IDLE || player->panim == PA_EDGE || player->panim == PA_WALK || player->panim == PA_RUN || (player->charflags & SF_DASHMODE && player->panim == PA_DASH)))) && !(maptol & TOL_NIGHTS)) @@ -4677,8 +4656,7 @@ void P_DoSpinDashDust(player_t *player) P_SetMobjState(particle, S_SPINDUST_FIRE1); P_SetTarget(&particle->target, player->mo); - particle->destscale = (2*player->mo->scale)/3; - P_SetScale(particle, particle->destscale); + P_SetScale(particle, (2*player->mo->scale)/3, true); if (player->mo->eflags & MFE_VERTICALFLIP) // readjust z position if needed particle->z = player->mo->z + player->mo->height - particle->height; prandom[0] = P_RandomFixed()<<2; // P_RandomByte()<<10 @@ -5077,7 +5055,7 @@ void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type) if (!P_MobjWasRemoved(missile)) { P_SetTarget(&missile->target, player->mo); - P_SetScale(missile, (missile->destscale >>= 1)); + P_SetScale(missile, missile->destscale/2, true); missile->angle = ang + movang; missile->fuse = TICRATE/2; missile->extravalue2 = (99*FRACUNIT)/100; @@ -5281,7 +5259,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock // // Handles player jumping // -static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) +static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhack) { mobj_t *lockonthok = NULL, *visual = NULL; @@ -5314,45 +5292,53 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) ; else if (P_PlayerShieldThink(player, cmd, lockonthok, visual)) ; - else if ((cmd->buttons & BT_SPIN) && !LUA_HookPlayer(player, HOOK(JumpSpinSpecial))) + else if (cmd->buttons & BT_SPIN) { - switch (player->charability) + if (spinshieldhack && !(player->pflags & PF_SPINDOWN) && P_SuperReady(player, true) + && !player->powers[pw_invulnerability] && !(player->powers[pw_shield] & SH_NOSTACK)) // These two checks are no longer in P_SuperReady { - case CA_THOK: - if (player->powers[pw_super]) // Super Sonic float - { - if ((player->speed > 5*player->mo->scale) // FixedMul(5<mo->scale), but scale is FRACUNIT-based - && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) - { - if (player->panim != PA_RUN && player->panim != PA_WALK) - { - if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) - P_SetMobjState(player->mo, S_PLAY_FLOAT_RUN); - else - P_SetMobjState(player->mo, S_PLAY_FLOAT); - } - - player->mo->momz = 0; - player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); - player->secondjump = 1; - } - } - break; - case CA_TELEKINESIS: - if (!(player->pflags & (PF_THOKKED|PF_SPINDOWN)) || (player->charflags & SF_MULTIABILITY)) - { - P_Telekinesis(player, - -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) - FixedMul(384*FRACUNIT, player->mo->scale)); - } - break; - case CA_TWINSPIN: - if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_SPINDOWN)) || player->charflags & SF_MULTIABILITY)) - P_DoTwinSpin(player); - break; - default: - break; + // If you're using two-button play, can turn Super and aren't already, + // and you don't have a shield, then turn Super! + P_DoSuperTransformation(player, false); } + else if (!LUA_HookPlayer(player, HOOK(JumpSpinSpecial))) + switch (player->charability) + { + case CA_THOK: + if (player->powers[pw_super]) // Super Sonic float + { + if ((player->speed > 5*player->mo->scale) // FixedMul(5<mo->scale), but scale is FRACUNIT-based + && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) + { + if (player->panim != PA_RUN && player->panim != PA_WALK) + { + if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) + P_SetMobjState(player->mo, S_PLAY_FLOAT_RUN); + else + P_SetMobjState(player->mo, S_PLAY_FLOAT); + } + + player->mo->momz = 0; + player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); + player->secondjump = 1; + } + } + break; + case CA_TELEKINESIS: + if (!(player->pflags & (PF_THOKKED|PF_SPINDOWN)) || (player->charflags & SF_MULTIABILITY)) + { + P_Telekinesis(player, + -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) + FixedMul(384*FRACUNIT, player->mo->scale)); + } + break; + case CA_TWINSPIN: + if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_SPINDOWN)) || player->charflags & SF_MULTIABILITY)) + P_DoTwinSpin(player); + break; + default: + break; + } } } @@ -7417,9 +7403,8 @@ static void P_NiGHTSMovement(player_t *player) firstmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle+ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle+ANGLE_90, spawndist), z, MT_NIGHTSPARKLE); if (!P_MobjWasRemoved(firstmobj)) { - firstmobj->destscale = player->mo->scale; P_SetTarget(&firstmobj->target, player->mo); - P_SetScale(firstmobj, player->mo->scale); + P_SetScale(firstmobj, player->mo->scale, true); // Superloop turns sparkles red if (player->powers[pw_nights_superloop]) P_SetMobjState(firstmobj, mobjinfo[MT_NIGHTSPARKLE].seestate); @@ -7427,10 +7412,8 @@ static void P_NiGHTSMovement(player_t *player) secondmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle-ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle-ANGLE_90, spawndist), z, MT_NIGHTSPARKLE); if (!P_MobjWasRemoved(secondmobj)) { - secondmobj->destscale = player->mo->scale; P_SetTarget(&secondmobj->target, player->mo); - P_SetScale(secondmobj, player->mo->scale); - + P_SetScale(secondmobj, player->mo->scale, true); // Superloop turns sparkles red if (player->powers[pw_nights_superloop]) P_SetMobjState(secondmobj, mobjinfo[MT_NIGHTSPARKLE].seestate); @@ -7445,7 +7428,7 @@ static void P_NiGHTSMovement(player_t *player) { helpermobj->fuse = player->mo->fuse = leveltime; P_SetTarget(&helpermobj->target, player->mo); - P_SetScale(helpermobj, player->mo->scale); + P_SetScale(helpermobj, player->mo->scale, false); } } @@ -7645,8 +7628,7 @@ static void P_NiGHTSMovement(player_t *player) water->flags2 |= MF2_OBJECTFLIP; water->eflags |= MFE_VERTICALFLIP; } - water->destscale = player->mo->scale; - P_SetScale(water, player->mo->scale); + P_SetScale(water, player->mo->scale, true); } } @@ -7889,8 +7871,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle) P_SetTarget(&flame->target, player->mo); flame->angle = travelangle + i*(ANGLE_MAX/numangles); flame->fuse = TICRATE*7; // takes about an extra second to hit the ground - flame->destscale = player->mo->scale; - P_SetScale(flame, player->mo->scale); + P_SetScale(flame, player->mo->scale, true); if (!(player->mo->flags2 & MF2_OBJECTFLIP) != !(player->powers[pw_gravityboots])) // take gravity boots into account flame->flags2 |= MF2_OBJECTFLIP; flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); @@ -7927,8 +7908,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle) P_SetTarget(&flame->target, player->mo); flame->angle = travelangle; flame->fuse = TICRATE*6; - flame->destscale = player->mo->scale; - P_SetScale(flame, player->mo->scale); + P_SetScale(flame, player->mo->scale, true); if (!(player->mo->flags2 & MF2_OBJECTFLIP) != !(player->powers[pw_gravityboots])) // take gravity boots into account flame->flags2 |= MF2_OBJECTFLIP; flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); @@ -7976,8 +7956,7 @@ void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound) } particle->tics = 10; - particle->destscale = (2*mo->scale)/3; - P_SetScale(particle, particle->destscale); + P_SetScale(particle, (2*mo->scale)/3, true); P_SetObjectMomZ(particle, FRACUNIT, false); if (mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version @@ -8074,6 +8053,7 @@ void P_MovePlayer(player_t *player) { ticcmd_t *cmd; INT32 i; + boolean spinshieldhack = false; // Hack: Is Spin and Shield bound to the same button (pressed on the same tic)? fixed_t runspd; @@ -8566,8 +8546,7 @@ void P_MovePlayer(player_t *player) water->flags2 |= MF2_OBJECTFLIP; water->eflags |= MFE_VERTICALFLIP; } - water->destscale = player->mo->scale; - P_SetScale(water, player->mo->scale); + P_SetScale(water, player->mo->scale, true); } } @@ -8696,10 +8675,13 @@ void P_MovePlayer(player_t *player) && !(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) P_ElementalFire(player, false); + if ((cmd->buttons & (BT_SPIN|BT_SHIELD)) == (BT_SPIN|BT_SHIELD) && !(player->pflags & (PF_SPINDOWN|PF_SHIELDDOWN))) + spinshieldhack = true; // Spin and Shield is bound to the same button (pressed on the same tic), so enable two-button play (Jump and Spin+Shield) + P_DoSpinAbility(player, cmd); // jumping - P_DoJumpStuff(player, cmd); + P_DoJumpStuff(player, cmd, spinshieldhack); // If you're not spinning, you'd better not be spindashing! if (!(player->pflags & PF_SPINNING) && player->powers[pw_carry] != CR_NIGHTSMODE) @@ -8777,30 +8759,32 @@ void P_MovePlayer(player_t *player) if (!(player->mo->momz || player->mo->momx || player->mo->momy) && !(player->mo->eflags & MFE_GOOWATER) && player->panim == PA_IDLE && !(player->powers[pw_carry])) P_DoTeeter(player); + + // Toss a flag + if (G_GametypeHasTeams() && (cmd->buttons & BT_TOSSFLAG) && !(player->powers[pw_super]) && !(player->tossdelay)) + { + if (!(player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + P_PlayerEmeraldBurst(player, true); // Toss emeralds + else + P_PlayerFlagBurst(player, true); + } // Check for fire and shield buttons - if (!player->exiting && !(player->pflags & PF_STASIS)) + if (!player->exiting) { - // Check for fire buttons P_DoFiring(player, cmd); - - // Release the shield button - if (!(cmd->buttons & BT_SHIELD)) - player->pflags &= ~PF_SHIELDDOWN; - + // Shield button behavior // Check P_PlayerShieldThink for actual shields! - else if (!(player->pflags & PF_SHIELDDOWN)) + if ((cmd->buttons & BT_SHIELD) && !(player->pflags & PF_SHIELDDOWN) && !spinshieldhack) { // Transform into super if we can! if (P_SuperReady(player, true)) P_DoSuperTransformation(player, false); - + // Detransform from super if we can! else if (P_SuperReady(player, false)) P_DoSuperDetransformation(player); - - player->pflags |= PF_SHIELDDOWN; } } @@ -11000,8 +10984,7 @@ static void P_SpawnSparks(mobj_t *mo, angle_t maindir) spark->momz = mo->momz + r3; P_Thrust(spark, R_PointToAngle2(mo->x, mo->y, spark->x, spark->y), 8*FRACUNIT); - P_SetScale(spark, FRACUNIT/4); - spark->destscale = spark->scale; + P_SetScale(spark, FRACUNIT/4, true); spark->fuse = TICRATE/3; } @@ -11308,7 +11291,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) fixed_t backwards = -1*FRACUNIT; boolean doswim = (player->panim == PA_ABILITY && (player->mo->eflags & MFE_UNDERWATER)); boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || doswim); - angle_t rollangle; + angle_t rollangle = 0; boolean panimchange; INT32 ticnum = 0; statenum_t chosenstate; @@ -11473,8 +11456,9 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) tails->threshold = player->mo->z; tails->movecount = player->panim; tails->angle = horizangle; - P_SetScale(tails, player->mo->scale); + P_SetScale(tails, player->mo->scale, false); tails->destscale = player->mo->destscale; + tails->old_scale = player->mo->old_scale; tails->radius = player->mo->radius; tails->height = player->mo->height; zoffs = FixedMul(zoffs, tails->scale); @@ -11565,7 +11549,9 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) y = mo->y + radiusY + FixedMul(offsetH, factorY); z = mo->z + heightoffset + offsetV; bubble = P_SpawnMobj(x, y, z, MT_SMALLBUBBLE); - bubble->scale = mo->scale >> 1; + P_SetScale(bubble, mo->scale/2, true); + bubble->destscale = mo->scale; + bubble->scalespeed = FixedMul(bubble->scalespeed, mo->scale); P_SetTarget(&bubble->dontdrawforviewmobj, mo); // Hide the bubble in first-person } @@ -11586,7 +11572,7 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (stat == fume->info->spawnstate) // If currently inivisble, activate! { P_SetMobjState(fume, (stat = fume->info->seestate)); - P_SetScale(fume, mo->scale); + P_SetScale(fume, mo->scale, false); resetinterp = true; } @@ -11601,7 +11587,7 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (dashmode == DASHMODE_THRESHOLD && dashmode > (tic_t)fume->movecount) // If just about to enter dashmode, play the startup animation again { P_SetMobjState(fume, (stat = fume->info->seestate)); - P_SetScale(fume, mo->scale << 1); + P_SetScale(fume, 2*mo->scale, true); } fume->flags2 = (fume->flags2 & ~MF2_DONTDRAW) | (mo->flags2 & MF2_DONTDRAW); fume->destscale = (mo->scale + FixedDiv(player->speed, player->normalspeed)) / (underwater ? 6 : 3); @@ -12055,7 +12041,7 @@ void P_PlayerThink(player_t *player) ticmiss++; P_DoRopeHang(player); - P_DoJumpStuff(player, &player->cmd); + P_DoJumpStuff(player, &player->cmd, false); // P_DoRopeHang would set PF_SPINDOWN, so no spinshieldhack here } else //if (player->powers[pw_carry] == CR_ZOOMTUBE) { @@ -12090,7 +12076,7 @@ void P_PlayerThink(player_t *player) // deez New User eXperiences. { angle_t oldang = player->drawangle, diff = 0; - UINT8 factor; + UINT8 factor = 0; // Directionchar! // Camera angle stuff. if (player->exiting // no control, no modification @@ -12325,6 +12311,12 @@ void P_PlayerThink(player_t *player) player->pflags &= ~PF_SPINDOWN; } + // Check for Shield button + if (cmd->buttons & BT_SHIELD) + player->pflags |= PF_SHIELDDOWN; + else + player->pflags &= ~PF_SHIELDDOWN; + // IF PLAYER NOT HERE THEN FLASH END IF if (player->quittime && player->powers[pw_flashing] < flashingtics - 1 && !(G_TagGametype() && !(player->pflags & PF_TAGIT)) && !player->gotflag) diff --git a/src/r_bsp.c b/src/r_bsp.c index 918dc40b0..d606d7a27 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1382,10 +1382,9 @@ void R_RenderPortalHorizonLine(sector_t *sector) || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum)) { - ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, - ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingxscale, frontsector->ceilingyscale, - frontsector->ceilingyoffset, frontsector->ceilingangle, - ceilingcolormap, NULL, NULL, NULL, NULL); + ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, + frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingxscale, frontsector->ceilingyscale, + frontsector->ceilingangle, ceilingcolormap, NULL, NULL, NULL, NULL); } else ceilingplane = NULL; diff --git a/src/r_defs.h b/src/r_defs.h index 369fd5fbf..7e92c9249 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -751,9 +751,6 @@ typedef struct seg_s lightmap_t *lightmaps; // for static lightmap #endif - // Why slow things down by calculating lightlists for every thick side? - size_t numlights; - r_lightlist_t *rlights; polyobj_t *polyseg; boolean dontrenderme; boolean glseg; @@ -837,6 +834,7 @@ typedef struct drawseg_s INT16 *sprtopclip; INT16 *sprbottomclip; fixed_t *maskedtexturecol; + fixed_t *maskedtextureheight; // For handling sloped midtextures fixed_t *invscale; struct visplane_s *ffloorplanes[MAXFFLOORS]; @@ -848,8 +846,6 @@ typedef struct drawseg_s UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping - fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures - vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes } drawseg_t; diff --git a/src/r_fps.c b/src/r_fps.c index 83fd0eec1..0773f228d 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -817,6 +817,10 @@ void R_ResetMobjInterpolationState(mobj_t *mobj) mobj->old_roll2 = mobj->old_roll; mobj->old_spriteroll2 = mobj->old_spriteroll; mobj->old_scale2 = mobj->old_scale; + mobj->old_spritexscale2 = mobj->old_spritexscale; + mobj->old_spriteyscale2 = mobj->old_spriteyscale; + mobj->old_spritexoffset2 = mobj->old_spritexoffset; + mobj->old_spriteyoffset2 = mobj->old_spriteyoffset; mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; @@ -853,6 +857,10 @@ void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj) mobj->old_pitch2 = mobj->old_pitch; mobj->old_roll2 = mobj->old_roll; mobj->old_spriteroll2 = mobj->old_spriteroll; + mobj->old_spritexscale2 = mobj->old_spritexscale; + mobj->old_spriteyscale2 = mobj->old_spriteyscale; + mobj->old_spritexoffset2 = mobj->old_spritexoffset; + mobj->old_spriteyoffset2 = mobj->old_spriteyoffset; mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; diff --git a/src/r_main.c b/src/r_main.c index 08cb4eb6a..462439294 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -66,6 +66,10 @@ sector_t *viewsector; player_t *viewplayer; mobj_t *r_viewmobj; +boolean r_renderwalls; +boolean r_renderfloors; +boolean r_renderthings; + fixed_t rendertimefrac; fixed_t renderdeltatics; boolean renderisnewtic; @@ -149,8 +153,6 @@ consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_ffloorclip = CVAR_INIT ("r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_spriteclip = CVAR_INIT ("r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL|CV_ALLOWLUA, CV_YesNo, R_SetViewSize); consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL); @@ -161,12 +163,17 @@ consvar_t cv_drawdist_nights = CVAR_INIT ("drawdist_nights", "2048", CV_SAVE, dr consvar_t cv_drawdist_precip = CVAR_INIT ("drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL); consvar_t cv_fov = CVAR_INIT ("fov", "90", CV_SAVE|CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange); consvar_t cv_fovchange = CVAR_INIT ("fovchange", "Off", CV_SAVE, CV_OnOff, NULL); - -// Okay, whoever said homremoval causes a performance hit should be shot. -consvar_t cv_homremoval = CVAR_INIT ("homremoval", "No", CV_SAVE, homremoval_cons_t, NULL); - consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL); +consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); +consvar_t cv_renderwalls = CVAR_INIT ("r_renderwalls", "On", 0, CV_OnOff, NULL); +consvar_t cv_renderfloors = CVAR_INIT ("r_renderfloors", "On", 0, CV_OnOff, NULL); +consvar_t cv_renderthings = CVAR_INIT ("r_renderthings", "On", 0, CV_OnOff, NULL); +consvar_t cv_ffloorclip = CVAR_INIT ("r_ffloorclip", "On", 0, CV_OnOff, NULL); +consvar_t cv_spriteclip = CVAR_INIT ("r_spriteclip", "On", 0, CV_OnOff, NULL); + +consvar_t cv_homremoval = CVAR_INIT ("homremoval", "No", CV_SAVE, homremoval_cons_t, NULL); + consvar_t cv_renderstats = CVAR_INIT ("renderstats", "Off", 0, CV_OnOff, NULL); void SplitScreen_OnChange(void) @@ -383,33 +390,26 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y) return R_PointToDist2(viewx, viewy, x, y); } -// -// R_ScaleFromGlobalAngle -// Returns the texture mapping scale for the current line (horizontal span) -// at the given angle. -// rw_distance must be calculated first. -// -// killough 5/2/98: reformatted, cleaned up -// -// note: THIS IS USED ONLY FOR WALLS! -fixed_t R_ScaleFromGlobalAngle(angle_t visangle) +line_t *R_GetFFloorLine(const seg_t *seg, const ffloor_t *pfloor) { - angle_t anglea = ANGLE_90 + (visangle-viewangle); - angle_t angleb = ANGLE_90 + (visangle-rw_normalangle); - fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT)); - // proff 11/06/98: Changed for high-res - fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT)); - - if (den > num>>16) + if (pfloor->master->flags & ML_TFERLINE) { - num = FixedDiv(num, den); - if (num > 64*FRACUNIT) - return 64*FRACUNIT; - if (num < 256) - return 256; - return num; + size_t linenum = seg->linedef - pfloor->target->lines[0]; + return pfloor->master->frontsector->lines[0] + linenum; } - return 64*FRACUNIT; + else + return pfloor->master; +} + +side_t *R_GetFFloorSide(const seg_t *seg, const ffloor_t *pfloor) +{ + if (pfloor->master->flags & ML_TFERLINE) + { + line_t *newline = R_GetFFloorLine(seg, pfloor); + return &sides[newline->sidenum[0]]; + } + else + return &sides[pfloor->master->sidenum[0]]; } // @@ -1620,17 +1620,11 @@ void R_RenderPlayerView(player_t *player) void R_RegisterEngineStuff(void) { - CV_RegisterVar(&cv_gravity); - CV_RegisterVar(&cv_tailspickup); - CV_RegisterVar(&cv_allowmlook); - CV_RegisterVar(&cv_homremoval); - CV_RegisterVar(&cv_flipcam); - CV_RegisterVar(&cv_flipcam2); - - // Enough for dedicated server + // Do nothing for dedicated server if (dedicated) return; + CV_RegisterVar(&cv_homremoval); CV_RegisterVar(&cv_translucency); CV_RegisterVar(&cv_drawdist); CV_RegisterVar(&cv_drawdist_nights); @@ -1643,6 +1637,13 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_shadow); CV_RegisterVar(&cv_skybox); + CV_RegisterVar(&cv_renderview); + CV_RegisterVar(&cv_renderhitboxinterpolation); + CV_RegisterVar(&cv_renderhitboxgldepth); + CV_RegisterVar(&cv_renderhitbox); + CV_RegisterVar(&cv_renderwalls); + CV_RegisterVar(&cv_renderfloors); + CV_RegisterVar(&cv_renderthings); CV_RegisterVar(&cv_ffloorclip); CV_RegisterVar(&cv_spriteclip); @@ -1681,8 +1682,6 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_maxportals); - CV_RegisterVar(&cv_movebob); - // Frame interpolation/uncapped CV_RegisterVar(&cv_fpscap); } diff --git a/src/r_main.h b/src/r_main.h index 3f8c55746..aedfeb6ad 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -80,13 +80,15 @@ angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); fixed_t R_PointToDist(fixed_t x, fixed_t y); fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); -fixed_t R_ScaleFromGlobalAngle(angle_t visangle); boolean R_IsPointInSector(sector_t *sector, fixed_t x, fixed_t y); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); +line_t *R_GetFFloorLine(const seg_t *seg, const ffloor_t *pfloor); +side_t *R_GetFFloorSide(const seg_t *seg, const ffloor_t *pfloor); + // Render stats extern precise_t ps_prevframetime;// time when previous frame was rendered @@ -117,12 +119,18 @@ extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_shadow; -extern consvar_t cv_ffloorclip, cv_spriteclip; extern consvar_t cv_translucency; extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_fov, cv_fovchange; extern consvar_t cv_skybox; -extern consvar_t cv_tailspickup; +extern consvar_t cv_renderview; +extern consvar_t cv_renderhitbox, cv_renderhitboxinterpolation, cv_renderhitboxgldepth; +extern consvar_t cv_renderwalls, cv_renderfloors, cv_renderthings; +extern consvar_t cv_ffloorclip, cv_spriteclip; + +extern boolean r_renderwalls; +extern boolean r_renderfloors; +extern boolean r_renderthings; // Called by startup code. void R_Init(void); diff --git a/src/r_plane.c b/src/r_plane.c index 87b8a8856..33e3aac13 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -603,6 +603,9 @@ void R_DrawPlanes(void) visplane_t *pl; INT32 i; + if (!r_renderfloors) + return; + R_UpdatePlaneRipple(); for (i = 0; i < MAXVISPLANES; i++, pl++) @@ -881,9 +884,6 @@ void R_DrawSinglePlane(visplane_t *pl) if (!(pl->minx <= pl->maxx)) return; - if (!cv_renderfloors.value) - return; - // sky flat if (pl->picnum == skyflatnum) { diff --git a/src/r_segs.c b/src/r_segs.c index 56a62f10c..e07ced86a 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -16,7 +16,6 @@ #include "r_sky.h" #include "r_portal.h" -#include "r_splats.h" #include "w_wad.h" #include "z_zone.h" @@ -75,6 +74,8 @@ static fixed_t *maskedtextureheight = NULL; static fixed_t *thicksidecol = NULL; static fixed_t *invscale = NULL; +static boolean texcoltables; + //SoM: 3/23/2000: Use boom opening limit removal static size_t numopenings; static INT16 *openings, *lastopening; @@ -88,10 +89,6 @@ void R_ClearSegTables(void) curtexturecolumntable = texturecolumntable; } -// ========================================================================== -// R_RenderMaskedSegRange -// ========================================================================== - transnum_t R_GetLinedefTransTable(fixed_t alpha) { return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); @@ -111,10 +108,12 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) INT32 times, repeats; INT64 overflow_test; INT32 range; + UINT8 vertflip; unsigned lengthcol; - if (!cv_renderwalls.value) - return; + fixed_t wall_scaley; + fixed_t scalestep; + fixed_t scale1; // Calculate light table. // Use different light tables @@ -163,9 +162,17 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) colfunc = colfuncs[COLDRAWFUNC_FUZZY]; } - fixed_t wall_scaley = sidedef->scaley_mid; - fixed_t scalestep = FixedDiv(ds->scalestep, wall_scaley); - fixed_t scale1 = FixedDiv(ds->scale1, wall_scaley); + vertflip = textures[texnum]->flip & 2; + + wall_scaley = sidedef->scaley_mid; + if (wall_scaley < 0) + { + wall_scaley = -wall_scaley; + vertflip = !vertflip; + } + + scalestep = FixedDiv(ds->scalestep, wall_scaley); + scale1 = FixedDiv(ds->scale1, wall_scaley); range = max(ds->x2-ds->x1, 1); rw_scalestep = scalestep; @@ -174,7 +181,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Texture must be cached R_CheckTextureCache(texnum); - if (textures[texnum]->flip & 2) // vertically flipped? + if (vertflip) // vertically flipped? colfunc_2s = R_DrawFlippedMaskedColumn; else colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture @@ -470,6 +477,11 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) return false; } +static fixed_t R_GetSlopeTextureSlide(pslope_t *slope, angle_t lineangle) +{ + return FixedMul(slope->zdelta, FINECOSINE((lineangle-slope->xydirection)>>ANGLETOFINESHIFT)); +} + // // R_RenderThickSideRange // Renders all the thick sides in the given range. @@ -494,19 +506,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) INT64 top_frac, top_step, bottom_frac, bottom_step; // skew FOF walls with slopes? fixed_t ffloortextureslide = 0; - INT32 oldx = -1; + fixed_t oldtexturecolumn = -1; fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; boolean do_texture_skew; boolean dont_peg_bottom; + fixed_t wall_offsetx; fixed_t wall_scalex, wall_scaley; + UINT8 vertflip; unsigned lengthcol; void (*colfunc_2s) (column_t *, unsigned); - if (!cv_renderwalls.value) - return; - // Calculate light table. // Use different light tables // for horizontal / vertical / diagonal. Diagonal? @@ -515,15 +526,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) curline = ds->curline; backsector = pfloor->target; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; - sidedef = &sides[pfloor->master->sidenum[0]]; + sidedef = R_GetFFloorSide(curline, pfloor); colfunc = colfuncs[BASEDRAWFUNC]; if (pfloor->master->flags & ML_TFERLINE) { - size_t linenum = curline->linedef-backsector->lines[0]; - line_t *newline = pfloor->master->frontsector->lines[0] + linenum; - sidedef = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(curline, pfloor); do_texture_skew = newline->flags & ML_SKEWTD; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; } @@ -534,6 +543,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } texnum = R_GetTextureNum(sidedef->midtexture); + vertflip = textures[texnum]->flip & 2; if (pfloor->fofflags & FOF_TRANSLUCENT) { @@ -687,18 +697,25 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) wall_scalex = FixedDiv(FRACUNIT, sidedef->scalex_mid); wall_scaley = sidedef->scaley_mid; + if (wall_scaley < 0) + { + wall_scaley = -wall_scaley; + vertflip = !vertflip; + } thicksidecol = ffloortexturecolumn; + wall_offsetx = ds->offsetx + sidedef->offsetx_mid; + if (wall_scalex == FRACUNIT) { for (INT32 x = x1; x <= x2; x++) - thicksidecol[x] = ds->thicksidecol[x] + ds->offsetx; + thicksidecol[x] = ds->thicksidecol[x]; } else { for (INT32 x = x1; x <= x2; x++) - thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex) + ds->offsetx; + thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex); } mfloorclip = ds->sprbottomclip; @@ -733,7 +750,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (skewslope) { angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); - ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); + ffloortextureslide = FixedMul(R_GetSlopeTextureSlide(skewslope, lineangle), wall_scaley); } dc_texturemid += offsetvalue; @@ -741,7 +758,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Texture must be cached R_CheckTextureCache(texnum); - if (textures[texnum]->flip & 2) // vertically flipped? + if (vertflip) // vertically flipped? colfunc_2s = R_DrawRepeatFlippedMaskedColumn; else colfunc_2s = R_DrawRepeatMaskedColumn; @@ -775,9 +792,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // skew FOF walls if (ffloortextureslide) { - if (oldx != -1) - dc_texturemid += FixedMul(ffloortextureslide, thicksidecol[oldx]-thicksidecol[dc_x]); - oldx = dc_x; + if (oldtexturecolumn != -1) + dc_texturemid += FixedMul(ffloortextureslide, oldtexturecolumn-ds->thicksidecol[dc_x]); + oldtexturecolumn = ds->thicksidecol[dc_x]; } // Calculate bounds @@ -814,7 +831,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_iscale = FixedMul(0xffffffffu / (unsigned)spryscale, wall_scaley); // Get data for the column - col = R_GetColumn(texnum, (thicksidecol[dc_x] >> FRACBITS)); + col = R_GetColumn(texnum, ((thicksidecol[dc_x] + wall_offsetx) >> FRACBITS)); // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. @@ -988,36 +1005,77 @@ static boolean R_FFloorCanClip(visffloor_t *pfloor) #define HEIGHTBITS 12 #define HEIGHTUNIT (1<= 0 && yl < viewheight) { - if (cv_renderwalls.value) - { - fixed_t offset = texturecolumn + rw_offsetx; + fixed_t offset = texturecolumn + rw_offsetx; - dc_yl = yl; - dc_yh = yh; - dc_texturemid = rw_midtexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_midtexturescaley); - dc_source = R_GetColumn(midtexture, offset >> FRACBITS)->pixels; - dc_texheight = textureheight[midtexture]>>FRACBITS; - - //profile stuff --------------------------------------------------------- -#ifdef TIMING - ProfZeroTimer(); -#endif - colfunc(); -#ifdef TIMING - RDMSR(0x10,&mycount); - mytotal += mycount; //64bit add - - if (nombre--==0) - I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1), - (INT32)mytotal); -#endif - //profile stuff --------------------------------------------------------- - } + dc_yl = yl; + dc_yh = yh; + dc_texturemid = rw_midtexturemid; + dc_texheight = textureheight[midtexture]>>FRACBITS; + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, midscaley); + drawmiddle(R_GetColumn(midtexture, offset >> FRACBITS)->pixels, dc_texheight); // dont draw anything more for this column, since // a midtexture blocks the view @@ -1321,21 +1361,17 @@ static void R_RenderSegLoop (void) } else if (mid >= 0) // safe to draw top texture { - if (cv_renderwalls.value) - { - fixed_t offset = rw_offset_top; - if (rw_toptexturescalex < 0) - offset = -offset; - offset = toptexturecolumn + offset; + fixed_t offset = rw_offset_top; + if (rw_toptexturescalex < 0) + offset = -offset; + offset = toptexturecolumn + offset; - dc_yl = yl; - dc_yh = mid; - dc_texturemid = rw_toptexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_toptexturescaley); - dc_source = R_GetColumn(toptexture, offset >> FRACBITS)->pixels; - dc_texheight = textureheight[toptexture]>>FRACBITS; - colfunc(); - } + dc_yl = yl; + dc_yh = mid; + dc_texturemid = rw_toptexturemid; + dc_texheight = textureheight[toptexture]>>FRACBITS; + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, topscaley); + drawtop(R_GetColumn(toptexture, offset >> FRACBITS)->pixels, dc_texheight); ceilingclip[rw_x] = (INT16)mid; } else if (!rw_ceilingmarked) // entirely off top of screen @@ -1345,8 +1381,8 @@ static void R_RenderSegLoop (void) ceilingclip[rw_x] = topclip; if (oldtexturecolumn_top != -1) - rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn_top-toptexturecolumn); - oldtexturecolumn_top = toptexturecolumn; + rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn_top-textureoffset); + oldtexturecolumn_top = textureoffset; } else if (markceiling && (!rw_ceilingmarked)) // no top wall ceilingclip[rw_x] = topclip; @@ -1372,21 +1408,17 @@ static void R_RenderSegLoop (void) } else if (mid < viewheight) // safe to draw bottom texture { - if (cv_renderwalls.value) - { - fixed_t offset = rw_offset_bottom; - if (rw_bottomtexturescalex < 0) - offset = -offset; - offset = bottomtexturecolumn + offset; + fixed_t offset = rw_offset_bottom; + if (rw_bottomtexturescalex < 0) + offset = -offset; + offset = bottomtexturecolumn + offset; - dc_yl = mid; - dc_yh = yh; - dc_texturemid = rw_bottomtexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_bottomtexturescaley); - dc_source = R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels; - dc_texheight = textureheight[bottomtexture]>>FRACBITS; - colfunc(); - } + dc_yl = mid; + dc_yh = yh; + dc_texturemid = rw_bottomtexturemid; + dc_texheight = textureheight[bottomtexture]>>FRACBITS; + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, bottomscaley); + drawbottom(R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels, dc_texheight); floorclip[rw_x] = (INT16)mid; } else if (!rw_floormarked) // entirely off bottom of screen @@ -1396,8 +1428,8 @@ static void R_RenderSegLoop (void) floorclip[rw_x] = bottomclip; if (oldtexturecolumn_bottom != -1) - rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn_bottom-bottomtexturecolumn); - oldtexturecolumn_bottom = bottomtexturecolumn; + rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn_bottom-textureoffset); + oldtexturecolumn_bottom = textureoffset; } else if (markfloor && (!rw_floormarked)) // no bottom wall floorclip[rw_x] = bottomclip; @@ -1421,11 +1453,14 @@ static void R_RenderSegLoop (void) { if (oldtexturecolumn != -1) { - rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); - rw_midtextureback += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn); + INT32 diff = oldtexturecolumn-textureoffset; + if (rw_invmidtexturescalex < 0) + diff = -diff; + rw_midtexturemid += FixedMul(rw_midtextureslide, diff); + rw_midtextureback += FixedMul(rw_midtexturebackslide, diff); } - oldtexturecolumn = texturecolumn; + oldtexturecolumn = textureoffset; } if (invscale) @@ -1519,7 +1554,7 @@ static void R_AllocClippingTables(size_t range) static void R_AllocTextureColumnTables(size_t range) { size_t pos = curtexturecolumntable - texturecolumntable; - size_t need = range * 3; + size_t need = range * 4; if (pos + need < texturecolumntablesize) return; @@ -1540,15 +1575,48 @@ static void R_AllocTextureColumnTables(size_t range) for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) { // Check if it's in range of the tables - if (ds->maskedtexturecol + ds->x1 >= oldtable && ds->maskedtexturecol + ds->x1 <= oldlast) - ds->maskedtexturecol = (ds->maskedtexturecol - oldtable) + texturecolumntable; - if (ds->thicksidecol + ds->x1 >= oldtable && ds->thicksidecol + ds->x1 <= oldlast) - ds->thicksidecol = (ds->thicksidecol - oldtable) + texturecolumntable; - if (ds->invscale + ds->x1 >= oldtable && ds->invscale + ds->x1 <= oldlast) - ds->invscale = (ds->invscale - oldtable) + texturecolumntable; +#define CHECK(which) \ + if (which + ds->x1 >= oldtable && which + ds->x1 <= oldlast) \ + which = (which - oldtable) + texturecolumntable + + CHECK(ds->maskedtexturecol); + CHECK(ds->maskedtextureheight); + CHECK(ds->thicksidecol); + CHECK(ds->invscale); + +#undef CHECK } } +// +// R_ScaleFromGlobalAngle +// Returns the texture mapping scale for the current line (horizontal span) +// at the given angle. +// rw_distance must be calculated first. +// +// killough 5/2/98: reformatted, cleaned up +// +// note: THIS IS USED ONLY FOR WALLS! +static fixed_t R_ScaleFromGlobalAngle(angle_t visangle) +{ + angle_t anglea = ANGLE_90 + (visangle-viewangle); + angle_t angleb = ANGLE_90 + (visangle-rw_normalangle); + fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT)); + // proff 11/06/98: Changed for high-res + fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT)); + + if (den > num>>16) + { + num = FixedDiv(num, den); + if (num > 64*FRACUNIT) + return 64*FRACUNIT; + if (num < 256) + return 256; + return num; + } + return 64*FRACUNIT; +} + // // R_StoreWallRange // A wall segment will be drawn @@ -1720,11 +1788,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) midtexture = toptexture = bottomtexture = maskedtexture = 0; ds_p->maskedtexturecol = NULL; + ds_p->maskedtextureheight = NULL; ds_p->numthicksides = numthicksides = 0; ds_p->thicksidecol = NULL; ds_p->invscale = NULL; ds_p->tsilheight = 0; + texcoltables = false; + numbackffloors = 0; for (i = 0; i < MAXFFLOORS; i++) @@ -1750,16 +1821,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); if (frontsector->f_slope) - floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + floorfrontslide = R_GetSlopeTextureSlide(frontsector->f_slope, lineangle); if (frontsector->c_slope) - ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + ceilingfrontslide = R_GetSlopeTextureSlide(frontsector->c_slope, lineangle); - if (backsector && backsector->f_slope) - floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + if (backsector) + { + if (backsector->f_slope) + floorbackslide = R_GetSlopeTextureSlide(backsector->f_slope, lineangle); - if (backsector && backsector->c_slope) - ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + if (backsector->c_slope) + ceilingbackslide = R_GetSlopeTextureSlide(backsector->c_slope, lineangle); + } } rw_midtexturescalex = sidedef->scalex_mid; @@ -1775,26 +1849,27 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t rowoffset = sidedef->rowoffset + sidedef->offsety_mid; fixed_t texheight = textureheight[midtexture]; + fixed_t scaley = abs(rw_midtexturescaley); if (rw_midtexturescaley > 0) { if (linedef->flags & ML_NOSKEW) { if (linedef->flags & ML_DONTPEGBOTTOM) - rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, rw_midtexturescaley) + texheight; + rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, scaley) + texheight; else - rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, rw_midtexturescaley); + rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, scaley); } else if (linedef->flags & ML_DONTPEGBOTTOM) { - rw_midtexturemid = FixedMul(worldbottom, rw_midtexturescaley) + texheight; - rw_midtextureslide = floorfrontslide; + rw_midtexturemid = FixedMul(worldbottom, scaley) + texheight; + rw_midtextureslide = FixedMul(floorfrontslide, scaley); } else { // top of texture at top - rw_midtexturemid = FixedMul(worldtop, rw_midtexturescaley); - rw_midtextureslide = ceilingfrontslide; + rw_midtexturemid = FixedMul(worldtop, scaley); + rw_midtextureslide = FixedMul(ceilingfrontslide, scaley); } } else @@ -1805,20 +1880,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (linedef->flags & ML_NOSKEW) { if (linedef->flags & ML_DONTPEGBOTTOM) - rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, rw_midtexturescaley); + rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, scaley); else - rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, rw_midtexturescaley) + texheight; + rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, scaley) + texheight; } else if (linedef->flags & ML_DONTPEGBOTTOM) { - rw_midtexturemid = FixedMul(worldbottom, rw_midtexturescaley); - rw_midtextureslide = floorfrontslide; + rw_midtexturemid = FixedMul(worldbottom, scaley); + rw_midtextureslide = FixedMul(floorfrontslide, scaley); } else { // top of texture at top - rw_midtexturemid = FixedMul(worldtop, rw_midtexturescaley) + texheight; - rw_midtextureslide = ceilingfrontslide; + rw_midtexturemid = FixedMul(worldtop, scaley) + texheight; + rw_midtextureslide = FixedMul(ceilingfrontslide, scaley); } } @@ -2027,15 +2102,16 @@ void R_StoreWallRange(INT32 start, INT32 stop) { // top of texture at top rw_toptexturemid = worldtop; - rw_toptextureslide = ceilingfrontslide; + rw_toptextureslide = FixedMul(ceilingfrontslide, abs(rw_toptexturescaley)); } else { rw_toptexturemid = worldhigh + texheight; - rw_toptextureslide = ceilingbackslide; + rw_toptextureslide = FixedMul(ceilingbackslide, abs(rw_toptexturescaley)); } - rw_toptexturemid = FixedMul(rw_toptexturemid, rw_toptexturescaley); + rw_toptexturemid = FixedMul(rw_toptexturemid, abs(rw_toptexturescaley)); + rw_toptexturemid += toprowoffset; } // check BOTTOM TEXTURE @@ -2066,24 +2142,24 @@ void R_StoreWallRange(INT32 start, INT32 stop) // bottom of texture at bottom // top of texture at top rw_bottomtexturemid = worldbottom; - rw_bottomtextureslide = floorfrontslide; + rw_bottomtextureslide = FixedMul(floorfrontslide, abs(rw_bottomtexturescaley)); } else { // top of texture at top rw_bottomtexturemid = worldlow; - rw_bottomtextureslide = floorbackslide; + rw_bottomtextureslide = FixedMul(floorbackslide, abs(rw_bottomtexturescaley)); } - rw_bottomtexturemid = FixedMul(rw_bottomtexturemid, rw_bottomtexturescaley); + rw_bottomtexturemid = FixedMul(rw_bottomtexturemid, abs(rw_bottomtexturescaley)); + rw_bottomtexturemid += botrowoffset; } - rw_toptexturemid += toprowoffset; - rw_bottomtexturemid += botrowoffset; - // allocate space for masked texture tables R_AllocTextureColumnTables(rw_stopx - start); + texcoltables = true; + if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) { ffloor_t *rover; @@ -2282,7 +2358,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x; curtexturecolumntable += rw_stopx - rw_x; - maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0]) + ds_p->maskedtextureheight = maskedtextureheight = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; maskedtexture = true; @@ -2324,13 +2401,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } - rw_midtexturemid = FixedMul(rw_midtexturemid, rw_midtexturescaley); - rw_midtextureback = FixedMul(rw_midtextureback, rw_midtexturescaley); + rw_midtexturemid = FixedMul(rw_midtexturemid, abs(rw_midtexturescaley)); + rw_midtextureback = FixedMul(rw_midtextureback, abs(rw_midtexturescaley)); + + rw_midtextureslide = FixedMul(rw_midtextureslide, abs(rw_midtexturescaley)); + rw_midtexturebackslide = FixedMul(rw_midtexturebackslide, abs(rw_midtexturescaley)); rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid; rw_midtextureback += sidedef->rowoffset + sidedef->offsety_mid; - - maskedtexture = true; } } diff --git a/src/r_skins.c b/src/r_skins.c index 6b4aeefe1..2029b4eff 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -376,7 +376,7 @@ static void SetSkin(player_t *player, INT32 skinnum) player->mo->skin = skin; if (newcolor) player->mo->color = newcolor; - P_SetScale(player->mo, player->mo->scale); + P_SetScale(player->mo, player->mo->scale, false); player->mo->radius = radius; P_SetMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames diff --git a/src/r_things.c b/src/r_things.c index 57078b4a6..642269909 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -658,12 +658,31 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol) static UINT8 *flippedcol = NULL; static size_t flippedcolsize = 0; +void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void)) +{ + if (!length) + return; + + if (!flippedcolsize || length > flippedcolsize) + { + flippedcolsize = length; + flippedcol = Z_Realloc(flippedcol, length, PU_STATIC, NULL); + } + + dc_source = flippedcol; + + for (UINT8 *s = (UINT8 *)source, *d = flippedcol+length-1; d >= flippedcol; s++) + *d-- = *s; + + drawcolfunc(); +} + void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) { INT32 topscreen; INT32 bottomscreen; fixed_t basetexturemid = dc_texturemid; - UINT8 *d,*s; + INT32 topdelta; for (unsigned i = 0; i < column->num_posts; i++) { @@ -671,7 +690,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) if (!post->length) continue; - INT32 topdelta = lengthcol-post->length-post->topdelta; + topdelta = lengthcol-post->length-post->topdelta; topscreen = sprtopscreen + spryscale*topdelta; bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*post->length : sprbotscreen + spryscale*post->length; @@ -698,18 +717,9 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) if (dc_yl <= dc_yh && dc_yh > 0) { - if (post->length > flippedcolsize) - { - flippedcolsize = post->length; - flippedcol = Z_Realloc(flippedcol, flippedcolsize, PU_STATIC, NULL); - } - - for (s = column->pixels+post->data_offset+post->length, d = flippedcol; d < flippedcol+post->length; --s) - *d++ = *s; - dc_source = flippedcol; dc_texturemid = basetexturemid - (topdelta<pixels + post->data_offset, post->length, colfunc); } } @@ -1527,7 +1537,7 @@ static void R_ProjectSprite(mobj_t *thing) // uncapped/interpolation interpmobjstate_t interp = {0}; - if (!cv_renderthings.value) + if (!r_renderthings) return; // do interpolation @@ -2684,7 +2694,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps // Add the 3D floors, thicksides, and masked textures... for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];) { - if (ds->numthicksides) + if (ds->numthicksides && r_renderwalls) { for (i = 0; i < ds->numthicksides; i++) { @@ -2703,17 +2713,19 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps else { // Put it in! entry = R_CreateDrawNode(head); - entry->plane = plane; - entry->seg = ds; + if (r_renderwalls) + entry->seg = ds; + if (r_renderfloors) + entry->plane = plane; } ds->curline->polyseg->visplane = NULL; } - if (ds->maskedtexturecol) + if (ds->maskedtexturecol && r_renderwalls) { entry = R_CreateDrawNode(head); entry->seg = ds; } - if (ds->numffloorplanes) + if (ds->numffloorplanes && r_renderfloors) { for (i = 0; i < ds->numffloorplanes; i++) { @@ -3180,9 +3192,6 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port (lowscale < spr->sortscale && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) { - // masked mid texture? - /*if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, r1, r2);*/ // seg is behind sprite continue; } diff --git a/src/r_things.h b/src/r_things.h index 043b454b0..f68d75a83 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -48,6 +48,7 @@ extern fixed_t windowbottom; void R_DrawMaskedColumn(column_t *column, unsigned lengthcol); void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol); +void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void)); // ---------------- // SPRITE RENDERING diff --git a/src/r_translation.c b/src/r_translation.c index 390545802..a53b30e9f 100644 --- a/src/r_translation.c +++ b/src/r_translation.c @@ -556,7 +556,7 @@ static boolean ParseDecimal(tokenizer_t *sc, double *out) return M_StringToDecimal(tkn, out); } -static struct PaletteRemapParseResult *ThrowError(const char *format, ...) +FUNCPRINTF static struct PaletteRemapParseResult *ThrowError(const char *format, ...) { const size_t err_size = 512 * sizeof(char); @@ -792,7 +792,7 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char return result; } -static void PrintError(const char *name, const char *format, ...) +FUNCDEBUG static void PrintError(const char *name, const char *format, ...) { char error[256]; diff --git a/src/s_sound.c b/src/s_sound.c index a579292ff..aa049899f 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1910,7 +1910,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi if (!music_stacks) { music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL); - strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), 7); + strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), sizeof(music_stacks->musname)-1); music_stacks->musflags = (status == JT_MASTER ? mflags : (S_CheckQueue() ? queue_flags : mapmusflags)); music_stacks->looping = (status == JT_MASTER ? looping : (S_CheckQueue() ? queue_looping : true)); music_stacks->position = (status == JT_MASTER ? position : (S_CheckQueue() ? queue_position : S_GetMusicPosition())); @@ -2033,7 +2033,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst) if (result) { *entry = *result; - strncpy(entry->musname, result->musname, 7); + memcpy(entry->musname, result->musname, sizeof(entry->musname)); } // no result, just grab mapmusname @@ -2255,7 +2255,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 if (S_MusicDisabled()) return; - strncpy(newmusic, mmusic, 7); + strncpy(newmusic, mmusic, sizeof(newmusic)-1); if (LUA_HookMusicChange(music_name, &hook_param)) return; newmusic[6] = 0; diff --git a/src/s_sound.h b/src/s_sound.h index 288859c8d..d64778fc3 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -238,7 +238,7 @@ UINT32 S_GetMusicPosition(void); typedef struct musicstack_s { - char musname[7]; + char musname[7+1]; UINT16 musflags; boolean looping; UINT32 position; diff --git a/src/screen.c b/src/screen.c index c1970d0e8..9a82a1561 100644 --- a/src/screen.c +++ b/src/screen.c @@ -44,6 +44,8 @@ // SRB2Kart #include "r_fps.h" // R_GetFramerateCap +#include "lua_hud.h" // LUA_HudEnabled + // -------------------------------------------- // assembly or c drawer routines for 8bpp/16bpp // -------------------------------------------- @@ -70,11 +72,6 @@ consvar_t cv_scr_width_w = CVAR_INIT ("scr_width_w", "640", CV_SAVE, CV_Unsigned consvar_t cv_scr_height_w = CVAR_INIT ("scr_height_w", "400", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL); -consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); -consvar_t cv_renderwalls = CVAR_INIT ("renderwalls", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_renderfloors = CVAR_INIT ("renderfloors", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_renderthings = CVAR_INIT ("renderthings", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL); - CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, #ifdef HWRENDER @@ -494,6 +491,7 @@ void SCR_ClosedCaptions(void) basey -= 8; else if ((modeattacking == ATTACKING_NIGHTS) || (!(maptol & TOL_NIGHTS) + && LUA_HudEnabled(hud_powerups) && ((cv_powerupdisplay.value == 2) // "Always" || (cv_powerupdisplay.value == 1 && !camera.chase)))) // "First-person only" basey -= 16; diff --git a/src/screen.h b/src/screen.h index 5df5d2889..8b952e553 100644 --- a/src/screen.h +++ b/src/screen.h @@ -157,9 +157,7 @@ extern CV_PossibleValue_t cv_renderer_t[]; extern INT32 scr_bpp; extern consvar_t cv_scr_width, cv_scr_height, cv_scr_width_w, cv_scr_height_w, cv_scr_depth, cv_fullscreen; -extern consvar_t cv_renderwalls, cv_renderfloors, cv_renderthings; -extern consvar_t cv_renderview, cv_renderer; -extern consvar_t cv_renderhitbox, cv_renderhitboxinterpolation, cv_renderhitboxgldepth; +extern consvar_t cv_renderer; // wait for page flipping to end or not extern consvar_t cv_vidwait; extern consvar_t cv_timescale; diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index bebecd8d0..86ffa7082 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -191,7 +191,8 @@ 4244;4267;4146;4003 HAVE_CURL;%(PreprocessorDefinitions) - ..\libs\curl\include;%(AdditionalIncludeDirectories) + ..\..\libs\curl\include;%(AdditionalIncludeDirectories) + false @@ -204,7 +205,7 @@ libcurl.dll.a;libz32.a;%(AdditionalDependencies) - ..\libs\zlib\win32;..\libs\curl\lib32;%(AdditionalLibraryDirectories) + ..\..\libs\zlib\win32;..\..\libs\curl\lib32;%(AdditionalLibraryDirectories) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 173866e8b..9f0fa0250 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1714,7 +1714,7 @@ const char *I_GetJoyName(INT32 joyindex) { tempname = SDL_JoystickNameForIndex(joyindex); if (tempname) - strncpy(joyname, tempname, 255); + strncpy(joyname, tempname, sizeof(joyname)-1); } return joyname; } @@ -2857,7 +2857,7 @@ size_t I_GetRandomBytes(char *destination, size_t count) { #if defined (__unix__) || defined (UNIXCOMMON) || defined(__APPLE__) FILE *rndsource; - size_t actual_bytes; + size_t actual_bytes = 0; if (!(rndsource = fopen("/dev/urandom", "r"))) if (!(rndsource = fopen("/dev/random", "r"))) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index a5be3a754..8f2ca3408 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -140,15 +140,18 @@ static void Midiplayer_Onchange(void) restart = true; } - if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) + if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) { if (!Mix_SetSoundFonts(cv_midisoundfontpath.string)) // == 0 means error CONS_Alert(CONS_ERROR, "Sound font error: %s", Mix_GetError()); else restart = true; } - +#if SDL_MIXER_VERSION_ATLEAST(2,5,0) + Mix_SetTimidityCfg(cv_miditimiditypath.string); +#else Mix_Timidity_addToPathList(cv_miditimiditypath.string); +#endif if (restart) S_StartEx(true); @@ -159,7 +162,7 @@ static void MidiSoundfontPath_Onchange(void) if (Mix_GetMidiPlayer() != MIDI_Fluidsynth || (I_SongType() != MU_NONE && I_SongType() != MU_MID_EX)) return; - if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) + if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) { char *miditoken; char *source = strdup(cv_midisoundfontpath.string); @@ -286,8 +289,12 @@ void I_StartupSound(void) #ifdef HAVE_MIXERX Mix_SetMidiPlayer(cv_midiplayer.value); Mix_SetSoundFonts(cv_midisoundfontpath.string); +#if SDL_MIXER_VERSION_ATLEAST(2,5,0) + Mix_SetTimidityCfg(cv_miditimiditypath.string); +#else Mix_Timidity_addToPathList(cv_miditimiditypath.string); #endif +#endif #if SDL_MIXER_VERSION_ATLEAST(1,2,11) Mix_Init(MIX_INIT_FLAC|MIX_INIT_MP3|MIX_INIT_OGG|MIX_INIT_MOD); #endif @@ -942,7 +949,12 @@ UINT32 I_GetSongLength(void) else { #ifdef HAVE_MIXERX +#if SDL_MIXER_VERSION_ATLEAST(2,5,0) + double xlength = Mix_MusicDuration(music); +#else double xlength = Mix_GetMusicTotalTime(music); +#endif + if (xlength >= 0) return (UINT32)(xlength*1000); #endif @@ -1198,10 +1210,14 @@ boolean I_LoadSong(char *data, size_t len) #ifdef HAVE_MIXERX if (Mix_GetMidiPlayer() != cv_midiplayer.value) Mix_SetMidiPlayer(cv_midiplayer.value); - if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) + if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) Mix_SetSoundFonts(cv_midisoundfontpath.string); +#if SDL_MIXER_VERSION_ATLEAST(2,5,0) + Mix_SetTimidityCfg(cv_miditimiditypath.string); +#else Mix_Timidity_addToPathList(cv_miditimiditypath.string); // this overwrites previous custom path #endif +#endif #ifdef HAVE_OPENMPT /* diff --git a/src/st_stuff.c b/src/st_stuff.c index 06847988b..083bb5224 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -815,7 +815,7 @@ static inline void ST_drawRings(void) static void ST_drawLivesArea(void) { - INT32 v_colmap = V_YELLOWMAP, livescount; + INT32 v_colmap = V_YELLOWMAP, livescount = -1; boolean notgreyedout = false; if (!stplyr->skincolor) @@ -1171,8 +1171,10 @@ static void ST_drawInput(void) V_DrawFill(x+16+(xoffs), y+(yoffs)-offs, 10, 10, col);\ V_DrawCharacter(x+16+1+(xoffs), y+1+(yoffs)-offs, hudinfo[HUD_INPUT].f|symb, false) - drawbutt( 4,-3, BT_JUMP, 'J'); - drawbutt(15,-3, BT_SPIN, 'S'); + drawbutt( 4,-3, BT_JUMP, 'J' ); + drawbutt(15,-3, BT_SPIN, 'S' ); + drawbutt(26,-3, BT_SHIELD, '\0'); // Instead of a wide 'J' or 'S', we'll draw a thin "SH" for Shield + V_DrawThinString(x+16+26, y+2+(-3)-offs, hudinfo[HUD_LIVES].f, "SH"); V_DrawFill(x+16+4, y+8, 21, 10, hudinfo[HUD_INPUT].f|20); // sundial backing if (stplyr->mo) @@ -2821,14 +2823,14 @@ static void ST_overlayDrawer(void) || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)) { ST_drawFirstPersonHUD(); - if (cv_powerupdisplay.value) + if (cv_powerupdisplay.value && LUA_HudEnabled(hud_powerups)) ST_drawPowerupHUD(); // same as it ever was... } - else if (cv_powerupdisplay.value == 2) + else if (cv_powerupdisplay.value == 2 && LUA_HudEnabled(hud_powerups)) ST_drawPowerupHUD(); // same as it ever was... } - else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2) + else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2 && LUA_HudEnabled(hud_powerups)) ST_drawPowerupHUD(); // same as it ever was... if (!(netgame || multiplayer) || !hu_showscores) diff --git a/src/v_video.c b/src/v_video.c index cb7db487e..355bdf860 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -384,13 +384,14 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue) const char *R_GetPalname(UINT16 num) { - static char palname[9]; - char newpal[9] = "PLAYPAL"; + static char palname[8+1]; + char newpal[9] = "PLAYPAL\0"; if (num > 0 && num <= 10000) snprintf(newpal, 8, "PAL%04u", num-1); - strncpy(palname, newpal, 8); + strncpy(palname, newpal, sizeof(palname)-1); + palname[8] = 0; return palname; } diff --git a/src/y_inter.c b/src/y_inter.c index bb4fa0690..2add8645b 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -579,9 +579,9 @@ void Y_IntermissionDrawer(void) { if (LUA_HudEnabled(hud_intermissiontitletext)) { - const char *ringtext = "\x82" "get 50 rings then"; + const char *ringtext = "\x82" "get 50 rings, then"; const char *tut1text = "\x82" "press " "\x80" "shield"; - const char *tut2text = "\x82" "to " "\x80" "transform"; + const char *tut2text = "\x82" "to transform"; ttheight = 8; V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); ttheight += V_LevelNameHeight(data.spec.passed3) + 2;