mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-31 13:40:45 +00:00
Merge remote-tracking branch 'origin/master' into renderswitch
This commit is contained in:
commit
c6253bb6f9
138 changed files with 19816 additions and 4193 deletions
|
@ -13,11 +13,10 @@ set(SRB2_ASSET_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/installer"
|
|||
CACHE STRING "Path to directory that contains all asset files for the installer.")
|
||||
|
||||
set(SRB2_ASSET_HASHED
|
||||
"srb2.srb;\
|
||||
"srb2.pk3;\
|
||||
player.dta;\
|
||||
rings.dta;\
|
||||
zones.dta;\
|
||||
patch.dta"
|
||||
zones.pk3;\
|
||||
patch.pk3"
|
||||
CACHE STRING "Asset filenames to apply MD5 checks. No spaces between entries!"
|
||||
)
|
||||
|
||||
|
|
6482
extras/conf/SRB2-22.cfg
Normal file
6482
extras/conf/SRB2-22.cfg
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
# libopenmpt mingw-w64 binary info
|
||||
|
||||
Current built version as of 2019/05/23 is 0.4.4+r11531.pkg
|
||||
Current built version as of 2019/09/27 is 0.4.7+r12088.pkg
|
||||
|
||||
* mingw binaries (.dll): `bin/[x86 or x86_64]/mingw`
|
||||
* mingw import libraries (.dll.a): `lib/[x86 or x86_64]/mingw`
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,6 +5,44 @@ Changelog {#changelog}
|
|||
For fully detailed change log, please see the source repository directly. This
|
||||
is just a high-level summary.
|
||||
|
||||
### libopenmpt 0.4.7 (2019-09-23)
|
||||
|
||||
* [**Bug**] Compilation fix for various platforms that do not provide
|
||||
`std::aligned_alloc` in C++17 mode. The problematic dependency has been
|
||||
removed. This should fix build problems on MinGW, OpenBSD, Haiku, and others
|
||||
for good.
|
||||
|
||||
* J2B: Ignore notes with non-existing instrument (fixes Ending.j2b).
|
||||
|
||||
* mpg123: Update to v1.25.13 (2019-08-24).
|
||||
* ogg: Update to v1.3.4. (2019-08-31).
|
||||
* flac: Update to v1.3.3. (2019-08-04).
|
||||
|
||||
### libopenmpt 0.4.6 (2019-08-10)
|
||||
|
||||
* [**Bug**] Compilation fix for OpenBSD.
|
||||
* [**Bug**] Compilation fix for NO_PLUGINS being defined.
|
||||
|
||||
* in_openmpt: Correct documentation. `openmpt-mpg123.dll` must be placed into
|
||||
the Winamp directory.
|
||||
|
||||
* Detect IT files unpacked with early UNMO3 versions.
|
||||
|
||||
* mpg123: Update to v1.25.11 (2019-07-18).
|
||||
* minimp3: Update to commit 977514a6dfc4960d819a103f43b358e58ac6c28f
|
||||
(2019-07-24).
|
||||
* miniz: Update to v2.1.0 (2019-05-05).
|
||||
* stb_vorbis: Update to v1.17 (2019-08-09).
|
||||
|
||||
### libopenmpt 0.4.5 (2019-05-27)
|
||||
|
||||
* [**Sec**] Possible crash during playback due out-of-bounds read in XM and
|
||||
MT2 files (r11608).
|
||||
|
||||
* Breaking out of a sustain loop through Note-Off sometimes didn't continue in
|
||||
the regular sample loop.
|
||||
* Seeking did not stop notes playing with XM Key Off (Kxx) effect.
|
||||
|
||||
### libopenmpt 0.4.4 (2019-04-07)
|
||||
|
||||
* [**Bug**] Channel VU meters were swapped.
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
/*! \brief libopenmpt minor version number */
|
||||
#define OPENMPT_API_VERSION_MINOR 4
|
||||
/*! \brief libopenmpt patch version number */
|
||||
#define OPENMPT_API_VERSION_PATCH 4
|
||||
#define OPENMPT_API_VERSION_PATCH 7
|
||||
/*! \brief libopenmpt pre-release tag */
|
||||
#define OPENMPT_API_VERSION_PREREL ""
|
||||
/*! \brief libopenmpt pre-release flag */
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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
|
||||
|
|
28
src/Makefile
28
src/Makefile
|
@ -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
|
||||
|
|
14
src/b_bot.c
14
src/b_bot.c
|
@ -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;
|
||||
}
|
||||
|
|
246
src/command.c
246
src/command.c
|
@ -49,6 +49,7 @@ static void COM_Exec_f(void);
|
|||
static void COM_Wait_f(void);
|
||||
static void COM_Help_f(void);
|
||||
static void COM_Toggle_f(void);
|
||||
static void COM_Add_f(void);
|
||||
|
||||
static void CV_EnforceExecVersion(void);
|
||||
static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr);
|
||||
|
@ -291,6 +292,7 @@ void COM_Init(void)
|
|||
COM_AddCommand("wait", COM_Wait_f);
|
||||
COM_AddCommand("help", COM_Help_f);
|
||||
COM_AddCommand("toggle", COM_Toggle_f);
|
||||
COM_AddCommand("add", COM_Add_f);
|
||||
RegisterNetXCmd(XD_NETVAR, Got_NetVar);
|
||||
}
|
||||
|
||||
|
@ -709,15 +711,21 @@ static void COM_Help_f(void)
|
|||
|
||||
if (COM_Argc() > 1)
|
||||
{
|
||||
cvar = CV_FindVar(COM_Argv(1));
|
||||
const char *help = COM_Argv(1);
|
||||
cvar = CV_FindVar(help);
|
||||
if (cvar)
|
||||
{
|
||||
CONS_Printf(M_GetText("Variable %s:\n"), cvar->name);
|
||||
boolean floatmode = false;
|
||||
const char *cvalue = NULL;
|
||||
CONS_Printf("\x82""Variable %s:\n", cvar->name);
|
||||
CONS_Printf(M_GetText(" flags :"));
|
||||
if (cvar->flags & CV_SAVE)
|
||||
CONS_Printf("AUTOSAVE ");
|
||||
if (cvar->flags & CV_FLOAT)
|
||||
{
|
||||
CONS_Printf("FLOAT ");
|
||||
floatmode = true;
|
||||
}
|
||||
if (cvar->flags & CV_NETVAR)
|
||||
CONS_Printf("NETVAR ");
|
||||
if (cvar->flags & CV_CALL)
|
||||
|
@ -727,59 +735,113 @@ static void COM_Help_f(void)
|
|||
CONS_Printf("\n");
|
||||
if (cvar->PossibleValue)
|
||||
{
|
||||
if (stricmp(cvar->PossibleValue[0].strvalue, "MIN") == 0)
|
||||
{
|
||||
for (i = 1; cvar->PossibleValue[i].strvalue != NULL; i++)
|
||||
if (!stricmp(cvar->PossibleValue[i].strvalue, "MAX"))
|
||||
break;
|
||||
CONS_Printf(M_GetText(" range from %d to %d\n"), cvar->PossibleValue[0].value,
|
||||
cvar->PossibleValue[i].value);
|
||||
CONS_Printf(M_GetText(" Current value: %d\n"), cvar->value);
|
||||
}
|
||||
CONS_Printf(" Possible values:\n");
|
||||
if (cvar->PossibleValue == CV_YesNo)
|
||||
CONS_Printf(" Yes or No (On or Off, 1 or 0)\n");
|
||||
else if (cvar->PossibleValue == CV_OnOff)
|
||||
CONS_Printf(" On or Off (Yes or No, 1 or 0)\n");
|
||||
else
|
||||
{
|
||||
const char *cvalue = NULL;
|
||||
CONS_Printf(M_GetText(" possible value : %s\n"), cvar->name);
|
||||
#define MINVAL 0
|
||||
#define MAXVAL 1
|
||||
if (!stricmp(cvar->PossibleValue[MINVAL].strvalue, "MIN"))
|
||||
{
|
||||
if (floatmode)
|
||||
CONS_Printf(" range from %f to %f\n", FIXED_TO_FLOAT(cvar->PossibleValue[MINVAL].value),
|
||||
FIXED_TO_FLOAT(cvar->PossibleValue[MAXVAL].value));
|
||||
else
|
||||
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[MINVAL].value,
|
||||
cvar->PossibleValue[MAXVAL].value);
|
||||
i = MAXVAL+1;
|
||||
}
|
||||
#undef MINVAL
|
||||
#undef MAXVAL
|
||||
|
||||
//CONS_Printf(M_GetText(" possible value : %s\n"), cvar->name);
|
||||
while (cvar->PossibleValue[i].strvalue)
|
||||
{
|
||||
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
if (floatmode)
|
||||
CONS_Printf(" %-2f : %s\n", FIXED_TO_FLOAT(cvar->PossibleValue[i].value),
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
else
|
||||
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
|
||||
cvar->PossibleValue[i].strvalue);
|
||||
if (cvar->PossibleValue[i].value == cvar->value)
|
||||
cvalue = cvar->PossibleValue[i].strvalue;
|
||||
i++;
|
||||
}
|
||||
if (cvalue)
|
||||
CONS_Printf(M_GetText(" Current value: %s\n"), cvalue);
|
||||
else
|
||||
CONS_Printf(M_GetText(" Current value: %d\n"), cvar->value);
|
||||
}
|
||||
}
|
||||
|
||||
if (cvalue)
|
||||
CONS_Printf(" Current value: %s\n", cvalue);
|
||||
else if (cvar->string)
|
||||
CONS_Printf(" Current value: %s\n", cvar->string);
|
||||
else
|
||||
CONS_Printf(M_GetText(" Current value: %d\n"), cvar->value);
|
||||
CONS_Printf(" Current value: %d\n", cvar->value);
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("No help for this command/variable\n"));
|
||||
{
|
||||
for (cmd = com_commands; cmd; cmd = cmd->next)
|
||||
{
|
||||
if (strcmp(cmd->name, help))
|
||||
continue;
|
||||
|
||||
CONS_Printf("\x82""Command %s:\n", cmd->name);
|
||||
CONS_Printf(" help is not available for commands");
|
||||
CONS_Printf("\x82""\nCheck wiki.srb2.org for more or try typing <name> without arguments\n");
|
||||
return;
|
||||
}
|
||||
|
||||
CONS_Printf("No exact match, searching...\n");
|
||||
|
||||
// variables
|
||||
CONS_Printf("\x82""Variables:\n");
|
||||
for (cvar = consvar_vars; cvar; cvar = cvar->next)
|
||||
{
|
||||
if ((cvar->flags & CV_NOSHOWHELP) || (!strstr(cvar->name, help)))
|
||||
continue;
|
||||
CONS_Printf("%s ", cvar->name);
|
||||
i++;
|
||||
}
|
||||
|
||||
// commands
|
||||
CONS_Printf("\x82""\nCommands:\n");
|
||||
for (cmd = com_commands; cmd; cmd = cmd->next)
|
||||
{
|
||||
if (!strstr(cmd->name, help))
|
||||
continue;
|
||||
CONS_Printf("%s ",cmd->name);
|
||||
i++;
|
||||
}
|
||||
|
||||
CONS_Printf("\x82""\nCheck wiki.srb2.org for more or type help <command or variable>\n");
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "\x87Total : %d\n", i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// variables
|
||||
CONS_Printf("\x82""Variables:\n");
|
||||
for (cvar = consvar_vars; cvar; cvar = cvar->next)
|
||||
{
|
||||
if (cvar->flags & CV_NOSHOWHELP)
|
||||
continue;
|
||||
CONS_Printf("%s ", cvar->name);
|
||||
i++;
|
||||
}
|
||||
|
||||
// commands
|
||||
CONS_Printf("\x82%s", M_GetText("Commands\n"));
|
||||
CONS_Printf("\x82""\nCommands:\n");
|
||||
for (cmd = com_commands; cmd; cmd = cmd->next)
|
||||
{
|
||||
CONS_Printf("%s ",cmd->name);
|
||||
i++;
|
||||
}
|
||||
|
||||
// variables
|
||||
CONS_Printf("\n\x82%s", M_GetText("Variables\n"));
|
||||
for (cvar = consvar_vars; cvar; cvar = cvar->next)
|
||||
{
|
||||
if (!(cvar->flags & CV_NOSHOWHELP))
|
||||
CONS_Printf("%s ", cvar->name);
|
||||
i++;
|
||||
}
|
||||
|
||||
CONS_Printf("\n\x82%s", M_GetText("Read help file for more or type help <command or variable>\n"));
|
||||
CONS_Printf("\x82""\nCheck wiki.srb2.org for more or type help <command or variable>\n");
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "\x82Total : %d\n", i);
|
||||
}
|
||||
|
@ -816,6 +878,30 @@ static void COM_Toggle_f(void)
|
|||
CV_AddValue(cvar, +1);
|
||||
}
|
||||
|
||||
/** Command variant of CV_AddValue
|
||||
*/
|
||||
static void COM_Add_f(void)
|
||||
{
|
||||
consvar_t *cvar;
|
||||
|
||||
if (COM_Argc() != 3)
|
||||
{
|
||||
CONS_Printf(M_GetText("Add <cvar_name> <value>: Add to the value of a cvar. Negative values work too!\n"));
|
||||
return;
|
||||
}
|
||||
cvar = CV_FindVar(COM_Argv(1));
|
||||
if (!cvar)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("%s is not a cvar\n"), COM_Argv(1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (( cvar->flags & CV_FLOAT ))
|
||||
CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
|
||||
else
|
||||
CV_AddValue(cvar, atoi(COM_Argv(2)));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// VARIABLE SIZE BUFFERS
|
||||
// =========================================================================
|
||||
|
@ -1123,32 +1209,42 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
|
|||
|
||||
if (var->PossibleValue[0].strvalue && !stricmp(var->PossibleValue[0].strvalue, "MIN")) // bounded cvar
|
||||
{
|
||||
#define MINVAL 0
|
||||
#define MAXVAL 1
|
||||
INT32 i;
|
||||
// search for maximum
|
||||
for (i = 1; var->PossibleValue[i].strvalue; i++)
|
||||
if (!stricmp(var->PossibleValue[i].strvalue, "MAX"))
|
||||
break;
|
||||
#ifdef PARANOIA
|
||||
if (!var->PossibleValue[i].strvalue)
|
||||
if (!var->PossibleValue[MAXVAL].strvalue)
|
||||
I_Error("Bounded cvar \"%s\" without maximum!\n", var->name);
|
||||
#endif
|
||||
|
||||
if ((v != INT32_MIN && v < var->PossibleValue[0].value) || !stricmp(valstr, "MIN"))
|
||||
// search for other
|
||||
for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++)
|
||||
if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr))
|
||||
{
|
||||
var->value = var->PossibleValue[i].value;
|
||||
var->string = var->PossibleValue[i].strvalue;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
if ((v != INT32_MIN && v < var->PossibleValue[MINVAL].value) || !stricmp(valstr, "MIN"))
|
||||
{
|
||||
v = var->PossibleValue[0].value;
|
||||
valstr = var->PossibleValue[0].strvalue;
|
||||
v = var->PossibleValue[MINVAL].value;
|
||||
valstr = var->PossibleValue[MINVAL].strvalue;
|
||||
override = true;
|
||||
overrideval = v;
|
||||
}
|
||||
else if ((v != INT32_MIN && v > var->PossibleValue[i].value) || !stricmp(valstr, "MAX"))
|
||||
else if ((v != INT32_MIN && v > var->PossibleValue[MAXVAL].value) || !stricmp(valstr, "MAX"))
|
||||
{
|
||||
v = var->PossibleValue[i].value;
|
||||
valstr = var->PossibleValue[i].strvalue;
|
||||
v = var->PossibleValue[MAXVAL].value;
|
||||
valstr = var->PossibleValue[MAXVAL].strvalue;
|
||||
override = true;
|
||||
overrideval = v;
|
||||
}
|
||||
if (v == INT32_MIN)
|
||||
goto badinput;
|
||||
#undef MINVAL
|
||||
#undef MAXVAL
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1515,6 +1611,9 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
{
|
||||
INT32 newvalue, max;
|
||||
|
||||
if (!increment)
|
||||
return;
|
||||
|
||||
// count pointlimit better
|
||||
if (var == &cv_pointlimit && (gametype == GT_MATCH))
|
||||
increment *= 50;
|
||||
|
@ -1538,13 +1637,11 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
|
||||
if (var->PossibleValue)
|
||||
{
|
||||
#define MINVAL 0
|
||||
if (var == &cv_nextmap)
|
||||
{
|
||||
// Special case for the nextmap variable, used only directly from the menu
|
||||
INT32 oldvalue = var->value - 1, gt;
|
||||
gt = cv_newgametype.value;
|
||||
if (increment != 0) // Going up!
|
||||
{
|
||||
newvalue = var->value - 1;
|
||||
do
|
||||
|
@ -1575,21 +1672,58 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
return;
|
||||
}
|
||||
}
|
||||
#define MINVAL 0
|
||||
#define MAXVAL 1
|
||||
else if (var->PossibleValue[MINVAL].strvalue && !strcmp(var->PossibleValue[MINVAL].strvalue, "MIN"))
|
||||
{
|
||||
// search the next to last
|
||||
for (max = 0; var->PossibleValue[max+1].strvalue; max++)
|
||||
;
|
||||
#ifdef PARANOIA
|
||||
if (!var->PossibleValue[MAXVAL].strvalue)
|
||||
I_Error("Bounded cvar \"%s\" without maximum!\n", var->name);
|
||||
#endif
|
||||
|
||||
if (newvalue < var->PossibleValue[MINVAL].value) // add the max+1
|
||||
newvalue += var->PossibleValue[max].value - var->PossibleValue[MINVAL].value + 1;
|
||||
if (newvalue < var->PossibleValue[MINVAL].value || newvalue > var->PossibleValue[MAXVAL].value)
|
||||
{
|
||||
INT32 currentindice = -1, newindice;
|
||||
for (max = MAXVAL+1; var->PossibleValue[max].strvalue; max++)
|
||||
{
|
||||
if (var->PossibleValue[max].value == newvalue)
|
||||
{
|
||||
increment = 0;
|
||||
currentindice = max;
|
||||
}
|
||||
else if (var->PossibleValue[max].value == var->value)
|
||||
currentindice = max;
|
||||
}
|
||||
|
||||
newvalue = var->PossibleValue[MINVAL].value + (newvalue - var->PossibleValue[MINVAL].value)
|
||||
% (var->PossibleValue[max].value - var->PossibleValue[MINVAL].value + 1);
|
||||
if (increment)
|
||||
{
|
||||
increment = (increment > 0) ? 1 : -1;
|
||||
if (currentindice == -1 && max != MAXVAL+1)
|
||||
newindice = ((increment > 0) ? MAXVAL : max) + increment;
|
||||
else
|
||||
newindice = currentindice + increment;
|
||||
|
||||
CV_SetValue(var, newvalue);
|
||||
#undef MINVAL
|
||||
if (newindice >= max || newindice <= MAXVAL)
|
||||
{
|
||||
if (var == &cv_pointlimit && (gametype == GT_MATCH) && increment > 0)
|
||||
CV_SetValue(var, 50);
|
||||
else
|
||||
{
|
||||
newvalue = var->PossibleValue[((increment > 0) ? MINVAL : MAXVAL)].value;
|
||||
CV_SetValue(var, newvalue);
|
||||
}
|
||||
}
|
||||
else
|
||||
CV_Set(var, var->PossibleValue[newindice].strvalue);
|
||||
}
|
||||
else
|
||||
CV_Set(var, var->PossibleValue[currentindice].strvalue);
|
||||
}
|
||||
else
|
||||
CV_SetValue(var, newvalue);
|
||||
}
|
||||
#undef MINVAL
|
||||
#undef MAXVAL
|
||||
else
|
||||
{
|
||||
INT32 currentindice = -1, newindice;
|
||||
|
@ -1599,8 +1733,6 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
if (var->PossibleValue[max].value == var->value)
|
||||
currentindice = max;
|
||||
|
||||
max--;
|
||||
|
||||
if (var == &cv_chooseskin)
|
||||
{
|
||||
// Special case for the chooseskin variable, used only directly from the menu
|
||||
|
@ -1632,7 +1764,7 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
var->value);
|
||||
#endif
|
||||
|
||||
newindice = (currentindice + increment + max + 1) % (max+1);
|
||||
newindice = (currentindice + increment + max) % max;
|
||||
CV_Set(var, var->PossibleValue[newindice].strvalue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
114
src/d_clisrv.c
114
src/d_clisrv.c
|
@ -83,11 +83,9 @@ tic_t jointimeout = (10*TICRATE);
|
|||
static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
|
||||
static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
|
||||
|
||||
#ifdef NEWPING
|
||||
UINT16 pingmeasurecount = 1;
|
||||
UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone.
|
||||
UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values.
|
||||
#endif
|
||||
SINT8 nodetoplayer[MAXNETNODES];
|
||||
SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
|
||||
UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen
|
||||
|
@ -621,6 +619,10 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
|
|||
rsp->friction = LONG(players[i].mo->friction);
|
||||
rsp->movefactor = LONG(players[i].mo->movefactor);
|
||||
|
||||
rsp->sprite = (spritenum_t)LONG(players[i].mo->sprite);
|
||||
rsp->frame = LONG(players[i].mo->frame);
|
||||
rsp->sprite2 = players[i].mo->sprite2;
|
||||
rsp->anim_duration = SHORT(players[i].mo->anim_duration);
|
||||
rsp->tics = LONG(players[i].mo->tics);
|
||||
rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :(
|
||||
rsp->eflags = (UINT16)SHORT(players[i].mo->eflags);
|
||||
|
@ -767,8 +769,17 @@ static void resynch_read_player(resynch_pak *rsp)
|
|||
players[i].mo->momy = LONG(rsp->momy);
|
||||
players[i].mo->momz = LONG(rsp->momz);
|
||||
players[i].mo->movefactor = LONG(rsp->movefactor);
|
||||
|
||||
// Don't use P_SetMobjStateNF to restore state, write/read all the values manually!
|
||||
// This should stop those stupid console errors, hopefully.
|
||||
// -- Monster Iestyn
|
||||
players[i].mo->sprite = (spritenum_t)LONG(rsp->sprite);
|
||||
players[i].mo->frame = LONG(rsp->frame);
|
||||
players[i].mo->sprite2 = rsp->sprite2;
|
||||
players[i].mo->anim_duration = SHORT(rsp->anim_duration);
|
||||
players[i].mo->tics = LONG(rsp->tics);
|
||||
P_SetMobjStateNF(players[i].mo, LONG(rsp->statenum));
|
||||
players[i].mo->state = &states[LONG(rsp->statenum)];
|
||||
|
||||
players[i].mo->x = LONG(rsp->x);
|
||||
players[i].mo->y = LONG(rsp->y);
|
||||
players[i].mo->z = LONG(rsp->z);
|
||||
|
@ -1253,7 +1264,8 @@ static boolean CL_SendJoin(void)
|
|||
netbuffer->u.clientcfg.localplayers = localplayers;
|
||||
netbuffer->u.clientcfg.version = VERSION;
|
||||
netbuffer->u.clientcfg.subversion = SUBVERSION;
|
||||
|
||||
strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME);
|
||||
strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME);
|
||||
return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
|
||||
}
|
||||
|
||||
|
@ -1312,33 +1324,13 @@ static void SV_SendPlayerInfo(INT32 node)
|
|||
continue;
|
||||
}
|
||||
|
||||
netbuffer->u.playerinfo[i].node = (UINT8)playernode[i];
|
||||
netbuffer->u.playerinfo[i].node = i;
|
||||
strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1);
|
||||
netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0';
|
||||
|
||||
//fetch IP address
|
||||
{
|
||||
const char *claddress;
|
||||
UINT32 numericaddress[4];
|
||||
|
||||
memset(netbuffer->u.playerinfo[i].address, 0, 4);
|
||||
if (playernode[i] == 0)
|
||||
{
|
||||
//127.0.0.1
|
||||
netbuffer->u.playerinfo[i].address[0] = 127;
|
||||
netbuffer->u.playerinfo[i].address[3] = 1;
|
||||
}
|
||||
else if (playernode[i] > 0 && I_GetNodeAddress && (claddress = I_GetNodeAddress(playernode[i])) != NULL)
|
||||
{
|
||||
if (sscanf(claddress, "%d.%d.%d.%d", &numericaddress[0], &numericaddress[1], &numericaddress[2], &numericaddress[3]) < 4)
|
||||
goto badaddress;
|
||||
netbuffer->u.playerinfo[i].address[0] = (UINT8)numericaddress[0];
|
||||
netbuffer->u.playerinfo[i].address[1] = (UINT8)numericaddress[1];
|
||||
netbuffer->u.playerinfo[i].address[2] = (UINT8)numericaddress[2];
|
||||
netbuffer->u.playerinfo[i].address[3] = (UINT8)numericaddress[3];
|
||||
}
|
||||
}
|
||||
badaddress:
|
||||
//No, don't do that, you fuckface.
|
||||
memset(netbuffer->u.playerinfo[i].address, 0, 4);
|
||||
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
|
@ -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)
|
||||
D_StartTitle();
|
||||
{
|
||||
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;
|
||||
|
@ -4853,8 +4860,13 @@ void NetUpdate(void)
|
|||
for (i = 0; i < MAXNETNODES; ++i)
|
||||
if (resynch_inprogress[i])
|
||||
{
|
||||
SV_SendResynch(i);
|
||||
counts = -666;
|
||||
if (!nodeingame[i] || nettics[i] == gametic)
|
||||
{
|
||||
SV_SendResynch(i);
|
||||
counts = -666;
|
||||
}
|
||||
else
|
||||
counts = 0; // Let the client catch up with the server
|
||||
}
|
||||
|
||||
// Do not make tics while resynching
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
187
src/d_main.c
187
src/d_main.c
|
@ -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 */
|
||||
F_TitleScreenDrawer();
|
||||
break;
|
||||
case GS_LEVEL:
|
||||
if (!gametic)
|
||||
break;
|
||||
|
@ -392,75 +396,26 @@ 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();
|
||||
ST_Drawer();
|
||||
F_TextPromptDrawer();
|
||||
HU_Drawer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,24 +1314,40 @@ void D_SRB2Main(void)
|
|||
sound_disabled = true;
|
||||
midi_disabled = digital_disabled = true;
|
||||
}
|
||||
if (M_CheckParm("-noaudio")) // combines -nosound and -nomusic
|
||||
{
|
||||
sound_disabled = true;
|
||||
digital_disabled = true;
|
||||
midi_disabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (M_CheckParm("-nosound"))
|
||||
sound_disabled = true;
|
||||
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
|
||||
{
|
||||
digital_disabled = true;
|
||||
midi_disabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (M_CheckParm("-nomidimusic"))
|
||||
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
|
||||
if (M_CheckParm("-nodigmusic"))
|
||||
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
|
||||
}
|
||||
}
|
||||
if (!( sound_disabled && digital_disabled
|
||||
#ifndef NO_MIDI
|
||||
&& midi_disabled
|
||||
#endif
|
||||
))
|
||||
{
|
||||
CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
|
||||
I_StartupSound();
|
||||
I_InitMusic();
|
||||
S_InitSfxChannels(cv_soundvolume.value);
|
||||
}
|
||||
if (M_CheckParm("-nosound"))
|
||||
sound_disabled = true;
|
||||
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
|
||||
midi_disabled = digital_disabled = true;
|
||||
else
|
||||
{
|
||||
if (M_CheckParm("-nomidimusic"))
|
||||
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
|
||||
if (M_CheckParm("-nodigmusic"))
|
||||
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
|
||||
}
|
||||
I_StartupSound();
|
||||
I_InitMusic();
|
||||
S_InitSfxChannels(cv_soundvolume.value);
|
||||
|
||||
CONS_Printf("ST_Init(): Init status bar.\n");
|
||||
ST_Init();
|
||||
|
|
|
@ -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__
|
||||
|
|
125
src/d_net.c
125
src/d_net.c
|
@ -185,22 +185,10 @@ typedef struct
|
|||
UINT8 nextacknum;
|
||||
|
||||
UINT8 flags;
|
||||
#ifndef NEWPING
|
||||
// jacobson tcp timeout evaluation algorithm (Karn variation)
|
||||
fixed_t ping;
|
||||
fixed_t varping;
|
||||
INT32 timeout; // computed with ping and varping
|
||||
#endif
|
||||
} node_t;
|
||||
|
||||
static node_t nodes[MAXNETNODES];
|
||||
#ifndef NEWPING
|
||||
#define PINGDEFAULT ((200*TICRATE*FRACUNIT)/1000)
|
||||
#define VARPINGDEFAULT ((50*TICRATE*FRACUNIT)/1000)
|
||||
#define TIMEOUT(p,v) (p+4*v+FRACUNIT/2)>>FRACBITS;
|
||||
#else
|
||||
#define NODETIMEOUT 14 //What the above boiled down to...
|
||||
#endif
|
||||
#define NODETIMEOUT 14
|
||||
|
||||
#ifndef NONET
|
||||
// return <0 if a < b (mod 256)
|
||||
|
@ -320,19 +308,7 @@ static UINT8 GetAcktosend(INT32 node)
|
|||
static void RemoveAck(INT32 i)
|
||||
{
|
||||
INT32 node = ackpak[i].destinationnode;
|
||||
#ifndef NEWPING
|
||||
fixed_t trueping = (I_GetTime() - ackpak[i].senttime)<<FRACBITS;
|
||||
if (ackpak[i].resentnum)
|
||||
{
|
||||
// +FRACUNIT/2 for round
|
||||
nodes[node].ping = (nodes[node].ping*7 + trueping)/8;
|
||||
nodes[node].varping = (nodes[node].varping*7 + abs(nodes[node].ping-trueping))/8;
|
||||
nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping);
|
||||
}
|
||||
DEBFILE(va("Remove ack %d trueping %d ping %f var %f timeout %d\n",ackpak[i].acknum,trueping>>FRACBITS,(double)FIXED_TO_FLOAT(nodes[node].ping),(double)FIXED_TO_FLOAT(nodes[node].varping),nodes[node].timeout));
|
||||
#else
|
||||
DEBFILE(va("Remove ack %d\n",ackpak[i].acknum));
|
||||
#endif
|
||||
ackpak[i].acknum = 0;
|
||||
if (nodes[node].flags & NF_CLOSE)
|
||||
Net_CloseConnection(node);
|
||||
|
@ -519,11 +495,7 @@ void Net_AckTicker(void)
|
|||
{
|
||||
const INT32 nodei = ackpak[i].destinationnode;
|
||||
node_t *node = &nodes[nodei];
|
||||
#ifdef NEWPING
|
||||
if (ackpak[i].acknum && ackpak[i].senttime + NODETIMEOUT < I_GetTime())
|
||||
#else
|
||||
if (ackpak[i].acknum && ackpak[i].senttime + node->timeout < I_GetTime())
|
||||
#endif
|
||||
{
|
||||
if (ackpak[i].resentnum > 10 && (node->flags & NF_CLOSE))
|
||||
{
|
||||
|
@ -534,13 +506,8 @@ void Net_AckTicker(void)
|
|||
ackpak[i].acknum = 0;
|
||||
continue;
|
||||
}
|
||||
#ifdef NEWPING
|
||||
DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
|
||||
NODETIMEOUT, I_GetTime()));
|
||||
#else
|
||||
DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
|
||||
node->timeout, I_GetTime()));
|
||||
#endif
|
||||
M_Memcpy(netbuffer, ackpak[i].pak.raw, ackpak[i].length);
|
||||
ackpak[i].senttime = I_GetTime();
|
||||
ackpak[i].resentnum++;
|
||||
|
@ -658,11 +625,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
|
|||
static void InitNode(node_t *node)
|
||||
{
|
||||
node->acktosend_head = node->acktosend_tail = 0;
|
||||
#ifndef NEWPING
|
||||
node->ping = PINGDEFAULT;
|
||||
node->varping = VARPINGDEFAULT;
|
||||
node->timeout = TIMEOUT(node->ping, node->varping);
|
||||
#endif
|
||||
node->firstacktosend = 0;
|
||||
node->nextacknum = 1;
|
||||
node->remotefirstack = 0;
|
||||
|
@ -843,9 +805,7 @@ static const char *packettypename[NUMPACKETTYPE] =
|
|||
"CLIENTJOIN",
|
||||
"NODETIMEOUT",
|
||||
"RESYNCHING",
|
||||
#ifdef NEWPING
|
||||
"PING"
|
||||
#endif
|
||||
};
|
||||
|
||||
static void DebugPrintpacket(const char *header)
|
||||
|
@ -1384,30 +1344,73 @@ boolean D_CheckNetGame(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct pingcell
|
||||
{
|
||||
INT32 num;
|
||||
INT32 ms;
|
||||
};
|
||||
|
||||
static int pingcellcmp(const void *va, const void *vb)
|
||||
{
|
||||
const struct pingcell *a, *b;
|
||||
a = va;
|
||||
b = vb;
|
||||
return ( a->ms - b->ms );
|
||||
}
|
||||
|
||||
/*
|
||||
New ping command formatted nicely to present ping in
|
||||
ascending order. And with equally spaced columns.
|
||||
The caller's ping is presented at the bottom too, for
|
||||
convenience.
|
||||
*/
|
||||
|
||||
void Command_Ping_f(void)
|
||||
{
|
||||
#ifndef NEWPING
|
||||
if(server)
|
||||
struct pingcell pingv[MAXPLAYERS];
|
||||
INT32 pingc;
|
||||
|
||||
int name_width = 0;
|
||||
int ms_width = 0;
|
||||
|
||||
int n;
|
||||
INT32 i;
|
||||
|
||||
pingc = 0;
|
||||
for (i = 1; i < MAXPLAYERS; ++i)
|
||||
if (playeringame[i])
|
||||
{
|
||||
#endif
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS;i++)
|
||||
{
|
||||
#ifndef NEWPING
|
||||
const INT32 node = playernode[i];
|
||||
if (playeringame[i] && node != 0)
|
||||
CONS_Printf(M_GetText("%.2d : %s\n %d tics, %d ms.\n"), i, player_names[i],
|
||||
GetLag(node), G_TicsToMilliseconds(GetLag(node)));
|
||||
#else
|
||||
if (playeringame[i] && i != 0)
|
||||
CONS_Printf(M_GetText("%.2d : %s\n %d ms\n"), i, player_names[i], playerpingtable[i]);
|
||||
#endif
|
||||
}
|
||||
#ifndef NEWPING
|
||||
n = strlen(player_names[i]);
|
||||
if (n > name_width)
|
||||
name_width = n;
|
||||
|
||||
n = playerpingtable[i];
|
||||
if (n > ms_width)
|
||||
ms_width = n;
|
||||
|
||||
pingv[pingc].num = i;
|
||||
pingv[pingc].ms = playerpingtable[i];
|
||||
pingc++;
|
||||
}
|
||||
|
||||
if (ms_width < 10) ms_width = 1;
|
||||
else if (ms_width < 100) ms_width = 2;
|
||||
else ms_width = 3;
|
||||
|
||||
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
|
||||
|
||||
for (i = 0; i < pingc; ++i)
|
||||
{
|
||||
CONS_Printf("%02d : %-*s %*d ms\n",
|
||||
pingv[i].num,
|
||||
name_width, player_names[pingv[i].num],
|
||||
ms_width, pingv[i].ms);
|
||||
}
|
||||
|
||||
if (!server && playeringame[consoleplayer])
|
||||
{
|
||||
CONS_Printf("\nYour ping is %d ms\n", playerpingtable[consoleplayer]);
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("Only the server can use this.\n"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void D_CloseConnection(void)
|
||||
|
|
139
src/d_netcmd.c
139
src/d_netcmd.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -752,11 +752,9 @@ void Got_Filetxpak(void)
|
|||
nameonly(filename);
|
||||
|
||||
if (!(strcmp(filename, "srb2.pk3")
|
||||
&& strcmp(filename, "srb2.srb")
|
||||
&& strcmp(filename, "srb2.wad")
|
||||
&& strcmp(filename, "zones.dta")
|
||||
&& strcmp(filename, "zones.pk3")
|
||||
&& strcmp(filename, "player.dta")
|
||||
&& strcmp(filename, "patch.dta")
|
||||
&& strcmp(filename, "patch.pk3")
|
||||
&& strcmp(filename, "music.dta")
|
||||
))
|
||||
I_Error("Tried to download \"%s\"", filename);
|
||||
|
|
|
@ -234,7 +234,9 @@ typedef enum
|
|||
CR_ZOOMTUBE,
|
||||
CR_ROPEHANG,
|
||||
CR_MACESPIN,
|
||||
CR_MINECART
|
||||
CR_MINECART,
|
||||
CR_ROLLOUT,
|
||||
CR_PTERABYTE
|
||||
} carrytype_t; // pw_carry
|
||||
|
||||
// Player powers. (don't edit this comment)
|
||||
|
@ -250,6 +252,8 @@ typedef enum
|
|||
pw_spacetime, // In space, no one can hear you spin!
|
||||
pw_extralife, // Extra Life timer
|
||||
pw_pushing,
|
||||
pw_justsprung,
|
||||
pw_noautobrake,
|
||||
|
||||
pw_super, // Are you super?
|
||||
pw_gravityboots, // gravity boots
|
||||
|
@ -509,6 +513,10 @@ typedef struct player_s
|
|||
#endif
|
||||
} player_t;
|
||||
|
||||
// Values for dashmode
|
||||
#define DASHMODE_THRESHOLD (3*TICRATE)
|
||||
#define DASHMODE_MAX (DASHMODE_THRESHOLD + 3)
|
||||
|
||||
// Value for infinite lives
|
||||
#define INFLIVES 0x7F
|
||||
|
||||
|
|
526
src/dehacked.c
526
src/dehacked.c
|
@ -313,7 +313,13 @@ static boolean findFreeSlot(INT32 *num)
|
|||
if (*num >= MAXSKINS)
|
||||
return false;
|
||||
|
||||
description[*num].picname[0] = '\0'; // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...)
|
||||
// Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...)
|
||||
description[*num].picname[0] = '\0';
|
||||
description[*num].nametag[0] = '\0';
|
||||
description[*num].displayname[0] = '\0';
|
||||
description[*num].oppositecolor = SKINCOLOR_NONE;
|
||||
description[*num].tagtextcolor = SKINCOLOR_NONE;
|
||||
description[*num].tagoutlinecolor = SKINCOLOR_NONE;
|
||||
|
||||
// Found one! ^_^
|
||||
return (description[*num].used = true);
|
||||
|
@ -326,9 +332,16 @@ static void readPlayer(MYFILE *f, INT32 num)
|
|||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
char *word;
|
||||
char *word2;
|
||||
char *displayname = ZZ_Alloc(MAXLINELEN+1);
|
||||
INT32 i;
|
||||
boolean slotfound = false;
|
||||
|
||||
#define SLOTFOUND \
|
||||
if (!slotfound && (slotfound = findFreeSlot(&num)) == false) \
|
||||
goto done;
|
||||
|
||||
displayname[MAXLINELEN] = '\0';
|
||||
|
||||
do
|
||||
{
|
||||
if (myfgets(s, MAXLINELEN, f))
|
||||
|
@ -336,6 +349,17 @@ static void readPlayer(MYFILE *f, INT32 num)
|
|||
if (s[0] == '\n')
|
||||
break;
|
||||
|
||||
for (i = 0; i < MAXLINELEN-3; i++)
|
||||
{
|
||||
char *tmp;
|
||||
if (s[i] == '=')
|
||||
{
|
||||
tmp = &s[i+2];
|
||||
strncpy(displayname, tmp, SKINNAMESIZE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
word = strtok(s, " ");
|
||||
if (word)
|
||||
strupr(word);
|
||||
|
@ -346,8 +370,7 @@ static void readPlayer(MYFILE *f, INT32 num)
|
|||
{
|
||||
char *playertext = NULL;
|
||||
|
||||
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
|
||||
goto done;
|
||||
SLOTFOUND
|
||||
|
||||
for (i = 0; i < MAXLINELEN-3; i++)
|
||||
{
|
||||
|
@ -395,11 +418,54 @@ static void readPlayer(MYFILE *f, INT32 num)
|
|||
|
||||
if (fastcmp(word, "PICNAME"))
|
||||
{
|
||||
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
|
||||
goto done;
|
||||
|
||||
SLOTFOUND
|
||||
strncpy(description[num].picname, word2, 8);
|
||||
}
|
||||
// new character select
|
||||
else if (fastcmp(word, "DISPLAYNAME"))
|
||||
{
|
||||
SLOTFOUND
|
||||
// replace '#' with line breaks
|
||||
// (also remove any '\n')
|
||||
{
|
||||
char *cur = NULL;
|
||||
|
||||
// remove '\n'
|
||||
cur = strchr(displayname, '\n');
|
||||
if (cur)
|
||||
*cur = '\0';
|
||||
|
||||
// turn '#' into '\n'
|
||||
cur = strchr(displayname, '#');
|
||||
while (cur)
|
||||
{
|
||||
*cur = '\n';
|
||||
cur = strchr(cur, '#');
|
||||
}
|
||||
}
|
||||
// copy final string
|
||||
strncpy(description[num].displayname, displayname, SKINNAMESIZE);
|
||||
}
|
||||
else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR"))
|
||||
{
|
||||
SLOTFOUND
|
||||
description[num].oppositecolor = (UINT8)get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME"))
|
||||
{
|
||||
SLOTFOUND
|
||||
strncpy(description[num].nametag, word2, 8);
|
||||
}
|
||||
else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR"))
|
||||
{
|
||||
SLOTFOUND
|
||||
description[num].tagtextcolor = (UINT8)get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "TAGOUTLINECOLOR") || fastcmp(word, "TAGOUTLINECOLOUR"))
|
||||
{
|
||||
SLOTFOUND
|
||||
description[num].tagoutlinecolor = (UINT8)get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "STATUS"))
|
||||
{
|
||||
/*
|
||||
|
@ -417,9 +483,7 @@ static void readPlayer(MYFILE *f, INT32 num)
|
|||
else if (fastcmp(word, "SKINNAME"))
|
||||
{
|
||||
// Send to free slot.
|
||||
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
|
||||
goto done;
|
||||
|
||||
SLOTFOUND
|
||||
strlcpy(description[num].skinname, word2, sizeof description[num].skinname);
|
||||
strlwr(description[num].skinname);
|
||||
}
|
||||
|
@ -427,8 +491,9 @@ static void readPlayer(MYFILE *f, INT32 num)
|
|||
deh_warning("readPlayer %d: unknown word '%s'", num, word);
|
||||
}
|
||||
} while (!myfeof(f)); // finish when the line is empty
|
||||
|
||||
#undef SLOTFOUND
|
||||
done:
|
||||
Z_Free(displayname);
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ typedef struct
|
|||
// Music stuff.
|
||||
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
|
||||
char musintername[7]; ///< Intermission screen music.
|
||||
|
||||
|
||||
char muspostbossname[7]; ///< Post-bossdeath music.
|
||||
UINT16 muspostbosstrack; ///< Post-bossdeath track.
|
||||
UINT32 muspostbosspos; ///< Post-bossdeath position
|
||||
|
@ -433,6 +433,7 @@ typedef struct
|
|||
tic_t time; ///< Time in which the level was finished.
|
||||
UINT32 score; ///< Score when the level was finished.
|
||||
UINT16 rings; ///< Rings when the level was finished.
|
||||
boolean gotperfect; ///< Got perfect bonus?
|
||||
} recorddata_t;
|
||||
|
||||
/** Setup for one NiGHTS map.
|
||||
|
|
|
@ -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?) */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 red;
|
||||
UINT8 green;
|
||||
UINT8 blue;
|
||||
UINT8 alpha;
|
||||
} byteColor_t;
|
||||
|
||||
union FColorRGBA
|
||||
{
|
||||
UINT32 rgba;
|
||||
struct
|
||||
{
|
||||
UINT8 red;
|
||||
UINT8 green;
|
||||
UINT8 blue;
|
||||
UINT8 alpha;
|
||||
} s;
|
||||
byteColor_t s;
|
||||
} ATTRPACK;
|
||||
typedef union FColorRGBA RGBA_t;
|
||||
|
||||
|
|
1104
src/f_finale.c
1104
src/f_finale.c
File diff suppressed because it is too large
Load diff
|
@ -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])
|
||||
|
||||
|
|
814
src/g_game.c
814
src/g_game.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
||||
|
|
|
@ -709,8 +709,8 @@ void G_DefineDefaultControls(void)
|
|||
|
||||
for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
|
||||
{
|
||||
gamecontroldefault[i][gc_weaponnext ][0] = 'e';
|
||||
gamecontroldefault[i][gc_weaponprev ][0] = 'q';
|
||||
gamecontroldefault[i][gc_weaponnext ][0] = KEY_MOUSEWHEELUP+0;
|
||||
gamecontroldefault[i][gc_weaponprev ][0] = KEY_MOUSEWHEELDOWN+0;
|
||||
gamecontroldefault[i][gc_wepslot1 ][0] = '1';
|
||||
gamecontroldefault[i][gc_wepslot2 ][0] = '2';
|
||||
gamecontroldefault[i][gc_wepslot3 ][0] = '3';
|
||||
|
|
|
@ -201,7 +201,7 @@ static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1,
|
|||
// (do not accept hit with the extensions)
|
||||
num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx;
|
||||
frac = num / den;
|
||||
if (frac < 0.0 || frac > 1.0)
|
||||
if (frac < 0.0l || frac > 1.0l)
|
||||
return NULL;
|
||||
|
||||
// now get the frac along the BSP line
|
||||
|
|
|
@ -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,46 +920,21 @@ 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;
|
||||
grMipmap->width = (UINT16)pflatsize;
|
||||
grMipmap->height = (UINT16)pflatsize;
|
||||
|
||||
// the flat raw data needn't be converted with palettized textures
|
||||
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
|
||||
PU_HWRCACHE, &grMipmap->grInfo.data));
|
||||
}
|
||||
// the flat raw data needn't be converted with palettized textures
|
||||
W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum),
|
||||
PU_HWRCACHE, &grMipmap->grInfo.data));
|
||||
}
|
||||
|
||||
// Download a Doom 'flat' to the hardware cache and make it ready for use
|
||||
void HWR_GetFlat(lumpnum_t flatlumpnum)
|
||||
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,24 +953,56 @@ 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)
|
||||
{
|
||||
GLTexture_t *grtex;
|
||||
#ifdef PARANOIA
|
||||
if ((unsigned)texturenum >= gr_numtextures)
|
||||
I_Error("HWR_GetTextureFlat: texturenum >= numtextures\n");
|
||||
#endif
|
||||
if (texturenum == 0 || texturenum == -1)
|
||||
GLMipmap_t *grmip;
|
||||
if (flatlumpnum == LUMPERROR)
|
||||
return;
|
||||
grtex = &gr_textures2[texturenum];
|
||||
|
||||
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
|
||||
HWR_LoadTextureFlat(&grtex->mipmap, texturenum);
|
||||
if (needpatchflush)
|
||||
W_FlushCachedPatches();
|
||||
|
||||
HWD.pfnSetTexture(&grtex->mipmap);
|
||||
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(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||
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_GetLevelFlat: texturenum >= numtextures\n");
|
||||
#endif
|
||||
if (texturenum == 0 || texturenum == -1)
|
||||
return;
|
||||
grtex = &gr_textures2[texturenum];
|
||||
|
||||
if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded)
|
||||
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);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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*/;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
|
|
|
@ -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,48 +596,49 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
|
|||
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
|
||||
}
|
||||
|
||||
len = W_LumpLength(lumpnum);
|
||||
|
||||
switch (len)
|
||||
// set texture for polygon
|
||||
if (levelflat != NULL)
|
||||
{
|
||||
case 4194304: // 2048x2048 lump
|
||||
fflatwidth = fflatheight = 2048.0f;
|
||||
break;
|
||||
case 1048576: // 1024x1024 lump
|
||||
fflatwidth = fflatheight = 1024.0f;
|
||||
break;
|
||||
case 262144:// 512x512 lump
|
||||
fflatwidth = fflatheight = 512.0f;
|
||||
break;
|
||||
case 65536: // 256x256 lump
|
||||
fflatwidth = fflatheight = 256.0f;
|
||||
break;
|
||||
case 16384: // 128x128 lump
|
||||
fflatwidth = fflatheight = 128.0f;
|
||||
break;
|
||||
case 1024: // 32x32 lump
|
||||
fflatwidth = fflatheight = 32.0f;
|
||||
break;
|
||||
default: // 64x64 lump
|
||||
fflatwidth = fflatheight = 64.0f;
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
flatflag = ((INT32)fflatwidth)-1;
|
||||
switch (len)
|
||||
{
|
||||
case 4194304: // 2048x2048 lump
|
||||
fflatwidth = fflatheight = 2048.0f;
|
||||
break;
|
||||
case 1048576: // 1024x1024 lump
|
||||
fflatwidth = fflatheight = 1024.0f;
|
||||
break;
|
||||
case 262144:// 512x512 lump
|
||||
fflatwidth = fflatheight = 512.0f;
|
||||
break;
|
||||
case 65536: // 256x256 lump
|
||||
fflatwidth = fflatheight = 256.0f;
|
||||
break;
|
||||
case 16384: // 128x128 lump
|
||||
fflatwidth = fflatheight = 128.0f;
|
||||
break;
|
||||
case 1024: // 32x32 lump
|
||||
fflatwidth = fflatheight = 32.0f;
|
||||
break;
|
||||
default: // 64x64 lump
|
||||
fflatwidth = fflatheight = 64.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
if (texturenum != 0 && texturenum != -1)
|
||||
{
|
||||
fflatwidth = textures[texturenum]->width;
|
||||
fflatheight = textures[texturenum]->height;
|
||||
flatflag = ((INT32)fflatwidth)-1;
|
||||
}
|
||||
}
|
||||
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,48 +3224,49 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
|
|||
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
|
||||
}
|
||||
|
||||
len = W_LumpLength(lumpnum);
|
||||
|
||||
switch (len)
|
||||
// set texture for polygon
|
||||
if (levelflat != NULL)
|
||||
{
|
||||
case 4194304: // 2048x2048 lump
|
||||
fflatwidth = fflatheight = 2048.0f;
|
||||
break;
|
||||
case 1048576: // 1024x1024 lump
|
||||
fflatwidth = fflatheight = 1024.0f;
|
||||
break;
|
||||
case 262144:// 512x512 lump
|
||||
fflatwidth = fflatheight = 512.0f;
|
||||
break;
|
||||
case 65536: // 256x256 lump
|
||||
fflatwidth = fflatheight = 256.0f;
|
||||
break;
|
||||
case 16384: // 128x128 lump
|
||||
fflatwidth = fflatheight = 128.0f;
|
||||
break;
|
||||
case 1024: // 32x32 lump
|
||||
fflatwidth = fflatheight = 32.0f;
|
||||
break;
|
||||
default: // 64x64 lump
|
||||
fflatwidth = fflatheight = 64.0f;
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
flatflag = ((INT32)fflatwidth)-1;
|
||||
switch (len)
|
||||
{
|
||||
case 4194304: // 2048x2048 lump
|
||||
fflatwidth = fflatheight = 2048.0f;
|
||||
break;
|
||||
case 1048576: // 1024x1024 lump
|
||||
fflatwidth = fflatheight = 1024.0f;
|
||||
break;
|
||||
case 262144:// 512x512 lump
|
||||
fflatwidth = fflatheight = 512.0f;
|
||||
break;
|
||||
case 65536: // 256x256 lump
|
||||
fflatwidth = fflatheight = 256.0f;
|
||||
break;
|
||||
case 16384: // 128x128 lump
|
||||
fflatwidth = fflatheight = 128.0f;
|
||||
break;
|
||||
case 1024: // 32x32 lump
|
||||
fflatwidth = fflatheight = 32.0f;
|
||||
break;
|
||||
default: // 64x64 lump
|
||||
fflatwidth = fflatheight = 64.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
if (texturenum != 0 && texturenum != -1)
|
||||
{
|
||||
fflatwidth = textures[texturenum]->width;
|
||||
fflatheight = textures[texturenum]->height;
|
||||
flatflag = ((INT32)fflatwidth)-1;
|
||||
}
|
||||
}
|
||||
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)
|
||||
continue;
|
||||
if (thing->sprite == SPR_HOOP)
|
||||
{
|
||||
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (limit_dist && approx_dist > limit_dist)
|
||||
continue;
|
||||
}
|
||||
|
||||
HWR_ProjectSprite(thing);
|
||||
}
|
||||
|
@ -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,86 +5877,122 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
// ==========================================================================
|
||||
//
|
||||
// ==========================================================================
|
||||
static void HWR_DrawSkyBackground(void)
|
||||
static void HWR_DrawSkyBackground(player_t *player)
|
||||
{
|
||||
FOutVector v[4];
|
||||
angle_t angle;
|
||||
float dimensionmultiply;
|
||||
float aspectratio;
|
||||
float angleturn;
|
||||
|
||||
HWR_GetTexture(texturetranslation[skytexture]);
|
||||
aspectratio = (float)vid.width/(float)vid.height;
|
||||
|
||||
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
|
||||
// because it's called just after clearing the screen
|
||||
// and thus, the near clipping plane is set to 3.99
|
||||
// Sryder: Just use the near clipping plane value then
|
||||
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
v[0].x = v[3].x = -ZCLIP_PLANE-1;
|
||||
v[1].x = v[2].x = ZCLIP_PLANE+1;
|
||||
v[0].y = v[1].y = -ZCLIP_PLANE-1;
|
||||
v[2].y = v[3].y = ZCLIP_PLANE+1;
|
||||
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
|
||||
|
||||
// X
|
||||
|
||||
// NOTE: This doesn't work right with texture widths greater than 1024
|
||||
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
|
||||
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
|
||||
|
||||
angle = (dup_viewangle + gr_xtoviewangle[0]);
|
||||
|
||||
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
|
||||
|
||||
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
|
||||
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
|
||||
// use +angle and -1.0f above instead if you wanted old backwards behavior
|
||||
|
||||
// Y
|
||||
angle = aimingangle;
|
||||
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
|
||||
|
||||
if (splitscreen)
|
||||
if (cv_grskydome.value)
|
||||
{
|
||||
dimensionmultiply *= 2;
|
||||
angle *= 2;
|
||||
}
|
||||
FTransform transform;
|
||||
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
|
||||
postimg_t *type;
|
||||
|
||||
// Middle of the sky should always be at angle 0
|
||||
// need to keep correct aspect ratio with X
|
||||
if (atransform.flip)
|
||||
{
|
||||
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
|
||||
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
|
||||
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
|
||||
if (splitscreen && player == &players[secondarydisplayplayer])
|
||||
type = &postimgtype2;
|
||||
else
|
||||
type = &postimgtype;
|
||||
|
||||
memset(&transform, 0x00, sizeof(FTransform));
|
||||
|
||||
//04/01/2000: Hurdler: added for T&L
|
||||
// It should replace all other gr_viewxxx when finished
|
||||
transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
|
||||
transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
|
||||
|
||||
if (*type == postimg_flip)
|
||||
transform.flip = true;
|
||||
else
|
||||
transform.flip = false;
|
||||
|
||||
transform.scalex = 1;
|
||||
transform.scaley = (float)vid.width/vid.height;
|
||||
transform.scalez = 1;
|
||||
transform.fovxangle = fpov; // Tails
|
||||
transform.fovyangle = fpov; // Tails
|
||||
transform.splitscreen = splitscreen;
|
||||
|
||||
HWR_GetTexture(texturetranslation[skytexture]);
|
||||
HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
|
||||
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
|
||||
}
|
||||
FOutVector v[4];
|
||||
angle_t angle;
|
||||
float dimensionmultiply;
|
||||
float aspectratio;
|
||||
float angleturn;
|
||||
|
||||
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
|
||||
HWR_GetTexture(texturetranslation[skytexture]);
|
||||
aspectratio = (float)vid.width/(float)vid.height;
|
||||
|
||||
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
|
||||
{
|
||||
angle = InvAngle(angle);
|
||||
v[3].tow = v[2].tow += ((float) angle / angleturn);
|
||||
v[0].tow = v[1].tow += ((float) angle / angleturn);
|
||||
}
|
||||
else
|
||||
{
|
||||
v[3].tow = v[2].tow -= ((float) angle / angleturn);
|
||||
v[0].tow = v[1].tow -= ((float) angle / angleturn);
|
||||
}
|
||||
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
|
||||
// because it's called just after clearing the screen
|
||||
// and thus, the near clipping plane is set to 3.99
|
||||
// Sryder: Just use the near clipping plane value then
|
||||
|
||||
HWD.pfnDrawPolygon(NULL, v, 4, 0);
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
v[0].x = v[3].x = -ZCLIP_PLANE-1;
|
||||
v[1].x = v[2].x = ZCLIP_PLANE+1;
|
||||
v[0].y = v[1].y = -ZCLIP_PLANE-1;
|
||||
v[2].y = v[3].y = ZCLIP_PLANE+1;
|
||||
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
|
||||
|
||||
// X
|
||||
|
||||
// NOTE: This doesn't work right with texture widths greater than 1024
|
||||
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
|
||||
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
|
||||
|
||||
angle = (dup_viewangle + gr_xtoviewangle[0]);
|
||||
|
||||
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
|
||||
|
||||
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
|
||||
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
|
||||
// use +angle and -1.0f above instead if you wanted old backwards behavior
|
||||
|
||||
// Y
|
||||
angle = aimingangle;
|
||||
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
|
||||
|
||||
if (splitscreen)
|
||||
{
|
||||
dimensionmultiply *= 2;
|
||||
angle *= 2;
|
||||
}
|
||||
|
||||
// Middle of the sky should always be at angle 0
|
||||
// need to keep correct aspect ratio with X
|
||||
if (atransform.flip)
|
||||
{
|
||||
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
|
||||
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
|
||||
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
|
||||
}
|
||||
else
|
||||
{
|
||||
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
|
||||
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
|
||||
}
|
||||
|
||||
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
|
||||
|
||||
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
|
||||
{
|
||||
angle = InvAngle(angle);
|
||||
v[3].tow = v[2].tow += ((float) angle / angleturn);
|
||||
v[0].tow = v[1].tow += ((float) angle / angleturn);
|
||||
}
|
||||
else
|
||||
{
|
||||
v[3].tow = v[2].tow -= ((float) angle / angleturn);
|
||||
v[0].tow = v[1].tow -= ((float) angle / angleturn);
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(NULL, v, 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -6100,7 +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
|
||||
|
||||
|
|
|
@ -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
|
@ -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
576
src/hardware/hw_md2load.c
Normal 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
19
src/hardware/hw_md2load.h
Normal 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
522
src/hardware/hw_md3load.c
Normal 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
19
src/hardware/hw_md3load.h
Normal 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
737
src/hardware/hw_model.c
Normal 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
121
src/hardware/hw_model.h
Normal 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
|
|
@ -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
|
@ -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
|
||||
|
||||
// ==========================================================================
|
||||
|
|
52
src/hardware/r_opengl/r_vbo.h
Normal file
52
src/hardware/r_opengl/r_vbo.h
Normal 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
230
src/hardware/u_list.c
Normal 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
29
src/hardware/u_list.h
Normal 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
|
|
@ -71,6 +71,10 @@ patch_t *lt_font[LT_FONTSIZE];
|
|||
patch_t *cred_font[CRED_FONTSIZE];
|
||||
patch_t *ttlnum[20]; // act numbers (0-19)
|
||||
|
||||
// Name tag fonts
|
||||
patch_t *ntb_font[NT_FONTSIZE];
|
||||
patch_t *nto_font[NT_FONTSIZE];
|
||||
|
||||
static player_t *plr;
|
||||
boolean chat_on; // entering a chat message?
|
||||
static char w_chat[HU_MAXMSGLEN];
|
||||
|
@ -246,6 +250,32 @@ void HU_LoadGraphics(void)
|
|||
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// cache the base name tag font for entire game execution
|
||||
j = NT_FONTSTART;
|
||||
for (i = 0; i < NT_FONTSIZE; i++)
|
||||
{
|
||||
sprintf(buffer, "NTFNT%.3d", j);
|
||||
j++;
|
||||
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
ntb_font[i] = NULL;
|
||||
else
|
||||
ntb_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// cache the outline name tag font for entire game execution
|
||||
j = NT_FONTSTART;
|
||||
for (i = 0; i < NT_FONTSIZE; i++)
|
||||
{
|
||||
sprintf(buffer, "NTFNO%.3d", j);
|
||||
j++;
|
||||
|
||||
if (W_CheckNumForName(buffer) == LUMPERROR)
|
||||
nto_font[i] = NULL;
|
||||
else
|
||||
nto_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
|
||||
}
|
||||
|
||||
// cache the crosshairs, don't bother to know which one is being used,
|
||||
// just cache all 3, they're so small anyway.
|
||||
for (i = 0; i < HU_CROSSHAIRS; i++)
|
||||
|
|
|
@ -35,6 +35,12 @@
|
|||
#define CRED_FONTEND 'Z' // the last font character
|
||||
#define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1)
|
||||
|
||||
// Name tag font
|
||||
// Used by base and outline font set
|
||||
#define NT_FONTSTART '!' // the first font character
|
||||
#define NT_FONTEND 'Z' // the last font character
|
||||
#define NT_FONTSIZE (NT_FONTEND - NT_FONTSTART + 1)
|
||||
|
||||
#define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init();
|
||||
|
||||
extern char *shiftxform; // english translation shift table
|
||||
|
@ -77,6 +83,8 @@ extern patch_t *tallnum[10];
|
|||
extern patch_t *nightsnum[10];
|
||||
extern patch_t *lt_font[LT_FONTSIZE];
|
||||
extern patch_t *cred_font[CRED_FONTSIZE];
|
||||
extern patch_t *ntb_font[NT_FONTSIZE];
|
||||
extern patch_t *nto_font[NT_FONTSIZE];
|
||||
extern patch_t *ttlnum[20];
|
||||
extern patch_t *emeraldpics[3][8];
|
||||
extern patch_t *rflagico;
|
||||
|
|
36
src/i_tcp.c
36
src/i_tcp.c
|
@ -776,6 +776,8 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
|
|||
#endif
|
||||
#endif
|
||||
mysockaddr_t straddr;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
|
||||
if (s == (SOCKET_TYPE)ERRSOCKET)
|
||||
return (SOCKET_TYPE)ERRSOCKET;
|
||||
|
@ -869,12 +871,16 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
|
|||
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
|
||||
}
|
||||
|
||||
if (getsockname(s, (struct sockaddr *)&sin, &len) == -1)
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n"));
|
||||
else
|
||||
current_port = (UINT16)ntohs(sin.sin_port);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static boolean UDP_Socket(void)
|
||||
{
|
||||
const char *sock_port = NULL;
|
||||
size_t s;
|
||||
struct my_addrinfo *ai, *runp, hints;
|
||||
int gaie;
|
||||
|
@ -896,20 +902,11 @@ static boolean UDP_Socket(void)
|
|||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
|
||||
if (M_CheckParm("-clientport"))
|
||||
{
|
||||
if (!M_IsNextParm())
|
||||
I_Error("syntax: -clientport <portnum>");
|
||||
sock_port = M_GetNextParm();
|
||||
}
|
||||
else
|
||||
sock_port = port_name;
|
||||
|
||||
if (M_CheckParm("-bindaddr"))
|
||||
{
|
||||
while (M_IsNextParm())
|
||||
{
|
||||
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
|
||||
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
|
@ -930,7 +927,7 @@ static boolean UDP_Socket(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
gaie = I_getaddrinfo("0.0.0.0", sock_port, &hints, &ai);
|
||||
gaie = I_getaddrinfo("0.0.0.0", port_name, &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
|
@ -945,8 +942,8 @@ static boolean UDP_Socket(void)
|
|||
#ifdef HAVE_MINIUPNPC
|
||||
if (UPNP_support)
|
||||
{
|
||||
I_UPnP_rem(sock_port, "UDP");
|
||||
I_UPnP_add(NULL, sock_port, "UDP");
|
||||
I_UPnP_rem(port_name, "UDP");
|
||||
I_UPnP_add(NULL, port_name, "UDP");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -963,7 +960,7 @@ static boolean UDP_Socket(void)
|
|||
{
|
||||
while (M_IsNextParm())
|
||||
{
|
||||
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
|
||||
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
|
@ -984,7 +981,7 @@ static boolean UDP_Socket(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
gaie = I_getaddrinfo("::", sock_port, &hints, &ai);
|
||||
gaie = I_getaddrinfo("::", port_name, &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
|
@ -1260,7 +1257,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
|
|||
int gaie;
|
||||
|
||||
if (!port || !port[0])
|
||||
port = port_name;
|
||||
port = DEFAULTPORT;
|
||||
|
||||
DEBFILE(va("Creating new node: %s@%s\n", address, port));
|
||||
|
||||
|
@ -1424,14 +1421,15 @@ boolean I_InitTcpNetwork(void)
|
|||
if (!I_InitTcpDriver())
|
||||
return false;
|
||||
|
||||
if (M_CheckParm("-udpport"))
|
||||
if (M_CheckParm("-port"))
|
||||
// Combined -udpport and -clientport into -port
|
||||
// As it was really redundant having two seperate parms that does the same thing
|
||||
{
|
||||
if (M_IsNextParm())
|
||||
strcpy(port_name, M_GetNextParm());
|
||||
else
|
||||
strcpy(port_name, "0");
|
||||
}
|
||||
current_port = (UINT16)atoi(port_name);
|
||||
|
||||
// parse network game options,
|
||||
if (M_CheckParm("-server") || dedicated)
|
||||
|
|
1172
src/info.c
1172
src/info.c
File diff suppressed because it is too large
Load diff
324
src/info.h
324
src/info.h
|
@ -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,
|
||||
|
|
|
@ -816,15 +816,12 @@ static int lib_pCheckDeathPitCollide(lua_State *L)
|
|||
|
||||
static int lib_pCheckSolidLava(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
|
||||
//HUDSAFE
|
||||
INLEVEL
|
||||
if (!mo)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
if (!rover)
|
||||
return LUA_ErrInvalid(L, "ffloor_t");
|
||||
lua_pushboolean(L, P_CheckSolidLava(mo, rover));
|
||||
lua_pushboolean(L, P_CheckSolidLava(rover));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ enum hook {
|
|||
hook_FollowMobj,
|
||||
hook_PlayerCanDamage,
|
||||
hook_PlayerQuit,
|
||||
hook_IntermissionThinker,
|
||||
|
||||
hook_MAX // last hook
|
||||
};
|
||||
|
@ -91,5 +92,6 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnM
|
|||
boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following
|
||||
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
|
||||
void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
|
||||
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,6 +61,7 @@ const char *const hookNames[hook_MAX+1] = {
|
|||
"FollowMobj",
|
||||
"PlayerCanDamage",
|
||||
"PlayerQuit",
|
||||
"IntermissionThinker",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -1322,4 +1323,27 @@ void LUAh_PlayerQuit(player_t *plr, int reason)
|
|||
lua_settop(gL, 0);
|
||||
}
|
||||
|
||||
// Hook for Y_Ticker
|
||||
void LUAh_IntermissionThinker(void)
|
||||
{
|
||||
hook_p hookp;
|
||||
if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8))))
|
||||
return;
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
{
|
||||
if (hookp->type != hook_IntermissionThinker)
|
||||
continue;
|
||||
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
if (lua_pcall(gL, 0, 0, 0)) {
|
||||
if (!hookp->error || cv_debug & DBG_LUA)
|
||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
|
||||
lua_pop(gL, 1);
|
||||
hookp->error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -411,37 +411,53 @@ static int sector_iterate(lua_State *L)
|
|||
|
||||
// sector.lines, i -> sector.lines[i]
|
||||
// sector.lines.valid, for validity checking
|
||||
//
|
||||
// 25/9/19 Monster Iestyn
|
||||
// Modified this and _num to use triple pointers, to allow for a new hack of mine involving offsetof
|
||||
// this way we don't need to check frontsector or backsector of line #0 in the array
|
||||
//
|
||||
static int sectorlines_get(lua_State *L)
|
||||
{
|
||||
line_t **seclines = *((line_t ***)luaL_checkudata(L, 1, META_SECTORLINES));
|
||||
line_t ***seclines = *((line_t ****)luaL_checkudata(L, 1, META_SECTORLINES));
|
||||
size_t i;
|
||||
size_t numoflines = 0;
|
||||
lua_settop(L, 2);
|
||||
if (!lua_isnumber(L, 2))
|
||||
{
|
||||
int field = luaL_checkoption(L, 2, NULL, valid_opt);
|
||||
if (!seclines)
|
||||
if (!seclines || !(*seclines))
|
||||
{
|
||||
if (field == 0) {
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
return luaL_error(L, "accessed sector_t doesn't exist anymore.");
|
||||
return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
|
||||
} else if (field == 0) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* a snip from sector_t struct in r_defs.h, for reference
|
||||
size_t linecount;
|
||||
struct line_s **lines; // [linecount] size
|
||||
*/
|
||||
// get the "linecount" by shifting our retrieved memory address of "lines" to where "linecount" is in the sector_t, then dereferencing the result
|
||||
// we need this to determine the array's actual size, and therefore also the maximum value allowed as an index
|
||||
// this only works if seclines is actually a pointer to a sector's lines member in memory, oh boy
|
||||
numoflines = (size_t)(*(seclines - (offsetof(sector_t, lines) - offsetof(sector_t, linecount))));
|
||||
|
||||
/* OLD HACK
|
||||
// check first linedef to figure which of its sectors owns this sector->lines pointer
|
||||
// then check that sector's linecount to get a maximum index
|
||||
//if (!seclines[0])
|
||||
//if (!(*seclines)[0])
|
||||
//return luaL_error(L, "no lines found!"); // no first linedef?????
|
||||
if (seclines[0]->frontsector->lines == seclines)
|
||||
numoflines = seclines[0]->frontsector->linecount;
|
||||
else if (seclines[0]->backsector && seclines[0]->backsector->lines == seclines) // check backsector exists first
|
||||
numoflines = seclines[0]->backsector->linecount;
|
||||
if ((*seclines)[0]->frontsector->lines == *seclines)
|
||||
numoflines = (*seclines)[0]->frontsector->linecount;
|
||||
else if ((*seclines)[0]->backsector && *seclines[0]->backsector->lines == *seclines) // check backsector exists first
|
||||
numoflines = (*seclines)[0]->backsector->linecount;
|
||||
//if neither sector has it then ???
|
||||
*/
|
||||
|
||||
if (!numoflines)
|
||||
return luaL_error(L, "no lines found!");
|
||||
|
@ -449,23 +465,21 @@ static int sectorlines_get(lua_State *L)
|
|||
i = (size_t)lua_tointeger(L, 2);
|
||||
if (i >= numoflines)
|
||||
return 0;
|
||||
LUA_PushUserdata(L, seclines[i], META_LINE);
|
||||
LUA_PushUserdata(L, (*seclines)[i], META_LINE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// #(sector.lines) -> sector.linecount
|
||||
static int sectorlines_num(lua_State *L)
|
||||
{
|
||||
line_t **seclines = *((line_t ***)luaL_checkudata(L, 1, META_SECTORLINES));
|
||||
line_t ***seclines = *((line_t ****)luaL_checkudata(L, 1, META_SECTORLINES));
|
||||
size_t numoflines = 0;
|
||||
// check first linedef to figure which of its sectors owns this sector->lines pointer
|
||||
// then check that sector's linecount to get a maximum index
|
||||
//if (!seclines[0])
|
||||
//return luaL_error(L, "no lines found!"); // no first linedef?????
|
||||
if (seclines[0]->frontsector->lines == seclines)
|
||||
numoflines = seclines[0]->frontsector->linecount;
|
||||
else if (seclines[0]->backsector && seclines[0]->backsector->lines == seclines) // check backsector exists first
|
||||
numoflines = seclines[0]->backsector->linecount;
|
||||
//if neither sector has it then ???
|
||||
|
||||
if (!seclines || !(*seclines))
|
||||
return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
|
||||
|
||||
// see comments in the _get function above
|
||||
numoflines = (size_t)(*(seclines - (offsetof(sector_t, lines) - offsetof(sector_t, linecount))));
|
||||
lua_pushinteger(L, numoflines);
|
||||
return 1;
|
||||
}
|
||||
|
@ -543,7 +557,7 @@ static int sector_get(lua_State *L)
|
|||
LUA_PushUserdata(L, §ors[sector->camsec], META_SECTOR);
|
||||
return 1;
|
||||
case sector_lines: // lines
|
||||
LUA_PushUserdata(L, sector->lines, META_SECTORLINES);
|
||||
LUA_PushUserdata(L, §or->lines, META_SECTORLINES); // push the address of the "lines" member in the struct, to allow our hacks in sectorlines_get/_num to work
|
||||
return 1;
|
||||
case sector_ffloors: // ffloors
|
||||
lua_pushcfunction(L, lib_iterateSectorFFloors);
|
||||
|
@ -579,6 +593,7 @@ static int sector_set(lua_State *L)
|
|||
case sector_thinglist: // thinglist
|
||||
case sector_heightsec: // heightsec
|
||||
case sector_camsec: // camsec
|
||||
case sector_lines: // lines
|
||||
case sector_ffloors: // ffloors
|
||||
#ifdef ESLOPE
|
||||
case sector_fslope: // f_slope
|
||||
|
|
|
@ -164,6 +164,8 @@ static int mobj_get(lua_State *L)
|
|||
enum mobj_e field = Lua_optoption(L, 2, NULL, mobj_opt);
|
||||
lua_settop(L, 2);
|
||||
|
||||
INLEVEL
|
||||
|
||||
if (!mo) {
|
||||
if (field == mobj_valid) {
|
||||
lua_pushboolean(L, 0);
|
||||
|
@ -409,6 +411,8 @@ static int mobj_set(lua_State *L)
|
|||
enum mobj_e field = Lua_optoption(L, 2, mobj_opt[0], mobj_opt);
|
||||
lua_settop(L, 3);
|
||||
|
||||
INLEVEL
|
||||
|
||||
if (!mo)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
static int lib_iteratePlayers(lua_State *L)
|
||||
{
|
||||
INT32 i = -1;
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
{
|
||||
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
|
||||
|
@ -52,7 +51,6 @@ static int lib_getPlayer(lua_State *L)
|
|||
{
|
||||
const char *field;
|
||||
// i -> players[i]
|
||||
INLEVEL
|
||||
if (lua_type(L, 2) == LUA_TNUMBER)
|
||||
{
|
||||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
|
|
|
@ -431,7 +431,7 @@ void LUA_InvalidateLevel(void)
|
|||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
LUA_InvalidateUserdata(§ors[i]);
|
||||
LUA_InvalidateUserdata(sectors[i].lines);
|
||||
LUA_InvalidateUserdata(§ors[i].lines);
|
||||
if (sectors[i].ffloors)
|
||||
{
|
||||
for (rover = sectors[i].ffloors; rover; rover = rover->next)
|
||||
|
@ -1121,7 +1121,7 @@ void LUA_Archive(void)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
if (!playeringame[i] && i > 0) // dedicated servers...
|
||||
continue;
|
||||
// all players in game will be archived, even if they just add a 0.
|
||||
ArchiveExtVars(&players[i], "player");
|
||||
|
@ -1157,7 +1157,7 @@ void LUA_UnArchive(void)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
if (!playeringame[i] && i > 0) // dedicated servers...
|
||||
continue;
|
||||
UnArchiveExtVars(&players[i]);
|
||||
}
|
||||
|
|
32
src/m_cond.c
32
src/m_cond.c
|
@ -528,12 +528,22 @@ skincolors_t M_GetEmblemColor(emblem_t *em)
|
|||
return em->color;
|
||||
}
|
||||
|
||||
const char *M_GetEmblemPatch(emblem_t *em)
|
||||
const char *M_GetEmblemPatch(emblem_t *em, boolean big)
|
||||
{
|
||||
static char pnamebuf[7] = "GOTITn";
|
||||
static char pnamebuf[7];
|
||||
|
||||
if (!big)
|
||||
strcpy(pnamebuf, "GOTITn");
|
||||
else
|
||||
strcpy(pnamebuf, "EMBMn0");
|
||||
|
||||
I_Assert(em->sprite >= 'A' && em->sprite <= 'Z');
|
||||
pnamebuf[5] = em->sprite;
|
||||
|
||||
if (!big)
|
||||
pnamebuf[5] = em->sprite;
|
||||
else
|
||||
pnamebuf[4] = em->sprite;
|
||||
|
||||
return pnamebuf;
|
||||
}
|
||||
|
||||
|
@ -544,11 +554,21 @@ skincolors_t M_GetExtraEmblemColor(extraemblem_t *em)
|
|||
return em->color;
|
||||
}
|
||||
|
||||
const char *M_GetExtraEmblemPatch(extraemblem_t *em)
|
||||
const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big)
|
||||
{
|
||||
static char pnamebuf[7] = "GOTITn";
|
||||
static char pnamebuf[7];
|
||||
|
||||
if (!big)
|
||||
strcpy(pnamebuf, "GOTITn");
|
||||
else
|
||||
strcpy(pnamebuf, "EMBMn0");
|
||||
|
||||
I_Assert(em->sprite >= 'A' && em->sprite <= 'Z');
|
||||
pnamebuf[5] = em->sprite;
|
||||
|
||||
if (!big)
|
||||
pnamebuf[5] = em->sprite;
|
||||
else
|
||||
pnamebuf[4] = em->sprite;
|
||||
|
||||
return pnamebuf;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
239
src/m_fixed.c
239
src/m_fixed.c
|
@ -56,7 +56,7 @@ fixed_t FixedDiv2(fixed_t a, fixed_t b)
|
|||
if (b == 0)
|
||||
I_Error("FixedDiv: divide by zero");
|
||||
|
||||
ret = (((INT64)a * FRACUNIT) ) / b;
|
||||
ret = (((INT64)a * FRACUNIT)) / b;
|
||||
|
||||
if ((ret > INT32_MAX) || (ret < INT32_MIN))
|
||||
I_Error("FixedDiv: divide by zero");
|
||||
|
@ -117,7 +117,7 @@ fixed_t FixedHypot(fixed_t x, fixed_t y)
|
|||
yx = FixedDiv(y, x); // (x/y)
|
||||
}
|
||||
yx2 = FixedMul(yx, yx); // (x/y)^2
|
||||
yx1 = FixedSqrt(1*FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
|
||||
yx1 = FixedSqrt(1 * FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
|
||||
return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2)
|
||||
}
|
||||
|
||||
|
@ -191,8 +191,8 @@ vector2_t *FV2_Divide(vector2_t *a_i, fixed_t a_c)
|
|||
// Vector Complex Math
|
||||
vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a_o)
|
||||
{
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
|
||||
a_o->x = a_1->x + a_o->x;
|
||||
a_o->y = a_1->y + a_o->y;
|
||||
return a_o;
|
||||
|
@ -200,16 +200,16 @@ vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a
|
|||
|
||||
fixed_t FV2_Distance(const vector2_t *p1, const vector2_t *p2)
|
||||
{
|
||||
fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
|
||||
fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
|
||||
return FixedSqrt(xs+ys);
|
||||
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
|
||||
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
|
||||
return FixedSqrt(xs + ys);
|
||||
}
|
||||
|
||||
fixed_t FV2_Magnitude(const vector2_t *a_normal)
|
||||
{
|
||||
fixed_t xs = FixedMul(a_normal->x,a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y,a_normal->y);
|
||||
return FixedSqrt(xs+ys);
|
||||
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
|
||||
return FixedSqrt(xs + ys);
|
||||
}
|
||||
|
||||
// Also returns the magnitude
|
||||
|
@ -240,7 +240,7 @@ vector2_t *FV2_Negate(vector2_t *a_1)
|
|||
|
||||
boolean FV2_Equal(const vector2_t *a_1, const vector2_t *a_2)
|
||||
{
|
||||
fixed_t Epsilon = FRACUNIT/FRACUNIT;
|
||||
fixed_t Epsilon = FRACUNIT / FRACUNIT;
|
||||
|
||||
if ((abs(a_2->x - a_1->x) > Epsilon) ||
|
||||
(abs(a_2->y - a_1->y) > Epsilon))
|
||||
|
@ -261,7 +261,7 @@ fixed_t FV2_Dot(const vector2_t *a_1, const vector2_t *a_2)
|
|||
//
|
||||
// Given two points, create a vector between them.
|
||||
//
|
||||
vector2_t *FV2_Point2Vec (const vector2_t *point1, const vector2_t *point2, vector2_t *a_o)
|
||||
vector2_t *FV2_Point2Vec(const vector2_t *point1, const vector2_t *point2, vector2_t *a_o)
|
||||
{
|
||||
a_o->x = point1->x - point2->x;
|
||||
a_o->y = point1->y - point2->y;
|
||||
|
@ -344,9 +344,9 @@ vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c)
|
|||
// Vector Complex Math
|
||||
vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
|
||||
a_o->z = FixedDiv(a_2->z - a_1->z, 2*FRACUNIT);
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
|
||||
a_o->z = FixedDiv(a_2->z - a_1->z, 2 * FRACUNIT);
|
||||
a_o->x = a_1->x + a_o->x;
|
||||
a_o->y = a_1->y + a_o->y;
|
||||
a_o->z = a_1->z + a_o->z;
|
||||
|
@ -355,18 +355,18 @@ vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a
|
|||
|
||||
fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2)
|
||||
{
|
||||
fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
|
||||
fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
|
||||
fixed_t zs = FixedMul(p2->z-p1->z,p2->z-p1->z);
|
||||
return FixedSqrt(xs+ys+zs);
|
||||
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
|
||||
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
|
||||
fixed_t zs = FixedMul(p2->z - p1->z, p2->z - p1->z);
|
||||
return FixedSqrt(xs + ys + zs);
|
||||
}
|
||||
|
||||
fixed_t FV3_Magnitude(const vector3_t *a_normal)
|
||||
{
|
||||
fixed_t xs = FixedMul(a_normal->x,a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y,a_normal->y);
|
||||
fixed_t zs = FixedMul(a_normal->z,a_normal->z);
|
||||
return FixedSqrt(xs+ys+zs);
|
||||
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
|
||||
fixed_t zs = FixedMul(a_normal->z, a_normal->z);
|
||||
return FixedSqrt(xs + ys + zs);
|
||||
}
|
||||
|
||||
// Also returns the magnitude
|
||||
|
@ -399,7 +399,7 @@ vector3_t *FV3_Negate(vector3_t *a_1)
|
|||
|
||||
boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
|
||||
{
|
||||
fixed_t Epsilon = FRACUNIT/FRACUNIT;
|
||||
fixed_t Epsilon = FRACUNIT / FRACUNIT;
|
||||
|
||||
if ((abs(a_2->x - a_1->x) > Epsilon) ||
|
||||
(abs(a_2->y - a_1->y) > Epsilon) ||
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -465,7 +479,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
|
|||
// the closest point on the edge of
|
||||
// the triangle is returned.
|
||||
//
|
||||
void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, vector3_t *result)
|
||||
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result)
|
||||
{
|
||||
UINT8 i;
|
||||
fixed_t dist, closestdist;
|
||||
|
@ -506,7 +520,7 @@ void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, v
|
|||
//
|
||||
// Given two points, create a vector between them.
|
||||
//
|
||||
vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vector3_t *a_o)
|
||||
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = point1->x - point2->x;
|
||||
a_o->y = point1->y - point2->y;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -550,11 +585,11 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin
|
|||
|
||||
*originDistance = FV3_PlaneDistance(a_normal, &a_triangle[0]);
|
||||
|
||||
distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y)
|
||||
+ FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
|
||||
distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y)
|
||||
+ FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
|
||||
|
||||
distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y)
|
||||
+ FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
|
||||
distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y)
|
||||
+ FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
|
||||
|
||||
// Positive or zero number means no intersection
|
||||
if (FixedMul(distance1, distance2) >= 0)
|
||||
|
@ -575,8 +610,8 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin
|
|||
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector)
|
||||
{
|
||||
fixed_t d = -(FV3_Dot(pNormal, pOrigin));
|
||||
fixed_t number = FV3_Dot(pNormal,rOrigin) + d;
|
||||
fixed_t denom = FV3_Dot(pNormal,rVector);
|
||||
fixed_t number = FV3_Dot(pNormal, rOrigin) + d;
|
||||
fixed_t denom = FV3_Dot(pNormal, rVector);
|
||||
return -FixedDiv(number, denom);
|
||||
}
|
||||
|
||||
|
@ -597,11 +632,11 @@ fixed_t FV3_IntersectRaySphere(const vector3_t *rO, const vector3_t *rV, const v
|
|||
|
||||
c = FV3_Magnitude(&Q);
|
||||
v = FV3_Dot(&Q, rV);
|
||||
d = FixedMul(sR, sR) - (FixedMul(c,c) - FixedMul(v,v));
|
||||
d = FixedMul(sR, sR) - (FixedMul(c, c) - FixedMul(v, v));
|
||||
|
||||
// If there was no intersection, return -1
|
||||
if (d < 0*FRACUNIT)
|
||||
return (-1*FRACUNIT);
|
||||
if (d < 0 * FRACUNIT)
|
||||
return (-1 * FRACUNIT);
|
||||
|
||||
// Return the distance to the [first] intersecting point
|
||||
return (v - FixedSqrt(d));
|
||||
|
@ -629,9 +664,9 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
|
|||
// Here I just chose a arbitrary point as the point to find that distance. You notice we negate that
|
||||
// distance. We negate the distance because we want to eventually go BACKWARDS from our point to the plane.
|
||||
// By doing this is will basically bring us back to the plane to find our intersection point.
|
||||
Numerator = - (FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line
|
||||
FixedMul(vNormal->y, vLine[0].y) +
|
||||
FixedMul(vNormal->z, vLine[0].z) + distance);
|
||||
Numerator = -(FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line
|
||||
FixedMul(vNormal->y, vLine[0].y) +
|
||||
FixedMul(vNormal->z, vLine[0].z) + distance);
|
||||
|
||||
// 3) If we take the dot product between our line vector and the normal of the polygon,
|
||||
// this will give us the cosine of the angle between the 2 (since they are both normalized - length 1).
|
||||
|
@ -643,7 +678,7 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
|
|||
// on the plane (the normal is perpendicular to the line - (Normal.Vector = 0)).
|
||||
// In this case, we should just return any point on the line.
|
||||
|
||||
if( Denominator == 0*FRACUNIT) // Check so we don't divide by zero
|
||||
if (Denominator == 0 * FRACUNIT) // Check so we don't divide by zero
|
||||
{
|
||||
ReturnVec->x = vLine[0].x;
|
||||
ReturnVec->y = vLine[0].y;
|
||||
|
@ -686,8 +721,8 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
|
|||
//
|
||||
UINT8 FV3_PointOnLineSide(const vector3_t *point, const vector3_t *line)
|
||||
{
|
||||
fixed_t s1 = FixedMul((point->y - line[0].y),(line[1].x - line[0].x));
|
||||
fixed_t s2 = FixedMul((point->x - line[0].x),(line[1].y - line[0].y));
|
||||
fixed_t s1 = FixedMul((point->y - line[0].y), (line[1].x - line[0].x));
|
||||
fixed_t s2 = FixedMul((point->x - line[0].x), (line[1].y - line[0].y));
|
||||
return (UINT8)(s1 - s2 < 0);
|
||||
}
|
||||
|
||||
|
@ -752,7 +787,7 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
|
|||
matrix->m[0] = upcross.x;
|
||||
matrix->m[1] = upcross.y;
|
||||
matrix->m[2] = upcross.z;
|
||||
matrix->m[3] = 0*FRACUNIT;
|
||||
matrix->m[3] = 0 * FRACUNIT;
|
||||
|
||||
matrix->m[4] = upx;
|
||||
matrix->m[5] = upy;
|
||||
|
@ -764,9 +799,9 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
|
|||
matrix->m[10] = anglez;
|
||||
matrix->m[11] = 0;
|
||||
|
||||
matrix->m[12] = x - FixedMul(upx,radius);
|
||||
matrix->m[13] = y - FixedMul(upy,radius);
|
||||
matrix->m[14] = z - FixedMul(upz,radius);
|
||||
matrix->m[12] = x - FixedMul(upx, radius);
|
||||
matrix->m[13] = y - FixedMul(upy, radius);
|
||||
matrix->m[14] = z - FixedMul(upz, radius);
|
||||
matrix->m[15] = FRACUNIT;
|
||||
}
|
||||
|
||||
|
@ -778,20 +813,20 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
|
|||
void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out)
|
||||
{
|
||||
#define M(row,col) matrix->m[col * 4 + row]
|
||||
out->x = FixedMul(vec->x,M(0, 0))
|
||||
+ FixedMul(vec->y,M(0, 1))
|
||||
+ FixedMul(vec->z,M(0, 2))
|
||||
+ M(0, 3);
|
||||
out->x = FixedMul(vec->x, M(0, 0))
|
||||
+ FixedMul(vec->y, M(0, 1))
|
||||
+ FixedMul(vec->z, M(0, 2))
|
||||
+ M(0, 3);
|
||||
|
||||
out->y = FixedMul(vec->x,M(1, 0))
|
||||
+ FixedMul(vec->y,M(1, 1))
|
||||
+ FixedMul(vec->z,M(1, 2))
|
||||
+ M(1, 3);
|
||||
out->y = FixedMul(vec->x, M(1, 0))
|
||||
+ FixedMul(vec->y, M(1, 1))
|
||||
+ FixedMul(vec->z, M(1, 2))
|
||||
+ M(1, 3);
|
||||
|
||||
out->z = FixedMul(vec->x,M(2, 0))
|
||||
+ FixedMul(vec->y,M(2, 1))
|
||||
+ FixedMul(vec->z,M(2, 2))
|
||||
+ M(2, 3);
|
||||
out->z = FixedMul(vec->x, M(2, 0))
|
||||
+ FixedMul(vec->y, M(2, 1))
|
||||
+ FixedMul(vec->z, M(2, 2))
|
||||
+ M(2, 3);
|
||||
#undef M
|
||||
}
|
||||
|
||||
|
@ -811,7 +846,7 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme)
|
|||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
R(i, j) = FixedMul(D(i, 0),M(0, j)) + FixedMul(D(i, 1),M(1, j)) + FixedMul(D(i, 2),M(2, j)) + FixedMul(D(i, 3),M(3, j));
|
||||
R(i, j) = FixedMul(D(i, 0), M(0, j)) + FixedMul(D(i, 1), M(1, j)) + FixedMul(D(i, 2), M(2, j)) + FixedMul(D(i, 3), M(3, j));
|
||||
}
|
||||
|
||||
M_Memcpy(dest, &result, sizeof(matrix_t));
|
||||
|
@ -869,8 +904,8 @@ void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z)
|
|||
|
||||
static inline void M_print(INT64 a)
|
||||
{
|
||||
const fixed_t w = (a>>FRACBITS);
|
||||
fixed_t f = a%FRACUNIT;
|
||||
const fixed_t w = (a >> FRACBITS);
|
||||
fixed_t f = a % FRACUNIT;
|
||||
fixed_t d = FRACUNIT;
|
||||
|
||||
if (f == 0)
|
||||
|
@ -878,7 +913,7 @@ static inline void M_print(INT64 a)
|
|||
printf("%d", (fixed_t)w);
|
||||
return;
|
||||
}
|
||||
else while (f != 1 && f/2 == f>>1)
|
||||
else while (f != 1 && f / 2 == f >> 1)
|
||||
{
|
||||
d /= 2;
|
||||
f /= 2;
|
||||
|
@ -892,7 +927,7 @@ static inline void M_print(INT64 a)
|
|||
|
||||
FUNCMATH FUNCINLINE static inline fixed_t FixedMulC(fixed_t a, fixed_t b)
|
||||
{
|
||||
return (fixed_t)((((INT64)a * b) ) / FRACUNIT);
|
||||
return (fixed_t)((((INT64)a * b)) / FRACUNIT);
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
|
||||
|
@ -902,7 +937,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
|
|||
if (b == 0)
|
||||
I_Error("FixedDiv: divide by zero");
|
||||
|
||||
ret = (((INT64)a * FRACUNIT) ) / b;
|
||||
ret = (((INT64)a * FRACUNIT)) / b;
|
||||
|
||||
if ((ret > INT32_MAX) || (ret < INT32_MIN))
|
||||
I_Error("FixedDiv: divide by zero");
|
||||
|
@ -911,7 +946,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
|
|||
|
||||
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC(fixed_t a, fixed_t b)
|
||||
{
|
||||
if ((abs(a) >> (FRACBITS-2)) >= abs(b))
|
||||
if ((abs(a) >> (FRACBITS - 2)) >= abs(b))
|
||||
return (a^b) < 0 ? INT32_MIN : INT32_MAX;
|
||||
|
||||
return FixedDivC2(a, b);
|
||||
|
@ -938,43 +973,43 @@ int main(int argc, char** argv)
|
|||
|
||||
#ifdef MULDIV_TEST
|
||||
for (a = 1; a <= INT32_MAX; a += FRACUNIT)
|
||||
for (b = 0; b <= INT32_MAX; b += FRACUNIT)
|
||||
{
|
||||
c = FixedMul(a, b);
|
||||
d = FixedMulC(a, b);
|
||||
if (c != d)
|
||||
for (b = 0; b <= INT32_MAX; b += FRACUNIT)
|
||||
{
|
||||
printf("(");
|
||||
M_print(a);
|
||||
printf(") * (");
|
||||
M_print(b);
|
||||
printf(") = (");
|
||||
M_print(c);
|
||||
printf(") != (");
|
||||
M_print(d);
|
||||
printf(") \n");
|
||||
n--;
|
||||
printf("%d != %d\n", c, d);
|
||||
c = FixedMul(a, b);
|
||||
d = FixedMulC(a, b);
|
||||
if (c != d)
|
||||
{
|
||||
printf("(");
|
||||
M_print(a);
|
||||
printf(") * (");
|
||||
M_print(b);
|
||||
printf(") = (");
|
||||
M_print(c);
|
||||
printf(") != (");
|
||||
M_print(d);
|
||||
printf(") \n");
|
||||
n--;
|
||||
printf("%d != %d\n", c, d);
|
||||
}
|
||||
c = FixedDiv(a, b);
|
||||
d = FixedDivC(a, b);
|
||||
if (c != d)
|
||||
{
|
||||
printf("(");
|
||||
M_print(a);
|
||||
printf(") / (");
|
||||
M_print(b);
|
||||
printf(") = (");
|
||||
M_print(c);
|
||||
printf(") != (");
|
||||
M_print(d);
|
||||
printf(")\n");
|
||||
n--;
|
||||
printf("%d != %d\n", c, d);
|
||||
}
|
||||
if (n <= 0)
|
||||
exit(-1);
|
||||
}
|
||||
c = FixedDiv(a, b);
|
||||
d = FixedDivC(a, b);
|
||||
if (c != d)
|
||||
{
|
||||
printf("(");
|
||||
M_print(a);
|
||||
printf(") / (");
|
||||
M_print(b);
|
||||
printf(") = (");
|
||||
M_print(c);
|
||||
printf(") != (");
|
||||
M_print(d);
|
||||
printf(")\n");
|
||||
n--;
|
||||
printf("%d != %d\n", c, d);
|
||||
}
|
||||
if (n <= 0)
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQRT_TEST
|
||||
|
@ -982,7 +1017,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
c = FixedSqrt(a);
|
||||
d = FixedSqrtC(a);
|
||||
b = abs(c-d);
|
||||
b = abs(c - d);
|
||||
if (b > 1)
|
||||
{
|
||||
printf("sqrt(");
|
||||
|
|
|
@ -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);
|
||||
|
|
1113
src/m_menu.c
1113
src/m_menu.c
File diff suppressed because it is too large
Load diff
31
src/m_menu.h
31
src/m_menu.h
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
662
src/p_enemy.c
662
src/p_enemy.c
|
@ -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);
|
||||
strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7);
|
||||
mapmusname[6] = 0;
|
||||
mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET;
|
||||
mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos;
|
||||
// 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)
|
||||
{
|
||||
|
@ -4763,8 +4777,17 @@ void A_FishJump(mobj_t *actor)
|
|||
|
||||
if (locvar2)
|
||||
{
|
||||
fixed_t rad = actor->radius>>FRACBITS;
|
||||
P_SpawnMobjFromMobj(actor, P_RandomRange(rad, -rad)<<FRACBITS, P_RandomRange(rad, -rad)<<FRACBITS, 0, (mobjtype_t)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,59 +5020,186 @@ 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->target)
|
||||
|
||||
if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins)
|
||||
return;
|
||||
|
||||
if (!actor->target->player)
|
||||
return;
|
||||
|
||||
skin = &skins[actor->target->player->skin];
|
||||
|
||||
if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
|
||||
// if no face overlay, spawn one
|
||||
if (actor->tracer->tracer == NULL || P_MobjWasRemoved(actor->tracer->tracer))
|
||||
{
|
||||
actor->color = skin->prefoppositecolor;
|
||||
/*
|
||||
If you're here from the comment above Color_Opposite,
|
||||
the following line is the one which is dependent on the
|
||||
array being symmetrical. It gets the opposite of the
|
||||
opposite of your desired colour just so it can get the
|
||||
brightness frame for the End Sign. It's not a great
|
||||
design choice, but it's constant time array access and
|
||||
the idea that the colours should be OPPOSITES is kind
|
||||
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]);
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
if (skin->sprites[SPR2_SIGN].numframes)
|
||||
{
|
||||
// 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;
|
||||
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;
|
||||
|
||||
if (!actor->target->player)
|
||||
return;
|
||||
|
||||
skin = &skins[actor->target->player->skin];
|
||||
facecolor = actor->target->player->skincolor;
|
||||
|
||||
if (signcolor)
|
||||
;
|
||||
else if ((actor->target->player->skincolor == skin->prefcolor) && (skin->prefoppositecolor)) // Set it as the skin's preferred oppositecolor?
|
||||
{
|
||||
signcolor = skin->prefoppositecolor;
|
||||
/*
|
||||
If you're here from the comment above Color_Opposite,
|
||||
the following line is the one which is dependent on the
|
||||
array being symmetrical. It gets the opposite of the
|
||||
opposite of your desired colour just so it can get the
|
||||
brightness frame for the End Sign. It's not a great
|
||||
design choice, but it's constant time array access and
|
||||
the idea that the colours should be OPPOSITES is kind
|
||||
of in the name. If you have a better idea, feel free
|
||||
to let me know. ~toast 2016/07/20
|
||||
*/
|
||||
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.
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
facecolor = skin->prefcolor;
|
||||
if (signcolor)
|
||||
;
|
||||
else if (skin->prefoppositecolor)
|
||||
{
|
||||
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,20 +5493,22 @@ static mobj_t *minus;
|
|||
|
||||
static boolean PIT_MinusCarry(mobj_t *thing)
|
||||
{
|
||||
if (minus->tracer)
|
||||
return true;
|
||||
|
||||
if (minus->type == thing->type)
|
||||
return true;
|
||||
|
||||
if (!(thing->flags & MF_SHOOTABLE) || !(thing->flags & MF_ENEMY))
|
||||
if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY)))
|
||||
return true;
|
||||
|
||||
if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius * 3)
|
||||
if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius*3)
|
||||
return true;
|
||||
|
||||
if (abs(thing->z - minus->z) > minus->height)
|
||||
return true;
|
||||
|
||||
P_SetTarget(&minus->tracer, thing);
|
||||
minus->tracer->flags &= ~MF_PUSHABLE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -5420,6 +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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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 (playeronme)
|
||||
if (raise->vars[9]) // Dynamically Sinking Platform^tm
|
||||
{
|
||||
#define shaketime 10
|
||||
if (raise->vars[11] > shaketime) // State: moving
|
||||
{
|
||||
if (playeronme) // If player is standing on the platform, accelerate
|
||||
{
|
||||
raise->vars[10] += (FRACUNIT >> 5);
|
||||
}
|
||||
else // otherwise, decelerate until inflection
|
||||
{
|
||||
raise->vars[10] -= FRACUNIT >> 3;
|
||||
if (raise->vars[10] <= 0) // inflection!
|
||||
{
|
||||
raise->vars[10] = 0;
|
||||
raise->vars[11] = 0; // allow the shake to occur again (fucks over players attempting to jump-cheese)
|
||||
}
|
||||
}
|
||||
active = raise->vars[10] > 0;
|
||||
}
|
||||
else // State: shaking
|
||||
{
|
||||
if (playeronme || raise->vars[11])
|
||||
{
|
||||
active = true;
|
||||
if (++raise->vars[11] > shaketime)
|
||||
{
|
||||
if (playeronme)
|
||||
raise->vars[10] = FRACUNIT >> 5;
|
||||
else
|
||||
raise->vars[10] = FRACUNIT << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
raise->vars[10] = ((shaketime/2) - raise->vars[11]) << FRACBITS;
|
||||
if (raise->vars[10] < -raise->vars[2]/2)
|
||||
raise->vars[10] = -raise->vars[2]/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef shaketime
|
||||
}
|
||||
else // Air bobbing platform (not a Dynamically Sinking Platform^tm)
|
||||
active = playeronme;
|
||||
|
||||
if (active)
|
||||
{
|
||||
raise->vars[3] = raise->vars[2];
|
||||
|
||||
|
@ -2553,6 +2599,8 @@ void T_RaiseSector(levelspecthink_t *raise)
|
|||
raise->vars[3] = origspeed;
|
||||
}
|
||||
|
||||
raise->vars[3] += raise->vars[10];
|
||||
|
||||
res = T_MovePlane
|
||||
(
|
||||
raise->sector, // sector
|
||||
|
|
|
@ -428,7 +428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|| special->state == &states[S_FANG_BOUNCE4]
|
||||
|| special->state == &states[S_FANG_PINCHBOUNCE3]
|
||||
|| special->state == &states[S_FANG_PINCHBOUNCE4])
|
||||
&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > -(special->height/4))
|
||||
&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > (special->height/4))
|
||||
{
|
||||
P_DamageMobj(toucher, special, special, 1, 0);
|
||||
P_SetTarget(&special->tracer, toucher);
|
||||
|
@ -450,12 +450,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case MT_PYREFLY:
|
||||
if (special->extravalue2 == 2 && P_DamageMobj(player->mo, special, special, 1, DMG_FIRE))
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object?
|
||||
{
|
||||
if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1)
|
||||
return; // Can't hurt a Pterabyte if it's trying to pick you up
|
||||
|
||||
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
|
||||
{
|
||||
if (elementalpierce == 2)
|
||||
|
@ -471,13 +477,29 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
toucher->momy = -toucher->momy;
|
||||
if (player->charability == CA_FLY && player->panim == PA_ABILITY)
|
||||
toucher->momz = -toucher->momz/2;
|
||||
else if (player->pflags & PF_GLIDING && !P_IsObjectOnGround(toucher))
|
||||
{
|
||||
player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE);
|
||||
P_SetPlayerMobjState(toucher, S_PLAY_FALL);
|
||||
toucher->momz += P_MobjFlip(toucher) * (player->speed >> 3);
|
||||
toucher->momx = 7*toucher->momx>>3;
|
||||
toucher->momy = 7*toucher->momy>>3;
|
||||
}
|
||||
else if (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
|
||||
&& player->panim == PA_DASH)
|
||||
P_DoPlayerPain(player, special, special);
|
||||
}
|
||||
P_DamageMobj(special, toucher, toucher, 1, 0);
|
||||
if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)
|
||||
P_TwinSpinRejuvenate(player, player->thokitem);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (special->type == MT_PTERABYTE && special->target == player->mo)
|
||||
return; // Don't hurt the player you're trying to grab
|
||||
|
||||
P_DamageMobj(toucher, special, special, 1, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
|
|
@ -303,7 +303,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
|
|||
|
||||
boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
|
||||
boolean P_CheckDeathPitCollide(mobj_t *mo);
|
||||
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover);
|
||||
boolean P_CheckSolidLava(ffloor_t *rover);
|
||||
void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype);
|
||||
|
||||
mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type);
|
||||
|
|
322
src/p_map.c
322
src/p_map.c
|
@ -124,6 +124,7 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
|||
// Positive spring modes are minor variants of vanilla spring behaviour.
|
||||
// 1 = launch players in jump
|
||||
// 2 = don't modify player at all, just add momentum
|
||||
// 3 = speed-booster mode (force onto ground, MF_AMBUSH causes auto-spin)
|
||||
// Negative spring modes are mildly-related gimmicks with customisation.
|
||||
// -1 = pinball bumper
|
||||
// Any other spring mode defaults to standard vanilla spring behaviour,
|
||||
|
@ -151,7 +152,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
|
||||
if (object->player)
|
||||
{
|
||||
if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
|
||||
if (spring->info->painchance == 3)
|
||||
;
|
||||
else if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
|
||||
strong = 1;
|
||||
else if (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2)
|
||||
strong = 2;
|
||||
|
@ -208,7 +211,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
{
|
||||
angle_t nightsangle = 0;
|
||||
|
||||
if (object->player->bumpertime >= TICRATE/4)
|
||||
if (object->player->bumpertime > (TICRATE/2)-5)
|
||||
return false;
|
||||
|
||||
if ((object->player->pflags & PF_TRANSFERTOCLOSEST) && object->player->axis1 && object->player->axis2)
|
||||
|
@ -286,7 +289,27 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
if (spring->info->painchance != 2)
|
||||
{
|
||||
if (object->player)
|
||||
{
|
||||
object->player->pflags &= ~PF_APPLYAUTOBRAKE;
|
||||
#ifndef SPRINGSPIN
|
||||
object->player->powers[pw_justsprung] = 5;
|
||||
if (horizspeed)
|
||||
object->player->powers[pw_noautobrake] = ((horizspeed*TICRATE)>>(FRACBITS+3))/9; // TICRATE at 72*FRACUNIT
|
||||
else if (P_MobjFlip(object) == P_MobjFlip(spring))
|
||||
object->player->powers[pw_justsprung] |= (1<<15);
|
||||
#else
|
||||
object->player->powers[pw_justsprung] = 15;
|
||||
if (horizspeed)
|
||||
object->player->powers[pw_noautobrake] = ((horizspeed*TICRATE)>>(FRACBITS+3))/9; // TICRATE at 72*FRACUNIT
|
||||
else
|
||||
{
|
||||
if (abs(object->player->rmomx) > object->scale || abs(object->player->rmomy) > object->scale)
|
||||
object->player->drawangle = R_PointToAngle2(0, 0, object->player->rmomx, object->player->rmomy);
|
||||
if (P_MobjFlip(object) == P_MobjFlip(spring))
|
||||
object->player->powers[pw_justsprung] |= (1<<15);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((horizspeed && vertispeed) || (object->player && object->player->homing)) // Mimic SA
|
||||
{
|
||||
|
@ -321,6 +344,14 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
|
||||
// Set position!
|
||||
P_TryMove(object, spring->x + offx, spring->y + offy, true);
|
||||
|
||||
if ((spring->info->painchance == 3))
|
||||
{
|
||||
object->z = spring->z;
|
||||
if (spring->eflags & MFE_VERTICALFLIP)
|
||||
object->z -= object->height;
|
||||
object->momz = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,8 +375,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
|
||||
if (horizspeed)
|
||||
{
|
||||
object->player->drawangle = spring->angle;
|
||||
object->angle = spring->angle;
|
||||
object->angle = object->player->drawangle = spring->angle;
|
||||
|
||||
if (!demoplayback || P_AnalogMove(object->player))
|
||||
{
|
||||
|
@ -356,11 +386,25 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
}
|
||||
}
|
||||
|
||||
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these.
|
||||
secondjump = object->player->secondjump;
|
||||
washoming = object->player->homing;
|
||||
if (object->player->pflags & PF_GLIDING)
|
||||
P_SetPlayerMobjState(object, S_PLAY_FALL);
|
||||
if ((spring->info->painchance == 3))
|
||||
{
|
||||
if (!(pflags = (object->player->pflags & PF_SPINNING)) &&
|
||||
(((object->player->charability2 == CA2_SPINDASH) && (object->player->cmd.buttons & BT_USE))
|
||||
|| (spring->flags2 & MF2_AMBUSH)))
|
||||
{
|
||||
pflags = PF_SPINNING;
|
||||
P_SetPlayerMobjState(object, S_PLAY_ROLL);
|
||||
S_StartSound(object, sfx_spin);
|
||||
}
|
||||
else
|
||||
P_SetPlayerMobjState(object, S_PLAY_ROLL);
|
||||
}
|
||||
else
|
||||
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these.
|
||||
secondjump = object->player->secondjump;
|
||||
washoming = object->player->homing;
|
||||
P_ResetPlayer(object->player);
|
||||
|
||||
if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities.
|
||||
|
@ -368,7 +412,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
object->player->pflags |= P_GetJumpFlags(object->player);
|
||||
P_SetPlayerMobjState(object, S_PLAY_JUMP);
|
||||
}
|
||||
else if ((spring->info->painchance == 2) || (pflags & PF_BOUNCING)) // Adding momentum only.
|
||||
else if ((spring->info->painchance == 2) || ((spring->info->painchance != 3) && (pflags & PF_BOUNCING))) // Adding momentum only.
|
||||
{
|
||||
object->player->pflags |= (pflags &~ PF_STARTJUMP);
|
||||
object->player->secondjump = secondjump;
|
||||
|
@ -382,6 +426,10 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
object->player->pflags |= pflags;
|
||||
object->player->secondjump = secondjump;
|
||||
}
|
||||
else if (object->player->dashmode >= 3*TICRATE)
|
||||
P_SetPlayerMobjState(object, S_PLAY_DASH);
|
||||
else if (P_IsObjectOnGround(object) && horizspeed >= FixedMul(object->player->runspeed, object->scale))
|
||||
P_SetPlayerMobjState(object, S_PLAY_RUN);
|
||||
else
|
||||
P_SetPlayerMobjState(object, S_PLAY_WALK);
|
||||
}
|
||||
|
@ -490,6 +538,42 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
|
|||
}
|
||||
}
|
||||
|
||||
static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera)
|
||||
{
|
||||
if (player->powers[pw_carry] && 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,41 +1005,73 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
}
|
||||
}
|
||||
|
||||
if (thing->type == MT_TNTBARREL && tmthing->player)
|
||||
if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
|
||||
{
|
||||
if (tmthing->momz < 0)
|
||||
{
|
||||
if (tmthing->z + tmthing->momz > thing->z + thing->height)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tmthing->momz > 0)
|
||||
{
|
||||
if (tmthing->z + tmthing->height + tmthing->momz < thing->z)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((tmthing->player->pflags & (PF_SPINNING | PF_GLIDING))
|
||||
|| ((tmthing->player->pflags & PF_JUMPED)
|
||||
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|
||||
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|
||||
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|
||||
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
|
||||
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height / 2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|
||||
|| (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)))
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
|
||||
if ((thing->flags & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (thing->type == MT_ROLLOUTROCK && tmthing->player && tmthing->health)
|
||||
{
|
||||
if (tmthing->player->powers[pw_carry] == CR_ROLLOUT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ((thing->flags & MF_PUSHABLE) // not carrying a player
|
||||
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
|
||||
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
|
||||
&& (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius))
|
||||
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0)
|
||||
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|
||||
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
|
||||
{
|
||||
thing->flags &= ~MF_PUSHABLE; // prevent riding player from applying pushable movement logic
|
||||
thing->flags2 &= ~MF2_DONTDRAW; // don't leave the rock invisible if it was flashing prior to boarding
|
||||
P_SetTarget(&thing->tracer, tmthing);
|
||||
P_ResetPlayer(tmthing->player);
|
||||
P_SetPlayerMobjState(tmthing, S_PLAY_WALK);
|
||||
tmthing->player->powers[pw_carry] = CR_ROLLOUT;
|
||||
P_SetTarget(&tmthing->tracer, thing);
|
||||
P_SetObjectMomZ(thing, tmthing->momz, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (tmthing->type == MT_ROLLOUTROCK)
|
||||
{
|
||||
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !thing->health)
|
||||
return true;
|
||||
|
||||
if (thing == tmthing->tracer) // don't collide with rider
|
||||
return true;
|
||||
|
||||
if (thing->flags & MF_SPRING) // bounce on springs
|
||||
{
|
||||
P_DoSpring(thing, tmthing);
|
||||
return true;
|
||||
}
|
||||
else if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) == (MF_MONITOR|MF_SHOOTABLE) && !(tmthing->flags & MF_PUSHABLE)) // pop monitors while carrying a player
|
||||
{
|
||||
P_KillMobj(thing, tmthing, tmthing->tracer, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (thing->type == tmthing->type // bounce against other rollout rocks
|
||||
&& (tmthing->momx || tmthing->momy || thing->momx || thing->momy))
|
||||
{
|
||||
fixed_t tempmomx = thing->momx, tempmomy = thing->momy;
|
||||
thing->momx = tmthing->momx;
|
||||
thing->momy = tmthing->momy;
|
||||
tmthing->momx = tempmomx;
|
||||
tmthing->momy = tempmomy;
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->type == MT_PTERABYTE && tmthing->player)
|
||||
P_DoPterabyteCarry(tmthing->player, thing);
|
||||
|
||||
if (thing->type == MT_TNTBARREL && tmthing->player)
|
||||
P_PlayerBarrelCollide(tmthing, thing);
|
||||
|
||||
if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE)
|
||||
{
|
||||
fixed_t dx = thing->x - tmthing->x;
|
||||
|
@ -1560,8 +1712,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
}
|
||||
}
|
||||
|
||||
if ((!tmthing->player) && (thing->player))
|
||||
; // no solid thing should ever be able to step up onto a player
|
||||
if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM) && (thing->player))
|
||||
; // springs and gas jets should never be able to step up onto a player
|
||||
// z checking at last
|
||||
// Treat noclip things as non-solid!
|
||||
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
|
||||
|
@ -1964,7 +2116,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover)))
|
||||
if (thing->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(thing->player, rover)))
|
||||
;
|
||||
else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))
|
||||
;
|
||||
|
@ -2629,8 +2781,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
|||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
#ifdef ESLOPE
|
||||
// HACK TO FIX DSZ2: apply only if slopes are involved
|
||||
else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
|
||||
else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
|
||||
{
|
||||
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
|
||||
thing->ceilingrover = tmceilingrover;
|
||||
|
@ -2645,8 +2796,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
|||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
#ifdef ESLOPE
|
||||
// HACK TO FIX DSZ2: apply only if slopes are involved
|
||||
else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
|
||||
else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
|
||||
{
|
||||
thing->z = thing->floorz = tmfloorz;
|
||||
thing->floorrover = tmfloorrover;
|
||||
|
@ -3334,13 +3484,13 @@ isblocking:
|
|||
&& canclimb)
|
||||
{
|
||||
slidemo->angle = climbangle;
|
||||
if (!demoplayback || P_AnalogMove(slidemo->player))
|
||||
/*if (!demoplayback || P_AnalogMove(slidemo->player))
|
||||
{
|
||||
if (slidemo->player == &players[consoleplayer])
|
||||
localangle = slidemo->angle;
|
||||
else if (slidemo->player == &players[secondarydisplayplayer])
|
||||
localangle2 = slidemo->angle;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!slidemo->player->climbing)
|
||||
{
|
||||
|
@ -3479,6 +3629,64 @@ stairstep:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t topheight, bottomheight;
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS))
|
||||
continue;
|
||||
|
||||
if (!(rover->flags & FF_SWIMMABLE))
|
||||
continue;
|
||||
|
||||
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3)
|
||||
continue;
|
||||
|
||||
if (rover->master->flags & ML_BLOCKMONSTERS)
|
||||
continue;
|
||||
|
||||
topheight =
|
||||
#ifdef ESLOPE
|
||||
*rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) :
|
||||
#endif
|
||||
*rover->topheight;
|
||||
|
||||
if (mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
if (topheight < mo->z - mo->height)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (topheight < mo->z)
|
||||
continue;
|
||||
}
|
||||
|
||||
bottomheight =
|
||||
#ifdef ESLOPE
|
||||
*rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) :
|
||||
#endif
|
||||
*rover->bottomheight;
|
||||
|
||||
if (mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
if (bottomheight > mo->z)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bottomheight > mo->z + mo->height)
|
||||
continue;
|
||||
}
|
||||
|
||||
P_DamageMobj(mo, NULL, NULL, 1, DMG_FIRE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_SlideMove
|
||||
// The momx / momy move is bad, so try to slide
|
||||
|
@ -3639,6 +3847,12 @@ retry:
|
|||
P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy,
|
||||
PT_ADDLINES, PTR_SlideTraverse);
|
||||
|
||||
if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff)
|
||||
{
|
||||
sector_t *sec = P_PointOnLineSide(mo->x, mo->y, bestslideline) ? bestslideline->frontsector : bestslideline->backsector;
|
||||
P_CheckLavaWall(mo, sec);
|
||||
}
|
||||
|
||||
// Some walls are bouncy even if you're not
|
||||
if (bestslideline && bestslideline->flags & ML_BOUNCY)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
986
src/p_mobj.c
986
src/p_mobj.c
File diff suppressed because it is too large
Load diff
10
src/p_mobj.h
10
src/p_mobj.h
|
@ -233,15 +233,17 @@ typedef enum
|
|||
MFE_VERTICALFLIP = 1<<5,
|
||||
// Goo water
|
||||
MFE_GOOWATER = 1<<6,
|
||||
// The mobj is touching a lava block
|
||||
MFE_TOUCHLAVA = 1<<7,
|
||||
// Mobj was already pushed this tic
|
||||
MFE_PUSHED = 1<<7,
|
||||
MFE_PUSHED = 1<<8,
|
||||
// Mobj was already sprung this tic
|
||||
MFE_SPRUNG = 1<<8,
|
||||
MFE_SPRUNG = 1<<9,
|
||||
// Platform movement
|
||||
MFE_APPLYPMOMZ = 1<<9,
|
||||
MFE_APPLYPMOMZ = 1<<10,
|
||||
// Compute and trigger on mobj angle relative to tracer
|
||||
// See Linedef Exec 457 (Track mobj angle to point)
|
||||
MFE_TRACERANGLE = 1<<10,
|
||||
MFE_TRACERANGLE = 1<<11,
|
||||
// free: to and including 1<<15
|
||||
} mobjeflag_t;
|
||||
|
||||
|
|
|
@ -3618,7 +3618,7 @@ static void P_NetUnArchiveThinkers(void)
|
|||
{
|
||||
executor_t *delay = NULL;
|
||||
UINT32 mobjnum;
|
||||
for (currentthinker = thlist[i].next; currentthinker != &thlist[i];
|
||||
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN];
|
||||
currentthinker = currentthinker->next)
|
||||
{
|
||||
if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue