Merge branch 'master' into new-title

This commit is contained in:
mazmazz 2019-10-25 22:29:29 -04:00
commit c7c72a4892
150 changed files with 20025 additions and 4673 deletions

9
.gitattributes vendored
View File

@ -1,3 +1,12 @@
#Source code
/src/*.c text=auto
/src/*.h text=auto
/src/*.s text=auto
/src/*.m text=auto
/src/*.xpm text=auto
/src/Makefile text=auto
/src/Make*.cfg text=auto
/src/CMakeLists.txt text=auto
# Windows EOL
*.cs -crlf -whitespace
*.mk -crlf -whitespace

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.1.24
VERSION 2.1.25
LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})

View File

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

6482
extras/conf/SRB2-22.cfg Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
# libopenmpt mingw-w64 binary info
Current built version as of 2019/05/23 is 0.4.4+r11531.pkg
Current built version as of 2019/09/27 is 0.4.7+r12088.pkg
* mingw binaries (.dll): `bin/[x86 or x86_64]/mingw`
* mingw import libraries (.dll.a): `lib/[x86 or x86_64]/mingw`

View File

@ -5,6 +5,44 @@ Changelog {#changelog}
For fully detailed change log, please see the source repository directly. This
is just a high-level summary.
### libopenmpt 0.4.7 (2019-09-23)
* [**Bug**] Compilation fix for various platforms that do not provide
`std::aligned_alloc` in C++17 mode. The problematic dependency has been
removed. This should fix build problems on MinGW, OpenBSD, Haiku, and others
for good.
* J2B: Ignore notes with non-existing instrument (fixes Ending.j2b).
* mpg123: Update to v1.25.13 (2019-08-24).
* ogg: Update to v1.3.4. (2019-08-31).
* flac: Update to v1.3.3. (2019-08-04).
### libopenmpt 0.4.6 (2019-08-10)
* [**Bug**] Compilation fix for OpenBSD.
* [**Bug**] Compilation fix for NO_PLUGINS being defined.
* in_openmpt: Correct documentation. `openmpt-mpg123.dll` must be placed into
the Winamp directory.
* Detect IT files unpacked with early UNMO3 versions.
* mpg123: Update to v1.25.11 (2019-07-18).
* minimp3: Update to commit 977514a6dfc4960d819a103f43b358e58ac6c28f
(2019-07-24).
* miniz: Update to v2.1.0 (2019-05-05).
* stb_vorbis: Update to v1.17 (2019-08-09).
### libopenmpt 0.4.5 (2019-05-27)
* [**Sec**] Possible crash during playback due out-of-bounds read in XM and
MT2 files (r11608).
* Breaking out of a sustain loop through Note-Off sometimes didn't continue in
the regular sample loop.
* Seeking did not stop notes playing with XM Key Off (Kxx) effect.
### libopenmpt 0.4.4 (2019-04-07)
* [**Bug**] Channel VU meters were swapped.

View File

@ -19,7 +19,7 @@
/*! \brief libopenmpt minor version number */
#define OPENMPT_API_VERSION_MINOR 4
/*! \brief libopenmpt patch version number */
#define OPENMPT_API_VERSION_PATCH 4
#define OPENMPT_API_VERSION_PATCH 7
/*! \brief libopenmpt pre-release tag */
#define OPENMPT_API_VERSION_PREREL ""
/*! \brief libopenmpt pre-release flag */

View File

@ -62,7 +62,6 @@
#define PNG_NO_READ_iTXt
#define PNG_NO_READ_APNG
#define PNG_NO_READ_UNKNOWN_CHUNKS
#define PNG_NO_READ_USER_TRANSFORM
#define PNG_READ_BGR_SUPPORTED
#define PNG_NO_READ_SWAP_ALPHA

Binary file not shown.

Binary file not shown.

BIN
srb2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -226,8 +226,7 @@ ifdef GCC61
WFLAGS+=-Wno-tautological-compare -Wno-error=tautological-compare
endif
ifdef GCC71
WFLAGS+=-Wno-error=implicit-fallthrough
WFLAGS+=-Wno-implicit-fallthrough
WFLAGS+=-Wimplicit-fallthrough=4
endif
ifdef GCC81
WFLAGS+=-Wno-error=format-overflow

View File

@ -62,7 +62,7 @@ static const UINT8 NOCLIMBYELLOWS = (11*16);
#define NOCLIMBCDWALLCOLORS NOCLIMBYELLOWS
#define THINGCOLORS GREENS
#define GRIDCOLORS (GRAYS + GRAYSRANGE/2)
#define XHAIRCOLORS GRAYS
#define XHAIRCOLORS DWHITE
// controls
#define AM_PANUPKEY KEY_UPARROW
@ -111,11 +111,6 @@ typedef struct
mpoint_t a, b;
} mline_t;
typedef struct
{
fixed_t slp, islp;
} islope_t;
//
// The vector graphics for the automap.
// A line drawing of the player pointing right,
@ -137,16 +132,14 @@ static const mline_t player_arrow[] = {
#undef R
#define NUMPLYRLINES (sizeof (player_arrow)/sizeof (mline_t))
#if 0
#define R (FRACUNIT)
static mline_t triangle_guy[] = {
{ { (fixed_t)-.867f*R, (fixed_t)-.5f*R }, { (fixed_t) .867f*R, (fixed_t)-.5f*R } },
{ { (fixed_t) .867f*R, (fixed_t)-.5f*R }, { (fixed_t) 0, (fixed_t) R } },
{ { (fixed_t) 0, (fixed_t) R }, { (fixed_t)-.867f*R, (fixed_t)-.5f*R } }
static const mline_t cross_mark[] =
{
{ { -R, 0 }, { R, 0} },
{ { 0, -R }, { 0, R } },
};
#undef R
#define NUMTRIANGLEGUYLINES (sizeof (triangle_guy)/sizeof (mline_t))
#endif
#define NUMCROSSMARKLINES (sizeof(cross_mark)/sizeof(mline_t))
#define R (FRACUNIT)
static const mline_t thintriangle_guy[] = {
@ -206,7 +199,7 @@ static fixed_t scale_ftom;
static player_t *plr; // the player represented by an arrow
static INT32 followplayer = true; // specifies whether to follow the player around
static boolean followplayer = true; // specifies whether to follow the player around
// function for drawing lines, depends on rendermode
typedef void (*AMDRAWFLINEFUNC) (const fline_t *fl, INT32 color);
@ -816,17 +809,18 @@ static void AM_drawGrid(INT32 color)
fixed_t x, y;
fixed_t start, end;
mline_t ml;
fixed_t gridsize = (MAPBLOCKUNITS<<MAPBITS);
// Figure out start of vertical gridlines
start = m_x;
if ((start - bmaporgx) % (MAPBLOCKUNITS<<FRACBITS))
start += (MAPBLOCKUNITS<<FRACBITS) - ((start - bmaporgx) % (MAPBLOCKUNITS<<FRACBITS));
if ((start - (bmaporgx>>FRACTOMAPBITS)) % gridsize)
start += gridsize - ((start - (bmaporgx>>FRACTOMAPBITS)) % gridsize);
end = m_x + m_w;
// draw vertical gridlines
ml.a.y = m_y;
ml.b.y = m_y + m_h;
for (x = start; x < end; x += (MAPBLOCKUNITS<<FRACBITS))
for (x = start; x < end; x += gridsize)
{
ml.a.x = x;
ml.b.x = x;
@ -835,14 +829,14 @@ static void AM_drawGrid(INT32 color)
// Figure out start of horizontal gridlines
start = m_y;
if ((start - bmaporgy) % (MAPBLOCKUNITS<<FRACBITS))
start += (MAPBLOCKUNITS<<FRACBITS) - ((start - bmaporgy) % (MAPBLOCKUNITS<<FRACBITS));
if ((start - (bmaporgy>>FRACTOMAPBITS)) % gridsize)
start += gridsize - ((start - (bmaporgy>>FRACTOMAPBITS)) % gridsize);
end = m_y + m_h;
// draw horizontal gridlines
ml.a.x = m_x;
ml.b.x = m_x + m_w;
for (y = start; y < end; y += (MAPBLOCKUNITS<<FRACBITS))
for (y = start; y < end; y += gridsize)
{
ml.a.y = y;
ml.b.y = y;
@ -1039,7 +1033,7 @@ static inline void AM_drawPlayers(void)
if (!multiplayer)
{
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, DWHITE, plr->mo->x, plr->mo->y);
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 16<<FRACBITS, plr->mo->angle, DWHITE, plr->mo->x, plr->mo->y);
return;
}
@ -1053,7 +1047,7 @@ static inline void AM_drawPlayers(void)
if (p->skincolor > 0)
color = R_GetTranslationColormap(TC_DEFAULT, p->skincolor, GTC_CACHE)[GREENS + 8];
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, color, p->mo->x, p->mo->y);
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 16<<FRACBITS, p->mo->angle, color, p->mo->x, p->mo->y);
}
}
@ -1073,13 +1067,30 @@ static inline void AM_drawThings(UINT8 colors)
}
}
/** Draws the crosshair, actually just a dot in software mode.
/** Draws the crosshair.
*
* \param color Color for the crosshair.
*/
static inline void AM_drawCrosshair(UINT8 color)
{
V_DrawFill(f_w/2 + f_x, f_h/2 + f_y, 1, 1, color|V_NOSCALESTART);
const fixed_t scale = 4<<FRACBITS;
size_t i;
fline_t fl;
for (i = 0; i < NUMCROSSMARKLINES; i++)
{
fl.a.x = FixedMul(cross_mark[i].a.x, scale) >> FRACBITS;
fl.a.y = FixedMul(cross_mark[i].a.y, scale) >> FRACBITS;
fl.b.x = FixedMul(cross_mark[i].b.x, scale) >> FRACBITS;
fl.b.y = FixedMul(cross_mark[i].b.y, scale) >> FRACBITS;
fl.a.x += f_x + (f_w / 2);
fl.a.y += f_y + (f_h / 2);
fl.b.x += f_x + (f_w / 2);
fl.b.y += f_y + (f_h / 2);
AM_drawFline(&fl, color);
}
}
/** Draws the automap.
@ -1095,5 +1106,5 @@ void AM_Drawer(void)
AM_drawPlayers();
AM_drawThings(THINGCOLORS);
AM_drawCrosshair(XHAIRCOLORS);
if (!followplayer) AM_drawCrosshair(XHAIRCOLORS);
}

View File

@ -26,11 +26,6 @@ typedef struct
fpoint_t a, b;
} fline_t;
// Used by ST StatusBar stuff.
#define AM_MSGHEADER (('a'<<24)+('m'<<16))
#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
extern boolean am_recalc; // true if screen size changes
extern boolean automapactive; // In AutoMap mode?

View File

@ -24,12 +24,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define APNG_H
#ifndef _MSC_VER
#ifndef _WII
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#endif
#endif
#ifndef _LFS64_LARGEFILE
#define _LFS64_LARGEFILE

View File

@ -140,6 +140,9 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin)
{
// don't try to do stuff if your sonic is in a minecart or something
if (players[consoleplayer].powers[pw_carry])
return;
// Turn the virtual keypresses into ticcmd_t.
if (twodlevel || mo->flags2 & MF2_TWOD) {
if (players[consoleplayer].climbing
@ -218,7 +221,12 @@ boolean B_CheckRespawn(player_t *player)
return false;
// Low ceiling, do not want!
if (sonic->ceilingz - sonic->z < 2*sonic->height)
if (sonic->eflags & MFE_VERTICALFLIP)
{
if (sonic->z - sonic->floorz < (sonic->player->exiting ? 5 : 2)*sonic->height)
return false;
}
else if (sonic->ceilingz - sonic->z < (sonic->player->exiting ? 6 : 3)*sonic->height)
return false;
// If you're dead, wait a few seconds to respawn.
@ -252,11 +260,11 @@ void B_RespawnBot(INT32 playernum)
y = sonic->y;
if (sonic->eflags & MFE_VERTICALFLIP) {
tails->eflags |= MFE_VERTICALFLIP;
z = sonic->z - FixedMul(512*FRACUNIT,sonic->scale);
z = sonic->z - (512*sonic->scale);
if (z < sonic->floorz)
z = sonic->floorz;
} else {
z = sonic->z + sonic->height + FixedMul(512*FRACUNIT,sonic->scale);
z = sonic->z + sonic->height + (512*sonic->scale);
if (z > sonic->ceilingz - sonic->height)
z = sonic->ceilingz - sonic->height;
}

View File

@ -49,6 +49,7 @@ static void COM_Exec_f(void);
static void COM_Wait_f(void);
static void COM_Help_f(void);
static void COM_Toggle_f(void);
static void COM_Add_f(void);
static void CV_EnforceExecVersion(void);
static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr);
@ -291,6 +292,7 @@ void COM_Init(void)
COM_AddCommand("wait", COM_Wait_f);
COM_AddCommand("help", COM_Help_f);
COM_AddCommand("toggle", COM_Toggle_f);
COM_AddCommand("add", COM_Add_f);
RegisterNetXCmd(XD_NETVAR, Got_NetVar);
}
@ -709,15 +711,21 @@ static void COM_Help_f(void)
if (COM_Argc() > 1)
{
cvar = CV_FindVar(COM_Argv(1));
const char *help = COM_Argv(1);
cvar = CV_FindVar(help);
if (cvar)
{
CONS_Printf(M_GetText("Variable %s:\n"), cvar->name);
boolean floatmode = false;
const char *cvalue = NULL;
CONS_Printf("\x82""Variable %s:\n", cvar->name);
CONS_Printf(M_GetText(" flags :"));
if (cvar->flags & CV_SAVE)
CONS_Printf("AUTOSAVE ");
if (cvar->flags & CV_FLOAT)
{
CONS_Printf("FLOAT ");
floatmode = true;
}
if (cvar->flags & CV_NETVAR)
CONS_Printf("NETVAR ");
if (cvar->flags & CV_CALL)
@ -727,59 +735,113 @@ static void COM_Help_f(void)
CONS_Printf("\n");
if (cvar->PossibleValue)
{
if (stricmp(cvar->PossibleValue[0].strvalue, "MIN") == 0)
{
for (i = 1; cvar->PossibleValue[i].strvalue != NULL; i++)
if (!stricmp(cvar->PossibleValue[i].strvalue, "MAX"))
break;
CONS_Printf(M_GetText(" range from %d to %d\n"), cvar->PossibleValue[0].value,
cvar->PossibleValue[i].value);
CONS_Printf(M_GetText(" Current value: %d\n"), cvar->value);
}
CONS_Printf(" Possible values:\n");
if (cvar->PossibleValue == CV_YesNo)
CONS_Printf(" Yes or No (On or Off, 1 or 0)\n");
else if (cvar->PossibleValue == CV_OnOff)
CONS_Printf(" On or Off (Yes or No, 1 or 0)\n");
else
{
const char *cvalue = NULL;
CONS_Printf(M_GetText(" possible value : %s\n"), cvar->name);
#define MINVAL 0
#define MAXVAL 1
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));
else
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[MINVAL].value,
cvar->PossibleValue[MAXVAL].value);
i = MAXVAL+1;
}
#undef MINVAL
#undef MAXVAL
//CONS_Printf(M_GetText(" possible value : %s\n"), cvar->name);
while (cvar->PossibleValue[i].strvalue)
{
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
cvar->PossibleValue[i].strvalue);
if (floatmode)
CONS_Printf(" %-2f : %s\n", FIXED_TO_FLOAT(cvar->PossibleValue[i].value),
cvar->PossibleValue[i].strvalue);
else
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
cvar->PossibleValue[i].strvalue);
if (cvar->PossibleValue[i].value == cvar->value)
cvalue = cvar->PossibleValue[i].strvalue;
i++;
}
if (cvalue)
CONS_Printf(M_GetText(" Current value: %s\n"), cvalue);
else
CONS_Printf(M_GetText(" Current value: %d\n"), cvar->value);
}
}
if (cvalue)
CONS_Printf(" Current value: %s\n", cvalue);
else if (cvar->string)
CONS_Printf(" Current value: %s\n", cvar->string);
else
CONS_Printf(M_GetText(" Current value: %d\n"), cvar->value);
CONS_Printf(" Current value: %d\n", cvar->value);
}
else
CONS_Printf(M_GetText("No help for this command/variable\n"));
{
for (cmd = com_commands; cmd; cmd = cmd->next)
{
if (strcmp(cmd->name, help))
continue;
CONS_Printf("\x82""Command %s:\n", cmd->name);
CONS_Printf(" help is not available for commands");
CONS_Printf("\x82""\nCheck wiki.srb2.org for more or try typing <name> without arguments\n");
return;
}
CONS_Printf("No exact match, searching...\n");
// variables
CONS_Printf("\x82""Variables:\n");
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if ((cvar->flags & CV_NOSHOWHELP) || (!strstr(cvar->name, help)))
continue;
CONS_Printf("%s ", cvar->name);
i++;
}
// commands
CONS_Printf("\x82""\nCommands:\n");
for (cmd = com_commands; cmd; cmd = cmd->next)
{
if (!strstr(cmd->name, help))
continue;
CONS_Printf("%s ",cmd->name);
i++;
}
CONS_Printf("\x82""\nCheck wiki.srb2.org for more or type help <command or variable>\n");
CONS_Debug(DBG_GAMELOGIC, "\x87Total : %d\n", i);
}
return;
}
else
{
// variables
CONS_Printf("\x82""Variables:\n");
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->flags & CV_NOSHOWHELP)
continue;
CONS_Printf("%s ", cvar->name);
i++;
}
// commands
CONS_Printf("\x82%s", M_GetText("Commands\n"));
CONS_Printf("\x82""\nCommands:\n");
for (cmd = com_commands; cmd; cmd = cmd->next)
{
CONS_Printf("%s ",cmd->name);
i++;
}
// variables
CONS_Printf("\n\x82%s", M_GetText("Variables\n"));
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (!(cvar->flags & CV_NOSHOWHELP))
CONS_Printf("%s ", cvar->name);
i++;
}
CONS_Printf("\n\x82%s", M_GetText("Read help file for more or type help <command or variable>\n"));
CONS_Printf("\x82""\nCheck wiki.srb2.org for more or type help <command or variable>\n");
CONS_Debug(DBG_GAMELOGIC, "\x82Total : %d\n", i);
}
@ -816,6 +878,30 @@ static void COM_Toggle_f(void)
CV_AddValue(cvar, +1);
}
/** Command variant of CV_AddValue
*/
static void COM_Add_f(void)
{
consvar_t *cvar;
if (COM_Argc() != 3)
{
CONS_Printf(M_GetText("Add <cvar_name> <value>: Add to the value of a cvar. Negative values work too!\n"));
return;
}
cvar = CV_FindVar(COM_Argv(1));
if (!cvar)
{
CONS_Alert(CONS_NOTICE, M_GetText("%s is not a cvar\n"), COM_Argv(1));
return;
}
if (( cvar->flags & CV_FLOAT ))
CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
else
CV_AddValue(cvar, atoi(COM_Argv(2)));
}
// =========================================================================
// VARIABLE SIZE BUFFERS
// =========================================================================
@ -1123,32 +1209,42 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
if (var->PossibleValue[0].strvalue && !stricmp(var->PossibleValue[0].strvalue, "MIN")) // bounded cvar
{
#define MINVAL 0
#define MAXVAL 1
INT32 i;
// search for maximum
for (i = 1; var->PossibleValue[i].strvalue; i++)
if (!stricmp(var->PossibleValue[i].strvalue, "MAX"))
break;
#ifdef PARANOIA
if (!var->PossibleValue[i].strvalue)
if (!var->PossibleValue[MAXVAL].strvalue)
I_Error("Bounded cvar \"%s\" without maximum!\n", var->name);
#endif
if ((v != INT32_MIN && v < var->PossibleValue[0].value) || !stricmp(valstr, "MIN"))
// search for other
for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++)
if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr))
{
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
}
if ((v != INT32_MIN && v < var->PossibleValue[MINVAL].value) || !stricmp(valstr, "MIN"))
{
v = var->PossibleValue[0].value;
valstr = var->PossibleValue[0].strvalue;
v = var->PossibleValue[MINVAL].value;
valstr = var->PossibleValue[MINVAL].strvalue;
override = true;
overrideval = v;
}
else if ((v != INT32_MIN && v > var->PossibleValue[i].value) || !stricmp(valstr, "MAX"))
else if ((v != INT32_MIN && v > var->PossibleValue[MAXVAL].value) || !stricmp(valstr, "MAX"))
{
v = var->PossibleValue[i].value;
valstr = var->PossibleValue[i].strvalue;
v = var->PossibleValue[MAXVAL].value;
valstr = var->PossibleValue[MAXVAL].strvalue;
override = true;
overrideval = v;
}
if (v == INT32_MIN)
goto badinput;
#undef MINVAL
#undef MAXVAL
}
else
{
@ -1515,6 +1611,9 @@ void CV_AddValue(consvar_t *var, INT32 increment)
{
INT32 newvalue, max;
if (!increment)
return;
// count pointlimit better
if (var == &cv_pointlimit && (gametype == GT_MATCH))
increment *= 50;
@ -1538,13 +1637,11 @@ void CV_AddValue(consvar_t *var, INT32 increment)
if (var->PossibleValue)
{
#define MINVAL 0
if (var == &cv_nextmap)
{
// Special case for the nextmap variable, used only directly from the menu
INT32 oldvalue = var->value - 1, gt;
gt = cv_newgametype.value;
if (increment != 0) // Going up!
{
newvalue = var->value - 1;
do
@ -1575,21 +1672,58 @@ void CV_AddValue(consvar_t *var, INT32 increment)
return;
}
}
#define MINVAL 0
#define MAXVAL 1
else if (var->PossibleValue[MINVAL].strvalue && !strcmp(var->PossibleValue[MINVAL].strvalue, "MIN"))
{
// search the next to last
for (max = 0; var->PossibleValue[max+1].strvalue; max++)
;
#ifdef PARANOIA
if (!var->PossibleValue[MAXVAL].strvalue)
I_Error("Bounded cvar \"%s\" without maximum!\n", var->name);
#endif
if (newvalue < var->PossibleValue[MINVAL].value) // add the max+1
newvalue += var->PossibleValue[max].value - var->PossibleValue[MINVAL].value + 1;
if (newvalue < var->PossibleValue[MINVAL].value || newvalue > var->PossibleValue[MAXVAL].value)
{
INT32 currentindice = -1, newindice;
for (max = MAXVAL+1; var->PossibleValue[max].strvalue; max++)
{
if (var->PossibleValue[max].value == newvalue)
{
increment = 0;
currentindice = max;
}
else if (var->PossibleValue[max].value == var->value)
currentindice = max;
}
newvalue = var->PossibleValue[MINVAL].value + (newvalue - var->PossibleValue[MINVAL].value)
% (var->PossibleValue[max].value - var->PossibleValue[MINVAL].value + 1);
if (increment)
{
increment = (increment > 0) ? 1 : -1;
if (currentindice == -1 && max != MAXVAL+1)
newindice = ((increment > 0) ? MAXVAL : max) + increment;
else
newindice = currentindice + increment;
CV_SetValue(var, newvalue);
#undef MINVAL
if (newindice >= max || newindice <= MAXVAL)
{
if (var == &cv_pointlimit && (gametype == GT_MATCH) && increment > 0)
CV_SetValue(var, 50);
else
{
newvalue = var->PossibleValue[((increment > 0) ? MINVAL : MAXVAL)].value;
CV_SetValue(var, newvalue);
}
}
else
CV_Set(var, var->PossibleValue[newindice].strvalue);
}
else
CV_Set(var, var->PossibleValue[currentindice].strvalue);
}
else
CV_SetValue(var, newvalue);
}
#undef MINVAL
#undef MAXVAL
else
{
INT32 currentindice = -1, newindice;
@ -1599,8 +1733,6 @@ void CV_AddValue(consvar_t *var, INT32 increment)
if (var->PossibleValue[max].value == var->value)
currentindice = max;
max--;
if (var == &cv_chooseskin)
{
// Special case for the chooseskin variable, used only directly from the menu
@ -1632,7 +1764,7 @@ void CV_AddValue(consvar_t *var, INT32 increment)
var->value);
#endif
newindice = (currentindice + increment + max + 1) % (max+1);
newindice = (currentindice + increment + max) % max;
CV_Set(var, var->PossibleValue[newindice].strvalue);
}
}
@ -1666,7 +1798,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (joyaxis_default)
{
#if !defined (_WII) && !defined (WMINPUT)
if (!stricmp(v->name, "joyaxis_turn"))
{
if (joyaxis_count > 6) return false;
@ -1676,7 +1807,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "X-Axis")) joyaxis_count++;
else joyaxis_default = false;
}
#if !defined (PSP)
if (!stricmp(v->name, "joyaxis_move"))
{
if (joyaxis_count > 6) return false;
@ -1685,8 +1815,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "Y-Axis")) joyaxis_count++;
else joyaxis_default = false;
}
#endif
#if !defined (_arch_dreamcast) && !defined (_XBOX) && !defined (PSP)
if (!stricmp(v->name, "joyaxis_side"))
{
if (joyaxis_count > 6) return false;
@ -1695,8 +1823,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "Z-Axis")) joyaxis_count++;
else joyaxis_default = false;
}
#endif
#if !defined (_XBOX) && !defined (PSP)
if (!stricmp(v->name, "joyaxis_look"))
{
if (joyaxis_count > 6) return false;
@ -1705,7 +1831,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "None")) joyaxis_count++;
else joyaxis_default = false;
}
#endif
if (!stricmp(v->name, "joyaxis_fire")
|| !stricmp(v->name, "joyaxis_firenormal"))
{
@ -1715,7 +1840,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "None")) joyaxis_count++;
else joyaxis_default = false;
}
#endif
// reset all axis settings to defaults
if (joyaxis_count == 6)
{
@ -1732,7 +1856,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (joyaxis2_default)
{
#if !defined (_WII) && !defined (WMINPUT)
if (!stricmp(v->name, "joyaxis2_turn"))
{
if (joyaxis2_count > 6) return false;
@ -1742,7 +1865,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "X-Axis")) joyaxis2_count++;
else joyaxis2_default = false;
}
// #if !defined (PSP)
if (!stricmp(v->name, "joyaxis2_move"))
{
if (joyaxis2_count > 6) return false;
@ -1751,8 +1873,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "Y-Axis")) joyaxis2_count++;
else joyaxis2_default = false;
}
// #endif
#if !defined (_arch_dreamcast) && !defined (_XBOX) && !defined (PSP)
if (!stricmp(v->name, "joyaxis2_side"))
{
if (joyaxis2_count > 6) return false;
@ -1761,8 +1881,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "Z-Axis")) joyaxis2_count++;
else joyaxis2_default = false;
}
#endif
#if !defined (_XBOX) // && !defined (PSP)
if (!stricmp(v->name, "joyaxis2_look"))
{
if (joyaxis2_count > 6) return false;
@ -1771,7 +1889,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "None")) joyaxis2_count++;
else joyaxis2_default = false;
}
#endif
if (!stricmp(v->name, "joyaxis2_fire")
|| !stricmp(v->name, "joyaxis2_firenormal"))
{
@ -1781,7 +1898,6 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
if (!stricmp(valstr, "None")) joyaxis2_count++;
else joyaxis2_default = false;
}
#endif
// reset all axis settings to defaults
if (joyaxis2_count == 6)

View File

@ -175,11 +175,11 @@ static void CONS_Clear_f(void)
// Choose english keymap
//
static void CONS_English_f(void)
/*static void CONS_English_f(void)
{
shiftxform = english_shiftxform;
CONS_Printf(M_GetText("%s keymap.\n"), M_GetText("English"));
}
}*/
static char *bindtable[NUMINPUTS];
@ -394,7 +394,7 @@ void CON_Init(void)
// register our commands
//
COM_AddCommand("cls", CONS_Clear_f);
COM_AddCommand("english", CONS_English_f);
//COM_AddCommand("english", CONS_English_f);
// set console full screen for game startup MAKE SURE VID_Init() done !!!
con_destlines = vid.height;
con_curlines = vid.height;

View File

@ -42,6 +42,7 @@
#include "lzf.h"
#include "lua_script.h"
#include "lua_hook.h"
#include "md5.h"
#ifdef CLIENT_LOADINGSCREEN
// cl loading screen
@ -82,11 +83,9 @@ tic_t jointimeout = (10*TICRATE);
static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
#ifdef NEWPING
UINT16 pingmeasurecount = 1;
UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone.
UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values.
#endif
SINT8 nodetoplayer[MAXNETNODES];
SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen
@ -110,6 +109,9 @@ static UINT8 resynch_local_inprogress = false; // WE are desynched and getting p
static UINT8 player_joining = false;
UINT8 hu_resynching = 0;
UINT8 adminpassmd5[16];
boolean adminpasswordset = false;
// Client specific
static ticcmd_t localcmds;
static ticcmd_t localcmds2;
@ -148,7 +150,7 @@ ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL};
static consvar_t cv_showjoinaddress = {"showjoinaddress", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}};
consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -509,6 +511,10 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->currentweapon = LONG(players[i].currentweapon);
rsp->ringweapons = LONG(players[i].ringweapons);
rsp->ammoremoval = (UINT16)SHORT(players[i].ammoremoval);
rsp->ammoremovaltimer = (tic_t)LONG(players[i].ammoremovaltimer);
rsp->ammoremovalweapon = LONG(players[i].ammoremovalweapon);
for (j = 0; j < NUMPOWERS; ++j)
rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]);
@ -571,6 +577,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->starpostnum = LONG(players[i].starpostnum);
rsp->starposttime = (tic_t)LONG(players[i].starposttime);
rsp->starpostangle = (angle_t)LONG(players[i].starpostangle);
rsp->starpostscale = (fixed_t)LONG(players[i].starpostscale);
rsp->maxlink = LONG(players[i].maxlink);
rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed);
@ -612,6 +619,10 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->friction = LONG(players[i].mo->friction);
rsp->movefactor = LONG(players[i].mo->movefactor);
rsp->sprite = (spritenum_t)LONG(players[i].mo->sprite);
rsp->frame = LONG(players[i].mo->frame);
rsp->sprite2 = players[i].mo->sprite2;
rsp->anim_duration = SHORT(players[i].mo->anim_duration);
rsp->tics = LONG(players[i].mo->tics);
rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :(
rsp->eflags = (UINT16)SHORT(players[i].mo->eflags);
@ -640,6 +651,10 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].currentweapon = LONG(rsp->currentweapon);
players[i].ringweapons = LONG(rsp->ringweapons);
players[i].ammoremoval = (UINT16)SHORT(rsp->ammoremoval);
players[i].ammoremovaltimer = (tic_t)LONG(rsp->ammoremovaltimer);
players[i].ammoremovalweapon = LONG(rsp->ammoremovalweapon);
for (j = 0; j < NUMPOWERS; ++j)
players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]);
@ -702,6 +717,7 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].starpostnum = LONG(rsp->starpostnum);
players[i].starposttime = (tic_t)LONG(rsp->starposttime);
players[i].starpostangle = (angle_t)LONG(rsp->starpostangle);
players[i].starpostscale = (fixed_t)LONG(rsp->starpostscale);
players[i].maxlink = LONG(rsp->maxlink);
players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed);
@ -753,8 +769,17 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].mo->momy = LONG(rsp->momy);
players[i].mo->momz = LONG(rsp->momz);
players[i].mo->movefactor = LONG(rsp->movefactor);
// Don't use P_SetMobjStateNF to restore state, write/read all the values manually!
// This should stop those stupid console errors, hopefully.
// -- Monster Iestyn
players[i].mo->sprite = (spritenum_t)LONG(rsp->sprite);
players[i].mo->frame = LONG(rsp->frame);
players[i].mo->sprite2 = rsp->sprite2;
players[i].mo->anim_duration = SHORT(rsp->anim_duration);
players[i].mo->tics = LONG(rsp->tics);
P_SetMobjStateNF(players[i].mo, LONG(rsp->statenum));
players[i].mo->state = &states[LONG(rsp->statenum)];
players[i].mo->x = LONG(rsp->x);
players[i].mo->y = LONG(rsp->y);
players[i].mo->z = LONG(rsp->z);
@ -1239,7 +1264,8 @@ static boolean CL_SendJoin(void)
netbuffer->u.clientcfg.localplayers = localplayers;
netbuffer->u.clientcfg.version = VERSION;
netbuffer->u.clientcfg.subversion = SUBVERSION;
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));
}
@ -1298,33 +1324,13 @@ static void SV_SendPlayerInfo(INT32 node)
continue;
}
netbuffer->u.playerinfo[i].node = (UINT8)playernode[i];
netbuffer->u.playerinfo[i].node = i;
strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1);
netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0';
//fetch IP address
{
const char *claddress;
UINT32 numericaddress[4];
memset(netbuffer->u.playerinfo[i].address, 0, 4);
if (playernode[i] == 0)
{
//127.0.0.1
netbuffer->u.playerinfo[i].address[0] = 127;
netbuffer->u.playerinfo[i].address[3] = 1;
}
else if (playernode[i] > 0 && I_GetNodeAddress && (claddress = I_GetNodeAddress(playernode[i])) != NULL)
{
if (sscanf(claddress, "%d.%d.%d.%d", &numericaddress[0], &numericaddress[1], &numericaddress[2], &numericaddress[3]) < 4)
goto badaddress;
netbuffer->u.playerinfo[i].address[0] = (UINT8)numericaddress[0];
netbuffer->u.playerinfo[i].address[1] = (UINT8)numericaddress[1];
netbuffer->u.playerinfo[i].address[2] = (UINT8)numericaddress[2];
netbuffer->u.playerinfo[i].address[3] = (UINT8)numericaddress[3];
}
}
badaddress:
//No, don't do that, you fuckface.
memset(netbuffer->u.playerinfo[i].address, 0, 4);
if (G_GametypeHasTeams())
{
@ -2403,7 +2409,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
// the remaining players.
if (G_IsSpecialStage(gamemap))
{
INT32 i, count, increment, spheres;
INT32 i, count, sincrement, spheres, rincrement, rings;
for (i = 0, count = 0; i < MAXPLAYERS; i++)
{
@ -2413,18 +2419,35 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
count--;
spheres = players[playernum].spheres;
increment = spheres/count;
rings = players[playernum].rings;
sincrement = spheres/count;
rincrement = rings/count;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && i != playernum)
{
if (spheres < increment)
if (spheres < 2*sincrement)
{
P_GivePlayerSpheres(&players[i], spheres);
spheres = 0;
}
else
P_GivePlayerSpheres(&players[i], increment);
{
P_GivePlayerSpheres(&players[i], sincrement);
spheres -= sincrement;
}
spheres -= increment;
if (rings < 2*rincrement)
{
P_GivePlayerRings(&players[i], rings);
rings = 0;
}
else
{
P_GivePlayerRings(&players[i], rincrement);
rings -= rincrement;
}
}
}
}
@ -2839,12 +2862,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
kickreason = KR_KICK;
break;
#ifdef NEWPING
case KICK_MSG_PING_HIGH:
HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false);
kickreason = KR_PINGLIMIT;
break;
#endif
case KICK_MSG_CON_FAIL:
HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false);
kickreason = KR_SYNCH;
@ -2917,10 +2938,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
D_StartTitle();
if (msg == KICK_MSG_CON_FAIL)
M_StartMessage(M_GetText("Server closed connection\n(synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
#ifdef NEWPING
else if (msg == KICK_MSG_PING_HIGH)
M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING);
#endif
else if (msg == KICK_MSG_BANNED)
M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
else if (msg == KICK_MSG_CUSTOM_KICK)
@ -2934,13 +2953,13 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
CL_RemovePlayer(pnum, kickreason);
}
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|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 resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}};
consvar_t cv_resynchattempts = {"resynchattempts", "10", 0, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_blamecfail = {"blamecfail", "Off", 0, CV_OnOff, 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 };
// max file size to send to a player (in kilobytes)
static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}};
@ -2981,11 +3000,6 @@ void D_ClientServerInit(void)
RegisterNetXCmd(XD_KICK, Got_KickCmd);
RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer);
CV_RegisterVar(&cv_joinnextround);
CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_blamecfail);
#ifdef DUMPCONSISTENCY
CV_RegisterVar(&cv_dumpconsistency);
#endif
@ -3173,6 +3187,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (!splitscreen && !botingame)
CL_ClearPlayer(newplayernum);
playeringame[newplayernum] = true;
READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME);
G_AddPlayer(newplayernum);
if (newplayernum+1 > doomcom->numslots)
doomcom->numslots = (INT16)(newplayernum+1);
@ -3205,10 +3220,10 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
{
const char *address;
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
HU_AddChatText(va("\x82*Player %d has joined the game (node %d) (%s)", newplayernum+1, node, address), false); // merge join notification + IP to avoid clogging console/chat.
HU_AddChatText(va("\x82*%s has joined the game (node %d) (%s)", player_names[newplayernum], node, address), false); // merge join notification + IP to avoid clogging console/chat.
}
else
HU_AddChatText(va("\x82*Player %d has joined the game (node %d)", newplayernum+1, node), false); // if you don't wanna see the join address.
HU_AddChatText(va("\x82*%s has joined the game (node %d)", player_names[newplayernum], node), false); // if you don't wanna see the join address.
}
if (server && multiplayer && motd[0] != '\0')
@ -3219,10 +3234,11 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
#endif
}
static boolean SV_AddWaitingPlayers(void)
static boolean SV_AddWaitingPlayers(const char *name, const char *name2)
{
INT32 node, n, newplayer = false;
UINT8 buf[2];
UINT8 buf[2 + MAXPLAYERNAME];
UINT8 *p;
UINT8 newplayernum = 0;
// What is the reason for this? Why can't newplayernum always be 0?
@ -3305,18 +3321,23 @@ static boolean SV_AddWaitingPlayers(void)
playernode[newplayernum] = (UINT8)node;
p = buf + 2;
buf[0] = (UINT8)node;
buf[1] = newplayernum;
if (playerpernode[node] < 1)
{
nodetoplayer[node] = newplayernum;
WRITESTRINGN(p, name, MAXPLAYERNAME);
}
else
{
nodetoplayer2[node] = newplayernum;
buf[1] |= 0x80;
WRITESTRINGN(p, name2, MAXPLAYERNAME);
}
playerpernode[node]++;
SendNetXCmd(XD_ADDPLAYER, &buf, 2);
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)
@ -3378,7 +3399,7 @@ boolean SV_SpawnServer(void)
else doomcom->numslots = 1;
}
return SV_AddWaitingPlayers();
return SV_AddWaitingPlayers(cv_playername.zstring, cv_playername2.zstring);
}
void SV_StopServer(void)
@ -3449,6 +3470,9 @@ static size_t TotalTextCmdPerTic(tic_t tic)
*/
static void HandleConnect(SINT8 node)
{
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1];
INT32 i;
if (bannednode && bannednode[node])
SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
else if (netbuffer->u.clientcfg.version != VERSION
@ -3468,6 +3492,16 @@ static void HandleConnect(SINT8 node)
boolean newnode = false;
#endif
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))
{
SV_SendRefuse(node, "Bad player name");
return;
}
}
// client authorised to join
nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]);
if (!nodeingame[node])
@ -3508,7 +3542,7 @@ static void HandleConnect(SINT8 node)
SV_SendSaveGame(node); // send a complete game state
DEBFILE("send savegame\n");
}
SV_AddWaitingPlayers();
SV_AddWaitingPlayers(names[0], names[1]);
player_joining = true;
}
#else
@ -3784,6 +3818,7 @@ static void HandlePacketFromPlayer(SINT8 node)
INT32 netconsole;
tic_t realend, realstart;
UINT8 *pak, *txtpak, numtxtpak;
UINT8 finalmd5[16];/* Well, it's the cool thing to do? */
txtpak = NULL;
@ -3814,7 +3849,7 @@ static void HandlePacketFromPlayer(SINT8 node)
break;
// Ignore tics from those not synched
if (resynch_inprogress[node])
if (resynch_inprogress[node] && nettics[node] == gametic)
break;
// To save bytes, only the low byte of tic numbers are sent
@ -3981,6 +4016,32 @@ static void HandlePacketFromPlayer(SINT8 node)
textcmd[0] += (UINT8)netbuffer->u.textcmd[0];
}
break;
case PT_LOGIN:
if (client)
break;
#ifndef NOMD5
if (doomcom->datalength < 16)/* ignore partial sends */
break;
if (!adminpasswordset)
{
CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]);
break;
}
// Do the final pass to compare with the sent md5
D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", netconsole), &finalmd5);
if (!memcmp(netbuffer->u.md5sum, finalmd5, 16))
{
CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]);
COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately
}
else
CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]);
#endif
break;
case PT_NODETIMEOUT:
case PT_CLIENTQUIT:
if (client)
@ -4122,7 +4183,6 @@ static void HandlePacketFromPlayer(SINT8 node)
resynch_local_inprogress = true;
CL_AcknowledgeResynch(&netbuffer->u.resynchpak);
break;
#ifdef NEWPING
case PT_PING:
// Only accept PT_PING from the server.
if (node != servernode)
@ -4150,7 +4210,6 @@ static void HandlePacketFromPlayer(SINT8 node)
}
break;
#endif
case PT_SERVERCFG:
break;
case PT_FILEFRAGMENT:
@ -4646,7 +4705,7 @@ void TryRunTics(tic_t realtics)
if (player_joining)
return;
if (neededtic > gametic)
if (neededtic > gametic && !resynch_local_inprogress)
{
if (advancedemo)
D_StartTitle();
@ -4664,7 +4723,6 @@ void TryRunTics(tic_t realtics)
}
}
#ifdef NEWPING
static inline void PingUpdate(void)
{
INT32 i;
@ -4722,7 +4780,6 @@ static inline void PingUpdate(void)
pingmeasurecount = 1; //Reset count
}
#endif
void NetUpdate(void)
{
@ -4747,7 +4804,6 @@ void NetUpdate(void)
gametime = nowtime;
#ifdef NEWPING
if (server)
{
if (netgame && !(gametime % 255))
@ -4758,7 +4814,6 @@ void NetUpdate(void)
realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
pingmeasurecount++;
}
#endif
if (client)
maketic = neededtic;
@ -4800,8 +4855,13 @@ void NetUpdate(void)
for (i = 0; i < MAXNETNODES; ++i)
if (resynch_inprogress[i])
{
SV_SendResynch(i);
counts = -666;
if (!nodeingame[i] || nettics[i] == gametic)
{
SV_SendResynch(i);
counts = -666;
}
else
counts = 0; // Let the client catch up with the server
}
// Do not make tics while resynching
@ -4858,3 +4918,29 @@ tic_t GetLag(INT32 node)
{
return gametic - nettics[node];
}
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest)
{
#ifdef NOMD5
(void)buffer;
(void)len;
(void)salt;
memset(dest, 0, 16);
#else
char tmpbuf[256];
const size_t sl = strlen(salt);
if (len > 256-sl)
len = 256-sl;
memcpy(tmpbuf, buffer, len);
memmove(&tmpbuf[len], salt, sl);
//strcpy(&tmpbuf[len], salt);
len += strlen(salt);
if (len < 256)
memset(&tmpbuf[len],0,256-len);
// Yes, we intentionally md5 the ENTIRE buffer regardless of size...
md5_buffer(tmpbuf, 256, dest);
#endif
}

View File

@ -15,6 +15,7 @@
#include "d_ticcmd.h"
#include "d_netcmd.h"
#include "d_net.h"
#include "tables.h"
#include "d_player.h"
@ -70,9 +71,10 @@ typedef enum
PT_NODETIMEOUT, // Packet sent to self if the connection times out.
PT_RESYNCHING, // Packet sent to resync players.
// Blocks game advance until synched.
#ifdef NEWPING
PT_LOGIN, // Login attempt from the client.
PT_PING, // Packet sent to tell clients the other client's latency to server.
#endif
NUMPACKETTYPE
} packettype_t;
@ -161,6 +163,9 @@ typedef struct
angle_t aiming;
INT32 currentweapon;
INT32 ringweapons;
UINT16 ammoremoval;
tic_t ammoremovaltimer;
INT32 ammoremovalweapon;
UINT16 powers[NUMPOWERS];
// Score is resynched in the confirm resync packet
@ -222,6 +227,7 @@ typedef struct
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
fixed_t starpostscale;
INT32 maxlink;
fixed_t dashspeed;
@ -258,6 +264,10 @@ typedef struct
fixed_t friction;
fixed_t movefactor;
spritenum_t sprite;
UINT32 frame;
UINT8 sprite2;
UINT16 anim_duration;
INT32 tics;
statenum_t statenum;
UINT32 flags;
@ -315,6 +325,7 @@ typedef struct
UINT8 subversion; // Contains build version
UINT8 localplayers;
UINT8 mode;
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
} ATTRPACK clientconfig_pak;
#define MAXSERVERNAME 32
@ -407,15 +418,14 @@ typedef struct
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
filetx_pak filetxpak; // 139 bytes
clientconfig_pak clientcfg; // 136 bytes
UINT8 md5sum[16];
serverinfo_pak serverinfo; // 1024 bytes
serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
askinfo_pak askinfo; // 61 bytes
msaskinfo_pak msaskinfo; // 22 bytes
plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes (I'd say 36~38)
plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE)
#ifdef NEWPING
UINT32 pingtable[MAXPLAYERS]; // 128 bytes
#endif
} u; // This is needed to pack diff packet types data together
} ATTRPACK doomdata_t;
@ -437,6 +447,7 @@ extern INT32 mapchangepending;
// Points inside doomcom
extern doomdata_t *netbuffer;
extern consvar_t cv_showjoinaddress;
extern consvar_t cv_playbackspeed;
#define BASEPACKETSIZE offsetof(doomdata_t, u)
@ -448,9 +459,7 @@ extern consvar_t cv_playbackspeed;
#define KICK_MSG_PLAYER_QUIT 3
#define KICK_MSG_TIMEOUT 4
#define KICK_MSG_BANNED 5
#ifdef NEWPING
#define KICK_MSG_PING_HIGH 6
#endif
#define KICK_MSG_CUSTOM_KICK 7
#define KICK_MSG_CUSTOM_BAN 8
@ -475,11 +484,9 @@ extern SINT8 servernode;
void Command_Ping_f(void);
extern tic_t connectiontimeout;
extern tic_t jointimeout;
#ifdef NEWPING
extern UINT16 pingmeasurecount;
extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS];
#endif
extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;
@ -535,5 +542,10 @@ void D_ResetTiccmds(void);
tic_t GetLag(INT32 node);
UINT8 GetFreeXCmdSize(void);
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
extern UINT8 hu_resynching;
extern UINT8 adminpassmd5[16];
extern boolean adminpasswordset;
#endif

View File

@ -129,6 +129,7 @@ char srb2home[256] = ".";
char srb2path[256] = ".";
boolean usehome = true;
const char *pandf = "%s" PATHSEP "%s";
static char addonsdir[MAX_WADPATH];
//
// EVENT HANDLING
@ -287,7 +288,7 @@ static void D_Display(void)
F_TitleScreenDrawer();
break;
}
// Intentional fall-through
/* FALLTHRU */
case GS_LEVEL:
if (!gametic)
break;
@ -358,7 +359,7 @@ static void D_Display(void)
// clean up border stuff
// see if the border needs to be initially drawn
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide))
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap)))
{
// draw the view directly
@ -716,6 +717,7 @@ void D_StartTitle(void)
botskin = 0;
cv_debug = 0;
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
lastmaploaded = 0;
// In case someone exits out at the same time they start a time attack run,
@ -1038,7 +1040,6 @@ void D_SRB2Main(void)
// can't use sprintf since there is %u in savegamename
strcatbf(savegamename, srb2home, PATHSEP);
I_mkdir(srb2home, 0700);
#else
snprintf(srb2home, sizeof srb2home, "%s", userhome);
snprintf(downloaddir, sizeof downloaddir, "%s", userhome);
@ -1055,6 +1056,10 @@ void D_SRB2Main(void)
configfile[sizeof configfile - 1] = '\0';
}
// Create addons dir
snprintf(addonsdir, sizeof addonsdir, "%s%s%s", srb2home, PATHSEP, "addons");
I_mkdir(addonsdir, 0755);
// rand() needs seeded regardless of password
srand((unsigned int)time(NULL));
@ -1239,24 +1244,40 @@ void D_SRB2Main(void)
sound_disabled = true;
midi_disabled = digital_disabled = true;
}
if (M_CheckParm("-noaudio")) // combines -nosound and -nomusic
{
sound_disabled = true;
digital_disabled = true;
midi_disabled = true;
}
else
{
if (M_CheckParm("-nosound"))
sound_disabled = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
{
digital_disabled = true;
midi_disabled = true;
}
else
{
if (M_CheckParm("-nomidimusic"))
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
if (M_CheckParm("-nodigmusic"))
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
}
}
if (!( sound_disabled && digital_disabled
#ifndef NO_MIDI
&& midi_disabled
#endif
))
{
CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
I_StartupSound();
I_InitMusic();
S_InitSfxChannels(cv_soundvolume.value);
}
if (M_CheckParm("-nosound"))
sound_disabled = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
midi_disabled = digital_disabled = true;
else
{
if (M_CheckParm("-nomidimusic"))
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
if (M_CheckParm("-nodigmusic"))
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
}
I_StartupSound();
I_InitMusic();
S_InitSfxChannels(cv_soundvolume.value);
CONS_Printf("ST_Init(): Init status bar.\n");
ST_Init();

View File

@ -185,22 +185,10 @@ typedef struct
UINT8 nextacknum;
UINT8 flags;
#ifndef NEWPING
// jacobson tcp timeout evaluation algorithm (Karn variation)
fixed_t ping;
fixed_t varping;
INT32 timeout; // computed with ping and varping
#endif
} node_t;
static node_t nodes[MAXNETNODES];
#ifndef NEWPING
#define PINGDEFAULT ((200*TICRATE*FRACUNIT)/1000)
#define VARPINGDEFAULT ((50*TICRATE*FRACUNIT)/1000)
#define TIMEOUT(p,v) (p+4*v+FRACUNIT/2)>>FRACBITS;
#else
#define NODETIMEOUT 14 //What the above boiled down to...
#endif
#define NODETIMEOUT 14
#ifndef NONET
// return <0 if a < b (mod 256)
@ -320,19 +308,7 @@ static UINT8 GetAcktosend(INT32 node)
static void RemoveAck(INT32 i)
{
INT32 node = ackpak[i].destinationnode;
#ifndef NEWPING
fixed_t trueping = (I_GetTime() - ackpak[i].senttime)<<FRACBITS;
if (ackpak[i].resentnum)
{
// +FRACUNIT/2 for round
nodes[node].ping = (nodes[node].ping*7 + trueping)/8;
nodes[node].varping = (nodes[node].varping*7 + abs(nodes[node].ping-trueping))/8;
nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping);
}
DEBFILE(va("Remove ack %d trueping %d ping %f var %f timeout %d\n",ackpak[i].acknum,trueping>>FRACBITS,(double)FIXED_TO_FLOAT(nodes[node].ping),(double)FIXED_TO_FLOAT(nodes[node].varping),nodes[node].timeout));
#else
DEBFILE(va("Remove ack %d\n",ackpak[i].acknum));
#endif
ackpak[i].acknum = 0;
if (nodes[node].flags & NF_CLOSE)
Net_CloseConnection(node);
@ -519,11 +495,7 @@ void Net_AckTicker(void)
{
const INT32 nodei = ackpak[i].destinationnode;
node_t *node = &nodes[nodei];
#ifdef NEWPING
if (ackpak[i].acknum && ackpak[i].senttime + NODETIMEOUT < I_GetTime())
#else
if (ackpak[i].acknum && ackpak[i].senttime + node->timeout < I_GetTime())
#endif
{
if (ackpak[i].resentnum > 10 && (node->flags & NF_CLOSE))
{
@ -534,13 +506,8 @@ void Net_AckTicker(void)
ackpak[i].acknum = 0;
continue;
}
#ifdef NEWPING
DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
NODETIMEOUT, I_GetTime()));
#else
DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
node->timeout, I_GetTime()));
#endif
M_Memcpy(netbuffer, ackpak[i].pak.raw, ackpak[i].length);
ackpak[i].senttime = I_GetTime();
ackpak[i].resentnum++;
@ -658,11 +625,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
static void InitNode(node_t *node)
{
node->acktosend_head = node->acktosend_tail = 0;
#ifndef NEWPING
node->ping = PINGDEFAULT;
node->varping = VARPINGDEFAULT;
node->timeout = TIMEOUT(node->ping, node->varping);
#endif
node->firstacktosend = 0;
node->nextacknum = 1;
node->remotefirstack = 0;
@ -843,9 +805,7 @@ static const char *packettypename[NUMPACKETTYPE] =
"CLIENTJOIN",
"NODETIMEOUT",
"RESYNCHING",
#ifdef NEWPING
"PING"
#endif
};
static void DebugPrintpacket(const char *header)
@ -1384,30 +1344,73 @@ boolean D_CheckNetGame(void)
return ret;
}
struct pingcell
{
INT32 num;
INT32 ms;
};
static int pingcellcmp(const void *va, const void *vb)
{
const struct pingcell *a, *b;
a = va;
b = vb;
return ( a->ms - b->ms );
}
/*
New ping command formatted nicely to present ping in
ascending order. And with equally spaced columns.
The caller's ping is presented at the bottom too, for
convenience.
*/
void Command_Ping_f(void)
{
#ifndef NEWPING
if(server)
struct pingcell pingv[MAXPLAYERS];
INT32 pingc;
int name_width = 0;
int ms_width = 0;
int n;
INT32 i;
pingc = 0;
for (i = 1; i < MAXPLAYERS; ++i)
if (playeringame[i])
{
#endif
INT32 i;
for (i = 0; i < MAXPLAYERS;i++)
{
#ifndef NEWPING
const INT32 node = playernode[i];
if (playeringame[i] && node != 0)
CONS_Printf(M_GetText("%.2d : %s\n %d tics, %d ms.\n"), i, player_names[i],
GetLag(node), G_TicsToMilliseconds(GetLag(node)));
#else
if (playeringame[i] && i != 0)
CONS_Printf(M_GetText("%.2d : %s\n %d ms\n"), i, player_names[i], playerpingtable[i]);
#endif
}
#ifndef NEWPING
n = strlen(player_names[i]);
if (n > name_width)
name_width = n;
n = playerpingtable[i];
if (n > ms_width)
ms_width = n;
pingv[pingc].num = i;
pingv[pingc].ms = playerpingtable[i];
pingc++;
}
if (ms_width < 10) ms_width = 1;
else if (ms_width < 100) ms_width = 2;
else ms_width = 3;
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
for (i = 0; i < pingc; ++i)
{
CONS_Printf("%02d : %-*s %*d ms\n",
pingv[i].num,
name_width, player_names[pingv[i].num],
ms_width, pingv[i].ms);
}
if (!server && playeringame[consoleplayer])
{
CONS_Printf("\nYour ping is %d ms\n", playerpingtable[consoleplayer]);
}
else
CONS_Printf(M_GetText("Only the server can use this.\n"));
#endif
}
void D_CloseConnection(void)

View File

@ -34,18 +34,19 @@
#include "p_spec.h"
#include "m_cheat.h"
#include "d_clisrv.h"
#include "d_net.h"
#include "v_video.h"
#include "d_main.h"
#include "m_random.h"
#include "f_finale.h"
#include "filesrch.h"
#include "mserv.h"
#include "md5.h"
#include "z_zone.h"
#include "lua_script.h"
#include "lua_hook.h"
#include "m_cond.h"
#include "m_anigif.h"
#include "md5.h"
#ifdef NETGAME_DEVMODE
#define CV_RESTRICT CV_NETVAR
@ -73,6 +74,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum);
static void PointLimit_OnChange(void);
static void TimeLimit_OnChange(void);
static void NumLaps_OnChange(void);
static void BaseNumLaps_OnChange(void);
static void Mute_OnChange(void);
static void Hidetime_OnChange(void);
@ -140,7 +142,6 @@ static void Command_Clearscores_f(void);
// Remote Administration
static void Command_Changepassword_f(void);
static void Command_Login_f(void);
static void Got_Login(UINT8 **cp, INT32 playernum);
static void Got_Verification(UINT8 **cp, INT32 playernum);
static void Got_Removal(UINT8 **cp, INT32 playernum);
static void Command_Verify_f(void);
@ -210,7 +211,7 @@ consvar_t cv_allowteamchange = {"allowteamchange", "Yes", CV_NETVAR, CV_YesNo, N
consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t respawntime_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}};
static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}};
consvar_t cv_respawntime = {"respawndelay", "3", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_competitionboxes = {"competitionboxes", "Mystery", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -246,20 +247,20 @@ INT32 cv_debug;
consvar_t cv_usemouse = {"use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t,
consvar_t cv_usejoystick = {"use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t,
I_InitJoystick, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t,
consvar_t cv_usejoystick2 = {"use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t,
I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL};
#if (defined (LJOYSTICK) || defined (HAVE_SDL))
#ifdef LJOYSTICK
consvar_t cv_joyport = {"joyport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyport2 = {"joyport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: for later
consvar_t cv_joyport = {"padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyport2 = {"padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: for later
#endif
consvar_t cv_joyscale = {"joyscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyscale = {"padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyscale2 = {"padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2, 0, NULL, NULL, 0, 0, NULL};
#else
consvar_t cv_joyscale = {"joyscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale = {"padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale2 = {"padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
#endif
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
consvar_t cv_mouse2port = {"mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -315,16 +316,17 @@ consvar_t cv_timetic = {"timerres", "Classic", CV_SAVE, timetic_cons_t, NULL, 0,
static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-person only"}, {2, "Always"}, {0, NULL}};
consvar_t cv_powerupdisplay = {"powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t pointlimit_cons_t[] = {{0, "MIN"}, {999999990, "MAX"}, {0, NULL}};
consvar_t cv_pointlimit = {"pointlimit", "0", CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t,
static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, {0, "None"}, {0, NULL}};
consvar_t cv_pointlimit = {"pointlimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t,
PointLimit_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t timelimit_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}};
consvar_t cv_timelimit = {"timelimit", "0", CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t,
static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}};
consvar_t cv_timelimit = {"timelimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t,
TimeLimit_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t numlaps_cons_t[] = {{0, "MIN"}, {50, "MAX"}, {0, NULL}};
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}};
consvar_t cv_numlaps = {"numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t,
NumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usemapnumlaps = {"usemaplaps", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
// log elemental hazards -- not a netvar, is local to current player
consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -340,9 +342,7 @@ static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE
consvar_t cv_nettimeout = {"nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
consvar_t cv_jointimeout = {"jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
#ifdef NEWPING
consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
// Intermission time Tails 04-19-2002
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_inttime = {"inttime", "10", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -363,7 +363,7 @@ consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL
consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sleep = {"cpusleep", "-1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
INT16 gametype = GT_COOP;
boolean splitscreen = false;
@ -435,7 +435,6 @@ void D_RegisterServerCommands(void)
// Remote Administration
COM_AddCommand("password", Command_Changepassword_f);
RegisterNetXCmd(XD_LOGIN, Got_Login);
COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin
COM_AddCommand("promote", Command_Verify_f);
RegisterNetXCmd(XD_VERIFIED, Got_Verification);
@ -498,7 +497,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_friendlyfire);
CV_RegisterVar(&cv_pointlimit);
CV_RegisterVar(&cv_numlaps);
CV_RegisterVar(&cv_usemapnumlaps);
CV_RegisterVar(&cv_basenumlaps);
CV_RegisterVar(&cv_hazardlog);
@ -557,9 +556,16 @@ void D_RegisterServerCommands(void)
// d_clisrv
CV_RegisterVar(&cv_maxplayers);
CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload);
CV_RegisterVar(&cv_downloadspeed);
#ifndef NONET
CV_RegisterVar(&cv_allownewplayer);
CV_RegisterVar(&cv_joinnextround);
CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_blamecfail);
#endif
COM_AddCommand("ping", Command_Ping_f);
CV_RegisterVar(&cv_nettimeout);
@ -567,9 +573,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_skipmapcheck);
CV_RegisterVar(&cv_sleep);
#ifdef NEWPING
CV_RegisterVar(&cv_maxping);
#endif
#ifdef SEENAMES
CV_RegisterVar(&cv_allowseenames);
@ -599,6 +603,11 @@ void D_RegisterClientCommands(void)
Color_cons_t[MAXSKINCOLORS].value = 0;
Color_cons_t[MAXSKINCOLORS].strvalue = NULL;
// 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);
if (dedicated)
return;
@ -626,6 +635,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_screenshot_folder);
CV_RegisterVar(&cv_screenshot_colorprofile);
CV_RegisterVar(&cv_moviemode);
CV_RegisterVar(&cv_movie_option);
CV_RegisterVar(&cv_movie_folder);
// PNG variables
CV_RegisterVar(&cv_zlib_level);
CV_RegisterVar(&cv_zlib_memory);
@ -727,6 +738,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_chasefreelook);
CV_RegisterVar(&cv_chasefreelook2);
CV_RegisterVar(&cv_tutorialprompt);
CV_RegisterVar(&cv_showfocuslost);
CV_RegisterVar(&cv_pauseifunfocused);
// g_input.c
CV_RegisterVar(&cv_sideaxis);
@ -845,6 +858,7 @@ void D_RegisterClientCommands(void)
COM_AddCommand("rteleport", Command_RTeleport_f);
COM_AddCommand("skynum", Command_Skynum_f);
COM_AddCommand("weather", Command_Weather_f);
COM_AddCommand("toggletwod", Command_Toggletwod_f);
#ifdef _DEBUG
COM_AddCommand("causecfail", Command_CauseCfail_f);
#endif
@ -865,7 +879,7 @@ void D_RegisterClientCommands(void)
* \sa CleanupPlayerName, SetPlayerName, Got_NameAndColor
* \author Graue <graue@oceanbase.org>
*/
static boolean IsNameGood(char *name, INT32 playernum)
boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
{
INT32 ix;
@ -906,14 +920,14 @@ static boolean IsNameGood(char *name, INT32 playernum)
if (len > 1)
{
name[len-1] = '\0';
if (!IsNameGood (name, playernum))
if (!EnsurePlayerNameIsGood (name, playernum))
return false;
}
else if (len == 1) // Agh!
{
// Last ditch effort...
sprintf(name, "%d", M_RandomKey(10));
if (!IsNameGood (name, playernum))
if (!EnsurePlayerNameIsGood (name, playernum))
return false;
}
else
@ -1042,12 +1056,12 @@ static void CleanupPlayerName(INT32 playernum, const char *newname)
* \param newname New name for that player. Should be good, but won't
* necessarily be if the client is maliciously modified or
* buggy.
* \sa CleanupPlayerName, IsNameGood
* \sa CleanupPlayerName, EnsurePlayerNameIsGood
* \author Graue <graue@oceanbase.org>
*/
static void SetPlayerName(INT32 playernum, char *newname)
{
if (IsNameGood(newname, playernum))
if (EnsurePlayerNameIsGood(newname, playernum))
{
if (strcasecmp(newname, player_names[playernum]) != 0)
{
@ -1172,12 +1186,12 @@ static void SendNameAndColor(void)
&& !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name))
return;
players[consoleplayer].availabilities = R_GetSkinAvailabilities();
// We'll handle it later if we're not playing.
if (!Playing())
return;
players[consoleplayer].availabilities = R_GetSkinAvailabilities();
// If you're not in a netgame, merely update the skin, color, and name.
if (!netgame)
{
@ -1290,12 +1304,12 @@ static void SendNameAndColor2(void)
CV_StealthSet(&cv_playercolor2, cv_playercolor2.defaultvalue);
}
players[secondplaya].availabilities = R_GetSkinAvailabilities();
// We'll handle it later if we're not playing.
if (!Playing())
return;
players[secondplaya].availabilities = R_GetSkinAvailabilities();
// If you're not in a netgame, merely update the skin, color, and name.
if (botingame)
{
@ -1678,7 +1692,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
// Kick bot from special stages
if (botskin)
{
if (G_IsSpecialStage(mapnum))
if (G_IsSpecialStage(mapnum) || (mapheaderinfo[mapnum-1] && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_NIGHTS)))
{
if (botingame)
{
@ -1904,7 +1918,10 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
precache = false;
if (resetplayer && !FLS)
{
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
}
if (modeattacking)
{
@ -2015,8 +2032,6 @@ static void Command_Suicide(void)
UINT8 buf[4];
UINT8 *cp = buf;
WRITEINT32(cp, consoleplayer);
if (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
{
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
@ -2036,6 +2051,7 @@ static void Command_Suicide(void)
return;
}
WRITEINT32(cp, consoleplayer);
SendNetXCmd(XD_SUICIDE, &buf, 4);
}
@ -2702,14 +2718,6 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
}
}
// Clear player score and rings if a spectator.
if (players[playernum].spectator)
{
players[playernum].score = players[playernum].rings = 0;
if (players[playernum].mo)
players[playernum].mo->health = 1;
}
// In tag, check to see if you still have a game.
if (G_TagGametype())
P_CheckSurvivors();
@ -2719,35 +2727,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
// Attempts to make password system a little sane without
// rewriting the entire goddamn XD_file system
//
#include "md5.h"
static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest)
{
#ifdef NOMD5
(void)buffer;
(void)len;
(void)salt;
memset(dest, 0, 16);
#else
char tmpbuf[256];
const size_t sl = strlen(salt);
if (len > 256-sl)
len = 256-sl;
memcpy(tmpbuf, buffer, len);
memmove(&tmpbuf[len], salt, sl);
//strcpy(&tmpbuf[len], salt);
len += strlen(salt);
if (len < 256)
memset(&tmpbuf[len],0,256-len);
// Yes, we intentionally md5 the ENTIRE buffer regardless of size...
md5_buffer(tmpbuf, 256, dest);
#endif
}
#define BASESALT "basepasswordstorage"
static UINT8 adminpassmd5[16];
static boolean adminpasswordset = false;
void D_SetPassword(const char *pw)
{
@ -2785,7 +2765,6 @@ static void Command_Login_f(void)
// If we have no MD5 support then completely disable XD_LOGIN responses for security.
CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n");
#else
UINT8 finalmd5[16];
const char *pw;
if (!netgame)
@ -2805,47 +2784,15 @@ static void Command_Login_f(void)
pw = COM_Argv(1);
// Do the base pass to get what the server has (or should?)
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &finalmd5);
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &netbuffer->u.md5sum);
// Do the final pass to get the comparison the server will come up with
D_MD5PasswordPass(finalmd5, 16, va("PNUM%02d", consoleplayer), &finalmd5);
D_MD5PasswordPass(netbuffer->u.md5sum, 16, va("PNUM%02d", consoleplayer), &netbuffer->u.md5sum);
CONS_Printf(M_GetText("Sending login... (Notice only given if password is correct.)\n"));
SendNetXCmd(XD_LOGIN, finalmd5, 16);
#endif
}
static void Got_Login(UINT8 **cp, INT32 playernum)
{
#ifdef NOMD5
// If we have no MD5 support then completely disable XD_LOGIN responses for security.
(void)cp;
(void)playernum;
#else
UINT8 sentmd5[16], finalmd5[16];
READMEM(*cp, sentmd5, 16);
if (client)
return;
if (!adminpasswordset)
{
CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[playernum]);
return;
}
// Do the final pass to compare with the sent md5
D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", playernum), &finalmd5);
if (!memcmp(sentmd5, finalmd5, 16))
{
CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[playernum]);
COM_BufInsertText(va("promote %d\n", playernum)); // do this immediately
}
else
CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[playernum]);
netbuffer->packettype = PT_LOGIN;
HSendPacket(servernode, true, 0, 16);
#endif
}
@ -3657,7 +3604,7 @@ static void CoopLives_OnChange(void)
{
case 0:
CONS_Printf(M_GetText("Players can now respawn indefinitely.\n"));
return;
break;
case 1:
CONS_Printf(M_GetText("Lives are now per-player.\n"));
return;
@ -4160,6 +4107,7 @@ void Command_ExitGame_f(void)
botskin = 0;
cv_debug = 0;
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
if (dirmenu)
closefilemenu(true);
@ -4516,3 +4464,14 @@ static void Command_ShowTime_f(void)
CONS_Printf(M_GetText("The current time is %f.\nThe timelimit is %f\n"), (double)leveltime/TICRATE, (double)timelimitintics/TICRATE);
}
static void BaseNumLaps_OnChange(void)
{
if (gametype == GT_RACE)
{
if (cv_basenumlaps.value)
CONS_Printf(M_GetText("Number of laps will be changed to map defaults next round.\n"));
else
CONS_Printf(M_GetText("Number of laps will be changed to %d next round.\n"), cv_basenumlaps.value);
}
}

View File

@ -66,7 +66,7 @@ extern consvar_t cv_friendlyfire;
extern consvar_t cv_pointlimit;
extern consvar_t cv_timelimit;
extern consvar_t cv_numlaps;
extern consvar_t cv_usemapnumlaps;
extern consvar_t cv_basenumlaps;
extern UINT32 timelimitintics;
extern consvar_t cv_allowexitlevel;
@ -107,9 +107,7 @@ extern consvar_t cv_ringslinger, cv_soundtest;
extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes;
#ifdef NEWPING
extern consvar_t cv_maxping;
#endif
extern consvar_t cv_skipmapcheck;
@ -129,8 +127,8 @@ typedef enum
XD_ADDPLAYER, // 10
XD_TEAMCHANGE, // 11
XD_CLEARSCORES, // 12
XD_LOGIN, // 13
XD_VERIFIED, // 14
// UNUSED 13 (Because I don't want to change these comments)
XD_VERIFIED = 14,//14
XD_RANDOMSEED, // 15
XD_RUNSOC, // 16
XD_REQADDFILE, // 17
@ -190,6 +188,7 @@ typedef union {
// add game commands, needs cleanup
void D_RegisterServerCommands(void);
void D_RegisterClientCommands(void);
boolean EnsurePlayerNameIsGood(char *name, INT32 playernum);
void D_SendPlayerConfig(void);
void Command_ExitGame_f(void);
void Command_Retry_f(void);

View File

@ -745,9 +745,12 @@ void Got_Filetxpak(void)
{
INT32 filenum = netbuffer->u.filetxpak.fileid;
fileneeded_t *file = &fileneeded[filenum];
char *filename = file->filename;
char *filename;
static INT32 filetime = 0;
filename = va("%s", file->filename);
nameonly(filename);
if (!(strcmp(filename, "srb2.pk3")
&& strcmp(filename, "srb2.srb")
&& strcmp(filename, "srb2.wad")
@ -758,6 +761,8 @@ void Got_Filetxpak(void)
))
I_Error("Tried to download \"%s\"", filename);
filename = file->filename;
if (filenum >= fileneedednum)
{
DEBFILE(va("fileframent not needed %d>%d\n", filenum, fileneedednum));

View File

@ -234,7 +234,9 @@ typedef enum
CR_ZOOMTUBE,
CR_ROPEHANG,
CR_MACESPIN,
CR_MINECART
CR_MINECART,
CR_ROLLOUT,
CR_PTERABYTE
} carrytype_t; // pw_carry
// Player powers. (don't edit this comment)
@ -250,6 +252,8 @@ typedef enum
pw_spacetime, // In space, no one can hear you spin!
pw_extralife, // Extra Life timer
pw_pushing,
pw_justsprung,
pw_noautobrake,
pw_super, // Are you super?
pw_gravityboots, // gravity boots
@ -333,6 +337,10 @@ typedef struct player_s
INT32 currentweapon; // current weapon selected.
INT32 ringweapons; // weapons currently obtained.
UINT16 ammoremoval; // amount of ammo removed for the current weapon.
tic_t ammoremovaltimer; // flashing counter for ammo used.
INT32 ammoremovalweapon; // weapon from which the ammo was removed.
// Power ups. invinc and invis are tic counters.
UINT16 powers[NUMPOWERS];
@ -437,6 +445,7 @@ typedef struct player_s
INT32 starpostnum; // The number of the last starpost you hit
tic_t starposttime; // Your time when you hit the starpost
angle_t starpostangle; // Angle that the starpost is facing - you respawn facing this way
fixed_t starpostscale; // Scale of the player; if negative, player is gravflipped
/////////////////
// NiGHTS Stuff//

View File

@ -313,7 +313,13 @@ static boolean findFreeSlot(INT32 *num)
if (*num >= MAXSKINS)
return false;
description[*num].picname[0] = '\0'; // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...)
// Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...)
description[*num].picname[0] = '\0';
description[*num].nametag[0] = '\0';
description[*num].displayname[0] = '\0';
description[*num].oppositecolor = SKINCOLOR_NONE;
description[*num].tagtextcolor = SKINCOLOR_NONE;
description[*num].tagoutlinecolor = SKINCOLOR_NONE;
// Found one! ^_^
return (description[*num].used = true);
@ -326,9 +332,16 @@ static void readPlayer(MYFILE *f, INT32 num)
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word;
char *word2;
char *displayname = ZZ_Alloc(MAXLINELEN+1);
INT32 i;
boolean slotfound = false;
#define SLOTFOUND \
if (!slotfound && (slotfound = findFreeSlot(&num)) == false) \
goto done;
displayname[MAXLINELEN] = '\0';
do
{
if (myfgets(s, MAXLINELEN, f))
@ -336,6 +349,17 @@ static void readPlayer(MYFILE *f, INT32 num)
if (s[0] == '\n')
break;
for (i = 0; i < MAXLINELEN-3; i++)
{
char *tmp;
if (s[i] == '=')
{
tmp = &s[i+2];
strncpy(displayname, tmp, SKINNAMESIZE);
break;
}
}
word = strtok(s, " ");
if (word)
strupr(word);
@ -346,8 +370,7 @@ static void readPlayer(MYFILE *f, INT32 num)
{
char *playertext = NULL;
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
SLOTFOUND
for (i = 0; i < MAXLINELEN-3; i++)
{
@ -395,11 +418,54 @@ static void readPlayer(MYFILE *f, INT32 num)
if (fastcmp(word, "PICNAME"))
{
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
SLOTFOUND
strncpy(description[num].picname, word2, 8);
}
// new character select
else if (fastcmp(word, "DISPLAYNAME"))
{
SLOTFOUND
// replace '#' with line breaks
// (also remove any '\n')
{
char *cur = NULL;
// remove '\n'
cur = strchr(displayname, '\n');
if (cur)
*cur = '\0';
// turn '#' into '\n'
cur = strchr(displayname, '#');
while (cur)
{
*cur = '\n';
cur = strchr(cur, '#');
}
}
// copy final string
strncpy(description[num].displayname, displayname, SKINNAMESIZE);
}
else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR"))
{
SLOTFOUND
description[num].oppositecolor = (UINT8)get_number(word2);
}
else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME"))
{
SLOTFOUND
strncpy(description[num].nametag, word2, 8);
}
else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR"))
{
SLOTFOUND
description[num].tagtextcolor = (UINT8)get_number(word2);
}
else if (fastcmp(word, "TAGOUTLINECOLOR") || fastcmp(word, "TAGOUTLINECOLOUR"))
{
SLOTFOUND
description[num].tagoutlinecolor = (UINT8)get_number(word2);
}
else if (fastcmp(word, "STATUS"))
{
/*
@ -417,9 +483,7 @@ static void readPlayer(MYFILE *f, INT32 num)
else if (fastcmp(word, "SKINNAME"))
{
// Send to free slot.
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
SLOTFOUND
strlcpy(description[num].skinname, word2, sizeof description[num].skinname);
strlwr(description[num].skinname);
}
@ -427,8 +491,9 @@ static void readPlayer(MYFILE *f, INT32 num)
deh_warning("readPlayer %d: unknown word '%s'", num, word);
}
} while (!myfeof(f)); // finish when the line is empty
#undef SLOTFOUND
done:
Z_Free(displayname);
Z_Free(s);
}
@ -1181,6 +1246,20 @@ static void readlevelheader(MYFILE *f, INT32 num)
mapheaderinfo[num-1]->muspostbosspos = (UINT32)get_number(word2);
else if (fastcmp(word, "MUSICPOSTBOSSFADEIN"))
mapheaderinfo[num-1]->muspostbossfadein = (UINT32)get_number(word2);
else if (fastcmp(word, "FORCERESETMUSIC"))
{
// This is a weird one because "FALSE"/"NO" could either apply to "leave to default preference" (cv_resetmusic)
// or "force off". Let's assume it means "force off", and let an unspecified value mean "default preference"
if (fastcmp(word2, "OFF") || word2[0] == 'F' || word2[0] == 'N') i = 0;
else if (fastcmp(word2, "ON") || word2[0] == 'T' || word2[0] == 'Y') i = 1;
else i = -1; // (fastcmp(word2, "DEFAULT"))
if (i >= -1 && i <= 1) // -1 to force off, 1 to force on, 0 to honor default.
// This behavior can be disabled with cv_resetmusicbyheader
mapheaderinfo[num-1]->musforcereset = (SINT8)i;
else
deh_warning("Level header %d: invalid forceresetmusic option %d", num, i);
}
else if (fastcmp(word, "FORCECHARACTER"))
{
strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1);
@ -2362,6 +2441,7 @@ static actionpointer_t actionpointers[] =
{{A_Boss1Spikeballs}, "A_BOSS1SPIKEBALLS"},
{{A_Boss3TakeDamage}, "A_BOSS3TAKEDAMAGE"},
{{A_Boss3Path}, "A_BOSS3PATH"},
{{A_Boss3ShockThink}, "A_BOSS3SHOCKTHINK"},
{{A_LinedefExecute}, "A_LINEDEFEXECUTE"},
{{A_PlaySeeSound}, "A_PLAYSEESOUND"},
{{A_PlayAttackSound}, "A_PLAYATTACKSOUND"},
@ -2468,6 +2548,7 @@ static actionpointer_t actionpointers[] =
{{A_Boss5CheckFalling}, "A_BOSS5CHECKFALLING"},
{{A_Boss5PinchShot}, "A_BOSS5PINCHSHOT"},
{{A_Boss5MakeItRain}, "A_BOSS5MAKEITRAIN"},
{{A_Boss5MakeJunk}, "A_BOSS5MAKEJUNK"},
{{A_LookForBetter}, "A_LOOKFORBETTER"},
{{A_Boss5BombExplode}, "A_BOSS5BOMBEXPLODE"},
{{A_DustDevilThink}, "A_DUSTDEVILTHINK"},
@ -2482,6 +2563,14 @@ static actionpointer_t actionpointers[] =
{{A_SaloonDoorSpawn}, "A_SALOONDOORSPAWN"},
{{A_MinecartSparkThink}, "A_MINECARTSPARKTHINK"},
{{A_ModuloToState}, "A_MODULOTOSTATE"},
{{A_LavafallRocks}, "A_LAVAFALLROCKS"},
{{A_LavafallLava}, "A_LAVAFALLLAVA"},
{{A_FallingLavaCheck}, "A_FALLINGLAVACHECK"},
{{A_FireShrink}, "A_FIRESHRINK"},
{{A_SpawnPterabytes}, "A_SPAWNPTERABYTES"},
{{A_PterabyteHover}, "A_PTERABYTEHOVER"},
{{A_RolloutSpawn}, "A_ROLLOUTSPAWN"},
{{A_RolloutRock}, "A_ROLLOUTROCK"},
{{NULL}, "NONE"},
// This NULL entry must be the last in the list
@ -3008,6 +3097,17 @@ static void readunlockable(MYFILE *f, INT32 num)
Z_Free(s);
}
static const char NIGHTSGRADE_LIST[] = {
'F', // GRADE_F
'E', // GRADE_E
'D', // GRADE_D
'C', // GRADE_C
'B', // GRADE_B
'A', // GRADE_A
'S', // GRADE_S
'\0'
};
#define PARAMCHECK(n) do { if (!params[n]) { deh_warning("Too few parameters, need %d", n); return; }} while (0)
static void readcondition(UINT8 set, UINT32 id, char *word2)
{
@ -3109,7 +3209,21 @@ static void readcondition(UINT8 set, UINT32 id, char *word2)
PARAMCHECK(2); // one optional one
ty = UC_NIGHTSSCORE + offset;
re = atoi(params[2 + !!(params[3])]);
i = (params[3] ? 3 : 2);
if (fastncmp("GRADE_",params[i],6))
{
char *p = params[i]+6;
for (re = 0; NIGHTSGRADE_LIST[re]; re++)
if (*p == NIGHTSGRADE_LIST[re])
break;
if (!NIGHTSGRADE_LIST[re])
{
deh_warning("Invalid NiGHTS grade %s\n", params[i]);
return;
}
}
else
re = atoi(params[i]);
// Convert to map number if it appears to be one
if (params[1][0] >= 'A' && params[1][0] <= 'Z')
@ -3398,6 +3512,10 @@ static void readmaincfg(MYFILE *f)
{
gameovertics = get_number(word2);
}
else if (fastcmp(word, "AMMOREMOVALTICS"))
{
ammoremovaltics = get_number(word2);
}
else if (fastcmp(word, "INTROTOPLAY"))
{
introtoplay = (UINT8)get_number(word2);
@ -4489,6 +4607,21 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CRUSHCLAW_WAIT",
"S_CRUSHCHAIN",
// Banpyura
"S_BANPYURA_ROAM1",
"S_BANPYURA_ROAM2",
"S_BANPYURA_ROAM3",
"S_BANPYURA_ROAM4",
"S_BANPYURA_ROAMPAUSE",
"S_CDIAG1",
"S_CDIAG2",
"S_CDIAG3",
"S_CDIAG4",
"S_CDIAG5",
"S_CDIAG6",
"S_CDIAG7",
"S_CDIAG8",
// Jet Jaw
"S_JETJAW_ROAM1",
"S_JETJAW_ROAM2",
@ -4675,6 +4808,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CANARIVOREGAS_7",
"S_CANARIVOREGAS_8",
// Pyre Fly
"S_PYREFLY_FLY",
"S_PYREFLY_BURN",
"S_PYREFIRE1",
"S_PYREFIRE2",
// Pterabyte
"S_PTERABYTESPAWNER",
"S_PTERABYTEWAYPOINT",
"S_PTERABYTE_FLY1",
"S_PTERABYTE_FLY2",
"S_PTERABYTE_FLY3",
"S_PTERABYTE_FLY4",
"S_PTERABYTE_SWOOPDOWN",
"S_PTERABYTE_SWOOPUP",
// Boss Explosion
"S_BOSSEXPLODE",
@ -4687,10 +4836,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SONIC3KBOSSEXPLOSION6",
"S_JETFUME1",
"S_JETFUME2",
// Boss 1
"S_EGGMOBILE_STND",
"S_EGGMOBILE_ROFL",
"S_EGGMOBILE_LATK1",
"S_EGGMOBILE_LATK2",
"S_EGGMOBILE_LATK3",
@ -4700,7 +4849,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_LATK7",
"S_EGGMOBILE_LATK8",
"S_EGGMOBILE_LATK9",
"S_EGGMOBILE_LATK10",
"S_EGGMOBILE_RATK1",
"S_EGGMOBILE_RATK2",
"S_EGGMOBILE_RATK3",
@ -4710,7 +4858,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_RATK7",
"S_EGGMOBILE_RATK8",
"S_EGGMOBILE_RATK9",
"S_EGGMOBILE_RATK10",
"S_EGGMOBILE_PANIC1",
"S_EGGMOBILE_PANIC2",
"S_EGGMOBILE_PANIC3",
@ -4721,26 +4868,23 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE_PANIC8",
"S_EGGMOBILE_PANIC9",
"S_EGGMOBILE_PANIC10",
"S_EGGMOBILE_PANIC11",
"S_EGGMOBILE_PANIC12",
"S_EGGMOBILE_PANIC13",
"S_EGGMOBILE_PANIC14",
"S_EGGMOBILE_PANIC15",
"S_EGGMOBILE_PAIN",
"S_EGGMOBILE_PAIN2",
"S_EGGMOBILE_DIE1",
"S_EGGMOBILE_DIE2",
"S_EGGMOBILE_DIE3",
"S_EGGMOBILE_DIE4",
"S_EGGMOBILE_DIE5",
"S_EGGMOBILE_DIE6",
"S_EGGMOBILE_DIE7",
"S_EGGMOBILE_DIE8",
"S_EGGMOBILE_DIE9",
"S_EGGMOBILE_DIE10",
"S_EGGMOBILE_DIE11",
"S_EGGMOBILE_DIE12",
"S_EGGMOBILE_DIE13",
"S_EGGMOBILE_DIE14",
"S_EGGMOBILE_FLEE1",
"S_EGGMOBILE_FLEE2",
"S_EGGMOBILE_BALL",
"S_EGGMOBILE_TARGET",
"S_BOSSEGLZ1",
"S_BOSSEGLZ2",
// Boss 2
"S_EGGMOBILE2_STND",
@ -4757,16 +4901,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE2_DIE2",
"S_EGGMOBILE2_DIE3",
"S_EGGMOBILE2_DIE4",
"S_EGGMOBILE2_DIE5",
"S_EGGMOBILE2_DIE6",
"S_EGGMOBILE2_DIE7",
"S_EGGMOBILE2_DIE8",
"S_EGGMOBILE2_DIE9",
"S_EGGMOBILE2_DIE10",
"S_EGGMOBILE2_DIE11",
"S_EGGMOBILE2_DIE12",
"S_EGGMOBILE2_DIE13",
"S_EGGMOBILE2_DIE14",
"S_EGGMOBILE2_FLEE1",
"S_EGGMOBILE2_FLEE2",
@ -4782,11 +4916,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Boss 3
"S_EGGMOBILE3_STND",
"S_EGGMOBILE3_LAUGH1",
"S_EGGMOBILE3_LAUGH2",
"S_EGGMOBILE3_LAUGH3",
"S_EGGMOBILE3_LAUGH4",
"S_EGGMOBILE3_LAUGH5",
"S_EGGMOBILE3_SHOCK",
"S_EGGMOBILE3_ATK1",
"S_EGGMOBILE3_ATK2",
"S_EGGMOBILE3_ATK3A",
@ -4795,49 +4925,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE3_ATK3D",
"S_EGGMOBILE3_ATK4",
"S_EGGMOBILE3_ATK5",
"S_EGGMOBILE3_LAUGH6",
"S_EGGMOBILE3_LAUGH7",
"S_EGGMOBILE3_LAUGH8",
"S_EGGMOBILE3_LAUGH9",
"S_EGGMOBILE3_LAUGH10",
"S_EGGMOBILE3_LAUGH11",
"S_EGGMOBILE3_LAUGH12",
"S_EGGMOBILE3_LAUGH13",
"S_EGGMOBILE3_LAUGH14",
"S_EGGMOBILE3_LAUGH15",
"S_EGGMOBILE3_LAUGH16",
"S_EGGMOBILE3_LAUGH17",
"S_EGGMOBILE3_LAUGH18",
"S_EGGMOBILE3_LAUGH19",
"S_EGGMOBILE3_LAUGH20",
"S_EGGMOBILE3_ROFL",
"S_EGGMOBILE3_PAIN",
"S_EGGMOBILE3_PAIN2",
"S_EGGMOBILE3_DIE1",
"S_EGGMOBILE3_DIE2",
"S_EGGMOBILE3_DIE3",
"S_EGGMOBILE3_DIE4",
"S_EGGMOBILE3_DIE5",
"S_EGGMOBILE3_DIE6",
"S_EGGMOBILE3_DIE7",
"S_EGGMOBILE3_DIE8",
"S_EGGMOBILE3_DIE9",
"S_EGGMOBILE3_DIE10",
"S_EGGMOBILE3_DIE11",
"S_EGGMOBILE3_DIE12",
"S_EGGMOBILE3_DIE13",
"S_EGGMOBILE3_DIE14",
"S_EGGMOBILE3_FLEE1",
"S_EGGMOBILE3_FLEE2",
// Boss 3 Propeller
"S_PROPELLER1",
"S_PROPELLER2",
"S_PROPELLER3",
"S_PROPELLER4",
"S_PROPELLER5",
"S_PROPELLER6",
"S_PROPELLER7",
// Boss 3 pinch
"S_FAKEMOBILE_INIT",
"S_FAKEMOBILE",
@ -4850,6 +4947,14 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FAKEMOBILE_DIE1",
"S_FAKEMOBILE_DIE2",
"S_BOSSSEBH1",
"S_BOSSSEBH2",
// Boss 3 Shockwave
"S_SHOCKWAVE1",
"S_SHOCKWAVE2",
// Boss 4
"S_EGGMOBILE4_STND",
"S_EGGMOBILE4_LATK1",
@ -4872,16 +4977,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE4_DIE2",
"S_EGGMOBILE4_DIE3",
"S_EGGMOBILE4_DIE4",
"S_EGGMOBILE4_DIE5",
"S_EGGMOBILE4_DIE6",
"S_EGGMOBILE4_DIE7",
"S_EGGMOBILE4_DIE8",
"S_EGGMOBILE4_DIE9",
"S_EGGMOBILE4_DIE10",
"S_EGGMOBILE4_DIE11",
"S_EGGMOBILE4_DIE12",
"S_EGGMOBILE4_DIE13",
"S_EGGMOBILE4_DIE14",
"S_EGGMOBILE4_FLEE1",
"S_EGGMOBILE4_FLEE2",
"S_EGGMOBILE4_MACE",
@ -4902,6 +4997,25 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGROBOJET",
// Boss 5
"S_FANG_SETUP",
"S_FANG_INTRO0",
"S_FANG_INTRO1",
"S_FANG_INTRO2",
"S_FANG_INTRO3",
"S_FANG_INTRO4",
"S_FANG_INTRO5",
"S_FANG_INTRO6",
"S_FANG_INTRO7",
"S_FANG_INTRO8",
"S_FANG_INTRO9",
"S_FANG_INTRO10",
"S_FANG_INTRO11",
"S_FANG_INTRO12",
"S_FANG_CLONE1",
"S_FANG_CLONE2",
"S_FANG_CLONE3",
"S_FANG_CLONE4",
"S_FANG_IDLE0",
"S_FANG_IDLE1",
"S_FANG_IDLE2",
"S_FANG_IDLE3",
@ -4937,6 +5051,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FANG_FIRE3",
"S_FANG_FIRE4",
"S_FANG_FIREREPEAT",
"S_FANG_LOBSHOT0",
"S_FANG_LOBSHOT1",
"S_FANG_LOBSHOT2",
"S_FANG_WAIT1",
@ -4953,6 +5068,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FANG_PINCHFALL2",
"S_FANG_PINCHSKID1",
"S_FANG_PINCHSKID2",
"S_FANG_PINCHLOBSHOT0",
"S_FANG_PINCHLOBSHOT1",
"S_FANG_PINCHLOBSHOT2",
"S_FANG_PINCHLOBSHOT3",
@ -4971,6 +5087,26 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FANG_FLEEBOUNCE2",
"S_FANG_KO",
"S_BROKENROBOTRANDOM",
"S_BROKENROBOTA",
"S_BROKENROBOTB",
"S_BROKENROBOTC",
"S_BROKENROBOTD",
"S_BROKENROBOTE",
"S_BROKENROBOTF",
"S_ALART1",
"S_ALART2",
"S_VWREF",
"S_VWREB",
"S_PROJECTORLIGHT1",
"S_PROJECTORLIGHT2",
"S_PROJECTORLIGHT3",
"S_PROJECTORLIGHT4",
"S_PROJECTORLIGHT5",
"S_FBOMB1",
"S_FBOMB2",
"S_FBOMB_EXPL1",
@ -5258,21 +5394,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_METALSONIC_DEATH4",
"S_METALSONIC_FLEE1",
"S_METALSONIC_FLEE2",
"S_METALSONIC_FLEE3",
"S_METALSONIC_FLEE4",
"S_MSSHIELD_F1",
"S_MSSHIELD_F2",
"S_MSSHIELD_F3",
"S_MSSHIELD_F4",
"S_MSSHIELD_F5",
"S_MSSHIELD_F6",
"S_MSSHIELD_F7",
"S_MSSHIELD_F8",
"S_MSSHIELD_F9",
"S_MSSHIELD_F10",
"S_MSSHIELD_F11",
"S_MSSHIELD_F12",
// Ring
"S_RING",
@ -5706,14 +5830,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_DRIPC1",
"S_DRIPC2",
// Coral 1
// Coral
"S_CORAL1",
// Coral 2
"S_CORAL2",
// Coral 3
"S_CORAL3",
"S_CORAL4",
"S_CORAL5",
// Blue Crystal
"S_BLUECRYSTAL1",
@ -5721,6 +5843,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Kelp,
"S_KELP",
// Animated algae
"S_ANIMALGAETOP1",
"S_ANIMALGAETOP2",
"S_ANIMALGAESEG",
// DSZ Stalagmites
"S_DSZSTALAGMITE",
"S_DSZ2STALAGMITE",
@ -5865,6 +5992,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CACTI7",
"S_CACTI8",
"S_CACTI9",
"S_CACTI10",
"S_CACTI11",
"S_CACTITINYSEG",
"S_CACTISMALLSEG",
// Warning signs sprites
"S_ARIDSIGN_CAUTION",
@ -5936,7 +6067,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Saloon door
"S_SALOONDOOR",
"S_SALOONDOORTHINKER",
"S_SALOONDOORCENTER",
// Train cameo
"S_TRAINCAMEOSPAWNER_1",
@ -5957,6 +6088,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLAMEJETFLAME1",
"S_FLAMEJETFLAME2",
"S_FLAMEJETFLAME3",
"S_FLAMEJETFLAME4",
"S_FLAMEJETFLAME5",
"S_FLAMEJETFLAME6",
"S_FLAMEJETFLAME7",
"S_FLAMEJETFLAME8",
"S_FLAMEJETFLAME9",
// Spinning flame jets
"S_FJSPINAXISA1", // Counter-clockwise
@ -5969,6 +6106,28 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLAMEJETFLAMEB2",
"S_FLAMEJETFLAMEB3",
// Lavafall
"S_LAVAFALL_DORMANT",
"S_LAVAFALL_TELL",
"S_LAVAFALL_SHOOT",
"S_LAVAFALL_LAVA1",
"S_LAVAFALL_LAVA2",
"S_LAVAFALL_LAVA3",
"S_LAVAFALLROCK",
// Rollout Rock
"S_ROLLOUTSPAWN",
"S_ROLLOUTROCK",
// RVZ scenery
"S_BIGFERNLEAF",
"S_BIGFERN1",
"S_BIGFERN2",
"S_JUNGLEPALM",
"S_TORCHFLOWER",
"S_WALLVINE_LONG",
"S_WALLVINE_SHORT",
// Trapgoyles
"S_TRAPGOYLE",
"S_TRAPGOYLE_CHECK",
@ -6000,6 +6159,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_TARGET_RESPAWN",
"S_TARGET_ALLDONE",
// ATZ's green flame
"S_GREENFLAME",
// Stalagmites
"S_STG0",
"S_STG1",
@ -6020,6 +6182,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_LAMPPOST1", // normal
"S_LAMPPOST2", // with snow
"S_HANGSTAR",
"S_MISTLETOE",
// Xmas GFZ bushes
"S_XMASBLUEBERRYBUSH",
"S_XMASBERRYBUSH",
@ -6027,6 +6190,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// FHZ
"S_FHZICE1",
"S_FHZICE2",
"S_ROSY_IDLE1",
"S_ROSY_IDLE2",
"S_ROSY_IDLE3",
"S_ROSY_IDLE4",
"S_ROSY_JUMP",
"S_ROSY_WALK",
"S_ROSY_HUG",
"S_ROSY_PAIN",
"S_ROSY_STND",
"S_ROSY_UNHAPPY",
// Halloween Scenery
// Pumpkins
@ -6678,6 +6851,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BHORIZ7",
"S_BHORIZ8",
"S_BOOSTERSOUND",
"S_YELLOWBOOSTERROLLER",
"S_YELLOWBOOSTERSEG_LEFT",
"S_YELLOWBOOSTERSEG_RIGHT",
"S_YELLOWBOOSTERSEG_FACE",
"S_REDBOOSTERROLLER",
"S_REDBOOSTERSEG_LEFT",
"S_REDBOOSTERSEG_RIGHT",
"S_REDBOOSTERSEG_FACE",
// Rain
"S_RAIN1",
"S_RAINRETURN",
@ -6698,6 +6881,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SPLISH8",
"S_SPLISH9",
// Lava splish
"S_LAVASPLISH",
// added water splash
"S_SPLASH1",
"S_SPLASH2",
@ -7327,6 +7513,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_CRUSHSTACEAN", // Crushstacean
"MT_CRUSHCLAW", // Big meaty claw
"MT_CRUSHCHAIN", // Chain
"MT_BANPYURA", // Banpyura
"MT_BANPSPRING", // Banpyura spring
"MT_JETJAW", // Jet Jaw
"MT_SNAILER", // Snailer
"MT_VULTURE", // BASH
@ -7348,6 +7536,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_UNIBALL", // Unidus Ball
"MT_CANARIVORE", // Canarivore
"MT_CANARIVORE_GAS", // Canarivore gas
"MT_PYREFLY", // Pyre Fly
"MT_PYREFLY_FIRE", // Pyre Fly fire
"MT_PTERABYTESPAWNER", // Pterabyte spawner
"MT_PTERABYTEWAYPOINT", // Pterabyte waypoint
"MT_PTERABYTE", // Pterabyte
// Generic Boss Items
"MT_BOSSEXPLODE",
@ -7356,6 +7549,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_EGGTRAP",
"MT_BOSS3WAYPOINT",
"MT_BOSS9GATHERPOINT",
"MT_BOSSJUNK",
// Boss 1
"MT_EGGMOBILE",
@ -7367,17 +7561,13 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Boss 2
"MT_EGGMOBILE2",
"MT_EGGMOBILE2_POGO",
"MT_BOSSTANK1",
"MT_BOSSTANK2",
"MT_BOSSSPIGOT",
"MT_GOOP",
"MT_GOOPTRAIL",
// Boss 3
"MT_EGGMOBILE3",
"MT_PROPELLER",
"MT_FAKEMOBILE",
"MT_SHOCK",
"MT_SHOCKWAVE",
// Boss 4
"MT_EGGMOBILE4",
@ -7388,6 +7578,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Boss 5
"MT_FANG",
"MT_BROKENROBOT",
"MT_VWREF",
"MT_VWREB",
"MT_PROJECTORLIGHT",
"MT_FBOMB",
"MT_TNTDUST", // also used by barrel
"MT_FSGNA",
@ -7458,6 +7652,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_REDHORIZ",
"MT_BLUEHORIZ",
"MT_BOOSTERSEG",
"MT_BOOSTERROLLER",
"MT_YELLOWBOOSTER",
"MT_REDBOOSTER",
// Interactive Objects
"MT_BUBBLES", // Bubble source
"MT_SIGN", // Level end sign
@ -7586,11 +7785,15 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_SEAWEED", // DSZ Seaweed
"MT_WATERDRIP", // Dripping Water source
"MT_WATERDROP", // Water drop from dripping water
"MT_CORAL1", // Coral 1
"MT_CORAL2", // Coral 2
"MT_CORAL3", // Coral 3
"MT_CORAL1", // Coral
"MT_CORAL2",
"MT_CORAL3",
"MT_CORAL4",
"MT_CORAL5",
"MT_BLUECRYSTAL", // Blue Crystal
"MT_KELP", // Kelp
"MT_ANIMALGAETOP", // Animated algae top
"MT_ANIMALGAESEG", // Animated algae segment
"MT_DSZSTALAGMITE", // Deep Sea 1 Stalagmite
"MT_DSZ2STALAGMITE", // Deep Sea 2 Stalagmite
"MT_LIGHTBEAM", // DSZ Light beam
@ -7650,6 +7853,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_CACTI7",
"MT_CACTI8",
"MT_CACTI9",
"MT_CACTI10",
"MT_CACTI11",
"MT_CACTITINYSEG",
"MT_CACTISMALLSEG",
"MT_ARIDSIGN_CAUTION",
"MT_ARIDSIGN_CACTI",
"MT_ARIDSIGN_SHARPTURN",
@ -7667,7 +7874,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_MINECARTSIDEMARK",
"MT_MINECARTSPARK",
"MT_SALOONDOOR",
"MT_SALOONDOORTHINKER",
"MT_SALOONDOORCENTER",
"MT_TRAINCAMEOSPAWNER",
"MT_TRAINSEG",
"MT_TRAINDUSTSPAWNER",
@ -7684,6 +7891,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_FLAMEJETFLAMEB", // Blade's flame
"MT_LAVAFALL",
"MT_LAVAFALL_LAVA",
"MT_LAVAFALLROCK",
"MT_ROLLOUTSPAWN",
"MT_ROLLOUTROCK",
"MT_BIGFERNLEAF",
"MT_BIGFERN",
"MT_JUNGLEPALM",
"MT_TORCHFLOWER",
"MT_WALLVINE_LONG",
"MT_WALLVINE_SHORT",
// Dark City Scenery
// Egg Rock Scenery
@ -7694,6 +7915,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_TRAPGOYLEDOWN",
"MT_TRAPGOYLELONG",
"MT_TARGET",
"MT_GREENFLAME",
// Stalagmites
"MT_STALAGMITE0",
@ -7715,6 +7937,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_LAMPPOST1", // normal
"MT_LAMPPOST2", // with snow
"MT_HANGSTAR",
"MT_MISTLETOE",
// Xmas GFZ bushes
"MT_XMASBLUEBERRYBUSH",
"MT_XMASBERRYBUSH",
@ -7722,6 +7945,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// FHZ
"MT_FHZICE1",
"MT_FHZICE2",
"MT_ROSY",
"MT_CDLHRT",
// Halloween Scenery
// Pumpkins
@ -7850,6 +8075,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_RAIN", // Rain
"MT_SNOWFLAKE", // Snowflake
"MT_SPLISH", // Water splish!
"MT_LAVASPLISH", // Lava splish!
"MT_SMOKE",
"MT_SMALLBUBBLE", // small bubble
"MT_MEDIUMBUBBLE", // medium bubble
@ -8335,6 +8561,8 @@ static const char *const POWERS_LIST[] = {
"SPACETIME", // In space, no one can hear you spin!
"EXTRALIFE", // Extra Life timer
"PUSHING",
"JUSTSPRUNG",
"NOAUTOBRAKE",
"SUPER", // Are you super?
"GRAVITYBOOTS", // gravity boots
@ -8615,15 +8843,6 @@ struct {
{"LF2_NOVISITNEEDED",LF2_NOVISITNEEDED},
{"LF2_WIDEICON",LF2_WIDEICON},
// NiGHTS grades
{"GRADE_F",GRADE_F},
{"GRADE_E",GRADE_E},
{"GRADE_D",GRADE_D},
{"GRADE_C",GRADE_C},
{"GRADE_B",GRADE_B},
{"GRADE_A",GRADE_A},
{"GRADE_S",GRADE_S},
// Emeralds
{"EMERALD1",EMERALD1},
{"EMERALD2",EMERALD2},
@ -8684,6 +8903,8 @@ struct {
{"CR_ROPEHANG",CR_ROPEHANG},
{"CR_MACESPIN",CR_MACESPIN},
{"CR_MINECART",CR_MINECART},
{"CR_ROLLOUT", CR_ROLLOUT},
{"CR_PTERABYTE",CR_PTERABYTE},
// Ring weapons (ringweapons_t)
// Useful for A_GiveWeapon
@ -8905,9 +9126,9 @@ struct {
{"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top.
{"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
{"FF_INTANGABLEFLATS",FF_INTANGABLEFLATS}, ///< Both flats are intangable, but the sides are still solid.
{"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Thinks everyone's Knuckles.
{"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Jump or fall onto it while curled in a ball.
{"FF_ONLYKNUX",FF_ONLYKNUX}, ///< Used with ::FF_BUSTUP. Only Knuckles can break this rock.
{"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Bustable on mere touch.
{"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames.
{"FF_STRONGBUST",FF_STRONGBUST }, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee).
{"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats
{"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel
{"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
@ -9038,6 +9259,7 @@ struct {
{"V_OFFSET",V_OFFSET},
{"V_ALLOWLOWERCASE",V_ALLOWLOWERCASE},
{"V_FLIP",V_FLIP},
{"V_CENTERNAMETAG",V_CENTERNAMETAG},
{"V_SNAPTOTOP",V_SNAPTOTOP},
{"V_SNAPTOBOTTOM",V_SNAPTOBOTTOM},
{"V_SNAPTOLEFT",V_SNAPTOLEFT},
@ -9445,6 +9667,19 @@ static fixed_t find_const(const char **rword)
free(word);
return 0;
}
else if (fastncmp("GRADE_",word,6))
{
char *p = word+6;
for (i = 0; NIGHTSGRADE_LIST[i]; i++)
if (*p == NIGHTSGRADE_LIST[i])
{
free(word);
return i;
}
const_warning("NiGHTS grade",word);
free(word);
return 0;
}
for (i = 0; INT_CONST[i].n; i++)
if (fastcmp(word,INT_CONST[i].n)) {
free(word);
@ -9893,6 +10128,18 @@ static inline int lib_getenum(lua_State *L)
if (mathlib) return luaL_error(L, "skincolor '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GRADE_",word,6))
{
p = word+6;
for (i = 0; NIGHTSGRADE_LIST[i]; i++)
if (*p == NIGHTSGRADE_LIST[i])
{
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MN_",word,3)) {
p = word+3;
for (i = 0; i < NUMMENUTYPES; i++)
@ -10032,6 +10279,23 @@ static inline int lib_getenum(lua_State *L)
} else if (fastcmp(word,"mapmusposition")) {
lua_pushinteger(L, mapmusposition);
return 1;
// local player variables, by popular request
} else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1)
if (consoleplayer < 0 || !playeringame[consoleplayer])
return 0;
LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"displayplayer")) { // player visible on screen (aka display player 1)
if (displayplayer < 0 || !playeringame[displayplayer])
return 0;
LUA_PushUserdata(L, &players[displayplayer], META_PLAYER);
return 1;
} else if (fastcmp(word,"secondarydisplayplayer")) { // local/display player 2, for splitscreen
if (!splitscreen || secondarydisplayplayer < 0 || !playeringame[secondarydisplayplayer])
return 0;
LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER);
return 1;
// end local player variables
} else if (fastcmp(word,"server")) {
if ((!multiplayer || !netgame) && !playeringame[serverplayer])
return 0;

View File

@ -210,7 +210,7 @@ typedef struct
extern const UINT8 Color_Index[MAXTRANSLATIONS-1][16];
extern const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS];
extern const UINT8 Color_Opposite[(MAXSKINCOLORS - 1)*2];
extern const UINT8 Color_Opposite[MAXSKINCOLORS - 1][2];
#define NUMMAPS 1035

View File

@ -148,7 +148,7 @@ extern FILE *logstream;
// Does this version require an added patch file?
// Comment or uncomment this as necessary.
#define USE_PATCH_DTA
//#define USE_PATCH_DTA
// Use .kart extension addons
//#define USE_KART
@ -206,7 +206,7 @@ extern FILE *logstream;
// 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.1.0 is not version "1".
#define MODVERSION 28
#define MODVERSION 30
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
// Increment MINOREXECVERSION whenever a config change is needed that does not correspond
@ -506,13 +506,20 @@ INT32 I_GetKey(void);
#define max(x, y) (((x) > (y)) ? (x) : (y))
#endif
// Max gamepad/joysticks that can be detected/used.
#define MAX_JOYSTICKS 4
#ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L
#endif
// Floating point comparison epsilons from float.h
#ifndef FLT_EPSILON
#define FLT_EPSILON 1.1920928955078125e-7f
#endif
#ifndef DBL_EPSILON
#define DBL_EPSILON 2.2204460492503131e-16
#define DBL_EPSILON 2.2204460492503131e-16l
#endif
// An assert-type mechanism.
@ -558,9 +565,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Polyobject fake flat code
#define POLYOBJECTS_PLANES
/// Improved way of dealing with ping values and a ping limit.
#define NEWPING
/// See name of player in your crosshair
#define SEENAMES
@ -616,4 +620,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// SRB2CB itself ported this from PrBoom+
#define NEWCLIP
#ifndef HAVE_PNG
#define NO_PNG_LUMPS
#endif
#endif // __DOOMDEF__

View File

@ -327,12 +327,14 @@ typedef struct
// Music stuff.
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
char musintername[7]; ///< Intermission screen music.
char muspostbossname[7]; ///< Post-bossdeath music.
UINT16 muspostbosstrack; ///< Post-bossdeath track.
UINT32 muspostbosspos; ///< Post-bossdeath position
UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds.
SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on)
// Lua stuff.
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
@ -418,6 +420,10 @@ extern UINT16 emeralds;
#define EMERALD7 64
#define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7))
// yes, even in non HAVE_BLUA
#define NUM_LUABANKS 16 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8
extern INT32 luabanks[NUM_LUABANKS];
extern INT32 nummaprings; //keep track of spawned rings/coins
/** Time attack information, currently a very small structure.
@ -427,6 +433,7 @@ typedef struct
tic_t time; ///< Time in which the level was finished.
UINT32 score; ///< Score when the level was finished.
UINT16 rings; ///< Rings when the level was finished.
boolean gotperfect; ///< Got perfect bonus?
} recorddata_t;
/** Setup for one NiGHTS map.

View File

@ -46,7 +46,7 @@
// Stage of animation:
// 0 = text, 1 = art screen
static INT32 finalecount;
INT32 titlescrollxspeed = 80;
INT32 titlescrollxspeed = 20;
INT32 titlescrollyspeed = 0;
UINT8 titlemapinaction = TITLEMAP_OFF;
@ -74,6 +74,7 @@ INT32 curbgcolor;
INT32 curbgxspeed;
INT32 curbgyspeed;
boolean curbghide;
boolean hidetitlemap; // WARNING: set to false by M_SetupNextMenu and M_ClearMenus
static UINT8 curDemo = 0;
static UINT32 demoDelayLeft;
@ -670,6 +671,7 @@ static void F_IntroDrawScene(void)
}
else
{
menuanimtimer = animtimer; // Reusing this variable for the intro to fix the scrolling sky, better than changing the function around.
F_SkyScroll(80*4, 0, "TITLESKY");
if (timetonext == 6)
{
@ -1617,22 +1619,22 @@ void F_StartEnding(void)
UINT8 skinnum = players[consoleplayer].skin;
spritedef_t *sprdef;
spriteframe_t *sprframe;
if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 5)
if (skins[skinnum].sprites[SPR2_XTRA].numframes >= (XTRA_ENDING+2)+1)
{
sprdef = &skins[skinnum].sprites[SPR2_XTRA];
// character head, skin specific
sprframe = &sprdef->spriteframes[2];
sprframe = &sprdef->spriteframes[XTRA_ENDING];
endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
sprframe = &sprdef->spriteframes[3];
sprframe = &sprdef->spriteframes[XTRA_ENDING+1];
endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
sprframe = &sprdef->spriteframes[4];
sprframe = &sprdef->spriteframes[XTRA_ENDING+2];
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
}
else // eh, yknow what? too lazy to put MISSINGs here. eggman wins if you don't give your character an ending firework display.
else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this)
{
endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_LEVEL);
endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_LEVEL);
endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_LEVEL);
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_LEVEL);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_LEVEL);
endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_LEVEL);
}
endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_LEVEL);
@ -2129,9 +2131,9 @@ void F_InitMenuPresValues(void)
strncpy(curbgname, "TITLESKY", 9);
curfadevalue = 16;
curbgcolor = -1;
curbgxspeed = titlescrollxspeed;
curbgyspeed = titlescrollyspeed;
curbghide = true;
curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
curbgyspeed = (gamestate == GS_TIMEATTACK) ? 22 : titlescrollyspeed;
curbghide = (gamestate == GS_TIMEATTACK) ? false : true;
curhidepics = hidetitlepics;
curttmode = ttmode;
@ -2144,7 +2146,7 @@ void F_InitMenuPresValues(void)
curtttics = tttics;
// Find current presentation values
M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "SRB2BACK" : "TITLESKY");
M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY");
M_SetMenuCurFadeValue(16);
M_SetMenuCurTitlePics();
}
@ -2636,6 +2638,11 @@ void F_TitleDemoTicker(void)
// ==========
// CONTINUE
// ==========
static skin_t *contskins[2];
static UINT8 cont_spr2[2][6];
static UINT8 *contcolormaps[2];
void F_StartContinue(void)
{
I_Assert(!netgame && !multiplayer);
@ -2659,7 +2666,44 @@ void F_StartContinue(void)
S_ChangeMusicInternal("_conti", false);
S_StopSounds();
timetonext = TICRATE*11;
contskins[0] = &skins[players[consoleplayer].skin];
cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT1, NULL);
cont_spr2[0][2] = contskins[0]->contangle & 7;
contcolormaps[0] = R_GetTranslationColormap(players[consoleplayer].skin, players[consoleplayer].skincolor, GTC_CACHE);
cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes;
cont_spr2[0][5] = max(1, contskins[0]->contspeed);
if (botskin)
{
INT32 secondplaya;
if (secondarydisplayplayer != consoleplayer)
secondplaya = secondarydisplayplayer;
else // HACK
secondplaya = 1;
contskins[1] = &skins[players[secondplaya].skin];
cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT4, NULL);
cont_spr2[1][2] = (contskins[1]->contangle >> 3) & 7;
contcolormaps[1] = R_GetTranslationColormap(players[secondplaya].skin, players[secondplaya].skincolor, GTC_CACHE);
cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes;
if (cont_spr2[1][0] == SPR2_CNT4)
cont_spr2[1][5] = 4; // sorry, this one is hardcoded
else
cont_spr2[1][5] = max(1, contskins[1]->contspeed);
}
else
{
contskins[1] = NULL;
contcolormaps[1] = NULL;
cont_spr2[1][0] = cont_spr2[1][2] = cont_spr2[1][4] = cont_spr2[1][5] = 0;
}
cont_spr2[0][1] = cont_spr2[0][3] =\
cont_spr2[1][1] = cont_spr2[1][3] = 0;
timetonext = (11*TICRATE)+11;
continuetime = 0;
}
//
@ -2668,47 +2712,198 @@ void F_StartContinue(void)
//
void F_ContinueDrawer(void)
{
patch_t *contsonic;
INT32 i, x = (BASEVIDWIDTH/2) + 4, ncontinues = players[consoleplayer].continues;
if (ncontinues > 20)
ncontinues = 20;
spritedef_t *sprdef;
spriteframe_t *sprframe;
patch_t *patch;
INT32 i, x = (BASEVIDWIDTH>>1), ncontinues = players[consoleplayer].continues;
char numbuf[9] = "CONTNUM*";
tic_t timeleft = (timetonext/TICRATE);
INT32 offsx = 0, offsy = 0, lift[2] = {0, 0};
if (imcontinuing)
contsonic = W_CachePatchName("CONT2", PU_CACHE);
else
contsonic = W_CachePatchName("CONT1", PU_CACHE);
if (continuetime >= 3*TICRATE)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0);
return;
}
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawCenteredString(BASEVIDWIDTH/2, 100, 0, "CONTINUE?");
// Draw a Sonic!
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(contsonic->width))/2, 32, 0, contsonic);
if (timetonext >= (11*TICRATE)+10)
return;
// Draw the continue markers! Show continues minus one.
x -= ncontinues * 6;
for (i = 0; i < ncontinues; ++i)
V_DrawContinueIcon(x + (i*12), 140, 0, players[consoleplayer].skin, players[consoleplayer].skincolor);
V_DrawLevelTitle(x - (V_LevelNameWidth("CONTINUE")>>1), 16, 0, "CONTINUE");
V_DrawCenteredString(BASEVIDWIDTH/2, 168, 0, va("\x82*\x80" " %02d " "\x82*\x80", timetonext/TICRATE));
// Two stars...
patch = W_CachePatchName("CONTSTAR", PU_CACHE);
V_DrawScaledPatch(x-32, 160, 0, patch);
V_DrawScaledPatch(x+32, 160, 0, patch);
// Time left!
if (timeleft > 9)
{
numbuf[7] = '1';
V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE));
numbuf[7] = '0';
V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_CACHE));
}
else
{
numbuf[7] = '0'+timeleft;
V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_CACHE));
}
// Draw the continue markers! Show continues.
if (ncontinues > 10)
{
if (!(continuetime & 1) || continuetime > 17)
V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor);
V_DrawScaledPatch(x+12, 68-2, 0, stlivex);
V_DrawRightAlignedString(x+36, 69-5, 0,
va("%d",(imcontinuing ? ncontinues-1 : ncontinues)));
}
else
{
x += (ncontinues/2) * 30;
if (!(ncontinues & 1))
x -= 15;
for (i = 0; i < ncontinues; ++i)
{
if (i == (ncontinues/2) && ((continuetime & 1) || continuetime > 17))
continue;
V_DrawContinueIcon(x - (i*30), 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor);
}
x = BASEVIDWIDTH>>1;
}
// Spotlight
V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_CACHE));
// warping laser
if (continuetime)
{
INT32 w = min(continuetime, 28), brightness = (continuetime>>1) & 7;
if (brightness > 3)
brightness = 8-brightness;
V_DrawFadeFill(x-w, 0, w<<1, 140, 0, 0, (3+brightness));
}
if (contskins[1])
{
if (continuetime > 15)
{
angle_t work = FixedAngle((10*(continuetime-15))<<FRACBITS)>>ANGLETOFINESHIFT;
offsy = FINESINE(work)<<1;
offsx = (27*FINECOSINE(work))>>1;
}
else
offsx = 27<<(FRACBITS-1);
lift[1] = continuetime-10;
if (lift[1] < 0)
lift[1] = 0;
else if (lift[1] > TICRATE+5)
lift[1] = TICRATE+5;
}
lift[0] = continuetime-5;
if (lift[0] < 0)
lift[0] = 0;
else if (lift[0] > TICRATE+5)
lift[0] = TICRATE+5;
#define drawchar(dx, dy, n) {\
sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\
sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\
patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_CACHE);\
V_DrawFixedPatch((dx), (dy), FRACUNIT, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\
}
if (offsy < 0)
drawchar((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])<<FRACBITS)-offsy, 0);
if (contskins[1])
drawchar((BASEVIDWIDTH<<(FRACBITS-1))+offsx, ((140-lift[1])<<FRACBITS)+offsy, 1);
if (offsy >= 0)
drawchar((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])<<FRACBITS)-offsy, 0);
#undef drawchar
if (timetonext > (11*TICRATE))
V_DrawFadeScreen(31, timetonext-(11*TICRATE));
if (continuetime > ((3*TICRATE) - 10))
V_DrawFadeScreen(0, (continuetime - ((3*TICRATE) - 10)));
}
void F_ContinueTicker(void)
{
if (!imcontinuing)
{
// note the setup to prevent 2x reloading
if (timetonext >= 0)
timetonext--;
if (timetonext == 0)
Command_ExitGame_f();
if (timetonext > 0)
{
if (!(--timetonext))
{
Command_ExitGame_f();
return;
}
}
}
else
{
// note the setup to prevent 2x reloading
if (continuetime >= 0)
continuetime--;
if (continuetime == 0)
if (++continuetime == 3*TICRATE)
{
G_Continue();
return;
}
if (continuetime > 5 && ((continuetime & 1) || continuetime > TICRATE) && (++cont_spr2[0][2]) >= 8)
cont_spr2[0][2] = 0;
if (continuetime > 10 && (!(continuetime & 1) || continuetime > TICRATE+5) && (++cont_spr2[1][2]) >= 8)
cont_spr2[1][2] = 0;
if (continuetime == (3*TICRATE)-10)
S_StartSound(NULL, sfx_cdfm56); // or 31
else if (continuetime == 5)
{
cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT2, NULL);
cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes;
cont_spr2[0][1] = cont_spr2[0][3] = 0;
cont_spr2[0][5] = 2;
}
else if (continuetime == TICRATE)
{
cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT3, NULL);
cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes;
cont_spr2[0][1] = cont_spr2[0][3] = 0;
}
else if (contskins[1])
{
if (continuetime == 10)
{
cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT2, NULL);
cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes;
cont_spr2[1][1] = cont_spr2[1][3] = 0;
cont_spr2[1][5] = 2;
}
else if (continuetime == TICRATE+5)
{
cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT3, NULL);
cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes;
cont_spr2[1][1] = cont_spr2[1][3] = 0;
}
}
}
if ((++cont_spr2[0][3]) >= cont_spr2[0][5])
{
cont_spr2[0][3] = 0;
if (++cont_spr2[0][1] >= cont_spr2[0][4])
cont_spr2[0][1] = 0;
}
if (contskins[1] && (++cont_spr2[1][3]) >= cont_spr2[1][5])
{
cont_spr2[1][3] = 0;
if (++cont_spr2[1][1] >= cont_spr2[1][4])
cont_spr2[1][1] = 0;
}
}
@ -2739,8 +2934,9 @@ boolean F_ContinueResponder(event_t *event)
keypressed = true;
imcontinuing = true;
continuetime = TICRATE;
S_StartSound(NULL, sfx_itemup);
S_StartSound(NULL, sfx_kc6b);
I_FadeSong(0, MUSICRATE, &S_StopMusic);
return true;
}

View File

@ -114,6 +114,7 @@ extern INT32 curbgcolor;
extern INT32 curbgxspeed;
extern INT32 curbgyspeed;
extern boolean curbghide;
extern boolean hidetitlemap;
extern boolean curhidepics;
extern ttmode_enum curttmode;

View File

@ -751,7 +751,7 @@ boolean preparefilemenu(boolean samedepth)
}
else if (ext == EXT_TXT)
{
if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
if (!strncmp(dent->d_name, "log-", 4) || !strcmp(dent->d_name, "errorlog.txt"))
ext |= EXT_LOADED;
}

View File

@ -97,7 +97,7 @@ boolean runemeraldmanager = false;
UINT16 emeraldspawndelay = 60*TICRATE;
// menu demo things
UINT8 numDemos = 3;
UINT8 numDemos = 0;
UINT32 demoDelayTime = 15*TICRATE;
UINT32 demoIdleTime = 3*TICRATE;
@ -172,6 +172,7 @@ static boolean retrying = false;
UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage.
UINT16 emeralds;
INT32 luabanks[NUM_LUABANKS]; // yes, even in non HAVE_BLUA
UINT32 token; // Number of tokens collected in a level
UINT32 tokenlist; // List of tokens collected
boolean gottoken; // Did you get a token? Used for end of act
@ -215,7 +216,9 @@ UINT16 spacetimetics = 11*TICRATE + (TICRATE/2);
UINT16 extralifetics = 4*TICRATE;
UINT16 nightslinktics = 2*TICRATE;
INT32 gameovertics = 15*TICRATE;
INT32 gameovertics = 11*TICRATE;
UINT8 ammoremovaltics = 2*TICRATE;
UINT8 use1upSound = 0;
UINT8 maxXtraLife = 2; // Max extra lives from rings
@ -358,6 +361,8 @@ consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, N
static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}};
consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// Pause game upon window losing focus
consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -416,49 +421,13 @@ consvar_t cv_spinaxis2 = {"joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#if MAXPLAYERS > 32
#error "please update player_name table using the new value for MAXPLAYERS"
#endif
#ifdef SEENAMES
player_t *seenplayer; // player we're aiming at right now
#endif
char player_names[MAXPLAYERS][MAXPLAYERNAME+1] =
{
"Player 1",
"Player 2",
"Player 3",
"Player 4",
"Player 5",
"Player 6",
"Player 7",
"Player 8",
"Player 9",
"Player 10",
"Player 11",
"Player 12",
"Player 13",
"Player 14",
"Player 15",
"Player 16",
"Player 17",
"Player 18",
"Player 19",
"Player 20",
"Player 21",
"Player 22",
"Player 23",
"Player 24",
"Player 25",
"Player 26",
"Player 27",
"Player 28",
"Player 29",
"Player 30",
"Player 31",
"Player 32"
};
// now automatically allocated in D_RegisterClientCommands
// so that it doesn't have to be updated depending on the value of MAXPLAYERS
char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
INT16 rw_maximums[NUM_WEAPONS] =
{
@ -919,6 +888,7 @@ static fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
{
boolean forcestrafe = false;
boolean forcefullinput = false;
INT32 tspeed, forward, side, axis, altaxis, i;
const INT32 speed = 1;
// these ones used for multiple conditions
@ -992,6 +962,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]);
}
if (twodlevel
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| (!demoplayback && (player->pflags & PF_SLIDING)))
forcefullinput = true;
if (twodlevel
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| (!demoplayback && (player->climbing
@ -1205,11 +1179,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
// No additional acceleration when moving forward/backward and strafing simultaneously.
// do this AFTER we cap to MAXPLMOVE so people can't find ways to cheese around this.
// 9-18-2017: ALSO, only do this when using keys to move. Gamepad analog sticks get severely gimped by this
if (!forcestrafe && (((movefkey || movebkey) && side) || ((strafelkey || straferkey) && forward)))
if (!forcefullinput && forward && side)
{
forward = FixedMul(forward, 3*FRACUNIT/4);
side = FixedMul(side, 3*FRACUNIT/4);
angle_t angle = R_PointToAngle2(0, 0, side << FRACBITS, forward << FRACBITS);
INT32 maxforward = abs(P_ReturnThrustY(NULL, angle, MAXPLMOVE));
INT32 maxside = abs(P_ReturnThrustX(NULL, angle, MAXPLMOVE));
forward = max(min(forward, maxforward), -maxforward);
side = max(min(side, maxside), -maxside);
}
//Silly hack to make 2d mode *somewhat* playable with no chasecam.
@ -1245,6 +1221,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
{
boolean forcestrafe = false;
boolean forcefullinput = false;
INT32 tspeed, forward, side, axis, altaxis, i;
const INT32 speed = 1;
// these ones used for multiple conditions
@ -1316,6 +1293,10 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]);
}
if (twodlevel
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| (!demoplayback && (player->pflags & PF_SLIDING)))
forcefullinput = true;
if (twodlevel
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| player->climbing
@ -1526,11 +1507,13 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
// No additional acceleration when moving forward/backward and strafing simultaneously.
// do this AFTER we cap to MAXPLMOVE so people can't find ways to cheese around this.
// 9-18-2017: ALSO, only do this when using keys to move. Gamepad analog sticks get severely gimped by this
if (!forcestrafe && (((movefkey || movebkey) && side) || ((strafelkey || straferkey) && forward)))
if (!forcefullinput && forward && side)
{
forward = FixedMul(forward, 3*FRACUNIT/4);
side = FixedMul(side, 3*FRACUNIT/4);
angle_t angle = R_PointToAngle2(0, 0, side << FRACBITS, forward << FRACBITS);
INT32 maxforward = abs(P_ReturnThrustY(NULL, angle, MAXPLMOVE));
INT32 maxside = abs(P_ReturnThrustX(NULL, angle, MAXPLMOVE));
forward = max(min(forward, maxforward), -maxforward);
side = max(min(side, maxside), -maxside);
}
//Silly hack to make 2d mode *somewhat* playable with no chasecam.
@ -1732,65 +1715,6 @@ static INT32 camtoggledelay, camtoggledelay2 = 0;
//
boolean G_Responder(event_t *ev)
{
// allow spy mode changes even during the demo
if (gamestate == GS_LEVEL && ev->type == ev_keydown
&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
{
if (splitscreen || !netgame)
displayplayer = consoleplayer;
else
{
// spy mode
do
{
displayplayer++;
if (displayplayer == MAXPLAYERS)
displayplayer = 0;
if (!playeringame[displayplayer])
continue;
if (players[displayplayer].spectator)
continue;
if (G_GametypeHasTeams())
{
if (players[consoleplayer].ctfteam
&& players[displayplayer].ctfteam != players[consoleplayer].ctfteam)
continue;
}
else if (gametype == GT_HIDEANDSEEK)
{
if (players[consoleplayer].pflags & PF_TAGIT)
continue;
}
// Other Tag-based gametypes?
else if (G_TagGametype())
{
if (!players[consoleplayer].spectator
&& (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT))
continue;
}
else if (G_GametypeHasSpectators() && G_RingSlingerGametype())
{
if (!players[consoleplayer].spectator)
continue;
}
break;
} while (displayplayer != consoleplayer);
// change statusbar also if playing back demo
if (singledemo)
ST_changeDemoView();
// tell who's the view
CONS_Printf(M_GetText("Viewpoint: %s\n"), player_names[displayplayer]);
return true;
}
}
// any other key pops up menu if in demos
if (gameaction == ga_nothing && !singledemo &&
((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN))
@ -1867,6 +1791,65 @@ boolean G_Responder(event_t *ev)
if (HU_Responder(ev))
return true; // chat ate the event
// allow spy mode changes even during the demo
if (gamestate == GS_LEVEL && ev->type == ev_keydown
&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
{
if (splitscreen || !netgame)
displayplayer = consoleplayer;
else
{
// spy mode
do
{
displayplayer++;
if (displayplayer == MAXPLAYERS)
displayplayer = 0;
if (!playeringame[displayplayer])
continue;
if (players[displayplayer].spectator)
continue;
if (G_GametypeHasTeams())
{
if (players[consoleplayer].ctfteam
&& players[displayplayer].ctfteam != players[consoleplayer].ctfteam)
continue;
}
else if (gametype == GT_HIDEANDSEEK)
{
if (players[consoleplayer].pflags & PF_TAGIT)
continue;
}
// Other Tag-based gametypes?
else if (G_TagGametype())
{
if (!players[consoleplayer].spectator
&& (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT))
continue;
}
else if (G_GametypeHasSpectators() && G_RingSlingerGametype())
{
if (!players[consoleplayer].spectator)
continue;
}
break;
} while (displayplayer != consoleplayer);
// change statusbar also if playing back demo
if (singledemo)
ST_changeDemoView();
// tell who's the view
CONS_Printf(M_GetText("Viewpoint: %s\n"), player_names[displayplayer]);
return true;
}
}
// update keys current state
G_MapEventsToControls(ev);
@ -2117,6 +2100,7 @@ static inline void G_PlayerFinishLevel(INT32 player)
p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility
P_FlashPal(p, 0, 0); // Resets
p->starpostscale = 0;
p->starpostangle = 0;
p->starposttime = 0;
p->starpostx = 0;
@ -2132,7 +2116,7 @@ static inline void G_PlayerFinishLevel(INT32 player)
// G_PlayerReborn
// Called after a player dies. Almost everything is cleared and initialized.
//
void G_PlayerReborn(INT32 player)
void G_PlayerReborn(INT32 player, boolean betweenmaps)
{
player_t *p;
INT32 score;
@ -2163,6 +2147,7 @@ void G_PlayerReborn(INT32 player)
INT16 starpostz;
INT32 starpostnum;
INT32 starpostangle;
fixed_t starpostscale;
fixed_t jumpfactor;
fixed_t height;
fixed_t spinheight;
@ -2179,6 +2164,8 @@ void G_PlayerReborn(INT32 player)
boolean outofcoop;
INT16 bot;
SINT8 pity;
INT16 rings;
INT16 spheres;
score = players[player].score;
lives = players[player].lives;
@ -2218,6 +2205,7 @@ void G_PlayerReborn(INT32 player)
starpostz = players[player].starpostz;
starpostnum = players[player].starpostnum;
starpostangle = players[player].starpostangle;
starpostscale = players[player].starpostscale;
jumpfactor = players[player].jumpfactor;
height = players[player].height;
spinheight = players[player].spinheight;
@ -2233,6 +2221,17 @@ void G_PlayerReborn(INT32 player)
bot = players[player].bot;
pity = players[player].pity;
if (betweenmaps || !G_IsSpecialStage(gamemap))
{
rings = (ultimatemode ? 0 : mapheaderinfo[gamemap-1]->startrings);
spheres = 0;
}
else
{
rings = players[player].rings;
spheres = players[player].spheres;
}
p = &players[player];
memset(p, 0, sizeof (*p));
@ -2273,6 +2272,7 @@ void G_PlayerReborn(INT32 player)
p->starpostz = starpostz;
p->starpostnum = starpostnum;
p->starpostangle = starpostangle;
p->starpostscale = starpostscale;
p->jumpfactor = jumpfactor;
p->height = height;
p->spinheight = spinheight;
@ -2286,6 +2286,8 @@ void G_PlayerReborn(INT32 player)
if (bot)
p->bot = 1; // reset to AI-controlled
p->pity = pity;
p->rings = rings;
p->spheres = spheres;
// Don't do anything immediately
p->pflags |= PF_USEDOWN;
@ -2293,44 +2295,11 @@ void G_PlayerReborn(INT32 player)
p->pflags |= PF_JUMPDOWN;
p->playerstate = PST_LIVE;
p->rings = p->spheres = 0; // 0 rings
p->panim = PA_IDLE; // standing animation
//if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there
//p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
if (p-players == consoleplayer)
{
if (mapmusflags & MUSIC_RELOADRESET)
{
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
mapmusname[6] = 0;
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
}
// This is in S_Start, but this was not here previously.
// if (cv_resetmusic.value)
// S_StopMusic();
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
if (gametype == GT_COOP)
P_FindEmerald(); // scan for emeralds to hunt for
// Reset Nights score and max link to 0 on death
p->marescore = p->maxlink = 0;
// If NiGHTS, find lowest mare to start with.
p->mare = P_FindLowestMare();
CONS_Debug(DBG_NIGHTS, M_GetText("Current mare is %d\n"), p->mare);
if (p->mare == 255)
p->mare = 0;
p->marelap = p->marebonuslap = 0;
// Check to make sure their color didn't change somehow...
if (G_GametypeHasTeams())
{
@ -2349,6 +2318,36 @@ void G_PlayerReborn(INT32 player)
CV_SetValue(&cv_playercolor2, skincolor_blueteam);
}
}
if (betweenmaps)
return;
if (p-players == consoleplayer)
{
if (mapmusflags & MUSIC_RELOADRESET)
{
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
mapmusname[6] = 0;
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
}
// This is in S_Start, but this was not here previously.
// if (RESETMUSIC)
// S_StopMusic();
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
}
if (gametype == GT_COOP)
P_FindEmerald(); // scan for emeralds to hunt for
// If NiGHTS, find lowest mare to start with.
p->mare = P_FindLowestMare();
CONS_Debug(DBG_NIGHTS, M_GetText("Current mare is %d\n"), p->mare);
if (p->mare == 255)
p->mare = 0;
}
//
@ -2404,8 +2403,6 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
P_SpawnPlayer(playernum);
players[playernum].rings = mapheaderinfo[gamemap-1]->startrings;
if (starpost) //Don't even bother with looking for a place to spawn.
{
P_MovePlayerToStarpost(playernum);
@ -2628,7 +2625,7 @@ void G_DoReborn(INT32 playernum)
if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP))
resetlevel = true;
else if (gametype == GT_COOP && (netgame || multiplayer))
else if (gametype == GT_COOP && (netgame || multiplayer) && !G_IsSpecialStage(gamemap))
{
boolean notgameover = true;
@ -2691,6 +2688,7 @@ void G_DoReborn(INT32 playernum)
{
if (!playeringame[i])
continue;
players[i].starpostscale = 0;
players[i].starpostangle = 0;
players[i].starposttime = 0;
players[i].starpostx = 0;
@ -2813,6 +2811,7 @@ void G_AddPlayer(INT32 playernum)
if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum)))
continue;
p->starpostscale = players[i].starpostscale;
p->starposttime = players[i].starposttime;
p->starpostx = players[i].starpostx;
p->starposty = players[i].starposty;
@ -3321,9 +3320,11 @@ void G_LoadGameSettings(void)
{
// defaults
spstage_start = 1;
sstage_start = smpstage_start = 50;
sstage_end = smpstage_end = 56; // 7 special stages in vanilla SRB2
sstage_start = 50;
sstage_end = 56; // 7 special stages in vanilla SRB2
sstage_end++; // plus one weirdo
smpstage_start = 60;
smpstage_end = 66; // 7 multiplayer special stages too
// initialize free sfx slots for skin sounds
S_InitRuntimeSounds();
@ -3342,6 +3343,7 @@ void G_LoadGameData(void)
UINT32 recscore;
tic_t rectime;
UINT16 recrings;
boolean gotperf;
UINT8 recmares;
INT32 curmare;
@ -3434,6 +3436,7 @@ void G_LoadGameData(void)
recscore = READUINT32(save_p);
rectime = (tic_t)READUINT32(save_p);
recrings = READUINT16(save_p);
gotperf = (boolean)READUINT8(save_p);
if (recrings > 10000 || recscore > MAXSCORE)
goto datacorrupt;
@ -3445,6 +3448,9 @@ void G_LoadGameData(void)
mainrecords[i]->time = rectime;
mainrecords[i]->rings = recrings;
}
if (gotperf)
mainrecords[i]->gotperfect = gotperf;
}
// Nights records
@ -3576,12 +3582,14 @@ void G_SaveGameData(void)
WRITEUINT32(save_p, mainrecords[i]->score);
WRITEUINT32(save_p, mainrecords[i]->time);
WRITEUINT16(save_p, mainrecords[i]->rings);
WRITEUINT8(save_p, mainrecords[i]->gotperfect);
}
else
{
WRITEUINT32(save_p, 0);
WRITEUINT32(save_p, 0);
WRITEUINT16(save_p, 0);
WRITEUINT8(save_p, 0);
}
}
@ -3814,7 +3822,29 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
// File end marker check
CHECKPOS
if (READUINT8(save_p) != 0x1d) BADSAVE;
switch (READUINT8(save_p))
{
case 0xb7:
{
UINT8 i, banksinuse;
CHECKPOS
banksinuse = READUINT8(save_p);
CHECKPOS
if (banksinuse > NUM_LUABANKS)
BADSAVE
for (i = 0; i < banksinuse; i++)
{
(void)READINT32(save_p);
CHECKPOS
}
if (READUINT8(save_p) != 0x1d)
BADSAVE
}
case 0x1d:
break;
default:
BADSAVE
}
// done
saved = FIL_WriteFile(backup, savebuffer, length);
@ -3898,7 +3928,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
for (i = 0; i < MAXPLAYERS; i++)
{
players[i].playerstate = PST_REBORN;
players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
players[i].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
players[i].starpostx = players[i].starposty = players[i].starpostz = 0;
if (netgame || multiplayer)
@ -4609,7 +4639,7 @@ void G_GhostTicker(void)
default:
case GHC_RETURNSKIN:
g->mo->skin = g->oldmo.skin;
// fallthru
/* FALLTHRU */
case GHC_NORMAL: // Go back to skin color
g->mo->color = g->oldmo.color;
break;

View File

@ -51,6 +51,7 @@ extern tic_t levelstarttic;
// for modding?
extern INT16 prevmap, nextmap;
extern INT32 gameovertics;
extern UINT8 ammoremovaltics;
extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
extern INT16 rw_maximums[NUM_WEAPONS];
extern INT32 pausedelay;
@ -58,6 +59,8 @@ extern boolean pausebreakkey;
extern boolean promptactive;
extern consvar_t cv_pauseifunfocused;
// used in game menu
extern consvar_t cv_tutorialprompt;
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard;
@ -99,7 +102,7 @@ extern INT32 localaiming, localaiming2; // should be an angle_t but signed
//
void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo);
void G_DoReborn(INT32 playernum);
void G_PlayerReborn(INT32 player);
void G_PlayerReborn(INT32 player, boolean betweenmaps);
void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer,
boolean skipprecutscene, boolean FLS);
char *G_BuildMapTitle(INT32 mapnum);

View File

@ -709,8 +709,8 @@ void G_DefineDefaultControls(void)
for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
{
gamecontroldefault[i][gc_weaponnext ][0] = 'e';
gamecontroldefault[i][gc_weaponprev ][0] = 'q';
gamecontroldefault[i][gc_weaponnext ][0] = KEY_MOUSEWHEELUP+0;
gamecontroldefault[i][gc_weaponprev ][0] = KEY_MOUSEWHEELDOWN+0;
gamecontroldefault[i][gc_wepslot1 ][0] = '1';
gamecontroldefault[i][gc_wepslot2 ][0] = '2';
gamecontroldefault[i][gc_wepslot3 ][0] = '3';

View File

@ -201,7 +201,7 @@ static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1,
// (do not accept hit with the extensions)
num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx;
frac = num / den;
if (frac < 0.0 || frac > 1.0)
if (frac < 0.0l || frac > 1.0l)
return NULL;
// now get the frac along the BSP line

View File

@ -30,6 +30,7 @@
#include "../z_zone.h"
#include "../v_video.h"
#include "../r_draw.h"
#include "../p_setup.h"
//Hurdler: 25/04/2000: used for new colormap code in hardware mode
//static UINT8 *gr_colormap = NULL; // by default it must be NULL ! (because colormap tables are not initialized)
@ -60,7 +61,6 @@ static const INT32 format2bpp[16] =
2, //14 GR_TEXFMT_AP_88
};
// This code was originally placed directly in HWR_DrawPatchInCache.
// It is now split from it for my sanity! (and the sanity of others)
// -- Monster Iestyn (13/02/19)
@ -138,18 +138,37 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
// Alam: SRB2 uses Mingw, HUGS
switch (bpp)
{
case 2 : texelu16 = (UINT16)((alpha<<8) | texel);
case 2 : // uhhhhhhhh..........
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha);
texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
rgbatexel.rgba = *(UINT32 *)dest;
colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha);
}
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4 : colortemp = V_GetColor(texel);
colortemp.s.alpha = alpha;
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
rgbatexel.rgba = *(UINT32 *)dest;
colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha);
}
memcpy(dest, &colortemp, sizeof(RGBA_t));
break;
// default is 1
default: *dest = texel;
default:
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
*dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha);
else
*dest = texel;
break;
}
@ -233,18 +252,37 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
// Alam: SRB2 uses Mingw, HUGS
switch (bpp)
{
case 2 : texelu16 = (UINT16)((alpha<<8) | texel);
case 2 : // uhhhhhhhh..........
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
texel = ASTBlendPixel_8bpp(*(dest+1), texel, originPatch->style, originPatch->alpha);
texelu16 = (UINT16)((alpha<<8) | texel);
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3 : colortemp = V_GetColor(texel);
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
rgbatexel.rgba = *(UINT32 *)dest;
colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha);
}
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4 : colortemp = V_GetColor(texel);
colortemp.s.alpha = alpha;
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
rgbatexel.rgba = *(UINT32 *)dest;
colortemp.rgba = ASTBlendPixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha);
}
memcpy(dest, &colortemp, sizeof(RGBA_t));
break;
// default is 1
default: *dest = texel;
default:
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
*dest = ASTBlendPixel_8bpp(*dest, texel, originPatch->style, originPatch->alpha);
else
*dest = texel;
break;
}
@ -331,16 +369,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
if (texture->width <= 0 || texture->height <= 0)
return;
/*if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency?
{
if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then.
continue;
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawTransFlippedColumnInCache : HWR_DrawTransColumnInCache;
}
else*/
{
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache;
}
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache;
x1 = patch->originx;
width = SHORT(realpatch->width);
@ -420,6 +449,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
GrTexInfo *grInfo)
{
#ifdef GLIDE_API_COMPATIBILITY
// Build the full textures from patches.
static const GrLOD_t gr_lods[9] =
{
@ -456,6 +486,9 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
INT32 j,k;
INT32 max,min;
#else
(void)grInfo;
#endif
// find a power of 2 width/height
if (cv_grrounddown.value)
@ -511,6 +544,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
}
else
{
#ifdef GLIDE_API_COMPATIBILITY
//size up to nearest power of 2
blockwidth = 1;
while (blockwidth < originalwidth)
@ -528,9 +562,14 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
if (blockheight > 2048)
blockheight = 2048;
//I_Error("3D GenerateTexture : too big");
#else
blockwidth = originalwidth;
blockheight = originalheight;
#endif
}
// do the boring LOD stuff.. blech!
#ifdef GLIDE_API_COMPATIBILITY
if (blockwidth >= blockheight)
{
max = blockwidth;
@ -562,6 +601,7 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
if (blockwidth < blockheight)
j += 4;
grInfo->aspectRatioLog2 = gr_aspects[j].aspect;
#endif
blocksize = blockwidth * blockheight;
@ -650,7 +690,12 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
// Composite the columns together.
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
{
size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump);
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL, false);
#endif
HWR_DrawTexturePatchInCache(&grtex->mipmap,
blockwidth, blockheight,
texture, patch,
@ -679,6 +724,13 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
{
INT32 newwidth, newheight;
#ifndef NO_PNG_LUMPS
// lump is a png so convert it
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
if ((patch != NULL) && R_IsLumpPNG((const UINT8 *)patch, len))
patch = R_PNGToPatch((const UINT8 *)patch, len, NULL, true);
#endif
// don't do it twice (like a cache)
if (grMipmap->width == 0)
{
@ -756,11 +808,13 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
static size_t gr_numtextures;
static GLTexture_t *gr_textures; // for ALL Doom textures
static GLTexture_t *gr_textures2;
void HWR_InitTextureCache(void)
{
gr_numtextures = 0;
gr_textures = NULL;
gr_textures2 = NULL;
}
@ -799,7 +853,10 @@ void HWR_FreeTextureCache(void)
// texturecache info, we can free it
if (gr_textures)
free(gr_textures);
if (gr_textures2)
free(gr_textures2);
gr_textures = NULL;
gr_textures2 = NULL;
gr_numtextures = 0;
}
@ -817,6 +874,9 @@ void HWR_PrepLevelCache(size_t pnumtextures)
gr_textures = calloc(pnumtextures, sizeof (*gr_textures));
if (gr_textures == NULL)
I_Error("3D can't alloc gr_textures");
gr_textures2 = calloc(pnumtextures, sizeof (*gr_textures2));
if (gr_textures2 == NULL)
I_Error("3D can't alloc gr_textures2");
}
void HWR_SetPalette(RGBA_t *palette)
@ -847,7 +907,7 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
GLTexture_t *grtex;
#ifdef PARANOIA
if ((unsigned)tex >= gr_numtextures)
I_Error(" HWR_GetTexture: tex >= numtextures\n");
I_Error("HWR_GetTexture: tex >= numtextures\n");
#endif
grtex = &gr_textures[tex];
@ -862,15 +922,39 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
return grtex;
}
// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch.
lumpnum_t gr_patchflat;
static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
{
UINT8 *flat;
patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC);
size_t lumplength = W_LumpLength(flatlumpnum);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)patch, lumplength))
patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL, false);
#endif
grMipmap->width = (UINT16)SHORT(patch->width);
grMipmap->height = (UINT16)SHORT(patch->height);
flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data);
memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height);
R_PatchToFlat(patch, flat);
}
static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
{
size_t size, pflatsize;
// setup the texture info
#ifdef GLIDE_API_COMPATIBILITY
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
grMipmap->grInfo.format = GR_TEXFMT_P_8;
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
@ -900,15 +984,20 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
pflatsize = 64;
break;
}
grMipmap->width = (UINT16)pflatsize;
grMipmap->height = (UINT16)pflatsize;
// the flat raw data needn't be converted with palettized textures
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
PU_HWRCACHE, &grMipmap->grInfo.data));
if (R_CheckIfPatch(flatlumpnum))
HWR_LoadPatchFlat(grMipmap, flatlumpnum);
else
{
grMipmap->width = (UINT16)pflatsize;
grMipmap->height = (UINT16)pflatsize;
// the flat raw data needn't be converted with palettized textures
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
PU_HWRCACHE, &grMipmap->grInfo.data));
}
}
// Download a Doom 'flat' to the hardware cache and make it ready for use
void HWR_GetFlat(lumpnum_t flatlumpnum)
{
@ -923,6 +1012,52 @@ void HWR_GetFlat(lumpnum_t flatlumpnum)
// The system-memory data can be purged now.
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
gr_patchflat = 0;
if (R_CheckIfPatch(flatlumpnum))
gr_patchflat = flatlumpnum;
}
static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
{
UINT8 *flat;
// setup the texture info
#ifdef GLIDE_API_COMPATIBILITY
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64;
grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
grMipmap->grInfo.format = GR_TEXFMT_P_8;
grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
grMipmap->width = (UINT16)textures[texturenum]->width;
grMipmap->height = (UINT16)textures[texturenum]->height;
flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data);
memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height);
R_TextureToFlat(texturenum, flat);
}
void HWR_GetTextureFlat(INT32 texturenum)
{
GLTexture_t *grtex;
#ifdef PARANOIA
if ((unsigned)texturenum >= gr_numtextures)
I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n");
#endif
if (texturenum == 0 || texturenum == -1)
return;
grtex = &gr_textures2[texturenum];
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
HWR_LoadTextureFlat(&grtex->mipmap, texturenum);
HWD.pfnSetTexture(&grtex->mipmap);
// The system-memory data can be purged now.
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
}
//

