Merge remote-tracking branch 'upstream/master' into viewroll

This commit is contained in:
fickleheart 2020-02-16 21:32:57 -06:00
commit c4b390bc76
45 changed files with 685 additions and 441 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. # DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
# Version change is fine. # Version change is fine.
project(SRB2 project(SRB2
VERSION 2.2.0 VERSION 2.2.1
LANGUAGES C) LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) 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 os: MinGW
environment: environment:

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_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 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 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 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) 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); typedef void (*AMDRAWFLINEFUNC) (const fline_t *fl, INT32 color);
static AMDRAWFLINEFUNC AM_drawFline; 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_drawFline_soft(const fline_t *fl, INT32 color);
static void AM_activateNewScale(void) static void AM_activateNewScale(void)
@ -344,22 +346,22 @@ static void AM_initVariables(void)
old_m_h = m_h; 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 // should be called at the start of every level
// right now, i figure it out myself // right now, i figure it out myself
// //
static void AM_LevelInit(void) 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(); AM_findMinMaxBoundaries();
scale_mtof = FixedDiv(min_scale_mtof*10, 7*FRACUNIT); scale_mtof = FixedDiv(min_scale_mtof*10, 7*FRACUNIT);
if (scale_mtof > max_scale_mtof) if (scale_mtof > max_scale_mtof)
@ -381,7 +383,7 @@ void AM_Stop(void)
* *
* \sa AM_Stop * \sa AM_Stop
*/ */
static inline void AM_Start(void) void AM_Start(void)
{ {
static INT32 lastlevel = -1; static INT32 lastlevel = -1;
@ -390,8 +392,12 @@ static inline void AM_Start(void)
am_stopped = false; am_stopped = false;
if (lastlevel != gamemap || am_recalc) // screen size changed if (lastlevel != gamemap || am_recalc) // screen size changed
{ {
AM_LevelInit(); AM_FrameBufferInit();
lastlevel = gamemap; if (lastlevel != gamemap)
{
AM_LevelInit();
lastlevel = gamemap;
}
am_recalc = false; am_recalc = false;
} }
AM_initVariables(); AM_initVariables();
@ -417,6 +423,28 @@ static void AM_maxOutWindowScale(void)
AM_activateNewScale(); 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. /** Responds to user inputs in automap mode.
* *
* \param ev Event to possibly respond to. * \param ev Event to possibly respond to.
@ -449,35 +477,49 @@ boolean AM_Responder(event_t *ev)
{ {
case AM_PANRIGHTKEY: // pan right case AM_PANRIGHTKEY: // pan right
if (!followplayer) if (!followplayer)
m_paninc.x = FTOM(F_PANINC); {
m_keydown[0] = true;
AM_setWindowPanning();
}
else else
rc = false; rc = false;
break; break;
case AM_PANLEFTKEY: // pan left case AM_PANLEFTKEY: // pan left
if (!followplayer) if (!followplayer)
m_paninc.x = -FTOM(F_PANINC); {
m_keydown[1] = true;
AM_setWindowPanning();
}
else else
rc = false; rc = false;
break; break;
case AM_PANUPKEY: // pan up case AM_PANUPKEY: // pan up
if (!followplayer) if (!followplayer)
m_paninc.y = FTOM(F_PANINC); {
m_keydown[2] = true;
AM_setWindowPanning();
}
else else
rc = false; rc = false;
break; break;
case AM_PANDOWNKEY: // pan down case AM_PANDOWNKEY: // pan down
if (!followplayer) if (!followplayer)
m_paninc.y = -FTOM(F_PANINC); {
m_keydown[3] = true;
AM_setWindowPanning();
}
else else
rc = false; rc = false;
break; break;
case AM_ZOOMOUTKEY: // zoom out case AM_ZOOMOUTKEY: // zoom out
mtof_zoommul = M_ZOOMOUT; mtof_zoommul = M_ZOOMOUT;
ftom_zoommul = M_ZOOMIN; ftom_zoommul = M_ZOOMIN;
AM_setWindowPanning();
break; break;
case AM_ZOOMINKEY: // zoom in case AM_ZOOMINKEY: // zoom in
mtof_zoommul = M_ZOOMIN; mtof_zoommul = M_ZOOMIN;
ftom_zoommul = M_ZOOMOUT; ftom_zoommul = M_ZOOMOUT;
AM_setWindowPanning();
break; break;
case AM_TOGGLEKEY: case AM_TOGGLEKEY:
AM_Stop(); AM_Stop();
@ -491,6 +533,7 @@ boolean AM_Responder(event_t *ev)
} }
else else
AM_restoreScaleAndLoc(); AM_restoreScaleAndLoc();
AM_setWindowPanning();
break; break;
case AM_FOLLOWKEY: case AM_FOLLOWKEY:
followplayer = !followplayer; followplayer = !followplayer;
@ -510,14 +553,32 @@ boolean AM_Responder(event_t *ev)
switch (ev->data1) switch (ev->data1)
{ {
case AM_PANRIGHTKEY: case AM_PANRIGHTKEY:
if (!followplayer)
{
m_keydown[0] = false;
AM_setWindowPanning();
}
break;
case AM_PANLEFTKEY: case AM_PANLEFTKEY:
if (!followplayer) if (!followplayer)
m_paninc.x = 0; {
m_keydown[1] = false;
AM_setWindowPanning();
}
break; break;
case AM_PANUPKEY: case AM_PANUPKEY:
if (!followplayer)
{
m_keydown[2] = false;
AM_setWindowPanning();
}
break;
case AM_PANDOWNKEY: case AM_PANDOWNKEY:
if (!followplayer) if (!followplayer)
m_paninc.y = 0; {
m_keydown[3] = false;
AM_setWindowPanning();
}
break; break;
case AM_ZOOMOUTKEY: case AM_ZOOMOUTKEY:
case AM_ZOOMINKEY: case AM_ZOOMINKEY:
@ -718,6 +779,17 @@ static boolean AM_clipMline(const mline_t *ml, fline_t *fl)
} }
#undef DOOUTCODE #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 // Classic Bresenham w/ whatever optimizations needed for speed
// //
@ -739,8 +811,6 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
} }
#endif #endif
#define PUTDOT(xx,yy,cc) V_DrawFill(xx,yy,1,1,cc|V_NOSCALESTART);
dx = fl->b.x - fl->a.x; dx = fl->b.x - fl->a.x;
ax = 2 * (dx < 0 ? -dx : dx); ax = 2 * (dx < 0 ? -dx : dx);
sx = dx < 0 ? -1 : 1; sx = dx < 0 ? -1 : 1;
@ -757,7 +827,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d = ay - ax/2; d = ay - ax/2;
for (;;) for (;;)
{ {
PUTDOT(x, y, color) AM_drawPixel(x, y, color);
if (x == fl->b.x) if (x == fl->b.x)
return; return;
if (d >= 0) if (d >= 0)
@ -774,7 +844,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d = ax - ay/2; d = ax - ay/2;
for (;;) for (;;)
{ {
PUTDOT(x, y, color) AM_drawPixel(x, y, color);
if (y == fl->b.y) if (y == fl->b.y)
return; return;
if (d >= 0) if (d >= 0)
@ -786,8 +856,6 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d += ax; d += ax;
} }
} }
#undef PUTDOT
} }
// //
@ -1100,6 +1168,12 @@ void AM_Drawer(void)
if (!automapactive) if (!automapactive)
return; return;
AM_drawFline = AM_drawFline_soft;
#ifdef HWRENDER
if (rendermode == render_opengl)
AM_drawFline = HWR_drawAMline;
#endif
AM_clearFB(BACKGROUND); AM_clearFB(BACKGROUND);
if (draw_grid) AM_drawGrid(GRIDCOLORS); if (draw_grid) AM_drawGrid(GRIDCOLORS);
AM_drawWalls(); AM_drawWalls();

View File

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

View File

@ -26,12 +26,12 @@
#else #else
/* Manually defined asset hashes for non-CMake builds /* 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 * Last updated 20?? / ?? / ?? - v2.2.? - patch.pk3
*/ */
#define ASSET_HASH_SRB2_PK3 "51419a33b4982d840c6772c159ba7c0a" #define ASSET_HASH_SRB2_PK3 "0277c9416756627004e83cbb5b2e3e28"
#define ASSET_HASH_ZONES_PK3 "df74843919fd51af26a0baa8e21e4c19" #define ASSET_HASH_ZONES_PK3 "f7e88afb6af7996a834c7d663144bead"
#define ASSET_HASH_PLAYER_DTA "56a247e074dd0dc794b6617efef1e918" #define ASSET_HASH_PLAYER_DTA "ad49e07b17cc662f1ad70c454910b4ae"
#ifdef USE_PATCH_DTA #ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_PK3 "there is no patch.pk3, only zuul" #define ASSET_HASH_PATCH_PK3 "there is no patch.pk3, only zuul"
#endif #endif

View File

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

View File

@ -404,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 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, // 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 need to put the commands in it // because if you need to resend a PT_SERVERTICS packet, you will need to put the commands in it
if (client) if (client)
D_FreeTextcmd(gametic); D_FreeTextcmd(gametic);
} }
@ -1278,8 +1278,14 @@ static boolean CL_SendJoin(void)
netbuffer->u.clientcfg.subversion = SUBVERSION; netbuffer->u.clientcfg.subversion = SUBVERSION;
strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION, strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION,
sizeof netbuffer->u.clientcfg.application); 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[0], cv_playername.zstring, MAXPLAYERNAME);
strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME);
return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
} }
@ -4504,7 +4510,7 @@ static void CL_SendClientCmd(void)
packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16);
HSendPacket(servernode, false, 0, packetsize); HSendPacket(servernode, false, 0, packetsize);
} }
else if (gamestate != GS_NULL && addedtogame) else if (gamestate != GS_NULL && (addedtogame || dedicated))
{ {
G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1);
netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]);
@ -4678,6 +4684,7 @@ static void Local_Maketic(INT32 realtics)
G_BuildTiccmd(&localcmds2, realtics, 2); G_BuildTiccmd(&localcmds2, realtics, 2);
localcmds.angleturn |= TICCMD_RECEIVED; localcmds.angleturn |= TICCMD_RECEIVED;
localcmds2.angleturn |= TICCMD_RECEIVED;
} }
// This function is utter bullshit and is responsible for // This function is utter bullshit and is responsible for

