Merge remote-tracking branch 'stjr/next' into team-gametype-keep-player-color

This commit is contained in:
Lactozilla 2023-09-12 19:17:07 -03:00
commit 69df136e2b
63 changed files with 1373 additions and 868 deletions

1
.gitignore vendored
View file

@ -23,3 +23,4 @@ Win32_LIB_ASM_Release
/bin /bin
/build /build
/build/* /build/*
/CMakeUserPresets.json

View file

@ -1,4 +1,4 @@
version: 2.2.11.{branch}-{build} version: 2.2.13.{branch}-{build}
os: MinGW os: MinGW
environment: environment:

View file

@ -4367,7 +4367,6 @@ thingtypes
{ {
color = 14; // Yellow color = 14; // Yellow
title = "Rings and Weapon Panels"; title = "Rings and Weapon Panels";
width = 24;
height = 24; height = 24;
flags8height = 24; flags8height = 24;
flags8text = "[8] Float"; flags8text = "[8] Float";
@ -4377,7 +4376,6 @@ thingtypes
{ {
title = "Ring"; title = "Ring";
sprite = "RINGA0"; sprite = "RINGA0";
width = 16;
} }
301 301
{ {
@ -4393,6 +4391,7 @@ thingtypes
{ {
title = "Infinity Ring"; title = "Infinity Ring";
sprite = "RNGIA0"; sprite = "RNGIA0";
width = 24;
} }
304 304
{ {
@ -4418,43 +4417,53 @@ thingtypes
{ {
title = "CTF Team Ring (Red)"; title = "CTF Team Ring (Red)";
sprite = "internal:TRNGA0R"; sprite = "internal:TRNGA0R";
width = 16;
} }
309 309
{ {
title = "CTF Team Ring (Blue)"; title = "CTF Team Ring (Blue)";
sprite = "internal:TRNGA0B"; sprite = "internal:TRNGA0B";
width = 16;
} }
330 330
{ {
title = "Bounce Ring Panel"; title = "Bounce Ring Panel";
sprite = "PIKBA0"; sprite = "PIKBA0";
width = 24;
height = 40;
} }
331 331
{ {
title = "Rail Ring Panel"; title = "Rail Ring Panel";
sprite = "PIKRA0"; sprite = "PIKRA0";
width = 24;
height = 40;
} }
332 332
{ {
title = "Automatic Ring Panel"; title = "Automatic Ring Panel";
sprite = "PIKAA0"; sprite = "PIKAA0";
width = 24;
height = 40;
} }
333 333
{ {
title = "Explosion Ring Panel"; title = "Explosion Ring Panel";
sprite = "PIKEA0"; sprite = "PIKEA0";
width = 24;
height = 40;
} }
334 334
{ {
title = "Scatter Ring Panel"; title = "Scatter Ring Panel";
sprite = "PIKSA0"; sprite = "PIKSA0";
width = 24;
height = 40;
} }
335 335
{ {
title = "Grenade Ring Panel"; title = "Grenade Ring Panel";
sprite = "PIKGA0"; sprite = "PIKGA0";
width = 24;
height = 40;
} }
} }
@ -4463,7 +4472,7 @@ thingtypes
color = 10; // Light Green color = 10; // Light Green
title = "Other Collectibles"; title = "Other Collectibles";
width = 16; width = 16;
height = 32; height = 24;
sort = 1; sort = 1;
sprite = "CEMGA0"; sprite = "CEMGA0";
@ -4529,6 +4538,7 @@ thingtypes
{ {
title = "Emerald Hunt Location"; title = "Emerald Hunt Location";
sprite = "SHRDA0"; sprite = "SHRDA0";
height = 32;
flags8height = 24; flags8height = 24;
flags8text = "[8] Float"; flags8text = "[8] Float";
} }

View file

@ -1185,7 +1185,7 @@ udmf
{ {
color = 14; // Yellow color = 14; // Yellow
title = "Rings and Weapon Panels"; title = "Rings and Weapon Panels";
width = 24; width = 16;
height = 24; height = 24;
sprite = "RINGA0"; sprite = "RINGA0";
@ -1193,7 +1193,6 @@ udmf
{ {
title = "Ring"; title = "Ring";
sprite = "RINGA0"; sprite = "RINGA0";
width = 16;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1227,6 +1226,7 @@ udmf
{ {
title = "Infinity Ring"; title = "Infinity Ring";
sprite = "RNGIA0"; sprite = "RNGIA0";
width = 24;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1282,7 +1282,6 @@ udmf
{ {
title = "CTF Team Ring (Red)"; title = "CTF Team Ring (Red)";
sprite = "internal:TRNGA0R"; sprite = "internal:TRNGA0R";
width = 16;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1294,7 +1293,6 @@ udmf
{ {
title = "CTF Team Ring (Blue)"; title = "CTF Team Ring (Blue)";
sprite = "internal:TRNGA0B"; sprite = "internal:TRNGA0B";
width = 16;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1306,6 +1304,8 @@ udmf
{ {
title = "Bounce Ring Panel"; title = "Bounce Ring Panel";
sprite = "PIKBA0"; sprite = "PIKBA0";
width = 24;
height = 40;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1317,6 +1317,8 @@ udmf
{ {
title = "Rail Ring Panel"; title = "Rail Ring Panel";
sprite = "PIKRA0"; sprite = "PIKRA0";
width = 24;
height = 40;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1328,6 +1330,8 @@ udmf
{ {
title = "Automatic Ring Panel"; title = "Automatic Ring Panel";
sprite = "PIKAA0"; sprite = "PIKAA0";
width = 24;
height = 40;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1339,6 +1343,8 @@ udmf
{ {
title = "Explosion Ring Panel"; title = "Explosion Ring Panel";
sprite = "PIKEA0"; sprite = "PIKEA0";
width = 24;
height = 40;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1350,6 +1356,8 @@ udmf
{ {
title = "Scatter Ring Panel"; title = "Scatter Ring Panel";
sprite = "PIKSA0"; sprite = "PIKSA0";
width = 24;
height = 40;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1361,6 +1369,8 @@ udmf
{ {
title = "Grenade Ring Panel"; title = "Grenade Ring Panel";
sprite = "PIKGA0"; sprite = "PIKGA0";
width = 24;
height = 40;
arg0 arg0
{ {
title = "Float?"; title = "Float?";
@ -1375,7 +1385,7 @@ udmf
color = 10; // Light_Green color = 10; // Light_Green
title = "Other Collectibles"; title = "Other Collectibles";
width = 16; width = 16;
height = 32; height = 24;
sort = 1; sort = 1;
sprite = "CEMGA0"; sprite = "CEMGA0";
@ -1445,6 +1455,7 @@ udmf
{ {
title = "Emerald Hunt Location"; title = "Emerald Hunt Location";
sprite = "SHRDA0"; sprite = "SHRDA0";
height = 32;
arg0 arg0
{ {
title = "Float?"; title = "Float?";

View file

@ -392,4 +392,4 @@ else
@: @:
endif 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.)

View file

@ -25,7 +25,7 @@ endif
# Tested by Steel, as of release 2.2.8. # Tested by Steel, as of release 2.2.8.
ifdef FREEBSD ifdef FREEBSD
opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD
libs+=-L/usr/X11R6/lib -lipx -lkvm libs+=-L/usr/X11R6/lib -lkvm -lexecinfo
endif endif
# FIXME: UNTESTED # FIXME: UNTESTED

View file

@ -38,12 +38,14 @@
* Last updated 2021 / 05 / 06 - v2.2.9 - patch.pk3 & zones.pk3 * Last updated 2021 / 05 / 06 - v2.2.9 - patch.pk3 & zones.pk3
* Last updated 2022 / 03 / 06 - v2.2.10 - main assets * 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 / 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_SRB2_PK3 "ad911f29a28a18968ee5b2d11c2acb39"
#define ASSET_HASH_ZONES_PK3 "1c8adf8d079ecb87d00081f158acf3c7" #define ASSET_HASH_ZONES_PK3 "1c8adf8d079ecb87d00081f158acf3c7"
#define ASSET_HASH_PLAYER_DTA "2e7aaae8a6b1b77d90ffe7606ceadb6c" #define ASSET_HASH_PLAYER_DTA "2e7aaae8a6b1b77d90ffe7606ceadb6c"
#ifdef USE_PATCH_DTA #ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_PK3 "2e69558bce3b9610624549a75e29e19b" #define ASSET_HASH_PATCH_PK3 "3c7b73f34af7e9a7bceb2d5260f76172"
#endif #endif
#endif #endif

View file

@ -1740,14 +1740,15 @@ void D_SRB2Main(void)
// Prevent warping to nonexistent levels // Prevent warping to nonexistent levels
if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR) if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR)
I_Error("Could not warp to %s (map not found)\n", G_BuildMapName(pstartmap)); 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 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); D_MapChange(pstartmap, gametype, ultimatemode, true, 0, false, false);
} }
} }

View file

@ -777,6 +777,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_showfocuslost); CV_RegisterVar(&cv_showfocuslost);
CV_RegisterVar(&cv_pauseifunfocused); CV_RegisterVar(&cv_pauseifunfocused);
CV_RegisterVar(&cv_instantretry);
// g_input.c // g_input.c
CV_RegisterVar(&cv_sideaxis); CV_RegisterVar(&cv_sideaxis);
CV_RegisterVar(&cv_sideaxis2); CV_RegisterVar(&cv_sideaxis2);
@ -1801,8 +1803,8 @@ static void Command_Map_f(void)
size_t option_gametype; size_t option_gametype;
const char *gametypename; const char *gametypename;
boolean newresetplayers; boolean newresetplayers;
boolean prevent_cheat;
boolean wouldSetCheats; boolean set_cheated;
INT32 newmapnum; INT32 newmapnum;
@ -1823,22 +1825,35 @@ static void Command_Map_f(void)
option_gametype = COM_CheckPartialParm("-g"); option_gametype = COM_CheckPartialParm("-g");
newresetplayers = ! COM_CheckParm("-noresetplayers"); newresetplayers = ! COM_CheckParm("-noresetplayers");
wouldSetCheats = prevent_cheat = !( usedCheats ) && !( option_force || cv_debug );
!( netgame || multiplayer ) && set_cheated = false;
!( usedCheats );
if (wouldSetCheats && !option_force) if (!( netgame || multiplayer ))
{
if (prevent_cheat)
{ {
/* May want to be more descriptive? */ /* May want to be more descriptive? */
CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); CONS_Printf(M_GetText("Cheats must be enabled to level change in single player.\n"));
return; return;
} }
else
if (!newresetplayers && !cv_debug)
{ {
CONS_Printf(M_GetText("DEVMODE must be enabled.\n")); set_cheated = true;
}
}
if (!newresetplayers)
{
if (prevent_cheat)
{
CONS_Printf(M_GetText("Cheats must be enabled to use -noresetplayers.\n"));
return; return;
} }
else
{
set_cheated = true;
}
}
if (option_gametype) if (option_gametype)
{ {
@ -1858,7 +1873,9 @@ static void Command_Map_f(void)
} }
if (!( first_option = COM_FirstOption() )) if (!( first_option = COM_FirstOption() ))
{
first_option = COM_Argc(); first_option = COM_Argc();
}
if (first_option < 2) if (first_option < 2)
{ {
@ -1881,11 +1898,6 @@ static void Command_Map_f(void)
return; return;
} }
if (wouldSetCheats && option_force)
{
G_SetUsedCheats(false);
}
// new gametype value // new gametype value
// use current one by default // use current one by default
if (option_gametype) if (option_gametype)
@ -1927,15 +1939,13 @@ static void Command_Map_f(void)
} }
// don't use a gametype the map doesn't support // 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 // G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
else
{
if (!( if (!(
mapheaderinfo[newmapnum-1] && mapheaderinfo[newmapnum-1] &&
mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype) 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), 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")); (multiplayer ? gametype_cons_t[newgametype].strvalue : "Single Player"));
@ -1944,25 +1954,35 @@ static void Command_Map_f(void)
return; return;
} }
else else
{
// The player wants us to trek on anyway. Do so.
fromlevelselect = false;
set_cheated = ((gametypedefaultrules[newgametype] & GTR_CAMPAIGN) == GTR_CAMPAIGN);
}
}
else
{ {
fromlevelselect = fromlevelselect =
( netgame || multiplayer ) && ( netgame || multiplayer ) &&
newgametype == gametype && newgametype == gametype &&
gametypedefaultrules[newgametype] & GTR_CAMPAIGN; (gametypedefaultrules[newgametype] & GTR_CAMPAIGN);
}
} }
// Prevent warping to locked levels // Prevent warping to locked levels
// ... unless you're in a dedicated server. Yes, technically this means you can view any level by if (M_CampaignWarpIsCheat(newgametype, newmapnum, serverGamedata))
// 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))
{ {
CONS_Alert(CONS_NOTICE, M_GetText("You need to unlock this level before you can warp to it!\n")); 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(realmapname);
Z_Free(mapname); Z_Free(mapname);
return; return;
} }
else
{
set_cheated = true;
}
}
// Ultimate Mode only in SP via menu // Ultimate Mode only in SP via menu
if (netgame || multiplayer) if (netgame || multiplayer)
@ -1978,6 +1998,11 @@ static void Command_Map_f(void)
} }
tutorialmode = false; // warping takes us out of tutorial mode 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); D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect);
Z_Free(realmapname); Z_Free(realmapname);
@ -2019,11 +2044,13 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
lastgametype = gametype; lastgametype = gametype;
gametype = READUINT8(*cp); gametype = READUINT8(*cp);
G_SetGametype(gametype); // I fear putting that macro as an argument
if (gametype < 0 || gametype >= gametypecount) if (gametype < 0 || gametype >= gametypecount)
gametype = lastgametype; gametype = lastgametype;
else if (gametype != lastgametype) else
G_SetGametype(gametype);
if (gametype != lastgametype)
D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype
skipprecutscene = ((flags & (1<<2)) != 0); skipprecutscene = ((flags & (1<<2)) != 0);
@ -4139,9 +4166,6 @@ void D_GameTypeChanged(INT32 lastgametype)
else if (!multiplayer && !netgame) else if (!multiplayer && !netgame)
{ {
G_SetGametype(GT_COOP); 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 // 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")); 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) static void Command_ExitLevel_f(void)
{ {
if (!(netgame || (multiplayer && gametype != GT_COOP)) && !cv_debug) if (!(server || (IsPlayerAdmin(consoleplayer))))
CONS_Printf(M_GetText("This only works in a netgame.\n"));
else if (!(server || (IsPlayerAdmin(consoleplayer))))
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
else if (( gamestate != GS_LEVEL && gamestate != GS_CREDITS ) || demoplayback) else if (( gamestate != GS_LEVEL && gamestate != GS_CREDITS ) || demoplayback)
CONS_Printf(M_GetText("You must be in a level to use this.\n")); CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else else
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(true);
} }
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
{ {
(void)cp; boolean cheat = false;
cheat = (boolean)READUINT8(*cp);
// Ignore duplicate XD_EXITLEVEL commands. // Ignore duplicate XD_EXITLEVEL commands.
if (gameaction == ga_completed) if (gameaction == ga_completed)
{
return; return;
}
if (playernum != serverplayer && !IsPlayerAdmin(playernum)) if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{ {
@ -4470,6 +4506,11 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
return; return;
} }
if (G_CoopGametype() && cheat)
{
G_SetUsedCheats(false);
}
G_ExitLevel(); G_ExitLevel();
} }

View file

@ -201,6 +201,7 @@ void D_SendPlayerConfig(void);
void Command_ExitGame_f(void); void Command_ExitGame_f(void);
void Command_Retry_f(void); void Command_Retry_f(void);
void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore 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); void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect);
boolean IsPlayerAdmin(INT32 playernum); boolean IsPlayerAdmin(INT32 playernum);
void SetAdminPlayer(INT32 playernum); void SetAdminPlayer(INT32 playernum);

