Merge branch 'next' of https://git.do.srb2.org/STJr/SRB2 into udmf-multitag

# Conflicts:
#	src/lua_baselib.c
#	src/lua_maplib.c
This commit is contained in:
Nev3r 2020-10-27 20:48:25 +01:00
commit c62ef355ef
129 changed files with 7169 additions and 4278 deletions

View File

@ -43,7 +43,7 @@ jobs:
- v1-SRB2-APT
- run:
name: Install SDK
command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libopenmpt-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libcurl4-openssl-dev:i386 libopenmpt-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
- save_cache:
key: v1-SRB2-APT
@ -71,4 +71,4 @@ jobs:
- save_cache:
key: v1-SRB2-{{ .Branch }}-{{ checksum "objs/Linux/SDL/Release/depend.dep" }}
paths:
- /root/.ccache
- /root/.ccache

View File

@ -1,4 +1,4 @@
version: 2.2.6.{branch}-{build}
version: 2.2.8.{branch}-{build}
os: MinGW
environment:

View File

@ -32,6 +32,7 @@ set(SRB2_CORE_SOURCES
m_fixed.c
m_menu.c
m_misc.c
m_perfstats.c
m_queue.c
m_random.c
md5.c
@ -97,12 +98,12 @@ set(SRB2_CORE_HEADERS
m_fixed.h
m_menu.h
m_misc.h
m_perfstats.h
m_queue.h
m_random.h
m_swap.h
md5.h
mserv.h
http-mserv.h
p5prof.h
s_sound.h
screen.h
@ -128,7 +129,8 @@ set(SRB2_CORE_RENDER_SOURCES
r_sky.c
r_splats.c
r_things.c
r_patch.c
r_textures.c
r_picformats.c
r_portal.c
r_bsp.h
@ -144,7 +146,8 @@ set(SRB2_CORE_RENDER_SOURCES
r_splats.h
r_state.h
r_things.h
r_patch.h
r_textures.h
r_picformats.h
r_portal.h
)
@ -232,6 +235,8 @@ set(SRB2_CONFIG_HAVE_OPENMPT ON CACHE BOOL
"Enable OpenMPT support.")
set(SRB2_CONFIG_HAVE_CURL ON CACHE BOOL
"Enable curl support, used for downloading files via HTTP.")
set(SRB2_CONFIG_HAVE_THREADS ON CACHE BOOL
"Enable multithreading support.")
if(${CMAKE_SYSTEM} MATCHES Windows)
set(SRB2_CONFIG_HAVE_MIXERX ON CACHE BOOL
"Enable SDL Mixer X support.")
@ -264,6 +269,7 @@ set(SRB2_LUA_SOURCES
lua_mathlib.c
lua_mobjlib.c
lua_playerlib.c
lua_polyobjlib.c
lua_script.c
lua_skinlib.c
lua_thinkerlib.c
@ -471,6 +477,12 @@ if(${SRB2_CONFIG_HAVE_CURL})
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})
add_definitions(-DHWRENDER)
set(SRB2_HWRENDER_SOURCES

View File

@ -56,10 +56,10 @@
# Compile with GCC 4.6x version, add 'GCC46=1'
# Compile a profile version, add 'PROFILEMODE=1'
# Compile a debug version, add 'DEBUGMODE=1'
# Compile with extra warnings, add 'WARNINGMODE=1'
# Compile with less warnings, add 'RELAXWARNINGS=1'
# Generate compiler errors for most compiler warnings, add 'ERRORMODE=1'
# Compile without NASM's tmap.nas, add 'NOASM=1'
# Compile without 3D hardware support, add 'NOHW=1'
# Compile without 3D sound support, add 'NOHS=1'
# Compile with GDBstubs, add 'RDB=1'
# Compile without PNG, add 'NOPNG=1'
# Compile without zlib, add 'NOZLIB=1'
@ -80,6 +80,58 @@
#
#############################################################################
ALL_SYSTEMS=\
PANDORA\
LINUX64\
MINGW64\
HAIKU\
DUMMY\
DJGPPDOS\
MINGW\
UNIX\
LINUX\
SOLARIS\
FREEBSD\
MACOSX\
SDL\
# check for user specified system
ifeq (,$(filter $(ALL_SYSTEMS),$(.VARIABLES)))
ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
$(info Detected a Windows system, compiling for 32-bit MinGW SDL2...)
# go for a 32-bit sdl mingw exe by default
MINGW=1
SDL=1
WINDOWSHELL=1
else # if you on the *nix
system:=$(shell uname -s)
ifeq ($(system),Linux)
new_system=LINUX
else
$(error \
Could not automatically detect your system,\
try specifying a system manually)
endif
ifeq ($(shell getconf LONG_BIT),64)
system+=64-bit
new_system:=$(new_system)64
endif
$(info Detected $(system) ($(new_system))...)
$(new_system)=1
endif
endif
# SRB2 data files
D_DIR?=../bin/Resources
D_FILES=$(D_DIR)/srb2.pk3 \
@ -119,7 +171,6 @@ NOPNG=1
NOZLIB=1
NONET=1
NOHW=1
NOHS=1
NOASM=1
NOIPX=1
EXENAME?=srb2dummy
@ -141,7 +192,6 @@ endif
ifdef PANDORA
NONX86=1
NOHW=1
NOHS=1
endif
ifndef NOOPENMPT
@ -223,13 +273,6 @@ else
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o
endif
ifdef NOHS
OPTS+=-DNOHS
else
OPTS+=-DHW3SOUND
OBJS+=$(OBJDIR)/hw3sound.o
endif
OPTS += -DCOMPVERSION
ifndef NONX86
@ -443,6 +486,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/m_fixed.o \
$(OBJDIR)/m_menu.o \
$(OBJDIR)/m_misc.o \
$(OBJDIR)/m_perfstats.o \
$(OBJDIR)/m_random.o \
$(OBJDIR)/m_queue.o \
$(OBJDIR)/info.o \
@ -474,7 +518,8 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_sky.o \
$(OBJDIR)/r_splats.o \
$(OBJDIR)/r_things.o \
$(OBJDIR)/r_patch.o \
$(OBJDIR)/r_textures.o \
$(OBJDIR)/r_picformats.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
$(OBJDIR)/taglist.o \
@ -563,8 +608,9 @@ ifndef VALGRIND
ifndef NOOBJDUMP
@echo Dumping debugging info
$(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt
ifdef WINDOWSHELL
-$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
ifndef WINDOWSHELL
else
-$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
endif
endif
@ -584,8 +630,9 @@ endif
reobjdump:
@echo Redumping debugging info
$(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt
ifdef WINDOWSHELL
-$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
ifndef WINDOWSHELL
else
-$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
endif
@ -751,19 +798,6 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
endif
ifndef NOHS
$(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_ds3d.o $(WFLAGS) -D_WINDOWS -mwindows -c hardware/s_ds3d/s_ds3d.c
$(OBJDIR)/s_fmod.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o $(WFLAGS) -D_WINDOWS -mwindows -c hardware/s_fmod/s_fmod.c
$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o $(WFLAGS) -D_WINDOWS -mwindows -c hardware/s_openal/s_openal.c
endif
endif
endif

View File

@ -48,7 +48,9 @@ endif
# Automatically set version flag, but not if one was manually set
ifeq (,$(filter GCC%,$(.VARIABLES)))
ifneq (,$(findstring gcc,$(shell $(CC) --version))) # if it's GCC
version:=$(shell $(CC) --version)
# check if this is in fact GCC
ifneq (,$(or $(findstring gcc,$(version)),$(findstring GCC,$(version))))
version:=$(shell $(CC) -dumpversion)
# Turn version into words of major, minor
@ -208,10 +210,7 @@ WFLAGS=-Wall
ifndef GCC295
#WFLAGS+=-Wno-packed
endif
ifdef ERRORMODE
WARNINGMODE=1
endif
ifdef WARNINGMODE
ifndef RELAXWARNINGS
WFLAGS+=-W
#WFLAGS+=-Wno-sign-compare
ifndef GCC295

View File

@ -8,8 +8,8 @@
UINT8 cdaudio_started = 0;
consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cd_volume = CVAR_INIT ("cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL);
consvar_t cdUpdate = CVAR_INIT ("cd_update","1",CV_SAVE, NULL, NULL);
void I_InitCD(void){}

View File

@ -16,7 +16,7 @@ boolean allow_fullscreen = false;
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL);
void I_StartupGraphics(void){}
void I_ShutdownGraphics(void){}

View File

@ -47,5 +47,6 @@ OBJS:=$(OBJS) \
$(OBJDIR)/lua_skinlib.o \
$(OBJDIR)/lua_thinkerlib.o \
$(OBJDIR)/lua_maplib.o \
$(OBJDIR)/lua_polyobjlib.o \
$(OBJDIR)/lua_blockmaplib.o \
$(OBJDIR)/lua_hudlib.o

View File

@ -19,6 +19,7 @@
#include "lauxlib.h"
#include "lualib.h"
#include "../m_fixed.h"
/* macro to `unsign' a character */
#define uchar(c) ((unsigned char)(c))
@ -790,7 +791,7 @@ static int str_format (lua_State *L) {
case 'e': case 'E': case 'f':
case 'g': case 'G': {
lua_Number n = luaL_checknumber(L, arg);
sprintf(buff, form, (double)n);
sprintf(buff, form, (double)n / FRACUNIT);
break;
}
case 'q': {

View File

@ -322,8 +322,8 @@ static void Arith (lua_State *L, StkId ra, TValue *rb,
case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
case TM_DIV: if (nc == 0) { lua_pushliteral(L, "divide by zero error"); lua_error(L); } else setnvalue(ra, luai_numdiv(nb, nc)); break;
case TM_MOD: if (nc == 0) { lua_pushliteral(L, "modulo by zero error"); lua_error(L); } else setnvalue(ra, luai_nummod(nb, nc)); break;
case TM_DIV: if (nc == 0) { luaG_runerror(L, "divide by zero error"); } else setnvalue(ra, luai_numdiv(nb, nc)); break;
case TM_MOD: if (nc == 0) { luaG_runerror(L, "modulo by zero error"); } else setnvalue(ra, luai_nummod(nb, nc)); break;
case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
case TM_AND: setnvalue(ra, luai_numand(nb, nc)); break;
@ -492,8 +492,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
if (nc == 0) {
lua_pushliteral(L, "divide by zero error");
lua_error(L);
luaG_runerror(L, "divide by zero error");
}
else
setnvalue(ra, luai_numdiv(nb, nc));
@ -508,8 +507,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
if (nc == 0) {
lua_pushliteral(L, "modulo by zero error");
lua_error(L);
luaG_runerror(L, "modulo by zero error");
}
else
setnvalue(ra, luai_nummod(nb, nc));

View File

@ -79,7 +79,7 @@ CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
// First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20)
// Also set CV_HIDEN during runtime, after config is loaded
static boolean execversion_enabled = false;
consvar_t cv_execversion = {"execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_execversion = CVAR_INIT ("execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion);
// for default joyaxis detection
static boolean joyaxis_default = false;
@ -165,6 +165,8 @@ void COM_BufAddTextEx(const char *ptext, int flags)
*/
void COM_BufInsertTextEx(const char *ptext, int flags)
{
const INT32 old_wait = com_wait;
char *temp = NULL;
size_t templen;
@ -176,10 +178,14 @@ void COM_BufInsertTextEx(const char *ptext, int flags)
VS_Clear(&com_text);
}
com_wait = 0;
// add the entire text of the file (or alias)
COM_BufAddTextEx(ptext, flags);
COM_BufExecute(); // do it right away
com_wait += old_wait;
// add the copied off data
if (templen)
{
@ -560,7 +566,7 @@ static boolean COM_Exists(const char *com_name)
* \param partial The partial name of the command (potentially).
* \param skips Number of commands to skip.
* \return The complete command name, or NULL.
* \sa CV_CompleteVar
* \sa CV_CompleteAlias, CV_CompleteVar
*/
const char *COM_CompleteCommand(const char *partial, INT32 skips)
{
@ -581,6 +587,32 @@ const char *COM_CompleteCommand(const char *partial, INT32 skips)
return NULL;
}
/** Completes the name of an alias.
*
* \param partial The partial name of the alias (potentially).
* \param skips Number of aliases to skip.
* \return The complete alias name, or NULL.
* \sa CV_CompleteCommand, CV_CompleteVar
*/
const char *COM_CompleteAlias(const char *partial, INT32 skips)
{
cmdalias_t *a;
size_t len;
len = strlen(partial);
if (!len)
return NULL;
// check functions
for (a = com_alias; a; a = a->next)
if (!strncmp(partial, a->name, len))
if (!skips--)
return a->name;
return NULL;
}
/** Parses a single line of text into arguments and tries to execute it.
* The text can come from the command buffer, a remote client, or stdin.
*
@ -875,6 +907,9 @@ static void COM_Help_f(void)
CONS_Printf(" Current value: %s\n", cvar->string);
else
CONS_Printf(" Current value: %d\n", cvar->value);
if (cvar->revert.v.string != NULL && strcmp(cvar->revert.v.string, cvar->string) != 0)
CONS_Printf(" Value before netgame: %s\n", cvar->revert.v.string);
}
else
{
@ -1201,7 +1236,7 @@ static consvar_t *CV_FindNetVar(UINT16 netid)
{
consvar_t *cvar;
if (netid >= consvar_number_of_netids)
if (netid > consvar_number_of_netids)
return NULL;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
@ -1262,12 +1297,12 @@ void CV_RegisterVar(consvar_t *variable)
// check net variables
if (variable->flags & CV_NETVAR)
{
variable->netid = consvar_number_of_netids++;
/* in case of overflow... */
if (variable->netid > consvar_number_of_netids)
if (consvar_number_of_netids == UINT16_MAX)
I_Error("Way too many netvars");
variable->netid = ++consvar_number_of_netids;
#ifdef OLD22DEMOCOMPAT
CV_RegisterOldDemoVar(variable);
#endif
@ -1280,6 +1315,7 @@ void CV_RegisterVar(consvar_t *variable)
consvar_vars = variable;
}
variable->string = variable->zstring = NULL;
memset(&variable->revert, 0, sizeof variable->revert);
variable->changed = 0; // new variable has not been modified by the user
#ifdef PARANOIA
@ -1321,7 +1357,7 @@ static const char *CV_StringValue(const char *var_name)
* \param partial The partial name of the variable (potentially).
* \param skips Number of variables to skip.
* \return The complete variable name, or NULL.
* \sa COM_CompleteCommand
* \sa COM_CompleteCommand, CV_CompleteAlias
*/
const char *CV_CompleteVar(char *partial, INT32 skips)
{
@ -1392,6 +1428,18 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++)
if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr))
{
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.const_munge = var->PossibleValue[i].strvalue;
return;
}
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
@ -1452,12 +1500,36 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
// ...or not.
goto badinput;
found:
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.const_munge = var->PossibleValue[i].strvalue;
return;
}
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
}
}
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.string = Z_StrDup(valstr);
return;
}
// free the old value string
Z_Free(var->zstring);
@ -1676,8 +1748,19 @@ static void CV_LoadVars(UINT8 **p,
serverloading = true;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->flags & CV_NETVAR)
{
if (client && cvar->revert.v.string == NULL)
{
cvar->revert.v.const_munge = cvar->string;
cvar->revert.allocated = ( cvar->zstring != NULL );
cvar->zstring = NULL;/* don't free this */
}
Setvalue(cvar, cvar->defaultvalue, true);
}
}
count = READUINT16(*p);
while (count--)
@ -1691,6 +1774,26 @@ static void CV_LoadVars(UINT8 **p,
serverloading = false;
}
void CV_RevertNetVars(void)
{
consvar_t * cvar;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->revert.v.string != NULL)
{
Setvalue(cvar, cvar->revert.v.string, false);
if (cvar->revert.allocated)
{
Z_Free(cvar->revert.v.string);
}
cvar->revert.v.string = NULL;
}
}
}
void CV_LoadNetVars(UINT8 **p)
{
CV_LoadVars(p, ReadNetVar);
@ -1764,6 +1867,14 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
// send the value of the variable
UINT8 buf[128];
UINT8 *p = buf;
// Loading from a config in a netgame? Set revert value.
if (client && execversion_enabled)
{
Setvalue(var, value, true);
return;
}
if (!(server || (addedtogame && IsPlayerAdmin(consoleplayer))))
{
CONS_Printf(M_GetText("Only the server or admin can change: %s %s\n"), var->name, var->string);
@ -2297,18 +2408,43 @@ void CV_SaveVariables(FILE *f)
{
char stringtowrite[MAXTEXTCMD+1];
// Silly hack for Min/Max vars
if (!strcmp(cvar->string, "MAX") || !strcmp(cvar->string, "MIN"))
const char * string;
if (cvar->revert.v.string != NULL)
{
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(cvar->value));
else
sprintf(stringtowrite, "%d", cvar->value);
string = cvar->revert.v.string;
}
else
strcpy(stringtowrite, cvar->string);
{
string = cvar->string;
}
fprintf(f, "%s \"%s\"\n", cvar->name, stringtowrite);
// Silly hack for Min/Max vars
#define MINVAL 0
#define MAXVAL 1
if (
cvar->PossibleValue != NULL &&
cvar->PossibleValue[0].strvalue &&
stricmp(cvar->PossibleValue[0].strvalue, "MIN") == 0
){ // bounded cvar
int which = stricmp(string, "MAX") == 0;
if (which || stricmp(string, "MIN") == 0)
{
INT32 value = cvar->PossibleValue[which].value;
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(value));
else
sprintf(stringtowrite, "%d", value);
string = stringtowrite;
}
}
#undef MINVAL
#undef MAXVAL
fprintf(f, "%s \"%s\"\n", cvar->name, string);
}
}
@ -2370,15 +2506,6 @@ skipwhite:
}
}
// parse single characters
if (c == '{' || c == '}' || c == ')' || c == '(' || c == '\'')
{
com_token[len] = c;
len++;
com_token[len] = 0;
return data + 1;
}
// parse a regular word
do
{
@ -2398,8 +2525,6 @@ skipwhite:
len++;
c = *data;
}
if (c == '{' || c == '}' || c == ')'|| c == '(' || c == '\'')
break;
} while (c > 32);
com_token[len] = 0;

View File

@ -49,6 +49,8 @@ size_t COM_FirstOption(void);
// match existing command or NULL
const char *COM_CompleteCommand(const char *partial, INT32 skips);
const char *COM_CompleteAlias(const char *partial, INT32 skips);
// insert at queu (at end of other command)
#define COM_BufAddText(s) COM_BufAddTextEx(s, 0)
void COM_BufAddTextEx(const char *btext, int flags);
@ -138,12 +140,26 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL
const char *string; // value in string
char *zstring; // Either NULL or same as string.
// If non-NULL, must be Z_Free'd later.
struct
{
char allocated; // whether to Z_Free
union
{
char * string;
const char * const_munge;
} v;
} revert; // value of netvar before joining netgame
UINT16 netid; // used internaly : netid for send end receive
// used only with CV_NETVAR
char changed; // has variable been changed by the user? 0 = no, 1 = yes
struct consvar_s *next;
} consvar_t;
/* name, defaultvalue, flags, PossibleValue, func */
#define CVAR_INIT( ... ) \
{ __VA_ARGS__, 0, NULL, NULL, {0}, 0U, (char)0, NULL }
#ifdef OLD22DEMOCOMPAT
typedef struct old_demo_var old_demo_var_t;
@ -202,6 +218,9 @@ void CV_SaveVars(UINT8 **p, boolean in_demo);
#define CV_SaveNetVars(p) CV_SaveVars(p, false)
void CV_LoadNetVars(UINT8 **p);
// then revert after leaving a netgame
void CV_RevertNetVars(void);
#define CV_SaveDemoVars(p) CV_SaveVars(p, true)
void CV_LoadDemoVars(UINT8 **p);

View File

@ -32,12 +32,14 @@
* Last updated 2020 / 05 / 11 - v2.2.4 - patch.pk3
* Last updated 2020 / 07 / 07 - v2.2.5 - player.dta & patch.pk3
* Last updated 2020 / 07 / 10 - v2.2.6 - player.dta & patch.pk3
* Last updated 2020 / 09 / 27 - v2.2.7 - patch.pk3
* Last updated 2020 / 10 / 02 - v2.2.8 - patch.pk3
*/
#define ASSET_HASH_SRB2_PK3 "0277c9416756627004e83cbb5b2e3e28"
#define ASSET_HASH_ZONES_PK3 "f7e88afb6af7996a834c7d663144bead"
#define ASSET_HASH_PLAYER_DTA "49dad7b24634c89728cc3e0b689e12bb"
#ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_PK3 "ecf00060f03c76b3e49c6ae3925b627f"
#define ASSET_HASH_PATCH_PK3 "466cdf60075262b3f5baa5e07f0999e8"
#endif
#endif

View File

@ -124,22 +124,22 @@ static void CONS_backcolor_Change(void);
static char con_buffer[CON_BUFFERSIZE];
// how many seconds the hud messages lasts on the screen
static consvar_t cons_msgtimeout = {"con_hudtime", "5", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_msgtimeout = CVAR_INIT ("con_hudtime", "5", CV_SAVE, CV_Unsigned, NULL);
// number of lines displayed on the HUD
static consvar_t cons_hudlines = {"con_hudlines", "5", CV_CALL|CV_SAVE, CV_Unsigned, CONS_hudlines_Change, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_hudlines = CVAR_INIT ("con_hudlines", "5", CV_CALL|CV_SAVE, CV_Unsigned, CONS_hudlines_Change);
// number of lines console move per frame
// (con_speed needs a limit, apparently)
static CV_PossibleValue_t speed_cons_t[] = {{0, "MIN"}, {64, "MAX"}, {0, NULL}};
static consvar_t cons_speed = {"con_speed", "8", CV_SAVE, speed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_speed = CVAR_INIT ("con_speed", "8", CV_SAVE, speed_cons_t, NULL);
// percentage of screen height to use for console
static consvar_t cons_height = {"con_height", "50", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_height = CVAR_INIT ("con_height", "50", CV_SAVE, CV_Unsigned, NULL);
static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}, {0, NULL}};
// whether to use console background picture, or translucent mode
static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cons_backpic = CVAR_INIT ("con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL);
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {2, "Sepia"},
{3, "Brown"}, {4, "Pink"}, {5, "Raspberry"},
@ -151,7 +151,7 @@ static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {
{0, NULL}};
consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
consvar_t cons_backcolor = CVAR_INIT ("con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change);
static void CON_Print(char *msg);
@ -870,9 +870,14 @@ boolean CON_Responder(event_t *ev)
// sequential completions a la 4dos
static char completion[80];
static INT32 comskips, varskips;
const char *cmd = "";
static INT32 skips;
static INT32 com_skips;
static INT32 var_skips;
static INT32 alias_skips;
const char *cmd = NULL;
INT32 key;
if (chat_on)
@ -1007,7 +1012,6 @@ boolean CON_Responder(event_t *ev)
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
return true;
strcpy(completion, inputlines[inputline]);
comskips = varskips = 0;
}
len = strlen(completion);
@ -1023,6 +1027,14 @@ boolean CON_Responder(event_t *ev)
CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len);
if (i == 0) CONS_Printf(" (none)\n");
//and finally aliases
CONS_Printf("Aliases:\n");
for (i = 0, cmd = COM_CompleteAlias(completion, i); cmd; cmd = COM_CompleteAlias(completion, ++i))
CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len);
if (i == 0) CONS_Printf(" (none)\n");
completion[0] = 0;
return true;
}
// ---
@ -1091,43 +1103,64 @@ boolean CON_Responder(event_t *ev)
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
return true;
strcpy(completion, inputlines[inputline]);
comskips = varskips = 0;
skips = 0;
com_skips = 0;
var_skips = 0;
alias_skips = 0;
}
else
{
if (shiftdown)
{
if (comskips < 0)
{
if (--varskips < 0)
comskips = -comskips - 2;
}
else if (comskips > 0) comskips--;
if (skips > 0)
skips--;
}
else
{
if (comskips < 0) varskips++;
else comskips++;
skips++;
}
}
if (comskips >= 0)
if (skips <= com_skips)
{
cmd = COM_CompleteCommand(completion, comskips);
if (!cmd) // dirty: make sure if comskips is zero, to have a neg value
comskips = -comskips - 1;
cmd = COM_CompleteCommand(completion, skips);
if (cmd && skips == com_skips)
{
com_skips ++;
var_skips ++;
alias_skips++;
}
}
if (!cmd && skips <= var_skips)
{
cmd = CV_CompleteVar(completion, skips - com_skips);
if (cmd && skips == var_skips)
{
var_skips ++;
alias_skips++;
}
}
if (!cmd && skips <= alias_skips)
{
cmd = COM_CompleteAlias(completion, skips - var_skips);
if (cmd && skips == alias_skips)
{
alias_skips++;
}
}
if (comskips < 0)
cmd = CV_CompleteVar(completion, varskips);
if (cmd)
{
CON_InputSetString(va("%s ", cmd));
}
else
{
if (comskips > 0)
comskips--;
else if (varskips > 0)
varskips--;
skips--;
}
return true;
@ -1677,8 +1710,12 @@ static void CON_DrawBackpic(void)
lumpnum_t piclump;
int x, w, h;
// Get the lumpnum for CONSBACK, or fallback into MISSING.
piclump = W_CheckNumForName("CONSBACK");
// Get the lumpnum for CONSBACK, STARTUP (Only during game startup) or fallback into MISSING.
if (con_startup)
piclump = W_CheckNumForName("STARTUP");
else
piclump = W_CheckNumForName("CONSBACK");
if (piclump == LUMPERROR)
piclump = W_GetNumForName("MISSING");

View File