View File

@ -61,9 +61,6 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR;
// ==========================================================================
// Constants
#ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L
#endif
#define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360
void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/;

View File

@ -47,6 +47,7 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma);
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform);
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
@ -89,6 +90,7 @@ struct hwdriver_s
FinishUpdate pfnFinishUpdate;
Draw2DLine pfnDraw2DLine;
DrawPolygon pfnDrawPolygon;
RenderSkyDome pfnRenderSkyDome;
SetBlend pfnSetBlend;
ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture;

View File

@ -59,9 +59,11 @@ typedef FxI32 GrTextureFormat_t;
typedef struct
{
#ifdef GLIDE_API_COMPATIBILITY
GrLOD_t smallLodLog2;
GrLOD_t largeLodLog2;
GrAspectRatio_t aspectRatioLog2;
#endif
GrTextureFormat_t format;
void *data;
} GrTexInfo;

View File

@ -101,6 +101,7 @@ void HWR_FreeTextureCache(void);
void HWR_FreeExtraSubsectors(void);
void HWR_GetFlat(lumpnum_t flatlumpnum);
void HWR_GetTextureFlat(INT32 texturenum);
GLTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetPatch(GLPatch_t *gpatch);
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap);
@ -114,6 +115,8 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
// --------
// hw_draw.c
// --------
extern lumpnum_t gr_patchflat;
extern float gr_patch_scalex;
extern float gr_patch_scaley;