View file

@ -277,8 +277,8 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
} }
else if (fastncmp("MTF_", word, 4)) { else if (fastncmp("MTF_", word, 4)) {
p = word+4; p = word+4;
for (i = 0; i < 4; i++) for (i = 0; MAPTHINGFLAG_LIST[i]; i++)
if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) { if (fastcmp(p, MAPTHINGFLAG_LIST[i])) {
CacheAndPushConstant(L, word, ((lua_Integer)1<<i)); CacheAndPushConstant(L, word, ((lua_Integer)1<<i));
return 1; return 1;
} }

View file

@ -4410,11 +4410,12 @@ const char *const MOBJEFLAG_LIST[] = {
NULL NULL
}; };
const char *const MAPTHINGFLAG_LIST[4] = { const char *const MAPTHINGFLAG_LIST[] = {
"EXTRA", // Extra flag for objects. "EXTRA", // Extra flag for objects.
"OBJECTFLIP", // Reverse gravity flag for objects. "OBJECTFLIP", // Reverse gravity flag for objects.
"OBJECTSPECIAL", // Special flag used with certain objects. "OBJECTSPECIAL", // Special flag used with certain objects.
"AMBUSH" // Deaf monsters/do not react to sound. "AMBUSH", // Deaf monsters/do not react to sound.
"ABSOLUTEZ" // Absolute spawn height flag for objects.
}; };
const char *const PLAYERFLAG_LIST[] = { const char *const PLAYERFLAG_LIST[] = {
@ -4613,8 +4614,7 @@ const char *COLOR_ENUMS[] = {
// Desaturated // Desaturated
"AETHER", // SKINCOLOR_AETHER, "AETHER", // SKINCOLOR_AETHER,
"SLATE", // SKINCOLOR_SLATE, "SLATE", // SKINCOLOR_SLATE,
"METEORITE", // SKINCOLOR_METEORITE, "MOONSTONE", // SKINCOLOR_MOONSTONE,
"MERCURY", // SKINCOLOR_MERCURY,
"BLUEBELL", // SKINCOLOR_BLUEBELL, "BLUEBELL", // SKINCOLOR_BLUEBELL,
"PINK", // SKINCOLOR_PINK, "PINK", // SKINCOLOR_PINK,
"ROSEWOOD", // SKINCOLOR_ROSEWOOD, "ROSEWOOD", // SKINCOLOR_ROSEWOOD,
@ -4651,10 +4651,10 @@ const char *COLOR_ENUMS[] = {
"COPPER", // SKINCOLOR_COPPER, "COPPER", // SKINCOLOR_COPPER,
"APRICOT", // SKINCOLOR_APRICOT, "APRICOT", // SKINCOLOR_APRICOT,
"ORANGE", // SKINCOLOR_ORANGE, "ORANGE", // SKINCOLOR_ORANGE,
"PUMPKIN", // SKINCOLOR_PUMPKIN,
"RUST", // SKINCOLOR_RUST, "RUST", // SKINCOLOR_RUST,
"GOLD", // SKINCOLOR_GOLD, "TANGERINE", // SKINCOLOR_TANGERINE,
"TOPAZ", // SKINCOLOR_TOPAZ, "TOPAZ", // SKINCOLOR_TOPAZ,
"GOLD", // SKINCOLOR_GOLD,
"SANDY", // SKINCOLOR_SANDY, "SANDY", // SKINCOLOR_SANDY,
"GOLDENROD", // SKINCOLOR_GOLDENROD, "GOLDENROD", // SKINCOLOR_GOLDENROD,
"YELLOW", // SKINCOLOR_YELLOW, "YELLOW", // SKINCOLOR_YELLOW,
@ -4664,20 +4664,21 @@ const char *COLOR_ENUMS[] = {
"LIME", // SKINCOLOR_LIME, "LIME", // SKINCOLOR_LIME,
"PERIDOT", // SKINCOLOR_PERIDOT, "PERIDOT", // SKINCOLOR_PERIDOT,
"APPLE", // SKINCOLOR_APPLE, "APPLE", // SKINCOLOR_APPLE,
"HEADLIGHT", // SKINCOLOR_HEADLIGHT,
"CHARTREUSE", // SKINCOLOR_CHARTREUSE, "CHARTREUSE", // SKINCOLOR_CHARTREUSE,
"GREEN", // SKINCOLOR_GREEN, "GREEN", // SKINCOLOR_GREEN,
"FOREST", // SKINCOLOR_FOREST, "FOREST", // SKINCOLOR_FOREST,
"SHAMROCK", // SKINCOLOR_SHAMROCK, "SHAMROCK", // SKINCOLOR_SHAMROCK,
"JADE", // SKINCOLOR_JADE, "JADE", // SKINCOLOR_JADE,
"HEADLIGHT", // SKINCOLOR_HEADLIGHT,
"MINT", // SKINCOLOR_MINT, "MINT", // SKINCOLOR_MINT,
"MASTER", // SKINCOLOR_MASTER, "MASTER", // SKINCOLOR_MASTER,
"EMERALD", // SKINCOLOR_EMERALD, "EMERALD", // SKINCOLOR_EMERALD,
"BOTTLE", // SKINCOLOR_BOTTLE,
"SEAFOAM", // SKINCOLOR_SEAFOAM, "SEAFOAM", // SKINCOLOR_SEAFOAM,
"ISLAND", // SKINCOLOR_ISLAND, "ISLAND", // SKINCOLOR_ISLAND,
"BOTTLE", // SKINCOLOR_BOTTLE,
"AQUA", // SKINCOLOR_AQUA, "AQUA", // SKINCOLOR_AQUA,
"TEAL", // SKINCOLOR_TEAL, "TEAL", // SKINCOLOR_TEAL,
"OCEAN", // SKINCOLOR_OCEAN,
"WAVE", // SKINCOLOR_WAVE, "WAVE", // SKINCOLOR_WAVE,
"CYAN", // SKINCOLOR_CYAN, "CYAN", // SKINCOLOR_CYAN,
"TURQUOISE", // SKINCOLOR_TURQUOISE, "TURQUOISE", // SKINCOLOR_TURQUOISE,
@ -4703,7 +4704,7 @@ const char *COLOR_ENUMS[] = {
"NOBLE", // SKINCOLOR_NOBLE, "NOBLE", // SKINCOLOR_NOBLE,
"FUCHSIA", // SKINCOLOR_FUCHSIA, "FUCHSIA", // SKINCOLOR_FUCHSIA,
"BUBBLEGUM", // SKINCOLOR_BUBBLEGUM, "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM,
"CRYSTAL", // SKINCOLOR_CRYSTAL, "SIBERITE", // SKINCOLOR_SIBERITE,
"MAGENTA", // SKINCOLOR_MAGENTA, "MAGENTA", // SKINCOLOR_MAGENTA,
"NEON", // SKINCOLOR_NEON, "NEON", // SKINCOLOR_NEON,
"VIOLET", // SKINCOLOR_VIOLET, "VIOLET", // SKINCOLOR_VIOLET,

View file

@ -62,7 +62,7 @@ extern const char *const MOBJTYPE_LIST[];
extern const char *const MOBJFLAG_LIST[]; extern const char *const MOBJFLAG_LIST[];
extern const char *const MOBJFLAG2_LIST[]; // \tMF2_(\S+).*// (.+) --> \t"\1", // \2 extern const char *const MOBJFLAG2_LIST[]; // \tMF2_(\S+).*// (.+) --> \t"\1", // \2
extern const char *const MOBJEFLAG_LIST[]; 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 PLAYERFLAG_LIST[];
extern const char *const GAMETYPERULE_LIST[]; extern const char *const GAMETYPERULE_LIST[];
extern const char *const ML_LIST[]; // Linedef flags extern const char *const ML_LIST[]; // Linedef flags

View file

@ -62,6 +62,10 @@ enum
#define MTF_AMBUSH 8 #define MTF_AMBUSH 8
// Do not use bit five or after, as they are used for object z-offsets. // 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) #if defined(_MSC_VER)
#pragma pack(1) #pragma pack(1)

View file

@ -269,8 +269,7 @@ typedef enum
// Desaturated // Desaturated
SKINCOLOR_AETHER, SKINCOLOR_AETHER,
SKINCOLOR_SLATE, SKINCOLOR_SLATE,
SKINCOLOR_METEORITE, SKINCOLOR_MOONSTONE,
SKINCOLOR_MERCURY,
SKINCOLOR_BLUEBELL, SKINCOLOR_BLUEBELL,
SKINCOLOR_PINK, SKINCOLOR_PINK,
SKINCOLOR_ROSEWOOD, SKINCOLOR_ROSEWOOD,
@ -307,10 +306,10 @@ typedef enum
SKINCOLOR_COPPER, SKINCOLOR_COPPER,
SKINCOLOR_APRICOT, SKINCOLOR_APRICOT,
SKINCOLOR_ORANGE, SKINCOLOR_ORANGE,
SKINCOLOR_PUMPKIN,
SKINCOLOR_RUST, SKINCOLOR_RUST,
SKINCOLOR_GOLD, SKINCOLOR_TANGERINE,
SKINCOLOR_TOPAZ, SKINCOLOR_TOPAZ,
SKINCOLOR_GOLD,
SKINCOLOR_SANDY, SKINCOLOR_SANDY,
SKINCOLOR_GOLDENROD, SKINCOLOR_GOLDENROD,
SKINCOLOR_YELLOW, SKINCOLOR_YELLOW,
@ -320,20 +319,21 @@ typedef enum
SKINCOLOR_LIME, SKINCOLOR_LIME,
SKINCOLOR_PERIDOT, SKINCOLOR_PERIDOT,
SKINCOLOR_APPLE, SKINCOLOR_APPLE,
SKINCOLOR_HEADLIGHT,
SKINCOLOR_CHARTREUSE, SKINCOLOR_CHARTREUSE,
SKINCOLOR_GREEN, SKINCOLOR_GREEN,
SKINCOLOR_FOREST, SKINCOLOR_FOREST,
SKINCOLOR_SHAMROCK, SKINCOLOR_SHAMROCK,
SKINCOLOR_JADE, SKINCOLOR_JADE,
SKINCOLOR_HEADLIGHT,
SKINCOLOR_MINT, SKINCOLOR_MINT,
SKINCOLOR_MASTER, SKINCOLOR_MASTER,
SKINCOLOR_EMERALD, SKINCOLOR_EMERALD,
SKINCOLOR_BOTTLE,
SKINCOLOR_SEAFOAM, SKINCOLOR_SEAFOAM,
SKINCOLOR_ISLAND, SKINCOLOR_ISLAND,
SKINCOLOR_BOTTLE,
SKINCOLOR_AQUA, SKINCOLOR_AQUA,
SKINCOLOR_TEAL, SKINCOLOR_TEAL,
SKINCOLOR_OCEAN,
SKINCOLOR_WAVE, SKINCOLOR_WAVE,
SKINCOLOR_CYAN, SKINCOLOR_CYAN,
SKINCOLOR_TURQUOISE, SKINCOLOR_TURQUOISE,
@ -359,7 +359,7 @@ typedef enum
SKINCOLOR_NOBLE, SKINCOLOR_NOBLE,
SKINCOLOR_FUCHSIA, SKINCOLOR_FUCHSIA,
SKINCOLOR_BUBBLEGUM, SKINCOLOR_BUBBLEGUM,
SKINCOLOR_CRYSTAL, SKINCOLOR_SIBERITE,
SKINCOLOR_MAGENTA, SKINCOLOR_MAGENTA,
SKINCOLOR_NEON, SKINCOLOR_NEON,
SKINCOLOR_VIOLET, SKINCOLOR_VIOLET,

View file

@ -249,6 +249,7 @@ extern textprompt_t *textprompts[MAX_PROMPTS];
// For the Custom Exit linedef. // For the Custom Exit linedef.
extern INT16 nextmapoverride; extern INT16 nextmapoverride;
extern UINT8 skipstats; extern UINT8 skipstats;
extern INT16 nextgametype;
extern UINT32 ssspheres; // Total # of spheres in a level extern UINT32 ssspheres; // Total # of spheres in a level

View file

@ -113,6 +113,15 @@ int endswith (const char *base, const char *tag);
#define HAVE_DOSSTR_FUNCS #define HAVE_DOSSTR_FUNCS
#endif #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 #ifndef HAVE_DOSSTR_FUNCS
int strupr(char *n); // from dosstr.c int strupr(char *n); // from dosstr.c
int strlwr(char *n); // from dosstr.c int strlwr(char *n); // from dosstr.c
@ -120,7 +129,7 @@ int strlwr(char *n); // from dosstr.c
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#ifndef __APPLE__ #ifndef SRB2_HAVE_STRLCPY
size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcat(char *dst, const char *src, size_t siz);
size_t strlcpy(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz);
#endif #endif

View file

@ -1062,12 +1062,14 @@ static const char *credits[] = {
"\"Golden\"", "\"Golden\"",
"Vivian \"toaster\" Grannell", "Vivian \"toaster\" Grannell",
"Julio \"Chaos Zero 64\" Guir", "Julio \"Chaos Zero 64\" Guir",
"\"Hanicef\"",
"\"Hannu_Hanhi\"", // For many OpenGL performance improvements! "\"Hannu_Hanhi\"", // For many OpenGL performance improvements!
"Kepa \"Nev3r\" Iceta", "Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe", "Thomas \"Shadow Hog\" Igoe",
"Iestyn \"Monster Iestyn\" Jealous", "Iestyn \"Monster Iestyn\" Jealous",
"\"Kaito Sinclaire\"", "\"Kaito Sinclaire\"",
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"\"katsy\"",
"Ronald \"Furyhunter\" Kinard", // The SDL2 port "Ronald \"Furyhunter\" Kinard", // The SDL2 port
"\"Lat'\"", // SRB2-CHAT, the chat window from Kart "\"Lat'\"", // SRB2-CHAT, the chat window from Kart
"\"LZA\"", "\"LZA\"",
@ -1090,6 +1092,7 @@ static const char *credits[] = {
"Ben \"Cue\" Woodford", "Ben \"Cue\" Woodford",
"Lachlan \"Lach\" Wright", "Lachlan \"Lach\" Wright",
"Marco \"mazmazz\" Zafra", "Marco \"mazmazz\" Zafra",
"\"Zwip-Zwap Zapony\"",
"", "",
"\1Art", "\1Art",
"Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: "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 "FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
"Kart Krew", "Kart Krew",
"Alex \"MistaED\" Fuller", "Alex \"MistaED\" Fuller",
"Howard Drossin", // Virtual Sonic - Sonic & Knuckles Theme
"Pascal \"CodeImp\" vd Heiden", // Doom Builder developer "Pascal \"CodeImp\" vd Heiden", // Doom Builder developer
"Randi Heit (<!>)", // For their MSPaint <!> sprite that we nicked "Randi Heit (<!>)", // For their MSPaint <!> sprite that we nicked
"Simon \"sirjuddington\" Judd", // SLADE developer "Simon \"sirjuddington\" Judd", // SLADE developer
@ -1644,7 +1648,7 @@ void F_GameEvaluationTicker(void)
sparklloop = 0; sparklloop = 0;
} }
if (finalecount == 5*TICRATE) if (G_CoopGametype() && !stagefailed && finalecount == 5*TICRATE)
{ {
serverGamedata->timesBeaten++; serverGamedata->timesBeaten++;
clientGamedata->timesBeaten++; clientGamedata->timesBeaten++;
@ -2256,7 +2260,7 @@ void F_InitMenuPresValues(void)
curfadevalue = 16; curfadevalue = 16;
curbgcolor = -1; curbgcolor = -1;
curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
curbgyspeed = (gamestate == GS_TIMEATTACK) ? 22 : titlescrollyspeed; curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed;
curbghide = (gamestate == GS_TIMEATTACK) ? false : true; curbghide = (gamestate == GS_TIMEATTACK) ? false : true;
curhidepics = hidetitlepics; curhidepics = hidetitlepics;

View file

@ -158,6 +158,7 @@ textprompt_t *textprompts[MAX_PROMPTS];
INT16 nextmapoverride; INT16 nextmapoverride;
UINT8 skipstats; UINT8 skipstats;
INT16 nextgametype = -1;
// Pointers to each CTF flag // Pointers to each CTF flag
mobj_t *redflag; mobj_t *redflag;
@ -317,6 +318,8 @@ consvar_t cv_consolechat = CVAR_INIT ("chatmode", "Window", CV_SAVE, consolechat
// Pause game upon window losing focus // Pause game upon window losing focus
consvar_t cv_pauseifunfocused = CVAR_INIT ("pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL); 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_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_crosshair2 = CVAR_INIT ("crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL);
consvar_t cv_invertmouse = CVAR_INIT ("invertmouse", "Off", CV_SAVE, CV_OnOff, 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 && if (gameaction == ga_nothing && !singledemo &&
((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN)) ((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(); M_StartControlPanel();
return true; return true;
@ -2139,7 +2142,7 @@ boolean G_Responder(event_t *ev)
if (! netgame) if (! netgame)
F_StartGameEvaluation(); F_StartGameEvaluation();
else if (server || IsPlayerAdmin(consoleplayer)) else if (server || IsPlayerAdmin(consoleplayer))
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
return true; return true;
} }
} }
@ -2174,9 +2177,9 @@ boolean G_Responder(event_t *ev)
if (menuactive || pausedelay < 0 || leveltime < 2) if (menuactive || pausedelay < 0 || leveltime < 2)
return true; return true;
if (pausedelay < 1+(NEWTICRATE/2)) if (!cv_instantretry.value && pausedelay < 1+(NEWTICRATE/2))
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(); G_SetModeAttackRetryFlag();
return true; return true;
@ -3444,9 +3447,7 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] =
}; };
// //
// G_SetGametype // Sets a new gametype.
//
// Set a new gametype, also setting gametype rules accordingly. Yay!
// //
void G_SetGametype(INT16 gtype) void G_SetGametype(INT16 gtype)
{ {
@ -3844,7 +3845,7 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap)
for (ix = 0; ix < NUMMAPS; ix++) for (ix = 0; ix < NUMMAPS; ix++)
if (mapheaderinfo[ix] && (mapheaderinfo[ix]->typeoflevel & tolflags) == tolflags if (mapheaderinfo[ix] && (mapheaderinfo[ix]->typeoflevel & tolflags) == tolflags
&& ix != pprevmap // Don't pick the same map. && 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; okmaps[numokmaps++] = ix;
@ -4036,6 +4037,13 @@ static void G_DoCompleted(void)
nextmap = 1100-1; // No infinite loop for you 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 // 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 // a map of the proper gametype -- skip levels that don't support
// the current gametype. (Helps avoid playing boss levels in Race, // the current gametype. (Helps avoid playing boss levels in Race,
@ -4044,8 +4052,8 @@ static void G_DoCompleted(void)
{ {
if (nextmap >= 0 && nextmap < NUMMAPS) if (nextmap >= 0 && nextmap < NUMMAPS)
{ {
register INT16 cm = nextmap; INT16 cm = nextmap;
UINT32 tolflag = G_TOLFlag(gametype); UINT32 tolflag = G_TOLFlag(gametype_to_use);
UINT8 visitedmap[(NUMMAPS+7)/8]; UINT8 visitedmap[(NUMMAPS+7)/8];
memset(visitedmap, 0, sizeof (visitedmap)); memset(visitedmap, 0, sizeof (visitedmap));
@ -4100,7 +4108,7 @@ static void G_DoCompleted(void)
{ {
token--; 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++) for (i = 0; i < 7; i++)
if (!(emeralds & (1<<i))) if (!(emeralds & (1<<i)))
{ {
@ -4125,7 +4133,7 @@ static void G_DoCompleted(void)
if (cv_advancemap.value == 0) // Stay on same map. if (cv_advancemap.value == 0) // Stay on same map.
nextmap = prevmap; nextmap = prevmap;
else if (cv_advancemap.value == 2) // Go to random map. else if (cv_advancemap.value == 2) // Go to random map.
nextmap = RandMap(G_TOLFlag(gametype), prevmap); nextmap = RandMap(G_TOLFlag(gametype_to_use), prevmap);
} }
// We are committed to this map now. // We are committed to this map now.
@ -4134,7 +4142,6 @@ static void G_DoCompleted(void)
if (nextmap < NUMMAPS && !mapheaderinfo[nextmap]) if (nextmap < NUMMAPS && !mapheaderinfo[nextmap])
P_AllocMapHeader(nextmap); P_AllocMapHeader(nextmap);
// If the current gametype has no intermission screen set, then don't start it.
Y_DetermineIntermissionType(); Y_DetermineIntermissionType();
if ((skipstats && !modeattacking) || (modeattacking && stagefailed) || (intertype == int_none)) if ((skipstats && !modeattacking) || (modeattacking && stagefailed) || (intertype == int_none))
@ -4200,12 +4207,21 @@ static void G_DoWorldDone(void)
{ {
if (server) if (server)
{ {
INT16 gametype_to_use;
if (nextgametype >= 0 && nextgametype < gametypecount)
gametype_to_use = nextgametype;
else
gametype_to_use = gametype;
if (gametyperules & GTR_CAMPAIGN) if (gametyperules & GTR_CAMPAIGN)
// don't reset player between maps // 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 else
// resetplayer in match/chaos/tag/CTF/race for more equality // 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; gameaction = ga_nothing;

View file

@ -49,6 +49,8 @@ extern boolean promptactive;
extern consvar_t cv_pauseifunfocused; extern consvar_t cv_pauseifunfocused;
extern consvar_t cv_instantretry;
// used in game menu // used in game menu
extern consvar_t cv_tutorialprompt; extern consvar_t cv_tutorialprompt;
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard; extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard;

View file

@ -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) if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
{ {
blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; 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) 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) if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
{ {
blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; 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) if (gl_backsector->numlights)
@ -3095,7 +3095,7 @@ static void HWR_Subsector(size_t num)
false, false,
*rover->bottomheight, *rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel, *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), HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
false, *gl_frontsector->lightlist[light].extra_colormap); false, *gl_frontsector->lightlist[light].extra_colormap);
} }
@ -3141,7 +3141,7 @@ static void HWR_Subsector(size_t num)
true, true,
*rover->topheight, *rover->topheight,
*gl_frontsector->lightlist[light].lightlevel, *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), HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
false, *gl_frontsector->lightlist[light].extra_colormap); false, *gl_frontsector->lightlist[light].extra_colormap);
} }
@ -3595,7 +3595,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
return; 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; alpha = floordiff / (4*FRACUNIT) + 75;
if (alpha >= 255) return; if (alpha >= 255) return;
@ -3606,9 +3606,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
HWR_GetPatch(gpatch); HWR_GetPatch(gpatch);
scalemul = FixedMul(FRACUNIT - floordiff/640, scale); scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); scalemul = FixedMul(scalemul, (interp.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));
fscale = FIXED_TO_FLOAT(scalemul); fscale = FIXED_TO_FLOAT(scalemul);
fx = FIXED_TO_FLOAT(interp.x); 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) if (P_MobjFlip(spr->mobj) == -1)
{ {
basey = FIXED_TO_FLOAT(interp.z + spr->mobj->height); basey = FIXED_TO_FLOAT(interp.z + interp.height);
} }
else else
{ {
@ -4055,32 +4053,32 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis)
// repeat this 4 times (overhead) // repeat this 4 times (overhead)
// //
// //
// 17 20 21 11 // 15 16 17 09
// 16 15 14 10 // 14 13 12 08
// 27 22 *--* 07 12 // 23 18 *--* 07 10
// | | // | |
// 26 23 *--* 06 13 // 22 19 *--* 06 11
// 24 00 01 02 // 20 00 01 02
// 25 05 04 03 // 21 05 04 03
// //
v[000].x = v[005].x = v[015].x = v[016].x = v[017].x = v[020].x = v[ 0].x = v[ 5].x = v[13].x = v[14].x = v[15].x = v[16].x =
v[022].x = v[023].x = v[024].x = v[025].x = v[026].x = v[027].x = vis->x1; // west 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[ 1].x = v[ 2].x = v[ 3].x = v[ 4].x = v[ 6].x = v[ 7].x =
v[010].x = v[011].x = v[012].x = v[013].x = v[014].x = v[021].x = vis->x2; // east 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[ 0].z = v[ 1].z = v[ 2].z = v[ 3].z = v[ 4].z = v[ 5].z =
v[006].z = v[013].z = v[023].z = v[024].z = v[025].z = v[026].z = vis->z1; // south 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[ 7].z = v[ 8].z = v[ 9].z = v[10].z = v[12].z = v[13].z =
v[016].z = v[017].z = v[020].z = v[021].z = v[022].z = v[027].z = vis->z2; // north 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[ 0].y = v[ 1].y = v[ 2].y = v[ 6].y = v[ 7].y = v[ 8].y =
v[014].y = v[015].y = v[016].y = v[022].y = v[023].y = v[024].y = vis->gz; // bottom 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[ 3].y = v[ 4].y = v[ 5].y = v[ 9].y = v[10].y = v[11].y =
v[017].y = v[020].y = v[021].y = v[025].y = v[026].y = v[027].y = vis->gzt; // top 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)); Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj));
@ -5326,7 +5324,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
} }
groundz = R_GetShadowZ(thing, NULL); 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); shadowheight = FIXED_TO_FLOAT(floordiff);
shadowscale = FIXED_TO_FLOAT(FixedMul(FRACUNIT - floordiff/640, casterinterp.scale)); shadowscale = FIXED_TO_FLOAT(FixedMul(FRACUNIT - floordiff/640, casterinterp.scale));
@ -5378,7 +5376,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (vflip) 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); gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale);
} }
else else
@ -5684,7 +5682,6 @@ static void HWR_ProjectBoundingBox(mobj_t *thing)
gl_vissprite_t *vis; gl_vissprite_t *vis;
float tr_x, tr_y; float tr_x, tr_y;
float tz; float tz;
float rad;
if (!thing) if (!thing)
return; return;
@ -5719,15 +5716,13 @@ static void HWR_ProjectBoundingBox(mobj_t *thing)
tr_x += gl_viewx; tr_x += gl_viewx;
tr_y += gl_viewy; tr_y += gl_viewy;
rad = FIXED_TO_FLOAT(thing->radius);
vis = HWR_NewVisSprite(); vis = HWR_NewVisSprite();
vis->x1 = tr_x - rad; vis->x1 = tr_x - FIXED_TO_FLOAT(interp.radius);
vis->x2 = tr_x + rad; vis->x2 = tr_x + FIXED_TO_FLOAT(interp.radius);
vis->z1 = tr_y - rad; vis->z1 = tr_y - FIXED_TO_FLOAT(interp.radius);
vis->z2 = tr_y + rad; vis->z2 = tr_y + FIXED_TO_FLOAT(interp.radius);
vis->gz = FIXED_TO_FLOAT(interp.z); 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->mobj = thing;
vis->precip = false; vis->precip = false;

