Merge remote-tracking branch 'origin/master' into renderswitch

This commit is contained in:
Jaime Passos 2019-11-12 20:25:40 -03:00
commit c6253bb6f9
138 changed files with 19816 additions and 4193 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

@ -423,7 +423,11 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_trick.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c
)
set (SRB2_HWRENDER_HEADERS
@ -437,6 +441,10 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.h
)
set(SRB2_R_OPENGL_SOURCES

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
@ -229,7 +226,8 @@ else
#OPTS+=-DUSE_PALETTED_TEXTURE
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o
endif
ifdef NOHS
@ -649,16 +647,18 @@ ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
endif
@ -736,16 +736,18 @@ ifndef NOHW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
endif

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

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

@ -176,11 +176,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];
@ -395,7 +395,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];
//No, don't do that, you fuckface.
memset(netbuffer->u.playerinfo[i].address, 0, 4);
if (playernode[i] == 0)
{
//127.0.0.1
netbuffer->u.playerinfo[i].address[0] = 127;
netbuffer->u.playerinfo[i].address[3] = 1;
}
else if (playernode[i] > 0 && I_GetNodeAddress && (claddress = I_GetNodeAddress(playernode[i])) != NULL)
{
if (sscanf(claddress, "%d.%d.%d.%d", &numericaddress[0], &numericaddress[1], &numericaddress[2], &numericaddress[3]) < 4)
goto badaddress;
netbuffer->u.playerinfo[i].address[0] = (UINT8)numericaddress[0];
netbuffer->u.playerinfo[i].address[1] = (UINT8)numericaddress[1];
netbuffer->u.playerinfo[i].address[2] = (UINT8)numericaddress[2];
netbuffer->u.playerinfo[i].address[3] = (UINT8)numericaddress[3];
}
}
badaddress:
if (G_GametypeHasTeams())
{
@ -2499,7 +2491,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
void CL_Reset(void)
{
if (metalrecording)
G_StopMetalRecording();
G_StopMetalRecording(false);
if (metalplayback)
G_StopMetalDemo();
if (demorecording)
@ -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,10 +4705,15 @@ void TryRunTics(tic_t realtics)
if (player_joining)
return;
if (neededtic > gametic)
if (neededtic > gametic && !resynch_local_inprogress)
{
if (advancedemo)
{
if (timedemo_quit)
COM_ImmedExecute("quit");
else
D_StartTitle();
}
else
// run the count * tics
while (neededtic > gametic)
@ -4717,7 +4728,6 @@ void TryRunTics(tic_t realtics)
}
}
#ifdef NEWPING
static inline void PingUpdate(void)
{
INT32 i;
@ -4775,7 +4785,6 @@ static inline void PingUpdate(void)
pingmeasurecount = 1; //Reset count
}
#endif
void NetUpdate(void)
{
@ -4800,7 +4809,6 @@ void NetUpdate(void)
gametime = nowtime;
#ifdef NEWPING
if (server)
{
if (netgame && !(gametime % 255))
@ -4811,7 +4819,6 @@ void NetUpdate(void)
realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
pingmeasurecount++;
}
#endif
if (client)
maketic = neededtic;
@ -4852,10 +4859,15 @@ void NetUpdate(void)
for (i = 0; i < MAXNETNODES; ++i)
if (resynch_inprogress[i])
{
if (!nodeingame[i] || nettics[i] == gametic)
{
SV_SendResynch(i);
counts = -666;
}
else
counts = 0; // Let the client catch up with the server
}
// Do not make tics while resynching
if (counts != -666)

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

@ -257,7 +257,14 @@ static void D_Display(void)
}
if (vid.recalc || setrenderstillneeded)
{
SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc()
#ifdef HWRENDER
// Shoot! The screen texture was flushed!
if ((rendermode == render_opengl) && (gamestate == GS_INTERMISSION))
usebuffer = false;
#endif
}
// change the view size if needed
if (setsizeneeded || setrenderstillneeded)
@ -317,11 +324,8 @@ static void D_Display(void)
switch (gamestate)
{
case GS_TITLESCREEN:
if (!titlemapinaction || !curbghide) {
F_TitleScreenDrawer();
break;
}
/* FALLTHRU */
case GS_LEVEL:
if (!gametic)
break;
@ -392,76 +396,27 @@ 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)
{
// draw the view directly
if (!automapactive && !dedicated && cv_renderview.value)
{
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// Image postprocessing effect
if (rendermode == render_soft)
{
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
}
D_Render();
if (lastdraw)
{
if (rendermode == render_soft)
{
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
Y_ConsiderScreenBuffer();
usebuffer = true;
}
lastdraw = false;
}
if (gamestate == GS_LEVEL)
{
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
}
else
F_TitleScreenDrawer();
}
}
// change gamma if needed
@ -516,6 +471,13 @@ static void D_Display(void)
F_RunWipe(wipetypepost, gamestate != GS_TIMEATTACK && gamestate != GS_TITLESCREEN);
}
// reset counters so timedemo doesn't count the wipe duration
if (timingdemo)
{
framecount = 0;
demostarttime = I_GetTime();
}
wipetypepost = -1;
}
else
@ -575,6 +537,56 @@ void D_CheckRendererState(void)
R_ReloadHUDGraphics();
}
void D_Render(void)
{
if (!automapactive && !dedicated && cv_renderview.value)
{
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(0, &players[displayplayer]);
else
#endif
if (rendermode != render_none)
R_RenderPlayerView(&players[displayplayer]);
}
// render the second screen
if (splitscreen && players[secondarydisplayplayer].mo)
{
#ifdef HWRENDER
if (rendermode != render_soft)
HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
else
#endif
if (rendermode != render_none)
{
viewwindowy = vid.height / 2;
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
R_RenderPlayerView(&players[secondarydisplayplayer]);
viewwindowy = 0;
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
// Image postprocessing effect
if (rendermode == render_soft)
{
if (postimgtype)
V_DoPostProcessor(0, postimgtype, postimgparam);
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
}
}
// =========================================================================
// D_SRB2Loop
// =========================================================================
@ -588,9 +600,6 @@ void D_SRB2Loop(void)
if (dedicated)
server = true;
if (M_CheckParm("-voodoo")) // 256x256 Texture Limiter
COM_BufAddText("gr_voodoocompatibility on\n");
// Pushing of + parameters is now done back in D_SRB2Main, not here.
CONS_Printf("I_StartupKeyboard()...\n");
@ -903,7 +912,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"));
@ -1196,10 +1205,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.
@ -1208,7 +1217,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
@ -1305,14 +1314,21 @@ void D_SRB2Main(void)
sound_disabled = true;
midi_disabled = digital_disabled = true;
}
if (M_CheckParm("-noaudio")) // combines -nosound and -nomusic
{
sound_disabled = true;
digital_disabled = true;
midi_disabled = true;
}
else
{
CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
}
if (M_CheckParm("-nosound"))
sound_disabled = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
midi_disabled = digital_disabled = true;
{
digital_disabled = true;
midi_disabled = true;
}
else
{
if (M_CheckParm("-nomidimusic"))
@ -1320,9 +1336,18 @@ void D_SRB2Main(void)
if (M_CheckParm("-nodigmusic"))
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
}
}
if (!( sound_disabled && digital_disabled
#ifndef NO_MIDI
&& midi_disabled
#endif
))
{
CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
I_StartupSound();
I_InitMusic();
S_InitSfxChannels(cv_soundvolume.value);
}
CONS_Printf("ST_Init(): Init status bar.\n");
ST_Init();

View File

