make sure the capture command doesn't switch between gamedirs while capturing.

added dimension_default global to provide default dimensions. expected to be a (var) constant.
support setcustomskin in menuqc.
implement some considerations for win95, so it can actually run on that horrendously outdated system.
provide scr_autoid and r_showbbox-field info when running csqc.
ignore vid_restarts at the end of config.cfg files from other engines. in fte, these are at best redundant and at worst overrides user settings.
fix issue with latched cvars not flagging the config as modified.
path command always shows filenames properly.
fix some fteqcc inlining bugs.
added precaches command to display all active precaches.
added docs for mapcluster.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4881 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-06-04 06:15:14 +00:00
parent 4bfb34a8c0
commit f4d3df7bf5
62 changed files with 1042 additions and 431 deletions

View File

@ -1624,11 +1624,6 @@ help:
@-echo "vc - Attempts to use msvc8+ to compile. Note: uses profile guided optimisations. You must build+run the relevent profile target before a release target will compile properly. Debug doesn't care." @-echo "vc - Attempts to use msvc8+ to compile. Note: uses profile guided optimisations. You must build+run the relevent profile target before a release target will compile properly. Debug doesn't care."
@-echo "android, npfte, nacl targets explicitly cross compile, and should generally not be given an FTE_TARGET." @-echo "android, npfte, nacl targets explicitly cross compile, and should generally not be given an FTE_TARGET."
install:
-cp debug/*.* /opt/quake/
-cp release/*.* /opt/quake/
-cp profile/*.* /opt/quake
clean: clean:
-rm -f -r $(RELEASE_DIR) -rm -f -r $(RELEASE_DIR)
-rm -f -r $(DEBUG_DIR) -rm -f -r $(DEBUG_DIR)
@ -1847,3 +1842,16 @@ else
test -f libvorbis-$(VORBISVER).tar.gz || wget http://downloads.xiph.org/releases/vorbis/libvorbis-$(VORBISVER).tar.gz test -f libvorbis-$(VORBISVER).tar.gz || wget http://downloads.xiph.org/releases/vorbis/libvorbis-$(VORBISVER).tar.gz
-test -f libs-$(ARCH)/libvorbisfile.a || (cd libs-$(ARCH) && tar -xvzf ../libvorbis-$(VORBISVER).tar.gz && cd libvorbis-$(VORBISVER) && $(TOOLOVERRIDES) ./configure PKG_CONFIG= $(CONFIGARGS) --disable-oggtest --with-ogg-libraries=.. --with-ogg-includes=$(NATIVE_ABSBASE_DIR)/libs-$(ARCH)/libogg-$(OGGVER)/include && $(TOOLOVERRIDES) $(MAKE) && cp lib/.libs/libvorbis.a ../ && cp lib/.libs/libvorbisfile.a ../ ) -test -f libs-$(ARCH)/libvorbisfile.a || (cd libs-$(ARCH) && tar -xvzf ../libvorbis-$(VORBISVER).tar.gz && cd libvorbis-$(VORBISVER) && $(TOOLOVERRIDES) ./configure PKG_CONFIG= $(CONFIGARGS) --disable-oggtest --with-ogg-libraries=.. --with-ogg-includes=$(NATIVE_ABSBASE_DIR)/libs-$(ARCH)/libogg-$(OGGVER)/include && $(TOOLOVERRIDES) $(MAKE) && cp lib/.libs/libvorbis.a ../ && cp lib/.libs/libvorbisfile.a ../ )
endif endif
prefix ?= /usr/local
exec_prefix ?= $(prefix)
bindir ?= $(exec_prefix)/bin
sbindir ?= $(exec_prefix)/sbin
INSTALL ?= install
INSTALL_PROGRAM ?= $(INSTALL)
INSTALL_DATA ?= ${INSTALL} -m 644
install: sv-rel gl-rel mingl-rel qcc-rel
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqw $(DESTDIR)$(bindir)/fteqw
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqwsv $(DESTDIR)$(bindir)/fteqwsv
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqcc $(DESTDIR)$(bindir)/fteqcc

View File

@ -1101,10 +1101,10 @@ float CL_FilterTime (double time, float wantfps, qboolean ignoreserver) //now re
fps = bound (6.7, wantfps, fpscap); //we actually cap ourselves to 150msecs (1000/7 = 142) fps = bound (6.7, wantfps, fpscap); //we actually cap ourselves to 150msecs (1000/7 = 142)
} }
if (time < 1000 / fps) if (time < ceil(1000 / fps))
return 0; return 0;
return time - (1000 / fps); return time - ceil(1000 / fps);
} }
qboolean allowindepphys; qboolean allowindepphys;

View File

@ -333,6 +333,9 @@ CL_Quit_f
*/ */
void CL_Quit_f (void) void CL_Quit_f (void)
{ {
if (!host_initialized)
return;
if (forcesaveprompt && strcmp(Cmd_Argv(1), "force")) if (forcesaveprompt && strcmp(Cmd_Argv(1), "force"))
{ {
forcesaveprompt = false; forcesaveprompt = false;
@ -4586,7 +4589,7 @@ double Host_Frame (double time)
#endif #endif
Key_Dest_Has(kdm_menu) || Key_Dest_Has(kdm_menu) ||
Key_Dest_Has(kdm_editor) || Key_Dest_Has(kdm_editor) ||
cl.paused; cl.paused || !ActiveApp;
// TODO: check if minimized or unfocused // TODO: check if minimized or unfocused
//read packets early and always, so we don't have stuff waiting for reception quite so often. //read packets early and always, so we don't have stuff waiting for reception quite so often.
@ -5238,6 +5241,8 @@ void Host_Shutdown(void)
} }
host_initialized = false; host_initialized = false;
HTTP_CL_Terminate();
#ifdef PLUGINS #ifdef PLUGINS
Plug_Shutdown(false); Plug_Shutdown(false);
#endif #endif

View File

@ -1959,12 +1959,12 @@ typedef struct _TargaHeader {
#if defined(AVAIL_JPEGLIB) && !defined(NO_JPEG) #if defined(AVAIL_JPEGLIB) && !defined(NO_JPEG)
qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int screenwidth, int screenheight); qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int screenwidth, int screenheight);
#endif #endif
#ifdef AVAIL_PNGLIB #ifdef AVAIL_PNGLIB
int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, int height); int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qbyte *pixels, int width, int height);
#endif #endif
void WriteBMPFile(char *filename, qbyte *in, int width, int height); void WriteBMPFile(char *filename, enum fs_relative fsroot, qbyte *in, int width, int height);
/* /*
Find closest color in the palette for named color Find closest color in the palette for named color
@ -1999,9 +1999,9 @@ int MipColor(int r, int g, int b)
return best; return best;
} }
qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height) qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buffer, int width, int height)
{ {
int i, c, temp; int i, c, temp;
#if defined(AVAIL_PNGLIB) || defined(AVAIL_JPEGLIB) #if defined(AVAIL_PNGLIB) || defined(AVAIL_JPEGLIB)
extern cvar_t scr_sshot_compression; extern cvar_t scr_sshot_compression;
#endif #endif
@ -2016,14 +2016,14 @@ qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height
#ifdef AVAIL_PNGLIB #ifdef AVAIL_PNGLIB
if (!Q_strcasecmp(ext, "png")) if (!Q_strcasecmp(ext, "png"))
{ {
return Image_WritePNG(filename, scr_sshot_compression.value, rgb_buffer, width, height); return Image_WritePNG(filename, fsroot, scr_sshot_compression.value, rgb_buffer, width, height);
} }
else else
#endif #endif
#ifdef AVAIL_JPEGLIB #ifdef AVAIL_JPEGLIB
if (!Q_strcasecmp(ext, "jpeg") || !Q_strcasecmp(ext, "jpg")) if (!Q_strcasecmp(ext, "jpeg") || !Q_strcasecmp(ext, "jpg"))
{ {
return screenshotJPEG(filename, scr_sshot_compression.value, rgb_buffer, width, height); return screenshotJPEG(filename, fsroot, scr_sshot_compression.value, rgb_buffer, width, height);
} }
else else
#endif #endif
@ -2049,13 +2049,13 @@ qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height
} }
} }
WritePCXfile (filename, newbuf, width, height, width, host_basepal, false); WritePCXfile (filename, fsroot, newbuf, width, height, width, host_basepal, false);
} }
else if (!Q_strcasecmp(ext, "tga")) //tga else if (!Q_strcasecmp(ext, "tga")) //tga
{ {
vfsfile_t *vfs; vfsfile_t *vfs;
FS_CreatePath(filename, FS_GAMEONLY); FS_CreatePath(filename, fsroot);
vfs = FS_OpenVFS(filename, "wb", FS_GAMEONLY); vfs = FS_OpenVFS(filename, "wb", fsroot);
if (vfs) if (vfs)
{ {
unsigned char header[18]; unsigned char header[18];
@ -2144,7 +2144,7 @@ void SCR_ScreenShot_f (void)
rgbbuffer = VID_GetRGBInfo(0, &width, &height); rgbbuffer = VID_GetRGBInfo(0, &width, &height);
if (rgbbuffer) if (rgbbuffer)
{ {
if (SCR_ScreenShot(pcxname, rgbbuffer, width, height)) if (SCR_ScreenShot(pcxname, FS_GAMEONLY, rgbbuffer, width, height))
{ {
Con_Printf ("Wrote %s\n", sysname); Con_Printf ("Wrote %s\n", sysname);
BZ_Free(rgbbuffer); BZ_Free(rgbbuffer);
@ -2217,7 +2217,7 @@ void SCR_ScreenShot_Mega_f(void)
rgbbuffer = VID_GetRGBInfo(0, &width, &height); rgbbuffer = VID_GetRGBInfo(0, &width, &height);
if (rgbbuffer) if (rgbbuffer)
{ {
if (SCR_ScreenShot(filename, rgbbuffer, width, height)) if (SCR_ScreenShot(filename, FS_GAMEONLY, rgbbuffer, width, height))
{ {
char sysname[1024]; char sysname[1024];
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname)); FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
@ -2385,7 +2385,7 @@ qboolean SCR_RSShot (void)
Q_strncpyz(st, name.string, sizeof(st)); Q_strncpyz(st, name.string, sizeof(st));
SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 21, w); SCR_DrawStringToSnap (st, newbuf, w - strlen(st)*8, h - 21, w);
WritePCXfile ("snap.pcx", newbuf, w, h, w, host_basepal, true); WritePCXfile ("snap.pcx", FS_GAMEONLY, newbuf, w, h, w, host_basepal, true);
BZ_Free(newbuf); BZ_Free(newbuf);

View File

@ -977,7 +977,7 @@ error:
#ifndef NPFTE #ifndef NPFTE
int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, int height) int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qbyte *pixels, int width, int height)
{ {
char name[MAX_OSPATH]; char name[MAX_OSPATH];
int i; int i;
@ -987,7 +987,7 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i
png_byte **row_pointers; png_byte **row_pointers;
struct pngerr errctx; struct pngerr errctx;
if (!FS_NativePath(filename, FS_GAMEONLY, name, sizeof(name))) if (!FS_NativePath(filename, fsroot, name, sizeof(name)))
return false; return false;
if (!LibPNG_Init()) if (!LibPNG_Init())
@ -1533,7 +1533,7 @@ METHODDEF(void) jpeg_error_exit (j_common_ptr cinfo)
{ {
longjmp(((jpeg_error_mgr_wrapper *) cinfo->err)->setjmp_buffer, 1); longjmp(((jpeg_error_mgr_wrapper *) cinfo->err)->setjmp_buffer, 1);
} }
qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba
{ {
qbyte *buffer; qbyte *buffer;
vfsfile_t *outfile; vfsfile_t *outfile;
@ -1544,10 +1544,10 @@ qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int
if (!LIBJPEG_LOADED()) if (!LIBJPEG_LOADED())
return false; return false;
if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY))) if (!(outfile = FS_OpenVFS(filename, "wb", fsroot)))
{ {
FS_CreatePath (filename, FS_GAMEONLY); FS_CreatePath (filename, fsroot);
if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY))) if (!(outfile = FS_OpenVFS(filename, "wb", fsroot)))
{ {
Con_Printf("Error opening %s\n", filename); Con_Printf("Error opening %s\n", filename);
return false; return false;
@ -1632,7 +1632,7 @@ qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int
WritePCXfile WritePCXfile
============== ==============
*/ */
void WritePCXfile (const char *filename, qbyte *data, int width, int height, void WritePCXfile (const char *filename, enum fs_relative fsroot, qbyte *data, int width, int height,
int rowbytes, qbyte *palette, qboolean upload) //data is 8bit. int rowbytes, qbyte *palette, qboolean upload) //data is 8bit.
{ {
int i, j, length; int i, j, length;
@ -1695,7 +1695,7 @@ void WritePCXfile (const char *filename, qbyte *data, int width, int height,
if (upload) if (upload)
CL_StartUpload((void *)pcx, length); CL_StartUpload((void *)pcx, length);
else else
COM_WriteFile (filename, pcx, length); COM_WriteFile (filename, fsroot, pcx, length);
} }
#endif #endif

View File

@ -30,7 +30,6 @@ void Editor_Key(int key, int unicode);
void Key_ConsoleInsert(char *instext); void Key_ConsoleInsert(char *instext);
void Key_ClearTyping (void); void Key_ClearTyping (void);
#define KEY_MODIFIERSTATES 8
unsigned char *key_lines[CON_EDIT_LINES_MASK+1]; unsigned char *key_lines[CON_EDIT_LINES_MASK+1];
int key_linepos; int key_linepos;
int shift_down=false; int shift_down=false;
@ -1561,11 +1560,11 @@ int Key_StringToKeynum (const char *str, int *modifier)
if (!underscore || !underscore[1]) if (!underscore || !underscore[1])
break; //nothing afterwards or no underscore. break; //nothing afterwards or no underscore.
if (!strnicmp(str, "shift_", 6)) if (!strnicmp(str, "shift_", 6))
*modifier |= 1; *modifier |= KEY_MODIFIER_SHIFT;
else if (!strnicmp(str, "alt_", 4)) else if (!strnicmp(str, "alt_", 4))
*modifier |= 2; *modifier |= KEY_MODIFIER_ALT;
else if (!strnicmp(str, "ctrl_", 5)) else if (!strnicmp(str, "ctrl_", 5))
*modifier |= 4; *modifier |= KEY_MODIFIER_CTRL;
else else
break; break;
str = underscore+1; //next char. str = underscore+1; //next char.
@ -1616,7 +1615,7 @@ char *Key_KeynumToString (int keynum)
if (keynum == -1) if (keynum == -1)
return "<KEY NOT FOUND>"; return "<KEY NOT FOUND>";
if (keynum > 32 && keynum < 127) if (keynum > 32 && keynum < 127 && keynum != '\'' && keynum != '\"')
{ // printable ascii { // printable ascii
tinystr[0] = keynum; tinystr[0] = keynum;
tinystr[1] = 0; tinystr[1] = 0;
@ -1853,11 +1852,11 @@ void Key_WriteBindings (vfsfile_t *f)
if (strcmp(binding, base) || (m==0 && keybindings[i][0]) || bindcmdlevel[i][m] != bindcmdlevel[i][0]) if (strcmp(binding, base) || (m==0 && keybindings[i][0]) || bindcmdlevel[i][m] != bindcmdlevel[i][0])
{ {
*prefix = '\0'; *prefix = '\0';
if (m & 4) if (m & KEY_MODIFIER_CTRL)
strcat(prefix, "CTRL_"); strcat(prefix, "CTRL_");
if (m & 2) if (m & KEY_MODIFIER_ALT)
strcat(prefix, "ALT_"); strcat(prefix, "ALT_");
if (m & 1) if (m & KEY_MODIFIER_SHIFT)
strcat(prefix, "SHIFT_"); strcat(prefix, "SHIFT_");
s = va("%s%s", prefix, Key_KeynumToString(i)); s = va("%s%s", prefix, Key_KeynumToString(i));

View File

@ -166,6 +166,11 @@ K_PRINTSCREEN = 248,
K_MAX = 256 K_MAX = 256
}; };
#define KEY_MODIFIER_SHIFT (1<<0)
#define KEY_MODIFIER_ALT (1<<1)
#define KEY_MODIFIER_CTRL (1<<2)
#define KEY_MODIFIERSTATES (1<<3)
#define K_SHIFT K_LSHIFT #define K_SHIFT K_LSHIFT
#define K_CTRL K_LCTRL #define K_CTRL K_LCTRL
#define K_ALT K_LALT #define K_ALT K_LALT

View File

@ -6,7 +6,7 @@
#ifdef DOWNLOADMENU #ifdef DOWNLOADMENU
#define ROOTDOWNLOADABLESSOURCE "http://fteqw.com/downloadables.txt" #define ROOTDOWNLOADABLESSOURCE "http://fte.triptohell.info/downloadables.txt"
#define INSTALLEDFILES "installed.lst" //the file that resides in the quakedir (saying what's installed). #define INSTALLEDFILES "installed.lst" //the file that resides in the quakedir (saying what's installed).
#define DPF_HAVEAVERSION 1 //any old version #define DPF_HAVEAVERSION 1 //any old version

View File

@ -2530,6 +2530,7 @@ void *currentcapture_ctx;
struct capture_raw_ctx struct capture_raw_ctx
{ {
int frames; int frames;
enum fs_relative fsroot;
char videonameprefix[MAX_QPATH]; char videonameprefix[MAX_QPATH];
char videonameextension[16]; char videonameextension[16];
vfsfile_t *audio; vfsfile_t *audio;
@ -2544,7 +2545,12 @@ static void *QDECL capture_raw_begin (char *streamname, int videorate, int width
else else
Q_strncpyz(ctx->videonameextension, "tga", sizeof(ctx->videonameextension)); Q_strncpyz(ctx->videonameextension, "tga", sizeof(ctx->videonameextension));
Q_strncpyz(ctx->videonameprefix, streamname, sizeof(ctx->videonameprefix)); if (!FS_NativePath(va("%s", streamname), FS_GAMEONLY, ctx->videonameprefix, sizeof(ctx->videonameprefix)))
{
Z_Free(ctx);
return NULL;
}
ctx->fsroot = FS_SYSTEM;
ctx->audio = NULL; ctx->audio = NULL;
if (*sndkhz) if (*sndkhz)
{ {
@ -2558,8 +2564,8 @@ static void *QDECL capture_raw_begin (char *streamname, int videorate, int width
if (*sndchannels < 1) if (*sndchannels < 1)
*sndchannels = 1; *sndchannels = 1;
Q_snprintfz(filename, sizeof(filename), "%s/audio_%ichan_%ikhz_%ib.raw", ctx->videonameprefix, *sndchannels, *sndkhz/1000, *sndbits); Q_snprintfz(filename, sizeof(filename), "%s/audio_%ichan_%ikhz_%ib.raw", ctx->videonameprefix, *sndchannels, *sndkhz/1000, *sndbits);
FS_CreatePath(filename, FS_GAMEONLY); FS_CreatePath(filename, ctx->fsroot);
ctx->audio = FS_OpenVFS(filename, "wb", FS_GAMEONLY); ctx->audio = FS_OpenVFS(filename, "wb", ctx->fsroot);
} }
if (!ctx->audio) if (!ctx->audio)
{ {
@ -2575,7 +2581,7 @@ static void QDECL capture_raw_video (void *vctx, void *data, int frame, int widt
char filename[MAX_OSPATH]; char filename[MAX_OSPATH];
ctx->frames = frame+1; ctx->frames = frame+1;
Q_snprintfz(filename, sizeof(filename), "%s/%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension); Q_snprintfz(filename, sizeof(filename), "%s/%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension);
SCR_ScreenShot(filename, data, width, height); SCR_ScreenShot(filename, ctx->fsroot, data, width, height);
} }
static void QDECL capture_raw_audio (void *vctx, void *data, int bytes) static void QDECL capture_raw_audio (void *vctx, void *data, int bytes)
{ {

View File

@ -105,31 +105,51 @@ void M_DrawTextBox (int x, int y, int width, int lines)
M_DrawScalePic (cx, cy+8, 8, 8, p); M_DrawScalePic (cx, cy+8, 8, 8, p);
} }
int M_FindKeysForBind (char *command, int *keylist, int total) int M_FindKeysForBind (char *command, int *keylist, int *keymods, int total)
{ {
int count; int count;
int j; int j, m;
int l; int l, p;
char *b; char *b;
for (count = 0; count < total; count++)
keylist[count] = -1;
l = strlen(command); l = strlen(command);
count = 0; count = 0;
for (j=0 ; j<256 ; j++) for (j=0 ; j<256 ; j++)
{ {
b = keybindings[j][0]; for (m = 0; m < KEY_MODIFIERSTATES; m++)
if (!b)
continue;
if (!strncmp (b, command, l) && (!b[l] || b[l] == ' ' || b[l] == ';'))
{ {
keylist[count] = j; b = keybindings[j][m];
count++; if (!b)
if (count == total) continue;
break; if (!strncmp (b, command, l) && (!b[l] || b[l] == ' ' || b[l] == ';'))
{
//if ctrl_a and ctrl_shift_a do the same thing, don't report ctrl_shift_a because its redundant.
for (p = 0; p < m; p++)
{
if (p&~m) //ignore shift_a if we're checking ctrl_a
continue;
if (!strcmp(keybindings[j][p], b))
break; //break+continue
}
if (p != m)
continue;
keylist[count] = j;
if (keymods)
keymods[count] = j;
count++;
if (count == total)
return count;
}
} }
} }
for (j = count; j < total; j++)
{
keylist[j] = -1;
if (keymods)
keymods[j] = 0;
}
return count; return count;
} }
void M_FindKeysForCommand (int pnum, const char *command, int *twokeys) void M_FindKeysForCommand (int pnum, const char *command, int *twokeys)
@ -160,7 +180,7 @@ void M_FindKeysForCommand (int pnum, const char *command, int *twokeys)
prefix[3] = 0; prefix[3] = 0;
} }
} }
M_FindKeysForBind(va("%s%s", prefix, command), twokeys, 2); M_FindKeysForBind(va("%s%s", prefix, command), twokeys, NULL, 2);
} }
#ifndef NOBUILTINMENUS #ifndef NOBUILTINMENUS

View File

@ -468,6 +468,7 @@ void M_Keyup (int key, int unicode);
void M_Draw (int uimenu); void M_Draw (int uimenu);
#endif #endif
void M_FindKeysForCommand (int pnum, const char *command, int *twokeys); void M_FindKeysForCommand (int pnum, const char *command, int *twokeys);
int M_FindKeysForBind (char *command, int *keylist, int *keymods, int total);
void M_Media_Draw (void); void M_Media_Draw (void);
void M_Media_Key (int key); void M_Media_Key (int key);

View File

@ -1170,7 +1170,7 @@ static void P_ParticleEffect_f(void)
ptype->alpha = atof(value); ptype->alpha = atof(value);
else if (!strcmp(var, "alphachange")) else if (!strcmp(var, "alphachange"))
{ {
Con_DPrintf("alphachange is deprechiated, use alphadelta\n"); Con_DPrintf("alphachange is deprecated, use alphadelta\n");
ptype->alphachange = atof(value); ptype->alphachange = atof(value);
} }
else if (!strcmp(var, "alphadelta")) else if (!strcmp(var, "alphadelta"))
@ -1195,7 +1195,7 @@ static void P_ParticleEffect_f(void)
} }
else if (!strcmp(var, "diesubrand")) else if (!strcmp(var, "diesubrand"))
{ {
Con_DPrintf("diesubrand is deprechiated, use die with two arguments\n"); Con_DPrintf("diesubrand is deprecated, use die with two arguments\n");
ptype->randdie = atof(value); ptype->randdie = atof(value);
} }
@ -1550,7 +1550,7 @@ static void P_ParticleEffect_f(void)
} }
else if (!strcmp(var, "isbeam")) else if (!strcmp(var, "isbeam"))
{ {
Con_DPrintf("isbeam is deprechiated, use type beam\n"); Con_DPrintf("isbeam is deprecated, use type beam\n");
ptype->looks.type = PT_BEAM; ptype->looks.type = PT_BEAM;
} }
else if (!strcmp(var, "spawntime")) else if (!strcmp(var, "spawntime"))
@ -1589,22 +1589,22 @@ static void P_ParticleEffect_f(void)
// old names // old names
else if (!strcmp(var, "areaspread")) else if (!strcmp(var, "areaspread"))
{ {
Con_DPrintf("areaspread is deprechiated, use spawnorg\n"); Con_DPrintf("areaspread is deprecated, use spawnorg\n");
ptype->areaspread = atof(value); ptype->areaspread = atof(value);
} }
else if (!strcmp(var, "areaspreadvert")) else if (!strcmp(var, "areaspreadvert"))
{ {
Con_DPrintf("areaspreadvert is deprechiated, use spawnorg\n"); Con_DPrintf("areaspreadvert is deprecated, use spawnorg\n");
ptype->areaspreadvert = atof(value); ptype->areaspreadvert = atof(value);
} }
else if (!strcmp(var, "offsetspread")) else if (!strcmp(var, "offsetspread"))
{ {
Con_DPrintf("offsetspread is deprechiated, use spawnvel\n"); Con_DPrintf("offsetspread is deprecated, use spawnvel\n");
ptype->spawnvel = atof(value); ptype->spawnvel = atof(value);
} }
else if (!strcmp(var, "offsetspreadvert")) else if (!strcmp(var, "offsetspreadvert"))
{ {
Con_DPrintf("offsetspreadvert is deprechiated, use spawnvel\n"); Con_DPrintf("offsetspreadvert is deprecated, use spawnvel\n");
ptype->spawnvelvert = atof(value); ptype->spawnvelvert = atof(value);
} }
@ -1640,7 +1640,7 @@ static void P_ParticleEffect_f(void)
ptype->rampmode = RAMP_NONE; ptype->rampmode = RAMP_NONE;
else if (!strcmp(value, "absolute")) else if (!strcmp(value, "absolute"))
{ {
Con_DPrintf("'rampmode absolute' is deprechiated, use 'rampmode nearest'\n"); Con_DPrintf("'rampmode absolute' is deprecated, use 'rampmode nearest'\n");
ptype->rampmode = RAMP_NEAREST; ptype->rampmode = RAMP_NEAREST;
} }
else if (!strcmp(value, "nearest")) else if (!strcmp(value, "nearest"))
@ -2902,7 +2902,7 @@ static void P_ExportBuiltinSet_f(void)
file = *partset_list[i].data; file = *partset_list[i].data;
if (file) if (file)
{ {
COM_WriteFile(va("particles/%s.cfg", efname), file, strlen(file)); COM_WriteFile(va("particles/%s.cfg", efname), FS_GAMEONLY, file, strlen(file));
Con_Printf("Written particles/%s.cfg\n", efname); Con_Printf("Written particles/%s.cfg\n", efname);
} }
else else