View File

@ -188,14 +188,14 @@ void D_ProcessEvents(void)
continue; continue;
} }
// console input
if (CON_Responder(ev))
continue; // ate the event
// Menu input // Menu input
if (M_Responder(ev)) if (M_Responder(ev))
continue; // menu ate the event continue; // menu ate the event
// console input
if (CON_Responder(ev))
continue; // ate the event
G_Responder(ev); G_Responder(ev);
} }
} }
@ -508,12 +508,13 @@ static void D_Display(void)
// vid size change is now finished if it was on... // vid size change is now finished if it was on...
vid.recalc = 0; vid.recalc = 0;
M_Drawer(); // menu is drawn even on top of everything // FIXME: draw either console or menu, not the two
// focus lost moved to M_Drawer
if (gamestate != GS_TIMEATTACK) if (gamestate != GS_TIMEATTACK)
CON_Drawer(); CON_Drawer();
M_Drawer(); // menu is drawn even on top of everything
// focus lost moved to M_Drawer
// //
// wipe update // wipe update
// //
@ -1219,7 +1220,7 @@ void D_SRB2Main(void)
#endif #endif
D_CleanFile(); 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 // Check MD5s of autoloaded files
W_VerifyFileMD5(0, ASSET_HASH_SRB2_PK3); // srb2.pk3 W_VerifyFileMD5(0, ASSET_HASH_SRB2_PK3); // srb2.pk3

View File

