mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-04-14 22:21:20 +00:00
Merge branch 'next' into spritestuff2
This commit is contained in:
commit
5e890ee6f8
84 changed files with 4749 additions and 2626 deletions
|
@ -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,6 +98,7 @@ 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
|
||||
|
@ -171,6 +173,7 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
p_telept.c
|
||||
p_tick.c
|
||||
p_user.c
|
||||
taglist.c
|
||||
|
||||
p_local.h
|
||||
p_maputl.h
|
||||
|
@ -182,6 +185,7 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
p_slopes.h
|
||||
p_spec.h
|
||||
p_tick.h
|
||||
taglist.h
|
||||
)
|
||||
|
||||
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
|
@ -234,7 +238,9 @@ set(SRB2_CONFIG_HAVE_GME ON CACHE BOOL
|
|||
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.")
|
||||
"Enable curl support.")
|
||||
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.")
|
||||
|
@ -267,6 +273,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
|
||||
|
@ -457,7 +464,7 @@ endif()
|
|||
if(${SRB2_CONFIG_HAVE_CURL})
|
||||
if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES})
|
||||
set(CURL_FOUND ON)
|
||||
set(CURL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/curl)
|
||||
set(CURL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/curl/include)
|
||||
if(${SRB2_SYSTEM_BITS} EQUAL 64)
|
||||
set(CURL_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/curl/lib64 -lcurl")
|
||||
else() # 32-bit
|
||||
|
@ -474,6 +481,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
|
||||
|
@ -545,6 +558,7 @@ if(${SRB2_CONFIG_USEASM})
|
|||
endif()
|
||||
set(SRB2_USEASM ON)
|
||||
add_definitions(-DUSEASM)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse")
|
||||
else()
|
||||
set(SRB2_USEASM OFF)
|
||||
add_definitions(-DNONX86 -DNORUSEASM)
|
||||
|
|
10
src/Makefile
10
src/Makefile
|
@ -277,7 +277,7 @@ OPTS += -DCOMPVERSION
|
|||
|
||||
ifndef NONX86
|
||||
ifndef GCC29
|
||||
ARCHOPTS?=-march=pentium
|
||||
ARCHOPTS?=-msse3 -mfpmath=sse
|
||||
else
|
||||
ARCHOPTS?=-mpentium
|
||||
endif
|
||||
|
@ -486,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 \
|
||||
|
@ -523,6 +524,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/r_picformats.o \
|
||||
$(OBJDIR)/r_portal.o \
|
||||
$(OBJDIR)/screen.o \
|
||||
$(OBJDIR)/taglist.o \
|
||||
$(OBJDIR)/v_video.o \
|
||||
$(OBJDIR)/s_sound.o \
|
||||
$(OBJDIR)/sounds.o \
|
||||
|
@ -608,8 +610,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
|
||||
|
@ -629,8 +632,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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
126
src/command.c
126
src/command.c
|
@ -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)
|
||||
{
|
||||
|
@ -901,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
|
||||
{
|
||||
|
@ -1306,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
|
||||
|
@ -1418,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;
|
||||
|
@ -1478,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);
|
||||
|
||||
|
@ -1702,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--)
|
||||
|
@ -1717,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);
|
||||
|
@ -1790,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);
|
||||
|
@ -2323,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,16 @@ 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
|
||||
|
@ -148,7 +158,7 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL
|
|||
|
||||
/* name, defaultvalue, flags, PossibleValue, func */
|
||||
#define CVAR_INIT( ... ) \
|
||||
{ __VA_ARGS__, 0, NULL, NULL, 0U, (char)0, NULL }
|
||||
{ __VA_ARGS__, 0, NULL, NULL, {0}, 0U, (char)0, NULL }
|
||||
|
||||
#ifdef OLD22DEMOCOMPAT
|
||||
typedef struct old_demo_var old_demo_var_t;
|
||||
|
@ -208,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);
|
||||
|
||||
|
|
1028
src/d_clisrv.c
1028
src/d_clisrv.c
File diff suppressed because it is too large
Load diff
191
src/d_clisrv.h
191
src/d_clisrv.h
|
@ -64,8 +64,10 @@ typedef enum
|
|||
PT_REQUESTFILE, // Client requests a file transfer
|
||||
PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client.
|
||||
// If this ID changes, update masterserver definition.
|
||||
PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic
|
||||
PT_RESYNCHGET, // Player got resynch packet
|
||||
|
||||
PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate!
|
||||
PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead.
|
||||
PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again!
|
||||
|
||||
PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file
|
||||
PT_ASKLUAFILE, // Client telling the server they don't have the file
|
||||
|
@ -85,8 +87,6 @@ typedef enum
|
|||
PT_TEXTCMD2, // Splitscreen text commands.
|
||||
PT_CLIENTJOIN, // Client wants to join; used in start game.
|
||||
PT_NODETIMEOUT, // Packet sent to self if the connection times out.
|
||||
PT_RESYNCHING, // Packet sent to resync players.
|
||||
// Blocks game advance until synched.
|
||||
|
||||
PT_LOGIN, // Login attempt from the client.
|
||||
|
||||
|
@ -139,176 +139,6 @@ typedef struct
|
|||
ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
|
||||
} ATTRPACK servertics_pak;
|
||||
|
||||
// Sent to client when all consistency data
|
||||
// for players has been restored
|
||||
typedef struct
|
||||
{
|
||||
UINT32 randomseed;
|
||||
|
||||
// CTF flag stuff
|
||||
SINT8 flagplayer[2];
|
||||
INT32 flagloose[2];
|
||||
INT32 flagflags[2];
|
||||
fixed_t flagx[2];
|
||||
fixed_t flagy[2];
|
||||
fixed_t flagz[2];
|
||||
|
||||
UINT32 ingame; // Spectator bit for each player
|
||||
UINT32 outofcoop; // outofcoop bit for each player
|
||||
INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
|
||||
|
||||
// Resynch game scores and the like all at once
|
||||
UINT32 score[MAXPLAYERS]; // Everyone's score
|
||||
INT16 numboxes[MAXPLAYERS];
|
||||
INT16 totalring[MAXPLAYERS];
|
||||
tic_t realtime[MAXPLAYERS];
|
||||
UINT8 laps[MAXPLAYERS];
|
||||
} ATTRPACK resynchend_pak;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Player stuff
|
||||
UINT8 playernum;
|
||||
|
||||
// Do not send anything visual related.
|
||||
// Only send data that we need to know for physics.
|
||||
UINT8 playerstate; // playerstate_t
|
||||
UINT32 pflags; // pflags_t
|
||||
UINT8 panim; // panim_t
|
||||
|
||||
INT16 angleturn;
|
||||
INT16 oldrelangleturn;
|
||||
|
||||
angle_t aiming;
|
||||
INT32 currentweapon;
|
||||
INT32 ringweapons;
|
||||
UINT16 ammoremoval;
|
||||
tic_t ammoremovaltimer;
|
||||
INT32 ammoremovalweapon;
|
||||
UINT16 powers[NUMPOWERS];
|
||||
|
||||
// Score is resynched in the confirm resync packet
|
||||
INT16 rings;
|
||||
INT16 spheres;
|
||||
SINT8 lives;
|
||||
SINT8 continues;
|
||||
UINT8 scoreadd;
|
||||
SINT8 xtralife;
|
||||
SINT8 pity;
|
||||
|
||||
UINT16 skincolor;
|
||||
INT32 skin;
|
||||
UINT32 availabilities;
|
||||
// Just in case Lua does something like
|
||||
// modify these at runtime
|
||||
fixed_t camerascale;
|
||||
fixed_t shieldscale;
|
||||
fixed_t normalspeed;
|
||||
fixed_t runspeed;
|
||||
UINT8 thrustfactor;
|
||||
UINT8 accelstart;
|
||||
UINT8 acceleration;
|
||||
UINT8 charability;
|
||||
UINT8 charability2;
|
||||
UINT32 charflags;
|
||||
UINT32 thokitem; // mobjtype_t
|
||||
UINT32 spinitem; // mobjtype_t
|
||||
UINT32 revitem; // mobjtype_t
|
||||
UINT32 followitem; // mobjtype_t
|
||||
fixed_t actionspd;
|
||||
fixed_t mindash;
|
||||
fixed_t maxdash;
|
||||
fixed_t jumpfactor;
|
||||
fixed_t playerheight;
|
||||
fixed_t playerspinheight;
|
||||
|
||||
fixed_t speed;
|
||||
UINT8 secondjump;
|
||||
UINT8 fly1;
|
||||
tic_t glidetime;
|
||||
UINT8 climbing;
|
||||
INT32 deadtimer;
|
||||
tic_t exiting;
|
||||
UINT8 homing;
|
||||
tic_t dashmode;
|
||||
tic_t skidtime;
|
||||
fixed_t cmomx;
|
||||
fixed_t cmomy;
|
||||
fixed_t rmomx;
|
||||
fixed_t rmomy;
|
||||
|
||||
INT32 weapondelay;
|
||||
INT32 tossdelay;
|
||||
|
||||
INT16 starpostx;
|
||||
INT16 starposty;
|
||||
INT16 starpostz;
|
||||
INT32 starpostnum;
|
||||
tic_t starposttime;
|
||||
angle_t starpostangle;
|
||||
fixed_t starpostscale;
|
||||
|
||||
INT32 maxlink;
|
||||
fixed_t dashspeed;
|
||||
angle_t angle_pos;
|
||||
angle_t old_angle_pos;
|
||||
tic_t bumpertime;
|
||||
INT32 flyangle;
|
||||
tic_t drilltimer;
|
||||
INT32 linkcount;
|
||||
tic_t linktimer;
|
||||
INT32 anotherflyangle;
|
||||
tic_t nightstime;
|
||||
INT32 drillmeter;
|
||||
UINT8 drilldelay;
|
||||
UINT8 bonustime;
|
||||
UINT8 mare;
|
||||
INT16 lastsidehit, lastlinehit;
|
||||
|
||||
tic_t losstime;
|
||||
UINT8 timeshit;
|
||||
INT32 onconveyor;
|
||||
|
||||
//player->mo stuff
|
||||
UINT8 hasmo; // Boolean
|
||||
|
||||
INT32 health;
|
||||
angle_t angle;
|
||||
angle_t rollangle;
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
fixed_t momx;
|
||||
fixed_t momy;
|
||||
fixed_t momz;
|
||||
fixed_t friction;
|
||||
fixed_t movefactor;
|
||||
|
||||
spritenum_t sprite;
|
||||
UINT32 frame;
|
||||
UINT8 sprite2;
|
||||
UINT16 anim_duration;
|
||||
|
||||
fixed_t spritexscale;
|
||||
fixed_t spriteyscale;
|
||||
fixed_t spritexoffset;
|
||||
fixed_t spriteyoffset;
|
||||
|
||||
INT32 tics;
|
||||
statenum_t statenum;
|
||||
UINT32 flags;
|
||||
UINT32 flags2;
|
||||
UINT16 eflags;
|
||||
UINT32 renderflags;
|
||||
INT32 blendmode;
|
||||
|
||||
fixed_t radius;
|
||||
fixed_t height;
|
||||
fixed_t scale;
|
||||
fixed_t destscale;
|
||||
fixed_t scalespeed;
|
||||
} ATTRPACK resynch_pak;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 version; // Different versions don't work
|
||||
|
@ -322,18 +152,10 @@ typedef struct
|
|||
UINT8 clientnode;
|
||||
UINT8 gamestate;
|
||||
|
||||
// 0xFF == not in game; else player skin num
|
||||
UINT8 playerskins[MAXPLAYERS];
|
||||
UINT16 playercolor[MAXPLAYERS];
|
||||
UINT32 playeravailabilities[MAXPLAYERS];
|
||||
|
||||
UINT8 gametype;
|
||||
UINT8 modifiedgame;
|
||||
SINT8 adminplayers[MAXPLAYERS]; // Needs to be signed
|
||||
|
||||
char server_context[8]; // Unique context id, generated at server startup.
|
||||
|
||||
UINT8 varlengthinputs[0]; // Playernames and netvars
|
||||
} ATTRPACK serverconfig_pak;
|
||||
|
||||
typedef struct
|
||||
|
@ -470,9 +292,6 @@ typedef struct
|
|||
client2cmd_pak client2pak; // 200 bytes
|
||||
servertics_pak serverpak; // 132495 bytes (more around 360, no?)
|
||||
serverconfig_pak servercfg; // 773 bytes
|
||||
resynchend_pak resynchend; //
|
||||
resynch_pak resynchpak; //
|
||||
UINT8 resynchgot; //
|
||||
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
|
||||
filetx_pak filetxpak; // 139 bytes
|
||||
fileack_pak fileack;
|
||||
|
@ -614,7 +433,7 @@ UINT8 GetFreeXCmdSize(void);
|
|||
|
||||
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
|
||||
|
||||
extern UINT8 hu_resynching;
|
||||
extern UINT8 hu_redownloadinggamestate;
|
||||
|
||||
extern UINT8 adminpassmd5[16];
|
||||
extern boolean adminpasswordset;
|
||||
|
|
103
src/d_main.c
103
src/d_main.c
|
@ -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"
|
||||
|
@ -412,7 +413,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;
|
||||
|
@ -459,7 +460,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)
|
||||
|
@ -473,7 +474,7 @@ static void D_Display(void)
|
|||
lastdraw = false;
|
||||
}
|
||||
|
||||
rs_uitime = I_GetTimeMicros();
|
||||
ps_uitime = I_GetTimeMicros();
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
|
@ -486,7 +487,7 @@ static void D_Display(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
rs_uitime = I_GetTimeMicros();
|
||||
ps_uitime = I_GetTimeMicros();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -528,7 +529,7 @@ static void D_Display(void)
|
|||
|
||||
CON_Drawer();
|
||||
|
||||
rs_uitime = I_GetTimeMicros() - rs_uitime;
|
||||
ps_uitime = I_GetTimeMicros() - ps_uitime;
|
||||
|
||||
//
|
||||
// wipe update
|
||||
|
@ -609,90 +610,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
|
||||
{
|
||||
#ifdef HWRENDER
|
||||
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, "ui %d", rs_uitime / divisor);
|
||||
V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
|
||||
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
|
||||
V_DrawThinString(30, 90, V_MONOSPACE | V_YELLOWMAP, s);
|
||||
snprintf(s, sizeof s - 1, "tic %d", rs_tictime / divisor);
|
||||
V_DrawThinString(30, 105, V_MONOSPACE | V_GRAYMAP, 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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
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, "ui %d", rs_uitime / 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);
|
||||
snprintf(s, sizeof s - 1, "tic %d", rs_tictime / divisor);
|
||||
V_DrawThinString(30, 95, V_MONOSPACE | V_GRAYMAP, 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1542,6 +1467,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()))
|
||||
{
|
||||
|
@ -1620,7 +1551,7 @@ void D_SRB2Main(void)
|
|||
{
|
||||
levelstarttic = gametic;
|
||||
G_SetGamestate(GS_LEVEL);
|
||||
if (!P_LoadLevel(false))
|
||||
if (!P_LoadLevel(false, false))
|
||||
I_Quit(); // fail so reset game stuff
|
||||
}
|
||||
}
|
||||
|
|
|
@ -798,8 +798,9 @@ static const char *packettypename[NUMPACKETTYPE] =
|
|||
"REQUESTFILE",
|
||||
"ASKINFOVIAMS",
|
||||
|
||||
"RESYNCHEND",
|
||||
"RESYNCHGET",
|
||||
"WILLRESENDGAMESTATE",
|
||||
"CANRECEIVEGAMESTATE",
|
||||
"RECEIVEDGAMESTATE",
|
||||
|
||||
"SENDINGLUAFILE",
|
||||
"ASKLUAFILE",
|
||||
|
@ -813,7 +814,6 @@ static const char *packettypename[NUMPACKETTYPE] =
|
|||
"TEXTCMD2",
|
||||
"CLIENTJOIN",
|
||||
"NODETIMEOUT",
|
||||
"RESYNCHING",
|
||||
"LOGIN",
|
||||
"PING"
|
||||
};
|
||||
|
|
281
src/d_netcmd.c
281
src/d_netcmd.c
|
@ -204,20 +204,20 @@ static consvar_t cv_fishcake = CVAR_INIT ("fishcake", "Off", CV_CALL|CV_NOSHOWHE
|
|||
#endif
|
||||
static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange);
|
||||
|
||||
consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL);
|
||||
consvar_t cv_allowteamchange = CVAR_INIT ("allowteamchange", "Yes", CV_NETVAR, CV_YesNo, 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 = CVAR_INIT ("startinglives", "3", CV_NETVAR|CV_CHEAT, startingliveslimit_cons_t, 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 = CVAR_INIT ("respawndelay", "3", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL);
|
||||
consvar_t cv_respawntime = CVAR_INIT ("respawndelay", "3", CV_SAVE|CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL);
|
||||
|
||||
consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL);
|
||||
consvar_t cv_competitionboxes = CVAR_INIT ("competitionboxes", "Mystery", CV_SAVE|CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL);
|
||||
|
||||
#ifdef SEENAMES
|
||||
static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}};
|
||||
consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0);
|
||||
consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL);
|
||||
consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
|
||||
#endif
|
||||
|
||||
// names
|
||||
|
@ -264,22 +264,22 @@ consvar_t cv_mouse2opt = CVAR_INIT ("mouse2opt", "0", CV_SAVE, NULL, NULL);
|
|||
consvar_t cv_mouse2port = CVAR_INIT ("mouse2port", "COM2", CV_SAVE, mouse2port_cons_t, NULL);
|
||||
#endif
|
||||
|
||||
consvar_t cv_matchboxes = CVAR_INIT ("matchboxes", "Normal", CV_NETVAR|CV_CHEAT, matchboxes_cons_t, NULL);
|
||||
consvar_t cv_specialrings = CVAR_INIT ("specialrings", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_powerstones = CVAR_INIT ("powerstones", "On", CV_NETVAR, CV_OnOff, 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 = CVAR_INIT ("tv_recycler", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_teleporters = CVAR_INIT ("tv_teleporter", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_superring = CVAR_INIT ("tv_superring", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_supersneakers = CVAR_INIT ("tv_supersneaker", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_invincibility = CVAR_INIT ("tv_invincibility", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_jumpshield = CVAR_INIT ("tv_jumpshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_watershield = CVAR_INIT ("tv_watershield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_ringshield = CVAR_INIT ("tv_ringshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_forceshield = CVAR_INIT ("tv_forceshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_bombshield = CVAR_INIT ("tv_bombshield", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_1up = CVAR_INIT ("tv_1up", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL);
|
||||
consvar_t cv_eggmanbox = CVAR_INIT ("tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, 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 = 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);
|
||||
|
@ -287,20 +287,20 @@ consvar_t cv_gravity = CVAR_INIT ("gravity", "0.5", CV_RESTRICT|CV_FLOAT|CV_CALL
|
|||
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 = CVAR_INIT ("countdowntime", "60", CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL);
|
||||
consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL);
|
||||
|
||||
consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_hidetime = CVAR_INIT ("hidetime", "30", CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange);
|
||||
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 = CVAR_INIT ("autobalance", "Off", CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange);
|
||||
consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange);
|
||||
consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_NETVAR, teamscramble_cons_t, 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 = CVAR_INIT ("friendlyfire", "Off", CV_NETVAR, CV_OnOff, 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 = CVAR_INIT ("overtime", "Yes", CV_NETVAR, CV_YesNo, NULL);
|
||||
consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
|
||||
|
||||
consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
|
@ -311,13 +311,13 @@ static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-pe
|
|||
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 = CVAR_INIT ("pointlimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange);
|
||||
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 = CVAR_INIT ("timelimit", "None", CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange);
|
||||
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 = 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 = CVAR_INIT ("basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange);
|
||||
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];
|
||||
|
@ -328,7 +328,7 @@ consvar_t cv_hazardlog = CVAR_INIT ("hazardlog", "Yes", 0, CV_YesNo, 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_NETVAR, CV_YesNo, NULL);
|
||||
consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_SAVE|CV_NETVAR, CV_YesNo, NULL);
|
||||
|
||||
consvar_t cv_killingdead = CVAR_INIT ("killingdead", "Off", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
|
@ -336,11 +336,11 @@ consvar_t cv_netstat = CVAR_INIT ("netstat", "Off", 0, CV_OnOff, NULL); // show
|
|||
static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {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 = CVAR_INIT ("jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange);
|
||||
consvar_t cv_maxping = CVAR_INIT ("maxping", "0", CV_SAVE, CV_Unsigned, 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 = CVAR_INIT ("pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, 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}};
|
||||
|
@ -348,29 +348,33 @@ consvar_t cv_showping = CVAR_INIT ("showping", "Warning", CV_SAVE, showping_cons
|
|||
|
||||
// Intermission time Tails 04-19-2002
|
||||
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_inttime = CVAR_INIT ("inttime", "10", CV_NETVAR, inttime_cons_t, 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 = CVAR_INIT ("coopstarposts", "Per-player", CV_NETVAR|CV_CALL, coopstarposts_cons_t, CoopStarposts_OnChange);
|
||||
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 = CVAR_INIT ("cooplives", "Avoid Game Over", CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange);
|
||||
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 = CVAR_INIT ("advancemap", "Next", CV_NETVAR, advancemap_cons_t, 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 = CVAR_INIT ("playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL);
|
||||
consvar_t cv_playersforexit = CVAR_INIT ("playersforexit", "All", CV_SAVE|CV_NETVAR, playersforexit_cons_t, NULL);
|
||||
|
||||
consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange);
|
||||
consvar_t cv_exitmove = CVAR_INIT ("exitmove", "On", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, ExitMove_OnChange);
|
||||
|
||||
consvar_t cv_runscripts = CVAR_INIT ("runscripts", "Yes", 0, CV_YesNo, NULL);
|
||||
|
||||
consvar_t cv_pause = CVAR_INIT ("pausepermission", "Server", CV_NETVAR, pause_cons_t, 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 = 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;
|
||||
char timedemo_csv_id[256];
|
||||
|
@ -860,6 +864,8 @@ void D_RegisterClientCommands(void)
|
|||
|
||||
CV_RegisterVar(&cv_soundtest);
|
||||
|
||||
CV_RegisterVar(&cv_perfstats);
|
||||
|
||||
// ingame object placing
|
||||
COM_AddCommand("objectplace", Command_ObjectPlace_f);
|
||||
COM_AddCommand("writethings", Command_Writethings_f);
|
||||
|
@ -3237,97 +3243,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)
|
||||
|
|
|
@ -111,6 +111,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];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "dehacked.h"
|
||||
#include "st_stuff.h"
|
||||
#include "i_system.h"
|
||||
#include "i_sound.h" // musictype_t (for lua)
|
||||
#include "p_local.h" // for var1 and var2, and some constants
|
||||
#include "p_setup.h"
|
||||
#include "r_data.h"
|
||||
|
@ -39,6 +40,7 @@
|
|||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "g_state.h" // gamestate_t (for lua)
|
||||
|
||||
#include "m_cond.h"
|
||||
|
||||
|
@ -5171,6 +5173,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_TAILSOVERLAY_PAIN",
|
||||
"S_TAILSOVERLAY_GASP",
|
||||
"S_TAILSOVERLAY_EDGE",
|
||||
"S_TAILSOVERLAY_DASH",
|
||||
|
||||
// [:
|
||||
"S_JETFUMEFLASH",
|
||||
|
@ -9725,6 +9728,7 @@ struct {
|
|||
{"SF_NONIGHTSSUPER",SF_NONIGHTSSUPER},
|
||||
{"SF_NOSUPERSPRITES",SF_NOSUPERSPRITES},
|
||||
{"SF_NOSUPERJUMPBOOST",SF_NOSUPERJUMPBOOST},
|
||||
{"SF_CANBUSTWALLS",SF_CANBUSTWALLS},
|
||||
|
||||
// Dashmode constants
|
||||
{"DASHMODE_THRESHOLD",DASHMODE_THRESHOLD},
|
||||
|
@ -9932,6 +9936,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.
|
||||
|
@ -10110,6 +10133,35 @@ struct {
|
|||
{"MA_NOCUTSCENES",MA_NOCUTSCENES},
|
||||
{"MA_INGAME",MA_INGAME},
|
||||
|
||||
// music types
|
||||
{"MU_NONE", MU_NONE},
|
||||
{"MU_CMD", MU_CMD},
|
||||
{"MU_WAV", MU_WAV},
|
||||
{"MU_MOD", MU_MOD},
|
||||
{"MU_MID", MU_MID},
|
||||
{"MU_OGG", MU_OGG},
|
||||
{"MU_MP3", MU_MP3},
|
||||
{"MU_FLAC", MU_FLAC},
|
||||
{"MU_GME", MU_GME},
|
||||
{"MU_MOD_EX", MU_MOD_EX},
|
||||
{"MU_MID_EX", MU_MID_EX},
|
||||
|
||||
// gamestates
|
||||
{"GS_NULL",GS_NULL},
|
||||
{"GS_LEVEL",GS_LEVEL},
|
||||
{"GS_INTERMISSION",GS_INTERMISSION},
|
||||
{"GS_CONTINUING",GS_CONTINUING},
|
||||
{"GS_TITLESCREEN",GS_TITLESCREEN},
|
||||
{"GS_TIMEATTACK",GS_TIMEATTACK},
|
||||
{"GS_CREDITS",GS_CREDITS},
|
||||
{"GS_EVALUATION",GS_EVALUATION},
|
||||
{"GS_GAMEEND",GS_GAMEEND},
|
||||
{"GS_INTRO",GS_INTRO},
|
||||
{"GS_ENDING",GS_ENDING},
|
||||
{"GS_CUTSCENE",GS_CUTSCENE},
|
||||
{"GS_DEDICATEDSERVER",GS_DEDICATEDSERVER},
|
||||
{"GS_WAITINGPLAYERS",GS_WAITINGPLAYERS},
|
||||
|
||||
{NULL,0}
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
// Some global defines, that configure the game.
|
||||
#include "doomdef.h"
|
||||
|
||||
#include "taglist.h"
|
||||
#include "m_fixed.h" // See the mapthing_t scale.
|
||||
|
||||
//
|
||||
|
@ -208,11 +209,10 @@ typedef struct
|
|||
UINT16 options;
|
||||
INT16 z;
|
||||
UINT8 extrainfo;
|
||||
taglist_t tags;
|
||||
fixed_t scale;
|
||||
INT16 tag;
|
||||
INT32 args[NUMMAPTHINGARGS];
|
||||
char *stringargs[NUMMAPTHINGSTRINGARGS];
|
||||
|
||||
struct mobj_s *mobj;
|
||||
} mapthing_t;
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -1127,6 +1127,7 @@ static const char *credits[] = {
|
|||
"Sherman \"CoatRack\" DesJardins",
|
||||
"\"DirkTheHusky\"",
|
||||
"Jesse \"Jeck Jims\" Emerick",
|
||||
"\"Fighter_Builder\"", // for the CEZ3 button debris
|
||||
"Buddy \"KinkaJoy\" Fischer",
|
||||
"Vivian \"toaster\" Grannell",
|
||||
"James \"SwitchKaze\" Hale",
|
||||
|
@ -1207,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",
|
||||
|
|
|
@ -625,7 +625,7 @@ void G_ConsGhostTic(void)
|
|||
if (followtic & FZT_SCALE)
|
||||
demo_p += sizeof(fixed_t);
|
||||
// momx, momy and momz
|
||||
demo_p += (demoversion < 0x000e) ? sizeof(UINT16) * 3 : sizeof(fixed_t) * 3;
|
||||
demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3;
|
||||
if (followtic & FZT_SKIN)
|
||||
demo_p++;
|
||||
demo_p += sizeof(UINT16);
|
||||
|
@ -2163,7 +2163,7 @@ void G_AddGhost(char *defdemoname)
|
|||
count = READUINT16(p);
|
||||
while (count--)
|
||||
{
|
||||
p += 2;
|
||||
SKIPSTRING(p);
|
||||
SKIPSTRING(p);
|
||||
p++;
|
||||
}
|
||||
|
|
|
@ -1829,7 +1829,7 @@ void G_DoLoadLevel(boolean resetplayer)
|
|||
}
|
||||
|
||||
// Setup the level.
|
||||
if (!P_LoadLevel(false)) // this never returns false?
|
||||
if (!P_LoadLevel(false, false)) // this never returns false?
|
||||
{
|
||||
// fail so reset game stuff
|
||||
Command_ExitGame_f();
|
||||
|
@ -2019,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);
|
||||
|
@ -3518,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;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -235,13 +234,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 +248,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 +261,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 +397,8 @@ void HWR_RenderBatches(void)
|
|||
// execute draw call
|
||||
HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, 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 +415,7 @@ void HWR_RenderBatches(void)
|
|||
currentShader = nextShader;
|
||||
changeShader = false;
|
||||
|
||||
rs_hw_numshaders++;
|
||||
ps_hw_numshaders++;
|
||||
}
|
||||
if (changeTexture)
|
||||
{
|
||||
|
@ -425,21 +424,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 +446,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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2020 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
|
|
@ -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;
|
||||
|
@ -255,6 +292,16 @@ enum hwdsetspecialstate
|
|||
|
||||
typedef enum hwdsetspecialstate hwdspecialstate_t;
|
||||
|
||||
// Lactozilla: Shader options
|
||||
enum hwdshaderoption
|
||||
{
|
||||
HWD_SHADEROPTION_OFF,
|
||||
HWD_SHADEROPTION_ON,
|
||||
HWD_SHADEROPTION_NOCUSTOM,
|
||||
};
|
||||
|
||||
typedef enum hwdshaderoption hwdshaderoption_t;
|
||||
|
||||
// Lactozilla: Shader info
|
||||
// Generally set at the start of the frame.
|
||||
enum hwdshaderinfo
|
||||
|
|
|
@ -69,14 +69,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 void HWRAPI(SetShader) (int shader);
|
||||
EXPORT boolean HWRAPI(CompileShaders) (void);
|
||||
EXPORT void HWRAPI(CleanShaders) (void);
|
||||
EXPORT void HWRAPI(SetShader) (int type);
|
||||
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
|
||||
|
@ -122,14 +121,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;
|
||||
|
|
|
@ -147,21 +147,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_init = false;
|
||||
boolean gl_maploaded = false;
|
||||
|
@ -568,11 +569,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);
|
||||
|
||||
|
@ -785,7 +786,7 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I
|
|||
static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
@ -1584,7 +1585,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
|||
|
||||
|
||||
//Hurdler: 3d-floors test
|
||||
if (gl_frontsector && gl_backsector && gl_frontsector->tag != gl_backsector->tag && (gl_backsector->ffloors || gl_frontsector->ffloors))
|
||||
if (gl_frontsector && gl_backsector && !Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags) && (gl_backsector->ffloors || gl_frontsector->ffloors))
|
||||
{
|
||||
ffloor_t * rover;
|
||||
fixed_t highcut = 0, lowcut = 0;
|
||||
|
@ -1601,6 +1602,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
|||
{
|
||||
for (rover = gl_backsector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
boolean bothsides = false;
|
||||
// Skip if it exists on both sectors.
|
||||
ffloor_t * r2;
|
||||
for (r2 = gl_frontsector->ffloors; r2; r2 = r2->next)
|
||||
if (rover->master == r2->master)
|
||||
{
|
||||
bothsides = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bothsides) continue;
|
||||
|
||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES))
|
||||
continue;
|
||||
if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES)
|
||||
|
@ -1735,6 +1748,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
|||
{
|
||||
for (rover = gl_frontsector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
boolean bothsides = false;
|
||||
// Skip if it exists on both sectors.
|
||||
ffloor_t * r2;
|
||||
for (r2 = gl_backsector->ffloors; r2; r2 = r2->next)
|
||||
if (rover->master == r2->master)
|
||||
{
|
||||
bothsides = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bothsides) continue;
|
||||
|
||||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES))
|
||||
continue;
|
||||
if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES))
|
||||
|
@ -2360,7 +2385,7 @@ static void HWR_AddLine(seg_t * line)
|
|||
if (!line->polyseg &&
|
||||
!line->sidedef->midtexture
|
||||
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors)
|
||||
|| (gl_frontsector->tag == gl_backsector->tag)))
|
||||
|| Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags)))
|
||||
return; // line is empty, don't even bother
|
||||
// treat like wide open window instead
|
||||
HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
|
||||
|
@ -2399,7 +2424,7 @@ static void HWR_AddLine(seg_t * line)
|
|||
if (!line->polyseg &&
|
||||
!line->sidedef->midtexture
|
||||
&& ((!gl_frontsector->ffloors && !gl_backsector->ffloors)
|
||||
|| (gl_frontsector->tag == gl_backsector->tag)))
|
||||
|| Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags)))
|
||||
return; // line is empty, don't even bother
|
||||
|
||||
goto clippass; // treat like wide open window instead
|
||||
|
@ -2820,7 +2845,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
|
|||
else
|
||||
blendmode |= PF_Masked|PF_Modulated;
|
||||
|
||||
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)
|
||||
|
@ -3165,7 +3190,7 @@ static void HWR_Subsector(size_t num)
|
|||
}
|
||||
|
||||
// for render stats
|
||||
rs_numpolyobjects += numpolys;
|
||||
ps_numpolyobjects += numpolys;
|
||||
|
||||
// Sort polyobjects
|
||||
R_SortPolyObjects(sub);
|
||||
|
@ -3273,7 +3298,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)
|
||||
|
@ -3633,7 +3658,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, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated, SHADER_SPRITE, false); // sprite shader
|
||||
}
|
||||
|
||||
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
|
||||
|
@ -3915,7 +3940,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
|
||||
Surf.PolyColor.s.alpha = alpha;
|
||||
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, SHADER_SPRITE, false); // sprite shader
|
||||
|
||||
if (use_linkdraw_hack)
|
||||
HWR_LinkDrawHackAdd(wallVerts, spr);
|
||||
|
@ -3944,7 +3969,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
|
||||
Surf.PolyColor.s.alpha = alpha;
|
||||
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, SHADER_SPRITE, false); // sprite shader
|
||||
|
||||
if (use_linkdraw_hack)
|
||||
HWR_LinkDrawHackAdd(wallVerts, spr);
|
||||
|
@ -4246,7 +4271,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
if (!occlusion) use_linkdraw_hack = true;
|
||||
}
|
||||
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, SHADER_SPRITE, false); // sprite shader
|
||||
|
||||
if (use_linkdraw_hack)
|
||||
HWR_LinkDrawHackAdd(wallVerts, spr);
|
||||
|
@ -4330,12 +4355,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
|
|||
HWR_Lighting(&Surf, lightlevel, colormap);
|
||||
}
|
||||
|
||||
if (spr->mobj->flags2 & MF2_SHADOW)
|
||||
{
|
||||
Surf.PolyColor.s.alpha = 0x40;
|
||||
blend = HWR_GetBlendModeFlag(spr->mobj->blendmode);
|
||||
}
|
||||
else if (spr->mobj->frame & FF_TRANSMASK)
|
||||
if (spr->mobj->frame & FF_TRANSMASK)
|
||||
{
|
||||
INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT;
|
||||
if (spr->mobj->blendmode == AST_TRANSLUCENT && trans >= NUMTRANSMAPS)
|
||||
|
@ -4352,7 +4372,7 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
|
|||
blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|PF_Occlude;
|
||||
}
|
||||
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader
|
||||
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, SHADER_SPRITE, false); // sprite shader
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4634,7 +4654,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++)
|
||||
{
|
||||
|
@ -4654,7 +4674,7 @@ static void HWR_CreateDrawNodes(void)
|
|||
sortindex[p] = p;
|
||||
}
|
||||
|
||||
rs_numdrawnodes = p;
|
||||
ps_numdrawnodes = p;
|
||||
|
||||
// p is the number of stuff to sort
|
||||
|
||||
|
@ -4689,13 +4709,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++)
|
||||
{
|
||||
|
@ -4728,7 +4748,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;
|
||||
|
@ -5590,7 +5610,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);
|
||||
}
|
||||
|
@ -5677,7 +5697,7 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
HWD.pfnDrawPolygon(NULL, v, 4, 0);
|
||||
}
|
||||
|
||||
HWD.pfnSetShader(0);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5762,6 +5782,20 @@ static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean
|
|||
trans->anglex = (float)(gl_aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
|
||||
}
|
||||
|
||||
//
|
||||
// Sets the shader state.
|
||||
//
|
||||
static void HWR_SetShaderState(void)
|
||||
{
|
||||
hwdshaderoption_t state = cv_glshaders.value;
|
||||
|
||||
if (!cv_glallowshaders.value)
|
||||
state = (cv_glshaders.value == HWD_SHADEROPTION_ON ? HWD_SHADEROPTION_NOCUSTOM : cv_glshaders.value);
|
||||
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)state);
|
||||
HWD.pfnSetShader(SHADER_DEFAULT);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Same as rendering the player view, but from the skybox object
|
||||
// ==========================================================================
|
||||
|
@ -5880,8 +5914,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
|
|||
HWD.pfnSetTransform(&atransform);
|
||||
|
||||
// Reset the shader state.
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_glshaders.value);
|
||||
HWD.pfnSetShader(0);
|
||||
HWR_SetShaderState();
|
||||
|
||||
validcount++;
|
||||
|
||||
|
@ -5984,8 +6017,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)?
|
||||
|
@ -6093,12 +6128,11 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
|
|||
HWD.pfnSetTransform(&atransform);
|
||||
|
||||
// Reset the shader state.
|
||||
HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_glshaders.value);
|
||||
HWD.pfnSetShader(0);
|
||||
HWR_SetShaderState();
|
||||
|
||||
rs_numbspcalls = 0;
|
||||
rs_numpolyobjects = 0;
|
||||
rs_bsptime = I_GetTimeMicros();
|
||||
ps_numbspcalls = 0;
|
||||
ps_numpolyobjects = 0;
|
||||
ps_bsptime = I_GetTimeMicros();
|
||||
|
||||
validcount++;
|
||||
|
||||
|
@ -6136,7 +6170,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();
|
||||
|
@ -6151,22 +6185,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();
|
||||
|
@ -6216,9 +6250,10 @@ void HWR_LoadLevel(void)
|
|||
// 3D ENGINE COMMANDS
|
||||
// ==========================================================================
|
||||
|
||||
static CV_PossibleValue_t grmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
|
||||
static CV_PossibleValue_t grfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}};
|
||||
static CV_PossibleValue_t grshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glshaders_cons_t[] = {{HWD_SHADEROPTION_OFF, "Off"}, {HWD_SHADEROPTION_ON, "On"}, {HWD_SHADEROPTION_NOCUSTOM, "Ignore custom shaders"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}};
|
||||
|
||||
static void CV_glfiltermode_OnChange(void);
|
||||
static void CV_glanisotropic_OnChange(void);
|
||||
|
@ -6229,9 +6264,10 @@ static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA
|
|||
{HWD_SET_TEXTUREFILTER_MIXED2, "Nearest_Linear"},
|
||||
{HWD_SET_TEXTUREFILTER_MIXED3, "Nearest_Mipmap"},
|
||||
{0, NULL}};
|
||||
CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}};
|
||||
CV_PossibleValue_t glanisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}};
|
||||
|
||||
consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE, glshaders_cons_t, NULL);
|
||||
consvar_t cv_glallowshaders = CVAR_INIT ("gr_allowclientshaders", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_fovchange = CVAR_INIT ("gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
#ifdef ALAM_LIGHTING
|
||||
|
@ -6242,17 +6278,17 @@ consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0
|
|||
#endif
|
||||
|
||||
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_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, glmodelinterpolation_cons_t, NULL);
|
||||
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, grshearing_cons_t, NULL);
|
||||
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, glshearing_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_glfakecontrast = CVAR_INIT ("gr_fakecontrast", "Smooth", CV_SAVE, glfakecontrast_cons_t, NULL);
|
||||
consvar_t cv_glslopecontrast = CVAR_INIT ("gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, 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_glanisotropicmode = CVAR_INIT ("gr_anisotropicmode", "1", CV_CALL, glanisotropicmode_cons_t, CV_glanisotropic_OnChange);
|
||||
|
||||
consvar_t cv_glsolvetjoin = CVAR_INIT ("gr_solvetjoin", "On", 0, CV_OnOff, NULL);
|
||||
|
||||
|
@ -6291,11 +6327,11 @@ void HWR_AddCommands(void)
|
|||
CV_RegisterVar(&cv_glfakecontrast);
|
||||
CV_RegisterVar(&cv_glshearing);
|
||||
CV_RegisterVar(&cv_glshaders);
|
||||
CV_RegisterVar(&cv_glallowshaders);
|
||||
|
||||
CV_RegisterVar(&cv_glfiltermode);
|
||||
CV_RegisterVar(&cv_glsolvetjoin);
|
||||
|
||||
CV_RegisterVar(&cv_renderstats);
|
||||
CV_RegisterVar(&cv_glbatching);
|
||||
|
||||
#ifndef NEWCLIP
|
||||
|
@ -6318,7 +6354,6 @@ void HWR_Startup(void)
|
|||
{
|
||||
if (!gl_init)
|
||||
{
|
||||
INT32 i;
|
||||
CONS_Printf("HWR_Startup()...\n");
|
||||
|
||||
HWR_InitPolyPool();
|
||||
|
@ -6329,10 +6364,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;
|
||||
}
|
||||
|
||||
|
@ -6436,7 +6469,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
|
||||
|
@ -6444,7 +6477,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
|
||||
|
@ -6623,13 +6656,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;
|
||||
|
@ -6642,12 +6669,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;
|
||||
|
@ -6658,19 +6707,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;
|
||||
|
||||
|
@ -6696,7 +6733,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;
|
||||
}
|
||||
|
@ -6715,19 +6752,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))
|
||||
{
|
||||
|
@ -6753,7 +6790,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;
|
||||
}
|
||||
|
@ -6779,4 +6816,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
|
||||
|
|
|
@ -73,10 +73,15 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 ast);
|
|||
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf);
|
||||
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
|
||||
|
||||
void HWR_ReadShaders(UINT16 wadnum, boolean PK3);
|
||||
boolean HWR_LoadShaders(void);
|
||||
boolean HWR_CompileShaders(void);
|
||||
|
||||
extern CV_PossibleValue_t granisotropicmode_cons_t[];
|
||||
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 glanisotropicmode_cons_t[];
|
||||
|
||||
#ifdef ALAM_LIGHTING
|
||||
extern consvar_t cv_gldynamiclighting;
|
||||
|
@ -85,7 +90,7 @@ extern consvar_t cv_glcoronas;
|
|||
extern consvar_t cv_glcoronasize;
|
||||
#endif
|
||||
|
||||
extern consvar_t cv_glshaders;
|
||||
extern consvar_t cv_glshaders, cv_glallowshaders;
|
||||
extern consvar_t cv_glmodels;
|
||||
extern consvar_t cv_glmodelinterpolation;
|
||||
extern consvar_t cv_glmodellighting;
|
||||
|
@ -111,21 +116,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_init;
|
||||
extern boolean gl_maploaded;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -503,11 +519,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);
|
||||
|
||||
|
@ -579,9 +599,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
|
||||
|
@ -634,9 +658,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!
|
||||
|
@ -1601,7 +1629,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,12 +91,6 @@ static GLuint startScreenWipe = 0;
|
|||
static GLuint endScreenWipe = 0;
|
||||
static GLuint finalScreenTexture = 0;
|
||||
|
||||
// Lactozilla: Set shader programs and uniforms
|
||||
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 GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
// shortcut for ((float)1/i)
|
||||
static const GLfloat byte2float[256] = {
|
||||
0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f,
|
||||
|
@ -536,8 +530,8 @@ boolean SetupGLfunc(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
static boolean gl_allowshaders = false;
|
||||
static boolean gl_shadersenabled = false;
|
||||
static hwdshaderoption_t gl_allowshaders = HWD_SHADEROPTION_OFF;
|
||||
|
||||
#ifdef GL_SHADERS
|
||||
typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum);
|
||||
|
@ -547,6 +541,7 @@ typedef void (APIENTRY *PFNglGetShaderiv) (GLuint, GLenum, GLint*);
|
|||
typedef void (APIENTRY *PFNglGetShaderInfoLog) (GLuint, GLsizei, GLsizei*, GLchar*);
|
||||
typedef void (APIENTRY *PFNglDeleteShader) (GLuint);
|
||||
typedef GLuint (APIENTRY *PFNglCreateProgram) (void);
|
||||
typedef void (APIENTRY *PFNglDeleteProgram) (GLuint);
|
||||
typedef void (APIENTRY *PFNglAttachShader) (GLuint, GLuint);
|
||||
typedef void (APIENTRY *PFNglLinkProgram) (GLuint);
|
||||
typedef void (APIENTRY *PFNglGetProgramiv) (GLuint, GLenum, GLint*);
|
||||
|
@ -568,6 +563,7 @@ static PFNglGetShaderiv pglGetShaderiv;
|
|||
static PFNglGetShaderInfoLog pglGetShaderInfoLog;
|
||||
static PFNglDeleteShader pglDeleteShader;
|
||||
static PFNglCreateProgram pglCreateProgram;
|
||||
static PFNglDeleteProgram pglDeleteProgram;
|
||||
static PFNglAttachShader pglAttachShader;
|
||||
static PFNglLinkProgram pglLinkProgram;
|
||||
static PFNglGetProgramiv pglGetProgramiv;
|
||||
|
@ -582,15 +578,6 @@ 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;
|
||||
|
||||
// 13062019
|
||||
typedef enum
|
||||
{
|
||||
|
@ -608,23 +595,85 @@ typedef enum
|
|||
gluniform_max,
|
||||
} gluniform_t;
|
||||
|
||||
typedef struct gl_shaderprogram_s
|
||||
typedef struct gl_shader_s
|
||||
{
|
||||
GLuint program;
|
||||
boolean custom;
|
||||
GLint uniforms[gluniform_max+1];
|
||||
} gl_shaderprogram_t;
|
||||
static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS];
|
||||
boolean custom;
|
||||
} gl_shader_t;
|
||||
|
||||
static gl_shader_t gl_shaders[HWR_MAXSHADERS];
|
||||
static gl_shader_t gl_usershaders[HWR_MAXSHADERS];
|
||||
static shadersource_t gl_customshaders[HWR_MAXSHADERS];
|
||||
|
||||
// 09102020
|
||||
typedef struct gl_shaderstate_s
|
||||
{
|
||||
gl_shader_t *current;
|
||||
GLuint type;
|
||||
GLuint program;
|
||||
boolean changed;
|
||||
} gl_shaderstate_t;
|
||||
static gl_shaderstate_t gl_shaderstate;
|
||||
|
||||
// Shader info
|
||||
static INT32 shader_leveltime = 0;
|
||||
|
||||
// ========================
|
||||
// Fragment shader macros
|
||||
// ========================
|
||||
// Lactozilla: Shader functions
|
||||
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader);
|
||||
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum);
|
||||
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade);
|
||||
|
||||
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
// ================
|
||||
// Vertex shaders
|
||||
// ================
|
||||
|
||||
//
|
||||
// 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 \
|
||||
|
@ -765,22 +814,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" \
|
||||
|
@ -788,97 +825,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
|
||||
|
@ -907,6 +889,7 @@ void SetupGLFunc4(void)
|
|||
pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog");
|
||||
pglDeleteShader = GetGLFunc("glDeleteShader");
|
||||
pglCreateProgram = GetGLFunc("glCreateProgram");
|
||||
pglDeleteProgram = GetGLFunc("glDeleteProgram");
|
||||
pglAttachShader = GetGLFunc("glAttachShader");
|
||||
pglLinkProgram = GetGLFunc("glLinkProgram");
|
||||
pglGetProgramiv = GetGLFunc("glGetProgramiv");
|
||||
|
@ -927,136 +910,63 @@ void SetupGLFunc4(void)
|
|||
}
|
||||
|
||||
// jimita
|
||||
EXPORT boolean HWRAPI(LoadShaders) (void)
|
||||
EXPORT boolean HWRAPI(CompileShaders) (void)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
GLuint gl_vertShader, gl_fragShader;
|
||||
GLint i, result;
|
||||
GLint i;
|
||||
|
||||
if (!pglUseProgram) return false;
|
||||
if (!pglUseProgram)
|
||||
return false;
|
||||
|
||||
gl_customvertexshaders[0] = NULL;
|
||||
gl_customfragmentshaders[0] = NULL;
|
||||
gl_customshaders[SHADER_DEFAULT].vertex = NULL;
|
||||
gl_customshaders[SHADER_DEFAULT].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));
|
||||
gl_shader_t *shader, *usershader;
|
||||
const GLchar *vert_shader = gl_shadersources[i].vertex;
|
||||
const GLchar *frag_shader = gl_shadersources[i].fragment;
|
||||
|
||||
if (i >= HWR_MAXSHADERS)
|
||||
break;
|
||||
|
||||
shader = &gl_shaders[i];
|
||||
usershader = &gl_usershaders[i];
|
||||
|
||||
if (shader->program)
|
||||
pglDeleteProgram(shader->program);
|
||||
if (usershader->program)
|
||||
pglDeleteProgram(usershader->program);
|
||||
|
||||
shader->program = 0;
|
||||
usershader->program = 0;
|
||||
|
||||
if (!Shader_CompileProgram(shader, i, vert_shader, frag_shader))
|
||||
shader->program = 0;
|
||||
|
||||
// Compile custom shader
|
||||
if ((i == SHADER_DEFAULT) || !(gl_customshaders[i].vertex || gl_customshaders[i].fragment))
|
||||
continue;
|
||||
|
||||
// 18032019
|
||||
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)
|
||||
break;
|
||||
|
||||
shader = &gl_shaderprograms[i];
|
||||
shader->program = 0;
|
||||
shader->custom = custom;
|
||||
|
||||
//
|
||||
// Load and compile vertex shader
|
||||
//
|
||||
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
|
||||
if (!gl_vertShader)
|
||||
if (!Shader_CompileProgram(usershader, i, vert_shader, frag_shader))
|
||||
{
|
||||
GL_MSG_Error("LoadShaders: Error creating vertex shader %d\n", i);
|
||||
continue;
|
||||
GL_MSG_Warning("CompileShaders: Could not compile custom shader program for %s\n", HWR_GetShaderName(i));
|
||||
usershader->program = 0;
|
||||
}
|
||||
|
||||
pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
|
||||
pglCompileShader(gl_vertShader);
|
||||
|
||||
// check for compile errors
|
||||
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Load and compile fragment shader
|
||||
//
|
||||
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!gl_fragShader)
|
||||
{
|
||||
GL_MSG_Error("LoadShaders: Error creating fragment shader %d\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
|
||||
pglCompileShader(gl_fragShader);
|
||||
|
||||
// check for compile errors
|
||||
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
shader->program = pglCreateProgram();
|
||||
pglAttachShader(shader->program, gl_vertShader);
|
||||
pglAttachShader(shader->program, gl_fragShader);
|
||||
pglLinkProgram(shader->program);
|
||||
|
||||
// check link status
|
||||
pglGetProgramiv(shader->program, GL_LINK_STATUS, &result);
|
||||
|
||||
// delete the shader objects
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
|
||||
// couldn't link?
|
||||
if (result != GL_TRUE)
|
||||
{
|
||||
shader->program = 0;
|
||||
shader->custom = false;
|
||||
GL_MSG_Error("LoadShaders: Error linking shader program %d\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 13062019
|
||||
#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform);
|
||||
|
||||
// lighting
|
||||
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
|
||||
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
|
||||
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
|
||||
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
|
||||
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
|
||||
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
|
||||
|
||||
// misc. (custom shaders)
|
||||
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
|
||||
|
||||
#undef GETUNI
|
||||
}
|
||||
#endif
|
||||
|
||||
SetShader(SHADER_DEFAULT);
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1084,25 +994,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;
|
||||
|
@ -1111,34 +1030,45 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boo
|
|||
#endif
|
||||
}
|
||||
|
||||
EXPORT boolean HWRAPI(InitCustomShaders) (void)
|
||||
EXPORT void HWRAPI(SetShader) (int type)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
KillShaders();
|
||||
return LoadShaders();
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT void HWRAPI(SetShader) (int shader)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
if (gl_allowshaders)
|
||||
if (gl_allowshaders != HWD_SHADEROPTION_OFF)
|
||||
{
|
||||
gl_shader_t *shader = gl_shaderstate.current;
|
||||
|
||||
// If using model lighting, set the appropriate shader.
|
||||
// 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 ((GLuint)shader != gl_currentshaderprogram)
|
||||
if (type == SHADER_MODEL && model_lighting
|
||||
&& !(gl_shaders[SHADER_MODEL].custom && !gl_shaders[SHADER_MODEL_LIGHTING].custom))
|
||||
type = SHADER_MODEL_LIGHTING;
|
||||
|
||||
if ((shader == NULL) || (GLuint)type != gl_shaderstate.type)
|
||||
{
|
||||
gl_currentshaderprogram = shader;
|
||||
gl_shaderprogramchanged = true;
|
||||
gl_shader_t *baseshader = &gl_shaders[type];
|
||||
gl_shader_t *usershader = &gl_usershaders[type];
|
||||
|
||||
if (usershader->program)
|
||||
shader = (gl_allowshaders == HWD_SHADEROPTION_NOCUSTOM) ? baseshader : usershader;
|
||||
else
|
||||
shader = baseshader;
|
||||
|
||||
gl_shaderstate.current = shader;
|
||||
gl_shaderstate.type = type;
|
||||
gl_shaderstate.changed = true;
|
||||
}
|
||||
gl_shadersenabled = true;
|
||||
|
||||
if (gl_shaderstate.program != shader->program)
|
||||
{
|
||||
gl_shaderstate.program = shader->program;
|
||||
gl_shaderstate.changed = true;
|
||||
}
|
||||
|
||||
gl_shadersenabled = (shader->program != 0);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
(void)shader;
|
||||
(void)type;
|
||||
#endif
|
||||
gl_shadersenabled = false;
|
||||
}
|
||||
|
@ -1146,16 +1076,34 @@ EXPORT void HWRAPI(SetShader) (int shader)
|
|||
EXPORT void HWRAPI(UnSetShader) (void)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
gl_shadersenabled = false;
|
||||
gl_currentshaderprogram = 0;
|
||||
if (!pglUseProgram) return;
|
||||
pglUseProgram(0);
|
||||
gl_shaderstate.current = NULL;
|
||||
gl_shaderstate.type = 0;
|
||||
gl_shaderstate.program = 0;
|
||||
|
||||
if (pglUseProgram)
|
||||
pglUseProgram(0);
|
||||
#endif
|
||||
|
||||
gl_shadersenabled = false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
|
@ -1992,42 +1940,24 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
|
|||
}
|
||||
}
|
||||
|
||||
static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
if (gl_shadersenabled && pglUseProgram)
|
||||
{
|
||||
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
|
||||
if (shader->program)
|
||||
{
|
||||
if (gl_shaderprogramchanged)
|
||||
{
|
||||
pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program);
|
||||
gl_shaderprogramchanged = false;
|
||||
}
|
||||
Shader_SetUniforms(Surface, poly, tint, fade);
|
||||
return shader;
|
||||
}
|
||||
else
|
||||
pglUseProgram(0);
|
||||
}
|
||||
#else
|
||||
(void)Surface;
|
||||
(void)poly;
|
||||
(void)tint;
|
||||
(void)fade;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade)
|
||||
{
|
||||
#ifdef GL_SHADERS
|
||||
if (gl_shadersenabled)
|
||||
gl_shader_t *shader = gl_shaderstate.current;
|
||||
|
||||
if (gl_shadersenabled && (shader != NULL) && pglUseProgram)
|
||||
{
|
||||
gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram];
|
||||
if (!shader->program)
|
||||
{
|
||||
pglUseProgram(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gl_shaderstate.changed)
|
||||
{
|
||||
pglUseProgram(shader->program);
|
||||
gl_shaderstate.changed = false;
|
||||
}
|
||||
|
||||
// Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f)
|
||||
if (poly == NULL)
|
||||
|
@ -2080,6 +2010,116 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
|
|||
#endif
|
||||
}
|
||||
|
||||
static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader)
|
||||
{
|
||||
GLuint gl_vertShader, gl_fragShader;
|
||||
GLint result;
|
||||
|
||||
//
|
||||
// Load and compile vertex shader
|
||||
//
|
||||
gl_vertShader = pglCreateShader(GL_VERTEX_SHADER);
|
||||
if (!gl_vertShader)
|
||||
{
|
||||
GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i));
|
||||
return false;
|
||||
}
|
||||
|
||||
pglShaderSource(gl_vertShader, 1, &vert_shader, NULL);
|
||||
pglCompileShader(gl_vertShader);
|
||||
|
||||
// check for compile errors
|
||||
pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
Shader_CompileError("Error compiling vertex shader", gl_vertShader, i);
|
||||
pglDeleteShader(gl_vertShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Load and compile fragment shader
|
||||
//
|
||||
gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!gl_fragShader)
|
||||
{
|
||||
GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i));
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
pglShaderSource(gl_fragShader, 1, &frag_shader, NULL);
|
||||
pglCompileShader(gl_fragShader);
|
||||
|
||||
// check for compile errors
|
||||
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
Shader_CompileError("Error compiling fragment shader", gl_fragShader, i);
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
shader->program = pglCreateProgram();
|
||||
pglAttachShader(shader->program, gl_vertShader);
|
||||
pglAttachShader(shader->program, gl_fragShader);
|
||||
pglLinkProgram(shader->program);
|
||||
|
||||
// check link status
|
||||
pglGetProgramiv(shader->program, GL_LINK_STATUS, &result);
|
||||
|
||||
// delete the shader objects
|
||||
pglDeleteShader(gl_vertShader);
|
||||
pglDeleteShader(gl_fragShader);
|
||||
|
||||
// couldn't link?
|
||||
if (result != GL_TRUE)
|
||||
{
|
||||
GL_MSG_Error("Shader_CompileProgram: Error linking shader program %s\n", HWR_GetShaderName(i));
|
||||
pglDeleteProgram(shader->program);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 13062019
|
||||
#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform);
|
||||
|
||||
// lighting
|
||||
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
|
||||
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
|
||||
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
|
||||
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
|
||||
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
|
||||
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
|
||||
|
||||
// misc. (custom shaders)
|
||||
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
|
||||
|
||||
#undef GETUNI
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum)
|
||||
{
|
||||
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("Shader_CompileProgram: %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)
|
||||
|
@ -2184,7 +2224,7 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD
|
|||
pglColor4ubv(c);
|
||||
}
|
||||
|
||||
Shader_Load(pSurf, &poly, &tint, &fade);
|
||||
Shader_SetUniforms(pSurf, &poly, &tint, &fade);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
|
@ -2230,7 +2270,7 @@ EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky)
|
|||
{
|
||||
int i, j;
|
||||
|
||||
Shader_Load(NULL, NULL, NULL, NULL);
|
||||
Shader_SetUniforms(NULL, NULL, NULL, NULL);
|
||||
|
||||
// Build the sky dome! Yes!
|
||||
if (sky->rebuild)
|
||||
|
@ -2322,15 +2362,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
|
|||
break;
|
||||
|
||||
case HWD_SET_SHADERS:
|
||||
switch (Value)
|
||||
{
|
||||
case 1:
|
||||
gl_allowshaders = true;
|
||||
break;
|
||||
default:
|
||||
gl_allowshaders = false;
|
||||
break;
|
||||
}
|
||||
gl_allowshaders = (hwdshaderoption_t)Value;
|
||||
break;
|
||||
|
||||
case HWD_SET_TEXTUREFILTERMODE:
|
||||
|
@ -2685,7 +2717,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
|
|||
flags |= (PF_Occlude | PF_Masked);
|
||||
|
||||
SetBlend(flags);
|
||||
Shader_Load(Surface, &poly, &tint, &fade);
|
||||
Shader_SetUniforms(Surface, &poly, &tint, &fade);
|
||||
|
||||
pglEnable(GL_CULL_FACE);
|
||||
pglEnable(GL_NORMALIZE);
|
||||
|
|
|
@ -2120,7 +2120,7 @@ void HU_Drawer(void)
|
|||
HU_DrawCrosshair2();
|
||||
|
||||
// draw desynch text
|
||||
if (hu_resynching)
|
||||
if (hu_redownloadinggamestate)
|
||||
{
|
||||
static UINT32 resynch_ticker = 0;
|
||||
char resynch_text[14];
|
||||
|
|
|
@ -584,6 +584,7 @@ char spr2names[NUMPLAYERSPRITES][5] =
|
|||
"TAL9",
|
||||
"TALA",
|
||||
"TALB",
|
||||
"TALC",
|
||||
|
||||
"CNT1",
|
||||
"CNT2",
|
||||
|
@ -661,6 +662,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
SPR2_TAL0, // SPR2_TAL9,
|
||||
SPR2_TAL9, // SPR2_TALA,
|
||||
SPR2_TAL0, // SPR2_TALB,
|
||||
SPR2_TAL6, // SPR2_TALC,
|
||||
|
||||
SPR2_WAIT, // SPR2_CNT1,
|
||||
SPR2_FALL, // SPR2_CNT2,
|
||||
|
@ -801,6 +803,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN}, // S_TAILSOVERLAY_PAIN
|
||||
{SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_GASP}, // S_TAILSOVERLAY_GASP
|
||||
{SPR_PLAY, SPR2_TALB , 35, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE}, // S_TAILSOVERLAY_EDGE
|
||||
{SPR_PLAY, SPR2_TALC|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_DASH}, // S_TAILSOVERLAY_DASH
|
||||
|
||||
// [:
|
||||
{SPR_JETF, 3|FF_ANIMATE|FF_FULLBRIGHT, 2, {NULL}, 1, 1, S_JETFUME1}, // S_JETFUMEFLASH
|
||||
|
|
|
@ -856,6 +856,7 @@ typedef enum playersprite
|
|||
SPR2_TAL9,
|
||||
SPR2_TALA,
|
||||
SPR2_TALB,
|
||||
SPR2_TALC,
|
||||
|
||||
SPR2_CNT1, // continue disappointment
|
||||
SPR2_CNT2, // continue lift
|
||||
|
@ -997,6 +998,7 @@ typedef enum state
|
|||
S_TAILSOVERLAY_PAIN,
|
||||
S_TAILSOVERLAY_GASP,
|
||||
S_TAILSOVERLAY_EDGE,
|
||||
S_TAILSOVERLAY_DASH,
|
||||
|
||||
// [:
|
||||
S_JETFUMEFLASH,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "lua_script.h"
|
||||
#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)\
|
||||
|
@ -173,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"},
|
||||
|
@ -241,6 +247,56 @@ static int lib_userdataType(lua_State *L)
|
|||
return luaL_typerror(L, 1, "userdata");
|
||||
}
|
||||
|
||||
// Takes a metatable as first and only argument
|
||||
// Only callable during script loading
|
||||
static int lib_registerMetatable(lua_State *L)
|
||||
{
|
||||
static UINT16 nextid = 1;
|
||||
|
||||
if (!lua_lumploading)
|
||||
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
if (nextid == 0)
|
||||
return luaL_error(L, "Too many metatables registered?! Please consider rewriting your script once you are sober again.\n");
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_METATABLES); // 2
|
||||
// registry.metatables[metatable] = nextid
|
||||
lua_pushvalue(L, 1); // 3
|
||||
lua_pushnumber(L, nextid); // 4
|
||||
lua_settable(L, 2);
|
||||
|
||||
// registry.metatables[nextid] = metatable
|
||||
lua_pushnumber(L, nextid); // 3
|
||||
lua_pushvalue(L, 1); // 4
|
||||
lua_settable(L, 2);
|
||||
lua_pop(L, 1);
|
||||
|
||||
nextid++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Takes a string as only argument and returns the metatable
|
||||
// associated to the userdata type this string refers to
|
||||
// Returns nil if the string does not refer to a valid userdata type
|
||||
static int lib_userdataMetatable(lua_State *L)
|
||||
{
|
||||
UINT32 i;
|
||||
const char *udname = luaL_checkstring(L, 1);
|
||||
|
||||
// Find internal metatable name
|
||||
for (i = 0; meta2utype[i].meta; i++)
|
||||
if (!strcmp(udname, meta2utype[i].utype))
|
||||
{
|
||||
luaL_getmetatable(L, meta2utype[i].meta);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_isPlayerAdmin(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
@ -1752,6 +1808,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));
|
||||
|
@ -3011,6 +3079,185 @@ static int lib_sStartMusicCaption(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_sMusicType(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushinteger(L, S_MusicType());
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sMusicPlaying(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushboolean(L, S_MusicPlaying());
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sMusicPaused(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushboolean(L, S_MusicPaused());
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sMusicName(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushstring(L, S_MusicName());
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sMusicExists(lua_State *L)
|
||||
{
|
||||
boolean checkMIDI = lua_opttrueboolean(L, 2);
|
||||
boolean checkDigi = lua_opttrueboolean(L, 3);
|
||||
#ifdef MUSICSLOT_COMPATIBILITY
|
||||
const char *music_name;
|
||||
UINT32 music_num;
|
||||
char music_compat_name[7];
|
||||
UINT16 music_flags = 0;
|
||||
NOHUD
|
||||
if (lua_isnumber(L, 1))
|
||||
{
|
||||
music_num = (UINT32)luaL_checkinteger(L, 1);
|
||||
music_flags = (UINT16)(music_num & 0x0000FFFF);
|
||||
if (music_flags && music_flags <= 1035)
|
||||
snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
|
||||
else if (music_flags && music_flags <= 1050)
|
||||
strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
|
||||
else
|
||||
music_compat_name[0] = 0; // becomes empty string
|
||||
music_compat_name[6] = 0;
|
||||
music_name = (const char *)&music_compat_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
music_num = 0;
|
||||
music_name = luaL_checkstring(L, 1);
|
||||
}
|
||||
#else
|
||||
const char *music_name = luaL_checkstring(L, 1);
|
||||
#endif
|
||||
NOHUD
|
||||
lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sSetMusicLoopPoint(lua_State *L)
|
||||
{
|
||||
UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1);
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushboolean(L, S_SetMusicLoopPoint(looppoint));
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sGetMusicLoopPoint(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushinteger(L, (int)S_GetMusicLoopPoint());
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sPauseMusic(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
{
|
||||
S_PauseAudio();
|
||||
lua_pushboolean(L, true);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sResumeMusic(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
{
|
||||
S_ResumeAudio();
|
||||
lua_pushboolean(L, true);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// G_GAME
|
||||
////////////
|
||||
|
||||
|
@ -3499,6 +3746,8 @@ static luaL_Reg lib[] = {
|
|||
{"chatprint", lib_chatprint},
|
||||
{"chatprintf", lib_chatprintf},
|
||||
{"userdataType", lib_userdataType},
|
||||
{"registerMetatable", lib_registerMetatable},
|
||||
{"userdataMetatable", lib_userdataMetatable},
|
||||
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
||||
{"reserveLuabanks", lib_reserveLuabanks},
|
||||
|
||||
|
@ -3628,6 +3877,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
|
||||
|
@ -3718,6 +3968,15 @@ static luaL_Reg lib[] = {
|
|||
{"S_IdPlaying",lib_sIdPlaying},
|
||||
{"S_SoundPlaying",lib_sSoundPlaying},
|
||||
{"S_StartMusicCaption", lib_sStartMusicCaption},
|
||||
{"S_MusicType",lib_sMusicType},
|
||||
{"S_MusicPlaying",lib_sMusicPlaying},
|
||||
{"S_MusicPaused",lib_sMusicPaused},
|
||||
{"S_MusicName",lib_sMusicName},
|
||||
{"S_MusicExists",lib_sMusicExists},
|
||||
{"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint},
|
||||
{"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint},
|
||||
{"S_PauseMusic",lib_sPauseMusic},
|
||||
{"S_ResumeMusic", lib_sResumeMusic},
|
||||
|
||||
// g_game
|
||||
{"G_AddGametype", lib_gAddGametype},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -432,6 +432,54 @@ 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);
|
||||
|
||||
if (cvar->flags & CV_NOLUA)
|
||||
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
|
||||
|
||||
switch (lua_type(L, 2))
|
||||
{
|
||||
case LUA_TSTRING:
|
||||
(*Set)(cvar, lua_tostring(L, 2));
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
(*SetValue)(cvar, (INT32)lua_tonumber(L, 2));
|
||||
break;
|
||||
default:
|
||||
return luaL_typerror(L, 1, "string or number");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_cvSet(lua_State *L)
|
||||
{
|
||||
return CVarSetFunction(L, CV_Set, CV_SetValue);
|
||||
}
|
||||
|
||||
static int lib_cvStealthSet(lua_State *L)
|
||||
{
|
||||
return CVarSetFunction(L, CV_StealthSet, CV_StealthSetValue);
|
||||
}
|
||||
|
||||
static int lib_cvAddValue(lua_State *L)
|
||||
{
|
||||
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
|
||||
|
||||
if (cvar->flags & CV_NOLUA)
|
||||
return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name);
|
||||
|
||||
CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CONS_Printf for a single player
|
||||
// Use 'print' in baselib for a global message.
|
||||
static int lib_consPrintf(lua_State *L)
|
||||
|
@ -472,6 +520,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}
|
||||
};
|
||||
|
|
|
@ -60,6 +60,7 @@ enum hook {
|
|||
hook_ShouldJingleContinue,
|
||||
hook_GameQuit,
|
||||
hook_PlayerCmd,
|
||||
hook_MusicChange,
|
||||
|
||||
hook_MAX // last hook
|
||||
};
|
||||
|
@ -118,3 +119,4 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_
|
|||
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
|
||||
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart)
|
||||
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes
|
|
@ -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] = {
|
||||
|
@ -72,6 +76,7 @@ const char *const hookNames[hook_MAX+1] = {
|
|||
"ShouldJingleContinue",
|
||||
"GameQuit",
|
||||
"PlayerCmd",
|
||||
"MusicChange",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -260,6 +265,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);
|
||||
|
||||
|
@ -269,6 +277,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);
|
||||
|
@ -290,6 +299,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);
|
||||
|
@ -325,6 +335,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);
|
||||
|
@ -456,6 +467,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;
|
||||
|
||||
|
@ -466,6 +480,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)
|
||||
|
@ -473,6 +489,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
|
||||
|
@ -514,6 +540,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);
|
||||
|
||||
|
@ -523,6 +552,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);
|
||||
|
@ -553,6 +583,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);
|
||||
|
@ -591,6 +622,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);
|
||||
|
||||
|
@ -600,6 +634,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);
|
||||
|
@ -630,6 +665,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);
|
||||
|
@ -669,12 +705,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);
|
||||
|
@ -693,6 +733,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);
|
||||
|
@ -719,10 +760,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);
|
||||
|
||||
|
@ -732,6 +776,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);
|
||||
|
@ -757,6 +802,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);
|
||||
|
@ -791,6 +837,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);
|
||||
|
||||
|
@ -800,6 +849,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);
|
||||
|
@ -835,6 +885,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);
|
||||
|
@ -876,10 +927,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);
|
||||
|
||||
|
@ -889,6 +943,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);
|
||||
|
@ -920,6 +975,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);
|
||||
|
@ -956,10 +1012,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);
|
||||
|
||||
|
@ -969,6 +1028,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);
|
||||
|
@ -998,6 +1058,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);
|
||||
|
@ -1190,6 +1251,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);
|
||||
|
@ -1355,6 +1417,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);
|
||||
|
||||
|
@ -1364,6 +1429,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);
|
||||
|
@ -1389,6 +1455,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);
|
||||
|
@ -1421,6 +1488,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);
|
||||
|
||||
|
@ -1430,6 +1500,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);
|
||||
|
@ -1455,6 +1526,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);
|
||||
|
@ -1495,6 +1567,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);
|
||||
|
@ -1840,3 +1913,62 @@ boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd)
|
|||
hook_cmd_running = false;
|
||||
return hooked;
|
||||
}
|
||||
|
||||
// Hook for music changes
|
||||
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
|
||||
UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms)
|
||||
{
|
||||
hook_p hookp;
|
||||
boolean hooked = false;
|
||||
|
||||
if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8))))
|
||||
return false;
|
||||
|
||||
lua_settop(gL, 0);
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_MusicChange)
|
||||
{
|
||||
PushHook(gL, hookp);
|
||||
lua_pushstring(gL, oldname);
|
||||
lua_pushstring(gL, newname);
|
||||
lua_pushinteger(gL, *mflags);
|
||||
lua_pushboolean(gL, *looping);
|
||||
lua_pushinteger(gL, *position);
|
||||
lua_pushinteger(gL, *prefadems);
|
||||
lua_pushinteger(gL, *fadeinms);
|
||||
if (lua_pcall(gL, 7, 6, 1)) {
|
||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
|
||||
lua_pop(gL, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// output 1: true, false, or string musicname override
|
||||
if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6))
|
||||
hooked = true;
|
||||
else if (lua_isstring(gL, -6))
|
||||
strncpy(newname, lua_tostring(gL, -6), 7);
|
||||
// output 2: mflags override
|
||||
if (lua_isnumber(gL, -5))
|
||||
*mflags = lua_tonumber(gL, -5);
|
||||
// output 3: looping override
|
||||
if (lua_isboolean(gL, -4))
|
||||
*looping = lua_toboolean(gL, -4);
|
||||
// output 4: position override
|
||||
if (lua_isboolean(gL, -3))
|
||||
*position = lua_tonumber(gL, -3);
|
||||
// output 5: prefadems override
|
||||
if (lua_isboolean(gL, -2))
|
||||
*prefadems = lua_tonumber(gL, -2);
|
||||
// output 6: fadeinms override
|
||||
if (lua_isboolean(gL, -1))
|
||||
*fadeinms = lua_tonumber(gL, -1);
|
||||
|
||||
lua_pop(gL, 7); // Pop returned values and error handler
|
||||
}
|
||||
|
||||
lua_settop(gL, 0);
|
||||
newname[6] = 0;
|
||||
return hooked;
|
||||
}
|
|
@ -16,6 +16,7 @@ extern lua_State *gL;
|
|||
#define LREG_EXTVARS "LUA_VARS"
|
||||
#define LREG_STATEACTION "STATE_ACTION"
|
||||
#define LREG_ACTIONS "MOBJ_ACTION"
|
||||
#define LREG_METATABLES "METATABLES"
|
||||
|
||||
#define META_STATE "STATE_T*"
|
||||
#define META_MOBJINFO "MOBJINFO_T*"
|
||||
|
@ -50,6 +51,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 +61,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 +93,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);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "p_setup.h"
|
||||
#include "z_zone.h"
|
||||
#include "p_slopes.h"
|
||||
#include "p_polyobj.h"
|
||||
#include "r_main.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
|
@ -68,6 +69,7 @@ enum subsector_e {
|
|||
subsector_sector,
|
||||
subsector_numlines,
|
||||
subsector_firstline,
|
||||
subsector_polyList
|
||||
};
|
||||
|
||||
static const char *const subsector_opt[] = {
|
||||
|
@ -75,6 +77,7 @@ static const char *const subsector_opt[] = {
|
|||
"sector",
|
||||
"numlines",
|
||||
"firstline",
|
||||
"polyList",
|
||||
NULL};
|
||||
|
||||
enum line_e {
|
||||
|
@ -96,8 +99,7 @@ enum line_e {
|
|||
line_slopetype,
|
||||
line_frontsector,
|
||||
line_backsector,
|
||||
line_firsttag,
|
||||
line_nexttag,
|
||||
line_polyobj,
|
||||
line_text,
|
||||
line_callcount
|
||||
};
|
||||
|
@ -121,8 +123,7 @@ static const char *const line_opt[] = {
|
|||
"slopetype",
|
||||
"frontsector",
|
||||
"backsector",
|
||||
"firsttag",
|
||||
"nexttag",
|
||||
"polyobj",
|
||||
"text",
|
||||
"callcount",
|
||||
NULL};
|
||||
|
@ -223,6 +224,7 @@ enum seg_e {
|
|||
seg_linedef,
|
||||
seg_frontsector,
|
||||
seg_backsector,
|
||||
seg_polyseg
|
||||
};
|
||||
|
||||
static const char *const seg_opt[] = {
|
||||
|
@ -236,6 +238,7 @@ static const char *const seg_opt[] = {
|
|||
"linedef",
|
||||
"frontsector",
|
||||
"backsector",
|
||||
"polyseg",
|
||||
NULL};
|
||||
|
||||
enum node_e {
|
||||
|
@ -325,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)
|
||||
|
@ -399,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"
|
||||
|
@ -447,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
|
||||
|
@ -481,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;
|
||||
}
|
||||
|
@ -541,7 +579,7 @@ static int sector_get(lua_State *L)
|
|||
lua_pushinteger(L, sector->special);
|
||||
return 1;
|
||||
case sector_tag:
|
||||
lua_pushinteger(L, sector->tag);
|
||||
lua_pushinteger(L, Tag_FGet(§or->tags));
|
||||
return 1;
|
||||
case sector_thinglist: // thinglist
|
||||
lua_pushcfunction(L, lib_iterateSectorThinglist);
|
||||
|
@ -642,7 +680,7 @@ static int sector_set(lua_State *L)
|
|||
sector->special = (INT16)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case sector_tag:
|
||||
P_ChangeSectorTag((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
|
||||
Tag_SectorFSet((UINT32)(sector - sectors), (INT16)luaL_checkinteger(L, 3));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -687,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;
|
||||
}
|
||||
|
@ -776,7 +819,7 @@ static int line_get(lua_State *L)
|
|||
lua_pushinteger(L, line->special);
|
||||
return 1;
|
||||
case line_tag:
|
||||
lua_pushinteger(L, line->tag);
|
||||
lua_pushinteger(L, Tag_FGet(&line->tags));
|
||||
return 1;
|
||||
case line_args:
|
||||
LUA_PushUserdata(L, line->args, META_LINEARGS);
|
||||
|
@ -824,11 +867,8 @@ static int line_get(lua_State *L)
|
|||
case line_backsector:
|
||||
LUA_PushUserdata(L, line->backsector, META_SECTOR);
|
||||
return 1;
|
||||
case line_firsttag:
|
||||
lua_pushinteger(L, line->firsttag);
|
||||
return 1;
|
||||
case line_nexttag:
|
||||
lua_pushinteger(L, line->nexttag);
|
||||
case line_polyobj:
|
||||
LUA_PushUserdata(L, line->polyobj, META_POLYOBJ);
|
||||
return 1;
|
||||
case line_text:
|
||||
lua_pushstring(L, line->text);
|
||||
|
@ -1092,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;
|
||||
}
|
||||
|
|
|
@ -903,7 +903,7 @@ static int mapthing_get(lua_State *L)
|
|||
else if(fastcmp(field,"extrainfo"))
|
||||
number = mt->extrainfo;
|
||||
else if(fastcmp(field,"tag"))
|
||||
number = mt->tag;
|
||||
number = Tag_FGet(&mt->tags);
|
||||
else if(fastcmp(field,"args"))
|
||||
{
|
||||
LUA_PushUserdata(L, mt->args, META_THINGARGS);
|
||||
|
@ -965,7 +965,7 @@ static int mapthing_set(lua_State *L)
|
|||
mt->extrainfo = (UINT8)extrainfo;
|
||||
}
|
||||
else if (fastcmp(field,"tag"))
|
||||
mt->tag = (INT16)luaL_checkinteger(L, 3);
|
||||
Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3));
|
||||
else if(fastcmp(field,"mobj"))
|
||||
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
else
|
||||
|
|
486
src/lua_polyobjlib.c
Normal file
486
src/lua_polyobjlib.c
Normal 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;
|
||||
}
|
|
@ -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
|
||||
|
@ -33,6 +34,7 @@
|
|||
#include "lua_hook.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
#include "g_state.h"
|
||||
|
||||
lua_State *gL = NULL;
|
||||
|
||||
|
@ -50,6 +52,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
|
||||
|
@ -359,6 +362,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word, "token")) {
|
||||
lua_pushinteger(L, token);
|
||||
return 1;
|
||||
} else if (fastcmp(word, "gamestate")) {
|
||||
lua_pushinteger(L, gamestate);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -437,6 +443,10 @@ static void LUA_ClearState(void)
|
|||
lua_newtable(L);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, LREG_VALID);
|
||||
|
||||
// make LREG_METATABLES table for all registered metatables
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, LREG_METATABLES);
|
||||
|
||||
// open srb2 libraries
|
||||
for(i = 0; liblist[i]; i++) {
|
||||
lua_pushcfunction(L, liblist[i]);
|
||||
|
@ -774,6 +784,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 +848,7 @@ enum
|
|||
ARCH_NODE,
|
||||
#endif
|
||||
ARCH_FFLOOR,
|
||||
ARCH_POLYOBJ,
|
||||
ARCH_SLOPE,
|
||||
ARCH_MAPHEADER,
|
||||
ARCH_SKINCOLOR,
|
||||
|
@ -858,6 +875,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},
|
||||
|
@ -966,8 +984,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
|||
lua_pop(gL, 1);
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
t++;
|
||||
|
||||
if (t == 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
|
||||
WRITEUINT8(save_p, ARCH_NULL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
WRITEUINT8(save_p, ARCH_TABLE);
|
||||
WRITEUINT16(save_p, t);
|
||||
|
||||
|
@ -1126,6 +1153,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));
|
||||
|
@ -1269,8 +1307,22 @@ static void ArchiveTables(void)
|
|||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
lua_pop(gL, 1);
|
||||
WRITEUINT8(save_p, ARCH_TEND);
|
||||
|
||||
// Write metatable ID
|
||||
if (lua_getmetatable(gL, -1))
|
||||
{
|
||||
// registry.metatables[metatable]
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
|
||||
lua_pushvalue(gL, -2);
|
||||
lua_gettable(gL, -2);
|
||||
WRITEUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
|
||||
lua_pop(gL, 3);
|
||||
}
|
||||
else
|
||||
WRITEUINT16(save_p, 0);
|
||||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1381,6 +1433,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;
|
||||
|
@ -1438,6 +1493,7 @@ static void UnArchiveTables(void)
|
|||
{
|
||||
int TABLESINDEX;
|
||||
UINT16 i, n;
|
||||
UINT16 metatableid;
|
||||
|
||||
if (!gL)
|
||||
return;
|
||||
|
@ -1462,6 +1518,19 @@ static void UnArchiveTables(void)
|
|||
else
|
||||
lua_rawset(gL, -3);
|
||||
}
|
||||
|
||||
metatableid = READUINT16(save_p);
|
||||
if (metatableid)
|
||||
{
|
||||
// setmetatable(table, registry.metatables[metatableid])
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
|
||||
lua_rawgeti(gL, -1, metatableid);
|
||||
if (lua_isnil(gL, -1))
|
||||
I_Error("Unknown metatable ID %d\n", metatableid);
|
||||
lua_setmetatable(gL, -3);
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,15 +29,21 @@
|
|||
// GIFs are always little-endian
|
||||
#include "byteptr.h"
|
||||
|
||||
CV_PossibleValue_t gif_dynamicdelay_cons_t[] = {
|
||||
{0, "Off"},
|
||||
{1, "On"},
|
||||
{2, "Accurate, experimental"},
|
||||
{0, NULL}};
|
||||
|
||||
consvar_t cv_gif_optimize = CVAR_INIT ("gif_optimize", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_gif_downscale = CVAR_INIT ("gif_downscale", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_gif_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_gif_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, gif_dynamicdelay_cons_t, NULL);
|
||||
consvar_t cv_gif_localcolortable = CVAR_INIT ("gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
#ifdef HAVE_ANIGIF
|
||||
static boolean gif_optimize = false; // So nobody can do something dumb
|
||||
static boolean gif_downscale = false; // like changing cvars mid output
|
||||
static boolean gif_dynamicdelay = false; // and messing something up
|
||||
static UINT8 gif_dynamicdelay = (UINT8)0; // and messing something up
|
||||
|
||||
// Palette handling
|
||||
static boolean gif_localcolortable = false;
|
||||
|
@ -47,7 +53,8 @@ static RGBA_t *gif_framepalette = NULL;
|
|||
|
||||
static FILE *gif_out = NULL;
|
||||
static INT32 gif_frames = 0;
|
||||
static UINT32 gif_prevframems = 0;
|
||||
static UINT32 gif_prevframeus = 0; // "us" is microseconds
|
||||
static UINT32 gif_delayus = 0;
|
||||
static UINT8 gif_writeover = 0;
|
||||
|
||||
|
||||
|
@ -507,7 +514,7 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
|
|||
size_t src = 0, dest = 0;
|
||||
size_t size = (vid.width * vid.height * 3);
|
||||
|
||||
InitColorLUT(&gif_colorlookup, gif_framepalette, true);
|
||||
InitColorLUT(&gif_colorlookup, (gif_localcolortable) ? gif_framepalette : gif_headerpalette, true);
|
||||
|
||||
while (src < size)
|
||||
{
|
||||
|
@ -594,16 +601,30 @@ static void GIF_framewrite(void)
|
|||
|
||||
// screen regions are handled in GIF_lzw
|
||||
{
|
||||
UINT16 delay;
|
||||
UINT16 delay = 0;
|
||||
INT32 startline;
|
||||
|
||||
if (gif_dynamicdelay) {
|
||||
if (gif_dynamicdelay ==(UINT8) 2)
|
||||
{
|
||||
// golden's attempt at creating a "dynamic delay"
|
||||
UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise).
|
||||
gif_delayus += (I_GetTimeMicros() - gif_prevframeus); // increase delay by how much time was spent between last measurement
|
||||
|
||||
if (gif_delayus/1000 >= mingifdelay) // delay is big enough to be able to effect gif frame delay?
|
||||
{
|
||||
int frames = (gif_delayus/1000) / mingifdelay; // get amount of frames to delay.
|
||||
delay = frames; // set the delay to delay that amount of frames.
|
||||
gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency.
|
||||
}
|
||||
}
|
||||
else if (gif_dynamicdelay ==(UINT8) 1)
|
||||
{
|
||||
float delayf = ceil(100.0f/NEWTICRATE);
|
||||
|
||||
delay = (UINT16)((I_GetTimeMicros() - gif_prevframems)/10/1000);
|
||||
if (delay < (int)(delayf))
|
||||
delay = (int)(delayf);
|
||||
delay = (UINT16)((I_GetTimeMicros() - gif_prevframeus)/10/1000);
|
||||
|
||||
if (delay < (UINT16)(delayf))
|
||||
delay = (UINT16)(delayf);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -690,7 +711,7 @@ static void GIF_framewrite(void)
|
|||
}
|
||||
fwrite(gifframe_data, 1, (p - gifframe_data), gif_out);
|
||||
++gif_frames;
|
||||
gif_prevframems = I_GetTimeMicros();
|
||||
gif_prevframeus = I_GetTimeMicros();
|
||||
}
|
||||
|
||||
|
||||
|
@ -711,14 +732,15 @@ INT32 GIF_open(const char *filename)
|
|||
|
||||
gif_optimize = (!!cv_gif_optimize.value);
|
||||
gif_downscale = (!!cv_gif_downscale.value);
|
||||
gif_dynamicdelay = (!!cv_gif_dynamicdelay.value);
|
||||
gif_dynamicdelay = (UINT8)cv_gif_dynamicdelay.value;
|
||||
gif_localcolortable = (!!cv_gif_localcolortable.value);
|
||||
gif_colorprofile = (!!cv_screenshot_colorprofile.value);
|
||||
gif_headerpalette = GIF_getpalette(0);
|
||||
|
||||
GIF_headwrite();
|
||||
gif_frames = 0;
|
||||
gif_prevframems = I_GetTimeMicros();
|
||||
gif_prevframeus = I_GetTimeMicros();
|
||||
gif_delayus = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1108,7 +1108,6 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
|
|||
|
||||
mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
|
||||
mt->scale = player->mo->scale;
|
||||
mt->tag = 0;
|
||||
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
|
||||
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
|
||||
mt->pitch = mt->roll = 0;
|
||||
|
@ -1435,19 +1434,26 @@ void Command_Writethings_f(void)
|
|||
REQUIRE_SINGLEPLAYER;
|
||||
REQUIRE_OBJECTPLACE;
|
||||
|
||||
P_WriteThings(W_GetNumForName(G_BuildMapName(gamemap)) + ML_THINGS);
|
||||
P_WriteThings();
|
||||
}
|
||||
|
||||
void Command_ObjectPlace_f(void)
|
||||
{
|
||||
size_t thingarg;
|
||||
size_t silent;
|
||||
|
||||
REQUIRE_INLEVEL;
|
||||
REQUIRE_SINGLEPLAYER;
|
||||
REQUIRE_NOULTIMATE;
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
|
||||
silent = COM_CheckParm("-silent");
|
||||
|
||||
thingarg = 2 - ( silent != 1 );
|
||||
|
||||
// Entering objectplace?
|
||||
if (!objectplacing || COM_Argc() > 1)
|
||||
if (!objectplacing || thingarg < COM_Argc())
|
||||
{
|
||||
if (!objectplacing)
|
||||
{
|
||||
|
@ -1456,7 +1462,7 @@ void Command_ObjectPlace_f(void)
|
|||
if (players[0].powers[pw_carry] == CR_NIGHTSMODE)
|
||||
return;
|
||||
|
||||
if (!COM_CheckParm("-silent"))
|
||||
if (! silent)
|
||||
{
|
||||
HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE|V_AUTOFADEOUT);
|
||||
HU_SetCEchoDuration(10);
|
||||
|
@ -1507,9 +1513,9 @@ void Command_ObjectPlace_f(void)
|
|||
op_oldstate = (statenum_t)(players[0].mo->state-states);
|
||||
}
|
||||
|
||||
if (COM_Argc() > 1)
|
||||
if (thingarg < COM_Argc())
|
||||
{
|
||||
UINT16 mapthingnum = atoi(COM_Argv(1));
|
||||
UINT16 mapthingnum = atoi(COM_Argv(thingarg));
|
||||
mobjtype_t type = P_GetMobjtype(mapthingnum);
|
||||
if (type == MT_UNKNOWN)
|
||||
CONS_Printf(M_GetText("No mobj type delegated to thing type %d.\n"), mapthingnum);
|
||||
|
|
|
@ -8236,14 +8236,15 @@ static void M_CacheLoadGameData(void)
|
|||
|
||||
static void M_DrawLoadGameData(void)
|
||||
{
|
||||
INT32 i, savetodraw, x, y, hsep = 90;
|
||||
INT32 i, prev_i = 1, savetodraw, x, y, hsep = 90;
|
||||
skin_t *charskin = NULL;
|
||||
|
||||
if (vid.width != BASEVIDWIDTH*vid.dupx)
|
||||
hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx);
|
||||
|
||||
for (i = -2; i <= 2; i++)
|
||||
for (i = 2; prev_i; i = -(i + ((UINT32)i >> 31))) // draws from outwards in; 2, -2, 1, -1, 0
|
||||
{
|
||||
prev_i = i;
|
||||
savetodraw = (saveSlotSelected + i + numsaves)%numsaves;
|
||||
x = (BASEVIDWIDTH/2 - 42 + loadgamescroll) + (i*hsep);
|
||||
y = 33 + 9;
|
||||
|
|
540
src/m_perfstats.c
Normal file
540
src/m_perfstats.c
Normal file
|
@ -0,0 +1,540 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
src/m_perfstats.h
Normal file
41
src/m_perfstats.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 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
|
|
@ -62,7 +62,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
|
|||
};
|
||||
|
||||
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_CALL|CV_NOINIT, NULL, Update_parameters);
|
||||
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 = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters);
|
||||
|
||||
|
|
|
@ -394,8 +394,10 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
|
|||
INT32 secnum = -1;
|
||||
sector_t *sec;
|
||||
ceiling_t *ceiling;
|
||||
mtag_t tag = Tag_FGet(&line->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
|
||||
TAG_ITER_SECTORS(0, tag, secnum)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
|
@ -593,7 +595,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
|
|||
|
||||
}
|
||||
|
||||
ceiling->tag = sec->tag;
|
||||
ceiling->tag = tag;
|
||||
ceiling->type = type;
|
||||
firstone = 0;
|
||||
}
|
||||
|
@ -614,8 +616,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
|
|||
INT32 secnum = -1;
|
||||
sector_t *sec;
|
||||
ceiling_t *ceiling;
|
||||
mtag_t tag = Tag_FGet(&line->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
|
||||
TAG_ITER_SECTORS(0, tag, secnum)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
|
@ -670,7 +674,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
|
|||
break;
|
||||
}
|
||||
|
||||
ceiling->tag = sec->tag;
|
||||
ceiling->tag = tag;
|
||||
ceiling->type = type;
|
||||
}
|
||||
return rtn;
|
||||
|
|
|
@ -3925,11 +3925,12 @@ void A_BossDeath(mobj_t *mo)
|
|||
else
|
||||
{
|
||||
// Bring the egg trap up to the surface
|
||||
junk.tag = LE_CAPSULE0;
|
||||
// Incredibly shitty code ahead
|
||||
Tag_FSet(&junk.tags, LE_CAPSULE0);
|
||||
EV_DoElevator(&junk, elevateHighest, false);
|
||||
junk.tag = LE_CAPSULE1;
|
||||
Tag_FSet(&junk.tags, LE_CAPSULE1);
|
||||
EV_DoElevator(&junk, elevateUp, false);
|
||||
junk.tag = LE_CAPSULE2;
|
||||
Tag_FSet(&junk.tags, LE_CAPSULE2);
|
||||
EV_DoElevator(&junk, elevateHighest, false);
|
||||
|
||||
if (mapheaderinfo[gamemap-1]->muspostbossname[0] &&
|
||||
|
@ -4052,7 +4053,7 @@ bossjustdie:
|
|||
}
|
||||
case MT_KOOPA:
|
||||
{
|
||||
junk.tag = LE_KOOPA;
|
||||
Tag_FSet(&junk.tags, LE_KOOPA);
|
||||
EV_DoCeiling(&junk, raiseToHighest);
|
||||
return;
|
||||
}
|
||||
|
@ -6157,7 +6158,7 @@ void A_RockSpawn(mobj_t *actor)
|
|||
{
|
||||
mobj_t *mo;
|
||||
mobjtype_t type;
|
||||
INT32 i = P_FindSpecialLineFromTag(12, (INT16)actor->threshold, -1);
|
||||
INT32 i = Tag_FindLineSpecial(12, (INT16)actor->threshold);
|
||||
line_t *line;
|
||||
fixed_t dist;
|
||||
fixed_t randomoomph;
|
||||
|
|
|
@ -632,8 +632,10 @@ void T_BounceCheese(bouncecheese_t *bouncer)
|
|||
fixed_t waterheight;
|
||||
fixed_t floorheight;
|
||||
sector_t *actionsector;
|
||||
INT32 i;
|
||||
boolean remove;
|
||||
INT32 i;
|
||||
mtag_t tag = Tag_FGet(&bouncer->sourceline->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT
|
||||
|| bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself!
|
||||
|
@ -648,7 +650,7 @@ void T_BounceCheese(bouncecheese_t *bouncer)
|
|||
}
|
||||
|
||||
// You can use multiple target sectors, but at your own risk!!!
|
||||
for (i = -1; (i = P_FindSectorFromTag(bouncer->sourceline->tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
{
|
||||
actionsector = §ors[i];
|
||||
actionsector->moved = true;
|
||||
|
@ -772,6 +774,8 @@ void T_StartCrumble(crumble_t *crumble)
|
|||
ffloor_t *rover;
|
||||
sector_t *sector;
|
||||
INT32 i;
|
||||
mtag_t tag = Tag_FGet(&crumble->sourceline->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
// Once done, the no-return thinker just sits there,
|
||||
// constantly 'returning'... kind of an oxymoron, isn't it?
|
||||
|
@ -800,7 +804,7 @@ void T_StartCrumble(crumble_t *crumble)
|
|||
}
|
||||
else if (++crumble->timer == 0) // Reposition back to original spot
|
||||
{
|
||||
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
{
|
||||
sector = §ors[i];
|
||||
|
||||
|
@ -836,7 +840,7 @@ void T_StartCrumble(crumble_t *crumble)
|
|||
// Flash to indicate that the platform is about to return.
|
||||
if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0))
|
||||
{
|
||||
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
{
|
||||
sector = §ors[i];
|
||||
|
||||
|
@ -928,7 +932,7 @@ void T_StartCrumble(crumble_t *crumble)
|
|||
P_RemoveThinker(&crumble->thinker);
|
||||
}
|
||||
|
||||
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
{
|
||||
sector = §ors[i];
|
||||
sector->moved = true;
|
||||
|
@ -944,6 +948,7 @@ void T_StartCrumble(crumble_t *crumble)
|
|||
void T_MarioBlock(mariothink_t *block)
|
||||
{
|
||||
INT32 i;
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
T_MovePlane
|
||||
(
|
||||
|
@ -978,8 +983,7 @@ void T_MarioBlock(mariothink_t *block)
|
|||
block->sector->ceilspeed = 0;
|
||||
block->direction = 0;
|
||||
}
|
||||
|
||||
for (i = -1; (i = P_FindSectorFromTag(block->tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, (INT16)block->tag, i)
|
||||
P_RecalcPrecipInSector(§ors[i]);
|
||||
}
|
||||
|
||||
|
@ -992,8 +996,7 @@ void T_FloatSector(floatthink_t *floater)
|
|||
|
||||
// Just find the first sector with the tag.
|
||||
// Doesn't work with multiple sectors that have different floor/ceiling heights.
|
||||
secnum = P_FindSectorFromTag(floater->tag, -1);
|
||||
if (secnum <= 0)
|
||||
if ((secnum = Tag_Iterate_Sectors((INT16)floater->tag, 0)) < 0)
|
||||
return;
|
||||
actionsector = §ors[secnum];
|
||||
|
||||
|
@ -1131,10 +1134,8 @@ void T_ThwompSector(thwomp_t *thwomp)
|
|||
|
||||
// Just find the first sector with the tag.
|
||||
// Doesn't work with multiple sectors that have different floor/ceiling heights.
|
||||
secnum = P_FindSectorFromTag(thwomp->tag, -1);
|
||||
|
||||
if (secnum <= 0)
|
||||
return; // Bad bad bad!
|
||||
if ((secnum = Tag_Iterate_Sectors((INT16)thwomp->tag, 0)) < 0)
|
||||
return;
|
||||
|
||||
actionsector = §ors[secnum];
|
||||
|
||||
|
@ -1293,8 +1294,10 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
|
|||
sector_t *sec = NULL;
|
||||
INT32 secnum = -1;
|
||||
boolean FOFsector = false;
|
||||
mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
while ((secnum = P_FindSectorFromTag(nobaddies->sourceline->tag, secnum)) >= 0)
|
||||
TAG_ITER_SECTORS(0, tag, secnum)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
|
@ -1304,13 +1307,15 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
|
|||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
INT32 targetsecnum = -1;
|
||||
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
|
||||
TAG_ITER_DECLARECOUNTER(1);
|
||||
|
||||
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
|
||||
continue;
|
||||
|
||||
FOFsector = true;
|
||||
|
||||
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0)
|
||||
TAG_ITER_SECTORS(1, tag2, targetsecnum)
|
||||
{
|
||||
if (T_SectorHasEnemies(§ors[targetsecnum]))
|
||||
return;
|
||||
|
@ -1321,7 +1326,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
|
|||
return;
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", nobaddies->sourceline->tag);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", tag);
|
||||
|
||||
// No enemies found, run the linedef exec and terminate this thinker
|
||||
P_RunTriggerLinedef(nobaddies->sourceline, NULL, NULL);
|
||||
|
@ -1396,6 +1401,8 @@ void T_EachTimeThinker(eachtime_t *eachtime)
|
|||
boolean floortouch = false;
|
||||
fixed_t bottomheight, topheight;
|
||||
ffloor_t *rover;
|
||||
mtag_t tag = Tag_FGet(&eachtime->sourceline->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -1405,7 +1412,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
|
|||
eachtime->playersOnArea[i] = false;
|
||||
}
|
||||
|
||||
while ((secnum = P_FindSectorFromTag(eachtime->sourceline->tag, secnum)) >= 0)
|
||||
TAG_ITER_SECTORS(0, tag, secnum)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
|
@ -1422,13 +1429,15 @@ void T_EachTimeThinker(eachtime_t *eachtime)
|
|||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
INT32 targetsecnum = -1;
|
||||
mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags);
|
||||
TAG_ITER_DECLARECOUNTER(1);
|
||||
|
||||
if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300)
|
||||
continue;
|
||||
|
||||
FOFsector = true;
|
||||
|
||||
while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0)
|
||||
TAG_ITER_SECTORS(1, tag2, targetsecnum)
|
||||
{
|
||||
targetsec = §ors[targetsecnum];
|
||||
|
||||
|
@ -1530,7 +1539,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
|
|||
if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i)))
|
||||
continue;
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", eachtime->sourceline->tag);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", tag);
|
||||
|
||||
// 03/08/14 -Monster Iestyn
|
||||
// No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever!
|
||||
|
@ -1562,11 +1571,13 @@ void T_RaiseSector(raise_t *raise)
|
|||
fixed_t distToNearestEndpoint;
|
||||
INT32 direction;
|
||||
result_e res = 0;
|
||||
mtag_t tag = raise->tag;
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata)
|
||||
return;
|
||||
|
||||
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
{
|
||||
sector = §ors[i];
|
||||
|
||||
|
@ -1693,7 +1704,7 @@ void T_RaiseSector(raise_t *raise)
|
|||
raise->sector->ceilspeed = 42;
|
||||
raise->sector->floorspeed = speed*direction;
|
||||
|
||||
for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
P_RecalcPrecipInSector(§ors[i]);
|
||||
}
|
||||
|
||||
|
@ -1810,8 +1821,10 @@ void EV_DoFloor(line_t *line, floor_e floortype)
|
|||
INT32 secnum = -1;
|
||||
sector_t *sec;
|
||||
floormove_t *dofloor;
|
||||
mtag_t tag = Tag_FGet(&line->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
|
||||
TAG_ITER_SECTORS(0, tag, secnum)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
|
@ -2025,9 +2038,11 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
|
|||
INT32 secnum = -1;
|
||||
sector_t *sec;
|
||||
elevator_t *elevator;
|
||||
mtag_t tag = Tag_FGet(&line->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
// act on all sectors with the same tag as the triggering linedef
|
||||
while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
|
||||
TAG_ITER_SECTORS(0, tag, secnum)
|
||||
{
|
||||
sec = §ors[secnum];
|
||||
|
||||
|
@ -2148,6 +2163,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
|
|||
INT16 flags;
|
||||
|
||||
sector_t *controlsec = rover->master->frontsector;
|
||||
mtag_t tag = Tag_FGet(&controlsec->tags);
|
||||
|
||||
if (sec == NULL)
|
||||
{
|
||||
|
@ -2176,9 +2192,9 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
|
|||
lifetime = 3*TICRATE;
|
||||
flags = 0;
|
||||
|
||||
if (controlsec->tag != 0)
|
||||
if (tag != 0)
|
||||
{
|
||||
INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1);
|
||||
INT32 tagline = Tag_FindLineSpecial(14, tag);
|
||||
if (tagline != -1)
|
||||
{
|
||||
if (sides[lines[tagline].sidenum[0]].toptexture)
|
||||
|
@ -2322,6 +2338,8 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
|
|||
crumble_t *crumble;
|
||||
sector_t *foundsec;
|
||||
INT32 i;
|
||||
mtag_t tag = Tag_FGet(&rover->master->tags);
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
// If floor is already activated, skip it
|
||||
if (sec->floordata)
|
||||
|
@ -2364,7 +2382,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
|
|||
|
||||
crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
|
||||
|
||||
for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
{
|
||||
foundsec = §ors[i];
|
||||
|
||||
|
@ -2413,7 +2431,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
|
|||
block->direction = 1;
|
||||
block->floorstartheight = block->sector->floorheight;
|
||||
block->ceilingstartheight = block->sector->ceilingheight;
|
||||
block->tag = (INT16)sector->tag;
|
||||
block->tag = (INT16)Tag_FGet(§or->tags);
|
||||
|
||||
if (itsamonitor)
|
||||
{
|
||||
|
|
|
@ -1388,7 +1388,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (player->bot)
|
||||
return;
|
||||
|
||||
junk.tag = LE_AXE;
|
||||
Tag_FSet(&junk.tags, LE_AXE);
|
||||
EV_DoElevator(&junk, bridgeFall, false);
|
||||
|
||||
// scan the remaining thinkers to find koopa
|
||||
|
|
|
@ -374,8 +374,10 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean
|
|||
void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force)
|
||||
{
|
||||
INT32 i;
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
// search all sectors for ones with tag
|
||||
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0 ;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
{
|
||||
if (!force && ticbased // always let speed fader execute
|
||||
&& sectors[i].lightingdata
|
||||
|
|
|
@ -428,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);
|
||||
|
|
137
src/p_map.c
137
src/p_map.c
|
@ -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 (maxstep > 0 && 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 (maxstep > 0 && 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)
|
||||
|
@ -3114,7 +3107,7 @@ static void P_HitSlideLine(line_t *ld)
|
|||
lineangle >>= ANGLETOFINESHIFT;
|
||||
deltaangle >>= ANGLETOFINESHIFT;
|
||||
|
||||
movelen = P_AproxDistance(tmxmove, tmymove);
|
||||
movelen = R_PointToDist2(0, 0, tmxmove, tmymove);
|
||||
newlen = FixedMul(movelen, FINECOSINE(deltaangle));
|
||||
|
||||
tmxmove = FixedMul(newlen, FINECOSINE(lineangle));
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
89
src/p_mobj.c
89
src/p_mobj.c
|
@ -3509,16 +3509,19 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
|
|||
{
|
||||
sector_t *sector;
|
||||
fixed_t halfheight = thiscam->z + (thiscam->height >> 1);
|
||||
size_t i;
|
||||
|
||||
// see if we are in water
|
||||
sector = thiscam->subsector->sector;
|
||||
|
||||
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
|
||||
return true;
|
||||
for (i = 0; i < sector->tags.count; i++)
|
||||
if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
|
||||
return true;
|
||||
|
||||
if (sector->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
size_t j;
|
||||
|
||||
for (rover = sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
|
@ -3530,7 +3533,8 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
|
|||
if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y))
|
||||
continue;
|
||||
|
||||
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
|
||||
for (j = 0; j < rover->master->frontsector->tags.count; j++)
|
||||
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -4599,16 +4603,18 @@ static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta)
|
|||
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
|
||||
INT32 snum;
|
||||
sector_t *sector;
|
||||
for (snum = sectors[tag%numsectors].firsttag; snum != -1; snum = sector->nexttag)
|
||||
boolean gotcage = false;
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
TAG_ITER_SECTORS(0, tag, snum)
|
||||
{
|
||||
sector = §ors[snum];
|
||||
if (sector->tag != tag)
|
||||
continue;
|
||||
sector->floorheight += delta;
|
||||
sector->ceilingheight += delta;
|
||||
P_CheckSector(sector, true);
|
||||
gotcage = true;
|
||||
}
|
||||
return sectors[tag%numsectors].firsttag != -1;
|
||||
return gotcage;
|
||||
}
|
||||
|
||||
// Move Boss4's arms to angle
|
||||
|
@ -4680,26 +4686,16 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
|
|||
static void P_Boss4DestroyCage(mobj_t *mobj)
|
||||
{
|
||||
const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0);
|
||||
INT32 snum, next;
|
||||
INT32 snum;
|
||||
size_t a;
|
||||
sector_t *sector, *rsec;
|
||||
ffloor_t *rover;
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
// This will be the final iteration of sector tag.
|
||||
// We'll destroy the tag list as we go.
|
||||
next = sectors[tag%numsectors].firsttag;
|
||||
sectors[tag%numsectors].firsttag = -1;
|
||||
|
||||
for (snum = next; snum != -1; snum = next)
|
||||
TAG_ITER_SECTORS(0, tag, snum)
|
||||
{
|
||||
sector = §ors[snum];
|
||||
|
||||
next = sector->nexttag;
|
||||
sector->nexttag = -1;
|
||||
if (sector->tag != tag)
|
||||
continue;
|
||||
sector->tag = 0;
|
||||
|
||||
// Destroy the FOFs.
|
||||
for (a = 0; a < sector->numattached; a++)
|
||||
{
|
||||
|
@ -10013,11 +10009,12 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
// Sector special (2,8) allows ANY mobj to trigger a linedef exec
|
||||
if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8)
|
||||
{
|
||||
sector_t *sec2;
|
||||
|
||||
sec2 = P_ThingOnSpecial3DFloor(mobj);
|
||||
sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
|
||||
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
|
||||
P_LinedefExecute(sec2->tag, mobj, sec2);
|
||||
{
|
||||
mtag_t tag = Tag_FGet(&sec2->tags);
|
||||
P_LinedefExecute(tag, mobj, sec2);
|
||||
}
|
||||
}
|
||||
|
||||
if (mobj->scale != mobj->destscale)
|
||||
|
@ -10241,14 +10238,19 @@ void P_PushableThinker(mobj_t *mobj)
|
|||
sec = mobj->subsector->sector;
|
||||
|
||||
if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight)
|
||||
P_LinedefExecute(sec->tag, mobj, sec);
|
||||
{
|
||||
mtag_t tag = Tag_FGet(&sec->tags);
|
||||
P_LinedefExecute(tag, mobj, sec);
|
||||
}
|
||||
|
||||
// else if (GETSECSPECIAL(sec->special, 2) == 8)
|
||||
{
|
||||
sector_t *sec2;
|
||||
|
||||
sec2 = P_ThingOnSpecial3DFloor(mobj);
|
||||
sector_t *sec2 = P_ThingOnSpecial3DFloor(mobj);
|
||||
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
|
||||
P_LinedefExecute(sec2->tag, mobj, sec2);
|
||||
{
|
||||
mtag_t tag = Tag_FGet(&sec2->tags);
|
||||
P_LinedefExecute(tag, mobj, sec2);
|
||||
}
|
||||
}
|
||||
|
||||
// it has to be pushable RIGHT NOW for this part to happen
|
||||
|
@ -11039,10 +11041,10 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
|
|||
}
|
||||
|
||||
static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "30", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL);
|
||||
consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_NETVAR, CV_OnOff, 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 = CVAR_INIT ("flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL);
|
||||
consvar_t cv_flagtime = CVAR_INIT ("flagtime", "30", CV_SAVE|CV_NETVAR|CV_CHEAT, flagtime_cons_t, NULL);
|
||||
|
||||
void P_SpawnPrecipitation(void)
|
||||
{
|
||||
|
@ -11948,9 +11950,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;
|
||||
}
|
||||
|
||||
|
@ -12025,8 +12024,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
|
|||
const size_t mthingi = (size_t)(mthing - mapthings);
|
||||
|
||||
// Find the corresponding linedef special, using angle as tag
|
||||
// P_FindSpecialLineFromTag works here now =D
|
||||
line = P_FindSpecialLineFromTag(9, mthing->angle, -1);
|
||||
line = Tag_FindLineSpecial(9, mthing->angle);
|
||||
|
||||
if (line == -1)
|
||||
{
|
||||
|
@ -12336,7 +12334,7 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
|
|||
const size_t mthingi = (size_t)(mthing - mapthings);
|
||||
|
||||
// Find the corresponding linedef special, using angle as tag
|
||||
line = P_FindSpecialLineFromTag(15, mthing->angle, -1);
|
||||
line = Tag_FindLineSpecial(15, mthing->angle);
|
||||
|
||||
if (line == -1)
|
||||
{
|
||||
|
@ -12575,17 +12573,20 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
break;
|
||||
}
|
||||
case MT_SKYBOX:
|
||||
if (mthing->tag < 0 || mthing->tag > 15)
|
||||
{
|
||||
mtag_t tag = Tag_FGet(&mthing->tags);
|
||||
if (tag < 0 || tag > 15)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", mthing->tag, sizeu1((size_t)(mthing - mapthings)));
|
||||
CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", tag, sizeu1((size_t)(mthing - mapthings)));
|
||||
break;
|
||||
}
|
||||
|
||||
if (mthing->options & MTF_OBJECTSPECIAL)
|
||||
skyboxcenterpnts[mthing->tag] = mobj;
|
||||
skyboxcenterpnts[tag] = mobj;
|
||||
else
|
||||
skyboxviewpnts[mthing->tag] = mobj;
|
||||
skyboxviewpnts[tag] = mobj;
|
||||
break;
|
||||
}
|
||||
case MT_EGGSTATUE:
|
||||
if (mthing->options & MTF_EXTRA)
|
||||
{
|
||||
|
@ -13072,8 +13073,8 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
|
|||
mobj = P_SpawnMobj(x, y, z, i);
|
||||
mobj->spawnpoint = mthing;
|
||||
|
||||
P_SetScale(mobj, mthing->scale);
|
||||
mobj->destscale = mthing->scale;
|
||||
P_SetScale(mobj, FixedMul(mobj->scale, mthing->scale));
|
||||
mobj->destscale = FixedMul(mobj->destscale, mthing->scale);
|
||||
|
||||
if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle))
|
||||
return mobj;
|
||||
|
|
|
@ -556,10 +556,11 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
|
|||
polyobj_t *po;
|
||||
vertex_t dist, sspot;
|
||||
size_t i;
|
||||
mtag_t tag = Tag_FGet(&anchor->tags);
|
||||
|
||||
if (!(po = Polyobj_GetForNum(anchor->tag)))
|
||||
if (!(po = Polyobj_GetForNum(tag)))
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->tag);
|
||||
CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", tag);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -976,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;
|
||||
|
@ -1162,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;
|
||||
|
@ -1342,7 +1343,7 @@ void Polyobj_InitLevel(void)
|
|||
{
|
||||
qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue);
|
||||
|
||||
Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->tag);
|
||||
Polyobj_spawnPolyObj(i, qitem->mo, Tag_FGet(&qitem->mo->spawnpoint->tags));
|
||||
}
|
||||
|
||||
// move polyobjects to spawn points
|
||||
|
@ -2444,10 +2445,11 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
|
|||
polymove_t *th;
|
||||
size_t i;
|
||||
INT32 start;
|
||||
mtag_t tag = pfdata->polyObjNum;
|
||||
|
||||
if (!(po = Polyobj_GetForNum(pfdata->polyObjNum)))
|
||||
if (!(po = Polyobj_GetForNum(tag)))
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->polyObjNum);
|
||||
CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2470,7 +2472,7 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
|
|||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
th->polyObjNum = pfdata->polyObjNum;
|
||||
th->polyObjNum = tag;
|
||||
th->distance = 0;
|
||||
th->speed = pfdata->speed;
|
||||
th->angle = pfdata->angle;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -98,13 +98,16 @@ static void P_NetArchivePlayers(void)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
WRITESINT8(save_p, (SINT8)adminplayers[i]);
|
||||
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
flags = 0;
|
||||
|
||||
// no longer send ticcmds, player name, skin, or color
|
||||
// no longer send ticcmds
|
||||
|
||||
WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME);
|
||||
WRITEINT16(save_p, players[i].angleturn);
|
||||
WRITEINT16(save_p, players[i].oldrelangleturn);
|
||||
WRITEANGLE(save_p, players[i].aiming);
|
||||
|
@ -134,6 +137,9 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEUINT16(save_p, players[i].flashpal);
|
||||
WRITEUINT16(save_p, players[i].flashcount);
|
||||
|
||||
WRITEUINT8(save_p, players[i].skincolor);
|
||||
WRITEINT32(save_p, players[i].skin);
|
||||
WRITEUINT32(save_p, players[i].availabilities);
|
||||
WRITEUINT32(save_p, players[i].score);
|
||||
WRITEFIXED(save_p, players[i].dashspeed);
|
||||
WRITESINT8(save_p, players[i].lives);
|
||||
|
@ -305,6 +311,8 @@ static void P_NetUnArchivePlayers(void)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
adminplayers[i] = (INT32)READSINT8(save_p);
|
||||
|
||||
// Do NOT memset player struct to 0
|
||||
// other areas may initialize data elsewhere
|
||||
//memset(&players[i], 0, sizeof (player_t));
|
||||
|
@ -312,9 +320,8 @@ static void P_NetUnArchivePlayers(void)
|
|||
continue;
|
||||
|
||||
// NOTE: sending tics should (hopefully) no longer be necessary
|
||||
// sending player names, skin and color should not be necessary at all!
|
||||
// (that data is handled in the server config now)
|
||||
|
||||
READSTRINGN(save_p, player_names[i], MAXPLAYERNAME);
|
||||
players[i].angleturn = READINT16(save_p);
|
||||
players[i].oldrelangleturn = READINT16(save_p);
|
||||
players[i].aiming = READANGLE(save_p);
|
||||
|
@ -344,6 +351,9 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].flashpal = READUINT16(save_p);
|
||||
players[i].flashcount = READUINT16(save_p);
|
||||
|
||||
players[i].skincolor = READUINT8(save_p);
|
||||
players[i].skin = READINT32(save_p);
|
||||
players[i].availabilities = READUINT32(save_p);
|
||||
players[i].score = READUINT32(save_p);
|
||||
players[i].dashspeed = READFIXED(save_p); // dashing speed
|
||||
players[i].lives = READSINT8(save_p);
|
||||
|
@ -913,7 +923,7 @@ static void UnArchiveFFloors(const sector_t *ss)
|
|||
|
||||
static void ArchiveSectors(void)
|
||||
{
|
||||
size_t i;
|
||||
size_t i, j;
|
||||
const sector_t *ss = sectors;
|
||||
const sector_t *spawnss = spawnsectors;
|
||||
UINT8 diff, diff2, diff3;
|
||||
|
@ -951,10 +961,8 @@ static void ArchiveSectors(void)
|
|||
if (ss->ceilingpic_angle != spawnss->ceilingpic_angle)
|
||||
diff2 |= SD_CEILANG;
|
||||
|
||||
if (ss->tag != spawnss->tag)
|
||||
if (!Tag_Compare(&ss->tags, &spawnss->tags))
|
||||
diff2 |= SD_TAG;
|
||||
if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag)
|
||||
diff3 |= SD_TAGLIST;
|
||||
|
||||
if (ss->extra_colormap != spawnss->extra_colormap)
|
||||
diff3 |= SD_COLORMAP;
|
||||
|
@ -1002,12 +1010,11 @@ static void ArchiveSectors(void)
|
|||
WRITEANGLE(save_p, ss->floorpic_angle);
|
||||
if (diff2 & SD_CEILANG)
|
||||
WRITEANGLE(save_p, ss->ceilingpic_angle);
|
||||
if (diff2 & SD_TAG) // save only the tag
|
||||
WRITEINT16(save_p, ss->tag);
|
||||
if (diff3 & SD_TAGLIST) // save both firsttag and nexttag
|
||||
{ // either of these could be changed even if tag isn't
|
||||
WRITEINT32(save_p, ss->firsttag);
|
||||
WRITEINT32(save_p, ss->nexttag);
|
||||
if (diff2 & SD_TAG)
|
||||
{
|
||||
WRITEUINT32(save_p, ss->tags.count);
|
||||
for (j = 0; j < ss->tags.count; j++)
|
||||
WRITEINT16(save_p, ss->tags.tags[j]);
|
||||
}
|
||||
|
||||
if (diff3 & SD_COLORMAP)
|
||||
|
@ -1025,7 +1032,7 @@ static void ArchiveSectors(void)
|
|||
|
||||
static void UnArchiveSectors(void)
|
||||
{
|
||||
UINT16 i;
|
||||
UINT16 i, j;
|
||||
UINT8 diff, diff2, diff3;
|
||||
for (;;)
|
||||
{
|
||||
|
@ -1079,13 +1086,29 @@ static void UnArchiveSectors(void)
|
|||
if (diff2 & SD_CEILANG)
|
||||
sectors[i].ceilingpic_angle = READANGLE(save_p);
|
||||
if (diff2 & SD_TAG)
|
||||
sectors[i].tag = READINT16(save_p); // DON'T use P_ChangeSectorTag
|
||||
if (diff3 & SD_TAGLIST)
|
||||
{
|
||||
sectors[i].firsttag = READINT32(save_p);
|
||||
sectors[i].nexttag = READINT32(save_p);
|
||||
size_t ncount = READUINT32(save_p);
|
||||
|
||||
// Remove entries from global lists.
|
||||
for (j = 0; j < sectors[i].tags.count; j++)
|
||||
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
|
||||
|
||||
// Reallocate if size differs.
|
||||
if (ncount != sectors[i].tags.count)
|
||||
{
|
||||
sectors[i].tags.count = ncount;
|
||||
sectors[i].tags.tags = Z_Realloc(sectors[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL);
|
||||
}
|
||||
|
||||
for (j = 0; j < ncount; j++)
|
||||
sectors[i].tags.tags[j] = READINT16(save_p);
|
||||
|
||||
// Add new entries.
|
||||
for (j = 0; j < sectors[i].tags.count; j++)
|
||||
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
|
||||
}
|
||||
|
||||
|
||||
if (diff3 & SD_COLORMAP)
|
||||
sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
|
||||
if (diff3 & SD_CRUMBLESTATE)
|
||||
|
@ -4041,14 +4064,17 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
|
|||
playeringame[consoleplayer] = true;
|
||||
}
|
||||
|
||||
static void P_NetArchiveMisc(void)
|
||||
static void P_NetArchiveMisc(boolean resending)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
|
||||
|
||||
if (resending)
|
||||
WRITEUINT32(save_p, gametic);
|
||||
WRITEINT16(save_p, gamemap);
|
||||
WRITEINT16(save_p, gamestate);
|
||||
WRITEINT16(save_p, gametype);
|
||||
|
||||
{
|
||||
UINT32 pig = 0;
|
||||
|
@ -4111,13 +4137,16 @@ static void P_NetArchiveMisc(void)
|
|||
WRITEUINT8(save_p, 0x2e);
|
||||
}
|
||||
|
||||
static inline boolean P_NetUnArchiveMisc(void)
|
||||
static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
|
||||
I_Error("Bad $$$.sav at archive block Misc");
|
||||
|
||||
if (reloading)
|
||||
gametic = READUINT32(save_p);
|
||||
|
||||
gamemap = READINT16(save_p);
|
||||
|
||||
// gamemap changed; we assume that its map header is always valid,
|
||||
|
@ -4131,6 +4160,8 @@ static inline boolean P_NetUnArchiveMisc(void)
|
|||
|
||||
G_SetGamestate(READINT16(save_p));
|
||||
|
||||
gametype = READINT16(save_p);
|
||||
|
||||
{
|
||||
UINT32 pig = READUINT32(save_p);
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
@ -4144,7 +4175,7 @@ static inline boolean P_NetUnArchiveMisc(void)
|
|||
|
||||
tokenlist = READUINT32(save_p);
|
||||
|
||||
if (!P_LoadLevel(true))
|
||||
if (!P_LoadLevel(true, reloading))
|
||||
return false;
|
||||
|
||||
// get the time
|
||||
|
@ -4243,14 +4274,14 @@ void P_SaveGame(INT16 mapnum)
|
|||
P_ArchiveLuabanksAndConsistency();
|
||||
}
|
||||
|
||||
void P_SaveNetGame(void)
|
||||
void P_SaveNetGame(boolean resending)
|
||||
{
|
||||
thinker_t *th;
|
||||
mobj_t *mobj;
|
||||
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
|
||||
|
||||
CV_SaveNetVars(&save_p);
|
||||
P_NetArchiveMisc();
|
||||
P_NetArchiveMisc(resending);
|
||||
|
||||
// Assign the mobjnumber for pointer tracking
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
|
@ -4298,10 +4329,10 @@ boolean P_LoadGame(INT16 mapoverride)
|
|||
return true;
|
||||
}
|
||||
|
||||
boolean P_LoadNetGame(void)
|
||||
boolean P_LoadNetGame(boolean reloading)
|
||||
{
|
||||
CV_LoadNetVars(&save_p);
|
||||
if (!P_NetUnArchiveMisc())
|
||||
if (!P_NetUnArchiveMisc(reloading))
|
||||
return false;
|
||||
P_NetUnArchivePlayers();
|
||||
if (gamestate == GS_LEVEL)
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
// These are the load / save game routines.
|
||||
|
||||
void P_SaveGame(INT16 mapnum);
|
||||
void P_SaveNetGame(void);
|
||||
void P_SaveNetGame(boolean resending);
|
||||
boolean P_LoadGame(INT16 mapoverride);
|
||||
boolean P_LoadNetGame(void);
|
||||
boolean P_LoadNetGame(boolean reloading);
|
||||
|
||||
mobj_t *P_FindNewPosition(UINT32 oldposition);
|
||||
|
||||
|
|
216
src/p_setup.c
216
src/p_setup.c
|
@ -83,6 +83,8 @@
|
|||
|
||||
#include "fastcmp.h" // textmap parsing
|
||||
|
||||
#include "taglist.h"
|
||||
|
||||
//
|
||||
// Map MD5, calculated on level load.
|
||||
// Sent to clients in PT_SERVERINFO.
|
||||
|
@ -905,16 +907,13 @@ static void P_SpawnMapThings(boolean spawnemblems)
|
|||
}
|
||||
|
||||
// Experimental groovy write function!
|
||||
void P_WriteThings(lumpnum_t lumpnum)
|
||||
void P_WriteThings(void)
|
||||
{
|
||||
size_t i, length;
|
||||
mapthing_t *mt;
|
||||
UINT8 *data;
|
||||
UINT8 *savebuffer, *savebuf_p;
|
||||
INT16 temp;
|
||||
|
||||
data = W_CacheLumpNum(lumpnum, PU_LEVEL);
|
||||
|
||||
savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t));
|
||||
|
||||
if (!savebuf_p)
|
||||
|
@ -936,8 +935,6 @@ void P_WriteThings(lumpnum_t lumpnum)
|
|||
WRITEUINT16(savebuf_p, mt->options);
|
||||
}
|
||||
|
||||
Z_Free(data);
|
||||
|
||||
length = savebuf_p - savebuffer;
|
||||
|
||||
FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length);
|
||||
|
@ -969,8 +966,6 @@ static void P_LoadVertices(UINT8 *data)
|
|||
|
||||
static void P_InitializeSector(sector_t *ss)
|
||||
{
|
||||
ss->nexttag = ss->firsttag = -1;
|
||||
|
||||
memset(&ss->soundorg, 0, sizeof(ss->soundorg));
|
||||
|
||||
ss->validcount = 0;
|
||||
|
@ -1041,7 +1036,7 @@ static void P_LoadSectors(UINT8 *data)
|
|||
|
||||
ss->lightlevel = SHORT(ms->lightlevel);
|
||||
ss->special = SHORT(ms->special);
|
||||
ss->tag = SHORT(ms->tag);
|
||||
Tag_FSet(&ss->tags, SHORT(ms->tag));
|
||||
|
||||
ss->floor_xoffs = ss->floor_yoffs = 0;
|
||||
ss->ceiling_xoffs = ss->ceiling_yoffs = 0;
|
||||
|
@ -1080,7 +1075,6 @@ static void P_InitializeLinedef(line_t *ld)
|
|||
ld->frontsector = ld->backsector = NULL;
|
||||
|
||||
ld->validcount = 0;
|
||||
ld->firsttag = ld->nexttag = -1;
|
||||
ld->polyobj = NULL;
|
||||
|
||||
ld->text = NULL;
|
||||
|
@ -1152,7 +1146,7 @@ static void P_LoadLinedefs(UINT8 *data)
|
|||
{
|
||||
ld->flags = SHORT(mld->flags);
|
||||
ld->special = SHORT(mld->special);
|
||||
ld->tag = SHORT(mld->tag);
|
||||
Tag_FSet(&ld->tags, SHORT(mld->tag));
|
||||
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
|
||||
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
|
||||
ld->alpha = FRACUNIT;
|
||||
|
@ -1345,7 +1339,7 @@ static void P_LoadSidedefs(UINT8 *data)
|
|||
|| (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F'))
|
||||
sd->toptexture = axtoi(msd->toptexture);
|
||||
else
|
||||
I_Error("Custom FOF (tag %d) needs a value in the linedef's back side upper texture field.", sd->line->tag);
|
||||
I_Error("Custom FOF (line id %s) needs a value in the linedef's back side upper texture field.", sizeu1(sd->line - lines));
|
||||
|
||||
sd->midtexture = R_TextureNumForName(msd->midtexture);
|
||||
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
|
||||
|
@ -1385,8 +1379,8 @@ static void P_LoadThings(UINT8 *data)
|
|||
mt->type = READUINT16(data);
|
||||
mt->options = READUINT16(data);
|
||||
mt->extrainfo = (UINT8)(mt->type >> 12);
|
||||
Tag_FSet(&mt->tags, 0);
|
||||
mt->scale = FRACUNIT;
|
||||
mt->tag = 0;
|
||||
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
|
||||
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
|
||||
mt->pitch = mt->roll = 0;
|
||||
|
@ -1522,7 +1516,17 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
|
|||
else if (fastcmp(param, "special"))
|
||||
sectors[i].special = atol(val);
|
||||
else if (fastcmp(param, "id"))
|
||||
sectors[i].tag = atol(val);
|
||||
Tag_FSet(§ors[i].tags, atol(val));
|
||||
else if (fastcmp(param, "moreids"))
|
||||
{
|
||||
char* id = val;
|
||||
while (id)
|
||||
{
|
||||
Tag_Add(§ors[i].tags, atol(id));
|
||||
if ((id = strchr(id, ' ')))
|
||||
id++;
|
||||
}
|
||||
}
|
||||
else if (fastcmp(param, "xpanningfloor"))
|
||||
sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val));
|
||||
else if (fastcmp(param, "ypanningfloor"))
|
||||
|
@ -1600,7 +1604,17 @@ static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val)
|
|||
static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
|
||||
{
|
||||
if (fastcmp(param, "id"))
|
||||
lines[i].tag = atol(val);
|
||||
Tag_FSet(&lines[i].tags, atol(val));
|
||||
else if (fastcmp(param, "moreids"))
|
||||
{
|
||||
char* id = val;
|
||||
while (id)
|
||||
{
|
||||
Tag_Add(&lines[i].tags, atol(id));
|
||||
if ((id = strchr(id, ' ')))
|
||||
id++;
|
||||
}
|
||||
}
|
||||
else if (fastcmp(param, "special"))
|
||||
lines[i].special = atol(val);
|
||||
else if (fastcmp(param, "v1"))
|
||||
|
@ -1669,8 +1683,18 @@ static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
|
|||
static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
|
||||
{
|
||||
if (fastcmp(param, "id"))
|
||||
mapthings[i].tag = atol(val);
|
||||
if (fastcmp(param, "x"))
|
||||
Tag_FSet(&mapthings[i].tags, atol(val));
|
||||
else if (fastcmp(param, "moreids"))
|
||||
{
|
||||
char* id = val;
|
||||
while (id)
|
||||
{
|
||||
Tag_Add(&mapthings[i].tags, atol(id));
|
||||
if ((id = strchr(id, ' ')))
|
||||
id++;
|
||||
}
|
||||
}
|
||||
else if (fastcmp(param, "x"))
|
||||
mapthings[i].x = atol(val);
|
||||
else if (fastcmp(param, "y"))
|
||||
mapthings[i].y = atol(val);
|
||||
|
@ -1827,7 +1851,7 @@ static void P_LoadTextmap(void)
|
|||
sc->lightlevel = 255;
|
||||
|
||||
sc->special = 0;
|
||||
sc->tag = 0;
|
||||
Tag_FSet(&sc->tags, 0);
|
||||
|
||||
sc->floor_xoffs = sc->floor_yoffs = 0;
|
||||
sc->ceiling_xoffs = sc->ceiling_yoffs = 0;
|
||||
|
@ -1845,6 +1869,7 @@ static void P_LoadTextmap(void)
|
|||
textmap_colormap.fadeend = 31;
|
||||
textmap_colormap.flags = 0;
|
||||
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
|
||||
|
||||
P_InitializeSector(sc);
|
||||
if (textmap_colormap.used)
|
||||
{
|
||||
|
@ -1861,7 +1886,8 @@ static void P_LoadTextmap(void)
|
|||
ld->v1 = ld->v2 = NULL;
|
||||
ld->flags = 0;
|
||||
ld->special = 0;
|
||||
ld->tag = 0;
|
||||
Tag_FSet(&ld->tags, 0);
|
||||
|
||||
memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args));
|
||||
memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs));
|
||||
ld->alpha = FRACUNIT;
|
||||
|
@ -1909,8 +1935,8 @@ static void P_LoadTextmap(void)
|
|||
mt->options = 0;
|
||||
mt->z = 0;
|
||||
mt->extrainfo = 0;
|
||||
Tag_FSet(&mt->tags, 0);
|
||||
mt->scale = FRACUNIT;
|
||||
mt->tag = 0;
|
||||
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
|
||||
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
|
||||
mt->mobj = NULL;
|
||||
|
@ -2396,6 +2422,10 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
|
|||
seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y);
|
||||
if (seg->linedef)
|
||||
segs[i].offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y);
|
||||
seg->length = P_SegLength(seg);
|
||||
#ifdef HWRENDER
|
||||
seg->flength = (rendermode == render_opengl) ? P_SegLengthFloat(seg) : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2920,30 +2950,6 @@ static void P_LinkMapData(void)
|
|||
}
|
||||
}
|
||||
|
||||
/** Hashes the sector tags across the sectors and linedefs.
|
||||
*
|
||||
* \sa P_FindSectorFromTag, P_ChangeSectorTag
|
||||
* \author Lee Killough
|
||||
*/
|
||||
static inline void P_InitTagLists(void)
|
||||
{
|
||||
register size_t i;
|
||||
|
||||
for (i = numsectors - 1; i != (size_t)-1; i--)
|
||||
{
|
||||
size_t j = (unsigned)sectors[i].tag % numsectors;
|
||||
sectors[i].nexttag = sectors[j].firsttag;
|
||||
sectors[j].firsttag = (INT32)i;
|
||||
}
|
||||
|
||||
for (i = numlines - 1; i != (size_t)-1; i--)
|
||||
{
|
||||
size_t j = (unsigned)lines[i].tag % numlines;
|
||||
lines[i].nexttag = lines[j].firsttag;
|
||||
lines[j].firsttag = (INT32)i;
|
||||
}
|
||||
}
|
||||
|
||||
//For maps in binary format, converts setup of specials to UDMF format.
|
||||
static void P_ConvertBinaryMap(void)
|
||||
{
|
||||
|
@ -2951,14 +2957,28 @@ static void P_ConvertBinaryMap(void)
|
|||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
mtag_t tag = Tag_FGet(&lines[i].tags);
|
||||
|
||||
switch (lines[i].special)
|
||||
{
|
||||
case 20: //PolyObject first line
|
||||
{
|
||||
INT32 paramline = P_FindSpecialLineFromTag(22, lines[i].tag, -1);
|
||||
INT32 check = -1;
|
||||
INT32 paramline = -1;
|
||||
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
TAG_ITER_LINES(0, tag, check)
|
||||
{
|
||||
if (lines[check].special == 22)
|
||||
{
|
||||
paramline = check;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//PolyObject ID
|
||||
lines[i].args[0] = lines[i].tag;
|
||||
lines[i].args[0] = tag;
|
||||
|
||||
//Default: Invisible planes
|
||||
lines[i].args[3] |= TMPF_INVISIBLEPLANES;
|
||||
|
@ -3004,7 +3024,7 @@ static void P_ConvertBinaryMap(void)
|
|||
CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i));
|
||||
break;
|
||||
case 447: //Change colormap
|
||||
lines[i].args[0] = lines[i].tag;
|
||||
lines[i].args[0] = Tag_FGet(&lines[i].tags);
|
||||
if (lines[i].flags & ML_EFFECT3)
|
||||
lines[i].args[2] |= TMCF_RELATIVE;
|
||||
if (lines[i].flags & ML_EFFECT1)
|
||||
|
@ -3020,7 +3040,7 @@ static void P_ConvertBinaryMap(void)
|
|||
abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS)
|
||||
: abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS));
|
||||
|
||||
lines[i].args[0] = lines[i].tag;
|
||||
lines[i].args[0] = Tag_FGet(&lines[i].tags);
|
||||
if (lines[i].flags & ML_EFFECT4)
|
||||
lines[i].args[2] = speed;
|
||||
else
|
||||
|
@ -3040,10 +3060,10 @@ static void P_ConvertBinaryMap(void)
|
|||
break;
|
||||
}
|
||||
case 456: //Stop fading colormap
|
||||
lines[i].args[0] = lines[i].tag;
|
||||
lines[i].args[0] = Tag_FGet(&lines[i].tags);
|
||||
break;
|
||||
case 606: //Colormap
|
||||
lines[i].args[0] = lines[i].tag;
|
||||
lines[i].args[0] = Tag_FGet(&lines[i].tags);
|
||||
break;
|
||||
case 700: //Slope front sector floor
|
||||
case 701: //Slope front sector ceiling
|
||||
|
@ -3084,7 +3104,7 @@ static void P_ConvertBinaryMap(void)
|
|||
else if (lines[i].special == 715)
|
||||
lines[i].args[0] = TMSP_BACKCEILING;
|
||||
|
||||
lines[i].args[1] = lines[i].tag;
|
||||
lines[i].args[1] = tag;
|
||||
|
||||
if (lines[i].flags & ML_EFFECT6)
|
||||
{
|
||||
|
@ -3116,9 +3136,9 @@ static void P_ConvertBinaryMap(void)
|
|||
case 721: //Copy front side ceiling slope
|
||||
case 722: //Copy front side floor and ceiling slope
|
||||
if (lines[i].special != 721)
|
||||
lines[i].args[0] = lines[i].tag;
|
||||
lines[i].args[0] = tag;
|
||||
if (lines[i].special != 720)
|
||||
lines[i].args[1] = lines[i].tag;
|
||||
lines[i].args[1] = tag;
|
||||
lines[i].special = 720;
|
||||
break;
|
||||
case 900: //Translucent wall (10%)
|
||||
|
@ -3151,21 +3171,39 @@ static void P_ConvertBinaryMap(void)
|
|||
switch (mapthings[i].type)
|
||||
{
|
||||
case 750:
|
||||
Tag_Add(&mapthings[i].tags, mapthings[i].angle);
|
||||
break;
|
||||
case 760:
|
||||
case 761:
|
||||
mapthings[i].tag = mapthings[i].angle;
|
||||
Tag_FSet(&mapthings[i].tags, mapthings[i].angle);
|
||||
break;
|
||||
case 762:
|
||||
{
|
||||
INT32 firstline = P_FindSpecialLineFromTag(20, mapthings[i].angle, -1);
|
||||
INT32 check = -1;
|
||||
INT32 firstline = -1;
|
||||
mtag_t tag = mapthings[i].angle;
|
||||
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
Tag_FSet(&mapthings[i].tags, tag);
|
||||
|
||||
TAG_ITER_LINES(0, tag, check)
|
||||
{
|
||||
if (lines[check].special == 20)
|
||||
{
|
||||
firstline = check;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstline != -1)
|
||||
lines[firstline].args[3] |= TMPF_CRUSH;
|
||||
mapthings[i].tag = mapthings[i].angle;
|
||||
|
||||
mapthings[i].type = 761;
|
||||
break;
|
||||
}
|
||||
case 780:
|
||||
mapthings[i].tag = mapthings[i].extrainfo;
|
||||
Tag_FSet(&mapthings[i].tags, mapthings[i].extrainfo);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -3239,6 +3277,7 @@ static boolean P_LoadMapFromFile(void)
|
|||
{
|
||||
virtres_t *virt = vres_GetMap(lastloadedmaplumpnum);
|
||||
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
|
||||
size_t i;
|
||||
udmf = textmap != NULL;
|
||||
|
||||
if (!P_LoadMapData(virt))
|
||||
|
@ -3248,7 +3287,7 @@ static boolean P_LoadMapFromFile(void)
|
|||
|
||||
P_LinkMapData();
|
||||
|
||||
P_InitTagLists(); // Create xref tables for tags
|
||||
Taglist_InitGlobalTables();
|
||||
|
||||
if (!udmf)
|
||||
P_ConvertBinaryMap();
|
||||
|
@ -3262,6 +3301,10 @@ static boolean P_LoadMapFromFile(void)
|
|||
memcpy(spawnlines, lines, numlines * sizeof(*lines));
|
||||
memcpy(spawnsides, sides, numsides * sizeof(*sides));
|
||||
|
||||
for (i = 0; i < numsectors; i++)
|
||||
if (sectors[i].tags.count)
|
||||
spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t));
|
||||
|
||||
P_MakeMapMD5(virt, &mapmd5);
|
||||
|
||||
vres_Free(virt);
|
||||
|
@ -3310,8 +3353,6 @@ static void P_InitLevelSettings(void)
|
|||
|
||||
leveltime = 0;
|
||||
|
||||
localaiming = 0;
|
||||
localaiming2 = 0;
|
||||
modulothing = 0;
|
||||
|
||||
// special stage tokens, emeralds, and ring total
|
||||
|
@ -3426,6 +3467,9 @@ void P_RespawnThings(void)
|
|||
|
||||
P_InitLevelSettings();
|
||||
|
||||
localaiming = 0;
|
||||
localaiming2 = 0;
|
||||
|
||||
P_SpawnMapThings(true);
|
||||
|
||||
// restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that
|
||||
|
@ -3933,7 +3977,7 @@ static void P_InitGametype(void)
|
|||
* \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot.
|
||||
* \todo Clean up, refactor, split up; get rid of the bloat.
|
||||
*/
|
||||
boolean P_LoadLevel(boolean fromnetsave)
|
||||
boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
||||
{
|
||||
// use gamemap to get map number.
|
||||
// 99% of the things already did, so.
|
||||
|
@ -4003,44 +4047,49 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
players[consoleplayer].viewz = 1;
|
||||
|
||||
// Cancel all d_main.c fadeouts (keep fade in though).
|
||||
wipegamestate = FORCEWIPEOFF;
|
||||
if (reloadinggamestate)
|
||||
wipegamestate = gamestate; // Don't fade if reloading the gamestate
|
||||
else
|
||||
wipegamestate = FORCEWIPEOFF;
|
||||
wipestyleflags = 0;
|
||||
|
||||
// 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();
|
||||
|
||||
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
|
||||
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
|
||||
if (!titlemapinaction && (RESETMUSIC ||
|
||||
if (!(reloadinggamestate || titlemapinaction) && (RESETMUSIC ||
|
||||
strnicmp(S_MusicName(),
|
||||
(mapmusflags & MUSIC_RELOADRESET) ? mapheaderinfo[gamemap-1]->musname : mapmusname, 7)))
|
||||
{
|
||||
S_FadeMusic(0, FixedMul(
|
||||
FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE));
|
||||
}
|
||||
|
||||
// Let's fade to black here
|
||||
// But only if we didn't do the special stage wipe
|
||||
if (rendermode != render_none && !ranspecialwipe)
|
||||
if (rendermode != render_none && !(ranspecialwipe || reloadinggamestate))
|
||||
P_RunLevelWipe();
|
||||
|
||||
if (!titlemapinaction)
|
||||
if (!(reloadinggamestate || titlemapinaction))
|
||||
{
|
||||
if (ranspecialwipe == 2)
|
||||
{
|
||||
|
@ -4162,7 +4211,12 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
if (!fromnetsave)
|
||||
P_InitGametype();
|
||||
|
||||
P_InitCamera();
|
||||
if (!reloadinggamestate)
|
||||
{
|
||||
P_InitCamera();
|
||||
localaiming = 0;
|
||||
localaiming2 = 0;
|
||||
}
|
||||
|
||||
// clear special respawning que
|
||||
iquehead = iquetail = 0;
|
||||
|
@ -4170,7 +4224,7 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
P_MapEnd();
|
||||
|
||||
// Remove the loading shit from the screen
|
||||
if (rendermode != render_none && !titlemapinaction)
|
||||
if (rendermode != render_none && !(titlemapinaction || reloadinggamestate))
|
||||
F_WipeColorFill(levelfadecol);
|
||||
|
||||
if (precache || dedicated)
|
||||
|
@ -4179,9 +4233,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;
|
||||
|
@ -4214,8 +4268,8 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
LUAh_MapLoad();
|
||||
}
|
||||
|
||||
// No render mode, stop here.
|
||||
if (rendermode == render_none)
|
||||
// No render mode or reloading gamestate, stop here.
|
||||
if (rendermode == render_none || reloadinggamestate)
|
||||
return true;
|
||||
|
||||
// Title card!
|
||||
|
|
|
@ -97,7 +97,7 @@ void P_SetupLevelSky(INT32 skynum, boolean global);
|
|||
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
|
||||
#endif
|
||||
void P_RespawnThings(void);
|
||||
boolean P_LoadLevel(boolean fromnetsave);
|
||||
boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
|
||||
#ifdef HWRENDER
|
||||
void HWR_LoadLevel(void);
|
||||
#endif
|
||||
|
@ -105,7 +105,7 @@ boolean P_AddWadFile(const char *wadfilename);
|
|||
boolean P_RunSOC(const char *socfilename);
|
||||
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
void P_WriteThings(lumpnum_t lump);
|
||||
void P_WriteThings(void);
|
||||
size_t P_PrecacheLevelFlats(void);
|
||||
void P_AllocMapHeader(INT16 i);
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ void T_DynamicSlopeVert (dynplanethink_t* th)
|
|||
INT32 l;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
l = P_FindSpecialLineFromTag(799, th->tags[i], -1);
|
||||
l = Tag_FindLineSpecial(799, th->tags[i]);
|
||||
if (l != -1) {
|
||||
th->vex[i].z = lines[l].frontsector->floorheight;
|
||||
}
|
||||
|
@ -405,9 +405,6 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
|
|||
P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if(!line->tag)
|
||||
return;
|
||||
}
|
||||
|
||||
/// Creates a new slope from three mapthings with the specified IDs
|
||||
|
@ -426,11 +423,11 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
|
|||
if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
|
||||
continue;
|
||||
|
||||
if (!vertices[0] && mt->tag == tag1)
|
||||
if (!vertices[0] && Tag_Find(&mt->tags, tag1))
|
||||
vertices[0] = mt;
|
||||
else if (!vertices[1] && mt->tag == tag2)
|
||||
else if (!vertices[1] && Tag_Find(&mt->tags, tag2))
|
||||
vertices[1] = mt;
|
||||
else if (!vertices[2] && mt->tag == tag3)
|
||||
else if (!vertices[2] && Tag_Find(&mt->tags, tag3))
|
||||
vertices[2] = mt;
|
||||
}
|
||||
|
||||
|
@ -549,11 +546,11 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling)
|
|||
{
|
||||
INT32 i;
|
||||
pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope;
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
|
||||
if (!tag || *secslope)
|
||||
return false;
|
||||
|
||||
for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0;)
|
||||
TAG_ITER_SECTORS(0, tag, i)
|
||||
{
|
||||
pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope;
|
||||
if (srcslope)
|
||||
|
|
426
src/p_spec.c
426
src/p_spec.c
File diff suppressed because it is too large
Load diff
|
@ -55,9 +55,6 @@ fixed_t P_FindNextLowestFloor(sector_t *sec, fixed_t currentheight);
|
|||
fixed_t P_FindLowestCeilingSurrounding(sector_t *sec);
|
||||
fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
|
||||
|
||||
INT32 P_FindSectorFromTag(INT16 tag, INT32 start);
|
||||
INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start);
|
||||
|
||||
INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
|
||||
|
||||
void P_SetupSignExit(player_t *player);
|
||||
|
@ -67,7 +64,6 @@ void P_SwitchWeather(INT32 weathernum);
|
|||
|
||||
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
|
||||
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
|
||||
void P_ChangeSectorTag(UINT32 sector, INT16 newtag);
|
||||
void P_RunNightserizeExecutors(mobj_t *actor);
|
||||
void P_RunDeNightserizeExecutors(mobj_t *actor);
|
||||
void P_RunNightsLapExecutors(mobj_t *actor);
|
||||
|
|
13
src/p_tick.c
13
src/p_tick.c
|
@ -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
|
||||
|
|
316
src/p_user.c
316
src/p_user.c
|
@ -2029,6 +2029,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
|
|||
ghost->colorized = mobj->colorized; // alternatively, "true" for sonic advance style colourisation
|
||||
|
||||
ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle);
|
||||
ghost->rollangle = mobj->rollangle;
|
||||
ghost->sprite = mobj->sprite;
|
||||
ghost->sprite2 = mobj->sprite2;
|
||||
ghost->frame = mobj->frame;
|
||||
|
@ -2564,7 +2565,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 +2612,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 +2634,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 +3215,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 +3256,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 +3301,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 +3358,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 +3398,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 +5007,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 +5126,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,107 +5153,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->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;
|
||||
player->secondjump = 0;
|
||||
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))
|
||||
|
@ -10559,6 +10573,7 @@ static void P_CalcPostImg(player_t *player)
|
|||
postimg_t *type;
|
||||
INT32 *param;
|
||||
fixed_t pviewheight;
|
||||
size_t i;
|
||||
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
pviewheight = player->mo->z + player->mo->height - player->viewheight;
|
||||
|
@ -10583,28 +10598,45 @@ static void P_CalcPostImg(player_t *player)
|
|||
}
|
||||
|
||||
// see if we are in heat (no, not THAT kind of heat...)
|
||||
|
||||
if (P_FindSpecialLineFromTag(13, sector->tag, -1) != -1)
|
||||
*type = postimg_heat;
|
||||
else if (sector->ffloors)
|
||||
for (i = 0; i < sector->tags.count; i++)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t topheight;
|
||||
fixed_t bottomheight;
|
||||
|
||||
for (rover = sector->ffloors; rover; rover = rover->next)
|
||||
if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS))
|
||||
continue;
|
||||
*type = postimg_heat;
|
||||
break;
|
||||
}
|
||||
else if (sector->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t topheight;
|
||||
fixed_t bottomheight;
|
||||
boolean gotres = false;
|
||||
|
||||
topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y);
|
||||
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y);
|
||||
for (rover = sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
if (pviewheight >= topheight || pviewheight <= bottomheight)
|
||||
continue;
|
||||
if (!(rover->flags & FF_EXISTS))
|
||||
continue;
|
||||
|
||||
if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
|
||||
*type = postimg_heat;
|
||||
topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y);
|
||||
bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y);
|
||||
|
||||
if (pviewheight >= topheight || pviewheight <= bottomheight)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < rover->master->frontsector->tags.count; j++)
|
||||
{
|
||||
if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1)
|
||||
{
|
||||
*type = postimg_heat;
|
||||
gotres = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gotres)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10703,22 +10735,21 @@ static sector_t *P_GetMinecartSector(fixed_t x, fixed_t y, fixed_t z, fixed_t *n
|
|||
static INT32 P_GetMinecartSpecialLine(sector_t *sec)
|
||||
{
|
||||
INT32 line = -1;
|
||||
size_t i;
|
||||
|
||||
if (!sec)
|
||||
return line;
|
||||
|
||||
if (sec->tag != 0)
|
||||
line = P_FindSpecialLineFromTag(16, sec->tag, -1);
|
||||
for (i = 0; i < sec->tags.count; i++)
|
||||
if (sec->tags.tags[i] != 0)
|
||||
line = Tag_FindLineSpecial(16, sec->tags.tags[i]);
|
||||
|
||||
// Also try for lines facing the sector itself, with tag 0.
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
UINT32 i;
|
||||
for (i = 0; i < sec->linecount; i++)
|
||||
{
|
||||
line_t *li = sec->lines[i];
|
||||
if (li->tag == 0 && li->special == 16 && li->frontsector == sec)
|
||||
line = li - lines;
|
||||
}
|
||||
line_t *li = sec->lines[i];
|
||||
if (Tag_Find(&li->tags, 0) && li->special == 16 && li->frontsector == sec)
|
||||
line = li - lines;
|
||||
}
|
||||
|
||||
return line;
|
||||
|
@ -11187,6 +11218,8 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails)
|
|||
chosenstate = S_TAILSOVERLAY_GASP;
|
||||
else if (player->mo->state-states == S_PLAY_EDGE)
|
||||
chosenstate = S_TAILSOVERLAY_EDGE;
|
||||
else if (player->panim == PA_DASH)
|
||||
chosenstate = S_TAILSOVERLAY_DASH;
|
||||
else if (player->panim == PA_RUN)
|
||||
chosenstate = S_TAILSOVERLAY_RUN;
|
||||
else if (player->panim == PA_WALK)
|
||||
|
@ -12275,12 +12308,14 @@ void P_PlayerThink(player_t *player)
|
|||
sector_t *controlsec;
|
||||
for (j=0; j<numsectors; j++)
|
||||
{
|
||||
mtag_t sectag = Tag_FGet(§ors[j].tags);
|
||||
controlsec = NULL;
|
||||
// Does this sector have a water linedef?
|
||||
for (i=0; i<numlines;i++)
|
||||
{
|
||||
mtag_t linetag = Tag_FGet(&lines[i].tags);
|
||||
if ((lines[i].special == 121 || lines[i].special == 123)
|
||||
&& lines[i].tag == sectors[j].tag)
|
||||
&& linetag == sectag)
|
||||
{
|
||||
controlsec = lines[i].frontsector;
|
||||
break;
|
||||
|
@ -12289,15 +12324,16 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
if (i < numlines && controlsec)
|
||||
{
|
||||
controlsectag = Tag_FGet(&controlsec->tags);
|
||||
// Does this sector have a colormap?
|
||||
for (i=0; i<numlines;i++)
|
||||
{
|
||||
if (lines[i].special == 606 && lines[i].tag == controlsec->tag)
|
||||
if (lines[i].special == 606 && linetag == controlsectag)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == numlines)
|
||||
CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectors[j].tag);
|
||||
CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
31
src/r_bsp.c
31
src/r_bsp.c
|
@ -21,6 +21,7 @@
|
|||
#include "p_local.h" // camera
|
||||
#include "p_slopes.h"
|
||||
#include "z_zone.h" // Check R_Prep3DFloors
|
||||
#include "taglist.h"
|
||||
|
||||
seg_t *curline;
|
||||
side_t *sidedef;
|
||||
|
@ -374,7 +375,7 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
|
|||
// Consider colormaps
|
||||
&& back->extra_colormap == front->extra_colormap
|
||||
&& ((!front->ffloors && !back->ffloors)
|
||||
|| front->tag == back->tag));
|
||||
|| Tag_Compare(&front->tags, &back->tags)));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -448,21 +449,25 @@ static void R_AddLine(seg_t *line)
|
|||
// Portal line
|
||||
if (line->linedef->special == 40 && line->side == 0)
|
||||
{
|
||||
// Render portal if recursiveness limit hasn't been reached.
|
||||
// Otherwise, render the wall normally.
|
||||
if (portalrender < cv_maxportals.value)
|
||||
{
|
||||
// Find the other side!
|
||||
INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1);
|
||||
if (line->linedef == &lines[line2])
|
||||
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2);
|
||||
if (line2 >= 0) // found it!
|
||||
size_t p;
|
||||
mtag_t tag = Tag_FGet(&line->linedef->tags);
|
||||
INT32 li1 = line->linedef-lines;
|
||||
INT32 li2;
|
||||
|
||||
for (p = 0; (li2 = Tag_Iterate_Lines(tag, p)) >= 0; p++)
|
||||
{
|
||||
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
|
||||
//return; // Don't fill in that space now!
|
||||
// Skip invalid lines.
|
||||
if ((tag != Tag_FGet(&lines[li2].tags)) || (lines[li1].special != lines[li2].special) || (li1 == li2))
|
||||
continue;
|
||||
|
||||
Portal_Add2Lines(li1, li2, x1, x2);
|
||||
goto clipsolid;
|
||||
}
|
||||
}
|
||||
// Recursed TOO FAR (viewing a portal within a portal)
|
||||
// So uhhh, render it as a normal wall instead or something ???
|
||||
}
|
||||
|
||||
// Single sided line?
|
||||
|
@ -483,7 +488,7 @@ static void R_AddLine(seg_t *line)
|
|||
if (!line->polyseg &&
|
||||
!line->sidedef->midtexture
|
||||
&& ((!frontsector->ffloors && !backsector->ffloors)
|
||||
|| (frontsector->tag == backsector->tag)))
|
||||
|| Tag_Compare(&frontsector->tags, &backsector->tags)))
|
||||
return; // line is empty, don't even bother
|
||||
|
||||
goto clippass; // treat like wide open window instead
|
||||
|
@ -799,7 +804,7 @@ static void R_AddPolyObjects(subsector_t *sub)
|
|||
}
|
||||
|
||||
// for render stats
|
||||
rs_numpolyobjects += numpolys;
|
||||
ps_numpolyobjects += numpolys;
|
||||
|
||||
// sort polyobjects
|
||||
R_SortPolyObjects(sub);
|
||||
|
@ -1234,7 +1239,7 @@ void R_RenderBSPNode(INT32 bspnum)
|
|||
node_t *bsp;
|
||||
INT32 side;
|
||||
|
||||
rs_numbspcalls++;
|
||||
ps_numbspcalls++;
|
||||
|
||||
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
|
||||
{
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "m_aatree.h"
|
||||
#endif
|
||||
|
||||
#include "taglist.h"
|
||||
|
||||
//
|
||||
// ClipWallSegment
|
||||
// Clips the given range of columns
|
||||
|
@ -281,8 +283,7 @@ typedef struct sector_s
|
|||
INT32 ceilingpic;
|
||||
INT16 lightlevel;
|
||||
INT16 special;
|
||||
UINT16 tag;
|
||||
INT32 nexttag, firsttag; // for fast tag searches
|
||||
taglist_t tags;
|
||||
|
||||
// origin for any sounds played by the sector
|
||||
// also considered the center for e.g. Mario blocks
|
||||
|
@ -389,7 +390,7 @@ typedef struct line_s
|
|||
// Animation related.
|
||||
INT16 flags;
|
||||
INT16 special;
|
||||
INT16 tag;
|
||||
taglist_t tags;
|
||||
INT32 args[NUMLINEARGS];
|
||||
char *stringargs[NUMLINESTRINGARGS];
|
||||
|
||||
|
@ -409,7 +410,6 @@ typedef struct line_s
|
|||
sector_t *backsector;
|
||||
|
||||
size_t validcount; // if == validcount, already checked
|
||||
INT32 firsttag, nexttag; // improves searches for tags.
|
||||
polyobj_t *polyobj; // Belongs to a polyobject?
|
||||
|
||||
char *text; // a concatenation of all front and back texture names, for linedef specials that require a string.
|
||||
|
|
|
@ -26,6 +26,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;
|
||||
|
@ -44,19 +46,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;
|
||||
|
@ -660,6 +682,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;
|
||||
|
@ -676,20 +700,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];
|
||||
|
@ -707,6 +750,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;
|
||||
|
@ -723,20 +768,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);
|
||||
|
@ -1152,6 +1216,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;
|
||||
|
@ -1168,20 +1234,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++;
|
||||
|
@ -1195,6 +1280,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;
|
||||
|
@ -1212,20 +1299,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;
|
||||
|
|
50
src/r_main.c
50
src/r_main.c
|
@ -100,22 +100,22 @@ lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
|
|||
extracolormap_t *extra_colormaps = NULL;
|
||||
|
||||
// Render stats
|
||||
int rs_prevframetime = 0;
|
||||
int rs_rendercalltime = 0;
|
||||
int rs_uitime = 0;
|
||||
int rs_swaptime = 0;
|
||||
int rs_tictime = 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"},
|
||||
|
@ -151,6 +151,7 @@ consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT,
|
|||
|
||||
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);
|
||||
|
@ -1496,11 +1497,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
|
||||
|
@ -1510,7 +1511,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.
|
||||
|
@ -1518,7 +1521,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;
|
||||
|
@ -1558,17 +1561,17 @@ 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();
|
||||
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);
|
||||
}
|
||||
|
@ -1601,6 +1604,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);
|
||||
|
|
29
src/r_main.h
29
src/r_main.h
|
@ -78,24 +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_uitime;
|
||||
extern int rs_swaptime;
|
||||
extern int rs_tictime;
|
||||
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.
|
||||
|
@ -107,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;
|
||||
|
|
|
@ -969,26 +969,45 @@ static png_bytep *PNG_Read(
|
|||
// matches the color count of SRB2's palette: 256 colors.
|
||||
if (png_get_PLTE(png_ptr, png_info_ptr, &palette, &palette_size))
|
||||
{
|
||||
if (palette_size == 256)
|
||||
if (palette_size == 256 && pMasterPalette)
|
||||
{
|
||||
png_colorp pal = palette;
|
||||
INT32 i;
|
||||
|
||||
usepal = true;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UINT32 rgb = R_PutRgbaRGBA(pal->red, pal->green, pal->blue, 0xFF);
|
||||
if (rgb != pMasterPalette[i].rgba)
|
||||
{
|
||||
usepal = false;
|
||||
break;
|
||||
}
|
||||
pal++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If any of the tRNS colors have an alpha lower than 0xFF, and that
|
||||
// color is present on the image, the palette flag is disabled.
|
||||
png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values);
|
||||
|
||||
if (trans && trans_num == 256)
|
||||
if (usepal)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < trans_num; i++)
|
||||
png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values);
|
||||
|
||||
if (trans && trans_num == 256)
|
||||
{
|
||||
// libpng will transform this image into RGB even if
|
||||
// the transparent index does not exist in the image,
|
||||
// and there is no way around that.
|
||||
if (trans[i] < 0xFF)
|
||||
INT32 i;
|
||||
for (i = 0; i < trans_num; i++)
|
||||
{
|
||||
usepal = false;
|
||||
break;
|
||||
// libpng will transform this image into RGB even if
|
||||
// the transparent index does not exist in the image,
|
||||
// and there is no way around that.
|
||||
if (trans[i] < 0xFF)
|
||||
{
|
||||
usepal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,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;
|
||||
|
@ -397,28 +397,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);
|
||||
|
||||
|
@ -488,9 +490,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;
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
#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?
|
||||
|
|
149
src/r_segs.c
149
src/r_segs.c
|
@ -25,6 +25,7 @@
|
|||
#include "p_local.h" // Camera...
|
||||
#include "p_slopes.h"
|
||||
#include "console.h" // con_clipviewtop
|
||||
#include "taglist.h"
|
||||
|
||||
// OPTIMIZE: closed two sided lines as single sided
|
||||
|
||||
|
@ -55,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;
|
||||
|
@ -522,6 +532,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.
|
||||
|
@ -1024,7 +1047,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)
|
||||
{
|
||||
|
@ -1034,6 +1057,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
|
||||
|
@ -1115,8 +1146,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
|
||||
|
@ -1147,8 +1183,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1173,8 +1231,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1280,20 +1360,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)
|
||||
{
|
||||
|
@ -1307,7 +1392,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;
|
||||
|
@ -1318,14 +1406,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)
|
||||
{
|
||||
|
@ -1340,7 +1428,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;
|
||||
|
@ -1352,14 +1443,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)
|
||||
|
@ -1813,7 +1904,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
|| backsector->floorlightsec != frontsector->floorlightsec
|
||||
//SoM: 4/3/2000: Check for colormaps
|
||||
|| frontsector->extra_colormap != backsector->extra_colormap
|
||||
|| (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag))
|
||||
|| (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags)))
|
||||
{
|
||||
markfloor = true;
|
||||
}
|
||||
|
@ -1844,7 +1935,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
|| backsector->ceilinglightsec != frontsector->ceilinglightsec
|
||||
//SoM: 4/3/2000: Check for colormaps
|
||||
|| frontsector->extra_colormap != backsector->extra_colormap
|
||||
|| (frontsector->ffloors != backsector->ffloors && frontsector->tag != backsector->tag))
|
||||
|| (frontsector->ffloors != backsector->ffloors && !Tag_Compare(&frontsector->tags, &backsector->tags)))
|
||||
{
|
||||
markceiling = true;
|
||||
}
|
||||
|
@ -1934,7 +2025,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
rw_bottomtexturemid += sidedef->rowoffset;
|
||||
|
||||
// allocate space for masked texture tables
|
||||
if (frontsector && backsector && frontsector->tag != backsector->tag && (backsector->ffloors || frontsector->ffloors))
|
||||
if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors))
|
||||
{
|
||||
ffloor_t *rover;
|
||||
ffloor_t *r2;
|
||||
|
@ -1976,6 +2067,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
|
||||
for (r2 = frontsector->ffloors; r2; r2 = r2->next)
|
||||
{
|
||||
if (r2->master == rover->master) // Skip if same control line.
|
||||
break;
|
||||
|
||||
if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
|
||||
continue;
|
||||
|
||||
|
@ -2031,6 +2125,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
|
||||
for (r2 = backsector->ffloors; r2; r2 = r2->next)
|
||||
{
|
||||
if (r2->master == rover->master) // Skip if same control line.
|
||||
break;
|
||||
|
||||
if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
|
||||
continue;
|
||||
|
||||
|
@ -2622,6 +2719,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
}
|
||||
}
|
||||
|
||||
rw_silhouette = &(ds_p->silhouette);
|
||||
rw_tsilheight = &(ds_p->tsilheight);
|
||||
rw_bsilheight = &(ds_p->bsilheight);
|
||||
|
||||
R_RenderSegLoop();
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
|
||||
|
|
|
@ -2744,7 +2744,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link)
|
|||
node->ffloor = NULL;
|
||||
node->sprite = NULL;
|
||||
|
||||
rs_numdrawnodes++;
|
||||
ps_numdrawnodes++;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,7 @@
|
|||
#include "fastcmp.h"
|
||||
#include "m_misc.h" // for tunes command
|
||||
#include "m_cond.h" // for conditionsets
|
||||
|
||||
#ifdef HAVE_LUA_MUSICPLUS
|
||||
#include "lua_hook.h" // MusicChange hook
|
||||
#endif
|
||||
|
||||
#ifdef HW3SOUND
|
||||
// 3D Sound Interface
|
||||
|
@ -2272,10 +2269,8 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
|
|||
return;
|
||||
|
||||
strncpy(newmusic, mmusic, 7);
|
||||
#ifdef HAVE_LUA_MUSICPLUS
|
||||
if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
|
||||
if (LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
|
||||
return;
|
||||
#endif
|
||||
newmusic[6] = 0;
|
||||
|
||||
// No Music (empty string)
|
||||
|
|
|
@ -55,6 +55,10 @@ set(SRB2_SDL2_HEADERS
|
|||
sdlmain.h
|
||||
)
|
||||
|
||||
if(${SRB2_CONFIG_HAVE_THREADS})
|
||||
set(SRB2_SDL2_SOURCES ${SRB2_SDL2_SOURCES} i_threads.c)
|
||||
endif()
|
||||
|
||||
source_group("Interface Code" FILES ${SRB2_SDL2_SOURCES} ${SRB2_SDL2_HEADERS})
|
||||
|
||||
# Dependency
|
||||
|
@ -268,7 +272,7 @@ if(${SDL2_FOUND})
|
|||
endif()
|
||||
|
||||
target_compile_definitions(SRB2SDL2 PRIVATE
|
||||
-DDDIRECTFULLSCREEN -DHAVE_SDL
|
||||
-DDIRECTFULLSCREEN -DHAVE_SDL
|
||||
)
|
||||
|
||||
## strip debug symbols into separate file when using gcc.
|
||||
|
|
|
@ -262,6 +262,7 @@
|
|||
<ClInclude Include="..\m_fixed.h" />
|
||||
<ClInclude Include="..\m_menu.h" />
|
||||
<ClInclude Include="..\m_misc.h" />
|
||||
<ClInclude Include="..\m_perfstats.h" />
|
||||
<ClInclude Include="..\m_queue.h" />
|
||||
<ClInclude Include="..\m_random.h" />
|
||||
<ClInclude Include="..\m_swap.h" />
|
||||
|
@ -403,6 +404,7 @@
|
|||
<ClCompile Include="..\lua_mathlib.c" />
|
||||
<ClCompile Include="..\lua_mobjlib.c" />
|
||||
<ClCompile Include="..\lua_playerlib.c" />
|
||||
<ClCompile Include="..\lua_polyobjlib.c" />
|
||||
<ClCompile Include="..\lua_script.c" />
|
||||
<ClCompile Include="..\lua_skinlib.c" />
|
||||
<ClCompile Include="..\lua_thinkerlib.c" />
|
||||
|
@ -419,6 +421,7 @@
|
|||
<ClCompile Include="..\m_fixed.c" />
|
||||
<ClCompile Include="..\m_menu.c" />
|
||||
<ClCompile Include="..\m_misc.c" />
|
||||
<ClCompile Include="..\m_perfstats.c" />
|
||||
<ClCompile Include="..\m_queue.c" />
|
||||
<ClCompile Include="..\m_random.c" />
|
||||
<ClCompile Include="..\p_ceilng.c" />
|
||||
|
|
|
@ -348,6 +348,9 @@
|
|||
<ClInclude Include="..\m_misc.h">
|
||||
<Filter>M_Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\m_perfstats.h">
|
||||
<Filter>M_Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\m_queue.h">
|
||||
<Filter>M_Misc</Filter>
|
||||
</ClInclude>
|
||||
|
@ -729,6 +732,9 @@
|
|||
<ClCompile Include="..\lua_playerlib.c">
|
||||
<Filter>LUA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lua_polyobjlib.c">
|
||||
<Filter>LUA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lua_script.c">
|
||||
<Filter>LUA</Filter>
|
||||
</ClCompile>
|
||||
|
@ -768,6 +774,9 @@
|
|||
<ClCompile Include="..\m_misc.c">
|
||||
<Filter>M_Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\m_perfstats.c">
|
||||
<Filter>M_Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\m_queue.c">
|
||||
<Filter>M_Misc</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -105,14 +105,13 @@ void *hwSym(const char *funcName,void *handle)
|
|||
GETFUNC(MakeScreenFinalTexture);
|
||||
GETFUNC(DrawScreenFinalTexture);
|
||||
|
||||
GETFUNC(LoadShaders);
|
||||
GETFUNC(KillShaders);
|
||||
GETFUNC(CompileShaders);
|
||||
GETFUNC(CleanShaders);
|
||||
GETFUNC(SetShader);
|
||||
GETFUNC(UnSetShader);
|
||||
|
||||
GETFUNC(SetShaderInfo);
|
||||
GETFUNC(LoadCustomShader);
|
||||
GETFUNC(InitCustomShaders);
|
||||
|
||||
#else //HWRENDER
|
||||
if (0 == strcmp("FinishUpdate", funcName))
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
#ifdef HAVE_IMAGE
|
||||
#include "SDL_image.h"
|
||||
#elif defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) // Windows doesn't need this, as SDL will do it for us.
|
||||
#elif defined (__unix__) || (!defined(__APPLE__) && defined (UNIXCOMMON)) // Windows & Mac don't need this, as SDL will do it for us.
|
||||
#define LOAD_XPM //I want XPM!
|
||||
#include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so
|
||||
#define HAVE_IMAGE //I have SDL_Image, sortof
|
||||
|
@ -1884,14 +1884,13 @@ void VID_StartupOpenGL(void)
|
|||
HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
|
||||
HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
|
||||
|
||||
HWD.pfnLoadShaders = hwSym("LoadShaders",NULL);
|
||||
HWD.pfnKillShaders = hwSym("KillShaders",NULL);
|
||||
HWD.pfnCompileShaders = hwSym("CompileShaders",NULL);
|
||||
HWD.pfnCleanShaders = hwSym("CleanShaders",NULL);
|
||||
HWD.pfnSetShader = hwSym("SetShader",NULL);
|
||||
HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
|
||||
|
||||
HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL);
|
||||
HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
|
||||
HWD.pfnInitCustomShaders= hwSym("InitCustomShaders",NULL);
|
||||
|
||||
vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ boolean OglSdlSurface(INT32 w, INT32 h)
|
|||
|
||||
SetupGLFunc4();
|
||||
|
||||
granisotropicmode_cons_t[1].value = maximumAnisotropy;
|
||||
glanisotropicmode_cons_t[1].value = maximumAnisotropy;
|
||||
|
||||
SDL_GL_SetSwapInterval(cv_vidwait.value ? 1 : 0);
|
||||
|
||||
|
|
366
src/taglist.c
Normal file
366
src/taglist.c
Normal file
|
@ -0,0 +1,366 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2020 by Nev3r.
|
||||
//
|
||||
// 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 taglist.c
|
||||
/// \brief Ingame sector/line/mapthing tagging.
|
||||
|
||||
#include "taglist.h"
|
||||
#include "z_zone.h"
|
||||
#include "r_data.h"
|
||||
|
||||
// Taggroups are used to list elements of the same tag, for iteration.
|
||||
// Since elements can now have multiple tags, it means an element may appear
|
||||
// in several taggroups at the same time. These are built on level load.
|
||||
taggroup_t* tags_sectors[MAXTAGS + 1];
|
||||
taggroup_t* tags_lines[MAXTAGS + 1];
|
||||
taggroup_t* tags_mapthings[MAXTAGS + 1];
|
||||
|
||||
/// Adds a tag to a given element's taglist.
|
||||
/// \warning This does not rebuild the global taggroups, which are used for iteration.
|
||||
void Tag_Add (taglist_t* list, const mtag_t tag)
|
||||
{
|
||||
list->tags = Z_Realloc(list->tags, (list->count + 1) * sizeof(list->tags), PU_LEVEL, NULL);
|
||||
list->tags[list->count++] = tag;
|
||||
}
|
||||
|
||||
/// Sets the first tag entry in a taglist.
|
||||
/// Replicates the old way of accessing element->tag.
|
||||
void Tag_FSet (taglist_t* list, const mtag_t tag)
|
||||
{
|
||||
if (!list->count)
|
||||
{
|
||||
Tag_Add(list, tag);
|
||||
return;
|
||||
}
|
||||
|
||||
list->tags[0] = tag;
|
||||
}
|
||||
|
||||
/// Gets the first tag entry in a taglist.
|
||||
/// Replicates the old way of accessing element->tag.
|
||||
mtag_t Tag_FGet (const taglist_t* list)
|
||||
{
|
||||
if (list->count)
|
||||
return list->tags[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Returns true if the given tag exist inside the list.
|
||||
boolean Tag_Find (const taglist_t* list, const mtag_t tag)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < list->count; i++)
|
||||
if (list->tags[i] == tag)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns true if at least one tag is shared between two given lists.
|
||||
boolean Tag_Share (const taglist_t* list1, const taglist_t* list2)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < list1->count; i++)
|
||||
if (Tag_Find(list2, list1->tags[i]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns true if both lists are identical.
|
||||
boolean Tag_Compare (const taglist_t* list1, const taglist_t* list2)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (list1->count != list2->count)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < list1->count; i++)
|
||||
if (list1->tags[i] != list2->tags[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Search for an element inside a global taggroup.
|
||||
size_t Taggroup_Find (const taggroup_t *group, const size_t id)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!group)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < group->count; i++)
|
||||
if (group->elements[i] == id)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Add an element to a global taggroup.
|
||||
void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id)
|
||||
{
|
||||
taggroup_t *group;
|
||||
size_t i; // Insert position.
|
||||
|
||||
if (tag == MTAG_GLOBAL)
|
||||
return;
|
||||
|
||||
group = garray[(UINT16)tag];
|
||||
|
||||
// Don't add duplicate entries.
|
||||
if (Taggroup_Find(group, id) != (size_t)-1)
|
||||
return;
|
||||
|
||||
// Create group if empty.
|
||||
if (!group)
|
||||
{
|
||||
i = 0;
|
||||
group = garray[(UINT16)tag] = Z_Calloc(sizeof(taggroup_t), PU_LEVEL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep the group element ids in an ascending order.
|
||||
// Find the location to insert the element to.
|
||||
for (i = 0; i < group->count; i++)
|
||||
if (group->elements[i] > id)
|
||||
break;
|
||||
|
||||
group->elements = Z_Realloc(group->elements, (group->count + 1) * sizeof(size_t), PU_LEVEL, NULL);
|
||||
|
||||
// Offset existing elements to make room for the new one.
|
||||
if (i < group->count)
|
||||
memmove(&group->elements[i + 1], &group->elements[i], group->count - i);
|
||||
}
|
||||
|
||||
group->count++;
|
||||
group->elements = Z_Realloc(group->elements, group->count * sizeof(size_t), PU_LEVEL, NULL);
|
||||
group->elements[i] = id;
|
||||
}
|
||||
|
||||
/// Remove an element from a global taggroup.
|
||||
void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id)
|
||||
{
|
||||
taggroup_t *group;
|
||||
size_t rempos;
|
||||
size_t newcount;
|
||||
|
||||
if (tag == MTAG_GLOBAL)
|
||||
return;
|
||||
|
||||
group = garray[(UINT16)tag];
|
||||
|
||||
if ((rempos = Taggroup_Find(group, id)) == (size_t)-1)
|
||||
return;
|
||||
|
||||
// Strip away taggroup if no elements left.
|
||||
if (!(newcount = --group->count))
|
||||
{
|
||||
Z_Free(group->elements);
|
||||
Z_Free(group);
|
||||
garray[(UINT16)tag] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t *newelements = Z_Malloc(newcount * sizeof(size_t), PU_LEVEL, NULL);
|
||||
size_t i;
|
||||
|
||||
// Copy the previous entries save for the one to remove.
|
||||
for (i = 0; i < rempos; i++)
|
||||
newelements[i] = group->elements[i];
|
||||
|
||||
for (i = rempos + 1; i < group->count; i++)
|
||||
newelements[i - 1] = group->elements[i];
|
||||
|
||||
Z_Free(group->elements);
|
||||
group->elements = newelements;
|
||||
group->count = newcount;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialization.
|
||||
|
||||
static void Taglist_AddToSectors (const mtag_t tag, const size_t itemid)
|
||||
{
|
||||
Taggroup_Add(tags_sectors, tag, itemid);
|
||||
}
|
||||
|
||||
static void Taglist_AddToLines (const mtag_t tag, const size_t itemid)
|
||||
{
|
||||
Taggroup_Add(tags_lines, tag, itemid);
|
||||
}
|
||||
|
||||
static void Taglist_AddToMapthings (const mtag_t tag, const size_t itemid)
|
||||
{
|
||||
Taggroup_Add(tags_mapthings, tag, itemid);
|
||||
}
|
||||
|
||||
/// After all taglists have been built for each element (sectors, lines, things),
|
||||
/// the global taggroups, made for iteration, are built here.
|
||||
void Taglist_InitGlobalTables(void)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < MAXTAGS; i++)
|
||||
{
|
||||
tags_sectors[i] = NULL;
|
||||
tags_lines[i] = NULL;
|
||||
tags_mapthings[i] = NULL;
|
||||
}
|
||||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
for (j = 0; j < sectors[i].tags.count; j++)
|
||||
Taglist_AddToSectors(sectors[i].tags.tags[j], i);
|
||||
}
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
for (j = 0; j < lines[i].tags.count; j++)
|
||||
Taglist_AddToLines(lines[i].tags.tags[j], i);
|
||||
}
|
||||
for (i = 0; i < nummapthings; i++)
|
||||
{
|
||||
for (j = 0; j < mapthings[i].tags.count; j++)
|
||||
Taglist_AddToMapthings(mapthings[i].tags.tags[j], i);
|
||||
}
|
||||
}
|
||||
|
||||
// Iteration, ingame search.
|
||||
|
||||
INT32 Tag_Iterate_Sectors (const mtag_t tag, const size_t p)
|
||||
{
|
||||
if (tag == MTAG_GLOBAL)
|
||||
{
|
||||
if (p < numsectors)
|
||||
return p;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tags_sectors[(UINT16)tag])
|
||||
{
|
||||
if (p < tags_sectors[(UINT16)tag]->count)
|
||||
return tags_sectors[(UINT16)tag]->elements[p];
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
INT32 Tag_Iterate_Lines (const mtag_t tag, const size_t p)
|
||||
{
|
||||
if (tag == MTAG_GLOBAL)
|
||||
{
|
||||
if (p < numlines)
|
||||
return p;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tags_lines[(UINT16)tag])
|
||||
{
|
||||
if (p < tags_lines[(UINT16)tag]->count)
|
||||
return tags_lines[(UINT16)tag]->elements[p];
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p)
|
||||
{
|
||||
if (tag == MTAG_GLOBAL)
|
||||
{
|
||||
if (p < nummapthings)
|
||||
return p;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tags_mapthings[(UINT16)tag])
|
||||
{
|
||||
if (p < tags_mapthings[(UINT16)tag]->count)
|
||||
return tags_mapthings[(UINT16)tag]->elements[p];
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (tag == MTAG_GLOBAL)
|
||||
{
|
||||
for (i = 0; i < numlines; i++)
|
||||
if (lines[i].special == special)
|
||||
return i;
|
||||
}
|
||||
else if (tags_lines[(UINT16)tag])
|
||||
{
|
||||
taggroup_t *tagged = tags_lines[(UINT16)tag];
|
||||
for (i = 0; i < tagged->count; i++)
|
||||
if (lines[tagged->elements[i]].special == special)
|
||||
return tagged->elements[i];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Backwards compatibility iteration function for Lua scripts.
|
||||
INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start)
|
||||
{
|
||||
if (tag == -1)
|
||||
{
|
||||
start++;
|
||||
|
||||
if (start >= (INT32)numlines)
|
||||
return -1;
|
||||
|
||||
while (start < (INT32)numlines && lines[start].special != special)
|
||||
start++;
|
||||
|
||||
return start;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t p = 0;
|
||||
INT32 id;
|
||||
|
||||
// For backwards compatibility's sake, simulate the old linked taglist behavior:
|
||||
// Iterate through the taglist and find the "start" line's position in the list,
|
||||
// And start checking with the next one (if it exists).
|
||||
if (start != -1)
|
||||
{
|
||||
for (; (id = Tag_Iterate_Lines(tag, p)) >= 0; p++)
|
||||
if (id == start)
|
||||
{
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (; (id = Tag_Iterate_Lines(tag, p)) >= 0; p++)
|
||||
if (lines[id].special == special)
|
||||
return id;
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Ingame list manipulation.
|
||||
|
||||
/// Changes the first tag for a given sector, and updates the global taggroups.
|
||||
void Tag_SectorFSet (const size_t id, const mtag_t tag)
|
||||
{
|
||||
sector_t* sec = §ors[id];
|
||||
mtag_t curtag = Tag_FGet(&sec->tags);
|
||||
if (curtag == tag)
|
||||
return;
|
||||
|
||||
Taggroup_Remove(tags_sectors, curtag, id);
|
||||
Taggroup_Add(tags_sectors, tag, id);
|
||||
Tag_FSet(&sec->tags, tag);
|
||||
}
|
127
src/taglist.h
Normal file
127
src/taglist.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
// Copyright (C) 2020 by Nev3r.
|
||||
//
|
||||
// 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 taglist.h
|
||||
/// \brief Tag iteration and reading functions and macros' declarations.
|
||||
|
||||
#ifndef __R_TAGLIST__
|
||||
#define __R_TAGLIST__
|
||||
|
||||
#include "doomtype.h"
|
||||
|
||||
typedef INT16 mtag_t;
|
||||
#define MAXTAGS UINT16_MAX
|
||||
#define MTAG_GLOBAL -1
|
||||
|
||||
/// Multitag list. Each taggable element will have its own taglist.
|
||||
typedef struct
|
||||
{
|
||||
mtag_t* tags;
|
||||
UINT16 count;
|
||||
} taglist_t;
|
||||
|
||||
void Tag_Add (taglist_t* list, const mtag_t tag);
|
||||
void Tag_FSet (taglist_t* list, const mtag_t tag);
|
||||
mtag_t Tag_FGet (const taglist_t* list);
|
||||
boolean Tag_Find (const taglist_t* list, const mtag_t tag);
|
||||
boolean Tag_Share (const taglist_t* list1, const taglist_t* list2);
|
||||
boolean Tag_Compare (const taglist_t* list1, const taglist_t* list2);
|
||||
|
||||
void Tag_SectorFSet (const size_t id, const mtag_t tag);
|
||||
|
||||
/// Taggroup list. It is essentially just an element id list.
|
||||
typedef struct
|
||||
{
|
||||
size_t *elements;
|
||||
size_t count;
|
||||
} taggroup_t;
|
||||
|
||||
extern taggroup_t* tags_sectors[];
|
||||
extern taggroup_t* tags_lines[];
|
||||
extern taggroup_t* tags_mapthings[];
|
||||
|
||||
void Taggroup_Add (taggroup_t *garray[], const mtag_t tag, size_t id);
|
||||
void Taggroup_Remove (taggroup_t *garray[], const mtag_t tag, size_t id);
|
||||
size_t Taggroup_Find (const taggroup_t *group, const size_t id);
|
||||
|
||||
void Taglist_InitGlobalTables(void);
|
||||
|
||||
INT32 Tag_Iterate_Sectors (const mtag_t tag, const size_t p);
|
||||
INT32 Tag_Iterate_Lines (const mtag_t tag, const size_t p);
|
||||
INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p);
|
||||
|
||||
INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag);
|
||||
INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start);
|
||||
|
||||
// Use this macro to declare an iterator position variable.
|
||||
#define TAG_ITER_DECLARECOUNTER(level) size_t ICNT_##level
|
||||
|
||||
#define TAG_ITER(level, fn, tag, return_varname) for(ICNT_##level = 0; (return_varname = fn(tag, ICNT_##level)) >= 0; ICNT_##level++)
|
||||
|
||||
// Use these macros as wrappers for a taglist iteration.
|
||||
#define TAG_ITER_SECTORS(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Sectors, tag, return_varname)
|
||||
#define TAG_ITER_LINES(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Lines, tag, return_varname)
|
||||
#define TAG_ITER_THINGS(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Things, tag, return_varname)
|
||||
|
||||
/* ITERATION MACROS
|
||||
TAG_ITER_DECLARECOUNTER must be used before using the iterators.
|
||||
|
||||
'level':
|
||||
For each nested iteration, an additional TAG_ITER_DECLARECOUNTER
|
||||
must be used with a different level number to avoid conflict with
|
||||
the outer iterations.
|
||||
Most cases don't have nested iterations and thus the level is just 0.
|
||||
|
||||
'tag':
|
||||
Pretty much the elements' tag to iterate through.
|
||||
|
||||
'return_varname':
|
||||
Target variable's name to return the iteration results to.
|
||||
|
||||
|
||||
EXAMPLE:
|
||||
{
|
||||
TAG_ITER_DECLARECOUNTER(0);
|
||||
TAG_ITER_DECLARECOUNTER(1); // For the nested iteration.
|
||||
|
||||
size_t li;
|
||||
size_t sec;
|
||||
|
||||
INT32 tag1 = 4;
|
||||
|
||||
...
|
||||
|
||||
TAG_ITER_LINES(0, tag1, li)
|
||||
{
|
||||
line_t *line = lines + li;
|
||||
|
||||
...
|
||||
|
||||
if (something)
|
||||
{
|
||||
mtag_t tag2 = 8;
|
||||
|
||||
// Nested iteration; just make sure the level is higher
|
||||
// and that it has its own counter declared in scope.
|
||||
TAG_ITER_SECTORS(1, tag2, sec)
|
||||
{
|
||||
sector_t *sector = sectors + sec;
|
||||
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Notes:
|
||||
If no elements are found for a given tag, the loop inside won't be executed.
|
||||
*/
|
||||
|
||||
#endif //__R_TAGLIST__
|
51
src/w_wad.c
51
src/w_wad.c
|
@ -845,8 +845,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
// Read shaders from file
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
{
|
||||
HWR_ReadShaders(numwadfiles - 1, (type == RET_PK3));
|
||||
HWR_LoadShaders();
|
||||
HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3));
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
#endif // HWRENDER
|
||||
|
||||
|
@ -2052,14 +2052,59 @@ int W_VerifyNMUSlumps(const char *filename)
|
|||
{"CLM", 3}, // Colormap changes
|
||||
{"TRANS", 5}, // Translucency map changes
|
||||
|
||||
{"CONSBACK", 8}, // Console Background graphic
|
||||
|
||||
{"SAVE", 4}, // Save Select graphics here and below
|
||||
{"BLACXLVL", 8},
|
||||
{"GAMEDONE", 8},
|
||||
{"CONT", 4}, // Continue icons on saves (probably not used anymore)
|
||||
{"STNONEX", 7}, // "X" graphic
|
||||
{"ULTIMATE", 8}, // Ultimate no-save
|
||||
|
||||
{"CRFNT", 5}, // Sonic 1 font changes
|
||||
{"NTFNT", 5}, // Character Select font changes
|
||||
{"NTFNO", 5}, // Character Select font (outline)
|
||||
{"LTFNT", 5}, // Level title font changes
|
||||
{"TTL", 3}, // Act number changes
|
||||
{"STCFN", 5}, // Console font changes
|
||||
{"TNYFN", 5}, // Tiny console font changes
|
||||
|
||||
{"STLIVE", 6}, // Life graphics, background and the "X" that shows under skin's HUDNAME
|
||||
{"CROSHAI", 7}, // First person crosshairs
|
||||
{"INTERSC", 7}, // Default intermission backgrounds (co-op)
|
||||
{"STT", 3}, // Acceptable HUD changes (Score Time Rings)
|
||||
{"YB_", 3}, // Intermission graphics, goes with the above
|
||||
{"M_", 2}, // As does menu stuff
|
||||
{"RESULT", 6}, // Used in intermission for competitive modes, above too :3
|
||||
{"RACE", 4}, // Race mode graphics, 321go
|
||||
{"M_", 2}, // Menu stuff
|
||||
{"LT", 2}, // Titlecard changes
|
||||
|
||||
{"SLID", 4}, // Continue
|
||||
{"CONT", 4},
|
||||
|
||||
{"MINICAPS", 8}, // NiGHTS graphics here and below
|
||||
{"BLUESTAT", 8}, // Sphere status
|
||||
{"BYELSTAT", 8},
|
||||
{"ORNGSTAT", 8},
|
||||
{"REDSTAT", 7},
|
||||
{"YELSTAT", 7},
|
||||
{"NBRACKET", 8},
|
||||
{"NGHTLINK", 8},
|
||||
{"NGT", 3}, // Link numbers
|
||||
{"NARROW", 6},
|
||||
{"NREDAR", 6},
|
||||
{"NSS", 3},
|
||||
{"NBON", 4},
|
||||
{"NRNG", 4},
|
||||
{"NHUD", 4},
|
||||
{"CAPS", 4},
|
||||
{"DRILL", 5},
|
||||
{"GRADE", 5},
|
||||
{"MINUS5", 6},
|
||||
|
||||
{"MUSICDEF", 8}, // Song definitions (thanks kart)
|
||||
{"SHADERS", 7}, // OpenGL shader definitions
|
||||
{"SH_", 3}, // GLSL shader
|
||||
|
||||
{NULL, 0},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue