Merge branch 'master' of https://git.magicalgirl.moe/STJr/SRB2Internal.git into internal-md3-vanilla-c

Merge seems fine, but won't compile for some reason.
This commit is contained in:
toaster 2019-11-02 18:26:20 +00:00
commit 915e50a1e4
105 changed files with 12972 additions and 1521 deletions

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -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

View File

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

View File

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

View File

@ -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"

View File

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

View File

@ -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];
memset(netbuffer->u.playerinfo[i].address, 0, 4);
if (playernode[i] == 0)
{
//127.0.0.1
netbuffer->u.playerinfo[i].address[0] = 127;
netbuffer->u.playerinfo[i].address[3] = 1;
}
else if (playernode[i] > 0 && I_GetNodeAddress && (claddress = I_GetNodeAddress(playernode[i])) != NULL)
{
if (sscanf(claddress, "%d.%d.%d.%d", &numericaddress[0], &numericaddress[1], &numericaddress[2], &numericaddress[3]) < 4)
goto badaddress;
netbuffer->u.playerinfo[i].address[0] = (UINT8)numericaddress[0];
netbuffer->u.playerinfo[i].address[1] = (UINT8)numericaddress[1];
netbuffer->u.playerinfo[i].address[2] = (UINT8)numericaddress[2];
netbuffer->u.playerinfo[i].address[3] = (UINT8)numericaddress[3];
}
}
badaddress:
//No, don't do that, you fuckface.
memset(netbuffer->u.playerinfo[i].address, 0, 4);
if (G_GametypeHasTeams())
{
@ -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)
{
@ -4722,7 +4728,6 @@ void TryRunTics(tic_t realtics)
}
}
#ifdef NEWPING
static inline void PingUpdate(void)
{
INT32 i;
@ -4780,7 +4785,6 @@ static inline void PingUpdate(void)
pingmeasurecount = 1; //Reset count
}
#endif
void NetUpdate(void)
{
@ -4805,7 +4809,6 @@ void NetUpdate(void)
gametime = nowtime;
#ifdef NEWPING
if (server)
{
if (netgame && !(gametime % 255))
@ -4816,7 +4819,6 @@ void NetUpdate(void)
realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
pingmeasurecount++;
}
#endif
if (client)
maketic = neededtic;
@ -4858,8 +4860,13 @@ void NetUpdate(void)
for (i = 0; i < MAXNETNODES; ++i)
if (resynch_inprogress[i])
{
SV_SendResynch(i);
counts = -666;
if (!nodeingame[i] || nettics[i] == gametic)
{
SV_SendResynch(i);
counts = -666;
}
else
counts = 0; // Let the client catch up with the server
}
// Do not make tics while resynching

View File

@ -15,6 +15,7 @@
#include "d_ticcmd.h"
#include "d_netcmd.h"
#include "d_net.h"
#include "tables.h"
#include "d_player.h"
@ -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;

View File

@ -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
@ -856,7 +856,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"));
@ -1149,10 +1149,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.
@ -1161,7 +1161,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
@ -1248,24 +1248,40 @@ void D_SRB2Main(void)
sound_disabled = true;
midi_disabled = digital_disabled = true;
}
if (M_CheckParm("-noaudio")) // combines -nosound and -nomusic
{
sound_disabled = true;
digital_disabled = true;
midi_disabled = true;
}
else
{
if (M_CheckParm("-nosound"))
sound_disabled = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
{
digital_disabled = true;
midi_disabled = true;
}
else
{
if (M_CheckParm("-nomidimusic"))
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
if (M_CheckParm("-nodigmusic"))
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
}
}
if (!( sound_disabled && digital_disabled
#ifndef NO_MIDI
&& midi_disabled
#endif
))
{
CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
I_StartupSound();
I_InitMusic();
S_InitSfxChannels(cv_soundvolume.value);
}
if (M_CheckParm("-nosound"))
sound_disabled = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
midi_disabled = digital_disabled = true;
else
{
if (M_CheckParm("-nomidimusic"))
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
if (M_CheckParm("-nodigmusic"))
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
}
I_StartupSound();
I_InitMusic();
S_InitSfxChannels(cv_soundvolume.value);
CONS_Printf("ST_Init(): Init status bar.\n");
ST_Init();

View File

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

View File