@ -632,7 +632,7 @@ void D_RegisterClientCommands(void)
// Set default player names // Set default player names
// Monster Iestyn (12/08/19): not sure where else I could have actually put this, but oh well // Monster Iestyn (12/08/19): not sure where else I could have actually put this, but oh well
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
sprintf(player_names[i], "Player %d", i); sprintf(player_names[i], "Player %d", 1 + i);
if (dedicated) if (dedicated)
return; return;
@ -1008,7 +1008,7 @@ boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
* SetPlayerName * SetPlayerName
* \author Graue <graue@oceanbase.org> * \author Graue <graue@oceanbase.org>
*/ */
static void CleanupPlayerName(INT32 playernum, const char *newname) void CleanupPlayerName(INT32 playernum, const char *newname)
{ {
char *buf; char *buf;
char *p; char *p;
@ -1036,6 +1036,17 @@ static void CleanupPlayerName(INT32 playernum, const char *newname)
tmpname = p; tmpname = p;
do
{
/* from EnsurePlayerNameIsGood */
if (!isprint(*p) || *p == ';' || (UINT8)*p >= 0x80)
break;
}
while (*++p) ;
if (*p)/* bad char found */
break;
// Remove trailing spaces. // Remove trailing spaces.
p = &tmpname[strlen(tmpname)-1]; // last character p = &tmpname[strlen(tmpname)-1]; // last character
while (*p == ' ' && p >= tmpname) while (*p == ' ' && p >= tmpname)

View File

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

View File

@ -1293,10 +1293,7 @@ static void readgametype(MYFILE *f, char *gtname)
UINT32 wordgt = 0; UINT32 wordgt = 0;
for (j = 0; GAMETYPERULE_LIST[j]; j++) for (j = 0; GAMETYPERULE_LIST[j]; j++)
if (fastcmp(word, GAMETYPERULE_LIST[j])) { if (fastcmp(word, GAMETYPERULE_LIST[j])) {
if (!j) // GTR_CAMPAIGN wordgt |= (1<<j);
wordgt |= 1;
else
wordgt |= (1<<j);
if (i || word2[0] == 'T' || word2[0] == 'Y') if (i || word2[0] == 'T' || word2[0] == 'Y')
newgtrules |= wordgt; newgtrules |= wordgt;
break; break;
@ -4945,19 +4942,19 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_PLAY_SUPER_TRANS3", "S_PLAY_SUPER_TRANS3",
"S_PLAY_SUPER_TRANS4", "S_PLAY_SUPER_TRANS4",
"S_PLAY_SUPER_TRANS5", "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 // technically the player goes here but it's an infinite tic state
"S_OBJPLACE_DUMMY", "S_OBJPLACE_DUMMY",
// 1-Up Box Sprites (uses player sprite) // 1-Up Box Sprites overlay (uses player sprite)
"S_PLAY_BOX1", "S_PLAY_BOX1",
"S_PLAY_BOX2", "S_PLAY_BOX2",
"S_PLAY_ICON1", "S_PLAY_ICON1",
"S_PLAY_ICON2", "S_PLAY_ICON2",
"S_PLAY_ICON3", "S_PLAY_ICON3",
// Level end sign (uses player sprite) // Level end sign overlay (uses player sprite)
"S_PLAY_SIGN", "S_PLAY_SIGN",
// NiGHTS character (uses player sprite) // NiGHTS character (uses player sprite)
@ -5205,7 +5202,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ROBOHOOD_JUMP2", "S_ROBOHOOD_JUMP2",
"S_ROBOHOOD_JUMP3", "S_ROBOHOOD_JUMP3",
// CastleBot FaceStabber // Castlebot Facestabber
"S_FACESTABBER_STND1", "S_FACESTABBER_STND1",
"S_FACESTABBER_STND2", "S_FACESTABBER_STND2",
"S_FACESTABBER_STND3", "S_FACESTABBER_STND3",
@ -5425,6 +5422,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_FLEE2", "S_EGGMOBILE_FLEE2",
"S_EGGMOBILE_BALL", "S_EGGMOBILE_BALL",
"S_EGGMOBILE_TARGET", "S_EGGMOBILE_TARGET",
"S_BOSSEGLZ1", "S_BOSSEGLZ1",
"S_BOSSEGLZ2", "S_BOSSEGLZ2",
@ -5477,7 +5475,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE3_FLEE1", "S_EGGMOBILE3_FLEE1",
"S_EGGMOBILE3_FLEE2", "S_EGGMOBILE3_FLEE2",
// Boss 3 pinch // Boss 3 Pinch
"S_FAKEMOBILE_INIT", "S_FAKEMOBILE_INIT",
"S_FAKEMOBILE", "S_FAKEMOBILE",
"S_FAKEMOBILE_ATK1", "S_FAKEMOBILE_ATK1",
@ -5493,7 +5491,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BOSSSEBH2", "S_BOSSSEBH2",
// Boss 3 Shockwave // Boss 3 Shockwave
"S_SHOCKWAVE1", "S_SHOCKWAVE1",
"S_SHOCKWAVE2", "S_SHOCKWAVE2",
@ -5530,9 +5527,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_JETFLAME", "S_JETFLAME",
// Boss 4 Spectator Eggrobo // Boss 4 Spectator Eggrobo
"S_EGGROBO1_IDLE", "S_EGGROBO1_STND",
"S_EGGROBO1_BSLAP1", "S_EGGROBO1_BSLAP1",
"S_EGGROBO2_BSLAP2", "S_EGGROBO1_BSLAP2",
"S_EGGROBO1_PISSED", "S_EGGROBO1_PISSED",
// Boss 4 Spectator Eggrobo jet flame // Boss 4 Spectator Eggrobo jet flame
@ -5776,7 +5773,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CYBRAKDEMON_NAPALM_ATTACK1", "S_CYBRAKDEMON_NAPALM_ATTACK1",
"S_CYBRAKDEMON_NAPALM_ATTACK2", "S_CYBRAKDEMON_NAPALM_ATTACK2",
"S_CYBRAKDEMON_NAPALM_ATTACK3", "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_FINISH_ATTACK2", // Force a delay between attacks so you don't get bombarded with them back-to-back
"S_CYBRAKDEMON_PAIN1", "S_CYBRAKDEMON_PAIN1",
"S_CYBRAKDEMON_PAIN2", "S_CYBRAKDEMON_PAIN2",
@ -6470,7 +6467,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_LITTLETUMBLEWEED_ROLL7", "S_LITTLETUMBLEWEED_ROLL7",
"S_LITTLETUMBLEWEED_ROLL8", "S_LITTLETUMBLEWEED_ROLL8",
// Cacti Sprites // Cacti
"S_CACTI1", "S_CACTI1",
"S_CACTI2", "S_CACTI2",
"S_CACTI3", "S_CACTI3",
@ -6485,7 +6482,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CACTITINYSEG", "S_CACTITINYSEG",
"S_CACTISMALLSEG", "S_CACTISMALLSEG",
// Warning signs sprites // Warning signs
"S_ARIDSIGN_CAUTION", "S_ARIDSIGN_CAUTION",
"S_ARIDSIGN_CACTI", "S_ARIDSIGN_CACTI",
"S_ARIDSIGN_SHARPTURN", "S_ARIDSIGN_SHARPTURN",
@ -6502,6 +6499,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_TNTBARREL_EXPL4", "S_TNTBARREL_EXPL4",
"S_TNTBARREL_EXPL5", "S_TNTBARREL_EXPL5",
"S_TNTBARREL_EXPL6", "S_TNTBARREL_EXPL6",
"S_TNTBARREL_EXPL7",
"S_TNTBARREL_FLYING", "S_TNTBARREL_FLYING",
// TNT proximity shell // TNT proximity shell
@ -7047,7 +7045,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ZAPSB10", "S_ZAPSB10",
"S_ZAPSB11", // blank frame "S_ZAPSB11", // blank frame
// Thunder spark //Thunder spark
"S_THUNDERCOIN_SPARK", "S_THUNDERCOIN_SPARK",
// Invincibility Sparkles // Invincibility Sparkles
@ -7348,6 +7346,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BHORIZ7", "S_BHORIZ7",
"S_BHORIZ8", "S_BHORIZ8",
// Booster
"S_BOOSTERSOUND", "S_BOOSTERSOUND",
"S_YELLOWBOOSTERROLLER", "S_YELLOWBOOSTERROLLER",
"S_YELLOWBOOSTERSEG_LEFT", "S_YELLOWBOOSTERSEG_LEFT",
@ -7378,7 +7377,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SPLISH8", "S_SPLISH8",
"S_SPLISH9", "S_SPLISH9",
// Lava splish // Lava Splish
"S_LAVASPLISH", "S_LAVASPLISH",
// added water splash // added water splash
@ -7974,6 +7973,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ROCKCRUMBLEN", "S_ROCKCRUMBLEN",
"S_ROCKCRUMBLEO", "S_ROCKCRUMBLEO",
"S_ROCKCRUMBLEP", "S_ROCKCRUMBLEP",
// Level debris
"S_GFZDEBRIS", "S_GFZDEBRIS",
"S_BRICKDEBRIS", "S_BRICKDEBRIS",
"S_WOODDEBRIS", "S_WOODDEBRIS",
@ -7993,7 +7994,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_THOK", // Thok! mobj "MT_THOK", // Thok! mobj
"MT_PLAYER", "MT_PLAYER",
"MT_TAILSOVERLAY", // c: "MT_TAILSOVERLAY", // c:
"MT_METALJETFUME", // [: "MT_METALJETFUME",
// Enemies // Enemies
"MT_BLUECRAWLA", // Crawla (Blue) "MT_BLUECRAWLA", // Crawla (Blue)
@ -8110,7 +8111,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_CYBRAKDEMON_NAPALM_FLAMES", "MT_CYBRAKDEMON_NAPALM_FLAMES",
"MT_CYBRAKDEMON_VILE_EXPLOSION", "MT_CYBRAKDEMON_VILE_EXPLOSION",
// Metal Sonic // Metal Sonic (Boss 9)
"MT_METALSONIC_RACE", "MT_METALSONIC_RACE",
"MT_METALSONIC_BATTLE", "MT_METALSONIC_BATTLE",
"MT_MSSHIELD_FRONT", "MT_MSSHIELD_FRONT",
@ -8124,7 +8125,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BOMBSPHERE", "MT_BOMBSPHERE",
"MT_REDTEAMRING", //Rings collectable by red team. "MT_REDTEAMRING", //Rings collectable by red team.
"MT_BLUETEAMRING", //Rings collectable by blue 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_REDFLAG", // Red CTF Flag
"MT_BLUEFLAG", // Blue CTF Flag "MT_BLUEFLAG", // Blue CTF Flag
"MT_EMBLEM", "MT_EMBLEM",
@ -8350,22 +8351,22 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Arid Canyon Scenery // Arid Canyon Scenery
"MT_BIGTUMBLEWEED", "MT_BIGTUMBLEWEED",
"MT_LITTLETUMBLEWEED", "MT_LITTLETUMBLEWEED",
"MT_CACTI1", "MT_CACTI1", // Tiny Red Flower Cactus
"MT_CACTI2", "MT_CACTI2", // Small Red Flower Cactus
"MT_CACTI3", "MT_CACTI3", // Tiny Blue Flower Cactus
"MT_CACTI4", "MT_CACTI4", // Small Blue Flower Cactus
"MT_CACTI5", "MT_CACTI5", // Prickly Pear
"MT_CACTI6", "MT_CACTI6", // Barrel Cactus
"MT_CACTI7", "MT_CACTI7", // Tall Barrel Cactus
"MT_CACTI8", "MT_CACTI8", // Armed Cactus
"MT_CACTI9", "MT_CACTI9", // Ball Cactus
"MT_CACTI10", "MT_CACTI10", // Tiny Cactus
"MT_CACTI11", "MT_CACTI11", // Small Cactus
"MT_CACTITINYSEG", "MT_CACTITINYSEG", // Tiny Cactus Segment
"MT_CACTISMALLSEG", "MT_CACTISMALLSEG", // Small Cactus Segment
"MT_ARIDSIGN_CAUTION", "MT_ARIDSIGN_CAUTION", // Caution Sign
"MT_ARIDSIGN_CACTI", "MT_ARIDSIGN_CACTI", // Cacti Sign
"MT_ARIDSIGN_SHARPTURN", "MT_ARIDSIGN_SHARPTURN", // Sharp Turn Sign
"MT_OILLAMP", "MT_OILLAMP",
"MT_TNTBARREL", "MT_TNTBARREL",
"MT_PROXIMITYTNT", "MT_PROXIMITYTNT",
@ -8420,7 +8421,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_GLAREGOYLEUP", "MT_GLAREGOYLEUP",
"MT_GLAREGOYLEDOWN", "MT_GLAREGOYLEDOWN",
"MT_GLAREGOYLELONG", "MT_GLAREGOYLELONG",
"MT_TARGET", "MT_TARGET", // AKA Red Crystal
"MT_GREENFLAME", "MT_GREENFLAME",
"MT_BLUEGARGOYLE", "MT_BLUEGARGOYLE",
@ -8471,7 +8472,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_HHZSTALAGMITE_TALL", "MT_HHZSTALAGMITE_TALL",
"MT_HHZSTALAGMITE_SHORT", "MT_HHZSTALAGMITE_SHORT",
// Botanic Serenity // Botanic Serenity scenery
"MT_BSZTALLFLOWER_RED", "MT_BSZTALLFLOWER_RED",
"MT_BSZTALLFLOWER_PURPLE", "MT_BSZTALLFLOWER_PURPLE",
"MT_BSZTALLFLOWER_BLUE", "MT_BSZTALLFLOWER_BLUE",
@ -8751,6 +8752,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_ROCKCRUMBLE14", "MT_ROCKCRUMBLE14",
"MT_ROCKCRUMBLE15", "MT_ROCKCRUMBLE15",
"MT_ROCKCRUMBLE16", "MT_ROCKCRUMBLE16",
// Level debris
"MT_GFZDEBRIS", "MT_GFZDEBRIS",
"MT_BRICKDEBRIS", "MT_BRICKDEBRIS",
"MT_WOODDEBRIS", "MT_WOODDEBRIS",
@ -9143,6 +9146,7 @@ static const char *const HUDITEMS_LIST[] = {
"RINGS", "RINGS",
"RINGSNUM", "RINGSNUM",
"RINGSNUMTICS",
"SCORE", "SCORE",
"SCORENUM", "SCORENUM",
@ -9162,8 +9166,7 @@ static const char *const HUDITEMS_LIST[] = {
"TIMELEFTNUM", "TIMELEFTNUM",
"TIMEUP", "TIMEUP",
"HUNTPICS", "HUNTPICS",
"POWERUPS", "POWERUPS"
"LAP"
}; };
static const char *const MENUTYPES_LIST[] = { static const char *const MENUTYPES_LIST[] = {

View File

@ -143,9 +143,9 @@ extern char logfilename[1024];
// we use comprevision and compbranch instead. // we use comprevision and compbranch instead.
#else #else
#define VERSION 202 // Game version #define VERSION 202 // Game version
#define SUBVERSION 0 // more precise version number #define SUBVERSION 1 // more precise version number
#define VERSIONSTRING "v2.2.0" #define VERSIONSTRING "v2.2.1"
#define VERSIONSTRINGW L"v2.2.0" #define VERSIONSTRINGW L"v2.2.1"
// Hey! If you change this, add 1 to the MODVERSION below! // Hey! If you change this, add 1 to the MODVERSION below!
// Otherwise we can't force updates! // Otherwise we can't force updates!
#endif #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. // it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously. // Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1". // Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1".
#define MODVERSION 40 #define MODVERSION 41
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
// Increment MINOREXECVERSION whenever a config change is needed that does not correspond // Increment MINOREXECVERSION whenever a config change is needed that does not correspond

View File

@ -1120,6 +1120,9 @@ static const char *credits[] = {
"\1Sonic Robo Blast II", "\1Sonic Robo Blast II",
"\1Credits", "\1Credits",
"", "",
"\1Producer",
"Rob Tisdell",
"",
"\1Game Design", "\1Game Design",
"Ben \"Mystic\" Geyer", "Ben \"Mystic\" Geyer",
"\"SSNTails\"", "\"SSNTails\"",
@ -1234,7 +1237,7 @@ static const char *credits[] = {
"Thomas \"Shadow Hog\" Igoe", "Thomas \"Shadow Hog\" Igoe",
"Alexander \"DrTapeworm\" Moench-Ford", "Alexander \"DrTapeworm\" Moench-Ford",
"\"Kaito Sinclaire\"", "\"Kaito Sinclaire\"",
"\"QueenDelta\"", "Anna \"QueenDelta\" Sandlin",
"Wessel \"sphere\" Smit", "Wessel \"sphere\" Smit",
"\"Spazzo\"", "\"Spazzo\"",
"\"SSNTails\"", "\"SSNTails\"",
@ -1258,7 +1261,7 @@ static const char *credits[] = {
"Cody \"SRB2 Playah\" Koester", "Cody \"SRB2 Playah\" Koester",
"Skye \"OmegaVelocity\" Meredith", "Skye \"OmegaVelocity\" Meredith",
"Stephen \"HEDGESMFG\" Moellering", "Stephen \"HEDGESMFG\" Moellering",
"Nick \"ST218\" Molina", "Rosalie \"ST218\" Molina",
"Samuel \"Prime 2.0\" Peters", "Samuel \"Prime 2.0\" Peters",
"Colin \"Sonict\" Pfaff", "Colin \"Sonict\" Pfaff",
"Bill \"Tets\" Reed", "Bill \"Tets\" Reed",
@ -2695,8 +2698,18 @@ static void F_FigureActiveTtScale(void)
SINT8 newttscale = max(1, min(6, vid.dupx)); SINT8 newttscale = max(1, min(6, vid.dupx));
SINT8 oldttscale = activettscale; SINT8 oldttscale = activettscale;
if (newttscale == testttscale) if (needpatchrecache)
return; 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; testttscale = newttscale;
// If ttscale is unavailable: look for lower scales, then higher scales. // If ttscale is unavailable: look for lower scales, then higher scales.
@ -2714,10 +2727,6 @@ static void F_FigureActiveTtScale(void)
activettscale = (newttscale >= 1 && newttscale <= 6) ? newttscale : 0; activettscale = (newttscale >= 1 && newttscale <= 6) ? newttscale : 0;
// We have a new ttscale, so load gfx
if(oldttscale > 0)
F_UnloadAlacroixGraphics(oldttscale);
if(activettscale > 0) if(activettscale > 0)
F_LoadAlacroixGraphics(activettscale); F_LoadAlacroixGraphics(activettscale);
} }
@ -2759,12 +2768,6 @@ void F_TitleScreenDrawer(void)
return; return;
#endif #endif
if (needpatchrecache && (curttmode == TTMODE_ALACROIX))
{
ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0;
F_LoadAlacroixGraphics(activettscale);
}
switch(curttmode) switch(curttmode)
{ {
case TTMODE_OLD: case TTMODE_OLD:
@ -3630,7 +3633,6 @@ void F_StartContinue(void)
} }
wipestyleflags = WSF_FADEOUT; wipestyleflags = WSF_FADEOUT;
F_TryColormapFade(31);
G_SetGamestate(GS_CONTINUING); G_SetGamestate(GS_CONTINUING);
gameaction = ga_nothing; gameaction = ga_nothing;

View File

@ -1941,6 +1941,10 @@ boolean G_IsTitleCardAvailable(void)
if (gametyperules & GTR_NOTITLECARD) if (gametyperules & GTR_NOTITLECARD)
return false; return false;
// The current level has no name.
if (!mapheaderinfo[gamemap-1]->lvlttl[0])
return false;
// The title card is available. // The title card is available.
return true; return true;
} }
@ -3252,8 +3256,8 @@ void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
{ {
size_t r = 0; // read size_t r = 0; // read
size_t w = 0; // write size_t w = 0; // write
char *gtconst = Z_Calloc(strlen(newgtconst) + 3, PU_STATIC, NULL); char *gtconst = Z_Calloc(strlen(newgtconst) + 4, PU_STATIC, NULL);
char *tmpconst = Z_Calloc(strlen(newgtconst), PU_STATIC, NULL); char *tmpconst = Z_Calloc(strlen(newgtconst) + 1, PU_STATIC, NULL);
// Copy the gametype name. // Copy the gametype name.
strcpy(tmpconst, newgtconst); strcpy(tmpconst, newgtconst);
@ -3735,7 +3739,10 @@ static void G_DoCompleted(void)
} }
if (i == 7) if (i == 7)
{
gottoken = false; gottoken = false;
token = 0;
}
} }
if (spec && !gottoken) if (spec && !gottoken)

View File

@ -5325,7 +5325,7 @@ static void HWR_AddSprites(sector_t *sec)
#ifdef HWPRECIP #ifdef HWPRECIP
precipmobj_t *precipthing; precipmobj_t *precipthing;
#endif #endif
fixed_t approx_dist, limit_dist, hoop_limit_dist; fixed_t limit_dist, hoop_limit_dist;
// BSP is traversed by subsector. // BSP is traversed by subsector.
// A sector might have been split into several // A sector might have been split into several
@ -5344,35 +5344,10 @@ static void HWR_AddSprites(sector_t *sec)
// If a limit exists, handle things a tiny bit different. // If a limit exists, handle things a tiny bit different.
limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS; limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS;
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.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 (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist))
{
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;
}
HWR_ProjectSprite(thing); 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 #ifdef HWPRECIP
@ -5381,15 +5356,8 @@ static void HWR_AddSprites(sector_t *sec)
{ {
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
{ {
if (precipthing->precipflags & PCF_INVISIBLE) if (R_PrecipThingVisible(precipthing, limit_dist))
continue; HWR_ProjectPrecipitationSprite(precipthing);
approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y);
if (approx_dist > limit_dist)
continue;
HWR_ProjectPrecipitationSprite(precipthing);
} }
} }
#endif #endif
@ -5643,7 +5611,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer)
{ {
// bodge support - not nearly as comprehensive as r_things.c, but better than nothing // 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; return;
} }

View File

@ -1437,7 +1437,7 @@ static void HU_drawMiniChat(void)
for (; i>0; i--) 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; size_t j = 0;
INT32 linescount = 0; INT32 linescount = 0;
@ -1479,6 +1479,9 @@ static void HU_drawMiniChat(void)
dy = 0; dy = 0;
dx = 0; dx = 0;
msglines += linescount+1; msglines += linescount+1;
if (msg)
Z_Free(msg);
} }
y = chaty - charheight*(msglines+1); 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 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. INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one.
size_t j = 0; 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; UINT8 *colormap = NULL;
while(msg[j]) // iterate through msg while(msg[j]) // iterate through msg
@ -1547,6 +1550,9 @@ static void HU_drawMiniChat(void)
} }
dy += charheight; dy += charheight;
dx = 0; dx = 0;
if (msg)
Z_Free(msg);
} }
// decrement addy and make that shit smooth: // decrement addy and make that shit smooth:
@ -1598,7 +1604,7 @@ static void HU_drawChatLog(INT32 offset)
{ {
INT32 clrflag = 0; INT32 clrflag = 0;
INT32 j = 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; UINT8 *colormap = NULL;
while(msg[j]) // iterate through msg while(msg[j]) // iterate through msg
{ {
@ -1638,6 +1644,9 @@ static void HU_drawChatLog(INT32 offset)
} }
dy += charheight; dy += charheight;
dx = 0; dx = 0;
if (msg)
Z_Free(msg);
} }