View File

@ -162,6 +162,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_TURR
&lspr[NOLIGHT], // SPR_SHRP
&lspr[NOLIGHT], // SPR_CRAB
&lspr[NOLIGHT], // SPR_CR2B
&lspr[NOLIGHT], // SPR_CSPR
&lspr[NOLIGHT], // SPR_JJAW
&lspr[NOLIGHT], // SPR_SNLR
&lspr[NOLIGHT], // SPR_VLTR
@ -180,24 +182,26 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_UNID
&lspr[NOLIGHT], // SPR_CANA
&lspr[NOLIGHT], // SPR_CANG
&lspr[NOLIGHT], // SPR_PYRE
&lspr[NOLIGHT], // SPR_PTER
// Generic Boos Items
&lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes
// Boss 1, (Greenflower)
&lspr[NOLIGHT], // SPR_EGGM
&lspr[NOLIGHT], // SPR_EGLZ
// Boss 2, (Techno Hill)
&lspr[NOLIGHT], // SPR_EGGN
&lspr[NOLIGHT], // SPR_TNKA
&lspr[NOLIGHT], // SPR_TNKB
&lspr[NOLIGHT], // SPR_SPNK
&lspr[NOLIGHT], // SPR_TANK
&lspr[NOLIGHT], // SPR_GOOP
// Boss 3 (Deep Sea)
&lspr[NOLIGHT], // SPR_EGGO
&lspr[NOLIGHT], // SPR_PRPL
&lspr[NOLIGHT], // SPR_SEBH
&lspr[NOLIGHT], // SPR_FAKE
&lspr[LBLUESHINE_L],// SPR_SHCK
// Boss 4 (Castle Eggman)
&lspr[NOLIGHT], // SPR_EGGP
@ -205,11 +209,15 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_EGR1
// Boss 5 (Arid Canyon)
&lspr[NOLIGHT], //SPR_FANG // replaces EGGQ
&lspr[NOLIGHT], //SPR_FBOM
&lspr[NOLIGHT], //SPR_FSGN
&lspr[REDBALL_L], //SPR_BARX // bomb explosion (also used by barrel)
&lspr[NOLIGHT], //SPR_BARD // bomb dust (also used by barrel)
&lspr[NOLIGHT], // SPR_FANG // replaces EGGQ
&lspr[NOLIGHT], // SPR_BRKN
&lspr[NOLIGHT], // SPR_WHAT
&lspr[INVINCIBLE_L], // SPR_VWRE
&lspr[INVINCIBLE_L], // SPR_PROJ
&lspr[NOLIGHT], // SPR_FBOM
&lspr[NOLIGHT], // SPR_FSGN
&lspr[REDBALL_L], // SPR_BARX // bomb explosion (also used by barrel)
&lspr[NOLIGHT], // SPR_BARD // bomb dust (also used by barrel)
// Boss 6 (Red Volcano)
&lspr[NOLIGHT], // SPR_EEGR
@ -256,6 +264,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_WSPB
&lspr[NOLIGHT], // SPR_STPT
&lspr[NOLIGHT], // SPR_BMNE
&lspr[NOLIGHT], // SPR_PUMI
// Monitor Boxes
&lspr[NOLIGHT], // SPR_MSTV
@ -373,6 +382,10 @@ light_t *t_lspr[NUMSPRITES] =
// Red Volcano Scenery
&lspr[REDBALL_L], // SPR_FLME
&lspr[REDBALL_L], // SPR_DFLM
&lspr[NOLIGHT], // SPR_LFAL
&lspr[NOLIGHT], // SPR_JPLA
&lspr[NOLIGHT], // SPR_TFLO
&lspr[NOLIGHT], // SPR_WVIN
// Dark City Scenery
@ -384,13 +397,20 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_XMS3
&lspr[NOLIGHT], // SPR_XMS4
&lspr[NOLIGHT], // SPR_XMS5
&lspr[NOLIGHT], // SPR_XMS6
&lspr[NOLIGHT], // SPR_FHZI
&lspr[NOLIGHT], // SPR_ROSY
// Halloween Scenery
&lspr[RINGLIGHT_L], // SPR_PUMK
&lspr[NOLIGHT], // SPR_HHPL
&lspr[NOLIGHT], // SPR_SHRM
&lspr[NOLIGHT], // SPR_HHZM
// Azure Temple Scenery
&lspr[NOLIGHT], // SPR_BGAR
&lspr[NOLIGHT], // SPR_RCRY
&lspr[GREENBALL_L], // SPR_CFLM
// Botanic Serenity Scenery
&lspr[NOLIGHT], // SPR_BSZ1
@ -411,7 +431,6 @@ light_t *t_lspr[NUMSPRITES] =
// Misc Scenery
&lspr[NOLIGHT], // SPR_STLG
&lspr[NOLIGHT], // SPR_DBAL
&lspr[NOLIGHT], // SPR_RCRY
// Powerup Indicators
&lspr[NOLIGHT], // SPR_ARMA
@ -465,11 +484,14 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SSWY
&lspr[NOLIGHT], // SPR_SSWR
&lspr[NOLIGHT], // SPR_SSWB
&lspr[NOLIGHT], // SPR_BSTY
&lspr[NOLIGHT], // SPR_BSTR
// Environmental Effects
&lspr[NOLIGHT], // SPR_RAIN
&lspr[NOLIGHT], // SPR_SNO1
&lspr[NOLIGHT], // SPR_SPLH
&lspr[NOLIGHT], // SPR_LSPL
&lspr[NOLIGHT], // SPR_SPLA
&lspr[NOLIGHT], // SPR_SMOK
&lspr[NOLIGHT], // SPR_BUBL
@ -1226,9 +1248,11 @@ static void HWR_SetLight(void)
lightmappatch.height = 128;
lightmappatch.mipmap.width = 128;
lightmappatch.mipmap.height = 128;
#ifdef GLIDE_API_COMPATIBILITY
lightmappatch.mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
lightmappatch.mipmap.flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw !
}
HWD.pfnSetTexture(&lightmappatch.mipmap);

View File

@ -70,9 +70,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
#endif
#ifdef SORTING
void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
#else
static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
@ -522,7 +522,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c
// HWR_RenderPlane : Render a floor or ceiling convex polygon
// -----------------+
static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
{
polyvertex_t * pv;
float height; //constant y for all points on the convex flat polygon
@ -530,8 +530,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
INT32 nrPlaneVerts; //verts original define of convex flat polygon
INT32 i;
float flatxref,flatyref;
float fflatsize;
float fflatwidth, fflatheight;
INT32 flatflag;
boolean texflat = true;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
@ -540,6 +541,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
#ifdef ESLOPE
pslope_t *slope = NULL;
#endif
patch_t *patch;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
@ -580,9 +582,10 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
if (nrPlaneVerts < 3) //not even a triangle ?
return;
if (nrPlaneVerts > (INT32)UINT16_MAX) // FIXME: exceeds plVerts size
// This check is so inconsistent between functions, it hurts.
if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size
{
CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX);
CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, INT16_MAX);
return;
}
@ -599,38 +602,47 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
switch (len)
{
case 4194304: // 2048x2048 lump
fflatsize = 2048.0f;
flatflag = 2047;
fflatwidth = fflatheight = 2048.0f;
break;
case 1048576: // 1024x1024 lump
fflatsize = 1024.0f;
flatflag = 1023;
fflatwidth = fflatheight = 1024.0f;
break;
case 262144:// 512x512 lump
fflatsize = 512.0f;
flatflag = 511;
fflatwidth = fflatheight = 512.0f;
break;
case 65536: // 256x256 lump
fflatsize = 256.0f;
flatflag = 255;
fflatwidth = fflatheight = 256.0f;
break;
case 16384: // 128x128 lump
fflatsize = 128.0f;
flatflag = 127;
fflatwidth = fflatheight = 128.0f;
break;
case 1024: // 32x32 lump
fflatsize = 32.0f;
flatflag = 31;
fflatwidth = fflatheight = 32.0f;
break;
default: // 64x64 lump
fflatsize = 64.0f;
flatflag = 63;
fflatwidth = fflatheight = 64.0f;
break;
}
flatflag = ((INT32)fflatwidth)-1;
if (texturenum != 0 && texturenum != -1)
{
fflatwidth = textures[texturenum]->width;
fflatheight = textures[texturenum]->height;
}
else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case?
{
patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
fflatwidth = SHORT(patch->width);
fflatheight = SHORT(patch->height);
}
else
texflat = false;
// reference point for flat texture coord for each vertex around the polygon
flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize);
flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize);
flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth);
flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight);
// transform
v3d = planeVerts;
@ -639,14 +651,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight;
angle = FOFsector->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight;
angle = FOFsector->ceilingpic_angle;
}
}
@ -654,14 +666,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight;
angle = gr_frontsector->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight;
angle = gr_frontsector->ceilingpic_angle;
}
}
@ -680,17 +692,24 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++)
{
// Hurdler: add scrolling texture on floor/ceiling
v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx);
v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly);
//v3d->sow = (float)(pv->x / fflatsize);
//v3d->tow = (float)(pv->y / fflatsize);
if (texflat)
{
v3d->sow = (float)(pv->x / fflatwidth) + scrollx;
v3d->tow = -(float)(pv->y / fflatheight) + scrolly;
}
else
{
v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx);
v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly);
}
// Need to rotate before translate
if (angle) // Only needs to be done if there's an altered angle
{
tempxsow = FLOAT_TO_FIXED(v3d->sow);
tempytow = FLOAT_TO_FIXED(v3d->tow);
if (texflat)
tempytow = -tempytow;
v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
}
@ -3164,21 +3183,23 @@ static inline void HWR_AddPolyObjectSegs(void)
#ifdef POLYOBJECTS_PLANES
static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector,
FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector,
UINT8 alpha, extracolormap_t *planecolormap)
{
float height; //constant y for all points on the convex flat polygon
FOutVector *v3d;
INT32 i;
float flatxref,flatyref;
float fflatsize;
float fflatwidth, fflatheight;
INT32 flatflag;
boolean texflat = true;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
FSurfaceInfo Surf;
fixed_t tempxsow, tempytow;
size_t nrPlaneVerts;
patch_t *patch;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
@ -3209,38 +3230,47 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
switch (len)
{
case 4194304: // 2048x2048 lump
fflatsize = 2048.0f;
flatflag = 2047;
fflatwidth = fflatheight = 2048.0f;
break;
case 1048576: // 1024x1024 lump
fflatsize = 1024.0f;
flatflag = 1023;
fflatwidth = fflatheight = 1024.0f;
break;
case 262144:// 512x512 lump
fflatsize = 512.0f;
flatflag = 511;
fflatwidth = fflatheight = 512.0f;
break;
case 65536: // 256x256 lump
fflatsize = 256.0f;
flatflag = 255;
fflatwidth = fflatheight = 256.0f;
break;
case 16384: // 128x128 lump
fflatsize = 128.0f;
flatflag = 127;
fflatwidth = fflatheight = 128.0f;
break;
case 1024: // 32x32 lump
fflatsize = 32.0f;
flatflag = 31;
fflatwidth = fflatheight = 32.0f;
break;
default: // 64x64 lump
fflatsize = 64.0f;
flatflag = 63;
fflatwidth = fflatheight = 64.0f;
break;
}
flatflag = ((INT32)fflatwidth)-1;
if (texturenum != 0 && texturenum != -1)
{
fflatwidth = textures[texturenum]->width;
fflatheight = textures[texturenum]->height;
}
else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case?
{
patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
fflatwidth = SHORT(patch->width);
fflatheight = SHORT(patch->height);
}
else
texflat = false;
// reference point for flat texture coord for each vertex around the polygon
flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize);
flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize);
flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth);
flatyref = (float)((polysector->origVerts[0].y & (~flatflag)) / fflatheight);
// transform
v3d = planeVerts;
@ -3249,14 +3279,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight;
angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight;
angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT;
}
}
@ -3264,14 +3294,14 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatheight;
angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatheight;
angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT;
}
}
@ -3294,15 +3324,26 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++)
{
// Hurdler: add scrolling texture on floor/ceiling
v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations
v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations
// Go from the polysector's original vertex locations
// Means the flat is offset based on the original vertex locations
if (texflat)
{
v3d->sow = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx;
v3d->tow = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly;
}
else
{
v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx);
v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly);
}
// Need to rotate before translate
if (angle) // Only needs to be done if there's an altered angle
{
tempxsow = FLOAT_TO_FIXED(v3d->sow);
tempytow = FLOAT_TO_FIXED(v3d->tow);
if (texflat)
tempytow = -tempytow;
v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle))));
}
@ -3333,6 +3374,7 @@ static void HWR_AddPolyObjectPlanes(void)
{
size_t i;
sector_t *polyobjsector;
INT32 light = 0;
// Polyobject Planes need their own function for drawing because they don't have extrasubsectors by themselves
// It should be okay because polyobjects should always be convex anyway
@ -3351,19 +3393,23 @@ static void HWR_AddPolyObjectPlanes(void)
&& polyobjsector->floorheight >= gr_frontsector->floorheight
&& (viewz < polyobjsector->floorheight))
{
light = R_GetPlaneLight(gr_frontsector, polyobjsector->floorheight, true);
if (po_ptrs[i]->translucency > 0)
{
FSurfaceInfo Surf;
FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], false, polyobjsector->floorheight,
polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL);
FBITFIELD blendmode;
memset(&Surf, 0x00, sizeof(Surf));
blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum);
HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum);
HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude,
polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum,
polyobjsector, 255, NULL);
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
}
@ -3371,21 +3417,23 @@ static void HWR_AddPolyObjectPlanes(void)
&& polyobjsector->ceilingheight <= gr_frontsector->ceilingheight
&& (viewz > polyobjsector->ceilingheight))
{
light = R_GetPlaneLight(gr_frontsector, polyobjsector->ceilingheight, true);
if (po_ptrs[i]->translucency > 0)
{
FSurfaceInfo Surf;
FBITFIELD blendmode;
memset(&Surf, 0x00, sizeof(Surf));
blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], true, polyobjsector->ceilingheight,
polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum);
HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum);
HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude,
polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum,
polyobjsector, 255, NULL);
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
}
}
@ -3536,11 +3584,12 @@ static void HWR_Subsector(size_t num)
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum);
HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum);
HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false,
// Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap);
PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap);
}
}
else
@ -3558,11 +3607,12 @@ static void HWR_Subsector(size_t num)
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum);
HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum);
HWR_RenderPlane(NULL, &extrasubsectors[num], true,
// Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap);
PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap);
}
}
else
@ -3621,7 +3671,7 @@ static void HWR_Subsector(size_t num)
else
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
HWR_AddTransparentFloor(0,
HWR_AddTransparentFloor(0, 0,
&extrasubsectors[num],
false,
*rover->bottomheight,
@ -3640,6 +3690,7 @@ static void HWR_Subsector(size_t num)
rover->alpha-1, rover->master->frontsector);
#else
HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum,
levelflats[*rover->bottompic].texturenum,
&extrasubsectors[num],
false,
*rover->bottomheight,
@ -3651,8 +3702,9 @@ static void HWR_Subsector(size_t num)
else
{
HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum,
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum,
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -3684,7 +3736,7 @@ static void HWR_Subsector(size_t num)
else
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
HWR_AddTransparentFloor(0,
HWR_AddTransparentFloor(0, 0,
&extrasubsectors[num],
true,
*rover->topheight,
@ -3703,6 +3755,7 @@ static void HWR_Subsector(size_t num)
rover->alpha-1, rover->master->frontsector);
#else
HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum,
levelflats[*rover->bottompic].texturenum,
&extrasubsectors[num],
true,
*rover->topheight,
@ -3715,8 +3768,9 @@ static void HWR_Subsector(size_t num)
else
{
HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum,
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum,
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -5045,6 +5099,7 @@ typedef struct
fixed_t fixedheight;
INT32 lightlevel;
lumpnum_t lumpnum;
INT32 texturenum;
INT32 alpha;
sector_t *FOFSector;
FBITFIELD blend;
@ -5063,6 +5118,7 @@ typedef struct
fixed_t fixedheight;
INT32 lightlevel;
lumpnum_t lumpnum;
INT32 texturenum;
INT32 alpha;
sector_t *FOFSector;
FBITFIELD blend;
@ -5093,7 +5149,7 @@ static INT32 drawcount = 0;
#define MAX_TRANSPARENTFLOOR 512
// This will likely turn into a copy of HWR_Add3DWater and replace it.
void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling,
void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap)
{
static size_t allocedplanes = 0;
@ -5112,6 +5168,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean
planeinfo[numplanes].fixedheight = fixedheight;
planeinfo[numplanes].lightlevel = lightlevel;
planeinfo[numplanes].lumpnum = lumpnum;
planeinfo[numplanes].texturenum = texturenum;
planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha;
planeinfo[numplanes].FOFSector = FOFSector;
@ -5125,7 +5182,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean
// Adding this for now until I can create extrasubsector info for polyobjects
// When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling,
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap)
{
static size_t allocedpolyplanes = 0;
@ -5144,6 +5201,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector,
polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
polyplaneinfo[numpolyplanes].lumpnum = lumpnum;
polyplaneinfo[numpolyplanes].texturenum = texturenum;
polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha;
polyplaneinfo[numpolyplanes].FOFSector = FOFSector;
@ -5305,9 +5363,12 @@ static void HWR_CreateDrawNodes(void)
gr_frontsector = NULL;
if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture))
{
HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum);
HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum);
}
HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel,
sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
}
else if (sortnode[sortindex[i]].polyplane)
{
@ -5315,9 +5376,12 @@ static void HWR_CreateDrawNodes(void)
gr_frontsector = NULL;
if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture))
{
HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum);
HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum);
}
HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel,
sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
}
else if (sortnode[sortindex[i]].wall)
{
@ -5390,7 +5454,7 @@ static void HWR_AddSprites(sector_t *sec)
#ifdef HWPRECIP
precipmobj_t *precipthing;
#endif
fixed_t approx_dist, limit_dist;
fixed_t approx_dist, limit_dist, hoop_limit_dist;
// BSP is traversed by subsector.
// A sector might have been split into several
@ -5407,7 +5471,9 @@ static void HWR_AddSprites(sector_t *sec)
// Handle all things in sector.
// If a limit exists, handle things a tiny bit different.
if ((limit_dist = (fixed_t)((maptol & TOL_NIGHTS) ? cv_drawdist_nights.value : cv_drawdist.value) << FRACBITS))
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)
{
@ -5416,8 +5482,16 @@ static void HWR_AddSprites(sector_t *sec)
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
if (approx_dist > limit_dist)
continue;
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);
}
@ -5647,6 +5721,13 @@ static void HWR_ProjectSprite(mobj_t *thing)
return;
}
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)
return;
}
// store information in a vissprite
vis = HWR_NewVisSprite();
vis->x1 = x1;
@ -5660,7 +5741,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->z2 = z2;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
if ((vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
@ -5805,86 +5886,122 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
// ==========================================================================
//
// ==========================================================================
static void HWR_DrawSkyBackground(void)
static void HWR_DrawSkyBackground(player_t *player)
{
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gr_xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
if (cv_grskydome.value)
{
dimensionmultiply *= 2;
angle *= 2;
}
FTransform transform;
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
postimg_t *type;
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.flip)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
if (splitscreen && player == &players[secondarydisplayplayer])
type = &postimgtype2;
else
type = &postimgtype;
memset(&transform, 0x00, sizeof(FTransform));
//04/01/2000: Hurdler: added for T&L
// It should replace all other gr_viewxxx when finished
transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
if (*type == postimg_flip)
transform.flip = true;
else
transform.flip = false;
transform.scalex = 1;
transform.scaley = (float)vid.width/vid.height;
transform.scalez = 1;
transform.fovxangle = fpov; // Tails
transform.fovyangle = fpov; // Tails
transform.splitscreen = splitscreen;
HWR_GetTexture(texturetranslation[skytexture]);
HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform);
}
else
{
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
}
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].tow = v[2].tow += ((float) angle / angleturn);
v[0].tow = v[1].tow += ((float) angle / angleturn);
}
else
{
v[3].tow = v[2].tow -= ((float) angle / angleturn);
v[0].tow = v[1].tow -= ((float) angle / angleturn);
}
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
HWD.pfnDrawPolygon(NULL, v, 4, 0);
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gr_xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
{
dimensionmultiply *= 2;
angle *= 2;
}
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.flip)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
}
else
{
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
}
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].tow = v[2].tow += ((float) angle / angleturn);
v[0].tow = v[1].tow += ((float) angle / angleturn);
}
else
{
v[3].tow = v[2].tow -= ((float) angle / angleturn);
v[0].tow = v[1].tow -= ((float) angle / angleturn);
}
HWD.pfnDrawPolygon(NULL, v, 4, 0);
}
}
@ -6036,7 +6153,7 @@ if (0)
}
if (drawsky)
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;
@ -6253,7 +6370,7 @@ if (0)
}
if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;

View File

@ -98,6 +98,7 @@ extern consvar_t cv_voodoocompatibility;
extern consvar_t cv_grfovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;
extern consvar_t cv_grskydome;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;

View File

