This commit is contained in:
Louis-Antoine 2020-02-19 22:40:54 +01:00
commit 12959ff4a9
81 changed files with 2537 additions and 1256 deletions

View file

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
# DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
# Version change is fine.
project(SRB2
VERSION 2.2.0
VERSION 2.2.1
LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})

View file

@ -1,4 +1,4 @@
version: 2.2.0.{branch}-{build}
version: 2.2.1.{branch}-{build}
os: MinGW
environment:
@ -83,7 +83,14 @@ before_build:
- ccache -V
- ccache -s
- if [%NOUPX%] == [1] ( set "NOUPX=NOUPX=1" ) else ( set "NOUPX=" )
- set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 NOOBJDUMP=1 %NOUPX%"
- if defined [%APPVEYOR_PULL_REQUEST_HEAD_COMMIT%] ( set "COMMIT=%APPVEYOR_PULL_REQUEST_HEAD_COMMIT%" ) else ( set "COMMIT=%APPVEYOR_REPO_COMMIT%" )
- cmd: git rev-parse --short %COMMIT%>%TMP%/gitshort.txt
- cmd: set /P GITSHORT=<%TMP%/gitshort.txt
# for pull requests, take the owner's name only, if this isn't the same repo of course
- set "REPO=%APPVEYOR_REPO_BRANCH%"
- if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [] ( if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [%APPVEYOR_REPO_NAME%] ( for /f "delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set "REPO=%%a-%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%" ) )
- set "EXENAME=EXENAME=srb2win-%REPO%-%GITSHORT%.exe"
- set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 NOOBJDUMP=1 %NOUPX% %EXENAME%"
- if [%X86_64%] == [1] ( set "MINGW_FLAGS=MINGW64=1 X86_64=1 GCC81=1" ) else ( set "MINGW_FLAGS=MINGW=1 GCC91=1" )
- set "SRB2_MFLAGS=%SRB2_MFLAGS% %MINGW_FLAGS% %CONFIGURATION%=1"
@ -99,10 +106,8 @@ after_build:
)
- if [%X86_64%] == [1] ( set "CONFIGURATION=%CONFIGURATION%64" )
- ccache -s
- cmd: git rev-parse --short %APPVEYOR_REPO_COMMIT%>%TMP%/gitshort.txt
- cmd: set /P GITSHORT=<%TMP%/gitshort.txt
- set BUILD_ARCHIVE=%APPVEYOR_REPO_BRANCH%-%GITSHORT%-%CONFIGURATION%.7z
- set BUILDSARCHIVE=%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%.7z
- set BUILD_ARCHIVE=%REPO%-%GITSHORT%-%CONFIGURATION%.7z
- set BUILDSARCHIVE=%REPO%-%CONFIGURATION%.7z
- cmd: 7z a %BUILD_ARCHIVE% %BUILD_PATH% -xr!.gitignore
- appveyor PushArtifact %BUILD_ARCHIVE%
- cmd: copy %BUILD_ARCHIVE% %BUILDSARCHIVE%

View file

@ -160,6 +160,7 @@ static boolean am_stopped = true;
static INT32 f_x, f_y; // location of window on screen (always zero for both)
static INT32 f_w, f_h; // size of window on screen (always the screen width and height respectively)
static boolean m_keydown[4]; // which window panning keys are being pressed down?
static mpoint_t m_paninc; // how far the window pans each tic (map coords)
static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords)
@ -205,6 +206,7 @@ static boolean followplayer = true; // specifies whether to follow the player ar
typedef void (*AMDRAWFLINEFUNC) (const fline_t *fl, INT32 color);
static AMDRAWFLINEFUNC AM_drawFline;
static void AM_drawPixel(INT32 xx, INT32 yy, INT32 cc);
static void AM_drawFline_soft(const fline_t *fl, INT32 color);
static void AM_activateNewScale(void)
@ -344,22 +346,22 @@ static void AM_initVariables(void)
old_m_h = m_h;
}
//
// Called when the screen size changes.
//
static void AM_FrameBufferInit(void)
{
f_x = f_y = 0;
f_w = vid.width;
f_h = vid.height;
}
//
// should be called at the start of every level
// right now, i figure it out myself
//
static void AM_LevelInit(void)
{
f_x = f_y = 0;
f_w = vid.width;
f_h = vid.height;
AM_drawFline = AM_drawFline_soft;
#ifdef HWRENDER
if (rendermode == render_opengl)
AM_drawFline = HWR_drawAMline;
#endif
AM_findMinMaxBoundaries();
scale_mtof = FixedDiv(min_scale_mtof*10, 7*FRACUNIT);
if (scale_mtof > max_scale_mtof)
@ -381,7 +383,7 @@ void AM_Stop(void)
*
* \sa AM_Stop
*/
static inline void AM_Start(void)
void AM_Start(void)
{
static INT32 lastlevel = -1;
@ -390,8 +392,12 @@ static inline void AM_Start(void)
am_stopped = false;
if (lastlevel != gamemap || am_recalc) // screen size changed
{
AM_LevelInit();
lastlevel = gamemap;
AM_FrameBufferInit();
if (lastlevel != gamemap)
{
AM_LevelInit();
lastlevel = gamemap;
}
am_recalc = false;
}
AM_initVariables();
@ -417,6 +423,28 @@ static void AM_maxOutWindowScale(void)
AM_activateNewScale();
}
//
// set window panning
//
static void AM_setWindowPanning(void)
{
// up and down
if (m_keydown[2]) // pan up
m_paninc.y = FTOM(F_PANINC);
else if (m_keydown[3]) // pan down
m_paninc.y = -FTOM(F_PANINC);
else
m_paninc.y = 0;
// left and right
if (m_keydown[0]) // pan right
m_paninc.x = FTOM(F_PANINC);
else if (m_keydown[1]) // pan left
m_paninc.x = -FTOM(F_PANINC);
else
m_paninc.x = 0;
}
/** Responds to user inputs in automap mode.
*
* \param ev Event to possibly respond to.
@ -449,35 +477,49 @@ boolean AM_Responder(event_t *ev)
{
case AM_PANRIGHTKEY: // pan right
if (!followplayer)
m_paninc.x = FTOM(F_PANINC);
{
m_keydown[0] = true;
AM_setWindowPanning();
}
else
rc = false;
break;
case AM_PANLEFTKEY: // pan left
if (!followplayer)
m_paninc.x = -FTOM(F_PANINC);
{
m_keydown[1] = true;
AM_setWindowPanning();
}
else
rc = false;
break;
case AM_PANUPKEY: // pan up
if (!followplayer)
m_paninc.y = FTOM(F_PANINC);
{
m_keydown[2] = true;
AM_setWindowPanning();
}
else
rc = false;
break;
case AM_PANDOWNKEY: // pan down
if (!followplayer)
m_paninc.y = -FTOM(F_PANINC);
{
m_keydown[3] = true;
AM_setWindowPanning();
}
else
rc = false;
break;
case AM_ZOOMOUTKEY: // zoom out
mtof_zoommul = M_ZOOMOUT;
ftom_zoommul = M_ZOOMIN;
AM_setWindowPanning();
break;
case AM_ZOOMINKEY: // zoom in
mtof_zoommul = M_ZOOMIN;
ftom_zoommul = M_ZOOMOUT;
AM_setWindowPanning();
break;
case AM_TOGGLEKEY:
AM_Stop();
@ -491,6 +533,7 @@ boolean AM_Responder(event_t *ev)
}
else
AM_restoreScaleAndLoc();
AM_setWindowPanning();
break;
case AM_FOLLOWKEY:
followplayer = !followplayer;
@ -510,14 +553,32 @@ boolean AM_Responder(event_t *ev)
switch (ev->data1)
{
case AM_PANRIGHTKEY:
if (!followplayer)
{
m_keydown[0] = false;
AM_setWindowPanning();
}
break;
case AM_PANLEFTKEY:
if (!followplayer)
m_paninc.x = 0;
{
m_keydown[1] = false;
AM_setWindowPanning();
}
break;
case AM_PANUPKEY:
if (!followplayer)
{
m_keydown[2] = false;
AM_setWindowPanning();
}
break;
case AM_PANDOWNKEY:
if (!followplayer)
m_paninc.y = 0;
{
m_keydown[3] = false;
AM_setWindowPanning();
}
break;
case AM_ZOOMOUTKEY:
case AM_ZOOMINKEY:
@ -718,6 +779,17 @@ static boolean AM_clipMline(const mline_t *ml, fline_t *fl)
}
#undef DOOUTCODE
//
// Draws a pixel.
//
static void AM_drawPixel(INT32 xx, INT32 yy, INT32 cc)
{
UINT8 *dest = screens[0];
if (xx < 0 || yy < 0 || xx >= vid.width || yy >= vid.height)
return; // off the screen
dest[(yy*vid.width) + xx] = cc;
}
//
// Classic Bresenham w/ whatever optimizations needed for speed
//
@ -739,8 +811,6 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
}
#endif
#define PUTDOT(xx,yy,cc) V_DrawFill(xx,yy,1,1,cc|V_NOSCALESTART);
dx = fl->b.x - fl->a.x;
ax = 2 * (dx < 0 ? -dx : dx);
sx = dx < 0 ? -1 : 1;
@ -757,7 +827,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d = ay - ax/2;
for (;;)
{
PUTDOT(x, y, color)
AM_drawPixel(x, y, color);
if (x == fl->b.x)
return;
if (d >= 0)
@ -774,7 +844,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d = ax - ay/2;
for (;;)
{
PUTDOT(x, y, color)
AM_drawPixel(x, y, color);
if (y == fl->b.y)
return;
if (d >= 0)
@ -786,8 +856,6 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d += ax;
}
}
#undef PUTDOT
}
//
@ -1100,6 +1168,12 @@ void AM_Drawer(void)
if (!automapactive)
return;
AM_drawFline = AM_drawFline_soft;
#ifdef HWRENDER
if (rendermode == render_opengl)
AM_drawFline = HWR_drawAMline;
#endif
AM_clearFB(BACKGROUND);
if (draw_grid) AM_drawGrid(GRIDCOLORS);
AM_drawWalls();

View file

@ -38,6 +38,9 @@ void AM_Ticker(void);
// Called by main loop, instead of view drawer if automap is active.
void AM_Drawer(void);
// Enables the automap.
void AM_Start(void);
// Called to force the automap to quit if the level is completed while it is up.
void AM_Stop(void);

View file

@ -823,8 +823,13 @@ static void COM_Help_f(void)
if (!stricmp(cvar->PossibleValue[MINVAL].strvalue, "MIN"))
{
if (floatmode)
CONS_Printf(" range from %f to %f\n", FIXED_TO_FLOAT(cvar->PossibleValue[MINVAL].value),
FIXED_TO_FLOAT(cvar->PossibleValue[MAXVAL].value));
{
float fu = FIXED_TO_FLOAT(cvar->PossibleValue[MINVAL].value);
float ck = FIXED_TO_FLOAT(cvar->PossibleValue[MAXVAL].value);
CONS_Printf(" range from %ld%s to %ld%s\n",
(long)fu, M_Ftrim(fu),
(long)ck, M_Ftrim(ck));
}
else
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[MINVAL].value,
cvar->PossibleValue[MAXVAL].value);
@ -973,7 +978,10 @@ static void COM_Add_f(void)
}
if (( cvar->flags & CV_FLOAT ))
CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
{
float n =FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2));
CV_Set(cvar, va("%ld%s", (long)n, M_Ftrim(n)));
}
else
CV_AddValue(cvar, atoi(COM_Argv(2)));
}
@ -1458,7 +1466,7 @@ static void Got_NetVar(UINT8 **p, INT32 playernum)
// not from server or remote admin, must be hacked/buggy client
CONS_Alert(CONS_WARNING, M_GetText("Illegal netvar command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
netid = READUINT16(*p);

View file

@ -26,12 +26,12 @@
#else
/* Manually defined asset hashes for non-CMake builds
* Last updated 2019 / 12 / 06 - v2.2.0 - main assets
* Last updated 2020 / 02 / 15 - v2.2.1 - main assets
* Last updated 20?? / ?? / ?? - v2.2.? - patch.pk3
*/
#define ASSET_HASH_SRB2_PK3 "51419a33b4982d840c6772c159ba7c0a"
#define ASSET_HASH_ZONES_PK3 "df74843919fd51af26a0baa8e21e4c19"
#define ASSET_HASH_PLAYER_DTA "56a247e074dd0dc794b6617efef1e918"
#define ASSET_HASH_SRB2_PK3 "0277c9416756627004e83cbb5b2e3e28"
#define ASSET_HASH_ZONES_PK3 "f7e88afb6af7996a834c7d663144bead"
#define ASSET_HASH_PLAYER_DTA "ad49e07b17cc662f1ad70c454910b4ae"
#ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_PK3 "there is no patch.pk3, only zuul"
#endif

View file

@ -613,6 +613,15 @@ void CON_Ticker(void)
con_tick++;
con_tick &= 7;
// if the menu is open then close the console.
if (menuactive && con_destlines)
{
consoletoggle = false;
con_destlines = 0;
CON_ClearHUD();
I_UpdateMouseGrab();
}
// console key was pushed
if (consoletoggle)
{
@ -769,7 +778,7 @@ boolean CON_Responder(event_t *ev)
// check for console toggle key
if (ev->type != ev_console)
{
if (modeattacking || metalrecording || menuactive)
if (modeattacking || metalrecording)
return false;
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
@ -784,7 +793,7 @@ boolean CON_Responder(event_t *ev)
// check other keys only if console prompt is active
if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!!
{
if (! menuactive && bindtable[key])
if (bindtable[key])
{
COM_BufAddText(bindtable[key]);
COM_BufAddText("\n");

View file

@ -21,6 +21,7 @@
#include "d_net.h"
#include "d_main.h"
#include "g_game.h"
#include "st_stuff.h"
#include "hu_stuff.h"
#include "keys.h"
#include "g_input.h" // JOY1
@ -76,6 +77,7 @@ char motd[254], server_context[8]; // Message of the Day, Unique Context (even w
// Server specific vars
UINT8 playernode[MAXPLAYERS];
char playeraddress[MAXPLAYERS][64];
// Minimum timeout for sending the savegame
// The actual timeout will be longer depending on the savegame length
@ -391,7 +393,7 @@ static void ExtraDataTicker(void)
{
if (server)
{
SendKick(i, KICK_MSG_CON_FAIL);
SendKick(i, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic));
}
CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]);
@ -402,8 +404,8 @@ static void ExtraDataTicker(void)
}
// If you are a client, you can safely forget the net commands for this tic
// If you are the server, you need to remember them until every client has been aknowledged,
// because if you need to resend a PT_SERVERTICS packet, you need to put the commands in it
// If you are the server, you need to remember them until every client has been acknowledged,
// because if you need to resend a PT_SERVERTICS packet, you will need to put the commands in it
if (client)
D_FreeTextcmd(gametic);
}
@ -437,6 +439,9 @@ void SendKick(UINT8 playernum, UINT8 msg)
{
UINT8 buf[2];
if (!(server && cv_rejointimeout.value))
msg &= ~KICK_MSG_KEEP_BODY;
buf[0] = playernum;
buf[1] = msg;
SendNetXCmd(XD_KICK, &buf, 2);
@ -1058,7 +1063,7 @@ static void SV_SendResynch(INT32 node)
if (resynch_score[node] > (unsigned)cv_resynchattempts.value*250)
{
SendKick(nodetoplayer[node], KICK_MSG_CON_FAIL);
SendKick(nodetoplayer[node], KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
resynch_score[node] = 0;
}
}
@ -1273,8 +1278,14 @@ static boolean CL_SendJoin(void)
netbuffer->u.clientcfg.subversion = SUBVERSION;
strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION,
sizeof netbuffer->u.clientcfg.application);
CleanupPlayerName(consoleplayer, cv_playername.zstring);
if (splitscreen)
CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */
strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME);
strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME);
return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
}
@ -2413,6 +2424,7 @@ void CL_ClearPlayer(INT32 playernum)
if (players[playernum].mo)
P_RemoveMobj(players[playernum].mo);
memset(&players[playernum], 0, sizeof (player_t));
memset(playeraddress[playernum], 0, sizeof(*playeraddress));
}
//
@ -2420,7 +2432,7 @@ void CL_ClearPlayer(INT32 playernum)
//
// Removes a player from the current game
//
static void CL_RemovePlayer(INT32 playernum, INT32 reason)
static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
{
// Sanity check: exceptional cases (i.e. c-fails) can cause multiple
// kick commands to be issued for the same player.
@ -2433,9 +2445,6 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
playerpernode[node]--;
if (playerpernode[node] <= 0)
{
// If a resynch was in progress, well, it no longer needs to be.
SV_InitResynchVars(playernode[playernum]);
nodeingame[playernode[playernum]] = false;
Net_CloseConnection(playernode[playernum]);
ResetNode(node);
@ -2557,6 +2566,7 @@ void CL_Reset(void)
multiplayer = false;
servernode = 0;
server = true;
resynch_local_inprogress = false;
doomcom->numnodes = 1;
doomcom->numslots = 1;
SV_StopServer();
@ -2830,9 +2840,12 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
char buf[3 + MAX_REASONLENGTH];
char *reason = buf;
kickreason_t kickreason = KR_KICK;
boolean keepbody;
pnum = READUINT8(*p);
msg = READUINT8(*p);
keepbody = (msg & KICK_MSG_KEEP_BODY) != 0;
msg &= ~KICK_MSG_KEEP_BODY;
if (pnum == serverplayer && IsPlayerAdmin(playernum))
{
@ -2892,6 +2905,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
*/
pnum = playernum;
msg = KICK_MSG_CON_FAIL;
keepbody = true;
}
//CONS_Printf("\x82%s ", player_names[pnum]);
@ -2911,7 +2925,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
switch (msg)
{
case KICK_MSG_GO_AWAY:
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
if (!players[pnum].quittime)
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
kickreason = KR_KICK;
break;
case KICK_MSG_PING_HIGH:
@ -2960,7 +2975,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
kickreason = KR_TIMEOUT;
break;
case KICK_MSG_PLAYER_QUIT:
if (netgame) // not splitscreen/bots
if (netgame && !players[pnum].quittime) // not splitscreen/bots or soulless body
HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false);
kickreason = KR_LEAVE;
break;
@ -3001,6 +3016,24 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
else
M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
}
else if (keepbody)
{
if (server && !demoplayback)
{
INT32 node = playernode[pnum];
playerpernode[node]--;
if (playerpernode[node] <= 0)
{
nodeingame[node] = false;
Net_CloseConnection(node);
ResetNode(node);
}
}
playernode[pnum] = UINT8_MAX;
players[pnum].quittime = 1;
}
else
CL_RemovePlayer(pnum, kickreason);
}
@ -3009,6 +3042,9 @@ consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0,
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}};
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}};
consvar_t cv_rejointimeout = {"rejointimeout", "Off", CV_SAVE|CV_FLOAT, rejointimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}};
consvar_t cv_resynchattempts = {"resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
@ -3078,6 +3114,7 @@ static void ResetNode(INT32 node)
nodewaiting[node] = 0;
playerpernode[node] = 0;
sendingsavegame[node] = false;
SV_InitResynchVars(node);
}
void SV_ResetServer(void)
@ -3093,13 +3130,8 @@ void SV_ResetServer(void)
tictoclear = maketic;
for (i = 0; i < MAXNETNODES; i++)
{
ResetNode(i);
// Make sure resynch status doesn't get carried over!
SV_InitResynchVars(i);
}
for (i = 0; i < MAXPLAYERS; i++)
{
#ifdef HAVE_BLUA
@ -3107,6 +3139,7 @@ void SV_ResetServer(void)
#endif
playeringame[i] = false;
playernode[i] = UINT8_MAX;
memset(playeraddress[i], 0, sizeof(*playeraddress));
sprintf(player_names[i], "Player %d", i + 1);
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
}
@ -3199,6 +3232,37 @@ void D_QuitNetGame(void)
#endif
}
static INT32 FindRejoinerNum(SINT8 node)
{
char strippednodeaddress[64];
const char *nodeaddress;
char *port;
INT32 i;
// Make sure there is no dead dress before proceeding to the stripping
if (!I_GetNodeAddress)
return -1;
nodeaddress = I_GetNodeAddress(node);
if (!nodeaddress)
return -1;
// Strip the address of its port
strcpy(strippednodeaddress, nodeaddress);
port = strchr(strippednodeaddress, ':');
if (port)
*port = '\0';
// Check if any player matches the stripped address
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX
&& !strcmp(playeraddress[i], strippednodeaddress))
return i;
}
return -1;
}
// Adds a node to the game (player will follow at map change or at savegame....)
static inline void SV_AddNode(INT32 node)
{
@ -3215,13 +3279,16 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
{
INT16 node, newplayernum;
boolean splitscreenplayer;
boolean rejoined;
player_t *newplayer;
char *port;
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
// protect against hacked/buggy client
CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -3230,15 +3297,34 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
splitscreenplayer = newplayernum & 0x80;
newplayernum &= ~0x80;
// Clear player before joining, lest some things get set incorrectly
// HACK: don't do this for splitscreen, it relies on preset values
if (!splitscreen && !botingame)
CL_ClearPlayer(newplayernum);
playeringame[newplayernum] = true;
rejoined = playeringame[newplayernum];
if (!rejoined)
{
// Clear player before joining, lest some things get set incorrectly
// HACK: don't do this for splitscreen, it relies on preset values
if (!splitscreen && !botingame)
CL_ClearPlayer(newplayernum);
playeringame[newplayernum] = true;
G_AddPlayer(newplayernum);
if (newplayernum+1 > doomcom->numslots)
doomcom->numslots = (INT16)(newplayernum+1);
if (server && I_GetNodeAddress)
{
strcpy(playeraddress[newplayernum], I_GetNodeAddress(node));
port = strchr(playeraddress[newplayernum], ':');
if (port)
*port = '\0';
}
}
newplayer = &players[newplayernum];
newplayer->jointime = 0;
newplayer->quittime = 0;
READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME);
G_AddPlayer(newplayernum);
if (newplayernum+1 > doomcom->numslots)
doomcom->numslots = (INT16)(newplayernum+1);
// the server is creating my player
if (node == mynode)
@ -3256,29 +3342,67 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
secondarydisplayplayer = newplayernum;
DEBFILE("spawning my brother\n");
if (botingame)
players[newplayernum].bot = 1;
newplayer->bot = 1;
}
D_SendPlayerConfig();
addedtogame = true;
if (rejoined)
{
if (newplayer->mo)
{
if (!splitscreenplayer)
localangle = newplayer->mo->angle;
else
localangle2 = newplayer->mo->angle;
newplayer->viewheight = 41*newplayer->height/48;
if (newplayer->mo->eflags & MFE_VERTICALFLIP)
newplayer->viewz = newplayer->mo->z + newplayer->mo->height - newplayer->viewheight;
else
newplayer->viewz = newplayer->mo->z + newplayer->viewheight;
}
// wake up the status bar
ST_Start();
// wake up the heads up text
HU_Start();
if (camera.chase && !splitscreenplayer)
P_ResetCamera(newplayer, &camera);
if (camera2.chase && splitscreenplayer)
P_ResetCamera(newplayer, &camera2);
}
}
if (netgame)
{
if (server && cv_showjoinaddress.value)
{
const char *address;
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
HU_AddChatText(va("\x82*%s has joined the game (player %d) (%s)", player_names[newplayernum], newplayernum, address), false); // merge join notification + IP to avoid clogging console/chat.
}
char joinmsg[256];
if (rejoined)
strcpy(joinmsg, M_GetText("\x82*%s has rejoined the game (player %d)"));
else
HU_AddChatText(va("\x82*%s has joined the game (player %d)", player_names[newplayernum], newplayernum), false); // if you don't wanna see the join address.
strcpy(joinmsg, M_GetText("\x82*%s has joined the game (player %d)"));
strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum));
// Merge join notification + IP to avoid clogging console/chat
if (server && cv_showjoinaddress.value && I_GetNodeAddress)
{
const char *address = I_GetNodeAddress(node);
if (address)
strcat(joinmsg, va(" (%s)", address));
}
HU_AddChatText(joinmsg, false);
}
if (server && multiplayer && motd[0] != '\0')
COM_BufAddText(va("sayto %d %s\n", newplayernum, motd));
#ifdef HAVE_BLUA
LUAh_PlayerJoin(newplayernum);
if (!rejoined)
LUAh_PlayerJoin(newplayernum);
#endif
}
@ -3287,11 +3411,7 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2)
INT32 node, n, newplayer = false;
UINT8 buf[2 + MAXPLAYERNAME];
UINT8 *p;
UINT8 newplayernum = 0;
// What is the reason for this? Why can't newplayernum always be 0?
if (dedicated)
newplayernum = 1;
INT32 newplayernum;
for (node = 0; node < MAXNETNODES; node++)
{
@ -3300,68 +3420,22 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2)
{
newplayer = true;
if (netgame)
// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
//
// The line just after that comment is an awful, horrible, terrible, TERRIBLE hack.
//
// Basically, the fix I did in order to fix the download freezes happens
// to cause situations in which a player number does not match
// the node number associated to that player.
// That is totally normal, there is absolutely *nothing* wrong with that.
// Really. Player 7 being tied to node 29, for instance, is totally fine.
//
// HOWEVER. A few (broken) parts of the netcode do the TERRIBLE mistake
// of mixing up the concepts of node and player, resulting in
// incorrect handling of cases where a player is tied to a node that has
// a different number (which is a totally normal case, or at least should be).
// This incorrect handling can go as far as literally
// anyone from joining your server at all, forever.
//
// Given those two facts, there are two options available
// in order to let this download freeze fix be:
// 1) Fix the broken parts that assume a node is a player or similar bullshit.
// 2) Change the part this comment is located at, so that any player who joins
// is given the same number as their associated node.
//
// No need to say, 1) is by far the obvious best, whereas 2) is a terrible hack.
// Unfortunately, after trying 1), I most likely didn't manage to find all
// of those broken parts, and thus 2) has become the only safe option that remains.
//
// So I did this hack.
//
// If it isn't clear enough, in order to get rid of this ugly hack,
// you will have to fix all parts of the netcode that
// make a confusion between nodes and players.
//
// And if it STILL isn't clear enough, a node and a player
// is NOT the same thing. Never. NEVER. *NEVER*.
//
// And if someday you make the terrible mistake of
// daring to have the unforgivable idea to try thinking
// that a node might possibly be the same as a player,
// or that a player should have the same number as its node,
// be sure that I will somehow know about it and
// hunt you down tirelessly and make you regret it,
// even if you live on the other side of the world.
//
// TODO: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// \todo >>>>>>>>>> Remove this horrible hack as soon as possible <<<<<<<<<<
// TODO: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
newplayernum = node; // OMFG SAY WELCOME TO TEH NEW HACK FOR FIX FIL DOWNLOAD!!1!
else // Don't use the hack if we don't have to
newplayernum = FindRejoinerNum(node);
if (newplayernum == -1)
{
// search for a free playernum
// we can't use playeringame since it is not updated here
for (; newplayernum < MAXPLAYERS; newplayernum++)
for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++)
{
if (playeringame[newplayernum])
continue;
for (n = 0; n < MAXNETNODES; n++)
if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum)
break;
if (n == MAXNETNODES)
break;
}
}
// should never happen since we check the playernum
// before accepting the join
@ -3388,8 +3462,6 @@ static boolean SV_AddWaitingPlayers(const char *name, const char *name2)
SendNetXCmd(XD_ADDPLAYER, &buf, p - buf);
DEBFILE(va("Server added player %d node %d\n", newplayernum, node));
// use the next free slot (we can't put playeringame[newplayernum] = true here)
newplayernum++;
}
}
@ -3515,8 +3587,11 @@ static size_t TotalTextCmdPerTic(tic_t tic)
static void HandleConnect(SINT8 node)
{
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1];
INT32 rejoinernum;
INT32 i;
rejoinernum = FindRejoinerNum(node);
if (bannednode && bannednode[node])
SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
else if (netbuffer->u.clientcfg._255 != 255 ||
@ -3528,9 +3603,9 @@ static void HandleConnect(SINT8 node)
else if (netbuffer->u.clientcfg.version != VERSION
|| netbuffer->u.clientcfg.subversion != SUBVERSION)
SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION));
else if (!cv_allownewplayer.value && node)
else if (!cv_allownewplayer.value && node && rejoinernum == -1)
SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment"));
else if (D_NumPlayers() >= cv_maxplayers.value)
else if (D_NumPlayers() >= cv_maxplayers.value && rejoinernum == -1)
SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value));
else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client?
SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
@ -3549,7 +3624,7 @@ static void HandleConnect(SINT8 node)
for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++)
{
strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1);
if (!EnsurePlayerNameIsGood(names[i], -1))
if (!EnsurePlayerNameIsGood(names[i], rejoinernum))
{
SV_SendRefuse(node, "Bad player name");
return;
@ -3990,7 +4065,7 @@ static void HandlePacketFromPlayer(SINT8 node)
}
else
{
SendKick(netconsole, KICK_MSG_CON_FAIL);
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
netconsole, realstart, consistancy[realstart%BACKUPTICS],
SHORT(netbuffer->u.clientpak.consistancy)));
@ -4109,6 +4184,7 @@ static void HandlePacketFromPlayer(SINT8 node)
kickmsg = KICK_MSG_TIMEOUT;
else
kickmsg = KICK_MSG_PLAYER_QUIT;
kickmsg |= KICK_MSG_KEEP_BODY;
SendKick(netconsole, kickmsg);
nodetoplayer[node] = -1;
@ -4144,7 +4220,7 @@ static void HandlePacketFromPlayer(SINT8 node)
{
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHEND", node);
if (server)
SendKick(netconsole, KICK_MSG_CON_FAIL);
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
break;
}
resynch_local_inprogress = false;
@ -4162,7 +4238,7 @@ static void HandlePacketFromPlayer(SINT8 node)
{
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node);
if (server)
SendKick(netconsole, KICK_MSG_CON_FAIL);
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
break;
}
@ -4222,7 +4298,7 @@ static void HandlePacketFromPlayer(SINT8 node)
{
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHING", node);
if (server)
SendKick(netconsole, KICK_MSG_CON_FAIL);
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
break;
}
resynch_local_inprogress = true;
@ -4234,7 +4310,7 @@ static void HandlePacketFromPlayer(SINT8 node)
{
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node);
if (server)
SendKick(netconsole, KICK_MSG_CON_FAIL);
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
break;
}
@ -4258,7 +4334,7 @@ static void HandlePacketFromPlayer(SINT8 node)
{
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node);
if (server)
SendKick(netconsole, KICK_MSG_CON_FAIL);
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
break;
}
if (client)
@ -4460,7 +4536,7 @@ static void CL_SendClientCmd(void)
packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16);
HSendPacket(servernode, false, 0, packetsize);
}
else if (gamestate != GS_NULL)
else if (gamestate != GS_NULL && (addedtogame || dedicated))
{
G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1);
netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]);
@ -4634,8 +4710,14 @@ static void Local_Maketic(INT32 realtics)
G_BuildTiccmd(&localcmds2, realtics, 2);
localcmds.angleturn |= TICCMD_RECEIVED;
localcmds2.angleturn |= TICCMD_RECEIVED;
}
// This function is utter bullshit and is responsible for
// the random desynch that happens when a player spawns.
// This is because ticcmds are resent to clients if a packet
// was dropped, and thus modifying them can lead to several
// clients having their ticcmds set to different values.
void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
{
tic_t tic;
@ -4669,28 +4751,36 @@ void SV_SpawnPlayer(INT32 playernum, INT32 x, INT32 y, angle_t angle)
// create missed tic
static void SV_Maketic(void)
{
INT32 j;
INT32 i;
for (j = 0; j < MAXNETNODES; j++)
if (playerpernode[j])
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
// We didn't receive this tic
if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0)
{
INT32 player = nodetoplayer[j];
if ((netcmds[maketic%BACKUPTICS][player].angleturn & TICCMD_RECEIVED) == 0)
{ // we didn't receive this tic
INT32 i;
ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i];
ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i];
DEBFILE(va("MISS tic%4d for node %d\n", maketic, j));
#if defined(PARANOIA) && 0
CONS_Debug(DBG_NETPLAY, "Client Misstic %d\n", maketic);
#endif
// copy the old tic
for (i = 0; i < playerpernode[j]; i++, player = nodetoplayer2[j])
{
netcmds[maketic%BACKUPTICS][player] = netcmds[(maketic-1)%BACKUPTICS][player];
netcmds[maketic%BACKUPTICS][player].angleturn &= ~TICCMD_RECEIVED;
}
if (players[i].quittime)
{
// Copy the angle/aiming from the previous tic
// and empty the other inputs
memset(ticcmd, 0, sizeof(netcmds[0][0]));
ticcmd->angleturn = prevticcmd->angleturn | TICCMD_RECEIVED;
ticcmd->aiming = prevticcmd->aiming;
}
else
{
DEBFILE(va("MISS tic%4d for player %d\n", maketic, i));
// Copy the input from the previous tic
*ticcmd = *prevticcmd;
ticcmd->angleturn &= ~TICCMD_RECEIVED;
}
}
}
// all tic are now proceed make the next
maketic++;
@ -4812,7 +4902,7 @@ static inline void PingUpdate(void)
// ok your net has been bad for too long, you deserve to die.
{
pingtimeout[i] = 0;
SendKick(i, KICK_MSG_PING_HIGH);
SendKick(i, KICK_MSG_PING_HIGH | KICK_MSG_KEEP_BODY);
}
}
/*

View file

@ -491,6 +491,7 @@ extern consvar_t cv_playbackspeed;
#define KICK_MSG_PING_HIGH 6
#define KICK_MSG_CUSTOM_KICK 7
#define KICK_MSG_CUSTOM_BAN 8
#define KICK_MSG_KEEP_BODY 0x80
typedef enum
{
@ -518,7 +519,9 @@ extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS];
extern tic_t servermaxping;
extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;
extern consvar_t cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_rejointimeout;
extern consvar_t cv_resynchattempts, cv_blamecfail;
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
// Used in d_net, the only dependence
tic_t ExpandTics(INT32 low);

View file

@ -188,14 +188,14 @@ void D_ProcessEvents(void)
continue;
}
// console input
if (CON_Responder(ev))
continue; // ate the event
// Menu input
if (M_Responder(ev))
continue; // menu ate the event
// console input
if (CON_Responder(ev))
continue; // ate the event
G_Responder(ev);
}
}
@ -266,6 +266,9 @@ static void D_Display(void)
#endif
}
if (rendermode == render_soft && !splitscreen)
R_CheckViewMorph();
// change the view size if needed
if (setsizeneeded || setrenderstillneeded)
{
@ -446,6 +449,9 @@ static void D_Display(void)
// Image postprocessing effect
if (rendermode == render_soft)
{
if (!splitscreen)
R_ApplyViewMorph();
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
@ -502,12 +508,13 @@ static void D_Display(void)
// vid size change is now finished if it was on...
vid.recalc = 0;
M_Drawer(); // menu is drawn even on top of everything
// focus lost moved to M_Drawer
// FIXME: draw either console or menu, not the two
if (gamestate != GS_TIMEATTACK)
CON_Drawer();
M_Drawer(); // menu is drawn even on top of everything
// focus lost moved to M_Drawer
//
// wipe update
//
@ -651,8 +658,14 @@ void D_SRB2Loop(void)
// hack to start on a nice clear console screen.
COM_ImmedExecute("cls;version");
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE));
I_FinishUpdate(); // page flip or blit buffer
/*
LMFAO this was showing garbage under OpenGL
because I_FinishUpdate was called afterward
*/
/* Smells like a hack... Don't fade Sonic's ass into the title screen. */
if (gamestate != GS_TITLESCREEN)
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_CACHE));
for (;;)
{
@ -1202,15 +1215,10 @@ void D_SRB2Main(void)
// load wad, including the main wad file
CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n");
if (!W_InitMultipleFiles(startupwadfiles, mainwads))
#ifdef _DEBUG
CONS_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n");
#else
I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n");
#endif
W_InitMultipleFiles(startupwadfiles, mainwads);
D_CleanFile();
#ifndef DEVELOP // md5s last updated 06/12/19 (ddmmyy)
#ifndef DEVELOP // md5s last updated 16/02/20 (ddmmyy)
// Check MD5s of autoloaded files
W_VerifyFileMD5(0, ASSET_HASH_SRB2_PK3); // srb2.pk3
@ -1287,12 +1295,14 @@ void D_SRB2Main(void)
// Lactozilla: Does the render mode need to change?
if ((setrenderneeded != 0) && (setrenderneeded != rendermode))
{
CONS_Printf("Switching the renderer...\n");
needpatchflush = true;
needpatchrecache = true;
VID_CheckRenderer();
SCR_ChangeRendererCVars(setrenderneeded);
D_CheckRendererState();
setrenderneeded = 0;
}
D_CheckRendererState();
wipegamestate = gamestate;

View file

@ -370,7 +370,7 @@ consvar_t cv_advancemap = {"advancemap", "Next", CV_NETVAR, advancemap_cons_t, N
static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}};
consvar_t cv_playersforexit = {"playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_exitmove = {"exitmove", "Off", CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_exitmove = {"exitmove", "On", CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -581,6 +581,7 @@ void D_RegisterServerCommands(void)
// d_clisrv
CV_RegisterVar(&cv_maxplayers);
CV_RegisterVar(&cv_rejointimeout);
CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload);
@ -633,7 +634,7 @@ void D_RegisterClientCommands(void)
// Set default player names
// Monster Iestyn (12/08/19): not sure where else I could have actually put this, but oh well
for (i = 0; i < MAXPLAYERS; i++)
sprintf(player_names[i], "Player %d", i);
sprintf(player_names[i], "Player %d", 1 + i);
if (dedicated)
return;
@ -678,6 +679,7 @@ void D_RegisterClientCommands(void)
// GIF variables
CV_RegisterVar(&cv_gif_optimize);
CV_RegisterVar(&cv_gif_downscale);
CV_RegisterVar(&cv_gif_localcolortable);
#ifdef WALLSPLATS
CV_RegisterVar(&cv_splats);
@ -1009,7 +1011,7 @@ boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
* SetPlayerName
* \author Graue <graue@oceanbase.org>
*/
static void CleanupPlayerName(INT32 playernum, const char *newname)
void CleanupPlayerName(INT32 playernum, const char *newname)
{
char *buf;
char *p;
@ -1037,6 +1039,17 @@ static void CleanupPlayerName(INT32 playernum, const char *newname)
tmpname = p;
do
{
/* from EnsurePlayerNameIsGood */
if (!isprint(*p) || *p == ';' || (UINT8)*p >= 0x80)
break;
}
while (*++p) ;
if (*p)/* bad char found */
break;
// Remove trailing spaces.
p = &tmpname[strlen(tmpname)-1]; // last character
while (*p == ' ' && p >= tmpname)
@ -1126,7 +1139,7 @@ static void SetPlayerName(INT32 playernum, char *newname)
{
CONS_Printf(M_GetText("Player %d sent a bad name change\n"), playernum+1);
if (server && netgame)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
}
}
@ -1484,7 +1497,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
if (kick)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal color change received from %s (team: %d), color: %d)\n"), player_names[playernum], p->ctfteam, p->skincolor);
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
}
@ -2024,7 +2037,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal map change received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -2135,7 +2148,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal pause command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -2210,7 +2223,7 @@ static void Got_Suicide(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal suicide command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -2273,7 +2286,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal clear scores command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -2620,7 +2633,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
// this should never happen unless the client is hacked/buggy
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
}
if (NetPacket.packet.verification) // Special marker that the server sent the request
@ -2629,7 +2642,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
playernum = NetPacket.packet.playernum;
@ -2662,7 +2675,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
}
return;
}
@ -2721,7 +2734,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
if (server && ((NetPacket.packet.newteam < 0 || NetPacket.packet.newteam > 3) || error))
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
}
//Safety first!
@ -3013,7 +3026,7 @@ static void Got_Verification(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal verification received from %s (serverplayer is %s)\n"), player_names[playernum], player_names[serverplayer]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -3063,7 +3076,7 @@ static void Got_Removal(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal demotion received from %s (serverplayer is %s)\n"), player_names[playernum], player_names[serverplayer]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -3137,7 +3150,7 @@ static void Got_MotD_f(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal motd change received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
Z_Free(mymotd);
return;
}
@ -3193,7 +3206,7 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal runsoc command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -3351,7 +3364,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfile command received from %s\n"), player_names[playernum]);
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -3400,7 +3413,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfile command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -3738,9 +3751,15 @@ static void ExitMove_OnChange(void)
if (cv_exitmove.value)
{
for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo
&& players[i].mo->target && players[i].mo->target->type == MT_SIGN)
P_SetTarget(&players[i].mo->target, NULL);
if (playeringame[i] && players[i].mo)
{
if (players[i].mo->target && players[i].mo->target->type == MT_SIGN)
P_SetTarget(&players[i].mo->target, NULL);
if (players[i].pflags & PF_FINISHED)
P_GiveFinishFlags(&players[i]);
}
CONS_Printf(M_GetText("Players can now move after completing the level.\n"));
}
else
@ -4193,7 +4212,7 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal exitlevel command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}