View File

@ -762,7 +762,7 @@ state_t states[NUMSTATES] =
{SPR_PLAY, SPR2_LIFE, 20, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3 {SPR_PLAY, SPR2_LIFE, 20, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3
// Level end sign (uses player sprite) // 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 // NiGHTS Player, transforming
{SPR_PLAY, SPR2_TRNS|FF_ANIMATE, 7, {NULL}, 0, 4, S_PLAY_NIGHTS_TRANS2}, // S_PLAY_NIGHTS_TRANS1 {SPR_PLAY, SPR2_TRNS|FF_ANIMATE, 7, {NULL}, 0, 4, S_PLAY_NIGHTS_TRANS2}, // S_PLAY_NIGHTS_TRANS1
@ -2343,12 +2343,13 @@ state_t states[NUMSTATES] =
// TNT barrel // TNT barrel
{SPR_BARR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_TNTBARREL_STND1 {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, 0, 0, {A_RollAngle}, 0, 1, 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, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_TNTBARREL_EXPL3}, // S_TNTBARREL_EXPL2
{SPR_BARX, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_TNTBARREL_EXPL4}, // S_TNTBARREL_EXPL3 {SPR_BARX, 1|FF_FULLBRIGHT, 2, {A_TNTExplode}, MT_TNTDUST, 0, S_TNTBARREL_EXPL4}, // S_TNTBARREL_EXPL3
{SPR_BARX, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL5}, // S_TNTBARREL_EXPL4 {SPR_BARX, 1|FF_FULLBRIGHT, 1, {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_BARX, 2|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, 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 #ifndef ROTSPRITE
{SPR_BARR, 1|FF_ANIMATE, -1, {NULL}, 7, 2, S_NULL}, // S_TNTBARREL_FLYING {SPR_BARR, 1|FF_ANIMATE, -1, {NULL}, 7, 2, S_NULL}, // S_TNTBARREL_FLYING
#else #else
@ -2394,7 +2395,7 @@ state_t states[NUMSTATES] =
// Minecart // Minecart
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_MINECART_IDLE}, // S_MINECART_IDLE {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, 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, 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 {SPR_MCRT, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_MINECARTSEG_BACK
@ -6487,10 +6488,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
24*FRACUNIT, // radius 24*FRACUNIT, // radius
24*FRACUNIT, // height 24*FRACUNIT, // height
0, // display offset 0, // display offset
0, // mass DMG_FIRE, // mass
1, // damage 1, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags MF_NOBLOCKMAP|MF_MISSILE|MF_PAIN|MF_NOGRAVITY, // flags
S_NULL // raisestate S_NULL // raisestate
}, },

View File

@ -2503,6 +2503,7 @@ typedef enum state
S_TNTBARREL_EXPL4, S_TNTBARREL_EXPL4,
S_TNTBARREL_EXPL5, S_TNTBARREL_EXPL5,
S_TNTBARREL_EXPL6, S_TNTBARREL_EXPL6,
S_TNTBARREL_EXPL7,
S_TNTBARREL_FLYING, S_TNTBARREL_FLYING,
// TNT proximity shell // TNT proximity shell

View File

@ -268,10 +268,14 @@ static int patch_get(lua_State *L)
#endif #endif
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
// patches are CURRENTLY always valid, expected to be cached with PU_STATIC // patches are invalidated when switching renderers
// this may change in the future, so patch.valid still exists if (!patch) {
if (!patch) if (field == patch_valid) {
lua_pushboolean(L, 0);
return 1;
}
return LUA_ErrInvalid(L, "patch_t"); return LUA_ErrInvalid(L, "patch_t");
}
switch (field) switch (field)
{ {
@ -1214,7 +1218,7 @@ void LUAh_GameHUD(player_t *stplayr)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); 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)); I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
@ -1248,7 +1252,7 @@ void LUAh_ScoresHUD(void)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); 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)); I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
@ -1273,7 +1277,7 @@ void LUAh_TitleHUD(void)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); 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)); I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
@ -1298,7 +1302,7 @@ void LUAh_TitleCardHUD(player_t *stplayr)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); 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)); I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
@ -1332,7 +1336,7 @@ void LUAh_IntermissionHUD(void)
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); 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)); I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw

View File

@ -624,14 +624,6 @@ static void GIF_framewrite(void)
// //
INT32 GIF_open(const char *filename) 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"); gif_out = fopen(filename, "wb");
if (!gif_out) if (!gif_out)
return 0; return 0;
@ -640,13 +632,13 @@ INT32 GIF_open(const char *filename)
gif_downscale = (!!cv_gif_downscale.value); gif_downscale = (!!cv_gif_downscale.value);
// GIF color table // GIF color table
// In hardware mode, uses the master palette // In hardware mode, forces the local palette
gif_palette = ((cv_screenshot_colorprofile.value
#ifdef HWRENDER #ifdef HWRENDER
&& (rendermode == render_soft) if (rendermode == render_opengl)
gif_palette = pLocalPalette;
else
#endif #endif
) ? pLocalPalette gif_palette = ((cv_screenshot_colorprofile.value) ? pLocalPalette : pMasterPalette);
: pMasterPalette);
GIF_headwrite(); GIF_headwrite();
gif_frames = 0; gif_frames = 0;

View File

@ -5602,7 +5602,8 @@ static void M_DrawNightsAttackMountains(void)
static INT32 bgscrollx; static INT32 bgscrollx;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
patch_t *background = W_CachePatchName(curbgname, PU_PATCH); 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; INT32 y = BASEVIDHEIGHT - SHORT(background->height)*2;
if (vid.height != BASEVIDHEIGHT * dupz) if (vid.height != BASEVIDHEIGHT * dupz)
@ -5610,11 +5611,13 @@ static void M_DrawNightsAttackMountains(void)
V_DrawFill(0, y+50, vid.width, BASEVIDHEIGHT, V_SNAPTOLEFT|31); V_DrawFill(0, y+50, vid.width, BASEVIDHEIGHT, V_SNAPTOLEFT|31);
V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background); V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background);
x += SHORT(background->width); x += w;
if (x < BASEVIDWIDTH) if (x < BASEVIDWIDTH)
V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background); V_DrawScaledPatch(x, y, V_SNAPTOLEFT, background);
bgscrollx -= (FRACUNIT/2); bgscrollx += (FRACUNIT/2);
if (bgscrollx > w<<FRACBITS)
bgscrollx &= 0xFFFF;
} }
// NiGHTS Attack foreground. // NiGHTS Attack foreground.
@ -10843,7 +10846,6 @@ static void M_HandleConnectIP(INT32 choice)
default: // otherwise do nothing. default: // otherwise do nothing.
break; break;
} }
break; // don't check for typed keys
} }
if (l >= 28-1) if (l >= 28-1)