@ -44,6 +44,7 @@
#include "lua_script.h"
#include "lua_hook.h"
#include "md5.h"
#include "m_perfstats.h"
#ifndef NONET
// cl loading screen
@ -157,10 +158,10 @@ ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL};
consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}};
consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL);
static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n)
{
@ -1269,19 +1270,25 @@ static UINT8 Snake_GetOppositeDir(UINT8 dir)
return 12 + 5 - dir;
}
static void Snake_FindFreeSlot(UINT8 *x, UINT8 *y, UINT8 headx, UINT8 heady)
static void Snake_FindFreeSlot(UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady)
{
UINT8 x, y;
UINT16 i;
do
{
*x = M_RandomKey(SNAKE_NUM_BLOCKS_X);
*y = M_RandomKey(SNAKE_NUM_BLOCKS_Y);
x = M_RandomKey(SNAKE_NUM_BLOCKS_X);
y = M_RandomKey(SNAKE_NUM_BLOCKS_Y);
for (i = 0; i < snake->snakelength; i++)
if (*x == snake->snakex[i] && *y == snake->snakey[i])
if (x == snake->snakex[i] && y == snake->snakey[i])
break;
} while (i < snake->snakelength || (*x == headx && *y == heady));
} while (i < snake->snakelength || (x == headx && y == heady)
|| (x == snake->applex && y == snake->appley)
|| (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy));
*freex = x;
*freey = y;
}
static void Snake_Handle(void)
@ -1412,7 +1419,7 @@ static void Snake_Handle(void)
// Check collision with apple
if (x == snake->applex && y == snake->appley)
{
if (snake->snakelength + 1 < SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y)
if (snake->snakelength + 3 < SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y)
{
snake->snakelength++;
snake->snakex [snake->snakelength - 1] = snake->snakex [snake->snakelength - 2];
@ -2113,7 +2120,7 @@ static void SV_SendSaveGame(INT32 node)
#ifdef DUMPCONSISTENCY
#define TMPSAVENAME "badmath.sav"
static consvar_t cv_dumpconsistency = {"dumpconsistency", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
static void SV_SavedGame(void)
{
@ -2306,7 +2313,7 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
M_SortServerList();
}
#ifdef HAVE_THREADS
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
struct Fetch_servers_ctx
{
int room;
@ -2351,7 +2358,7 @@ Fetch_servers_thread (struct Fetch_servers_ctx *ctx)
free(ctx);
}
#endif/*HAVE_THREADS*/
#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/
void CL_QueryServerList (msg_server_t *server_list)
{
@ -2388,9 +2395,8 @@ void CL_QueryServerList (msg_server_t *server_list)
void CL_UpdateServerList(boolean internetsearch, INT32 room)
{
#ifdef HAVE_THREADS
struct Fetch_servers_ctx *ctx;
#endif
(void)internetsearch;
(void)room;
SL_ClearServerList(0);
@ -2407,9 +2413,12 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
if (netgame)
SendAskInfo(BROADCASTADDR);
#ifdef MASTERSERVER
if (internetsearch)
{
#ifdef HAVE_THREADS
struct Fetch_servers_ctx *ctx;
ctx = malloc(sizeof *ctx);
/* This called from M_Refresh so I don't use a mutex */
@ -2436,6 +2445,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
}
#endif
}
#endif/*MASTERSERVER*/
}
#endif // ifndef NONET
@ -2510,11 +2520,11 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have WAD files loaded or have\n"
"modified the game in some way, and\n"
"your file list does not match\n"
"the server's file list.\n"
"Please restart SRB2 before connecting.\n\n"
"You have the wrong addons loaded.\n\n"
"To play on this server, restart\n"
"the game and don't load any addons.\n"
"SRB2 will automatically add\n"
"everything you need when you join.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
@ -2563,7 +2573,6 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
*asksent = I_GetTime();
}
#else
(void)viams;
(void)asksent;
// No netgames, so we skip this state.
cl_mode = CL_ASKJOIN;
@ -3159,6 +3168,8 @@ static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
// Reset the name
sprintf(player_names[playernum], "Player %d", playernum+1);
player_name_changes[playernum] = 0;
if (IsPlayerAdmin(playernum))
{
RemoveAdminPlayer(playernum); // don't stay admin after you're gone
@ -3198,6 +3209,7 @@ void CL_Reset(void)
doomcom->numslots = 1;
SV_StopServer();
SV_ResetServer();
CV_RevertNetVars();
// make sure we don't leave any fileneeded gunk over from a failed join
fileneedednum = 0;
@ -3665,29 +3677,29 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
}
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
consvar_t cv_netticbuffer = {"netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL);
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); /// \todo not done
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}};
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL);
static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}};
consvar_t cv_joindelay = {"joindelay", "10", CV_SAVE, joindelay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL);
static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}};
consvar_t cv_rejointimeout = {"rejointimeout", "Off", CV_SAVE|CV_FLOAT, rejointimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "Off", CV_SAVE|CV_NETVAR|CV_FLOAT, rejointimeout_cons_t, NULL);
static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}};
consvar_t cv_resynchattempts = {"resynchattempts", "10", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL);
consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
// max file size to send to a player (in kilobytes)
static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}};
consvar_t cv_maxsend = {"maxsend", "4096", CV_SAVE, maxsend_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_noticedownload = {"noticedownload", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL);
consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
// Speed of file downloading (in packets per tic)
static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}};
consvar_t cv_downloadspeed = {"downloadspeed", "16", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL);
static void Got_AddPlayer(UINT8 **p, INT32 playernum);
@ -3775,6 +3787,8 @@ void SV_ResetServer(void)
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
}
memset(player_name_changes, 0, sizeof player_name_changes);
mynode = 0;
cl_packetmissed = false;
@ -3840,8 +3854,10 @@ void D_QuitNetGame(void)
for (i = 0; i < MAXNETNODES; i++)
if (nodeingame[i])
HSendPacket(i, true, 0, 0);
#ifdef MASTERSERVER
if (serverrunning && ms_RoomId > 0)
UnregisterServer();
#endif
}
else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode])
{
@ -4105,8 +4121,10 @@ boolean SV_SpawnServer(void)
if (netgame && I_NetOpenSocket)
{
I_NetOpenSocket();
#ifdef MASTERSERVER
if (ms_RoomId > 0)
RegisterServer();
#endif
}
// non dedicated server just connect to itself
@ -5427,11 +5445,15 @@ void TryRunTics(tic_t realtics)
{
DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic));
ps_tictime = I_GetTimeMicros();
G_Ticker((gametic % NEWTICRATERATIO) == 0);
ExtraDataTicker();
gametic++;
consistancy[gametic%BACKUPTICS] = Consistancy();
ps_tictime = I_GetTimeMicros() - ps_tictime;
// Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame.
if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value)
break;
@ -5568,7 +5590,9 @@ void NetUpdate(void)
// client send the command after a receive of the server
// the server send before because in single player is beter
#ifdef MASTERSERVER
MasterClient_Ticker(); // Acking the Master Server
#endif
if (client)
{
@ -5587,8 +5611,13 @@ void NetUpdate(void)
firstticstosend = gametic;
for (i = 0; i < MAXNETNODES; i++)
if (nodeingame[i] && nettics[i] < firstticstosend)
{
firstticstosend = nettics[i];
if (maketic + 1 >= nettics[i] + BACKUPTICS)
Net_ConnectionTimeout(i);
}
// Don't erase tics not acknowledged
counts = realtics;

View File

@ -14,6 +14,7 @@
#define __D_CLISRV__
#include "d_ticcmd.h"
#include "d_net.h"
#include "d_netcmd.h"
#include "d_net.h"
#include "tables.h"
@ -484,7 +485,7 @@ typedef struct
#pragma pack()
#endif
#define MAXSERVERLIST 64 // Depends only on the display
#define MAXSERVERLIST (MAXNETNODES-1)
typedef struct
{
SINT8 node;
@ -526,6 +527,10 @@ typedef enum
} kickreason_t;
/* the max number of name changes in some time period */
#define MAXNAMECHANGES (5)
#define NAMECHANGERATE (60*TICRATE)
extern boolean server;
extern boolean serverrunning;
#define client (!server)

View File

@ -67,6 +67,7 @@
#include "keys.h"
#include "filesrch.h" // refreshdirmenu, mainwadstally
#include "g_input.h" // tutorial mode control scheming
#include "m_perfstats.h"
#ifdef CMAKECONFIG
#include "config.h"
@ -99,6 +100,7 @@ UINT8 window_notinfocus = false;
// DEMO LOOP
//
static char *startupwadfiles[MAX_WADFILES];
static char *startuppwads[MAX_WADFILES];
boolean devparm = false; // started game with -devparm
@ -434,7 +436,7 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value)
{
rs_rendercalltime = I_GetTimeMicros();
ps_rendercalltime = I_GetTimeMicros();
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
@ -481,7 +483,7 @@ static void D_Display(void)
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
rs_rendercalltime = I_GetTimeMicros() - rs_rendercalltime;
ps_rendercalltime = I_GetTimeMicros() - ps_rendercalltime;
}
if (lastdraw)
@ -495,6 +497,8 @@ static void D_Display(void)
lastdraw = false;
}
ps_uitime = I_GetTimeMicros();
if (gamestate == GS_LEVEL)
{
ST_Drawer();
@ -504,6 +508,10 @@ static void D_Display(void)
else
F_TitleScreenDrawer();
}
else
{
ps_uitime = I_GetTimeMicros();
}
}
// change gamma if needed
@ -544,6 +552,8 @@ static void D_Display(void)
CON_Drawer();
ps_uitime = I_GetTimeMicros() - ps_uitime;
//
// wipe update
//
@ -623,80 +633,14 @@ static void D_Display(void)
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
}
if (cv_renderstats.value)
if (cv_perfstats.value)
{
char s[50];
int frametime = I_GetTimeMicros() - rs_prevframetime;
int divisor = 1;
rs_prevframetime = I_GetTimeMicros();
if (rs_rendercalltime > 10000) divisor = 1000;
snprintf(s, sizeof s - 1, "ft %d", frametime / divisor);
V_DrawThinString(30, 10, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "rtot %d", rs_rendercalltime / divisor);
V_DrawThinString(30, 20, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "bsp %d", rs_bsptime / divisor);
V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "nbsp %d", rs_numbspcalls);
V_DrawThinString(80, 10, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "nspr %d", rs_numsprites);
V_DrawThinString(80, 20, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "nnod %d", rs_numdrawnodes);
V_DrawThinString(80, 30, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "npob %d", rs_numpolyobjects);
V_DrawThinString(80, 40, V_MONOSPACE | V_BLUEMAP, s);
if (rendermode == render_opengl) // OpenGL specific stats
{
snprintf(s, sizeof s - 1, "nsrt %d", rs_hw_nodesorttime / divisor);
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ndrw %d", rs_hw_nodedrawtime / divisor);
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ssrt %d", rs_hw_spritesorttime / divisor);
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "sdrw %d", rs_hw_spritedrawtime / divisor);
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
if (cv_glbatching.value)
{
snprintf(s, sizeof s - 1, "bsrt %d", rs_hw_batchsorttime / divisor);
V_DrawThinString(80, 55, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "bdrw %d", rs_hw_batchdrawtime / divisor);
V_DrawThinString(80, 65, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "npol %d", rs_hw_numpolys);
V_DrawThinString(130, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ndc %d", rs_hw_numcalls);
V_DrawThinString(130, 20, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "nshd %d", rs_hw_numshaders);
V_DrawThinString(130, 30, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "nvrt %d", rs_hw_numverts);
V_DrawThinString(130, 40, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ntex %d", rs_hw_numtextures);
V_DrawThinString(185, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "npf %d", rs_hw_numpolyflags);
V_DrawThinString(185, 20, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ncol %d", rs_hw_numcolors);
V_DrawThinString(185, 30, V_MONOSPACE | V_PURPLEMAP, s);
}
}
else // software specific stats
{
snprintf(s, sizeof s - 1, "prtl %d", rs_sw_portaltime / divisor);
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "plns %d", rs_sw_planetime / divisor);
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "mskd %d", rs_sw_maskedtime / divisor);
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
}
M_DrawPerfStats();
}
rs_swaptime = I_GetTimeMicros();
ps_swaptime = I_GetTimeMicros();
I_FinishUpdate(); // page flip or blit buffer
rs_swaptime = I_GetTimeMicros() - rs_swaptime;
ps_swaptime = I_GetTimeMicros() - ps_swaptime;
}
needpatchflush = false;
@ -729,6 +673,7 @@ tic_t rendergametic;
void D_SRB2Loop(void)
{
tic_t oldentertics = 0, entertic = 0, realtics = 0, rendertimeout = INFTICS;
static lumpnum_t gstartuplumpnum;
if (dedicated)
server = true;
@ -768,7 +713,12 @@ void D_SRB2Loop(void)
*/
/* Smells like a hack... Don't fade Sonic's ass into the title screen. */
if (gamestate != GS_TITLESCREEN)
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(W_GetNumForName("CONSBACK"), PU_PATCH));
{
gstartuplumpnum = W_CheckNumForName("STARTUP");
if (gstartuplumpnum == LUMPERROR)
gstartuplumpnum = W_GetNumForName("MISSING");
V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(gstartuplumpnum, PU_PATCH));
}
for (;;)
{
@ -953,12 +903,12 @@ void D_StartTitle(void)
//
// D_AddFile
//
static void D_AddFile(const char *file)
static void D_AddFile(char **list, const char *file)
{
size_t pnumwadfiles;
char *newfile;
for (pnumwadfiles = 0; startupwadfiles[pnumwadfiles]; pnumwadfiles++)
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
;
newfile = malloc(strlen(file) + 1);
@ -968,16 +918,16 @@ static void D_AddFile(const char *file)
}
strcpy(newfile, file);
startupwadfiles[pnumwadfiles] = newfile;
list[pnumwadfiles] = newfile;
}
static inline void D_CleanFile(void)
static inline void D_CleanFile(char **list)
{
size_t pnumwadfiles;
for (pnumwadfiles = 0; startupwadfiles[pnumwadfiles]; pnumwadfiles++)
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
{
free(startupwadfiles[pnumwadfiles]);
startupwadfiles[pnumwadfiles] = NULL;
free(list[pnumwadfiles]);
list[pnumwadfiles] = NULL;
}
}
@ -1062,7 +1012,7 @@ static void IdentifyVersion(void)
// Load the IWAD
if (srb2wad != NULL && FIL_ReadFileOK(srb2wad))
D_AddFile(srb2wad);
D_AddFile(startupwadfiles, srb2wad);
else
I_Error("srb2.pk3 not found! Expected in %s, ss file: %s\n", srb2waddir, srb2wad);
@ -1073,14 +1023,14 @@ static void IdentifyVersion(void)
// checking in D_SRB2Main
// Add the maps
D_AddFile(va(pandf,srb2waddir,"zones.pk3"));
D_AddFile(startupwadfiles, va(pandf,srb2waddir,"zones.pk3"));
// Add the players
D_AddFile(va(pandf,srb2waddir, "player.dta"));
D_AddFile(startupwadfiles, va(pandf,srb2waddir, "player.dta"));
#ifdef USE_PATCH_DTA
// Add our crappy patches to fix our bugs
D_AddFile(va(pandf,srb2waddir,"patch.pk3"));
D_AddFile(startupwadfiles, va(pandf,srb2waddir,"patch.pk3"));
#endif
#if !defined (HAVE_SDL) || defined (HAVE_MIXER)
@ -1090,7 +1040,7 @@ static void IdentifyVersion(void)
const char *musicpath = va(pandf,srb2waddir,str);\
int ms = W_VerifyNMUSlumps(musicpath); \
if (ms == 1) \
D_AddFile(musicpath); \
D_AddFile(startupwadfiles, musicpath); \
else if (ms == 0) \
I_Error("File "str" has been modified with non-music/sound lumps"); \
}
@ -1280,7 +1230,7 @@ void D_SRB2Main(void)
{
if (!W_VerifyNMUSlumps(s))
G_SetGameModified(true);
D_AddFile(s);
D_AddFile(startuppwads, s);
}
}
}
@ -1321,8 +1271,8 @@ void D_SRB2Main(void)
// load wad, including the main wad file
CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n");
W_InitMultipleFiles(startupwadfiles, mainwads);
D_CleanFile();
W_InitMultipleFiles(startupwadfiles);
D_CleanFile(startupwadfiles);
#ifndef DEVELOP // md5s last updated 22/02/20 (ddmmyy)
@ -1358,8 +1308,6 @@ void D_SRB2Main(void)
// setup loading screen
SCR_Startup();
// we need the font of the console
CONS_Printf("HU_Init(): Setting up heads up display.\n");
HU_Init();
CON_Init();
@ -1371,6 +1319,13 @@ void D_SRB2Main(void)
I_RegisterSysCommands();
CONS_Printf("W_InitMultipleFiles(): Adding extra PWADs.\n");
W_InitMultipleFiles(startuppwads);
D_CleanFile(startuppwads);
CONS_Printf("HU_LoadGraphics()...\n");
HU_LoadGraphics();
//--------------------------------------------------------- CONFIG.CFG
M_FirstLoadConfig(); // WARNING : this do a "COM_BufExecute()"
@ -1559,6 +1514,12 @@ void D_SRB2Main(void)
ultimatemode = true;
}
if (M_CheckParm("-splitscreen"))
{
autostart = true;
splitscreen = true;
}
// rei/miru: bootmap (Idea: starts the game on a predefined map)
if (bootmap && !(M_CheckParm("-warp") && M_IsNextParm()))
{

View File

@ -19,7 +19,9 @@
#define __D_NET__
// Max computers in a game
#define MAXNETNODES (MAXPLAYERS+4)
// 127 is probably as high as this can go, because
// SINT8 is used for nodes sometimes >:(
#define MAXNETNODES 127
#define BROADCASTADDR MAXNETNODES
#define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer
//#define NETSPLITSCREEN // Kart's splitscreen netgame feature

View File

@ -197,186 +197,183 @@ static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"},
static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}};
consvar_t cv_showinputjoy = {"showinputjoy", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", 0, CV_OnOff, NULL);
#ifdef NETGAME_DEVMODE
static consvar_t cv_fishcake = {"fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_fishcake = CVAR_INIT ("fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange);
#endif
static consvar_t cv_dummyconsvar = {"dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff,
DummyConsvar_OnChange, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange);
consvar_t cv_restrictskinchange = {"restrictskinchange", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowteamchange = {"allowteamchange", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_SAVE|CV_NETVAR|CV_CHEAT, CV_YesNo, NULL);
consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_startinglives = CVAR_INIT ("startinglives", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, NULL);
static CV_PossibleValue_t respawntime_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "Off"}, {0, NULL}};
consvar_t cv_respawntime = {"respawndelay", "3", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL);
consvar_t cv_competitionboxes = {"competitionboxes", "Mystery", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, 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}};
consvar_t cv_seenames = {"seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
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);
#endif
// names
consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange);
consvar_t cv_playername2 = CVAR_INIT ("name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange);
// player colors
UINT16 lastgoodcolor = SKINCOLOR_BLUE, lastgoodcolor2 = SKINCOLOR_BLUE;
consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playercolor = CVAR_INIT ("color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange);
consvar_t cv_playercolor2 = CVAR_INIT ("color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange);
// player's skin, saved for commodity, when using a favorite skins wad..
consvar_t cv_skin = {"skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skin2 = {"skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skin = CVAR_INIT ("skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange);
consvar_t cv_skin2 = CVAR_INIT ("skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange);
// saved versions of the above six
consvar_t cv_defaultplayercolor = {"defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_defaultplayercolor2 = {"defaultcolor2", "Orange", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_defaultskin = {"defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_defaultskin2 = {"defaultskin2", DEFAULTSKIN2, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_defaultplayercolor = CVAR_INIT ("defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL);
consvar_t cv_defaultplayercolor2 = CVAR_INIT ("defaultcolor2", "Orange", CV_SAVE, Color_cons_t, NULL);
consvar_t cv_defaultskin = CVAR_INIT ("defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL);
consvar_t cv_defaultskin2 = CVAR_INIT ("defaultskin2", DEFAULTSKIN2, CV_SAVE, NULL, NULL);
consvar_t cv_skipmapcheck = {"skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skipmapcheck = CVAR_INIT ("skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL);
INT32 cv_debug;
consvar_t cv_usemouse = {"use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse);
consvar_t cv_usemouse2 = CVAR_INIT ("use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2);
consvar_t cv_usejoystick = {"use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t,
I_InitJoystick, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usejoystick2 = {"use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t,
I_InitJoystick2, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_usejoystick = CVAR_INIT ("use_gamepad", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick);
consvar_t cv_usejoystick2 = CVAR_INIT ("use_gamepad2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2);
#if (defined (LJOYSTICK) || defined (HAVE_SDL))
#ifdef LJOYSTICK
consvar_t cv_joyport = {"padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyport2 = {"padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: for later
consvar_t cv_joyport = CVAR_INIT ("padport", "/dev/js0", CV_SAVE, joyport_cons_t, NULL);
consvar_t cv_joyport2 = CVAR_INIT ("padport2", "/dev/js0", CV_SAVE, joyport_cons_t, NULL); //Alam: for later
#endif
consvar_t cv_joyscale = {"padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyscale2 = {"padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale);
consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2);
#else
consvar_t cv_joyscale = {"padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale2 = {"padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale = CVAR_INIT ("padscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save
consvar_t cv_joyscale2 = CVAR_INIT ("padscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL); //Alam: Dummy for save
#endif
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
consvar_t cv_mouse2port = {"mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouse2opt = {"mouse2opt", "0", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL);
consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL);
#else
consvar_t cv_mouse2port = {"mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL);
#endif
consvar_t cv_matchboxes = {"matchboxes", "Normal", CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_specialrings = {"specialrings", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_powerstones = {"powerstones", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_SAVE|CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL);
consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_recycler = {"tv_recycler", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_teleporters = {"tv_teleporter", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_superring = {"tv_superring", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_supersneakers = {"tv_supersneaker", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invincibility = {"tv_invincibility", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_jumpshield = {"tv_jumpshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_watershield = {"tv_watershield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ringshield = {"tv_ringshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_forceshield = {"tv_forceshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_bombshield = {"tv_bombshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_1up = {"tv_1up", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_eggmanbox = {"tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_recycler = CVAR_INIT ("tv_recycler", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_SAVE|CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
consvar_t cv_ringslinger = {"ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT, CV_YesNo,
Ringslinger_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gravity = {"gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ringslinger = CVAR_INIT ("ringslinger", "No", CV_NETVAR|CV_NOSHOWHELP|CV_CALL|CV_CHEAT, CV_YesNo, Ringslinger_OnChange);
consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange);
consvar_t cv_soundtest = {"soundtest", "0", CV_CALL, NULL, SoundTest_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_soundtest = CVAR_INIT ("soundtest", "0", CV_CALL, NULL, SoundTest_OnChange);
static CV_PossibleValue_t minitimelimit_cons_t[] = {{15, "MIN"}, {9999, "MAX"}, {0, NULL}};
consvar_t cv_countdowntime = {"countdowntime", "60", CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL);
consvar_t cv_touchtag = {"touchtag", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_hidetime = {"hidetime", "30", CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_SAVE|CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange);
consvar_t cv_autobalance = {"autobalance", "Off", CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_teamscramble = {"teamscramble", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_scrambleonchange = {"scrambleonchange", "Off", CV_NETVAR, teamscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange);
consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange);
consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV_NETVAR, teamscramble_cons_t, NULL);
consvar_t cv_friendlyfire = {"friendlyfire", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_itemfinder = {"itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_friendlyfire = CVAR_INIT ("friendlyfire", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange);
// Scoring type options
consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL);
static CV_PossibleValue_t timetic_cons_t[] = {{0, "Classic"}, {1, "Centiseconds"}, {2, "Mania"}, {3, "Tics"}, {0, NULL}};
consvar_t cv_timetic = {"timerres", "Classic", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_timetic = CVAR_INIT ("timerres", "Classic", CV_SAVE, timetic_cons_t, NULL);
static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-person only"}, {2, "Always"}, {0, NULL}};
consvar_t cv_powerupdisplay = {"powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_powerupdisplay = CVAR_INIT ("powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL);
static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"}, {0, "None"}, {0, NULL}};
consvar_t cv_pointlimit = {"pointlimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t,
PointLimit_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange);
static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}};
consvar_t cv_timelimit = {"timelimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t,
TimeLimit_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange);
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, NULL}};
consvar_t cv_numlaps = {"numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t,
NumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange);
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange);
// Point and time limits for every gametype
INT32 pointlimits[NUMGAMETYPES];
INT32 timelimits[NUMGAMETYPES];
// log elemental hazards -- not a netvar, is local to current player
consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_hazardlog = CVAR_INIT ("hazardlog", "Yes", 0, CV_YesNo, NULL);
consvar_t cv_forceskin = {"forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_downloading = {"downloading", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange);
consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL);
consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_killingdead = {"killingdead", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_netstat = {"netstat", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // show bandwidth statistics
consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show bandwidth statistics
static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
consvar_t cv_nettimeout = {"nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_nettimeout = CVAR_INIT ("nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange);
static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
consvar_t cv_jointimeout = {"jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_jointimeout = CVAR_INIT ("jointimeout", "350", CV_CALL|CV_SAVE|CV_NETVAR, jointimeout_cons_t, JoinTimeout_OnChange);
consvar_t cv_maxping = CVAR_INIT ("maxping", "0", CV_SAVE|CV_NETVAR, CV_Unsigned, NULL);
static CV_PossibleValue_t pingtimeout_cons_t[] = {{8, "MIN"}, {120, "MAX"}, {0, NULL}};
consvar_t cv_pingtimeout = {"pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pingtimeout = CVAR_INIT ("pingtimeout", "10", CV_SAVE|CV_NETVAR, pingtimeout_cons_t, NULL);
// show your ping on the HUD next to framerate. Defaults to warning only (shows up if your ping is > maxping)
static CV_PossibleValue_t showping_cons_t[] = {{0, "Off"}, {1, "Always"}, {2, "Warning"}, {0, NULL}};
consvar_t cv_showping = {"showping", "Warning", CV_SAVE, showping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showping = CVAR_INIT ("showping", "Warning", CV_SAVE, showping_cons_t, NULL);
// Intermission time Tails 04-19-2002
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_inttime = {"inttime", "10", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_SAVE|CV_NETVAR, inttime_cons_t, NULL);
static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}};
consvar_t cv_coopstarposts = {"coopstarposts", "Per-player", CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_coopstarposts = CVAR_INIT ("coopstarposts", "Per-player", CV_SAVE|CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange);
static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}};
consvar_t cv_cooplives = {"cooplives", "Avoid Game Over", CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cooplives = CVAR_INIT ("cooplives", "Avoid Game Over", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange);
static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}};
consvar_t cv_advancemap = {"advancemap", "Next", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_advancemap = CVAR_INIT ("advancemap", "Next", CV_SAVE|CV_NETVAR, advancemap_cons_t, NULL);
static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}};
consvar_t cv_playersforexit = {"playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR, playersforexit_cons_t, NULL);
consvar_t cv_exitmove = {"exitmove", "On", CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange);
consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", 0, CV_YesNo, NULL);
consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_SAVE|CV_NETVAR, pause_cons_t, NULL);
consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange);
consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL);
static CV_PossibleValue_t perfstats_cons_t[] = {
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL);
char timedemo_name[256];
boolean timedemo_csv;
@ -865,15 +862,14 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_fullscreen);
CV_RegisterVar(&cv_renderview);
CV_RegisterVar(&cv_renderer);
#ifdef HWRENDER
CV_RegisterVar(&cv_newrenderer);
#endif
CV_RegisterVar(&cv_scr_depth);
CV_RegisterVar(&cv_scr_width);
CV_RegisterVar(&cv_scr_height);
CV_RegisterVar(&cv_soundtest);
CV_RegisterVar(&cv_perfstats);
// ingame object placing
COM_AddCommand("objectplace", Command_ObjectPlace_f);
COM_AddCommand("writethings", Command_Writethings_f);
@ -1126,6 +1122,8 @@ static void SetPlayerName(INT32 playernum, char *newname)
if (netgame)
HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false);
player_name_changes[playernum]++;
strcpy(player_names[playernum], newname);
}
}
@ -1302,7 +1300,12 @@ static void SendNameAndColor(void)
snacpending++;
// Don't change name if muted
if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))
if (player_name_changes[consoleplayer] >= MAXNAMECHANGES)
{
CV_StealthSet(&cv_playername, player_names[consoleplayer]);
HU_AddChatText("\x85*You must wait to change your name again", false);
}
else if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))
CV_StealthSet(&cv_playername, player_names[consoleplayer]);
else // Cleanup name if changing it
CleanupPlayerName(consoleplayer, cv_playername.zstring);
@ -1463,8 +1466,11 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
skin = READUINT8(*cp);
// set name
if (strcasecmp(player_names[playernum], name) != 0)
SetPlayerName(playernum, name);
if (player_name_changes[playernum] < MAXNAMECHANGES)
{
if (strcasecmp(player_names[playernum], name) != 0)
SetPlayerName(playernum, name);
}
// set color
p->skincolor = color % numskincolors;
@ -3241,97 +3247,130 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
*/
static void Command_Addfile(void)
{
const char *fn, *p;
char buf[256];
char *buf_p = buf;
INT32 i;
int musiconly; // W_VerifyNMUSlumps isn't boolean
size_t argc = COM_Argc(); // amount of arguments total
size_t curarg; // current argument index
if (COM_Argc() != 2)
const char *addedfiles[argc]; // list of filenames already processed
size_t numfilesadded = 0; // the amount of filenames processed
if (argc < 2)
{
CONS_Printf(M_GetText("addfile <wadfile.wad>: load wad file\n"));
return;
}
else
fn = COM_Argv(1);
// Disallow non-printing characters and semicolons.
for (i = 0; fn[i] != '\0'; i++)
if (!isprint(fn[i]) || fn[i] == ';')
return;
musiconly = W_VerifyNMUSlumps(fn);
if (!musiconly)
{
// ... But only so long as they contain nothing more then music and sprites.
if (netgame && !(server || IsPlayerAdmin(consoleplayer)))
{
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
return;
}
G_SetGameModified(multiplayer);
}
// Add file on your client directly if it is trivial, or you aren't in a netgame.
if (!(netgame || multiplayer) || musiconly)
{
P_AddWadFile(fn);
CONS_Printf(M_GetText("addfile <filename.pk3/wad/lua/soc> [filename2...] [...]: Load add-ons\n"));
return;
}
p = fn+strlen(fn);
while(--p >= fn)
if (*p == '\\' || *p == '/' || *p == ':')
break;
++p;
// check total packet size and no of files currently loaded
// See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
// start at one to skip command name
for (curarg = 1; curarg < argc; curarg++)
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
}
const char *fn, *p;
char buf[256];
char *buf_p = buf;
INT32 i;
size_t ii;
int musiconly; // W_VerifyNMUSlumps isn't boolean
boolean fileadded = false;
WRITESTRINGN(buf_p,p,240);
fn = COM_Argv(curarg);
// calculate and check md5
{
UINT8 md5sum[16];
#ifdef NOMD5
memset(md5sum,0,16);
#else
FILE *fhandle;
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL)
// For the amount of filenames previously processed...
for (ii = 0; ii < numfilesadded; ii++)
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn);
md5_stream(fhandle, md5sum);
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE);
fclose(fhandle);
}
else // file not found
return;
for (i = 0; i < numwadfiles; i++)
{
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
// If this is one of them, don't try to add it.
if (!strcmp(fn, addedfiles[ii]))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
return;
fileadded = true;
break;
}
}
#endif
WRITEMEM(buf_p, md5sum, 16);
}
if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file
SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf);
else
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
// If we've added this one, skip to the next one.
if (fileadded)
{
CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn);
continue;
}
// Disallow non-printing characters and semicolons.
for (i = 0; fn[i] != '\0'; i++)
if (!isprint(fn[i]) || fn[i] == ';')
return;
musiconly = W_VerifyNMUSlumps(fn);
if (!musiconly)
{
// ... But only so long as they contain nothing more then music and sprites.
if (netgame && !(server || IsPlayerAdmin(consoleplayer)))
{
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
continue;
}
G_SetGameModified(multiplayer);
}
// Add file on your client directly if it is trivial, or you aren't in a netgame.
if (!(netgame || multiplayer) || musiconly)
{
P_AddWadFile(fn);
addedfiles[numfilesadded++] = fn;
continue;
}
p = fn+strlen(fn);
while(--p >= fn)
if (*p == '\\' || *p == '/' || *p == ':')
break;
++p;
// check total packet size and no of files currently loaded
// See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
}
WRITESTRINGN(buf_p,p,240);
// calculate and check md5
{
UINT8 md5sum[16];
#ifdef NOMD5
memset(md5sum,0,16);
#else
FILE *fhandle;
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL)
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn);
md5_stream(fhandle, md5sum);
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE);
fclose(fhandle);
}
else // file not found
continue;
for (i = 0; i < numwadfiles; i++)
{
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
continue;
}
}
#endif
WRITEMEM(buf_p, md5sum, 16);
}
addedfiles[numfilesadded++] = fn;
if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file
SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf);
else
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
}
}
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)

View File

@ -114,6 +114,8 @@ extern consvar_t cv_skipmapcheck;
extern consvar_t cv_sleep;
extern consvar_t cv_perfstats;
extern char timedemo_name[256];
extern boolean timedemo_csv;
extern char timedemo_csv_id[256];

View File

@ -51,6 +51,7 @@ typedef enum
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_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
} skinflags_t;

View File

@ -29,8 +29,9 @@
#include "p_local.h" // for var1 and var2, and some constants
#include "p_setup.h"
#include "r_data.h"
#include "r_textures.h"
#include "r_draw.h"
#include "r_patch.h"
#include "r_picformats.h"
#include "r_things.h" // R_Char2Frame
#include "r_sky.h"
#include "fastcmp.h"
@ -9516,6 +9517,7 @@ struct {
{"RING_DIST",RING_DIST},
{"PUSHACCEL",PUSHACCEL},
{"MODID",MODID}, // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into.
{"MODVERSION",MODVERSION}, // or what version of the mod this is.
{"CODEBASE",CODEBASE}, // or what release of SRB2 this is.
{"NEWTICRATE",NEWTICRATE}, // TICRATE*NEWTICRATERATIO
{"NEWTICRATERATIO",NEWTICRATERATIO},
@ -9699,6 +9701,7 @@ struct {
{"SF_NONIGHTSSUPER",SF_NONIGHTSSUPER},
{"SF_NOSUPERSPRITES",SF_NOSUPERSPRITES},
{"SF_NOSUPERJUMPBOOST",SF_NOSUPERJUMPBOOST},
{"SF_CANBUSTWALLS",SF_CANBUSTWALLS},
// Dashmode constants
{"DASHMODE_THRESHOLD",DASHMODE_THRESHOLD},
@ -9906,6 +9909,25 @@ struct {
{"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel
{"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
// PolyObject flags
{"POF_CLIPLINES",POF_CLIPLINES}, ///< Test against lines for collision
{"POF_CLIPPLANES",POF_CLIPPLANES}, ///< Test against tops and bottoms for collision
{"POF_SOLID",POF_SOLID}, ///< Clips things.
{"POF_TESTHEIGHT",POF_TESTHEIGHT}, ///< Test line collision with heights
{"POF_RENDERSIDES",POF_RENDERSIDES}, ///< Renders the sides.
{"POF_RENDERTOP",POF_RENDERTOP}, ///< Renders the top.
{"POF_RENDERBOTTOM",POF_RENDERBOTTOM}, ///< Renders the bottom.
{"POF_RENDERPLANES",POF_RENDERPLANES}, ///< Renders top and bottom.
{"POF_RENDERALL",POF_RENDERALL}, ///< Renders everything.
{"POF_INVERT",POF_INVERT}, ///< Inverts collision (like a cage).
{"POF_INVERTPLANES",POF_INVERTPLANES}, ///< Render inside planes.
{"POF_INVERTPLANESONLY",POF_INVERTPLANESONLY}, ///< Only render inside planes.
{"POF_PUSHABLESTOP",POF_PUSHABLESTOP}, ///< Pushables will stop movement.
{"POF_LDEXEC",POF_LDEXEC}, ///< This PO triggers a linedef executor.
{"POF_ONESIDE",POF_ONESIDE}, ///< Only use the first side of the linedef.
{"POF_NOSPECIALS",POF_NOSPECIALS}, ///< Don't apply sector specials.
{"POF_SPLAT",POF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible).
#ifdef HAVE_LUA_SEGS
// Node flags
{"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf.
@ -10844,7 +10866,6 @@ static inline int lib_getenum(lua_State *L)
}
else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release...
{
LUA_Deprecated(L, "PF_USEDOWN", "PF_SPINDOWN");
lua_pushinteger(L, (lua_Integer)PF_SPINDOWN);
return 1;
}
@ -11116,7 +11137,6 @@ static inline int lib_getenum(lua_State *L)
if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release...
{
LUA_Deprecated(L, "BT_USE", "BT_SPIN");
lua_pushinteger(L, (lua_Integer)BT_SPIN);
return 1;
}

View File

@ -29,7 +29,6 @@
// Use Mixer interface?
#ifdef HAVE_MIXER
#define SOUND SOUND_MIXER
#define NOHS // No HW3SOUND
#ifdef HW3SOUND
#undef HW3SOUND
#endif
@ -45,7 +44,6 @@
// Use FMOD?
#ifdef HAVE_FMOD
#define SOUND SOUND_FMOD
#define NOHS // No HW3SOUND
#ifdef HW3SOUND
#undef HW3SOUND
#endif
@ -62,10 +60,6 @@
#if !defined (HWRENDER) && !defined (NOHW)
#define HWRENDER
#endif
// judgecutor: 3D sound support
#if !defined(HW3SOUND) && !defined (NOHS)
#define HW3SOUND
#endif
#endif
#ifdef _WIN32
@ -135,8 +129,15 @@ extern char logfilename[1024];
#define VERSIONSTRING "Development EXE"
// most interface strings are ignored in development mode.
// we use comprevision and compbranch instead.
// VERSIONSTRING_RC is for the resource-definition script used by windows builds
#else
#ifdef BETAVERSION
#define VERSIONSTRING "v"SRB2VERSION" "BETAVERSION
#define VERSIONSTRING_RC SRB2VERSION " " BETAVERSION "\0"
#else
#define VERSIONSTRING "v"SRB2VERSION
#define VERSIONSTRING_RC SRB2VERSION "\0"
#endif
// Hey! If you change this, add 1 to the MODVERSION below!
// Otherwise we can't force updates!
#endif
@ -159,7 +160,9 @@ extern char logfilename[1024];
// the other options the same.
// Comment out this line to completely disable update alerts (recommended for testing, but not for release)
#ifndef BETAVERSION
#define UPDATE_ALERT
#endif
// The string used in the alert that pops up in the event of an update being available.
// Please change to apply to your modification (we don't want everyone asking where your mod is on SRB2.org!).
@ -644,4 +647,10 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Maintain compatibility with older 2.2 demos
#define OLD22DEMOCOMPAT
#if defined (HAVE_CURL) && ! defined (NONET)
#define MASTERSERVER
#else
#undef UPDATE_ALERT
#endif
#endif // __DOOMDEF__

View File

@ -371,4 +371,12 @@ typedef UINT32 tic_t;
#define WSTRING2(s) L ## 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))
#endif //__DOOMTYPE__

View File

@ -8,8 +8,8 @@
UINT8 cdaudio_started = 0;
consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cd_volume = CVAR_INIT ("cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL);
consvar_t cdUpdate = CVAR_INIT ("cd_update","1",CV_SAVE, NULL, NULL);
void I_InitCD(void){}

View File

@ -8,7 +8,7 @@ boolean highcolor = false;
boolean allow_fullscreen = false;
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL);
void I_StartupGraphics(void){}
void I_ShutdownGraphics(void){}

View File

@ -225,6 +225,9 @@ static INT32 cutscene_textspeed = 0;
static UINT8 cutscene_boostspeed = 0;
static tic_t cutscene_lasttextwrite = 0;
// STJR Intro
char stjrintro[9] = "STJRI000";
//
// This alters the text string cutscene_disptext.
// Use the typical string drawing functions to display it.
@ -312,7 +315,7 @@ const char *introtext[NUMINTROSCENES];
static tic_t introscenetime[NUMINTROSCENES] =
{
7*TICRATE + (TICRATE/2), // STJr Presents
5*TICRATE, // STJr Presents
11*TICRATE + (TICRATE/2), // Two months had passed since...
15*TICRATE + (TICRATE/2), // As it was about to drain the rings...
14*TICRATE, // What Sonic, Tails, and Knuckles...
@ -527,6 +530,7 @@ static void F_IntroDrawScene(void)
switch (intro_scenenum)
{
case 0:
bgxoffs = 28;
break;
case 1:
background = W_CachePatchName("INTRO1", PU_PATCH);
@ -617,97 +621,34 @@ static void F_IntroDrawScene(void)
}
else if (intro_scenenum == 0) // STJr presents
{
// "Waaaaaaah" intro
if (finalecount-TICRATE/2 < 4*TICRATE+23) {
// aspect is FRACUNIT/2 for 4:3 (source) resolutions, smaller for 16:10 (SRB2) resolutions
fixed_t aspect = (FRACUNIT + (FRACUNIT*4/3 - FRACUNIT*vid.width/vid.height)/2)>>1;
fixed_t x,y;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 2);
if (finalecount < 30) { // Cry!
if (finalecount < 4)
S_StopMusic();
if (finalecount == 4)
S_ChangeMusicInternal("_stjr", false);
x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(334<<FRACBITS, aspect)/2;
y = (BASEVIDHEIGHT<<FRACBITS)/2 - FixedMul(358<<FRACBITS, aspect)/2;
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH1", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
if (finalecount > 6) {
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH2", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
}
if (finalecount > 10) {
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH3", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
}
if (finalecount > 14) {
V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH4", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
}
}
else if (finalecount-30 < 20) { // Big eggy
background = W_CachePatchName("FEEDIN", PU_PATCH);
x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(560<<FRACBITS, aspect)/2;
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(477<<FRACBITS, aspect);
V_DrawSciencePatch(x, y, V_SNAPTOBOTTOM, background, aspect);
}
else if (finalecount-50 < 30) { // Zoom out
fixed_t scale = FixedDiv(aspect, FixedDiv((finalecount-50)<<FRACBITS, (15<<FRACBITS))+FRACUNIT);
background = W_CachePatchName("FEEDIN", PU_PATCH);
x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(560<<FRACBITS, aspect)/2 + (FixedMul(560<<FRACBITS, aspect) - FixedMul(560<<FRACBITS, scale));
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(477<<FRACBITS, scale);
V_DrawSciencePatch(x, y, V_SNAPTOBOTTOM, background, scale);
}
else
if (intro_curtime > 1 && intro_curtime < (INT32)introscenetime[intro_scenenum])
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
if (intro_curtime < TICRATE-5) // Make the text shine!
sprintf(stjrintro, "STJRI%03u", intro_curtime-1);
else if (intro_curtime >= TICRATE-6 && intro_curtime < 2*TICRATE-20) // Pause on black screen for just a second
return;
else if (intro_curtime == 2*TICRATE-19)
{
{
// Draw tiny eggy
fixed_t scale = FixedMul(FRACUNIT/3, aspect);
background = W_CachePatchName("FEEDIN", PU_PATCH);
x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(560<<FRACBITS, aspect)/2 + (FixedMul(560<<FRACBITS, aspect) - FixedMul(560<<FRACBITS, scale));
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(477<<FRACBITS, scale);
V_DrawSciencePatch(x, y, V_SNAPTOBOTTOM, background, scale);
}
// Fade in the text
// The text fade out is automatically handled when switching to a new intro scene
strncpy(stjrintro, "STJRI029", 9);
S_ChangeMusicInternal("_stjr", false);
if (finalecount-84 < 58) { // Pure Fat is driving up!
int ftime = (finalecount-84);
x = (-189*FRACUNIT) + (FixedMul((6<<FRACBITS)+FRACUNIT/3, ftime<<FRACBITS) - FixedMul((6<<FRACBITS)+FRACUNIT/3, FixedDiv(FixedMul(ftime<<FRACBITS, ftime<<FRACBITS), 120<<FRACBITS)));
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(417<<FRACBITS, aspect);
// Draw the body
V_DrawSciencePatch(x, y, V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT1", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the door
V_DrawSciencePatch(x+FixedMul(344<<FRACBITS, aspect), y+FixedMul(292<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT2", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the wheel
V_DrawSciencePatch(x+FixedMul(178<<FRACBITS, aspect), y+FixedMul(344<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName(va("TYRE%02u",(abs(finalecount-144)/3)%16), PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the wheel cover
V_DrawSciencePatch(x+FixedMul(88<<FRACBITS, aspect), y+FixedMul(238<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT3", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
} else { // Pure Fat has stopped!
y = (BASEVIDHEIGHT<<FRACBITS) - FixedMul(417<<FRACBITS, aspect);
// Draw the body
V_DrawSciencePatch(0, y, V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT1", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the wheel
V_DrawSciencePatch(FixedMul(178<<FRACBITS, aspect), y+FixedMul(344<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("TYRE00", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the wheel cover
V_DrawSciencePatch(FixedMul(88<<FRACBITS, aspect), y+FixedMul(238<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT3", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
// Draw the door
if (finalecount-TICRATE/2 > 4*TICRATE) { // Door is being raised!
int ftime = (finalecount-TICRATE/2-4*TICRATE);
y -= FixedDiv((ftime*ftime)<<FRACBITS, 23<<FRACBITS);
}
V_DrawSciencePatch(FixedMul(344<<FRACBITS, aspect), y+FixedMul(292<<FRACBITS, aspect), V_SNAPTOLEFT|V_SNAPTOBOTTOM, (patch = W_CachePatchName("PUREFAT2", PU_PATCH)), aspect);
W_UnlockCachedPatch(patch);
}
background = W_CachePatchName(stjrintro, PU_PATCH);
wipestyleflags = WSF_FADEIN;
F_WipeStartScreen();
F_TryColormapFade(31);
V_DrawSmallScaledPatch(bgxoffs, 84, 0, background);
F_WipeEndScreen();
F_RunWipe(0,true);
}
if (!WipeInAction) // Draw the patch if not in a wipe
{
background = W_CachePatchName(stjrintro, PU_PATCH);
V_DrawSmallScaledPatch(bgxoffs, 84, 0, background);
}
} else {
V_DrawCreditString((160 - V_CreditStringWidth("SONIC TEAM JR")/2)<<FRACBITS, 80<<FRACBITS, 0, "SONIC TEAM JR");
V_DrawCreditString((160 - V_CreditStringWidth("PRESENTS")/2)<<FRACBITS, 96<<FRACBITS, 0, "PRESENTS");
}
}
else if (intro_scenenum == 10) // Sky Runner
@ -1017,7 +958,7 @@ void F_IntroDrawer(void)
F_WipeEndScreen();
F_RunWipe(99,true);
}
/*else if (intro_scenenum == 12 && intro_curtime == 7*TICRATE)
/*else if (intro_scenenum == 11 && intro_curtime == 7*TICRATE)
{
patch_t *confront = W_CachePatchName("CONFRONT", PU_PATCH);
@ -1126,61 +1067,58 @@ static const char *credits[] = {
"\1Credits",
"",
"\1Game Design",
"Ben \"Mystic\" Geyer",
"Sonic Team Junior",
"\"SSNTails\"",
"Johnny \"Sonikku\" Wallbank",
"",
"\1Programming",
"Alam \"GBC\" Arias",
"Logan \"GBA\" Arias",
"Colette \"fickleheart\" Bordelon",
"Andrew \"orospakr\" Clunis",
"Sally \"TehRealSalt\" Cochenour",
"Gregor \"Oogaland\" Dick",
"Callum Dickinson",
"Scott \"Graue\" Feeney",
"Victor \"SteelT\" Fuentes",
"Nathan \"Jazz\" Giroux",
"\"Golden\"",
"Vivian \"toaster\" Grannell",
"Julio \"Chaos Zero 64\" Guir",
"\"Hannu_Hanhi\"", // For many OpenGL performance improvements!
"Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe",
"\"james\"",
"Iestyn \"Monster Iestyn\" Jealous",
"\"Jimita\"",
"Ronald \"Furyhunter\" Kinard", // The SDL2 port
"Louis-Antoine \"LJ Sonic\" de Moulins", // de Rochefort doesn't quite fit on the screen sorry lol
"John \"JTE\" Muniz",
"Ehab \"Wolfy\" Saeed",
"Jonas \"MascaraSnake\" Sauer",
"\"Kaito Sinclaire\"",
"\"SSNTails\"",
"Lachlan \"Lach\" Wright",
"Marco \"mazmazz\" Zafra",
"",
"\1Programming",
"\1Assistance",
"Colette \"fickleheart\" Bordelon",
"\"chi.miru\"", // helped port slope drawing code from ZDoom
"Andrew \"orospakr\" Clunis",
"Sally \"TehRealSalt\" Cochenour",
"Gregor \"Oogaland\" Dick",
"Julio \"Chaos Zero 64\" Guir",
"\"Hannu_Hanhi\"", // For many OpenGL performance improvements!
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"Ronald \"Furyhunter\" Kinard", // The SDL2 port
"\"Lat'\"", // SRB2-CHAT, the chat window from Kart
"Matthew \"Shuffle\" Marsalko",
"Steven \"StroggOnMeth\" McGranahan",
"\"Morph\"", // For SRB2Morphed stuff
"Louis-Antoine \"LJ Sonic\" de Moulins", // de Rochefort doesn't quite fit on the screen sorry lol
"John \"JTE\" Muniz",
"Colin \"Sonict\" Pfaff",
"Sean \"Sryder13\" Ryder",
"Ehab \"Wolfy\" Saeed",
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
"Jonas \"MascaraSnake\" Sauer",
"Wessel \"sphere\" Smit",
"Ben \"Cue\" Woodford",
"\"SSNTails\"",
"\"Varren\"",
"\"VelocitOni\"", // Wrote the original dashmode script
"Ikaro \"Tatsuru\" Vinhas",
// Git contributors with 5+ approved merges of substantive quality,
// or contributors with at least one groundbreaking merge, may be named.
// Everyone else is acknowledged under "Special Thanks > SRB2 Community Contributors".
"Ben \"Cue\" Woodford",
"Lachlan \"Lach\" Wright",
"Marco \"mazmazz\" Zafra",
"",
"\1Art",
"Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D:
"\"Arrietty\"",
"Ryan \"Blaze Hedgehog\" Bloom",
"Graeme P. \"SuperPhanto\" Caldwell", // for the new brak render
"\"ChrispyPixels\"",
"Paul \"Boinciel\" Clempson",
"Sally \"TehRealSalt\" Cochenour",
@ -1188,6 +1126,8 @@ static const char *credits[] = {
"Desmond \"Blade\" DesJardins",
"Sherman \"CoatRack\" DesJardins",
"\"DirkTheHusky\"",
"Jesse \"Jeck Jims\" Emerick",
"\"Fighter_Builder\"", // for the CEZ3 button debris
"Buddy \"KinkaJoy\" Fischer",
"Vivian \"toaster\" Grannell",
"James \"SwitchKaze\" Hale",
@ -1200,6 +1140,7 @@ static const char *credits[] = {
"Andrew \"Senku Niola\" Moran",
"\"MotorRoach\"",
"Phillip \"TelosTurntable\" Robinson",
"\"Scizor300\"",
"Wessel \"sphere\" Smit",
"David \"Instant Sonic\" Spencer Jr.",
"\"SSNTails\"",
@ -1213,9 +1154,9 @@ static const char *credits[] = {
"Malcolm \"RedXVI\" Brown",
"Dave \"DemonTomatoDave\" Bulmer",
"Paul \"Boinciel\" Clempson",
"\"Cyan Helkaraxe\"",
"Shane \"CobaltBW\" Ellis",
"James \"SeventhSentinel\" Hall",
"Cyan Helkaraxe",
"Kepa \"Nev3r\" Iceta",
"Iestyn \"Monster Iestyn\" Jealous",
"Jarel \"Arrow\" Jones",
@ -1242,8 +1183,9 @@ static const char *credits[] = {
"James \"SeventhSentinel\" Hall",
"Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe",
"Alexander \"DrTapeworm\" Moench-Ford",
"\"Kaito Sinclaire\"",
"Alexander \"DrTapeworm\" Moench-Ford",
"\"Revan\"",
"Anna \"QueenDelta\" Sandlin",
"Wessel \"sphere\" Smit",
"\"Spazzo\"",
@ -1266,7 +1208,7 @@ static const char *credits[] = {
"\1Testing",
"Discord Community Testers",
"Hank \"FuriousFox\" Brannock",
"Cody \"SRB2 Playah\" Koester",
"Cody \"Playah\" Koester",
"Skye \"OmegaVelocity\" Meredith",
"Stephen \"HEDGESMFG\" Moellering",
"Rosalie \"ST218\" Molina",
@ -1283,13 +1225,6 @@ static const char *credits[] = {
"Pascal \"CodeImp\" vd Heiden", // Doom Builder developer
"Randi Heit (<!>)", // For their MSPaint <!> sprite that we nicked
"Simon \"sirjuddington\" Judd", // SLADE developer
// Acknowledged here are the following:
// Minor merge request authors, see guideline above
// - Golden - Expanded thin font
// Creators of small quantities of sprite/texture assets
// - Arietty - New Green Hill-styled textures
// - Scizor300 - the only other contributor to the 2.0 SRB2 Asset Pack
// - Revan/Icefox - the new Nimbus Ruins skybox
"SRB2 Community Contributors",
"",
"\1Produced By",

View File

@ -312,18 +312,18 @@ static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"},
#endif
{3, "CUSTOM"}, {0, NULL}};
consvar_t cv_addons_option = {"addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_folder = {"addons_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_option = CVAR_INIT ("addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange);
consvar_t cv_addons_folder = CVAR_INIT ("addons_folder", "", CV_SAVE, NULL, NULL);
static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}};
consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_md5 = CVAR_INIT ("addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL);
consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_showall = CVAR_INIT ("addons_showall", "No", CV_SAVE, CV_YesNo, NULL);
consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_search_case = CVAR_INIT ("addons_search_case", "No", CV_SAVE, CV_YesNo, NULL);
static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}};
consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_addons_search_type = CVAR_INIT ("addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL);
char menupath[1024];
size_t menupathindex[menudepth];

View File

@ -94,7 +94,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x000d
#define DEMOVERSION 0x000e
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -345,32 +345,29 @@ void G_WriteGhostTic(mobj_t *ghost)
else
{
// For moving normally:
// Store one full byte of movement, plus one byte of fractional movement.
INT16 momx = (INT16)((ghost->x-oldghost.x)>>8);
INT16 momy = (INT16)((ghost->y-oldghost.y)>>8);
fixed_t momx = ghost->x-oldghost.x;
fixed_t momy = ghost->y-oldghost.y;
if (momx != oldghost.momx
|| momy != oldghost.momy)
{
oldghost.momx = momx;
oldghost.momy = momy;
ziptic |= GZT_MOMXY;
WRITEINT16(demo_p,momx);
WRITEINT16(demo_p,momy);
WRITEFIXED(demo_p,momx);
WRITEFIXED(demo_p,momy);
}
momx = (INT16)((ghost->z-oldghost.z)>>8);
momx = ghost->z-oldghost.z;
if (momx != oldghost.momz)
{
oldghost.momz = momx;
ziptic |= GZT_MOMZ;
WRITEINT16(demo_p,momx);
WRITEFIXED(demo_p,momx);
}
// This SHOULD set oldghost.x/y/z to match ghost->x/y/z
// but it keeps the fractional loss of one byte,
// so it will hopefully be made up for in future tics.
oldghost.x += oldghost.momx<<8;
oldghost.y += oldghost.momy<<8;
oldghost.z += oldghost.momz<<8;
oldghost.x += oldghost.momx;
oldghost.y += oldghost.momy;
oldghost.z += oldghost.momz;
}
#undef MAXMOM
@ -464,7 +461,7 @@ void G_WriteGhostTic(mobj_t *ghost)
if (ghost->player && ghost->player->followmobj && !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->flags2 & MF2_DONTDRAW))) // bloats tails runs but what can ya do
{
INT16 temp;
fixed_t temp;
UINT8 *followtic_p = demo_p++;
UINT8 followtic = 0;
@ -492,12 +489,12 @@ void G_WriteGhostTic(mobj_t *ghost)
WRITEFIXED(demo_p,ghost->player->followmobj->scale);
}
temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8);
WRITEINT16(demo_p,temp);
temp = ghost->player->followmobj->x-ghost->x;
WRITEFIXED(demo_p,temp);
temp = ghost->player->followmobj->y-ghost->y;
WRITEFIXED(demo_p,temp);
temp = ghost->player->followmobj->z-ghost->z;
WRITEFIXED(demo_p,temp);
if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
@ -547,11 +544,11 @@ void G_ConsGhostTic(void)
{
if (ziptic & GZT_MOMXY)
{
oldghost.momx = READINT16(demo_p)<<8;
oldghost.momy = READINT16(demo_p)<<8;
oldghost.momx = (demoversion < 0x000e) ? READINT16(demo_p)<<8 : READFIXED(demo_p);
oldghost.momy = (demoversion < 0x000e) ? READINT16(demo_p)<<8 : READFIXED(demo_p);
}
if (ziptic & GZT_MOMZ)
oldghost.momz = READINT16(demo_p)<<8;
oldghost.momz = (demoversion < 0x000e) ? READINT16(demo_p)<<8 : READFIXED(demo_p);
oldghost.x += oldghost.momx;
oldghost.y += oldghost.momy;
oldghost.z += oldghost.momz;
@ -627,9 +624,8 @@ void G_ConsGhostTic(void)
}
if (followtic & FZT_SCALE)
demo_p += sizeof(fixed_t);
demo_p += sizeof(INT16);
demo_p += sizeof(INT16);
demo_p += sizeof(INT16);
// momx, momy and momz
demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3;
if (followtic & FZT_SKIN)
demo_p++;
demo_p += sizeof(UINT16);
@ -697,11 +693,11 @@ void G_GhostTicker(void)
{
if (ziptic & GZT_MOMXY)
{
g->oldmo.momx = READINT16(g->p)<<8;
g->oldmo.momy = READINT16(g->p)<<8;
g->oldmo.momx = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
g->oldmo.momy = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
}
if (ziptic & GZT_MOMZ)
g->oldmo.momz = READINT16(g->p)<<8;
g->oldmo.momz = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
g->oldmo.x += g->oldmo.momx;
g->oldmo.y += g->oldmo.momy;
g->oldmo.z += g->oldmo.momz;
@ -905,11 +901,11 @@ void G_GhostTicker(void)
P_SetScale(follow, follow->destscale);
P_UnsetThingPosition(follow);
temp = READINT16(g->p)<<8;
temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
follow->x = g->mo->x + temp;
temp = READINT16(g->p)<<8;
temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
follow->y = g->mo->y + temp;
temp = READINT16(g->p)<<8;
temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p);
follow->z = g->mo->z + temp;
P_SetThingPosition(follow);
if (followtic & FZT_SKIN)
@ -1010,11 +1006,11 @@ void G_ReadMetalTic(mobj_t *metal)
{
if (ziptic & GZT_MOMXY)
{
oldmetal.momx = READINT16(metal_p)<<8;
oldmetal.momy = READINT16(metal_p)<<8;
oldmetal.momx = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
oldmetal.momy = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
}
if (ziptic & GZT_MOMZ)
oldmetal.momz = READINT16(metal_p)<<8;
oldmetal.momz = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
oldmetal.x += oldmetal.momx;
oldmetal.y += oldmetal.momy;
oldmetal.z += oldmetal.momz;
@ -1149,11 +1145,11 @@ void G_ReadMetalTic(mobj_t *metal)
P_SetScale(follow, follow->destscale);
P_UnsetThingPosition(follow);
temp = READINT16(metal_p)<<8;
temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
follow->x = metal->x + temp;
temp = READINT16(metal_p)<<8;
temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
follow->y = metal->y + temp;
temp = READINT16(metal_p)<<8;
temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p);
follow->z = metal->z + temp;
P_SetThingPosition(follow);
if (followtic & FZT_SKIN)
@ -1213,32 +1209,30 @@ void G_WriteMetalTic(mobj_t *metal)
else
{
// For moving normally:
// Store one full byte of movement, plus one byte of fractional movement.
INT16 momx = (INT16)((metal->x-oldmetal.x)>>8);
INT16 momy = (INT16)((metal->y-oldmetal.y)>>8);
// Store movement as a fixed value
fixed_t momx = metal->x-oldmetal.x;
fixed_t momy = metal->y-oldmetal.y;
if (momx != oldmetal.momx
|| momy != oldmetal.momy)
{
oldmetal.momx = momx;
oldmetal.momy = momy;
ziptic |= GZT_MOMXY;
WRITEINT16(demo_p,momx);
WRITEINT16(demo_p,momy);
WRITEFIXED(demo_p,momx);
WRITEFIXED(demo_p,momy);
}
momx = (INT16)((metal->z-oldmetal.z)>>8);
momx = metal->z-oldmetal.z;
if (momx != oldmetal.momz)
{
oldmetal.momz = momx;
ziptic |= GZT_MOMZ;
WRITEINT16(demo_p,momx);
WRITEFIXED(demo_p,momx);
}
// This SHOULD set oldmetal.x/y/z to match metal->x/y/z
// but it keeps the fractional loss of one byte,
// so it will hopefully be made up for in future tics.
oldmetal.x += oldmetal.momx<<8;
oldmetal.y += oldmetal.momy<<8;
oldmetal.z += oldmetal.momz<<8;
oldmetal.x += oldmetal.momx;
oldmetal.y += oldmetal.momy;
oldmetal.z += oldmetal.momz;
}
#undef MAXMOM
@ -1307,7 +1301,7 @@ void G_WriteMetalTic(mobj_t *metal)
if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->flags2 & MF2_DONTDRAW)))
{
INT16 temp;
fixed_t temp;
UINT8 *followtic_p = demo_p++;
UINT8 followtic = 0;
@ -1335,12 +1329,12 @@ void G_WriteMetalTic(mobj_t *metal)
WRITEFIXED(demo_p,metal->player->followmobj->scale);
}
temp = (INT16)((metal->player->followmobj->x-metal->x)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((metal->player->followmobj->y-metal->y)>>8);
WRITEINT16(demo_p,temp);
temp = (INT16)((metal->player->followmobj->z-metal->z)>>8);
WRITEINT16(demo_p,temp);
temp = metal->player->followmobj->x-metal->x;
WRITEFIXED(demo_p,temp);
temp = metal->player->followmobj->y-metal->y;
WRITEFIXED(demo_p,temp);
temp = metal->player->followmobj->z-metal->z;
WRITEFIXED(demo_p,temp);
if (followtic & FZT_SKIN)
WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
WRITEUINT16(demo_p,metal->player->followmobj->sprite);
@ -1818,6 +1812,7 @@ void G_DoPlayDemo(char *defdemoname)
demoversion = READUINT16(demo_p);
switch(demoversion)
{
case 0x000d:
case DEMOVERSION: // latest always supported
cnamelen = MAXCOLORNAME;
break;
@ -1933,9 +1928,8 @@ void G_DoPlayDemo(char *defdemoname)
if (use_old_demo_vars)
CV_LoadOldDemoVars(&demo_p);
else
#else
CV_LoadDemoVars(&demo_p);
#endif
CV_LoadDemoVars(&demo_p);
// Sigh ... it's an empty demo.
if (*demo_p == DEMOMARKER)
@ -2073,6 +2067,7 @@ void G_AddGhost(char *defdemoname)
ghostversion = READUINT16(p);
switch(ghostversion)
{
case 0x000d:
case DEMOVERSION: // latest always supported
cnamelen = MAXCOLORNAME;
break;
@ -2168,7 +2163,7 @@ void G_AddGhost(char *defdemoname)
count = READUINT16(p);
while (count--)
{
p += 2;
SKIPSTRING(p);
SKIPSTRING(p);
p++;
}
@ -2324,6 +2319,7 @@ void G_DoPlayMetal(void)
switch(metalversion)
{
case DEMOVERSION: // latest always supported
case 0x000d: // There are checks wheter the momentum is from older demo versions or not
case 0x000c: // all that changed between then and now was longer color name
break;
// too old, cannot support.

View File

@ -297,100 +297,100 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
// don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler.
// it automatically becomes compact with 20+ players, but if you like it, I guess you can turn that on!
consvar_t cv_compactscoreboard= {"compactscoreboard", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_compactscoreboard= CVAR_INIT ("compactscoreboard", "Off", CV_SAVE, CV_OnOff, NULL);
// chat timer thingy
static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NULL}};
consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chattime = CVAR_INIT ("chattime", "8", CV_SAVE, chattime_cons_t, NULL);
// chatwidth
static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {300, "MAX"}, {0, NULL}};
consvar_t cv_chatwidth = {"chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatwidth = CVAR_INIT ("chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL);
// chatheight
static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}};
consvar_t cv_chatheight= {"chatheight", "8", CV_SAVE, chatheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatheight= CVAR_INIT ("chatheight", "8", CV_SAVE, chatheight_cons_t, NULL);
// chat notifications (do you want to hear beeps? I'd understand if you didn't.)
consvar_t cv_chatnotifications= {"chatnotifications", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatnotifications= CVAR_INIT ("chatnotifications", "On", CV_SAVE, CV_OnOff, NULL);
// chat spam protection (why would you want to disable that???)
consvar_t cv_chatspamprotection= {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatspamprotection= CVAR_INIT ("chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL);
// minichat text background
consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chatbacktint = CVAR_INIT ("chatbacktint", "On", CV_SAVE, CV_OnOff, NULL);
// old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.)
static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}};
consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_consolechat = CVAR_INIT ("chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL);
// Pause game upon window losing focus
consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_pauseifunfocused = CVAR_INIT ("pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL);
consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invertmouse = {"invertmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_alwaysfreelook = {"alwaysmlook", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invertmouse2 = {"invertmouse2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_alwaysfreelook2 = {"alwaysmlook2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasefreelook = {"chasemlook", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasefreelook2 = {"chasemlook2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousemove = {"mousemove", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousemove2 = {"mousemove2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair = CVAR_INIT ("crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL);
consvar_t cv_crosshair2 = CVAR_INIT ("crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL);
consvar_t cv_invertmouse = CVAR_INIT ("invertmouse", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_alwaysfreelook = CVAR_INIT ("alwaysmlook", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_invertmouse2 = CVAR_INIT ("invertmouse2", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_alwaysfreelook2 = CVAR_INIT ("alwaysmlook2", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_chasefreelook = CVAR_INIT ("chasemlook", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_chasefreelook2 = CVAR_INIT ("chasemlook2", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_mousemove = CVAR_INIT ("mousemove", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_mousemove2 = CVAR_INIT ("mousemove2", "Off", CV_SAVE, CV_OnOff, NULL);
// previously "analog", "analog2", "useranalog", and "useranalog2", invalidating 2.1-era copies of config.cfg
// changed because it'd be nice to see people try out our actually good controls with gamepads now autobrake exists
consvar_t cv_analog[2] = {
{"sessionanalog", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"sessionanalog2", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog2_OnChange, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("sessionanalog", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog_OnChange),
CVAR_INIT ("sessionanalog2", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, Analog2_OnChange),
};
consvar_t cv_useranalog[2] = {
{"configanalog", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"configanalog2", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog2_OnChange, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("configanalog", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog_OnChange),
CVAR_INIT ("configanalog2", "Off", CV_SAVE|CV_CALL|CV_NOSHOWHELP, CV_OnOff, UserAnalog2_OnChange),
};
// deez New User eXperiences
static CV_PossibleValue_t directionchar_cons_t[] = {{0, "Camera"}, {1, "Movement"}, {2, "Simple Locked"}, {0, NULL}};
consvar_t cv_directionchar[2] = {
{"directionchar", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar_OnChange, 0, NULL, NULL, 0, 0, NULL},
{"directionchar2", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar2_OnChange, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("directionchar", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar_OnChange),
CVAR_INIT ("directionchar2", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar2_OnChange),
};
consvar_t cv_autobrake = {"autobrake", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_autobrake2 = {"autobrake2", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_autobrake = CVAR_INIT ("autobrake", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake_OnChange);
consvar_t cv_autobrake2 = CVAR_INIT ("autobrake2", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake2_OnChange);
// hi here's some new controls
static CV_PossibleValue_t zerotoone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_cam_shiftfacing[2] = {
{"cam_shiftfacingchar", "0.33", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_shiftfacingchar", "0.33", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_shiftfacingchar", "0.33", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_shiftfacingchar", "0.33", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
consvar_t cv_cam_turnfacing[2] = {
{"cam_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_turnfacingchar", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
consvar_t cv_cam_turnfacingability[2] = {
{"cam_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_turnfacingability", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
consvar_t cv_cam_turnfacingspindash[2] = {
{"cam_turnfacingspindash", "0.5", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_turnfacingspindash", "0.5", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_turnfacingspindash", "0.5", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_turnfacingspindash", "0.5", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
consvar_t cv_cam_turnfacinginput[2] = {
{"cam_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
CVAR_INIT ("cam2_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL),
};
static CV_PossibleValue_t centertoggle_cons_t[] = {{0, "Hold"}, {1, "Toggle"}, {2, "Sticky Hold"}, {0, NULL}};
consvar_t cv_cam_centertoggle[2] = {
{"cam_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL),
CVAR_INIT ("cam2_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL),
};
static CV_PossibleValue_t lockedinput_cons_t[] = {{0, "Strafe"}, {1, "Turn"}, {0, NULL}};
consvar_t cv_cam_lockedinput[2] = {
{"cam_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL),
CVAR_INIT ("cam2_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL),
};
static CV_PossibleValue_t lockedassist_cons_t[] = {
@ -402,8 +402,8 @@ static CV_PossibleValue_t lockedassist_cons_t[] = {
{0, NULL}
};
consvar_t cv_cam_lockonboss[2] = {
{"cam_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
{"cam2_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
CVAR_INIT ("cam_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL),
CVAR_INIT ("cam2_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL),
};
typedef enum
@ -422,27 +422,27 @@ typedef enum
AXISFIRENORMAL,
} axis_input_e;
consvar_t cv_turnaxis = {"joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_moveaxis = {"joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sideaxis = {"joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_lookaxis = {"joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_jumpaxis = {"joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spinaxis = {"joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fireaxis = {"joyaxis_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis = {"joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_deadzone = {"joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_digitaldeadzone = {"joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_firenaxis = CVAR_INIT ("joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_deadzone = CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_turnaxis2 = {"joyaxis2_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_moveaxis2 = {"joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sideaxis2 = {"joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_lookaxis2 = {"joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_jumpaxis2 = {"joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spinaxis2 = {"joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_firenaxis2 = {"joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_deadzone2 = {"joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_digitaldeadzone2 = {"joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Axis-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_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);
#ifdef SEENAMES
player_t *seenplayer; // player we're aiming at right now
@ -452,6 +452,8 @@ player_t *seenplayer; // player we're aiming at right now
// so that it doesn't have to be updated depending on the value of MAXPLAYERS
char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
INT32 player_name_changes[MAXPLAYERS];
INT16 rw_maximums[NUM_WEAPONS] =
{
800, // MAX_INFINITY
@ -1675,6 +1677,10 @@ 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.
if (gamestate == GS_LEVEL)
LUAh_PlayerCmd(player, cmd);
//Reset away view if a command is given.
if (ssplayer == 1 && (cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer)
@ -2013,7 +2019,7 @@ boolean G_Responder(event_t *ev)
if (F_CreditResponder(ev))
{
// Skip credits for everyone
if (! serverrunning)/* hahahahahaha */
if (! netgame)
F_StartGameEvaluation();
else if (server || IsPlayerAdmin(consoleplayer))
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
@ -2345,6 +2351,11 @@ void G_Ticker(boolean run)
if (camtoggledelay2)
camtoggledelay2--;
if (gametic % NAMECHANGERATE == 0)
{
memset(player_name_changes, 0, sizeof player_name_changes);
}
}
}
@ -3507,7 +3518,7 @@ INT32 G_GetGametypeByName(const char *gametypestr)
//
boolean G_IsSpecialStage(INT32 mapnum)
{
if (gametype != GT_COOP || modeattacking == ATTACKING_RECORD)
if (modeattacking == ATTACKING_RECORD)
return false;
if (mapnum >= sstage_start && mapnum <= sstage_end)
return true;
@ -3808,7 +3819,7 @@ static void G_DoCompleted(void)
// a map of the proper gametype -- skip levels that don't support
// the current gametype. (Helps avoid playing boss levels in Race,
// for instance).
if (!spec)
if (!spec || nextmapoverride)
{
if (nextmap >= 0 && nextmap < NUMMAPS)
{
@ -3860,7 +3871,8 @@ static void G_DoCompleted(void)
if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1)
I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
lastmap = nextmap; // Remember last map for when you come out of the special stage.
if (!spec)
lastmap = nextmap; // Remember last map for when you come out of the special stage.
}
if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token)))
@ -3881,7 +3893,7 @@ static void G_DoCompleted(void)
}
}
if (spec && !gottoken)
if (spec && !gottoken && !nextmapoverride)
nextmap = lastmap; // Exiting from a special stage? Go back to the game. Tails 08-11-2001
automapactive = false;

View File

@ -18,6 +18,7 @@
#include "doomstat.h"
#include "d_event.h"
#include "g_demo.h"
#include "m_cheat.h" // objectplacing
extern char gamedatafilename[64];
extern char timeattackfolder[64];
@ -27,7 +28,8 @@ extern char customversionstring[32];
#ifdef SEENAMES
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 player_t players[MAXPLAYERS];
extern boolean playeringame[MAXPLAYERS];
@ -64,7 +66,7 @@ typedef enum {
CS_STANDARD,
CS_SIMPLE = CS_LMAOGALOG|CS_STANDARD,
} controlstyle_e;
#define G_ControlStyle(ssplayer) (cv_directionchar[(ssplayer)-1].value == 3 ? CS_LMAOGALOG : ((cv_analog[(ssplayer)-1].value ? CS_LMAOGALOG : 0) | (cv_directionchar[(ssplayer)-1].value ? CS_STANDARD : 0)))
#define G_ControlStyle(ssplayer) (cv_directionchar[(ssplayer)-1].value == 3 ? CS_LMAOGALOG : ((!objectplacing && cv_analog[(ssplayer)-1].value ? CS_LMAOGALOG : 0) | (cv_directionchar[(ssplayer)-1].value ? CS_STANDARD : 0)))
#define P_ControlStyle(player) ((((player)->pflags & PF_ANALOGMODE) ? CS_LMAOGALOG : 0) | (((player)->pflags & PF_DIRECTIONCHAR) ? CS_STANDARD : 0))
extern consvar_t cv_autobrake, cv_autobrake2;

View File

@ -25,11 +25,11 @@ static CV_PossibleValue_t mousesens_cons_t[] = {{1, "MIN"}, {MAXMOUSESENSITIVITY
static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several"}, {0, NULL}};
// mouse values are used once
consvar_t cv_mousesens = {"mousesens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousesens2 = {"mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouseysens = {"mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouseysens2 = {"mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousesens = CVAR_INIT ("mousesens", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_mousesens2 = CVAR_INIT ("mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_mouseysens = CVAR_INIT ("mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_mouseysens2 = CVAR_INIT ("mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL);
consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL);
INT32 mousex, mousey;
INT32 mlooky; // like mousey but with a custom sensitivity for mlook

View File

@ -235,13 +235,13 @@ void HWR_RenderBatches(void)
currently_batching = false;// no longer collecting batches
if (!polygonArraySize)
{
rs_hw_numpolys = rs_hw_numcalls = rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 0;
ps_hw_numpolys = ps_hw_numcalls = ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 0;
return;// nothing to draw
}
// init stats vars
rs_hw_numpolys = polygonArraySize;
rs_hw_numcalls = rs_hw_numverts = 0;
rs_hw_numshaders = rs_hw_numtextures = rs_hw_numpolyflags = rs_hw_numcolors = 1;
ps_hw_numpolys = polygonArraySize;
ps_hw_numcalls = ps_hw_numverts = 0;
ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 1;
// init polygonIndexArray
for (i = 0; i < polygonArraySize; i++)
{
@ -249,12 +249,12 @@ void HWR_RenderBatches(void)
}
// sort polygons
rs_hw_batchsorttime = I_GetTimeMicros();
ps_hw_batchsorttime = I_GetTimeMicros();
if (cv_glshaders.value && gl_shadersavailable)
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
else
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
rs_hw_batchsorttime = I_GetTimeMicros() - rs_hw_batchsorttime;
ps_hw_batchsorttime = I_GetTimeMicros() - ps_hw_batchsorttime;
// sort order
// 1. shader
// 2. texture
@ -262,7 +262,7 @@ void HWR_RenderBatches(void)
// 4. colors + light level
// not sure about what order of the last 2 should be, or if it even matters
rs_hw_batchdrawtime = I_GetTimeMicros();
ps_hw_batchdrawtime = I_GetTimeMicros();
currentShader = polygonArray[polygonIndexArray[0]].shader;
currentTexture = polygonArray[polygonIndexArray[0]].texture;
@ -398,8 +398,8 @@ void HWR_RenderBatches(void)
// execute draw call
HWD.pfnDrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
// update stats
rs_hw_numcalls++;
rs_hw_numverts += finalIndexWritePos;
ps_hw_numcalls++;
ps_hw_numverts += finalIndexWritePos;
// reset write positions
finalVertexWritePos = 0;
finalIndexWritePos = 0;
@ -416,7 +416,7 @@ void HWR_RenderBatches(void)
currentShader = nextShader;
changeShader = false;
rs_hw_numshaders++;
ps_hw_numshaders++;
}
if (changeTexture)
{
@ -425,21 +425,21 @@ void HWR_RenderBatches(void)
currentTexture = nextTexture;
changeTexture = false;
rs_hw_numtextures++;
ps_hw_numtextures++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
rs_hw_numpolyflags++;
ps_hw_numpolyflags++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
rs_hw_numcolors++;
ps_hw_numcolors++;
}
// and that should be it?
}
@ -447,7 +447,7 @@ void HWR_RenderBatches(void)
polygonArraySize = 0;
unsortedVertexArraySize = 0;
rs_hw_batchdrawtime = I_GetTimeMicros() - rs_hw_batchdrawtime;
ps_hw_batchdrawtime = I_GetTimeMicros() - ps_hw_batchdrawtime;
}

View File

@ -20,11 +20,12 @@
#include "../doomstat.h" //gamemode
#include "../i_video.h" //rendermode
#include "../r_data.h"
#include "../r_textures.h"
#include "../w_wad.h"
#include "../z_zone.h"
#include "../v_video.h"
#include "../r_draw.h"
#include "../r_patch.h"
#include "../r_picformats.h"
#include "../p_setup.h"
INT32 patchformat = GL_TEXFMT_AP_88; // use alpha for holes
@ -99,17 +100,15 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
count--;
texel = source[yfrac>>FRACBITS];
alpha = 0xFF;
// Make pixel transparent if chroma keyed
if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
alpha = 0x00;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if (mipmap->colormap)
texel = mipmap->colormap[texel];
// If the mipmap is chromakeyed, check if the texel's color
// is equivalent to the chroma key's color index.
alpha = 0xff;
if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
alpha = 0x00;
// hope compiler will get this switch out of the loops (dreams...)
// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)
// Alam: SRB2 uses Mingw, HUGS
@ -211,17 +210,15 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
count--;
texel = source[yfrac>>FRACBITS];
alpha = 0xFF;
// Make pixel transparent if chroma keyed
if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
alpha = 0x00;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if (mipmap->colormap)
texel = mipmap->colormap[texel];
// If the mipmap is chromakeyed, check if the texel's color
// is equivalent to the chroma key's color index.
alpha = 0xff;
if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
alpha = 0x00;
// hope compiler will get this switch out of the loops (dreams...)
// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)
// Alam: SRB2 uses Mingw, HUGS
@ -508,13 +505,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
realpatch = (patch_t *)pdata;
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength, NULL);
if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength))
realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0);
else
#endif
#ifdef WALLFLATS
if (texture->type == TEXTURETYPE_FLAT)
realpatch = R_FlatToPatch(pdata, texture->width, texture->height, 0, 0, NULL, false);
realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0);
else
#endif
{
@ -550,8 +547,8 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
#ifndef NO_PNG_LUMPS
// lump is a png so convert it
size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum);
if ((patch != NULL) && R_IsLumpPNG((const UINT8 *)patch, len))
patch = R_PNGToPatch((const UINT8 *)patch, len, NULL);
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)
@ -788,6 +785,8 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
{
UINT8 *flat;
UINT8 *converted;
size_t size;
// setup the texture info
grMipmap->format = GL_TEXFMT_P_8;
@ -795,11 +794,12 @@ static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum)
grMipmap->width = (UINT16)textures[texturenum]->width;
grMipmap->height = (UINT16)textures[texturenum]->height;
size = (grMipmap->width * grMipmap->height);
flat = Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->data);
memset(flat, TRANSPARENTPIXEL, grMipmap->width * grMipmap->height);
R_TextureToFlat(texturenum, flat);
flat = Z_Malloc(size, PU_HWRCACHE, &grMipmap->data);
converted = (UINT8 *)Picture_TextureToFlat(texturenum);
M_Memcpy(flat, converted, size);
Z_Free(converted);
}
// Download a Doom 'flat' to the hardware cache and make it ready for use
@ -837,7 +837,7 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
INT32 texturenum = levelflat->u.texture.num;
#ifdef PARANOIA
if ((unsigned)texturenum >= gl_numtextures)
I_Error("HWR_GetLevelFlat: texturenum >= numtextures\n");
I_Error("HWR_GetLevelFlat: texturenum >= numtextures");
#endif
// Who knows?
@ -860,6 +860,53 @@ void HWR_GetLevelFlat(levelflat_t *levelflat)
// The system-memory data can be purged now.
Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED);
}
else if (levelflat->type == LEVELFLAT_PATCH)
{
GLPatch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE);
levelflat->width = (UINT16)SHORT(patch->width);
levelflat->height = (UINT16)SHORT(patch->height);
HWR_GetPatch(patch);
}
#ifndef NO_PNG_LUMPS
else if (levelflat->type == LEVELFLAT_PNG)
{
INT32 pngwidth = 0, pngheight = 0;
GLMipmap_t *mipmap = levelflat->mipmap;
UINT8 *flat;
size_t size;
// Cache the picture.
if (!levelflat->picture)
{
levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0);
levelflat->width = (UINT16)pngwidth;
levelflat->height = (UINT16)pngheight;
}
// Make the mipmap.
if (mipmap == NULL)
{
mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_LEVEL, NULL);
mipmap->format = GL_TEXFMT_P_8;
mipmap->flags = TF_WRAPXY|TF_CHROMAKEYED;
levelflat->mipmap = mipmap;
}
if (!mipmap->data && !mipmap->downloaded)
{
mipmap->width = levelflat->width;
mipmap->height = levelflat->height;
size = (mipmap->width * mipmap->height);
flat = Z_Malloc(size, PU_LEVEL, &mipmap->data);
if (levelflat->picture == NULL)
I_Error("HWR_GetLevelFlat: levelflat->picture == NULL");
M_Memcpy(flat, levelflat->picture, size);
}
// Tell the hardware driver to bind the current texture to the flat's mipmap
HWD.pfnSetTexture(mipmap);
}
#endif
else // set no texture
HWR_SetCurrentTexture(NULL);
}

View File

@ -132,6 +132,43 @@ typedef struct
FLOAT t; // t texture ordinate (t over w)
} FOutVector;
#ifdef GL_SHADERS
// Predefined shader types
enum
{
SHADER_DEFAULT = 0,
SHADER_FLOOR,
SHADER_WALL,
SHADER_SPRITE,
SHADER_MODEL, SHADER_MODEL_LIGHTING,
SHADER_WATER,
SHADER_FOG,
SHADER_SKY,
NUMBASESHADERS,
};
// Maximum amount of shader programs
// Must be higher than NUMBASESHADERS
#define HWR_MAXSHADERS 16
// Shader sources (vertex and fragment)
typedef struct
{
char *vertex;
char *fragment;
} shadersource_t;
// Custom shader reference table
typedef struct
{
const char *type;
INT32 id;
} customshaderxlat_t;
#endif
typedef struct vbo_vertex_s
{
float x, y, z;

View File

@ -68,14 +68,13 @@ EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
// jimita
EXPORT boolean HWRAPI(LoadShaders) (void);
EXPORT void HWRAPI(KillShaders) (void);
EXPORT boolean HWRAPI(CompileShaders) (void);
EXPORT void HWRAPI(CleanShaders) (void);
EXPORT void HWRAPI(SetShader) (int shader);
EXPORT void HWRAPI(UnSetShader) (void);
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment);
EXPORT boolean HWRAPI(InitCustomShaders) (void);
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment);
// ==========================================================================
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
@ -120,14 +119,13 @@ struct hwdriver_s
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
LoadShaders pfnLoadShaders;
KillShaders pfnKillShaders;
CompileShaders pfnCompileShaders;
CleanShaders pfnCleanShaders;
SetShader pfnSetShader;
UnSetShader pfnUnSetShader;
SetShaderInfo pfnSetShaderInfo;
LoadCustomShader pfnLoadCustomShader;
InitCustomShaders pfnInitCustomShaders;
};
extern struct hwdriver_s hwdriver;