View file

@ -195,6 +195,7 @@ typedef union {
// add game commands, needs cleanup
void D_RegisterServerCommands(void);
void D_RegisterClientCommands(void);
void CleanupPlayerName(INT32 playernum, const char *newname);
boolean EnsurePlayerNameIsGood(char *name, INT32 playernum);
void D_SendPlayerConfig(void);
void Command_ExitGame_f(void);

View file

@ -278,6 +278,7 @@ typedef enum
pw_nights_linkfreeze,
pw_nocontrol, //for linedef exec 427
pw_justlaunched, // Launched off a slope this tic (0=none, 1=standard launch, 2=half-pipe launch)
NUMPOWERS
} powertype_t;
@ -324,6 +325,8 @@ typedef struct player_s
// bounded/scaled total momentum.
fixed_t bob;
angle_t viewrollangle;
// Mouse aiming, where the guy is looking at!
// It is updated with cmd->aiming.
angle_t aiming;
@ -510,6 +513,7 @@ typedef struct player_s
UINT8 bot;
tic_t jointime; // Timer when player joins game to change skin/color
tic_t quittime; // Time elapsed since user disconnected, zero if connected
#ifdef HWRENDER
fixed_t fovadd; // adjust FOV for hw rendering
#endif

View file

@ -585,21 +585,30 @@ static void readfreeslots(MYFILE *f)
continue;
// Copy in the spr2 name and increment free_spr2.
if (free_spr2 < NUMPLAYERSPRITES) {
CONS_Printf("Sprite SPR2_%s allocated.\n",word);
strncpy(spr2names[free_spr2],word,4);
spr2defaults[free_spr2] = 0;
spr2names[free_spr2++][4] = 0;
} else
CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n");
deh_warning("Ran out of free SPR2 slots!\n");
}
else if (fastcmp(type, "TOL"))
{
if (lastcustomtol > 31)
CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n");
// Search if we already have a typeoflevel by that name...
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(word, TYPEOFLEVEL[i].name))
break;
// We found it? Then don't allocate another one.
if (TYPEOFLEVEL[i].name)
continue;
// We don't, so freeslot it.
if (lastcustomtol == (UINT32)MAXTOL) // Unless you have way too many, since they're flags.
deh_warning("Ran out of free typeoflevel slots!\n");
else
{
G_AddTOL((1<<lastcustomtol), word);
lastcustomtol++;
G_AddTOL(lastcustomtol, word);
lastcustomtol <<= 1;
}
}
else
@ -1105,38 +1114,7 @@ static void readsprite2(MYFILE *f, INT32 num)
Z_Free(s);
}
INT32 numtolinfo = NUMBASETOL;
UINT32 lastcustomtol = 13;
tolinfo_t TYPEOFLEVEL[NUMMAXTOL] = {
{"SOLO",TOL_SP},
{"SP",TOL_SP},
{"SINGLEPLAYER",TOL_SP},
{"SINGLE",TOL_SP},
{"COOP",TOL_COOP},
{"CO-OP",TOL_COOP},
{"COMPETITION",TOL_COMPETITION},
{"RACE",TOL_RACE},
{"MATCH",TOL_MATCH},
{"TAG",TOL_TAG},
{"CTF",TOL_CTF},
{"2D",TOL_2D},
{"MARIO",TOL_MARIO},
{"NIGHTS",TOL_NIGHTS},
{"OLDBRAK",TOL_ERZ3},
{"XMAS",TOL_XMAS},
{"CHRISTMAS",TOL_XMAS},
{"WINTER",TOL_XMAS},
{NULL, 0}
};
// copypasted from readPlayer :sleep:
// copypasted from readPlayer :]
static const char *const GAMETYPERULE_LIST[];
static void readgametype(MYFILE *f, char *gtname)
{
@ -1293,10 +1271,7 @@ static void readgametype(MYFILE *f, char *gtname)
UINT32 wordgt = 0;
for (j = 0; GAMETYPERULE_LIST[j]; j++)
if (fastcmp(word, GAMETYPERULE_LIST[j])) {
if (!j) // GTR_CAMPAIGN
wordgt |= 1;
else
wordgt |= (1<<j);
wordgt |= (1<<j);
if (i || word2[0] == 'T' || word2[0] == 'Y')
newgtrules |= wordgt;
break;
@ -1831,6 +1806,24 @@ static void readlevelheader(MYFILE *f, INT32 num)
else
mapheaderinfo[num-1]->levelflags &= ~LF_NOTITLECARD;
}
else if (fastcmp(word, "SHOWTITLECARDFOR"))
{
mapheaderinfo[num-1]->levelflags |= LF_NOTITLECARD;
tmp = strtok(word2,",");
do {
if (fastcmp(tmp, "FIRST"))
mapheaderinfo[num-1]->levelflags &= ~LF_NOTITLECARDFIRST;
else if (fastcmp(tmp, "RESPAWN"))
mapheaderinfo[num-1]->levelflags &= ~LF_NOTITLECARDRESPAWN;
else if (fastcmp(tmp, "RECORDATTACK"))
mapheaderinfo[num-1]->levelflags &= ~LF_NOTITLECARDRECORDATTACK;
else if (fastcmp(tmp, "ALL"))
mapheaderinfo[num-1]->levelflags &= ~LF_NOTITLECARD;
else if (!fastcmp(tmp, "NONE"))
deh_warning("Level header %d: unknown titlecard show option %s\n", num, tmp);
} while((tmp = strtok(NULL,",")) != NULL);
}
// Individual triggers for menu flags
else if (fastcmp(word, "HIDDEN"))
@ -4945,19 +4938,19 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_PLAY_SUPER_TRANS3",
"S_PLAY_SUPER_TRANS4",
"S_PLAY_SUPER_TRANS5",
"S_PLAY_SUPER_TRANS6", // This has special significance in the code. If you add more frames, search for it and make the appropriate changes.
"S_PLAY_SUPER_TRANS6",
// technically the player goes here but it's an infinite tic state
"S_OBJPLACE_DUMMY",
// 1-Up Box Sprites (uses player sprite)
// 1-Up Box Sprites overlay (uses player sprite)
"S_PLAY_BOX1",
"S_PLAY_BOX2",
"S_PLAY_ICON1",
"S_PLAY_ICON2",
"S_PLAY_ICON3",
// Level end sign (uses player sprite)
// Level end sign overlay (uses player sprite)
"S_PLAY_SIGN",
// NiGHTS character (uses player sprite)
@ -5205,7 +5198,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ROBOHOOD_JUMP2",
"S_ROBOHOOD_JUMP3",
// CastleBot FaceStabber
// Castlebot Facestabber
"S_FACESTABBER_STND1",
"S_FACESTABBER_STND2",
"S_FACESTABBER_STND3",
@ -5425,6 +5418,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_FLEE2",
"S_EGGMOBILE_BALL",
"S_EGGMOBILE_TARGET",
"S_BOSSEGLZ1",
"S_BOSSEGLZ2",
@ -5477,7 +5471,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE3_FLEE1",
"S_EGGMOBILE3_FLEE2",
// Boss 3 pinch
// Boss 3 Pinch
"S_FAKEMOBILE_INIT",
"S_FAKEMOBILE",
"S_FAKEMOBILE_ATK1",
@ -5493,7 +5487,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BOSSSEBH2",
// Boss 3 Shockwave
"S_SHOCKWAVE1",
"S_SHOCKWAVE2",
@ -5530,9 +5523,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_JETFLAME",
// Boss 4 Spectator Eggrobo
"S_EGGROBO1_IDLE",
"S_EGGROBO1_STND",
"S_EGGROBO1_BSLAP1",
"S_EGGROBO2_BSLAP2",
"S_EGGROBO1_BSLAP2",
"S_EGGROBO1_PISSED",
// Boss 4 Spectator Eggrobo jet flame
@ -5776,7 +5769,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CYBRAKDEMON_NAPALM_ATTACK1",
"S_CYBRAKDEMON_NAPALM_ATTACK2",
"S_CYBRAKDEMON_NAPALM_ATTACK3",
"S_CYBRAKDEMON_FINISH_ATTACK", // If just attacked, remove MF2_FRET w/out going back to spawnstate
"S_CYBRAKDEMON_FINISH_ATTACK1", // If just attacked, remove MF2_FRET w/out going back to spawnstate
"S_CYBRAKDEMON_FINISH_ATTACK2", // Force a delay between attacks so you don't get bombarded with them back-to-back
"S_CYBRAKDEMON_PAIN1",
"S_CYBRAKDEMON_PAIN2",
@ -6470,7 +6463,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_LITTLETUMBLEWEED_ROLL7",
"S_LITTLETUMBLEWEED_ROLL8",
// Cacti Sprites
// Cacti
"S_CACTI1",
"S_CACTI2",
"S_CACTI3",
@ -6485,7 +6478,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CACTITINYSEG",
"S_CACTISMALLSEG",
// Warning signs sprites
// Warning signs
"S_ARIDSIGN_CAUTION",
"S_ARIDSIGN_CACTI",
"S_ARIDSIGN_SHARPTURN",
@ -6502,6 +6495,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_TNTBARREL_EXPL4",
"S_TNTBARREL_EXPL5",
"S_TNTBARREL_EXPL6",
"S_TNTBARREL_EXPL7",
"S_TNTBARREL_FLYING",
// TNT proximity shell
@ -7047,7 +7041,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ZAPSB10",
"S_ZAPSB11", // blank frame
// Thunder spark
//Thunder spark
"S_THUNDERCOIN_SPARK",
// Invincibility Sparkles
@ -7348,6 +7342,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BHORIZ7",
"S_BHORIZ8",
// Booster
"S_BOOSTERSOUND",
"S_YELLOWBOOSTERROLLER",
"S_YELLOWBOOSTERSEG_LEFT",
@ -7378,7 +7373,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SPLISH8",
"S_SPLISH9",
// Lava splish
// Lava Splish
"S_LAVASPLISH",
// added water splash
@ -7482,6 +7477,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Got Flag Sign
"S_GOTFLAG",
// Finish flag
"S_FINISHFLAG",
"S_CORK",
"S_LHRT",
@ -7974,6 +7972,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ROCKCRUMBLEN",
"S_ROCKCRUMBLEO",
"S_ROCKCRUMBLEP",
// Level debris
"S_GFZDEBRIS",
"S_BRICKDEBRIS",
"S_WOODDEBRIS",
@ -7993,7 +7993,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_THOK", // Thok! mobj
"MT_PLAYER",
"MT_TAILSOVERLAY", // c:
"MT_METALJETFUME", // [:
"MT_METALJETFUME",
// Enemies
"MT_BLUECRAWLA", // Crawla (Blue)
@ -8110,7 +8110,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_CYBRAKDEMON_NAPALM_FLAMES",
"MT_CYBRAKDEMON_VILE_EXPLOSION",
// Metal Sonic
// Metal Sonic (Boss 9)
"MT_METALSONIC_RACE",
"MT_METALSONIC_BATTLE",
"MT_MSSHIELD_FRONT",
@ -8124,7 +8124,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BOMBSPHERE",
"MT_REDTEAMRING", //Rings collectable by red team.
"MT_BLUETEAMRING", //Rings collectable by blue team.
"MT_TOKEN", // Special Stage Token
"MT_TOKEN", // Special Stage token for special stage
"MT_REDFLAG", // Red CTF Flag
"MT_BLUEFLAG", // Blue CTF Flag
"MT_EMBLEM",
@ -8350,22 +8350,22 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Arid Canyon Scenery
"MT_BIGTUMBLEWEED",
"MT_LITTLETUMBLEWEED",
"MT_CACTI1",
"MT_CACTI2",
"MT_CACTI3",
"MT_CACTI4",
"MT_CACTI5",
"MT_CACTI6",
"MT_CACTI7",
"MT_CACTI8",
"MT_CACTI9",
"MT_CACTI10",
"MT_CACTI11",
"MT_CACTITINYSEG",
"MT_CACTISMALLSEG",
"MT_ARIDSIGN_CAUTION",
"MT_ARIDSIGN_CACTI",
"MT_ARIDSIGN_SHARPTURN",
"MT_CACTI1", // Tiny Red Flower Cactus
"MT_CACTI2", // Small Red Flower Cactus
"MT_CACTI3", // Tiny Blue Flower Cactus
"MT_CACTI4", // Small Blue Flower Cactus
"MT_CACTI5", // Prickly Pear
"MT_CACTI6", // Barrel Cactus
"MT_CACTI7", // Tall Barrel Cactus
"MT_CACTI8", // Armed Cactus
"MT_CACTI9", // Ball Cactus
"MT_CACTI10", // Tiny Cactus
"MT_CACTI11", // Small Cactus
"MT_CACTITINYSEG", // Tiny Cactus Segment
"MT_CACTISMALLSEG", // Small Cactus Segment
"MT_ARIDSIGN_CAUTION", // Caution Sign
"MT_ARIDSIGN_CACTI", // Cacti Sign
"MT_ARIDSIGN_SHARPTURN", // Sharp Turn Sign
"MT_OILLAMP",
"MT_TNTBARREL",
"MT_PROXIMITYTNT",
@ -8420,7 +8420,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_GLAREGOYLEUP",
"MT_GLAREGOYLEDOWN",
"MT_GLAREGOYLELONG",
"MT_TARGET",
"MT_TARGET", // AKA Red Crystal
"MT_GREENFLAME",
"MT_BLUEGARGOYLE",
@ -8471,7 +8471,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_HHZSTALAGMITE_TALL",
"MT_HHZSTALAGMITE_SHORT",
// Botanic Serenity
// Botanic Serenity scenery
"MT_BSZTALLFLOWER_RED",
"MT_BSZTALLFLOWER_PURPLE",
"MT_BSZTALLFLOWER_BLUE",
@ -8601,6 +8601,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_LOCKONINF", // In-level Target
"MT_TAG", // Tag Sign
"MT_GOTFLAG", // Got Flag sign
"MT_FINISHFLAG", // Finish flag
// Ambient Sounds
"MT_AWATERA", // Ambient Water Sound 1
@ -8751,6 +8752,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_ROCKCRUMBLE14",
"MT_ROCKCRUMBLE15",
"MT_ROCKCRUMBLE16",
// Level debris
"MT_GFZDEBRIS",
"MT_BRICKDEBRIS",
"MT_WOODDEBRIS",
@ -8989,9 +8992,11 @@ static const char *COLOR_ENUMS[] = {
// Desaturated
"AETHER", // SKINCOLOR_AETHER,
"SLATE", // SKINCOLOR_SLATE,
"BLUEBELL", // SKINCOLOR_BLUEBELL,
"PINK", // SKINCOLOR_PINK,
"YOGURT", // SKINCOLOR_YOGURT,
"BROWN", // SKINCOLOR_BROWN,
"BRONZE", // SKINCOLOR_BRONZE,
"TAN", // SKINCOLOR_TAN,
"BEIGE", // SKINCOLOR_BEIGE,
"MOSS", // SKINCOLOR_MOSS,
@ -9004,9 +9009,11 @@ static const char *COLOR_ENUMS[] = {
"RED", // SKINCOLOR_RED,
"CRIMSON", // SKINCOLOR_CRIMSON,
"FLAME", // SKINCOLOR_FLAME,
"KETCHUP", // SKINCOLOR_KETCHUP,
"PEACHY", // SKINCOLOR_PEACHY,
"QUAIL", // SKINCOLOR_QUAIL,
"SUNSET", // SKINCOLOR_SUNSET,
"COPPER", // SKINCOLOR_COPPER,
"APRICOT", // SKINCOLOR_APRICOT,
"ORANGE", // SKINCOLOR_ORANGE,
"RUST", // SKINCOLOR_RUST,
@ -9016,6 +9023,7 @@ static const char *COLOR_ENUMS[] = {
"OLIVE", // SKINCOLOR_OLIVE,
"LIME", // SKINCOLOR_LIME,
"PERIDOT", // SKINCOLOR_PERIDOT,
"APPLE", // SKINCOLOR_APPLE,
"GREEN", // SKINCOLOR_GREEN,
"FOREST", // SKINCOLOR_FOREST,
"EMERALD", // SKINCOLOR_EMERALD,
@ -9042,6 +9050,7 @@ static const char *COLOR_ENUMS[] = {
"VIOLET", // SKINCOLOR_VIOLET,
"LILAC", // SKINCOLOR_LILAC,
"PLUM", // SKINCOLOR_PLUM,
"RASPBERRY", // SKINCOLOR_RASPBERRY,
"ROSY", // SKINCOLOR_ROSY,
// Super special awesome Super flashing colors!
@ -9135,7 +9144,8 @@ static const char *const POWERS_LIST[] = {
"NIGHTS_LINKFREEZE",
//for linedef exec 427
"NOCONTROL"
"NOCONTROL",
"JUSTLAUNCHED",
};
static const char *const HUDITEMS_LIST[] = {
@ -9143,6 +9153,7 @@ static const char *const HUDITEMS_LIST[] = {
"RINGS",
"RINGSNUM",
"RINGSNUMTICS",
"SCORE",
"SCORENUM",
@ -9162,8 +9173,7 @@ static const char *const HUDITEMS_LIST[] = {
"TIMELEFTNUM",
"TIMEUP",
"HUNTPICS",
"POWERUPS",
"LAP"
"POWERUPS"
};
static const char *const MENUTYPES_LIST[] = {
@ -9372,6 +9382,9 @@ struct {
{"LF_NOZONE",LF_NOZONE},
{"LF_SAVEGAME",LF_SAVEGAME},
{"LF_MIXNIGHTSCOUNTDOWN",LF_MIXNIGHTSCOUNTDOWN},
{"LF_NOTITLECARDFIRST",LF_NOTITLECARDFIRST},
{"LF_NOTITLECARDRESPAWN",LF_NOTITLECARDRESPAWN},
{"LF_NOTITLECARDRECORDATTACK",LF_NOTITLECARDRECORDATTACK},
{"LF_NOTITLECARD",LF_NOTITLECARD},
{"LF_WARNINGTITLE",LF_WARNINGTITLE},
// And map flags
@ -10465,16 +10478,23 @@ static inline int lib_freeslot(lua_State *L)
}
else if (fastcmp(type, "TOL"))
{
if (lastcustomtol > 31)
CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n");
else
{
UINT32 newtol = (1<<lastcustomtol);
CONS_Printf("TypeOfLevel TOL_%s allocated.\n",word);
G_AddTOL(newtol, word);
lua_pushinteger(L, newtol);
lastcustomtol++;
r++;
// Search if we already have a typeoflevel by that name...
int i;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(word, TYPEOFLEVEL[i].name))
break;
// We don't, so allocate a new one.
if (TYPEOFLEVEL[i].name == NULL) {
if (lastcustomtol == (UINT32)MAXTOL) // Unless you have way too many, since they're flags.
CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n");
else {
CONS_Printf("TypeOfLevel TOL_%s allocated.\n",word);
G_AddTOL(lastcustomtol, word);
lua_pushinteger(L, lastcustomtol);
lastcustomtol <<= 1;
r++;
}
}
}
Z_Free(s);

View file

@ -143,9 +143,9 @@ extern char logfilename[1024];
// we use comprevision and compbranch instead.
#else
#define VERSION 202 // Game version
#define SUBVERSION 0 // more precise version number
#define VERSIONSTRING "v2.2.0"
#define VERSIONSTRINGW L"v2.2.0"
#define SUBVERSION 1 // more precise version number
#define VERSIONSTRING "v2.2.1"
#define VERSIONSTRINGW L"v2.2.1"
// Hey! If you change this, add 1 to the MODVERSION below!
// Otherwise we can't force updates!
#endif
@ -210,7 +210,7 @@ extern char logfilename[1024];
// it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1".
#define MODVERSION 40
#define MODVERSION 41
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
// Increment MINOREXECVERSION whenever a config change is needed that does not correspond
@ -253,9 +253,11 @@ typedef enum
// Desaturated
SKINCOLOR_AETHER,
SKINCOLOR_SLATE,
SKINCOLOR_BLUEBELL,
SKINCOLOR_PINK,
SKINCOLOR_YOGURT,
SKINCOLOR_BROWN,
SKINCOLOR_BRONZE,
SKINCOLOR_TAN,
SKINCOLOR_BEIGE,
SKINCOLOR_MOSS,
@ -268,9 +270,11 @@ typedef enum
SKINCOLOR_RED,
SKINCOLOR_CRIMSON,
SKINCOLOR_FLAME,
SKINCOLOR_KETCHUP,
SKINCOLOR_PEACHY,
SKINCOLOR_QUAIL,
SKINCOLOR_SUNSET,
SKINCOLOR_COPPER,
SKINCOLOR_APRICOT,
SKINCOLOR_ORANGE,
SKINCOLOR_RUST,
@ -280,6 +284,7 @@ typedef enum
SKINCOLOR_OLIVE,
SKINCOLOR_LIME,
SKINCOLOR_PERIDOT,
SKINCOLOR_APPLE,
SKINCOLOR_GREEN,
SKINCOLOR_FOREST,
SKINCOLOR_EMERALD,
@ -306,6 +311,7 @@ typedef enum
SKINCOLOR_VIOLET,
SKINCOLOR_LILAC,
SKINCOLOR_PLUM,
SKINCOLOR_RASPBERRY,
SKINCOLOR_ROSY,
// SKINCOLOR_? - one left before we bump up against 0x39, which isn't a HARD limit anymore but would be excessive
@ -490,6 +496,7 @@ extern INT32 cv_debug;
#define DBG_SETUP 0x0400
#define DBG_LUA 0x0800
#define DBG_RANDOMIZER 0x1000
#define DBG_VIEWMORPH 0x2000
// =======================
// Misc stuff for later...

View file

@ -351,15 +351,19 @@ typedef struct
} mapheader_t;
// level flags
#define LF_SCRIPTISFILE 1 ///< True if the script is a file, not a lump.
#define LF_SPEEDMUSIC 2 ///< Speed up act music for super sneakers
#define LF_NOSSMUSIC 4 ///< Disable Super Sonic music
#define LF_NORELOAD 8 ///< Don't reload level on death
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title
#define LF_SAVEGAME 32 ///< Save the game upon loading this level
#define LF_MIXNIGHTSCOUNTDOWN 64 ///< Play sfx_timeup instead of music change for NiGHTS countdown
#define LF_WARNINGTITLE 128 ///< WARNING! WARNING! WARNING! WARNING!
#define LF_NOTITLECARD 256 ///< Don't start the title card
#define LF_SCRIPTISFILE (1<<0) ///< True if the script is a file, not a lump.
#define LF_SPEEDMUSIC (1<<1) ///< Speed up act music for super sneakers
#define LF_NOSSMUSIC (1<<2) ///< Disable Super Sonic music
#define LF_NORELOAD (1<<3) ///< Don't reload level on death
#define LF_NOZONE (1<<4) ///< Don't include "ZONE" on level title
#define LF_SAVEGAME (1<<5) ///< Save the game upon loading this level
#define LF_MIXNIGHTSCOUNTDOWN (1<<6) ///< Play sfx_timeup instead of music change for NiGHTS countdown
#define LF_WARNINGTITLE (1<<7) ///< WARNING! WARNING! WARNING! WARNING!
#define LF_NOTITLECARDFIRST (1<<8)
#define LF_NOTITLECARDRESPAWN (1<<9)
#define LF_NOTITLECARDRECORDATTACK (1<<10)
#define LF_NOTITLECARD (LF_NOTITLECARDFIRST|LF_NOTITLECARDRESPAWN|LF_NOTITLECARDRECORDATTACK) ///< Don't start the title card at all
#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen
@ -437,6 +441,7 @@ extern const char *Gametype_ConstantNames[NUMGAMETYPES];
extern INT32 pointlimits[NUMGAMETYPES];
extern INT32 timelimits[NUMGAMETYPES];
// TypeOfLevel things
enum TypeOfLevel
{
TOL_SP = 0x01, ///< Single Player
@ -461,16 +466,16 @@ enum TypeOfLevel
TOL_XMAS = 0x1000, ///< Christmas NiGHTS
};
#define NUMBASETOL 18
#define NUMMAXTOL (18 + NUMGAMETYPEFREESLOTS)
#define MAXTOL (1<<31)
#define NUMBASETOLNAMES (19)
#define NUMTOLNAMES (NUMBASETOLNAMES + NUMGAMETYPEFREESLOTS)
typedef struct
{
const char *name;
UINT32 flag;
} tolinfo_t;
extern tolinfo_t TYPEOFLEVEL[NUMMAXTOL];
extern INT32 numtolinfo;
extern tolinfo_t TYPEOFLEVEL[NUMTOLNAMES];
extern UINT32 lastcustomtol;
extern tic_t totalplaytime;

View file

@ -1120,6 +1120,9 @@ static const char *credits[] = {
"\1Sonic Robo Blast II",
"\1Credits",
"",
"\1Producer",
"Rob Tisdell",
"",
"\1Game Design",
"Ben \"Mystic\" Geyer",
"\"SSNTails\"",
@ -1165,6 +1168,7 @@ static const char *credits[] = {
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
"Wessel \"sphere\" Smit",
"Ben \"Cue\" Woodford",
"Ikaro \"Tatsuru\" Vinhas",
// Git contributors with 5+ approved merges of substantive quality,
// or contributors with at least one groundbreaking merge, may be named.
// Everyone else is acknowledged under "Special Thanks > SRB2 Community Contributors".
@ -1233,7 +1237,7 @@ static const char *credits[] = {
"Thomas \"Shadow Hog\" Igoe",
"Alexander \"DrTapeworm\" Moench-Ford",
"\"Kaito Sinclaire\"",
"\"QueenDelta\"",
"Anna \"QueenDelta\" Sandlin",
"Wessel \"sphere\" Smit",
"\"Spazzo\"",
"\"SSNTails\"",
@ -1257,7 +1261,7 @@ static const char *credits[] = {
"Cody \"SRB2 Playah\" Koester",
"Skye \"OmegaVelocity\" Meredith",
"Stephen \"HEDGESMFG\" Moellering",
"Nick \"ST218\" Molina",
"Rosalie \"ST218\" Molina",
"Samuel \"Prime 2.0\" Peters",
"Colin \"Sonict\" Pfaff",
"Bill \"Tets\" Reed",
@ -2694,8 +2698,18 @@ static void F_FigureActiveTtScale(void)
SINT8 newttscale = max(1, min(6, vid.dupx));
SINT8 oldttscale = activettscale;
if (newttscale == testttscale)
return;
if (needpatchrecache)
ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0;
else
{
if (newttscale == testttscale)
return;
// We have a new ttscale, so load gfx
if(oldttscale > 0)
F_UnloadAlacroixGraphics(oldttscale);
}
testttscale = newttscale;
// If ttscale is unavailable: look for lower scales, then higher scales.
@ -2713,10 +2727,6 @@ static void F_FigureActiveTtScale(void)
activettscale = (newttscale >= 1 && newttscale <= 6) ? newttscale : 0;
// We have a new ttscale, so load gfx
if(oldttscale > 0)
F_UnloadAlacroixGraphics(oldttscale);
if(activettscale > 0)
F_LoadAlacroixGraphics(activettscale);
}
@ -2758,12 +2768,6 @@ void F_TitleScreenDrawer(void)
return;
#endif
if (needpatchrecache && (curttmode == TTMODE_ALACROIX))
{
ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0;
F_LoadAlacroixGraphics(activettscale);
}
switch(curttmode)
{
case TTMODE_OLD:
@ -3629,7 +3633,6 @@ void F_StartContinue(void)
}
wipestyleflags = WSF_FADEOUT;
F_TryColormapFade(31);
G_SetGamestate(GS_CONTINUING);
gameaction = ga_nothing;

View file

@ -192,8 +192,7 @@ void F_WipeStageTitle(void)
// draw level title
if ((WipeStageTitle && st_overlay)
&& (wipestyle == WIPESTYLE_COLORMAP)
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)
&& *mapheaderinfo[gamemap-1]->lvlttl != '\0')
&& G_IsTitleCardAvailable())
{
ST_runTitleCard();
ST_drawWipeTitleCard();

View file

@ -1140,7 +1140,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
INT32 *myaiming = (ssplayer == 1 ? &localaiming : &localaiming2);
angle_t drawangleoffset = (player->powers[pw_carry] == CR_ROLLOUT) ? ANGLE_180 : 0;
INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, mousemove;
INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, turnmultiplier, mousemove;
controlstyle_e controlstyle = G_ControlStyle(ssplayer);
INT32 *mx; INT32 *my; INT32 *mly;
@ -1163,6 +1163,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
alwaysfreelook = cv_alwaysfreelook.value;
usejoystick = cv_usejoystick.value;
invertmouse = cv_invertmouse.value;
turnmultiplier = cv_cam_turnmultiplier.value;
mousemove = cv_mousemove.value;
mx = &mousex;
my = &mousey;
@ -1176,6 +1177,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
alwaysfreelook = cv_alwaysfreelook2.value;
usejoystick = cv_usejoystick2.value;
invertmouse = cv_invertmouse2.value;
turnmultiplier = cv_cam2_turnmultiplier.value;
mousemove = cv_mousemove2.value;
mx = &mouse2x;
my = &mouse2y;
@ -1293,14 +1295,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
{
if (turnright && turnleft);
else if (turnright)
cmd->angleturn = (INT16)(cmd->angleturn - ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS));
cmd->angleturn = (INT16)(cmd->angleturn - ((angleturn[tspeed] * turnmultiplier)>>FRACBITS));
else if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS));
cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * turnmultiplier)>>FRACBITS));
if (analogjoystickmove && lookjoystickvector.xaxis != 0)
{
// JOYAXISRANGE should be 1023 (divide by 1024)
cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * cv_cam_turnmultiplier.value)>>FRACBITS)); // ANALOG!
cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * turnmultiplier)>>FRACBITS)); // ANALOG!
}
if (turnright || turnleft || abs(cmd->angleturn) > angleturn[2])
@ -1926,19 +1928,32 @@ void G_PreLevelTitleCard(void)
wipestyleflags = WSF_CROSSFADE;
}
static boolean titlecardforreload = false;
//
// Returns true if the current level has a title card.
//
boolean G_IsTitleCardAvailable(void)
{
// The current level header explicitly disabled the title card.
if (mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)
UINT16 titleflag = LF_NOTITLECARDFIRST;
if (modeattacking != ATTACKING_NONE)
titleflag = LF_NOTITLECARDRECORDATTACK;
else if (titlecardforreload)
titleflag = LF_NOTITLECARDRESPAWN;
if (mapheaderinfo[gamemap-1]->levelflags & titleflag)
return false;
// The current gametype doesn't have a title card.
if (gametyperules & GTR_NOTITLECARD)
return false;
// The current level has no name.
if (!mapheaderinfo[gamemap-1]->lvlttl[0])
return false;
// The title card is available.
return true;
}
@ -2412,6 +2427,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
INT32 skin;
UINT32 availabilities;
tic_t jointime;
tic_t quittime;
boolean spectator;
boolean outofcoop;
INT16 bot;
@ -2425,6 +2441,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
ctfteam = players[player].ctfteam;
exiting = players[player].exiting;
jointime = players[player].jointime;
quittime = players[player].quittime;
spectator = players[player].spectator;
outofcoop = players[player].outofcoop;
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
@ -2496,6 +2513,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->pflags = pflags;
p->ctfteam = ctfteam;
p->jointime = jointime;
p->quittime = quittime;
p->spectator = spectator;
p->outofcoop = outofcoop;
@ -2649,73 +2667,24 @@ static boolean G_CheckSpot(INT32 playernum, mapthing_t *mthing)
// or a not-so-appropriate spot, if it initially fails
// due to a lack of starts open or something.
//
void G_SpawnPlayer(INT32 playernum, boolean starpost)
void G_SpawnPlayer(INT32 playernum)
{
mapthing_t *spawnpoint;
if (!playeringame[playernum])
return;
P_SpawnPlayer(playernum);
if (starpost) //Don't even bother with looking for a place to spawn.
{
P_MovePlayerToStarpost(playernum);
#ifdef HAVE_BLUA
LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :)
#endif
return;
}
// -- CTF --
// Order: CTF->DM->Coop
if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam)
{
if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
spawnpoint = G_FindCoopStart(playernum); // fallback
}
// -- DM/Tag/CTF-spectator/etc --
// Order: DM->CTF->Coop
else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT))
{
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
spawnpoint = G_FindCoopStart(playernum); // fallback
}
// -- Other game modes --
// Order: Coop->DM->CTF
else
{
if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
spawnpoint = G_FindCTFStart(playernum); // fallback
}
//No spawns found. ANYWHERE.
if (!spawnpoint)
{
if (nummapthings)
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n"));
spawnpoint = &mapthings[0];
}
else
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n"));
//P_MovePlayerToSpawn handles this fine if the spawnpoint is NULL.
}
}
P_MovePlayerToSpawn(playernum, spawnpoint);
G_MovePlayerToSpawnOrStarpost(playernum);
#ifdef HAVE_BLUA
LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :)
#endif
}
void G_MovePlayerToSpawnOrStarpost(INT32 playernum)
{
if (players[playernum].starposttime)
P_MovePlayerToStarpost(playernum);
else
P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum));
}
mapthing_t *G_FindCTFStart(INT32 playernum)
@ -2812,6 +2781,59 @@ mapthing_t *G_FindCoopStart(INT32 playernum)
return NULL;
}
mapthing_t *G_FindMapStart(INT32 playernum)
{
mapthing_t *spawnpoint;
if (!playeringame[playernum])
return NULL;
// -- CTF --
// Order: CTF->DM->Coop
if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam)
{
if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
spawnpoint = G_FindCoopStart(playernum); // fallback
}
// -- DM/Tag/CTF-spectator/etc --
// Order: DM->CTF->Coop
else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT))
{
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
spawnpoint = G_FindCoopStart(playernum); // fallback
}
// -- Other game modes --
// Order: Coop->DM->CTF
else
{
if (!(spawnpoint = G_FindCoopStart(playernum)) // find a Co-op start
&& !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start
spawnpoint = G_FindCTFStart(playernum); // fallback
}
//No spawns found. ANYWHERE.
if (!spawnpoint)
{
if (nummapthings)
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n"));
spawnpoint = &mapthings[0];
}
else
{
if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))
CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n"));
}
}
return spawnpoint;
}
// Go back through all the projectiles and remove all references to the old
// player mobj, replacing them with the new one.
void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
@ -2990,7 +3012,7 @@ void G_DoReborn(INT32 playernum)
{
if (!playeringame[i])
continue;
G_SpawnPlayer(i, (players[i].starposttime));
G_SpawnPlayer(i);
}
// restore time in netgame (see also p_setup.c)
@ -3011,7 +3033,9 @@ void G_DoReborn(INT32 playernum)
#ifdef HAVE_BLUA
LUAh_MapChange(gamemap);
#endif
titlecardforreload = true;
G_DoLoadLevel(true);
titlecardforreload = false;
if (metalrecording)
G_BeginMetal();
return;
@ -3036,7 +3060,7 @@ void G_DoReborn(INT32 playernum)
P_RemoveMobj(player->mo);
}
G_SpawnPlayer(playernum, (player->starposttime));
G_SpawnPlayer(playernum);
if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo);
}
@ -3078,7 +3102,6 @@ void G_AddPlayer(INT32 playernum)
}
}
p->jointime = 0;
p->playerstate = PST_REBORN;
p->height = mobjinfo[MT_PLAYER].height;
@ -3101,6 +3124,8 @@ boolean G_EnoughPlayersFinished(void)
{
if (!playeringame[i] || players[i].spectator || players[i].bot)
continue;
if (players[i].quittime > 30 * TICRATE)
continue;
if (players[i].lives <= 0)
continue;
@ -3189,17 +3214,17 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] =
GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT,
// Match
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY,
// Team Match
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
// Tag
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
// Hide and Seek
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
// CTF
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
};
//
@ -3242,8 +3267,8 @@ void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
{
size_t r = 0; // read
size_t w = 0; // write
char *gtconst = Z_Calloc(strlen(newgtconst) + 3, PU_STATIC, NULL);
char *tmpconst = Z_Calloc(strlen(newgtconst), PU_STATIC, NULL);
char *gtconst = Z_Calloc(strlen(newgtconst) + 4, PU_STATIC, NULL);
char *tmpconst = Z_Calloc(strlen(newgtconst) + 1, PU_STATIC, NULL);
// Copy the gametype name.
strcpy(tmpconst, newgtconst);
@ -3370,6 +3395,36 @@ UINT32 gametypetol[NUMGAMETYPES] =
TOL_CTF, // CTF
};
tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = {
{"SOLO",TOL_SP},
{"SP",TOL_SP},
{"SINGLEPLAYER",TOL_SP},
{"SINGLE",TOL_SP},
{"COOP",TOL_COOP},
{"CO-OP",TOL_COOP},
{"COMPETITION",TOL_COMPETITION},
{"RACE",TOL_RACE},
{"MATCH",TOL_MATCH},
{"TAG",TOL_TAG},
{"CTF",TOL_CTF},
{"2D",TOL_2D},
{"MARIO",TOL_MARIO},
{"NIGHTS",TOL_NIGHTS},
{"OLDBRAK",TOL_ERZ3},
{"XMAS",TOL_XMAS},
{"CHRISTMAS",TOL_XMAS},
{"WINTER",TOL_XMAS},
{NULL, 0}
};
UINT32 lastcustomtol = (TOL_XMAS<<1);
//
// G_AddTOL
//
@ -3377,16 +3432,16 @@ UINT32 gametypetol[NUMGAMETYPES] =
//
void G_AddTOL(UINT32 newtol, const char *tolname)
{
TYPEOFLEVEL[numtolinfo].name = Z_StrDup(tolname);
TYPEOFLEVEL[numtolinfo].flag = newtol;
numtolinfo++;
INT32 i;
for (i = 0; TYPEOFLEVEL[i].name; i++)
;
TYPEOFLEVEL[numtolinfo].name = NULL;
TYPEOFLEVEL[numtolinfo].flag = 0;
TYPEOFLEVEL[i].name = Z_StrDup(tolname);
TYPEOFLEVEL[i].flag = newtol;
}
//
// G_AddTOL
// G_AddGametypeTOL
//
// Assigns a type of level to a gametype.
//
@ -3725,7 +3780,10 @@ static void G_DoCompleted(void)
}
if (i == 7)
{
gottoken = false;
token = 0;
}
}
if (spec && !gottoken)