@ -26,6 +26,7 @@
#include <string.h>
#include <math.h>
#include "../d_main.h"
#include "../doomdef.h"
#include "../doomstat.h"
#include "../fastcmp.h"
@ -70,6 +71,10 @@
#endif
#endif
#ifndef errno
#include "errno.h"
#endif
#define NUMVERTEXNORMALS 162
float avertexnormals[NUMVERTEXNORMALS][3] = {
{-0.525731f, 0.000000f, 0.850651f},
@ -294,7 +299,8 @@ static md2_model_t *md2_readModel(const char *filename)
if (model == NULL)
return 0;
file = fopen(filename, "rb");
//Filename checking fixed ~Monster Iestyn and Golden
file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb");
if (!file)
{
free(model);
@ -523,7 +529,8 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
#endif
#endif
png_FILE_p png_FILE;
char *pngfilename = va("md2/%s", filename);
//Filename checking fixed ~Monster Iestyn and Golden
char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
FIL_ForceExtension(pngfilename, ".png");
png_FILE = fopen(pngfilename, "rb");
@ -651,7 +658,8 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
size_t pw, ph, size, ptr = 0;
INT32 ch, rep;
FILE *file;
char *pcxfilename = va("md2/%s", filename);
//Filename checking fixed ~Monster Iestyn and Golden
char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb");
@ -747,10 +755,12 @@ static void md2_loadTexture(md2_t *model)
grpatch->mipmap.width = (UINT16)w;
grpatch->mipmap.height = (UINT16)h;
#ifdef GLIDE_API_COMPATIBILITY
// not correct!
grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
}
HWD.pfnSetTexture(&grpatch->mipmap);
HWR_UnlockCachedPatch(grpatch);
@ -798,10 +808,12 @@ static void md2_loadBlendTexture(md2_t *model)
grpatch->mipmap.width = (UINT16)w;
grpatch->mipmap.height = (UINT16)h;
#ifdef GLIDE_API_COMPATIBILITY
// not correct!
grpatch->mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_256;
grpatch->mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
}
HWD.pfnSetTexture(&grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
HWR_UnlockCachedPatch(grpatch);
@ -841,11 +853,12 @@ void HWR_InitMD2(void)
}
// read the md2.dat file
f = fopen("md2.dat", "rt");
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt");
if (!f)
{
CONS_Printf("%s", M_GetText("Error while loading md2.dat\n"));
CONS_Printf("%s %s\n", M_GetText("Error while loading md2.dat:"), strerror(errno));
nomd2s = true;
return;
}
@ -907,7 +920,8 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
CONS_Printf("AddPlayerMD2()...\n");
// read the md2.dat file
f = fopen("md2.dat", "rt");
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt");
if (!f)
{
@ -952,7 +966,8 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu
return;
// Read the md2.dat file
f = fopen("md2.dat", "rt");
//Filename checking fixed ~Monster Iestyn and Golden
f = fopen(va("%s"PATHSEP"%s", srb2home, "md2.dat"), "rt");
if (!f)
{
@ -1198,7 +1213,7 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p
if (!md2 || !skin)
return 0;
if ((unsigned)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
return 0;
while (!(md2->model->spr2frames[spr2*2 + 1])
@ -1262,6 +1277,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// MD2 colormap fix
// colormap test
if (spr->mobj->subsector)
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = 255;
@ -1293,6 +1309,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
}
else
Surf.FlatColor.rgba = 0xFFFFFFFF;
// Look at HWR_ProjectSprite for more
{

View File

@ -1427,6 +1427,219 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf,
Clamp2D(GL_TEXTURE_WRAP_T);
}
typedef struct vbo_vertex_s
{
float x, y, z;
float u, v;
unsigned char r, g, b, a;
} vbo_vertex_t;
typedef struct
{
int mode;
int vertexcount;
int vertexindex;
int use_texture;
} GLSkyLoopDef;
typedef struct
{
int id;
int rows, columns;
int loopcount;
GLSkyLoopDef *loops;
vbo_vertex_t *data;
} GLSkyVBO;
// The texture offset to be applied to the texture coordinates in SkyVertex().
static int rows, columns;
static boolean yflip;
static int texw, texh;
static boolean foglayer;
static float delta = 0.0f;
static int gl_sky_detail = 16;
static INT32 lasttex = -1;
#define MAP_COEFF 128.0f
static void SkyVertex(vbo_vertex_t *vbo, int r, int c)
{
const float radians = (M_PIl / 180.0f);
const float scale = 10000.0f;
const float maxSideAngle = 60.0f;
float topAngle = (c / (float)columns * 360.0f);
float sideAngle = (maxSideAngle * (rows - r) / rows);
float height = sin(sideAngle * radians);
float realRadius = scale * cos(sideAngle * radians);
float x = realRadius * cos(topAngle * radians);
float y = (!yflip) ? scale * height : -scale * height;
float z = realRadius * sin(topAngle * radians);
float timesRepeat = (4 * (256.0f / texw));
if (fpclassify(timesRepeat) == FP_ZERO)
timesRepeat = 1.0f;
if (!foglayer)
{
vbo->r = 255;
vbo->g = 255;
vbo->b = 255;
vbo->a = (r == 0 ? 0 : 255);
// And the texture coordinates.
vbo->u = (-timesRepeat * c / (float)columns);
if (!yflip) // Flipped Y is for the lower hemisphere.
vbo->v = (r / (float)rows) + 0.5f;
else
vbo->v = 1.0f + ((rows - r) / (float)rows) + 0.5f;
}
if (r != 4)
{
y += 300.0f;
}
// And finally the vertex.
vbo->x = x;
vbo->y = y + delta;
vbo->z = z;
}
static GLSkyVBO sky_vbo;
static void gld_BuildSky(int row_count, int col_count)
{
int c, r;
vbo_vertex_t *vertex_p;
int vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2;
GLSkyVBO *vbo = &sky_vbo;
if ((vbo->columns != col_count) || (vbo->rows != row_count))
{
free(vbo->loops);
free(vbo->data);
memset(vbo, 0, sizeof(&vbo));
}
if (!vbo->data)
{
memset(vbo, 0, sizeof(&vbo));
vbo->loops = malloc((row_count * 2 + 2) * sizeof(vbo->loops[0]));
// create vertex array
vbo->data = malloc(vertex_count * sizeof(vbo->data[0]));
}
vbo->columns = col_count;
vbo->rows = row_count;
vertex_p = &vbo->data[0];
vbo->loopcount = 0;
for (yflip = 0; yflip < 2; yflip++)
{
vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN;
vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0];
vbo->loops[vbo->loopcount].vertexcount = col_count;
vbo->loops[vbo->loopcount].use_texture = false;
vbo->loopcount++;
delta = 0.0f;
foglayer = true;
for (c = 0; c < col_count; c++)
{
SkyVertex(vertex_p, 1, c);
vertex_p->r = 255;
vertex_p->g = 255;
vertex_p->b = 255;
vertex_p->a = 255;
vertex_p++;
}
foglayer = false;
delta = (yflip ? 5.0f : -5.0f) / MAP_COEFF;
for (r = 0; r < row_count; r++)
{
vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP;
vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0];
vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2;
vbo->loops[vbo->loopcount].use_texture = true;
vbo->loopcount++;
for (c = 0; c <= col_count; c++)
{
SkyVertex(vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0));
SkyVertex(vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0));
}
}
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
static void RenderDome(INT32 skytexture)
{
int i, j;
GLSkyVBO *vbo = &sky_vbo;
pglRotatef(270.0f, 0.0f, 1.0f, 0.0f);
rows = 4;
columns = 4 * gl_sky_detail;
if (lasttex != skytexture)
{
lasttex = skytexture;
gld_BuildSky(rows, columns);
}
pglScalef(1.0f, (float)texh / 230.0f, 1.0f);
for (j = 0; j < 2; j++)
{
for (i = 0; i < vbo->loopcount; i++)
{
GLSkyLoopDef *loop = &vbo->loops[i];
if (j == 0 ? loop->use_texture : !loop->use_texture)
continue;
else
{
int k;
pglBegin(loop->mode);
for (k = loop->vertexindex; k < (loop->vertexindex + loop->vertexcount); k++)
{
vbo_vertex_t *v = &vbo->data[k];
if (loop->use_texture)
pglTexCoord2f(v->u, v->v);
pglColor4f(v->r, v->g, v->b, v->a);
pglVertex3f(v->x, v->y, v->z);
}
pglEnd();
}
}
}
pglScalef(1.0f, 1.0f, 1.0f);
pglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform)
{
SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
SetTransform(&transform);
texw = texture_width;
texh = texture_height;
RenderDome(tex);
SetBlend(0);
}
// ==========================================================================
//

View File

@ -71,6 +71,10 @@ patch_t *lt_font[LT_FONTSIZE];
patch_t *cred_font[CRED_FONTSIZE];
patch_t *ttlnum[20]; // act numbers (0-19)
// Name tag fonts
patch_t *ntb_font[NT_FONTSIZE];
patch_t *nto_font[NT_FONTSIZE];
static player_t *plr;
boolean chat_on; // entering a chat message?
static char w_chat[HU_MAXMSGLEN];
@ -246,6 +250,32 @@ void HU_LoadGraphics(void)
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// cache the base name tag font for entire game execution
j = NT_FONTSTART;
for (i = 0; i < NT_FONTSIZE; i++)
{
sprintf(buffer, "NTFNT%.3d", j);
j++;
if (W_CheckNumForName(buffer) == LUMPERROR)
ntb_font[i] = NULL;
else
ntb_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// cache the outline name tag font for entire game execution
j = NT_FONTSTART;
for (i = 0; i < NT_FONTSIZE; i++)
{
sprintf(buffer, "NTFNO%.3d", j);
j++;
if (W_CheckNumForName(buffer) == LUMPERROR)
nto_font[i] = NULL;
else
nto_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// cache the crosshairs, don't bother to know which one is being used,
// just cache all 3, they're so small anyway.
for (i = 0; i < HU_CROSSHAIRS; i++)

View File

@ -35,6 +35,12 @@
#define CRED_FONTEND 'Z' // the last font character
#define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1)
// Name tag font
// Used by base and outline font set
#define NT_FONTSTART '!' // the first font character
#define NT_FONTEND 'Z' // the last font character
#define NT_FONTSIZE (NT_FONTEND - NT_FONTSTART + 1)
#define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init();
extern char *shiftxform; // english translation shift table
@ -77,6 +83,8 @@ extern patch_t *tallnum[10];
extern patch_t *nightsnum[10];
extern patch_t *lt_font[LT_FONTSIZE];
extern patch_t *cred_font[CRED_FONTSIZE];
extern patch_t *ntb_font[NT_FONTSIZE];
extern patch_t *nto_font[NT_FONTSIZE];
extern patch_t *ttlnum[20];
extern patch_t *emeraldpics[3][8];
extern patch_t *rflagico;

View File

@ -776,6 +776,8 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
#endif
#endif
mysockaddr_t straddr;
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (s == (SOCKET_TYPE)ERRSOCKET)
return (SOCKET_TYPE)ERRSOCKET;
@ -869,12 +871,16 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
}
if (getsockname(s, (struct sockaddr *)&sin, &len) == -1)
CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n"));
else
current_port = (UINT16)ntohs(sin.sin_port);
return s;
}
static boolean UDP_Socket(void)
{
const char *sock_port = NULL;
size_t s;
struct my_addrinfo *ai, *runp, hints;
int gaie;
@ -896,20 +902,11 @@ static boolean UDP_Socket(void)
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
if (M_CheckParm("-clientport"))
{
if (!M_IsNextParm())
I_Error("syntax: -clientport <portnum>");
sock_port = M_GetNextParm();
}
else
sock_port = port_name;
if (M_CheckParm("-bindaddr"))
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -930,7 +927,7 @@ static boolean UDP_Socket(void)
}
else
{
gaie = I_getaddrinfo("0.0.0.0", sock_port, &hints, &ai);
gaie = I_getaddrinfo("0.0.0.0", port_name, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -945,8 +942,8 @@ static boolean UDP_Socket(void)
#ifdef HAVE_MINIUPNPC
if (UPNP_support)
{
I_UPnP_rem(sock_port, "UDP");
I_UPnP_add(NULL, sock_port, "UDP");
I_UPnP_rem(port_name, "UDP");
I_UPnP_add(NULL, port_name, "UDP");
}
#endif
}
@ -963,7 +960,7 @@ static boolean UDP_Socket(void)
{
while (M_IsNextParm())
{
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -984,7 +981,7 @@ static boolean UDP_Socket(void)
}
else
{
gaie = I_getaddrinfo("::", sock_port, &hints, &ai);
gaie = I_getaddrinfo("::", port_name, &hints, &ai);
if (gaie == 0)
{
runp = ai;
@ -1260,7 +1257,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
int gaie;
if (!port || !port[0])
port = port_name;
port = DEFAULTPORT;
DEBFILE(va("Creating new node: %s@%s\n", address, port));
@ -1424,14 +1421,15 @@ boolean I_InitTcpNetwork(void)
if (!I_InitTcpDriver())
return false;
if (M_CheckParm("-udpport"))
if (M_CheckParm("-port"))
// Combined -udpport and -clientport into -port
// As it was really redundant having two seperate parms that does the same thing
{
if (M_IsNextParm())
strcpy(port_name, M_GetNextParm());
else
strcpy(port_name, "0");
}
current_port = (UINT16)atoi(port_name);
// parse network game options,
if (M_CheckParm("-server") || dedicated)

1983
src/info.c

File diff suppressed because it is too large Load Diff

View File

@ -138,6 +138,7 @@ void A_SetReactionTime();
void A_Boss1Spikeballs();
void A_Boss3TakeDamage();
void A_Boss3Path();
void A_Boss3ShockThink();
void A_LinedefExecute();
void A_PlaySeeSound();
void A_PlayAttackSound();
@ -252,6 +253,7 @@ void A_Boss5CheckOnGround();
void A_Boss5CheckFalling();
void A_Boss5PinchShot();
void A_Boss5MakeItRain();
void A_Boss5MakeJunk();
void A_LookForBetter();
void A_Boss5BombExplode();
void A_DustDevilThink();
@ -266,6 +268,14 @@ void A_SnapperThinker();
void A_SaloonDoorSpawn();
void A_MinecartSparkThink();
void A_ModuloToState();
void A_LavafallRocks();
void A_LavafallLava();
void A_FallingLavaCheck();
void A_FireShrink();
void A_SpawnPterabytes();
void A_PterabyteHover();
void A_RolloutSpawn();
void A_RolloutRock();
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 512
@ -296,6 +306,8 @@ typedef enum sprite
SPR_TURR, // Pop-Up Turret
SPR_SHRP, // Sharp
SPR_CRAB, // Crushstacean
SPR_CR2B, // Banpyura
SPR_CSPR, // Banpyura spring
SPR_JJAW, // Jet Jaw
SPR_SNLR, // Snailer
SPR_VLTR, // BASH
@ -314,24 +326,26 @@ typedef enum sprite
SPR_UNID, // Unidus
SPR_CANA, // Canarivore
SPR_CANG, // Canarivore gas
SPR_PYRE, // Pyre Fly
SPR_PTER, // Pterabyte
// Generic Boss Items
SPR_JETF, // Boss jet fumes
// Boss 1 (Greenflower)
SPR_EGGM,
SPR_EGGM, // Boss 1
SPR_EGLZ, // Boss 1 Junk
// Boss 2 (Techno Hill)
SPR_EGGN, // Boss 2
SPR_TNKA, // Boss 2 Tank 1
SPR_TNKB, // Boss 2 Tank 2
SPR_SPNK, // Boss 2 Spigot
SPR_TANK, // Boss 2 Junk
SPR_GOOP, // Boss 2 Goop
// Boss 3 (Deep Sea)
SPR_EGGO, // Boss 3
SPR_PRPL, // Boss 3 Propeller
SPR_SEBH, // Boss 3 Junk
SPR_FAKE, // Boss 3 Fakemobile
SPR_SHCK, // Boss 3 Shockwave
// Boss 4 (Castle Eggman)
SPR_EGGP,
@ -340,6 +354,10 @@ typedef enum sprite
// Boss 5 (Arid Canyon)
SPR_FANG, // replaces EGGQ
SPR_BRKN,
SPR_WHAT,
SPR_VWRE,
SPR_PROJ, // projector light
SPR_FBOM,
SPR_FSGN,
SPR_BARX, // bomb explosion (also used by barrel)
@ -391,6 +409,7 @@ typedef enum sprite
SPR_WSPB, // Wall spike base
SPR_STPT, // Starpost
SPR_BMNE, // Big floating mine
SPR_PUMI, // Rollout Rock
// Monitor Boxes
SPR_MSTV, // MiSc TV sprites
@ -459,11 +478,11 @@ typedef enum sprite
SPR_GARG, // Deep Sea Gargoyle
SPR_SEWE, // Deep Sea Seaweed
SPR_DRIP, // Dripping water
SPR_CRL1, // Coral 1
SPR_CRL2, // Coral 2
SPR_CRL3, // Coral 3
SPR_CORL, // Coral
SPR_BCRY, // Blue Crystal
SPR_KELP, // Kelp
SPR_ALGA, // Animated algae top
SPR_ALGB, // Animated algae segment
SPR_DSTG, // DSZ Stalagmites
SPR_LIBE, // DSZ Light beam
@ -493,7 +512,7 @@ typedef enum sprite
// Arid Canyon Scenery
SPR_BTBL, // Big tumbleweed
SPR_STBL, // Small tumbleweed
SPR_CACT, // Cacti sprites
SPR_CACT, // Cacti
SPR_WWSG, // Caution Sign
SPR_WWS2, // Cacti Sign
SPR_WWS3, // Sharp Turn Sign
@ -505,7 +524,6 @@ typedef enum sprite
SPR_ADST, // Arid dust
SPR_MCRT, // Minecart
SPR_MCSP, // Minecart spark
SPR_NON2, // Saloon door thinker
SPR_SALD, // Saloon door
SPR_TRAE, // Train cameo locomotive
SPR_TRAI, // Train cameo wagon
@ -514,6 +532,10 @@ typedef enum sprite
// Red Volcano Scenery
SPR_FLME, // Flame jet
SPR_DFLM, // Blade's flame
SPR_LFAL, // Lavafall
SPR_JPLA, // Jungle palm
SPR_TFLO, // Torch flower
SPR_WVIN, // Wall vines
// Dark City Scenery
@ -525,13 +547,20 @@ typedef enum sprite
SPR_XMS3, // Snowman
SPR_XMS4, // Lamppost
SPR_XMS5, // Hanging Star
SPR_XMS6, // Mistletoe
SPR_FHZI, // FHZ Ice
SPR_ROSY,
// Halloween Scenery
SPR_PUMK, // Pumpkins
SPR_HHPL, // Dr Seuss Trees
SPR_SHRM, // Mushroom
SPR_HHZM, // Misc
// Azure Temple Scenery
SPR_BGAR, // ATZ Gargoyles
SPR_RCRY, // ATZ Red Crystal (Target)
SPR_CFLM, // Green torch flame
// Botanic Serenity Scenery
SPR_BSZ1, // Tall flowers
@ -552,7 +581,6 @@ typedef enum sprite
// Misc Scenery
SPR_STLG, // Stalagmites
SPR_DBAL, // Disco
SPR_RCRY, // ATZ Red Crystal (Target)
// Powerup Indicators
SPR_ARMA, // Armageddon Shield Orb
@ -606,11 +634,14 @@ typedef enum sprite
SPR_SSWY, // Yellow Side Spring
SPR_SSWR, // Red Side Spring
SPR_SSWB, // Blue Side Spring
SPR_BSTY, // Yellow Booster
SPR_BSTR, // Red Booster
// Environmental Effects
SPR_RAIN, // Rain
SPR_SNO1, // Snowflake
SPR_SPLH, // Water Splish
SPR_LSPL, // Lava Splish
SPR_SPLA, // Water Splash
SPR_SMOK,
SPR_BUBL, // Bubble
@ -833,15 +864,27 @@ typedef enum playersprite
SPR2_TALA,
SPR2_TALB,
SPR2_CNT1, // continue disappointment
SPR2_CNT2, // continue lift
SPR2_CNT3, // continue spin
SPR2_CNT4, // continue "soooooooniiic!" tugging
SPR2_SIGN, // end sign head
SPR2_LIFE, // life monitor icon
SPR2_XTRA, // stuff that isn't in-game - keep this last in the list
SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?"
SPR2_FIRSTFREESLOT,
SPR2_LASTFREESLOT = 0x7f,
NUMPLAYERSPRITES
} playersprite_t;
// SPR2_XTRA
#define XTRA_LIFEPIC 0 // Life icon patch
#define XTRA_CHARSEL 1 // Character select picture
#define XTRA_CONTINUE 2 // Continue icon
#define XTRA_ENDING 3 // Ending finale patches
typedef enum state
{
S_NULL,
@ -1135,6 +1178,21 @@ typedef enum state
S_CRUSHCLAW_WAIT,
S_CRUSHCHAIN,
// Banpyura
S_BANPYURA_ROAM1,
S_BANPYURA_ROAM2,
S_BANPYURA_ROAM3,
S_BANPYURA_ROAM4,
S_BANPYURA_ROAMPAUSE,
S_CDIAG1,
S_CDIAG2,
S_CDIAG3,
S_CDIAG4,
S_CDIAG5,
S_CDIAG6,
S_CDIAG7,
S_CDIAG8,
// Jet Jaw
S_JETJAW_ROAM1,
S_JETJAW_ROAM2,
@ -1321,6 +1379,22 @@ typedef enum state
S_CANARIVOREGAS_7,
S_CANARIVOREGAS_8,
// Pyre Fly
S_PYREFLY_FLY,
S_PYREFLY_BURN,
S_PYREFIRE1,
S_PYREFIRE2,
// Pterabyte
S_PTERABYTESPAWNER,
S_PTERABYTEWAYPOINT,
S_PTERABYTE_FLY1,
S_PTERABYTE_FLY2,
S_PTERABYTE_FLY3,
S_PTERABYTE_FLY4,
S_PTERABYTE_SWOOPDOWN,
S_PTERABYTE_SWOOPUP,
// Boss Explosion
S_BOSSEXPLODE,
@ -1333,10 +1407,10 @@ typedef enum state
S_SONIC3KBOSSEXPLOSION6,
S_JETFUME1,
S_JETFUME2,
// Boss 1
S_EGGMOBILE_STND,
S_EGGMOBILE_ROFL,
S_EGGMOBILE_LATK1,
S_EGGMOBILE_LATK2,
S_EGGMOBILE_LATK3,
@ -1346,7 +1420,6 @@ typedef enum state
S_EGGMOBILE_LATK7,
S_EGGMOBILE_LATK8,
S_EGGMOBILE_LATK9,
S_EGGMOBILE_LATK10,
S_EGGMOBILE_RATK1,
S_EGGMOBILE_RATK2,
S_EGGMOBILE_RATK3,
@ -1356,7 +1429,6 @@ typedef enum state
S_EGGMOBILE_RATK7,
S_EGGMOBILE_RATK8,
S_EGGMOBILE_RATK9,
S_EGGMOBILE_RATK10,
S_EGGMOBILE_PANIC1,
S_EGGMOBILE_PANIC2,
S_EGGMOBILE_PANIC3,
@ -1367,27 +1439,25 @@ typedef enum state
S_EGGMOBILE_PANIC8,
S_EGGMOBILE_PANIC9,
S_EGGMOBILE_PANIC10,
S_EGGMOBILE_PANIC11,
S_EGGMOBILE_PANIC12,
S_EGGMOBILE_PANIC13,
S_EGGMOBILE_PANIC14,
S_EGGMOBILE_PANIC15,
S_EGGMOBILE_PAIN,
S_EGGMOBILE_PAIN2,
S_EGGMOBILE_DIE1,
S_EGGMOBILE_DIE2,
S_EGGMOBILE_DIE3,
S_EGGMOBILE_DIE4,
S_EGGMOBILE_DIE5,
S_EGGMOBILE_DIE6,
S_EGGMOBILE_DIE7,
S_EGGMOBILE_DIE8,
S_EGGMOBILE_DIE9,
S_EGGMOBILE_DIE10,
S_EGGMOBILE_DIE11,
S_EGGMOBILE_DIE12,
S_EGGMOBILE_DIE13,
S_EGGMOBILE_DIE14,
S_EGGMOBILE_FLEE1,
S_EGGMOBILE_FLEE2,
S_EGGMOBILE_BALL,
S_EGGMOBILE_TARGET,
S_BOSSEGLZ1,
S_BOSSEGLZ2,
// Boss 2
S_EGGMOBILE2_STND,
S_EGGMOBILE2_POGO1,
@ -1403,16 +1473,6 @@ typedef enum state
S_EGGMOBILE2_DIE2,
S_EGGMOBILE2_DIE3,
S_EGGMOBILE2_DIE4,
S_EGGMOBILE2_DIE5,
S_EGGMOBILE2_DIE6,
S_EGGMOBILE2_DIE7,
S_EGGMOBILE2_DIE8,
S_EGGMOBILE2_DIE9,
S_EGGMOBILE2_DIE10,
S_EGGMOBILE2_DIE11,
S_EGGMOBILE2_DIE12,
S_EGGMOBILE2_DIE13,
S_EGGMOBILE2_DIE14,
S_EGGMOBILE2_FLEE1,
S_EGGMOBILE2_FLEE2,
@ -1428,11 +1488,7 @@ typedef enum state
// Boss 3
S_EGGMOBILE3_STND,
S_EGGMOBILE3_LAUGH1,
S_EGGMOBILE3_LAUGH2,
S_EGGMOBILE3_LAUGH3,
S_EGGMOBILE3_LAUGH4,
S_EGGMOBILE3_LAUGH5,
S_EGGMOBILE3_SHOCK,
S_EGGMOBILE3_ATK1,
S_EGGMOBILE3_ATK2,
S_EGGMOBILE3_ATK3A,
@ -1441,49 +1497,16 @@ typedef enum state
S_EGGMOBILE3_ATK3D,
S_EGGMOBILE3_ATK4,
S_EGGMOBILE3_ATK5,
S_EGGMOBILE3_LAUGH6,
S_EGGMOBILE3_LAUGH7,
S_EGGMOBILE3_LAUGH8,
S_EGGMOBILE3_LAUGH9,
S_EGGMOBILE3_LAUGH10,
S_EGGMOBILE3_LAUGH11,
S_EGGMOBILE3_LAUGH12,
S_EGGMOBILE3_LAUGH13,
S_EGGMOBILE3_LAUGH14,
S_EGGMOBILE3_LAUGH15,
S_EGGMOBILE3_LAUGH16,
S_EGGMOBILE3_LAUGH17,
S_EGGMOBILE3_LAUGH18,
S_EGGMOBILE3_LAUGH19,
S_EGGMOBILE3_LAUGH20,
S_EGGMOBILE3_ROFL,
S_EGGMOBILE3_PAIN,
S_EGGMOBILE3_PAIN2,
S_EGGMOBILE3_DIE1,
S_EGGMOBILE3_DIE2,
S_EGGMOBILE3_DIE3,
S_EGGMOBILE3_DIE4,
S_EGGMOBILE3_DIE5,
S_EGGMOBILE3_DIE6,
S_EGGMOBILE3_DIE7,
S_EGGMOBILE3_DIE8,
S_EGGMOBILE3_DIE9,
S_EGGMOBILE3_DIE10,
S_EGGMOBILE3_DIE11,
S_EGGMOBILE3_DIE12,
S_EGGMOBILE3_DIE13,
S_EGGMOBILE3_DIE14,
S_EGGMOBILE3_FLEE1,
S_EGGMOBILE3_FLEE2,
// Boss 3 Propeller
S_PROPELLER1,
S_PROPELLER2,
S_PROPELLER3,
S_PROPELLER4,
S_PROPELLER5,
S_PROPELLER6,
S_PROPELLER7,
// Boss 3 Pinch
S_FAKEMOBILE_INIT,
S_FAKEMOBILE,
@ -1496,6 +1519,13 @@ typedef enum state
S_FAKEMOBILE_DIE1,
S_FAKEMOBILE_DIE2,
S_BOSSSEBH1,
S_BOSSSEBH2,
// Boss 3 Shockwave
S_SHOCKWAVE1,
S_SHOCKWAVE2,
// Boss 4
S_EGGMOBILE4_STND,
S_EGGMOBILE4_LATK1,
@ -1518,16 +1548,6 @@ typedef enum state
S_EGGMOBILE4_DIE2,
S_EGGMOBILE4_DIE3,
S_EGGMOBILE4_DIE4,
S_EGGMOBILE4_DIE5,
S_EGGMOBILE4_DIE6,
S_EGGMOBILE4_DIE7,
S_EGGMOBILE4_DIE8,
S_EGGMOBILE4_DIE9,
S_EGGMOBILE4_DIE10,
S_EGGMOBILE4_DIE11,
S_EGGMOBILE4_DIE12,
S_EGGMOBILE4_DIE13,
S_EGGMOBILE4_DIE14,
S_EGGMOBILE4_FLEE1,
S_EGGMOBILE4_FLEE2,
S_EGGMOBILE4_MACE,
@ -1548,6 +1568,25 @@ typedef enum state
S_EGGROBOJET,
// Boss 5
S_FANG_SETUP,
S_FANG_INTRO0,
S_FANG_INTRO1,
S_FANG_INTRO2,
S_FANG_INTRO3,
S_FANG_INTRO4,
S_FANG_INTRO5,
S_FANG_INTRO6,
S_FANG_INTRO7,
S_FANG_INTRO8,
S_FANG_INTRO9,
S_FANG_INTRO10,
S_FANG_INTRO11,
S_FANG_INTRO12,
S_FANG_CLONE1,
S_FANG_CLONE2,
S_FANG_CLONE3,
S_FANG_CLONE4,
S_FANG_IDLE0,
S_FANG_IDLE1,
S_FANG_IDLE2,
S_FANG_IDLE3,
@ -1583,6 +1622,7 @@ typedef enum state
S_FANG_FIRE3,
S_FANG_FIRE4,
S_FANG_FIREREPEAT,
S_FANG_LOBSHOT0,
S_FANG_LOBSHOT1,
S_FANG_LOBSHOT2,
S_FANG_WAIT1,
@ -1599,6 +1639,7 @@ typedef enum state
S_FANG_PINCHFALL2,
S_FANG_PINCHSKID1,
S_FANG_PINCHSKID2,
S_FANG_PINCHLOBSHOT0,
S_FANG_PINCHLOBSHOT1,
S_FANG_PINCHLOBSHOT2,
S_FANG_PINCHLOBSHOT3,
@ -1617,6 +1658,26 @@ typedef enum state
S_FANG_FLEEBOUNCE2,
S_FANG_KO,
S_BROKENROBOTRANDOM,
S_BROKENROBOTA,
S_BROKENROBOTB,
S_BROKENROBOTC,
S_BROKENROBOTD,
S_BROKENROBOTE,
S_BROKENROBOTF,
S_ALART1,
S_ALART2,
S_VWREF,
S_VWREB,
S_PROJECTORLIGHT1,
S_PROJECTORLIGHT2,
S_PROJECTORLIGHT3,
S_PROJECTORLIGHT4,
S_PROJECTORLIGHT5,
S_FBOMB1,
S_FBOMB2,
S_FBOMB_EXPL1,
@ -1904,21 +1965,9 @@ typedef enum state
S_METALSONIC_DEATH4,
S_METALSONIC_FLEE1,
S_METALSONIC_FLEE2,
S_METALSONIC_FLEE3,
S_METALSONIC_FLEE4,
S_MSSHIELD_F1,
S_MSSHIELD_F2,
S_MSSHIELD_F3,
S_MSSHIELD_F4,
S_MSSHIELD_F5,
S_MSSHIELD_F6,
S_MSSHIELD_F7,
S_MSSHIELD_F8,
S_MSSHIELD_F9,
S_MSSHIELD_F10,
S_MSSHIELD_F11,
S_MSSHIELD_F12,
// Ring
S_RING,
@ -2352,14 +2401,12 @@ typedef enum state
S_DRIPC1,
S_DRIPC2,
// Coral 1
// Coral
S_CORAL1,
// Coral 2
S_CORAL2,
// Coral 3
S_CORAL3,
S_CORAL4,
S_CORAL5,
// Blue Crystal
S_BLUECRYSTAL1,
@ -2367,6 +2414,11 @@ typedef enum state
// Kelp,
S_KELP,
// Animated algae
S_ANIMALGAETOP1,
S_ANIMALGAETOP2,
S_ANIMALGAESEG,
// DSZ Stalagmites
S_DSZSTALAGMITE,
S_DSZ2STALAGMITE,
@ -2501,7 +2553,7 @@ typedef enum state
S_LITTLETUMBLEWEED_ROLL7,
S_LITTLETUMBLEWEED_ROLL8,
// Cacti Sprites
// Cacti
S_CACTI1,
S_CACTI2,
S_CACTI3,
@ -2511,8 +2563,12 @@ typedef enum state
S_CACTI7,
S_CACTI8,
S_CACTI9,
S_CACTI10,
S_CACTI11,
S_CACTITINYSEG,
S_CACTISMALLSEG,
// Warning signs sprites
// Warning signs
S_ARIDSIGN_CAUTION,
S_ARIDSIGN_CACTI,
S_ARIDSIGN_SHARPTURN,
@ -2582,7 +2638,7 @@ typedef enum state
// Saloon door
S_SALOONDOOR,
S_SALOONDOORTHINKER,
S_SALOONDOORCENTER,
// Train cameo
S_TRAINCAMEOSPAWNER_1,
@ -2603,6 +2659,12 @@ typedef enum state
S_FLAMEJETFLAME1,
S_FLAMEJETFLAME2,
S_FLAMEJETFLAME3,
S_FLAMEJETFLAME4,
S_FLAMEJETFLAME5,
S_FLAMEJETFLAME6,
S_FLAMEJETFLAME7,
S_FLAMEJETFLAME8,
S_FLAMEJETFLAME9,
// Spinning flame jets
S_FJSPINAXISA1, // Counter-clockwise
@ -2615,6 +2677,28 @@ typedef enum state
S_FLAMEJETFLAMEB2,
S_FLAMEJETFLAMEB3,
// Lavafall
S_LAVAFALL_DORMANT,
S_LAVAFALL_TELL,
S_LAVAFALL_SHOOT,
S_LAVAFALL_LAVA1,
S_LAVAFALL_LAVA2,
S_LAVAFALL_LAVA3,
S_LAVAFALLROCK,
// Rollout Rock
S_ROLLOUTSPAWN,
S_ROLLOUTROCK,
// RVZ scenery
S_BIGFERNLEAF,
S_BIGFERN1,
S_BIGFERN2,
S_JUNGLEPALM,
S_TORCHFLOWER,
S_WALLVINE_LONG,
S_WALLVINE_SHORT,
// Trapgoyles
S_TRAPGOYLE,
S_TRAPGOYLE_CHECK,
@ -2646,6 +2730,9 @@ typedef enum state
S_TARGET_RESPAWN,
S_TARGET_ALLDONE,
// ATZ's green flame
S_GREENFLAME,
// Stalagmites
S_STG0,
S_STG1,
@ -2666,6 +2753,7 @@ typedef enum state
S_LAMPPOST1, // normal
S_LAMPPOST2, // with snow
S_HANGSTAR,
S_MISTLETOE,
// Xmas GFZ bushes
S_XMASBLUEBERRYBUSH,
S_XMASBERRYBUSH,
@ -2673,6 +2761,16 @@ typedef enum state
// FHZ
S_FHZICE1,
S_FHZICE2,
S_ROSY_IDLE1,
S_ROSY_IDLE2,
S_ROSY_IDLE3,
S_ROSY_IDLE4,
S_ROSY_JUMP,
S_ROSY_WALK,
S_ROSY_HUG,
S_ROSY_PAIN,
S_ROSY_STND,
S_ROSY_UNHAPPY,
// Halloween Scenery
// Pumpkins
@ -3324,6 +3422,17 @@ typedef enum state
S_BHORIZ7,
S_BHORIZ8,
// Booster
S_BOOSTERSOUND,
S_YELLOWBOOSTERROLLER,
S_YELLOWBOOSTERSEG_LEFT,
S_YELLOWBOOSTERSEG_RIGHT,
S_YELLOWBOOSTERSEG_FACE,
S_REDBOOSTERROLLER,
S_REDBOOSTERSEG_LEFT,
S_REDBOOSTERSEG_RIGHT,
S_REDBOOSTERSEG_FACE,
// Rain
S_RAIN1,
S_RAINRETURN,
@ -3344,6 +3453,9 @@ typedef enum state
S_SPLISH8,
S_SPLISH9,
// Lava Splish
S_LAVASPLISH,
// added water splash
S_SPLASH1,
S_SPLASH2,
@ -3995,6 +4107,8 @@ typedef enum mobj_type
MT_CRUSHSTACEAN, // Crushstacean
MT_CRUSHCLAW, // Big meaty claw
MT_CRUSHCHAIN, // Chain
MT_BANPYURA, // Banpyura
MT_BANPSPRING, // Banpyura spring
MT_JETJAW, // Jet Jaw
MT_SNAILER, // Snailer
MT_VULTURE, // BASH
@ -4016,6 +4130,11 @@ typedef enum mobj_type
MT_UNIBALL, // Unidus Ball
MT_CANARIVORE, // Canarivore
MT_CANARIVORE_GAS, // Canarivore gas
MT_PYREFLY, // Pyre Fly
MT_PYREFLY_FIRE, // Pyre Fly fire
MT_PTERABYTESPAWNER, // Pterabyte spawner
MT_PTERABYTEWAYPOINT, // Pterabyte waypoint
MT_PTERABYTE, // Pterabyte
// Generic Boss Items
MT_BOSSEXPLODE,
@ -4024,6 +4143,7 @@ typedef enum mobj_type
MT_EGGTRAP,
MT_BOSS3WAYPOINT,
MT_BOSS9GATHERPOINT,
MT_BOSSJUNK,
// Boss 1
MT_EGGMOBILE,
@ -4035,17 +4155,13 @@ typedef enum mobj_type
// Boss 2
MT_EGGMOBILE2,
MT_EGGMOBILE2_POGO,
MT_BOSSTANK1,
MT_BOSSTANK2,
MT_BOSSSPIGOT,
MT_GOOP,
MT_GOOPTRAIL,
// Boss 3
MT_EGGMOBILE3,
MT_PROPELLER,
MT_FAKEMOBILE,
MT_SHOCK,
MT_SHOCKWAVE,
// Boss 4
MT_EGGMOBILE4,
@ -4056,6 +4172,10 @@ typedef enum mobj_type
// Boss 5
MT_FANG,
MT_BROKENROBOT,
MT_VWREF,
MT_VWREB,
MT_PROJECTORLIGHT,
MT_FBOMB,
MT_TNTDUST, // also used by barrel
MT_FSGNA,
@ -4126,6 +4246,11 @@ typedef enum mobj_type
MT_REDHORIZ,
MT_BLUEHORIZ,
MT_BOOSTERSEG,
MT_BOOSTERROLLER,
MT_YELLOWBOOSTER,
MT_REDBOOSTER,
// Interactive Objects
MT_BUBBLES, // Bubble source
MT_SIGN, // Level end sign
@ -4254,11 +4379,15 @@ typedef enum mobj_type
MT_SEAWEED, // DSZ Seaweed
MT_WATERDRIP, // Dripping Water source
MT_WATERDROP, // Water drop from dripping water
MT_CORAL1, // Coral 1
MT_CORAL2, // Coral 2
MT_CORAL3, // Coral 3
MT_CORAL1, // Coral
MT_CORAL2,
MT_CORAL3,
MT_CORAL4,
MT_CORAL5,
MT_BLUECRYSTAL, // Blue Crystal
MT_KELP, // Kelp
MT_ANIMALGAETOP, // Animated algae top
MT_ANIMALGAESEG, // Animated algae segment
MT_DSZSTALAGMITE, // Deep Sea 1 Stalagmite
MT_DSZ2STALAGMITE, // Deep Sea 2 Stalagmite
MT_LIGHTBEAM, // DSZ Light beam
@ -4309,15 +4438,19 @@ typedef enum mobj_type
// Arid Canyon Scenery
MT_BIGTUMBLEWEED,
MT_LITTLETUMBLEWEED,
MT_CACTI1,
MT_CACTI2,
MT_CACTI3,
MT_CACTI4,
MT_CACTI5, // Harmful Cactus 1
MT_CACTI6, // Harmful Cactus 2
MT_CACTI7, // Harmful Cactus 3
MT_CACTI8, // Harmful Cactus 4
MT_CACTI9, // Harmful Cactus 5
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
@ -4335,7 +4468,7 @@ typedef enum mobj_type
MT_MINECARTSIDEMARK,
MT_MINECARTSPARK,
MT_SALOONDOOR,
MT_SALOONDOORTHINKER,
MT_SALOONDOORCENTER,
MT_TRAINCAMEOSPAWNER,
MT_TRAINSEG,
MT_TRAINDUSTSPAWNER,
@ -4352,6 +4485,20 @@ typedef enum mobj_type
MT_FLAMEJETFLAMEB, // Blade's flame
MT_LAVAFALL,
MT_LAVAFALL_LAVA,
MT_LAVAFALLROCK,
MT_ROLLOUTSPAWN,
MT_ROLLOUTROCK,
MT_BIGFERNLEAF,
MT_BIGFERN,
MT_JUNGLEPALM,
MT_TORCHFLOWER,
MT_WALLVINE_LONG,
MT_WALLVINE_SHORT,
// Dark City Scenery
// Egg Rock Scenery
@ -4362,6 +4509,7 @@ typedef enum mobj_type
MT_TRAPGOYLEDOWN,
MT_TRAPGOYLELONG,
MT_TARGET, // AKA Red Crystal
MT_GREENFLAME,
// Stalagmites
MT_STALAGMITE0,
@ -4383,6 +4531,7 @@ typedef enum mobj_type
MT_LAMPPOST1, // normal
MT_LAMPPOST2, // with snow
MT_HANGSTAR,
MT_MISTLETOE,
// Xmas GFZ bushes
MT_XMASBLUEBERRYBUSH,
MT_XMASBERRYBUSH,
@ -4390,6 +4539,8 @@ typedef enum mobj_type
// FHZ
MT_FHZICE1,
MT_FHZICE2,
MT_ROSY,
MT_CDLHRT,
// Halloween Scenery
// Pumpkins
@ -4518,6 +4669,7 @@ typedef enum mobj_type
MT_RAIN, // Rain
MT_SNOWFLAKE, // Snowflake
MT_SPLISH, // Water splish!
MT_LAVASPLISH, // Lava splish!
MT_SMOKE,
MT_SMALLBUBBLE, // small bubble
MT_MEDIUMBUBBLE, // medium bubble

View File

@ -182,6 +182,8 @@ static const struct {
{META_CAMERA, "camera_t"},
{META_ACTION, "action"},
{META_LUABANKS, "luabanks[]"},
{NULL, NULL}
};
@ -228,6 +230,18 @@ static int lib_isPlayerAdmin(lua_State *L)
return 1;
}
static int lib_reserveLuabanks(lua_State *L)
{
static boolean reserved = false;
if (!lua_lumploading)
return luaL_error(L, "luabanks[] cannot be reserved from within a hook or coroutine!");
if (reserved)
return luaL_error(L, "luabanks[] has already been reserved! Only one savedata-enabled mod at a time may use this feature.");
reserved = true;
LUA_PushUserdata(L, &luabanks, META_LUABANKS);
return 1;
}
// M_RANDOM
//////////////
@ -802,15 +816,12 @@ static int lib_pCheckDeathPitCollide(lua_State *L)
static int lib_pCheckSolidLava(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
if (!rover)
return LUA_ErrInvalid(L, "ffloor_t");
lua_pushboolean(L, P_CheckSolidLava(mo, rover));
lua_pushboolean(L, P_CheckSolidLava(rover));
return 1;
}
@ -2736,6 +2747,7 @@ static luaL_Reg lib[] = {
{"chatprintf", lib_chatprintf},
{"userdataType", lib_userdataType},
{"IsPlayerAdmin", lib_isPlayerAdmin},
{"reserveLuabanks", lib_reserveLuabanks},
// m_random
{"P_RandomFixed",lib_pRandomFixed},

View File

@ -308,6 +308,8 @@ static int lib_cvRegisterVar(lua_State *L)
#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e);
#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1)))
memset(cvar, 0x00, sizeof(consvar_t)); // zero everything by default
lua_pushnil(L);
while (lua_next(L, 1)) {
// stack: cvar table, cvar userdata, key/index, value
@ -395,6 +397,13 @@ static int lib_cvRegisterVar(lua_State *L)
#undef FIELDERROR
#undef TYPEERROR
if (!cvar->name)
return luaL_error(L, M_GetText("Variable has no name!\n"));
if ((cvar->flags & CV_NOINIT) && !(cvar->flags & CV_CALL))
return luaL_error(L, M_GetText("Variable %s has CV_NOINIT without CV_CALL\n"), cvar->name);
if ((cvar->flags & CV_CALL) && !cvar->func)
return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function\n"), cvar->name);
// stack: cvar table, cvar userdata
lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars");
I_Assert(lua_istable(L, 3));

View File

@ -50,6 +50,7 @@ enum hook {
hook_FollowMobj,
hook_PlayerCanDamage,
hook_PlayerQuit,
hook_IntermissionThinker,
hook_MAX // last hook
};
@ -91,5 +92,6 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnM
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_IntermissionThinker(void); // Hook for Y_Ticker
#endif

View File

@ -61,6 +61,7 @@ const char *const hookNames[hook_MAX+1] = {
"FollowMobj",
"PlayerCanDamage",
"PlayerQuit",
"IntermissionThinker",
NULL
};
@ -1322,4 +1323,27 @@ void LUAh_PlayerQuit(player_t *plr, int reason)
lua_settop(gL, 0);
}
// Hook for Y_Ticker
void LUAh_IntermissionThinker(void)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8))))
return;
for (hookp = roothook; hookp; hookp = hookp->next)
{
if (hookp->type != hook_IntermissionThinker)
continue;
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
if (lua_pcall(gL, 0, 0, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
}
}
}
#endif

View File

@ -637,6 +637,68 @@ static int libd_drawString(lua_State *L)
return 0;
}
static int libd_drawNameTag(lua_State *L)
{
INT32 x;
INT32 y;
const char *str;
INT32 flags;
UINT8 basecolor;
UINT8 outlinecolor;
UINT8 *basecolormap = NULL;
UINT8 *outlinecolormap = NULL;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
str = luaL_checkstring(L, 3);
flags = luaL_optinteger(L, 4, 0);
basecolor = luaL_optinteger(L, 5, SKINCOLOR_BLUE);
outlinecolor = luaL_optinteger(L, 6, SKINCOLOR_ORANGE);
if (basecolor != SKINCOLOR_NONE)
basecolormap = R_GetTranslationColormap(TC_DEFAULT, basecolor, GTC_CACHE);
if (outlinecolor != SKINCOLOR_NONE)
outlinecolormap = R_GetTranslationColormap(TC_DEFAULT, outlinecolor, GTC_CACHE);
flags &= ~V_PARAMMASK; // Don't let crashes happen.
V_DrawNameTag(x, y, flags, FRACUNIT, basecolormap, outlinecolormap, str);
return 0;
}
static int libd_drawScaledNameTag(lua_State *L)
{
fixed_t x;
fixed_t y;
const char *str;
INT32 flags;
fixed_t scale;
UINT8 basecolor;
UINT8 outlinecolor;
UINT8 *basecolormap = NULL;
UINT8 *outlinecolormap = NULL;
HUDONLY
x = luaL_checkfixed(L, 1);
y = luaL_checkfixed(L, 2);
str = luaL_checkstring(L, 3);
flags = luaL_optinteger(L, 4, 0);
scale = luaL_optinteger(L, 5, FRACUNIT);
if (scale < 0)
return luaL_error(L, "negative scale");
basecolor = luaL_optinteger(L, 6, SKINCOLOR_BLUE);
outlinecolor = luaL_optinteger(L, 7, SKINCOLOR_ORANGE);
if (basecolor != SKINCOLOR_NONE)
basecolormap = R_GetTranslationColormap(TC_DEFAULT, basecolor, GTC_CACHE);
if (outlinecolor != SKINCOLOR_NONE)
outlinecolormap = R_GetTranslationColormap(TC_DEFAULT, outlinecolor, GTC_CACHE);
flags &= ~V_PARAMMASK; // Don't let crashes happen.
V_DrawNameTag(FixedInt(x), FixedInt(y), flags, scale, basecolormap, outlinecolormap, str);
return 0;
}
static int libd_stringWidth(lua_State *L)
{
const char *str = luaL_checkstring(L, 1);
@ -659,6 +721,13 @@ static int libd_stringWidth(lua_State *L)
return 1;
}
static int libd_nameTagWidth(lua_State *L)
{
HUDONLY
lua_pushinteger(L, V_NameTagWidth(luaL_checkstring(L, 1)));
return 1;
}
static int libd_getColormap(lua_State *L)
{
INT32 skinnum = TC_DEFAULT;
@ -837,9 +906,12 @@ static luaL_Reg lib_draw[] = {
{"drawPaddedNum", libd_drawPaddedNum},
{"drawFill", libd_drawFill},
{"drawString", libd_drawString},
{"drawNameTag", libd_drawNameTag},
{"drawScaledNameTag", libd_drawScaledNameTag},
{"fadeScreen", libd_fadeScreen},
// misc
{"stringWidth", libd_stringWidth},
{"nameTagWidth", libd_nameTagWidth},
// m_random
{"RandomFixed",libd_RandomFixed},
{"RandomByte",libd_RandomByte},

View File

@ -18,6 +18,7 @@
#include "p_mobj.h"
#include "p_local.h"
#include "z_zone.h"
#include "doomstat.h" // luabanks[]
#include "lua_script.h"
#include "lua_libs.h"
@ -146,7 +147,7 @@ static int lib_getSpr2default(lua_State *L)
return luaL_error(L, "spr2defaults[] invalid index");
if (i >= free_spr2)
return 0;
return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, 0, free_spr2-1);
lua_pushinteger(L, spr2defaults[i]);
return 1;
@ -1026,6 +1027,61 @@ static int sfxinfo_num(lua_State *L)
return 1;
}
//////////////
// LUABANKS //
//////////////
static int lib_getluabanks(lua_State *L)
{
UINT8 i;
lua_remove(L, 1); // don't care about luabanks[] dummy userdata.
if (lua_isnumber(L, 1))
i = lua_tonumber(L, 1);
else
return luaL_error(L, "luabanks[] invalid index");
if (i >= NUM_LUABANKS)
luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1);
lua_pushinteger(L, luabanks[i]);
return 1;
}
static int lib_setluabanks(lua_State *L)
{
UINT8 i;
INT32 j = 0;
if (hud_running)
return luaL_error(L, "Do not alter luabanks[] in HUD rendering code!");
lua_remove(L, 1); // don't care about luabanks[] dummy userdata.
if (lua_isnumber(L, 1))
i = lua_tonumber(L, 1);
else
return luaL_error(L, "luabanks[] invalid index");
if (i >= NUM_LUABANKS)
luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1);
if (lua_isnumber(L, 2))
j = lua_tonumber(L, 2);
else
return luaL_error(L, "luabanks[] invalid set");
luabanks[i] = j;
return 0;
}
static int lib_luabankslen(lua_State *L)
{
lua_pushinteger(L, NUM_LUABANKS);
return 1;
}
//////////////////////////////
//
// Now push all these functions into the Lua state!
@ -1147,6 +1203,18 @@ int LUA_InfoLib(lua_State *L)
lua_pushvalue(L, -1);
lua_setglobal(L, "S_sfx");
lua_setglobal(L, "sfxinfo");
luaL_newmetatable(L, META_LUABANKS);
lua_pushcfunction(L, lib_getluabanks);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_setluabanks);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, lib_luabankslen);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
return 0;
}

View File

@ -67,6 +67,8 @@ extern lua_State *gL;
#define META_ACTION "ACTIONF_T*"
#define META_LUABANKS "LUABANKS[]*"
boolean luaL_checkboolean(lua_State *L, int narg);
int LUA_EnumLib(lua_State *L);

View File

@ -411,37 +411,53 @@ static int sector_iterate(lua_State *L)
// sector.lines, i -> sector.lines[i]
// sector.lines.valid, for validity checking
//
// 25/9/19 Monster Iestyn
// Modified this and _num to use triple pointers, to allow for a new hack of mine involving offsetof
// this way we don't need to check frontsector or backsector of line #0 in the array
//
static int sectorlines_get(lua_State *L)
{
line_t **seclines = *((line_t ***)luaL_checkudata(L, 1, META_SECTORLINES));
line_t ***seclines = *((line_t ****)luaL_checkudata(L, 1, META_SECTORLINES));
size_t i;
size_t numoflines = 0;
lua_settop(L, 2);
if (!lua_isnumber(L, 2))
{
int field = luaL_checkoption(L, 2, NULL, valid_opt);
if (!seclines)
if (!seclines || !(*seclines))
{
if (field == 0) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed sector_t doesn't exist anymore.");
return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
} else if (field == 0) {
lua_pushboolean(L, 1);
return 1;
}
}
/* a snip from sector_t struct in r_defs.h, for reference
size_t linecount;
struct line_s **lines; // [linecount] size
*/
// get the "linecount" by shifting our retrieved memory address of "lines" to where "linecount" is in the sector_t, then dereferencing the result
// we need this to determine the array's actual size, and therefore also the maximum value allowed as an index
// this only works if seclines is actually a pointer to a sector's lines member in memory, oh boy
numoflines = (size_t)(*(seclines - (offsetof(sector_t, lines) - offsetof(sector_t, linecount))));
/* OLD HACK
// check first linedef to figure which of its sectors owns this sector->lines pointer
// then check that sector's linecount to get a maximum index
//if (!seclines[0])
//if (!(*seclines)[0])
//return luaL_error(L, "no lines found!"); // no first linedef?????
if (seclines[0]->frontsector->lines == seclines)
numoflines = seclines[0]->frontsector->linecount;
else if (seclines[0]->backsector && seclines[0]->backsector->lines == seclines) // check backsector exists first
numoflines = seclines[0]->backsector->linecount;
if ((*seclines)[0]->frontsector->lines == *seclines)
numoflines = (*seclines)[0]->frontsector->linecount;
else if ((*seclines)[0]->backsector && *seclines[0]->backsector->lines == *seclines) // check backsector exists first
numoflines = (*seclines)[0]->backsector->linecount;
//if neither sector has it then ???
*/
if (!numoflines)
return luaL_error(L, "no lines found!");
@ -449,23 +465,21 @@ static int sectorlines_get(lua_State *L)
i = (size_t)lua_tointeger(L, 2);
if (i >= numoflines)
return 0;
LUA_PushUserdata(L, seclines[i], META_LINE);
LUA_PushUserdata(L, (*seclines)[i], META_LINE);
return 1;
}
// #(sector.lines) -> sector.linecount
static int sectorlines_num(lua_State *L)
{
line_t **seclines = *((line_t ***)luaL_checkudata(L, 1, META_SECTORLINES));
line_t ***seclines = *((line_t ****)luaL_checkudata(L, 1, META_SECTORLINES));
size_t numoflines = 0;
// check first linedef to figure which of its sectors owns this sector->lines pointer
// then check that sector's linecount to get a maximum index
//if (!seclines[0])
//return luaL_error(L, "no lines found!"); // no first linedef?????
if (seclines[0]->frontsector->lines == seclines)
numoflines = seclines[0]->frontsector->linecount;
else if (seclines[0]->backsector && seclines[0]->backsector->lines == seclines) // check backsector exists first
numoflines = seclines[0]->backsector->linecount;
//if neither sector has it then ???
if (!seclines || !(*seclines))
return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
// see comments in the _get function above
numoflines = (size_t)(*(seclines - (offsetof(sector_t, lines) - offsetof(sector_t, linecount))));
lua_pushinteger(L, numoflines);
return 1;
}
@ -543,7 +557,7 @@ static int sector_get(lua_State *L)
LUA_PushUserdata(L, &sectors[sector->camsec], META_SECTOR);
return 1;
case sector_lines: // lines
LUA_PushUserdata(L, sector->lines, META_SECTORLINES);
LUA_PushUserdata(L, &sector->lines, META_SECTORLINES); // push the address of the "lines" member in the struct, to allow our hacks in sectorlines_get/_num to work
return 1;
case sector_ffloors: // ffloors
lua_pushcfunction(L, lib_iterateSectorFFloors);
@ -579,6 +593,7 @@ static int sector_set(lua_State *L)
case sector_thinglist: // thinglist
case sector_heightsec: // heightsec
case sector_camsec: // camsec
case sector_lines: // lines
case sector_ffloors: // ffloors
#ifdef ESLOPE
case sector_fslope: // f_slope
@ -2017,6 +2032,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->muspostbosspos);
else if (fastcmp(field,"muspostbossfadein"))
lua_pushinteger(L, header->muspostbossfadein);
else if (fastcmp(field,"musforcereset"))
lua_pushinteger(L, header->musforcereset);
else if (fastcmp(field,"forcecharacter"))
lua_pushstring(L, header->forcecharacter);
else if (fastcmp(field,"weather"))

View File

@ -173,15 +173,15 @@ static int lib_all7emeralds(lua_State *L)
return 1;
}
// Whee, special Lua-exclusive function for making use of Color_Opposite[] without needing *2 or +1
// Returns both color and frame numbers!
// Whee, special Lua-exclusive function for making use of Color_Opposite[]
// Returns both color and signpost shade numbers!
static int lib_coloropposite(lua_State *L)
{
UINT8 colornum = (UINT8)luaL_checkinteger(L, 1);
if (colornum >= MAXSKINCOLORS)
return luaL_error(L, "skincolor %d out of range (0 - %d).", colornum, MAXSKINCOLORS-1);
lua_pushinteger(L, Color_Opposite[colornum*2]); // push color
lua_pushinteger(L, Color_Opposite[colornum*2+1]); // push frame
if (!colornum || colornum >= MAXSKINCOLORS)
return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, MAXSKINCOLORS-1);
lua_pushinteger(L, Color_Opposite[colornum-1][0]); // push color
lua_pushinteger(L, Color_Opposite[colornum-1][1]); // push sign shade index, 0-15
return 2;
}

View File

@ -164,6 +164,8 @@ static int mobj_get(lua_State *L)
enum mobj_e field = Lua_optoption(L, 2, NULL, mobj_opt);
lua_settop(L, 2);
INLEVEL
if (!mo) {
if (field == mobj_valid) {
lua_pushboolean(L, 0);
@ -409,6 +411,8 @@ static int mobj_set(lua_State *L)
enum mobj_e field = Lua_optoption(L, 2, mobj_opt[0], mobj_opt);
lua_settop(L, 3);
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");

View File

@ -25,7 +25,6 @@
static int lib_iteratePlayers(lua_State *L)
{
INT32 i = -1;
INLEVEL
if (lua_gettop(L) < 2)
{
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
@ -52,7 +51,6 @@ static int lib_getPlayer(lua_State *L)
{
const char *field;
// i -> players[i]
INLEVEL
if (lua_type(L, 2) == LUA_TNUMBER)
{
lua_Integer i = luaL_checkinteger(L, 2);
@ -136,6 +134,12 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->currentweapon);
else if (fastcmp(field,"ringweapons"))
lua_pushinteger(L, plr->ringweapons);
else if (fastcmp(field,"ammoremoval"))
lua_pushinteger(L, plr->ammoremoval);
else if (fastcmp(field,"ammoremovaltimer"))
lua_pushinteger(L, plr->ammoremovaltimer);
else if (fastcmp(field,"ammoremovalweapon"))
lua_pushinteger(L, plr->ammoremovalweapon);
else if (fastcmp(field,"powers"))
LUA_PushUserdata(L, plr->powers, META_POWERS);
else if (fastcmp(field,"pflags"))
@ -256,6 +260,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->starposttime);
else if (fastcmp(field,"starpostangle"))
lua_pushangle(L, plr->starpostangle);
else if (fastcmp(field,"starpostscale"))
lua_pushfixed(L, plr->starpostscale);
else if (fastcmp(field,"angle_pos"))
lua_pushangle(L, plr->angle_pos);
else if (fastcmp(field,"old_angle_pos"))
@ -428,6 +434,12 @@ static int player_set(lua_State *L)
plr->currentweapon = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"ringweapons"))
plr->ringweapons = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"ammoremoval"))
plr->ammoremoval = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"ammoremovaltimer"))
plr->ammoremovaltimer = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"ammoremovalweapon"))
plr->ammoremovalweapon = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"powers"))
return NOSET;
else if (fastcmp(field,"pflags"))
@ -558,6 +570,8 @@ static int player_set(lua_State *L)
plr->starposttime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"starpostangle"))
plr->starpostangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"starpostscale"))
plr->starpostscale = luaL_checkfixed(L, 3);
else if (fastcmp(field,"angle_pos"))
plr->angle_pos = luaL_checkangle(L, 3);
else if (fastcmp(field,"old_angle_pos"))

View File

@ -431,7 +431,7 @@ void LUA_InvalidateLevel(void)
for (i = 0; i < numsectors; i++)
{
LUA_InvalidateUserdata(&sectors[i]);
LUA_InvalidateUserdata(sectors[i].lines);
LUA_InvalidateUserdata(&sectors[i].lines);
if (sectors[i].ffloors)
{
for (rover = sectors[i].ffloors; rover; rover = rover->next)
@ -1121,7 +1121,7 @@ void LUA_Archive(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!playeringame[i] && i > 0) // dedicated servers...
continue;
// all players in game will be archived, even if they just add a 0.
ArchiveExtVars(&players[i], "player");
@ -1157,7 +1157,7 @@ void LUA_UnArchive(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!playeringame[i] && i > 0) // dedicated servers...
continue;
UnArchiveExtVars(&players[i]);
}

View File

@ -52,6 +52,8 @@ enum skin {
skin_supercolor,
skin_prefoppositecolor,
skin_highresscale,
skin_contspeed,
skin_contangle,
skin_soundsid,
skin_availability
};
@ -88,6 +90,8 @@ static const char *const skin_opt[] = {
"supercolor",
"prefoppositecolor",
"highresscale",
"contspeed",
"contangle",
"soundsid",
"availability",
NULL};
@ -199,6 +203,12 @@ static int skin_get(lua_State *L)
case skin_highresscale:
lua_pushinteger(L, skin->highresscale);
break;
case skin_contspeed:
lua_pushinteger(L, skin->contspeed);
break;
case skin_contangle:
lua_pushinteger(L, skin->contangle);
break;
case skin_soundsid:
LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID);
break;

View File

@ -746,6 +746,18 @@ void Command_Weather_f(void)
P_SwitchWeather(atoi(COM_Argv(1)));
}
void Command_Toggletwod_f(void)
{
player_t *p = &players[consoleplayer];
REQUIRE_DEVMODE;
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
if (p->mo)
p->mo->flags2 ^= MF2_TWOD;
}
#ifdef _DEBUG
// You never thought you needed this, did you? >=D
// Yes, this has the specific purpose of completely screwing you up
@ -819,6 +831,12 @@ void Command_Savecheckpoint_f(void)
players[consoleplayer].starposty = players[consoleplayer].mo->y>>FRACBITS;
players[consoleplayer].starpostz = players[consoleplayer].mo->floorz>>FRACBITS;
players[consoleplayer].starpostangle = players[consoleplayer].mo->angle;
players[consoleplayer].starpostscale = players[consoleplayer].mo->destscale;
if (players[consoleplayer].mo->flags2 & MF2_OBJECTFLIP)
{
players[consoleplayer].starpostscale *= -1;
players[consoleplayer].starpostz += players[consoleplayer].mo->height;
}
CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].starpostx, players[consoleplayer].starposty, players[consoleplayer].starpostz);
}

View File

@ -64,6 +64,7 @@ void Command_Teleport_f(void);
void Command_RTeleport_f(void);
void Command_Skynum_f(void);
void Command_Weather_f(void);
void Command_Toggletwod_f(void);
#ifdef _DEBUG
void Command_CauseCfail_f(void);
#endif

View File

@ -528,12 +528,22 @@ skincolors_t M_GetEmblemColor(emblem_t *em)
return em->color;
}
const char *M_GetEmblemPatch(emblem_t *em)
const char *M_GetEmblemPatch(emblem_t *em, boolean big)
{
static char pnamebuf[7] = "GOTITn";
static char pnamebuf[7];
if (!big)
strcpy(pnamebuf, "GOTITn");
else
strcpy(pnamebuf, "EMBMn0");
I_Assert(em->sprite >= 'A' && em->sprite <= 'Z');
pnamebuf[5] = em->sprite;
if (!big)
pnamebuf[5] = em->sprite;
else
pnamebuf[4] = em->sprite;
return pnamebuf;
}
@ -544,11 +554,21 @@ skincolors_t M_GetExtraEmblemColor(extraemblem_t *em)
return em->color;
}
const char *M_GetExtraEmblemPatch(extraemblem_t *em)
const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big)
{
static char pnamebuf[7] = "GOTITn";
static char pnamebuf[7];
if (!big)
strcpy(pnamebuf, "GOTITn");
else
strcpy(pnamebuf, "EMBMn0");
I_Assert(em->sprite >= 'A' && em->sprite <= 'Z');
pnamebuf[5] = em->sprite;
if (!big)
pnamebuf[5] = em->sprite;
else
pnamebuf[4] = em->sprite;
return pnamebuf;
}

View File

@ -171,9 +171,9 @@ INT32 M_CountEmblems(void);
// Emblem shit
emblem_t *M_GetLevelEmblems(INT32 mapnum);
skincolors_t M_GetEmblemColor(emblem_t *em);
const char *M_GetEmblemPatch(emblem_t *em);
const char *M_GetEmblemPatch(emblem_t *em, boolean big);
skincolors_t M_GetExtraEmblemColor(extraemblem_t *em);
const char *M_GetExtraEmblemPatch(extraemblem_t *em);
const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big);
// If you're looking to compare stats for unlocks or what not, use these
// They stop checking upon reaching the target number so they

File diff suppressed because it is too large Load Diff

View File

@ -64,6 +64,7 @@ typedef enum
MN_MP_CONNECT,
MN_MP_ROOM,
MN_MP_PLAYERSETUP, // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
MN_MP_SERVER_OPTIONS,
// Options
MN_OP_MAIN,
@ -73,10 +74,12 @@ typedef enum
MN_OP_P1MOUSE,
MN_OP_P1JOYSTICK,
MN_OP_JOYSTICKSET, // OP_JoystickSetDef shared with P2
MN_OP_P1CAMERA,
MN_OP_P2CONTROLS,
MN_OP_P2MOUSE,
MN_OP_P2JOYSTICK,
MN_OP_P2CAMERA,
MN_OP_VIDEO,
MN_OP_VIDEOMODE,
@ -102,6 +105,7 @@ typedef enum
MN_SR_LEVELSELECT,
MN_SR_UNLOCKCHECKLIST,
MN_SR_EMBLEMHINT,
MN_SR_PLAYER,
// Addons (Part of MISC, but let's make it our own)
MN_AD_MAIN,
@ -216,7 +220,6 @@ void M_QuitResponse(INT32 ch);
// Determines whether to show a level in the list (platter version does not need to be exposed)
boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
// flags for items in the menu
// menu handle (what we do when key is pressed
#define IT_TYPE 14 // (2+4+8)
@ -252,6 +255,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
#define IT_CV_NOPRINT 1536
#define IT_CV_NOMOD 2048
#define IT_CV_INVISSLIDER 2560
#define IT_CV_INTEGERSTEP 4096 // if IT_CV_NORMAL and cvar is CV_FLOAT, modify it by 1 instead of 0.0625
#define IT_CV_FLOATSLIDER 4608 // IT_CV_SLIDER, value modified by 0.0625 instead of 1 (for CV_FLOAT cvars)
//call/submenu specific
// There used to be a lot more here but ...
@ -319,6 +324,10 @@ extern menu_t *currentMenu;
extern menu_t MainDef;
extern menu_t SP_LoadDef;
// Call upon joystick hotplug
void M_SetupJoystickMenu(INT32 choice);
extern menu_t OP_JoystickSetDef;
// Stuff for customizing the player select screen
typedef struct
{
@ -326,9 +335,18 @@ typedef struct
char notes[441];
char picname[8];
char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
patch_t *pic;
patch_t *charpic;
UINT8 prev;
UINT8 next;
// new character select
char displayname[SKINNAMESIZE+1];
SINT8 skinnum[2];
UINT8 oppositecolor;
char nametag[8];
patch_t *namepic;
UINT8 tagtextcolor;
UINT8 tagoutlinecolor;
} description_t;
// level select platter
@ -377,6 +395,7 @@ typedef struct
extern description_t description[MAXSKINS];
extern consvar_t cv_showfocuslost;
extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
extern CV_PossibleValue_t gametype_cons_t[];
@ -407,6 +426,9 @@ void Screenshot_option_Onchange(void);
// Addons menu updating
void Addons_option_Onchange(void);
// Moviemode menu updating
void Moviemode_option_Onchange(void);
// These defines make it a little easier to make menus
#define DEFAULTMENUSTYLE(id, header, source, prev, x, y)\
{\

View File

@ -108,6 +108,9 @@ consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAV
static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}};
consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_movie_option = {"movie_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Moviemode_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_movie_folder = {"movie_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t zlib_mem_level_t[] = {
{1, "(Min Memory) 1"},
{2, "2"}, {3, "3"}, {4, "4"}, {5, "5"}, {6, "6"}, {7, "7"},
@ -194,7 +197,7 @@ INT32 M_MapNumber(char first, char second)
// ==========================================================================
// some libcs has no access function, make our own
#if defined (_WIN32_WCE)
#if 0
int access(const char *path, int amode)
{
int accesshandle = -1;
@ -1124,19 +1127,25 @@ static inline moviemode_t M_StartMovieGIF(const char *pathname)
void M_StartMovie(void)
{
#if NUMSCREENS > 2
const char *pathname = ".";
char pathname[MAX_WADPATH];
if (moviemode)
return;
if (cv_screenshot_option.value == 0)
pathname = usehome ? srb2home : srb2path;
else if (cv_screenshot_option.value == 1)
pathname = srb2home;
else if (cv_screenshot_option.value == 2)
pathname = srb2path;
else if (cv_screenshot_option.value == 3 && *cv_screenshot_folder.string != '\0')
pathname = cv_screenshot_folder.string;
if (cv_movie_option.value == 0)
strcpy(pathname, usehome ? srb2home : srb2path);
else if (cv_movie_option.value == 1)
strcpy(pathname, srb2home);
else if (cv_movie_option.value == 2)
strcpy(pathname, srb2path);
else if (cv_movie_option.value == 3 && *cv_movie_folder.string != '\0')
strcpy(pathname, cv_movie_folder.string);
if (cv_movie_option.value != 3)
{
strcat(pathname, PATHSEP"movies"PATHSEP);
I_mkdir(pathname, 0755);
}
if (rendermode == render_none)
I_Error("Can't make a movie without a render system\n");
@ -1474,7 +1483,8 @@ void M_ScreenShot(void)
void M_DoScreenShot(void)
{
#if NUMSCREENS > 2
const char *freename = NULL, *pathname = ".";
const char *freename = NULL;
char pathname[MAX_WADPATH];
boolean ret = false;
UINT8 *linear = NULL;
@ -1486,13 +1496,19 @@ void M_DoScreenShot(void)
return;
if (cv_screenshot_option.value == 0)
pathname = usehome ? srb2home : srb2path;
strcpy(pathname, usehome ? srb2home : srb2path);
else if (cv_screenshot_option.value == 1)
pathname = srb2home;
strcpy(pathname, srb2home);
else if (cv_screenshot_option.value == 2)
pathname = srb2path;
strcpy(pathname, srb2path);
else if (cv_screenshot_option.value == 3 && *cv_screenshot_folder.string != '\0')
pathname = cv_screenshot_folder.string;
strcpy(pathname, cv_screenshot_folder.string);
if (cv_screenshot_option.value != 3)
{
strcat(pathname, PATHSEP"screenshots"PATHSEP);
I_mkdir(pathname, 0755);
}
#ifdef USE_PNG
freename = Newsnapshotfile(pathname,"png");

View File

@ -30,7 +30,7 @@ typedef enum {
extern moviemode_t moviemode;
extern consvar_t cv_screenshot_option, cv_screenshot_folder, cv_screenshot_colorprofile;
extern consvar_t cv_moviemode;
extern consvar_t cv_moviemode, cv_movie_folder, cv_movie_option;
extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits;
extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa;
extern consvar_t cv_apng_delay;

View File

@ -14,29 +14,39 @@
#ifndef __M_SWAP__
#define __M_SWAP__
#include "endian.h"
// Endianess handling.
// WAD files are stored little endian.
#include "endian.h"
// Little to big endian
#ifdef SRB2_BIG_ENDIAN
#define SHORT(x) ((INT16)(\
(((UINT16)(x) & (UINT16)0x00ffU) << 8) \
| \
(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \
#define SHORT(x) ((INT16)(\
(((UINT16)(x) & (UINT16)0x00ffU) << 8) \
| \
(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \
#define LONG(x) ((INT32)(\
(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \
| \
(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \
| \
(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \
| \
(((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
#define LONG(x) ((INT32)(\
(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \
| \
(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \
| \
(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \
| \
(((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
#else
#define SHORT(x) ((INT16)(x))
#define LONG(x) ((INT32)(x))
#define SHORT(x) ((INT16)(x))
#define LONG(x) ((INT32)(x))
#endif
// Big to little endian
#ifdef SRB2_LITTLE_ENDIAN
#define BIGENDIAN_LONG(x) ((INT32)(((x)>>24)&0xff)|(((x)<<8)&0xff0000)|(((x)>>8)&0xff00)|(((x)<<24)&0xff000000))
#define BIGENDIAN_SHORT(x) ((INT16)(((x)>>8)|((x)<<8)))
#else
#define BIGENDIAN_LONG(x) ((INT32)(x))
#define BIGENDIAN_SHORT(x) ((INT16)(x))
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1778,6 +1778,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
case MT_RAIN:
case MT_SNOWFLAKE:
case MT_SPLISH:
case MT_LAVASPLISH:
case MT_SMOKE:
case MT_SMALLBUBBLE:
case MT_MEDIUMBUBBLE:
@ -2424,7 +2425,7 @@ void T_RaiseSector(levelspecthink_t *raise)
mobj_t *thing;
sector_t *sector;
INT32 i;
boolean playeronme = false;
boolean playeronme = false, active = false;
fixed_t ceilingdestination, floordestination;
result_e res = 0;
@ -2458,8 +2459,53 @@ void T_RaiseSector(levelspecthink_t *raise)
break;
}
}
if (raise->vars[9]) // Dynamically Sinking Platform^tm
{
#define shaketime 10
if (raise->vars[11] > shaketime) // State: moving
{
if (playeronme) // If player is standing on the platform, accelerate
{
raise->vars[10] += (FRACUNIT >> 5);
}
else // otherwise, decelerate until inflection
{
raise->vars[10] -= FRACUNIT >> 3;
if (raise->vars[10] <= 0) // inflection!
{
raise->vars[10] = 0;
raise->vars[11] = 0; // allow the shake to occur again (fucks over players attempting to jump-cheese)
}
}
active = raise->vars[10] > 0;
}
else // State: shaking
{
if (playeronme || raise->vars[11])
{
active = true;
if (++raise->vars[11] > shaketime)
{
if (playeronme)
raise->vars[10] = FRACUNIT >> 5;
else
raise->vars[10] = FRACUNIT << 1;
}
else
{
raise->vars[10] = ((shaketime/2) - raise->vars[11]) << FRACBITS;
if (raise->vars[10] < -raise->vars[2]/2)
raise->vars[10] = -raise->vars[2]/2;
}
}
}
#undef shaketime
}
else // Air bobbing platform (not a Dynamically Sinking Platform^tm)
active = playeronme;
if (playeronme)
if (active)
{
raise->vars[3] = raise->vars[2];
@ -2553,6 +2599,8 @@ void T_RaiseSector(levelspecthink_t *raise)
raise->vars[3] = origspeed;
}
raise->vars[3] += raise->vars[10];
res = T_MovePlane
(
raise->sector, // sector

View File

@ -428,7 +428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|| special->state == &states[S_FANG_BOUNCE4]
|| special->state == &states[S_FANG_PINCHBOUNCE3]
|| special->state == &states[S_FANG_PINCHBOUNCE4])
&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > 0)
&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > (special->height/4))
{
P_DamageMobj(toucher, special, special, 1, 0);
P_SetTarget(&special->tracer, toucher);
@ -450,12 +450,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
}
break;
case MT_PYREFLY:
if (special->extravalue2 == 2 && P_DamageMobj(player->mo, special, special, 1, DMG_FIRE))
return;
default:
break;
}
if (P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object?
{
if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1)
return; // Can't hurt a Pterabyte if it's trying to pick you up
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
{
if (elementalpierce == 2)
@ -477,7 +483,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_TwinSpinRejuvenate(player, player->thokitem);
}
else
{
if (special->type == MT_PTERABYTE && special->target == player->mo)
return; // Don't hurt the player you're trying to grab
P_DamageMobj(toucher, special, special, 1, 0);
}
return;
}
@ -1074,7 +1085,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->exiting)
return;
if (player->bumpertime < TICRATE/4)
if (player->bumpertime <= (TICRATE/2)-5)
{
S_StartSound(toucher, special->info->seesound);
if (player->powers[pw_carry] == CR_NIGHTSMODE)
@ -1427,6 +1438,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
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]))
@ -1443,6 +1460,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
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);
}
@ -1470,8 +1493,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_SetMobjState(mo2, mo2->info->painstate);
}
}
S_StartSound(toucher, special->info->painsound);
return;
case MT_FAKEMOBILE:
@ -1583,6 +1604,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Buenos Dias Mandy
P_SetPlayerMobjState(toucher, S_PLAY_STUN);
player->pflags &= ~PF_APPLYAUTOBRAKE;
P_ResetPlayer(player);
player->drawangle = special->angle + ANGLE_180;
P_InstaThrust(toucher, special->angle, FixedMul(3*special->info->speed, special->scale/2));
toucher->z += P_MobjFlip(toucher);
@ -1688,13 +1710,15 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
if (mariomode)
return;
if (special->state-states != S_EXTRALARGEBUBBLE)
return; // Don't grab the bubble during its spawn animation
else if (toucher->eflags & MFE_VERTICALFLIP)
{
if (special->z+special->height < toucher->z + toucher->height / 3
|| special->z+special->height > toucher->z + (toucher->height*2/3))
if (special->z+special->height < toucher->z
|| special->z+special->height > toucher->z + (toucher->height*2/3))
return; // Only go in the mouth
}
else if (special->z < toucher->z + toucher->height / 3
else if (special->z < toucher->z
|| special->z > toucher->z + (toucher->height*2/3))
return; // Only go in the mouth
@ -1750,7 +1774,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
case MT_MINECARTSPAWNER:
if (!special->fuse || player->powers[pw_carry] != CR_MINECART)
if (!player->bot && (special->fuse < TICRATE || player->powers[pw_carry] != CR_MINECART))
{
mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
P_SetTarget(&mcart->target, toucher);
@ -1760,7 +1784,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_ResetPlayer(player);
player->pflags |= PF_JUMPDOWN;
player->powers[pw_carry] = CR_MINECART;
toucher->player->pflags &= ~PF_APPLYAUTOBRAKE;
player->pflags &= ~PF_APPLYAUTOBRAKE;
P_SetTarget(&toucher->tracer, mcart);
toucher->momx = toucher->momy = toucher->momz = 0;
@ -2442,6 +2466,28 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
P_SetThingPosition(target);
if (target->player->powers[pw_super])
{
target->player->powers[pw_super] = 0;
if (P_IsLocalPlayer(target->player))
{
music_stack_noposition = true; // HACK: Do not reposition next music
music_stack_fadeout = MUSICRATE/2; // HACK: Fade out current music
}
P_RestoreMusic(target->player);
if (gametype != GT_COOP)
{
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[target->player-players]));
}
}
target->color = target->player->skincolor;
target->colorized = false;
G_GhostAddColor(GHC_NORMAL);
if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0))
;
else if (!target->player->bot && !target->player->spectator && !G_IsSpecialStage(gamemap) && (target->player->lives != INFLIVES)
@ -2469,8 +2515,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
else if (P_IsLocalPlayer(target->player))
gameovermus = true;
if (gameovermus)
P_PlayJingle(target->player, JT_GOVER); // Yousa dead now, Okieday? Tails 03-14-2000
if (gameovermus) // Yousa dead now, Okieday? Tails 03-14-2000
S_ChangeMusicEx("_gover", 0, 0, 0, (2*MUSICRATE) - (MUSICRATE/25), 0); // 1.96 seconds
//P_PlayJingle(target->player, JT_GOVER); // can't be used because incompatible with track fadeout
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers)
{
@ -2586,6 +2633,14 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
}
break;
case MT_BANPYURA:
if (target->tracer)
{
S_StopSound(target->tracer);
P_KillMobj(target->tracer, inflictor, source, damagetype);
}
break;
case MT_EGGSHIELD:
P_SetObjectMomZ(target, 4*target->scale, false);
P_InstaThrust(target, target->angle, 3*target->scale);
@ -2594,6 +2649,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
case MT_EGGMOBILE3:
{
mobj_t *mo2;
thinker_t *th;
UINT32 i = 0; // to check how many clones we've removed
@ -2614,6 +2670,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mo->scalespeed = (mo->scale - mo->destscale)/(2*TICRATE);
mo->momz = mo->info->speed;
mo->angle = FixedAngle((P_RandomKey(36)*10)<<FRACBITS);
mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_SetMobjState(mo2, S_BOSSSEBH2);
if (++i == 2) // we've already removed 2 of these, let's stop now
break;
else
@ -3386,7 +3447,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return false;
// Spectator handling
if (netgame)
if (multiplayer)
{
if (damagetype != DMG_SPECTATOR && target->player && target->player->spectator)
return false;
@ -3418,7 +3479,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return false;
// Make sure that boxes cannot be popped by enemies, red rings, etc.
if (target->flags & MF_MONITOR && ((!source || !source->player || source->player->bot) || (inflictor && !inflictor->player)))
if (target->flags & MF_MONITOR && ((!source || !source->player || source->player->bot)
|| (inflictor && inflictor->type >= MT_REDRING && inflictor->type <= MT_GRENADERING)))
return false;
}
@ -3500,7 +3562,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return true;
}
if (G_IsSpecialStage(gamemap))
if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK))
{
P_SpecialStageDamage(player, inflictor, source);
return true;
@ -3524,10 +3586,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// Instant-Death
if (damagetype & DMG_DEATHMASK)
{
P_KillPlayer(player, source, damage);
player->rings = player->spheres = 0;
}
else if (metalrecording)
{
if (!inflictor)
@ -3562,7 +3621,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype))
return true;
#endif
else if (player->powers[pw_shield] || player->bot) //If One-Hit Shield
else if (player->powers[pw_shield] || (player->bot && !ultimatemode)) //If One-Hit Shield
{
P_ShieldDamage(player, inflictor, source, damage, damagetype);
damage = 0;

View File

@ -115,10 +115,10 @@ typedef struct camera_s
extern camera_t camera, camera2;
extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height;
extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed;
extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_orbit, cv_cam_adjust;
extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height;
extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed;
extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_orbit, cv_cam2_adjust;
extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate;
extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate;
@ -303,7 +303,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
boolean P_CheckDeathPitCollide(mobj_t *mo);
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover);
boolean P_CheckSolidLava(ffloor_t *rover);
void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype);
mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type);
@ -509,7 +509,7 @@ extern INT32 ceilmovesound;
void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
INT16 starpostx, INT16 starposty, INT16 starpostz,
INT32 starpostnum, tic_t starposttime, angle_t starpostangle,
INT32 flags2);
fixed_t starpostscale, angle_t drawangle, INT32 flags2);
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove);
boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state);
boolean P_CheckMissileSpawn(mobj_t *th);