@ -54,4 +54,7 @@ const char *D_Home(void);
void D_AdvanceDemo(void);
void D_StartTitle(void);
/* Here for title maps */
void D_Render(void);
#endif //__D_MAIN__

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)
{
#endif
struct pingcell pingv[MAXPLAYERS];
INT32 pingc;
int name_width = 0;
int ms_width = 0;
int n;
INT32 i;
for (i = 0; i < MAXPLAYERS;i++)
pingc = 0;
for (i = 1; i < MAXPLAYERS; ++i)
if (playeringame[i])
{
#ifndef NEWPING
const INT32 node = playernode[i];
if (playeringame[i] && node != 0)
CONS_Printf(M_GetText("%.2d : %s\n %d tics, %d ms.\n"), i, player_names[i],
GetLag(node), G_TicsToMilliseconds(GetLag(node)));
#else
if (playeringame[i] && i != 0)
CONS_Printf(M_GetText("%.2d : %s\n %d ms\n"), i, player_names[i], playerpingtable[i]);
#endif
n = strlen(player_names[i]);
if (n > name_width)
name_width = n;
n = playerpingtable[i];
if (n > ms_width)
ms_width = n;
pingv[pingc].num = i;
pingv[pingc].ms = playerpingtable[i];
pingc++;
}
#ifndef NEWPING
if (ms_width < 10) ms_width = 1;
else if (ms_width < 100) ms_width = 2;
else ms_width = 3;
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
for (i = 0; i < pingc; ++i)
{
CONS_Printf("%02d : %-*s %*d ms\n",
pingv[i].num,
name_width, player_names[pingv[i].num],
ms_width, pingv[i].ms);
}
if (!server && playeringame[consoleplayer])
{
CONS_Printf("\nYour ping is %d ms\n", playerpingtable[consoleplayer]);
}
else
CONS_Printf(M_GetText("Only the server can use this.\n"));
#endif
}
void D_CloseConnection(void)

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,12 @@ 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;
char timedemo_csv_id[256];
boolean timedemo_quit;
INT16 gametype = GT_COOP;
boolean splitscreen = false;
@ -497,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);
@ -573,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);
@ -740,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);
@ -880,7 +885,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;
@ -921,14 +926,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
@ -1057,12 +1062,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)
{
@ -1187,12 +1192,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)
{
@ -1207,9 +1212,9 @@ static void SendNameAndColor(void)
players[consoleplayer].mo->color = players[consoleplayer].skincolor;
if (metalrecording)
{ // Metal Sonic is Sonic, obviously.
SetPlayerSkinByNum(consoleplayer, 0);
CV_StealthSet(&cv_skin, skins[0].name);
{ // Starring Metal Sonic as themselves, obviously.
SetPlayerSkinByNum(consoleplayer, 5);
CV_StealthSet(&cv_skin, skins[5].name);
}
else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin))
{
@ -1305,12 +1310,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)
{
@ -1570,11 +1575,11 @@ static void Command_Playdemo_f(void)
static void Command_Timedemo_f(void)
{
char name[256];
size_t i = 0;
if (COM_Argc() != 2)
if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("timedemo <demoname>: time a demo\n"));
CONS_Printf(M_GetText("timedemo <demoname> [-csv [<trialid>]] [-quit]: time a demo\n"));
return;
}
@ -1591,12 +1596,23 @@ static void Command_Timedemo_f(void)
G_StopMetalDemo();
// open the demo file
strcpy (name, COM_Argv(1));
strcpy (timedemo_name, COM_Argv(1));
// dont add .lmp so internal game demos can be played
CONS_Printf(M_GetText("Timing demo '%s'.\n"), name);
// print timedemo results as CSV?
i = COM_CheckParm("-csv");
timedemo_csv = (i > 0);
if (COM_CheckParm("-quit") != i + 1)
strcpy(timedemo_csv_id, COM_Argv(i + 1)); // user-defined string to identify row
else
timedemo_csv_id[0] = 0;
G_TimeDemo(name);
// exit after the timedemo?
timedemo_quit = (COM_CheckParm("-quit") > 0);
CONS_Printf(M_GetText("Timing demo '%s'.\n"), timedemo_name);
G_TimeDemo(timedemo_name);
}
// stop current demo
@ -1647,7 +1663,31 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
// The supplied data are assumed to be good.
I_Assert(delay >= 0 && delay <= 2);
if (mapnum != -1)
{
CV_SetValue(&cv_nextmap, mapnum);
// Kick bot from special stages
if (botskin)
{
if (G_IsSpecialStage(mapnum) || (mapheaderinfo[mapnum-1] && (mapheaderinfo[mapnum-1]->typeoflevel & TOL_NIGHTS)))
{
if (botingame)
{
//CL_RemoveSplitscreenPlayer();
botingame = false;
playeringame[1] = false;
}
}
else if (!botingame)
{
//CL_AddSplitscreenPlayer();
botingame = true;
secondarydisplayplayer = 1;
playeringame[1] = true;
players[1].bot = 1;
SendNameAndColor2();
}
}
}
CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d ultmode=%d resetplayers=%d delay=%d skipprecutscene=%d\n",
mapnum, newgametype, pultmode, resetplayers, delay, skipprecutscene);
if ((netgame || multiplayer) && !((gametype == newgametype) && (newgametype == GT_COOP)))
@ -1690,29 +1730,6 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
return;
}
// Kick bot from special stages
if (botskin)
{
if (G_IsSpecialStage(mapnum))
{
if (botingame)
{
//CL_RemoveSplitscreenPlayer();
botingame = false;
playeringame[1] = false;
}
}
else if (!botingame)
{
//CL_AddSplitscreenPlayer();
botingame = true;
secondarydisplayplayer = 1;
playeringame[1] = true;
players[1].bot = 1;
SendNameAndColor2();
}
}
chmappending++;
if (netgame)
WRITEUINT32(buf_p, M_RandomizedSeed()); // random seed
@ -2033,8 +2050,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"));
@ -2054,6 +2069,7 @@ static void Command_Suicide(void)
return;
}
WRITEINT32(cp, consoleplayer);
SendNetXCmd(XD_SUICIDE, &buf, 4);
}
@ -4466,3 +4482,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,14 +107,17 @@ 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;
extern consvar_t cv_sleep;
extern char timedemo_name[256];
extern boolean timedemo_csv;
extern char timedemo_csv_id[256];
extern boolean timedemo_quit;
typedef enum
{
XD_NAMEANDCOLOR = 1,
@ -190,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);
}
@ -2024,12 +2089,59 @@ static void readmenu(MYFILE *f, INT32 num)
menupres[num].bgcolor = get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "HIDEPICS"))
else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "HIDEPICS") || fastcmp(word, "TITLEPICSHIDE"))
{
// true by default, except MM_MAIN
menupres[num].hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSMODE"))
{
if (fastcmp(word2, "USER"))
menupres[num].ttmode = TTMODE_USER;
else if (fastcmp(word2, "ALACROIX"))
menupres[num].ttmode = TTMODE_ALACROIX;
else if (fastcmp(word2, "HIDE") || fastcmp(word2, "HIDDEN") || fastcmp(word2, "NONE"))
{
menupres[num].ttmode = TTMODE_USER;
menupres[num].ttname[0] = 0;
menupres[num].hidetitlepics = true;
}
else // if (fastcmp(word2, "OLD") || fastcmp(word2, "SSNTAILS"))
menupres[num].ttmode = TTMODE_OLD;
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSSCALE"))
{
// Don't handle Alacroix special case here; see Maincfg section.
menupres[num].ttscale = max(1, min(8, (UINT8)get_number(word2)));
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSNAME"))
{
strncpy(menupres[num].ttname, word2, 9);
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSX"))
{
menupres[num].ttx = (INT16)get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSY"))
{
menupres[num].tty = (INT16)get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSLOOP"))
{
menupres[num].ttloop = (INT16)get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSTICS"))
{
menupres[num].tttics = (UINT16)get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "TITLESCROLLSPEED") || fastcmp(word, "TITLESCROLLXSPEED")
|| fastcmp(word, "SCROLLSPEED") || fastcmp(word, "SCROLLXSPEED"))
{
@ -2243,6 +2355,7 @@ static actionpointer_t actionpointers[] =
{{A_ThrownRing}, "A_THROWNRING"},
{{A_SetSolidSteam}, "A_SETSOLIDSTEAM"},
{{A_UnsetSolidSteam}, "A_UNSETSOLIDSTEAM"},
{{A_SignSpin}, "S_SIGNSPIN"},
{{A_SignPlayer}, "A_SIGNPLAYER"},
{{A_OverlayThink}, "A_OVERLAYTHINK"},
{{A_JetChase}, "A_JETCHASE"},
@ -2447,6 +2560,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
@ -3419,11 +3540,78 @@ static void readmaincfg(MYFILE *f)
titlemap = (INT16)value;
titlechanged = true;
}
else if (fastcmp(word, "HIDETITLEPICS"))
else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "TITLEPICSHIDE"))
{
hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSMODE"))
{
if (fastcmp(word2, "USER"))
ttmode = TTMODE_USER;
else if (fastcmp(word2, "ALACROIX"))
ttmode = TTMODE_ALACROIX;
else if (fastcmp(word2, "HIDE") || fastcmp(word2, "HIDDEN") || fastcmp(word2, "NONE"))
{
ttmode = TTMODE_USER;
ttname[0] = 0;
hidetitlepics = true;
}
else // if (fastcmp(word2, "OLD") || fastcmp(word2, "SSNTAILS"))
ttmode = TTMODE_OLD;
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSSCALE"))
{
ttscale = max(1, min(8, (UINT8)get_number(word2)));
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSSCALESAVAILABLE"))
{
// SPECIAL CASE for Alacroix: Comma-separated list of resolutions that are available
// for gfx loading.
ttavailable[0] = ttavailable[1] = ttavailable[2] = ttavailable[3] =\
ttavailable[4] = ttavailable[5] = false;
if (strstr(word2, "1") != NULL)
ttavailable[0] = true;
if (strstr(word2, "2") != NULL)
ttavailable[1] = true;
if (strstr(word2, "3") != NULL)
ttavailable[2] = true;
if (strstr(word2, "4") != NULL)
ttavailable[3] = true;
if (strstr(word2, "5") != NULL)
ttavailable[4] = true;
if (strstr(word2, "6") != NULL)
ttavailable[5] = true;
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSNAME"))
{
strncpy(ttname, word2, 9);
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSX"))
{
ttx = (INT16)get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSY"))
{
tty = (INT16)get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSLOOP"))
{
ttloop = (INT16)get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "TITLEPICSTICS"))
{
tttics = (UINT16)get_number(word2);
titlechanged = true;
}
else if (fastcmp(word, "TITLESCROLLSPEED") || fastcmp(word, "TITLESCROLLXSPEED"))
{
titlescrollxspeed = get_number(word2);
@ -4185,6 +4373,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 +4473,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 +4624,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 +4825,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",
@ -5152,25 +5375,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CYBRAKDEMONVILEEXPLOSION3",
// Metal Sonic (Race)
// S_PLAY_STND
"S_METALSONIC_STAND",
// S_PLAY_TAP1
"S_METALSONIC_WAIT1",
"S_METALSONIC_WAIT2",
// S_PLAY_WALK
"S_METALSONIC_WALK1",
"S_METALSONIC_WALK2",
"S_METALSONIC_WALK3",
"S_METALSONIC_WALK4",
"S_METALSONIC_WALK5",
"S_METALSONIC_WALK6",
"S_METALSONIC_WALK7",
"S_METALSONIC_WALK8",
// S_PLAY_SPD1
"S_METALSONIC_RUN1",
"S_METALSONIC_RUN2",
"S_METALSONIC_RUN3",
"S_METALSONIC_RUN4",
"S_METALSONIC_RACE",
// Metal Sonic (Battle)
"S_METALSONIC_FLOAT",
"S_METALSONIC_VECTOR",
@ -5277,59 +5482,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BUBBLES4",
// Level End Sign
"S_SIGN1",
"S_SIGN2",
"S_SIGN3",
"S_SIGN4",
"S_SIGN5",
"S_SIGN6",
"S_SIGN7",
"S_SIGN8",
"S_SIGN9",
"S_SIGN10",
"S_SIGN11",
"S_SIGN12",
"S_SIGN13",
"S_SIGN14",
"S_SIGN15",
"S_SIGN16",
"S_SIGN17",
"S_SIGN18",
"S_SIGN19",
"S_SIGN20",
"S_SIGN21",
"S_SIGN22",
"S_SIGN23",
"S_SIGN24",
"S_SIGN25",
"S_SIGN26",
"S_SIGN27",
"S_SIGN28",
"S_SIGN29",
"S_SIGN30",
"S_SIGN31",
"S_SIGN32",
"S_SIGN33",
"S_SIGN34",
"S_SIGN35",
"S_SIGN36",
"S_SIGN37",
"S_SIGN38",
"S_SIGN39",
"S_SIGN40",
"S_SIGN41",
"S_SIGN42",
"S_SIGN43",
"S_SIGN44",
"S_SIGN45",
"S_SIGN46",
"S_SIGN47",
"S_SIGN48",
"S_SIGN49",
"S_SIGN50",
"S_SIGN51",
"S_SIGN52", // Eggman
"S_SIGN53",
"S_SIGN",
"S_SIGNSPIN1",
"S_SIGNSPIN2",
"S_SIGNSPIN3",
"S_SIGNSPIN4",
"S_SIGNSPIN5",
"S_SIGNSPIN6",
"S_SIGNPLAYER",
"S_SIGNSLOW",
"S_SIGNSTOP",
"S_SIGNBOARD",
"S_EGGMANSIGN",
// Spike Ball
"S_SPIKEBALL1",
@ -5554,7 +5718,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ARROW",
"S_ARROWBONK",
// Trapgoyle Demon fire
// Glaregoyle Demon fire
"S_DEMONFIRE",
// GFZ flowers
@ -5861,7 +6025,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 +6046,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,29 +6064,57 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLAMEJETFLAMEB2",
"S_FLAMEJETFLAMEB3",
// Trapgoyles
"S_TRAPGOYLE",
"S_TRAPGOYLE_CHECK",
"S_TRAPGOYLE_FIRE1",
"S_TRAPGOYLE_FIRE2",
"S_TRAPGOYLE_FIRE3",
"S_TRAPGOYLEUP",
"S_TRAPGOYLEUP_CHECK",
"S_TRAPGOYLEUP_FIRE1",
"S_TRAPGOYLEUP_FIRE2",
"S_TRAPGOYLEUP_FIRE3",
"S_TRAPGOYLEDOWN",
"S_TRAPGOYLEDOWN_CHECK",
"S_TRAPGOYLEDOWN_FIRE1",
"S_TRAPGOYLEDOWN_FIRE2",
"S_TRAPGOYLEDOWN_FIRE3",
"S_TRAPGOYLELONG",
"S_TRAPGOYLELONG_CHECK",
"S_TRAPGOYLELONG_FIRE1",
"S_TRAPGOYLELONG_FIRE2",
"S_TRAPGOYLELONG_FIRE3",
"S_TRAPGOYLELONG_FIRE4",
"S_TRAPGOYLELONG_FIRE5",
// 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",
// Glaregoyles
"S_GLAREGOYLE",
"S_GLAREGOYLE_CHARGE",
"S_GLAREGOYLE_BLINK",
"S_GLAREGOYLE_HOLD",
"S_GLAREGOYLE_FIRE",
"S_GLAREGOYLE_LOOP",
"S_GLAREGOYLE_COOLDOWN",
"S_GLAREGOYLEUP",
"S_GLAREGOYLEUP_CHARGE",
"S_GLAREGOYLEUP_BLINK",
"S_GLAREGOYLEUP_HOLD",
"S_GLAREGOYLEUP_FIRE",
"S_GLAREGOYLEUP_LOOP",
"S_GLAREGOYLEUP_COOLDOWN",
"S_GLAREGOYLEDOWN",
"S_GLAREGOYLEDOWN_CHARGE",
"S_GLAREGOYLEDOWN_BLINK",
"S_GLAREGOYLEDOWN_HOLD",
"S_GLAREGOYLEDOWN_FIRE",
"S_GLAREGOYLEDOWN_LOOP",
"S_GLAREGOYLEDOWN_COOLDOWN",
"S_GLAREGOYLELONG",
"S_GLAREGOYLELONG_CHARGE",
"S_GLAREGOYLELONG_BLINK",
"S_GLAREGOYLELONG_HOLD",
"S_GLAREGOYLELONG_FIRE",
"S_GLAREGOYLELONG_LOOP",
"S_GLAREGOYLELONG_COOLDOWN",
// ATZ's Red Crystal/Target
"S_TARGET_IDLE",
@ -5925,6 +6123,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_TARGET_RESPAWN",
"S_TARGET_ALLDONE",
// ATZ's green flame
"S_GREENFLAME",
// ATZ Blue Gargoyle
"S_BLUEGARGOYLE",
// Stalagmites
"S_STG0",
"S_STG1",
@ -5945,6 +6149,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 +6157,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 +6818,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 +6848,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",
@ -7090,8 +7318,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BUMBLEBORE_STUCK2",
"S_BUMBLEBORE_DIE",
"S_BBUZZFLY1",
"S_BBUZZFLY2",
"S_BUGGLEIDLE",
"S_BUGGLEFLY",
"S_SMASHSPIKE_FLOAT",
"S_SMASHSPIKE_EASE1",
@ -7234,6 +7462,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 +7481,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 +7504,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 +7620,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
@ -7474,7 +7715,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_CANNONBALL", // Cannonball
"MT_CANNONBALLDECOR", // Decorative/still cannonball
"MT_ARROW", // Arrow
"MT_DEMONFIRE", // Trapgoyle fire
"MT_DEMONFIRE", // Glaregoyle fire
// Greenflower Scenery
"MT_GFZFLOWER1",
@ -7601,7 +7842,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,16 +7859,32 @@ 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
// Azure Temple Scenery
"MT_TRAPGOYLE",
"MT_TRAPGOYLEUP",
"MT_TRAPGOYLEDOWN",
"MT_TRAPGOYLELONG",
"MT_GLAREGOYLE",
"MT_GLAREGOYLEUP",
"MT_GLAREGOYLEDOWN",
"MT_GLAREGOYLELONG",
"MT_TARGET",
"MT_GREENFLAME",
"MT_BLUEGARGOYLE",
// Stalagmites
"MT_STALAGMITE0",
@ -7649,6 +7906,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 +7914,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 +8044,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
@ -7898,7 +8159,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_HIVEELEMENTAL",
"MT_BUMBLEBORE",
"MT_BUBBLEBUZZ",
"MT_BUGGLE",
"MT_SMASHINGSPIKEBALL",
"MT_CACOLANTERN",
@ -8269,6 +8530,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 +8872,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 +9095,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 +9228,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 +9262,7 @@ struct {
{"TC_ALLWHITE",TC_ALLWHITE},
{"TC_RAINBOW",TC_RAINBOW},
{"TC_BLINK",TC_BLINK},
{"TC_DASHMODE",TC_DASHMODE},
#endif
{NULL,0}
@ -9982,6 +10249,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

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

@ -326,16 +326,18 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
/* Miscellaneous types that don't fit anywhere else (Can this be changed?) */
union FColorRGBA
{
UINT32 rgba;
struct
typedef struct
{
UINT8 red;
UINT8 green;
UINT8 blue;
UINT8 alpha;
} s;
} byteColor_t;
union FColorRGBA
{
UINT32 rgba;
byteColor_t s;
} ATTRPACK;
typedef union FColorRGBA RGBA_t;

File diff suppressed because it is too large Load Diff

View File

@ -77,6 +77,28 @@ void F_ContinueDrawer(void);
extern INT32 titlescrollxspeed;
extern INT32 titlescrollyspeed;
typedef enum
{
TTMODE_NONE = 0,
TTMODE_OLD,
TTMODE_ALACROIX,
TTMODE_USER
} ttmode_enum;
#define TTMAX_ALACROIX 30 // max frames for SONIC typeface, plus one for NULL terminating entry
#define TTMAX_USER 100
extern ttmode_enum ttmode;
extern UINT8 ttscale;
// ttmode user vars
extern char ttname[9];
extern INT16 ttx;
extern INT16 tty;
extern INT16 ttloop;
extern UINT16 tttics;
extern boolean ttavailable[6];
typedef enum
{
TITLEMAP_OFF = 0,
@ -89,11 +111,21 @@ typedef enum
extern mobj_t *titlemapcameraref;
extern char curbgname[9];
extern SINT8 curfadevalue;
extern boolean curhidepics;
extern INT32 curbgcolor;
extern INT32 curbgxspeed;
extern INT32 curbgyspeed;
extern boolean curbghide;
extern boolean hidetitlemap;
extern boolean curhidepics;
extern ttmode_enum curttmode;
extern UINT8 curttscale;
// ttmode user vars
extern char curttname[9];
extern INT16 curttx;
extern INT16 curtty;
extern INT16 curttloop;
extern UINT16 curtttics;
#define TITLEBACKGROUNDACTIVE (curfadevalue >= 0 || curbgname[0])

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@ extern boolean playeringame[MAXPLAYERS];
// demoplaying back and demo recording
extern boolean demoplayback, titledemo, demorecording, timingdemo;
extern tic_t demostarttime;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
@ -59,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;
@ -172,7 +175,7 @@ void G_AddGhost(char *defdemoname);
void G_DoPlayMetal(void);
void G_DoneLevelLoad(void);
void G_StopMetalDemo(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill);
void G_StopDemo(void);
boolean G_CheckDemoStatus(void);

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

@ -505,43 +505,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
if (blockheight < 1)
I_Error("3D GenerateTexture : too small");
}
else if (cv_voodoocompatibility.value)
{
if (originalwidth > 256 || originalheight > 256)
{
blockwidth = 256;
while (originalwidth < blockwidth)
blockwidth >>= 1;
if (blockwidth < 1)
I_Error("3D GenerateTexture : too small");
blockheight = 256;
while (originalheight < blockheight)
blockheight >>= 1;
if (blockheight < 1)
I_Error("3D GenerateTexture : too small");
}
else
{
//size up to nearest power of 2
blockwidth = 1;
while (blockwidth < originalwidth)
blockwidth <<= 1;
// scale down the original graphics to fit in 256
if (blockwidth > 256)
blockwidth = 256;
//I_Error("3D GenerateTexture : too big");
//size up to nearest power of 2
blockheight = 1;
while (blockheight < originalheight)
blockheight <<= 1;
// scale down the original graphics to fit in 256
if (blockheight > 256)
blockheight = 255;
//I_Error("3D GenerateTexture : too big");
}
}
else
{
#ifdef GLIDE_API_COMPATIBILITY
@ -690,7 +653,9 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
// Composite the columns together.
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
{
#ifndef NO_PNG_LUMPS
size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump);
#endif
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
@ -768,18 +733,6 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
newwidth = blockwidth;
newheight = blockheight;
}
else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256.
{
// no rounddown, do not size up patches, so they don't look 'scaled'
newwidth = min(grPatch->width, blockwidth);
newheight = min(grPatch->height, blockheight);
if (newwidth > 256 || newheight > 256)
{
newwidth = blockwidth;
newheight = blockheight;
}
}
else
{
// no rounddown, do not size up patches, so they don't look 'scaled'
@ -821,10 +774,10 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch)
{
GLPatch_t* const grpatch = patch;
(void)patchnum; //unused
while (grpatch->mipmap.nextcolormap)
while (grpatch->mipmap->nextcolormap)
{
GLMipmap_t *grmip = grpatch->mipmap.nextcolormap;
grpatch->mipmap.nextcolormap = grmip->nextcolormap;
GLMipmap_t *grmip = grpatch->mipmap->nextcolormap;
grpatch->mipmap->nextcolormap = grmip->nextcolormap;
if (grmip->grInfo.data) Z_Free(grmip->grInfo.data);
free(grmip);
}
@ -927,29 +880,6 @@ GLTexture_t *HWR_GetTexture(INT32 tex)
return grtex;
}
// HWR_RenderPlane and HWR_RenderPolyObjectPlane need this to get the flat dimensions from a patch.
lumpnum_t gr_patchflat;
static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
{
UINT8 *flat;
patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC);
size_t lumplength = W_LumpLength(flatlumpnum);
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)patch, lumplength))
patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL, false);
#endif
grMipmap->width = (UINT16)SHORT(patch->width);
grMipmap->height = (UINT16)SHORT(patch->height);
flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data);
memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height);
R_PatchToFlat(patch, flat);
}
static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
{
size_t size, pflatsize;
@ -990,10 +920,6 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
break;
}
if (R_CheckIfPatch(flatlumpnum))
HWR_LoadPatchFlat(grMipmap, flatlumpnum);
else
{
grMipmap->width = (UINT16)pflatsize;
grMipmap->height = (UINT16)pflatsize;
@ -1001,35 +927,14 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
PU_HWRCACHE, &grMipmap->grInfo.data));
}
}
// Download a Doom 'flat' to the hardware cache and make it ready for use
void HWR_GetFlat(lumpnum_t flatlumpnum)
static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
{
GLMipmap_t *grmip;
UINT8 *flat;
if (needpatchflush)
W_FlushCachedPatches();
grmip = &HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data)
HWR_CacheFlat(grmip, flatlumpnum);
HWD.pfnSetTexture(grmip);
// The system-memory data can be purged now.
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
gr_patchflat = 0;
if (R_CheckIfPatch(flatlumpnum))
gr_patchflat = flatlumpnum;
}
static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
{
UINT8 *flat;
// setup the texture info
#ifdef GLIDE_API_COMPATIBILITY
grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64;
@ -1048,25 +953,57 @@ static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
R_TextureToFlat(texturenum, flat);
}
void HWR_GetTextureFlat(INT32 texturenum)
// Download a Doom 'flat' to the hardware cache and make it ready for use
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
{
GLMipmap_t *grmip;
if (flatlumpnum == LUMPERROR)
return;
if (needpatchflush)
W_FlushCachedPatches();
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data)
HWR_CacheFlat(grmip, flatlumpnum);
HWD.pfnSetTexture(grmip);
// The system-memory data can be purged now.
Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
}
void HWR_GetLevelFlat(levelflat_t *levelflat)
{
// Who knows?
if (levelflat == NULL)
return;
if (levelflat->type == LEVELFLAT_FLAT)
HWR_LiterallyGetFlat(levelflat->u.flat.lumpnum);
else if (levelflat->type == LEVELFLAT_TEXTURE)
{
GLTexture_t *grtex;
INT32 texturenum = levelflat->u.texture.num;
#ifdef PARANOIA
if ((unsigned)texturenum >= gr_numtextures)
I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n");
I_Error("HWR_GetLevelFlat: texturenum >= numtextures\n");
#endif
if (texturenum == 0 || texturenum == -1)
return;
grtex = &gr_textures2[texturenum];
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
HWR_LoadTextureFlat(&grtex->mipmap, texturenum);
HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum);
HWD.pfnSetTexture(&grtex->mipmap);
// The system-memory data can be purged now.
Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
}
else // set no texture
HWD.pfnSetTexture(NULL);
}
//
// HWR_LoadMappedPatch(): replace the skin color of the sprite in cache
@ -1097,22 +1034,22 @@ void HWR_GetPatch(GLPatch_t *gpatch)
W_FlushCachedPatches();
// is it in hardware cache
if (!gpatch->mipmap.downloaded && !gpatch->mipmap.grInfo.data)
if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data)
{
// load the software patch, PU_STATIC or the Z_Malloc for hardware patch will
// flush the software patch before the conversion! oh yeah I suffered
patch_t *ptr = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
HWR_MakePatch(ptr, gpatch, &gpatch->mipmap, true);
HWR_MakePatch(ptr, gpatch, gpatch->mipmap, true);
// this is inefficient.. but the hardware patch in heap is purgeable so it should
// not fragment memory, and besides the REAL cache here is the hardware memory
Z_Free(ptr);
}
HWD.pfnSetTexture(&gpatch->mipmap);
HWD.pfnSetTexture(gpatch->mipmap);
// The system-memory patch data can be purged now.
Z_ChangeTag(gpatch->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED);
}
@ -1135,7 +1072,7 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
// search for the mimmap
// skip the first (no colormap translated)
for (grmip = &gpatch->mipmap; grmip->nextcolormap; )
for (grmip = gpatch->mipmap; grmip->nextcolormap; )
{
grmip = grmip->nextcolormap;
if (grmip->colormap == colormap)
@ -1165,7 +1102,7 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch)
if (!gpatch)
return;
Z_ChangeTag(gpatch->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED);
Z_ChangeTag(gpatch, PU_HWRPATCHINFO_UNLOCKED);
}
@ -1256,7 +1193,7 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
grpatch = HWR_GetCachedGLPatch(lumpnum);
if (!grpatch->mipmap.downloaded && !grpatch->mipmap.grInfo.data)
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data)
{
pic_t *pic;
UINT8 *block;
@ -1272,19 +1209,19 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
grpatch->topoffset = 0;
// find the good 3dfx size (boring spec)
HWR_ResizeBlock (grpatch->width, grpatch->height, &grpatch->mipmap.grInfo);
grpatch->mipmap.width = (UINT16)blockwidth;
grpatch->mipmap.height = (UINT16)blockheight;
HWR_ResizeBlock (grpatch->width, grpatch->height, &grpatch->mipmap->grInfo);
grpatch->mipmap->width = (UINT16)blockwidth;
grpatch->mipmap->height = (UINT16)blockheight;
if (pic->mode == PALETTE)
grpatch->mipmap.grInfo.format = textureformat; // can be set by driver
grpatch->mipmap->grInfo.format = textureformat; // can be set by driver
else
grpatch->mipmap.grInfo.format = picmode2GR[pic->mode];
grpatch->mipmap->grInfo.format = picmode2GR[pic->mode];
Z_Free(grpatch->mipmap.grInfo.data);
Z_Free(grpatch->mipmap->grInfo.data);
// allocate block
block = MakeBlock(&grpatch->mipmap);
block = MakeBlock(grpatch->mipmap);
// if rounddown, rounddown patches as well as textures
if (cv_grrounddown.value)
@ -1292,18 +1229,6 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
newwidth = blockwidth;
newheight = blockheight;
}
else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256.
{
// no rounddown, do not size up patches, so they don't look 'scaled'
newwidth = min(SHORT(pic->width),blockwidth);
newheight = min(SHORT(pic->height),blockheight);
if (newwidth > 256 || newheight > 256)
{
newwidth = blockwidth;
newheight = blockheight;
}
}
else
{
// no rounddown, do not size up patches, so they don't look 'scaled'
@ -1314,25 +1239,25 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
if (grpatch->width == blockwidth &&
grpatch->height == blockheight &&
format2bpp[grpatch->mipmap.grInfo.format] == format2bpp[picmode2GR[pic->mode]])
format2bpp[grpatch->mipmap->grInfo.format] == format2bpp[picmode2GR[pic->mode]])
{
// no conversion needed
M_Memcpy(grpatch->mipmap.grInfo.data, pic->data,len);
M_Memcpy(grpatch->mipmap->grInfo.data, pic->data,len);
}
else
HWR_DrawPicInCache(block, newwidth, newheight,
blockwidth*format2bpp[grpatch->mipmap.grInfo.format],
blockwidth*format2bpp[grpatch->mipmap->grInfo.format],
pic,
format2bpp[grpatch->mipmap.grInfo.format]);
format2bpp[grpatch->mipmap->grInfo.format]);
Z_Unlock(pic);
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
grpatch->mipmap.flags = 0;
grpatch->mipmap->flags = 0;
grpatch->max_s = (float)newwidth / (float)blockwidth;
grpatch->max_t = (float)newheight / (float)blockheight;
}
HWD.pfnSetTexture(&grpatch->mipmap);
HWD.pfnSetTexture(grpatch->mipmap);
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.grInfo.data, grpatch->mipmap.downloaded);
return grpatch;
@ -1348,6 +1273,7 @@ GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum)
grpatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL);
grpatch->wadnum = wadnum;
grpatch->lumpnum = lumpnum;
grpatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
M_AATreeSet(hwrcache, lumpnum, grpatch);
}
@ -1454,7 +1380,7 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
if (needpatchflush)
W_FlushCachedPatches();
grmip = &HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap;
if (!grmip->downloaded && !grmip->grInfo.data)
HWR_CacheFadeMask(grmip, fademasklumpnum);

View File

@ -77,8 +77,8 @@
#include "r_opengl/r_opengl.h"
#ifdef HAVE_SPHEREFRUSTRUM
static GLdouble viewMatrix[16];
static GLdouble projMatrix[16];
static GLfloat viewMatrix[16];
static GLfloat projMatrix[16];
float frustum[6][4];
#endif
@ -380,8 +380,8 @@ void gld_FrustrumSetup(void)
float t;
float clip[16];
pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix);
pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
clip[1] = CALCMATRIX(0, 1, 1, 5, 2, 9, 3, 13);

View File

@ -83,8 +83,8 @@ struct GLPatch_s
float max_s,max_t;
UINT16 wadnum; // the software patch lump num for when the hardware patch
UINT16 lumpnum; // was flushed, and we need to re-create it
GLMipmap_t mipmap;
};
GLMipmap_t *mipmap;
} ATTRPACK;
typedef struct GLPatch_s GLPatch_t;
#endif //_HWR_DATA_

View File

@ -95,14 +95,29 @@ typedef struct
//Hurdler: Transform (coords + angles)
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
// Kart features
//#define USE_FTRANSFORM_ANGLEZ
//#define USE_FTRANSFORM_MIRROR
// Vanilla features
#define USE_MODEL_NEXTFRAME
typedef struct
{
FLOAT x,y,z; // position
#ifdef USE_FTRANSFORM_ANGLEZ
FLOAT anglex,angley,anglez; // aimingangle / viewangle
#else
FLOAT anglex,angley; // aimingangle / viewangle
#endif
FLOAT scalex,scaley,scalez;
FLOAT fovxangle, fovyangle;
INT32 splitscreen;
UINT8 splitscreen;
boolean flip; // screenflip
#ifdef USE_FTRANSFORM_MIRROR
boolean mirror; // SRB2Kart: Encore Mode
#endif
} FTransform;
// Transformed vector, as passed to HWR API
@ -145,7 +160,7 @@ enum EPolyFlags
// When set, pass the color constant into the FSurfaceInfo -> FlatColor
PF_NoTexture = 0x00002000, // Use the small white texture
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
PF_MD2 = 0x00008000, // Tell the rendrer we are drawing an MD2
PF_Unused = 0x00008000, // Unused
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
@ -203,8 +218,6 @@ enum hwdsetspecialstate
HWD_SET_FOG_COLOR,
HWD_SET_FOG_DENSITY,
HWD_SET_FOV,
HWD_SET_POLYGON_SMOOTH,
HWD_SET_PALETTECOLOR,
HWD_SET_TEXTUREFILTERMODE,
HWD_SET_TEXTUREANISOTROPICMODE,
HWD_NUMSTATE

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