View File

@ -285,6 +285,7 @@ int MP_TranslateQCtoFTECodes(int code)
void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
const char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0); const char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0);
//float bindmap = G_FLOAT(OFS_PARM1);
int keynums[2]; int keynums[2];
char keyname[512]; char keyname[512];
@ -298,6 +299,26 @@ void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalva
RETURN_TSTRING(keyname); RETURN_TSTRING(keyname);
} }
void QCBUILTIN PF_cl_findkeysforcommandex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0);
int keynums[256];
int keymods[countof(keynums)];
char keyname[512];
int i, count;
count = M_FindKeysForBind(cmdname, keynums, keymods, countof(keynums));
keyname[0] = '\0';
for (i = 0; i < count; i++)
{
Q_strncatz (keyname, va("%s%s%s%s ", (keymods[i]&KEY_MODIFIER_CTRL)?"CTRL_":"", (keymods[i]&KEY_MODIFIER_ALT)?"ALT_":"", (keymods[i]&KEY_MODIFIER_SHIFT)?"SHIFT_":"", Key_KeynumToString(keynums[i])), sizeof(keyname));
}
RETURN_TSTRING(keyname);
}
void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
char *binding = Key_GetBinding(MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0))); char *binding = Key_GetBinding(MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0)));

View File

@ -184,6 +184,7 @@ extern sfx_t *cl_sfx_r_exp3;
globalvector(input_cursor_impact, "input_cursor_trace_endpos"); /*float filled by getinputstate*/ \ globalvector(input_cursor_impact, "input_cursor_trace_endpos"); /*float filled by getinputstate*/ \
globalfloat(input_cursor_entitynumber, "input_cursor_entitynumber"); /*float filled by getinputstate*/ \ globalfloat(input_cursor_entitynumber, "input_cursor_entitynumber"); /*float filled by getinputstate*/ \
\ \
globalfloat(dimension_default, "dimension_default"); /*float default value for dimension_hit+dimension_solid*/ \
globalfloat(autocvar_vid_conwidth, "autocvar_vid_conwidth"); /*float hackfix for dp mods*/ \ globalfloat(autocvar_vid_conwidth, "autocvar_vid_conwidth"); /*float hackfix for dp mods*/ \
globalfloat(autocvar_vid_conheight, "autocvar_vid_conheight"); /*float hackfix for dp mods*/ \ globalfloat(autocvar_vid_conheight, "autocvar_vid_conheight"); /*float hackfix for dp mods*/ \
@ -278,6 +279,7 @@ static void CSQC_ChangeLocalPlayer(int seat)
static void CSQC_FindGlobals(void) static void CSQC_FindGlobals(void)
{ {
static float csphysicsmode = 0; static float csphysicsmode = 0;
static float dimension_default = 255;
#define globalfloat(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); #define globalfloat(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
#define globalint(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); #define globalint(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
#define globalvector(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); #define globalvector(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL);
@ -320,6 +322,9 @@ static void CSQC_FindGlobals(void)
csqc_world.g.physics_mode = &csphysicsmode; csqc_world.g.physics_mode = &csphysicsmode;
} }
if (!csqcg.dimension_default)
csqcg.dimension_default = &dimension_default;
if (csqcg.maxclients) if (csqcg.maxclients)
*csqcg.maxclients = cl.allocated_client_slots; *csqcg.maxclients = cl.allocated_client_slots;
} }
@ -492,6 +497,7 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t
} }
//and the normal frames. //and the normal frames.
out->g[FS_REG].endbone = 0x7fffffff;
out->g[FS_REG].frame[0] = in->v->frame; out->g[FS_REG].frame[0] = in->v->frame;
out->g[FS_REG].frame[1] = in->xv->frame2; out->g[FS_REG].frame[1] = in->xv->frame2;
out->g[FS_REG].frame[2] = in->xv->frame3; out->g[FS_REG].frame[2] = in->xv->frame3;
@ -1757,6 +1763,7 @@ void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
} }
void R2D_PolyBlend (void); void R2D_PolyBlend (void);
void R_DrawNameTags(void);
static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
if (csqc_worldchanged) if (csqc_worldchanged)
@ -1775,6 +1782,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars
V_ApplyRefdef(); V_ApplyRefdef();
R_RenderView(); R_RenderView();
R2D_PolyBlend (); R2D_PolyBlend ();
R_DrawNameTags();
{ {
srect_t srect; srect_t srect;
@ -4062,8 +4070,6 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src
ent->v->colormap = src->colormap; ent->v->colormap = src->colormap;
ent->v->skin = src->skinnum; ent->v->skin = src->skinnum;
// ent->v->glowsize = src->glowsize;
// ent->v->glowcolor = src->glowcolour;
ent->xv->scale = src->scale/16.0f; ent->xv->scale = src->scale/16.0f;
ent->xv->fatness = src->fatness/16.0f; ent->xv->fatness = src->fatness/16.0f;
// ent->xv->drawflags = src->hexen2flags; // ent->xv->drawflags = src->hexen2flags;
@ -4072,16 +4078,23 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src
ent->xv->colormod[0] = src->colormod[0]*(8/256.0f); ent->xv->colormod[0] = src->colormod[0]*(8/256.0f);
ent->xv->colormod[1] = src->colormod[1]*(8/256.0f); ent->xv->colormod[1] = src->colormod[1]*(8/256.0f);
ent->xv->colormod[2] = src->colormod[2]*(8/256.0f); ent->xv->colormod[2] = src->colormod[2]*(8/256.0f);
ent->xv->glowmod[0] = src->glowmod[0]*(8/256.0f);
ent->xv->glowmod[1] = src->glowmod[1]*(8/256.0f);
ent->xv->glowmod[2] = src->glowmod[2]*(8/256.0f);
// ent->xv->glow_size = src->glowsize*4;
// ent->xv->glow_color = src->glowcolour;
// ent->xv->glow_trail = !!(state->dpflags & RENDER_GLOWTRAIL);
ent->xv->alpha = src->trans/255.0f; ent->xv->alpha = src->trans/255.0f;
// ent->v->solid = src->solid;
// ent->v->color[0] = src->light[0]/255.0;
// ent->v->color[1] = src->light[1]/255.0;
// ent->v->color[2] = src->light[2]/255.0;
// ent->v->light_lev = src->light[3];
// ent->xv->style = src->lightstyle; // ent->xv->style = src->lightstyle;
// ent->xv->pflags = src->lightpflags; // ent->xv->pflags = src->lightpflags;
// ent->v->solid = src->solid;
// ent->v->color[0] = src->light[0]; ent->xv->tag_entity = src->tagentity;
// ent->v->color[1] = src->light[1]; ent->xv->tag_index = src->tagindex;
// ent->v->color[2] = src->light[2];
// ent->v->light_lev = src->light[3];
// ent->xv->tagentity = src->tagentity;
// ent->xv->tagindex = src->tagindex;
if (src->solid == ES_SOLID_BSP) if (src->solid == ES_SOLID_BSP)
{ {
@ -5346,6 +5359,7 @@ static struct {
{"keynumtostring_omgwtf", PF_cl_keynumtostring, 520}, {"keynumtostring_omgwtf", PF_cl_keynumtostring, 520},
{"findkeysforcommand", PF_cl_findkeysforcommand, 521}, {"findkeysforcommand", PF_cl_findkeysforcommand, 521},
{"findkeysforcommandex", PF_cl_findkeysforcommandex, 0},
{"loadfromdata", PF_loadfromdata, 529}, {"loadfromdata", PF_loadfromdata, 529},
{"loadfromfile", PF_loadfromfile, 530}, {"loadfromfile", PF_loadfromfile, 530},
@ -5373,7 +5387,7 @@ static struct {
{"getresolution", PF_cl_getresolution, 608}, {"getresolution", PF_cl_getresolution, 608},
{"keynumtostring_menu", PF_cl_keynumtostring, 609}, //while present in dp's menuqc, dp doesn't actually support keynumtostring=609 in csqc. Which is probably a good thing because csqc would have 3 separate versions if it did. {"keynumtostring_menu", PF_cl_keynumtostring, 609}, //while present in dp's menuqc, dp doesn't actually support keynumtostring=609 in csqc. Which is probably a good thing because csqc would have 3 separate versions if it did.
{"findkeysforcommand_dp", PF_cl_findkeysforcommand, 610}, {"findkeysforcommand_menu", PF_cl_findkeysforcommand, 610},
{"gethostcachevalue", PF_cl_gethostcachevalue, 611}, {"gethostcachevalue", PF_cl_gethostcachevalue, 611},
{"gethostcachestring", PF_cl_gethostcachestring, 612}, {"gethostcachestring", PF_cl_gethostcachestring, 612},
{"parseentitydata", PF_parseentitydata, 613}, {"parseentitydata", PF_parseentitydata, 613},
@ -5474,7 +5488,7 @@ void VARGS CSQC_Abort (char *format, ...) //an error occured.
int size = 1024*1024*8; int size = 1024*1024*8;
char *buffer = BZ_Malloc(size); char *buffer = BZ_Malloc(size);
csqcprogs->save_ents(csqcprogs, buffer, &size, size, 3); csqcprogs->save_ents(csqcprogs, buffer, &size, size, 3);
COM_WriteFile("csqccore.txt", buffer, size); COM_WriteFile("csqccore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer); BZ_Free(buffer);
} }
@ -5506,11 +5520,11 @@ void PDECL CSQC_EntSpawn (struct edict_s *e, int loading)
if (1) if (1)
{ {
// ent->xv->dimension_see = 255; // ent->xv->dimension_see = csqc_world.dimension_default;
// ent->xv->dimension_seen = 255; // ent->xv->dimension_seen = csqc_world.dimension_default;
// ent->xv->dimension_ghost = 0; // ent->xv->dimension_ghost = 0;
ent->xv->dimension_solid = 255; ent->xv->dimension_solid = *csqcg.dimension_default;
ent->xv->dimension_hit = 255; ent->xv->dimension_hit = *csqcg.dimension_default;
} }
} }
@ -5710,7 +5724,7 @@ qbyte *PDECL CSQC_PRLoadFile (const char *path, void *buffer, int bufsize, size_
#ifndef FTE_TARGET_WEB #ifndef FTE_TARGET_WEB
//back it up //back it up
COM_WriteFile(newname, file, *sz); COM_WriteFile(newname, FS_GAMEONLY, file, *sz);
#endif #endif
} }
} }
@ -6147,7 +6161,7 @@ void CSQC_CoreDump(void)
int size = 1024*1024*8; int size = 1024*1024*8;
char *buffer = BZ_Malloc(size); char *buffer = BZ_Malloc(size);
csqcprogs->save_ents(csqcprogs, buffer, &size, size, 3); csqcprogs->save_ents(csqcprogs, buffer, &size, size, 3);
COM_WriteFile("csqccore.txt", buffer, size); COM_WriteFile("csqccore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer); BZ_Free(buffer);
} }

View File

@ -1038,6 +1038,7 @@ static struct
evalc_t frame1time; evalc_t frame1time;
evalc_t frame2time; evalc_t frame2time;
evalc_t renderflags; evalc_t renderflags;
evalc_t skinobject;
} menuc_eval; } menuc_eval;
static playerview_t menuview; static playerview_t menuview;
@ -1670,6 +1671,29 @@ static void QCBUILTIN PF_m_setmodel(pubprogfuncs_t *prinst, struct globalvars_s
if (mod && maxsval) if (mod && maxsval)
VectorCopy(mod->maxs, maxsval->_vector); VectorCopy(mod->maxs, maxsval->_vector);
} }
static void QCBUILTIN PF_m_setcustomskin(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
menuedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0);
const char *fname = PR_GetStringOfs(prinst, OFS_PARM1);
const char *skindata = PF_VarString(prinst, 2, pr_globals);
eval_t *val = prinst->GetEdictFieldValue(prinst, (void*)ent, "skinobject", &menuc_eval.skinobject);
if (!val)
return;
if (val->_float > 0)
{
Mod_WipeSkin(val->_float);
val->_float = 0;
}
if (*fname || *skindata)
{
if (*skindata)
val->_float = Mod_ReadSkinFile(fname, skindata);
else
val->_float = -(int)Mod_RegisterSkinFile(fname);
}
}
//trivially basic //trivially basic
static void QCBUILTIN PF_m_setorigin(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_m_setorigin(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -1707,6 +1731,7 @@ static qboolean CopyMenuEdictToEntity(pubprogfuncs_t *prinst, menuedict_t *in, e
eval_t *frame2timeval = prinst->GetEdictFieldValue(prinst, (void*)in, "frame2time", &menuc_eval.frame2time); eval_t *frame2timeval = prinst->GetEdictFieldValue(prinst, (void*)in, "frame2time", &menuc_eval.frame2time);
eval_t *colormapval = prinst->GetEdictFieldValue(prinst, (void*)in, "colormap", &menuc_eval.colormap); eval_t *colormapval = prinst->GetEdictFieldValue(prinst, (void*)in, "colormap", &menuc_eval.colormap);
eval_t *renderflagsval = prinst->GetEdictFieldValue(prinst, (void*)in, "renderflags", &menuc_eval.renderflags); eval_t *renderflagsval = prinst->GetEdictFieldValue(prinst, (void*)in, "renderflags", &menuc_eval.renderflags);
eval_t *skinobjectval = prinst->GetEdictFieldValue(prinst, (void*)in, "skinobject", &menuc_eval.skinobject);
int ival; int ival;
int rflags; int rflags;
@ -1730,6 +1755,8 @@ static qboolean CopyMenuEdictToEntity(pubprogfuncs_t *prinst, menuedict_t *in, e
out->framestate.g[FS_REG].frametime[0] = frame1timeval?frame1timeval->_float:0; out->framestate.g[FS_REG].frametime[0] = frame1timeval?frame1timeval->_float:0;
out->framestate.g[FS_REG].frametime[1] = frame2timeval?frame2timeval->_float:0; out->framestate.g[FS_REG].frametime[1] = frame2timeval?frame2timeval->_float:0;
out->customskin = skinobjectval?skinobjectval->_float:0;
//FIXME: colourmap //FIXME: colourmap
ival = colormapval?colormapval->_float:0; ival = colormapval?colormapval->_float:0;
out->playerindex = -1; out->playerindex = -1;
@ -1969,6 +1996,10 @@ static struct {
{"findfont", PF_CL_findfont, 356}, {"findfont", PF_CL_findfont, 356},
{"loadfont", PF_CL_loadfont, 357}, {"loadfont", PF_CL_loadfont, 357},
//gap //gap
// {"dynamiclight_get", PF_R_DynamicLight_Get, 372},
// {"dynamiclight_set", PF_R_DynamicLight_Set, 373},
{"setcustomskin", PF_m_setcustomskin, 376},
//gap
{"memalloc", PF_memalloc, 384}, {"memalloc", PF_memalloc, 384},
{"memfree", PF_memfree, 385}, {"memfree", PF_memfree, 385},
{"memcpy", PF_memcpy, 386}, {"memcpy", PF_memcpy, 386},
@ -2245,7 +2276,7 @@ void VARGS Menu_Abort (char *format, ...)
int size = 1024*1024*8; int size = 1024*1024*8;
buffer = Z_Malloc(size); buffer = Z_Malloc(size);
menu_world.progs->save_ents(menu_world.progs, buffer, &size, size, 3); menu_world.progs->save_ents(menu_world.progs, buffer, &size, size, 3);
COM_WriteFile("menucore.txt", buffer, size); COM_WriteFile("menucore.txt", FS_GAMEONLY, buffer, size);
Z_Free(buffer); Z_Free(buffer);
} }
@ -2422,7 +2453,7 @@ void MP_CoreDump_f(void)
int size = 1024*1024*8; int size = 1024*1024*8;
char *buffer = BZ_Malloc(size); char *buffer = BZ_Malloc(size);
menu_world.progs->save_ents(menu_world.progs, buffer, &size, size, 3); menu_world.progs->save_ents(menu_world.progs, buffer, &size, size, 3);
COM_WriteFile("menucore.txt", buffer, size); COM_WriteFile("menucore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer); BZ_Free(buffer);
} }
} }

View File

@ -199,28 +199,30 @@ static void R_Clutter_Insert_Mesh(clutter_build_ctx_t *ctx, model_t *mod, float
if (!mod) if (!mod)
return; return;
//fill in the parts of the entity_t that Alias_GAliasBuildMesh needs. if (mod->type == mod_alias)
memset(&re, 0, sizeof(re));
// memset(&re.framestate, 0, sizeof(re.framestate));
re.framestate.g[FS_REG].lerpweight[0] = 1;
re.model = mod;
inf = (galiasinfo_t*)Mod_Extradata (mod);
while(inf)
{ {
galiasskin_t *skins = inf->ofsskins; //fill in the parts of the entity_t that Alias_GAliasBuildMesh needs.
re.framestate.g[FS_REG].frame[0] = randanim%inf->numanimations; memset(&re, 0, sizeof(re));
if (skins->numframes) re.framestate.g[FS_REG].lerpweight[0] = 1;
re.model = mod;
inf = (galiasinfo_t*)Mod_Extradata (mod);
while(inf)
{ {
unsigned int frame = randskin%skins->numframes; galiasskin_t *skins = inf->ofsskins;
Alias_GAliasBuildMesh(&mesh, NULL, inf, surfnum, &re, false); re.framestate.g[FS_REG].frame[0] = randanim%inf->numanimations;
surfnum++; if (skins->numframes)
//fixme: if shares verts, rewind the verts and don't add more somehow, while being careful with shaders {
R_Clutter_Insert_Soup(ctx, skins->frame[frame].shader, mesh.xyz_array, mesh.st_array, mesh.normals_array, mesh.snormals_array, mesh.tnormals_array, mesh.colors4f_array[0], mesh.numvertexes, mesh.indexes, mesh.numindexes, scale, origin, axis); unsigned int frame = randskin%skins->numframes;
Alias_GAliasBuildMesh(&mesh, NULL, inf, surfnum, &re, false);
surfnum++;
//fixme: if shares verts, rewind the verts and don't add more somehow, while being careful with shaders
R_Clutter_Insert_Soup(ctx, skins->frame[frame].shader, mesh.xyz_array, mesh.st_array, mesh.normals_array, mesh.snormals_array, mesh.tnormals_array, mesh.colors4f_array[0], mesh.numvertexes, mesh.indexes, mesh.numindexes, scale, origin, axis);
}
inf = inf->nextsurf;
} }
inf = inf->nextsurf; Alias_FlushCache(); //it got built using an entity on the stack, make sure other stuff doesn't get hurt.
} }
Alias_FlushCache(); //it got built using an entity on the stack, make sure other stuff doesn't get hurt.
} }
static void R_Clutter_Insert(void *vctx, vec3_t *fte_restrict points, size_t numtris, shader_t *surface) static void R_Clutter_Insert(void *vctx, vec3_t *fte_restrict points, size_t numtris, shader_t *surface)
{ {

View File

@ -517,7 +517,7 @@ void CLQ2_FlyEffect(struct q2centity_s *ent, vec3_t org);
void CLQ2_DiminishingTrail(vec3_t oldorg, vec3_t neworg, struct q2centity_s *ent, unsigned int effects); void CLQ2_DiminishingTrail(vec3_t oldorg, vec3_t neworg, struct q2centity_s *ent, unsigned int effects);
void CLQ2_BlasterTrail2(vec3_t oldorg, vec3_t neworg); void CLQ2_BlasterTrail2(vec3_t oldorg, vec3_t neworg);
void WritePCXfile (const char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit. void WritePCXfile (const char *filename, enum fs_relative fsroot, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit.
qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height); qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height);
qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *hasalpha, int asgrey); qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *hasalpha, int asgrey);
qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height); qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height);

View File

@ -204,7 +204,7 @@ cvar_t vid_conwidth = CVARF ("vid_conwidth", "0",
cvar_t vid_renderer = CVARFD ("vid_renderer", "", cvar_t vid_renderer = CVARFD ("vid_renderer", "",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Specifies which backend is used. Values that might work are: sv (dedicated server), gl (opengl), egl (opengl es), d3d9 (direct3d 9), d3d11 (direct3d 11, with default hardware rendering), d3d11 warp (direct3d 11, with software rendering)."); CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Specifies which backend is used. Values that might work are: sv (dedicated server), gl (opengl), egl (opengl es), d3d9 (direct3d 9), d3d11 (direct3d 11, with default hardware rendering), d3d11 warp (direct3d 11, with software rendering).");
cvar_t vid_bpp = CVARFD ("vid_bpp", "32", cvar_t vid_bpp = CVARFD ("vid_bpp", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The number of colour bits to request from the renedering context"); CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The number of colour bits to request from the renedering context");
cvar_t vid_desktopsettings = CVARFD ("vid_desktopsettings", "0", cvar_t vid_desktopsettings = CVARFD ("vid_desktopsettings", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Ignore the values of vid_width and vid_height, and just use the same settings that are used for the desktop."); CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Ignore the values of vid_width and vid_height, and just use the same settings that are used for the desktop.");

View File

@ -79,7 +79,8 @@ void SCR_ShowPic_Script_f(void);
//a header is better than none... //a header is better than none...
void Draw_TextBox (int x, int y, int width, int lines); void Draw_TextBox (int x, int y, int width, int lines);
qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height); enum fs_relative;
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buffer, int width, int height);
void SCR_DrawTwoDimensional(int uimenu, qboolean nohud); void SCR_DrawTwoDimensional(int uimenu, qboolean nohud);

View File

@ -585,7 +585,9 @@ qboolean MyRegGetStringValue(HKEY base, const char *keyname, const char *valuena
DWORD type = REG_NONE; DWORD type = REG_NONE;
if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS) if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS)
{ {
result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &datalen); DWORD dl = datalen;
result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &dl);
datalen = dl;
RegCloseKey (subkey); RegCloseKey (subkey);
} }

View File

@ -360,22 +360,38 @@ void Sys_CloseLibrary(dllhandle_t *lib)
{ {
FreeLibrary((HMODULE)lib); FreeLibrary((HMODULE)lib);
} }
HMODULE LoadLibraryU(const char *name)
{
if (WinNT)
{
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), name);
return LoadLibraryW(wide);
}
else
{
wchar_t wide[MAX_OSPATH];
char ansi[MAX_OSPATH];
widen(wide, sizeof(wide), name);
ansi[WideCharToMultiByte(CP_ACP, 0, wide, wcslen(wide), ansi, sizeof(ansi)-1, NULL, NULL)] = 0;
return LoadLibraryA(ansi);
}
}
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs) dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
{ {
int i; int i;
HMODULE lib; HMODULE lib;
wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), name); lib = LoadLibraryU(name);
lib = LoadLibraryW(wide);
if (!lib) if (!lib)
{ {
if (!strstr(COM_SkipPath(name), ".dll")) if (!strstr(COM_SkipPath(name), ".dll"))
{ //.dll implies that it is a system dll, or something that is otherwise windows-specific already. { //.dll implies that it is a system dll, or something that is otherwise windows-specific already.
#ifdef _WIN64 #ifdef _WIN64
lib = LoadLibrary(va("%s_64", name)); lib = LoadLibraryU(va("%s_64", name));
#elif defined(_WIN32) #elif defined(_WIN32)
lib = LoadLibrary(va("%s_32", name)); lib = LoadLibraryU(va("%s_32", name));
#endif #endif
} }
if (!lib) if (!lib)
@ -1537,7 +1553,15 @@ void VARGS Sys_Printf (char *fmt, ...)
if (debugout) if (debugout)
OutputDebugStringW(wide); OutputDebugStringW(wide);
if (houtput) if (houtput)
WriteConsoleW(houtput, wide, wlen, &dummy, NULL); {
if (WinNT)
WriteConsoleW(houtput, wide, wlen, &dummy, NULL);
else
{
//win95 doesn't support wide chars *sigh*. blank consoles suck. this conversion might loose stuff if the multibytes are too long.
WriteConsole(houtput, text, WideCharToMultiByte(CP_ACP, 0, wide, wlen, text, sizeof(text), NULL, NULL), &dummy, NULL);
}
}
} }
void Sys_Quit (void) void Sys_Quit (void)
@ -1941,7 +1965,13 @@ char *Sys_ConsoleInput (void)
} else if (ch >= ' ') } else if (ch >= ' ')
{ {
wchar_t wch = ch; wchar_t wch = ch;
WriteConsoleW(houtput, &wch, 1, &dummy, NULL); if (WinNT)
WriteConsoleW(houtput, &wch, 1, &dummy, NULL);
else
{
char mb[8]; //hopefully ucs-2-only will be sufficient...
WriteConsoleA(houtput, mb, WideCharToMultiByte(CP_ACP, 0, &wch, 1, mb, sizeof(mb), NULL, NULL), &dummy, NULL);
}
len += utf8_encode(text+len, ch, sizeof(text)-1-len); len += utf8_encode(text+len, ch, sizeof(text)-1-len);
} }
@ -2170,8 +2200,6 @@ HWND hwnd_dialog;
#define COBJMACROS
#include <shlobj.h> #include <shlobj.h>
typedef struct qSHARDAPPIDINFOLINK { typedef struct qSHARDAPPIDINFOLINK {
@ -2413,15 +2441,24 @@ typedef struct {
} qOPENASINFO; } qOPENASINFO;
HRESULT (WINAPI *pSHOpenWithDialog)(HWND hwndParent, const qOPENASINFO *poainfo); HRESULT (WINAPI *pSHOpenWithDialog)(HWND hwndParent, const qOPENASINFO *poainfo);
LPITEMIDLIST (STDAPICALLTYPE *pSHBrowseForFolderW)(LPBROWSEINFOW lpbi);
BOOL (STDAPICALLTYPE *pSHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath);
BOOL (STDAPICALLTYPE *pSHGetSpecialFolderPathW)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);
BOOL (STDAPICALLTYPE *pShell_NotifyIconW)(DWORD dwMessage, PNOTIFYICONDATAW lpData);
void Win7_Init(void) void Win7_Init(void)
{ {
HANDLE h; HANDLE h;
HRESULT (WINAPI *pSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID); HRESULT (WINAPI *pSetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID);
h = LoadLibraryU("shell32.dll");
h = LoadLibraryW(L"shell32.dll");
if (h) if (h)
{ {
pSHBrowseForFolderW = (void*)GetProcAddress(h, "SHBrowseForFolderW");
pSHGetPathFromIDListW = (void*)GetProcAddress(h, "SHGetPathFromIDListW");
pSHGetSpecialFolderPathW = (void*)GetProcAddress(h, "SHGetSpecialFolderPathW");
pShell_NotifyIconW = (void*)GetProcAddress(h, "Shell_NotifyIconW");
pSHOpenWithDialog = (void*)GetProcAddress(h, "SHOpenWithDialog"); pSHOpenWithDialog = (void*)GetProcAddress(h, "SHOpenWithDialog");
pSetCurrentProcessExplicitAppUserModelID = (void*)GetProcAddress(h, "SetCurrentProcessExplicitAppUserModelID"); pSetCurrentProcessExplicitAppUserModelID = (void*)GetProcAddress(h, "SetCurrentProcessExplicitAppUserModelID");
@ -2507,6 +2544,13 @@ void Win7_TaskListInit(void)
} }
} }
BOOL CopyFileU(const char *src, const char *dst, BOOL bFailIfExists)
{
wchar_t wide1[2048];
wchar_t wide2[2048];
return CopyFileW(widen(wide1, sizeof(wide1), src), widen(wide2, sizeof(wide2), dst), bFailIfExists);
}
//#define SVNREVISION 1 //#define SVNREVISION 1
#if defined(SVNREVISION) && !defined(MINIMAL) #if defined(SVNREVISION) && !defined(MINIMAL)
#define SVNREVISIONSTR STRINGIFY(SVNREVISION) #define SVNREVISIONSTR STRINGIFY(SVNREVISION)
@ -3115,7 +3159,7 @@ static int Sys_ProcessCommandline(char **argv, int maxargc, char *argv0)
//using this like posix' access function, but with much more code, microsoftisms, and no errno codes/info //using this like posix' access function, but with much more code, microsoftisms, and no errno codes/info
//no, I don't really have a clue why it needs to be so long. //no, I don't really have a clue why it needs to be so long.
#include <svrapi.h> #include <svrapi.h>
static BOOL microsoft_access(LPCSTR pszFolder, DWORD dwAccessDesired) static BOOL microsoft_accessW(LPWSTR pszFolder, DWORD dwAccessDesired)
{ {
HANDLE hToken; HANDLE hToken;
PRIVILEGE_SET PrivilegeSet; PRIVILEGE_SET PrivilegeSet;
@ -3126,11 +3170,9 @@ static BOOL microsoft_access(LPCSTR pszFolder, DWORD dwAccessDesired)
SECURITY_INFORMATION si = (SECURITY_INFORMATION)( OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION); SECURITY_INFORMATION si = (SECURITY_INFORMATION)( OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION);
PSECURITY_DESCRIPTOR psdSD = NULL; PSECURITY_DESCRIPTOR psdSD = NULL;
DWORD dwNeeded; DWORD dwNeeded;
wchar_t wpath[MAX_OSPATH]; GetFileSecurityW(pszFolder,si,NULL,0,&dwNeeded);
widen(wpath, sizeof(wpath), pszFolder);
GetFileSecurityW(wpath,si,NULL,0,&dwNeeded);
psdSD = malloc(dwNeeded); psdSD = malloc(dwNeeded);
GetFileSecurityW(wpath,si,psdSD,dwNeeded,&dwNeeded); GetFileSecurityW(pszFolder,si,psdSD,dwNeeded,&dwNeeded);
ImpersonateSelf(SecurityImpersonation); ImpersonateSelf(SecurityImpersonation);
OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken); OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken);
memset(&GenericMapping, 0xff, sizeof(GENERIC_MAPPING)); memset(&GenericMapping, 0xff, sizeof(GENERIC_MAPPING));
@ -3144,8 +3186,13 @@ static BOOL microsoft_access(LPCSTR pszFolder, DWORD dwAccessDesired)
free(psdSD); free(psdSD);
return fAccessGranted; return fAccessGranted;
} }
static BOOL microsoft_accessU(LPCSTR pszFolder, DWORD dwAccessDesired)
{
wchar_t wpath[MAX_OSPATH];
return microsoft_accessW(widen(wpath, sizeof(wpath), pszFolder), dwAccessDesired);
}
static int MessageBoxU(HWND hWnd, char *lpText, char *lpCaption, UINT uType) int MessageBoxU(HWND hWnd, char *lpText, char *lpCaption, UINT uType)
{ {
wchar_t widecaption[256]; wchar_t widecaption[256];
wchar_t widetext[2048]; wchar_t widetext[2048];
@ -3175,8 +3222,8 @@ static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM
gah.ptDrag.x = gah.ptDrag.y = 0; gah.ptDrag.x = gah.ptDrag.y = 0;
gah.hdr = fu->hdr; gah.hdr = fu->hdr;
gah.hdr.code = TVN_SELCHANGEDW; gah.hdr.code = TVN_SELCHANGEDW;
r = CallWindowProc(omgwtfwhyohwhy,w,m,wp,lp); r = CallWindowProcW(omgwtfwhyohwhy,w,m,wp,lp);
CallWindowProc(omgwtfwhyohwhy,w,WM_NOTIFY,wp,(LPARAM)&gah); CallWindowProcW(omgwtfwhyohwhy,w,WM_NOTIFY,wp,(LPARAM)&gah);
return r; return r;
} }
break; break;
@ -3191,8 +3238,8 @@ static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM
gah.ptDrag.x = gah.ptDrag.y = 0; gah.ptDrag.x = gah.ptDrag.y = 0;
gah.hdr = fu->hdr; gah.hdr = fu->hdr;
gah.hdr.code = TVN_SELCHANGEDA; gah.hdr.code = TVN_SELCHANGEDA;
r = CallWindowProc(omgwtfwhyohwhy,w,m,wp,lp); r = CallWindowProcW(omgwtfwhyohwhy,w,m,wp,lp);
CallWindowProc(omgwtfwhyohwhy,w,WM_NOTIFY,wp,(LPARAM)&gah); CallWindowProcW(omgwtfwhyohwhy,w,WM_NOTIFY,wp,(LPARAM)&gah);
return r; return r;
} }
break; break;
@ -3202,7 +3249,7 @@ static LRESULT CALLBACK stoopidstoopidstoopid(HWND w, UINT m, WPARAM wp, LPARAM
} }
break; break;
} }
return CallWindowProc(omgwtfwhyohwhy,w,m,wp,lp); return CallWindowProcW(omgwtfwhyohwhy,w,m,wp,lp);
} }
struct egadsthisisretarded struct egadsthisisretarded
@ -3213,11 +3260,20 @@ struct egadsthisisretarded
char statustext[MAX_OSPATH]; char statustext[MAX_OSPATH];
}; };
void FS_Directorize(char *fname, size_t fnamesize)
{
size_t l = strlen(fname);
if (!l) //technically already a directory
return;
if (fname[l-1] == '\\' || fname[l-1] == '/')
return; //already a directory
Q_strncatz(fname, "/", fnamesize);
}
static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pDatafoo) static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pDatafoo)
{ //'stolen' from microsoft's knowledge base. { //'stolen' from microsoft's knowledge base.
//required to work around microsoft being annoying. //required to work around microsoft being annoying.
struct egadsthisisretarded *pData = (struct egadsthisisretarded*)pDatafoo; struct egadsthisisretarded *pData = (struct egadsthisisretarded*)pDatafoo;
TCHAR szDir[MAX_PATH];
// char *foo; // char *foo;
HWND edit = FindWindowEx(hwnd, NULL, "EDIT", NULL); HWND edit = FindWindowEx(hwnd, NULL, "EDIT", NULL);
HWND list; HWND list;
@ -3226,8 +3282,6 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
switch(uMsg) switch(uMsg)
{ {
case BFFM_INITIALIZED: case BFFM_INITIALIZED:
OutputDebugStringA("initialised\n");
//combat windows putting new windows behind everything else if it takes a while for UAC prompts to go away //combat windows putting new windows behind everything else if it takes a while for UAC prompts to go away
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
@ -3236,53 +3290,68 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
if (list) if (list)
omgwtfwhyohwhy = (WNDPROC)SetWindowLongPtr(list, GWLP_WNDPROC, (LONG_PTR)stoopidstoopidstoopid); omgwtfwhyohwhy = (WNDPROC)SetWindowLongPtr(list, GWLP_WNDPROC, (LONG_PTR)stoopidstoopidstoopid);
{
wchar_t szDir[MAX_PATH];
#ifndef _DEBUG #ifndef _DEBUG
//the standard location iiuc //the standard location iiuc
if (com_homepathenabled && SHGetSpecialFolderPath(NULL, szDir, CSIDL_PROGRAM_FILES, TRUE) && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE)) if (com_homepathenabled && pSHGetSpecialFolderPathW(NULL, szDir, CSIDL_PROGRAM_FILES, TRUE) && microsoft_accessW(szDir, ACCESS_READ | ACCESS_WRITE))
;
else if (microsoft_access("C:\\Games\\", ACCESS_READ | ACCESS_WRITE))
Q_strncpyz(szDir, "C:\\Games\\", sizeof(szDir));
else if (microsoft_access("C:\\", ACCESS_READ | ACCESS_WRITE))
Q_strncpyz(szDir, "C:\\", sizeof(szDir));
//if we're not an admin, install it somewhere else.
else if (SHGetSpecialFolderPath(NULL, szDir, CSIDL_LOCAL_APPDATA, TRUE) && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
;
else
#endif
if (GetCurrentDirectory(sizeof(szDir)/sizeof(TCHAR), szDir))// && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
; ;
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir); else if (microsoft_accessU("C:\\Games\\", ACCESS_READ | ACCESS_WRITE))
// SendMessage(hwnd, BFFM_SETEXPANDED, TRUE, (LPARAM)szDir); widen(szDir, sizeof(szDir), "C:\\Games\\");
SendMessageW(hwnd, BFFM_SETOKTEXT, TRUE, (LPARAM)L"Install"); else if (microsoft_accessU("C:\\", ACCESS_READ | ACCESS_WRITE))
widen(szDir, sizeof(szDir), "C:\\");
//if we're not an admin, install it somewhere else.
else if (pSHGetSpecialFolderPathW(NULL, szDir, CSIDL_LOCAL_APPDATA, TRUE) && microsoft_accessW(szDir, ACCESS_READ | ACCESS_WRITE))
;
else
#endif
if (GetCurrentDirectoryW(countof(szDir), szDir))// && microsoft_access(szDir, ACCESS_READ | ACCESS_WRITE))
;
SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM)szDir);
SendMessageW(hwnd, BFFM_SETEXPANDED, TRUE, (LPARAM)szDir);
SendMessageW(hwnd, BFFM_SETOKTEXT, TRUE, (LPARAM)widen(szDir, sizeof(szDir), "Install"));
}
break; break;
case BFFM_VALIDATEFAILEDA: case BFFM_VALIDATEFAILEDA:
if (!microsoft_access(pData->parentdir, ACCESS_READ | ACCESS_WRITE))
return 1;
if (edit)
GetWindowText(edit, pData->subdir, sizeof(pData->subdir));
if (microsoft_access(va("%s\\%s", pData->parentdir, pData->subdir), ACCESS_READ))
return MessageBoxU(hwnd, va("%s\\%s already exists!\nThis installer will (generally) not overwrite.\nIf you want to re-install, you must manually uninstall it first.\n\nContinue?", pData->parentdir, pData->subdir), fs_gamename.string, MB_ICONWARNING|MB_OKCANCEL|MB_TOPMOST) == IDCANCEL;
else
return MessageBoxU(hwnd, va("Install to %s\\%s ?", pData->parentdir, pData->subdir), fs_gamename.string, MB_OKCANCEL) == IDCANCEL;
case BFFM_VALIDATEFAILEDW: case BFFM_VALIDATEFAILEDW:
return 1;//!microsoft_access("C:\\Games\\", ACCESS_READ | ACCESS_WRITE)) if (!microsoft_accessU(pData->parentdir, ACCESS_READ | ACCESS_WRITE))
case BFFM_SELCHANGED:
OutputDebugStringA("selchanged\n");
if (SHGetPathFromIDList((LPITEMIDLIST)lp, pData->parentdir))
{ {
// OutputDebugString(va("selchanged: %s\n", szDir)); MessageBoxU(hwnd, va("%s is not writable.", pData->parentdir), fs_gamename.string, 0);
// while(foo = strchr(pData->parentdir, '\\')) return 1;
// *foo = '/'; }
//fixme: verify that id1 is a subdir perhaps? if (edit)
if (edit) {
wchar_t wide[256];
GetWindowTextW(edit, wide, countof(wide));
narrowen(pData->subdir, sizeof(pData->subdir), wide);
}
if (microsoft_accessU(va("%s%s", pData->parentdir, pData->subdir), ACCESS_READ))
return MessageBoxU(hwnd, va("%s%s already exists!\nThis installer will (generally) not overwrite existing data files.\nIf you want to re-install, you must manually uninstall it first.\n\nContinue?", pData->parentdir, pData->subdir), fs_gamename.string, MB_ICONWARNING|MB_OKCANCEL|MB_TOPMOST) == IDCANCEL;
else
return MessageBoxU(hwnd, va("Install to %s%s ?", pData->parentdir, pData->subdir), fs_gamename.string, MB_OKCANCEL) == IDCANCEL;
case BFFM_SELCHANGED:
{
wchar_t wide[MAX_PATH*2+2];
char *foo;
if (pSHGetPathFromIDListW((LPITEMIDLIST)lp, wide))
{ {
wchar_t wide[128]; narrowen(pData->parentdir, sizeof(pData->parentdir), wide);
SetWindowTextW(edit, widen(wide, sizeof(wide), fs_gamename.string)); FS_Directorize(pData->parentdir, sizeof(pData->parentdir));
SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)va("%s", pData->parentdir));
//this'll make microsoft happy.
while(foo = strchr(pData->parentdir, '/'))
*foo = '\\';
if (edit)
{
wchar_t wide[128];
SetWindowTextW(edit, widen(wide, sizeof(wide), fs_gamename.string));
SendMessageW(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)widen(wide, sizeof(wide), va("%s", pData->parentdir)));
}
else
SendMessageW(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)widen(wide, sizeof(wide), va("%s%s", pData->parentdir, fs_gamename.string)));
} }
else
SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)va("%s/%s", pData->parentdir, fs_gamename.string));
} }
break; break;
case BFFM_IUNKNOWN: case BFFM_IUNKNOWN:
@ -3298,16 +3367,6 @@ LRESULT CALLBACK NoCloseWindowProc(HWND w, UINT m, WPARAM wp, LPARAM lp)
return DefWindowProc(w, m, wp, lp); return DefWindowProc(w, m, wp, lp);
} }
void FS_Directorize(char *fname, size_t fnamesize)
{
size_t l = strlen(fname);
if (!l) //technically already a directory
return;
if (fname[l-1] == '\\' || fname[l-1] == '/')
return; //already a directory
Q_strncatz(fname, "/", fnamesize);
}
void FS_CreateBasedir(const char *path); void FS_CreateBasedir(const char *path);
qboolean Sys_DoInstall(void) qboolean Sys_DoInstall(void)
{ {
@ -3315,22 +3374,31 @@ qboolean Sys_DoInstall(void)
char exepath[MAX_OSPATH]; char exepath[MAX_OSPATH];
char newexepath[MAX_OSPATH]; char newexepath[MAX_OSPATH];
wchar_t wide[MAX_PATH]; wchar_t wide[MAX_PATH];
wchar_t wide2[MAX_PATH];
char resultpath[MAX_OSPATH]; char resultpath[MAX_OSPATH];
BROWSEINFOW bi; BROWSEINFOW bi;
LPITEMIDLIST il; LPITEMIDLIST il;
struct egadsthisisretarded diediedie; struct egadsthisisretarded diediedie;
if (!pSHGetSpecialFolderPathW)
{
MessageBoxU(NULL, "SHGetSpecialFolderPathW is not supported\n", fs_gamename.string, 0);
return TRUE;
}
if (fs_manifest && fs_manifest->eula) if (fs_manifest && fs_manifest->eula)
{ {
if (MessageBoxU(NULL, fs_manifest->eula, fs_gamename.string, MB_OKCANCEL|MB_TOPMOST|MB_DEFBUTTON2) != IDOK) if (MessageBoxU(NULL, fs_manifest->eula, fs_gamename.string, MB_OKCANCEL|MB_TOPMOST|MB_DEFBUTTON2) != IDOK)
return TRUE; return TRUE;
} }
Q_strncpyz(diediedie.subdir, fs_gamename.string, sizeof(diediedie.subdir));
_snwprintf(diediedie.title, countof(diediedie.title), L"Where would you like to install %s to?", widen(wide, sizeof(wide), fs_gamename.string));
GetCurrentDirectoryW(countof(wide)-1, wide);
memset(&bi, 0, sizeof(bi)); memset(&bi, 0, sizeof(bi));
bi.hwndOwner = mainwindow; //note that this is usually still null bi.hwndOwner = mainwindow; //note that this is usually still null
bi.pidlRoot = NULL; bi.pidlRoot = NULL;
_snwprintf(diediedie.title, countof(diediedie.title), L"Where would you like to install %s to?", widen(wide, sizeof(wide), fs_gamename.string));
GetCurrentDirectoryW(countof(wide)-1, wide);
bi.pszDisplayName = wide; bi.pszDisplayName = wide;
bi.lpszTitle = diediedie.title; bi.lpszTitle = diediedie.title;
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT | BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_VALIDATE; bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT | BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_VALIDATE;
@ -3338,12 +3406,10 @@ qboolean Sys_DoInstall(void)
bi.lParam = (LPARAM)&diediedie; bi.lParam = (LPARAM)&diediedie;
bi.iImage = 0; bi.iImage = 0;
Q_strncpyz(diediedie.subdir, fs_gamename.string, sizeof(diediedie.subdir)); il = pSHBrowseForFolderW?pSHBrowseForFolderW(&bi):NULL;
il = SHBrowseForFolderW(&bi);
if (il) if (il)
{ {
SHGetPathFromIDListW(il, wide); pSHGetPathFromIDListW(il, wide);
CoTaskMemFree(il); CoTaskMemFree(il);
} }
else else
@ -3359,9 +3425,10 @@ qboolean Sys_DoInstall(void)
FS_CreateBasedir(resultpath); FS_CreateBasedir(resultpath);
GetModuleFileName(NULL, exepath, sizeof(exepath)); GetModuleFileNameW(NULL, wide, countof(wide));
narrowen(exepath, sizeof(exepath), wide);
FS_NativePath(va("%s.exe", fs_gamename.string), FS_ROOT, newexepath, sizeof(newexepath)); FS_NativePath(va("%s.exe", fs_gamename.string), FS_ROOT, newexepath, sizeof(newexepath));
CopyFile(exepath, newexepath, FALSE); CopyFileU(exepath, newexepath, FALSE);
/*the game can now be run (using regular autoupdate stuff), but most installers are expected to install the data instead of just more downloaders, so lets do that with a 'nice' progress box*/ /*the game can now be run (using regular autoupdate stuff), but most installers are expected to install the data instead of just more downloaders, so lets do that with a 'nice' progress box*/
{ {
@ -3453,13 +3520,15 @@ qboolean Sys_DoInstall(void)
widen(wsz, sizeof(wsz), resultpath); widen(wsz, sizeof(wsz), resultpath);
psl->lpVtbl->SetWorkingDirectory(psl, wsz); psl->lpVtbl->SetWorkingDirectory(psl, wsz);
hres = psl->lpVtbl->QueryInterface(psl, &qIID_IPersistFile, (LPVOID*)&ppf); hres = psl->lpVtbl->QueryInterface(psl, &qIID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres) && SHGetSpecialFolderPath(NULL, startmenu, CSIDL_COMMON_PROGRAMS, TRUE)) if (SUCCEEDED(hres) && pSHGetSpecialFolderPathW(NULL, wsz, CSIDL_COMMON_PROGRAMS, TRUE))
{ {
WCHAR wsz[MAX_PATH]; WCHAR wsz[MAX_PATH];
narrowen(startmenu, sizeof(startmenu), wsz);
widen(wsz, sizeof(wsz), va("%s/%s.lnk", startmenu, fs_gamename.string)); widen(wsz, sizeof(wsz), va("%s/%s.lnk", startmenu, fs_gamename.string));
hres = ppf->lpVtbl->Save(ppf, wsz, TRUE); hres = ppf->lpVtbl->Save(ppf, wsz, TRUE);
if (hres == E_ACCESSDENIED && SHGetSpecialFolderPath(NULL, startmenu, CSIDL_PROGRAMS, TRUE)) if (hres == E_ACCESSDENIED && pSHGetSpecialFolderPathW(NULL, wsz, CSIDL_PROGRAMS, TRUE))
{ {
narrowen(startmenu, sizeof(startmenu), wsz);
widen(wsz, sizeof(wsz), va("%s/%s.lnk", startmenu, fs_gamename.string)); widen(wsz, sizeof(wsz), va("%s/%s.lnk", startmenu, fs_gamename.string));
hres = ppf->lpVtbl->Save(ppf, wsz, TRUE); hres = ppf->lpVtbl->Save(ppf, wsz, TRUE);
} }
@ -3470,7 +3539,7 @@ qboolean Sys_DoInstall(void)
} }
//now start it up properly. //now start it up properly.
ShellExecute(mainwindow, "open", newexepath, Q_strcasecmp(fs_manifest->installation, "quake")?"":"+sys_register_file_associations", resultpath, SW_SHOWNORMAL); ShellExecuteW(mainwindow, L"open", widen(wide, sizeof(wide), newexepath), Q_strcasecmp(fs_manifest->installation, "quake")?L"":L"+sys_register_file_associations", widen(wide2, sizeof(wide2), resultpath), SW_SHOWNORMAL);
return true; return true;
} }
qboolean Sys_RunInstaller(void) qboolean Sys_RunInstaller(void)
@ -3742,11 +3811,11 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
memset(&parms, 0, sizeof(parms)); memset(&parms, 0, sizeof(parms));
#ifndef MINGW // #ifndef MINGW
#if _MSC_VER > 1200 // #if _MSC_VER > 1200
Win7_Init(); Win7_Init();
#endif // #endif
#endif // #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#if _M_IX86_FP >= 1 #if _M_IX86_FP >= 1
@ -3781,11 +3850,16 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
#endif #endif
#ifdef CATCHCRASH #ifdef CATCHCRASH
LoadLibraryA ("DBGHELP"); //heap corruption can prevent loadlibrary from working properly, so do this in advance. LoadLibraryU ("DBGHELP"); //heap corruption can prevent loadlibrary from working properly, so do this in advance.
#ifdef _MSC_VER #ifdef _MSC_VER
__try __try
#else #else
AddVectoredExceptionHandler(true, nonmsvc_CrashExceptionHandler); {
PVOID (WINAPI *pAddVectoredExceptionHandler)(ULONG FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler);
dllfunction_t dbgfuncs[] = {{(void*)&pAddVectoredExceptionHandler, "AddVectoredExceptionHandler"}, {NULL,NULL}};
if (Sys_LoadLibrary("kernel32.dll", dbgfuncs) && pAddVectoredExceptionHandler)
pAddVectoredExceptionHandler(0, nonmsvc_CrashExceptionHandler);
}
#endif #endif
#endif #endif
{ {

View File

@ -252,7 +252,7 @@ static qboolean EditorSaveFile(char *s) //returns true if succesful
pos++; pos++;
} }
COM_WriteFile(s, data, len); COM_WriteFile(s, FS_GAMEONLY, data, len);
madechanges = false; madechanges = false;
editenabled = true; editenabled = true;

View File

@ -4,7 +4,7 @@
#include "shader.h" #include "shader.h"
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include "winquake.h"
#include "resource.h" #include "resource.h"
#else #else
#include <unistd.h> #include <unistd.h>
@ -68,7 +68,10 @@ LRESULT CALLBACK HeadlessWndProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lpara
} }
return 0; return 0;
default: default:
return DefWindowProcA(wnd, msg, wparam, lparam); if (WinNT)
return DefWindowProcW(wnd, msg, wparam, lparam);
else
return DefWindowProcA(wnd, msg, wparam, lparam);
} }
} }
#endif #endif
@ -79,31 +82,64 @@ static qboolean Headless_VID_Init (rendererstate_t *info, unsigned char *pale
//tray icon crap, so the user can still restore the game. //tray icon crap, so the user can still restore the game.
extern HWND mainwindow; extern HWND mainwindow;
extern HINSTANCE global_hInstance; extern HINSTANCE global_hInstance;
WNDCLASSW wc; if (WinNT)
NOTIFYICONDATAW data; {
WNDCLASSW wc;
NOTIFYICONDATAW data;
//Shell_NotifyIcon requires a window to provide events etc. //Shell_NotifyIcon requires a window to provide events etc.
wc.style = 0; wc.style = 0;
wc.lpfnWndProc = (WNDPROC)HeadlessWndProc; wc.lpfnWndProc = (WNDPROC)HeadlessWndProc;
wc.cbClsExtra = 0; wc.cbClsExtra = 0;
wc.cbWndExtra = 0; wc.cbWndExtra = 0;
wc.hInstance = global_hInstance; wc.hInstance = global_hInstance;
wc.hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); wc.hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1));
wc.hCursor = LoadCursor (NULL,IDC_ARROW); wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL; wc.hbrBackground = NULL;
wc.lpszMenuName = 0; wc.lpszMenuName = 0;
wc.lpszClassName = L"FTEHeadlessClass"; wc.lpszClassName = L"FTEHeadlessClass";
RegisterClassW(&wc); RegisterClassW(&wc);
mainwindow = CreateWindowExW(0L, wc.lpszClassName, L"FTE QuakeWorld", 0, 0, 0, 0, 0, NULL, NULL, global_hInstance, NULL); mainwindow = CreateWindowExW(0L, wc.lpszClassName, L"FTE QuakeWorld", 0, 0, 0, 0, 0, NULL, NULL, global_hInstance, NULL);
data.cbSize = sizeof(data); data.cbSize = sizeof(data);
data.hWnd = mainwindow; data.hWnd = mainwindow;
data.uID = 0; data.uID = 0;
data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
data.uCallbackMessage = WM_USER; data.uCallbackMessage = WM_USER;
data.hIcon = wc.hIcon; data.hIcon = wc.hIcon;
wcscpy(data.szTip, L"Right-click to restore"); wcscpy(data.szTip, L"Right-click to restore");
Shell_NotifyIconW(NIM_ADD, &data); if (pShell_NotifyIconW)
pShell_NotifyIconW(NIM_ADD, &data);
}
else
{
WNDCLASSA wc;
NOTIFYICONDATAA data;
//Shell_NotifyIcon requires a window to provide events etc.
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)HeadlessWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = global_hInstance;
wc.hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1));
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = "FTEHeadlessClass";
RegisterClassA(&wc);
mainwindow = CreateWindowExA(0L, wc.lpszClassName, "FTE QuakeWorld", 0, 0, 0, 0, 0, NULL, NULL, global_hInstance, NULL);
data.cbSize = sizeof(data);
data.hWnd = mainwindow;
data.uID = 0;
data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
data.uCallbackMessage = WM_USER;
data.hIcon = wc.hIcon;
//fixme: proper multibyte
Q_strncpyz(data.szTip, "Right-click to restore", sizeof(data.szTip));
Shell_NotifyIconA(NIM_ADD, &data);
}
#endif #endif
return true; return true;
} }
@ -111,6 +147,7 @@ static void Headless_VID_DeInit (void)
{ {
#ifdef _WIN32 #ifdef _WIN32
//tray icon crap, so the user can still restore the game. //tray icon crap, so the user can still restore the game.
//FIXME: remove tray icon. win95 won't do this automagically.
extern HWND mainwindow; extern HWND mainwindow;
DestroyWindow(mainwindow); DestroyWindow(mainwindow);
mainwindow = NULL; mainwindow = NULL;

View File

@ -575,10 +575,20 @@ void V_BonusFlash_f (void)
{ {
if (v_bonusflash.value || !Cmd_FromGamecode()) if (v_bonusflash.value || !Cmd_FromGamecode())
{ {
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215; if (Cmd_Argc() > 1)
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186; { //this is how I understand DP expects them.
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69; cl.cshifts[CSHIFT_BONUS].destcolor[0] = atof(Cmd_Argv(1));
cl.cshifts[CSHIFT_BONUS].percent = 50*v_bonusflash.value; cl.cshifts[CSHIFT_BONUS].destcolor[1] = atof(Cmd_Argv(2));
cl.cshifts[CSHIFT_BONUS].destcolor[2] = atof(Cmd_Argv(3));
cl.cshifts[CSHIFT_BONUS].percent = atof(Cmd_Argv(4))*255*v_bonusflash.value;
}
else
{
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
cl.cshifts[CSHIFT_BONUS].percent = 50*v_bonusflash.value;
}
} }
} }
void V_DarkFlash_f (void) void V_DarkFlash_f (void)
@ -1544,7 +1554,8 @@ void R_DrawNameTags(void)
e = WEDICT_NUM(w->progs, i); e = WEDICT_NUM(w->progs, i);
if (e->isfree) if (e->isfree)
continue; continue;
VectorInterpolate(e->v->absmin, 0.5, e->v->absmax, org); VectorInterpolate(e->v->mins, 0.5, e->v->maxs, org);
VectorAdd(org, e->v->origin, org);
VectorSubtract(org, r_refdef.vieworg, diff); VectorSubtract(org, r_refdef.vieworg, diff);
if (DotProduct(diff, diff) > 256*256) if (DotProduct(diff, diff) > 256*256)
continue; continue;

View File

@ -74,6 +74,16 @@ LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif #endif
//shell32 stuff that doesn't exist in win95
#define COBJMACROS
#include <shlobj.h>
#include <shellapi.h>
extern LPITEMIDLIST (STDAPICALLTYPE *pSHBrowseForFolderW)(LPBROWSEINFOW lpbi);
extern BOOL (STDAPICALLTYPE *pSHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath);
extern BOOL (STDAPICALLTYPE *pSHGetSpecialFolderPathW)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);
extern BOOL (STDAPICALLTYPE *pShell_NotifyIconW)(DWORD dwMessage, PNOTIFYICONDATAW lpData);
//void VID_LockBuffer (void); //void VID_LockBuffer (void);
//void VID_UnlockBuffer (void); //void VID_UnlockBuffer (void);

View File

@ -528,8 +528,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ARCH_DL_POSTFIX ".so" #define ARCH_DL_POSTFIX ".so"
#endif #endif
#if defined(__amd64__) #if defined(_M_AMD64) || defined(__amd64__)
#define ARCH_CPU_POSTFIX "amd" #ifdef _WIN32
#define ARCH_CPU_POSTFIX "x64"
#else
#define ARCH_CPU_POSTFIX "amd64"
#endif
#elif defined(_M_IX86) || defined(__i386__) #elif defined(_M_IX86) || defined(__i386__)
#define ARCH_CPU_POSTFIX "x86" #define ARCH_CPU_POSTFIX "x86"
#elif defined(__powerpc__) || defined(__ppc__) #elif defined(__powerpc__) || defined(__ppc__)

View File

@ -581,6 +581,20 @@ void Cmd_Exec_f (void)
int defdepth = COM_FDepthFile("default.cfg", true); int defdepth = COM_FDepthFile("default.cfg", true);
if (defdepth < cfgdepth) if (defdepth < cfgdepth)
Cbuf_InsertText("exec default.cfg\n", ((Cmd_FromGamecode() || untrusted) ? RESTRICT_INSECURE : Cmd_ExecLevel), false); Cbuf_InsertText("exec default.cfg\n", ((Cmd_FromGamecode() || untrusted) ? RESTRICT_INSECURE : Cmd_ExecLevel), false);
//hack to work around the more insideous hacks of other engines.
//namely: vid_restart at the end of config.cfg is evil, and NOT desired in FTE as it generally means any saved video settings are wrong.
if (l >= 13 && !strcmp(f+l-13, "\nvid_restart\n"))
{
Con_Printf(CON_WARNING "WARNING: %s came from a different engine\n", loc.rawname);
l -= 12;
}
else if (l >= 14 && !strcmp(f+l-14, "\nvid_restart\r\n"))
{
Con_Printf(CON_WARNING "WARNING: %s came from a different engine\n", loc.rawname);
l -= 13;
}
f[l] = 0;
} }
// don't execute anything if it was from server (either the stuffcmd/localcmd, or the file) // don't execute anything if it was from server (either the stuffcmd/localcmd, or the file)
if (!strcmp(name, "default.cfg") && !(Cmd_FromGamecode() || untrusted)) if (!strcmp(name, "default.cfg") && !(Cmd_FromGamecode() || untrusted))

View File

@ -5065,6 +5065,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
int bonemap[MAX_BONES]; int bonemap[MAX_BONES];
char *e; char *e;
size_t psasize; size_t psasize;
void *psabuffer;
pskpnts_t *pnts = NULL; pskpnts_t *pnts = NULL;
pskvtxw_t *vtxw = NULL; pskvtxw_t *vtxw = NULL;
@ -5205,13 +5206,14 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
/*attempt to load a psa file. don't die if we can't find one*/ /*attempt to load a psa file. don't die if we can't find one*/
COM_StripExtension(mod->name, psaname, sizeof(psaname)); COM_StripExtension(mod->name, psaname, sizeof(psaname));
Q_strncatz(psaname, ".psa", sizeof(psaname)); Q_strncatz(psaname, ".psa", sizeof(psaname));
buffer = COM_LoadFile(psaname, 5, &psasize); buffer = NULL;//test
if (buffer) psabuffer = COM_LoadFile(psaname, 5, &psasize);
if (psabuffer)
{ {
pos = 0; pos = 0;
while (pos < psasize && !fail) while (pos < psasize && !fail)
{ {
chunk = (pskchunk_t*)((char*)buffer + pos); chunk = (pskchunk_t*)((char*)psabuffer + pos);
chunk->version = LittleLong(chunk->version); chunk->version = LittleLong(chunk->version);
chunk->recordsize = LittleLong(chunk->recordsize); chunk->recordsize = LittleLong(chunk->recordsize);
chunk->numrecords = LittleLong(chunk->numrecords); chunk->numrecords = LittleLong(chunk->numrecords);
@ -5224,7 +5226,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
else if (!strcmp("BONENAMES", chunk->id) && chunk->recordsize == sizeof(pskboneinfo_t)) else if (!strcmp("BONENAMES", chunk->id) && chunk->recordsize == sizeof(pskboneinfo_t))
{ {
/*parsed purely to ensure that the bones match the main model*/ /*parsed purely to ensure that the bones match the main model*/
pskboneinfo_t *animbones = (pskboneinfo_t*)((char*)buffer + pos); pskboneinfo_t *animbones = (pskboneinfo_t*)((char*)psabuffer + pos);
pos += chunk->recordsize * chunk->numrecords; pos += chunk->recordsize * chunk->numrecords;
if (num_boneinfo != chunk->numrecords) if (num_boneinfo != chunk->numrecords)
{ {
@ -5262,7 +5264,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
else if (!strcmp("ANIMINFO", chunk->id) && chunk->recordsize == sizeof(pskaniminfo_t)) else if (!strcmp("ANIMINFO", chunk->id) && chunk->recordsize == sizeof(pskaniminfo_t))
{ {
num_animinfo = chunk->numrecords; num_animinfo = chunk->numrecords;
animinfo = (pskaniminfo_t*)((char*)buffer + pos); animinfo = (pskaniminfo_t*)((char*)psabuffer + pos);
pos += chunk->recordsize * chunk->numrecords; pos += chunk->recordsize * chunk->numrecords;
for (i = 0; i < num_animinfo; i++) for (i = 0; i < num_animinfo; i++)
@ -5277,7 +5279,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
else if (!strcmp("ANIMKEYS", chunk->id) && chunk->recordsize == sizeof(pskanimkeys_t)) else if (!strcmp("ANIMKEYS", chunk->id) && chunk->recordsize == sizeof(pskanimkeys_t))
{ {
num_animkeys = chunk->numrecords; num_animkeys = chunk->numrecords;
animkeys = (pskanimkeys_t*)((char*)buffer + pos); animkeys = (pskanimkeys_t*)((char*)psabuffer + pos);
pos += chunk->recordsize * chunk->numrecords; pos += chunk->recordsize * chunk->numrecords;
for (i = 0; i < num_animkeys; i++) for (i = 0; i < num_animkeys; i++)
@ -5317,11 +5319,11 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
num_animkeys = 0; num_animkeys = 0;
fail = false; fail = false;
} }
BZ_Free(buffer);
} }
if (fail) if (fail)
{ {
BZ_Free(psabuffer);
return false; return false;
} }
@ -5613,6 +5615,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
gmdl[i].nextsurf = (i != num_matt-1)?&gmdl[i+1]:NULL; gmdl[i].nextsurf = (i != num_matt-1)?&gmdl[i+1]:NULL;
} }
BZ_Free(psabuffer);
if (fail) if (fail)
{ {
return false; return false;

View File

@ -2271,7 +2271,8 @@ unsigned int qchar_encode(char *out, unsigned int unicode, int maxlen, qboolean
{ {
static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
//FIXME: is it a bug that we can't distinguish between true ascii and 0xe0XX ? //FIXME: is it a bug that we can't distinguish between true ascii and 0xe0XX ?
if (((unicode >= 32 || unicode == '\n' || unicode == '\t' || unicode == '\r') && unicode < 128) || (unicode >= 0xe000 && unicode <= 0xe0ff)) //ntrv are considered special by parsefunstring and are not remapped back to the quake glyphs, so try to keep them as quake glyphs where possible
if (((unicode >= 32 || unicode == '\n' || unicode == '\t' || unicode == '\r') && unicode < 128) || (unicode >= 0xe000 && unicode <= 0xe0ff && unicode != (0xe000|'\n') && unicode != (0xe000|'\t') && unicode != (0xe000|'\r') && unicode != (0xe000|'\v')))
{ //quake compatible chars { //quake compatible chars
if (maxlen < 1) if (maxlen < 1)
return 0; return 0;
@ -2965,7 +2966,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
while(*str) while(*str)
{ {
if (*str & 0x80 && utf8 > 0) if ((*str & 0x80) && utf8 > 0)
{ //check for utf-8 { //check for utf-8
int decodeerror; int decodeerror;
char *end; char *end;

View File

@ -344,8 +344,6 @@ extern char com_homepath[MAX_OSPATH];
extern char com_configdir[MAX_OSPATH]; //dir to put cfg_save configs in extern char com_configdir[MAX_OSPATH]; //dir to put cfg_save configs in
//extern char *com_basedir; //extern char *com_basedir;
void COM_WriteFile (const char *filename, const void *data, int len);
//qofs_Make is used to 'construct' a variable of qofs_t type. this is so the code can merge two 32bit ints on old systems and use a long long type internally without generating warnings about bit shifts when qofs_t is only 32bit instead. //qofs_Make is used to 'construct' a variable of qofs_t type. this is so the code can merge two 32bit ints on old systems and use a long long type internally without generating warnings about bit shifts when qofs_t is only 32bit instead.
#if defined(__amd64__) || defined(_AMD64_) || __WORDSIZE == 64 #if defined(__amd64__) || defined(_AMD64_) || __WORDSIZE == 64
#define FS_64BIT #define FS_64BIT
@ -443,6 +441,8 @@ enum fs_relative{
FS_SYSTEM //a system path. absolute paths are explicitly allowed and expected. FS_SYSTEM //a system path. absolute paths are explicitly allowed and expected.
}; };
void COM_WriteFile (const char *filename, enum fs_relative fsroot, const void *data, int len);
void FS_FlushFSHashReally(qboolean domutexes); void FS_FlushFSHashReally(qboolean domutexes);
void FS_FlushFSHashWritten(void); void FS_FlushFSHashWritten(void);
void FS_FlushFSHashRemoved(void); void FS_FlushFSHashRemoved(void);
@ -458,9 +458,9 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
vfsfile_t *FS_OpenTemp(void); vfsfile_t *FS_OpenTemp(void);
vfsfile_t *FS_OpenTCP(const char *name, int defaultport); vfsfile_t *FS_OpenTCP(const char *name, int defaultport);
#define countof(array) (sizeof(array)/sizeof(array[0]))
#ifdef _WIN32 #ifdef _WIN32
//windows doesn't support utf-8. Which is a shame really, because that's the charset we expect from everything. //windows doesn't support utf-8. Which is a shame really, because that's the charset we expect from everything.
#define countof(array) (sizeof(array)/sizeof(array[0]))
char *narrowen(char *out, size_t outlen, wchar_t *wide); char *narrowen(char *out, size_t outlen, wchar_t *wide);
wchar_t *widen(wchar_t *out, size_t outbytes, const char *utf8); wchar_t *widen(wchar_t *out, size_t outbytes, const char *utf8);
#define __L(x) L ## x #define __L(x) L ## x

View File

@ -740,6 +740,7 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
if (var->latched_string && !strcmp(var->latched_string, value)) //no point, this would force the same if (var->latched_string && !strcmp(var->latched_string, value)) //no point, this would force the same
return NULL; return NULL;
Cvar_ConfigChanged();
if (var->latched_string) if (var->latched_string)
Z_Free(var->latched_string); Z_Free(var->latched_string);
if (!strcmp(var->string, value)) //latch to the original value? remove the latch. if (!strcmp(var->string, value)) //latch to the original value? remove the latch.

View File

@ -581,7 +581,7 @@ COM_Path_f
*/ */
static void COM_PathLine(searchpath_t *s) static void COM_PathLine(searchpath_t *s)
{ {
Con_Printf("%s %s%s%s%s%s%s\n", s->logicalpath, Con_Printf(U8("%s")" %s%s%s%s%s%s\n", s->logicalpath,
(s->flags & SPF_REFERENCED)?"^[(ref)\\tip\\Referenced\\desc\\Package will auto-download to clients^]":"", (s->flags & SPF_REFERENCED)?"^[(ref)\\tip\\Referenced\\desc\\Package will auto-download to clients^]":"",
(s->flags & SPF_TEMPORARY)?"^[(temp)\\tip\\Temporary\\desc\\Flushed on map change^]":"", (s->flags & SPF_TEMPORARY)?"^[(temp)\\tip\\Temporary\\desc\\Flushed on map change^]":"",
(s->flags & SPF_COPYPROTECTED)?"^[(c)\\tip\\Copyrighted\\desc\\Copy-Protected and is not downloadable^]":"", (s->flags & SPF_COPYPROTECTED)?"^[(c)\\tip\\Copyrighted\\desc\\Copy-Protected and is not downloadable^]":"",
@ -672,15 +672,18 @@ COM_Locate_f
void COM_Locate_f (void) void COM_Locate_f (void)
{ {
flocation_t loc; flocation_t loc;
if (FS_FLocateFile(Cmd_Argv(1), FSLFRT_LENGTH, &loc)>=0) char *f = Cmd_Argv(1);
if (strchr(f, '^')) //fte's filesystem is assumed to be utf-8, but that doesn't mean that console input is. and I'm too lazy to utf-8ify the string (in part because markup can be used to exploit ascii assumptions).
Con_Printf("Warning: filename contains markup. If this is because of unicode, set com_parseutf8 1\n");
if (FS_FLocateFile(f, FSLFRT_LENGTH, &loc)>=0)
{ {
if (!*loc.rawname) if (!*loc.rawname)
{ {
Con_Printf("File is %u bytes compressed inside %s\n", (unsigned)loc.len, loc.search->logicalpath); Con_Printf("File is %u bytes compressed inside "U8("%s")"\n", (unsigned)loc.len, loc.search->logicalpath);
} }
else else
{ {
Con_Printf("Inside %s (%u bytes)\n %s\n", loc.rawname, (unsigned)loc.len, loc.search->logicalpath); Con_Printf("Inside "U8("%s")" (%u bytes)\n "U8("%s")"\n", loc.rawname, (unsigned)loc.len, loc.search->logicalpath);
} }
} }
else else
@ -694,14 +697,14 @@ COM_WriteFile
The filename will be prefixed by the current game directory The filename will be prefixed by the current game directory
============ ============
*/ */
void COM_WriteFile (const char *filename, const void *data, int len) void COM_WriteFile (const char *filename, enum fs_relative fsroot, const void *data, int len)
{ {
vfsfile_t *vfs; vfsfile_t *vfs;
Sys_Printf ("COM_WriteFile: %s\n", filename); Sys_Printf ("COM_WriteFile: %s\n", filename);
FS_CreatePath(filename, FS_GAMEONLY); FS_CreatePath(filename, fsroot);
vfs = FS_OpenVFS(filename, "wb", FS_GAMEONLY); vfs = FS_OpenVFS(filename, "wb", fsroot);
if (vfs) if (vfs)
{ {
VFS_WRITE(vfs, data, len); VFS_WRITE(vfs, data, len);
@ -928,7 +931,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation
{ {
int depth=0; int depth=0;
searchpath_t *search; searchpath_t *search;
char cleanpath[MAX_QPATH]; char cleanpath[MAX_OSPATH];
flocation_t allownoloc; flocation_t allownoloc;
void *pf; void *pf;
@ -3158,7 +3161,6 @@ void FS_ReloadPackFiles_f(void)
#ifdef MINGW #ifdef MINGW
#define byte BYTE //some versions of mingw headers are broken slightly. this lets it compile. #define byte BYTE //some versions of mingw headers are broken slightly. this lets it compile.
#endif #endif
#include <shlobj.h>
static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir, char *fname) static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir, char *fname)
{ {
/* /*
@ -3209,7 +3211,7 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
case BFFM_VALIDATEFAILEDW: case BFFM_VALIDATEFAILEDW:
break; //FIXME: validate that the gamedir contains what its meant to break; //FIXME: validate that the gamedir contains what its meant to
case BFFM_SELCHANGED: case BFFM_SELCHANGED:
if (SHGetPathFromIDListW((LPITEMIDLIST) lp, szDir)) if (pSHGetPathFromIDListW((LPITEMIDLIST) lp, szDir))
{ {
wchar_t statustxt[MAX_OSPATH]; wchar_t statustxt[MAX_OSPATH];
while(foo = wcschr(szDir, '\\')) while(foo = wcschr(szDir, '\\'))
@ -3225,6 +3227,7 @@ static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LP
} }
return 0; return 0;
} }
int MessageBoxU(HWND hWnd, char *lpText, char *lpCaption, UINT uType);
#endif #endif
qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *poshname, const char *savedname) qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *poshname, const char *savedname)
@ -3242,6 +3245,10 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
widen(resultpath, sizeof(resultpath), poshname); widen(resultpath, sizeof(resultpath), poshname);
_snwprintf(title, countof(title), L"Please locate your existing %s installation", resultpath); _snwprintf(title, countof(title), L"Please locate your existing %s installation", resultpath);
//force mouse to deactivate, so that we can actually see it.
INS_UpdateGrabs(false, false);
bi.lpszTitle = title; bi.lpszTitle = title;
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT; bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
@ -3249,33 +3256,16 @@ qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *
bi.lParam = 0;//(LPARAM)poshname; bi.lParam = 0;//(LPARAM)poshname;
bi.iImage = 0; bi.iImage = 0;
//force mouse to deactivate, so that we can actually see it. il = pSHBrowseForFolderW?pSHBrowseForFolderW(&bi):NULL;
INS_UpdateGrabs(false, false);
il = SHBrowseForFolderW(&bi);
if (il) if (il)
{ {
SHGetPathFromIDListW(il, resultpath); pSHGetPathFromIDListW(il, resultpath);
CoTaskMemFree(il); CoTaskMemFree(il);
narrowen(basepath, basepathsize, resultpath); narrowen(basepath, basepathsize, resultpath);
if (savedname) if (savedname)
{ {
HKEY key = NULL; if (MessageBoxU(mainwindow, va("Would you like to save the location of %s as:\n%s", poshname, resultpath), "Save Instaltion path", MB_YESNO|MB_DEFBUTTON2) == IDYES)
//and save it into the windows registry MyRegSetValue(HKEY_CURRENT_USER, "SOFTWARE\\" FULLENGINENAME "\\GamePaths", savedname, REG_SZ, basepath, strlen(basepath));
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\" _L(FULLENGINENAME) L"\\GamePaths",
0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&key,
NULL) == ERROR_SUCCESS)
{
wchar_t wsavedname[MAX_OSPATH];
widen(wsavedname, sizeof(wsavedname), savedname);
RegSetValueExW(key, wsavedname, 0, REG_SZ, (BYTE*)resultpath, sizeof(wchar_t)*wcslen(resultpath));
RegCloseKey(key);
}
} }
return true; return true;
} }

View File

@ -328,12 +328,13 @@ static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *qu
if (!WinNT) if (!WinNT)
{ {
//FILE_SHARE_DELETE is not supported in 9x, sorry.
if ((write && read) || append) if ((write && read) || append)
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (write) else if (write)
h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
else if (read) else if (read)
h = CreateFileA(osname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); h = CreateFileA(osname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
else else
h = INVALID_HANDLE_VALUE; h = INVALID_HANDLE_VALUE;
} }
@ -341,7 +342,6 @@ static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *qu
{ {
wchar_t wide[MAX_OSPATH]; wchar_t wide[MAX_OSPATH];
widen(wide, sizeof(wide), osname); widen(wide, sizeof(wide), osname);
h = INVALID_HANDLE_VALUE; h = INVALID_HANDLE_VALUE;
if (write || append) if (write || append)
{ {

View File

@ -116,10 +116,12 @@ void CalcSurfaceExtents (model_t *mod, msurface_t *s)
bmaxs[i] = ceil(maxs[i]/(1<<s->lmshift)); bmaxs[i] = ceil(maxs[i]/(1<<s->lmshift));
s->texturemins[i] = bmins[i] << s->lmshift; s->texturemins[i] = bmins[i] << s->lmshift;
s->extents[i] = (bmaxs[i] - bmins[i]) << s->lmshift; s->extents[i] = (bmaxs[i] - bmins[i]);
// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 8176 ) //q2 uses 512. probably for skys. // if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 17 ) //vanilla used 16(+1), glquake used 17(+1). FTE uses 255(+1), but we omit lightmapping instead of crashing if its larger than our limit, so we omit the check here. different engines use different limits here, many of them make no sense.
// Con_Printf ("Bad surface extents (texture %s)\n", s->texinfo->texture->name); // Con_Printf ("Bad surface extents (texture %s, more than %i lightmap samples)\n", s->texinfo->texture->name, s->extents[i]);
s->extents[i] <<= s->lmshift;
} }
} }

View File

@ -902,7 +902,7 @@ void PM_CategorizePosition (void)
pmove.onground = false; pmove.onground = false;
else else
{ {
pmove.onground = true; pmove.onground = !trace.startsolid;
pmove.groundent = trace.entnum; pmove.groundent = trace.entnum;
groundplane = trace.plane; groundplane = trace.plane;
pmove.waterjumptime = 0; pmove.waterjumptime = 0;
@ -1273,8 +1273,8 @@ were contacted during the move.
*/ */
void PM_PlayerMove (float gamespeed) void PM_PlayerMove (float gamespeed)
{ {
int i; // int i;
int tmp; //for rounding // int tmp; //for rounding
frametime = pmove.cmd.msec * 0.001*gamespeed; frametime = pmove.cmd.msec * 0.001*gamespeed;
pmove.numtouch = 0; pmove.numtouch = 0;
@ -1337,7 +1337,7 @@ void PM_PlayerMove (float gamespeed)
else else
PM_AirMove (); PM_AirMove ();
//round to network precision /* //round to network precision
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
tmp = floor(pmove.velocity[i]*8 + 0.5); tmp = floor(pmove.velocity[i]*8 + 0.5);
@ -1346,7 +1346,7 @@ void PM_PlayerMove (float gamespeed)
pmove.origin[i] = tmp/8.0; pmove.origin[i] = tmp/8.0;
} }
PM_NudgePosition (); PM_NudgePosition ();
*/
// set onground, watertype, and waterlevel for final spot // set onground, watertype, and waterlevel for final spot
PM_CategorizePosition (); PM_CategorizePosition ();

View File

@ -514,7 +514,7 @@ pbool QDECL QC_WriteFile(const char *name, void *data, int len)
{ {
char buffer[256]; char buffer[256];
Q_snprintfz(buffer, sizeof(buffer), "%s", name); Q_snprintfz(buffer, sizeof(buffer), "%s", name);
COM_WriteFile(buffer, data, len); COM_WriteFile(buffer, FS_GAMEONLY, data, len);
return true; return true;
} }
@ -1879,7 +1879,7 @@ void PF_fclose_i (int fnum)
switch(pf_fopen_files[fnum].accessmode) switch(pf_fopen_files[fnum].accessmode)
{ {
case FRIK_FILE_MMAP_RW: case FRIK_FILE_MMAP_RW:
COM_WriteFile(pf_fopen_files[fnum].name, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); COM_WriteFile(pf_fopen_files[fnum].name, FS_GAMEONLY, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len);
/*fall through*/ /*fall through*/
case FRIK_FILE_MMAP_READ: case FRIK_FILE_MMAP_READ:
pf_fopen_files[fnum].prinst->AddressableFree(pf_fopen_files[fnum].prinst, pf_fopen_files[fnum].data); pf_fopen_files[fnum].prinst->AddressableFree(pf_fopen_files[fnum].prinst, pf_fopen_files[fnum].data);
@ -1891,7 +1891,7 @@ void PF_fclose_i (int fnum)
break; break;
case 1: case 1:
case 2: case 2:
COM_WriteFile(pf_fopen_files[fnum].name, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); COM_WriteFile(pf_fopen_files[fnum].name, FS_GAMEONLY, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len);
BZ_Free(pf_fopen_files[fnum].data); BZ_Free(pf_fopen_files[fnum].data);
break; break;
case 3: case 3:
@ -2859,7 +2859,7 @@ void QCBUILTIN PF_chr2str (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
{ {
ch = G_FLOAT(OFS_PARM0 + i*3); ch = G_FLOAT(OFS_PARM0 + i*3);
if (VMUTF8 || ch > 0xff) if (VMUTF8 || ch > 0xff)
s += unicode_encode(s, ch, (string+sizeof(string)-1)-s, VMUTF8MARKUP); s += unicode_encode(s, ch, (string+sizeof(string)-1)-s, VMUTF8MARKUP||(ch>0xff));
else else
*s++ = G_FLOAT(OFS_PARM0 + i*3); *s++ = G_FLOAT(OFS_PARM0 + i*3);
} }
@ -4818,7 +4818,7 @@ void QCBUILTIN PF_coredump (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
int size = 1024*1024*8; int size = 1024*1024*8;
char *buffer = BZ_Malloc(size); char *buffer = BZ_Malloc(size);
prinst->save_ents(prinst, buffer, &size, size, 3); prinst->save_ents(prinst, buffer, &size, size, 3);
COM_WriteFile("core.txt", buffer, size); COM_WriteFile("core.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer); BZ_Free(buffer);
} }
void QCBUILTIN PF_eprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_eprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)

View File

@ -382,6 +382,7 @@ void QCBUILTIN PF_cl_GetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr
void QCBUILTIN PF_cl_SetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_SetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_keynumtostring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_keynumtostring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_findkeysforcommandex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_setmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_setmousetarget (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View File

@ -102,7 +102,7 @@ void VM_fclose (int fnum, int owner)
case VM_FS_WRITE: case VM_FS_WRITE:
case VM_FS_APPEND: case VM_FS_APPEND:
case VM_FS_APPEND2: case VM_FS_APPEND2:
COM_WriteFile(vm_fopen_files[fnum].name, vm_fopen_files[fnum].data, vm_fopen_files[fnum].len); COM_WriteFile(vm_fopen_files[fnum].name, FS_GAMEONLY, vm_fopen_files[fnum].data, vm_fopen_files[fnum].len);
BZ_Free(vm_fopen_files[fnum].data); BZ_Free(vm_fopen_files[fnum].data);
break; break;
} }

View File

@ -85,7 +85,12 @@ unsigned int WINAPI threadwrapper(void *args)
Sys_SetThreadName(GetCurrentThreadId(), ((threadwrap_t *)args)->name); Sys_SetThreadName(GetCurrentThreadId(), ((threadwrap_t *)args)->name);
#endif #endif
#ifdef CATCHCRASH #ifdef CATCHCRASH
AddVectoredExceptionHandler(true, nonmsvc_CrashExceptionHandler); {
PVOID (WINAPI *pAddVectoredExceptionHandler)(ULONG FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler);
dllfunction_t dbgfuncs[] = {{(void*)&pAddVectoredExceptionHandler, "AddVectoredExceptionHandler"}, {NULL,NULL}};
if (Sys_LoadLibrary("kernel32.dll", dbgfuncs) && pAddVectoredExceptionHandler)
pAddVectoredExceptionHandler(0, nonmsvc_CrashExceptionHandler);
}
#endif #endif
free(args); free(args);
@ -177,7 +182,7 @@ void *Sys_CreateMutex(void)
return (void *)mutex; return (void *)mutex;
} }
qboolean Sys_TryLockMutex(void *mutex) /*qboolean Sys_TryLockMutex(void *mutex)
{ {
#ifdef _DEBUG #ifdef _DEBUG
if (!mutex) if (!mutex)
@ -196,7 +201,7 @@ qboolean Sys_TryLockMutex(void *mutex)
return true; return true;
} }
return false; return false;
} }*/
qboolean Sys_LockMutex(void *mutex) qboolean Sys_LockMutex(void *mutex)
{ {

View File

@ -595,13 +595,13 @@ static void initD3D9(HWND hWnd, rendererstate_t *info)
d3d9dll = LoadLibrary("d3d9.dll"); d3d9dll = LoadLibrary("d3d9.dll");
if (!d3d9dll) if (!d3d9dll)
{ {
Con_Printf("Direct3d 9 does not appear to be installed\n"); Con_Printf(CON_ERROR "Direct3d 9 does not appear to be installed\n");
return; return;
} }
pDirect3DCreate9 = (void*)GetProcAddress(d3d9dll, "Direct3DCreate9"); pDirect3DCreate9 = (void*)GetProcAddress(d3d9dll, "Direct3DCreate9");
if (!pDirect3DCreate9) if (!pDirect3DCreate9)
{ {
Con_Printf("Direct3d 9 does not appear to be installed properly\n"); Con_Printf(CON_ERROR "Direct3d 9 does not appear to be installed properly\n");
return; return;
} }

View File

@ -582,9 +582,9 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
if (!sk->qwskin && *sk->qwskinname) if (!sk->qwskin && *sk->qwskinname)
sk->qwskin = Skin_Lookup(sk->qwskinname); sk->qwskin = Skin_Lookup(sk->qwskinname);
if (sk->q1lower != Q1UNSPECIFIED) if (sk->q1lower != Q1UNSPECIFIED)
bc = sk->q1lower; bc = e->bottomcolour = sk->q1lower;
if (sk->q1upper != Q1UNSPECIFIED) if (sk->q1upper != Q1UNSPECIFIED)
bc = sk->q1upper; bc = e->topcolour = sk->q1upper;
plskin = sk->qwskin; plskin = sk->qwskin;
} }
} }
@ -610,7 +610,9 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
if (!gl_nocolors.ival || forced) if (!gl_nocolors.ival || forced)
{ {
if (!plskin || plskin->loadstate == SKIN_FAILED) if (plskin && plskin->loadstate == SKIN_LOADING)
plskin = NULL;
else if (!plskin || plskin->loadstate != SKIN_LOADED)
{ {
if (e->playerindex >= 0 && e->playerindex <= MAX_CLIENTS) if (e->playerindex >= 0 && e->playerindex <= MAX_CLIENTS)
{ {

View File

@ -6620,7 +6620,7 @@ void Mod_Terrain_Create_f(void)
"origin \"0 0 1024\"\n" "origin \"0 0 1024\"\n"
"}\n" "}\n"
, Cmd_Argv(2)); , Cmd_Argv(2));
COM_WriteFile(mname, mdata, strlen(mdata)); COM_WriteFile(mname, FS_GAMEONLY, mdata, strlen(mdata));
//FIXME: create 4 sections around the origin //FIXME: create 4 sections around the origin
} }

View File

@ -79,7 +79,8 @@ typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey,
extern cvar_t vid_conwidth, vid_conautoscale; extern cvar_t vid_conwidth, vid_conautoscale;
#define WINDOW_CLASS_NAME L"FTEGLQuake" #define WINDOW_CLASS_NAME_W L"FTEGLQuake"
#define WINDOW_CLASS_NAME_A "FTEGLQuake"
#define MAX_MODE_LIST 128 #define MAX_MODE_LIST 128
#define VID_ROW_SIZE 3 #define VID_ROW_SIZE 3
@ -470,8 +471,10 @@ qboolean GLInitialise (char *renderer)
if (*renderer && stricmp(renderer, "opengl32.dll") && stricmp(renderer, "opengl32")) if (*renderer && stricmp(renderer, "opengl32.dll") && stricmp(renderer, "opengl32"))
{ {
unsigned int emode = SetErrorMode(SEM_FAILCRITICALERRORS); /*no annoying errors if they use glide*/
Con_DPrintf ("Loading renderer dll \"%s\"", renderer); Con_DPrintf ("Loading renderer dll \"%s\"", renderer);
hInstGL = Sys_LoadLibrary(opengldllname, NULL); hInstGL = Sys_LoadLibrary(opengldllname, NULL);
SetErrorMode(emode);
if (hInstGL) if (hInstGL)
{ {
usingminidriver = true; usingminidriver = true;
@ -531,7 +534,7 @@ qboolean GLInitialise (char *renderer)
} }
else else
{ {
qwglSwapLayerBuffers = (void *)getwglfunc("wglSwapLayerBuffers"); qwglSwapLayerBuffers = NULL;//(void *)getwglfunc("wglSwapLayerBuffers");
qSwapBuffers = SwapBuffers; qSwapBuffers = SwapBuffers;
qChoosePixelFormat = ChoosePixelFormat; qChoosePixelFormat = ChoosePixelFormat;
qSetPixelFormat = SetPixelFormat; qSetPixelFormat = SetPixelFormat;
@ -765,18 +768,36 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
WindowRect = centerrect(pleft, ptop, pwidth, pheight, wwidth, wheight); WindowRect = centerrect(pleft, ptop, pwidth, pheight, wwidth, wheight);
// Create the DIB window // Create the DIB window
dibwindow = CreateWindowExW ( if (WinNT)
ExWindowStyle, {
WINDOW_CLASS_NAME, dibwindow = CreateWindowExW (
_L(FULLENGINENAME), ExWindowStyle,
WindowStyle, WINDOW_CLASS_NAME_W,
WindowRect.left, WindowRect.top, _L(FULLENGINENAME),
WindowRect.right - WindowRect.left, WindowStyle,
WindowRect.bottom - WindowRect.top, WindowRect.left, WindowRect.top,
sys_parentwindow, WindowRect.right - WindowRect.left,
NULL, WindowRect.bottom - WindowRect.top,
global_hInstance, sys_parentwindow,
NULL); NULL,
global_hInstance,
NULL);
}
else
{
dibwindow = CreateWindowExA (
ExWindowStyle,
WINDOW_CLASS_NAME_A,
FULLENGINENAME,
WindowStyle,
WindowRect.left, WindowRect.top,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
sys_parentwindow,
NULL,
global_hInstance,
NULL);
}
if (!dibwindow) if (!dibwindow)
{ {
@ -889,7 +910,7 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info)
gdevmode.dmBitsPerPel = info->bpp; gdevmode.dmBitsPerPel = info->bpp;
if (info->bpp && (gdevmode.dmBitsPerPel < 15)) if (info->bpp && (gdevmode.dmBitsPerPel < 15))
{ {
Con_Printf("Forcing at least 16bpp\n"); Con_Printf("Forcing at least 15bpp\n");
gdevmode.dmBitsPerPel = 16; gdevmode.dmBitsPerPel = 16;
} }
gdevmode.dmDisplayFrequency = info->rate; gdevmode.dmDisplayFrequency = info->rate;
@ -899,7 +920,7 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info)
if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{ {
Con_SafePrintf((gdevmode.dmFields&DM_DISPLAYFREQUENCY)?"Windows rejected mode %i*%i*%i*%i\n":"Windows rejected mode %i*%i*%i\n", (int)gdevmode.dmPelsWidth, (int)gdevmode.dmPelsHeight, (int)gdevmode.dmBitsPerPel, (int)gdevmode.dmDisplayFrequency); Con_SafePrintf((gdevmode.dmFields&DM_DISPLAYFREQUENCY)?"Windows rejected mode %i*%i*%ibpp@%ihz\n":"Windows rejected mode %i*%i*%ibpp\n", (int)gdevmode.dmPelsWidth, (int)gdevmode.dmPelsHeight, (int)gdevmode.dmBitsPerPel, (int)gdevmode.dmDisplayFrequency);
return false; return false;
} }
} }
@ -927,18 +948,36 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info)
wheight = rect.bottom - rect.top; wheight = rect.bottom - rect.top;
// Create the DIB window // Create the DIB window
dibwindow = CreateWindowExW ( if(WinNT)
ExWindowStyle, {
WINDOW_CLASS_NAME, dibwindow = CreateWindowExW (
_L(FULLENGINENAME), ExWindowStyle,
WindowStyle, WINDOW_CLASS_NAME_W,
rect.left, rect.top, _L(FULLENGINENAME),
wwidth, WindowStyle,
wheight, rect.left, rect.top,
NULL, wwidth,
NULL, wheight,
global_hInstance, NULL,
NULL); NULL,
global_hInstance,
NULL);
}
else
{
dibwindow = CreateWindowExA (
ExWindowStyle,
WINDOW_CLASS_NAME_A,
FULLENGINENAME,
WindowStyle,
rect.left, rect.top,
wwidth,
wheight,
NULL,
NULL,
global_hInstance,
NULL);
}
if (!dibwindow) if (!dibwindow)
Sys_Error ("Couldn't create DIB window"); Sys_Error ("Couldn't create DIB window");
@ -1002,20 +1041,40 @@ static void Win_Touch_Init(HWND wnd);
static qboolean CreateMainWindow(rendererstate_t *info) static qboolean CreateMainWindow(rendererstate_t *info)
{ {
qboolean stat; qboolean stat;
WNDCLASSW wc; if (WinNT)
/* Register the frame class */ {
wc.style = CS_OWNDC; WNDCLASSW wc;
wc.lpfnWndProc = (WNDPROC)GLMainWndProc; /* Register the frame class */
wc.cbClsExtra = 0; wc.style = CS_OWNDC;
wc.cbWndExtra = 0; wc.lpfnWndProc = (WNDPROC)GLMainWndProc;
wc.hInstance = global_hInstance; wc.cbClsExtra = 0;
wc.hIcon = hIcon; wc.cbWndExtra = 0;
wc.hCursor = hArrowCursor; wc.hInstance = global_hInstance;
wc.hbrBackground = NULL; wc.hIcon = hIcon;
wc.lpszMenuName = 0; wc.hCursor = hArrowCursor;
wc.lpszClassName = WINDOW_CLASS_NAME; wc.hbrBackground = NULL;
if (!RegisterClassW (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead. wc.lpszMenuName = 0;
Con_Printf("RegisterClass failed\n"); wc.lpszClassName = WINDOW_CLASS_NAME_W;
if (!RegisterClassW (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead.
Con_Printf("RegisterClass failed\n");
}
else
{
WNDCLASSA wc;
/* Register the frame class */
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)GLMainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = global_hInstance;
wc.hIcon = hIcon;
wc.hCursor = hArrowCursor;
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = WINDOW_CLASS_NAME_A;
if (!RegisterClassA (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead.
Con_Printf("RegisterClass failed\n");
}
if (!info->fullscreen) if (!info->fullscreen)
{ {
@ -2464,7 +2523,10 @@ LONG WINAPI GLMainWndProc (
default: default:
/* pass all unhandled messages to DefWindowProc */ /* pass all unhandled messages to DefWindowProc */
lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam); if (WinNT)
lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam);
else
lRet = DefWindowProcA (hWnd, uMsg, wParam, lParam);
break; break;
} }
@ -2521,7 +2583,10 @@ void GLVID_DeInit (void)
Cvar_Unhook(&vid_wndalpha); Cvar_Unhook(&vid_wndalpha);
Cmd_RemoveCommand("vid_recenter"); Cmd_RemoveCommand("vid_recenter");
UnregisterClassW(WINDOW_CLASS_NAME, global_hInstance); if (WinNT)
UnregisterClassW(WINDOW_CLASS_NAME_W, global_hInstance);
else
UnregisterClassA(WINDOW_CLASS_NAME_A, global_hInstance);
} }
/* /*

View File

@ -491,7 +491,7 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
nl = strchr(msg, '\n'); nl = strchr(msg, '\n');
if (nl) if (nl)
*nl = '\0'; *nl = '\0';
Con_Printf("HTTP: %s %s\n", buffer, COM_TrimString(msg, trimmed, sizeof(trimmed))); Con_Printf("HTTP: %s %s (%s)\n", buffer, COM_TrimString(msg, trimmed, sizeof(trimmed)), Location);
if (!*Location) if (!*Location)
Con_Printf("Server redirected to null location\n"); Con_Printf("Server redirected to null location\n");
else else
@ -1324,6 +1324,21 @@ void HTTP_CL_Think(void)
#endif #endif
} }
} }
void HTTP_CL_Terminate(void)
{
struct dl_download *dl = activedownloads;
struct dl_download *next = NULL;
next = activedownloads;
activedownloads = NULL;
while (next)
{
dl = next;
next = dl->next;
DL_Close(dl);
}
HTTP_CL_Think();
}
#endif #endif
#endif /*WEBCLIENT*/ #endif /*WEBCLIENT*/

View File

@ -150,6 +150,7 @@ struct dl_download
vfsfile_t *VFSPIPE_Open(void); vfsfile_t *VFSPIPE_Open(void);
void HTTP_CL_Think(void); void HTTP_CL_Think(void);
void HTTP_CL_Terminate(void); //kills all active downloads
struct dl_download *HTTP_CL_Get(const char *url, const char *localfile, void (*NotifyFunction)(struct dl_download *dl)); struct dl_download *HTTP_CL_Get(const char *url, const char *localfile, void (*NotifyFunction)(struct dl_download *dl));
struct dl_download *HTTP_CL_Put(const char *url, const char *mime, const char *data, size_t datalen, void (*NotifyFunction)(struct dl_download *dl)); struct dl_download *HTTP_CL_Put(const char *url, const char *mime, const char *data, size_t datalen, void (*NotifyFunction)(struct dl_download *dl));

View File

@ -559,6 +559,11 @@ extern pbool keyword_inline; //don't write the def to the output.
extern pbool keyword_strip; //don't write the def to the output. extern pbool keyword_strip; //don't write the def to the output.
extern pbool keyword_union; //you surly know what a union is! extern pbool keyword_union; //you surly know what a union is!
extern pbool keyword_unused;
extern pbool keyword_used;
extern pbool keyword_static;
extern pbool keyword_nonstatic;
extern pbool keyword_ignore;
extern pbool keywords_coexist; extern pbool keywords_coexist;
extern pbool output_parms; extern pbool output_parms;

View File

@ -50,6 +50,11 @@ pbool keyword_struct;
pbool keyword_var; //allow it to be initialised and set around the place. pbool keyword_var; //allow it to be initialised and set around the place.
pbool keyword_vector; //for skipping the local pbool keyword_vector; //for skipping the local
pbool keyword_static;
pbool keyword_nonstatic;
pbool keyword_used;
pbool keyword_unused;
pbool keyword_enum; //kinda like in c, but typedef not supported. pbool keyword_enum; //kinda like in c, but typedef not supported.
pbool keyword_enumflags; //like enum, but doubles instead of adds 1. pbool keyword_enumflags; //like enum, but doubles instead of adds 1.
@ -69,6 +74,7 @@ pbool keyword_noref; //nowhere else references this, don't strip it.
pbool keyword_nosave; //don't write the def to the output. pbool keyword_nosave; //don't write the def to the output.
pbool keyword_inline; pbool keyword_inline;
pbool keyword_strip; pbool keyword_strip;
pbool keyword_ignore;
pbool keyword_union; //you surly know what a union is! pbool keyword_union; //you surly know what a union is!
#define keyword_not 1 //hexenc support needs this, and fteqcc can optimise without it, but it adds an extra token after the if, so it can cause no namespace conflicts #define keyword_not 1 //hexenc support needs this, and fteqcc can optimise without it, but it adds an extra token after the if, so it can cause no namespace conflicts
@ -2038,6 +2044,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
case OP_LOADA_I: case OP_LOADA_I:
{ {
QCC_sref_t nd = var_a; QCC_sref_t nd = var_a;
QCC_FreeTemp(var_b);
nd.ofs += eval_b->_int; nd.ofs += eval_b->_int;
//FIXME: case away the array... //FIXME: case away the array...
return nd; return nd;
@ -2884,7 +2891,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
//a - (n * floor(a/n)); //a - (n * floor(a/n));
//(except using v|v instead of floor) //(except using v|v instead of floor)
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], var_a, var_b, NULL, STFL_CONVERTA|STFL_CONVERTB|STFL_PRESERVEA|STFL_PRESERVEB); var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], var_a, var_b, NULL, STFL_CONVERTA|STFL_CONVERTB|STFL_PRESERVEA|STFL_PRESERVEB);
var_c = QCC_PR_Statement(&pr_opcodes[OP_BITOR_F], var_c, var_c, NULL); var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_F], var_c, var_c, NULL, STFL_PRESERVEA);
var_c = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], var_b, var_c, NULL); var_c = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], var_b, var_c, NULL);
return QCC_PR_Statement(&pr_opcodes[OP_SUB_F], var_a, var_c, NULL); return QCC_PR_Statement(&pr_opcodes[OP_SUB_F], var_a, var_c, NULL);
@ -2960,7 +2967,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{ {
const QCC_eval_t *eval_a = QCC_SRef_EvalConst(var_a); const QCC_eval_t *eval_a = QCC_SRef_EvalConst(var_a);
if (eval_a) if (eval_a)
{
QCC_FreeTemp(var_a);
var_a = QCC_MakeFloatConst(eval_a->_int); var_a = QCC_MakeFloatConst(eval_a->_int);
}
else else
{ {
var_c = QCC_PR_GetSRef(NULL, "itof", NULL, false, 0, 0); var_c = QCC_PR_GetSRef(NULL, "itof", NULL, false, 0, 0);
@ -2983,7 +2993,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{ {
const QCC_eval_t *eval_a = QCC_SRef_EvalConst(var_a); const QCC_eval_t *eval_a = QCC_SRef_EvalConst(var_a);
if (eval_a) if (eval_a)
{
QCC_FreeTemp(var_a);
var_a = QCC_MakeIntConst(eval_a->_float); var_a = QCC_MakeIntConst(eval_a->_float);
}
else else
{ {
var_c = QCC_PR_GetSRef(NULL, "ftoi", NULL, false, 0, 0); var_c = QCC_PR_GetSRef(NULL, "ftoi", NULL, false, 0, 0);
@ -3972,6 +3985,7 @@ struct inlinectx_s
{ {
QCC_def_t *def; QCC_def_t *def;
QCC_def_t *srcsym; QCC_def_t *srcsym;
int bias;
} locals[64]; } locals[64];
int numlocals; int numlocals;
}; };
@ -3993,6 +4007,7 @@ static pbool QCC_PR_InlinePushResult(struct inlinectx_s *ctx, QCC_sref_t src, QC
else if (ctx->locals[i].def) else if (ctx->locals[i].def)
QCC_FreeDef(ctx->locals[i].def); QCC_FreeDef(ctx->locals[i].def);
ctx->locals[i].def = mappedto.sym; ctx->locals[i].def = mappedto.sym;
ctx->locals[i].bias = mappedto.ofs - src.ofs; //FIXME: this feels unsafe (needed for array[immediate] fixups)
return true; return true;
} }
@ -4015,10 +4030,11 @@ static QCC_sref_t QCC_PR_InlineFindDef(struct inlinectx_s *ctx, QCC_sref_t src,
{ {
QCC_FreeDef(ctx->locals[p].def); QCC_FreeDef(ctx->locals[p].def);
ctx->locals[p].def = NULL; ctx->locals[p].def = NULL;
ctx->locals[p].bias = 0;
d = NULL; d = NULL;
return QCC_MakeSRefForce(NULL, 0, NULL); return QCC_MakeSRefForce(NULL, 0, NULL);
} }
return QCC_MakeSRefForce(d, src.ofs, src.cast); return QCC_MakeSRefForce(d, src.ofs + ctx->locals[p].bias, src.cast);
} }
} }
@ -4030,7 +4046,7 @@ static QCC_sref_t QCC_PR_InlineFindDef(struct inlinectx_s *ctx, QCC_sref_t src,
{ {
if (src.sym->symbolheader == local) if (src.sym->symbolheader == local)
{ {
return QCC_MakeSRefForce(ctx->arglist[p].sym->symbolheader, ctx->arglist[p].sym->ofs+src.ofs, src.cast); return QCC_MakeSRefForce(ctx->arglist[p].sym->symbolheader, src.ofs, src.cast);
} }
} }
@ -4082,9 +4098,14 @@ static QCC_sref_t QCC_PR_InlineFindDef(struct inlinectx_s *ctx, QCC_sref_t src,
//returns a string saying why inlining failed. //returns a string saying why inlining failed.
static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx) static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
{ {
/*FIXME: what happens with:
t = foo;
foo = 5;
return t;
*/
QCC_sref_t a, b, c; QCC_sref_t a, b, c;
QCC_statement_t *st; QCC_statement_t *st;
// const QCC_eval_t *eval; const QCC_eval_t *eval;
// float af,bf; // float af,bf;
// int i; // int i;
@ -4099,6 +4120,10 @@ static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
case OP_IFNOT_I: case OP_IFNOT_I:
case OP_IF_S: case OP_IF_S:
case OP_IFNOT_S: case OP_IFNOT_S:
if (st->b.ofs > 0 && st[st->b.ofs].op == OP_DONE)
{
//logically, an if statement around the entire function is safe because the locals are safe
}
case OP_GOTO: case OP_GOTO:
case OP_SWITCH_F: case OP_SWITCH_F:
case OP_SWITCH_I: case OP_SWITCH_I:
@ -4138,20 +4163,18 @@ static char *QCC_PR_InlineStatements(struct inlinectx_s *ctx)
return "OP_RETURN no a"; return "OP_RETURN no a";
} }
return NULL; return NULL;
#ifdef IAMNOTLAZY
case OP_BOUNDCHECK: case OP_BOUNDCHECK:
a = QCC_PR_InlineFindDef(ctx, st->a); a = QCC_PR_InlineFindDef(ctx, st->a, false);
QCC_PR_InlinePushResult(ctx, st->a, a); QCC_PR_InlinePushResult(ctx, st->a, a);
eval = QCC_SRef_EvalConst(st->a); eval = QCC_SRef_EvalConst(a);
if (eval) if (eval)
{ {
if (eval->_int < st->c || eval->_int >= st->b) if (eval->_int < (int)st->c.ofs || eval->_int >= (int)st->b.ofs)
QCC_PR_ParseWarning(0, "constant value exceeds bounds failed bounds check while inlining\n"); QCC_PR_ParseWarning(0, "constant value exceeds bounds failed bounds check while inlining\n");
} }
else else
QCC_PR_SimpleStatement(OP_BOUNDCHECK, a->ofs, st->b, st->c, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_BOUNDCHECK], a, st->b, st->c, false);
break; break;
#endif
default: default:
if ((st->op >= OP_CALL0 && st->op <= OP_CALL8) || (st->op >= OP_CALL1H && st->op <= OP_CALL8H)) if ((st->op >= OP_CALL0 && st->op <= OP_CALL8) || (st->op >= OP_CALL1H && st->op <= OP_CALL8H))
{ {
@ -4910,6 +4933,7 @@ QCC_sref_t QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
if (!func.sym->initialized) if (!func.sym->initialized)
func.sym->initialized = 3; func.sym->initialized = 3;
func.sym->referenced = true; func.sym->referenced = true;
QCC_FreeTemp(func);
e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); e = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
QCC_PR_Expect(")"); QCC_PR_Expect(")");
@ -4917,6 +4941,7 @@ QCC_sref_t QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
d = QCC_PR_GetSRef(NULL, "nextent", NULL, false, 0, false); d = QCC_PR_GetSRef(NULL, "nextent", NULL, false, 0, false);
if (!d.cast) if (!d.cast)
QCC_PR_ParseError(0, "the nextent builtin is not defined"); QCC_PR_ParseError(0, "the nextent builtin is not defined");
QCC_UnFreeTemp(e);
d = QCC_PR_GenerateFunctionCall (nullsref, d, &e, &type_float, 1); d = QCC_PR_GenerateFunctionCall (nullsref, d, &e, &type_float, 1);
d = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntConst(1), NULL, 0); d = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], d, QCC_MakeIntConst(1), NULL, 0);
e = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], e, d, NULL, 0); e = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], e, d, NULL, 0);
@ -5600,7 +5625,7 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype)
pr.local_head.nextlocal = NULL; pr.local_head.nextlocal = NULL;
pr.local_tail = &pr.local_head; pr.local_tail = &pr.local_head;
scope->initialized = true;
scope->symboldata[scope->ofs].function = pr_scope - functions; scope->symboldata[scope->ofs].function = pr_scope - functions;
ed = QCC_PR_GetSRef(type_entity, "self", NULL, true, 0, false); ed = QCC_PR_GetSRef(type_entity, "self", NULL, true, 0, false);
@ -6295,6 +6320,8 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
} }
} }
d.sym->referenced = true;
//class code uses self as though it was 'this'. its a hack, but this is QC. //class code uses self as though it was 'this'. its a hack, but this is QC.
if (assumeclass && pr_classtype && !strcmp(name, "self")) if (assumeclass && pr_classtype && !strcmp(name, "self"))
{ {
@ -7340,11 +7367,11 @@ QCC_sref_t QCC_StoreToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable, pb
TypeName(source.cast, typea, sizeof(typea)); TypeName(source.cast, typea, sizeof(typea));
TypeName(dest->cast, typeb, sizeof(typeb)); TypeName(dest->cast, typeb, sizeof(typeb));
if (dest->type == REF_FIELD) if (dest->type == REF_FIELD)
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s to %s %s.%s", typea, typeb, dest->base.cast->name, QCC_GetSRefName(dest->index)); QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s %s to %s %s.%s", typea, QCC_GetSRefName(source), typeb, QCC_GetSRefName(dest->base), QCC_GetSRefName(dest->index));
else if (dest->index.cast) else if (dest->index.cast)
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s to %s[%s]", typea, typeb, QCC_GetSRefName(dest->base), QCC_GetSRefName(dest->index)); QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s %s to %s[%s]", typea, QCC_GetSRefName(source), typeb, QCC_GetSRefName(dest->base), QCC_GetSRefName(dest->index));
else else
QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s to %s %s", typea, typeb, QCC_GetSRefName(dest->base)); QCC_PR_ParseWarning(WARN_STRICTTYPEMISMATCH, "type mismatch: %s %s to %s %s", typea, QCC_GetSRefName(source), typeb, QCC_GetSRefName(dest->base));
} }
} }
} }
@ -10646,6 +10673,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
index = QCC_PR_GetSRef(type_float, "__indexg", pr_scope, true, 0, false); index = QCC_PR_GetSRef(type_float, "__indexg", pr_scope, true, 0, false);
scope->initialized = true;
scope->symboldata[scope->ofs]._int = pr_scope - functions; scope->symboldata[scope->ofs]._int = pr_scope - functions;
/* if (fasttrackpossible) /* if (fasttrackpossible)
@ -10828,6 +10856,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *arraydef, char *ar
index = QCC_PR_GetSRef(type_float, "indexs___", pr_scope, true, 0, false); index = QCC_PR_GetSRef(type_float, "indexs___", pr_scope, true, 0, false);
value = QCC_PR_GetSRef(thearray.cast, "value___", pr_scope, true, 0, false); value = QCC_PR_GetSRef(thearray.cast, "value___", pr_scope, true, 0, false);
scope->initialized = true;
scope->symboldata[scope->ofs]._int = pr_scope - functions; scope->symboldata[scope->ofs]._int = pr_scope - functions;
if (fasttrackpossible.cast) if (fasttrackpossible.cast)
@ -11272,6 +11301,8 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, struct QCC_function_s *s
QCC_PR_ParseWarning(WARN_MISUSEDAUTOCVAR, "Autocvar \"%s\" defined as constant", name); QCC_PR_ParseWarning(WARN_MISUSEDAUTOCVAR, "Autocvar \"%s\" defined as constant", name);
else if (flags & GDF_STATIC) else if (flags & GDF_STATIC)
QCC_PR_ParseWarning(WARN_MISUSEDAUTOCVAR, "Autocvar \"%s\" defined as static", name); QCC_PR_ParseWarning(WARN_MISUSEDAUTOCVAR, "Autocvar \"%s\" defined as static", name);
if (!(flags & GDF_STRIP))
flags |= GDF_USED;
} }
def = QCC_PR_DummyDef(type, name, scope, arraysize, NULL, ofs, true, flags); def = QCC_PR_DummyDef(type, name, scope, arraysize, NULL, ofs, true, flags);
@ -11829,7 +11860,7 @@ void QCC_PR_ParseDefs (char *classname)
pbool inlinefunction = false; pbool inlinefunction = false;
pbool allowinline = false; pbool allowinline = false;
pbool dostrip = false; pbool dostrip = false;
pbool ignored = false; pbool forceused = false;
int arraysize; int arraysize;
unsigned int gd_flags; unsigned int gd_flags;
@ -12046,20 +12077,24 @@ void QCC_PR_ParseDefs (char *classname)
isconstant = true; isconstant = true;
else if (QCC_PR_CheckKeyword(keyword_var, "var")) else if (QCC_PR_CheckKeyword(keyword_var, "var"))
isvar = true; isvar = true;
else if (QCC_PR_CheckKeyword(keyword_var, "static")) else if (QCC_PR_CheckKeyword(keyword_static, "static"))
isstatic = true; isstatic = true;
else if (!pr_scope && QCC_PR_CheckKeyword(keyword_var, "nonstatic")) else if (!pr_scope && QCC_PR_CheckKeyword(keyword_nonstatic, "nonstatic"))
isstatic = false; isstatic = false;
else if (QCC_PR_CheckKeyword(keyword_noref, "noref")) else if (QCC_PR_CheckKeyword(keyword_noref, "noref"))
noref=true; noref=true;
else if (QCC_PR_CheckKeyword(keyword_unused, "unused"))
noref=true;
else if (QCC_PR_CheckKeyword(keyword_used, "used"))
forceused=true;
else if (QCC_PR_CheckKeyword(keyword_nosave, "nosave")) else if (QCC_PR_CheckKeyword(keyword_nosave, "nosave"))
nosave = true; nosave = true;
else if (QCC_PR_CheckKeyword(keyword_strip, "strip")) else if (QCC_PR_CheckKeyword(keyword_strip, "strip"))
dostrip = true; dostrip = true;
else if (QCC_PR_CheckKeyword(keyword_inline, "inline")) else if (QCC_PR_CheckKeyword(keyword_inline, "inline"))
allowinline = true; allowinline = true;
else if (QCC_PR_CheckKeyword(keyword_inline, "ignore")) else if (QCC_PR_CheckKeyword(keyword_ignore, "ignore"))
ignored = true; dostrip = true;
else else
break; break;
} }
@ -12085,7 +12120,7 @@ void QCC_PR_ParseDefs (char *classname)
def = QCC_PR_GetDef (type, name, NULL, true, 0, false); def = QCC_PR_GetDef (type, name, NULL, true, 0, false);
if (autoprototype || ignored) if (autoprototype || dostrip)
{ //ignore the code and stuff { //ignore the code and stuff
if (QCC_PR_CheckKeyword(keyword_external, "external")) if (QCC_PR_CheckKeyword(keyword_external, "external"))
@ -12283,7 +12318,7 @@ void QCC_PR_ParseDefs (char *classname)
gd_flags |= GDF_INLINE; gd_flags |= GDF_INLINE;
if (dostrip) if (dostrip)
gd_flags |= GDF_STRIP; gd_flags |= GDF_STRIP;
if (isvar && !ignored) //FIXME: make proper pragma(used) thingie else if (forceused) //FIXME: make proper pragma(used) thingie
gd_flags |= GDF_USED; gd_flags |= GDF_USED;
#if IAMNOTLAZY #if IAMNOTLAZY
@ -12366,10 +12401,12 @@ void QCC_PR_ParseDefs (char *classname)
// QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name); // QCC_PR_ParseErrorPrintDef(ERR_REDECLARATION, def, "%s redeclared", name);
} }
if (autoprototype || ignored) if (autoprototype || dostrip)
{ //ignore the code and stuff { //ignore the code and stuff
if (ignored && !def->initialized) if (dostrip && !def->initialized)
def->initialized = 3; def->initialized = 3;
if (dostrip)
def->referenced = true;
if (QCC_PR_CheckToken("[")) if (QCC_PR_CheckToken("["))
{ {
while (!QCC_PR_CheckToken("]")) while (!QCC_PR_CheckToken("]"))
@ -12425,7 +12462,12 @@ void QCC_PR_ParseDefs (char *classname)
if (type->type == ev_function) if (type->type == ev_function)
isconstant = !isvar; isconstant = !isvar;
if (type->type == ev_field) if (dostrip)
{
def->constant = isconstant;
def->referenced = true;
}
else if (type->type == ev_field)
{ {
//fields are const by default, even when not initialised (as they are initialised behind the scenes) //fields are const by default, even when not initialised (as they are initialised behind the scenes)
if (isconstant) if (isconstant)

View File

@ -4642,6 +4642,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
pbool isvirt = false; pbool isvirt = false;
pbool isnonvirt = false; pbool isnonvirt = false;
pbool isstatic = false; pbool isstatic = false;
pbool isignored = false;
while(1) while(1)
{ {
if (QCC_PR_CheckKeyword(1, "nonvirtual")) if (QCC_PR_CheckKeyword(1, "nonvirtual"))
@ -4650,6 +4651,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
isstatic = true; isstatic = true;
else if (QCC_PR_CheckKeyword(1, "virtual")) else if (QCC_PR_CheckKeyword(1, "virtual"))
isvirt = true; isvirt = true;
else if (QCC_PR_CheckKeyword(1, "ignore"))
isignored = true;
else if (QCC_PR_CheckKeyword(1, "strip"))
isignored = true;
else else
break; break;
} }
@ -4721,19 +4726,27 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
QC_snprintfz(membername, sizeof(membername), "%s::%s", classname, parmname); QC_snprintfz(membername, sizeof(membername), "%s::%s", classname, parmname);
if (isnull) if (isnull)
{ {
def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, 0); if (isignored)
def->symboldata[def->ofs].function = 0; def = NULL;
def->initialized = 1; else
{
def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, 0);
def->symboldata[def->ofs].function = 0;
def->initialized = 1;
}
} }
else else
{ {
def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST); if (isignored)
def = NULL;
else
def = QCC_PR_GetDef(newparm, membername, NULL, true, 0, GDF_CONST);
if (newparm->type != ev_function) if (newparm->type != ev_function)
QCC_Error(ERR_INTERNAL, "Can only initialise member functions"); QCC_Error(ERR_INTERNAL, "Can only initialise member functions");
else else
{ {
if (autoprototype) if (autoprototype || isignored)
{ {
QCC_PR_Expect("{"); QCC_PR_Expect("{");
@ -4765,9 +4778,10 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
} }
} }
} }
QCC_FreeDef(def); if (def)
QCC_FreeDef(def);
if (!isvirt) if (!isvirt && !isignored)
{ {
QCC_def_t *fdef; QCC_def_t *fdef;
QCC_type_t *pc; QCC_type_t *pc;
@ -4799,6 +4813,9 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
QCC_PR_Expect(";"); QCC_PR_Expect(";");
if (isignored) //member doesn't really exist
continue;
//static members are technically just funny-named globals, and do not generate fields. //static members are technically just funny-named globals, and do not generate fields.
if (isnonvirt || isstatic || (newparm->type == ev_function && !arraysize)) if (isnonvirt || isstatic || (newparm->type == ev_function && !arraysize))
{ {

View File

@ -282,7 +282,13 @@ compiler_flag_t compiler_flag[] = {
{&keyword_goto, defaultkeyword, "goto", "Keyword: goto", "Disables the 'goto' keyword."}, {&keyword_goto, defaultkeyword, "goto", "Keyword: goto", "Disables the 'goto' keyword."},
{&keyword_int, defaultkeyword, "int", "Keyword: int", "Disables the 'int' keyword."}, {&keyword_int, defaultkeyword, "int", "Keyword: int", "Disables the 'int' keyword."},
{&keyword_integer, defaultkeyword, "integer", "Keyword: integer", "Disables the 'integer' keyword."}, {&keyword_integer, defaultkeyword, "integer", "Keyword: integer", "Disables the 'integer' keyword."},
{&keyword_noref, defaultkeyword, "noref", "Keyword: noref", "Disables the 'noref' keyword."}, //nowhere else references this, don't strip it. {&keyword_noref, defaultkeyword, "noref", "Keyword: noref", "Disables the 'noref' keyword."}, //nowhere else references this, don't warn about it.
{&keyword_unused, nondefaultkeyword, "unused", "Keyword: unused", "Disables the 'unused' keyword. 'unused' means that the variable is unused, you're aware that its unused, and you'd rather not know about all the warnings this results in."},
{&keyword_used, nondefaultkeyword, "used", "Keyword: used", "Disables the 'used' keyword. 'used' means that the variable is used even if the qcc can't see how - thus preventing it from ever being stripped."},
{&keyword_static, defaultkeyword, "static", "Keyword: static", "Disables the 'static' keyword. 'static' means that a variable has altered scope. On globals, the variable is visible only to the current .qc file. On locals, the variable's value does not change between calls to the function. On class variables, specifies that the field is a scoped global instead of a local. On class functions, specifies that 'this' is expected to be invalid and that the function will access any memembers via it."},
{&keyword_nonstatic, defaultkeyword, "nonstatic", "Keyword: nonstatic", "Disables the 'nonstatic' keyword. 'nonstatic' acts upon globals+functions, reverting the defaultstatic pragma on a per-variable basis. For use by people who prefer to keep their APIs explicit."},
{&keyword_ignore, nondefaultkeyword, "ignore", "Keyword: ignore", "Disables the 'ignore' keyword. 'ignore' is expected to typically be hidden behind a 'csqconly' define, and in such a context can be used to conditionally compile functions a little more gracefully. The opposite of the 'used' keyword. These variables/functions/members are ALWAYS stripped, and effectively ignored."},
{&keyword_nosave, defaultkeyword, "nosave", "Keyword: nosave", "Disables the 'nosave' keyword."}, //don't write the def to the output. {&keyword_nosave, defaultkeyword, "nosave", "Keyword: nosave", "Disables the 'nosave' keyword."}, //don't write the def to the output.
{&keyword_inline, defaultkeyword, "inline", "Keyword: inline", "Disables the 'inline' keyword."}, //don't write the def to the output. {&keyword_inline, defaultkeyword, "inline", "Keyword: inline", "Disables the 'inline' keyword."}, //don't write the def to the output.
{&keyword_strip, defaultkeyword, "strip", "Keyword: strip", "Disables the 'strip' keyword."}, //don't write the def to the output. {&keyword_strip, defaultkeyword, "strip", "Keyword: strip", "Disables the 'strip' keyword."}, //don't write the def to the output.
@ -1307,9 +1313,9 @@ pbool QCC_WriteData (int crc)
for (i = 0; i < nummodels; i++) for (i = 0; i < nummodels; i++)
{ {
if (!precache_model[i].used) if (!precache_model[i].used)
QCC_PR_Warning(WARN_EXTRAPRECACHE, precache_model[i].filename, precache_model[i].fileline, "Model %s was precached but not directly used", precache_model[i].name); QCC_PR_Warning(WARN_EXTRAPRECACHE, precache_model[i].filename, precache_model[i].fileline, "Model \"%s\" was precached but not directly used", precache_model[i].name);
else if (!precache_model[i].block) else if (!precache_model[i].block)
QCC_PR_Warning(WARN_NOTPRECACHED, precache_model[i].filename, precache_model[i].fileline, "Model %s was used but not precached", precache_model[i].name); QCC_PR_Warning(WARN_NOTPRECACHED, precache_model[i].filename, precache_model[i].fileline, "Model \"%s\" was used but not precached", precache_model[i].name);
} }
//PrintStrings (); //PrintStrings ();
//PrintFunctions (); //PrintFunctions ();

View File

@ -205,11 +205,11 @@ void PDECL ED_Spawned (struct edict_s *ent, int loading)
if (!loading || !ent->xv->Version) if (!loading || !ent->xv->Version)
{ {
ent->xv->dimension_see = 255; ent->xv->dimension_see = pr_global_struct->dimension_default;
ent->xv->dimension_seen = 255; ent->xv->dimension_seen = pr_global_struct->dimension_default;
ent->xv->dimension_ghost = 0; ent->xv->dimension_ghost = 0;
ent->xv->dimension_solid = 255; ent->xv->dimension_solid = pr_global_struct->dimension_default;
ent->xv->dimension_hit = 255; ent->xv->dimension_hit = pr_global_struct->dimension_default;
if (progstype != PROG_H2) if (progstype != PROG_H2)
ent->xv->drawflags = SCALE_ORIGIN_ORIGIN; //if not running hexen2, default the scale origin to the actual origin. ent->xv->drawflags = SCALE_ORIGIN_ORIGIN; //if not running hexen2, default the scale origin to the actual origin.
@ -666,6 +666,7 @@ void PR_LoadGlabalStruct(qboolean muted)
static float svphysicsmode = 2; static float svphysicsmode = 2;
static float writeonly; static float writeonly;
static float dimension_send_default; static float dimension_send_default;
static float dimension_default = 255;
static float zero_default; static float zero_default;
static float input_buttons_default; static float input_buttons_default;
static float input_timelength_default; static float input_timelength_default;
@ -725,6 +726,7 @@ void PR_LoadGlabalStruct(qboolean muted)
globalfunc (false, SetChangeParms); globalfunc (false, SetChangeParms);
globalfloat (false, cycle_wrapped); globalfloat (false, cycle_wrapped);
globalfloat (false, dimension_send); globalfloat (false, dimension_send);
globalfloat (false, dimension_default);
globalfloat (false, clientcommandframe); globalfloat (false, clientcommandframe);
@ -747,6 +749,7 @@ void PR_LoadGlabalStruct(qboolean muted)
// make sure these entries are always valid pointers // make sure these entries are always valid pointers
ensureglobal(dimension_send, dimension_send_default); ensureglobal(dimension_send, dimension_send_default);
ensureglobal(dimension_default, dimension_default);
ensureglobal(trace_endcontents, writeonly); ensureglobal(trace_endcontents, writeonly);
ensureglobal(trace_surfaceflags, writeonly); ensureglobal(trace_surfaceflags, writeonly);
@ -804,8 +807,8 @@ void PR_LoadGlabalStruct(qboolean muted)
//this can be a map start or a loadgame. don't hurt stuff. //this can be a map start or a loadgame. don't hurt stuff.
if (!pr_global_struct->dimension_send) if (!pr_global_struct->dimension_send)
pr_global_struct->dimension_send = 255; pr_global_struct->dimension_send = pr_global_struct->dimension_default;
/* pr_global_struct->dimension_send = 255; /*
pr_global_struct->serverflags = 0; pr_global_struct->serverflags = 0;
pr_global_struct->total_secrets = 0; pr_global_struct->total_secrets = 0;
pr_global_struct->total_monsters = 0; pr_global_struct->total_monsters = 0;
@ -1218,7 +1221,7 @@ void PR_SSCoreDump_f(void)
int size = 1024*1024*8; int size = 1024*1024*8;
char *buffer = BZ_Malloc(size); char *buffer = BZ_Malloc(size);
svprogfuncs->save_ents(svprogfuncs, buffer, &size, size, 3); svprogfuncs->save_ents(svprogfuncs, buffer, &size, size, 3);
COM_WriteFile("ssqccore.txt", buffer, size); COM_WriteFile("ssqccore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer); BZ_Free(buffer);
} }
} }
@ -9681,7 +9684,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"keynumtostring_csqc",PF_Fixme,0, 0, 0, 340, D("string(float keynum)", "Returns a hunam-readable name for the given keycode, as a tempstring.")},// (found in menuqc) {"keynumtostring_csqc",PF_Fixme,0, 0, 0, 340, D("string(float keynum)", "Returns a hunam-readable name for the given keycode, as a tempstring.")},// (found in menuqc)
{"stringtokeynum", PF_Fixme, 0, 0, 0, 341, D("float(string keyname)", "Looks up the key name in the same way that the bind command would, returning the keycode for that key.")},// (EXT_CSQC) {"stringtokeynum", PF_Fixme, 0, 0, 0, 341, D("float(string keyname)", "Looks up the key name in the same way that the bind command would, returning the keycode for that key.")},// (EXT_CSQC)
{"stringtokeynum_csqc", PF_Fixme,0, 0, 0, 341, D("float(string keyname)", "Looks up the key name in the same way that the bind command would, returning the keycode for that key.")},// (found in menuqc) {"stringtokeynum_csqc", PF_Fixme,0, 0, 0, 341, D("float(string keyname)", "Looks up the key name in the same way that the bind command would, returning the keycode for that key.")},// (found in menuqc)
{"getkeybind", PF_Fixme, 0, 0, 0, 342, D("string(float keynum)", "Finds the current binding for the given key (ignores modifiers like shift/alt/ctrl).")},// (EXT_CSQC) {"getkeybind", PF_Fixme, 0, 0, 0, 342, D("string(float keynum)", "Returns the current binding for the given key (returning only the command executed when no modifiers are pressed).")},// (EXT_CSQC)
{"setcursormode", PF_Fixme, 0, 0, 0, 343, D("void(float usecursor, optional string cursorimage, optional vector hotspot, optional float scale)", "Pass TRUE if you want the engine to release the mouse cursor (absolute input events + touchscreen mode). Pass FALSE if you want the engine to grab the cursor (relative input events + standard looking). If the image name is specified, the engine will use that image for a cursor (use an empty string to clear it again), in a way that will not conflict with the console. Images specified this way will be hardware accelerated, if supported by the platform/port.")}, {"setcursormode", PF_Fixme, 0, 0, 0, 343, D("void(float usecursor, optional string cursorimage, optional vector hotspot, optional float scale)", "Pass TRUE if you want the engine to release the mouse cursor (absolute input events + touchscreen mode). Pass FALSE if you want the engine to grab the cursor (relative input events + standard looking). If the image name is specified, the engine will use that image for a cursor (use an empty string to clear it again), in a way that will not conflict with the console. Images specified this way will be hardware accelerated, if supported by the platform/port.")},
{"getmousepos", PF_Fixme, 0, 0, 0, 344, D("vector()", "Nasty convoluted DP extension. Typically returns deltas instead of positions. Use CSQC_InputEvent for such things in csqc mods.")}, // #344 This is a DP extension {"getmousepos", PF_Fixme, 0, 0, 0, 344, D("vector()", "Nasty convoluted DP extension. Typically returns deltas instead of positions. Use CSQC_InputEvent for such things in csqc mods.")}, // #344 This is a DP extension
@ -9918,7 +9921,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"uri_escape", PF_uri_escape, 0, 0, 0, 510, "string(string in)"},//DP_QC_URI_ESCAPE {"uri_escape", PF_uri_escape, 0, 0, 0, 510, "string(string in)"},//DP_QC_URI_ESCAPE
{"uri_unescape", PF_uri_unescape, 0, 0, 0, 511, "string(string in)"},//DP_QC_URI_ESCAPE {"uri_unescape", PF_uri_unescape, 0, 0, 0, 511, "string(string in)"},//DP_QC_URI_ESCAPE
{"num_for_edict", PF_num_for_edict, 0, 0, 0, 512, "float(entity ent)"},//DP_QC_NUM_FOR_EDICT {"num_for_edict", PF_num_for_edict, 0, 0, 0, 512, "float(entity ent)"},//DP_QC_NUM_FOR_EDICT
{"uri_get", PF_uri_get, 0, 0, 0, 513, D("#define uri_post uri_get\nfloat(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string")},//DP_QC_URI_GET {"uri_get", PF_uri_get, 0, 0, 0, 513, D("#define uri_post uri_get\nfloat(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string\nFor a POST request, you will typically want the postmimetype set to application/x-www-form-urlencoded.\nFor a GET request, omit the mime+data entirely.\nConsult your webserver/php/etc documentation for best-practise.")},//DP_QC_URI_GET
{"uri_post", PF_uri_get, 0, 0, 0, 513, D("float(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string"), true},//DP_QC_URI_POST {"uri_post", PF_uri_get, 0, 0, 0, 513, D("float(string uril, float id, optional string postmimetype, optional string postdata)", "uri_get() gets content from an URL and calls a callback \"uri_get_callback\" with it set as string; an unique ID of the transfer is returned\nreturns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string"), true},//DP_QC_URI_POST
{"tokenize_console",PF_tokenize_console,0, 0, 0, 514, D("float(string str)", "Tokenize a string exactly as the console's tokenizer would do so. The regular tokenize builtin became bastardized for convienient string parsing, which resulted in a large disparity that can be exploited to bypass checks implemented in a naive SV_ParseClientCommand function, therefore you can use this builtin to make sure it exactly matches.")}, {"tokenize_console",PF_tokenize_console,0, 0, 0, 514, D("float(string str)", "Tokenize a string exactly as the console's tokenizer would do so. The regular tokenize builtin became bastardized for convienient string parsing, which resulted in a large disparity that can be exploited to bypass checks implemented in a naive SV_ParseClientCommand function, therefore you can use this builtin to make sure it exactly matches.")},
{"argv_start_index",PF_argv_start_index,0, 0, 0, 515, D("float(float idx)", "Returns the character index that the tokenized arg started at.")}, {"argv_start_index",PF_argv_start_index,0, 0, 0, 515, D("float(float idx)", "Returns the character index that the tokenized arg started at.")},
@ -9927,7 +9930,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"cvar_description",PF_cvar_description,0, 0, 0, 518, D("string(string cvarname)", "Retrieves the description of a cvar, which might be useful for tooltips or help files. This may still not be useful.")}, {"cvar_description",PF_cvar_description,0, 0, 0, 518, D("string(string cvarname)", "Retrieves the description of a cvar, which might be useful for tooltips or help files. This may still not be useful.")},
{"gettime", PF_gettime, 0, 0, 0, 519, "float(optional float timetype)"}, {"gettime", PF_gettime, 0, 0, 0, 519, "float(optional float timetype)"},
{"keynumtostring_omgwtf",PF_Fixme, 0, 0, 0, 520, "string(float keynum)"}, //excessive third version in dp's csqc. {"keynumtostring_omgwtf",PF_Fixme, 0, 0, 0, 520, "string(float keynum)"}, //excessive third version in dp's csqc.
{"findkeysforcommand",PF_Fixme, 0, 0, 0, 521, "string(string command, optional float bindmap)"}, {"findkeysforcommand",PF_Fixme, 0, 0, 0, 521, D("string(string command, optional float bindmap)", "Returns a list of keycodes that perform the given console command in a format that can only be parsed via tokenize (NOT tokenize_console). This only and always returns two values - if only one key is actually bound, -1 will be returned. The bindmap argument is listed for compatibility with dp-specific defs, but is ignored in FTE.")},
{"findkeysforcommandex",PF_Fixme, 0, 0, 0, 0, D("string(string command)", "Returns a list of key bindings in keyname format instead of keynums. Use tokenize to parse. This list may contain modifiers. May return large numbers of keys.")},
// {"initparticlespawner",PF_Fixme, 0, 0, 0, 522, "void(float max_themes)"}, // {"initparticlespawner",PF_Fixme, 0, 0, 0, 522, "void(float max_themes)"},
// {"resetparticle", PF_Fixme, 0, 0, 0, 523, "void()"}, // {"resetparticle", PF_Fixme, 0, 0, 0, 523, "void()"},
// {"particletheme", PF_Fixme, 0, 0, 0, 524, "void(float theme)"}, // {"particletheme", PF_Fixme, 0, 0, 0, 524, "void(float theme)"},
@ -10698,6 +10702,8 @@ void PR_DumpPlatform_f(void)
{"parm17, parm18, parm19, parm20, parm21, parm22, parm23, parm24, parm25, parm26, parm27, parm28, parm29, parm30, parm31, parm32", "float", QW|NQ}, {"parm17, parm18, parm19, parm20, parm21, parm22, parm23, parm24, parm25, parm26, parm27, parm28, parm29, parm30, parm31, parm32", "float", QW|NQ},
{"parm33, parm34, parm35, parm36, parm37, parm38, parm39, parm40, parm41, parm42, parm43, parm44, parm45, parm46, parm47, parm48", "float", QW|NQ}, {"parm33, parm34, parm35, parm36, parm37, parm38, parm39, parm40, parm41, parm42, parm43, parm44, parm45, parm46, parm47, parm48", "float", QW|NQ},
{"parm49, parm50, parm51, parm52, parm53, parm54, parm55, parm56, parm57, parm58, parm59, parm60, parm61, parm62, parm63, parm64", "float", QW|NQ}, {"parm49, parm50, parm51, parm52, parm53, parm54, parm55, parm56, parm57, parm58, parm59, parm60, parm61, parm62, parm63, parm64", "float", QW|NQ},
{"dimension_send", "var float", QW|NQ, "Used by multicast functionality. Multicasts (and related builtins that multicast internally) will only be sent to players where (player.dimension_see & dimension_send) is non-zero."},
{"dimension_default", "//var float", QW|NQ, "Default dimension bitmask", 255},
{"physics_mode", "var float", QW|NQ|CS, "0: original csqc - physics are not run\n1: DP-compat. Thinks occur, but not true movetypes.\n2: movetypes occur just as they do in ssqc.", 2}, {"physics_mode", "var float", QW|NQ|CS, "0: original csqc - physics are not run\n1: DP-compat. Thinks occur, but not true movetypes.\n2: movetypes occur just as they do in ssqc.", 2},
{"gamespeed", "float", CS, "Set by the engine, this is the value of the sv_gamespeed cvar"}, {"gamespeed", "float", CS, "Set by the engine, this is the value of the sv_gamespeed cvar"},
{"numclientseats", "float", CS, "This is the number of splitscreen clients currently running on this client."}, {"numclientseats", "float", CS, "This is the number of splitscreen clients currently running on this client."},

View File

@ -1950,6 +1950,7 @@ static void Lua_SetupGlobals(world_t *world)
memset(&lua.globals, 0, sizeof(lua.globals)); memset(&lua.globals, 0, sizeof(lua.globals));
lua.globals.physics_mode = 2; lua.globals.physics_mode = 2;
lua.globals.dimension_send = 255; lua.globals.dimension_send = 255;
lua.globals.dimension_default = 255;
flds = 0; flds = 0;
bucks = 64; bucks = 64;

View File

@ -81,6 +81,7 @@ typedef struct nqglobalvars_s
func_t *SetChangeParms; func_t *SetChangeParms;
float *cycle_wrapped; float *cycle_wrapped;
float *dimension_send; float *dimension_send;
float *dimension_default;
float *physics_mode; float *physics_mode;
float *clientcommandframe; float *clientcommandframe;

View File

@ -1215,7 +1215,7 @@ void SV_Savegame (char *savename)
rgbbuffer = VID_GetRGBInfo(0, &width, &height); rgbbuffer = VID_GetRGBInfo(0, &width, &height);
if (rgbbuffer) if (rgbbuffer)
{ {
SCR_ScreenShot(savefilename, rgbbuffer, width, height); SCR_ScreenShot(savefilename, FS_GAMEONLY, rgbbuffer, width, height);
BZ_Free(rgbbuffer); BZ_Free(rgbbuffer);

View File

@ -2573,6 +2573,31 @@ void SV_ReallyEvilHack_f(void)
} }
*/ */
void SV_PrecacheList_f(void)
{
unsigned int i;
for (i = 0; i < sizeof(sv.strings.vw_model_precache)/sizeof(sv.strings.vw_model_precache[0]); i++)
{
if (sv.strings.vw_model_precache[i])
Con_Printf("vweap %u: %s\n", i, sv.strings.vw_model_precache[i]);
}
for (i = 0; i < MAX_PRECACHE_MODELS; i++)
{
if (sv.strings.model_precache[i])
Con_Printf("model %u: %s\n", i, sv.strings.model_precache[i]);
}
for (i = 0; i < MAX_PRECACHE_SOUNDS; i++)
{
if (*sv.strings.sound_precache[i])
Con_Printf("sound %u: %s\n", i, sv.strings.sound_precache[i]);
}
for (i = 0; i < MAX_SSPARTICLESPRE; i++)
{
if (*sv.strings.particle_precache[i])
Con_Printf("pticl %u: %s\n", i, sv.strings.particle_precache[i]);
}
}
/* /*
================== ==================
SV_InitOperatorCommands SV_InitOperatorCommands
@ -2636,6 +2661,7 @@ void SV_InitOperatorCommands (void)
Cmd_AddCommand ("killserver", SV_KillServer_f); Cmd_AddCommand ("killserver", SV_KillServer_f);
Cmd_AddCommand ("map", SV_Map_f); Cmd_AddCommand ("map", SV_Map_f);
Cmd_AddCommandD ("precaches", SV_PrecacheList_f, "Displays a list of current server precaches.");
#ifdef Q3SERVER #ifdef Q3SERVER
Cmd_AddCommand ("spmap", SV_Map_f); Cmd_AddCommand ("spmap", SV_Map_f);
#endif #endif

View File

@ -119,9 +119,11 @@ pubsubserver_t *MSV_FindSubServer(unsigned int id)
} }
//"5" finds server 5 only //"5" finds server 5 only
//"5:" is equivelent to the above
//"5:dm4" finds server 5, and will start it if not known (even if a different node is running the same map) //"5:dm4" finds server 5, and will start it if not known (even if a different node is running the same map)
//"0:dm4" starts a new server running dm4, even if its already running //"0:dm4" starts a new server running dm4, even if its already running
//":dm4" finds any server running dm4. starts a new one if needed. //":dm4" finds any server running dm4. starts a new one if needed.
//"dm4" is ambiguous, in the case of a map beginning with a number (bah). don't use.
pubsubserver_t *MSV_FindSubServerName(const char *servername) pubsubserver_t *MSV_FindSubServerName(const char *servername)
{ {
pubsubserver_t *s; pubsubserver_t *s;
@ -136,8 +138,11 @@ pubsubserver_t *MSV_FindSubServerName(const char *servername)
forcenew = true; forcenew = true;
mapname++; mapname++;
} }
else else if (*mapname)
{
Con_Printf("Invalid node name (lacks colon): %s\n", servername);
mapname = ""; mapname = "";
}
if (id) if (id)
{ {
@ -216,17 +221,9 @@ void MSV_MapCluster_f(void)
//child processes return 0 and fall through //child processes return 0 and fall through
memset(&sv, 0, sizeof(sv)); memset(&sv, 0, sizeof(sv));
if (Cmd_Argc() > 1) if (atoi(Cmd_Argv(1)))
{ {
char *dbname = Cmd_Argv(1); Con_Printf("Opening database \"%s\"\n", sqlparams[3]);
char *sqlparams[] =
{
"", //host
"", //username
"", //password
dbname, //db
};
Con_Printf("Opening database \"%s\"\n", dbname);
sv.logindatabase = SQL_NewServer("sqlite", sqlparams); sv.logindatabase = SQL_NewServer("sqlite", sqlparams);
if (sv.logindatabase == -1) if (sv.logindatabase == -1)
{ {
@ -777,9 +774,22 @@ void SSV_ReadFromControlServer(void)
for (i = 0; i < sv.allocated_client_slots; i++) for (i = 0; i < sv.allocated_client_slots; i++)
{ {
cl = &svs.clients[i]; cl = &svs.clients[i];
if (cl->state >= ca_connected)
if (!*dest || !strcmp(dest, cl->name)) if (!*dest || !strcmp(dest, cl->name))
{ {
SV_PrintToClient(cl, PRINT_HIGH, va("%s from [%s]: %s\n", cmd, from, info)); if (!strcmp(cmd, "say"))
SV_PrintToClient(cl, PRINT_HIGH, va("^[%s^]: %s\n", from, info));
else if (!strcmp(cmd, "join"))
{
SV_PrintToClient(cl, PRINT_HIGH, va("^[%s^] is joining you\n", from));
SSV_Send(from, cl->name, "joinnode", va("%i", svs.clusterserverid));
}
else if (!strcmp(cmd, "joinnode"))
{
SSV_InitiatePlayerTransfer(cl, info);
}
else
SV_PrintToClient(cl, PRINT_HIGH, va("%s from [%s]: %s\n", cmd, from, info));
if (*dest) if (*dest)
break; break;
} }
@ -815,7 +825,7 @@ void SSV_UpdateAddresses(void)
{ {
if (addr[i].type == NA_IP) if (addr[i].type == NA_IP)
{ {
NET_StringToAdr(sv_serverip.string, BigShort(addr[i].port), &addr[0]); NET_StringToAdr2(sv_serverip.string, BigShort(addr[i].port), &addr[0], sizeof(addr)/sizeof(addr[0]));
count = 1; count = 1;
break; break;
} }

View File

@ -295,7 +295,7 @@ void VARGS SV_Error (char *error, ...)
int size = 1024*1024*8; int size = 1024*1024*8;
char *buffer = BZ_Malloc(size); char *buffer = BZ_Malloc(size);
svprogfuncs->save_ents(svprogfuncs, buffer, &size, size, 3); svprogfuncs->save_ents(svprogfuncs, buffer, &size, size, 3);
COM_WriteFile("ssqccore.txt", buffer, size); COM_WriteFile("ssqccore.txt", FS_GAMEONLY, buffer, size);
BZ_Free(buffer); BZ_Free(buffer);
} }
} }

View File

@ -1053,17 +1053,41 @@ void ApplyColour(unsigned int chr)
} }
} }
void Sys_PrintColouredChar(unsigned int chr) //this could be much more efficient.
static void Sys_PrintColouredChars(conchar_t *start, conchar_t *end)
{ {
conchar_t m;
wchar_t wc[256];
int l;
DWORD dummy; DWORD dummy;
wchar_t wc;
if (chr & CON_HIDDEN) while(start < end)
return; {
ApplyColour(chr); l = 0;
m = *start & CON_FLAGSMASK;
for (;;)
{
if (start == end || m != (*start & CON_FLAGSMASK) || l >= countof(wc))
{
ApplyColour(m);
if (WinNT)
WriteConsoleW(hconsoleout, wc, l, &dummy, NULL);
else
{
//win95 doesn't support wide chars *sigh*. blank consoles suck.
char ac[256];
l = WideCharToMultiByte(CP_ACP, 0, wc, l, ac, sizeof(ac), NULL, NULL);
WriteConsole(hconsoleout, ac, l, &dummy, NULL);
}
break;
}
if (!(*start & CON_HIDDEN))
wc[l++] = *start & CON_CHARMASK;
start++;
}
}
wc = chr & CON_CHARMASK; ApplyColour(CON_WHITEMASK);
WriteConsoleW(hconsoleout, &wc, 1, &dummy, NULL);
} }
/* /*
@ -1112,13 +1136,9 @@ void Sys_Printf (char *fmt, ...)
if (sys_colorconsole.value && hconsoleout) if (sys_colorconsole.value && hconsoleout)
{ {
conchar_t out[MAXPRINTMSG], *c, *end; conchar_t out[MAXPRINTMSG], *end;
end = COM_ParseFunString(CON_WHITEMASK, msg, out, sizeof(out), false); end = COM_ParseFunString(CON_WHITEMASK, msg, out, sizeof(out), false);
Sys_PrintColouredChars (out, end);
for (c = out; c < end; c++)
Sys_PrintColouredChar (*c);
ApplyColour(CON_WHITEMASK);
} }
else else
{ {

View File

@ -4346,7 +4346,7 @@ void Cmd_Fly_f (void)
} }
#ifdef SUBSERVERS #ifdef SUBSERVERS
void Cmd_Transfer_f(void) void Cmd_SSV_Transfer_f(void)
{ {
char *dest = Cmd_Argv(1); char *dest = Cmd_Argv(1);
if (!SV_MayCheat()) if (!SV_MayCheat())
@ -4357,6 +4357,46 @@ void Cmd_Transfer_f(void)
SSV_InitiatePlayerTransfer(host_client, dest); SSV_InitiatePlayerTransfer(host_client, dest);
} }
void Cmd_SSV_AllSay_f(void)
{
char *text = Cmd_Args();
if (!SV_MayCheat())
{
SV_TPrintToClient(host_client, PRINT_HIGH, "Cheats are not allowed on this server\n");
return;
}
SSV_Send("", host_client->name, "say", text);
}
void Cmd_SSV_Join_f(void)
{
int i;
char *who = Cmd_Argv(1);
if (!SV_MayCheat())
{
SV_TPrintToClient(host_client, PRINT_HIGH, "Cheats are not allowed on this server\n");
return;
}
for (i = 0; i < sv.allocated_client_slots; i++)
{
if (!strcmp(who, svs.clients[i].name))
{
// VectorCopy(svs.clients[i].edict->v->origin, sv_player->v->oldorigin);
VectorCopy(svs.clients[i].edict->v->origin, sv_player->v->origin);
World_LinkEdict (&sv.world, (wedict_t*)sv_player, false);
sv_player->xv->dimension_hit = (int)sv_player->xv->dimension_hit & ~128;
sv_player->xv->dimension_solid = (int)sv_player->xv->dimension_solid & 128;
svs.clients[i].edict->xv->dimension_hit = (int)svs.clients[i].edict->xv->dimension_hit & ~128;
svs.clients[i].edict->xv->dimension_solid = (int)svs.clients[i].edict->xv->dimension_solid & 128;
return;
}
}
SSV_Send(who, host_client->name, "join", "");
}
#endif #endif
/* /*
@ -5272,7 +5312,9 @@ ucmd_t ucmds[] =
{"notarget", Cmd_Notarget_f}, {"notarget", Cmd_Notarget_f},
{"setpos", Cmd_SetPos_f}, {"setpos", Cmd_SetPos_f},
#ifdef SUBSERVERS #ifdef SUBSERVERS
{"transfer", Cmd_Transfer_f}, //transfer the player to a different map/server {"ssvtransfer", Cmd_SSV_Transfer_f},//transfer the player to a different map/server
{"ssvsay", Cmd_SSV_AllSay_f}, //transfer the player to a different map/server
{"ssvjoin", Cmd_SSV_Join_f}, //transfer the player to a different map/server
#endif #endif
#ifdef NQPROT #ifdef NQPROT

View File

@ -9,7 +9,7 @@ PLUG_NATIVE_EXT=_amd.dll
PLUG_LDFLAGS=-Lavplug/lib64 -L../engine/libs/mingw64-libs -lz -Wl,--support-old-code PLUG_LDFLAGS=-Lavplug/lib64 -L../engine/libs/mingw64-libs -lz -Wl,--support-old-code
endif endif
PLUG_LDFLAGS?=-L/usr/local/lib -Wl,-R/usr/local/lib -lz PLUG_LDFLAGS?=-L/usr/local/lib -Wl,-R/usr/local/lib -lz -lm
ifneq ($(PLUG_NATIVE_EXT),) ifneq ($(PLUG_NATIVE_EXT),)
#if we're on windows, we'll put our windows-specific hacks here. #if we're on windows, we'll put our windows-specific hacks here.
@ -129,7 +129,7 @@ native: $(OUT_DIR)/fteplug_irc$(PLUG_NATIVE_EXT)
#for compat with ezquake #for compat with ezquake
$(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT): ezhud/ezquakeisms.c ezhud/hud.c ezhud/hud_common.c ezhud/hud_editor.c plugin.c qvm_api.c $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT): ezhud/ezquakeisms.c ezhud/hud.c ezhud/hud_common.c ezhud/hud_editor.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Iirc $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Iezhud $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
native: $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT) native: $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT)
native: native:

View File

@ -60,6 +60,12 @@ client compat:
#include <time.h> #include <time.h>
#include "xmpp.h" #include "xmpp.h"
#ifdef DEFAULTDOMAIN
#define EXAMPLEDOMAIN DEFAULTDOMAIN //used in examples / default text field (but not otherwise assumed when omitted)
#else
#define EXAMPLEDOMAIN "gmail.com" //used in examples
#endif
#ifdef JINGLE #ifdef JINGLE
icefuncs_t *piceapi; icefuncs_t *piceapi;
@ -1578,7 +1584,7 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args)
else if (!strcmp(what, "newaccount")) else if (!strcmp(what, "newaccount"))
{ {
pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true); pCon_SetConsoleFloat(BUDDYLISTTITLE, "linebuffered", true);
pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your account name"); pCon_SetConsoleString(BUDDYLISTTITLE, "footer", "Please enter your XMPP account name\neg: example@"EXAMPLEDOMAIN);
jclient_action_cl = jcl; jclient_action_cl = jcl;
jclient_action_buddy = NULL; jclient_action_buddy = NULL;
jclient_action = ACT_NEWACCOUNT; jclient_action = ACT_NEWACCOUNT;
@ -1746,7 +1752,7 @@ qintptr_t JCL_ConExecuteCommand(qintptr_t *args)
case ACT_NONE: case ACT_NONE:
break; break;
case ACT_NEWACCOUNT: case ACT_NEWACCOUNT:
if (*args) if (!*args)
break; //they didn't enter anything! oh well. break; //they didn't enter anything! oh well.
for (i = 0; i < sizeof(jclients)/sizeof(jclients[0]); i++) for (i = 0; i < sizeof(jclients)/sizeof(jclients[0]); i++)
{ {
@ -2208,14 +2214,13 @@ jclient_t *JCL_Connect(int accnum, char *server, int forcetls, char *account, ch
} }
else else
{ {
#ifdef DEFAULTDOMAIN
domain = DEFAULTDOMAIN; domain = DEFAULTDOMAIN;
if (domain && *domain) Con_Printf("XMPP: domain not specified, assuming %s\n", domain);
Con_Printf("XMPP: domain not specified, assuming %s\n", domain); #else
else Con_Printf("XMPP: domain not specified\n");
{ return NULL;
Con_Printf("XMPP: domain not specified\n"); #endif
return NULL;
}
} }
x = XML_CreateNode(NULL, "account", "", ""); x = XML_CreateNode(NULL, "account", "", "");
@ -5401,7 +5406,7 @@ void XMPP_Menu_Connect(void)
y = 36; y = 36;
pCmd_AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16; pCmd_AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16;
pCmd_AddText(va("menueditpriv 48 %i \"Username\" \"example\"\n", y), false);y+=16; pCmd_AddText(va("menueditpriv 48 %i \"Username\" \"example\"\n", y), false);y+=16;
pCmd_AddText(va("menueditpriv 48 %i \"Domain\" \"gmail.com\"\n", y), false);y+=16; pCmd_AddText(va("menueditpriv 48 %i \"Domain\" \""EXAMPLEDOMAIN"\"\n", y), false);y+=16;
pCmd_AddText(va("menueditpriv 48 %i \"Resource\" \"\"\n", y), false);y+=32; pCmd_AddText(va("menueditpriv 48 %i \"Resource\" \"\"\n", y), false);y+=32;
pCmd_AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false); pCmd_AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false);
pCmd_AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false); pCmd_AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false);

View File

@ -22,7 +22,7 @@
#define JCL_BUILD "4" #define JCL_BUILD "4"
#define DEFAULTDOMAIN "" //#define DEFAULTDOMAIN "triptohell.info"
#define DEFAULTRESOURCE "Quake" #define DEFAULTRESOURCE "Quake"
#define QUAKEMEDIAXMLNS "http://fteqw.com/protocol/quake" #define QUAKEMEDIAXMLNS "http://fteqw.com/protocol/quake"
#define DISCONODE "http://fteqw.com/ftexmpp" //some sort of client identifier #define DISCONODE "http://fteqw.com/ftexmpp" //some sort of client identifier

79
specs/mapcluster.txt Normal file
View File

@ -0,0 +1,79 @@
WARNING: this mode is not currently compiled in by default, in order to avoid potential unexpected resource usage.
you will need to enable it by enabling the SUBSERVERS preprocessor define at compile time.
random useful commands (bash or console):
make sv-rel CFLAGS=-DSUBSERVERS
mapcluster <enablelogins>
ssv 1 quit
ssv * say The Admin Is Awesome
sv_serverip 127.0.0.1
the mapcluster command provides support for a single host running multiple maps as a single server cluster.
this is achieved by running multiple instances of the server in multiple processes, each with their own port numbers.
the initial server acts as a login server, which communicates with the various nodes.
ssqc is able to transfer clients from one node to another within the cluster, or send messages to the node hosting clients (or, if the node's id is explicitly known, can be used to directly communicate with other nodes).
node naming rules:
a node name takes the form of id:name
if the id is empty, then it is considered unspecified, and the message/transfer will id used will be updated to any existing node with the same name (:e1m1 will pick ANY e1m1).
if the id is 0, then it will NEVER use an existing node.
if the id is invalid/0/empty, and the name is not blank, and the node is named via a transfer request, a new node will be started using that name as the new node's initial map.
note that "0:start$\\foo\\bar" can be used, in which case you will ALWAYS get a new instance, using maps/start.bsp and that infoget(startspot, "foo") will return "bar".
event destinations:
event destinations logically use player names. However, if the name takes the form "\\5" for example, then the message will be sent to the node with id 5, rather than to the node of a name player. You can use this to directly communicate server-to-server. If the node id does not exist, the event will be returned to the sender as an error - no new node will be created with this (fixme: it probably should be, but blurgh).
ssqc builtins:
forceinfokey(player, "*transfer", ":e1m1");
initiates a transfer request. the infokey will be cleared out upon failure, and the client will drop on success.
their parms will be transfered immediately, and will be available to the new server once the transfer completes.
WARNING: it is the QC's responsibility to terminate servers {localcmd("quit\n");} - the engine will not automatically do this.
If you are implementing an mmo-like game, you would presumably do this when there are no players and all monsters were respawned (such that restarting will not be noticed). Otherwise you may choose to terminate the node instantly or after some delay after the last player has left. If you only have limited maps, you might opt to never terminate any nodes - lucky you.
void(string dest, string from, string cmd, string info) clusterevent = #;
sends a message to the destination.
if dest is blank, the event will be broadcast to EVERY node.
if the destination is prefixed with a \ char, (eg: "\\1"), then the message is sent to node id 1.
if the destination is a player name, will send to whichever node that player is currently on. the receiving server is expected to handle the event on behalf of the player (perhaps by forwarding to csqc, or just doing a sprint or something).
if the destination appears invalid (and cmd is not prefixed with 'error:'), the cmd will be prefixed with error:, the dest+from args swapped, and the event will be sent back to the receiver.
info and cmd have meaning to the engine only if the receiver's ssqc does not handle the event.
float serverid
this float contains the node's unique id. no two active nodes will use the same id, and can be used in replies to identify the node as the receipient of a transfer.
float(string dest, string from, string cmd, string info) SV_ParseClusterEvent = {};
this function is called by the engine in response to a clusterevent call. the arguments match those of the prior call.
if you return false, the engine will attempt to handle it the best it can. which is limited and probably not ideal. any other result will cause the node to carry out no further action (meaning the from+cmd+info args are completely free-form if you do so).
the dest argument follows the restrictions/expectations specified for clusterevent.
this is handled by the receipient server, and as such the qc is expected to find the named player (if not direct-to-server) and handle the event itself.
the senders and receivers of these messages are all part of the same cluster, and so should all be considered trustworthy - unless you permit direct message injection. for this reason, you should *probably* ALWAYS use constants for the cmd argument, and thereby avoid surprises. this allows you to make assumptions about the dest+from+info fields more easily, simplifying your parsing.
it is possible for a client to have transfered off the server (or be in the process of transfering and thus ownership of the player's properties uncertain). in such cases, you are recommended to mimic the error: behaviour so that the sender can handle things in a consistent way.
debug/cheat commands (mods are expected to provide their own functionality for these things, and thus these are considered cheats to limit their use):
cmd ssvtransfer :e1m1
transfers the player to the named node (see node naming rules), just like forceinfokey would.
cmd ssvsay hello world
broadcasts the message to every single player on every single node (instead of merely the node the player is on).
(this does: clusterevent("", self.netname, "say", args()) )
cmd ssvjoin playername
attempts to teleport the player to the named player's server.
if the named player is already on the same node, teleports the player on top of the named player.
(this does: clusterevent(player, self.netname, "join", ""), the default join handler will reply with joinnode, and the handler of that will initiate a transfer request to the node specified by the joinnode's info string)
gotchas:
in order to invite another player, you will likely need to implement some sort of timeout serverside, in order to avoid issues with people's UIs ignoring the request (or not receiving it due to a player transfering at the time).
you probably shouldn't allow people to join others without mutual consent, to reduce trolling. probably you'll want the server of the person being joined in ultimate control of the join, if only because its nice and easy to pull another player to your node on account of the puller already knowing the destination's serverid.
due to players disconnecting or randomly transfering before your messages get to them, all of these messages should be considered unreliable.
if you block transfers of one player, you can hopefully get away with a race condition between the reply and a timeout. for non-parm based things, you can use sql transaction support to ensure atomicity.