View File

@ -25,7 +25,7 @@
#include "../p_local.h"
#include "../p_setup.h"
#include "../r_local.h"
#include "../r_patch.h"
#include "../r_picformats.h"
#include "../r_bsp.h"
#include "../d_clisrv.h"
#include "../w_wad.h"
@ -146,21 +146,22 @@ static angle_t gl_aimingangle;
static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox);
// Render stats
int rs_hw_nodesorttime = 0;
int rs_hw_nodedrawtime = 0;
int rs_hw_spritesorttime = 0;
int rs_hw_spritedrawtime = 0;
int ps_hw_skyboxtime = 0;
int ps_hw_nodesorttime = 0;
int ps_hw_nodedrawtime = 0;
int ps_hw_spritesorttime = 0;
int ps_hw_spritedrawtime = 0;
// Render stats for batching
int rs_hw_numpolys = 0;
int rs_hw_numverts = 0;
int rs_hw_numcalls = 0;
int rs_hw_numshaders = 0;
int rs_hw_numtextures = 0;
int rs_hw_numpolyflags = 0;
int rs_hw_numcolors = 0;
int rs_hw_batchsorttime = 0;
int rs_hw_batchdrawtime = 0;
int ps_hw_numpolys = 0;
int ps_hw_numverts = 0;
int ps_hw_numcalls = 0;
int ps_hw_numshaders = 0;
int ps_hw_numtextures = 0;
int ps_hw_numpolyflags = 0;
int ps_hw_numcolors = 0;
int ps_hw_batchsorttime = 0;
int ps_hw_batchdrawtime = 0;
boolean gl_shadersavailable = true;
@ -358,7 +359,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
float fflatwidth = 64.0f, fflatheight = 64.0f;
INT32 flatflag = 63;
boolean texflat = false;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
FSurfaceInfo Surf;
@ -413,16 +413,9 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
// set texture for polygon
if (levelflat != NULL)
{
if (levelflat->type == LEVELFLAT_TEXTURE)
if (levelflat->type == LEVELFLAT_FLAT)
{
fflatwidth = textures[levelflat->u.texture.num]->width;
fflatheight = textures[levelflat->u.texture.num]->height;
texflat = true;
}
else if (levelflat->type == LEVELFLAT_FLAT)
{
len = W_LumpLength(levelflat->u.flat.lumpnum);
size_t len = W_LumpLength(levelflat->u.flat.lumpnum);
switch (len)
{
case 4194304: // 2048x2048 lump
@ -447,9 +440,22 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
fflatwidth = fflatheight = 64.0f;
break;
}
flatflag = ((INT32)fflatwidth)-1;
}
else
{
if (levelflat->type == LEVELFLAT_TEXTURE)
{
fflatwidth = textures[levelflat->u.texture.num]->width;
fflatheight = textures[levelflat->u.texture.num]->height;
}
else if (levelflat->type == LEVELFLAT_PATCH || levelflat->type == LEVELFLAT_PNG)
{
fflatwidth = levelflat->width;
fflatheight = levelflat->height;
}
texflat = true;
}
}
else // set no texture
HWR_SetCurrentTexture(NULL);
@ -560,11 +566,11 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
PolyFlags |= PF_Masked|PF_Modulated;
if (PolyFlags & PF_Fog)
shader = 6; // fog shader
shader = SHADER_FOG; // fog shader
else if (PolyFlags & PF_Ripple)
shader = 5; // water shader
shader = SHADER_WATER; // water shader
else
shader = 1; // floor shader
shader = SHADER_FLOOR; // floor shader
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false);
@ -761,7 +767,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
break;
}
HWD.pfnSetShader(2); // wall shader
HWD.pfnSetShader(SHADER_WALL); // wall shader
HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal);
}
}
@ -798,7 +804,7 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL
{
HWR_Lighting(pSurf, lightlevel, wallcolormap);
HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, 2, false); // wall shader
HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, SHADER_WALL, false); // wall shader
#ifdef WALLSPLATS
if (gl_curline->linedef->splats && cv_splats.value)
@ -1977,7 +1983,7 @@ static cliprange_t * hw_newend;
static cliprange_t gl_solidsegs[MAXSEGS];
// needs fix: walls are incorrectly clipped one column less
static consvar_t cv_glclipwalls = {"gr_clipwalls", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_glclipwalls = CVAR_INIT ("gr_clipwalls", "Off", 0, CV_OnOff, NULL);
static void printsolidsegs(void)
{
@ -2683,7 +2689,6 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
float fflatwidth = 64.0f, fflatheight = 64.0f;
INT32 flatflag = 63;
boolean texflat = false;
size_t len;
float scrollx = 0.0f, scrolly = 0.0f;
angle_t angle = 0;
FSurfaceInfo Surf;
@ -2717,16 +2722,9 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
// set texture for polygon
if (levelflat != NULL)
{
if (levelflat->type == LEVELFLAT_TEXTURE)
if (levelflat->type == LEVELFLAT_FLAT)
{
fflatwidth = textures[levelflat->u.texture.num]->width;
fflatheight = textures[levelflat->u.texture.num]->height;
texflat = true;
}
else if (levelflat->type == LEVELFLAT_FLAT)
{
len = W_LumpLength(levelflat->u.flat.lumpnum);
size_t len = W_LumpLength(levelflat->u.flat.lumpnum);
switch (len)
{
case 4194304: // 2048x2048 lump
@ -2751,9 +2749,22 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
fflatwidth = fflatheight = 64.0f;
break;
}
flatflag = ((INT32)fflatwidth)-1;
}
else
{
if (levelflat->type == LEVELFLAT_TEXTURE)
{
fflatwidth = textures[levelflat->u.texture.num]->width;
fflatheight = textures[levelflat->u.texture.num]->height;
}
else if (levelflat->type == LEVELFLAT_PATCH || levelflat->type == LEVELFLAT_PNG)
{
fflatwidth = levelflat->width;
fflatheight = levelflat->height;
}
texflat = true;
}
}
else // set no texture
HWR_SetCurrentTexture(NULL);
@ -2857,7 +2868,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
else
blendmode |= PF_Masked|PF_Modulated|PF_Clip;
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, 1, false); // floor shader
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, SHADER_FLOOR, false); // floor shader
}
static void HWR_AddPolyObjectPlanes(void)
@ -3202,7 +3213,7 @@ static void HWR_Subsector(size_t num)
}
// for render stats
rs_numpolyobjects += numpolys;
ps_numpolyobjects += numpolys;
// Sort polyobjects
R_SortPolyObjects(sub);
@ -3310,7 +3321,7 @@ static void HWR_RenderBSPNode(INT32 bspnum)
// Decide which side the view point is on
INT32 side;
rs_numbspcalls++;
ps_numbspcalls++;
// Found a subsector?
if (bspnum & NF_SUBSECTOR)
@ -3669,7 +3680,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
HWR_Lighting(&sSurf, 0, colormap);
sSurf.PolyColor.s.alpha = alpha;
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
}
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
@ -3943,7 +3954,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
Surf.PolyColor.s.alpha = alpha;
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
if (use_linkdraw_hack)
HWR_LinkDrawHackAdd(wallVerts, spr);
@ -3972,7 +3983,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
Surf.PolyColor.s.alpha = alpha;
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
if (use_linkdraw_hack)
HWR_LinkDrawHackAdd(wallVerts, spr);
@ -4132,7 +4143,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
if (!occlusion) use_linkdraw_hack = true;
}
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
if (use_linkdraw_hack)
HWR_LinkDrawHackAdd(wallVerts, spr);
@ -4234,7 +4245,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
blend = PF_Translucent|PF_Occlude;
}
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader
}
#endif
@ -4516,7 +4527,7 @@ static void HWR_CreateDrawNodes(void)
// that is already lying around. This should all be in some sort of linked list or lists.
sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL);
rs_hw_nodesorttime = I_GetTimeMicros();
ps_hw_nodesorttime = I_GetTimeMicros();
for (i = 0; i < numplanes; i++, p++)
{
@ -4536,7 +4547,7 @@ static void HWR_CreateDrawNodes(void)
sortindex[p] = p;
}
rs_numdrawnodes = p;
ps_numdrawnodes = p;
// p is the number of stuff to sort
@ -4571,13 +4582,13 @@ static void HWR_CreateDrawNodes(void)
}
}
rs_hw_nodesorttime = I_GetTimeMicros() - rs_hw_nodesorttime;
ps_hw_nodesorttime = I_GetTimeMicros() - ps_hw_nodesorttime;
rs_hw_nodedrawtime = I_GetTimeMicros();
ps_hw_nodedrawtime = I_GetTimeMicros();
// Okay! Let's draw it all! Woo!
HWD.pfnSetTransform(&atransform);
HWD.pfnSetShader(0);
HWD.pfnSetShader(SHADER_DEFAULT);
for (i = 0; i < p; i++)
{
@ -4610,7 +4621,7 @@ static void HWR_CreateDrawNodes(void)
}
}
rs_hw_nodedrawtime = I_GetTimeMicros() - rs_hw_nodedrawtime;
ps_hw_nodedrawtime = I_GetTimeMicros() - ps_hw_nodedrawtime;
numwalls = 0;
numplanes = 0;
@ -5397,7 +5408,7 @@ static void HWR_DrawSkyBackground(player_t *player)
HWR_BuildSkyDome();
}
HWD.pfnSetShader(7); // sky shader
HWD.pfnSetShader(SHADER_SKY); // sky shader
HWD.pfnSetTransform(&dometransform);
HWD.pfnRenderSkyDome(&gl_sky);
}
@ -5484,7 +5495,7 @@ static void HWR_DrawSkyBackground(player_t *player)
HWD.pfnDrawPolygon(NULL, v, 4, 0);
}
HWD.pfnSetShader(0);
HWD.pfnSetShader(SHADER_DEFAULT);
}
@ -5688,7 +5699,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
// Reset the shader state.
HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_glshaders.value);
HWD.pfnSetShader(0);
HWD.pfnSetShader(SHADER_DEFAULT);
validcount++;
@ -5791,8 +5802,10 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
if (viewnumber == 0) // Only do it if it's the first screen being rendered
HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs.
ps_hw_skyboxtime = I_GetTimeMicros();
if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox
HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind
ps_hw_skyboxtime = I_GetTimeMicros() - ps_hw_skyboxtime;
{
// do we really need to save player (is it not the same)?
@ -5901,11 +5914,11 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
// Reset the shader state.
HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_glshaders.value);
HWD.pfnSetShader(0);
HWD.pfnSetShader(SHADER_DEFAULT);
rs_numbspcalls = 0;
rs_numpolyobjects = 0;
rs_bsptime = I_GetTimeMicros();
ps_numbspcalls = 0;
ps_numpolyobjects = 0;
ps_bsptime = I_GetTimeMicros();
validcount++;
@ -5943,7 +5956,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
}
#endif
rs_bsptime = I_GetTimeMicros() - rs_bsptime;
ps_bsptime = I_GetTimeMicros() - ps_bsptime;
if (cv_glbatching.value)
HWR_RenderBatches();
@ -5958,22 +5971,22 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
#endif
// Draw MD2 and sprites
rs_numsprites = gl_visspritecount;
rs_hw_spritesorttime = I_GetTimeMicros();
ps_numsprites = gl_visspritecount;
ps_hw_spritesorttime = I_GetTimeMicros();
HWR_SortVisSprites();
rs_hw_spritesorttime = I_GetTimeMicros() - rs_hw_spritesorttime;
rs_hw_spritedrawtime = I_GetTimeMicros();
ps_hw_spritesorttime = I_GetTimeMicros() - ps_hw_spritesorttime;
ps_hw_spritedrawtime = I_GetTimeMicros();
HWR_DrawSprites();
rs_hw_spritedrawtime = I_GetTimeMicros() - rs_hw_spritedrawtime;
ps_hw_spritedrawtime = I_GetTimeMicros() - ps_hw_spritedrawtime;
#ifdef NEWCORONAS
//Hurdler: they must be drawn before translucent planes, what about gl fog?
HWR_DrawCoronas();
#endif
rs_numdrawnodes = 0;
rs_hw_nodesorttime = 0;
rs_hw_nodedrawtime = 0;
ps_numdrawnodes = 0;
ps_hw_nodesorttime = 0;
ps_hw_nodedrawtime = 0;
if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything
{
HWR_CreateDrawNodes();
@ -6011,34 +6024,32 @@ static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA
{0, NULL}};
CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}};
consvar_t cv_glshaders = {"gr_shaders", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_fovchange = CVAR_INIT ("gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL);
#ifdef ALAM_LIGHTING
consvar_t cv_gldynamiclighting = {"gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glstaticlighting = {"gr_staticlighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glcoronas = {"gr_coronas", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glcoronasize = {"gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gldynamiclighting = CVAR_INIT ("gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glstaticlighting = CVAR_INIT ("gr_staticlighting", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glcoronas = CVAR_INIT ("gr_coronas", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0, NULL);
#endif
consvar_t cv_glmodels = {"gr_models", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glmodelinterpolation = {"gr_modelinterpolation", "Sometimes", CV_SAVE, grmodelinterpolation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glmodellighting = {"gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glmodels = CVAR_INIT ("gr_models", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, grmodelinterpolation_cons_t, NULL);
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glshearing = {"gr_shearing", "Off", CV_SAVE, grshearing_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glfakecontrast = {"gr_fakecontrast", "Smooth", CV_SAVE, grfakecontrast_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glslopecontrast = {"gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, grshearing_cons_t, NULL);
consvar_t cv_glspritebillboarding = CVAR_INIT ("gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glskydome = CVAR_INIT ("gr_skydome", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glfakecontrast = CVAR_INIT ("gr_fakecontrast", "Smooth", CV_SAVE, grfakecontrast_cons_t, NULL);
consvar_t cv_glslopecontrast = CVAR_INIT ("gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glfiltermode = {"gr_filtermode", "Nearest", CV_SAVE|CV_CALL, glfiltermode_cons_t,
CV_glfiltermode_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glanisotropicmode = {"gr_anisotropicmode", "1", CV_CALL, granisotropicmode_cons_t,
CV_glanisotropic_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glfiltermode = CVAR_INIT ("gr_filtermode", "Nearest", CV_SAVE|CV_CALL, glfiltermode_cons_t, CV_glfiltermode_OnChange);
consvar_t cv_glanisotropicmode = CVAR_INIT ("gr_anisotropicmode", "1", CV_CALL, granisotropicmode_cons_t, CV_glanisotropic_OnChange);
consvar_t cv_glsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glsolvetjoin = CVAR_INIT ("gr_solvetjoin", "On", 0, CV_OnOff, NULL);
consvar_t cv_glbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL);
static void CV_glfiltermode_OnChange(void)
{
@ -6077,7 +6088,6 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_glfiltermode);
CV_RegisterVar(&cv_glsolvetjoin);
CV_RegisterVar(&cv_renderstats);
CV_RegisterVar(&cv_glbatching);
#ifndef NEWCLIP
@ -6106,7 +6116,6 @@ void HWR_Startup(void)
// do this once
if (!startupdone)
{
INT32 i;
CONS_Printf("HWR_Startup()...\n");
HWR_InitPolyPool();
@ -6117,10 +6126,8 @@ void HWR_Startup(void)
HWR_InitLight();
#endif
// read every custom shader
for (i = 0; i < numwadfiles; i++)
HWR_ReadShaders(i, (wadfiles[i]->type == RET_PK3));
if (!HWR_LoadShaders())
HWR_LoadAllCustomShaders();
if (!HWR_CompileShaders())
gl_shadersavailable = false;
}
@ -6212,7 +6219,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting
shader = 2; // wall shader
shader = SHADER_WALL; // wall shader
if (blend & PF_Environment)
blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects
@ -6220,7 +6227,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
if (fogwall)
{
blendmode |= PF_Fog;
shader = 6; // fog shader
shader = SHADER_FOG; // fog shader
}
blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency
@ -6405,13 +6412,7 @@ void HWR_DrawScreenFinalTexture(int width, int height)
}
// jimita 18032019
typedef struct
{
char type[16];
INT32 id;
} shaderxlat_t;
static inline UINT16 HWR_CheckShader(UINT16 wadnum)
static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
{
UINT16 i;
lumpinfo_t *lump_p;
@ -6424,12 +6425,34 @@ static inline UINT16 HWR_CheckShader(UINT16 wadnum)
return INT16_MAX;
}
boolean HWR_LoadShaders(void)
boolean HWR_CompileShaders(void)
{
return HWD.pfnInitCustomShaders();
return HWD.pfnCompileShaders();
}
void HWR_ReadShaders(UINT16 wadnum, boolean PK3)
customshaderxlat_t shaderxlat[] =
{
{"Flat", SHADER_FLOOR},
{"WallTexture", SHADER_WALL},
{"Sprite", SHADER_SPRITE},
{"Model", SHADER_MODEL},
{"ModelLighting", SHADER_MODEL_LIGHTING},
{"WaterRipple", SHADER_WATER},
{"Fog", SHADER_FOG},
{"Sky", SHADER_SKY},
{NULL, 0},
};
void HWR_LoadAllCustomShaders(void)
{
INT32 i;
// read every custom shader
for (i = 0; i < numwadfiles; i++)
HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3));
}
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
{
UINT16 lump;
char *shaderdef, *line;
@ -6440,19 +6463,7 @@ void HWR_ReadShaders(UINT16 wadnum, boolean PK3)
int shadertype = 0;
int i;
#define SHADER_TYPES 7
shaderxlat_t shaderxlat[SHADER_TYPES] =
{
{"Flat", 1},
{"WallTexture", 2},
{"Sprite", 3},
{"Model", 4},
{"WaterRipple", 5},
{"Fog", 6},
{"Sky", 7},
};
lump = HWR_CheckShader(wadnum);
lump = HWR_FindShaderDefs(wadnum);
if (lump == INT16_MAX)
return;
@ -6478,7 +6489,7 @@ void HWR_ReadShaders(UINT16 wadnum, boolean PK3)
value = strtok(NULL, "\r\n ");
if (!value)
{
CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
stoken = strtok(NULL, "\r\n"); // skip end of line
goto skip_lump;
}
@ -6497,19 +6508,19 @@ skip_lump:
value = strtok(NULL, "\r\n= ");
if (!value)
{
CONS_Alert(CONS_WARNING, "HWR_ReadShaders: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
stoken = strtok(NULL, "\r\n"); // skip end of line
goto skip_field;
}
if (!shadertype)
{
CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
Z_Free(line);
return;
}
for (i = 0; i < SHADER_TYPES; i++)
for (i = 0; shaderxlat[i].type; i++)
{
if (!stricmp(shaderxlat[i].type, stoken))
{
@ -6535,7 +6546,7 @@ skip_lump:
if (shader_lumpnum == INT16_MAX)
{
CONS_Alert(CONS_ERROR, "HWR_ReadShaders: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum);
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum);
Z_Free(shader_lumpname);
continue;
}
@ -6561,4 +6572,22 @@ skip_field:
return;
}
const char *HWR_GetShaderName(INT32 shader)
{
INT32 i;
if (shader)
{
for (i = 0; shaderxlat[i].type; i++)
{
if (shaderxlat[i].id == shader)
return shaderxlat[i].type;
}
return "Unknown";
}
return "Default";
}
#endif // HWRENDER

View File

@ -70,8 +70,13 @@ void HWR_DrawScreenFinalTexture(int width, int height);
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
void HWR_ReadShaders(UINT16 wadnum, boolean PK3);
boolean HWR_LoadShaders(void);
boolean HWR_CompileShaders(void);
void HWR_LoadAllCustomShaders(void);
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
const char *HWR_GetShaderName(INT32 shader);
extern customshaderxlat_t shaderxlat[];
extern CV_PossibleValue_t granisotropicmode_cons_t[];
@ -108,21 +113,22 @@ extern FTransform atransform;
// Render stats
extern int rs_hw_nodesorttime;
extern int rs_hw_nodedrawtime;
extern int rs_hw_spritesorttime;
extern int rs_hw_spritedrawtime;
extern int ps_hw_skyboxtime;
extern int ps_hw_nodesorttime;
extern int ps_hw_nodedrawtime;
extern int ps_hw_spritesorttime;
extern int ps_hw_spritedrawtime;
// Render stats for batching
extern int rs_hw_numpolys;
extern int rs_hw_numverts;
extern int rs_hw_numcalls;
extern int rs_hw_numshaders;
extern int rs_hw_numtextures;
extern int rs_hw_numpolyflags;
extern int rs_hw_numcolors;
extern int rs_hw_batchsorttime;
extern int rs_hw_batchdrawtime;
extern int ps_hw_numpolys;
extern int ps_hw_numverts;
extern int ps_hw_numcalls;
extern int ps_hw_numshaders;
extern int ps_hw_numtextures;
extern int ps_hw_numpolyflags;
extern int ps_hw_numcolors;
extern int ps_hw_batchsorttime;
extern int ps_hw_batchdrawtime;
extern boolean gl_shadersavailable;

View File

@ -92,7 +92,13 @@ static void md2_freeModel (model_t *model)
static model_t *md2_readModel(const char *filename)
{
//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)
@ -160,8 +166,12 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
png_FILE = fopen(pngfilename, "rb");
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);
return 0;
if (!png_FILE)
return 0;
}
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");
file = fopen(pcxfilename, "rb");
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)
{
@ -493,11 +509,15 @@ void HWR_InitModels(void)
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
}
// length of the player model prefix
prefixlen = strlen(PLAYERMODELPREFIX);
@ -569,9 +589,13 @@ void HWR_AddPlayerModel(int skin) // For skins that were added after startup
if (!f)
{
CONS_Printf("Error while loading models.dat\n");
nomd2s = true;
return;
f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
if (!f)
{
CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno));
nomd2s = true;
return;
}
}
// length of the player model prefix
@ -624,9 +648,13 @@ void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after s
if (!f)
{
CONS_Printf("Error while loading models.dat\n");
nomd2s = true;
return;
f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt");
if (!f)
{
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!
@ -1177,6 +1205,7 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t
return spr2;
}
// 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)
{
int i;
@ -1185,24 +1214,35 @@ static void adjustTextureCoords(model_t *model, GLPatch_t *gpatch)
int j;
mesh_t *mesh = &model->meshes[i];
int numVertices;
float *uvPtr = mesh->uvs;
float *uvReadPtr = mesh->originaluvs;
float *uvWritePtr;
// i dont know if this is actually possible, just logical conclusion of structure in CreateModelVBOs
if (!mesh->frames && !mesh->tinyframes) return;
if (!mesh->frames && !mesh->tinyframes) continue;
if (mesh->frames) // again CreateModelVBO and CreateModelVBOTiny iterate like this so I'm gonna do that too
numVertices = mesh->numTriangles * 3;
else
numVertices = mesh->numVertices;
// if originaluvs points to uvs, we need to allocate new memory for adjusted uvs
// the old uvs are kept around for use in possible readjustments
if (mesh->uvs == mesh->originaluvs)
mesh->uvs = Z_Malloc(numVertices * 2 * sizeof(float), PU_STATIC, NULL);
uvWritePtr = mesh->uvs;
// fix uvs (texture coordinates) to take into account that the actual texture
// has empty space added until the next power of two
for (j = 0; j < numVertices; j++)
{
*uvPtr++ *= gpatch->max_s;
*uvPtr++ *= gpatch->max_t;
*uvWritePtr++ = *uvReadPtr++ * gpatch->max_s;
*uvWritePtr++ = *uvReadPtr++ * gpatch->max_t;
}
}
// Save the values we adjusted the uvs for
model->max_s = gpatch->max_s;
model->max_t = gpatch->max_t;
}
//
@ -1226,6 +1266,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
if (spr->precip)
return false;
// Lactozilla: Disallow certain models from rendering
if (!HWR_AllowModel(spr->mobj))
return false;
memset(&p, 0x00, sizeof(FTransform));
// MD2 colormap fix
@ -1330,10 +1374,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
if (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
if (!gpatch || !gpatch->mipmap->format)
adjustTextureCoords(md2->model, spr->gpatch);
// 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_t = md2->model->max_t;
HWD.pfnCreateModelVBOs(md2->model);
}
else
@ -1344,10 +1391,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
}
}
// Lactozilla: Disallow certain models from rendering
if (!HWR_AllowModel(spr->mobj))
return false;
//HWD.pfnSetBlend(blend); // This seems to actually break translucency?
finalscale = md2->scale;
//Hurdler: arf, I don't like that implementation at all... too much crappy
@ -1391,6 +1434,14 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
{
// Sprite
gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
// Check if sprite dimensions are different from previously used sprite.
// If so, uvs need to be readjusted.
// Comparing floats with the != operator here should be okay because they
// are just copies of glpatches' max_s and max_t values.
// 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 ||
memcmp(&(gpatch->max_t), &(md2->model->max_t), sizeof(md2->model->max_t)) != 0)
adjustTextureCoords(md2->model, gpatch);
HWR_GetMappedPatch(gpatch, spr->colormap);
}
@ -1549,7 +1600,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.mirror = atransform.mirror; // from Kart
#endif
HWD.pfnSetShader(4); // model shader
HWD.pfnSetShader(SHADER_MODEL); // model shader
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
}

View File

@ -221,6 +221,15 @@ model_t *LoadModel(const char *filename, int ztag)
material->shininess = 25.0f;
}
// Set originaluvs to point to uvs
for (i = 0; i < model->numMeshes; i++)
model->meshes[i].originaluvs = model->meshes[i].uvs;
model->max_s = 1.0;
model->max_t = 1.0;
model->vbo_max_s = 1.0;
model->vbo_max_t = 1.0;
return model;
}

View File

@ -59,6 +59,11 @@ typedef struct mesh_s
int numTriangles;
float *uvs;
// if uv adjustment is needed, uvs is changed to point to adjusted ones and
// this one retains the originals
// note: this member has been added with the assumption that models are never freed.
// (UnloadModel is called by nobody at the time of writing.)
float *originaluvs;
float *lightuvs;
int numFrames;
@ -99,6 +104,15 @@ typedef struct model_s
char *framenames;
boolean interpolate[256];
modelspr2frames_t *spr2frames;
// the max_s and max_t values that the uvs are currently adjusted to
// (if a sprite is used as a texture)
float max_s;
float max_t;
// These are the values that the uvs in the VBO have been adjusted to.
// If they are not same as max_s and max_t, then the VBO won't be used.
float vbo_max_s;
float vbo_max_t;
} model_t;
extern int numModels;

View File

@ -91,9 +91,10 @@ static GLuint startScreenWipe = 0;
static GLuint endScreenWipe = 0;
static GLuint finalScreenTexture = 0;
// Lactozilla: Set shader programs and uniforms
// 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};
@ -578,15 +579,12 @@ static PFNglUniform2fv pglUniform2fv;
static PFNglUniform3fv pglUniform3fv;
static PFNglGetUniformLocation pglGetUniformLocation;
#define MAXSHADERS 16
#define MAXSHADERPROGRAMS 16
// 18032019
static char *gl_customvertexshaders[MAXSHADERS];
static char *gl_customfragmentshaders[MAXSHADERS];
static GLuint gl_currentshaderprogram = 0;
static boolean gl_shaderprogramchanged = true;
static shadersource_t gl_customshaders[HWR_MAXSHADERS];
// 13062019
typedef enum
{
@ -610,17 +608,59 @@ typedef struct gl_shaderprogram_s
boolean custom;
GLint uniforms[gluniform_max+1];
} gl_shaderprogram_t;
static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS];
static gl_shaderprogram_t gl_shaderprograms[HWR_MAXSHADERS];
// Shader info
static INT32 shader_leveltime = 0;
// ========================
// Fragment shader macros
// ========================
// ================
// Vertex shaders
// ================
//
// GLSL Software fragment shader
// Generic vertex shader
//
#define GLSL_DEFAULT_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_FrontColor = gl_Color;\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
// replicates the way fixed function lighting is used by the model lighting option,
// stores the lighting result to gl_Color
// (ambient lighting of 0.75 and diffuse lighting from above)
#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
"float light = 0.75 + max(nDotVP, 0.0);\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
// ==================
// Fragment shaders
// ==================
//
// Generic fragment shader
//
#define GLSL_DEFAULT_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
"}\0"
//
// Software fragment shader
//
#define GLSL_DOOM_COLORMAP \
@ -761,22 +801,10 @@ static INT32 shader_leveltime = 0;
"gl_FragColor = final_color;\n" \
"}\0"
//
// GLSL generic fragment shader
//
#define GLSL_DEFAULT_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
"}\0"
//
// Sky fragment shader
// Modulates poly_color with gl_Color
//
#define GLSL_SKY_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
@ -784,97 +812,42 @@ static INT32 shader_leveltime = 0;
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
"}\0"
static const char *fragment_shaders[] = {
// Default fragment shader
GLSL_DEFAULT_FRAGMENT_SHADER,
// ================
// Shader sources
// ================
// Floor fragment shader
GLSL_SOFTWARE_FRAGMENT_SHADER,
static struct {
const char *vertex;
const char *fragment;
} const gl_shadersources[] = {
// Default shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER},
// Wall fragment shader
GLSL_SOFTWARE_FRAGMENT_SHADER,
// Floor shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
// Sprite fragment shader
GLSL_SOFTWARE_FRAGMENT_SHADER,
// Wall shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
// Model fragment shader
GLSL_SOFTWARE_FRAGMENT_SHADER,
// Sprite shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
// Water fragment shader
GLSL_WATER_FRAGMENT_SHADER,
// Model shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER},
// Fog fragment shader
GLSL_FOG_FRAGMENT_SHADER,
// Model shader + diffuse lighting from above
{GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER},
// Sky fragment shader
GLSL_SKY_FRAGMENT_SHADER,
// Water shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
// Model fragment shader + diffuse lighting from above
GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER,
// Fog shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
NULL,
};
// Sky shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER},
// ======================
// Vertex shader macros
// ======================
//
// GLSL generic vertex shader
//
#define GLSL_DEFAULT_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_FrontColor = gl_Color;\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
// replicates the way fixed function lighting is used by the model lighting option,
// stores the lighting result to gl_Color
// (ambient lighting of 0.75 and diffuse lighting from above)
#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
"float light = 0.75 + max(nDotVP, 0.0);\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
static const char *vertex_shaders[] = {
// Default vertex shader
GLSL_DEFAULT_VERTEX_SHADER,
// Floor vertex shader
GLSL_DEFAULT_VERTEX_SHADER,
// Wall vertex shader
GLSL_DEFAULT_VERTEX_SHADER,
// Sprite vertex shader
GLSL_DEFAULT_VERTEX_SHADER,
// Model vertex shader
GLSL_DEFAULT_VERTEX_SHADER,
// Water vertex shader
GLSL_DEFAULT_VERTEX_SHADER,
// Fog vertex shader
GLSL_DEFAULT_VERTEX_SHADER,
// Sky vertex shader
GLSL_DEFAULT_VERTEX_SHADER,
// Model vertex shader + diffuse lighting from above
GLSL_MODEL_LIGHTING_VERTEX_SHADER,
NULL,
{NULL, NULL},
};
#endif // GL_SHADERS
@ -920,7 +893,7 @@ void SetupGLFunc4(void)
}
// jimita
EXPORT boolean HWRAPI(LoadShaders) (void)
EXPORT boolean HWRAPI(CompileShaders) (void)
{
#ifdef GL_SHADERS
GLuint gl_vertShader, gl_fragShader;
@ -928,25 +901,23 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
if (!pglUseProgram) return false;
gl_customvertexshaders[0] = NULL;
gl_customfragmentshaders[0] = NULL;
gl_customshaders[0].vertex = NULL;
gl_customshaders[0].fragment = NULL;
for (i = 0; vertex_shaders[i] && fragment_shaders[i]; i++)
for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++)
{
gl_shaderprogram_t *shader;
const GLchar* vert_shader = vertex_shaders[i];
const GLchar* frag_shader = fragment_shaders[i];
boolean custom = ((gl_customvertexshaders[i] || gl_customfragmentshaders[i]) && (i > 0));
const GLchar *vert_shader = gl_shadersources[i].vertex;
const GLchar *frag_shader = gl_shadersources[i].fragment;
boolean custom = ((gl_customshaders[i].vertex || gl_customshaders[i].fragment) && (i > 0));
// 18032019
if (gl_customvertexshaders[i])
vert_shader = gl_customvertexshaders[i];
if (gl_customfragmentshaders[i])
frag_shader = gl_customfragmentshaders[i];
if (gl_customshaders[i].vertex)
vert_shader = gl_customshaders[i].vertex;
if (gl_customshaders[i].fragment)
frag_shader = gl_customshaders[i].fragment;
if (i >= MAXSHADERS)
break;
if (i >= MAXSHADERPROGRAMS)
if (i >= HWR_MAXSHADERS)
break;
shader = &gl_shaderprograms[i];
@ -959,7 +930,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
if (!gl_vertShader)
{
GL_MSG_Error("LoadShaders: Error creating vertex shader %d\n", i);
GL_MSG_Error("CompileShaders: Error creating vertex shader %s\n", HWR_GetShaderName(i));
continue;
}
@ -970,15 +941,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
GLchar* infoLog;
GLint logLength;
pglGetShaderiv(gl_vertShader, GL_INFO_LOG_LENGTH, &logLength);
infoLog = malloc(logLength);
pglGetShaderInfoLog(gl_vertShader, logLength, NULL, infoLog);
GL_MSG_Error("LoadShaders: Error compiling vertex shader %d\n%s", i, infoLog);
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
continue;
}
@ -988,7 +951,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
if (!gl_fragShader)
{
GL_MSG_Error("LoadShaders: Error creating fragment shader %d\n", i);
GL_MSG_Error("CompileShaders: Error creating fragment shader %s\n", HWR_GetShaderName(i));
continue;
}
@ -999,15 +962,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
GLchar* infoLog;
GLint logLength;
pglGetShaderiv(gl_fragShader, GL_INFO_LOG_LENGTH, &logLength);
infoLog = malloc(logLength);
pglGetShaderInfoLog(gl_fragShader, logLength, NULL, infoLog);
GL_MSG_Error("LoadShaders: Error compiling fragment shader %d\n%s", i, infoLog);
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
continue;
}
@ -1028,7 +983,7 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
{
shader->program = 0;
shader->custom = false;
GL_MSG_Error("LoadShaders: Error linking shader program %d\n", i);
GL_MSG_Error("CompileShaders: Error linking shader program %s\n", HWR_GetShaderName(i));
continue;
}
@ -1048,8 +1003,10 @@ EXPORT boolean HWRAPI(LoadShaders) (void)
#undef GETUNI
}
#endif
return true;
#else
return false;
#endif
}
//
@ -1077,25 +1034,34 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value)
//
// Custom shader loading
//
EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment)
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment)
{
#ifdef GL_SHADERS
if (!pglUseProgram) return;
if (number < 1 || number > MAXSHADERS)
I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS);
shadersource_t *shader;
if (fragment)
{
gl_customfragmentshaders[number] = malloc(size+1);
strncpy(gl_customfragmentshaders[number], shader, size);
gl_customfragmentshaders[number][size] = 0;
if (!pglUseProgram)
return;
if (number < 1 || number > HWR_MAXSHADERS)
I_Error("LoadCustomShader: cannot load shader %d (min 1, max %d)", number, HWR_MAXSHADERS);
else if (code == NULL)
I_Error("LoadCustomShader: empty shader");
shader = &gl_customshaders[number];
#define COPYSHADER(source) { \
if (shader->source) \
free(shader->source); \
shader->source = malloc(size+1); \
strncpy(shader->source, code, size); \
shader->source[size] = 0; \
}
if (isfragment)
COPYSHADER(fragment)
else
{
gl_customvertexshaders[number] = malloc(size+1);
strncpy(gl_customvertexshaders[number], shader, size);
gl_customvertexshaders[number][size] = 0;
}
COPYSHADER(vertex)
#else
(void)number;
(void)shader;
@ -1104,14 +1070,6 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boo
#endif
}
EXPORT boolean HWRAPI(InitCustomShaders) (void)
{
#ifdef GL_SHADERS
KillShaders();
return LoadShaders();
#endif
}
EXPORT void HWRAPI(SetShader) (int shader)
{
#ifdef GL_SHADERS
@ -1119,9 +1077,9 @@ EXPORT void HWRAPI(SetShader) (int shader)
{
// If using model lighting, set the appropriate shader.
// However don't override a custom shader.
// Should use an enum or something...
if (shader == 4 && model_lighting && !gl_shaderprograms[4].custom)
shader = 8;
if (shader == SHADER_MODEL && model_lighting
&& !(gl_shaderprograms[SHADER_MODEL].custom && !gl_shaderprograms[SHADER_MODEL_LIGHTING].custom))
shader = SHADER_MODEL_LIGHTING;
if ((GLuint)shader != gl_currentshaderprogram)
{
gl_currentshaderprogram = shader;
@ -1146,9 +1104,23 @@ EXPORT void HWRAPI(UnSetShader) (void)
#endif
}
EXPORT void HWRAPI(KillShaders) (void)
EXPORT void HWRAPI(CleanShaders) (void)
{
// unused.........................
INT32 i;
for (i = 1; i < HWR_MAXSHADERS; i++)
{
shadersource_t *shader = &gl_customshaders[i];
if (shader->vertex)
free(shader->vertex);
if (shader->fragment)
free(shader->fragment);
shader->vertex = NULL;
shader->fragment = NULL;
}
}
// -----------------+
@ -2017,6 +1989,25 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
#endif
}
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum)
{
GLchar *infoLog = NULL;
GLint logLength;
pglGetShaderiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength)
{
infoLog = malloc(logLength);
pglGetShaderInfoLog(program, logLength, NULL, infoLog);
}
GL_MSG_Error("CompileShaders: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : ""));
if (infoLog)
free(infoLog);
}
// code that is common between DrawPolygon and DrawIndexedTriangles
// the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching
static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags)
@ -2535,6 +2526,8 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
boolean useTinyFrames;
boolean useVBO = true;
int i;
// Because otherwise, scaling the screen negatively vertically breaks the lighting
@ -2678,6 +2671,15 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
if (useTinyFrames)
pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f);
// Don't use the VBO if it does not have the correct texture coordinates.
// (Can happen when model uses a sprite as a texture and the sprite changes)
// Comparing floats with the != operator here should be okay because they
// are just copies of glpatches' max_s and max_t values.
// Instead of the != operator, memcmp is used to avoid a compiler warning.
if (memcmp(&(model->vbo_max_s), &(model->max_s), sizeof(model->max_s)) != 0 ||
memcmp(&(model->vbo_max_t), &(model->max_t), sizeof(model->max_t)) != 0)
useVBO = false;
pglEnableClientState(GL_NORMAL_ARRAY);
for (i = 0; i < model->numMeshes; i++)
@ -2694,13 +2696,23 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
if (!nextframe || fpclassify(pol) == FP_ZERO)
{
pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID);
pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0));
pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3));
pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6));
if (useVBO)
{
pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID);
pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0));
pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3));
pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6));
pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
pglBindBuffer(GL_ARRAY_BUFFER, 0);
pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
pglBindBuffer(GL_ARRAY_BUFFER, 0);
}
else
{
pglVertexPointer(3, GL_SHORT, 0, frame->vertices);
pglNormalPointer(GL_BYTE, 0, frame->normals);
pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs);
pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
}
}
else
{
@ -2736,21 +2748,25 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
if (!nextframe || fpclassify(pol) == FP_ZERO)
{
// Zoom! Take advantage of just shoving the entire arrays to the GPU.
/* pglVertexPointer(3, GL_FLOAT, 0, frame->vertices);
pglNormalPointer(GL_FLOAT, 0, frame->normals);
pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs);
pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);*/
if (useVBO)
{
pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID);
pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0));
pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3));
pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6));
pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID);
pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0));
pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3));
pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6));
pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);
// No tinyframes, no mesh indices
//pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
pglBindBuffer(GL_ARRAY_BUFFER, 0);
pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);
// No tinyframes, no mesh indices
//pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices);
pglBindBuffer(GL_ARRAY_BUFFER, 0);
}
else
{
pglVertexPointer(3, GL_FLOAT, 0, frame->vertices);
pglNormalPointer(GL_FLOAT, 0, frame->normals);
pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs);
pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3);
}
}
else
{

View File

@ -14,7 +14,9 @@ Documentation available here.
<http://mb.srb2.org/MS/tools/api/v1/>
*/
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
#include "doomdef.h"
#include "d_clisrv.h"
@ -34,20 +36,25 @@ Documentation available here.
static void MasterServer_Debug_OnChange (void);
consvar_t cv_masterserver_timeout = {
"masterserver_timeout", "5", CV_SAVE, CV_Unsigned,
NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
consvar_t cv_masterserver_timeout = CVAR_INIT
(
"masterserver_timeout", "5", CV_SAVE, CV_Unsigned,
NULL
);
consvar_t cv_masterserver_debug = {
consvar_t cv_masterserver_debug = CVAR_INIT
(
"masterserver_debug", "Off", CV_SAVE|CV_CALL, CV_OnOff,
MasterServer_Debug_OnChange, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
MasterServer_Debug_OnChange
);
consvar_t cv_masterserver_token = {
"masterserver_token", "", CV_SAVE, NULL,
NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */
};
consvar_t cv_masterserver_token = CVAR_INIT
(
"masterserver_token", "", CV_SAVE, NULL,
NULL
);
#ifdef MASTERSERVER
static int hms_started;
@ -468,6 +475,7 @@ HMS_list_servers (void)
{
struct HMS_buffer *hms;
char *list;
char *p;
hms = HMS_connect("servers");
@ -477,11 +485,17 @@ HMS_list_servers (void)
if (HMS_do(hms))
{
p = &hms->buffer[strlen(hms->buffer)];
while (*--p == '\n')
;
list = curl_easy_unescape(hms->curl, hms->buffer, 0, NULL);
CONS_Printf("%s\n", hms->buffer);
p = strtok(list, "\n");
while (p != NULL)
{
CONS_Printf("\x80%s\n", p);
p = strtok(NULL, "\n");
}
curl_free(list);
}
HMS_end(hms);
@ -664,10 +678,14 @@ HMS_set_api (char *api)
#endif
}
#endif/*MASTERSERVER*/
static void
MasterServer_Debug_OnChange (void)
{
#ifdef MASTERSERVER
/* TODO: change to 'latest-log.txt' for log files revision. */
if (cv_masterserver_debug.value)
CONS_Printf("Master server debug messages will appear in log.txt\n");
#endif
}

View File

@ -330,8 +330,6 @@ void HU_Init(void)
// set shift translation table
shiftxform = english_shiftxform;
HU_LoadGraphics();
}
static inline void HU_Stop(void)
@ -1466,7 +1464,7 @@ static void HU_drawMiniChat(void)
if (cv_chatbacktint.value) // on request of wolfy
V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT);
V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, !cv_allcaps.value, colormap);
V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, true, colormap);
}
dx += charwidth;
@ -1559,7 +1557,7 @@ static void HU_drawChatLog(INT32 offset)
else
{
if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy)))
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, !cv_allcaps.value, colormap);
V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, true, colormap);
else
j++; // don't forget to increment this or we'll get stuck in the limbo.
}
@ -1659,7 +1657,7 @@ static void HU_DrawChat(void)
++i;
else
{
V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, !cv_allcaps.value, V_GetStringColormap(talk[i]|cflag));
V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, true, V_GetStringColormap(talk[i]|cflag));
i++;
}
@ -1677,7 +1675,7 @@ static void HU_DrawChat(void)
typelines = 1;
if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4)
V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, true, NULL);
while (w_chat[i])
{
@ -1687,7 +1685,7 @@ static void HU_DrawChat(void)
INT32 cursorx = (c+charwidth < boxw-charwidth) ? (chatx + 2 + c+charwidth) : (chatx+1); // we may have to go down.
INT32 cursory = (cursorx != chatx+1) ? (y) : (y+charheight);
if (hu_tick < 4)
V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, !cv_allcaps.value, NULL);
V_DrawChatCharacter(cursorx, cursory+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, true, NULL);
if (cursorx == chatx+1 && saylen == i) // a weirdo hack
{
@ -1700,7 +1698,7 @@ static void HU_DrawChat(void)
if (w_chat[i] < HU_FONTSTART)
++i;
else
V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, !cv_allcaps.value, NULL);
V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, true, NULL);
c += charwidth;
if (c > boxw-(charwidth*2) && !skippedline)
@ -1825,7 +1823,7 @@ static void HU_DrawChat_Old(void)
}
if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4)
V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value);
V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true);
i = 0;
while (w_chat[i])
@ -1835,7 +1833,7 @@ static void HU_DrawChat_Old(void)
{
INT32 cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down.
INT32 cursory = (cursorx != HU_INPUTX) ? (y) : (y+charheight);
V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, !cv_allcaps.value);
V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true);
}
//Hurdler: isn't it better like that?
@ -2038,9 +2036,6 @@ static void HU_DrawDemoInfo(void)
//
void HU_Drawer(void)
{
if (needpatchrecache)
R_ReloadHUDGraphics();
#ifndef NONET
// draw chat string plus cursor
if (chat_on)

View File

@ -1,4 +1,4 @@
// SONIC ROBO BLAST 2 KART
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R.
//

View File

@ -5139,7 +5139,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIP|MF_SPECIAL, // flags
MF_SPECIAL, // flags
S_NULL // raisestate
},

View File

@ -33,9 +33,12 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "taglist.h" // P_FindSpecialLineFromTag
#include "lua_hook.h" // hook_cmd_running errors
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
return luaL_error(L, "HUD rendering code should not call this function!");\
else if (hook_cmd_running)\
return luaL_error(L, "CMD building code should not call this function!");
boolean luaL_checkboolean(lua_State *L, int narg) {
luaL_checktype(L, narg, LUA_TBOOLEAN);
@ -171,8 +174,13 @@ static const struct {
{META_SEG, "seg_t"},
{META_NODE, "node_t"},
#endif
{META_SLOPE, "slope_t"},
{META_VECTOR2, "vector2_t"},
{META_VECTOR3, "vector3_t"},
{META_MAPHEADER, "mapheader_t"},
{META_POLYOBJ, "polyobj_t"},
{META_CVAR, "consvar_t"},
{META_SECTORLINES, "sector_t.lines"},
@ -911,44 +919,52 @@ static int lib_pMaceRotate(lua_State *L)
static int lib_pRailThinker(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *ptmthing = tmthing;
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_RailThinker(mobj));
P_SetTarget(&tmthing, ptmthing);
return 1;
}
static int lib_pXYMovement(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *ptmthing = tmthing;
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_XYMovement(actor);
P_SetTarget(&tmthing, ptmthing);
return 0;
}
static int lib_pRingXYMovement(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *ptmthing = tmthing;
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_RingXYMovement(actor);
P_SetTarget(&tmthing, ptmthing);
return 0;
}
static int lib_pSceneryXYMovement(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *ptmthing = tmthing;
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_SceneryXYMovement(actor);
P_SetTarget(&tmthing, ptmthing);
return 0;
}
@ -960,6 +976,7 @@ static int lib_pZMovement(lua_State *L)
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_ZMovement(actor));
P_CheckPosition(actor, actor->x, actor->y);
return 1;
}
@ -971,6 +988,7 @@ static int lib_pRingZMovement(lua_State *L)
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_RingZMovement(actor);
P_CheckPosition(actor, actor->x, actor->y);
return 0;
}
@ -982,6 +1000,7 @@ static int lib_pSceneryZMovement(lua_State *L)
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_SceneryZMovement(actor));
P_CheckPosition(actor, actor->x, actor->y);
return 1;
}
@ -993,6 +1012,7 @@ static int lib_pPlayerZMovement(lua_State *L)
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_PlayerZMovement(actor);
P_CheckPosition(actor, actor->x, actor->y);
return 0;
}
@ -1716,6 +1736,18 @@ static int lib_pFloorzAtPos(lua_State *L)
return 1;
}
static int lib_pCeilingzAtPos(lua_State *L)
{
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
fixed_t z = luaL_checkfixed(L, 3);
fixed_t height = luaL_checkfixed(L, 4);
//HUDSAFE
INLEVEL
lua_pushfixed(L, P_CeilingzAtPos(x, y, z, height));
return 1;
}
static int lib_pDoSpring(lua_State *L)
{
mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -2587,30 +2619,56 @@ static int lib_rGetNameByColor(lua_State *L)
// S_SOUND
////////////
static int GetValidSoundOrigin(lua_State *L, void **origin)
{
const char *type;
lua_settop(L, 1);
type = GetUserdataUType(L);
if (fasticmp(type, "mobj_t"))
{
*origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
if (!(*origin))
return LUA_ErrInvalid(L, "mobj_t");
return 1;
}
else if (fasticmp(type, "sector_t"))
{
*origin = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
if (!(*origin))
return LUA_ErrInvalid(L, "sector_t");
*origin = &((sector_t *)(*origin))->soundorg;
return 1;
}
return LUA_ErrInvalid(L, "mobj_t/sector_t");
}
static int lib_sStartSound(lua_State *L)
{
const void *origin = NULL;
void *origin = NULL;
sfxenum_t sound_id = luaL_checkinteger(L, 2);
player_t *player = NULL;
//NOHUD
if (sound_id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
if (!lua_isnil(L, 1))
{
origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
}
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
{
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!lua_isnil(L, 1))
if (!GetValidSoundOrigin(L, &origin))
return 0;
if (!player || P_IsLocalPlayer(player))
{
if (hud_running)
origin = NULL; // HUD rendering startsound shouldn't have an origin, just remove it instead of having a retarded error.
if (hud_running || hook_cmd_running)
origin = NULL; // HUD rendering and CMD building startsound shouldn't have an origin, just remove it instead of having a retarded error.
S_StartSound(origin, sound_id);
}
@ -2619,18 +2677,12 @@ static int lib_sStartSound(lua_State *L)
static int lib_sStartSoundAtVolume(lua_State *L)
{
const void *origin = NULL;
void *origin = NULL;
sfxenum_t sound_id = luaL_checkinteger(L, 2);
INT32 volume = (INT32)luaL_checkinteger(L, 3);
player_t *player = NULL;
//NOHUD
if (!lua_isnil(L, 1))
{
origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
}
if (sound_id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
@ -2639,30 +2691,37 @@ static int lib_sStartSoundAtVolume(lua_State *L)
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!lua_isnil(L, 1))
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
if (!player || P_IsLocalPlayer(player))
S_StartSoundAtVolume(origin, sound_id, volume);
S_StartSoundAtVolume(origin, sound_id, volume);
return 0;
}
static int lib_sStopSound(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
void *origin = NULL;
//NOHUD
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
S_StopSound(origin);
return 0;
}
static int lib_sStopSoundByID(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
void *origin = NULL;
sfxenum_t sound_id = luaL_checkinteger(L, 2);
//NOHUD
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (sound_id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
if (!lua_isnil(L, 1))
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
S_StopSoundByID(origin, sound_id);
return 0;
@ -2888,11 +2947,12 @@ static int lib_sSetMusicPosition(lua_State *L)
static int lib_sOriginPlaying(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
void *origin = NULL;
//NOHUD
INLEVEL
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
lua_pushboolean(L, S_OriginPlaying(origin));
return 1;
}
@ -2909,14 +2969,15 @@ static int lib_sIdPlaying(lua_State *L)
static int lib_sSoundPlaying(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
void *origin = NULL;
sfxenum_t id = luaL_checkinteger(L, 2);
//NOHUD
INLEVEL
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1);
if (!GetValidSoundOrigin(L, &origin))
return LUA_ErrInvalid(L, "mobj_t/sector_t");
lua_pushboolean(L, S_SoundPlaying(origin, id));
return 1;
}
@ -3561,6 +3622,7 @@ static luaL_Reg lib[] = {
{"P_CheckHoopPosition",lib_pCheckHoopPosition},
{"P_RadiusAttack",lib_pRadiusAttack},
{"P_FloorzAtPos",lib_pFloorzAtPos},
{"P_CeilingzAtPos",lib_pCeilingzAtPos},
{"P_DoSpring",lib_pDoSpring},
// p_inter

View File

@ -1,6 +1,6 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by Iestyn "Monster Iestyn" Jealous.
// Copyright (C) 2016-2020 by Iestyn "Monster Iestyn" Jealous.
// Copyright (C) 2016-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
@ -13,6 +13,7 @@
#include "doomdef.h"
#include "p_local.h"
#include "r_main.h" // validcount
#include "p_polyobj.h"
#include "lua_script.h"
#include "lua_libs.h"
//#include "lua_hud.h" // hud_running errors
@ -20,6 +21,7 @@
static const char *const search_opt[] = {
"objects",
"lines",
"polyobjs",
NULL};
// a quickly-made function pointer typedef used by lib_searchBlockmap...
@ -167,6 +169,55 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th
return 0; // Everything was checked.
}
// Helper function for "polyobjs" search
static UINT8 lib_searchBlockmap_PolyObjs(lua_State *L, INT32 x, INT32 y, mobj_t *thing)
{
INT32 offset;
polymaplink_t *plink; // haleyjd 02/22/06
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
return 0;
offset = y*bmapwidth + x;
// haleyjd 02/22/06: consider polyobject lines
plink = polyblocklinks[offset];
while (plink)
{
polyobj_t *po = plink->po;
if (po->validcount != validcount) // if polyobj hasn't been checked
{
po->validcount = validcount;
lua_pushvalue(L, 1);
LUA_PushUserdata(L, thing, META_MOBJ);
LUA_PushUserdata(L, po, META_POLYOBJ);
if (lua_pcall(gL, 2, 1, 0)) {
if (!blockfuncerror || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
blockfuncerror = true;
return 0; // *shrugs*
}
if (!lua_isnil(gL, -1))
{ // if nil, continue
if (lua_toboolean(gL, -1))
return 2; // stop whole search
else
return 1; // stop block search
}
lua_pop(gL, 1);
if (P_MobjWasRemoved(thing))
return 2;
}
plink = (polymaplink_t *)(plink->link.next);
}
return 0; // Everything was checked.
}
// The searchBlockmap function
// arguments: searchBlockmap(searchtype, function, mobj, [x1, x2, y1, y2])
// return value:
@ -195,6 +246,9 @@ static int lib_searchBlockmap(lua_State *L)
case 1: // "lines"
searchFunc = lib_searchBlockmap_Lines;
break;
case 2: // "polyobjs"
searchFunc = lib_searchBlockmap_PolyObjs;
break;
}
// the mobj we are searching around, the "calling" mobj we could say

View File

@ -432,6 +432,46 @@ static int lib_cvFindVar(lua_State *L)
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);
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);
CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2));
return 0;
}
// CONS_Printf for a single player
// Use 'print' in baselib for a global message.
static int lib_consPrintf(lua_State *L)
@ -472,6 +512,9 @@ static luaL_Reg lib[] = {
{"COM_BufInsertText", lib_comBufInsertText},
{"CV_RegisterVar", lib_cvRegisterVar},
{"CV_FindVar", lib_cvFindVar},
{"CV_Set", lib_cvSet},
{"CV_StealthSet", lib_cvStealthSet},
{"CV_AddValue", lib_cvAddValue},
{"CONS_Printf", lib_consPrintf},
{NULL, NULL}
};