View file

@ -161,7 +161,9 @@ INT32 G_FindMapByNameOrCode(const char *query, char **foundmapnamep);
mapthing_t *G_FindCTFStart(INT32 playernum);
mapthing_t *G_FindMatchStart(INT32 playernum);
mapthing_t *G_FindCoopStart(INT32 playernum);
void G_SpawnPlayer(INT32 playernum, boolean starpost);
mapthing_t *G_FindMapStart(INT32 playernum);
void G_MovePlayerToSpawnOrStarpost(INT32 playernum);
void G_SpawnPlayer(INT32 playernum);
// Can be called by the startup code or M_Responder.
// A normal game starts at map 1, but a warp test can start elsewhere

View file

@ -662,7 +662,13 @@ INT32 G_KeyStringtoNum(const char *keystr)
return keystr[0];
if (!strncmp(keystr, "KEY", 3) && keystr[3] >= '0' && keystr[3] <= '9')
return atoi(&keystr[3]);
{
/* what if we out of range bruh? */
j = atoi(&keystr[3]);
if (j < NUMINPUTS)
return j;
return 0;
}
for (j = 0; j < NUMKEYNAMES; j++)
if (!stricmp(keynames[j].name, keystr))

View file

@ -509,6 +509,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_LCKN
&lspr[NOLIGHT], // SPR_TTAG
&lspr[NOLIGHT], // SPR_GFLG
&lspr[NOLIGHT], // SPR_FNSF
&lspr[NOLIGHT], // SPR_CORK
&lspr[NOLIGHT], // SPR_LHRT

View file

@ -5022,12 +5022,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo
planeinfo[numplanes].isceiling = isceiling;
planeinfo[numplanes].fixedheight = fixedheight;
if (planecolormap && (planecolormap->fog & 1))
planeinfo[numplanes].lightlevel = lightlevel;
else
planeinfo[numplanes].lightlevel = 255;
planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255;
planeinfo[numplanes].levelflat = levelflat;
planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha;
@ -5059,12 +5054,7 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse
polyplaneinfo[numpolyplanes].isceiling = isceiling;
polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
if (planecolormap && (planecolormap->fog & 1))
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
else
polyplaneinfo[numpolyplanes].lightlevel = 255;
polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255;
polyplaneinfo[numpolyplanes].levelflat = levelflat;
polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha;
@ -5325,7 +5315,7 @@ static void HWR_AddSprites(sector_t *sec)
#ifdef HWPRECIP
precipmobj_t *precipthing;
#endif
fixed_t approx_dist, limit_dist, hoop_limit_dist;
fixed_t limit_dist, hoop_limit_dist;
// BSP is traversed by subsector.
// A sector might have been split into several
@ -5344,35 +5334,10 @@ static void HWR_AddSprites(sector_t *sec)
// If a limit exists, handle things a tiny bit different.
limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS;
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS;
if (limit_dist || hoop_limit_dist)
for (thing = sec->thinglist; thing; thing = thing->snext)
{
for (thing = sec->thinglist; thing; thing = thing->snext)
{
if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW)
continue;
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
if (thing->sprite == SPR_HOOP)
{
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
continue;
}
else
{
if (limit_dist && approx_dist > limit_dist)
continue;
}
if (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist))
HWR_ProjectSprite(thing);
}
}
else
{
// Draw everything in sector, no checks
for (thing = sec->thinglist; thing; thing = thing->snext)
if (!(thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW))
HWR_ProjectSprite(thing);
}
#ifdef HWPRECIP
@ -5381,15 +5346,8 @@ static void HWR_AddSprites(sector_t *sec)
{
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
{
if (precipthing->precipflags & PCF_INVISIBLE)
continue;
approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y);
if (approx_dist > limit_dist)
continue;
HWR_ProjectPrecipitationSprite(precipthing);
if (R_PrecipThingVisible(precipthing, limit_dist))
HWR_ProjectPrecipitationSprite(precipthing);
}
}
#endif
@ -5643,7 +5601,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer)
{
// bodge support - not nearly as comprehensive as r_things.c, but better than nothing
if (thing->tracer->sprite == SPR_NULL || thing->tracer->flags2 & MF2_DONTDRAW)
if (! R_ThingVisible(thing->tracer))
return;
}
@ -5851,6 +5809,12 @@ static void HWR_DrawSkyBackground(player_t *player)
dometransform.scalez = 1;
dometransform.fovxangle = fpov; // Tails
dometransform.fovyangle = fpov; // Tails
if (player->viewrollangle != 0)
{
fixed_t rol = AngleFixed(player->viewrollangle);
dometransform.rollangle = FIXED_TO_FLOAT(rol);
dometransform.roll = true;
}
dometransform.splitscreen = splitscreen;
HWR_GetTexture(texturetranslation[skytexture]);
@ -6074,6 +6038,12 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
atransform.scalez = 1;
atransform.fovxangle = fpov; // Tails
atransform.fovyangle = fpov; // Tails
if (player->viewrollangle != 0)
{
fixed_t rol = AngleFixed(player->viewrollangle);
atransform.rollangle = FIXED_TO_FLOAT(rol);
atransform.roll = true;
}
atransform.splitscreen = splitscreen;
gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l)));
@ -6294,6 +6264,12 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
atransform.scalez = 1;
atransform.fovxangle = fpov; // Tails
atransform.fovyangle = fpov; // Tails
if (player->viewrollangle != 0)
{
fixed_t rol = AngleFixed(player->viewrollangle);
atransform.rollangle = FIXED_TO_FLOAT(rol);
atransform.roll = true;
}
atransform.splitscreen = splitscreen;
gr_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l)));

View file

@ -476,8 +476,9 @@ void HWR_InitModels(void)
size_t i;
INT32 s;
FILE *f;
char name[18], filename[32];
char name[24], filename[32];
float scale, offset;
size_t prefixlen;
CONS_Printf("HWR_InitModels()...\n");
for (s = 0; s < MAXSKINS; s++)
@ -509,46 +510,54 @@ void HWR_InitModels(void)
nomd2s = true;
return;
}
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
// length of the player model prefix
prefixlen = strlen(PLAYERMODELPREFIX);
while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4)
{
if (stricmp(name, "PLAY") == 0)
char *skinname = name;
size_t len = strlen(name);
// check for the player model prefix.
if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen))
{
CONS_Printf("Model for sprite PLAY detected in models.dat, use a player skin instead!\n");
continue;
skinname += prefixlen;
goto addskinmodel;
}
for (i = 0; i < NUMSPRITES; i++)
// add sprite model
if (len == 4) // must be 4 characters long exactly. otherwise it's not a sprite name.
{
if (stricmp(name, sprnames[i]) == 0)
for (i = 0; i < NUMSPRITES; i++)
{
//if (stricmp(name, "PLAY") == 0)
//continue;
//CONS_Debug(DBG_RENDER, " Found: %s %s %f %f\n", name, filename, scale, offset);
md2_models[i].scale = scale;
md2_models[i].offset = offset;
md2_models[i].notfound = false;
strcpy(md2_models[i].filename, filename);
goto md2found;
if (stricmp(name, sprnames[i]) == 0)
{
md2_models[i].scale = scale;
md2_models[i].offset = offset;
md2_models[i].notfound = false;
strcpy(md2_models[i].filename, filename);
goto modelfound;
}
}
}
addskinmodel:
// add player model
for (s = 0; s < MAXSKINS; s++)
{
if (stricmp(name, skins[s].name) == 0)
if (stricmp(skinname, skins[s].name) == 0)
{
//CONS_Printf(" Found: %s %s %f %f\n", name, filename, scale, offset);
md2_playermodels[s].skin = s;
md2_playermodels[s].scale = scale;
md2_playermodels[s].offset = offset;
md2_playermodels[s].notfound = false;
strcpy(md2_playermodels[s].filename, filename);
goto md2found;
goto modelfound;
}
}
// no sprite/player skin name found?!?
//CONS_Printf("Unknown sprite/player skin %s detected in models.dat\n", name);
md2found:
modelfound:
// move on to next line...
continue;
}
@ -558,8 +567,9 @@ md2found:
void HWR_AddPlayerModel(int skin) // For skins that were added after startup
{
FILE *f;
char name[18], filename[32];
char name[24], filename[32];
float scale, offset;
size_t prefixlen;
if (nomd2s)
return;
@ -577,32 +587,42 @@ void HWR_AddPlayerModel(int skin) // For skins that were added after startup
return;
}
// Check for any model that match the names of player skins!
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
// length of the player model prefix
prefixlen = strlen(PLAYERMODELPREFIX);
// Check for any models that match the names of player skins!
while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4)
{
if (stricmp(name, skins[skin].name) == 0)
char *skinname = name;
size_t len = strlen(name);
// ignore the player model prefix.
if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen))
skinname += prefixlen;
if (stricmp(skinname, skins[skin].name) == 0)
{
md2_playermodels[skin].skin = skin;
md2_playermodels[skin].scale = scale;
md2_playermodels[skin].offset = offset;
md2_playermodels[skin].notfound = false;
strcpy(md2_playermodels[skin].filename, filename);
goto playermd2found;
goto playermodelfound;
}
}
//CONS_Printf("Model for player skin %s not found\n", skins[skin].name);
md2_playermodels[skin].notfound = true;
playermd2found:
playermodelfound:
fclose(f);
}
void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after startup
{
FILE *f;
// name[18] is used to check for names in the models.dat file that match with sprites or player skins
// name[24] is used to check for names in the models.dat file that match with sprites or player skins
// sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long
char name[18], filename[32];
// PLAYERMODELPREFIX is 6 characters long
char name[24], filename[32];
float scale, offset;
if (nomd2s)
@ -622,22 +642,30 @@ void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after s
return;
}
// Check for any MD2s that match the names of sprite names!
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
// Check for any models that match the names of sprite names!
while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4)
{
// length of the sprite name
size_t len = strlen(name);
if (len != 4) // must be 4 characters long exactly. otherwise it's not a sprite name.
continue;
// check for the player model prefix.
if (!strnicmp(name, PLAYERMODELPREFIX, strlen(PLAYERMODELPREFIX)))
continue; // that's not a sprite...
if (stricmp(name, sprnames[spritenum]) == 0)
{
md2_models[spritenum].scale = scale;
md2_models[spritenum].offset = offset;
md2_models[spritenum].notfound = false;
strcpy(md2_models[spritenum].filename, filename);
goto spritemd2found;
goto spritemodelfound;
}
}
//CONS_Printf("MD2 for sprite %s not found\n", sprnames[spritenum]);
md2_models[spritenum].notfound = true;
spritemd2found:
spritemodelfound:
fclose(f);
}

View file

@ -49,4 +49,6 @@ void HWR_AddPlayerModel(INT32 skin);
void HWR_AddSpriteModel(size_t spritenum);
boolean HWR_DrawModel(gr_vissprite_t *spr);
#define PLAYERMODELPREFIX "PLAYER"
#endif // _HW_MD2_H_

View file

@ -2238,6 +2238,8 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
else
pglScalef(stransform->scalex, stransform->scaley, -stransform->scalez);
if (stransform->roll)
pglRotatef(stransform->rollangle, 0.0f, 0.0f, 1.0f);
pglRotatef(stransform->anglex , 1.0f, 0.0f, 0.0f);
pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f);
pglTranslatef(-stransform->x, -stransform->z, -stransform->y);

View file

@ -654,7 +654,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"),
player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
@ -668,7 +668,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal say command received from %s containing invalid characters\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
}
@ -1437,7 +1437,7 @@ static void HU_drawMiniChat(void)
for (; i>0; i--)
{
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
size_t j = 0;
INT32 linescount = 0;
@ -1479,6 +1479,9 @@ static void HU_drawMiniChat(void)
dy = 0;
dx = 0;
msglines += linescount+1;
if (msg)
Z_Free(msg);
}
y = chaty - charheight*(msglines+1);
@ -1501,7 +1504,7 @@ static void HU_drawMiniChat(void)
INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below...
INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one.
size_t j = 0;
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL;
while(msg[j]) // iterate through msg
@ -1547,6 +1550,9 @@ static void HU_drawMiniChat(void)
}
dy += charheight;
dx = 0;
if (msg)
Z_Free(msg);
}
// decrement addy and make that shit smooth:
@ -1598,7 +1604,7 @@ static void HU_drawChatLog(INT32 offset)
{
INT32 clrflag = 0;
INT32 j = 0;
const char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
UINT8 *colormap = NULL;
while(msg[j]) // iterate through msg
{
@ -1638,6 +1644,9 @@ static void HU_drawChatLog(INT32 offset)
}
dy += charheight;
dx = 0;
if (msg)
Z_Free(msg);
}
@ -2369,7 +2378,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (!splitscreen) // don't draw it on splitscreen,
{
if (!(tab[i].num == serverplayer))
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 253, y, playerpingtable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER");
@ -2568,7 +2577,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer)
V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
if (!splitscreen)
{
if (!(tab[i].num == serverplayer))
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
//else
//V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
@ -2692,7 +2701,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
V_DrawRightAlignedThinString(x+100, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
if (!splitscreen)
{
if (!(tab[i].num == serverplayer))
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
@ -2723,7 +2732,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
supercheck = supercheckdef;
strlcpy(name, tab[i].name, 7);
if (!(tab[i].num == serverplayer))
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 113, y, playerpingtable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
@ -2831,7 +2840,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor
strlcpy(name, tab[i].name, 7);
if (!splitscreen) // don't draw it on splitscreen,
{
if (!(tab[i].num == serverplayer))
if (!(tab[i].num == serverplayer || players[tab[i].num].quittime))
HU_drawPing(x+ 135, y+1, playerpingtable[tab[i].num], true, 0);
//else
// V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");

View file

@ -407,6 +407,7 @@ char sprnames[NUMSPRITES + 1][5] =
"LCKN", // Target
"TTAG", // Tag Sign
"GFLG", // Got Flag sign
"FNSF", // Finish flag
"CORK",
"LHRT",
@ -762,7 +763,7 @@ state_t states[NUMSTATES] =
{SPR_PLAY, SPR2_LIFE, 20, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3
// Level end sign (uses player sprite)
{SPR_PLAY, SPR2_SIGN|FF_PAPERSPRITE, -1, {NULL}, 0, 29, S_PLAY_SIGN}, // S_PLAY_SIGN
{SPR_PLAY, SPR2_SIGN|FF_PAPERSPRITE, 2, {NULL}, 0, 29, S_PLAY_SIGN}, // S_PLAY_SIGN
// NiGHTS Player, transforming
{SPR_PLAY, SPR2_TRNS|FF_ANIMATE, 7, {NULL}, 0, 4, S_PLAY_NIGHTS_TRANS2}, // S_PLAY_NIGHTS_TRANS1
@ -2343,12 +2344,13 @@ state_t states[NUMSTATES] =
// TNT barrel
{SPR_BARR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_TNTBARREL_STND1
{SPR_BARX, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_TNTBARREL_EXPL2}, // S_TNTBARREL_EXPL1
{SPR_BARX, 1|FF_FULLBRIGHT, 2, {A_TNTExplode}, MT_TNTDUST, 0, S_TNTBARREL_EXPL3}, // S_TNTBARREL_EXPL2
{SPR_BARX, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_TNTBARREL_EXPL4}, // S_TNTBARREL_EXPL3
{SPR_BARX, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL5}, // S_TNTBARREL_EXPL4
{SPR_BARX, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL6}, // S_TNTBARREL_EXPL5
{SPR_NULL, 0, 35, {NULL}, 0, 0, S_NULL}, // S_TNTBARREL_EXPL6
{SPR_BARX, 0, 0, {A_RollAngle}, 0, 1, S_TNTBARREL_EXPL2}, // S_TNTBARREL_EXPL1
{SPR_BARX, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_TNTBARREL_EXPL3}, // S_TNTBARREL_EXPL2
{SPR_BARX, 1|FF_FULLBRIGHT, 2, {A_TNTExplode}, MT_TNTDUST, 0, S_TNTBARREL_EXPL4}, // S_TNTBARREL_EXPL3
{SPR_BARX, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_TNTBARREL_EXPL5}, // S_TNTBARREL_EXPL4
{SPR_BARX, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL6}, // S_TNTBARREL_EXPL5
{SPR_BARX, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL7}, // S_TNTBARREL_EXPL6
{SPR_NULL, 0, 35, {NULL}, 0, 0, S_NULL}, // S_TNTBARREL_EXPL7
#ifndef ROTSPRITE
{SPR_BARR, 1|FF_ANIMATE, -1, {NULL}, 7, 2, S_NULL}, // S_TNTBARREL_FLYING
#else
@ -2394,7 +2396,7 @@ state_t states[NUMSTATES] =
// Minecart
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_MINECART_IDLE}, // S_MINECART_IDLE
{SPR_NULL, 0, 0, {A_KillSegments}, 0, 0, S_TNTBARREL_EXPL3}, // S_MINECART_DTH1
{SPR_NULL, 0, 0, {A_KillSegments}, 0, 0, S_TNTBARREL_EXPL4}, // S_MINECART_DTH1
{SPR_MCRT, 8|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_MINECARTEND
{SPR_MCRT, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_MINECARTSEG_FRONT
{SPR_MCRT, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_MINECARTSEG_BACK
@ -3348,7 +3350,10 @@ state_t states[NUMSTATES] =
{SPR_TTAG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_TTAG
// CTF Sign
{SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG
{SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG
// Finish flag
{SPR_FNSF, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL}, // S_FINISHFLAG
{SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK
{SPR_LHRT, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LHRT
@ -6487,10 +6492,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
24*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
0, // mass
DMG_FIRE, // mass
1, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags
MF_NOBLOCKMAP|MF_MISSILE|MF_PAIN|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@ -17994,6 +17999,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_FINISHFLAG
-1, // doomednum
S_FINISHFLAG, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
4*FRACUNIT, // speed
8*FRACUNIT, // radius
8*FRACUNIT, // height
1, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
// ambient water 1a (large)
{ // MT_AWATERA

View file

@ -670,6 +670,7 @@ typedef enum sprite
SPR_LCKN, // Target
SPR_TTAG, // Tag Sign
SPR_GFLG, // Got Flag sign
SPR_FNSF, // Finish flag
SPR_CORK,
SPR_LHRT,
@ -2503,6 +2504,7 @@ typedef enum state
S_TNTBARREL_EXPL4,
S_TNTBARREL_EXPL5,
S_TNTBARREL_EXPL6,
S_TNTBARREL_EXPL7,
S_TNTBARREL_FLYING,
// TNT proximity shell
@ -3484,6 +3486,9 @@ typedef enum state
// Got Flag Sign
S_GOTFLAG,
// Finish flag
S_FINISHFLAG,
S_CORK,
S_LHRT,
@ -4625,6 +4630,7 @@ typedef enum mobj_type
MT_LOCKONINF, // In-level Target
MT_TAG, // Tag Sign
MT_GOTFLAG, // Got Flag sign
MT_FINISHFLAG, // Finish flag
// Ambient Sounds
MT_AWATERA, // Ambient Water Sound 1

View file

@ -20,6 +20,7 @@
#endif
#include "z_zone.h"
#include "r_main.h"
#include "r_draw.h"
#include "r_things.h"
#include "m_random.h"
#include "s_sound.h"
@ -2193,11 +2194,11 @@ static int lib_rPointInSubsector(lua_State *L)
return 1;
}
static int lib_rIsPointInSubsector(lua_State *L)
static int lib_rPointInSubsectorOrNil(lua_State *L)
{
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
subsector_t *sub = R_IsPointInSubsector(x, y);
subsector_t *sub = R_PointInSubsectorOrNull(x, y);
//HUDSAFE
INLEVEL
if (sub)
@ -2313,9 +2314,29 @@ static int lib_rTextureNumForName(lua_State *L)
return 1;
}
// R_DRAW
////////////
static int lib_rGetColorByName(lua_State *L)
{
const char* colorname = luaL_checkstring(L, 1);
//HUDSAFE
lua_pushinteger(L, R_GetColorByName(colorname));
return 1;
}
// Lua exclusive function, returns the name of a color from the SKINCOLOR_ constant.
// SKINCOLOR_GREEN > "Green" for example
static int lib_rGetNameByColor(lua_State *L)
{
UINT8 colornum = (UINT8)luaL_checkinteger(L, 1);
if (!colornum || colornum >= MAXSKINCOLORS)
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, MAXSKINCOLORS-1);
lua_pushstring(L, Color_Names[colornum]);
return 1;
}
// S_SOUND
////////////
static int lib_sStartSound(lua_State *L)
{
const void *origin = NULL;
@ -3141,7 +3162,7 @@ static luaL_Reg lib[] = {
{"R_PointToDist",lib_rPointToDist},
{"R_PointToDist2",lib_rPointToDist2},
{"R_PointInSubsector",lib_rPointInSubsector},
{"R_IsPointInSubsector",lib_rIsPointInSubsector},
{"R_PointInSubsectorOrNil",lib_rPointInSubsectorOrNil},
// r_things (sprite)
{"R_Char2Frame",lib_rChar2Frame},
@ -3153,6 +3174,10 @@ static luaL_Reg lib[] = {
{"R_CheckTextureNumForName",lib_rCheckTextureNumForName},
{"R_TextureNumForName",lib_rTextureNumForName},
// r_draw
{"R_GetColorByName", lib_rGetColorByName},
{"R_GetNameByColor", lib_rGetNameByColor},
// s_sound
{"S_StartSound",lib_sStartSound},
{"S_StartSoundAtVolume",lib_sStartSoundAtVolume},

View file

@ -87,7 +87,7 @@ deny:
CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
}
// Wrapper for COM_AddCommand commands

View file

@ -102,7 +102,7 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type
boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player quitting
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode

View file

@ -1439,7 +1439,7 @@ UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj)
return shouldCollide;
}
void LUAh_PlayerQuit(player_t *plr, int reason)
void LUAh_PlayerQuit(player_t *plr, kickreason_t reason)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8))))
@ -1594,7 +1594,7 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
hook_p hookp;
boolean hasSeenPlayer = true;
if (!gL || !(hooksAvailable[hook_SeenPlayer/8] & (1<<(hook_SeenPlayer%8))))
return 0;
return true;
lua_settop(gL, 0);
hud_running = true; // local hook

View file

@ -268,10 +268,14 @@ static int patch_get(lua_State *L)
#endif
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
// patches are CURRENTLY always valid, expected to be cached with PU_STATIC
// this may change in the future, so patch.valid still exists
if (!patch)
// patches are invalidated when switching renderers
if (!patch) {
if (field == patch_valid) {
lua_pushboolean(L, 0);
return 1;
}
return LUA_ErrInvalid(L, "patch_t");
}
switch (field)
{
@ -424,7 +428,7 @@ static int libd_cachePatch(lua_State *L)
return 1;
}
// v.getSpritePatch(sprite, [frame, [angle]])
// v.getSpritePatch(sprite, [frame, [angle, [rollangle]]])
static int libd_getSpritePatch(lua_State *L)
{
UINT32 i; // sprite prefix
@ -475,13 +479,31 @@ static int libd_getSpritePatch(lua_State *L)
if (angle >= ((sprframe->rotate & SRF_3DGE) ? 16 : 8)) // out of range?
return 0;
#ifdef ROTSPRITE
if (lua_isnumber(L, 4))
{
// rotsprite?????
angle_t rollangle = luaL_checkangle(L, 4);
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle)))
R_CacheRotSprite(i, frame, NULL, sprframe, angle, sprframe->flip & (1<<angle));
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
return 3;
}
}
#endif
// push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2;
}
// v.getSprite2Patch(skin, sprite, [super?,] [frame, [angle]])
// v.getSprite2Patch(skin, sprite, [super?,] [frame, [angle, [rollangle]]])
static int libd_getSprite2Patch(lua_State *L)
{
INT32 i; // skin number
@ -570,6 +592,24 @@ static int libd_getSprite2Patch(lua_State *L)
if (angle >= ((sprframe->rotate & SRF_3DGE) ? 16 : 8)) // out of range?
return 0;
#ifdef ROTSPRITE
if (lua_isnumber(L, 4))
{
// rotsprite?????
angle_t rollangle = luaL_checkangle(L, 4);
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle)))
R_CacheRotSprite(SPR_PLAY, frame, &skins[i].sprinfo[j], sprframe, angle, sprframe->flip & (1<<angle));
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
return 3;
}
}
#endif
// push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
@ -1214,7 +1254,7 @@ void LUAh_GameHUD(player_t *stplayr)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2); // HUD[2] = rendering funcs
lua_rawgeti(gL, -1, 2+hudhook_game); // HUD[2] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
@ -1248,7 +1288,7 @@ void LUAh_ScoresHUD(void)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 3); // HUD[3] = rendering funcs
lua_rawgeti(gL, -1, 2+hudhook_scores); // HUD[3] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
@ -1273,7 +1313,7 @@ void LUAh_TitleHUD(void)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 4); // HUD[4] = rendering funcs
lua_rawgeti(gL, -1, 2+hudhook_title); // HUD[5] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
@ -1298,7 +1338,7 @@ void LUAh_TitleCardHUD(player_t *stplayr)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 5); // HUD[5] = rendering funcs
lua_rawgeti(gL, -1, 2+hudhook_titlecard); // HUD[6] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
@ -1332,7 +1372,7 @@ void LUAh_IntermissionHUD(void)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 4); // HUD[4] = rendering funcs
lua_rawgeti(gL, -1, 2+hudhook_intermission); // HUD[4] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw

View file

@ -120,6 +120,8 @@ static int player_get(lua_State *L)
lua_pushfixed(L, plr->deltaviewheight);
else if (fastcmp(field,"bob"))
lua_pushfixed(L, plr->bob);
else if (fastcmp(field,"viewrollangle"))
lua_pushangle(L, plr->viewrollangle);
else if (fastcmp(field,"aiming"))
lua_pushangle(L, plr->aiming);
else if (fastcmp(field,"drawangle"))
@ -362,6 +364,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->bot);
else if (fastcmp(field,"jointime"))
lua_pushinteger(L, plr->jointime);
else if (fastcmp(field,"quittime"))
lua_pushinteger(L, plr->quittime);
#ifdef HWRENDER
else if (fastcmp(field,"fovadd"))
lua_pushfixed(L, plr->fovadd);
@ -415,6 +419,8 @@ static int player_set(lua_State *L)
plr->deltaviewheight = luaL_checkfixed(L, 3);
else if (fastcmp(field,"bob"))
plr->bob = luaL_checkfixed(L, 3);
else if (fastcmp(field,"viewrollangle"))
plr->viewrollangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"aiming")) {
plr->aiming = luaL_checkangle(L, 3);
if (plr == &players[consoleplayer])
@ -701,6 +707,8 @@ static int player_set(lua_State *L)
return NOSET;
else if (fastcmp(field,"jointime"))
plr->jointime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"quittime"))
plr->quittime = (tic_t)luaL_checkinteger(L, 3);
#ifdef HWRENDER
else if (fastcmp(field,"fovadd"))
plr->fovadd = luaL_checkfixed(L, 3);

View file

@ -102,6 +102,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word,"circuitmap")) {
lua_pushboolean(L, circuitmap);
return 1;
} else if (fastcmp(word,"stoppedclock")) {
lua_pushboolean(L, stoppedclock);
return 1;
} else if (fastcmp(word,"netgame")) {
lua_pushboolean(L, netgame);
return 1;

View file

@ -19,6 +19,7 @@
#include "v_video.h"
#include "i_video.h"
#include "m_misc.h"
#include "st_stuff.h" // st_palette
#ifdef HWRENDER
#include "hardware/hw_main.h"
@ -29,11 +30,17 @@
consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#ifdef HAVE_ANIGIF
static boolean gif_optimize = false; // So nobody can do something dumb
static boolean gif_downscale = false; // like changing cvars mid output
static RGBA_t *gif_palette = NULL;
// Palette handling
static boolean gif_localcolortable = false;
static boolean gif_colorprofile = false;
static RGBA_t *gif_headerpalette = NULL;
static RGBA_t *gif_framepalette = NULL;
static FILE *gif_out = NULL;
static INT32 gif_frames = 0;
@ -393,16 +400,47 @@ const UINT8 gifhead_nsid[19] = {0x21,0xFF,0x0B, // extension block + size
0x4E,0x45,0x54,0x53,0x43,0x41,0x50,0x45,0x32,0x2E,0x30, // NETSCAPE2.0
0x03,0x01,0xFF,0xFF,0x00}; // sub-block, repetitions
//
// GIF_getpalette
// determine the palette for the current frame.
//
static RGBA_t *GIF_getpalette(size_t palnum)
{
// In hardware mode, always returns the local palette
#ifdef HWRENDER
if (rendermode == render_opengl)
return pLocalPalette;
else
#endif
return (gif_colorprofile ? &pLocalPalette[palnum*256] : &pMasterPalette[palnum*256]);
}
//
// GIF_palwrite
// writes the gif palette.
// used both for the header and local color tables.
//
static UINT8 *GIF_palwrite(UINT8 *p, RGBA_t *pal)
{
INT32 i;
for (i = 0; i < 256; i++)
{
WRITEUINT8(p, pal[i].s.red);
WRITEUINT8(p, pal[i].s.green);
WRITEUINT8(p, pal[i].s.blue);
}
return p;
}
//
// GIF_headwrite
// writes the gif header to the currently open output file.
// NOTE that this code does not accomodate for palette changes.
//
static void GIF_headwrite(void)
{
UINT8 *gifhead = Z_Malloc(800, PU_STATIC, NULL);
UINT8 *p = gifhead;
INT32 i;
UINT16 rwidth, rheight;
if (!gif_out)
@ -423,24 +461,17 @@ static void GIF_headwrite(void)
rwidth = vid.width;
rheight = vid.height;
}
WRITEUINT16(p, rwidth);
WRITEUINT16(p, rheight);
// colors, aspect, etc
WRITEUINT8(p, 0xF7);
WRITEUINT8(p, 0xF7); // (0xF7 = 1111 0111)
WRITEUINT8(p, 0x00);
WRITEUINT8(p, 0x00);
// write color table
{
RGBA_t *pal = gif_palette;
for (i = 0; i < 256; i++)
{
WRITEUINT8(p, pal[i].s.red);
WRITEUINT8(p, pal[i].s.green);
WRITEUINT8(p, pal[i].s.blue);
}
}
p = GIF_palwrite(p, gif_headerpalette);
// write extension block
WRITEMEM(p, gifhead_nsid, sizeof(gifhead_nsid));
@ -468,7 +499,7 @@ static void hwrconvert(void)
INT32 x, y;
size_t i = 0;
InitColorLUT(gif_palette);
InitColorLUT(gif_framepalette);
for (y = 0; y < vid.height; y++)
{
@ -494,6 +525,7 @@ static void GIF_framewrite(void)
UINT8 *p;
UINT8 *movie_screen = screens[2];
INT32 blitx, blity, blitw, blith;
boolean palchanged;
if (!gifframe_data)
gifframe_data = Z_Malloc(gifframe_size, PU_STATIC, NULL);
@ -502,8 +534,18 @@ static void GIF_framewrite(void)
if (!gif_out)
return;
// Lactozilla: Compare the header's palette with the current frame's palette and see if it changed.
if (gif_localcolortable)
{
gif_framepalette = GIF_getpalette(max(st_palette, 0));
palchanged = memcmp(gif_headerpalette, gif_framepalette, sizeof(RGBA_t) * 256);
}
else
palchanged = false;
// Compare image data (for optimizing GIF)
if (gif_optimize && gif_frames > 0)
// If the palette has changed, the entire frame is considered to be different.
if (gif_optimize && gif_frames > 0 && (!palchanged))
{
// before blit movie_screen points to last frame, cur_screen points to this frame
UINT8 *cur_screen = screens[0];
@ -566,7 +608,20 @@ static void GIF_framewrite(void)
WRITEUINT16(p, (UINT16)(blity / scrbuf_downscaleamt));
WRITEUINT16(p, (UINT16)(blitw / scrbuf_downscaleamt));
WRITEUINT16(p, (UINT16)(blith / scrbuf_downscaleamt));
WRITEUINT8(p, 0); // no local table of colors
if (!gif_localcolortable)
WRITEUINT8(p, 0); // no local table of colors
else
{
if (palchanged)
{
// The palettes are different, so write the Local Color Table!
WRITEUINT8(p, 0x87); // (0x87 = 1000 0111)
p = GIF_palwrite(p, gif_framepalette);
}
else
WRITEUINT8(p, 0); // They are equal, no Local Color Table needed.
}
scrbuf_pos = movie_screen + blitx + (blity * vid.width);
scrbuf_writeend = scrbuf_pos + (blitw - 1) + ((blith - 1) * vid.width);
@ -624,29 +679,15 @@ static void GIF_framewrite(void)
//
INT32 GIF_open(const char *filename)
{
#if 0
if (rendermode != render_soft)
{
CONS_Alert(CONS_WARNING, M_GetText("GIFs cannot be taken in non-software modes!\n"));
return 0;
}
#endif
gif_out = fopen(filename, "wb");
if (!gif_out)
return 0;
gif_optimize = (!!cv_gif_optimize.value);
gif_downscale = (!!cv_gif_downscale.value);
// GIF color table
// In hardware mode, uses the master palette
gif_palette = ((cv_screenshot_colorprofile.value
#ifdef HWRENDER
&& (rendermode == render_soft)
#endif
) ? pLocalPalette
: pMasterPalette);
gif_localcolortable = (!!cv_gif_localcolortable.value);
gif_colorprofile = (!!cv_screenshot_colorprofile.value);
gif_headerpalette = GIF_getpalette(0);
GIF_headwrite();
gif_frames = 0;

View file

@ -27,6 +27,6 @@ void GIF_frame(void);
INT32 GIF_close(void);
#endif
extern consvar_t cv_gif_optimize, cv_gif_downscale;
extern consvar_t cv_gif_optimize, cv_gif_downscale, cv_gif_localcolortable;
#endif

View file

@ -92,36 +92,21 @@ const char *M_GetNextParm(void)
void M_PushSpecialParameters(void)
{
INT32 i;
char s[256];
boolean onetime = false;
for (i = 1; i < myargc; i++)
{
if (myargv[i][0] == '+')
{
strcpy(s, &myargv[i][1]);
COM_BufAddText(&myargv[i][1]);
i++;
// get the parameters of the command too
for (; i < myargc && myargv[i][0] != '+' && myargv[i][0] != '-'; i++)
{
strcat(s, " ");
if (!onetime)
{
strcat(s, "\"");
onetime = true;
}
strcat(s, myargv[i]);
COM_BufAddText(va(" \"%s\"", myargv[i]));
}
if (onetime)
{
strcat(s, "\"");
onetime = false;
}
strcat(s, "\n");
// push it
COM_BufAddText(s);
COM_BufAddText("\n");
i--;
}
}

View file

@ -452,7 +452,7 @@ void Command_RTeleport_f(void)
else
inty = 0;
ss = R_IsPointInSubsector(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT);
ss = R_PointInSubsectorOrNull(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
@ -530,7 +530,7 @@ void Command_Teleport_f(void)
inty = mt->y<<FRACBITS;
offset = mt->z<<FRACBITS;
ss = R_IsPointInSubsector(intx, inty);
ss = R_PointInSubsectorOrNull(intx, inty);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Spawnpoint not in a valid location.\n"));
@ -597,7 +597,7 @@ void Command_Teleport_f(void)
return;
}
ss = R_IsPointInSubsector(mo2->x, mo2->y);
ss = R_PointInSubsectorOrNull(mo2->x, mo2->y);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Starpost not in a valid location.\n"));
@ -653,7 +653,7 @@ void Command_Teleport_f(void)
}
}
ss = R_IsPointInSubsector(intx, inty);
ss = R_PointInSubsectorOrNull(intx, inty);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));

View file

@ -231,6 +231,8 @@ static void M_Credits(INT32 choice);
static void M_SoundTest(INT32 choice);
static void M_PandorasBox(INT32 choice);
static void M_EmblemHints(INT32 choice);
static void M_HandleEmblemHints(INT32 choice);
UINT32 hintpage = 1;
static void M_HandleChecklist(INT32 choice);
menu_t SR_MainDef, SR_UnlockChecklistDef;
@ -323,6 +325,7 @@ menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef;
menu_t OP_ServerOptionsDef;
menu_t OP_MonitorToggleDef;
static void M_ScreenshotOptions(INT32 choice);
static void M_SetupScreenshotMenu(void);
static void M_EraseData(INT32 choice);
static void M_Addons(INT32 choice);
@ -364,7 +367,6 @@ static void M_DrawMonitorToggles(void);
static void M_OGL_DrawFogMenu(void);
#endif
#ifndef NONET
static void M_DrawScreenshotMenu(void);
static void M_DrawConnectMenu(void);
static void M_DrawMPMainMenu(void);
static void M_DrawRoomMenu(void);
@ -727,8 +729,9 @@ static menuitem_t SR_SoundTestMenu[] =
static menuitem_t SR_EmblemHintMenu[] =
{
{IT_STRING|IT_CVAR, NULL, "Emblem Radar", &cv_itemfinder, 10},
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SPauseDef, 20}
{IT_STRING | IT_ARROWS, NULL, "Page", M_HandleEmblemHints, 10},
{IT_STRING|IT_CVAR, NULL, "Emblem Radar", &cv_itemfinder, 20},
{IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SPauseDef, 30}
};
// --------------------------------
@ -1514,6 +1517,7 @@ static menuitem_t OP_ScreenshotOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 95},
{IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 100},
{IT_STRING|IT_CVAR, NULL, "Local Color Table", &cv_gif_localcolortable, 105},
{IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 95},
{IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 100},
@ -1524,13 +1528,14 @@ static menuitem_t OP_ScreenshotOptionsMenu[] =
enum
{
op_screenshot_colorprofile = 1,
op_screenshot_storagelocation = 3,
op_screenshot_folder = 4,
op_movie_folder = 11,
op_screenshot_capture = 12,
op_screenshot_gif_start = 13,
op_screenshot_gif_end = 14,
op_screenshot_apng_start = 15,
op_screenshot_apng_end = 18,
op_screenshot_gif_end = 15,
op_screenshot_apng_start = 16,
op_screenshot_apng_end = 19,
};
static menuitem_t OP_EraseDataMenu[] =
@ -3028,7 +3033,8 @@ static void M_ChangeCvar(INT32 choice)
|| !(currentMenu->menuitems[itemOn].status & IT_CV_INTEGERSTEP))
{
char s[20];
sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f));
float n = FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f);
sprintf(s,"%ld%s",(long)n,M_Ftrim(n));
CV_Set(cv,s);
}
else
@ -3758,6 +3764,12 @@ void M_SetupNextMenu(menu_t *menudef)
hidetitlemap = false;
}
// Guess I'll put this here, idk
boolean M_MouseNeeded(void)
{
return (currentMenu == &MessageDef && currentMenu->prevMenu == &OP_ChangeControlsDef);
}
//
// M_Ticker
//
@ -3779,6 +3791,9 @@ void M_Ticker(void)
if (--vidm_testingmode == 0)
setmodeneeded = vidm_previousmode + 1;
}
if (currentMenu == &OP_ScreenshotOptionsDef)
M_SetupScreenshotMenu();
}
//
@ -5596,7 +5611,8 @@ static void M_DrawNightsAttackMountains(void)
static INT32 bgscrollx;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
patch_t *background = W_CachePatchName(curbgname, PU_PATCH);
INT32 x = FixedInt(bgscrollx) % SHORT(background->width);
INT16 w = SHORT(background->width);
INT32 x = FixedInt(-bgscrollx) % w;
INT32 y = BASEVIDHEIGHT - SHORT(background->height)*2;
if (vid.height != BASEVIDHEIGHT * dupz)
@ -5604,11 +5620,13 @@ static void M_DrawNightsAttackMountains(void)
V_DrawFill(0, y+50, vid.width, BASEVIDHEIGHT, V_SNAPTOLEFT|31);
V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background);
x += SHORT(background->width);
x += w;
if (x < BASEVIDWIDTH)
V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background);
bgscrollx -= (FRACUNIT/2);
bgscrollx += (FRACUNIT/2);
if (bgscrollx > w<<FRACBITS)
bgscrollx &= 0xFFFF;
}
// NiGHTS Attack foreground.
@ -7225,18 +7243,33 @@ finishchecklist:
}
#define NUMHINTS 5
static void M_EmblemHints(INT32 choice)
{
INT32 i;
UINT32 local = 0;
emblem_t *emblem;
for (i = 0; i < numemblems; i++)
{
emblem = &emblemlocations[i];
if (emblem->level != gamemap || emblem->type > ET_SKIN)
continue;
if (++local > NUMHINTS*2)
break;
}
(void)choice;
SR_EmblemHintMenu[0].status = (M_SecretUnlocked(SECRET_ITEMFINDER)) ? (IT_CVAR|IT_STRING) : (IT_SECRET);
SR_EmblemHintMenu[0].status = (local > NUMHINTS*2) ? (IT_STRING | IT_ARROWS) : (IT_DISABLED);
SR_EmblemHintMenu[1].status = (M_SecretUnlocked(SECRET_ITEMFINDER)) ? (IT_CVAR|IT_STRING) : (IT_SECRET);
hintpage = 1;
M_SetupNextMenu(&SR_EmblemHintDef);
itemOn = 1; // always start on back.
itemOn = 2; // always start on back.
}
static void M_DrawEmblemHints(void)
{
INT32 i, j = 0, x, y, left_hints = NUMHINTS;
UINT32 collected = 0, local = 0;
INT32 i, j = 0, x, y, left_hints = NUMHINTS, pageflag = 0;
UINT32 collected = 0, totalemblems = 0, local = 0;
emblem_t *emblem;
const char *hint;
@ -7245,17 +7278,34 @@ static void M_DrawEmblemHints(void)
emblem = &emblemlocations[i];
if (emblem->level != gamemap || emblem->type > ET_SKIN)
continue;
if (++local >= NUMHINTS*2)
break;
local++;
}
x = (local > NUMHINTS ? 4 : 12);
y = 8;
// If there are more than 1 page's but less than 2 pages' worth of emblems,
if (local > NUMHINTS){
if (local > ((hintpage-1)*NUMHINTS*2) && local < ((hintpage)*NUMHINTS*2)){
if (NUMHINTS % 2 == 1)
left_hints = (local - ((hintpage-1)*NUMHINTS*2) + 1) / 2;
else
left_hints = (local - ((hintpage-1)*NUMHINTS*2)) / 2;
}else{
left_hints = NUMHINTS;
}
}
if (local > NUMHINTS*2){
if (itemOn == 0){
pageflag = V_YELLOWMAP;
}
V_DrawString(currentMenu->x + 40, currentMenu->y + 10, pageflag, va("%d of %d",hintpage, local/(NUMHINTS*2) + 1));
}
// If there are more than 1 page's but less than 2 pages' worth of emblems on the last possible page,
// put half (rounded up) of the hints on the left, and half (rounded down) on the right
if (local > NUMHINTS && local < (NUMHINTS*2)-1)
left_hints = (local + 1) / 2;
if (!local)
V_DrawCenteredString(160, 48, V_YELLOWMAP, "No hidden emblems on this map.");
@ -7265,42 +7315,80 @@ static void M_DrawEmblemHints(void)
if (emblem->level != gamemap || emblem->type > ET_SKIN)
continue;
if (emblem->collected)
{
collected = V_GREENMAP;
V_DrawMappedPatch(x, y+4, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE));
}
else
{
collected = 0;
V_DrawScaledPatch(x, y+4, 0, W_CachePatchName("NEEDIT", PU_PATCH));
}
totalemblems++;
if (emblem->hint[0])
hint = emblem->hint;
else
hint = M_GetText("No hint available for this emblem.");
hint = V_WordWrap(40, BASEVIDWIDTH-12, 0, hint);
if (local > NUMHINTS)
V_DrawThinString(x+28, y, V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
else
V_DrawString(x+28, y, V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
if (totalemblems >= ((hintpage-1)*(NUMHINTS*2) + 1) && totalemblems < (hintpage*NUMHINTS*2)+1){
y += 28;
if (emblem->collected)
{
collected = V_GREENMAP;
V_DrawMappedPatch(x, y+4, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE));
}
else
{
collected = 0;
V_DrawScaledPatch(x, y+4, 0, W_CachePatchName("NEEDIT", PU_PATCH));
}
if (++j == left_hints)
{
x = 4+(BASEVIDWIDTH/2);
y = 8;
if (emblem->hint[0])
hint = emblem->hint;
else
hint = M_GetText("No hint available for this emblem.");
hint = V_WordWrap(40, BASEVIDWIDTH-12, 0, hint);
//always draw tiny if we have more than NUMHINTS*2, visually more appealing
if (local > NUMHINTS)
V_DrawThinString(x+28, y, V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
else
V_DrawString(x+28, y, V_RETURN8|V_ALLOWLOWERCASE|collected, hint);
y += 28;
// If there are more than 1 page's but less than 2 pages' worth of emblems on the last possible page,
// put half (rounded up) of the hints on the left, and half (rounded down) on the right
if (++j == left_hints)
{
x = 4+(BASEVIDWIDTH/2);
y = 8;
}
else if (j >= NUMHINTS*2)
break;
}
else if (j >= NUMHINTS*2)
break;
}
M_DrawGenericMenu();
}
static void M_HandleEmblemHints(INT32 choice)
{
INT32 i;
emblem_t *emblem;
UINT32 stageemblems = 0;
for (i = 0; i < numemblems; i++)
{
emblem = &emblemlocations[i];
if (emblem->level != gamemap || emblem->type > ET_SKIN)
continue;
stageemblems++;
}
if (choice == 0){
if (hintpage > 1){
hintpage--;
}
}else{
if (hintpage < ((stageemblems-1)/(NUMHINTS*2) + 1)){
hintpage++;
}
}
}
/*static void M_DrawSkyRoom(void)
{
INT32 i, y = 0;
@ -8059,8 +8147,16 @@ static void M_DrawLoadGameData(void)
col = 134;
else
{
col = charskin->prefcolor - 1;
col = Color_Index[Color_Opposite[col][0]-1][Color_Opposite[col][1]];
if (charskin->prefoppositecolor)
{
col = charskin->prefoppositecolor - 1;
col = Color_Index[col][Color_Opposite[Color_Opposite[col][0] - 1][1]];
}
else
{
col = charskin->prefcolor - 1;
col = Color_Index[Color_Opposite[col][0]-1][Color_Opposite[col][1]];
}
}
V_DrawFill(x+6, y+64, 72, 50, col);
@ -10837,7 +10933,6 @@ static void M_HandleConnectIP(INT32 choice)
default: // otherwise do nothing.
break;
}
break; // don't check for typed keys
}
if (l >= 28-1)
@ -11341,9 +11436,27 @@ static void M_ScreenshotOptions(INT32 choice)
Screenshot_option_Onchange();
Moviemode_mode_Onchange();
M_SetupScreenshotMenu();
M_SetupNextMenu(&OP_ScreenshotOptionsDef);
}
static void M_SetupScreenshotMenu(void)
{
menuitem_t *item = &OP_ScreenshotOptionsMenu[op_screenshot_colorprofile];
#ifdef HWRENDER
// Hide some options based on render mode
if (rendermode == render_opengl)
{
item->status = IT_GRAYEDOUT;
if ((currentMenu == &OP_ScreenshotOptionsDef) && (itemOn == op_screenshot_colorprofile)) // Can't select that
itemOn = op_screenshot_storagelocation;
}
else
#endif
item->status = (IT_STRING | IT_CVAR);
}
// =============
// JOYSTICK MENU
// =============
@ -12286,6 +12399,15 @@ static void M_HandleVideoMode(INT32 ch)
static void M_DrawScreenshotMenu(void)
{
M_DrawGenericScrollMenu();
#ifdef HWRENDER
if ((rendermode == render_opengl) && (itemOn < 7)) // where it starts to go offscreen; change this number if you change the layout of the screenshot menu
{
INT32 y = currentMenu->y+currentMenu->menuitems[op_screenshot_colorprofile].alphaKey*2;
if (itemOn == 6)
y -= 10;
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, y, V_REDMAP, "Yes");
}
#endif
}
// ===============

View file

@ -322,6 +322,9 @@ typedef struct menu_s
void M_SetupNextMenu(menu_t *menudef);
void M_ClearMenus(boolean callexitmenufunc);
// Maybe this goes here????? Who knows.
boolean M_MouseNeeded(void);
extern menu_t *currentMenu;
extern menu_t MainDef;

View file

@ -2612,3 +2612,21 @@ int M_JumpWordReverse(const char *line, int offset)
offset--;
return offset;
}
const char * M_Ftrim (double f)
{
static char dig[9];/* "0." + 6 digits (6 is printf's default) */
int i;
/* I know I said it's the default, but just in case... */
sprintf(dig, "%.6f", fabs(modf(f, &f)));
/* trim trailing zeroes */
for (i = strlen(dig)-1; dig[i] == '0'; --i)
;
if (dig[i] == '.')/* :NOTHING: */
return "";
else
{
dig[i + 1] = '\0';
return &dig[1];/* skip the 0 */
}
}

View file

@ -109,6 +109,12 @@ int M_JumpWord (const char *s);
/* E.g. cursor = M_JumpWordReverse(line, cursor); */
int M_JumpWordReverse (const char *line, int offset);
/*
Return dot and then the fractional part of a float, without
trailing zeros, or "" if the fractional part is zero.
*/
const char * M_Ftrim (double);
// counting bits, for weapon ammo code, usually
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);

View file

@ -746,6 +746,9 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
if (player->bot)
continue; // ignore bots
if (player->quittime)
continue; // Ignore uncontrolled bodies
if (dist > 0
&& P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist)
continue; // Too far away
@ -5195,8 +5198,8 @@ void A_SignPlayer(mobj_t *actor)
player_t *player = actor->target ? actor->target->player : NULL;
UINT8 skinnum;
UINT8 skincount = 0;
for (skincount = 0; skincount < numskins; skincount++)
if (!skincheck(skincount))
for (skinnum = 0; skinnum < numskins; skinnum++)
if (!skincheck(skinnum))
skincount++;
skinnum = P_RandomKey(skincount);
for (skincount = 0; skincount < numskins; skincount++)
@ -5229,20 +5232,23 @@ void A_SignPlayer(mobj_t *actor)
{
ov->color = facecolor;
ov->skin = skin;
P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN
if ((statenum_t)(ov->state-states) != actor->info->seestate)
P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN
}
else // CLEAR! sign
{
ov->color = SKINCOLOR_NONE;
ov->skin = NULL; // needs to be NULL in the case of SF_HIRES characters
P_SetMobjState(ov, actor->info->missilestate); // S_CLEARSIGN
if ((statenum_t)(ov->state-states) != actor->info->missilestate)
P_SetMobjState(ov, actor->info->missilestate); // S_CLEARSIGN
}
}
else // Eggman face
{
ov->color = SKINCOLOR_NONE;
ov->skin = NULL;
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
if ((statenum_t)(ov->state-states) != actor->info->meleestate)
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
if (!signcolor)
signcolor = SKINCOLOR_CARBON;
}

View file

@ -1428,98 +1428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Misc touchables //
// *************** //
case MT_STARPOST:
if (player->bot)
return;
// In circuit, player must have touched all previous starposts
if (circuitmap
&& special->health - player->starpostnum > 1)
{
// blatant reuse of a variable that's normally unused in circuit
if (!player->tossdelay)
S_StartSound(toucher, sfx_lose);
player->tossdelay = 3;
return;
}
// We could technically have 91.1 Star Posts. 90 is cleaner.
if (special->health > 90)
{
CONS_Debug(DBG_GAMELOGIC, "Bad Starpost Number!\n");
return;
}
if (player->starpostnum >= special->health)
return; // Already hit this post
if (cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (netgame || multiplayer))
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
{
if (players[i].bot) // ignore dumb, stupid tails
continue;
players[i].starposttime = leveltime;
players[i].starpostx = player->mo->x>>FRACBITS;
players[i].starposty = player->mo->y>>FRACBITS;
players[i].starpostz = special->z>>FRACBITS;
players[i].starpostangle = special->angle;
players[i].starpostscale = player->mo->destscale;
if (special->flags2 & MF2_OBJECTFLIP)
{
players[i].starpostscale *= -1;
players[i].starpostz += special->height>>FRACBITS;
}
players[i].starpostnum = special->health;
if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i]))
P_SpectatorJoinGame(&players[i]); //players[i].playerstate = PST_REBORN;
}
}
S_StartSound(NULL, special->info->painsound);
}
else
{
// Save the player's time and position.
player->starposttime = leveltime;
player->starpostx = toucher->x>>FRACBITS;
player->starposty = toucher->y>>FRACBITS;
player->starpostz = special->z>>FRACBITS;
player->starpostangle = special->angle;
player->starpostscale = player->mo->destscale;
if (special->flags2 & MF2_OBJECTFLIP)
{
player->starpostscale *= -1;
player->starpostz += special->height>>FRACBITS;
}
player->starpostnum = special->health;
S_StartSound(toucher, special->info->painsound);
}
P_ClearStarPost(special->health);
// Find all starposts in the level with this value - INCLUDING this one!
if (!(netgame && circuitmap && player != &players[consoleplayer]))
{
thinker_t *th;
mobj_t *mo2;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST)
continue;
if (mo2->health != special->health)
continue;
P_SetMobjState(mo2, mo2->info->painstate);
}
}
P_TouchStarPost(special, player, special->spawnpoint && (special->spawnpoint->options & MTF_OBJECTSPECIAL));
return;
case MT_FAKEMOBILE:
@ -1872,6 +1781,112 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->shadowscale = 0;
}
/** Saves a player's level progress at a star post
*
* \param post The star post to trigger
* \param player The player that should receive the checkpoint
* \param snaptopost If true, the respawn point will use the star post's position, otherwise player x/y and star post z
*/
void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
{
size_t i;
mobj_t *toucher = player->mo;
mobj_t *checkbase = snaptopost ? post : toucher;
if (player->bot)
return;
// In circuit, player must have touched all previous starposts
if (circuitmap
&& post->health - player->starpostnum > 1)
{
// blatant reuse of a variable that's normally unused in circuit
if (!player->tossdelay)
S_StartSound(toucher, sfx_lose);
player->tossdelay = 3;
return;
}
// With the parameter + angle setup, we can go up to 1365 star posts. Who needs that many?
if (post->health > 1365)
{
CONS_Debug(DBG_GAMELOGIC, "Bad Starpost Number!\n");
return;
}
if (player->starpostnum >= post->health)
return; // Already hit this post
if (cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (netgame || multiplayer))
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
{
if (players[i].bot) // ignore dumb, stupid tails
continue;
players[i].starposttime = leveltime;
players[i].starpostx = checkbase->x>>FRACBITS;
players[i].starposty = checkbase->y>>FRACBITS;
players[i].starpostz = post->z>>FRACBITS;
players[i].starpostangle = post->angle;
players[i].starpostscale = player->mo->destscale;
if (post->flags2 & MF2_OBJECTFLIP)
{
players[i].starpostscale *= -1;
players[i].starpostz += post->height>>FRACBITS;
}
players[i].starpostnum = post->health;
if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i]))
P_SpectatorJoinGame(&players[i]); //players[i].playerstate = PST_REBORN;
}
}
S_StartSound(NULL, post->info->painsound);
}
else
{
// Save the player's time and position.
player->starposttime = leveltime;
player->starpostx = checkbase->x>>FRACBITS;
player->starposty = checkbase->y>>FRACBITS;
player->starpostz = post->z>>FRACBITS;
player->starpostangle = post->angle;
player->starpostscale = player->mo->destscale;
if (post->flags2 & MF2_OBJECTFLIP)
{
player->starpostscale *= -1;
player->starpostz += post->height>>FRACBITS;
}
player->starpostnum = post->health;
S_StartSound(toucher, post->info->painsound);
}
P_ClearStarPost(post->health);
// Find all starposts in the level with this value - INCLUDING this one!
if (!(netgame && circuitmap && player != &players[consoleplayer]))
{
thinker_t *th;
mobj_t *mo2;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST)
continue;
if (mo2->health != post->health)
continue;
P_SetMobjState(mo2, mo2->info->painstate);
}
}
}
/** Prints death messages relating to a dying or hit player.
*
* \param player Affected player.
@ -2257,9 +2272,9 @@ void P_CheckSurvivors(void)
{
if (players[i].spectator)
spectators++;
else if (players[i].pflags & PF_TAGIT)
else if ((players[i].pflags & PF_TAGIT) && players[i].quittime < 30 * TICRATE)
taggers++;
else if (!(players[i].pflags & PF_GAMETYPEOVER))
else if (!(players[i].pflags & PF_GAMETYPEOVER) && players[i].quittime < 30 * TICRATE)
{
survivorarray[survivors] = i;
survivors++;
@ -2527,7 +2542,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
else if (!target->player->bot && !target->player->spectator && (target->player->lives != INFLIVES)
&& G_GametypeUsesLives())
{
target->player->lives -= 1; // Lose a life Tails 03-11-2000
if (!(target->player->pflags & PF_FINISHED))
target->player->lives -= 1; // Lose a life Tails 03-11-2000
if (target->player->lives <= 0) // Tails 03-14-2000
{

View file

@ -159,6 +159,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives);
void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound);
UINT8 P_GetNextEmerald(void);
void P_GiveEmerald(boolean spawnObj);
void P_GiveFinishFlags(player_t *player);
#if 0
void P_ResetScore(player_t *player);
#else
@ -486,6 +487,7 @@ void P_PlayerWeaponPanelOrAmmoBurst(player_t *player);
void P_PlayerEmeraldBurst(player_t *player, boolean toss);
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck);
void P_TouchStarPost(mobj_t *starpost, player_t *player, boolean snaptopost);
void P_PlayerFlagBurst(player_t *player, boolean toss);
void P_CheckTimeLimit(void);
void P_CheckPointLimit(void);

View file

@ -592,9 +592,6 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
if (!(tails->pflags & PF_CANCARRY))
return;
if (sonic->pflags & PF_FINISHED)
return;
if ((sonic->mo->eflags & MFE_VERTICALFLIP) != (tails->mo->eflags & MFE_VERTICALFLIP))
return; // Both should be in same gravity

View file

@ -1997,8 +1997,12 @@ void P_XYMovement(mobj_t *mo)
{
mo->momz = transfermomz;
mo->standingslope = NULL;
if (player && (player->pflags & PF_SPINNING))
player->pflags |= PF_THOKKED;
if (player)
{
player->powers[pw_justlaunched] = 2;
if (player->pflags & PF_SPINNING)
player->pflags |= PF_THOKKED;
}
}
}
#endif
@ -2350,6 +2354,7 @@ static void P_RingZMovement(mobj_t *mo)
if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{
mo->momz += mo->pmomz;
mo->pmomz = 0;
mo->eflags &= ~MFE_APPLYPMOMZ;
}
mo->z += mo->momz;
@ -2419,6 +2424,7 @@ static boolean P_ZMovement(mobj_t *mo)
if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{
mo->momz += mo->pmomz;
mo->pmomz = 0;
mo->eflags &= ~MFE_APPLYPMOMZ;
}
mo->z += mo->momz;
@ -2907,6 +2913,7 @@ static void P_PlayerZMovement(mobj_t *mo)
if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{
mo->momz += mo->pmomz;
mo->pmomz = 0;
mo->eflags &= ~MFE_APPLYPMOMZ;
}
@ -3157,6 +3164,7 @@ static boolean P_SceneryZMovement(mobj_t *mo)
if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{
mo->momz += mo->pmomz;
mo->pmomz = 0;
mo->eflags &= ~MFE_APPLYPMOMZ;
}
mo->z += mo->momz;
@ -3396,7 +3404,7 @@ void P_MobjCheckWater(mobj_t *mobj)
if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability])))
{
boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC);
if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER)))
if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER) && !(mobj->eflags & MFE_TOUCHLAVA)))
{ // Water removes electric and non-water fire shields...
P_FlashPal(p,
electric
@ -3918,6 +3926,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
// Needed for gravity boots
P_CheckGravity(mobj, false);
mobj->player->powers[pw_justlaunched] = 0;
if (mobj->momx || mobj->momy)
{
P_XYMovement(mobj);
@ -7996,6 +8005,37 @@ static void P_MobjSceneryThink(mobj_t *mobj)
mobj->frame = (mobj->frame & ~FF_TRANSMASK) | ((10 - (mobj->fuse*2)) << (FF_TRANSSHIFT));
}
break;
case MT_FINISHFLAG:
{
if (!mobj->target || mobj->target->player->playerstate == PST_DEAD || !cv_exitmove.value)
{
P_RemoveMobj(mobj);
return;
}
if (!camera.chase)
mobj->flags2 |= MF2_DONTDRAW;
else
mobj->flags2 &= ~MF2_DONTDRAW;
P_UnsetThingPosition(mobj);
{
fixed_t radius = FixedMul(10*mobj->info->speed, mobj->target->scale);
angle_t fa;
mobj->angle += FixedAngle(mobj->info->speed);
fa = mobj->angle >> ANGLETOFINESHIFT;
mobj->x = mobj->target->x + FixedMul(FINECOSINE(fa),radius);
mobj->y = mobj->target->y + FixedMul(FINESINE(fa),radius);
mobj->z = mobj->target->z + mobj->target->height/2;
}
P_SetThingPosition(mobj);
P_SetScale(mobj, mobj->target->scale);
}
break;
case MT_VWREF:
case MT_VWREB:
{
@ -10457,6 +10497,61 @@ void P_SceneryThinker(mobj_t *mobj)
// GAME SPAWN FUNCTIONS
//
static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
{
switch (thing->type)
{
case MT_PLAYER:
case MT_ROLLOUTROCK:
case MT_EGGMOBILE4_MACE:
case MT_SMALLMACE:
case MT_BIGMACE:
case MT_SMALLGRABCHAIN:
case MT_BIGGRABCHAIN:
case MT_YELLOWSPRINGBALL:
case MT_REDSPRINGBALL:
return FRACUNIT;
case MT_RING:
case MT_FLINGRING:
case MT_BLUESPHERE:
case MT_FLINGBLUESPHERE:
case MT_BOMBSPHERE:
case MT_REDTEAMRING:
case MT_BLUETEAMRING:
case MT_REDFLAG:
case MT_BLUEFLAG:
case MT_EMBLEM:
case MT_TOKEN:
case MT_EMERALD1:
case MT_EMERALD2:
case MT_EMERALD3:
case MT_EMERALD4:
case MT_EMERALD5:
case MT_EMERALD6:
case MT_EMERALD7:
case MT_EMERHUNT:
case MT_FLINGEMERALD:
return 2*FRACUNIT/3;
default:
if (thing->flags & (MF_ENEMY|MF_BOSS))
return FRACUNIT;
else
return 0;
}
}
//
// P_SpawnMobj
//
@ -10558,20 +10653,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->z = z;
// Set shadowscale here, before spawn hook so that Lua can change it
if (
type == MT_PLAYER ||
type == MT_ROLLOUTROCK ||
type == MT_EGGMOBILE4_MACE ||
(type >= MT_SMALLMACE && type <= MT_REDSPRINGBALL) ||
(mobj->flags & (MF_ENEMY|MF_BOSS))
)
mobj->shadowscale = FRACUNIT;
else if (
type >= MT_RING && type <= MT_FLINGEMERALD && type != MT_EMERALDSPAWN
)
mobj->shadowscale = 2*FRACUNIT/3;
else
mobj->shadowscale = 0;
mobj->shadowscale = P_DefaultMobjShadowScale(mobj);
#ifdef HAVE_BLUA
// DANGER! This can cause P_SpawnMobj to return NULL!
@ -11114,7 +11196,7 @@ void P_SpawnPrecipitation(void)
x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3);
y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3);
precipsector = R_IsPointInSubsector(x, y);
precipsector = R_PointInSubsectorOrNull(x, y);
// No sector? Stop wasting time,
// move on to the next entry in the blockmap
@ -11512,6 +11594,9 @@ void P_AfterPlayerSpawn(INT32 playernum)
if (CheckForReverseGravity)
P_CheckGravity(mobj, false);
if (p->pflags & PF_FINISHED)
P_GiveFinishFlags(p);
}
// spawn it at a playerspawn mapthing
@ -12931,7 +13016,16 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
thinker_t* th;
mobj_t* mo2;
boolean foundanother = false;
mobj->health = (mthing->angle/360) + 1;
if (mthing->extrainfo)
// Allow thing Parameter to define star post num too!
// For starposts above param 15 (the 16th), add 360 to the angle like before and start parameter from 1 (NOT 0)!
// So the 16th starpost is angle=0 param=15, the 17th would be angle=360 param=1.
// This seems more intuitive for mappers to use until UDMF is ready, since most SP maps won't have over 16 consecutive star posts.
mobj->health = mthing->extrainfo + (mthing->angle/360)*15 + 1;
else
// Old behavior if Parameter is 0; add 360 to the angle for each consecutive star post.
mobj->health = (mthing->angle/360) + 1;
// See if other starposts exist in this level that have the same value.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)

View file

@ -1001,15 +1001,35 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo)
//
static void Polyobj_slideThing(mobj_t *mo, fixed_t dx, fixed_t dy)
{
if (mo->player) { // Do something similar to conveyor movement. -Red
mo->player->cmomx += dx;
mo->player->cmomy += dy;
if (mo->player) { // Finally this doesn't suck eggs -fickle
fixed_t cdx, cdy;
dx = FixedMul(dx, CARRYFACTOR);
dy = FixedMul(dy, CARRYFACTOR);
cdx = FixedMul(dx, FRACUNIT-CARRYFACTOR);
cdy = FixedMul(dy, FRACUNIT-CARRYFACTOR);
mo->player->cmomx -= dx;
mo->player->cmomy -= dy;
if (mo->player->onconveyor == 1)
{
mo->momx += cdx;
mo->momy += cdy;
// Multiple slides in the same tic, somehow
mo->player->cmomx += cdx;
mo->player->cmomy += cdy;
}
else
{
if (mo->player->onconveyor == 3)
{
mo->momx += cdx - mo->player->cmomx;
mo->momy += cdy - mo->player->cmomy;
}
mo->player->cmomx = cdx;
mo->player->cmomy = cdy;
}
dx = FixedMul(dx, FRACUNIT - mo->friction);
dy = FixedMul(dy, FRACUNIT - mo->friction);
if (mo->player->pflags & PF_SPINNING && (mo->player->rmomx || mo->player->rmomy) && !(mo->player->pflags & PF_STARTDASH)) {
#define SPINMULT 5184 // Consider this a substitute for properly calculating FRACUNIT-friction. I'm tired. -Red
@ -1282,7 +1302,8 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
{
static INT32 pomovecount = 10000;
INT32 x, y;
angle_t deltafine = delta >> ANGLETOFINESHIFT;
angle_t deltafine = (((po->angle + delta) >> ANGLETOFINESHIFT) - (po->angle >> ANGLETOFINESHIFT)) & FINEMASK;
// This fineshift trickery replaces the old delta>>ANGLETOFINESHIFT; doing it this way avoids loss of precision causing objects to slide off -fickle
pomovecount++;
@ -1334,19 +1355,10 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
oldxoff = mo->x-origin.x;
oldyoff = mo->y-origin.y;
if (mo->player) // Hack to fix players sliding off of spinning polys -Red
{
fixed_t temp;
newxoff = FixedMul(oldxoff, c)-FixedMul(oldyoff, s) - oldxoff;
newyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s) - oldyoff;
temp = FixedMul(oldxoff, c)-FixedMul(oldyoff, s);
oldyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s);
oldxoff = temp;
}
newxoff = FixedMul(oldxoff, c)-FixedMul(oldyoff, s);
newyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s);
Polyobj_slideThing(mo, newxoff-oldxoff, newyoff-oldyoff);
Polyobj_slideThing(mo, newxoff, newyoff);
if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
mo->angle += delta;

View file

@ -116,6 +116,7 @@ static void P_NetArchivePlayers(void)
WRITEANGLE(save_p, players[i].aiming);
WRITEANGLE(save_p, players[i].drawangle);
WRITEANGLE(save_p, players[i].viewrollangle);
WRITEANGLE(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics);
WRITEINT16(save_p, players[i].rings);
@ -255,6 +256,7 @@ static void P_NetArchivePlayers(void)
WRITEINT32(save_p, players[i].onconveyor);
WRITEUINT32(save_p, players[i].jointime);
WRITEUINT32(save_p, players[i].quittime);
WRITEUINT16(save_p, flags);
@ -325,6 +327,7 @@ static void P_NetUnArchivePlayers(void)
players[i].aiming = READANGLE(save_p);
players[i].drawangle = READANGLE(save_p);
players[i].viewrollangle = READANGLE(save_p);
players[i].awayviewaiming = READANGLE(save_p);
players[i].awayviewtics = READINT32(save_p);
players[i].rings = READINT16(save_p);
@ -446,6 +449,7 @@ static void P_NetUnArchivePlayers(void)
players[i].onconveyor = READINT32(save_p);
players[i].jointime = READUINT32(save_p);
players[i].quittime = READUINT32(save_p);
flags = READUINT16(save_p);
@ -607,7 +611,7 @@ static void P_NetArchiveColormaps(void)
WRITEUINT8(save_p, exc->fadestart);
WRITEUINT8(save_p, exc->fadeend);
WRITEUINT8(save_p, exc->fog);
WRITEUINT8(save_p, exc->flags);
WRITEINT32(save_p, exc->rgba);
WRITEINT32(save_p, exc->fadergba);
@ -637,7 +641,7 @@ static void P_NetUnArchiveColormaps(void)
for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next)
{
UINT8 fadestart, fadeend, fog;
UINT8 fadestart, fadeend, flags;
INT32 rgba, fadergba;
#ifdef EXTRACOLORMAPLUMPS
char lumpname[9];
@ -645,7 +649,7 @@ static void P_NetUnArchiveColormaps(void)
fadestart = READUINT8(save_p);
fadeend = READUINT8(save_p);
fog = READUINT8(save_p);
flags = READUINT8(save_p);
rgba = READINT32(save_p);
fadergba = READINT32(save_p);
@ -677,7 +681,7 @@ static void P_NetUnArchiveColormaps(void)
exc->fadestart = fadestart;
exc->fadeend = fadeend;
exc->fog = fog;
exc->flags = flags;
exc->rgba = rgba;
exc->fadergba = fadergba;
@ -687,7 +691,7 @@ static void P_NetUnArchiveColormaps(void)
exc->lumpname[0] = 0;
#endif
existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags);
if (existing_exc)
exc->colormap = existing_exc->colormap;
@ -1253,6 +1257,7 @@ typedef enum
#endif
MD2_COLORIZED = 1<<12,
MD2_ROLLANGLE = 1<<13,
MD2_SHADOWSCALE = 1<<14,
} mobj_diff2_t;
typedef enum
@ -1474,6 +1479,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_COLORIZED;
if (mobj->rollangle)
diff2 |= MD2_ROLLANGLE;
if (mobj->shadowscale)
diff2 |= MD2_SHADOWSCALE;
if (diff2 != 0)
diff |= MD_MORE;
@ -1640,6 +1647,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEUINT8(save_p, mobj->colorized);
if (diff2 & MD2_ROLLANGLE)
WRITEANGLE(save_p, mobj->rollangle);
if (diff2 & MD2_SHADOWSCALE)
WRITEFIXED(save_p, mobj->shadowscale);
WRITEUINT32(save_p, mobj->mobjnum);
}
@ -2719,6 +2728,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->colorized = READUINT8(save_p);
if (diff2 & MD2_ROLLANGLE)
mobj->rollangle = READANGLE(save_p);
if (diff2 & MD2_SHADOWSCALE)
mobj->shadowscale = READFIXED(save_p);
if (diff & MD_REDFLAG)
{

View file

@ -411,7 +411,7 @@ levelflat refers to an array of level flats,
or NULL if we want to allocate it now.
*/
static INT32
Ploadflat (levelflat_t *levelflat, const char *flatname)
Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
{
#ifndef NO_PNG_LUMPS
UINT8 buffer[8];
@ -422,31 +422,26 @@ Ploadflat (levelflat_t *levelflat, const char *flatname)
size_t i;
if (levelflat)
// Scan through the already found flats, return if it matches.
for (i = 0; i < numlevelflats; i++)
{
// Scan through the already found flats, return if it matches.
for (i = 0; i < numlevelflats; i++)
{
if (strnicmp(levelflat[i].name, flatname, 8) == 0)
return i;
}
if (strnicmp(levelflat[i].name, flatname, 8) == 0)
return i;
}
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
#endif
if (numlevelflats >= MAXLEVELFLATS)
I_Error("Too many flats in level\n");
if (levelflat)
levelflat += numlevelflats;
else
if (resize)
{
// allocate new flat memory
levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL);
levelflat = levelflats + numlevelflats;
}
else
{
if (numlevelflats >= MAXLEVELFLATS)
I_Error("Too many flats in level\n");
levelflat += numlevelflats;
}
// Store the name.
strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
@ -501,6 +496,10 @@ flatfound:
levelflat->u.flat.baselumpnum = LUMPERROR;
}
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
#endif
return ( numlevelflats++ );
}
@ -508,7 +507,7 @@ flatfound:
// allocate an id for it, and set the levelflat (to speedup search)
INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
{
return Ploadflat(levelflat, flatname);
return Ploadflat(levelflat, flatname, false);
}
// help function for Lua and $$$.sav reading
@ -517,7 +516,7 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
//
INT32 P_AddLevelFlatRuntime(const char *flatname)
{
return Ploadflat(levelflats, flatname);
return Ploadflat(levelflats, flatname, true);
}
// help function for $$$.sav checking
@ -3097,7 +3096,7 @@ static void P_InitTagGametype(void)
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
if (playeringame[i] && !(players[i].spectator && players[i].quittime))
{
playersactive[realnumplayers] = i; //stores the player's node in the array.
realnumplayers++;
@ -3119,7 +3118,7 @@ static void P_InitTagGametype(void)
if (players[playersactive[i]].mo)
P_RemoveMobj(players[playersactive[i]].mo);
G_SpawnPlayer(playersactive[i], false); //respawn the lucky player in his dedicated spawn location.
G_SpawnPlayer(playersactive[i]); //respawn the lucky player in his dedicated spawn location.
}
static void P_SetupCamera(void)
@ -3297,7 +3296,7 @@ static void P_InitPlayers(void)
G_DoReborn(i);
else // gametype is GT_COOP or GT_RACE
{
G_SpawnPlayer(i, players[i].starposttime);
G_SpawnPlayer(i);
if (players[i].starposttime)
P_ClearStarPost(players[i].starpostnum);
}
@ -3685,8 +3684,7 @@ boolean P_LoadLevel(boolean fromnetsave)
return true;
// If so...
if ((!(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)) && (*mapheaderinfo[gamemap-1]->lvlttl != '\0'))
G_PreLevelTitleCard();
G_PreLevelTitleCard();
return true;
}
@ -3828,10 +3826,9 @@ boolean P_AddWadFile(const char *wadfilename)
// UINT16 mapPos, mapNum = 0;
// Init file.
if ((numlumps = W_InitFile(wadfilename, false)) == INT16_MAX)
if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX)
{
refreshdirmenu |= REFRESHDIR_NOTLOADED;
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename);
return false;
}
else