@ -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};
char timedemo_name[256];
boolean timedemo_csv;
@ -502,7 +502,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);
@ -578,9 +578,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);
@ -745,6 +743,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);
@ -884,7 +884,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;
@ -925,14 +925,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
@ -1061,12 +1061,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)
{
@ -1191,12 +1191,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)
{
@ -1309,12 +1309,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)
{
@ -1708,7 +1708,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)
{
@ -2048,8 +2048,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"));
@ -2069,6 +2067,7 @@ static void Command_Suicide(void)
return;
}
WRITEINT32(cp, consoleplayer);
SendNetXCmd(XD_SUICIDE, &buf, 4);
}
@ -4481,3 +4480,14 @@ static void Command_ShowTime_f(void)
CONS_Printf(M_GetText("The current time is %f.\nThe timelimit is %f\n"), (double)leveltime/TICRATE, (double)timelimitintics/TICRATE);
}
static void BaseNumLaps_OnChange(void)
{
if (gametype == GT_RACE)
{
if (cv_basenumlaps.value)
CONS_Printf(M_GetText("Number of laps will be changed to map defaults next round.\n"));
else
CONS_Printf(M_GetText("Number of laps will be changed to %d next round.\n"), cv_basenumlaps.value);
}
}

View File

@ -66,7 +66,7 @@ extern consvar_t cv_friendlyfire;
extern consvar_t cv_pointlimit;
extern consvar_t cv_timelimit;
extern consvar_t cv_numlaps;
extern consvar_t cv_usemapnumlaps;
extern consvar_t cv_basenumlaps;
extern UINT32 timelimitintics;
extern consvar_t cv_allowexitlevel;
@ -107,9 +107,7 @@ extern consvar_t cv_ringslinger, cv_soundtest;
extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes;
#ifdef NEWPING
extern consvar_t cv_maxping;
#endif
extern consvar_t cv_skipmapcheck;
@ -195,6 +193,7 @@ typedef union {
// add game commands, needs cleanup
void D_RegisterServerCommands(void);
void D_RegisterClientCommands(void);
boolean EnsurePlayerNameIsGood(char *name, INT32 playernum);
void D_SendPlayerConfig(void);
void Command_ExitGame_f(void);
void Command_Retry_f(void);

View File

@ -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);

View File

@ -234,7 +234,9 @@ typedef enum
CR_ZOOMTUBE,
CR_ROPEHANG,
CR_MACESPIN,
CR_MINECART
CR_MINECART,
CR_ROLLOUT,
CR_PTERABYTE
} carrytype_t; // pw_carry
// Player powers. (don't edit this comment)
@ -250,6 +252,8 @@ typedef enum
pw_spacetime, // In space, no one can hear you spin!
pw_extralife, // Extra Life timer
pw_pushing,
pw_justsprung,
pw_noautobrake,
pw_super, // Are you super?
pw_gravityboots, // gravity boots
@ -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

View File