View File

@ -59,11 +59,14 @@ enum hook {
hook_PlayerThink,
hook_ShouldJingleContinue,
hook_GameQuit,
hook_PlayerCmd,
hook_MAX // last hook
};
extern const char *const hookNames[];
extern boolean hook_cmd_running;
void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load)
void LUAh_MapLoad(void); // Hook for map load
void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer
@ -113,4 +116,5 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_
#endif
#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
void LUAh_GameQuit(void); // Hook for game quitting
void LUAh_GameQuit(void); // Hook for game quitting
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart)

View File

@ -23,6 +23,10 @@
#include "lua_hook.h"
#include "lua_hud.h" // hud_running errors
#include "m_perfstats.h"
#include "d_netcmd.h" // for cv_perfstats
#include "i_system.h" // I_GetTimeMicros
static UINT8 hooksAvailable[(hook_MAX/8)+1];
const char *const hookNames[hook_MAX+1] = {
@ -71,6 +75,7 @@ const char *const hookNames[hook_MAX+1] = {
"PlayerThink",
"ShouldJingleContinue",
"GameQuit",
"PlayerCmd",
NULL
};
@ -259,6 +264,9 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
I_Assert(mo->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -268,6 +276,7 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, mo, META_MOBJ);
PushHook(gL, hookp);
@ -289,6 +298,7 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, mo, META_MOBJ);
PushHook(gL, hookp);
@ -324,6 +334,7 @@ boolean LUAh_PlayerHook(player_t *plr, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, plr, META_PLAYER);
PushHook(gL, hookp);
@ -455,6 +466,9 @@ void LUAh_PreThinkFrame(void)
void LUAh_ThinkFrame(void)
{
hook_p hookp;
// variables used by perf stats
int hook_index = 0;
int time_taken = 0;
if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8))))
return;
@ -465,6 +479,8 @@ void LUAh_ThinkFrame(void)
if (hookp->type != hook_ThinkFrame)
continue;
if (cv_perfstats.value == 3)
time_taken = I_GetTimeMicros();
PushHook(gL, hookp);
if (lua_pcall(gL, 0, 0, 1)) {
if (!hookp->error || cv_debug & DBG_LUA)
@ -472,6 +488,16 @@ void LUAh_ThinkFrame(void)
lua_pop(gL, 1);
hookp->error = true;
}
if (cv_perfstats.value == 3)
{
lua_Debug ar;
time_taken = I_GetTimeMicros() - time_taken;
// we need the function, let's just retrieve it again
PushHook(gL, hookp);
lua_getinfo(gL, ">S", &ar);
PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
hook_index++;
}
}
lua_pop(gL, 1); // Pop error handler
@ -513,6 +539,9 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
I_Assert(thing1->type < NUMMOBJTYPES);
if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing1->type]))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -522,6 +551,7 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, thing1, META_MOBJ);
@ -552,6 +582,7 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, thing1, META_MOBJ);
@ -590,6 +621,9 @@ UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which)
I_Assert(thing->type < NUMMOBJTYPES);
if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing->type]))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -599,6 +633,7 @@ UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, thing, META_MOBJ);
@ -629,6 +664,7 @@ UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which)
if (hookp->type != which)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, thing, META_MOBJ);
@ -668,12 +704,16 @@ boolean LUAh_MobjThinker(mobj_t *mo)
I_Assert(mo->type < NUMMOBJTYPES);
if (!(mobjthinkerhooks[MT_NULL] || mobjthinkerhooks[mo->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
// Look for all generic mobj thinker hooks
for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next)
{
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, mo, META_MOBJ);
PushHook(gL, hookp);
@ -692,6 +732,7 @@ boolean LUAh_MobjThinker(mobj_t *mo)
for (hookp = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next)
{
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
LUA_PushUserdata(gL, mo, META_MOBJ);
PushHook(gL, hookp);
@ -718,10 +759,13 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8))))
return 0;
return false;
I_Assert(special->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[special->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -731,6 +775,7 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
if (hookp->type != hook_TouchSpecial)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, special, META_MOBJ);
@ -756,6 +801,7 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
if (hookp->type != hook_TouchSpecial)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, special, META_MOBJ);
@ -790,6 +836,9 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -799,6 +848,7 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
if (hookp->type != hook_ShouldDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -834,6 +884,7 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
{
if (hookp->type != hook_ShouldDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -875,10 +926,13 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8))))
return 0;
return false;
I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -888,6 +942,7 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
if (hookp->type != hook_MobjDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -919,6 +974,7 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
if (hookp->type != hook_MobjDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -955,10 +1011,13 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8))))
return 0;
return false;
I_Assert(target->type < NUMMOBJTYPES);
if (!(mobjhooks[MT_NULL] || mobjhooks[target->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -968,6 +1027,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
if (hookp->type != hook_MobjDeath)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -997,6 +1057,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
if (hookp->type != hook_MobjDeath)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, target, META_MOBJ);
@ -1189,6 +1250,7 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
if (strcmp(hookp->s.str, line->stringargs[0]))
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, line, META_LINE);
@ -1354,6 +1416,9 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8))))
return false;
if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type]))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -1363,6 +1428,7 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
if (hookp->type != hook_MapThingSpawn)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, mo, META_MOBJ);
@ -1388,6 +1454,7 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
if (hookp->type != hook_MapThingSpawn)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, mo, META_MOBJ);
@ -1420,6 +1487,9 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
if (!gL || !(hooksAvailable[hook_FollowMobj/8] & (1<<(hook_FollowMobj%8))))
return 0;
if (!(mobjhooks[MT_NULL] || mobjhooks[mobj->type]))
return 0;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
@ -1429,6 +1499,7 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
if (hookp->type != hook_FollowMobj)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, player, META_PLAYER);
@ -1454,6 +1525,7 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
if (hookp->type != hook_FollowMobj)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, player, META_PLAYER);
@ -1494,6 +1566,7 @@ UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj)
if (hookp->type != hook_PlayerCanDamage)
continue;
ps_lua_mobjhooks++;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, player, META_PLAYER);
@ -1793,6 +1866,49 @@ void LUAh_GameQuit(void)
hookp->error = true;
}
}
lua_pop(gL, 1); // Pop error handler
}
// Hook for building player's ticcmd struct (Ported from SRB2Kart)
boolean hook_cmd_running = false;
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_PlayerCmd/8] & (1<<(hook_PlayerCmd%8))))
return false;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
hook_cmd_running = true;
for (hookp = roothook; hookp; hookp = hookp->next)
{
if (hookp->type != hook_PlayerCmd)
continue;
if (lua_gettop(gL) == 1)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, cmd, META_TICCMD);
}
PushHook(gL, hookp);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 1)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
}
lua_settop(gL, 0);
hook_cmd_running = false;
return hooked;
}

View File

@ -992,6 +992,19 @@ static int libd_getColormap(lua_State *L)
return 1;
}
static int libd_getStringColormap(lua_State *L)
{
INT32 flags = luaL_checkinteger(L, 1);
UINT8* colormap = NULL;
HUDONLY
colormap = V_GetStringColormap(flags & V_CHARCOLORMASK);
if (colormap) {
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1;
}
return 0;
}
static int libd_fadeScreen(lua_State *L)
{
UINT16 color = luaL_checkinteger(L, 1);
@ -1142,6 +1155,7 @@ static luaL_Reg lib_draw[] = {
{"getSpritePatch", libd_getSpritePatch},
{"getSprite2Patch", libd_getSprite2Patch},
{"getColormap", libd_getColormap},
{"getStringColormap", libd_getStringColormap},
// drawing
{"draw", libd_draw},
{"drawScaled", libd_drawScaled},

View File

@ -17,7 +17,7 @@
#include "p_mobj.h"
#include "p_local.h"
#include "z_zone.h"
#include "r_patch.h"
#include "r_picformats.h"
#include "r_things.h"
#include "r_draw.h" // R_GetColorByName
#include "doomstat.h" // luabanks[]
@ -25,6 +25,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
extern CV_PossibleValue_t Color_cons_t[];
extern UINT8 skincolor_modified[];
@ -165,6 +166,8 @@ static int lib_setSpr2default(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spr2defaults[] in CMD building code!");
// todo: maybe allow setting below first freeslot..? step 1 is toggling this, step 2 is testing to see whether it's net-safe
#ifdef SETALLSPR2DEFAULTS
@ -371,6 +374,8 @@ static int lib_setSpriteInfo(lua_State *L)
return luaL_error(L, "Do not alter spriteinfo_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!");
lua_remove(L, 1);
{
@ -455,6 +460,8 @@ static int spriteinfo_set(lua_State *L)
return luaL_error(L, "Do not alter spriteinfo_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!");
I_Assert(sprinfo != NULL);
@ -533,6 +540,8 @@ static int pivotlist_set(lua_State *L)
return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteframepivot_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!");
I_Assert(pivotlist != NULL);
@ -587,6 +596,8 @@ static int framepivot_set(lua_State *L)
return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteframepivot_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!");
I_Assert(framepivot != NULL);
@ -686,6 +697,8 @@ static int lib_setState(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter states in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter states in CMD building code!");
// clear the state to start with, in case of missing table elements
memset(state,0,sizeof(state_t));
@ -906,6 +919,8 @@ static int state_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter states in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter states in CMD building code!");
if (fastcmp(field,"sprite")) {
value = luaL_checknumber(L, 3);
@ -1006,6 +1021,8 @@ static int lib_setMobjInfo(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobjinfo in CMD building code!");
// clear the mobjinfo to start with, in case of missing table elements
memset(info,0,sizeof(mobjinfo_t));
@ -1173,6 +1190,8 @@ static int mobjinfo_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobjinfo in CMD building code!");
I_Assert(info != NULL);
I_Assert(info >= mobjinfo);
@ -1295,6 +1314,8 @@ static int lib_setSfxInfo(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter sfxinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter sfxinfo in CMD building code!");
lua_pushnil(L);
while (lua_next(L, 1)) {
@ -1376,6 +1397,8 @@ static int sfxinfo_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter S_sfx in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter S_sfx in CMD building code!");
I_Assert(sfx != NULL);
@ -1443,6 +1466,8 @@ static int lib_setluabanks(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter luabanks[] in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter luabanks[] in CMD building code!");
lua_remove(L, 1); // don't care about luabanks[] dummy userdata.
@ -1523,6 +1548,8 @@ static int lib_setSkinColor(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter skincolors in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter skincolors in CMD building code!");
// clear the skincolor to start with, in case of missing table elements
memset(info,0,sizeof(skincolor_t));
@ -1542,8 +1569,10 @@ static int lib_setSkinColor(lua_State *L)
strlcpy(info->name, n, MAXCOLORNAME+1);
if (strlen(n) > MAXCOLORNAME)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name);
#if 0
if (strchr(info->name, ' ') != NULL)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", info->name);
#endif
if (info->name[0] != '\0') // don't check empty string for dupe
{
@ -1633,8 +1662,10 @@ static int skincolor_set(lua_State *L)
strlcpy(info->name, n, MAXCOLORNAME+1);
if (strlen(n) > MAXCOLORNAME)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name);
#if 0
if (strchr(info->name, ' ') != NULL)
CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", info->name);
#endif
if (info->name[0] != '\0') // don't check empty string for dupe
{
@ -1707,6 +1738,8 @@ static int colorramp_set(lua_State *L)
return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1);
if (hud_running)
return luaL_error(L, "Do not alter skincolor_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter skincolor_t in CMD building code!");
colorramp[n] = i;
skincolor_modified[cnum] = true;
return 0;

View File

@ -50,6 +50,8 @@ extern lua_State *gL;
#define META_VECTOR3 "VECTOR3_T"
#define META_MAPHEADER "MAPHEADER_T*"
#define META_POLYOBJ "POLYOBJ_T*"
#define META_CVAR "CONSVAR_T*"
#define META_SECTORLINES "SECTOR_T*LINES"
@ -58,6 +60,8 @@ extern lua_State *gL;
#define META_LINESTRINGARGS "LINE_T*STRINGARGS"
#define META_THINGARGS "MAPTHING_T*ARGS"
#define META_THINGSTRINGARGS "MAPTHING_T*STRINGARGS"
#define META_POLYOBJVERTICES "POLYOBJ_T*VERTICES"
#define META_POLYOBJLINES "POLYOBJ_T*LINES"
#ifdef HAVE_LUA_SEGS
#define META_NODEBBOX "NODE_T*BBOX"
#define META_NODECHILDREN "NODE_T*CHILDREN"
@ -88,5 +92,6 @@ int LUA_PlayerLib(lua_State *L);
int LUA_SkinLib(lua_State *L);
int LUA_ThinkerLib(lua_State *L);
int LUA_MapLib(lua_State *L);
int LUA_PolyObjLib(lua_State *L);
int LUA_BlockmapLib(lua_State *L);
int LUA_HudLib(lua_State *L);

View File

@ -16,11 +16,13 @@
#include "p_setup.h"
#include "z_zone.h"
#include "p_slopes.h"
#include "p_polyobj.h"
#include "r_main.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
#include "dehacked.h"
#include "fastcmp.h"
@ -67,6 +69,7 @@ enum subsector_e {
subsector_sector,
subsector_numlines,
subsector_firstline,
subsector_polyList
};
static const char *const subsector_opt[] = {
@ -74,6 +77,7 @@ static const char *const subsector_opt[] = {
"sector",
"numlines",
"firstline",
"polyList",
NULL};
enum line_e {
@ -95,6 +99,7 @@ enum line_e {
line_slopetype,
line_frontsector,
line_backsector,
line_polyobj,
line_text,
line_callcount
};
@ -118,6 +123,7 @@ static const char *const line_opt[] = {
"slopetype",
"frontsector",
"backsector",
"polyobj",
"text",
"callcount",
NULL};
@ -218,6 +224,7 @@ enum seg_e {
seg_linedef,
seg_frontsector,
seg_backsector,
seg_polyseg
};
static const char *const seg_opt[] = {
@ -231,6 +238,7 @@ static const char *const seg_opt[] = {
"linedef",
"frontsector",
"backsector",
"polyseg",
NULL};
enum node_e {
@ -320,9 +328,9 @@ static const char *const vector_opt[] = {
static const char *const array_opt[] ={"iterate",NULL};
static const char *const valid_opt[] ={"valid",NULL};
///////////////////////////////////
// sector list iterate functions //
///////////////////////////////////
/////////////////////////////////////////////
// sector/subsector list iterate functions //
/////////////////////////////////////////////
// iterates through a sector's thinglist!
static int lib_iterateSectorThinglist(lua_State *L)
@ -394,6 +402,41 @@ static int lib_iterateSectorFFloors(lua_State *L)
return 0;
}
// iterates through a subsector's polyList! (for polyobj_t)
static int lib_iterateSubSectorPolylist(lua_State *L)
{
polyobj_t *state = NULL;
polyobj_t *po = NULL;
INLEVEL
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call subsector.polyList() directly, use it as 'for polyobj in subsector.polyList do <block> end'.");
if (!lua_isnil(L, 1))
state = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
else
return 0; // no polylist to iterate through sorry!
lua_settop(L, 2);
lua_remove(L, 1); // remove state now.
if (!lua_isnil(L, 1))
{
po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
po = (polyobj_t *)(po->link.next);
}
else
po = state; // state is used as the "start" of the polylist
if (po)
{
LUA_PushUserdata(L, po, META_POLYOBJ);
return 1;
}
return 0;
}
static int sector_iterate(lua_State *L)
{
lua_pushvalue(L, lua_upvalueindex(1)); // iterator function, or the "generator"
@ -442,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
// we need this to determine the array's actual size, and therefore also the maximum value allowed as an index
// this only works if seclines is actually a pointer to a sector's lines member in memory, oh boy
numoflines = (size_t)(*(size_t *)(((size_t)seclines) - (offsetof(sector_t, lines) - offsetof(sector_t, linecount))));
numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount);
/* OLD HACK
// check first linedef to figure which of its sectors owns this sector->lines pointer
@ -476,7 +519,7 @@ static int sectorlines_num(lua_State *L)
return luaL_error(L, "accessed sector_t.lines doesn't exist anymore.");
// 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);
return 1;
}
@ -581,6 +624,8 @@ static int sector_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter sector_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter sector_t in CMD building code!");
switch(field)
{
@ -680,6 +725,11 @@ static int subsector_get(lua_State *L)
case subsector_firstline:
lua_pushinteger(L, subsector->firstline);
return 1;
case subsector_polyList: // polyList
lua_pushcfunction(L, lib_iterateSubSectorPolylist);
LUA_PushUserdata(L, subsector->polyList, META_POLYOBJ);
lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateSubSectorPolylist and subsector->polyList as upvalues for the function
return 1;
}
return 0;
}
@ -817,6 +867,9 @@ static int line_get(lua_State *L)
case line_backsector:
LUA_PushUserdata(L, line->backsector, META_SECTOR);
return 1;
case line_polyobj:
LUA_PushUserdata(L, line->polyobj, META_POLYOBJ);
return 1;
case line_text:
lua_pushstring(L, line->text);
return 1;
@ -1079,6 +1132,9 @@ static int seg_get(lua_State *L)
case seg_backsector:
LUA_PushUserdata(L, seg->backsector, META_SECTOR);
return 1;
case seg_polyseg:
LUA_PushUserdata(L, seg->polyseg, META_POLYOBJ);
return 1;
}
return 0;
}
@ -1762,6 +1818,8 @@ static int ffloor_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter ffloor_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter ffloor_t in CMD building code!");
switch(field)
{
@ -1886,6 +1944,8 @@ static int slope_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter pslope_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter pslope_t in CMD building code!");
switch(field) // todo: reorganize this shit
{

View File

@ -20,6 +20,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
static const char *const array_opt[] ={"iterate",NULL};
@ -437,6 +438,8 @@ static int mobj_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter mobj_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobj_t in CMD building code!");
switch(field)
{
@ -878,6 +881,8 @@ static int mapthing_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter mapthing_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mapthing_t in CMD building code!");
if(fastcmp(field,"x"))
mt->x = (INT16)luaL_checkinteger(L, 3);

View File

@ -20,6 +20,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running errors
static int lib_iteratePlayers(lua_State *L)
{
@ -400,6 +401,8 @@ static int player_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in CMD building code!");
if (fastcmp(field,"mo") || fastcmp(field,"realmo")) {
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
@ -770,6 +773,8 @@ static int power_set(lua_State *L)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %d", (INT16)p);
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in CMD building code!");
powers[p] = i;
return 0;
}

486
src/lua_polyobjlib.c Normal file
View File

@ -0,0 +1,486 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Iestyn "Monster Iestyn" Jealous.
// Copyright (C) 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 lua_polyobjlib.c
/// \brief polyobject library for Lua scripting
#include "doomdef.h"
#include "fastcmp.h"
#include "p_local.h"
#include "p_polyobj.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
enum polyobj_e {
// properties
polyobj_valid = 0,
polyobj_id,
polyobj_parent,
polyobj_vertices,
polyobj_lines,
polyobj_sector,
polyobj_angle,
polyobj_damage,
polyobj_thrust,
polyobj_flags,
polyobj_translucency,
polyobj_triggertag,
// special functions - utility
polyobj_pointInside,
polyobj_mobjTouching,
polyobj_mobjInside,
// special functions - manipulation
polyobj_moveXY,
polyobj_rotate
};
static const char *const polyobj_opt[] = {
// properties
"valid",
"id",
"parent",
"vertices",
"lines",
"sector",
"angle",
"damage",
"thrust",
"flags",
"translucency",
"triggertag",
// special functions - utility
"pointInside",
"mobjTouching",
"mobjInside",
// special functions - manipulation
"moveXY",
"rotate",
NULL};
static const char *const valid_opt[] ={"valid",NULL};
////////////////////////
// polyobj.vertices[] //
////////////////////////
// polyobj.vertices, i -> polyobj.vertices[i]
// polyobj.vertices.valid, for validity checking
//
// see sectorlines_get in lua_maplib.c
//
static int polyobjvertices_get(lua_State *L)
{
vertex_t ***polyverts = *((vertex_t ****)luaL_checkudata(L, 1, META_POLYOBJVERTICES));
size_t i;
size_t numofverts = 0;
lua_settop(L, 2);
if (!lua_isnumber(L, 2))
{
int field = luaL_checkoption(L, 2, NULL, valid_opt);
if (!polyverts || !(*polyverts))
{
if (field == 0) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore.");
} else if (field == 0) {
lua_pushboolean(L, 1);
return 1;
}
}
numofverts = *(size_t *)FIELDFROM (polyobj_t, polyverts, vertices,/* -> */numVertices);
if (!numofverts)
return luaL_error(L, "no vertices found!");
i = (size_t)lua_tointeger(L, 2);
if (i >= numofverts)
return 0;
LUA_PushUserdata(L, (*polyverts)[i], META_VERTEX);
return 1;
}
// #(polyobj.vertices) -> polyobj.numVertices
static int polyobjvertices_num(lua_State *L)
{
vertex_t ***polyverts = *((vertex_t ****)luaL_checkudata(L, 1, META_POLYOBJVERTICES));
size_t numofverts = 0;
if (!polyverts || !(*polyverts))
return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore.");
numofverts = *(size_t *)FIELDFROM (polyobj_t, polyverts, vertices,/* -> */numVertices);
lua_pushinteger(L, numofverts);
return 1;
}
/////////////////////
// polyobj.lines[] //
/////////////////////
// polyobj.lines, i -> polyobj.lines[i]
// polyobj.lines.valid, for validity checking
//
// see sectorlines_get in lua_maplib.c
//
static int polyobjlines_get(lua_State *L)
{
line_t ***polylines = *((line_t ****)luaL_checkudata(L, 1, META_POLYOBJLINES));
size_t i;
size_t numoflines = 0;
lua_settop(L, 2);
if (!lua_isnumber(L, 2))
{
int field = luaL_checkoption(L, 2, NULL, valid_opt);
if (!polylines || !(*polylines))
{
if (field == 0) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore.");
} else if (field == 0) {
lua_pushboolean(L, 1);
return 1;
}
}
numoflines = *(size_t *)FIELDFROM (polyobj_t, polylines, lines,/* -> */numLines);
if (!numoflines)
return luaL_error(L, "no lines found!");
i = (size_t)lua_tointeger(L, 2);
if (i >= numoflines)
return 0;
LUA_PushUserdata(L, (*polylines)[i], META_LINE);
return 1;
}
// #(polyobj.lines) -> polyobj.numLines
static int polyobjlines_num(lua_State *L)
{
line_t ***polylines = *((line_t ****)luaL_checkudata(L, 1, META_POLYOBJLINES));
size_t numoflines = 0;
if (!polylines || !(*polylines))
return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore.");
numoflines = *(size_t *)FIELDFROM (polyobj_t, polylines, lines,/* -> */numLines);
lua_pushinteger(L, numoflines);
return 1;
}
/////////////////////////////////
// polyobj_t function wrappers //
/////////////////////////////////
// special functions - utility
static int lib_polyobj_PointInside(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
lua_pushboolean(L, P_PointInsidePolyobj(po, x, y));
return 1;
}
static int lib_polyobj_MobjTouching(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_MobjTouchingPolyobj(po, mo));
return 1;
}
static int lib_polyobj_MobjInside(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_MobjInsidePolyobj(po, mo));
return 1;
}
// special functions - manipulation
static int lib_polyobj_moveXY(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
boolean checkmobjs = lua_opttrueboolean(L, 4);
NOHUD
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
lua_pushboolean(L, Polyobj_moveXY(po, x, y, checkmobjs));
return 1;
}
static int lib_polyobj_rotate(lua_State *L)
{
polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
angle_t delta = luaL_checkangle(L, 2);
UINT8 turnthings = (UINT8)luaL_optinteger(L, 3, 0); // don't turn anything by default? (could change this if not desired)
boolean checkmobjs = lua_opttrueboolean(L, 4);
NOHUD
INLEVEL
if (!po)
return LUA_ErrInvalid(L, "polyobj_t");
lua_pushboolean(L, Polyobj_rotate(po, delta, turnthings, checkmobjs));
return 1;
}
///////////////
// polyobj_t //
///////////////
static int polyobj_get(lua_State *L)
{
polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
enum polyobj_e field = luaL_checkoption(L, 2, NULL, polyobj_opt);
if (!polyobj) {
if (field == polyobj_valid) {
lua_pushboolean(L, false);
return 1;
}
return LUA_ErrInvalid(L, "polyobj_t");
}
switch (field)
{
// properties
case polyobj_valid:
lua_pushboolean(L, true);
break;
case polyobj_id:
lua_pushinteger(L, polyobj->id);
break;
case polyobj_parent:
lua_pushinteger(L, polyobj->parent);
break;
case polyobj_vertices: // vertices
LUA_PushUserdata(L, &polyobj->vertices, META_POLYOBJVERTICES); // push the address of the "vertices" member in the struct, to allow our hacks to work
break;
case polyobj_lines: // lines
LUA_PushUserdata(L, &polyobj->lines, META_POLYOBJLINES); // push the address of the "lines" member in the struct, to allow our hacks to work
break;
case polyobj_sector: // shortcut that exists only in Lua!
LUA_PushUserdata(L, polyobj->lines[0]->backsector, META_SECTOR);
break;
case polyobj_angle:
lua_pushangle(L, polyobj->angle);
break;
case polyobj_damage:
lua_pushinteger(L, polyobj->damage);
break;
case polyobj_thrust:
lua_pushfixed(L, polyobj->thrust);
break;
case polyobj_flags:
lua_pushinteger(L, polyobj->flags);
break;
case polyobj_translucency:
lua_pushinteger(L, polyobj->translucency);
break;
case polyobj_triggertag:
lua_pushinteger(L, polyobj->triggertag);
break;
// special functions - utility
case polyobj_pointInside:
lua_pushcfunction(L, lib_polyobj_PointInside);
break;
case polyobj_mobjTouching:
lua_pushcfunction(L, lib_polyobj_MobjTouching);
break;
case polyobj_mobjInside:
lua_pushcfunction(L, lib_polyobj_MobjInside);
break;
// special functions - manipulation
case polyobj_moveXY:
lua_pushcfunction(L, lib_polyobj_moveXY);
break;
case polyobj_rotate:
lua_pushcfunction(L, lib_polyobj_rotate);
break;
}
return 1;
}
static int polyobj_set(lua_State *L)
{
polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
enum polyobj_e field = luaL_checkoption(L, 2, NULL, polyobj_opt);
if (!polyobj)
return LUA_ErrInvalid(L, "polyobj_t");
if (hud_running)
return luaL_error(L, "Do not alter polyobj_t in HUD rendering code!");
switch (field)
{
default:
return luaL_error(L, LUA_QL("polyobj_t") " field " LUA_QS " cannot be modified.", polyobj_opt[field]);
case polyobj_angle:
return luaL_error(L, LUA_QL("polyobj_t") " field " LUA_QS " should not be set directly. Use the function " LUA_QL("polyobj:rotate(angle)") " instead.", polyobj_opt[field]);
case polyobj_parent:
polyobj->parent = luaL_checkinteger(L, 3);
break;
case polyobj_flags:
polyobj->flags = luaL_checkinteger(L, 3);
break;
case polyobj_translucency:
polyobj->translucency = luaL_checkinteger(L, 3);
break;
}
return 0;
}
static int polyobj_num(lua_State *L)
{
polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ));
if (!polyobj)
return luaL_error(L, "accessed polyobj_t doesn't exist anymore.");
lua_pushinteger(L, polyobj-PolyObjects);
return 1;
}
///////////////////
// PolyObjects[] //
///////////////////
static int lib_iteratePolyObjects(lua_State *L)
{
INT32 i = -1;
if (lua_gettop(L) < 2)
{
//return luaL_error(L, "Don't call PolyObjects.iterate() directly, use it as 'for polyobj in PolyObjects.iterate do <block> end'.");
lua_pushcfunction(L, lib_iteratePolyObjects);
return 1;
}
lua_settop(L, 2);
lua_remove(L, 1); // state is unused.
if (!lua_isnil(L, 1))
i = (INT32)(*((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)) - PolyObjects);
for (i++; i < numPolyObjects; i++)
{
LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ);
return 1;
}
return 0;
}
static int lib_PolyObject_getfornum(lua_State *L)
{
INT32 id = (INT32)luaL_checkinteger(L, 1);
if (!numPolyObjects)
return 0; // if there's no PolyObjects then bail out here
LUA_PushUserdata(L, Polyobj_GetForNum(id), META_POLYOBJ);
return 1;
}
static int lib_getPolyObject(lua_State *L)
{
const char *field;
INT32 i;
// find PolyObject by number
if (lua_type(L, 2) == LUA_TNUMBER)
{
i = luaL_checkinteger(L, 2);
if (i < 0 || i >= numPolyObjects)
return luaL_error(L, "PolyObjects[] index %d out of range (0 - %d)", i, numPolyObjects-1);
LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ);
return 1;
}
field = luaL_checkstring(L, 2);
// special function iterate
if (fastcmp(field,"iterate"))
{
lua_pushcfunction(L, lib_iteratePolyObjects);
return 1;
}
// find PolyObject by ID
else if (fastcmp(field,"GetForNum")) // name could probably be better
{
lua_pushcfunction(L, lib_PolyObject_getfornum);
return 1;
}
return 0;
}
static int lib_numPolyObjects(lua_State *L)
{
lua_pushinteger(L, numPolyObjects);
return 1;
}
int LUA_PolyObjLib(lua_State *L)
{
luaL_newmetatable(L, META_POLYOBJVERTICES);
lua_pushcfunction(L, polyobjvertices_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, polyobjvertices_num);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_POLYOBJLINES);
lua_pushcfunction(L, polyobjlines_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, polyobjlines_num);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_POLYOBJ);
lua_pushcfunction(L, polyobj_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, polyobj_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, polyobj_num);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getPolyObject);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numPolyObjects);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "PolyObjects");
return 0;
}

View File

@ -24,6 +24,7 @@
#include "p_saveg.h"
#include "p_local.h"
#include "p_slopes.h" // for P_SlopeById
#include "p_polyobj.h" // polyobj_t, PolyObjects
#ifdef LUA_ALLOW_BYTECODE
#include "d_netfil.h" // for LUA_DumpFile
#endif
@ -50,6 +51,7 @@ static lua_CFunction liblist[] = {
LUA_SkinLib, // skin_t, skins[]
LUA_ThinkerLib, // thinker_t
LUA_MapLib, // line_t, side_t, sector_t, subsector_t
LUA_PolyObjLib, // polyobj_t
LUA_BlockmapLib, // blockmap stuff
LUA_HudLib, // HUD stuff
NULL
@ -774,6 +776,12 @@ void LUA_InvalidateLevel(void)
LUA_InvalidateUserdata(&sides[i]);
for (i = 0; i < numvertexes; i++)
LUA_InvalidateUserdata(&vertexes[i]);
for (i = 0; i < (size_t)numPolyObjects; i++)
{
LUA_InvalidateUserdata(&PolyObjects[i]);
LUA_InvalidateUserdata(&PolyObjects[i].vertices);
LUA_InvalidateUserdata(&PolyObjects[i].lines);
}
#ifdef HAVE_LUA_SEGS
for (i = 0; i < numsegs; i++)
LUA_InvalidateUserdata(&segs[i]);
@ -832,6 +840,7 @@ enum
ARCH_NODE,
#endif
ARCH_FFLOOR,
ARCH_POLYOBJ,
ARCH_SLOPE,
ARCH_MAPHEADER,
ARCH_SKINCOLOR,
@ -858,6 +867,7 @@ static const struct {
{META_NODE, ARCH_NODE},
#endif
{META_FFLOOR, ARCH_FFLOOR},
{META_POLYOBJ, ARCH_POLYOBJ},
{META_SLOPE, ARCH_SLOPE},
{META_MAPHEADER, ARCH_MAPHEADER},
{META_SKINCOLOR, ARCH_SKINCOLOR},
@ -1126,6 +1136,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
}
break;
}
case ARCH_POLYOBJ:
{
polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex));
if (!polyobj)
WRITEUINT8(save_p, ARCH_NULL);
else {
WRITEUINT8(save_p, ARCH_POLYOBJ);
WRITEUINT16(save_p, polyobj-PolyObjects);
}
break;
}
case ARCH_SLOPE:
{
pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex));
@ -1381,6 +1402,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
LUA_PushUserdata(gL, rover, META_FFLOOR);
break;
}
case ARCH_POLYOBJ:
LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ);
break;
case ARCH_SLOPE:
LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE);
break;