View file

@ -726,6 +726,9 @@ void P_SlopeLaunch(mobj_t *mo)
//CONS_Printf("Launched off of slope.\n");
mo->standingslope = NULL;
if (mo->player)
mo->player->powers[pw_justlaunched] = 1;
}
//

View file

@ -3516,7 +3516,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
false, // subtract FadeA (no flag for this, just pass negative alpha)
false, // subtract FadeStart (we ran out of flags)
false, // subtract FadeEnd (we ran out of flags)
false, // ignore Fog (we ran out of flags)
false, // ignore Flags (we ran out of flags)
line->flags & ML_DONTPEGBOTTOM,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0,
@ -3883,7 +3883,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
false, // subtract FadeA (no flag for this, just pass negative alpha)
false, // subtract FadeStart (we ran out of flags)
false, // subtract FadeEnd (we ran out of flags)
false, // ignore Fog (we ran out of flags)
false, // ignore Flags (we ran out of flags)
line->flags & ML_DONTPEGBOTTOM,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].textureoffset >> FRACBITS) : 0,
(line->flags & ML_DONTPEGBOTTOM) ? (sides[line->sidenum[0]].rowoffset >> FRACBITS) : 0,
@ -4426,10 +4426,18 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
case 6: // Death Pit (Camera Mod)
case 7: // Death Pit (No Camera Mod)
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
{
if (player->quittime)
G_MovePlayerToSpawnOrStarpost(player - players);
else
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
}
break;
case 8: // Instant Kill
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
if (player->quittime)
G_MovePlayerToSpawnOrStarpost(player - players);
else
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
break;
case 9: // Ring Drainer (Floor Touch)
case 10: // Ring Drainer (No Floor Touch)
@ -4684,7 +4692,7 @@ DoneSection2:
if (!post)
break;
P_TouchSpecialThing(post, player->mo, false);
P_TouchStarPost(post, player, false);
break;
}
@ -7073,10 +7081,9 @@ void P_SpawnSpecials(boolean fromnetsave)
case 202: // Fog
ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_BOTHPLANES|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES;
sec = sides[*lines[i].sidenum].sector - sectors;
// SoM: Because it's fog, check for an extra colormap and set
// the fog flag...
// SoM: Because it's fog, check for an extra colormap and set the fog flag...
if (sectors[sec].extra_colormap)
sectors[sec].extra_colormap->fog = 1;
sectors[sec].extra_colormap->flags = CMF_FOG;
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break;
@ -8464,7 +8471,7 @@ void T_FadeColormap(fadecolormap_t *d)
extracolormap_t *exc;
INT32 duration = d->ticbased ? d->duration : 256;
fixed_t factor = min(FixedDiv(duration - d->timer, duration), 1*FRACUNIT);
INT16 cr, cg, cb, ca, fadestart, fadeend, fog;
INT16 cr, cg, cb, ca, fadestart, fadeend, flags;
INT32 rgba, fadergba;
// NULL failsafes (or intentionally set to signify default)
@ -8513,7 +8520,7 @@ void T_FadeColormap(fadecolormap_t *d)
fadestart = APPLYFADE(d->dest_exc->fadestart, d->source_exc->fadestart, d->sector->extra_colormap->fadestart);
fadeend = APPLYFADE(d->dest_exc->fadeend, d->source_exc->fadeend, d->sector->extra_colormap->fadeend);
fog = abs(factor) > FRACUNIT/2 ? d->dest_exc->fog : d->source_exc->fog; // set new fog flag halfway through fade
flags = abs(factor) > FRACUNIT/2 ? d->dest_exc->flags : d->source_exc->flags; // set new flags halfway through fade
#undef APPLYFADE
@ -8521,12 +8528,12 @@ void T_FadeColormap(fadecolormap_t *d)
// setup new colormap
//////////////////
if (!(d->sector->extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog)))
if (!(d->sector->extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags)))
{
exc = R_CreateDefaultColormap(false);
exc->fadestart = fadestart;
exc->fadeend = fadeend;
exc->fog = (boolean)fog;
exc->flags = flags;
exc->rgba = rgba;
exc->fadergba = fadergba;
exc->colormap = R_CreateLightTable(exc);

View file

@ -590,10 +590,24 @@ void P_Ticker(boolean run)
{
INT32 i;
//Increment jointime even if paused.
// Increment jointime and quittime even if paused
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
++players[i].jointime;
{
players[i].jointime++;
if (players[i].quittime)
{
players[i].quittime++;
if (players[i].quittime == 30 * TICRATE && G_TagGametype())
P_CheckSurvivors();
if (server && players[i].quittime >= (tic_t)FixedMul(cv_rejointimeout.value, 60 * TICRATE)
&& !(players[i].quittime % TICRATE))
SendKick(i, KICK_MSG_PLAYER_QUIT);
}
}
if (objectplacing)
{

View file

@ -370,6 +370,33 @@ void P_GiveEmerald(boolean spawnObj)
}
}
//
// P_GiveFinishFlags
//
// Give the player visual indicators
// that they've finished the map.
//
void P_GiveFinishFlags(player_t *player)
{
angle_t angle = FixedAngle(player->mo->angle << FRACBITS);
UINT8 i;
if (!player->mo)
return;
for (i = 0; i < 3; i++)
{
angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t xoffs = FINECOSINE(fa);
fixed_t yoffs = FINESINE(fa);
mobj_t* flag = P_SpawnMobjFromMobj(player->mo, xoffs, yoffs, 0, MT_FINISHFLAG);
flag->angle = angle;
angle += FixedAngle(120*FRACUNIT);
P_SetTarget(&flag->target, player->mo);
}
}
#if 0
//
// P_ResetScore
@ -2171,6 +2198,7 @@ void P_DoPlayerFinish(player_t *player)
return;
player->pflags |= PF_FINISHED;
P_GiveFinishFlags(player);
if (netgame)
CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);
@ -2380,6 +2408,8 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
}
}
}
else if (player->charability == CA_GLIDEANDCLIMB && (player->mo->state-states == S_PLAY_GLIDE_LANDING))
;
else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
;
else if (player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH)
@ -3160,7 +3190,7 @@ static void P_DoClimbing(player_t *player)
platx = P_ReturnThrustX(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
platy = P_ReturnThrustY(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
glidesector = R_IsPointInSubsector(player->mo->x + platx, player->mo->y + platy);
glidesector = R_PointInSubsectorOrNull(player->mo->x + platx, player->mo->y + platy);
{
boolean floorclimb = false;
@ -4537,16 +4567,14 @@ void P_DoJump(player_t *player, boolean soundandstate)
player->mo->z--;
if (player->mo->pmomz < 0)
player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump.
else
player->mo->pmomz = 0;
player->mo->pmomz = 0;
}
else
{
player->mo->z++;
if (player->mo->pmomz > 0)
player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump.
else
player->mo->pmomz = 0;
player->mo->pmomz = 0;
}
player->mo->eflags &= ~MFE_APPLYPMOMZ;
@ -5503,10 +5531,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
; // Can't do anything if you're a fish out of water!
else if (player->powers[pw_tailsfly]) // If currently flying, give an ascend boost.
{
if (!player->fly1)
player->fly1 = 20;
else
player->fly1 = 2;
player->fly1 = 20;
if (player->charability == CA_SWIM)
player->fly1 /= 2;
@ -7439,6 +7464,8 @@ static void P_NiGHTSMovement(player_t *player)
else // AngleFixed(R_PointToAngle2()) results in slight inaccuracy! Don't use it unless movement is on both axises.
newangle = (INT16)FixedInt(AngleFixed(R_PointToAngle2(0,0, cmd->sidemove*FRACUNIT, cmd->forwardmove*FRACUNIT)));
newangle -= player->viewrollangle / ANG1;
if (newangle < 0 && moved)
newangle = (INT16)(360+newangle);
}
@ -8487,7 +8514,11 @@ static void P_MovePlayer(player_t *player)
// Descend
if (cmd->buttons & BT_USE && !(player->pflags & PF_STASIS) && !player->exiting && !(player->mo->eflags & MFE_GOOWATER))
if (P_MobjFlip(player->mo)*player->mo->momz > -FixedMul(5*actionspd, player->mo->scale))
{
if (player->fly1 > 2)
player->fly1 = 2;
P_SetObjectMomZ(player->mo, -actionspd/2, true);
}
}
else
@ -10235,7 +10266,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
}
// move camera down to move under lower ceilings
newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1));
newsubsec = R_PointInSubsectorOrNull(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1));
if (!newsubsec)
newsubsec = thiscam->subsector;
@ -11043,10 +11074,21 @@ static void P_MinecartThink(player_t *player)
if (angdiff + minecart->angle != player->mo->angle && (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG))
{
angle_t *ang = NULL;
if (player == &players[consoleplayer])
localangle = player->mo->angle;
ang = &localangle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
ang = &localangle2;
if (ang)
{
angdiff = *ang - minecart->angle;
if (angdiff < ANGLE_180 && angdiff > MINECARTCONEMAX)
*ang = minecart->angle + MINECARTCONEMAX;
else if (angdiff > ANGLE_180 && angdiff < InvAngle(MINECARTCONEMAX))
*ang = minecart->angle - MINECARTCONEMAX;
}
}
}
@ -11756,6 +11798,8 @@ void P_PlayerThink(player_t *player)
{
if (!playeringame[i] || players[i].spectator || players[i].bot)
continue;
if (players[i].quittime > 30 * TICRATE)
continue;
if (players[i].lives <= 0)
continue;
@ -12160,7 +12204,9 @@ void P_PlayerThink(player_t *player)
#ifdef POLYOBJECTS
if (player->onconveyor == 1)
player->cmomy = player->cmomx = 0;
player->onconveyor = 3;
else if (player->onconveyor == 3)
player->cmomy = player->cmomx = 0;
#endif
P_DoSuperStuff(player);
@ -12208,6 +12254,11 @@ void P_PlayerThink(player_t *player)
player->pflags &= ~PF_USEDOWN;
}
// IF PLAYER NOT HERE THEN FLASH END IF
if (player->quittime && player->powers[pw_flashing] < flashingtics - 1
&& !(G_TagGametype() && !(player->pflags & PF_TAGIT)) && !player->gotflag)
player->powers[pw_flashing] = flashingtics - 1;
// Counters, time dependent power ups.
// Time Bonus & Ring Bonus count settings
@ -12251,12 +12302,12 @@ void P_PlayerThink(player_t *player)
else
player->powers[pw_underwater] = 0;
}
else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && (player->spectator || player->quittime))) // underwater timer
player->powers[pw_underwater]--;
if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER)))
player->powers[pw_spacetime] = 0;
else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && (player->spectator || player->quittime))) // underwater timer
player->powers[pw_spacetime]--;
if (player->powers[pw_gravityboots] && player->powers[pw_gravityboots] < UINT16_MAX)

View file

@ -1799,7 +1799,7 @@ extracolormap_t *R_CreateDefaultColormap(boolean lighttable)
extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL);
exc->fadestart = 0;
exc->fadeend = 31;
exc->fog = 0;
exc->flags = 0;
exc->rgba = 0;
exc->fadergba = 0x19000000;
exc->colormap = lighttable ? R_CreateLightTable(exc) : NULL;
@ -1903,17 +1903,17 @@ void R_AddColormapToList(extracolormap_t *extra_colormap)
//
#ifdef EXTRACOLORMAPLUMPS
boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump)
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags, lumpnum_t lump)
#else
boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog)
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags)
#endif
{
return (
(!checkparams ? true :
(fadestart == 0
&& fadeend == 31
&& !fog)
&& !flags)
)
&& (!checkrgba ? true : rgba == 0)
&& (!checkfadergba ? true : fadergba == 0x19000000)
@ -1930,9 +1930,9 @@ boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgb
return true;
#ifdef EXTRACOLORMAPLUMPS
return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump);
return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->flags, extra_colormap->lump);
#else
return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog);
return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->flags);
#endif
}
@ -1952,7 +1952,7 @@ boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, bo
(!checkparams ? true :
(exc_a->fadestart == exc_b->fadestart
&& exc_a->fadeend == exc_b->fadeend
&& exc_a->fog == exc_b->fog)
&& exc_a->flags == exc_b->flags)
)
&& (!checkrgba ? true : exc_a->rgba == exc_b->rgba)
&& (!checkfadergba ? true : exc_a->fadergba == exc_b->fadergba)
@ -1968,9 +1968,9 @@ boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, bo
// NOTE: Returns NULL if no match is found
//
#ifdef EXTRACOLORMAPLUMPS
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump)
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags, lumpnum_t lump)
#else
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog)
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags)
#endif
{
extracolormap_t *exc;
@ -1982,7 +1982,7 @@ extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8
&& fadergba == exc->fadergba
&& fadestart == exc->fadestart
&& fadeend == exc->fadeend
&& fog == exc->fog
&& flags == exc->flags
#ifdef EXTRACOLORMAPLUMPS
&& (lump != LUMPERROR && lump == exc->lump)
#endif
@ -2001,9 +2001,9 @@ extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8
extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap)
{
#ifdef EXTRACOLORMAPLUMPS
return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog, extra_colormap->lump);
return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->flags, extra_colormap->lump);
#else
return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->fog);
return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->flags);
#endif
}
@ -2035,7 +2035,7 @@ extracolormap_t *R_ColormapForName(char *name)
// is no real way to tell how GL should handle a colormap lump anyway..
exc->fadestart = 0;
exc->fadeend = 31;
exc->fog = 0;
exc->flags = 0;
exc->rgba = 0;
exc->fadergba = 0x19000000;
@ -2192,7 +2192,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
// default values
UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25;
UINT32 fadestart = 0, fadeend = 31;
UINT8 fog = 0;
UINT8 flags = 0;
INT32 rgba = 0, fadergba = 0x19000000;
#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
@ -2241,12 +2241,12 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0)
// Get parameters like fadestart, fadeend, and the fogflag
// Get parameters like fadestart, fadeend, and flags
if (p2[0] == '#')
{
if (p2[1])
{
fog = NUMFROMCHAR(p2[1]);
flags = NUMFROMCHAR(p2[1]);
if (p2[2] && p2[3])
{
fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
@ -2313,18 +2313,18 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
// Did we just make a default colormap?
#ifdef EXTRACOLORMAPLUMPS
if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog, LUMPERROR))
if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, flags, LUMPERROR))
return NULL;
#else
if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, fog))
if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, flags))
return NULL;
#endif
// Look for existing colormaps
#ifdef EXTRACOLORMAPLUMPS
exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog, LUMPERROR);
exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags, LUMPERROR);
#else
exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, fog);
exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags);
#endif
if (exc)
return exc;
@ -2336,7 +2336,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
extra_colormap->fadestart = (UINT16)fadestart;
extra_colormap->fadeend = (UINT16)fadeend;
extra_colormap->fog = fog;
extra_colormap->flags = flags;
extra_colormap->rgba = rgba;
extra_colormap->fadergba = fadergba;
@ -2363,7 +2363,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3)
extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
boolean subR, boolean subG, boolean subB, boolean subA,
boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog,
boolean subFadeStart, boolean subFadeEnd, boolean ignoreFlags,
boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
boolean lighttable)
{
@ -2451,8 +2451,8 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
// HACK: fadeend defaults to 31, so don't add anything in this case
, 31), 0);
if (!ignoreFog) // overwrite fog with new value
exc_augend->fog = exc_addend->fog;
if (!ignoreFlags) // overwrite flags with new value
exc_augend->flags = exc_addend->flags;
///////////////////
// put it together
@ -2465,16 +2465,20 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
// Thanks to quake2 source!
// utils3/qdata/images.c
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette)
{
int dr, dg, db;
int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i;
// Use master palette if none specified
if (palette == NULL)
palette = pMasterPalette;
for (i = 0; i < 256; i++)
{
dr = r - pMasterPalette[i].s.red;
dg = g - pMasterPalette[i].s.green;
db = b - pMasterPalette[i].s.blue;
dr = r - palette[i].s.red;
dg = g - palette[i].s.green;
db = b - palette[i].s.blue;
distortion = dr*dr + dg*dg + db*db;
if (distortion < bestdistortion)
{

View file

@ -135,12 +135,12 @@ void R_AddColormapToList(extracolormap_t *extra_colormap);
#ifdef EXTRACOLORMAPLUMPS
boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump);
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog, lumpnum_t lump);
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags, lumpnum_t lump);
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags, lumpnum_t lump);
#else
boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams,
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog);
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 fog);
INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags);
extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags);
#endif
boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams);
boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams);
@ -151,7 +151,7 @@ extracolormap_t *R_CreateColormap(char *p1, char *p2, char *p3);
extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend,
boolean subR, boolean subG, boolean subB, boolean subA,
boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA,
boolean subFadeStart, boolean subFadeEnd, boolean ignoreFog,
boolean subFadeStart, boolean subFadeEnd, boolean ignoreFlags,
boolean useAltAlpha, INT16 altAlpha, INT16 altFadeAlpha,
boolean lighttable);
#ifdef EXTRACOLORMAPLUMPS
@ -171,7 +171,8 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap);
#define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b))
#define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a))
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette);
#define NearestColor(r, g, b) NearestPaletteColor(r, g, b, NULL)
extern INT32 numtextures;

View file

@ -53,11 +53,14 @@ typedef struct
// Could even use more than 32 levels.
typedef UINT8 lighttable_t;
#define CMF_FADEFULLBRIGHTSPRITES 1
#define CMF_FOG 4
// ExtraColormap type. Use for extra_colormaps from now on.
typedef struct extracolormap_s
{
UINT8 fadestart, fadeend;
UINT8 fog; // categorical value, not boolean
UINT8 flags;
// store rgba values in combined bitwise
// also used in OpenGL instead lighttables

View file

@ -153,9 +153,11 @@ const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
// Desaturated
{0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, // SKINCOLOR_AETHER
{0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, // SKINCOLOR_SLATE
{0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, // SKINCOLOR_BLUEBELL
{0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, // SKINCOLOR_PINK
{0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, // SKINCOLOR_YOGURT
{0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, // SKINCOLOR_BROWN
{0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, // SKINCOLOR_BRONZE
{0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, // SKINCOLOR_TAN
{0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, // SKINCOLOR_BEIGE
{0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, // SKINCOLOR_MOSS
@ -168,9 +170,11 @@ const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, // SKINCOLOR_RED
{0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, // SKINCOLOR_CRIMSON
{0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, // SKINCOLOR_FLAME
{0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, // SKINCOLOR_KETCHUP
{0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, // SKINCOLOR_PEACHY
{0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, // SKINCOLOR_QUAIL
{0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, // SKINCOLOR_SUNSET
{0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, // SKINCOLOR_COPPER
{0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, // SKINCOLOR_APRICOT
{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, // SKINCOLOR_ORANGE
{0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, // SKINCOLOR_RUST
@ -180,6 +184,7 @@ const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
{0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, // SKINCOLOR_OLIVE
{0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, // SKINCOLOR_LIME
{0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, // SKINCOLOR_PERIDOT
{0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, // SKINCOLOR_APPLE
{0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, // SKINCOLOR_GREEN
{0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, // SKINCOLOR_FOREST
{0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, // SKINCOLOR_EMERALD
@ -206,6 +211,7 @@ const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
{0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, // SKINCOLOR_VIOLET
{0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, // SKINCOLOR_LILAC
{0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, // SKINCOLOR_PLUM
{0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, // SKINCOLOR_RASPBERRY
{0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, // SKINCOLOR_ROSY
// {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_?
@ -285,9 +291,11 @@ const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS] =
// Desaturated
"Aether", // SKINCOLOR_AETHER,
"Slate", // SKINCOLOR_SLATE,
"Bluebell", // SKINCOLOR_BLUEBELL,
"Pink", // SKINCOLOR_PINK,
"Yogurt", // SKINCOLOR_YOGURT,
"Brown", // SKINCOLOR_BROWN,
"Brown", // SKINCOLOR_BROWN,
"Bronze", // SKINCOLOR_BRONZE,
"Tan", // SKINCOLOR_TAN,
"Beige", // SKINCOLOR_BEIGE,
"Moss", // SKINCOLOR_MOSS,
@ -300,9 +308,11 @@ const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS] =
"Red", // SKINCOLOR_RED,
"Crimson", // SKINCOLOR_CRIMSON,
"Flame", // SKINCOLOR_FLAME,
"Ketchup", // SKINCOLOR_KETCHUP,
"Peachy", // SKINCOLOR_PEACHY,
"Quail", // SKINCOLOR_QUAIL,
"Sunset", // SKINCOLOR_SUNSET,
"Copper", // SKINCOLOR_COPPER,
"Apricot", // SKINCOLOR_APRICOT,
"Orange", // SKINCOLOR_ORANGE,
"Rust", // SKINCOLOR_RUST,
@ -312,6 +322,7 @@ const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS] =
"Olive", // SKINCOLOR_OLIVE,
"Lime", // SKINCOLOR_LIME,
"Peridot", // SKINCOLOR_PERIDOT,
"Apple", // SKINCOLOR_APPLE,
"Green", // SKINCOLOR_GREEN,
"Forest", // SKINCOLOR_FOREST,
"Emerald", // SKINCOLOR_EMERALD,
@ -338,6 +349,7 @@ const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS] =
"Violet", // SKINCOLOR_VIOLET,
"Lilac", // SKINCOLOR_LILAC,
"Plum", // SKINCOLOR_PLUM,
"Raspberry", // SKINCOLOR_RASPBERRY,
"Rosy", // SKINCOLOR_ROSY,
// Super behaves by different rules (one name per 5 colours), and will be accessed exclusively via R_GetSuperColorByName instead of R_GetColorByName.
@ -375,9 +387,11 @@ const UINT8 Color_Opposite[MAXSKINCOLORS - 1][2] =
// Desaturated
{SKINCOLOR_GREY, 15}, // SKINCOLOR_AETHER,
{SKINCOLOR_SILVER, 12}, // SKINCOLOR_SLATE,
{SKINCOLOR_COPPER, 4}, // SKINCOLOR_BLUEBELL,
{SKINCOLOR_AZURE, 9}, // SKINCOLOR_PINK,
{SKINCOLOR_RUST, 7}, // SKINCOLOR_YOGURT,
{SKINCOLOR_TAN, 2}, // SKINCOLOR_BROWN,
{SKINCOLOR_KETCHUP, 0}, // SKINCOLOR_BRONZE,
{SKINCOLOR_BROWN, 12}, // SKINCOLOR_TAN,
{SKINCOLOR_MOSS, 5}, // SKINCOLOR_BEIGE,
{SKINCOLOR_BEIGE, 13}, // SKINCOLOR_MOSS,
@ -390,9 +404,11 @@ const UINT8 Color_Opposite[MAXSKINCOLORS - 1][2] =
{SKINCOLOR_GREEN, 10}, // SKINCOLOR_RED,
{SKINCOLOR_ICY, 10}, // SKINCOLOR_CRIMSON,
{SKINCOLOR_PURPLE, 8}, // SKINCOLOR_FLAME,
{SKINCOLOR_BRONZE, 8}, // SKINCOLOR_KETCHUP,
{SKINCOLOR_TEAL, 7}, // SKINCOLOR_PEACHY,
{SKINCOLOR_WAVE, 5}, // SKINCOLOR_QUAIL,
{SKINCOLOR_SAPPHIRE, 5}, // SKINCOLOR_SUNSET,
{SKINCOLOR_BLUEBELL, 5}, // SKINCOLOR_COPPER
{SKINCOLOR_CYAN, 4}, // SKINCOLOR_APRICOT,
{SKINCOLOR_BLUE, 4}, // SKINCOLOR_ORANGE,
{SKINCOLOR_YOGURT, 8}, // SKINCOLOR_RUST,
@ -402,6 +418,7 @@ const UINT8 Color_Opposite[MAXSKINCOLORS - 1][2] =
{SKINCOLOR_DUSK, 3}, // SKINCOLOR_OLIVE,
{SKINCOLOR_MAGENTA, 9}, // SKINCOLOR_LIME,
{SKINCOLOR_COBALT, 2}, // SKINCOLOR_PERIDOT,
{SKINCOLOR_RASPBERRY, 13}, // SKINCOLOR_APPLE,
{SKINCOLOR_RED, 6}, // SKINCOLOR_GREEN,
{SKINCOLOR_SALMON, 9}, // SKINCOLOR_FOREST,
{SKINCOLOR_RUBY, 4}, // SKINCOLOR_EMERALD,
@ -428,6 +445,7 @@ const UINT8 Color_Opposite[MAXSKINCOLORS - 1][2] =
{SKINCOLOR_MINT, 6}, // SKINCOLOR_VIOLET,
{SKINCOLOR_VAPOR, 4}, // SKINCOLOR_LILAC,
{SKINCOLOR_MINT, 7}, // SKINCOLOR_PLUM,
{SKINCOLOR_APPLE, 13}, // SKINCOLOR_RASPBERRY
{SKINCOLOR_AQUA, 1} // SKINCOLOR_ROSY,
};

View file

@ -644,6 +644,7 @@ void R_CalcTiltedLighting(fixed_t start, fixed_t end)
}
}
#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
/** \brief The R_DrawTiltedSpan_8 function
Draw slopes! Holy sheit!
@ -669,7 +670,7 @@ void R_DrawTiltedSpan_8(void)
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds_szp->x*width) * planelightfloat;
@ -805,7 +806,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds_szp->x*width) * planelightfloat;
@ -942,7 +943,7 @@ void R_DrawTiltedTranslucentWaterSpan_8(void)
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds_szp->x*width) * planelightfloat;
@ -1078,7 +1079,7 @@ void R_DrawTiltedSplat_8(void)
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds_szp->x*width) * planelightfloat;

View file

@ -62,6 +62,9 @@ void R_DrawSpan_NPO2_8 (void)
}
#ifdef ESLOPE
#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
/** \brief The R_DrawTiltedSpan_NPO2_8 function
Draw slopes! Holy sheit!
*/
@ -86,7 +89,7 @@ void R_DrawTiltedSpan_NPO2_8(void)
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds_szp->x*width) * planelightfloat;
@ -282,7 +285,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void)
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds_szp->x*width) * planelightfloat;
@ -476,7 +479,7 @@ void R_DrawTiltedSplat_NPO2_8(void)
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds_szp->x*width) * planelightfloat;
@ -869,7 +872,7 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void)
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds_szp->x*width) * planelightfloat;

View file

@ -71,6 +71,7 @@ angle_t viewangle, aimingangle;
fixed_t viewcos, viewsin;
sector_t *viewsector;
player_t *viewplayer;
mobj_t *r_viewmobj;
//
// precalculated math tables
@ -546,6 +547,303 @@ static inline void R_InitLightTables(void)
}
}
//#define WOUGHMP_WOUGHMP // I got a fish-eye lens - I'll make a rap video with a couple of friends
// it's kinda laggy sometimes
static struct {
angle_t rollangle; // pre-shifted by fineshift
#ifdef WOUGHMP_WOUGHMP
fixed_t fisheye;
#endif
fixed_t zoomneeded;
INT32 *scrmap;
INT32 scrmapsize;
INT32 x1; // clip rendering horizontally for efficiency
INT16 ceilingclip[MAXVIDWIDTH], floorclip[MAXVIDWIDTH];
boolean use;
} viewmorph = {
0,
#ifdef WOUGHMP_WOUGHMP
0,
#endif
FRACUNIT,
NULL,
0,
0,
{}, {},
false
};
void R_CheckViewMorph(void)
{
float zoomfactor, rollcos, rollsin;
float x1, y1, x2, y2;
fixed_t temp;
INT32 end, vx, vy, pos, usedpos;
INT32 usedx, usedy, halfwidth = vid.width/2, halfheight = vid.height/2;
#ifdef WOUGHMP_WOUGHMP
float fisheyemap[MAXVIDWIDTH/2 + 1];
#endif
angle_t rollangle = players[displayplayer].viewrollangle;
#ifdef WOUGHMP_WOUGHMP
fixed_t fisheye = cv_cam2_turnmultiplier.value; // temporary test value
#endif
rollangle >>= ANGLETOFINESHIFT;
rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot.
#ifdef WOUGHMP_WOUGHMP
fisheye &= ~0x7FF; // Same
#endif
if (rollangle == viewmorph.rollangle &&
#ifdef WOUGHMP_WOUGHMP
fisheye == viewmorph.fisheye &&
#endif
viewmorph.scrmapsize == vid.width*vid.height)
return; // No change
viewmorph.rollangle = rollangle;
#ifdef WOUGHMP_WOUGHMP
viewmorph.fisheye = fisheye;
#endif
if (viewmorph.rollangle == 0
#ifdef WOUGHMP_WOUGHMP
&& viewmorph.fisheye == 0
#endif
)
{
viewmorph.use = false;
viewmorph.x1 = 0;
if (viewmorph.zoomneeded != FRACUNIT)
R_SetViewSize();
viewmorph.zoomneeded = FRACUNIT;
return;
}
if (viewmorph.scrmapsize != vid.width*vid.height)
{
if (viewmorph.scrmap)
free(viewmorph.scrmap);
viewmorph.scrmap = malloc(vid.width*vid.height * sizeof(INT32));
viewmorph.scrmapsize = vid.width*vid.height;
}
temp = FINECOSINE(rollangle);
rollcos = FIXED_TO_FLOAT(temp);
temp = FINESINE(rollangle);
rollsin = FIXED_TO_FLOAT(temp);
// Calculate maximum zoom needed
x1 = (vid.width*fabsf(rollcos) + vid.height*fabsf(rollsin)) / vid.width;
y1 = (vid.height*fabsf(rollcos) + vid.width*fabsf(rollsin)) / vid.height;
#ifdef WOUGHMP_WOUGHMP
if (fisheye)
{
float f = FIXED_TO_FLOAT(fisheye);
for (vx = 0; vx <= halfwidth; vx++)
fisheyemap[vx] = 1.0f / cos(atan(vx * f / halfwidth));
f = cos(atan(f));
if (f < 1.0f)
{
x1 /= f;
y1 /= f;
}
}
#endif
temp = max(x1, y1)*FRACUNIT;
if (temp < FRACUNIT)
temp = FRACUNIT;
else
temp |= 0x3FFF; // Limit how many times the viewport needs to be recalculated
//CONS_Printf("Setting zoom to %f\n", FIXED_TO_FLOAT(temp));
if (temp != viewmorph.zoomneeded)
{
viewmorph.zoomneeded = temp;
R_SetViewSize();
}
zoomfactor = FIXED_TO_FLOAT(viewmorph.zoomneeded);
end = vid.width * vid.height - 1;
pos = 0;
// Pre-multiply rollcos and rollsin to use for positional stuff
rollcos /= zoomfactor;
rollsin /= zoomfactor;
x1 = -(halfwidth * rollcos - halfheight * rollsin);
y1 = -(halfheight * rollcos + halfwidth * rollsin);
#ifdef WOUGHMP_WOUGHMP
if (fisheye)
viewmorph.x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin)) * fisheyemap[halfwidth]);
else
#endif
viewmorph.x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin)));
//CONS_Printf("saving %d cols\n", viewmorph.x1);
// Set ceilingclip and floorclip
for (vx = 0; vx < vid.width; vx++)
{
viewmorph.ceilingclip[vx] = vid.height;
viewmorph.floorclip[vx] = -1;
}
x2 = x1;
y2 = y1;
for (vx = 0; vx < vid.width; vx++)
{
INT16 xa, ya, xb, yb;
xa = x2+halfwidth;
ya = y2+halfheight-1;
xb = vid.width-1-xa;
yb = vid.height-1-ya;
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
x2 += rollcos;
y2 += rollsin;
}
x2 = x1;
y2 = y1;
for (vy = 0; vy < vid.height; vy++)
{
INT16 xa, ya, xb, yb;
xa = x2+halfwidth;
ya = y2+halfheight;
xb = vid.width-1-xa;
yb = vid.height-1-ya;
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
x2 -= rollsin;
y2 += rollcos;
}
//CONS_Printf("Top left corner is %f %f\n", x1, y1);
#ifdef WOUGHMP_WOUGHMP
if (fisheye)
{
for (vy = 0; vy < halfheight; vy++)
{
x2 = x1;
y2 = y1;
x1 -= rollsin;
y1 += rollcos;
for (vx = 0; vx < vid.width; vx++)
{
usedx = halfwidth + x2*fisheyemap[(int) floorf(fabsf(y2*zoomfactor))];
usedy = halfheight + y2*fisheyemap[(int) floorf(fabsf(x2*zoomfactor))];
usedpos = usedx + usedy*vid.width;
viewmorph.scrmap[pos] = usedpos;
viewmorph.scrmap[end-pos] = end-usedpos;
x2 += rollcos;
y2 += rollsin;
pos++;
}
}
}
else
{
#endif
x1 += halfwidth;
y1 += halfheight;
for (vy = 0; vy < halfheight; vy++)
{
x2 = x1;
y2 = y1;
x1 -= rollsin;
y1 += rollcos;
for (vx = 0; vx < vid.width; vx++)
{
usedx = x2;
usedy = y2;
usedpos = usedx + usedy*vid.width;
viewmorph.scrmap[pos] = usedpos;
viewmorph.scrmap[end-pos] = end-usedpos;
x2 += rollcos;
y2 += rollsin;
pos++;
}
}
#ifdef WOUGHMP_WOUGHMP
}
#endif
viewmorph.use = true;
}
void R_ApplyViewMorph(void)
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
INT32 p, end = vid.width * vid.height;
if (!viewmorph.use)
return;
if (cv_debug & DBG_VIEWMORPH)
{
UINT8 border = 32;
UINT8 grid = 160;
INT32 ws = vid.width / 4;
INT32 hs = vid.width * (vid.height / 4);
memcpy(tmpscr, srcscr, vid.width*vid.height);
for (p = 0; p < vid.width; p++)
{
tmpscr[viewmorph.scrmap[p]] = border;
tmpscr[viewmorph.scrmap[p + hs]] = grid;
tmpscr[viewmorph.scrmap[p + hs*2]] = grid;
tmpscr[viewmorph.scrmap[p + hs*3]] = grid;
tmpscr[viewmorph.scrmap[end - 1 - p]] = border;
}
for (p = vid.width; p < end; p += vid.width)
{
tmpscr[viewmorph.scrmap[p]] = border;
tmpscr[viewmorph.scrmap[p + ws]] = grid;
tmpscr[viewmorph.scrmap[p + ws*2]] = grid;
tmpscr[viewmorph.scrmap[p + ws*3]] = grid;
tmpscr[viewmorph.scrmap[end - 1 - p]] = border;
}
}
else
for (p = 0; p < end; p++)
tmpscr[p] = srcscr[viewmorph.scrmap[p]];
VID_BlitLinearScreen(tmpscr, screens[0],
vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width);
}
//
// R_SetViewSize
@ -594,7 +892,7 @@ void R_ExecuteSetViewSize(void)
centeryfrac = centery<<FRACBITS;
fov = FixedAngle(cv_fov.value/2) + ANGLE_90;
fovtan = FINETANGENT(fov >> ANGLETOFINESHIFT);
fovtan = FixedMul(FINETANGENT(fov >> ANGLETOFINESHIFT), viewmorph.zoomneeded);
if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view
fovtan = 17*fovtan/10;
@ -701,9 +999,9 @@ subsector_t *R_PointInSubsector(fixed_t x, fixed_t y)
}
//
// R_IsPointInSubsector, same as above but returns 0 if not in subsector
// R_PointInSubsectorOrNull, same as above but returns 0 if not in subsector
//
subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y)
{
node_t *node;
INT32 side, i;
@ -742,10 +1040,8 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
// R_SetupFrame
//
static mobj_t *viewmobj;
// WARNING: a should be unsigned but to add with 2048, it isn't!
#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS, fovtan)
#define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)/fovtan)
// recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight).
@ -800,16 +1096,16 @@ void R_SetupFrame(player_t *player)
if (player->awayviewtics)
{
// cut-away view stuff
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
I_Assert(viewmobj != NULL);
viewz = viewmobj->z + 20*FRACUNIT;
r_viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
I_Assert(r_viewmobj != NULL);
viewz = r_viewmobj->z + 20*FRACUNIT;
aimingangle = player->awayviewaiming;
viewangle = viewmobj->angle;
viewangle = r_viewmobj->angle;
}
else if (!player->spectator && chasecam)
// use outside cam view
{
viewmobj = NULL;
r_viewmobj = NULL;
viewz = thiscam->z + (thiscam->height>>1);
aimingangle = thiscam->aiming;
viewangle = thiscam->angle;
@ -819,11 +1115,11 @@ void R_SetupFrame(player_t *player)
{
viewz = player->viewz;
viewmobj = player->mo;
I_Assert(viewmobj != NULL);
r_viewmobj = player->mo;
I_Assert(r_viewmobj != NULL);
aimingangle = player->aiming;
viewangle = viewmobj->angle;
viewangle = r_viewmobj->angle;
if (!demoplayback && player->playerstate != PST_DEAD)
{
@ -857,13 +1153,13 @@ void R_SetupFrame(player_t *player)
}
else
{
viewx = viewmobj->x;
viewy = viewmobj->y;
viewx = r_viewmobj->x;
viewy = r_viewmobj->y;
viewx += quake.x;
viewy += quake.y;
if (viewmobj->subsector)
viewsector = viewmobj->subsector->sector;
if (r_viewmobj->subsector)
viewsector = r_viewmobj->subsector->sector;
else
viewsector = R_PointInSubsector(viewx, viewy)->sector;
}
@ -885,12 +1181,12 @@ void R_SkyboxFrame(player_t *player)
thiscam = &camera;
// cut-away view stuff
viewmobj = skyboxmo[0];
r_viewmobj = skyboxmo[0];
#ifdef PARANOIA
if (!viewmobj)
if (!r_viewmobj)
{
const size_t playeri = (size_t)(player - players);
I_Error("R_SkyboxFrame: viewmobj null (player %s)", sizeu1(playeri));
I_Error("R_SkyboxFrame: r_viewmobj null (player %s)", sizeu1(playeri));
}
#endif
if (player->awayviewtics)
@ -921,13 +1217,13 @@ void R_SkyboxFrame(player_t *player)
}
}
}
viewangle += viewmobj->angle;
viewangle += r_viewmobj->angle;
viewplayer = player;
viewx = viewmobj->x;
viewy = viewmobj->y;
viewz = viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle!
viewx = r_viewmobj->x;
viewy = r_viewmobj->y;
viewz = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle!
if (mapheaderinfo[gamemap-1])
{
@ -967,29 +1263,29 @@ void R_SkyboxFrame(player_t *player)
else if (mh->skybox_scaley < 0)
y = (campos.y - skyboxmo[1]->y) * -mh->skybox_scaley;
if (viewmobj->angle == 0)
if (r_viewmobj->angle == 0)
{
viewx += x;
viewy += y;
}
else if (viewmobj->angle == ANGLE_90)
else if (r_viewmobj->angle == ANGLE_90)
{
viewx -= y;
viewy += x;
}
else if (viewmobj->angle == ANGLE_180)
else if (r_viewmobj->angle == ANGLE_180)
{
viewx -= x;
viewy -= y;
}
else if (viewmobj->angle == ANGLE_270)
else if (r_viewmobj->angle == ANGLE_270)
{
viewx += y;
viewy -= x;
}
else
{
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
angle_t ang = r_viewmobj->angle>>ANGLETOFINESHIFT;
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
}
@ -1000,8 +1296,8 @@ void R_SkyboxFrame(player_t *player)
viewz += campos.z * -mh->skybox_scalez;
}
if (viewmobj->subsector)
viewsector = viewmobj->subsector->sector;
if (r_viewmobj->subsector)
viewsector = r_viewmobj->subsector->sector;
else
viewsector = R_PointInSubsector(viewx, viewy)->sector;
@ -1082,9 +1378,22 @@ void R_RenderPlayerView(player_t *player)
validcount++;
// Clear buffers.
R_ClearClipSegs();
R_ClearDrawSegs();
R_ClearPlanes();
if (viewmorph.use)
{
portalclipstart = viewmorph.x1;
portalclipend = viewwidth-viewmorph.x1-1;
R_PortalClearClipSegs(portalclipstart, portalclipend);
memcpy(ceilingclip, viewmorph.ceilingclip, sizeof(INT16)*vid.width);
memcpy(floorclip, viewmorph.floorclip, sizeof(INT16)*vid.width);
}
else
{
portalclipstart = 0;
portalclipend = viewwidth-1;
R_ClearClipSegs();
}
R_ClearDrawSegs();
R_ClearSprites();
#ifdef FLOORSPLATS
R_ClearVisibleFloorSplats();

View file

@ -26,6 +26,7 @@ extern INT32 centerx, centery;
extern fixed_t centerxfrac, centeryfrac;
extern fixed_t projection, projectiony;
extern fixed_t fovtan; // field of view
extern size_t validcount, linecount, loopcount, framecount;
@ -45,6 +46,8 @@ extern size_t validcount, linecount, loopcount, framecount;
#define MAXLIGHTZ 128
#define LIGHTZSHIFT 20
#define LIGHTRESOLUTIONFIX (640*fovtan/vid.width)
extern lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
extern lighttable_t *scalelightfixed[MAXLIGHTSCALE];
extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
@ -64,7 +67,7 @@ fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
fixed_t R_ScaleFromGlobalAngle(angle_t visangle);
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y);
subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y);
boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph);
@ -91,6 +94,9 @@ void R_InitHardwareMode(void);
#endif
void R_ReloadHUDGraphics(void);
void R_CheckViewMorph(void);
void R_ApplyViewMorph(void);
// just sets setsizeneeded true
extern boolean setsizeneeded;
void R_SetViewSize(void);

View file

@ -1196,7 +1196,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
INT32 angle;
patch_t *patch;
patch_t *newpatch;
UINT16 *rawsrc, *rawdst;
UINT16 *rawdst;
size_t size;
INT32 bflip = (flip != 0x00);
@ -1212,14 +1212,23 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
INT32 width, height, leftoffset;
fixed_t ca, sa;
lumpnum_t lump = sprframe->lumppat[rot];
size_t lumplength;
if (lump == LUMPERROR)
return;
patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC);
lumplength = W_LumpLength(lump);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)patch, lumplength))
patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL);
else
#endif
// Because there's something wrong with SPR_DFLM, I guess
if (!R_CheckIfPatch(lump))
return;
patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC);
width = patch->width;
height = patch->height;
leftoffset = patch->leftoffset;
@ -1242,16 +1251,6 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
leftoffset = width - leftoffset;
}
// Draw the sprite to a temporary buffer.
size = (width*height);
rawsrc = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL);
// can't memset here
for (i = 0; i < size; i++)
rawsrc[i] = 0xFF00;
R_PatchToMaskedFlat(patch, rawsrc, bflip);
// Don't cache angle = 0
for (angle = 1; angle < ROTANGLES; angle++)
{

View file

@ -44,9 +44,6 @@
// Quincunx antialiasing of flats!
//#define QUINCUNX
// good night sweet prince
#define SHITPLANESPARENCY
//SoM: 3/23/2000: Use Boom visplane hashing.
visplane_t *visplanes[MAXVISPLANES];
@ -995,11 +992,7 @@ void R_DrawSinglePlane(visplane_t *pl)
else // Opaque, but allow transparent flat pixels
spanfunctype = SPANDRAWFUNC_SPLAT;
#ifdef SHITPLANESPARENCY
if ((spanfunctype == SPANDRAWFUNC_SPLAT) != (pl->extra_colormap && (pl->extra_colormap->fog & 4)))
#else
if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2))
#endif
if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
light = (pl->lightlevel >> LIGHTSEGSHIFT);
else
light = LIGHTLEVELS-1;
@ -1053,11 +1046,7 @@ void R_DrawSinglePlane(visplane_t *pl)
else // Opaque, but allow transparent flat pixels
spanfunctype = SPANDRAWFUNC_SPLAT;
#ifdef SHITPLANESPARENCY
if ((spanfunctype == SPANDRAWFUNC_SPLAT) != (pl->extra_colormap && (pl->extra_colormap->fog & 4)))
#else
if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2))
#endif
if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
light = (pl->lightlevel >> LIGHTSEGSHIFT);
else
light = LIGHTLEVELS-1;

View file

@ -199,7 +199,7 @@ static void R_DrawWallSplats(void)
// draw the columns
for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw_scalestep)
{
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
dc_colormap = walllights[pindex];
@ -418,14 +418,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
rlight->extra_colormap = *light->extra_colormap;
rlight->flags = light->flags;
if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (rlight->flags & FF_FOG)
|| (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
lightnum = LIGHTLEVELS - 1;
else
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
lightnum = LIGHTLEVELS - 1;
if (rlight->extra_colormap && rlight->extra_colormap->fog)
if (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))
;
else if (curline->v1->y == curline->v2->y)
lightnum--;
@ -437,18 +437,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
}
else
{
if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
{
if (frontsector->extra_colormap && frontsector->extra_colormap->fog)
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
else
lightnum = LIGHTLEVELS - 1;
}
else
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
else
lightnum = LIGHTLEVELS - 1;
if (colfunc == colfuncs[COLDRAWFUNC_FOG]
|| (frontsector->extra_colormap && frontsector->extra_colormap->fog))
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
;
else if (curline->v1->y == curline->v2->y)
lightnum--;
@ -599,7 +595,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
else
xwalllights = scalelight[rlight->lightnum];
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
@ -644,7 +640,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
}
// calculate lighting
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
@ -947,7 +943,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else
rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog))
if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
;
else if (curline->v1->y == curline->v2->y)
rlight->lightnum--;
@ -962,7 +958,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else
{
// Get correct light level!
if ((frontsector->extra_colormap && frontsector->extra_colormap->fog))
if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
else if (pfloor->flags & FF_FOG)
lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
@ -972,7 +968,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)
->lightlevel >> LIGHTSEGSHIFT;
if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && frontsector->extra_colormap->fog));
if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)));
else if (curline->v1->y == curline->v2->y)
lightnum--;
else if (curline->v1->x == curline->v2->x)
@ -1188,7 +1184,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
@ -1281,7 +1277,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
}
// calculate lighting
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
@ -1486,7 +1482,7 @@ static void R_RenderSegLoop (void)
if (segtextured)
{
// calculate lighting
pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
pindex = FixedMul(rw_scale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
@ -1521,7 +1517,7 @@ static void R_RenderSegLoop (void)
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
pindex = FixedMul(rw_scale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;

View file

@ -76,5 +76,5 @@ void R_SetupSkyDraw(void)
void R_SetSkyScale(void)
{
fixed_t difference = vid.fdupx-(vid.dupx<<FRACBITS);
skyscale = FixedDiv(FRACUNIT, vid.fdupx+difference);
skyscale = FixedDiv(fovtan, vid.fdupx+difference);
}

View file

@ -86,6 +86,7 @@ extern fixed_t viewx, viewy, viewz;
extern angle_t viewangle, aimingangle;
extern sector_t *viewsector;
extern player_t *viewplayer;
extern mobj_t *r_viewmobj;
extern consvar_t cv_allowmlook;
extern consvar_t cv_maxportals;

View file

@ -1094,10 +1094,10 @@ static void R_SplitSprite(vissprite_t *sprite)
newsprite->extra_colormap = *sector->lightlist[i].extra_colormap;
if (!((newsprite->cut & SC_FULLBRIGHT)
&& (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1))))
if (!(newsprite->cut & SC_FULLBRIGHT)
|| (newsprite->extra_colormap && (newsprite->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES)))
{
lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT);
lindex = FixedMul(sprite->xscale, LIGHTRESOLUTIONFIX)>>(LIGHTSCALESHIFT);
if (lindex >= MAXLIGHTSCALE)
lindex = MAXLIGHTSCALE-1;
@ -1307,17 +1307,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
shadow->mobj = thing; // Easy access! Tails 06-07-2002
shadow->x1 = x1 < 0 ? 0 : x1;
shadow->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
// PORTAL SEMI-CLIPPING
if (portalrender)
{
if (shadow->x1 < portalclipstart)
shadow->x1 = portalclipstart;
if (shadow->x2 >= portalclipend)
shadow->x2 = portalclipend-1;
}
shadow->x1 = x1 < portalclipstart ? portalclipstart : x1;
shadow->x2 = x2 >= portalclipend ? portalclipend-1 : x2;
shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000
shadow->scale = FixedMul(yscale, shadowyscale);
@ -1695,7 +1686,7 @@ static void R_ProjectSprite(mobj_t *thing)
thing = thing->tracer;
if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW)
if (! R_ThingVisible(thing))
return;
tr_x = thing->x - viewx;
@ -1815,17 +1806,8 @@ static void R_ProjectSprite(mobj_t *thing)
vis->mobj = thing; // Easy access! Tails 06-07-2002
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
// PORTAL SEMI-CLIPPING
if (portalrender)
{
if (vis->x1 < portalclipstart)
vis->x1 = portalclipstart;
if (vis->x2 >= portalclipend)
vis->x2 = portalclipend-1;
}
vis->x1 = x1 < portalclipstart ? portalclipstart : x1;
vis->x2 = x2 >= portalclipend ? portalclipend-1 : x2;
vis->xscale = xscale; //SoM: 4/17/2000
vis->sector = thing->subsector->sector;
@ -1882,7 +1864,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->cut |= SC_FULLBRIGHT;
if (vis->cut & SC_FULLBRIGHT
&& (!vis->extra_colormap || !(vis->extra_colormap->fog & 1)))
&& (!vis->extra_colormap || !(vis->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES)))
{
// full bright: goggles
vis->colormap = colormaps;
@ -1890,7 +1872,7 @@ static void R_ProjectSprite(mobj_t *thing)
else
{
// diminished light
lindex = FixedMul(xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT);
lindex = FixedMul(xscale, LIGHTRESOLUTIONFIX)>>(LIGHTSCALESHIFT);
if (lindex >= MAXLIGHTSCALE)
lindex = MAXLIGHTSCALE-1;
@ -2034,17 +2016,8 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->shear.tan = 0;
vis->shear.offset = 0;
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
// PORTAL SEMI-CLIPPING
if (portalrender)
{
if (vis->x1 < portalclipstart)
vis->x1 = portalclipstart;
if (vis->x2 >= portalclipend)
vis->x2 = portalclipend-1;
}
vis->x1 = x1 < portalclipstart ? portalclipstart : x1;
vis->x2 = x2 >= portalclipend ? portalclipend-1 : x2;
vis->xscale = xscale; //SoM: 4/17/2000
vis->sector = thing->subsector->sector;
@ -2098,7 +2071,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
mobj_t *thing;
precipmobj_t *precipthing; // Tails 08-25-2002
INT32 lightnum;
fixed_t approx_dist, limit_dist, hoop_limit_dist;
fixed_t limit_dist, hoop_limit_dist;
if (rendermode != render_soft)
return;
@ -2131,35 +2104,10 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
// If a limit exists, handle things a tiny bit different.
limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS;
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS;
if (limit_dist || hoop_limit_dist)
for (thing = sec->thinglist; thing; thing = thing->snext)
{
for (thing = sec->thinglist; thing; thing = thing->snext)
{
if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW)
continue;
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
if (thing->sprite == SPR_HOOP)
{
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
continue;
}
else
{
if (limit_dist && approx_dist > limit_dist)
continue;
}
if (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist))
R_ProjectSprite(thing);
}
}
else
{
// Draw everything in sector, no checks
for (thing = sec->thinglist; thing; thing = thing->snext)
if (!(thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW))
R_ProjectSprite(thing);
}
// no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
@ -2167,15 +2115,8 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
{
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
{
if (precipthing->precipflags & PCF_INVISIBLE)
continue;
approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y);
if (approx_dist > limit_dist)
continue;
R_ProjectPrecipitationSprite(precipthing);
if (R_PrecipThingVisible(precipthing, limit_dist))
R_ProjectPrecipitationSprite(precipthing);
}
}
}
@ -2877,6 +2818,55 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
}
}
/* Check if thing may be drawn from our current view. */
boolean R_ThingVisible (mobj_t *thing)
{
return (!(
thing->sprite == SPR_NULL ||
( thing->flags2 & (MF2_DONTDRAW) ) ||
thing == r_viewmobj
));
}
boolean R_ThingVisibleWithinDist (mobj_t *thing,
fixed_t limit_dist,
fixed_t hoop_limit_dist)
{
fixed_t approx_dist;
if (! R_ThingVisible(thing))
return false;
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
if (thing->sprite == SPR_HOOP)
{
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
return false;
}
else
{
if (limit_dist && approx_dist > limit_dist)
return false;
}
return true;
}
/* Check if precipitation may be drawn from our current view. */
boolean R_PrecipThingVisible (precipmobj_t *precipthing,
fixed_t limit_dist)
{
fixed_t approx_dist;
if (( precipthing->precipflags & PCF_INVISIBLE ))
return false;
approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y);
return ( approx_dist <= limit_dist );
}
//
// R_DrawMasked
//
@ -3446,6 +3436,7 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
GETFLAG(DASHMODE)
GETFLAG(FASTEDGE)
GETFLAG(MULTIABILITY)
GETFLAG(NONIGHTSROTATION)
#undef GETFLAG
else // let's check if it's a sound, otherwise error out

View file

@ -59,6 +59,15 @@ void R_InitSprites(void);
void R_ClearSprites(void);
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
boolean R_ThingVisible (mobj_t *thing);
boolean R_ThingVisibleWithinDist (mobj_t *thing,
fixed_t draw_dist,
fixed_t nights_draw_dist);
boolean R_PrecipThingVisible (precipmobj_t *precipthing,
fixed_t precip_draw_dist);
/** Used to count the amount of masked elements
* per portal to later group them in separate
* drawnode lists.

View file

@ -1441,6 +1441,12 @@ static tic_t pause_starttic;
/// Music Definitions
/// ------------------------
enum
{
MUSICDEF_220,
MUSICDEF_221,
};
musicdef_t soundtestsfx = {
"_STSFX", // prevents exactly one valid track name from being used on the sound test
"Sound Effects",
@ -1472,188 +1478,164 @@ static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid)
return INT16_MAX; // not found
}
void S_LoadMusicDefs(UINT16 wadnum)
static void
MusicDefStrcpy (char *p, const char *s, size_t n, int version)
{
UINT16 lumpnum;
char *lump, *buf;
char *musdeftext;
char *stoken;
strlcpy(p, s, n);
if (version == MUSICDEF_220)
{
while (( p = strchr(p, '_') ))
*p++ = ' '; // turn _ into spaces.
}
}
static boolean
ReadMusicDefFields (UINT16 wadnum, int line, boolean fields, char *stoken,
musicdef_t **defp, int *versionp)
{
musicdef_t *def;
int version;
char *value;
char *textline;
size_t size;
INT32 i;
musicdef_t *def = NULL;
UINT16 line = 1; // for better error msgs
int i;
lumpnum = W_CheckForMusicDefInPwad(wadnum);
if (lumpnum == INT16_MAX)
return;
lump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
size = W_LumpLengthPwad(wadnum, lumpnum);
// Null-terminated MUSICDEF lump.
musdeftext = malloc(size+1);
if (!musdeftext)
I_Error("S_LoadMusicDefs: No more free memory for the parser\n");
M_Memcpy(musdeftext, lump, size);
musdeftext[size] = '\0';
// for strtok
buf = malloc(size+1);
if (!buf)
I_Error("S_LoadMusicDefs: No more free memory for the parser\n");
M_Memcpy(buf, musdeftext, size+1);
stoken = strtok(buf, "\r\n ");
// Find music def
while (stoken)
if (!stricmp(stoken, "lump"))
{
/*if ((stoken[0] == '/' && stoken[1] == '/')
|| (stoken[0] == '#')) // skip comments
value = strtok(NULL, " ");
if (!value)
{
stoken = strtok(NULL, "\r\n"); // skip end of line
if (def)
stoken = strtok(NULL, "\r\n= ");
else
stoken = strtok(NULL, "\r\n ");
line++;
}
else*/ if (!stricmp(stoken, "lump"))
{
value = strtok(NULL, "\r\n ");
if (!value)
{
CONS_Alert(CONS_WARNING, "MUSICDEF: Lump '%s' is missing name. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
stoken = strtok(NULL, "\r\n"); // skip end of line
goto skip_lump;
}
// No existing musicdefs
/*if (!musicdefstart)
{
musicdefstart = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL);
STRBUFCPY(musicdefstart->name, value);
strlwr(musicdefstart->name);
def = musicdefstart;
//CONS_Printf("S_LoadMusicDefs: Initialized musicdef w/ song '%s'\n", def->name);
}
else*/
{
musicdef_t *prev = NULL;
def = musicdefstart;
// Search if this is a replacement
//CONS_Printf("S_LoadMusicDefs: Searching for song replacement...\n");
while (def)
{
if (!stricmp(def->name, value))
{
//CONS_Printf("S_LoadMusicDefs: Found song replacement '%s'\n", def->name);
break;
}
prev = def;
def = def->next;
}
// Nothing found, add to the end.
if (!def)
{
def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL);
STRBUFCPY(def->name, value);
strlwr(def->name);
def->bpm = TICRATE<<(FRACBITS-1); // FixedDiv((60*TICRATE)<<FRACBITS, 120<<FRACBITS)
if (prev != NULL)
prev->next = def;
//CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name);
}
}
skip_lump:
stoken = strtok(NULL, "\r\n ");
line++;
CONS_Alert(CONS_WARNING,
"MUSICDEF: Field '%s' is missing name. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
return false;
}
else
{
// If this is set true, the line was invalid.
boolean brokenline = false;
musicdef_t *prev = NULL;
def = musicdefstart;
// Delimit only by line break.
value = strtok(NULL, "\r\n");
// Search if this is a replacement
//CONS_Printf("S_LoadMusicDefs: Searching for song replacement...\n");
while (def)
{
if (!stricmp(def->name, value))
{
//CONS_Printf("S_LoadMusicDefs: Found song replacement '%s'\n", def->name);
break;
}
// Find the equals sign.
value = strchr(value, '=');
prev = def;
def = def->next;
}
// It's not there?!
// Nothing found, add to the end.
if (!def)
{
def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL);
STRBUFCPY(def->name, value);
strlwr(def->name);
def->bpm = TICRATE<<(FRACBITS-1); // FixedDiv((60*TICRATE)<<FRACBITS, 120<<FRACBITS)
if (prev != NULL)
prev->next = def;
//CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name);
}
(*defp) = def;
}
}
else if (!stricmp(stoken, "version"))
{
if (fields)/* is this not the first field? */
{
CONS_Alert(CONS_WARNING,
"MUSICDEF: Field '%s' must come first. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
return false;
}
else
{
value = strtok(NULL, " ");
if (!value)
brokenline = true;
{
CONS_Alert(CONS_WARNING,
"MUSICDEF: Field '%s' is missing version. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
return false;
}
else
{
if (strcasecmp(value, "2.2.0"))
(*versionp) = MUSICDEF_221;
}
}
}
else
{
version = (*versionp);
if (version == MUSICDEF_220)
value = strtok(NULL, " =");
else
{
value = strtok(NULL, "");
if (value)
{
// Find the equals sign.
value = strchr(value, '=');
}
}
if (!value)
{
CONS_Alert(CONS_WARNING,
"MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
return false;
}
else
{
def = (*defp);
if (!def)
{
CONS_Alert(CONS_ERROR,
"MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
return false;
}
if (version != MUSICDEF_220)
{
// Skip the equals sign.
value++;
// Now skip funny whitespace.
if (value[0] == '\0') // :NOTHING:
brokenline = true;
else
value += strspn(value, "\t ");
value += strspn(value, "\t ");
}
// If the line is valid, copy the text line from the lump data.
if (!brokenline)
{
// strtok returns memory that already belongs to the input string.
value = musdeftext + (value - buf);
// Find the length of the line.
size = strcspn(value, "\r\n");
// Copy the line.
textline = malloc(size+1);
if (!textline)
I_Error("S_LoadMusicDefs: No more free memory for text line\n");
M_Memcpy(textline, value, size);
textline[size] = '\0';
}
else
{
CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
stoken = strtok(NULL, "\r\n"); // skip end of line
goto skip_field;
}
if (!def)
{
CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
free(textline);
free(buf);
free(musdeftext);
return;
}
i = atoi(textline);
textline = value;
i = atoi(value);
/* based ignored lumps */
if (!stricmp(stoken, "usage")) {
#if 0 // Ignore for now
STRBUFCPY(def->usage, textline);
//CONS_Printf("S_LoadMusicDefs: Set usage to '%s'\n", def->usage);
#endif
} else if (!stricmp(stoken, "source")) {
#if 0 // Ignore for now
STRBUFCPY(def->source, textline);
//CONS_Printf("S_LoadMusicDefs: Set source to '%s'\n", def->usage);
#endif
} else if (!stricmp(stoken, "title")) {
STRBUFCPY(def->title, textline);
//CONS_Printf("S_LoadMusicDefs: Set title to '%s'\n", def->source);
MusicDefStrcpy(def->title, textline,
sizeof def->title, version);
} else if (!stricmp(stoken, "alttitle")) {
STRBUFCPY(def->alttitle, textline);
//CONS_Printf("S_LoadMusicDefs: Set alttitle to '%s'\n", def->source);
MusicDefStrcpy(def->alttitle, textline,
sizeof def->alttitle, version);
} else if (!stricmp(stoken, "authors")) {
STRBUFCPY(def->authors, textline);
//CONS_Printf("S_LoadMusicDefs: Set authors to '%s'\n", def->source);
MusicDefStrcpy(def->authors, textline,
sizeof def->authors, version);
} else if (!stricmp(stoken, "soundtestpage")) {
def->soundtestpage = (UINT8)i;
} else if (!stricmp(stoken, "soundtestcond")) {
@ -1670,21 +1652,90 @@ skip_lump:
if (bpmf > 0)
def->bpm = FixedDiv((60*TICRATE)<<FRACBITS, bpmf);
} else {
CONS_Alert(CONS_WARNING, "MUSICDEF: Invalid field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
CONS_Alert(CONS_WARNING,
"MUSICDEF: Invalid field '%s'. (file %s, line %d)\n",
stoken, wadfiles[wadnum]->filename, line);
}
// Free the temporary text line from memory.
free(textline);
skip_field:
stoken = strtok(NULL, "\r\n= ");
line++;
}
}
free(buf);
return true;
}
void S_LoadMusicDefs(UINT16 wadnum)
{
UINT16 lumpnum;
char *lump;
char *musdeftext;
size_t size;
char *lf;
char *stoken;
size_t nlf;
size_t ncr;
musicdef_t *def = NULL;
int version = MUSICDEF_220;
int line = 1; // for better error msgs
boolean fields = false;
lumpnum = W_CheckForMusicDefInPwad(wadnum);
if (lumpnum == INT16_MAX)
return;
lump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
size = W_LumpLengthPwad(wadnum, lumpnum);
// Null-terminated MUSICDEF lump.
musdeftext = malloc(size+1);
if (!musdeftext)
I_Error("S_LoadMusicDefs: No more free memory for the parser\n");
M_Memcpy(musdeftext, lump, size);
musdeftext[size] = '\0';
// Find music def
stoken = musdeftext;
for (;;)
{
lf = strpbrk(stoken, "\r\n");
if (lf)
{
if (*lf == '\n')
nlf = 1;
else
nlf = 0;
*lf++ = '\0';/* now we can delimit to here */
}
stoken = strtok(stoken, " ");
if (stoken)
{
if (! ReadMusicDefFields(wadnum, line, fields, stoken,
&def, &version))
break;
fields = true;
}
if (lf)
{
do
{
line += nlf;
ncr = strspn(lf, "\r");/* skip CR */
lf += ncr;
nlf = strspn(lf, "\n");
lf += nlf;
}
while (nlf || ncr) ;
stoken = lf;/* now the next nonempty line */
}
else
break;/* EOF */
}
free(musdeftext);
return;
}
//

View file

@ -360,10 +360,13 @@ void SCR_Recalc(void)
vid.fsmalldupy = vid.smalldupy*FRACUNIT;
#endif
// toggle off automap because some screensize-dependent values will
// toggle off (then back on) the automap because some screensize-dependent values will
// be calculated next time the automap is activated.
if (automapactive)
AM_Stop();
{
am_recalc = true;
AM_Start();
}
// set the screen[x] ptrs on the new vidbuffers
V_Init();

View file

@ -110,7 +110,6 @@ static SDL_bool disable_fullscreen = SDL_FALSE;
#define USE_FULLSCREEN (disable_fullscreen||!allow_fullscreen)?0:cv_fullscreen.value
static SDL_bool disable_mouse = SDL_FALSE;
#define USE_MOUSEINPUT (!disable_mouse && cv_usemouse.value && havefocus)
#define IGNORE_MOUSE (!cv_alwaysgrabmouse.value && (menuactive || paused || con_destlines || chat_on || gamestate != GS_LEVEL))
#define MOUSE_MENU false //(!disable_mouse && cv_usemouse.value && menuactive && !USE_FULLSCREEN)
#define MOUSEBUTTONS_MAX MOUSEBUTTONS
@ -362,6 +361,17 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
return 0;
}
static boolean IgnoreMouse(void)
{
if (cv_alwaysgrabmouse.value)
return false;
if (menuactive)
return !M_MouseNeeded();
if (paused || con_destlines || chat_on || gamestate != GS_LEVEL)
return true;
return false;
}
static void SDLdoGrabMouse(void)
{
SDL_ShowCursor(SDL_DISABLE);
@ -388,7 +398,7 @@ void I_UpdateMouseGrab(void)
{
if (SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO && window != NULL
&& SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window
&& USE_MOUSEINPUT && !IGNORE_MOUSE)
&& USE_MOUSEINPUT && !IgnoreMouse())
SDLdoGrabMouse();
}
@ -596,7 +606,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
}
//else firsttimeonmouse = SDL_FALSE;
if (USE_MOUSEINPUT && !IGNORE_MOUSE)
if (USE_MOUSEINPUT && !IgnoreMouse())
SDLdoGrabMouse();
}
else if (!mousefocus && !kbfocus)
@ -647,7 +657,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
if (USE_MOUSEINPUT)
{
if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window) || (IGNORE_MOUSE && !firstmove))
if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window) || (IgnoreMouse() && !firstmove))
{
SDLdoUngrabMouse();
firstmove = false;
@ -700,7 +710,7 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
// this apparently makes a mouse button down event but not a mouse button up event,
// resulting in whatever key was pressed down getting "stuck" if we don't ignore it.
// -- Monster Iestyn (28/05/18)
if (SDL_GetMouseFocus() != window || IGNORE_MOUSE)
if (SDL_GetMouseFocus() != window || IgnoreMouse())
return;
/// \todo inputEvent.button.which
@ -1082,7 +1092,7 @@ void I_StartupMouse(void)
}
else
firsttimeonmouse = SDL_FALSE;
if (cv_usemouse.value && !IGNORE_MOUSE)
if (cv_usemouse.value && !IgnoreMouse())
SDLdoGrabMouse();
else
SDLdoUngrabMouse();
@ -1489,7 +1499,6 @@ void VID_CheckRenderer(void)
{
I_StartupHardwareGraphics();
R_InitHardwareMode();
HWR_Switch();
}
#endif
}

View file

@ -1219,7 +1219,7 @@
C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.2.0;
CURRENT_PROJECT_VERSION = 2.2.1;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
NORMALSRB2,
@ -1231,7 +1231,7 @@
C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.2.0;
CURRENT_PROJECT_VERSION = 2.2.1;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (

View file

@ -128,6 +128,7 @@ static patch_t *minus5sec;
static patch_t *minicaps;
static patch_t *gotrflag;
static patch_t *gotbflag;
static patch_t *fnshico;
static boolean facefreed[MAXPLAYERS];
@ -310,6 +311,7 @@ void ST_LoadGraphics(void)
bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX);
gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX);
gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX);
fnshico = W_CachePatchName("FNSHICO", PU_HUDGFX);
nonicon = W_CachePatchName("NONICON", PU_HUDGFX);
nonicon2 = W_CachePatchName("NONICON2", PU_HUDGFX);
@ -944,7 +946,7 @@ static void ST_drawLivesArea(void)
'\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false);
else
{
if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)))
if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)) && !(stplyr->pflags & PF_FINISHED))
livescount++;
if (livescount > 99)
livescount = 99;
@ -1278,13 +1280,15 @@ void ST_preDrawTitleCard(void)
//
void ST_runTitleCard(void)
{
boolean run = !(paused || P_AutoPause());
if (!G_IsTitleCardAvailable())
return;
if (lt_ticker >= (lt_endtime + TICRATE))
return;
if (!(paused || P_AutoPause()))
if (run || (lt_ticker < PRELEVELTIME))
{
// tick
lt_ticker++;
@ -1432,7 +1436,7 @@ static void ST_drawPowerupHUD(void)
UINT16 invulntime = 0;
INT32 offs = hudinfo[HUD_POWERUPS].x;
const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
static INT32 flagoffs[2] = {0, 0}, shieldoffs[2] = {0, 0};
static INT32 flagoffs[2] = {0, 0}, shieldoffs[2] = {0, 0}, finishoffs[2] = {0, 0};
#define ICONSEP (16+4) // matches weapon rings HUD
if (F_GetPromptHideHud(hudinfo[HUD_POWERUPS].y))
@ -1440,6 +1444,26 @@ static void ST_drawPowerupHUD(void)
if (stplyr->spectator || stplyr->playerstate != PST_LIVE)
return;
// ---------
// Finish icon
// ---------
// Let's have a power-like icon to represent finishing the level!
if (stplyr->pflags & PF_FINISHED && cv_exitmove.value)
{
finishoffs[q] = ICONSEP;
V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, fnshico);
}
else if (finishoffs[q])
{
if (finishoffs[q] > 1)
finishoffs[q] = 2*finishoffs[q]/3;
else
finishoffs[q] = 0;
}
offs -= finishoffs[q];
// -------
// Shields
@ -2623,7 +2647,7 @@ static void ST_overlayDrawer(void)
// Check for a valid level title
// If the HUD is enabled
// And, if Lua is running, if the HUD library has the stage title enabled
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) && *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer)))
if (G_IsTitleCardAvailable() && *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer)))
{
stagetitle = true;
ST_preDrawTitleCard();

View file

@ -3244,7 +3244,6 @@ Unoptimized version
#endif
}
// Taken from my videos-in-SRB2 project
// Generates a color look-up table
// which has up to 64 colors at each channel
// (see the defines in v_video.h)
@ -3261,7 +3260,7 @@ void InitColorLUT(RGBA_t *palette)
for (r = 0; r < CLUTSIZE; r++)
for (g = 0; g < CLUTSIZE; g++)
for (b = 0; b < CLUTSIZE; b++)
colorlookup[r][g][b] = NearestColor(r << SHIFTCOLORBITS, g << SHIFTCOLORBITS, b << SHIFTCOLORBITS);
colorlookup[r][g][b] = NearestPaletteColor(r << SHIFTCOLORBITS, g << SHIFTCOLORBITS, b << SHIFTCOLORBITS, palette);
clutinit = true;
lastpalette = palette;
}

View file

@ -37,10 +37,7 @@ cv_allcaps;
// Allocates buffer screens, call before R_Init.
void V_Init(void);
// Taken from my videos-in-SRB2 project
// Generates a color look-up table
// which has up to 64 colors at each channel
// Color look-up table
#define COLORBITS 6
#define SHIFTCOLORBITS (8-COLORBITS)
#define CLUTSIZE (1<<COLORBITS)

View file

@ -637,6 +637,21 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
return lumpinfo;
}
static UINT16 W_InitFileError (const char *filename, boolean exitworthy)
{
if (exitworthy)
{
#ifdef _DEBUG
CONS_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n");
#else
I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n");
#endif
}
else
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), filename);
return INT16_MAX;
}
// Allocate a wadfile, setup the lumpinfo (directory) and
// lumpcache, add the wadfile to the current active wadfiles
//
@ -648,7 +663,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
//
// Can now load dehacked files (.soc)
//
UINT16 W_InitFile(const char *filename, boolean mainfile)
UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
{
FILE *handle;
lumpinfo_t *lumpinfo = NULL;
@ -681,12 +696,12 @@ UINT16 W_InitFile(const char *filename, boolean mainfile)
{
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
refreshdirmenu |= REFRESHDIR_MAX;
return INT16_MAX;
return W_InitFileError(filename, startup);
}
// open wad file
if ((handle = W_OpenWadFile(&filename, true)) == NULL)
return INT16_MAX;
return W_InitFileError(filename, startup);
// Check if wad files will overflow fileneededbuffer. Only the filename part
// is send in the packet; cf.
@ -701,7 +716,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile)
refreshdirmenu |= REFRESHDIR_MAX;
if (handle)
fclose(handle);
return INT16_MAX;
return W_InitFileError(filename, startup);
}
packetsizetally = packetsize;
@ -722,7 +737,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile)
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
if (handle)
fclose(handle);
return INT16_MAX;
return W_InitFileError(filename, false);
}
}
#endif
@ -750,7 +765,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile)
if (lumpinfo == NULL)
{
fclose(handle);
return INT16_MAX;
return W_InitFileError(filename, startup);
}
//
@ -822,13 +837,9 @@ UINT16 W_InitFile(const char *filename, boolean mainfile)
* backwards, so a later file overrides all earlier ones.
*
* \param filenames A null-terminated list of files to use.
* \return 1 if all files were loaded, 0 if at least one was missing or
* invalid.
*/
INT32 W_InitMultipleFiles(char **filenames, UINT16 mainfiles)
void W_InitMultipleFiles(char **filenames, UINT16 mainfiles)
{
INT32 rc = 1;
// open all the files, load headers, and count lumps
numwadfiles = 0;
@ -836,13 +847,8 @@ INT32 W_InitMultipleFiles(char **filenames, UINT16 mainfiles)
for (; *filenames; filenames++)
{
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
rc &= (W_InitFile(*filenames, numwadfiles < mainfiles) != INT16_MAX) ? 1 : 0;
W_InitFile(*filenames, numwadfiles < mainfiles, true);
}
if (!numwadfiles)
I_Error("W_InitMultipleFiles: no files found");
return rc;
}
/** Make sure a lump number is valid.
@ -1691,7 +1697,7 @@ W_VerifyName (const char *name, lumpchecklist_t *checklist, boolean status)
size_t j;
for (j = 0; checklist[j].len && checklist[j].name; ++j)
{
if (( strncmp(name, checklist[j].name,
if (( strncasecmp(name, checklist[j].name,
checklist[j].len) != false ) == status)
{
return true;
@ -1746,6 +1752,19 @@ W_VerifyWAD (FILE *fp, lumpchecklist_t *checklist, boolean status)
return true;
}
// List of blacklisted folders to use when checking the PK3
static lumpchecklist_t folderblacklist[] =
{
{"Lua/", 4},
{"SOC/", 4},
{"Sprites/", 8},
{"Textures/", 9},
{"Patches/", 8},
{"Flats/", 6},
{"Fades/", 6},
{NULL, 0},
};
static int
W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
{
@ -1797,7 +1816,7 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
else
trimname = fullname; // Care taken for root files.
if (*trimname) // Ignore directories
if (*trimname) // Ignore directories, well kinda
{
if ((dotpos = strrchr(trimname, '.')) == 0)
dotpos = fullname + strlen(fullname); // Watch for files without extension.
@ -1807,6 +1826,10 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
if (! W_VerifyName(lumpname, checklist, status))
return false;
// Check for directories next, if it's blacklisted it will return false
if (W_VerifyName(fullname, folderblacklist, status))
return false;
}
free(fullname);

View file

@ -146,11 +146,10 @@ void W_Shutdown(void);
// Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened
FILE *W_OpenWadFile(const char **filename, boolean useerrors);
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
UINT16 W_InitFile(const char *filename, boolean mainfile);
UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup);
// W_InitMultipleFiles returns 1 if all is okay, 0 otherwise,
// so that it stops with a message if a file was not found, but not if all is okay.
INT32 W_InitMultipleFiles(char **filenames, UINT16 mainfiles);
// W_InitMultipleFiles exits if a file was not found, but not if all is okay.
void W_InitMultipleFiles(char **filenames, UINT16 mainfiles);
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
const char *W_CheckNameForNum(lumpnum_t lumpnum);

View file

@ -232,12 +232,12 @@ void Z_Free(void *ptr)
// Free the memory and get rid of the block.
free(block->real);
block->prev->next = block->next;
block->next->prev = block->prev;
free(block);
#ifdef VALGRIND_DESTROY_MEMPOOL
VALGRIND_DESTROY_MEMPOOL(block);
#endif
block->prev->next = block->next;
block->next->prev = block->prev;
free(block);
}
/** malloc() that doesn't accept failure.
@ -317,13 +317,9 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
// The mem header lives 'sizeof (memhdr_t)' bytes before given.
hdr = (memhdr_t *)((UINT8 *)given - sizeof *hdr);
#ifdef VALGRIND_CREATE_MEMPOOL
VALGRIND_CREATE_MEMPOOL(block, padsize, Z_calloc);
#ifdef HAVE_VALGRIND
Z_calloc = false;
#endif
#ifdef VALGRIND_MEMPOOL_ALLOC
VALGRIND_MEMPOOL_ALLOC(block, hdr, size + sizeof *hdr);
#endif
block->next = head.next;
block->prev = &head;
@ -341,6 +337,13 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
block->size = blocksize;
block->realsize = size;
#ifdef VALGRIND_CREATE_MEMPOOL
VALGRIND_CREATE_MEMPOOL(block, padsize, Z_calloc);
#endif
//#ifdef VALGRIND_MEMPOOL_ALLOC
// VALGRIND_MEMPOOL_ALLOC(block, hdr, size + sizeof *hdr);
//#endif
hdr->id = ZONEID;
hdr->block = block;