View File

@ -124,6 +124,7 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
// Positive spring modes are minor variants of vanilla spring behaviour.
// 1 = launch players in jump
// 2 = don't modify player at all, just add momentum
// 3 = speed-booster mode (force onto ground, MF_AMBUSH causes auto-spin)
// Negative spring modes are mildly-related gimmicks with customisation.
// -1 = pinball bumper
// Any other spring mode defaults to standard vanilla spring behaviour,
@ -151,7 +152,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
if (object->player)
{
if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
if (spring->info->painchance == 3)
;
else if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
strong = 1;
else if (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2)
strong = 2;
@ -208,7 +211,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
angle_t nightsangle = 0;
if (object->player->bumpertime >= TICRATE/4)
if (object->player->bumpertime > (TICRATE/2)-5)
return false;
if ((object->player->pflags & PF_TRANSFERTOCLOSEST) && object->player->axis1 && object->player->axis2)
@ -285,6 +288,29 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
if (spring->info->painchance != 2)
{
if (object->player)
{
object->player->pflags &= ~PF_APPLYAUTOBRAKE;
#ifndef SPRINGSPIN
object->player->powers[pw_justsprung] = 5;
if (horizspeed)
object->player->powers[pw_noautobrake] = ((horizspeed*TICRATE)>>(FRACBITS+3))/9; // TICRATE at 72*FRACUNIT
else if (P_MobjFlip(object) == P_MobjFlip(spring))
object->player->powers[pw_justsprung] |= (1<<15);
#else
object->player->powers[pw_justsprung] = 15;
if (horizspeed)
object->player->powers[pw_noautobrake] = ((horizspeed*TICRATE)>>(FRACBITS+3))/9; // TICRATE at 72*FRACUNIT
else
{
if (abs(object->player->rmomx) > object->scale || abs(object->player->rmomy) > object->scale)
object->player->drawangle = R_PointToAngle2(0, 0, object->player->rmomx, object->player->rmomy);
if (P_MobjFlip(object) == P_MobjFlip(spring))
object->player->powers[pw_justsprung] |= (1<<15);
}
#endif
}
if ((horizspeed && vertispeed) || (object->player && object->player->homing)) // Mimic SA
{
object->momx = object->momy = 0;
@ -318,6 +344,14 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
// Set position!
P_TryMove(object, spring->x + offx, spring->y + offy, true);
if ((spring->info->painchance == 3))
{
object->z = spring->z;
if (spring->eflags & MFE_VERTICALFLIP)
object->z -= object->height;
object->momz = 0;
}
}
}
@ -341,26 +375,36 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
if (horizspeed)
{
object->player->drawangle = spring->angle;
if (vertispeed || (object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0))
{
object->angle = spring->angle;
object->angle = object->player->drawangle = spring->angle;
if (!demoplayback || P_AnalogMove(object->player))
{
if (object->player == &players[consoleplayer])
localangle = spring->angle;
else if (object->player == &players[secondarydisplayplayer])
localangle2 = spring->angle;
}
if (!demoplayback || P_AnalogMove(object->player))
{
if (object->player == &players[consoleplayer])
localangle = spring->angle;
else if (object->player == &players[secondarydisplayplayer])
localangle2 = spring->angle;
}
}
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these.
secondjump = object->player->secondjump;
washoming = object->player->homing;
if (object->player->pflags & PF_GLIDING)
P_SetPlayerMobjState(object, S_PLAY_FALL);
if ((spring->info->painchance == 3))
{
if (!(pflags = (object->player->pflags & PF_SPINNING)) &&
(((object->player->charability2 == CA2_SPINDASH) && (object->player->cmd.buttons & BT_USE))
|| (spring->flags2 & MF2_AMBUSH)))
{
pflags = PF_SPINNING;
P_SetPlayerMobjState(object, S_PLAY_ROLL);
S_StartSound(object, sfx_spin);
}
else
P_SetPlayerMobjState(object, S_PLAY_ROLL);
}
else
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these.
secondjump = object->player->secondjump;
washoming = object->player->homing;
P_ResetPlayer(object->player);
if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities.
@ -368,7 +412,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
object->player->pflags |= P_GetJumpFlags(object->player);
P_SetPlayerMobjState(object, S_PLAY_JUMP);
}
else if ((spring->info->painchance == 2) || (pflags & PF_BOUNCING)) // Adding momentum only.
else if ((spring->info->painchance == 2) || ((spring->info->painchance != 3) && (pflags & PF_BOUNCING))) // Adding momentum only.
{
object->player->pflags |= (pflags &~ PF_STARTJUMP);
object->player->secondjump = secondjump;
@ -382,6 +426,10 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
object->player->pflags |= pflags;
object->player->secondjump = secondjump;
}
else if (object->player->dashmode >= 3*TICRATE)
P_SetPlayerMobjState(object, S_PLAY_DASH);
else if (P_IsObjectOnGround(object) && horizspeed >= FixedMul(object->player->runspeed, object->scale))
P_SetPlayerMobjState(object, S_PLAY_RUN);
else
P_SetPlayerMobjState(object, S_PLAY_WALK);
}
@ -490,6 +538,42 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
}
}
static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera)
{
if (player->powers[pw_carry] && players->powers[pw_carry] != CR_ROLLOUT)
return;
if (ptera->extravalue1 != 1)
return; // Not swooping
if (ptera->target != player->mo)
return; // Not swooping for you!
if (player->spectator)
return;
if ((player->mo->eflags & MFE_VERTICALFLIP) != (ptera->eflags & MFE_VERTICALFLIP))
return; // Both should be in same gravity
if (ptera->eflags & MFE_VERTICALFLIP)
{
if (ptera->ceilingz - (ptera->z + ptera->height) < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return;
}
else if (ptera->z - ptera->floorz < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return; // No room to pick up this guy!
P_ResetPlayer(player);
P_SetTarget(&player->mo->tracer, ptera);
player->pflags &= ~PF_APPLYAUTOBRAKE;
player->powers[pw_carry] = CR_PTERABYTE;
S_StartSound(player->mo, sfx_s3k4a);
P_UnsetThingPosition(player->mo);
player->mo->x = ptera->x;
player->mo->y = ptera->y;
P_SetThingPosition(player->mo);
ptera->movefactor = 3*TICRATE;
ptera->watertop = ptera->waterbottom = ptera->cusval = 0;
}
static void P_DoTailsCarry(player_t *sonic, player_t *tails)
{
INT32 p;
@ -604,6 +688,34 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole)
P_SetTarget(&pole->tracer, NULL);
}
static void P_PlayerBarrelCollide(mobj_t *toucher, mobj_t *barrel)
{
if (toucher->momz < 0)
{
if (toucher->z + toucher->momz > barrel->z + barrel->height)
return;
}
else
{
if (toucher->z > barrel->z + barrel->height)
return;
}
if (toucher->momz > 0)
{
if (toucher->z + toucher->height + toucher->momz < barrel->z)
return;
}
else
{
if (toucher->z + toucher->height < barrel->z)
return;
}
if (P_PlayerCanDamage(toucher->player, barrel))
P_DamageMobj(barrel, toucher, toucher, 1, 0);
}
//
// PIT_CheckThing
//
@ -746,7 +858,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
}
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING)))
if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING)))
return true;
// Don't collide with your buddies while NiGHTS-flying.
@ -854,6 +966,15 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
#endif
if (tmthing->type == MT_LAVAFALL_LAVA && (thing->type == MT_RING || thing->type == MT_REDTEAMRING || thing->type == MT_BLUETEAMRING || thing->type == MT_FLINGRING))
{
//height check
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !(thing->health))
return true;
P_KillMobj(thing, tmthing, tmthing, DMG_FIRE);
}
if (tmthing->type == MT_MINECART)
{
//height check
@ -872,12 +993,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOOR && tmthing->player)
{
if (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer) && tmthing->tracer->health)
mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing;
if ((thing->flags & MF2_AMBUSH) || ref != tmthing)
{
fixed_t dx = tmthing->tracer->momx;
fixed_t dy = tmthing->tracer->momy;
fixed_t dm = min(FixedHypot(dx, dy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, dx, dy) - thing->angle;
fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle;
fixed_t s = FINESINE((ang >> ANGLETOFINESHIFT) & FINEMASK);
S_StartSound(tmthing, thing->info->activesound);
thing->extravalue2 += 2*FixedMul(s, dm)/3;
@ -885,41 +1005,73 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
}
if (thing->type == MT_TNTBARREL && tmthing->player)
if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
{
if (tmthing->momz < 0)
{
if (tmthing->z + tmthing->momz > thing->z + thing->height)
return true;
}
else
{
if (tmthing->z > thing->z + thing->height)
return true;
}
if (tmthing->momz > 0)
{
if (tmthing->z + tmthing->height + tmthing->momz < thing->z)
return true;
}
else
{
if (tmthing->z + tmthing->height < thing->z)
return true;
}
if ((tmthing->player->pflags & (PF_SPINNING | PF_GLIDING))
|| ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height / 2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|| (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)))
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
if ((thing->flags & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
return true;
}
if (thing->type == MT_ROLLOUTROCK && tmthing->player && tmthing->health)
{
if (tmthing->player->powers[pw_carry] == CR_ROLLOUT)
{
return true;
}
if ((thing->flags & MF_PUSHABLE) // not carrying a player
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
&& (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius))
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0)
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
{
thing->flags &= ~MF_PUSHABLE; // prevent riding player from applying pushable movement logic
thing->flags2 &= ~MF2_DONTDRAW; // don't leave the rock invisible if it was flashing prior to boarding
P_SetTarget(&thing->tracer, tmthing);
P_ResetPlayer(tmthing->player);
P_SetPlayerMobjState(tmthing, S_PLAY_WALK);
tmthing->player->powers[pw_carry] = CR_ROLLOUT;
P_SetTarget(&tmthing->tracer, thing);
P_SetObjectMomZ(thing, tmthing->momz, true);
return true;
}
}
else if (tmthing->type == MT_ROLLOUTROCK)
{
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !thing->health)
return true;
if (thing == tmthing->tracer) // don't collide with rider
return true;
if (thing->flags & MF_SPRING) // bounce on springs
{
P_DoSpring(thing, tmthing);
return true;
}
else if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) == (MF_MONITOR|MF_SHOOTABLE) && !(tmthing->flags & MF_PUSHABLE)) // pop monitors while carrying a player
{
P_KillMobj(thing, tmthing, tmthing->tracer, 0);
return true;
}
if (thing->type == tmthing->type // bounce against other rollout rocks
&& (tmthing->momx || tmthing->momy || thing->momx || thing->momy))
{
fixed_t tempmomx = thing->momx, tempmomy = thing->momy;
thing->momx = tmthing->momx;
thing->momy = tmthing->momy;
tmthing->momx = tempmomx;
tmthing->momy = tempmomy;
}
}
if (thing->type == MT_PTERABYTE && tmthing->player)
P_DoPterabyteCarry(tmthing->player, thing);
if (thing->type == MT_TNTBARREL && tmthing->player)
P_PlayerBarrelCollide(tmthing, thing);
if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE)
{
fixed_t dx = thing->x - tmthing->x;
@ -1019,7 +1171,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; // underneath
if (tmthing->flags & MF_SHOOTABLE && thing->health > 0)
{
UINT8 damagetype = (thing->info->mass & 0xFF);
UINT32 damagetype = (thing->info->mass & 0xFF);
if (!damagetype && thing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE;
if (P_DamageMobj(tmthing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8)))
@ -1036,7 +1188,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; // underneath
if (thing->flags & MF_SHOOTABLE && tmthing->health > 0)
{
UINT8 damagetype = (tmthing->info->mass & 0xFF);
UINT32 damagetype = (tmthing->info->mass & 0xFF);
if (!damagetype && tmthing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE;
if (P_DamageMobj(thing, tmthing, tmthing, 1, damagetype) && (damagetype = (tmthing->info->mass>>8)))
@ -1560,8 +1712,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
}
if ((!tmthing->player) && (thing->player))
; // no solid thing should ever be able to step up onto a player
if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM) && (thing->player))
; // springs and gas jets should never be able to step up onto a player
// z checking at last
// Treat noclip things as non-solid!
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
@ -1964,7 +2116,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
continue;
}
if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover)))
if (thing->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(thing->player, rover)))
;
else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))
;
@ -2629,8 +2781,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
#ifdef ESLOPE
// HACK TO FIX DSZ2: apply only if slopes are involved
else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
{
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
@ -2645,8 +2796,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
#ifdef ESLOPE
// HACK TO FIX DSZ2: apply only if slopes are involved
else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
{
thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;
@ -2881,11 +3031,8 @@ static boolean P_ThingHeightClip(mobj_t *thing)
thing->z = thing->ceilingz - thing->height;
}
if (thing->z != oldz)
{
if (thing->player)
P_PlayerHitFloor(thing->player, false);
}
if (P_MobjFlip(thing)*(thing->z - oldz) > 0 && thing->player)
P_PlayerHitFloor(thing->player, !onfloor);
// debug: be sure it falls to the floor
thing->eflags &= ~MFE_ONGROUND;
@ -3199,7 +3346,7 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
&& glidesector->sector->ceilingpic == skyflatnum)
return false;
if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < ceilingz)
if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < floorz)
|| (player->mo->z >= ceilingz))
floorclimb = true;
}
@ -3482,6 +3629,64 @@ stairstep:
goto retry;
}
static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
for (rover = sec->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_SWIMMABLE))
continue;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3)
continue;
if (rover->master->flags & ML_BLOCKMONSTERS)
continue;
topheight =
#ifdef ESLOPE
*rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) :
#endif
*rover->topheight;
if (mo->eflags & MFE_VERTICALFLIP)
{
if (topheight < mo->z - mo->height)
continue;
}
else
{
if (topheight < mo->z)
continue;
}
bottomheight =
#ifdef ESLOPE
*rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) :
#endif
*rover->bottomheight;
if (mo->eflags & MFE_VERTICALFLIP)
{
if (bottomheight > mo->z)
continue;
}
else
{
if (bottomheight > mo->z + mo->height)
continue;
}
P_DamageMobj(mo, NULL, NULL, 1, DMG_FIRE);
return;
}
}
//
// P_SlideMove
// The momx / momy move is bad, so try to slide
@ -3642,6 +3847,12 @@ retry:
P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy,
PT_ADDLINES, PTR_SlideTraverse);
if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff)
{
sector_t *sec = P_PointOnLineSide(mo->x, mo->y, bestslideline) ? bestslideline->frontsector : bestslideline->backsector;
P_CheckLavaWall(mo, sec);
}
// Some walls are bouncy even if you're not
if (bestslideline && bestslideline->flags & ML_BOUNCY)
{
@ -4136,7 +4347,7 @@ boolean P_CheckSector(sector_t *sector, boolean crunch)
{
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
if (!P_MobjTouchingPolyobj(po, mo))
if (!P_MobjInsidePolyobj(po, mo))
continue;
if (!PIT_ChangeSector(mo, false))
@ -4246,7 +4457,7 @@ boolean P_CheckSector(sector_t *sector, boolean crunch)
{
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
if (!P_MobjTouchingPolyobj(po, mo))
if (!P_MobjInsidePolyobj(po, mo))
continue;
PIT_ChangeSector(mo, true);

View File

@ -419,10 +419,6 @@ void P_CameraLineOpening(line_t *linedef)
if (front->ffloors || back->ffloors)
{
ffloor_t *rover;
fixed_t highestceiling = highceiling;
fixed_t lowestceiling = opentop;
fixed_t highestfloor = openbottom;
fixed_t lowestfloor = lowfloor;
fixed_t delta1, delta2;
// Check for frontsector's fake floors
@ -438,15 +434,15 @@ void P_CameraLineOpening(line_t *linedef)
delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
if (bottomheight < lowestceiling && delta1 >= delta2)
lowestceiling = bottomheight;
else if (bottomheight < highestceiling && delta1 >= delta2)
highestceiling = bottomheight;
if (bottomheight < opentop && delta1 >= delta2)
opentop = bottomheight;
else if (bottomheight < highceiling && delta1 >= delta2)
highceiling = bottomheight;
if (topheight > highestfloor && delta1 < delta2)
highestfloor = topheight;
else if (topheight > lowestfloor && delta1 < delta2)
lowestfloor = topheight;
if (topheight > openbottom && delta1 < delta2)
openbottom = topheight;
else if (topheight > lowfloor && delta1 < delta2)
lowfloor = topheight;
}
// Check for backsectors fake floors
@ -462,28 +458,16 @@ void P_CameraLineOpening(line_t *linedef)
delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
if (bottomheight < lowestceiling && delta1 >= delta2)
lowestceiling = bottomheight;
else if (bottomheight < highestceiling && delta1 >= delta2)
highestceiling = bottomheight;
if (bottomheight < opentop && delta1 >= delta2)
opentop = bottomheight;
else if (bottomheight < highceiling && delta1 >= delta2)
highceiling = bottomheight;
if (topheight > highestfloor && delta1 < delta2)
highestfloor = topheight;
else if (topheight > lowestfloor && delta1 < delta2)
lowestfloor = topheight;
if (topheight > openbottom && delta1 < delta2)
openbottom = topheight;
else if (topheight > lowfloor && delta1 < delta2)
lowfloor = topheight;
}
if (highestceiling < highceiling)
highceiling = highestceiling;
if (highestfloor > openbottom)
openbottom = highestfloor;
if (lowestceiling < opentop)
opentop = lowestceiling;
if (lowestfloor > lowfloor)
lowfloor = lowestfloor;
}
openrange = opentop - openbottom;
return;
@ -501,25 +485,27 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
return;
}
// Treat polyobjects kind of like 3D Floors
#ifdef POLYOBJECTS
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT))
{
front = linedef->frontsector;
back = linedef->frontsector;
}
else
#endif
{
front = linedef->frontsector;
back = linedef->backsector;
}
front = linedef->frontsector;
back = linedef->backsector;
I_Assert(front != NULL);
I_Assert(back != NULL);
openfloorrover = openceilingrover = NULL;
#ifdef POLYOBJECTS
if (linedef->polyobj)
{
// set these defaults so that polyobjects don't interfere with collision above or below them
opentop = INT32_MAX;
openbottom = INT32_MIN;
highceiling = INT32_MIN;
lowfloor = INT32_MAX;
#ifdef ESLOPE
opentopslope = openbottomslope = NULL;
#endif
}
else
#endif
{ // Set open and high/low values here
fixed_t frontheight, backheight;
@ -625,27 +611,49 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
}
}
}
// Check for fake floors in the sector.
if (front->ffloors || back->ffloors
#ifdef POLYOBJECTS
|| linedef->polyobj
if (linedef->polyobj)
{
// Treat polyobj's backsector like a 3D Floor
if (linedef->polyobj->flags & POF_TESTHEIGHT)
{
const sector_t *polysec = linedef->backsector;
fixed_t polytop, polybottom;
fixed_t delta1, delta2;
if (linedef->polyobj->flags & POF_CLIPPLANES)
{
polytop = polysec->ceilingheight;
polybottom = polysec->floorheight;
}
else
{
polytop = INT32_MAX;
polybottom = INT32_MIN;
}
delta1 = abs(mobj->z - (polybottom + ((polytop - polybottom)/2)));
delta2 = abs(thingtop - (polybottom + ((polytop - polybottom)/2)));
if (polybottom < opentop && delta1 >= delta2)
opentop = polybottom;
else if (polybottom < highceiling && delta1 >= delta2)
highceiling = polybottom;
if (polytop > openbottom && delta1 < delta2)
openbottom = polytop;
else if (polytop > lowfloor && delta1 < delta2)
lowfloor = polytop;
}
// otherwise don't do anything special, pretend there's nothing else there
}
else
#endif
)
// Check for fake floors in the sector.
if (front->ffloors || back->ffloors)
{
ffloor_t *rover;
fixed_t highestceiling = highceiling;
fixed_t lowestceiling = opentop;
fixed_t highestfloor = openbottom;
fixed_t lowestfloor = lowfloor;
fixed_t delta1, delta2;
#ifdef ESLOPE
pslope_t *ceilingslope = opentopslope;
pslope_t *floorslope = openbottomslope;
#endif
ffloor_t *floorrover = NULL;
ffloor_t *ceilingrover = NULL;
// Check for frontsector's fake floors
for (rover = front->ffloors; rover; rover = rover->next)
@ -654,7 +662,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (!(rover->flags & FF_EXISTS))
continue;
if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover)))
if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover)))
;
else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
@ -666,30 +674,30 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
if (delta1 >= delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_PLATFORM) // thing is below FOF
{
if (bottomheight < lowestceiling) {
lowestceiling = bottomheight;
if (bottomheight < opentop) {
opentop = bottomheight;
#ifdef ESLOPE
ceilingslope = *rover->b_slope;
opentopslope = *rover->b_slope;
#endif
ceilingrover = rover;
openceilingrover = rover;
}
else if (bottomheight < highestceiling)
highestceiling = bottomheight;
else if (bottomheight < highceiling)
highceiling = bottomheight;
}
if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF
if (delta1 < delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
{
if (topheight > highestfloor) {
highestfloor = topheight;
if (topheight > openbottom) {
openbottom = topheight;
#ifdef ESLOPE
floorslope = *rover->t_slope;
openbottomslope = *rover->t_slope;
#endif
floorrover = rover;
openfloorrover = rover;
}
else if (topheight > lowestfloor)
lowestfloor = topheight;
else if (topheight > lowfloor)
lowfloor = topheight;
}
}
@ -700,7 +708,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (!(rover->flags & FF_EXISTS))
continue;
if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover)))
if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover)))
;
else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
@ -712,83 +720,32 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
if (delta1 >= delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_PLATFORM) // thing is below FOF
{
if (bottomheight < lowestceiling) {
lowestceiling = bottomheight;
if (bottomheight < opentop) {
opentop = bottomheight;
#ifdef ESLOPE
ceilingslope = *rover->b_slope;
opentopslope = *rover->b_slope;
#endif
ceilingrover = rover;
openceilingrover = rover;
}
else if (bottomheight < highestceiling)
highestceiling = bottomheight;
else if (bottomheight < highceiling)
highceiling = bottomheight;
}
if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF
if (delta1 < delta2 && (rover->flags & FF_INTANGABLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
{
if (topheight > highestfloor) {
highestfloor = topheight;
if (topheight > openbottom) {
openbottom = topheight;
#ifdef ESLOPE
floorslope = *rover->t_slope;
openbottomslope = *rover->t_slope;
#endif
floorrover = rover;
openfloorrover = rover;
}
else if (topheight > lowestfloor)
lowestfloor = topheight;
else if (topheight > lowfloor)
lowfloor = topheight;
}
}
#ifdef POLYOBJECTS
// Treat polyobj's backsector like a 3D Floor
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT))
{
const sector_t *polysec = linedef->backsector;
delta1 = abs(mobj->z - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
delta2 = abs(thingtop - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
if (polysec->floorheight < lowestceiling && delta1 >= delta2) {
lowestceiling = polysec->floorheight;
#ifdef ESLOPE
ceilingslope = NULL;
#endif
ceilingrover = NULL;
}
else if (polysec->floorheight < highestceiling && delta1 >= delta2)
highestceiling = polysec->floorheight;
if (polysec->ceilingheight > highestfloor && delta1 < delta2) {
highestfloor = polysec->ceilingheight;
#ifdef ESLOPE
floorslope = NULL;
#endif
floorrover = NULL;
}
else if (polysec->ceilingheight > lowestfloor && delta1 < delta2)
lowestfloor = polysec->ceilingheight;
}
#endif
if (highestceiling < highceiling)
highceiling = highestceiling;
if (highestfloor > openbottom) {
openbottom = highestfloor;
#ifdef ESLOPE
openbottomslope = floorslope;
#endif
openfloorrover = floorrover;
}
if (lowestceiling < opentop) {
opentop = lowestceiling;
#ifdef ESLOPE
opentopslope = ceilingslope;
#endif
openceilingrover = ceilingrover;
}
if (lowestfloor > lowfloor)
lowfloor = lowestfloor;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -233,15 +233,17 @@ typedef enum
MFE_VERTICALFLIP = 1<<5,
// Goo water
MFE_GOOWATER = 1<<6,
// The mobj is touching a lava block
MFE_TOUCHLAVA = 1<<7,
// Mobj was already pushed this tic
MFE_PUSHED = 1<<7,
MFE_PUSHED = 1<<8,
// Mobj was already sprung this tic
MFE_SPRUNG = 1<<8,
MFE_SPRUNG = 1<<9,
// Platform movement
MFE_APPLYPMOMZ = 1<<9,
MFE_APPLYPMOMZ = 1<<10,
// Compute and trigger on mobj angle relative to tracer
// See Linedef Exec 457 (Track mobj angle to point)
MFE_TRACERANGLE = 1<<10,
MFE_TRACERANGLE = 1<<11,
// free: to and including 1<<15
} mobjeflag_t;

View File

@ -125,6 +125,10 @@ static void P_NetArchivePlayers(void)
WRITEINT32(save_p, players[i].currentweapon);
WRITEINT32(save_p, players[i].ringweapons);
WRITEUINT16(save_p, players[i].ammoremoval);
WRITEUINT32(save_p, players[i].ammoremovaltimer);
WRITEINT32(save_p, players[i].ammoremovaltimer);
for (j = 0; j < NUMPOWERS; j++)
WRITEUINT16(save_p, players[i].powers[j]);
@ -185,6 +189,7 @@ static void P_NetArchivePlayers(void)
WRITEINT16(save_p, players[i].starpostz);
WRITEINT32(save_p, players[i].starpostnum);
WRITEANGLE(save_p, players[i].starpostangle);
WRITEFIXED(save_p, players[i].starpostscale);
WRITEANGLE(save_p, players[i].angle_pos);
WRITEANGLE(save_p, players[i].old_angle_pos);
@ -329,6 +334,10 @@ static void P_NetUnArchivePlayers(void)
players[i].currentweapon = READINT32(save_p);
players[i].ringweapons = READINT32(save_p);
players[i].ammoremoval = READUINT16(save_p);
players[i].ammoremovaltimer = READUINT32(save_p);
players[i].ammoremovalweapon = READINT32(save_p);
for (j = 0; j < NUMPOWERS; j++)
players[i].powers[j] = READUINT16(save_p);
@ -389,6 +398,7 @@ static void P_NetUnArchivePlayers(void)
players[i].starpostz = READINT16(save_p);
players[i].starpostnum = READINT32(save_p);
players[i].starpostangle = READANGLE(save_p);
players[i].starpostscale = READFIXED(save_p);
players[i].angle_pos = READANGLE(save_p);
players[i].old_angle_pos = READANGLE(save_p);
@ -3608,7 +3618,7 @@ static void P_NetUnArchiveThinkers(void)
{
executor_t *delay = NULL;
UINT32 mobjnum;
for (currentthinker = thlist[i].next; currentthinker != &thlist[i];
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN];
currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay)
@ -4109,12 +4119,54 @@ static inline boolean P_NetUnArchiveMisc(void)
return true;
}
static inline void P_ArchiveLuabanksAndConsistency(void)
{
UINT8 i, banksinuse = NUM_LUABANKS;
while (banksinuse && !luabanks[banksinuse-1])
banksinuse--; // get the last used bank
if (banksinuse)
{
WRITEUINT8(save_p, 0xb7); // luabanks marker
WRITEUINT8(save_p, banksinuse);
for (i = 0; i < banksinuse; i++)
WRITEINT32(save_p, luabanks[i]);
}
WRITEUINT8(save_p, 0x1d); // consistency marker
}
static inline boolean P_UnArchiveLuabanksAndConsistency(void)
{
switch (READUINT8(save_p))
{
case 0xb7:
{
UINT8 i, banksinuse = READUINT8(save_p);
if (banksinuse > NUM_LUABANKS)
return false;
for (i = 0; i < banksinuse; i++)
luabanks[i] = READINT32(save_p);
if (READUINT8(save_p) != 0x1d)
return false;
}
case 0x1d:
break;
default:
return false;
}
return true;
}
void P_SaveGame(void)
{
P_ArchiveMisc();
P_ArchivePlayer();
WRITEUINT8(save_p, 0x1d); // consistency marker
// yes, even in non HAVE_BLUA
P_ArchiveLuabanksAndConsistency();
}
void P_SaveNetGame(void)
@ -4153,7 +4205,7 @@ void P_SaveNetGame(void)
LUA_Archive();
#endif
WRITEUINT8(save_p, 0x1d); // consistency marker
P_ArchiveLuabanksAndConsistency();
}
boolean P_LoadGame(INT16 mapoverride)
@ -4165,8 +4217,7 @@ boolean P_LoadGame(INT16 mapoverride)
P_UnArchiveSPGame(mapoverride);
P_UnArchivePlayer();
// Savegame end marker
if (READUINT8(save_p) != 0x1d)
if (!P_UnArchiveLuabanksAndConsistency())
return false;
// Only do this after confirming savegame is ok
@ -4207,5 +4258,5 @@ boolean P_LoadNetGame(void)
// precipitation when loading a netgame save. Instead, precip has to be spawned here.
// This is done in P_NetUnArchiveSpecials now.
return READUINT8(save_p) == 0x1d;
return P_UnArchiveLuabanksAndConsistency();
}

View File

@ -221,6 +221,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->muspostbosstrack = 0;
mapheaderinfo[num]->muspostbosspos = 0;
mapheaderinfo[num]->muspostbossfadein = 0;
mapheaderinfo[num]->musforcereset = -1;
mapheaderinfo[num]->forcecharacter[0] = '\0';
mapheaderinfo[num]->weather = 0;
mapheaderinfo[num]->skynum = 1;
@ -573,6 +574,11 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
// store the flat lump number
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->texturenum = R_CheckTextureNumForName(flatname);
levelflat->lasttexturenum = levelflat->texturenum;
levelflat->baselumpnum = LUMPERROR;
levelflat->basetexturenum = -1;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
@ -617,6 +623,11 @@ INT32 P_AddLevelFlatRuntime(const char *flatname)
// store the flat lump number
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->texturenum = R_CheckTextureNumForName(flatname);
levelflat->lasttexturenum = levelflat->texturenum;
levelflat->baselumpnum = LUMPERROR;
levelflat->basetexturenum = -1;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
@ -1480,6 +1491,7 @@ static void P_LoadRawSideDefs2(void *data)
case 425: // Calls P_SetMobjState on calling mobj
case 434: // Custom Power
case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors
case 461: // Spawns an object on the map based on texture offsets
{
char process[8*3+1];
memset(process,0,8*3+1);
@ -2234,6 +2246,8 @@ static void P_LevelInitStuff(void)
for (i = 0; i < MAXPLAYERS; i++)
{
G_PlayerReborn(i, true);
if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0))
{
// In Co-Op, replenish a user's lives if they are depleted.
@ -2241,41 +2255,18 @@ static void P_LevelInitStuff(void)
}
// obliteration station...
players[i].rings = players[i].spheres =\
players[i].xtralife = players[i].deadtimer =\
players[i].numboxes = players[i].totalring =\
players[i].laps = players[i].aiming =\
players[i].losstime = players[i].timeshit =\
players[i].marescore = players[i].lastmarescore =\
players[i].maxlink = players[i].startedtime =\
players[i].finishedtime = players[i].finishedspheres =\
players[i].finishedrings = players[i].lastmare =\
players[i].lastmarelap = players[i].lastmarebonuslap =\
players[i].totalmarelap = players[i].totalmarebonuslap =\
players[i].marebegunat = players[i].textvar =\
players[i].texttimer = players[i].linkcount =\
players[i].linktimer = players[i].flyangle =\
players[i].anotherflyangle = players[i].nightstime =\
players[i].oldscale = players[i].mare = players[i].marelap =\
players[i].marebonuslap = players[i].lapbegunat =\
players[i].lapstartedtime = players[i].totalmarescore =\
players[i].realtime = players[i].exiting = 0;
players[i].numboxes = players[i].totalring =\
players[i].laps = players[i].marescore = players[i].lastmarescore =\
players[i].mare = players[i].exiting = 0;
// i guess this could be part of the above but i feel mildly uncomfortable implicitly casting
players[i].gotcontinue = false;
// aha, the first evidence this shouldn't be a memset!
players[i].drillmeter = 40*20;
P_ResetPlayer(&players[i]);
// hit these too
players[i].pflags &= ~(PF_GAMETYPEOVER|PF_TRANSFERTOCLOSEST);
// unset ALL the pointers. P_SetTarget isn't needed here because if this
// function is being called we're just going to clobber the data anyways
players[i].mo = players[i].followmobj = players[i].awayviewmobj =\
players[i].capsule = players[i].axis1 = players[i].axis2 = players[i].drone = NULL;
players[i].pflags &= ~(PF_GAMETYPEOVER);
}
if (botingame)
CV_SetValue(&cv_analog2, true);
}
//
@ -2615,7 +2606,6 @@ boolean P_SetupLevel(boolean skipprecip)
boolean loadedbm = false;
sector_t *ss;
boolean chase;
levelloading = true;
// This is needed. Don't touch.
@ -2692,7 +2682,7 @@ boolean P_SetupLevel(boolean skipprecip)
S_StartSound(NULL, sfx_s3kaf);
// Fade music! Time it to S3KAF: 0.25 seconds is snappy.
if (cv_resetmusic.value ||
if (RESETMUSIC ||
strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7))
S_FadeOutStopMusic(MUSICRATE/4); //FixedMul(FixedDiv(F_GetWipeLength(wipedefs[wipe_speclevel_towhite])*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)
@ -2725,7 +2715,7 @@ boolean P_SetupLevel(boolean skipprecip)
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
if (!titlemapinaction && (cv_resetmusic.value ||
if (!titlemapinaction && (RESETMUSIC ||
strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)))
S_FadeMusic(0, FixedMul(
@ -3056,8 +3046,11 @@ boolean P_SetupLevel(boolean skipprecip)
CONS_Printf(M_GetText("No player currently available to become IT. Awaiting available players.\n"));
}
else if (gametype == GT_RACE && server && cv_usemapnumlaps.value)
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
else if (gametype == GT_RACE && server)
CV_StealthSetValue(&cv_numlaps,
(cv_basenumlaps.value)
? cv_basenumlaps.value
: mapheaderinfo[gamemap - 1]->numlaps);
// ===========
// landing point for netgames.

Some files were not shown because too many files have changed in this diff Show More