@ -647,7 +647,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
v[0].tow = v[1].tow = (float)((y & flatflag)/dflatsize);
v[2].tow = v[3].tow = (float)(v[0].tow + h/dflatsize);
HWR_GetFlat(flatlumpnum);
HWR_LiterallyGetFlat(flatlumpnum);
//Hurdler: Boris, the same comment as above... but maybe for pics
// it not a problem since they don't have any transparent pixel

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);
@ -58,20 +59,18 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale);
EXPORT void HWRAPI(DrawMD2i) (INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
EXPORT INT32 HWRAPI(GetRenderVersion) (void);
#ifdef SHUFFLE
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
#endif
EXPORT void HWRAPI(FlushScreenTextures) (void);
EXPORT void HWRAPI(StartScreenWipe) (void);
EXPORT void HWRAPI(EndScreenWipe) (void);
EXPORT void HWRAPI(DoScreenWipe) (float alpha);
EXPORT void HWRAPI(DoScreenWipe) (void);
EXPORT void HWRAPI(DrawIntermissionBG) (void);
EXPORT void HWRAPI(MakeScreenTexture) (void);
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
@ -89,6 +88,7 @@ struct hwdriver_s
FinishUpdate pfnFinishUpdate;
Draw2DLine pfnDraw2DLine;
DrawPolygon pfnDrawPolygon;
RenderSkyDome pfnRenderSkyDome;
SetBlend pfnSetBlend;
ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture;
@ -96,8 +96,8 @@ struct hwdriver_s
GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache;
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
DrawMD2 pfnDrawMD2;
DrawMD2i pfnDrawMD2i;
DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs;
SetTransform pfnSetTransform;
GetTextureUsed pfnGetTextureUsed;
GetRenderVersion pfnGetRenderVersion;
@ -107,9 +107,7 @@ struct hwdriver_s
#ifndef HAVE_SDL
Shutdown pfnShutdown;
#endif
#ifdef SHUFFLE
PostImgRedraw pfnPostImgRedraw;
#endif
FlushScreenTextures pfnFlushScreenTextures;
StartScreenWipe pfnStartScreenWipe;
EndScreenWipe pfnEndScreenWipe;

View File

@ -23,6 +23,7 @@
#include "hw_defs.h"
#include "hw_main.h"
#include "../m_misc.h"
#include "../p_setup.h"
// the original aspect ratio of Doom graphics isn't square
#define ORIGINAL_ASPECT (320.0f/200.0f)
@ -101,8 +102,8 @@ void HWR_FreeTextureCache(void);
void HWR_FreeColormaps(void);
void HWR_FreeExtraSubsectors(void);
void HWR_GetFlat(lumpnum_t flatlumpnum);
void HWR_GetTextureFlat(INT32 texturenum);
void HWR_GetLevelFlat(levelflat_t *levelflat);
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum);
GLTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetPatch(GLPatch_t *gpatch);
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap);
@ -116,8 +117,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
// --------
// hw_draw.c
// --------
extern lumpnum_t gr_patchflat;
extern float gr_patch_scalex;
extern float gr_patch_scaley;

View File

@ -162,6 +162,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_TURR
&lspr[NOLIGHT], // SPR_SHRP
&lspr[NOLIGHT], // SPR_CRAB
&lspr[NOLIGHT], // SPR_CR2B
&lspr[NOLIGHT], // SPR_CSPR
&lspr[NOLIGHT], // SPR_JJAW
&lspr[NOLIGHT], // SPR_SNLR
&lspr[NOLIGHT], // SPR_VLTR
@ -180,6 +182,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_UNID
&lspr[NOLIGHT], // SPR_CANA
&lspr[NOLIGHT], // SPR_CANG
&lspr[NOLIGHT], // SPR_PYRE
&lspr[NOLIGHT], // SPR_PTER
// Generic Boos Items
&lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes
@ -197,7 +201,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_EGGO
&lspr[NOLIGHT], // SPR_SEBH
&lspr[NOLIGHT], // SPR_FAKE
&lspr[NOLIGHT], // SPR_SHCK
&lspr[LBLUESHINE_L],// SPR_SHCK
// Boss 4 (Castle Eggman)
&lspr[NOLIGHT], // SPR_EGGP
@ -260,6 +264,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_WSPB
&lspr[NOLIGHT], // SPR_STPT
&lspr[NOLIGHT], // SPR_BMNE
&lspr[NOLIGHT], // SPR_PUMI
// Monitor Boxes
&lspr[NOLIGHT], // SPR_MSTV
@ -377,6 +382,10 @@ light_t *t_lspr[NUMSPRITES] =
// Red Volcano Scenery
&lspr[REDBALL_L], // SPR_FLME
&lspr[REDBALL_L], // SPR_DFLM
&lspr[NOLIGHT], // SPR_LFAL
&lspr[NOLIGHT], // SPR_JPLA
&lspr[NOLIGHT], // SPR_TFLO
&lspr[NOLIGHT], // SPR_WVIN
// Dark City Scenery
@ -388,7 +397,9 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_XMS3
&lspr[NOLIGHT], // SPR_XMS4
&lspr[NOLIGHT], // SPR_XMS5
&lspr[NOLIGHT], // SPR_XMS6
&lspr[NOLIGHT], // SPR_FHZI
&lspr[NOLIGHT], // SPR_ROSY
// Halloween Scenery
&lspr[RINGLIGHT_L], // SPR_PUMK
@ -396,6 +407,11 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SHRM
&lspr[NOLIGHT], // SPR_HHZM
// Azure Temple Scenery
&lspr[NOLIGHT], // SPR_BGAR
&lspr[NOLIGHT], // SPR_RCRY
&lspr[GREENBALL_L], // SPR_CFLM
// Botanic Serenity Scenery
&lspr[NOLIGHT], // SPR_BSZ1
&lspr[NOLIGHT], // SPR_BSZ2
@ -415,7 +431,6 @@ light_t *t_lspr[NUMSPRITES] =
// Misc Scenery
&lspr[NOLIGHT], // SPR_STLG
&lspr[NOLIGHT], // SPR_DBAL
&lspr[NOLIGHT], // SPR_RCRY
// Powerup Indicators
&lspr[NOLIGHT], // SPR_ARMA
@ -469,11 +484,14 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SSWY
&lspr[NOLIGHT], // SPR_SSWR
&lspr[NOLIGHT], // SPR_SSWB
&lspr[NOLIGHT], // SPR_BSTY
&lspr[NOLIGHT], // SPR_BSTR
// Environmental Effects
&lspr[NOLIGHT], // SPR_RAIN
&lspr[NOLIGHT], // SPR_SNO1
&lspr[NOLIGHT], // SPR_SPLH
&lspr[NOLIGHT], // SPR_LSPL
&lspr[NOLIGHT], // SPR_SPLA
&lspr[NOLIGHT], // SPR_SMOK
&lspr[NOLIGHT], // SPR_BUBL
@ -1187,7 +1205,8 @@ void HWR_DL_AddLight(gr_vissprite_t *spr, GLPatch_t *patch)
dynlights->nb++;
}
static GLPatch_t lightmappatch;
static GLMipmap_t lightmappatchmipmap;
static GLPatch_t lightmappatch = { .mipmap = &lightmappatchmipmap };
void HWR_InitLight(void)
{
@ -1197,7 +1216,7 @@ void HWR_InitLight(void)
for (i = 0;i < NUMLIGHTS;i++)
lspr[i].dynamic_sqrradius = lspr[i].dynamic_radius*lspr[i].dynamic_radius;
lightmappatch.mipmap.downloaded = false;
lightmappatch.mipmap->downloaded = false;
coronalumpnum = W_CheckNumForName("CORONA");
}
@ -1208,10 +1227,10 @@ static void HWR_SetLight(void)
{
int i, j;
if (!lightmappatch.mipmap.downloaded && !lightmappatch.mipmap.grInfo.data)
if (!lightmappatch.mipmap->downloaded && !lightmappatch.mipmap->grInfo.data)
{
UINT16 *Data = Z_Malloc(129*128*sizeof (UINT16), PU_HWRCACHE, &lightmappatch.mipmap.grInfo.data);
UINT16 *Data = Z_Malloc(129*128*sizeof (UINT16), PU_HWRCACHE, &lightmappatch.mipmap->grInfo.data);
for (i = 0; i < 128; i++)
{
@ -1224,23 +1243,23 @@ static void HWR_SetLight(void)
Data[i*128+j] = 0;
}
}
lightmappatch.mipmap.grInfo.format = GR_TEXFMT_ALPHA_INTENSITY_88;
lightmappatch.mipmap->grInfo.format = GR_TEXFMT_ALPHA_INTENSITY_88;
lightmappatch.width = 128;
lightmappatch.height = 128;
lightmappatch.mipmap.width = 128;
lightmappatch.mipmap.height = 128;
lightmappatch.mipmap->width = 128;
lightmappatch.mipmap->height = 128;
#ifdef GLIDE_API_COMPATIBILITY
lightmappatch.mipmap.grInfo.smallLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap.grInfo.largeLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap.grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
lightmappatch.mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_128;
lightmappatch.mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
#endif
lightmappatch.mipmap.flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw !
lightmappatch.mipmap->flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw !
}
HWD.pfnSetTexture(&lightmappatch.mipmap);
HWD.pfnSetTexture(lightmappatch.mipmap);
// The system-memory data can be purged now.
Z_ChangeTag(lightmappatch.mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
Z_ChangeTag(lightmappatch.mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED);
}
//**********************************************************

View File

@ -70,12 +70,12 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
#endif
#ifdef SORTING
void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
#else
static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub, fixed_t fixedheight,
INT32 lightlevel, INT32 alpha, sector_t *FOFSector);
static void HWR_Render3DWater(void);
static void HWR_RenderTransparentWalls(void);
@ -522,7 +522,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c
// HWR_RenderPlane : Render a floor or ceiling convex polygon
// -----------------+
static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
{
polyvertex_t * pv;
float height; //constant y for all points on the convex flat polygon
@ -530,9 +530,9 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
INT32 nrPlaneVerts; //verts original define of convex flat polygon
INT32 i;
float flatxref,flatyref;
float fflatwidth, fflatheight;
INT32 flatflag;
boolean texflat = true;
float fflatwidth = 64.0f, fflatheight = 64.0f;
INT32 flatflag = 63;
boolean texflat = false;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
@ -541,7 +541,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
#ifdef ESLOPE
pslope_t *slope = NULL;
#endif
patch_t *patch;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
@ -597,7 +596,18 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
}
len = W_LumpLength(lumpnum);
// set texture for polygon
if (levelflat != NULL)
{
if (levelflat->type == LEVELFLAT_TEXTURE)
{
fflatwidth = textures[levelflat->u.texture.num]->width;
fflatheight = textures[levelflat->u.texture.num]->height;
texflat = true;
}
else if (levelflat->type == LEVELFLAT_FLAT)
{
len = W_LumpLength(levelflat->u.flat.lumpnum);
switch (len)
{
@ -625,20 +635,10 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
}
flatflag = ((INT32)fflatwidth)-1;
if (texturenum != 0 && texturenum != -1)
{
fflatwidth = textures[texturenum]->width;
fflatheight = textures[texturenum]->height;
}
else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case?
{
patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
fflatwidth = SHORT(patch->width);
fflatheight = SHORT(patch->height);
}
else
texflat = false;
else // set no texture
HWD.pfnSetTexture(NULL);
// reference point for flat texture coord for each vertex around the polygon
flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth);
@ -1972,7 +1972,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
{
// Single sided line... Deal only with the middletexture (if one exists)
gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
if (gr_midtexture)
if (gr_midtexture && gr_linedef->special != 41) // Ignore horizon line for OGL
{
{
fixed_t texturevpeg;
@ -3183,23 +3183,22 @@ static inline void HWR_AddPolyObjectSegs(void)
#ifdef POLYOBJECTS_PLANES
static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, INT32 texturenum, sector_t *FOFsector,
FBITFIELD blendmode, UINT8 lightlevel, levelflat_t *levelflat, sector_t *FOFsector,
UINT8 alpha, extracolormap_t *planecolormap)
{
float height; //constant y for all points on the convex flat polygon
FOutVector *v3d;
INT32 i;
float flatxref,flatyref;
float fflatwidth, fflatheight;
INT32 flatflag;
boolean texflat = true;
float fflatwidth = 64.0f, fflatheight = 64.0f;
INT32 flatflag = 63;
boolean texflat = false;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
FSurfaceInfo Surf;
fixed_t tempxsow, tempytow;
size_t nrPlaneVerts;
patch_t *patch;
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
@ -3225,7 +3224,18 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
}
len = W_LumpLength(lumpnum);
// set texture for polygon
if (levelflat != NULL)
{
if (levelflat->type == LEVELFLAT_TEXTURE)
{
fflatwidth = textures[levelflat->u.texture.num]->width;
fflatheight = textures[levelflat->u.texture.num]->height;
texflat = true;
}
else if (levelflat->type == LEVELFLAT_FLAT)
{
len = W_LumpLength(levelflat->u.flat.lumpnum);
switch (len)
{
@ -3253,20 +3263,10 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
}
flatflag = ((INT32)fflatwidth)-1;
if (texturenum != 0 && texturenum != -1)
{
fflatwidth = textures[texturenum]->width;
fflatheight = textures[texturenum]->height;
}
else if (gr_patchflat && R_CheckIfPatch(gr_patchflat)) // Just in case?
{
patch = (patch_t *)W_CacheLumpNum(gr_patchflat, PU_STATIC);
fflatwidth = SHORT(patch->width);
fflatheight = SHORT(patch->height);
}
else
texflat = false;
else // set no texture
HWD.pfnSetTexture(NULL);
// reference point for flat texture coord for each vertex around the polygon
flatxref = (float)((polysector->origVerts[0].x & (~flatflag)) / fflatwidth);
@ -3400,15 +3400,14 @@ static void HWR_AddPolyObjectPlanes(void)
FBITFIELD blendmode;
memset(&Surf, 0x00, sizeof(Surf));
blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], false, polyobjsector->floorheight,
HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->floorpic], po_ptrs[i], false, polyobjsector->floorheight,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum);
HWR_GetTextureFlat(levelflats[polyobjsector->floorpic].texturenum);
HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic]);
HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic],
polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
}
@ -3424,15 +3423,14 @@ static void HWR_AddPolyObjectPlanes(void)
FBITFIELD blendmode;
memset(&Surf, 0x00, sizeof(Surf));
blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum, po_ptrs[i], true, polyobjsector->ceilingheight,
HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->ceilingpic], po_ptrs[i], true, polyobjsector->ceilingheight,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), Surf.FlatColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
else
{
HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum);
HWR_GetTextureFlat(levelflats[polyobjsector->ceilingpic].texturenum);
HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic]);
HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), levelflats[polyobjsector->floorpic].lumpnum, levelflats[polyobjsector->floorpic].texturenum,
(light == -1 ? gr_frontsector->lightlevel : *gr_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic],
polyobjsector, 255, (light == -1 ? gr_frontsector->extra_colormap : *gr_frontsector->lightlist[light].extra_colormap));
}
}
@ -3583,13 +3581,12 @@ static void HWR_Subsector(size_t num)
{
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum);
HWR_GetTextureFlat(levelflats[gr_frontsector->floorpic].texturenum);
HWR_GetLevelFlat(&levelflats[gr_frontsector->floorpic]);
HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false,
// Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, levelflats[gr_frontsector->floorpic].texturenum, NULL, 255, false, floorcolormap);
PF_Occlude, floorlightlevel, &levelflats[gr_frontsector->floorpic], NULL, 255, false, floorcolormap);
}
}
else
@ -3606,13 +3603,12 @@ static void HWR_Subsector(size_t num)
{
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum);
HWR_GetTextureFlat(levelflats[gr_frontsector->ceilingpic].texturenum);
HWR_GetLevelFlat(&levelflats[gr_frontsector->ceilingpic]);
HWR_RenderPlane(NULL, &extrasubsectors[num], true,
// Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum, levelflats[gr_frontsector->ceilingpic].texturenum, NULL, 255, false, ceilingcolormap);
PF_Occlude, ceilinglightlevel, &levelflats[gr_frontsector->ceilingpic], NULL, 255, false, ceilingcolormap);
}
}
else
@ -3671,7 +3667,7 @@ static void HWR_Subsector(size_t num)
else
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
HWR_AddTransparentFloor(0, 0,
HWR_AddTransparentFloor(NULL,
&extrasubsectors[num],
false,
*rover->bottomheight,
@ -3683,14 +3679,13 @@ static void HWR_Subsector(size_t num)
{
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
#ifndef SORTING
HWR_Add3DWater(levelflats[*rover->bottompic].lumpnum,
HWR_Add3DWater(&levelflats[*rover->bottompic],
&extrasubsectors[num],
*rover->bottomheight,
*gr_frontsector->lightlist[light].lightlevel,
rover->alpha-1, rover->master->frontsector);
#else
HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum,
levelflats[*rover->bottompic].texturenum,
HWR_AddTransparentFloor(&levelflats[*rover->bottompic],
&extrasubsectors[num],
false,
*rover->bottomheight,
@ -3701,10 +3696,9 @@ static void HWR_Subsector(size_t num)
}
else
{
HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
HWR_GetTextureFlat(levelflats[*rover->bottompic].texturenum);
HWR_GetLevelFlat(&levelflats[*rover->bottompic]);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, levelflats[*rover->bottompic].texturenum,
HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -3736,7 +3730,7 @@ static void HWR_Subsector(size_t num)
else
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, NORMALFOG);
HWR_AddTransparentFloor(0, 0,
HWR_AddTransparentFloor(NULL,
&extrasubsectors[num],
true,
*rover->topheight,
@ -3748,14 +3742,13 @@ static void HWR_Subsector(size_t num)
{
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
#ifndef SORTING
HWR_Add3DWater(levelflats[*rover->toppic].lumpnum,
HWR_Add3DWater(&levelflats[*rover->toppic],
&extrasubsectors[num],
*rover->topheight,
*gr_frontsector->lightlist[light].lightlevel,
rover->alpha-1, rover->master->frontsector);
#else
HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum,
levelflats[*rover->bottompic].texturenum,
HWR_AddTransparentFloor(&levelflats[*rover->toppic],
&extrasubsectors[num],
true,
*rover->topheight,
@ -3767,10 +3760,9 @@ static void HWR_Subsector(size_t num)
}
else
{
HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
HWR_GetTextureFlat(levelflats[*rover->toppic].texturenum);
HWR_GetLevelFlat(&levelflats[*rover->toppic]);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, levelflats[*rover->toppic].texturenum,
HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
}
}
@ -5098,8 +5090,7 @@ typedef struct
boolean isceiling;
fixed_t fixedheight;
INT32 lightlevel;
lumpnum_t lumpnum;
INT32 texturenum;
levelflat_t *levelflat;
INT32 alpha;
sector_t *FOFSector;
FBITFIELD blend;
@ -5117,8 +5108,7 @@ typedef struct
boolean isceiling;
fixed_t fixedheight;
INT32 lightlevel;
lumpnum_t lumpnum;
INT32 texturenum;
levelflat_t *levelflat;
INT32 alpha;
sector_t *FOFSector;
FBITFIELD blend;
@ -5149,7 +5139,7 @@ static INT32 drawcount = 0;
#define MAX_TRANSPARENTFLOOR 512
// This will likely turn into a copy of HWR_Add3DWater and replace it.
void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector_t *xsub, boolean isceiling,
void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap)
{
static size_t allocedplanes = 0;
@ -5167,8 +5157,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector
planeinfo[numplanes].isceiling = isceiling;
planeinfo[numplanes].fixedheight = fixedheight;
planeinfo[numplanes].lightlevel = lightlevel;
planeinfo[numplanes].lumpnum = lumpnum;
planeinfo[numplanes].texturenum = texturenum;
planeinfo[numplanes].levelflat = levelflat;
planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha;
planeinfo[numplanes].FOFSector = FOFSector;
@ -5182,7 +5171,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, INT32 texturenum, extrasubsector
// Adding this for now until I can create extrasubsector info for polyobjects
// When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane
void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, polyobj_t *polysector, boolean isceiling,
void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap)
{
static size_t allocedpolyplanes = 0;
@ -5200,8 +5189,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, INT32 texturenum, poly
polyplaneinfo[numpolyplanes].isceiling = isceiling;
polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
polyplaneinfo[numpolyplanes].lumpnum = lumpnum;
polyplaneinfo[numpolyplanes].texturenum = texturenum;
polyplaneinfo[numpolyplanes].levelflat = levelflat;
polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha;
polyplaneinfo[numpolyplanes].FOFSector = FOFSector;
@ -5363,12 +5351,9 @@ static void HWR_CreateDrawNodes(void)
gr_frontsector = NULL;
if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture))
{
HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum);
HWR_GetTextureFlat(sortnode[sortindex[i]].plane->texturenum);
}
HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat);
HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel,
sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->texturenum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
}
else if (sortnode[sortindex[i]].polyplane)
{
@ -5376,12 +5361,9 @@ static void HWR_CreateDrawNodes(void)
gr_frontsector = NULL;
if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture))
{
HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum);
HWR_GetTextureFlat(sortnode[sortindex[i]].polyplane->texturenum);
}
HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat);
HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel,
sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->texturenum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
sortnode[sortindex[i]].polyplane->levelflat, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
}
else if (sortnode[sortindex[i]].wall)
{
@ -5426,17 +5408,17 @@ static void HWR_DrawSprites(void)
#endif
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
{
if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f)
if (!cv_grmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f)
HWR_DrawSprite(spr);
else
HWR_DrawMD2(spr);
HWR_DrawModel(spr);
}
else
{
if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
if (!cv_grmodels.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
HWR_DrawSprite(spr);
else
HWR_DrawMD2(spr);
HWR_DrawModel(spr);
}
}
}
@ -5454,7 +5436,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 +5453,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 +5464,16 @@ static void HWR_AddSprites(sector_t *sec)
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
if (approx_dist > limit_dist)
if (thing->sprite == SPR_HOOP)
{
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
continue;
}
else
{
if (limit_dist && approx_dist > limit_dist)
continue;
}
HWR_ProjectSprite(thing);
}
@ -5554,7 +5546,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
// thing is behind view plane?
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmodels.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
return;
// The above can stay as it works for cutting sprites that are too close
@ -5711,6 +5703,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 +5723,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);
@ -5738,6 +5737,15 @@ static void HWR_ProjectSprite(mobj_t *thing)
// New colormap stuff for skins Tails 06-07-2002
if (thing->colorized)
vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE);
else if (thing->player && thing->player->dashmode >= DASHMODE_THRESHOLD
&& (thing->player->charflags & SF_DASHMODE)
&& ((leveltime/2) & 1))
{
if (thing->player->charflags & SF_MACHINE)
vis->colormap = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE);
else
vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE);
}
else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player!
{
size_t skinnum = (skin_t*)thing->skin-skins;
@ -5869,7 +5877,42 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
// ==========================================================================
//
// ==========================================================================
static void HWR_DrawSkyBackground(void)
static void HWR_DrawSkyBackground(player_t *player)
{
if (cv_grskydome.value)
{
FTransform transform;
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
postimg_t *type;
if (splitscreen && player == &players[secondarydisplayplayer])
type = &postimgtype2;
else
type = &postimgtype;
memset(&transform, 0x00, sizeof(FTransform));
//04/01/2000: Hurdler: added for T&L
// It should replace all other gr_viewxxx when finished
transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
if (*type == postimg_flip)
transform.flip = true;
else
transform.flip = false;
transform.scalex = 1;
transform.scaley = (float)vid.width/vid.height;
transform.scalez = 1;
transform.fovxangle = fpov; // Tails
transform.fovyangle = fpov; // Tails
transform.splitscreen = splitscreen;
HWR_GetTexture(texturetranslation[skytexture]);
HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform);
}
else
{
FOutVector v[4];
angle_t angle;
@ -5950,6 +5993,7 @@ static void HWR_DrawSkyBackground(void)
HWD.pfnDrawPolygon(NULL, v, 4, 0);
}
}
// -----------------+
@ -6100,7 +6144,7 @@ if (0)
}
if (drawsky)
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;
@ -6254,6 +6298,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
// note: sets viewangle, viewx, viewy, viewz
R_SetupFrame(player);
framecount++; // timedemo
// copy view cam position for local use
dup_viewx = viewx;
@ -6317,7 +6362,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;
@ -6555,13 +6600,13 @@ void HWR_Startup(void)
// do this once
if (!startupdone)
{
CONS_Printf("HWR_Startup()\n");
CONS_Printf("HWR_Startup()...\n");
HWR_InitPolyPool();
// add console cmds & vars
HWR_AddEngineCommands();
HWR_InitTextureCache();
HWR_InitMD2();
HWR_InitModels();
#ifdef ALAM_LIGHTING
HWR_InitLight();
@ -6613,10 +6658,11 @@ void transform(float *cx, float *cy, float *cz)
//Hurdler: 3D Water stuff
#ifndef SORTING
#define MAX_3DWATER 512
#ifndef SORTING
static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub,
static void HWR_Add3DWater(levelflat_t *levelflat, extrasubsector_t *xsub,
fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector)
{
static size_t allocedplanes = 0;
@ -6632,17 +6678,15 @@ static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub,
}
planeinfo[numfloors].fixedheight = fixedheight;
planeinfo[numfloors].lightlevel = lightlevel;
planeinfo[numfloors].lumpnum = lumpnum;
planeinfo[numfloors].levelflat = levelflat;
planeinfo[numfloors].xsub = xsub;
planeinfo[numfloors].alpha = alpha;
planeinfo[numfloors].FOFSector = FOFSector;
numfloors++;
}
#endif
#define DIST_PLANE(i) ABS(planeinfo[(i)].fixedheight-dup_viewz)
#if 0
static void HWR_QuickSortPlane(INT32 start, INT32 finish)
{
INT32 left = start;
@ -6672,9 +6716,7 @@ static void HWR_QuickSortPlane(INT32 start, INT32 finish)
if (start < right) HWR_QuickSortPlane(start, right);
if (left < finish) HWR_QuickSortPlane(left, finish);
}
#endif
#ifndef SORTING
static void HWR_Render3DWater(void)
{
size_t i;
@ -6705,8 +6747,8 @@ static void HWR_Render3DWater(void)
gr_frontsector = NULL; //Hurdler: gr_fronsector is no longer valid
for (i = 0; i < numfloors; i++)
{
HWR_GetFlat(planeinfo[i].lumpnum);
HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].lumpnum,
HWR_GetLevelFlat(planeinfo[i].levelflat);
HWR_RenderPlane(NULL, planeinfo[i].xsub, planeinfo[i].isceiling, planeinfo[i].fixedheight, PF_Translucent, planeinfo[i].lightlevel, planeinfo[i].levelflat,
planeinfo[i].FOFSector, planeinfo[i].alpha, planeinfo[i].fogplane, planeinfo[i].planecolormap);
}
numfloors = 0;
@ -6739,6 +6781,7 @@ static void HWR_AddTransparentWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, I
wallinfo[numwalls].wallcolormap = wallcolormap;
numwalls++;
}
#ifndef SORTING
static void HWR_RenderTransparentWalls(void)
{
@ -6771,6 +6814,7 @@ static void HWR_RenderTransparentWalls(void)
numwalls = 0;
}
#endif
static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap)
{
FOutVector trVerts[4];
@ -6829,11 +6873,6 @@ static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIE
#endif
}
void HWR_SetPaletteColor(INT32 palcolor)
{
HWD.pfnSetSpecialState(HWD_SET_PALETTECOLOR, palcolor);
}
INT32 HWR_GetTextureUsed(void)
{
return HWD.pfnGetTextureUsed();
@ -6880,7 +6919,6 @@ void HWR_DoPostProcessor(player_t *player)
if (splitscreen) // Not supported in splitscreen - someone want to add support?
return;
#ifdef SHUFFLE
// Drunken vision! WooOOooo~
if (*type == postimg_water || *type == postimg_heat)
{
@ -6923,7 +6961,6 @@ void HWR_DoPostProcessor(player_t *player)
HWD.pfnMakeScreenTexture();
}
// Flipping of the screen isn't done here anymore
#endif // SHUFFLE
}
void HWR_StartScreenWipe(void)
@ -6970,7 +7007,7 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
HWR_GetFadeMask(lumpnum);
HWD.pfnDoScreenWipe(HWRWipeCounter); // Still send in wipecounter since old stuff might not support multitexturing
HWD.pfnDoScreenWipe();
HWRWipeCounter += 0.05f; // increase opacity of end screen

View File

@ -60,7 +60,6 @@ void HWR_AddCommands(void);
void HWR_CorrectSWTricks(void);
void transform(float *cx, float *cy, float *cz);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
void HWR_SetPaletteColor(INT32 palcolor);
INT32 HWR_GetTextureUsed(void);
void HWR_DoPostProcessor(player_t *player);
void HWR_StartScreenWipe(void);
@ -83,7 +82,8 @@ extern consvar_t cv_grcoronas;
extern consvar_t cv_grcoronasize;
#endif
extern consvar_t cv_grfov;
extern consvar_t cv_grmd2;
extern consvar_t cv_grmodels;
extern consvar_t cv_grmodelinterpolation;
extern consvar_t cv_grfog;
extern consvar_t cv_grfogcolor;
extern consvar_t cv_grfogdensity;
@ -94,10 +94,10 @@ extern consvar_t cv_grgammablue;
extern consvar_t cv_grfiltermode;
extern consvar_t cv_granisotropicmode;
extern consvar_t cv_grcorrecttricks;
extern consvar_t cv_voodoocompatibility;
extern consvar_t cv_grfovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;
extern consvar_t cv_grskydome;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;

File diff suppressed because it is too large Load Diff

View File

@ -22,104 +22,7 @@
#define _HW_MD2_H_
#include "hw_glob.h"
#include "../info.h"
// magic number "IDP2" or 844121161
#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
// model version
#define MD2_VERSION 8
// magic number "IDP2" or 844121161
#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
// model version
#define MD2_VERSION 8
#define MD2_MAX_TRIANGLES 8192
#define MD2_MAX_VERTICES 4096
#define MD2_MAX_TEXCOORDS 4096
#define MD2_MAX_FRAMES 512
#define MD2_MAX_SKINS 32
#define MD2_MAX_FRAMESIZE (MD2_MAX_VERTICES * 4 + 128)
#if defined(_MSC_VER)
#pragma pack(1)
#endif
typedef struct
{
UINT32 magic;
UINT32 version;
UINT32 skinWidth;
UINT32 skinHeight;
UINT32 frameSize;
UINT32 numSkins;
UINT32 numVertices;
UINT32 numTexCoords;
UINT32 numTriangles;
UINT32 numGlCommands;
UINT32 numFrames;
UINT32 offsetSkins;
UINT32 offsetTexCoords;
UINT32 offsetTriangles;
UINT32 offsetFrames;
UINT32 offsetGlCommands;
UINT32 offsetEnd;
} ATTRPACK md2_header_t; //NOTE: each of md2_header's members are 4 unsigned bytes
typedef struct
{
UINT8 vertex[3];
UINT8 lightNormalIndex;
} ATTRPACK md2_alias_triangleVertex_t;
typedef struct
{
float vertex[3];
float normal[3];
} ATTRPACK md2_triangleVertex_t;
typedef struct
{
INT16 vertexIndices[3];
INT16 textureIndices[3];
} ATTRPACK md2_triangle_t;
typedef struct
{
INT16 s, t;
} ATTRPACK md2_textureCoordinate_t;
typedef struct
{
float scale[3];
float translate[3];
char name[16];
md2_alias_triangleVertex_t alias_vertices[1];
} ATTRPACK md2_alias_frame_t;
typedef struct
{
char name[16];
md2_triangleVertex_t *vertices;
} ATTRPACK md2_frame_t;
typedef char md2_skin_t[64];
typedef struct
{
float s, t;
INT32 vertexIndex;
} ATTRPACK md2_glCommandVertex_t;
typedef struct
{
md2_header_t header;
md2_skin_t *skins;
md2_textureCoordinate_t *texCoords;
md2_triangle_t *triangles;
md2_frame_t *frames;
size_t *spr2frames; // size_t spr2frames[2*NUMPLAYERSPRITES][2];
INT32 *glCommandBuffer;
} ATTRPACK md2_model_t;
#include "hw_model.h"
#if defined(_MSC_VER)
#pragma pack()
@ -130,7 +33,7 @@ typedef struct
char filename[32];
float scale;
float offset;
md2_model_t *model;
model_t *model;
void *grpatch;
void *blendgrpatch;
boolean notfound;
@ -141,9 +44,9 @@ typedef struct
extern md2_t md2_models[NUMSPRITES];
extern md2_t md2_playermodels[MAXSKINS];
void HWR_InitMD2(void);
void HWR_DrawMD2(gr_vissprite_t *spr);
void HWR_AddPlayerMD2(INT32 skin);
void HWR_AddSpriteMD2(size_t spritenum);
void HWR_InitModels(void);
void HWR_DrawModel(gr_vissprite_t *spr);
void HWR_AddPlayerModel(INT32 skin);
void HWR_AddSpriteModel(size_t spritenum);
#endif // _HW_MD2_H_

576
src/hardware/hw_md2load.c Normal file
View File