View File

@ -5198,8 +5198,8 @@ void A_SignPlayer(mobj_t *actor)
player_t *player = actor->target ? actor->target->player : NULL; player_t *player = actor->target ? actor->target->player : NULL;
UINT8 skinnum; UINT8 skinnum;
UINT8 skincount = 0; UINT8 skincount = 0;
for (skincount = 0; skincount < numskins; skincount++) for (skinnum = 0; skinnum < numskins; skinnum++)
if (!skincheck(skincount)) if (!skincheck(skinnum))
skincount++; skincount++;
skinnum = P_RandomKey(skincount); skinnum = P_RandomKey(skincount);
for (skincount = 0; skincount < numskins; skincount++) for (skincount = 0; skincount < numskins; skincount++)
@ -5232,20 +5232,23 @@ void A_SignPlayer(mobj_t *actor)
{ {
ov->color = facecolor; ov->color = facecolor;
ov->skin = skin; 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 else // CLEAR! sign
{ {
ov->color = SKINCOLOR_NONE; ov->color = SKINCOLOR_NONE;
ov->skin = NULL; // needs to be NULL in the case of SF_HIRES characters 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 else // Eggman face
{ {
ov->color = SKINCOLOR_NONE; ov->color = SKINCOLOR_NONE;
ov->skin = NULL; 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) if (!signcolor)
signcolor = SKINCOLOR_CARBON; signcolor = SKINCOLOR_CARBON;
} }

View File

@ -1428,98 +1428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Misc touchables // // Misc touchables //
// *************** // // *************** //
case MT_STARPOST: case MT_STARPOST:
if (player->bot) P_TouchStarPost(special, player, special->spawnpoint && (special->spawnpoint->options & MTF_OBJECTSPECIAL));
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);
}
}
return; return;
case MT_FAKEMOBILE: case MT_FAKEMOBILE:
@ -1872,6 +1781,112 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->shadowscale = 0; 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. /** Prints death messages relating to a dying or hit player.
* *
* \param player Affected player. * \param player Affected player.

View File

@ -486,6 +486,7 @@ void P_PlayerWeaponPanelOrAmmoBurst(player_t *player);
void P_PlayerEmeraldBurst(player_t *player, boolean toss); void P_PlayerEmeraldBurst(player_t *player, boolean toss);
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck); 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_PlayerFlagBurst(player_t *player, boolean toss);
void P_CheckTimeLimit(void); void P_CheckTimeLimit(void);
void P_CheckPointLimit(void); void P_CheckPointLimit(void);

View File

@ -2350,6 +2350,7 @@ static void P_RingZMovement(mobj_t *mo)
if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo)) if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{ {
mo->momz += mo->pmomz; mo->momz += mo->pmomz;
mo->pmomz = 0;
mo->eflags &= ~MFE_APPLYPMOMZ; mo->eflags &= ~MFE_APPLYPMOMZ;
} }
mo->z += mo->momz; mo->z += mo->momz;
@ -2419,6 +2420,7 @@ static boolean P_ZMovement(mobj_t *mo)
if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo)) if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{ {
mo->momz += mo->pmomz; mo->momz += mo->pmomz;
mo->pmomz = 0;
mo->eflags &= ~MFE_APPLYPMOMZ; mo->eflags &= ~MFE_APPLYPMOMZ;
} }
mo->z += mo->momz; mo->z += mo->momz;
@ -2907,6 +2909,7 @@ static void P_PlayerZMovement(mobj_t *mo)
if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo)) if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{ {
mo->momz += mo->pmomz; mo->momz += mo->pmomz;
mo->pmomz = 0;
mo->eflags &= ~MFE_APPLYPMOMZ; mo->eflags &= ~MFE_APPLYPMOMZ;
} }
@ -3157,6 +3160,7 @@ static boolean P_SceneryZMovement(mobj_t *mo)
if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo)) if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
{ {
mo->momz += mo->pmomz; mo->momz += mo->pmomz;
mo->pmomz = 0;
mo->eflags &= ~MFE_APPLYPMOMZ; mo->eflags &= ~MFE_APPLYPMOMZ;
} }
mo->z += mo->momz; mo->z += mo->momz;
@ -10457,6 +10461,61 @@ void P_SceneryThinker(mobj_t *mobj)
// GAME SPAWN FUNCTIONS // 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 // P_SpawnMobj
// //
@ -10558,20 +10617,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->z = z; mobj->z = z;
// Set shadowscale here, before spawn hook so that Lua can change it // Set shadowscale here, before spawn hook so that Lua can change it
if ( mobj->shadowscale = P_DefaultMobjShadowScale(mobj);
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;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
// DANGER! This can cause P_SpawnMobj to return NULL! // DANGER! This can cause P_SpawnMobj to return NULL!
@ -12931,7 +12977,16 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
thinker_t* th; thinker_t* th;
mobj_t* mo2; mobj_t* mo2;
boolean foundanother = false; 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. // 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) 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) static void Polyobj_slideThing(mobj_t *mo, fixed_t dx, fixed_t dy)
{ {
if (mo->player) { // Do something similar to conveyor movement. -Red if (mo->player) { // Finally this doesn't suck eggs -fickle
mo->player->cmomx += dx; fixed_t cdx, cdy;
mo->player->cmomy += dy;
dx = FixedMul(dx, CARRYFACTOR); cdx = FixedMul(dx, FRACUNIT-CARRYFACTOR);
dy = FixedMul(dy, CARRYFACTOR); cdy = FixedMul(dy, FRACUNIT-CARRYFACTOR);
mo->player->cmomx -= dx; if (mo->player->onconveyor == 1)
mo->player->cmomy -= dy; {
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)) { 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 #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; static INT32 pomovecount = 10000;
INT32 x, y; 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++; pomovecount++;
@ -1334,19 +1355,10 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
oldxoff = mo->x-origin.x; oldxoff = mo->x-origin.x;
oldyoff = mo->y-origin.y; oldyoff = mo->y-origin.y;
if (mo->player) // Hack to fix players sliding off of spinning polys -Red newxoff = FixedMul(oldxoff, c)-FixedMul(oldyoff, s) - oldxoff;
{ newyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s) - oldyoff;
fixed_t temp;
temp = FixedMul(oldxoff, c)-FixedMul(oldyoff, s); Polyobj_slideThing(mo, newxoff, newyoff);
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);
if (turnthings == 2 || (turnthings == 1 && !mo->player)) { if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
mo->angle += delta; mo->angle += delta;

View File

@ -1257,6 +1257,7 @@ typedef enum
#endif #endif
MD2_COLORIZED = 1<<12, MD2_COLORIZED = 1<<12,
MD2_ROLLANGLE = 1<<13, MD2_ROLLANGLE = 1<<13,
MD2_SHADOWSCALE = 1<<14,
} mobj_diff2_t; } mobj_diff2_t;
typedef enum typedef enum
@ -1478,6 +1479,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_COLORIZED; diff2 |= MD2_COLORIZED;
if (mobj->rollangle) if (mobj->rollangle)
diff2 |= MD2_ROLLANGLE; diff2 |= MD2_ROLLANGLE;
if (mobj->shadowscale)
diff2 |= MD2_SHADOWSCALE;
if (diff2 != 0) if (diff2 != 0)
diff |= MD_MORE; diff |= MD_MORE;
@ -1644,6 +1647,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEUINT8(save_p, mobj->colorized); WRITEUINT8(save_p, mobj->colorized);
if (diff2 & MD2_ROLLANGLE) if (diff2 & MD2_ROLLANGLE)
WRITEANGLE(save_p, mobj->rollangle); WRITEANGLE(save_p, mobj->rollangle);
if (diff2 & MD2_SHADOWSCALE)
WRITEFIXED(save_p, mobj->shadowscale);
WRITEUINT32(save_p, mobj->mobjnum); WRITEUINT32(save_p, mobj->mobjnum);
} }
@ -2723,6 +2728,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->colorized = READUINT8(save_p); mobj->colorized = READUINT8(save_p);
if (diff2 & MD2_ROLLANGLE) if (diff2 & MD2_ROLLANGLE)
mobj->rollangle = READANGLE(save_p); mobj->rollangle = READANGLE(save_p);
if (diff2 & MD2_SHADOWSCALE)
mobj->shadowscale = READFIXED(save_p);
if (diff & MD_REDFLAG) if (diff & MD_REDFLAG)
{ {

View File

@ -3684,8 +3684,7 @@ boolean P_LoadLevel(boolean fromnetsave)
return true; return true;
// If so... // If so...
if ((!(mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD)) && (*mapheaderinfo[gamemap-1]->lvlttl != '\0')) G_PreLevelTitleCard();
G_PreLevelTitleCard();
return true; return true;
} }

View File

@ -4692,7 +4692,7 @@ DoneSection2:
if (!post) if (!post)
break; break;
P_TouchSpecialThing(post, player->mo, false); P_TouchStarPost(post, player, false);
break; break;
} }

View File

@ -600,7 +600,7 @@ void P_Ticker(boolean run)
{ {
players[i].quittime++; players[i].quittime++;
if (players[i].quittime == 30 * TICRATE) if (players[i].quittime == 30 * TICRATE && G_TagGametype())
P_CheckSurvivors(); P_CheckSurvivors();
if (server && players[i].quittime >= (tic_t)FixedMul(cv_rejointimeout.value, 60 * TICRATE) if (server && players[i].quittime >= (tic_t)FixedMul(cv_rejointimeout.value, 60 * TICRATE)

View File

@ -2380,6 +2380,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->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) else if (player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH)
@ -4537,16 +4539,14 @@ void P_DoJump(player_t *player, boolean soundandstate)
player->mo->z--; player->mo->z--;
if (player->mo->pmomz < 0) if (player->mo->pmomz < 0)
player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump. player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump.
else player->mo->pmomz = 0;
player->mo->pmomz = 0;
} }
else else
{ {
player->mo->z++; player->mo->z++;
if (player->mo->pmomz > 0) if (player->mo->pmomz > 0)
player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump. 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; player->mo->eflags &= ~MFE_APPLYPMOMZ;
@ -5503,10 +5503,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
; // Can't do anything if you're a fish out of water! ; // 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. else if (player->powers[pw_tailsfly]) // If currently flying, give an ascend boost.
{ {
if (!player->fly1) player->fly1 = 20;
player->fly1 = 20;
else
player->fly1 = 2;
if (player->charability == CA_SWIM) if (player->charability == CA_SWIM)
player->fly1 /= 2; player->fly1 /= 2;
@ -8489,7 +8486,11 @@ static void P_MovePlayer(player_t *player)
// Descend // Descend
if (cmd->buttons & BT_USE && !(player->pflags & PF_STASIS) && !player->exiting && !(player->mo->eflags & MFE_GOOWATER)) 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 (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); P_SetObjectMomZ(player->mo, -actionspd/2, true);
}
} }
else else
@ -11045,10 +11046,21 @@ static void P_MinecartThink(player_t *player)
if (angdiff + minecart->angle != player->mo->angle && (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG)) if (angdiff + minecart->angle != player->mo->angle && (!demoplayback || P_ControlStyle(player) == CS_LMAOGALOG))
{ {
angle_t *ang = NULL;
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
localangle = player->mo->angle; ang = &localangle;
else if (player == &players[secondarydisplayplayer]) 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;
}
} }
} }
@ -12164,7 +12176,9 @@ void P_PlayerThink(player_t *player)
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
if (player->onconveyor == 1) if (player->onconveyor == 1)
player->cmomy = player->cmomx = 0; player->onconveyor = 3;
else if (player->onconveyor == 3)
player->cmomy = player->cmomx = 0;
#endif #endif
P_DoSuperStuff(player); P_DoSuperStuff(player);

View File

@ -2465,16 +2465,20 @@ extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *ex
// Thanks to quake2 source! // Thanks to quake2 source!
// utils3/qdata/images.c // 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 dr, dg, db;
int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i; 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++) for (i = 0; i < 256; i++)
{ {
dr = r - pMasterPalette[i].s.red; dr = r - palette[i].s.red;
dg = g - pMasterPalette[i].s.green; dg = g - palette[i].s.green;
db = b - pMasterPalette[i].s.blue; db = b - palette[i].s.blue;
distortion = dr*dr + dg*dg + db*db; distortion = dr*dr + dg*dg + db*db;
if (distortion < bestdistortion) if (distortion < bestdistortion)
{ {

View File

@ -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_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)) #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; extern INT32 numtextures;

View File

@ -71,6 +71,7 @@ angle_t viewangle, aimingangle;
fixed_t viewcos, viewsin; fixed_t viewcos, viewsin;
sector_t *viewsector; sector_t *viewsector;
player_t *viewplayer; player_t *viewplayer;
mobj_t *r_viewmobj;
// //
// precalculated math tables // precalculated math tables
@ -1039,8 +1040,6 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y)
// R_SetupFrame // R_SetupFrame
// //
static mobj_t *viewmobj;
// WARNING: a should be unsigned but to add with 2048, it isn't! // WARNING: a should be unsigned but to add with 2048, it isn't!
#define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)/fovtan) #define AIMINGTODY(a) ((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)/fovtan)
@ -1097,16 +1096,16 @@ void R_SetupFrame(player_t *player)
if (player->awayviewtics) if (player->awayviewtics)
{ {
// cut-away view stuff // cut-away view stuff
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN r_viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
I_Assert(viewmobj != NULL); I_Assert(r_viewmobj != NULL);
viewz = viewmobj->z + 20*FRACUNIT; viewz = r_viewmobj->z + 20*FRACUNIT;
aimingangle = player->awayviewaiming; aimingangle = player->awayviewaiming;
viewangle = viewmobj->angle; viewangle = r_viewmobj->angle;
} }
else if (!player->spectator && chasecam) else if (!player->spectator && chasecam)
// use outside cam view // use outside cam view
{ {
viewmobj = NULL; r_viewmobj = NULL;
viewz = thiscam->z + (thiscam->height>>1); viewz = thiscam->z + (thiscam->height>>1);
aimingangle = thiscam->aiming; aimingangle = thiscam->aiming;
viewangle = thiscam->angle; viewangle = thiscam->angle;
@ -1116,11 +1115,11 @@ void R_SetupFrame(player_t *player)
{ {
viewz = player->viewz; viewz = player->viewz;
viewmobj = player->mo; r_viewmobj = player->mo;
I_Assert(viewmobj != NULL); I_Assert(r_viewmobj != NULL);
aimingangle = player->aiming; aimingangle = player->aiming;
viewangle = viewmobj->angle; viewangle = r_viewmobj->angle;
if (!demoplayback && player->playerstate != PST_DEAD) if (!demoplayback && player->playerstate != PST_DEAD)
{ {
@ -1154,13 +1153,13 @@ void R_SetupFrame(player_t *player)
} }
else else
{ {
viewx = viewmobj->x; viewx = r_viewmobj->x;
viewy = viewmobj->y; viewy = r_viewmobj->y;
viewx += quake.x; viewx += quake.x;
viewy += quake.y; viewy += quake.y;
if (viewmobj->subsector) if (r_viewmobj->subsector)
viewsector = viewmobj->subsector->sector; viewsector = r_viewmobj->subsector->sector;
else else
viewsector = R_PointInSubsector(viewx, viewy)->sector; viewsector = R_PointInSubsector(viewx, viewy)->sector;
} }
@ -1182,12 +1181,12 @@ void R_SkyboxFrame(player_t *player)
thiscam = &camera; thiscam = &camera;
// cut-away view stuff // cut-away view stuff
viewmobj = skyboxmo[0]; r_viewmobj = skyboxmo[0];
#ifdef PARANOIA #ifdef PARANOIA
if (!viewmobj) if (!r_viewmobj)
{ {
const size_t playeri = (size_t)(player - players); 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 #endif
if (player->awayviewtics) if (player->awayviewtics)
@ -1218,13 +1217,13 @@ void R_SkyboxFrame(player_t *player)
} }
} }
} }
viewangle += viewmobj->angle; viewangle += r_viewmobj->angle;
viewplayer = player; viewplayer = player;
viewx = viewmobj->x; viewx = r_viewmobj->x;
viewy = viewmobj->y; viewy = r_viewmobj->y;
viewz = viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle! viewz = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle!
if (mapheaderinfo[gamemap-1]) if (mapheaderinfo[gamemap-1])
{ {
@ -1264,29 +1263,29 @@ void R_SkyboxFrame(player_t *player)
else if (mh->skybox_scaley < 0) else if (mh->skybox_scaley < 0)
y = (campos.y - skyboxmo[1]->y) * -mh->skybox_scaley; y = (campos.y - skyboxmo[1]->y) * -mh->skybox_scaley;
if (viewmobj->angle == 0) if (r_viewmobj->angle == 0)
{ {
viewx += x; viewx += x;
viewy += y; viewy += y;
} }
else if (viewmobj->angle == ANGLE_90) else if (r_viewmobj->angle == ANGLE_90)
{ {
viewx -= y; viewx -= y;
viewy += x; viewy += x;
} }
else if (viewmobj->angle == ANGLE_180) else if (r_viewmobj->angle == ANGLE_180)
{ {
viewx -= x; viewx -= x;
viewy -= y; viewy -= y;
} }
else if (viewmobj->angle == ANGLE_270) else if (r_viewmobj->angle == ANGLE_270)
{ {
viewx += y; viewx += y;
viewy -= x; viewy -= x;
} }
else else
{ {
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT; angle_t ang = r_viewmobj->angle>>ANGLETOFINESHIFT;
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
} }
@ -1297,8 +1296,8 @@ void R_SkyboxFrame(player_t *player)
viewz += campos.z * -mh->skybox_scalez; viewz += campos.z * -mh->skybox_scalez;
} }
if (viewmobj->subsector) if (r_viewmobj->subsector)
viewsector = viewmobj->subsector->sector; viewsector = r_viewmobj->subsector->sector;
else else
viewsector = R_PointInSubsector(viewx, viewy)->sector; viewsector = R_PointInSubsector(viewx, viewy)->sector;

View File

@ -1196,7 +1196,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
INT32 angle; INT32 angle;
patch_t *patch; patch_t *patch;
patch_t *newpatch; patch_t *newpatch;
UINT16 *rawsrc, *rawdst; UINT16 *rawdst;
size_t size; size_t size;
INT32 bflip = (flip != 0x00); INT32 bflip = (flip != 0x00);
@ -1242,16 +1242,6 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
leftoffset = width - leftoffset; 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 // Don't cache angle = 0
for (angle = 1; angle < ROTANGLES; angle++) for (angle = 1; angle < ROTANGLES; angle++)
{ {

View File

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

View File

@ -1686,7 +1686,7 @@ static void R_ProjectSprite(mobj_t *thing)
thing = thing->tracer; thing = thing->tracer;
if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW) if (! R_ThingVisible(thing))
return; return;
tr_x = thing->x - viewx; tr_x = thing->x - viewx;
@ -2071,7 +2071,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
mobj_t *thing; mobj_t *thing;
precipmobj_t *precipthing; // Tails 08-25-2002 precipmobj_t *precipthing; // Tails 08-25-2002
INT32 lightnum; INT32 lightnum;
fixed_t approx_dist, limit_dist, hoop_limit_dist; fixed_t limit_dist, hoop_limit_dist;
if (rendermode != render_soft) if (rendermode != render_soft)
return; return;
@ -2104,35 +2104,10 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
// If a limit exists, handle things a tiny bit different. // If a limit exists, handle things a tiny bit different.
limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS; limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS;
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.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 (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist))
{
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;
}
R_ProjectSprite(thing); 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 // no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
@ -2140,15 +2115,8 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
{ {
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
{ {
if (precipthing->precipflags & PCF_INVISIBLE) if (R_PrecipThingVisible(precipthing, limit_dist))
continue; R_ProjectPrecipitationSprite(precipthing);
approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y);
if (approx_dist > limit_dist)
continue;
R_ProjectPrecipitationSprite(precipthing);
} }
} }
} }
@ -2850,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 // R_DrawMasked
// //
@ -3419,6 +3436,7 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
GETFLAG(DASHMODE) GETFLAG(DASHMODE)
GETFLAG(FASTEDGE) GETFLAG(FASTEDGE)
GETFLAG(MULTIABILITY) GETFLAG(MULTIABILITY)
GETFLAG(NONIGHTSROTATION)
#undef GETFLAG #undef GETFLAG
else // let's check if it's a sound, otherwise error out 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_ClearSprites(void);
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal); 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 /** Used to count the amount of masked elements
* per portal to later group them in separate * per portal to later group them in separate
* drawnode lists. * drawnode lists.

View File

@ -360,10 +360,13 @@ void SCR_Recalc(void)
vid.fsmalldupy = vid.smalldupy*FRACUNIT; vid.fsmalldupy = vid.smalldupy*FRACUNIT;
#endif #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. // be calculated next time the automap is activated.
if (automapactive) if (automapactive)
AM_Stop(); {
am_recalc = true;
AM_Start();
}
// set the screen[x] ptrs on the new vidbuffers // set the screen[x] ptrs on the new vidbuffers
V_Init(); V_Init();

View File

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

View File

@ -1278,13 +1278,15 @@ void ST_preDrawTitleCard(void)
// //
void ST_runTitleCard(void) void ST_runTitleCard(void)
{ {
boolean run = !(paused || P_AutoPause());
if (!G_IsTitleCardAvailable()) if (!G_IsTitleCardAvailable())
return; return;
if (lt_ticker >= (lt_endtime + TICRATE)) if (lt_ticker >= (lt_endtime + TICRATE))
return; return;
if (!(paused || P_AutoPause())) if (run || (lt_ticker < PRELEVELTIME))
{ {
// tick // tick
lt_ticker++; lt_ticker++;

View File

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

View File

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

View File

@ -822,13 +822,11 @@ UINT16 W_InitFile(const char *filename, boolean mainfile)
* backwards, so a later file overrides all earlier ones. * backwards, so a later file overrides all earlier ones.
* *
* \param filenames A null-terminated list of files to use. * \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 * \return 1 if base files were loaded, 0 if at least one was missing or
* invalid. * invalid.
*/ */
INT32 W_InitMultipleFiles(char **filenames, UINT16 mainfiles) INT32 W_InitMultipleFiles(char **filenames, UINT16 mainfiles)
{ {
INT32 rc = 1;
// open all the files, load headers, and count lumps // open all the files, load headers, and count lumps
numwadfiles = 0; numwadfiles = 0;
@ -836,13 +834,15 @@ INT32 W_InitMultipleFiles(char **filenames, UINT16 mainfiles)
for (; *filenames; filenames++) for (; *filenames; filenames++)
{ {
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames); //CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
rc &= (W_InitFile(*filenames, numwadfiles < mainfiles) != INT16_MAX) ? 1 : 0; if (W_InitFile(*filenames, numwadfiles < mainfiles) == INT16_MAX)
{
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), *filenames);
if (numwadfiles < mainfiles)
return 0;
}
} }
if (!numwadfiles) return 1;
I_Error("W_InitMultipleFiles: no files found");
return rc;
} }
/** Make sure a lump number is valid. /** Make sure a lump number is valid.
@ -1691,7 +1691,7 @@ W_VerifyName (const char *name, lumpchecklist_t *checklist, boolean status)
size_t j; size_t j;
for (j = 0; checklist[j].len && checklist[j].name; ++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) checklist[j].len) != false ) == status)
{ {
return true; return true;
@ -1746,6 +1746,19 @@ W_VerifyWAD (FILE *fp, lumpchecklist_t *checklist, boolean status)
return true; 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 static int
W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
{ {
@ -1797,7 +1810,7 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
else else
trimname = fullname; // Care taken for root files. trimname = fullname; // Care taken for root files.
if (*trimname) // Ignore directories if (*trimname) // Ignore directories, well kinda
{ {
if ((dotpos = strrchr(trimname, '.')) == 0) if ((dotpos = strrchr(trimname, '.')) == 0)
dotpos = fullname + strlen(fullname); // Watch for files without extension. dotpos = fullname + strlen(fullname); // Watch for files without extension.
@ -1807,6 +1820,10 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
if (! W_VerifyName(lumpname, checklist, status)) if (! W_VerifyName(lumpname, checklist, status))
return false; return false;
// Check for directories next, if it's blacklisted it will return false
if (W_VerifyName(fullname, folderblacklist, status))
return false;
} }
free(fullname); free(fullname);

View File

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