mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-17 23:21:22 +00:00
Merge branch 'master' into cobalt-ai
This commit is contained in:
commit
00361d30d8
105 changed files with 12972 additions and 1521 deletions
|
@ -13,11 +13,10 @@ set(SRB2_ASSET_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/installer"
|
|||
CACHE STRING "Path to directory that contains all asset files for the installer.")
|
||||
|
||||
set(SRB2_ASSET_HASHED
|
||||
"srb2.srb;\
|
||||
"srb2.pk3;\
|
||||
player.dta;\
|
||||
rings.dta;\
|
||||
zones.dta;\
|
||||
patch.dta"
|
||||
zones.pk3;\
|
||||
patch.pk3"
|
||||
CACHE STRING "Asset filenames to apply MD5 checks. No spaces between entries!"
|
||||
)
|
||||
|
||||
|
|
6482
extras/conf/SRB2-22.cfg
Normal file
6482
extras/conf/SRB2-22.cfg
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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`
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -86,10 +86,7 @@
|
|||
D_DIR?=../bin/Resources
|
||||
D_FILES=$(D_DIR)/srb2.pk3 \
|
||||
$(D_DIR)/player.dta \
|
||||
$(D_DIR)/rings.wpn \
|
||||
$(D_DIR)/drill.dta \
|
||||
$(D_DIR)/soar.dta \
|
||||
$(D_DIR)/zones.dta \
|
||||
$(D_DIR)/zones.pk3 \
|
||||
$(D_DIR)/music.dta \
|
||||
|
||||
PKG_CONFIG?=pkg-config
|
||||
|
|
14
src/b_bot.c
14
src/b_bot.c
|
@ -375,6 +375,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
|
||||
|
@ -460,7 +463,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.
|
||||
|
@ -494,11 +502,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;
|
||||
}
|
||||
|
|
252
src/command.c
252
src/command.c
|
@ -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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText(" Current value: %d\n"), cvar->value);
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("No help for this command/variable\n"));
|
||||
CONS_Printf(" Current value: %d\n", cvar->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
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%s", M_GetText("Commands\n"));
|
||||
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""\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))
|
||||
{
|
||||
v = var->PossibleValue[0].value;
|
||||
valstr = var->PossibleValue[0].strvalue;
|
||||
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[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;
|
||||
|
||||
newvalue = var->PossibleValue[MINVAL].value + (newvalue - var->PossibleValue[MINVAL].value)
|
||||
% (var->PossibleValue[max].value - var->PossibleValue[MINVAL].value + 1);
|
||||
|
||||
CV_SetValue(var, newvalue);
|
||||
#undef MINVAL
|
||||
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;
|
||||
}
|
||||
|
||||
if (increment)
|
||||
{
|
||||
increment = (increment > 0) ? 1 : -1;
|
||||
if (currentindice == -1 && max != MAXVAL+1)
|
||||
newindice = ((increment > 0) ? MAXVAL : max) + increment;
|
||||
else
|
||||
newindice = currentindice + increment;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#define ASSET_HASH_SRB2_PK3 "${SRB2_ASSET_srb2.pk3_HASH}"
|
||||
#define ASSET_HASH_PLAYER_DTA "${SRB2_ASSET_player.dta_HASH}"
|
||||
#define ASSET_HASH_ZONES_DTA "${SRB2_ASSET_zones.dta_HASH}"
|
||||
#define ASSET_HASH_ZONES_PK3 "${SRB2_ASSET_zones.pk3_HASH}"
|
||||
#ifdef USE_PATCH_DTA
|
||||
#define ASSET_HASH_PATCH_PK3 "${SRB2_ASSET_patch.pk3_HASH}"
|
||||
#endif
|
||||
|
@ -30,7 +30,7 @@
|
|||
* Last updated 2018 / ?? / ?? - v2.2 - patch.pk3
|
||||
*/
|
||||
#define ASSET_HASH_SRB2_PK3 "c1b9577687f8a795104aef4600720ea7"
|
||||
#define ASSET_HASH_ZONES_DTA "303838c6c534d9540288360fa49cca60"
|
||||
#define ASSET_HASH_ZONES_PK3 "303838c6c534d9540288360fa49cca60"
|
||||
#define ASSET_HASH_PLAYER_DTA "cfca0f1c73023cbbd8f844f45480f799"
|
||||
#ifdef USE_PATCH_DTA
|
||||
#define ASSET_HASH_PATCH_PK3 "dbbf8bc6121618ee3be2d5b14650429b"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -83,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
|
||||
|
@ -621,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);
|
||||
|
@ -767,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);
|
||||
|
@ -1253,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));
|
||||
}
|
||||
|
||||
|
@ -1312,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];
|
||||
|
||||
//No, don't do that, you fuckface.
|
||||
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:
|
||||
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
|
@ -2870,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;
|
||||
|
@ -2948,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)
|
||||
|
@ -2969,7 +2957,7 @@ consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, N
|
|||
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}};
|
||||
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 };
|
||||
|
||||
|
@ -3199,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);
|
||||
|
@ -3231,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')
|
||||
|
@ -3245,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?
|
||||
|
@ -3331,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)
|
||||
|
@ -3404,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)
|
||||
|
@ -3475,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
|
||||
|
@ -3494,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])
|
||||
|
@ -3534,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
|
||||
|
@ -3841,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
|
||||
|
@ -4175,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)
|
||||
|
@ -4203,7 +4210,6 @@ static void HandlePacketFromPlayer(SINT8 node)
|
|||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
case PT_SERVERCFG:
|
||||
break;
|
||||
case PT_FILEFRAGMENT:
|
||||
|
@ -4699,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();
|
||||
|
@ -4717,7 +4723,6 @@ void TryRunTics(tic_t realtics)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef NEWPING
|
||||
static inline void PingUpdate(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
@ -4775,7 +4780,6 @@ static inline void PingUpdate(void)
|
|||
|
||||
pingmeasurecount = 1; //Reset count
|
||||
}
|
||||
#endif
|
||||
|
||||
void NetUpdate(void)
|
||||
{
|
||||
|
@ -4800,7 +4804,6 @@ void NetUpdate(void)
|
|||
|
||||
gametime = nowtime;
|
||||
|
||||
#ifdef NEWPING
|
||||
if (server)
|
||||
{
|
||||
if (netgame && !(gametime % 255))
|
||||
|
@ -4811,7 +4814,6 @@ void NetUpdate(void)
|
|||
realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
|
||||
pingmeasurecount++;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (client)
|
||||
maketic = neededtic;
|
||||
|
@ -4852,10 +4854,15 @@ void NetUpdate(void)
|
|||
|
||||
for (i = 0; i < MAXNETNODES; ++i)
|
||||
if (resynch_inprogress[i])
|
||||
{
|
||||
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
|
||||
if (counts != -666)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "d_ticcmd.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "d_net.h"
|
||||
#include "tables.h"
|
||||
#include "d_player.h"
|
||||
|
||||
|
@ -73,9 +74,7 @@ typedef enum
|
|||
|
||||
PT_LOGIN, // Login attempt from the client.
|
||||
|
||||
#ifdef NEWPING
|
||||
PT_PING, // Packet sent to tell clients the other client's latency to server.
|
||||
#endif
|
||||
NUMPACKETTYPE
|
||||
} packettype_t;
|
||||
|
||||
|
@ -265,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;
|
||||
|
@ -322,6 +325,7 @@ typedef struct
|
|||
UINT8 subversion; // Contains build version
|
||||
UINT8 localplayers;
|
||||
UINT8 mode;
|
||||
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
|
||||
} ATTRPACK clientconfig_pak;
|
||||
|
||||
#define MAXSERVERNAME 32
|
||||
|
@ -421,9 +425,7 @@ typedef struct
|
|||
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;
|
||||
|
||||
|
@ -457,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
|
||||
|
||||
|
@ -484,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;
|
||||
|
||||
|
|
32
src/d_main.c
32
src/d_main.c
|
@ -359,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
|
||||
|
||||
|
@ -852,7 +852,7 @@ static void IdentifyVersion(void)
|
|||
// checking in D_SRB2Main
|
||||
|
||||
// Add the maps
|
||||
D_AddFile(va(pandf,srb2waddir,"zones.dta"));
|
||||
D_AddFile(va(pandf,srb2waddir,"zones.pk3"));
|
||||
|
||||
// Add the players
|
||||
D_AddFile(va(pandf,srb2waddir, "player.dta"));
|
||||
|
@ -1145,10 +1145,10 @@ void D_SRB2Main(void)
|
|||
|
||||
// Check MD5s of autoloaded files
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_SRB2_PK3); // srb2.pk3
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_ZONES_DTA); // zones.dta
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_ZONES_PK3); // zones.pk3
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_PLAYER_DTA); // player.dta
|
||||
#ifdef USE_PATCH_DTA
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_PATCH_DTA); // patch.dta
|
||||
W_VerifyFileMD5(mainwads++, ASSET_HASH_PATCH_DTA); // patch.pk3
|
||||
#endif
|
||||
// don't check music.dta because people like to modify it, and it doesn't matter if they do
|
||||
// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
|
||||
|
@ -1157,7 +1157,7 @@ void D_SRB2Main(void)
|
|||
#else
|
||||
|
||||
mainwads++; // srb2.pk3
|
||||
mainwads++; // zones.dta
|
||||
mainwads++; // zones.pk3
|
||||
mainwads++; // player.dta
|
||||
#ifdef USE_PATCH_DTA
|
||||
mainwads++; // patch.dta
|
||||
|
@ -1244,14 +1244,21 @@ 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
|
||||
{
|
||||
CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
|
||||
}
|
||||
if (M_CheckParm("-nosound"))
|
||||
sound_disabled = true;
|
||||
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
|
||||
midi_disabled = digital_disabled = true;
|
||||
{
|
||||
digital_disabled = true;
|
||||
midi_disabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (M_CheckParm("-nomidimusic"))
|
||||
|
@ -1259,9 +1266,18 @@ void D_SRB2Main(void)
|
|||
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);
|
||||
}
|
||||
|
||||
CONS_Printf("ST_Init(): Init status bar.\n");
|
||||
ST_Init();
|
||||
|
|
121
src/d_net.c
121
src/d_net.c
|
@ -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)
|
||||
{
|
||||
#endif
|
||||
struct pingcell pingv[MAXPLAYERS];
|
||||
INT32 pingc;
|
||||
|
||||
int name_width = 0;
|
||||
int ms_width = 0;
|
||||
|
||||
int n;
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS;i++)
|
||||
|
||||
pingc = 0;
|
||||
for (i = 1; i < MAXPLAYERS; ++i)
|
||||
if (playeringame[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
|
||||
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++;
|
||||
}
|
||||
#ifndef NEWPING
|
||||
|
||||
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)
|
||||
|
|
|
@ -74,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);
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
@ -497,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);
|
||||
|
||||
|
@ -573,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);
|
||||
|
@ -740,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);
|
||||
|
@ -879,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;
|
||||
|
||||
|
@ -920,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
|
||||
|
@ -1056,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)
|
||||
{
|
||||
|
@ -1186,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)
|
||||
{
|
||||
|
@ -1304,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)
|
||||
{
|
||||
|
@ -1692,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)
|
||||
{
|
||||
|
@ -2032,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"));
|
||||
|
@ -2053,6 +2051,7 @@ static void Command_Suicide(void)
|
|||
return;
|
||||
}
|
||||
|
||||
WRITEINT32(cp, consoleplayer);
|
||||
SendNetXCmd(XD_SUICIDE, &buf, 4);
|
||||
}
|
||||
|
||||
|
@ -4465,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -752,11 +752,9 @@ void Got_Filetxpak(void)
|
|||
nameonly(filename);
|
||||
|
||||
if (!(strcmp(filename, "srb2.pk3")
|
||||
&& strcmp(filename, "srb2.srb")
|
||||
&& strcmp(filename, "srb2.wad")
|
||||
&& strcmp(filename, "zones.dta")
|
||||
&& strcmp(filename, "zones.pk3")
|
||||
&& strcmp(filename, "player.dta")
|
||||
&& strcmp(filename, "patch.dta")
|
||||
&& strcmp(filename, "patch.pk3")
|
||||
&& strcmp(filename, "music.dta")
|
||||
))
|
||||
I_Error("Tried to download \"%s\"", filename);
|
||||
|
|
|
@ -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
|
||||
|
@ -509,6 +513,10 @@ typedef struct player_s
|
|||
#endif
|
||||
} player_t;
|
||||
|
||||
// Values for dashmode
|
||||
#define DASHMODE_THRESHOLD (3*TICRATE)
|
||||
#define DASHMODE_MAX (DASHMODE_THRESHOLD + 3)
|
||||
|
||||
// Value for infinite lives
|
||||
#define INFLIVES 0x7F
|
||||
|
||||
|
|
248
src/dehacked.c
248
src/dehacked.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -2447,6 +2512,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
|
||||
|
@ -4185,6 +4258,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
|
||||
// CA_GLIDEANDCLIMB
|
||||
"S_PLAY_GLIDE",
|
||||
"S_PLAY_GLIDE_LANDING",
|
||||
"S_PLAY_CLING",
|
||||
"S_PLAY_CLIMB",
|
||||
|
||||
|
@ -4284,6 +4358,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_TAILSOVERLAY_GASP",
|
||||
"S_TAILSOVERLAY_EDGE",
|
||||
|
||||
// [:
|
||||
"S_JETFUMEFLASH",
|
||||
|
||||
// Blue Crawla
|
||||
"S_POSS_STND",
|
||||
"S_POSS_RUN1",
|
||||
|
@ -4432,6 +4509,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",
|
||||
|
@ -4618,6 +4710,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",
|
||||
|
||||
|
@ -5861,7 +5969,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",
|
||||
|
@ -5882,6 +5990,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
|
||||
|
@ -5894,6 +6008,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",
|
||||
|
@ -5925,6 +6061,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",
|
||||
|
@ -5945,6 +6084,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",
|
||||
|
@ -5952,6 +6092,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
|
||||
|
@ -6603,6 +6753,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",
|
||||
|
@ -6623,6 +6783,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",
|
||||
|
@ -7234,6 +7397,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_THOK", // Thok! mobj
|
||||
"MT_PLAYER",
|
||||
"MT_TAILSOVERLAY", // c:
|
||||
"MT_METALJETFUME", // [:
|
||||
|
||||
// Enemies
|
||||
"MT_BLUECRAWLA", // Crawla (Blue)
|
||||
|
@ -7252,6 +7416,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
|
||||
|
@ -7273,6 +7439,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",
|
||||
|
@ -7384,6 +7555,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
|
||||
|
@ -7601,7 +7777,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",
|
||||
|
@ -7618,6 +7794,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
|
||||
|
@ -7628,6 +7818,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_TRAPGOYLEDOWN",
|
||||
"MT_TRAPGOYLELONG",
|
||||
"MT_TARGET",
|
||||
"MT_GREENFLAME",
|
||||
|
||||
// Stalagmites
|
||||
"MT_STALAGMITE0",
|
||||
|
@ -7649,6 +7840,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",
|
||||
|
@ -7656,6 +7848,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
|
||||
|
@ -7784,6 +7978,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
|
||||
|
@ -8269,6 +8464,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
|
||||
|
@ -8609,6 +8806,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
|
||||
|
@ -8830,9 +9029,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.
|
||||
|
@ -8963,6 +9162,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},
|
||||
|
@ -8996,6 +9196,7 @@ struct {
|
|||
{"TC_ALLWHITE",TC_ALLWHITE},
|
||||
{"TC_RAINBOW",TC_RAINBOW},
|
||||
{"TC_BLINK",TC_BLINK},
|
||||
{"TC_DASHMODE",TC_DASHMODE},
|
||||
#endif
|
||||
|
||||
{NULL,0}
|
||||
|
@ -9982,6 +10183,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;
|
||||
|
|
|
@ -509,13 +509,17 @@ INT32 I_GetKey(void);
|
|||
// 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.
|
||||
|
@ -561,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
|
||||
|
||||
|
|
|
@ -433,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.
|
||||
|
|
|
@ -75,6 +75,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;
|
||||
|
@ -637,6 +638,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)
|
||||
{
|
||||
|
@ -1584,15 +1586,15 @@ void F_StartEnding(void)
|
|||
UINT8 skinnum = players[consoleplayer].skin;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 7)
|
||||
if (skins[skinnum].sprites[SPR2_XTRA].numframes >= (XTRA_ENDING+2)+1)
|
||||
{
|
||||
sprdef = &skins[skinnum].sprites[SPR2_XTRA];
|
||||
// character head, skin specific
|
||||
sprframe = &sprdef->spriteframes[4];
|
||||
sprframe = &sprdef->spriteframes[XTRA_ENDING];
|
||||
endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
|
||||
sprframe = &sprdef->spriteframes[5];
|
||||
sprframe = &sprdef->spriteframes[XTRA_ENDING+1];
|
||||
endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
|
||||
sprframe = &sprdef->spriteframes[6];
|
||||
sprframe = &sprdef->spriteframes[XTRA_ENDING+2];
|
||||
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
|
||||
}
|
||||
else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this)
|
||||
|
@ -2097,12 +2099,12 @@ void F_InitMenuPresValues(void)
|
|||
curfadevalue = 16;
|
||||
curhidepics = hidetitlepics;
|
||||
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;
|
||||
|
||||
// Find current presentation values
|
||||
M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "SRB2BACK" : "TITLESKY");
|
||||
M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY");
|
||||
M_SetMenuCurFadeValue(16);
|
||||
M_SetMenuCurHideTitlePics();
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ extern INT32 curbgcolor;
|
|||
extern INT32 curbgxspeed;
|
||||
extern INT32 curbgyspeed;
|
||||
extern boolean curbghide;
|
||||
extern boolean hidetitlemap;
|
||||
|
||||
#define TITLEBACKGROUNDACTIVE (curfadevalue >= 0 || curbgname[0])
|
||||
|
||||
|
|
133
src/g_game.c
133
src/g_game.c
|
@ -361,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};
|
||||
|
@ -966,8 +968,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|
|||
forcefullinput = true;
|
||||
if (twodlevel
|
||||
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|
||||
|| (!demoplayback && (player->climbing
|
||||
|| (player->powers[pw_carry] == CR_NIGHTSMODE)
|
||||
|| (!demoplayback && ((player->powers[pw_carry] == CR_NIGHTSMODE)
|
||||
|| (player->pflags & (PF_SLIDING|PF_FORCESTRAFE))))) // Analog
|
||||
forcestrafe = true;
|
||||
if (forcestrafe)
|
||||
|
@ -1148,8 +1149,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
|
|||
if (!mouseaiming && cv_mousemove.value)
|
||||
forward += mousey;
|
||||
|
||||
if ((!demoplayback && (player->climbing
|
||||
|| (player->pflags & PF_SLIDING)))) // Analog for mouse
|
||||
if ((!demoplayback && (player->pflags & PF_SLIDING))) // Analog for mouse
|
||||
side += mousex*2;
|
||||
else if (cv_analog.value)
|
||||
{
|
||||
|
@ -1713,65 +1713,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))
|
||||
|
@ -1848,6 +1789,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);
|
||||
|
||||
|
@ -3341,6 +3341,7 @@ void G_LoadGameData(void)
|
|||
UINT32 recscore;
|
||||
tic_t rectime;
|
||||
UINT16 recrings;
|
||||
boolean gotperf;
|
||||
|
||||
UINT8 recmares;
|
||||
INT32 curmare;
|
||||
|
@ -3433,6 +3434,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;
|
||||
|
@ -3444,6 +3446,9 @@ void G_LoadGameData(void)
|
|||
mainrecords[i]->time = rectime;
|
||||
mainrecords[i]->rings = recrings;
|
||||
}
|
||||
|
||||
if (gotperf)
|
||||
mainrecords[i]->gotperfect = gotperf;
|
||||
}
|
||||
|
||||
// Nights records
|
||||
|
@ -3575,12 +3580,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,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;
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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*/;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,6 +182,8 @@ 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
|
||||
|
@ -197,7 +201,7 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
&lspr[NOLIGHT], // SPR_EGGO
|
||||
&lspr[NOLIGHT], // SPR_SEBH
|
||||
&lspr[NOLIGHT], // SPR_FAKE
|
||||
&lspr[NOLIGHT], // SPR_SHCK
|
||||
&lspr[LBLUESHINE_L],// SPR_SHCK
|
||||
|
||||
// Boss 4 (Castle Eggman)
|
||||
&lspr[NOLIGHT], // SPR_EGGP
|
||||
|
@ -260,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
|
||||
|
@ -377,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
|
||||
|
||||
|
@ -388,7 +397,9 @@ 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
|
||||
|
@ -396,6 +407,11 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
&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
|
||||
&lspr[NOLIGHT], // SPR_BSZ2
|
||||
|
@ -415,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
|
||||
|
@ -469,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
|
||||
|
|
|
@ -5454,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
|
||||
|
@ -5471,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)
|
||||
{
|
||||
|
@ -5480,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)
|
||||
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);
|
||||
}
|
||||
|
@ -5711,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;
|
||||
|
@ -5724,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);
|
||||
|
@ -5869,8 +5886,43 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
// ==========================================================================
|
||||
//
|
||||
// ==========================================================================
|
||||
static void HWR_DrawSkyBackground(void)
|
||||
static void HWR_DrawSkyBackground(player_t *player)
|
||||
{
|
||||
if (cv_grskydome.value)
|
||||
{
|
||||
FTransform transform;
|
||||
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
|
||||
postimg_t *type;
|
||||
|
||||
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
|
||||
{
|
||||
FOutVector v[4];
|
||||
angle_t angle;
|
||||
float dimensionmultiply;
|
||||
|
@ -5949,6 +6001,7 @@ static void HWR_DrawSkyBackground(void)
|
|||
}
|
||||
|
||||
HWD.pfnDrawPolygon(NULL, v, 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -6100,7 +6153,7 @@ if (0)
|
|||
}
|
||||
|
||||
if (drawsky)
|
||||
HWR_DrawSkyBackground();
|
||||
HWR_DrawSkyBackground(player);
|
||||
|
||||
//Hurdler: it doesn't work in splitscreen mode
|
||||
drawsky = splitscreen;
|
||||
|
@ -6317,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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1277,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;
|
||||
|
@ -1308,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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
//
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
|
36
src/i_tcp.c
36
src/i_tcp.c
|
@ -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)
|
||||
|
|
959
src/info.c
959
src/info.c
File diff suppressed because it is too large
Load diff
164
src/info.h
164
src/info.h
|
@ -268,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
|
||||
|
@ -298,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
|
||||
|
@ -316,6 +326,8 @@ 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
|
||||
|
@ -397,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
|
||||
|
@ -511,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
|
||||
|
@ -520,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
|
||||
|
||||
|
@ -531,7 +547,9 @@ 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
|
||||
|
@ -539,6 +557,11 @@ typedef enum sprite
|
|||
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
|
||||
SPR_BSZ2, // Medium flowers
|
||||
|
@ -558,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
|
||||
|
@ -612,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
|
||||
|
@ -771,6 +796,7 @@ typedef enum playersprite
|
|||
SPR2_TIRE, // tired
|
||||
|
||||
SPR2_GLID, // glide
|
||||
SPR2_LAND, // landing after glide/bounce
|
||||
SPR2_CLNG, // cling
|
||||
SPR2_CLMB, // climb
|
||||
|
||||
|
@ -778,7 +804,6 @@ typedef enum playersprite
|
|||
SPR2_FRUN, // float run
|
||||
|
||||
SPR2_BNCE, // bounce
|
||||
SPR2_BLND, // bounce landing
|
||||
|
||||
SPR2_FIRE, // fire
|
||||
|
||||
|
@ -854,6 +879,12 @@ typedef enum playersprite
|
|||
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,
|
||||
|
@ -900,6 +931,7 @@ typedef enum state
|
|||
|
||||
// CA_GLIDEANDCLIMB
|
||||
S_PLAY_GLIDE,
|
||||
S_PLAY_GLIDE_LANDING,
|
||||
S_PLAY_CLING,
|
||||
S_PLAY_CLIMB,
|
||||
|
||||
|
@ -999,6 +1031,9 @@ typedef enum state
|
|||
S_TAILSOVERLAY_GASP,
|
||||
S_TAILSOVERLAY_EDGE,
|
||||
|
||||
// [:
|
||||
S_JETFUMEFLASH,
|
||||
|
||||
// Blue Crawla
|
||||
S_POSS_STND,
|
||||
S_POSS_RUN1,
|
||||
|
@ -1147,6 +1182,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,
|
||||
|
@ -1333,6 +1383,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,
|
||||
|
||||
|
@ -2576,7 +2642,7 @@ typedef enum state
|
|||
|
||||
// Saloon door
|
||||
S_SALOONDOOR,
|
||||
S_SALOONDOORTHINKER,
|
||||
S_SALOONDOORCENTER,
|
||||
|
||||
// Train cameo
|
||||
S_TRAINCAMEOSPAWNER_1,
|
||||
|
@ -2597,6 +2663,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
|
||||
|
@ -2609,6 +2681,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,
|
||||
|
@ -2640,6 +2734,9 @@ typedef enum state
|
|||
S_TARGET_RESPAWN,
|
||||
S_TARGET_ALLDONE,
|
||||
|
||||
// ATZ's green flame
|
||||
S_GREENFLAME,
|
||||
|
||||
// Stalagmites
|
||||
S_STG0,
|
||||
S_STG1,
|
||||
|
@ -2660,6 +2757,7 @@ typedef enum state
|
|||
S_LAMPPOST1, // normal
|
||||
S_LAMPPOST2, // with snow
|
||||
S_HANGSTAR,
|
||||
S_MISTLETOE,
|
||||
// Xmas GFZ bushes
|
||||
S_XMASBLUEBERRYBUSH,
|
||||
S_XMASBERRYBUSH,
|
||||
|
@ -2667,6 +2765,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
|
||||
|
@ -3318,6 +3426,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,
|
||||
|
@ -3338,6 +3457,9 @@ typedef enum state
|
|||
S_SPLISH8,
|
||||
S_SPLISH9,
|
||||
|
||||
// Lava Splish
|
||||
S_LAVASPLISH,
|
||||
|
||||
// added water splash
|
||||
S_SPLASH1,
|
||||
S_SPLASH2,
|
||||
|
@ -3971,6 +4093,7 @@ typedef enum mobj_type
|
|||
MT_THOK, // Thok! mobj
|
||||
MT_PLAYER,
|
||||
MT_TAILSOVERLAY, // c:
|
||||
MT_METALJETFUME,
|
||||
|
||||
// Enemies
|
||||
MT_BLUECRAWLA, // Crawla (Blue)
|
||||
|
@ -3989,6 +4112,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
|
||||
|
@ -4010,6 +4135,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,
|
||||
|
@ -4121,6 +4251,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
|
||||
|
@ -4338,7 +4473,7 @@ typedef enum mobj_type
|
|||
MT_MINECARTSIDEMARK,
|
||||
MT_MINECARTSPARK,
|
||||
MT_SALOONDOOR,
|
||||
MT_SALOONDOORTHINKER,
|
||||
MT_SALOONDOORCENTER,
|
||||
MT_TRAINCAMEOSPAWNER,
|
||||
MT_TRAINSEG,
|
||||
MT_TRAINDUSTSPAWNER,
|
||||
|
@ -4355,6 +4490,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
|
||||
|
@ -4365,6 +4514,7 @@ typedef enum mobj_type
|
|||
MT_TRAPGOYLEDOWN,
|
||||
MT_TRAPGOYLELONG,
|
||||
MT_TARGET, // AKA Red Crystal
|
||||
MT_GREENFLAME,
|
||||
|
||||
// Stalagmites
|
||||
MT_STALAGMITE0,
|
||||
|
@ -4386,6 +4536,7 @@ typedef enum mobj_type
|
|||
MT_LAMPPOST1, // normal
|
||||
MT_LAMPPOST2, // with snow
|
||||
MT_HANGSTAR,
|
||||
MT_MISTLETOE,
|
||||
// Xmas GFZ bushes
|
||||
MT_XMASBLUEBERRYBUSH,
|
||||
MT_XMASBERRYBUSH,
|
||||
|
@ -4393,6 +4544,8 @@ typedef enum mobj_type
|
|||
// FHZ
|
||||
MT_FHZICE1,
|
||||
MT_FHZICE2,
|
||||
MT_ROSY,
|
||||
MT_CDLHRT,
|
||||
|
||||
// Halloween Scenery
|
||||
// Pumpkins
|
||||
|
@ -4521,6 +4674,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
|
||||
|
|
|
@ -816,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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, §ors[sector->camsec], META_SECTOR);
|
||||
return 1;
|
||||
case sector_lines: // lines
|
||||
LUA_PushUserdata(L, sector->lines, META_SECTORLINES);
|
||||
LUA_PushUserdata(L, §or->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
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -431,7 +431,7 @@ void LUA_InvalidateLevel(void)
|
|||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
LUA_InvalidateUserdata(§ors[i]);
|
||||
LUA_InvalidateUserdata(sectors[i].lines);
|
||||
LUA_InvalidateUserdata(§ors[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]);
|
||||
}
|
||||
|
|
28
src/m_cond.c
28
src/m_cond.c
|
@ -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');
|
||||
|
||||
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');
|
||||
|
||||
if (!big)
|
||||
pnamebuf[5] = em->sprite;
|
||||
else
|
||||
pnamebuf[4] = em->sprite;
|
||||
|
||||
return pnamebuf;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
929
src/m_menu.c
929
src/m_menu.c
File diff suppressed because it is too large
Load diff
14
src/m_menu.h
14
src/m_menu.h
|
@ -63,6 +63,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,
|
||||
|
@ -103,6 +104,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,
|
||||
|
@ -323,9 +325,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
|
||||
|
@ -374,6 +385,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[];
|
||||
|
||||
|
|
|
@ -197,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;
|
||||
|
|
418
src/p_enemy.c
418
src/p_enemy.c
|
@ -298,6 +298,14 @@ void A_SnapperThinker(mobj_t *actor);
|
|||
void A_SaloonDoorSpawn(mobj_t *actor);
|
||||
void A_MinecartSparkThink(mobj_t *actor);
|
||||
void A_ModuloToState(mobj_t *actor);
|
||||
void A_LavafallRocks(mobj_t *actor);
|
||||
void A_LavafallLava(mobj_t *actor);
|
||||
void A_FallingLavaCheck(mobj_t *actor);
|
||||
void A_FireShrink(mobj_t *actor);
|
||||
void A_SpawnPterabytes(mobj_t *actor);
|
||||
void A_PterabyteHover(mobj_t *actor);
|
||||
void A_RolloutSpawn(mobj_t *actor);
|
||||
void A_RolloutRock(mobj_t *actor);
|
||||
|
||||
//for p_enemy.c
|
||||
|
||||
|
@ -2019,6 +2027,7 @@ void A_CrushstaceanWalk(mobj_t *actor)
|
|||
|| (actor->reactiontime-- <= 0))
|
||||
{
|
||||
actor->flags2 ^= MF2_AMBUSH;
|
||||
P_SetTarget(&actor->target, NULL);
|
||||
P_SetMobjState(actor, locvar2);
|
||||
actor->reactiontime = actor->info->reactiontime;
|
||||
}
|
||||
|
@ -2079,7 +2088,7 @@ void A_CrushclawAim(mobj_t *actor)
|
|||
return; // there is only one step and it is crab
|
||||
}
|
||||
|
||||
if (crab->target || P_LookForPlayers(crab, true, false, 600*crab->scale))
|
||||
if (crab->target || P_LookForPlayers(crab, true, false, actor->info->speed*crab->scale))
|
||||
ang = R_PointToAngle2(crab->x, crab->y, crab->target->x, crab->target->y);
|
||||
else
|
||||
ang = crab->angle + ((crab->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);
|
||||
|
@ -2162,7 +2171,7 @@ void A_CrushclawLaunch(mobj_t *actor)
|
|||
UINT8 i = 0;
|
||||
for (i = 0; (i < CSEGS); i++)
|
||||
{
|
||||
mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate);
|
||||
mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, (mobjtype_t)actor->info->raisestate);
|
||||
P_SetTarget(&prevchain->target, newchain);
|
||||
prevchain = newchain;
|
||||
}
|
||||
|
@ -5343,20 +5352,22 @@ static mobj_t *minus;
|
|||
|
||||
static boolean PIT_MinusCarry(mobj_t *thing)
|
||||
{
|
||||
if (minus->tracer)
|
||||
return true;
|
||||
|
||||
if (minus->type == thing->type)
|
||||
return true;
|
||||
|
||||
if (!(thing->flags & MF_SHOOTABLE) || !(thing->flags & MF_ENEMY))
|
||||
if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY)))
|
||||
return true;
|
||||
|
||||
if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius * 3)
|
||||
if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius*3)
|
||||
return true;
|
||||
|
||||
if (abs(thing->z - minus->z) > minus->height)
|
||||
return true;
|
||||
|
||||
P_SetTarget(&minus->tracer, thing);
|
||||
minus->tracer->flags &= ~MF_PUSHABLE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -5420,6 +5431,9 @@ void A_MinusDigging(mobj_t *actor)
|
|||
A_Chase(actor);
|
||||
|
||||
// Carry over shit, maybe
|
||||
if (P_MobjWasRemoved(actor->tracer) || !actor->tracer->health)
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
|
||||
if (!actor->tracer)
|
||||
{
|
||||
fixed_t radius = 3*actor->radius;
|
||||
|
@ -5469,7 +5483,6 @@ void A_MinusPopup(mobj_t *actor)
|
|||
else
|
||||
actor->momz = 10*FRACUNIT;
|
||||
|
||||
actor->flags |= MF_SPECIAL|MF_SHOOTABLE;
|
||||
S_StartSound(actor, sfx_s3k82);
|
||||
for (i = 1; i <= num; i++)
|
||||
{
|
||||
|
@ -5482,6 +5495,7 @@ void A_MinusPopup(mobj_t *actor)
|
|||
if (actor->tracer)
|
||||
P_DamageMobj(actor->tracer, actor, actor, 1, 0);
|
||||
|
||||
actor->flags = (actor->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE;
|
||||
}
|
||||
|
||||
// Function: A_MinusCheck
|
||||
|
@ -8408,8 +8422,8 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
|
|||
//
|
||||
// var1 = sound # to play
|
||||
// var2:
|
||||
// 0 = Play sound without an origin
|
||||
// 1 = Play sound using calling object as origin
|
||||
// lower 16 bits = If 1, play sound using calling object as origin. If 0, play sound without an origin
|
||||
// upper 16 bits = If 1, do not play sound during preticker.
|
||||
//
|
||||
void A_PlaySound(mobj_t *actor)
|
||||
{
|
||||
|
@ -8420,7 +8434,10 @@ void A_PlaySound(mobj_t *actor)
|
|||
return;
|
||||
#endif
|
||||
|
||||
S_StartSound(locvar2 ? actor : NULL, locvar1);
|
||||
if (leveltime < 2 && (locvar2 >> 16))
|
||||
return;
|
||||
|
||||
S_StartSound((locvar2 & 65535) ? actor : NULL, locvar1);
|
||||
}
|
||||
|
||||
// Function: A_FindTarget
|
||||
|
@ -12197,7 +12214,7 @@ void A_MineExplode(mobj_t *actor)
|
|||
#undef dist
|
||||
|
||||
if (actor->watertop != INT32_MAX)
|
||||
P_SpawnMobj(actor->x, actor->y, actor->watertop, MT_SPLISH);
|
||||
P_SpawnMobj(actor->x, actor->y, actor->watertop, (actor->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12237,7 +12254,6 @@ void A_ConnectToGround(mobj_t *actor)
|
|||
mobj_t *work;
|
||||
fixed_t workz;
|
||||
fixed_t workh;
|
||||
SINT8 dir;
|
||||
angle_t ang;
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
|
@ -12251,23 +12267,17 @@ void A_ConnectToGround(mobj_t *actor)
|
|||
P_AdjustMobjFloorZ_FFloors(actor, actor->subsector->sector, 2);
|
||||
|
||||
if (actor->flags2 & MF2_OBJECTFLIP)
|
||||
{
|
||||
workz = actor->ceilingz - (actor->z + actor->height);
|
||||
dir = -1;
|
||||
}
|
||||
workz = (actor->z + actor->height) - actor->ceilingz;
|
||||
else
|
||||
{
|
||||
workz = actor->floorz - actor->z;
|
||||
dir = 1;
|
||||
}
|
||||
|
||||
if (locvar2)
|
||||
{
|
||||
workh = FixedMul(mobjinfo[locvar2].height, actor->scale);
|
||||
if (actor->flags2 & MF2_OBJECTFLIP)
|
||||
workz -= workh;
|
||||
workz += workh;
|
||||
work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar2);
|
||||
workz += dir*workh;
|
||||
workz += workh;
|
||||
}
|
||||
|
||||
if (!locvar1)
|
||||
|
@ -12276,21 +12286,18 @@ void A_ConnectToGround(mobj_t *actor)
|
|||
if (!(workh = FixedMul(mobjinfo[locvar1].height, actor->scale)))
|
||||
return;
|
||||
|
||||
if (actor->flags2 & MF2_OBJECTFLIP)
|
||||
workz -= workh;
|
||||
|
||||
ang = actor->angle + ANGLE_45;
|
||||
while (dir*workz < 0)
|
||||
while (workz < 0)
|
||||
{
|
||||
work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1);
|
||||
if (work)
|
||||
work->angle = ang;
|
||||
ang += ANGLE_90;
|
||||
workz += dir*workh;
|
||||
workz += workh;
|
||||
}
|
||||
|
||||
if (workz != 0)
|
||||
actor->z += workz;
|
||||
actor->z += P_MobjFlip(actor)*workz;
|
||||
}
|
||||
|
||||
// Function: A_SpawnParticleRelative
|
||||
|
@ -13455,6 +13462,13 @@ void A_TNTExplode(mobj_t *actor)
|
|||
if (LUA_CallAction("A_TNTExplode", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (actor->tracer)
|
||||
{
|
||||
P_SetTarget(&actor->tracer->tracer, NULL);
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
}
|
||||
|
||||
P_UnsetThingPosition(actor);
|
||||
if (sector_list)
|
||||
{
|
||||
|
@ -13668,8 +13682,6 @@ void A_KillSegments(mobj_t *actor)
|
|||
static void P_SnapperLegPlace(mobj_t *mo)
|
||||
{
|
||||
mobj_t *seg = mo->tracer;
|
||||
fixed_t x0 = mo->x;
|
||||
fixed_t y0 = mo->y;
|
||||
angle_t a = mo->angle;
|
||||
angle_t fa = (a >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
fixed_t c = FINECOSINE(fa);
|
||||
|
@ -13684,7 +13696,8 @@ static void P_SnapperLegPlace(mobj_t *mo)
|
|||
fixed_t rad = mo->radius;
|
||||
INT32 necklen = (32*(mo->info->reactiontime - mo->reactiontime))/mo->info->reactiontime; // Not in FU
|
||||
|
||||
P_TeleportMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, mo->z + mo->height/3);
|
||||
seg->z = mo->z + ((mo->eflags & MFE_VERTICALFLIP) ? (((mo->height<<1)/3) - seg->height) : mo->height/3);
|
||||
P_TryMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, true);
|
||||
seg->angle = a;
|
||||
|
||||
// Move as many legs as available.
|
||||
|
@ -13704,13 +13717,14 @@ static void P_SnapperLegPlace(mobj_t *mo)
|
|||
{
|
||||
x = c*o2 + s*o1;
|
||||
y = s*o2 - c*o1;
|
||||
P_TryMove(seg, x0 + x, y0 + y, true);
|
||||
seg->z = mo->z + (((mo->eflags & MFE_VERTICALFLIP) ? (mo->height - seg->height) : 0));
|
||||
P_TryMove(seg, mo->x + x, mo->y + y, true);
|
||||
P_SetMobjState(seg, seg->info->raisestate);
|
||||
}
|
||||
else
|
||||
P_SetMobjState(seg, seg->info->spawnstate);
|
||||
|
||||
seg->angle = R_PointToAngle2(x0, y0, seg->x, seg->y);
|
||||
seg->angle = R_PointToAngle2(mo->x, mo->y, seg->x, seg->y);
|
||||
|
||||
seg = seg->tracer;
|
||||
} while (seg);
|
||||
|
@ -13738,14 +13752,14 @@ void A_SnapperSpawn(mobj_t *actor)
|
|||
#endif
|
||||
|
||||
// It spawns 1 head.
|
||||
seg = P_SpawnMobj(actor->x, actor->y, actor->z, headtype);
|
||||
seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, headtype);
|
||||
P_SetTarget(&ptr->tracer, seg);
|
||||
ptr = seg;
|
||||
|
||||
// It spawns 4 legs which will be handled in the thinker function.
|
||||
for (i = 1; i <= 4; i++)
|
||||
{
|
||||
seg = P_SpawnMobj(actor->x, actor->y, actor->z, legtype);
|
||||
seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, legtype);
|
||||
P_SetTarget(&ptr->tracer, seg);
|
||||
ptr = seg;
|
||||
|
||||
|
@ -13893,51 +13907,43 @@ void A_SnapperThinker(mobj_t *actor)
|
|||
//
|
||||
// Description: Spawns a saloon door.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
// var1 = mobjtype for sides
|
||||
// var2 = distance sides should be placed apart
|
||||
//
|
||||
void A_SaloonDoorSpawn(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
angle_t ang = actor->angle;
|
||||
angle_t fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
fixed_t c = FINECOSINE(fa);
|
||||
fixed_t s = FINESINE(fa);
|
||||
INT32 d = 48;
|
||||
fixed_t x = actor->x;
|
||||
fixed_t y = actor->y;
|
||||
fixed_t z = actor->z;
|
||||
fixed_t c = FINECOSINE(fa)*locvar2;
|
||||
fixed_t s = FINESINE(fa)*locvar2;
|
||||
mobj_t *door;
|
||||
mobjflag2_t ambush = (actor->flags & MF2_AMBUSH);
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_SaloonDoorSpawn", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
//Front
|
||||
door = P_SpawnMobj(x + c*d, y + s*d, z, MT_SALOONDOOR);
|
||||
if (!locvar1)
|
||||
return;
|
||||
|
||||
// One door...
|
||||
if (!(door = P_SpawnMobjFromMobj(actor, c, s, 0, locvar1))) return;
|
||||
door->angle = ang + ANGLE_180;
|
||||
door->extravalue1 = AngleFixed(door->angle); // Origin angle
|
||||
door->extravalue2 = 0; // Angular speed
|
||||
P_SetTarget(&door->tracer, actor); // Origin door
|
||||
door->flags2 |= ambush; // Can be opened by normal players?
|
||||
|
||||
// Origin angle
|
||||
door->extravalue1 = AngleFixed(door->angle);
|
||||
|
||||
// Angular speed
|
||||
door->extravalue2 = 0;
|
||||
|
||||
// Origin door
|
||||
P_SetTarget(&door->tracer, actor);
|
||||
|
||||
//Back
|
||||
door = P_SpawnMobj(x - c*d, y - s*d, z, MT_SALOONDOOR);
|
||||
// ...two door!
|
||||
if (!(door = P_SpawnMobjFromMobj(actor, -c, -s, 0, locvar1))) return;
|
||||
door->angle = ang;
|
||||
|
||||
// Origin angle
|
||||
door->extravalue1 = AngleFixed(door->angle);
|
||||
|
||||
// Angular speed
|
||||
door->extravalue2 = 0;
|
||||
|
||||
// Origin door
|
||||
P_SetTarget(&door->tracer, actor);
|
||||
door->extravalue1 = AngleFixed(door->angle); // Origin angle
|
||||
door->extravalue2 = 0; // Angular speed
|
||||
P_SetTarget(&door->tracer, actor); // Origin door
|
||||
door->flags2 |= ambush; // Can be opened by normal players?
|
||||
}
|
||||
|
||||
// Function: A_MinecartSparkThink
|
||||
|
@ -13998,3 +14004,289 @@ void A_ModuloToState(mobj_t *actor)
|
|||
P_SetMobjState(actor, (locvar2));
|
||||
modulothing++;
|
||||
}
|
||||
|
||||
// Function: A_LavafallRocks
|
||||
//
|
||||
// Description: Spawn random rock particles.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_LavafallRocks(mobj_t *actor)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_LavafallRocks", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Don't spawn rocks unless a player is relatively close by.
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
if (playeringame[i] && players[i].mo
|
||||
&& P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (1600 << FRACBITS))
|
||||
break; // Stop looking.
|
||||
|
||||
if (i < MAXPLAYERS)
|
||||
{
|
||||
angle_t fa = (FixedAngle(P_RandomKey(360) << FRACBITS) >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
fixed_t offset = P_RandomRange(4, 12) << FRACBITS;
|
||||
fixed_t xoffs = FixedMul(FINECOSINE(fa), actor->radius + offset);
|
||||
fixed_t yoffs = FixedMul(FINESINE(fa), actor->radius + offset);
|
||||
P_SpawnMobjFromMobj(actor, xoffs, yoffs, 0, MT_LAVAFALLROCK);
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_LavafallLava
|
||||
//
|
||||
// Description: Spawn lava from lavafall.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_LavafallLava(mobj_t *actor)
|
||||
{
|
||||
mobj_t *lavafall;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_LavafallLava", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS)))
|
||||
return;
|
||||
|
||||
lavafall = P_SpawnMobjFromMobj(actor, 0, 0, -8*FRACUNIT, MT_LAVAFALL_LAVA);
|
||||
lavafall->momz = -P_MobjFlip(actor)*25*FRACUNIT;
|
||||
}
|
||||
|
||||
// Function: A_FallingLavaCheck
|
||||
//
|
||||
// Description: If actor hits the ground or a water surface, enter the death animation.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_FallingLavaCheck(mobj_t *actor)
|
||||
{
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FallingLavaCheck", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (actor->eflags & MFE_TOUCHWATER || P_IsObjectOnGround(actor))
|
||||
{
|
||||
actor->flags = MF_NOGRAVITY|MF_NOCLIPTHING;
|
||||
actor->momz = 0;
|
||||
if (actor->eflags & MFE_TOUCHWATER)
|
||||
actor->z = (actor->eflags & MFE_VERTICALFLIP) ? actor->waterbottom : actor->watertop;
|
||||
P_SetMobjState(actor, actor->info->deathstate);
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_FireShrink
|
||||
//
|
||||
// Description: Shrink the actor down to the specified scale at the specified speed.
|
||||
//
|
||||
// var1 = Scale to shrink to
|
||||
// var2 = Shrinking speed
|
||||
//
|
||||
void A_FireShrink(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FireShrink", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
actor->destscale = locvar1;
|
||||
actor->scalespeed = FRACUNIT/locvar2;
|
||||
}
|
||||
|
||||
// Function: A_SpawnPterabytes
|
||||
//
|
||||
// Description: Spawn Pterabytes around the actor in a circle.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_SpawnPterabytes(mobj_t *actor)
|
||||
{
|
||||
mobj_t *waypoint, *ptera;
|
||||
fixed_t c, s;
|
||||
fixed_t rad = 280*FRACUNIT;
|
||||
angle_t ang = 0;
|
||||
angle_t interval, fa;
|
||||
UINT8 amount = 1;
|
||||
UINT8 i;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_SpawnPterabytes", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (actor->spawnpoint)
|
||||
amount = actor->spawnpoint->extrainfo + 1;
|
||||
|
||||
interval = FixedAngle(FRACUNIT*360/amount);
|
||||
|
||||
for (i = 0; i < amount; i++)
|
||||
{
|
||||
fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
c = FINECOSINE(fa);
|
||||
s = FINESINE(fa);
|
||||
waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT);
|
||||
waypoint->angle = ang + ANGLE_90;
|
||||
P_SetTarget(&waypoint->tracer, actor);
|
||||
ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE);
|
||||
ptera->angle = waypoint->angle;
|
||||
P_SetTarget(&ptera->tracer, waypoint);
|
||||
ptera->extravalue1 = 0;
|
||||
ang += interval;
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_PterabyteHover
|
||||
//
|
||||
// Description: Hover in a circular fashion, bobbing up and down slightly.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_PterabyteHover(mobj_t *actor)
|
||||
{
|
||||
angle_t ang, fa;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_PterabyteHover", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
P_InstaThrust(actor, actor->angle, actor->info->speed);
|
||||
actor->angle += ANG1;
|
||||
actor->extravalue1 = (actor->extravalue1 + 3) % 360;
|
||||
ang = actor->extravalue1*ANG1;
|
||||
fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
actor->z += FINESINE(fa);
|
||||
}
|
||||
// Function: A_RolloutSpawn
|
||||
//
|
||||
// Description: Spawns a new Rollout Rock when the currently spawned rock is destroyed or moves far enough away.
|
||||
//
|
||||
// var1 = Distance currently spawned rock should travel before spawning a new one
|
||||
// var2 = Object type to spawn
|
||||
//
|
||||
void A_RolloutSpawn(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_RolloutSpawn", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!(actor->target)
|
||||
|| P_MobjWasRemoved(actor->target)
|
||||
|| P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) > locvar1)
|
||||
{
|
||||
actor->target = P_SpawnMobj(actor->x, actor->y, actor->z, locvar2);
|
||||
actor->target->flags2 |= (actor->flags2 & (MF2_AMBUSH | MF2_OBJECTFLIP)) | MF2_SLIDEPUSH;
|
||||
actor->target->eflags |= (actor->eflags & MFE_VERTICALFLIP);
|
||||
|
||||
if (actor->target->flags2 & MF2_AMBUSH)
|
||||
{
|
||||
actor->target->color = SKINCOLOR_SUPERRUST3;
|
||||
actor->target->colorized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_RolloutRock
|
||||
//
|
||||
// Description: Thinker for Rollout Rock.
|
||||
//
|
||||
// var1 = Drag
|
||||
// var2 = Vertical bobbing speed factor
|
||||
//
|
||||
void A_RolloutRock(mobj_t *actor)
|
||||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
UINT8 maxframes = actor->info->reactiontime; // number of frames the mobj cycles through
|
||||
fixed_t pi = (22*FRACUNIT/7);
|
||||
fixed_t circumference = FixedMul(2 * pi, actor->radius); // used to calculate when to change frame
|
||||
fixed_t speed = P_AproxDistance(actor->momx, actor->momy), topspeed = FixedMul(actor->info->speed, actor->scale);
|
||||
boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER);
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_RolloutRock", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves
|
||||
|
||||
if (actor->threshold)
|
||||
actor->threshold--;
|
||||
|
||||
if (inwater && !(actor->flags2 & MF2_AMBUSH)) // buoyancy in water (or lava)
|
||||
{
|
||||
UINT8 flip = P_MobjFlip(actor);
|
||||
fixed_t prevmomz = actor->momz;
|
||||
actor->momz = FixedMul(actor->momz, locvar2);
|
||||
actor->momz += flip * FixedMul(locvar2, actor->scale);
|
||||
if (flip*prevmomz < 0 && flip*actor->momz >= 0 && !actor->threshold)
|
||||
{
|
||||
if (actor->eflags & MFE_UNDERWATER)
|
||||
S_StartSound(actor, sfx_splash);
|
||||
else if (!actor->threshold)
|
||||
S_StartSound(actor, sfx_splish);
|
||||
actor->threshold = max((topspeed - speed) >> FRACBITS, 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (speed > topspeed) // cap speed
|
||||
{
|
||||
actor->momx = FixedMul(FixedDiv(actor->momx, speed), topspeed);
|
||||
actor->momy = FixedMul(FixedDiv(actor->momy, speed), topspeed);
|
||||
}
|
||||
|
||||
if (P_IsObjectOnGround(actor) || inwater) // apply drag to speed (compensates for lack of friction but also works in liquids)
|
||||
{
|
||||
actor->momx = FixedMul(actor->momx, locvar1);
|
||||
actor->momy = FixedMul(actor->momy, locvar1);
|
||||
}
|
||||
|
||||
speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling
|
||||
|
||||
if (speed < actor->scale >> 1) // stop moving if speed is insignificant
|
||||
{
|
||||
actor->momx = 0;
|
||||
actor->momy = 0;
|
||||
}
|
||||
else if (speed > actor->scale)
|
||||
{
|
||||
actor->movecount = 1; // rock has moved; fuse should be set so we don't have a trillion rocks lying around
|
||||
actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); // set rock's angle to movement direction
|
||||
actor->movefactor += speed;
|
||||
if (actor->movefactor > circumference / maxframes) // if distance moved is enough to change frame, change it!
|
||||
{
|
||||
actor->reactiontime++;
|
||||
actor->reactiontime %= maxframes;
|
||||
actor->movefactor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
actor->frame = actor->reactiontime % maxframes; // set frame
|
||||
|
||||
if (!(actor->flags & MF_PUSHABLE)) // if being ridden, don't disappear
|
||||
actor->fuse = 0;
|
||||
else if (!actor->fuse && actor->movecount == 1) // otherwise if rock has moved, set its fuse
|
||||
actor->fuse = actor->info->painchance;
|
||||
|
||||
if (actor->fuse && actor->fuse < 2*TICRATE)
|
||||
actor->flags2 ^= MF2_DONTDRAW;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -2459,7 +2460,52 @@ void T_RaiseSector(levelspecthink_t *raise)
|
|||
}
|
||||
}
|
||||
|
||||
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 (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
|
||||
|
|
|
@ -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)) > -(special->height/4))
|
||||
&& 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)
|
||||
|
@ -471,13 +477,29 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
toucher->momy = -toucher->momy;
|
||||
if (player->charability == CA_FLY && player->panim == PA_ABILITY)
|
||||
toucher->momz = -toucher->momz/2;
|
||||
else if (player->pflags & PF_GLIDING && !P_IsObjectOnGround(toucher))
|
||||
{
|
||||
player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE);
|
||||
P_SetPlayerMobjState(toucher, S_PLAY_FALL);
|
||||
toucher->momz += P_MobjFlip(toucher) * (player->speed >> 3);
|
||||
toucher->momx = 7*toucher->momx>>3;
|
||||
toucher->momy = 7*toucher->momy>>3;
|
||||
}
|
||||
else if (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
|
||||
&& player->panim == PA_DASH)
|
||||
P_DoPlayerPain(player, special, special);
|
||||
}
|
||||
P_DamageMobj(special, toucher, toucher, 1, 0);
|
||||
if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)
|
||||
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 +1096,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)
|
||||
|
@ -1482,8 +1504,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:
|
||||
|
@ -1509,10 +1529,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
toucher->momx = P_ReturnThrustX(special, angle, touchspeed);
|
||||
toucher->momy = P_ReturnThrustY(special, angle, touchspeed);
|
||||
toucher->momz = -toucher->momz;
|
||||
if (player->pflags & PF_GLIDING)
|
||||
if (player->pflags & PF_GLIDING && !P_IsObjectOnGround(toucher))
|
||||
{
|
||||
player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE);
|
||||
P_SetPlayerMobjState(toucher, S_PLAY_FALL);
|
||||
toucher->momz += P_MobjFlip(toucher) * (player->speed >> 3);
|
||||
toucher->momx = 7*toucher->momx>>3;
|
||||
toucher->momy = 7*toucher->momy>>3;
|
||||
}
|
||||
player->homing = 0;
|
||||
|
||||
|
@ -1557,10 +1580,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
toucher->momx = P_ReturnThrustX(special, special->angle, touchspeed);
|
||||
toucher->momy = P_ReturnThrustY(special, special->angle, touchspeed);
|
||||
toucher->momz = -toucher->momz;
|
||||
if (player->pflags & PF_GLIDING)
|
||||
if (player->pflags & PF_GLIDING && !P_IsObjectOnGround(toucher))
|
||||
{
|
||||
player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE);
|
||||
P_SetPlayerMobjState(toucher, S_PLAY_FALL);
|
||||
toucher->momz += P_MobjFlip(toucher) * (player->speed >> 3);
|
||||
toucher->momx = 7*toucher->momx>>3;
|
||||
toucher->momy = 7*toucher->momy>>3;
|
||||
}
|
||||
player->homing = 0;
|
||||
|
||||
|
@ -1765,7 +1791,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);
|
||||
|
@ -1775,7 +1801,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;
|
||||
|
||||
|
@ -2457,6 +2483,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)
|
||||
|
@ -2602,6 +2650,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);
|
||||
|
|
|
@ -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);
|
||||
|
|
322
src/p_map.c
322
src/p_map.c
|
@ -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)
|
||||
|
@ -286,7 +289,27 @@ 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
|
||||
{
|
||||
|
@ -321,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,8 +375,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
|
||||
if (horizspeed)
|
||||
{
|
||||
object->player->drawangle = spring->angle;
|
||||
object->angle = spring->angle;
|
||||
object->angle = object->player->drawangle = spring->angle;
|
||||
|
||||
if (!demoplayback || P_AnalogMove(object->player))
|
||||
{
|
||||
|
@ -356,11 +386,25 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (object->player->pflags & PF_GLIDING)
|
||||
P_SetPlayerMobjState(object, S_PLAY_FALL);
|
||||
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
|
||||
//
|
||||
|
@ -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,40 +1005,72 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
}
|
||||
}
|
||||
|
||||
if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
P_PlayerBarrelCollide(tmthing, thing);
|
||||
|
||||
if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -3334,13 +3484,13 @@ isblocking:
|
|||
&& canclimb)
|
||||
{
|
||||
slidemo->angle = climbangle;
|
||||
if (!demoplayback || P_AnalogMove(slidemo->player))
|
||||
/*if (!demoplayback || P_AnalogMove(slidemo->player))
|
||||
{
|
||||
if (slidemo->player == &players[consoleplayer])
|
||||
localangle = slidemo->angle;
|
||||
else if (slidemo->player == &players[secondarydisplayplayer])
|
||||
localangle2 = slidemo->angle;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!slidemo->player->climbing)
|
||||
{
|
||||
|
@ -3479,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
|
||||
|
@ -3639,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)
|
||||
{
|
||||
|
|
|
@ -662,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)))
|
||||
|
@ -674,7 +674,7 @@ 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 < opentop) {
|
||||
opentop = bottomheight;
|
||||
|
@ -687,7 +687,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
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 > openbottom) {
|
||||
openbottom = topheight;
|
||||
|
@ -708,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)))
|
||||
|
@ -720,7 +720,7 @@ 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 < opentop) {
|
||||
opentop = bottomheight;
|
||||
|
@ -733,7 +733,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
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 > openbottom) {
|
||||
openbottom = topheight;
|
||||
|
|
764
src/p_mobj.c
764
src/p_mobj.c
File diff suppressed because it is too large
Load diff
10
src/p_mobj.h
10
src/p_mobj.h
|
@ -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;
|
||||
|
||||
|
|
|
@ -3618,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)
|
||||
|
|
|
@ -2606,7 +2606,6 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
boolean loadedbm = false;
|
||||
sector_t *ss;
|
||||
boolean chase;
|
||||
|
||||
levelloading = true;
|
||||
|
||||
// This is needed. Don't touch.
|
||||
|
@ -3047,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.
|
||||
|
|
201
src/p_spec.c
201
src/p_spec.c
|
@ -2718,6 +2718,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
CONS_Debug(DBG_GAMELOGIC, "Line type 414 Executor: sfx number %d is invalid!\n", sfxnum);
|
||||
return;
|
||||
}
|
||||
|
||||
if (line->tag != 0) // Do special stuff only if a non-zero linedef tag is set
|
||||
{
|
||||
if (line->flags & ML_EFFECT5) // Repeat Midtexture
|
||||
|
@ -2758,7 +2759,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (line->flags & ML_NOCLIMB)
|
||||
{
|
||||
// play the sound from nowhere, but only if display player triggered it
|
||||
|
@ -2784,6 +2786,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
S_StartSound(mo, sfxnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 415: // Run a script
|
||||
|
@ -4174,27 +4177,12 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
|
|||
// Check the 3D floor's type...
|
||||
if (rover->flags & FF_BLOCKPLAYER)
|
||||
{
|
||||
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight));
|
||||
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight));
|
||||
// Thing must be on top of the floor to be affected...
|
||||
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
|
||||
{
|
||||
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight)
|
||||
if (!(floorallowed || ceilingallowed))
|
||||
continue;
|
||||
}
|
||||
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
|
||||
{
|
||||
if (!(player->mo->eflags & MFE_VERTICALFLIP)
|
||||
|| player->mo->z + player->mo->height != bottomheight)
|
||||
continue;
|
||||
}
|
||||
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
|
||||
{
|
||||
if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight)
|
||||
|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight)))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Water and DEATH FOG!!! heh
|
||||
|
@ -4234,27 +4222,12 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
|
|||
// Check the 3D floor's type...
|
||||
if (rover->flags & FF_BLOCKPLAYER)
|
||||
{
|
||||
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight));
|
||||
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight));
|
||||
// Thing must be on top of the floor to be affected...
|
||||
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
|
||||
{
|
||||
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight)
|
||||
if (!(floorallowed || ceilingallowed))
|
||||
continue;
|
||||
}
|
||||
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
|
||||
{
|
||||
if (!(player->mo->eflags & MFE_VERTICALFLIP)
|
||||
|| player->mo->z + player->mo->height != bottomheight)
|
||||
continue;
|
||||
}
|
||||
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
|
||||
{
|
||||
if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight)
|
||||
|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight)))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Water and DEATH FOG!!! heh
|
||||
|
@ -4304,26 +4277,11 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar
|
|||
// Check the 3D floor's type...
|
||||
if (rover->flags & FF_BLOCKPLAYER)
|
||||
{
|
||||
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == top));
|
||||
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottom));
|
||||
// Thing must be on top of the floor to be affected...
|
||||
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
|
||||
{
|
||||
if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != top)
|
||||
return false;
|
||||
}
|
||||
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
|
||||
{
|
||||
if (!(mo->eflags & MFE_VERTICALFLIP)
|
||||
|| mo->z + mo->height != bottom)
|
||||
return false;
|
||||
}
|
||||
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
|
||||
{
|
||||
if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottom)
|
||||
|| (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == top)))
|
||||
return false;
|
||||
}
|
||||
if (!(floorallowed || ceilingallowed))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4345,10 +4303,10 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar
|
|||
//
|
||||
static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec)
|
||||
{
|
||||
if (mo->eflags & MFE_VERTICALFLIP)
|
||||
return (mo->z+mo->height == P_GetSpecialTopZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_CEILING);
|
||||
else
|
||||
return (mo->z == P_GetSpecialBottomZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_FLOOR);
|
||||
boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == P_GetSpecialBottomZ(mo, sec, sec)));
|
||||
boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == P_GetSpecialTopZ(mo, sec, sec)));
|
||||
// Thing must be on top of the floor to be affected...
|
||||
return (floorallowed || ceilingallowed);
|
||||
}
|
||||
|
||||
/** Applies a sector special to a player.
|
||||
|
@ -5312,27 +5270,12 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo)
|
|||
if (((rover->flags & FF_BLOCKPLAYER) && mo->player)
|
||||
|| ((rover->flags & FF_BLOCKOTHERS) && !mo->player))
|
||||
{
|
||||
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight));
|
||||
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight));
|
||||
// Thing must be on top of the floor to be affected...
|
||||
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
|
||||
{
|
||||
if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != topheight)
|
||||
if (!(floorallowed || ceilingallowed))
|
||||
continue;
|
||||
}
|
||||
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
|
||||
{
|
||||
if (!(mo->eflags & MFE_VERTICALFLIP)
|
||||
|| mo->z + mo->height != bottomheight)
|
||||
continue;
|
||||
}
|
||||
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
|
||||
{
|
||||
if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottomheight)
|
||||
|| (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == topheight)))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Water and intangible FOFs
|
||||
|
@ -5374,27 +5317,12 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector)
|
|||
// Check the 3D floor's type...
|
||||
if (rover->flags & FF_BLOCKPLAYER)
|
||||
{
|
||||
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight));
|
||||
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight));
|
||||
// Thing must be on top of the floor to be affected...
|
||||
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
|
||||
{
|
||||
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight)
|
||||
if (!(floorallowed || ceilingallowed))
|
||||
continue;
|
||||
}
|
||||
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
|
||||
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
|
||||
{
|
||||
if (!(player->mo->eflags & MFE_VERTICALFLIP)
|
||||
|| player->mo->z + player->mo->height != bottomheight)
|
||||
continue;
|
||||
}
|
||||
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
|
||||
{
|
||||
if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight)
|
||||
|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight)))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Water and DEATH FOG!!! heh
|
||||
|
@ -5450,40 +5378,18 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector)
|
|||
}
|
||||
|
||||
if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking
|
||||
{
|
||||
}
|
||||
;
|
||||
else if (po->flags & POF_SOLID)
|
||||
{
|
||||
boolean floorallowed = ((polysec->flags & SF_FLIPSPECIAL_FLOOR) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == polysec->ceilingheight));
|
||||
boolean ceilingallowed = ((polysec->flags & SF_FLIPSPECIAL_CEILING) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == polysec->floorheight));
|
||||
// Thing must be on top of the floor to be affected...
|
||||
if ((polysec->flags & SF_FLIPSPECIAL_FLOOR)
|
||||
&& !(polysec->flags & SF_FLIPSPECIAL_CEILING))
|
||||
{
|
||||
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != polysec->ceilingheight)
|
||||
if (!(floorallowed || ceilingallowed))
|
||||
{
|
||||
po = (polyobj_t *)(po->link.next);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ((polysec->flags & SF_FLIPSPECIAL_CEILING)
|
||||
&& !(polysec->flags & SF_FLIPSPECIAL_FLOOR))
|
||||
{
|
||||
if (!(player->mo->eflags & MFE_VERTICALFLIP)
|
||||
|| player->mo->z + player->mo->height != polysec->floorheight)
|
||||
{
|
||||
po = (polyobj_t *)(po->link.next);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (polysec->flags & SF_FLIPSPECIAL_BOTH)
|
||||
{
|
||||
if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == polysec->floorheight)
|
||||
|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == polysec->ceilingheight)))
|
||||
{
|
||||
po = (polyobj_t *)(po->link.next);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Water and DEATH FOG!!! heh
|
||||
|
@ -5580,17 +5486,13 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector)
|
|||
f_affectpoint = P_GetSpecialBottomZ(player->mo, sector, sector);
|
||||
c_affectpoint = P_GetSpecialTopZ(player->mo, sector, sector);
|
||||
|
||||
// Only go further if on the ground
|
||||
if ((sector->flags & SF_FLIPSPECIAL_FLOOR) && !(sector->flags & SF_FLIPSPECIAL_CEILING) && player->mo->z != f_affectpoint)
|
||||
return;
|
||||
|
||||
if ((sector->flags & SF_FLIPSPECIAL_CEILING) && !(sector->flags & SF_FLIPSPECIAL_FLOOR) && player->mo->z + player->mo->height != c_affectpoint)
|
||||
return;
|
||||
|
||||
if ((sector->flags & SF_FLIPSPECIAL_BOTH)
|
||||
&& player->mo->z != f_affectpoint
|
||||
&& player->mo->z + player->mo->height != c_affectpoint)
|
||||
{
|
||||
boolean floorallowed = ((sector->flags & SF_FLIPSPECIAL_FLOOR) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == f_affectpoint));
|
||||
boolean ceilingallowed = ((sector->flags & SF_FLIPSPECIAL_CEILING) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == c_affectpoint));
|
||||
// Thing must be on top of the floor to be affected...
|
||||
if (!(floorallowed || ceilingallowed))
|
||||
return;
|
||||
}
|
||||
|
||||
P_ProcessSpecialSector(player, sector, NULL);
|
||||
}
|
||||
|
@ -6085,8 +5987,6 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
|
|||
* to the lowest nearby height if not
|
||||
* there already.
|
||||
*
|
||||
* Replaces the old "AirBob".
|
||||
*
|
||||
* \param sec Control sector.
|
||||
* \param actionsector Target sector.
|
||||
* \param sourceline Control linedef.
|
||||
|
@ -6131,8 +6031,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
|
|||
raise->sourceline = sourceline;
|
||||
}
|
||||
|
||||
// Function to maintain backwards compatibility
|
||||
static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
|
||||
static void P_AddAirbob(sector_t *sec, line_t *sourceline, boolean noadjust, boolean dynamic)
|
||||
{
|
||||
levelspecthink_t *airbob;
|
||||
|
||||
|
@ -6170,6 +6069,8 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
|
|||
airbob->vars[4] = airbob->vars[5]
|
||||
- (sec->ceilingheight - sec->floorheight);
|
||||
|
||||
airbob->vars[9] = dynamic ? 1 : 0;
|
||||
|
||||
airbob->sourceline = sourceline;
|
||||
}
|
||||
|
||||
|
@ -6683,6 +6584,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
|
||||
if (lines[i].flags & ML_EFFECT3)
|
||||
sectors[s].flags |= SF_TRIGGERSPECIAL_TOUCH;
|
||||
if (lines[i].flags & ML_EFFECT2)
|
||||
sectors[s].flags |= SF_TRIGGERSPECIAL_HEADBUMP;
|
||||
|
||||
if (lines[i].flags & ML_EFFECT1)
|
||||
sectors[s].flags |= SF_INVERTPRECIP;
|
||||
|
||||
if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12)
|
||||
sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors;
|
||||
|
@ -6987,11 +6893,16 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
case 151: // Adjustable air bobbing platform
|
||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
|
||||
lines[i].flags |= ML_BLOCKMONSTERS;
|
||||
P_AddOldAirbob(lines[i].frontsector, lines + i, (lines[i].special != 151));
|
||||
P_AddAirbob(lines[i].frontsector, lines + i, (lines[i].special != 151), false);
|
||||
break;
|
||||
case 152: // Adjustable air bobbing platform in reverse
|
||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
|
||||
P_AddOldAirbob(lines[i].frontsector, lines + i, true);
|
||||
P_AddAirbob(lines[i].frontsector, lines + i, true, false);
|
||||
break;
|
||||
case 153: // Dynamic Sinking Platform
|
||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
|
||||
lines[i].flags |= ML_BLOCKMONSTERS;
|
||||
P_AddAirbob(lines[i].frontsector, lines + i, false, true);
|
||||
break;
|
||||
|
||||
case 160: // Float/bob platform
|
||||
|
@ -7042,14 +6953,14 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
case 176: // Air bobbing platform that will crumble and bob on the water when it falls and hits
|
||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers);
|
||||
lines[i].flags |= ML_BLOCKMONSTERS;
|
||||
P_AddOldAirbob(lines[i].frontsector, lines + i, true);
|
||||
P_AddAirbob(lines[i].frontsector, lines + i, true, false);
|
||||
break;
|
||||
|
||||
case 177: // Air bobbing platform that will crumble and bob on
|
||||
// the water when it falls and hits, then never return
|
||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB|FF_CRUMBLE|FF_NORETURN, secthinkers);
|
||||
lines[i].flags |= ML_BLOCKMONSTERS;
|
||||
P_AddOldAirbob(lines[i].frontsector, lines + i, true);
|
||||
P_AddAirbob(lines[i].frontsector, lines + i, true, false);
|
||||
break;
|
||||
|
||||
case 178: // Crumbling platform that will float when it hits water
|
||||
|
@ -7063,7 +6974,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
case 180: // Air bobbing platform that will crumble
|
||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE, secthinkers);
|
||||
lines[i].flags |= ML_BLOCKMONSTERS;
|
||||
P_AddOldAirbob(lines[i].frontsector, lines + i, true);
|
||||
P_AddAirbob(lines[i].frontsector, lines + i, true, false);
|
||||
break;
|
||||
|
||||
case 190: // Rising Platform FOF (solid, opaque, shadows)
|
||||
|
@ -7171,21 +7082,21 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
break;
|
||||
|
||||
case 252: // Shatter block (breaks when touched)
|
||||
ffloorflags = FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER;
|
||||
ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER;
|
||||
if (lines[i].flags & ML_NOCLIMB)
|
||||
ffloorflags |= FF_SOLID|FF_SHATTERBOTTOM;
|
||||
ffloorflags |= FF_BLOCKPLAYER|FF_SHATTERBOTTOM;
|
||||
|
||||
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
|
||||
break;
|
||||
|
||||
case 253: // Translucent shatter block (see 76)
|
||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_TRANSLUCENT, secthinkers);
|
||||
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_TRANSLUCENT, secthinkers);
|
||||
break;
|
||||
|
||||
case 254: // Bustable block
|
||||
ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP;
|
||||
if (lines[i].flags & ML_NOCLIMB)
|
||||
ffloorflags |= FF_ONLYKNUX;
|
||||
ffloorflags |= FF_STRONGBUST;
|
||||
|
||||
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
|
||||
break;
|
||||
|
|
|
@ -482,7 +482,7 @@ static inline void P_DoSpecialStageStuff(void)
|
|||
countspheres += players[i].spheres;
|
||||
|
||||
// If in water, deplete timer 6x as fast.
|
||||
if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
|
||||
if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & SH_PROTECTWATER))
|
||||
players[i].nightstime -= 5;
|
||||
if (--players[i].nightstime > 6)
|
||||
{
|
||||
|
|
639
src/p_user.c
639
src/p_user.c
File diff suppressed because it is too large
Load diff
360
src/r_data.c
360
src/r_data.c
|
@ -35,7 +35,7 @@
|
|||
#endif
|
||||
|
||||
// Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog
|
||||
#ifdef _WIN32_WCE
|
||||
#if 0
|
||||
#define AVOID_ERRNO
|
||||
#else
|
||||
#include <errno.h>
|
||||
|
@ -483,7 +483,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
|||
wadnum = patch->wad;
|
||||
lumpnum = patch->lump;
|
||||
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
|
||||
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); // can't use W_CachePatchNumPwad because OpenGL
|
||||
|
||||
#ifndef NO_PNG_LUMPS
|
||||
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
|
||||
|
@ -557,7 +557,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
|||
texturememory += blocksize;
|
||||
block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]);
|
||||
|
||||
memset(block, 0xFF, blocksize+1); // Transparency hack
|
||||
memset(block, TRANSPARENTPIXEL, blocksize+1); // Transparency hack
|
||||
|
||||
// columns lookup table
|
||||
colofs = (UINT32 *)(void *)block;
|
||||
|
@ -2520,7 +2520,11 @@ void R_PrecacheLevel(void)
|
|||
"spritememory: %s k\n", sizeu1(flatmemory>>10), sizeu2(texturememory>>10), sizeu3(spritememory>>10));
|
||||
}
|
||||
|
||||
// https://github.com/coelckers/prboom-plus/blob/master/prboom2/src/r_patch.c#L350
|
||||
//
|
||||
// R_CheckIfPatch
|
||||
//
|
||||
// Returns true if the lump is a valid patch.
|
||||
//
|
||||
boolean R_CheckIfPatch(lumpnum_t lump)
|
||||
{
|
||||
size_t size;
|
||||
|
@ -2565,6 +2569,71 @@ boolean R_CheckIfPatch(lumpnum_t lump)
|
|||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// R_TextureToFlat
|
||||
//
|
||||
// Convert a texture to a flat.
|
||||
//
|
||||
void R_TextureToFlat(size_t tex, UINT8 *flat)
|
||||
{
|
||||
texture_t *texture = textures[tex];
|
||||
|
||||
fixed_t col, ofs;
|
||||
column_t *column;
|
||||
UINT8 *desttop, *dest, *deststop;
|
||||
UINT8 *source;
|
||||
|
||||
// yea
|
||||
R_CheckTextureCache(tex);
|
||||
|
||||
desttop = flat;
|
||||
deststop = desttop + (texture->width * texture->height);
|
||||
|
||||
for (col = 0; col < texture->width; col++, desttop++)
|
||||
{
|
||||
// no post_t info
|
||||
if (!texture->holes)
|
||||
{
|
||||
column = (column_t *)(R_GetColumn(tex, col));
|
||||
source = (UINT8 *)(column);
|
||||
dest = desttop;
|
||||
for (ofs = 0; dest < deststop && ofs < texture->height; ofs++)
|
||||
{
|
||||
if (source[ofs] != TRANSPARENTPIXEL)
|
||||
*dest = source[ofs];
|
||||
dest += texture->width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 topdelta, prevdelta = -1;
|
||||
column = (column_t *)((UINT8 *)R_GetColumn(tex, col) - 3);
|
||||
while (column->topdelta != 0xff)
|
||||
{
|
||||
topdelta = column->topdelta;
|
||||
if (topdelta <= prevdelta)
|
||||
topdelta += prevdelta;
|
||||
prevdelta = topdelta;
|
||||
|
||||
dest = desttop + (topdelta * texture->width);
|
||||
source = (UINT8 *)column + 3;
|
||||
for (ofs = 0; dest < deststop && ofs < column->length; ofs++)
|
||||
{
|
||||
if (source[ofs] != TRANSPARENTPIXEL)
|
||||
*dest = source[ofs];
|
||||
dest += texture->width;
|
||||
}
|
||||
column = (column_t *)((UINT8 *)column + column->length + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// R_PatchToFlat
|
||||
//
|
||||
// Convert a patch to a flat.
|
||||
//
|
||||
void R_PatchToFlat(patch_t *patch, UINT8 *flat)
|
||||
{
|
||||
fixed_t col, ofs;
|
||||
|
@ -2599,7 +2668,124 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// R_FlatToPatch
|
||||
//
|
||||
// Convert a flat to a patch.
|
||||
//
|
||||
static unsigned char imgbuf[1<<26];
|
||||
patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency)
|
||||
{
|
||||
UINT32 x, y;
|
||||
UINT8 *img;
|
||||
UINT8 *imgptr = imgbuf;
|
||||
UINT8 *colpointers, *startofspan;
|
||||
size_t size = 0;
|
||||
|
||||
// Write image size and offset
|
||||
WRITEINT16(imgptr, width);
|
||||
WRITEINT16(imgptr, height);
|
||||
WRITEINT16(imgptr, leftoffset);
|
||||
WRITEINT16(imgptr, topoffset);
|
||||
|
||||
// Leave placeholder to column pointers
|
||||
colpointers = imgptr;
|
||||
imgptr += width*4;
|
||||
|
||||
// Write columns
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
int lastStartY = 0;
|
||||
int spanSize = 0;
|
||||
startofspan = NULL;
|
||||
|
||||
// Write column pointer
|
||||
WRITEINT32(colpointers, imgptr - imgbuf);
|
||||
|
||||
// Write pixels
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
UINT8 paletteIndex = raw[((y * width) + x)];
|
||||
boolean opaque = transparency ? (paletteIndex != TRANSPARENTPIXEL) : true;
|
||||
|
||||
// End span if we have a transparent pixel
|
||||
if (!opaque)
|
||||
{
|
||||
if (startofspan)
|
||||
WRITEUINT8(imgptr, 0);
|
||||
startofspan = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start new column if we need to
|
||||
if (!startofspan || spanSize == 255)
|
||||
{
|
||||
int writeY = y;
|
||||
|
||||
// If we reached the span size limit, finish the previous span
|
||||
if (startofspan)
|
||||
WRITEUINT8(imgptr, 0);
|
||||
|
||||
if (y > 254)
|
||||
{
|
||||
// Make sure we're aligned to 254
|
||||
if (lastStartY < 254)
|
||||
{
|
||||
WRITEUINT8(imgptr, 254);
|
||||
WRITEUINT8(imgptr, 0);
|
||||
imgptr += 2;
|
||||
lastStartY = 254;
|
||||
}
|
||||
|
||||
// Write stopgap empty spans if needed
|
||||
writeY = y - lastStartY;
|
||||
|
||||
while (writeY > 254)
|
||||
{
|
||||
WRITEUINT8(imgptr, 254);
|
||||
WRITEUINT8(imgptr, 0);
|
||||
imgptr += 2;
|
||||
writeY -= 254;
|
||||
}
|
||||
}
|
||||
|
||||
startofspan = imgptr;
|
||||
WRITEUINT8(imgptr, writeY);
|
||||
imgptr += 2;
|
||||
spanSize = 0;
|
||||
|
||||
lastStartY = y;
|
||||
}
|
||||
|
||||
// Write the pixel
|
||||
WRITEUINT8(imgptr, paletteIndex);
|
||||
spanSize++;
|
||||
startofspan[1] = spanSize;
|
||||
}
|
||||
|
||||
if (startofspan)
|
||||
WRITEUINT8(imgptr, 0);
|
||||
|
||||
WRITEUINT8(imgptr, 0xFF);
|
||||
}
|
||||
|
||||
size = imgptr-imgbuf;
|
||||
img = Z_Malloc(size, PU_STATIC, NULL);
|
||||
memcpy(img, imgbuf, size);
|
||||
|
||||
Z_Free(raw);
|
||||
|
||||
if (destsize != NULL)
|
||||
*destsize = size;
|
||||
return (patch_t *)img;
|
||||
}
|
||||
|
||||
#ifndef NO_PNG_LUMPS
|
||||
//
|
||||
// R_IsLumpPNG
|
||||
//
|
||||
// Returns true if the lump is a valid PNG.
|
||||
//
|
||||
boolean R_IsLumpPNG(const UINT8 *d, size_t s)
|
||||
{
|
||||
if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/
|
||||
|
@ -2812,125 +2998,31 @@ static UINT8 *PNG_RawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topo
|
|||
return flat;
|
||||
}
|
||||
|
||||
//
|
||||
// R_PNGToFlat
|
||||
//
|
||||
// Convert a PNG to a flat.
|
||||
UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size)
|
||||
//
|
||||
UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size)
|
||||
{
|
||||
return PNG_RawConvert(png, &levelflat->width, &levelflat->height, NULL, NULL, size);
|
||||
return PNG_RawConvert(png, width, height, NULL, NULL, size);
|
||||
}
|
||||
|
||||
//
|
||||
// R_PNGToPatch
|
||||
//
|
||||
// Convert a PNG to a patch.
|
||||
static unsigned char imgbuf[1<<26];
|
||||
//
|
||||
patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency)
|
||||
{
|
||||
UINT16 width, height;
|
||||
INT16 topoffset = 0, leftoffset = 0;
|
||||
UINT8 *raw = PNG_RawConvert(png, &width, &height, &topoffset, &leftoffset, size);
|
||||
|
||||
UINT32 x, y;
|
||||
UINT8 *img;
|
||||
UINT8 *imgptr = imgbuf;
|
||||
UINT8 *colpointers, *startofspan;
|
||||
|
||||
if (!raw)
|
||||
I_Error("R_PNGToPatch: conversion failed");
|
||||
|
||||
// Write image size and offset
|
||||
WRITEINT16(imgptr, width);
|
||||
WRITEINT16(imgptr, height);
|
||||
WRITEINT16(imgptr, leftoffset);
|
||||
WRITEINT16(imgptr, topoffset);
|
||||
|
||||
// Leave placeholder to column pointers
|
||||
colpointers = imgptr;
|
||||
imgptr += width*4;
|
||||
|
||||
// Write columns
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
int lastStartY = 0;
|
||||
int spanSize = 0;
|
||||
startofspan = NULL;
|
||||
|
||||
//printf("%d ", x);
|
||||
// Write column pointer (@TODO may be wrong)
|
||||
WRITEINT32(colpointers, imgptr - imgbuf);
|
||||
|
||||
// Write pixels
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
UINT8 paletteIndex = raw[((y * width) + x)];
|
||||
boolean opaque = transparency ? (paletteIndex != TRANSPARENTPIXEL) : true;
|
||||
|
||||
// End span if we have a transparent pixel
|
||||
if (!opaque)
|
||||
{
|
||||
if (startofspan)
|
||||
WRITEUINT8(imgptr, 0);
|
||||
startofspan = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start new column if we need to
|
||||
if (!startofspan || spanSize == 255)
|
||||
{
|
||||
int writeY = y;
|
||||
|
||||
// If we reached the span size limit, finish the previous span
|
||||
if (startofspan)
|
||||
WRITEUINT8(imgptr, 0);
|
||||
|
||||
if (y > 254)
|
||||
{
|
||||
// Make sure we're aligned to 254
|
||||
if (lastStartY < 254)
|
||||
{
|
||||
WRITEUINT8(imgptr, 254);
|
||||
WRITEUINT8(imgptr, 0);
|
||||
imgptr += 2;
|
||||
lastStartY = 254;
|
||||
}
|
||||
|
||||
// Write stopgap empty spans if needed
|
||||
writeY = y - lastStartY;
|
||||
|
||||
while (writeY > 254)
|
||||
{
|
||||
WRITEUINT8(imgptr, 254);
|
||||
WRITEUINT8(imgptr, 0);
|
||||
imgptr += 2;
|
||||
writeY -= 254;
|
||||
}
|
||||
}
|
||||
|
||||
startofspan = imgptr;
|
||||
WRITEUINT8(imgptr, writeY);///@TODO calculate starting y pos
|
||||
imgptr += 2;
|
||||
spanSize = 0;
|
||||
|
||||
lastStartY = y;
|
||||
}
|
||||
|
||||
// Write the pixel
|
||||
WRITEUINT8(imgptr, paletteIndex);
|
||||
spanSize++;
|
||||
startofspan[1] = spanSize;
|
||||
}
|
||||
|
||||
if (startofspan)
|
||||
WRITEUINT8(imgptr, 0);
|
||||
|
||||
WRITEUINT8(imgptr, 0xFF);
|
||||
}
|
||||
|
||||
size = imgptr-imgbuf;
|
||||
img = Z_Malloc(size, PU_STATIC, NULL);
|
||||
memcpy(img, imgbuf, size);
|
||||
|
||||
Z_Free(raw);
|
||||
|
||||
if (destsize != NULL)
|
||||
*destsize = size;
|
||||
return (patch_t *)img;
|
||||
return R_FlatToPatch(raw, width, height, leftoffset, topoffset, destsize, transparency);
|
||||
}
|
||||
|
||||
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size)
|
||||
|
@ -3001,53 +3093,3 @@ boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size)
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void R_TextureToFlat(size_t tex, UINT8 *flat)
|
||||
{
|
||||
texture_t *texture = textures[tex];
|
||||
|
||||
fixed_t col, ofs;
|
||||
column_t *column;
|
||||
UINT8 *desttop, *dest, *deststop;
|
||||
UINT8 *source;
|
||||
|
||||
desttop = flat;
|
||||
deststop = desttop + (texture->width * texture->height);
|
||||
|
||||
for (col = 0; col < texture->width; col++, desttop++)
|
||||
{
|
||||
column = (column_t *)R_GetColumn(tex, col);
|
||||
if (!texture->holes)
|
||||
{
|
||||
dest = desttop;
|
||||
source = (UINT8 *)(column);
|
||||
for (ofs = 0; dest < deststop && ofs < texture->height; ofs++)
|
||||
{
|
||||
if (source[ofs] != TRANSPARENTPIXEL)
|
||||
*dest = source[ofs];
|
||||
dest += texture->width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 topdelta, prevdelta = -1;
|
||||
while (column->topdelta != 0xff)
|
||||
{
|
||||
topdelta = column->topdelta;
|
||||
if (topdelta <= prevdelta)
|
||||
topdelta += prevdelta;
|
||||
prevdelta = topdelta;
|
||||
|
||||
dest = desttop + (topdelta * texture->width);
|
||||
source = (UINT8 *)(column) + 3;
|
||||
for (ofs = 0; dest < deststop && ofs < column->length; ofs++)
|
||||
{
|
||||
if (source[ofs] != TRANSPARENTPIXEL)
|
||||
*dest = source[ofs];
|
||||
dest += texture->width;
|
||||
}
|
||||
column = (column_t *)((UINT8 *)column + column->length + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,15 +159,14 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap);
|
|||
#define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a))
|
||||
|
||||
boolean R_CheckIfPatch(lumpnum_t lump);
|
||||
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
|
||||
|
||||
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
|
||||
void R_TextureToFlat(size_t tex, UINT8 *flat);
|
||||
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
|
||||
patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency);
|
||||
|
||||
#ifndef NO_PNG_LUMPS
|
||||
boolean R_IsLumpPNG(const UINT8 *d, size_t s);
|
||||
|
||||
UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size);
|
||||
UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size);
|
||||
patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency);
|
||||
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size);
|
||||
#endif
|
||||
|
|
17
src/r_defs.h
17
src/r_defs.h
|
@ -139,9 +139,9 @@ typedef enum
|
|||
FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top.
|
||||
FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
|
||||
FF_INTANGABLEFLATS = 0x6000000, ///< Both flats are intangable, but the sides are still solid.
|
||||
FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Thinks everyone's Knuckles.
|
||||
FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Jump or fall onto it while curled in a ball.
|
||||
FF_ONLYKNUX = 0x20000000, ///< Used with ::FF_BUSTUP. Only Knuckles can break this rock.
|
||||
FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch.
|
||||
FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames.
|
||||
FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee).
|
||||
FF_RIPPLE = 0x40000000, ///< Ripple the flats
|
||||
FF_COLORMAPONLY = 0x80000000, ///< Only copy the colormap, not the lightlevel
|
||||
FF_GOOWATER = FF_SHATTERBOTTOM, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
|
||||
|
@ -263,10 +263,15 @@ typedef struct pslope_s
|
|||
|
||||
typedef enum
|
||||
{
|
||||
// flipspecial - planes with effect
|
||||
SF_FLIPSPECIAL_FLOOR = 1,
|
||||
SF_FLIPSPECIAL_CEILING = 2,
|
||||
SF_FLIPSPECIAL_BOTH = 3,
|
||||
SF_TRIGGERSPECIAL_TOUCH = 4,
|
||||
SF_FLIPSPECIAL_CEILING = 1<<1,
|
||||
SF_FLIPSPECIAL_BOTH = (SF_FLIPSPECIAL_FLOOR|SF_FLIPSPECIAL_CEILING),
|
||||
// triggerspecial - conditions under which plane touch causes effect
|
||||
SF_TRIGGERSPECIAL_TOUCH = 1<<2,
|
||||
SF_TRIGGERSPECIAL_HEADBUMP = 1<<3,
|
||||
// invertprecip - inverts presence of precipitation
|
||||
SF_INVERTPRECIP = 1<<4,
|
||||
} sectorflags_t;
|
||||
|
||||
//
|
||||
|
|
38
src/r_draw.c
38
src/r_draw.c
|
@ -130,10 +130,11 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
|
|||
#define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3)
|
||||
#define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4)
|
||||
#define BLINK_TT_CACHE_INDEX (MAXSKINS + 5)
|
||||
#define DASHMODE_TT_CACHE_INDEX (MAXSKINS + 6)
|
||||
#define DEFAULT_STARTTRANSCOLOR 96
|
||||
#define NUM_PALETTE_ENTRIES 256
|
||||
|
||||
static UINT8** translationtablecache[MAXSKINS + 6] = {NULL};
|
||||
static UINT8** translationtablecache[MAXSKINS + 7] = {NULL};
|
||||
|
||||
const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
|
||||
// {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_NONE
|
||||
|
@ -569,6 +570,40 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
|
|||
dest_colormap[Color_Index[SKINCOLOR_BLUE-1][12-i]] = Color_Index[SKINCOLOR_BLUE-1][i];
|
||||
dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0;
|
||||
}
|
||||
else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices
|
||||
{
|
||||
// greens -> ketchups
|
||||
dest_colormap[96] = dest_colormap[97] = 48;
|
||||
dest_colormap[98] = 49;
|
||||
dest_colormap[99] = 51;
|
||||
dest_colormap[100] = 52;
|
||||
dest_colormap[101] = dest_colormap[102] = 54;
|
||||
dest_colormap[103] = 34;
|
||||
dest_colormap[104] = 37;
|
||||
dest_colormap[105] = 39;
|
||||
dest_colormap[106] = 41;
|
||||
for (i = 0; i < 5; i++)
|
||||
dest_colormap[107 + i] = 43 + i;
|
||||
|
||||
// reds -> steel blues
|
||||
dest_colormap[32] = 146;
|
||||
dest_colormap[33] = 147;
|
||||
dest_colormap[34] = dest_colormap[35] = 170;
|
||||
dest_colormap[36] = 171;
|
||||
dest_colormap[37] = dest_colormap[38] = 172;
|
||||
dest_colormap[39] = dest_colormap[40] = dest_colormap[41] = 173;
|
||||
dest_colormap[42] = dest_colormap[43] = dest_colormap[44] = 174;
|
||||
dest_colormap[45] = dest_colormap[46] = dest_colormap[47] = 175;
|
||||
dest_colormap[71] = 139;
|
||||
|
||||
// steel blues -> oranges
|
||||
dest_colormap[170] = 52;
|
||||
dest_colormap[171] = 54;
|
||||
dest_colormap[172] = 56;
|
||||
dest_colormap[173] = 42;
|
||||
dest_colormap[174] = 45;
|
||||
dest_colormap[175] = 47;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (color == SKINCOLOR_NONE)
|
||||
|
@ -628,6 +663,7 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags)
|
|||
case TC_ALLWHITE: skintableindex = ALLWHITE_TT_CACHE_INDEX; break;
|
||||
case TC_RAINBOW: skintableindex = RAINBOW_TT_CACHE_INDEX; break;
|
||||
case TC_BLINK: skintableindex = BLINK_TT_CACHE_INDEX; break;
|
||||
case TC_DASHMODE: skintableindex = DASHMODE_TT_CACHE_INDEX; break;
|
||||
default: skintableindex = skinnum; break;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ extern lumpnum_t viewborderlump[8];
|
|||
#define TC_ALLWHITE -4 // For Cy-Brak-demon
|
||||
#define TC_RAINBOW -5 // For single colour
|
||||
#define TC_BLINK -6 // For item blinking, according to kart
|
||||
#define TC_DASHMODE -7 // For Metal Sonic's dashmode
|
||||
|
||||
// Initialize color translation tables, for player rendering etc.
|
||||
void R_InitTranslationTables(void);
|
||||
|
|
|
@ -1219,6 +1219,7 @@ void R_RegisterEngineStuff(void)
|
|||
#endif
|
||||
CV_RegisterVar(&cv_grmd2);
|
||||
CV_RegisterVar(&cv_grspritebillboarding);
|
||||
CV_RegisterVar(&cv_grskydome);
|
||||
#endif
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
// Quincunx antialiasing of flats!
|
||||
//#define QUINCUNX
|
||||
|
||||
// good night sweet prince
|
||||
#define SHITPLANESPARENCY
|
||||
|
||||
//SoM: 3/23/2000: Use Boom visplane hashing.
|
||||
|
||||
visplane_t *visplanes[MAXVISPLANES];
|
||||
|
@ -650,6 +653,11 @@ static void R_DrawSkyPlane(visplane_t *pl)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// R_CheckPowersOfTwo
|
||||
//
|
||||
// Self-explanatory?
|
||||
//
|
||||
boolean R_CheckPowersOfTwo(void)
|
||||
{
|
||||
boolean wpow2 = (!(ds_flatwidth & (ds_flatwidth - 1)));
|
||||
|
@ -667,6 +675,11 @@ boolean R_CheckPowersOfTwo(void)
|
|||
return ds_powersoftwo;
|
||||
}
|
||||
|
||||
//
|
||||
// R_CheckFlatLength
|
||||
//
|
||||
// Determine the flat's dimensions from the lump length.
|
||||
//
|
||||
void R_CheckFlatLength(size_t size)
|
||||
{
|
||||
switch (size)
|
||||
|
@ -723,7 +736,24 @@ void R_CheckFlatLength(size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
|
||||
//
|
||||
// R_GenerateFlat
|
||||
//
|
||||
// Generate a flat from specified width and height.
|
||||
//
|
||||
static UINT8 *R_GenerateFlat(UINT16 width, UINT16 height)
|
||||
{
|
||||
UINT8 *flat = Z_Malloc(width * height, PU_LEVEL, NULL);
|
||||
memset(flat, TRANSPARENTPIXEL, width * height);
|
||||
return flat;
|
||||
}
|
||||
|
||||
//
|
||||
// R_GetTextureFlat
|
||||
//
|
||||
// Convert a texture or patch to a flat.
|
||||
//
|
||||
static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
|
||||
{
|
||||
UINT8 *flat;
|
||||
textureflat_t *texflat = &texflats[levelflat->texturenum];
|
||||
|
@ -747,14 +777,14 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole
|
|||
// If the texture changed, or the patch doesn't exist, convert either of them to a flat.
|
||||
if (levelflat->flatpatch == NULL || texturechanged)
|
||||
{
|
||||
// Level texture
|
||||
if (leveltexture)
|
||||
{
|
||||
texture_t *texture = textures[levelflat->texturenum];
|
||||
texflat->width = ds_flatwidth = texture->width;
|
||||
texflat->height = ds_flatheight = texture->height;
|
||||
|
||||
texflat->flat = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
|
||||
memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
|
||||
texflat->flat = R_GenerateFlat(ds_flatwidth, ds_flatheight);
|
||||
R_TextureToFlat(levelflat->texturenum, texflat->flat);
|
||||
flat = texflat->flat;
|
||||
|
||||
|
@ -762,13 +792,14 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole
|
|||
levelflat->width = ds_flatwidth;
|
||||
levelflat->height = ds_flatheight;
|
||||
}
|
||||
// Patch (never happens yet)
|
||||
else
|
||||
{
|
||||
patch = (patch_t *)ds_source;
|
||||
#ifndef NO_PNG_LUMPS
|
||||
if (ispng)
|
||||
{
|
||||
levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum));
|
||||
levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->lumpnum));
|
||||
levelflat->topoffset = levelflat->leftoffset = 0;
|
||||
ds_flatwidth = levelflat->width;
|
||||
ds_flatheight = levelflat->height;
|
||||
|
@ -782,8 +813,7 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole
|
|||
levelflat->topoffset = patch->topoffset * FRACUNIT;
|
||||
levelflat->leftoffset = patch->leftoffset * FRACUNIT;
|
||||
|
||||
levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
|
||||
memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
|
||||
levelflat->flatpatch = R_GenerateFlat(ds_flatwidth, ds_flatheight);
|
||||
R_PatchToFlat(patch, levelflat->flatpatch);
|
||||
}
|
||||
flat = levelflat->flatpatch;
|
||||
|
@ -794,10 +824,10 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole
|
|||
flat = levelflat->flatpatch;
|
||||
ds_flatwidth = levelflat->width;
|
||||
ds_flatheight = levelflat->height;
|
||||
}
|
||||
|
||||
xoffs += levelflat->leftoffset;
|
||||
yoffs += levelflat->topoffset;
|
||||
}
|
||||
|
||||
levelflat->lasttexturenum = levelflat->texturenum;
|
||||
return flat;
|
||||
|
@ -841,7 +871,11 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
else // Opaque, but allow transparent flat pixels
|
||||
spanfunc = splatfunc;
|
||||
|
||||
#ifdef SHITPLANESPARENCY
|
||||
if ((spanfunc == splatfunc) != (pl->extra_colormap && (pl->extra_colormap->fog & 4)))
|
||||
#else
|
||||
if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2))
|
||||
#endif
|
||||
light = (pl->lightlevel >> LIGHTSEGSHIFT);
|
||||
else
|
||||
light = LIGHTLEVELS-1;
|
||||
|
@ -895,7 +929,11 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
else // Opaque, but allow transparent flat pixels
|
||||
spanfunc = splatfunc;
|
||||
|
||||
#ifdef SHITPLANESPARENCY
|
||||
if ((spanfunc == splatfunc) != (pl->extra_colormap && (pl->extra_colormap->fog & 4)))
|
||||
#else
|
||||
if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2))
|
||||
#endif
|
||||
light = (pl->lightlevel >> LIGHTSEGSHIFT);
|
||||
else
|
||||
light = LIGHTLEVELS-1;
|
||||
|
@ -963,15 +1001,15 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
|
||||
// Check if the flat is actually a wall texture.
|
||||
if (levelflat->texturenum != 0 && levelflat->texturenum != -1)
|
||||
flat = R_GetPatchFlat(levelflat, true, false);
|
||||
flat = R_GetTextureFlat(levelflat, true, false);
|
||||
#ifndef NO_PNG_LUMPS
|
||||
// Maybe it's a PNG?!
|
||||
else if (R_IsLumpPNG(ds_source, size))
|
||||
flat = R_GetPatchFlat(levelflat, false, true);
|
||||
flat = R_GetTextureFlat(levelflat, false, true);
|
||||
#endif
|
||||
// Maybe it's just a patch, then?
|
||||
else if (R_CheckIfPatch(levelflat->lumpnum))
|
||||
flat = R_GetPatchFlat(levelflat, false, false);
|
||||
flat = R_GetTextureFlat(levelflat, false, false);
|
||||
// It's a raw flat.
|
||||
else
|
||||
{
|
||||
|
@ -1075,7 +1113,7 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy);
|
||||
zeroheight = FIXED_TO_FLOAT(temp);
|
||||
|
||||
#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180)
|
||||
#define ANG2RAD(angle) ((float)((angle)*M_PIl)/ANGLE_180)
|
||||
|
||||
// p is the texture origin in view space
|
||||
// Don't add in the offsets at this stage, because doing so can result in
|
||||
|
|
|
@ -753,6 +753,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
dc_transmap = vis->transmap;
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
|
||||
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
|
||||
else if (!(vis->cut & SC_PRECIP)
|
||||
&& vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD
|
||||
&& (vis->mobj->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
|
||||
&& ((leveltime/2) & 1))
|
||||
{
|
||||
dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE);
|
||||
}
|
||||
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_>
|
||||
{
|
||||
size_t skinnum = (skin_t*)vis->mobj->skin-skins;
|
||||
|
@ -774,6 +781,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
// New colormap stuff for skins Tails 06-07-2002
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
|
||||
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
|
||||
else if (!(vis->cut & SC_PRECIP)
|
||||
&& vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD
|
||||
&& (vis->mobj->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
|
||||
&& ((leveltime/2) & 1))
|
||||
{
|
||||
dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE);
|
||||
}
|
||||
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
|
||||
{
|
||||
size_t skinnum = (skin_t*)vis->mobj->skin-skins;
|
||||
|
@ -1230,7 +1244,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
else
|
||||
range = 1;
|
||||
|
||||
scalestep = (yscale2 - yscale)/range;
|
||||
scalestep = (yscale2 - yscale)/range ?: 1;
|
||||
|
||||
// The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2?
|
||||
// sortscale = max(yscale, yscale2);
|
||||
|
@ -1637,7 +1651,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
|
|||
mobj_t *thing;
|
||||
precipmobj_t *precipthing; // Tails 08-25-2002
|
||||
INT32 lightnum;
|
||||
fixed_t approx_dist, limit_dist;
|
||||
fixed_t approx_dist, limit_dist, hoop_limit_dist;
|
||||
|
||||
if (rendermode != render_soft)
|
||||
return;
|
||||
|
@ -1668,7 +1682,9 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
|
|||
|
||||
// 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)
|
||||
{
|
||||
|
@ -1677,8 +1693,16 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
|
|||
|
||||
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
|
||||
|
||||
if (approx_dist > limit_dist)
|
||||
if (thing->sprite == SPR_HOOP)
|
||||
{
|
||||
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (limit_dist && approx_dist > limit_dist)
|
||||
continue;
|
||||
}
|
||||
|
||||
R_ProjectSprite(thing);
|
||||
}
|
||||
|
@ -2786,9 +2810,9 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
}
|
||||
|
||||
if (P_IsLocalPlayer(player))
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Requested skin not found\n"));
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum);
|
||||
else if(server || IsPlayerAdmin(consoleplayer))
|
||||
CONS_Alert(CONS_WARNING, "Player %d (%s) skin not found\n", playernum, player_names[playernum]);
|
||||
CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum);
|
||||
SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,10 @@ consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_O
|
|||
consvar_t cv_gamemidimusic = {"midimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameMIDIMusic_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_gamesounds = {"sounds", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameSounds_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// Window focus sound sytem toggles
|
||||
consvar_t cv_playmusicifunfocused = {"playmusicifunfocused", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_playsoundsifunfocused = {"playsoundsifunfocused", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
#ifdef HAVE_OPENMPT
|
||||
static CV_PossibleValue_t interpolationfilter_cons_t[] = {{0, "Default"}, {1, "None"}, {2, "Linear"}, {4, "Cubic"}, {8, "Windowed sinc"}, {0, NULL}};
|
||||
consvar_t cv_modfilter = {"modfilter", "0", CV_SAVE|CV_CALL, interpolationfilter_cons_t, ModFilter_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -278,6 +282,8 @@ void S_RegisterSoundStuff(void)
|
|||
CV_RegisterVar(&cv_samplerate);
|
||||
CV_RegisterVar(&cv_resetmusic);
|
||||
CV_RegisterVar(&cv_resetmusicbyheader);
|
||||
CV_RegisterVar(&cv_playsoundsifunfocused);
|
||||
CV_RegisterVar(&cv_playmusicifunfocused);
|
||||
CV_RegisterVar(&cv_gamesounds);
|
||||
CV_RegisterVar(&cv_gamedigimusic);
|
||||
CV_RegisterVar(&cv_gamemidimusic);
|
||||
|
@ -373,6 +379,18 @@ lumpnum_t S_GetSfxLumpNum(sfxinfo_t *sfx)
|
|||
return W_GetNumForName("dsthok");
|
||||
}
|
||||
|
||||
//
|
||||
// Sound Status
|
||||
//
|
||||
|
||||
boolean S_SoundDisabled(void)
|
||||
{
|
||||
return (
|
||||
sound_disabled ||
|
||||
( window_notinfocus && ! cv_playsoundsifunfocused.value )
|
||||
);
|
||||
}
|
||||
|
||||
// Stop all sounds, load level info, THEN start sounds.
|
||||
void S_StopSounds(void)
|
||||
{
|
||||
|
@ -540,7 +558,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
|
|||
mobj_t *listenmobj = players[displayplayer].mo;
|
||||
mobj_t *listenmobj2 = NULL;
|
||||
|
||||
if (sound_disabled || !sound_started)
|
||||
if (S_SoundDisabled() || !sound_started)
|
||||
return;
|
||||
|
||||
// Don't want a sound? Okay then...
|
||||
|
@ -730,7 +748,7 @@ dontplay:
|
|||
|
||||
void S_StartSound(const void *origin, sfxenum_t sfx_id)
|
||||
{
|
||||
if (sound_disabled)
|
||||
if (S_SoundDisabled())
|
||||
return;
|
||||
|
||||
if (mariomode) // Sounds change in Mario mode!
|
||||
|
@ -1434,6 +1452,13 @@ boolean S_MusicPaused(void)
|
|||
return I_SongPaused();
|
||||
}
|
||||
|
||||
boolean S_MusicNotInFocus(void)
|
||||
{
|
||||
return (
|
||||
( window_notinfocus && ! cv_playmusicifunfocused.value )
|
||||
);
|
||||
}
|
||||
|
||||
musictype_t S_MusicType(void)
|
||||
{
|
||||
return I_SongType();
|
||||
|
@ -1867,6 +1892,10 @@ static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
|
|||
}
|
||||
|
||||
S_InitMusicVolume(); // switch between digi and sequence volume
|
||||
|
||||
if (S_MusicNotInFocus())
|
||||
S_PauseAudio();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2009,6 +2038,9 @@ void S_PauseAudio(void)
|
|||
|
||||
void S_ResumeAudio(void)
|
||||
{
|
||||
if (S_MusicNotInFocus())
|
||||
return;
|
||||
|
||||
if (I_SongPlaying() && I_SongPaused())
|
||||
I_ResumeSong();
|
||||
|
||||
|
@ -2202,7 +2234,7 @@ static void Command_RestartAudio_f(void)
|
|||
|
||||
void GameSounds_OnChange(void)
|
||||
{
|
||||
if (M_CheckParm("-nosound"))
|
||||
if (M_CheckParm("-nosound") || M_CheckParm("-noaudio"))
|
||||
return;
|
||||
|
||||
if (sound_disabled)
|
||||
|
@ -2220,7 +2252,7 @@ void GameSounds_OnChange(void)
|
|||
|
||||
void GameDigiMusic_OnChange(void)
|
||||
{
|
||||
if (M_CheckParm("-nomusic"))
|
||||
if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio"))
|
||||
return;
|
||||
else if (M_CheckParm("-nodigmusic"))
|
||||
return;
|
||||
|
@ -2262,7 +2294,7 @@ void GameDigiMusic_OnChange(void)
|
|||
|
||||
void GameMIDIMusic_OnChange(void)
|
||||
{
|
||||
if (M_CheckParm("-nomusic"))
|
||||
if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio"))
|
||||
return;
|
||||
else if (M_CheckParm("-nomidimusic"))
|
||||
return;
|
||||
|
@ -2279,7 +2311,7 @@ void GameMIDIMusic_OnChange(void)
|
|||
else
|
||||
{
|
||||
midi_disabled = true;
|
||||
if (S_MusicType() == MU_MID)
|
||||
if (S_MusicType() == MU_MID || S_MusicType() == MU_MID_EX)
|
||||
{
|
||||
if (digital_disabled)
|
||||
S_StopMusic();
|
||||
|
|
|
@ -45,6 +45,9 @@ extern consvar_t cv_gamedigimusic;
|
|||
extern consvar_t cv_gamemidimusic;
|
||||
extern consvar_t cv_gamesounds;
|
||||
|
||||
extern consvar_t cv_playmusicifunfocused;
|
||||
extern consvar_t cv_playsoundsifunfocused;
|
||||
|
||||
#ifdef HAVE_OPENMPT
|
||||
extern consvar_t cv_modfilter;
|
||||
#endif
|
||||
|
@ -144,6 +147,12 @@ void S_StartEx(boolean reset);
|
|||
//
|
||||
lumpnum_t S_GetSfxLumpNum(sfxinfo_t *sfx);
|
||||
|
||||
//
|
||||
// Sound Status
|
||||
//
|
||||
|
||||
boolean S_SoundDisabled(void);
|
||||
|
||||
//
|
||||
// Start sound for thing at <origin> using <sound_id> from sounds.h
|
||||
//
|
||||
|
@ -164,6 +173,7 @@ boolean S_MIDIMusicDisabled(void);
|
|||
boolean S_MusicDisabled(void);
|
||||
boolean S_MusicPlaying(void);
|
||||
boolean S_MusicPaused(void);
|
||||
boolean S_MusicNotInFocus(void);
|
||||
musictype_t S_MusicType(void);
|
||||
const char *S_MusicName(void);
|
||||
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping);
|
||||
|
|
|
@ -421,9 +421,9 @@ void SCR_DisplayTicRate(void)
|
|||
else if (totaltics == TICRATE) ticcntcolor = V_GREENMAP;
|
||||
|
||||
V_DrawString(vid.width-(72*vid.dupx), h,
|
||||
V_YELLOWMAP|V_NOSCALESTART, "FPS:");
|
||||
V_YELLOWMAP|V_NOSCALESTART|V_HUDTRANS, "FPS:");
|
||||
V_DrawString(vid.width-(40*vid.dupx), h,
|
||||
ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));
|
||||
ticcntcolor|V_NOSCALESTART|V_HUDTRANS, va("%02d/%02u", totaltics, TICRATE));
|
||||
|
||||
lasttic = ontic;
|
||||
}
|
||||
|
|
|
@ -39,13 +39,8 @@
|
|||
// we try to re-allocate a minimum of buffers for stability of the memory,
|
||||
// so all the small-enough tables based on screen size, are allocated once
|
||||
// and for all at the maximum size.
|
||||
#if defined (_WIN32_WCE)
|
||||
#define MAXVIDWIDTH 320
|
||||
#define MAXVIDHEIGHT 200
|
||||
#else
|
||||
#define MAXVIDWIDTH 1920 // don't set this too high because actually
|
||||
#define MAXVIDHEIGHT 1200 // lots of tables are allocated with the MAX size.
|
||||
#endif
|
||||
#define BASEVIDWIDTH 320 // NEVER CHANGE THIS! This is the original
|
||||
#define BASEVIDHEIGHT 200 // resolution of the graphics.
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ void *hwSym(const char *funcName,void *handle)
|
|||
GETFUNC(Init);
|
||||
GETFUNC(Draw2DLine);
|
||||
GETFUNC(DrawPolygon);
|
||||
GETFUNC(RenderSkyDome);
|
||||
GETFUNC(SetBlend);
|
||||
GETFUNC(ClearBuffer);
|
||||
GETFUNC(SetTexture);
|
||||
|
|
|
@ -357,6 +357,14 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void SDLdoGrabMouse(void)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL_SetWindowGrab(window, SDL_TRUE);
|
||||
if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful
|
||||
wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore?
|
||||
}
|
||||
|
||||
static void SDLdoUngrabMouse(void)
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
@ -579,12 +587,18 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
if (cv_usemouse.value) I_StartupMouse();
|
||||
}
|
||||
//else firsttimeonmouse = SDL_FALSE;
|
||||
|
||||
if (USE_MOUSEINPUT)
|
||||
SDLdoGrabMouse();
|
||||
}
|
||||
else if (!mousefocus && !kbfocus)
|
||||
{
|
||||
// Tell game we lost focus, pause music
|
||||
window_notinfocus = true;
|
||||
if (! cv_playmusicifunfocused.value)
|
||||
S_PauseAudio();
|
||||
if (! cv_playsoundsifunfocused.value)
|
||||
S_StopSounds();
|
||||
|
||||
if (!disable_mouse)
|
||||
{
|
||||
|
@ -655,9 +669,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
|
|||
// -- Monster Iestyn
|
||||
if (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window)
|
||||
{
|
||||
SDL_SetWindowGrab(window, SDL_TRUE);
|
||||
if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful
|
||||
wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore?
|
||||
SDLdoGrabMouse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1056,7 +1068,7 @@ void I_StartupMouse(void)
|
|||
else
|
||||
firsttimeonmouse = SDL_FALSE;
|
||||
if (cv_usemouse.value)
|
||||
return;
|
||||
SDLdoGrabMouse();
|
||||
else
|
||||
SDLdoUngrabMouse();
|
||||
}
|
||||
|
@ -1164,8 +1176,11 @@ void I_FinishUpdate(void)
|
|||
if (cv_closedcaptioning.value)
|
||||
SCR_ClosedCaptions();
|
||||
|
||||
if (st_overlay)
|
||||
{
|
||||
if (cv_ticrate.value)
|
||||
SCR_DisplayTicRate();
|
||||
}
|
||||
|
||||
if (rendermode == render_soft && screens[0])
|
||||
{
|
||||
|
@ -1629,6 +1644,7 @@ void I_StartupGraphics(void)
|
|||
HWD.pfnFinishUpdate = NULL;
|
||||
HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL);
|
||||
HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL);
|
||||
HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL);
|
||||
HWD.pfnSetBlend = hwSym("SetBlend",NULL);
|
||||
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
|
||||
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
|
||||
|
|
|
@ -878,7 +878,11 @@ boolean I_SetSongSpeed(float speed)
|
|||
#ifdef HAVE_OPENMPT
|
||||
if (openmpt_mhandle)
|
||||
{
|
||||
char modspd[16];
|
||||
char modspd[13];
|
||||
|
||||
if (speed > 4.0f)
|
||||
speed = 4.0f; // Limit this to 4x to prevent crashing, stupid fix but... ~SteelT 27/9/19
|
||||
|
||||
sprintf(modspd, "%g", speed);
|
||||
openmpt_module_ctl_set(openmpt_mhandle, "play.tempo_factor", modspd);
|
||||
return true;
|
||||
|
|
|
@ -218,6 +218,8 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"},
|
||||
{"bsnipe", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Home-run smash"},
|
||||
{"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"},
|
||||
{"lvfal1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rumble"},
|
||||
{"pscree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "SCREE!"},
|
||||
|
||||
// Menu, interface
|
||||
{"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"},
|
||||
|
@ -504,7 +506,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical damage"},
|
||||
{"s3k6f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"},
|
||||
{"s3k70", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
|
||||
{"s3k70", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
|
||||
{"s3k71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Basic Shield"},
|
||||
{"s3k72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Movement"},
|
||||
{"s3k73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"},
|
||||
|
@ -555,7 +557,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s3ka0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"},
|
||||
{"s3ka1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s3ka2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"},
|
||||
{"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lift"},
|
||||
{"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising charge"},
|
||||
{"s3ka4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"},
|
||||
{"s3ka5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s3ka6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction fizzle"},
|
||||
|
@ -713,7 +715,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"cdfm59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"cdfm60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"cdfm61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"cdfm62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"cdfm62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Speed boost"},
|
||||
{"cdfm63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"cdfm64", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"cdfm65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
|
|
|
@ -267,6 +267,8 @@ typedef enum
|
|||
sfx_chuchu,
|
||||
sfx_bsnipe,
|
||||
sfx_sprong,
|
||||
sfx_lvfal1,
|
||||
sfx_pscree,
|
||||
|
||||
// Menu, interface
|
||||
sfx_chchng,
|
||||
|
|
|
@ -351,7 +351,7 @@ void ST_LoadFaceGraphics(INT32 skinnum)
|
|||
if (skins[skinnum].sprites[SPR2_XTRA].numframes)
|
||||
{
|
||||
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
|
||||
spriteframe_t *sprframe = &sprdef->spriteframes[0];
|
||||
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC];
|
||||
faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
|
||||
if (skins[skinnum].sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes)
|
||||
{
|
||||
|
@ -1474,12 +1474,9 @@ static void ST_drawNightsRecords(void)
|
|||
|
||||
if (P_HasGrades(gamemap, stplyr->lastmare + 1))
|
||||
{
|
||||
if (aflag)
|
||||
V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, 160, aflag,
|
||||
ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]);
|
||||
else
|
||||
V_DrawScaledPatch(BASEVIDWIDTH/2 + 60, 160, 0,
|
||||
ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]);
|
||||
UINT8 grade = P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare);
|
||||
if (modeattacking || grade >= GRADE_A)
|
||||
V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, 160, aflag, ngradeletters[grade]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1857,7 +1854,8 @@ static void ST_drawNiGHTSHUD(void)
|
|||
numbersize = 48/2;
|
||||
|
||||
if ((oldspecialstage && leveltime & 2)
|
||||
&& (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)))
|
||||
&& (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
|
||||
&& !(stplyr->powers[pw_shield] & SH_PROTECTWATER))
|
||||
col = SKINCOLOR_ORANGE;
|
||||
|
||||
ST_DrawNightsOverlayNum((160 + numbersize)<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP, realnightstime, nightsnum, col);
|
||||
|
|
212
src/v_video.c
212
src/v_video.c
|
@ -112,6 +112,7 @@ static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NUL
|
|||
// console variables in development
|
||||
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#endif
|
||||
|
||||
// local copy of the palette for V_GetColor()
|
||||
|
@ -1073,7 +1074,7 @@ void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skin
|
|||
if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes >= 4)
|
||||
{
|
||||
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
|
||||
spriteframe_t *sprframe = &sprdef->spriteframes[3];
|
||||
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CONTINUE];
|
||||
patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL);
|
||||
const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE);
|
||||
|
||||
|
@ -2191,7 +2192,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
|
|||
w = SHORT(hu_font[c]->width) * dupx;
|
||||
|
||||
if (cx > scrwidth)
|
||||
break;
|
||||
continue;
|
||||
if (cx+left + w < 0) //left boundary check
|
||||
{
|
||||
cx += w;
|
||||
|
@ -2305,7 +2306,7 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
|
|||
w = SHORT(hu_font[c]->width) * dupx / 2;
|
||||
|
||||
if (cx > scrwidth)
|
||||
break;
|
||||
continue;
|
||||
if (cx+left + w < 0) //left boundary check
|
||||
{
|
||||
cx += w;
|
||||
|
@ -2410,7 +2411,7 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
|
|||
w = (SHORT(tny_font[c]->width) * dupx);
|
||||
|
||||
if (cx > scrwidth)
|
||||
break;
|
||||
continue;
|
||||
if (cx+left + w < 0) //left boundary check
|
||||
{
|
||||
cx += w;
|
||||
|
@ -2508,7 +2509,7 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|||
w = SHORT(hu_font[c]->width) * dupx;
|
||||
|
||||
if ((cx>>FRACBITS) > scrwidth)
|
||||
break;
|
||||
continue;
|
||||
if ((cx>>FRACBITS)+left + w < 0) //left boundary check
|
||||
{
|
||||
cx += w<<FRACBITS;
|
||||
|
@ -2620,13 +2621,210 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string)
|
|||
|
||||
w = SHORT(cred_font[c]->width) * dupx;
|
||||
if ((cx>>FRACBITS) > scrwidth)
|
||||
break;
|
||||
continue;
|
||||
|
||||
V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT);
|
||||
cx += w<<FRACBITS;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a string using the nt_font
|
||||
// Note that the outline is a seperate font set
|
||||
static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string)
|
||||
{
|
||||
fixed_t cx, cy, w;
|
||||
INT32 c, dupx, dupy, scrwidth, left = 0;
|
||||
const char *ch = string;
|
||||
|
||||
if (option & V_CENTERNAMETAG)
|
||||
x -= FixedInt(FixedMul((V_NameTagWidth(string)/2)*FRACUNIT, scale));
|
||||
option &= ~V_CENTERNAMETAG; // which is also shared with V_ALLOWLOWERCASE...
|
||||
|
||||
cx = x<<FRACBITS;
|
||||
cy = y<<FRACBITS;
|
||||
|
||||
if (option & V_NOSCALESTART)
|
||||
{
|
||||
dupx = vid.dupx;
|
||||
dupy = vid.dupy;
|
||||
scrwidth = vid.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
dupx = dupy = 1;
|
||||
scrwidth = vid.width/vid.dupx;
|
||||
left = (scrwidth - BASEVIDWIDTH)/2;
|
||||
scrwidth -= left;
|
||||
}
|
||||
|
||||
for (;;ch++)
|
||||
{
|
||||
if (!*ch)
|
||||
break;
|
||||
if (*ch == '\n')
|
||||
{
|
||||
cx = x<<FRACBITS;
|
||||
cy += FixedMul((21*dupy)*FRACUNIT, scale);
|
||||
continue;
|
||||
}
|
||||
|
||||
c = toupper(*ch);
|
||||
c -= NT_FONTSTART;
|
||||
|
||||
// character does not exist or is a space
|
||||
if (c < 0 || c >= NT_FONTSIZE || !ntb_font[c] || !nto_font[c])
|
||||
{
|
||||
cx += FixedMul((4 * dupx)*FRACUNIT, scale);
|
||||
continue;
|
||||
}
|
||||
|
||||
w = FixedMul((SHORT(ntb_font[c]->width)+2 * dupx) * FRACUNIT, scale);
|
||||
|
||||
if (FixedInt(cx) > scrwidth)
|
||||
continue;
|
||||
if (cx+(left*FRACUNIT) + w < 0) // left boundary check
|
||||
{
|
||||
cx += w;
|
||||
continue;
|
||||
}
|
||||
|
||||
V_DrawFixedPatch(cx, cy, scale, option, nto_font[c], outlinecolormap);
|
||||
V_DrawFixedPatch(cx, cy, scale, option, ntb_font[c], basecolormap);
|
||||
|
||||
cx += w;
|
||||
}
|
||||
}
|
||||
|
||||
// Looks familiar.
|
||||
void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string)
|
||||
{
|
||||
const char *text = string;
|
||||
const char *first_token = text;
|
||||
char *last_token = strchr(text, '\n');
|
||||
const INT32 lbreakheight = 21;
|
||||
INT32 ntlines;
|
||||
|
||||
if (option & V_CENTERNAMETAG)
|
||||
{
|
||||
ntlines = V_CountNameTagLines(string);
|
||||
y -= FixedInt(FixedMul(((lbreakheight/2) * (ntlines-1))*FRACUNIT, scale));
|
||||
}
|
||||
|
||||
// No line breaks?
|
||||
// Draw entire string
|
||||
if (!last_token)
|
||||
V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, string);
|
||||
// Split string by the line break character
|
||||
else
|
||||
{
|
||||
char *str = NULL;
|
||||
INT32 len;
|
||||
while (true)
|
||||
{
|
||||
// There are still lines left to draw
|
||||
if (last_token)
|
||||
{
|
||||
size_t shift = 0;
|
||||
// Free this line
|
||||
if (str)
|
||||
Z_Free(str);
|
||||
// Find string length, do a malloc...
|
||||
len = (last_token-first_token)+1;
|
||||
str = ZZ_Alloc(len);
|
||||
// Copy the line
|
||||
strncpy(str, first_token, len-1);
|
||||
str[len-1] = '\0';
|
||||
// Don't leave a line break character
|
||||
// at the start of the string!
|
||||
if ((strlen(str) >= 2) && (string[0] == '\n') && (string[1] != '\n'))
|
||||
shift++;
|
||||
// Then draw it
|
||||
V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, str+shift);
|
||||
}
|
||||
// No line break character was found
|
||||
else
|
||||
{
|
||||
// Don't leave a line break character
|
||||
// at the start of the string!
|
||||
if ((strlen(first_token) >= 2) && (first_token[0] == '\n') && (first_token[1] != '\n'))
|
||||
first_token++;
|
||||
// Then draw it
|
||||
V_DrawNameTagLine(x, y, option, scale, basecolormap, outlinecolormap, first_token);
|
||||
break;
|
||||
}
|
||||
|
||||
// Next line
|
||||
y += FixedInt(FixedMul(lbreakheight*FRACUNIT, scale));
|
||||
if ((last_token-text)+1 >= (signed)strlen(text))
|
||||
last_token = NULL;
|
||||
else
|
||||
{
|
||||
first_token = last_token;
|
||||
last_token = strchr(first_token+1, '\n');
|
||||
}
|
||||
}
|
||||
// Free this line
|
||||
if (str)
|
||||
Z_Free(str);
|
||||
}
|
||||
}
|
||||
|
||||
// Count the amount of lines in name tag string
|
||||
INT32 V_CountNameTagLines(const char *string)
|
||||
{
|
||||
INT32 ntlines = 1;
|
||||
const char *text = string;
|
||||
const char *first_token = text;
|
||||
char *last_token = strchr(text, '\n');
|
||||
|
||||
// No line breaks?
|
||||
if (!last_token)
|
||||
return ntlines;
|
||||
// Split string by the line break character
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (last_token)
|
||||
ntlines++;
|
||||
// No line break character was found
|
||||
else
|
||||
break;
|
||||
|
||||
// Next line
|
||||
if ((last_token-text)+1 >= (signed)strlen(text))
|
||||
last_token = NULL;
|
||||
else
|
||||
{
|
||||
first_token = last_token;
|
||||
last_token = strchr(first_token+1, '\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
return ntlines;
|
||||
}
|
||||
|
||||
INT32 V_NameTagWidth(const char *string)
|
||||
{
|
||||
INT32 c, w = 0;
|
||||
size_t i;
|
||||
|
||||
// It's possible for string to be a null pointer
|
||||
if (!string)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < strlen(string); i++)
|
||||
{
|
||||
c = toupper(string[i]) - NT_FONTSTART;
|
||||
if (c < 0 || c >= NT_FONTSIZE || !ntb_font[c] || !nto_font[c])
|
||||
w += 4;
|
||||
else
|
||||
w += SHORT(ntb_font[c]->width)+2;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
// Find string width from cred_font chars
|
||||
//
|
||||
INT32 V_CreditStringWidth(const char *string)
|
||||
|
@ -2702,7 +2900,7 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
|
|||
w = SHORT(lt_font[c]->width) * dupx;
|
||||
|
||||
if (cx > scrwidth)
|
||||
break;
|
||||
continue;
|
||||
if (cx+left + w < 0) //left boundary check
|
||||
{
|
||||
cx += w;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue