From 151adc38ed8ebe9906f21228e4855187ed91dfec Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 9 Dec 2016 09:09:12 +0000 Subject: [PATCH] move 'not a field' messages to dprints. try to fix hlbsp palette issues. fix drawstring showing link infos. move some annoying cvar defaults over to quake-specific settings, instead of always being on. fix possible hlmdl crash. fix __fullspawninfo fix switching between player/spectator not tracking spawned slot counts properly. fix a possible crash from runstandardplayerphysics. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5030 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_ents.c | 8 +++-- engine/client/cl_main.c | 2 +- engine/client/cl_parse.c | 12 ++++++-- engine/client/image.c | 64 +++++++++++++++++++++++++++++++-------- engine/client/pr_csqc.c | 1 + engine/client/pr_menu.c | 3 ++ engine/client/renderer.c | 20 +++--------- engine/client/screen.h | 5 +-- engine/client/wad.c | 8 ++++- engine/common/fs.c | 13 +++++++- engine/common/pmovetst.c | 2 +- engine/common/pr_bgcmd.c | 56 ++++++++++++++++++++++++++-------- engine/common/pr_common.h | 1 + engine/gl/gl_hlmdl.c | 57 ++++++++++++++++++++++------------ engine/gl/gl_model.c | 23 ++++++++++++-- engine/gl/gl_shader.c | 31 ++++++++++++++----- engine/qclib/initlib.c | 1 + engine/qclib/pr_edict.c | 4 +-- engine/qclib/progsint.h | 1 + engine/qclib/progslib.h | 3 +- engine/qclib/qccgui.c | 1 + engine/server/pr_cmds.c | 43 ++++++++++++++++++++------ engine/server/sv_main.c | 8 ++--- engine/server/sv_phys.c | 2 ++ engine/server/sv_user.c | 4 --- engine/server/svhl_game.c | 4 +-- 26 files changed, 273 insertions(+), 104 deletions(-) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 8ecdc0e1d..d071daeb5 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -3938,8 +3938,13 @@ void CL_LinkPacketEntities (void) ent->flags |= RF_NODEPTHTEST; if (state->effects & EF_NOSHADOW) ent->flags |= RF_NOSHADOW; - if (state->trans != 0xff) + if (state->trans < 0xfe) + { + ent->shaderRGBAf[3] = state->trans/(float)0xfe; ent->flags |= RF_TRANSLUCENT; + } + else + ent->shaderRGBAf[3] = 1; /* if (le->origin[2] < r_refdef.waterheight != le->lastorigin[2] < r_refdef.waterheight) { @@ -3983,7 +3988,6 @@ void CL_LinkPacketEntities (void) ent->shaderRGBAf[1] = (state->colormod[1]*8.0f)/256; ent->shaderRGBAf[2] = (state->colormod[2]*8.0f)/256; } - ent->shaderRGBAf[3] = state->trans/255.0f; #ifdef PEXT_FATNESS //set trans diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 368a283ed..60f020561 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -194,7 +194,7 @@ cvar_t ruleset_allow_sensitive_texture_replacements = CVAR("ruleset_allow_sensit cvar_t ruleset_allow_localvolume = CVAR("ruleset_allow_localvolume", "1"); cvar_t ruleset_allow_shaders = CVARF("ruleset_allow_shaders", "1", CVAR_SHADERSYSTEM); cvar_t ruleset_allow_watervis = CVARF("ruleset_allow_watervis", "1", CVAR_SHADERSYSTEM); -cvar_t ruleset_allow_fbmodels = CVARF("ruleset_allow_fbmodels", "1", CVAR_SHADERSYSTEM); +cvar_t ruleset_allow_fbmodels = CVARF("ruleset_allow_fbmodels", "0", CVAR_SHADERSYSTEM); extern cvar_t cl_hightrack; extern cvar_t vid_renderer; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index ddb272b63..d7d4f12b0 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -992,9 +992,11 @@ qboolean CL_CheckHLBspWads(char *file) while ((w = strchr(com_token, '\\'))) *w = '/'; w = COM_SkipPath(com_token); - Con_Printf("wads: %s\n", w); if (!CL_CheckFile(w)) + { + Con_Printf("missing wad: %s\n", w); CL_CheckOrEnqueDownloadFile(va("textures/%s", w), NULL, DLLF_REQUIRED); + } } return false; } @@ -4396,7 +4398,6 @@ void CL_ParseStatic (int version) ent->shaderRGBAf[0] = (8.0f/256.0f)*es.colormod[0]; ent->shaderRGBAf[1] = (8.0f/256.0f)*es.colormod[1]; ent->shaderRGBAf[2] = (8.0f/256.0f)*es.colormod[2]; - ent->shaderRGBAf[3] = es.trans/255.0f; ent->fatness = es.fatness/16.0; ent->abslight = es.abslight; @@ -4412,8 +4413,13 @@ void CL_ParseStatic (int version) ent->flags |= RF_NODEPTHTEST; if (es.effects & EF_NOSHADOW) ent->flags |= RF_NOSHADOW; - if (es.trans != 0xff) + if (es.trans < 0xfe) + { + ent->shaderRGBAf[3] = es.trans/(float)0xfe; ent->flags |= RF_TRANSLUCENT; + } + else + ent->shaderRGBAf[3] = 1.0; VectorCopy (es.origin, ent->origin); VectorCopy (es.angles, ent->angles); diff --git a/engine/client/image.c b/engine/client/image.c index ae1248720..e15f2c711 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -3751,7 +3751,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag mips->encoding = PTI_BGRA8; break; case TF_MIP4_LUM8: - //8bit opaque data + //8bit indexed data. Image_RoundDimensions(&mips->mip[0].width, &mips->mip[0].height, flags); flags |= IF_NOPICMIP; if (/*!r_dodgymiptex.ival &&*/ mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight) @@ -3792,7 +3792,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag //8bit opaque data Image_RoundDimensions(&mips->mip[0].width, &mips->mip[0].height, flags); flags |= IF_NOPICMIP; - if (!r_dodgymiptex.ival && mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight && sh_config.texfmt[PTI_RGBX8]) + if (!r_dodgymiptex.ival && mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight) { //special hack required to preserve the hand-drawn lower mips. unsigned int pixels = (imgwidth>>0) * (imgheight>>0) + @@ -3949,6 +3949,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag freedata = true; break; + case TF_MIP4_8PAL24_T255: case TF_MIP4_8PAL24: //8bit opaque data { @@ -3960,7 +3961,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag palettedata = (qbyte*)rawdata + pixels; Image_RoundDimensions(&mips->mip[0].width, &mips->mip[0].height, flags); flags |= IF_NOPICMIP; - if (!r_dodgymiptex.ival && mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight && sh_config.texfmt[PTI_RGBX8]) + if (!r_dodgymiptex.ival && mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight) { unsigned int pixels = (imgwidth>>0) * (imgheight>>0) + @@ -3968,13 +3969,31 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag (imgwidth>>2) * (imgheight>>2) + (imgwidth>>3) * (imgheight>>3); - mips->encoding = PTI_RGBX8; rgbadata = BZ_Malloc(pixels*4); - for (i = 0; i < pixels; i++) + if (fmt == TF_MIP4_8PAL24_T255) { - qbyte *p = ((qbyte*)palettedata) + ((qbyte*)rawdata)[i]*3; - //FIXME: endian - rgbadata[i] = 0xff000000 | (p[0]<<0) | (p[1]<<8) | (p[2]<<16); + mips->encoding = PTI_RGBA8; + for (i = 0; i < pixels; i++) + { + qbyte idx = ((qbyte*)rawdata)[i]; + if (idx == 255) + rgbadata[i] = 0; + else + { + qbyte *p = ((qbyte*)palettedata) + idx*3; + rgbadata[i] = 0xff000000 | (p[0]<<0) | (p[1]<<8) | (p[2]<<16); //FIXME: endian + } + } + } + else + { + mips->encoding = PTI_RGBX8; + for (i = 0; i < pixels; i++) + { + qbyte *p = ((qbyte*)palettedata) + ((qbyte*)rawdata)[i]*3; + //FIXME: endian + rgbadata[i] = 0xff000000 | (p[0]<<0) | (p[1]<<8) | (p[2]<<16); + } } for (i = 0; i < 4; i++) @@ -4005,13 +4024,31 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag BZ_Free(rawdata); return false; } - mips->encoding = PTI_RGBX8; rgbadata = BZ_Malloc(imgwidth * imgheight*4); - for (i = 0; i < imgwidth * imgheight; i++) + if (fmt == TF_MIP4_8PAL24_T255) { - qbyte *p = ((qbyte*)palettedata) + ((qbyte*)rawdata)[i]*3; - //FIXME: endian - rgbadata[i] = 0xff000000 | (p[0]<<0) | (p[1]<<8) | (p[2]<<16); + mips->encoding = PTI_RGBA8; + for (i = 0; i < imgwidth * imgheight; i++) + { + qbyte idx = ((qbyte*)rawdata)[i]; + if (idx == 255) + rgbadata[i] = 0; + else + { + qbyte *p = ((qbyte*)palettedata) + idx*3; + rgbadata[i] = 0xff000000 | (p[0]<<0) | (p[1]<<8) | (p[2]<<16); //FIXME: endian + } + } + } + else + { + mips->encoding = PTI_RGBX8; + for (i = 0; i < imgwidth * imgheight; i++) + { + qbyte *p = ((qbyte*)palettedata) + ((qbyte*)rawdata)[i]*3; + //FIXME: endian + rgbadata[i] = 0xff000000 | (p[0]<<0) | (p[1]<<8) | (p[2]<<16); + } } if (freedata) BZ_Free(rawdata); @@ -4800,6 +4837,7 @@ image_t *Image_GetTexture(const char *identifier, const char *subpath, unsigned b *= 4; break; case TF_MIP4_8PAL24: + case TF_MIP4_8PAL24_T255: pb = 3*256; case TF_MIP4_LUM8: case TF_MIP4_SOLID8: diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index d4368ec44..71ec5915a 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -6723,6 +6723,7 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks csqcprogparms.FileSize = CSQC_PRFileSize;//int (*FileSize) (char *fname); //-1 if file does not exist csqcprogparms.WriteFile = QC_WriteFile;//bool (*WriteFile) (char *name, void *data, int len); csqcprogparms.Printf = PR_Printf;//Con_Printf;//void (*printf) (char *, ...); + csqcprogparms.DPrintf = PR_DPrintf;//Con_Printf;//void (*printf) (char *, ...); csqcprogparms.Sys_Error = Sys_Error; csqcprogparms.Abort = CSQC_Abort; csqcprogparms.CheckHeaderCrc = CSQC_CheckHeaderCrc; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 6ca0258cb..b4ee5cc15 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -457,6 +457,8 @@ void QCBUILTIN PF_CL_drawcolouredstring (pubprogfuncs_t *prinst, struct globalva while(*str) { str = Font_Decode(str, &codeflags, &codepoint); + if (codeflags & CON_HIDDEN) + continue; if (codepoint == '\n') py += Font_CharHeight(); else if (codepoint == '\r') @@ -2510,6 +2512,7 @@ qboolean MP_Init (void) menuprogparms.FileSize = MP_PRFileSize;//int (*FileSize) (char *fname); //-1 if file does not exist menuprogparms.WriteFile = QC_WriteFile;//bool (*WriteFile) (char *name, void *data, int len); menuprogparms.Printf = (void *)Con_Printf;//Con_Printf;//void (*printf) (char *, ...); + menuprogparms.Printf = (void *)Con_DPrintf;//Con_DPrintf;//void (*dprintf) (char *, ...); menuprogparms.Sys_Error = Sys_Error; menuprogparms.Abort = Menu_Abort; menuprogparms.CheckHeaderCrc = Menu_CheckHeaderCrc; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index d7356d844..eab48044c 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -116,7 +116,7 @@ cvar_t r_fastskycolour = CVARF ("r_fastskycolour", "0", cvar_t r_fb_bmodels = CVARAF("r_fb_bmodels", "1", "gl_fb_bmodels", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); cvar_t r_fb_models = CVARAFD ("r_fb_models", "1", - "gl_fb_models", CVAR_SEMICHEAT, "Force all non-player models to be fullbright in deathmatch. Because if you don't enable these cheats then you'll go splat because everone else uses them. QuakeWorld players suck."); + "gl_fb_models", CVAR_SEMICHEAT, "Enables the use of lumas on models. Note that if ruleset_allow_fbmodels is enabled, then all models are unconditionally fullbright in deathmatch, because cheaters would set up their models like that anyway, hurrah for beating them at their own game. QuakeWorld players suck."); cvar_t r_skin_overlays = CVARF ("r_skin_overlays", "1", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); cvar_t r_globalskin_first = CVARFD ("r_globalskin_first", "100", CVAR_RENDERERLATCH, "Specifies the first .skin value that is a global skin. Entities within this range will use the shader/image called 'gfx/skinSKIN.lmp' instead of their regular skin. See also: r_globalskin_count."); @@ -135,9 +135,9 @@ cvar_t r_floorcolour = CVARAF ("r_floorcolour", "64 64 128", //cvar_t r_floortexture = SCVARF ("r_floortexture", "", // CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); cvar_t r_fullbright = CVARFD ("r_fullbright", "0", - CVAR_CHEAT|CVAR_SHADERSYSTEM, "Ignore world lightmaps, drawing everything fully lit."); -cvar_t r_fullbrightSkins = CVARF ("r_fullbrightSkins", "0.8", /*don't default to 1, as it looks a little ugly (too bright), but don't default to 0 either because then you're handicapped in the dark*/ - CVAR_SEMICHEAT|CVAR_SHADERSYSTEM); + CVAR_CHEAT|CVAR_SHADERSYSTEM, "Ignore world lightmaps, drawing *everything* fully lit."); +cvar_t r_fullbrightSkins = CVARFD ("r_fullbrightSkins", "0.8", /*don't default to 1, as it looks a little ugly (too bright), but don't default to 0 either because then you're handicapped in the dark*/ + CVAR_SEMICHEAT|CVAR_SHADERSYSTEM, "Force the use of fullbright skins on other players. No more hiding in the dark."); cvar_t r_lightmap_saturation = CVAR ("r_lightmap_saturation", "1"); cvar_t r_lightstylesmooth = CVARF ("r_lightstylesmooth", "0", CVAR_ARCHIVE); cvar_t r_lightstylesmooth_limit = CVAR ("r_lightstylesmooth_limit", "2"); @@ -286,20 +286,8 @@ extern cvar_t r_novis; extern cvar_t r_speeds; extern cvar_t r_waterwarp; -#ifndef NOLEGACY -#if defined(ANDROID) -//on android, these numbers seem to be generating major weirdness, so disable these. cvar_t r_polygonoffset_submodel_factor = CVAR("r_polygonoffset_submodel_factor", "0"); cvar_t r_polygonoffset_submodel_offset = CVAR("r_polygonoffset_submodel_offset", "0"); -#elif defined(FTE_TARGET_WEB) -//on firefox (but not chrome or ie), these numbers seem to be generating major weirdness, so tone them down significantly by default. -cvar_t r_polygonoffset_submodel_factor = CVAR("r_polygonoffset_submodel_factor", "0.05"); -cvar_t r_polygonoffset_submodel_offset = CVAR("r_polygonoffset_submodel_offset", "1"); -#else -cvar_t r_polygonoffset_submodel_factor = CVAR("r_polygonoffset_submodel_factor", "0.05"); -cvar_t r_polygonoffset_submodel_offset = CVAR("r_polygonoffset_submodel_offset", "25"); -#endif -#endif cvar_t r_polygonoffset_shadowmap_offset = CVAR("r_polygonoffset_shadowmap_factor", "0.05"); cvar_t r_polygonoffset_shadowmap_factor = CVAR("r_polygonoffset_shadowmap_offset", "0"); diff --git a/engine/client/screen.h b/engine/client/screen.h index 0873d0a0c..c6e61faf8 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -94,8 +94,9 @@ typedef enum uploadfmt TF_BGR24_FLIP, /*bgr byte order, no alpha channel nor pad, and bottom up*/ TF_LUM8, /*8bit greyscale image*/ TF_MIP4_LUM8, /*8bit 4-mip greyscale image*/ - TF_MIP4_SOLID8, /*8bit 4-mip image*/ - TF_MIP4_8PAL24, /*8bit 4-mip image*/ + TF_MIP4_SOLID8, /*8bit 4-mip image in default palette*/ + TF_MIP4_8PAL24, /*8bit 4-mip image with included palette*/ + TF_MIP4_8PAL24_T255,/*8bit 4-mip image with included palette where index 255 is alpha 0*/ TF_SOLID8, /*8bit quake-palette image*/ TF_TRANS8, /*8bit quake-palette image, index 255=transparent*/ TF_TRANS8_FULLBRIGHT, /*fullbright 8 - fullbright texels have alpha 255, everything else 0*/ diff --git a/engine/client/wad.c b/engine/client/wad.c index 716d44bef..61ad5e81a 100644 --- a/engine/client/wad.c +++ b/engine/client/wad.c @@ -425,7 +425,13 @@ qbyte *W_ConvertWAD3Texture(miptex_t *tex, size_t lumpsize, int *width, int *hei tex->offsets[2] == tex->offsets[1] + (tex->width>>1)*(tex->height>>1) && tex->offsets[3] == tex->offsets[2] + (tex->width>>2)*(tex->height>>2) && ((lumpsize+3)&~3) >= ((tex->offsets[3] + (tex->width>>3)*(tex->height>>3) + 2 + 768+3)&~3)) - pal = (qbyte *)tex + tex->offsets[3] + (tex->width>>3)*(tex->height>>3) + 2; + { + short fl = *(short*)((qbyte *)tex + tex->offsets[3] + (tex->width>>3)*(tex->height>>3)); + if (fl == 256) + pal = (qbyte *)tex + tex->offsets[3] + (tex->width>>3)*(tex->height>>3) + 2; + else + pal = host_basepal; + } else pal = host_basepal; diff --git a/engine/common/fs.c b/engine/common/fs.c index 353fac2c4..c9300493a 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -2911,8 +2911,19 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths) FS_ChangeGame(man, cfg_reload_on_gamedir.ival, false); } +#ifdef NOLEGACY + #define ZFIXHACK +#elif defined(ANDROID) //on android, these numbers seem to be generating major weirdness, so disable these. + #define ZFIXHACK +#elif defined(FTE_TARGET_WEB) //on firefox (but not chrome or ie), these numbers seem to be generating major weirdness, so tone them down significantly by default. + #define ZFIXHACK "r_polygonoffset_submodel_offset 1\nr_polygonoffset_submodel_factor 0.05\n" +#else //many quake maps have hideous z-fighting. this provides a way to work around it, although the exact numbers are gpu and bitdepth dependant, and trying to fix it can actually break other things. + #define ZFIXHACK "r_polygonoffset_submodel_offset 25\nr_polygonoffset_submodel_factor 0.05\n" +#endif + /*quake requires a few settings for compatibility*/ -#define QCFG "set com_parseutf8 0\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" +#define EZQUAKECOMPETITIVE "set ruleset_allow_fbmodels 1\n" +#define QCFG "set com_parseutf8 0\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE /*stuff that makes dp-only mods work a bit better*/ #define DPCOMPAT QCFG "set _cl_playermodel \"\"\n set dpcompat_set 1\nset dpcompat_corruptglobals 1\nset vid_pixelheight 1\n" /*nexuiz/xonotic has a few quirks/annoyances...*/ diff --git a/engine/common/pmovetst.c b/engine/common/pmovetst.c index 7605def39..f53709dbb 100644 --- a/engine/common/pmovetst.c +++ b/engine/common/pmovetst.c @@ -184,7 +184,7 @@ int PM_ExtraBoxContents (vec3_t p) { if (!PM_TransformedHullCheck(pm, p, p, pmove.player_mins, pmove.player_maxs, &tr, pe->origin, pe->angles)) continue; - if (tr.startsolid) + if (tr.startsolid || tr.inwater) pc |= pe->forcecontentsmask; } } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 36a30e26f..8ba81806a 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -419,18 +419,12 @@ int QDECL QCEditor (pubprogfuncs_t *prinst, const char *filename, int *line, int } //tag warnings/errors for easier debugging. -int PR_Printf (const char *fmt, ...) +int PR_Print (qboolean dev, const char *msg) { - va_list argptr; - char msg[1024]; char file[MAX_OSPATH]; int line = -1; char *ls, *ms, *nl; - va_start (argptr,fmt); - vsnprintf (msg,sizeof(msg), fmt,argptr); - va_end (argptr); - while (*msg) { nl = strchr(msg, '\n'); @@ -445,7 +439,7 @@ int PR_Printf (const char *fmt, ...) Draw_FunString(0, debuggerstacky, msg); debuggerstacky += 8; if (nl) - memmove(msg, nl+1, strlen(nl+1)+1); + msg = nl+1; else break; continue; @@ -469,15 +463,28 @@ int PR_Printf (const char *fmt, ...) } } - if (*file) - Con_Printf ("^[%s\\edit\\%s:%i^]", msg, file, line); + if (dev) + { + if (*file) + Con_DPrintf ("^[%s\\edit\\%s:%i^]", msg, file, line); + else + Con_DPrintf ("%s", msg); + } else - Con_Printf ("%s", msg); + { + if (*file) + Con_Printf ("^[%s\\edit\\%s:%i^]", msg, file, line); + else + Con_Printf ("%s", msg); + } if (nl) { - Con_Printf ("\n"); - memmove(msg, nl+1, strlen(nl+1)+1); + if (dev) + Con_DPrintf ("\n"); + else + Con_Printf ("\n"); + msg = nl+1; } else break; @@ -485,6 +492,29 @@ int PR_Printf (const char *fmt, ...) return 0; } +int PR_Printf (const char *fmt, ...) +{ + va_list argptr; + char msg[1024]; + + va_start (argptr,fmt); + vsnprintf (msg,sizeof(msg), fmt,argptr); + va_end (argptr); + + return PR_Print(false, msg); +} +int PR_DPrintf (const char *fmt, ...) +{ + va_list argptr; + char msg[1024]; + + va_start (argptr,fmt); + vsnprintf (msg,sizeof(msg), fmt,argptr); + va_end (argptr); + + return PR_Print(true, msg); +} + #define MAX_TEMPSTRS ((int)pr_tempstringcount.value) #define MAXTEMPBUFFERLEN ((int)pr_tempstringsize.value) string_t PR_TempString(pubprogfuncs_t *prinst, const char *str) diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 86862532c..fdb0b844d 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -66,6 +66,7 @@ void *VARGS PR_CB_Malloc(int size); //these functions should be tracked by the l void VARGS PR_CB_Free(void *mem); int PR_Printf (const char *fmt, ...); +int PR_DPrintf (const char *fmt, ...); void PF_InitTempStrings(pubprogfuncs_t *prinst); string_t PR_TempString(pubprogfuncs_t *prinst, const char *str); //returns a tempstring containing str char *PF_TempStr(pubprogfuncs_t *prinst); //returns a tempstring which can be filled in with whatever junk you want. diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 35afe45aa..a276875c6 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -73,7 +73,7 @@ struct hlvremaps unsigned short scoord; unsigned short tcoord; }; -static index_t HLMDL_DeDupe(unsigned short *order, struct hlvremaps *rem, size_t *count) +static index_t HLMDL_DeDupe(unsigned short *order, struct hlvremaps *rem, size_t *count, size_t max) { size_t i; for (i = *count; i-- > 0;) @@ -82,10 +82,13 @@ static index_t HLMDL_DeDupe(unsigned short *order, struct hlvremaps *rem, size_t return i; } i = *count; - rem[i].vertidx = order[0]; - rem[i].normalidx = order[1]; - rem[i].scoord = order[2]; - rem[i].tcoord = order[3]; + if (i < max) + { + rem[i].vertidx = order[0]; + rem[i].normalidx = order[1]; + rem[i].scoord = order[2]; + rem[i].tcoord = order[3]; + } *count += 1; return i; } @@ -94,10 +97,11 @@ static index_t HLMDL_DeDupe(unsigned short *order, struct hlvremaps *rem, size_t static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel, struct hlalternative_s *submodel) { struct hlvremaps *uvert; - size_t uvertcount; + size_t uvertcount, uvertstart; unsigned short count; int i; - size_t idx = 0, v, m; + size_t idx = 0, v, m, maxidx=65536*3; + size_t maxverts = 65536; mesh_t *mesh = &submodel->mesh; index_t *index; @@ -107,15 +111,15 @@ static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel, vec3_t *norms = (vec3_t *) ((qbyte *) model->header + amodel->normindex); uvertcount = 0; - uvert = malloc(sizeof(*uvert)*2048); - - index = mesh->indexes = ZG_Malloc(model->memgroup, sizeof(*mesh->colors4b_array)*65536); + uvert = malloc(sizeof(*uvert)*maxverts); + index = malloc(sizeof(*mesh->colors4b_array)*maxidx); for(m = 0; m < amodel->nummesh; m++) { hlmdl_mesh_t *inmesh = (hlmdl_mesh_t *) ((qbyte *) model->header + amodel->meshindex) + m; unsigned short *order = (unsigned short *) ((qbyte *) model->header + inmesh->index); + uvertstart = uvertcount; submodel->submesh[m].firstindex = mesh->numindexes; submodel->submesh[m].numindexes = 0; @@ -126,22 +130,26 @@ static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel, if(count & 0x8000) { //fan - int first = HLMDL_DeDupe(order+0*4, uvert, &uvertcount); - int prev = HLMDL_DeDupe(order+1*4, uvert, &uvertcount); - for (i = min(2,count); i < -(short)count; i++) + int first = HLMDL_DeDupe(order+0*4, uvert, &uvertcount, maxverts); + int prev = HLMDL_DeDupe(order+1*4, uvert, &uvertcount, maxverts); + count = (unsigned short)-(short)count; + if (idx + (count-2)*3 > maxidx) + break; //would overflow. fixme: extend + for (i = min(2,count); i < count; i++) { index[idx++] = first; index[idx++] = prev; - index[idx++] = prev = HLMDL_DeDupe(order+i*4, uvert, &uvertcount); + index[idx++] = prev = HLMDL_DeDupe(order+i*4, uvert, &uvertcount, maxverts); } } else { - int v0 = HLMDL_DeDupe(order+0*4, uvert, &uvertcount); - int v1 = HLMDL_DeDupe(order+1*4, uvert, &uvertcount); + int v0 = HLMDL_DeDupe(order+0*4, uvert, &uvertcount, maxverts); + int v1 = HLMDL_DeDupe(order+1*4, uvert, &uvertcount, maxverts); //emit (count-2)*3 indicies as a strip //012 213, etc - + if (idx + (count-2)*3 > maxidx) + break; //would overflow. fixme: extend for (i = min(2,count); i < count; i++) { if (i & 1) @@ -155,18 +163,28 @@ static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel, index[idx++] = v1; } v0 = v1; - index[idx++] = v1 = HLMDL_DeDupe(order+i*4, uvert, &uvertcount); + index[idx++] = v1 = HLMDL_DeDupe(order+i*4, uvert, &uvertcount, maxverts); } } order += i*4; } - submodel->submesh[m].numindexes = idx - submodel->submesh[m].firstindex; + if (uvertcount >= maxverts) + { + //if we're overflowing our verts, rewind, as we cannot generate this mesh. we'll just end up with a 0-index mesh, with no extra verts either + uvertcount = uvertstart; + idx = submodel->submesh[m].firstindex; + } + submodel->submesh[m].numindexes = idx - submodel->submesh[m].firstindex; } + mesh->numindexes = idx; mesh->numvertexes = uvertcount; + mesh->indexes = ZG_Malloc(model->memgroup, sizeof(*mesh->indexes)*idx); + memcpy(mesh->indexes, index, sizeof(*mesh->indexes)*idx); + mesh->colors4b_array = ZG_Malloc(model->memgroup, sizeof(*mesh->colors4b_array)*uvertcount); mesh->st_array = ZG_Malloc(model->memgroup, sizeof(*mesh->st_array)*uvertcount); mesh->lmst_array[0] = ZG_Malloc(model->memgroup, sizeof(*mesh->lmst_array[0])*uvertcount); @@ -195,6 +213,7 @@ static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel, //don't need that mapping any more free(uvert); + free(index); //treat this as the base pose, and calculate the sdir+tdir for bumpmaps. R_Generate_Mesh_ST_Vectors(mesh); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index f475b3ee2..7b57eb767 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -1491,6 +1491,7 @@ void Mod_FinishTexture(texture_t *tx, const char *loadname, qboolean safetoloadf R_InitSky (tx->shader, shadername, tx->mips[0], tx->width, tx->height); else { + uploadfmt_t fmt; unsigned int maps = 0; maps |= SHADER_HASPALETTED; maps |= SHADER_HASDIFFUSE; @@ -1500,7 +1501,23 @@ void Mod_FinishTexture(texture_t *tx, const char *loadname, qboolean safetoloadf maps |= SHADER_HASNORMALMAP; if (gl_specular.ival) maps |= SHADER_HASGLOSS; - R_BuildLegacyTexnums(tx->shader, origname, loadname, maps, 0, ((*tx->name=='{')?TF_TRANS8:TF_MIP4_SOLID8), tx->width, tx->height, tx->mips, tx->palette); + + if (tx->palette) + { //halflife, probably... + if (*tx->name == '{') + fmt = TF_MIP4_8PAL24_T255; + else + fmt = TF_MIP4_8PAL24; + } + else + { + if (*tx->name == '{') + fmt = TF_TRANS8; + else + fmt = TF_MIP4_SOLID8; + } + + R_BuildLegacyTexnums(tx->shader, origname, loadname, maps, 0, fmt, tx->width, tx->height, tx->mips, tx->palette); } BZ_Free(tx->mips[0]); #endif @@ -1514,7 +1531,7 @@ static void Mod_LoadMiptex(model_t *loadmodel, texture_t *tx, miptex_t *mt) (mt->width>>2)*(mt->height>>2) + (mt->width>>3)*(mt->height>>3); - if (loadmodel->fromgame == fg_halflife) + if (loadmodel->fromgame == fg_halflife && *(short*)((qbyte *)mt + mt->offsets[3] + (mt->width>>3)*(mt->height>>3)) == 256) { //mostly identical, just a specific palette hidden at the end. handle fences elsewhere. tx->mips[0] = BZ_Malloc(size + 768); tx->palette = tx->mips[0] + size; @@ -1523,7 +1540,7 @@ static void Mod_LoadMiptex(model_t *loadmodel, texture_t *tx, miptex_t *mt) else { tx->mips[0] = BZ_Malloc(size); - tx->palette = host_basepal; + tx->palette = NULL; } tx->mips[1] = tx->mips[0] + (mt->width>>0)*(mt->height>>0); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 6c4d1e4b1..819f0a349 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -5092,16 +5092,32 @@ void QDECL R_BuildLegacyTexnums(shader_t *shader, const char *fallbackname, cons if (shader->generator == Shader_DefaultSkin) subpath = shader->genargs; - if (basefmt == TF_MIP4_SOLID8 && (!mipdata[0] || !mipdata[1] || !mipdata[2] || !mipdata[3])) - basefmt = TF_SOLID8; + //optimise away any palette info if we can... + if (!palette || palette == host_basepal) + { + if (basefmt == TF_MIP4_8PAL24) + basefmt = TF_MIP4_SOLID8; +// if (basefmt == TF_MIP4_8PAL24_T255) +// basefmt = TF_MIP4_TRANS8; + } //make sure the noalpha thing is set properly. - imageflags |= (basefmt==TF_SOLID8 || basefmt == TF_MIP4_SOLID8)?IF_NOALPHA:0; + switch(basefmt) + { + case TF_MIP4_8PAL24: + case TF_MIP4_SOLID8: + case TF_SOLID8: + imageflags |= IF_NOALPHA; + if (!mipdata[0] || !mipdata[1] || !mipdata[2] || !mipdata[3]) + basefmt = TF_SOLID8; + break; + default: + if (!mipdata[0] || !mipdata[1] || !mipdata[2] || !mipdata[3]) + basefmt = TF_SOLID8; + break; + } imageflags |= IF_MIPCAP; - if (basefmt == TF_MIP4_SOLID8 && palette && palette != host_basepal) - basefmt = TF_MIP4_8PAL24; - COM_StripExtension(imagename, imagename, sizeof(imagename)); aframes = max(1, shader->numdefaulttextures); @@ -5731,6 +5747,7 @@ void Shader_DefaultBSPQ1(const char *shortname, shader_t *s, const void *args) if (!builtin && *shortname == '{') { /*alpha test*/ + /*FIXME: use defaultwall#ALPHA=0.666 or so*/ builtin = ( "{\n" /* "if $deluxmap\n" @@ -5746,7 +5763,7 @@ void Shader_DefaultBSPQ1(const char *shortname, shader_t *s, const void *args) "{\n" "map $diffuse\n" "tcgen base\n" - "alphamask\n" + "alphafunc ge128\n" "}\n" // "if $lightmap\n" "{\n" diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 102d500c0..7aaed7730 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -1469,6 +1469,7 @@ progexterns_t defexterns = { NULL, //int (*FileSize) (char *fname); //-1 if file does not exist NULL, //bool (*WriteFile) (char *name, void *data, int len); qclib_null_printf, //void (*printf) (char *, ...); + qclib_null_printf, //void (*dprintf) (char *, ...); (void*)exit, //void (*Sys_Error) (char *, ...); NULL, //void (*Abort) (char *, ...); NULL, diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 01948d120..4939a7c99 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -1410,7 +1410,7 @@ const char *ED_ParseEdict (progfuncs_t *progfuncs, const char *data, edictrun_t { if ((key = ED_FindField (progfuncs, "angles"))) { - sprintf (qcc_token, "0 %f 0", atof(qcc_token)); //change it from yaw to 3d angle + QC_snprintfz (qcc_token, sizeof(qcc_token), "0 %f 0", atof(qcc_token)); //change it from yaw to 3d angle goto cont; } } @@ -1419,7 +1419,7 @@ const char *ED_ParseEdict (progfuncs_t *progfuncs, const char *data, edictrun_t goto cont; if (externs->badfield && externs->badfield(&progfuncs->funcs, (struct edict_s*)ent, keyname, qcc_token)) continue; - printf ("'%s' is not a field\n", keyname); + PR_DPrintf ("'%s' is not a field\n", keyname); continue; } diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 259dd161d..640f02673 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -212,6 +212,7 @@ extern QCC_opcode_t pr_opcodes[]; // sized by initialization #define sv_num_edicts (*externs->sv_num_edicts) #define sv_edicts (*externs->sv_edicts) +#define PR_DPrintf externs->DPrintf #define printf externs->Printf #define Sys_Error externs->Sys_Error diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index dc1f76819..59263bd03 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -206,6 +206,7 @@ typedef struct progexterns_s { int (PDECL *FileSize) (const char *fname); //-1 if file does not exist pbool (PDECL *WriteFile) (const char *name, void *data, int len); int (VARGS *Printf) (const char *, ...) LIKEPRINTF(1); + int (VARGS *DPrintf) (const char *, ...) LIKEPRINTF(1); void (VARGS *Sys_Error) (const char *, ...) LIKEPRINTF(1); void (VARGS *Abort) (char *, ...) LIKEPRINTF(1); pbool (PDECL *CheckHeaderCrc) (pubprogfuncs_t *inst, progsnum_t idx, int crc); @@ -262,7 +263,7 @@ typedef union eval_s #define PR_CURRENT -1 #define PR_ANY -2 //not always valid. Use for finding funcs #define PR_ANYBACK -3 -#define PROGSTRUCT_VERSION 3 +#define PROGSTRUCT_VERSION 4 #ifndef DLL_PROG diff --git a/engine/qclib/qccgui.c b/engine/qclib/qccgui.c index 3bf348c8a..5ec4c86b0 100644 --- a/engine/qclib/qccgui.c +++ b/engine/qclib/qccgui.c @@ -6195,6 +6195,7 @@ void RunCompiler(char *args, pbool quick) ext.Printf = GUIprintf; GUIprintf(""); } + ext.DPrintf = ext.Printf; if (logfile) fclose(logfile); diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 1f8f68486..0500eea74 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -607,6 +607,7 @@ void Q_SetProgsParms(qboolean forcompiler) svprogparms.FileSize = COM_FileSize;//int (*FileSize) (char *fname); //-1 if file does not exist svprogparms.WriteFile = QC_WriteFile;//bool (*WriteFile) (char *name, void *data, int len); svprogparms.Printf = PR_Printf;//Con_Printf;//void (*printf) (char *, ...); + svprogparms.DPrintf = PR_DPrintf;//Con_Printf;//void (*printf) (char *, ...); svprogparms.CheckHeaderCrc = PR_SSQC_CheckHeaderCrc; svprogparms.Sys_Error = Sys_Error; svprogparms.Abort = SV_Error; @@ -1496,15 +1497,13 @@ static void PDECL PR_DoSpawnInitialEntity(pubprogfuncs_t *progfuncs, struct edic #ifdef QCGC const char *in; ctx->fulldata->string = progfuncs->AllocTempString(progfuncs, &spawndata, end-start+1); - for (in = start; in < end; in++) + for (in = start; in < end; ) { - if (*in == '\n') - { - in++; + char c = *in++; + if (c == '\n') *spawndata++ = '\t'; - } else - *spawndata++ = *in++; + *spawndata++ = c; } *spawndata = 0; #else @@ -8996,7 +8995,24 @@ int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *v #endif if (!strcmp(key, "*spectator")) - svs.clients[entnum-1].spectator = !!atoi(value); + { + int ns = !!atoi(value); + + if (svs.clients[entnum-1].state == cs_spawned) + { + if (svs.clients[entnum-1].spectator) + sv.spawned_observer_slots--; + else + sv.spawned_client_slots--; + svs.clients[entnum-1].spectator = ns; + if (ns) + sv.spawned_observer_slots++; + else + sv.spawned_client_slots++; + } + else + svs.clients[entnum-1].spectator = ns; + } #ifdef _DEBUG if (!strcmp(key, "*transfer")) Con_Printf("WARNING: *transfer is no longer supported\n"); @@ -9717,7 +9733,16 @@ static void QCBUILTIN PF_clustertransfer(pubprogfuncs_t *prinst, struct globalva #endif } - +static void QCBUILTIN PF_setpause(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int pause = (G_FLOAT(OFS_PARM0)?PAUSE_EXPLICIT:0) | (sv.paused&~PAUSE_EXPLICIT); + G_FLOAT(OFS_RETURN) = !!(sv.paused&PAUSE_EXPLICIT); + if (sv.paused != pause) + { + sv.paused = pause; + sv.pausedstart = Sys_DoubleTime(); + } +} #define STUB ,NULL,true @@ -10609,7 +10634,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs // {"delayedparticle", PF_Fixme, 0, 0, 0, 528, "float(vector org, vector vel, float delay, float collisiondelay, optional float theme)"}, {"loadfromdata", PF_loadfromdata, 0, 0, 0, 529, D("void(string s)", "Reads a set of entities from the given string. This string should have the same format as a .ent file or a saved game. Entities will be spawned as required. If you need to see the entities that were created, you should use parseentitydata instead.")}, {"loadfromfile", PF_loadfromfile, 0, 0, 0, 530, D("void(string s)", "Reads a set of entities from the named file. This file should have the same format as a .ent file or a saved game. Entities will be spawned as required. If you need to see the entities that were created, you should use parseentitydata instead.")}, -// {"setpause", VM_SV_setpause, 0, 0, 0, 531, "void(float pause)" STUB}, + {"setpause", PF_setpause, 0, 0, 0, 531, D("void(float pause)", "Sets whether the server should or should not be paused. This does not affect auto-paused things like when the console is down.")}, //end dp extras //begin mvdsv extras {"precache_vwep_model",PF_precache_vwep_model,0,0, 0, 532, "float(string mname)"}, diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index f22ffe457..a15fd9e1c 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -4476,10 +4476,10 @@ float SV_Frame (void) #ifndef SERVERONLY isidle = !isDedicated && sv.allocated_client_slots == 1 && Key_Dest_Has(~kdm_game) && cls.state == ca_active; - /*server is effectively paused if there are no clients*/ -// if (sv.spawned_client_slots == 0 && sv.spawned_observer_slots == 0 && (cls.state != ca_connected)) -// isidle = true; - if ((sv.paused & PAUSE_AUTO) != ((isidle||(sv.spawned_client_slots==0&&!deathmatch.ival))?PAUSE_AUTO:0)) + /*server is effectively paused in SP/coop if there are no clients/spectators*/ + if (sv.spawned_client_slots == 0 && sv.spawned_observer_slots == 0 && !deathmatch.ival) + isidle = true; + if ((sv.paused & PAUSE_AUTO) != ((isidle)?PAUSE_AUTO:0)) sv.paused ^= PAUSE_AUTO; #endif diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 46e784b08..0c5b9eacd 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -2364,6 +2364,8 @@ void World_Physics_Frame(world_t *w) float ft = host_frametime; host_client = &svs.clients[i-1]; sv_player = svs.clients[i-1].edict; + + host_client->lastruncmd = newt; SV_PreRunCmd(); #ifndef NEWSPEEDCHEATPROT svs.clients[i-1].last_check = 0; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 18481aa11..57f9515a0 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -6425,10 +6425,6 @@ void SV_PreRunCmd(void) playertouch = BZ_Malloc((playertouchmax>>3)+1); } memset(playertouch, 0, playertouchmax>>3); - - //timestamp it, so things can't go weird - if (host_client) - host_client->lastruncmd = sv.time * 1000; } void SV_RunCmdCleanup(void) { diff --git a/engine/server/svhl_game.c b/engine/server/svhl_game.c index 99562f13f..7b1365ea0 100644 --- a/engine/server/svhl_game.c +++ b/engine/server/svhl_game.c @@ -2354,11 +2354,11 @@ void SVHL_Snapshot_Build(client_t *client, packet_entities_t *pack, qbyte *pvs, case 0: s->trans = 255; break; - case 1: //used on laser beams, apparently + case 1: //used on laser beams, apparently. disables textures or something. break; case 2: //transparent windows. break; - case 3: //used on coronarey sprites. + case 3: //used on coronarey sprites. both additive and resizing to give constant distance s->effects |= NQEF_ADDITIVE; break; case 4: //used on fence textures, apparently. we already deal with these clientside.