View File

@ -29,10 +29,10 @@
// GIFs are always little-endian
#include "byteptr.h"
consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_dynamicdelay = {"gif_dynamicdelay", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, 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_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_gif_localcolortable = CVAR_INIT ("gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL);
#ifdef HAVE_ANIGIF
static boolean gif_optimize = false; // So nobody can do something dumb
@ -499,20 +499,22 @@ static size_t gifframe_size = 8192;
// converts an RGB frame to a frame with a palette.
//
#ifdef HWRENDER
static colorlookup_t gif_colorlookup;
static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
{
UINT8 r, g, b;
size_t src = 0, dest = 0;
size_t size = (vid.width * vid.height * 3);
InitColorLUT(gif_framepalette);
InitColorLUT(&gif_colorlookup, (gif_localcolortable) ? gif_framepalette : gif_headerpalette, true);
while (src < size)
{
r = (UINT8)linear[src];
g = (UINT8)linear[src + 1];
b = (UINT8)linear[src + 2];
scr[dest] = colorlookup[r >> SHIFTCOLORBITS][g >> SHIFTCOLORBITS][b >> SHIFTCOLORBITS];
scr[dest] = GetColorLUTDirect(&gif_colorlookup, r, g, b);
src += (3 * scrbuf_downscaleamt);
dest += scrbuf_downscaleamt;
}

View File

@ -967,10 +967,10 @@ static CV_PossibleValue_t op_speed_t[] = {{1, "MIN"}, {128, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_flags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_hoopflags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}};
consvar_t cv_mapthingnum = {"op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_speed = {"op_speed", "16", CV_NOTINNET, op_speed_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_opflags = {"op_flags", "0", CV_NOTINNET, op_flags_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ophoopflags = {"op_hoopflags", "4", CV_NOTINNET, op_hoopflags_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mapthingnum = CVAR_INIT ("op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL);
consvar_t cv_speed = CVAR_INIT ("op_speed", "16", CV_NOTINNET, op_speed_t, NULL);
consvar_t cv_opflags = CVAR_INIT ("op_flags", "0", CV_NOTINNET, op_flags_t, NULL);
consvar_t cv_ophoopflags = CVAR_INIT ("op_hoopflags", "4", CV_NOTINNET, op_hoopflags_t, NULL);
boolean objectplacing = false;
mobjtype_t op_currentthing = 0; // For the object placement mode
@ -1023,8 +1023,8 @@ static void OP_CycleThings(INT32 amt)
states[S_OBJPLACE_DUMMY].frame = states[mobjinfo[op_currentthing].spawnstate].frame;
}
if (players[0].mo->eflags & MFE_VERTICALFLIP) // correct z when flipped
players[0].mo->z += players[0].mo->height - mobjinfo[op_currentthing].height;
players[0].mo->height = mobjinfo[op_currentthing].height;
players[0].mo->z += players[0].mo->height - FixedMul(mobjinfo[op_currentthing].height, players[0].mo->scale);
players[0].mo->height = FixedMul(mobjinfo[op_currentthing].height, players[0].mo->scale);
P_SetPlayerMobjState(players[0].mo, S_OBJPLACE_DUMMY);
op_currentdoomednum = mobjinfo[op_currentthing].doomednum;
@ -1107,6 +1107,10 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle)));
mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
mt->scale = player->mo->scale;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0;
return mt;
}
@ -1297,27 +1301,26 @@ void OP_ObjectplaceMovement(player_t *player)
{
ticcmd_t *cmd = &player->cmd;
if (!player->climbing && (netgame || !cv_analog[0].value || (player->pflags & PF_SPINNING)))
player->drawangle = player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */);
player->drawangle = player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */);
ticruned++;
if (!(cmd->angleturn & TICCMD_RECEIVED))
ticmiss++;
if (cmd->buttons & BT_JUMP)
player->mo->z += FRACUNIT*cv_speed.value;
player->mo->z += player->mo->scale*cv_speed.value;
else if (cmd->buttons & BT_SPIN)
player->mo->z -= FRACUNIT*cv_speed.value;
player->mo->z -= player->mo->scale*cv_speed.value;
if (cmd->forwardmove != 0)
{
P_Thrust(player->mo, player->mo->angle, (cmd->forwardmove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
P_Thrust(player->mo, player->mo->angle, (cmd->forwardmove*player->mo->scale/MAXPLMOVE)*cv_speed.value);
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
player->mo->momx = player->mo->momy = 0;
}
if (cmd->sidemove != 0)
{
P_Thrust(player->mo, player->mo->angle-ANGLE_90, (cmd->sidemove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
P_Thrust(player->mo, player->mo->angle-ANGLE_90, (cmd->sidemove*player->mo->scale/MAXPLMOVE)*cv_speed.value);
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
player->mo->momx = player->mo->momy = 0;
}
@ -1443,62 +1446,75 @@ void Command_ObjectPlace_f(void)
G_SetGameModified(multiplayer);
// Entering objectplace?
if (!objectplacing)
if (!objectplacing || COM_Argc() > 1)
{
objectplacing = true;
if (players[0].powers[pw_carry] == CR_NIGHTSMODE)
return;
if (!COM_CheckParm("-silent"))
if (!objectplacing)
{
HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE|V_AUTOFADEOUT);
HU_SetCEchoDuration(10);
HU_DoCEcho(va(M_GetText(
"\\\\\\\\\\\\\\\\\\\\\\\\\x82"
" Objectplace Controls: \x80\\\\"
"Weapon Next/Prev: Cycle mapthings\\"
" Jump: Float up \\"
" Spin: Float down \\"
" Fire Ring: Place object \\")));
objectplacing = true;
if (players[0].powers[pw_carry] == CR_NIGHTSMODE)
return;
if (!COM_CheckParm("-silent"))
{
HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE|V_AUTOFADEOUT);
HU_SetCEchoDuration(10);
HU_DoCEcho(va(M_GetText(
"\\\\\\\\\\\\\\\\\\\\\\\\\x82"
" Objectplace Controls: \x80\\\\"
"Weapon Next/Prev: Cycle mapthings\\"
" Jump: Float up \\"
" Spin: Float down \\"
" Fire Ring: Place object \\")));
}
// Save all the player's data.
op_oldflags1 = players[0].mo->flags;
op_oldflags2 = players[0].mo->flags2;
op_oldeflags = players[0].mo->eflags;
op_oldpflags = players[0].pflags;
op_oldmomx = players[0].mo->momx;
op_oldmomy = players[0].mo->momy;
op_oldmomz = players[0].mo->momz;
op_oldheight = players[0].mo->height;
op_oldstate = S_PLAY_STND;
op_oldcolor = players[0].mo->color; // save color too in case of super/fireflower
// Remove ALL flags and motion.
P_UnsetThingPosition(players[0].mo);
players[0].pflags = 0;
players[0].mo->flags2 = 0;
players[0].mo->eflags = 0;
players[0].mo->flags = (MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP);
players[0].mo->momx = players[0].mo->momy = players[0].mo->momz = 0;
P_SetThingPosition(players[0].mo);
// Take away color so things display properly
players[0].mo->color = 0;
// Like the classics, recover from death by entering objectplace
if (players[0].mo->health <= 0)
{
players[0].mo->health = 1;
players[0].deadtimer = 0;
op_oldflags1 = mobjinfo[MT_PLAYER].flags;
++players[0].lives;
players[0].playerstate = PST_LIVE;
P_RestoreMusic(&players[0]);
}
else
op_oldstate = (statenum_t)(players[0].mo->state-states);
}
// Save all the player's data.
op_oldflags1 = players[0].mo->flags;
op_oldflags2 = players[0].mo->flags2;
op_oldeflags = players[0].mo->eflags;
op_oldpflags = players[0].pflags;
op_oldmomx = players[0].mo->momx;
op_oldmomy = players[0].mo->momy;
op_oldmomz = players[0].mo->momz;
op_oldheight = players[0].mo->height;
op_oldstate = S_PLAY_STND;
op_oldcolor = players[0].mo->color; // save color too in case of super/fireflower
// Remove ALL flags and motion.
P_UnsetThingPosition(players[0].mo);
players[0].pflags = 0;
players[0].mo->flags2 = 0;
players[0].mo->eflags = 0;
players[0].mo->flags = (MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP);
players[0].mo->momx = players[0].mo->momy = players[0].mo->momz = 0;
P_SetThingPosition(players[0].mo);
// Take away color so things display properly
players[0].mo->color = 0;
// Like the classics, recover from death by entering objectplace
if (players[0].mo->health <= 0)
if (COM_Argc() > 1)
{
players[0].mo->health = 1;
players[0].deadtimer = 0;
op_oldflags1 = mobjinfo[MT_PLAYER].flags;
++players[0].lives;
players[0].playerstate = PST_LIVE;
P_RestoreMusic(&players[0]);
UINT16 mapthingnum = atoi(COM_Argv(1));
mobjtype_t type = P_GetMobjtype(mapthingnum);
if (type == MT_UNKNOWN)
CONS_Printf(M_GetText("No mobj type delegated to thing type %d.\n"), mapthingnum);
else
op_currentthing = type;
}
else
op_oldstate = (statenum_t)(players[0].mo->state-states);
// If no thing set, then cycle a little
if (!op_currentthing)
@ -1506,8 +1522,8 @@ void Command_ObjectPlace_f(void)
op_currentthing = 1;
OP_CycleThings(1);
}
else // Cycle things sets this for the former.
players[0].mo->height = mobjinfo[op_currentthing].height;
else
OP_CycleThings(0); // sets all necessary height values without cycling op_currentthing
P_SetPlayerMobjState(players[0].mo, S_OBJPLACE_DUMMY);
}

View File

@ -406,37 +406,29 @@ static void M_ResetCvars(void);
// Consvar onchange functions
static void Newgametype_OnChange(void);
#ifdef HWRENDER
static void Newrenderer_OnChange(void);
#endif
static void Dummymares_OnChange(void);
// ==========================================================================
// CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE.
// ==========================================================================
consvar_t cv_showfocuslost = {"showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL };
consvar_t cv_showfocuslost = CVAR_INIT ("showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL);
static CV_PossibleValue_t map_cons_t[] = {
{1,"MIN"},
{NUMMAPS, "MAX"},
{0,NULL}
};
consvar_t cv_nextmap = {"nextmap", "1", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_nextmap = CVAR_INIT ("nextmap", "1", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange);
static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}};
consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL};
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.
// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h!
CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1];
consvar_t cv_newgametype = {"newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL};
#ifdef HWRENDER
consvar_t cv_newrenderer = {"newrenderer", "Software", CV_HIDEN|CV_CALL, cv_renderer_t, Newrenderer_OnChange, 0, NULL, NULL, 0, 0, NULL};
static int newrenderer_set = 1;/* Software doesn't need confirmation! */
#endif
consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange);
static CV_PossibleValue_t serversort_cons_t[] = {
{0,"Ping"},
@ -447,22 +439,22 @@ static CV_PossibleValue_t serversort_cons_t[] = {
{5,"Gametype"},
{0,NULL}
};
consvar_t cv_serversort = {"serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_serversort = CVAR_INIT ("serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList);
// first time memory
consvar_t cv_tutorialprompt = {"tutorialprompt", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_tutorialprompt = CVAR_INIT ("tutorialprompt", "On", CV_SAVE, CV_OnOff, NULL);
// autorecord demos for time attack
static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_autorecord = CVAR_INIT ("autorecord", "Yes", 0, CV_YesNo, NULL);
CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show"}, {2, "Show All"}, {0, NULL}};
CV_PossibleValue_t ghost2_cons_t[] = {{0, "Hide"}, {1, "Show"}, {0, NULL}};
consvar_t cv_ghost_bestscore = {"ghost_bestscore", "Show", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_besttime = {"ghost_besttime", "Show", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_bestrings = {"ghost_bestrings", "Show", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_last = {"ghost_last", "Show", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_guest = {"ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ghost_bestscore = CVAR_INIT ("ghost_bestscore", "Show", CV_SAVE, ghost_cons_t, NULL);
consvar_t cv_ghost_besttime = CVAR_INIT ("ghost_besttime", "Show", CV_SAVE, ghost_cons_t, NULL);
consvar_t cv_ghost_bestrings = CVAR_INIT ("ghost_bestrings", "Show", CV_SAVE, ghost_cons_t, NULL);
consvar_t cv_ghost_last = CVAR_INIT ("ghost_last", "Show", CV_SAVE, ghost_cons_t, NULL);
consvar_t cv_ghost_guest = CVAR_INIT ("ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL);
//Console variables used solely in the menu system.
//todo: add a way to use non-console variables in the menu
@ -476,19 +468,19 @@ static CV_PossibleValue_t dummymares_cons_t[] = {
{-1, "END"}, {0,"Overall"}, {1,"Mare 1"}, {2,"Mare 2"}, {3,"Mare 3"}, {4,"Mare 4"}, {5,"Mare 5"}, {6,"Mare 6"}, {7,"Mare 7"}, {8,"Mare 8"}, {0,NULL}
};
static consvar_t cv_dummyteam = {"dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummyscramble = {"dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummyrings = {"dummyrings", "0", CV_HIDEN, ringlimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummylives = {"dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummycontinues = {"dummycontinues", "0", CV_HIDEN, contlimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL);
static consvar_t cv_dummyscramble = CVAR_INIT ("dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL);
static consvar_t cv_dummyrings = CVAR_INIT ("dummyrings", "0", CV_HIDEN, ringlimit_cons_t, NULL);
static consvar_t cv_dummylives = CVAR_INIT ("dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL);
static consvar_t cv_dummycontinues = CVAR_INIT ("dummycontinues", "0", CV_HIDEN, contlimit_cons_t, NULL);
static consvar_t cv_dummymares = CVAR_INIT ("dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange);
CV_PossibleValue_t marathon_cons_t[] = {{0, "Standard"}, {1, "Live Event Backup"}, {2, "Ultimate"}, {0, NULL}};
CV_PossibleValue_t loadless_cons_t[] = {{0, "Realtime"}, {1, "In-game"}, {0, NULL}};
consvar_t cv_dummymarathon = {"dummymarathon", "Standard", CV_HIDEN, marathon_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummycutscenes = {"dummycutscenes", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummyloadless = {"dummyloadless", "In-game", CV_HIDEN, loadless_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummymarathon = CVAR_INIT ("dummymarathon", "Standard", CV_HIDEN, marathon_cons_t, NULL);
consvar_t cv_dummycutscenes = CVAR_INIT ("dummycutscenes", "Off", CV_HIDEN, CV_OnOff, NULL);
consvar_t cv_dummyloadless = CVAR_INIT ("dummyloadless", "In-game", CV_HIDEN, loadless_cons_t, NULL);
// ==========================================================================
// ORGANIZATION START.
@ -1347,7 +1339,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
#endif
{IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 16},
#ifdef HWRENDER
{IT_STRING | IT_CVAR, NULL, "Renderer", &cv_newrenderer, 21},
{IT_STRING | IT_CVAR, NULL, "Renderer", &cv_renderer, 21},
#else
{IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", &cv_renderer, 21},
#endif
@ -1663,8 +1655,11 @@ static menuitem_t OP_ServerOptionsMenu[] =
#ifndef NONET
{IT_HEADER, NULL, "Advanced", NULL, 225},
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 231},
{IT_STRING | IT_CVAR, NULL, "Join delay", &cv_joindelay, 246},
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 251},
{IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 256},
#endif
};
@ -2455,46 +2450,6 @@ static void Newgametype_OnChange(void)
}
}
#ifdef HWRENDER
static void Newrenderer_AREYOUSURE(INT32 c)
{
int n;
switch (c)
{
case 'y':
case KEY_ENTER:
n = cv_newrenderer.value;
newrenderer_set |= n;
CV_SetValue(&cv_renderer, n);
break;
default:
CV_StealthSetValue(&cv_newrenderer, cv_renderer.value);
}
}
static void Newrenderer_OnChange(void)
{
/* Well this works for now because there's only two options. */
int n;
n = cv_newrenderer.value;
newrenderer_set |= cv_renderer.value;
if (( newrenderer_set & n ))
CV_SetValue(&cv_renderer, n);
else
{
M_StartMessage(
"The OpenGL renderer is incomplete.\n"
"Some visuals may fail to appear, or\n"
"appear incorrectly.\n"
"Do you still want to switch to it?\n"
"\n"
"(Press 'y' or 'n')",
Newrenderer_AREYOUSURE, MM_YESNO
);
}
}
#endif/*HWRENDER*/
void Screenshot_option_Onchange(void)
{
OP_ScreenshotOptionsMenu[op_screenshot_folder].status =
@ -3839,7 +3794,7 @@ void M_SetupNextMenu(menu_t *menudef)
{
INT16 i;
#ifdef HAVE_THREADS
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
if (currentMenu == &MP_RoomDef || currentMenu == &MP_ConnectDef)
{
I_lock_mutex(&ms_QueryId_mutex);
@ -3927,7 +3882,7 @@ void M_Ticker(void)
if (currentMenu == &OP_ScreenshotOptionsDef)
M_SetupScreenshotMenu();
#ifdef HAVE_THREADS
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
I_lock_mutex(&ms_ServerList_mutex);
{
if (ms_ServerList)
@ -8017,7 +7972,7 @@ static void M_SecretsMenu(INT32 choice)
skyRoomMenuTranslations[i-1] = (UINT8)ul;
SR_MainMenu[i].text = unlockables[ul].name;
SR_MainMenu[i].alphaKey = (UINT8)unlockables[ul].height;
SR_MainMenu[i].alphaKey = (UINT16)unlockables[ul].height;
if (unlockables[ul].type == SECRET_HEADER)
{
@ -8480,7 +8435,7 @@ static void M_DrawLoadGameData(void)
sprdef = &charbotskin->sprites[SPR2_SIGN];
if (!sprdef->numframes)
goto skipbot;
colormap = R_GetTranslationColormap(savegameinfo[savetodraw].botskin, charbotskin->prefcolor, 0);
colormap = R_GetTranslationColormap(savegameinfo[savetodraw].botskin-1, charbotskin->prefcolor, 0);
sprframe = &sprdef->spriteframes[0];
patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
@ -9002,8 +8957,6 @@ void M_ForceSaveSlotSelected(INT32 sslot)
// ================
// CHARACTER SELECT
// ================
// lactozilla: sometimes the renderer changes and these patches don't exist anymore
static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
{
if (!(description[i].picname[0]))
@ -9246,7 +9199,6 @@ static void M_DrawSetupChoosePlayerMenu(void)
INT32 x, y;
INT32 w = (vid.width/vid.dupx);
// lactozilla: the renderer changed so recache patches
if (needpatchrecache)
M_CacheCharacterSelect();
@ -11191,8 +11143,9 @@ static boolean M_CheckMODVersion(int id)
} else
return true;
}
#endif/*UPDATE_ALERT*/
#ifdef HAVE_THREADS
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
static void
Check_new_version_thread (int *id)
{
@ -11201,7 +11154,9 @@ Check_new_version_thread (int *id)
okay = 0;
#ifdef UPDATE_ALERT
if (M_CheckMODVersion(*id))
#endif
{
I_lock_mutex(&ms_QueryId_mutex);
{
@ -11221,6 +11176,7 @@ Check_new_version_thread (int *id)
GetRoomsList(hosting, *id);
}
}
#ifdef UPDATE_ALERT
else
{
I_lock_mutex(&ms_QueryId_mutex);
@ -11229,6 +11185,7 @@ Check_new_version_thread (int *id)
}
I_unlock_mutex(ms_QueryId_mutex);
}
#endif
if (okay)
{
@ -11245,8 +11202,7 @@ Check_new_version_thread (int *id)
free(id);
}
#endif/*HAVE_THREADS*/
#endif/*UPDATE_ALERT*/
#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/
static void M_ConnectMenu(INT32 choice)
{
@ -11275,7 +11231,7 @@ static void M_ConnectMenuModChecks(INT32 choice)
if (modifiedgame)
{
M_StartMessage(M_GetText("Add-ons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing add-ons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER);
M_StartMessage(M_GetText("You have add-ons loaded.\nYou won't be able to join netgames!\n\nTo play online, restart the game\nand don't load any addons.\nSRB2 will automatically add\neverything you need when you join.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER);
return;
}
@ -11287,7 +11243,7 @@ UINT32 roomIds[NUM_LIST_ROOMS];
static void M_RoomMenu(INT32 choice)
{
INT32 i;
#ifdef HAVE_THREADS
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
int *id;
#endif
@ -11309,9 +11265,14 @@ static void M_RoomMenu(INT32 choice)
MP_RoomDef.prevMenu = currentMenu;
M_SetupNextMenu(&MP_RoomDef);
#ifdef UPDATE_ALERT
#ifdef MASTERSERVER
#ifdef HAVE_THREADS
#ifdef UPDATE_ALERT
m_waiting_mode = M_WAITING_VERSION;
#else/*UPDATE_ALERT*/
m_waiting_mode = M_WAITING_ROOMS;
#endif/*UPDATE_ALERT*/
MP_RoomMenu[0].text = "";
id = malloc(sizeof *id);
@ -11325,17 +11286,19 @@ static void M_RoomMenu(INT32 choice)
I_spawn_thread("check-new-version",
(I_thread_fn)Check_new_version_thread, id);
#else/*HAVE_THREADS*/
#ifdef UPDATE_ALERT
if (M_CheckMODVersion(0))
#endif/*UPDATE_ALERT*/
{
GetRoomsList(currentMenu->prevMenu == &MP_ServerDef, 0);
}
#endif/*HAVE_THREADS*/
#endif/*UPDATE_ALERT*/
#endif/*MASTERSERVER*/
}
static void M_ChooseRoom(INT32 choice)
{
#ifdef HAVE_THREADS
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
I_lock_mutex(&ms_QueryId_mutex);
{
ms_QueryId++;

View File

@ -327,7 +327,7 @@ typedef struct menuitem_s
void *itemaction;
// hotkey in menu or y of the item
UINT8 alphaKey;
UINT16 alphaKey;
} menuitem_t;
extern menuitem_t MP_RoomMenu[];

View File

@ -102,16 +102,16 @@ typedef off_t off64_t;
#endif
static CV_PossibleValue_t screenshot_cons_t[] = {{0, "Default"}, {1, "HOME"}, {2, "SRB2"}, {3, "CUSTOM"}, {0, NULL}};
consvar_t cv_screenshot_option = {"screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_screenshot_folder = {"screenshot_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_screenshot_option = CVAR_INIT ("screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange);
consvar_t cv_screenshot_folder = CVAR_INIT ("screenshot_folder", "", CV_SAVE, NULL, NULL);
consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_screenshot_colorprofile = CVAR_INIT ("screenshot_colorprofile", "Yes", CV_SAVE, CV_YesNo, NULL);
static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}};
consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_moviemode = CVAR_INIT ("moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange);
consvar_t cv_movie_option = {"movie_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Moviemode_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_movie_folder = {"movie_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_movie_option = CVAR_INIT ("movie_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Moviemode_option_Onchange);
consvar_t cv_movie_folder = CVAR_INIT ("movie_folder", "", CV_SAVE, NULL, NULL);
static CV_PossibleValue_t zlib_mem_level_t[] = {
{1, "(Min Memory) 1"},
@ -153,16 +153,16 @@ static CV_PossibleValue_t apng_delay_t[] = {
// zlib memory usage is as follows:
// (1 << (zlib_window_bits+2)) + (1 << (zlib_level+9))
consvar_t cv_zlib_memory = {"png_memory_level", "7", CV_SAVE, zlib_mem_level_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_level = {"png_compress_level", "(Optimal) 6", CV_SAVE, zlib_level_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_strategy = {"png_strategy", "Normal", CV_SAVE, zlib_strategy_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_window_bits = {"png_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_memory = CVAR_INIT ("png_memory_level", "7", CV_SAVE, zlib_mem_level_t, NULL);
consvar_t cv_zlib_level = CVAR_INIT ("png_compress_level", "(Optimal) 6", CV_SAVE, zlib_level_t, NULL);
consvar_t cv_zlib_strategy = CVAR_INIT ("png_strategy", "Normal", CV_SAVE, zlib_strategy_t, NULL);
consvar_t cv_zlib_window_bits = CVAR_INIT ("png_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL);
consvar_t cv_zlib_memorya = {"apng_memory_level", "(Max Memory) 9", CV_SAVE, zlib_mem_level_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_levela = {"apng_compress_level", "4", CV_SAVE, zlib_level_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_strategya = {"apng_strategy", "RLE", CV_SAVE, zlib_strategy_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_window_bitsa = {"apng_window_size", "32k", CV_SAVE, zlib_window_bits_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_apng_delay = {"apng_speed", "1x", CV_SAVE, apng_delay_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_zlib_memorya = CVAR_INIT ("apng_memory_level", "(Max Memory) 9", CV_SAVE, zlib_mem_level_t, NULL);
consvar_t cv_zlib_levela = CVAR_INIT ("apng_compress_level", "4", CV_SAVE, zlib_level_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_apng_delay = CVAR_INIT ("apng_speed", "1x", CV_SAVE, apng_delay_t, NULL);
boolean takescreenshot = false; // Take a screenshot this tic

541
src/m_perfstats.c Normal file
View File

@ -0,0 +1,541 @@
// 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 m_perfstats.c
/// \brief Performance measurement tools.
#include "m_perfstats.h"
#include "v_video.h"
#include "i_video.h"
#include "d_netcmd.h"
#include "r_main.h"
#include "i_system.h"
#include "z_zone.h"
#include "p_local.h"
#ifdef HWRENDER
#include "hardware/hw_main.h"
#endif
int ps_tictime = 0;
int ps_playerthink_time = 0;
int ps_thinkertime = 0;
int ps_thlist_times[NUM_THINKERLISTS];
static const char* thlist_names[] = {
"Polyobjects: %d",
"Main: %d",
"Mobjs: %d",
"Dynamic slopes: %d",
"Precipitation: %d",
NULL
};
static const char* thlist_shortnames[] = {
"plyobjs %d",
"main %d",
"mobjs %d",
"dynslop %d",
"precip %d",
NULL
};
int ps_checkposition_calls = 0;
int ps_lua_thinkframe_time = 0;
int ps_lua_mobjhooks = 0;
// dynamically allocated resizeable array for thinkframe hook stats
ps_hookinfo_t *thinkframe_hooks = NULL;
int thinkframe_hooks_length = 0;
int thinkframe_hooks_capacity = 16;
void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src)
{
if (!thinkframe_hooks)
{
// array needs to be initialized
thinkframe_hooks = Z_Malloc(sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL);
}
if (index >= thinkframe_hooks_capacity)
{
// array needs more space, realloc with double size
thinkframe_hooks_capacity *= 2;
thinkframe_hooks = Z_Realloc(thinkframe_hooks,
sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL);
}
thinkframe_hooks[index].time_taken = time_taken;
memcpy(thinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char));
// since the values are set sequentially from begin to end, the last call should leave
// the correct value to this variable
thinkframe_hooks_length = index + 1;
}
void M_DrawPerfStats(void)
{
char s[100];
int currenttime = I_GetTimeMicros();
int frametime = currenttime - ps_prevframetime;
ps_prevframetime = currenttime;
if (cv_perfstats.value == 1) // rendering
{
if (vid.width < 640 || vid.height < 400) // low resolution
{
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
{
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 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
{
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
return;
if (vid.width < 640 || vid.height < 400) // low resolution
{
// it's not gonna fit very well..
V_DrawThinString(30, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Not available for resolutions below 640x400");
}
else // high resolution
{
int i;
// text writing position
int x = 2;
int y = 4;
UINT32 text_color;
char tempbuffer[LUA_IDSIZE];
char last_mod_name[LUA_IDSIZE];
last_mod_name[0] = '\0';
for (i = 0; i < thinkframe_hooks_length; i++)
{
char* str = thinkframe_hooks[i].short_src;
char* tempstr = tempbuffer;
int len = (int)strlen(str);
char* str_ptr;
if (strcmp(".lua", str + len - 4) == 0)
{
str[len-4] = '\0'; // remove .lua at end
len -= 4;
}
// we locate the wad/pk3 name in the string and compare it to
// what we found on the previous iteration.
// if the name has changed, print it out on the screen
strcpy(tempstr, str);
str_ptr = strrchr(tempstr, '|');
if (str_ptr)
{
*str_ptr = '\0';
str = str_ptr + 1; // this is the name of the hook without the mod file name
str_ptr = strrchr(tempstr, PATHSEP[0]);
if (str_ptr)
tempstr = str_ptr + 1;
// tempstr should now point to the mod name, (wad/pk3) possibly truncated
if (strcmp(tempstr, last_mod_name) != 0)
{
strcpy(last_mod_name, tempstr);
len = (int)strlen(tempstr);
if (len > 25)
tempstr += len - 25;
snprintf(s, sizeof s - 1, "%s", tempstr);
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s);
y += 4; // repeated code!
if (y > 192)
{
y = 4;
x += 106;
if (x > 214)
break;
}
}
text_color = V_YELLOWMAP;
}
else
{
// probably a standalone lua file
// cut off the folder if it's there
str_ptr = strrchr(tempstr, PATHSEP[0]);
if (str_ptr)
str = str_ptr + 1;
text_color = 0; // white
}
len = (int)strlen(str);
if (len > 20)
str += len - 20;
snprintf(s, sizeof s - 1, "%20s: %u", str, thinkframe_hooks[i].time_taken);
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s);
y += 4; // repeated code!
if (y > 192)
{
y = 4;
x += 106;
if (x > 214)
break;
}
}
}
}
}

42
src/m_perfstats.h Normal file
View File

@ -0,0 +1,42 @@
// 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 m_perfstats.h
/// \brief Performance measurement tools.
#ifndef __M_PERFSTATS_H__
#define __M_PERFSTATS_H__
#include "doomdef.h"
#include "lua_script.h"
#include "p_local.h"
extern int ps_tictime;
extern int ps_playerthink_time;
extern int ps_thinkertime;
extern int ps_thlist_times[];
extern int ps_checkposition_calls;
extern int ps_lua_thinkframe_time;
extern int ps_lua_mobjhooks;
typedef struct
{
UINT32 time_taken;
char short_src[LUA_IDSIZE];
} ps_hookinfo_t;
void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src);
void M_DrawPerfStats(void);
#endif

View File

@ -23,6 +23,8 @@
#include "m_menu.h"
#include "z_zone.h"
#ifdef MASTERSERVER
static int MSId;
static int MSRegisteredId = -1;
@ -43,27 +45,30 @@ static I_cond MSCond;
# define Unlock_state()
#endif/*HAVE_THREADS*/
static void Update_parameters (void);
#ifndef NONET
static void Command_Listserv_f(void);
#endif
#endif/*MASTERSERVER*/
static void Update_parameters (void);
static void MasterServer_OnChange(void);
static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
{2, "MIN"},
{60, "MAX"},
{0}
{0,NULL}
};
consvar_t cv_masterserver = {"masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_servername = {"servername", "SRB2Kart server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, NULL, Update_parameters);
consvar_t cv_masterserver_update_rate = {"masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters);
INT16 ms_RoomId = -1;
#ifdef HAVE_THREADS
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
int ms_QueryId;
I_mutex ms_QueryId_mutex;
@ -91,10 +96,14 @@ void AddMServCommands(void)
CV_RegisterVar(&cv_masterserver_debug);
CV_RegisterVar(&cv_masterserver_token);
CV_RegisterVar(&cv_servername);
#ifdef MASTERSERVER
COM_AddCommand("listserv", Command_Listserv_f);
#endif
#endif
}
#ifdef MASTERSERVER
static void WarnGUI (void)
{
#ifdef HAVE_THREADS
@ -395,6 +404,7 @@ Change_masterserver_thread (char *api)
void RegisterServer(void)
{
#ifdef MASTERSERVER
#ifdef HAVE_THREADS
I_spawn_thread(
"register-server",
@ -404,6 +414,7 @@ void RegisterServer(void)
#else
Finish_registration();
#endif
#endif/*MASTERSERVER*/
}
static void UpdateServer(void)
@ -421,6 +432,7 @@ static void UpdateServer(void)
void UnregisterServer(void)
{
#ifdef MASTERSERVER
#ifdef HAVE_THREADS
I_spawn_thread(
"unlist-server",
@ -430,6 +442,7 @@ void UnregisterServer(void)
#else
Finish_unlist();
#endif
#endif/*MASTERSERVER*/
}
static boolean
@ -465,9 +478,33 @@ static inline void SendPingToMasterServer(void)
}
}
void MasterClient_Ticker(void)
{
#ifdef MASTERSERVER
SendPingToMasterServer();
#endif
}
static void
Set_api (const char *api)
{
#ifdef HAVE_THREADS
I_spawn_thread(
"change-masterserver",
(I_thread_fn)Change_masterserver_thread,
strdup(api)
);
#else
HMS_set_api(strdup(api));
#endif
}
#endif/*MASTERSERVER*/
static void
Update_parameters (void)
{
#ifdef MASTERSERVER
int registered;
int delayed;
@ -487,29 +524,12 @@ Update_parameters (void)
if (! delayed && registered)
UpdateServer();
}
}
void MasterClient_Ticker(void)
{
SendPingToMasterServer();
}
static void
Set_api (const char *api)
{
#ifdef HAVE_THREADS
I_spawn_thread(
"change-masterserver",
(I_thread_fn)Change_masterserver_thread,
strdup(api)
);
#else
HMS_set_api(strdup(api));
#endif
#endif/*MASTERSERVER*/
}
static void MasterServer_OnChange(void)
{
#ifdef MASTERSERVER
UnregisterServer();
/*
@ -527,4 +547,5 @@ static void MasterServer_OnChange(void)
if (Online())
RegisterServer();
#endif/*MASTERSERVER*/
}

View File

@ -3040,11 +3040,11 @@ void A_Boss1Laser(mobj_t *actor)
z = actor->z + FixedMul(56*FRACUNIT, actor->scale);
break;
case 2:
var2 = 3; // Fire middle laser
var1 = locvar1; var2 = 3; // Fire middle laser
A_Boss1Laser(actor);
var2 = 0; // Fire left laser
var1 = locvar1; var2 = 0; // Fire left laser
A_Boss1Laser(actor);
var2 = 1; // Fire right laser
var1 = locvar1; var2 = 1; // Fire right laser
A_Boss1Laser(actor);
return;
break;
@ -8840,25 +8840,26 @@ void A_Dye(mobj_t *actor)
INT32 locvar2 = var2;
mobj_t *target = ((locvar1 && actor->target) ? actor->target : actor);
UINT8 color = (UINT8)locvar2;
UINT16 color = (UINT16)locvar2;
if (LUA_CallAction("A_Dye", actor))
return;
if (color >= numskincolors)
return;
if (!color)
target->colorized = false;
else
target->colorized = true;
// What if it's a player?
if (target->player)
{
target->player->powers[pw_dye] = color;
return;
}
target->color = color;
if (!color)
{
target->colorized = false;
target->color = target->player ? target->player->skincolor : SKINCOLOR_NONE;
}
else if (!(target->player))
{
target->colorized = true;
target->color = color;
}
}
// Function: A_MoveRelative

View File

@ -274,6 +274,8 @@ extern tic_t itemrespawntime[ITEMQUESIZE];
extern size_t iquehead, iquetail;
extern consvar_t cv_gravity, cv_movebob;
mobjtype_t P_GetMobjtype(UINT16 mthingtype);
void P_RespawnSpecials(void);
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
@ -426,6 +428,7 @@ void P_Initsecnode(void);
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype, boolean sightcheck);
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
boolean PIT_PushableMoved(mobj_t *thing);
boolean P_DoSpring(mobj_t *spring, mobj_t *object);

View File

@ -33,6 +33,8 @@
#include "lua_hook.h"
#include "m_perfstats.h" // ps_checkposition_calls
fixed_t tmbbox[4];
mobj_t *tmthing;
static INT32 tmflags;
@ -2019,6 +2021,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
subsector_t *newsubsec;
boolean blockval = true;
ps_checkposition_calls++;
I_Assert(thing != NULL);
#ifdef PARANOIA
if (P_MobjWasRemoved(thing))
@ -2661,7 +2665,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
fixed_t tryx = thing->x;
fixed_t tryy = thing->y;
fixed_t radius = thing->radius;
fixed_t thingtop = thing->z + thing->height;
fixed_t thingtop;
fixed_t startingonground = P_IsObjectOnGround(thing);
floatok = false;
@ -2702,6 +2706,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13)
maxstep <<= 1;
// If using type Section1:14, no maxstep.
if (P_PlayerTouchingSectorSpecial(thing->player, 1, 14)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14)
maxstep = 0;
// Don't 'step up' while springing,
// Only step up "if needed".
if (thing->player->panim == PA_SPRING
@ -2721,39 +2730,45 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
floatok = true;
if (thing->eflags & MFE_VERTICALFLIP)
thingtop = thing->z + thing->height;
// Step up
if (thing->z < tmfloorz)
{
if (thing->z < tmfloorz)
if (tmfloorz - thing->z <= maxstep)
{
thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else
{
return false; // mobj must raise itself to fit
}
}
else if (tmceilingz < thingtop)
return false; // mobj must lower itself to fit
// Ramp test
if (maxstep > 0 && !(
thing->player && (
P_PlayerTouchingSectorSpecial(thing->player, 1, 14)
|| GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 14)
)
)
{
if (thingtop - tmceilingz <= maxstep)
{
thing->z = ( thing->ceilingz = tmceilingz ) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else
{
return false; // mobj must lower itself to fit
}
}
else if (maxstep > 0) // Step down
{
// If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS
// step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more.
if (thing->eflags & MFE_VERTICALFLIP)
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
{
if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
{
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
{
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
thing->z = (thing->ceilingz = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep)
{
@ -2761,28 +2776,6 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->floorrover = tmfloorrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
{
thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
}
if (thing->eflags & MFE_VERTICALFLIP)
{
if (thingtop - tmceilingz > maxstep)
{
if (tmfloorthing)
tmhitthing = tmfloorthing;
return false; // too big a step up
}
}
else if (tmfloorz - thing->z > maxstep)
{
if (tmfloorthing)
tmhitthing = tmfloorthing;
return false; // too big a step up
}
if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tmfloorthing)
@ -3351,7 +3344,7 @@ static void PTR_GlideClimbTraverse(line_t *li)
{
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;
topheight = P_GetFFloorTopZAt (rover, slidemo->x, slidemo->y);
@ -4963,7 +4956,7 @@ void P_MapEnd(void)
}
// P_FloorzAtPos
// Returns the floorz of the XYZ position // TODO: Need ceilingpos function too
// Returns the floorz of the XYZ position
// Tails 05-26-2003
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
{
@ -5007,3 +5000,47 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
return floorz;
}
// P_CeilingZAtPos
// Returns the ceilingz of the XYZ position
fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
{
sector_t *sec = R_PointInSubsector(x, y)->sector;
fixed_t ceilingz = P_GetSectorCeilingZAt(sec, x, y);
if (sec->ffloors)
{
ffloor_t *rover;
fixed_t delta1, delta2, thingtop = z + height;
for (rover = sec->ffloors; rover; rover = rover->next)
{
fixed_t topheight, bottomheight;
if (!(rover->flags & FF_EXISTS))
continue;
if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
continue;
topheight = P_GetFFloorTopZAt (rover, x, y);
bottomheight = P_GetFFloorBottomZAt(rover, x, y);
if (rover->flags & FF_QUICKSAND)
{
if (thingtop > bottomheight && topheight > z)
{
if (ceilingz > z)
ceilingz = z;
}
continue;
}
delta1 = z - (bottomheight + ((topheight - bottomheight)/2));
delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2));
if (bottomheight < ceilingz && abs(delta1) > abs(delta2))
ceilingz = bottomheight;
}
}
return ceilingz;
}

View File

@ -18,6 +18,7 @@
#include "p_local.h"
#include "r_main.h"
#include "r_data.h"
#include "r_textures.h"
#include "p_maputl.h"
#include "p_polyobj.h"
#include "p_slopes.h"

View File

@ -36,10 +36,10 @@
#include "m_cond.h"
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = {"movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
#ifdef WALLSPLATS
consvar_t cv_splats = {"splats", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_splats = CVAR_INIT ("splats", "On", CV_SAVE, CV_OnOff, NULL);
#endif
actioncache_t actioncachehead;
@ -4198,7 +4198,7 @@ boolean P_SupermanLook4Players(mobj_t *actor)
for (c = 0; c < MAXPLAYERS; c++)
{
if (playeringame[c])
if (playeringame[c] && !players[c].spectator)
{
if (players[c].pflags & PF_INVIS)
continue; // ignore notarget
@ -11049,10 +11049,10 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
}
static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
consvar_t cv_itemrespawntime = {"respawnitemtime", "30", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_itemrespawn = {"respawnitem", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL);
consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
static CV_PossibleValue_t flagtime_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}};
consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_flagtime = CVAR_INIT ("flagtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL);
void P_SpawnPrecipitation(void)
{
@ -11251,7 +11251,7 @@ void P_PrecipitationEffects(void)
* \param mthingtype Mapthing number in question.
* \return Mobj type; MT_UNKNOWN if nothing found.
*/
static mobjtype_t P_GetMobjtype(UINT16 mthingtype)
mobjtype_t P_GetMobjtype(UINT16 mthingtype)
{
mobjtype_t i;
for (i = 0; i < NUMMOBJTYPES; i++)
@ -11958,9 +11958,6 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
return MT_SCORE1K_BOX; // 1,000
}
if (mariomode && i == MT_ROSY)
return MT_TOAD; // don't remove on penalty of death
return i;
}

View File

@ -977,7 +977,7 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
// Moves a polyobject on the x-y plane.
static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs)
boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs)
{
size_t i;
vertex_t vec;
@ -1163,7 +1163,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
}
// Rotates a polyobject around its start point.
static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs)
boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs)
{
size_t i;
angle_t angle;

View File

@ -336,6 +336,8 @@ typedef struct polyfadedata_s
// Functions
//
boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs);
boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs);
polyobj_t *Polyobj_GetForNum(INT32 id);
void Polyobj_InitLevel(void);
void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y);

View File

@ -22,6 +22,8 @@
#include "p_setup.h"
#include "p_saveg.h"
#include "r_data.h"
#include "r_textures.h"
#include "r_things.h"
#include "r_skins.h"
#include "r_state.h"
#include "w_wad.h"

View File

@ -28,7 +28,8 @@
#include "r_data.h"
#include "r_things.h" // for R_AddSpriteDefs
#include "r_patch.h"
#include "r_textures.h"
#include "r_picformats.h"
#include "r_sky.h"
#include "r_draw.h"
@ -549,6 +550,8 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
lumpnum_t flatnum;
int texturenum;
patch_t *flatpatch;
size_t lumplength;
size_t i;
@ -605,7 +608,9 @@ texturefound:
{
flatfound:
/* This could be a flat, patch, or PNG. */
if (R_CheckIfPatch(flatnum))
flatpatch = W_CacheLumpNum(flatnum, PU_CACHE);
lumplength = W_LumpLength(flatnum);
if (Picture_CheckIfPatch(flatpatch, lumplength))
levelflat->type = LEVELFLAT_PATCH;
else
{
@ -615,12 +620,14 @@ flatfound:
FIXME: Put this elsewhere.
*/
W_ReadLumpHeader(flatnum, buffer, 8, 0);
if (R_IsLumpPNG(buffer, W_LumpLength(flatnum)))
if (Picture_IsLumpPNG(buffer, lumplength))
levelflat->type = LEVELFLAT_PNG;
else
#endif/*NO_PNG_LUMPS*/
levelflat->type = LEVELFLAT_FLAT;/* phew */
}
if (flatpatch)
Z_Free(flatpatch);
levelflat->u.flat. lumpnum = flatnum;
levelflat->u.flat.baselumpnum = LUMPERROR;
@ -4048,23 +4055,23 @@ boolean P_LoadLevel(boolean fromnetsave)
wipegamestate = FORCEWIPEOFF;
wipestyleflags = 0;
// Special stage fade to white
// Special stage & record attack retry fade to white
// This is handled BEFORE sounds are stopped.
if (modeattacking && !demoplayback && (pausedelay == INT32_MIN))
ranspecialwipe = 2;
if (G_GetModeAttackRetryFlag())
{
if (modeattacking && !demoplayback)
{
ranspecialwipe = 2;
wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE);
}
G_ClearModeAttackRetryFlag();
}
else if (rendermode != render_none && G_IsSpecialStage(gamemap))
{
P_RunSpecialStageWipe();
ranspecialwipe = 1;
}
if (G_GetModeAttackRetryFlag())
{
if (modeattacking)
wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE);
G_ClearModeAttackRetryFlag();
}
// Make sure all sounds are stopped before Z_FreeTags.
S_StopSounds();
S_ClearSfx();
@ -4224,9 +4231,9 @@ boolean P_LoadLevel(boolean fromnetsave)
nextmapoverride = 0;
skipstats = 0;
if (!(netgame || multiplayer) && (!modifiedgame || savemoddata))
if (!(netgame || multiplayer || demoplayback) && (!modifiedgame || savemoddata))
mapvisited[gamemap-1] |= MV_VISITED;
else
else if (netgame || multiplayer)
mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently
levelloading = false;

View File

@ -37,9 +37,7 @@ enum
LEVELFLAT_NONE,/* HOM time my friend */
LEVELFLAT_FLAT,
LEVELFLAT_PATCH,
#ifndef NO_PNG_LUMPS
LEVELFLAT_PNG,
#endif
LEVELFLAT_TEXTURE,
};
@ -72,15 +70,17 @@ typedef struct
u;
UINT16 width, height;
fixed_t topoffset, leftoffset;
// for flat animation
INT32 animseq; // start pos. in the anim sequence
INT32 numpics;
INT32 speed;
// for patchflats
UINT8 *flatpatch;
// for textures
UINT8 *picture;
#ifdef HWRENDER
void *mipmap;
#endif
} levelflat_t;
extern size_t numlevelflats;

View File

@ -20,6 +20,7 @@
#include "p_local.h"
#include "p_setup.h" // levelflats for flat animation
#include "r_data.h"
#include "r_textures.h"
#include "m_random.h"
#include "p_mobj.h"
#include "i_system.h"
@ -1786,7 +1787,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
case 336: // object dye - once
{
INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture;
UINT8 color = (actor->player ? actor->player->powers[pw_dye] : actor->color);
UINT16 color = (actor->player ? actor->player->powers[pw_dye] : actor->color);
boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false);
if (invert ^ (triggercolor != color))
@ -4250,7 +4251,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
// Ignore dead players.
// If this strange phenomenon could be potentially used in levels,
// TODO: modify this to accommodate for it.
if (player->playerstate == PST_DEAD)
if (player->playerstate != PST_LIVE)
return;
// Conveyor stuff

View File

@ -21,6 +21,8 @@
#include "m_random.h"
#include "lua_script.h"
#include "lua_hook.h"
#include "m_perfstats.h"
#include "i_system.h" // I_GetTimeMicros
// Object place
#include "m_cheat.h"
@ -321,6 +323,7 @@ static inline void P_RunThinkers(void)
size_t i;
for (i = 0; i < NUM_THINKERLISTS; i++)
{
ps_thlist_times[i] = I_GetTimeMicros();
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
{
#ifdef PARANOIA
@ -328,6 +331,7 @@ static inline void P_RunThinkers(void)
#endif
currentthinker->function.acp1(currentthinker);
}
ps_thlist_times[i] = I_GetTimeMicros() - ps_thlist_times[i];
}
}
@ -641,11 +645,16 @@ void P_Ticker(boolean run)
if (demoplayback)
G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0);
ps_lua_mobjhooks = 0;
ps_checkposition_calls = 0;
LUAh_PreThinkFrame();
ps_playerthink_time = I_GetTimeMicros();
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerThink(&players[i]);
ps_playerthink_time = I_GetTimeMicros() - ps_playerthink_time;
}
// Keep track of how long they've been playing!
@ -660,14 +669,18 @@ void P_Ticker(boolean run)
if (run)
{
ps_thinkertime = I_GetTimeMicros();
P_RunThinkers();
ps_thinkertime = I_GetTimeMicros() - ps_thinkertime;
// Run any "after all the other thinkers" stuff
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]);
ps_lua_thinkframe_time = I_GetTimeMicros();
LUAh_ThinkFrame();
ps_lua_thinkframe_time = I_GetTimeMicros() - ps_lua_thinkframe_time;
}
// Run shield positioning

View File

@ -2564,7 +2564,7 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover)
}
// Strong abilities can break even FF_STRONGBUST.
if (player->charability == CA_GLIDEANDCLIMB)
if (player->charflags & SF_CANBUSTWALLS)
return true;
if (player->pflags & PF_BOUNCING)
@ -2611,10 +2611,10 @@ static void P_CheckBustableBlocks(player_t *player)
if ((netgame || multiplayer) && player->spectator)
return;
oldx = player->mo->x;
oldy = player->mo->y;
if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways
{
P_UnsetThingPosition(player->mo);
@ -2633,7 +2633,7 @@ static void P_CheckBustableBlocks(player_t *player)
if (!node->m_sector->ffloors)
continue;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!P_PlayerCanBust(player, rover))
@ -3214,7 +3214,7 @@ static void P_DoClimbing(player_t *player)
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;
floorclimb = true;
@ -3255,7 +3255,7 @@ static void P_DoClimbing(player_t *player)
// Is there a FOF directly below this one that we can move onto?
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;
if (roverbelow == rover)
@ -3300,7 +3300,7 @@ static void P_DoClimbing(player_t *player)
// Is there a FOF directly below this one that we can move onto?
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;
if (roverbelow == rover)
@ -3357,7 +3357,7 @@ static void P_DoClimbing(player_t *player)
ffloor_t *rover;
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;
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y);
@ -3397,7 +3397,7 @@ static void P_DoClimbing(player_t *player)
ffloor_t *rover;
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;
topheight = P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y);
@ -5006,6 +5006,118 @@ static void P_DoTwinSpin(player_t *player)
P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN);
}
//
// returns true if the player used a shield ability, false otherwise
// passing in the mobjs from P_DoJumpStuff is a bit hackily specific, but I don't care enough to make a more elaborate solution (I think that is more appropriately approached with a more general MT_LOCKON spawning system)
//
static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lockonthok, mobj_t *visual)
{
mobj_t *lockonshield = NULL;
if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN)
&& ((!(player->pflags & PF_THOKKED) || (((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP || (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) && player->secondjump == UINT8_MAX) ))) // thokked is optional if you're bubblewrapped / 3dblasted
{
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)
{
if ((lockonshield = P_LookForEnemies(player, false, false)))
{
if (P_IsLocalPlayer(player)) // Only display it on your own view.
{
boolean dovis = true;
if (lockonshield == lockonthok)
{
if (leveltime & 2)
dovis = false;
else if (visual)
P_RemoveMobj(visual);
}
if (dovis)
{
visual = P_SpawnMobj(lockonshield->x, lockonshield->y, lockonshield->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
P_SetTarget(&visual->target, lockonshield);
P_SetMobjStateNF(visual, visual->info->spawnstate+1);
}
}
}
}
if (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player)) // Spin button effects
{
// Force stop
if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
{
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
S_StartSound(player->mo, sfx_ngskid);
}
else
{
switch (player->powers[pw_shield] & SH_NOSTACK)
{
// Whirlwind jump/Thunder jump
case SH_WHIRLWIND:
case SH_THUNDERCOIN:
P_DoJumpShield(player);
break;
// Armageddon pow
case SH_ARMAGEDDON:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
P_BlackOw(player);
break;
// Attraction blast
case SH_ATTRACT:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
player->homing = 2;
P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonshield));
if (lockonshield)
{
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonshield->x, lockonshield->y);
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k40);
player->homing = 3*TICRATE;
}
else
S_StartSound(player->mo, sfx_s3ka6);
break;
// Elemental stomp/Bubble bounce
case SH_ELEMENTAL:
case SH_BUBBLEWRAP:
{
boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL);
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
if (elem)
{
player->mo->momx = player->mo->momy = 0;
S_StartSound(player->mo, sfx_s3k43);
}
else
{
player->mo->momx -= (player->mo->momx/3);
player->mo->momy -= (player->mo->momy/3);
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k44);
}
player->secondjump = 0;
P_SetObjectMomZ(player->mo, -24*FRACUNIT, false);
break;
}
// Flame burst
case SH_FLAMEAURA:
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));
player->drawangle = player->mo->angle;
S_StartSound(player->mo, sfx_s3k43);
default:
break;
}
}
}
return player->pflags & PF_SHIELDABILITY;
}
return false;
}
//
// P_DoJumpStuff
//
@ -5013,7 +5125,7 @@ static void P_DoTwinSpin(player_t *player)
//
static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
{
mobj_t *lockonthok = NULL, *lockonshield = NULL, *visual = NULL;
mobj_t *lockonthok = NULL, *visual = NULL;
if (player->pflags & PF_JUMPSTASIS)
return;
@ -5040,106 +5152,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
;
else if (player->pflags & (PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player has used an ability previously
;
else if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN)
&& ((!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX)))) // thokked is optional if you're bubblewrapped
{
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)
{
if ((lockonshield = P_LookForEnemies(player, false, false)))
{
if (P_IsLocalPlayer(player)) // Only display it on your own view.
{
boolean dovis = true;
if (lockonshield == lockonthok)
{
if (leveltime & 2)
dovis = false;
else if (visual)
P_RemoveMobj(visual);
}
if (dovis)
{
visual = P_SpawnMobj(lockonshield->x, lockonshield->y, lockonshield->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
P_SetTarget(&visual->target, lockonshield);
P_SetMobjStateNF(visual, visual->info->spawnstate+1);
}
}
}
}
if (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player)) // Spin button effects
{
// Force stop
if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
{
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
S_StartSound(player->mo, sfx_ngskid);
}
else
{
switch (player->powers[pw_shield] & SH_NOSTACK)
{
// Whirlwind jump/Thunder jump
case SH_WHIRLWIND:
case SH_THUNDERCOIN:
P_DoJumpShield(player);
break;
// Armageddon pow
case SH_ARMAGEDDON:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
P_BlackOw(player);
break;
// Attraction blast
case SH_ATTRACT:
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
player->homing = 2;
P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockonshield));
if (lockonshield)
{
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonshield->x, lockonshield->y);
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k40);
player->homing = 3*TICRATE;
}
else
S_StartSound(player->mo, sfx_s3ka6);
break;
// Elemental stomp/Bubble bounce
case SH_ELEMENTAL:
case SH_BUBBLEWRAP:
{
boolean elem = ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL);
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
if (elem)
{
player->mo->momx = player->mo->momy = 0;
S_StartSound(player->mo, sfx_s3k43);
}
else
{
player->mo->momx -= (player->mo->momx/3);
player->mo->momy -= (player->mo->momy/3);
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k44);
}
player->secondjump = 0;
P_SetObjectMomZ(player->mo, -24*FRACUNIT, false);
break;
}
// Flame burst
case SH_FLAMEAURA:
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));
player->drawangle = player->mo->angle;
S_StartSound(player->mo, sfx_s3k43);
default:
break;
}
}
}
}
else if (P_PlayerShieldThink(player, cmd, lockonthok, visual))
;
else if ((cmd->buttons & BT_SPIN))
{
if (!(player->pflags & PF_SPINDOWN) && P_SuperReady(player))
@ -5484,6 +5498,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
{
if (!P_HomingAttack(player->mo, player->mo->tracer))
{
player->pflags &= ~PF_SHIELDABILITY;
player->secondjump = UINT8_MAX;
P_SetObjectMomZ(player->mo, 6*FRACUNIT, false);
if (player->mo->eflags & MFE_UNDERWATER)
player->mo->momz = FixedMul(player->mo->momz, FRACUNIT/3);
@ -9631,45 +9647,45 @@ static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {25, "MAX"}, {0, NULL
static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}};
static CV_PossibleValue_t multiplier_cons_t[] = {{0, "MIN"}, {3*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_cam_dist = {"cam_curdist", "160", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_height = {"cam_curheight", "25", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_turnmultiplier = {"cam_turnmultiplier", "1.0", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_adjust = {"cam_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_dist = {"cam2_curdist", "160", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_height = {"cam2_curheight", "25", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_turnmultiplier = {"cam2_turnmultiplier", "1.0", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_adjust = {"cam2_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT, NULL, NULL);
consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT, NULL, NULL);
consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", 0, CV_OnOff, NULL);
consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL);
consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange);
consvar_t cv_cam_rotspeed = CVAR_INIT ("cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL);
consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "1.0", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL);
consvar_t cv_cam_orbit = CVAR_INIT ("cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT, NULL, NULL);
consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT, NULL, NULL);
consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", 0, CV_OnOff, NULL);
consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL);
consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange);
consvar_t cv_cam2_rotspeed = CVAR_INIT ("cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL);
consvar_t cv_cam2_turnmultiplier = CVAR_INIT ("cam2_turnmultiplier", "1.0", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL);
consvar_t cv_cam2_orbit = CVAR_INIT ("cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_cam2_adjust = CVAR_INIT ("cam2_adjust", "On", CV_SAVE, CV_OnOff, NULL);
// [standard vs simple][p1 or p2]
consvar_t cv_cam_savedist[2][2] = {
{ // standard
{"cam_dist", "160", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist, 0, NULL, NULL, 0, 0, NULL},
{"cam2_dist", "160", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("cam_dist", "160", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist),
CVAR_INIT ("cam2_dist", "160", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist),
},
{ // simple
{"cam_simpledist", "224", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist, 0, NULL, NULL, 0, 0, NULL},
{"cam2_simpledist", "224", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("cam_simpledist", "224", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist),
CVAR_INIT ("cam2_simpledist", "224", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist),
}
};
consvar_t cv_cam_saveheight[2][2] = {
{ // standard
{"cam_height", "25", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist, 0, NULL, NULL, 0, 0, NULL},
{"cam2_height", "25", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("cam_height", "25", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist),
CVAR_INIT ("cam2_height", "25", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist),
},
{ // simple
{"cam_simpleheight", "48", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist, 0, NULL, NULL, 0, 0, NULL},
{"cam2_simpleheight", "48", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist, 0, NULL, NULL, 0, 0, NULL}
CVAR_INIT ("cam_simpleheight", "48", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCamDist),
CVAR_INIT ("cam2_simpleheight", "48", CV_FLOAT|CV_SAVE|CV_CALL, NULL, CV_UpdateCam2Dist),
}
};

View File

@ -804,7 +804,7 @@ static void R_AddPolyObjects(subsector_t *sub)
}
// for render stats
rs_numpolyobjects += numpolys;
ps_numpolyobjects += numpolys;
// sort polyobjects
R_SortPolyObjects(sub);
@ -1244,7 +1244,7 @@ void R_RenderBSPNode(INT32 bspnum)
node_t *bsp;
INT32 side;
rs_numbspcalls++;
ps_numbspcalls++;
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,14 @@
#pragma interface
#endif
// Store lists of lumps for F_START/F_END etc.
typedef struct
{
UINT16 wadfile;
UINT16 firstlump;
size_t numlumps;
} lumplist_t;
// Possible alpha types for a patch.
enum patchalphastyle {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY};
@ -31,97 +39,17 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT
extern INT32 ASTTextureBlendingThreshold[2];
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
// moved here for r_sky.c (texpatch_t is used)
// A single patch from a texture definition,
// basically a rectangular area within
// the texture rectangle.
typedef struct
{
// Block origin (always UL), which has already accounted for the internal origin of the patch.
INT16 originx, originy;
UINT16 wad, lump;
UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
UINT8 alpha; // Translucency value
enum patchalphastyle style;
} texpatch_t;
// texture type
enum
{
TEXTURETYPE_UNKNOWN,
TEXTURETYPE_SINGLEPATCH,
TEXTURETYPE_COMPOSITE,
#ifdef WALLFLATS
TEXTURETYPE_FLAT,
#endif
};
// A maptexturedef_t describes a rectangular texture,
// which is composed of one or more mappatch_t structures
// that arrange graphic patches.
typedef struct
{
// Keep name for switch changing, etc.
char name[8];
UINT8 type; // TEXTURETYPE_
INT16 width, height;
boolean holes;
UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
// All the patches[patchcount] are drawn back to front into the cached texture.
INT16 patchcount;
texpatch_t patches[0];
} texture_t;
typedef struct
{
UINT8 *flat;
INT16 width, height;
} textureflat_t;
// all loaded and prepared textures from the start of the game
extern texture_t **textures;
extern textureflat_t *texflats;
extern INT32 *texturewidth;
extern fixed_t *textureheight; // needed for texture pegging
extern INT16 color8to16[256]; // remap color index to highcolor
extern INT16 *hicolormaps; // remap high colors to high colors..
extern CV_PossibleValue_t Color_cons_t[];
// Load TEXTURES definitions, create lookup tables
void R_LoadTextures(void);
void R_FlushTextureCache(void);
INT32 R_GetTextureNum(INT32 texnum);
void R_CheckTextureCache(INT32 tex);
// Retrieve column data for span blitting.
UINT8 *R_GetColumn(fixed_t tex, INT32 col);
UINT8 *R_GetFlat(lumpnum_t flatnum);
// I/O, setting up the stuff.
void R_InitData(void);
void R_PrecacheLevel(void);
extern size_t flatmemory, spritememory, texturememory;
// Retrieval.
// Floor/ceiling opaque texture tiles,
// lookup by name. For animation?
lumpnum_t R_GetFlatNumForName(const char *name);
// Called by P_Ticker for switches and animations,
// returns the texture number for the texture name.
void R_ClearTextureNumCache(boolean btell);
INT32 R_TextureNumForName(const char *name);
INT32 R_CheckTextureNumForName(const char *name);
// Extra Colormap lumps (C_START/C_END) are not used anywhere
// Uncomment to enable
//#define EXTRACOLORMAPLUMPS
@ -195,6 +123,4 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap);
UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette);
#define NearestColor(r, g, b) NearestPaletteColor(r, g, b, NULL)
extern INT32 numtextures;
#endif

View File

@ -23,6 +23,8 @@ void R_DrawSpan_NPO2_8 (void)
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
fixed_t x, y;
fixed_t fixedwidth, fixedheight;
UINT8 *source;
UINT8 *colormap;
@ -41,19 +43,39 @@ void R_DrawSpan_NPO2_8 (void)
if (dest+8 > deststop)
return;
fixedwidth = ds_flatwidth << FRACBITS;
fixedheight = ds_flatheight << FRACBITS;
// Fix xposition and yposition if they are out of bounds.
if (xposition < 0)
xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
else if (xposition >= fixedwidth)
xposition %= fixedwidth;
if (yposition < 0)
yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
else if (yposition >= fixedheight)
yposition %= fixedheight;
while (count-- && dest <= deststop)
{
fixed_t x = (xposition >> FRACBITS);
fixed_t y = (yposition >> FRACBITS);
// The loops here keep the texture coordinates within the texture.
// They will rarely iterate multiple times, and are cheaper than a modulo operation,
// even if using libdivide.
if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
while (xposition < 0)
xposition += fixedwidth;
else
while (xposition >= fixedwidth)
xposition -= fixedwidth;
if (ystep < 0)
while (yposition < 0)
yposition += fixedheight;
else
while (yposition >= fixedheight)
yposition -= fixedheight;
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
x = (xposition >> FRACBITS);
y = (yposition >> FRACBITS);
*dest++ = colormap[source[((y * ds_flatwidth) + x)]];
xposition += xstep;
@ -668,6 +690,8 @@ void R_DrawSplat_NPO2_8 (void)
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
fixed_t x, y;
fixed_t fixedwidth, fixedheight;
UINT8 *source;
UINT8 *colormap;
@ -684,20 +708,39 @@ void R_DrawSplat_NPO2_8 (void)
colormap = ds_colormap;
dest = ylookup[ds_y] + columnofs[ds_x1];
fixedwidth = ds_flatwidth << FRACBITS;
fixedheight = ds_flatheight << FRACBITS;
// Fix xposition and yposition if they are out of bounds.
if (xposition < 0)
xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
else if (xposition >= fixedwidth)
xposition %= fixedwidth;
if (yposition < 0)
yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
else if (yposition >= fixedheight)
yposition %= fixedheight;
while (count-- && dest <= deststop)
{
fixed_t x = (xposition >> FRACBITS);
fixed_t y = (yposition >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
// The loops here keep the texture coordinates within the texture.
// They will rarely iterate multiple times, and are cheaper than a modulo operation,
// even if using libdivide.
if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
while (xposition < 0)
xposition += fixedwidth;
else
while (xposition >= fixedwidth)
xposition -= fixedwidth;
if (ystep < 0)
while (yposition < 0)
yposition += fixedheight;
else
while (yposition >= fixedheight)
yposition -= fixedheight;
x = (xposition >> FRACBITS);
y = (yposition >> FRACBITS);
val = source[((y * ds_flatwidth) + x)];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
@ -715,6 +758,8 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
fixed_t x, y;
fixed_t fixedwidth, fixedheight;
UINT8 *source;
UINT8 *colormap;
@ -731,20 +776,39 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
colormap = ds_colormap;
dest = ylookup[ds_y] + columnofs[ds_x1];
fixedwidth = ds_flatwidth << FRACBITS;
fixedheight = ds_flatheight << FRACBITS;
// Fix xposition and yposition if they are out of bounds.
if (xposition < 0)
xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
else if (xposition >= fixedwidth)
xposition %= fixedwidth;
if (yposition < 0)
yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
else if (yposition >= fixedheight)
yposition %= fixedheight;
while (count-- && dest <= deststop)
{
fixed_t x = (xposition >> FRACBITS);
fixed_t y = (yposition >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
// The loops here keep the texture coordinates within the texture.
// They will rarely iterate multiple times, and are cheaper than a modulo operation,
// even if using libdivide.
if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
while (xposition < 0)
xposition += fixedwidth;
else
while (xposition >= fixedwidth)
xposition -= fixedwidth;
if (ystep < 0)
while (yposition < 0)
yposition += fixedheight;
else
while (yposition >= fixedheight)
yposition -= fixedheight;
x = (xposition >> FRACBITS);
y = (yposition >> FRACBITS);
val = source[((y * ds_flatwidth) + x)];
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
@ -762,6 +826,8 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
fixed_t x, y;
fixed_t fixedwidth, fixedheight;
UINT8 *source;
UINT8 *colormap;
@ -778,20 +844,39 @@ void R_DrawTranslucentSpan_NPO2_8 (void)
colormap = ds_colormap;
dest = ylookup[ds_y] + columnofs[ds_x1];
fixedwidth = ds_flatwidth << FRACBITS;
fixedheight = ds_flatheight << FRACBITS;
// Fix xposition and yposition if they are out of bounds.
if (xposition < 0)
xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
else if (xposition >= fixedwidth)
xposition %= fixedwidth;
if (yposition < 0)
yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
else if (yposition >= fixedheight)
yposition %= fixedheight;
while (count-- && dest <= deststop)
{
fixed_t x = (xposition >> FRACBITS);
fixed_t y = (yposition >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
// The loops here keep the texture coordinates within the texture.
// They will rarely iterate multiple times, and are cheaper than a modulo operation,
// even if using libdivide.
if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
while (xposition < 0)
xposition += fixedwidth;
else
while (xposition >= fixedwidth)
xposition -= fixedwidth;
if (ystep < 0)
while (yposition < 0)
yposition += fixedheight;
else
while (yposition >= fixedheight)
yposition -= fixedheight;
x = (xposition >> FRACBITS);
y = (yposition >> FRACBITS);
val = ((y * ds_flatwidth) + x);
*dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest);
dest++;
@ -806,6 +891,8 @@ void R_DrawTranslucentWaterSpan_NPO2_8(void)
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
fixed_t x, y;
fixed_t fixedwidth, fixedheight;
UINT8 *source;
UINT8 *colormap;
@ -823,20 +910,39 @@ void R_DrawTranslucentWaterSpan_NPO2_8(void)
dest = ylookup[ds_y] + columnofs[ds_x1];
dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1;
fixedwidth = ds_flatwidth << FRACBITS;
fixedheight = ds_flatheight << FRACBITS;
// Fix xposition and yposition if they are out of bounds.
if (xposition < 0)
xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth);
else if (xposition >= fixedwidth)
xposition %= fixedwidth;
if (yposition < 0)
yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight);
else if (yposition >= fixedheight)
yposition %= fixedheight;
while (count-- && dest <= deststop)
{
fixed_t x = (xposition >> FRACBITS);
fixed_t y = (yposition >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
// The loops here keep the texture coordinates within the texture.
// They will rarely iterate multiple times, and are cheaper than a modulo operation,
// even if using libdivide.
if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop
while (xposition < 0)
xposition += fixedwidth;
else
while (xposition >= fixedwidth)
xposition -= fixedwidth;
if (ystep < 0)
while (yposition < 0)
yposition += fixedheight;
else
while (yposition >= fixedheight)
yposition -= fixedheight;
x = (xposition >> FRACBITS);
y = (yposition >> FRACBITS);
*dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)];
xposition += xstep;
yposition += ystep;

View File

@ -31,6 +31,7 @@
#include "r_plane.h"
#include "r_sky.h"
#include "r_data.h"
#include "r_textures.h"
#include "r_things.h"
#include "r_draw.h"

View File

@ -100,20 +100,22 @@ lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
extracolormap_t *extra_colormaps = NULL;
// Render stats
int rs_prevframetime = 0;
int rs_rendercalltime = 0;
int rs_swaptime = 0;
int ps_prevframetime = 0;
int ps_rendercalltime = 0;
int ps_uitime = 0;
int ps_swaptime = 0;
int rs_bsptime = 0;
int ps_bsptime = 0;
int rs_sw_portaltime = 0;
int rs_sw_planetime = 0;
int rs_sw_maskedtime = 0;
int ps_sw_spritecliptime = 0;
int ps_sw_portaltime = 0;
int ps_sw_planetime = 0;
int ps_sw_maskedtime = 0;
int rs_numbspcalls = 0;
int rs_numsprites = 0;
int rs_numdrawnodes = 0;
int rs_numpolyobjects = 0;
int ps_numbspcalls = 0;
int ps_numsprites = 0;
int ps_numdrawnodes = 0;
int ps_numpolyobjects = 0;
static CV_PossibleValue_t drawdist_cons_t[] = {
{256, "256"}, {512, "512"}, {768, "768"},
@ -141,31 +143,32 @@ static void FlipCam2_OnChange(void);
void SendWeaponPref(void);
void SendWeaponPref2(void);
consvar_t cv_tailspickup = {"tailspickup", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam = {"chasecam", "On", CV_CALL, CV_OnOff, ChaseCam_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam2 = {"chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_flipcam = {"flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_tailspickup = CVAR_INIT ("tailspickup", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_chasecam = CVAR_INIT ("chasecam", "On", CV_CALL, CV_OnOff, ChaseCam_OnChange);
consvar_t cv_chasecam2 = CVAR_INIT ("chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChange);
consvar_t cv_flipcam = CVAR_INIT ("flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange);
consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange);
consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_ffloorclip = CVAR_INIT ("ffloorclip", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize);
consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL);
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
//consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucency = CVAR_INIT ("translucency", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_drawdist = CVAR_INIT ("drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL);
consvar_t cv_drawdist_nights = CVAR_INIT ("drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL);
consvar_t cv_drawdist_precip = CVAR_INIT ("drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL);
//consvar_t cv_precipdensity = CVAR_INIT ("precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL);
consvar_t cv_fov = CVAR_INIT ("fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange);
// Okay, whoever said homremoval causes a performance hit should be shot.
consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_homremoval = CVAR_INIT ("homremoval", "No", CV_SAVE, homremoval_cons_t, NULL);
consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL);
consvar_t cv_renderstats = {"renderstats", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_renderstats = CVAR_INIT ("renderstats", "Off", 0, CV_OnOff, NULL);
void SplitScreen_OnChange(void)
{
@ -1074,15 +1077,22 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y)
// recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight).
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
static void R_SetupFreelook(void)
static void R_SetupFreelook(player_t *player, boolean skybox)
{
INT32 dy = 0;
#ifndef HWRENDER
(void)player;
(void)skybox;
#endif
// clip it in the case we are looking a hardware 90 degrees full aiming
// (lmps, network and use F12...)
if (rendermode == render_soft
#ifdef HWRENDER
|| cv_glshearing.value
|| (rendermode == render_opengl
&& (cv_glshearing.value == 1
|| (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))))
#endif
)
{
@ -1203,7 +1213,7 @@ void R_SetupFrame(player_t *player)
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
R_SetupFreelook();
R_SetupFreelook(player, false);
}
void R_SkyboxFrame(player_t *player)
@ -1340,7 +1350,7 @@ void R_SkyboxFrame(player_t *player)
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
R_SetupFreelook();
R_SetupFreelook(player, true);
}
boolean R_ViewpointHasChasecam(player_t *player)
@ -1480,11 +1490,11 @@ void R_RenderPlayerView(player_t *player)
mytotal = 0;
ProfZeroTimer();
#endif
rs_numbspcalls = rs_numpolyobjects = rs_numdrawnodes = 0;
rs_bsptime = I_GetTimeMicros();
ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0;
ps_bsptime = I_GetTimeMicros();
R_RenderBSPNode((INT32)numnodes - 1);
rs_bsptime = I_GetTimeMicros() - rs_bsptime;
rs_numsprites = visspritecount;
ps_bsptime = I_GetTimeMicros() - ps_bsptime;
ps_numsprites = visspritecount;
#ifdef TIMING
RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add
@ -1494,7 +1504,9 @@ void R_RenderPlayerView(player_t *player)
//profile stuff ---------------------------------------------------------
Mask_Post(&masks[nummasks - 1]);
ps_sw_spritecliptime = I_GetTimeMicros();
R_ClipSprites(drawsegs, NULL);
ps_sw_spritecliptime = I_GetTimeMicros() - ps_sw_spritecliptime;
// Add skybox portals caused by sky visplanes.
@ -1502,7 +1514,7 @@ void R_RenderPlayerView(player_t *player)
Portal_AddSkyboxPortals();
// Portal rendering. Hijacks the BSP traversal.
rs_sw_portaltime = I_GetTimeMicros();
ps_sw_portaltime = I_GetTimeMicros();
if (portal_base)
{
portal_t *portal;
@ -1542,25 +1554,24 @@ void R_RenderPlayerView(player_t *player)
Portal_Remove(portal);
}
}
rs_sw_portaltime = I_GetTimeMicros() - rs_sw_portaltime;
ps_sw_portaltime = I_GetTimeMicros() - ps_sw_portaltime;
rs_sw_planetime = I_GetTimeMicros();
ps_sw_planetime = I_GetTimeMicros();
R_DrawPlanes();
#ifdef FLOORSPLATS
R_DrawVisibleFloorSplats();
#endif
rs_sw_planetime = I_GetTimeMicros() - rs_sw_planetime;
ps_sw_planetime = I_GetTimeMicros() - ps_sw_planetime;
// draw mid texture and sprite
// And now 3D floors/sides!
rs_sw_maskedtime = I_GetTimeMicros();
ps_sw_maskedtime = I_GetTimeMicros();
R_DrawMasked(masks, nummasks);
rs_sw_maskedtime = I_GetTimeMicros() - rs_sw_maskedtime;
ps_sw_maskedtime = I_GetTimeMicros() - ps_sw_maskedtime;
free(masks);
}
// Lactozilla: Renderer switching
#ifdef HWRENDER
void R_InitHardwareMode(void)
{
@ -1574,7 +1585,6 @@ void R_InitHardwareMode(void)
void R_ReloadHUDGraphics(void)
{
CONS_Debug(DBG_RENDER, "R_ReloadHUDGraphics()...\n");
ST_LoadGraphics();
HU_LoadGraphics();
ST_ReloadSkinFaceGraphics();
@ -1608,6 +1618,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_shadow);
CV_RegisterVar(&cv_skybox);
CV_RegisterVar(&cv_ffloorclip);
CV_RegisterVar(&cv_cam_dist);
CV_RegisterVar(&cv_cam_still);

View File

@ -16,6 +16,7 @@
#include "d_player.h"
#include "r_data.h"
#include "r_textures.h"
//
// POV related.
@ -77,22 +78,22 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
// Render stats
extern consvar_t cv_renderstats;
extern int ps_prevframetime;// time when previous frame was rendered
extern int ps_rendercalltime;
extern int ps_uitime;
extern int ps_swaptime;
extern int rs_prevframetime;// time when previous frame was rendered
extern int rs_rendercalltime;
extern int rs_swaptime;
extern int ps_bsptime;
extern int rs_bsptime;
extern int ps_sw_spritecliptime;
extern int ps_sw_portaltime;
extern int ps_sw_planetime;
extern int ps_sw_maskedtime;
extern int rs_sw_portaltime;
extern int rs_sw_planetime;
extern int rs_sw_maskedtime;
extern int rs_numbspcalls;
extern int rs_numsprites;
extern int rs_numdrawnodes;
extern int rs_numpolyobjects;
extern int ps_numbspcalls;
extern int ps_numsprites;
extern int ps_numdrawnodes;
extern int ps_numpolyobjects;
//
// REFRESH - the actual rendering functions.
@ -104,6 +105,7 @@ extern consvar_t cv_chasecam, cv_chasecam2;
extern consvar_t cv_flipcam, cv_flipcam2;
extern consvar_t cv_shadow;
extern consvar_t cv_ffloorclip;
extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
extern consvar_t cv_fov;

View File

@ -1,74 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos.
// Copyright (C) 2019-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 r_patch.h
/// \brief Patch generation.
#ifndef __R_PATCH__
#define __R_PATCH__
#include "r_defs.h"
#include "doomdef.h"
// Structs
typedef enum
{
ROTAXIS_X, // Roll (the default)
ROTAXIS_Y, // Pitch
ROTAXIS_Z // Yaw
} rotaxis_t;
typedef struct
{
INT32 x, y;
rotaxis_t rotaxis;
} spriteframepivot_t;
typedef struct
{
spriteframepivot_t pivot[64];
boolean available;
} spriteinfo_t;
// Conversions between patches / flats / textures...
boolean R_CheckIfPatch(lumpnum_t lump);
void R_TextureToFlat(size_t tex, UINT8 *flat);
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip);
patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency);
patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize);
// Portable Network Graphics
boolean R_IsLumpPNG(const UINT8 *d, size_t s);
#define W_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic
#ifndef NO_PNG_LUMPS
UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size);
patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize);
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size);
#endif
// SpriteInfo
extern spriteinfo_t spriteinfo[NUMSPRITES];
void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps);
void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum);
// Sprite rotation
#ifdef ROTSPRITE
INT32 R_GetRollAngle(angle_t rollangle);
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip);
void R_FreeSingleRotSprite(spritedef_t *spritedef);
void R_FreeSkinRotSprite(size_t skinnum);
extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
void R_FreeAllRotSprite(void);
#endif
#endif // __R_PATCH__

File diff suppressed because it is too large Load Diff

134
src/r_picformats.h Normal file
View File

@ -0,0 +1,134 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos.
// Copyright (C) 2019-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 r_picformats.h
/// \brief Patch generation.
#ifndef __R_PICFORMATS__
#define __R_PICFORMATS__
#include "r_defs.h"
#include "doomdef.h"
typedef enum
{
PICFMT_NONE = 0,
// Doom formats
PICFMT_PATCH,
PICFMT_FLAT,
// PNG
PICFMT_PNG,
// 16bpp
PICFMT_PATCH16,
PICFMT_FLAT16,
// 32bpp
PICFMT_PATCH32,
PICFMT_FLAT32
} pictureformat_t;
typedef enum
{
PICFLAGS_XFLIP = 1,
PICFLAGS_YFLIP = 1<<1
} pictureflags_t;
enum
{
PICDEPTH_NONE = 0,
PICDEPTH_8BPP = 8,
PICDEPTH_16BPP = 16,
PICDEPTH_32BPP = 32
};
void *Picture_Convert(
pictureformat_t informat, void *picture, pictureformat_t outformat,
size_t insize, size_t *outsize,
INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset,
pictureflags_t flags);
void *Picture_PatchConvert(
pictureformat_t informat, void *picture, pictureformat_t outformat,
size_t insize, size_t *outsize,
INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset,
pictureflags_t flags);
void *Picture_FlatConvert(
pictureformat_t informat, void *picture, pictureformat_t outformat,
size_t insize, size_t *outsize,
INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset,
pictureflags_t flags);
void *Picture_GetPatchPixel(
patch_t *patch, pictureformat_t informat,
INT32 x, INT32 y,
pictureflags_t flags);
void *Picture_TextureToFlat(size_t trickytex);
INT32 Picture_FormatBPP(pictureformat_t format);
boolean Picture_IsPatchFormat(pictureformat_t format);
boolean Picture_IsFlatFormat(pictureformat_t format);
boolean Picture_CheckIfPatch(patch_t *patch, size_t size);
// Structs
typedef enum
{
ROTAXIS_X, // Roll (the default)
ROTAXIS_Y, // Pitch
ROTAXIS_Z // Yaw
} rotaxis_t;
typedef struct
{
INT32 x, y;
rotaxis_t rotaxis;
} spriteframepivot_t;
typedef struct
{
spriteframepivot_t pivot[64];
boolean available;
} spriteinfo_t;
// Portable Network Graphics
boolean Picture_IsLumpPNG(const UINT8 *d, size_t s);
#define Picture_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic
#ifndef NO_PNG_LUMPS
void *Picture_PNGConvert(
const UINT8 *png, pictureformat_t outformat,
INT32 *w, INT32 *h,
INT16 *topoffset, INT16 *leftoffset,
size_t insize, size_t *outsize,
pictureflags_t flags);
boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size);
#endif
#define PICTURE_PNG_USELOOKUP
// SpriteInfo
extern spriteinfo_t spriteinfo[NUMSPRITES];
void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps);
void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum);
// Sprite rotation
#ifdef ROTSPRITE
INT32 R_GetRollAngle(angle_t rollangle);
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip);
void R_FreeSingleRotSprite(spritedef_t *spritedef);
void R_FreeSkinRotSprite(size_t skinnum);
extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
void R_FreeAllRotSprite(void);
#endif
#endif // __R_PATCH__

View File

@ -19,6 +19,7 @@
#include "p_setup.h" // levelflats
#include "p_slopes.h"
#include "r_data.h"
#include "r_textures.h"
#include "r_local.h"
#include "r_state.h"
#include "r_splats.h" // faB(21jan):testing
@ -59,7 +60,7 @@ INT32 numffloors;
//SoM: 3/23/2000: Boom visplane hashing routine.
#define visplane_hash(picnum,lightlevel,height) \
((unsigned)((picnum)*3+(lightlevel)+(height)*7) & (MAXVISPLANES-1))
((unsigned)((picnum)*3+(lightlevel)+(height)*7) & VISPLANEHASHMASK)
//SoM: 3/23/2000: Use boom opening limit removal
size_t maxopenings;
@ -379,28 +380,30 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
lightlevel = 0;
}
// New visplane algorithm uses hash table
hash = visplane_hash(picnum, lightlevel, height);
for (check = visplanes[hash]; check; check = check->next)
if (!pfloor)
{
if (check->polyobj && pfloor)
continue;
if (polyobj != check->polyobj)
continue;
if (height == check->height && picnum == check->picnum
&& lightlevel == check->lightlevel
&& xoff == check->xoffs && yoff == check->yoffs
&& planecolormap == check->extra_colormap
&& !pfloor && !check->ffloor
&& check->viewx == viewx && check->viewy == viewy && check->viewz == viewz
&& check->viewangle == viewangle
&& check->plangle == plangle
&& check->slope == slope)
hash = visplane_hash(picnum, lightlevel, height);
for (check = visplanes[hash]; check; check = check->next)
{
return check;
if (polyobj != check->polyobj)
continue;
if (height == check->height && picnum == check->picnum
&& lightlevel == check->lightlevel
&& xoff == check->xoffs && yoff == check->yoffs
&& planecolormap == check->extra_colormap
&& check->viewx == viewx && check->viewy == viewy && check->viewz == viewz
&& check->viewangle == viewangle
&& check->plangle == plangle
&& check->slope == slope)
{
return check;
}
}
}
else
{
hash = MAXVISPLANES - 1;
}
check = new_visplane(hash);
@ -470,9 +473,17 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
}
else /* Cannot use existing plane; create a new one */
{
unsigned hash =
visplane_hash(pl->picnum, pl->lightlevel, pl->height);
visplane_t *new_pl = new_visplane(hash);
visplane_t *new_pl;
if (pl->ffloor)
{
new_pl = new_visplane(MAXVISPLANES - 1);
}
else
{
unsigned hash =
visplane_hash(pl->picnum, pl->lightlevel, pl->height);
new_pl = new_visplane(hash);
}
new_pl->height = pl->height;
new_pl->picnum = pl->picnum;
@ -644,188 +655,6 @@ static void R_DrawSkyPlane(visplane_t *pl)
}
}
//
// R_CheckPowersOfTwo
//
// Self-explanatory?
//
boolean R_CheckPowersOfTwo(void)
{
boolean wpow2 = (!(ds_flatwidth & (ds_flatwidth - 1)));
boolean hpow2 = (!(ds_flatheight & (ds_flatheight - 1)));
// Initially, the flat isn't powers-of-two-sized.
ds_powersoftwo = false;
// But if the width and height are powers of two,
// and are EQUAL, then it's okay :]
if ((ds_flatwidth == ds_flatheight) && (wpow2 && hpow2))
ds_powersoftwo = true;
// Just return ds_powersoftwo.
return ds_powersoftwo;
}
//
// R_CheckFlatLength
//
// Determine the flat's dimensions from the lump length.
//
void R_CheckFlatLength(size_t size)
{
switch (size)
{
case 4194304: // 2048x2048 lump
nflatmask = 0x3FF800;
nflatxshift = 21;
nflatyshift = 10;
nflatshiftup = 5;
ds_flatwidth = ds_flatheight = 2048;
break;
case 1048576: // 1024x1024 lump
nflatmask = 0xFFC00;
nflatxshift = 22;
nflatyshift = 12;
nflatshiftup = 6;
ds_flatwidth = ds_flatheight = 1024;
break;
case 262144:// 512x512 lump
nflatmask = 0x3FE00;
nflatxshift = 23;
nflatyshift = 14;
nflatshiftup = 7;
ds_flatwidth = ds_flatheight = 512;
break;
case 65536: // 256x256 lump
nflatmask = 0xFF00;
nflatxshift = 24;
nflatyshift = 16;
nflatshiftup = 8;
ds_flatwidth = ds_flatheight = 256;
break;
case 16384: // 128x128 lump
nflatmask = 0x3F80;
nflatxshift = 25;
nflatyshift = 18;
nflatshiftup = 9;
ds_flatwidth = ds_flatheight = 128;
break;
case 1024: // 32x32 lump
nflatmask = 0x3E0;
nflatxshift = 27;
nflatyshift = 22;
nflatshiftup = 11;
ds_flatwidth = ds_flatheight = 32;
break;
default: // 64x64 lump
nflatmask = 0xFC0;
nflatxshift = 26;
nflatyshift = 20;
nflatshiftup = 10;
ds_flatwidth = ds_flatheight = 64;
break;
}
}
//
// R_GenerateFlat
//
// Generate a flat from specified width and height.
//
static UINT8 *R_GenerateFlat(UINT16 width, UINT16 height)
{
UINT8 *flat = Z_Malloc(width * height, PU_LEVEL, NULL);
memset(flat, TRANSPARENTPIXEL, width * height);
return flat;
}
//
// R_GetTextureFlat
//
// Convert a texture or patch to a flat.
//
static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
{
UINT8 *flat;
textureflat_t *texflat = &texflats[levelflat->u.texture.num];
patch_t *patch = NULL;
boolean texturechanged = (leveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false);
(void)ispng;
// Check if the texture changed.
if (leveltexture && (!texturechanged))
{
if (texflat != NULL && texflat->flat)
{
flat = texflat->flat;
ds_flatwidth = texflat->width;
ds_flatheight = texflat->height;
texturechanged = false;
}
else
texturechanged = true;
}
// If the texture changed, or the patch doesn't exist, convert either of them to a flat.
if (levelflat->flatpatch == NULL || texturechanged)
{
// Level texture
if (leveltexture)
{
texture_t *texture = textures[levelflat->u.texture.num];
texflat->width = ds_flatwidth = texture->width;
texflat->height = ds_flatheight = texture->height;
texflat->flat = R_GenerateFlat(ds_flatwidth, ds_flatheight);
R_TextureToFlat(levelflat->u.texture.num, texflat->flat);
flat = texflat->flat;
levelflat->flatpatch = flat;
levelflat->width = ds_flatwidth;
levelflat->height = ds_flatheight;
}
// Patch (never happens yet)
else
{
patch = (patch_t *)ds_source;
#ifndef NO_PNG_LUMPS
if (ispng)
{
levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->u.flat.lumpnum));
levelflat->topoffset = levelflat->leftoffset = 0;
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
}
else
#endif
{
levelflat->width = ds_flatwidth = SHORT(patch->width);
levelflat->height = ds_flatheight = SHORT(patch->height);
levelflat->topoffset = patch->topoffset * FRACUNIT;
levelflat->leftoffset = patch->leftoffset * FRACUNIT;
levelflat->flatpatch = R_GenerateFlat(ds_flatwidth, ds_flatheight);
R_PatchToFlat(patch, levelflat->flatpatch);
}
flat = levelflat->flatpatch;
}
}
else
{
flat = levelflat->flatpatch;
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
}
xoffs += levelflat->leftoffset;
yoffs += levelflat->topoffset;
levelflat->u.texture.lastnum = levelflat->u.texture.num;
return flat;
}
static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge)
{
// Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
@ -919,12 +748,11 @@ d.z = (v1.x * v2.y) - (v1.y * v2.x)
void R_DrawSinglePlane(visplane_t *pl)
{
UINT8 *flat;
levelflat_t *levelflat;
INT32 light = 0;
INT32 x;
INT32 stop, angle;
ffloor_t *rover;
levelflat_t *levelflat;
int type;
int spanfunctype = BASEDRAWFUNC;
@ -1077,30 +905,15 @@ void R_DrawSinglePlane(visplane_t *pl)
case LEVELFLAT_NONE:
return;
case LEVELFLAT_FLAT:
ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE);
ds_source = (UINT8 *)R_GetFlat(levelflat->u.flat.lumpnum);
R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum));
// Raw flats always have dimensions that are powers-of-two numbers.
ds_powersoftwo = true;
break;
default:
switch (type)
{
case LEVELFLAT_TEXTURE:
/* Textures get cached differently and don't need ds_source */
ds_source = R_GetTextureFlat(levelflat, true, false);
break;
default:
ds_source = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_STATIC);
flat = R_GetTextureFlat(levelflat, false,
#ifndef NO_PNG_LUMPS
( type == LEVELFLAT_PNG )
#else
false
#endif
);
Z_ChangeTag(ds_source, PU_CACHE);
ds_source = flat;
}
ds_source = (UINT8 *)R_GetLevelFlat(levelflat);
if (!ds_source)
return;
// Check if this texture or patch has power-of-two dimensions.
if (R_CheckPowersOfTwo())
R_CheckFlatLength(ds_flatwidth * ds_flatheight);