@ -313,7 +313,13 @@ static boolean findFreeSlot(INT32 *num)
if (*num >= MAXSKINS)
return false;
description[*num].picname[0] = '\0'; // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...)
// Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...)
description[*num].picname[0] = '\0';
description[*num].nametag[0] = '\0';
description[*num].displayname[0] = '\0';
description[*num].oppositecolor = SKINCOLOR_NONE;
description[*num].tagtextcolor = SKINCOLOR_NONE;
description[*num].tagoutlinecolor = SKINCOLOR_NONE;
// Found one! ^_^
return (description[*num].used = true);
@ -326,9 +332,16 @@ static void readPlayer(MYFILE *f, INT32 num)
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word;
char *word2;
char *displayname = ZZ_Alloc(MAXLINELEN+1);
INT32 i;
boolean slotfound = false;
#define SLOTFOUND \
if (!slotfound && (slotfound = findFreeSlot(&num)) == false) \
goto done;
displayname[MAXLINELEN] = '\0';
do
{
if (myfgets(s, MAXLINELEN, f))
@ -336,6 +349,17 @@ static void readPlayer(MYFILE *f, INT32 num)
if (s[0] == '\n')
break;
for (i = 0; i < MAXLINELEN-3; i++)
{
char *tmp;
if (s[i] == '=')
{
tmp = &s[i+2];
strncpy(displayname, tmp, SKINNAMESIZE);
break;
}
}
word = strtok(s, " ");
if (word)
strupr(word);
@ -346,8 +370,7 @@ static void readPlayer(MYFILE *f, INT32 num)
{
char *playertext = NULL;
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
SLOTFOUND
for (i = 0; i < MAXLINELEN-3; i++)
{
@ -395,11 +418,54 @@ static void readPlayer(MYFILE *f, INT32 num)
if (fastcmp(word, "PICNAME"))
{
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
SLOTFOUND
strncpy(description[num].picname, word2, 8);
}
// new character select
else if (fastcmp(word, "DISPLAYNAME"))
{
SLOTFOUND
// replace '#' with line breaks
// (also remove any '\n')
{
char *cur = NULL;
// remove '\n'
cur = strchr(displayname, '\n');
if (cur)
*cur = '\0';
// turn '#' into '\n'
cur = strchr(displayname, '#');
while (cur)
{
*cur = '\n';
cur = strchr(cur, '#');
}
}
// copy final string
strncpy(description[num].displayname, displayname, SKINNAMESIZE);
}
else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR"))
{
SLOTFOUND
description[num].oppositecolor = (UINT8)get_number(word2);
}
else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME"))
{
SLOTFOUND
strncpy(description[num].nametag, word2, 8);
}
else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR"))
{
SLOTFOUND
description[num].tagtextcolor = (UINT8)get_number(word2);
}
else if (fastcmp(word, "TAGOUTLINECOLOR") || fastcmp(word, "TAGOUTLINECOLOUR"))
{
SLOTFOUND
description[num].tagoutlinecolor = (UINT8)get_number(word2);
}
else if (fastcmp(word, "STATUS"))
{
/*
@ -417,9 +483,7 @@ static void readPlayer(MYFILE *f, INT32 num)
else if (fastcmp(word, "SKINNAME"))
{
// Send to free slot.
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
SLOTFOUND
strlcpy(description[num].skinname, word2, sizeof description[num].skinname);
strlwr(description[num].skinname);
}
@ -427,8 +491,9 @@ static void readPlayer(MYFILE *f, INT32 num)
deh_warning("readPlayer %d: unknown word '%s'", num, word);
}
} while (!myfeof(f)); // finish when the line is empty
#undef SLOTFOUND
done:
Z_Free(displayname);
Z_Free(s);
}
@ -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;

View File

@ -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

View File

@ -327,7 +327,7 @@ typedef struct
// Music stuff.
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
char musintername[7]; ///< Intermission screen music.
char muspostbossname[7]; ///< Post-bossdeath music.
UINT16 muspostbosstrack; ///< Post-bossdeath track.
UINT32 muspostbosspos; ///< Post-bossdeath position
@ -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.

View File

@ -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();
}

View File

@ -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])

View File

@ -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);
}
}

View File

@ -60,6 +60,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;

View File

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

View File

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

View File

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

View File

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

View File

@ -162,6 +162,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_TURR
&lspr[NOLIGHT], // SPR_SHRP
&lspr[NOLIGHT], // SPR_CRAB
&lspr[NOLIGHT], // SPR_CR2B
&lspr[NOLIGHT], // SPR_CSPR
&lspr[NOLIGHT], // SPR_JJAW
&lspr[NOLIGHT], // SPR_SNLR
&lspr[NOLIGHT], // SPR_VLTR
@ -180,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,13 +397,20 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_XMS3
&lspr[NOLIGHT], // SPR_XMS4
&lspr[NOLIGHT], // SPR_XMS5
&lspr[NOLIGHT], // SPR_XMS6
&lspr[NOLIGHT], // SPR_FHZI
&lspr[NOLIGHT], // SPR_ROSY
// Halloween Scenery
&lspr[RINGLIGHT_L], // SPR_PUMK
&lspr[NOLIGHT], // SPR_HHPL
&lspr[NOLIGHT], // SPR_SHRM
&lspr[NOLIGHT], // SPR_HHZM
// Azure Temple Scenery
&lspr[NOLIGHT], // SPR_BGAR
&lspr[NOLIGHT], // SPR_RCRY
&lspr[GREENBALL_L], // SPR_CFLM
// Botanic Serenity Scenery
&lspr[NOLIGHT], // SPR_BSZ1
@ -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

View File

@ -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)
continue;
if (thing->sprite == SPR_HOOP)
{
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
continue;
}
else
{
if (limit_dist && approx_dist > limit_dist)
continue;
}
HWR_ProjectSprite(thing);
}
@ -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,86 +5886,122 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
// ==========================================================================
//
// ==========================================================================
static void HWR_DrawSkyBackground(void)
static void HWR_DrawSkyBackground(player_t *player)
{
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gr_xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
if (cv_grskydome.value)
{
dimensionmultiply *= 2;
angle *= 2;
}
FTransform transform;
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
postimg_t *type;
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.flip)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
if (splitscreen && player == &players[secondarydisplayplayer])
type = &postimgtype2;
else
type = &postimgtype;
memset(&transform, 0x00, sizeof(FTransform));
//04/01/2000: Hurdler: added for T&L
// It should replace all other gr_viewxxx when finished
transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
if (*type == postimg_flip)
transform.flip = true;
else
transform.flip = false;
transform.scalex = 1;
transform.scaley = (float)vid.width/vid.height;
transform.scalez = 1;
transform.fovxangle = fpov; // Tails
transform.fovyangle = fpov; // Tails
transform.splitscreen = splitscreen;
HWR_GetTexture(texturetranslation[skytexture]);
HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform);
}
else
{
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
}
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].tow = v[2].tow += ((float) angle / angleturn);
v[0].tow = v[1].tow += ((float) angle / angleturn);
}
else
{
v[3].tow = v[2].tow -= ((float) angle / angleturn);
v[0].tow = v[1].tow -= ((float) angle / angleturn);
}
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
HWD.pfnDrawPolygon(NULL, v, 4, 0);
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gr_xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
{
dimensionmultiply *= 2;
angle *= 2;
}
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.flip)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
}
else
{
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
}
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].tow = v[2].tow += ((float) angle / angleturn);
v[0].tow = v[1].tow += ((float) angle / angleturn);
}
else
{
v[3].tow = v[2].tow -= ((float) angle / angleturn);
v[0].tow = v[1].tow -= ((float) angle / angleturn);
}
HWD.pfnDrawPolygon(NULL, v, 4, 0);
}
}
@ -6100,7 +6153,7 @@ if (0)
}
if (drawsky)
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;
@ -6318,7 +6371,7 @@ if (0)
}
if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;

View File

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

View File

@ -925,6 +925,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;
@ -956,6 +957,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
}
else
Surf.FlatColor.rgba = 0xFFFFFFFF;
// Look at HWR_ProjectSprite for more
{

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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,13 +547,20 @@ typedef enum sprite
SPR_XMS3, // Snowman
SPR_XMS4, // Lamppost
SPR_XMS5, // Hanging Star
SPR_XMS6, // Mistletoe
SPR_FHZI, // FHZ Ice
SPR_ROSY,
// Halloween Scenery
SPR_PUMK, // Pumpkins
SPR_HHPL, // Dr Seuss Trees
SPR_SHRM, // Mushroom
SPR_HHZM, // Misc
// Azure Temple Scenery
SPR_BGAR, // ATZ Gargoyles
SPR_RCRY, // ATZ Red Crystal (Target)
SPR_CFLM, // Green torch flame
// Botanic Serenity Scenery
SPR_BSZ1, // Tall flowers
@ -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

View File

@ -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;
}

View File

@ -50,6 +50,7 @@ enum hook {
hook_FollowMobj,
hook_PlayerCanDamage,
hook_PlayerQuit,
hook_IntermissionThinker,
hook_MAX // last hook
};
@ -91,5 +92,6 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnM
boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
#endif

View File

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

View File

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

View File

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

View File

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

View File

@ -25,7 +25,6 @@
static int lib_iteratePlayers(lua_State *L)
{
INT32 i = -1;
INLEVEL
if (lua_gettop(L) < 2)
{
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
@ -52,7 +51,6 @@ static int lib_getPlayer(lua_State *L)
{
const char *field;
// i -> players[i]
INLEVEL
if (lua_type(L, 2) == LUA_TNUMBER)
{
lua_Integer i = luaL_checkinteger(L, 2);

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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[];

View File

@ -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;

View File

@ -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;
}

View File

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

View File

@ -428,7 +428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|| special->state == &states[S_FANG_BOUNCE4]
|| special->state == &states[S_FANG_PINCHBOUNCE3]
|| special->state == &states[S_FANG_PINCHBOUNCE4])
&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > -(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);

View File

@ -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);

View File

@ -124,6 +124,7 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
// Positive spring modes are minor variants of vanilla spring behaviour.
// 1 = launch players in jump
// 2 = don't modify player at all, just add momentum
// 3 = speed-booster mode (force onto ground, MF_AMBUSH causes auto-spin)
// Negative spring modes are mildly-related gimmicks with customisation.
// -1 = pinball bumper
// Any other spring mode defaults to standard vanilla spring behaviour,
@ -151,7 +152,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
if (object->player)
{
if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
if (spring->info->painchance == 3)
;
else if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
strong = 1;
else if (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2)
strong = 2;
@ -208,7 +211,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
angle_t nightsangle = 0;
if (object->player->bumpertime >= TICRATE/4)
if (object->player->bumpertime > (TICRATE/2)-5)
return false;
if ((object->player->pflags & PF_TRANSFERTOCLOSEST) && object->player->axis1 && object->player->axis2)
@ -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)
}
}
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these.
secondjump = object->player->secondjump;
washoming = object->player->homing;
if (object->player->pflags & PF_GLIDING)
P_SetPlayerMobjState(object, S_PLAY_FALL);
if ((spring->info->painchance == 3))
{
if (!(pflags = (object->player->pflags & PF_SPINNING)) &&
(((object->player->charability2 == CA2_SPINDASH) && (object->player->cmd.buttons & BT_USE))
|| (spring->flags2 & MF2_AMBUSH)))
{
pflags = PF_SPINNING;
P_SetPlayerMobjState(object, S_PLAY_ROLL);
S_StartSound(object, sfx_spin);
}
else
P_SetPlayerMobjState(object, S_PLAY_ROLL);
}
else
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these.
secondjump = object->player->secondjump;
washoming = object->player->homing;
P_ResetPlayer(object->player);
if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities.
@ -368,7 +412,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
object->player->pflags |= P_GetJumpFlags(object->player);
P_SetPlayerMobjState(object, S_PLAY_JUMP);
}
else if ((spring->info->painchance == 2) || (pflags & PF_BOUNCING)) // Adding momentum only.
else if ((spring->info->painchance == 2) || ((spring->info->painchance != 3) && (pflags & PF_BOUNCING))) // Adding momentum only.
{
object->player->pflags |= (pflags &~ PF_STARTJUMP);
object->player->secondjump = secondjump;
@ -382,6 +426,10 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
object->player->pflags |= pflags;
object->player->secondjump = secondjump;
}
else if (object->player->dashmode >= 3*TICRATE)
P_SetPlayerMobjState(object, S_PLAY_DASH);
else if (P_IsObjectOnGround(object) && horizspeed >= FixedMul(object->player->runspeed, object->scale))
P_SetPlayerMobjState(object, S_PLAY_RUN);
else
P_SetPlayerMobjState(object, S_PLAY_WALK);
}
@ -490,6 +538,42 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
}
}
static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera)
{
if (player->powers[pw_carry] && players->powers[pw_carry] != CR_ROLLOUT)
return;
if (ptera->extravalue1 != 1)
return; // Not swooping
if (ptera->target != player->mo)
return; // Not swooping for you!
if (player->spectator)
return;
if ((player->mo->eflags & MFE_VERTICALFLIP) != (ptera->eflags & MFE_VERTICALFLIP))
return; // Both should be in same gravity
if (ptera->eflags & MFE_VERTICALFLIP)
{
if (ptera->ceilingz - (ptera->z + ptera->height) < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return;
}
else if (ptera->z - ptera->floorz < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return; // No room to pick up this guy!
P_ResetPlayer(player);
P_SetTarget(&player->mo->tracer, ptera);
player->pflags &= ~PF_APPLYAUTOBRAKE;
player->powers[pw_carry] = CR_PTERABYTE;
S_StartSound(player->mo, sfx_s3k4a);
P_UnsetThingPosition(player->mo);
player->mo->x = ptera->x;
player->mo->y = ptera->y;
P_SetThingPosition(player->mo);
ptera->movefactor = 3*TICRATE;
ptera->watertop = ptera->waterbottom = ptera->cusval = 0;
}
static void P_DoTailsCarry(player_t *sonic, player_t *tails)
{
INT32 p;
@ -604,6 +688,34 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole)
P_SetTarget(&pole->tracer, NULL);
}
static void P_PlayerBarrelCollide(mobj_t *toucher, mobj_t *barrel)
{
if (toucher->momz < 0)
{
if (toucher->z + toucher->momz > barrel->z + barrel->height)
return;
}
else
{
if (toucher->z > barrel->z + barrel->height)
return;
}
if (toucher->momz > 0)
{
if (toucher->z + toucher->height + toucher->momz < barrel->z)
return;
}
else
{
if (toucher->z + toucher->height < barrel->z)
return;
}
if (P_PlayerCanDamage(toucher->player, barrel))
P_DamageMobj(barrel, toucher, toucher, 1, 0);
}
//
// PIT_CheckThing
//
@ -854,6 +966,15 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
#endif
if (tmthing->type == MT_LAVAFALL_LAVA && (thing->type == MT_RING || thing->type == MT_REDTEAMRING || thing->type == MT_BLUETEAMRING || thing->type == MT_FLINGRING))
{
//height check
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !(thing->health))
return true;
P_KillMobj(thing, tmthing, tmthing, DMG_FIRE);
}
if (tmthing->type == MT_MINECART)
{
//height check
@ -872,12 +993,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOOR && tmthing->player)
{
if (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer) && tmthing->tracer->health)
mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing;
if ((thing->flags & MF2_AMBUSH) || ref != tmthing)
{
fixed_t dx = tmthing->tracer->momx;
fixed_t dy = tmthing->tracer->momy;
fixed_t dm = min(FixedHypot(dx, dy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, dx, dy) - thing->angle;
fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle;
fixed_t s = FINESINE((ang >> ANGLETOFINESHIFT) & FINEMASK);
S_StartSound(tmthing, thing->info->activesound);
thing->extravalue2 += 2*FixedMul(s, dm)/3;
@ -885,41 +1005,73 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
}
if (thing->type == MT_TNTBARREL && tmthing->player)
if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
{
if (tmthing->momz < 0)
{
if (tmthing->z + tmthing->momz > thing->z + thing->height)
return true;
}
else
{
if (tmthing->z > thing->z + thing->height)
return true;
}
if (tmthing->momz > 0)
{
if (tmthing->z + tmthing->height + tmthing->momz < thing->z)
return true;
}
else
{
if (tmthing->z + tmthing->height < thing->z)
return true;
}
if ((tmthing->player->pflags & (PF_SPINNING | PF_GLIDING))
|| ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height / 2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|| (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)))
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
if ((thing->flags & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
return true;
}
if (thing->type == MT_ROLLOUTROCK && tmthing->player && tmthing->health)
{
if (tmthing->player->powers[pw_carry] == CR_ROLLOUT)
{
return true;
}
if ((thing->flags & MF_PUSHABLE) // not carrying a player
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
&& (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius))
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0)
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
{
thing->flags &= ~MF_PUSHABLE; // prevent riding player from applying pushable movement logic
thing->flags2 &= ~MF2_DONTDRAW; // don't leave the rock invisible if it was flashing prior to boarding
P_SetTarget(&thing->tracer, tmthing);
P_ResetPlayer(tmthing->player);
P_SetPlayerMobjState(tmthing, S_PLAY_WALK);
tmthing->player->powers[pw_carry] = CR_ROLLOUT;
P_SetTarget(&tmthing->tracer, thing);
P_SetObjectMomZ(thing, tmthing->momz, true);
return true;
}
}
else if (tmthing->type == MT_ROLLOUTROCK)
{
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !thing->health)
return true;
if (thing == tmthing->tracer) // don't collide with rider
return true;
if (thing->flags & MF_SPRING) // bounce on springs
{
P_DoSpring(thing, tmthing);
return true;
}
else if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) == (MF_MONITOR|MF_SHOOTABLE) && !(tmthing->flags & MF_PUSHABLE)) // pop monitors while carrying a player
{
P_KillMobj(thing, tmthing, tmthing->tracer, 0);
return true;
}
if (thing->type == tmthing->type // bounce against other rollout rocks
&& (tmthing->momx || tmthing->momy || thing->momx || thing->momy))
{
fixed_t tempmomx = thing->momx, tempmomy = thing->momy;
thing->momx = tmthing->momx;
thing->momy = tmthing->momy;
tmthing->momx = tempmomx;
tmthing->momy = tempmomy;
}
}
if (thing->type == MT_PTERABYTE && tmthing->player)
P_DoPterabyteCarry(tmthing->player, thing);
if (thing->type == MT_TNTBARREL && tmthing->player)
P_PlayerBarrelCollide(tmthing, thing);
if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE)
{
fixed_t dx = thing->x - tmthing->x;
@ -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)
{

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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)

View File

@ -2607,7 +2607,6 @@ boolean P_SetupLevel(boolean skipprecip)
boolean loadedbm = false;
sector_t *ss;
boolean chase;
levelloading = true;
// This is needed. Don't touch.
@ -3048,8 +3047,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.

View File

@ -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,30 +2759,32 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
return;
}
}
if (line->flags & ML_NOCLIMB)
else
{
// play the sound from nowhere, but only if display player triggered it
if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer]))
if (line->flags & ML_NOCLIMB)
{
// play the sound from nowhere, but only if display player triggered it
if (mo && mo->player && (mo->player == &players[displayplayer] || mo->player == &players[secondarydisplayplayer]))
S_StartSound(NULL, sfxnum);
}
else if (line->flags & ML_EFFECT4)
{
// play the sound from nowhere
S_StartSound(NULL, sfxnum);
}
else if (line->flags & ML_EFFECT4)
{
// play the sound from nowhere
S_StartSound(NULL, sfxnum);
}
else if (line->flags & ML_BLOCKMONSTERS)
{
// play the sound from calling sector's soundorg
if (callsec)
S_StartSound(&callsec->soundorg, sfxnum);
}
else if (line->flags & ML_BLOCKMONSTERS)
{
// play the sound from calling sector's soundorg
if (callsec)
S_StartSound(&callsec->soundorg, sfxnum);
else if (mo)
S_StartSound(&mo->subsector->sector->soundorg, sfxnum);
}
else if (mo)
S_StartSound(&mo->subsector->sector->soundorg, sfxnum);
}
else if (mo)
{
// play the sound from mobj that triggered it
S_StartSound(mo, sfxnum);
{
// play the sound from mobj that triggered it
S_StartSound(mo, sfxnum);
}
}
}
break;
@ -4174,26 +4177,11 @@ 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)
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;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -4234,26 +4222,11 @@ 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)
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;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -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,26 +5270,11 @@ 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)
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;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -5374,26 +5317,11 @@ 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)
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;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -5450,38 +5378,16 @@ 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 (!(floorallowed || ceilingallowed))
{
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != polysec->ceilingheight)
{
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;
}
po = (polyobj_t *)(po->link.next);
continue;
}
}
else
@ -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)
return;
{
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;
@ -6169,6 +6068,8 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
airbob->vars[5] = sec->ceilingheight;
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;

View File

@ -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)
{

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}
}
}

View File

@ -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

View File

@ -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
{
SF_FLIPSPECIAL_FLOOR = 1,
SF_FLIPSPECIAL_CEILING = 2,
SF_FLIPSPECIAL_BOTH = 3,
SF_TRIGGERSPECIAL_TOUCH = 4,
// flipspecial - planes with effect
SF_FLIPSPECIAL_FLOOR = 1,
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;
//

View File

@ -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;
}

View File

@ -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);

View File

@ -1218,6 +1218,7 @@ void R_RegisterEngineStuff(void)
#endif
CV_RegisterVar(&cv_grmodels);
CV_RegisterVar(&cv_grspritebillboarding);
CV_RegisterVar(&cv_grskydome);
#endif
#ifdef HWRENDER

View File

@ -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,11 +824,11 @@ 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;
}
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

View File

@ -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)
continue;
if (thing->sprite == SPR_HOOP)
{
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
continue;
}
else
{
if (limit_dist && approx_dist > limit_dist)
continue;
}
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
}

View File

@ -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();

View File

@ -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);

View File

@ -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;
}

View File

@ -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.

View File

@ -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);

View File

@ -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;
S_PauseAudio();
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 (cv_ticrate.value)
SCR_DisplayTicRate();
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);

View File

@ -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;

View File

@ -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, ""},

View File

@ -267,6 +267,8 @@ typedef enum
sfx_chuchu,
sfx_bsnipe,
sfx_sprong,
sfx_lvfal1,
sfx_pscree,
// Menu, interface
sfx_chchng,

View File

@ -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);

View File

@ -111,6 +111,7 @@ static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NUL
// console variables in development
consvar_t cv_grmodels = {"gr_models", "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()
@ -1072,7 +1073,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);
@ -2190,7 +2191,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;
@ -2304,7 +2305,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;
@ -2409,7 +2410,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;
@ -2507,7 +2508,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;
@ -2619,13 +2620,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)
@ -2701,7 +2899,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