diff --git a/.gitignore b/.gitignore index 2b4d9d2fb..268e36329 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ Win32_LIB_ASM_Release /bin /build /build/* +/CMakeUserPresets.json \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 9770cb37d..63d801b73 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.2.11.{branch}-{build} +version: 2.2.13.{branch}-{build} os: MinGW environment: diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index dd5cdb46b..41ad99889 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -4367,7 +4367,6 @@ thingtypes { color = 14; // Yellow title = "Rings and Weapon Panels"; - width = 24; height = 24; flags8height = 24; flags8text = "[8] Float"; @@ -4377,7 +4376,6 @@ thingtypes { title = "Ring"; sprite = "RINGA0"; - width = 16; } 301 { @@ -4393,6 +4391,7 @@ thingtypes { title = "Infinity Ring"; sprite = "RNGIA0"; + width = 24; } 304 { @@ -4418,43 +4417,53 @@ thingtypes { title = "CTF Team Ring (Red)"; sprite = "internal:TRNGA0R"; - width = 16; } 309 { title = "CTF Team Ring (Blue)"; sprite = "internal:TRNGA0B"; - width = 16; } 330 { title = "Bounce Ring Panel"; sprite = "PIKBA0"; + width = 24; + height = 40; } 331 { title = "Rail Ring Panel"; sprite = "PIKRA0"; + width = 24; + height = 40; } 332 { title = "Automatic Ring Panel"; sprite = "PIKAA0"; + width = 24; + height = 40; } 333 { title = "Explosion Ring Panel"; sprite = "PIKEA0"; + width = 24; + height = 40; } 334 { title = "Scatter Ring Panel"; sprite = "PIKSA0"; + width = 24; + height = 40; } 335 { title = "Grenade Ring Panel"; sprite = "PIKGA0"; + width = 24; + height = 40; } } @@ -4463,7 +4472,7 @@ thingtypes color = 10; // Light Green title = "Other Collectibles"; width = 16; - height = 32; + height = 24; sort = 1; sprite = "CEMGA0"; @@ -4529,6 +4538,7 @@ thingtypes { title = "Emerald Hunt Location"; sprite = "SHRDA0"; + height = 32; flags8height = 24; flags8text = "[8] Float"; } diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index df08e3ac5..9eb227974 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -1185,7 +1185,7 @@ udmf { color = 14; // Yellow title = "Rings and Weapon Panels"; - width = 24; + width = 16; height = 24; sprite = "RINGA0"; @@ -1193,7 +1193,6 @@ udmf { title = "Ring"; sprite = "RINGA0"; - width = 16; arg0 { title = "Float?"; @@ -1227,6 +1226,7 @@ udmf { title = "Infinity Ring"; sprite = "RNGIA0"; + width = 24; arg0 { title = "Float?"; @@ -1282,7 +1282,6 @@ udmf { title = "CTF Team Ring (Red)"; sprite = "internal:TRNGA0R"; - width = 16; arg0 { title = "Float?"; @@ -1294,7 +1293,6 @@ udmf { title = "CTF Team Ring (Blue)"; sprite = "internal:TRNGA0B"; - width = 16; arg0 { title = "Float?"; @@ -1306,6 +1304,8 @@ udmf { title = "Bounce Ring Panel"; sprite = "PIKBA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1317,6 +1317,8 @@ udmf { title = "Rail Ring Panel"; sprite = "PIKRA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1328,6 +1330,8 @@ udmf { title = "Automatic Ring Panel"; sprite = "PIKAA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1339,6 +1343,8 @@ udmf { title = "Explosion Ring Panel"; sprite = "PIKEA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1350,6 +1356,8 @@ udmf { title = "Scatter Ring Panel"; sprite = "PIKSA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1361,6 +1369,8 @@ udmf { title = "Grenade Ring Panel"; sprite = "PIKGA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1375,7 +1385,7 @@ udmf color = 10; // Light_Green title = "Other Collectibles"; width = 16; - height = 32; + height = 24; sort = 1; sprite = "CEMGA0"; @@ -1445,6 +1455,7 @@ udmf { title = "Emerald Hunt Location"; sprite = "SHRDA0"; + height = 32; arg0 { title = "Float?"; diff --git a/src/Makefile b/src/Makefile index e1d9cb384..41cef2a17 100644 --- a/src/Makefile +++ b/src/Makefile @@ -392,4 +392,4 @@ else @: endif -$(warning The handwritten GNU Makefile for SRB2 is deprecated, and may be removed in the future. Please consider switching to CMake.) +#$(warning The handwritten GNU Makefile for SRB2 is deprecated, and may be removed in the future. Please consider switching to CMake.) diff --git a/src/Makefile.d/nix.mk b/src/Makefile.d/nix.mk index aa2e96df7..9adf3f0f1 100644 --- a/src/Makefile.d/nix.mk +++ b/src/Makefile.d/nix.mk @@ -25,7 +25,7 @@ endif # Tested by Steel, as of release 2.2.8. ifdef FREEBSD opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD -libs+=-L/usr/X11R6/lib -lipx -lkvm +libs+=-L/usr/X11R6/lib -lkvm -lexecinfo endif # FIXME: UNTESTED diff --git a/src/config.h.in b/src/config.h.in index 0ca0f26e9..6d49a6989 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -38,12 +38,14 @@ * Last updated 2021 / 05 / 06 - v2.2.9 - patch.pk3 & zones.pk3 * Last updated 2022 / 03 / 06 - v2.2.10 - main assets * Last updated 2023 / 05 / 02 - v2.2.11 - patch.pk3 & zones.pk3 + * Last updated 2023 / 09 / 06 - v2.2.12 - patch.pk3 + * Last updated 2023 / 09 / 09 - v2.2.13 - none */ #define ASSET_HASH_SRB2_PK3 "ad911f29a28a18968ee5b2d11c2acb39" #define ASSET_HASH_ZONES_PK3 "1c8adf8d079ecb87d00081f158acf3c7" #define ASSET_HASH_PLAYER_DTA "2e7aaae8a6b1b77d90ffe7606ceadb6c" #ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_PK3 "2e69558bce3b9610624549a75e29e19b" +#define ASSET_HASH_PATCH_PK3 "3c7b73f34af7e9a7bceb2d5260f76172" #endif #endif diff --git a/src/d_main.c b/src/d_main.c index 5c6db2e29..871b8400c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1740,14 +1740,15 @@ void D_SRB2Main(void) // Prevent warping to nonexistent levels if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR) I_Error("Could not warp to %s (map not found)\n", G_BuildMapName(pstartmap)); - // Prevent warping to locked levels - // ... unless you're in a dedicated server. Yes, technically this means you can view any level by - // running a dedicated server and joining it yourself, but that's better than making dedicated server's - // lives hell. - else if (!dedicated && M_MapLocked(pstartmap, serverGamedata)) - I_Error("You need to unlock this level before you can warp to it!\n"); else { + if (M_CampaignWarpIsCheat(gametype, pstartmap, serverGamedata)) + { + // If you're warping via command line, you know what you're doing. + // No need to I_Error over this. + G_SetUsedCheats(false); + } + D_MapChange(pstartmap, gametype, ultimatemode, true, 0, false, false); } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 60013b5c5..5c93601ed 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -777,6 +777,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_showfocuslost); CV_RegisterVar(&cv_pauseifunfocused); + CV_RegisterVar(&cv_instantretry); + // g_input.c CV_RegisterVar(&cv_sideaxis); CV_RegisterVar(&cv_sideaxis2); @@ -1801,8 +1803,8 @@ static void Command_Map_f(void) size_t option_gametype; const char *gametypename; boolean newresetplayers; - - boolean wouldSetCheats; + boolean prevent_cheat; + boolean set_cheated; INT32 newmapnum; @@ -1823,21 +1825,34 @@ static void Command_Map_f(void) option_gametype = COM_CheckPartialParm("-g"); newresetplayers = ! COM_CheckParm("-noresetplayers"); - wouldSetCheats = - !( netgame || multiplayer ) && - !( usedCheats ); + prevent_cheat = !( usedCheats ) && !( option_force || cv_debug ); + set_cheated = false; - if (wouldSetCheats && !option_force) + if (!( netgame || multiplayer )) { - /* May want to be more descriptive? */ - CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); - return; + if (prevent_cheat) + { + /* May want to be more descriptive? */ + CONS_Printf(M_GetText("Cheats must be enabled to level change in single player.\n")); + return; + } + else + { + set_cheated = true; + } } - if (!newresetplayers && !cv_debug) + if (!newresetplayers) { - CONS_Printf(M_GetText("DEVMODE must be enabled.\n")); - return; + if (prevent_cheat) + { + CONS_Printf(M_GetText("Cheats must be enabled to use -noresetplayers.\n")); + return; + } + else + { + set_cheated = true; + } } if (option_gametype) @@ -1845,7 +1860,7 @@ static void Command_Map_f(void) if (!multiplayer) { CONS_Printf(M_GetText( - "You can't switch gametypes in single player!\n")); + "You can't switch gametypes in single player!\n")); return; } else if (COM_Argc() < option_gametype + 2)/* no argument after? */ @@ -1858,7 +1873,9 @@ static void Command_Map_f(void) } if (!( first_option = COM_FirstOption() )) + { first_option = COM_Argc(); + } if (first_option < 2) { @@ -1881,11 +1898,6 @@ static void Command_Map_f(void) return; } - if (wouldSetCheats && option_force) - { - G_SetUsedCheats(false); - } - // new gametype value // use current one by default if (option_gametype) @@ -1927,15 +1939,13 @@ static void Command_Map_f(void) } // don't use a gametype the map doesn't support - if (cv_debug || option_force || cv_skipmapcheck.value) - fromlevelselect = false; // The player wants us to trek on anyway. Do so. // G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer - else + if (!( + mapheaderinfo[newmapnum-1] && + mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype) + )) { - if (!( - mapheaderinfo[newmapnum-1] && - mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype) - )) + if (prevent_cheat && !cv_skipmapcheck.value) { CONS_Alert(CONS_WARNING, M_GetText("%s (%s) doesn't support %s mode!\n(Use -force to override)\n"), realmapname, G_BuildMapName(newmapnum), (multiplayer ? gametype_cons_t[newgametype].strvalue : "Single Player")); @@ -1945,23 +1955,33 @@ static void Command_Map_f(void) } else { - fromlevelselect = - ( netgame || multiplayer ) && - newgametype == gametype && - gametypedefaultrules[newgametype] & GTR_CAMPAIGN; + // The player wants us to trek on anyway. Do so. + fromlevelselect = false; + set_cheated = ((gametypedefaultrules[newgametype] & GTR_CAMPAIGN) == GTR_CAMPAIGN); } } + else + { + fromlevelselect = + ( netgame || multiplayer ) && + newgametype == gametype && + (gametypedefaultrules[newgametype] & GTR_CAMPAIGN); + } // Prevent warping to locked levels - // ... unless you're in a dedicated server. Yes, technically this means you can view any level by - // running a dedicated server and joining it yourself, but that's better than making dedicated server's - // lives hell. - if (!dedicated && M_MapLocked(newmapnum, serverGamedata)) + if (M_CampaignWarpIsCheat(newgametype, newmapnum, serverGamedata)) { - CONS_Alert(CONS_NOTICE, M_GetText("You need to unlock this level before you can warp to it!\n")); - Z_Free(realmapname); - Z_Free(mapname); - return; + if (prevent_cheat) + { + CONS_Alert(CONS_NOTICE, M_GetText("Cheats must be enabled to warp to a locked level!\n")); + Z_Free(realmapname); + Z_Free(mapname); + return; + } + else + { + set_cheated = true; + } } // Ultimate Mode only in SP via menu @@ -1978,6 +1998,11 @@ static void Command_Map_f(void) } tutorialmode = false; // warping takes us out of tutorial mode + if (set_cheated && !usedCheats) + { + G_SetUsedCheats(false); + } + D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect); Z_Free(realmapname); @@ -2019,11 +2044,13 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) lastgametype = gametype; gametype = READUINT8(*cp); - G_SetGametype(gametype); // I fear putting that macro as an argument if (gametype < 0 || gametype >= gametypecount) gametype = lastgametype; - else if (gametype != lastgametype) + else + G_SetGametype(gametype); + + if (gametype != lastgametype) D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype skipprecutscene = ((flags & (1<<2)) != 0); @@ -4139,9 +4166,6 @@ void D_GameTypeChanged(INT32 lastgametype) else if (!multiplayer && !netgame) { G_SetGametype(GT_COOP); - // These shouldn't matter anymore - //CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); - //CV_SetValue(&cv_itemrespawn, 0); } // reset timelimit and pointlimit in race/coop, prevent stupid cheats @@ -4442,25 +4466,37 @@ static void Command_Mapmd5_f(void) CONS_Printf(M_GetText("You must be in a level to use this.\n")); } +void D_SendExitLevel(boolean cheat) +{ + UINT8 buf[8]; + UINT8 *buf_p = buf; + + WRITEUINT8(buf_p, cheat); + + SendNetXCmd(XD_EXITLEVEL, &buf, buf_p - buf); +} + static void Command_ExitLevel_f(void) { - if (!(netgame || (multiplayer && gametype != GT_COOP)) && !cv_debug) - CONS_Printf(M_GetText("This only works in a netgame.\n")); - else if (!(server || (IsPlayerAdmin(consoleplayer)))) + if (!(server || (IsPlayerAdmin(consoleplayer)))) CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); else if (( gamestate != GS_LEVEL && gamestate != GS_CREDITS ) || demoplayback) CONS_Printf(M_GetText("You must be in a level to use this.\n")); else - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(true); } static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) { - (void)cp; + boolean cheat = false; + + cheat = (boolean)READUINT8(*cp); // Ignore duplicate XD_EXITLEVEL commands. if (gameaction == ga_completed) + { return; + } if (playernum != serverplayer && !IsPlayerAdmin(playernum)) { @@ -4470,6 +4506,11 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) return; } + if (G_CoopGametype() && cheat) + { + G_SetUsedCheats(false); + } + G_ExitLevel(); } diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 26bf4d5c6..8bbc801d0 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -201,6 +201,7 @@ void D_SendPlayerConfig(void); void Command_ExitGame_f(void); void Command_Retry_f(void); void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore +void D_SendExitLevel(boolean cheat); void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect); boolean IsPlayerAdmin(INT32 playernum); void SetAdminPlayer(INT32 playernum); diff --git a/src/deh_lua.c b/src/deh_lua.c index 1b177eb25..0b789547b 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -277,8 +277,8 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) } else if (fastncmp("MTF_", word, 4)) { p = word+4; - for (i = 0; i < 4; i++) - if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) { + for (i = 0; MAPTHINGFLAG_LIST[i]; i++) + if (fastcmp(p, MAPTHINGFLAG_LIST[i])) { CacheAndPushConstant(L, word, ((lua_Integer)1< \t"\1", // \2 extern const char *const MOBJEFLAG_LIST[]; -extern const char *const MAPTHINGFLAG_LIST[4]; +extern const char *const MAPTHINGFLAG_LIST[]; extern const char *const PLAYERFLAG_LIST[]; extern const char *const GAMETYPERULE_LIST[]; extern const char *const ML_LIST[]; // Linedef flags diff --git a/src/doomdata.h b/src/doomdata.h index 576fe03e2..276e03297 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -62,6 +62,10 @@ enum #define MTF_AMBUSH 8 // Do not use bit five or after, as they are used for object z-offsets. +// Unless it's exclusive to UDMF. + +// Flag to use Z as absolute spawn height, ignoring the floor and ceiling. +#define MTF_ABSOLUTEZ 16 #if defined(_MSC_VER) #pragma pack(1) diff --git a/src/doomdef.h b/src/doomdef.h index f82b0a4cd..45d6645fa 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -269,8 +269,7 @@ typedef enum // Desaturated SKINCOLOR_AETHER, SKINCOLOR_SLATE, - SKINCOLOR_METEORITE, - SKINCOLOR_MERCURY, + SKINCOLOR_MOONSTONE, SKINCOLOR_BLUEBELL, SKINCOLOR_PINK, SKINCOLOR_ROSEWOOD, @@ -307,10 +306,10 @@ typedef enum SKINCOLOR_COPPER, SKINCOLOR_APRICOT, SKINCOLOR_ORANGE, - SKINCOLOR_PUMPKIN, SKINCOLOR_RUST, - SKINCOLOR_GOLD, + SKINCOLOR_TANGERINE, SKINCOLOR_TOPAZ, + SKINCOLOR_GOLD, SKINCOLOR_SANDY, SKINCOLOR_GOLDENROD, SKINCOLOR_YELLOW, @@ -320,20 +319,21 @@ typedef enum SKINCOLOR_LIME, SKINCOLOR_PERIDOT, SKINCOLOR_APPLE, + SKINCOLOR_HEADLIGHT, SKINCOLOR_CHARTREUSE, SKINCOLOR_GREEN, SKINCOLOR_FOREST, SKINCOLOR_SHAMROCK, SKINCOLOR_JADE, - SKINCOLOR_HEADLIGHT, SKINCOLOR_MINT, SKINCOLOR_MASTER, SKINCOLOR_EMERALD, - SKINCOLOR_BOTTLE, SKINCOLOR_SEAFOAM, SKINCOLOR_ISLAND, + SKINCOLOR_BOTTLE, SKINCOLOR_AQUA, SKINCOLOR_TEAL, + SKINCOLOR_OCEAN, SKINCOLOR_WAVE, SKINCOLOR_CYAN, SKINCOLOR_TURQUOISE, @@ -359,7 +359,7 @@ typedef enum SKINCOLOR_NOBLE, SKINCOLOR_FUCHSIA, SKINCOLOR_BUBBLEGUM, - SKINCOLOR_CRYSTAL, + SKINCOLOR_SIBERITE, SKINCOLOR_MAGENTA, SKINCOLOR_NEON, SKINCOLOR_VIOLET, diff --git a/src/doomstat.h b/src/doomstat.h index a812cc304..fdd0d0b83 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -249,6 +249,7 @@ extern textprompt_t *textprompts[MAX_PROMPTS]; // For the Custom Exit linedef. extern INT16 nextmapoverride; extern UINT8 skipstats; +extern INT16 nextgametype; extern UINT32 ssspheres; // Total # of spheres in a level diff --git a/src/doomtype.h b/src/doomtype.h index 617fd4d47..4070e346a 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -113,6 +113,15 @@ int endswith (const char *base, const char *tag); #define HAVE_DOSSTR_FUNCS #endif +#if defined (__APPLE__) + #define SRB2_HAVE_STRLCPY +#elif defined (__GLIBC_PREREQ) + // glibc 2.38: added strlcpy and strlcat to _DEFAULT_SOURCE + #if __GLIBC_PREREQ(2, 38) + #define SRB2_HAVE_STRLCPY + #endif +#endif + #ifndef HAVE_DOSSTR_FUNCS int strupr(char *n); // from dosstr.c int strlwr(char *n); // from dosstr.c @@ -120,7 +129,7 @@ int strlwr(char *n); // from dosstr.c #include // for size_t -#ifndef __APPLE__ +#ifndef SRB2_HAVE_STRLCPY size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz); #endif diff --git a/src/f_finale.c b/src/f_finale.c index d03795dc4..91c06b316 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1062,12 +1062,14 @@ static const char *credits[] = { "\"Golden\"", "Vivian \"toaster\" Grannell", "Julio \"Chaos Zero 64\" Guir", + "\"Hanicef\"", "\"Hannu_Hanhi\"", // For many OpenGL performance improvements! "Kepa \"Nev3r\" Iceta", "Thomas \"Shadow Hog\" Igoe", "Iestyn \"Monster Iestyn\" Jealous", "\"Kaito Sinclaire\"", "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog + "\"katsy\"", "Ronald \"Furyhunter\" Kinard", // The SDL2 port "\"Lat'\"", // SRB2-CHAT, the chat window from Kart "\"LZA\"", @@ -1090,6 +1092,7 @@ static const char *credits[] = { "Ben \"Cue\" Woodford", "Lachlan \"Lach\" Wright", "Marco \"mazmazz\" Zafra", + "\"Zwip-Zwap Zapony\"", "", "\1Art", "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: @@ -1197,6 +1200,7 @@ static const char *credits[] = { "FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak "Kart Krew", "Alex \"MistaED\" Fuller", + "Howard Drossin", // Virtual Sonic - Sonic & Knuckles Theme "Pascal \"CodeImp\" vd Heiden", // Doom Builder developer "Randi Heit ()", // For their MSPaint sprite that we nicked "Simon \"sirjuddington\" Judd", // SLADE developer @@ -1644,7 +1648,7 @@ void F_GameEvaluationTicker(void) sparklloop = 0; } - if (finalecount == 5*TICRATE) + if (G_CoopGametype() && !stagefailed && finalecount == 5*TICRATE) { serverGamedata->timesBeaten++; clientGamedata->timesBeaten++; @@ -2256,7 +2260,7 @@ void F_InitMenuPresValues(void) curfadevalue = 16; curbgcolor = -1; curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; - curbgyspeed = (gamestate == GS_TIMEATTACK) ? 22 : titlescrollyspeed; + curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; curbghide = (gamestate == GS_TIMEATTACK) ? false : true; curhidepics = hidetitlepics; diff --git a/src/g_game.c b/src/g_game.c index eac5b29e5..60c3cf3d8 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -158,6 +158,7 @@ textprompt_t *textprompts[MAX_PROMPTS]; INT16 nextmapoverride; UINT8 skipstats; +INT16 nextgametype = -1; // Pointers to each CTF flag mobj_t *redflag; @@ -317,6 +318,8 @@ consvar_t cv_consolechat = CVAR_INIT ("chatmode", "Window", CV_SAVE, consolechat // Pause game upon window losing focus consvar_t cv_pauseifunfocused = CVAR_INIT ("pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL); +consvar_t cv_instantretry = CVAR_INIT ("instantretry", "No", CV_SAVE, CV_YesNo, NULL); + consvar_t cv_crosshair = CVAR_INIT ("crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL); consvar_t cv_crosshair2 = CVAR_INIT ("crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL); consvar_t cv_invertmouse = CVAR_INIT ("invertmouse", "Off", CV_SAVE, CV_OnOff, NULL); @@ -2081,7 +2084,7 @@ boolean G_Responder(event_t *ev) if (gameaction == ga_nothing && !singledemo && ((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN)) { - if (ev->type == ev_keydown && ev->key != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE)) + if (ev->type == ev_keydown && ev->key != 301 && !(gamestate == GS_TITLESCREEN && finalecount < (cv_tutorialprompt.value ? TICRATE : 0))) { M_StartControlPanel(); return true; @@ -2139,7 +2142,7 @@ boolean G_Responder(event_t *ev) if (! netgame) F_StartGameEvaluation(); else if (server || IsPlayerAdmin(consoleplayer)) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); return true; } } @@ -2174,9 +2177,9 @@ boolean G_Responder(event_t *ev) if (menuactive || pausedelay < 0 || leveltime < 2) return true; - if (pausedelay < 1+(NEWTICRATE/2)) + if (!cv_instantretry.value && pausedelay < 1+(NEWTICRATE/2)) pausedelay = 1+(NEWTICRATE/2); - else if (++pausedelay > 1+(NEWTICRATE/2)+(NEWTICRATE/3)) + else if (cv_instantretry.value || ++pausedelay > 1+(NEWTICRATE/2)+(NEWTICRATE/3)) { G_SetModeAttackRetryFlag(); return true; @@ -3444,9 +3447,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] = }; // -// G_SetGametype -// -// Set a new gametype, also setting gametype rules accordingly. Yay! +// Sets a new gametype. // void G_SetGametype(INT16 gtype) { @@ -3844,7 +3845,7 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) for (ix = 0; ix < NUMMAPS; ix++) if (mapheaderinfo[ix] && (mapheaderinfo[ix]->typeoflevel & tolflags) == tolflags && ix != pprevmap // Don't pick the same map. - && (dedicated || !M_MapLocked(ix+1, serverGamedata)) // Don't pick locked maps. + && (!M_MapLocked(ix+1, serverGamedata)) // Don't pick locked maps. ) okmaps[numokmaps++] = ix; @@ -4036,6 +4037,13 @@ static void G_DoCompleted(void) nextmap = 1100-1; // No infinite loop for you } + INT16 gametype_to_use; + + if (nextgametype >= 0 && nextgametype < gametypecount) + gametype_to_use = nextgametype; + else + gametype_to_use = gametype; + // If nextmap is actually going to get used, make sure it points to // a map of the proper gametype -- skip levels that don't support // the current gametype. (Helps avoid playing boss levels in Race, @@ -4044,8 +4052,8 @@ static void G_DoCompleted(void) { if (nextmap >= 0 && nextmap < NUMMAPS) { - register INT16 cm = nextmap; - UINT32 tolflag = G_TOLFlag(gametype); + INT16 cm = nextmap; + UINT32 tolflag = G_TOLFlag(gametype_to_use); UINT8 visitedmap[(NUMMAPS+7)/8]; memset(visitedmap, 0, sizeof (visitedmap)); @@ -4100,7 +4108,7 @@ static void G_DoCompleted(void) { token--; - if (!nextmapoverride) +// if (!nextmapoverride) // Having a token should pull the player into the special stage before going to the overridden map (Issue #933) for (i = 0; i < 7; i++) if (!(emeralds & (1<= 0 && nextgametype < gametypecount) + gametype_to_use = nextgametype; + else + gametype_to_use = gametype; + if (gametyperules & GTR_CAMPAIGN) // don't reset player between maps - D_MapChange(nextmap+1, gametype, ultimatemode, false, 0, false, false); + D_MapChange(nextmap+1, gametype_to_use, ultimatemode, false, 0, false, false); else // resetplayer in match/chaos/tag/CTF/race for more equality - D_MapChange(nextmap+1, gametype, ultimatemode, true, 0, false, false); + D_MapChange(nextmap+1, gametype_to_use, ultimatemode, true, 0, false, false); + + nextgametype = -1; } gameaction = ga_nothing; diff --git a/src/g_game.h b/src/g_game.h index cb38fc1d5..4d86a0455 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -49,6 +49,8 @@ extern boolean promptactive; extern consvar_t cv_pauseifunfocused; +extern consvar_t cv_instantretry; + // used in game menu extern consvar_t cv_tutorialprompt; extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 36ff86abd..f2022bcea 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1699,7 +1699,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) { blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; - Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255)); } if (gl_frontsector->numlights) @@ -1822,7 +1822,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) { blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; - Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255)); } if (gl_backsector->numlights) @@ -3095,7 +3095,7 @@ static void HWR_Subsector(size_t num) false, *rover->bottomheight, *gl_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, + 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); } @@ -3141,7 +3141,7 @@ static void HWR_Subsector(size_t num) true, *rover->topheight, *gl_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, + 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); } @@ -3595,7 +3595,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) return; } - floordiff = abs((flip < 0 ? thing->height : 0) + interp.z - groundz); + floordiff = abs((flip < 0 ? interp.height : 0) + interp.z - groundz); alpha = floordiff / (4*FRACUNIT) + 75; if (alpha >= 255) return; @@ -3606,9 +3606,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) HWR_GetPatch(gpatch); scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); - if ((thing->scale != thing->old_scale) && (thing->scale >= FRACUNIT/1024)) // Interpolate shadows when scaling mobjs - scalemul = FixedMul(scalemul, FixedDiv(interp.scale, thing->scale)); + scalemul = FixedMul(scalemul, (interp.radius*2) / gpatch->height); fscale = FIXED_TO_FLOAT(scalemul); fx = FIXED_TO_FLOAT(interp.x); @@ -3720,7 +3718,7 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts if (P_MobjFlip(spr->mobj) == -1) { - basey = FIXED_TO_FLOAT(interp.z + spr->mobj->height); + basey = FIXED_TO_FLOAT(interp.z + interp.height); } else { @@ -4055,32 +4053,32 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis) // repeat this 4 times (overhead) // // - // 17 20 21 11 - // 16 15 14 10 - // 27 22 *--* 07 12 + // 15 16 17 09 + // 14 13 12 08 + // 23 18 *--* 07 10 // | | - // 26 23 *--* 06 13 - // 24 00 01 02 - // 25 05 04 03 + // 22 19 *--* 06 11 + // 20 00 01 02 + // 21 05 04 03 // - v[000].x = v[005].x = v[015].x = v[016].x = v[017].x = v[020].x = - v[022].x = v[023].x = v[024].x = v[025].x = v[026].x = v[027].x = vis->x1; // west + v[ 0].x = v[ 5].x = v[13].x = v[14].x = v[15].x = v[16].x = + v[18].x = v[19].x = v[20].x = v[21].x = v[22].x = v[23].x = vis->x1; // west - v[001].x = v[002].x = v[003].x = v[004].x = v[006].x = v[007].x = - v[010].x = v[011].x = v[012].x = v[013].x = v[014].x = v[021].x = vis->x2; // east + v[ 1].x = v[ 2].x = v[ 3].x = v[ 4].x = v[ 6].x = v[ 7].x = + v[ 8].x = v[ 9].x = v[10].x = v[11].x = v[12].x = v[17].x = vis->x2; // east - v[000].z = v[001].z = v[002].z = v[003].z = v[004].z = v[005].z = - v[006].z = v[013].z = v[023].z = v[024].z = v[025].z = v[026].z = vis->z1; // south + v[ 0].z = v[ 1].z = v[ 2].z = v[ 3].z = v[ 4].z = v[ 5].z = + v[ 6].z = v[11].z = v[19].z = v[20].z = v[21].z = v[22].z = vis->z1; // south - v[007].z = v[010].z = v[011].z = v[012].z = v[014].z = v[015].z = - v[016].z = v[017].z = v[020].z = v[021].z = v[022].z = v[027].z = vis->z2; // north + v[ 7].z = v[ 8].z = v[ 9].z = v[10].z = v[12].z = v[13].z = + v[14].z = v[15].z = v[16].z = v[17].z = v[18].z = v[23].z = vis->z2; // north - v[000].y = v[001].y = v[002].y = v[006].y = v[007].y = v[010].y = - v[014].y = v[015].y = v[016].y = v[022].y = v[023].y = v[024].y = vis->gz; // bottom + v[ 0].y = v[ 1].y = v[ 2].y = v[ 6].y = v[ 7].y = v[ 8].y = + v[12].y = v[13].y = v[14].y = v[18].y = v[19].y = v[20].y = vis->gz; // bottom - v[003].y = v[004].y = v[005].y = v[011].y = v[012].y = v[013].y = - v[017].y = v[020].y = v[021].y = v[025].y = v[026].y = v[027].y = vis->gzt; // top + v[ 3].y = v[ 4].y = v[ 5].y = v[ 9].y = v[10].y = v[11].y = + v[15].y = v[16].y = v[17].y = v[21].y = v[22].y = v[23].y = vis->gzt; // top Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj)); @@ -5326,7 +5324,7 @@ static void HWR_ProjectSprite(mobj_t *thing) } groundz = R_GetShadowZ(thing, NULL); - floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + casterinterp.z - groundz); + floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? casterinterp.height : 0) + casterinterp.z - groundz); shadowheight = FIXED_TO_FLOAT(floordiff); shadowscale = FIXED_TO_FLOAT(FixedMul(FRACUNIT - floordiff/640, casterinterp.scale)); @@ -5378,7 +5376,7 @@ static void HWR_ProjectSprite(mobj_t *thing) if (vflip) { - gz = FIXED_TO_FLOAT(interp.z + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale); + gz = FIXED_TO_FLOAT(interp.z + interp.height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale); gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale); } else @@ -5684,7 +5682,6 @@ static void HWR_ProjectBoundingBox(mobj_t *thing) gl_vissprite_t *vis; float tr_x, tr_y; float tz; - float rad; if (!thing) return; @@ -5719,15 +5716,13 @@ static void HWR_ProjectBoundingBox(mobj_t *thing) tr_x += gl_viewx; tr_y += gl_viewy; - rad = FIXED_TO_FLOAT(thing->radius); - vis = HWR_NewVisSprite(); - vis->x1 = tr_x - rad; - vis->x2 = tr_x + rad; - vis->z1 = tr_y - rad; - vis->z2 = tr_y + rad; + vis->x1 = tr_x - FIXED_TO_FLOAT(interp.radius); + vis->x2 = tr_x + FIXED_TO_FLOAT(interp.radius); + vis->z1 = tr_y - FIXED_TO_FLOAT(interp.radius); + vis->z2 = tr_y + FIXED_TO_FLOAT(interp.radius); vis->gz = FIXED_TO_FLOAT(interp.z); - vis->gzt = vis->gz + FIXED_TO_FLOAT(thing->height); + vis->gzt = vis->gz + FIXED_TO_FLOAT(interp.height); vis->mobj = thing; vis->precip = false; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index d005f0037..6123eb9a9 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1585,7 +1585,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.y = FIXED_TO_FLOAT(interp.y)+md2->offset; if (flip) - p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height); + p.z = FIXED_TO_FLOAT(interp.z + interp.height); else p.z = FIXED_TO_FLOAT(interp.z); @@ -1621,8 +1621,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.roll = true; // rotation pivot - p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); - p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); + p.centerx = FIXED_TO_FLOAT(interp.radius / 2); + p.centery = FIXED_TO_FLOAT(interp.height / 2); // rotation axes relative to camera p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 091e2b2fb..e223d3208 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2025,7 +2025,7 @@ void HU_Drawer(void) V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP | V_ALLOWLOWERCASE, resynch_text); } - if (modeattacking && pausedelay > 0 && !pausebreakkey) + if (modeattacking && pausedelay > 0 && !(pausebreakkey || cv_instantretry.value)) { INT32 strength = ((pausedelay - 1 - NEWTICRATE/2)*10)/(NEWTICRATE/3); INT32 y = hudinfo[HUD_LIVES].y - 13; diff --git a/src/info.c b/src/info.c index abcf4b499..36389d849 100644 --- a/src/info.c +++ b/src/info.c @@ -7194,7 +7194,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD1, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7220,7 +7220,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD2, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7246,7 +7246,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD3, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7272,7 +7272,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD4, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7298,7 +7298,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD5, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7324,7 +7324,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD6, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7350,7 +7350,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD7, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -18344,7 +18344,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_bouncering, // mass @@ -18371,7 +18371,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_railring, // mass @@ -18425,7 +18425,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_automaticring, // mass @@ -18452,7 +18452,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_explosionring, // mass @@ -18479,7 +18479,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_scatterring, // mass @@ -18506,7 +18506,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_grenadering, // mass @@ -18535,7 +18535,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_bouncering, // mass 2*TICRATE, // damage @@ -18562,7 +18562,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_railring, // mass 2*TICRATE, // damage @@ -18589,7 +18589,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_automaticring, // mass 2*TICRATE, // damage @@ -18616,7 +18616,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_explosionring, // mass 2*TICRATE, // damage @@ -18643,7 +18643,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_scatterring, // mass 2*TICRATE, // damage @@ -18670,7 +18670,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_grenadering, // mass 2*TICRATE, // damage @@ -21584,10 +21584,9 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Black", {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, SKINCOLOR_WHITE, 7, V_GRAYMAP, true}, // SKINCOLOR_BLACK // Desaturated - {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER + {"Aether", {0x00, 0x00, 0x01, 0x01, 0x90, 0x90, 0x91, 0x91, 0x92, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xae}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE - {"Meteorite", { 0, 4, 8, 9, 11, 12, 14, 15, 171, 172, 173, 174, 175, 27, 29, 31}, SKINCOLOR_TOPAZ, 15, V_GRAYMAP, true}, // SKINCOLOR_METEORITE - {"Mercury", { 0, 3, 4, 7, 11, 12, 14, 15, 171, 172, 173, 155, 157, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_AZUREMAP, true}, // SKINCOLOR_MERCURY + {"Moonstone", { 0, 4, 8, 9, 11, 12, 14, 15, 171, 172, 173, 174, 175, 27, 29, 31}, SKINCOLOR_TOPAZ, 15, V_GRAYMAP, true}, // SKINCOLOR_MOONSTONE {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK {"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD @@ -21597,37 +21596,37 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Boulder", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BOULDER {"Bronze", { 82, 84, 50, 51, 223, 228, 230, 232, 234, 236, 237, 238, 239, 239, 30, 31}, SKINCOLOR_VOLCANIC, 9, V_BROWNMAP, true}, // SKINCOLOR_BRONZE {"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD, 5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA - {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_MERCURY, 15, V_BROWNMAP, true}, // SKINCOLOR_ECRU + {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_ARCTIC, 12, V_BROWNMAP, true}, // SKINCOLOR_ECRU {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN {"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE {"Rosebush", { 208, 216, 209, 85, 90, 91, 91, 92, 191, 93, 94, 107, 109, 110, 111, 111}, SKINCOLOR_EGGPLANT, 5, V_GREENMAP, true}, // SKINCOLOR_ROSEBUSH {"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS {"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE {"Eggplant", { 4, 8, 11, 11, 16, 195, 195, 195, 196, 186, 187, 187, 254, 254, 30, 31}, SKINCOLOR_ROSEBUSH, 5, V_PURPLEMAP, true}, // SKINCOLOR_EGGPLANT - {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER + {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER // Viv's vivid colours (toast 21/07/17) - // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) + // Tweaks & additions (Lach, Chrispy, sphere, Alice, MotorRoach & Saneko 26/10/22) {"Ruby", {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, SKINCOLOR_EMERALD, 10, V_REDMAP, true}, // SKINCOLOR_RUBY {"Cherry", { 202, 203, 204, 205, 206, 40, 41, 42, 43, 44, 186, 187, 28, 29, 30, 31}, SKINCOLOR_MIDNIGHT, 10, V_REDMAP, true}, // SKINCOLOR_CHERRY {"Salmon", {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, SKINCOLOR_FOREST, 6, V_REDMAP, true}, // SKINCOLOR_SALMON - {"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_PEPPER - {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_RED + {"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_PEPPER + {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED {"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON {"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME {"Garnet", { 0, 83, 50, 53, 34, 35, 37, 38, 39, 40, 42, 44, 45, 46, 47, 47}, SKINCOLOR_AQUAMARINE, 6, V_REDMAP, true}, // SKINCOLOR_GARNET {"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BOULDER, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP {"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY {"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL - {"Foundation", { 80, 81, 82, 84, 219, 221, 221, 212, 213, 214, 215, 195, 196, 186, 187, 30}, SKINCOLOR_DREAM, 6, V_ORANGEMAP, true}, // SKINCOLOR_FOUNDATION + {"Foundation", { 80, 81, 82, 84, 219, 221, 221, 212, 213, 214, 215, 197, 186, 187, 187, 30}, SKINCOLOR_DREAM, 6, V_ORANGEMAP, true}, // SKINCOLOR_FOUNDATION {"Sunset", {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, SKINCOLOR_SAPPHIRE, 5, V_ORANGEMAP, true}, // SKINCOLOR_SUNSET {"Copper", {0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, SKINCOLOR_BLUEBELL, 5, V_ORANGEMAP, true}, // SKINCOLOR_COPPER {"Apricot", {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, SKINCOLOR_CYAN, 4, V_ORANGEMAP, true}, // SKINCOLOR_APRICOT {"Orange", { 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 42, 44, 45, 46, 46}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE - {"Pumpkin", { 51, 52, 53, 54, 56, 58, 59, 59, 61, 61, 63, 45, 46, 47, 47, 31}, SKINCOLOR_ARCTIC, 12, V_ORANGEMAP, true}, // SKINCOLOR_PUMPKIN {"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST - {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_GOLD - {"Topaz", { 0, 81, 83, 73, 74, 74, 65, 52, 53, 54, 56, 58, 60, 42, 43, 45}, SKINCOLOR_METEORITE, 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ + {"Tangerine", { 81, 83, 64, 64, 51, 52, 53, 54, 56, 58, 60, 61, 63, 45, 46, 47}, SKINCOLOR_OCEAN, 12, V_ORANGEMAP, true}, // SKINCOLOR_TANGERINE + {"Topaz", { 0, 81, 83, 73, 74, 74, 65, 52, 53, 54, 56, 58, 60, 42, 43, 45}, SKINCOLOR_MOONSTONE, 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ + {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD {"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY {"Goldenrod", { 0, 80, 81, 81, 83, 73, 73, 64, 65, 66, 67, 68, 69, 62, 44, 45}, SKINCOLOR_MAJESTY, 8, V_YELLOWMAP, true}, // SKINCOLOR_GOLDENROD {"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW @@ -21637,20 +21636,21 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME {"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT {"Apple", {0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, SKINCOLOR_RASPBERRY, 13, V_PERIDOTMAP, true}, // SKINCOLOR_APPLE + {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT {"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE - {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_GREEN + {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN {"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST - {"Shamrock", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_CRYSTAL, 10, V_GREENMAP, true}, // SKINCOLOR_SHAMROCK - {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_ROSY, 7, V_GREENMAP, true}, // SKINCOLOR_JADE - {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT + {"Shamrock", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_SIBERITE, 10, V_GREENMAP, true}, // SKINCOLOR_SHAMROCK + {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_TAFFY, 10, V_GREENMAP, true}, // SKINCOLOR_JADE {"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT - {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_MASTER + {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_MASTER {"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 9, V_GREENMAP, true}, // SKINCOLOR_EMERALD - {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 14, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8b, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM {"Island", { 96, 97, 113, 113, 114, 124, 142, 136, 136, 150, 151, 153, 168, 168, 169, 169}, SKINCOLOR_GALAXY, 7, V_AQUAMAP, true}, // SKINCOLOR_ISLAND - {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_TAFFY, 10, V_AQUAMAP, true}, // SKINCOLOR_AQUA + {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 14, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE + {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA {"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL + {"Ocean", { 120, 121, 122, 122, 123, 141, 142, 142, 136, 137, 138, 138, 139, 139, 253, 253}, SKINCOLOR_TANGERINE, 4, V_AQUAMAP, true}, // SKINCOLOR_OCEAN {"Wave", {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_QUAIL, 5, V_SKYMAP, true}, // SKINCOLOR_WAVE {"Cyan", {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, SKINCOLOR_APRICOT, 6, V_SKYMAP, true}, // SKINCOLOR_CYAN {"Turquoise", { 0, 120, 121, 122, 123, 141, 141, 135, 136, 136, 150, 153, 155, 157, 159, 253}, SKINCOLOR_SANGRIA, 12, V_SKYMAP, true}, // SKINCOLOR_TURQUOISE @@ -21661,12 +21661,12 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Dream", { 80, 208, 200, 200, 146, 146, 133, 134, 135, 136, 137, 138, 139, 139, 254, 254}, SKINCOLOR_FOUNDATION, 9, V_SKYMAP, true}, // SKINCOLOR_DREAM {"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY {"Daybreak", { 80, 81, 82, 72, 64, 9, 11, 171, 149, 150, 151, 153, 156, 157, 159, 253}, SKINCOLOR_EVENTIDE, 12, V_BLUEMAP, true}, // SKINCOLOR_DAYBREAK - {"Sapphire", {0x80, 0x82, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE - {"Arctic", { 0, 1, 3, 4, 146, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_PUMPKIN, 6, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC + {"Sapphire", {0x80, 0x82, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_BLUEMAP, true}, // SKINCOLOR_SAPPHIRE + {"Arctic", { 0, 1, 3, 4, 145, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC {"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER {"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE {"Cobalt", { 145, 147, 149, 150, 151, 153, 154, 155, 156, 157, 158, 159, 253, 253, 254, 254}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT - {"Midnight", { 171, 171, 172, 173, 173, 174, 155, 156, 157, 159, 253, 253, 254, 254, 31, 31}, SKINCOLOR_CHERRY, 10, V_GRAYMAP, true}, // SKINCOLOR_MIDNIGHT + {"Midnight", { 171, 171, 172, 173, 173, 174, 175, 157, 158, 159, 253, 253, 254, 254, 31, 31}, SKINCOLOR_CHERRY, 10, V_GRAYMAP, true}, // SKINCOLOR_MIDNIGHT {"Galaxy", { 160, 161, 162, 163, 164, 165, 166, 166, 154, 155, 156, 157, 159, 253, 254, 31}, SKINCOLOR_ISLAND, 7, V_PURPLEMAP, true}, // SKINCOLOR_GALAXY {"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR {"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK @@ -21676,21 +21676,21 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Noble", { 144, 146, 147, 148, 149, 164, 164, 165, 166, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 10, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 182, 164, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM - {"Crystal", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_CRYSTAL + {"Siberite", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_SIBERITE {"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA {"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET {"Royal", { 208, 209, 192, 192, 192, 193, 193, 194, 194, 172, 173, 174, 175, 175, 139, 139}, SKINCOLOR_FANCY, 9, V_PURPLEMAP, true}, // SKINCOLOR_ROYAL {"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC - {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE + {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE {"Eventide", { 51, 52, 53, 33, 34, 204, 183, 183, 184, 184, 166, 167, 168, 169, 253, 254}, SKINCOLOR_DAYBREAK, 13, V_MAGENTAMAP, true}, // SKINCOLOR_EVENTIDE {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY - {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_TAFFY - {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_ROSY + {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY + {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY {"Fancy", { 0, 208, 49, 210, 210, 202, 202, 203, 204, 204, 205, 206, 207, 207, 186, 186}, SKINCOLOR_ROYAL, 9, V_ROSYMAP, true}, // SKINCOLOR_FANCY {"Sangria", { 210, 32, 33, 34, 34, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 12, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA - {"Volcanic", { 35, 38, 41, 42, 44, 46, 46, 169, 169, 159, 253, 254, 30, 30, 31, 31}, SKINCOLOR_BRONZE, 9, V_REDMAP, true}, // SKINCOLOR_VOLCANIC + {"Volcanic", { 54, 36, 42, 44, 45, 46, 46, 47, 28, 253, 253, 254, 254, 30, 31, 31}, SKINCOLOR_BRONZE, 9, V_REDMAP, true}, // SKINCOLOR_VOLCANIC // super {"Super Silver 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, SKINCOLOR_BLACK, 15, 0, false}, // SKINCOLOR_SUPERSILVER1 diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 915669bb2..4af5066ae 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3826,7 +3826,7 @@ static int lib_gDoReborn(lua_State *L) } // Another Lua function that doesn't actually exist! -// Sets nextmapoverride & skipstats without instantly ending the level, for instances where other sources should be exiting the level, like normal signposts. +// Sets nextmapoverride, skipstats and nextgametype without instantly ending the level, for instances where other sources should be exiting the level, like normal signposts. static int lib_gSetCustomExitVars(lua_State *L) { int n = lua_gettop(L); // Num arguments @@ -3835,18 +3835,21 @@ static int lib_gSetCustomExitVars(lua_State *L) // LUA EXTENSION: Custom exit like support // Supported: - // G_SetCustomExitVars(); [reset to defaults] - // G_SetCustomExitVars(int) [nextmap override only] - // G_SetCustomExitVars(nil, int) [skipstats only] - // G_SetCustomExitVars(int, int) [both of the above] + // G_SetCustomExitVars(); [reset to defaults] + // G_SetCustomExitVars(int) [nextmap override only] + // G_SetCustomExitVars(nil, int) [skipstats only] + // G_SetCustomExitVars(int, int) [both of the above] + // G_SetCustomExitVars(int, int, int) [nextmapoverride, skipstats and nextgametype] nextmapoverride = 0; skipstats = 0; + nextgametype = -1; if (n >= 1) { nextmapoverride = (INT16)luaL_optinteger(L, 1, 0); skipstats = (INT16)luaL_optinteger(L, 2, 0); + nextgametype = (INT16)luaL_optinteger(L, 3, -1); } return 0; diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 9e5d1e2ee..3783b8f7b 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -615,7 +615,7 @@ static int cvar_get(lua_State *L) break; default: if (devparm) - return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field); + return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS ".", lua_tostring(L, 2)); else return 0; } diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 2e3bb9c68..6eec91273 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -282,7 +282,6 @@ static int patch_get(lua_State *L) patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); enum patch field = Lua_optoption(L, 2, -1, patch_fields_ref); - // patches are invalidated when switching renderers if (!patch) { if (field == patch_valid) { lua_pushboolean(L, 0); @@ -436,7 +435,7 @@ static int camera_set(lua_State *L) cam->momz = luaL_checkfixed(L, 3); break; default: - return luaL_error(L, LUA_QL("camera_t") " has no field named " LUA_QS, camera_opt[field]); + return luaL_error(L, LUA_QL("camera_t") " has no field named " LUA_QS ".", lua_tostring(L, 2)); } return 0; } @@ -1487,7 +1486,6 @@ void LUA_SetHudHook(int hook, huddrawlist_h list) break; case HUD_HOOK(intermission): - lua_pushboolean(gL, intertype == int_spec && - stagefailed); + lua_pushboolean(gL, stagefailed); } } diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 3d95cdb75..e34397993 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -800,8 +800,9 @@ static int sector_set(lua_State *L) case sector_fslope: // f_slope case sector_cslope: // c_slope case sector_friction: // friction - default: return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); + default: + return luaL_error(L, "sector_t has no field named " LUA_QS ".", lua_tostring(L, 2)); case sector_floorheight: { // floorheight boolean flag; mobj_t *ptmthing = tmthing; @@ -1279,8 +1280,9 @@ static int side_set(lua_State *L) case side_sector: case side_special: case side_text: - default: return luaL_error(L, "side_t field " LUA_QS " cannot be set.", side_opt[field]); + default: + return luaL_error(L, "side_t has no field named " LUA_QS ".", lua_tostring(L, 2)); case side_textureoffset: side->textureoffset = luaL_checkfixed(L, 3); break; @@ -2291,8 +2293,9 @@ static int ffloor_set(lua_State *L) case ffloor_target: // target case ffloor_next: // next case ffloor_prev: // prev - default: return luaL_error(L, "ffloor_t field " LUA_QS " cannot be set.", ffloor_opt[field]); + default: + return luaL_error(L, "ffloor_t has no field named " LUA_QS ".", lua_tostring(L, 2)); case ffloor_topheight: { // topheight boolean flag; fixed_t lastpos = *ffloor->topheight; @@ -2426,8 +2429,9 @@ static int slope_set(lua_State *L) case slope_d: // d case slope_flags: // flags case slope_normal: // normal - default: return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]); + default: + return luaL_error(L, "pslope_t has no field named " LUA_QS ".", lua_tostring(L, 2)); case slope_o: { // o luaL_checktype(L, 3, LUA_TTABLE); diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 13e0dd987..041c5d598 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -25,6 +25,7 @@ enum skin { skin_flags, skin_realname, skin_hudname, + skin_supername, skin_ability, skin_ability2, skin_thokitem, @@ -63,6 +64,7 @@ static const char *const skin_opt[] = { "flags", "realname", "hudname", + "supername", "ability", "ability2", "thokitem", @@ -126,6 +128,9 @@ static int skin_get(lua_State *L) case skin_hudname: lua_pushstring(L, skin->hudname); break; + case skin_supername: + lua_pushstring(L, skin->supername); + break; case skin_ability: lua_pushinteger(L, skin->ability); break; diff --git a/src/m_cheat.c b/src/m_cheat.c index e370335f8..7ad86353a 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1102,6 +1102,8 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value; mt->scale = player->mo->scale; + mt->spritexscale = player->mo->spritexscale; + mt->spriteyscale = player->mo->spriteyscale; memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); mt->pitch = mt->roll = 0; diff --git a/src/m_cond.c b/src/m_cond.c index 13a483ea2..706a1b510 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -467,6 +467,15 @@ UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data) UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) { + if (dedicated) + { + // If you're in a dedicated server, every level is unlocked. + // Yes, technically this means you can view any level by + // running a dedicated server and joining it yourself, but + // that's better than making dedicated server's lives hell. + return false; + } + if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0) { return false; @@ -480,6 +489,48 @@ UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) return false; } +UINT8 M_CampaignWarpIsCheat(INT32 gt, INT32 mapnum, gamedata_t *data) +{ + if (M_MapLocked(mapnum, data) == true) + { + // Warping to locked maps is definitely always a cheat + return true; + } + + if ((gametypedefaultrules[gt] & GTR_CAMPAIGN) == 0) + { + // Not a campaign, do whatever you want. + return false; + } + + if (G_IsSpecialStage(mapnum)) + { + // Warping to special stages is a cheat + return true; + } + + if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->menuflags & LF2_HIDEINMENU) + { + // You're never allowed to warp to this level. + return true; + } + + if (mapheaderinfo[mapnum-1]->menuflags & LF2_NOVISITNEEDED) + { + // You're always allowed to warp to this level. + return false; + } + + if (mapnum == spstage_start) + { + // Warping to the first level is never a cheat + return false; + } + + // It's only a cheat if you've never been there. + return (!(data->mapvisited[mapnum-1])); +} + INT32 M_CountEmblems(gamedata_t *data) { INT32 found = 0, i; diff --git a/src/m_cond.h b/src/m_cond.h index 2be8d564b..2491a384c 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -252,6 +252,7 @@ void M_SilentUpdateSkinAvailabilites(void); UINT8 M_AnySecretUnlocked(gamedata_t *data); UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data); UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data); +UINT8 M_CampaignWarpIsCheat(INT32 gt, INT32 mapnum, gamedata_t *data); INT32 M_CountEmblems(gamedata_t *data); // Emblem shit diff --git a/src/m_menu.c b/src/m_menu.c index 63cb1e1c6..cbda2fed1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2649,7 +2649,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, { strncpy(curbgname, defaultname, 9); curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; - curbgyspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollyspeed; + curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; } } return false; @@ -2843,8 +2843,8 @@ static void M_HandleMenuPresState(menu_t *newMenu) curfadevalue = 16; curhidepics = hidetitlepics; curbgcolor = -1; - curbgxspeed = titlescrollxspeed; - curbgyspeed = titlescrollyspeed; + curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; + curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus curttmode = ttmode; @@ -3196,7 +3196,7 @@ boolean M_Responder(event_t *ev) || gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_GAMEEND) return false; - if (gamestate == GS_TITLESCREEN && finalecount < TICRATE) + if (gamestate == GS_TITLESCREEN && finalecount < (cv_tutorialprompt.value ? TICRATE : 0)) return false; if (CON_Ready() && gamestate != GS_WAITINGPLAYERS) @@ -12054,6 +12054,136 @@ static INT32 setupm_fakeskin; static menucolor_t *setupm_fakecolor; static boolean colorgrid; +#define COLOR_GRID_ROW_SIZE (16) + +static UINT16 M_GetColorGridIndex(UINT16 color) +{ + menucolor_t *look; + UINT16 i = 0; + + if (!skincolors[color].accessible) + { + return 0; + } + + for (look = menucolorhead; ; i++, look = look->next) + { + while (!skincolors[look->color].accessible) // skip inaccessible colors + { + if (look == menucolortail) + { + return 0; + } + + look = look->next; + } + + if (look->color == color) + { + return i; + } + + if (look == menucolortail) + { + return 0; + } + } +} + +static INT32 M_GridIndexToX(UINT16 index) +{ + return (index % COLOR_GRID_ROW_SIZE); +} + +static INT32 M_GridIndexToY(UINT16 index) +{ + return (index / COLOR_GRID_ROW_SIZE); +} + +static UINT16 M_ColorGridLen(void) +{ + menucolor_t *look; + UINT16 i = 0; + + for (look = menucolorhead; ; i++) + { + do + { + if (look == menucolortail) + { + return i; + } + + look = look->next; + } + while (!skincolors[look->color].accessible); // skip inaccessible colors + } +} + +static UINT16 M_GridPosToGridIndex(INT32 x, INT32 y) +{ + const UINT16 grid_len = M_ColorGridLen(); + const UINT16 grid_height = ((grid_len - 1) / COLOR_GRID_ROW_SIZE) + 1; + const UINT16 last_row_len = COLOR_GRID_ROW_SIZE - ((grid_height * COLOR_GRID_ROW_SIZE) - grid_len); + + UINT16 row_len = COLOR_GRID_ROW_SIZE; + UINT16 new_index = 0; + + while (y < 0) + { + y += grid_height; + } + y = (y % grid_height); + + if (y >= grid_height-1 && last_row_len > 0) + { + row_len = last_row_len; + } + + while (x < 0) + { + x += row_len; + } + x = (x % row_len); + + new_index = (y * COLOR_GRID_ROW_SIZE) + x; + if (new_index >= grid_len) + { + new_index = grid_len - 1; + } + + return new_index; +} + +static menucolor_t *M_GridIndexToMenuColor(UINT16 index) +{ + menucolor_t *look = menucolorhead; + UINT16 i = 0; + + for (look = menucolorhead; ; i++, look = look->next) + { + while (!skincolors[look->color].accessible) // skip inaccessible colors + { + if (look == menucolortail) + { + return menucolorhead; + } + + look = look->next; + } + + if (i == index) + { + return look; + } + + if (look == menucolortail) + { + return menucolorhead; + } + } +} + static void M_DrawSetupMultiPlayerMenu(void) { INT32 x, y, cursory = 0, flags = 0; @@ -12172,32 +12302,54 @@ colordraw: boolean stoprow = false; menucolor_t *mc; // Last accessed color + const UINT16 grid_len = M_ColorGridLen(); + const UINT16 grid_end_y = M_GridIndexToY(grid_len - 1); + + INT32 grid_select = M_GetColorGridIndex(setupm_fakecolor->color); + INT32 grid_select_y = M_GridIndexToY(grid_select); + x = 132; y = 66; - pos = min(max(0, 16*((M_GetColorIndex(setupm_fakecolor->color)-1)/16) - 64), 16*(M_GetColorIndex(menucolortail->color)/16-1) - 128); - mc = M_GetColorFromIndex(pos); + + pos = M_GridPosToGridIndex(0, max(0, min(grid_select_y - 3, grid_end_y - 7))); + mc = M_GridIndexToMenuColor(pos); // Draw grid V_DrawFill(x-2, y-2, 132, 132, 159); for (j = 0; j < 8; j++) { - for (i = 0; i < 16; i++) + for (i = 0; i < COLOR_GRID_ROW_SIZE; i++) { - if (skincolors[mc->color].accessible && !stoprow) + if (skincolors[mc->color].accessible) { M_DrawColorRamp(x + i*w, y + j*16, w, 1, skincolors[mc->color]); - if (mc->color == setupm_fakecolor->color) // store current color position - { - cx = x + i*w; - cy = y + j*16; - } + + if (mc == setupm_fakecolor) // store current color position + { + cx = x + i*w; + cy = y + j*16; + } } - mc = mc->next; - while (!skincolors[mc->color].accessible && !stoprow) // Find accessible color after this one + + if (stoprow) + { + break; + } + + // Find accessible color after this one + do { mc = mc->next; - if (mc == menucolortail) stoprow = true; - } + if (mc == menucolortail) + { + stoprow = true; + } + } while (!skincolors[mc->color].accessible && !stoprow); + } + + if (stoprow) + { + break; } } @@ -12318,15 +12470,16 @@ static void M_HandleSetupMultiPlayer(INT32 choice) case KEY_DOWNARROW: case KEY_UPARROW: { - UINT8 i; if (itemOn == 2 && colorgrid) { - for (i = 0; i < 16; i++) - { - setupm_fakecolor = (choice == KEY_UPARROW) ? setupm_fakecolor->prev : setupm_fakecolor->next; - while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors - setupm_fakecolor = (choice == KEY_UPARROW) ? setupm_fakecolor->prev : setupm_fakecolor->next; - } + UINT16 index = M_GetColorGridIndex(setupm_fakecolor->color); + INT32 x = M_GridIndexToX(index); + INT32 y = M_GridIndexToY(index); + + y += (choice == KEY_UPARROW) ? -1 : 1; + + index = M_GridPosToGridIndex(x, y); + setupm_fakecolor = M_GridIndexToMenuColor(index); } else if (choice == KEY_UPARROW) M_PrevOpt(); @@ -12353,8 +12506,8 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } else if (itemOn == 2) // player color { - S_StartSound(NULL,sfx_menu1); // Tails setupm_fakecolor = setupm_fakecolor->prev; + S_StartSound(NULL,sfx_menu1); // Tails } break; @@ -12393,8 +12546,8 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } else if (itemOn == 2) // player color { - S_StartSound(NULL,sfx_menu1); // Tails setupm_fakecolor = setupm_fakecolor->next; + S_StartSound(NULL,sfx_menu1); // Tails } break; @@ -12404,13 +12557,28 @@ static void M_HandleSetupMultiPlayer(INT32 choice) UINT8 i; if (itemOn == 2) // player color { - S_StartSound(NULL,sfx_menu1); - for (i = 0; i < (colorgrid ? 64 : 13); i++) // or (282-charw)/(2*indexwidth) + if (colorgrid) { - setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; - while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors - setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; + UINT16 index = M_GetColorGridIndex(setupm_fakecolor->color); + INT32 x = M_GridIndexToX(index); + INT32 y = M_GridIndexToY(index); + + y += (choice == KEY_UPARROW) ? -4 : 4; + + index = M_GridPosToGridIndex(x, y); + setupm_fakecolor = M_GridIndexToMenuColor(index); } + else + { + for (i = 0; i < 13; i++) // or (282-charw)/(2*indexwidth) + { + setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; + while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors + setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; + } + } + + S_StartSound(NULL, sfx_menu1); // Tails } } break; @@ -12440,7 +12608,6 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } } break; - break; case KEY_DEL: if (itemOn == 0 && (l = strlen(setupm_name))!=0) diff --git a/src/p_inter.c b/src/p_inter.c index 2d132b684..615507eb4 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1144,7 +1144,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!(mo2->type == MT_RING || mo2->type == MT_COIN || mo2->type == MT_BLUESPHERE || mo2->type == MT_BOMBSPHERE || mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR - || ((mo2->type == MT_EMBLEM) && (mo2->reactiontime & GE_NIGHTSPULL)))) + || ((mo2->type == MT_EMBLEM) && (mo2->reactiontime & GE_NIGHTSPULL) && P_CanPickupEmblem(player, mo2->health - 1) && !P_EmblemWasCollected(mo2->health - 1)))) continue; // Yay! The thing's in reach! Pull it in! @@ -2235,7 +2235,7 @@ void P_CheckTimeLimit(void) } if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } //Optional tie-breaker for Match/CTF @@ -2298,11 +2298,11 @@ void P_CheckTimeLimit(void) } } if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } /** Checks if a player's score is over the pointlimit and the round should end. @@ -2331,7 +2331,7 @@ void P_CheckPointLimit(void) if ((UINT32)cv_pointlimit.value <= redscore || (UINT32)cv_pointlimit.value <= bluescore) { if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } } else @@ -2344,7 +2344,7 @@ void P_CheckPointLimit(void) if ((UINT32)cv_pointlimit.value <= players[i].score) { if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); return; } } @@ -2388,7 +2388,7 @@ void P_CheckSurvivors(void) { CONS_Printf(M_GetText("The IT player has left the game.\n")); if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); return; } @@ -2408,7 +2408,7 @@ void P_CheckSurvivors(void) { CONS_Printf(M_GetText("All players have been tagged!\n")); if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } return; @@ -2420,7 +2420,7 @@ void P_CheckSurvivors(void) { CONS_Printf(M_GetText("There are no players able to become IT.\n")); if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } return; @@ -2432,7 +2432,7 @@ void P_CheckSurvivors(void) { CONS_Printf(M_GetText("All players have been tagged!\n")); if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } } diff --git a/src/p_map.c b/src/p_map.c index 132a3cf85..80135db74 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2524,7 +2524,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) { subsector_t *s = R_PointInSubsector(x, y); - boolean retval = true; boolean itsatwodlevel = false; floatok = false; @@ -2539,8 +2538,8 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) fixed_t tryx = thiscam->x; fixed_t tryy = thiscam->y; - if ((thiscam == &camera && (players[displayplayer].pflags & PF_NOCLIP)) - || (thiscam == &camera2 && (players[secondarydisplayplayer].pflags & PF_NOCLIP))) + if ((thiscam == &camera && (players[displayplayer].pflags & PF_NOCLIP || players[displayplayer].powers[pw_carry] == CR_NIGHTSMODE)) + || (thiscam == &camera2 && (players[secondarydisplayplayer].pflags & PF_NOCLIP || players[secondarydisplayplayer].powers[pw_carry] == CR_NIGHTSMODE))) { // Noclipping player camera noclips too!! floatok = true; thiscam->floorz = thiscam->z; @@ -2608,7 +2607,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) thiscam->y = y; thiscam->subsector = s; - return retval; + return true; } // diff --git a/src/p_mobj.c b/src/p_mobj.c index ff5e5006e..7858e0d8c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3688,7 +3688,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled dummy.y = thiscam->y; dummy.z = thiscam->z; dummy.height = thiscam->height; - if (!resetcalled && !(player->pflags & PF_NOCLIP) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. + if (!resetcalled && !(player->pflags & PF_NOCLIP || player->powers[pw_carry] == CR_NIGHTSMODE) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. P_ResetCamera(player, thiscam); else { @@ -3719,7 +3719,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled // adjust height thiscam->z += thiscam->momz + player->mo->pmomz; - if (!itsatwodlevel && !(player->pflags & PF_NOCLIP)) + if (!itsatwodlevel && !(player->pflags & PF_NOCLIP || player->powers[pw_carry] == CR_NIGHTSMODE)) { // clip movement if (thiscam->z <= thiscam->floorz) // hit the floor @@ -6882,7 +6882,6 @@ void P_RunOverlays(void) mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP); mo->scale = mo->destscale = mo->target->scale; mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir; - P_SetTarget(&mo->dontdrawforviewmobj, mo->target->dontdrawforviewmobj); // Hide the overlay from the view that its target is hidden from - But don't copy drawonlyforplayer! if (!(mo->state->frame & FF_ANIMATE)) zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale); @@ -9228,7 +9227,7 @@ static void P_DragonbomberThink(mobj_t *mobj) else { fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); - fixed_t z = mobj->target->z + (mobj->height >> 1) + (mobj->flags & MFE_VERTICALFLIP ? -128*mobj->scale : 128*mobj->scale + mobj->target->height); + fixed_t z = mobj->target->z + (mobj->height >> 1) + (mobj->eflags & MFE_VERTICALFLIP ? -128*mobj->scale : (128*mobj->scale + mobj->target->height)); angle_t diff = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) - mobj->angle; if (diff > ANGLE_180) mobj->angle -= DRAGONTURNSPEED; @@ -10564,6 +10563,29 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) case MT_REDFLAG: case MT_BLUEFLAG: + case MT_BOUNCERING: + case MT_AUTOMATICRING: + case MT_INFINITYRING: + case MT_RAILRING: + case MT_EXPLOSIONRING: + case MT_SCATTERRING: + case MT_GRENADERING: + + case MT_BOUNCEPICKUP: + case MT_RAILPICKUP: + case MT_AUTOPICKUP: + case MT_EXPLODEPICKUP: + case MT_SCATTERPICKUP: + case MT_GRENADEPICKUP: + + case MT_REDRING: + case MT_THROWNBOUNCE: + case MT_THROWNINFINITY: + case MT_THROWNAUTOMATIC: + case MT_THROWNSCATTER: + case MT_THROWNEXPLOSION: + case MT_THROWNGRENADE: + case MT_EMBLEM: case MT_TOKEN: @@ -11832,7 +11854,7 @@ void P_MovePlayerToStarpost(INT32 playernum) mapthing_t *huntemeralds[MAXHUNTEMERALDS]; INT32 numhuntemeralds; -fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale) +fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale, const boolean absolutez) { const subsector_t *ss = R_PointInSubsector(x, y); @@ -11842,9 +11864,9 @@ fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const f // Establish height. if (flip) - return P_GetSectorCeilingZAt(ss->sector, x, y) - dz - FixedMul(scale, offset + mobjinfo[mobjtype].height); + return (absolutez ? dz : P_GetSectorCeilingZAt(ss->sector, x, y) - dz) - FixedMul(scale, offset + mobjinfo[mobjtype].height); else - return P_GetSectorFloorZAt(ss->sector, x, y) + dz + FixedMul(scale, offset); + return (absolutez ? dz : P_GetSectorFloorZAt(ss->sector, x, y) + dz) + FixedMul(scale, offset); } fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y) @@ -11852,6 +11874,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt fixed_t dz = mthing->z << FRACBITS; // Base offset from the floor. fixed_t offset = 0; // Specific scaling object offset. boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); + boolean absolutez = !!(mthing->options & MTF_ABSOLUTEZ); switch (mobjtype) { @@ -11907,7 +11930,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt offset += mthing->args[0] ? 0 : 24*FRACUNIT; } - if (!(dz + offset)) // Snap to the surfaces when there's no offset set. + if (!(dz + offset) && !absolutez) // Snap to the surfaces when there's no offset set. { if (flip) return ONCEILINGZ; @@ -11915,7 +11938,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt return ONFLOORZ; } - return P_GetMobjSpawnHeight(mobjtype, x, y, dz, offset, flip, mthing->scale); + return P_GetMobjSpawnHeight(mobjtype, x, y, dz, offset, flip, mthing->scale, absolutez); } static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) @@ -12584,7 +12607,7 @@ static boolean P_SetupNiGHTSDrone(mapthing_t *mthing, mobj_t *mobj) dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0); if (flip && mobj->height != oldheight) - P_MoveOrigin(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight)); + P_SetOrigin(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight)); if (!flip) { @@ -13412,7 +13435,7 @@ void P_SpawnHoop(mapthing_t *mthing) vector4_t v, res; fixed_t x = mthing->x << FRACBITS; fixed_t y = mthing->y << FRACBITS; - fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale); + fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale, mthing->options & MTF_ABSOLUTEZ); hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); hoopcenter->spawnpoint = mthing; @@ -13539,7 +13562,7 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numi itemtypes[r] = P_GetMobjtypeSubstitute(&dummything, itemtypes[r]); } } - z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, mthing->options & MTF_OBJECTFLIP, mthing->scale); + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, mthing->options & MTF_OBJECTFLIP, mthing->scale, mthing->options & MTF_ABSOLUTEZ); for (r = 0; r < numitems; r++) { @@ -13598,7 +13621,7 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n itemtypes[i] = P_GetMobjtypeSubstitute(&dummything, itemtypes[i]); } } - z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, false, mthing->scale); + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, false, mthing->scale, mthing->options & MTF_ABSOLUTEZ); for (i = 0; i < numitems; i++) { diff --git a/src/p_mobj.h b/src/p_mobj.h index 9c598f59e..a980691be 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -491,7 +491,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing); void P_MovePlayerToStarpost(INT32 playernum); void P_AfterPlayerSpawn(INT32 playernum); -fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale); +fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale, const boolean absolutez); fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y); mobj_t *P_SpawnMapThing(mapthing_t *mthing); diff --git a/src/p_setup.c b/src/p_setup.c index d14d91fa5..e0235c335 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -50,6 +50,7 @@ #include "m_random.h" #include "dehacked.h" // for map headers +#include "deh_tables.h" // FREE_SKINCOLORS #include "r_main.h" #include "m_cond.h" // for emblems @@ -1266,12 +1267,19 @@ static void P_WriteDuplicateText(const char *text, char **target) static void P_WriteSkincolor(INT32 constant, char **target) { + const char *color_name; + if (constant <= SKINCOLOR_NONE || constant >= (INT32)numskincolors) return; + if (constant >= SKINCOLOR_FIRSTFREESLOT) + color_name = FREE_SKINCOLORS[constant - SKINCOLOR_FIRSTFREESLOT]; + else + color_name = COLOR_ENUMS[constant]; + P_WriteDuplicateText( - va("SKINCOLOR_%s", skincolors[constant].name), + va("SKINCOLOR_%s", color_name), target ); } @@ -2025,6 +2033,8 @@ static void ParseTextmapThingParameter(UINT32 i, const char *param, const char * // Flags else if (fastcmp(param, "flip") && fastcmp("true", val)) mapthings[i].options |= MTF_OBJECTFLIP; + else if (fastcmp(param, "absolutez") && fastcmp("true", val)) + mapthings[i].options |= MTF_ABSOLUTEZ; else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9) { @@ -6810,6 +6820,9 @@ static void P_ConvertBinaryThingTypes(void) default: break; } + + // Clear binary thing height hacks, to prevent interfering with UDMF-only flags + mapthings[i].options &= 0xF; } } @@ -8224,7 +8237,7 @@ static boolean P_LoadAddon(UINT16 numlumps) { CONS_Printf(M_GetText("Current map %d replaced by added file, ending the level to ensure consistency.\n"), gamemap); if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } return true; diff --git a/src/p_slopes.c b/src/p_slopes.c index 6aca116a5..1c0ee81a7 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -566,6 +566,7 @@ static void line_SpawnViaMapthingVertexes(const int linenum, const boolean spawn case TMSP_BACKCEILING: slopetoset = &line->backsector->c_slope; side = &sides[line->sidenum[1]]; + break; default: return; } diff --git a/src/p_spec.c b/src/p_spec.c index 169f129b9..28ecc60f4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3286,19 +3286,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) foundrover = true; // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 - // for relative alpha calc + // initialize its alpha to 0 for relative alpha calculation if (!(line->args[3] & TMST_DONTDOTRANSLUCENT) && // do translucent (rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE !(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERPLANES) && !(rover->fofflags & FOF_RENDERALL)) - rover->alpha = 1; + rover->alpha = 0; P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, rover->alpha, - max(1, min(256, (line->args[3] & TMST_RELATIVE) ? rover->alpha + destvalue : destvalue)), + max(0, min(255, (line->args[3] & TMST_RELATIVE) ? rover->alpha + destvalue : destvalue)), 0, // set alpha immediately false, NULL, // tic-based logic false, // do not handle FOF_EXISTS @@ -3372,19 +3371,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) else { // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 - // for relative alpha calc + // initialize its alpha to 1 for relative alpha calculation if (!(line->args[4] & TMFT_DONTDOTRANSLUCENT) && // do translucent (rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE !(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERPLANES) && !(rover->fofflags & FOF_RENDERALL)) - rover->alpha = 1; + rover->alpha = 0; P_RemoveFakeFloorFader(rover); P_FadeFakeFloor(rover, rover->alpha, - max(1, min(256, (line->args[4] & TMFT_RELATIVE) ? rover->alpha + destvalue : destvalue)), + max(0, min(255, (line->args[4] & TMFT_RELATIVE) ? rover->alpha + destvalue : destvalue)), 0, // set alpha immediately false, NULL, // tic-based logic !(line->args[4] & TMFT_DONTDOEXISTS), // do not handle FOF_EXISTS @@ -6565,10 +6563,10 @@ void P_SpawnSpecials(boolean fromnetsave) //Cutting options if (ffloorflags & FOF_RENDERALL) { - //If inside is visible, cut inner walls - if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFA_SPLAT) || (lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) + //If inside is visible from the outside, cut inner walls + if (lines[i].args[1] < 255 || (lines[i].args[3] & TMFA_SPLAT)) ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA; - else + else if (!(lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FOF_CUTLEVEL; } @@ -6624,20 +6622,19 @@ void P_SpawnSpecials(boolean fromnetsave) if (lines[i].args[4] & TMFC_SPLAT) ffloorflags |= FOF_SPLAT; - //If inside is visible, cut inner walls - if (lines[i].args[1] < 0xff || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) || (lines[i].args[4] & TMFC_SPLAT)) + //If inside is visible from the outside, cut inner walls + if (lines[i].args[1] < 255 || (lines[i].args[4] & TMFC_SPLAT)) ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA; - else - ffloorflags |= FOF_CUTLEVEL; - - //If player can enter it, render insides - if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) + //If player can view it from the inside, render insides + else if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) { if (ffloorflags & FOF_RENDERPLANES) ffloorflags |= FOF_BOTHPLANES; if (ffloorflags & FOF_RENDERSIDES) ffloorflags |= FOF_ALLSIDES; } + else + ffloorflags |= FOF_CUTLEVEL; P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); if (lines[i].args[4] & TMFC_AIRBOB) @@ -6688,10 +6685,10 @@ void P_SpawnSpecials(boolean fromnetsave) //Cutting options if (ffloorflags & FOF_RENDERALL) { - //If inside is visible, cut inner walls - if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFA_SPLAT) || (lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) + //If inside is visible from the outside, cut inner walls + if (lines[i].args[1] < 255 || (lines[i].args[3] & TMFA_SPLAT)) ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA; - else + else if (!(lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) ffloorflags |= FOF_CUTLEVEL; } @@ -7756,15 +7753,14 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destval if (rover->master->special == 258) // Laser block return false; - // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 + // If fading an invisible FOF whose render flags we did not yet set, initialize its alpha to 1 if (dotranslucent && (rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE !(rover->fofflags & FOF_FOG) && // do not include fog !(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERPLANES) && !(rover->fofflags & FOF_RENDERALL)) - rover->alpha = 1; + rover->alpha = 0; if (fadingdata) alpha = fadingdata->alpha; @@ -7850,7 +7846,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destval { if (doexists && !(rover->spawnflags & FOF_BUSTUP)) { - if (alpha <= 1) + if (alpha <= 0) rover->fofflags &= ~FOF_EXISTS; else rover->fofflags |= FOF_EXISTS; @@ -7862,7 +7858,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destval if (dotranslucent && !(rover->fofflags & FOF_FOG)) { - if (alpha >= 256) + if (alpha >= 255) { if (!(rover->fofflags & FOF_CUTSOLIDS) && (rover->spawnflags & FOF_CUTSOLIDS)) @@ -7962,11 +7958,11 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destval else // clamp fadingdata->alpha to software's alpha levels { if (alpha < 12) - rover->alpha = destvalue < 12 ? destvalue : 1; // Don't even draw it + rover->alpha = destvalue < 12 ? destvalue : 0; // Don't even draw it else if (alpha < 38) rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25; else if (alpha < 64) - rover->alpha = destvalue >=38 && destvalue < 64 ? destvalue : 51; + rover->alpha = destvalue >= 38 && destvalue < 64 ? destvalue : 51; else if (alpha < 89) rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76; else if (alpha < 115) @@ -7982,7 +7978,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destval else if (alpha < 243) rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230; else // Opaque - rover->alpha = destvalue >= 243 ? destvalue : 256; + rover->alpha = destvalue >= 243 ? destvalue : 255; } } @@ -8012,17 +8008,16 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor { fade_t *d; - // If fading an invisible FOF whose render flags we did not yet set, - // initialize its alpha to 1 + // If fading an invisible FOF whose render flags we did not yet set, initialize its alpha to 1 if (dotranslucent && (rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE !(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERPLANES) && !(rover->fofflags & FOF_RENDERALL)) - rover->alpha = 1; + rover->alpha = 0; // already equal, nothing to do - if (rover->alpha == max(1, min(256, relative ? rover->alpha + destvalue : destvalue))) + if (rover->alpha == max(0, min(255, relative ? rover->alpha + destvalue : destvalue))) return; d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); @@ -8033,7 +8028,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->ffloornum = (UINT32)ffloornum; d->alpha = d->sourcevalue = rover->alpha; - d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // rover->alpha is 1-256 + d->destvalue = max(0, min(255, relative ? rover->alpha + destvalue : destvalue)); // rover->alpha is 0-255 if (ticbased) { diff --git a/src/p_user.c b/src/p_user.c index 39626b5e2..a443b7323 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1855,6 +1855,7 @@ void P_SpawnShieldOrb(player_t *player) { ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY); P_SetTarget(&ov->target, shieldobj); + P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person P_SetMobjState(ov, shieldobj->info->seestate); P_SetTarget(&shieldobj->tracer, ov); } @@ -1862,12 +1863,14 @@ void P_SpawnShieldOrb(player_t *player) { ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY); P_SetTarget(&ov->target, shieldobj); + P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person P_SetMobjState(ov, shieldobj->info->meleestate); } if (shieldobj->info->missilestate) { ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY); P_SetTarget(&ov->target, shieldobj); + P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person P_SetMobjState(ov, shieldobj->info->missilestate); } if (player->powers[pw_shield] & SH_FORCE) @@ -2005,14 +2008,14 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->standingslope = mobj->standingslope; if (mobj->flags2 & MF2_OBJECTFLIP) - ghost->flags |= MF2_OBJECTFLIP; + ghost->flags2 |= MF2_OBJECTFLIP; if (mobj->player && mobj->player->followmobj) { mobj_t *ghost2 = P_SpawnGhostMobj(mobj->player->followmobj); P_SetTarget(&ghost2->tracer, ghost); P_SetTarget(&ghost->tracer, ghost2); - P_SetTarget(&ghost2->dontdrawforviewmobj, mobj); // Hide the follow-ghost for the non-follow object + P_SetTarget(&ghost2->dontdrawforviewmobj, mobj); // Hide the follow-ghost for the non-follow target ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW); } @@ -8717,7 +8720,10 @@ void P_MovePlayer(player_t *player) player->mo->height = P_GetPlayerHeight(player); if (player->mo->eflags & MFE_VERTICALFLIP && player->mo->height != oldheight) // adjust z height for reverse gravity, similar to how it's done for scaling - player->mo->z -= player->mo->height - oldheight; + { + player->mo->z -= player->mo->height - oldheight; + player->mo->old_z -= player->mo->height - oldheight; // Snap the Z adjustment, while keeping the Z interpolation + } // Crush test... if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) @@ -11507,7 +11513,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) } fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it - fume->eflags = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity! + fume->flags2 = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity! fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity! // Finally, set its position @@ -11758,7 +11764,7 @@ void P_PlayerThink(player_t *player) if (!total || ((4*exiting)/total) >= numneeded) { if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } else player->exiting = 3; @@ -11766,7 +11772,7 @@ void P_PlayerThink(player_t *player) else { if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + D_SendExitLevel(false); } } @@ -11864,7 +11870,7 @@ void P_PlayerThink(player_t *player) mo2 = (mobj_t *)th; if (!(mo2->type == MT_RING || mo2->type == MT_COIN - || mo2->type == MT_BLUESPHERE || mo2->type == MT_BOMBSPHERE + || mo2->type == MT_BLUESPHERE // || mo2->type == MT_BOMBSPHERE || mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR)) continue; diff --git a/src/r_bbox.c b/src/r_bbox.c index 4302d1b9a..cf417ec37 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -34,7 +34,7 @@ static CV_PossibleValue_t renderhitbox_cons_t[] = { {RENDERHITBOX_RINGS, "Rings"}, {0}}; -consvar_t cv_renderhitbox = CVAR_INIT ("renderhitbox", "Off", CV_CHEAT, renderhitbox_cons_t, NULL); +consvar_t cv_renderhitbox = CVAR_INIT ("renderhitbox", "Off", CV_CHEAT|CV_NOTINNET, renderhitbox_cons_t, NULL); consvar_t cv_renderhitboxinterpolation = CVAR_INIT ("renderhitbox_interpolation", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_renderhitboxgldepth = CVAR_INIT ("renderhitbox_gldepth", "Off", CV_SAVE, CV_OnOff, NULL); @@ -268,6 +268,9 @@ boolean R_ThingBoundingBoxVisible(mobj_t *thing) { INT32 cvmode = cv_renderhitbox.value; + if (multiplayer) // No hitboxes in multiplayer to avoid cheating + return false; + // Do not render bbox for these switch (thing->type) { diff --git a/src/r_defs.h b/src/r_defs.h index a9b9a4a08..dfd2d6d70 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -757,12 +757,12 @@ typedef struct drawseg_s // Pointers to lists for sprite clipping, all three adjusted so [x1] is first value. INT16 *sprtopclip; INT16 *sprbottomclip; - INT16 *maskedtexturecol; + fixed_t *maskedtexturecol; struct visplane_s *ffloorplanes[MAXFFLOORS]; INT32 numffloorplanes; struct ffloor_s *thicksides[MAXFFLOORS]; - INT16 *thicksidecol; + fixed_t *thicksidecol; INT32 numthicksides; fixed_t frontscale[MAXVIDWIDTH]; diff --git a/src/r_fps.c b/src/r_fps.c index c6eb59482..de450aaa7 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -292,6 +292,8 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out) out->y = mobj->y; out->z = mobj->z; out->scale = mobj->scale; + out->radius = mobj->radius; + out->height = mobj->height; out->subsector = mobj->subsector; out->angle = mobj->player ? mobj->player->drawangle : mobj->angle; out->pitch = mobj->pitch; @@ -307,10 +309,22 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out) out->x = R_LerpFixed(mobj->old_x, mobj->x, frac); out->y = R_LerpFixed(mobj->old_y, mobj->y, frac); out->z = R_LerpFixed(mobj->old_z, mobj->z, frac); - out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac); out->spritexscale = mobj->resetinterp ? mobj->spritexscale : R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac); out->spriteyscale = mobj->resetinterp ? mobj->spriteyscale : R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac); + if (mobj->scale == mobj->old_scale) // Tiny optimisation - scale is usually unchanging, so let's skip a lerp, two FixedMuls, and two FixedDivs + { + out->scale = mobj->scale; + out->radius = mobj->radius; + out->height = mobj->height; + } + else + { + out->scale = R_LerpFixed(mobj->old_scale, mobj->scale, frac); + out->radius = FixedMul(mobj->radius, FixedDiv(out->scale, mobj->scale)); + out->height = FixedMul(mobj->height, FixedDiv(out->scale, mobj->scale)); + } + // Sprite offsets are not interpolated until we have a way to interpolate them explicitly in Lua. // It seems existing mods visually break more often than not if it is interpolated. out->spritexoffset = mobj->spritexoffset; @@ -340,6 +354,8 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst out->y = mobj->y; out->z = mobj->z; out->scale = FRACUNIT; + out->radius = mobj->radius; + out->height = mobj->height; out->subsector = mobj->subsector; out->angle = mobj->angle; out->pitch = mobj->angle; @@ -356,6 +372,8 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst out->y = R_LerpFixed(mobj->old_y, mobj->y, frac); out->z = R_LerpFixed(mobj->old_z, mobj->z, frac); out->scale = FRACUNIT; + out->radius = mobj->radius; + out->height = mobj->height; out->spritexscale = R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac); out->spriteyscale = R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac); out->spritexoffset = R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac); diff --git a/src/r_fps.h b/src/r_fps.h index 9a8bfa38a..f43d29f30 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -63,6 +63,8 @@ typedef struct { angle_t roll; angle_t spriteroll; fixed_t scale; + fixed_t radius; + fixed_t height; fixed_t spritexscale; fixed_t spriteyscale; fixed_t spritexoffset; diff --git a/src/r_main.c b/src/r_main.c index 55bb9c4ff..54f7d7639 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -41,16 +41,6 @@ #include "hardware/hw_main.h" #endif -//profile stuff --------------------------------------------------------- -//#define TIMING -#ifdef TIMING -#include "p5prof.h" -INT64 mycount; -INT64 mytotal = 0; -//unsigned long nombre = 100000; -#endif -//profile stuff --------------------------------------------------------- - // Fineangles in the SCREENWIDTH wide window. #define FIELDOFVIEW 2048 @@ -157,7 +147,8 @@ 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 ("ffloorclip", "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); @@ -1479,6 +1470,7 @@ void R_RenderPlayerView(player_t *player) R_ClearClipSegs(); } R_ClearDrawSegs(); + R_ClearSegTables(); R_ClearSprites(); Portal_InitList(); @@ -1489,29 +1481,17 @@ void R_RenderPlayerView(player_t *player) Mask_Pre(&masks[nummasks - 1]); curdrawsegs = ds_p; -//profile stuff --------------------------------------------------------- -#ifdef TIMING - mytotal = 0; - ProfZeroTimer(); -#endif ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; PS_START_TIMING(ps_bsptime); R_RenderBSPNode((INT32)numnodes - 1); PS_STOP_TIMING(ps_bsptime); - ps_numsprites.value.i = visspritecount; -#ifdef TIMING - RDMSR(0x10, &mycount); - mytotal += mycount; // 64bit add - - CONS_Debug(DBG_RENDER, "RenderBSPNode: 0x%d %d\n", *((INT32 *)&mytotal + 1), (INT32)mytotal); -#endif -//profile stuff --------------------------------------------------------- Mask_Post(&masks[nummasks - 1]); PS_START_TIMING(ps_sw_spritecliptime); R_ClipSprites(drawsegs, NULL); PS_STOP_TIMING(ps_sw_spritecliptime); + ps_numsprites.value.i = numvisiblesprites; // Add skybox portals caused by sky visplanes. if (cv_skybox.value && skyboxmo[0]) @@ -1602,6 +1582,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_shadow); CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_ffloorclip); + CV_RegisterVar(&cv_spriteclip); CV_RegisterVar(&cv_cam_dist); CV_RegisterVar(&cv_cam_still); diff --git a/src/r_main.h b/src/r_main.h index f08070d0f..a6fb42ba2 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -114,7 +114,7 @@ extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_shadow; -extern consvar_t cv_ffloorclip; +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; diff --git a/src/r_plane.c b/src/r_plane.c index c568484b6..29ce26b29 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -53,10 +53,6 @@ INT32 numffloors; #define visplane_hash(picnum,lightlevel,height) \ ((unsigned)((picnum)*3+(lightlevel)+(height)*7) & VISPLANEHASHMASK) -//SoM: 3/23/2000: Use boom opening limit removal -size_t maxopenings; -INT16 *openings, *lastopening; /// \todo free leak - // // Clip values are the solid pixel bounding the range. // floorclip starts out SCREENHEIGHT @@ -366,8 +362,6 @@ void R_ClearPlanes(void) freehead = &(*freehead)->next; } - lastopening = openings; - // texture calculation memset(cachedheight, 0, sizeof (cachedheight)); } diff --git a/src/r_plane.h b/src/r_plane.h index 9870a43e2..917e8b041 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -60,9 +60,6 @@ extern visplane_t *floorplane; extern visplane_t *ceilingplane; // Visplane related. -extern INT16 *lastopening, *openings; -extern size_t maxopenings; - extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH]; extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16]; extern fixed_t cachedheight[MAXVIDHEIGHT]; diff --git a/src/r_segs.c b/src/r_segs.c index facab62ab..9af83f0c7 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -71,9 +71,22 @@ static fixed_t topfrac, topstep; static fixed_t bottomfrac, bottomstep; static lighttable_t **walllights; -static INT16 *maskedtexturecol; +static fixed_t *maskedtexturecol; static fixed_t *maskedtextureheight = NULL; +//SoM: 3/23/2000: Use boom opening limit removal +static size_t numopenings; +static INT16 *openings, *lastopening; + +static size_t texturecolumntablesize; +static fixed_t *texturecolumntable, *curtexturecolumntable; + +void R_ClearSegTables(void) +{ + lastopening = openings; + curtexturecolumntable = texturecolumntable; +} + // ========================================================================== // R_RenderMaskedSegRange // ========================================================================== @@ -350,170 +363,115 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; else dc_texturemid -= (textureheight[texnum])*times; - // calculate lighting - if (maskedtexturecol[dc_x] != INT16_MAX) + + // Check for overflows first + overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) { - // Check for overflows first - overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); - if (overflow_test < 0) overflow_test = -overflow_test; - if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) + // Eh, no, go away, don't waste our time + if (dc_numlights) { - // Eh, no, go away, don't waste our time - if (dc_numlights) + for (i = 0; i < dc_numlights; i++) { - for (i = 0; i < dc_numlights; i++) + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + } + } + spryscale += rw_scalestep; + continue; + } + + // calculate lighting + if (dc_numlights) + { + lighttable_t **xwalllights; + + sprbotscreen = INT32_MAX; + sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale)); + + realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // draw the texture + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3); + + for (i = 0; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + + if ((rlight->flags & FOF_NOSHADE)) + continue; + + if (rlight->lightnum < 0) + xwalllights = scalelight[0]; + else if (rlight->lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[rlight->lightnum]; + + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + + height = rlight->height; + rlight->height += rlight->heightstep; + + if (height <= windowtop) + { + dc_colormap = rlight->rcolormap; + continue; + } + + windowbottom = height; + if (windowbottom >= realbot) + { + windowbottom = realbot; + colfunc_2s(col); + for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; rlight->height += rlight->heightstep; } + + continue; } - spryscale += rw_scalestep; - continue; - } - - if (dc_numlights) - { - lighttable_t **xwalllights; - - sprbotscreen = INT32_MAX; - sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - - realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); - - for (i = 0; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - - if ((rlight->flags & FOF_NOSHADE)) - continue; - - if (rlight->lightnum < 0) - xwalllights = scalelight[0]; - else if (rlight->lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; - else - xwalllights = scalelight[rlight->lightnum]; - - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - - height = rlight->height; - rlight->height += rlight->heightstep; - - if (height <= windowtop) - { - dc_colormap = rlight->rcolormap; - continue; - } - - windowbottom = height; - if (windowbottom >= realbot) - { - windowbottom = realbot; - colfunc_2s(col); - for (i++; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height += rlight->heightstep; - } - - continue; - } - colfunc_2s(col); - windowtop = windowbottom + 1; - dc_colormap = rlight->rcolormap; - } - windowbottom = realbot; - if (windowtop < windowbottom) - colfunc_2s(col); - - spryscale += rw_scalestep; - continue; - } - - // calculate lighting - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - dc_colormap = walllights[pindex]; - - if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); - -#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red - if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) - { - fixed_t my_topscreen; - fixed_t my_bottomscreen; - fixed_t my_yl, my_yh; - - my_topscreen = sprtopscreen + spryscale*col->topdelta; - my_bottomscreen = sprbotscreen == INT32_MAX ? my_topscreen + spryscale*col->length - : sprbotscreen + spryscale*col->length; - - my_yl = (my_topscreen+FRACUNIT-1)>>FRACBITS; - my_yh = (my_bottomscreen-1)>>FRACBITS; - // CONS_Debug(DBG_RENDER, "my_topscreen: %d\nmy_bottomscreen: %d\nmy_yl: %d\nmy_yh: %d\n", my_topscreen, my_bottomscreen, my_yl, my_yh); - - if (numffloors) - { - INT32 top = my_yl; - INT32 bottom = my_yh; - - for (i = 0; i < numffloors; i++) - { - if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg) - continue; - - if (ffloor[i].height < viewz) - { - INT32 top_w = ffloor[i].plane->top[dc_x]; - - // CONS_Debug(DBG_RENDER, "Leveltime : %d\n", leveltime); - // CONS_Debug(DBG_RENDER, "Top is %d, top_w is %d\n", top, top_w); - if (top_w < top) - { - ffloor[i].plane->top[dc_x] = (INT16)top; - ffloor[i].plane->picnum = 0; - } - // CONS_Debug(DBG_RENDER, "top_w is now %d\n", ffloor[i].plane->top[dc_x]); - } - else if (ffloor[i].height > viewz) - { - INT32 bottom_w = ffloor[i].plane->bottom[dc_x]; - - if (bottom_w > bottom) - { - ffloor[i].plane->bottom[dc_x] = (INT16)bottom; - ffloor[i].plane->picnum = 0; - } - } - } - } - } - else -#endif colfunc_2s(col); + windowtop = windowbottom + 1; + dc_colormap = rlight->rcolormap; + } + windowbottom = realbot; + if (windowtop < windowbottom) + colfunc_2s(col); + + spryscale += rw_scalestep; + continue; } + + // calculate lighting + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + dc_colormap = walllights[pindex]; + + if (frontsector->extra_colormap) + dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // draw the texture + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3); + colfunc_2s(col); + spryscale += rw_scalestep; } } @@ -857,183 +815,182 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // draw the columns for (dc_x = x1; dc_x <= x2; dc_x++) { - if (maskedtexturecol[dc_x] != INT16_MAX) + // skew FOF walls + if (ffloortextureslide) { - if (ffloortextureslide) { // skew FOF walls - if (oldx != -1) - dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])< (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; - else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; - else sprtopscreen = windowtop = CLAMPMIN; - if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; - else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; - else sprbotscreen = windowbottom = CLAMPMIN; + // Calculate bounds + // clamp the values if necessary to avoid overflows and rendering glitches caused by them + if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; + else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; + else sprtopscreen = windowtop = CLAMPMIN; + if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; + else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; + else sprbotscreen = windowbottom = CLAMPMIN; - top_frac += top_step; - bottom_frac += bottom_step; + top_frac += top_step; + bottom_frac += bottom_step; - // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) + // SoM: If column is out of range, why bother with it?? + if (windowbottom < topbounds || windowtop > bottombounds) + { + if (dc_numlights) { - if (dc_numlights) + for (i = 0; i < dc_numlights; i++) { - for (i = 0; i < dc_numlights; i++) + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + if (rlight->flags & FOF_CUTLEVEL) + rlight->botheight += rlight->botheightstep; + } + } + spryscale += rw_scalestep; + continue; + } + + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // Get data for the column + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3); + + // SoM: New code does not rely on R_DrawColumnShadowed_8 which + // will (hopefully) put less strain on the stack. + if (dc_numlights) + { + lighttable_t **xwalllights; + fixed_t height; + fixed_t bheight = 0; + INT32 solid = 0; + INT32 lighteffect = 0; + + for (i = 0; i < dc_numlights; i++) + { + // Check if the current light effects the colormap/lightlevel + rlight = &dc_lightlist[i]; + lighteffect = !(dc_lightlist[i].flags & FOF_NOSHADE); + if (lighteffect) + { + lightnum = rlight->lightnum; + + if (lightnum < 0) + xwalllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[lightnum]; + + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE-1; + + if (pfloor->fofflags & FOF_FOG) + { + if (pfloor->master->frontsector->extra_colormap) + rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + } + else + { + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + } + } + + solid = 0; // don't carry over solid-cutting flag from the previous light + + // Check if the current light can cut the current 3D floor. + if (rlight->flags & FOF_CUTSOLIDS && !(pfloor->fofflags & FOF_EXTRA)) + solid = 1; + else if (rlight->flags & FOF_CUTEXTRA && pfloor->fofflags & FOF_EXTRA) + { + if (rlight->flags & FOF_EXTRA) + { + // The light is from an extra 3D floor... Check the flags so + // there are no undesired cuts. + if ((rlight->flags & (FOF_FOG|FOF_SWIMMABLE)) == (pfloor->fofflags & (FOF_FOG|FOF_SWIMMABLE))) + solid = 1; + } + else + solid = 1; + } + else + solid = 0; + + height = rlight->height; + rlight->height += rlight->heightstep; + + if (solid) + { + bheight = rlight->botheight - (FRACUNIT >> 1); + rlight->botheight += rlight->botheightstep; + } + + if (height <= windowtop) + { + if (lighteffect) + dc_colormap = rlight->rcolormap; + if (solid && windowtop < bheight) + windowtop = bheight; + continue; + } + + windowbottom = height; + if (windowbottom >= sprbotscreen) + { + windowbottom = sprbotscreen; + // draw the texture + colfunc_2s (col); + for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; rlight->height += rlight->heightstep; if (rlight->flags & FOF_CUTLEVEL) rlight->botheight += rlight->botheightstep; } + continue; } - spryscale += rw_scalestep; - continue; + // draw the texture + colfunc_2s (col); + if (solid) + windowtop = bheight; + else + windowtop = windowbottom + 1; + if (lighteffect) + dc_colormap = rlight->rcolormap; } + windowbottom = sprbotscreen; + // draw the texture, if there is any space left + if (windowtop < windowbottom) + colfunc_2s (col); - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // Get data for the column - col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); - - // SoM: New code does not rely on R_DrawColumnShadowed_8 which - // will (hopefully) put less strain on the stack. - if (dc_numlights) - { - lighttable_t **xwalllights; - fixed_t height; - fixed_t bheight = 0; - INT32 solid = 0; - INT32 lighteffect = 0; - - for (i = 0; i < dc_numlights; i++) - { - // Check if the current light effects the colormap/lightlevel - rlight = &dc_lightlist[i]; - lighteffect = !(dc_lightlist[i].flags & FOF_NOSHADE); - if (lighteffect) - { - lightnum = rlight->lightnum; - - if (lightnum < 0) - xwalllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; - else - xwalllights = scalelight[lightnum]; - - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE-1; - - if (pfloor->fofflags & FOF_FOG) - { - if (pfloor->master->frontsector->extra_colormap) - rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } - else - { - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } - } - - solid = 0; // don't carry over solid-cutting flag from the previous light - - // Check if the current light can cut the current 3D floor. - if (rlight->flags & FOF_CUTSOLIDS && !(pfloor->fofflags & FOF_EXTRA)) - solid = 1; - else if (rlight->flags & FOF_CUTEXTRA && pfloor->fofflags & FOF_EXTRA) - { - if (rlight->flags & FOF_EXTRA) - { - // The light is from an extra 3D floor... Check the flags so - // there are no undesired cuts. - if ((rlight->flags & (FOF_FOG|FOF_SWIMMABLE)) == (pfloor->fofflags & (FOF_FOG|FOF_SWIMMABLE))) - solid = 1; - } - else - solid = 1; - } - else - solid = 0; - - height = rlight->height; - rlight->height += rlight->heightstep; - - if (solid) - { - bheight = rlight->botheight - (FRACUNIT >> 1); - rlight->botheight += rlight->botheightstep; - } - - if (height <= windowtop) - { - if (lighteffect) - dc_colormap = rlight->rcolormap; - if (solid && windowtop < bheight) - windowtop = bheight; - continue; - } - - windowbottom = height; - if (windowbottom >= sprbotscreen) - { - windowbottom = sprbotscreen; - // draw the texture - colfunc_2s (col); - for (i++; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height += rlight->heightstep; - if (rlight->flags & FOF_CUTLEVEL) - rlight->botheight += rlight->botheightstep; - } - continue; - } - // draw the texture - colfunc_2s (col); - if (solid) - windowtop = bheight; - else - windowtop = windowbottom + 1; - if (lighteffect) - dc_colormap = rlight->rcolormap; - } - windowbottom = sprbotscreen; - // draw the texture, if there is any space left - if (windowtop < windowbottom) - colfunc_2s (col); - - spryscale += rw_scalestep; - continue; - } - - // calculate lighting - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - dc_colormap = walllights[pindex]; - - if (pfloor->fofflags & FOF_FOG && pfloor->master->frontsector->extra_colormap) - dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - else if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - - // draw the texture - colfunc_2s (col); spryscale += rw_scalestep; + continue; } + + // calculate lighting + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + dc_colormap = walllights[pindex]; + + if (pfloor->fofflags & FOF_FOG && pfloor->master->frontsector->extra_colormap) + dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + else if (frontsector->extra_colormap) + dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + + // draw the texture + colfunc_2s (col); + spryscale += rw_scalestep; } colfunc = colfuncs[BASEDRAWFUNC]; @@ -1270,7 +1227,7 @@ static void R_RenderSegLoop (void) } oldtexturecolumn = texturecolumn; - texturecolumn >>= FRACBITS; + INT32 itexturecolumn = texturecolumn >> FRACBITS; // texturecolumn and lighting are independent of wall tiers if (segtextured) @@ -1336,7 +1293,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = yh; dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn + (rw_offset_mid>>FRACBITS)); + dc_source = R_GetColumn(midtexture, itexturecolumn + (rw_offset_mid>>FRACBITS)); dc_texheight = textureheight[midtexture]>>FRACBITS; //profile stuff --------------------------------------------------------- @@ -1397,7 +1354,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = mid; dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn + (rw_offset_top>>FRACBITS)); + dc_source = R_GetColumn(toptexture, itexturecolumn + (rw_offset_top>>FRACBITS)); dc_texheight = textureheight[toptexture]>>FRACBITS; colfunc(); ceilingclip[rw_x] = (INT16)mid; @@ -1433,8 +1390,7 @@ static void R_RenderSegLoop (void) dc_yl = mid; dc_yh = yh; dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, - texturecolumn + (rw_offset_bot>>FRACBITS)); + dc_source = R_GetColumn(bottomtexture, itexturecolumn + (rw_offset_bot>>FRACBITS)); dc_texheight = textureheight[bottomtexture]>>FRACBITS; colfunc(); floorclip[rw_x] = (INT16)mid; @@ -1453,7 +1409,7 @@ static void R_RenderSegLoop (void) { // save texturecol // for backdrawing of masked mid texture - maskedtexturecol[rw_x] = (INT16)(texturecolumn + (rw_offset_mid>>FRACBITS)); + maskedtexturecol[rw_x] = texturecolumn + rw_offset_mid; if (maskedtextureheight != NULL) { maskedtextureheight[rw_x] = (curline->linedef->flags & ML_MIDPEG) ? @@ -1512,6 +1468,73 @@ static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2) } } +//SoM: Code to remove limits on openings. +static void R_AllocClippingTables(size_t range) +{ + size_t pos = lastopening - openings; + size_t need = range * 2; // for both sprtopclip and sprbottomclip + + if (pos + need < numopenings) + return; + + INT16 *oldopenings = openings; + INT16 *oldlast = lastopening; + + if (numopenings == 0) + numopenings = 16384; + + numopenings += need; + openings = Z_Realloc(openings, numopenings * sizeof (*openings), PU_STATIC, NULL); + lastopening = openings + pos; + + if (oldopenings == NULL) + return; + + // borrowed fix from *cough* zdoom *cough* + // [RH] We also need to adjust the openings pointers that + // were already stored in drawsegs. + for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) + { + // Check if it's in range of the openings + if (ds->sprtopclip + ds->x1 >= oldopenings && ds->sprtopclip + ds->x1 <= oldlast) + ds->sprtopclip = (ds->sprtopclip - oldopenings) + openings; + if (ds->sprbottomclip + ds->x1 >= oldopenings && ds->sprbottomclip + ds->x1 <= oldlast) + ds->sprbottomclip = (ds->sprbottomclip - oldopenings) + openings; + } +} + +static void R_AllocTextureColumnTables(size_t range) +{ + size_t pos = curtexturecolumntable - texturecolumntable; + + // For both tables, we reserve exactly an amount of memory that's equivalent to + // how many columns the seg will take on the entire screen (think about it) + if (pos + range < texturecolumntablesize) + return; + + fixed_t *oldtable = texturecolumntable; + fixed_t *oldlast = curtexturecolumntable; + + if (texturecolumntablesize == 0) + texturecolumntablesize = 16384; + + texturecolumntablesize += range; + texturecolumntable = Z_Realloc(texturecolumntable, texturecolumntablesize * sizeof (*texturecolumntable), PU_STATIC, NULL); + curtexturecolumntable = texturecolumntable + pos; + + if (oldtable == NULL) + return; + + 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; + } +} + // // R_StoreWallRange // A wall segment will be drawn @@ -1580,37 +1603,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->curline = curline; rw_stopx = stop+1; - //SoM: Code to remove limits on openings. - { - size_t pos = lastopening - openings; - size_t need = (rw_stopx - start)*4 + pos; - if (need > maxopenings) - { - drawseg_t *ds; //needed for fix from *cough* zdoom *cough* - INT16 *oldopenings = openings; - INT16 *oldlast = lastopening; - - do - maxopenings = maxopenings ? maxopenings*2 : 16384; - while (need > maxopenings); - openings = Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL); - lastopening = openings + pos; - - // borrowed fix from *cough* zdoom *cough* - // [RH] We also need to adjust the openings pointers that - // were already stored in drawsegs. - for (ds = drawsegs; ds < ds_p; ds++) - { -#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings; - ADJUST(maskedtexturecol); - ADJUST(sprtopclip); - ADJUST(sprbottomclip); - ADJUST(thicksidecol); -#undef ADJUST - } - } - } // end of code to remove limits on openings - // calculate scale at both ends and step ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); @@ -2026,6 +2018,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_toptexturemid += sidedef->rowoffset + sidedef->offsety_top; rw_bottomtexturemid += sidedef->rowoffset + sidedef->offsety_bot; + R_AllocTextureColumnTables(rw_stopx - start); + // allocate space for masked texture tables if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) { @@ -2040,8 +2034,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) //markceiling = markfloor = true; maskedtexture = true; - ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; + ds_p->thicksidecol = maskedtexturecol = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; lowcut = max(worldbottom, worldlow) + viewz; highcut = min(worldtop, worldhigh) + viewz; @@ -2224,8 +2218,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) // masked midtexture if (!ds_p->thicksidecol) { - ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; + ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; } else ds_p->maskedtexturecol = ds_p->thicksidecol; @@ -2737,29 +2731,34 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->portalpass = 0; // save sprite clipping info - if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM))) { - M_Memcpy(lastopening, ceilingclip+start, 2*(rw_stopx - start)); - ds_p->sprtopclip = lastopening - start; - lastopening += rw_stopx - start; - } + R_AllocClippingTables(rw_stopx - start); - if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) - { - M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx-start)); - ds_p->sprbottomclip = lastopening - start; - lastopening += rw_stopx - start; + if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + { + M_Memcpy(lastopening, ceilingclip + start, 2*(rw_stopx - start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; + } + + if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) + { + M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx - start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; + } } if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) { ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX; + ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN : INT32_MAX; } if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) { ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; + ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX : INT32_MIN; } ds_p++; } diff --git a/src/r_segs.h b/src/r_segs.h index 09c68b27e..cad014674 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -22,5 +22,6 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha); void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor); void R_StoreWallRange(INT32 start, INT32 stop); +void R_ClearSegTables(void); #endif diff --git a/src/r_skins.c b/src/r_skins.c index 4b72d9a27..308cee8d6 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -113,6 +113,7 @@ static void Sk_SetDefaultValue(skin_t *skin) strcpy(skin->realname, "Someone"); strcpy(skin->hudname, "???"); + strcpy(skin->supername, "Someone super"); skin->starttranscolor = 96; skin->prefcolor = SKINCOLOR_GREEN; @@ -693,7 +694,7 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile) char *value; size_t size; skin_t *skin; - boolean hudname, realname; + boolean hudname, realname, supername; // // search for all skin markers in pwad @@ -723,7 +724,7 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile) skin = &skins[numskins]; Sk_SetDefaultValue(skin); skin->wadnum = wadnum; - hudname = realname = false; + hudname = realname = supername = false; // parse stoken = strtok (buf2, "\r\n= "); while (stoken) @@ -766,7 +767,7 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile) Z_Free(value2); } - // copy to hudname and fullname as a default. + // copy to hudname, realname, and supername as a default. if (!realname) { STRBUFCPY(skin->realname, skin->name); @@ -782,6 +783,19 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile) strupr(skin->hudname); SYMBOLCONVERT(skin->hudname) } + if (!supername) + { + char superstring[SKINNAMESIZE+7]; + strcpy(superstring, "Super "); + strlcat(superstring, skin->name, sizeof(superstring)); + STRBUFCPY(skin->supername, superstring); + } + } + else if (!stricmp(stoken, "supername")) + { // Super name (eg. "Super Knuckles") + supername = true; + STRBUFCPY(skin->supername, value); + SYMBOLCONVERT(skin->supername) } else if (!stricmp(stoken, "realname")) { // Display name (eg. "Knuckles") @@ -790,6 +804,13 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile) SYMBOLCONVERT(skin->realname) if (!hudname) HUDNAMEWRITE(skin->realname); + if (!supername) //copy over default to capitalise the name + { + char superstring[SKINNAMESIZE+7]; + strcpy(superstring, "Super "); + strlcat(superstring, skin->realname, sizeof(superstring)); + STRBUFCPY(skin->supername, superstring); + } } else if (!stricmp(stoken, "hudname")) { // Life icon name (eg. "K.T.E") @@ -842,7 +863,7 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile) char *value; size_t size; skin_t *skin; - boolean noskincomplain, realname, hudname; + boolean noskincomplain, realname, hudname, supername; // // search for all skin patch markers in pwad @@ -866,7 +887,7 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile) buf2[size] = '\0'; skin = NULL; - noskincomplain = realname = hudname = false; + noskincomplain = realname = hudname = supername = false; /* Parse. Has more phases than the parser in R_AddSkins because it needs to have the patching name first (no default skin name is acceptible for patching, unlike skin creation) @@ -905,13 +926,26 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile) else // Get the properties! { // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. - if (!stricmp(stoken, "realname")) + if (!stricmp(stoken, "supername")) + { // Super name (eg. "Super Knuckles") + supername = true; + STRBUFCPY(skin->supername, value); + SYMBOLCONVERT(skin->supername) + } + else if (!stricmp(stoken, "realname")) { // Display name (eg. "Knuckles") realname = true; STRBUFCPY(skin->realname, value); SYMBOLCONVERT(skin->realname) if (!hudname) HUDNAMEWRITE(skin->realname); + if (!supername) //copy over default to capitalise the name + { + char superstring[SKINNAMESIZE+7]; + strcpy(superstring, "Super "); + strlcat(superstring, skin->realname, sizeof(superstring)); + STRBUFCPY(skin->supername, superstring); + } } else if (!stricmp(stoken, "hudname")) { // Life icon name (eg. "K.T.E") diff --git a/src/r_skins.h b/src/r_skins.h index 70164ff7a..bf2275a49 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -35,8 +35,9 @@ typedef struct UINT16 wadnum; skinflags_t flags; - char realname[SKINNAMESIZE+1]; // Display name for level completion. + char realname[SKINNAMESIZE+1]; // Display name for level completion char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long) + char supername[SKINNAMESIZE+7]; // Super name to display when collecting all emeralds UINT8 ability; // ability definition UINT8 ability2; // secondary ability definition diff --git a/src/r_splats.c b/src/r_splats.c index 737b6d110..0b482d798 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -314,9 +314,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr fixed_t planeheight = 0; fixed_t step; - int spanfunctype = SPANDRAWFUNC_SPRITE; - - prepare_rastertab(); + int spanfunctype; #define RASTERPARAMS(vnum1, vnum2, tv1, tv2, tc, dir) \ x1 = verts[vnum1].x; \ @@ -367,21 +365,15 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr if (ry1 > maxy) \ maxy = ry1; - // do segment a -> top of texture - RASTERPARAMS(3,2,0,pSplat->width-1,0,0); - // do segment b -> right side of texture - RASTERPARAMS(2,1,0,pSplat->width-1,pSplat->height-1,0); - // do segment c -> bottom of texture - RASTERPARAMS(1,0,pSplat->width-1,0,pSplat->height-1,0); - // do segment d -> left side of texture - RASTERPARAMS(0,3,pSplat->width-1,0,0,1); - ds_source = (UINT8 *)pSplat->pic; ds_flatwidth = pSplat->width; ds_flatheight = pSplat->height; - ds_powersoftwo = false; - if (R_CheckPowersOfTwo()) + ds_powersoftwo = ds_solidcolor = false; + + if (R_CheckSolidColorFlat()) + ds_solidcolor = true; + else if (R_CheckPowersOfTwo()) { R_SetFlatVars(ds_flatwidth * ds_flatheight); ds_powersoftwo = true; @@ -392,9 +384,8 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr R_SetTiltedSpan(0); R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle); R_CalculateSlopeVectors(); - spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; } - else + else if (!ds_solidcolor) { planeheight = abs(pSplat->z - vis->viewpoint.z); @@ -429,23 +420,70 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps]; } - if (vis->transmap) - { - ds_transmap = vis->transmap; + ds_transmap = vis->transmap; + // Determine which R_DrawWhatever to use + + // Solid color + if (ds_solidcolor) + { + UINT16 px = *(UINT16 *)ds_source; + + // Uh, it's not visible. + if (!(px & 0xFF00)) + return; + + // Pixel color is contained in the lower 8 bits (upper 8 are the opacity), so advance the pointer + ds_source++; + + if (pSplat->slope) + { + if (ds_transmap) + spanfunctype = SPANDRAWFUNC_TILTEDTRANSSOLID; + else + spanfunctype = SPANDRAWFUNC_TILTEDSOLID; + } + else + { + if (ds_transmap) + spanfunctype = SPANDRAWFUNC_TRANSSOLID; + else + spanfunctype = SPANDRAWFUNC_SOLID; + } + } + // Transparent + else if (ds_transmap) + { if (pSplat->slope) spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE; else spanfunctype = SPANDRAWFUNC_TRANSSPRITE; } + // Opaque else - ds_transmap = NULL; + { + if (pSplat->slope) + spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; + else + spanfunctype = SPANDRAWFUNC_SPRITE; + } - if (ds_powersoftwo) + if (ds_powersoftwo || ds_solidcolor) spanfunc = spanfuncs[spanfunctype]; else spanfunc = spanfuncs_npo2[spanfunctype]; + prepare_rastertab(); + + // do segment a -> top of texture + RASTERPARAMS(3,2,0,pSplat->width-1,0,0); + // do segment b -> right side of texture + RASTERPARAMS(2,1,0,pSplat->width-1,pSplat->height-1,0); + // do segment c -> bottom of texture + RASTERPARAMS(1,0,pSplat->width-1,0,pSplat->height-1,0); + // do segment d -> left side of texture + RASTERPARAMS(0,3,pSplat->width-1,0,0,1); + if (maxy >= vid.height) maxy = vid.height-1; @@ -500,7 +538,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr if (x2 < x1) continue; - if (!pSplat->slope) + if (!ds_solidcolor && !pSplat->slope) { fixed_t xstep, ystep; fixed_t distance, span; @@ -549,7 +587,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr rastertab[y].maxx = INT32_MIN; } - if (pSplat->angle && !pSplat->slope) + if (!ds_solidcolor && pSplat->angle && !pSplat->slope) memset(cachedheight, 0, sizeof(cachedheight)); } diff --git a/src/r_things.c b/src/r_things.c index 90b80dda8..be9c5cdff 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -524,7 +524,8 @@ void R_AddSpriteDefs(UINT16 wadnum) // // GAME FUNCTIONS // -UINT32 visspritecount; +UINT32 visspritecount, numvisiblesprites; + static UINT32 clippedvissprites; static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL}; @@ -598,7 +599,7 @@ void R_InitSprites(void) // void R_ClearSprites(void) { - visspritecount = clippedvissprites = 0; + visspritecount = numvisiblesprites = clippedvissprites = 0; } // @@ -844,6 +845,15 @@ static void R_DrawVisSprite(vissprite_t *vis) if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto } + // TODO This check should not be necessary. But Papersprites near to the camera will sometimes create invalid values + // for the vissprite's startfrac. This happens because they are not depth culled like other sprites. + // Someone who is more familiar with papersprites pls check and try to fix <3 + if (vis->startfrac < 0 || vis->startfrac > (patch->width << FRACBITS)) + { + // never draw vissprites with startfrac out of patch range + return; + } + colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; dc_translation = R_GetSpriteTranslation(vis); @@ -887,7 +897,7 @@ static void R_DrawVisSprite(vissprite_t *vis) frac = vis->startfrac; windowtop = windowbottom = sprbotscreen = INT32_MAX; - if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) + if (vis->cut & SC_SHADOW && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale); if (this_scale <= 0) this_scale = 1; @@ -897,10 +907,10 @@ static void R_DrawVisSprite(vissprite_t *vis) { vis->scale = FixedMul(vis->scale, this_scale); vis->scalestep = FixedMul(vis->scalestep, this_scale); - vis->xiscale = FixedDiv(vis->xiscale,this_scale); + vis->xiscale = FixedDiv(vis->xiscale, this_scale); vis->cut |= SC_ISSCALED; } - dc_texturemid = FixedDiv(dc_texturemid,this_scale); + dc_texturemid = FixedDiv(dc_texturemid, this_scale); } spryscale = vis->scale; @@ -1184,7 +1194,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) R_InterpolateMobjState(thing, FRACUNIT, &interp); } - halfHeight = interp.z + (thing->height >> 1); + halfHeight = interp.z + (interp.height >> 1); floorz = P_GetFloorZ(thing, interp.subsector->sector, interp.x, interp.y, NULL); ceilingz = P_GetCeilingZ(thing, interp.subsector->sector, interp.x, interp.y, NULL); @@ -1248,8 +1258,8 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) } } - if (isflipped ? (ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))) - : (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))) + if (isflipped ? (ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), interp.radius*3/2))) + : (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), interp.radius*3/2)))) { groundz = isflipped ? ceilingz : floorz; groundslope = NULL; @@ -1292,9 +1302,9 @@ static void R_SkewShadowSprite( //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); if (viewz < groundz) - *shadowyscale += FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); + *shadowyscale += FixedMul(FixedMul(interp.radius*2 / spriteheight, scalemul), zslope); else - *shadowyscale -= FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); + *shadowyscale -= FixedMul(FixedMul(interp.radius*2 / spriteheight, scalemul), zslope); *shadowyscale = abs((*shadowyscale)); *shadowskew = xslope; @@ -1345,20 +1355,18 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, return; } - floordiff = abs((isflipped ? thing->height : 0) + interp.z - groundz); + floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz); trans = floordiff / (100*FRACUNIT) + 3; if (trans >= 9) return; scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - if ((thing->scale != thing->old_scale) && (thing->scale >= FRACUNIT/1024)) // Interpolate shadows when scaling mobjs - scalemul = FixedMul(scalemul, FixedDiv(interp.scale, thing->scale)); patch = W_CachePatchName("DSHADOW", PU_SPRITE); xscale = FixedDiv(projection, tz); yscale = FixedDiv(projectiony, tz); - shadowxscale = FixedMul(thing->radius*2, scalemul); - shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz)); + shadowxscale = FixedMul(interp.radius*2, scalemul); + shadowyscale = FixedMul(FixedMul(interp.radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz)); shadowyscale = min(shadowyscale, shadowxscale) / patch->height; shadowxscale /= patch->width; shadowskew = 0; @@ -1484,8 +1492,8 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) // 0--2 // start in the (0) corner - gx = interp.x - thing->radius - viewx; - gy = interp.y - thing->radius - viewy; + gx = interp.x - interp.radius - viewx; + gy = interp.y - interp.radius - viewy; tz = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); @@ -1507,14 +1515,14 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) box = R_NewVisSprite(); box->mobj = thing; box->mobjflags = thing->flags; - box->thingheight = thing->height; + box->thingheight = interp.height; box->cut = SC_BBOX; box->gx = tx; box->gy = tz; - box->scale = 2 * FixedMul(thing->radius, viewsin); - box->xscale = 2 * FixedMul(thing->radius, viewcos); + box->scale = 2 * FixedMul(interp.radius, viewsin); + box->xscale = 2 * FixedMul(interp.radius, viewcos); box->pz = interp.z; box->pzt = box->pz + box->thingheight; @@ -1563,6 +1571,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t tr_x, tr_y; fixed_t tx, tz; fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! + fixed_t radius, height; // For drop shadows fixed_t sortscale, sortsplat = 0; fixed_t linkscale = 0; fixed_t sort_x = 0, sort_y = 0, sort_z; @@ -1638,6 +1647,8 @@ static void R_ProjectSprite(mobj_t *thing) } this_scale = interp.scale; + radius = interp.radius; // For drop shadows + height = interp.height; // Ditto // transform the origin point tr_x = interp.x - viewx; @@ -1758,9 +1769,6 @@ static void R_ProjectSprite(mobj_t *thing) I_Assert(lump < max_spritelumps); - if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) - this_scale = FixedMul(this_scale, ((skin_t *)thing->skin)->highresscale); - spr_width = spritecachedinfo[lump].width; spr_height = spritecachedinfo[lump].height; spr_offset = spritecachedinfo[lump].offset; @@ -1810,6 +1818,14 @@ static void R_ProjectSprite(mobj_t *thing) // calculate edges of the shape spritexscale = interp.spritexscale; spriteyscale = interp.spriteyscale; + + if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) + { + fixed_t highresscale = ((skin_t *)thing->skin)->highresscale; + spritexscale = FixedMul(spritexscale, highresscale); + spriteyscale = FixedMul(spriteyscale, highresscale); + } + if (spritexscale < 1 || spriteyscale < 1) return; @@ -1977,6 +1993,8 @@ static void R_ProjectSprite(mobj_t *thing) { R_InterpolateMobjState(thing, FRACUNIT, &tracer_interp); } + radius = tracer_interp.radius; // For drop shadows + height = tracer_interp.height; // Ditto tr_x = (tracer_interp.x + sort_x) - viewx; tr_y = (tracer_interp.y + sort_y) - viewy; @@ -2068,7 +2086,7 @@ static void R_ProjectSprite(mobj_t *thing) if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes - floordiff = abs((isflipped ? caster->height : 0) + casterinterp.z - groundz); + floordiff = abs((isflipped ? casterinterp.height : 0) + casterinterp.z - groundz); trans += ((floordiff / (100*FRACUNIT)) + 3); shadowscale = FixedMul(FRACUNIT - floordiff/640, casterinterp.scale); } @@ -2083,8 +2101,8 @@ static void R_ProjectSprite(mobj_t *thing) if (shadowdraw) { - spritexscale = FixedMul(thing->radius * 2, FixedMul(shadowscale, spritexscale)); - spriteyscale = FixedMul(thing->radius * 2, FixedMul(shadowscale, spriteyscale)); + spritexscale = FixedMul(radius * 2, FixedMul(shadowscale, spritexscale)); + spriteyscale = FixedMul(radius * 2, FixedMul(shadowscale, spriteyscale)); spriteyscale = FixedMul(spriteyscale, FixedDiv(abs(groundz - viewz), tz)); spriteyscale = min(spriteyscale, spritexscale) / patch->height; spritexscale /= patch->width; @@ -2099,7 +2117,7 @@ static void R_ProjectSprite(mobj_t *thing) { R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan); - gzt = (isflipped ? (interp.z + thing->height) : interp.z) + patch->height * spriteyscale / 2; + gzt = (isflipped ? (interp.z + height) : interp.z) + patch->height * spriteyscale / 2; gz = gzt - patch->height * spriteyscale; cut |= SC_SHEAR; @@ -2114,7 +2132,7 @@ static void R_ProjectSprite(mobj_t *thing) // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. // remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes! - gz = interp.z + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); + gz = interp.z + interp.height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); gzt = gz + FixedMul(spr_height, FixedMul(spriteyscale, this_scale)); } else @@ -2193,7 +2211,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->gy = interp.y; vis->gz = gz; vis->gzt = gzt; - vis->thingheight = thing->height; + vis->thingheight = height; vis->pz = interp.z; vis->pzt = vis->pz + vis->thingheight; vis->texturemid = FixedDiv(gzt - viewz, spriteyscale); @@ -2633,6 +2651,14 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e // bundle linkdraw for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev) { + // Remove this sprite if it was determined to not be visible + if (ds->cut & SC_NOTVISIBLE) + { + ds->next->prev = ds->prev; + ds->prev->next = ds->next; + continue; + } + if (!(ds->cut & SC_LINKDRAW)) continue; @@ -2659,21 +2685,27 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e continue; // don't connect if the tracer's top is cut off, but lower than the link's top - if ((dsfirst->cut & SC_TOP) - && dsfirst->szt > ds->szt) + if ((dsfirst->cut & SC_TOP) && dsfirst->szt > ds->szt) continue; // don't connect if the tracer's bottom is cut off, but higher than the link's bottom - if ((dsfirst->cut & SC_BOTTOM) - && dsfirst->sz < ds->sz) + if ((dsfirst->cut & SC_BOTTOM) && dsfirst->sz < ds->sz) continue; + // If the object isn't visible, then the bounding box isn't either + if (ds->cut & SC_BBOX && dsfirst->cut & SC_NOTVISIBLE) + ds->cut |= SC_NOTVISIBLE; + break; } // remove from chain ds->next->prev = ds->prev; ds->prev->next = ds->next; + + if (ds->cut & SC_NOTVISIBLE) + continue; + linkedvissprites++; if (dsfirst != &unsorted) @@ -2725,12 +2757,15 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e best = ds; } } - best->next->prev = best->prev; - best->prev->next = best->next; - best->next = vsprsortedhead; - best->prev = vsprsortedhead->prev; - vsprsortedhead->prev->next = best; - vsprsortedhead->prev = best; + if (best) + { + best->next->prev = best->prev; + best->prev->next = best->next; + best->next = vsprsortedhead; + best->prev = vsprsortedhead->prev; + vsprsortedhead->prev->next = best; + vsprsortedhead->prev = best; + } } } @@ -3161,6 +3196,44 @@ static void R_HeightSecClip(vissprite_t *spr, INT32 x1, INT32 x2) } } +static boolean R_CheckSpriteVisible(vissprite_t *spr, INT32 x1, INT32 x2) +{ + INT16 sz = spr->sz; + INT16 szt = spr->szt; + + fixed_t texturemid, yscale, scalestep = spr->scalestep; + INT32 height; + + if (scalestep) + { + height = spr->patch->height; + yscale = spr->scale; + scalestep = FixedMul(scalestep, spr->spriteyscale); + + if (spr->thingscale != FRACUNIT) + texturemid = FixedDiv(spr->texturemid, max(spr->thingscale, 1)); + else + texturemid = spr->texturemid; + } + + for (INT32 x = x1; x <= x2; x++) + { + if (scalestep) + { + fixed_t top = centeryfrac - FixedMul(texturemid, yscale); + fixed_t bottom = top + (height * yscale); + szt = (INT16)(top >> FRACBITS); + sz = (INT16)(bottom >> FRACBITS); + yscale += scalestep; + } + + if (spr->cliptop[x] < spr->clipbot[x] && sz > spr->cliptop[x] && szt < spr->clipbot[x]) + return true; + } + + return false; +} + // R_ClipVisSprite // Clips vissprites without drawing, so that portals can work. -Red static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal) @@ -3304,8 +3377,7 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port spr->clipbot[x] = (INT16)viewheight; if (spr->cliptop[x] == -2) - //Fab : 26-04-98: was -1, now clips against console bottom - spr->cliptop[x] = (INT16)con_clipviewtop; + spr->cliptop[x] = -1; } if (portal) @@ -3330,6 +3402,14 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port spr->cliptop[x] = -1; } } + + // Check if it'll be visible + // Not done for floorsprites. + if (cv_spriteclip.value && (spr->cut & SC_SPLAT) == 0) + { + if (!R_CheckSpriteVisible(spr, x1, x2)) + spr->cut |= SC_NOTVISIBLE; + } } void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) @@ -3398,8 +3478,19 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) { vissprite_t *spr = R_GetVisSprite(clippedvissprites); - if (spr->cut & SC_BBOX) + if (cv_spriteclip.value + && (spr->szt > vid.height || spr->sz < 0) + && !((spr->cut & SC_SPLAT) || spr->scalestep)) + { + spr->cut |= SC_NOTVISIBLE; continue; + } + + if (spr->cut & SC_BBOX) + { + numvisiblesprites++; + continue; + } INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1; INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2; @@ -3421,6 +3512,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) } R_ClipVisSprite(spr, x1, x2, portal); + + if ((spr->cut & SC_NOTVISIBLE) == 0) + numvisiblesprites++; } } diff --git a/src/r_things.h b/src/r_things.h index e11005363..318234886 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -123,21 +123,22 @@ typedef enum SC_NONE = 0, SC_TOP = 1, SC_BOTTOM = 1<<1, + SC_NOTVISIBLE = 1<<2, // other flags - SC_PRECIP = 1<<2, - SC_LINKDRAW = 1<<3, - SC_FULLBRIGHT = 1<<4, - SC_SEMIBRIGHT = 1<<5, - SC_FULLDARK = 1<<6, - SC_VFLIP = 1<<7, - SC_ISSCALED = 1<<8, - SC_ISROTATED = 1<<9, - SC_SHADOW = 1<<10, - SC_SHEAR = 1<<11, - SC_SPLAT = 1<<12, - SC_BBOX = 1<<13, + SC_PRECIP = 1<<3, + SC_LINKDRAW = 1<<4, + SC_FULLBRIGHT = 1<<5, + SC_SEMIBRIGHT = 1<<6, + SC_FULLDARK = 1<<7, + SC_VFLIP = 1<<8, + SC_ISSCALED = 1<<9, + SC_ISROTATED = 1<<10, + SC_SHADOW = 1<<11, + SC_SHEAR = 1<<12, + SC_SPLAT = 1<<13, + SC_BBOX = 1<<14, // masks - SC_CUTMASK = SC_TOP|SC_BOTTOM, + SC_CUTMASK = SC_TOP|SC_BOTTOM|SC_NOTVISIBLE, SC_FLAGMASK = ~SC_CUTMASK } spritecut_e; @@ -219,7 +220,7 @@ typedef struct vissprite_s INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing } vissprite_t; -extern UINT32 visspritecount; +extern UINT32 visspritecount, numvisiblesprites; void R_ClipSprites(drawseg_t* dsstart, portal_t* portal); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 075199a19..902194f4f 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -90,7 +90,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif #include -#include +#include #endif #endif @@ -325,8 +325,10 @@ static void write_backtrace(INT32 signal) static void I_ReportSignal(int num, int coredumped) { //static char msg[] = "oh no! back to reality!\r\n"; - const char *sigmsg, *sigttl; + const char *sigmsg, *signame; char ttl[128]; + char sigttl[512] = "Process killed by signal: "; + const char *reportmsg = "\n\nTo help us figure out the cause, you can visit our official Discord server\nwhere you will find more instructions on how to submit a crash report.\n\nSorry for the inconvenience!"; switch (num) { @@ -335,16 +337,16 @@ static void I_ReportSignal(int num, int coredumped) // sigmsg = "SRB2 was interrupted prematurely by the user."; // break; case SIGILL: - sigmsg = "SRB2 has attempted to execute an illegal instruction and needs to close. %s"; - sigttl = "SIGILL"; // illegal instruction - invalid function image + sigmsg = "SRB2 has attempted to execute an illegal instruction and needs to close."; + signame = "SIGILL"; // illegal instruction - invalid function image break; case SIGFPE: - sigmsg = "SRB2 has encountered a mathematical exception and needs to close. %s"; - sigttl = "SIGFPE"; // mathematical exception + sigmsg = "SRB2 has encountered a mathematical exception and needs to close."; + signame = "SIGFPE"; // mathematical exception break; case SIGSEGV: - sigmsg = "SRB2 has attempted to access a memory location that it shouldn't and needs to close. %s"; - sigttl = "SIGSEGV"; // segment violation + sigmsg = "SRB2 has attempted to access a memory location that it shouldn't and needs to close."; + signame = "SIGSEGV"; // segment violation break; // case SIGTERM: // sigmsg = "SRB2 was terminated by a kill signal."; @@ -355,34 +357,31 @@ static void I_ReportSignal(int num, int coredumped) // sigttl = "SIGBREAK" // Ctrl-Break sequence // break; case SIGABRT: - sigmsg = "SRB2 was terminated by an abort signal. %s"; - sigttl = "SIGABRT"; // abnormal termination triggered by abort call + sigmsg = "SRB2 was terminated by an abort signal."; + signame = "SIGABRT"; // abnormal termination triggered by abort call break; default: - sigmsg = "SRB2 was terminated by an unknown signal. %s"; + sigmsg = "SRB2 was terminated by an unknown signal."; sprintf(ttl, "number %d", num); if (coredumped) - sigttl = 0; + signame = 0; else - sigttl = ttl; + signame = ttl; } if (coredumped) { - if (sigttl) - sprintf(ttl, "%s (core dumped)", sigttl); + if (signame) + sprintf(ttl, "%s (core dumped)", signame); else strcat(ttl, " (core dumped)"); - sigttl = ttl; + signame = ttl; } - sprintf(ttl, "Process killed by signal: %s", sigttl); - - sigttl = ttl; - - I_OutputMsg("\n%s\n\n", sigttl); + strcat(sigttl, signame); + I_OutputMsg("%s\n", sigttl); if (M_CheckParm("-dedicated")) return; @@ -396,8 +395,7 @@ static void I_ReportSignal(int num, int coredumped) SDL_MESSAGEBOX_ERROR, /* .flags */ NULL, /* .window */ sigttl, /* .title */ - va(sigmsg, - "\n\nTo help us figure out the cause, you can visit our official Discord server\nwhere you will find more instructions on how to submit a crash report.\n\nSorry for the inconvenience!"), /* .message */ + va("%s %s", sigmsg, reportmsg), /* .message */ SDL_arraysize(buttons), /* .numbuttons */ buttons, /* .buttons */ NULL /* .colorScheme */ @@ -3035,40 +3033,17 @@ static long get_entry(const char* name, const char* buf) size_t I_GetFreeMem(size_t *total) { #ifdef FREEBSD - struct vmmeter sum; - kvm_t *kd; - struct nlist namelist[] = - { -#define X_SUM 0 - {"_cnt"}, - {NULL} - }; - if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL) - { - if (total) - *total = 0L; - return 0; - } - if (kvm_nlist(kd, namelist) != 0) - { - kvm_close (kd); - if (total) - *total = 0L; - return 0; - } - if (kvm_read(kd, namelist[X_SUM].n_value, &sum, - sizeof (sum)) != sizeof (sum)) - { - kvm_close(kd); - if (total) - *total = 0L; - return 0; - } - kvm_close(kd); + u_int v_free_count, v_page_size, v_page_count; + size_t size = sizeof(v_free_count); + sysctlbyname("vm.stat.vm.v_free_count", &v_free_count, &size, NULL, 0); + size_t size = sizeof(v_page_size); + sysctlbyname("vm.stat.vm.v_page_size", &v_page_size, &size, NULL, 0); + size_t size = sizeof(v_page_count); + sysctlbyname("vm.stat.vm.v_page_count", &v_page_count, &size, NULL, 0); if (total) - *total = sum.v_page_count * sum.v_page_size; - return sum.v_free_count * sum.v_page_size; + *total = v_page_count * v_page_size; + return v_free_count * v_page_size; #elif defined (SOLARIS) /* Just guess */ if (total) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index b2215f634..590d7d142 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1593,7 +1593,6 @@ boolean VID_CheckRenderer(void) else if (vid.glstate == VID_GL_LIBRARY_ERROR) rendererchanged = false; } - else #endif if (!contextcreated) diff --git a/src/st_stuff.c b/src/st_stuff.c index 1a6e944c8..de19c468f 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -174,7 +174,7 @@ static huddrawlist_h luahuddrawlist_titlecard; skincolornum_t linkColor[3][NUMLINKCOLORS] = { {SKINCOLOR_SHAMROCK, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT}, -{SKINCOLOR_EMERALD, SKINCOLOR_AQUAMARINE, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_GALAXY, SKINCOLOR_CRYSTAL, +{SKINCOLOR_EMERALD, SKINCOLOR_OCEAN, SKINCOLOR_AQUAMARINE, SKINCOLOR_SAPPHIRE, SKINCOLOR_GALAXY, SKINCOLOR_SIBERITE, SKINCOLOR_TAFFY, SKINCOLOR_RUBY, SKINCOLOR_GARNET, SKINCOLOR_TOPAZ, SKINCOLOR_LEMON, SKINCOLOR_LIME}, {SKINCOLOR_ISLAND, SKINCOLOR_TURQUOISE, SKINCOLOR_DREAM, SKINCOLOR_DAYBREAK, SKINCOLOR_VAPOR, SKINCOLOR_FUCHSIA, SKINCOLOR_VIOLET, SKINCOLOR_EVENTIDE, SKINCOLOR_KETCHUP, SKINCOLOR_FOUNDATION, SKINCOLOR_HEADLIGHT, SKINCOLOR_CHARTREUSE}}; @@ -2515,6 +2515,8 @@ num: static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset) { INT32 interval, i; + if (stplyr->mo == NULL) + return 0; // player just joined after spectating, can happen on custom gamemodes. UINT32 dist = ((UINT32)P_AproxDistance(P_AproxDistance(stplyr->mo->x - hunt->x, stplyr->mo->y - hunt->y), stplyr->mo->z - hunt->z))>>FRACBITS; if (dist < 128) diff --git a/src/string.c b/src/string.c index dd3080a97..2f16fa4c6 100644 --- a/src/string.c +++ b/src/string.c @@ -15,7 +15,7 @@ #include #include "doomdef.h" -#if !defined (__APPLE__) +#ifndef SRB2_HAVE_STRLCPY // Like the OpenBSD version, but it doesn't check for src not being a valid // C string. diff --git a/src/version.h b/src/version.h index 083c53134..3242cad67 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define SRB2VERSION "2.2.11"/* this must be the first line, for cmake !! */ +#define SRB2VERSION "2.2.13"/* this must be the first line, for cmake !! */ // The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/members/?key=ms_admin ). // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. @@ -9,7 +9,7 @@ // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1". -#define MODVERSION 52 +#define MODVERSION 54 // Define this as a prerelease version suffix (pre#, RC#) //#define BETAVERSION "pre1" diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index 869c0e7d3..b69900746 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -77,8 +77,8 @@ END #include "../doomdef.h" // Needed for version string VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,2,11,0 - PRODUCTVERSION 2,2,11,0 + FILEVERSION 2,2,13,0 + PRODUCTVERSION 2,2,13,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L diff --git a/src/y_inter.c b/src/y_inter.c index 5e071171f..8bec2b30f 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -998,8 +998,7 @@ void Y_Ticker(void) if (paused || P_AutoPause()) return; - LUA_HookBool(intertype == int_spec && stagefailed, - HOOK(IntermissionThinker)); + LUA_HookBool(stagefailed, HOOK(IntermissionThinker)); intertic++; @@ -1477,10 +1476,10 @@ void Y_StartIntermission(void) if (players[consoleplayer].charflags & SF_SUPER) { strcpy(data.spec.passed3, "can now become"); - snprintf(data.spec.passed4, - sizeof data.spec.passed4, "Super %s", - skins[players[consoleplayer].skin].realname); - data.spec.passed4[sizeof data.spec.passed4 - 1] = '\0'; + if (strlen(skins[players[consoleplayer].skin].supername) > 20) //too long, use generic + strcpy(data.spec.passed4, "their super form"); + else + strcpy(data.spec.passed4, skins[players[consoleplayer].skin].supername); } } else