Merge branch 'next' of https://github.com/STJr/SRB2 into text-color

This commit is contained in:
Zippy_Zolton 2020-12-14 00:16:38 -06:00
commit c247b94be7
147 changed files with 20390 additions and 17478 deletions

View File

@ -13,6 +13,9 @@ set(SRB2_CORE_SOURCES
d_netcmd.c d_netcmd.c
d_netfil.c d_netfil.c
dehacked.c dehacked.c
deh_soc.c
deh_lua.c
deh_tables.c
f_finale.c f_finale.c
f_wipe.c f_wipe.c
filesrch.c filesrch.c
@ -66,6 +69,9 @@ set(SRB2_CORE_HEADERS
d_think.h d_think.h
d_ticcmd.h d_ticcmd.h
dehacked.h dehacked.h
deh_soc.h
deh_lua.h
deh_tables.h
doomdata.h doomdata.h
doomdef.h doomdef.h
doomstat.h doomstat.h
@ -130,6 +136,8 @@ set(SRB2_CORE_RENDER_SOURCES
r_splats.c r_splats.c
r_things.c r_things.c
r_textures.c r_textures.c
r_patch.c
r_patchrotation.c
r_picformats.c r_picformats.c
r_portal.c r_portal.c
@ -147,6 +155,8 @@ set(SRB2_CORE_RENDER_SOURCES
r_state.h r_state.h
r_things.h r_things.h
r_textures.h r_textures.h
r_patch.h
r_patchrotation.h
r_picformats.h r_picformats.h
r_portal.h r_portal.h
) )
@ -169,6 +179,7 @@ set(SRB2_CORE_GAME_SOURCES
p_telept.c p_telept.c
p_tick.c p_tick.c
p_user.c p_user.c
taglist.c
p_local.h p_local.h
p_maputl.h p_maputl.h
@ -180,6 +191,7 @@ set(SRB2_CORE_GAME_SOURCES
p_slopes.h p_slopes.h
p_spec.h p_spec.h
p_tick.h p_tick.h
taglist.h
) )
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
@ -232,7 +244,9 @@ set(SRB2_CONFIG_HAVE_GME ON CACHE BOOL
set(SRB2_CONFIG_HAVE_OPENMPT ON CACHE BOOL set(SRB2_CONFIG_HAVE_OPENMPT ON CACHE BOOL
"Enable OpenMPT support.") "Enable OpenMPT support.")
set(SRB2_CONFIG_HAVE_CURL ON CACHE BOOL set(SRB2_CONFIG_HAVE_CURL ON CACHE BOOL
"Enable curl support, used for downloading files via HTTP.") "Enable curl support.")
set(SRB2_CONFIG_HAVE_THREADS ON CACHE BOOL
"Enable multithreading support.")
if(${CMAKE_SYSTEM} MATCHES Windows) if(${CMAKE_SYSTEM} MATCHES Windows)
set(SRB2_CONFIG_HAVE_MIXERX ON CACHE BOOL set(SRB2_CONFIG_HAVE_MIXERX ON CACHE BOOL
"Enable SDL Mixer X support.") "Enable SDL Mixer X support.")
@ -456,7 +470,7 @@ endif()
if(${SRB2_CONFIG_HAVE_CURL}) if(${SRB2_CONFIG_HAVE_CURL})
if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES})
set(CURL_FOUND ON) set(CURL_FOUND ON)
set(CURL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/curl) set(CURL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/curl/include)
if(${SRB2_SYSTEM_BITS} EQUAL 64) if(${SRB2_SYSTEM_BITS} EQUAL 64)
set(CURL_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/curl/lib64 -lcurl") set(CURL_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/curl/lib64 -lcurl")
else() # 32-bit else() # 32-bit
@ -473,6 +487,12 @@ if(${SRB2_CONFIG_HAVE_CURL})
endif() endif()
endif() endif()
if(${SRB2_CONFIG_HAVE_THREADS})
set(SRB2_HAVE_THREADS ON)
set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/i_threads.h)
add_definitions(-DHAVE_THREADS)
endif()
if(${SRB2_CONFIG_HWRENDER}) if(${SRB2_CONFIG_HWRENDER})
add_definitions(-DHWRENDER) add_definitions(-DHWRENDER)
set(SRB2_HWRENDER_SOURCES set(SRB2_HWRENDER_SOURCES
@ -544,6 +564,7 @@ if(${SRB2_CONFIG_USEASM})
endif() endif()
set(SRB2_USEASM ON) set(SRB2_USEASM ON)
add_definitions(-DUSEASM) add_definitions(-DUSEASM)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse")
else() else()
set(SRB2_USEASM OFF) set(SRB2_USEASM OFF)
add_definitions(-DNONX86 -DNORUSEASM) add_definitions(-DNONX86 -DNORUSEASM)

View File

@ -13,8 +13,7 @@
# -DHAVE_SDL -> use for the SDL interface # -DHAVE_SDL -> use for the SDL interface
# #
# Sets: # Sets:
# Compile the DirectX/Mingw version with 'make MINGW=1' # Compile the SDL/Mingw version with 'make MINGW=1'
# Compile the SDL/Mingw version with 'make MINGW=1 SDL=1'
# Compile the SDL/Linux version with 'make LINUX=1' # Compile the SDL/Linux version with 'make LINUX=1'
# Compile the SDL/Solaris version with 'make SOLARIS=1' # Compile the SDL/Solaris version with 'make SOLARIS=1'
# Compile the SDL/FreeBSD version with 'gmake FREEBSD=1' # Compile the SDL/FreeBSD version with 'gmake FREEBSD=1'
@ -103,7 +102,6 @@ ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
# go for a 32-bit sdl mingw exe by default # go for a 32-bit sdl mingw exe by default
MINGW=1 MINGW=1
SDL=1
WINDOWSHELL=1 WINDOWSHELL=1
else # if you on the *nix else # if you on the *nix
@ -277,7 +275,7 @@ OPTS += -DCOMPVERSION
ifndef NONX86 ifndef NONX86
ifndef GCC29 ifndef GCC29
ARCHOPTS?=-march=pentium ARCHOPTS?=-msse3 -mfpmath=sse
else else
ARCHOPTS?=-mpentium ARCHOPTS?=-mpentium
endif endif
@ -465,6 +463,9 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/d_netfil.o \ $(OBJDIR)/d_netfil.o \
$(OBJDIR)/d_netcmd.o \ $(OBJDIR)/d_netcmd.o \
$(OBJDIR)/dehacked.o \ $(OBJDIR)/dehacked.o \
$(OBJDIR)/deh_soc.o \
$(OBJDIR)/deh_lua.o \
$(OBJDIR)/deh_tables.o \
$(OBJDIR)/z_zone.o \ $(OBJDIR)/z_zone.o \
$(OBJDIR)/f_finale.o \ $(OBJDIR)/f_finale.o \
$(OBJDIR)/f_wipe.o \ $(OBJDIR)/f_wipe.o \
@ -519,9 +520,12 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_splats.o \ $(OBJDIR)/r_splats.o \
$(OBJDIR)/r_things.o \ $(OBJDIR)/r_things.o \
$(OBJDIR)/r_textures.o \ $(OBJDIR)/r_textures.o \
$(OBJDIR)/r_patch.o \
$(OBJDIR)/r_patchrotation.o \
$(OBJDIR)/r_picformats.o \ $(OBJDIR)/r_picformats.o \
$(OBJDIR)/r_portal.o \ $(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \ $(OBJDIR)/screen.o \
$(OBJDIR)/taglist.o \
$(OBJDIR)/v_video.o \ $(OBJDIR)/v_video.o \
$(OBJDIR)/s_sound.o \ $(OBJDIR)/s_sound.o \
$(OBJDIR)/sounds.o \ $(OBJDIR)/sounds.o \
@ -538,6 +542,15 @@ OBJS:=$(i_main_o) \
$(i_sound_o) \ $(i_sound_o) \
$(OBJS) $(OBJS)
ifndef ECHO
ifndef NOECHOFILENAMES
define echoName =
@echo -- $< ...
endef
endif
endif
# List of languages to compile. # List of languages to compile.
# For reference, this is the command I use to build a srb2.pot file from the source code. # For reference, this is the command I use to build a srb2.pot file from the source code.
# (The listed source files are the ones containing translated strings). # (The listed source files are the ones containing translated strings).
@ -553,12 +566,6 @@ all: pre-build $(BIN)/$(PNDNAME)
endif endif
ifdef MINGW
ifndef SDL
all: pre-build $(BIN)/$(EXENAME) dll
endif
endif
ifdef SDL ifdef SDL
all: pre-build $(BIN)/$(EXENAME) all: pre-build $(BIN)/$(EXENAME)
endif endif
@ -638,57 +645,6 @@ endif
$(OBJDIR): $(OBJDIR):
-$(MKDIR) $(OBJDIR) -$(MKDIR) $(OBJDIR)
ifndef SDL
ifdef NOHW
dll :
else
dll : opengl_dll
endif
ifdef MINGW
all_dll: opengl_dll ds3d_dll fmod_dll openal_dll
opengl_dll: $(BIN)/r_opengl.dll
$(BIN)/r_opengl.dll: $(OBJDIR)/ogl_win.o $(OBJDIR)/r_opengl.o
-$(MKDIR) $(BIN)
@echo Linking R_OpenGL.dll...
$(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lgdi32 -static-libgcc
ifndef NOUPX
-$(UPX) $(UPX_OPTS) $@
endif
ds3d_dll: $(BIN)/s_ds3d.dll
$(BIN)/s_ds3d.dll: $(OBJDIR)/s_ds3d.o
@echo Linking S_DS3d.dll...
$(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -ldsound -luuid
fmod_dll: $(BIN)/s_fmod.dll
$(BIN)/s_fmod.dll: $(OBJDIR)/s_fmod.o
-$(MKDIR) $(BIN)
@echo Linking S_FMOD.dll...
$(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lfmod
openal_dll: $(BIN)/s_openal.dll
$(BIN)/s_openal.dll: $(OBJDIR)/s_openal.o
-$(MKDIR) $(BIN)
@echo Linking S_OpenAL.dll...
$(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lopenal32
else
all_dll: fmod_so openal_so
fmod_so: $(BIN)/s_fmod.so
$(BIN)/s_fmod.so: $(OBJDIR)/s_fmod.o
-$(MKDIR) $(BIN)
@echo Linking S_FMOD.so...
$(CC) --shared $^ -o $@ -g --nostartfiles -lm -lfmod
openal_so: $(BIN)/s_openal.so
$(BIN)/s_openal.so: $(OBJDIR)/s_openal.o
-$(MKDIR) $(BIN)
@echo Linking S_OpenAL.so...
$(CC) --shared $^ -o $@ -g --nostartfiles -lm -lopenal
endif
else
ifdef SDL ifdef SDL
ifdef MINGW ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
@ -698,6 +654,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.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 \ 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 p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
else else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
@ -707,12 +664,11 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.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 \ 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 p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
endif endif
endif endif
endif
#dependecy made by gcc itself ! #dependecy made by gcc itself !
$(OBJS): $(OBJS):
ifndef DUMMY ifndef DUMMY
@ -735,100 +691,93 @@ endif
ifdef VALGRIND ifdef VALGRIND
$(OBJDIR)/z_zone.o: z_zone.c $(OBJDIR)/z_zone.o: z_zone.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@
endif endif
$(OBJDIR)/comptime.o: comptime.c pre-build $(OBJDIR)/comptime.o: comptime.c pre-build
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(BIN)/%.mo: locale/%.po $(BIN)/%.mo: locale/%.po
-$(MKDIR) $(BIN) -$(MKDIR) $(BIN)
$(echoName)
$(MSGFMT) -f -o $@ $< $(MSGFMT) -f -o $@ $<
$(OBJDIR)/%.o: %.c $(OBJDIR)/%.o: %.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(INTERFACE)/%.c $(OBJDIR)/%.o: $(INTERFACE)/%.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
ifdef MACOSX ifdef MACOSX
$(OBJDIR)/%.o: sdl/macosx/%.c $(OBJDIR)/%.o: sdl/macosx/%.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif endif
$(OBJDIR)/%.o: hardware/%.c $(OBJDIR)/%.o: hardware/%.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/%.o: blua/%.c $(OBJDIR)/%.o: blua/%.c
$(echoName)
$(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/%.o: %.nas $(OBJDIR)/%.o: %.nas
$(echoName)
$(NASM) $(NASMOPTS) -o $@ -f $(NASMFORMAT) $< $(NASM) $(NASMOPTS) -o $@ -f $(NASMFORMAT) $<
$(OBJDIR)/vid_copy.o: vid_copy.s asm_defs.inc $(OBJDIR)/vid_copy.o: vid_copy.s asm_defs.inc
$(echoName)
$(CC) $(OPTS) $(ASFLAGS) -x assembler-with-cpp -c $< -o $@ $(CC) $(OPTS) $(ASFLAGS) -x assembler-with-cpp -c $< -o $@
$(OBJDIR)/%.o: %.s $(OBJDIR)/%.o: %.s
$(echoName)
$(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@ $(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@
$(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h $(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h
$(echoName)
$(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff $(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff
ifdef MINGW
ifndef SDL
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_defs.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_defs.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
endif
endif
ifdef SDL ifdef SDL
ifdef MINGW ifdef MINGW
$(OBJDIR)/win_dbg.o: win32/win_dbg.c $(OBJDIR)/win_dbg.o: win32/win_dbg.c
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif endif
ifdef STATICHS ifdef STATICHS
$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
ifdef MINGW ifdef MINGW
$(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif endif
else else
$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c
$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ $(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h hardware/hw_dll.h
$(echoName)
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c
endif endif
endif endif

View File

@ -420,14 +420,14 @@ ifdef CYGWIN32
BIN:=$(BIN)/Cygwin BIN:=$(BIN)/Cygwin
else else
ifdef MINGW64 ifdef MINGW64
INTERFACE=win32
#NASMFORMAT=win64 #NASMFORMAT=win64
SDL=1
OBJDIR:=$(OBJDIR)/Mingw64 OBJDIR:=$(OBJDIR)/Mingw64
BIN:=$(BIN)/Mingw64 BIN:=$(BIN)/Mingw64
else else
ifdef MINGW ifdef MINGW
INTERFACE=win32
NASMFORMAT=win32 NASMFORMAT=win32
SDL=1
OBJDIR:=$(OBJDIR)/Mingw OBJDIR:=$(OBJDIR)/Mingw
BIN:=$(BIN)/Mingw BIN:=$(BIN)/Mingw
endif endif

View File

@ -9,6 +9,7 @@
#include "utils/Log.h" #include "utils/Log.h"
rendermode_t rendermode = render_soft; rendermode_t rendermode = render_soft;
rendermode_t chosenrendermode = render_none;
boolean highcolor = false; boolean highcolor = false;
@ -52,8 +53,15 @@ INT32 VID_SetMode(INT32 modenum)
return 0; return 0;
} }
void VID_CheckRenderer(void) {} boolean VID_CheckRenderer(void)
void VID_CheckGLLoaded(rendermode_t oldrender) {} {
return false;
}
void VID_CheckGLLoaded(rendermode_t oldrender)
{
(void)oldrender;
}
const char *VID_GetModeName(INT32 modenum) const char *VID_GetModeName(INT32 modenum)
{ {

View File

@ -686,6 +686,15 @@ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
} }
static void codeunaryarith (FuncState *fs, OpCode op, expdesc *e) {
expdesc e2;
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
if (op == OP_LEN || !isnumeral(e))
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
codearith(fs, op, e, &e2);
}
static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
expdesc *e2) { expdesc *e2) {
int o1 = luaK_exp2RK(fs, e1); int o1 = luaK_exp2RK(fs, e1);
@ -703,27 +712,11 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
expdesc e2;
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
switch (op) { switch (op) {
case OPR_MINUS: { case OPR_MINUS: codeunaryarith(fs, OP_UNM, e); break;
if (!isnumeral(e)) case OPR_BNOT: codeunaryarith(fs, OP_BNOT, e); break;
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
codearith(fs, OP_UNM, e, &e2);
break;
}
case OPR_BNOT: {
if (e->k == VK)
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
codearith(fs, OP_BNOT, e, &e2);
break;
}
case OPR_NOT: codenot(fs, e); break; case OPR_NOT: codenot(fs, e); break;
case OPR_LEN: { case OPR_LEN: codeunaryarith(fs, OP_LEN, e); break;
luaK_exp2anyreg(fs, e); /* cannot operate on constants */
codearith(fs, OP_LEN, e, &e2);
break;
}
default: lua_assert(0); default: lua_assert(0);
} }
} }

View File

@ -277,6 +277,9 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
if (!luafiletransfers) if (!luafiletransfers)
I_Error("No Lua file transfer\n"); I_Error("No Lua file transfer\n");
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
// Retrieve the callback and push it on the stack // Retrieve the callback and push it on the stack
lua_pushfstring(gL, FMT_FILECALLBACKID, luafiletransfers->id); lua_pushfstring(gL, FMT_FILECALLBACKID, luafiletransfers->id);
lua_gettable(gL, LUA_REGISTRYINDEX); lua_gettable(gL, LUA_REGISTRYINDEX);
@ -304,7 +307,8 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
lua_pushstring(gL, luafiletransfers->filename); lua_pushstring(gL, luafiletransfers->filename);
// Call the callback // Call the callback
LUA_Call(gL, 2); LUA_Call(gL, 2, 0, 1);
lua_settop(gL, 0);
if (success) if (success)
{ {

View File

@ -165,6 +165,8 @@ void COM_BufAddTextEx(const char *ptext, int flags)
*/ */
void COM_BufInsertTextEx(const char *ptext, int flags) void COM_BufInsertTextEx(const char *ptext, int flags)
{ {
const INT32 old_wait = com_wait;
char *temp = NULL; char *temp = NULL;
size_t templen; size_t templen;
@ -176,10 +178,14 @@ void COM_BufInsertTextEx(const char *ptext, int flags)
VS_Clear(&com_text); VS_Clear(&com_text);
} }
com_wait = 0;
// add the entire text of the file (or alias) // add the entire text of the file (or alias)
COM_BufAddTextEx(ptext, flags); COM_BufAddTextEx(ptext, flags);
COM_BufExecute(); // do it right away COM_BufExecute(); // do it right away
com_wait += old_wait;
// add the copied off data // add the copied off data
if (templen) if (templen)
{ {

View File

@ -56,7 +56,8 @@ I_mutex con_mutex;
#endif/*HAVE_THREADS*/ #endif/*HAVE_THREADS*/
static boolean con_started = false; // console has been initialised static boolean con_started = false; // console has been initialised
boolean con_startup = false; // true at game startup, screen need refreshing boolean con_startup = false; // true at game startup
boolean con_refresh = false; // screen needs refreshing
static boolean con_forcepic = true; // at startup toggle console translucency when first off static boolean con_forcepic = true; // at startup toggle console translucency when first off
boolean con_recalc; // set true when screen size has changed boolean con_recalc; // set true when screen size has changed
@ -458,7 +459,8 @@ void CON_Init(void)
Lock_state(); Lock_state();
con_started = true; con_started = true;
con_startup = true; // need explicit screen refresh until we are in Doom loop con_startup = true;
con_refresh = true; // needs explicit screen refresh until we are in the main game loop
consoletoggle = false; consoletoggle = false;
Unlock_state(); Unlock_state();
@ -476,7 +478,8 @@ void CON_Init(void)
Lock_state(); Lock_state();
con_started = true; con_started = true;
con_startup = false; // need explicit screen refresh until we are in Doom loop con_startup = false;
con_refresh = false; // disable explicit screen refresh
consoletoggle = true; consoletoggle = true;
Unlock_state(); Unlock_state();
@ -1457,7 +1460,7 @@ void CONS_Printf(const char *fmt, ...)
{ {
va_list argptr; va_list argptr;
static char *txt = NULL; static char *txt = NULL;
boolean startup; boolean refresh;
if (txt == NULL) if (txt == NULL)
txt = malloc(8192); txt = malloc(8192);
@ -1473,32 +1476,21 @@ void CONS_Printf(const char *fmt, ...)
if (con_started) if (con_started)
CON_Print(txt); CON_Print(txt);
CON_LogMessage(txt); CON_LogMessage(txt);
Lock_state(); Lock_state();
// make sure new text is visible // make sure new text is visible
con_scrollup = 0; con_scrollup = 0;
startup = con_startup; refresh = con_refresh;
Unlock_state(); Unlock_state();
// if not in display loop, force screen update // if not in display loop, force screen update
if (startup && (!setrenderneeded)) if (refresh)
{ {
#ifdef _WINDOWS CON_Drawer(); // here we display the console text
patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
// Jimita: CON_DrawBackpic just called V_DrawScaledPatch
V_DrawScaledPatch(0, 0, 0, con_backpic);
W_UnlockCachedPatch(con_backpic);
I_LoadingScreen(txt); // Win32/OS2 only
#else
// here we display the console text
CON_Drawer();
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
#endif
} }
} }
@ -1560,7 +1552,7 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...)
// //
void CONS_Error(const char *msg) void CONS_Error(const char *msg)
{ {
#ifdef RPC_NO_WINDOWS_H #if defined(RPC_NO_WINDOWS_H) && defined(_WINDOWS)
if (!graphics_started) if (!graphics_started)
{ {
MessageBoxA(vid.WndParent, msg, "SRB2 Warning", MB_OK); MessageBoxA(vid.WndParent, msg, "SRB2 Warning", MB_OK);
@ -1709,7 +1701,7 @@ static void CON_DrawHudlines(void)
;//charwidth = 4 * con_scalefactor; ;//charwidth = 4 * con_scalefactor;
else else
{ {
//charwidth = SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; //charwidth = (hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
} }
} }
@ -1738,8 +1730,8 @@ static void CON_DrawBackpic(void)
if (piclump == LUMPERROR) if (piclump == LUMPERROR)
piclump = W_GetNumForName("MISSING"); piclump = W_GetNumForName("MISSING");
// Cache the Software patch. // Cache the patch.
con_backpic = W_CacheSoftwarePatchNum(piclump, PU_PATCH); con_backpic = W_CachePatchNum(piclump, PU_PATCH);
// Center the backpic, and draw a vertically cropped patch. // Center the backpic, and draw a vertically cropped patch.
w = (con_backpic->width * vid.dupx); w = (con_backpic->width * vid.dupx);
@ -1750,7 +1742,7 @@ static void CON_DrawBackpic(void)
// then fill the sides with a solid color. // then fill the sides with a solid color.
if (x > 0) if (x > 0)
{ {
column_t *column = (column_t *)((UINT8 *)(con_backpic) + LONG(con_backpic->columnofs[0])); column_t *column = (column_t *)((UINT8 *)(con_backpic->columns) + (con_backpic->columnofs[0]));
if (!column->topdelta) if (!column->topdelta)
{ {
UINT8 *source = (UINT8 *)(column) + 3; UINT8 *source = (UINT8 *)(column) + 3;
@ -1762,8 +1754,7 @@ static void CON_DrawBackpic(void)
} }
} }
// Cache the patch normally. // Draw the patch.
con_backpic = W_CachePatchNum(piclump, PU_PATCH);
V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic, V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic,
0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h); 0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h);
@ -1848,9 +1839,6 @@ void CON_Drawer(void)
return; return;
} }
if (needpatchrecache)
HU_LoadGraphics();
if (con_recalc) if (con_recalc)
{ {
CON_RecalcSize(); CON_RecalcSize();

View File

@ -25,8 +25,12 @@ extern I_mutex con_mutex;
// set true when screen size has changed, to adapt console // set true when screen size has changed, to adapt console
extern boolean con_recalc; extern boolean con_recalc;
// console being displayed at game startup
extern boolean con_startup; extern boolean con_startup;
// needs explicit screen refresh until we are in the main game loop
extern boolean con_refresh;
// top clip value for view render: do not draw part of view hidden by console // top clip value for view render: do not draw part of view hidden by console
extern INT32 con_clipviewtop; extern INT32 con_clipviewtop;

File diff suppressed because it is too large Load Diff

View File

@ -64,8 +64,10 @@ typedef enum
PT_REQUESTFILE, // Client requests a file transfer PT_REQUESTFILE, // Client requests a file transfer
PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client. PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client.
// If this ID changes, update masterserver definition. // If this ID changes, update masterserver definition.
PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic
PT_RESYNCHGET, // Player got resynch packet PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate!
PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead.
PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again!
PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file
PT_ASKLUAFILE, // Client telling the server they don't have the file PT_ASKLUAFILE, // Client telling the server they don't have the file
@ -85,8 +87,6 @@ typedef enum
PT_TEXTCMD2, // Splitscreen text commands. PT_TEXTCMD2, // Splitscreen text commands.
PT_CLIENTJOIN, // Client wants to join; used in start game. PT_CLIENTJOIN, // Client wants to join; used in start game.
PT_NODETIMEOUT, // Packet sent to self if the connection times out. PT_NODETIMEOUT, // Packet sent to self if the connection times out.
PT_RESYNCHING, // Packet sent to resync players.
// Blocks game advance until synched.
PT_LOGIN, // Login attempt from the client. PT_LOGIN, // Login attempt from the client.
@ -139,168 +139,6 @@ typedef struct
ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
} ATTRPACK servertics_pak; } ATTRPACK servertics_pak;
// Sent to client when all consistency data
// for players has been restored
typedef struct
{
UINT32 randomseed;
// CTF flag stuff
SINT8 flagplayer[2];
INT32 flagloose[2];
INT32 flagflags[2];
fixed_t flagx[2];
fixed_t flagy[2];
fixed_t flagz[2];
UINT32 ingame; // Spectator bit for each player
UINT32 outofcoop; // outofcoop bit for each player
INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
// Resynch game scores and the like all at once
UINT32 score[MAXPLAYERS]; // Everyone's score
INT16 numboxes[MAXPLAYERS];
INT16 totalring[MAXPLAYERS];
tic_t realtime[MAXPLAYERS];
UINT8 laps[MAXPLAYERS];
} ATTRPACK resynchend_pak;
typedef struct
{
// Player stuff
UINT8 playernum;
// Do not send anything visual related.
// Only send data that we need to know for physics.
UINT8 playerstate; // playerstate_t
UINT32 pflags; // pflags_t
UINT8 panim; // panim_t
INT16 angleturn;
INT16 oldrelangleturn;
angle_t aiming;
INT32 currentweapon;
INT32 ringweapons;
UINT16 ammoremoval;
tic_t ammoremovaltimer;
INT32 ammoremovalweapon;
UINT16 powers[NUMPOWERS];
// Score is resynched in the confirm resync packet
INT16 rings;
INT16 spheres;
SINT8 lives;
SINT8 continues;
UINT8 scoreadd;
SINT8 xtralife;
SINT8 pity;
UINT16 skincolor;
INT32 skin;
UINT32 availabilities;
// Just in case Lua does something like
// modify these at runtime
fixed_t camerascale;
fixed_t shieldscale;
fixed_t normalspeed;
fixed_t runspeed;
UINT8 thrustfactor;
UINT8 accelstart;
UINT8 acceleration;
UINT8 charability;
UINT8 charability2;
UINT32 charflags;
UINT32 thokitem; // mobjtype_t
UINT32 spinitem; // mobjtype_t
UINT32 revitem; // mobjtype_t
UINT32 followitem; // mobjtype_t
fixed_t actionspd;
fixed_t mindash;
fixed_t maxdash;
fixed_t jumpfactor;
fixed_t playerheight;
fixed_t playerspinheight;
fixed_t speed;
UINT8 secondjump;
UINT8 fly1;
tic_t glidetime;
UINT8 climbing;
INT32 deadtimer;
tic_t exiting;
UINT8 homing;
tic_t dashmode;
tic_t skidtime;
fixed_t cmomx;
fixed_t cmomy;
fixed_t rmomx;
fixed_t rmomy;
INT32 weapondelay;
INT32 tossdelay;
INT16 starpostx;
INT16 starposty;
INT16 starpostz;
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
fixed_t starpostscale;
INT32 maxlink;
fixed_t dashspeed;
angle_t angle_pos;
angle_t old_angle_pos;
tic_t bumpertime;
INT32 flyangle;
tic_t drilltimer;
INT32 linkcount;
tic_t linktimer;
INT32 anotherflyangle;
tic_t nightstime;
INT32 drillmeter;
UINT8 drilldelay;
UINT8 bonustime;
UINT8 mare;
INT16 lastsidehit, lastlinehit;
tic_t losstime;
UINT8 timeshit;
INT32 onconveyor;
//player->mo stuff
UINT8 hasmo; // Boolean
INT32 health;
angle_t angle;
angle_t rollangle;
fixed_t x;
fixed_t y;
fixed_t z;
fixed_t momx;
fixed_t momy;
fixed_t momz;
fixed_t friction;
fixed_t movefactor;
spritenum_t sprite;
UINT32 frame;
UINT8 sprite2;
UINT16 anim_duration;
INT32 tics;
statenum_t statenum;
UINT32 flags;
UINT32 flags2;
UINT16 eflags;
fixed_t radius;
fixed_t height;
fixed_t scale;
fixed_t destscale;
fixed_t scalespeed;
} ATTRPACK resynch_pak;
typedef struct typedef struct
{ {
UINT8 version; // Different versions don't work UINT8 version; // Different versions don't work
@ -314,18 +152,10 @@ typedef struct
UINT8 clientnode; UINT8 clientnode;
UINT8 gamestate; UINT8 gamestate;
// 0xFF == not in game; else player skin num
UINT8 playerskins[MAXPLAYERS];
UINT16 playercolor[MAXPLAYERS];
UINT32 playeravailabilities[MAXPLAYERS];
UINT8 gametype; UINT8 gametype;
UINT8 modifiedgame; UINT8 modifiedgame;
SINT8 adminplayers[MAXPLAYERS]; // Needs to be signed
char server_context[8]; // Unique context id, generated at server startup. char server_context[8]; // Unique context id, generated at server startup.
UINT8 varlengthinputs[0]; // Playernames and netvars
} ATTRPACK serverconfig_pak; } ATTRPACK serverconfig_pak;
typedef struct typedef struct
@ -462,9 +292,6 @@ typedef struct
client2cmd_pak client2pak; // 200 bytes client2cmd_pak client2pak; // 200 bytes
servertics_pak serverpak; // 132495 bytes (more around 360, no?) servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; // 773 bytes serverconfig_pak servercfg; // 773 bytes
resynchend_pak resynchend; //
resynch_pak resynchpak; //
UINT8 resynchgot; //
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
filetx_pak filetxpak; // 139 bytes filetx_pak filetxpak; // 139 bytes
fileack_pak fileack; fileack_pak fileack;
@ -606,7 +433,7 @@ UINT8 GetFreeXCmdSize(void);
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest); void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
extern UINT8 hu_resynching; extern UINT8 hu_redownloadinggamestate;
extern UINT8 adminpassmd5[16]; extern UINT8 adminpassmd5[16];
extern boolean adminpasswordset; extern boolean adminpasswordset;

View File

@ -107,8 +107,6 @@ boolean devparm = false; // started game with -devparm
boolean singletics = false; // timedemo boolean singletics = false; // timedemo
boolean lastdraw = false; boolean lastdraw = false;
static void D_CheckRendererState(void);
postimg_t postimgtype = postimg_none; postimg_t postimgtype = postimg_none;
INT32 postimgparam; INT32 postimgparam;
postimg_t postimgtype2 = postimg_none; postimg_t postimgtype2 = postimg_none;
@ -237,7 +235,6 @@ INT16 wipetypepost = -1;
static void D_Display(void) static void D_Display(void)
{ {
INT32 setrenderstillneeded = 0;
boolean forcerefresh = false; boolean forcerefresh = false;
static boolean wipe = false; static boolean wipe = false;
INT32 wipedefindex = 0; INT32 wipedefindex = 0;
@ -260,48 +257,28 @@ static void D_Display(void)
// create plane polygons, if necessary. // create plane polygons, if necessary.
// 3. Functions related to switching video // 3. Functions related to switching video
// modes (resolution) are called. // modes (resolution) are called.
// 4. Patch data is freed from memory, // 4. The frame is ready to be drawn!
// and recached if necessary.
// 5. The frame is ready to be drawn!
// stop movie if needs to change renderer // Check for change of renderer or screen size (video mode)
if (setrenderneeded && (moviemode == MM_APNG))
M_StopMovie();
// check for change of renderer or screen size (video mode)
if ((setrenderneeded || setmodeneeded) && !wipe) if ((setrenderneeded || setmodeneeded) && !wipe)
{
if (setrenderneeded)
{
CONS_Debug(DBG_RENDER, "setrenderneeded set (%d)\n", setrenderneeded);
setrenderstillneeded = setrenderneeded;
}
SCR_SetMode(); // change video mode SCR_SetMode(); // change video mode
}
if (vid.recalc || setrenderstillneeded) // Recalc the screen
{ if (vid.recalc)
SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc() 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
}
// View morph
if (rendermode == render_soft && !splitscreen) if (rendermode == render_soft && !splitscreen)
R_CheckViewMorph(); R_CheckViewMorph();
// change the view size if needed // Change the view size if needed
if (setsizeneeded || setrenderstillneeded) // Set by changing video mode or renderer
if (setsizeneeded)
{ {
R_ExecuteSetViewSize(); R_ExecuteSetViewSize();
forcerefresh = true; // force background redraw forcerefresh = true; // force background redraw
} }
// Lactozilla: Renderer switching
D_CheckRendererState();
// draw buffered stuff to screen // draw buffered stuff to screen
// Used only by linux GGI version // Used only by linux GGI version
I_UpdateNoBlit(); I_UpdateNoBlit();
@ -436,7 +413,7 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value) if (!automapactive && !dedicated && cv_renderview.value)
{ {
ps_rendercalltime = I_GetTimeMicros(); ps_rendercalltime = I_GetPreciseTime();
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{ {
topleft = screens[0] + viewwindowy*vid.width + viewwindowx; topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
@ -483,7 +460,7 @@ static void D_Display(void)
if (postimgtype2) if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2); V_DoPostProcessor(1, postimgtype2, postimgparam2);
} }
ps_rendercalltime = I_GetTimeMicros() - ps_rendercalltime; ps_rendercalltime = I_GetPreciseTime() - ps_rendercalltime;
} }
if (lastdraw) if (lastdraw)
@ -497,7 +474,7 @@ static void D_Display(void)
lastdraw = false; lastdraw = false;
} }
ps_uitime = I_GetTimeMicros(); ps_uitime = I_GetPreciseTime();
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
@ -510,7 +487,7 @@ static void D_Display(void)
} }
else else
{ {
ps_uitime = I_GetTimeMicros(); ps_uitime = I_GetPreciseTime();
} }
} }
@ -530,7 +507,7 @@ static void D_Display(void)
else else
py = viewwindowy + 4; py = viewwindowy + 4;
patch = W_CachePatchName("M_PAUSE", PU_PATCH); patch = W_CachePatchName("M_PAUSE", PU_PATCH);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch); V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, 0, patch);
#else #else
INT32 y = ((automapactive) ? (32) : (BASEVIDHEIGHT/2)); INT32 y = ((automapactive) ? (32) : (BASEVIDHEIGHT/2));
M_DrawTextBox((BASEVIDWIDTH/2) - (60), y - (16), 13, 2); M_DrawTextBox((BASEVIDWIDTH/2) - (60), y - (16), 13, 2);
@ -552,7 +529,7 @@ static void D_Display(void)
CON_Drawer(); CON_Drawer();
ps_uitime = I_GetTimeMicros() - ps_uitime; ps_uitime = I_GetPreciseTime() - ps_uitime;
// //
// wipe update // wipe update
@ -638,30 +615,10 @@ static void D_Display(void)
M_DrawPerfStats(); M_DrawPerfStats();
} }
ps_swaptime = I_GetTimeMicros(); ps_swaptime = I_GetPreciseTime();
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
ps_swaptime = I_GetTimeMicros() - ps_swaptime; ps_swaptime = I_GetPreciseTime() - ps_swaptime;
} }
needpatchflush = false;
needpatchrecache = false;
}
// Check the renderer's state
// after a possible renderer switch.
void D_CheckRendererState(void)
{
// flush all patches from memory
if (needpatchflush)
{
Z_FlushCachedPatches();
needpatchflush = false;
}
// some patches have been freed,
// so cache them again
if (needpatchrecache)
R_ReloadHUDGraphics();
} }
// ========================================================================= // =========================================================================
@ -688,12 +645,15 @@ void D_SRB2Loop(void)
oldentertics = I_GetTime(); oldentertics = I_GetTime();
// end of loading screen: CONS_Printf() will no more call FinishUpdate() // end of loading screen: CONS_Printf() will no more call FinishUpdate()
con_refresh = false;
con_startup = false; con_startup = false;
// make sure to do a d_display to init mode _before_ load a level // make sure to do a d_display to init mode _before_ load a level
SCR_SetMode(); // change video mode SCR_SetMode(); // change video mode
SCR_Recalc(); SCR_Recalc();
chosenrendermode = render_none;
// Check and print which version is executed. // Check and print which version is executed.
// Use this as the border between setup and the main game loop being entered. // Use this as the border between setup and the main game loop being entered.
CONS_Printf( CONS_Printf(
@ -1038,7 +998,7 @@ static void IdentifyVersion(void)
#define MUSICTEST(str) \ #define MUSICTEST(str) \
{\ {\
const char *musicpath = va(pandf,srb2waddir,str);\ const char *musicpath = va(pandf,srb2waddir,str);\
int ms = W_VerifyNMUSlumps(musicpath); \ int ms = W_VerifyNMUSlumps(musicpath, false); \
if (ms == 1) \ if (ms == 1) \
D_AddFile(startupwadfiles, musicpath); \ D_AddFile(startupwadfiles, musicpath); \
else if (ms == 0) \ else if (ms == 0) \
@ -1227,11 +1187,7 @@ void D_SRB2Main(void)
const char *s = M_GetNextParm(); const char *s = M_GetNextParm();
if (s) // Check for NULL? if (s) // Check for NULL?
{
if (!W_VerifyNMUSlumps(s))
G_SetGameModified(true);
D_AddFile(startuppwads, s); D_AddFile(startuppwads, s);
}
} }
} }
} }
@ -1338,24 +1294,6 @@ void D_SRB2Main(void)
// set user default mode or mode set at cmdline // set user default mode or mode set at cmdline
SCR_CheckDefaultMode(); SCR_CheckDefaultMode();
// Lactozilla: Does the render mode need to change?
if ((setrenderneeded != 0) && (setrenderneeded != rendermode))
{
CONS_Printf(M_GetText("Switching the renderer...\n"));
Z_PreparePatchFlush();
// set needpatchflush / needpatchrecache true for D_CheckRendererState
needpatchflush = true;
needpatchrecache = true;
// Set cv_renderer to the new render mode
VID_CheckRenderer();
SCR_ChangeRendererCVars(rendermode);
// check the renderer's state
D_CheckRendererState();
}
wipegamestate = gamestate; wipegamestate = gamestate;
savedata.lives = 0; // flag this as not-used savedata.lives = 0; // flag this as not-used
@ -1598,7 +1536,7 @@ void D_SRB2Main(void)
{ {
levelstarttic = gametic; levelstarttic = gametic;
G_SetGamestate(GS_LEVEL); G_SetGamestate(GS_LEVEL);
if (!P_LoadLevel(false)) if (!P_LoadLevel(false, false))
I_Quit(); // fail so reset game stuff I_Quit(); // fail so reset game stuff
} }
} }

View File

@ -798,8 +798,9 @@ static const char *packettypename[NUMPACKETTYPE] =
"REQUESTFILE", "REQUESTFILE",
"ASKINFOVIAMS", "ASKINFOVIAMS",
"RESYNCHEND", "WILLRESENDGAMESTATE",
"RESYNCHGET", "CANRECEIVEGAMESTATE",
"RECEIVEDGAMESTATE",
"SENDINGLUAFILE", "SENDINGLUAFILE",
"ASKLUAFILE", "ASKLUAFILE",
@ -813,7 +814,6 @@ static const char *packettypename[NUMPACKETTYPE] =
"TEXTCMD2", "TEXTCMD2",
"CLIENTJOIN", "CLIENTJOIN",
"NODETIMEOUT", "NODETIMEOUT",
"RESYNCHING",
"LOGIN", "LOGIN",
"PING" "PING"
}; };

View File

@ -214,11 +214,9 @@ consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_
consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL); consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL);
#ifdef SEENAMES
static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}}; static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}};
consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0); consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0);
consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL); consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
#endif
// names // names
consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange); consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange);
@ -374,6 +372,7 @@ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL)
static CV_PossibleValue_t perfstats_cons_t[] = { static CV_PossibleValue_t perfstats_cons_t[] = {
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL); consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL);
consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL);
char timedemo_name[256]; char timedemo_name[256];
boolean timedemo_csv; boolean timedemo_csv;
@ -596,9 +595,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_pingtimeout); CV_RegisterVar(&cv_pingtimeout);
CV_RegisterVar(&cv_showping); CV_RegisterVar(&cv_showping);
#ifdef SEENAMES CV_RegisterVar(&cv_allowseenames);
CV_RegisterVar(&cv_allowseenames);
#endif
CV_RegisterVar(&cv_dummyconsvar); CV_RegisterVar(&cv_dummyconsvar);
} }
@ -669,16 +666,13 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_zlib_strategya); CV_RegisterVar(&cv_zlib_strategya);
CV_RegisterVar(&cv_zlib_window_bitsa); CV_RegisterVar(&cv_zlib_window_bitsa);
CV_RegisterVar(&cv_apng_delay); CV_RegisterVar(&cv_apng_delay);
CV_RegisterVar(&cv_apng_downscale);
// GIF variables // GIF variables
CV_RegisterVar(&cv_gif_optimize); CV_RegisterVar(&cv_gif_optimize);
CV_RegisterVar(&cv_gif_downscale); CV_RegisterVar(&cv_gif_downscale);
CV_RegisterVar(&cv_gif_dynamicdelay); CV_RegisterVar(&cv_gif_dynamicdelay);
CV_RegisterVar(&cv_gif_localcolortable); CV_RegisterVar(&cv_gif_localcolortable);
#ifdef WALLSPLATS
CV_RegisterVar(&cv_splats);
#endif
// register these so it is saved to config // register these so it is saved to config
CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playername);
CV_RegisterVar(&cv_playercolor); CV_RegisterVar(&cv_playercolor);
@ -693,9 +687,7 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_defaultplayercolor2); CV_RegisterVar(&cv_defaultplayercolor2);
CV_RegisterVar(&cv_defaultskin2); CV_RegisterVar(&cv_defaultskin2);
#ifdef SEENAMES
CV_RegisterVar(&cv_seenames); CV_RegisterVar(&cv_seenames);
#endif
CV_RegisterVar(&cv_rollingdemos); CV_RegisterVar(&cv_rollingdemos);
CV_RegisterVar(&cv_netstat); CV_RegisterVar(&cv_netstat);
CV_RegisterVar(&cv_netticbuffer); CV_RegisterVar(&cv_netticbuffer);
@ -880,6 +872,8 @@ void D_RegisterClientCommands(void)
// CV_RegisterVar(&cv_grid); // CV_RegisterVar(&cv_grid);
// CV_RegisterVar(&cv_snapto); // CV_RegisterVar(&cv_snapto);
CV_RegisterVar(&cv_freedemocamera);
// add cheat commands // add cheat commands
COM_AddCommand("noclip", Command_CheatNoClip_f); COM_AddCommand("noclip", Command_CheatNoClip_f);
COM_AddCommand("god", Command_CheatGod_f); COM_AddCommand("god", Command_CheatGod_f);
@ -3295,7 +3289,13 @@ static void Command_Addfile(void)
if (!isprint(fn[i]) || fn[i] == ';') if (!isprint(fn[i]) || fn[i] == ';')
return; return;
musiconly = W_VerifyNMUSlumps(fn); musiconly = W_VerifyNMUSlumps(fn, false);
if (musiconly == -1)
{
addedfiles[numfilesadded++] = fn;
continue;
}
if (!musiconly) if (!musiconly)
{ {
@ -3607,8 +3607,7 @@ static void Command_Playintro_f(void)
*/ */
FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void) FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void)
{ {
if (Playing()) LUAh_GameQuit(true);
LUAh_GameQuit();
I_Quit(); I_Quit();
} }
@ -4270,8 +4269,7 @@ void Command_ExitGame_f(void)
{ {
INT32 i; INT32 i;
if (Playing()) LUAh_GameQuit(false);
LUAh_GameQuit();
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();

View File

@ -31,9 +31,7 @@ extern consvar_t cv_defaultskin;
extern consvar_t cv_defaultplayercolor2; extern consvar_t cv_defaultplayercolor2;
extern consvar_t cv_defaultskin2; extern consvar_t cv_defaultskin2;
#ifdef SEENAMES
extern consvar_t cv_seenames, cv_allowseenames; extern consvar_t cv_seenames, cv_allowseenames;
#endif
extern consvar_t cv_usemouse; extern consvar_t cv_usemouse;
extern consvar_t cv_usejoystick; extern consvar_t cv_usejoystick;
extern consvar_t cv_usejoystick2; extern consvar_t cv_usejoystick2;
@ -75,9 +73,6 @@ extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange; extern consvar_t cv_scrambleonchange;
extern consvar_t cv_netstat; extern consvar_t cv_netstat;
#ifdef WALLSPLATS
extern consvar_t cv_splats;
#endif
extern consvar_t cv_countdowntime; extern consvar_t cv_countdowntime;
extern consvar_t cv_runscripts; extern consvar_t cv_runscripts;
@ -121,6 +116,8 @@ extern boolean timedemo_csv;
extern char timedemo_csv_id[256]; extern char timedemo_csv_id[256];
extern boolean timedemo_quit; extern boolean timedemo_quit;
extern consvar_t cv_freedemocamera;
typedef enum typedef enum
{ {
XD_NAMEANDCOLOR = 1, XD_NAMEANDCOLOR = 1,

View File

@ -51,6 +51,7 @@ typedef enum
SF_NONIGHTSSUPER = 1<<15, // Disable super colors for NiGHTS (if you have SF_SUPER) SF_NONIGHTSSUPER = 1<<15, // Disable super colors for NiGHTS (if you have SF_SUPER)
SF_NOSUPERSPRITES = 1<<16, // Don't use super sprites while super SF_NOSUPERSPRITES = 1<<16, // Don't use super sprites while super
SF_NOSUPERJUMPBOOST = 1<<17, // Disable the jump boost given while super (i.e. Knuckles) SF_NOSUPERJUMPBOOST = 1<<17, // Disable the jump boost given while super (i.e. Knuckles)
SF_CANBUSTWALLS = 1<<18, // Can naturally bust walls on contact? (i.e. Knuckles)
// free up to and including 1<<31 // free up to and including 1<<31
} skinflags_t; } skinflags_t;

697
src/deh_lua.c Normal file
View File

@ -0,0 +1,697 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_lua.c
/// \brief Lua SOC library
#include "g_game.h"
#include "s_sound.h"
#include "z_zone.h"
#include "m_menu.h"
#include "m_misc.h"
#include "p_local.h"
#include "st_stuff.h"
#include "fastcmp.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "dehacked.h"
#include "deh_lua.h"
#include "deh_tables.h"
#ifdef MUSICSLOT_COMPATIBILITY
#include "deh_soc.h" // for get_mus
#endif
// freeslot takes a name (string only!)
// and allocates it to the appropriate free slot.
// Returns the slot number allocated for it or nil if failed.
// ex. freeslot("MT_MYTHING","S_MYSTATE1","S_MYSTATE2")
// TODO: Error checking! @.@; There's currently no way to know which ones failed and why!
//
static inline int lib_freeslot(lua_State *L)
{
int n = lua_gettop(L);
int r = 0; // args returned
char *s, *type,*word;
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
while (n-- > 0)
{
s = Z_StrDup(luaL_checkstring(L,1));
type = strtok(s, "_");
if (type)
strupr(type);
else {
Z_Free(s);
return luaL_error(L, "Unknown enum type in '%s'\n", luaL_checkstring(L, 1));
}
word = strtok(NULL, "\n");
if (word)
strupr(word);
else {
Z_Free(s);
return luaL_error(L, "Missing enum name in '%s'\n", luaL_checkstring(L, 1));
}
if (fastcmp(type, "SFX")) {
sfxenum_t sfx;
strlwr(word);
CONS_Printf("Sound sfx_%s allocated.\n",word);
sfx = S_AddSoundFx(word, false, 0, false);
if (sfx != sfx_None) {
lua_pushinteger(L, sfx);
r++;
} else
CONS_Alert(CONS_WARNING, "Ran out of free SFX slots!\n");
}
else if (fastcmp(type, "SPR"))
{
char wad;
spritenum_t j;
lua_getfield(L, LUA_REGISTRYINDEX, "WAD");
wad = (char)lua_tointeger(L, -1);
lua_pop(L, 1);
for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++)
{
if (used_spr[(j-SPR_FIRSTFREESLOT)/8] & (1<<(j%8)))
{
if (!sprnames[j][4] && memcmp(sprnames[j],word,4)==0)
sprnames[j][4] = wad;
continue; // Already allocated, next.
}
// Found a free slot!
CONS_Printf("Sprite SPR_%s allocated.\n",word);
strncpy(sprnames[j],word,4);
//sprnames[j][4] = 0;
used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now.
lua_pushinteger(L, j);
r++;
break;
}
if (j > SPR_LASTFREESLOT)
CONS_Alert(CONS_WARNING, "Ran out of free sprite slots!\n");
}
else if (fastcmp(type, "S"))
{
statenum_t i;
for (i = 0; i < NUMSTATEFREESLOTS; i++)
if (!FREE_STATES[i]) {
CONS_Printf("State S_%s allocated.\n",word);
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word);
lua_pushinteger(L, S_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMSTATEFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free State slots!\n");
}
else if (fastcmp(type, "MT"))
{
mobjtype_t i;
for (i = 0; i < NUMMOBJFREESLOTS; i++)
if (!FREE_MOBJS[i]) {
CONS_Printf("MobjType MT_%s allocated.\n",word);
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word);
lua_pushinteger(L, MT_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMMOBJFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free MobjType slots!\n");
}
else if (fastcmp(type, "SKINCOLOR"))
{
skincolornum_t i;
for (i = 0; i < NUMCOLORFREESLOTS; i++)
if (!FREE_SKINCOLORS[i]) {
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word);
M_AddMenuColor(numskincolors++);
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMCOLORFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free skincolor slots!\n");
}
else if (fastcmp(type, "SPR2"))
{
// Search if we already have an SPR2 by that name...
playersprite_t i;
for (i = SPR2_FIRSTFREESLOT; i < free_spr2; i++)
if (memcmp(spr2names[i],word,4) == 0)
break;
// We don't, so allocate a new one.
if (i >= free_spr2) {
if (free_spr2 < NUMPLAYERSPRITES)
{
CONS_Printf("Sprite SPR2_%s allocated.\n",word);
strncpy(spr2names[free_spr2],word,4);
spr2defaults[free_spr2] = 0;
lua_pushinteger(L, free_spr2);
r++;
spr2names[free_spr2++][4] = 0;
} else
CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n");
}
}
else if (fastcmp(type, "TOL"))
{
// Search if we already have a typeoflevel by that name...
int i;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(word, TYPEOFLEVEL[i].name))
break;
// We don't, so allocate a new one.
if (TYPEOFLEVEL[i].name == NULL) {
if (lastcustomtol == (UINT32)MAXTOL) // Unless you have way too many, since they're flags.
CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n");
else {
CONS_Printf("TypeOfLevel TOL_%s allocated.\n",word);
G_AddTOL(lastcustomtol, word);
lua_pushinteger(L, lastcustomtol);
lastcustomtol <<= 1;
r++;
}
}
}
Z_Free(s);
lua_remove(L, 1);
continue;
}
return r;
}
// Wrapper for ALL A_Action functions.
// Arguments: mobj_t actor, int var1, int var2
static int action_call(lua_State *L)
{
//actionf_t *action = lua_touserdata(L,lua_upvalueindex(1));
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION));
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
var1 = (INT32)luaL_optinteger(L, 3, 0);
var2 = (INT32)luaL_optinteger(L, 4, 0);
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
action->acp1(actor);
return 0;
}
// Hardcoded A_Action name to call for super() or NULL if super() would be invalid.
// Set in lua_infolib.
const char *superactions[MAXRECURSION];
UINT8 superstack = 0;
static int lib_dummysuper(lua_State *L)
{
return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;;
}
static inline int lib_getenum(lua_State *L)
{
const char *word, *p;
fixed_t i;
boolean mathlib = lua_toboolean(L, lua_upvalueindex(1));
if (lua_type(L,2) != LUA_TSTRING)
return 0;
word = lua_tostring(L,2);
if (strlen(word) == 1) { // Assume sprite frame if length 1.
if (*word >= 'A' && *word <= '~')
{
lua_pushinteger(L, *word-'A');
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
return 0;
}
else if (fastncmp("MF_", word, 3)) {
p = word+3;
for (i = 0; MOBJFLAG_LIST[i]; i++)
if (fastcmp(p, MOBJFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MF2_", word, 4)) {
p = word+4;
for (i = 0; MOBJFLAG2_LIST[i]; i++)
if (fastcmp(p, MOBJFLAG2_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag2 '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MFE_", word, 4)) {
p = word+4;
for (i = 0; MOBJEFLAG_LIST[i]; i++)
if (fastcmp(p, MOBJEFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjeflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MTF_", word, 4)) {
p = word+4;
for (i = 0; i < 4; i++)
if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mapthingflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("PF_", word, 3)) {
p = word+3;
for (i = 0; PLAYERFLAG_LIST[i]; i++)
if (fastcmp(p, PLAYERFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (fastcmp(p, "FULLSTASIS"))
{
lua_pushinteger(L, (lua_Integer)PF_FULLSTASIS);
return 1;
}
else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release...
{
lua_pushinteger(L, (lua_Integer)PF_SPINDOWN);
return 1;
}
if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GT_", word, 3)) {
p = word;
for (i = 0; Gametype_ConstantNames[i]; i++)
if (fastcmp(p, Gametype_ConstantNames[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GTR_", word, 4)) {
p = word+4;
for (i = 0; GAMETYPERULE_LIST[i]; i++)
if (fastcmp(p, GAMETYPERULE_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "game type rule '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("TOL_", word, 4)) {
p = word+4;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(p, TYPEOFLEVEL[i].name)) {
lua_pushinteger(L, TYPEOFLEVEL[i].flag);
return 1;
}
if (mathlib) return luaL_error(L, "typeoflevel '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("ML_", word, 3)) {
p = word+3;
for (i = 0; i < 16; i++)
if (ML_LIST[i] && fastcmp(p, ML_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("S_",word,2)) {
p = word+2;
for (i = 0; i < NUMSTATEFREESLOTS; i++) {
if (!FREE_STATES[i])
break;
if (fastcmp(p, FREE_STATES[i])) {
lua_pushinteger(L, S_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < S_FIRSTFREESLOT; i++)
if (fastcmp(p, STATE_LIST[i]+2)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "state '%s' does not exist.\n", word);
}
else if (fastncmp("MT_",word,3)) {
p = word+3;
for (i = 0; i < NUMMOBJFREESLOTS; i++) {
if (!FREE_MOBJS[i])
break;
if (fastcmp(p, FREE_MOBJS[i])) {
lua_pushinteger(L, MT_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < MT_FIRSTFREESLOT; i++)
if (fastcmp(p, MOBJTYPE_LIST[i]+3)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "mobjtype '%s' does not exist.\n", word);
}
else if (fastncmp("SPR_",word,4)) {
p = word+4;
for (i = 0; i < NUMSPRITES; i++)
if (!sprnames[i][4] && fastncmp(p,sprnames[i],4)) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("SPR2_",word,5)) {
p = word+5;
for (i = 0; i < (fixed_t)free_spr2; i++)
if (!spr2names[i][4])
{
// special 3-char cases, e.g. SPR2_RUN
// the spr2names entry will have "_" on the end, as in "RUN_"
if (spr2names[i][3] == '_' && !p[3]) {
if (fastncmp(p,spr2names[i],3)) {
lua_pushinteger(L, i);
return 1;
}
}
else if (fastncmp(p,spr2names[i],4)) {
lua_pushinteger(L, i);
return 1;
}
}
if (mathlib) return luaL_error(L, "player sprite '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("sfx_",word,4)) {
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fastcmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
return 0;
}
else if (mathlib && fastncmp("SFX_",word,4)) { // SOCs are ALL CAPS!
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "sfx '%s' could not be found.\n", word);
}
else if (mathlib && fastncmp("DS",word,2)) {
p = word+2;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word);
return 0;
}
#ifdef MUSICSLOT_COMPATIBILITY
else if (!mathlib && fastncmp("mus_",word,4)) {
p = word+4;
if ((i = get_mus(p, false)) == 0)
return 0;
lua_pushinteger(L, i);
return 1;
}
else if (mathlib && fastncmp("MUS_",word,4)) { // SOCs are ALL CAPS!
p = word+4;
if ((i = get_mus(p, false)) == 0)
return luaL_error(L, "music '%s' could not be found.\n", word);
lua_pushinteger(L, i);
return 1;
}
else if (mathlib && (fastncmp("O_",word,2) || fastncmp("D_",word,2))) {
p = word+2;
if ((i = get_mus(p, false)) == 0)
return luaL_error(L, "music '%s' could not be found.\n", word);
lua_pushinteger(L, i);
return 1;
}
#endif
else if (!mathlib && fastncmp("pw_",word,3)) {
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fasticmp(p, POWERS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
return 0;
}
else if (mathlib && fastncmp("PW_",word,3)) { // SOCs are ALL CAPS!
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fastcmp(p, POWERS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "power '%s' could not be found.\n", word);
}
else if (fastncmp("HUD_",word,4)) {
p = word+4;
for (i = 0; i < NUMHUDITEMS; i++)
if (fastcmp(p, HUDITEMS_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "huditem '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("SKINCOLOR_",word,10)) {
p = word+10;
for (i = 0; i < NUMCOLORFREESLOTS; i++) {
if (!FREE_SKINCOLORS[i])
break;
if (fastcmp(p, FREE_SKINCOLORS[i])) {
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++)
if (fastcmp(p, COLOR_ENUMS[i])) {
lua_pushinteger(L, i);
return 1;
}
return luaL_error(L, "skincolor '%s' could not be found.\n", word);
}
else if (fastncmp("GRADE_",word,6))
{
p = word+6;
for (i = 0; NIGHTSGRADE_LIST[i]; i++)
if (*p == NIGHTSGRADE_LIST[i])
{
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MN_",word,3)) {
p = word+3;
for (i = 0; i < NUMMENUTYPES; i++)
if (fastcmp(p, MENUTYPES_LIST[i])) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("A_",word,2)) {
char *caps;
// Try to get a Lua action first.
/// \todo Push a closure that sets superactions[] and superstack.
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
// actions are stored in all uppercase.
caps = Z_StrDup(word);
strupr(caps);
lua_getfield(L, -1, caps);
Z_Free(caps);
if (!lua_isnil(L, -1))
return 1; // Success! :D That was easy.
// Welp, that failed.
lua_pop(L, 2); // pop nil and LREG_ACTIONS
// Hardcoded actions as callable Lua functions!
// Retrieving them from this metatable allows them to be case-insensitive!
for (i = 0; actionpointers[i].name; i++)
if (fasticmp(word, actionpointers[i].name)) {
// We push the actionf_t* itself as userdata!
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
return 0;
}
else if (!mathlib && fastcmp("super",word))
{
if (!superstack)
{
lua_pushcfunction(L, lib_dummysuper);
return 1;
}
for (i = 0; actionpointers[i].name; i++)
if (fasticmp(superactions[superstack-1], actionpointers[i].name)) {
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
return 0;
}
if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release...
{
lua_pushinteger(L, (lua_Integer)BT_SPIN);
return 1;
}
for (i = 0; INT_CONST[i].n; i++)
if (fastcmp(word,INT_CONST[i].n)) {
lua_pushinteger(L, INT_CONST[i].v);
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
// DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here.
// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime.
return LUA_PushGlobals(L, word);
}
int LUA_EnumLib(lua_State *L)
{
if (lua_gettop(L) == 0)
lua_pushboolean(L, 0);
// Set the global metatable
lua_createtable(L, 0, 1);
lua_pushvalue(L, 1); // boolean passed to LUA_EnumLib as first argument.
lua_pushcclosure(L, lib_getenum, 1);
lua_setfield(L, -2, "__index");
lua_setmetatable(L, LUA_GLOBALSINDEX);
return 0;
}
// getActionName(action) -> return action's string name
static int lib_getActionName(lua_State *L)
{
if (lua_isuserdata(L, 1)) // arg 1 is built-in action, expect action userdata
{
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION));
const char *name = NULL;
if (!action)
return luaL_error(L, "not a valid action?");
name = LUA_GetActionName(action);
if (!name) // that can't be right?
return luaL_error(L, "no name string could be found for this action");
lua_pushstring(L, name);
return 1;
}
else if (lua_isfunction(L, 1)) // arg 1 is a function (either C or Lua)
{
lua_settop(L, 1); // set top of stack to 1 (removing any extra args, which there shouldn't be)
// get the name for this action, if possible.
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
lua_pushnil(L);
// Lua stack at this point:
// 1 ... -2 -1
// arg ... LREG_ACTIONS nil
while (lua_next(L, -2))
{
// Lua stack at this point:
// 1 ... -3 -2 -1
// arg ... LREG_ACTIONS "A_ACTION" function
if (lua_rawequal(L, -1, 1)) // is this the same as the arg?
{
// make sure the key (i.e. "A_ACTION") is a string first
// (note: we don't use lua_isstring because it also returns true for numbers)
if (lua_type(L, -2) == LUA_TSTRING)
{
lua_pushvalue(L, -2); // push "A_ACTION" string to top of stack
return 1;
}
lua_pop(L, 2); // pop the name and function
break; // probably should have succeeded but we didn't, so end the loop
}
lua_pop(L, 1);
}
lua_pop(L, 1); // pop LREG_ACTIONS
return 0; // return nothing (don't error)
}
return luaL_typerror(L, 1, "action userdata or Lua function");
}
int LUA_SOCLib(lua_State *L)
{
lua_register(L,"freeslot",lib_freeslot);
lua_register(L,"getActionName",lib_getActionName);
luaL_newmetatable(L, META_ACTION);
lua_pushcfunction(L, action_call);
lua_setfield(L, -2, "__call");
lua_pop(L, 1);
return 0;
}
const char *LUA_GetActionName(void *action)
{
actionf_t *act = (actionf_t *)action;
size_t z;
for (z = 0; actionpointers[z].name; z++)
{
if (actionpointers[z].action.acv == act->acv)
return actionpointers[z].name;
}
return NULL;
}
void LUA_SetActionByName(void *state, const char *actiontocompare)
{
state_t *st = (state_t *)state;
size_t z;
for (z = 0; actionpointers[z].name; z++)
{
if (fasticmp(actiontocompare, actionpointers[z].name))
{
st->action = actionpointers[z].action;
st->action.acv = actionpointers[z].action.acv; // assign
st->action.acp1 = actionpointers[z].action.acp1;
return;
}
}
}
enum actionnum LUA_GetActionNumByName(const char *actiontocompare)
{
size_t z;
for (z = 0; actionpointers[z].name; z++)
if (fasticmp(actiontocompare, actionpointers[z].name))
return z;
return z;
}

21
src/deh_lua.h Normal file
View File

@ -0,0 +1,21 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_lua.h
/// \brief Lua SOC library
#ifndef __DEH_LUA_H__
#define __DEH_LUA_H__
boolean LUA_SetLuaAction(void *state, const char *actiontocompare);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);
enum actionnum LUA_GetActionNumByName(const char *actiontocompare);
#endif

4527
src/deh_soc.c Normal file

File diff suppressed because it is too large Load Diff

89
src/deh_soc.h Normal file
View File

@ -0,0 +1,89 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_soc.h
/// \brief Load SOC file and change tables and text
#ifndef __DEH_SOC_H__
#define __DEH_SOC_H__
#include "doomdef.h"
#include "g_game.h"
#include "sounds.h"
#include "info.h"
#include "d_think.h"
#include "m_argv.h"
#include "z_zone.h"
#include "w_wad.h"
#include "m_menu.h"
#include "m_misc.h"
#include "f_finale.h"
#include "st_stuff.h"
#include "i_system.h"
#include "p_setup.h"
#include "r_data.h"
#include "r_textures.h"
#include "r_draw.h"
#include "r_picformats.h"
#include "r_things.h" // R_Char2Frame
#include "r_sky.h"
#include "fastcmp.h"
#include "lua_script.h" // Reluctantly included for LUA_EvalMath
#include "d_clisrv.h"
#ifdef HWRENDER
#include "hardware/hw_light.h"
#endif
#include "info.h"
#include "dehacked.h"
#include "doomdef.h" // MUSICSLOT_COMPATIBILITY, HWRENDER
// Crazy word-reading stuff
/// \todo Put these in a seperate file or something.
mobjtype_t get_mobjtype(const char *word);
statenum_t get_state(const char *word);
spritenum_t get_sprite(const char *word);
playersprite_t get_sprite2(const char *word);
sfxenum_t get_sfx(const char *word);
#ifdef MUSICSLOT_COMPATIBILITY
UINT16 get_mus(const char *word, UINT8 dehacked_mode);
#endif
hudnum_t get_huditem(const char *word);
menutype_t get_menutype(const char *word);
//INT16 get_gametype(const char *word);
//powertype_t get_power(const char *word);
skincolornum_t get_skincolor(const char *word);
void readwipes(MYFILE *f);
void readmaincfg(MYFILE *f);
void readconditionset(MYFILE *f, UINT8 setnum);
void readunlockable(MYFILE *f, INT32 num);
void readextraemblemdata(MYFILE *f, INT32 num);
void reademblemdata(MYFILE *f, INT32 num);
void readsound(MYFILE *f, INT32 num);
void readframe(MYFILE *f, INT32 num);
void readhuditem(MYFILE *f, INT32 num);
void readmenu(MYFILE *f, INT32 num);
void readtextprompt(MYFILE *f, INT32 num);
void readcutscene(MYFILE *f, INT32 num);
void readlevelheader(MYFILE *f, INT32 num);
void readgametype(MYFILE *f, char *gtname);
void readsprite2(MYFILE *f, INT32 num);
void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2);
#ifdef HWRENDER
void readlight(MYFILE *f, INT32 num);
#endif
void readskincolor(MYFILE *f, INT32 num);
void readthing(MYFILE *f, INT32 num);
void readfreeslots(MYFILE *f);
void readPlayer(MYFILE *f, INT32 num);
void clear_levels(void);
void clear_conditionsets(void);
#endif

5451
src/deh_tables.c Normal file

File diff suppressed because it is too large Load Diff

75
src/deh_tables.h Normal file
View File

@ -0,0 +1,75 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file deh_tables.h
/// \brief Define DeHackEd tables.
#ifndef __DEH_TABLES_H__
#define __DEH_TABLES_H__
#include "doomdef.h" // Constants
#include "d_think.h" // actionf_t
#include "info.h" // Mobj, state, sprite, etc constants
#include "lua_script.h"
// Free slot names
// The crazy word-reading stuff uses these.
extern char *FREE_STATES[NUMSTATEFREESLOTS];
extern char *FREE_MOBJS[NUMMOBJFREESLOTS];
extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
#define initfreeslots() {\
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
}
struct flickytypes_s {
const char *name;
const mobjtype_t type;
};
#define MAXFLICKIES 64
/** Action pointer for reading actions from Dehacked lumps.
*/
typedef struct
{
actionf_t action; ///< Function pointer corresponding to the actual action.
const char *name; ///< Name of the action in ALL CAPS.
} actionpointer_t;
struct int_const_s {
const char *n;
// has to be able to hold both fixed_t and angle_t, so drastic measure!!
lua_Integer v;
};
extern const char NIGHTSGRADE_LIST[];
extern struct flickytypes_s FLICKYTYPES[];
extern actionpointer_t actionpointers[]; // Array mapping action names to action functions.
extern const char *const STATE_LIST[];
extern const char *const MOBJTYPE_LIST[];
extern const char *const MOBJFLAG_LIST[];
extern const char *const MOBJFLAG2_LIST[]; // \tMF2_(\S+).*// (.+) --> \t"\1", // \2
extern const char *const MOBJEFLAG_LIST[];
extern const char *const MAPTHINGFLAG_LIST[4];
extern const char *const PLAYERFLAG_LIST[];
extern const char *const GAMETYPERULE_LIST[];
extern const char *const ML_LIST[16]; // Linedef flags
extern const char *COLOR_ENUMS[];
extern const char *const POWERS_LIST[];
extern const char *const HUDITEMS_LIST[];
extern const char *const MENUTYPES_LIST[];
extern struct int_const_s const INT_CONST[];
#endif

File diff suppressed because it is too large Load Diff

View File

@ -33,13 +33,15 @@ void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump, boolean mainfile);
void DEH_Check(void); void DEH_Check(void);
fixed_t get_number(const char *word); fixed_t get_number(const char *word);
FUNCPRINTF void deh_warning(const char *first, ...);
boolean LUA_SetLuaAction(void *state, const char *actiontocompare); void deh_strlcpy(char *dst, const char *src, size_t size, const char *warntext);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);
extern boolean deh_loaded; extern boolean deh_loaded;
extern boolean gamedataadded;
extern boolean titlechanged;
extern boolean introchanged;
#define MAXRECURSION 30 #define MAXRECURSION 30
extern const char *superactions[MAXRECURSION]; extern const char *superactions[MAXRECURSION];
extern UINT8 superstack; extern UINT8 superstack;
@ -60,4 +62,5 @@ typedef struct
} MYFILE; } MYFILE;
#define myfeof(a) (a->data + a->size <= a->curpos) #define myfeof(a) (a->data + a->size <= a->curpos)
char *myfgets(char *buf, size_t bufsize, MYFILE *f); char *myfgets(char *buf, size_t bufsize, MYFILE *f);
char *myhashfgets(char *buf, size_t bufsize, MYFILE *f);
#endif #endif

View File

@ -23,6 +23,7 @@
// Some global defines, that configure the game. // Some global defines, that configure the game.
#include "doomdef.h" #include "doomdef.h"
#include "taglist.h"
#include "m_fixed.h" // See the mapthing_t scale. #include "m_fixed.h" // See the mapthing_t scale.
// //
@ -208,11 +209,10 @@ typedef struct
UINT16 options; UINT16 options;
INT16 z; INT16 z;
UINT8 extrainfo; UINT8 extrainfo;
taglist_t tags;
fixed_t scale; fixed_t scale;
INT16 tag;
INT32 args[NUMMAPTHINGARGS]; INT32 args[NUMMAPTHINGARGS];
char *stringargs[NUMMAPTHINGSTRINGARGS]; char *stringargs[NUMMAPTHINGSTRINGARGS];
struct mobj_s *mobj; struct mobj_s *mobj;
} mapthing_t; } mapthing_t;

View File

@ -582,9 +582,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Dumps the contents of a network save game upon consistency failure for debugging. /// Dumps the contents of a network save game upon consistency failure for debugging.
//#define DUMPCONSISTENCY //#define DUMPCONSISTENCY
/// See name of player in your crosshair
#define SEENAMES
/// Who put weights on my recycler? ... Inuyasha did. /// Who put weights on my recycler? ... Inuyasha did.
/// \note XMOD port. /// \note XMOD port.
//#define WEIGHTEDRECYCLER //#define WEIGHTEDRECYCLER
@ -628,9 +625,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them. /// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
#define SECTORSPECIALSAFTERTHINK #define SECTORSPECIALSAFTERTHINK
/// Cache patches in Lua in a way that renderer switching will work flawlessly.
//#define LUA_PATCH_SAFETY
/// Sprite rotation /// Sprite rotation
#define ROTSPRITE #define ROTSPRITE
#define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...) #define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...)

View File

@ -410,7 +410,7 @@ enum GameType
GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1, GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1,
NUMGAMETYPES NUMGAMETYPES
}; };
// If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c // If you alter this list, update deh_tables.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c
// Gametype rules // Gametype rules
enum GameTypeRules enum GameTypeRules

View File

@ -371,4 +371,16 @@ typedef UINT32 tic_t;
#define WSTRING2(s) L ## s #define WSTRING2(s) L ## s
#define WSTRING(s) WSTRING2 (s) #define WSTRING(s) WSTRING2 (s)
/*
A hack by Monster Iestyn: Return a pointer to a field of
a struct from a pointer to another field in the struct.
Needed for some lua shenanigans.
*/
#define FIELDFROM( type, field, have, want ) \
(void *)((intptr_t)(field) - offsetof (type, have) + offsetof (type, want))
#ifdef HAVE_SDL
typedef UINT64 precise_t;
#endif
#endif //__DOOMTYPE__ #endif //__DOOMTYPE__

View File

@ -3,6 +3,7 @@
#include "../i_video.h" #include "../i_video.h"
rendermode_t rendermode = render_none; rendermode_t rendermode = render_none;
rendermode_t chosenrendermode = render_none;
boolean highcolor = false; boolean highcolor = false;
@ -40,8 +41,15 @@ INT32 VID_SetMode(INT32 modenum)
return 0; return 0;
} }
void VID_CheckRenderer(void) {} boolean VID_CheckRenderer(void)
void VID_CheckGLLoaded(rendermode_t oldrender) {} {
return false;
}
void VID_CheckGLLoaded(rendermode_t oldrender)
{
(void)oldrender;
}
const char *VID_GetModeName(INT32 modenum) const char *VID_GetModeName(INT32 modenum)
{ {

View File

@ -533,78 +533,78 @@ static void F_IntroDrawScene(void)
bgxoffs = 28; bgxoffs = 28;
break; break;
case 1: case 1:
background = W_CachePatchName("INTRO1", PU_PATCH); background = W_CachePatchName("INTRO1", PU_PATCH_LOWPRIORITY);
break; break;
case 2: case 2:
background = W_CachePatchName("INTRO2", PU_PATCH); background = W_CachePatchName("INTRO2", PU_PATCH_LOWPRIORITY);
break; break;
case 3: case 3:
background = W_CachePatchName("INTRO3", PU_PATCH); background = W_CachePatchName("INTRO3", PU_PATCH_LOWPRIORITY);
break; break;
case 4: case 4:
background = W_CachePatchName("INTRO4", PU_PATCH); background = W_CachePatchName("INTRO4", PU_PATCH_LOWPRIORITY);
break; break;
case 5: case 5:
if (intro_curtime >= 5*TICRATE) if (intro_curtime >= 5*TICRATE)
background = W_CachePatchName("RADAR", PU_PATCH); background = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("DRAT", PU_PATCH); background = W_CachePatchName("DRAT", PU_PATCH_LOWPRIORITY);
break; break;
case 6: case 6:
background = W_CachePatchName("INTRO6", PU_PATCH); background = W_CachePatchName("INTRO6", PU_PATCH_LOWPRIORITY);
cx = 180; cx = 180;
cy = 8; cy = 8;
break; break;
case 7: case 7:
{ {
if (intro_curtime >= 7*TICRATE + ((TICRATE/7)*2)) if (intro_curtime >= 7*TICRATE + ((TICRATE/7)*2))
background = W_CachePatchName("SGRASS5", PU_PATCH); background = W_CachePatchName("SGRASS5", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 7*TICRATE + (TICRATE/7)) else if (intro_curtime >= 7*TICRATE + (TICRATE/7))
background = W_CachePatchName("SGRASS4", PU_PATCH); background = W_CachePatchName("SGRASS4", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 7*TICRATE) else if (intro_curtime >= 7*TICRATE)
background = W_CachePatchName("SGRASS3", PU_PATCH); background = W_CachePatchName("SGRASS3", PU_PATCH_LOWPRIORITY);
else if (intro_curtime >= 6*TICRATE) else if (intro_curtime >= 6*TICRATE)
background = W_CachePatchName("SGRASS2", PU_PATCH); background = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("SGRASS1", PU_PATCH); background = W_CachePatchName("SGRASS1", PU_PATCH_LOWPRIORITY);
break; break;
} }
case 8: case 8:
background = W_CachePatchName("WATCHING", PU_PATCH); background = W_CachePatchName("WATCHING", PU_PATCH_LOWPRIORITY);
break; break;
case 9: case 9:
background = W_CachePatchName("ZOOMING", PU_PATCH); background = W_CachePatchName("ZOOMING", PU_PATCH_LOWPRIORITY);
break; break;
case 10: case 10:
break; break;
case 11: case 11:
background = W_CachePatchName("INTRO5", PU_PATCH); background = W_CachePatchName("INTRO5", PU_PATCH_LOWPRIORITY);
break; break;
case 12: case 12:
background = W_CachePatchName("REVENGE", PU_PATCH); background = W_CachePatchName("REVENGE", PU_PATCH_LOWPRIORITY);
cx = 208; cx = 208;
cy = 8; cy = 8;
break; break;
case 13: case 13:
background = W_CachePatchName("CONFRONT", PU_PATCH); background = W_CachePatchName("CONFRONT", PU_PATCH_LOWPRIORITY);
cy += 48; cy += 48;
break; break;
case 14: case 14:
background = W_CachePatchName("TAILSSAD", PU_PATCH); background = W_CachePatchName("TAILSSAD", PU_PATCH_LOWPRIORITY);
bgxoffs = 144; bgxoffs = 144;
cx = 8; cx = 8;
cy = 8; cy = 8;
break; break;
case 15: case 15:
if (intro_curtime >= 7*TICRATE) if (intro_curtime >= 7*TICRATE)
background = W_CachePatchName("SONICDO2", PU_PATCH); background = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("SONICDO1", PU_PATCH); background = W_CachePatchName("SONICDO1", PU_PATCH_LOWPRIORITY);
cx = 224; cx = 224;
cy = 8; cy = 8;
break; break;
case 16: case 16:
background = W_CachePatchName("INTRO7", PU_PATCH); background = W_CachePatchName("INTRO7", PU_PATCH_LOWPRIORITY);
break; break;
default: default:
break; break;
@ -635,7 +635,7 @@ static void F_IntroDrawScene(void)
strncpy(stjrintro, "STJRI029", 9); strncpy(stjrintro, "STJRI029", 9);
S_ChangeMusicInternal("_stjr", false); S_ChangeMusicInternal("_stjr", false);
background = W_CachePatchName(stjrintro, PU_PATCH); background = W_CachePatchName(stjrintro, PU_PATCH_LOWPRIORITY);
wipestyleflags = WSF_FADEIN; wipestyleflags = WSF_FADEIN;
F_WipeStartScreen(); F_WipeStartScreen();
F_TryColormapFade(31); F_TryColormapFade(31);
@ -646,7 +646,7 @@ static void F_IntroDrawScene(void)
if (!WipeInAction) // Draw the patch if not in a wipe if (!WipeInAction) // Draw the patch if not in a wipe
{ {
background = W_CachePatchName(stjrintro, PU_PATCH); background = W_CachePatchName(stjrintro, PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(bgxoffs, 84, 0, background); V_DrawSmallScaledPatch(bgxoffs, 84, 0, background);
} }
} }
@ -656,27 +656,27 @@ static void F_IntroDrawScene(void)
if (timetonext > 5*TICRATE && timetonext < 6*TICRATE) if (timetonext > 5*TICRATE && timetonext < 6*TICRATE)
{ {
if (!(finalecount & 3)) if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG1", PU_PATCH); background = W_CachePatchName("BRITEGG1", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("DARKEGG1", PU_PATCH); background = W_CachePatchName("DARKEGG1", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background); V_DrawSmallScaledPatch(0, 0, 0, background);
} }
else if (timetonext > 3*TICRATE && timetonext < 4*TICRATE) else if (timetonext > 3*TICRATE && timetonext < 4*TICRATE)
{ {
if (!(finalecount & 3)) if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG2", PU_PATCH); background = W_CachePatchName("BRITEGG2", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("DARKEGG2", PU_PATCH); background = W_CachePatchName("DARKEGG2", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background); V_DrawSmallScaledPatch(0, 0, 0, background);
} }
else if (timetonext > 1*TICRATE && timetonext < 2*TICRATE) else if (timetonext > 1*TICRATE && timetonext < 2*TICRATE)
{ {
if (!(finalecount & 3)) if (!(finalecount & 3))
background = W_CachePatchName("BRITEGG3", PU_PATCH); background = W_CachePatchName("BRITEGG3", PU_PATCH_LOWPRIORITY);
else else
background = W_CachePatchName("DARKEGG3", PU_PATCH); background = W_CachePatchName("DARKEGG3", PU_PATCH_LOWPRIORITY);
V_DrawSmallScaledPatch(0, 0, 0, background); V_DrawSmallScaledPatch(0, 0, 0, background);
} }
@ -708,79 +708,79 @@ static void F_IntroDrawScene(void)
knucklesx += sonicx; knucklesx += sonicx;
sonicx += P_ReturnThrustX(NULL, finalecount * ANG10, 3); sonicx += P_ReturnThrustX(NULL, finalecount * ANG10, 3);
V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH))); V_DrawSmallScaledPatch(skyx, 0, 0, (patch = W_CachePatchName("INTROSKY", PU_PATCH_LOWPRIORITY)));
V_DrawSmallScaledPatch(skyx - 320, 0, 0, patch); V_DrawSmallScaledPatch(skyx - 320, 0, 0, patch);
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH))); V_DrawSmallScaledPatch(grassx, 0, 0, (patch = W_CachePatchName("INTROGRS", PU_PATCH_LOWPRIORITY)));
V_DrawSmallScaledPatch(grassx - 320, 0, 0, patch); V_DrawSmallScaledPatch(grassx - 320, 0, 0, patch);
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
if (finalecount & 1) if (finalecount & 1)
{ {
// Sonic // Sonic
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH))); V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Appendages // Appendages
if (finalecount & 2) if (finalecount & 2)
{ {
// Sonic's feet // Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH))); V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT4", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Tails' tails // Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
else else
{ {
// Sonic's feet // Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH))); V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Tails' tails // Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
// Tails // Tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Knuckles // Knuckles
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH))); V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
else else
{ {
// Sonic // Sonic
V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH))); V_DrawSmallScaledPatch(sonicx, 54, 0, (patch = W_CachePatchName("RUN1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Appendages // Appendages
if (finalecount & 2) if (finalecount & 2)
{ {
// Sonic's feet // Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH))); V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT3", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Tails' tails // Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP2", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
else else
{ {
// Sonic's feet // Sonic's feet
V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH))); V_DrawSmallScaledPatch(sonicx - 8, 92, 0, (patch = W_CachePatchName("PEELOUT1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Tails' tails // Tails' tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("HELICOP1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
// Tails // Tails
V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH))); V_DrawSmallScaledPatch(tailsx, tailsy, 0, (patch = W_CachePatchName("FLY1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
// Knuckles // Knuckles
V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH))); V_DrawSmallScaledPatch(knucklesx, knucklesy, 0, (patch = W_CachePatchName("GLIDE1", PU_PATCH_LOWPRIORITY)));
W_UnlockCachedPatch(patch); W_UnlockCachedPatch(patch);
} }
@ -813,8 +813,8 @@ static void F_IntroDrawScene(void)
y += (30*(FRACUNIT-scale)); y += (30*(FRACUNIT-scale));
} }
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH); rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH); glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_PATCH_LOWPRIORITY);
if (worktics >= 5) if (worktics >= 5)
trans = (worktics-5)>>1; trans = (worktics-5)>>1;
@ -934,7 +934,7 @@ void F_IntroDrawer(void)
{ {
if (intro_scenenum == 5 && intro_curtime == 5*TICRATE) if (intro_scenenum == 5 && intro_curtime == 5*TICRATE)
{ {
patch_t *radar = W_CachePatchName("RADAR", PU_PATCH); patch_t *radar = W_CachePatchName("RADAR", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen(); F_WipeStartScreen();
F_WipeColorFill(31); F_WipeColorFill(31);
@ -947,7 +947,7 @@ void F_IntroDrawer(void)
} }
else if (intro_scenenum == 7 && intro_curtime == 6*TICRATE) // Force a wipe here else if (intro_scenenum == 7 && intro_curtime == 6*TICRATE) // Force a wipe here
{ {
patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH); patch_t *grass = W_CachePatchName("SGRASS2", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen(); F_WipeStartScreen();
F_WipeColorFill(31); F_WipeColorFill(31);
@ -960,7 +960,7 @@ void F_IntroDrawer(void)
} }
/*else if (intro_scenenum == 11 && intro_curtime == 7*TICRATE) /*else if (intro_scenenum == 11 && intro_curtime == 7*TICRATE)
{ {
patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH); patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen(); F_WipeStartScreen();
F_WipeColorFill(31); F_WipeColorFill(31);
@ -973,7 +973,7 @@ void F_IntroDrawer(void)
}*/ }*/
if (intro_scenenum == 15 && intro_curtime == 7*TICRATE) if (intro_scenenum == 15 && intro_curtime == 7*TICRATE)
{ {
patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH); patch_t *sdo = W_CachePatchName("SONICDO2", PU_PATCH_LOWPRIORITY);
F_WipeStartScreen(); F_WipeStartScreen();
F_WipeColorFill(31); F_WipeColorFill(31);
@ -1074,6 +1074,7 @@ static const char *credits[] = {
"\1Programming", "\1Programming",
"Alam \"GBC\" Arias", "Alam \"GBC\" Arias",
"Logan \"GBA\" Arias", "Logan \"GBA\" Arias",
"Zolton \"Zippy_Zolton\" Auburn",
"Colette \"fickleheart\" Bordelon", "Colette \"fickleheart\" Bordelon",
"Andrew \"orospakr\" Clunis", "Andrew \"orospakr\" Clunis",
"Sally \"TehRealSalt\" Cochenour", "Sally \"TehRealSalt\" Cochenour",
@ -1104,6 +1105,7 @@ static const char *credits[] = {
"Sean \"Sryder13\" Ryder", "Sean \"Sryder13\" Ryder",
"Ehab \"Wolfy\" Saeed", "Ehab \"Wolfy\" Saeed",
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible "Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
"Riku \"Ors\" Salminen", // Demo consistency improvements
"Jonas \"MascaraSnake\" Sauer", "Jonas \"MascaraSnake\" Sauer",
"Wessel \"sphere\" Smit", "Wessel \"sphere\" Smit",
"\"SSNTails\"", "\"SSNTails\"",
@ -1127,6 +1129,7 @@ static const char *credits[] = {
"Sherman \"CoatRack\" DesJardins", "Sherman \"CoatRack\" DesJardins",
"\"DirkTheHusky\"", "\"DirkTheHusky\"",
"Jesse \"Jeck Jims\" Emerick", "Jesse \"Jeck Jims\" Emerick",
"\"Fighter_Builder\"", // for the CEZ3 button debris
"Buddy \"KinkaJoy\" Fischer", "Buddy \"KinkaJoy\" Fischer",
"Vivian \"toaster\" Grannell", "Vivian \"toaster\" Grannell",
"James \"SwitchKaze\" Hale", "James \"SwitchKaze\" Hale",
@ -1207,7 +1210,7 @@ static const char *credits[] = {
"\1Testing", "\1Testing",
"Discord Community Testers", "Discord Community Testers",
"Hank \"FuriousFox\" Brannock", "Hank \"FuriousFox\" Brannock",
"Cody \"SRB2 Playah\" Koester", "Cody \"Playah\" Koester",
"Skye \"OmegaVelocity\" Meredith", "Skye \"OmegaVelocity\" Meredith",
"Stephen \"HEDGESMFG\" Moellering", "Stephen \"HEDGESMFG\" Moellering",
"Rosalie \"ST218\" Molina", "Rosalie \"ST218\" Molina",
@ -1302,14 +1305,14 @@ void F_CreditDrawer(void)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
// Zig Zagz // Zig Zagz
V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH)); V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH)); V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH)); V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH)); V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
// Draw background pictures first // Draw background pictures first
for (i = 0; credits_pics[i].patch; i++) for (i = 0; credits_pics[i].patch; i++)
V_DrawSciencePatch(credits_pics[i].x<<FRACBITS, (280<<FRACBITS) + (((i*credits_height)<<FRACBITS)/(credits_numpics)) - 4*(animtimer<<FRACBITS)/5, 0, W_CachePatchName(credits_pics[i].patch, PU_PATCH), FRACUNIT>>1); V_DrawSciencePatch(credits_pics[i].x<<FRACBITS, (280<<FRACBITS) + (((i*credits_height)<<FRACBITS)/(credits_numpics)) - 4*(animtimer<<FRACBITS)/5, 0, W_CachePatchName(credits_pics[i].patch, PU_PATCH_LOWPRIORITY), FRACUNIT>>1);
// Dim the background // Dim the background
V_DrawFadeScreen(0xFF00, 16); V_DrawFadeScreen(0xFF00, 16);
@ -1518,14 +1521,14 @@ void F_GameEvaluationDrawer(void)
if (goodending) if (goodending)
{ {
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH); rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH); glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH_LOWPRIORITY);
x -= FRACUNIT; x -= FRACUNIT;
} }
else else
{ {
rockpat = W_CachePatchName("ROID0000", PU_LEVEL); rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY);
glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH); glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH_LOWPRIORITY);
} }
if (finalecount >= 5) if (finalecount >= 5)
@ -1557,20 +1560,20 @@ void F_GameEvaluationDrawer(void)
// if j == 0 - alternate between 0 and 1 // if j == 0 - alternate between 0 and 1
// 1 - 1 and 2 // 1 - 1 and 2
// 2 - 2 and not rendered // 2 - 2 and not rendered
V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE)); V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH_LOWPRIORITY), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE));
} }
j--; j--;
} }
} }
else else
{ {
patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH); patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH_LOWPRIORITY);
V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]); V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]);
if (trans < 10) if (trans < 10)
V_DrawFixedPatch(x, y, scale, trans<<V_ALPHASHIFT, eggrock, colormap[1]); V_DrawFixedPatch(x, y, scale, trans<<V_ALPHASHIFT, eggrock, colormap[1]);
else if (sparklloop) else if (sparklloop)
V_DrawFixedPatch(x, y, scale, (10-sparklloop)<<V_ALPHASHIFT, V_DrawFixedPatch(x, y, scale, (10-sparklloop)<<V_ALPHASHIFT,
W_CachePatchName("ENDEGRK0", PU_PATCH), colormap[1]); W_CachePatchName("ENDEGRK0", PU_PATCH_LOWPRIORITY), colormap[1]);
} }
} }
@ -1584,7 +1587,7 @@ void F_GameEvaluationDrawer(void)
eemeralds_cur += (360<<FRACBITS)/7; eemeralds_cur += (360<<FRACBITS)/7;
patchname[4] = 'A'+(char)i; patchname[4] = 'A'+(char)i;
V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<<i)) ? 0 : V_80TRANS), W_CachePatchName(patchname, PU_PATCH), NULL); V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<<i)) ? 0 : V_80TRANS), W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY), NULL);
} }
V_DrawCreditString((BASEVIDWIDTH - V_CreditStringWidth(endingtext))<<(FRACBITS-1), (BASEVIDHEIGHT-100)<<(FRACBITS-1), 0, endingtext); V_DrawCreditString((BASEVIDWIDTH - V_CreditStringWidth(endingtext))<<(FRACBITS-1), (BASEVIDHEIGHT-100)<<(FRACBITS-1), 0, endingtext);
@ -1713,32 +1716,32 @@ void F_GameEvaluationTicker(void)
static void F_CacheEnding(void) static void F_CacheEnding(void)
{ {
endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH); endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH_LOWPRIORITY);
endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH); endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH_LOWPRIORITY);
endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH); endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH_LOWPRIORITY);
endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH); endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH_LOWPRIORITY);
endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH); endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH_LOWPRIORITY);
endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH); endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH_LOWPRIORITY);
endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH); endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH_LOWPRIORITY);
endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH); endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH_LOWPRIORITY);
endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH); endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH_LOWPRIORITY);
endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH); endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH_LOWPRIORITY);
endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH); endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH_LOWPRIORITY);
endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH); endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH_LOWPRIORITY);
endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH); endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH_LOWPRIORITY);
endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH); endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH_LOWPRIORITY);
endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH); endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH_LOWPRIORITY);
endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH); endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH_LOWPRIORITY);
endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH); endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH_LOWPRIORITY);
endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH); endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH_LOWPRIORITY);
endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH); endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH_LOWPRIORITY);
endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH); endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH_LOWPRIORITY);
// so we only need to check once // so we only need to check once
if ((goodending = ALL7EMERALDS(emeralds))) if ((goodending = ALL7EMERALDS(emeralds)))
@ -1751,41 +1754,41 @@ static void F_CacheEnding(void)
sprdef = &skins[skinnum].sprites[SPR2_XTRA]; sprdef = &skins[skinnum].sprites[SPR2_XTRA];
// character head, skin specific // character head, skin specific
sprframe = &sprdef->spriteframes[XTRA_ENDING]; sprframe = &sprdef->spriteframes[XTRA_ENDING];
endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
sprframe = &sprdef->spriteframes[XTRA_ENDING+1]; sprframe = &sprdef->spriteframes[XTRA_ENDING+1];
endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
sprframe = &sprdef->spriteframes[XTRA_ENDING+2]; sprframe = &sprdef->spriteframes[XTRA_ENDING+2];
endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY);
} }
else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this) else // Show a star if your character doesn't have an ending firework display. (Basically the MISSINGs for this)
{ {
endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH); endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH_LOWPRIORITY);
endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH); endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH_LOWPRIORITY);
endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH); endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH_LOWPRIORITY);
} }
endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH); endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH_LOWPRIORITY);
} }
else else
{ {
// eggman, skin nonspecific // eggman, skin nonspecific
endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH); endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH_LOWPRIORITY);
endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH); endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH_LOWPRIORITY);
endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH); endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH_LOWPRIORITY);
endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL); endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_PATCH_LOWPRIORITY);
} }
} }
static void F_CacheGoodEnding(void) static void F_CacheGoodEnding(void)
{ {
endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH); endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH_LOWPRIORITY);
endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH); endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH_LOWPRIORITY);
endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH); endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH_LOWPRIORITY);
endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH); endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH_LOWPRIORITY);
endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH); endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH_LOWPRIORITY);
} }
void F_StartEnding(void) void F_StartEnding(void)
@ -1842,17 +1845,10 @@ void F_EndingDrawer(void)
INT32 x, y, i, j, parallaxticker; INT32 x, y, i, j, parallaxticker;
patch_t *rockpat; patch_t *rockpat;
if (needpatchrecache)
{
F_CacheEnding();
if (goodending && finalecount >= INFLECTIONPOINT) // time to swap some assets
F_CacheGoodEnding();
}
if (!goodending || finalecount < INFLECTIONPOINT) if (!goodending || finalecount < INFLECTIONPOINT)
rockpat = W_CachePatchName("ROID0000", PU_PATCH); rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY);
else else
rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH); rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH_LOWPRIORITY);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
@ -2189,7 +2185,7 @@ void F_EndingDrawer(void)
eemeralds_cur[0] += (360<<FRACBITS)/7; eemeralds_cur[0] += (360<<FRACBITS)/7;
patchname[4] = 'A'+(char)i; patchname[4] = 'A'+(char)i;
V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_LEVEL), NULL); V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY), NULL);
} }
} // if (goodending... } // if (goodending...
} // (finalecount > 20) } // (finalecount > 20)
@ -2336,14 +2332,14 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
if (!scrollxspeed && !scrollyspeed) if (!scrollxspeed && !scrollyspeed)
{ {
V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH)); V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY));
return; return;
} }
pat = W_CachePatchName(patchname, PU_PATCH); pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY);
patwidth = SHORT(pat->width); patwidth = pat->width;
patheight = SHORT(pat->height); patheight = pat->height;
pw = patwidth * dupz; pw = patwidth * dupz;
ph = patheight * dupz; ph = patheight * dupz;
@ -2379,7 +2375,7 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
lumpnum = W_CheckNumForName(name); \ lumpnum = W_CheckNumForName(name); \
if (lumpnum != LUMPERROR) \ if (lumpnum != LUMPERROR) \
{ \ { \
arr[0] = W_CachePatchName(name, PU_LEVEL); \ arr[0] = W_CachePatchName(name, PU_PATCH_LOWPRIORITY); \
arr[min(1, maxf-1)] = 0; \ arr[min(1, maxf-1)] = 0; \
} \ } \
else if (strlen(name) <= 6) \ else if (strlen(name) <= 6) \
@ -2392,7 +2388,7 @@ else if (strlen(name) <= 6) \
lumpname[8] = 0; \ lumpname[8] = 0; \
lumpnum = W_CheckNumForName(lumpname); \ lumpnum = W_CheckNumForName(lumpname); \
if (lumpnum != LUMPERROR) \ if (lumpnum != LUMPERROR) \
arr[i] = W_CachePatchName(lumpname, PU_LEVEL); \ arr[i] = W_CachePatchName(lumpname, PU_PATCH_LOWPRIORITY); \
else \ else \
break; \ break; \
} \ } \
@ -2407,21 +2403,21 @@ static void F_CacheTitleScreen(void)
{ {
case TTMODE_OLD: case TTMODE_OLD:
case TTMODE_NONE: case TTMODE_NONE:
ttbanner = W_CachePatchName("TTBANNER", PU_LEVEL); ttbanner = W_CachePatchName("TTBANNER", PU_PATCH_LOWPRIORITY);
ttwing = W_CachePatchName("TTWING", PU_LEVEL); ttwing = W_CachePatchName("TTWING", PU_PATCH_LOWPRIORITY);
ttsonic = W_CachePatchName("TTSONIC", PU_LEVEL); ttsonic = W_CachePatchName("TTSONIC", PU_PATCH_LOWPRIORITY);
ttswave1 = W_CachePatchName("TTSWAVE1", PU_LEVEL); ttswave1 = W_CachePatchName("TTSWAVE1", PU_PATCH_LOWPRIORITY);
ttswave2 = W_CachePatchName("TTSWAVE2", PU_LEVEL); ttswave2 = W_CachePatchName("TTSWAVE2", PU_PATCH_LOWPRIORITY);
ttswip1 = W_CachePatchName("TTSWIP1", PU_LEVEL); ttswip1 = W_CachePatchName("TTSWIP1", PU_PATCH_LOWPRIORITY);
ttsprep1 = W_CachePatchName("TTSPREP1", PU_LEVEL); ttsprep1 = W_CachePatchName("TTSPREP1", PU_PATCH_LOWPRIORITY);
ttsprep2 = W_CachePatchName("TTSPREP2", PU_LEVEL); ttsprep2 = W_CachePatchName("TTSPREP2", PU_PATCH_LOWPRIORITY);
ttspop1 = W_CachePatchName("TTSPOP1", PU_LEVEL); ttspop1 = W_CachePatchName("TTSPOP1", PU_PATCH_LOWPRIORITY);
ttspop2 = W_CachePatchName("TTSPOP2", PU_LEVEL); ttspop2 = W_CachePatchName("TTSPOP2", PU_PATCH_LOWPRIORITY);
ttspop3 = W_CachePatchName("TTSPOP3", PU_LEVEL); ttspop3 = W_CachePatchName("TTSPOP3", PU_PATCH_LOWPRIORITY);
ttspop4 = W_CachePatchName("TTSPOP4", PU_LEVEL); ttspop4 = W_CachePatchName("TTSPOP4", PU_PATCH_LOWPRIORITY);
ttspop5 = W_CachePatchName("TTSPOP5", PU_LEVEL); ttspop5 = W_CachePatchName("TTSPOP5", PU_PATCH_LOWPRIORITY);
ttspop6 = W_CachePatchName("TTSPOP6", PU_LEVEL); ttspop6 = W_CachePatchName("TTSPOP6", PU_PATCH_LOWPRIORITY);
ttspop7 = W_CachePatchName("TTSPOP7", PU_LEVEL); ttspop7 = W_CachePatchName("TTSPOP7", PU_PATCH_LOWPRIORITY);
break; break;
// don't load alacroix gfx yet; we do that upon first draw. // don't load alacroix gfx yet; we do that upon first draw.
@ -2541,7 +2537,7 @@ void F_StartTitleScreen(void)
static void F_UnloadAlacroixGraphics(SINT8 oldttscale) static void F_UnloadAlacroixGraphics(SINT8 oldttscale)
{ {
// This all gets freed by PU_LEVEL when exiting the menus. // This all gets freed by PU_PATCH_LOWPRIORITY when exiting the menus.
// When re-visiting the menus (e.g., from exiting in-game), the gfx are force-reloaded. // When re-visiting the menus (e.g., from exiting in-game), the gfx are force-reloaded.
// So leftover addresses here should not be a problem. // So leftover addresses here should not be a problem.
@ -2647,17 +2643,12 @@ static void F_FigureActiveTtScale(void)
SINT8 newttscale = max(1, min(6, vid.dupx)); SINT8 newttscale = max(1, min(6, vid.dupx));
SINT8 oldttscale = activettscale; SINT8 oldttscale = activettscale;
if (needpatchrecache) if (newttscale == testttscale)
ttloaded[0] = ttloaded[1] = ttloaded[2] = ttloaded[3] = ttloaded[4] = ttloaded[5] = 0; return;
else
{
if (newttscale == testttscale)
return;
// We have a new ttscale, so load gfx // We have a new ttscale, so load gfx
if(oldttscale > 0) if(oldttscale > 0)
F_UnloadAlacroixGraphics(oldttscale); F_UnloadAlacroixGraphics(oldttscale);
}
testttscale = newttscale; testttscale = newttscale;
@ -2691,9 +2682,6 @@ void F_TitleScreenDrawer(void)
if (modeattacking) if (modeattacking)
return; // We likely came here from retrying. Don't do a damn thing. return; // We likely came here from retrying. Don't do a damn thing.
if (needpatchrecache && (curttmode != TTMODE_ALACROIX))
F_CacheTitleScreen();
// Draw that sky! // Draw that sky!
if (curbgcolor >= 0) if (curbgcolor >= 0)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
@ -3657,7 +3645,7 @@ void F_ContinueDrawer(void)
V_DrawLevelTitle(x - (V_LevelNameWidth("Continue?")>>1), 16, 0, "Continue?"); V_DrawLevelTitle(x - (V_LevelNameWidth("Continue?")>>1), 16, 0, "Continue?");
// Two stars... // Two stars...
patch = W_CachePatchName("CONTSTAR", PU_PATCH); patch = W_CachePatchName("CONTSTAR", PU_PATCH_LOWPRIORITY);
V_DrawScaledPatch(x-32, 160, 0, patch); V_DrawScaledPatch(x-32, 160, 0, patch);
V_DrawScaledPatch(x+32, 160, 0, patch); V_DrawScaledPatch(x+32, 160, 0, patch);
@ -3665,14 +3653,14 @@ void F_ContinueDrawer(void)
if (timeleft > 9) if (timeleft > 9)
{ {
numbuf[7] = '1'; numbuf[7] = '1';
V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); V_DrawScaledPatch(x - 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
numbuf[7] = '0'; numbuf[7] = '0';
V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); V_DrawScaledPatch(x + 10, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
} }
else else
{ {
numbuf[7] = '0'+timeleft; numbuf[7] = '0'+timeleft;
V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH)); V_DrawScaledPatch(x, 160, 0, W_CachePatchName(numbuf, PU_PATCH_LOWPRIORITY));
} }
// Draw the continue markers! Show continues. // Draw the continue markers! Show continues.
@ -3701,7 +3689,7 @@ void F_ContinueDrawer(void)
} }
// Spotlight // Spotlight
V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH)); V_DrawScaledPatch(x, 140, 0, W_CachePatchName("CONTSPOT", PU_PATCH_LOWPRIORITY));
// warping laser // warping laser
if (continuetime) if (continuetime)
@ -3738,7 +3726,7 @@ void F_ContinueDrawer(void)
#define drawchar(dx, dy, n) {\ #define drawchar(dx, dy, n) {\
sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\ sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\
sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\ sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\
patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH);\ patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH_LOWPRIORITY);\
V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\ V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\
} }
@ -4003,10 +3991,10 @@ void F_CutsceneDrawer(void)
{ {
if (cutscenes[cutnum]->scene[scenenum].pichires[picnum]) if (cutscenes[cutnum]->scene[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0, V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
else else
V_DrawScaledPatch(picxpos,picypos, 0, V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
} }
if (dofadenow && rendermode != render_none) if (dofadenow && rendermode != render_none)
@ -4492,10 +4480,10 @@ void F_TextPromptDrawer(void)
{ {
if (textprompts[cutnum]->page[scenenum].pichires[picnum]) if (textprompts[cutnum]->page[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0, V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
else else
V_DrawScaledPatch(picxpos,picypos, 0, V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
} }
// Draw background // Draw background
@ -4505,7 +4493,7 @@ void F_TextPromptDrawer(void)
if (iconlump != LUMPERROR) if (iconlump != LUMPERROR)
{ {
INT32 iconx, icony, scale, scaledsize; INT32 iconx, icony, scale, scaledsize;
patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH); patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH_LOWPRIORITY);
// scale and center // scale and center
if (patch->width > patch->height) if (patch->width > patch->height)

View File

@ -293,7 +293,7 @@ static void F_DoWipe(fademask_t *fademask)
else else
{ {
// pointer to transtable that this mask would use // pointer to transtable that this mask would use
transtbl = transtables + ((9 - *mask)<<FF_TRANSSHIFT); transtbl = R_GetTranslucencyTable((9 - *mask) + 1);
// DRAWING LOOP // DRAWING LOOP
while (draw_linestogo--) while (draw_linestogo--)

View File

@ -453,8 +453,7 @@ void G_WriteGhostTic(mobj_t *ghost)
WRITEUINT16(demo_p,oldghost.sprite); WRITEUINT16(demo_p,oldghost.sprite);
if (ghostext.flags & EZT_HEIGHT) if (ghostext.flags & EZT_HEIGHT)
{ {
height >>= FRACBITS; WRITEFIXED(demo_p, height);
WRITEINT16(demo_p, height);
} }
ghostext.flags = 0; ghostext.flags = 0;
} }
@ -610,7 +609,7 @@ void G_ConsGhostTic(void)
if (xziptic & EZT_SPRITE) if (xziptic & EZT_SPRITE)
demo_p += sizeof(UINT16); demo_p += sizeof(UINT16);
if (xziptic & EZT_HEIGHT) if (xziptic & EZT_HEIGHT)
demo_p += sizeof(INT16); demo_p += (demoversion < 0x000e) ? sizeof(INT16) : sizeof(fixed_t);
} }
if (ziptic & GZT_FOLLOW) if (ziptic & GZT_FOLLOW)
@ -625,7 +624,7 @@ void G_ConsGhostTic(void)
if (followtic & FZT_SCALE) if (followtic & FZT_SCALE)
demo_p += sizeof(fixed_t); demo_p += sizeof(fixed_t);
// momx, momy and momz // momx, momy and momz
demo_p += (demoversion < 0x000e) ? sizeof(UINT16) * 3 : sizeof(fixed_t) * 3; demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3;
if (followtic & FZT_SKIN) if (followtic & FZT_SKIN)
demo_p++; demo_p++;
demo_p += sizeof(UINT16); demo_p += sizeof(UINT16);
@ -842,7 +841,7 @@ void G_GhostTicker(void)
g->mo->sprite = READUINT16(g->p); g->mo->sprite = READUINT16(g->p);
if (xziptic & EZT_HEIGHT) if (xziptic & EZT_HEIGHT)
{ {
fixed_t temp = READINT16(g->p)<<FRACBITS; fixed_t temp = (g->version < 0x000e) ? READINT16(g->p)<<FRACBITS : READFIXED(g->p);
g->mo->height = FixedMul(temp, g->mo->scale); g->mo->height = FixedMul(temp, g->mo->scale);
} }
} }
@ -1106,7 +1105,7 @@ void G_ReadMetalTic(mobj_t *metal)
metal->sprite = READUINT16(metal_p); metal->sprite = READUINT16(metal_p);
if (xziptic & EZT_HEIGHT) if (xziptic & EZT_HEIGHT)
{ {
fixed_t temp = READINT16(metal_p)<<FRACBITS; fixed_t temp = (metalversion < 0x000e) ? READINT16(metal_p)<<FRACBITS : READFIXED(metal_p);
metal->height = FixedMul(temp, metal->scale); metal->height = FixedMul(temp, metal->scale);
} }
} }
@ -1293,8 +1292,7 @@ void G_WriteMetalTic(mobj_t *metal)
WRITEUINT16(demo_p,oldmetal.sprite); WRITEUINT16(demo_p,oldmetal.sprite);
if (ghostext.flags & EZT_HEIGHT) if (ghostext.flags & EZT_HEIGHT)
{ {
height >>= FRACBITS; WRITEFIXED(demo_p, height);
WRITEINT16(demo_p, height);
} }
ghostext.flags = 0; ghostext.flags = 0;
} }
@ -1474,8 +1472,8 @@ void G_BeginRecording(void)
WRITEUINT8(demo_p,player->thrustfactor); WRITEUINT8(demo_p,player->thrustfactor);
WRITEUINT8(demo_p,player->accelstart); WRITEUINT8(demo_p,player->accelstart);
WRITEUINT8(demo_p,player->acceleration); WRITEUINT8(demo_p,player->acceleration);
WRITEUINT8(demo_p,player->height>>FRACBITS); WRITEFIXED(demo_p,player->height);
WRITEUINT8(demo_p,player->spinheight>>FRACBITS); WRITEFIXED(demo_p,player->spinheight);
WRITEUINT8(demo_p,player->camerascale>>FRACBITS); WRITEUINT8(demo_p,player->camerascale>>FRACBITS);
WRITEUINT8(demo_p,player->shieldscale>>FRACBITS); WRITEUINT8(demo_p,player->shieldscale>>FRACBITS);
@ -1901,8 +1899,8 @@ void G_DoPlayDemo(char *defdemoname)
thrustfactor = READUINT8(demo_p); thrustfactor = READUINT8(demo_p);
accelstart = READUINT8(demo_p); accelstart = READUINT8(demo_p);
acceleration = READUINT8(demo_p); acceleration = READUINT8(demo_p);
height = (fixed_t)READUINT8(demo_p)<<FRACBITS; height = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
spinheight = (fixed_t)READUINT8(demo_p)<<FRACBITS; spinheight = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS; camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS; shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
jumpfactor = READFIXED(demo_p); jumpfactor = READFIXED(demo_p);
@ -1958,9 +1956,7 @@ void G_DoPlayDemo(char *defdemoname)
// Set skin // Set skin
SetPlayerSkin(0, skin); SetPlayerSkin(0, skin);
#ifdef HAVE_BLUA
LUAh_MapChange(gamemap); LUAh_MapChange(gamemap);
#endif
displayplayer = consoleplayer = 0; displayplayer = consoleplayer = 0;
memset(playeringame,0,sizeof(playeringame)); memset(playeringame,0,sizeof(playeringame));
playeringame[0] = true; playeringame[0] = true;
@ -2150,8 +2146,7 @@ void G_AddGhost(char *defdemoname)
p++; // thrustfactor p++; // thrustfactor
p++; // accelstart p++; // accelstart
p++; // acceleration p++; // acceleration
p++; // height p += (ghostversion < 0x000e) ? 2 : 2 * sizeof(fixed_t); // height and spinheight
p++; // spinheight
p++; // camerascale p++; // camerascale
p++; // shieldscale p++; // shieldscale
p += 4; // jumpfactor p += 4; // jumpfactor
@ -2163,7 +2158,7 @@ void G_AddGhost(char *defdemoname)
count = READUINT16(p); count = READUINT16(p);
while (count--) while (count--)
{ {
p += 2; SKIPSTRING(p);
SKIPSTRING(p); SKIPSTRING(p);
p++; p++;
} }

View File

@ -444,9 +444,7 @@ consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, j
consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL); consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
#ifdef SEENAMES
player_t *seenplayer; // player we're aiming at right now player_t *seenplayer; // player we're aiming at right now
#endif
// now automatically allocated in D_RegisterClientCommands // now automatically allocated in D_RegisterClientCommands
// so that it doesn't have to be updated depending on the value of MAXPLAYERS // so that it doesn't have to be updated depending on the value of MAXPLAYERS
@ -1677,10 +1675,26 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
} }
} }
// Note: Lat originally made the PlayerCmd hook for SRB2 Kart so credit goes to him. // At this point, cmd doesn't contain the final angle yet,
// So we need to temporarily transform it so Lua scripters
// don't need to handle it differently than in other hooks.
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{
INT16 extra = ticcmd_oldangleturn[forplayer] - player->oldrelangleturn;
INT16 origangle = cmd->angleturn;
INT16 orighookangle = (INT16)(origangle + player->angleturn + extra);
INT16 origaiming = cmd->aiming;
cmd->angleturn = orighookangle;
LUAh_PlayerCmd(player, cmd); LUAh_PlayerCmd(player, cmd);
extra = cmd->angleturn - orighookangle;
cmd->angleturn = origangle + extra;
*myangle += extra << 16;
*myaiming += (cmd->aiming - origaiming) << 16;
}
//Reset away view if a command is given. //Reset away view if a command is given.
if (ssplayer == 1 && (cmd->forwardmove || cmd->sidemove || cmd->buttons) if (ssplayer == 1 && (cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer) && displayplayer != consoleplayer)
@ -1829,7 +1843,7 @@ void G_DoLoadLevel(boolean resetplayer)
} }
// Setup the level. // Setup the level.
if (!P_LoadLevel(false)) // this never returns false? if (!P_LoadLevel(false, false)) // this never returns false?
{ {
// fail so reset game stuff // fail so reset game stuff
Command_ExitGame_f(); Command_ExitGame_f();
@ -2216,8 +2230,35 @@ void G_Ticker(boolean run)
// Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run. // Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime) if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
{ {
player_t *p = &players[consoleplayer];
marathonmode |= MA_INIT; marathonmode |= MA_INIT;
marathontime = 0; marathontime = 0;
numgameovers = tokenlist = token = 0;
countdown = countdown2 = exitfadestarted = 0;
p->playerstate = PST_REBORN;
p->starpostx = p->starposty = p->starpostz = 0;
p->lives = startinglivesbalance[0];
p->continues = 1;
p->score = 0;
// The latter two should clear by themselves, but just in case
p->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
// Clear cheatcodes too, just in case.
p->pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
p->xtralife = 0;
// Reset unlockable triggers
unlocktriggers = 0;
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
} }
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES) else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1; players[consoleplayer].lives -= 1;

View File

@ -25,9 +25,7 @@ extern char timeattackfolder[64];
extern char customversionstring[32]; extern char customversionstring[32];
#define GAMEDATASIZE (4*8192) #define GAMEDATASIZE (4*8192)
#ifdef SEENAMES
extern player_t *seenplayer; extern player_t *seenplayer;
#endif
extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
extern INT32 player_name_changes[MAXPLAYERS]; extern INT32 player_name_changes[MAXPLAYERS];

View File

@ -1,7 +1,6 @@
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
@ -249,12 +248,12 @@ void HWR_RenderBatches(void)
} }
// sort polygons // sort polygons
ps_hw_batchsorttime = I_GetTimeMicros(); ps_hw_batchsorttime = I_GetPreciseTime();
if (cv_glshaders.value && gl_shadersavailable) if (cv_glshaders.value && gl_shadersavailable)
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
else else
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
ps_hw_batchsorttime = I_GetTimeMicros() - ps_hw_batchsorttime; ps_hw_batchsorttime = I_GetPreciseTime() - ps_hw_batchsorttime;
// sort order // sort order
// 1. shader // 1. shader
// 2. texture // 2. texture
@ -262,7 +261,7 @@ void HWR_RenderBatches(void)
// 4. colors + light level // 4. colors + light level
// not sure about what order of the last 2 should be, or if it even matters // not sure about what order of the last 2 should be, or if it even matters
ps_hw_batchdrawtime = I_GetTimeMicros(); ps_hw_batchdrawtime = I_GetPreciseTime();
currentShader = polygonArray[polygonIndexArray[0]].shader; currentShader = polygonArray[polygonIndexArray[0]].shader;
currentTexture = polygonArray[polygonIndexArray[0]].texture; currentTexture = polygonArray[polygonIndexArray[0]].texture;
@ -447,7 +446,7 @@ void HWR_RenderBatches(void)
polygonArraySize = 0; polygonArraySize = 0;
unsortedVertexArraySize = 0; unsortedVertexArraySize = 0;
ps_hw_batchdrawtime = I_GetTimeMicros() - ps_hw_batchdrawtime; ps_hw_batchdrawtime = I_GetPreciseTime() - ps_hw_batchdrawtime;
} }

View File

@ -1,7 +1,6 @@
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
@ -17,7 +16,7 @@
#include "hw_data.h" #include "hw_data.h"
#include "hw_drv.h" #include "hw_drv.h"
typedef struct typedef struct
{ {
FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused
unsigned int vertsIndex;// location of verts in unsortedVertexArray unsigned int vertsIndex;// location of verts in unsortedVertexArray

View File

@ -25,6 +25,7 @@
#include "../z_zone.h" #include "../z_zone.h"
#include "../v_video.h" #include "../v_video.h"
#include "../r_draw.h" #include "../r_draw.h"
#include "../r_patch.h"
#include "../r_picformats.h" #include "../r_picformats.h"
#include "../p_setup.h" #include "../p_setup.h"
@ -306,7 +307,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
// Draw each column to the block cache // Draw each column to the block cache
for (; ncols--; block += bpp, xfrac += xfracstep) for (; ncols--; block += bpp, xfrac += xfracstep)
{ {
patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS])); patchcol = (const column_t *)((const UINT8 *)realpatch->columns + (realpatch->columnofs[xfrac>>FRACBITS]));
HWR_DrawColumnInCache(patchcol, block, mipmap, HWR_DrawColumnInCache(patchcol, block, mipmap,
pblockheight, blockmodulo, pblockheight, blockmodulo,
@ -320,7 +321,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
INT32 pblockwidth, INT32 pblockheight, INT32 pblockwidth, INT32 pblockheight,
texture_t *texture, texpatch_t *patch, texture_t *texture, texpatch_t *patch,
const patch_t *realpatch) const softwarepatch_t *realpatch)
{ {
INT32 x, x1, x2; INT32 x, x1, x2;
INT32 col, ncols; INT32 col, ncols;
@ -391,7 +392,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
bpp = format2bpp(mipmap->format); bpp = format2bpp(mipmap->format);
if (bpp < 1 || bpp > 4) if (bpp < 1 || bpp > 4)
I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); I_Error("HWR_DrawTexturePatchInCache: no drawer defined for this bpp (%d)\n",bpp);
// NOTE: should this actually be pblockwidth*bpp? // NOTE: should this actually be pblockwidth*bpp?
blockmodulo = pblockwidth*bpp; blockmodulo = pblockwidth*bpp;
@ -446,7 +447,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
UINT8 *block; UINT8 *block;
texture_t *texture; texture_t *texture;
texpatch_t *patch; texpatch_t *patch;
patch_t *realpatch; softwarepatch_t *realpatch;
UINT8 *pdata; UINT8 *pdata;
INT32 blockwidth, blockheight, blocksize; INT32 blockwidth, blockheight, blocksize;
@ -502,16 +503,16 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
boolean dealloc = true; boolean dealloc = true;
size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump);
pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
realpatch = (patch_t *)pdata; realpatch = (softwarepatch_t *)pdata;
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); realpatch = (softwarepatch_t *)Picture_PNGConvert(pdata, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else else
#endif #endif
#ifdef WALLFLATS #ifdef WALLFLATS
if (texture->type == TEXTURETYPE_FLAT) if (texture->type == TEXTURETYPE_FLAT)
realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0);
else else
#endif #endif
{ {
@ -544,36 +545,20 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
// patch may be NULL if grMipmap has been initialised already and makebitmap is false // patch may be NULL if grMipmap has been initialised already and makebitmap is false
void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap)
{ {
#ifndef NO_PNG_LUMPS
// lump is a png so convert it
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
if ((patch != NULL) && Picture_IsLumpPNG((const UINT8 *)patch, len))
patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, NULL, NULL, NULL, NULL, len, NULL, 0);
#endif
// don't do it twice (like a cache)
if (grMipmap->width == 0) if (grMipmap->width == 0)
{ {
// save the original patch header so that the GLPatch can be casted
// into a standard patch_t struct and the existing code can get the
// orginal patch dimensions and offsets.
grPatch->width = SHORT(patch->width);
grPatch->height = SHORT(patch->height);
grPatch->leftoffset = SHORT(patch->leftoffset);
grPatch->topoffset = SHORT(patch->topoffset);
grMipmap->width = grMipmap->height = 1; grMipmap->width = grMipmap->height = 1;
while (grMipmap->width < grPatch->width) grMipmap->width <<= 1; while (grMipmap->width < patch->width) grMipmap->width <<= 1;
while (grMipmap->height < grPatch->height) grMipmap->height <<= 1; while (grMipmap->height < patch->height) grMipmap->height <<= 1;
// no wrap around, no chroma key // no wrap around, no chroma key
grMipmap->flags = 0; grMipmap->flags = 0;
// setup the texture info // setup the texture info
grMipmap->format = patchformat; grMipmap->format = patchformat;
//grPatch->max_s = grPatch->max_t = 1.0f; grPatch->max_s = (float)patch->width / (float)grMipmap->width;
grPatch->max_s = (float)grPatch->width / (float)grMipmap->width; grPatch->max_t = (float)patch->height / (float)grMipmap->height;
grPatch->max_t = (float)grPatch->height / (float)grMipmap->height;
} }
Z_Free(grMipmap->data); Z_Free(grMipmap->data);
@ -585,7 +570,7 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
HWR_DrawPatchInCache(grMipmap, HWR_DrawPatchInCache(grMipmap,
grMipmap->width, grMipmap->height, grMipmap->width, grMipmap->height,
grPatch->width, grPatch->height, patch->width, patch->height,
patch); patch);
} }
} }
@ -598,20 +583,56 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
static size_t gl_numtextures = 0; // Texture count static size_t gl_numtextures = 0; // Texture count
static GLMapTexture_t *gl_textures; // For all textures static GLMapTexture_t *gl_textures; // For all textures
static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached
boolean gl_maptexturesloaded = false;
void HWR_InitTextureCache(void) void HWR_FreeTextureData(patch_t *patch)
{ {
gl_textures = NULL; GLPatch_t *grPatch;
gl_flats = NULL;
if (!patch || !patch->hardware)
return;
grPatch = patch->hardware;
if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWD.pfnDeleteTexture(grPatch->mipmap);
if (grPatch->mipmap->data)
Z_Free(grPatch->mipmap->data);
} }
// Callback function for HWR_FreeTextureCache. void HWR_FreeTexture(patch_t *patch)
static void FreeMipmapColormap(INT32 patchnum, void *patch)
{ {
GLPatch_t* const pat = patch; if (!patch)
(void)patchnum; //unused return;
if (patch->hardware)
{
GLPatch_t *grPatch = patch->hardware;
HWR_FreeTextureColormaps(patch);
if (grPatch->mipmap)
{
HWR_FreeTextureData(patch);
Z_Free(grPatch->mipmap);
}
Z_Free(patch->hardware);
}
patch->hardware = NULL;
}
// Called by HWR_FreePatchCache.
void HWR_FreeTextureColormaps(patch_t *patch)
{
GLPatch_t *pat;
// The patch must be valid, obviously // The patch must be valid, obviously
if (!patch)
return;
pat = patch->hardware;
if (!pat) if (!pat)
return; return;
@ -627,7 +648,7 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch)
if (!pat->mipmap) if (!pat->mipmap)
break; break;
// No colormap mipmap either. // No colormap mipmaps either.
if (!pat->mipmap->nextcolormap) if (!pat->mipmap->nextcolormap)
break; break;
@ -639,34 +660,61 @@ static void FreeMipmapColormap(INT32 patchnum, void *patch)
if (next->data) if (next->data)
Z_Free(next->data); Z_Free(next->data);
next->data = NULL; next->data = NULL;
HWD.pfnDeleteTexture(next);
// Free the old colormap mipmap from memory. // Free the old colormap mipmap from memory.
free(next); free(next);
} }
} }
void HWR_FreeMipmapCache(void) static void HWR_FreePatchCache(boolean freeall)
{ {
INT32 i; INT32 i;
// free references to the textures
HWD.pfnClearMipMapCache();
// free all hardware-converted graphics cached in the heap
// our gool is only the textures since user of the texture is the texture cache
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
// Alam: free the Z_Blocks before freeing it's users
// free all patch colormaps after each level: must be done after ClearMipMapCache!
for (i = 0; i < numwadfiles; i++) for (i = 0; i < numwadfiles; i++)
M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap); {
INT32 j = 0;
for (; j < wadfiles[i]->numlumps; j++)
(freeall ? HWR_FreeTexture : HWR_FreeTextureColormaps)(wadfiles[i]->patchcache[j]);
}
} }
void HWR_FreeTextureCache(void) // free all textures after each level
void HWR_ClearAllTextures(void)
{ {
// free references to the textures HWD.pfnClearMipMapCache(); // free references to the textures
HWR_FreeMipmapCache(); HWR_FreePatchCache(true);
}
void HWR_FreeColormapCache(void)
{
HWR_FreePatchCache(false);
}
void HWR_InitMapTextures(void)
{
gl_textures = NULL;
gl_flats = NULL;
gl_maptexturesloaded = false;
}
static void FreeMapTexture(GLMapTexture_t *tex)
{
HWD.pfnDeleteTexture(&tex->mipmap);
if (tex->mipmap.data)
Z_Free(tex->mipmap.data);
tex->mipmap.data = NULL;
}
void HWR_FreeMapTextures(void)
{
size_t i;
for (i = 0; i < gl_numtextures; i++)
{
FreeMapTexture(&gl_textures[i]);
FreeMapTexture(&gl_flats[i]);
}
// now the heap don't have any 'user' pointing to our // now the heap don't have any 'user' pointing to our
// texturecache info, we can free it // texturecache info, we can free it
@ -677,22 +725,22 @@ void HWR_FreeTextureCache(void)
gl_textures = NULL; gl_textures = NULL;
gl_flats = NULL; gl_flats = NULL;
gl_numtextures = 0; gl_numtextures = 0;
gl_maptexturesloaded = false;
} }
void HWR_LoadTextures(size_t pnumtextures) void HWR_LoadMapTextures(size_t pnumtextures)
{ {
// we must free it since numtextures changed // we must free it since numtextures may have changed
HWR_FreeTextureCache(); HWR_FreeMapTextures();
// Why not Z_Malloc?
gl_numtextures = pnumtextures; gl_numtextures = pnumtextures;
gl_textures = calloc(gl_numtextures, sizeof(*gl_textures)); gl_textures = calloc(gl_numtextures, sizeof(*gl_textures));
gl_flats = calloc(gl_numtextures, sizeof(*gl_flats)); gl_flats = calloc(gl_numtextures, sizeof(*gl_flats));
// Doesn't tell you which it _is_, but hopefully
// should never ever happen (right?!)
if ((gl_textures == NULL) || (gl_flats == NULL)) if ((gl_textures == NULL) || (gl_flats == NULL))
I_Error("HWR_LoadTextures: ran out of memory for OpenGL textures. Sad!"); I_Error("HWR_LoadMapTextures: ran out of memory for OpenGL textures");
gl_maptexturesloaded = true;
} }
void HWR_SetPalette(RGBA_t *palette) void HWR_SetPalette(RGBA_t *palette)
@ -730,7 +778,6 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex)
// If hardware does not have the texture, then call pfnSetTexture to upload it // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded) if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap); HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap); HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now. // The system-memory data can be purged now.
@ -806,17 +853,19 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum) void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum)
{ {
GLMipmap_t *grmip; GLMipmap_t *grmip;
patch_t *patch;
if (flatlumpnum == LUMPERROR) if (flatlumpnum == LUMPERROR)
return; return;
grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; patch = HWR_GetCachedGLPatch(flatlumpnum);
grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap;
if (!grmip->downloaded && !grmip->data) if (!grmip->downloaded && !grmip->data)
HWR_CacheFlat(grmip, flatlumpnum); HWR_CacheFlat(grmip, flatlumpnum);
// If hardware does not have the texture, then call pfnSetTexture to upload it // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grmip->downloaded) if (!grmip->downloaded)
HWD.pfnSetTexture(grmip); HWD.pfnSetTexture(grmip);
HWR_SetCurrentTexture(grmip); HWR_SetCurrentTexture(grmip);
// The system-memory data can be purged now. // The system-memory data can be purged now.
@ -854,7 +903,6 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
// If hardware does not have the texture, then call pfnSetTexture to upload it // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grtex->mipmap.downloaded) if (!grtex->mipmap.downloaded)
HWD.pfnSetTexture(&grtex->mipmap); HWD.pfnSetTexture(&grtex->mipmap);
HWR_SetCurrentTexture(&grtex->mipmap); HWR_SetCurrentTexture(&grtex->mipmap);
// The system-memory data can be purged now. // The system-memory data can be purged now.
@ -862,9 +910,9 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
} }
else if (levelflat->type == LEVELFLAT_PATCH) else if (levelflat->type == LEVELFLAT_PATCH)
{ {
GLPatch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE); patch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE);
levelflat->width = (UINT16)SHORT(patch->width); levelflat->width = (UINT16)(patch->width);
levelflat->height = (UINT16)SHORT(patch->height); levelflat->height = (UINT16)(patch->height);
HWR_GetPatch(patch); HWR_GetPatch(patch);
} }
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
@ -911,89 +959,61 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
HWR_SetCurrentTexture(NULL); HWR_SetCurrentTexture(NULL);
} }
// // --------------------+
// HWR_LoadMappedPatch(): replace the skin color of the sprite in cache // HWR_LoadPatchMipmap : Generates a patch into a mipmap, usually the mipmap inside the patch itself
// : load it first in doom cache if not already // --------------------+
// static void HWR_LoadPatchMipmap(patch_t *patch, GLMipmap_t *grMipmap)
static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch)
{ {
if (!grmip->downloaded && !grmip->data) GLPatch_t *grPatch = patch->hardware;
{ if (!grMipmap->downloaded && !grMipmap->data)
patch_t *patch = gpatch->rawpatch; HWR_MakePatch(patch, grPatch, grMipmap, true);
if (!patch)
patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
HWR_MakePatch(patch, gpatch, grmip, true);
// You can't free rawpatch for some reason?
// (Obviously I can't, sprite rotation needs that...)
if (!gpatch->rawpatch)
Z_Free(patch);
}
// If hardware does not have the texture, then call pfnSetTexture to upload it // If hardware does not have the texture, then call pfnSetTexture to upload it
if (!grmip->downloaded) if (!grMipmap->downloaded)
HWD.pfnSetTexture(grmip); HWD.pfnSetTexture(grMipmap);
HWR_SetCurrentTexture(grMipmap);
HWR_SetCurrentTexture(grmip);
// The system-memory data can be purged now. // The system-memory data can be purged now.
Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
} }
// -----------------+ // -----------------+
// HWR_GetPatch : Download a patch to the hardware cache and make it ready for use // HWR_GetPatch : Download a patch to the hardware cache and make it ready for use
// -----------------+ // -----------------+
void HWR_GetPatch(GLPatch_t *gpatch) void HWR_GetPatch(patch_t *patch)
{ {
// is it in hardware cache if (!patch->hardware)
if (!gpatch->mipmap->downloaded && !gpatch->mipmap->data) Patch_CreateGL(patch);
{ HWR_LoadPatchMipmap(patch, ((GLPatch_t *)patch->hardware)->mipmap);
// 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 = gpatch->rawpatch;
if (!ptr)
ptr = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
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
if (!gpatch->rawpatch)
Z_Free(ptr);
}
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!gpatch->mipmap->downloaded)
HWD.pfnSetTexture(gpatch->mipmap);
HWR_SetCurrentTexture(gpatch->mipmap);
// The system-memory patch data can be purged now.
Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED);
} }
// -------------------+ // -------------------+
// HWR_GetMappedPatch : Same as HWR_GetPatch for sprite color // HWR_GetMappedPatch : Same as HWR_GetPatch for sprite color
// -------------------+ // -------------------+
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap) void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap)
{ {
GLMipmap_t *grmip, *newmip; GLPatch_t *grPatch;
GLMipmap_t *grMipmap, *newMipmap;
if (!patch->hardware)
Patch_CreateGL(patch);
grPatch = patch->hardware;
if (colormap == colormaps || colormap == NULL) if (colormap == colormaps || colormap == NULL)
{ {
// Load the default (green) color in doom cache (temporary?) AND hardware cache // Load the default (green) color in hardware cache
HWR_GetPatch(gpatch); HWR_GetPatch(patch);
return; return;
} }
// search for the mimmap // search for the mimmap
// skip the first (no colormap translated) // skip the first (no colormap translated)
for (grmip = gpatch->mipmap; grmip->nextcolormap; ) for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; )
{ {
grmip = grmip->nextcolormap; grMipmap = grMipmap->nextcolormap;
if (grmip->colormap == colormap) if (grMipmap->colormap == colormap)
{ {
HWR_LoadMappedPatch(grmip, gpatch); HWR_LoadPatchMipmap(patch, grMipmap);
return; return;
} }
} }
@ -1002,15 +1022,15 @@ void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap)
//BP: WARNING: don't free it manually without clearing the cache of harware renderer //BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap) // (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache // this malloc is cleared in HWR_FreeColormapCache
// (...) unfortunately z_malloc fragment alot the memory :(so malloc is better // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better
newmip = calloc(1, sizeof (*newmip)); newMipmap = calloc(1, sizeof (*newMipmap));
if (newmip == NULL) if (newMipmap == NULL)
I_Error("%s: Out of memory", "HWR_GetMappedPatch"); I_Error("%s: Out of memory", "HWR_GetMappedPatch");
grmip->nextcolormap = newmip; grMipmap->nextcolormap = newMipmap;
newmip->colormap = colormap; newMipmap->colormap = colormap;
HWR_LoadMappedPatch(newmip, gpatch); HWR_LoadPatchMipmap(patch, newMipmap);
} }
void HWR_UnlockCachedPatch(GLPatch_t *gpatch) void HWR_UnlockCachedPatch(GLPatch_t *gpatch)
@ -1100,79 +1120,73 @@ static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheig
// HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes') // HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes')
// Returns : // Returns :
// -----------------+ // -----------------+
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) patch_t *HWR_GetPic(lumpnum_t lumpnum)
{ {
GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum); patch_t *patch = HWR_GetCachedGLPatch(lumpnum);
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) GLPatch_t *grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{ {
pic_t *pic; pic_t *pic;
UINT8 *block; UINT8 *block;
size_t len; size_t len;
pic = W_CacheLumpNum(lumpnum, PU_CACHE); pic = W_CacheLumpNum(lumpnum, PU_CACHE);
grpatch->width = SHORT(pic->width); patch->width = SHORT(pic->width);
grpatch->height = SHORT(pic->height); patch->height = SHORT(pic->height);
len = W_LumpLength(lumpnum) - sizeof (pic_t); len = W_LumpLength(lumpnum) - sizeof (pic_t);
grpatch->leftoffset = 0; grPatch->mipmap->width = (UINT16)patch->width;
grpatch->topoffset = 0; grPatch->mipmap->height = (UINT16)patch->height;
grpatch->mipmap->width = (UINT16)grpatch->width;
grpatch->mipmap->height = (UINT16)grpatch->height;
if (pic->mode == PALETTE) if (pic->mode == PALETTE)
grpatch->mipmap->format = textureformat; // can be set by driver grPatch->mipmap->format = textureformat; // can be set by driver
else else
grpatch->mipmap->format = picmode2GR[pic->mode]; grPatch->mipmap->format = picmode2GR[pic->mode];
Z_Free(grpatch->mipmap->data); Z_Free(grPatch->mipmap->data);
// allocate block // allocate block
block = MakeBlock(grpatch->mipmap); block = MakeBlock(grPatch->mipmap);
if (grpatch->width == SHORT(pic->width) && if (patch->width == SHORT(pic->width) &&
grpatch->height == SHORT(pic->height) && patch->height == SHORT(pic->height) &&
format2bpp(grpatch->mipmap->format) == format2bpp(picmode2GR[pic->mode])) format2bpp(grPatch->mipmap->format) == format2bpp(picmode2GR[pic->mode]))
{ {
// no conversion needed // no conversion needed
M_Memcpy(grpatch->mipmap->data, pic->data,len); M_Memcpy(grPatch->mipmap->data, pic->data,len);
} }
else else
HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height), HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height),
SHORT(pic->width)*format2bpp(grpatch->mipmap->format), SHORT(pic->width)*format2bpp(grPatch->mipmap->format),
pic, pic,
format2bpp(grpatch->mipmap->format)); format2bpp(grPatch->mipmap->format));
Z_Unlock(pic); Z_Unlock(pic);
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
grpatch->mipmap->flags = 0; grPatch->mipmap->flags = 0;
grpatch->max_s = grpatch->max_t = 1.0f; grPatch->max_s = grPatch->max_t = 1.0f;
} }
HWD.pfnSetTexture(grpatch->mipmap); HWD.pfnSetTexture(grPatch->mipmap);
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.data, grpatch->mipmap.downloaded); //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grPatch->mipmap->data, grPatch->mipmap->downloaded);
return grpatch; return patch;
} }
GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum)
{ {
aatree_t *hwrcache = wadfiles[wadnum]->hwrcache; lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache;
GLPatch_t *grpatch; if (!lumpcache[lumpnum])
if (!(grpatch = M_AATreeGet(hwrcache, lumpnum)))
{ {
grpatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); void *ptr = Z_Calloc(sizeof(patch_t), PU_PATCH, &lumpcache[lumpnum]);
grpatch->wadnum = wadnum; Patch_Create(NULL, 0, ptr);
grpatch->lumpnum = lumpnum; Patch_AllocateHardwarePatch(ptr);
grpatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
M_AATreeSet(hwrcache, lumpnum, grpatch);
} }
return (patch_t *)(lumpcache[lumpnum]);
return grpatch;
} }
GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum) patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum)
{ {
return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum)); return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum));
} }
@ -1192,8 +1206,8 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum), W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum),
PU_HWRCACHE, &flat)); PU_HWRCACHE, &flat));
stepy = ((INT32)SHORT(fmheight)<<FRACBITS)/pblockheight; stepy = ((INT32)fmheight<<FRACBITS)/pblockheight;
stepx = ((INT32)SHORT(fmwidth)<<FRACBITS)/pblockwidth; stepx = ((INT32)fmwidth<<FRACBITS)/pblockwidth;
posy = 0; posy = 0;
for (j = 0; j < pblockheight; j++) for (j = 0; j < pblockheight; j++)
{ {
@ -1265,7 +1279,8 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum)
void HWR_GetFadeMask(lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
{ {
GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; patch_t *patch = HWR_GetCachedGLPatch(fademasklumpnum);
GLMipmap_t *grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap;
if (!grmip->downloaded && !grmip->data) if (!grmip->downloaded && !grmip->data)
HWR_CacheFadeMask(grmip, fademasklumpnum); HWR_CacheFadeMask(grmip, fademasklumpnum);

View File

@ -43,20 +43,19 @@ typedef enum GLTextureFormat_e
// NULL if the texture is not in Doom heap cache. // NULL if the texture is not in Doom heap cache.
struct GLMipmap_s struct GLMipmap_s
{ {
//for TexDownloadMipMap // for TexDownloadMipMap
GLTextureFormat_t format; GLTextureFormat_t format;
void *data; void *data;
UINT32 flags; UINT32 flags;
UINT16 height; UINT16 height;
UINT16 width; UINT16 width;
UINT32 downloaded; // the dll driver have it in there cache ? UINT32 downloaded; // The GPU has this texture.
struct GLMipmap_s *nextcolormap; struct GLMipmap_s *nextcolormap;
const UINT8 *colormap; const UINT8 *colormap;
// opengl struct GLMipmap_s *nextmipmap; // Linked list of all textures
struct GLMipmap_s *nextmipmap; // opengl : liste of all texture in opengl driver
}; };
typedef struct GLMipmap_s GLMipmap_t; typedef struct GLMipmap_s GLMipmap_t;
@ -73,23 +72,10 @@ struct GLMapTexture_s
typedef struct GLMapTexture_s GLMapTexture_t; typedef struct GLMapTexture_s GLMapTexture_t;
// a cached patch as converted to hardware format, holding the original patch_t // a cached patch as converted to hardware format
// header so that the existing code can retrieve ->width, ->height as usual
// This is returned by W_CachePatchNum()/W_CachePatchName(), when rendermode
// is 'render_opengl'. Else it returns the normal patch_t data.
struct GLPatch_s struct GLPatch_s
{ {
// the 4 first fields come right away from the original patch_t
INT16 width;
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
//
float max_s,max_t; 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
void *rawpatch; // :^)
GLMipmap_t *mipmap; GLMipmap_t *mipmap;
} ATTRPACK; } ATTRPACK;
typedef struct GLPatch_s GLPatch_t; typedef struct GLPatch_s GLPatch_t;

View File

@ -212,35 +212,32 @@ typedef struct
// You pass a combination of these flags to DrawPolygon() // You pass a combination of these flags to DrawPolygon()
enum EPolyFlags enum EPolyFlags
{ {
// the first 5 are mutually exclusive // Mutually exclusive blend flags
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pixels are discarded (holes in texture)
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture)
PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency
PF_Additive = 0x00000004, // Poly is added to the frame buffer PF_Environment = 0x00000004, // Poly should be drawn environment mapped. (Hurdler: used for text drawing)
PF_Environment = 0x00000008, // Poly should be drawn environment mapped. PF_Additive = 0x00000008, // Additive color blending
// Hurdler: used for text drawing PF_AdditiveSource = 0x00000010, // Source blending factor is additive. This is the opposite of regular additive blending.
PF_Substractive = 0x00000010, // for splat PF_Subtractive = 0x00000020, // Subtractive color blending
PF_NoAlphaTest = 0x00000020, // hiden param PF_ReverseSubtract = 0x00000040, // Reverse subtract, used in wall splats (decals)
PF_Fog = 0x00000040, // Fog blocks PF_Multiplicative = 0x00000080, // Multiplicative color blending
PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest, PF_Fog = 0x20000000, // Fog blocks
PF_NoAlphaTest = 0x40000000, // Disables alpha testing
PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest,
// other flag bits // other flag bits
PF_Occlude = 0x00000100, // Updates the depth buffer
PF_Occlude = 0x00000100, // Update the depth buffer PF_NoDepthTest = 0x00000200, // Disables the depth test mode
PF_NoDepthTest = 0x00000200, // Disable the depth test mode PF_Invisible = 0x00000400, // Disables write to color buffer
PF_Invisible = 0x00000400, // Disable write to color buffer PF_Decal = 0x00000800, // Enables polygon offset
PF_Decal = 0x00000800, // Enable polygon offset
PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB) PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB)
// When set, pass the color constant into the FSurfaceInfo -> PolyColor // When set, pass the color constant into the FSurfaceInfo -> PolyColor
PF_NoTexture = 0x00002000, // Use the small white texture PF_NoTexture = 0x00002000, // Disables texturing
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona PF_Corona = 0x00004000, // Tells the renderer we are drawing a corona
PF_Ripple = 0x00008000, // Water shader effect PF_Ripple = 0x00008000, // Water effect shader
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X PF_ForceWrapX = 0x00020000, // Forces repeat texture on X
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y PF_ForceWrapY = 0x00040000 // Forces repeat texture on Y
PF_Clip = 0x40000000, // clip to frustum and nearz plane (glide only, automatic in opengl)
PF_NoZClip = 0x20000000, // in conjonction with PF_Clip
PF_Debug = 0x80000000 // print debug message in driver :)
}; };
@ -295,6 +292,16 @@ enum hwdsetspecialstate
typedef enum hwdsetspecialstate hwdspecialstate_t; typedef enum hwdsetspecialstate hwdspecialstate_t;
// Lactozilla: Shader options
enum hwdshaderoption
{
HWD_SHADEROPTION_OFF,
HWD_SHADEROPTION_ON,
HWD_SHADEROPTION_NOCUSTOM,
};
typedef enum hwdshaderoption hwdshaderoption_t;
// Lactozilla: Shader info // Lactozilla: Shader info
// Generally set at the start of the frame. // Generally set at the start of the frame.
enum hwdshaderinfo enum hwdshaderinfo

View File

@ -68,10 +68,11 @@ static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111
// Notes : x,y : positions relative to the original Doom resolution // Notes : x,y : positions relative to the original Doom resolution
// : textes(console+score) + menus + status bar // : textes(console+score) + menus + status bar
// -----------------+ // -----------------+
void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
{ {
FOutVector v[4]; FOutVector v[4];
FBITFIELD flags; FBITFIELD flags;
GLPatch_t *hwrPatch;
// 3--2 // 3--2
// | /| // | /|
@ -84,6 +85,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
// make patch ready in hardware cache // make patch ready in hardware cache
HWR_GetPatch(gpatch); HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
switch (option & V_SCALEPATCHMASK) switch (option & V_SCALEPATCHMASK)
{ {
@ -103,17 +105,17 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
if (option & V_NOSCALESTART) if (option & V_NOSCALESTART)
sdupx = sdupy = 2.0f; sdupx = sdupy = 2.0f;
v[0].x = v[3].x = (x*sdupx-SHORT(gpatch->leftoffset)*pdupx)/vid.width - 1; v[0].x = v[3].x = (x*sdupx-(gpatch->leftoffset)*pdupx)/vid.width - 1;
v[2].x = v[1].x = (x*sdupx+(SHORT(gpatch->width)-SHORT(gpatch->leftoffset))*pdupx)/vid.width - 1; v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdupy-SHORT(gpatch->topoffset)*pdupy)/vid.height; v[0].y = v[1].y = 1-(y*sdupy-(gpatch->topoffset)*pdupy)/vid.height;
v[2].y = v[3].y = 1-(y*sdupy+(SHORT(gpatch->height)-SHORT(gpatch->topoffset))*pdupy)/vid.height; v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = gpatch->max_s; v[2].s = v[1].s = hwrPatch->max_s;
v[0].t = v[1].t = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = gpatch->max_t; v[2].t = v[3].t = hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
@ -126,13 +128,14 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
HWD.pfnDrawPolygon(NULL, v, 4, flags); HWD.pfnDrawPolygon(NULL, v, 4, flags);
} }
void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap)
{ {
FOutVector v[4]; FOutVector v[4];
FBITFIELD flags; FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x); float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y); float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
GLPatch_t *hwrPatch;
// 3--2 // 3--2
// | /| // | /|
@ -151,6 +154,8 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
else else
HWR_GetMappedPatch(gpatch, colormap); HWR_GetMappedPatch(gpatch, colormap);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx; dupx = (float)vid.dupx;
dupy = (float)vid.dupy; dupy = (float)vid.dupy;
@ -181,13 +186,13 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
// left offset // left offset
if (option & V_FLIP) if (option & V_FLIP)
offsetx = (float)(SHORT(gpatch->width) - SHORT(gpatch->leftoffset)) * fscalew; offsetx = (float)(gpatch->width - gpatch->leftoffset) * fscalew;
else else
offsetx = (float)SHORT(gpatch->leftoffset) * fscalew; offsetx = (float)(gpatch->leftoffset) * fscalew;
// top offset // top offset
// TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!? // TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!?
offsety = (float)SHORT(gpatch->topoffset) * fscaleh; offsety = (float)(gpatch->topoffset) * fscaleh;
if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs
{ {
@ -277,17 +282,14 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
// cx and cy are possibly *slightly* off from float maths // cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre // This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT)
{ {
// Need to temporarily cache the real patch to get the colour of the top left pixel const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0]));
patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
if (!column->topdelta) if (!column->topdelta)
{ {
const UINT8 *source = (const UINT8 *)(column) + 3; const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
} }
Z_Free(realpatch);
} }
// centre screen // centre screen
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
@ -317,13 +319,13 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER)) if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
{ {
fwidth = (float)SHORT(gpatch->width) * fscalew * dupx; fwidth = (float)(gpatch->width) * fscalew * dupx;
fheight = (float)SHORT(gpatch->height) * fscaleh * dupy; fheight = (float)(gpatch->height) * fscaleh * dupy;
} }
else else
{ {
fwidth = (float)SHORT(gpatch->width) * dupx; fwidth = (float)(gpatch->width) * dupx;
fheight = (float)SHORT(gpatch->height) * dupy; fheight = (float)(gpatch->height) * dupy;
} }
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
@ -345,17 +347,17 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
if (option & V_FLIP) if (option & V_FLIP)
{ {
v[0].s = v[3].s = gpatch->max_s; v[0].s = v[3].s = hwrPatch->max_s;
v[2].s = v[1].s = 0.0f; v[2].s = v[1].s = 0.0f;
} }
else else
{ {
v[0].s = v[3].s = 0.0f; v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = gpatch->max_s; v[2].s = v[1].s = hwrPatch->max_s;
} }
v[0].t = v[1].t = 0.0f; v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = gpatch->max_t; v[2].t = v[3].t = hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
@ -380,13 +382,14 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
HWD.pfnDrawPolygon(NULL, v, 4, flags); HWD.pfnDrawPolygon(NULL, v, 4, flags);
} }
void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
{ {
FOutVector v[4]; FOutVector v[4];
FBITFIELD flags; FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x); float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y); float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
GLPatch_t *hwrPatch;
// 3--2 // 3--2
// | /| // | /|
@ -399,6 +402,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// make patch ready in hardware cache // make patch ready in hardware cache
HWR_GetPatch(gpatch); HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx; dupx = (float)vid.dupx;
dupy = (float)vid.dupy; dupy = (float)vid.dupy;
@ -423,8 +427,8 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus... // fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus...
cy -= (float)SHORT(gpatch->topoffset) * fscale; cy -= (float)(gpatch->topoffset) * fscale;
cx -= (float)SHORT(gpatch->leftoffset) * fscale; cx -= (float)(gpatch->leftoffset) * fscale;
if (!(option & V_NOSCALESTART)) if (!(option & V_NOSCALESTART))
{ {
@ -436,17 +440,14 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
// cx and cy are possibly *slightly* off from float maths // cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre // This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT)
{ {
// Need to temporarily cache the real patch to get the colour of the top left pixel const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0]));
patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
if (!column->topdelta) if (!column->topdelta)
{ {
const UINT8 *source = (const UINT8 *)(column) + 3; const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
} }
Z_Free(realpatch);
} }
// centre screen // centre screen
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
@ -469,11 +470,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
fwidth = w; fwidth = w;
fheight = h; fheight = h;
if (fwidth > SHORT(gpatch->width)) if (fwidth > gpatch->width)
fwidth = SHORT(gpatch->width); fwidth = gpatch->width;
if (fheight > SHORT(gpatch->height)) if (fheight > gpatch->height)
fheight = SHORT(gpatch->height); fheight = gpatch->height;
if (pscale != FRACUNIT) if (pscale != FRACUNIT)
{ {
@ -503,17 +504,17 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; v[0].s = v[3].s = ((sx)/(float)(gpatch->width))*hwrPatch->max_s;
if (sx + w > SHORT(gpatch->width)) if (sx + w > gpatch->width)
v[2].s = v[1].s = gpatch->max_s; v[2].s = v[1].s = hwrPatch->max_s - ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s;
else else
v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; v[2].s = v[1].s = ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s;
v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; v[0].t = v[1].t = ((sy)/(float)(gpatch->height))*hwrPatch->max_t;
if (sy + h > SHORT(gpatch->height)) if (sy + h > gpatch->height)
v[2].t = v[3].t = gpatch->max_t; v[2].t = v[3].t = hwrPatch->max_t - ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t;
else else
v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; v[2].t = v[3].t = ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
@ -541,7 +542,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
{ {
FOutVector v[4]; FOutVector v[4];
const GLPatch_t *patch; const patch_t *patch;
// make pic ready in hardware cache // make pic ready in hardware cache
patch = HWR_GetPic(lumpnum); patch = HWR_GetPic(lumpnum);
@ -558,10 +559,10 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0; v[0].s = v[3].s = 0;
v[2].s = v[1].s = patch->max_s; v[2].s = v[1].s = ((GLPatch_t *)patch->hardware)->max_s;
v[0].t = v[1].t = 0; v[0].t = v[1].t = 0;
v[2].t = v[3].t = patch->max_t; v[2].t = v[3].t = ((GLPatch_t *)patch->hardware)->max_t;
//Hurdler: Boris, the same comment as above... but maybe for pics //Hurdler: Boris, the same comment as above... but maybe for pics
@ -570,7 +571,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
// But then, the question is: why not 0 instead of PF_Masked ? // But then, the question is: why not 0 instead of PF_Masked ?
// or maybe PF_Environment ??? (like what I said above) // or maybe PF_Environment ??? (like what I said above)
// BP: PF_Environment don't change anything ! and 0 is undifined // BP: PF_Environment don't change anything ! and 0 is undifined
HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip); HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest);
} }
// ========================================================================== // ==========================================================================
@ -934,7 +935,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
INT32 top, side; INT32 top, side;
INT32 baseviewwidth, baseviewheight; INT32 baseviewwidth, baseviewheight;
INT32 basewindowx, basewindowy; INT32 basewindowx, basewindowy;
GLPatch_t *patch; patch_t *patch;
// if (gl_viewwidth == vid.width) // if (gl_viewwidth == vid.width)
// return; // return;

View File

@ -42,9 +42,11 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(DeleteTexture) (FTextureInfo *TexInfo);
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(ClearCacheList) (void);
//Hurdler: added for backward compatibility //Hurdler: added for backward compatibility
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
@ -70,7 +72,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
// jimita // jimita
EXPORT boolean HWRAPI(CompileShaders) (void); EXPORT boolean HWRAPI(CompileShaders) (void);
EXPORT void HWRAPI(CleanShaders) (void); EXPORT void HWRAPI(CleanShaders) (void);
EXPORT void HWRAPI(SetShader) (int shader); EXPORT void HWRAPI(SetShader) (int type);
EXPORT void HWRAPI(UnSetShader) (void); EXPORT void HWRAPI(UnSetShader) (void);
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
@ -95,9 +97,11 @@ struct hwdriver_s
ClearBuffer pfnClearBuffer; ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture; SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture; UpdateTexture pfnUpdateTexture;
DeleteTexture pfnDeleteTexture;
ReadRect pfnReadRect; ReadRect pfnReadRect;
GClipRect pfnGClipRect; GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache; ClearMipMapCache pfnClearMipMapCache;
ClearCacheList pfnClearCacheList;
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
DrawModel pfnDrawModel; DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs; CreateModelVBOs pfnCreateModelVBOs;

View File

@ -62,19 +62,32 @@ typedef struct
typedef struct gl_vissprite_s typedef struct gl_vissprite_s
{ {
float x1, x2; float x1, x2;
float tz, ty; float z1, z2;
float gz, gzt;
float tz;
float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting
//lumpnum_t patchlumpnum;
GLPatch_t *gpatch; float scale;
boolean flip; float shadowheight, shadowscale;
UINT8 translucency; //alpha level 0-255
mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. float spritexscale, spriteyscale;
float spritexoffset, spriteyoffset;
UINT32 renderflags;
UINT8 rotateflags;
boolean flip, vflip;
boolean precip; // Tails 08-25-2002 boolean precip; // Tails 08-25-2002
boolean vflip; boolean rotated;
//Hurdler: 25/04/2000: now support colormap in hardware mode UINT8 translucency; //alpha level 0-255
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap; UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
float z1, z2;
patch_t *gpatch;
mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out.
} gl_vissprite_t; } gl_vissprite_t;
// -------- // --------
@ -86,25 +99,36 @@ extern size_t addsubsector;
void HWR_InitPolyPool(void); void HWR_InitPolyPool(void);
void HWR_FreePolyPool(void); void HWR_FreePolyPool(void);
void HWR_FreeExtraSubsectors(void);
// -------- // --------
// hw_cache.c // hw_cache.c
// -------- // --------
void HWR_InitTextureCache(void); void HWR_InitMapTextures(void);
void HWR_FreeTextureCache(void); void HWR_LoadMapTextures(size_t pnumtextures);
void HWR_FreeMipmapCache(void); void HWR_FreeMapTextures(void);
void HWR_FreeExtraSubsectors(void);
patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetPatch(patch_t *patch);
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
patch_t *HWR_GetPic(lumpnum_t lumpnum);
GLMapTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetLevelFlat(levelflat_t *levelflat); void HWR_GetLevelFlat(levelflat_t *levelflat);
void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum); void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum);
GLMapTexture_t *HWR_GetTexture(INT32 tex);
void HWR_GetPatch(GLPatch_t *gpatch); void HWR_FreeTexture(patch_t *patch);
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); void HWR_FreeTextureData(patch_t *patch);
void HWR_FreeTextureColormaps(patch_t *patch);
void HWR_ClearAllTextures(void);
void HWR_FreeColormapCache(void);
void HWR_UnlockCachedPatch(GLPatch_t *gpatch); void HWR_UnlockCachedPatch(GLPatch_t *gpatch);
GLPatch_t *HWR_GetPic(lumpnum_t lumpnum);
void HWR_SetPalette(RGBA_t *palette); void HWR_SetPalette(RGBA_t *palette);
GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
// -------- // --------
// hw_draw.c // hw_draw.c

View File

@ -35,8 +35,7 @@
#define DL_HIGH_QUALITY #define DL_HIGH_QUALITY
//#define STATICLIGHT //Hurdler: TODO! //#define STATICLIGHT //Hurdler: TODO!
//#define LIGHTMAPFLAGS (PF_Masked|PF_Clip|PF_NoAlphaTest) // debug see overdraw #define LIGHTMAPFLAGS (PF_Modulated|PF_AdditiveSource)
#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive|PF_Clip)
#ifdef ALAM_LIGHTING #ifdef ALAM_LIGHTING
static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode
@ -1056,7 +1055,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr)
HWR_GetPic(coronalumpnum); /// \todo use different coronas HWR_GetPic(coronalumpnum); /// \todo use different coronas
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_Corona | PF_NoDepthTest); HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_Corona | PF_NoDepthTest);
} }
} }
#endif #endif
@ -1144,7 +1143,7 @@ void HWR_DrawCoronas(void)
light[3].y = cy+size*1.33f; light[3].y = cy+size*1.33f;
light[3].s = 0.0f; light[3].t = 1.0f; light[3].s = 0.0f; light[3].t = 1.0f;
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona); HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_NoDepthTest | PF_Corona);
} }
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -37,13 +37,12 @@ void HWR_DrawViewBorder(INT32 clearlines);
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum);
void HWR_InitTextureMapping(void); void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void); void HWR_SetViewSize(void);
void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum);
void HWR_LoadTextures(size_t pnumtextures);
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);
void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength); void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength);
void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right. void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right.
@ -55,7 +54,6 @@ boolean HWR_Screenshot(const char *pathname);
void HWR_AddCommands(void); void HWR_AddCommands(void);
void HWR_AddSessionCommands(void); void HWR_AddSessionCommands(void);
void transform(float *cx, float *cy, float *cz); void transform(float *cx, float *cy, float *cz);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
INT32 HWR_GetTextureUsed(void); INT32 HWR_GetTextureUsed(void);
void HWR_DoPostProcessor(player_t *player); void HWR_DoPostProcessor(player_t *player);
void HWR_StartScreenWipe(void); void HWR_StartScreenWipe(void);
@ -66,10 +64,15 @@ void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum);
void HWR_MakeScreenFinalTexture(void); void HWR_MakeScreenFinalTexture(void);
void HWR_DrawScreenFinalTexture(int width, int height); void HWR_DrawScreenFinalTexture(int width, int height);
// This stuff is put here so MD2's can use them // This stuff is put here so models can use them
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
UINT8 HWR_GetTranstableAlpha(INT32 transtablenum);
FBITFIELD HWR_GetBlendModeFlag(INT32 ast);
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
boolean HWR_CompileShaders(void); boolean HWR_CompileShaders(void);
void HWR_LoadAllCustomShaders(void); void HWR_LoadAllCustomShaders(void);
@ -78,7 +81,7 @@ const char *HWR_GetShaderName(INT32 shader);
extern customshaderxlat_t shaderxlat[]; extern customshaderxlat_t shaderxlat[];
extern CV_PossibleValue_t granisotropicmode_cons_t[]; extern CV_PossibleValue_t glanisotropicmode_cons_t[];
#ifdef ALAM_LIGHTING #ifdef ALAM_LIGHTING
extern consvar_t cv_gldynamiclighting; extern consvar_t cv_gldynamiclighting;
@ -87,7 +90,7 @@ extern consvar_t cv_glcoronas;
extern consvar_t cv_glcoronasize; extern consvar_t cv_glcoronasize;
#endif #endif
extern consvar_t cv_glshaders; extern consvar_t cv_glshaders, cv_glallowshaders;
extern consvar_t cv_glmodels; extern consvar_t cv_glmodels;
extern consvar_t cv_glmodelinterpolation; extern consvar_t cv_glmodelinterpolation;
extern consvar_t cv_glmodellighting; extern consvar_t cv_glmodellighting;
@ -113,11 +116,11 @@ extern FTransform atransform;
// Render stats // Render stats
extern int ps_hw_skyboxtime; extern precise_t ps_hw_skyboxtime;
extern int ps_hw_nodesorttime; extern precise_t ps_hw_nodesorttime;
extern int ps_hw_nodedrawtime; extern precise_t ps_hw_nodedrawtime;
extern int ps_hw_spritesorttime; extern precise_t ps_hw_spritesorttime;
extern int ps_hw_spritedrawtime; extern precise_t ps_hw_spritedrawtime;
// Render stats for batching // Render stats for batching
extern int ps_hw_numpolys; extern int ps_hw_numpolys;
@ -127,9 +130,13 @@ extern int ps_hw_numshaders;
extern int ps_hw_numtextures; extern int ps_hw_numtextures;
extern int ps_hw_numpolyflags; extern int ps_hw_numpolyflags;
extern int ps_hw_numcolors; extern int ps_hw_numcolors;
extern int ps_hw_batchsorttime; extern precise_t ps_hw_batchsorttime;
extern int ps_hw_batchdrawtime; extern precise_t ps_hw_batchdrawtime;
extern boolean gl_init;
extern boolean gl_maploaded;
extern boolean gl_maptexturesloaded;
extern boolean gl_sessioncommandsadded;
extern boolean gl_shadersavailable; extern boolean gl_shadersavailable;
#endif #endif

View File

@ -92,7 +92,13 @@ static void md2_freeModel (model_t *model)
static model_t *md2_readModel(const char *filename) static model_t *md2_readModel(const char *filename)
{ {
//Filename checking fixed ~Monster Iestyn and Golden //Filename checking fixed ~Monster Iestyn and Golden
return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC); if (FIL_FileExists(va("%s"PATHSEP"%s", srb2home, filename)))
return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC);
if (FIL_FileExists(va("%s"PATHSEP"%s", srb2path, filename)))
return LoadModel(va("%s"PATHSEP"%s", srb2path, filename), PU_STATIC);
return NULL;
} }
static inline void md2_printModelInfo (model_t *model) static inline void md2_printModelInfo (model_t *model)
@ -160,8 +166,12 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
png_FILE = fopen(pngfilename, "rb"); png_FILE = fopen(pngfilename, "rb");
if (!png_FILE) if (!png_FILE)
{ {
pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2path, filename);
FIL_ForceExtension(pngfilename, ".png");
png_FILE = fopen(pngfilename, "rb");
//CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename); //CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename);
return 0; if (!png_FILE)
return 0;
} }
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
@ -288,7 +298,13 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
FIL_ForceExtension(pcxfilename, ".pcx"); FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb"); file = fopen(pcxfilename, "rb");
if (!file) if (!file)
return 0; {
pcxfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2path, filename);
FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb");
if (!file)
return 0;
}
if (fread(&header, sizeof (PcxHeader), 1, file) != 1) if (fread(&header, sizeof (PcxHeader), 1, file) != 1)
{ {
@ -348,48 +364,53 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
// -----------------+ // -----------------+
static void md2_loadTexture(md2_t *model) static void md2_loadTexture(md2_t *model)
{ {
GLPatch_t *grpatch; patch_t *patch;
GLPatch_t *grPatch = NULL;
const char *filename = model->filename; const char *filename = model->filename;
if (model->grpatch) if (model->grpatch)
{ {
grpatch = model->grpatch; patch = model->grpatch;
Z_Free(grpatch->mipmap->data); grPatch = (GLPatch_t *)(patch->hardware);
if (grPatch)
Z_Free(grPatch->mipmap->data);
} }
else else
{ model->grpatch = patch = Patch_Create(NULL, 0, NULL);
grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO,
&(model->grpatch));
grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL);
}
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) if (!patch->hardware)
Patch_AllocateHardwarePatch(patch);
if (grPatch == NULL)
grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{ {
int w = 0, h = 0; int w = 0, h = 0;
UINT32 size; UINT32 size;
RGBA_t *image; RGBA_t *image;
#ifdef HAVE_PNG #ifdef HAVE_PNG
grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch); grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch);
if (grpatch->mipmap->format == 0) if (grPatch->mipmap->format == 0)
#endif #endif
grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch); grPatch->mipmap->format = PCX_Load(filename, &w, &h, grPatch);
if (grpatch->mipmap->format == 0) if (grPatch->mipmap->format == 0)
{ {
model->notexturefile = true; // mark it so its not searched for again repeatedly model->notexturefile = true; // mark it so its not searched for again repeatedly
return; return;
} }
grpatch->mipmap->downloaded = 0; grPatch->mipmap->downloaded = 0;
grpatch->mipmap->flags = 0; grPatch->mipmap->flags = 0;
grpatch->width = (INT16)w; patch->width = (INT16)w;
grpatch->height = (INT16)h; patch->height = (INT16)h;
grpatch->mipmap->width = (UINT16)w; grPatch->mipmap->width = (UINT16)w;
grpatch->mipmap->height = (UINT16)h; grPatch->mipmap->height = (UINT16)h;
// Lactozilla: Apply colour cube // Lactozilla: Apply colour cube
image = grpatch->mipmap->data; image = grPatch->mipmap->data;
size = w*h; size = w*h;
while (size--) while (size--)
{ {
@ -397,7 +418,7 @@ static void md2_loadTexture(md2_t *model)
image++; image++;
} }
} }
HWD.pfnSetTexture(grpatch->mipmap); HWD.pfnSetTexture(grPatch->mipmap);
} }
// -----------------+ // -----------------+
@ -405,48 +426,53 @@ static void md2_loadTexture(md2_t *model)
// -----------------+ // -----------------+
static void md2_loadBlendTexture(md2_t *model) static void md2_loadBlendTexture(md2_t *model)
{ {
GLPatch_t *grpatch; patch_t *patch;
GLPatch_t *grPatch = NULL;
char *filename = Z_Malloc(strlen(model->filename)+7, PU_STATIC, NULL); char *filename = Z_Malloc(strlen(model->filename)+7, PU_STATIC, NULL);
strcpy(filename, model->filename);
strcpy(filename, model->filename);
FIL_ForceExtension(filename, "_blend.png"); FIL_ForceExtension(filename, "_blend.png");
if (model->blendgrpatch) if (model->blendgrpatch)
{ {
grpatch = model->blendgrpatch; patch = model->blendgrpatch;
Z_Free(grpatch->mipmap->data); grPatch = (GLPatch_t *)(patch->hardware);
if (grPatch)
Z_Free(grPatch->mipmap->data);
} }
else else
{ model->blendgrpatch = patch = Patch_Create(NULL, 0, NULL);
grpatch = Z_Calloc(sizeof *grpatch, PU_HWRPATCHINFO,
&(model->blendgrpatch));
grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL);
}
if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) if (!patch->hardware)
Patch_AllocateHardwarePatch(patch);
if (grPatch == NULL)
grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{ {
int w = 0, h = 0; int w = 0, h = 0;
#ifdef HAVE_PNG #ifdef HAVE_PNG
grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch); grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch);
if (grpatch->mipmap->format == 0) if (grPatch->mipmap->format == 0)
#endif #endif
grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch); grPatch->mipmap->format = PCX_Load(filename, &w, &h, grPatch);
if (grpatch->mipmap->format == 0) if (grPatch->mipmap->format == 0)
{ {
model->noblendfile = true; // mark it so its not searched for again repeatedly model->noblendfile = true; // mark it so its not searched for again repeatedly
Z_Free(filename); Z_Free(filename);
return; return;
} }
grpatch->mipmap->downloaded = 0; grPatch->mipmap->downloaded = 0;
grpatch->mipmap->flags = 0; grPatch->mipmap->flags = 0;
grpatch->width = (INT16)w; patch->width = (INT16)w;
grpatch->height = (INT16)h; patch->height = (INT16)h;
grpatch->mipmap->width = (UINT16)w; grPatch->mipmap->width = (UINT16)w;
grpatch->mipmap->height = (UINT16)h; grPatch->mipmap->height = (UINT16)h;
} }
HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary HWD.pfnSetTexture(grPatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary
Z_Free(filename); Z_Free(filename);
} }
@ -493,9 +519,13 @@ void HWR_InitModels(void)
if (!f) if (!f)
{ {
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
nomd2s = true; if (!f)
return; {
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
} }
// length of the player model prefix // length of the player model prefix
@ -569,9 +599,13 @@ void HWR_AddPlayerModel(int skin) // For skins that were added after startup
if (!f) if (!f)
{ {
CONS_Printf("Error while loading models.dat\n"); f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
nomd2s = true; if (!f)
return; {
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
} }
// length of the player model prefix // length of the player model prefix
@ -624,9 +658,13 @@ void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after s
if (!f) if (!f)
{ {
CONS_Printf("Error while loading models.dat\n"); f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
nomd2s = true; if (!f)
return; {
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
} }
// Check for any models that match the names of sprite names! // Check for any models that match the names of sprite names!
@ -664,8 +702,10 @@ spritemodelfound:
#define SETBRIGHTNESS(brightness,r,g,b) \ #define SETBRIGHTNESS(brightness,r,g,b) \
brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000)) brightness = (UINT8)(((1063*(UINT16)(r))/5000) + ((3576*(UINT16)(g))/5000) + ((361*(UINT16)(b))/5000))
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolornum_t color) static void HWR_CreateBlendedTexture(patch_t *gpatch, patch_t *blendgpatch, GLMipmap_t *grMipmap, INT32 skinnum, skincolornum_t color)
{ {
GLPatch_t *hwrPatch = gpatch->hardware;
GLPatch_t *hwrBlendPatch = blendgpatch->hardware;
UINT16 w = gpatch->width, h = gpatch->height; UINT16 w = gpatch->width, h = gpatch->height;
UINT32 size = w*h; UINT32 size = w*h;
RGBA_t *image, *blendimage, *cur, blendcolor; RGBA_t *image, *blendimage, *cur, blendcolor;
@ -678,28 +718,29 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
memset(translation, 0, sizeof(translation)); memset(translation, 0, sizeof(translation));
memset(cutoff, 0, sizeof(cutoff)); memset(cutoff, 0, sizeof(cutoff));
if (grmip->width == 0) if (grMipmap->width == 0)
{ {
grmip->width = gpatch->width; grMipmap->width = gpatch->width;
grmip->height = gpatch->height; grMipmap->height = gpatch->height;
// no wrap around, no chroma key // no wrap around, no chroma key
grmip->flags = 0; grMipmap->flags = 0;
// setup the texture info // setup the texture info
grmip->format = GL_TEXFMT_RGBA; grMipmap->format = GL_TEXFMT_RGBA;
} }
if (grmip->data) if (grMipmap->data)
{ {
Z_Free(grmip->data); Z_Free(grMipmap->data);
grmip->data = NULL; grMipmap->data = NULL;
} }
cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grmip->data); cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grMipmap->data);
memset(cur, 0x00, size*4); memset(cur, 0x00, size*4);
image = gpatch->mipmap->data; image = hwrPatch->mipmap->data;
blendimage = blendgpatch->mipmap->data; blendimage = hwrBlendPatch->mipmap->data;
// TC_METALSONIC includes an actual skincolor translation, on top of its flashing. // TC_METALSONIC includes an actual skincolor translation, on top of its flashing.
if (skinnum == TC_METALSONIC) if (skinnum == TC_METALSONIC)
@ -1038,37 +1079,39 @@ skippixel:
#undef SETBRIGHTNESS #undef SETBRIGHTNESS
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color) static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color)
{ {
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment // mostly copied from HWR_GetMappedPatch, hence the similarities and comment
GLMipmap_t *grmip, *newmip; GLPatch_t *grPatch = patch->hardware;
GLPatch_t *grBlendPatch = NULL;
GLMipmap_t *grMipmap, *newMipmap;
if (colormap == colormaps || colormap == NULL) if (blendpatch == NULL || colormap == colormaps || colormap == NULL)
{ {
// Don't do any blending // Don't do any blending
HWD.pfnSetTexture(gpatch->mipmap); HWD.pfnSetTexture(grPatch->mipmap);
return; return;
} }
if ((blendgpatch && blendgpatch->mipmap->format) if ((blendpatch && (grBlendPatch = blendpatch->hardware) && grBlendPatch->mipmap->format)
&& (gpatch->width != blendgpatch->width || gpatch->height != blendgpatch->height)) && (patch->width != blendpatch->width || patch->height != blendpatch->height))
{ {
// Blend image exists, but it's bad. // Blend image exists, but it's bad.
HWD.pfnSetTexture(gpatch->mipmap); HWD.pfnSetTexture(grPatch->mipmap);
return; return;
} }
// search for the mipmap // search for the mipmap
// skip the first (no colormap translated) // skip the first (no colormap translated)
for (grmip = gpatch->mipmap; grmip->nextcolormap; ) for (grMipmap = grPatch->mipmap; grMipmap->nextcolormap; )
{ {
grmip = grmip->nextcolormap; grMipmap = grMipmap->nextcolormap;
if (grmip->colormap == colormap) if (grMipmap->colormap == colormap)
{ {
if (grmip->downloaded && grmip->data) if (grMipmap->downloaded && grMipmap->data)
{ {
HWD.pfnSetTexture(grmip); // found the colormap, set it to the correct texture HWD.pfnSetTexture(grMipmap); // found the colormap, set it to the correct texture
Z_ChangeTag(grmip->data, PU_HWRMODELTEXTURE_UNLOCKED); Z_ChangeTag(grMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED);
return; return;
} }
} }
@ -1079,18 +1122,18 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT
//BP: WARNING: don't free it manually without clearing the cache of harware renderer //BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap) // (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache // this malloc is cleared in HWR_FreeColormapCache
// (...) unfortunately z_malloc fragment alot the memory :(so malloc is better // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better
newmip = calloc(1, sizeof (*newmip)); newMipmap = calloc(1, sizeof (*newMipmap));
if (newmip == NULL) if (newMipmap == NULL)
I_Error("%s: Out of memory", "HWR_GetBlendedTexture"); I_Error("%s: Out of memory", "HWR_GetBlendedTexture");
grmip->nextcolormap = newmip; grMipmap->nextcolormap = newMipmap;
newmip->colormap = colormap; newMipmap->colormap = colormap;
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color); HWR_CreateBlendedTexture(patch, blendpatch, newMipmap, skinnum, color);
HWD.pfnSetTexture(newmip); HWD.pfnSetTexture(newMipmap);
Z_ChangeTag(newmip->data, PU_HWRMODELTEXTURE_UNLOCKED); Z_ChangeTag(newMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED);
} }
#define NORMALFOG 0x00000000 #define NORMALFOG 0x00000000
@ -1178,9 +1221,11 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t
} }
// Adjust texture coords of model to fit into a patch's max_s and max_t // Adjust texture coords of model to fit into a patch's max_s and max_t
static void adjustTextureCoords(model_t *model, GLPatch_t *gpatch) static void adjustTextureCoords(model_t *model, patch_t *patch)
{ {
int i; int i;
GLPatch_t *gpatch = ((GLPatch_t *)patch->hardware);
for (i = 0; i < model->numMeshes; i++) for (i = 0; i < model->numMeshes; i++)
{ {
int j; int j;
@ -1280,7 +1325,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
// Look at HWR_ProjectSprite for more // Look at HWR_ProjectSprite for more
{ {
GLPatch_t *gpatch; patch_t *gpatch, *blendgpatch;
GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL;
INT32 durs = spr->mobj->state->tics; INT32 durs = spr->mobj->state->tics;
INT32 tics = spr->mobj->tics; INT32 tics = spr->mobj->tics;
//mdlframe_t *next = NULL; //mdlframe_t *next = NULL;
@ -1298,15 +1344,16 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
//if (tics > durs) //if (tics > durs)
//durs = tics; //durs = tics;
if (spr->mobj->flags2 & MF2_SHADOW) if (spr->mobj->frame & FF_TRANSMASK)
Surf.PolyColor.s.alpha = 0x40; Surf.PolyFlags = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else if (spr->mobj->frame & FF_TRANSMASK)
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else else
Surf.PolyColor.s.alpha = 0xFF; {
Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff;
Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode);
}
// dont forget to enabled the depth test because we can't do this like // don't forget to enable the depth test because we can't do this
// before: polygons models are not sorted // like before: model polygons are not sorted
// 1. load model+texture if not already loaded // 1. load model+texture if not already loaded
// 2. draw model with correct position, rotation,... // 2. draw model with correct position, rotation,...
@ -1325,14 +1372,26 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
// texture loading before model init, so it knows if sprite graphics are used, which // texture loading before model init, so it knows if sprite graphics are used, which
// means that texture coordinates have to be adjusted // means that texture coordinates have to be adjusted
gpatch = md2->grpatch; gpatch = md2->grpatch;
if (!gpatch || ((!gpatch->mipmap->format || !gpatch->mipmap->downloaded) && !md2->notexturefile)) if (gpatch)
md2_loadTexture(md2); hwrPatch = ((GLPatch_t *)gpatch->hardware);
gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
if ((gpatch && gpatch->mipmap->format) // don't load the blend texture if the base texture isn't available if (!gpatch || !hwrPatch
&& (!md2->blendgrpatch || ((!hwrPatch->mipmap->format || !hwrPatch->mipmap->downloaded) && !md2->notexturefile))
|| ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded) md2_loadTexture(md2);
&& !md2->noblendfile)))
// Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
gpatch = md2->grpatch;
if (gpatch)
hwrPatch = ((GLPatch_t *)gpatch->hardware);
// Load blend texture
blendgpatch = md2->blendgrpatch;
if (blendgpatch)
hwrBlendPatch = ((GLPatch_t *)blendgpatch->hardware);
if ((gpatch && hwrPatch && hwrPatch->mipmap->format) // don't load the blend texture if the base texture isn't available
&& (!blendgpatch || !hwrBlendPatch
|| ((!hwrBlendPatch->mipmap->format || !hwrBlendPatch->mipmap->downloaded) && !md2->noblendfile)))
md2_loadBlendTexture(md2); md2_loadBlendTexture(md2);
if (md2->error) if (md2->error)
@ -1348,7 +1407,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
md2_printModelInfo(md2->model); md2_printModelInfo(md2->model);
// If model uses sprite patch as texture, then // If model uses sprite patch as texture, then
// adjust texture coordinates to take power of two textures into account // adjust texture coordinates to take power of two textures into account
if (!gpatch || !gpatch->mipmap->format) if (!gpatch || !hwrPatch->mipmap->format)
adjustTextureCoords(md2->model, spr->gpatch); adjustTextureCoords(md2->model, spr->gpatch);
// note down the max_s and max_t that end up in the VBO // note down the max_s and max_t that end up in the VBO
md2->model->vbo_max_s = md2->model->max_s; md2->model->vbo_max_s = md2->model->max_s;
@ -1367,7 +1426,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
finalscale = md2->scale; finalscale = md2->scale;
//Hurdler: arf, I don't like that implementation at all... too much crappy //Hurdler: arf, I don't like that implementation at all... too much crappy
if (gpatch && gpatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture if (gpatch && hwrPatch && hwrPatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
{ {
INT32 skinnum = TC_DEFAULT; INT32 skinnum = TC_DEFAULT;
@ -1400,21 +1459,19 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
} }
// Translation or skin number found // Translation or skin number found
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color); HWR_GetBlendedTexture(gpatch, blendgpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color);
} }
else else // Sprite
{ {
// Sprite
gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
// Check if sprite dimensions are different from previously used sprite. // Check if sprite dimensions are different from previously used sprite.
// If so, uvs need to be readjusted. // If so, uvs need to be readjusted.
// Comparing floats with the != operator here should be okay because they // Comparing floats with the != operator here should be okay because they
// are just copies of glpatches' max_s and max_t values. // are just copies of glpatches' max_s and max_t values.
// Instead of the != operator, memcmp is used to avoid a compiler warning. // Instead of the != operator, memcmp is used to avoid a compiler warning.
if (memcmp(&(gpatch->max_s), &(md2->model->max_s), sizeof(md2->model->max_s)) != 0 || if (memcmp(&(hwrPatch->max_s), &(md2->model->max_s), sizeof(md2->model->max_s)) != 0 ||
memcmp(&(gpatch->max_t), &(md2->model->max_t), sizeof(md2->model->max_t)) != 0) memcmp(&(hwrPatch->max_t), &(md2->model->max_t), sizeof(md2->model->max_t)) != 0)
adjustTextureCoords(md2->model, gpatch); adjustTextureCoords(md2->model, spr->gpatch);
HWR_GetMappedPatch(gpatch, spr->colormap); HWR_GetMappedPatch(spr->gpatch, spr->colormap);
} }
if (spr->mobj->frame & FF_ANIMATE) if (spr->mobj->frame & FF_ANIMATE)

View File

@ -91,13 +91,6 @@ static GLuint startScreenWipe = 0;
static GLuint endScreenWipe = 0; static GLuint endScreenWipe = 0;
static GLuint finalScreenTexture = 0; static GLuint finalScreenTexture = 0;
// Lactozilla: Shader functions
static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum);
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
// shortcut for ((float)1/i) // shortcut for ((float)1/i)
static const GLfloat byte2float[256] = { static const GLfloat byte2float[256] = {
0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f, 0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f,
@ -426,6 +419,10 @@ static PFNglBufferData pglBufferData;
typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers);
static PFNglDeleteBuffers pglDeleteBuffers; static PFNglDeleteBuffers pglDeleteBuffers;
/* 2.0 functions */
typedef void (APIENTRY * PFNglBlendEquation) (GLenum mode);
static PFNglBlendEquation pglBlendEquation;
/* 1.2 Parms */ /* 1.2 Parms */
/* GL_CLAMP_TO_EDGE_EXT */ /* GL_CLAMP_TO_EDGE_EXT */
@ -533,8 +530,8 @@ boolean SetupGLfunc(void)
return true; return true;
} }
static boolean gl_allowshaders = false;
static boolean gl_shadersenabled = false; static boolean gl_shadersenabled = false;
static hwdshaderoption_t gl_allowshaders = HWD_SHADEROPTION_OFF;
#ifdef GL_SHADERS #ifdef GL_SHADERS
typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum); typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum);
@ -544,6 +541,7 @@ typedef void (APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*);
typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*); typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*);
typedef void (APIENTRY *PFNglDeleteShader) (GLuint); typedef void (APIENTRY *PFNglDeleteShader) (GLuint);
typedef GLuint (APIENTRY *PFNglCreateProgram) (void); typedef GLuint (APIENTRY *PFNglCreateProgram) (void);
typedef void (APIENTRY *PFNglDeleteProgram) (GLuint);
typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint); typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint);
typedef void (APIENTRY *PFNglLinkProgram) (GLuint); typedef void (APIENTRY *PFNglLinkProgram) (GLuint);
typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*); typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*);
@ -565,6 +563,7 @@ static PFNglGetShaderiv pglGetShaderiv;
static PFNglGetShaderInfoLog pglGetShaderInfoLog; static PFNglGetShaderInfoLog pglGetShaderInfoLog;
static PFNglDeleteShader pglDeleteShader; static PFNglDeleteShader pglDeleteShader;
static PFNglCreateProgram pglCreateProgram; static PFNglCreateProgram pglCreateProgram;
static PFNglDeleteProgram pglDeleteProgram;
static PFNglAttachShader pglAttachShader; static PFNglAttachShader pglAttachShader;
static PFNglLinkProgram pglLinkProgram; static PFNglLinkProgram pglLinkProgram;
static PFNglGetProgramiv pglGetProgramiv; static PFNglGetProgramiv pglGetProgramiv;
@ -579,12 +578,6 @@ static PFNglUniform2fv pglUniform2fv;
static PFNglUniform3fv pglUniform3fv; static PFNglUniform3fv pglUniform3fv;
static PFNglGetUniformLocation pglGetUniformLocation; static PFNglGetUniformLocation pglGetUniformLocation;
// 18032019
static GLuint gl_currentshaderprogram = 0;
static boolean gl_shaderprogramchanged = true;
static shadersource_t gl_customshaders[HWR_MAXSHADERS];
// 13062019 // 13062019
typedef enum typedef enum
{ {
@ -602,17 +595,37 @@ typedef enum
gluniform_max, gluniform_max,
} gluniform_t; } gluniform_t;
typedef struct gl_shaderprogram_s typedef struct gl_shader_s
{ {
GLuint program; GLuint program;
boolean custom;
GLint uniforms[gluniform_max+1]; GLint uniforms[gluniform_max+1];
} gl_shaderprogram_t; boolean custom;
static gl_shaderprogram_t gl_shaderprograms[HWR_MAXSHADERS]; } gl_shader_t;
static gl_shader_t gl_shaders[HWR_MAXSHADERS];
static gl_shader_t gl_usershaders[HWR_MAXSHADERS];
static shadersource_t gl_customshaders[HWR_MAXSHADERS];
// 09102020
typedef struct gl_shaderstate_s
{
gl_shader_t *current;
GLuint type;
GLuint program;
boolean changed;
} gl_shaderstate_t;
static gl_shaderstate_t gl_shaderstate;
// Shader info // Shader info
static INT32 shader_leveltime = 0; static INT32 shader_leveltime = 0;
// Lactozilla: Shader functions
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader);
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum);
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
// ================ // ================
// Vertex shaders // Vertex shaders
// ================ // ================
@ -865,6 +878,9 @@ void SetupGLFunc4(void)
pglBufferData = GetGLFunc("glBufferData"); pglBufferData = GetGLFunc("glBufferData");
pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); pglDeleteBuffers = GetGLFunc("glDeleteBuffers");
/* 2.0 funcs */
pglBlendEquation = GetGLFunc("glBlendEquation");
#ifdef GL_SHADERS #ifdef GL_SHADERS
pglCreateShader = GetGLFunc("glCreateShader"); pglCreateShader = GetGLFunc("glCreateShader");
pglShaderSource = GetGLFunc("glShaderSource"); pglShaderSource = GetGLFunc("glShaderSource");
@ -873,6 +889,7 @@ void SetupGLFunc4(void)
pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog"); pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog");
pglDeleteShader = GetGLFunc("glDeleteShader"); pglDeleteShader = GetGLFunc("glDeleteShader");
pglCreateProgram = GetGLFunc("glCreateProgram"); pglCreateProgram = GetGLFunc("glCreateProgram");
pglDeleteProgram = GetGLFunc("glDeleteProgram");
pglAttachShader = GetGLFunc("glAttachShader"); pglAttachShader = GetGLFunc("glAttachShader");
pglLinkProgram = GetGLFunc("glLinkProgram"); pglLinkProgram = GetGLFunc("glLinkProgram");
pglGetProgramiv = GetGLFunc("glGetProgramiv"); pglGetProgramiv = GetGLFunc("glGetProgramiv");
@ -896,20 +913,40 @@ void SetupGLFunc4(void)
EXPORT boolean HWRAPI(CompileShaders) (void) EXPORT boolean HWRAPI(CompileShaders) (void)
{ {
#ifdef GL_SHADERS #ifdef GL_SHADERS
GLuint gl_vertShader, gl_fragShader; GLint i;
GLint i, result;
if (!pglUseProgram) return false; if (!pglUseProgram)
return false;
gl_customshaders[0].vertex = NULL; gl_customshaders[SHADER_DEFAULT].vertex = NULL;
gl_customshaders[0].fragment = NULL; gl_customshaders[SHADER_DEFAULT].fragment = NULL;
for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++) for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++)
{ {
gl_shaderprogram_t *shader; gl_shader_t *shader, *usershader;
const GLchar *vert_shader = gl_shadersources[i].vertex; const GLchar *vert_shader = gl_shadersources[i].vertex;
const GLchar *frag_shader = gl_shadersources[i].fragment; const GLchar *frag_shader = gl_shadersources[i].fragment;
boolean custom = ((gl_customshaders[i].vertex || gl_customshaders[i].fragment) && (i > 0));
if (i >= HWR_MAXSHADERS)
break;
shader = &gl_shaders[i];
usershader = &gl_usershaders[i];
if (shader->program)
pglDeleteProgram(shader->program);
if (usershader->program)
pglDeleteProgram(usershader->program);
shader->program = 0;
usershader->program = 0;
if (!Shader_CompileProgram(shader, i, vert_shader, frag_shader))
shader->program = 0;
// Compile custom shader
if ((i == SHADER_DEFAULT) || !(gl_customshaders[i].vertex || gl_customshaders[i].fragment))
continue;
// 18032019 // 18032019
if (gl_customshaders[i].vertex) if (gl_customshaders[i].vertex)
@ -917,92 +954,15 @@ EXPORT boolean HWRAPI(CompileShaders) (void)
if (gl_customshaders[i].fragment) if (gl_customshaders[i].fragment)
frag_shader = gl_customshaders[i].fragment; frag_shader = gl_customshaders[i].fragment;
if (i >= HWR_MAXSHADERS) if (!Shader_CompileProgram(usershader, i, vert_shader, frag_shader))
break;
shader = &gl_shaderprograms[i];
shader->program = 0;
shader->custom = custom;
//
// Load and compile vertex shader
//
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
if (!gl_vertShader)
{ {
GL_MSG_Error("CompileShaders: Error creating vertex shader %s\n", HWR_GetShaderName(i)); GL_MSG_Warning("CompileShaders: Could not compile custom shader program for %s\n", HWR_GetShaderName(i));
continue; usershader->program = 0;
} }
pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
pglCompileShader(gl_vertShader);
// check for compile errors
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
continue;
}
//
// Load and compile fragment shader
//
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
if (!gl_fragShader)
{
GL_MSG_Error("CompileShaders: Error creating fragment shader %s\n", HWR_GetShaderName(i));
continue;
}
pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
pglCompileShader(gl_fragShader);
// check for compile errors
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
continue;
}
shader->program = pglCreateProgram();
pglAttachShader(shader->program, gl_vertShader);
pglAttachShader(shader->program, gl_fragShader);
pglLinkProgram(shader->program);
// check link status
pglGetProgramiv(shader->program, GL_LINK_STATUS, &result);
// delete the shader objects
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
// couldn't link?
if (result != GL_TRUE)
{
shader->program = 0;
shader->custom = false;
GL_MSG_Error("CompileShaders: Error linking shader program %s\n", HWR_GetShaderName(i));
continue;
}
// 13062019
#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform);
// lighting
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
// misc. (custom shaders)
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
#undef GETUNI
} }
SetShader(SHADER_DEFAULT);
return true; return true;
#else #else
return false; return false;
@ -1070,26 +1030,45 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boole
#endif #endif
} }
EXPORT void HWRAPI(SetShader) (int shader) EXPORT void HWRAPI(SetShader) (int type)
{ {
#ifdef GL_SHADERS #ifdef GL_SHADERS
if (gl_allowshaders) if (gl_allowshaders != HWD_SHADEROPTION_OFF)
{ {
gl_shader_t *shader = gl_shaderstate.current;
// If using model lighting, set the appropriate shader. // If using model lighting, set the appropriate shader.
// However don't override a custom shader. // However don't override a custom shader.
if (shader == SHADER_MODEL && model_lighting if (type == SHADER_MODEL && model_lighting
&& !(gl_shaderprograms[SHADER_MODEL].custom && !gl_shaderprograms[SHADER_MODEL_LIGHTING].custom)) && !(gl_shaders[SHADER_MODEL].custom && !gl_shaders[SHADER_MODEL_LIGHTING].custom))
shader = SHADER_MODEL_LIGHTING; type = SHADER_MODEL_LIGHTING;
if ((GLuint)shader != gl_currentshaderprogram)
if ((shader == NULL) || (GLuint)type != gl_shaderstate.type)
{ {
gl_currentshaderprogram = shader; gl_shader_t *baseshader = &gl_shaders[type];
gl_shaderprogramchanged = true; gl_shader_t *usershader = &gl_usershaders[type];
if (usershader->program)
shader = (gl_allowshaders == HWD_SHADEROPTION_NOCUSTOM) ? baseshader : usershader;
else
shader = baseshader;
gl_shaderstate.current = shader;
gl_shaderstate.type = type;
gl_shaderstate.changed = true;
} }
gl_shadersenabled = true;
if (gl_shaderstate.program != shader->program)
{
gl_shaderstate.program = shader->program;
gl_shaderstate.changed = true;
}
gl_shadersenabled = (shader->program != 0);
return; return;
} }
#else #else
(void)shader; (void)type;
#endif #endif
gl_shadersenabled = false; gl_shadersenabled = false;
} }
@ -1097,11 +1076,15 @@ EXPORT void HWRAPI(SetShader) (int shader)
EXPORT void HWRAPI(UnSetShader) (void) EXPORT void HWRAPI(UnSetShader) (void)
{ {
#ifdef GL_SHADERS #ifdef GL_SHADERS
gl_shadersenabled = false; gl_shaderstate.current = NULL;
gl_currentshaderprogram = 0; gl_shaderstate.type = 0;
if (!pglUseProgram) return; gl_shaderstate.program = 0;
pglUseProgram(0);
if (pglUseProgram)
pglUseProgram(0);
#endif #endif
gl_shadersenabled = false;
} }
EXPORT void HWRAPI(CleanShaders) (void) EXPORT void HWRAPI(CleanShaders) (void)
@ -1258,6 +1241,7 @@ void SetStates(void)
pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
pglEnable(GL_ALPHA_TEST);
pglAlphaFunc(GL_NOTEQUAL, 0.0f); pglAlphaFunc(GL_NOTEQUAL, 0.0f);
//pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque) //pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque)
@ -1300,6 +1284,17 @@ void SetStates(void)
} }
// -----------------+
// DeleteTexture : Deletes a texture from the GPU and frees its data
// -----------------+
EXPORT void HWRAPI(DeleteTexture) (FTextureInfo *pTexInfo)
{
if (pTexInfo->downloaded)
pglDeleteTextures(1, (GLuint *)&pTexInfo->downloaded);
pTexInfo->downloaded = 0;
}
// -----------------+ // -----------------+
// Flush : flush OpenGL textures // Flush : flush OpenGL textures
// : Clear list of downloaded mipmaps // : Clear list of downloaded mipmaps
@ -1310,17 +1305,24 @@ void Flush(void)
while (gl_cachehead) while (gl_cachehead)
{ {
if (gl_cachehead->downloaded) DeleteTexture(gl_cachehead);
pglDeleteTextures(1, (GLuint *)&gl_cachehead->downloaded);
gl_cachehead->downloaded = 0;
gl_cachehead = gl_cachehead->nextmipmap; gl_cachehead = gl_cachehead->nextmipmap;
} }
gl_cachetail = gl_cachehead = NULL; //Hurdler: well, gl_cachehead is already NULL
ClearCacheList(); //Hurdler: well, gl_cachehead is already NULL
tex_downloaded = 0; tex_downloaded = 0;
} }
// -----------------+
// ClearCacheList : Clears the texture cache tail and head
// -----------------+
EXPORT void HWRAPI(ClearCacheList) (void)
{
gl_cachetail = gl_cachehead = NULL;
}
// -----------------+ // -----------------+
// isExtAvailable : Look if an OpenGL extension is available // isExtAvailable : Look if an OpenGL extension is available
// Returns : true if extension available // Returns : true if extension available
@ -1517,64 +1519,110 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1,
pglEnable(GL_TEXTURE_2D); pglEnable(GL_TEXTURE_2D);
} }
static void Clamp2D(GLenum pname)
{
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE);
}
// -----------------+ // -----------------+
// SetBlend : Set render mode // SetBlend : Set render mode
// -----------------+ // -----------------+
// PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0, // PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0,
// is it faster when pixels are discarded ? // is it faster when pixels are discarded ?
static void Clamp2D(GLenum pname)
{
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE);
}
static void SetBlendEquation(GLenum mode)
{
if (pglBlendEquation)
pglBlendEquation(mode);
}
static void SetBlendMode(FBITFIELD flags)
{
// Set blending function
switch (flags)
{
case PF_Translucent & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
break;
case PF_Masked & PF_Blending:
// Hurdler: does that mean lighting is only made by alpha src?
// it sounds ok, but not for polygonsmooth
pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture
break;
case PF_Additive & PF_Blending:
case PF_Subtractive & PF_Blending:
case PF_ReverseSubtract & PF_Blending:
case PF_Environment & PF_Blending:
pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
break;
case PF_AdditiveSource & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
break;
case PF_Multiplicative & PF_Blending:
pglBlendFunc(GL_DST_COLOR, GL_ZERO);
break;
case PF_Fog & PF_Fog:
// Sryder: Fog
// multiplies input colour by input alpha, and destination colour by input colour, then adds them
pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
break;
default: // must be 0, otherwise it's an error
// No blending
pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending
break;
}
// Set blending equation
switch (flags)
{
case PF_Subtractive & PF_Blending:
SetBlendEquation(GL_FUNC_SUBTRACT);
break;
case PF_ReverseSubtract & PF_Blending:
// good for shadow
// not really but what else ?
SetBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
break;
default:
SetBlendEquation(GL_FUNC_ADD);
break;
}
// Alpha test
switch (flags)
{
case PF_Masked & PF_Blending:
pglAlphaFunc(GL_GREATER, 0.5f);
break;
case PF_Translucent & PF_Blending:
case PF_Additive & PF_Blending:
case PF_AdditiveSource & PF_Blending:
case PF_Subtractive & PF_Blending:
case PF_ReverseSubtract & PF_Blending:
case PF_Environment & PF_Blending:
case PF_Multiplicative & PF_Blending:
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Fog & PF_Fog:
pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments
break;
default:
pglAlphaFunc(GL_GREATER, 0.5f);
break;
}
}
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
{ {
FBITFIELD Xor; FBITFIELD Xor;
Xor = CurrentPolyFlags^PolyFlags; Xor = CurrentPolyFlags^PolyFlags;
if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible|PF_NoAlphaTest)) if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible))
{ {
if (Xor&(PF_Blending)) // if blending mode must be changed if (Xor & PF_Blending) // if blending mode must be changed
{ SetBlendMode(PolyFlags & PF_Blending);
switch (PolyFlags & PF_Blending) {
case PF_Translucent & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Masked & PF_Blending:
// Hurdler: does that mean lighting is only made by alpha src?
// it sounds ok, but not for polygonsmooth
pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture
pglAlphaFunc(GL_GREATER, 0.5f);
break;
case PF_Additive & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Environment & PF_Blending:
pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Substractive & PF_Blending:
// good for shadow
// not really but what else ?
pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Fog & PF_Fog:
// Sryder: Fog
// multiplies input colour by input alpha, and destination colour by input colour, then adds them
pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments
break;
default : // must be 0, otherwise it's an error
// No blending
pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending
pglAlphaFunc(GL_GREATER, 0.5f);
break;
}
}
if (Xor & PF_NoAlphaTest) if (Xor & PF_NoAlphaTest)
{ {
if (PolyFlags & PF_NoAlphaTest) if (PolyFlags & PF_NoAlphaTest)
@ -1591,7 +1639,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
pglDisable(GL_POLYGON_OFFSET_FILL); pglDisable(GL_POLYGON_OFFSET_FILL);
} }
if (Xor&PF_NoDepthTest) if (Xor & PF_NoDepthTest)
{ {
if (PolyFlags & PF_NoDepthTest) if (PolyFlags & PF_NoDepthTest)
pglDepthFunc(GL_ALWAYS); //pglDisable(GL_DEPTH_TEST); pglDepthFunc(GL_ALWAYS); //pglDisable(GL_DEPTH_TEST);
@ -1599,25 +1647,25 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
pglDepthFunc(GL_LEQUAL); //pglEnable(GL_DEPTH_TEST); pglDepthFunc(GL_LEQUAL); //pglEnable(GL_DEPTH_TEST);
} }
if (Xor&PF_RemoveYWrap) if (Xor & PF_RemoveYWrap)
{ {
if (PolyFlags & PF_RemoveYWrap) if (PolyFlags & PF_RemoveYWrap)
Clamp2D(GL_TEXTURE_WRAP_T); Clamp2D(GL_TEXTURE_WRAP_T);
} }
if (Xor&PF_ForceWrapX) if (Xor & PF_ForceWrapX)
{ {
if (PolyFlags & PF_ForceWrapX) if (PolyFlags & PF_ForceWrapX)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
} }
if (Xor&PF_ForceWrapY) if (Xor & PF_ForceWrapY)
{ {
if (PolyFlags & PF_ForceWrapY) if (PolyFlags & PF_ForceWrapY)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
} }
if (Xor&PF_Modulated) if (Xor & PF_Modulated)
{ {
#if defined (__unix__) || defined (UNIXCOMMON) #if defined (__unix__) || defined (UNIXCOMMON)
if (oglflags & GLF_NOTEXENV) if (oglflags & GLF_NOTEXENV)
@ -1891,52 +1939,36 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
{ {
UpdateTexture(pTexInfo); UpdateTexture(pTexInfo);
pTexInfo->nextmipmap = NULL; pTexInfo->nextmipmap = NULL;
// insertion at the tail
if (gl_cachetail) if (gl_cachetail)
{ // insertion at the tail {
gl_cachetail->nextmipmap = pTexInfo; gl_cachetail->nextmipmap = pTexInfo;
gl_cachetail = pTexInfo; gl_cachetail = pTexInfo;
} }
else // initialization of the linked list else // initialization of the linked list
gl_cachetail = gl_cachehead = pTexInfo; gl_cachetail = gl_cachehead = pTexInfo;
} }
} }
static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
{
#ifdef GL_SHADERS
if (gl_shadersenabled && pglUseProgram)
{
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
if (shader->program)
{
if (gl_shaderprogramchanged)
{
pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program);
gl_shaderprogramchanged = false;
}
Shader_SetUniforms(Surface, poly, tint, fade);
return shader;
}
else
pglUseProgram(0);
}
#else
(void)Surface;
(void)poly;
(void)tint;
(void)fade;
#endif
return NULL;
}
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
{ {
#ifdef GL_SHADERS #ifdef GL_SHADERS
if (gl_shadersenabled) gl_shader_t *shader = gl_shaderstate.current;
if (gl_shadersenabled && (shader != NULL) && pglUseProgram)
{ {
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
if (!shader->program) if (!shader->program)
{
pglUseProgram(0);
return; return;
}
if (gl_shaderstate.changed)
{
pglUseProgram(shader->program);
gl_shaderstate.changed = false;
}
// Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f) // Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f)
if (poly == NULL) if (poly == NULL)
@ -1989,6 +2021,97 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
#endif #endif
} }
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader)
{
GLuint gl_vertShader, gl_fragShader;
GLint result;
//
// Load and compile vertex shader
//
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
if (!gl_vertShader)
{
GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i));
return false;
}
pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
pglCompileShader(gl_vertShader);
// check for compile errors
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
pglDeleteShader(gl_vertShader);
return false;
}
//
// Load and compile fragment shader
//
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
if (!gl_fragShader)
{
GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i));
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
return false;
}
pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
pglCompileShader(gl_fragShader);
// check for compile errors
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
return false;
}
shader->program = pglCreateProgram();
pglAttachShader(shader->program, gl_vertShader);
pglAttachShader(shader->program, gl_fragShader);
pglLinkProgram(shader->program);
// check link status
pglGetProgramiv(shader->program, GL_LINK_STATUS, &result);
// delete the shader objects
pglDeleteShader(gl_vertShader);
pglDeleteShader(gl_fragShader);
// couldn't link?
if (result != GL_TRUE)
{
GL_MSG_Error("Shader_CompileProgram: Error linking shader program %s\n", HWR_GetShaderName(i));
pglDeleteProgram(shader->program);
return false;
}
// 13062019
#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform);
// lighting
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
// misc. (custom shaders)
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
#undef GETUNI
return true;
}
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum) static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum)
{ {
GLchar *infoLog = NULL; GLchar *infoLog = NULL;
@ -2002,7 +2125,7 @@ static void Shader_CompileError(const char *message, GLuint program, INT32 shade
pglGetShaderInfoLog(program, logLength, NULL, infoLog); pglGetShaderInfoLog(program, logLength, NULL, infoLog);
} }
GL_MSG_Error("CompileShaders: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : "")); GL_MSG_Error("Shader_CompileProgram: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : ""));
if (infoLog) if (infoLog)
free(infoLog); free(infoLog);
@ -2112,7 +2235,7 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD
pglColor4ubv(c); pglColor4ubv(c);
} }
Shader_Load(pSurf, &poly, &tint, &fade); Shader_SetUniforms(pSurf, &poly, &tint, &fade);
} }
// -----------------+ // -----------------+
@ -2158,7 +2281,7 @@ EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky)
{ {
int i, j; int i, j;
Shader_Load(NULL, NULL, NULL, NULL); Shader_SetUniforms(NULL, NULL, NULL, NULL);
// Build the sky dome! Yes! // Build the sky dome! Yes!
if (sky->rebuild) if (sky->rebuild)
@ -2250,15 +2373,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
break; break;
case HWD_SET_SHADERS: case HWD_SET_SHADERS:
switch (Value) gl_allowshaders = (hwdshaderoption_t)Value;
{
case 1:
gl_allowshaders = true;
break;
default:
gl_allowshaders = false;
break;
}
break; break;
case HWD_SET_TEXTUREFILTERMODE: case HWD_SET_TEXTUREFILTERMODE:
@ -2528,6 +2643,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
boolean useVBO = true; boolean useVBO = true;
FBITFIELD flags;
int i; int i;
// Because otherwise, scaling the screen negatively vertically breaks the lighting // Because otherwise, scaling the screen negatively vertically breaks the lighting
@ -2595,8 +2711,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
else else
pglColor4ubv((GLubyte*)&Surface->PolyColor.s); pglColor4ubv((GLubyte*)&Surface->PolyColor.s);
SetBlend((poly.alpha < 1 ? PF_Translucent : (PF_Masked|PF_Occlude))|PF_Modulated);
tint.red = byte2float[Surface->TintColor.s.red]; tint.red = byte2float[Surface->TintColor.s.red];
tint.green = byte2float[Surface->TintColor.s.green]; tint.green = byte2float[Surface->TintColor.s.green];
tint.blue = byte2float[Surface->TintColor.s.blue]; tint.blue = byte2float[Surface->TintColor.s.blue];
@ -2607,7 +2721,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.blue = byte2float[Surface->FadeColor.s.blue];
fade.alpha = byte2float[Surface->FadeColor.s.alpha]; fade.alpha = byte2float[Surface->FadeColor.s.alpha];
Shader_Load(Surface, &poly, &tint, &fade); flags = (Surface->PolyFlags | PF_Modulated);
if (Surface->PolyFlags & (PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative))
flags |= PF_Occlude;
else if (Surface->PolyColor.s.alpha == 0xFF)
flags |= (PF_Occlude | PF_Masked);
SetBlend(flags);
Shader_SetUniforms(Surface, &poly, &tint, &fade);
pglEnable(GL_CULL_FACE); pglEnable(GL_CULL_FACE);
pglEnable(GL_NORMALIZE); pglEnable(GL_NORMALIZE);
@ -3176,7 +3297,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void)
pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
SetBlend(PF_Modulated|PF_NoDepthTest|PF_Clip|PF_NoZClip); SetBlend(PF_Modulated|PF_NoDepthTest);
pglEnable(GL_TEXTURE_2D); pglEnable(GL_TEXTURE_2D);
// Draw the original screen // Draw the original screen
@ -3186,7 +3307,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void)
pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest|PF_Clip|PF_NoZClip); SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest);
// Draw the end screen that fades in // Draw the end screen that fades in
pglActiveTexture(GL_TEXTURE0); pglActiveTexture(GL_TEXTURE0);

View File

@ -1794,8 +1794,8 @@ static void HU_DrawChat_Old(void)
size_t i = 0; size_t i = 0;
const char *ntalk = "Say: ", *ttalk = "Say-Team: "; const char *ntalk = "Say: ", *ttalk = "Say-Team: ";
const char *talk = ntalk; const char *talk = ntalk;
INT32 charwidth = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; INT32 charwidth = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
INT32 charheight = 8 * con_scalefactor; //SHORT(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor; INT32 charheight = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor;
if (teamtalk) if (teamtalk)
{ {
talk = ttalk; talk = ttalk;
@ -1816,7 +1816,7 @@ static void HU_DrawChat_Old(void)
} }
else else
{ {
//charwidth = SHORT(hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor; //charwidth = (hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true); V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true);
} }
c += charwidth; c += charwidth;
@ -1844,7 +1844,7 @@ static void HU_DrawChat_Old(void)
} }
else else
{ {
//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; //charwidth = (hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true); V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true);
} }
@ -2120,7 +2120,7 @@ void HU_Drawer(void)
HU_DrawCrosshair2(); HU_DrawCrosshair2();
// draw desynch text // draw desynch text
if (hu_resynching) if (hu_redownloadinggamestate)
{ {
static UINT32 resynch_ticker = 0; static UINT32 resynch_ticker = 0;
char resynch_text[14]; char resynch_text[14];
@ -2364,7 +2364,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
} }
if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED)) if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); V_DrawSmallScaledPatch(x - exiticon->width/2 - 1, y-3, 0, exiticon);
if (gametyperankings[gametype] == GT_RACE) if (gametyperankings[gametype] == GT_RACE)
{ {
@ -2668,7 +2668,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);
if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED)) if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED))
V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); V_DrawSmallScaledPatch(x - exiticon->width/2 - 1, y-3, 0, exiticon);
// Draw emeralds // Draw emeralds
if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1))
@ -3094,7 +3094,7 @@ static void HU_DrawCoopOverlay(void)
if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata)) if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata))
{ {
V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems)); V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems));
V_DrawScaledPatch(128, 144 - SHORT(emblemicon->height)/4, 0, emblemicon); V_DrawScaledPatch(128, 144 - emblemicon->height/4, 0, emblemicon);
} }
if (!LUA_HudEnabled(hud_coopemeralds)) if (!LUA_HudEnabled(hud_coopemeralds))

View File

@ -21,15 +21,12 @@
// copied from SDL mixer, plus GME // copied from SDL mixer, plus GME
typedef enum { typedef enum {
MU_NONE, MU_NONE,
MU_CMD,
MU_WAV, MU_WAV,
MU_MOD, MU_MOD,
MU_MID, MU_MID,
MU_OGG, MU_OGG,
MU_MP3, MU_MP3,
MU_MP3_MAD_UNUSED, // use MU_MP3 instead
MU_FLAC, MU_FLAC,
MU_MODPLUG_UNUSED, // use MU_MOD instead
MU_GME, MU_GME,
MU_MOD_EX, // libopenmpt MU_MOD_EX, // libopenmpt
MU_MID_EX // Non-native MIDI MU_MID_EX // Non-native MIDI

View File

@ -46,7 +46,13 @@ UINT32 I_GetFreeMem(UINT32 *total);
*/ */
tic_t I_GetTime(void); tic_t I_GetTime(void);
int I_GetTimeMicros(void);// provides microsecond counter for render stats /** \brief Returns precise time value for performance measurement.
*/
precise_t I_GetPreciseTime(void);
/** \brief Returns the difference between precise times as microseconds.
*/
int I_PreciseToMicros(precise_t);
/** \brief The I_Sleep function /** \brief The I_Sleep function

View File

@ -20,127 +20,121 @@
#endif #endif
#ifndef NO_IPV6 #ifndef NO_IPV6
#define HAVE_IPV6 #define HAVE_IPV6
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
#define USE_WINSOCK #define USE_WINSOCK
#if defined (_WIN64) || defined (HAVE_IPV6) #if defined (_WIN64) || defined (HAVE_IPV6)
#define USE_WINSOCK2 #define USE_WINSOCK2
#else //_WIN64/HAVE_IPV6 #else //_WIN64/HAVE_IPV6
#define USE_WINSOCK1 #define USE_WINSOCK1
#endif #endif
#endif //WIN32 OS #endif //WIN32 OS
#ifdef USE_WINSOCK2 #ifdef USE_WINSOCK2
#include <ws2tcpip.h> #include <ws2tcpip.h>
#endif #endif
#include "doomdef.h" #include "doomdef.h"
#if defined (NOMD5) && !defined (NONET) #if defined (NOMD5) && !defined (NONET)
//#define NONET //#define NONET
#endif #endif
#ifdef NONET #ifdef NONET
#undef HAVE_MINIUPNPC #undef HAVE_MINIUPNPC
#else #else
#ifdef USE_WINSOCK1 #ifdef USE_WINSOCK1
#include <winsock.h> #include <winsock.h>
#elif !defined (SCOUW2) && !defined (SCOUW7) #else
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
#include <arpa/inet.h> #include <arpa/inet.h>
#endif //normal BSD API #ifdef __APPLE_CC__
#ifndef _BSD_SOCKLEN_T_
#define _BSD_SOCKLEN_T_
#endif //_BSD_SOCKLEN_T_
#endif //__APPLE_CC__
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/ioctl.h>
#endif //normal BSD API
#ifndef USE_WINSOCK #include <errno.h>
#ifdef __APPLE_CC__ #include <time.h>
#ifndef _BSD_SOCKLEN_T_
#define _BSD_SOCKLEN_T_
#endif //_BSD_SOCKLEN_T_
#endif //__APPLE_CC__
#include <sys/socket.h>
#include <netinet/in.h>
#endif //normal BSD API
#ifndef USE_WINSOCK #if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
#include <netdb.h> #include <sys/time.h>
#include <sys/ioctl.h> #endif // UNIXCOMMON
#endif //normal BSD API #endif
#include <errno.h> #ifdef USE_WINSOCK
#include <time.h> // some undefined under win32
#undef errno
//#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right?
#define errno h_errno // some very strange things happen when not using h_error?!?
#ifdef EWOULDBLOCK
#undef EWOULDBLOCK
#endif
#define EWOULDBLOCK WSAEWOULDBLOCK
#ifdef EMSGSIZE
#undef EMSGSIZE
#endif
#define EMSGSIZE WSAEMSGSIZE
#ifdef ECONNREFUSED
#undef ECONNREFUSED
#endif
#define ECONNREFUSED WSAECONNREFUSED
#ifdef ETIMEDOUT
#undef ETIMEDOUT
#endif
#define ETIMEDOUT WSAETIMEDOUT
#ifndef IOC_VENDOR
#define IOC_VENDOR 0x18000000
#endif
#ifndef _WSAIOW
#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
#endif
#ifndef SIO_UDP_CONNRESET
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
#endif
#ifndef AI_ADDRCONFIG
#define AI_ADDRCONFIG 0x00000400
#endif
#ifndef STATUS_INVALID_PARAMETER
#define STATUS_INVALID_PARAMETER 0xC000000D
#endif
#endif // USE_WINSOCK
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) #ifdef __DJGPP__
#include <sys/time.h> #ifdef WATTCP // Alam_GBC: Wattcp may need this
#endif // UNIXCOMMON #include <tcp.h>
#endif // !NONET #define strerror strerror_s
#else // wattcp
#include <lsck/lsck.h>
#endif // libsocket
#endif // djgpp
#ifdef USE_WINSOCK typedef union
// some undefined under win32 {
#undef errno struct sockaddr any;
//#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right? struct sockaddr_in ip4;
#define errno h_errno // some very strange things happen when not using h_error?!? #ifdef HAVE_IPV6
#ifdef EWOULDBLOCK struct sockaddr_in6 ip6;
#undef EWOULDBLOCK
#endif #endif
#define EWOULDBLOCK WSAEWOULDBLOCK } mysockaddr_t;
#ifdef EMSGSIZE
#undef EMSGSIZE
#endif
#define EMSGSIZE WSAEMSGSIZE
#ifdef ECONNREFUSED
#undef ECONNREFUSED
#endif
#define ECONNREFUSED WSAECONNREFUSED
#ifdef ETIMEDOUT
#undef ETIMEDOUT
#endif
#define ETIMEDOUT WSAETIMEDOUT
#ifndef IOC_VENDOR
#define IOC_VENDOR 0x18000000
#endif
#ifndef _WSAIOW
#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
#endif
#ifndef SIO_UDP_CONNRESET
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
#endif
#ifndef AI_ADDRCONFIG
#define AI_ADDRCONFIG 0x00000400
#endif
#ifndef STATUS_INVALID_PARAMETER
#define STATUS_INVALID_PARAMETER 0xC000000D
#endif
#endif
#ifdef __DJGPP__ #ifdef HAVE_MINIUPNPC
#ifdef WATTCP // Alam_GBC: Wattcp may need this #ifdef STATIC_MINIUPNPC
#include <tcp.h> #define STATICLIB
#define strerror strerror_s #endif
#else // wattcp #include "miniupnpc/miniwget.h"
#include <lsck/lsck.h> #include "miniupnpc/miniupnpc.h"
#endif // libsocket #include "miniupnpc/upnpcommands.h"
#endif // djgpp #undef STATICLIB
static UINT8 UPNP_support = TRUE;
typedef union #endif // HAVE_MINIUPNC
{
struct sockaddr any;
struct sockaddr_in ip4;
#ifdef HAVE_IPV6
struct sockaddr_in6 ip6;
#endif
} mysockaddr_t;
#ifdef HAVE_MINIUPNPC
#ifdef STATIC_MINIUPNPC
#define STATICLIB
#endif
#include "miniupnpc/miniwget.h"
#include "miniupnpc/miniupnpc.h"
#include "miniupnpc/upnpcommands.h"
#undef STATICLIB
static UINT8 UPNP_support = TRUE;
#endif
#endif // !NONET #endif // !NONET
@ -177,32 +171,32 @@ static UINT8 UPNP_support = TRUE;
#define DEFAULTPORT "5029" #define DEFAULTPORT "5029"
#if defined (USE_WINSOCK) && !defined (NONET) #if defined (USE_WINSOCK) && !defined (NONET)
typedef SOCKET SOCKET_TYPE; typedef SOCKET SOCKET_TYPE;
#define ERRSOCKET (SOCKET_ERROR) #define ERRSOCKET (SOCKET_ERROR)
#else #else
#if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__) #if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__)
typedef int SOCKET_TYPE; typedef int SOCKET_TYPE;
#else #else
typedef unsigned long SOCKET_TYPE; typedef unsigned long SOCKET_TYPE;
#endif #endif
#define ERRSOCKET (-1) #define ERRSOCKET (-1)
#endif
#if (defined (WATTCP) && !defined (__libsocket_socklen_t)) || defined (USE_WINSOCK1)
typedef int socklen_t;
#endif #endif
#ifndef NONET #ifndef NONET
static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET}; // define socklen_t in DOS/Windows if it is not already defined
static size_t mysocketses = 0; #if (defined (WATTCP) && !defined (__libsocket_socklen_t)) || defined (USE_WINSOCK1)
static int myfamily[MAXNETNODES+1] = {0}; typedef int socklen_t;
static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET}; #endif
static mysockaddr_t clientaddress[MAXNETNODES+1]; static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET};
static mysockaddr_t broadcastaddress[MAXNETNODES+1]; static size_t mysocketses = 0;
static size_t broadcastaddresses = 0; static int myfamily[MAXNETNODES+1] = {0};
static boolean nodeconnected[MAXNETNODES+1]; static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET};
static mysockaddr_t banned[MAXBANS]; static mysockaddr_t clientaddress[MAXNETNODES+1];
static UINT8 bannedmask[MAXBANS]; static mysockaddr_t broadcastaddress[MAXNETNODES+1];
static size_t broadcastaddresses = 0;
static boolean nodeconnected[MAXNETNODES+1];
static mysockaddr_t banned[MAXBANS];
static UINT8 bannedmask[MAXBANS];
#endif #endif
static size_t numbans = 0; static size_t numbans = 0;

View File

@ -36,10 +36,9 @@ typedef enum
*/ */
extern rendermode_t rendermode; extern rendermode_t rendermode;
/** \brief OpenGL state /** \brief render mode set by command line arguments
0 = never loaded, 1 = loaded successfully, -1 = failed loading
*/ */
extern INT32 vid_opengl_state; extern rendermode_t chosenrendermode;
/** \brief use highcolor modes if true /** \brief use highcolor modes if true
*/ */
@ -90,8 +89,9 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h);
INT32 VID_SetMode(INT32 modenum); INT32 VID_SetMode(INT32 modenum);
/** \brief Checks the render state /** \brief Checks the render state
\return true if the renderer changed
*/ */
void VID_CheckRenderer(void); boolean VID_CheckRenderer(void);
/** \brief Load OpenGL mode /** \brief Load OpenGL mode
*/ */

View File

@ -584,6 +584,7 @@ char spr2names[NUMPLAYERSPRITES][5] =
"TAL9", "TAL9",
"TALA", "TALA",
"TALB", "TALB",
"TALC",
"CNT1", "CNT1",
"CNT2", "CNT2",
@ -661,6 +662,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
SPR2_TAL0, // SPR2_TAL9, SPR2_TAL0, // SPR2_TAL9,
SPR2_TAL9, // SPR2_TALA, SPR2_TAL9, // SPR2_TALA,
SPR2_TAL0, // SPR2_TALB, SPR2_TAL0, // SPR2_TALB,
SPR2_TAL6, // SPR2_TALC,
SPR2_WAIT, // SPR2_CNT1, SPR2_WAIT, // SPR2_CNT1,
SPR2_FALL, // SPR2_CNT2, SPR2_FALL, // SPR2_CNT2,
@ -801,6 +803,7 @@ state_t states[NUMSTATES] =
{SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN}, // S_TAILSOVERLAY_PAIN {SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN}, // S_TAILSOVERLAY_PAIN
{SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_GASP}, // S_TAILSOVERLAY_GASP {SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_GASP}, // S_TAILSOVERLAY_GASP
{SPR_PLAY, SPR2_TALB , 35, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE}, // S_TAILSOVERLAY_EDGE {SPR_PLAY, SPR2_TALB , 35, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE}, // S_TAILSOVERLAY_EDGE
{SPR_PLAY, SPR2_TALC|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_DASH}, // S_TAILSOVERLAY_DASH
// [: // [:
{SPR_JETF, 3|FF_ANIMATE|FF_FULLBRIGHT, 2, {NULL}, 1, 1, S_JETFUME1}, // S_JETFUMEFLASH {SPR_JETF, 3|FF_ANIMATE|FF_FULLBRIGHT, 2, {NULL}, 1, 1, S_JETFUME1}, // S_JETFUMEFLASH
@ -3921,9 +3924,7 @@ state_t states[NUMSTATES] =
{SPR_BRIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_BLUEBRICKDEBRIS {SPR_BRIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_BLUEBRICKDEBRIS
{SPR_BRIY, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_YELLOWBRICKDEBRIS {SPR_BRIY, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_YELLOWBRICKDEBRIS
#ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif
}; };
mobjinfo_t mobjinfo[NUMMOBJTYPES] = mobjinfo_t mobjinfo[NUMMOBJTYPES] =
@ -6455,8 +6456,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_fizzle, // deathsound sfx_fizzle, // deathsound
10*FRACUNIT, // speed 10*FRACUNIT, // speed
48*FRACUNIT, // radius 24*FRACUNIT, // radius
160*FRACUNIT, // height 80*FRACUNIT, // height
0, // display offset 0, // display offset
DMG_ELECTRIC, // mass DMG_ELECTRIC, // mass
1, // damage 1, // damage
@ -21650,7 +21651,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
#ifdef SEENAMES
{ // MT_NAMECHECK { // MT_NAMECHECK
-1, // doomednum -1, // doomednum
S_NAMECHECK, // spawnstate S_NAMECHECK, // spawnstate
@ -21677,7 +21677,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY|MF_NOSECTOR, // flags MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY|MF_NOSECTOR, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
#endif
}; };
skincolor_t skincolors[MAXSKINCOLORS] = { skincolor_t skincolors[MAXSKINCOLORS] = {

View File

@ -19,11 +19,279 @@
#include "sounds.h" #include "sounds.h"
#include "m_fixed.h" #include "m_fixed.h"
// dehacked.c now has lists for the more named enums! PLEASE keep them up to date! // deh_tables.c now has lists for the more named enums! PLEASE keep them up to date!
// For great modding!! // For great modding!!
// IMPORTANT!
// DO NOT FORGET TO SYNC THIS LIST WITH THE ACTIONPOINTERS ARRAY IN DEH_TABLES.C
enum actionnum
{
A_EXPLODE = 0,
A_PAIN,
A_FALL,
A_MONITORPOP,
A_GOLDMONITORPOP,
A_GOLDMONITORRESTORE,
A_GOLDMONITORSPARKLE,
A_LOOK,
A_CHASE,
A_FACESTABCHASE,
A_FACESTABREV,
A_FACESTABHURL,
A_FACESTABMISS,
A_STATUEBURST,
A_FACETARGET,
A_FACETRACER,
A_SCREAM,
A_BOSSDEATH,
A_CUSTOMPOWER,
A_GIVEWEAPON,
A_RINGBOX,
A_INVINCIBILITY,
A_SUPERSNEAKERS,
A_BUNNYHOP,
A_BUBBLESPAWN,
A_FANBUBBLESPAWN,
A_BUBBLERISE,
A_BUBBLECHECK,
A_AWARDSCORE,
A_EXTRALIFE,
A_GIVESHIELD,
A_GRAVITYBOX,
A_SCORERISE,
A_ATTRACTCHASE,
A_DROPMINE,
A_FISHJUMP,
A_THROWNRING,
A_SETSOLIDSTEAM,
A_UNSETSOLIDSTEAM,
A_SIGNSPIN,
A_SIGNPLAYER,
A_OVERLAYTHINK,
A_JETCHASE,
A_JETBTHINK,
A_JETGTHINK,
A_JETGSHOOT,
A_SHOOTBULLET,
A_MINUSDIGGING,
A_MINUSPOPUP,
A_MINUSCHECK,
A_CHICKENCHECK,
A_MOUSETHINK,
A_DETONCHASE,
A_CAPECHASE,
A_ROTATESPIKEBALL,
A_SLINGAPPEAR,
A_UNIDUSBALL,
A_ROCKSPAWN,
A_SETFUSE,
A_CRAWLACOMMANDERTHINK,
A_SMOKETRAILER,
A_RINGEXPLODE,
A_OLDRINGEXPLODE,
A_MIXUP,
A_RECYCLEPOWERS,
A_BOSS1CHASE,
A_FOCUSTARGET,
A_BOSS2CHASE,
A_BOSS2POGO,
A_BOSSZOOM,
A_BOSSSCREAM,
A_BOSS2TAKEDAMAGE,
A_BOSS7CHASE,
A_GOOPSPLAT,
A_BOSS2POGOSFX,
A_BOSS2POGOTARGET,
A_BOSSJETFUME,
A_EGGMANBOX,
A_TURRETFIRE,
A_SUPERTURRETFIRE,
A_TURRETSTOP,
A_JETJAWROAM,
A_JETJAWCHOMP,
A_POINTYTHINK,
A_CHECKBUDDY,
A_HOODFIRE,
A_HOODTHINK,
A_HOODFALL,
A_ARROWBONKS,
A_SNAILERTHINK,
A_SHARPCHASE,
A_SHARPSPIN,
A_SHARPDECEL,
A_CRUSHSTACEANWALK,
A_CRUSHSTACEANPUNCH,
A_CRUSHCLAWAIM,
A_CRUSHCLAWLAUNCH,
A_VULTUREVTOL,
A_VULTURECHECK,
A_VULTUREHOVER,
A_VULTUREBLAST,
A_VULTUREFLY,
A_SKIMCHASE,
A_1UPTHINKER,
A_SKULLATTACK,
A_LOBSHOT,
A_FIRESHOT,
A_SUPERFIRESHOT,
A_BOSSFIRESHOT,
A_BOSS7FIREMISSILES,
A_BOSS1LASER,
A_BOSS4REVERSE,
A_BOSS4SPEEDUP,
A_BOSS4RAISE,
A_SPARKFOLLOW,
A_BUZZFLY,
A_GUARDCHASE,
A_EGGSHIELD,
A_SETREACTIONTIME,
A_BOSS1SPIKEBALLS,
A_BOSS3TAKEDAMAGE,
A_BOSS3PATH,
A_BOSS3SHOCKTHINK,
A_LINEDEFEXECUTE,
A_PLAYSEESOUND,
A_PLAYATTACKSOUND,
A_PLAYACTIVESOUND,
A_SPAWNOBJECTABSOLUTE,
A_SPAWNOBJECTRELATIVE,
A_CHANGEANGLERELATIVE,
A_CHANGEANGLEABSOLUTE,
A_ROLLANGLE,
A_CHANGEROLLANGLERELATIVE,
A_CHANGEROLLANGLEABSOLUTE,
A_PLAYSOUND,
A_FINDTARGET,
A_FINDTRACER,
A_SETTICS,
A_SETRANDOMTICS,
A_CHANGECOLORRELATIVE,
A_CHANGECOLORABSOLUTE,
A_DYE,
A_MOVERELATIVE,
A_MOVEABSOLUTE,
A_THRUST,
A_ZTHRUST,
A_SETTARGETSTARGET,
A_SETOBJECTFLAGS,
A_SETOBJECTFLAGS2,
A_RANDOMSTATE,
A_RANDOMSTATERANGE,
A_DUALACTION,
A_REMOTEACTION,
A_TOGGLEFLAMEJET,
A_ORBITNIGHTS,
A_GHOSTME,
A_SETOBJECTSTATE,
A_SETOBJECTTYPESTATE,
A_KNOCKBACK,
A_PUSHAWAY,
A_RINGDRAIN,
A_SPLITSHOT,
A_MISSILESPLIT,
A_MULTISHOT,
A_INSTALOOP,
A_CUSTOM3DROTATE,
A_SEARCHFORPLAYERS,
A_CHECKRANDOM,
A_CHECKTARGETRINGS,
A_CHECKRINGS,
A_CHECKTOTALRINGS,
A_CHECKHEALTH,
A_CHECKRANGE,
A_CHECKHEIGHT,
A_CHECKTRUERANGE,
A_CHECKTHINGCOUNT,
A_CHECKAMBUSH,
A_CHECKCUSTOMVALUE,
A_CHECKCUSVALMEMO,
A_SETCUSTOMVALUE,
A_USECUSVALMEMO,
A_RELAYCUSTOMVALUE,
A_CUSVALACTION,
A_FORCESTOP,
A_FORCEWIN,
A_SPIKERETRACT,
A_INFOSTATE,
A_REPEAT,
A_SETSCALE,
A_REMOTEDAMAGE,
A_HOMINGCHASE,
A_TRAPSHOT,
A_VILETARGET,
A_VILEATTACK,
A_VILEFIRE,
A_BRAKCHASE,
A_BRAKFIRESHOT,
A_BRAKLOBSHOT,
A_NAPALMSCATTER,
A_SPAWNFRESHCOPY,
A_FLICKYSPAWN,
A_FLICKYCENTER,
A_FLICKYAIM,
A_FLICKYFLY,
A_FLICKYSOAR,
A_FLICKYCOAST,
A_FLICKYHOP,
A_FLICKYFLOUNDER,
A_FLICKYCHECK,
A_FLICKYHEIGHTCHECK,
A_FLICKYFLUTTER,
A_FLAMEPARTICLE,
A_FADEOVERLAY,
A_BOSS5JUMP,
A_LIGHTBEAMRESET,
A_MINEEXPLODE,
A_MINERANGE,
A_CONNECTTOGROUND,
A_SPAWNPARTICLERELATIVE,
A_MULTISHOTDIST,
A_WHOCARESIFYOURSONISABEE,
A_PARENTTRIESTOSLEEP,
A_CRYINGTOMOMMA,
A_CHECKFLAGS2,
A_BOSS5FINDWAYPOINT,
A_DONPCSKID,
A_DONPCPAIN,
A_PREPAREREPEAT,
A_BOSS5EXTRAREPEAT,
A_BOSS5CALM,
A_BOSS5CHECKONGROUND,
A_BOSS5CHECKFALLING,
A_BOSS5PINCHSHOT,
A_BOSS5MAKEITRAIN,
A_BOSS5MAKEJUNK,
A_LOOKFORBETTER,
A_BOSS5BOMBEXPLODE,
A_DUSTDEVILTHINK,
A_TNTEXPLODE,
A_DEBRISRANDOM,
A_TRAINCAMEO,
A_TRAINCAMEO2,
A_CANARIVOREGAS,
A_KILLSEGMENTS,
A_SNAPPERSPAWN,
A_SNAPPERTHINKER,
A_SALOONDOORSPAWN,
A_MINECARTSPARKTHINK,
A_MODULOTOSTATE,
A_LAVAFALLROCKS,
A_LAVAFALLLAVA,
A_FALLINGLAVACHECK,
A_FIRESHRINK,
A_SPAWNPTERABYTES,
A_PTERABYTEHOVER,
A_ROLLOUTSPAWN,
A_ROLLOUTROCK,
A_DRAGONBOMBERSPAWN,
A_DRAGONWING,
A_DRAGONSEGMENT,
A_CHANGEHEIGHT,
NUMACTIONS
};
// IMPORTANT NOTE: If you add/remove from this list of action // IMPORTANT NOTE: If you add/remove from this list of action
// functions, don't forget to update them in dehacked.c! // functions, don't forget to update them in deh_tables.c!
void A_Explode(); void A_Explode();
void A_Pain(); void A_Pain();
void A_Fall(); void A_Fall();
@ -286,6 +554,8 @@ void A_DragonWing();
void A_DragonSegment(); void A_DragonSegment();
void A_ChangeHeight(); void A_ChangeHeight();
extern boolean actionsoverridden[NUMACTIONS];
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1 // ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 512 #define NUMMOBJFREESLOTS 512
#define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS #define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS
@ -856,6 +1126,7 @@ typedef enum playersprite
SPR2_TAL9, SPR2_TAL9,
SPR2_TALA, SPR2_TALA,
SPR2_TALB, SPR2_TALB,
SPR2_TALC,
SPR2_CNT1, // continue disappointment SPR2_CNT1, // continue disappointment
SPR2_CNT2, // continue lift SPR2_CNT2, // continue lift
@ -997,6 +1268,7 @@ typedef enum state
S_TAILSOVERLAY_PAIN, S_TAILSOVERLAY_PAIN,
S_TAILSOVERLAY_GASP, S_TAILSOVERLAY_GASP,
S_TAILSOVERLAY_EDGE, S_TAILSOVERLAY_EDGE,
S_TAILSOVERLAY_DASH,
// [: // [:
S_JETFUMEFLASH, S_JETFUMEFLASH,
@ -4008,9 +4280,7 @@ typedef enum state
S_BLUEBRICKDEBRIS, // for CEZ3 S_BLUEBRICKDEBRIS, // for CEZ3
S_YELLOWBRICKDEBRIS, // for CEZ3 S_YELLOWBRICKDEBRIS, // for CEZ3
#ifdef SEENAMES
S_NAMECHECK, S_NAMECHECK,
#endif
S_FIRSTFREESLOT, S_FIRSTFREESLOT,
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1, S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
@ -4810,9 +5080,7 @@ typedef enum mobj_type
MT_BLUEBRICKDEBRIS, // for CEZ3 MT_BLUEBRICKDEBRIS, // for CEZ3
MT_YELLOWBRICKDEBRIS, // for CEZ3 MT_YELLOWBRICKDEBRIS, // for CEZ3
#ifdef SEENAMES
MT_NAMECHECK, MT_NAMECHECK,
#endif
MT_FIRSTFREESLOT, MT_FIRSTFREESLOT,
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1, MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,

View File

@ -32,6 +32,7 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#include "taglist.h" // P_FindSpecialLineFromTag
#include "lua_hook.h" // hook_cmd_running errors #include "lua_hook.h" // hook_cmd_running errors
#define NOHUD if (hud_running)\ #define NOHUD if (hud_running)\
@ -162,6 +163,8 @@ static const struct {
{META_SKIN, "skin_t"}, {META_SKIN, "skin_t"},
{META_POWERS, "player_t.powers"}, {META_POWERS, "player_t.powers"},
{META_SOUNDSID, "skin_t.soundsid"}, {META_SOUNDSID, "skin_t.soundsid"},
{META_SKINSPRITES, "skin_t.sprites"},
{META_SKINSPRITESLIST, "skin_t.sprites[]"},
{META_VERTEX, "vertex_t"}, {META_VERTEX, "vertex_t"},
{META_LINE, "line_t"}, {META_LINE, "line_t"},
@ -246,6 +249,56 @@ static int lib_userdataType(lua_State *L)
return luaL_typerror(L, 1, "userdata"); return luaL_typerror(L, 1, "userdata");
} }
// Takes a metatable as first and only argument
// Only callable during script loading
static int lib_registerMetatable(lua_State *L)
{
static UINT16 nextid = 1;
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
luaL_checktype(L, 1, LUA_TTABLE);
if (nextid == 0)
return luaL_error(L, "Too many metatables registered?! Please consider rewriting your script once you are sober again.\n");
lua_getfield(L, LUA_REGISTRYINDEX, LREG_METATABLES); // 2
// registry.metatables[metatable] = nextid
lua_pushvalue(L, 1); // 3
lua_pushnumber(L, nextid); // 4
lua_settable(L, 2);
// registry.metatables[nextid] = metatable
lua_pushnumber(L, nextid); // 3
lua_pushvalue(L, 1); // 4
lua_settable(L, 2);
lua_pop(L, 1);
nextid++;
return 0;
}
// Takes a string as only argument and returns the metatable
// associated to the userdata type this string refers to
// Returns nil if the string does not refer to a valid userdata type
static int lib_userdataMetatable(lua_State *L)
{
UINT32 i;
const char *udname = luaL_checkstring(L, 1);
// Find internal metatable name
for (i = 0; meta2utype[i].meta; i++)
if (!strcmp(udname, meta2utype[i].utype))
{
luaL_getmetatable(L, meta2utype[i].meta);
return 1;
}
lua_pushnil(L);
return 1;
}
static int lib_isPlayerAdmin(lua_State *L) static int lib_isPlayerAdmin(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -915,6 +968,28 @@ static int lib_pMaceRotate(lua_State *L)
return 0; return 0;
} }
static int lib_pCreateFloorSpriteSlope(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, (pslope_t *)P_CreateFloorSpriteSlope(mobj), META_SLOPE);
return 1;
}
static int lib_pRemoveFloorSpriteSlope(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
P_RemoveFloorSpriteSlope(mobj);
return 1;
}
static int lib_pRailThinker(lua_State *L) static int lib_pRailThinker(lua_State *L)
{ {
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -3006,6 +3081,185 @@ static int lib_sStartMusicCaption(lua_State *L)
return 0; return 0;
} }
static int lib_sMusicType(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, S_MusicType());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicPlaying(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_MusicPlaying());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicPaused(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_MusicPaused());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicName(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushstring(L, S_MusicName());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicExists(lua_State *L)
{
boolean checkMIDI = lua_opttrueboolean(L, 2);
boolean checkDigi = lua_opttrueboolean(L, 3);
#ifdef MUSICSLOT_COMPATIBILITY
const char *music_name;
UINT32 music_num;
char music_compat_name[7];
UINT16 music_flags = 0;
NOHUD
if (lua_isnumber(L, 1))
{
music_num = (UINT32)luaL_checkinteger(L, 1);
music_flags = (UINT16)(music_num & 0x0000FFFF);
if (music_flags && music_flags <= 1035)
snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
else if (music_flags && music_flags <= 1050)
strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
else
music_compat_name[0] = 0; // becomes empty string
music_compat_name[6] = 0;
music_name = (const char *)&music_compat_name;
}
else
{
music_num = 0;
music_name = luaL_checkstring(L, 1);
}
#else
const char *music_name = luaL_checkstring(L, 1);
#endif
NOHUD
lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi));
return 1;
}
static int lib_sSetMusicLoopPoint(lua_State *L)
{
UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_SetMusicLoopPoint(looppoint));
else
lua_pushnil(L);
return 1;
}
static int lib_sGetMusicLoopPoint(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, (int)S_GetMusicLoopPoint());
else
lua_pushnil(L);
return 1;
}
static int lib_sPauseMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_PauseAudio();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sResumeMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_ResumeAudio();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
// G_GAME // G_GAME
//////////// ////////////
@ -3494,6 +3748,8 @@ static luaL_Reg lib[] = {
{"chatprint", lib_chatprint}, {"chatprint", lib_chatprint},
{"chatprintf", lib_chatprintf}, {"chatprintf", lib_chatprintf},
{"userdataType", lib_userdataType}, {"userdataType", lib_userdataType},
{"registerMetatable", lib_registerMetatable},
{"userdataMetatable", lib_userdataMetatable},
{"IsPlayerAdmin", lib_isPlayerAdmin}, {"IsPlayerAdmin", lib_isPlayerAdmin},
{"reserveLuabanks", lib_reserveLuabanks}, {"reserveLuabanks", lib_reserveLuabanks},
@ -3553,6 +3809,8 @@ static luaL_Reg lib[] = {
{"P_CheckSolidLava",lib_pCheckSolidLava}, {"P_CheckSolidLava",lib_pCheckSolidLava},
{"P_CanRunOnWater",lib_pCanRunOnWater}, {"P_CanRunOnWater",lib_pCanRunOnWater},
{"P_MaceRotate",lib_pMaceRotate}, {"P_MaceRotate",lib_pMaceRotate},
{"P_CreateFloorSpriteSlope",lib_pCreateFloorSpriteSlope},
{"P_RemoveFloorSpriteSlope",lib_pRemoveFloorSpriteSlope},
{"P_RailThinker",lib_pRailThinker}, {"P_RailThinker",lib_pRailThinker},
{"P_XYMovement",lib_pXYMovement}, {"P_XYMovement",lib_pXYMovement},
{"P_RingXYMovement",lib_pRingXYMovement}, {"P_RingXYMovement",lib_pRingXYMovement},
@ -3712,6 +3970,15 @@ static luaL_Reg lib[] = {
{"S_IdPlaying",lib_sIdPlaying}, {"S_IdPlaying",lib_sIdPlaying},
{"S_SoundPlaying",lib_sSoundPlaying}, {"S_SoundPlaying",lib_sSoundPlaying},
{"S_StartMusicCaption", lib_sStartMusicCaption}, {"S_StartMusicCaption", lib_sStartMusicCaption},
{"S_MusicType",lib_sMusicType},
{"S_MusicPlaying",lib_sMusicPlaying},
{"S_MusicPaused",lib_sMusicPaused},
{"S_MusicName",lib_sMusicName},
{"S_MusicExists",lib_sMusicExists},
{"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint},
{"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint},
{"S_PauseMusic",lib_sPauseMusic},
{"S_ResumeMusic", lib_sResumeMusic},
// g_game // g_game
{"G_AddGametype", lib_gAddGametype}, {"G_AddGametype", lib_gAddGametype},

View File

@ -40,6 +40,10 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
// like sending random junk lua commands to crash the server // like sending random junk lua commands to crash the server
if (!gL) goto deny; if (!gL) goto deny;
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
if (!lua_istable(gL, -1)) goto deny; if (!lua_istable(gL, -1)) goto deny;
@ -76,7 +80,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
READSTRINGN(*cp, buf, 255); READSTRINGN(*cp, buf, 255);
lua_pushstring(gL, buf); lua_pushstring(gL, buf);
} }
LUA_Call(gL, (int)argc); // argc is 1-based, so this will cover the player we passed too. LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too.
return; return;
deny: deny:
@ -98,6 +102,10 @@ void COM_Lua_f(void)
INT32 playernum = consoleplayer; INT32 playernum = consoleplayer;
I_Assert(gL != NULL); I_Assert(gL != NULL);
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -167,7 +175,7 @@ void COM_Lua_f(void)
LUA_PushUserdata(gL, &players[playernum], META_PLAYER); LUA_PushUserdata(gL, &players[playernum], META_PLAYER);
for (i = 1; i < COM_Argc(); i++) for (i = 1; i < COM_Argc(); i++)
lua_pushstring(gL, COM_Argv(i)); lua_pushstring(gL, COM_Argv(i));
LUA_Call(gL, (int)COM_Argc()); // COM_Argc is 1-based, so this will cover the player we passed too. LUA_Call(gL, (int)COM_Argc(), 0, 1); // COM_Argc is 1-based, so this will cover the player we passed too.
} }
// Wrapper for COM_AddCommand // Wrapper for COM_AddCommand
@ -277,6 +285,9 @@ static void Lua_OnChange(void)
/// \todo Network this! XD_LUAVAR /// \todo Network this! XD_LUAVAR
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
// From CV_OnChange registry field, get the function for this cvar by name. // From CV_OnChange registry field, get the function for this cvar by name.
lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange"); lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -288,7 +299,7 @@ static void Lua_OnChange(void)
lua_getfield(gL, -1, cvname); // get consvar_t* userdata. lua_getfield(gL, -1, cvname); // get consvar_t* userdata.
lua_remove(gL, -2); // pop the CV_Vars table. lua_remove(gL, -2); // pop the CV_Vars table.
LUA_Call(gL, 1); // call function(cvar) LUA_Call(gL, 1, 0, 1); // call function(cvar)
lua_pop(gL, 1); // pop CV_OnChange table lua_pop(gL, 1); // pop CV_OnChange table
} }
@ -432,6 +443,54 @@ static int lib_cvFindVar(lua_State *L)
return 1; return 1;
} }
static int CVarSetFunction
(
lua_State *L,
void (*Set)(consvar_t *, const char *),
void (*SetValue)(consvar_t *, INT32)
){
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
if (cvar->flags & CV_NOLUA)
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
switch (lua_type(L, 2))
{
case LUA_TSTRING:
(*Set)(cvar, lua_tostring(L, 2));
break;
case LUA_TNUMBER:
(*SetValue)(cvar, (INT32)lua_tonumber(L, 2));
break;
default:
return luaL_typerror(L, 1, "string or number");
}
return 0;
}
static int lib_cvSet(lua_State *L)
{
return CVarSetFunction(L, CV_Set, CV_SetValue);
}
static int lib_cvStealthSet(lua_State *L)
{
return CVarSetFunction(L, CV_StealthSet, CV_StealthSetValue);
}
static int lib_cvAddValue(lua_State *L)
{
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
if (cvar->flags & CV_NOLUA)
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2));
return 0;
}
// CONS_Printf for a single player // CONS_Printf for a single player
// Use 'print' in baselib for a global message. // Use 'print' in baselib for a global message.
static int lib_consPrintf(lua_State *L) static int lib_consPrintf(lua_State *L)
@ -472,6 +531,9 @@ static luaL_Reg lib[] = {
{"COM_BufInsertText", lib_comBufInsertText}, {"COM_BufInsertText", lib_comBufInsertText},
{"CV_RegisterVar", lib_cvRegisterVar}, {"CV_RegisterVar", lib_cvRegisterVar},
{"CV_FindVar", lib_cvFindVar}, {"CV_FindVar", lib_cvFindVar},
{"CV_Set", lib_cvSet},
{"CV_StealthSet", lib_cvStealthSet},
{"CV_AddValue", lib_cvAddValue},
{"CONS_Printf", lib_consPrintf}, {"CONS_Printf", lib_consPrintf},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -60,6 +60,7 @@ enum hook {
hook_ShouldJingleContinue, hook_ShouldJingleContinue,
hook_GameQuit, hook_GameQuit,
hook_PlayerCmd, hook_PlayerCmd,
hook_MusicChange,
hook_MAX // last hook hook_MAX // last hook
}; };
@ -111,10 +112,9 @@ void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player qui
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode
#ifdef SEENAMES
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
#endif
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink #define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
void LUAh_GameQuit(void); // Hook for game quitting void LUAh_GameQuit(boolean quitting); // Hook for game quitting
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart) boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart)
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes

View File

@ -25,7 +25,7 @@
#include "m_perfstats.h" #include "m_perfstats.h"
#include "d_netcmd.h" // for cv_perfstats #include "d_netcmd.h" // for cv_perfstats
#include "i_system.h" // I_GetTimeMicros #include "i_system.h" // I_GetPreciseTime
static UINT8 hooksAvailable[(hook_MAX/8)+1]; static UINT8 hooksAvailable[(hook_MAX/8)+1];
@ -76,6 +76,7 @@ const char *const hookNames[hook_MAX+1] = {
"ShouldJingleContinue", "ShouldJingleContinue",
"GameQuit", "GameQuit",
"PlayerCmd", "PlayerCmd",
"MusicChange",
NULL NULL
}; };
@ -264,6 +265,9 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
I_Assert(mo->type < NUMMOBJTYPES); I_Assert(mo->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type]))
return false;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -477,7 +481,7 @@ void LUAh_ThinkFrame(void)
continue; continue;
if (cv_perfstats.value == 3) if (cv_perfstats.value == 3)
time_taken = I_GetTimeMicros(); time_taken = I_GetPreciseTime();
PushHook(gL, hookp); PushHook(gL, hookp);
if (lua_pcall(gL, 0, 0, 1)) { if (lua_pcall(gL, 0, 0, 1)) {
if (!hookp->error || cv_debug & DBG_LUA) if (!hookp->error || cv_debug & DBG_LUA)
@ -488,7 +492,7 @@ void LUAh_ThinkFrame(void)
if (cv_perfstats.value == 3) if (cv_perfstats.value == 3)
{ {
lua_Debug ar; lua_Debug ar;
time_taken = I_GetTimeMicros() - time_taken; time_taken = I_GetPreciseTime() - time_taken;
// we need the function, let's just retrieve it again // we need the function, let's just retrieve it again
PushHook(gL, hookp); PushHook(gL, hookp);
lua_getinfo(gL, ">S", &ar); lua_getinfo(gL, ">S", &ar);
@ -536,6 +540,9 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
I_Assert(thing1->type < NUMMOBJTYPES); I_Assert(thing1->type < NUMMOBJTYPES);
if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing1->type]))
return 0;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -615,6 +622,9 @@ UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which)
I_Assert(thing->type < NUMMOBJTYPES); I_Assert(thing->type < NUMMOBJTYPES);
if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing->type]))
return 0;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -695,6 +705,9 @@ boolean LUAh_MobjThinker(mobj_t *mo)
I_Assert(mo->type < NUMMOBJTYPES); I_Assert(mo->type < NUMMOBJTYPES);
if (!(mobjthinkerhooks[MT_NULL] || mobjthinkerhooks[mo->type]))
return false;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -747,10 +760,13 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
hook_p hookp; hook_p hookp;
boolean hooked = false; boolean hooked = false;
if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8)))) if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8))))
return 0; return false;
I_Assert(special->type < NUMMOBJTYPES); I_Assert(special->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[special->type]))
return false;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -821,6 +837,9 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
I_Assert(target->type < NUMMOBJTYPES); I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return 0;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -908,10 +927,13 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
hook_p hookp; hook_p hookp;
boolean hooked = false; boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8)))) if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8))))
return 0; return false;
I_Assert(target->type < NUMMOBJTYPES); I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return false;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -990,10 +1012,13 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
hook_p hookp; hook_p hookp;
boolean hooked = false; boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8)))) if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8))))
return 0; return false;
I_Assert(target->type < NUMMOBJTYPES); I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return false;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -1392,6 +1417,9 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8)))) if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8))))
return false; return false;
if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type]))
return false;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -1460,6 +1488,9 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
if (!gL || !(hooksAvailable[hook_FollowMobj/8] & (1<<(hook_FollowMobj%8)))) if (!gL || !(hooksAvailable[hook_FollowMobj/8] & (1<<(hook_FollowMobj%8))))
return 0; return 0;
if (!(mobjhooks[MT_NULL] || mobjhooks[mobj->type]))
return 0;
lua_settop(gL, 0); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -1723,7 +1754,6 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
} }
// Hook for MT_NAMECHECK // Hook for MT_NAMECHECK
#ifdef SEENAMES
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend) boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
{ {
hook_p hookp; hook_p hookp;
@ -1767,7 +1797,6 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
return hasSeenPlayer; return hasSeenPlayer;
} }
#endif // SEENAMES
boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname) boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
{ {
@ -1815,7 +1844,7 @@ boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
} }
// Hook for game quitting // Hook for game quitting
void LUAh_GameQuit(void) void LUAh_GameQuit(boolean quitting)
{ {
hook_p hookp; hook_p hookp;
if (!gL || !(hooksAvailable[hook_GameQuit/8] & (1<<(hook_GameQuit%8)))) if (!gL || !(hooksAvailable[hook_GameQuit/8] & (1<<(hook_GameQuit%8))))
@ -1829,7 +1858,8 @@ void LUAh_GameQuit(void)
continue; continue;
PushHook(gL, hookp); PushHook(gL, hookp);
if (lua_pcall(gL, 0, 0, 1)) { lua_pushboolean(gL, quitting);
if (lua_pcall(gL, 1, 0, 1)) {
if (!hookp->error || cv_debug & DBG_LUA) if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1); lua_pop(gL, 1);
@ -1882,3 +1912,62 @@ boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd)
hook_cmd_running = false; hook_cmd_running = false;
return hooked; return hooked;
} }
// Hook for music changes
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8))))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_MusicChange)
{
PushHook(gL, hookp);
lua_pushstring(gL, oldname);
lua_pushstring(gL, newname);
lua_pushinteger(gL, *mflags);
lua_pushboolean(gL, *looping);
lua_pushinteger(gL, *position);
lua_pushinteger(gL, *prefadems);
lua_pushinteger(gL, *fadeinms);
if (lua_pcall(gL, 7, 6, 1)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
continue;
}
// output 1: true, false, or string musicname override
if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6))
hooked = true;
else if (lua_isstring(gL, -6))
strncpy(newname, lua_tostring(gL, -6), 7);
// output 2: mflags override
if (lua_isnumber(gL, -5))
*mflags = lua_tonumber(gL, -5);
// output 3: looping override
if (lua_isboolean(gL, -4))
*looping = lua_toboolean(gL, -4);
// output 4: position override
if (lua_isboolean(gL, -3))
*position = lua_tonumber(gL, -3);
// output 5: prefadems override
if (lua_isboolean(gL, -2))
*prefadems = lua_tonumber(gL, -2);
// output 6: fadeinms override
if (lua_isboolean(gL, -1))
*fadeinms = lua_tonumber(gL, -1);
lua_pop(gL, 7); // Pop returned values and error handler
}
lua_settop(gL, 0);
newname[6] = 0;
return hooked;
}

View File

@ -35,11 +35,6 @@ static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field static UINT8 hudAvailable; // hud hooks field
#ifdef LUA_PATCH_SAFETY
static patchinfo_t *patchinfo, *patchinfohead;
static int numluapatches;
#endif
// must match enum hud in lua_hud.h // must match enum hud in lua_hud.h
static const char *const hud_disable_options[] = { static const char *const hud_disable_options[] = {
"stagetitle", "stagetitle",
@ -292,11 +287,7 @@ static int colormap_get(lua_State *L)
static int patch_get(lua_State *L) static int patch_get(lua_State *L)
{ {
#ifdef LUA_PATCH_SAFETY
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
#else
patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH));
#endif
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
// patches are invalidated when switching renderers // patches are invalidated when switching renderers
@ -314,16 +305,16 @@ static int patch_get(lua_State *L)
lua_pushboolean(L, patch != NULL); lua_pushboolean(L, patch != NULL);
break; break;
case patch_width: case patch_width:
lua_pushinteger(L, SHORT(patch->width)); lua_pushinteger(L, patch->width);
break; break;
case patch_height: case patch_height:
lua_pushinteger(L, SHORT(patch->height)); lua_pushinteger(L, patch->height);
break; break;
case patch_leftoffset: case patch_leftoffset:
lua_pushinteger(L, SHORT(patch->leftoffset)); lua_pushinteger(L, patch->leftoffset);
break; break;
case patch_topoffset: case patch_topoffset:
lua_pushinteger(L, SHORT(patch->topoffset)); lua_pushinteger(L, patch->topoffset);
break; break;
} }
return 1; return 1;
@ -403,59 +394,8 @@ static int libd_patchExists(lua_State *L)
static int libd_cachePatch(lua_State *L) static int libd_cachePatch(lua_State *L)
{ {
#ifdef LUA_PATCH_SAFETY
int i;
lumpnum_t lumpnum;
patchinfo_t *luapat;
patch_t *realpatch;
HUDONLY
luapat = patchinfohead;
lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1));
if (lumpnum == LUMPERROR)
lumpnum = W_GetNumForLongName("MISSING");
for (i = 0; i < numluapatches; i++)
{
// check if already cached
if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum))
{
LUA_PushUserdata(L, luapat, META_PATCH);
return 1;
}
luapat = luapat->next;
if (!luapat)
break;
}
if (numluapatches > 0)
{
patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfo = patchinfo->next;
}
else
{
patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfohead = patchinfo;
}
realpatch = W_CachePatchNum(lumpnum, PU_PATCH);
patchinfo->width = realpatch->width;
patchinfo->height = realpatch->height;
patchinfo->leftoffset = realpatch->leftoffset;
patchinfo->topoffset = realpatch->topoffset;
patchinfo->wadnum = WADFILENUM(lumpnum);
patchinfo->lumpnum = LUMPNUM(lumpnum);
LUA_PushUserdata(L, patchinfo, META_PATCH);
numluapatches++;
#else
HUDONLY HUDONLY
LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
#endif
return 1; return 1;
} }
@ -518,9 +458,8 @@ static int libd_getSpritePatch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle); INT32 rot = R_GetRollAngle(rollangle);
if (rot) { if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle))) patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &spriteinfo[i], rot);
R_CacheRotSprite(i, frame, NULL, sprframe, angle, sprframe->flip & (1<<angle)); LUA_PushUserdata(L, rotsprite, META_PATCH);
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
lua_pushboolean(L, false); lua_pushboolean(L, false);
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 3; return 3;
@ -529,7 +468,7 @@ static int libd_getSpritePatch(lua_State *L)
#endif #endif
// push both the patch and it's "flip" value // push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0); lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2; return 2;
} }
@ -631,9 +570,8 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle); INT32 rot = R_GetRollAngle(rollangle);
if (rot) { if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle))) patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &skins[i].sprinfo[j], rot);
R_CacheRotSprite(SPR_PLAY, frame, &skins[i].sprinfo[j], sprframe, angle, sprframe->flip & (1<<angle)); LUA_PushUserdata(L, rotsprite, META_PATCH);
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
lua_pushboolean(L, false); lua_pushboolean(L, false);
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 3; return 3;
@ -642,7 +580,7 @@ static int libd_getSprite2Patch(lua_State *L)
#endif #endif
// push both the patch and it's "flip" value // push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_SPRITE), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0); lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2; return 2;
} }
@ -651,22 +589,14 @@ static int libd_draw(lua_State *L)
{ {
INT32 x, y, flags; INT32 x, y, flags;
patch_t *patch; patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL; const UINT8 *colormap = NULL;
HUDONLY HUDONLY
x = luaL_checkinteger(L, 1); x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2); y = luaL_checkinteger(L, 2);
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 3, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH)); patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH));
if (!patch) if (!patch)
return LUA_ErrInvalid(L, "patch_t"); return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 4, 0); flags = luaL_optinteger(L, 4, 0);
if (!lua_isnoneornil(L, 5)) if (!lua_isnoneornil(L, 5))
colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP)); colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
@ -682,9 +612,6 @@ static int libd_drawScaled(lua_State *L)
fixed_t x, y, scale; fixed_t x, y, scale;
INT32 flags; INT32 flags;
patch_t *patch; patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL; const UINT8 *colormap = NULL;
HUDONLY HUDONLY
@ -693,14 +620,9 @@ static int libd_drawScaled(lua_State *L)
scale = luaL_checkinteger(L, 3); scale = luaL_checkinteger(L, 3);
if (scale < 0) if (scale < 0)
return luaL_error(L, "negative scale"); return luaL_error(L, "negative scale");
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH));
if (!patch) if (!patch)
return LUA_ErrInvalid(L, "patch_t"); return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 5, 0); flags = luaL_optinteger(L, 5, 0);
if (!lua_isnoneornil(L, 6)) if (!lua_isnoneornil(L, 6))
colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP)); colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP));
@ -974,8 +896,10 @@ static int libd_getColormap(lua_State *L)
else if (lua_type(L, 1) == LUA_TNUMBER) // skin number else if (lua_type(L, 1) == LUA_TNUMBER) // skin number
{ {
skinnum = (INT32)luaL_checkinteger(L, 1); skinnum = (INT32)luaL_checkinteger(L, 1);
if (skinnum < TC_BLINK || skinnum >= MAXSKINS) if (skinnum >= MAXSKINS)
return luaL_error(L, "skin number %d is out of range (%d - %d)", skinnum, TC_BLINK, MAXSKINS-1); return luaL_error(L, "skin number %d is out of range (>%d)", skinnum, MAXSKINS-1);
else if (skinnum < 0 && skinnum > TC_DEFAULT)
return luaL_error(L, "translation colormap index is out of range");
} }
else // skin name else // skin name
{ {
@ -1261,10 +1185,6 @@ int LUA_HudLib(lua_State *L)
{ {
memset(hud_enabled, 0xff, (hud_MAX/8)+1); memset(hud_enabled, 0xff, (hud_MAX/8)+1);
#ifdef LUA_PATCH_SAFETY
numluapatches = 0;
#endif
lua_newtable(L); // HUD registry table lua_newtable(L); // HUD registry table
lua_newtable(L); lua_newtable(L);
luaL_register(L, NULL, lib_draw); luaL_register(L, NULL, lib_draw);
@ -1343,7 +1263,9 @@ void LUAh_GameHUD(player_t *stplayr)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1365,9 +1287,9 @@ void LUAh_GameHUD(player_t *stplayr)
lua_pushvalue(gL, -5); // graphics library (HUD[1]) lua_pushvalue(gL, -5); // graphics library (HUD[1])
lua_pushvalue(gL, -5); // stplayr lua_pushvalue(gL, -5); // stplayr
lua_pushvalue(gL, -5); // camera lua_pushvalue(gL, -5); // camera
LUA_Call(gL, 3); LUA_Call(gL, 3, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }
@ -1377,7 +1299,9 @@ void LUAh_ScoresHUD(void)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1390,9 +1314,9 @@ void LUAh_ScoresHUD(void)
lua_pushnil(gL); lua_pushnil(gL);
while (lua_next(gL, -3) != 0) { while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1]) lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1); LUA_Call(gL, 1, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }
@ -1402,7 +1326,9 @@ void LUAh_TitleHUD(void)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1415,9 +1341,9 @@ void LUAh_TitleHUD(void)
lua_pushnil(gL); lua_pushnil(gL);
while (lua_next(gL, -3) != 0) { while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1]) lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1); LUA_Call(gL, 1, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }
@ -1427,7 +1353,9 @@ void LUAh_TitleCardHUD(player_t *stplayr)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1448,10 +1376,10 @@ void LUAh_TitleCardHUD(player_t *stplayr)
lua_pushvalue(gL, -6); // stplayr lua_pushvalue(gL, -6); // stplayr
lua_pushvalue(gL, -6); // lt_ticker lua_pushvalue(gL, -6); // lt_ticker
lua_pushvalue(gL, -6); // lt_endtime lua_pushvalue(gL, -6); // lt_endtime
LUA_Call(gL, 4); LUA_Call(gL, 4, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }
@ -1461,7 +1389,9 @@ void LUAh_IntermissionHUD(void)
return; return;
hud_running = true; hud_running = true;
lua_pop(gL, -1); lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -1474,8 +1404,8 @@ void LUAh_IntermissionHUD(void)
lua_pushnil(gL); lua_pushnil(gL);
while (lua_next(gL, -3) != 0) { while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1]) lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1); LUA_Call(gL, 1, 0, 1);
} }
lua_pop(gL, -1); lua_settop(gL, 0);
hud_running = false; hud_running = false;
} }

View File

@ -14,9 +14,12 @@
#include "fastcmp.h" #include "fastcmp.h"
#include "info.h" #include "info.h"
#include "dehacked.h" #include "dehacked.h"
#include "deh_tables.h"
#include "deh_lua.h"
#include "p_mobj.h" #include "p_mobj.h"
#include "p_local.h" #include "p_local.h"
#include "z_zone.h" #include "z_zone.h"
#include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "r_things.h" #include "r_things.h"
#include "r_draw.h" // R_GetColorByName #include "r_draw.h" // R_GetColorByName
@ -30,7 +33,7 @@
extern CV_PossibleValue_t Color_cons_t[]; extern CV_PossibleValue_t Color_cons_t[];
extern UINT8 skincolor_modified[]; extern UINT8 skincolor_modified[];
boolean LUA_CallAction(const char *action, mobj_t *actor); boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor);
state_t *astate; state_t *astate;
enum sfxinfo_read { enum sfxinfo_read {
@ -63,6 +66,8 @@ const char *const sfxinfo_wopt[] = {
"caption", "caption",
NULL}; NULL};
boolean actionsoverridden[NUMACTIONS] = {false};
// //
// Sprite Names // Sprite Names
// //
@ -375,17 +380,13 @@ static int lib_setSpriteInfo(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!"); return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!");
if (hook_cmd_running) if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!"); return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!");
lua_remove(L, 1); lua_remove(L, 1);
{ {
UINT32 i = luaL_checkinteger(L, 1); UINT32 i = luaL_checkinteger(L, 1);
if (i == 0 || i >= NUMSPRITES) if (i == 0 || i >= NUMSPRITES)
return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1); return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1);
#ifdef ROTSPRITE
if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[i]);
#endif
info = &spriteinfo[i]; // get the spriteinfo to assign to. info = &spriteinfo[i]; // get the spriteinfo to assign to.
} }
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
@ -469,11 +470,6 @@ static int spriteinfo_set(lua_State *L)
lua_remove(L, 1); // remove field lua_remove(L, 1); // remove field
lua_settop(L, 1); // leave only one value lua_settop(L, 1); // leave only one value
#ifdef ROTSPRITE
if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]);
#endif
if (fastcmp(field, "pivot")) if (fastcmp(field, "pivot"))
{ {
// pivot[] is a table // pivot[] is a table
@ -630,6 +626,9 @@ static void A_Lua(mobj_t *actor)
boolean found = false; boolean found = false;
I_Assert(actor != NULL); I_Assert(actor != NULL);
lua_settop(gL, 0); // Just in case...
lua_pushcfunction(gL, LUA_GetErrorMessage);
// get the action for this state // get the action for this state
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_STATEACTION); lua_getfield(gL, LUA_REGISTRYINDEX, LREG_STATEACTION);
I_Assert(lua_istable(gL, -1)); I_Assert(lua_istable(gL, -1));
@ -658,7 +657,7 @@ static void A_Lua(mobj_t *actor)
LUA_PushUserdata(gL, actor, META_MOBJ); LUA_PushUserdata(gL, actor, META_MOBJ);
lua_pushinteger(gL, var1); lua_pushinteger(gL, var1);
lua_pushinteger(gL, var2); lua_pushinteger(gL, var2);
LUA_Call(gL, 3); LUA_Call(gL, 3, 0, 1);
if (found) if (found)
{ {
@ -813,36 +812,33 @@ boolean LUA_SetLuaAction(void *stv, const char *action)
return true; // action successfully set. return true; // action successfully set.
} }
boolean LUA_CallAction(const char *csaction, mobj_t *actor) boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor)
{ {
I_Assert(csaction != NULL);
I_Assert(actor != NULL); I_Assert(actor != NULL);
if (!gL) // Lua isn't loaded, if (!actionsoverridden[actionnum]) // The action is not overriden,
return false; // action not called. return false; // action not called.
if (superstack && fasticmp(csaction, superactions[superstack-1])) // the action is calling itself, if (superstack && fasticmp(actionpointers[actionnum].name, superactions[superstack-1])) // the action is calling itself,
return false; // let it call the hardcoded function instead. return false; // let it call the hardcoded function instead.
lua_pushcfunction(gL, LUA_GetErrorMessage);
// grab function by uppercase name. // grab function by uppercase name.
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS); lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS);
{ lua_getfield(gL, -1, actionpointers[actionnum].name);
char *action = Z_StrDup(csaction);
strupr(action);
lua_getfield(gL, -1, action);
Z_Free(action);
}
lua_remove(gL, -2); // pop LREG_ACTIONS lua_remove(gL, -2); // pop LREG_ACTIONS
if (lua_isnil(gL, -1)) // no match if (lua_isnil(gL, -1)) // no match
{ {
lua_pop(gL, 1); // pop nil lua_pop(gL, 2); // pop nil and error handler
return false; // action not called. return false; // action not called.
} }
if (superstack == MAXRECURSION) if (superstack == MAXRECURSION)
{ {
CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n"); CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n");
lua_pop(gL, 2); // pop function and error handler
return true; return true;
} }
@ -853,10 +849,11 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor)
lua_pushinteger(gL, var1); lua_pushinteger(gL, var1);
lua_pushinteger(gL, var2); lua_pushinteger(gL, var2);
superactions[superstack] = csaction; superactions[superstack] = actionpointers[actionnum].name;
++superstack; ++superstack;
LUA_Call(gL, 3); LUA_Call(gL, 3, 0, -(2 + 3));
lua_pop(gL, -1); // Error handler
--superstack; --superstack;
superactions[superstack] = NULL; superactions[superstack] = NULL;

View File

@ -16,6 +16,7 @@ extern lua_State *gL;
#define LREG_EXTVARS "LUA_VARS" #define LREG_EXTVARS "LUA_VARS"
#define LREG_STATEACTION "STATE_ACTION" #define LREG_STATEACTION "STATE_ACTION"
#define LREG_ACTIONS "MOBJ_ACTION" #define LREG_ACTIONS "MOBJ_ACTION"
#define LREG_METATABLES "METATABLES"
#define META_STATE "STATE_T*" #define META_STATE "STATE_T*"
#define META_MOBJINFO "MOBJINFO_T*" #define META_MOBJINFO "MOBJINFO_T*"
@ -34,6 +35,8 @@ extern lua_State *gL;
#define META_SKIN "SKIN_T*" #define META_SKIN "SKIN_T*"
#define META_POWERS "PLAYER_T*POWERS" #define META_POWERS "PLAYER_T*POWERS"
#define META_SOUNDSID "SKIN_T*SOUNDSID" #define META_SOUNDSID "SKIN_T*SOUNDSID"
#define META_SKINSPRITES "SKIN_T*SPRITES"
#define META_SKINSPRITESLIST "SKIN_T*SPRITES[]"
#define META_VERTEX "VERTEX_T*" #define META_VERTEX "VERTEX_T*"
#define META_LINE "LINE_T*" #define META_LINE "LINE_T*"

View File

@ -99,8 +99,6 @@ enum line_e {
line_slopetype, line_slopetype,
line_frontsector, line_frontsector,
line_backsector, line_backsector,
line_firsttag,
line_nexttag,
line_polyobj, line_polyobj,
line_text, line_text,
line_callcount line_callcount
@ -125,8 +123,6 @@ static const char *const line_opt[] = {
"slopetype", "slopetype",
"frontsector", "frontsector",
"backsector", "backsector",
"firsttag",
"nexttag",
"polyobj", "polyobj",
"text", "text",
"callcount", "callcount",
@ -489,7 +485,7 @@ static int sectorlines_get(lua_State *L)
// get the "linecount" by shifting our retrieved memory address of "lines" to where "linecount" is in the sector_t, then dereferencing the result // 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 // 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 // this only works if seclines is actually a pointer to a sector's lines member in memory, oh boy
numoflines = (size_t)(*(size_t *)(((size_t)seclines) - (offsetof(sector_t, lines) - offsetof(sector_t, linecount)))); numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount);
/* OLD HACK /* OLD HACK
// check first linedef to figure which of its sectors owns this sector->lines pointer // check first linedef to figure which of its sectors owns this sector->lines pointer
@ -523,7 +519,7 @@ static int sectorlines_num(lua_State *L)
return luaL_error(L, "accessed sector_t.lines doesn't exist anymore."); return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
// see comments in the _get function above // see comments in the _get function above
numoflines = (size_t)(*(size_t *)(((size_t)seclines) - (offsetof(sector_t, lines) - offsetof(sector_t, linecount)))); numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount);
lua_pushinteger(L, numoflines); lua_pushinteger(L, numoflines);
return 1; return 1;
} }
@ -583,7 +579,7 @@ static int sector_get(lua_State *L)
lua_pushinteger(L, sector->special); lua_pushinteger(L, sector->special);
return 1; return 1;
case sector_tag: case sector_tag:
lua_pushinteger(L, sector->tag); lua_pushinteger(L, Tag_FGet(&sector->tags));
return 1; return 1;
case sector_thinglist: // thinglist case sector_thinglist: // thinglist
lua_pushcfunction(L, lib_iterateSectorThinglist); lua_pushcfunction(L, lib_iterateSectorThinglist);
@ -684,7 +680,7 @@ static int sector_set(lua_State *L)
sector->special = (INT16)luaL_checkinteger(L, 3); sector->special = (INT16)luaL_checkinteger(L, 3);
break; break;
case sector_tag: case sector_tag:
P_ChangeSectorTag((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3)); Tag_SectorFSet((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
break; break;
} }
return 0; return 0;
@ -823,7 +819,7 @@ static int line_get(lua_State *L)
lua_pushinteger(L, line->special); lua_pushinteger(L, line->special);
return 1; return 1;
case line_tag: case line_tag:
lua_pushinteger(L, line->tag); lua_pushinteger(L, Tag_FGet(&line->tags));
return 1; return 1;
case line_args: case line_args:
LUA_PushUserdata(L, line->args, META_LINEARGS); LUA_PushUserdata(L, line->args, META_LINEARGS);
@ -871,12 +867,6 @@ static int line_get(lua_State *L)
case line_backsector: case line_backsector:
LUA_PushUserdata(L, line->backsector, META_SECTOR); LUA_PushUserdata(L, line->backsector, META_SECTOR);
return 1; return 1;
case line_firsttag:
lua_pushinteger(L, line->firsttag);
return 1;
case line_nexttag:
lua_pushinteger(L, line->nexttag);
return 1;
case line_polyobj: case line_polyobj:
LUA_PushUserdata(L, line->polyobj, META_POLYOBJ); LUA_PushUserdata(L, line->polyobj, META_POLYOBJ);
return 1; return 1;
@ -2199,6 +2189,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->levelflags); lua_pushinteger(L, header->levelflags);
else if (fastcmp(field,"menuflags")) else if (fastcmp(field,"menuflags"))
lua_pushinteger(L, header->menuflags); lua_pushinteger(L, header->menuflags);
else if (fastcmp(field,"selectheading"))
lua_pushstring(L, header->selectheading);
else if (fastcmp(field,"startrings")) else if (fastcmp(field,"startrings"))
lua_pushinteger(L, header->startrings); lua_pushinteger(L, header->startrings);
else if (fastcmp(field, "sstimer")) else if (fastcmp(field, "sstimer"))

View File

@ -192,18 +192,30 @@ static luaL_Reg lib[] = {
{"cos", lib_finecosine}, {"cos", lib_finecosine},
{"tan", lib_finetangent}, {"tan", lib_finetangent},
{"FixedAngle", lib_fixedangle}, {"FixedAngle", lib_fixedangle},
{"fixangle" , lib_fixedangle},
{"AngleFixed", lib_anglefixed}, {"AngleFixed", lib_anglefixed},
{"anglefix" , lib_anglefixed},
{"InvAngle", lib_invangle}, {"InvAngle", lib_invangle},
{"FixedMul", lib_fixedmul}, {"FixedMul", lib_fixedmul},
{"fixmul" , lib_fixedmul},
{"FixedInt", lib_fixedint}, {"FixedInt", lib_fixedint},
{"fixint" , lib_fixedint},
{"FixedDiv", lib_fixeddiv}, {"FixedDiv", lib_fixeddiv},
{"fixdiv" , lib_fixeddiv},
{"FixedRem", lib_fixedrem}, {"FixedRem", lib_fixedrem},
{"fixrem" , lib_fixedrem},
{"FixedSqrt", lib_fixedsqrt}, {"FixedSqrt", lib_fixedsqrt},
{"fixsqrt" , lib_fixedsqrt},
{"FixedHypot", lib_fixedhypot}, {"FixedHypot", lib_fixedhypot},
{"fixhypot" , lib_fixedhypot},
{"FixedFloor", lib_fixedfloor}, {"FixedFloor", lib_fixedfloor},
{"fixfloor" , lib_fixedfloor},
{"FixedTrunc", lib_fixedtrunc}, {"FixedTrunc", lib_fixedtrunc},
{"fixtrunc" , lib_fixedtrunc},
{"FixedCeil", lib_fixedceil}, {"FixedCeil", lib_fixedceil},
{"fixceil" , lib_fixedceil},
{"FixedRound", lib_fixedround}, {"FixedRound", lib_fixedround},
{"fixround" , lib_fixedround},
{"GetSecSpecial", lib_getsecspecial}, {"GetSecSpecial", lib_getsecspecial},
{"All7Emeralds", lib_all7emeralds}, {"All7Emeralds", lib_all7emeralds},
{"ColorOpposite", lib_coloropposite}, {"ColorOpposite", lib_coloropposite},

View File

@ -39,6 +39,11 @@ enum mobj_e {
mobj_frame, mobj_frame,
mobj_sprite2, mobj_sprite2,
mobj_anim_duration, mobj_anim_duration,
mobj_spritexscale,
mobj_spriteyscale,
mobj_spritexoffset,
mobj_spriteyoffset,
mobj_floorspriteslope,
mobj_touching_sectorlist, mobj_touching_sectorlist,
mobj_subsector, mobj_subsector,
mobj_floorz, mobj_floorz,
@ -56,8 +61,10 @@ enum mobj_e {
mobj_flags, mobj_flags,
mobj_flags2, mobj_flags2,
mobj_eflags, mobj_eflags,
mobj_renderflags,
mobj_skin, mobj_skin,
mobj_color, mobj_color,
mobj_blendmode,
mobj_bnext, mobj_bnext,
mobj_bprev, mobj_bprev,
mobj_hnext, mobj_hnext,
@ -108,6 +115,11 @@ static const char *const mobj_opt[] = {
"frame", "frame",
"sprite2", "sprite2",
"anim_duration", "anim_duration",
"spritexscale",
"spriteyscale",
"spritexoffset",
"spriteyoffset",
"floorspriteslope",
"touching_sectorlist", "touching_sectorlist",
"subsector", "subsector",
"floorz", "floorz",
@ -125,8 +137,10 @@ static const char *const mobj_opt[] = {
"flags", "flags",
"flags2", "flags2",
"eflags", "eflags",
"renderflags",
"skin", "skin",
"color", "color",
"blendmode",
"bnext", "bnext",
"bprev", "bprev",
"hnext", "hnext",
@ -227,6 +241,21 @@ static int mobj_get(lua_State *L)
case mobj_anim_duration: case mobj_anim_duration:
lua_pushinteger(L, mo->anim_duration); lua_pushinteger(L, mo->anim_duration);
break; break;
case mobj_spritexscale:
lua_pushfixed(L, mo->spritexscale);
break;
case mobj_spriteyscale:
lua_pushfixed(L, mo->spriteyscale);
break;
case mobj_spritexoffset:
lua_pushfixed(L, mo->spritexoffset);
break;
case mobj_spriteyoffset:
lua_pushfixed(L, mo->spriteyoffset);
break;
case mobj_floorspriteslope:
LUA_PushUserdata(L, mo->floorspriteslope, META_SLOPE);
break;
case mobj_touching_sectorlist: case mobj_touching_sectorlist:
return UNIMPLEMENTED; return UNIMPLEMENTED;
case mobj_subsector: case mobj_subsector:
@ -277,6 +306,9 @@ static int mobj_get(lua_State *L)
case mobj_eflags: case mobj_eflags:
lua_pushinteger(L, mo->eflags); lua_pushinteger(L, mo->eflags);
break; break;
case mobj_renderflags:
lua_pushinteger(L, mo->renderflags);
break;
case mobj_skin: // skin name or nil, not struct case mobj_skin: // skin name or nil, not struct
if (!mo->skin) if (!mo->skin)
return 0; return 0;
@ -285,6 +317,9 @@ static int mobj_get(lua_State *L)
case mobj_color: case mobj_color:
lua_pushinteger(L, mo->color); lua_pushinteger(L, mo->color);
break; break;
case mobj_blendmode:
lua_pushinteger(L, mo->blendmode);
break;
case mobj_bnext: case mobj_bnext:
LUA_PushUserdata(L, mo->bnext, META_MOBJ); LUA_PushUserdata(L, mo->bnext, META_MOBJ);
break; break;
@ -492,6 +527,20 @@ static int mobj_set(lua_State *L)
case mobj_anim_duration: case mobj_anim_duration:
mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);
break; break;
case mobj_spritexscale:
mo->spritexscale = luaL_checkfixed(L, 3);
break;
case mobj_spriteyscale:
mo->spriteyscale = luaL_checkfixed(L, 3);
break;
case mobj_spritexoffset:
mo->spritexoffset = luaL_checkfixed(L, 3);
break;
case mobj_spriteyoffset:
mo->spriteyoffset = luaL_checkfixed(L, 3);
break;
case mobj_floorspriteslope:
return NOSET;
case mobj_touching_sectorlist: case mobj_touching_sectorlist:
return UNIMPLEMENTED; return UNIMPLEMENTED;
case mobj_subsector: case mobj_subsector:
@ -580,6 +629,9 @@ static int mobj_set(lua_State *L)
case mobj_eflags: case mobj_eflags:
mo->eflags = (UINT32)luaL_checkinteger(L, 3); mo->eflags = (UINT32)luaL_checkinteger(L, 3);
break; break;
case mobj_renderflags:
mo->renderflags = (UINT32)luaL_checkinteger(L, 3);
break;
case mobj_skin: // set skin by name case mobj_skin: // set skin by name
{ {
INT32 i; INT32 i;
@ -603,6 +655,9 @@ static int mobj_set(lua_State *L)
mo->color = newcolor; mo->color = newcolor;
break; break;
} }
case mobj_blendmode:
mo->blendmode = (INT32)luaL_checkinteger(L, 3);
break;
case mobj_bnext: case mobj_bnext:
return NOSETPOS; return NOSETPOS;
case mobj_bprev: case mobj_bprev:
@ -848,7 +903,7 @@ static int mapthing_get(lua_State *L)
else if(fastcmp(field,"extrainfo")) else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo; number = mt->extrainfo;
else if(fastcmp(field,"tag")) else if(fastcmp(field,"tag"))
number = mt->tag; number = Tag_FGet(&mt->tags);
else if(fastcmp(field,"args")) else if(fastcmp(field,"args"))
{ {
LUA_PushUserdata(L, mt->args, META_THINGARGS); LUA_PushUserdata(L, mt->args, META_THINGARGS);
@ -910,7 +965,7 @@ static int mapthing_set(lua_State *L)
mt->extrainfo = (UINT8)extrainfo; mt->extrainfo = (UINT8)extrainfo;
} }
else if (fastcmp(field,"tag")) else if (fastcmp(field,"tag"))
mt->tag = (INT16)luaL_checkinteger(L, 3); Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3));
else if(fastcmp(field,"mobj")) else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else else

View File

@ -158,6 +158,10 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->flashpal); lua_pushinteger(L, plr->flashpal);
else if (fastcmp(field,"skincolor")) else if (fastcmp(field,"skincolor"))
lua_pushinteger(L, plr->skincolor); lua_pushinteger(L, plr->skincolor);
else if (fastcmp(field,"skin"))
lua_pushinteger(L, plr->skin);
else if (fastcmp(field,"availabilities"))
lua_pushinteger(L, plr->availabilities);
else if (fastcmp(field,"score")) else if (fastcmp(field,"score"))
lua_pushinteger(L, plr->score); lua_pushinteger(L, plr->score);
else if (fastcmp(field,"dashspeed")) else if (fastcmp(field,"dashspeed"))
@ -469,6 +473,10 @@ static int player_set(lua_State *L)
return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1); return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1);
plr->skincolor = newcolor; plr->skincolor = newcolor;
} }
else if (fastcmp(field,"skin"))
return NOSET;
else if (fastcmp(field,"availabilities"))
return NOSET;
else if (fastcmp(field,"score")) else if (fastcmp(field,"score"))
plr->score = (UINT32)luaL_checkinteger(L, 3); plr->score = (UINT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"dashspeed")) else if (fastcmp(field,"dashspeed"))

View File

@ -99,7 +99,7 @@ static int polyobjvertices_get(lua_State *L)
} }
} }
numofverts = (size_t)(*(size_t *)(((size_t)polyverts) - (offsetof(polyobj_t, vertices) - offsetof(polyobj_t, numVertices)))); numofverts = *(size_t *)FIELDFROM (polyobj_t, polyverts, vertices,/* -> */numVertices);
if (!numofverts) if (!numofverts)
return luaL_error(L, "no vertices found!"); return luaL_error(L, "no vertices found!");
@ -120,7 +120,7 @@ static int polyobjvertices_num(lua_State *L)
if (!polyverts || !(*polyverts)) if (!polyverts || !(*polyverts))
return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore."); return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore.");
numofverts = (size_t)(*(size_t *)(((size_t)polyverts) - (offsetof(polyobj_t, vertices) - offsetof(polyobj_t, numVertices)))); numofverts = *(size_t *)FIELDFROM (polyobj_t, polyverts, vertices,/* -> */numVertices);
lua_pushinteger(L, numofverts); lua_pushinteger(L, numofverts);
return 1; return 1;
} }
@ -156,7 +156,7 @@ static int polyobjlines_get(lua_State *L)
} }
} }
numoflines = (size_t)(*(size_t *)(((size_t)polylines) - (offsetof(polyobj_t, lines) - offsetof(polyobj_t, numLines)))); numoflines = *(size_t *)FIELDFROM (polyobj_t, polylines, lines,/* -> */numLines);
if (!numoflines) if (!numoflines)
return luaL_error(L, "no lines found!"); return luaL_error(L, "no lines found!");
@ -177,7 +177,7 @@ static int polyobjlines_num(lua_State *L)
if (!polylines || !(*polylines)) if (!polylines || !(*polylines))
return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore."); return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore.");
numoflines = (size_t)(*(size_t *)(((size_t)polylines) - (offsetof(polyobj_t, lines) - offsetof(polyobj_t, numLines)))); numoflines = *(size_t *)FIELDFROM (polyobj_t, polylines, lines,/* -> */numLines);
lua_pushinteger(L, numoflines); lua_pushinteger(L, numoflines);
return 1; return 1;
} }

View File

@ -13,6 +13,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "fastcmp.h" #include "fastcmp.h"
#include "dehacked.h" #include "dehacked.h"
#include "deh_lua.h"
#include "z_zone.h" #include "z_zone.h"
#include "w_wad.h" #include "w_wad.h"
#include "p_setup.h" #include "p_setup.h"
@ -34,6 +35,7 @@
#include "lua_hook.h" #include "lua_hook.h"
#include "doomstat.h" #include "doomstat.h"
#include "g_state.h"
lua_State *gL = NULL; lua_State *gL = NULL;
@ -132,6 +134,19 @@ int LUA_GetErrorMessage(lua_State *L)
return 1; return 1;
} }
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex)
{
int err = lua_pcall(L, nargs, nresults, errorhandlerindex);
if (err)
{
CONS_Alert(CONS_WARNING, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
return err;
}
// Moved here from lib_getenum. // Moved here from lib_getenum.
int LUA_PushGlobals(lua_State *L, const char *word) int LUA_PushGlobals(lua_State *L, const char *word)
{ {
@ -361,6 +376,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word, "token")) { } else if (fastcmp(word, "token")) {
lua_pushinteger(L, token); lua_pushinteger(L, token);
return 1; return 1;
} else if (fastcmp(word, "gamestate")) {
lua_pushinteger(L, gamestate);
return 1;
} }
return 0; return 0;
} }
@ -372,6 +390,44 @@ int LUA_CheckGlobals(lua_State *L, const char *word)
redscore = (UINT32)luaL_checkinteger(L, 2); redscore = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "bluescore")) else if (fastcmp(word, "bluescore"))
bluescore = (UINT32)luaL_checkinteger(L, 2); bluescore = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_redteam"))
skincolor_redteam = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_blueteam"))
skincolor_blueteam = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_redring"))
skincolor_redring = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "skincolor_bluering"))
skincolor_bluering = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "emeralds"))
emeralds = (UINT16)luaL_checkinteger(L, 2);
else if (fastcmp(word, "token"))
token = (UINT32)luaL_checkinteger(L, 2);
else if (fastcmp(word, "gravity"))
gravity = (fixed_t)luaL_checkinteger(L, 2);
else if (fastcmp(word, "stoppedclock"))
stoppedclock = luaL_checkboolean(L, 2);
else if (fastcmp(word, "displayplayer"))
{
player_t *player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (player)
displayplayer = player - players;
}
else if (fastcmp(word, "mapmusname"))
{
size_t strlength;
const char *str = luaL_checklstring(L, 2, &strlength);
if (strlength > 6)
return luaL_error(L, "string length out of range (maximum 6 characters)");
if (strlen(str) < strlength)
return luaL_error(L, "string must not contain embedded zeros!");
strncpy(mapmusname, str, strlength);
}
else if (fastcmp(word, "mapmusflags"))
mapmusflags = (UINT16)luaL_checkinteger(L, 2);
else else
return 0; return 0;
@ -384,6 +440,7 @@ static int setglobals(lua_State *L)
{ {
const char *csname; const char *csname;
char *name; char *name;
enum actionnum actionnum;
lua_remove(L, 1); // we're not gonna be using _G lua_remove(L, 1); // we're not gonna be using _G
csname = lua_tostring(L, 1); csname = lua_tostring(L, 1);
@ -402,6 +459,10 @@ static int setglobals(lua_State *L)
lua_rawset(L, -3); // rawset doesn't trigger this metatable again. lua_rawset(L, -3); // rawset doesn't trigger this metatable again.
// otherwise we would've used setfield, obviously. // otherwise we would've used setfield, obviously.
actionnum = LUA_GetActionNumByName(name);
if (actionnum < NUMACTIONS)
actionsoverridden[actionnum] = true;
Z_Free(name); Z_Free(name);
return 0; return 0;
} }
@ -433,12 +494,16 @@ static void LUA_ClearState(void)
// open base libraries // open base libraries
luaL_openlibs(L); luaL_openlibs(L);
lua_pop(L, -1); lua_settop(L, 0);
// make LREG_VALID table for all pushed userdata cache. // make LREG_VALID table for all pushed userdata cache.
lua_newtable(L); lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, LREG_VALID); lua_setfield(L, LUA_REGISTRYINDEX, LREG_VALID);
// make LREG_METATABLES table for all registered metatables
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, LREG_METATABLES);
// open srb2 libraries // open srb2 libraries
for(i = 0; liblist[i]; i++) { for(i = 0; liblist[i]; i++) {
lua_pushcfunction(L, liblist[i]); lua_pushcfunction(L, liblist[i]);
@ -632,7 +697,7 @@ fixed_t LUA_EvalMath(const char *word)
*b = '\0'; *b = '\0';
// eval string. // eval string.
lua_pop(L, -1); lua_settop(L, 0);
if (luaL_dostring(L, buf)) if (luaL_dostring(L, buf))
{ {
p = lua_tostring(L, -1); p = lua_tostring(L, -1);
@ -976,8 +1041,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
lua_pop(gL, 1); lua_pop(gL, 1);
} }
if (!found) if (!found)
{
t++; t++;
if (t == 0)
{
CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
WRITEUINT8(save_p, ARCH_NULL);
return 0;
}
}
WRITEUINT8(save_p, ARCH_TABLE); WRITEUINT8(save_p, ARCH_TABLE);
WRITEUINT16(save_p, t); WRITEUINT16(save_p, t);
@ -1290,8 +1364,22 @@ static void ArchiveTables(void)
lua_pop(gL, 1); lua_pop(gL, 1);
} }
lua_pop(gL, 1);
WRITEUINT8(save_p, ARCH_TEND); WRITEUINT8(save_p, ARCH_TEND);
// Write metatable ID
if (lua_getmetatable(gL, -1))
{
// registry.metatables[metatable]
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
lua_pushvalue(gL, -2);
lua_gettable(gL, -2);
WRITEUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
lua_pop(gL, 3);
}
else
WRITEUINT16(save_p, 0);
lua_pop(gL, 1);
} }
} }
@ -1462,6 +1550,7 @@ static void UnArchiveTables(void)
{ {
int TABLESINDEX; int TABLESINDEX;
UINT16 i, n; UINT16 i, n;
UINT16 metatableid;
if (!gL) if (!gL)
return; return;
@ -1486,6 +1575,19 @@ static void UnArchiveTables(void)
else else
lua_rawset(gL, -3); lua_rawset(gL, -3);
} }
metatableid = READUINT16(save_p);
if (metatableid)
{
// setmetatable(table, registry.metatables[metatableid])
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
lua_rawgeti(gL, -1, metatableid);
if (lua_isnil(gL, -1))
I_Error("Unknown metatable ID %d\n", metatableid);
lua_setmetatable(gL, -3);
lua_pop(gL, 1);
}
lua_pop(gL, 1); lua_pop(gL, 1);
} }
} }

View File

@ -40,6 +40,7 @@ void LUA_ClearExtVars(void);
extern INT32 lua_lumploading; // is LUA_LoadLump being called? extern INT32 lua_lumploading; // is LUA_LoadLump being called?
int LUA_GetErrorMessage(lua_State *L); int LUA_GetErrorMessage(lua_State *L);
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex);
void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults); void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults);
#ifdef LUA_ALLOW_BYTECODE #ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename); void LUA_DumpFile(const char *filename);
@ -65,14 +66,6 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc);
// Console wrapper // Console wrapper
void COM_Lua_f(void); void COM_Lua_f(void);
#define LUA_Call(L,a)\
{\
if (lua_pcall(L, a, 0, 0)) {\
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(L,-1));\
lua_pop(L, 1);\
}\
}
#define LUA_ErrInvalid(L, type) luaL_error(L, "accessed " type " doesn't exist anymore, please check 'valid' before using " type "."); #define LUA_ErrInvalid(L, type) luaL_error(L, "accessed " type " doesn't exist anymore, please check 'valid' before using " type ".");
// Deprecation warnings // Deprecation warnings

View File

@ -21,7 +21,6 @@
enum skin { enum skin {
skin_valid = 0, skin_valid = 0,
skin_name, skin_name,
skin_spritedef,
skin_wadnum, skin_wadnum,
skin_flags, skin_flags,
skin_realname, skin_realname,
@ -54,12 +53,12 @@ enum skin {
skin_contspeed, skin_contspeed,
skin_contangle, skin_contangle,
skin_soundsid, skin_soundsid,
skin_availability skin_availability,
skin_sprites
}; };
static const char *const skin_opt[] = { static const char *const skin_opt[] = {
"valid", "valid",
"name", "name",
"spritedef",
"wadnum", "wadnum",
"flags", "flags",
"realname", "realname",
@ -93,6 +92,7 @@ static const char *const skin_opt[] = {
"contangle", "contangle",
"soundsid", "soundsid",
"availability", "availability",
"sprites",
NULL}; NULL};
#define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field]) #define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field])
@ -113,8 +113,6 @@ static int skin_get(lua_State *L)
case skin_name: case skin_name:
lua_pushstring(L, skin->name); lua_pushstring(L, skin->name);
break; break;
case skin_spritedef:
return UNIMPLEMENTED;
case skin_wadnum: case skin_wadnum:
// !!WARNING!! May differ between clients due to music wads, therefore NOT NETWORK SAFE // !!WARNING!! May differ between clients due to music wads, therefore NOT NETWORK SAFE
return UNIMPLEMENTED; return UNIMPLEMENTED;
@ -214,6 +212,9 @@ static int skin_get(lua_State *L)
case skin_availability: case skin_availability:
lua_pushinteger(L, skin->availability); lua_pushinteger(L, skin->availability);
break; break;
case skin_sprites:
LUA_PushLightUserdata(L, skin->sprites, META_SKINSPRITES);
break;
} }
return 1; return 1;
} }
@ -324,6 +325,49 @@ static int soundsid_num(lua_State *L)
return 1; return 1;
} }
enum spritesopt {
numframes = 0
};
static const char *const sprites_opt[] = {
"numframes",
NULL};
// skin.sprites[i] -> sprites[i]
static int lib_getSkinSprite(lua_State *L)
{
spritedef_t *sprites = (spritedef_t *)luaL_checkudata(L, 1, META_SKINSPRITES);
playersprite_t i = luaL_checkinteger(L, 2);
if (i < 0 || i >= NUMPLAYERSPRITES*2)
return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1);
LUA_PushLightUserdata(L, &sprites[i], META_SKINSPRITESLIST);
return 1;
}
// #skin.sprites -> NUMPLAYERSPRITES*2
static int lib_numSkinsSprites(lua_State *L)
{
lua_pushinteger(L, NUMPLAYERSPRITES*2);
return 1;
}
static int sprite_get(lua_State *L)
{
spritedef_t *sprite = (spritedef_t *)luaL_checkudata(L, 1, META_SKINSPRITESLIST);
enum spritesopt field = luaL_checkoption(L, 2, NULL, sprites_opt);
switch (field)
{
case numframes:
lua_pushinteger(L, sprite->numframes);
break;
}
return 1;
}
int LUA_SkinLib(lua_State *L) int LUA_SkinLib(lua_State *L)
{ {
luaL_newmetatable(L, META_SKIN); luaL_newmetatable(L, META_SKIN);
@ -345,6 +389,19 @@ int LUA_SkinLib(lua_State *L)
lua_setfield(L, -2, "__len"); lua_setfield(L, -2, "__len");
lua_pop(L,1); lua_pop(L,1);
luaL_newmetatable(L, META_SKINSPRITES);
lua_pushcfunction(L, lib_getSkinSprite);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numSkinsSprites);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
luaL_newmetatable(L, META_SKINSPRITESLIST);
lua_pushcfunction(L, sprite_get);
lua_setfield(L, -2, "__index");
lua_pop(L,1);
lua_newuserdata(L, 0); lua_newuserdata(L, 0);
lua_createtable(L, 0, 2); lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getSkin); lua_pushcfunction(L, lib_getSkin);

View File

@ -18,7 +18,7 @@
#include "z_zone.h" #include "z_zone.h"
#include "v_video.h" #include "v_video.h"
#include "i_video.h" #include "i_video.h"
#include "i_system.h" // I_GetTimeMicros #include "i_system.h" // I_GetPreciseTime
#include "m_misc.h" #include "m_misc.h"
#include "st_stuff.h" // st_palette #include "st_stuff.h" // st_palette
@ -29,15 +29,21 @@
// GIFs are always little-endian // GIFs are always little-endian
#include "byteptr.h" #include "byteptr.h"
CV_PossibleValue_t gif_dynamicdelay_cons_t[] = {
{0, "Off"},
{1, "On"},
{2, "Accurate, experimental"},
{0, NULL}};
consvar_t cv_gif_optimize = CVAR_INIT ("gif_optimize", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_gif_optimize = CVAR_INIT ("gif_optimize", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_gif_downscale = CVAR_INIT ("gif_downscale", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_gif_downscale = CVAR_INIT ("gif_downscale", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_gif_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_gif_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, gif_dynamicdelay_cons_t, NULL);
consvar_t cv_gif_localcolortable = CVAR_INIT ("gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_gif_localcolortable = CVAR_INIT ("gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL);
#ifdef HAVE_ANIGIF #ifdef HAVE_ANIGIF
static boolean gif_optimize = false; // So nobody can do something dumb static boolean gif_optimize = false; // So nobody can do something dumb
static boolean gif_downscale = false; // like changing cvars mid output static boolean gif_downscale = false; // like changing cvars mid output
static boolean gif_dynamicdelay = false; // and messing something up static UINT8 gif_dynamicdelay = (UINT8)0; // and messing something up
// Palette handling // Palette handling
static boolean gif_localcolortable = false; static boolean gif_localcolortable = false;
@ -47,7 +53,8 @@ static RGBA_t *gif_framepalette = NULL;
static FILE *gif_out = NULL; static FILE *gif_out = NULL;
static INT32 gif_frames = 0; static INT32 gif_frames = 0;
static UINT32 gif_prevframems = 0; static precise_t gif_prevframetime = 0;
static UINT32 gif_delayus = 0; // "us" is microseconds
static UINT8 gif_writeover = 0; static UINT8 gif_writeover = 0;
@ -594,16 +601,30 @@ static void GIF_framewrite(void)
// screen regions are handled in GIF_lzw // screen regions are handled in GIF_lzw
{ {
UINT16 delay; UINT16 delay = 0;
INT32 startline; INT32 startline;
if (gif_dynamicdelay) { if (gif_dynamicdelay ==(UINT8) 2)
{
// golden's attempt at creating a "dynamic delay" // golden's attempt at creating a "dynamic delay"
UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise).
gif_delayus += I_PreciseToMicros(I_GetPreciseTime() - gif_prevframetime); // increase delay by how much time was spent between last measurement
if (gif_delayus/1000 >= mingifdelay) // delay is big enough to be able to effect gif frame delay?
{
int frames = (gif_delayus/1000) / mingifdelay; // get amount of frames to delay.
delay = frames; // set the delay to delay that amount of frames.
gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency.
}
}
else if (gif_dynamicdelay ==(UINT8) 1)
{
float delayf = ceil(100.0f/NEWTICRATE); float delayf = ceil(100.0f/NEWTICRATE);
delay = (UINT16)((I_GetTimeMicros() - gif_prevframems)/10/1000); delay = (UINT16)I_PreciseToMicros((I_GetPreciseTime() - gif_prevframetime))/10/1000;
if (delay < (int)(delayf))
delay = (int)(delayf); if (delay < (UINT16)(delayf))
delay = (UINT16)(delayf);
} }
else else
{ {
@ -690,7 +711,7 @@ static void GIF_framewrite(void)
} }
fwrite(gifframe_data, 1, (p - gifframe_data), gif_out); fwrite(gifframe_data, 1, (p - gifframe_data), gif_out);
++gif_frames; ++gif_frames;
gif_prevframems = I_GetTimeMicros(); gif_prevframetime = I_GetPreciseTime();
} }
@ -711,14 +732,15 @@ INT32 GIF_open(const char *filename)
gif_optimize = (!!cv_gif_optimize.value); gif_optimize = (!!cv_gif_optimize.value);
gif_downscale = (!!cv_gif_downscale.value); gif_downscale = (!!cv_gif_downscale.value);
gif_dynamicdelay = (!!cv_gif_dynamicdelay.value); gif_dynamicdelay = (UINT8)cv_gif_dynamicdelay.value;
gif_localcolortable = (!!cv_gif_localcolortable.value); gif_localcolortable = (!!cv_gif_localcolortable.value);
gif_colorprofile = (!!cv_screenshot_colorprofile.value); gif_colorprofile = (!!cv_screenshot_colorprofile.value);
gif_headerpalette = GIF_getpalette(0); gif_headerpalette = GIF_getpalette(0);
GIF_headwrite(); GIF_headwrite();
gif_frames = 0; gif_frames = 0;
gif_prevframems = I_GetTimeMicros(); gif_prevframetime = I_GetPreciseTime();
gif_delayus = 0;
return 1; return 1;
} }

View File

@ -1108,7 +1108,6 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value; mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
mt->scale = player->mo->scale; mt->scale = player->mo->scale;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0; mt->pitch = mt->roll = 0;
@ -1435,19 +1434,26 @@ void Command_Writethings_f(void)
REQUIRE_SINGLEPLAYER; REQUIRE_SINGLEPLAYER;
REQUIRE_OBJECTPLACE; REQUIRE_OBJECTPLACE;
P_WriteThings(W_GetNumForName(G_BuildMapName(gamemap)) + ML_THINGS); P_WriteThings();
} }
void Command_ObjectPlace_f(void) void Command_ObjectPlace_f(void)
{ {
size_t thingarg;
size_t silent;
REQUIRE_INLEVEL; REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER; REQUIRE_SINGLEPLAYER;
REQUIRE_NOULTIMATE; REQUIRE_NOULTIMATE;
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer);
silent = COM_CheckParm("-silent");
thingarg = 2 - ( silent != 1 );
// Entering objectplace? // Entering objectplace?
if (!objectplacing || COM_Argc() > 1) if (!objectplacing || thingarg < COM_Argc())
{ {
if (!objectplacing) if (!objectplacing)
{ {
@ -1456,7 +1462,7 @@ void Command_ObjectPlace_f(void)
if (players[0].powers[pw_carry] == CR_NIGHTSMODE) if (players[0].powers[pw_carry] == CR_NIGHTSMODE)
return; return;
if (!COM_CheckParm("-silent")) if (! silent)
{ {
HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE|V_AUTOFADEOUT); HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE|V_AUTOFADEOUT);
HU_SetCEchoDuration(10); HU_SetCEchoDuration(10);
@ -1507,9 +1513,9 @@ void Command_ObjectPlace_f(void)
op_oldstate = (statenum_t)(players[0].mo->state-states); op_oldstate = (statenum_t)(players[0].mo->state-states);
} }
if (COM_Argc() > 1) if (thingarg < COM_Argc())
{ {
UINT16 mapthingnum = atoi(COM_Argv(1)); UINT16 mapthingnum = atoi(COM_Argv(thingarg));
mobjtype_t type = P_GetMobjtype(mapthingnum); mobjtype_t type = P_GetMobjtype(mapthingnum);
if (type == MT_UNKNOWN) if (type == MT_UNKNOWN)
CONS_Printf(M_GetText("No mobj type delegated to thing type %d.\n"), mapthingnum); CONS_Printf(M_GetText("No mobj type delegated to thing type %d.\n"), mapthingnum);

View File

@ -425,7 +425,7 @@ static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}};
consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange); consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange);
// This gametype list is integral for many different reasons. // This gametype list is integral for many different reasons.
// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! // When you add gametypes here, don't forget to update them in deh_tables.c and doomstat.h!
CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1];
consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange); consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange);
@ -1356,9 +1356,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Score/Time/Rings", &cv_timetic, 71}, {IT_STRING | IT_CVAR, NULL, "Score/Time/Rings", &cv_timetic, 71},
{IT_STRING | IT_CVAR, NULL, "Show Powerups", &cv_powerupdisplay, 76}, {IT_STRING | IT_CVAR, NULL, "Show Powerups", &cv_powerupdisplay, 76},
{IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 81}, // shows ping next to framerate if we want to. {IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 81}, // shows ping next to framerate if we want to.
#ifdef SEENAMES
{IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 86}, {IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 86},
#endif
{IT_HEADER, NULL, "Console", NULL, 95}, {IT_HEADER, NULL, "Console", NULL, 95},
{IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 101}, {IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 101},
@ -1483,7 +1481,7 @@ static menuitem_t OP_SoundOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "MIDI Music", &cv_gamemidimusic, 36}, {IT_STRING | IT_CVAR, NULL, "MIDI Music", &cv_gamemidimusic, 36},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "MIDI Music Volume", &cv_midimusicvolume, 41}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "MIDI Music Volume", &cv_midimusicvolume, 41},
{IT_STRING | IT_CVAR, NULL, "Music Preference", &cv_musicpref, 51}, {IT_STRING | IT_CVAR, NULL, "Music Preference", &cv_musicpref, 51},
{IT_HEADER, NULL, "Miscellaneous", NULL, 61}, {IT_HEADER, NULL, "Miscellaneous", NULL, 61},
@ -1551,18 +1549,19 @@ static menuitem_t OP_ScreenshotOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 57}, {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 57},
{IT_HEADER, NULL, "Movie Mode (F9)", NULL, 64}, {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 64},
{IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_movie_option, 70}, {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_movie_option, 70},
{IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_movie_folder, 75}, {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_movie_folder, 75},
{IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 90}, {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 90},
{IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 95}, {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 95},
{IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 100}, {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 100},
{IT_STRING|IT_CVAR, NULL, "Local Color Table", &cv_gif_localcolortable, 105}, {IT_STRING|IT_CVAR, NULL, "Local Color Table", &cv_gif_localcolortable, 105},
{IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 95}, {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_apng_downscale, 95},
{IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 100}, {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 100},
{IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 105}, {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 105},
{IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 110}, {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 110},
{IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 115},
}; };
enum enum
@ -1575,7 +1574,7 @@ enum
op_screenshot_gif_start = 13, op_screenshot_gif_start = 13,
op_screenshot_gif_end = 15, op_screenshot_gif_end = 15,
op_screenshot_apng_start = 16, op_screenshot_apng_start = 16,
op_screenshot_apng_end = 19, op_screenshot_apng_end = 20,
}; };
static menuitem_t OP_EraseDataMenu[] = static menuitem_t OP_EraseDataMenu[] =
@ -2145,15 +2144,20 @@ menu_t OP_PlaystyleDef = {
static void M_VideoOptions(INT32 choice) static void M_VideoOptions(INT32 choice)
{ {
(void)choice; (void)choice;
#ifdef HWRENDER
if (vid_opengl_state == -1)
{
OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
OP_VideoOptionsMenu[op_video_renderer].text = "Software";
}
OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
OP_VideoOptionsMenu[op_video_renderer].text = "Software";
#ifdef HWRENDER
if (vid.glstate != VID_GL_LIBRARY_ERROR)
{
OP_VideoOptionsMenu[op_video_renderer].status = (IT_STRING | IT_CVAR);
OP_VideoOptionsMenu[op_video_renderer].patch = NULL;
OP_VideoOptionsMenu[op_video_renderer].text = "Renderer";
}
#endif #endif
M_SetupNextMenu(&OP_VideoOptionsDef); M_SetupNextMenu(&OP_VideoOptionsDef);
} }
@ -4026,7 +4030,7 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv)
cursorlump = W_GetNumForName("M_THERMO"); cursorlump = W_GetNumForName("M_THERMO");
V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_PATCH)); V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_PATCH));
xx += SHORT(p->width) - SHORT(p->leftoffset); xx += p->width - p->leftoffset;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_PATCH)); V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_PATCH));
@ -4165,7 +4169,7 @@ static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_
fixed_t sw, pw; fixed_t sw, pw;
patch = W_CachePatchName("LSSTATIC", PU_PATCH); patch = W_CachePatchName("LSSTATIC", PU_PATCH);
pw = SHORT(patch->width) - (sw = w*2); //FixedDiv(w, scale); -- for scale FRACUNIT/2 pw = patch->width - (sw = w*2); //FixedDiv(w, scale); -- for scale FRACUNIT/2
/*if (pw > 0) -- model code for modders providing weird LSSTATIC /*if (pw > 0) -- model code for modders providing weird LSSTATIC
{ {
@ -4262,8 +4266,8 @@ static void M_DrawMenuTitle(void)
if (p->height > 24) // title is larger than normal if (p->height > 24) // title is larger than normal
{ {
INT32 xtitle = (BASEVIDWIDTH - (SHORT(p->width)/2))/2; INT32 xtitle = (BASEVIDWIDTH - (p->width/2))/2;
INT32 ytitle = (30 - (SHORT(p->height)/2))/2; INT32 ytitle = (30 - (p->height/2))/2;
if (xtitle < 0) if (xtitle < 0)
xtitle = 0; xtitle = 0;
@ -4274,8 +4278,8 @@ static void M_DrawMenuTitle(void)
} }
else else
{ {
INT32 xtitle = (BASEVIDWIDTH - SHORT(p->width))/2; INT32 xtitle = (BASEVIDWIDTH - p->width)/2;
INT32 ytitle = (30 - SHORT(p->height))/2; INT32 ytitle = (30 - p->height)/2;
if (xtitle < 0) if (xtitle < 0)
xtitle = 0; xtitle = 0;
@ -4311,7 +4315,7 @@ static void M_DrawGenericMenu(void)
{ {
patch_t *p; patch_t *p;
p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH); p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p); V_DrawScaledPatch((BASEVIDWIDTH - p->width)/2, y, 0, p);
} }
else else
{ {
@ -4842,7 +4846,7 @@ static void M_DrawCenteredMenu(void)
{ {
patch_t *p; patch_t *p;
p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH); p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_PATCH);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p); V_DrawScaledPatch((BASEVIDWIDTH - p->width)/2, y, 0, p);
} }
else else
{ {
@ -5585,9 +5589,6 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo
if (map <= 0) if (map <= 0)
return; return;
if (needpatchrecache)
M_CacheLevelPlatter();
// A 564x100 image of the level as entry MAPxxW // A 564x100 image of the level as entry MAPxxW
if (!(levelselect.rows[row].mapavailable[col])) if (!(levelselect.rows[row].mapavailable[col]))
{ {
@ -5619,9 +5620,6 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea
if (map <= 0) if (map <= 0)
return; return;
if (needpatchrecache)
M_CacheLevelPlatter();
// A 160x100 image of the level as entry MAPxxP // A 160x100 image of the level as entry MAPxxP
if (!(levelselect.rows[row].mapavailable[col])) if (!(levelselect.rows[row].mapavailable[col]))
{ {
@ -5696,7 +5694,7 @@ static void M_DrawRecordAttackForeground(void)
angle_t fa; angle_t fa;
INT32 i; INT32 i;
INT32 height = (SHORT(fg->height)/2); INT32 height = (fg->height / 2);
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++) for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++)
@ -5731,9 +5729,9 @@ static void M_DrawNightsAttackMountains(void)
static INT32 bgscrollx; static INT32 bgscrollx;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
patch_t *background = W_CachePatchName(curbgname, PU_PATCH); patch_t *background = W_CachePatchName(curbgname, PU_PATCH);
INT16 w = SHORT(background->width); INT16 w = background->width;
INT32 x = FixedInt(-bgscrollx) % w; INT32 x = FixedInt(-bgscrollx) % w;
INT32 y = BASEVIDHEIGHT - SHORT(background->height)*2; INT32 y = BASEVIDHEIGHT - (background->height * 2);
if (vid.height != BASEVIDHEIGHT * dupz) if (vid.height != BASEVIDHEIGHT * dupz)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158);
@ -5758,18 +5756,18 @@ static void M_DrawNightsAttackBackground(void)
// top // top
patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_PATCH); patch_t *backtopfg = W_CachePatchName("NTSATKT1", PU_PATCH);
patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_PATCH); patch_t *fronttopfg = W_CachePatchName("NTSATKT2", PU_PATCH);
INT32 backtopwidth = SHORT(backtopfg->width); INT32 backtopwidth = backtopfg->width;
//INT32 backtopheight = SHORT(backtopfg->height); //INT32 backtopheight = backtopfg->height;
INT32 fronttopwidth = SHORT(fronttopfg->width); INT32 fronttopwidth = fronttopfg->width;
//INT32 fronttopheight = SHORT(fronttopfg->height); //INT32 fronttopheight = fronttopfg->height;
// bottom // bottom
patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_PATCH); patch_t *backbottomfg = W_CachePatchName("NTSATKB1", PU_PATCH);
patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_PATCH); patch_t *frontbottomfg = W_CachePatchName("NTSATKB2", PU_PATCH);
INT32 backbottomwidth = SHORT(backbottomfg->width); INT32 backbottomwidth = backbottomfg->width;
INT32 backbottomheight = SHORT(backbottomfg->height); INT32 backbottomheight = backbottomfg->height;
INT32 frontbottomwidth = SHORT(frontbottomfg->width); INT32 frontbottomwidth = frontbottomfg->width;
INT32 frontbottomheight = SHORT(frontbottomfg->height); INT32 frontbottomheight = frontbottomfg->height;
// background // background
M_DrawNightsAttackMountains(); M_DrawNightsAttackMountains();
@ -5831,8 +5829,6 @@ static void M_DrawNightsAttackSuperSonic(void)
const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE); const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE);
INT32 timer = (ntsatkdrawtimer/4) % 2; INT32 timer = (ntsatkdrawtimer/4) % 2;
angle_t fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK; angle_t fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK;
ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH);
ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH);
V_DrawFixedPatch(235<<FRACBITS, (120<<FRACBITS) - (8*FINESINE(fa)), FRACUNIT, 0, ntssupersonic[timer], colormap); V_DrawFixedPatch(235<<FRACBITS, (120<<FRACBITS) - (8*FINESINE(fa)), FRACUNIT, 0, ntssupersonic[timer], colormap);
} }
@ -6154,7 +6150,7 @@ static void M_DrawMessageMenu(void)
} }
V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string); V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string);
y += 8; //SHORT(hu_font[0]->height); y += 8; //hu_font[0]->height;
} }
} }
@ -6176,7 +6172,7 @@ static void M_StopMessage(INT32 choice)
static void M_DrawImageDef(void) static void M_DrawImageDef(void)
{ {
// Grr. Need to autodetect for pic_ts. // Grr. Need to autodetect for pic_ts.
pic_t *pictest = (pic_t *)W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); pic_t *pictest = (pic_t *)W_CacheLumpName(currentMenu->menuitems[itemOn].text,PU_CACHE);
if (!pictest->zero) if (!pictest->zero)
V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text)); V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text));
else else
@ -6444,10 +6440,6 @@ static void M_DrawAddons(void)
return; return;
} }
// Lactozilla: Load addons menu patches.
if (needpatchrecache)
M_LoadAddonsPatches();
if (Playing()) if (Playing())
V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems.");
else else
@ -6944,8 +6936,7 @@ static void M_SelectableClearMenus(INT32 choice)
static void M_UltimateCheat(INT32 choice) static void M_UltimateCheat(INT32 choice)
{ {
(void)choice; (void)choice;
if (Playing()) LUAh_GameQuit(true);
LUAh_GameQuit();
I_Quit(); I_Quit();
} }
@ -7602,9 +7593,6 @@ static void M_DrawSoundTest(void)
fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0; fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0;
UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY}; UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY};
if (needpatchrecache)
M_CacheSoundTest();
// let's handle the ticker first. ideally we'd tick this somewhere else, BUT... // let's handle the ticker first. ideally we'd tick this somewhere else, BUT...
if (curplaying) if (curplaying)
{ {
@ -8246,17 +8234,15 @@ static void M_CacheLoadGameData(void)
static void M_DrawLoadGameData(void) static void M_DrawLoadGameData(void)
{ {
INT32 i, savetodraw, x, y, hsep = 90; INT32 i, prev_i = 1, savetodraw, x, y, hsep = 90;
skin_t *charskin = NULL; skin_t *charskin = NULL;
if (vid.width != BASEVIDWIDTH*vid.dupx) if (vid.width != BASEVIDWIDTH*vid.dupx)
hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx); hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx);
if (needpatchrecache) for (i = 2; prev_i; i = -(i + ((UINT32)i >> 31))) // draws from outwards in; 2, -2, 1, -1, 0
M_CacheLoadGameData();
for (i = -2; i <= 2; i++)
{ {
prev_i = i;
savetodraw = (saveSlotSelected + i + numsaves)%numsaves; savetodraw = (saveSlotSelected + i + numsaves)%numsaves;
x = (BASEVIDWIDTH/2 - 42 + loadgamescroll) + (i*hsep); x = (BASEVIDWIDTH/2 - 42 + loadgamescroll) + (i*hsep);
y = 33 + 9; y = 33 + 9;
@ -8957,6 +8943,7 @@ void M_ForceSaveSlotSelected(INT32 sslot)
// ================ // ================
// CHARACTER SELECT // CHARACTER SELECT
// ================ // ================
static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
{ {
if (!(description[i].picname[0])) if (!(description[i].picname[0]))
@ -8977,22 +8964,6 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH); description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH);
} }
static void M_CacheCharacterSelect(void)
{
INT32 i, skinnum;
for (i = 0; i < MAXSKINS; i++)
{
if (!description[i].used)
continue;
// Already set in M_SetupChoosePlayer
skinnum = description[i].skinnum[0];
if ((skinnum != -1) && (R_SkinUsable(-1, skinnum)))
M_CacheCharacterSelectEntry(i, skinnum);
}
}
static UINT8 M_SetupChoosePlayerDirect(INT32 choice) static UINT8 M_SetupChoosePlayerDirect(INT32 choice)
{ {
INT32 skinnum; INT32 skinnum;
@ -9192,16 +9163,13 @@ static void M_DrawSetupChoosePlayerMenu(void)
patch_t *charbg = W_CachePatchName("CHARBG", PU_PATCH); patch_t *charbg = W_CachePatchName("CHARBG", PU_PATCH);
patch_t *charfg = W_CachePatchName("CHARFG", PU_PATCH); patch_t *charfg = W_CachePatchName("CHARFG", PU_PATCH);
INT16 bgheight = SHORT(charbg->height); INT16 bgheight = charbg->height;
INT16 fgheight = SHORT(charfg->height); INT16 fgheight = charfg->height;
INT16 bgwidth = SHORT(charbg->width); INT16 bgwidth = charbg->width;
INT16 fgwidth = SHORT(charfg->width); INT16 fgwidth = charfg->width;
INT32 x, y; INT32 x, y;
INT32 w = (vid.width/vid.dupx); INT32 w = (vid.width/vid.dupx);
if (needpatchrecache)
M_CacheCharacterSelect();
if (abs(char_scroll) > FRACUNIT) if (abs(char_scroll) > FRACUNIT)
char_scroll -= (char_scroll>>2); char_scroll -= (char_scroll>>2);
else // close enough. else // close enough.
@ -9290,14 +9258,14 @@ static void M_DrawSetupChoosePlayerMenu(void)
curoutlinecolor = col = skincolors[charskin->prefcolor].invcolor; curoutlinecolor = col = skincolors[charskin->prefcolor].invcolor;
txsh = oxsh; txsh = oxsh;
ox = 8 + SHORT((description[char_on].charpic)->width)/2; ox = 8 + ((description[char_on].charpic)->width)/2;
y = my + 144; y = my + 144;
// cur // cur
{ {
x = ox - txsh; x = ox - txsh;
if (curpatch) if (curpatch)
x -= (SHORT(curpatch->width)/2); x -= curpatch->width / 2;
if (curtext[0] != '\0') if (curtext[0] != '\0')
{ {
@ -9330,7 +9298,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
x = (ox - txsh) - w; x = (ox - txsh) - w;
if (prevpatch) if (prevpatch)
x -= (SHORT(prevpatch->width)/2); x -= prevpatch->width / 2;
if (prevtext[0] != '\0') if (prevtext[0] != '\0')
{ {
@ -9360,7 +9328,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
x = (ox - txsh) + w; x = (ox - txsh) + w;
if (nextpatch) if (nextpatch)
x -= (SHORT(nextpatch->width)/2); x -= nextpatch->width / 2;
if (nexttext[0] != '\0') if (nexttext[0] != '\0')
{ {
@ -9382,7 +9350,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
{ {
patch_t *header = W_CachePatchName("M_PICKP", PU_PATCH); patch_t *header = W_CachePatchName("M_PICKP", PU_PATCH);
INT32 xtitle = 146; INT32 xtitle = 146;
INT32 ytitle = (35 - SHORT(header->height))/2; INT32 ytitle = (35 - header->height) / 2;
V_DrawFixedPatch(xtitle<<FRACBITS, ytitle<<FRACBITS, FRACUNIT/2, 0, header, NULL); V_DrawFixedPatch(xtitle<<FRACBITS, ytitle<<FRACBITS, FRACUNIT/2, 0, header, NULL);
} }
#endif // CHOOSEPLAYER_DRAWHEADER #endif // CHOOSEPLAYER_DRAWHEADER
@ -9848,8 +9816,8 @@ void M_DrawTimeAttackMenu(void)
empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_PATCH); empatch = W_CachePatchName(M_GetEmblemPatch(em, true), PU_PATCH);
empatx = SHORT(empatch->leftoffset)/2; empatx = empatch->leftoffset / 2;
empaty = SHORT(empatch->topoffset)/2; empaty = empatch->topoffset / 2;
if (em->collected) if (em->collected)
V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch, V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch,
@ -10085,7 +10053,7 @@ void M_DrawNightsAttackMenu(void)
// Super Sonic // Super Sonic
M_DrawNightsAttackSuperSonic(); M_DrawNightsAttackSuperSonic();
//if (P_HasGrades(cv_nextmap.value, 0)) //if (P_HasGrades(cv_nextmap.value, 0))
// V_DrawScaledPatch(235 - (SHORT((ngradeletters[bestoverall])->width)*3)/2, 135, 0, ngradeletters[bestoverall]); // V_DrawScaledPatch(235 - (((ngradeletters[bestoverall])->width)*3)/2, 135, 0, ngradeletters[bestoverall]);
if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) if (P_HasGrades(cv_nextmap.value, cv_dummymares.value))
{//make bigger again {//make bigger again
@ -10172,6 +10140,9 @@ static void M_NightsAttack(INT32 choice)
// This is really just to make sure Sonic is the played character, just in case // This is really just to make sure Sonic is the played character, just in case
M_PatchSkinNameTable(); M_PatchSkinNameTable();
ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH);
ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH);
G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
M_SetupNextMenu(&SP_NightsAttackDef); M_SetupNextMenu(&SP_NightsAttackDef);
@ -10573,10 +10544,6 @@ void M_DrawMarathon(void)
angle_t fa; angle_t fa;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy; INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy;
// lactozilla: the renderer changed so recache patches
if (needpatchrecache)
M_CacheCharacterSelect();
curbgxspeed = 0; curbgxspeed = 0;
curbgyspeed = 18; curbgyspeed = 18;
@ -10643,7 +10610,7 @@ void M_DrawMarathon(void)
{ {
patch_t *fg = W_CachePatchName("RECATKFG", PU_PATCH); patch_t *fg = W_CachePatchName("RECATKFG", PU_PATCH);
INT32 trans = V_60TRANS+((cnt&~3)<<(V_ALPHASHIFT-2)); INT32 trans = V_60TRANS+((cnt&~3)<<(V_ALPHASHIFT-2));
INT32 height = (SHORT(fg->height)/2); INT32 height = fg->height / 2;
char patchname[7] = "CEMGx0"; char patchname[7] = "CEMGx0";
dupz = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain. dupz = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain.
@ -11413,7 +11380,7 @@ static void M_DrawServerMenu(void)
else else
PictureOfLevel = W_CachePatchName("BLANKLVL", PU_PATCH); PictureOfLevel = W_CachePatchName("BLANKLVL", PU_PATCH);
V_DrawSmallScaledPatch(319 - (currentMenu->x + (SHORT(PictureOfLevel->width)/2)), currentMenu->y + imgheight, 0, PictureOfLevel); V_DrawSmallScaledPatch(319 - (currentMenu->x + (PictureOfLevel->width / 2)), currentMenu->y + imgheight, 0, PictureOfLevel);
} }
} }
@ -13403,8 +13370,7 @@ void M_QuitResponse(INT32 ch)
if (ch != 'y' && ch != KEY_ENTER) if (ch != 'y' && ch != KEY_ENTER)
return; return;
if (Playing()) LUAh_GameQuit(true);
LUAh_GameQuit();
if (!(netgame || cv_debug)) if (!(netgame || cv_debug))
{ {
S_ResetCaptions(); S_ResetCaptions();

View File

@ -163,6 +163,9 @@ consvar_t cv_zlib_levela = CVAR_INIT ("apng_compress_level", "4", CV_SAVE, zlib_
consvar_t cv_zlib_strategya = CVAR_INIT ("apng_strategy", "RLE", CV_SAVE, zlib_strategy_t, NULL); consvar_t cv_zlib_strategya = CVAR_INIT ("apng_strategy", "RLE", CV_SAVE, zlib_strategy_t, NULL);
consvar_t cv_zlib_window_bitsa = CVAR_INIT ("apng_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL); consvar_t cv_zlib_window_bitsa = CVAR_INIT ("apng_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL);
consvar_t cv_apng_delay = CVAR_INIT ("apng_speed", "1x", CV_SAVE, apng_delay_t, NULL); consvar_t cv_apng_delay = CVAR_INIT ("apng_speed", "1x", CV_SAVE, apng_delay_t, NULL);
consvar_t cv_apng_downscale = CVAR_INIT ("apng_downscale", "On", CV_SAVE, CV_OnOff, NULL);
static boolean apng_downscale = false; // So nobody can do something dumb like changing cvars mid output
boolean takescreenshot = false; // Take a screenshot this tic boolean takescreenshot = false; // Take a screenshot this tic
@ -981,25 +984,38 @@ static inline boolean M_PNGLib(void)
static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep png_buf) static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep png_buf)
{ {
png_uint_16 downscale = apng_downscale ? vid.dupx : 1;
png_uint_32 pitch = png_get_rowbytes(png_ptr, png_info_ptr); png_uint_32 pitch = png_get_rowbytes(png_ptr, png_info_ptr);
PNG_CONST png_uint_32 height = vid.height; PNG_CONST png_uint_32 width = vid.width / downscale;
png_bytepp row_pointers = png_malloc(png_ptr, height* sizeof (png_bytep)); PNG_CONST png_uint_32 height = vid.height / downscale;
png_uint_32 y; png_bytepp row_pointers = png_malloc(png_ptr, height * sizeof (png_bytep));
png_uint_32 x, y;
png_uint_16 framedelay = (png_uint_16)cv_apng_delay.value; png_uint_16 framedelay = (png_uint_16)cv_apng_delay.value;
apng_frames++; apng_frames++;
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
row_pointers[y] = png_buf; row_pointers[y] = malloc(pitch * sizeof(png_byte));
png_buf += pitch; for (x = 0; x < width; x++)
row_pointers[y][x] = png_buf[x * downscale];
png_buf += pitch * (downscale * downscale);
} }
//for (x = 0; x < width; x++)
//{
// printf("%d", x);
// row_pointers[y][x] = 0;
//}
/* row_pointers[y] = calloc(1, sizeof(png_bytep));
png_buf += pitch * 2;
}*/
#ifndef PNG_STATIC #ifndef PNG_STATIC
if (aPNG_write_frame_head) if (aPNG_write_frame_head)
#endif #endif
aPNG_write_frame_head(apng_ptr, apng_info_ptr, row_pointers, aPNG_write_frame_head(apng_ptr, apng_info_ptr, row_pointers,
vid.width, /* width */ width, /* width */
height, /* height */ height, /* height */
0, /* x offset */ 0, /* x offset */
0, /* y offset */ 0, /* y offset */
@ -1030,6 +1046,12 @@ static void M_PNGfix_acTL(png_structp png_ptr, png_infop png_info_ptr,
static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal) static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
{ {
png_uint_16 downscale;
apng_downscale = (!!cv_apng_downscale.value);
downscale = apng_downscale ? vid.dupx : 1;
apng_FILE = fopen(filename,"wb+"); // + mode for reading apng_FILE = fopen(filename,"wb+"); // + mode for reading
if (!apng_FILE) if (!apng_FILE)
{ {
@ -1080,7 +1102,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
png_set_compression_strategy(apng_ptr, cv_zlib_strategya.value); png_set_compression_strategy(apng_ptr, cv_zlib_strategya.value);
png_set_compression_window_bits(apng_ptr, cv_zlib_window_bitsa.value); png_set_compression_window_bits(apng_ptr, cv_zlib_window_bitsa.value);
M_PNGhdr(apng_ptr, apng_info_ptr, vid.width, vid.height, pal); M_PNGhdr(apng_ptr, apng_info_ptr, vid.width / downscale, vid.height / downscale, pal);
M_PNGText(apng_ptr, apng_info_ptr, true); M_PNGText(apng_ptr, apng_info_ptr, true);

View File

@ -33,7 +33,7 @@ extern consvar_t cv_screenshot_option, cv_screenshot_folder, cv_screenshot_color
extern consvar_t cv_moviemode, cv_movie_folder, cv_movie_option; extern consvar_t cv_moviemode, cv_movie_folder, cv_movie_option;
extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits; extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits;
extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa; extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa;
extern consvar_t cv_apng_delay; extern consvar_t cv_apng_delay, cv_apng_downscale;
void M_StartMovie(void); void M_StartMovie(void);
void M_SaveFrame(void); void M_SaveFrame(void);

View File

@ -1,7 +1,6 @@
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
@ -23,32 +22,37 @@
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
#endif #endif
int ps_tictime = 0; struct perfstatcol;
struct perfstatrow;
int ps_playerthink_time = 0; typedef struct perfstatcol perfstatcol_t;
int ps_thinkertime = 0; typedef struct perfstatrow perfstatrow_t;
int ps_thlist_times[NUM_THINKERLISTS]; struct perfstatcol {
static const char* thlist_names[] = { INT32 lores_x;
"Polyobjects: %d", INT32 hires_x;
"Main: %d", INT32 color;
"Mobjs: %d", perfstatrow_t * rows;
"Dynamic slopes: %d",
"Precipitation: %d",
NULL
}; };
static const char* thlist_shortnames[] = {
"plyobjs %d", struct perfstatrow {
"main %d", const char * lores_label;
"mobjs %d", const char * hires_label;
"dynslop %d", void * value;
"precip %d",
NULL
}; };
static precise_t ps_frametime = 0;
precise_t ps_tictime = 0;
precise_t ps_playerthink_time = 0;
precise_t ps_thinkertime = 0;
precise_t ps_thlist_times[NUM_THINKERLISTS];
int ps_checkposition_calls = 0; int ps_checkposition_calls = 0;
int ps_lua_thinkframe_time = 0; precise_t ps_lua_thinkframe_time = 0;
int ps_lua_mobjhooks = 0; int ps_lua_mobjhooks = 0;
// dynamically allocated resizeable array for thinkframe hook stats // dynamically allocated resizeable array for thinkframe hook stats
@ -56,6 +60,8 @@ ps_hookinfo_t *thinkframe_hooks = NULL;
int thinkframe_hooks_length = 0; int thinkframe_hooks_length = 0;
int thinkframe_hooks_capacity = 16; int thinkframe_hooks_capacity = 16;
static INT32 draw_row;
void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src) void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src)
{ {
if (!thinkframe_hooks) if (!thinkframe_hooks)
@ -77,379 +83,413 @@ void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src)
thinkframe_hooks_length = index + 1; thinkframe_hooks_length = index + 1;
} }
static void PS_SetFrameTime(void)
{
precise_t currenttime = I_GetPreciseTime();
ps_frametime = currenttime - ps_prevframetime;
ps_prevframetime = currenttime;
}
static boolean M_HighResolution(void)
{
return (vid.width >= 640 && vid.height >= 400);
}
enum {
PERF_TIME,
PERF_COUNT,
};
static void M_DrawPerfString(perfstatcol_t *col, int type)
{
const boolean hires = M_HighResolution();
INT32 draw_flags = V_MONOSPACE | col->color;
perfstatrow_t * row;
int value;
if (hires)
draw_flags |= V_ALLOWLOWERCASE;
for (row = col->rows; row->lores_label; ++row)
{
if (type == PERF_TIME)
value = I_PreciseToMicros(*(precise_t *)row->value);
else
value = *(int *)row->value;
if (hires)
{
V_DrawSmallString(col->hires_x, draw_row, draw_flags,
va("%s %d", row->hires_label, value));
draw_row += 5;
}
else
{
V_DrawThinString(col->lores_x, draw_row, draw_flags,
va("%s %d", row->lores_label, value));
draw_row += 8;
}
}
}
static void M_DrawPerfTiming(perfstatcol_t *col)
{
M_DrawPerfString(col, PERF_TIME);
}
static void M_DrawPerfCount(perfstatcol_t *col)
{
M_DrawPerfString(col, PERF_COUNT);
}
static void M_DrawRenderStats(void)
{
const boolean hires = M_HighResolution();
const int half_row = hires ? 5 : 4;
precise_t extrarendertime;
perfstatrow_t frametime_row[] = {
{"frmtime", "Frame time: ", &ps_frametime},
{0}
};
perfstatrow_t rendercalltime_row[] = {
{"drwtime", "3d rendering: ", &ps_rendercalltime},
{0}
};
perfstatrow_t opengltime_row[] = {
{"skybox ", "Skybox render: ", &ps_hw_skyboxtime},
{"bsptime", "RenderBSPNode: ", &ps_bsptime},
{"nodesrt", "Drwnode sort: ", &ps_hw_nodesorttime},
{"nodedrw", "Drwnode render:", &ps_hw_nodedrawtime},
{"sprsort", "Sprite sort: ", &ps_hw_spritesorttime},
{"sprdraw", "Sprite render: ", &ps_hw_spritedrawtime},
{"other ", "Other: ", &extrarendertime},
{0}
};
perfstatrow_t softwaretime_row[] = {
{"bsptime", "RenderBSPNode: ", &ps_bsptime},
{"sprclip", "R_ClipSprites: ", &ps_sw_spritecliptime},
{"portals", "Portals+Skybox:", &ps_sw_portaltime},
{"planes ", "R_DrawPlanes: ", &ps_sw_planetime},
{"masked ", "R_DrawMasked: ", &ps_sw_maskedtime},
{"other ", "Other: ", &extrarendertime},
{0}
};
perfstatrow_t uiswaptime_row[] = {
{"ui ", "UI render: ", &ps_uitime},
{"finupdt", "I_FinishUpdate:", &ps_swaptime},
{0}
};
perfstatrow_t tictime_row[] = {
{"logic ", "Game logic: ", &ps_tictime},
{0}
};
perfstatrow_t rendercalls_row[] = {
{"bspcall", "BSP calls: ", &ps_numbspcalls},
{"sprites", "Sprites: ", &ps_numsprites},
{"drwnode", "Drawnodes: ", &ps_numdrawnodes},
{"plyobjs", "Polyobjects: ", &ps_numpolyobjects},
{0}
};
perfstatrow_t batchtime_row[] = {
{"batsort", "Batch sort: ", &ps_hw_batchsorttime},
{"batdraw", "Batch render:", &ps_hw_batchdrawtime},
{0}
};
perfstatrow_t batchcount_row[] = {
{"polygon", "Polygons: ", &ps_hw_numpolys},
{"vertex ", "Vertices: ", &ps_hw_numverts},
{0}
};
perfstatrow_t batchcalls_row[] = {
{"drwcall", "Draw calls:", &ps_hw_numcalls},
{"shaders", "Shaders: ", &ps_hw_numshaders},
{"texture", "Textures: ", &ps_hw_numtextures},
{"polyflg", "Polyflags: ", &ps_hw_numpolyflags},
{"colors ", "Colors: ", &ps_hw_numcolors},
{0}
};
perfstatcol_t frametime_col = {20, 20, V_YELLOWMAP, frametime_row};
perfstatcol_t rendercalltime_col = {20, 20, V_YELLOWMAP, rendercalltime_row};
perfstatcol_t opengltime_col = {24, 24, V_YELLOWMAP, opengltime_row};
perfstatcol_t softwaretime_col = {24, 24, V_YELLOWMAP, softwaretime_row};
perfstatcol_t uiswaptime_col = {20, 20, V_YELLOWMAP, uiswaptime_row};
perfstatcol_t tictime_col = {20, 20, V_GRAYMAP, tictime_row};
perfstatcol_t rendercalls_col = {90, 115, V_BLUEMAP, rendercalls_row};
perfstatcol_t batchtime_col = {90, 115, V_REDMAP, batchtime_row};
perfstatcol_t batchcount_col = {155, 200, V_PURPLEMAP, batchcount_row};
perfstatcol_t batchcalls_col = {220, 200, V_PURPLEMAP, batchcalls_row};
boolean rendering = (
gamestate == GS_LEVEL ||
(gamestate == GS_TITLESCREEN && titlemapinaction)
);
draw_row = 10;
M_DrawPerfTiming(&frametime_col);
if (rendering)
{
M_DrawPerfTiming(&rendercalltime_col);
// Remember to update this calculation when adding more 3d rendering stats!
extrarendertime = ps_rendercalltime - ps_bsptime;
#ifdef HWRENDER
if (rendermode == render_opengl)
{
extrarendertime -=
ps_hw_skyboxtime +
ps_hw_nodesorttime +
ps_hw_nodedrawtime +
ps_hw_spritesorttime +
ps_hw_spritedrawtime;
if (cv_glbatching.value)
{
extrarendertime -=
ps_hw_batchsorttime +
ps_hw_batchdrawtime;
}
M_DrawPerfTiming(&opengltime_col);
}
else
#endif
{
extrarendertime -=
ps_sw_spritecliptime +
ps_sw_portaltime +
ps_sw_planetime +
ps_sw_maskedtime;
M_DrawPerfTiming(&softwaretime_col);
}
}
M_DrawPerfTiming(&uiswaptime_col);
draw_row += half_row;
M_DrawPerfTiming(&tictime_col);
if (rendering)
{
draw_row = 10;
M_DrawPerfCount(&rendercalls_col);
#ifdef HWRENDER
if (rendermode == render_opengl && cv_glbatching.value)
{
draw_row += half_row;
M_DrawPerfTiming(&batchtime_col);
draw_row = 10;
M_DrawPerfCount(&batchcount_col);
if (hires)
draw_row += half_row;
else
draw_row = 10;
M_DrawPerfCount(&batchcalls_col);
}
#endif
}
}
static void M_DrawTickStats(void)
{
int i = 0;
thinker_t *thinker;
int thinkercount = 0;
int polythcount = 0;
int mainthcount = 0;
int mobjcount = 0;
int nothinkcount = 0;
int scenerycount = 0;
int regularcount = 0;
int dynslopethcount = 0;
int precipcount = 0;
int removecount = 0;
precise_t extratime =
ps_tictime -
ps_playerthink_time -
ps_thinkertime -
ps_lua_thinkframe_time;
perfstatrow_t tictime_row[] = {
{"logic ", "Game logic: ", &ps_tictime},
{0}
};
perfstatrow_t thinker_time_row[] = {
{"plrthnk", "P_PlayerThink: ", &ps_playerthink_time},
{"thnkers", "P_RunThinkers: ", &ps_thinkertime},
{0}
};
perfstatrow_t detailed_thinker_time_row[] = {
{"plyobjs", "Polyobjects: ", &ps_thlist_times[THINK_POLYOBJ]},
{"main ", "Main: ", &ps_thlist_times[THINK_MAIN]},
{"mobjs ", "Mobjs: ", &ps_thlist_times[THINK_MOBJ]},
{"dynslop", "Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE]},
{"precip ", "Precipitation: ", &ps_thlist_times[THINK_PRECIP]},
{0}
};
perfstatrow_t extra_thinker_time_row[] = {
{"lthinkf", "LUAh_ThinkFrame:", &ps_lua_thinkframe_time},
{"other ", "Other: ", &extratime},
{0}
};
perfstatrow_t thinkercount_row[] = {
{"thnkers", "Thinkers: ", &thinkercount},
{0}
};
perfstatrow_t detailed_thinkercount_row[] = {
{"plyobjs", "Polyobjects: ", &polythcount},
{"main ", "Main: ", &mainthcount},
{"mobjs ", "Mobjs: ", &mobjcount},
{0}
};
perfstatrow_t mobjthinkercount_row[] = {
{"regular", "Regular: ", &regularcount},
{"scenery", "Scenery: ", &scenerycount},
{0}
};
perfstatrow_t nothinkcount_row[] = {
{"nothink", "Nothink: ", &nothinkcount},
{0}
};
perfstatrow_t detailed_thinkercount_row2[] = {
{"dynslop", "Dynamic slopes: ", &dynslopethcount},
{"precip ", "Precipitation: ", &precipcount},
{"remove ", "Pending removal:", &removecount},
{0}
};
perfstatrow_t misc_calls_row[] = {
{"lmhook", "Lua mobj hooks: ", &ps_lua_mobjhooks},
{"chkpos", "P_CheckPosition:", &ps_checkposition_calls},
{0}
};
perfstatcol_t tictime_col = {20, 20, V_YELLOWMAP, tictime_row};
perfstatcol_t thinker_time_col = {24, 24, V_YELLOWMAP, thinker_time_row};
perfstatcol_t detailed_thinker_time_col = {28, 28, V_YELLOWMAP, detailed_thinker_time_row};
perfstatcol_t extra_thinker_time_col = {24, 24, V_YELLOWMAP, extra_thinker_time_row};
perfstatcol_t thinkercount_col = {90, 115, V_BLUEMAP, thinkercount_row};
perfstatcol_t detailed_thinkercount_col = {94, 119, V_BLUEMAP, detailed_thinkercount_row};
perfstatcol_t mobjthinkercount_col = {98, 123, V_BLUEMAP, mobjthinkercount_row};
perfstatcol_t nothinkcount_col = {98, 123, V_BLUEMAP, nothinkcount_row};
perfstatcol_t detailed_thinkercount_col2 = {94, 119, V_BLUEMAP, detailed_thinkercount_row2};
perfstatcol_t misc_calls_col = {170, 216, V_PURPLEMAP, misc_calls_row};
for (i = 0; i < NUM_THINKERLISTS; i++)
{
for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next)
{
thinkercount++;
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
removecount++;
else if (i == THINK_POLYOBJ)
polythcount++;
else if (i == THINK_MAIN)
mainthcount++;
else if (i == THINK_MOBJ)
{
if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
{
mobj_t *mobj = (mobj_t*)thinker;
mobjcount++;
if (mobj->flags & MF_NOTHINK)
nothinkcount++;
else if (mobj->flags & MF_SCENERY)
scenerycount++;
else
regularcount++;
}
}
else if (i == THINK_DYNSLOPE)
dynslopethcount++;
else if (i == THINK_PRECIP)
precipcount++;
}
}
draw_row = 10;
M_DrawPerfTiming(&tictime_col);
M_DrawPerfTiming(&thinker_time_col);
M_DrawPerfTiming(&detailed_thinker_time_col);
M_DrawPerfTiming(&extra_thinker_time_col);
draw_row = 10;
M_DrawPerfCount(&thinkercount_col);
M_DrawPerfCount(&detailed_thinkercount_col);
M_DrawPerfCount(&mobjthinkercount_col);
if (nothinkcount)
M_DrawPerfCount(&nothinkcount_col);
M_DrawPerfCount(&detailed_thinkercount_col2);
if (M_HighResolution())
{
V_DrawSmallString(212, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, "Calls:");
draw_row = 15;
}
else
{
draw_row = 10;
}
M_DrawPerfCount(&misc_calls_col);
}
void M_DrawPerfStats(void) void M_DrawPerfStats(void)
{ {
char s[100]; char s[100];
int currenttime = I_GetTimeMicros();
int frametime = currenttime - ps_prevframetime; PS_SetFrameTime();
ps_prevframetime = currenttime;
if (cv_perfstats.value == 1) // rendering if (cv_perfstats.value == 1) // rendering
{ {
if (vid.width < 640 || vid.height < 400) // low resolution M_DrawRenderStats();
{
snprintf(s, sizeof s - 1, "frmtime %d", frametime);
V_DrawThinString(20, 10, V_MONOSPACE | V_YELLOWMAP, s);
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
{
snprintf(s, sizeof s - 1, "ui %d", ps_uitime);
V_DrawThinString(20, 18, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "finupdt %d", ps_swaptime);
V_DrawThinString(20, 26, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "logic %d", ps_tictime);
V_DrawThinString(20, 38, V_MONOSPACE | V_GRAYMAP, s);
return;
}
snprintf(s, sizeof s - 1, "drwtime %d", ps_rendercalltime);
V_DrawThinString(20, 18, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "bspcall %d", ps_numbspcalls);
V_DrawThinString(90, 10, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "sprites %d", ps_numsprites);
V_DrawThinString(90, 18, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "drwnode %d", ps_numdrawnodes);
V_DrawThinString(90, 26, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "plyobjs %d", ps_numpolyobjects);
V_DrawThinString(90, 34, V_MONOSPACE | V_BLUEMAP, s);
#ifdef HWRENDER
if (rendermode == render_opengl) // OpenGL specific stats
{
snprintf(s, sizeof s - 1, "skybox %d", ps_hw_skyboxtime);
V_DrawThinString(24, 26, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "bsptime %d", ps_bsptime);
V_DrawThinString(24, 34, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "nodesrt %d", ps_hw_nodesorttime);
V_DrawThinString(24, 42, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "nodedrw %d", ps_hw_nodedrawtime);
V_DrawThinString(24, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "sprsort %d", ps_hw_spritesorttime);
V_DrawThinString(24, 58, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "sprdraw %d", ps_hw_spritedrawtime);
V_DrawThinString(24, 66, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "other %d",
ps_rendercalltime - ps_hw_skyboxtime - ps_bsptime - ps_hw_nodesorttime
- ps_hw_nodedrawtime - ps_hw_spritesorttime - ps_hw_spritedrawtime
- ps_hw_batchsorttime - ps_hw_batchdrawtime);
V_DrawThinString(24, 74, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ui %d", ps_uitime);
V_DrawThinString(20, 82, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "finupdt %d", ps_swaptime);
V_DrawThinString(20, 90, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "logic %d", ps_tictime);
V_DrawThinString(20, 102, V_MONOSPACE | V_GRAYMAP, s);
if (cv_glbatching.value)
{
snprintf(s, sizeof s - 1, "batsort %d", ps_hw_batchsorttime);
V_DrawThinString(90, 46, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "batdraw %d", ps_hw_batchdrawtime);
V_DrawThinString(90, 54, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "polygon %d", ps_hw_numpolys);
V_DrawThinString(155, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "drwcall %d", ps_hw_numcalls);
V_DrawThinString(155, 18, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "shaders %d", ps_hw_numshaders);
V_DrawThinString(155, 26, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "vertex %d", ps_hw_numverts);
V_DrawThinString(155, 34, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "texture %d", ps_hw_numtextures);
V_DrawThinString(220, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "polyflg %d", ps_hw_numpolyflags);
V_DrawThinString(220, 18, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "colors %d", ps_hw_numcolors);
V_DrawThinString(220, 26, V_MONOSPACE | V_PURPLEMAP, s);
}
else
{
// reset these vars so the "other" measurement isn't off
ps_hw_batchsorttime = 0;
ps_hw_batchdrawtime = 0;
}
}
else // software specific stats
#endif
{
snprintf(s, sizeof s - 1, "bsptime %d", ps_bsptime);
V_DrawThinString(24, 26, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "sprclip %d", ps_sw_spritecliptime);
V_DrawThinString(24, 34, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "portals %d", ps_sw_portaltime);
V_DrawThinString(24, 42, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "planes %d", ps_sw_planetime);
V_DrawThinString(24, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "masked %d", ps_sw_maskedtime);
V_DrawThinString(24, 58, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "other %d",
ps_rendercalltime - ps_bsptime - ps_sw_spritecliptime
- ps_sw_portaltime - ps_sw_planetime - ps_sw_maskedtime);
V_DrawThinString(24, 66, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ui %d", ps_uitime);
V_DrawThinString(20, 74, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "finupdt %d", ps_swaptime);
V_DrawThinString(20, 82, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "logic %d", ps_tictime);
V_DrawThinString(20, 94, V_MONOSPACE | V_GRAYMAP, s);
}
}
else // high resolution
{
snprintf(s, sizeof s - 1, "Frame time: %d", frametime);
V_DrawSmallString(20, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
{
snprintf(s, sizeof s - 1, "UI render: %d", ps_uitime);
V_DrawSmallString(20, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "I_FinishUpdate: %d", ps_swaptime);
V_DrawSmallString(20, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Game logic: %d", ps_tictime);
V_DrawSmallString(20, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s);
return;
}
snprintf(s, sizeof s - 1, "3d rendering: %d", ps_rendercalltime);
V_DrawSmallString(20, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "BSP calls: %d", ps_numbspcalls);
V_DrawSmallString(115, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Sprites: %d", ps_numsprites);
V_DrawSmallString(115, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Drawnodes: %d", ps_numdrawnodes);
V_DrawSmallString(115, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Polyobjects: %d", ps_numpolyobjects);
V_DrawSmallString(115, 25, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
#ifdef HWRENDER
if (rendermode == render_opengl) // OpenGL specific stats
{
snprintf(s, sizeof s - 1, "Skybox render: %d", ps_hw_skyboxtime);
V_DrawSmallString(24, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "RenderBSPNode: %d", ps_bsptime);
V_DrawSmallString(24, 25, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Drwnode sort: %d", ps_hw_nodesorttime);
V_DrawSmallString(24, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Drwnode render: %d", ps_hw_nodedrawtime);
V_DrawSmallString(24, 35, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Sprite sort: %d", ps_hw_spritesorttime);
V_DrawSmallString(24, 40, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Sprite render: %d", ps_hw_spritedrawtime);
V_DrawSmallString(24, 45, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
// Remember to update this calculation when adding more 3d rendering stats!
snprintf(s, sizeof s - 1, "Other: %d",
ps_rendercalltime - ps_hw_skyboxtime - ps_bsptime - ps_hw_nodesorttime
- ps_hw_nodedrawtime - ps_hw_spritesorttime - ps_hw_spritedrawtime
- ps_hw_batchsorttime - ps_hw_batchdrawtime);
V_DrawSmallString(24, 50, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "UI render: %d", ps_uitime);
V_DrawSmallString(20, 55, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "I_FinishUpdate: %d", ps_swaptime);
V_DrawSmallString(20, 60, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Game logic: %d", ps_tictime);
V_DrawSmallString(20, 70, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s);
if (cv_glbatching.value)
{
snprintf(s, sizeof s - 1, "Batch sort: %d", ps_hw_batchsorttime);
V_DrawSmallString(115, 35, V_MONOSPACE | V_ALLOWLOWERCASE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "Batch render: %d", ps_hw_batchdrawtime);
V_DrawSmallString(115, 40, V_MONOSPACE | V_ALLOWLOWERCASE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "Polygons: %d", ps_hw_numpolys);
V_DrawSmallString(200, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "Vertices: %d", ps_hw_numverts);
V_DrawSmallString(200, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "Draw calls: %d", ps_hw_numcalls);
V_DrawSmallString(200, 25, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "Shaders: %d", ps_hw_numshaders);
V_DrawSmallString(200, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "Textures: %d", ps_hw_numtextures);
V_DrawSmallString(200, 35, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "Polyflags: %d", ps_hw_numpolyflags);
V_DrawSmallString(200, 40, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "Colors: %d", ps_hw_numcolors);
V_DrawSmallString(200, 45, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
}
else
{
// reset these vars so the "other" measurement isn't off
ps_hw_batchsorttime = 0;
ps_hw_batchdrawtime = 0;
}
}
else // software specific stats
#endif
{
snprintf(s, sizeof s - 1, "RenderBSPNode: %d", ps_bsptime);
V_DrawSmallString(24, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "R_ClipSprites: %d", ps_sw_spritecliptime);
V_DrawSmallString(24, 25, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Portals+Skybox: %d", ps_sw_portaltime);
V_DrawSmallString(24, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "R_DrawPlanes: %d", ps_sw_planetime);
V_DrawSmallString(24, 35, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "R_DrawMasked: %d", ps_sw_maskedtime);
V_DrawSmallString(24, 40, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
// Remember to update this calculation when adding more 3d rendering stats!
snprintf(s, sizeof s - 1, "Other: %d",
ps_rendercalltime - ps_bsptime - ps_sw_spritecliptime
- ps_sw_portaltime - ps_sw_planetime - ps_sw_maskedtime);
V_DrawSmallString(24, 45, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "UI render: %d", ps_uitime);
V_DrawSmallString(20, 50, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "I_FinishUpdate: %d", ps_swaptime);
V_DrawSmallString(20, 55, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Game logic: %d", ps_tictime);
V_DrawSmallString(20, 65, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s);
}
}
} }
else if (cv_perfstats.value == 2) // logic else if (cv_perfstats.value == 2) // logic
{ {
int i = 0; M_DrawTickStats();
thinker_t *thinker;
int thinkercount = 0;
int polythcount = 0;
int mainthcount = 0;
int mobjcount = 0;
int nothinkcount = 0;
int scenerycount = 0;
int dynslopethcount = 0;
int precipcount = 0;
int removecount = 0;
// y offset for drawing columns
int yoffset1 = 0;
int yoffset2 = 0;
for (i = 0; i < NUM_THINKERLISTS; i++)
{
for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next)
{
thinkercount++;
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
removecount++;
else if (i == THINK_POLYOBJ)
polythcount++;
else if (i == THINK_MAIN)
mainthcount++;
else if (i == THINK_MOBJ)
{
if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
{
mobj_t *mobj = (mobj_t*)thinker;
mobjcount++;
if (mobj->flags & MF_NOTHINK)
nothinkcount++;
else if (mobj->flags & MF_SCENERY)
scenerycount++;
}
}
else if (i == THINK_DYNSLOPE)
dynslopethcount++;
else if (i == THINK_PRECIP)
precipcount++;
}
}
if (vid.width < 640 || vid.height < 400) // low resolution
{
snprintf(s, sizeof s - 1, "logic %d", ps_tictime);
V_DrawThinString(20, 10, V_MONOSPACE | V_YELLOWMAP, s);
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
return;
snprintf(s, sizeof s - 1, "plrthnk %d", ps_playerthink_time);
V_DrawThinString(24, 18, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "thnkers %d", ps_thinkertime);
V_DrawThinString(24, 26, V_MONOSPACE | V_YELLOWMAP, s);
for (i = 0; i < NUM_THINKERLISTS; i++)
{
yoffset1 += 8;
snprintf(s, sizeof s - 1, thlist_shortnames[i], ps_thlist_times[i]);
V_DrawThinString(28, 26+yoffset1, V_MONOSPACE | V_YELLOWMAP, s);
}
snprintf(s, sizeof s - 1, "lthinkf %d", ps_lua_thinkframe_time);
V_DrawThinString(24, 34+yoffset1, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "other %d",
ps_tictime - ps_playerthink_time - ps_thinkertime - ps_lua_thinkframe_time);
V_DrawThinString(24, 42+yoffset1, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "thnkers %d", thinkercount);
V_DrawThinString(90, 10, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "plyobjs %d", polythcount);
V_DrawThinString(94, 18, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "main %d", mainthcount);
V_DrawThinString(94, 26, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "mobjs %d", mobjcount);
V_DrawThinString(94, 34, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "regular %d", mobjcount - scenerycount - nothinkcount);
V_DrawThinString(98, 42, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "scenery %d", scenerycount);
V_DrawThinString(98, 50, V_MONOSPACE | V_BLUEMAP, s);
if (nothinkcount)
{
snprintf(s, sizeof s - 1, "nothink %d", nothinkcount);
V_DrawThinString(98, 58, V_MONOSPACE | V_BLUEMAP, s);
yoffset2 += 8;
}
snprintf(s, sizeof s - 1, "dynslop %d", dynslopethcount);
V_DrawThinString(94, 58+yoffset2, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "precip %d", precipcount);
V_DrawThinString(94, 66+yoffset2, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "remove %d", removecount);
V_DrawThinString(94, 74+yoffset2, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "lmhooks %d", ps_lua_mobjhooks);
V_DrawThinString(170, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "chkpos %d", ps_checkposition_calls);
V_DrawThinString(170, 18, V_MONOSPACE | V_PURPLEMAP, s);
}
else // high resolution
{
snprintf(s, sizeof s - 1, "Game logic: %d", ps_tictime);
V_DrawSmallString(20, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
return;
snprintf(s, sizeof s - 1, "P_PlayerThink: %d", ps_playerthink_time);
V_DrawSmallString(24, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "P_RunThinkers: %d", ps_thinkertime);
V_DrawSmallString(24, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
for (i = 0; i < NUM_THINKERLISTS; i++)
{
yoffset1 += 5;
snprintf(s, sizeof s - 1, thlist_names[i], ps_thlist_times[i]);
V_DrawSmallString(28, 20+yoffset1, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
}
snprintf(s, sizeof s - 1, "LUAh_ThinkFrame: %d", ps_lua_thinkframe_time);
V_DrawSmallString(24, 25+yoffset1, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Other: %d",
ps_tictime - ps_playerthink_time - ps_thinkertime - ps_lua_thinkframe_time);
V_DrawSmallString(24, 30+yoffset1, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "Thinkers: %d", thinkercount);
V_DrawSmallString(115, 10+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Polyobjects: %d", polythcount);
V_DrawSmallString(119, 15+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Main: %d", mainthcount);
V_DrawSmallString(119, 20+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Mobjs: %d", mobjcount);
V_DrawSmallString(119, 25+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Regular: %d", mobjcount - scenerycount - nothinkcount);
V_DrawSmallString(123, 30+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Scenery: %d", scenerycount);
V_DrawSmallString(123, 35+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
if (nothinkcount)
{
snprintf(s, sizeof s - 1, "Nothink: %d", nothinkcount);
V_DrawSmallString(123, 40+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
yoffset2 += 5;
}
snprintf(s, sizeof s - 1, "Dynamic slopes: %d", dynslopethcount);
V_DrawSmallString(119, 40+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Precipitation: %d", precipcount);
V_DrawSmallString(119, 45+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Pending removal: %d", removecount);
V_DrawSmallString(119, 50+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "Calls:");
V_DrawSmallString(212, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "Lua mobj hooks: %d", ps_lua_mobjhooks);
V_DrawSmallString(216, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "P_CheckPosition: %d", ps_checkposition_calls);
V_DrawSmallString(216, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s);
}
} }
else if (cv_perfstats.value == 3) // lua thinkframe else if (cv_perfstats.value == 3) // lua thinkframe
{ {

View File

@ -1,7 +1,6 @@
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 1999-2020 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
@ -17,17 +16,17 @@
#include "lua_script.h" #include "lua_script.h"
#include "p_local.h" #include "p_local.h"
extern int ps_tictime; extern precise_t ps_tictime;
extern int ps_playerthink_time; extern precise_t ps_playerthink_time;
extern int ps_thinkertime; extern precise_t ps_thinkertime;
extern int ps_thlist_times[]; extern precise_t ps_thlist_times[];
extern int ps_checkposition_calls; extern int ps_checkposition_calls;
extern int ps_lua_thinkframe_time; extern precise_t ps_lua_thinkframe_time;
extern int ps_lua_mobjhooks; extern int ps_lua_mobjhooks;
typedef struct typedef struct
{ {

View File

@ -394,8 +394,10 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
ceiling_t *ceiling; ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -593,7 +595,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
} }
ceiling->tag = sec->tag; ceiling->tag = tag;
ceiling->type = type; ceiling->type = type;
firstone = 0; firstone = 0;
} }
@ -614,8 +616,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
ceiling_t *ceiling; ceiling_t *ceiling;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -670,7 +674,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
break; break;
} }
ceiling->tag = sec->tag; ceiling->tag = tag;
ceiling->type = type; ceiling->type = type;
} }
return rtn; return rtn;

File diff suppressed because it is too large Load Diff

View File

@ -632,8 +632,10 @@ void T_BounceCheese(bouncecheese_t *bouncer)
fixed_t waterheight; fixed_t waterheight;
fixed_t floorheight; fixed_t floorheight;
sector_t *actionsector; sector_t *actionsector;
INT32 i;
boolean remove; boolean remove;
INT32 i;
mtag_t tag = Tag_FGet(&bouncer->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT
|| bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself! || bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself!
@ -648,7 +650,7 @@ void T_BounceCheese(bouncecheese_t *bouncer)
} }
// You can use multiple target sectors, but at your own risk!!! // You can use multiple target sectors, but at your own risk!!!
for (i = -1; (i = P_FindSectorFromTag(bouncer->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
actionsector = &sectors[i]; actionsector = &sectors[i];
actionsector->moved = true; actionsector->moved = true;
@ -772,6 +774,8 @@ void T_StartCrumble(crumble_t *crumble)
ffloor_t *rover; ffloor_t *rover;
sector_t *sector; sector_t *sector;
INT32 i; INT32 i;
mtag_t tag = Tag_FGet(&crumble->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
// Once done, the no-return thinker just sits there, // Once done, the no-return thinker just sits there,
// constantly 'returning'... kind of an oxymoron, isn't it? // constantly 'returning'... kind of an oxymoron, isn't it?
@ -800,7 +804,7 @@ void T_StartCrumble(crumble_t *crumble)
} }
else if (++crumble->timer == 0) // Reposition back to original spot else if (++crumble->timer == 0) // Reposition back to original spot
{ {
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
sector = &sectors[i]; sector = &sectors[i];
@ -836,7 +840,7 @@ void T_StartCrumble(crumble_t *crumble)
// Flash to indicate that the platform is about to return. // Flash to indicate that the platform is about to return.
if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0)) if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0))
{ {
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
sector = &sectors[i]; sector = &sectors[i];
@ -928,7 +932,7 @@ void T_StartCrumble(crumble_t *crumble)
P_RemoveThinker(&crumble->thinker); P_RemoveThinker(&crumble->thinker);
} }
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
sector = &sectors[i]; sector = &sectors[i];
sector->moved = true; sector->moved = true;
@ -944,6 +948,7 @@ void T_StartCrumble(crumble_t *crumble)
void T_MarioBlock(mariothink_t *block) void T_MarioBlock(mariothink_t *block)
{ {
INT32 i; INT32 i;
TAG_ITER_DECLARECOUNTER(0);
T_MovePlane T_MovePlane
( (
@ -978,8 +983,7 @@ void T_MarioBlock(mariothink_t *block)
block->sector->ceilspeed = 0; block->sector->ceilspeed = 0;
block->direction = 0; block->direction = 0;
} }
TAG_ITER_SECTORS(0, (INT16)block->tag, i)
for (i = -1; (i = P_FindSectorFromTag(block->tag, i)) >= 0 ;)
P_RecalcPrecipInSector(&sectors[i]); P_RecalcPrecipInSector(&sectors[i]);
} }
@ -992,8 +996,7 @@ void T_FloatSector(floatthink_t *floater)
// Just find the first sector with the tag. // Just find the first sector with the tag.
// Doesn't work with multiple sectors that have different floor/ceiling heights. // Doesn't work with multiple sectors that have different floor/ceiling heights.
secnum = P_FindSectorFromTag(floater->tag, -1); if ((secnum = Tag_Iterate_Sectors((INT16)floater->tag, 0)) < 0)
if (secnum <= 0)
return; return;
actionsector = &sectors[secnum]; actionsector = &sectors[secnum];
@ -1061,9 +1064,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
case MT_HOOP: case MT_HOOP:
case MT_HOOPCOLLIDE: case MT_HOOPCOLLIDE:
case MT_NIGHTSCORE: case MT_NIGHTSCORE:
#ifdef SEENAMES
case MT_NAMECHECK: // DEFINITELY not this, because it is client-side. case MT_NAMECHECK: // DEFINITELY not this, because it is client-side.
#endif
continue; continue;
default: default:
break; break;
@ -1131,10 +1132,8 @@ void T_ThwompSector(thwomp_t *thwomp)
// Just find the first sector with the tag. // Just find the first sector with the tag.
// Doesn't work with multiple sectors that have different floor/ceiling heights. // Doesn't work with multiple sectors that have different floor/ceiling heights.
secnum = P_FindSectorFromTag(thwomp->tag, -1); if ((secnum = Tag_Iterate_Sectors((INT16)thwomp->tag, 0)) < 0)
return;
if (secnum <= 0)
return; // Bad bad bad!
actionsector = &sectors[secnum]; actionsector = &sectors[secnum];
@ -1293,8 +1292,10 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
sector_t *sec = NULL; sector_t *sec = NULL;
INT32 secnum = -1; INT32 secnum = -1;
boolean FOFsector = false; boolean FOFsector = false;
mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(nobaddies->sourceline->tag, secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -1304,13 +1305,15 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
for (i = 0; i < sec->linecount; i++) for (i = 0; i < sec->linecount; i++)
{ {
INT32 targetsecnum = -1; INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
TAG_ITER_DECLARECOUNTER(1);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue; continue;
FOFsector = true; FOFsector = true;
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0) TAG_ITER_SECTORS(1, tag2, targetsecnum)
{ {
if (T_SectorHasEnemies(&sectors[targetsecnum])) if (T_SectorHasEnemies(&sectors[targetsecnum]))
return; return;
@ -1321,7 +1324,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
return; return;
} }
CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", nobaddies->sourceline->tag); CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", tag);
// No enemies found, run the linedef exec and terminate this thinker // No enemies found, run the linedef exec and terminate this thinker
P_RunTriggerLinedef(nobaddies->sourceline, NULL, NULL); P_RunTriggerLinedef(nobaddies->sourceline, NULL, NULL);
@ -1396,6 +1399,8 @@ void T_EachTimeThinker(eachtime_t *eachtime)
boolean floortouch = false; boolean floortouch = false;
fixed_t bottomheight, topheight; fixed_t bottomheight, topheight;
ffloor_t *rover; ffloor_t *rover;
mtag_t tag = Tag_FGet(&eachtime->sourceline->tags);
TAG_ITER_DECLARECOUNTER(0);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
@ -1405,7 +1410,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
eachtime->playersOnArea[i] = false; eachtime->playersOnArea[i] = false;
} }
while ((secnum = P_FindSectorFromTag(eachtime->sourceline->tag, secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -1422,13 +1427,15 @@ void T_EachTimeThinker(eachtime_t *eachtime)
for (i = 0; i < sec->linecount; i++) for (i = 0; i < sec->linecount; i++)
{ {
INT32 targetsecnum = -1; INT32 targetsecnum = -1;
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
TAG_ITER_DECLARECOUNTER(1);
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
continue; continue;
FOFsector = true; FOFsector = true;
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0) TAG_ITER_SECTORS(1, tag2, targetsecnum)
{ {
targetsec = &sectors[targetsecnum]; targetsec = &sectors[targetsecnum];
@ -1530,7 +1537,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i))) if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i)))
continue; continue;
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", eachtime->sourceline->tag); CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag);
// 03/08/14 -Monster Iestyn // 03/08/14 -Monster Iestyn
// No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever! // No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever!
@ -1562,11 +1569,13 @@ void T_RaiseSector(raise_t *raise)
fixed_t distToNearestEndpoint; fixed_t distToNearestEndpoint;
INT32 direction; INT32 direction;
result_e res = 0; result_e res = 0;
mtag_t tag = raise->tag;
TAG_ITER_DECLARECOUNTER(0);
if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata) if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata)
return; return;
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
sector = &sectors[i]; sector = &sectors[i];
@ -1693,7 +1702,7 @@ void T_RaiseSector(raise_t *raise)
raise->sector->ceilspeed = 42; raise->sector->ceilspeed = 42;
raise->sector->floorspeed = speed*direction; raise->sector->floorspeed = speed*direction;
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
P_RecalcPrecipInSector(&sectors[i]); P_RecalcPrecipInSector(&sectors[i]);
} }
@ -1810,8 +1819,10 @@ void EV_DoFloor(line_t *line, floor_e floortype)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
floormove_t *dofloor; floormove_t *dofloor;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -2025,9 +2036,11 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
INT32 secnum = -1; INT32 secnum = -1;
sector_t *sec; sector_t *sec;
elevator_t *elevator; elevator_t *elevator;
mtag_t tag = Tag_FGet(&line->tags);
TAG_ITER_DECLARECOUNTER(0);
// act on all sectors with the same tag as the triggering linedef // act on all sectors with the same tag as the triggering linedef
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) TAG_ITER_SECTORS(0, tag, secnum)
{ {
sec = &sectors[secnum]; sec = &sectors[secnum];
@ -2148,6 +2161,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
INT16 flags; INT16 flags;
sector_t *controlsec = rover->master->frontsector; sector_t *controlsec = rover->master->frontsector;
mtag_t tag = Tag_FGet(&controlsec->tags);
if (sec == NULL) if (sec == NULL)
{ {
@ -2176,9 +2190,9 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
lifetime = 3*TICRATE; lifetime = 3*TICRATE;
flags = 0; flags = 0;
if (controlsec->tag != 0) if (tag != 0)
{ {
INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1); INT32 tagline = Tag_FindLineSpecial(14, tag);
if (tagline != -1) if (tagline != -1)
{ {
if (sides[lines[tagline].sidenum[0]].toptexture) if (sides[lines[tagline].sidenum[0]].toptexture)
@ -2322,6 +2336,8 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble_t *crumble; crumble_t *crumble;
sector_t *foundsec; sector_t *foundsec;
INT32 i; INT32 i;
mtag_t tag = Tag_FGet(&rover->master->tags);
TAG_ITER_DECLARECOUNTER(0);
// If floor is already activated, skip it // If floor is already activated, skip it
if (sec->floordata) if (sec->floordata)
@ -2364,7 +2380,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
crumble->sector->crumblestate = CRUMBLE_ACTIVATED; crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
foundsec = &sectors[i]; foundsec = &sectors[i];
@ -2413,7 +2429,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
block->direction = 1; block->direction = 1;
block->floorstartheight = block->sector->floorheight; block->floorstartheight = block->sector->floorheight;
block->ceilingstartheight = block->sector->ceilingheight; block->ceilingstartheight = block->sector->ceilingheight;
block->tag = (INT16)sector->tag; block->tag = (INT16)Tag_FGet(&sector->tags);
if (itsamonitor) if (itsamonitor)
{ {

View File

@ -470,14 +470,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
{ {
fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce
if (elementalpierce == 2) // Reset bubblewrap, part 1 if (elementalpierce == 2) // Reset bubblewrap, part 1
P_DoBubbleBounce(player); P_DoBubbleBounce(player);
toucher->momz = setmomz; toucher->momz = setmomz;
if (elementalpierce == 2) // Reset bubblewrap, part 2 if (elementalpierce == 2) // Reset bubblewrap, part 2
{ {
boolean underwater = toucher->eflags & MFE_UNDERWATER; boolean underwater = toucher->eflags & MFE_UNDERWATER;
if (underwater) if (underwater)
toucher->momz /= 2; toucher->momz /= 2;
toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height! toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height!
@ -1388,7 +1388,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->bot) if (player->bot)
return; return;
junk.tag = LE_AXE; // Initialize my junk
junk.tags.tags = NULL;
junk.tags.count = 0;
Tag_FSet(&junk.tags, LE_AXE);
EV_DoElevator(&junk, bridgeFall, false); EV_DoElevator(&junk, bridgeFall, false);
// scan the remaining thinkers to find koopa // scan the remaining thinkers to find koopa
@ -1613,7 +1617,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX)) if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX))
macespin = true; macespin = true;
if (macespin ? (player->powers[pw_ignorelatch] & (1<<15)) : (player->powers[pw_ignorelatch])) if (macespin ? (player->powers[pw_ignorelatch] & (1<<15)) : (player->powers[pw_ignorelatch]))
return; return;

View File

@ -374,8 +374,10 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force) void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force)
{ {
INT32 i; INT32 i;
TAG_ITER_DECLARECOUNTER(0);
// search all sectors for ones with tag // search all sectors for ones with tag
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;) TAG_ITER_SECTORS(0, tag, i)
{ {
if (!force && ticbased // always let speed fader execute if (!force && ticbased // always let speed fader execute
&& sectors[i].lightingdata && sectors[i].lightingdata

View File

@ -326,9 +326,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za,
mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z, INT32 shiftingAngle); mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z, INT32 shiftingAngle);
mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 aimtype, UINT32 flags2); mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 aimtype, UINT32 flags2);
#define P_SpawnPlayerMissile(s,t,f) P_SPMAngle(s,t,s->angle,true,f) #define P_SpawnPlayerMissile(s,t,f) P_SPMAngle(s,t,s->angle,true,f)
#ifdef SEENAMES
#define P_SpawnNameFinder(s,t) P_SPMAngle(s,t,s->angle,true,0) #define P_SpawnNameFinder(s,t) P_SPMAngle(s,t,s->angle,true,0)
#endif
void P_ColorTeamMissile(mobj_t *missile, player_t *source); void P_ColorTeamMissile(mobj_t *missile, player_t *source);
SINT8 P_MobjFlip(mobj_t *mobj); SINT8 P_MobjFlip(mobj_t *mobj);
fixed_t P_GetMobjGravity(mobj_t *mo); fixed_t P_GetMobjGravity(mobj_t *mo);

View File

@ -727,9 +727,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
|| (thing->player && thing->player->spectator)) || (thing->player && thing->player->spectator))
return true; return true;
#ifdef SEENAMES // Do name checks all the way up here
// Do name checks all the way up here // So that NOTHING ELSE can see MT_NAMECHECK because it is client-side.
// So that NOTHING ELSE can see MT_NAMECHECK because it is client-side.
if (tmthing->type == MT_NAMECHECK) if (tmthing->type == MT_NAMECHECK)
{ {
// Ignore things that aren't players, ignore spectators, ignore yourself. // Ignore things that aren't players, ignore spectators, ignore yourself.
@ -753,7 +752,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
seenplayer = thing->player; seenplayer = thing->player;
return false; return false;
} }
#endif
// Metal Sonic destroys tiny baby objects. // Metal Sonic destroys tiny baby objects.
if (tmthing->type == MT_METALSONIC_RACE if (tmthing->type == MT_METALSONIC_RACE
@ -982,7 +980,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOOR && tmthing->player) if (thing->type == MT_SALOONDOOR && tmthing->player)
{ {
mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing; mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing;
if ((thing->flags2 & MF2_AMBUSH) || ref != tmthing) if (((thing->flags2 & MF2_AMBUSH) && (tmthing->z <= thing->z + thing->height) && (tmthing->z + tmthing->height >= thing->z))
|| ref != tmthing)
{ {
fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT); fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle; angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle;
@ -995,7 +994,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOORCENTER && tmthing->player) if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
{ {
if ((thing->flags2 & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer))) if (((thing->flags2 & MF2_AMBUSH) && (tmthing->z <= thing->z + thing->height) && (tmthing->z + tmthing->height >= thing->z))
|| (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
return true; return true;
} }
@ -1683,7 +1683,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
{ {
fixed_t setmomz = -*momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce fixed_t setmomz = -*momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce
if (elementalpierce == 2) // Reset bubblewrap, part 1 if (elementalpierce == 2) // Reset bubblewrap, part 1
P_DoBubbleBounce(player); P_DoBubbleBounce(player);
*momz = setmomz; // Therefore, you should be thrust in the opposite direction, vertically. *momz = setmomz; // Therefore, you should be thrust in the opposite direction, vertically.
@ -1692,7 +1692,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (elementalpierce == 2) // Reset bubblewrap, part 2 if (elementalpierce == 2) // Reset bubblewrap, part 2
{ {
boolean underwater = tmthing->eflags & MFE_UNDERWATER; boolean underwater = tmthing->eflags & MFE_UNDERWATER;
if (underwater) if (underwater)
*momz /= 2; *momz /= 2;
*momz -= (*momz/(underwater ? 8 : 4)); // Cap the height! *momz -= (*momz/(underwater ? 8 : 4)); // Cap the height!
@ -2735,7 +2735,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
// Step up // Step up
if (thing->z < tmfloorz) if (thing->z < tmfloorz)
{ {
if (tmfloorz - thing->z <= maxstep) if (maxstep > 0 && tmfloorz - thing->z <= maxstep)
{ {
thing->z = thing->floorz = tmfloorz; thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover; thing->floorrover = tmfloorrover;
@ -2748,7 +2748,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
} }
else if (tmceilingz < thingtop) else if (tmceilingz < thingtop)
{ {
if (thingtop - tmceilingz <= maxstep) if (maxstep > 0 && thingtop - tmceilingz <= maxstep)
{ {
thing->z = ( thing->ceilingz = tmceilingz ) - thing->height; thing->z = ( thing->ceilingz = tmceilingz ) - thing->height;
thing->ceilingrover = tmceilingrover; thing->ceilingrover = tmceilingrover;
@ -3107,7 +3107,7 @@ static void P_HitSlideLine(line_t *ld)
lineangle >>= ANGLETOFINESHIFT; lineangle >>= ANGLETOFINESHIFT;
deltaangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT;
movelen = P_AproxDistance(tmxmove, tmymove); movelen = R_PointToDist2(0, 0, tmxmove, tmymove);
newlen = FixedMul(movelen, FINECOSINE(deltaangle)); newlen = FixedMul(movelen, FINECOSINE(deltaangle));
tmxmove = FixedMul(newlen, FINECOSINE(lineangle)); tmxmove = FixedMul(newlen, FINECOSINE(lineangle));
@ -3344,7 +3344,7 @@ static void PTR_GlideClimbTraverse(line_t *li)
{ {
for (rover = checksector->ffloors; rover; rover = rover->next) for (rover = checksector->ffloors; rover; rover = rover->next)
{ {
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || ((rover->flags & FF_BUSTUP) && (slidemo->player->charflags & SF_CANBUSTWALLS)))
continue; continue;
topheight = P_GetFFloorTopZAt (rover, slidemo->x, slidemo->y); topheight = P_GetFFloorTopZAt (rover, slidemo->x, slidemo->y);
@ -3443,9 +3443,17 @@ static boolean PTR_SlideTraverse(intercept_t *in)
P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector); P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector);
} }
if (slidemo->player && slidemo->player->charability == CA_GLIDEANDCLIMB if (slidemo->player)
&& (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing)) {
PTR_GlideClimbTraverse(li); if (slidemo->player->charability == CA_GLIDEANDCLIMB
&& (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing))
PTR_GlideClimbTraverse(li);
else
{
slidemo->player->lastsidehit = li->sidenum[P_PointOnLineSide(slidemo->x, slidemo->y, li)];
slidemo->player->lastlinehit = (INT16)(li - lines);
}
}
if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing)) if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing))
{ {

View File

@ -38,10 +38,6 @@
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL); consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
#ifdef WALLSPLATS
consvar_t cv_splats = CVAR_INIT ("splats", "On", CV_SAVE, CV_OnOff, NULL);
#endif
actioncache_t actioncachehead; actioncache_t actioncachehead;
static mobj_t *overlaycap = NULL; static mobj_t *overlaycap = NULL;
@ -1961,29 +1957,6 @@ void P_XYMovement(mobj_t *mo)
return; return;
} }
// draw damage on wall
//SPLAT TEST ----------------------------------------------------------
#ifdef WALLSPLATS
if (blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL
&& !(mo->flags2 & (MF2_AUTOMATIC|MF2_RAILRING|MF2_BOUNCERING|MF2_EXPLOSION|MF2_SCATTER)))
// set by last P_TryMove() that failed
{
divline_t divl;
divline_t misl;
fixed_t frac;
P_MakeDivline(blockingline, &divl);
misl.x = mo->x;
misl.y = mo->y;
misl.dx = mo->momx;
misl.dy = mo->momy;
frac = P_InterceptVector(&divl, &misl);
R_AddWallSplat(blockingline, P_PointOnLineSide(mo->x,mo->y,blockingline),
"A_DMG3", mo->z, frac, SPLATDRAWMODE_SHADE);
}
#endif
// --------------------------------------------------------- SPLAT TEST
P_ExplodeMissile(mo); P_ExplodeMissile(mo);
return; return;
} }
@ -3393,7 +3366,7 @@ void P_MobjCheckWater(mobj_t *mobj)
} }
// skipping stone! // skipping stone!
if (p && (p->charability2 == CA2_SPINDASH) && p->speed/2 > abs(mobj->momz) if (p && p->speed/2 > abs(mobj->momz)
&& ((p->pflags & (PF_SPINNING|PF_JUMPED)) == PF_SPINNING) && ((p->pflags & (PF_SPINNING|PF_JUMPED)) == PF_SPINNING)
&& ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop) && ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop)
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom))) || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom)))
@ -3536,16 +3509,19 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
{ {
sector_t *sector; sector_t *sector;
fixed_t halfheight = thiscam->z + (thiscam->height >> 1); fixed_t halfheight = thiscam->z + (thiscam->height >> 1);
size_t i;
// see if we are in water // see if we are in water
sector = thiscam->subsector->sector; sector = thiscam->subsector->sector;
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1) for (i = 0; i < sector->tags.count; i++)
return true; if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
return true;
if (sector->ffloors) if (sector->ffloors)
{ {
ffloor_t *rover; ffloor_t *rover;
size_t j;
for (rover = sector->ffloors; rover; rover = rover->next) for (rover = sector->ffloors; rover; rover = rover->next)
{ {
@ -3557,7 +3533,8 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y)) if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
continue; continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) for (j = 0; j < rover->master->frontsector->tags.count; j++)
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
return true; return true;
} }
} }
@ -4626,16 +4603,18 @@ static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta)
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum; INT32 snum;
sector_t *sector; sector_t *sector;
for (snum = sectors[tag%numsectors].firsttag; snum != -1; snum = sector->nexttag) boolean gotcage = false;
TAG_ITER_DECLARECOUNTER(0);
TAG_ITER_SECTORS(0, tag, snum)
{ {
sector = &sectors[snum]; sector = &sectors[snum];
if (sector->tag != tag)
continue;
sector->floorheight += delta; sector->floorheight += delta;
sector->ceilingheight += delta; sector->ceilingheight += delta;
P_CheckSector(sector, true); P_CheckSector(sector, true);
gotcage = true;
} }
return sectors[tag%numsectors].firsttag != -1; return gotcage;
} }
// Move Boss4's arms to angle // Move Boss4's arms to angle
@ -4707,26 +4686,16 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
static void P_Boss4DestroyCage(mobj_t *mobj) static void P_Boss4DestroyCage(mobj_t *mobj)
{ {
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
INT32 snum, next; INT32 snum;
size_t a; size_t a;
sector_t *sector, *rsec; sector_t *sector, *rsec;
ffloor_t *rover; ffloor_t *rover;
TAG_ITER_DECLARECOUNTER(0);
// This will be the final iteration of sector tag. TAG_ITER_SECTORS(0, tag, snum)
// We'll destroy the tag list as we go.
next = sectors[tag%numsectors].firsttag;
sectors[tag%numsectors].firsttag = -1;
for (snum = next; snum != -1; snum = next)
{ {
sector = &sectors[snum]; sector = &sectors[snum];
next = sector->nexttag;
sector->nexttag = -1;
if (sector->tag != tag)
continue;
sector->tag = 0;
// Destroy the FOFs. // Destroy the FOFs.
for (a = 0; a < sector->numattached; a++) for (a = 0; a < sector->numattached; a++)
{ {
@ -5685,14 +5654,10 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1) if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1)
break; break;
} }
if (spawner) if (spawner && dist)
{ {
mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER);
missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy));
if (dist == 0)
missile->fuse = 0;
else
missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy));
if (missile->fuse > mobj->fuse) if (missile->fuse > mobj->fuse)
P_RemoveMobj(missile); P_RemoveMobj(missile);
@ -7968,7 +7933,7 @@ static boolean P_MobjPushableThink(mobj_t *mobj)
P_PushableThinker(mobj); P_PushableThinker(mobj);
// Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.) // Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.)
if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL if ((mobj->flags & MF_FIRE) && !(mobj->eflags & MFE_TOUCHLAVA)
&& (mobj->eflags & (MFE_UNDERWATER | MFE_TOUCHWATER))) && (mobj->eflags & (MFE_UNDERWATER | MFE_TOUCHWATER)))
{ {
P_KillMobj(mobj, NULL, NULL, 0); P_KillMobj(mobj, NULL, NULL, 0);
@ -9614,12 +9579,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->fuse = 1; // Return to base. mobj->fuse = 1; // Return to base.
break; break;
} }
case MT_CANNONBALL:
#ifdef FLOORSPLATS
R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x,
mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE);
#endif
break;
case MT_SPINDUST: // Spindash dust case MT_SPINDUST: // Spindash dust
mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000
mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same
@ -9688,6 +9647,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
break; break;
} }
case MT_SALOONDOOR: case MT_SALOONDOOR:
if (!mobj->tracer) // Door center is gone or not spawned?
{
P_RemoveMobj(mobj); // Die
return false;
}
P_SaloonDoorThink(mobj); P_SaloonDoorThink(mobj);
break; break;
case MT_MINECARTSPAWNER: case MT_MINECARTSPAWNER:
@ -9742,7 +9707,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
P_MobjCheckWater(mobj); P_MobjCheckWater(mobj);
// Extinguish fire objects in water // Extinguish fire objects in water
if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL if ((mobj->flags & MF_FIRE) && !(mobj->eflags & MFE_TOUCHLAVA)
&& (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)))
{ {
P_KillMobj(mobj, NULL, NULL, 0); P_KillMobj(mobj, NULL, NULL, 0);
@ -10046,11 +10011,12 @@ void P_MobjThinker(mobj_t *mobj)
// Sector special (2,8) allows ANY mobj to trigger a linedef exec // Sector special (2,8) allows ANY mobj to trigger a linedef exec
if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8) if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8)
{ {
sector_t *sec2; sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1) if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2); {
mtag_t tag = Tag_FGet(&sec2->tags);
P_LinedefExecute(tag, mobj, sec2);
}
} }
if (mobj->scale != mobj->destscale) if (mobj->scale != mobj->destscale)
@ -10274,14 +10240,19 @@ void P_PushableThinker(mobj_t *mobj)
sec = mobj->subsector->sector; sec = mobj->subsector->sector;
if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight) if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight)
P_LinedefExecute(sec->tag, mobj, sec); {
mtag_t tag = Tag_FGet(&sec->tags);
P_LinedefExecute(tag, mobj, sec);
}
// else if (GETSECSPECIAL(sec->special, 2) == 8) // else if (GETSECSPECIAL(sec->special, 2) == 8)
{ {
sector_t *sec2; sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1) if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2); {
mtag_t tag = Tag_FGet(&sec2->tags);
P_LinedefExecute(tag, mobj, sec2);
}
} }
// it has to be pushable RIGHT NOW for this part to happen // it has to be pushable RIGHT NOW for this part to happen
@ -10502,6 +10473,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN)) if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN))
mobj->destscale = FRACUNIT/2; mobj->destscale = FRACUNIT/2;
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->spritexoffset = mobj->spriteyoffset = 0;
mobj->floorspriteslope = NULL;
// set subsector and/or block links // set subsector and/or block links
P_SetThingPosition(mobj); P_SetThingPosition(mobj);
I_Assert(mobj->subsector != NULL); I_Assert(mobj->subsector != NULL);
@ -10902,6 +10879,22 @@ static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mob
return mo; return mo;
} }
void *P_CreateFloorSpriteSlope(mobj_t *mobj)
{
if (mobj->floorspriteslope)
Z_Free(mobj->floorspriteslope);
mobj->floorspriteslope = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL);
mobj->floorspriteslope->normal.z = FRACUNIT;
return (void *)mobj->floorspriteslope;
}
void P_RemoveFloorSpriteSlope(mobj_t *mobj)
{
if (mobj->floorspriteslope)
Z_Free(mobj->floorspriteslope);
mobj->floorspriteslope = NULL;
}
// //
// P_RemoveMobj // P_RemoveMobj
// //
@ -10958,11 +10951,14 @@ void P_RemoveMobj(mobj_t *mobj)
P_DelSeclist(sector_list); P_DelSeclist(sector_list);
sector_list = NULL; sector_list = NULL;
} }
mobj->flags |= MF_NOSECTOR|MF_NOBLOCKMAP; mobj->flags |= MF_NOSECTOR|MF_NOBLOCKMAP;
mobj->subsector = NULL; mobj->subsector = NULL;
mobj->state = NULL; mobj->state = NULL;
mobj->player = NULL; mobj->player = NULL;
P_RemoveFloorSpriteSlope(mobj);
// stop any playing sound // stop any playing sound
S_StopSound(mobj); S_StopSound(mobj);
@ -11403,6 +11399,10 @@ void P_SpawnPlayer(INT32 playernum)
p->jumpfactor = skins[p->skin].jumpfactor; p->jumpfactor = skins[p->skin].jumpfactor;
} }
// Clear lastlinehit and lastsidehit
p->lastsidehit = -1;
p->lastlinehit = -1;
//awayview stuff //awayview stuff
p->awayviewmobj = NULL; p->awayviewmobj = NULL;
p->awayviewtics = 0; p->awayviewtics = 0;
@ -12030,8 +12030,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
const size_t mthingi = (size_t)(mthing - mapthings); const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag // Find the corresponding linedef special, using angle as tag
// P_FindSpecialLineFromTag works here now =D line = Tag_FindLineSpecial(9, mthing->angle);
line = P_FindSpecialLineFromTag(9, mthing->angle, -1);
if (line == -1) if (line == -1)
{ {
@ -12341,7 +12340,7 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
const size_t mthingi = (size_t)(mthing - mapthings); const size_t mthingi = (size_t)(mthing - mapthings);
// Find the corresponding linedef special, using angle as tag // Find the corresponding linedef special, using angle as tag
line = P_FindSpecialLineFromTag(15, mthing->angle, -1); line = Tag_FindLineSpecial(15, mthing->angle);
if (line == -1) if (line == -1)
{ {
@ -12580,17 +12579,20 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
break; break;
} }
case MT_SKYBOX: case MT_SKYBOX:
if (mthing->tag < 0 || mthing->tag > 15) {
mtag_t tag = Tag_FGet(&mthing->tags);
if (tag < 0 || tag > 15)
{ {
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", mthing->tag, sizeu1((size_t)(mthing - mapthings))); CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", tag, sizeu1((size_t)(mthing - mapthings)));
break; break;
} }
if (mthing->options & MTF_OBJECTSPECIAL) if (mthing->options & MTF_OBJECTSPECIAL)
skyboxcenterpnts[mthing->tag] = mobj; skyboxcenterpnts[tag] = mobj;
else else
skyboxviewpnts[mthing->tag] = mobj; skyboxviewpnts[tag] = mobj;
break; break;
}
case MT_EGGSTATUE: case MT_EGGSTATUE:
if (mthing->options & MTF_EXTRA) if (mthing->options & MTF_EXTRA)
{ {
@ -13077,8 +13079,8 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
mobj = P_SpawnMobj(x, y, z, i); mobj = P_SpawnMobj(x, y, z, i);
mobj->spawnpoint = mthing; mobj->spawnpoint = mthing;
P_SetScale(mobj, mthing->scale); P_SetScale(mobj, FixedMul(mobj->scale, mthing->scale));
mobj->destscale = mthing->scale; mobj->destscale = FixedMul(mobj->destscale, mthing->scale);
if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle)) if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle))
return mobj; return mobj;

View File

@ -194,6 +194,7 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
MF2_SPLAT = 1<<30, // Renders as a splat
// free: to and including 1<<31 // free: to and including 1<<31
} mobjflag2_t; } mobjflag2_t;
@ -264,6 +265,7 @@ typedef enum {
// Ran the thinker this tic. // Ran the thinker this tic.
PCF_THUNK = 32, PCF_THUNK = 32,
} precipflag_t; } precipflag_t;
// Map Object definition. // Map Object definition.
typedef struct mobj_s typedef struct mobj_s
{ {
@ -285,6 +287,12 @@ typedef struct mobj_s
UINT8 sprite2; // player sprites UINT8 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
struct subsector_s *subsector; // Subsector the mobj resides in. struct subsector_s *subsector; // Subsector the mobj resides in.
@ -399,13 +407,19 @@ typedef struct precipmobj_s
struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite. // More drawing info: to determine current sprite.
angle_t angle, pitch, roll; // orientation angle_t angle, pitch, roll; // orientation
angle_t rollangle; angle_t rollangle;
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites UINT8 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states UINT16 anim_duration; // for FF_ANIMATE states
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
struct subsector_s *subsector; // Subsector the mobj resides in. struct subsector_s *subsector; // Subsector the mobj resides in.
@ -462,6 +476,8 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime);
void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle); void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle);
void P_SpawnPrecipitation(void); void P_SpawnPrecipitation(void);
void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter); void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter);
void *P_CreateFloorSpriteSlope(mobj_t *mobj);
void P_RemoveFloorSpriteSlope(mobj_t *mobj);
boolean P_BossTargetPlayer(mobj_t *actor, boolean closest); boolean P_BossTargetPlayer(mobj_t *actor, boolean closest);
boolean P_SupermanLook4Players(mobj_t *actor); boolean P_SupermanLook4Players(mobj_t *actor);
void P_DestroyRobots(void); void P_DestroyRobots(void);

View File

@ -556,10 +556,11 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
polyobj_t *po; polyobj_t *po;
vertex_t dist, sspot; vertex_t dist, sspot;
size_t i; size_t i;
mtag_t tag = Tag_FGet(&anchor->tags);
if (!(po = Polyobj_GetForNum(anchor->tag))) if (!(po = Polyobj_GetForNum(tag)))
{ {
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->tag); CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", tag);
return; return;
} }
@ -1342,7 +1343,7 @@ void Polyobj_InitLevel(void)
{ {
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue); qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue);
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->tag); Polyobj_spawnPolyObj(i, qitem->mo, Tag_FGet(&qitem->mo->spawnpoint->tags));
} }
// move polyobjects to spawn points // move polyobjects to spawn points
@ -2444,10 +2445,11 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
polymove_t *th; polymove_t *th;
size_t i; size_t i;
INT32 start; INT32 start;
mtag_t tag = pfdata->polyObjNum;
if (!(po = Polyobj_GetForNum(pfdata->polyObjNum))) if (!(po = Polyobj_GetForNum(tag)))
{ {
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->polyObjNum); CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", tag);
return false; return false;
} }
@ -2470,7 +2472,7 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
po->thinker = &th->thinker; po->thinker = &th->thinker;
// set fields // set fields
th->polyObjNum = pfdata->polyObjNum; th->polyObjNum = tag;
th->distance = 0; th->distance = 0;
th->speed = pfdata->speed; th->speed = pfdata->speed;
th->angle = pfdata->angle; th->angle = pfdata->angle;

View File

@ -98,13 +98,16 @@ static void P_NetArchivePlayers(void)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
WRITESINT8(save_p, (SINT8)adminplayers[i]);
if (!playeringame[i]) if (!playeringame[i])
continue; continue;
flags = 0; flags = 0;
// no longer send ticcmds, player name, skin, or color // no longer send ticcmds
WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME);
WRITEINT16(save_p, players[i].angleturn); WRITEINT16(save_p, players[i].angleturn);
WRITEINT16(save_p, players[i].oldrelangleturn); WRITEINT16(save_p, players[i].oldrelangleturn);
WRITEANGLE(save_p, players[i].aiming); WRITEANGLE(save_p, players[i].aiming);
@ -134,6 +137,9 @@ static void P_NetArchivePlayers(void)
WRITEUINT16(save_p, players[i].flashpal); WRITEUINT16(save_p, players[i].flashpal);
WRITEUINT16(save_p, players[i].flashcount); WRITEUINT16(save_p, players[i].flashcount);
WRITEUINT8(save_p, players[i].skincolor);
WRITEINT32(save_p, players[i].skin);
WRITEUINT32(save_p, players[i].availabilities);
WRITEUINT32(save_p, players[i].score); WRITEUINT32(save_p, players[i].score);
WRITEFIXED(save_p, players[i].dashspeed); WRITEFIXED(save_p, players[i].dashspeed);
WRITESINT8(save_p, players[i].lives); WRITESINT8(save_p, players[i].lives);
@ -305,6 +311,8 @@ static void P_NetUnArchivePlayers(void)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
adminplayers[i] = (INT32)READSINT8(save_p);
// Do NOT memset player struct to 0 // Do NOT memset player struct to 0
// other areas may initialize data elsewhere // other areas may initialize data elsewhere
//memset(&players[i], 0, sizeof (player_t)); //memset(&players[i], 0, sizeof (player_t));
@ -312,9 +320,8 @@ static void P_NetUnArchivePlayers(void)
continue; continue;
// NOTE: sending tics should (hopefully) no longer be necessary // NOTE: sending tics should (hopefully) no longer be necessary
// sending player names, skin and color should not be necessary at all!
// (that data is handled in the server config now)
READSTRINGN(save_p, player_names[i], MAXPLAYERNAME);
players[i].angleturn = READINT16(save_p); players[i].angleturn = READINT16(save_p);
players[i].oldrelangleturn = READINT16(save_p); players[i].oldrelangleturn = READINT16(save_p);
players[i].aiming = READANGLE(save_p); players[i].aiming = READANGLE(save_p);
@ -344,6 +351,9 @@ static void P_NetUnArchivePlayers(void)
players[i].flashpal = READUINT16(save_p); players[i].flashpal = READUINT16(save_p);
players[i].flashcount = READUINT16(save_p); players[i].flashcount = READUINT16(save_p);
players[i].skincolor = READUINT8(save_p);
players[i].skin = READINT32(save_p);
players[i].availabilities = READUINT32(save_p);
players[i].score = READUINT32(save_p); players[i].score = READUINT32(save_p);
players[i].dashspeed = READFIXED(save_p); // dashing speed players[i].dashspeed = READFIXED(save_p); // dashing speed
players[i].lives = READSINT8(save_p); players[i].lives = READSINT8(save_p);
@ -913,7 +923,7 @@ static void UnArchiveFFloors(const sector_t *ss)
static void ArchiveSectors(void) static void ArchiveSectors(void)
{ {
size_t i; size_t i, j;
const sector_t *ss = sectors; const sector_t *ss = sectors;
const sector_t *spawnss = spawnsectors; const sector_t *spawnss = spawnsectors;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3;
@ -951,10 +961,8 @@ static void ArchiveSectors(void)
if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) if (ss->ceilingpic_angle != spawnss->ceilingpic_angle)
diff2 |= SD_CEILANG; diff2 |= SD_CEILANG;
if (ss->tag != spawnss->tag) if (!Tag_Compare(&ss->tags, &spawnss->tags))
diff2 |= SD_TAG; diff2 |= SD_TAG;
if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag)
diff3 |= SD_TAGLIST;
if (ss->extra_colormap != spawnss->extra_colormap) if (ss->extra_colormap != spawnss->extra_colormap)
diff3 |= SD_COLORMAP; diff3 |= SD_COLORMAP;
@ -1002,12 +1010,11 @@ static void ArchiveSectors(void)
WRITEANGLE(save_p, ss->floorpic_angle); WRITEANGLE(save_p, ss->floorpic_angle);
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
WRITEANGLE(save_p, ss->ceilingpic_angle); WRITEANGLE(save_p, ss->ceilingpic_angle);
if (diff2 & SD_TAG) // save only the tag if (diff2 & SD_TAG)
WRITEINT16(save_p, ss->tag); {
if (diff3 & SD_TAGLIST) // save both firsttag and nexttag WRITEUINT32(save_p, ss->tags.count);
{ // either of these could be changed even if tag isn't for (j = 0; j < ss->tags.count; j++)
WRITEINT32(save_p, ss->firsttag); WRITEINT16(save_p, ss->tags.tags[j]);
WRITEINT32(save_p, ss->nexttag);
} }
if (diff3 & SD_COLORMAP) if (diff3 & SD_COLORMAP)
@ -1025,7 +1032,7 @@ static void ArchiveSectors(void)
static void UnArchiveSectors(void) static void UnArchiveSectors(void)
{ {
UINT16 i; UINT16 i, j;
UINT8 diff, diff2, diff3; UINT8 diff, diff2, diff3;
for (;;) for (;;)
{ {
@ -1079,13 +1086,29 @@ static void UnArchiveSectors(void)
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
sectors[i].ceilingpic_angle = READANGLE(save_p); sectors[i].ceilingpic_angle = READANGLE(save_p);
if (diff2 & SD_TAG) if (diff2 & SD_TAG)
sectors[i].tag = READINT16(save_p); // DON'T use P_ChangeSectorTag
if (diff3 & SD_TAGLIST)
{ {
sectors[i].firsttag = READINT32(save_p); size_t ncount = READUINT32(save_p);
sectors[i].nexttag = READINT32(save_p);
// Remove entries from global lists.
for (j = 0; j < sectors[i].tags.count; j++)
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
// Reallocate if size differs.
if (ncount != sectors[i].tags.count)
{
sectors[i].tags.count = ncount;
sectors[i].tags.tags = Z_Realloc(sectors[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL);
}
for (j = 0; j < ncount; j++)
sectors[i].tags.tags[j] = READINT16(save_p);
// Add new entries.
for (j = 0; j < sectors[i].tags.count; j++)
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
} }
if (diff3 & SD_COLORMAP) if (diff3 & SD_COLORMAP)
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
if (diff3 & SD_CRUMBLESTATE) if (diff3 & SD_CRUMBLESTATE)
@ -1394,6 +1417,13 @@ typedef enum
MD2_MIRRORED = 1<<13, MD2_MIRRORED = 1<<13,
MD2_ROLLANGLE = 1<<14, MD2_ROLLANGLE = 1<<14,
MD2_SHADOWSCALE = 1<<15, MD2_SHADOWSCALE = 1<<15,
MD2_RENDERFLAGS = 1<<16,
MD2_BLENDMODE = 1<<17,
MD2_SPRITEXSCALE = 1<<18,
MD2_SPRITEYSCALE = 1<<19,
MD2_SPRITEXOFFSET = 1<<20,
MD2_SPRITEYOFFSET = 1<<21,
MD2_FLOORSPRITESLOPE = 1<<22,
} mobj_diff2_t; } mobj_diff2_t;
typedef enum typedef enum
@ -1606,6 +1636,27 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_ROLLANGLE; diff2 |= MD2_ROLLANGLE;
if (mobj->shadowscale) if (mobj->shadowscale)
diff2 |= MD2_SHADOWSCALE; diff2 |= MD2_SHADOWSCALE;
if (mobj->renderflags)
diff2 |= MD2_RENDERFLAGS;
if (mobj->renderflags)
diff2 |= MD2_BLENDMODE;
if (mobj->spritexscale != FRACUNIT)
diff2 |= MD2_SPRITEXSCALE;
if (mobj->spriteyscale != FRACUNIT)
diff2 |= MD2_SPRITEYSCALE;
if (mobj->spritexoffset)
diff2 |= MD2_SPRITEXOFFSET;
if (mobj->floorspriteslope)
{
pslope_t *slope = mobj->floorspriteslope;
if (slope->zangle || slope->zdelta || slope->xydirection
|| slope->o.x || slope->o.y || slope->o.z
|| slope->d.x || slope->d.y
|| slope->normal.x || slope->normal.y
|| (slope->normal.z != FRACUNIT))
diff2 |= MD2_FLOORSPRITESLOPE;
}
if (diff2 != 0) if (diff2 != 0)
diff |= MD_MORE; diff |= MD_MORE;
@ -1748,6 +1799,37 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEANGLE(save_p, mobj->rollangle); WRITEANGLE(save_p, mobj->rollangle);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
WRITEFIXED(save_p, mobj->shadowscale); WRITEFIXED(save_p, mobj->shadowscale);
if (diff2 & MD2_RENDERFLAGS)
WRITEUINT32(save_p, mobj->renderflags);
if (diff2 & MD2_BLENDMODE)
WRITEINT32(save_p, mobj->blendmode);
if (diff2 & MD2_SPRITEXSCALE)
WRITEFIXED(save_p, mobj->spritexscale);
if (diff2 & MD2_SPRITEYSCALE)
WRITEFIXED(save_p, mobj->spriteyscale);
if (diff2 & MD2_SPRITEXOFFSET)
WRITEFIXED(save_p, mobj->spritexoffset);
if (diff2 & MD2_SPRITEYOFFSET)
WRITEFIXED(save_p, mobj->spriteyoffset);
if (diff2 & MD2_FLOORSPRITESLOPE)
{
pslope_t *slope = mobj->floorspriteslope;
WRITEFIXED(save_p, slope->zdelta);
WRITEANGLE(save_p, slope->zangle);
WRITEANGLE(save_p, slope->xydirection);
WRITEFIXED(save_p, slope->o.x);
WRITEFIXED(save_p, slope->o.y);
WRITEFIXED(save_p, slope->o.z);
WRITEFIXED(save_p, slope->d.x);
WRITEFIXED(save_p, slope->d.y);
WRITEFIXED(save_p, slope->normal.x);
WRITEFIXED(save_p, slope->normal.y);
WRITEFIXED(save_p, slope->normal.z);
}
WRITEUINT32(save_p, mobj->mobjnum); WRITEUINT32(save_p, mobj->mobjnum);
} }
@ -2757,6 +2839,37 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->rollangle = READANGLE(save_p); mobj->rollangle = READANGLE(save_p);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
mobj->shadowscale = READFIXED(save_p); mobj->shadowscale = READFIXED(save_p);
if (diff2 & MD2_RENDERFLAGS)
mobj->renderflags = READUINT32(save_p);
if (diff2 & MD2_BLENDMODE)
mobj->blendmode = READINT32(save_p);
if (diff2 & MD2_SPRITEXSCALE)
mobj->spritexscale = READFIXED(save_p);
if (diff2 & MD2_SPRITEYSCALE)
mobj->spriteyscale = READFIXED(save_p);
if (diff2 & MD2_SPRITEXOFFSET)
mobj->spritexoffset = READFIXED(save_p);
if (diff2 & MD2_SPRITEYOFFSET)
mobj->spriteyoffset = READFIXED(save_p);
if (diff2 & MD2_FLOORSPRITESLOPE)
{
pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj);
slope->zdelta = READFIXED(save_p);
slope->zangle = READANGLE(save_p);
slope->xydirection = READANGLE(save_p);
slope->o.x = READFIXED(save_p);
slope->o.y = READFIXED(save_p);
slope->o.z = READFIXED(save_p);
slope->d.x = READFIXED(save_p);
slope->d.y = READFIXED(save_p);
slope->normal.x = READFIXED(save_p);
slope->normal.y = READFIXED(save_p);
slope->normal.z = READFIXED(save_p);
}
if (diff & MD_REDFLAG) if (diff & MD_REDFLAG)
{ {
@ -3951,14 +4064,17 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
playeringame[consoleplayer] = true; playeringame[consoleplayer] = true;
} }
static void P_NetArchiveMisc(void) static void P_NetArchiveMisc(boolean resending)
{ {
INT32 i; INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC); WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
if (resending)
WRITEUINT32(save_p, gametic);
WRITEINT16(save_p, gamemap); WRITEINT16(save_p, gamemap);
WRITEINT16(save_p, gamestate); WRITEINT16(save_p, gamestate);
WRITEINT16(save_p, gametype);
{ {
UINT32 pig = 0; UINT32 pig = 0;
@ -3990,6 +4106,12 @@ static void P_NetArchiveMisc(void)
WRITEINT32(save_p, sstimer); WRITEINT32(save_p, sstimer);
WRITEUINT32(save_p, bluescore); WRITEUINT32(save_p, bluescore);
WRITEUINT32(save_p, redscore); WRITEUINT32(save_p, redscore);
WRITEUINT16(save_p, skincolor_redteam);
WRITEUINT16(save_p, skincolor_blueteam);
WRITEUINT16(save_p, skincolor_redring);
WRITEUINT16(save_p, skincolor_bluering);
WRITEINT32(save_p, modulothing); WRITEINT32(save_p, modulothing);
WRITEINT16(save_p, autobalance); WRITEINT16(save_p, autobalance);
@ -4021,13 +4143,16 @@ static void P_NetArchiveMisc(void)
WRITEUINT8(save_p, 0x2e); WRITEUINT8(save_p, 0x2e);
} }
static inline boolean P_NetUnArchiveMisc(void) static inline boolean P_NetUnArchiveMisc(boolean reloading)
{ {
INT32 i; INT32 i;
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC) if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
I_Error("Bad $$$.sav at archive block Misc"); I_Error("Bad $$$.sav at archive block Misc");
if (reloading)
gametic = READUINT32(save_p);
gamemap = READINT16(save_p); gamemap = READINT16(save_p);
// gamemap changed; we assume that its map header is always valid, // gamemap changed; we assume that its map header is always valid,
@ -4041,6 +4166,8 @@ static inline boolean P_NetUnArchiveMisc(void)
G_SetGamestate(READINT16(save_p)); G_SetGamestate(READINT16(save_p));
gametype = READINT16(save_p);
{ {
UINT32 pig = READUINT32(save_p); UINT32 pig = READUINT32(save_p);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -4054,7 +4181,7 @@ static inline boolean P_NetUnArchiveMisc(void)
tokenlist = READUINT32(save_p); tokenlist = READUINT32(save_p);
if (!P_LoadLevel(true)) if (!P_LoadLevel(true, reloading))
return false; return false;
// get the time // get the time
@ -4074,6 +4201,12 @@ static inline boolean P_NetUnArchiveMisc(void)
sstimer = READINT32(save_p); sstimer = READINT32(save_p);
bluescore = READUINT32(save_p); bluescore = READUINT32(save_p);
redscore = READUINT32(save_p); redscore = READUINT32(save_p);
skincolor_redteam = READUINT16(save_p);
skincolor_blueteam = READUINT16(save_p);
skincolor_redring = READUINT16(save_p);
skincolor_bluering = READUINT16(save_p);
modulothing = READINT32(save_p); modulothing = READINT32(save_p);
autobalance = READINT16(save_p); autobalance = READINT16(save_p);
@ -4153,14 +4286,14 @@ void P_SaveGame(INT16 mapnum)
P_ArchiveLuabanksAndConsistency(); P_ArchiveLuabanksAndConsistency();
} }
void P_SaveNetGame(void) void P_SaveNetGame(boolean resending)
{ {
thinker_t *th; thinker_t *th;
mobj_t *mobj; mobj_t *mobj;
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
CV_SaveNetVars(&save_p); CV_SaveNetVars(&save_p);
P_NetArchiveMisc(); P_NetArchiveMisc(resending);
// Assign the mobjnumber for pointer tracking // Assign the mobjnumber for pointer tracking
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
@ -4208,10 +4341,10 @@ boolean P_LoadGame(INT16 mapoverride)
return true; return true;
} }
boolean P_LoadNetGame(void) boolean P_LoadNetGame(boolean reloading)
{ {
CV_LoadNetVars(&save_p); CV_LoadNetVars(&save_p);
if (!P_NetUnArchiveMisc()) if (!P_NetUnArchiveMisc(reloading))
return false; return false;
P_NetUnArchivePlayers(); P_NetUnArchivePlayers();
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)

View File

@ -22,9 +22,9 @@
// These are the load / save game routines. // These are the load / save game routines.
void P_SaveGame(INT16 mapnum); void P_SaveGame(INT16 mapnum);
void P_SaveNetGame(void); void P_SaveNetGame(boolean resending);
boolean P_LoadGame(INT16 mapoverride); boolean P_LoadGame(INT16 mapoverride);
boolean P_LoadNetGame(void); boolean P_LoadNetGame(boolean reloading);
mobj_t *P_FindNewPosition(UINT32 oldposition); mobj_t *P_FindNewPosition(UINT32 oldposition);

View File

@ -29,6 +29,7 @@
#include "r_data.h" #include "r_data.h"
#include "r_things.h" // for R_AddSpriteDefs #include "r_things.h" // for R_AddSpriteDefs
#include "r_textures.h" #include "r_textures.h"
#include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "r_sky.h" #include "r_sky.h"
#include "r_draw.h" #include "r_draw.h"
@ -82,6 +83,8 @@
#include "fastcmp.h" // textmap parsing #include "fastcmp.h" // textmap parsing
#include "taglist.h"
// //
// Map MD5, calculated on level load. // Map MD5, calculated on level load.
// Sent to clients in PT_SERVERINFO. // Sent to clients in PT_SERVERINFO.
@ -548,7 +551,7 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
lumpnum_t flatnum; lumpnum_t flatnum;
int texturenum; int texturenum;
patch_t *flatpatch; UINT8 *flatpatch;
size_t lumplength; size_t lumplength;
size_t i; size_t i;
@ -608,7 +611,7 @@ flatfound:
/* This could be a flat, patch, or PNG. */ /* This could be a flat, patch, or PNG. */
flatpatch = W_CacheLumpNum(flatnum, PU_CACHE); flatpatch = W_CacheLumpNum(flatnum, PU_CACHE);
lumplength = W_LumpLength(flatnum); lumplength = W_LumpLength(flatnum);
if (Picture_CheckIfPatch(flatpatch, lumplength)) if (Picture_CheckIfDoomPatch((softwarepatch_t *)flatpatch, lumplength))
levelflat->type = LEVELFLAT_PATCH; levelflat->type = LEVELFLAT_PATCH;
else else
{ {
@ -904,16 +907,13 @@ static void P_SpawnMapThings(boolean spawnemblems)
} }
// Experimental groovy write function! // Experimental groovy write function!
void P_WriteThings(lumpnum_t lumpnum) void P_WriteThings(void)
{ {
size_t i, length; size_t i, length;
mapthing_t *mt; mapthing_t *mt;
UINT8 *data;
UINT8 *savebuffer, *savebuf_p; UINT8 *savebuffer, *savebuf_p;
INT16 temp; INT16 temp;
data = W_CacheLumpNum(lumpnum, PU_LEVEL);
savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t)); savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t));
if (!savebuf_p) if (!savebuf_p)
@ -935,8 +935,6 @@ void P_WriteThings(lumpnum_t lumpnum)
WRITEUINT16(savebuf_p, mt->options); WRITEUINT16(savebuf_p, mt->options);
} }
Z_Free(data);
length = savebuf_p - savebuffer; length = savebuf_p - savebuffer;
FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length); FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length);
@ -968,8 +966,6 @@ static void P_LoadVertices(UINT8 *data)
static void P_InitializeSector(sector_t *ss) static void P_InitializeSector(sector_t *ss)
{ {
ss->nexttag = ss->firsttag = -1;
memset(&ss->soundorg, 0, sizeof(ss->soundorg)); memset(&ss->soundorg, 0, sizeof(ss->soundorg));
ss->validcount = 0; ss->validcount = 0;
@ -1040,7 +1036,7 @@ static void P_LoadSectors(UINT8 *data)
ss->lightlevel = SHORT(ms->lightlevel); ss->lightlevel = SHORT(ms->lightlevel);
ss->special = SHORT(ms->special); ss->special = SHORT(ms->special);
ss->tag = SHORT(ms->tag); Tag_FSet(&ss->tags, SHORT(ms->tag));
ss->floor_xoffs = ss->floor_yoffs = 0; ss->floor_xoffs = ss->floor_yoffs = 0;
ss->ceiling_xoffs = ss->ceiling_yoffs = 0; ss->ceiling_xoffs = ss->ceiling_yoffs = 0;
@ -1079,10 +1075,6 @@ static void P_InitializeLinedef(line_t *ld)
ld->frontsector = ld->backsector = NULL; ld->frontsector = ld->backsector = NULL;
ld->validcount = 0; ld->validcount = 0;
#ifdef WALLSPLATS
ld->splats = NULL;
#endif
ld->firsttag = ld->nexttag = -1;
ld->polyobj = NULL; ld->polyobj = NULL;
ld->text = NULL; ld->text = NULL;
@ -1154,7 +1146,7 @@ static void P_LoadLinedefs(UINT8 *data)
{ {
ld->flags = SHORT(mld->flags); ld->flags = SHORT(mld->flags);
ld->special = SHORT(mld->special); ld->special = SHORT(mld->special);
ld->tag = SHORT(mld->tag); Tag_FSet(&ld->tags, SHORT(mld->tag));
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT; ld->alpha = FRACUNIT;
@ -1347,7 +1339,7 @@ static void P_LoadSidedefs(UINT8 *data)
|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F')) || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F'))
sd->toptexture = axtoi(msd->toptexture); sd->toptexture = axtoi(msd->toptexture);
else else
I_Error("Custom FOF (tag %d) needs a value in the linedef's back side upper texture field.", sd->line->tag); I_Error("Custom FOF (line id %s) needs a value in the linedef's back side upper texture field.", sizeu1(sd->line - lines));
sd->midtexture = R_TextureNumForName(msd->midtexture); sd->midtexture = R_TextureNumForName(msd->midtexture);
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
@ -1387,8 +1379,8 @@ static void P_LoadThings(UINT8 *data)
mt->type = READUINT16(data); mt->type = READUINT16(data);
mt->options = READUINT16(data); mt->options = READUINT16(data);
mt->extrainfo = (UINT8)(mt->type >> 12); mt->extrainfo = (UINT8)(mt->type >> 12);
Tag_FSet(&mt->tags, 0);
mt->scale = FRACUNIT; mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0; mt->pitch = mt->roll = 0;
@ -1524,7 +1516,17 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
else if (fastcmp(param, "special")) else if (fastcmp(param, "special"))
sectors[i].special = atol(val); sectors[i].special = atol(val);
else if (fastcmp(param, "id")) else if (fastcmp(param, "id"))
sectors[i].tag = atol(val); Tag_FSet(&sectors[i].tags, atol(val));
else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&sectors[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "xpanningfloor")) else if (fastcmp(param, "xpanningfloor"))
sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val)); sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "ypanningfloor")) else if (fastcmp(param, "ypanningfloor"))
@ -1602,13 +1604,31 @@ static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val)
static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val) static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "id")) if (fastcmp(param, "id"))
lines[i].tag = atol(val); Tag_FSet(&lines[i].tags, atol(val));
else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&lines[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "special")) else if (fastcmp(param, "special"))
lines[i].special = atol(val); lines[i].special = atol(val);
else if (fastcmp(param, "v1")) else if (fastcmp(param, "v1"))
P_SetLinedefV1(i, atol(val)); P_SetLinedefV1(i, atol(val));
else if (fastcmp(param, "v2")) else if (fastcmp(param, "v2"))
P_SetLinedefV2(i, atol(val)); P_SetLinedefV2(i, atol(val));
else if (strlen(param) == 7 && fastncmp(param, "arg", 3) && fastncmp(param + 4, "str", 3))
{
size_t argnum = param[3] - '0';
if (argnum >= NUMLINESTRINGARGS)
return;
lines[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(lines[i].stringargs[argnum], val, strlen(val) + 1);
}
else if (fastncmp(param, "arg", 3) && strlen(param) > 3) else if (fastncmp(param, "arg", 3) && strlen(param) > 3)
{ {
size_t argnum = atol(param + 3); size_t argnum = atol(param + 3);
@ -1616,14 +1636,6 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
return; return;
lines[i].args[argnum] = atol(val); lines[i].args[argnum] = atol(val);
} }
else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9)
{
size_t argnum = param[9] - '0';
if (argnum >= NUMLINESTRINGARGS)
return;
lines[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(lines[i].stringargs[argnum], val, strlen(val) + 1);
}
else if (fastcmp(param, "sidefront")) else if (fastcmp(param, "sidefront"))
lines[i].sidenum[0] = atol(val); lines[i].sidenum[0] = atol(val);
else if (fastcmp(param, "sideback")) else if (fastcmp(param, "sideback"))
@ -1671,8 +1683,18 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
static void ParseTextmapThingParameter(UINT32 i, char *param, char *val) static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "id")) if (fastcmp(param, "id"))
mapthings[i].tag = atol(val); Tag_FSet(&mapthings[i].tags, atol(val));
if (fastcmp(param, "x")) else if (fastcmp(param, "moreids"))
{
char* id = val;
while (id)
{
Tag_Add(&mapthings[i].tags, atol(id));
if ((id = strchr(id, ' ')))
id++;
}
}
else if (fastcmp(param, "x"))
mapthings[i].x = atol(val); mapthings[i].x = atol(val);
else if (fastcmp(param, "y")) else if (fastcmp(param, "y"))
mapthings[i].y = atol(val); mapthings[i].y = atol(val);
@ -1698,6 +1720,14 @@ static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
else if (fastcmp(param, "ambush") && fastcmp("true", val)) else if (fastcmp(param, "ambush") && fastcmp("true", val))
mapthings[i].options |= MTF_AMBUSH; mapthings[i].options |= MTF_AMBUSH;
else if (strlen(param) == 7 && fastncmp(param, "arg", 3) && fastncmp(param + 4, "str", 3))
{
size_t argnum = param[3] - '0';
if (argnum >= NUMMAPTHINGSTRINGARGS)
return;
mapthings[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(mapthings[i].stringargs[argnum], val, strlen(val) + 1);
}
else if (fastncmp(param, "arg", 3) && strlen(param) > 3) else if (fastncmp(param, "arg", 3) && strlen(param) > 3)
{ {
size_t argnum = atol(param + 3); size_t argnum = atol(param + 3);
@ -1705,14 +1735,6 @@ static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
return; return;
mapthings[i].args[argnum] = atol(val); mapthings[i].args[argnum] = atol(val);
} }
else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9)
{
size_t argnum = param[9] - '0';
if (argnum >= NUMMAPTHINGSTRINGARGS)
return;
mapthings[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(mapthings[i].stringargs[argnum], val, strlen(val) + 1);
}
} }
/** From a given position table, run a specified parser function through a {}-encapsuled text. /** From a given position table, run a specified parser function through a {}-encapsuled text.
@ -1829,7 +1851,7 @@ static void P_LoadTextmap(void)
sc->lightlevel = 255; sc->lightlevel = 255;
sc->special = 0; sc->special = 0;
sc->tag = 0; Tag_FSet(&sc->tags, 0);
sc->floor_xoffs = sc->floor_yoffs = 0; sc->floor_xoffs = sc->floor_yoffs = 0;
sc->ceiling_xoffs = sc->ceiling_yoffs = 0; sc->ceiling_xoffs = sc->ceiling_yoffs = 0;
@ -1847,6 +1869,7 @@ static void P_LoadTextmap(void)
textmap_colormap.fadeend = 31; textmap_colormap.fadeend = 31;
textmap_colormap.flags = 0; textmap_colormap.flags = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc); P_InitializeSector(sc);
if (textmap_colormap.used) if (textmap_colormap.used)
{ {
@ -1863,7 +1886,8 @@ static void P_LoadTextmap(void)
ld->v1 = ld->v2 = NULL; ld->v1 = ld->v2 = NULL;
ld->flags = 0; ld->flags = 0;
ld->special = 0; ld->special = 0;
ld->tag = 0; Tag_FSet(&ld->tags, 0);
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
ld->alpha = FRACUNIT; ld->alpha = FRACUNIT;
@ -1911,8 +1935,8 @@ static void P_LoadTextmap(void)
mt->options = 0; mt->options = 0;
mt->z = 0; mt->z = 0;
mt->extrainfo = 0; mt->extrainfo = 0;
Tag_FSet(&mt->tags, 0);
mt->scale = FRACUNIT; mt->scale = FRACUNIT;
mt->tag = 0;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL; mt->mobj = NULL;
@ -2080,9 +2104,6 @@ static boolean P_LoadMapData(const virtres_t *virt)
static void P_InitializeSubsector(subsector_t *ss) static void P_InitializeSubsector(subsector_t *ss)
{ {
ss->sector = NULL; ss->sector = NULL;
#ifdef FLOORSPLATS
ss->splats = NULL;
#endif
ss->validcount = 0; ss->validcount = 0;
} }
@ -2127,7 +2148,7 @@ static void P_LoadNodes(UINT8 *data)
* \param seg Seg to compute length for. * \param seg Seg to compute length for.
* \return Length in fracunits. * \return Length in fracunits.
*/ */
fixed_t P_SegLength(seg_t *seg) static fixed_t P_SegLength(seg_t *seg)
{ {
INT64 dx = (seg->v2->x - seg->v1->x)>>1; INT64 dx = (seg->v2->x - seg->v1->x)>>1;
INT64 dy = (seg->v2->y - seg->v1->y)>>1; INT64 dy = (seg->v2->y - seg->v1->y)>>1;
@ -2401,6 +2422,10 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y);
if (seg->linedef) if (seg->linedef)
segs[i].offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y); segs[i].offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y);
seg->length = P_SegLength(seg);
#ifdef HWRENDER
seg->flength = (rendermode == render_opengl) ? P_SegLengthFloat(seg) : 0;
#endif
} }
return true; return true;
@ -2925,30 +2950,6 @@ static void P_LinkMapData(void)
} }
} }
/** Hashes the sector tags across the sectors and linedefs.
*
* \sa P_FindSectorFromTag, P_ChangeSectorTag
* \author Lee Killough
*/
static inline void P_InitTagLists(void)
{
register size_t i;
for (i = numsectors - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)sectors[i].tag % numsectors;
sectors[i].nexttag = sectors[j].firsttag;
sectors[j].firsttag = (INT32)i;
}
for (i = numlines - 1; i != (size_t)-1; i--)
{
size_t j = (unsigned)lines[i].tag % numlines;
lines[i].nexttag = lines[j].firsttag;
lines[j].firsttag = (INT32)i;
}
}
//For maps in binary format, converts setup of specials to UDMF format. //For maps in binary format, converts setup of specials to UDMF format.
static void P_ConvertBinaryMap(void) static void P_ConvertBinaryMap(void)
{ {
@ -2956,14 +2957,28 @@ static void P_ConvertBinaryMap(void)
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
{ {
mtag_t tag = Tag_FGet(&lines[i].tags);
switch (lines[i].special) switch (lines[i].special)
{ {
case 20: //PolyObject first line case 20: //PolyObject first line
{ {
INT32 paramline = P_FindSpecialLineFromTag(22, lines[i].tag, -1); INT32 check = -1;
INT32 paramline = -1;
TAG_ITER_DECLARECOUNTER(0);
TAG_ITER_LINES(0, tag, check)
{
if (lines[check].special == 22)
{
paramline = check;
break;
}
}
//PolyObject ID //PolyObject ID
lines[i].args[0] = lines[i].tag; lines[i].args[0] = tag;
//Default: Invisible planes //Default: Invisible planes
lines[i].args[3] |= TMPF_INVISIBLEPLANES; lines[i].args[3] |= TMPF_INVISIBLEPLANES;
@ -3009,7 +3024,7 @@ static void P_ConvertBinaryMap(void)
CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i)); CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i));
break; break;
case 447: //Change colormap case 447: //Change colormap
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
if (lines[i].flags & ML_EFFECT3) if (lines[i].flags & ML_EFFECT3)
lines[i].args[2] |= TMCF_RELATIVE; lines[i].args[2] |= TMCF_RELATIVE;
if (lines[i].flags & ML_EFFECT1) if (lines[i].flags & ML_EFFECT1)
@ -3025,7 +3040,7 @@ static void P_ConvertBinaryMap(void)
abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS) abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS)
: abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS)); : abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS));
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
if (lines[i].flags & ML_EFFECT4) if (lines[i].flags & ML_EFFECT4)
lines[i].args[2] = speed; lines[i].args[2] = speed;
else else
@ -3045,10 +3060,10 @@ static void P_ConvertBinaryMap(void)
break; break;
} }
case 456: //Stop fading colormap case 456: //Stop fading colormap
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
break; break;
case 606: //Colormap case 606: //Colormap
lines[i].args[0] = lines[i].tag; lines[i].args[0] = Tag_FGet(&lines[i].tags);
break; break;
case 700: //Slope front sector floor case 700: //Slope front sector floor
case 701: //Slope front sector ceiling case 701: //Slope front sector ceiling
@ -3089,7 +3104,7 @@ static void P_ConvertBinaryMap(void)
else if (lines[i].special == 715) else if (lines[i].special == 715)
lines[i].args[0] = TMSP_BACKCEILING; lines[i].args[0] = TMSP_BACKCEILING;
lines[i].args[1] = lines[i].tag; lines[i].args[1] = tag;
if (lines[i].flags & ML_EFFECT6) if (lines[i].flags & ML_EFFECT6)
{ {
@ -3121,9 +3136,9 @@ static void P_ConvertBinaryMap(void)
case 721: //Copy front side ceiling slope case 721: //Copy front side ceiling slope
case 722: //Copy front side floor and ceiling slope case 722: //Copy front side floor and ceiling slope
if (lines[i].special != 721) if (lines[i].special != 721)
lines[i].args[0] = lines[i].tag; lines[i].args[0] = tag;
if (lines[i].special != 720) if (lines[i].special != 720)
lines[i].args[1] = lines[i].tag; lines[i].args[1] = tag;
lines[i].special = 720; lines[i].special = 720;
break; break;
case 900: //Translucent wall (10%) case 900: //Translucent wall (10%)
@ -3156,21 +3171,39 @@ static void P_ConvertBinaryMap(void)
switch (mapthings[i].type) switch (mapthings[i].type)
{ {
case 750: case 750:
Tag_Add(&mapthings[i].tags, mapthings[i].angle);
break;
case 760: case 760:
case 761: case 761:
mapthings[i].tag = mapthings[i].angle; Tag_FSet(&mapthings[i].tags, mapthings[i].angle);
break; break;
case 762: case 762:
{ {
INT32 firstline = P_FindSpecialLineFromTag(20, mapthings[i].angle, -1); INT32 check = -1;
INT32 firstline = -1;
mtag_t tag = mapthings[i].angle;
TAG_ITER_DECLARECOUNTER(0);
Tag_FSet(&mapthings[i].tags, tag);
TAG_ITER_LINES(0, tag, check)
{
if (lines[check].special == 20)
{
firstline = check;
break;
}
}
if (firstline != -1) if (firstline != -1)
lines[firstline].args[3] |= TMPF_CRUSH; lines[firstline].args[3] |= TMPF_CRUSH;
mapthings[i].tag = mapthings[i].angle;
mapthings[i].type = 761; mapthings[i].type = 761;
break; break;
} }
case 780: case 780:
mapthings[i].tag = mapthings[i].extrainfo; Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo);
break; break;
default: default:
break; break;
@ -3244,6 +3277,7 @@ static boolean P_LoadMapFromFile(void)
{ {
virtres_t *virt = vres_GetMap(lastloadedmaplumpnum); virtres_t *virt = vres_GetMap(lastloadedmaplumpnum);
virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
size_t i;
udmf = textmap != NULL; udmf = textmap != NULL;
if (!P_LoadMapData(virt)) if (!P_LoadMapData(virt))
@ -3253,7 +3287,7 @@ static boolean P_LoadMapFromFile(void)
P_LinkMapData(); P_LinkMapData();
P_InitTagLists(); // Create xref tables for tags Taglist_InitGlobalTables();
if (!udmf) if (!udmf)
P_ConvertBinaryMap(); P_ConvertBinaryMap();
@ -3267,6 +3301,10 @@ static boolean P_LoadMapFromFile(void)
memcpy(spawnlines, lines, numlines * sizeof(*lines)); memcpy(spawnlines, lines, numlines * sizeof(*lines));
memcpy(spawnsides, sides, numsides * sizeof(*sides)); memcpy(spawnsides, sides, numsides * sizeof(*sides));
for (i = 0; i < numsectors; i++)
if (sectors[i].tags.count)
spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t));
P_MakeMapMD5(virt, &mapmd5); P_MakeMapMD5(virt, &mapmd5);
vres_Free(virt); vres_Free(virt);
@ -3315,8 +3353,6 @@ static void P_InitLevelSettings(void)
leveltime = 0; leveltime = 0;
localaiming = 0;
localaiming2 = 0;
modulothing = 0; modulothing = 0;
// special stage tokens, emeralds, and ring total // special stage tokens, emeralds, and ring total
@ -3431,6 +3467,9 @@ void P_RespawnThings(void)
P_InitLevelSettings(); P_InitLevelSettings();
localaiming = 0;
localaiming2 = 0;
P_SpawnMapThings(true); P_SpawnMapThings(true);
// restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that // restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that
@ -3938,7 +3977,7 @@ static void P_InitGametype(void)
* \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot. * \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot.
* \todo Clean up, refactor, split up; get rid of the bloat. * \todo Clean up, refactor, split up; get rid of the bloat.
*/ */
boolean P_LoadLevel(boolean fromnetsave) boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
{ {
// use gamemap to get map number. // use gamemap to get map number.
// 99% of the things already did, so. // 99% of the things already did, so.
@ -4008,7 +4047,10 @@ boolean P_LoadLevel(boolean fromnetsave)
players[consoleplayer].viewz = 1; players[consoleplayer].viewz = 1;
// Cancel all d_main.c fadeouts (keep fade in though). // Cancel all d_main.c fadeouts (keep fade in though).
wipegamestate = FORCEWIPEOFF; if (reloadinggamestate)
wipegamestate = gamestate; // Don't fade if reloading the gamestate
else
wipegamestate = FORCEWIPEOFF;
wipestyleflags = 0; wipestyleflags = 0;
// Special stage & record attack retry fade to white // Special stage & record attack retry fade to white
@ -4034,18 +4076,20 @@ boolean P_LoadLevel(boolean fromnetsave)
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0. // Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug. // But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
if (!titlemapinaction && (RESETMUSIC || if (!(reloadinggamestate || titlemapinaction) && (RESETMUSIC ||
strnicmp(S_MusicName(), strnicmp(S_MusicName(),
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7))) (mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)))
{
S_FadeMusic(0, FixedMul( S_FadeMusic(0, FixedMul(
FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)); FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE));
}
// Let's fade to black here // Let's fade to black here
// But only if we didn't do the special stage wipe // But only if we didn't do the special stage wipe
if (rendermode != render_none && !ranspecialwipe) if (rendermode != render_none && !(ranspecialwipe || reloadinggamestate))
P_RunLevelWipe(); P_RunLevelWipe();
if (!titlemapinaction) if (!(reloadinggamestate || titlemapinaction))
{ {
if (ranspecialwipe == 2) if (ranspecialwipe == 2)
{ {
@ -4089,13 +4133,16 @@ boolean P_LoadLevel(boolean fromnetsave)
// Clear pointers that would be left dangling by the purge // Clear pointers that would be left dangling by the purge
R_FlushTranslationColormapCache(); R_FlushTranslationColormapCache();
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); #ifdef HWRENDER
// Free GPU textures before freeing patches.
#if defined (WALLSPLATS) || defined (FLOORSPLATS) if (vid.glstate == VID_GL_LIBRARY_LOADED)
// clear the splats from previous level HWR_ClearAllTextures();
R_ClearLevelSplats();
#endif #endif
Patch_FreeTag(PU_PATCH_LOWPRIORITY);
Patch_FreeTag(PU_PATCH_ROTATED);
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);
P_InitThinkers(); P_InitThinkers();
P_InitCachedActions(); P_InitCachedActions();
@ -4152,14 +4199,14 @@ boolean P_LoadLevel(boolean fromnetsave)
P_SpawnPrecipitation(); P_SpawnPrecipitation();
#ifdef HWRENDER // not win32 only 19990829 by Kin #ifdef HWRENDER // not win32 only 19990829 by Kin
gl_maploaded = false;
// Lactozilla: Free extrasubsectors regardless of renderer. // Lactozilla: Free extrasubsectors regardless of renderer.
// Maybe we're not in OpenGL anymore. HWR_FreeExtraSubsectors();
if (extrasubsectors)
free(extrasubsectors); // Create plane polygons.
extrasubsectors = NULL;
// stuff like HWR_CreatePlanePolygons is called there
if (rendermode == render_opengl) if (rendermode == render_opengl)
HWR_SetupLevel(); HWR_LoadLevel();
#endif #endif
// oh god I hope this helps // oh god I hope this helps
@ -4170,7 +4217,12 @@ boolean P_LoadLevel(boolean fromnetsave)
if (!fromnetsave) if (!fromnetsave)
P_InitGametype(); P_InitGametype();
P_InitCamera(); if (!reloadinggamestate)
{
P_InitCamera();
localaiming = 0;
localaiming2 = 0;
}
// clear special respawning que // clear special respawning que
iquehead = iquetail = 0; iquehead = iquetail = 0;
@ -4178,7 +4230,7 @@ boolean P_LoadLevel(boolean fromnetsave)
P_MapEnd(); P_MapEnd();
// Remove the loading shit from the screen // Remove the loading shit from the screen
if (rendermode != render_none && !titlemapinaction) if (rendermode != render_none && !(titlemapinaction || reloadinggamestate))
F_WipeColorFill(levelfadecol); F_WipeColorFill(levelfadecol);
if (precache || dedicated) if (precache || dedicated)
@ -4222,8 +4274,8 @@ boolean P_LoadLevel(boolean fromnetsave)
LUAh_MapLoad(); LUAh_MapLoad();
} }
// No render mode, stop here. // No render mode or reloading gamestate, stop here.
if (rendermode == render_none) if (rendermode == render_none || reloadinggamestate)
return true; return true;
// Title card! // Title card!
@ -4241,33 +4293,6 @@ boolean P_LoadLevel(boolean fromnetsave)
return true; return true;
} }
#ifdef HWRENDER
void HWR_SetupLevel(void)
{
// Lactozilla (December 8, 2019)
// Level setup used to free EVERY mipmap from memory.
// Even mipmaps that aren't related to level textures.
// Presumably, the hardware render code used to store textures as level data.
// Meaning, they had memory allocated and marked with the PU_LEVEL tag.
// Level textures are only reloaded after R_LoadTextures, which is
// when the texture list is loaded.
// Sal: Unfortunately, NOT freeing them causes the dreaded Color Bug.
HWR_FreeMipmapCache();
#ifdef ALAM_LIGHTING
// BP: reset light between levels (we draw preview frame lights on current frame)
HWR_ResetLights();
#endif
HWR_CreatePlanePolygons((INT32)numnodes - 1);
// Build the sky dome
HWR_ClearSkyDome();
HWR_BuildSkyDome();
}
#endif
// //
// P_RunSOC // P_RunSOC
// //
@ -4473,10 +4498,17 @@ boolean P_AddWadFile(const char *wadfilename)
if (!devparm && digmreplaces) if (!devparm && digmreplaces)
CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces)); CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces));
#ifdef HWRENDER
// Free GPU textures before freeing patches.
if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWR_ClearAllTextures();
#endif
// //
// search for sprite replacements // search for sprite replacements
// //
Patch_FreeTag(PU_SPRITE);
Patch_FreeTag(PU_PATCH_ROTATED);
R_AddSpriteDefs(wadnum); R_AddSpriteDefs(wadnum);
// Reload it all anyway, just in case they // Reload it all anyway, just in case they

View File

@ -97,15 +97,15 @@ void P_SetupLevelSky(INT32 skynum, boolean global);
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
#endif #endif
void P_RespawnThings(void); void P_RespawnThings(void);
boolean P_LoadLevel(boolean fromnetsave); boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
#ifdef HWRENDER #ifdef HWRENDER
void HWR_SetupLevel(void); void HWR_LoadLevel(void);
#endif #endif
boolean P_AddWadFile(const char *wadfilename); boolean P_AddWadFile(const char *wadfilename);
boolean P_RunSOC(const char *socfilename); boolean P_RunSOC(const char *socfilename);
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
void P_WriteThings(lumpnum_t lump); void P_WriteThings(void);
size_t P_PrecacheLevelFlats(void); size_t P_PrecacheLevelFlats(void);
void P_AllocMapHeader(INT16 i); void P_AllocMapHeader(INT16 i);

View File

@ -139,7 +139,7 @@ void T_DynamicSlopeVert (dynplanethink_t* th)
INT32 l; INT32 l;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
l = P_FindSpecialLineFromTag(799, th->tags[i], -1); l = Tag_FindLineSpecial(799, th->tags[i]);
if (l != -1) { if (l != -1) {
th->vex[i].z = lines[l].frontsector->floorheight; th->vex[i].z = lines[l].frontsector->floorheight;
} }
@ -405,9 +405,6 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL); P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL);
} }
} }
if(!line->tag)
return;
} }
/// Creates a new slope from three mapthings with the specified IDs /// Creates a new slope from three mapthings with the specified IDs
@ -426,11 +423,11 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something! if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
continue; continue;
if (!vertices[0] && mt->tag == tag1) if (!vertices[0] && Tag_Find(&mt->tags, tag1))
vertices[0] = mt; vertices[0] = mt;
else if (!vertices[1] && mt->tag == tag2) else if (!vertices[1] && Tag_Find(&mt->tags, tag2))
vertices[1] = mt; vertices[1] = mt;
else if (!vertices[2] && mt->tag == tag3) else if (!vertices[2] && Tag_Find(&mt->tags, tag3))
vertices[2] = mt; vertices[2] = mt;
} }
@ -549,11 +546,11 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling)
{ {
INT32 i; INT32 i;
pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope; pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope;
TAG_ITER_DECLARECOUNTER(0);
if (!tag || *secslope) if (!tag || *secslope)
return false; return false;
TAG_ITER_SECTORS(0, tag, i)
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0;)
{ {
pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope; pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope;
if (srcslope) if (srcslope)

File diff suppressed because it is too large Load Diff

View File

@ -55,9 +55,6 @@ fixed_t P_FindNextLowestFloor(sector_t *sec, fixed_t currentheight);
fixed_t P_FindLowestCeilingSurrounding(sector_t *sec); fixed_t P_FindLowestCeilingSurrounding(sector_t *sec);
fixed_t P_FindHighestCeilingSurrounding(sector_t *sec); fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
INT32 P_FindSectorFromTag(INT16 tag, INT32 start);
INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start);
INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max); INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
void P_SetupSignExit(player_t *player); void P_SetupSignExit(player_t *player);
@ -67,7 +64,6 @@ void P_SwitchWeather(INT32 weathernum);
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
void P_ChangeSectorTag(UINT32 sector, INT16 newtag);
void P_RunNightserizeExecutors(mobj_t *actor); void P_RunNightserizeExecutors(mobj_t *actor);
void P_RunDeNightserizeExecutors(mobj_t *actor); void P_RunDeNightserizeExecutors(mobj_t *actor);
void P_RunNightsLapExecutors(mobj_t *actor); void P_RunNightsLapExecutors(mobj_t *actor);

View File

@ -22,7 +22,7 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_hook.h" #include "lua_hook.h"
#include "m_perfstats.h" #include "m_perfstats.h"
#include "i_system.h" // I_GetTimeMicros #include "i_system.h" // I_GetPreciseTime
// Object place // Object place
#include "m_cheat.h" #include "m_cheat.h"
@ -323,7 +323,7 @@ static inline void P_RunThinkers(void)
size_t i; size_t i;
for (i = 0; i < NUM_THINKERLISTS; i++) for (i = 0; i < NUM_THINKERLISTS; i++)
{ {
ps_thlist_times[i] = I_GetTimeMicros(); ps_thlist_times[i] = I_GetPreciseTime();
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
{ {
#ifdef PARANOIA #ifdef PARANOIA
@ -331,7 +331,7 @@ static inline void P_RunThinkers(void)
#endif #endif
currentthinker->function.acp1(currentthinker); currentthinker->function.acp1(currentthinker);
} }
ps_thlist_times[i] = I_GetTimeMicros() - ps_thlist_times[i]; ps_thlist_times[i] = I_GetPreciseTime() - ps_thlist_times[i];
} }
} }
@ -643,18 +643,26 @@ void P_Ticker(boolean run)
if (demorecording) if (demorecording)
G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0); G_WriteDemoTiccmd(&players[consoleplayer].cmd, 0);
if (demoplayback) if (demoplayback)
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0); {
player_t* p = &players[consoleplayer];
G_ReadDemoTiccmd(&p->cmd, 0);
if (!cv_freedemocamera.value)
{
P_ForceLocalAngle(p, p->cmd.angleturn << 16);
localaiming = p->aiming;
}
}
ps_lua_mobjhooks = 0; ps_lua_mobjhooks = 0;
ps_checkposition_calls = 0; ps_checkposition_calls = 0;
LUAh_PreThinkFrame(); LUAh_PreThinkFrame();
ps_playerthink_time = I_GetTimeMicros(); ps_playerthink_time = I_GetPreciseTime();
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerThink(&players[i]); P_PlayerThink(&players[i]);
ps_playerthink_time = I_GetTimeMicros() - ps_playerthink_time; ps_playerthink_time = I_GetPreciseTime() - ps_playerthink_time;
} }
// Keep track of how long they've been playing! // Keep track of how long they've been playing!
@ -669,18 +677,18 @@ void P_Ticker(boolean run)
if (run) if (run)
{ {
ps_thinkertime = I_GetTimeMicros(); ps_thinkertime = I_GetPreciseTime();
P_RunThinkers(); P_RunThinkers();
ps_thinkertime = I_GetTimeMicros() - ps_thinkertime; ps_thinkertime = I_GetPreciseTime() - ps_thinkertime;
// Run any "after all the other thinkers" stuff // Run any "after all the other thinkers" stuff
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]); P_PlayerAfterThink(&players[i]);
ps_lua_thinkframe_time = I_GetTimeMicros(); ps_lua_thinkframe_time = I_GetPreciseTime();
LUAh_ThinkFrame(); LUAh_ThinkFrame();
ps_lua_thinkframe_time = I_GetTimeMicros() - ps_lua_thinkframe_time; ps_lua_thinkframe_time = I_GetPreciseTime() - ps_lua_thinkframe_time;
} }
// Run shield positioning // Run shield positioning

View File

@ -1341,7 +1341,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
// Transformation animation // Transformation animation
P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS1); P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS1);
if (giverings) if (giverings && player->rings < 50)
player->rings = 50; player->rings = 50;
// Just in case. // Just in case.
@ -1491,10 +1491,10 @@ void P_PlayLivesJingle(player_t *player)
if (player && !P_IsLocalPlayer(player)) if (player && !P_IsLocalPlayer(player))
return; return;
if (use1upSound || cv_1upsound.value) if (mariomode)
S_StartSound(NULL, sfx_oneup);
else if (mariomode)
S_StartSound(NULL, sfx_marioa); S_StartSound(NULL, sfx_marioa);
else if (use1upSound || cv_1upsound.value)
S_StartSound(NULL, sfx_oneup);
else else
{ {
P_PlayJingle(player, JT_1UP); P_PlayJingle(player, JT_1UP);
@ -2029,6 +2029,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->colorized = mobj->colorized; // alternatively, "true" for sonic advance style colourisation ghost->colorized = mobj->colorized; // alternatively, "true" for sonic advance style colourisation
ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle); ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle);
ghost->rollangle = mobj->rollangle;
ghost->sprite = mobj->sprite; ghost->sprite = mobj->sprite;
ghost->sprite2 = mobj->sprite2; ghost->sprite2 = mobj->sprite2;
ghost->frame = mobj->frame; ghost->frame = mobj->frame;
@ -2328,7 +2329,8 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
P_MobjCheckWater(player->mo); P_MobjCheckWater(player->mo);
if (player->pflags & PF_SPINNING) if (player->pflags & PF_SPINNING)
{ {
if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) if (!(player->pflags & PF_STARTDASH) && player->panim != PA_ROLL && player->panim != PA_ETC
&& player->panim != PA_ABILITY && player->panim != PA_ABILITY2)
{ {
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_spin); S_StartSound(player->mo, sfx_spin);
@ -2564,7 +2566,7 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover)
} }
// Strong abilities can break even FF_STRONGBUST. // Strong abilities can break even FF_STRONGBUST.
if (player->charability == CA_GLIDEANDCLIMB) if (player->charflags & SF_CANBUSTWALLS)
return true; return true;
if (player->pflags & PF_BOUNCING) if (player->pflags & PF_BOUNCING)
@ -3214,7 +3216,7 @@ static void P_DoClimbing(player_t *player)
for (rover = glidesector->sector->ffloors; rover; rover = rover->next) for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
{ {
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || ((rover->flags & FF_BUSTUP) && (player->charflags & SF_CANBUSTWALLS)))
continue; continue;
floorclimb = true; floorclimb = true;
@ -3255,7 +3257,7 @@ static void P_DoClimbing(player_t *player)
// Is there a FOF directly below this one that we can move onto? // Is there a FOF directly below this one that we can move onto?
for (roverbelow = glidesector->sector->ffloors; roverbelow; roverbelow = roverbelow->next) for (roverbelow = glidesector->sector->ffloors; roverbelow; roverbelow = roverbelow->next)
{ {
if (!(roverbelow->flags & FF_EXISTS) || !(roverbelow->flags & FF_BLOCKPLAYER) || (roverbelow->flags & FF_BUSTUP)) if (!(roverbelow->flags & FF_EXISTS) || !(roverbelow->flags & FF_BLOCKPLAYER) || ((rover->flags & FF_BUSTUP) && (player->charflags & SF_CANBUSTWALLS)))
continue; continue;
if (roverbelow == rover) if (roverbelow == rover)
@ -3300,7 +3302,7 @@ static void P_DoClimbing(player_t *player)
// Is there a FOF directly below this one that we can move onto? // Is there a FOF directly below this one that we can move onto?
for (roverbelow = glidesector->sector->ffloors; roverbelow; roverbelow = roverbelow->next) for (roverbelow = glidesector->sector->ffloors; roverbelow; roverbelow = roverbelow->next)
{ {
if (!(roverbelow->flags & FF_EXISTS) || !(roverbelow->flags & FF_BLOCKPLAYER) || (roverbelow->flags & FF_BUSTUP)) if (!(roverbelow->flags & FF_EXISTS) || !(roverbelow->flags & FF_BLOCKPLAYER) || ((rover->flags & FF_BUSTUP) && (player->charflags & SF_CANBUSTWALLS)))
continue; continue;
if (roverbelow == rover) if (roverbelow == rover)
@ -3357,7 +3359,7 @@ static void P_DoClimbing(player_t *player)
ffloor_t *rover; ffloor_t *rover;
for (rover = glidesector->sector->ffloors; rover; rover = rover->next) for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
{ {
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || ((rover->flags & FF_BUSTUP) && (player->charflags & SF_CANBUSTWALLS)))
continue; continue;
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y);
@ -3397,7 +3399,7 @@ static void P_DoClimbing(player_t *player)
ffloor_t *rover; ffloor_t *rover;
for (rover = glidesector->sector->ffloors; rover; rover = rover->next) for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
{ {
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || ((rover->flags & FF_BUSTUP) && (player->charflags & SF_CANBUSTWALLS)))
continue; continue;
topheight = P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y); topheight = P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y);
@ -4524,6 +4526,9 @@ void P_DoJump(player_t *player, boolean soundandstate)
player->pflags |= P_GetJumpFlags(player);; player->pflags |= P_GetJumpFlags(player);;
if (player->charflags & SF_NOJUMPDAMAGE)
player->pflags &= ~PF_SPINNING;
if (soundandstate) if (soundandstate)
{ {
if (!player->spectator) if (!player->spectator)
@ -4835,6 +4840,8 @@ void P_DoJumpShield(player_t *player)
} }
#undef limitangle #undef limitangle
#undef numangles #undef numangles
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k45); S_StartSound(player->mo, sfx_s3k45);
} }
else else
@ -5107,6 +5114,8 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale));
player->drawangle = player->mo->angle; player->drawangle = player->mo->angle;
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k43); S_StartSound(player->mo, sfx_s3k43);
default: default:
break; break;
@ -5915,7 +5924,7 @@ static void P_3dMovement(player_t *player)
player->rmomy = player->mo->momy - player->cmomy; player->rmomy = player->mo->momy - player->cmomy;
// Calculates player's speed based on distance-of-a-line formula // Calculates player's speed based on distance-of-a-line formula
player->speed = P_AproxDistance(player->rmomx, player->rmomy); player->speed = R_PointToDist2(0, 0, player->rmomx, player->rmomy);
// Monster Iestyn - 04-11-13 // Monster Iestyn - 04-11-13
// Quadrants are stupid, excessive and broken, let's do this a much simpler way! // Quadrants are stupid, excessive and broken, let's do this a much simpler way!
@ -8600,12 +8609,6 @@ void P_MovePlayer(player_t *player)
player->climbing--; player->climbing--;
} }
if (!player->climbing)
{
player->lastsidehit = -1;
player->lastlinehit = -1;
}
// Make sure you're not teetering when you shouldn't be. // Make sure you're not teetering when you shouldn't be.
if (player->panim == PA_EDGE if (player->panim == PA_EDGE
&& (player->mo->momx || player->mo->momy || player->mo->momz)) && (player->mo->momx || player->mo->momy || player->mo->momz))
@ -8630,6 +8633,7 @@ void P_MovePlayer(player_t *player)
P_DoFiring(player, cmd); P_DoFiring(player, cmd);
{ {
boolean atspinheight = false;
fixed_t oldheight = player->mo->height; fixed_t oldheight = player->mo->height;
// Less height while spinning. Good for spinning under things...? // Less height while spinning. Good for spinning under things...?
@ -8639,32 +8643,35 @@ void P_MovePlayer(player_t *player)
|| player->powers[pw_tailsfly] || player->pflags & PF_GLIDING || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING
|| (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING)
|| (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED))
{
player->mo->height = P_GetPlayerSpinHeight(player); player->mo->height = P_GetPlayerSpinHeight(player);
atspinheight = true;
}
else else
player->mo->height = P_GetPlayerHeight(player); player->mo->height = P_GetPlayerHeight(player);
if (player->mo->eflags & MFE_VERTICALFLIP && player->mo->height != oldheight) // adjust z height for reverse gravity, similar to how it's done for scaling if (player->mo->eflags & MFE_VERTICALFLIP && player->mo->height != oldheight) // adjust z height for reverse gravity, similar to how it's done for scaling
player->mo->z -= player->mo->height - oldheight; player->mo->z -= player->mo->height - oldheight;
}
// Crush test... // Crush test...
if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) if ((player->mo->ceilingz - player->mo->floorz < player->mo->height)
&& !(player->mo->flags & MF_NOCLIP)) && !(player->mo->flags & MF_NOCLIP))
{
if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SPINNING))
{ {
player->pflags |= PF_SPINNING; if (!atspinheight)
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); {
} player->pflags |= PF_SPINNING;
else if (player->mo->ceilingz - player->mo->floorz < player->mo->height) P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
{ }
if ((netgame || multiplayer) && player->spectator) else if (player->mo->ceilingz - player->mo->floorz < player->mo->height)
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators {
else if ((netgame || multiplayer) && player->spectator)
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators
else
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED);
if (player->playerstate == PST_DEAD) if (player->playerstate == PST_DEAD)
return; return;
}
} }
} }
@ -8691,12 +8698,6 @@ void P_MovePlayer(player_t *player)
player->fovadd = 0; player->fovadd = 0;
#endif #endif
#ifdef FLOORSPLATS
if (cv_shadow.value && rendermode == render_soft)
R_AddFloorSplat(player->mo->subsector, player->mo, "SHADOW", player->mo->x,
player->mo->y, player->mo->floorz, SPLATDRAWMODE_OPAQUE);
#endif
// Look for blocks to bust up // Look for blocks to bust up
// Because of FF_SHATTER, we should look for blocks constantly, // Because of FF_SHATTER, we should look for blocks constantly,
// not just when spinning or playing as Knuckles // not just when spinning or playing as Knuckles
@ -10578,6 +10579,7 @@ static void P_CalcPostImg(player_t *player)
postimg_t *type; postimg_t *type;
INT32 *param; INT32 *param;
fixed_t pviewheight; fixed_t pviewheight;
size_t i;
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
pviewheight = player->mo->z + player->mo->height - player->viewheight; pviewheight = player->mo->z + player->mo->height - player->viewheight;
@ -10602,28 +10604,45 @@ static void P_CalcPostImg(player_t *player)
} }
// see if we are in heat (no, not THAT kind of heat...) // see if we are in heat (no, not THAT kind of heat...)
for (i = 0; i < sector->tags.count; i++)
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
*type = postimg_heat;
else if (sector->ffloors)
{ {
ffloor_t *rover; if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
fixed_t topheight;
fixed_t bottomheight;
for (rover = sector->ffloors; rover; rover = rover->next)
{ {
if (!(rover->flags & FF_EXISTS)) *type = postimg_heat;
continue; break;
}
else if (sector->ffloors)
{
ffloor_t *rover;
fixed_t topheight;
fixed_t bottomheight;
boolean gotres = false;
topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); for (rover = sector->ffloors; rover; rover = rover->next)
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); {
size_t j;
if (pviewheight >= topheight || pviewheight <= bottomheight) if (!(rover->flags & FF_EXISTS))
continue; continue;
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y);
*type = postimg_heat; bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y);
if (pviewheight >= topheight || pviewheight <= bottomheight)
continue;
for (j = 0; j < rover->master->frontsector->tags.count; j++)
{
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
{
*type = postimg_heat;
gotres = true;
break;
}
}
}
if (gotres)
break;
} }
} }
@ -10722,22 +10741,21 @@ static sector_t *P_GetMinecartSector(fixed_t x, fixed_t y, fixed_t z, fixed_t *n
static INT32 P_GetMinecartSpecialLine(sector_t *sec) static INT32 P_GetMinecartSpecialLine(sector_t *sec)
{ {
INT32 line = -1; INT32 line = -1;
size_t i;
if (!sec) if (!sec)
return line; return line;
if (sec->tag != 0) for (i = 0; i < sec->tags.count; i++)
line = P_FindSpecialLineFromTag(16, sec->tag, -1); if (sec->tags.tags[i] != 0)
line = Tag_FindLineSpecial(16, sec->tags.tags[i]);
// Also try for lines facing the sector itself, with tag 0. // Also try for lines facing the sector itself, with tag 0.
for (i = 0; i < sec->linecount; i++)
{ {
UINT32 i; line_t *li = sec->lines[i];
for (i = 0; i < sec->linecount; i++) if (Tag_Find(&li->tags, 0) && li->special == 16 && li->frontsector == sec)
{ line = li - lines;
line_t *li = sec->lines[i];
if (li->tag == 0 && li->special == 16 && li->frontsector == sec)
line = li - lines;
}
} }
return line; return line;
@ -11206,6 +11224,8 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails)
chosenstate = S_TAILSOVERLAY_GASP; chosenstate = S_TAILSOVERLAY_GASP;
else if (player->mo->state-states == S_PLAY_EDGE) else if (player->mo->state-states == S_PLAY_EDGE)
chosenstate = S_TAILSOVERLAY_EDGE; chosenstate = S_TAILSOVERLAY_EDGE;
else if (player->panim == PA_DASH)
chosenstate = S_TAILSOVERLAY_DASH;
else if (player->panim == PA_RUN) else if (player->panim == PA_RUN)
chosenstate = S_TAILSOVERLAY_RUN; chosenstate = S_TAILSOVERLAY_RUN;
else if (player->panim == PA_WALK) else if (player->panim == PA_WALK)
@ -11464,7 +11484,6 @@ void P_PlayerThink(player_t *player)
} }
} }
#ifdef SEENAMES
if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5))) if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5)))
{ {
seenplayer = NULL; seenplayer = NULL;
@ -11489,7 +11508,6 @@ void P_PlayerThink(player_t *player)
} }
} }
} }
#endif
if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj))
{ {
@ -12294,12 +12312,14 @@ void P_PlayerThink(player_t *player)
sector_t *controlsec; sector_t *controlsec;
for (j=0; j<numsectors; j++) for (j=0; j<numsectors; j++)
{ {
mtag_t sectag = Tag_FGet(&sectors[j].tags);
controlsec = NULL; controlsec = NULL;
// Does this sector have a water linedef? // Does this sector have a water linedef?
for (i=0; i<numlines;i++) for (i=0; i<numlines;i++)
{ {
mtag_t linetag = Tag_FGet(&lines[i].tags);
if ((lines[i].special == 121 || lines[i].special == 123) if ((lines[i].special == 121 || lines[i].special == 123)
&& lines[i].tag == sectors[j].tag) && linetag == sectag)
{ {
controlsec = lines[i].frontsector; controlsec = lines[i].frontsector;
break; break;
@ -12308,15 +12328,16 @@ void P_PlayerThink(player_t *player)
if (i < numlines && controlsec) if (i < numlines && controlsec)
{ {
controlsectag = Tag_FGet(&controlsec->tags);
// Does this sector have a colormap? // Does this sector have a colormap?
for (i=0; i<numlines;i++) for (i=0; i<numlines;i++)
{ {
if (lines[i].special == 606 && lines[i].tag == controlsec->tag) if (lines[i].special == 606 && linetag == controlsectag)
break; break;
} }
if (i == numlines) if (i == numlines)
CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectors[j].tag); CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectag);
} }
} }
@ -12557,13 +12578,16 @@ void P_PlayerAfterThink(player_t *player)
player->powers[pw_carry] = CR_NONE; player->powers[pw_carry] = CR_NONE;
else else
{ {
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); if (tails->player)
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true);
else
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->angle, 4*FRACUNIT), true);
player->mo->momx = tails->momx; player->mo->momx = tails->momx;
player->mo->momy = tails->momy; player->mo->momy = tails->momy;
player->mo->momz = tails->momz; player->mo->momz = tails->momz;
} }
if (G_CoopGametype() && (!tails->player || tails->player->bot != 1)) if (G_CoopGametype() && tails->player && tails->player->bot != 1)
{ {
player->mo->angle = tails->angle; player->mo->angle = tails->angle;
@ -12578,7 +12602,7 @@ void P_PlayerAfterThink(player_t *player)
{ {
if (player->mo->state-states != S_PLAY_RIDE) if (player->mo->state-states != S_PLAY_RIDE)
P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); P_SetPlayerMobjState(player->mo, S_PLAY_RIDE);
if ((tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) if (tails->player && (tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER))
tails->player->powers[pw_tailsfly] = 0; tails->player->powers[pw_tailsfly] = 0;
} }
else else

View File

@ -21,6 +21,7 @@
#include "p_local.h" // camera #include "p_local.h" // camera
#include "p_slopes.h" #include "p_slopes.h"
#include "z_zone.h" // Check R_Prep3DFloors #include "z_zone.h" // Check R_Prep3DFloors
#include "taglist.h"
seg_t *curline; seg_t *curline;
side_t *sidedef; side_t *sidedef;
@ -374,7 +375,7 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
// Consider colormaps // Consider colormaps
&& back->extra_colormap == front->extra_colormap && back->extra_colormap == front->extra_colormap
&& ((!front->ffloors && !back->ffloors) && ((!front->ffloors && !back->ffloors)
|| front->tag == back->tag)); || Tag_Compare(&front->tags, &back->tags)));
} }
// //
@ -448,21 +449,25 @@ static void R_AddLine(seg_t *line)
// Portal line // Portal line
if (line->linedef->special == 40 && line->side == 0) if (line->linedef->special == 40 && line->side == 0)
{ {
// Render portal if recursiveness limit hasn't been reached.
// Otherwise, render the wall normally.
if (portalrender < cv_maxportals.value) if (portalrender < cv_maxportals.value)
{ {
// Find the other side! size_t p;
INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1); mtag_t tag = Tag_FGet(&line->linedef->tags);
if (line->linedef == &lines[line2]) INT32 li1 = line->linedef-lines;
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2); INT32 li2;
if (line2 >= 0) // found it!
for (p = 0; (li2 = Tag_Iterate_Lines(tag, p)) >= 0; p++)
{ {
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering // Skip invalid lines.
//return; // Don't fill in that space now! if ((tag != Tag_FGet(&lines[li2].tags)) || (lines[li1].special != lines[li2].special) || (li1 == li2))
continue;
Portal_Add2Lines(li1, li2, x1, x2);
goto clipsolid; goto clipsolid;
} }
} }
// Recursed TOO FAR (viewing a portal within a portal)
// So uhhh, render it as a normal wall instead or something ???
} }
// Single sided line? // Single sided line?
@ -483,7 +488,7 @@ static void R_AddLine(seg_t *line)
if (!line->polyseg && if (!line->polyseg &&
!line->sidedef->midtexture !line->sidedef->midtexture
&& ((!frontsector->ffloors && !backsector->ffloors) && ((!frontsector->ffloors && !backsector->ffloors)
|| (frontsector->tag == backsector->tag))) || Tag_Compare(&frontsector->tags, &backsector->tags)))
return; // line is empty, don't even bother return; // line is empty, don't even bother
goto clippass; // treat like wide open window instead goto clippass; // treat like wide open window instead
@ -1048,11 +1053,6 @@ static void R_Subsector(size_t num)
} }
} }
#ifdef FLOORSPLATS
if (sub->splats)
R_AddVisibleFloorSplats(sub);
#endif
// killough 9/18/98: Fix underwater slowdown, by passing real sector // killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite // instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area. // lightlevels on floor & ceiling lightlevels in the surrounding area.

View File

@ -20,6 +20,7 @@
#include "m_misc.h" #include "m_misc.h"
#include "r_data.h" #include "r_data.h"
#include "r_textures.h" #include "r_textures.h"
#include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
@ -174,13 +175,15 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT
if (alpha <= ASTTextureBlendingThreshold[1]) if (alpha <= ASTTextureBlendingThreshold[1])
{ {
UINT8 *mytransmap; UINT8 *mytransmap;
INT32 trans;
// Is the patch way too translucent? Don't blend then. // Is the patch way too translucent? Don't blend then.
if (alpha < ASTTextureBlendingThreshold[0]) if (alpha < ASTTextureBlendingThreshold[0])
return background; return background;
// The equation's not exact but it works as intended. I'll call it a day for now. // The equation's not exact but it works as intended. I'll call it a day for now.
mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); trans = (8*(alpha) + 255/8)/(255 - 255/11);
mytransmap = R_GetTranslucencyTable(trans + 1);
if (background != 0xFF) if (background != 0xFF)
return *(mytransmap + (background<<8) + foreground); return *(mytransmap + (background<<8) + foreground);
} }
@ -1307,7 +1310,7 @@ void R_PrecacheLevel(void)
lump = sf->lumppat[a];\ lump = sf->lumppat[a];\
if (devparm)\ if (devparm)\
spritememory += W_LumpLength(lump);\ spritememory += W_LumpLength(lump);\
W_CachePatchNum(lump, PU_PATCH);\ W_CachePatchNum(lump, PU_SPRITE);\
} }
// see R_InitSprites for more about lumppat,lumpid // see R_InitSprites for more about lumppat,lumpid
switch (sf->rotate) switch (sf->rotate)

View File

@ -28,6 +28,8 @@
#include "m_aatree.h" #include "m_aatree.h"
#endif #endif
#include "taglist.h"
// //
// ClipWallSegment // ClipWallSegment
// Clips the given range of columns // Clips the given range of columns
@ -281,8 +283,7 @@ typedef struct sector_s
INT32 ceilingpic; INT32 ceilingpic;
INT16 lightlevel; INT16 lightlevel;
INT16 special; INT16 special;
UINT16 tag; taglist_t tags;
INT32 nexttag, firsttag; // for fast tag searches
// origin for any sounds played by the sector // origin for any sounds played by the sector
// also considered the center for e.g. Mario blocks // also considered the center for e.g. Mario blocks
@ -389,7 +390,7 @@ typedef struct line_s
// Animation related. // Animation related.
INT16 flags; INT16 flags;
INT16 special; INT16 special;
INT16 tag; taglist_t tags;
INT32 args[NUMLINEARGS]; INT32 args[NUMLINEARGS];
char *stringargs[NUMLINESTRINGARGS]; char *stringargs[NUMLINESTRINGARGS];
@ -409,10 +410,6 @@ typedef struct line_s
sector_t *backsector; sector_t *backsector;
size_t validcount; // if == validcount, already checked size_t validcount; // if == validcount, already checked
#if 1//#ifdef WALLSPLATS
void *splats; // wallsplat_t list
#endif
INT32 firsttag, nexttag; // improves searches for tags.
polyobj_t *polyobj; // Belongs to a polyobject? polyobj_t *polyobj; // Belongs to a polyobject?
char *text; // a concatenation of all front and back texture names, for linedef specials that require a string. char *text; // a concatenation of all front and back texture names, for linedef specials that require a string.
@ -457,9 +454,6 @@ typedef struct subsector_s
INT16 numlines; INT16 numlines;
UINT16 firstline; UINT16 firstline;
struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects
#if 1//#ifdef FLOORSPLATS
void *splats; // floorsplat_t list
#endif
size_t validcount; size_t validcount;
} subsector_t; } subsector_t;
@ -652,8 +646,12 @@ typedef enum
RGBA32 = 4, // 32 bit rgba RGBA32 = 4, // 32 bit rgba
} pic_mode_t; } pic_mode_t;
#if defined(_MSC_VER) #ifdef ROTSPRITE
#pragma pack(1) typedef struct
{
INT32 angles;
void **patches;
} rotsprite_t;
#endif #endif
// Patches. // Patches.
@ -661,7 +659,26 @@ typedef enum
// Patches are used for sprites and all masked pictures, and we compose // Patches are used for sprites and all masked pictures, and we compose
// textures from the TEXTURES list of patches. // textures from the TEXTURES list of patches.
// //
// WARNING: this structure is cloned in GLPatch_t typedef struct
{
INT16 width, height;
INT16 leftoffset, topoffset;
INT32 *columnofs; // Column offsets. This is relative to patch->columns
UINT8 *columns; // Software column data
void *hardware; // OpenGL patch, allocated whenever necessary
void *flats[4]; // The patch as flats
#ifdef ROTSPRITE
rotsprite_t *rotated; // Rotated patches
#endif
} patch_t;
#if defined(_MSC_VER)
#pragma pack(1)
#endif
typedef struct typedef struct
{ {
INT16 width; // bounding box size INT16 width; // bounding box size
@ -670,7 +687,7 @@ typedef struct
INT16 topoffset; // pixels below the origin INT16 topoffset; // pixels below the origin
INT32 columnofs[8]; // only [width] used INT32 columnofs[8]; // only [width] used
// the [0] is &columnofs[width] // the [0] is &columnofs[width]
} ATTRPACK patch_t; } ATTRPACK softwarepatch_t;
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4200) #pragma warning(disable : 4200)
@ -696,14 +713,32 @@ typedef struct
#pragma pack() #pragma pack()
#endif #endif
// rotsprite typedef enum
#ifdef ROTSPRITE
typedef struct
{ {
patch_t *patch[16][ROTANGLES]; RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally
UINT16 cached; RF_VERTICALFLIP = 0x0002, // Flip sprite vertically
} rotsprite_t; RF_ABSOLUTEOFFSETS = 0x0004, // Sprite uses the object's offsets absolutely, instead of relatively
#endif/*ROTSPRITE*/ RF_FLIPOFFSETS = 0x0008, // Relative object offsets are flipped with the sprite
RF_SPLATMASK = 0x00F0, // --Floor sprite flags
RF_SLOPESPLAT = 0x0010, // Rotate floor sprites by a slope
RF_OBJECTSLOPESPLAT = 0x0020, // Rotate floor sprites by the object's standing slope
RF_NOSPLATBILLBOARD = 0x0040, // Don't billboard floor sprites (faces forward from the view angle)
RF_NOSPLATROLLANGLE = 0x0080, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead)
RF_BLENDMASK = 0x0F00, // --Blending modes
RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness
RF_FULLDARK = 0x0200, // Sprite is drawn completely dark
RF_NOCOLORMAPS = 0x0400, // Sprite is not drawn with colormaps
RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types
RF_PAPERSPRITE = 0x1000, // Paper sprite
RF_FLOORSPRITE = 0x2000, // Floor sprite
RF_SHADOWDRAW = 0x10000, // Stretches and skews the sprite like a shadow.
RF_SHADOWEFFECTS = 0x20000, // Scales and becomes transparent like a shadow.
RF_DROPSHADOW = (RF_SHADOWDRAW | RF_SHADOWEFFECTS | RF_FULLDARK),
} renderflags_t;
typedef enum typedef enum
{ {
@ -717,24 +752,6 @@ typedef enum
SRF_NONE = 0xff // Initial value SRF_NONE = 0xff // Initial value
} spriterotateflags_t; // SRF's up! } spriterotateflags_t; // SRF's up!
// Same as a patch_t, except just the header
// and the wadnum/lumpnum combination that points
// to wherever the patch is in memory.
struct patchinfo_s
{
INT16 width; // bounding box size
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
UINT16 wadnum; // the software patch lump num for when the patch
UINT16 lumpnum; // was flushed, and we need to re-create it
// next patchinfo_t in memory
struct patchinfo_s *next;
};
typedef struct patchinfo_s patchinfo_t;
// //
// Sprites are patches with a special naming convention so they can be // Sprites are patches with a special naming convention so they can be
// recognized by R_InitSprites. // recognized by R_InitSprites.
@ -764,7 +781,7 @@ typedef struct
UINT16 flip; UINT16 flip;
#ifdef ROTSPRITE #ifdef ROTSPRITE
rotsprite_t rotsprite; rotsprite_t *rotated[2][16]; // Rotated patches
#endif #endif
} spriteframe_t; } spriteframe_t;

View File

@ -75,6 +75,7 @@ UINT8 *dc_source;
#define NUMTRANSTABLES 9 // how many translucency tables are used #define NUMTRANSTABLES 9 // how many translucency tables are used
UINT8 *transtables; // translucency tables UINT8 *transtables; // translucency tables
UINT8 *blendtables[NUMBLENDMAPS];
/** \brief R_DrawTransColumn uses this /** \brief R_DrawTransColumn uses this
*/ */
@ -98,15 +99,19 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
INT32 ds_y, ds_x1, ds_x2; INT32 ds_y, ds_x1, ds_x2;
lighttable_t *ds_colormap; lighttable_t *ds_colormap;
lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
INT32 ds_waterofs, ds_bgofs;
UINT16 ds_flatwidth, ds_flatheight; UINT16 ds_flatwidth, ds_flatheight;
boolean ds_powersoftwo; boolean ds_powersoftwo;
UINT8 *ds_source; // start of a 64*64 tile image UINT8 *ds_source; // points to the start of a flat
UINT8 *ds_transmap; // one of the translucency tables UINT8 *ds_transmap; // one of the translucency tables
pslope_t *ds_slope; // Current slope being used // Vectors for Software's tilted slope drawers
floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff? floatv3_t *ds_su, *ds_sv, *ds_sz;
floatv3_t *ds_sup, *ds_svp, *ds_szp; floatv3_t *ds_sup, *ds_svp, *ds_szp;
float focallengthf, zeroheight; float focallengthf, zeroheight;
@ -115,10 +120,6 @@ float focallengthf, zeroheight;
UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
// ==========================================================================
// OLD DOOM FUZZY EFFECT
// ==========================================================================
// ========================================================================= // =========================================================================
// TRANSLATION COLORMAP CODE // TRANSLATION COLORMAP CODE
// ========================================================================= // =========================================================================
@ -138,11 +139,11 @@ UINT8 skincolor_modified[MAXSKINCOLORS];
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
/** \brief The R_InitTranslationTables #define TRANSTAB_AMTMUL10 (256.0f / 10.0f)
load in color translation tables /** \brief Initializes the translucency tables used by the Software renderer.
*/ */
void R_InitTranslationTables(void) void R_InitTranslucencyTables(void)
{ {
// Load here the transparency lookup tables 'TINTTAB' // Load here the transparency lookup tables 'TINTTAB'
// NOTE: the TINTTAB resource MUST BE aligned on 64k for the asm // NOTE: the TINTTAB resource MUST BE aligned on 64k for the asm
@ -159,17 +160,94 @@ void R_InitTranslationTables(void)
W_ReadLump(W_GetNumForName("TRANS70"), transtables+0x60000); W_ReadLump(W_GetNumForName("TRANS70"), transtables+0x60000);
W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000); W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000);
W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000); W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000);
R_GenerateBlendTables();
} }
void R_GenerateBlendTables(void)
{
INT32 i;
/** \brief Generates a translation colormap. for (i = 0; i < NUMBLENDMAPS; i++)
{
if (i == blendtab_modulate)
continue;
blendtables[i] = Z_MallocAlign((NUMTRANSTABLES + 1) * 0x10000, PU_STATIC, NULL, 16);
}
\param dest_colormap colormap to populate for (i = 0; i <= 9; i++)
\param skinnum number of skin, TC_DEFAULT or TC_BOSS {
\param color translation color const size_t offs = (0x10000 * i);
const UINT8 alpha = TRANSTAB_AMTMUL10 * i;
\return void R_GenerateTranslucencyTable(blendtables[blendtab_add] + offs, AST_ADD, alpha);
*/ R_GenerateTranslucencyTable(blendtables[blendtab_subtract] + offs, AST_SUBTRACT, alpha);
R_GenerateTranslucencyTable(blendtables[blendtab_reversesubtract] + offs, AST_REVERSESUBTRACT, alpha);
}
// Modulation blending only requires a single table
blendtables[blendtab_modulate] = Z_MallocAlign(0x10000, PU_STATIC, NULL, 16);
R_GenerateTranslucencyTable(blendtables[blendtab_modulate], AST_MODULATE, 0);
}
static colorlookup_t transtab_lut;
void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt)
{
INT16 bg, fg;
if (table == NULL)
I_Error("R_GenerateTranslucencyTable: input table was NULL!");
InitColorLUT(&transtab_lut, pMasterPalette, false);
for (bg = 0; bg < 0xFF; bg++)
{
for (fg = 0; fg < 0xFF; fg++)
{
RGBA_t backrgba = V_GetMasterColor(bg);
RGBA_t frontrgba = V_GetMasterColor(fg);
RGBA_t result;
result.rgba = ASTBlendPixel(backrgba, frontrgba, style, blendamt);
table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue);
}
}
}
#define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0)
UINT8 *R_GetTranslucencyTable(INT32 alphalevel)
{
return transtables + (ClipTransLevel(alphalevel-1) << FF_TRANSSHIFT);
}
UINT8 *R_GetBlendTable(int style, INT32 alphalevel)
{
size_t offs = (ClipTransLevel(alphalevel) << FF_TRANSSHIFT);
// Lactozilla: Returns the equivalent to AST_TRANSLUCENT
// if no alpha style matches any of the blend tables.
switch (style)
{
case AST_ADD:
return blendtables[blendtab_add] + offs;
case AST_SUBTRACT:
return blendtables[blendtab_subtract] + offs;
case AST_REVERSESUBTRACT:
return blendtables[blendtab_reversesubtract] + offs;
case AST_MODULATE:
return blendtables[blendtab_modulate];
default:
break;
}
// Return a normal translucency table
if (--alphalevel >= 0)
return transtables + (ClipTransLevel(alphalevel) << FF_TRANSSHIFT);
else
return NULL;
}
// Define for getting accurate color brightness readings according to how the human eye sees them. // Define for getting accurate color brightness readings according to how the human eye sees them.
// https://en.wikipedia.org/wiki/Relative_luminance // https://en.wikipedia.org/wiki/Relative_luminance
@ -227,6 +305,14 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor)
#undef SETBRIGHTNESS #undef SETBRIGHTNESS
/** \brief Generates a translation colormap.
\param dest_colormap colormap to populate
\param skinnum number of skin, TC_DEFAULT or TC_BOSS
\param color translation color
\return void
*/
static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT16 color) static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT16 color)
{ {
INT32 i, starttranscolor, skinramplength; INT32 i, starttranscolor, skinramplength;

View File

@ -37,7 +37,6 @@ extern UINT8 dc_hires;
extern UINT8 *dc_source; // first pixel in a column extern UINT8 *dc_source; // first pixel in a column
// translucency stuff here // translucency stuff here
extern UINT8 *transtables; // translucency tables, should be (*transtables)[5][256][256]
extern UINT8 *dc_transmap; extern UINT8 *dc_transmap;
// translation stuff here // translation stuff here
@ -56,9 +55,14 @@ extern INT32 dc_texheight;
extern INT32 ds_y, ds_x1, ds_x2; extern INT32 ds_y, ds_x1, ds_x2;
extern lighttable_t *ds_colormap; extern lighttable_t *ds_colormap;
extern lighttable_t *ds_translation;
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
extern INT32 ds_waterofs, ds_bgofs;
extern UINT16 ds_flatwidth, ds_flatheight; extern UINT16 ds_flatwidth, ds_flatheight;
extern boolean ds_powersoftwo; extern boolean ds_powersoftwo;
extern UINT8 *ds_source; extern UINT8 *ds_source;
extern UINT8 *ds_transmap; extern UINT8 *ds_transmap;
@ -66,8 +70,8 @@ typedef struct {
float x, y, z; float x, y, z;
} floatv3_t; } floatv3_t;
extern pslope_t *ds_slope; // Current slope being used // Vectors for Software's tilted slope drawers
extern floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff? extern floatv3_t *ds_su, *ds_sv, *ds_sz;
extern floatv3_t *ds_sup, *ds_svp, *ds_szp; extern floatv3_t *ds_sup, *ds_svp, *ds_szp;
extern float focallengthf, zeroheight; extern float focallengthf, zeroheight;
@ -102,25 +106,48 @@ extern lumpnum_t viewborderlump[8];
#define GTC_CACHE 1 #define GTC_CACHE 1
#define TC_DEFAULT -1 enum
#define TC_BOSS -2 {
#define TC_METALSONIC -3 // For Metal Sonic battle TC_BOSS = INT8_MIN,
#define TC_ALLWHITE -4 // For Cy-Brak-demon TC_METALSONIC, // For Metal Sonic battle
#define TC_RAINBOW -5 // For single colour TC_ALLWHITE, // For Cy-Brak-demon
#define TC_BLINK -6 // For item blinking, according to kart TC_RAINBOW, // For single colour
#define TC_DASHMODE -7 // For Metal Sonic's dashmode TC_BLINK, // For item blinking, according to kart
TC_DASHMODE, // For Metal Sonic's dashmode
TC_DEFAULT
};
// Custom player skin translation
// Initialize color translation tables, for player rendering etc. // Initialize color translation tables, for player rendering etc.
void R_InitTranslationTables(void);
UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags); UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags);
void R_FlushTranslationColormapCache(void); void R_FlushTranslationColormapCache(void);
UINT16 R_GetColorByName(const char *name); UINT16 R_GetColorByName(const char *name);
UINT16 R_GetSuperColorByName(const char *name); UINT16 R_GetSuperColorByName(const char *name);
extern UINT8 *transtables; // translucency tables, should be (*transtables)[5][256][256]
enum
{
blendtab_add,
blendtab_subtract,
blendtab_reversesubtract,
blendtab_modulate,
NUMBLENDMAPS
};
extern UINT8 *blendtables[NUMBLENDMAPS];
void R_InitTranslucencyTables(void);
void R_GenerateBlendTables(void);
void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt);
UINT8 *R_GetTranslucencyTable(INT32 alphalevel);
UINT8 *R_GetBlendTable(int style, INT32 alphalevel);
// Color ramp modification should force a recache // Color ramp modification should force a recache
extern UINT8 skincolor_modified[]; extern UINT8 skincolor_modified[];
// Custom player skin translation
void R_InitViewBuffer(INT32 width, INT32 height); void R_InitViewBuffer(INT32 width, INT32 height);
void R_InitViewBorder(void); void R_InitViewBorder(void);
void R_VideoErase(size_t ofs, INT32 count); void R_VideoErase(size_t ofs, INT32 count);
@ -149,39 +176,47 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void);
void R_DrawFogColumn_8(void); void R_DrawFogColumn_8(void);
void R_DrawColumnShadowed_8(void); void R_DrawColumnShadowed_8(void);
#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
void R_DrawSpan_8(void); void R_DrawSpan_8(void);
void R_DrawSplat_8(void);
void R_DrawTranslucentSpan_8(void); void R_DrawTranslucentSpan_8(void);
void R_DrawTranslucentSplat_8(void);
void R_DrawTiltedSpan_8(void); void R_DrawTiltedSpan_8(void);
void R_DrawTiltedTranslucentSpan_8(void); void R_DrawTiltedTranslucentSpan_8(void);
#ifndef NOWATER
void R_DrawTiltedTranslucentWaterSpan_8(void); void R_DrawSplat_8(void);
#endif void R_DrawTranslucentSplat_8(void);
void R_DrawTiltedSplat_8(void); void R_DrawTiltedSplat_8(void);
void R_DrawFloorSprite_8(void);
void R_DrawTranslucentFloorSprite_8(void);
void R_DrawTiltedFloorSprite_8(void);
void R_DrawTiltedTranslucentFloorSprite_8(void);
void R_CalcTiltedLighting(fixed_t start, fixed_t end); void R_CalcTiltedLighting(fixed_t start, fixed_t end);
extern INT32 tiltlighting[MAXVIDWIDTH]; extern INT32 tiltlighting[MAXVIDWIDTH];
#ifndef NOWATER
void R_DrawTranslucentWaterSpan_8(void); void R_DrawTranslucentWaterSpan_8(void);
extern INT32 ds_bgofs; void R_DrawTiltedTranslucentWaterSpan_8(void);
extern INT32 ds_waterofs;
#endif
void R_DrawFogSpan_8(void); void R_DrawFogSpan_8(void);
// Lactozilla: Non-powers-of-two // Lactozilla: Non-powers-of-two
void R_DrawSpan_NPO2_8(void); void R_DrawSpan_NPO2_8(void);
void R_DrawTranslucentSpan_NPO2_8(void); void R_DrawTranslucentSpan_NPO2_8(void);
void R_DrawSplat_NPO2_8(void);
void R_DrawTranslucentSplat_NPO2_8(void);
void R_DrawTiltedSpan_NPO2_8(void); void R_DrawTiltedSpan_NPO2_8(void);
void R_DrawTiltedTranslucentSpan_NPO2_8(void); void R_DrawTiltedTranslucentSpan_NPO2_8(void);
#ifndef NOWATER
void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void); void R_DrawSplat_NPO2_8(void);
#endif void R_DrawTranslucentSplat_NPO2_8(void);
void R_DrawTiltedSplat_NPO2_8(void); void R_DrawTiltedSplat_NPO2_8(void);
#ifndef NOWATER
void R_DrawFloorSprite_NPO2_8(void);
void R_DrawTranslucentFloorSprite_NPO2_8(void);
void R_DrawTiltedFloorSprite_NPO2_8(void);
void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void);
void R_DrawTranslucentWaterSpan_NPO2_8(void); void R_DrawTranslucentWaterSpan_NPO2_8(void);
#endif void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void);
#ifdef USEASM #ifdef USEASM
void ASMCALL R_DrawColumn_8_ASM(void); void ASMCALL R_DrawColumn_8_ASM(void);

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