Merge branch 'next' into po2-32x32-fix

This commit is contained in:
Jaime Ita Passos 2021-10-12 13:10:08 -03:00
commit 68788b7ce4
66 changed files with 2855 additions and 1384 deletions

View file

@ -2950,8 +2950,10 @@ linedeftypes
prefix = "(700)"; prefix = "(700)";
flags2048text = "[11] No physics"; flags2048text = "[11] No physics";
flags4096text = "[12] Dynamic"; flags4096text = "[12] Dynamic";
flags32768text = "[15] Copy to other side";
slope = "regular"; slope = "regular";
slopeargs = 1; slopeargs = 1;
copyslopeargs = 1;
} }
701 701
@ -2960,8 +2962,10 @@ linedeftypes
prefix = "(701)"; prefix = "(701)";
flags2048text = "[11] No physics"; flags2048text = "[11] No physics";
flags4096text = "[12] Dynamic"; flags4096text = "[12] Dynamic";
flags32768text = "[15] Copy to other side";
slope = "regular"; slope = "regular";
slopeargs = 2; slopeargs = 2;
copyslopeargs = 4;
} }
702 702
@ -2970,8 +2974,10 @@ linedeftypes
prefix = "(702)"; prefix = "(702)";
flags2048text = "[11] No physics"; flags2048text = "[11] No physics";
flags4096text = "[12] Dynamic"; flags4096text = "[12] Dynamic";
flags32768text = "[15] Copy to other side";
slope = "regular"; slope = "regular";
slopeargs = 3; slopeargs = 3;
copyslopeargs = 5;
} }
703 703
@ -2980,8 +2986,10 @@ linedeftypes
prefix = "(703)"; prefix = "(703)";
flags2048text = "[11] No physics"; flags2048text = "[11] No physics";
flags4096text = "[12] Dynamic"; flags4096text = "[12] Dynamic";
flags32768text = "[15] Copy to other side";
slope = "regular"; slope = "regular";
slopeargs = 9; slopeargs = 9;
copyslopeargs = 8;
} }
704 704
@ -3012,8 +3020,10 @@ linedeftypes
prefix = "(710)"; prefix = "(710)";
flags2048text = "[11] No physics"; flags2048text = "[11] No physics";
flags4096text = "[12] Dynamic"; flags4096text = "[12] Dynamic";
flags32768text = "[15] Copy to other side";
slope = "regular"; slope = "regular";
slopeargs = 4; slopeargs = 4;
copyslopeargs = 2;
} }
711 711
@ -3022,8 +3032,10 @@ linedeftypes
prefix = "(711)"; prefix = "(711)";
flags2048text = "[11] No physics"; flags2048text = "[11] No physics";
flags4096text = "[12] Dynamic"; flags4096text = "[12] Dynamic";
flags32768text = "[15] Copy to other side";
slope = "regular"; slope = "regular";
slopeargs = 8; slopeargs = 8;
copyslopeargs = 8;
} }
712 712
@ -3032,8 +3044,10 @@ linedeftypes
prefix = "(712)"; prefix = "(712)";
flags2048text = "[11] No physics"; flags2048text = "[11] No physics";
flags4096text = "[12] Dynamic"; flags4096text = "[12] Dynamic";
flags32768text = "[15] Copy to other side";
slope = "regular"; slope = "regular";
slopeargs = 12; slopeargs = 12;
copyslopeargs = 10;
} }
713 713
@ -3042,8 +3056,10 @@ linedeftypes
prefix = "(713)"; prefix = "(713)";
flags2048text = "[11] No physics"; flags2048text = "[11] No physics";
flags4096text = "[12] Dynamic"; flags4096text = "[12] Dynamic";
flags32768text = "[15] Copy to other side";
slope = "regular"; slope = "regular";
slopeargs = 6; slopeargs = 6;
copyslopeargs = 6;
} }
714 714

View file

@ -60,7 +60,7 @@ if(${SRB2_CONFIG_HAVE_GME})
endif() endif()
if(${GME_FOUND}) if(${GME_FOUND})
set(SRB2_HAVE_GME ON) set(SRB2_HAVE_GME ON)
target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_LIBGME) target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_GME)
else() else()
message(WARNING "You have specified that GME is available but it was not found.") message(WARNING "You have specified that GME is available but it was not found.")
endif() endif()

View file

@ -71,13 +71,17 @@ latest_gcc_version:=10.2
# manually set. And don't bother if this is a clean only # manually set. And don't bother if this is a clean only
# run. # run.
ifeq (,$(call Wildvar,GCC% destructive)) ifeq (,$(call Wildvar,GCC% destructive))
version:=$(shell $(CC) --version)
# can't use $(CC) --version here since that uses argv[0] to display the name
# also gcc outputs the information to stderr, so I had to do 2>&1
# this program really doesn't like identifying itself
version:=$(shell $(CC) -v 2>&1)
# check if this is in fact GCC # check if this is in fact GCC
ifneq (,$(or $(findstring gcc,$(version)),\ ifneq (,$(findstring gcc version,$(version)))
$(findstring GCC,$(version))))
version:=$(shell $(CC) -dumpversion) # in stark contrast to the name, gcc will give me a nicely formatted version number for free
version:=$(shell $(CC) -dumpfullversion)
# Turn version into words of major, minor # Turn version into words of major, minor
v:=$(subst ., ,$(version)) v:=$(subst ., ,$(version))

View file

@ -458,7 +458,7 @@ boolean AM_Responder(event_t *ev)
{ {
if (!automapactive) if (!automapactive)
{ {
if (ev->type == ev_keydown && ev->data1 == AM_TOGGLEKEY) if (ev->type == ev_keydown && ev->key == AM_TOGGLEKEY)
{ {
//faB: prevent alt-tab in win32 version to activate automap just before //faB: prevent alt-tab in win32 version to activate automap just before
// minimizing the app; doesn't do any harm to the DOS version // minimizing the app; doesn't do any harm to the DOS version
@ -473,7 +473,7 @@ boolean AM_Responder(event_t *ev)
else if (ev->type == ev_keydown) else if (ev->type == ev_keydown)
{ {
rc = true; rc = true;
switch (ev->data1) switch (ev->key)
{ {
case AM_PANRIGHTKEY: // pan right case AM_PANRIGHTKEY: // pan right
if (!followplayer) if (!followplayer)
@ -550,7 +550,7 @@ boolean AM_Responder(event_t *ev)
else if (ev->type == ev_keyup) else if (ev->type == ev_keyup)
{ {
rc = false; rc = false;
switch (ev->data1) switch (ev->key)
{ {
case AM_PANRIGHTKEY: case AM_PANRIGHTKEY:
if (!followplayer) if (!followplayer)

View file

@ -274,7 +274,7 @@ static int luaB_dofile (lua_State *L) {
UINT16 lumpnum; UINT16 lumpnum;
int n = lua_gettop(L); int n = lua_gettop(L);
if (wadfiles[numwadfiles - 1]->type != RET_PK3) if (!W_FileHasFolders(wadfiles[numwadfiles - 1]))
luaL_error(L, "dofile() only works with PK3 files"); luaL_error(L, "dofile() only works with PK3 files");
snprintf(fullfilename, sizeof(fullfilename), "Lua/%s", filename); snprintf(fullfilename, sizeof(fullfilename), "Lua/%s", filename);

View file

@ -221,7 +221,7 @@ static void CONS_Bind_f(void)
for (key = 0; key < NUMINPUTS; key++) for (key = 0; key < NUMINPUTS; key++)
if (bindtable[key]) if (bindtable[key])
{ {
CONS_Printf("%s : \"%s\"\n", G_KeyNumToString(key), bindtable[key]); CONS_Printf("%s : \"%s\"\n", G_KeyNumToName(key), bindtable[key]);
na = 1; na = 1;
} }
if (!na) if (!na)
@ -229,7 +229,7 @@ static void CONS_Bind_f(void)
return; return;
} }
key = G_KeyStringToNum(COM_Argv(1)); key = G_KeyNameToNum(COM_Argv(1));
if (key <= 0 || key >= NUMINPUTS) if (key <= 0 || key >= NUMINPUTS)
{ {
CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n")); CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n"));
@ -913,12 +913,12 @@ boolean CON_Responder(event_t *ev)
// let go keyup events, don't eat them // let go keyup events, don't eat them
if (ev->type != ev_keydown && ev->type != ev_console) if (ev->type != ev_keydown && ev->type != ev_console)
{ {
if (ev->data1 == gamecontrol[gc_console][0] || ev->data1 == gamecontrol[gc_console][1]) if (ev->key == gamecontrol[GC_CONSOLE][0] || ev->key == gamecontrol[GC_CONSOLE][1])
consdown = false; consdown = false;
return false; return false;
} }
key = ev->data1; key = ev->key;
// check for console toggle key // check for console toggle key
if (ev->type != ev_console) if (ev->type != ev_console)
@ -926,7 +926,7 @@ boolean CON_Responder(event_t *ev)
if (modeattacking || metalrecording || marathonmode) if (modeattacking || metalrecording || marathonmode)
return false; return false;
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1]) if (key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1])
{ {
if (consdown) // ignore repeat if (consdown) // ignore repeat
return true; return true;
@ -1759,8 +1759,8 @@ static void CON_DrawBackpic(void)
} }
// Draw the patch. // Draw the patch.
V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic, V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, FRACUNIT, V_NOSCALESTART, con_backpic, NULL,
0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h); 0, (BASEVIDHEIGHT - h) << FRACBITS, BASEVIDWIDTH << FRACBITS, h << FRACBITS);
// Unlock the cached patch. // Unlock the cached patch.
W_UnlockCachedPatch(con_backpic); W_UnlockCachedPatch(con_backpic);

View file

@ -43,6 +43,7 @@
#include "lzf.h" #include "lzf.h"
#include "lua_script.h" #include "lua_script.h"
#include "lua_hook.h" #include "lua_hook.h"
#include "lua_libs.h"
#include "md5.h" #include "md5.h"
#include "m_perfstats.h" #include "m_perfstats.h"
@ -663,14 +664,14 @@ static void Snake_Handle(void)
UINT16 i; UINT16 i;
// Handle retry // Handle retry
if (snake->gameover && (PLAYER1INPUTDOWN(gc_jump) || gamekeydown[KEY_ENTER])) if (snake->gameover && (PLAYER1INPUTDOWN(GC_JUMP) || gamekeydown[KEY_ENTER]))
{ {
Snake_Initialise(); Snake_Initialise();
snake->pausepressed = true; // Avoid accidental pause on respawn snake->pausepressed = true; // Avoid accidental pause on respawn
} }
// Handle pause // Handle pause
if (PLAYER1INPUTDOWN(gc_pause) || gamekeydown[KEY_ENTER]) if (PLAYER1INPUTDOWN(GC_PAUSE) || gamekeydown[KEY_ENTER])
{ {
if (!snake->pausepressed) if (!snake->pausepressed)
snake->paused = !snake->paused; snake->paused = !snake->paused;
@ -3331,6 +3332,9 @@ static inline void SV_GenContext(void)
// //
void D_QuitNetGame(void) void D_QuitNetGame(void)
{ {
mousegrabbedbylua = true;
I_UpdateMouseGrab();
if (!netgame || !netbuffer) if (!netgame || !netbuffer)
return; return;

View file

@ -33,9 +33,10 @@ typedef enum
typedef struct typedef struct
{ {
evtype_t type; evtype_t type;
INT32 data1; // keys / mouse/joystick buttons INT32 key; // keys/mouse/joystick buttons
INT32 data2; // mouse/joystick x move INT32 x; // mouse/joystick x move
INT32 data3; // mouse/joystick y move INT32 y; // mouse/joystick y move
boolean repeated; // key repeat
} event_t; } event_t;
// //

View file

@ -191,22 +191,22 @@ void D_ProcessEvents(void)
if (ev->type == ev_keydown || ev->type == ev_keyup) if (ev->type == ev_keydown || ev->type == ev_keyup)
{ {
// Mouse buttons // Mouse buttons
if ((UINT32)(ev->data1 - KEY_MOUSE1) < MOUSEBUTTONS) if ((UINT32)(ev->key - KEY_MOUSE1) < MOUSEBUTTONS)
{ {
if (ev->type == ev_keydown) if (ev->type == ev_keydown)
mouse.buttons |= 1 << (ev->data1 - KEY_MOUSE1); mouse.buttons |= 1 << (ev->key - KEY_MOUSE1);
else else
mouse.buttons &= ~(1 << (ev->data1 - KEY_MOUSE1)); mouse.buttons &= ~(1 << (ev->key - KEY_MOUSE1));
} }
else if ((UINT32)(ev->data1 - KEY_2MOUSE1) < MOUSEBUTTONS) else if ((UINT32)(ev->key - KEY_2MOUSE1) < MOUSEBUTTONS)
{ {
if (ev->type == ev_keydown) if (ev->type == ev_keydown)
mouse2.buttons |= 1 << (ev->data1 - KEY_2MOUSE1); mouse2.buttons |= 1 << (ev->key - KEY_2MOUSE1);
else else
mouse2.buttons &= ~(1 << (ev->data1 - KEY_2MOUSE1)); mouse2.buttons &= ~(1 << (ev->key - KEY_2MOUSE1));
} }
// Scroll (has no keyup event) // Scroll (has no keyup event)
else switch (ev->data1) { else switch (ev->key) {
case KEY_MOUSEWHEELUP: case KEY_MOUSEWHEELUP:
mouse.buttons |= MB_SCROLLUP; mouse.buttons |= MB_SCROLLUP;
break; break;
@ -936,10 +936,26 @@ static void D_AddFile(char **list, const char *file)
newfile = malloc(strlen(file) + 1); newfile = malloc(strlen(file) + 1);
if (!newfile) if (!newfile)
{
I_Error("No more free memory to AddFile %s",file); I_Error("No more free memory to AddFile %s",file);
}
strcpy(newfile, file); strcpy(newfile, file);
list[pnumwadfiles] = newfile;
}
static void D_AddFolder(char **list, const char *file)
{
size_t pnumwadfiles;
char *newfile;
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
;
newfile = malloc(strlen(file) + 2); // Path delimiter + NULL terminator
if (!newfile)
I_Error("No more free memory to AddFolder %s",file);
strcpy(newfile, file);
strcat(newfile, PATHSEP);
list[pnumwadfiles] = newfile; list[pnumwadfiles] = newfile;
} }
@ -1237,21 +1253,25 @@ void D_SRB2Main(void)
// Do this up here so that WADs loaded through the command line can use ExecCfg // Do this up here so that WADs loaded through the command line can use ExecCfg
COM_Init(); COM_Init();
// add any files specified on the command line with -file wadfile // Add any files specified on the command line with
// to the wad list // "-file <file>" or "-folder <folder>" to the add-on list
if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server"))) if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server")))
{ {
if (M_CheckParm("-file")) INT32 addontype = 0;
{ INT32 i;
// the parms after p are wadfile/lump names,
// until end of parms or another - preceded parm
while (M_IsNextParm())
{
const char *s = M_GetNextParm();
if (s) // Check for NULL? for (i = 1; i < myargc; i++)
D_AddFile(startuppwads, s); {
} if (!strcasecmp(myargv[i], "-file"))
addontype = 1;
else if (!strcasecmp(myargv[i], "-folder"))
addontype = 2;
else if (myargv[i][0] == '-' || myargv[i][0] == '+')
addontype = 0;
else if (addontype == 1)
D_AddFile(startuppwads, myargv[i]);
else if (addontype == 2)
D_AddFolder(startuppwads, myargv[i]);
} }
} }

View file

@ -63,7 +63,9 @@ static void Got_WeaponPref(UINT8 **cp, INT32 playernum);
static void Got_Mapcmd(UINT8 **cp, INT32 playernum); static void Got_Mapcmd(UINT8 **cp, INT32 playernum);
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum); static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum);
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum); static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum);
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum);
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum); static void Got_Addfilecmd(UINT8 **cp, INT32 playernum);
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum);
static void Got_Pause(UINT8 **cp, INT32 playernum); static void Got_Pause(UINT8 **cp, INT32 playernum);
static void Got_Suicide(UINT8 **cp, INT32 playernum); static void Got_Suicide(UINT8 **cp, INT32 playernum);
static void Got_RandomSeed(UINT8 **cp, INT32 playernum); static void Got_RandomSeed(UINT8 **cp, INT32 playernum);
@ -115,6 +117,7 @@ static void Command_Map_f(void);
static void Command_ResetCamera_f(void); static void Command_ResetCamera_f(void);
static void Command_Addfile(void); static void Command_Addfile(void);
static void Command_Addfolder(void);
static void Command_ListWADS_f(void); static void Command_ListWADS_f(void);
static void Command_RunSOC(void); static void Command_RunSOC(void);
static void Command_Pause(void); static void Command_Pause(void);
@ -284,7 +287,7 @@ 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); 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}}; static CV_PossibleValue_t minitimelimit_cons_t[] = {{1, "MIN"}, {9999, "MAX"}, {0, NULL}};
consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "60", CV_SAVE|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_SAVE|CV_NETVAR, CV_OnOff, NULL); consvar_t cv_touchtag = CVAR_INIT ("touchtag", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
@ -398,16 +401,16 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
"MAP", "MAP",
"EXITLEVEL", "EXITLEVEL",
"ADDFILE", "ADDFILE",
"ADDFOLDER",
"PAUSE", "PAUSE",
"ADDPLAYER", "ADDPLAYER",
"TEAMCHANGE", "TEAMCHANGE",
"CLEARSCORES", "CLEARSCORES",
"LOGIN",
"VERIFIED", "VERIFIED",
"RANDOMSEED", "RANDOMSEED",
"RUNSOC", "RUNSOC",
"REQADDFILE", "REQADDFILE",
"DELFILE", // replace next time we add an XD "REQADDFOLDER",
"SETMOTD", "SETMOTD",
"SUICIDE", "SUICIDE",
"LUACMD", "LUACMD",
@ -441,7 +444,9 @@ void D_RegisterServerCommands(void)
RegisterNetXCmd(XD_MAP, Got_Mapcmd); RegisterNetXCmd(XD_MAP, Got_Mapcmd);
RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd); RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd);
RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd); RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd);
RegisterNetXCmd(XD_ADDFOLDER, Got_Addfoldercmd);
RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd); RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd);
RegisterNetXCmd(XD_REQADDFOLDER, Got_RequestAddfoldercmd);
RegisterNetXCmd(XD_PAUSE, Got_Pause); RegisterNetXCmd(XD_PAUSE, Got_Pause);
RegisterNetXCmd(XD_SUICIDE, Got_Suicide); RegisterNetXCmd(XD_SUICIDE, Got_Suicide);
RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd); RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd);
@ -472,6 +477,7 @@ void D_RegisterServerCommands(void)
COM_AddCommand("showmap", Command_Showmap_f); COM_AddCommand("showmap", Command_Showmap_f);
COM_AddCommand("mapmd5", Command_Mapmd5_f); COM_AddCommand("mapmd5", Command_Mapmd5_f);
COM_AddCommand("addfolder", Command_Addfolder);
COM_AddCommand("addfile", Command_Addfile); COM_AddCommand("addfile", Command_Addfile);
COM_AddCommand("listwad", Command_ListWADS_f); COM_AddCommand("listwad", Command_ListWADS_f);
@ -3342,9 +3348,9 @@ static void Command_Addfile(void)
++p; ++p;
// check total packet size and no of files currently loaded // check total packet size and no of files currently loaded
// See W_LoadWadFile in w_wad.c // See W_InitFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES) if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8))) || ((packetsizetally + nameonlylength(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
{ {
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return; return;
@ -3392,6 +3398,139 @@ static void Command_Addfile(void)
} }
} }
static void Command_Addfolder(void)
{
size_t argc = COM_Argc(); // amount of arguments total
size_t curarg; // current argument index
const char *addedfolders[argc]; // list of filenames already processed
size_t numfoldersadded = 0; // the amount of filenames processed
if (argc < 2)
{
CONS_Printf(M_GetText("addfolder <path> [path2...] [...]: Load add-ons\n"));
return;
}
// start at one to skip command name
for (curarg = 1; curarg < argc; curarg++)
{
const char *fn, *p;
char *fullpath;
char buf[256];
char *buf_p = buf;
INT32 i, stat;
size_t ii;
boolean folderadded = false;
fn = COM_Argv(curarg);
// For the amount of filenames previously processed...
for (ii = 0; ii < numfoldersadded; ii++)
{
// If this is one of them, don't try to add it.
if (!strcmp(fn, addedfolders[ii]))
{
folderadded = true;
break;
}
}
// If we've added this one, skip to the next one.
if (folderadded)
{
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;
// Add file on your client directly if you aren't in a netgame.
if (!(netgame || multiplayer))
{
P_AddFolder(fn);
addedfolders[numfoldersadded++] = fn;
continue;
}
p = fn+strlen(fn);
while(--p >= fn)
if (*p == '\\' || *p == '/' || *p == ':')
break;
++p;
// Don't add an empty path.
if (M_IsStringEmpty(fn))
{
CONS_Alert(CONS_WARNING, M_GetText("Folder name is empty, skipping\n"));
continue;
}
// check total packet size and no of files currently loaded
// See W_InitFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + strlen(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
{
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return;
}
// Check if the path is valid.
stat = W_IsPathToFolderValid(fn);
if (stat == 0)
{
CONS_Alert(CONS_WARNING, M_GetText("Path %s is invalid, skipping\n"), fn);
continue;
}
else if (stat < 0)
{
#ifndef AVOID_ERRNO
CONS_Alert(CONS_WARNING, M_GetText("Error accessing %s (%s), skipping\n"), fn, strerror(direrror));
#else
CONS_Alert(CONS_WARNING, M_GetText("Error accessing %s, skipping\n"), fn);
#endif
continue;
}
// Get the full path for this folder.
fullpath = W_GetFullFolderPath(fn);
if (fullpath == NULL)
{
CONS_Alert(CONS_WARNING, M_GetText("Path %s is invalid, skipping\n"), fn);
continue;
}
// Check if the folder is already added.
for (i = 0; i < numwadfiles; i++)
{
if (wadfiles[i]->type != RET_FOLDER)
continue;
if (samepaths(wadfiles[i]->path, fullpath) > 0)
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
continue;
}
}
Z_Free(fullpath);
addedfolders[numfoldersadded++] = fn;
WRITESTRINGN(buf_p,p,240);
if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file
SendNetXCmd(XD_REQADDFOLDER, buf, buf_p - buf);
else
SendNetXCmd(XD_ADDFOLDER, buf, buf_p - buf);
}
}
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
{ {
char filename[241]; char filename[241];
@ -3420,9 +3559,9 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
return; return;
} }
// See W_LoadWadFile in w_wad.c // See W_InitFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES) if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8))) || ((packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
toomany = true; toomany = true;
else else
ncs = findfile(filename,md5sum,true); ncs = findfile(filename,md5sum,true);
@ -3452,6 +3591,64 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
COM_BufAddText(va("addfile %s\n", filename)); COM_BufAddText(va("addfile %s\n", filename));
} }
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
{
char path[241];
filestatus_t ncs = FS_NOTFOUND;
boolean kick = false;
boolean toomany = false;
INT32 i,j;
READSTRINGN(*cp, path, 240);
/// \todo Integrity checks.
// Only the server processes this message.
if (client)
return;
// Disallow non-printing characters and semicolons.
for (i = 0; path[i] != '\0'; i++)
if (!isprint(path[i]) || path[i] == ';')
kick = true;
if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfolder command received from %s\n"), player_names[playernum]);
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
// See W_InitFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + strlen(path) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
toomany = true;
else
ncs = findfolder(path);
if (ncs != FS_FOUND || toomany)
{
char message[256];
if (toomany)
sprintf(message, M_GetText("Too many files loaded to add %s\n"), path);
else if (ncs == FS_NOTFOUND)
sprintf(message, M_GetText("The server doesn't have %s\n"), path);
else
sprintf(message, M_GetText("Unknown error finding folder (%s)\n"), path);
CONS_Printf("%s",message);
for (j = 0; j < MAXPLAYERS; j++)
if (adminplayers[j])
COM_BufAddText(va("sayto %d %s", adminplayers[j], message));
return;
}
COM_BufAddText(va("addfolder \"%s\"\n", path));
}
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
{ {
char filename[241]; char filename[241];
@ -3500,6 +3697,49 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
G_SetGameModified(true); G_SetGameModified(true);
} }
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum)
{
char path[241];
filestatus_t ncs = FS_NOTFOUND;
READSTRINGN(*cp, path, 240);
/// \todo Integrity checks.
if (playernum != serverplayer)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfolder command received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
return;
}
ncs = findfolder(path);
if (ncs != FS_FOUND || !P_AddFolder(path))
{
Command_ExitGame_f();
if (ncs == FS_FOUND)
{
CONS_Printf(M_GetText("The server tried to add %s,\nbut you have too many files added.\nRestart the game to clear loaded files\nand play on this server."), path);
M_StartMessage(va("The server added a folder \n(%s)\nbut you have too many files added.\nRestart the game to clear loaded files.\n\nPress ESC\n",path), NULL, MM_NOTHING);
}
else if (ncs == FS_NOTFOUND)
{
CONS_Printf(M_GetText("The server tried to add %s,\nbut you don't have this file.\nYou need to find it in order\nto play on this server."), path);
M_StartMessage(va("The server added a folder \n(%s)\nthat you do not have.\n\nPress ESC\n",path), NULL, MM_NOTHING);
}
else
{
CONS_Printf(M_GetText("Unknown error finding folder (%s) the server added.\n"), path);
M_StartMessage(va("Unknown error trying to load a folder\nthat the server added \n(%s).\n\nPress ESC\n",path), NULL, MM_NOTHING);
}
return;
}
G_SetGameModified(true);
}
static void Command_ListWADS_f(void) static void Command_ListWADS_f(void)
{ {
INT32 i = numwadfiles; INT32 i = numwadfiles;
@ -3514,6 +3754,8 @@ static void Command_ListWADS_f(void)
CONS_Printf("\x82 * %.2d\x80: %s\n", i, tempname); CONS_Printf("\x82 * %.2d\x80: %s\n", i, tempname);
else if (!wadfiles[i]->important) else if (!wadfiles[i]->important)
CONS_Printf("\x86 %.2d: %s\n", i, tempname); CONS_Printf("\x86 %.2d: %s\n", i, tempname);
else if (wadfiles[i]->type == RET_FOLDER)
CONS_Printf("\x82 * %.2d\x84: %s\n", i, tempname);
else else
CONS_Printf(" %.2d: %s\n", i, tempname); CONS_Printf(" %.2d: %s\n", i, tempname);
} }

View file

@ -128,16 +128,16 @@ typedef enum
XD_MAP, // 6 XD_MAP, // 6
XD_EXITLEVEL, // 7 XD_EXITLEVEL, // 7
XD_ADDFILE, // 8 XD_ADDFILE, // 8
XD_PAUSE, // 9 XD_ADDFOLDER, // 9
XD_ADDPLAYER, // 10 XD_PAUSE, // 10
XD_TEAMCHANGE, // 11 XD_ADDPLAYER, // 11
XD_CLEARSCORES, // 12 XD_TEAMCHANGE, // 12
// UNUSED 13 (Because I don't want to change these comments) XD_CLEARSCORES, // 13
XD_VERIFIED = 14,//14 XD_VERIFIED, // 14
XD_RANDOMSEED, // 15 XD_RANDOMSEED, // 15
XD_RUNSOC, // 16 XD_RUNSOC, // 16
XD_REQADDFILE, // 17 XD_REQADDFILE, // 17
XD_DELFILE, // 18 - replace next time we add an XD XD_REQADDFOLDER,// 18
XD_SETMOTD, // 19 XD_SETMOTD, // 19
XD_SUICIDE, // 20 XD_SUICIDE, // 20
XD_DEMOTED, // 21 XD_DEMOTED, // 21

View file

@ -116,7 +116,7 @@ char luafiledir[256 + 16] = "luafiles";
/** Fills a serverinfo packet with information about wad files loaded. /** Fills a serverinfo packet with information about wad files loaded.
* *
* \todo Give this function a better name since it is in global scope. * \todo Give this function a better name since it is in global scope.
* Used to have size limiting built in - now handled via W_LoadWadFile in w_wad.c * Used to have size limiting built in - now handled via W_InitFile in w_wad.c
* *
*/ */
UINT8 *PutFileNeeded(void) UINT8 *PutFileNeeded(void)
@ -124,7 +124,7 @@ UINT8 *PutFileNeeded(void)
size_t i, count = 0; size_t i, count = 0;
UINT8 *p = netbuffer->u.serverinfo.fileneeded; UINT8 *p = netbuffer->u.serverinfo.fileneeded;
char wadfilename[MAX_WADPATH] = ""; char wadfilename[MAX_WADPATH] = "";
UINT8 filestatus; UINT8 filestatus, folder;
for (i = 0; i < numwadfiles; i++) for (i = 0; i < numwadfiles; i++)
{ {
@ -133,9 +133,10 @@ UINT8 *PutFileNeeded(void)
continue; continue;
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
folder = (wadfiles[i]->type == RET_FOLDER);
// Store in the upper four bits // Store in the upper four bits
if (!cv_downloading.value) if (!cv_downloading.value || folder) /// \todo Implement folder downloading.
filestatus += (2 << 4); // Won't send filestatus += (2 << 4); // Won't send
else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024)) else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
filestatus += (1 << 4); // Will send if requested filestatus += (1 << 4); // Will send if requested
@ -143,6 +144,7 @@ UINT8 *PutFileNeeded(void)
// filestatus += (0 << 4); -- Won't send, too big // filestatus += (0 << 4); -- Won't send, too big
WRITEUINT8(p, filestatus); WRITEUINT8(p, filestatus);
WRITEUINT8(p, folder);
count++; count++;
WRITEUINT32(p, wadfiles[i]->filesize); WRITEUINT32(p, wadfiles[i]->filesize);
@ -174,6 +176,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
fileneeded[i].justdownloaded = false; fileneeded[i].justdownloaded = false;
filestatus = READUINT8(p); // The first byte is the file status filestatus = READUINT8(p); // The first byte is the file status
fileneeded[i].folder = READUINT8(p); // The second byte is the folder flag
fileneeded[i].willsend = (UINT8)(filestatus >> 4); fileneeded[i].willsend = (UINT8)(filestatus >> 4);
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
fileneeded[i].file = NULL; // The file isn't open yet fileneeded[i].file = NULL; // The file isn't open yet
@ -416,7 +419,7 @@ INT32 CL_CheckFiles(void)
return 1; return 1;
} }
// See W_LoadWadFile in w_wad.c // See W_InitFile in w_wad.c
packetsize = packetsizetally; packetsize = packetsizetally;
for (i = 1; i < fileneedednum; i++) for (i = 1; i < fileneedednum; i++)
@ -438,7 +441,10 @@ INT32 CL_CheckFiles(void)
if (fileneeded[i].status != FS_NOTFOUND) if (fileneeded[i].status != FS_NOTFOUND)
continue; continue;
packetsize += nameonlylength(fileneeded[i].filename) + 22; if (fileneeded[i].folder)
packetsize += strlen(fileneeded[i].filename) + FILENEEDEDSIZE;
else
packetsize += nameonlylength(fileneeded[i].filename) + FILENEEDEDSIZE;
if ((numwadfiles+filestoget >= MAX_WADFILES) if ((numwadfiles+filestoget >= MAX_WADFILES)
|| (packetsize > MAXFILENEEDED*sizeof(UINT8))) || (packetsize > MAXFILENEEDED*sizeof(UINT8)))
@ -446,6 +452,9 @@ INT32 CL_CheckFiles(void)
filestoget++; filestoget++;
if (fileneeded[i].folder)
fileneeded[i].status = findfolder(fileneeded[i].filename);
else
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true); fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status); CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
if (fileneeded[i].status != FS_FOUND) if (fileneeded[i].status != FS_FOUND)
@ -468,6 +477,9 @@ void CL_LoadServerFiles(void)
continue; // Already loaded continue; // Already loaded
else if (fileneeded[i].status == FS_FOUND) else if (fileneeded[i].status == FS_FOUND)
{ {
if (fileneeded[i].folder)
P_AddFolder(fileneeded[i].filename);
else
P_AddWadFile(fileneeded[i].filename); P_AddWadFile(fileneeded[i].filename);
G_SetGameModified(true); G_SetGameModified(true);
fileneeded[i].status = FS_OPEN; fileneeded[i].status = FS_OPEN;
@ -756,7 +768,7 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid
// This formerly checked if (!findfile(p->id.filename, NULL, true)) // This formerly checked if (!findfile(p->id.filename, NULL, true))
// Not found // Not found
// Don't inform client (probably someone who thought they could leak 2.2 ACZ) // Don't inform client
DEBFILE(va("Client %d request %s: not found\n", node, filename)); DEBFILE(va("Client %d request %s: not found\n", node, filename));
free(p->id.filename); free(p->id.filename);
free(p); free(p);
@ -1571,3 +1583,26 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
} }
// Searches for a folder.
// This can be used with a full path, or an incomplete path.
// In the latter case, the function will try to find folders in
// srb2home, srb2path, and the current directory.
filestatus_t findfolder(const char *path)
{
// Check the path by itself first.
if (concatpaths(path, NULL) == 1)
return FS_FOUND;
#define checkpath(startpath) \
if (concatpaths(path, startpath) == 1) \
return FS_FOUND
checkpath(srb2home); // Then, look in srb2home.
checkpath(srb2path); // Now, look in srb2path.
checkpath("."); // Finally, look in the current directory.
#undef checkpath
return FS_NOTFOUND;
}

View file

@ -38,6 +38,7 @@ typedef enum
typedef struct typedef struct
{ {
UINT8 willsend; // Is the server willing to send it? UINT8 willsend; // Is the server willing to send it?
UINT8 folder; // File is a folder
char filename[MAX_WADPATH]; char filename[MAX_WADPATH];
UINT8 md5sum[16]; UINT8 md5sum[16];
filestatus_t status; // The value returned by recsearch filestatus_t status; // The value returned by recsearch
@ -54,6 +55,8 @@ typedef struct
UINT32 ackresendposition; // Used when resuming downloads UINT32 ackresendposition; // Used when resuming downloads
} fileneeded_t; } fileneeded_t;
#define FILENEEDEDSIZE 23
extern INT32 fileneedednum; extern INT32 fileneedednum;
extern fileneeded_t fileneeded[MAX_WADFILES]; extern fileneeded_t fileneeded[MAX_WADFILES];
extern char downloaddir[512]; extern char downloaddir[512];
@ -135,6 +138,9 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum,
boolean completepath); boolean completepath);
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum); filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum);
// Searches for a folder
filestatus_t findfolder(const char *path);
void nameonly(char *s); void nameonly(char *s);
size_t nameonlylength(const char *s); size_t nameonlylength(const char *s);

View file

@ -5478,49 +5478,49 @@ struct int_const_s const INT_CONST[] = {
{"JOYAXISRANGE",JOYAXISRANGE}, {"JOYAXISRANGE",JOYAXISRANGE},
// Game controls // Game controls
{"gc_null",gc_null}, {"GC_NULL",GC_NULL},
{"gc_forward",gc_forward}, {"GC_FORWARD",GC_FORWARD},
{"gc_backward",gc_backward}, {"GC_BACKWARD",GC_BACKWARD},
{"gc_strafeleft",gc_strafeleft}, {"GC_STRAFELEFT",GC_STRAFELEFT},
{"gc_straferight",gc_straferight}, {"GC_STRAFERIGHT",GC_STRAFERIGHT},
{"gc_turnleft",gc_turnleft}, {"GC_TURNLEFT",GC_TURNLEFT},
{"gc_turnright",gc_turnright}, {"GC_TURNRIGHT",GC_TURNRIGHT},
{"gc_weaponnext",gc_weaponnext}, {"GC_WEAPONNEXT",GC_WEAPONNEXT},
{"gc_weaponprev",gc_weaponprev}, {"GC_WEAPONPREV",GC_WEAPONPREV},
{"gc_wepslot1",gc_wepslot1}, {"GC_WEPSLOT1",GC_WEPSLOT1},
{"gc_wepslot2",gc_wepslot2}, {"GC_WEPSLOT2",GC_WEPSLOT2},
{"gc_wepslot3",gc_wepslot3}, {"GC_WEPSLOT3",GC_WEPSLOT3},
{"gc_wepslot4",gc_wepslot4}, {"GC_WEPSLOT4",GC_WEPSLOT4},
{"gc_wepslot5",gc_wepslot5}, {"GC_WEPSLOT5",GC_WEPSLOT5},
{"gc_wepslot6",gc_wepslot6}, {"GC_WEPSLOT6",GC_WEPSLOT6},
{"gc_wepslot7",gc_wepslot7}, {"GC_WEPSLOT7",GC_WEPSLOT7},
{"gc_wepslot8",gc_wepslot8}, {"GC_WEPSLOT8",GC_WEPSLOT8},
{"gc_wepslot9",gc_wepslot9}, {"GC_WEPSLOT9",GC_WEPSLOT9},
{"gc_wepslot10",gc_wepslot10}, {"GC_WEPSLOT10",GC_WEPSLOT10},
{"gc_fire",gc_fire}, {"GC_FIRE",GC_FIRE},
{"gc_firenormal",gc_firenormal}, {"GC_FIRENORMAL",GC_FIRENORMAL},
{"gc_tossflag",gc_tossflag}, {"GC_TOSSFLAG",GC_TOSSFLAG},
{"gc_spin",gc_spin}, {"GC_SPIN",GC_SPIN},
{"gc_camtoggle",gc_camtoggle}, {"GC_CAMTOGGLE",GC_CAMTOGGLE},
{"gc_camreset",gc_camreset}, {"GC_CAMRESET",GC_CAMRESET},
{"gc_lookup",gc_lookup}, {"GC_LOOKUP",GC_LOOKUP},
{"gc_lookdown",gc_lookdown}, {"GC_LOOKDOWN",GC_LOOKDOWN},
{"gc_centerview",gc_centerview}, {"GC_CENTERVIEW",GC_CENTERVIEW},
{"gc_mouseaiming",gc_mouseaiming}, {"GC_MOUSEAIMING",GC_MOUSEAIMING},
{"gc_talkkey",gc_talkkey}, {"GC_TALKKEY",GC_TALKKEY},
{"gc_teamkey",gc_teamkey}, {"GC_TEAMKEY",GC_TEAMKEY},
{"gc_scores",gc_scores}, {"GC_SCORES",GC_SCORES},
{"gc_jump",gc_jump}, {"GC_JUMP",GC_JUMP},
{"gc_console",gc_console}, {"GC_CONSOLE",GC_CONSOLE},
{"gc_pause",gc_pause}, {"GC_PAUSE",GC_PAUSE},
{"gc_systemmenu",gc_systemmenu}, {"GC_SYSTEMMENU",GC_SYSTEMMENU},
{"gc_screenshot",gc_screenshot}, {"GC_SCREENSHOT",GC_SCREENSHOT},
{"gc_recordgif",gc_recordgif}, {"GC_RECORDGIF",GC_RECORDGIF},
{"gc_viewpoint",gc_viewpoint}, {"GC_VIEWPOINT",GC_VIEWPOINT},
{"gc_custom1",gc_custom1}, {"GC_CUSTOM1",GC_CUSTOM1},
{"gc_custom2",gc_custom2}, {"GC_CUSTOM2",GC_CUSTOM2},
{"gc_custom3",gc_custom3}, {"GC_CUSTOM3",GC_CUSTOM3},
{"num_gamecontrols",num_gamecontrols}, {"NUM_GAMECONTROLS",NUM_GAMECONTROLS},
// Mouse buttons // Mouse buttons
{"MB_BUTTON1",MB_BUTTON1}, {"MB_BUTTON1",MB_BUTTON1},

View file

@ -127,6 +127,7 @@ extern char logfilename[1024];
//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
#ifdef DEVELOP #ifdef DEVELOP
#define VERSIONSTRING "Development EXE" #define VERSIONSTRING "Development EXE"
#define VERSIONSTRING_RC "Development EXE" "\0"
// most interface strings are ignored in development mode. // most interface strings are ignored in development mode.
// we use comprevision and compbranch instead. // we use comprevision and compbranch instead.
// VERSIONSTRING_RC is for the resource-definition script used by windows builds // VERSIONSTRING_RC is for the resource-definition script used by windows builds

View file

@ -41,6 +41,7 @@
#include "console.h" #include "console.h"
#include "lua_hud.h" #include "lua_hud.h"
#include "lua_hook.h"
// Stage of animation: // Stage of animation:
// 0 = text, 1 = art screen // 0 = text, 1 = art screen
@ -1011,7 +1012,7 @@ void F_IntroTicker(void)
// //
boolean F_IntroResponder(event_t *event) boolean F_IntroResponder(event_t *event)
{ {
INT32 key = event->data1; INT32 key = event->key;
// remap virtual keys (mouse & joystick buttons) // remap virtual keys (mouse & joystick buttons)
switch (key) switch (key)
@ -1089,7 +1090,6 @@ static const char *credits[] = {
"\"Hannu_Hanhi\"", // For many OpenGL performance improvements! "\"Hannu_Hanhi\"", // For many OpenGL performance improvements!
"Kepa \"Nev3r\" Iceta", "Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe", "Thomas \"Shadow Hog\" Igoe",
"\"james\"",
"Iestyn \"Monster Iestyn\" Jealous", "Iestyn \"Monster Iestyn\" Jealous",
"\"Jimita\"", "\"Jimita\"",
"\"Kaito Sinclaire\"", "\"Kaito Sinclaire\"",
@ -1102,6 +1102,7 @@ static const char *credits[] = {
"Louis-Antoine \"LJ Sonic\" de Moulins", // de Rochefort doesn't quite fit on the screen sorry lol "Louis-Antoine \"LJ Sonic\" de Moulins", // de Rochefort doesn't quite fit on the screen sorry lol
"John \"JTE\" Muniz", "John \"JTE\" Muniz",
"Colin \"Sonict\" Pfaff", "Colin \"Sonict\" Pfaff",
"James \"james\" Robert Roman",
"Sean \"Sryder13\" Ryder", "Sean \"Sryder13\" Ryder",
"Ehab \"Wolfy\" Saeed", "Ehab \"Wolfy\" Saeed",
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible "Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
@ -1397,7 +1398,7 @@ void F_CreditTicker(void)
boolean F_CreditResponder(event_t *event) boolean F_CreditResponder(event_t *event)
{ {
INT32 key = event->data1; INT32 key = event->key;
// remap virtual keys (mouse & joystick buttons) // remap virtual keys (mouse & joystick buttons)
switch (key) switch (key)
@ -3421,7 +3422,7 @@ void F_TitleScreenDrawer(void)
} }
luahook: luahook:
LUAh_TitleHUD(); LUA_HUDHOOK(title);
} }
// separate animation timer for backgrounds, since we also count // separate animation timer for backgrounds, since we also count
@ -3821,7 +3822,7 @@ void F_ContinueTicker(void)
boolean F_ContinueResponder(event_t *event) boolean F_ContinueResponder(event_t *event)
{ {
INT32 key = event->data1; INT32 key = event->key;
if (keypressed) if (keypressed)
return true; return true;

View file

@ -13,6 +13,7 @@
/// FS_FOUND /// FS_FOUND
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#ifdef __GNUC__ #ifdef __GNUC__
#include <dirent.h> #include <dirent.h>
#endif #endif
@ -29,10 +30,10 @@
#include "m_misc.h" #include "m_misc.h"
#include "z_zone.h" #include "z_zone.h"
#include "m_menu.h" // Addons_option_Onchange #include "m_menu.h" // Addons_option_Onchange
#include "w_wad.h"
#if defined (_WIN32) && defined (_MSC_VER) #if defined (_WIN32) && defined (_MSC_VER)
#include <errno.h>
#include <io.h> #include <io.h>
#include <tchar.h> #include <tchar.h>
@ -340,6 +341,11 @@ char *refreshdirname = NULL;
size_t packetsizetally = 0; size_t packetsizetally = 0;
size_t mainwadstally = 0; size_t mainwadstally = 0;
#define dirpathlen 1024
#define maxdirdepth 48
#define isuptree(dirent) ((dirent)[0]=='.' && ((dirent)[1]=='\0' || ((dirent)[1]=='.' && (dirent)[2]=='\0')))
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
{ {
filestatus_t retval = FS_NOTFOUND; filestatus_t retval = FS_NOTFOUND;
@ -387,10 +393,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
continue; continue;
} }
if (dent->d_name[0]=='.' && if (isuptree(dent->d_name))
(dent->d_name[1]=='\0' ||
(dent->d_name[1]=='.' &&
dent->d_name[2]=='\0')))
{ {
// we don't want to scan uptree // we don't want to scan uptree
continue; continue;
@ -445,6 +448,380 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
return retval; return retval;
} }
#ifndef AVOID_ERRNO
int direrror = 0;
#endif
// Checks if the specified path is a directory.
// Returns 1 if so, 0 if not, and -1 if an error occurred.
// direrror is set if there was an error.
INT32 pathisdirectory(const char *path)
{
struct stat fsstat;
if (stat(path, &fsstat) < 0)
{
#ifndef AVOID_ERRNO
direrror = errno;
#endif
return -1;
}
else if (S_ISDIR(fsstat.st_mode))
return 1;
return 0;
}
// Concatenates two paths, and checks if it is a directory that can be opened.
// Returns 1 if so, 0 if not, and -1 if an error occurred.
INT32 concatpaths(const char *path, const char *startpath)
{
char dirpath[dirpathlen];
DIR *dirhandle;
INT32 stat;
if (startpath)
{
char basepath[dirpathlen];
snprintf(basepath, sizeof basepath, "%s" PATHSEP, startpath);
snprintf(dirpath, sizeof dirpath, "%s%s", basepath, path);
// Base path and directory path are the same? Not valid.
stat = samepaths(basepath, dirpath);
if (stat == 1)
return 0;
else if (stat < 0)
return -1;
}
else
snprintf(dirpath, sizeof dirpath, "%s", path);
// Check if the path is a directory.
// Will return -1 if there was an error.
stat = pathisdirectory(dirpath);
if (stat == 0)
return 0;
else if (stat < 0)
{
// The path doesn't exist, so it can't be a directory.
if (direrror == ENOENT)
return 0;
return -1;
}
// Open the directory.
// Will return 0 if it couldn't be opened.
dirhandle = opendir(dirpath);
if (dirhandle == NULL)
return 0;
else
closedir(dirhandle);
return 1;
}
// Checks if two paths are the same. Returns 1 if so, and 0 if not.
// Returns -1 if an error occurred with the first path,
// and returns -2 if an error occurred with the second path.
// direrror is set if there was an error.
INT32 samepaths(const char *path1, const char *path2)
{
struct stat stat1;
struct stat stat2;
if (stat(path1, &stat1) < 0)
{
#ifndef AVOID_ERRNO
direrror = errno;
#endif
return -1;
}
if (stat(path2, &stat2) < 0)
{
#ifndef AVOID_ERRNO
direrror = errno;
#endif
return -2;
}
if (stat1.st_dev == stat2.st_dev)
{
#if !defined(_WIN32)
return (stat1.st_ino == stat2.st_ino);
#else
// The above doesn't work on NTFS or FAT.
HANDLE file1 = CreateFileA(path1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
HANDLE file2 = CreateFileA(path2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
BY_HANDLE_FILE_INFORMATION file1info, file2info;
if (file1 == INVALID_HANDLE_VALUE)
{
#ifndef AVOID_ERRNO
direrror = ENOENT;
#endif
return -1;
}
else if (file2 == INVALID_HANDLE_VALUE)
{
CloseHandle(file1);
#ifndef AVOID_ERRNO
direrror = ENOENT;
#endif
return -2;
}
// I have no idea why GetFileInformationByHandle would fail.
// Microsoft's documentation doesn't tell me.
// I'll just use EIO...
if (!GetFileInformationByHandle(file1, &file1info))
{
#ifndef AVOID_ERRNO
direrror = EIO;
#endif
return -1;
}
else if (!GetFileInformationByHandle(file2, &file2info))
{
CloseHandle(file1);
CloseHandle(file2);
#ifndef AVOID_ERRNO
direrror = EIO;
#endif
return -2;
}
if (file1info.dwVolumeSerialNumber == file2info.dwVolumeSerialNumber
&& file1info.nFileIndexLow == file2info.nFileIndexLow
&& file1info.nFileIndexHigh == file2info.nFileIndexHigh)
{
CloseHandle(file1);
CloseHandle(file2);
return 1;
}
return 0;
#endif
}
return 0;
}
//
// Directory loading
//
static void initdirpath(char *dirpath, size_t *dirpathindex, int depthleft)
{
dirpathindex[depthleft] = strlen(dirpath) + 1;
if (dirpath[dirpathindex[depthleft]-2] != PATHSEP[0])
{
dirpath[dirpathindex[depthleft]-1] = PATHSEP[0];
dirpath[dirpathindex[depthleft]] = 0;
}
else
dirpathindex[depthleft]--;
}
lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders)
{
DIR **dirhandle;
struct dirent *dent;
struct stat fsstat;
int rootdir = (maxdirdepth - 1);
int depthleft = rootdir;
char dirpath[dirpathlen];
size_t *dirpathindex;
lumpinfo_t *lumpinfo, *lump_p;
UINT16 i = 0, numlumps = 0;
boolean failure = false;
dirhandle = (DIR **)malloc(maxdirdepth * sizeof (DIR*));
dirpathindex = (size_t *)malloc(maxdirdepth * sizeof(size_t));
// Open the root directory
strlcpy(dirpath, path, dirpathlen);
dirhandle[depthleft] = opendir(dirpath);
if (dirhandle[depthleft] == NULL)
{
free(dirhandle);
free(dirpathindex);
return NULL;
}
initdirpath(dirpath, dirpathindex, depthleft);
(*nfolders) = 0;
// Count files and directories
while (depthleft < maxdirdepth)
{
dirpath[dirpathindex[depthleft]] = 0;
dent = readdir(dirhandle[depthleft]);
if (!dent)
{
if (depthleft != rootdir) // Don't close the root directory
closedir(dirhandle[depthleft]);
depthleft++;
continue;
}
else if (isuptree(dent->d_name))
continue;
strcpy(&dirpath[dirpathindex[depthleft]], dent->d_name);
if (stat(dirpath, &fsstat) < 0)
;
else if (S_ISDIR(fsstat.st_mode) && depthleft)
{
dirpathindex[--depthleft] = strlen(dirpath) + 1;
dirhandle[depthleft] = opendir(dirpath);
if (dirhandle[depthleft])
(*nfolders)++;
else
depthleft++;
dirpath[dirpathindex[depthleft]-1] = '/';
dirpath[dirpathindex[depthleft]] = 0;
}
else
numlumps++;
// Failure: Too many files.
if (numlumps == UINT16_MAX)
{
(*nlmp) = UINT16_MAX;
failure = true;
break;
}
}
// Failure: No files have been found.
if (!numlumps)
{
(*nlmp) = 0;
failure = true;
}
// Close any open directories and return if something went wrong.
if (failure)
{
free(dirpathindex);
free(dirhandle);
for (; depthleft < maxdirdepth; closedir(dirhandle[depthleft++]));
return NULL;
}
// Create the files and directories as lump entries
// It's possible to create lumps and count files at the same time,
// but I didn't want to have to reallocate memory for every lump.
rewinddir(dirhandle[rootdir]);
depthleft = rootdir;
strlcpy(dirpath, path, dirpathlen);
initdirpath(dirpath, dirpathindex, depthleft);
lump_p = lumpinfo = Z_Calloc(numlumps * sizeof(lumpinfo_t), PU_STATIC, NULL);
while (depthleft < maxdirdepth)
{
char *fullname, *trimname;
dirpath[dirpathindex[depthleft]] = 0;
dent = readdir(dirhandle[depthleft]);
if (!dent)
{
closedir(dirhandle[depthleft++]);
continue;
}
else if (isuptree(dent->d_name))
continue;
strcpy(&dirpath[dirpathindex[depthleft]], dent->d_name);
if (stat(dirpath, &fsstat) < 0)
continue;
else if (S_ISDIR(fsstat.st_mode) && depthleft)
{
dirpathindex[--depthleft] = strlen(dirpath) + 1;
dirhandle[depthleft] = opendir(dirpath);
if (dirhandle[depthleft])
{
dirpath[dirpathindex[depthleft]-1] = '/';
dirpath[dirpathindex[depthleft]] = 0;
}
else
depthleft++;
continue;
}
lump_p->diskpath = Z_StrDup(dirpath); // Path in the filesystem to the file
lump_p->compression = CM_NOCOMPRESSION; // Lump is uncompressed
// Remove the directory's path.
fullname = lump_p->diskpath;
if (strstr(fullname, path))
fullname += strlen(path) + 1;
// Get the 8-character long lump name.
trimname = strrchr(fullname, '/');
if (trimname)
trimname++;
else
trimname = fullname;
if (trimname[0])
{
char *dotpos = strrchr(trimname, '.');
if (dotpos == NULL)
dotpos = fullname + strlen(fullname);
strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
// The name of the file, without the extension.
lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
}
else
lump_p->longname = Z_Calloc(1, PU_STATIC, NULL);
// The complete name of the file, with its extension,
// excluding the path of the directory where it resides.
lump_p->fullname = Z_StrDup(fullname);
lump_p++;
i++;
if (i > numlumps || i == (UINT16_MAX-1))
{
for (; depthleft < maxdirdepth; closedir(dirhandle[depthleft++])); // Close any open directories.
break;
}
}
free(dirpathindex);
free(dirhandle);
(*nlmp) = numlumps;
return lumpinfo;
}
//
// Addons menu
//
char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two) char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two)
"\5.txt", "\5.cfg", // exec "\5.txt", "\5.cfg", // exec
"\5.wad", "\5.wad",
@ -455,7 +832,6 @@ char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) pl
char filenamebuf[MAX_WADFILES][MAX_WADPATH]; char filenamebuf[MAX_WADFILES][MAX_WADPATH];
static boolean filemenucmp(char *haystack, char *needle) static boolean filemenucmp(char *haystack, char *needle)
{ {
static char localhaystack[128]; static char localhaystack[128];
@ -640,10 +1016,7 @@ boolean preparefilemenu(boolean samedepth)
if (!dent) if (!dent)
break; break;
else if (dent->d_name[0]=='.' && else if (isuptree(dent->d_name))
(dent->d_name[1]=='\0' ||
(dent->d_name[1]=='.' &&
dent->d_name[2]=='\0')))
continue; // we don't want to scan uptree continue; // we don't want to scan uptree
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name); strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
@ -704,10 +1077,7 @@ boolean preparefilemenu(boolean samedepth)
if (!dent) if (!dent)
break; break;
else if (dent->d_name[0]=='.' && else if (isuptree(dent->d_name))
(dent->d_name[1]=='\0' ||
(dent->d_name[1]=='.' &&
dent->d_name[2]=='\0')))
continue; // we don't want to scan uptree continue; // we don't want to scan uptree
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name); strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);

View file

@ -7,6 +7,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "d_netfil.h" #include "d_netfil.h"
#include "m_menu.h" // MAXSTRINGLENGTH #include "m_menu.h" // MAXSTRINGLENGTH
#include "w_wad.h"
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type; extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
@ -28,6 +29,16 @@ extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_sh
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth); boolean completepath, int maxsearchdepth);
INT32 pathisdirectory(const char *path);
INT32 samepaths(const char *path1, const char *path2);
INT32 concatpaths(const char *path, const char *startpath);
#ifndef AVOID_ERRNO
extern int direrror;
#endif
lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders);
#define menudepth 20 #define menudepth 20
extern char menupath[1024]; extern char menupath[1024];
@ -94,5 +105,4 @@ typedef enum
void closefilemenu(boolean validsize); void closefilemenu(boolean validsize);
void searchfilemenu(char *tempname); void searchfilemenu(char *tempname);
boolean preparefilemenu(boolean samedepth); boolean preparefilemenu(boolean samedepth);
#endif // __FILESRCH_H__ #endif // __FILESRCH_H__

View file

@ -1680,6 +1680,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
switch(oldversion) // demoversion switch(oldversion) // demoversion
{ {
case DEMOVERSION: // latest always supported case DEMOVERSION: // latest always supported
case 0x000d: // The previous demoversion also supported
case 0x000c: // all that changed between then and now was longer color name case 0x000c: // all that changed between then and now was longer color name
break; break;
// too old, cannot support. // too old, cannot support.
@ -2023,7 +2024,7 @@ void G_AddGhost(char *defdemoname)
char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16]; char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16];
UINT8 cnamelen; UINT8 cnamelen;
demoghost *gh; demoghost *gh;
UINT8 flags; UINT8 flags, subversion;
UINT8 *buffer,*p; UINT8 *buffer,*p;
mapthing_t *mthing; mapthing_t *mthing;
UINT16 count, ghostversion; UINT16 count, ghostversion;
@ -2071,7 +2072,7 @@ void G_AddGhost(char *defdemoname)
return; return;
} p += 12; // DEMOHEADER } p += 12; // DEMOHEADER
p++; // VERSION p++; // VERSION
p++; // SUBVERSION subversion = READUINT8(p); // SUBVERSION
ghostversion = READUINT16(p); ghostversion = READUINT16(p);
switch(ghostversion) switch(ghostversion)
{ {
@ -2169,11 +2170,21 @@ void G_AddGhost(char *defdemoname)
// net var data // net var data
count = READUINT16(p); count = READUINT16(p);
while (count--) while (count--)
{
// In 2.2.7 netvar saving was updated
if (subversion < 7)
{
p += 2;
SKIPSTRING(p);
p++;
}
else
{ {
SKIPSTRING(p); SKIPSTRING(p);
SKIPSTRING(p); SKIPSTRING(p);
p++; p++;
} }
}
if (*p == DEMOMARKER) if (*p == DEMOMARKER)
{ {

View file

@ -45,6 +45,7 @@
#include "lua_hook.h" #include "lua_hook.h"
#include "b_bot.h" #include "b_bot.h"
#include "m_cond.h" // condition sets #include "m_cond.h" // condition sets
#include "lua_script.h"
#include "lua_hud.h" #include "lua_hud.h"
@ -1139,13 +1140,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
return; return;
} }
turnright = PLAYERINPUTDOWN(ssplayer, gc_turnright); turnright = PLAYERINPUTDOWN(ssplayer, GC_TURNRIGHT);
turnleft = PLAYERINPUTDOWN(ssplayer, gc_turnleft); turnleft = PLAYERINPUTDOWN(ssplayer, GC_TURNLEFT);
straferkey = PLAYERINPUTDOWN(ssplayer, gc_straferight); straferkey = PLAYERINPUTDOWN(ssplayer, GC_STRAFERIGHT);
strafelkey = PLAYERINPUTDOWN(ssplayer, gc_strafeleft); strafelkey = PLAYERINPUTDOWN(ssplayer, GC_STRAFELEFT);
movefkey = PLAYERINPUTDOWN(ssplayer, gc_forward); movefkey = PLAYERINPUTDOWN(ssplayer, GC_FORWARD);
movebkey = PLAYERINPUTDOWN(ssplayer, gc_backward); movebkey = PLAYERINPUTDOWN(ssplayer, GC_BACKWARD);
if (strafeisturn) if (strafeisturn)
{ {
@ -1154,7 +1155,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
straferkey = strafelkey = false; straferkey = strafelkey = false;
} }
mouseaiming = (PLAYERINPUTDOWN(ssplayer, gc_mouseaiming)) ^ mouseaiming = (PLAYERINPUTDOWN(ssplayer, GC_MOUSEAIMING)) ^
((chasecam && !player->spectator) ? chasefreelook : alwaysfreelook); ((chasecam && !player->spectator) ? chasefreelook : alwaysfreelook);
analogjoystickmove = usejoystick && !Joystick.bGamepadStyle; analogjoystickmove = usejoystick && !Joystick.bGamepadStyle;
gamepadjoystickmove = usejoystick && Joystick.bGamepadStyle; gamepadjoystickmove = usejoystick && Joystick.bGamepadStyle;
@ -1270,11 +1271,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// forward with key or button // forward with key or button
if (movefkey || (gamepadjoystickmove && movejoystickvector.yaxis < 0) if (movefkey || (gamepadjoystickmove && movejoystickvector.yaxis < 0)
|| ((player->powers[pw_carry] == CR_NIGHTSMODE) || ((player->powers[pw_carry] == CR_NIGHTSMODE)
&& (PLAYERINPUTDOWN(ssplayer, gc_lookup) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0)))) && (PLAYERINPUTDOWN(ssplayer, GC_LOOKUP) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))))
forward = forwardmove[speed]; forward = forwardmove[speed];
if (movebkey || (gamepadjoystickmove && movejoystickvector.yaxis > 0) if (movebkey || (gamepadjoystickmove && movejoystickvector.yaxis > 0)
|| ((player->powers[pw_carry] == CR_NIGHTSMODE) || ((player->powers[pw_carry] == CR_NIGHTSMODE)
&& (PLAYERINPUTDOWN(ssplayer, gc_lookdown) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0)))) && (PLAYERINPUTDOWN(ssplayer, GC_LOOKDOWN) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))))
forward -= forwardmove[speed]; forward -= forwardmove[speed];
if (analogjoystickmove && movejoystickvector.yaxis != 0) if (analogjoystickmove && movejoystickvector.yaxis != 0)
@ -1287,9 +1288,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (strafelkey) if (strafelkey)
side -= sidemove[speed]; side -= sidemove[speed];
if (PLAYERINPUTDOWN(ssplayer, gc_weaponnext)) if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONNEXT))
cmd->buttons |= BT_WEAPONNEXT; // Next Weapon cmd->buttons |= BT_WEAPONNEXT; // Next Weapon
if (PLAYERINPUTDOWN(ssplayer, gc_weaponprev)) if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONPREV))
cmd->buttons |= BT_WEAPONPREV; // Previous Weapon cmd->buttons |= BT_WEAPONPREV; // Previous Weapon
#if NUM_WEAPONS > 10 #if NUM_WEAPONS > 10
@ -1298,7 +1299,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
//use the four avaliable bits to determine the weapon. //use the four avaliable bits to determine the weapon.
cmd->buttons &= ~BT_WEAPONMASK; cmd->buttons &= ~BT_WEAPONMASK;
for (i = 0; i < NUM_WEAPONS; ++i) for (i = 0; i < NUM_WEAPONS; ++i)
if (PLAYERINPUTDOWN(ssplayer, gc_wepslot1 + i)) if (PLAYERINPUTDOWN(ssplayer, GC_WEPSLOT1 + i))
{ {
cmd->buttons |= (UINT16)(i + 1); cmd->buttons |= (UINT16)(i + 1);
break; break;
@ -1306,34 +1307,34 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// fire with any button/key // fire with any button/key
axis = PlayerJoyAxis(ssplayer, JA_FIRE); axis = PlayerJoyAxis(ssplayer, JA_FIRE);
if (PLAYERINPUTDOWN(ssplayer, gc_fire) || (usejoystick && axis > 0)) if (PLAYERINPUTDOWN(ssplayer, GC_FIRE) || (usejoystick && axis > 0))
cmd->buttons |= BT_ATTACK; cmd->buttons |= BT_ATTACK;
// fire normal with any button/key // fire normal with any button/key
axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL); axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL);
if (PLAYERINPUTDOWN(ssplayer, gc_firenormal) || (usejoystick && axis > 0)) if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0))
cmd->buttons |= BT_FIRENORMAL; cmd->buttons |= BT_FIRENORMAL;
if (PLAYERINPUTDOWN(ssplayer, gc_tossflag)) if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG))
cmd->buttons |= BT_TOSSFLAG; cmd->buttons |= BT_TOSSFLAG;
// Lua scriptable buttons // Lua scriptable buttons
if (PLAYERINPUTDOWN(ssplayer, gc_custom1)) if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM1))
cmd->buttons |= BT_CUSTOM1; cmd->buttons |= BT_CUSTOM1;
if (PLAYERINPUTDOWN(ssplayer, gc_custom2)) if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM2))
cmd->buttons |= BT_CUSTOM2; cmd->buttons |= BT_CUSTOM2;
if (PLAYERINPUTDOWN(ssplayer, gc_custom3)) if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM3))
cmd->buttons |= BT_CUSTOM3; cmd->buttons |= BT_CUSTOM3;
// use with any button/key // use with any button/key
axis = PlayerJoyAxis(ssplayer, JA_SPIN); axis = PlayerJoyAxis(ssplayer, JA_SPIN);
if (PLAYERINPUTDOWN(ssplayer, gc_spin) || (usejoystick && axis > 0)) if (PLAYERINPUTDOWN(ssplayer, GC_SPIN) || (usejoystick && axis > 0))
cmd->buttons |= BT_SPIN; cmd->buttons |= BT_SPIN;
// Centerview can be a toggle in simple mode! // Centerview can be a toggle in simple mode!
{ {
static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior
boolean down = PLAYERINPUTDOWN(ssplayer, gc_centerview); boolean down = PLAYERINPUTDOWN(ssplayer, GC_CENTERVIEW);
if (!(controlstyle == CS_SIMPLE && cv_cam_centertoggle[forplayer].value)) if (!(controlstyle == CS_SIMPLE && cv_cam_centertoggle[forplayer].value))
centerviewdown = down; centerviewdown = down;
@ -1432,7 +1433,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (ticcmd_centerviewdown[forplayer] && controlstyle == CS_SIMPLE) if (ticcmd_centerviewdown[forplayer] && controlstyle == CS_SIMPLE)
controlstyle = CS_LEGACY; controlstyle = CS_LEGACY;
if (PLAYERINPUTDOWN(ssplayer, gc_camreset)) if (PLAYERINPUTDOWN(ssplayer, GC_CAMRESET))
{ {
if (thiscam->chase && !resetdown[forplayer]) if (thiscam->chase && !resetdown[forplayer])
P_ResetCamera(&players[ssplayer == 1 ? displayplayer : secondarydisplayplayer], thiscam); P_ResetCamera(&players[ssplayer == 1 ? displayplayer : secondarydisplayplayer], thiscam);
@ -1445,7 +1446,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// jump button // jump button
axis = PlayerJoyAxis(ssplayer, JA_JUMP); axis = PlayerJoyAxis(ssplayer, JA_JUMP);
if (PLAYERINPUTDOWN(ssplayer, gc_jump) || (usejoystick && axis > 0)) if (PLAYERINPUTDOWN(ssplayer, GC_JUMP) || (usejoystick && axis > 0))
cmd->buttons |= BT_JUMP; cmd->buttons |= BT_JUMP;
// player aiming shit, ahhhh... // player aiming shit, ahhhh...
@ -1475,12 +1476,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (!(player->powers[pw_carry] == CR_NIGHTSMODE)) if (!(player->powers[pw_carry] == CR_NIGHTSMODE))
{ {
if (PLAYERINPUTDOWN(ssplayer, gc_lookup) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0)) if (PLAYERINPUTDOWN(ssplayer, GC_LOOKUP) || (gamepadjoystickmove && lookjoystickvector.yaxis < 0))
{ {
*myaiming += KB_LOOKSPEED * screen_invert; *myaiming += KB_LOOKSPEED * screen_invert;
keyboard_look[forplayer] = true; keyboard_look[forplayer] = true;
} }
else if (PLAYERINPUTDOWN(ssplayer, gc_lookdown) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0)) else if (PLAYERINPUTDOWN(ssplayer, GC_LOOKDOWN) || (gamepadjoystickmove && lookjoystickvector.yaxis > 0))
{ {
*myaiming -= KB_LOOKSPEED * screen_invert; *myaiming -= KB_LOOKSPEED * screen_invert;
keyboard_look[forplayer] = true; keyboard_look[forplayer] = true;
@ -1959,7 +1960,7 @@ boolean G_Responder(event_t *ev)
if (gameaction == ga_nothing && !singledemo && if (gameaction == ga_nothing && !singledemo &&
((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN)) ((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN))
{ {
if (ev->type == ev_keydown && ev->data1 != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE)) if (ev->type == ev_keydown && ev->key != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE))
{ {
M_StartControlPanel(); M_StartControlPanel();
return true; return true;
@ -2035,7 +2036,7 @@ boolean G_Responder(event_t *ev)
// allow spy mode changes even during the demo // allow spy mode changes even during the demo
if (gamestate == GS_LEVEL && ev->type == ev_keydown if (gamestate == GS_LEVEL && ev->type == ev_keydown
&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) && (ev->key == KEY_F12 || ev->key == gamecontrol[GC_VIEWPOINT][0] || ev->key == gamecontrol[GC_VIEWPOINT][1]))
{ {
// ViewpointSwitch Lua hook. // ViewpointSwitch Lua hook.
UINT8 canSwitchView = 0; UINT8 canSwitchView = 0;
@ -2108,13 +2109,13 @@ boolean G_Responder(event_t *ev)
switch (ev->type) switch (ev->type)
{ {
case ev_keydown: case ev_keydown:
if (ev->data1 == gamecontrol[gc_pause][0] if (ev->key == gamecontrol[GC_PAUSE][0]
|| ev->data1 == gamecontrol[gc_pause][1] || ev->key == gamecontrol[GC_PAUSE][1]
|| ev->data1 == KEY_PAUSE) || ev->key == KEY_PAUSE)
{ {
if (modeattacking && !demoplayback && (gamestate == GS_LEVEL)) if (modeattacking && !demoplayback && (gamestate == GS_LEVEL))
{ {
pausebreakkey = (ev->data1 == KEY_PAUSE); pausebreakkey = (ev->key == KEY_PAUSE);
if (menuactive || pausedelay < 0 || leveltime < 2) if (menuactive || pausedelay < 0 || leveltime < 2)
return true; return true;
@ -2139,8 +2140,8 @@ boolean G_Responder(event_t *ev)
} }
} }
} }
if (ev->data1 == gamecontrol[gc_camtoggle][0] if (ev->key == gamecontrol[GC_CAMTOGGLE][0]
|| ev->data1 == gamecontrol[gc_camtoggle][1]) || ev->key == gamecontrol[GC_CAMTOGGLE][1])
{ {
if (!camtoggledelay) if (!camtoggledelay)
{ {
@ -2148,8 +2149,8 @@ boolean G_Responder(event_t *ev)
CV_SetValue(&cv_chasecam, cv_chasecam.value ? 0 : 1); CV_SetValue(&cv_chasecam, cv_chasecam.value ? 0 : 1);
} }
} }
if (ev->data1 == gamecontrolbis[gc_camtoggle][0] if (ev->key == gamecontrolbis[GC_CAMTOGGLE][0]
|| ev->data1 == gamecontrolbis[gc_camtoggle][1]) || ev->key == gamecontrolbis[GC_CAMTOGGLE][1])
{ {
if (!camtoggledelay2) if (!camtoggledelay2)
{ {
@ -2185,8 +2186,20 @@ boolean G_Responder(event_t *ev)
// //
boolean G_LuaResponder(event_t *ev) boolean G_LuaResponder(event_t *ev)
{ {
return (ev->type == ev_keydown && LUA_HookKey(ev->data1, HOOK(KeyDown))) || boolean cancelled = false;
(ev->type == ev_keyup && LUA_HookKey(ev->data1, HOOK(KeyUp)));
if (ev->type == ev_keydown)
{
cancelled = LUA_HookKey(ev, HOOK(KeyDown));
LUA_InvalidateUserdata(ev);
}
else if (ev->type == ev_keyup)
{
cancelled = LUA_HookKey(ev, HOOK(KeyUp));
LUA_InvalidateUserdata(ev);
}
return cancelled;
} }
// //
@ -5311,4 +5324,3 @@ INT32 G_TicsToMilliseconds(tic_t tics)
{ {
return (INT32)((tics%TICRATE) * (1000.00f/TICRATE)); return (INT32)((tics%TICRATE) * (1000.00f/TICRATE));
} }

View file

@ -41,49 +41,49 @@ INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymo
UINT8 gamekeydown[NUMINPUTS]; UINT8 gamekeydown[NUMINPUTS];
// two key codes (or virtual key) per game control // two key codes (or virtual key) per game control
INT32 gamecontrol[num_gamecontrols][2]; INT32 gamecontrol[NUM_GAMECONTROLS][2];
INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player INT32 gamecontrolbis[NUM_GAMECONTROLS][2]; // secondary splitscreen player
INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention INT32 gamecontroldefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2]; // default control storage, use 0 (gcs_custom) for memory retention
INT32 gamecontrolbisdefault[num_gamecontrolschemes][num_gamecontrols][2]; INT32 gamecontrolbisdefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2];
// lists of GC codes for selective operation // lists of GC codes for selective operation
const INT32 gcl_tutorial_check[num_gcl_tutorial_check] = { const INT32 gcl_tutorial_check[num_gcl_tutorial_check] = {
gc_forward, gc_backward, gc_strafeleft, gc_straferight, GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
gc_turnleft, gc_turnright GC_TURNLEFT, GC_TURNRIGHT
}; };
const INT32 gcl_tutorial_used[num_gcl_tutorial_used] = { const INT32 gcl_tutorial_used[num_gcl_tutorial_used] = {
gc_forward, gc_backward, gc_strafeleft, gc_straferight, GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
gc_turnleft, gc_turnright, GC_TURNLEFT, GC_TURNRIGHT,
gc_jump, gc_spin GC_JUMP, GC_SPIN
}; };
const INT32 gcl_tutorial_full[num_gcl_tutorial_full] = { const INT32 gcl_tutorial_full[num_gcl_tutorial_full] = {
gc_forward, gc_backward, gc_strafeleft, gc_straferight, GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
gc_lookup, gc_lookdown, gc_turnleft, gc_turnright, gc_centerview, GC_LOOKUP, GC_LOOKDOWN, GC_TURNLEFT, GC_TURNRIGHT, GC_CENTERVIEW,
gc_jump, gc_spin, GC_JUMP, GC_SPIN,
gc_fire, gc_firenormal GC_FIRE, GC_FIRENORMAL
}; };
const INT32 gcl_movement[num_gcl_movement] = { const INT32 gcl_movement[num_gcl_movement] = {
gc_forward, gc_backward, gc_strafeleft, gc_straferight GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT
}; };
const INT32 gcl_camera[num_gcl_camera] = { const INT32 gcl_camera[num_gcl_camera] = {
gc_turnleft, gc_turnright GC_TURNLEFT, GC_TURNRIGHT
}; };
const INT32 gcl_movement_camera[num_gcl_movement_camera] = { const INT32 gcl_movement_camera[num_gcl_movement_camera] = {
gc_forward, gc_backward, gc_strafeleft, gc_straferight, GC_FORWARD, GC_BACKWARD, GC_STRAFELEFT, GC_STRAFERIGHT,
gc_turnleft, gc_turnright GC_TURNLEFT, GC_TURNRIGHT
}; };
const INT32 gcl_jump[num_gcl_jump] = { gc_jump }; const INT32 gcl_jump[num_gcl_jump] = { GC_JUMP };
const INT32 gcl_spin[num_gcl_spin] = { gc_spin }; const INT32 gcl_spin[num_gcl_spin] = { GC_SPIN };
const INT32 gcl_jump_spin[num_gcl_jump_spin] = { const INT32 gcl_jump_spin[num_gcl_jump_spin] = {
gc_jump, gc_spin GC_JUMP, GC_SPIN
}; };
typedef struct typedef struct
@ -115,54 +115,54 @@ void G_MapEventsToControls(event_t *ev)
switch (ev->type) switch (ev->type)
{ {
case ev_keydown: case ev_keydown:
if (ev->data1 < NUMINPUTS) if (ev->key < NUMINPUTS)
gamekeydown[ev->data1] = 1; gamekeydown[ev->key] = 1;
#ifdef PARANOIA #ifdef PARANOIA
else else
{ {
CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n",ev->data1); CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n",ev->key);
} }
#endif #endif
break; break;
case ev_keyup: case ev_keyup:
if (ev->data1 < NUMINPUTS) if (ev->key < NUMINPUTS)
gamekeydown[ev->data1] = 0; gamekeydown[ev->key] = 0;
#ifdef PARANOIA #ifdef PARANOIA
else else
{ {
CONS_Debug(DBG_GAMELOGIC, "Bad upkey input %d\n",ev->data1); CONS_Debug(DBG_GAMELOGIC, "Bad upkey input %d\n",ev->key);
} }
#endif #endif
break; break;
case ev_mouse: // buttons are virtual keys case ev_mouse: // buttons are virtual keys
mouse.rdx = ev->data2; mouse.rdx = ev->x;
mouse.rdy = ev->data3; mouse.rdy = ev->y;
break; break;
case ev_joystick: // buttons are virtual keys case ev_joystick: // buttons are virtual keys
i = ev->data1; i = ev->key;
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on) if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
break; break;
if (ev->data2 != INT32_MAX) joyxmove[i] = ev->data2; if (ev->x != INT32_MAX) joyxmove[i] = ev->x;
if (ev->data3 != INT32_MAX) joyymove[i] = ev->data3; if (ev->y != INT32_MAX) joyymove[i] = ev->y;
break; break;
case ev_joystick2: // buttons are virtual keys case ev_joystick2: // buttons are virtual keys
i = ev->data1; i = ev->key;
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on) if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
break; break;
if (ev->data2 != INT32_MAX) joy2xmove[i] = ev->data2; if (ev->x != INT32_MAX) joy2xmove[i] = ev->x;
if (ev->data3 != INT32_MAX) joy2ymove[i] = ev->data3; if (ev->y != INT32_MAX) joy2ymove[i] = ev->y;
break; break;
case ev_mouse2: // buttons are virtual keys case ev_mouse2: // buttons are virtual keys
if (menuactive || CON_Ready() || chat_on) if (menuactive || CON_Ready() || chat_on)
break; break;
mouse2.rdx = ev->data2; mouse2.rdx = ev->x;
mouse2.rdy = ev->data3; mouse2.rdy = ev->y;
break; break;
default: default:
@ -553,9 +553,9 @@ static keyname_t keynames[] =
}; };
static const char *gamecontrolname[num_gamecontrols] = static const char *gamecontrolname[NUM_GAMECONTROLS] =
{ {
"nothing", // a key/button mapped to gc_null has no effect "nothing", // a key/button mapped to GC_NULL has no effect
"forward", "forward",
"backward", "backward",
"strafeleft", "strafeleft",
@ -613,7 +613,7 @@ void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control)
void G_ClearAllControlKeys(void) void G_ClearAllControlKeys(void)
{ {
INT32 i; INT32 i;
for (i = 0; i < num_gamecontrols; i++) for (i = 0; i < NUM_GAMECONTROLS; i++)
{ {
G_ClearControlKeys(gamecontrol, i); G_ClearControlKeys(gamecontrol, i);
G_ClearControlKeys(gamecontrolbis, i); G_ClearControlKeys(gamecontrolbis, i);
@ -624,7 +624,7 @@ void G_ClearAllControlKeys(void)
// Returns the name of a key (or virtual key for mouse and joy) // Returns the name of a key (or virtual key for mouse and joy)
// the input value being an keynum // the input value being an keynum
// //
const char *G_KeyNumToString(INT32 keynum) const char *G_KeyNumToName(INT32 keynum)
{ {
static char keynamestr[8]; static char keynamestr[8];
@ -648,7 +648,7 @@ const char *G_KeyNumToString(INT32 keynum)
return keynamestr; return keynamestr;
} }
INT32 G_KeyStringToNum(const char *keystr) INT32 G_KeyNameToNum(const char *keystr)
{ {
UINT32 j; UINT32 j;
@ -676,92 +676,92 @@ void G_DefineDefaultControls(void)
INT32 i; INT32 i;
// FPS game controls (WASD) // FPS game controls (WASD)
gamecontroldefault[gcs_fps][gc_forward ][0] = 'w'; gamecontroldefault[gcs_fps][GC_FORWARD ][0] = 'w';
gamecontroldefault[gcs_fps][gc_backward ][0] = 's'; gamecontroldefault[gcs_fps][GC_BACKWARD ][0] = 's';
gamecontroldefault[gcs_fps][gc_strafeleft ][0] = 'a'; gamecontroldefault[gcs_fps][GC_STRAFELEFT ][0] = 'a';
gamecontroldefault[gcs_fps][gc_straferight][0] = 'd'; gamecontroldefault[gcs_fps][GC_STRAFERIGHT][0] = 'd';
gamecontroldefault[gcs_fps][gc_lookup ][0] = KEY_UPARROW; gamecontroldefault[gcs_fps][GC_LOOKUP ][0] = KEY_UPARROW;
gamecontroldefault[gcs_fps][gc_lookdown ][0] = KEY_DOWNARROW; gamecontroldefault[gcs_fps][GC_LOOKDOWN ][0] = KEY_DOWNARROW;
gamecontroldefault[gcs_fps][gc_turnleft ][0] = KEY_LEFTARROW; gamecontroldefault[gcs_fps][GC_TURNLEFT ][0] = KEY_LEFTARROW;
gamecontroldefault[gcs_fps][gc_turnright ][0] = KEY_RIGHTARROW; gamecontroldefault[gcs_fps][GC_TURNRIGHT ][0] = KEY_RIGHTARROW;
gamecontroldefault[gcs_fps][gc_centerview ][0] = KEY_END; gamecontroldefault[gcs_fps][GC_CENTERVIEW ][0] = KEY_END;
gamecontroldefault[gcs_fps][gc_jump ][0] = KEY_SPACE; gamecontroldefault[gcs_fps][GC_JUMP ][0] = KEY_SPACE;
gamecontroldefault[gcs_fps][gc_spin ][0] = KEY_LSHIFT; gamecontroldefault[gcs_fps][GC_SPIN ][0] = KEY_LSHIFT;
gamecontroldefault[gcs_fps][gc_fire ][0] = KEY_RCTRL; gamecontroldefault[gcs_fps][GC_FIRE ][0] = KEY_RCTRL;
gamecontroldefault[gcs_fps][gc_fire ][1] = KEY_MOUSE1+0; gamecontroldefault[gcs_fps][GC_FIRE ][1] = KEY_MOUSE1+0;
gamecontroldefault[gcs_fps][gc_firenormal ][0] = 'c'; gamecontroldefault[gcs_fps][GC_FIRENORMAL ][0] = 'c';
// Platform game controls (arrow keys) // Platform game controls (arrow keys)
gamecontroldefault[gcs_platform][gc_forward ][0] = KEY_UPARROW; gamecontroldefault[gcs_platform][GC_FORWARD ][0] = KEY_UPARROW;
gamecontroldefault[gcs_platform][gc_backward ][0] = KEY_DOWNARROW; gamecontroldefault[gcs_platform][GC_BACKWARD ][0] = KEY_DOWNARROW;
gamecontroldefault[gcs_platform][gc_strafeleft ][0] = 'a'; gamecontroldefault[gcs_platform][GC_STRAFELEFT ][0] = 'a';
gamecontroldefault[gcs_platform][gc_straferight][0] = 'd'; gamecontroldefault[gcs_platform][GC_STRAFERIGHT][0] = 'd';
gamecontroldefault[gcs_platform][gc_lookup ][0] = KEY_PGUP; gamecontroldefault[gcs_platform][GC_LOOKUP ][0] = KEY_PGUP;
gamecontroldefault[gcs_platform][gc_lookdown ][0] = KEY_PGDN; gamecontroldefault[gcs_platform][GC_LOOKDOWN ][0] = KEY_PGDN;
gamecontroldefault[gcs_platform][gc_turnleft ][0] = KEY_LEFTARROW; gamecontroldefault[gcs_platform][GC_TURNLEFT ][0] = KEY_LEFTARROW;
gamecontroldefault[gcs_platform][gc_turnright ][0] = KEY_RIGHTARROW; gamecontroldefault[gcs_platform][GC_TURNRIGHT ][0] = KEY_RIGHTARROW;
gamecontroldefault[gcs_platform][gc_centerview ][0] = KEY_END; gamecontroldefault[gcs_platform][GC_CENTERVIEW ][0] = KEY_END;
gamecontroldefault[gcs_platform][gc_jump ][0] = KEY_SPACE; gamecontroldefault[gcs_platform][GC_JUMP ][0] = KEY_SPACE;
gamecontroldefault[gcs_platform][gc_spin ][0] = KEY_LSHIFT; gamecontroldefault[gcs_platform][GC_SPIN ][0] = KEY_LSHIFT;
gamecontroldefault[gcs_platform][gc_fire ][0] = 's'; gamecontroldefault[gcs_platform][GC_FIRE ][0] = 's';
gamecontroldefault[gcs_platform][gc_fire ][1] = KEY_MOUSE1+0; gamecontroldefault[gcs_platform][GC_FIRE ][1] = KEY_MOUSE1+0;
gamecontroldefault[gcs_platform][gc_firenormal ][0] = 'w'; gamecontroldefault[gcs_platform][GC_FIRENORMAL ][0] = 'w';
for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0) for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
{ {
gamecontroldefault[i][gc_weaponnext ][0] = KEY_MOUSEWHEELUP+0; gamecontroldefault[i][GC_WEAPONNEXT ][0] = KEY_MOUSEWHEELUP+0;
gamecontroldefault[i][gc_weaponprev ][0] = KEY_MOUSEWHEELDOWN+0; gamecontroldefault[i][GC_WEAPONPREV ][0] = KEY_MOUSEWHEELDOWN+0;
gamecontroldefault[i][gc_wepslot1 ][0] = '1'; gamecontroldefault[i][GC_WEPSLOT1 ][0] = '1';
gamecontroldefault[i][gc_wepslot2 ][0] = '2'; gamecontroldefault[i][GC_WEPSLOT2 ][0] = '2';
gamecontroldefault[i][gc_wepslot3 ][0] = '3'; gamecontroldefault[i][GC_WEPSLOT3 ][0] = '3';
gamecontroldefault[i][gc_wepslot4 ][0] = '4'; gamecontroldefault[i][GC_WEPSLOT4 ][0] = '4';
gamecontroldefault[i][gc_wepslot5 ][0] = '5'; gamecontroldefault[i][GC_WEPSLOT5 ][0] = '5';
gamecontroldefault[i][gc_wepslot6 ][0] = '6'; gamecontroldefault[i][GC_WEPSLOT6 ][0] = '6';
gamecontroldefault[i][gc_wepslot7 ][0] = '7'; gamecontroldefault[i][GC_WEPSLOT7 ][0] = '7';
gamecontroldefault[i][gc_wepslot8 ][0] = '8'; gamecontroldefault[i][GC_WEPSLOT8 ][0] = '8';
gamecontroldefault[i][gc_wepslot9 ][0] = '9'; gamecontroldefault[i][GC_WEPSLOT9 ][0] = '9';
gamecontroldefault[i][gc_wepslot10 ][0] = '0'; gamecontroldefault[i][GC_WEPSLOT10 ][0] = '0';
gamecontroldefault[i][gc_tossflag ][0] = '\''; gamecontroldefault[i][GC_TOSSFLAG ][0] = '\'';
gamecontroldefault[i][gc_camtoggle ][0] = 'v'; gamecontroldefault[i][GC_CAMTOGGLE ][0] = 'v';
gamecontroldefault[i][gc_camreset ][0] = 'r'; gamecontroldefault[i][GC_CAMRESET ][0] = 'r';
gamecontroldefault[i][gc_talkkey ][0] = 't'; gamecontroldefault[i][GC_TALKKEY ][0] = 't';
gamecontroldefault[i][gc_teamkey ][0] = 'y'; gamecontroldefault[i][GC_TEAMKEY ][0] = 'y';
gamecontroldefault[i][gc_scores ][0] = KEY_TAB; gamecontroldefault[i][GC_SCORES ][0] = KEY_TAB;
gamecontroldefault[i][gc_console ][0] = KEY_CONSOLE; gamecontroldefault[i][GC_CONSOLE ][0] = KEY_CONSOLE;
gamecontroldefault[i][gc_pause ][0] = 'p'; gamecontroldefault[i][GC_PAUSE ][0] = 'p';
gamecontroldefault[i][gc_screenshot ][0] = KEY_F8; gamecontroldefault[i][GC_SCREENSHOT ][0] = KEY_F8;
gamecontroldefault[i][gc_recordgif ][0] = KEY_F9; gamecontroldefault[i][GC_RECORDGIF ][0] = KEY_F9;
gamecontroldefault[i][gc_viewpoint ][0] = KEY_F12; gamecontroldefault[i][GC_VIEWPOINT ][0] = KEY_F12;
// Gamepad controls -- same for both schemes // Gamepad controls -- same for both schemes
gamecontroldefault[i][gc_weaponnext ][1] = KEY_JOY1+1; // B gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_JOY1+1; // B
gamecontroldefault[i][gc_weaponprev ][1] = KEY_JOY1+2; // X gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_JOY1+2; // X
gamecontroldefault[i][gc_tossflag ][1] = KEY_JOY1+0; // A gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_JOY1+0; // A
gamecontroldefault[i][gc_spin ][1] = KEY_JOY1+4; // LB gamecontroldefault[i][GC_SPIN ][1] = KEY_JOY1+4; // LB
gamecontroldefault[i][gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_HAT1+0; // D-Pad Up
gamecontroldefault[i][gc_camreset ][1] = KEY_JOY1+3; // Y gamecontroldefault[i][GC_CAMRESET ][1] = KEY_JOY1+3; // Y
gamecontroldefault[i][gc_centerview ][1] = KEY_JOY1+9; // Right Stick gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+9; // Right Stick
gamecontroldefault[i][gc_talkkey ][1] = KEY_HAT1+2; // D-Pad Left gamecontroldefault[i][GC_TALKKEY ][1] = KEY_HAT1+2; // D-Pad Left
gamecontroldefault[i][gc_scores ][1] = KEY_HAT1+3; // D-Pad Right gamecontroldefault[i][GC_SCORES ][1] = KEY_HAT1+3; // D-Pad Right
gamecontroldefault[i][gc_jump ][1] = KEY_JOY1+5; // RB gamecontroldefault[i][GC_JUMP ][1] = KEY_JOY1+5; // RB
gamecontroldefault[i][gc_pause ][1] = KEY_JOY1+6; // Back gamecontroldefault[i][GC_PAUSE ][1] = KEY_JOY1+6; // Back
gamecontroldefault[i][gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_HAT1+1; // D-Pad Down
gamecontroldefault[i][gc_systemmenu ][0] = KEY_JOY1+7; // Start gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start
// Second player controls only have joypad defaults // Second player controls only have joypad defaults
gamecontrolbisdefault[i][gc_weaponnext][0] = KEY_2JOY1+1; // B gamecontrolbisdefault[i][GC_WEAPONNEXT][0] = KEY_2JOY1+1; // B
gamecontrolbisdefault[i][gc_weaponprev][0] = KEY_2JOY1+2; // X gamecontrolbisdefault[i][GC_WEAPONPREV][0] = KEY_2JOY1+2; // X
gamecontrolbisdefault[i][gc_tossflag ][0] = KEY_2JOY1+0; // A gamecontrolbisdefault[i][GC_TOSSFLAG ][0] = KEY_2JOY1+0; // A
gamecontrolbisdefault[i][gc_spin ][0] = KEY_2JOY1+4; // LB gamecontrolbisdefault[i][GC_SPIN ][0] = KEY_2JOY1+4; // LB
gamecontrolbisdefault[i][gc_camreset ][0] = KEY_2JOY1+3; // Y gamecontrolbisdefault[i][GC_CAMRESET ][0] = KEY_2JOY1+3; // Y
gamecontrolbisdefault[i][gc_centerview][0] = KEY_2JOY1+9; // Right Stick gamecontrolbisdefault[i][GC_CENTERVIEW][0] = KEY_2JOY1+9; // Right Stick
gamecontrolbisdefault[i][gc_jump ][0] = KEY_2JOY1+5; // RB gamecontrolbisdefault[i][GC_JUMP ][0] = KEY_2JOY1+5; // RB
//gamecontrolbisdefault[i][gc_pause ][0] = KEY_2JOY1+6; // Back //gamecontrolbisdefault[i][GC_PAUSE ][0] = KEY_2JOY1+6; // Back
//gamecontrolbisdefault[i][gc_systemmenu][0] = KEY_2JOY1+7; // Start //gamecontrolbisdefault[i][GC_SYSTEMMENU][0] = KEY_2JOY1+7; // Start
gamecontrolbisdefault[i][gc_camtoggle ][0] = KEY_2HAT1+0; // D-Pad Up gamecontrolbisdefault[i][GC_CAMTOGGLE ][0] = KEY_2HAT1+0; // D-Pad Up
gamecontrolbisdefault[i][gc_screenshot][0] = KEY_2HAT1+1; // D-Pad Down gamecontrolbisdefault[i][GC_SCREENSHOT][0] = KEY_2HAT1+1; // D-Pad Down
//gamecontrolbisdefault[i][gc_talkkey ][0] = KEY_2HAT1+2; // D-Pad Left //gamecontrolbisdefault[i][GC_TALKKEY ][0] = KEY_2HAT1+2; // D-Pad Left
//gamecontrolbisdefault[i][gc_scores ][0] = KEY_2HAT1+3; // D-Pad Right //gamecontrolbisdefault[i][GC_SCORES ][0] = KEY_2HAT1+3; // D-Pad Right
} }
} }
@ -773,7 +773,7 @@ INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gc
for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0) for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
{ {
skipscheme = false; skipscheme = false;
for (j = 0; j < (gclist && gclen ? gclen : num_gamecontrols); j++) for (j = 0; j < (gclist && gclen ? gclen : NUM_GAMECONTROLS); j++)
{ {
gc = (gclist && gclen) ? gclist[j] : j; gc = (gclist && gclen) ? gclist[j] : j;
if (((fromcontrols[gc][0] && gamecontroldefault[i][gc][0]) ? fromcontrols[gc][0] != gamecontroldefault[i][gc][0] : true) && if (((fromcontrols[gc][0] && gamecontroldefault[i][gc][0]) ? fromcontrols[gc][0] != gamecontroldefault[i][gc][0] : true) &&
@ -796,7 +796,7 @@ void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const I
{ {
INT32 i, gc; INT32 i, gc;
for (i = 0; i < (gclist && gclen ? gclen : num_gamecontrols); i++) for (i = 0; i < (gclist && gclen ? gclen : NUM_GAMECONTROLS); i++)
{ {
gc = (gclist && gclen) ? gclist[i] : i; gc = (gclist && gclen) ? gclist[i] : i;
setupcontrols[gc][0] = fromcontrols[gc][0]; setupcontrols[gc][0] = fromcontrols[gc][0];
@ -808,24 +808,24 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis
{ {
INT32 i; INT32 i;
for (i = 1; i < num_gamecontrols; i++) for (i = 1; i < NUM_GAMECONTROLS; i++)
{ {
fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i], fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i],
G_KeyNumToString(fromcontrols[i][0])); G_KeyNumToName(fromcontrols[i][0]));
if (fromcontrols[i][1]) if (fromcontrols[i][1])
fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrols[i][1])); fprintf(f, " \"%s\"\n", G_KeyNumToName(fromcontrols[i][1]));
else else
fprintf(f, "\n"); fprintf(f, "\n");
} }
for (i = 1; i < num_gamecontrols; i++) for (i = 1; i < NUM_GAMECONTROLS; i++)
{ {
fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i], fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i],
G_KeyNumToString(fromcontrolsbis[i][0])); G_KeyNumToName(fromcontrolsbis[i][0]));
if (fromcontrolsbis[i][1]) if (fromcontrolsbis[i][1])
fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrolsbis[i][1])); fprintf(f, " \"%s\"\n", G_KeyNumToName(fromcontrolsbis[i][1]));
else else
fprintf(f, "\n"); fprintf(f, "\n");
} }
@ -833,11 +833,11 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis
INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify) INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify)
{ {
INT32 result = gc_null; INT32 result = GC_NULL;
if (cv_controlperkey.value == 1) if (cv_controlperkey.value == 1)
{ {
INT32 i; INT32 i;
for (i = 0; i < num_gamecontrols; i++) for (i = 0; i < NUM_GAMECONTROLS; i++)
{ {
if (gamecontrol[i][0] == keynum) if (gamecontrol[i][0] == keynum)
{ {
@ -883,11 +883,11 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT
return -1; // skip setting control return -1; // skip setting control
if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22 if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22
numctrl == gc_weaponnext || numctrl == gc_weaponprev || numctrl == gc_tossflag || numctrl == GC_WEAPONNEXT || numctrl == GC_WEAPONPREV || numctrl == GC_TOSSFLAG ||
numctrl == gc_spin || numctrl == gc_camreset || numctrl == gc_jump || numctrl == GC_SPIN || numctrl == GC_CAMRESET || numctrl == GC_JUMP ||
numctrl == gc_pause || numctrl == gc_systemmenu || numctrl == gc_camtoggle || numctrl == GC_PAUSE || numctrl == GC_SYSTEMMENU || numctrl == GC_CAMTOGGLE ||
numctrl == gc_screenshot || numctrl == gc_talkkey || numctrl == gc_scores || numctrl == GC_SCREENSHOT || numctrl == GC_TALKKEY || numctrl == GC_SCORES ||
numctrl == gc_centerview numctrl == GC_CENTERVIEW
)) ))
{ {
INT32 keynum = 0, existingctrl = 0; INT32 keynum = 0, existingctrl = 0;
@ -895,7 +895,7 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT
boolean defaultoverride = false; boolean defaultoverride = false;
// get the default gamecontrol // get the default gamecontrol
if (player == 0 && numctrl == gc_systemmenu) if (player == 0 && numctrl == GC_SYSTEMMENU)
defaultkey = gamecontrol[numctrl][0]; defaultkey = gamecontrol[numctrl][0];
else else
defaultkey = (player == 1 ? gamecontrolbis[numctrl][0] : gamecontrol[numctrl][1]); defaultkey = (player == 1 ? gamecontrolbis[numctrl][0] : gamecontrol[numctrl][1]);
@ -993,16 +993,16 @@ static void setcontrol(INT32 (*gc)[2])
// Update me for 2.3 // Update me for 2.3
namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin"; namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin";
for (numctrl = 0; numctrl < num_gamecontrols && stricmp(namectrl, gamecontrolname[numctrl]); for (numctrl = 0; numctrl < NUM_GAMECONTROLS && stricmp(namectrl, gamecontrolname[numctrl]);
numctrl++) numctrl++)
; ;
if (numctrl == num_gamecontrols) if (numctrl == NUM_GAMECONTROLS)
{ {
CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl); CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl);
return; return;
} }
keynum1 = G_KeyStringToNum(COM_Argv(2)); keynum1 = G_KeyNameToNum(COM_Argv(2));
keynum2 = G_KeyStringToNum(COM_Argv(3)); keynum2 = G_KeyNameToNum(COM_Argv(3));
keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride);
if (keynum >= 0) if (keynum >= 0)

View file

@ -58,49 +58,49 @@ typedef enum
typedef enum typedef enum
{ {
gc_null = 0, // a key/button mapped to gc_null has no effect GC_NULL = 0, // a key/button mapped to GC_NULL has no effect
gc_forward, GC_FORWARD,
gc_backward, GC_BACKWARD,
gc_strafeleft, GC_STRAFELEFT,
gc_straferight, GC_STRAFERIGHT,
gc_turnleft, GC_TURNLEFT,
gc_turnright, GC_TURNRIGHT,
gc_weaponnext, GC_WEAPONNEXT,
gc_weaponprev, GC_WEAPONPREV,
gc_wepslot1, GC_WEPSLOT1,
gc_wepslot2, GC_WEPSLOT2,
gc_wepslot3, GC_WEPSLOT3,
gc_wepslot4, GC_WEPSLOT4,
gc_wepslot5, GC_WEPSLOT5,
gc_wepslot6, GC_WEPSLOT6,
gc_wepslot7, GC_WEPSLOT7,
gc_wepslot8, GC_WEPSLOT8,
gc_wepslot9, GC_WEPSLOT9,
gc_wepslot10, GC_WEPSLOT10,
gc_fire, GC_FIRE,
gc_firenormal, GC_FIRENORMAL,
gc_tossflag, GC_TOSSFLAG,
gc_spin, GC_SPIN,
gc_camtoggle, GC_CAMTOGGLE,
gc_camreset, GC_CAMRESET,
gc_lookup, GC_LOOKUP,
gc_lookdown, GC_LOOKDOWN,
gc_centerview, GC_CENTERVIEW,
gc_mouseaiming, // mouse aiming is momentary (toggleable in the menu) GC_MOUSEAIMING, // mouse aiming is momentary (toggleable in the menu)
gc_talkkey, GC_TALKKEY,
gc_teamkey, GC_TEAMKEY,
gc_scores, GC_SCORES,
gc_jump, GC_JUMP,
gc_console, GC_CONSOLE,
gc_pause, GC_PAUSE,
gc_systemmenu, GC_SYSTEMMENU,
gc_screenshot, GC_SCREENSHOT,
gc_recordgif, GC_RECORDGIF,
gc_viewpoint, GC_VIEWPOINT,
gc_custom1, // Lua scriptable GC_CUSTOM1, // Lua scriptable
gc_custom2, // Lua scriptable GC_CUSTOM2, // Lua scriptable
gc_custom3, // Lua scriptable GC_CUSTOM3, // Lua scriptable
num_gamecontrols NUM_GAMECONTROLS
} gamecontrols_e; } gamecontrols_e;
typedef enum typedef enum
@ -146,10 +146,10 @@ extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET],
extern UINT8 gamekeydown[NUMINPUTS]; extern UINT8 gamekeydown[NUMINPUTS];
// two key codes (or virtual key) per game control // two key codes (or virtual key) per game control
extern INT32 gamecontrol[num_gamecontrols][2]; extern INT32 gamecontrol[NUM_GAMECONTROLS][2];
extern INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player extern INT32 gamecontrolbis[NUM_GAMECONTROLS][2]; // secondary splitscreen player
extern INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention extern INT32 gamecontroldefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2]; // default control storage, use 0 (gcs_custom) for memory retention
extern INT32 gamecontrolbisdefault[num_gamecontrolschemes][num_gamecontrols][2]; extern INT32 gamecontrolbisdefault[num_gamecontrolschemes][NUM_GAMECONTROLS][2];
#define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]]) #define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]])
#define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]]) #define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]])
#define PLAYERINPUTDOWN(p, gc) ((p) == 2 ? PLAYER2INPUTDOWN(gc) : PLAYER1INPUTDOWN(gc)) #define PLAYERINPUTDOWN(p, gc) ((p) == 2 ? PLAYER2INPUTDOWN(gc) : PLAYER1INPUTDOWN(gc))
@ -181,8 +181,8 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin];
void G_MapEventsToControls(event_t *ev); void G_MapEventsToControls(event_t *ev);
// returns the name of a key // returns the name of a key
const char *G_KeyNumToString(INT32 keynum); const char *G_KeyNumToName(INT32 keynum);
INT32 G_KeyStringToNum(const char *keystr); INT32 G_KeyNameToNum(const char *keystr);
// detach any keys associated to the given game control // detach any keys associated to the given game control
void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control); void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control);

View file

@ -317,7 +317,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
} }
} }
if (pscale != FRACUNIT || (splitscreen && option & V_PERPLAYER)) if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
{ {
fwidth = (float)(gpatch->width) * fscalew * dupx; fwidth = (float)(gpatch->width) * fscalew * dupx;
fheight = (float)(gpatch->height) * fscaleh * dupy; fheight = (float)(gpatch->height) * fscaleh * dupy;
@ -382,7 +382,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
HWD.pfnDrawPolygon(NULL, v, 4, flags); HWD.pfnDrawPolygon(NULL, v, 4, flags);
} }
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
{ {
FOutVector v[4]; FOutVector v[4];
FBITFIELD flags; FBITFIELD flags;
@ -395,13 +395,19 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
// | /| // | /|
// |/ | // |/ |
// 0--1 // 0--1
float dupx, dupy, fscale, fwidth, fheight; float dupx, dupy, fscalew, fscaleh, fwidth, fheight;
UINT8 perplayershuffle = 0;
if (alphalevel >= 10 && alphalevel < 13) if (alphalevel >= 10 && alphalevel < 13)
return; return;
// make patch ready in hardware cache // make patch ready in hardware cache
if (!colormap)
HWR_GetPatch(gpatch); HWR_GetPatch(gpatch);
else
HWR_GetMappedPatch(gpatch, colormap);
hwrPatch = ((GLPatch_t *)gpatch->hardware); hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx; dupx = (float)vid.dupx;
@ -423,12 +429,80 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
} }
dupx = dupy = (dupx < dupy ? dupx : dupy); dupx = dupy = (dupx < dupy ? dupx : dupy);
fscale = FIXED_TO_FLOAT(pscale); fscalew = fscaleh = FIXED_TO_FLOAT(pscale);
if (vscale != pscale)
fscaleh = FIXED_TO_FLOAT(vscale);
// fuck it, no GL support for croppedpatch v_perplayer right now. it's not like it's accessible to Lua or anything, and we only use it for menus... cx -= (float)(gpatch->leftoffset) * fscalew;
cy -= (float)(gpatch->topoffset) * fscaleh;
cy -= (float)(gpatch->topoffset) * fscale; if (splitscreen && (option & V_PERPLAYER))
cx -= (float)(gpatch->leftoffset) * fscale; {
float adjusty = ((option & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
fscaleh /= 2;
cy /= 2;
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
float adjustx = ((option & V_NOSCALESTART) ? vid.width : BASEVIDWIDTH)/2.0f;
fscalew /= 2;
cx /= 2;
if (stplyr == &players[displayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
option &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
}
else if (stplyr == &players[secondarydisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 1;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
cx += adjustx;
option &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
}
else if (stplyr == &players[thirddisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4;
cy += adjusty;
option &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
}
else if (stplyr == &players[fourthdisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2;
if (!(option & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8;
cx += adjustx;
cy += adjusty;
option &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
}
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle = 1;
option &= ~V_SNAPTOBOTTOM;
}
else //if (stplyr == &players[secondarydisplayplayer])
{
if (!(option & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle = 2;
cy += adjusty;
option &= ~V_SNAPTOTOP;
}
}
}
if (!(option & V_NOSCALESTART)) if (!(option & V_NOSCALESTART))
{ {
@ -447,6 +521,10 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(option & V_SNAPTOLEFT)) else if (!(option & V_SNAPTOLEFT))
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2; cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
if (perplayershuffle & 4)
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
else if (perplayershuffle & 8)
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
} }
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
{ {
@ -454,23 +532,27 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(option & V_SNAPTOTOP)) else if (!(option & V_SNAPTOTOP))
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
if (perplayershuffle & 1)
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
else if (perplayershuffle & 2)
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
} }
} }
} }
fwidth = w; fwidth = FIXED_TO_FLOAT(w);
fheight = h; fheight = FIXED_TO_FLOAT(h);
if (sx + w > gpatch->width) if (sx + w > gpatch->width<<FRACBITS)
fwidth = gpatch->width - sx; fwidth = FIXED_TO_FLOAT((gpatch->width<<FRACBITS) - sx);
if (sy + h > gpatch->height) if (sy + h > gpatch->height<<FRACBITS)
fheight = gpatch->height - sy; fheight = FIXED_TO_FLOAT((gpatch->height<<FRACBITS) - sy);
if (pscale != FRACUNIT) if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
{ {
fwidth *= fscale * dupx; fwidth *= fscalew * dupx;
fheight *= fscale * dupy; fheight *= fscaleh * dupy;
} }
else else
{ {
@ -495,17 +577,17 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = ((sx)/(float)(gpatch->width))*hwrPatch->max_s; v[0].s = v[3].s = (FIXED_TO_FLOAT(sx)/(float)(gpatch->width))*hwrPatch->max_s;
if (sx + w > gpatch->width) if (sx + w > gpatch->width<<FRACBITS)
v[2].s = v[1].s = hwrPatch->max_s; v[2].s = v[1].s = hwrPatch->max_s;
else else
v[2].s = v[1].s = ((sx+w)/(float)(gpatch->width))*hwrPatch->max_s; v[2].s = v[1].s = (FIXED_TO_FLOAT(sx+w)/(float)(gpatch->width))*hwrPatch->max_s;
v[0].t = v[1].t = ((sy)/(float)(gpatch->height))*hwrPatch->max_t; v[0].t = v[1].t = (FIXED_TO_FLOAT(sy)/(float)(gpatch->height))*hwrPatch->max_t;
if (sy + h > gpatch->height) if (sy + h > gpatch->height<<FRACBITS)
v[2].t = v[3].t = hwrPatch->max_t; v[2].t = v[3].t = hwrPatch->max_t;
else else
v[2].t = v[3].t = ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t; v[2].t = v[3].t = (FIXED_TO_FLOAT(sy+h)/(float)(gpatch->height))*hwrPatch->max_t;
flags = PF_Translucent|PF_NoDepthTest; flags = PF_Translucent|PF_NoDepthTest;
@ -514,6 +596,76 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
if (option & V_WRAPY) if (option & V_WRAPY)
flags |= PF_ForceWrapY; flags |= PF_ForceWrapY;
// Auto-crop at splitscreen borders!
if (splitscreen && (option & V_PERPLAYER))
{
#define flerp(a,b,amount) (((a) * (1.0f - (amount))) + ((b) * (amount))) // Float lerp
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
#error Auto-cropping doesnt take quadscreen into account! Fix it!
// Hint: For player 1/2, copy player 1's code below. For player 3/4, copy player 2's code below
// For player 1/3 and 2/4, mangle the below code to apply horizontally instead of vertically
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer]) // Player 1's screen, crop at the bottom
{
if ((cy - fheight) < 0) // If the bottom is below the border
{
if (cy <= 0) // If the whole patch is beyond the border...
return; // ...crop away the entire patch, don't draw anything
if (fheight <= 0) // Don't divide by zero
return;
v[2].y = v[3].y = 0; // Clamp the polygon edge vertex position
// Now for the UV-map... Uh-oh, math time!
// On second thought, a basic linear interpolation suffices
//float full_height = fheight;
//float cropped_height = fheight - cy;
//float remaining_height = cy;
//float cropped_percentage = (fheight - cy) / fheight;
//float remaining_percentage = cy / fheight;
//v[2].t = v[3].t = lerp(v[2].t, v[0].t, cropped_percentage);
// By swapping v[2] and v[0], we can use remaining_percentage for less operations
//v[2].t = v[3].t = lerp(v[0].t, v[2].t, remaining_percentage);
v[2].t = v[3].t = flerp(v[0].t, v[2].t, cy/fheight);
}
}
else //if (stplyr == &players[secondarydisplayplayer]) // Player 2's screen, crop at the top
{
if (cy > 0) // If the top is above the border
{
if ((cy - fheight) >= 0) // If the whole patch is beyond the border...
return; // ...crop away the entire patch, don't draw anything
if (fheight <= 0) // Don't divide by zero
return;
v[0].y = v[1].y = 0; // Clamp the polygon edge vertex position
// Now for the UV-map... Uh-oh, math time!
// On second thought, a basic linear interpolation suffices
//float full_height = fheight;
//float cropped_height = cy;
//float remaining_height = fheight - cy;
//float cropped_percentage = cy / fheight;
//float remaining_percentage = (fheight - cy) / fheight;
//v[0].t = v[1].t = lerp(v[0].t, v[2].t, cropped_percentage);
v[0].t = v[1].t = flerp(v[0].t, v[2].t, cy/fheight);
}
}
}
#undef flerp
}
// clip it since it is used for bunny scroll in doom I // clip it since it is used for bunny scroll in doom I
if (alphalevel) if (alphalevel)
{ {

View file

@ -6718,7 +6718,7 @@ void HWR_LoadAllCustomShaders(void)
// read every custom shader // read every custom shader
for (i = 0; i < numwadfiles; i++) for (i = 0; i < numwadfiles; i++)
HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3)); HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
} }
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)

View file

@ -39,7 +39,7 @@ void HWR_InitTextureMapping(void);
void HWR_SetViewSize(void); void HWR_SetViewSize(void);
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option);
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap);
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap);
void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum);

View file

@ -936,7 +936,7 @@ void HU_Ticker(void)
hu_tick++; hu_tick++;
hu_tick &= 7; // currently only to blink chat input cursor hu_tick &= 7; // currently only to blink chat input cursor
if (PLAYER1INPUTDOWN(gc_scores)) if (PLAYER1INPUTDOWN(GC_SCORES))
hu_showscores = !chat_on; hu_showscores = !chat_on;
else else
hu_showscores = false; hu_showscores = false;
@ -1111,26 +1111,26 @@ boolean HU_Responder(event_t *ev)
// (Unless if you're sharing a keyboard, since you probably establish when you start chatting that you have dibs on it...) // (Unless if you're sharing a keyboard, since you probably establish when you start chatting that you have dibs on it...)
// (Ahhh, the good ol days when I was a kid who couldn't afford an extra USB controller...) // (Ahhh, the good ol days when I was a kid who couldn't afford an extra USB controller...)
if (ev->data1 >= KEY_MOUSE1) if (ev->key >= KEY_MOUSE1)
{ {
INT32 i; INT32 i;
for (i = 0; i < num_gamecontrols; i++) for (i = 0; i < NUM_GAMECONTROLS; i++)
{ {
if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1) if (gamecontrol[i][0] == ev->key || gamecontrol[i][1] == ev->key)
break; break;
} }
if (i == num_gamecontrols) if (i == NUM_GAMECONTROLS)
return false; return false;
}*/ //We don't actually care about that unless we get splitscreen netgames. :V }*/ //We don't actually care about that unless we get splitscreen netgames. :V
#ifndef NONET #ifndef NONET
c = (INT32)ev->data1; c = (INT32)ev->key;
if (!chat_on) if (!chat_on)
{ {
// enter chat mode // enter chat mode
if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1]) if ((ev->key == gamecontrol[GC_TALKKEY][0] || ev->key == gamecontrol[GC_TALKKEY][1])
&& netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise. && netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise.
{ {
chat_on = true; chat_on = true;
@ -1140,7 +1140,7 @@ boolean HU_Responder(event_t *ev)
typelines = 1; typelines = 1;
return true; return true;
} }
if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1]) if ((ev->key == gamecontrol[GC_TEAMKEY][0] || ev->key == gamecontrol[GC_TEAMKEY][1])
&& netgame && !OLD_MUTE) && netgame && !OLD_MUTE)
{ {
chat_on = true; chat_on = true;
@ -1157,12 +1157,12 @@ boolean HU_Responder(event_t *ev)
// Ignore modifier keys // Ignore modifier keys
// Note that we do this here so users can still set // Note that we do this here so users can still set
// their chat keys to one of these, if they so desire. // their chat keys to one of these, if they so desire.
if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT if (ev->key == KEY_LSHIFT || ev->key == KEY_RSHIFT
|| ev->data1 == KEY_LCTRL || ev->data1 == KEY_RCTRL || ev->key == KEY_LCTRL || ev->key == KEY_RCTRL
|| ev->data1 == KEY_LALT || ev->data1 == KEY_RALT) || ev->key == KEY_LALT || ev->key == KEY_RALT)
return true; return true;
c = (INT32)ev->data1; c = (INT32)ev->key;
// I know this looks very messy but this works. If it ain't broke, don't fix it! // I know this looks very messy but this works. If it ain't broke, don't fix it!
// shift LETTERS to uppercase if we have capslock or are holding shift // shift LETTERS to uppercase if we have capslock or are holding shift
@ -1234,8 +1234,8 @@ boolean HU_Responder(event_t *ev)
I_UpdateMouseGrab(); I_UpdateMouseGrab();
} }
else if (c == KEY_ESCAPE else if (c == KEY_ESCAPE
|| ((c == gamecontrol[gc_talkkey][0] || c == gamecontrol[gc_talkkey][1] || ((c == gamecontrol[GC_TALKKEY][0] || c == gamecontrol[GC_TALKKEY][1]
|| c == gamecontrol[gc_teamkey][0] || c == gamecontrol[gc_teamkey][1]) || c == gamecontrol[GC_TEAMKEY][0] || c == gamecontrol[GC_TEAMKEY][1])
&& c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle. && c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle.
{ {
chat_on = false; chat_on = false;
@ -2104,7 +2104,7 @@ void HU_Drawer(void)
} }
else else
HU_DrawCoopOverlay(); HU_DrawCoopOverlay();
LUAh_ScoresHUD(); LUA_HUDHOOK(scores);
} }
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)

View file

@ -1885,6 +1885,37 @@ static int lib_pDoSpring(lua_State *L)
return 1; return 1;
} }
static int lib_pTryCameraMove(lua_State *L)
{
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
if (!cam)
return LUA_ErrInvalid(L, "camera_t");
lua_pushboolean(L, P_TryCameraMove(x, y, cam));
return 1;
}
static int lib_pTeleportCameraMove(lua_State *L)
{
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
fixed_t z = luaL_checkfixed(L, 4);
if (!cam)
return LUA_ErrInvalid(L, "camera_t");
cam->x = x;
cam->y = y;
cam->z = z;
P_CheckCameraPosition(x, y, cam);
cam->subsector = R_PointInSubsector(x, y);
cam->floorz = tmfloorz;
cam->ceilingz = tmceilingz;
return 0;
}
// P_INTER // P_INTER
//////////// ////////////
@ -3405,7 +3436,7 @@ static int lib_gAddPlayer(lua_State *L)
{ {
INT16 i, newplayernum, botcount = 1; INT16 i, newplayernum, botcount = 1;
player_t *newplayer; player_t *newplayer;
INT8 skinnum = 0, bot; SINT8 skinnum = 0, bot;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
@ -3988,6 +4019,8 @@ static luaL_Reg lib[] = {
{"P_FloorzAtPos",lib_pFloorzAtPos}, {"P_FloorzAtPos",lib_pFloorzAtPos},
{"P_CeilingzAtPos",lib_pCeilingzAtPos}, {"P_CeilingzAtPos",lib_pCeilingzAtPos},
{"P_DoSpring",lib_pDoSpring}, {"P_DoSpring",lib_pDoSpring},
{"P_TryCameraMove", lib_pTryCameraMove},
{"P_TeleportCameraMove", lib_pTeleportCameraMove},
// p_inter // p_inter
{"P_RemoveShield",lib_pRemoveShield}, {"P_RemoveShield",lib_pRemoveShield},

View file

@ -13,6 +13,7 @@
#include "r_defs.h" #include "r_defs.h"
#include "d_player.h" #include "d_player.h"
#include "s_sound.h" #include "s_sound.h"
#include "d_event.h"
/* /*
Do you know what an 'X Macro' is? Such a macro is called over each element of Do you know what an 'X Macro' is? Such a macro is called over each element of
@ -78,6 +79,13 @@ automatically.
X (LinedefExecute),\ X (LinedefExecute),\
X (ShouldJingleContinue),/* should jingle of the given music continue playing */\ X (ShouldJingleContinue),/* should jingle of the given music continue playing */\
#define HUD_HOOK_LIST(X) \
X (game),\
X (scores),/* emblems/multiplayer list */\
X (title),/* titlescreen */\
X (titlecard),\
X (intermission),\
/* /*
I chose to access the hook enums through a macro as well. This could provide I chose to access the hook enums through a macro as well. This could provide
a hint to lookup the macro's definition instead of the enum's definition. a hint to lookup the macro's definition instead of the enum's definition.
@ -88,18 +96,26 @@ grepped and found in the lists above.
#define MOBJ_HOOK(name) mobjhook_ ## name #define MOBJ_HOOK(name) mobjhook_ ## name
#define HOOK(name) hook_ ## name #define HOOK(name) hook_ ## name
#define HUD_HOOK(name) hudhook_ ## name
#define STRING_HOOK(name) stringhook_ ## name #define STRING_HOOK(name) stringhook_ ## name
enum { MOBJ_HOOK_LIST (MOBJ_HOOK) MOBJ_HOOK(MAX) }; #define ENUM(X) enum { X ## _LIST (X) X(MAX) }
enum { HOOK_LIST (HOOK) HOOK(MAX) };
enum { STRING_HOOK_LIST (STRING_HOOK) STRING_HOOK(MAX) }; ENUM (MOBJ_HOOK);
ENUM (HOOK);
ENUM (HUD_HOOK);
ENUM (STRING_HOOK);
#undef ENUM
/* dead simple, LUA_HOOK(GameQuit) */ /* dead simple, LUA_HOOK(GameQuit) */
#define LUA_HOOK(type) LUA_HookVoid(HOOK(type)) #define LUA_HOOK(type) LUA_HookVoid(HOOK(type))
#define LUA_HUDHOOK(type) LUA_HookHUD(HUD_HOOK(type))
extern boolean hook_cmd_running; extern boolean hook_cmd_running;
void LUA_HookVoid(int hook); void LUA_HookVoid(int hook);
void LUA_HookHUD(int hook);
int LUA_HookMobj(mobj_t *, int hook); int LUA_HookMobj(mobj_t *, int hook);
int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook);
@ -107,7 +123,7 @@ void LUA_HookInt(INT32 integer, int hook);
void LUA_HookBool(boolean value, int hook); void LUA_HookBool(boolean value, int hook);
int LUA_HookPlayer(player_t *, int hook); int LUA_HookPlayer(player_t *, int hook);
int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook);
int LUA_HookKey(INT32 keycode, int hook); // Hooks for key events int LUA_HookKey(event_t *event, int hook); // Hooks for key events
void LUA_HookThinkFrame(void); void LUA_HookThinkFrame(void);
int LUA_HookMobjLineCollide(mobj_t *, line_t *); int LUA_HookMobjLineCollide(mobj_t *, line_t *);
@ -115,6 +131,7 @@ int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher);
int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype);
int LUA_HookMobjMoveBlocked(mobj_t *, mobj_t *, line_t *);
int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd);
void LUA_HookLinedefExecute(line_t *, mobj_t *, sector_t *); void LUA_HookLinedefExecute(line_t *, mobj_t *, sector_t *);
int LUA_HookPlayerMsg(int source, int target, int flags, char *msg); int LUA_HookPlayerMsg(int source, int target, int flags, char *msg);

View file

@ -31,12 +31,15 @@
ABSTRACTION ABSTRACTION
========================================================================= */ ========================================================================= */
static const char * const mobjHookNames[] = { MOBJ_HOOK_LIST (TOSTR) NULL }; #define LIST(id, M) \
static const char * const hookNames[] = { HOOK_LIST (TOSTR) NULL }; static const char * const id [] = { M (TOSTR) NULL }
static const char * const stringHookNames[] = { LIST (mobjHookNames, MOBJ_HOOK_LIST);
STRING_HOOK_LIST (TOSTR) NULL LIST (hookNames, HOOK_LIST);
}; LIST (hudHookNames, HUD_HOOK_LIST);
LIST (stringHookNames, STRING_HOOK_LIST);
#undef LIST
typedef struct { typedef struct {
int numHooks; int numHooks;
@ -49,6 +52,7 @@ typedef struct {
} stringhook_t; } stringhook_t;
static hook_t hookIds[HOOK(MAX)]; static hook_t hookIds[HOOK(MAX)];
static hook_t hudHookIds[HUD_HOOK(MAX)];
static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)]; static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)];
// Lua tables are used to lookup string hook ids. // Lua tables are used to lookup string hook ids.
@ -56,6 +60,7 @@ static stringhook_t stringHooks[STRING_HOOK(MAX)];
// This will be indexed by hook id, the value of which fetches the registry. // This will be indexed by hook id, the value of which fetches the registry.
static int * hookRefs; static int * hookRefs;
static int nextid;
// After a hook errors once, don't print the error again. // After a hook errors once, don't print the error again.
static UINT8 * hooksErrored; static UINT8 * hooksErrored;
@ -104,13 +109,13 @@ static void get_table(lua_State *L)
lua_remove(L, -2); lua_remove(L, -2);
} }
static void add_hook_to_table(lua_State *L, int id, int n) static void add_hook_to_table(lua_State *L, int n)
{ {
lua_pushnumber(L, id); lua_pushnumber(L, nextid);
lua_rawseti(L, -2, n); lua_rawseti(L, -2, n);
} }
static void add_string_hook(lua_State *L, int type, int id) static void add_string_hook(lua_State *L, int type)
{ {
stringhook_t * hook = &stringHooks[type]; stringhook_t * hook = &stringHooks[type];
@ -146,33 +151,54 @@ static void add_string_hook(lua_State *L, int type, int id)
{ {
lua_pushstring(L, string); lua_pushstring(L, string);
get_table(L); get_table(L);
add_hook_to_table(L, id, 1 + lua_objlen(L, -1)); add_hook_to_table(L, 1 + lua_objlen(L, -1));
} }
else else
add_hook_to_table(L, id, ++hook->numGeneric); add_hook_to_table(L, ++hook->numGeneric);
} }
static void add_hook(hook_t *map, int id) static void add_hook(hook_t *map)
{ {
Z_Realloc(map->ids, (map->numHooks + 1) * sizeof *map->ids, Z_Realloc(map->ids, (map->numHooks + 1) * sizeof *map->ids,
PU_STATIC, &map->ids); PU_STATIC, &map->ids);
map->ids[map->numHooks++] = id; map->ids[map->numHooks++] = nextid;
} }
static void add_mobj_hook(lua_State *L, int hook_type, int id) static void add_mobj_hook(lua_State *L, int hook_type)
{ {
mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL); mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL);
luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t"); luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t");
add_hook(&mobjHookIds[mobj_type][hook_type], id); add_hook(&mobjHookIds[mobj_type][hook_type]);
}
static void add_hud_hook(lua_State *L, int idx)
{
add_hook(&hudHookIds[luaL_checkoption(L,
idx, "game", hudHookNames)]);
}
static void add_hook_ref(lua_State *L, int idx)
{
if (!(nextid & 7))
{
Z_Realloc(hooksErrored,
BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored,
PU_STATIC, &hooksErrored);
hooksErrored[nextid >> 3] = 0;
}
Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs);
// set the hook function in the registry.
lua_pushvalue(L, idx);
hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX);
} }
// Takes hook, function, and additional arguments (mobj type to act on, etc.) // Takes hook, function, and additional arguments (mobj type to act on, etc.)
static int lib_addHook(lua_State *L) static int lib_addHook(lua_State *L)
{ {
static int nextid;
const char * name; const char * name;
int type; int type;
@ -185,34 +211,26 @@ static int lib_addHook(lua_State *L)
/* this is a very special case */ /* this is a very special case */
if (( type = hook_in_list(name, stringHookNames) ) < STRING_HOOK(MAX)) if (( type = hook_in_list(name, stringHookNames) ) < STRING_HOOK(MAX))
{ {
add_string_hook(L, type, nextid); add_string_hook(L, type);
} }
else if (( type = hook_in_list(name, mobjHookNames) ) < MOBJ_HOOK(MAX)) else if (( type = hook_in_list(name, mobjHookNames) ) < MOBJ_HOOK(MAX))
{ {
add_mobj_hook(L, type, nextid); add_mobj_hook(L, type);
} }
else if (( type = hook_in_list(name, hookNames) ) < HOOK(MAX)) else if (( type = hook_in_list(name, hookNames) ) < HOOK(MAX))
{ {
add_hook(&hookIds[type], nextid); add_hook(&hookIds[type]);
}
else if (strcmp(name, "HUD") == 0)
{
add_hud_hook(L, 3);
} }
else else
{ {
return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name)); return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name));
} }
if (!(nextid & 7)) add_hook_ref(L, 2);/* the function */
{
Z_Realloc(hooksErrored,
BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored,
PU_STATIC, &hooksErrored);
hooksErrored[nextid >> 3] = 0;
}
Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs);
// set the hook function in the registry.
lua_pushvalue(L, 2);/* the function */
hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX);
return 0; return 0;
} }
@ -227,6 +245,23 @@ int LUA_HookLib(lua_State *L)
return 0; return 0;
} }
/* TODO: remove in next backwards incompatible release */
#if MODID == 18
int lib_hudadd(lua_State *L);/* yeah compiler */
int lib_hudadd(lua_State *L)
{
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
luaL_checktype(L, 1, LUA_TFUNCTION);
add_hud_hook(L, 2);
add_hook_ref(L, 1);
return 0;
}
#endif
typedef struct Hook_State Hook_State; typedef struct Hook_State Hook_State;
typedef void (*Hook_Callback)(Hook_State *); typedef void (*Hook_Callback)(Hook_State *);
@ -259,11 +294,16 @@ static void push_string(void)
lua_pushvalue(gL, SINDEX); lua_pushvalue(gL, SINDEX);
} }
static boolean start_hook_stack(void) static boolean begin_hook_values(Hook_State *hook)
{
hook->top = lua_gettop(gL);
return true;
}
static void start_hook_stack(void)
{ {
lua_settop(gL, 0); lua_settop(gL, 0);
push_error_handler(); push_error_handler();
return true;
} }
static boolean init_hook_type static boolean init_hook_type
@ -279,10 +319,11 @@ static boolean init_hook_type
if (nonzero) if (nonzero)
{ {
start_hook_stack();
hook->hook_type = hook_type; hook->hook_type = hook_type;
hook->mobj_type = mobj_type; hook->mobj_type = mobj_type;
hook->string = string; hook->string = string;
return start_hook_stack(); return begin_hook_values(hook);
} }
else else
return false; return false;
@ -323,7 +364,7 @@ static boolean prepare_string_hook
stringHooks[hook_type].ref)) stringHooks[hook_type].ref))
{ {
lua_pushstring(gL, string); lua_pushstring(gL, string);
return true; return begin_hook_values(hook);
} }
else else
return false; return false;
@ -332,12 +373,12 @@ static boolean prepare_string_hook
static void init_hook_call static void init_hook_call
( (
Hook_State * hook, Hook_State * hook,
int values,
int results, int results,
Hook_Callback results_handler Hook_Callback results_handler
){ ){
hook->top = lua_gettop(gL); const int top = lua_gettop(gL);
hook->values = values; hook->values = (top - hook->top);
hook->top = top;
hook->results = results; hook->results = results;
hook->results_handler = results_handler; hook->results_handler = results_handler;
} }
@ -447,13 +488,12 @@ static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type)
static int call_hooks static int call_hooks
( (
Hook_State * hook, Hook_State * hook,
int values,
int results, int results,
Hook_Callback results_handler Hook_Callback results_handler
){ ){
int calls = 0; int calls = 0;
init_hook_call(hook, values, results, results_handler); init_hook_call(hook, results, results_handler);
if (hook->string) if (hook->string)
{ {
@ -514,7 +554,7 @@ int LUA_HookMobj(mobj_t *mobj, int hook_type)
if (prepare_mobj_hook(&hook, false, hook_type, mobj->type)) if (prepare_mobj_hook(&hook, false, hook_type, mobj->type))
{ {
LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, mobj, META_MOBJ);
call_hooks(&hook, 1, 1, res_true); call_hooks(&hook, 1, res_true);
} }
return hook.status; return hook.status;
} }
@ -526,7 +566,7 @@ int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type)
{ {
LUA_PushUserdata(gL, t1, META_MOBJ); LUA_PushUserdata(gL, t1, META_MOBJ);
LUA_PushUserdata(gL, t2, META_MOBJ); LUA_PushUserdata(gL, t2, META_MOBJ);
call_hooks(&hook, 2, 1, res_force); call_hooks(&hook, 1, res_force);
} }
return hook.status; return hook.status;
} }
@ -535,7 +575,7 @@ void LUA_HookVoid(int type)
{ {
Hook_State hook; Hook_State hook;
if (prepare_hook(&hook, 0, type)) if (prepare_hook(&hook, 0, type))
call_hooks(&hook, 0, 0, res_none); call_hooks(&hook, 0, res_none);
} }
void LUA_HookInt(INT32 number, int hook_type) void LUA_HookInt(INT32 number, int hook_type)
@ -544,7 +584,7 @@ void LUA_HookInt(INT32 number, int hook_type)
if (prepare_hook(&hook, 0, hook_type)) if (prepare_hook(&hook, 0, hook_type))
{ {
lua_pushinteger(gL, number); lua_pushinteger(gL, number);
call_hooks(&hook, 1, 0, res_none); call_hooks(&hook, 0, res_none);
} }
} }
@ -554,7 +594,7 @@ void LUA_HookBool(boolean value, int hook_type)
if (prepare_hook(&hook, 0, hook_type)) if (prepare_hook(&hook, 0, hook_type))
{ {
lua_pushboolean(gL, value); lua_pushboolean(gL, value);
call_hooks(&hook, 1, 0, res_none); call_hooks(&hook, 0, res_none);
} }
} }
@ -564,7 +604,7 @@ int LUA_HookPlayer(player_t *player, int hook_type)
if (prepare_hook(&hook, false, hook_type)) if (prepare_hook(&hook, false, hook_type))
{ {
LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, player, META_PLAYER);
call_hooks(&hook, 1, 1, res_true); call_hooks(&hook, 1, res_true);
} }
return hook.status; return hook.status;
} }
@ -580,7 +620,7 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type)
if (hook_type == HOOK(PlayerCmd)) if (hook_type == HOOK(PlayerCmd))
hook_cmd_running = true; hook_cmd_running = true;
call_hooks(&hook, 2, 1, res_true); call_hooks(&hook, 1, res_true);
if (hook_type == HOOK(PlayerCmd)) if (hook_type == HOOK(PlayerCmd))
hook_cmd_running = false; hook_cmd_running = false;
@ -588,17 +628,35 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type)
return hook.status; return hook.status;
} }
int LUA_HookKey(INT32 keycode, int hook_type) int LUA_HookKey(event_t *event, int hook_type)
{ {
Hook_State hook; Hook_State hook;
if (prepare_hook(&hook, false, hook_type)) if (prepare_hook(&hook, false, hook_type))
{ {
lua_pushinteger(gL, keycode); LUA_PushUserdata(gL, event, META_KEYEVENT);
call_hooks(&hook, 1, 1, res_true); call_hooks(&hook, 1, res_true);
} }
return hook.status; return hook.status;
} }
void LUA_HookHUD(int hook_type)
{
const hook_t * map = &hudHookIds[hook_type];
Hook_State hook;
if (map->numHooks > 0)
{
start_hook_stack();
begin_hook_values(&hook);
LUA_SetHudHook(hook_type);
hud_running = true; // local hook
init_hook_call(&hook, 0, res_none);
call_mapped(&hook, map);
hud_running = false;
}
}
/* ========================================================================= /* =========================================================================
SPECIALIZED HOOKS SPECIALIZED HOOKS
========================================================================= */ ========================================================================= */
@ -618,7 +676,7 @@ void LUA_HookThinkFrame(void)
if (prepare_hook(&hook, 0, type)) if (prepare_hook(&hook, 0, type))
{ {
init_hook_call(&hook, 0, 0, res_none); init_hook_call(&hook, 0, res_none);
for (k = 0; k < map->numHooks; ++k) for (k = 0; k < map->numHooks; ++k)
{ {
@ -653,7 +711,7 @@ int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line)
{ {
LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, mobj, META_MOBJ);
LUA_PushUserdata(gL, line, META_LINE); LUA_PushUserdata(gL, line, META_LINE);
call_hooks(&hook, 2, 1, res_force); call_hooks(&hook, 1, res_force);
} }
return hook.status; return hook.status;
} }
@ -665,7 +723,7 @@ int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher)
{ {
LUA_PushUserdata(gL, special, META_MOBJ); LUA_PushUserdata(gL, special, META_MOBJ);
LUA_PushUserdata(gL, toucher, META_MOBJ); LUA_PushUserdata(gL, toucher, META_MOBJ);
call_hooks(&hook, 2, 1, res_true); call_hooks(&hook, 1, res_true);
} }
return hook.status; return hook.status;
} }
@ -678,7 +736,6 @@ static int damage_hook
INT32 damage, INT32 damage,
UINT8 damagetype, UINT8 damagetype,
int hook_type, int hook_type,
int values,
Hook_Callback results_handler Hook_Callback results_handler
){ ){
Hook_State hook; Hook_State hook;
@ -687,10 +744,10 @@ static int damage_hook
LUA_PushUserdata(gL, target, META_MOBJ); LUA_PushUserdata(gL, target, META_MOBJ);
LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ);
if (values == 5) if (hook_type != MOBJ_HOOK(MobjDeath))
lua_pushinteger(gL, damage); lua_pushinteger(gL, damage);
lua_pushinteger(gL, damagetype); lua_pushinteger(gL, damagetype);
call_hooks(&hook, values, 1, results_handler); call_hooks(&hook, 1, results_handler);
} }
return hook.status; return hook.status;
} }
@ -698,19 +755,32 @@ static int damage_hook
int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
{ {
return damage_hook(target, inflictor, source, damage, damagetype, return damage_hook(target, inflictor, source, damage, damagetype,
MOBJ_HOOK(ShouldDamage), 5, res_force); MOBJ_HOOK(ShouldDamage), res_force);
} }
int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
{ {
return damage_hook(target, inflictor, source, damage, damagetype, return damage_hook(target, inflictor, source, damage, damagetype,
MOBJ_HOOK(MobjDamage), 5, res_true); MOBJ_HOOK(MobjDamage), res_true);
} }
int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype)
{ {
return damage_hook(target, inflictor, source, 0, damagetype, return damage_hook(target, inflictor, source, 0, damagetype,
MOBJ_HOOK(MobjDeath), 4, res_true); MOBJ_HOOK(MobjDeath), res_true);
}
int LUA_HookMobjMoveBlocked(mobj_t *t1, mobj_t *t2, line_t *line)
{
Hook_State hook;
if (prepare_mobj_hook(&hook, 0, MOBJ_HOOK(MobjMoveBlocked), t1->type))
{
LUA_PushUserdata(gL, t1, META_MOBJ);
LUA_PushUserdata(gL, t2, META_MOBJ);
LUA_PushUserdata(gL, line, META_LINE);
call_hooks(&hook, 1, res_true);
}
return hook.status;
} }
typedef struct { typedef struct {
@ -783,7 +853,7 @@ int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
hook.userdata = &botai; hook.userdata = &botai;
call_hooks(&hook, 2, 8, res_botai); call_hooks(&hook, 8, res_botai);
} }
return hook.status; return hook.status;
@ -798,7 +868,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
LUA_PushUserdata(gL, line, META_LINE); LUA_PushUserdata(gL, line, META_LINE);
LUA_PushUserdata(gL, mo, META_MOBJ); LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_PushUserdata(gL, sector, META_SECTOR); LUA_PushUserdata(gL, sector, META_SECTOR);
ps_lua_mobjhooks += call_hooks(&hook, 3, 0, res_none); ps_lua_mobjhooks += call_hooks(&hook, 0, res_none);
} }
} }
@ -822,7 +892,7 @@ int LUA_HookPlayerMsg(int source, int target, int flags, char *msg)
LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
} }
lua_pushstring(gL, msg); // msg lua_pushstring(gL, msg); // msg
call_hooks(&hook, 4, 1, res_true); call_hooks(&hook, 1, res_true);
} }
return hook.status; return hook.status;
} }
@ -836,7 +906,7 @@ int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 d
LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ);
lua_pushinteger(gL, damagetype); lua_pushinteger(gL, damagetype);
call_hooks(&hook, 4, 1, res_true); call_hooks(&hook, 1, res_true);
} }
return hook.status; return hook.status;
} }
@ -855,12 +925,14 @@ void LUA_HookNetArchive(lua_CFunction archFunc)
push_error_handler(); push_error_handler();
lua_insert(gL, EINDEX); lua_insert(gL, EINDEX);
begin_hook_values(&hook);
// tables becomes an upvalue of archFunc // tables becomes an upvalue of archFunc
lua_pushvalue(gL, -1); lua_pushvalue(gL, -1);
lua_pushcclosure(gL, archFunc, 1); lua_pushcclosure(gL, archFunc, 1);
// stack: tables, archFunc // stack: tables, archFunc
init_hook_call(&hook, 1, 0, res_none); init_hook_call(&hook, 0, res_none);
call_mapped(&hook, map); call_mapped(&hook, map);
lua_pop(gL, 1); // pop archFunc lua_pop(gL, 1); // pop archFunc
@ -876,7 +948,7 @@ int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing)
{ {
LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, mobj, META_MOBJ);
LUA_PushUserdata(gL, mthing, META_MAPTHING); LUA_PushUserdata(gL, mthing, META_MAPTHING);
call_hooks(&hook, 2, 1, res_true); call_hooks(&hook, 1, res_true);
} }
return hook.status; return hook.status;
} }
@ -888,7 +960,7 @@ int LUA_HookFollowMobj(player_t *player, mobj_t *mobj)
{ {
LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, mobj, META_MOBJ);
call_hooks(&hook, 2, 1, res_true); call_hooks(&hook, 1, res_true);
} }
return hook.status; return hook.status;
} }
@ -900,7 +972,7 @@ int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj)
{ {
LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, mobj, META_MOBJ);
call_hooks(&hook, 2, 1, res_force); call_hooks(&hook, 1, res_force);
} }
return hook.status; return hook.status;
} }
@ -912,7 +984,7 @@ void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason)
{ {
LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit
lua_pushinteger(gL, reason); // Reason for quitting lua_pushinteger(gL, reason); // Reason for quitting
call_hooks(&hook, 2, 0, res_none); call_hooks(&hook, 0, res_none);
} }
} }
@ -926,7 +998,7 @@ int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, bo
lua_pushboolean(gL, fromspectators); lua_pushboolean(gL, fromspectators);
lua_pushboolean(gL, tryingautobalance); lua_pushboolean(gL, tryingautobalance);
lua_pushboolean(gL, tryingscramble); lua_pushboolean(gL, tryingscramble);
call_hooks(&hook, 5, 1, res_false); call_hooks(&hook, 1, res_false);
} }
return hook.status; return hook.status;
} }
@ -941,7 +1013,7 @@ int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolea
lua_pushboolean(gL, forced); lua_pushboolean(gL, forced);
hud_running = true; // local hook hud_running = true; // local hook
call_hooks(&hook, 3, 1, res_force); call_hooks(&hook, 1, res_force);
hud_running = false; hud_running = false;
} }
return hook.status; return hook.status;
@ -956,7 +1028,7 @@ int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend)
LUA_PushUserdata(gL, seenfriend, META_PLAYER); LUA_PushUserdata(gL, seenfriend, META_PLAYER);
hud_running = true; // local hook hud_running = true; // local hook
call_hooks(&hook, 2, 1, res_false); call_hooks(&hook, 1, res_false);
hud_running = false; hud_running = false;
} }
return hook.status; return hook.status;
@ -972,7 +1044,7 @@ int LUA_HookShouldJingleContinue(player_t *player, const char *musname)
push_string(); push_string();
hud_running = true; // local hook hud_running = true; // local hook
call_hooks(&hook, 2, 1, res_true); call_hooks(&hook, 1, res_true);
hud_running = false; hud_running = false;
} }
return hook.status; return hook.status;
@ -1038,7 +1110,8 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param)
if (prepare_hook(&hook, false, type)) if (prepare_hook(&hook, false, type))
{ {
init_hook_call(&hook, 7, 6, res_musicchange); init_hook_call(&hook, 6, res_musicchange);
hook.values = 7;/* values pushed later */
hook.userdata = param; hook.userdata = param;
lua_pushstring(gL, oldname);/* the only constant value */ lua_pushstring(gL, oldname);/* the only constant value */
@ -1084,7 +1157,7 @@ fixed_t LUA_HookPlayerHeight(player_t *player)
if (prepare_hook(&hook, -1, HOOK(PlayerHeight))) if (prepare_hook(&hook, -1, HOOK(PlayerHeight)))
{ {
LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, player, META_PLAYER);
call_hooks(&hook, 1, 1, res_playerheight); call_hooks(&hook, 1, res_playerheight);
} }
return hook.status; return hook.status;
} }
@ -1095,7 +1168,7 @@ int LUA_HookPlayerCanEnterSpinGaps(player_t *player)
if (prepare_hook(&hook, 0, HOOK(PlayerCanEnterSpinGaps))) if (prepare_hook(&hook, 0, HOOK(PlayerCanEnterSpinGaps)))
{ {
LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, player, META_PLAYER);
call_hooks(&hook, 1, 1, res_force); call_hooks(&hook, 1, res_force);
} }
return hook.status; return hook.status;
} }

View file

@ -47,8 +47,4 @@ extern boolean hud_running;
boolean LUA_HudEnabled(enum hud option); boolean LUA_HudEnabled(enum hud option);
void LUAh_GameHUD(player_t *stplyr); void LUA_SetHudHook(int hook);
void LUAh_ScoresHUD(void);
void LUAh_TitleHUD(void);
void LUAh_TitleCardHUD(player_t *stplayr);
void LUAh_IntermissionHUD(boolean failedstage);

View file

@ -23,18 +23,18 @@
#include "v_video.h" #include "v_video.h"
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
#include "y_inter.h"
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" #include "lua_hud.h"
#include "lua_hook.h"
#define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!"); #define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
boolean hud_running = false; boolean hud_running = false;
static UINT8 hud_enabled[(hud_MAX/8)+1]; static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field
// must match enum hud in lua_hud.h // must match enum hud in lua_hud.h
static const char *const hud_disable_options[] = { static const char *const hud_disable_options[] = {
"stagetitle", "stagetitle",
@ -95,21 +95,6 @@ static const char *const patch_opt[] = {
"topoffset", "topoffset",
NULL}; NULL};
enum hudhook {
hudhook_game = 0,
hudhook_scores,
hudhook_intermission,
hudhook_title,
hudhook_titlecard
};
static const char *const hudhook_opt[] = {
"game",
"scores",
"intermission",
"title",
"titlecard",
NULL};
// alignment types for v.drawString // alignment types for v.drawString
enum align { enum align {
align_left = 0, align_left = 0,
@ -280,7 +265,7 @@ static int hudinfo_num(lua_State *L)
static int colormap_get(lua_State *L) static int colormap_get(lua_State *L)
{ {
const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
UINT32 i = luaL_checkinteger(L, 2); UINT32 i = luaL_checkinteger(L, 2);
if (i >= 256) if (i >= 256)
return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255); return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
@ -288,6 +273,23 @@ static int colormap_get(lua_State *L)
return 1; return 1;
} }
static int colormap_set(lua_State *L)
{
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
UINT32 i = luaL_checkinteger(L, 2);
if (i >= 256)
return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
colormap[i] = (UINT8)luaL_checkinteger(L, 3);
return 0;
}
static int colormap_free(lua_State *L)
{
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
Z_Free(colormap);
return 0;
}
static int patch_get(lua_State *L) static int patch_get(lua_State *L)
{ {
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
@ -384,6 +386,74 @@ static int camera_get(lua_State *L)
return 1; return 1;
} }
static int camera_set(lua_State *L)
{
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt);
I_Assert(cam != NULL);
switch(field)
{
case camera_subsector:
case camera_floorz:
case camera_ceilingz:
case camera_x:
case camera_y:
return luaL_error(L, LUA_QL("camera_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_TryCameraMove") " or " LUA_QL("P_TeleportCameraMove") " instead.", camera_opt[field]);
case camera_chase: {
INT32 chase = luaL_checkboolean(L, 3);
if (cam == &camera)
CV_SetValue(&cv_chasecam, chase);
else if (cam == &camera2)
CV_SetValue(&cv_chasecam2, chase);
else // ??? this should never happen, but ok
cam->chase = chase;
break;
}
case camera_aiming:
cam->aiming = luaL_checkangle(L, 3);
break;
case camera_z:
cam->z = luaL_checkfixed(L, 3);
P_CheckCameraPosition(cam->x, cam->y, cam);
cam->floorz = tmfloorz;
cam->ceilingz = tmceilingz;
break;
case camera_angle:
cam->angle = luaL_checkangle(L, 3);
break;
case camera_radius:
cam->radius = luaL_checkfixed(L, 3);
if (cam->radius < 0)
cam->radius = 0;
P_CheckCameraPosition(cam->x, cam->y, cam);
cam->floorz = tmfloorz;
cam->ceilingz = tmceilingz;
break;
case camera_height:
cam->height = luaL_checkfixed(L, 3);
if (cam->height < 0)
cam->height = 0;
P_CheckCameraPosition(cam->x, cam->y, cam);
cam->floorz = tmfloorz;
cam->ceilingz = tmceilingz;
break;
case camera_momx:
cam->momx = luaL_checkfixed(L, 3);
break;
case camera_momy:
cam->momy = luaL_checkfixed(L, 3);
break;
case camera_momz:
cam->momz = luaL_checkfixed(L, 3);
break;
default:
return luaL_error(L, LUA_QL("camera_t") " has no field named " LUA_QS, camera_opt[field]);
}
return 0;
}
// //
// lib_draw // lib_draw
// //
@ -663,6 +733,45 @@ static int libd_drawStretched(lua_State *L)
return 0; return 0;
} }
static int libd_drawCropped(lua_State *L)
{
fixed_t x, y, hscale, vscale, sx, sy, w, h;
INT32 flags;
patch_t *patch;
const UINT8 *colormap = NULL;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
hscale = luaL_checkinteger(L, 3);
if (hscale < 0)
return luaL_error(L, "negative horizontal scale");
vscale = luaL_checkinteger(L, 4);
if (vscale < 0)
return luaL_error(L, "negative vertical scale");
patch = *((patch_t **)luaL_checkudata(L, 5, META_PATCH));
flags = luaL_checkinteger(L, 6);
if (!lua_isnoneornil(L, 7))
colormap = *((UINT8 **)luaL_checkudata(L, 7, META_COLORMAP));
sx = luaL_checkinteger(L, 8);
if (sx < 0) // Don't crash. Now, we could do "x-=sx*FRACUNIT; sx=0;" here...
return luaL_error(L, "negative crop sx");
sy = luaL_checkinteger(L, 9);
if (sy < 0) // ...but it's more truthful to just deny it, as negative values would crash
return luaL_error(L, "negative crop sy");
w = luaL_checkinteger(L, 10);
if (w < 0) // Again, don't crash
return luaL_error(L, "negative crop w");
h = luaL_checkinteger(L, 11);
if (h < 0)
return luaL_error(L, "negative crop h");
flags &= ~V_PARAMMASK; // Don't let crashes happen.
V_DrawCroppedPatch(x, y, hscale, vscale, flags, patch, colormap, sx, sy, w, h);
return 0;
}
static int libd_drawNum(lua_State *L) static int libd_drawNum(lua_State *L)
{ {
INT32 x, y, flags, num; INT32 x, y, flags, num;
@ -948,7 +1057,7 @@ static int libd_getColormap(lua_State *L)
// all was successful above, now we generate the colormap at last! // all was successful above, now we generate the colormap at last!
colormap = R_GetTranslationColormap(skinnum, color, GTC_CACHE); colormap = R_GetTranslationColormap(skinnum, color, 0);
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use! LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1; return 1;
} }
@ -957,10 +1066,14 @@ static int libd_getStringColormap(lua_State *L)
{ {
INT32 flags = luaL_checkinteger(L, 1); INT32 flags = luaL_checkinteger(L, 1);
UINT8* colormap = NULL; UINT8* colormap = NULL;
UINT8* lua_colormap = NULL;
HUDONLY HUDONLY
colormap = V_GetStringColormap(flags & V_CHARCOLORMASK); colormap = V_GetStringColormap(flags & V_CHARCOLORMASK);
if (colormap) { if (colormap) {
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use! lua_colormap = Z_Malloc(256 * sizeof(UINT8), PU_LUA, NULL);
memcpy(lua_colormap, colormap, 256 * sizeof(UINT8));
LUA_PushUserdata(L, lua_colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1; return 1;
} }
return 0; return 0;
@ -1121,6 +1234,7 @@ static luaL_Reg lib_draw[] = {
{"draw", libd_draw}, {"draw", libd_draw},
{"drawScaled", libd_drawScaled}, {"drawScaled", libd_drawScaled},
{"drawStretched", libd_drawStretched}, {"drawStretched", libd_drawStretched},
{"drawCropped", libd_drawCropped},
{"drawNum", libd_drawNum}, {"drawNum", libd_drawNum},
{"drawPaddedNum", libd_drawPaddedNum}, {"drawPaddedNum", libd_drawPaddedNum},
{"drawFill", libd_drawFill}, {"drawFill", libd_drawFill},
@ -1152,6 +1266,8 @@ static luaL_Reg lib_draw[] = {
{NULL, NULL} {NULL, NULL}
}; };
static int lib_draw_ref;
// //
// lib_hud // lib_hud
// //
@ -1186,28 +1302,7 @@ static int lib_hudenabled(lua_State *L)
// add a HUD element for rendering // add a HUD element for rendering
static int lib_hudadd(lua_State *L) extern int lib_hudadd(lua_State *L);
{
enum hudhook field;
luaL_checktype(L, 1, LUA_TFUNCTION);
field = luaL_checkoption(L, 2, "game", hudhook_opt);
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
lua_getfield(L, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(L, -1));
lua_rawgeti(L, -1, field+2); // HUD[2+]
I_Assert(lua_istable(L, -1));
lua_remove(L, -2);
lua_pushvalue(L, 1);
lua_rawseti(L, -2, (int)(lua_objlen(L, -2) + 1));
hudAvailable |= 1<<field;
return 0;
}
static luaL_Reg lib_hud[] = { static luaL_Reg lib_hud[] = {
{"enable", lib_hudenable}, {"enable", lib_hudenable},
@ -1225,26 +1320,9 @@ int LUA_HudLib(lua_State *L)
{ {
memset(hud_enabled, 0xff, (hud_MAX/8)+1); memset(hud_enabled, 0xff, (hud_MAX/8)+1);
lua_newtable(L); // HUD registry table
lua_newtable(L); lua_newtable(L);
luaL_register(L, NULL, lib_draw); luaL_register(L, NULL, lib_draw);
lua_rawseti(L, -2, 1); // HUD[1] = lib_draw lib_draw_ref = luaL_ref(L, LUA_REGISTRYINDEX);
lua_newtable(L);
lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 3); // HUD[3] = scores rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 4); // HUD[4] = intermission rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 5); // HUD[5] = title rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 6); // HUD[6] = title card rendering functions array
lua_setfield(L, LUA_REGISTRYINDEX, "HUD");
luaL_newmetatable(L, META_HUDINFO); luaL_newmetatable(L, META_HUDINFO);
lua_pushcfunction(L, hudinfo_get); lua_pushcfunction(L, hudinfo_get);
@ -1270,6 +1348,12 @@ int LUA_HudLib(lua_State *L)
luaL_newmetatable(L, META_COLORMAP); luaL_newmetatable(L, META_COLORMAP);
lua_pushcfunction(L, colormap_get); lua_pushcfunction(L, colormap_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");
lua_pushcfunction(L, colormap_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, colormap_free);
lua_setfield(L, -2, "__gc");
lua_pop(L,1); lua_pop(L,1);
luaL_newmetatable(L, META_PATCH); luaL_newmetatable(L, META_PATCH);
@ -1283,6 +1367,9 @@ int LUA_HudLib(lua_State *L)
luaL_newmetatable(L, META_CAMERA); luaL_newmetatable(L, META_CAMERA);
lua_pushcfunction(L, camera_get); lua_pushcfunction(L, camera_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");
lua_pushcfunction(L, camera_set);
lua_setfield(L, -2, "__newindex");
lua_pop(L,1); lua_pop(L,1);
luaL_register(L, "hud", lib_hud); luaL_register(L, "hud", lib_hud);
@ -1296,160 +1383,29 @@ boolean LUA_HudEnabled(enum hud option)
return false; return false;
} }
// Hook for HUD rendering void LUA_SetHudHook(int hook)
void LUAh_GameHUD(player_t *stplayr)
{ {
if (!gL || !(hudAvailable & (1<<hudhook_game))) lua_getref(gL, lib_draw_ref);
return;
hud_running = true; switch (hook)
lua_settop(gL, 0); {
case HUD_HOOK(game): {
camera_t *cam = (splitscreen && stplyr ==
&players[secondarydisplayplayer])
? &camera2 : &camera;
lua_pushcfunction(gL, LUA_GetErrorMessage); LUA_PushUserdata(gL, stplyr, META_PLAYER);
LUA_PushUserdata(gL, cam, META_CAMERA);
} break;
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); case HUD_HOOK(titlecard):
I_Assert(lua_istable(gL, -1)); LUA_PushUserdata(gL, stplyr, META_PLAYER);
lua_rawgeti(gL, -1, 2+hudhook_game); // HUD[2] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplayr, META_PLAYER);
if (splitscreen && stplayr == &players[secondarydisplayplayer])
LUA_PushUserdata(gL, &camera2, META_CAMERA);
else
LUA_PushUserdata(gL, &camera, META_CAMERA);
lua_pushnil(gL);
while (lua_next(gL, -5) != 0) {
lua_pushvalue(gL, -5); // graphics library (HUD[1])
lua_pushvalue(gL, -5); // stplayr
lua_pushvalue(gL, -5); // camera
LUA_Call(gL, 3, 0, 1);
}
lua_settop(gL, 0);
hud_running = false;
}
void LUAh_ScoresHUD(void)
{
if (!gL || !(hudAvailable & (1<<hudhook_scores)))
return;
hud_running = true;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_scores); // HUD[3] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1, 0, 1);
}
lua_settop(gL, 0);
hud_running = false;
}
void LUAh_TitleHUD(void)
{
if (!gL || !(hudAvailable & (1<<hudhook_title)))
return;
hud_running = true;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_title); // HUD[5] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1, 0, 1);
}
lua_settop(gL, 0);
hud_running = false;
}
void LUAh_TitleCardHUD(player_t *stplayr)
{
if (!gL || !(hudAvailable & (1<<hudhook_titlecard)))
return;
hud_running = true;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_titlecard); // HUD[6] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplayr, META_PLAYER);
lua_pushinteger(gL, lt_ticker); lua_pushinteger(gL, lt_ticker);
lua_pushinteger(gL, (lt_endtime + TICRATE)); lua_pushinteger(gL, (lt_endtime + TICRATE));
lua_pushnil(gL); break;
while (lua_next(gL, -6) != 0) { case HUD_HOOK(intermission):
lua_pushvalue(gL, -6); // graphics library (HUD[1]) lua_pushboolean(gL, intertype == int_spec &&
lua_pushvalue(gL, -6); // stplayr stagefailed);
lua_pushvalue(gL, -6); // lt_ticker
lua_pushvalue(gL, -6); // lt_endtime
LUA_Call(gL, 4, 0, 1);
} }
lua_settop(gL, 0);
hud_running = false;
}
void LUAh_IntermissionHUD(boolean failedstage)
{
if (!gL || !(hudAvailable & (1<<hudhook_intermission)))
return;
hud_running = true;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_intermission); // HUD[4] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushboolean(gL, failedstage); // stagefailed
lua_pushnil(gL);
while (lua_next(gL, -4) != 0) {
lua_pushvalue(gL, -4); // graphics library (HUD[1])
lua_pushvalue(gL, -4); // stagefailed
LUA_Call(gL, 2, 0, 1);
}
lua_settop(gL, 0);
hud_running = false;
} }

View file

@ -19,6 +19,8 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
boolean mousegrabbedbylua = true;
/////////////// ///////////////
// FUNCTIONS // // FUNCTIONS //
/////////////// ///////////////
@ -26,8 +28,8 @@
static int lib_gameControlDown(lua_State *L) static int lib_gameControlDown(lua_State *L)
{ {
int i = luaL_checkinteger(L, 1); int i = luaL_checkinteger(L, 1);
if (i < 0 || i >= num_gamecontrols) if (i < 0 || i >= NUM_GAMECONTROLS)
return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
lua_pushinteger(L, PLAYER1INPUTDOWN(i)); lua_pushinteger(L, PLAYER1INPUTDOWN(i));
return 1; return 1;
} }
@ -35,8 +37,8 @@ static int lib_gameControlDown(lua_State *L)
static int lib_gameControl2Down(lua_State *L) static int lib_gameControl2Down(lua_State *L)
{ {
int i = luaL_checkinteger(L, 1); int i = luaL_checkinteger(L, 1);
if (i < 0 || i >= num_gamecontrols) if (i < 0 || i >= NUM_GAMECONTROLS)
return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
lua_pushinteger(L, PLAYER2INPUTDOWN(i)); lua_pushinteger(L, PLAYER2INPUTDOWN(i));
return 1; return 1;
} }
@ -44,8 +46,8 @@ static int lib_gameControl2Down(lua_State *L)
static int lib_gameControlToKeyNum(lua_State *L) static int lib_gameControlToKeyNum(lua_State *L)
{ {
int i = luaL_checkinteger(L, 1); int i = luaL_checkinteger(L, 1);
if (i < 0 || i >= num_gamecontrols) if (i < 0 || i >= NUM_GAMECONTROLS)
return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
lua_pushinteger(L, gamecontrol[i][0]); lua_pushinteger(L, gamecontrol[i][0]);
lua_pushinteger(L, gamecontrol[i][1]); lua_pushinteger(L, gamecontrol[i][1]);
return 2; return 2;
@ -54,8 +56,8 @@ static int lib_gameControlToKeyNum(lua_State *L)
static int lib_gameControl2ToKeyNum(lua_State *L) static int lib_gameControl2ToKeyNum(lua_State *L)
{ {
int i = luaL_checkinteger(L, 1); int i = luaL_checkinteger(L, 1);
if (i < 0 || i >= num_gamecontrols) if (i < 0 || i >= NUM_GAMECONTROLS)
return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); return luaL_error(L, "GC_* constant %d out of range (0 - %d)", i, NUM_GAMECONTROLS-1);
lua_pushinteger(L, gamecontrolbis[i][0]); lua_pushinteger(L, gamecontrolbis[i][0]);
lua_pushinteger(L, gamecontrolbis[i][1]); lua_pushinteger(L, gamecontrolbis[i][1]);
return 2; return 2;
@ -75,17 +77,17 @@ static int lib_joy2Axis(lua_State *L)
return 1; return 1;
} }
static int lib_keyNumToString(lua_State *L) static int lib_keyNumToName(lua_State *L)
{ {
int i = luaL_checkinteger(L, 1); int i = luaL_checkinteger(L, 1);
lua_pushstring(L, G_KeyNumToString(i)); lua_pushstring(L, G_KeyNumToName(i));
return 1; return 1;
} }
static int lib_keyStringToNum(lua_State *L) static int lib_keyNameToNum(lua_State *L)
{ {
const char *str = luaL_checkstring(L, 1); const char *str = luaL_checkstring(L, 1);
lua_pushinteger(L, G_KeyStringToNum(str)); lua_pushinteger(L, G_KeyNameToNum(str));
return 1; return 1;
} }
@ -106,14 +108,14 @@ static int lib_shiftKeyNum(lua_State *L)
static int lib_getMouseGrab(lua_State *L) static int lib_getMouseGrab(lua_State *L)
{ {
lua_pushboolean(L, I_GetMouseGrab()); lua_pushboolean(L, mousegrabbedbylua);
return 1; return 1;
} }
static int lib_setMouseGrab(lua_State *L) static int lib_setMouseGrab(lua_State *L)
{ {
boolean grab = luaL_checkboolean(L, 1); mousegrabbedbylua = luaL_checkboolean(L, 1);
I_SetMouseGrab(grab); I_UpdateMouseGrab();
return 0; return 0;
} }
@ -127,19 +129,19 @@ static int lib_getCursorPosition(lua_State *L)
} }
static luaL_Reg lib[] = { static luaL_Reg lib[] = {
{"G_GameControlDown", lib_gameControlDown}, {"gameControlDown", lib_gameControlDown},
{"G_GameControl2Down", lib_gameControl2Down}, {"gameControl2Down", lib_gameControl2Down},
{"G_GameControlToKeyNum", lib_gameControlToKeyNum}, {"gameControlToKeyNum", lib_gameControlToKeyNum},
{"G_GameControl2ToKeyNum", lib_gameControl2ToKeyNum}, {"gameControl2ToKeyNum", lib_gameControl2ToKeyNum},
{"G_JoyAxis", lib_joyAxis}, {"joyAxis", lib_joyAxis},
{"G_Joy2Axis", lib_joy2Axis}, {"joy2Axis", lib_joy2Axis},
{"G_KeyNumToString", lib_keyNumToString}, {"keyNumToName", lib_keyNumToName},
{"G_KeyStringToNum", lib_keyStringToNum}, {"keyNameToNum", lib_keyNameToNum},
{"HU_KeyNumPrintable", lib_keyNumPrintable}, {"keyNumPrintable", lib_keyNumPrintable},
{"HU_ShiftKeyNum", lib_shiftKeyNum}, {"shiftKeyNum", lib_shiftKeyNum},
{"I_GetMouseGrab", lib_getMouseGrab}, {"getMouseGrab", lib_getMouseGrab},
{"I_SetMouseGrab", lib_setMouseGrab}, {"setMouseGrab", lib_setMouseGrab},
{"I_GetCursorPosition", lib_getCursorPosition}, {"getCursorPosition", lib_getCursorPosition},
{NULL, NULL} {NULL, NULL}
}; };
@ -172,6 +174,29 @@ static int lib_lenGameKeyDown(lua_State *L)
return 1; return 1;
} }
///////////////
// KEY EVENT //
///////////////
static int keyevent_get(lua_State *L)
{
event_t *event = *((event_t **)luaL_checkudata(L, 1, META_KEYEVENT));
const char *field = luaL_checkstring(L, 2);
I_Assert(event != NULL);
if (fastcmp(field,"name"))
lua_pushstring(L, G_KeyNumToName(event->key));
else if (fastcmp(field,"num"))
lua_pushinteger(L, event->key);
else if (fastcmp(field,"repeated"))
lua_pushboolean(L, event->repeated);
else
return luaL_error(L, "keyevent_t has no field named %s", field);
return 1;
}
/////////// ///////////
// MOUSE // // MOUSE //
/////////// ///////////
@ -227,6 +252,11 @@ int LUA_InputLib(lua_State *L)
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_setglobal(L, "gamekeydown"); lua_setglobal(L, "gamekeydown");
luaL_newmetatable(L, META_KEYEVENT);
lua_pushcfunction(L, keyevent_get);
lua_setfield(L, -2, "__index");
lua_pop(L, 1);
luaL_newmetatable(L, META_MOUSE); luaL_newmetatable(L, META_MOUSE);
lua_pushcfunction(L, mouse_get); lua_pushcfunction(L, mouse_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");
@ -235,8 +265,6 @@ int LUA_InputLib(lua_State *L)
lua_setfield(L, -2, "__len"); lua_setfield(L, -2, "__len");
lua_pop(L, 1); lua_pop(L, 1);
// Set global functions luaL_register(L, "input", lib);
lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_register(L, NULL, lib);
return 0; return 0;
} }

View file

@ -12,6 +12,8 @@
extern lua_State *gL; extern lua_State *gL;
extern boolean mousegrabbedbylua;
#define MUTABLE_TAGS #define MUTABLE_TAGS
#define LREG_VALID "VALID_USERDATA" #define LREG_VALID "VALID_USERDATA"
@ -88,6 +90,7 @@ extern lua_State *gL;
#define META_LUABANKS "LUABANKS[]*" #define META_LUABANKS "LUABANKS[]*"
#define META_KEYEVENT "KEYEVENT_T*"
#define META_MOUSE "MOUSE_T*" #define META_MOUSE "MOUSE_T*"
boolean luaL_checkboolean(lua_State *L, int narg); boolean luaL_checkboolean(lua_State *L, int narg);

View file

@ -393,6 +393,14 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word, "mouse2")) { } else if (fastcmp(word, "mouse2")) {
LUA_PushUserdata(L, &mouse2, META_MOUSE); LUA_PushUserdata(L, &mouse2, META_MOUSE);
return 1; return 1;
} else if (fastcmp(word, "camera")) {
LUA_PushUserdata(L, &camera, META_CAMERA);
return 1;
} else if (fastcmp(word, "camera2")) {
if (!splitscreen)
return 0;
LUA_PushUserdata(L, &camera2, META_CAMERA);
return 1;
} }
return 0; return 0;
} }
@ -1384,21 +1392,13 @@ static void ArchiveTables(void)
// Write key // Write key
e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise) if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise)
{ CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i);
lua_pushvalue(gL, -2);
CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -1), luaL_typename(gL, -1), i);
lua_pop(gL, 1);
}
// Write value // Write value
e = ArchiveValue(TABLESINDEX, -1); e = ArchiveValue(TABLESINDEX, -1);
if (e == 1) if (e == 1)
n++; // the table contained a new table we'll have to archive. :( n++; // the table contained a new table we'll have to archive. :(
else if (e == 2) // invalid value type else if (e == 2) // invalid value type
{ CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -2), luaL_typename(gL, -1));
lua_pushvalue(gL, -2);
CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -1), luaL_typename(gL, -1));
lua_pop(gL, 1);
}
lua_pop(gL, 1); lua_pop(gL, 1);
} }

View file

@ -203,11 +203,11 @@ boolean cht_Responder(event_t *ev)
if (ev->type != ev_keydown) if (ev->type != ev_keydown)
return false; return false;
if (ev->data1 > 0xFF) if (ev->key > 0xFF)
{ {
// map some fake (joy) inputs into keys // map some fake (joy) inputs into keys
// map joy inputs into keys // map joy inputs into keys
switch (ev->data1) switch (ev->key)
{ {
case KEY_JOY1: case KEY_JOY1:
case KEY_JOY1 + 2: case KEY_JOY1 + 2:
@ -231,7 +231,7 @@ boolean cht_Responder(event_t *ev)
} }
} }
else else
ch = (UINT8)ev->data1; ch = (UINT8)ev->key;
ret += cht_CheckCheat(&cheat_ultimate, (char)ch); ret += cht_CheckCheat(&cheat_ultimate, (char)ch);
ret += cht_CheckCheat(&cheat_ultimate_joy, (char)ch); ret += cht_CheckCheat(&cheat_ultimate_joy, (char)ch);

View file

@ -1106,55 +1106,55 @@ static menuitem_t OP_ChangeControlsMenu[] =
{ {
{IT_HEADER, NULL, "Movement", NULL, 0}, {IT_HEADER, NULL, "Movement", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Move Forward", M_ChangeControl, gc_forward }, {IT_CALL | IT_STRING2, NULL, "Move Forward", M_ChangeControl, GC_FORWARD },
{IT_CALL | IT_STRING2, NULL, "Move Backward", M_ChangeControl, gc_backward }, {IT_CALL | IT_STRING2, NULL, "Move Backward", M_ChangeControl, GC_BACKWARD },
{IT_CALL | IT_STRING2, NULL, "Move Left", M_ChangeControl, gc_strafeleft }, {IT_CALL | IT_STRING2, NULL, "Move Left", M_ChangeControl, GC_STRAFELEFT },
{IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, gc_straferight }, {IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, GC_STRAFERIGHT },
{IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, gc_jump }, {IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, GC_JUMP },
{IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, gc_spin }, {IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, GC_SPIN },
{IT_HEADER, NULL, "Camera", NULL, 0}, {IT_HEADER, NULL, "Camera", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup }, {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, GC_LOOKUP },
{IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown }, {IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, GC_LOOKDOWN },
{IT_CALL | IT_STRING2, NULL, "Look Left", M_ChangeControl, gc_turnleft }, {IT_CALL | IT_STRING2, NULL, "Look Left", M_ChangeControl, GC_TURNLEFT },
{IT_CALL | IT_STRING2, NULL, "Look Right", M_ChangeControl, gc_turnright }, {IT_CALL | IT_STRING2, NULL, "Look Right", M_ChangeControl, GC_TURNRIGHT },
{IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview }, {IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, GC_CENTERVIEW },
{IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming }, {IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, GC_MOUSEAIMING },
{IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, gc_camtoggle}, {IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, GC_CAMTOGGLE},
{IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, gc_camreset }, {IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, GC_CAMRESET },
{IT_HEADER, NULL, "Meta", NULL, 0}, {IT_HEADER, NULL, "Meta", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Game Status", {IT_CALL | IT_STRING2, NULL, "Game Status",
M_ChangeControl, gc_scores }, M_ChangeControl, GC_SCORES },
{IT_CALL | IT_STRING2, NULL, "Pause / Run Retry", M_ChangeControl, gc_pause }, {IT_CALL | IT_STRING2, NULL, "Pause / Run Retry", M_ChangeControl, GC_PAUSE },
{IT_CALL | IT_STRING2, NULL, "Screenshot", M_ChangeControl, gc_screenshot }, {IT_CALL | IT_STRING2, NULL, "Screenshot", M_ChangeControl, GC_SCREENSHOT },
{IT_CALL | IT_STRING2, NULL, "Toggle GIF Recording", M_ChangeControl, gc_recordgif }, {IT_CALL | IT_STRING2, NULL, "Toggle GIF Recording", M_ChangeControl, GC_RECORDGIF },
{IT_CALL | IT_STRING2, NULL, "Open/Close Menu (ESC)", M_ChangeControl, gc_systemmenu }, {IT_CALL | IT_STRING2, NULL, "Open/Close Menu (ESC)", M_ChangeControl, GC_SYSTEMMENU },
{IT_CALL | IT_STRING2, NULL, "Change Viewpoint", M_ChangeControl, gc_viewpoint }, {IT_CALL | IT_STRING2, NULL, "Change Viewpoint", M_ChangeControl, GC_VIEWPOINT },
{IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console }, {IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, GC_CONSOLE },
{IT_HEADER, NULL, "Multiplayer", NULL, 0}, {IT_HEADER, NULL, "Multiplayer", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Talk", M_ChangeControl, gc_talkkey }, {IT_CALL | IT_STRING2, NULL, "Talk", M_ChangeControl, GC_TALKKEY },
{IT_CALL | IT_STRING2, NULL, "Talk (Team only)", M_ChangeControl, gc_teamkey }, {IT_CALL | IT_STRING2, NULL, "Talk (Team only)", M_ChangeControl, GC_TEAMKEY },
{IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 0}, {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Fire", M_ChangeControl, gc_fire }, {IT_CALL | IT_STRING2, NULL, "Fire", M_ChangeControl, GC_FIRE },
{IT_CALL | IT_STRING2, NULL, "Fire Normal", M_ChangeControl, gc_firenormal }, {IT_CALL | IT_STRING2, NULL, "Fire Normal", M_ChangeControl, GC_FIRENORMAL },
{IT_CALL | IT_STRING2, NULL, "Toss Flag", M_ChangeControl, gc_tossflag }, {IT_CALL | IT_STRING2, NULL, "Toss Flag", M_ChangeControl, GC_TOSSFLAG },
{IT_CALL | IT_STRING2, NULL, "Next Weapon", M_ChangeControl, gc_weaponnext }, {IT_CALL | IT_STRING2, NULL, "Next Weapon", M_ChangeControl, GC_WEAPONNEXT },
{IT_CALL | IT_STRING2, NULL, "Prev Weapon", M_ChangeControl, gc_weaponprev }, {IT_CALL | IT_STRING2, NULL, "Prev Weapon", M_ChangeControl, GC_WEAPONPREV },
{IT_CALL | IT_STRING2, NULL, "Normal / Infinity", M_ChangeControl, gc_wepslot1 }, {IT_CALL | IT_STRING2, NULL, "Normal / Infinity", M_ChangeControl, GC_WEPSLOT1 },
{IT_CALL | IT_STRING2, NULL, "Automatic", M_ChangeControl, gc_wepslot2 }, {IT_CALL | IT_STRING2, NULL, "Automatic", M_ChangeControl, GC_WEPSLOT2 },
{IT_CALL | IT_STRING2, NULL, "Bounce", M_ChangeControl, gc_wepslot3 }, {IT_CALL | IT_STRING2, NULL, "Bounce", M_ChangeControl, GC_WEPSLOT3 },
{IT_CALL | IT_STRING2, NULL, "Scatter", M_ChangeControl, gc_wepslot4 }, {IT_CALL | IT_STRING2, NULL, "Scatter", M_ChangeControl, GC_WEPSLOT4 },
{IT_CALL | IT_STRING2, NULL, "Grenade", M_ChangeControl, gc_wepslot5 }, {IT_CALL | IT_STRING2, NULL, "Grenade", M_ChangeControl, GC_WEPSLOT5 },
{IT_CALL | IT_STRING2, NULL, "Explosion", M_ChangeControl, gc_wepslot6 }, {IT_CALL | IT_STRING2, NULL, "Explosion", M_ChangeControl, GC_WEPSLOT6 },
{IT_CALL | IT_STRING2, NULL, "Rail", M_ChangeControl, gc_wepslot7 }, {IT_CALL | IT_STRING2, NULL, "Rail", M_ChangeControl, GC_WEPSLOT7 },
{IT_HEADER, NULL, "Add-ons", NULL, 0}, {IT_HEADER, NULL, "Add-ons", NULL, 0},
{IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_SPACE, NULL, NULL, NULL, 0}, // padding
{IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, gc_custom1 }, {IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, GC_CUSTOM1 },
{IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, gc_custom2 }, {IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, GC_CUSTOM2 },
{IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, gc_custom3 }, {IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, GC_CUSTOM3 },
}; };
static menuitem_t OP_Joystick1Menu[] = static menuitem_t OP_Joystick1Menu[] =
@ -3229,7 +3229,7 @@ boolean M_Responder(event_t *ev)
if (ev->type == ev_keydown) if (ev->type == ev_keydown)
{ {
keydown++; keydown++;
ch = ev->data1; ch = ev->key;
// added 5-2-98 remap virtual keys (mouse & joystick buttons) // added 5-2-98 remap virtual keys (mouse & joystick buttons)
switch (ch) switch (ch)
@ -3262,44 +3262,44 @@ boolean M_Responder(event_t *ev)
break; break;
} }
} }
else if (ev->type == ev_joystick && ev->data1 == 0 && joywait < I_GetTime()) else if (ev->type == ev_joystick && ev->key == 0 && joywait < I_GetTime())
{ {
const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT; const INT32 jdeadzone = (JOYAXISRANGE * cv_digitaldeadzone.value) / FRACUNIT;
if (ev->data3 != INT32_MAX) if (ev->y != INT32_MAX)
{ {
if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone) if (Joystick.bGamepadStyle || abs(ev->y) > jdeadzone)
{ {
if (ev->data3 < 0 && pjoyy >= 0) if (ev->y < 0 && pjoyy >= 0)
{ {
ch = KEY_UPARROW; ch = KEY_UPARROW;
joywait = I_GetTime() + NEWTICRATE/7; joywait = I_GetTime() + NEWTICRATE/7;
} }
else if (ev->data3 > 0 && pjoyy <= 0) else if (ev->y > 0 && pjoyy <= 0)
{ {
ch = KEY_DOWNARROW; ch = KEY_DOWNARROW;
joywait = I_GetTime() + NEWTICRATE/7; joywait = I_GetTime() + NEWTICRATE/7;
} }
pjoyy = ev->data3; pjoyy = ev->y;
} }
else else
pjoyy = 0; pjoyy = 0;
} }
if (ev->data2 != INT32_MAX) if (ev->x != INT32_MAX)
{ {
if (Joystick.bGamepadStyle || abs(ev->data2) > jdeadzone) if (Joystick.bGamepadStyle || abs(ev->x) > jdeadzone)
{ {
if (ev->data2 < 0 && pjoyx >= 0) if (ev->x < 0 && pjoyx >= 0)
{ {
ch = KEY_LEFTARROW; ch = KEY_LEFTARROW;
joywait = I_GetTime() + NEWTICRATE/17; joywait = I_GetTime() + NEWTICRATE/17;
} }
else if (ev->data2 > 0 && pjoyx <= 0) else if (ev->x > 0 && pjoyx <= 0)
{ {
ch = KEY_RIGHTARROW; ch = KEY_RIGHTARROW;
joywait = I_GetTime() + NEWTICRATE/17; joywait = I_GetTime() + NEWTICRATE/17;
} }
pjoyx = ev->data2; pjoyx = ev->x;
} }
else else
pjoyx = 0; pjoyx = 0;
@ -3307,7 +3307,7 @@ boolean M_Responder(event_t *ev)
} }
else if (ev->type == ev_mouse && mousewait < I_GetTime()) else if (ev->type == ev_mouse && mousewait < I_GetTime())
{ {
pmousey -= ev->data3; pmousey -= ev->y;
if (pmousey < lasty-30) if (pmousey < lasty-30)
{ {
ch = KEY_DOWNARROW; ch = KEY_DOWNARROW;
@ -3321,7 +3321,7 @@ boolean M_Responder(event_t *ev)
pmousey = lasty += 30; pmousey = lasty += 30;
} }
pmousex += ev->data2; pmousex += ev->x;
if (pmousex < lastx - 30) if (pmousex < lastx - 30)
{ {
ch = KEY_LEFTARROW; ch = KEY_LEFTARROW;
@ -3339,11 +3339,11 @@ boolean M_Responder(event_t *ev)
keydown = 0; keydown = 0;
} }
else if (ev->type == ev_keydown) // Preserve event for other responders else if (ev->type == ev_keydown) // Preserve event for other responders
ch = ev->data1; ch = ev->key;
if (ch == -1) if (ch == -1)
return false; return false;
else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key else if (ch == gamecontrol[GC_SYSTEMMENU][0] || ch == gamecontrol[GC_SYSTEMMENU][1]) // allow remappable ESC key
ch = KEY_ESCAPE; ch = KEY_ESCAPE;
// F-Keys // F-Keys
@ -4185,7 +4185,7 @@ static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_
if (staticalong > pw) // simplified for base LSSTATIC if (staticalong > pw) // simplified for base LSSTATIC
staticalong -= pw; staticalong -= pw;
V_DrawCroppedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT/2, flags, patch, staticalong, 0, sw, h*2); // FixedDiv(h, scale)); -- for scale FRACUNIT/2 V_DrawCroppedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT/2, FRACUNIT/2, flags, patch, NULL, staticalong<<FRACBITS, 0, sw<<FRACBITS, h*2<<FRACBITS); // FixedDiv(h, scale)); -- for scale FRACUNIT/2
staticalong += sw; //M_RandomRange(sw/2, 2*sw); -- turns out less randomisation looks better because immediately adjacent frames can't end up close to each other staticalong += sw; //M_RandomRange(sw/2, 2*sw); -- turns out less randomisation looks better because immediately adjacent frames can't end up close to each other
@ -12826,13 +12826,13 @@ static void M_DrawControl(void)
else else
{ {
if (keys[0] != KEY_NULL) if (keys[0] != KEY_NULL)
strcat (tmp, G_KeyNumToString (keys[0])); strcat (tmp, G_KeyNumToName (keys[0]));
if (keys[0] != KEY_NULL && keys[1] != KEY_NULL) if (keys[0] != KEY_NULL && keys[1] != KEY_NULL)
strcat(tmp," or "); strcat(tmp," or ");
if (keys[1] != KEY_NULL) if (keys[1] != KEY_NULL)
strcat (tmp, G_KeyNumToString (keys[1])); strcat (tmp, G_KeyNumToName (keys[1]));
} }
@ -12859,7 +12859,7 @@ static void M_ChangecontrolResponse(event_t *ev)
{ {
INT32 control; INT32 control;
INT32 found; INT32 found;
INT32 ch = ev->data1; INT32 ch = ev->key;
// ESCAPE cancels; dummy out PAUSE // ESCAPE cancels; dummy out PAUSE
if (ch != KEY_ESCAPE && ch != KEY_PAUSE) if (ch != KEY_ESCAPE && ch != KEY_PAUSE)
@ -12878,7 +12878,7 @@ static void M_ChangecontrolResponse(event_t *ev)
// keypad arrows are converted for the menu in cursor arrows // keypad arrows are converted for the menu in cursor arrows
// so use the event instead of ch // so use the event instead of ch
case ev_keydown: case ev_keydown:
ch = ev->data1; ch = ev->key;
break; break;
default: default:
@ -12929,7 +12929,7 @@ static void M_ChangecontrolResponse(event_t *ev)
static char tmp[158]; static char tmp[158];
menu_t *prev = currentMenu->prevMenu; menu_t *prev = currentMenu->prevMenu;
if (controltochange == gc_pause) if (controltochange == GC_PAUSE)
sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit cannot be used to retry runs \nduring Record Attack. \n\nHit another key for\n%s\nESC for Cancel"), sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit cannot be used to retry runs \nduring Record Attack. \n\nHit another key for\n%s\nESC for Cancel"),
controltochangetext); controltochangetext);
else else

View file

@ -1631,14 +1631,14 @@ boolean M_ScreenshotResponder(event_t *ev)
if (dedicated || ev->type != ev_keydown) if (dedicated || ev->type != ev_keydown)
return false; return false;
ch = ev->data1; ch = ev->key;
if (ch >= KEY_MOUSE1 && menuactive) // If it's not a keyboard key, then don't allow it in the menus! if (ch >= KEY_MOUSE1 && menuactive) // If it's not a keyboard key, then don't allow it in the menus!
return false; return false;
if (ch == KEY_F8 || ch == gamecontrol[gc_screenshot][0] || ch == gamecontrol[gc_screenshot][1]) // remappable F8 if (ch == KEY_F8 || ch == gamecontrol[GC_SCREENSHOT][0] || ch == gamecontrol[GC_SCREENSHOT][1]) // remappable F8
M_ScreenShot(); M_ScreenShot();
else if (ch == KEY_F9 || ch == gamecontrol[gc_recordgif][0] || ch == gamecontrol[gc_recordgif][1]) // remappable F9 else if (ch == KEY_F9 || ch == gamecontrol[GC_RECORDGIF][0] || ch == gamecontrol[GC_RECORDGIF][1]) // remappable F9
((moviemode) ? M_StopMovie : M_StartMovie)(); ((moviemode) ? M_StopMovie : M_StartMovie)();
else else
return false; return false;
@ -2688,3 +2688,22 @@ const char * M_Ftrim (double f)
return &dig[1];/* skip the 0 */ return &dig[1];/* skip the 0 */
} }
} }
// Returns true if the string is empty.
boolean M_IsStringEmpty(const char *s)
{
const char *ch = s;
if (s == NULL || s[0] == '\0')
return true;
for (;;ch++)
{
if (!(*ch))
break;
if (!isspace((*ch)))
return false;
}
return true;
}

View file

@ -117,6 +117,9 @@ trailing zeros, or "" if the fractional part is zero.
*/ */
const char * M_Ftrim (double); const char * M_Ftrim (double);
// Returns true if the string is empty.
boolean M_IsStringEmpty(const char *s);
// counting bits, for weapon ammo code, usually // counting bits, for weapon ammo code, usually
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);

View file

@ -8272,7 +8272,7 @@ void A_Boss3ShockThink(mobj_t *actor)
fixed_t x0, y0, x1, y1; fixed_t x0, y0, x1, y1;
// Break the link if movements are too different // Break the link if movements are too different
if (FixedHypot(snext->momx - actor->momx, snext->momy - actor->momy) > 12*actor->scale) if (R_PointToDist2(0, 0, snext->momx - actor->momx, snext->momy - actor->momy) > 12*actor->scale)
{ {
P_SetTarget(&actor->hnext, NULL); P_SetTarget(&actor->hnext, NULL);
return; return;
@ -8283,9 +8283,11 @@ void A_Boss3ShockThink(mobj_t *actor)
y0 = actor->y; y0 = actor->y;
x1 = snext->x; x1 = snext->x;
y1 = snext->y; y1 = snext->y;
if (FixedHypot(x1 - x0, y1 - y0) > 2*actor->radius) if (R_PointToDist2(0, 0, x1 - x0, y1 - y0) > 2*actor->radius)
{ {
snew = P_SpawnMobj((x0 + x1) >> 1, (y0 + y1) >> 1, (actor->z + snext->z) >> 1, actor->type); snew = P_SpawnMobj((x0 >> 1) + (x1 >> 1),
(y0 >> 1) + (y1 >> 1),
(actor->z >> 1) + (snext->z >> 1), actor->type);
snew->momx = (actor->momx + snext->momx) >> 1; snew->momx = (actor->momx + snext->momx) >> 1;
snew->momy = (actor->momy + snext->momy) >> 1; snew->momy = (actor->momy + snext->momy) >> 1;
snew->momz = (actor->momz + snext->momz) >> 1; // is this really needed? snew->momz = (actor->momz + snext->momz) >> 1; // is this really needed?
@ -8293,6 +8295,10 @@ void A_Boss3ShockThink(mobj_t *actor)
P_SetTarget(&snew->target, actor->target); P_SetTarget(&snew->target, actor->target);
snew->fuse = actor->fuse; snew->fuse = actor->fuse;
P_SetScale(snew, actor->scale);
snew->destscale = actor->destscale;
snew->scalespeed = actor->scalespeed;
P_SetTarget(&actor->hnext, snew); P_SetTarget(&actor->hnext, snew);
P_SetTarget(&snew->hnext, snext); P_SetTarget(&snew->hnext, snext);
} }

View file

@ -1842,7 +1842,7 @@ void P_XYMovement(mobj_t *mo)
if (player) if (player)
B_MoveBlocked(player); B_MoveBlocked(player);
if (LUA_HookMobj(mo, MOBJ_HOOK(MobjMoveBlocked))) if (LUA_HookMobjMoveBlocked(mo, tmhitthing, blockingline))
{ {
if (P_MobjWasRemoved(mo)) if (P_MobjWasRemoved(mo))
return; return;
@ -11056,7 +11056,7 @@ void P_SpawnPrecipitation(void)
subsector_t *precipsector = NULL; subsector_t *precipsector = NULL;
precipmobj_t *rainmo = NULL; precipmobj_t *rainmo = NULL;
if (dedicated || !(cv_drawdist_precip.value) || curWeather == PRECIP_NONE) if (dedicated || !(cv_drawdist_precip.value) || curWeather == PRECIP_NONE || curWeather == PRECIP_STORM_NORAIN)
return; return;
// Use the blockmap to narrow down our placing patterns // Use the blockmap to narrow down our placing patterns
@ -11102,22 +11102,14 @@ void P_SpawnPrecipitation(void)
continue; continue;
rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN); rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN);
if (curWeather == PRECIP_BLANK)
rainmo->precipflags |= PCF_INVISIBLE;
} }
// Randomly assign a height, now that floorz is set. // Randomly assign a height, now that floorz is set.
rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<<FRACBITS; rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<<FRACBITS;
} }
if (curWeather == PRECIP_BLANK)
{
curWeather = PRECIP_RAIN;
P_SwitchWeather(PRECIP_BLANK);
}
else if (curWeather == PRECIP_STORM_NORAIN)
{
curWeather = PRECIP_RAIN;
P_SwitchWeather(PRECIP_STORM_NORAIN);
}
} }
// //

View file

@ -1501,6 +1501,22 @@ typedef struct textmap_colormap_s {
textmap_colormap_t textmap_colormap = { false, 0, 25, 0, 25, 0, 31, 0 }; textmap_colormap_t textmap_colormap = { false, 0, 25, 0, 25, 0, 31, 0 };
typedef enum
{
PD_A = 1,
PD_B = 1<<1,
PD_C = 1<<2,
PD_D = 1<<3,
} planedef_t;
typedef struct textmap_plane_s {
UINT8 defined;
fixed_t a, b, c, d;
} textmap_plane_t;
textmap_plane_t textmap_planefloor = {0, 0, 0, 0, 0};
textmap_plane_t textmap_planeceiling = {0, 0, 0, 0, 0};
static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
{ {
if (fastcmp(param, "heightfloor")) if (fastcmp(param, "heightfloor"))
@ -1539,6 +1555,46 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastcmp(param, "rotationceiling")) else if (fastcmp(param, "rotationceiling"))
sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastcmp(param, "floorplane_a"))
{
textmap_planefloor.defined |= PD_A;
textmap_planefloor.a = FLOAT_TO_FIXED(atof(val));
}
else if (fastcmp(param, "floorplane_b"))
{
textmap_planefloor.defined |= PD_B;
textmap_planefloor.b = FLOAT_TO_FIXED(atof(val));
}
else if (fastcmp(param, "floorplane_c"))
{
textmap_planefloor.defined |= PD_C;
textmap_planefloor.c = FLOAT_TO_FIXED(atof(val));
}
else if (fastcmp(param, "floorplane_d"))
{
textmap_planefloor.defined |= PD_D;
textmap_planefloor.d = FLOAT_TO_FIXED(atof(val));
}
else if (fastcmp(param, "ceilingplane_a"))
{
textmap_planeceiling.defined |= PD_A;
textmap_planeceiling.a = FLOAT_TO_FIXED(atof(val));
}
else if (fastcmp(param, "ceilingplane_b"))
{
textmap_planeceiling.defined |= PD_B;
textmap_planeceiling.b = FLOAT_TO_FIXED(atof(val));
}
else if (fastcmp(param, "ceilingplane_c"))
{
textmap_planeceiling.defined |= PD_C;
textmap_planeceiling.c = FLOAT_TO_FIXED(atof(val));
}
else if (fastcmp(param, "ceilingplane_d"))
{
textmap_planeceiling.defined |= PD_D;
textmap_planeceiling.d = FLOAT_TO_FIXED(atof(val));
}
else if (fastcmp(param, "lightcolor")) else if (fastcmp(param, "lightcolor"))
{ {
textmap_colormap.used = true; textmap_colormap.used = true;
@ -1868,6 +1924,10 @@ static void P_LoadTextmap(void)
textmap_colormap.fadestart = 0; textmap_colormap.fadestart = 0;
textmap_colormap.fadeend = 31; textmap_colormap.fadeend = 31;
textmap_colormap.flags = 0; textmap_colormap.flags = 0;
textmap_planefloor.defined = 0;
textmap_planeceiling.defined = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc); P_InitializeSector(sc);
@ -1877,6 +1937,19 @@ static void P_LoadTextmap(void)
INT32 fadergba = P_ColorToRGBA(textmap_colormap.fadecolor, textmap_colormap.fadealpha); INT32 fadergba = P_ColorToRGBA(textmap_colormap.fadecolor, textmap_colormap.fadealpha);
sc->extra_colormap = sc->spawn_extra_colormap = R_CreateColormap(rgba, fadergba, textmap_colormap.fadestart, textmap_colormap.fadeend, textmap_colormap.flags); sc->extra_colormap = sc->spawn_extra_colormap = R_CreateColormap(rgba, fadergba, textmap_colormap.fadestart, textmap_colormap.fadeend, textmap_colormap.flags);
} }
if (textmap_planefloor.defined == (PD_A|PD_B|PD_C|PD_D))
{
sc->f_slope = MakeViaEquationConstants(textmap_planefloor.a, textmap_planefloor.b, textmap_planefloor.c, textmap_planefloor.d);
sc->hasslope = true;
}
if (textmap_planeceiling.defined == (PD_A|PD_B|PD_C|PD_D))
{
sc->c_slope = MakeViaEquationConstants(textmap_planeceiling.a, textmap_planeceiling.b, textmap_planeceiling.c, textmap_planeceiling.d);
sc->hasslope = true;
}
TextmapFixFlatOffsets(sc); TextmapFixFlatOffsets(sc);
} }
@ -3154,6 +3227,12 @@ static void P_ConvertBinaryMap(void)
if (lines[i].flags & ML_NONET) if (lines[i].flags & ML_NONET)
lines[i].args[2] |= TMSL_DYNAMIC; lines[i].args[2] |= TMSL_DYNAMIC;
if (lines[i].flags & ML_TFERLINE)
{
lines[i].args[4] |= backfloor ? TMSC_BACKTOFRONTFLOOR : (frontfloor ? TMSC_FRONTTOBACKFLOOR : 0);
lines[i].args[4] |= backceil ? TMSC_BACKTOFRONTCEILING : (frontceil ? TMSC_FRONTTOBACKCEILING : 0);
}
lines[i].special = 700; lines[i].special = 700;
break; break;
} }
@ -4274,6 +4353,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
P_MapStart(); // tmthing can be used starting from this point P_MapStart(); // tmthing can be used starting from this point
P_InitSlopes();
if (!P_LoadMapFromFile()) if (!P_LoadMapFromFile())
return false; return false;
@ -4485,10 +4566,9 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l
// Add a wadfile to the active wad files, // Add a wadfile to the active wad files,
// replace sounds, musics, patches, textures, sprites and maps // replace sounds, musics, patches, textures, sprites and maps
// //
boolean P_AddWadFile(const char *wadfilename) static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps)
{ {
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0; size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
UINT16 numlumps, wadnum;
char *name; char *name;
lumpinfo_t *lumpinfo; lumpinfo_t *lumpinfo;
@ -4509,18 +4589,10 @@ boolean P_AddWadFile(const char *wadfilename)
// UINT16 flaPos, flaNum = 0; // UINT16 flaPos, flaNum = 0;
// UINT16 mapPos, mapNum = 0; // UINT16 mapPos, mapNum = 0;
// Init file.
if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX)
{
refreshdirmenu |= REFRESHDIR_NOTLOADED;
return false;
}
else
wadnum = (UINT16)(numwadfiles-1);
switch(wadfiles[wadnum]->type) switch(wadfiles[wadnum]->type)
{ {
case RET_PK3: case RET_PK3:
case RET_FOLDER:
// Look for the lumps that act as resource delimitation markers. // Look for the lumps that act as resource delimitation markers.
lumpinfo = wadfiles[wadnum]->lumpinfo; lumpinfo = wadfiles[wadnum]->lumpinfo;
for (i = 0; i < numlumps; i++, lumpinfo++) for (i = 0; i < numlumps; i++, lumpinfo++)
@ -4684,3 +4756,35 @@ boolean P_AddWadFile(const char *wadfilename)
return true; return true;
} }
boolean P_AddWadFile(const char *wadfilename)
{
UINT16 numlumps, wadnum;
// Init file.
if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX)
{
refreshdirmenu |= REFRESHDIR_NOTLOADED;
return false;
}
else
wadnum = (UINT16)(numwadfiles-1);
return P_LoadAddon(wadnum, numlumps);
}
boolean P_AddFolder(const char *folderpath)
{
UINT16 numlumps, wadnum;
// Init file.
if ((numlumps = W_InitFolder(folderpath, false, false)) == INT16_MAX)
{
refreshdirmenu |= REFRESHDIR_NOTLOADED;
return false;
}
else
wadnum = (UINT16)(numwadfiles-1);
return P_LoadAddon(wadnum, numlumps);
}

View file

@ -103,6 +103,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
void HWR_LoadLevel(void); void HWR_LoadLevel(void);
#endif #endif
boolean P_AddWadFile(const char *wadfilename); boolean P_AddWadFile(const char *wadfilename);
boolean P_AddFolder(const char *folderpath);
boolean P_RunSOC(const char *socfilename); boolean P_RunSOC(const char *socfilename);
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);

View file

@ -90,6 +90,36 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v
} }
} }
/// Setup slope via constants.
static void ReconfigureViaConstants (pslope_t *slope, const fixed_t a, const fixed_t b, const fixed_t c, const fixed_t d)
{
fixed_t m;
vector3_t *normal = &slope->normal;
// Set origin.
FV3_Load(&slope->o, 0, 0, c ? -FixedDiv(d, c) : 0);
// Get slope's normal.
FV3_Load(normal, a, b, c);
FV3_Normalize(normal);
// Invert normal if it's facing down.
if (normal->z < 0)
FV3_Negate(normal);
// Get direction vector
m = FixedHypot(normal->x, normal->y);
slope->d.x = -FixedDiv(normal->x, m);
slope->d.y = -FixedDiv(normal->y, m);
// Z delta
slope->zdelta = FixedDiv(m, normal->z);
// Get angles
slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180;
slope->zangle = InvAngle(R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta));
}
/// Recalculate dynamic slopes. /// Recalculate dynamic slopes.
void T_DynamicSlopeLine (dynplanethink_t* th) void T_DynamicSlopeLine (dynplanethink_t* th)
{ {
@ -631,13 +661,20 @@ pslope_t *P_SlopeById(UINT16 id)
return ret; return ret;
} }
/// Creates a new slope from equation constants.
pslope_t *MakeViaEquationConstants(const fixed_t a, const fixed_t b, const fixed_t c, const fixed_t d)
{
pslope_t* ret = Slope_Add(0);
ReconfigureViaConstants(ret, a, b, c, d);
return ret;
}
/// Initializes and reads the slopes from the map data. /// Initializes and reads the slopes from the map data.
void P_SpawnSlopes(const boolean fromsave) { void P_SpawnSlopes(const boolean fromsave) {
size_t i; size_t i;
slopelist = NULL;
slopecount = 0;
/// Generates vertex slopes. /// Generates vertex slopes.
SpawnVertexSlopes(); SpawnVertexSlopes();
@ -664,6 +701,9 @@ void P_SpawnSlopes(const boolean fromsave) {
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
switch (lines[i].special) switch (lines[i].special)
{ {
case 700:
if (lines[i].flags & ML_TFERLINE) P_CopySectorSlope(&lines[i]);
break;
case 720: case 720:
P_CopySectorSlope(&lines[i]); P_CopySectorSlope(&lines[i]);
default: default:
@ -671,6 +711,13 @@ void P_SpawnSlopes(const boolean fromsave) {
} }
} }
/// Initializes slopes.
void P_InitSlopes(void)
{
slopelist = NULL;
slopecount = 0;
}
// ============================================================================ // ============================================================================
// //
// Various utilities related to slopes // Various utilities related to slopes

View file

@ -50,6 +50,7 @@ typedef enum
void P_LinkSlopeThinkers (void); void P_LinkSlopeThinkers (void);
void P_CalculateSlopeNormal(pslope_t *slope); void P_CalculateSlopeNormal(pslope_t *slope);
void P_InitSlopes(void);
void P_SpawnSlopes(const boolean fromsave); void P_SpawnSlopes(const boolean fromsave);
// //
@ -86,6 +87,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope);
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope);
void P_ButteredSlope(mobj_t *mo); void P_ButteredSlope(mobj_t *mo);
pslope_t *MakeViaEquationConstants(const fixed_t a, const fixed_t b, const fixed_t c, const fixed_t d);
/// Dynamic plane type enum for the thinker. Will have a different functionality depending on this. /// Dynamic plane type enum for the thinker. Will have a different functionality depending on this.
typedef enum { typedef enum {

View file

@ -1981,6 +1981,22 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
} }
} }
static boolean is_rain_type (INT32 weathernum)
{
switch (weathernum)
{
case PRECIP_SNOW:
case PRECIP_RAIN:
case PRECIP_STORM:
case PRECIP_STORM_NOSTRIKES:
case PRECIP_BLANK:
return true;
default:
return false;
}
}
// //
// P_SwitchWeather // P_SwitchWeather
// //
@ -1988,53 +2004,14 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
// //
void P_SwitchWeather(INT32 weathernum) void P_SwitchWeather(INT32 weathernum)
{ {
boolean purge = false; boolean purge = true;
INT32 swap = 0;
switch (weathernum) if (weathernum == curWeather)
{
case PRECIP_NONE: // None
if (curWeather == PRECIP_NONE)
return; // Nothing to do.
purge = true;
break;
case PRECIP_STORM: // Storm
case PRECIP_STORM_NOSTRIKES: // Storm w/ no lightning
case PRECIP_RAIN: // Rain
if (curWeather == PRECIP_SNOW || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN)
swap = PRECIP_RAIN;
break;
case PRECIP_SNOW: // Snow
if (curWeather == PRECIP_SNOW)
return; // Nothing to do.
if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN)
swap = PRECIP_SNOW; // Need to delete the other precips.
break;
case PRECIP_STORM_NORAIN: // Storm w/o rain
if (curWeather == PRECIP_SNOW
|| curWeather == PRECIP_STORM
|| curWeather == PRECIP_STORM_NOSTRIKES
|| curWeather == PRECIP_RAIN
|| curWeather == PRECIP_BLANK)
swap = PRECIP_STORM_NORAIN;
else if (curWeather == PRECIP_STORM_NORAIN)
return; return;
break;
case PRECIP_BLANK: if (is_rain_type(weathernum) &&
if (curWeather == PRECIP_SNOW is_rain_type(curWeather))
|| curWeather == PRECIP_STORM purge = false;
|| curWeather == PRECIP_STORM_NOSTRIKES
|| curWeather == PRECIP_RAIN)
swap = PRECIP_BLANK;
else if (curWeather == PRECIP_STORM_NORAIN)
swap = PRECIP_BLANK;
else if (curWeather == PRECIP_BLANK)
return;
break;
default:
CONS_Debug(DBG_GAMELOGIC, "P_SwitchWeather: Unknown weather type %d.\n", weathernum);
break;
}
if (purge) if (purge)
{ {
@ -2051,7 +2028,7 @@ void P_SwitchWeather(INT32 weathernum)
P_RemovePrecipMobj(precipmobj); P_RemovePrecipMobj(precipmobj);
} }
} }
else if (swap && !((swap == PRECIP_BLANK && curWeather == PRECIP_STORM_NORAIN) || (swap == PRECIP_STORM_NORAIN && curWeather == PRECIP_BLANK))) // Rather than respawn all that crap, reuse it! else // Rather than respawn all that crap, reuse it!
{ {
thinker_t *think; thinker_t *think;
precipmobj_t *precipmobj; precipmobj_t *precipmobj;
@ -2063,7 +2040,7 @@ void P_SwitchWeather(INT32 weathernum)
continue; // not a precipmobj thinker continue; // not a precipmobj thinker
precipmobj = (precipmobj_t *)think; precipmobj = (precipmobj_t *)think;
if (swap == PRECIP_RAIN) // Snow To Rain if (weathernum == (PRECIP_RAIN || PRECIP_STORM || PRECIP_STORM_NOSTRIKES)) // Snow To Rain
{ {
precipmobj->flags = mobjinfo[MT_RAIN].flags; precipmobj->flags = mobjinfo[MT_RAIN].flags;
st = &states[mobjinfo[MT_RAIN].spawnstate]; st = &states[mobjinfo[MT_RAIN].spawnstate];
@ -2078,7 +2055,7 @@ void P_SwitchWeather(INT32 weathernum)
precipmobj->precipflags |= PCF_RAIN; precipmobj->precipflags |= PCF_RAIN;
//think->function.acp1 = (actionf_p1)P_RainThinker; //think->function.acp1 = (actionf_p1)P_RainThinker;
} }
else if (swap == PRECIP_SNOW) // Rain To Snow else if (weathernum == PRECIP_SNOW) // Rain To Snow
{ {
INT32 z; INT32 z;
@ -2103,7 +2080,7 @@ void P_SwitchWeather(INT32 weathernum)
//think->function.acp1 = (actionf_p1)P_SnowThinker; //think->function.acp1 = (actionf_p1)P_SnowThinker;
} }
else if (swap == PRECIP_BLANK || swap == PRECIP_STORM_NORAIN) // Remove precip, but keep it around for reuse. else // Remove precip, but keep it around for reuse.
{ {
//think->function.acp1 = (actionf_p1)P_NullPrecipThinker; //think->function.acp1 = (actionf_p1)P_NullPrecipThinker;
@ -2117,48 +2094,33 @@ void P_SwitchWeather(INT32 weathernum)
case PRECIP_SNOW: // snow case PRECIP_SNOW: // snow
curWeather = PRECIP_SNOW; curWeather = PRECIP_SNOW;
if (!swap) if (purge)
P_SpawnPrecipitation(); P_SpawnPrecipitation();
break; break;
case PRECIP_RAIN: // rain case PRECIP_RAIN: // rain
{ {
boolean dontspawn = false;
if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES)
dontspawn = true;
curWeather = PRECIP_RAIN; curWeather = PRECIP_RAIN;
if (!dontspawn && !swap) if (purge)
P_SpawnPrecipitation(); P_SpawnPrecipitation();
break; break;
} }
case PRECIP_STORM: // storm case PRECIP_STORM: // storm
{ {
boolean dontspawn = false;
if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES)
dontspawn = true;
curWeather = PRECIP_STORM; curWeather = PRECIP_STORM;
if (!dontspawn && !swap) if (purge)
P_SpawnPrecipitation(); P_SpawnPrecipitation();
break; break;
} }
case PRECIP_STORM_NOSTRIKES: // storm w/o lightning case PRECIP_STORM_NOSTRIKES: // storm w/o lightning
{ {
boolean dontspawn = false;
if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES)
dontspawn = true;
curWeather = PRECIP_STORM_NOSTRIKES; curWeather = PRECIP_STORM_NOSTRIKES;
if (!dontspawn && !swap) if (purge)
P_SpawnPrecipitation(); P_SpawnPrecipitation();
break; break;
@ -2166,14 +2128,11 @@ void P_SwitchWeather(INT32 weathernum)
case PRECIP_STORM_NORAIN: // storm w/o rain case PRECIP_STORM_NORAIN: // storm w/o rain
curWeather = PRECIP_STORM_NORAIN; curWeather = PRECIP_STORM_NORAIN;
if (!swap)
P_SpawnPrecipitation();
break; break;
case PRECIP_BLANK: case PRECIP_BLANK: //preloaded
curWeather = PRECIP_BLANK; curWeather = PRECIP_BLANK;
if (!swap) if (purge)
P_SpawnPrecipitation(); P_SpawnPrecipitation();
break; break;
@ -7102,6 +7061,7 @@ void P_SpawnSpecials(boolean fromnetsave)
} }
} }
if (!fromnetsave)
P_RunLevelLoadExecutors(); P_RunLevelLoadExecutors();
} }

View file

@ -969,6 +969,9 @@ pflags_t P_GetJumpFlags(player_t *player)
// //
boolean P_PlayerInPain(player_t *player) boolean P_PlayerInPain(player_t *player)
{ {
// If the player doesn't have a mobj, it can't be in pain.
if (!player->mo)
return false;
// no silly, sliding isn't pain // no silly, sliding isn't pain
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing])
return true; return true;
@ -5357,9 +5360,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
// disabled because it seemed to disorient people and Z-targeting exists now // disabled because it seemed to disorient people and Z-targeting exists now
/*if (!demoplayback) /*if (!demoplayback)
{ {
if (player == &players[consoleplayer] && cv_cam_turnfacingability[0].value > 0 && !(PLAYER1INPUTDOWN(gc_turnleft) || PLAYER1INPUTDOWN(gc_turnright))) if (player == &players[consoleplayer] && cv_cam_turnfacingability[0].value > 0 && !(PLAYER1INPUTDOWN(GC_TURNLEFT) || PLAYER1INPUTDOWN(GC_TURNRIGHT)))
P_SetPlayerAngle(player, player->mo->angle);; P_SetPlayerAngle(player, player->mo->angle);;
else if (player == &players[secondarydisplayplayer] && cv_cam_turnfacingability[1].value > 0 && !(PLAYER2INPUTDOWN(gc_turnleft) || PLAYER2INPUTDOWN(gc_turnright))) else if (player == &players[secondarydisplayplayer] && cv_cam_turnfacingability[1].value > 0 && !(PLAYER2INPUTDOWN(GC_TURNLEFT) || PLAYER2INPUTDOWN(GC_TURNRIGHT)))
P_SetPlayerAngle(player, player->mo->angle); P_SetPlayerAngle(player, player->mo->angle);
}*/ }*/
} }
@ -5624,16 +5627,10 @@ INT32 P_GetPlayerControlDirection(player_t *player)
{ {
ticcmd_t *cmd = &player->cmd; ticcmd_t *cmd = &player->cmd;
angle_t controllerdirection, controlplayerdirection; angle_t controllerdirection, controlplayerdirection;
camera_t *thiscam;
angle_t dangle; angle_t dangle;
fixed_t tempx = 0, tempy = 0; fixed_t tempx = 0, tempy = 0;
angle_t tempangle, origtempangle; angle_t tempangle, origtempangle;
if (splitscreen && player == &players[secondarydisplayplayer])
thiscam = &camera2;
else
thiscam = &camera;
if (!cmd->forwardmove && !cmd->sidemove) if (!cmd->forwardmove && !cmd->sidemove)
return 0; return 0;
@ -5649,17 +5646,15 @@ INT32 P_GetPlayerControlDirection(player_t *player)
origtempangle = tempangle = 0; // relative to the axis rather than the player! origtempangle = tempangle = 0; // relative to the axis rather than the player!
controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
} }
else if ((P_ControlStyle(player) & CS_LMAOGALOG) && thiscam->chase) else
{ {
if (player->awayviewtics) if (player->awayviewtics)
origtempangle = tempangle = player->awayviewmobj->angle; origtempangle = tempangle = player->awayviewmobj->angle;
else if (P_ControlStyle(player) & CS_LMAOGALOG)
origtempangle = tempangle = (cmd->angleturn << 16);
else else
origtempangle = tempangle = thiscam->angle;
controlplayerdirection = player->mo->angle;
}
else
{
origtempangle = tempangle = player->mo->angle; origtempangle = tempangle = player->mo->angle;
controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
} }

View file

@ -901,9 +901,8 @@ static png_bytep *PNG_Read(
png_colorp palette; png_colorp palette;
int palette_size; int palette_size;
png_bytep trans; png_bytep trans = NULL;
int trans_num; int num_trans = 0;
png_color_16p trans_values;
#ifdef PNG_SETJMP_SUPPORTED #ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD #ifdef USE_FAR_KEYWORD
@ -998,12 +997,12 @@ static png_bytep *PNG_Read(
// color is present on the image, the palette flag is disabled. // color is present on the image, the palette flag is disabled.
if (usepal) if (usepal)
{ {
png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values); png_uint_32 result = png_get_tRNS(png_ptr, png_info_ptr, &trans, &num_trans, NULL);
if (trans && trans_num > 0) if ((result & PNG_INFO_tRNS) && num_trans > 0 && trans != NULL)
{ {
INT32 i; INT32 i;
for (i = 0; i < trans_num; i++) for (i = 0; i < num_trans; i++)
{ {
// libpng will transform this image into RGBA even if // libpng will transform this image into RGBA even if
// the transparent index does not exist in the image, // the transparent index does not exist in the image,

View file

@ -116,9 +116,9 @@ void *Picture_PNGConvert(
size_t insize, size_t *outsize, size_t insize, size_t *outsize,
pictureflags_t flags); pictureflags_t flags);
boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size); boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size);
#endif
#define PICTURE_PNG_USELOOKUP #define PICTURE_PNG_USELOOKUP
#endif
// SpriteInfo // SpriteInfo
extern spriteinfo_t spriteinfo[NUMSPRITES]; extern spriteinfo_t spriteinfo[NUMSPRITES];

View file

@ -89,8 +89,6 @@ static fixed_t planeheight;
fixed_t yslopetab[MAXVIDHEIGHT*16]; fixed_t yslopetab[MAXVIDHEIGHT*16];
fixed_t *yslope; fixed_t *yslope;
fixed_t basexscale, baseyscale;
fixed_t cachedheight[MAXVIDHEIGHT]; fixed_t cachedheight[MAXVIDHEIGHT];
fixed_t cacheddistance[MAXVIDHEIGHT]; fixed_t cacheddistance[MAXVIDHEIGHT];
fixed_t cachedxstep[MAXVIDHEIGHT]; fixed_t cachedxstep[MAXVIDHEIGHT];
@ -114,7 +112,7 @@ void R_InitPlanes(void)
// Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. // Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted.
// //
struct static struct
{ {
INT32 offset; INT32 offset;
fixed_t xfrac, yfrac; fixed_t xfrac, yfrac;
@ -143,15 +141,6 @@ static void R_UpdatePlaneRipple(void)
planeripple.offset = (leveltime * 140); planeripple.offset = (leveltime * 140);
} }
//
// R_MapPlane
//
// Uses global vars:
// planeheight
// basexscale
// baseyscale
// centerx
static void R_MapPlane(INT32 y, INT32 x1, INT32 x2) static void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
{ {
angle_t angle, planecos, planesin; angle_t angle, planecos, planesin;
@ -176,16 +165,13 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]); cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]);
span = abs(centery - y); span = abs(centery - y);
if (span) // don't divide by zero if (span) // Don't divide by zero
{ {
ds_xstep = FixedMul(planesin, planeheight) / span; ds_xstep = FixedMul(planesin, planeheight) / span;
ds_ystep = FixedMul(planecos, planeheight) / span; ds_ystep = FixedMul(planecos, planeheight) / span;
} }
else else
{ ds_xstep = ds_ystep = FRACUNIT;
ds_xstep = FixedMul(distance, basexscale);
ds_ystep = FixedMul(distance, baseyscale);
}
cachedxstep[y] = ds_xstep; cachedxstep[y] = ds_xstep;
cachedystep[y] = ds_ystep; cachedystep[y] = ds_ystep;
@ -197,6 +183,11 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
ds_ystep = cachedystep[y]; ds_ystep = cachedystep[y];
} }
// [RH] Instead of using the xtoviewangle array, I calculated the fractional values
// at the middle of the screen, then used the calculated ds_xstep and ds_ystep
// to step from those to the proper texture coordinate to start drawing at.
// That way, the texture coordinate is always calculated by its position
// on the screen and not by its position relative to the edge of the visplane.
ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep;
ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep;
@ -295,7 +286,6 @@ void R_ClearFFloorClips (void)
void R_ClearPlanes(void) void R_ClearPlanes(void)
{ {
INT32 i, p; INT32 i, p;
angle_t angle;
// opening / clipping determination // opening / clipping determination
for (i = 0; i < viewwidth; i++) for (i = 0; i < viewwidth; i++)
@ -321,13 +311,6 @@ void R_ClearPlanes(void)
// texture calculation // texture calculation
memset(cachedheight, 0, sizeof (cachedheight)); memset(cachedheight, 0, sizeof (cachedheight));
// left to right mapping
angle = (viewangle-ANGLE_90)>>ANGLETOFINESHIFT;
// scale will be unit scale at SCREENWIDTH/2 distance
basexscale = FixedDiv (FINECOSINE(angle),centerxfrac);
baseyscale = -FixedDiv (FINESINE(angle),centerxfrac);
} }
static visplane_t *new_visplane(unsigned hash) static visplane_t *new_visplane(unsigned hash)
@ -532,53 +515,22 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
// //
// R_ExpandPlane // R_ExpandPlane
// //
// This function basically expands the visplane or I_Errors. // This function basically expands the visplane.
// The reason for this is that when creating 3D floor planes, there is no // The reason for this is that when creating 3D floor planes, there is no
// need to create new ones with R_CheckPlane, because 3D floor planes // need to create new ones with R_CheckPlane, because 3D floor planes
// are created by subsector and there is no way a subsector can graphically // are created by subsector and there is no way a subsector can graphically
// overlap. // overlap.
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop)
{ {
// INT32 unionl, unionh;
// INT32 x;
// Don't expand polyobject planes here - we do that on our own. // Don't expand polyobject planes here - we do that on our own.
if (pl->polyobj) if (pl->polyobj)
return; return;
if (pl->minx > start) pl->minx = start; if (pl->minx > start) pl->minx = start;
if (pl->maxx < stop) pl->maxx = stop; if (pl->maxx < stop) pl->maxx = stop;
/*
if (start < pl->minx)
{
unionl = start;
}
else
{
unionl = pl->minx;
}
if (stop > pl->maxx)
{
unionh = stop;
}
else
{
unionh = pl->maxx;
}
for (x = start; x <= stop; x++)
if (pl->top[x] != 0xffff || pl->bottom[x] != 0x0000)
break;
if (x <= stop)
I_Error("R_ExpandPlane: planes in same subsector overlap?!\nminx: %d, maxx: %d, start: %d, stop: %d\n", pl->minx, pl->maxx, start, stop);
pl->minx = unionl, pl->maxx = unionh;
*/
} }
static void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) static void R_MakeSpans(void (*mapfunc)(INT32, INT32, INT32), INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
{ {
// Alam: from r_splats's R_RasterizeFloorSplat // Alam: from r_splats's R_RasterizeFloorSplat
if (t1 >= vid.height) t1 = vid.height-1; if (t1 >= vid.height) t1 = vid.height-1;
@ -589,38 +541,12 @@ static void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
while (t1 < t2 && t1 <= b1) while (t1 < t2 && t1 <= b1)
{ {
R_MapPlane(t1, spanstart[t1], x - 1); mapfunc(t1, spanstart[t1], x - 1);
t1++; t1++;
} }
while (b1 > b2 && b1 >= t1) while (b1 > b2 && b1 >= t1)
{ {
R_MapPlane(b1, spanstart[b1], x - 1); mapfunc(b1, spanstart[b1], x - 1);
b1--;
}
while (t2 < t1 && t2 <= b2)
spanstart[t2++] = x;
while (b2 > b1 && b2 >= t2)
spanstart[b2--] = x;
}
static void R_MakeTiltedSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
{
// Alam: from r_splats's R_RasterizeFloorSplat
if (t1 >= vid.height) t1 = vid.height-1;
if (b1 >= vid.height) b1 = vid.height-1;
if (t2 >= vid.height) t2 = vid.height-1;
if (b2 >= vid.height) b2 = vid.height-1;
if (x-1 >= vid.width) x = vid.width;
while (t1 < t2 && t1 <= b1)
{
R_MapTiltedPlane(t1, spanstart[t1], x - 1);
t1++;
}
while (b1 > b2 && b1 >= t1)
{
R_MapTiltedPlane(b1, spanstart[b1], x - 1);
b1--; b1--;
} }
@ -867,10 +793,10 @@ void R_DrawSinglePlane(visplane_t *pl)
{ {
levelflat_t *levelflat; levelflat_t *levelflat;
INT32 light = 0; INT32 light = 0;
INT32 x; INT32 x, stop;
INT32 stop, angle;
ffloor_t *rover; ffloor_t *rover;
INT32 spanfunctype = BASEDRAWFUNC; INT32 spanfunctype = BASEDRAWFUNC;
void (*mapfunc)(INT32, INT32, INT32) = R_MapPlane;
if (!(pl->minx <= pl->maxx)) if (!(pl->minx <= pl->maxx))
return; return;
@ -1021,9 +947,6 @@ void R_DrawSinglePlane(visplane_t *pl)
&& viewangle != pl->viewangle+pl->plangle) && viewangle != pl->viewangle+pl->plangle)
{ {
memset(cachedheight, 0, sizeof (cachedheight)); memset(cachedheight, 0, sizeof (cachedheight));
angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT;
basexscale = FixedDiv(FINECOSINE(angle),centerxfrac);
baseyscale = -FixedDiv(FINESINE(angle),centerxfrac);
viewangle = pl->viewangle+pl->plangle; viewangle = pl->viewangle+pl->plangle;
} }
@ -1038,6 +961,8 @@ void R_DrawSinglePlane(visplane_t *pl)
if (pl->slope) if (pl->slope)
{ {
mapfunc = R_MapTiltedPlane;
if (!pl->plangle) if (!pl->plangle)
{ {
if (ds_powersoftwo) if (ds_powersoftwo)
@ -1106,16 +1031,8 @@ void R_DrawSinglePlane(visplane_t *pl)
currentplane = pl; currentplane = pl;
stop = pl->maxx + 1; stop = pl->maxx + 1;
if (pl->slope)
{
for (x = pl->minx; x <= stop; x++) for (x = pl->minx; x <= stop; x++)
R_MakeTiltedSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); R_MakeSpans(mapfunc, x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]);
}
else
{
for (x = pl->minx; x <= stop; x++)
R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]);
}
/* /*
QUINCUNX anti-aliasing technique (sort of) QUINCUNX anti-aliasing technique (sort of)
@ -1182,7 +1099,7 @@ using the palette colors.
stop = pl->maxx + 1; stop = pl->maxx + 1;
for (x = pl->minx; x <= stop; x++) for (x = pl->minx; x <= stop; x++)
R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], R_MakeSpans(mapfunc, x, pl->top[x-1], pl->bottom[x-1],
pl->top[x], pl->bottom[x]); pl->top[x], pl->bottom[x]);
} }
} }

View file

@ -69,7 +69,6 @@ extern fixed_t cachedheight[MAXVIDHEIGHT];
extern fixed_t cacheddistance[MAXVIDHEIGHT]; extern fixed_t cacheddistance[MAXVIDHEIGHT];
extern fixed_t cachedxstep[MAXVIDHEIGHT]; extern fixed_t cachedxstep[MAXVIDHEIGHT];
extern fixed_t cachedystep[MAXVIDHEIGHT]; extern fixed_t cachedystep[MAXVIDHEIGHT];
extern fixed_t basexscale, baseyscale;
extern fixed_t *yslope; extern fixed_t *yslope;
extern lighttable_t **planezlight; extern lighttable_t **planezlight;

View file

@ -155,7 +155,6 @@ void R_DrawFloorSplat(vissprite_t *spr)
fixed_t xscale, yscale; fixed_t xscale, yscale;
fixed_t xoffset, yoffset; fixed_t xoffset, yoffset;
fixed_t leftoffset, topoffset; fixed_t leftoffset, topoffset;
pslope_t *slope = NULL;
INT32 i; INT32 i;
boolean hflip = (spr->xiscale < 0); boolean hflip = (spr->xiscale < 0);
@ -188,7 +187,7 @@ void R_DrawFloorSplat(vissprite_t *spr)
if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD)
splatangle = mobj->angle; splatangle = mobj->angle;
else else
splatangle = spr->viewangle; splatangle = spr->viewpoint.angle;
if (!(spr->cut & SC_ISROTATED)) if (!(spr->cut & SC_ISROTATED))
splatangle += mobj->rollangle; splatangle += mobj->rollangle;
@ -218,7 +217,7 @@ void R_DrawFloorSplat(vissprite_t *spr)
splat.x = x; splat.x = x;
splat.y = y; splat.y = y;
splat.z = mobj->z; splat.z = mobj->z;
splat.tilted = false; splat.slope = NULL;
// Set positions // Set positions
@ -238,9 +237,9 @@ void R_DrawFloorSplat(vissprite_t *spr)
splat.verts[3].x = w - xoffset; splat.verts[3].x = w - xoffset;
splat.verts[3].y = -h + yoffset; splat.verts[3].y = -h + yoffset;
angle = -splat.angle; angle = -splat.angle>>ANGLETOFINESHIFT;
ca = FINECOSINE(angle>>ANGLETOFINESHIFT); ca = FINECOSINE(angle);
sa = FINESINE(angle>>ANGLETOFINESHIFT); sa = FINESINE(angle);
// Rotate // Rotate
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
@ -255,36 +254,10 @@ void R_DrawFloorSplat(vissprite_t *spr)
// The slope that was defined for the sprite. // The slope that was defined for the sprite.
if (renderflags & RF_SLOPESPLAT) if (renderflags & RF_SLOPESPLAT)
slope = mobj->floorspriteslope; splat.slope = mobj->floorspriteslope;
if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT)) if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT))
slope = standingslope; splat.slope = standingslope;
// Set splat as tilted
splat.tilted = (slope != NULL);
}
if (splat.tilted)
{
pslope_t *s = &splat.slope;
s->o.x = slope->o.x;
s->o.y = slope->o.y;
s->o.z = slope->o.z;
s->d.x = slope->d.x;
s->d.y = slope->d.y;
s->normal.x = slope->normal.x;
s->normal.y = slope->normal.y;
s->normal.z = slope->normal.z;
s->zdelta = slope->zdelta;
s->zangle = slope->zangle;
s->xydirection = slope->xydirection;
s->next = NULL;
s->flags = 0;
} }
// Translate // Translate
@ -293,9 +266,9 @@ void R_DrawFloorSplat(vissprite_t *spr)
tr_x = rotated[i].x + x; tr_x = rotated[i].x + x;
tr_y = rotated[i].y + y; tr_y = rotated[i].y + y;
if (slope) if (splat.slope)
{ {
rot_z = P_GetSlopeZAt(slope, tr_x, tr_y); rot_z = P_GetSlopeZAt(splat.slope, tr_x, tr_y);
splat.verts[i].z = rot_z; splat.verts[i].z = rot_z;
} }
else else
@ -305,18 +278,23 @@ void R_DrawFloorSplat(vissprite_t *spr)
splat.verts[i].y = tr_y; splat.verts[i].y = tr_y;
} }
angle = spr->viewpoint.angle >> ANGLETOFINESHIFT;
ca = FINECOSINE(angle);
sa = FINESINE(angle);
// Project
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
v3d = &splat.verts[i]; v3d = &splat.verts[i];
// transform the origin point // transform the origin point
tr_x = v3d->x - viewx; tr_x = v3d->x - spr->viewpoint.x;
tr_y = v3d->y - viewy; tr_y = v3d->y - spr->viewpoint.y;
// rotation around vertical y axis // rotation around vertical y axis
rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); rot_x = FixedMul(tr_x, sa) - FixedMul(tr_y, ca);
rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); rot_y = FixedMul(tr_x, ca) + FixedMul(tr_y, sa);
rot_z = v3d->z - viewz; rot_z = v3d->z - spr->viewpoint.z;
if (rot_y < FRACUNIT) if (rot_y < FRACUNIT)
return; return;
@ -420,31 +398,32 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
ds_powersoftwo = true; ds_powersoftwo = true;
} }
if (pSplat->tilted) if (pSplat->slope)
{ {
R_SetTiltedSpan(0); R_SetTiltedSpan(0);
R_SetScaledSlopePlane(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle); R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle);
R_CalculateSlopeVectors(); R_CalculateSlopeVectors();
spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; spanfunctype = SPANDRAWFUNC_TILTEDSPRITE;
} }
else else
{ {
planeheight = abs(pSplat->z - viewz); planeheight = abs(pSplat->z - vis->viewpoint.z);
if (pSplat->angle) if (pSplat->angle)
{ {
// Add the view offset, rotated by the plane angle.
fixed_t a = -pSplat->verts[0].x + viewx;
fixed_t b = -pSplat->verts[0].y + viewy;
angle_t angle = (pSplat->angle >> ANGLETOFINESHIFT);
offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle));
offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle));
memset(cachedheight, 0, sizeof(cachedheight)); memset(cachedheight, 0, sizeof(cachedheight));
// Add the view offset, rotated by the plane angle.
fixed_t a = -pSplat->verts[0].x + vis->viewpoint.x;
fixed_t b = -pSplat->verts[0].y + vis->viewpoint.y;
angle_t angle = (pSplat->angle >> ANGLETOFINESHIFT);
offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b, FINESINE(angle));
offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b, FINECOSINE(angle));
} }
else else
{ {
offsetx = viewx - pSplat->verts[0].x; offsetx = vis->viewpoint.x - pSplat->verts[0].x;
offsety = pSplat->verts[0].y - viewy; offsety = pSplat->verts[0].y - vis->viewpoint.y;
} }
} }
@ -465,7 +444,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
{ {
ds_transmap = vis->transmap; ds_transmap = vis->transmap;
if (pSplat->tilted) if (pSplat->slope)
spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE; spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPRITE;
else else
spanfunctype = SPANDRAWFUNC_TRANSSPRITE; spanfunctype = SPANDRAWFUNC_TRANSSPRITE;
@ -532,12 +511,12 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
if (x2 < x1) if (x2 < x1)
continue; continue;
if (!pSplat->tilted) if (!pSplat->slope)
{ {
fixed_t xstep, ystep; fixed_t xstep, ystep;
fixed_t distance, span; fixed_t distance, span;
angle_t angle = (vis->viewangle + pSplat->angle)>>ANGLETOFINESHIFT; angle_t angle = (vis->viewpoint.angle + pSplat->angle)>>ANGLETOFINESHIFT;
angle_t planecos = FINECOSINE(angle); angle_t planecos = FINECOSINE(angle);
angle_t planesin = FINESINE(angle); angle_t planesin = FINESINE(angle);
@ -581,7 +560,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
rastertab[y].maxx = INT32_MIN; rastertab[y].maxx = INT32_MIN;
} }
if (pSplat->angle && !pSplat->tilted) if (pSplat->angle && !pSplat->slope)
memset(cachedheight, 0, sizeof(cachedheight)); memset(cachedheight, 0, sizeof(cachedheight));
} }

View file

@ -34,8 +34,7 @@ typedef struct floorsplat_s
INT32 width, height; INT32 width, height;
fixed_t scale, xscale, yscale; fixed_t scale, xscale, yscale;
angle_t angle; angle_t angle;
boolean tilted; // Uses the tilted drawer pslope_t *slope;
pslope_t slope;
vector3_t verts[4]; // (x,y,z) as viewed from above on map vector3_t verts[4]; // (x,y,z) as viewed from above on map
fixed_t x, y, z; // position fixed_t x, y, z; // position

View file

@ -724,7 +724,7 @@ Rloadflats (INT32 i, INT32 w)
texpatch_t *patch; texpatch_t *patch;
// Yes // Yes
if (wadfiles[w]->type == RET_PK3) if (W_FileHasFolders(wadfiles[w]))
{ {
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
@ -746,7 +746,7 @@ Rloadflats (INT32 i, INT32 w)
size_t lumplength; size_t lumplength;
size_t flatsize; size_t flatsize;
if (wadfiles[w]->type == RET_PK3) if (W_FileHasFolders(wadfiles[w]))
{ {
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
continue; // If it is then SKIP IT continue; // If it is then SKIP IT
@ -812,7 +812,7 @@ Rloadtextures (INT32 i, INT32 w)
texpatch_t *patch; texpatch_t *patch;
// Get the lump numbers for the markers in the WAD, if they exist. // Get the lump numbers for the markers in the WAD, if they exist.
if (wadfiles[w]->type == RET_PK3) if (W_FileHasFolders(wadfiles[w]))
{ {
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
@ -843,7 +843,7 @@ Rloadtextures (INT32 i, INT32 w)
size_t lumplength; size_t lumplength;
#endif #endif
if (wadfiles[w]->type == RET_PK3) if (W_FileHasFolders(wadfiles[w]))
{ {
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
continue; // If it is then SKIP IT continue; // If it is then SKIP IT
@ -932,7 +932,7 @@ void R_LoadTextures(void)
{ {
#ifdef WALLFLATS #ifdef WALLFLATS
// Count flats // Count flats
if (wadfiles[w]->type == RET_PK3) if (W_FileHasFolders(wadfiles[w]))
{ {
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
@ -946,7 +946,7 @@ void R_LoadTextures(void)
if (!( texstart == INT16_MAX || texend == INT16_MAX )) if (!( texstart == INT16_MAX || texend == INT16_MAX ))
{ {
// PK3s have subfolders, so we can't just make a simple sum // PK3s have subfolders, so we can't just make a simple sum
if (wadfiles[w]->type == RET_PK3) if (W_FileHasFolders(wadfiles[w]))
{ {
for (j = texstart; j < texend; j++) for (j = texstart; j < texend; j++)
{ {
@ -970,7 +970,7 @@ void R_LoadTextures(void)
} }
// Count single-patch textures // Count single-patch textures
if (wadfiles[w]->type == RET_PK3) if (W_FileHasFolders(wadfiles[w]))
{ {
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
@ -985,7 +985,7 @@ void R_LoadTextures(void)
continue; continue;
// PK3s have subfolders, so we can't just make a simple sum // PK3s have subfolders, so we can't just make a simple sum
if (wadfiles[w]->type == RET_PK3) if (W_FileHasFolders(wadfiles[w]))
{ {
for (j = texstart; j < texend; j++) for (j = texstart; j < texend; j++)
{ {
@ -1526,6 +1526,7 @@ lumpnum_t R_GetFlatNumForName(const char *name)
continue; continue;
break; break;
case RET_PK3: case RET_PK3:
case RET_FOLDER:
if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX) if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX)
continue; continue;
if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX) if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX)

View file

@ -443,6 +443,7 @@ void R_AddSpriteDefs(UINT16 wadnum)
end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib. end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib.
break; break;
case RET_PK3: case RET_PK3:
case RET_FOLDER:
start = W_CheckNumForFolderStartPK3("Sprites/", wadnum, 0); start = W_CheckNumForFolderStartPK3("Sprites/", wadnum, 0);
end = W_CheckNumForFolderEndPK3("Sprites/", wadnum, start); end = W_CheckNumForFolderEndPK3("Sprites/", wadnum, start);
break; break;
@ -1956,9 +1957,12 @@ static void R_ProjectSprite(mobj_t *thing)
vis->paperoffset = paperoffset; vis->paperoffset = paperoffset;
vis->paperdistance = paperdistance; vis->paperdistance = paperdistance;
vis->centerangle = centerangle; vis->centerangle = centerangle;
vis->viewangle = viewangle;
vis->shear.tan = sheartan; vis->shear.tan = sheartan;
vis->shear.offset = 0; vis->shear.offset = 0;
vis->viewpoint.x = viewx;
vis->viewpoint.y = viewy;
vis->viewpoint.z = viewz;
vis->viewpoint.angle = viewangle;
vis->mobj = thing; // Easy access! Tails 06-07-2002 vis->mobj = thing; // Easy access! Tails 06-07-2002

View file

@ -164,7 +164,12 @@ typedef struct vissprite_s
fixed_t xiscale; // negative if flipped fixed_t xiscale; // negative if flipped
angle_t centerangle; // for paper sprites angle_t centerangle; // for paper sprites
angle_t viewangle; // for floor sprites, the viewpoint's current angle
// for floor sprites
struct {
fixed_t x, y, z; // the viewpoint's current position
angle_t angle; // the viewpoint's current angle
} viewpoint;
struct { struct {
fixed_t tan; // The amount to shear the sprite vertically per row fixed_t tan; // The amount to shear the sprite vertically per row
@ -185,9 +190,10 @@ typedef struct vissprite_s
extracolormap_t *extra_colormap; // global colormaps extracolormap_t *extra_colormap; // global colormaps
// Precalculated top and bottom screen coords for the sprite.
fixed_t thingheight; // The actual height of the thing (for 3D floors) fixed_t thingheight; // The actual height of the thing (for 3D floors)
sector_t *sector; // The sector containing the thing. sector_t *sector; // The sector containing the thing.
// Precalculated top and bottom screen coords for the sprite.
INT16 sz, szt; INT16 sz, szt;
spritecut_e cut; spritecut_e cut;

View file

@ -550,7 +550,7 @@ static void I_StartupConsole(void)
void I_GetConsoleEvents(void) void I_GetConsoleEvents(void)
{ {
// we use this when sending back commands // we use this when sending back commands
event_t ev = {0,0,0,0}; event_t ev = {0};
char key = 0; char key = 0;
ssize_t d; ssize_t d;
@ -572,7 +572,7 @@ void I_GetConsoleEvents(void)
tty_con.buffer[tty_con.cursor] = '\0'; tty_con.buffer[tty_con.cursor] = '\0';
tty_Back(); tty_Back();
} }
ev.data1 = KEY_BACKSPACE; ev.key = KEY_BACKSPACE;
} }
else if (key < ' ') // check if this is a control char else if (key < ' ') // check if this is a control char
{ {
@ -580,19 +580,19 @@ void I_GetConsoleEvents(void)
{ {
tty_Clear(); tty_Clear();
tty_con.cursor = 0; tty_con.cursor = 0;
ev.data1 = KEY_ENTER; ev.key = KEY_ENTER;
} }
else return; else return;
} }
else else
{ {
// push regular character // push regular character
ev.data1 = tty_con.buffer[tty_con.cursor] = key; ev.key = tty_con.buffer[tty_con.cursor] = key;
tty_con.cursor++; tty_con.cursor++;
// print the current line (this is differential) // print the current line (this is differential)
d = write(STDOUT_FILENO, &key, 1); d = write(STDOUT_FILENO, &key, 1);
} }
if (ev.data1) D_PostEvent(&ev); if (ev.key) D_PostEvent(&ev);
//tty_FlushIn(); //tty_FlushIn();
(void)d; (void)d;
} }
@ -626,18 +626,18 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
{ {
case VK_ESCAPE: case VK_ESCAPE:
case VK_TAB: case VK_TAB:
event.data1 = KEY_NULL; event.key = KEY_NULL;
break; break;
case VK_RETURN: case VK_RETURN:
entering_con_command = false; entering_con_command = false;
/* FALLTHRU */ /* FALLTHRU */
default: default:
//event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char //event.key = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char
event.data1 = evt.uChar.AsciiChar; event.key = evt.uChar.AsciiChar;
} }
if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t)) if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t))
{ {
if (event.data1 && event.data1 != KEY_LSHIFT && event.data1 != KEY_RSHIFT) if (event.key && event.key != KEY_LSHIFT && event.key != KEY_RSHIFT)
{ {
#ifdef _UNICODE #ifdef _UNICODE
WriteConsole(co, &evt.uChar.UnicodeChar, 1, &t, NULL); WriteConsole(co, &evt.uChar.UnicodeChar, 1, &t, NULL);
@ -652,7 +652,7 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co)
} }
} }
} }
if (event.data1) D_PostEvent(&event); if (event.key) D_PostEvent(&event);
} }
void I_GetConsoleEvents(void) void I_GetConsoleEvents(void)
@ -917,7 +917,7 @@ INT32 I_GetKey (void)
ev = &events[eventtail]; ev = &events[eventtail];
if (ev->type == ev_keydown || ev->type == ev_console) if (ev->type == ev_keydown || ev->type == ev_console)
{ {
rc = ev->data1; rc = ev->key;
continue; continue;
} }
} }
@ -977,22 +977,22 @@ void I_ShutdownJoystick(void)
INT32 i; INT32 i;
event_t event; event_t event;
event.type=ev_keyup; event.type=ev_keyup;
event.data2 = 0; event.x = 0;
event.data3 = 0; event.y = 0;
lastjoybuttons = lastjoyhats = 0; lastjoybuttons = lastjoyhats = 0;
// emulate the up of all joystick buttons // emulate the up of all joystick buttons
for (i=0;i<JOYBUTTONS;i++) for (i=0;i<JOYBUTTONS;i++)
{ {
event.data1=KEY_JOY1+i; event.key=KEY_JOY1+i;
D_PostEvent(&event); D_PostEvent(&event);
} }
// emulate the up of all joystick hats // emulate the up of all joystick hats
for (i=0;i<JOYHATS*4;i++) for (i=0;i<JOYHATS*4;i++)
{ {
event.data1=KEY_HAT1+i; event.key=KEY_HAT1+i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1000,7 +1000,7 @@ void I_ShutdownJoystick(void)
event.type = ev_joystick; event.type = ev_joystick;
for (i=0;i<JOYAXISSET; i++) for (i=0;i<JOYAXISSET; i++)
{ {
event.data1 = i; event.key = i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1012,7 +1012,7 @@ void I_ShutdownJoystick(void)
void I_GetJoystickEvents(void) void I_GetJoystickEvents(void)
{ {
static event_t event = {0,0,0,0}; static event_t event = {0,0,0,0,false};
INT32 i = 0; INT32 i = 0;
UINT64 joyhats = 0; UINT64 joyhats = 0;
#if 0 #if 0
@ -1049,7 +1049,7 @@ void I_GetJoystickEvents(void)
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_JOY1 + i; event.key = KEY_JOY1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -1080,7 +1080,7 @@ void I_GetJoystickEvents(void)
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_HAT1 + i; event.key = KEY_HAT1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -1092,7 +1092,7 @@ void I_GetJoystickEvents(void)
for (i = JOYAXISSET - 1; i >= 0; i--) for (i = JOYAXISSET - 1; i >= 0; i--)
{ {
event.data1 = i; event.key = i;
if (i*2 + 1 <= JoyInfo.axises) if (i*2 + 1 <= JoyInfo.axises)
axisx = SDL_JoystickGetAxis(JoyInfo.dev, i*2 + 0); axisx = SDL_JoystickGetAxis(JoyInfo.dev, i*2 + 0);
else axisx = 0; else axisx = 0;
@ -1110,15 +1110,15 @@ void I_GetJoystickEvents(void)
{ {
// gamepad control type, on or off, live or die // gamepad control type, on or off, live or die
if (axisx < -(JOYAXISRANGE/2)) if (axisx < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (axisx > (JOYAXISRANGE/2)) else if (axisx > (JOYAXISRANGE/2))
event.data2 = 1; event.x = 1;
else event.data2 = 0; else event.x = 0;
if (axisy < -(JOYAXISRANGE/2)) if (axisy < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (axisy > (JOYAXISRANGE/2)) else if (axisy > (JOYAXISRANGE/2))
event.data3 = 1; event.y = 1;
else event.data3 = 0; else event.y = 0;
} }
else else
{ {
@ -1132,8 +1132,8 @@ void I_GetJoystickEvents(void)
#endif #endif
// analog control style , just send the raw data // analog control style , just send the raw data
event.data2 = axisx; // x axis event.x = axisx; // x axis
event.data3 = axisy; // y axis event.y = axisy; // y axis
} }
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1247,22 +1247,22 @@ void I_ShutdownJoystick2(void)
INT32 i; INT32 i;
event_t event; event_t event;
event.type = ev_keyup; event.type = ev_keyup;
event.data2 = 0; event.x = 0;
event.data3 = 0; event.y = 0;
lastjoy2buttons = lastjoy2hats = 0; lastjoy2buttons = lastjoy2hats = 0;
// emulate the up of all joystick buttons // emulate the up of all joystick buttons
for (i = 0; i < JOYBUTTONS; i++) for (i = 0; i < JOYBUTTONS; i++)
{ {
event.data1 = KEY_2JOY1 + i; event.key = KEY_2JOY1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
// emulate the up of all joystick hats // emulate the up of all joystick hats
for (i = 0; i < JOYHATS*4; i++) for (i = 0; i < JOYHATS*4; i++)
{ {
event.data1 = KEY_2HAT1 + i; event.key = KEY_2HAT1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1270,7 +1270,7 @@ void I_ShutdownJoystick2(void)
event.type = ev_joystick2; event.type = ev_joystick2;
for (i = 0; i < JOYAXISSET; i++) for (i = 0; i < JOYAXISSET; i++)
{ {
event.data1 = i; event.key = i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1282,7 +1282,7 @@ void I_ShutdownJoystick2(void)
void I_GetJoystick2Events(void) void I_GetJoystick2Events(void)
{ {
static event_t event = {0,0,0,0}; static event_t event = {0,0,0,0,false};
INT32 i = 0; INT32 i = 0;
UINT64 joyhats = 0; UINT64 joyhats = 0;
#if 0 #if 0
@ -1321,7 +1321,7 @@ void I_GetJoystick2Events(void)
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2JOY1 + i; event.key = KEY_2JOY1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -1352,7 +1352,7 @@ void I_GetJoystick2Events(void)
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2HAT1 + i; event.key = KEY_2HAT1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -1364,7 +1364,7 @@ void I_GetJoystick2Events(void)
for (i = JOYAXISSET - 1; i >= 0; i--) for (i = JOYAXISSET - 1; i >= 0; i--)
{ {
event.data1 = i; event.key = i;
if (i*2 + 1 <= JoyInfo2.axises) if (i*2 + 1 <= JoyInfo2.axises)
axisx = SDL_JoystickGetAxis(JoyInfo2.dev, i*2 + 0); axisx = SDL_JoystickGetAxis(JoyInfo2.dev, i*2 + 0);
else axisx = 0; else axisx = 0;
@ -1380,17 +1380,17 @@ void I_GetJoystick2Events(void)
{ {
// gamepad control type, on or off, live or die // gamepad control type, on or off, live or die
if (axisx < -(JOYAXISRANGE/2)) if (axisx < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (axisx > (JOYAXISRANGE/2)) else if (axisx > (JOYAXISRANGE/2))
event.data2 = 1; event.x = 1;
else else
event.data2 = 0; event.x = 0;
if (axisy < -(JOYAXISRANGE/2)) if (axisy < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (axisy > (JOYAXISRANGE/2)) else if (axisy > (JOYAXISRANGE/2))
event.data3 = 1; event.y = 1;
else else
event.data3 = 0; event.y = 0;
} }
else else
{ {
@ -1404,8 +1404,8 @@ void I_GetJoystick2Events(void)
#endif #endif
// analog control style , just send the raw data // analog control style , just send the raw data
event.data2 = axisx; // x axis event.x = axisx; // x axis
event.data3 = axisy; // y axis event.y = axisy; // y axis
} }
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1804,7 +1804,7 @@ void I_GetMouseEvents(void)
if (!(button & (1<<j))) //keyup if (!(button & (1<<j))) //keyup
{ {
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2MOUSE1+j; event.key = KEY_2MOUSE1+j;
D_PostEvent(&event); D_PostEvent(&event);
om2b ^= 1 << j; om2b ^= 1 << j;
} }
@ -1814,18 +1814,18 @@ void I_GetMouseEvents(void)
if (button & (1<<j)) if (button & (1<<j))
{ {
event.type = ev_keydown; event.type = ev_keydown;
event.data1 = KEY_2MOUSE1+j; event.key = KEY_2MOUSE1+j;
D_PostEvent(&event); D_PostEvent(&event);
om2b ^= 1 << j; om2b ^= 1 << j;
} }
} }
} }
event.data2 = ((SINT8)mdata[1])+((SINT8)mdata[3]); event.x = ((SINT8)mdata[1])+((SINT8)mdata[3]);
event.data3 = ((SINT8)mdata[2])+((SINT8)mdata[4]); event.y = ((SINT8)mdata[2])+((SINT8)mdata[4]);
if (event.data2 && event.data3) if (event.x && event.y)
{ {
event.type = ev_mouse2; event.type = ev_mouse2;
event.data1 = 0; event.key = 0;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -1867,7 +1867,7 @@ static void I_ShutdownMouse2(void)
for (i = 0; i < MOUSEBUTTONS; i++) for (i = 0; i < MOUSEBUTTONS; i++)
{ {
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2MOUSE1+i; event.key = KEY_2MOUSE1+i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1958,7 +1958,7 @@ void I_GetMouseEvents(void)
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2MOUSE1+i; event.key = KEY_2MOUSE1+i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -1966,10 +1966,10 @@ void I_GetMouseEvents(void)
if (handlermouse2x != 0 || handlermouse2y != 0) if (handlermouse2x != 0 || handlermouse2y != 0)
{ {
event.type = ev_mouse2; event.type = ev_mouse2;
event.data1 = 0; event.key = 0;
// event.data1 = buttons; // not needed // event.key = buttons; // not needed
event.data2 = handlermouse2x << 1; event.x = handlermouse2x << 1;
event.data3 = handlermouse2y << 1; event.y = handlermouse2y << 1;
handlermouse2x = 0; handlermouse2x = 0;
handlermouse2y = 0; handlermouse2y = 0;

View file

@ -73,6 +73,8 @@
#include "../console.h" #include "../console.h"
#include "../command.h" #include "../command.h"
#include "../r_main.h" #include "../r_main.h"
#include "../lua_script.h"
#include "../lua_libs.h"
#include "../lua_hook.h" #include "../lua_hook.h"
#include "sdlmain.h" #include "sdlmain.h"
#ifdef HWRENDER #ifdef HWRENDER
@ -372,6 +374,8 @@ static boolean IgnoreMouse(void)
if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION && if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION &&
gamestate != GS_CONTINUING && gamestate != GS_CUTSCENE) gamestate != GS_CONTINUING && gamestate != GS_CUTSCENE)
return true; return true;
if (!mousegrabbedbylua)
return true;
return false; return false;
} }
@ -663,8 +667,9 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type)
{ {
return; return;
} }
event.data1 = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode); event.key = Impl_SDL_Scancode_To_Keycode(evt.keysym.scancode);
if (event.data1) D_PostEvent(&event); event.repeated = (evt.repeat != 0);
if (event.key) D_PostEvent(&event);
} }
static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
@ -742,15 +747,15 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
} }
else return; else return;
if (evt.button == SDL_BUTTON_MIDDLE) if (evt.button == SDL_BUTTON_MIDDLE)
event.data1 = KEY_MOUSE1+2; event.key = KEY_MOUSE1+2;
else if (evt.button == SDL_BUTTON_RIGHT) else if (evt.button == SDL_BUTTON_RIGHT)
event.data1 = KEY_MOUSE1+1; event.key = KEY_MOUSE1+1;
else if (evt.button == SDL_BUTTON_LEFT) else if (evt.button == SDL_BUTTON_LEFT)
event.data1 = KEY_MOUSE1; event.key = KEY_MOUSE1;
else if (evt.button == SDL_BUTTON_X1) else if (evt.button == SDL_BUTTON_X1)
event.data1 = KEY_MOUSE1+3; event.key = KEY_MOUSE1+3;
else if (evt.button == SDL_BUTTON_X2) else if (evt.button == SDL_BUTTON_X2)
event.data1 = KEY_MOUSE1+4; event.key = KEY_MOUSE1+4;
if (event.type == ev_keyup || event.type == ev_keydown) if (event.type == ev_keyup || event.type == ev_keydown)
{ {
D_PostEvent(&event); D_PostEvent(&event);
@ -766,17 +771,17 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt)
if (evt.y > 0) if (evt.y > 0)
{ {
event.data1 = KEY_MOUSEWHEELUP; event.key = KEY_MOUSEWHEELUP;
event.type = ev_keydown; event.type = ev_keydown;
} }
if (evt.y < 0) if (evt.y < 0)
{ {
event.data1 = KEY_MOUSEWHEELDOWN; event.key = KEY_MOUSEWHEELDOWN;
event.type = ev_keydown; event.type = ev_keydown;
} }
if (evt.y == 0) if (evt.y == 0)
{ {
event.data1 = 0; event.key = 0;
event.type = ev_keyup; event.type = ev_keyup;
} }
if (event.type == ev_keyup || event.type == ev_keydown) if (event.type == ev_keyup || event.type == ev_keydown)
@ -795,7 +800,7 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev); joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev);
evt.axis++; evt.axis++;
event.data1 = event.data2 = event.data3 = INT32_MAX; event.key = event.x = event.y = INT32_MAX;
if (evt.which == joyid[0]) if (evt.which == joyid[0])
{ {
@ -812,14 +817,14 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
//vaule //vaule
if (evt.axis%2) if (evt.axis%2)
{ {
event.data1 = evt.axis / 2; event.key = evt.axis / 2;
event.data2 = SDLJoyAxis(evt.value, event.type); event.x = SDLJoyAxis(evt.value, event.type);
} }
else else
{ {
evt.axis--; evt.axis--;
event.data1 = evt.axis / 2; event.key = evt.axis / 2;
event.data3 = SDLJoyAxis(evt.value, event.type); event.y = SDLJoyAxis(evt.value, event.type);
} }
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -839,11 +844,11 @@ static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt)
if (evt.which == joyid[0]) if (evt.which == joyid[0])
{ {
event.data1 = KEY_HAT1 + (evt.hat*4); event.key = KEY_HAT1 + (evt.hat*4);
} }
else if (evt.which == joyid[1]) else if (evt.which == joyid[1])
{ {
event.data1 = KEY_2HAT1 + (evt.hat*4); event.key = KEY_2HAT1 + (evt.hat*4);
} }
else return; else return;
@ -862,11 +867,11 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
if (evt.which == joyid[0]) if (evt.which == joyid[0])
{ {
event.data1 = KEY_JOY1; event.key = KEY_JOY1;
} }
else if (evt.which == joyid[1]) else if (evt.which == joyid[1])
{ {
event.data1 = KEY_2JOY1; event.key = KEY_2JOY1;
} }
else return; else return;
if (type == SDL_JOYBUTTONUP) if (type == SDL_JOYBUTTONUP)
@ -880,7 +885,7 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
else return; else return;
if (evt.button < JOYBUTTONS) if (evt.button < JOYBUTTONS)
{ {
event.data1 += evt.button; event.key += evt.button;
} }
else return; else return;
@ -1084,9 +1089,9 @@ void I_GetEvent(void)
SDL_GetWindowSize(window, &wwidth, &wheight); SDL_GetWindowSize(window, &wwidth, &wheight);
//SDL_memset(&event, 0, sizeof(event_t)); //SDL_memset(&event, 0, sizeof(event_t));
event.type = ev_mouse; event.type = ev_mouse;
event.data1 = 0; event.key = 0;
event.data2 = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth)); event.x = (INT32)lround(mousemovex * ((float)wwidth / (float)realwidth));
event.data3 = (INT32)lround(mousemovey * ((float)wheight / (float)realheight)); event.y = (INT32)lround(mousemovey * ((float)wheight / (float)realheight));
D_PostEvent(&event); D_PostEvent(&event);
} }

View file

@ -9,7 +9,7 @@
/// \file /// \file
/// \brief SDL Mixer interface for sound /// \brief SDL Mixer interface for sound
#ifdef HAVE_LIBGME #ifdef HAVE_GME
#ifdef HAVE_ZLIB #ifdef HAVE_ZLIB
#ifndef _MSC_VER #ifndef _MSC_VER
#ifndef _LARGEFILE64_SOURCE #ifndef _LARGEFILE64_SOURCE
@ -27,7 +27,7 @@
#include <zlib.h> #include <zlib.h>
#endif // HAVE_ZLIB #endif // HAVE_ZLIB
#endif // HAVE_LIBGME #endif // HAVE_GME
#include "../doomdef.h" #include "../doomdef.h"
#include "../doomstat.h" // menuactive #include "../doomstat.h" // menuactive
@ -73,11 +73,11 @@
#define MUS_MODPLUG MUS_MODPLUG_UNUSED #define MUS_MODPLUG MUS_MODPLUG_UNUSED
#endif #endif
#ifdef HAVE_LIBGME #ifdef HAVE_GME
#include "gme/gme.h" #include "gme/gme.h"
#define GME_TREBLE 5.0f #define GME_TREBLE 5.0f
#define GME_BASS 1.0f #define GME_BASS 1.0f
#endif // HAVE_LIBGME #endif // HAVE_GME
static UINT16 BUFFERSIZE = 2048; static UINT16 BUFFERSIZE = 2048;
static UINT16 SAMPLERATE = 44100; static UINT16 SAMPLERATE = 44100;
@ -110,7 +110,7 @@ static INT32 fading_id;
static void (*fading_callback)(void); static void (*fading_callback)(void);
static boolean fading_nocleanup; static boolean fading_nocleanup;
#ifdef HAVE_LIBGME #ifdef HAVE_GME
static Music_Emu *gme; static Music_Emu *gme;
static UINT16 current_track; static UINT16 current_track;
#endif #endif
@ -220,7 +220,7 @@ static void var_cleanup(void)
internal_volume = 100; internal_volume = 100;
} }
#if defined (HAVE_LIBGME) && defined (HAVE_ZLIB) #if defined (HAVE_GME) && defined (HAVE_ZLIB)
static const char* get_zlib_error(int zErr) static const char* get_zlib_error(int zErr)
{ {
switch (zErr) switch (zErr)
@ -318,7 +318,7 @@ void I_ShutdownSound(void)
SDL_QuitSubSystem(SDL_INIT_AUDIO); SDL_QuitSubSystem(SDL_INIT_AUDIO);
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
gme_delete(gme); gme_delete(gme);
#endif #endif
@ -453,7 +453,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
void *lump; void *lump;
Mix_Chunk *chunk; Mix_Chunk *chunk;
SDL_RWops *rw; SDL_RWops *rw;
#ifdef HAVE_LIBGME #ifdef HAVE_GME
Music_Emu *emu; Music_Emu *emu;
gme_info_t *info; gme_info_t *info;
#endif #endif
@ -473,7 +473,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
} }
// Not a doom sound? Try something else. // Not a doom sound? Try something else.
#ifdef HAVE_LIBGME #ifdef HAVE_GME
// VGZ format // VGZ format
if (((UINT8 *)lump)[0] == 0x1F if (((UINT8 *)lump)[0] == 0x1F
&& ((UINT8 *)lump)[1] == 0x8B) && ((UINT8 *)lump)[1] == 0x8B)
@ -729,7 +729,7 @@ static UINT32 music_fade(UINT32 interval, void *param)
} }
} }
#ifdef HAVE_LIBGME #ifdef HAVE_GME
static void mix_gme(void *udata, Uint8 *stream, int len) static void mix_gme(void *udata, Uint8 *stream, int len)
{ {
int i; int i;
@ -797,7 +797,7 @@ void I_ShutdownMusic(void)
musictype_t I_SongType(void) musictype_t I_SongType(void)
{ {
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
return MU_GME; return MU_GME;
else else
@ -828,7 +828,7 @@ musictype_t I_SongType(void)
boolean I_SongPlaying(void) boolean I_SongPlaying(void)
{ {
return ( return (
#ifdef HAVE_LIBGME #ifdef HAVE_GME
(I_SongType() == MU_GME && gme) || (I_SongType() == MU_GME && gme) ||
#endif #endif
#ifdef HAVE_OPENMPT #ifdef HAVE_OPENMPT
@ -851,7 +851,7 @@ boolean I_SetSongSpeed(float speed)
{ {
if (speed > 250.0f) if (speed > 250.0f)
speed = 250.0f; //limit speed up to 250x speed = 250.0f; //limit speed up to 250x
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
{ {
SDL_LockAudio(); SDL_LockAudio();
@ -893,7 +893,7 @@ UINT32 I_GetSongLength(void)
{ {
INT32 length; INT32 length;
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
{ {
gme_info_t *info; gme_info_t *info;
@ -963,7 +963,7 @@ boolean I_SetSongLoopPoint(UINT32 looppoint)
UINT32 I_GetSongLoopPoint(void) UINT32 I_GetSongLoopPoint(void)
{ {
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
{ {
INT32 looppoint; INT32 looppoint;
@ -992,7 +992,7 @@ UINT32 I_GetSongLoopPoint(void)
boolean I_SetSongPosition(UINT32 position) boolean I_SetSongPosition(UINT32 position)
{ {
UINT32 length; UINT32 length;
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
{ {
// this is unstable, so fail silently // this is unstable, so fail silently
@ -1055,7 +1055,7 @@ boolean I_SetSongPosition(UINT32 position)
UINT32 I_GetSongPosition(void) UINT32 I_GetSongPosition(void)
{ {
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
{ {
INT32 position = gme_tell(gme); INT32 position = gme_tell(gme);
@ -1124,7 +1124,7 @@ boolean I_LoadSong(char *data, size_t len)
SDL_RWops *rw; SDL_RWops *rw;
if (music if (music
#ifdef HAVE_LIBGME #ifdef HAVE_GME
|| gme || gme
#endif #endif
#ifdef HAVE_OPENMPT #ifdef HAVE_OPENMPT
@ -1136,7 +1136,7 @@ boolean I_LoadSong(char *data, size_t len)
// always do this whether or not a music already exists // always do this whether or not a music already exists
var_cleanup(); var_cleanup();
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if ((UINT8)data[0] == 0x1F if ((UINT8)data[0] == 0x1F
&& (UINT8)data[1] == 0x8B) && (UINT8)data[1] == 0x8B)
{ {
@ -1271,7 +1271,7 @@ void I_UnloadSong(void)
{ {
I_StopSong(); I_StopSong();
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
{ {
gme_delete(gme); gme_delete(gme);
@ -1294,7 +1294,7 @@ void I_UnloadSong(void)
boolean I_PlaySong(boolean looping) boolean I_PlaySong(boolean looping)
{ {
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
{ {
gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
@ -1360,7 +1360,7 @@ void I_StopSong(void)
if (!fading_nocleanup) if (!fading_nocleanup)
I_StopFadingSong(); I_StopFadingSong();
#ifdef HAVE_LIBGME #ifdef HAVE_GME
if (gme) if (gme)
{ {
Mix_HookMusic(NULL, NULL); Mix_HookMusic(NULL, NULL);
@ -1433,7 +1433,7 @@ void I_SetMusicVolume(UINT8 volume)
boolean I_SetSongTrack(int track) boolean I_SetSongTrack(int track)
{ {
#ifdef HAVE_LIBGME #ifdef HAVE_GME
// If the specified track is within the number of tracks playing, then change it // If the specified track is within the number of tracks playing, then change it
if (gme) if (gme)
{ {

View file

@ -43,6 +43,7 @@
#endif #endif
#include "lua_hud.h" #include "lua_hud.h"
#include "lua_hook.h"
UINT16 objectsdrawn = 0; UINT16 objectsdrawn = 0;
@ -1391,7 +1392,7 @@ void ST_drawTitleCard(void)
lt_lasttic = lt_ticker; lt_lasttic = lt_ticker;
luahook: luahook:
LUAh_TitleCardHUD(stplyr); LUA_HUDHOOK(titlecard);
} }
// //
@ -2732,7 +2733,7 @@ static void ST_overlayDrawer(void)
ST_drawPowerupHUD(); // same as it ever was... ST_drawPowerupHUD(); // same as it ever was...
if (!(netgame || multiplayer) || !hu_showscores) if (!(netgame || multiplayer) || !hu_showscores)
LUAh_GameHUD(stplyr); LUA_HUDHOOK(game);
// draw level title Tails // draw level title Tails
if (stagetitle && (!WipeInAction) && (!WipeStageTitle)) if (stagetitle && (!WipeInAction) && (!WipeStageTitle))

View file

@ -809,13 +809,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
} }
// Draws a patch cropped and scaled to arbitrary size. // Draws a patch cropped and scaled to arbitrary size.
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
{ {
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t);
UINT32 alphalevel = 0; UINT32 alphalevel = 0;
// boolean flip = false; // boolean flip = false;
fixed_t col, ofs, colfrac, rowfrac, fdup; fixed_t col, ofs, colfrac, rowfrac, fdup, vdup;
INT32 dupx, dupy; INT32 dupx, dupy;
const column_t *column; const column_t *column;
UINT8 *desttop, *dest; UINT8 *desttop, *dest;
@ -830,7 +830,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
//if (rendermode != render_soft && !con_startup) // Not this again //if (rendermode != render_soft && !con_startup) // Not this again
if (rendermode == render_opengl) if (rendermode == render_opengl)
{ {
HWR_DrawCroppedPatch(patch,x,y,pscale,scrn,sx,sy,w,h); HWR_DrawCroppedPatch(patch,x,y,pscale,vscale,scrn,colormap,sx,sy,w,h);
return; return;
} }
#endif #endif
@ -857,31 +857,56 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
} }
} }
// only use one dup, to avoid stretching (har har) v_colormap = NULL;
dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); if (colormap)
fdup = FixedMul(dupx<<FRACBITS, pscale); {
colfrac = FixedDiv(FRACUNIT, fdup); v_colormap = colormap;
rowfrac = FixedDiv(FRACUNIT, fdup); patchdrawfunc = (v_translevel) ? transmappedpdraw : mappedpdraw;
}
dupx = vid.dupx;
dupy = vid.dupy;
if (scrn & V_SCALEPATCHMASK) switch ((scrn & V_SCALEPATCHMASK) >> V_SCALEPATCHSHIFT)
{
case 1: // V_NOSCALEPATCH
dupx = dupy = 1;
break;
case 2: // V_SMALLSCALEPATCH
dupx = vid.smalldupx;
dupy = vid.smalldupy;
break;
case 3: // V_MEDSCALEPATCH
dupx = vid.meddupx;
dupy = vid.meddupy;
break;
default:
break;
}
// only use one dup, to avoid stretching (har har)
dupx = dupy = (dupx < dupy ? dupx : dupy);
fdup = vdup = FixedMul(dupx<<FRACBITS, pscale);
if (vscale != pscale)
vdup = FixedMul(dupx<<FRACBITS, vscale);
colfrac = FixedDiv(FRACUNIT, fdup);
rowfrac = FixedDiv(FRACUNIT, vdup);
y -= FixedMul(patch->topoffset<<FRACBITS, pscale);
x -= FixedMul(patch->leftoffset<<FRACBITS, pscale); x -= FixedMul(patch->leftoffset<<FRACBITS, pscale);
y -= FixedMul(patch->topoffset<<FRACBITS, vscale);
if (splitscreen && (scrn & V_PERPLAYER)) if (splitscreen && (scrn & V_PERPLAYER))
{ {
fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1); fixed_t adjusty = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1);
fdup >>= 1; vdup >>= 1;
rowfrac <<= 1; rowfrac <<= 1;
y >>= 1; y >>= 1;
sy >>= 1;
h >>= 1;
#ifdef QUADS #ifdef QUADS
if (splitscreen > 1) // 3 or 4 players if (splitscreen > 1) // 3 or 4 players
{ {
fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1)); fixed_t adjustx = ((scrn & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)<<(FRACBITS-1));
fdup >>= 1;
colfrac <<= 1; colfrac <<= 1;
x >>= 1; x >>= 1;
sx >>= 1;
w >>= 1;
if (stplyr == &players[displayplayer]) if (stplyr == &players[displayplayer])
{ {
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
@ -897,7 +922,6 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT))) if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8; perplayershuffle |= 8;
x += adjustx; x += adjustx;
sx += adjustx;
scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT; scrn &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
} }
else if (stplyr == &players[thirddisplayplayer]) else if (stplyr == &players[thirddisplayplayer])
@ -907,7 +931,6 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT))) if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 4; perplayershuffle |= 4;
y += adjusty; y += adjusty;
sy += adjusty;
scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT; scrn &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
} }
else //if (stplyr == &players[fourthdisplayplayer]) else //if (stplyr == &players[fourthdisplayplayer])
@ -917,9 +940,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT))) if (!(scrn & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
perplayershuffle |= 8; perplayershuffle |= 8;
x += adjustx; x += adjustx;
sx += adjustx;
y += adjusty; y += adjusty;
sy += adjusty;
scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT; scrn &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
} }
} }
@ -938,7 +959,6 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) if (!(scrn & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
perplayershuffle |= 2; perplayershuffle |= 2;
y += adjusty; y += adjusty;
sy += adjusty;
scrn &= ~V_SNAPTOTOP; scrn &= ~V_SNAPTOTOP;
} }
} }
@ -951,7 +971,8 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
deststop = desttop + vid.rowbytes * vid.height; deststop = desttop + vid.rowbytes * vid.height;
if (scrn & V_NOSCALESTART) { if (scrn & V_NOSCALESTART)
{
x >>= FRACBITS; x >>= FRACBITS;
y >>= FRACBITS; y >>= FRACBITS;
desttop += (y*vid.width) + x; desttop += (y*vid.width) + x;
@ -999,7 +1020,38 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
desttop += (y*vid.width) + x; desttop += (y*vid.width) + x;
} }
for (col = sx<<FRACBITS; (col>>FRACBITS) < patch->width && ((col>>FRACBITS) - sx) < w; col += colfrac, ++x, desttop++) // Auto-crop at splitscreen borders!
if (splitscreen && (scrn & V_PERPLAYER))
{
#ifdef QUADS
if (splitscreen > 1) // 3 or 4 players
{
#error Auto-cropping doesnt take quadscreen into account! Fix it!
// Hint: For player 1/2, copy player 1's code below. For player 3/4, copy player 2's code below
// For player 1/3 and 2/4, hijack the X wrap prevention lines? That's probably easiest
}
else
#endif
// 2 players
{
if (stplyr == &players[displayplayer]) // Player 1's screen, crop at the bottom
{
// Just put a big old stop sign halfway through the screen
deststop -= vid.rowbytes * (vid.height>>1);
}
else //if (stplyr == &players[secondarydisplayplayer]) // Player 2's screen, crop at the top
{
if (y < (vid.height>>1)) // If the top is above the border
{
sy += ((vid.height>>1) - y) * rowfrac; // Start further down on the patch
h -= ((vid.height>>1) - y) * rowfrac; // Draw less downwards from the start
desttop += ((vid.height>>1) - y) * vid.width; // Start drawing at the border
}
}
}
}
for (col = sx; (col>>FRACBITS) < patch->width && (col - sx) < w; col += colfrac, ++x, desttop++)
{ {
INT32 topdelta, prevdelta = -1; INT32 topdelta, prevdelta = -1;
if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION) if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION)
@ -1016,15 +1068,15 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
prevdelta = topdelta; prevdelta = topdelta;
source = (const UINT8 *)(column) + 3; source = (const UINT8 *)(column) + 3;
dest = desttop; dest = desttop;
if (topdelta-sy > 0) if ((topdelta<<FRACBITS)-sy > 0)
{ {
dest += FixedInt(FixedMul((topdelta-sy)<<FRACBITS,fdup))*vid.width; dest += FixedInt(FixedMul((topdelta<<FRACBITS)-sy,vdup))*vid.width;
ofs = 0; ofs = 0;
} }
else else
ofs = (sy-topdelta)<<FRACBITS; ofs = sy-(topdelta<<FRACBITS);
for (; dest < deststop && (ofs>>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) for (; dest < deststop && (ofs>>FRACBITS) < column->length && ((ofs - sy) + (topdelta<<FRACBITS)) < h; ofs += rowfrac)
{ {
if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION)
*dest = patchdrawfunc(dest, source, ofs); *dest = patchdrawfunc(dest, source, ofs);

View file

@ -165,7 +165,7 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
#define V_DrawSciencePatch(x,y,s,p,sc) V_DrawFixedPatch(x,y,sc,s,p,NULL) #define V_DrawSciencePatch(x,y,s,p,sc) V_DrawFixedPatch(x,y,sc,s,p,NULL)
#define V_DrawFixedPatch(x,y,sc,s,p,c) V_DrawStretchyFixedPatch(x,y,sc,sc,s,p,c) #define V_DrawFixedPatch(x,y,sc,s,p,c) V_DrawStretchyFixedPatch(x,y,sc,sc,s,p,c)
void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap); void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor); void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor);

View file

@ -50,16 +50,17 @@
#include "filesrch.h" #include "filesrch.h"
#include "i_video.h" // rendermode #include "d_main.h"
#include "d_netfil.h" #include "d_netfil.h"
#include "dehacked.h"
#include "d_clisrv.h" #include "d_clisrv.h"
#include "dehacked.h"
#include "r_defs.h" #include "r_defs.h"
#include "r_data.h" #include "r_data.h"
#include "r_textures.h" #include "r_textures.h"
#include "r_patch.h" #include "r_patch.h"
#include "r_picformats.h" #include "r_picformats.h"
#include "i_system.h" #include "i_system.h"
#include "i_video.h" // rendermode
#include "md5.h" #include "md5.h"
#include "lua_script.h" #include "lua_script.h"
#ifdef SCANTHINGS #ifdef SCANTHINGS
@ -117,10 +118,15 @@ void W_Shutdown(void)
{ {
wadfile_t *wad = wadfiles[numwadfiles]; wadfile_t *wad = wadfiles[numwadfiles];
if (wad->handle)
fclose(wad->handle); fclose(wad->handle);
Z_Free(wad->filename); Z_Free(wad->filename);
if (wad->path)
Z_Free(wad->path);
while (wad->numlumps--) while (wad->numlumps--)
{ {
if (wad->lumpinfo[wad->numlumps].diskpath)
Z_Free(wad->lumpinfo[wad->numlumps].diskpath);
Z_Free(wad->lumpinfo[wad->numlumps].longname); Z_Free(wad->lumpinfo[wad->numlumps].longname);
Z_Free(wad->lumpinfo[wad->numlumps].fullname); Z_Free(wad->lumpinfo[wad->numlumps].fullname);
} }
@ -421,6 +427,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
{ {
lump_p->position = LONG(fileinfo->filepos); lump_p->position = LONG(fileinfo->filepos);
lump_p->size = lump_p->disksize = LONG(fileinfo->size); lump_p->size = lump_p->disksize = LONG(fileinfo->size);
lump_p->diskpath = NULL;
if (compressed) // wad is compressed, lump might be if (compressed) // wad is compressed, lump might be
{ {
UINT32 realsize = 0; UINT32 realsize = 0;
@ -602,6 +609,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
lump_p->position = zentry.offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position lump_p->position = zentry.offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position
lump_p->disksize = zentry.compsize; lump_p->disksize = zentry.compsize;
lump_p->diskpath = NULL;
lump_p->size = zentry.size; lump_p->size = zentry.size;
fullname = malloc(zentry.namelen + 1); fullname = malloc(zentry.namelen + 1);
@ -679,6 +687,114 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
return lumpinfo; return lumpinfo;
} }
static INT32 CheckPathsNotEqual(const char *path1, const char *path2)
{
INT32 stat = samepaths(path1, path2);
if (stat == 1)
return 0;
else if (stat < 0)
return -1;
return 1;
}
// Returns 1 if the path is valid, 0 if not, and -1 if there was an error.
INT32 W_IsPathToFolderValid(const char *path)
{
INT32 stat;
// Remove path delimiters.
const char *p = path + (strlen(path) - 1);
while (*p == '\\' || *p == '/' || *p == ':')
{
p--;
if (p < path)
return 0;
}
// Check if the path is a directory.
stat = pathisdirectory(path);
if (stat == 0)
return 0;
else if (stat < 0)
{
// The path doesn't exist, so it can't be a directory.
if (direrror == ENOENT)
return 0;
return -1;
}
// Don't add your home, you sodding tic tac.
stat = CheckPathsNotEqual(path, srb2home);
if (stat != 1)
return stat;
// Do the same checks for SRB2's path, and the current directory.
stat = CheckPathsNotEqual(path, srb2path);
if (stat != 1)
return stat;
stat = CheckPathsNotEqual(path, ".");
if (stat != 1)
return stat;
return 1;
}
// Checks if the combination of the first path and the second path are valid.
// If they are, the concatenated path is returned.
static char *CheckConcatFolderPath(const char *startpath, const char *path)
{
if (concatpaths(path, startpath) == 1)
{
char *fn;
if (startpath)
{
size_t len = strlen(startpath) + strlen(path) + strlen(PATHSEP) + 1;
fn = ZZ_Alloc(len);
snprintf(fn, len, "%s" PATHSEP "%s", startpath, path);
}
else
fn = Z_StrDup(path);
return fn;
}
return NULL;
}
// Looks for the first valid full path for a folder.
// Returns NULL if the folder doesn't exist, or it isn't valid.
char *W_GetFullFolderPath(const char *path)
{
// Check the path by itself first.
char *fn = CheckConcatFolderPath(NULL, path);
if (fn)
return fn;
#define checkpath(startpath) \
fn = CheckConcatFolderPath(startpath, path); \
if (fn) \
return fn
checkpath(srb2home); // Then, look in srb2home.
checkpath(srb2path); // Now, look in srb2path.
checkpath("."); // Finally, look in the current directory.
#undef checkpath
return NULL;
}
// Loads files from a folder into a lumpinfo structure.
static lumpinfo_t *ResGetLumpsFolder(const char *path, UINT16 *nlmp, UINT16 *nfolders)
{
return getdirectoryfiles(path, nlmp, nfolders);
}
static UINT16 W_InitFileError (const char *filename, boolean exitworthy) static UINT16 W_InitFileError (const char *filename, boolean exitworthy)
{ {
if (exitworthy) if (exitworthy)
@ -694,6 +810,19 @@ static UINT16 W_InitFileError (const char *filename, boolean exitworthy)
return INT16_MAX; return INT16_MAX;
} }
static void W_ReadFileShaders(wadfile_t *wadfile)
{
#ifdef HWRENDER
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
{
HWR_LoadCustomShadersFromFile(numwadfiles - 1, W_FileHasFolders(wadfile));
HWR_CompileShaders();
}
#else
(void)wadfile;
#endif
}
// Allocate a wadfile, setup the lumpinfo (directory) and // Allocate a wadfile, setup the lumpinfo (directory) and
// lumpcache, add the wadfile to the current active wadfiles // lumpcache, add the wadfile to the current active wadfiles
// //
@ -760,7 +889,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
// see PutFileNeeded in d_netfil.c // see PutFileNeeded in d_netfil.c
if ((important = !important)) if ((important = !important))
{ {
packetsize = packetsizetally + nameonlylength(filename) + 22; packetsize = packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE;
if (packetsize > MAXFILENEEDED*sizeof(UINT8)) if (packetsize > MAXFILENEEDED*sizeof(UINT8))
{ {
@ -788,7 +917,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
{ {
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
if (important) if (important)
packetsizetally -= nameonlylength(filename) + 22; packetsizetally -= nameonlylength(filename) + FILENEEDEDSIZE;
if (handle) if (handle)
fclose(handle); fclose(handle);
return W_InitFileError(filename, false); return W_InitFileError(filename, false);
@ -831,9 +960,11 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
// //
wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL); wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL);
wadfile->filename = Z_StrDup(filename); wadfile->filename = Z_StrDup(filename);
wadfile->path = NULL;
wadfile->type = type; wadfile->type = type;
wadfile->handle = handle; wadfile->handle = handle;
wadfile->numlumps = (UINT16)numlumps; wadfile->numlumps = numlumps;
wadfile->foldercount = 0;
wadfile->lumpinfo = lumpinfo; wadfile->lumpinfo = lumpinfo;
wadfile->important = important; wadfile->important = important;
fseek(handle, 0, SEEK_END); fseek(handle, 0, SEEK_END);
@ -856,14 +987,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
wadfiles[numwadfiles] = wadfile; wadfiles[numwadfiles] = wadfile;
numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded
#ifdef HWRENDER
// Read shaders from file // Read shaders from file
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) W_ReadFileShaders(wadfile);
{
HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3));
HWR_CompileShaders();
}
#endif // HWRENDER
// TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now. // TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now.
switch (wadfile->type) switch (wadfile->type)
@ -889,6 +1014,180 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
return wadfile->numlumps; return wadfile->numlumps;
} }
//
// Loads a folder as a WAD.
//
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
{
lumpinfo_t *lumpinfo = NULL;
wadfile_t *wadfile;
UINT16 numlumps = 0;
UINT16 foldercount;
size_t i;
char *fn, *fullpath;
const char *p;
int important;
INT32 stat;
if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier
if (refreshdirname)
Z_Free(refreshdirname);
if (dirmenu)
refreshdirname = Z_StrDup(path);
else
refreshdirname = NULL;
if (numwadfiles >= MAX_WADFILES)
{
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
refreshdirmenu |= REFRESHDIR_MAX;
return W_InitFileError(path, startup);
}
important = 0; // ???
/// \todo Implement a W_VerifyFolder.
if ((important = !important))
{
size_t packetsize = packetsizetally + strlen(path) + FILENEEDEDSIZE;
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
{
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
refreshdirmenu |= REFRESHDIR_MAX;
return W_InitFileError(path, startup);
}
packetsizetally = packetsize;
}
// Remove path delimiters.
p = path + (strlen(path) - 1);
while (*p == '\\' || *p == '/' || *p == ':')
{
p--;
if (p < path)
{
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), path);
return W_InitFileError(path, startup);
}
}
p++;
// Allocate the new path name.
i = (p - path) + 1;
fn = ZZ_Alloc(i);
strlcpy(fn, path, i);
// Don't add an empty path.
if (M_IsStringEmpty(fn))
{
CONS_Alert(CONS_ERROR, M_GetText("Folder name is empty\n"));
Z_Free(fn);
if (startup)
return W_InitFileError("A folder", true);
else
return W_InitFileError("a folder", false);
}
// Check if the path is valid.
stat = W_IsPathToFolderValid(fn);
if (stat != 1)
{
if (stat == 0)
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), fn);
else if (stat < 0)
{
#ifndef AVOID_ERRNO
CONS_Alert(CONS_ERROR, M_GetText("Could not stat %s: %s\n"), fn, strerror(direrror));
#else
CONS_Alert(CONS_ERROR, M_GetText("Could not stat %s\n"), fn);
#endif
}
Z_Free(fn);
return W_InitFileError(path, startup);
}
// Get the full path for this folder.
fullpath = W_GetFullFolderPath(fn);
if (fullpath == NULL)
{
CONS_Alert(CONS_ERROR, M_GetText("Path %s is invalid\n"), fn);
Z_Free(fn);
return W_InitFileError(path, startup);
}
// Check if the folder is already added.
for (i = 0; i < numwadfiles; i++)
{
if (wadfiles[i]->type != RET_FOLDER)
continue;
if (samepaths(wadfiles[i]->path, fullpath) > 0)
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), path);
if (important)
packetsizetally -= strlen(path) + FILENEEDEDSIZE;
Z_Free(fn);
Z_Free(fullpath);
return W_InitFileError(path, false);
}
}
lumpinfo = ResGetLumpsFolder(fullpath, &numlumps, &foldercount);
if (lumpinfo == NULL)
{
if (!numlumps)
CONS_Alert(CONS_ERROR, M_GetText("Folder %s is empty\n"), path);
else if (numlumps == UINT16_MAX)
CONS_Alert(CONS_ERROR, M_GetText("Folder %s contains too many files\n"), path);
else
CONS_Alert(CONS_ERROR, M_GetText("Unknown error enumerating files from folder %s\n"), path);
Z_Free(fn);
Z_Free(fullpath);
return W_InitFileError(path, startup);
}
if (important && !mainfile)
G_SetGameModified(true);
wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL);
wadfile->filename = fn;
wadfile->path = fullpath;
wadfile->type = RET_FOLDER;
wadfile->handle = NULL;
wadfile->numlumps = numlumps;
wadfile->foldercount = foldercount;
wadfile->lumpinfo = lumpinfo;
wadfile->important = important;
// Irrelevant.
wadfile->filesize = 0;
memset(wadfile->md5sum, 0x00, 16);
Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache);
Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache);
CONS_Printf(M_GetText("Added folder %s (%u files, %u folders)\n"), fn, numlumps, foldercount);
wadfiles[numwadfiles] = wadfile;
numwadfiles++;
W_ReadFileShaders(wadfile);
W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile);
W_InvalidateLumpnumCache();
return wadfile->numlumps;
}
/** Tries to load a series of files. /** Tries to load a series of files.
* All files are wads unless they have an extension of ".soc" or ".lua". * All files are wads unless they have an extension of ".soc" or ".lua".
* *
@ -900,11 +1199,18 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
*/ */
void W_InitMultipleFiles(char **filenames) void W_InitMultipleFiles(char **filenames)
{ {
// will be realloced as lumps are added
for (; *filenames; filenames++) for (; *filenames; filenames++)
{ {
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames); const char *fn = (*filenames);
W_InitFile(*filenames, numwadfiles < mainwads, true); char pathsep = fn[strlen(fn) - 1];
boolean mainfile = (numwadfiles < mainwads);
//CONS_Debug(DBG_SETUP, "Loading %s\n", fn);
if (pathsep == '\\' || pathsep == '/')
W_InitFolder(fn, mainfile, true);
else
W_InitFile(fn, mainfile, true);
} }
} }
@ -1178,7 +1484,7 @@ lumpnum_t W_CheckNumForMap(const char *name)
if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8)) if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
return (i<<16) + lumpNum; return (i<<16) + lumpNum;
} }
else if (wadfiles[i]->type == RET_PK3) else if (W_FileHasFolders(wadfiles[i]))
{ {
lumpNum = W_CheckNumForFolderStartPK3("maps/", i, 0); lumpNum = W_CheckNumForFolderStartPK3("maps/", i, 0);
if (lumpNum != INT16_MAX) if (lumpNum != INT16_MAX)
@ -1276,9 +1582,46 @@ UINT8 W_LumpExists(const char *name)
size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump) size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump)
{ {
lumpinfo_t *l;
if (!TestValidLump(wad, lump)) if (!TestValidLump(wad, lump))
return 0; return 0;
return wadfiles[wad]->lumpinfo[lump].size;
l = wadfiles[wad]->lumpinfo + lump;
// Open the external file for this lump, if the WAD is a folder.
if (wadfiles[wad]->type == RET_FOLDER)
{
// pathisdirectory calls stat, so if anything wrong has happened,
// this is the time to be aware of it.
INT32 stat = pathisdirectory(l->diskpath);
if (stat < 0)
{
#ifndef AVOID_ERRNO
if (direrror == ENOENT)
I_Error("W_LumpLengthPwad: file %s doesn't exist", l->diskpath);
else
I_Error("W_LumpLengthPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
#else
I_Error("W_LumpLengthPwad: could not access %s", l->diskpath);
#endif
}
else if (stat == 1) // Path is a folder.
return 0;
else
{
FILE *handle = fopen(l->diskpath, "rb");
if (handle == NULL)
I_Error("W_LumpLengthPwad: could not open file %s", l->diskpath);
fseek(handle, 0, SEEK_END);
l->size = l->disksize = ftell(handle);
fclose(handle);
}
}
return l->size;
} }
/** Returns the buffer size needed to load the given lump. /** Returns the buffer size needed to load the given lump.
@ -1297,7 +1640,7 @@ size_t W_LumpLength(lumpnum_t lumpnum)
// //
boolean W_IsLumpWad(lumpnum_t lumpnum) boolean W_IsLumpWad(lumpnum_t lumpnum)
{ {
if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3) if (W_FileHasFolders(wadfiles[WADFILENUM(lumpnum)]))
{ {
const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname; const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname;
@ -1315,7 +1658,7 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
// //
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump) boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
{ {
if (wadfiles[wad]->type == RET_PK3) if (W_FileHasFolders(wadfiles[wad]))
{ {
const char *name = wadfiles[wad]->lumpinfo[lump].fullname; const char *name = wadfiles[wad]->lumpinfo[lump].fullname;
@ -1365,17 +1708,55 @@ void zerr(int ret)
*/ */
size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset) size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset)
{ {
size_t lumpsize; size_t lumpsize, bytesread;
lumpinfo_t *l; lumpinfo_t *l;
FILE *handle; FILE *handle = NULL;
if (!TestValidLump(wad,lump)) if (!TestValidLump(wad, lump))
return 0; return 0;
l = wadfiles[wad]->lumpinfo + lump;
// Open the external file for this lump, if the WAD is a folder.
if (wadfiles[wad]->type == RET_FOLDER)
{
// pathisdirectory calls stat, so if anything wrong has happened,
// this is the time to be aware of it.
INT32 stat = pathisdirectory(l->diskpath);
if (stat < 0)
{
#ifndef AVOID_ERRNO
if (direrror == ENOENT)
I_Error("W_ReadLumpHeaderPwad: file %s doesn't exist", l->diskpath);
else
I_Error("W_ReadLumpHeaderPwad: could not stat %s: %s", l->diskpath, strerror(direrror));
#else
I_Error("W_ReadLumpHeaderPwad: could not access %s", l->diskpath);
#endif
}
else if (stat == 1) // Path is a folder.
return 0;
else
{
handle = fopen(l->diskpath, "rb");
if (handle == NULL)
I_Error("W_ReadLumpHeaderPwad: could not open file %s", l->diskpath);
// Find length of file
fseek(handle, 0, SEEK_END);
l->size = l->disksize = ftell(handle);
}
}
lumpsize = wadfiles[wad]->lumpinfo[lump].size; lumpsize = wadfiles[wad]->lumpinfo[lump].size;
// empty resource (usually markers like S_START, F_END ..) // empty resource (usually markers like S_START, F_END ..)
if (!lumpsize || lumpsize<offset) if (!lumpsize || lumpsize<offset)
{
if (wadfiles[wad]->type == RET_FOLDER)
fclose(handle);
return 0; return 0;
}
// zero size means read all the lump // zero size means read all the lump
if (!size || size+offset > lumpsize) if (!size || size+offset > lumpsize)
@ -1383,7 +1764,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
// Let's get the raw lump data. // Let's get the raw lump data.
// We setup the desired file handle to read the lump data. // We setup the desired file handle to read the lump data.
l = wadfiles[wad]->lumpinfo + lump; if (wadfiles[wad]->type != RET_FOLDER)
handle = wadfiles[wad]->handle; handle = wadfiles[wad]->handle;
fseek(handle, (long)(l->position + offset), SEEK_SET); fseek(handle, (long)(l->position + offset), SEEK_SET);
@ -1391,16 +1772,14 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
switch(wadfiles[wad]->lumpinfo[lump].compression) switch(wadfiles[wad]->lumpinfo[lump].compression)
{ {
case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read. case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read.
bytesread = fread(dest, 1, size, handle);
if (wadfiles[wad]->type == RET_FOLDER)
fclose(handle);
#ifdef NO_PNG_LUMPS #ifdef NO_PNG_LUMPS
{
size_t bytesread = fread(dest, 1, size, handle);
if (Picture_IsLumpPNG((UINT8 *)dest, bytesread)) if (Picture_IsLumpPNG((UINT8 *)dest, bytesread))
Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename); Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename);
return bytesread;
}
#else
return fread(dest, 1, size, handle);
#endif #endif
return bytesread;
case CM_LZF: // Is it LZF compressed? Used by ZWADs. case CM_LZF: // Is it LZF compressed? Used by ZWADs.
{ {
#ifdef ZWAD #ifdef ZWAD

View file

@ -69,6 +69,7 @@ typedef struct
char name[9]; // filelump_t name[] e.g. "LongEntr" char name[9]; // filelump_t name[] e.g. "LongEntr"
char *longname; // e.g. "LongEntryName" char *longname; // e.g. "LongEntryName"
char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension" char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension"
char *diskpath; // path to the file e.g. "/usr/games/srb2/Addon/Folder/Subfolder/LongEntryName.extension"
size_t size; // real (uncompressed) size size_t size; // real (uncompressed) size
compmethod compression; // lump compression method compmethod compression; // lump compression method
} lumpinfo_t; } lumpinfo_t;
@ -109,17 +110,19 @@ typedef enum restype
RET_SOC, RET_SOC,
RET_LUA, RET_LUA,
RET_PK3, RET_PK3,
RET_FOLDER,
RET_UNKNOWN, RET_UNKNOWN,
} restype_t; } restype_t;
typedef struct wadfile_s typedef struct wadfile_s
{ {
char *filename; char *filename, *path;
restype_t type; restype_t type;
lumpinfo_t *lumpinfo; lumpinfo_t *lumpinfo;
lumpcache_t *lumpcache; lumpcache_t *lumpcache;
lumpcache_t *patchcache; lumpcache_t *patchcache;
UINT16 numlumps; // this wad's number of resources UINT16 numlumps; // this wad's number of resources
UINT16 foldercount; // folder count
FILE *handle; FILE *handle;
UINT32 filesize; // for network UINT32 filesize; // for network
UINT8 md5sum[16]; UINT8 md5sum[16];
@ -127,7 +130,7 @@ typedef struct wadfile_s
boolean important; // also network - !W_VerifyNMUSlumps boolean important; // also network - !W_VerifyNMUSlumps
} wadfile_t; } wadfile_t;
#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word #define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad file number in upper word
#define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad #define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad
extern UINT16 numwadfiles; extern UINT16 numwadfiles;
@ -141,10 +144,17 @@ void W_Shutdown(void);
FILE *W_OpenWadFile(const char **filename, boolean useerrors); FILE *W_OpenWadFile(const char **filename, boolean useerrors);
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error // Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup); UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup);
// Adds a folder as a file
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup);
// W_InitMultipleFiles exits if a file was not found, but not if all is okay. // W_InitMultipleFiles exits if a file was not found, but not if all is okay.
void W_InitMultipleFiles(char **filenames); void W_InitMultipleFiles(char **filenames);
#define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3 || (wadfile)->type == RET_FOLDER)
INT32 W_IsPathToFolderValid(const char *path);
char *W_GetFullFolderPath(const char *path);
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump); const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
const char *W_CheckNameForNum(lumpnum_t lumpnum); const char *W_CheckNameForNum(lumpnum_t lumpnum);

View file

@ -188,11 +188,11 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
ev.type = ev_keydown; ev.type = ev_keydown;
handleKeyDoom: handleKeyDoom:
ev.data1 = 0; ev.key = 0;
if (wParam == VK_PAUSE) if (wParam == VK_PAUSE)
// intercept PAUSE key // intercept PAUSE key
{ {
ev.data1 = KEY_PAUSE; ev.key = KEY_PAUSE;
} }
else if (!keyboard_started) else if (!keyboard_started)
// post some keys during the game startup // post some keys during the game startup
@ -201,14 +201,14 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
{ {
switch (wParam) switch (wParam)
{ {
case VK_ESCAPE: ev.data1 = KEY_ESCAPE; break; case VK_ESCAPE: ev.key = KEY_ESCAPE; break;
case VK_RETURN: ev.data1 = KEY_ENTER; break; case VK_RETURN: ev.key = KEY_ENTER; break;
case VK_SHIFT: ev.data1 = KEY_LSHIFT; break; case VK_SHIFT: ev.key = KEY_LSHIFT; break;
default: ev.data1 = MapVirtualKey((DWORD)wParam,2); // convert in to char default: ev.key = MapVirtualKey((DWORD)wParam,2); // convert in to char
} }
} }
if (ev.data1) if (ev.key)
D_PostEvent (&ev); D_PostEvent (&ev);
return 0; return 0;
@ -240,7 +240,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
if (nodinput) if (nodinput)
{ {
ev.type = ev_keyup; ev.type = ev_keyup;
ev.data1 = KEY_MOUSE1 + 3 + HIWORD(wParam); ev.key = KEY_MOUSE1 + 3 + HIWORD(wParam);
D_PostEvent(&ev); D_PostEvent(&ev);
return TRUE; return TRUE;
} }
@ -249,7 +249,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
if (nodinput) if (nodinput)
{ {
ev.type = ev_keydown; ev.type = ev_keydown;
ev.data1 = KEY_MOUSE1 + 3 + HIWORD(wParam); ev.key = KEY_MOUSE1 + 3 + HIWORD(wParam);
D_PostEvent(&ev); D_PostEvent(&ev);
return TRUE; return TRUE;
} }
@ -258,9 +258,9 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
//I_OutputMsg("MW_WHEEL dispatched.\n"); //I_OutputMsg("MW_WHEEL dispatched.\n");
ev.type = ev_keydown; ev.type = ev_keydown;
if ((INT16)HIWORD(wParam) > 0) if ((INT16)HIWORD(wParam) > 0)
ev.data1 = KEY_MOUSEWHEELUP; ev.key = KEY_MOUSEWHEELUP;
else else
ev.data1 = KEY_MOUSEWHEELDOWN; ev.key = KEY_MOUSEWHEELDOWN;
D_PostEvent(&ev); D_PostEvent(&ev);
break; break;
@ -271,7 +271,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
case WM_CLOSE: case WM_CLOSE:
PostQuitMessage(0); //to quit while in-game PostQuitMessage(0); //to quit while in-game
ev.data1 = KEY_ESCAPE; //to exit network synchronization ev.key = KEY_ESCAPE; //to exit network synchronization
ev.type = ev_keydown; ev.type = ev_keydown;
D_PostEvent (&ev); D_PostEvent (&ev);
return 0; return 0;

View file

@ -322,20 +322,20 @@ static inline VOID I_GetConsoleEvents(VOID)
{ {
case VK_ESCAPE: case VK_ESCAPE:
case VK_TAB: case VK_TAB:
ev.data1 = KEY_NULL; ev.key = KEY_NULL;
break; break;
case VK_SHIFT: case VK_SHIFT:
ev.data1 = KEY_LSHIFT; ev.key = KEY_LSHIFT;
break; break;
case VK_RETURN: case VK_RETURN:
entering_con_command = false; entering_con_command = false;
/* FALLTHRU */ /* FALLTHRU */
default: default:
ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char ev.key = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char
} }
if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t)) if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t))
{ {
if (ev.data1 && ev.data1 != KEY_LSHIFT && ev.data1 != KEY_RSHIFT) if (ev.key && ev.key != KEY_LSHIFT && ev.key != KEY_RSHIFT)
{ {
#ifdef UNICODE #ifdef UNICODE
WriteConsole(co, &input.Event.KeyEvent.uChar.UnicodeChar, 1, &t, NULL); WriteConsole(co, &input.Event.KeyEvent.uChar.UnicodeChar, 1, &t, NULL);
@ -356,13 +356,13 @@ static inline VOID I_GetConsoleEvents(VOID)
switch (input.Event.KeyEvent.wVirtualKeyCode) switch (input.Event.KeyEvent.wVirtualKeyCode)
{ {
case VK_SHIFT: case VK_SHIFT:
ev.data1 = KEY_LSHIFT; ev.key = KEY_LSHIFT;
break; break;
default: default:
break; break;
} }
} }
if (ev.data1) D_PostEvent(&ev); if (ev.key) D_PostEvent(&ev);
break; break;
case MOUSE_EVENT: case MOUSE_EVENT:
case WINDOW_BUFFER_SIZE_EVENT: case WINDOW_BUFFER_SIZE_EVENT:
@ -945,7 +945,7 @@ static void I_ShutdownMouse2(VOID)
for (i = 0; i < MOUSEBUTTONS; i++) for (i = 0; i < MOUSEBUTTONS; i++)
{ {
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2MOUSE1 + i; event.key = KEY_2MOUSE1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1135,14 +1135,14 @@ VOID I_GetSysMouseEvents(INT mouse_state)
if ((mouse_state & (1 << i)) && !(old_mouse_state & (1 << i))) if ((mouse_state & (1 << i)) && !(old_mouse_state & (1 << i)))
{ {
event.type = ev_keydown; event.type = ev_keydown;
event.data1 = KEY_MOUSE1 + i; event.key = KEY_MOUSE1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
// check if button released // check if button released
if (!(mouse_state & (1 << i)) && (old_mouse_state & (1 << i))) if (!(mouse_state & (1 << i)) && (old_mouse_state & (1 << i)))
{ {
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_MOUSE1 + i; event.key = KEY_MOUSE1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -1156,9 +1156,9 @@ VOID I_GetSysMouseEvents(INT mouse_state)
if (xmickeys || ymickeys) if (xmickeys || ymickeys)
{ {
event.type = ev_mouse; event.type = ev_mouse;
event.data1 = 0; event.key = 0;
event.data2 = xmickeys; event.x = xmickeys;
event.data3 = -ymickeys; event.y = -ymickeys;
D_PostEvent(&event); D_PostEvent(&event);
SetCursorPos(center_x, center_y); SetCursorPos(center_x, center_y);
} }
@ -1240,7 +1240,7 @@ static void I_ShutdownMouse(void)
for (i = 0; i < MOUSEBUTTONS; i++) for (i = 0; i < MOUSEBUTTONS; i++)
{ {
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_MOUSE1 + i; event.key = KEY_MOUSE1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
if (nodinput) if (nodinput)
@ -1281,7 +1281,7 @@ void I_GetMouseEvents(void)
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2MOUSE1 + i; event.key = KEY_2MOUSE1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -1289,9 +1289,9 @@ void I_GetMouseEvents(void)
if (handlermouse2x || handlermouse2y) if (handlermouse2x || handlermouse2y)
{ {
event.type = ev_mouse2; event.type = ev_mouse2;
event.data1 = 0; event.key = 0;
event.data2 = handlermouse2x<<1; event.x = handlermouse2x<<1;
event.data3 = -handlermouse2y<<1; event.y = -handlermouse2y<<1;
handlermouse2x = 0; handlermouse2x = 0;
handlermouse2y = 0; handlermouse2y = 0;
@ -1330,7 +1330,7 @@ getBufferedData:
else else
event.type = ev_keyup; // Button up event.type = ev_keyup; // Button up
event.data1 = rgdod[d].dwOfs - DIMOFS_BUTTON0 + KEY_MOUSE1; event.key = rgdod[d].dwOfs - DIMOFS_BUTTON0 + KEY_MOUSE1;
D_PostEvent(&event); D_PostEvent(&event);
} }
else if (rgdod[d].dwOfs == DIMOFS_X) else if (rgdod[d].dwOfs == DIMOFS_X)
@ -1342,9 +1342,9 @@ getBufferedData:
{ {
// z-axes the wheel // z-axes the wheel
if ((int)rgdod[d].dwData > 0) if ((int)rgdod[d].dwData > 0)
event.data1 = KEY_MOUSEWHEELUP; event.key = KEY_MOUSEWHEELUP;
else else
event.data1 = KEY_MOUSEWHEELDOWN; event.key = KEY_MOUSEWHEELDOWN;
event.type = ev_keydown; event.type = ev_keydown;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -1354,9 +1354,9 @@ getBufferedData:
if (xmickeys || ymickeys) if (xmickeys || ymickeys)
{ {
event.type = ev_mouse; event.type = ev_mouse;
event.data1 = 0; event.key = 0;
event.data2 = xmickeys; event.x = xmickeys;
event.data3 = -ymickeys; event.y = -ymickeys;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -2395,14 +2395,14 @@ static VOID I_ShutdownJoystick(VOID)
// emulate the up of all joystick buttons // emulate the up of all joystick buttons
for (i = 0;i < JOYBUTTONS;i++) for (i = 0;i < JOYBUTTONS;i++)
{ {
event.data1 = KEY_JOY1+i; event.key = KEY_JOY1+i;
D_PostEvent(&event); D_PostEvent(&event);
} }
// emulate the up of all joystick hats // emulate the up of all joystick hats
for (i = 0;i < JOYHATS*4;i++) for (i = 0;i < JOYHATS*4;i++)
{ {
event.data1 = KEY_HAT1+i; event.key = KEY_HAT1+i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -2410,7 +2410,7 @@ static VOID I_ShutdownJoystick(VOID)
event.type = ev_joystick; event.type = ev_joystick;
for (i = 0;i < JOYAXISSET; i++) for (i = 0;i < JOYAXISSET; i++)
{ {
event.data1 = i; event.key = i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -2460,14 +2460,14 @@ static VOID I_ShutdownJoystick2(VOID)
// emulate the up of all joystick buttons // emulate the up of all joystick buttons
for (i = 0;i < JOYBUTTONS;i++) for (i = 0;i < JOYBUTTONS;i++)
{ {
event.data1 = KEY_2JOY1+i; event.key = KEY_2JOY1+i;
D_PostEvent(&event); D_PostEvent(&event);
} }
// emulate the up of all joystick hats // emulate the up of all joystick hats
for (i = 0;i < JOYHATS*4;i++) for (i = 0;i < JOYHATS*4;i++)
{ {
event.data1 = KEY_2HAT1+i; event.key = KEY_2HAT1+i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -2475,7 +2475,7 @@ static VOID I_ShutdownJoystick2(VOID)
event.type = ev_joystick2; event.type = ev_joystick2;
for (i = 0;i < JOYAXISSET; i++) for (i = 0;i < JOYAXISSET; i++)
{ {
event.data1 = i; event.key = i;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -2598,7 +2598,7 @@ acquire:
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_JOY1 + i; event.key = KEY_JOY1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -2618,7 +2618,7 @@ acquire:
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_HAT1 + i; event.key = KEY_HAT1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -2627,7 +2627,7 @@ acquire:
// send joystick axis positions // send joystick axis positions
event.type = ev_joystick; event.type = ev_joystick;
event.data1 = event.data2 = event.data3 = 0; event.key = event.x = event.y = 0;
if (Joystick.bGamepadStyle) if (Joystick.bGamepadStyle)
{ {
@ -2635,29 +2635,29 @@ acquire:
if (JoyInfo.X) if (JoyInfo.X)
{ {
if (js.lX < -(JOYAXISRANGE/2)) if (js.lX < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (js.lX > JOYAXISRANGE/2) else if (js.lX > JOYAXISRANGE/2)
event.data2 = 1; event.x = 1;
} }
if (JoyInfo.Y) if (JoyInfo.Y)
{ {
if (js.lY < -(JOYAXISRANGE/2)) if (js.lY < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (js.lY > JOYAXISRANGE/2) else if (js.lY > JOYAXISRANGE/2)
event.data3 = 1; event.y = 1;
} }
} }
else else
{ {
// analog control style, just send the raw data // analog control style, just send the raw data
if (JoyInfo.X) event.data2 = js.lX; // x axis if (JoyInfo.X) event.x = js.lX; // x axis
if (JoyInfo.Y) event.data3 = js.lY; // y axis if (JoyInfo.Y) event.y = js.lY; // y axis
} }
D_PostEvent(&event); D_PostEvent(&event);
#if JOYAXISSET > 1 #if JOYAXISSET > 1
event.data1 = 1; event.key = 1;
event.data2 = event.data3 = 0; event.x = event.y = 0;
if (Joystick.bGamepadStyle) if (Joystick.bGamepadStyle)
{ {
@ -2665,30 +2665,30 @@ acquire:
if (JoyInfo.Z) if (JoyInfo.Z)
{ {
if (js.lZ < -(JOYAXISRANGE/2)) if (js.lZ < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (js.lZ > JOYAXISRANGE/2) else if (js.lZ > JOYAXISRANGE/2)
event.data2 = 1; event.x = 1;
} }
if (JoyInfo.Rx) if (JoyInfo.Rx)
{ {
if (js.lRx < -(JOYAXISRANGE/2)) if (js.lRx < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (js.lRx > JOYAXISRANGE/2) else if (js.lRx > JOYAXISRANGE/2)
event.data3 = 1; event.y = 1;
} }
} }
else else
{ {
// analog control style, just send the raw data // analog control style, just send the raw data
if (JoyInfo.Z) event.data2 = js.lZ; // z axis if (JoyInfo.Z) event.x = js.lZ; // z axis
if (JoyInfo.Rx) event.data3 = js.lRx; // rx axis if (JoyInfo.Rx) event.y = js.lRx; // rx axis
} }
D_PostEvent(&event); D_PostEvent(&event);
#endif #endif
#if JOYAXISSET > 2 #if JOYAXISSET > 2
event.data1 = 2; event.key = 2;
event.data2 = event.data3 = 0; event.x = event.y = 0;
if (Joystick.bGamepadStyle) if (Joystick.bGamepadStyle)
{ {
@ -2696,53 +2696,53 @@ acquire:
if (JoyInfo.Rx) if (JoyInfo.Rx)
{ {
if (js.lRy < -(JOYAXISRANGE/2)) if (js.lRy < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (js.lRy > JOYAXISRANGE/2) else if (js.lRy > JOYAXISRANGE/2)
event.data2 = 1; event.x = 1;
} }
if (JoyInfo.Rz) if (JoyInfo.Rz)
{ {
if (js.lRz < -(JOYAXISRANGE/2)) if (js.lRz < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (js.lRz > JOYAXISRANGE/2) else if (js.lRz > JOYAXISRANGE/2)
event.data3 = 1; event.y = 1;
} }
} }
else else
{ {
// analog control style, just send the raw data // analog control style, just send the raw data
if (JoyInfo.Ry) event.data2 = js.lRy; // ry axis if (JoyInfo.Ry) event.x = js.lRy; // ry axis
if (JoyInfo.Rz) event.data3 = js.lRz; // rz axis if (JoyInfo.Rz) event.y = js.lRz; // rz axis
} }
D_PostEvent(&event); D_PostEvent(&event);
#endif #endif
#if JOYAXISSET > 3 #if JOYAXISSET > 3
event.data1 = 3; event.key = 3;
event.data2 = event.data3 = 0; event.x = event.y = 0;
if (Joystick.bGamepadStyle) if (Joystick.bGamepadStyle)
{ {
// gamepad control type, on or off, live or die // gamepad control type, on or off, live or die
if (JoyInfo.U) if (JoyInfo.U)
{ {
if (js.rglSlider[0] < -(JOYAXISRANGE/2)) if (js.rglSlider[0] < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (js.rglSlider[0] > JOYAXISRANGE/2) else if (js.rglSlider[0] > JOYAXISRANGE/2)
event.data2 = 1; event.x = 1;
} }
if (JoyInfo.V) if (JoyInfo.V)
{ {
if (js.rglSlider[1] < -(JOYAXISRANGE/2)) if (js.rglSlider[1] < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (js.rglSlider[1] > JOYAXISRANGE/2) else if (js.rglSlider[1] > JOYAXISRANGE/2)
event.data3 = 1; event.y = 1;
} }
} }
else else
{ {
// analog control style, just send the raw data // analog control style, just send the raw data
if (JoyInfo.U) event.data2 = js.rglSlider[0]; // U axis if (JoyInfo.U) event.x = js.rglSlider[0]; // U axis
if (JoyInfo.V) event.data3 = js.rglSlider[1]; // V axis if (JoyInfo.V) event.y = js.rglSlider[1]; // V axis
} }
D_PostEvent(&event); D_PostEvent(&event);
#endif #endif
@ -2842,7 +2842,7 @@ acquire:
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2JOY1 + i; event.key = KEY_2JOY1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -2862,7 +2862,7 @@ acquire:
event.type = ev_keydown; event.type = ev_keydown;
else else
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = KEY_2HAT1 + i; event.key = KEY_2HAT1 + i;
D_PostEvent(&event); D_PostEvent(&event);
} }
} }
@ -2871,7 +2871,7 @@ acquire:
// send joystick axis positions // send joystick axis positions
event.type = ev_joystick2; event.type = ev_joystick2;
event.data1 = event.data2 = event.data3 = 0; event.key = event.x = event.y = 0;
if (Joystick2.bGamepadStyle) if (Joystick2.bGamepadStyle)
{ {
@ -2879,29 +2879,29 @@ acquire:
if (JoyInfo2.X) if (JoyInfo2.X)
{ {
if (js.lX < -(JOYAXISRANGE/2)) if (js.lX < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (js.lX > JOYAXISRANGE/2) else if (js.lX > JOYAXISRANGE/2)
event.data2 = 1; event.x = 1;
} }
if (JoyInfo2.Y) if (JoyInfo2.Y)
{ {
if (js.lY < -(JOYAXISRANGE/2)) if (js.lY < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (js.lY > JOYAXISRANGE/2) else if (js.lY > JOYAXISRANGE/2)
event.data3 = 1; event.y = 1;
} }
} }
else else
{ {
// analog control style, just send the raw data // analog control style, just send the raw data
if (JoyInfo2.X) event.data2 = js.lX; // x axis if (JoyInfo2.X) event.x = js.lX; // x axis
if (JoyInfo2.Y) event.data3 = js.lY; // y axis if (JoyInfo2.Y) event.y = js.lY; // y axis
} }
D_PostEvent(&event); D_PostEvent(&event);
#if JOYAXISSET > 1 #if JOYAXISSET > 1
event.data1 = 1; event.key = 1;
event.data2 = event.data3 = 0; event.x = event.y = 0;
if (Joystick2.bGamepadStyle) if (Joystick2.bGamepadStyle)
{ {
@ -2909,30 +2909,30 @@ acquire:
if (JoyInfo2.Z) if (JoyInfo2.Z)
{ {
if (js.lZ < -(JOYAXISRANGE/2)) if (js.lZ < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (js.lZ > JOYAXISRANGE/2) else if (js.lZ > JOYAXISRANGE/2)
event.data2 = 1; event.x = 1;
} }
if (JoyInfo2.Rx) if (JoyInfo2.Rx)
{ {
if (js.lRx < -(JOYAXISRANGE/2)) if (js.lRx < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (js.lRx > JOYAXISRANGE/2) else if (js.lRx > JOYAXISRANGE/2)
event.data3 = 1; event.y = 1;
} }
} }
else else
{ {
// analog control style, just send the raw data // analog control style, just send the raw data
if (JoyInfo2.Z) event.data2 = js.lZ; // z axis if (JoyInfo2.Z) event.x = js.lZ; // z axis
if (JoyInfo2.Rx) event.data3 = js.lRx; // rx axis if (JoyInfo2.Rx) event.y = js.lRx; // rx axis
} }
D_PostEvent(&event); D_PostEvent(&event);
#endif #endif
#if JOYAXISSET > 2 #if JOYAXISSET > 2
event.data1 = 2; event.key = 2;
event.data2 = event.data3 = 0; event.x = event.y = 0;
if (Joystick2.bGamepadStyle) if (Joystick2.bGamepadStyle)
{ {
@ -2940,53 +2940,53 @@ acquire:
if (JoyInfo2.Rx) if (JoyInfo2.Rx)
{ {
if (js.lRy < -(JOYAXISRANGE/2)) if (js.lRy < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (js.lRy > JOYAXISRANGE/2) else if (js.lRy > JOYAXISRANGE/2)
event.data2 = 1; event.x = 1;
} }
if (JoyInfo2.Rz) if (JoyInfo2.Rz)
{ {
if (js.lRz < -(JOYAXISRANGE/2)) if (js.lRz < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (js.lRz > JOYAXISRANGE/2) else if (js.lRz > JOYAXISRANGE/2)
event.data3 = 1; event.y = 1;
} }
} }
else else
{ {
// analog control style, just send the raw data // analog control style, just send the raw data
if (JoyInfo2.Ry) event.data2 = js.lRy; // ry axis if (JoyInfo2.Ry) event.x = js.lRy; // ry axis
if (JoyInfo2.Rz) event.data3 = js.lRz; // rz axis if (JoyInfo2.Rz) event.y = js.lRz; // rz axis
} }
D_PostEvent(&event); D_PostEvent(&event);
#endif #endif
#if JOYAXISSET > 3 #if JOYAXISSET > 3
event.data1 = 3; event.key = 3;
event.data2 = event.data3 = 0; event.x = event.y = 0;
if (Joystick2.bGamepadStyle) if (Joystick2.bGamepadStyle)
{ {
// gamepad control type, on or off, live or die // gamepad control type, on or off, live or die
if (JoyInfo2.U) if (JoyInfo2.U)
{ {
if (js.rglSlider[0] < -(JOYAXISRANGE/2)) if (js.rglSlider[0] < -(JOYAXISRANGE/2))
event.data2 = -1; event.x = -1;
else if (js.rglSlider[0] > JOYAXISRANGE/2) else if (js.rglSlider[0] > JOYAXISRANGE/2)
event.data2 = 1; event.x = 1;
} }
if (JoyInfo2.V) if (JoyInfo2.V)
{ {
if (js.rglSlider[1] < -(JOYAXISRANGE/2)) if (js.rglSlider[1] < -(JOYAXISRANGE/2))
event.data3 = -1; event.y = -1;
else if (js.rglSlider[1] > JOYAXISRANGE/2) else if (js.rglSlider[1] > JOYAXISRANGE/2)
event.data3 = 1; event.y = 1;
} }
} }
else else
{ {
// analog control style, just send the raw data // analog control style, just send the raw data
if (JoyInfo2.U) event.data2 = js.rglSlider[0]; // U axis if (JoyInfo2.U) event.x = js.rglSlider[0]; // U axis
if (JoyInfo2.V) event.data3 = js.rglSlider[1]; // V axis if (JoyInfo2.V) event.y = js.rglSlider[1]; // V axis
} }
D_PostEvent(&event); D_PostEvent(&event);
#endif #endif
@ -3194,7 +3194,7 @@ INT32 I_GetKey(void)
ev = &events[eventtail]; ev = &events[eventtail];
eventtail = (eventtail+1) & (MAXEVENTS-1); eventtail = (eventtail+1) & (MAXEVENTS-1);
if (ev->type == ev_keydown || ev->type == ev_console) if (ev->type == ev_keydown || ev->type == ev_console)
return ev->data1; return ev->key;
else else
return 0; return 0;
} }
@ -3308,7 +3308,7 @@ static VOID I_GetKeyboardEvents(VOID)
if (!appActive && RepeatKeyCode) // Stop when lost focus if (!appActive && RepeatKeyCode) // Stop when lost focus
{ {
event.type = ev_keyup; event.type = ev_keyup;
event.data1 = RepeatKeyCode; event.key = RepeatKeyCode;
D_PostEvent(&event); D_PostEvent(&event);
RepeatKeyCode = 0; RepeatKeyCode = 0;
} }
@ -3363,9 +3363,9 @@ getBufferedData:
ch = rgdod[d].dwOfs & 0xFF; ch = rgdod[d].dwOfs & 0xFF;
if (ASCIINames[ch]) if (ASCIINames[ch])
event.data1 = ASCIINames[ch]; event.key = ASCIINames[ch];
else else
event.data1 = 0x80; event.key = 0x80;
D_PostEvent(&event); D_PostEvent(&event);
} }
@ -3378,7 +3378,7 @@ getBufferedData:
// delay is tripled for first repeating key // delay is tripled for first repeating key
RepeatKeyTics = hacktics + (KEY_REPEAT_DELAY*3); RepeatKeyTics = hacktics + (KEY_REPEAT_DELAY*3);
if (event.type == ev_keydown) // use the last event! if (event.type == ev_keydown) // use the last event!
RepeatKeyCode = event.data1; RepeatKeyCode = event.key;
} }
else else
{ {
@ -3386,7 +3386,7 @@ getBufferedData:
if (RepeatKeyCode && hacktics - RepeatKeyTics > KEY_REPEAT_DELAY) if (RepeatKeyCode && hacktics - RepeatKeyTics > KEY_REPEAT_DELAY)
{ {
event.type = ev_keydown; event.type = ev_keydown;
event.data1 = RepeatKeyCode; event.key = RepeatKeyCode;
D_PostEvent(&event); D_PostEvent(&event);
RepeatKeyTics = hacktics; RepeatKeyTics = hacktics;

View file

@ -212,7 +212,7 @@ static void Y_IntermissionTokenDrawer(void)
calc = (lowy - y)*2; calc = (lowy - y)*2;
if (calc > 0) if (calc > 0)
V_DrawCroppedPatch(32<<FRACBITS, y<<FRACBITS, FRACUNIT/2, 0, tokenicon, 0, 0, tokenicon->width, calc); V_DrawCroppedPatch(32<<FRACBITS, y<<FRACBITS, FRACUNIT/2, FRACUNIT/2, 0, tokenicon, NULL, 0, 0, tokenicon->width<<FRACBITS, calc<<FRACBITS);
} }
@ -430,7 +430,7 @@ void Y_IntermissionDrawer(void)
else if (bgtile) else if (bgtile)
V_DrawPatchFill(bgtile); V_DrawPatchFill(bgtile);
LUAh_IntermissionHUD(intertype == int_spec && stagefailed); LUA_HUDHOOK(intermission);
if (!LUA_HudEnabled(hud_intermissiontally)) if (!LUA_HudEnabled(hud_intermissiontally))
goto skiptallydrawer; goto skiptallydrawer;