View file

@ -1585,7 +1585,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.y = FIXED_TO_FLOAT(interp.y)+md2->offset; p.y = FIXED_TO_FLOAT(interp.y)+md2->offset;
if (flip) if (flip)
p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height); p.z = FIXED_TO_FLOAT(interp.z + interp.height);
else else
p.z = FIXED_TO_FLOAT(interp.z); p.z = FIXED_TO_FLOAT(interp.z);
@ -1621,8 +1621,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.roll = true; p.roll = true;
// rotation pivot // rotation pivot
p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); p.centerx = FIXED_TO_FLOAT(interp.radius / 2);
p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); p.centery = FIXED_TO_FLOAT(interp.height / 2);
// rotation axes relative to camera // rotation axes relative to camera
p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));

View file

@ -2025,7 +2025,7 @@ void HU_Drawer(void)
V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP | V_ALLOWLOWERCASE, resynch_text); 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 strength = ((pausedelay - 1 - NEWTICRATE/2)*10)/(NEWTICRATE/3);
INT32 y = hudinfo[HUD_LIVES].y - 13; INT32 y = hudinfo[HUD_LIVES].y - 13;

View file

@ -7194,7 +7194,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound sfx_cgot, // deathsound
EMERALD1, // speed EMERALD1, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
16, // mass 16, // mass
0, // damage 0, // damage
@ -7220,7 +7220,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound sfx_cgot, // deathsound
EMERALD2, // speed EMERALD2, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
16, // mass 16, // mass
0, // damage 0, // damage
@ -7246,7 +7246,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound sfx_cgot, // deathsound
EMERALD3, // speed EMERALD3, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
16, // mass 16, // mass
0, // damage 0, // damage
@ -7272,7 +7272,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound sfx_cgot, // deathsound
EMERALD4, // speed EMERALD4, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
16, // mass 16, // mass
0, // damage 0, // damage
@ -7298,7 +7298,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound sfx_cgot, // deathsound
EMERALD5, // speed EMERALD5, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
16, // mass 16, // mass
0, // damage 0, // damage
@ -7324,7 +7324,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound sfx_cgot, // deathsound
EMERALD6, // speed EMERALD6, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
16, // mass 16, // mass
0, // damage 0, // damage
@ -7350,7 +7350,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound sfx_cgot, // deathsound
EMERALD7, // speed EMERALD7, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
16, // mass 16, // mass
0, // damage 0, // damage
@ -18344,7 +18344,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_itemup, // deathsound sfx_itemup, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 16*FRACUNIT, // radius
24*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
pw_bouncering, // mass pw_bouncering, // mass
@ -18371,7 +18371,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_itemup, // deathsound sfx_itemup, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 16*FRACUNIT, // radius
24*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
pw_railring, // mass pw_railring, // mass
@ -18425,7 +18425,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_itemup, // deathsound sfx_itemup, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 16*FRACUNIT, // radius
24*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
pw_automaticring, // mass pw_automaticring, // mass
@ -18452,7 +18452,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_itemup, // deathsound sfx_itemup, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 16*FRACUNIT, // radius
24*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
pw_explosionring, // mass pw_explosionring, // mass
@ -18479,7 +18479,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_itemup, // deathsound sfx_itemup, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 16*FRACUNIT, // radius
24*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
pw_scatterring, // mass pw_scatterring, // mass
@ -18506,7 +18506,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_itemup, // deathsound sfx_itemup, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 16*FRACUNIT, // radius
24*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
pw_grenadering, // mass pw_grenadering, // mass
@ -18535,7 +18535,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound sfx_ncitem, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 24*FRACUNIT, // radius
24*FRACUNIT, // height 40*FRACUNIT, // height
0, // display offset 0, // display offset
pw_bouncering, // mass pw_bouncering, // mass
2*TICRATE, // damage 2*TICRATE, // damage
@ -18562,7 +18562,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound sfx_ncitem, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 24*FRACUNIT, // radius
24*FRACUNIT, // height 40*FRACUNIT, // height
0, // display offset 0, // display offset
pw_railring, // mass pw_railring, // mass
2*TICRATE, // damage 2*TICRATE, // damage
@ -18589,7 +18589,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound sfx_ncitem, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 24*FRACUNIT, // radius
24*FRACUNIT, // height 40*FRACUNIT, // height
0, // display offset 0, // display offset
pw_automaticring, // mass pw_automaticring, // mass
2*TICRATE, // damage 2*TICRATE, // damage
@ -18616,7 +18616,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound sfx_ncitem, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 24*FRACUNIT, // radius
24*FRACUNIT, // height 40*FRACUNIT, // height
0, // display offset 0, // display offset
pw_explosionring, // mass pw_explosionring, // mass
2*TICRATE, // damage 2*TICRATE, // damage
@ -18643,7 +18643,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound sfx_ncitem, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 24*FRACUNIT, // radius
24*FRACUNIT, // height 40*FRACUNIT, // height
0, // display offset 0, // display offset
pw_scatterring, // mass pw_scatterring, // mass
2*TICRATE, // damage 2*TICRATE, // damage
@ -18670,7 +18670,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound sfx_ncitem, // deathsound
60*FRACUNIT, // speed 60*FRACUNIT, // speed
24*FRACUNIT, // radius 24*FRACUNIT, // radius
24*FRACUNIT, // height 40*FRACUNIT, // height
0, // display offset 0, // display offset
pw_grenadering, // mass pw_grenadering, // mass
2*TICRATE, // damage 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 {"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 // 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 {"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 {"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
{"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
{"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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) // 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 {"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 {"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 {"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 {"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_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_RED {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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_METEORITE, 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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_ROSY, 7, V_GREENMAP, true}, // SKINCOLOR_JADE {"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
{"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
{"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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, 146, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_PUMPKIN, 6, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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 {"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_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_ROSY {"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 {"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 {"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
{"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 {"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

View file

@ -3826,7 +3826,7 @@ static int lib_gDoReborn(lua_State *L)
} }
// Another Lua function that doesn't actually exist! // 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) static int lib_gSetCustomExitVars(lua_State *L)
{ {
int n = lua_gettop(L); // Num arguments int n = lua_gettop(L); // Num arguments
@ -3839,14 +3839,17 @@ static int lib_gSetCustomExitVars(lua_State *L)
// G_SetCustomExitVars(int) [nextmap override only] // G_SetCustomExitVars(int) [nextmap override only]
// G_SetCustomExitVars(nil, int) [skipstats only] // G_SetCustomExitVars(nil, int) [skipstats only]
// G_SetCustomExitVars(int, int) [both of the above] // G_SetCustomExitVars(int, int) [both of the above]
// G_SetCustomExitVars(int, int, int) [nextmapoverride, skipstats and nextgametype]
nextmapoverride = 0; nextmapoverride = 0;
skipstats = 0; skipstats = 0;
nextgametype = -1;
if (n >= 1) if (n >= 1)
{ {
nextmapoverride = (INT16)luaL_optinteger(L, 1, 0); nextmapoverride = (INT16)luaL_optinteger(L, 1, 0);
skipstats = (INT16)luaL_optinteger(L, 2, 0); skipstats = (INT16)luaL_optinteger(L, 2, 0);
nextgametype = (INT16)luaL_optinteger(L, 3, -1);
} }
return 0; return 0;

View file

@ -615,7 +615,7 @@ static int cvar_get(lua_State *L)
break; break;
default: default:
if (devparm) 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 else
return 0; return 0;
} }

View file

@ -282,7 +282,6 @@ static int patch_get(lua_State *L)
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
enum patch field = Lua_optoption(L, 2, -1, patch_fields_ref); enum patch field = Lua_optoption(L, 2, -1, patch_fields_ref);
// patches are invalidated when switching renderers
if (!patch) { if (!patch) {
if (field == patch_valid) { if (field == patch_valid) {
lua_pushboolean(L, 0); lua_pushboolean(L, 0);
@ -436,7 +435,7 @@ static int camera_set(lua_State *L)
cam->momz = luaL_checkfixed(L, 3); cam->momz = luaL_checkfixed(L, 3);
break; break;
default: 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; return 0;
} }
@ -1487,7 +1486,6 @@ void LUA_SetHudHook(int hook, huddrawlist_h list)
break; break;
case HUD_HOOK(intermission): case HUD_HOOK(intermission):
lua_pushboolean(gL, intertype == int_spec && lua_pushboolean(gL, stagefailed);
stagefailed);
} }
} }

View file

@ -800,8 +800,9 @@ static int sector_set(lua_State *L)
case sector_fslope: // f_slope case sector_fslope: // f_slope
case sector_cslope: // c_slope case sector_cslope: // c_slope
case sector_friction: // friction case sector_friction: // friction
default:
return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); 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 case sector_floorheight: { // floorheight
boolean flag; boolean flag;
mobj_t *ptmthing = tmthing; mobj_t *ptmthing = tmthing;
@ -1279,8 +1280,9 @@ static int side_set(lua_State *L)
case side_sector: case side_sector:
case side_special: case side_special:
case side_text: case side_text:
default:
return luaL_error(L, "side_t field " LUA_QS " cannot be set.", side_opt[field]); 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: case side_textureoffset:
side->textureoffset = luaL_checkfixed(L, 3); side->textureoffset = luaL_checkfixed(L, 3);
break; break;
@ -2291,8 +2293,9 @@ static int ffloor_set(lua_State *L)
case ffloor_target: // target case ffloor_target: // target
case ffloor_next: // next case ffloor_next: // next
case ffloor_prev: // prev case ffloor_prev: // prev
default:
return luaL_error(L, "ffloor_t field " LUA_QS " cannot be set.", ffloor_opt[field]); 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 case ffloor_topheight: { // topheight
boolean flag; boolean flag;
fixed_t lastpos = *ffloor->topheight; fixed_t lastpos = *ffloor->topheight;
@ -2426,8 +2429,9 @@ static int slope_set(lua_State *L)
case slope_d: // d case slope_d: // d
case slope_flags: // flags case slope_flags: // flags
case slope_normal: // normal case slope_normal: // normal
default:
return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]); 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 case slope_o: { // o
luaL_checktype(L, 3, LUA_TTABLE); luaL_checktype(L, 3, LUA_TTABLE);

View file

@ -25,6 +25,7 @@ enum skin {
skin_flags, skin_flags,
skin_realname, skin_realname,
skin_hudname, skin_hudname,
skin_supername,
skin_ability, skin_ability,
skin_ability2, skin_ability2,
skin_thokitem, skin_thokitem,
@ -63,6 +64,7 @@ static const char *const skin_opt[] = {
"flags", "flags",
"realname", "realname",
"hudname", "hudname",
"supername",
"ability", "ability",
"ability2", "ability2",
"thokitem", "thokitem",
@ -126,6 +128,9 @@ static int skin_get(lua_State *L)
case skin_hudname: case skin_hudname:
lua_pushstring(L, skin->hudname); lua_pushstring(L, skin->hudname);
break; break;
case skin_supername:
lua_pushstring(L, skin->supername);
break;
case skin_ability: case skin_ability:
lua_pushinteger(L, skin->ability); lua_pushinteger(L, skin->ability);
break; break;

View file

@ -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->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
mt->scale = player->mo->scale; 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->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0; mt->pitch = mt->roll = 0;

View file

@ -467,6 +467,15 @@ UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data)
UINT8 M_MapLocked(INT32 mapnum, 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) if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0)
{ {
return false; return false;
@ -480,6 +489,48 @@ UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data)
return false; 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 M_CountEmblems(gamedata_t *data)
{ {
INT32 found = 0, i; INT32 found = 0, i;

View file

@ -252,6 +252,7 @@ void M_SilentUpdateSkinAvailabilites(void);
UINT8 M_AnySecretUnlocked(gamedata_t *data); UINT8 M_AnySecretUnlocked(gamedata_t *data);
UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data); UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data);
UINT8 M_MapLocked(INT32 mapnum, 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); INT32 M_CountEmblems(gamedata_t *data);
// Emblem shit // Emblem shit

View file

@ -2649,7 +2649,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval,
{ {
strncpy(curbgname, defaultname, 9); strncpy(curbgname, defaultname, 9);
curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
curbgyspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollyspeed; curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed;
} }
} }
return false; return false;
@ -2843,8 +2843,8 @@ static void M_HandleMenuPresState(menu_t *newMenu)
curfadevalue = 16; curfadevalue = 16;
curhidepics = hidetitlepics; curhidepics = hidetitlepics;
curbgcolor = -1; curbgcolor = -1;
curbgxspeed = titlescrollxspeed; curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
curbgyspeed = titlescrollyspeed; curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed;
curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus
curttmode = ttmode; curttmode = ttmode;
@ -3196,7 +3196,7 @@ boolean M_Responder(event_t *ev)
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_GAMEEND) || gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_GAMEEND)
return false; return false;
if (gamestate == GS_TITLESCREEN && finalecount < TICRATE) if (gamestate == GS_TITLESCREEN && finalecount < (cv_tutorialprompt.value ? TICRATE : 0))
return false; return false;
if (CON_Ready() && gamestate != GS_WAITINGPLAYERS) if (CON_Ready() && gamestate != GS_WAITINGPLAYERS)
@ -12054,6 +12054,136 @@ static INT32 setupm_fakeskin;
static menucolor_t *setupm_fakecolor; static menucolor_t *setupm_fakecolor;
static boolean colorgrid; 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) static void M_DrawSetupMultiPlayerMenu(void)
{ {
INT32 x, y, cursory = 0, flags = 0; INT32 x, y, cursory = 0, flags = 0;
@ -12172,32 +12302,54 @@ colordraw:
boolean stoprow = false; boolean stoprow = false;
menucolor_t *mc; // Last accessed color 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; x = 132;
y = 66; 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 // Draw grid
V_DrawFill(x-2, y-2, 132, 132, 159); V_DrawFill(x-2, y-2, 132, 132, 159);
for (j = 0; j < 8; j++) 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]); M_DrawColorRamp(x + i*w, y + j*16, w, 1, skincolors[mc->color]);
if (mc->color == setupm_fakecolor->color) // store current color position
if (mc == setupm_fakecolor) // store current color position
{ {
cx = x + i*w; cx = x + i*w;
cy = y + j*16; 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; 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_DOWNARROW:
case KEY_UPARROW: case KEY_UPARROW:
{ {
UINT8 i;
if (itemOn == 2 && colorgrid) if (itemOn == 2 && colorgrid)
{ {
for (i = 0; i < 16; i++) UINT16 index = M_GetColorGridIndex(setupm_fakecolor->color);
{ INT32 x = M_GridIndexToX(index);
setupm_fakecolor = (choice == KEY_UPARROW) ? setupm_fakecolor->prev : setupm_fakecolor->next; INT32 y = M_GridIndexToY(index);
while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors
setupm_fakecolor = (choice == KEY_UPARROW) ? setupm_fakecolor->prev : setupm_fakecolor->next; y += (choice == KEY_UPARROW) ? -1 : 1;
}
index = M_GridPosToGridIndex(x, y);
setupm_fakecolor = M_GridIndexToMenuColor(index);
} }
else if (choice == KEY_UPARROW) else if (choice == KEY_UPARROW)
M_PrevOpt(); M_PrevOpt();
@ -12353,8 +12506,8 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
} }
else if (itemOn == 2) // player color else if (itemOn == 2) // player color
{ {
S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor = setupm_fakecolor->prev; setupm_fakecolor = setupm_fakecolor->prev;
S_StartSound(NULL,sfx_menu1); // Tails
} }
break; break;
@ -12393,8 +12546,8 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
} }
else if (itemOn == 2) // player color else if (itemOn == 2) // player color
{ {
S_StartSound(NULL,sfx_menu1); // Tails
setupm_fakecolor = setupm_fakecolor->next; setupm_fakecolor = setupm_fakecolor->next;
S_StartSound(NULL,sfx_menu1); // Tails
} }
break; break;
@ -12404,14 +12557,29 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
UINT8 i; UINT8 i;
if (itemOn == 2) // player color if (itemOn == 2) // player color
{ {
S_StartSound(NULL,sfx_menu1); if (colorgrid)
for (i = 0; i < (colorgrid ? 64 : 13); i++) // or (282-charw)/(2*indexwidth) {
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; setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next;
while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors
setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next;
} }
} }
S_StartSound(NULL, sfx_menu1); // Tails
}
} }
break; break;
@ -12440,7 +12608,6 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
} }
} }
break; break;
break;
case KEY_DEL: case KEY_DEL:
if (itemOn == 0 && (l = strlen(setupm_name))!=0) if (itemOn == 0 && (l = strlen(setupm_name))!=0)