View File

@ -16,9 +16,13 @@
#include "screen.h" // needs MAXVIDWIDTH/MAXVIDHEIGHT
#include "r_data.h"
#include "r_textures.h"
#include "p_polyobj.h"
#define MAXVISPLANES 512
#define VISPLANEHASHBITS 9
#define VISPLANEHASHMASK ((1<<VISPLANEHASHBITS)-1)
// the last visplane list is outside of the hash table and is used for fof planes
#define MAXVISPLANES ((1<<VISPLANEHASHBITS)+1)
//
// Now what is a visplane, anyway?

View File

@ -15,6 +15,7 @@
#define __R_PORTAL__
#include "r_data.h"
#include "r_textures.h"
#include "r_plane.h" // visplanes
/** Portal structure for the software renderer.

View File

@ -56,6 +56,15 @@ static INT32 worldtop, worldbottom, worldhigh, worldlow;
static INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope
static fixed_t rw_toptextureslide, rw_midtextureslide, rw_bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes
static fixed_t rw_midtextureback, rw_midtexturebackslide; // Values for masked midtexture height calculation
// Lactozilla: 3D floor clipping
static boolean rw_floormarked = false;
static boolean rw_ceilingmarked = false;
static INT32 *rw_silhouette = NULL;
static fixed_t *rw_tsilheight = NULL;
static fixed_t *rw_bsilheight = NULL;
static fixed_t pixhigh, pixlow, pixhighstep, pixlowstep;
static fixed_t topfrac, topstep;
static fixed_t bottomfrac, bottomstep;
@ -687,6 +696,19 @@ static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
} while (sprtopscreen < sprbotscreen);
}
// Returns true if a fake floor is translucent.
static boolean R_IsFFloorTranslucent(visffloor_t *pfloor)
{
if (pfloor->polyobj)
return (pfloor->polyobj->translucency > 0);
// Polyobjects have no ffloors, and they're handled in the conditional above.
if (pfloor->ffloor != NULL)
return (pfloor->ffloor->flags & FF_TRANSLUCENT);
return false;
}
//
// R_RenderThickSideRange
// Renders all the thick sides in the given range.
@ -1189,7 +1211,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// R_ExpandPlaneY
//
// A simple function to modify a vsplane's top and bottom for a particular column
// A simple function to modify a visplane's top and bottom for a particular column
// Sort of like R_ExpandPlane in r_plane.c, except this is vertical expansion
static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bottom)
{
@ -1199,6 +1221,14 @@ static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bott
if (pl->bottom[x] < bottom) pl->bottom[x] = bottom;
}
// R_FFloorCanClip
//
// Returns true if a fake floor can clip a column away.
static boolean R_FFloorCanClip(visffloor_t *pfloor)
{
return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj);
}
//
// R_RenderSegLoop
// Draws zero, one, or two textures (and possibly a masked
@ -1280,8 +1310,13 @@ static void R_RenderSegLoop (void)
R_ExpandPlaneY(floorplane, rw_x, top, bottom);
}
rw_floormarked = false;
rw_ceilingmarked = false;
if (numffloors)
{
INT16 fftop, ffbottom;
firstseg->frontscale[rw_x] = frontscale[rw_x];
top = ceilingclip[rw_x]+1; // PRBoom
bottom = floorclip[rw_x]-1; // PRBoom
@ -1312,8 +1347,30 @@ static void R_RenderSegLoop (void)
{
if (top_w <= bottom_w)
{
ffloor[i].plane->top[rw_x] = (INT16)top_w;
ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
fftop = (INT16)top_w;
ffbottom = (INT16)bottom_w;
ffloor[i].plane->top[rw_x] = fftop;
ffloor[i].plane->bottom[rw_x] = ffbottom;
// Lactozilla: Cull part of the column by the 3D floor if it can't be seen
// "bottom" is the top pixel of the floor column
if (ffbottom >= bottom-1 && R_FFloorCanClip(&ffloor[i]))
{
rw_floormarked = true;
floorclip[rw_x] = fftop;
if (yh > fftop)
yh = fftop;
if (markfloor && floorplane)
floorplane->top[rw_x] = bottom;
if (rw_silhouette)
{
(*rw_silhouette) |= SIL_BOTTOM;
(*rw_bsilheight) = INT32_MAX;
}
}
}
}
}
@ -1338,8 +1395,30 @@ static void R_RenderSegLoop (void)
{
if (top_w <= bottom_w)
{
ffloor[i].plane->top[rw_x] = (INT16)top_w;
ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
fftop = (INT16)top_w;
ffbottom = (INT16)bottom_w;
ffloor[i].plane->top[rw_x] = fftop;
ffloor[i].plane->bottom[rw_x] = ffbottom;
// Lactozilla: Cull part of the column by the 3D floor if it can't be seen
// "top" is the height of the ceiling column
if (fftop <= top+1 && R_FFloorCanClip(&ffloor[i]))
{
rw_ceilingmarked = true;
ceilingclip[rw_x] = ffbottom;
if (yl < ffbottom)
yl = ffbottom;
if (markceiling && ceilingplane)
ceilingplane->bottom[rw_x] = top;
if (rw_silhouette)
{
(*rw_silhouette) |= SIL_TOP;
(*rw_tsilheight) = INT32_MIN;
}
}
}
}
}
@ -1445,20 +1524,25 @@ static void R_RenderSegLoop (void)
// dont draw anything more for this column, since
// a midtexture blocks the view
ceilingclip[rw_x] = (INT16)viewheight;
floorclip[rw_x] = -1;
if (!rw_ceilingmarked)
ceilingclip[rw_x] = (INT16)viewheight;
if (!rw_floormarked)
floorclip[rw_x] = -1;
}
else
{
// note: don't use min/max macros, since casting from INT32 to INT16 is involved here
if (markceiling)
if (markceiling && (!rw_ceilingmarked))
ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
if (markfloor)
if (markfloor && (!rw_floormarked))
floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
}
}
else
{
INT16 topclip = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
INT16 bottomclip = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
// two sided line
if (toptexture)
{
@ -1472,7 +1556,10 @@ static void R_RenderSegLoop (void)
if (mid >= yl) // back ceiling lower than front ceiling ?
{
if (yl >= viewheight) // entirely off bottom of screen
ceilingclip[rw_x] = (INT16)viewheight;
{
if (!rw_ceilingmarked)
ceilingclip[rw_x] = (INT16)viewheight;
}
else if (mid >= 0) // safe to draw top texture
{
dc_yl = yl;
@ -1483,14 +1570,14 @@ static void R_RenderSegLoop (void)
colfunc();
ceilingclip[rw_x] = (INT16)mid;
}
else // entirely off top of screen
else if (!rw_ceilingmarked) // entirely off top of screen
ceilingclip[rw_x] = -1;
}
else
ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
else if (!rw_ceilingmarked)
ceilingclip[rw_x] = topclip;
}
else if (markceiling) // no top wall
ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
else if (markceiling && (!rw_ceilingmarked)) // no top wall
ceilingclip[rw_x] = topclip;
if (bottomtexture)
{
@ -1505,7 +1592,10 @@ static void R_RenderSegLoop (void)
if (mid <= yh) // back floor higher than front floor ?
{
if (yh < 0) // entirely off top of screen
floorclip[rw_x] = -1;
{
if (!rw_floormarked)
floorclip[rw_x] = -1;
}
else if (mid < viewheight) // safe to draw bottom texture
{
dc_yl = mid;
@ -1517,14 +1607,14 @@ static void R_RenderSegLoop (void)
colfunc();
floorclip[rw_x] = (INT16)mid;
}
else // entirely off bottom of screen
else if (!rw_floormarked) // entirely off bottom of screen
floorclip[rw_x] = (INT16)viewheight;
}
else
floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
else if (!rw_floormarked)
floorclip[rw_x] = bottomclip;
}
else if (markfloor) // no bottom wall
floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
else if (markfloor && (!rw_floormarked)) // no bottom wall
floorclip[rw_x] = bottomclip;
}
if (maskedtexture || numthicksides)
@ -2793,6 +2883,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
}
}
rw_silhouette = &(ds_p->silhouette);
rw_tsilheight = &(ds_p->tsilheight);
rw_bsilheight = &(ds_p->bsilheight);
#ifdef WALLSPLATS
if (linedef->splats && cv_splats.value)
{

View File

@ -286,6 +286,11 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
else if (playernum == secondarydisplayplayer)
CV_StealthSetValue(&cv_playercolor2, skin->prefcolor);
player->skincolor = newcolor = skin->prefcolor;
if (player->bot && botingame)
{
botskin = (UINT8)(skinnum + 1);
botcolor = skin->prefcolor;
}
}
if (player->followmobj)

View File

@ -17,7 +17,7 @@
#include "info.h"
#include "sounds.h"
#include "d_player.h" // skinflags
#include "r_patch.h" // spriteinfo_t
#include "r_picformats.h" // spriteinfo_t
#include "r_defs.h" // spritedef_t
/// Defaults

1648
src/r_textures.c Normal file

File diff suppressed because it is too large Load Diff

103
src/r_textures.h Normal file
View File

@ -0,0 +1,103 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// 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 r_textures.h
/// \brief Texture generation.
#ifndef __R_TEXTURES__
#define __R_TEXTURES__
#include "r_defs.h"
#include "r_state.h"
#include "p_setup.h" // levelflats
#include "r_data.h"
#ifdef __GNUG__
#pragma interface
#endif
// A single patch from a texture definition,
// basically a rectangular area within
// the texture rectangle.
typedef struct
{
// Block origin (always UL), which has already accounted for the internal origin of the patch.
INT16 originx, originy;
UINT16 wad, lump;
UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
UINT8 alpha; // Translucency value
enum patchalphastyle style;
} texpatch_t;
// texture type
enum
{
TEXTURETYPE_UNKNOWN,
TEXTURETYPE_SINGLEPATCH,
TEXTURETYPE_COMPOSITE,
#ifdef WALLFLATS
TEXTURETYPE_FLAT,
#endif
};
// A texture_t describes a rectangular texture,
// which is composed of one or more texpatch_t structures
// that arrange graphic patches.
typedef struct
{
// Keep name for switch changing, etc.
char name[8];
UINT8 type; // TEXTURETYPE_
INT16 width, height;
boolean holes;
UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
void *flat; // The texture, as a flat.
// All the patches[patchcount] are drawn back to front into the cached texture.
INT16 patchcount;
texpatch_t patches[0];
} texture_t;
// all loaded and prepared textures from the start of the game
extern texture_t **textures;
extern INT32 *texturewidth;
extern fixed_t *textureheight; // needed for texture pegging
extern UINT32 **texturecolumnofs; // column offset lookup table for each texture
extern UINT8 **texturecache; // graphics data for each generated full-size texture
// Load TEXTURES definitions, create lookup tables
void R_LoadTextures(void);
void R_FlushTextureCache(void);
// Texture generation
UINT8 *R_GenerateTexture(size_t texnum);
UINT8 *R_GenerateTextureAsFlat(size_t texnum);
INT32 R_GetTextureNum(INT32 texnum);
void R_CheckTextureCache(INT32 tex);
void R_ClearTextureNumCache(boolean btell);
// Retrieve texture data.
void *R_GetLevelFlat(levelflat_t *levelflat);
UINT8 *R_GetColumn(fixed_t tex, INT32 col);
void *R_GetFlat(lumpnum_t flatnum);
boolean R_CheckPowersOfTwo(void);
void R_CheckFlatLength(size_t size);
// Returns the texture number for the texture name.
INT32 R_TextureNumForName(const char *name);
INT32 R_CheckTextureNumForName(const char *name);
lumpnum_t R_GetFlatNumForName(const char *name);
extern INT32 numtextures;
#endif

View File

@ -24,7 +24,7 @@
#include "i_video.h" // rendermode
#include "i_system.h"
#include "r_things.h"
#include "r_patch.h"
#include "r_picformats.h"
#include "r_plane.h"
#include "r_portal.h"
#include "p_tick.h"
@ -259,6 +259,12 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
{
if (memcmp(lumpinfo[l].name,sprname,4)==0)
{
INT32 width, height;
INT16 topoffset, leftoffset;
#ifndef NO_PNG_LUMPS
boolean isPNG = false;
#endif
frame = R_Char2Frame(lumpinfo[l].name[4]);
rotation = R_Char2Rotation(lumpinfo[l].name[5]);
@ -274,24 +280,35 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
// store sprite info in lookup tables
//FIXME : numspritelumps do not duplicate sprite replacements
W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof (patch_t), 0);
#ifndef NO_PNG_LUMPS
{
patch_t *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC);
size_t len = W_LumpLengthPwad(wadnum, l);
// lump is a png so convert it
if (R_IsLumpPNG((UINT8 *)png, len))
if (Picture_IsLumpPNG((UINT8 *)png, len))
{
png = R_PNGToPatch((UINT8 *)png, len, NULL);
M_Memcpy(&patch, png, sizeof(INT16)*4);
Picture_PNGDimensions((UINT8 *)png, &width, &height, &topoffset, &leftoffset, len);
isPNG = true;
}
Z_Free(png);
}
if (!isPNG)
#endif
spritecachedinfo[numspritelumps].width = SHORT(patch.width)<<FRACBITS;
spritecachedinfo[numspritelumps].offset = SHORT(patch.leftoffset)<<FRACBITS;
spritecachedinfo[numspritelumps].topoffset = SHORT(patch.topoffset)<<FRACBITS;
spritecachedinfo[numspritelumps].height = SHORT(patch.height)<<FRACBITS;
{
W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof (patch_t), 0);
width = SHORT(patch.width);
height = SHORT(patch.height);
topoffset = SHORT(patch.topoffset);
leftoffset = SHORT(patch.leftoffset);
}
spritecachedinfo[numspritelumps].width = width<<FRACBITS;
spritecachedinfo[numspritelumps].offset = leftoffset<<FRACBITS;
spritecachedinfo[numspritelumps].topoffset = topoffset<<FRACBITS;
spritecachedinfo[numspritelumps].height = height<<FRACBITS;
//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
if (rendermode != render_none) // not for psprite
@ -2514,7 +2531,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link)
node->ffloor = NULL;
node->sprite = NULL;
rs_numdrawnodes++;
ps_numdrawnodes++;
return node;
}

View File

@ -15,7 +15,7 @@
#define __R_THINGS__
#include "r_plane.h"
#include "r_patch.h"
#include "r_picformats.h"
#include "r_portal.h"
#include "r_defs.h"
#include "r_skins.h"

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