@ -0,0 +1,576 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../doomdef.h"
#include "hw_md2load.h"
#include "hw_model.h"
#include "../z_zone.h"
#define NUMVERTEXNORMALS 162
// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and
// you'll have your normals.
float avertexnormals[NUMVERTEXNORMALS][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},
};
typedef struct
{
int ident; // A "magic number" that's used to identify the .md2 file
int version; // The version of the file, always 8
int skinwidth; // Width of the skin(s) in pixels
int skinheight; // Height of the skin(s) in pixels
int framesize; // Size of each frame in bytes
int numSkins; // Number of skins with the model
int numXYZ; // Number of vertices in each frame
int numST; // Number of texture coordinates in each frame.
int numTris; // Number of triangles in each frame
int numGLcmds; // Number of dwords (4 bytes) in the gl command list.
int numFrames; // Number of frames
int offsetSkins; // Offset, in bytes from the start of the file, to the list of skin names.
int offsetST; // Offset, in bytes from the start of the file, to the list of texture coordinates
int offsetTris; // Offset, in bytes from the start of the file, to the list of triangles
int offsetFrames; // Offset, in bytes from the start of the file, to the list of frames
int offsetGLcmds; // Offset, in bytes from the start of the file, to the list of gl commands
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
} md2header_t;
typedef struct
{
unsigned short meshIndex[3]; // indices into the array of vertices in each frames
unsigned short stIndex[3]; // indices into the array of texture coordinates
} md2triangle_t;
typedef struct
{
short s;
short t;
} md2texcoord_t;
typedef struct
{
unsigned char v[3]; // Scaled vertices. You'll need to multiply them with scale[x] to make them normal.
unsigned char lightNormalIndex; // Index to the array of normals
} md2vertex_t;
typedef struct
{
float scale[3]; // Used by the v member in the md2framePoint structure
float translate[3]; // Used by the v member in the md2framePoint structure
char name[16]; // Name of the frame
} md2frame_t;
// Load the model
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
FILE *f;
model_t *retModel = NULL;
md2header_t *header;
size_t fileLen;
int i, j;
size_t namelen;
char *texturefilename;
const char *texPos;
char *buffer;
const float WUNITS = 1.0f;
float dataScale = WUNITS;
md2triangle_t *tris;
md2texcoord_t *texcoords;
md2frame_t *frames;
char *fname = NULL;
int foffset = 0;
int t;
// MD2 currently does not work with tinyframes, so force useFloat = true
//
// <SSNTails>
// the UV coordinates in MD2 are not compatible with glDrawElements like MD3 is. So they need to be loaded as full float.
//
// MD2 is intended to be draw in triangle strips and fans
// not very compatible with a modern GL implementation, either
// so the idea would be to full float expand it, and put it in a vertex buffer object
// I'm sure there's a way to convert the UVs to 'tinyframes', but maybe that's a job for someone else.
// You'd have to decompress the model, then recompress, reindexing the triangles and weeding out duplicate coordinates
// I already have the decompression work done
useFloat = true;
f = fopen(fileName, "rb");
if (!f)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
//size_t fileLen;
//int i, j;
//size_t namelen;
//char *texturefilename;
texPos = strchr(fileName, '/');
if (texPos)
{
texPos++;
namelen = strlen(texPos) + 1;
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
strcpy(texturefilename, texPos);
}
else
{
namelen = strlen(fileName) + 1;
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
strcpy(texturefilename, fileName);
}
texturefilename[namelen - 2] = 'z';
texturefilename[namelen - 3] = 'u';
texturefilename[namelen - 4] = 'b';
// find length of file
fseek(f, 0, SEEK_END);
fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
// read in file
buffer = malloc(fileLen);
if (fread(buffer, fileLen, 1, f)) { } // squash ignored fread error
fclose(f);
// get pointer to file header
header = (md2header_t*)buffer;
retModel->numMeshes = 1; // MD2 only has one mesh
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * retModel->numMeshes, ztag, 0);
retModel->meshes[0].numFrames = header->numFrames;
// const float WUNITS = 1.0f;
// float dataScale = WUNITS;
// Tris and ST are simple structures that can be straight-copied
tris = (md2triangle_t*)&buffer[header->offsetTris];
texcoords = (md2texcoord_t*)&buffer[header->offsetST];
frames = (md2frame_t*)&buffer[header->offsetFrames];
retModel->framenames = (char*)Z_Calloc(header->numFrames*16, ztag, 0);
fname = retModel->framenames;
for (i = 0; i < header->numFrames; i++)
{
md2frame_t *fr = (md2frame_t*)&buffer[header->offsetFrames + foffset];
memcpy(fname, fr->name, 16);
foffset += sizeof(md2frame_t) + (sizeof(md2vertex_t) * header->numXYZ);
fname += 16;
}
// Read in textures
retModel->numMaterials = header->numSkins;
if (retModel->numMaterials <= 0) // Always at least one skin, duh
retModel->numMaterials = 1;
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
// int t;
for (t = 0; t < retModel->numMaterials; t++)
{
retModel->materials[t].ambient[0] = 0.8f;
retModel->materials[t].ambient[1] = 0.8f;
retModel->materials[t].ambient[2] = 0.8f;
retModel->materials[t].ambient[3] = 1.0f;
retModel->materials[t].diffuse[0] = 0.8f;
retModel->materials[t].diffuse[1] = 0.8f;
retModel->materials[t].diffuse[2] = 0.8f;
retModel->materials[t].diffuse[3] = 1.0f;
retModel->materials[t].emissive[0] = 0.0f;
retModel->materials[t].emissive[1] = 0.0f;
retModel->materials[t].emissive[2] = 0.0f;
retModel->materials[t].emissive[3] = 1.0f;
retModel->materials[t].specular[0] = 0.0f;
retModel->materials[t].specular[1] = 0.0f;
retModel->materials[t].specular[2] = 0.0f;
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 0.0f;
retModel->materials[t].spheremap = false;
/* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, texturefilename);
size_t len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[t].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[0].numTriangles = header->numTris;
if (!useFloat) // Decompress to MD3 'tinyframe' space
{
char *ptr;
md2triangle_t *trisPtr;
unsigned short *indexptr;
float *uvptr;
dataScale = 0.015624f; // 1 / 64.0f
retModel->meshes[0].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*header->numFrames, ztag, 0);
retModel->meshes[0].numVertices = header->numXYZ;
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
ptr = (char*)frames;
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
{
short *vertptr;
char *normptr;
// char *tanptr;
md2vertex_t *vertex;
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].tinyframes[i].vertices = (short*)Z_Malloc(sizeof(short) * 3 * header->numXYZ, ztag, 0);
retModel->meshes[0].tinyframes[i].normals = (char*)Z_Malloc(sizeof(char) * 3 * header->numXYZ, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].tinyframes[i].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*header->numVerts, ztag);
retModel->meshes[0].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * header->numTris, ztag, 0);
vertptr = retModel->meshes[0].tinyframes[i].vertices;
normptr = retModel->meshes[0].tinyframes[i].normals;
// tanptr = retModel->meshes[0].tinyframes[i].tangents;
retModel->meshes[0].tinyframes[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
vertex = (md2vertex_t*)framePtr;
framePtr--;
for (j = 0; j < header->numXYZ; j++, vertex++)
{
*vertptr = (short)(((vertex->v[0] * framePtr->scale[0]) + framePtr->translate[0]) / dataScale);
vertptr++;
*vertptr = (short)(((vertex->v[2] * framePtr->scale[2]) + framePtr->translate[2]) / dataScale);
vertptr++;
*vertptr = -1.0f * (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale);
vertptr++;
// Normal
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][0] * 127);
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][2] * 127);
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][1] * 127);
}
}
// This doesn't need to be done every frame!
trisPtr = tris;
indexptr = retModel->meshes[0].indices;
uvptr = (float*)retModel->meshes[0].uvs;
for (j = 0; j < header->numTris; j++, trisPtr++)
{
*indexptr = trisPtr->meshIndex[0];
indexptr++;
*indexptr = trisPtr->meshIndex[1];
indexptr++;
*indexptr = trisPtr->meshIndex[2];
indexptr++;
uvptr[trisPtr->meshIndex[0] * 2] = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[0] * 2 + 1] = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
uvptr[trisPtr->meshIndex[1] * 2] = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[1] * 2 + 1] = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
uvptr[trisPtr->meshIndex[2] * 2] = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
uvptr[trisPtr->meshIndex[2] * 2 + 1] = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
}
}
else // Full float loading method
{
md2triangle_t *trisPtr;
float *uvptr;
char *ptr;
retModel->meshes[0].numVertices = header->numTris * 3;
retModel->meshes[0].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*header->numFrames, ztag, 0);
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
trisPtr = tris;
uvptr = retModel->meshes[0].uvs;
for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++)
{
*uvptr++ = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
*uvptr++ = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
*uvptr++ = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
*uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
}
ptr = (char*)frames;
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
{
float *vertptr, *normptr;
md2vertex_t *vertex;
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].frames[i].normals = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
retModel->meshes[0].frames[i].vertices = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].frames[i].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*header->numTris*3, ztag);
//float *vertptr, *normptr;
normptr = (float*)retModel->meshes[0].frames[i].normals;
vertptr = (float*)retModel->meshes[0].frames[i].vertices;
trisPtr = tris;
retModel->meshes[0].frames[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
vertex = (md2vertex_t*)framePtr;
framePtr--;
for (j = 0; j < header->numTris; j++, trisPtr++)
{
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[0]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[1]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
vertptr++;
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
vertptr++;
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[2]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
vertptr++;
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][1];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][1];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][0];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][2];
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][1];
}
}
}
free(buffer);
return retModel;
}

19
src/hardware/hw_md2load.h Normal file
View File

@ -0,0 +1,19 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MD2LOAD_H_
#define _HW_MD2LOAD_H_
#include "hw_model.h"
#include "../doomtype.h"
// Load the Model
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat);
#endif

522
src/hardware/hw_md3load.c Normal file
View File

@ -0,0 +1,522 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../doomdef.h"
#include "hw_md3load.h"
#include "hw_model.h"
#include "../z_zone.h"
typedef struct
{
int ident; // A "magic number" that's used to identify the .md3 file
int version; // The version of the file, always 15
char name[64];
int flags;
int numFrames; // Number of frames
int numTags;
int numSurfaces;
int numSkins; // Number of skins with the model
int offsetFrames;
int offsetTags;
int offsetSurfaces;
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
} md3modelHeader;
typedef struct
{
float minBounds[3]; // First corner of the bounding box
float maxBounds[3]; // Second corner of the bounding box
float localOrigin[3]; // Local origin, usually (0, 0, 0)
float radius; // Radius of bounding sphere
char name[16]; // Name of frame
} md3Frame;
typedef struct
{
char name[64]; // Name of tag
float origin[3]; // Coordinates of tag
float axis[9]; // Orientation of tag object
} md3Tag;
typedef struct
{
int ident;
char name[64]; // Name of this surface
int flags;
int numFrames; // # of keyframes
int numShaders; // # of shaders
int numVerts; // # of vertices
int numTriangles; // # of triangles
int offsetTriangles; // Relative offset from start of this struct to where the list of Triangles start
int offsetShaders; // Relative offset from start of this struct to where the list of Shaders start
int offsetST; // Relative offset from start of this struct to where the list of tex coords start
int offsetXYZNormal; // Relative offset from start of this struct to where the list of vertices start
int offsetEnd; // Relative offset from start of this struct to where this surface ends
} md3Surface;
typedef struct
{
char name[64]; // Name of this shader
int shaderIndex; // Shader index number
} md3Shader;
typedef struct
{
int index[3]; // List of offset values into the list of Vertex objects that constitute the corners of the Triangle object.
} md3Triangle;
typedef struct
{
float st[2];
} md3TexCoord;
typedef struct
{
short x, y, z, n;
} md3Vertex;
static float latlnglookup[256][256][3];
static void GetNormalFromLatLong(short latlng, float *out)
{
float *lookup = latlnglookup[(unsigned char)(latlng >> 8)][(unsigned char)(latlng & 255)];
out[0] = *lookup++;
out[1] = *lookup++;
out[2] = *lookup++;
}
#if 0
static void NormalToLatLng(float *n, short *out)
{
// Special cases
if (0.0f == n[0] && 0.0f == n[1])
{
if (n[2] > 0.0f)
*out = 0;
else
*out = 128;
}
else
{
char x, y;
x = (char)(57.2957795f * (atan2(n[1], n[0])) * (255.0f / 360.0f));
y = (char)(57.2957795f * (acos(n[2])) * (255.0f / 360.0f));
*out = (x << 8) + y;
}
}
#endif
static inline void LatLngToNormal(short n, float *out)
{
const float PI = (3.1415926535897932384626433832795f);
float lat = (float)(n >> 8);
float lng = (float)(n & 255);
lat *= PI / 128.0f;
lng *= PI / 128.0f;
out[0] = cosf(lat) * sinf(lng);
out[1] = sinf(lat) * sinf(lng);
out[2] = cosf(lng);
}
static void LatLngInit(void)
{
int i, j;
for (i = 0; i < 256; i++)
{
for (j = 0; j < 256; j++)
LatLngToNormal((short)((i << 8) + j), latlnglookup[i][j]);
}
}
static boolean latlnginit = false;
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
const float WUNITS = 1.0f;
model_t *retModel = NULL;
md3Frame *frames = NULL;
char *fname = NULL;
md3modelHeader *mdh;
long fileLen;
long fileReadLen;
char *buffer;
int surfEnd;
int i, t;
int matCount;
FILE *f;
if (!latlnginit)
{
LatLngInit();
latlnginit = true;
}
f = fopen(fileName, "rb");
if (!f)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
// find length of file
fseek(f, 0, SEEK_END);
fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
// read in file
buffer = malloc(fileLen);
fileReadLen = fread(buffer, fileLen, 1, f);
fclose(f);
(void)fileReadLen; // intentionally ignore return value, per buildbot
// get pointer to file header
mdh = (md3modelHeader*)buffer;
retModel->numMeshes = mdh->numSurfaces;
retModel->numMaterials = 0;
surfEnd = 0;
for (i = 0; i < mdh->numSurfaces; i++)
{
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces];
surfEnd += mdS->offsetEnd;
retModel->numMaterials += mdS->numShaders;
}
// Initialize materials
if (retModel->numMaterials <= 0) // Always at least one skin, duh
retModel->numMaterials = 1;
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
for (t = 0; t < retModel->numMaterials; t++)
{
retModel->materials[t].ambient[0] = 0.3686f;
retModel->materials[t].ambient[1] = 0.3684f;
retModel->materials[t].ambient[2] = 0.3684f;
retModel->materials[t].ambient[3] = 1.0f;
retModel->materials[t].diffuse[0] = 0.8863f;
retModel->materials[t].diffuse[1] = 0.8850f;
retModel->materials[t].diffuse[2] = 0.8850f;
retModel->materials[t].diffuse[3] = 1.0f;
retModel->materials[t].emissive[0] = 0.0f;
retModel->materials[t].emissive[1] = 0.0f;
retModel->materials[t].emissive[2] = 0.0f;
retModel->materials[t].emissive[3] = 1.0f;
retModel->materials[t].specular[0] = 0.4902f;
retModel->materials[t].specular[1] = 0.4887f;
retModel->materials[t].specular[2] = 0.4887f;
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 25.0f;
retModel->materials[t].spheremap = false;
}
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0);
frames = (md3Frame*)&buffer[mdh->offsetFrames];
retModel->framenames = (char*)Z_Calloc(mdh->numFrames*16, ztag, 0);
fname = retModel->framenames;
for (i = 0; i < mdh->numFrames; i++)
{
memcpy(fname, frames->name, 16);
fname += 16;
frames++;
}
matCount = 0;
for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++)
{
int j;
md3Shader *mdShader;
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces + surfEnd];
surfEnd += mdS->offsetEnd;
mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders);
for (j = 0; j < mdS->numShaders; j++, matCount++)
{
size_t len = strlen(mdShader[j].name);
mdShader[j].name[len-1] = 'z';
mdShader[j].name[len-2] = 'u';
mdShader[j].name[len-3] = 'b';
// Load material
/* retModel->materials[matCount].texture = Texture::ReadTexture(mdShader[j].name, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, mdShader[j].name);
len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[matCount].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[i].numFrames = mdS->numFrames;
retModel->meshes[i].numTriangles = mdS->numTriangles;
if (!useFloat) // 'tinyframe' mode with indices
{
float tempNormal[3];
float *uvptr;
md3TexCoord *mdST;
unsigned short *indexptr;
md3Triangle *mdT;
retModel->meshes[i].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*mdS->numFrames, ztag, 0);
retModel->meshes[i].numVertices = mdS->numVerts;
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numVerts, ztag, 0);
for (j = 0; j < mdS->numFrames; j++)
{
short *vertptr;
char *normptr;
// char *tanptr;
int k;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].tinyframes[j].vertices = (short*)Z_Malloc(sizeof(short)*3*mdS->numVerts, ztag, 0);
retModel->meshes[i].tinyframes[j].normals = (char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag, 0);
// if (retModel->materials[0].lightmap)
// retModel->meshes[i].tinyframes[j].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag);
retModel->meshes[i].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * mdS->numTriangles, ztag, 0);
vertptr = retModel->meshes[i].tinyframes[j].vertices;
normptr = retModel->meshes[i].tinyframes[j].normals;
// tanptr = retModel->meshes[i].tinyframes[j].tangents;
retModel->meshes[i].tinyframes[j].material = &retModel->materials[i];
for (k = 0; k < mdS->numVerts; k++)
{
// Vertex
*vertptr = mdV[k].x;
vertptr++;
*vertptr = mdV[k].z;
vertptr++;
*vertptr = 1.0f - mdV[k].y;
vertptr++;
// Normal
GetNormalFromLatLong(mdV[k].n, tempNormal);
*normptr = (char)(tempNormal[0] * 127);
normptr++;
*normptr = (char)(tempNormal[2] * 127);
normptr++;
*normptr = (char)(tempNormal[1] * 127);
normptr++;
}
}
uvptr = (float*)retModel->meshes[i].uvs;
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
for (j = 0; j < mdS->numVerts; j++)
{
*uvptr = mdST[j].st[0];
uvptr++;
*uvptr = mdST[j].st[1];
uvptr++;
}
indexptr = retModel->meshes[i].indices;
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (j = 0; j < mdS->numTriangles; j++, mdT++)
{
// Indices
*indexptr = (unsigned short)mdT->index[0];
indexptr++;
*indexptr = (unsigned short)mdT->index[1];
indexptr++;
*indexptr = (unsigned short)mdT->index[2];
indexptr++;
}
}
else // Traditional full-float loading method
{
float dataScale = 0.015624f * WUNITS;
float tempNormal[3];
md3TexCoord *mdST;
md3Triangle *mdT;
float *uvptr;
int k;
retModel->meshes[i].numVertices = mdS->numTriangles * 3;//mdS->numVerts;
retModel->meshes[i].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*mdS->numFrames, ztag, 0);
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numTriangles*3, ztag, 0);
for (j = 0; j < mdS->numFrames; j++)
{
float *vertptr;
float *normptr;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].frames[j].vertices = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
retModel->meshes[i].frames[j].normals = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
// if (retModel->materials[i].lightmap)
// retModel->meshes[i].frames[j].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag);
vertptr = retModel->meshes[i].frames[j].vertices;
normptr = retModel->meshes[i].frames[j].normals;
retModel->meshes[i].frames[j].material = &retModel->materials[i];
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (k = 0; k < mdS->numTriangles; k++)
{
// Vertex 1
*vertptr = mdV[mdT->index[0]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[0]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[0]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[0]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
// Vertex 2
*vertptr = mdV[mdT->index[1]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[1]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[1]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[1]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
// Vertex 3
*vertptr = mdV[mdT->index[2]].x * dataScale;
vertptr++;
*vertptr = mdV[mdT->index[2]].z * dataScale;
vertptr++;
*vertptr = 1.0f - mdV[mdT->index[2]].y * dataScale;
vertptr++;
GetNormalFromLatLong(mdV[mdT->index[2]].n, tempNormal);
*normptr = tempNormal[0];
normptr++;
*normptr = tempNormal[2];
normptr++;
*normptr = tempNormal[1];
normptr++;
mdT++; // Advance to next triangle
}
}
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
uvptr = (float*)retModel->meshes[i].uvs;
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
for (k = 0; k < mdS->numTriangles; k++)
{
*uvptr = mdST[mdT->index[0]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[0]].st[1];
uvptr++;
*uvptr = mdST[mdT->index[1]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[1]].st[1];
uvptr++;
*uvptr = mdST[mdT->index[2]].st[0];
uvptr++;
*uvptr = mdST[mdT->index[2]].st[1];
uvptr++;
mdT++; // Advance to next triangle
}
}
}
/*
// Tags?
retModel->numTags = mdh->numTags;
retModel->maxNumFrames = mdh->numFrames;
retModel->tags = (tag_t*)Z_Calloc(sizeof(tag_t) * retModel->numTags * mdh->numFrames, ztag);
md3Tag *mdTag = (md3Tag*)&buffer[mdh->offsetTags];
tag_t *curTag = retModel->tags;
for (i = 0; i < mdh->numFrames; i++)
{
int j;
for (j = 0; j < retModel->numTags; j++, mdTag++)
{
strcpys(curTag->name, mdTag->name, sizeof(curTag->name) / sizeof(char));
curTag->transform.m[0][0] = mdTag->axis[0];
curTag->transform.m[0][1] = mdTag->axis[1];
curTag->transform.m[0][2] = mdTag->axis[2];
curTag->transform.m[1][0] = mdTag->axis[3];
curTag->transform.m[1][1] = mdTag->axis[4];
curTag->transform.m[1][2] = mdTag->axis[5];
curTag->transform.m[2][0] = mdTag->axis[6];
curTag->transform.m[2][1] = mdTag->axis[7];
curTag->transform.m[2][2] = mdTag->axis[8];
curTag->transform.m[3][0] = mdTag->origin[0] * WUNITS;
curTag->transform.m[3][1] = mdTag->origin[1] * WUNITS;
curTag->transform.m[3][2] = mdTag->origin[2] * WUNITS;
curTag->transform.m[3][3] = 1.0f;
Matrix::Rotate(&curTag->transform, 90.0f, &Vector::Xaxis);
curTag++;
}
}*/
free(buffer);
return retModel;
}

19
src/hardware/hw_md3load.h Normal file
View File

@ -0,0 +1,19 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MD3LOAD_H_
#define _HW_MD3LOAD_H_
#include "hw_model.h"
#include "../doomtype.h"
// Load the Model
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat);
#endif

737
src/hardware/hw_model.c Normal file
View File

@ -0,0 +1,737 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include "../doomdef.h"
#include "../doomtype.h"
#include "../info.h"
#include "../z_zone.h"
#include "hw_model.h"
#include "hw_md2load.h"
#include "hw_md3load.h"
#include "hw_md2.h"
#include "u_list.h"
#include <string.h>
static float PI = (3.1415926535897932384626433832795f);
static float U_Deg2Rad(float deg)
{
return deg * ((float)PI / 180.0f);
}
vector_t vectorXaxis = { 1.0f, 0.0f, 0.0f };
vector_t vectorYaxis = { 0.0f, 1.0f, 0.0f };
vector_t vectorZaxis = { 0.0f, 0.0f, 1.0f };
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle)
{
float ux, uy, uz, vx, vy, vz, wx, wy, wz, sa, ca;
angle = U_Deg2Rad(angle);
// Rotate the point (x,y,z) around the vector (u,v,w)
ux = axisVec->x * rotVec->x;
uy = axisVec->x * rotVec->y;
uz = axisVec->x * rotVec->z;
vx = axisVec->y * rotVec->x;
vy = axisVec->y * rotVec->y;
vz = axisVec->y * rotVec->z;
wx = axisVec->z * rotVec->x;
wy = axisVec->z * rotVec->y;
wz = axisVec->z * rotVec->z;
sa = sinf(angle);
ca = cosf(angle);
rotVec->x = axisVec->x*(ux + vy + wz) + (rotVec->x*(axisVec->y*axisVec->y + axisVec->z*axisVec->z) - axisVec->x*(vy + wz))*ca + (-wy + vz)*sa;
rotVec->y = axisVec->y*(ux + vy + wz) + (rotVec->y*(axisVec->x*axisVec->x + axisVec->z*axisVec->z) - axisVec->y*(ux + wz))*ca + (wx - uz)*sa;
rotVec->z = axisVec->z*(ux + vy + wz) + (rotVec->z*(axisVec->x*axisVec->x + axisVec->y*axisVec->y) - axisVec->z*(ux + vy))*ca + (-vx + uy)*sa;
}
void UnloadModel(model_t *model)
{
// Wouldn't it be great if C just had destructors?
int i;
for (i = 0; i < model->numMeshes; i++)
{
mesh_t *mesh = &model->meshes[i];
if (mesh->frames)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
{
if (mesh->frames[j].normals)
Z_Free(mesh->frames[j].normals);
if (mesh->frames[j].tangents)
Z_Free(mesh->frames[j].tangents);
if (mesh->frames[j].vertices)
Z_Free(mesh->frames[j].vertices);
if (mesh->frames[j].colors)
Z_Free(mesh->frames[j].colors);
}
Z_Free(mesh->frames);
}
else if (mesh->tinyframes)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
{
if (mesh->tinyframes[j].normals)
Z_Free(mesh->tinyframes[j].normals);
if (mesh->tinyframes[j].tangents)
Z_Free(mesh->tinyframes[j].tangents);
if (mesh->tinyframes[j].vertices)
Z_Free(mesh->tinyframes[j].vertices);
}
if (mesh->indices)
Z_Free(mesh->indices);
Z_Free(mesh->tinyframes);
}
if (mesh->uvs)
Z_Free(mesh->uvs);
if (mesh->lightuvs)
Z_Free(mesh->lightuvs);
}
if (model->meshes)
Z_Free(model->meshes);
if (model->tags)
Z_Free(model->tags);
if (model->materials)
Z_Free(model->materials);
DeleteVBOs(model);
Z_Free(model);
}
tag_t *GetTagByName(model_t *model, char *name, int frame)
{
if (frame < model->maxNumFrames)
{
tag_t *iterator = &model->tags[frame * model->numTags];
int i;
for (i = 0; i < model->numTags; i++)
{
if (!stricmp(iterator[i].name, name))
return &iterator[i];
}
}
return NULL;
}
//
// LoadModel
//
// Load a model and
// convert it to the
// internal format.
//
model_t *LoadModel(const char *filename, int ztag)
{
model_t *model;
// What type of file?
const char *extension = NULL;
int i;
for (i = (int)strlen(filename)-1; i >= 0; i--)
{
if (filename[i] != '.')
continue;
extension = &filename[i];
break;
}
if (!extension)
{
CONS_Printf("Model %s is lacking a file extension, unable to determine type!\n", filename);
return NULL;
}
if (!strcmp(extension, ".md3"))
{
if (!(model = MD3_LoadModel(filename, ztag, false)))
return NULL;
}
else if (!strcmp(extension, ".md3s")) // MD3 that will be converted in memory to use full floats
{
if (!(model = MD3_LoadModel(filename, ztag, true)))
return NULL;
}
else if (!strcmp(extension, ".md2"))
{
if (!(model = MD2_LoadModel(filename, ztag, false)))
return NULL;
}
else if (!strcmp(extension, ".md2s"))
{
if (!(model = MD2_LoadModel(filename, ztag, true)))
return NULL;
}
else
{
CONS_Printf("Unknown model format: %s\n", extension);
return NULL;
}
model->mdlFilename = (char*)Z_Malloc(strlen(filename)+1, ztag, 0);
strcpy(model->mdlFilename, filename);
Optimize(model);
GeneratePolygonNormals(model, ztag);
LoadModelSprite2(model);
if (!model->spr2frames)
LoadModelInterpolationSettings(model);
// Default material properties
for (i = 0 ; i < model->numMaterials; i++)
{
material_t *material = &model->materials[i];
material->ambient[0] = 0.7686f;
material->ambient[1] = 0.7686f;
material->ambient[2] = 0.7686f;
material->ambient[3] = 1.0f;
material->diffuse[0] = 0.5863f;
material->diffuse[1] = 0.5863f;
material->diffuse[2] = 0.5863f;
material->diffuse[3] = 1.0f;
material->specular[0] = 0.4902f;
material->specular[1] = 0.4902f;
material->specular[2] = 0.4902f;
material->specular[3] = 1.0f;
material->shininess = 25.0f;
}
return model;
}
void HWR_ReloadModels(void)
{
size_t i;
INT32 s;
for (s = 0; s < MAXSKINS; s++)
{
if (md2_playermodels[s].model)
LoadModelSprite2(md2_playermodels[s].model);
}
for (i = 0; i < NUMSPRITES; i++)
{
if (md2_models[i].model)
LoadModelInterpolationSettings(md2_models[i].model);
}
}
void LoadModelInterpolationSettings(model_t *model)
{
INT32 i;
INT32 numframes = model->meshes[0].numFrames;
char *framename = model->framenames;
if (!framename)
return;
#define GET_OFFSET \
memcpy(&interpolation_flag, framename + offset, 2); \
model->interpolate[i] = (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2));
for (i = 0; i < numframes; i++)
{
int offset = (strlen(framename) - 4);
char interpolation_flag[3];
memset(&interpolation_flag, 0x00, 3);
// find the +i on the frame name
// ANIM+i00
// so the offset is (frame name length - 4)
GET_OFFSET;
// maybe the frame had three digits?
// ANIM+i000
// so the offset is (frame name length - 5)
if (!model->interpolate[i])
{
offset--;
GET_OFFSET;
}
framename += 16;
}
#undef GET_OFFSET
}
void LoadModelSprite2(model_t *model)
{
INT32 i;
modelspr2frames_t *spr2frames = NULL;
INT32 numframes = model->meshes[0].numFrames;
char *framename = model->framenames;
if (!framename)
return;
for (i = 0; i < numframes; i++)
{
char prefix[6];
char name[5];
char interpolation_flag[3];
char framechars[4];
UINT8 frame = 0;
UINT8 spr2idx;
boolean interpolate = false;
memset(&prefix, 0x00, 6);
memset(&name, 0x00, 5);
memset(&interpolation_flag, 0x00, 3);
memset(&framechars, 0x00, 4);
if (strlen(framename) >= 9)
{
boolean super;
char *modelframename = framename;
memcpy(&prefix, modelframename, 5);
modelframename += 5;
memcpy(&name, modelframename, 4);
modelframename += 4;
// Oh look
memcpy(&interpolation_flag, modelframename, 2);
if (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2))
{
interpolate = true;
modelframename += 2;
}
memcpy(&framechars, modelframename, 3);
if ((super = (!memcmp(prefix, "SUPER", 5))) || (!memcmp(prefix, "SPR2_", 5)))
{
spr2idx = 0;
while (spr2idx < free_spr2)
{
if (!memcmp(spr2names[spr2idx], name, 4))
{
if (!spr2frames)
spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL);
if (super)
spr2idx |= FF_SPR2SUPER;
if (framechars[0])
{
frame = atoi(framechars);
if (spr2frames[spr2idx].numframes < frame+1)
spr2frames[spr2idx].numframes = frame+1;
}
else
{
frame = spr2frames[spr2idx].numframes;
spr2frames[spr2idx].numframes++;
}
spr2frames[spr2idx].frames[frame] = i;
spr2frames[spr2idx].interpolate = interpolate;
break;
}
spr2idx++;
}
}
}
framename += 16;
}
if (model->spr2frames)
Z_Free(model->spr2frames);
model->spr2frames = spr2frames;
}
//
// GenerateVertexNormals
//
// Creates a new normal for a vertex using the average of all of the polygons it belongs to.
//
void GenerateVertexNormals(model_t *model)
{
int i;
for (i = 0; i < model->numMeshes; i++)
{
int j;
mesh_t *mesh = &model->meshes[i];
if (!mesh->frames)
continue;
for (j = 0; j < mesh->numFrames; j++)
{
mdlframe_t *frame = &mesh->frames[j];
int memTag = PU_STATIC;
float *newNormals = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag, 0);
int k;
float *vertPtr = frame->vertices;
float *oldNormals;
M_Memcpy(newNormals, frame->normals, sizeof(float)*3*mesh->numTriangles*3);
/* if (!systemSucks)
{
memTag = Z_GetTag(frame->tangents);
float *newTangents = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag);
M_Memcpy(newTangents, frame->tangents, sizeof(float)*3*mesh->numTriangles*3);
}*/
for (k = 0; k < mesh->numVertices; k++)
{
float x, y, z;
int vCount = 0;
vector_t normal;
int l;
float *testPtr = frame->vertices;
x = *vertPtr++;
y = *vertPtr++;
z = *vertPtr++;
normal.x = normal.y = normal.z = 0;
for (l = 0; l < mesh->numVertices; l++)
{
float testX, testY, testZ;
testX = *testPtr++;
testY = *testPtr++;
testZ = *testPtr++;
if (fabsf(x - testX) > FLT_EPSILON
|| fabsf(y - testY) > FLT_EPSILON
|| fabsf(z - testZ) > FLT_EPSILON)
continue;
// Found a vertex match! Add it...
normal.x += frame->normals[3 * l + 0];
normal.y += frame->normals[3 * l + 1];
normal.z += frame->normals[3 * l + 2];
vCount++;
}
if (vCount > 1)
{
// Vector::Normalize(&normal);
newNormals[3 * k + 0] = (float)normal.x;
newNormals[3 * k + 1] = (float)normal.y;
newNormals[3 * k + 2] = (float)normal.z;
/* if (!systemSucks)
{
Vector::vector_t tangent;
Vector::Tangent(&normal, &tangent);
newTangents[3 * k + 0] = tangent.x;
newTangents[3 * k + 1] = tangent.y;
newTangents[3 * k + 2] = tangent.z;
}*/
}
}
oldNormals = frame->normals;
frame->normals = newNormals;
Z_Free(oldNormals);
/* if (!systemSucks)
{
float *oldTangents = frame->tangents;
frame->tangents = newTangents;
Z_Free(oldTangents);
}*/
}
}
}
typedef struct materiallist_s
{
struct materiallist_s *next;
struct materiallist_s *prev;
material_t *material;
} materiallist_t;
static boolean AddMaterialToList(materiallist_t **head, material_t *material)
{
materiallist_t *node, *newMatNode;
for (node = *head; node; node = node->next)
{
if (node->material == material)
return false;
}
// Didn't find it, so add to the list
newMatNode = (materiallist_t*)Z_Malloc(sizeof(materiallist_t), PU_CACHE, 0);
newMatNode->material = material;
ListAdd(newMatNode, (listitem_t**)head);
return true;
}
//
// Optimize
//
// Groups triangles from meshes in the model
// Only works for models with 1 frame
//
void Optimize(model_t *model)
{
int numMeshes = 0;
int i;
materiallist_t *matListHead = NULL;
int memTag;
mesh_t *newMeshes;
materiallist_t *node;
if (model->numMeshes <= 1)
return; // No need
for (i = 0; i < model->numMeshes; i++)
{
mesh_t *curMesh = &model->meshes[i];
if (curMesh->numFrames > 1)
return; // Can't optimize models with > 1 frame
if (!curMesh->frames)
return; // Don't optimize tinyframe models (no need)
// We are condensing to 1 mesh per material, so
// the # of materials we use will be the new
// # of meshes
if (AddMaterialToList(&matListHead, curMesh->frames[0].material))
numMeshes++;
}
memTag = PU_STATIC;
newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0);
i = 0;
for (node = matListHead; node; node = node->next)
{
material_t *curMat = node->material;
mesh_t *newMesh = &newMeshes[i];
mdlframe_t *curFrame;
int uvCount;
int vertCount;
int colorCount;
// Find all triangles with this material and count them
int numTriangles = 0;
int j;
for (j = 0; j < model->numMeshes; j++)
{
mesh_t *curMesh = &model->meshes[j];
if (curMesh->frames[0].material == curMat)
numTriangles += curMesh->numTriangles;
}
newMesh->numFrames = 1;
newMesh->numTriangles = numTriangles;
newMesh->numVertices = numTriangles * 3;
newMesh->uvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
// if (node->material->lightmap)
// newMesh->lightuvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
newMesh->frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t), memTag, 0);
curFrame = &newMesh->frames[0];
curFrame->material = curMat;
curFrame->normals = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
// if (!systemSucks)
// curFrame->tangents = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
curFrame->vertices = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
curFrame->colors = (char*)Z_Malloc(sizeof(char)*4*numTriangles*3, memTag, 0);
// Now traverse the meshes of the model, adding in
// vertices/normals/uvs that match the current material
uvCount = 0;
vertCount = 0;
colorCount = 0;
for (j = 0; j < model->numMeshes; j++)
{
mesh_t *curMesh = &model->meshes[j];
if (curMesh->frames[0].material == curMat)
{
float *dest;
float *src;
char *destByte;
char *srcByte;
M_Memcpy(&newMesh->uvs[uvCount],
curMesh->uvs,
sizeof(float)*2*curMesh->numTriangles*3);
/* if (node->material->lightmap)
{
M_Memcpy(&newMesh->lightuvs[uvCount],
curMesh->lightuvs,
sizeof(float)*2*curMesh->numTriangles*3);
}*/
uvCount += 2*curMesh->numTriangles*3;
dest = (float*)newMesh->frames[0].vertices;
src = (float*)curMesh->frames[0].vertices;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
dest = (float*)newMesh->frames[0].normals;
src = (float*)curMesh->frames[0].normals;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
/* if (!systemSucks)
{
dest = (float*)newMesh->frames[0].tangents;
src = (float*)curMesh->frames[0].tangents;
M_Memcpy(&dest[vertCount],
src,
sizeof(float)*3*curMesh->numTriangles*3);
}*/
vertCount += 3 * curMesh->numTriangles * 3;
destByte = (char*)newMesh->frames[0].colors;
srcByte = (char*)curMesh->frames[0].colors;
if (srcByte)
{
M_Memcpy(&destByte[colorCount],
srcByte,
sizeof(char)*4*curMesh->numTriangles*3);
}
else
{
memset(&destByte[colorCount],
255,
sizeof(char)*4*curMesh->numTriangles*3);
}
colorCount += 4 * curMesh->numTriangles * 3;
}
}
i++;
}
CONS_Printf("Model::Optimize(): Model reduced from %d to %d meshes.\n", model->numMeshes, numMeshes);
model->meshes = newMeshes;
model->numMeshes = numMeshes;
}
void GeneratePolygonNormals(model_t *model, int ztag)
{
int i;
for (i = 0; i < model->numMeshes; i++)
{
int j;
mesh_t *mesh = &model->meshes[i];
if (!mesh->frames)
continue;
for (j = 0; j < mesh->numFrames; j++)
{
int k;
mdlframe_t *frame = &mesh->frames[j];
const float *vertices = frame->vertices;
vector_t *polyNormals;
frame->polyNormals = (vector_t*)Z_Malloc(sizeof(vector_t) * mesh->numTriangles, ztag, 0);
polyNormals = frame->polyNormals;
for (k = 0; k < mesh->numTriangles; k++)
{
// Vector::Normal(vertices, polyNormals);
vertices += 3 * 3;
polyNormals++;
}
}
}
}
//
// Reload
//
// Reload VBOs
//
#if 0
static void Reload(void)
{
/* model_t *node;
for (node = modelHead; node; node = node->next)
{
int i;
for (i = 0; i < node->numMeshes; i++)
{
mesh_t *mesh = &node->meshes[i];
if (mesh->frames)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
CreateVBO(mesh, &mesh->frames[j]);
}
else if (mesh->tinyframes)
{
int j;
for (j = 0; j < mesh->numFrames; j++)
CreateVBO(mesh, &mesh->tinyframes[j]);
}
}
}*/
}
#endif
void DeleteVBOs(model_t *model)
{
(void)model;
/* for (int i = 0; i < model->numMeshes; i++)
{
mesh_t *mesh = &model->meshes[i];
if (mesh->frames)
{
for (int j = 0; j < mesh->numFrames; j++)
{
mdlframe_t *frame = &mesh->frames[j];
if (!frame->vboID)
continue;
bglDeleteBuffers(1, &frame->vboID);
frame->vboID = 0;
}
}
else if (mesh->tinyframes)
{
for (int j = 0; j < mesh->numFrames; j++)
{
tinyframe_t *frame = &mesh->tinyframes[j];
if (!frame->vboID)
continue;
bglDeleteBuffers(1, &frame->vboID);
frame->vboID = 0;
}
}
}*/
}

121
src/hardware/hw_model.h Normal file
View File

@ -0,0 +1,121 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _HW_MODEL_H_
#define _HW_MODEL_H_
#include "../doomtype.h"
typedef struct
{
float x, y, z;
} vector_t;
extern vector_t vectorXaxis;
extern vector_t vectorYaxis;
extern vector_t vectorZaxis;
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle);
typedef struct
{
float ambient[4], diffuse[4], specular[4], emissive[4];
float shininess;
boolean spheremap;
// Texture::texture_t *texture;
// Texture::texture_t *lightmap;
} material_t;
typedef struct
{
material_t *material; // Pointer to the allocated 'materials' list in model_t
float *vertices;
float *normals;
float *tangents;
char *colors;
unsigned int vboID;
vector_t *polyNormals;
} mdlframe_t;
typedef struct
{
material_t *material;
short *vertices;
char *normals;
char *tangents;
unsigned int vboID;
} tinyframe_t;
// Equivalent to MD3's many 'surfaces'
typedef struct mesh_s
{
int numVertices;
int numTriangles;
float *uvs;
float *lightuvs;
int numFrames;
mdlframe_t *frames;
tinyframe_t *tinyframes;
unsigned short *indices;
} mesh_t;
typedef struct tag_s
{
char name[64];
// matrix_t transform;
} tag_t;
#define MODEL_INTERPOLATION_FLAG "+i"
typedef struct
{
INT32 frames[256];
UINT8 numframes;
boolean interpolate;
} modelspr2frames_t;
typedef struct model_s
{
int maxNumFrames;
int numMaterials;
material_t *materials;
int numMeshes;
mesh_t *meshes;
int numTags;
tag_t *tags;
char *mdlFilename;
boolean unloaded;
char *framenames;
boolean interpolate[256];
modelspr2frames_t *spr2frames;
} model_t;
extern int numModels;
extern model_t *modelHead;
void HWR_ReloadModels(void);
tag_t *GetTagByName(model_t *model, char *name, int frame);
model_t *LoadModel(const char *filename, int ztag);
void UnloadModel(model_t *model);
void Optimize(model_t *model);
void LoadModelInterpolationSettings(model_t *model);
void LoadModelSprite2(model_t *model);
void GenerateVertexNormals(model_t *model);
void GeneratePolygonNormals(model_t *model, int ztag);
void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame);
void CreateVBO(mesh_t *mesh, mdlframe_t *frame);
void DeleteVBOs(model_t *model);
#endif

View File

@ -347,13 +347,6 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD;
DBG_Printf("oglflags : 0x%X\n", oglflags);
#ifdef USE_PALETTED_TEXTURE
if (isExtAvailable("GL_EXT_paletted_texture",gl_extensions))
glColorTableEXT = GetGLFunc("glColorTableEXT");
else
glColorTableEXT = NULL;
#endif
#ifdef USE_WGL_SWAP
if (isExtAvailable("WGL_EXT_swap_control",gl_extensions))
wglSwapIntervalEXT = GetGLFunc("wglSwapIntervalEXT");
@ -582,19 +575,8 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *pal, RGBA_t *gamma)
myPaletteData[i].s.blue = (UINT8)MIN((pal[i].s.blue*gamma->s.blue)/127, 255);
myPaletteData[i].s.alpha = pal[i].s.alpha;
}
#ifdef USE_PALETTED_TEXTURE
if (glColorTableEXT)
{
for (i = 0; i < 256; i++)
{
palette_tex[3*i+0] = pal[i].s.red;
palette_tex[3*i+1] = pal[i].s.green;
palette_tex[3*i+2] = pal[i].s.blue;
}
glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex);
}
#endif
// on a chang<6E> de palette, il faut recharger toutes les textures
// on a palette change, you have to reload all of the textures
Flush();
}

File diff suppressed because it is too large Load Diff

View File

@ -71,7 +71,6 @@ extern FILE *gllogstream;
#endif
#ifndef DRIVER_STRING
// #define USE_PALETTED_TEXTURE
#define DRIVER_STRING "HWRAPI Init(): SRB2 OpenGL renderer" // Tails
#endif
@ -89,10 +88,6 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth
void SetModelView(GLint w, GLint h);
void SetStates(void);
FUNCMATH float byteasfloat(UINT8 fbyte);
#ifdef USE_PALETTED_TEXTURE
extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
extern GLubyte palette_tex[256*3];
#endif
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
@ -118,6 +113,10 @@ typedef void (APIENTRY * PFNglGetIntegerv) (GLenum pname, GLint *params);
extern PFNglGetIntegerv pglGetIntegerv;
typedef const GLubyte* (APIENTRY * PFNglGetString) (GLenum name);
extern PFNglGetString pglGetString;
#if 0
typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); // redefined in r_opengl.c
static PFNglEnableClientState pglEnableClientState;
#endif
#endif
// ==========================================================================

View File

@ -0,0 +1,52 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _R_VBO_H_
#define _R_VBO_H_
typedef struct
{
float x, y, z; // Vertex
float nx, ny, nz; // Normal
float s0, t0; // Texcoord0
} vbo32_t;
typedef struct
{
float x, y, z; // Vertex
float s0, t0; // Texcoord0
unsigned char r, g, b, a; // Color
float pad[2]; // Pad
} vbo2d32_t;
typedef struct
{
float x, y; // Vertex
float s0, t0; // Texcoord0
} vbofont_t;
typedef struct
{
short x, y, z; // Vertex
char nx, ny, nz; // Normal
char tanx, tany, tanz; // Tangent
float s0, t0; // Texcoord0
} vbotiny_t;
typedef struct
{
float x, y, z; // Vertex
float nx, ny, nz; // Normal
float s0, t0; // Texcoord0
float s1, t1; // Texcoord1
float s2, t2; // Texcoord2
float tan0, tan1, tan2; // Tangent
unsigned char r, g, b, a; // Color
} vbo64_t;
#endif

230
src/hardware/u_list.c Normal file
View File

@ -0,0 +1,230 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#include "u_list.h"
#include "../z_zone.h"
// Utility for managing
// structures in a linked
// list.
//
// Struct must have "next" and "prev" pointers
// as its first two variables.
//
//
// ListAdd
//
// Adds an item to the list
//
void ListAdd(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (*itemHead == NULL)
{
*itemHead = item;
(*itemHead)->prev = (*itemHead)->next = NULL;
}
else
{
listitem_t *tail;
tail = *itemHead;
while (tail->next != NULL)
tail = tail->next;
tail->next = item;
tail->next->prev = tail;
item->next = NULL;
}
}
//
// ListAddFront
//
// Adds an item to the front of the list
// (This is much faster)
//
void ListAddFront(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (*itemHead == NULL)
{
*itemHead = item;
(*itemHead)->prev = (*itemHead)->next = NULL;
}
else
{
(*itemHead)->prev = item;
item->next = (*itemHead);
item->prev = NULL;
*itemHead = item;
}
}
//
// ListAddBefore
//
// Adds an item before the item specified in the list
//
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
listitem_t *spot = (listitem_t*)pSpot;
listitem_t *prev = spot->prev;
if (!prev)
ListAddFront(pItem, itemHead);
else
{
item->next = spot;
spot->prev = item;
item->prev = prev;
prev->next = item;
}
}
//
// ListAddAfter
//
// Adds an item after the item specified in the list
//
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
listitem_t *spot = (listitem_t*)pSpot;
listitem_t *next = spot->next;
if (!next)
ListAdd(pItem, itemHead);
else
{
item->prev = spot;
spot->next = item;
item->next = next;
next->prev = item;
}
}
//
// ListRemove
//
// Take an item out of the list and free its memory.
//
void ListRemove(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (item == *itemHead) // Start of list
{
*itemHead = item->next;
if (*itemHead)
(*itemHead)->prev = NULL;
}
else if (item->next == NULL) // end of list
{
item->prev->next = NULL;
}
else // Somewhere in between
{
item->prev->next = item->next;
item->next->prev = item->prev;
}
Z_Free (item);
}
//
// ListRemoveAll
//
// Removes all items from the list, freeing their memory.
//
void ListRemoveAll(listitem_t **itemHead)
{
listitem_t *item;
listitem_t *next;
for (item = *itemHead; item; item = next)
{
next = item->next;
ListRemove(item, itemHead);
}
}
//
// ListRemoveNoFree
//
// Take an item out of the list, but don't free its memory.
//
void ListRemoveNoFree(void *pItem, listitem_t **itemHead)
{
listitem_t *item = (listitem_t*)pItem;
if (item == *itemHead) // Start of list
{
*itemHead = item->next;
if (*itemHead)
(*itemHead)->prev = NULL;
}
else if (item->next == NULL) // end of list
{
item->prev->next = NULL;
}
else // Somewhere in between
{
item->prev->next = item->next;
item->next->prev = item->prev;
}
}
//
// ListGetCount
//
// Counts the # of items in a list
// Should not be used in performance-minded code
//
unsigned int ListGetCount(void *itemHead)
{
listitem_t *item = (listitem_t*)itemHead;
unsigned int count = 0;
for (; item; item = item->next)
count++;
return count;
}
//
// ListGetByIndex
//
// Gets an item in the list by its index
// Should not be used in performance-minded code
//
listitem_t *ListGetByIndex(void *itemHead, unsigned int index)
{
listitem_t *head = (listitem_t*)itemHead;
unsigned int count = 0;
listitem_t *node;
for (node = head; node; node = node->next)
{
if (count == index)
return node;
count++;
}
return NULL;
}

29
src/hardware/u_list.h Normal file
View File

@ -0,0 +1,29 @@
/*
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
An experimental work-in-progress.
Donated to Sonic Team Junior and adapted to work with
Sonic Robo Blast 2. The license of this code matches whatever
the licensing is for Sonic Robo Blast 2.
*/
#ifndef _U_LIST_H_
#define _U_LIST_H_
typedef struct listitem_s
{
struct listitem_s *next;
struct listitem_s *prev;
} listitem_t;
void ListAdd(void *pItem, listitem_t **itemHead);
void ListAddFront(void *pItem, listitem_t **itemHead);
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead);
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead);
void ListRemove(void *pItem, listitem_t **itemHead);
void ListRemoveAll(listitem_t **itemHead);
void ListRemoveNoFree(void *pItem, listitem_t **itemHead);
unsigned int ListGetCount(void *itemHead);
listitem_t *ListGetByIndex(void *itemHead, unsigned int index);
#endif

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)

1168
src/info.c

File diff suppressed because it is too large Load Diff

View File

@ -63,6 +63,7 @@ void A_FishJump(); // Fish Jump
void A_ThrownRing(); // Sparkle trail for red ring
void A_SetSolidSteam();
void A_UnsetSolidSteam();
void A_SignSpin();
void A_SignPlayer();
void A_OverlayThink();
void A_JetChase();
@ -268,6 +269,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 +307,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 +327,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 +410,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 +525,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 +533,10 @@ typedef enum sprite
// Red Volcano Scenery
SPR_FLME, // Flame jet
SPR_DFLM, // Blade's flame
SPR_LFAL, // Lavafall
SPR_JPLA, // Jungle palm
SPR_TFLO, // Torch flower
SPR_WVIN, // Wall vines
// Dark City Scenery
@ -531,7 +548,9 @@ typedef enum sprite
SPR_XMS3, // Snowman
SPR_XMS4, // Lamppost
SPR_XMS5, // Hanging Star
SPR_XMS6, // Mistletoe
SPR_FHZI, // FHZ Ice
SPR_ROSY,
// Halloween Scenery
SPR_PUMK, // Pumpkins
@ -539,6 +558,11 @@ typedef enum sprite
SPR_SHRM, // Mushroom
SPR_HHZM, // Misc
// Azure Temple Scenery
SPR_BGAR, // ATZ Gargoyles
SPR_RCRY, // ATZ Red Crystal (Target)
SPR_CFLM, // Green torch flame
// Botanic Serenity Scenery
SPR_BSZ1, // Tall flowers
SPR_BSZ2, // Medium flowers
@ -558,7 +582,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 +635,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 +797,7 @@ typedef enum playersprite
SPR2_TIRE, // tired
SPR2_GLID, // glide
SPR2_LAND, // landing after glide/bounce
SPR2_CLNG, // cling
SPR2_CLMB, // climb
@ -778,7 +805,6 @@ typedef enum playersprite
SPR2_FRUN, // float run
SPR2_BNCE, // bounce
SPR2_BLND, // bounce landing
SPR2_FIRE, // fire
@ -854,6 +880,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 +932,7 @@ typedef enum state
// CA_GLIDEANDCLIMB
S_PLAY_GLIDE,
S_PLAY_GLIDE_LANDING,
S_PLAY_CLING,
S_PLAY_CLIMB,
@ -999,6 +1032,9 @@ typedef enum state
S_TAILSOVERLAY_GASP,
S_TAILSOVERLAY_EDGE,
// [:
S_JETFUMEFLASH,
// Blue Crawla
S_POSS_STND,
S_POSS_RUN1,
@ -1147,6 +1183,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 +1384,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,
@ -1867,25 +1934,7 @@ typedef enum state
S_CYBRAKDEMONVILEEXPLOSION3,
// Metal Sonic (Race)
// S_PLAY_STND
S_METALSONIC_STAND,
// S_PLAY_TAP1
S_METALSONIC_WAIT1,
S_METALSONIC_WAIT2,
// S_PLAY_WALK
S_METALSONIC_WALK1,
S_METALSONIC_WALK2,
S_METALSONIC_WALK3,
S_METALSONIC_WALK4,
S_METALSONIC_WALK5,
S_METALSONIC_WALK6,
S_METALSONIC_WALK7,
S_METALSONIC_WALK8,
// S_PLAY_SPD1
S_METALSONIC_RUN1,
S_METALSONIC_RUN2,
S_METALSONIC_RUN3,
S_METALSONIC_RUN4,
S_METALSONIC_RACE,
// Metal Sonic (Battle)
S_METALSONIC_FLOAT,
S_METALSONIC_VECTOR,
@ -1992,59 +2041,18 @@ typedef enum state
S_BUBBLES4,
// Level End Sign
S_SIGN1,
S_SIGN2,
S_SIGN3,
S_SIGN4,
S_SIGN5,
S_SIGN6,
S_SIGN7,
S_SIGN8,
S_SIGN9,
S_SIGN10,
S_SIGN11,
S_SIGN12,
S_SIGN13,
S_SIGN14,
S_SIGN15,
S_SIGN16,
S_SIGN17,
S_SIGN18,
S_SIGN19,
S_SIGN20,
S_SIGN21,
S_SIGN22,
S_SIGN23,
S_SIGN24,
S_SIGN25,
S_SIGN26,
S_SIGN27,
S_SIGN28,
S_SIGN29,
S_SIGN30,
S_SIGN31,
S_SIGN32,
S_SIGN33,
S_SIGN34,
S_SIGN35,
S_SIGN36,
S_SIGN37,
S_SIGN38,
S_SIGN39,
S_SIGN40,
S_SIGN41,
S_SIGN42,
S_SIGN43,
S_SIGN44,
S_SIGN45,
S_SIGN46,
S_SIGN47,
S_SIGN48,
S_SIGN49,
S_SIGN50,
S_SIGN51,
S_SIGN52, // Eggman
S_SIGN53,
S_SIGN,
S_SIGNSPIN1,
S_SIGNSPIN2,
S_SIGNSPIN3,
S_SIGNSPIN4,
S_SIGNSPIN5,
S_SIGNSPIN6,
S_SIGNPLAYER,
S_SIGNSLOW,
S_SIGNSTOP,
S_SIGNBOARD,
S_EGGMANSIGN,
// Spike Ball
S_SPIKEBALL1,
@ -2269,7 +2277,7 @@ typedef enum state
S_ARROW,
S_ARROWBONK,
// Trapgoyle Demon fire
// Glaregoyle Demon fire
S_DEMONFIRE,
// GFZ flowers
@ -2576,7 +2584,7 @@ typedef enum state
// Saloon door
S_SALOONDOOR,
S_SALOONDOORTHINKER,
S_SALOONDOORCENTER,
// Train cameo
S_TRAINCAMEOSPAWNER_1,
@ -2597,6 +2605,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,29 +2623,57 @@ typedef enum state
S_FLAMEJETFLAMEB2,
S_FLAMEJETFLAMEB3,
// Trapgoyles
S_TRAPGOYLE,
S_TRAPGOYLE_CHECK,
S_TRAPGOYLE_FIRE1,
S_TRAPGOYLE_FIRE2,
S_TRAPGOYLE_FIRE3,
S_TRAPGOYLEUP,
S_TRAPGOYLEUP_CHECK,
S_TRAPGOYLEUP_FIRE1,
S_TRAPGOYLEUP_FIRE2,
S_TRAPGOYLEUP_FIRE3,
S_TRAPGOYLEDOWN,
S_TRAPGOYLEDOWN_CHECK,
S_TRAPGOYLEDOWN_FIRE1,
S_TRAPGOYLEDOWN_FIRE2,
S_TRAPGOYLEDOWN_FIRE3,
S_TRAPGOYLELONG,
S_TRAPGOYLELONG_CHECK,
S_TRAPGOYLELONG_FIRE1,
S_TRAPGOYLELONG_FIRE2,
S_TRAPGOYLELONG_FIRE3,
S_TRAPGOYLELONG_FIRE4,
S_TRAPGOYLELONG_FIRE5,
// 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,
// Glaregoyles
S_GLAREGOYLE,
S_GLAREGOYLE_CHARGE,
S_GLAREGOYLE_BLINK,
S_GLAREGOYLE_HOLD,
S_GLAREGOYLE_FIRE,
S_GLAREGOYLE_LOOP,
S_GLAREGOYLE_COOLDOWN,
S_GLAREGOYLEUP,
S_GLAREGOYLEUP_CHARGE,
S_GLAREGOYLEUP_BLINK,
S_GLAREGOYLEUP_HOLD,
S_GLAREGOYLEUP_FIRE,
S_GLAREGOYLEUP_LOOP,
S_GLAREGOYLEUP_COOLDOWN,
S_GLAREGOYLEDOWN,
S_GLAREGOYLEDOWN_CHARGE,
S_GLAREGOYLEDOWN_BLINK,
S_GLAREGOYLEDOWN_HOLD,
S_GLAREGOYLEDOWN_FIRE,
S_GLAREGOYLEDOWN_LOOP,
S_GLAREGOYLEDOWN_COOLDOWN,
S_GLAREGOYLELONG,
S_GLAREGOYLELONG_CHARGE,
S_GLAREGOYLELONG_BLINK,
S_GLAREGOYLELONG_HOLD,
S_GLAREGOYLELONG_FIRE,
S_GLAREGOYLELONG_LOOP,
S_GLAREGOYLELONG_COOLDOWN,
// ATZ's Red Crystal/Target
S_TARGET_IDLE,
@ -2640,6 +2682,12 @@ typedef enum state
S_TARGET_RESPAWN,
S_TARGET_ALLDONE,
// ATZ's green flame
S_GREENFLAME,
// ATZ Blue Gargoyle
S_BLUEGARGOYLE,
// Stalagmites
S_STG0,
S_STG1,
@ -2660,6 +2708,7 @@ typedef enum state
S_LAMPPOST1, // normal
S_LAMPPOST2, // with snow
S_HANGSTAR,
S_MISTLETOE,
// Xmas GFZ bushes
S_XMASBLUEBERRYBUSH,
S_XMASBERRYBUSH,
@ -2667,6 +2716,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 +3377,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 +3408,9 @@ typedef enum state
S_SPLISH8,
S_SPLISH9,
// Lava Splish
S_LAVASPLISH,
// added water splash
S_SPLASH1,
S_SPLASH2,
@ -3805,8 +3878,8 @@ typedef enum state
S_BUMBLEBORE_STUCK2,
S_BUMBLEBORE_DIE,
S_BBUZZFLY1,
S_BBUZZFLY2,
S_BUGGLEIDLE,
S_BUGGLEFLY,
S_SMASHSPIKE_FLOAT,
S_SMASHSPIKE_EASE1,
@ -3971,6 +4044,7 @@ typedef enum mobj_type
MT_THOK, // Thok! mobj
MT_PLAYER,
MT_TAILSOVERLAY, // c:
MT_METALJETFUME,
// Enemies
MT_BLUECRAWLA, // Crawla (Blue)
@ -3989,6 +4063,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 +4086,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 +4202,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
@ -4211,7 +4297,7 @@ typedef enum mobj_type
MT_CANNONBALL, // Cannonball
MT_CANNONBALLDECOR, // Decorative/still cannonball
MT_ARROW, // Arrow
MT_DEMONFIRE, // Trapgoyle fire
MT_DEMONFIRE, // Glaregoyle fire
// Greenflower Scenery
MT_GFZFLOWER1,
@ -4338,7 +4424,7 @@ typedef enum mobj_type
MT_MINECARTSIDEMARK,
MT_MINECARTSPARK,
MT_SALOONDOOR,
MT_SALOONDOORTHINKER,
MT_SALOONDOORCENTER,
MT_TRAINCAMEOSPAWNER,
MT_TRAINSEG,
MT_TRAINDUSTSPAWNER,
@ -4355,16 +4441,32 @@ 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
// Azure Temple Scenery
MT_TRAPGOYLE,
MT_TRAPGOYLEUP,
MT_TRAPGOYLEDOWN,
MT_TRAPGOYLELONG,
MT_GLAREGOYLE,
MT_GLAREGOYLEUP,
MT_GLAREGOYLEDOWN,
MT_GLAREGOYLELONG,
MT_TARGET, // AKA Red Crystal
MT_GREENFLAME,
MT_BLUEGARGOYLE,
// Stalagmites
MT_STALAGMITE0,
@ -4386,6 +4488,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 +4496,8 @@ typedef enum mobj_type
// FHZ
MT_FHZICE1,
MT_FHZICE2,
MT_ROSY,
MT_CDLHRT,
// Halloween Scenery
// Pumpkins
@ -4521,6 +4626,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
@ -4635,7 +4741,7 @@ typedef enum mobj_type
MT_HIVEELEMENTAL,
MT_BUMBLEBORE,
MT_BUBBLEBUZZ,
MT_BUGGLE,
MT_SMASHINGSPIKEBALL,
MT_CACOLANTERN,

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

@ -718,6 +718,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);
@ -740,6 +802,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;
@ -918,9 +987,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');
if (!big)
pnamebuf[5] = em->sprite;
else
pnamebuf[4] = em->sprite;
return pnamebuf;
}
@ -544,11 +554,21 @@ skincolors_t M_GetExtraEmblemColor(extraemblem_t *em)
return em->color;
}
const char *M_GetExtraEmblemPatch(extraemblem_t *em)
const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big)
{
static char pnamebuf[7] = "GOTITn";
static char pnamebuf[7];
if (!big)
strcpy(pnamebuf, "GOTITn");
else
strcpy(pnamebuf, "EMBMn0");
I_Assert(em->sprite >= 'A' && em->sprite <= 'Z');
if (!big)
pnamebuf[5] = em->sprite;
else
pnamebuf[4] = em->sprite;
return pnamebuf;
}

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

View File

@ -458,6 +458,20 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
return FV3_AddEx(&Line[0], &V, out);
}
//
// ClosestPointOnVector
//
// Similar to ClosestPointOnLine, but uses a vector instead of two points.
//
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out)
{
fixed_t t = FV3_Dot(dir, p);
// Return the point on the line closest
FV3_MulEx(dir, t, out);
return;
}
//
// ClosestPointOnTriangle
//
@ -519,7 +533,7 @@ vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vect
//
// Calculates the normal of a polygon.
//
void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal)
{
vector3_t a_1;
vector3_t a_2;
@ -529,7 +543,28 @@ void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
FV3_Cross(&a_1, &a_2, a_normal);
FV3_NormalizeEx(a_normal, a_normal);
return FV3_NormalizeEx(a_normal, a_normal);
}
//
// Strength
//
// Measures the 'strength' of a vector in a particular direction.
//
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir)
{
vector3_t normal;
fixed_t dist = FV3_NormalizeEx(a_1, &normal);
fixed_t dot = FV3_Dot(&normal, dir);
FV3_ClosestPointOnVector(dir, a_1, &normal);
dist = FV3_Magnitude(&normal);
if (dot < 0) // Not facing same direction, so negate result.
dist = -dist;
return dist;
}
//

View File

@ -389,9 +389,11 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2);
fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2);
vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o);
vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vector3_t *out);
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out);
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result);
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o);
void FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir);
fixed_t FV3_PlaneDistance(const vector3_t *a_normal, const vector3_t *a_point);
boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_line, vector3_t *a_normal, fixed_t *originDistance);
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector);

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
#include "d_event.h"
#include "command.h"
#include "r_things.h" // for SKINNAMESIZE
#include "f_finale.h" // for ttmode_enum
//
// MENUS
@ -63,6 +64,7 @@ typedef enum
MN_MP_CONNECT,
MN_MP_ROOM,
MN_MP_PLAYERSETUP, // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
MN_MP_SERVER_OPTIONS,
// Options
MN_OP_MAIN,
@ -103,6 +105,7 @@ typedef enum
MN_SR_LEVELSELECT,
MN_SR_UNLOCKCHECKLIST,
MN_SR_EMBLEMHINT,
MN_SR_PLAYER,
// Addons (Part of MISC, but let's make it our own)
MN_AD_MAIN,
@ -126,19 +129,27 @@ typedef enum
typedef struct
{
char bgname[8]; // name for background gfx lump; lays over titlemap if this is set
SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting
SINT8 fadestrength; // darken background when displaying this menu, strength 0-31 or -1 for undefined
INT32 bgcolor; // fill color, overrides bg name. -1 means follow bg name rules.
INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting
INT32 titlescrollyspeed; // y scroll
INT32 bgcolor; // fill color, overrides bg name. -1 means follow bg name rules.
boolean bghide; // for titlemaps, hide the background.
SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting
ttmode_enum ttmode; // title wing animation mode; default TTMODE_OLD
UINT8 ttscale; // scale of title wing gfx (FRACUNIT / ttscale); -1 means undefined, inherits global setting
char ttname[9]; // lump name of title wing gfx. If name length is <= 6, engine will attempt to load numbered frames (TTNAMExx)
INT16 ttx; // X position of title wing
INT16 tty; // Y position of title wing
INT16 ttloop; // # frame to loop; -1 means dont loop
UINT16 tttics; // # of tics per frame
char musname[7]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
boolean muslooping; ///< Loop the music
boolean musstop; ///< Don't play any music
boolean musignore; ///< Let the current music keep playing
SINT8 fadestrength; // darken background when displaying this menu, strength 0-31 or -1 for undefined
boolean enterbubble; // run all entrance line execs after common ancestor and up to child. If false, only run the child's exec
boolean exitbubble; // run all exit line execs from child and up to before common ancestor. If false, only run the child's exec
INT32 entertag; // line exec to run on menu enter, if titlemap
@ -156,7 +167,7 @@ UINT8 M_GetYoungestChildMenu(void);
void M_ChangeMenuMusic(const char *defaultmusname, boolean defaultmuslooping);
void M_SetMenuCurBackground(const char *defaultname);
void M_SetMenuCurFadeValue(UINT8 defaultvalue);
void M_SetMenuCurHideTitlePics(void);
void M_SetMenuCurTitlePics(void);
// Called by main loop,
// saves config file and calls I_Quit when user exits.
@ -323,9 +334,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 +394,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

@ -129,6 +129,7 @@ void A_FishJump(mobj_t *actor);
void A_ThrownRing(mobj_t *actor);
void A_SetSolidSteam(mobj_t *actor);
void A_UnsetSolidSteam(mobj_t *actor);
void A_SignSpin(mobj_t *actor);
void A_SignPlayer(mobj_t *actor);
void A_OverlayThink(mobj_t *actor);
void A_JetChase(mobj_t *actor);
@ -298,6 +299,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 +2028,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 +2089,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 +2172,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;
}
@ -3921,11 +3931,15 @@ void A_BossDeath(mobj_t *mo)
{
// Touching the egg trap button calls P_DoPlayerExit, which calls P_RestoreMusic.
// So just park ourselves in the mapmus variables.
boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7);
// But don't change the mapmus variables if they were modified from their level header values (e.g., TUNES).
boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, S_MusicName(), 7);
if (!strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7))
{
strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7);
mapmusname[6] = 0;
mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET;
mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos;
}
// don't change if we're in another tune
// but in case we're in jingle, use our parked mapmus variables so the correct track restores
@ -4750,7 +4764,7 @@ void A_DropMine(mobj_t *actor)
// Description: Makes the stupid harmless fish in Greenflower Zone jump.
//
// var1 = Jump strength (in FRACBITS), if specified. Otherwise, uses the angle value.
// var2 = unused
// var2 = Trail object to spawn, if desired.
//
void A_FishJump(mobj_t *actor)
{
@ -4762,10 +4776,19 @@ void A_FishJump(mobj_t *actor)
#endif
if (locvar2)
{
UINT8 i;
// Don't spawn trail unless a player is nearby.
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) < (actor->info->speed))
break; // Stop looking.
if (i < MAXPLAYERS)
{
fixed_t rad = actor->radius>>FRACBITS;
P_SpawnMobjFromMobj(actor, P_RandomRange(rad, -rad)<<FRACBITS, P_RandomRange(rad, -rad)<<FRACBITS, 0, (mobjtype_t)locvar2);
}
}
if ((actor->z <= actor->floorz) || (actor->z <= actor->watertop - FixedMul((64 << FRACBITS), actor->scale)))
{
@ -4997,21 +5020,100 @@ void A_UnsetSolidSteam(mobj_t *actor)
actor->flags |= MF_NOCLIP;
}
// Function: A_SignSpin
//
// Description: Spins a signpost until it hits the ground and reaches its mapthing's angle.
//
// var1 = degrees to rotate object (must be positive, because I'm lazy)
// var2 = unused
//
void A_SignSpin(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
INT16 i;
angle_t rotateangle = FixedAngle(locvar1 << FRACBITS);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SignSpin", actor))
return;
#endif
if (P_IsObjectOnGround(actor) && P_MobjFlip(actor) * actor->momz <= 0)
{
if (actor->spawnpoint)
{
angle_t mapangle = FixedAngle(actor->spawnpoint->angle << FRACBITS);
angle_t diff = mapangle - actor->angle;
if (diff < ANG2)
{
actor->angle = mapangle;
P_SetMobjState(actor, actor->info->deathstate);
return;
}
if ((statenum_t)(actor->state-states) != actor->info->painstate)
P_SetMobjState(actor, actor->info->painstate);
actor->movedir = min((mapangle - actor->angle) >> 2, actor->movedir);
}
else // no mapthing? just finish in your current angle
{
P_SetMobjState(actor, locvar2);
return;
}
}
else
{
actor->movedir = rotateangle;
}
actor->angle += actor->movedir;
if (actor->tracer == NULL || P_MobjWasRemoved(actor->tracer)) return;
for (i = -1; i < 2; i += 2)
{
P_SpawnMobjFromMobj(actor,
P_ReturnThrustX(actor, actor->tracer->angle, i * actor->radius),
P_ReturnThrustY(actor, actor->tracer->angle, i * actor->radius),
(actor->eflags & MFE_VERTICALFLIP) ? 0 : actor->height,
actor->info->painchance)->destscale >>= 1;
}
}
// Function: A_SignPlayer
//
// Description: Changes the state of a level end sign to reflect the player that hit it.
// Also used to display Eggman or the skin roulette whilst spinning.
//
// var1 = unused
// var2 = unused
// var1 = number of skin to display (e.g. 2 = Knuckles; special cases: -1 = target's skin, -2 = skin roulette, -3 = Eggman)
// var2 = custom sign color, if desired.
//
void A_SignPlayer(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
skin_t *skin = NULL;
mobj_t *ov;
skin_t *skin;
UINT8 facecolor, signcolor = (UINT8)locvar2;
UINT32 signframe = states[actor->info->raisestate].frame;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SignPlayer", actor))
return;
#endif
if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins)
return;
// if no face overlay, spawn one
if (actor->tracer->tracer == NULL || P_MobjWasRemoved(actor->tracer->tracer))
{
ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY);
P_SetTarget(&ov->target, actor->tracer);
P_SetTarget(&actor->tracer->tracer, ov);
}
else
ov = actor->tracer->tracer;
if (locvar1 == -1) // set to target's skin
{
if (!actor->target)
return;
@ -5019,10 +5121,13 @@ void A_SignPlayer(mobj_t *actor)
return;
skin = &skins[actor->target->player->skin];
facecolor = actor->target->player->skincolor;
if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
if (signcolor)
;
else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
{
actor->color = skin->prefoppositecolor;
signcolor = skin->prefoppositecolor;
/*
If you're here from the comment above Color_Opposite,
the following line is the one which is dependent on the
@ -5034,22 +5139,67 @@ void A_SignPlayer(mobj_t *actor)
of in the name. If you have a better idea, feel free
to let me know. ~toast 2016/07/20
*/
actor->frame += (15 - Color_Opposite[Color_Opposite[skin->prefoppositecolor - 1][0] - 1][1]);
signframe += (15 - Color_Opposite[Color_Opposite[skin->prefoppositecolor - 1][0] - 1][1]);
}
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
{
actor->color = Color_Opposite[actor->target->player->skincolor - 1][0];
actor->frame += (15 - Color_Opposite[actor->target->player->skincolor - 1][1]);
signcolor = Color_Opposite[actor->target->player->skincolor - 1][0];
signframe += (15 - Color_Opposite[actor->target->player->skincolor - 1][1]);
}
else
signcolor = SKINCOLOR_NONE;
}
else if (locvar1 != -3) // set to a defined skin
{
// I turned this function into a fucking mess. I'm so sorry. -Lach
if (locvar1 == -2) // next skin
{
if (ov->skin == NULL) // pick a random skin to start with!
skin = &skins[P_RandomKey(numskins)];
else // otherwise, advance 1 skin
{
UINT8 skinnum = (skin_t*)ov->skin-skins;
player_t *player = actor->target ? actor->target->player : NULL;
while ((skinnum = (skinnum + 1) % numskins) && (player ? !R_SkinUsable(player-players, skinnum) : skins[skinnum].availability > 0));
skin = &skins[skinnum];
}
}
else // specific skin
{
skin = &skins[locvar1];
}
if (skin->sprites[SPR2_SIGN].numframes)
facecolor = skin->prefcolor;
if (signcolor)
;
else if (skin->prefoppositecolor)
{
// spawn an overlay of the player's face.
ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY);
P_SetTarget(&ov->target, actor);
ov->color = actor->target->player->skincolor;
signcolor = skin->prefoppositecolor;
}
else
{
signcolor = Color_Opposite[facecolor - 1][0];
}
signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
}
if (skin != NULL && skin->sprites[SPR2_SIGN].numframes) // player face
{
ov->color = facecolor;
ov->skin = skin;
P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN
actor->tracer->color = signcolor;
actor->tracer->frame = signframe;
}
else // Eggman face
{
ov->color = SKINCOLOR_NONE;
P_SetMobjState(ov, actor->info->meleestate); // S_EGGMANSIGN
if (signcolor)
actor->tracer->color = signcolor;
else
actor->tracer->color = signcolor = SKINCOLOR_CARBON;
actor->tracer->frame = signframe += (15 - Color_Opposite[Color_Opposite[signcolor - 1][0] - 1][1]);
}
}
@ -5097,7 +5247,7 @@ void A_OverlayThink(mobj_t *actor)
actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT;
else
actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT;
actor->angle = actor->target->angle;
actor->angle = actor->target->angle + actor->movedir;
actor->eflags = actor->target->eflags;
actor->momx = actor->target->momx;
@ -5343,10 +5493,13 @@ 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)
@ -5356,7 +5509,6 @@ static boolean PIT_MinusCarry(mobj_t *thing)
return true;
P_SetTarget(&minus->tracer, thing);
minus->tracer->flags &= ~MF_PUSHABLE;
return true;
}
@ -5420,6 +5572,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 +5624,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 +5636,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 +8563,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 +8575,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
@ -8949,10 +9107,11 @@ void A_BossJetFume(mobj_t *actor)
P_SetTarget(&filler->target, actor);
filler->fuse = 59;
P_SetTarget(&actor->tracer, filler);
filler->destscale = actor->scale/3;
P_SetScale(filler, filler->destscale);
P_SetScale(filler, (filler->destscale = actor->scale/3));
if (actor->eflags & MFE_VERTICALFLIP)
filler->flags2 |= MF2_OBJECTFLIP;
filler->color = SKINCOLOR_ICY;
filler->colorized = true;
}
else if (locvar1 == 3) // Boss 4 jet flame
{
@ -12197,7 +12356,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 +12396,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 +12409,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 +12428,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 +13604,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 +13824,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 +13838,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 +13859,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 +13894,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 +14049,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 +14146,299 @@ 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) < (actor->info->speed >> 1))
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;
UINT8 i;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_LavafallLava", actor))
return;
#endif
if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS)))
return;
// Don't spawn lava unless a player is nearby.
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) < (actor->info->speed))
break; // Stop looking.
if (i >= MAXPLAYERS)
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;
@ -2459,7 +2460,52 @@ void T_RaiseSector(levelspecthink_t *raise)
}
}
if (raise->vars[9]) // Dynamically Sinking Platform^tm
{
#define shaketime 10
if (raise->vars[11] > shaketime) // State: moving
{
if (playeronme) // If player is standing on the platform, accelerate
{
raise->vars[10] += (FRACUNIT >> 5);
}
else // otherwise, decelerate until inflection
{
raise->vars[10] -= FRACUNIT >> 3;
if (raise->vars[10] <= 0) // inflection!
{
raise->vars[10] = 0;
raise->vars[11] = 0; // allow the shake to occur again (fucks over players attempting to jump-cheese)
}
}
active = raise->vars[10] > 0;
}
else // State: shaking
{
if (playeronme || raise->vars[11])
{
active = true;
if (++raise->vars[11] > shaketime)
{
if (playeronme)
raise->vars[10] = FRACUNIT >> 5;
else
raise->vars[10] = FRACUNIT << 1;
}
else
{
raise->vars[10] = ((shaketime/2) - raise->vars[11]) << FRACBITS;
if (raise->vars[10] < -raise->vars[2]/2)
raise->vars[10] = -raise->vars[2]/2;
}
}
}
#undef shaketime
}
else // Air bobbing platform (not a Dynamically Sinking Platform^tm)
active = playeronme;
if (active)
{
raise->vars[3] = raise->vars[2];
@ -2553,6 +2599,8 @@ void T_RaiseSector(levelspecthink_t *raise)
raise->vars[3] = origspeed;
}
raise->vars[3] += raise->vars[10];
res = T_MovePlane
(
raise->sector, // sector

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;
}
@ -611,7 +633,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!(netgame || multiplayer))
{
player->continues += 1;
players->gotcontinue = true;
player->gotcontinue = true;
if (P_IsLocalPlayer(player))
S_StartSound(NULL, sfx_s3kac);
else
@ -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;
@ -2346,7 +2372,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (target->player && !target->player->spectator)
{
if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
G_StopMetalRecording();
G_StopMetalRecording(true);
if (gametype == GT_MATCH // note, no team match suicide penalty
&& ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player)))
{ // Suicide penalty
@ -2456,6 +2482,30 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
P_UnsetThingPosition(target);
target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
P_SetThingPosition(target);
target->standingslope = NULL;
target->pmomz = 0;
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))
;
@ -2567,7 +2617,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->fuse = target->info->damage;
break;
case MT_BUBBLEBUZZ:
case MT_BUGGLE:
if (inflictor && inflictor->player // did a player kill you? Spawn relative to the player so they're bound to get it
&& P_AproxDistance(inflictor->x - target->x, inflictor->y - target->y) <= inflictor->radius + target->radius + FixedMul(8*FRACUNIT, inflictor->scale) // close enough?
&& inflictor->z <= target->z + target->height + FixedMul(8*FRACUNIT, inflictor->scale)
@ -2602,6 +2652,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);
@ -2705,6 +2763,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
}
}
break;
case MT_METALSONIC_RACE:
target->fuse = TICRATE*3;
target->momx = target->momy = target->momz = 0;
P_SetObjectMomZ(target, 14*FRACUNIT, false);
target->flags = (target->flags & ~MF_NOGRAVITY)|(MF_NOCLIP|MF_NOCLIPTHING);
break;
default:
break;
}
@ -3559,11 +3623,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
else if (inflictor && inflictor->flags & MF_MISSILE)
return false; // Metal Sonic walk through flame !!
else
else if (!player->powers[pw_flashing])
{ // Oh no! Metal Sonic is hit !!
P_ShieldDamage(player, inflictor, source, damage, damagetype);
return true;
}
return false;
}
else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability
{

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)
}
}
if (object->player->pflags & PF_GLIDING)
P_SetPlayerMobjState(object, S_PLAY_FALL);
if ((spring->info->painchance == 3))
{
if (!(pflags = (object->player->pflags & PF_SPINNING)) &&
(((object->player->charability2 == CA2_SPINDASH) && (object->player->cmd.buttons & BT_USE))
|| (spring->flags2 & MF2_AMBUSH)))
{
pflags = PF_SPINNING;
P_SetPlayerMobjState(object, S_PLAY_ROLL);
S_StartSound(object, sfx_spin);
}
else
P_SetPlayerMobjState(object, S_PLAY_ROLL);
}
else
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these.
secondjump = object->player->secondjump;
washoming = object->player->homing;
if (object->player->pflags & PF_GLIDING)
P_SetPlayerMobjState(object, S_PLAY_FALL);
P_ResetPlayer(object->player);
if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities.
@ -368,7 +412,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
object->player->pflags |= P_GetJumpFlags(object->player);
P_SetPlayerMobjState(object, S_PLAY_JUMP);
}
else if ((spring->info->painchance == 2) || (pflags & PF_BOUNCING)) // Adding momentum only.
else if ((spring->info->painchance == 2) || ((spring->info->painchance != 3) && (pflags & PF_BOUNCING))) // Adding momentum only.
{
object->player->pflags |= (pflags &~ PF_STARTJUMP);
object->player->secondjump = secondjump;
@ -382,6 +426,10 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
object->player->pflags |= pflags;
object->player->secondjump = secondjump;
}
else if (object->player->dashmode >= 3*TICRATE)
P_SetPlayerMobjState(object, S_PLAY_DASH);
else if (P_IsObjectOnGround(object) && horizspeed >= FixedMul(object->player->runspeed, object->scale))
P_SetPlayerMobjState(object, S_PLAY_RUN);
else
P_SetPlayerMobjState(object, S_PLAY_WALK);
}
@ -490,6 +538,42 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
}
}
static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera)
{
if (player->powers[pw_carry] && player->powers[pw_carry] != CR_ROLLOUT)
return;
if (ptera->extravalue1 != 1)
return; // Not swooping
if (ptera->target != player->mo)
return; // Not swooping for you!
if (player->spectator)
return;
if ((player->mo->eflags & MFE_VERTICALFLIP) != (ptera->eflags & MFE_VERTICALFLIP))
return; // Both should be in same gravity
if (ptera->eflags & MFE_VERTICALFLIP)
{
if (ptera->ceilingz - (ptera->z + ptera->height) < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return;
}
else if (ptera->z - ptera->floorz < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return; // No room to pick up this guy!
P_ResetPlayer(player);
P_SetTarget(&player->mo->tracer, ptera);
player->pflags &= ~PF_APPLYAUTOBRAKE;
player->powers[pw_carry] = CR_PTERABYTE;
S_StartSound(player->mo, sfx_s3k4a);
P_UnsetThingPosition(player->mo);
player->mo->x = ptera->x;
player->mo->y = ptera->y;
P_SetThingPosition(player->mo);
ptera->movefactor = 3*TICRATE;
ptera->watertop = ptera->waterbottom = ptera->cusval = 0;
}
static void P_DoTailsCarry(player_t *sonic, player_t *tails)
{
INT32 p;
@ -604,6 +688,34 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole)
P_SetTarget(&pole->tracer, NULL);
}
static void P_PlayerBarrelCollide(mobj_t *toucher, mobj_t *barrel)
{
if (toucher->momz < 0)
{
if (toucher->z + toucher->momz > barrel->z + barrel->height)
return;
}
else
{
if (toucher->z > barrel->z + barrel->height)
return;
}
if (toucher->momz > 0)
{
if (toucher->z + toucher->height + toucher->momz < barrel->z)
return;
}
else
{
if (toucher->z + toucher->height < barrel->z)
return;
}
if (P_PlayerCanDamage(toucher->player, barrel))
P_DamageMobj(barrel, toucher, toucher, 1, 0);
}
//
// PIT_CheckThing
//
@ -854,6 +966,15 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
#endif
if (tmthing->type == MT_LAVAFALL_LAVA && (thing->type == MT_RING || thing->type == MT_REDTEAMRING || thing->type == MT_BLUETEAMRING || thing->type == MT_FLINGRING))
{
//height check
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !(thing->health))
return true;
P_KillMobj(thing, tmthing, tmthing, DMG_FIRE);
}
if (tmthing->type == MT_MINECART)
{
//height check
@ -872,12 +993,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOOR && tmthing->player)
{
if (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer) && tmthing->tracer->health)
mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing;
if ((thing->flags & MF2_AMBUSH) || ref != tmthing)
{
fixed_t dx = tmthing->tracer->momx;
fixed_t dy = tmthing->tracer->momy;
fixed_t dm = min(FixedHypot(dx, dy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, dx, dy) - thing->angle;
fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle;
fixed_t s = FINESINE((ang >> ANGLETOFINESHIFT) & FINEMASK);
S_StartSound(tmthing, thing->info->activesound);
thing->extravalue2 += 2*FixedMul(s, dm)/3;
@ -885,40 +1005,72 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
}
if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
{
if ((thing->flags & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
return true;
}
if (thing->type == MT_ROLLOUTROCK && tmthing->player && tmthing->health)
{
if (tmthing->player->powers[pw_carry] == CR_ROLLOUT)
{
return true;
}
if ((thing->flags & MF_PUSHABLE) // not carrying a player
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
&& (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius))
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0)
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
{
thing->flags &= ~MF_PUSHABLE; // prevent riding player from applying pushable movement logic
thing->flags2 &= ~MF2_DONTDRAW; // don't leave the rock invisible if it was flashing prior to boarding
P_SetTarget(&thing->tracer, tmthing);
P_ResetPlayer(tmthing->player);
P_SetPlayerMobjState(tmthing, S_PLAY_WALK);
tmthing->player->powers[pw_carry] = CR_ROLLOUT;
P_SetTarget(&tmthing->tracer, thing);
P_SetObjectMomZ(thing, tmthing->momz, true);
return true;
}
}
else if (tmthing->type == MT_ROLLOUTROCK)
{
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !thing->health)
return true;
if (thing == tmthing->tracer) // don't collide with rider
return true;
if (thing->flags & MF_SPRING) // bounce on springs
{
P_DoSpring(thing, tmthing);
return true;
}
else if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) == (MF_MONITOR|MF_SHOOTABLE) && !(tmthing->flags & MF_PUSHABLE)) // pop monitors while carrying a player
{
P_KillMobj(thing, tmthing, tmthing->tracer, 0);
return true;
}
if (thing->type == tmthing->type // bounce against other rollout rocks
&& (tmthing->momx || tmthing->momy || thing->momx || thing->momy))
{
fixed_t tempmomx = thing->momx, tempmomy = thing->momy;
thing->momx = tmthing->momx;
thing->momy = tmthing->momy;
tmthing->momx = tempmomx;
tmthing->momy = tempmomy;
}
}
if (thing->type == MT_PTERABYTE && tmthing->player)
P_DoPterabyteCarry(tmthing->player, thing);
if (thing->type == MT_TNTBARREL && tmthing->player)
{
if (tmthing->momz < 0)
{
if (tmthing->z + tmthing->momz > thing->z + thing->height)
return true;
}
else
{
if (tmthing->z > thing->z + thing->height)
return true;
}
if (tmthing->momz > 0)
{
if (tmthing->z + tmthing->height + tmthing->momz < thing->z)
return true;
}
else
{
if (tmthing->z + tmthing->height < thing->z)
return true;
}
if ((tmthing->player->pflags & (PF_SPINNING | PF_GLIDING))
|| ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height / 2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|| (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)))
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
}
P_PlayerBarrelCollide(tmthing, thing);
if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE)
{
@ -1560,8 +1712,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
}
if ((!tmthing->player) && (thing->player))
; // no solid thing should ever be able to step up onto a player
if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM) && (thing->player))
; // springs and gas jets should never be able to step up onto a player
// z checking at last
// Treat noclip things as non-solid!
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
@ -1964,7 +2116,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
continue;
}
if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover)))
if (thing->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(thing->player, rover)))
;
else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))
;
@ -2629,8 +2781,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
#ifdef ESLOPE
// HACK TO FIX DSZ2: apply only if slopes are involved
else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
{
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
@ -2645,8 +2796,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
#ifdef ESLOPE
// HACK TO FIX DSZ2: apply only if slopes are involved
else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
{
thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;
@ -3334,13 +3484,13 @@ isblocking:
&& canclimb)
{
slidemo->angle = climbangle;
if (!demoplayback || P_AnalogMove(slidemo->player))
/*if (!demoplayback || P_AnalogMove(slidemo->player))
{
if (slidemo->player == &players[consoleplayer])
localangle = slidemo->angle;
else if (slidemo->player == &players[secondarydisplayplayer])
localangle2 = slidemo->angle;
}
}*/
if (!slidemo->player->climbing)
{
@ -3479,6 +3629,64 @@ stairstep:
goto retry;
}
static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
for (rover = sec->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_SWIMMABLE))
continue;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3)
continue;
if (rover->master->flags & ML_BLOCKMONSTERS)
continue;
topheight =
#ifdef ESLOPE
*rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) :
#endif
*rover->topheight;
if (mo->eflags & MFE_VERTICALFLIP)
{
if (topheight < mo->z - mo->height)
continue;
}
else
{
if (topheight < mo->z)
continue;
}
bottomheight =
#ifdef ESLOPE
*rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) :
#endif
*rover->bottomheight;
if (mo->eflags & MFE_VERTICALFLIP)
{
if (bottomheight > mo->z)
continue;
}
else
{
if (bottomheight > mo->z + mo->height)
continue;
}
P_DamageMobj(mo, NULL, NULL, 1, DMG_FIRE);
return;
}
}
//
// P_SlideMove
// The momx / momy move is bad, so try to slide
@ -3639,6 +3847,12 @@ retry:
P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy,
PT_ADDLINES, PTR_SlideTraverse);
if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff)
{
sector_t *sec = P_PointOnLineSide(mo->x, mo->y, bestslideline) ? bestslideline->frontsector : bestslideline->backsector;
P_CheckLavaWall(mo, sec);
}
// Some walls are bouncy even if you're not
if (bestslideline && bestslideline->flags & ML_BOUNCY)
{

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)

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