View file

@ -1144,7 +1144,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!(mo2->type == MT_RING || mo2->type == MT_COIN 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 || 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; continue;
// Yay! The thing's in reach! Pull it in! // Yay! The thing's in reach! Pull it in!
@ -2235,7 +2235,7 @@ void P_CheckTimeLimit(void)
} }
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
//Optional tie-breaker for Match/CTF //Optional tie-breaker for Match/CTF
@ -2298,11 +2298,11 @@ void P_CheckTimeLimit(void)
} }
} }
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
if (server) 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. /** 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 ((UINT32)cv_pointlimit.value <= redscore || (UINT32)cv_pointlimit.value <= bluescore)
{ {
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
} }
else else
@ -2344,7 +2344,7 @@ void P_CheckPointLimit(void)
if ((UINT32)cv_pointlimit.value <= players[i].score) if ((UINT32)cv_pointlimit.value <= players[i].score)
{ {
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
return; return;
} }
} }
@ -2388,7 +2388,7 @@ void P_CheckSurvivors(void)
{ {
CONS_Printf(M_GetText("The IT player has left the game.\n")); CONS_Printf(M_GetText("The IT player has left the game.\n"));
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
return; return;
} }
@ -2408,7 +2408,7 @@ void P_CheckSurvivors(void)
{ {
CONS_Printf(M_GetText("All players have been tagged!\n")); CONS_Printf(M_GetText("All players have been tagged!\n"));
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
return; return;
@ -2420,7 +2420,7 @@ void P_CheckSurvivors(void)
{ {
CONS_Printf(M_GetText("There are no players able to become IT.\n")); CONS_Printf(M_GetText("There are no players able to become IT.\n"));
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
return; return;
@ -2432,7 +2432,7 @@ void P_CheckSurvivors(void)
{ {
CONS_Printf(M_GetText("All players have been tagged!\n")); CONS_Printf(M_GetText("All players have been tagged!\n"));
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
} }

View file

@ -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) boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
{ {
subsector_t *s = R_PointInSubsector(x, y); subsector_t *s = R_PointInSubsector(x, y);
boolean retval = true;
boolean itsatwodlevel = false; boolean itsatwodlevel = false;
floatok = 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 tryx = thiscam->x;
fixed_t tryy = thiscam->y; fixed_t tryy = thiscam->y;
if ((thiscam == &camera && (players[displayplayer].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))) || (thiscam == &camera2 && (players[secondarydisplayplayer].pflags & PF_NOCLIP || players[secondarydisplayplayer].powers[pw_carry] == CR_NIGHTSMODE)))
{ // Noclipping player camera noclips too!! { // Noclipping player camera noclips too!!
floatok = true; floatok = true;
thiscam->floorz = thiscam->z; thiscam->floorz = thiscam->z;
@ -2608,7 +2607,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
thiscam->y = y; thiscam->y = y;
thiscam->subsector = s; thiscam->subsector = s;
return retval; return true;
} }
// //

View file

@ -3688,7 +3688,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
dummy.y = thiscam->y; dummy.y = thiscam->y;
dummy.z = thiscam->z; dummy.z = thiscam->z;
dummy.height = thiscam->height; 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); P_ResetCamera(player, thiscam);
else else
{ {
@ -3719,7 +3719,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
// adjust height // adjust height
thiscam->z += thiscam->momz + player->mo->pmomz; 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 // clip movement
if (thiscam->z <= thiscam->floorz) // hit the floor 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->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
mo->scale = mo->destscale = mo->target->scale; mo->scale = mo->destscale = mo->target->scale;
mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir; 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)) if (!(mo->state->frame & FF_ANIMATE))
zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale); zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
@ -9228,7 +9227,7 @@ static void P_DragonbomberThink(mobj_t *mobj)
else else
{ {
fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); 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; angle_t diff = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) - mobj->angle;
if (diff > ANGLE_180) if (diff > ANGLE_180)
mobj->angle -= DRAGONTURNSPEED; mobj->angle -= DRAGONTURNSPEED;
@ -10564,6 +10563,29 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
case MT_REDFLAG: case MT_REDFLAG:
case MT_BLUEFLAG: 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_EMBLEM:
case MT_TOKEN: case MT_TOKEN:
@ -11832,7 +11854,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
mapthing_t *huntemeralds[MAXHUNTEMERALDS]; mapthing_t *huntemeralds[MAXHUNTEMERALDS];
INT32 numhuntemeralds; 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); 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. // Establish height.
if (flip) 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 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) 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 dz = mthing->z << FRACBITS; // Base offset from the floor.
fixed_t offset = 0; // Specific scaling object offset. fixed_t offset = 0; // Specific scaling object offset.
boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP));
boolean absolutez = !!(mthing->options & MTF_ABSOLUTEZ);
switch (mobjtype) 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; 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) if (flip)
return ONCEILINGZ; return ONCEILINGZ;
@ -11915,7 +11938,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt
return ONFLOORZ; 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) 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); dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0);
if (flip && mobj->height != oldheight) 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) if (!flip)
{ {
@ -13412,7 +13435,7 @@ void P_SpawnHoop(mapthing_t *mthing)
vector4_t v, res; vector4_t v, res;
fixed_t x = mthing->x << FRACBITS; fixed_t x = mthing->x << FRACBITS;
fixed_t y = mthing->y << 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 = P_SpawnMobj(x, y, z, MT_HOOPCENTER);
hoopcenter->spawnpoint = mthing; 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]); 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++) 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]); 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++) for (i = 0; i < numitems; i++)
{ {

View file

@ -491,7 +491,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing);
void P_MovePlayerToStarpost(INT32 playernum); void P_MovePlayerToStarpost(INT32 playernum);
void P_AfterPlayerSpawn(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); 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); mobj_t *P_SpawnMapThing(mapthing_t *mthing);

View file

@ -50,6 +50,7 @@
#include "m_random.h" #include "m_random.h"
#include "dehacked.h" // for map headers #include "dehacked.h" // for map headers
#include "deh_tables.h" // FREE_SKINCOLORS
#include "r_main.h" #include "r_main.h"
#include "m_cond.h" // for emblems #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) static void P_WriteSkincolor(INT32 constant, char **target)
{ {
const char *color_name;
if (constant <= SKINCOLOR_NONE if (constant <= SKINCOLOR_NONE
|| constant >= (INT32)numskincolors) || constant >= (INT32)numskincolors)
return; return;
if (constant >= SKINCOLOR_FIRSTFREESLOT)
color_name = FREE_SKINCOLORS[constant - SKINCOLOR_FIRSTFREESLOT];
else
color_name = COLOR_ENUMS[constant];
P_WriteDuplicateText( P_WriteDuplicateText(
va("SKINCOLOR_%s", skincolors[constant].name), va("SKINCOLOR_%s", color_name),
target target
); );
} }
@ -2025,6 +2033,8 @@ static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *
// Flags // Flags
else if (fastcmp(param, "flip") && fastcmp("true", val)) else if (fastcmp(param, "flip") && fastcmp("true", val))
mapthings[i].options |= MTF_OBJECTFLIP; 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) else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9)
{ {
@ -6810,6 +6820,9 @@ static void P_ConvertBinaryThingTypes(void)
default: default:
break; 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); CONS_Printf(M_GetText("Current map %d replaced by added file, ending the level to ensure consistency.\n"), gamemap);
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
return true; return true;

View file

@ -566,6 +566,7 @@ static void line_SpawnViaMapthingVertexes(const int linenum, const boolean spawn
case TMSP_BACKCEILING: case TMSP_BACKCEILING:
slopetoset = &line->backsector->c_slope; slopetoset = &line->backsector->c_slope;
side = &sides[line->sidenum[1]]; side = &sides[line->sidenum[1]];
break;
default: default:
return; return;
} }

View file

@ -3286,19 +3286,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
foundrover = true; foundrover = true;
// If fading an invisible FOF whose render flags we did not yet set, // If fading an invisible FOF whose render flags we did not yet set,
// initialize its alpha to 1 // initialize its alpha to 0 for relative alpha calculation
// for relative alpha calc
if (!(line->args[3] & TMST_DONTDOTRANSLUCENT) && // do translucent 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_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE
!(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERSIDES) &&
!(rover->spawnflags & FOF_RENDERPLANES) && !(rover->spawnflags & FOF_RENDERPLANES) &&
!(rover->fofflags & FOF_RENDERALL)) !(rover->fofflags & FOF_RENDERALL))
rover->alpha = 1; rover->alpha = 0;
P_RemoveFakeFloorFader(rover); P_RemoveFakeFloorFader(rover);
P_FadeFakeFloor(rover, P_FadeFakeFloor(rover,
rover->alpha, 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 0, // set alpha immediately
false, NULL, // tic-based logic false, NULL, // tic-based logic
false, // do not handle FOF_EXISTS false, // do not handle FOF_EXISTS
@ -3372,19 +3371,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
else else
{ {
// If fading an invisible FOF whose render flags we did not yet set, // If fading an invisible FOF whose render flags we did not yet set,
// initialize its alpha to 1 // initialize its alpha to 1 for relative alpha calculation
// for relative alpha calc
if (!(line->args[4] & TMFT_DONTDOTRANSLUCENT) && // do translucent 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_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE
!(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERSIDES) &&
!(rover->spawnflags & FOF_RENDERPLANES) && !(rover->spawnflags & FOF_RENDERPLANES) &&
!(rover->fofflags & FOF_RENDERALL)) !(rover->fofflags & FOF_RENDERALL))
rover->alpha = 1; rover->alpha = 0;
P_RemoveFakeFloorFader(rover); P_RemoveFakeFloorFader(rover);
P_FadeFakeFloor(rover, P_FadeFakeFloor(rover,
rover->alpha, 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 0, // set alpha immediately
false, NULL, // tic-based logic false, NULL, // tic-based logic
!(line->args[4] & TMFT_DONTDOEXISTS), // do not handle FOF_EXISTS !(line->args[4] & TMFT_DONTDOEXISTS), // do not handle FOF_EXISTS
@ -6565,10 +6563,10 @@ void P_SpawnSpecials(boolean fromnetsave)
//Cutting options //Cutting options
if (ffloorflags & FOF_RENDERALL) if (ffloorflags & FOF_RENDERALL)
{ {
//If inside is visible, cut inner walls //If inside is visible from the outside, cut inner walls
if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFA_SPLAT) || (lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) if (lines[i].args[1] < 255 || (lines[i].args[3] & TMFA_SPLAT))
ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA; ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA;
else else if (!(lines[i].args[4] & TMFT_VISIBLEFROMINSIDE))
ffloorflags |= FOF_CUTLEVEL; ffloorflags |= FOF_CUTLEVEL;
} }
@ -6624,20 +6622,19 @@ void P_SpawnSpecials(boolean fromnetsave)
if (lines[i].args[4] & TMFC_SPLAT) if (lines[i].args[4] & TMFC_SPLAT)
ffloorflags |= FOF_SPLAT; ffloorflags |= FOF_SPLAT;
//If inside is visible, cut inner walls //If inside is visible from the outside, cut inner walls
if (lines[i].args[1] < 0xff || (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE) || (lines[i].args[4] & TMFC_SPLAT)) if (lines[i].args[1] < 255 || (lines[i].args[4] & TMFC_SPLAT))
ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA; ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA;
else //If player can view it from the inside, render insides
ffloorflags |= FOF_CUTLEVEL; else if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)
//If player can enter it, render insides
if (lines[i].args[3] & TMFT_VISIBLEFROMINSIDE)
{ {
if (ffloorflags & FOF_RENDERPLANES) if (ffloorflags & FOF_RENDERPLANES)
ffloorflags |= FOF_BOTHPLANES; ffloorflags |= FOF_BOTHPLANES;
if (ffloorflags & FOF_RENDERSIDES) if (ffloorflags & FOF_RENDERSIDES)
ffloorflags |= FOF_ALLSIDES; ffloorflags |= FOF_ALLSIDES;
} }
else
ffloorflags |= FOF_CUTLEVEL;
P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, lines[i].args[1], lines[i].args[2], ffloorflags, secthinkers);
if (lines[i].args[4] & TMFC_AIRBOB) if (lines[i].args[4] & TMFC_AIRBOB)
@ -6688,10 +6685,10 @@ void P_SpawnSpecials(boolean fromnetsave)
//Cutting options //Cutting options
if (ffloorflags & FOF_RENDERALL) if (ffloorflags & FOF_RENDERALL)
{ {
//If inside is visible, cut inner walls //If inside is visible from the outside, cut inner walls
if ((lines[i].args[1] < 255) || (lines[i].args[3] & TMFA_SPLAT) || (lines[i].args[4] & TMFT_VISIBLEFROMINSIDE)) if (lines[i].args[1] < 255 || (lines[i].args[3] & TMFA_SPLAT))
ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA; ffloorflags |= FOF_CUTEXTRA|FOF_EXTRA;
else else if (!(lines[i].args[4] & TMFT_VISIBLEFROMINSIDE))
ffloorflags |= FOF_CUTLEVEL; 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 if (rover->master->special == 258) // Laser block
return false; return false;
// If fading an invisible FOF whose render flags we did not yet set, // If fading an invisible FOF whose render flags we did not yet set, initialize its alpha to 1
// initialize its alpha to 1
if (dotranslucent && if (dotranslucent &&
(rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE (rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE
!(rover->fofflags & FOF_FOG) && // do not include fog !(rover->fofflags & FOF_FOG) && // do not include fog
!(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERSIDES) &&
!(rover->spawnflags & FOF_RENDERPLANES) && !(rover->spawnflags & FOF_RENDERPLANES) &&
!(rover->fofflags & FOF_RENDERALL)) !(rover->fofflags & FOF_RENDERALL))
rover->alpha = 1; rover->alpha = 0;
if (fadingdata) if (fadingdata)
alpha = fadingdata->alpha; 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 (doexists && !(rover->spawnflags & FOF_BUSTUP))
{ {
if (alpha <= 1) if (alpha <= 0)
rover->fofflags &= ~FOF_EXISTS; rover->fofflags &= ~FOF_EXISTS;
else else
rover->fofflags |= FOF_EXISTS; 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 (dotranslucent && !(rover->fofflags & FOF_FOG))
{ {
if (alpha >= 256) if (alpha >= 255)
{ {
if (!(rover->fofflags & FOF_CUTSOLIDS) && if (!(rover->fofflags & FOF_CUTSOLIDS) &&
(rover->spawnflags & 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 else // clamp fadingdata->alpha to software's alpha levels
{ {
if (alpha < 12) 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) else if (alpha < 38)
rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25; rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25;
else if (alpha < 64) else if (alpha < 64)
rover->alpha = destvalue >=38 && destvalue < 64 ? destvalue : 51; rover->alpha = destvalue >= 38 && destvalue < 64 ? destvalue : 51;
else if (alpha < 89) else if (alpha < 89)
rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76; rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76;
else if (alpha < 115) else if (alpha < 115)
@ -7982,7 +7978,7 @@ static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destval
else if (alpha < 243) else if (alpha < 243)
rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230; rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230;
else // Opaque 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; fade_t *d;
// If fading an invisible FOF whose render flags we did not yet set, // If fading an invisible FOF whose render flags we did not yet set, initialize its alpha to 1
// initialize its alpha to 1
if (dotranslucent && if (dotranslucent &&
(rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE (rover->spawnflags & FOF_NOSHADE) && // do not include light blocks, which don't set FOF_NOSHADE
!(rover->spawnflags & FOF_RENDERSIDES) && !(rover->spawnflags & FOF_RENDERSIDES) &&
!(rover->spawnflags & FOF_RENDERPLANES) && !(rover->spawnflags & FOF_RENDERPLANES) &&
!(rover->fofflags & FOF_RENDERALL)) !(rover->fofflags & FOF_RENDERALL))
rover->alpha = 1; rover->alpha = 0;
// already equal, nothing to do // 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; return;
d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); 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->ffloornum = (UINT32)ffloornum;
d->alpha = d->sourcevalue = rover->alpha; 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) if (ticbased)
{ {

View file

@ -1855,6 +1855,7 @@ void P_SpawnShieldOrb(player_t *player)
{ {
ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY); ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY);
P_SetTarget(&ov->target, shieldobj); P_SetTarget(&ov->target, shieldobj);
P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person
P_SetMobjState(ov, shieldobj->info->seestate); P_SetMobjState(ov, shieldobj->info->seestate);
P_SetTarget(&shieldobj->tracer, ov); 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); ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY);
P_SetTarget(&ov->target, shieldobj); P_SetTarget(&ov->target, shieldobj);
P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person
P_SetMobjState(ov, shieldobj->info->meleestate); P_SetMobjState(ov, shieldobj->info->meleestate);
} }
if (shieldobj->info->missilestate) if (shieldobj->info->missilestate)
{ {
ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY); ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY);
P_SetTarget(&ov->target, shieldobj); P_SetTarget(&ov->target, shieldobj);
P_SetTarget(&ov->dontdrawforviewmobj, player->mo); // Hide the shield in first-person
P_SetMobjState(ov, shieldobj->info->missilestate); P_SetMobjState(ov, shieldobj->info->missilestate);
} }
if (player->powers[pw_shield] & SH_FORCE) if (player->powers[pw_shield] & SH_FORCE)
@ -2005,14 +2008,14 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->standingslope = mobj->standingslope; ghost->standingslope = mobj->standingslope;
if (mobj->flags2 & MF2_OBJECTFLIP) if (mobj->flags2 & MF2_OBJECTFLIP)
ghost->flags |= MF2_OBJECTFLIP; ghost->flags2 |= MF2_OBJECTFLIP;
if (mobj->player && mobj->player->followmobj) if (mobj->player && mobj->player->followmobj)
{ {
mobj_t *ghost2 = P_SpawnGhostMobj(mobj->player->followmobj); mobj_t *ghost2 = P_SpawnGhostMobj(mobj->player->followmobj);
P_SetTarget(&ghost2->tracer, ghost); P_SetTarget(&ghost2->tracer, ghost);
P_SetTarget(&ghost->tracer, ghost2); 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); ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW);
} }
@ -8717,7 +8720,10 @@ void P_MovePlayer(player_t *player)
player->mo->height = P_GetPlayerHeight(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 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... // Crush test...
if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) 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->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! fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity!
// Finally, set its position // Finally, set its position
@ -11758,7 +11764,7 @@ void P_PlayerThink(player_t *player)
if (!total || ((4*exiting)/total) >= numneeded) if (!total || ((4*exiting)/total) >= numneeded)
{ {
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
else else
player->exiting = 3; player->exiting = 3;
@ -11766,7 +11772,7 @@ void P_PlayerThink(player_t *player)
else else
{ {
if (server) if (server)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); D_SendExitLevel(false);
} }
} }
@ -11864,7 +11870,7 @@ void P_PlayerThink(player_t *player)
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (!(mo2->type == MT_RING || mo2->type == MT_COIN 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)) || mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR))
continue; continue;

View file

@ -34,7 +34,7 @@ static CV_PossibleValue_t renderhitbox_cons_t[] = {
{RENDERHITBOX_RINGS, "Rings"}, {RENDERHITBOX_RINGS, "Rings"},
{0}}; {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_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); 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; INT32 cvmode = cv_renderhitbox.value;
if (multiplayer) // No hitboxes in multiplayer to avoid cheating
return false;
// Do not render bbox for these // Do not render bbox for these
switch (thing->type) switch (thing->type)
{ {

View file

@ -757,12 +757,12 @@ typedef struct drawseg_s
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value. // Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
INT16 *sprtopclip; INT16 *sprtopclip;
INT16 *sprbottomclip; INT16 *sprbottomclip;
INT16 *maskedtexturecol; fixed_t *maskedtexturecol;
struct visplane_s *ffloorplanes[MAXFFLOORS]; struct visplane_s *ffloorplanes[MAXFFLOORS];
INT32 numffloorplanes; INT32 numffloorplanes;
struct ffloor_s *thicksides[MAXFFLOORS]; struct ffloor_s *thicksides[MAXFFLOORS];
INT16 *thicksidecol; fixed_t *thicksidecol;
INT32 numthicksides; INT32 numthicksides;
fixed_t frontscale[MAXVIDWIDTH]; fixed_t frontscale[MAXVIDWIDTH];

View file

@ -292,6 +292,8 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
out->y = mobj->y; out->y = mobj->y;
out->z = mobj->z; out->z = mobj->z;
out->scale = mobj->scale; out->scale = mobj->scale;
out->radius = mobj->radius;
out->height = mobj->height;
out->subsector = mobj->subsector; out->subsector = mobj->subsector;
out->angle = mobj->player ? mobj->player->drawangle : mobj->angle; out->angle = mobj->player ? mobj->player->drawangle : mobj->angle;
out->pitch = mobj->pitch; 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->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac); out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
out->z = R_LerpFixed(mobj->old_z, mobj->z, 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->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); 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. // 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. // It seems existing mods visually break more often than not if it is interpolated.
out->spritexoffset = mobj->spritexoffset; out->spritexoffset = mobj->spritexoffset;
@ -340,6 +354,8 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst
out->y = mobj->y; out->y = mobj->y;
out->z = mobj->z; out->z = mobj->z;
out->scale = FRACUNIT; out->scale = FRACUNIT;
out->radius = mobj->radius;
out->height = mobj->height;
out->subsector = mobj->subsector; out->subsector = mobj->subsector;
out->angle = mobj->angle; out->angle = mobj->angle;
out->pitch = 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->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac); out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
out->scale = FRACUNIT; out->scale = FRACUNIT;
out->radius = mobj->radius;
out->height = mobj->height;
out->spritexscale = R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac); out->spritexscale = R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac);
out->spriteyscale = R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac); out->spriteyscale = R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac);
out->spritexoffset = R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac); out->spritexoffset = R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac);

View file

@ -63,6 +63,8 @@ typedef struct {
angle_t roll; angle_t roll;
angle_t spriteroll; angle_t spriteroll;
fixed_t scale; fixed_t scale;
fixed_t radius;
fixed_t height;
fixed_t spritexscale; fixed_t spritexscale;
fixed_t spriteyscale; fixed_t spriteyscale;
fixed_t spritexoffset; fixed_t spritexoffset;

View file

@ -41,16 +41,6 @@
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
#endif #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. // Fineangles in the SCREENWIDTH wide window.
#define FIELDOFVIEW 2048 #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_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_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_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_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); 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_ClearClipSegs();
} }
R_ClearDrawSegs(); R_ClearDrawSegs();
R_ClearSegTables();
R_ClearSprites(); R_ClearSprites();
Portal_InitList(); Portal_InitList();
@ -1489,29 +1481,17 @@ void R_RenderPlayerView(player_t *player)
Mask_Pre(&masks[nummasks - 1]); Mask_Pre(&masks[nummasks - 1]);
curdrawsegs = ds_p; 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_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime); PS_START_TIMING(ps_bsptime);
R_RenderBSPNode((INT32)numnodes - 1); R_RenderBSPNode((INT32)numnodes - 1);
PS_STOP_TIMING(ps_bsptime); 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]); Mask_Post(&masks[nummasks - 1]);
PS_START_TIMING(ps_sw_spritecliptime); PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites(drawsegs, NULL); R_ClipSprites(drawsegs, NULL);
PS_STOP_TIMING(ps_sw_spritecliptime); PS_STOP_TIMING(ps_sw_spritecliptime);
ps_numsprites.value.i = numvisiblesprites;
// Add skybox portals caused by sky visplanes. // Add skybox portals caused by sky visplanes.
if (cv_skybox.value && skyboxmo[0]) if (cv_skybox.value && skyboxmo[0])
@ -1602,6 +1582,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_shadow); CV_RegisterVar(&cv_shadow);
CV_RegisterVar(&cv_skybox); CV_RegisterVar(&cv_skybox);
CV_RegisterVar(&cv_ffloorclip); CV_RegisterVar(&cv_ffloorclip);
CV_RegisterVar(&cv_spriteclip);
CV_RegisterVar(&cv_cam_dist); CV_RegisterVar(&cv_cam_dist);
CV_RegisterVar(&cv_cam_still); CV_RegisterVar(&cv_cam_still);

View file

@ -114,7 +114,7 @@ extern consvar_t cv_chasecam, cv_chasecam2;
extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_flipcam, cv_flipcam2;
extern consvar_t cv_shadow; extern consvar_t cv_shadow;
extern consvar_t cv_ffloorclip; extern consvar_t cv_ffloorclip, cv_spriteclip;
extern consvar_t cv_translucency; extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
extern consvar_t cv_fov; extern consvar_t cv_fov;

View file

@ -53,10 +53,6 @@ INT32 numffloors;
#define visplane_hash(picnum,lightlevel,height) \ #define visplane_hash(picnum,lightlevel,height) \
((unsigned)((picnum)*3+(lightlevel)+(height)*7) & VISPLANEHASHMASK) ((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. // Clip values are the solid pixel bounding the range.
// floorclip starts out SCREENHEIGHT // floorclip starts out SCREENHEIGHT
@ -366,8 +362,6 @@ void R_ClearPlanes(void)
freehead = &(*freehead)->next; freehead = &(*freehead)->next;
} }
lastopening = openings;
// texture calculation // texture calculation
memset(cachedheight, 0, sizeof (cachedheight)); memset(cachedheight, 0, sizeof (cachedheight));
} }

View file

@ -60,9 +60,6 @@ extern visplane_t *floorplane;
extern visplane_t *ceilingplane; extern visplane_t *ceilingplane;
// Visplane related. // Visplane related.
extern INT16 *lastopening, *openings;
extern size_t maxopenings;
extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH]; extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH];
extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16]; extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16];
extern fixed_t cachedheight[MAXVIDHEIGHT]; extern fixed_t cachedheight[MAXVIDHEIGHT];

View file

@ -71,9 +71,22 @@ static fixed_t topfrac, topstep;
static fixed_t bottomfrac, bottomstep; static fixed_t bottomfrac, bottomstep;
static lighttable_t **walllights; static lighttable_t **walllights;
static INT16 *maskedtexturecol; static fixed_t *maskedtexturecol;
static fixed_t *maskedtextureheight = NULL; 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 // R_RenderMaskedSegRange
// ========================================================================== // ==========================================================================
@ -350,9 +363,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; dc_texturemid += (textureheight[texnum])*times + textureheight[texnum];
else else
dc_texturemid -= (textureheight[texnum])*times; dc_texturemid -= (textureheight[texnum])*times;
// calculate lighting
if (maskedtexturecol[dc_x] != INT16_MAX)
{
// Check for overflows first // Check for overflows first
overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS);
if (overflow_test < 0) overflow_test = -overflow_test; if (overflow_test < 0) overflow_test = -overflow_test;
@ -371,6 +382,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
continue; continue;
} }
// calculate lighting
if (dc_numlights) if (dc_numlights)
{ {
lighttable_t **xwalllights; lighttable_t **xwalllights;
@ -382,7 +394,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
dc_iscale = 0xffffffffu / (unsigned)spryscale; dc_iscale = 0xffffffffu / (unsigned)spryscale;
// draw the texture // draw the texture
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3);
for (i = 0; i < dc_numlights; i++) for (i = 0; i < dc_numlights; i++)
{ {
@ -457,63 +469,9 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
dc_iscale = 0xffffffffu / (unsigned)spryscale; dc_iscale = 0xffffffffu / (unsigned)spryscale;
// draw the texture // draw the texture
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 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); colfunc_2s(col);
}
spryscale += rw_scalestep; spryscale += rw_scalestep;
} }
} }
@ -857,16 +815,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// draw the columns // draw the columns
for (dc_x = x1; dc_x <= x2; dc_x++) 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) if (oldx != -1)
dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<<FRACBITS); dc_texturemid += FixedMul(ffloortextureslide, maskedtexturecol[oldx]-maskedtexturecol[dc_x]);
oldx = dc_x; oldx = dc_x;
} }
// Calculate bounds // Calculate bounds
// clamp the values if necessary to avoid overflows and rendering glitches caused by them // clamp the values if necessary to avoid overflows and rendering glitches caused by them
if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX;
else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac;
else sprtopscreen = windowtop = CLAMPMIN; else sprtopscreen = windowtop = CLAMPMIN;
@ -897,7 +855,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
dc_iscale = 0xffffffffu / (unsigned)spryscale; dc_iscale = 0xffffffffu / (unsigned)spryscale;
// Get data for the column // Get data for the column
col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3);
// SoM: New code does not rely on R_DrawColumnShadowed_8 which // SoM: New code does not rely on R_DrawColumnShadowed_8 which
// will (hopefully) put less strain on the stack. // will (hopefully) put less strain on the stack.
@ -1034,7 +992,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
colfunc_2s (col); colfunc_2s (col);
spryscale += rw_scalestep; spryscale += rw_scalestep;
} }
}
colfunc = colfuncs[BASEDRAWFUNC]; colfunc = colfuncs[BASEDRAWFUNC];
#undef CLAMPMAX #undef CLAMPMAX
@ -1270,7 +1227,7 @@ static void R_RenderSegLoop (void)
} }
oldtexturecolumn = texturecolumn; oldtexturecolumn = texturecolumn;
texturecolumn >>= FRACBITS; INT32 itexturecolumn = texturecolumn >> FRACBITS;
// texturecolumn and lighting are independent of wall tiers // texturecolumn and lighting are independent of wall tiers
if (segtextured) if (segtextured)
@ -1336,7 +1293,7 @@ static void R_RenderSegLoop (void)
dc_yl = yl; dc_yl = yl;
dc_yh = yh; dc_yh = yh;
dc_texturemid = rw_midtexturemid; 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; dc_texheight = textureheight[midtexture]>>FRACBITS;
//profile stuff --------------------------------------------------------- //profile stuff ---------------------------------------------------------
@ -1397,7 +1354,7 @@ static void R_RenderSegLoop (void)
dc_yl = yl; dc_yl = yl;
dc_yh = mid; dc_yh = mid;
dc_texturemid = rw_toptexturemid; 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; dc_texheight = textureheight[toptexture]>>FRACBITS;
colfunc(); colfunc();
ceilingclip[rw_x] = (INT16)mid; ceilingclip[rw_x] = (INT16)mid;
@ -1433,8 +1390,7 @@ static void R_RenderSegLoop (void)
dc_yl = mid; dc_yl = mid;
dc_yh = yh; dc_yh = yh;
dc_texturemid = rw_bottomtexturemid; dc_texturemid = rw_bottomtexturemid;
dc_source = R_GetColumn(bottomtexture, dc_source = R_GetColumn(bottomtexture, itexturecolumn + (rw_offset_bot>>FRACBITS));
texturecolumn + (rw_offset_bot>>FRACBITS));
dc_texheight = textureheight[bottomtexture]>>FRACBITS; dc_texheight = textureheight[bottomtexture]>>FRACBITS;
colfunc(); colfunc();
floorclip[rw_x] = (INT16)mid; floorclip[rw_x] = (INT16)mid;
@ -1453,7 +1409,7 @@ static void R_RenderSegLoop (void)
{ {
// save texturecol // save texturecol
// for backdrawing of masked mid texture // 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) { if (maskedtextureheight != NULL) {
maskedtextureheight[rw_x] = (curline->linedef->flags & ML_MIDPEG) ? 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 // R_StoreWallRange
// A wall segment will be drawn // A wall segment will be drawn
@ -1580,37 +1603,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
ds_p->curline = curline; ds_p->curline = curline;
rw_stopx = stop+1; 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 // calculate scale at both ends and step
ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); 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_toptexturemid += sidedef->rowoffset + sidedef->offsety_top;
rw_bottomtexturemid += sidedef->rowoffset + sidedef->offsety_bot; rw_bottomtexturemid += sidedef->rowoffset + sidedef->offsety_bot;
R_AllocTextureColumnTables(rw_stopx - start);
// allocate space for masked texture tables // allocate space for masked texture tables
if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) 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; //markceiling = markfloor = true;
maskedtexture = true; maskedtexture = true;
ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x; ds_p->thicksidecol = maskedtexturecol = curtexturecolumntable - rw_x;
lastopening += rw_stopx - rw_x; curtexturecolumntable += rw_stopx - rw_x;
lowcut = max(worldbottom, worldlow) + viewz; lowcut = max(worldbottom, worldlow) + viewz;
highcut = min(worldtop, worldhigh) + viewz; highcut = min(worldtop, worldhigh) + viewz;
@ -2224,8 +2218,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// masked midtexture // masked midtexture
if (!ds_p->thicksidecol) if (!ds_p->thicksidecol)
{ {
ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x;
lastopening += rw_stopx - rw_x; curtexturecolumntable += rw_stopx - rw_x;
} }
else else
ds_p->maskedtexturecol = ds_p->thicksidecol; ds_p->maskedtexturecol = ds_p->thicksidecol;
@ -2737,29 +2731,34 @@ void R_StoreWallRange(INT32 start, INT32 stop)
ds_p->portalpass = 0; ds_p->portalpass = 0;
// save sprite clipping info // save sprite clipping info
if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM)))
{
R_AllocClippingTables(rw_stopx - start);
if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip)
{ {
M_Memcpy(lastopening, ceilingclip+start, 2*(rw_stopx - start)); M_Memcpy(lastopening, ceilingclip + start, 2*(rw_stopx - start));
ds_p->sprtopclip = lastopening - start; ds_p->sprtopclip = lastopening - start;
lastopening += rw_stopx - start; lastopening += rw_stopx - start;
} }
if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip)
{ {
M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx-start)); M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx - start));
ds_p->sprbottomclip = lastopening - start; ds_p->sprbottomclip = lastopening - start;
lastopening += rw_stopx - start; lastopening += rw_stopx - start;
} }
}
if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
{ {
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)) if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
{ {
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++; ds_p++;
} }

View file

@ -22,5 +22,6 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha);
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); 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_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor);
void R_StoreWallRange(INT32 start, INT32 stop); void R_StoreWallRange(INT32 start, INT32 stop);
void R_ClearSegTables(void);
#endif #endif

View file

@ -113,6 +113,7 @@ static void Sk_SetDefaultValue(skin_t *skin)
strcpy(skin->realname, "Someone"); strcpy(skin->realname, "Someone");
strcpy(skin->hudname, "???"); strcpy(skin->hudname, "???");
strcpy(skin->supername, "Someone super");
skin->starttranscolor = 96; skin->starttranscolor = 96;
skin->prefcolor = SKINCOLOR_GREEN; skin->prefcolor = SKINCOLOR_GREEN;
@ -693,7 +694,7 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile)
char *value; char *value;
size_t size; size_t size;
skin_t *skin; skin_t *skin;
boolean hudname, realname; boolean hudname, realname, supername;
// //
// search for all skin markers in pwad // search for all skin markers in pwad
@ -723,7 +724,7 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile)
skin = &skins[numskins]; skin = &skins[numskins];
Sk_SetDefaultValue(skin); Sk_SetDefaultValue(skin);
skin->wadnum = wadnum; skin->wadnum = wadnum;
hudname = realname = false; hudname = realname = supername = false;
// parse // parse
stoken = strtok (buf2, "\r\n= "); stoken = strtok (buf2, "\r\n= ");
while (stoken) while (stoken)
@ -766,7 +767,7 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile)
Z_Free(value2); Z_Free(value2);
} }
// copy to hudname and fullname as a default. // copy to hudname, realname, and supername as a default.
if (!realname) if (!realname)
{ {
STRBUFCPY(skin->realname, skin->name); STRBUFCPY(skin->realname, skin->name);
@ -782,6 +783,19 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile)
strupr(skin->hudname); strupr(skin->hudname);
SYMBOLCONVERT(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")) else if (!stricmp(stoken, "realname"))
{ // Display name (eg. "Knuckles") { // Display name (eg. "Knuckles")
@ -790,6 +804,13 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile)
SYMBOLCONVERT(skin->realname) SYMBOLCONVERT(skin->realname)
if (!hudname) if (!hudname)
HUDNAMEWRITE(skin->realname); 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")) else if (!stricmp(stoken, "hudname"))
{ // Life icon name (eg. "K.T.E") { // Life icon name (eg. "K.T.E")
@ -842,7 +863,7 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile)
char *value; char *value;
size_t size; size_t size;
skin_t *skin; skin_t *skin;
boolean noskincomplain, realname, hudname; boolean noskincomplain, realname, hudname, supername;
// //
// search for all skin patch markers in pwad // search for all skin patch markers in pwad
@ -866,7 +887,7 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile)
buf2[size] = '\0'; buf2[size] = '\0';
skin = NULL; 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) 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! else // Get the properties!
{ {
// Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. // 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") { // Display name (eg. "Knuckles")
realname = true; realname = true;
STRBUFCPY(skin->realname, value); STRBUFCPY(skin->realname, value);
SYMBOLCONVERT(skin->realname) SYMBOLCONVERT(skin->realname)
if (!hudname) if (!hudname)
HUDNAMEWRITE(skin->realname); 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")) else if (!stricmp(stoken, "hudname"))
{ // Life icon name (eg. "K.T.E") { // Life icon name (eg. "K.T.E")

View file

@ -35,8 +35,9 @@ typedef struct
UINT16 wadnum; UINT16 wadnum;
skinflags_t flags; 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 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 ability; // ability definition
UINT8 ability2; // secondary ability definition UINT8 ability2; // secondary ability definition

View file

@ -314,9 +314,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
fixed_t planeheight = 0; fixed_t planeheight = 0;
fixed_t step; fixed_t step;
int spanfunctype = SPANDRAWFUNC_SPRITE; int spanfunctype;
prepare_rastertab();
#define RASTERPARAMS(vnum1, vnum2, tv1, tv2, tc, dir) \ #define RASTERPARAMS(vnum1, vnum2, tv1, tv2, tc, dir) \
x1 = verts[vnum1].x; \ x1 = verts[vnum1].x; \
@ -367,21 +365,15 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
if (ry1 > maxy) \ if (ry1 > maxy) \
maxy = ry1; 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_source = (UINT8 *)pSplat->pic;
ds_flatwidth = pSplat->width; ds_flatwidth = pSplat->width;
ds_flatheight = pSplat->height; 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); R_SetFlatVars(ds_flatwidth * ds_flatheight);
ds_powersoftwo = true; ds_powersoftwo = true;
@ -392,9 +384,8 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
R_SetTiltedSpan(0); 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_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(); R_CalculateSlopeVectors();
spanfunctype = SPANDRAWFUNC_TILTEDSPRITE;
} }
else else if (!ds_solidcolor)
{ {
planeheight = abs(pSplat->z - vis->viewpoint.z); 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]; 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) if (pSplat->slope)
spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE; spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE;
else else
spanfunctype = SPANDRAWFUNC_TRANSSPRITE; spanfunctype = SPANDRAWFUNC_TRANSSPRITE;
} }
// Opaque
else 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]; spanfunc = spanfuncs[spanfunctype];
else else
spanfunc = spanfuncs_npo2[spanfunctype]; 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) if (maxy >= vid.height)
maxy = vid.height-1; maxy = vid.height-1;
@ -500,7 +538,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
if (x2 < x1) if (x2 < x1)
continue; continue;
if (!pSplat->slope) if (!ds_solidcolor && !pSplat->slope)
{ {
fixed_t xstep, ystep; fixed_t xstep, ystep;
fixed_t distance, span; fixed_t distance, span;
@ -549,7 +587,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
rastertab[y].maxx = INT32_MIN; rastertab[y].maxx = INT32_MIN;
} }
if (pSplat->angle && !pSplat->slope) if (!ds_solidcolor && pSplat->angle && !pSplat->slope)
memset(cachedheight, 0, sizeof(cachedheight)); memset(cachedheight, 0, sizeof(cachedheight));
} }

View file

@ -524,7 +524,8 @@ void R_AddSpriteDefs(UINT16 wadnum)
// //
// GAME FUNCTIONS // GAME FUNCTIONS
// //
UINT32 visspritecount; UINT32 visspritecount, numvisiblesprites;
static UINT32 clippedvissprites; static UINT32 clippedvissprites;
static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL}; static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL};
@ -598,7 +599,7 @@ void R_InitSprites(void)
// //
void R_ClearSprites(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 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. colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere.
dc_colormap = vis->colormap; dc_colormap = vis->colormap;
dc_translation = R_GetSpriteTranslation(vis); dc_translation = R_GetSpriteTranslation(vis);
@ -887,7 +897,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
frac = vis->startfrac; frac = vis->startfrac;
windowtop = windowbottom = sprbotscreen = INT32_MAX; 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); this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale);
if (this_scale <= 0) if (this_scale <= 0)
this_scale = 1; this_scale = 1;
@ -897,10 +907,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
{ {
vis->scale = FixedMul(vis->scale, this_scale); vis->scale = FixedMul(vis->scale, this_scale);
vis->scalestep = FixedMul(vis->scalestep, 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; vis->cut |= SC_ISSCALED;
} }
dc_texturemid = FixedDiv(dc_texturemid,this_scale); dc_texturemid = FixedDiv(dc_texturemid, this_scale);
} }
spryscale = vis->scale; spryscale = vis->scale;
@ -1184,7 +1194,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
R_InterpolateMobjState(thing, FRACUNIT, &interp); 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); floorz = P_GetFloorZ(thing, interp.subsector->sector, interp.x, interp.y, NULL);
ceilingz = P_GetCeilingZ(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))) if (isflipped ? (ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), interp.radius*3/2)))
: (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))) : (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), interp.radius*3/2))))
{ {
groundz = isflipped ? ceilingz : floorz; groundz = isflipped ? ceilingz : floorz;
groundslope = NULL; groundslope = NULL;
@ -1292,9 +1302,9 @@ static void R_SkewShadowSprite(
//CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope);
if (viewz < groundz) if (viewz < groundz)
*shadowyscale += FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); *shadowyscale += FixedMul(FixedMul(interp.radius*2 / spriteheight, scalemul), zslope);
else else
*shadowyscale -= FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); *shadowyscale -= FixedMul(FixedMul(interp.radius*2 / spriteheight, scalemul), zslope);
*shadowyscale = abs((*shadowyscale)); *shadowyscale = abs((*shadowyscale));
*shadowskew = xslope; *shadowskew = xslope;
@ -1345,20 +1355,18 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
return; return;
} }
floordiff = abs((isflipped ? thing->height : 0) + interp.z - groundz); floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz);
trans = floordiff / (100*FRACUNIT) + 3; trans = floordiff / (100*FRACUNIT) + 3;
if (trans >= 9) return; if (trans >= 9) return;
scalemul = FixedMul(FRACUNIT - floordiff/640, scale); 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); patch = W_CachePatchName("DSHADOW", PU_SPRITE);
xscale = FixedDiv(projection, tz); xscale = FixedDiv(projection, tz);
yscale = FixedDiv(projectiony, tz); yscale = FixedDiv(projectiony, tz);
shadowxscale = FixedMul(thing->radius*2, scalemul); shadowxscale = FixedMul(interp.radius*2, scalemul);
shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz)); shadowyscale = FixedMul(FixedMul(interp.radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz));
shadowyscale = min(shadowyscale, shadowxscale) / patch->height; shadowyscale = min(shadowyscale, shadowxscale) / patch->height;
shadowxscale /= patch->width; shadowxscale /= patch->width;
shadowskew = 0; shadowskew = 0;
@ -1484,8 +1492,8 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis)
// 0--2 // 0--2
// start in the (0) corner // start in the (0) corner
gx = interp.x - thing->radius - viewx; gx = interp.x - interp.radius - viewx;
gy = interp.y - thing->radius - viewy; gy = interp.y - interp.radius - viewy;
tz = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); 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 = R_NewVisSprite();
box->mobj = thing; box->mobj = thing;
box->mobjflags = thing->flags; box->mobjflags = thing->flags;
box->thingheight = thing->height; box->thingheight = interp.height;
box->cut = SC_BBOX; box->cut = SC_BBOX;
box->gx = tx; box->gx = tx;
box->gy = tz; box->gy = tz;
box->scale = 2 * FixedMul(thing->radius, viewsin); box->scale = 2 * FixedMul(interp.radius, viewsin);
box->xscale = 2 * FixedMul(thing->radius, viewcos); box->xscale = 2 * FixedMul(interp.radius, viewcos);
box->pz = interp.z; box->pz = interp.z;
box->pzt = box->pz + box->thingheight; 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 tr_x, tr_y;
fixed_t tx, tz; fixed_t tx, tz;
fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! 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 sortscale, sortsplat = 0;
fixed_t linkscale = 0; fixed_t linkscale = 0;
fixed_t sort_x = 0, sort_y = 0, sort_z; 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; this_scale = interp.scale;
radius = interp.radius; // For drop shadows
height = interp.height; // Ditto
// transform the origin point // transform the origin point
tr_x = interp.x - viewx; tr_x = interp.x - viewx;
@ -1758,9 +1769,6 @@ static void R_ProjectSprite(mobj_t *thing)
I_Assert(lump < max_spritelumps); 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_width = spritecachedinfo[lump].width;
spr_height = spritecachedinfo[lump].height; spr_height = spritecachedinfo[lump].height;
spr_offset = spritecachedinfo[lump].offset; spr_offset = spritecachedinfo[lump].offset;
@ -1810,6 +1818,14 @@ static void R_ProjectSprite(mobj_t *thing)
// calculate edges of the shape // calculate edges of the shape
spritexscale = interp.spritexscale; spritexscale = interp.spritexscale;
spriteyscale = interp.spriteyscale; 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) if (spritexscale < 1 || spriteyscale < 1)
return; return;
@ -1977,6 +1993,8 @@ static void R_ProjectSprite(mobj_t *thing)
{ {
R_InterpolateMobjState(thing, FRACUNIT, &tracer_interp); 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_x = (tracer_interp.x + sort_x) - viewx;
tr_y = (tracer_interp.y + sort_y) - viewy; 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) if (abs(groundz-viewz)/tz > 4)
return; // Prevent stretchy shadows and possible crashes 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); trans += ((floordiff / (100*FRACUNIT)) + 3);
shadowscale = FixedMul(FRACUNIT - floordiff/640, casterinterp.scale); shadowscale = FixedMul(FRACUNIT - floordiff/640, casterinterp.scale);
} }
@ -2083,8 +2101,8 @@ static void R_ProjectSprite(mobj_t *thing)
if (shadowdraw) if (shadowdraw)
{ {
spritexscale = FixedMul(thing->radius * 2, FixedMul(shadowscale, spritexscale)); spritexscale = FixedMul(radius * 2, FixedMul(shadowscale, spritexscale));
spriteyscale = FixedMul(thing->radius * 2, FixedMul(shadowscale, spriteyscale)); spriteyscale = FixedMul(radius * 2, FixedMul(shadowscale, spriteyscale));
spriteyscale = FixedMul(spriteyscale, FixedDiv(abs(groundz - viewz), tz)); spriteyscale = FixedMul(spriteyscale, FixedDiv(abs(groundz - viewz), tz));
spriteyscale = min(spriteyscale, spritexscale) / patch->height; spriteyscale = min(spriteyscale, spritexscale) / patch->height;
spritexscale /= patch->width; 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); 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; gz = gzt - patch->height * spriteyscale;
cut |= SC_SHEAR; 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. // 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. // 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! // 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)); gzt = gz + FixedMul(spr_height, FixedMul(spriteyscale, this_scale));
} }
else else
@ -2193,7 +2211,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->gy = interp.y; vis->gy = interp.y;
vis->gz = gz; vis->gz = gz;
vis->gzt = gzt; vis->gzt = gzt;
vis->thingheight = thing->height; vis->thingheight = height;
vis->pz = interp.z; vis->pz = interp.z;
vis->pzt = vis->pz + vis->thingheight; vis->pzt = vis->pz + vis->thingheight;
vis->texturemid = FixedDiv(gzt - viewz, spriteyscale); vis->texturemid = FixedDiv(gzt - viewz, spriteyscale);
@ -2633,6 +2651,14 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
// bundle linkdraw // bundle linkdraw
for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev) 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)) if (!(ds->cut & SC_LINKDRAW))
continue; continue;
@ -2659,21 +2685,27 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
continue; continue;
// don't connect if the tracer's top is cut off, but lower than the link's top // don't connect if the tracer's top is cut off, but lower than the link's top
if ((dsfirst->cut & SC_TOP) if ((dsfirst->cut & SC_TOP) && dsfirst->szt > ds->szt)
&& dsfirst->szt > ds->szt)
continue; continue;
// don't connect if the tracer's bottom is cut off, but higher than the link's bottom // don't connect if the tracer's bottom is cut off, but higher than the link's bottom
if ((dsfirst->cut & SC_BOTTOM) if ((dsfirst->cut & SC_BOTTOM) && dsfirst->sz < ds->sz)
&& dsfirst->sz < ds->sz)
continue; 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; break;
} }
// remove from chain // remove from chain
ds->next->prev = ds->prev; ds->next->prev = ds->prev;
ds->prev->next = ds->next; ds->prev->next = ds->next;
if (ds->cut & SC_NOTVISIBLE)
continue;
linkedvissprites++; linkedvissprites++;
if (dsfirst != &unsorted) if (dsfirst != &unsorted)
@ -2725,6 +2757,8 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
best = ds; best = ds;
} }
} }
if (best)
{
best->next->prev = best->prev; best->next->prev = best->prev;
best->prev->next = best->next; best->prev->next = best->next;
best->next = vsprsortedhead; best->next = vsprsortedhead;
@ -2732,6 +2766,7 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
vsprsortedhead->prev->next = best; vsprsortedhead->prev->next = best;
vsprsortedhead->prev = 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 // R_ClipVisSprite
// Clips vissprites without drawing, so that portals can work. -Red // Clips vissprites without drawing, so that portals can work. -Red
static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal) 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; spr->clipbot[x] = (INT16)viewheight;
if (spr->cliptop[x] == -2) if (spr->cliptop[x] == -2)
//Fab : 26-04-98: was -1, now clips against console bottom spr->cliptop[x] = -1;
spr->cliptop[x] = (INT16)con_clipviewtop;
} }
if (portal) if (portal)
@ -3330,6 +3402,14 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port
spr->cliptop[x] = -1; 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) 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); 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; continue;
}
if (spr->cut & SC_BBOX)
{
numvisiblesprites++;
continue;
}
INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1; INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1;
INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2; 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); R_ClipVisSprite(spr, x1, x2, portal);
if ((spr->cut & SC_NOTVISIBLE) == 0)
numvisiblesprites++;
} }
} }

View file

@ -123,21 +123,22 @@ typedef enum
SC_NONE = 0, SC_NONE = 0,
SC_TOP = 1, SC_TOP = 1,
SC_BOTTOM = 1<<1, SC_BOTTOM = 1<<1,
SC_NOTVISIBLE = 1<<2,
// other flags // other flags
SC_PRECIP = 1<<2, SC_PRECIP = 1<<3,
SC_LINKDRAW = 1<<3, SC_LINKDRAW = 1<<4,
SC_FULLBRIGHT = 1<<4, SC_FULLBRIGHT = 1<<5,
SC_SEMIBRIGHT = 1<<5, SC_SEMIBRIGHT = 1<<6,
SC_FULLDARK = 1<<6, SC_FULLDARK = 1<<7,
SC_VFLIP = 1<<7, SC_VFLIP = 1<<8,
SC_ISSCALED = 1<<8, SC_ISSCALED = 1<<9,
SC_ISROTATED = 1<<9, SC_ISROTATED = 1<<10,
SC_SHADOW = 1<<10, SC_SHADOW = 1<<11,
SC_SHEAR = 1<<11, SC_SHEAR = 1<<12,
SC_SPLAT = 1<<12, SC_SPLAT = 1<<13,
SC_BBOX = 1<<13, SC_BBOX = 1<<14,
// masks // masks
SC_CUTMASK = SC_TOP|SC_BOTTOM, SC_CUTMASK = SC_TOP|SC_BOTTOM|SC_NOTVISIBLE,
SC_FLAGMASK = ~SC_CUTMASK SC_FLAGMASK = ~SC_CUTMASK
} spritecut_e; } spritecut_e;
@ -219,7 +220,7 @@ typedef struct vissprite_s
INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing
} vissprite_t; } vissprite_t;
extern UINT32 visspritecount; extern UINT32 visspritecount, numvisiblesprites;
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal); void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);

View file

@ -90,7 +90,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#include <kvm.h> #include <kvm.h>
#endif #endif
#include <nlist.h> #include <nlist.h>
#include <sys/vmmeter.h> #include <sys/sysctl.h>
#endif #endif
#endif #endif
@ -325,8 +325,10 @@ static void write_backtrace(INT32 signal)
static void I_ReportSignal(int num, int coredumped) static void I_ReportSignal(int num, int coredumped)
{ {
//static char msg[] = "oh no! back to reality!\r\n"; //static char msg[] = "oh no! back to reality!\r\n";
const char *sigmsg, *sigttl; const char *sigmsg, *signame;
char ttl[128]; 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) switch (num)
{ {
@ -335,16 +337,16 @@ static void I_ReportSignal(int num, int coredumped)
// sigmsg = "SRB2 was interrupted prematurely by the user."; // sigmsg = "SRB2 was interrupted prematurely by the user.";
// break; // break;
case SIGILL: case SIGILL:
sigmsg = "SRB2 has attempted to execute an illegal instruction and needs to close. %s"; sigmsg = "SRB2 has attempted to execute an illegal instruction and needs to close.";
sigttl = "SIGILL"; // illegal instruction - invalid function image signame = "SIGILL"; // illegal instruction - invalid function image
break; break;
case SIGFPE: case SIGFPE:
sigmsg = "SRB2 has encountered a mathematical exception and needs to close. %s"; sigmsg = "SRB2 has encountered a mathematical exception and needs to close.";
sigttl = "SIGFPE"; // mathematical exception signame = "SIGFPE"; // mathematical exception
break; break;
case SIGSEGV: case SIGSEGV:
sigmsg = "SRB2 has attempted to access a memory location that it shouldn't and needs to close. %s"; sigmsg = "SRB2 has attempted to access a memory location that it shouldn't and needs to close.";
sigttl = "SIGSEGV"; // segment violation signame = "SIGSEGV"; // segment violation
break; break;
// case SIGTERM: // case SIGTERM:
// sigmsg = "SRB2 was terminated by a kill signal."; // 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 // sigttl = "SIGBREAK" // Ctrl-Break sequence
// break; // break;
case SIGABRT: case SIGABRT:
sigmsg = "SRB2 was terminated by an abort signal. %s"; sigmsg = "SRB2 was terminated by an abort signal.";
sigttl = "SIGABRT"; // abnormal termination triggered by abort call signame = "SIGABRT"; // abnormal termination triggered by abort call
break; break;
default: default:
sigmsg = "SRB2 was terminated by an unknown signal. %s"; sigmsg = "SRB2 was terminated by an unknown signal.";
sprintf(ttl, "number %d", num); sprintf(ttl, "number %d", num);
if (coredumped) if (coredumped)
sigttl = 0; signame = 0;
else else
sigttl = ttl; signame = ttl;
} }
if (coredumped) if (coredumped)
{ {
if (sigttl) if (signame)
sprintf(ttl, "%s (core dumped)", sigttl); sprintf(ttl, "%s (core dumped)", signame);
else else
strcat(ttl, " (core dumped)"); strcat(ttl, " (core dumped)");
sigttl = ttl; signame = ttl;
} }
sprintf(ttl, "Process killed by signal: %s", sigttl); strcat(sigttl, signame);
I_OutputMsg("%s\n", sigttl);
sigttl = ttl;
I_OutputMsg("\n%s\n\n", sigttl);
if (M_CheckParm("-dedicated")) if (M_CheckParm("-dedicated"))
return; return;
@ -396,8 +395,7 @@ static void I_ReportSignal(int num, int coredumped)
SDL_MESSAGEBOX_ERROR, /* .flags */ SDL_MESSAGEBOX_ERROR, /* .flags */
NULL, /* .window */ NULL, /* .window */
sigttl, /* .title */ sigttl, /* .title */
va(sigmsg, va("%s %s", sigmsg, reportmsg), /* .message */
"\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 */
SDL_arraysize(buttons), /* .numbuttons */ SDL_arraysize(buttons), /* .numbuttons */
buttons, /* .buttons */ buttons, /* .buttons */
NULL /* .colorScheme */ NULL /* .colorScheme */
@ -3035,40 +3033,17 @@ static long get_entry(const char* name, const char* buf)
size_t I_GetFreeMem(size_t *total) size_t I_GetFreeMem(size_t *total)
{ {
#ifdef FREEBSD #ifdef FREEBSD
struct vmmeter sum; u_int v_free_count, v_page_size, v_page_count;
kvm_t *kd; size_t size = sizeof(v_free_count);
struct nlist namelist[] = sysctlbyname("vm.stat.vm.v_free_count", &v_free_count, &size, NULL, 0);
{ size_t size = sizeof(v_page_size);
#define X_SUM 0 sysctlbyname("vm.stat.vm.v_page_size", &v_page_size, &size, NULL, 0);
{"_cnt"}, size_t size = sizeof(v_page_count);
{NULL} sysctlbyname("vm.stat.vm.v_page_count", &v_page_count, &size, NULL, 0);
};
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);
if (total) if (total)
*total = sum.v_page_count * sum.v_page_size; *total = v_page_count * v_page_size;
return sum.v_free_count * sum.v_page_size; return v_free_count * v_page_size;
#elif defined (SOLARIS) #elif defined (SOLARIS)
/* Just guess */ /* Just guess */
if (total) if (total)

View file

@ -1593,7 +1593,6 @@ boolean VID_CheckRenderer(void)
else if (vid.glstate == VID_GL_LIBRARY_ERROR) else if (vid.glstate == VID_GL_LIBRARY_ERROR)
rendererchanged = false; rendererchanged = false;
} }
else
#endif #endif
if (!contextcreated) if (!contextcreated)

View file

@ -174,7 +174,7 @@ static huddrawlist_h luahuddrawlist_titlecard;
skincolornum_t linkColor[3][NUMLINKCOLORS] = { skincolornum_t linkColor[3][NUMLINKCOLORS] = {
{SKINCOLOR_SHAMROCK, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, {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_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_TAFFY, SKINCOLOR_RUBY, SKINCOLOR_GARNET, SKINCOLOR_TOPAZ, SKINCOLOR_LEMON, SKINCOLOR_LIME},
{SKINCOLOR_ISLAND, SKINCOLOR_TURQUOISE, SKINCOLOR_DREAM, SKINCOLOR_DAYBREAK, SKINCOLOR_VAPOR, SKINCOLOR_FUCHSIA, {SKINCOLOR_ISLAND, SKINCOLOR_TURQUOISE, SKINCOLOR_DREAM, SKINCOLOR_DAYBREAK, SKINCOLOR_VAPOR, SKINCOLOR_FUCHSIA,
SKINCOLOR_VIOLET, SKINCOLOR_EVENTIDE, SKINCOLOR_KETCHUP, SKINCOLOR_FOUNDATION, SKINCOLOR_HEADLIGHT, SKINCOLOR_CHARTREUSE}}; 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) static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset)
{ {
INT32 interval, i; 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; 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) if (dist < 128)

View file

@ -15,7 +15,7 @@
#include <string.h> #include <string.h>
#include "doomdef.h" #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 // Like the OpenBSD version, but it doesn't check for src not being a valid
// C string. // C string.

View file

@ -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 ). // 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. // 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. // 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. // 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". // 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 this as a prerelease version suffix (pre#, RC#)
//#define BETAVERSION "pre1" //#define BETAVERSION "pre1"

View file

@ -77,8 +77,8 @@ END
#include "../doomdef.h" // Needed for version string #include "../doomdef.h" // Needed for version string
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,2,11,0 FILEVERSION 2,2,13,0
PRODUCTVERSION 2,2,11,0 PRODUCTVERSION 2,2,13,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L

View file

@ -998,8 +998,7 @@ void Y_Ticker(void)
if (paused || P_AutoPause()) if (paused || P_AutoPause())
return; return;
LUA_HookBool(intertype == int_spec && stagefailed, LUA_HookBool(stagefailed, HOOK(IntermissionThinker));
HOOK(IntermissionThinker));
intertic++; intertic++;
@ -1477,10 +1476,10 @@ void Y_StartIntermission(void)
if (players[consoleplayer].charflags & SF_SUPER) if (players[consoleplayer].charflags & SF_SUPER)
{ {
strcpy(data.spec.passed3, "can now become"); strcpy(data.spec.passed3, "can now become");
snprintf(data.spec.passed4, if (strlen(skins[players[consoleplayer].skin].supername) > 20) //too long, use generic
sizeof data.spec.passed4, "Super %s", strcpy(data.spec.passed4, "their super form");
skins[players[consoleplayer].skin].realname); else
data.spec.passed4[sizeof data.spec.passed4 - 1] = '\0'; strcpy(data.spec.passed4, skins[players[consoleplayer].skin].supername);
} }
} }
else else