Attempt to optimise texture memory by loading greyscale tgas as 8bit. Extend serverbrowser api for xonotic. Be more aggressive with loading hardware cursor images. Fix software banding with compressed textures. Rework autosprites to cope with atlased texcoords (note: q3 would discard the texcoords).

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5312 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-09-29 17:31:58 +00:00
parent caa5be6267
commit 8279a76675
53 changed files with 6924 additions and 7253 deletions

View file

@ -113,6 +113,9 @@ ENDIF()
IF(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-sign")
endif()
IF(CMAKE_BUILD_TYPE MATCHES "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong")
endif()
IF(${ANDROID})
# FIND_PACKAGE(Freetype REQUIRED)

View file

@ -273,7 +273,8 @@ fi
if [ "$BUILD_WINDOWS" == "y" ]; then
#for building windows targets
debianpackages mingw-w64 || otherpackages x86_64-w64-mingw32-gcc || exit
#python is needed to configure scintilla properly.
debianpackages mingw-w64 python || otherpackages x86_64-w64-mingw32-gcc python || exit
fi

View file

@ -214,19 +214,20 @@ fi
echo "--- QC builds ---"
rm -rf $QCCBUILDFOLDER 2>&1
mkdir -p $QCCBUILDFOLDER
if [ -e "$BUILDFOLDER/linux_x86/fteqw-gl32" ]
#this really should use the native cpu type... until then we use 32bit in case anyone's still using a 32bit kernel.
if [ -e "$BUILDFOLDER/linux_x86/fteqw32" ]
then
echo "Making fteextensions.qc"
mkdir -p ~/.fte/fte
echo "pr_dumpplatform -o fteextensions" > ~/.fte/fte/minusargsaresilly.cfg
echo "pr_dumpplatform -o csqcsysdefs -Tcs" >> ~/.fte/fte/minusargsaresilly.cfg
echo "pr_dumpplatform -o menusysdefs -Tmenu" >> ~/.fte/fte/minusargsaresilly.cfg
$BUILDFOLDER/linux_x86/fteqw-gl32 -basedir ~/.fte -nohome -quake +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null
$BUILDFOLDER/linux_x86/fteqw32 -basedir ~/.fte -nohome -quake +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null
mv ~/.fte/fte/src/fteextensions.qc $QCCBUILDFOLDER
mv ~/.fte/fte/src/csqcsysdefs.qc $QCCBUILDFOLDER
mv ~/.fte/fte/src/menusysdefs.qc $QCCBUILDFOLDER
else
echo "Skipping FTE Extensions, no Linux gl32 build located"
echo "Skipping FTE Extensions, no Linux x86 (merged) build located"
fi

View file

@ -2174,7 +2174,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
{
cl_pendingcmd[plnum].msec = 0;
cl_pendingcmd[plnum].impulse = 0;
cl_pendingcmd[plnum].buttons = 0;
// cl_pendingcmd[plnum].buttons = 0;
}
}

View file

@ -797,7 +797,7 @@ void CL_CheckForResend (void)
connectinfo.fteext1 = Net_PextMask(1, false);
connectinfo.fteext2 = Net_PextMask(2, false);
}
else if (!strcmp(lbp, "qwid") || !strcmp(cl_loopbackprotocol.string, "idqw"))
else if (!strcmp(lbp, "qwid") || !strcmp(lbp, "idqw"))
{ //for recording .qwd files in any client
connectinfo.protocol = CP_QUAKEWORLD;
connectinfo.subprotocol = PROTOCOL_VERSION_QW;
@ -824,12 +824,15 @@ void CL_CheckForResend (void)
connectinfo.fteext2 = Net_PextMask(2, false);
}
}
else if (!strcmp(lbp, "fitz") || !strcmp(lbp, "666") || !strcmp(lbp, "999"))
else if (!strcmp(lbp, "fitz") || !strcmp(lbp, "rmqe") ||
!strcmp(lbp, "qs") ||
!strcmp(lbp, "666") || !strcmp(lbp, "999"))
{ //we don't really distinguish between fitz and rmq protocols. we just use 999 with bigcoords and 666 othewise.
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_FITZ666;
}
else if (!strcmp(lbp, "bjp3") || !strcmp(lbp, "bjp"))
else if (!strcmp(lbp, "bjp1") || !strcmp(lbp, "bjp2") || //placeholders only
!strcmp(lbp, "bjp3") || !strcmp(lbp, "bjp"))
{
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_BJP3;
@ -845,17 +848,24 @@ void CL_CheckForResend (void)
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_ID;
}
else if (!strcmp(lbp, "dp6") || !strcmp(lbp, "dpp6"))
else if (!strcmp(lbp, "dp1") || !strcmp(lbp, "dpp1")|| //most of these are not supported, but parsed as placeholders on the slim chance that we ever do support them
!strcmp(lbp, "dp2") || !strcmp(lbp, "dpp2")||
!strcmp(lbp, "dp3") || !strcmp(lbp, "dpp3")||
!strcmp(lbp, "dp4") || !strcmp(lbp, "dpp4")||
!strcmp(lbp, "dp5") || !strcmp(lbp, "dpp5")|| //we support this serverside, but not clientside.
!strcmp(lbp, "dp6") || !strcmp(lbp, "dpp6")) //this one is supported.
{
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_DP6;
}
else if (!strcmp(lbp, "dp7") || !strcmp(lbp, "dpp7"))
else if (!strcmp(lbp, "dp7") || !strcmp(lbp, "dpp7") ||
!strcmp(lbp, "dp") || !strcmp(lbp, "xonotic")) //family name, common usage.
{
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_DP7;
}
else if (progstype != PROG_QW && progstype != PROG_H2) //h2 depends on various extensions and doesn't really match either protocol, but we go for qw because that gives us all sorts of extensions.
else if (!strcmp(lbp, "qss") ||
(progstype != PROG_QW && progstype != PROG_H2)) //h2 depends on various extensions and doesn't really match either protocol, but we go for qw because that gives us all sorts of extensions.
{
connectinfo.protocol = CP_NETQUAKE;
connectinfo.subprotocol = CPNQ_FITZ666;

View file

@ -72,6 +72,7 @@ typedef enum hostcachekey_e
SLKEY_NUMSPECTATORS,//spectators
SLKEY_NUMHUMANS, //actual players
SLKEY_QCSTATUS,
SLKEY_CATEGORY, //urgh, hideous shite.
// SLKEY_PLAYERS, //eep!
SLKEY_ISFAVORITE,//eep!
SLKEY_ISLOCAL,
@ -140,8 +141,10 @@ typedef struct serverinfo_s
qbyte numbots;
qbyte freeslots;
int qccategory; //urgh
char qcstatus[128];
char modname[8+1];
char qcstatus[8+1];
char gamedir[8+1];
char map[16];

View file

@ -128,7 +128,6 @@ static qintptr_t VARGS Plug_Draw_LoadImage(char *name, int type, char *script)
return i + 1;
}
qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean *hasalpha, const char *fname);
static qintptr_t VARGS Plug_Draw_LoadImageData(void *offset, quintptr_t mask, const qintptr_t *arg)
{
qintptr_t ret = 0;
@ -139,11 +138,12 @@ static qintptr_t VARGS Plug_Draw_LoadImageData(void *offset, quintptr_t mask, co
image_t *t;
qbyte *rgbdata;
unsigned int width, height;
uploadfmt_t format;
if (VM_OOB(arg[2], arg[3]))
return 0;
if ((rgbdata = Read32BitImageFile(codeddata, datalength, &width, &height, NULL, name)))
if ((rgbdata = ReadRawImageFile(codeddata, datalength, &width, &height, &format, false, name)))
{
// name = va("%s", name);
@ -152,7 +152,7 @@ static qintptr_t VARGS Plug_Draw_LoadImageData(void *offset, quintptr_t mask, co
t = Image_CreateTexture(name, NULL, IF_PREMULTIPLYALPHA|IF_NOMIPMAP|IF_UIPIC|IF_CLAMP);
if (TEXVALID(t))
{
Image_Upload(t, TF_RGBA32, rgbdata, NULL, width, height, IF_PREMULTIPLYALPHA|IF_NOMIPMAP|IF_UIPIC|IF_CLAMP);
Image_Upload(t, format, rgbdata, NULL, width, height, IF_PREMULTIPLYALPHA|IF_NOMIPMAP|IF_UIPIC|IF_CLAMP);
ret = Plug_Draw_LoadImage(name, 3, NULL);
}

View file

@ -993,7 +993,19 @@ void SCR_DrawCursor(void)
{
key_customcursor[cmod].handle = NULL;
if (!key_customcursor[cmod].handle && *key_customcursor[cmod].name)
key_customcursor[cmod].handle = rf->VID_CreateCursor(key_customcursor[cmod].name, key_customcursor[cmod].hotspot[0], key_customcursor[cmod].hotspot[1], key_customcursor[cmod].scale);
{
image_t dummytex;
flocation_t loc;
char bestname[MAX_QPATH];
unsigned int bestflags;
memset(&dummytex, 0, sizeof(dummytex));
dummytex.ident = key_customcursor[cmod].name;
dummytex.flags = IF_NOREPLACE; //no dds files
if (Image_LocateHighResTexture(&dummytex, &loc, bestname, sizeof(bestname), &bestflags))
key_customcursor[cmod].handle = rf->VID_CreateCursor(bestname, key_customcursor[cmod].hotspot[0], key_customcursor[cmod].hotspot[1], key_customcursor[cmod].scale);
else
key_customcursor[cmod].handle = rf->VID_CreateCursor(key_customcursor[cmod].name, key_customcursor[cmod].hotspot[0], key_customcursor[cmod].hotspot[1], key_customcursor[cmod].scale);
}
if (!key_customcursor[cmod].handle)
key_customcursor[cmod].handle = rf->VID_CreateCursor("gfx/cursor.tga", key_customcursor[cmod].hotspot[0], key_customcursor[cmod].hotspot[1], key_customcursor[cmod].scale); //try the fallback
if (!key_customcursor[cmod].handle)
@ -2147,6 +2159,7 @@ void SCR_EndLoadingPlaque (void)
void SCR_ImageName (const char *mapname)
{
//assume levelshots/foo
strcpy(levelshotname, "levelshots/");
COM_FileBase(mapname, levelshotname + strlen(levelshotname), sizeof(levelshotname)-strlen(levelshotname));
@ -2156,9 +2169,15 @@ void SCR_ImageName (const char *mapname)
if (!R_GetShaderSizes(R2D_SafeCachePic (levelshotname), NULL, NULL, true))
{
*levelshotname = '\0';
if (scr_disabled_for_loading)
return;
//try maps/foo
strcpy(levelshotname, "maps/");
COM_FileBase(mapname, levelshotname + strlen(levelshotname), sizeof(levelshotname)-strlen(levelshotname));
if (!R_GetShaderSizes(R2D_SafeCachePic (levelshotname), NULL, NULL, true))
{
*levelshotname = '\0';
if (scr_disabled_for_loading)
return;
}
}
}
else

View file

@ -2306,14 +2306,15 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
send += center;
if (selactive == 1)
{
R2D_ImageColours(SRGBA(0.1,0.1,0.3, alphaval));
if (send < sstart)
R2D_FillBlock((send*vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((sstart - send)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight);
else
R2D_FillBlock((sstart*vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((send - sstart)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight);
R2D_Flush();
}
R2D_ImageColours(SRGBA(0.1,0.1,0.3, alphaval)); //selected
else
R2D_ImageColours(SRGBA(0.3,0.3,0.3, alphaval)); //mouseover.
if (send < sstart)
R2D_FillBlock((send*vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((sstart - send)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight);
else
R2D_FillBlock((sstart*vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((send - sstart)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight);
R2D_Flush();
}
}
}
@ -2663,6 +2664,8 @@ void Con_DrawConsole (int lines, qboolean noback)
{
shader = R2D_SafeCachePic("tiprawimg");
shader->defaulttextures->base = Image_FindTexture(key, NULL, IF_NOREPLACE|IF_PREMULTIPLYALPHA);
if (!shader->defaulttextures->base)
shader->defaulttextures->base = Image_FindTexture(key, NULL, IF_NOREPLACE);
if (!shader->defaulttextures->base)
{
size_t fsize;

File diff suppressed because it is too large Load diff

View file

@ -2299,7 +2299,7 @@ static cin_t *Media_Static_TryLoad(char *name)
qbyte *staticfilmimage;
int imagewidth;
int imageheight;
qboolean hasalpha;
uploadfmt_t format = PTI_RGBA8;
int fsize;
char fullname[MAX_QPATH];
@ -2316,7 +2316,7 @@ static cin_t *Media_Static_TryLoad(char *name)
}
if ((staticfilmimage = ReadPCXFile(file, fsize, &imagewidth, &imageheight)) || //convert to 32 rgba if not corrupt
(staticfilmimage = ReadTargaFile(file, fsize, &imagewidth, &imageheight, &hasalpha, false)) ||
(staticfilmimage = ReadTargaFile(file, fsize, &imagewidth, &imageheight, &format, false, PTI_RGBA8)) ||
#ifdef AVAIL_JPEGLIB
(staticfilmimage = ReadJPEGFile(file, fsize, &imagewidth, &imageheight)) ||
#endif

View file

@ -481,6 +481,7 @@ qboolean MP_MousePosition(float x, float y, unsigned int devid);
qboolean MP_JoystickAxis(int axis, float value, unsigned int devid);
int MP_BuiltinValid(const char *name, int num);
qboolean MP_ConsoleCommand(const char *cmdtext);
int MP_GetServerCategory(int index);
#endif
#ifdef MENU_NATIVECODE

View file

@ -50,6 +50,26 @@ void Master_DetermineMasterTypes(void)
}
}
}
qboolean Master_MasterProtocolIsEnabled(enum masterprotocol_e protocol)
{
switch (protocol)
{
case MP_DPMASTER:
return sb_enabledarkplaces;
#ifdef Q2SERVER
case MP_QUAKE2:
return sb_enablequake2;
#endif
#ifdef Q3SERVER
case MP_QUAKE3:
return sb_enablequake3;
#endif
case MP_QUAKEWORLD:
return sb_enablequakeworld;
default:
return false;
}
}
#define MAX_MASTER_ADDRESSES 4 //each master might have multiple dns addresses, typically both ipv4+ipv6. we want to report to both address families so we work with remote single-stack hosts.
@ -429,7 +449,6 @@ let it know we are alive, and log information
void SV_Master_Heartbeat (void)
{
int i;
qboolean enabled;
if (sv_public.ival<=0 || SSV_IsSubServer())
return;
@ -446,19 +465,7 @@ void SV_Master_Heartbeat (void)
// send to group master
for (i = 0; net_masterlist[i].cv.name; i++)
{
switch (net_masterlist[i].protocol)
{
case MP_DPMASTER: enabled = sb_enabledarkplaces; break;
#ifdef Q2SERVER
case MP_QUAKE2: enabled = sb_enablequake2; break;
#endif
#ifdef Q3SERVER
case MP_QUAKE3: enabled = sb_enablequake3; break;
#endif
case MP_QUAKEWORLD: enabled = sb_enablequakeworld; break;
default: enabled = false; break;
}
if (!enabled)
if (!Master_MasterProtocolIsEnabled(net_masterlist[i].protocol))
continue;
if (net_masterlist[i].resolving)
@ -650,7 +657,10 @@ static int numvisibleservers;
static int maxvisibleservers;
static hostcachekey_t sortfield;
static qboolean decreasingorder;
static qboolean sort_decreasing;
static qboolean sort_favourites;
static qboolean sort_categories;
static serverinfo_t *categorisingserver; //returned for sorted server -1 (hacky)
@ -802,6 +812,14 @@ qboolean Master_CompareString(const char *a, const char *b, slist_test_t rule)
qboolean Master_ServerIsGreater(serverinfo_t *a, serverinfo_t *b)
{
if (sort_categories)
if (a->qccategory != b->qccategory)
return Master_CompareInteger(a->qccategory, b->qccategory, SLIST_TEST_LESS);
if (sort_favourites)
if ((a->special & SS_FAVORITE) != (b->special & SS_FAVORITE))
return Master_CompareInteger(a->special & SS_FAVORITE, b->special & SS_FAVORITE, SLIST_TEST_LESS);
switch(sortfield)
{
case SLKEY_ADDRESS:
@ -868,6 +886,9 @@ qboolean Master_ServerIsGreater(serverinfo_t *a, serverinfo_t *b)
case SLKEY_ISFAVORITE:
return Master_CompareInteger(a->special & SS_FAVORITE, b->special & SS_FAVORITE, SLIST_TEST_LESS);
case SLKEY_CATEGORY:
return Master_CompareInteger(a->qccategory, b->qccategory, SLIST_TEST_LESS);
case SLKEY_MOD:
case SLKEY_PROTOCOL:
case SLKEY_QCSTATUS:
@ -890,18 +911,6 @@ qboolean Master_PassesMasks(serverinfo_t *a)
if (!(a->status & 1))
return false;
/* switch(a->special & SS_PROTOCOLMASK)
{
case SS_QUAKE3: enabled = sb_enablequake3; break;
case SS_QUAKE2: enabled = sb_enablequake2; break;
case SS_NETQUAKE: enabled = sb_enablenetquake; break;
case SS_QUAKEWORLD: enabled = sb_enablequakeworld; break;
case SS_DARKPLACES: enabled = sb_enabledarkplaces; break;
default: enabled = true; break;
}
if (!enabled)
return false;
*/
val = 1;
for (i = 0; i < numvisrules; i++)
@ -961,6 +970,9 @@ qboolean Master_PassesMasks(serverinfo_t *a)
case SLKEY_QCSTATUS:
res = Master_CompareString(a->qcstatus, visrules[i].operands, visrules[i].compareop);
break;
case SLKEY_CATEGORY:
res = Master_CompareInteger(a->qccategory, visrules[i].operandi, visrules[i].compareop);
break;
default:
continue;
}
@ -1000,10 +1012,12 @@ void Master_SetMaskInteger(qboolean or, hostcachekey_t field, int param, slist_t
visrules[numvisrules].or = or;
numvisrules++;
}
void Master_SetSortField(hostcachekey_t field, qboolean descending)
void Master_SetSortField(hostcachekey_t field, unsigned int sortflags)
{
sortfield = field;
decreasingorder = descending;
sort_decreasing = sortflags & 1;
sort_favourites = sortflags & 2;
sort_categories = sortflags & 4;
}
hostcachekey_t Master_GetSortField(void)
{
@ -1011,7 +1025,7 @@ hostcachekey_t Master_GetSortField(void)
}
qboolean Master_GetSortDescending(void)
{
return decreasingorder;
return sort_decreasing;
}
void Master_ShowServer(serverinfo_t *server)
@ -1023,7 +1037,7 @@ void Master_ShowServer(serverinfo_t *server)
return;
}
if (decreasingorder)
if (sort_decreasing)
{
for (i = 0; i < numvisibleservers; i++)
{
@ -1092,7 +1106,11 @@ int Master_SortServers(void)
serverinfo_t *Master_SortedServer(int idx)
{
if (idx < 0 || idx >= numvisibleservers)
{
if (idx == -1)
return categorisingserver;
return NULL;
}
return visibleservers[idx];
}
@ -1141,6 +1159,8 @@ float Master_ReadKeyFloat(serverinfo_t *server, hostcachekey_t keynum)
return !!(server->special & SS_LOCAL);
case SLKEY_ISPROXY:
return !!(server->special & SS_PROXY);
case SLKEY_CATEGORY:
return server->qccategory;
default:
return atof(Master_ReadKeyString(server, keynum));
@ -1277,6 +1297,8 @@ hostcachekey_t Master_KeyForName(const char *keyname)
return SLKEY_ISLOCAL;
else if (!strcmp(keyname, "isproxy"))
return SLKEY_ISPROXY;
else if (!strcmp(keyname, "category"))
return SLKEY_CATEGORY;
else if (!strcmp(keyname, "serverinfo"))
return SLKEY_SERVERINFO;
else if (!strncmp(keyname, "player", 6))
@ -1425,7 +1447,9 @@ void CLMaster_AddMaster_Worker_Resolved(void *ctx, void *data, size_t a, size_t
if (mast->adr.type == NA_INVALID)
{
Con_Printf("Failed to resolve master address \"%s\"\n", mast->address);
if (b)
Con_Printf("Failed to resolve master address \"%s\"\n", mast->address);
//else master not enabled anyway. the lookup was skipped.
}
else if (mast->adr.type != NA_IP && mast->adr.type != NA_IPV6 && mast->adr.type != NA_IPX)
{
@ -1492,18 +1516,24 @@ void CLMaster_AddMaster_Worker_Resolve(void *ctx, void *data, size_t a, size_t b
// qboolean first = true;
char *str;
master_t *work = data;
//resolve all the addresses
str = work->address;
while (str && *str)
if (!b)
;
else
{
str = COM_ParseOut(str, token, sizeof(token));
if (*token)
found += NET_StringToAdr2(token, 0, &adrs[found], MAX_MASTER_ADDRESSES-found);
//we don't do this logic because windows doesn't look up ipv6 names if it only has teredo
//this means an ipv4+teredo client cannot see ivp6-only servers. and that sucks.
// if (first && found)
// break; //if we found one by name, don't try any fallback ip addresses.
// first = false;
//resolve all the addresses
str = work->address;
while (str && *str)
{
str = COM_ParseOut(str, token, sizeof(token));
if (*token)
found += NET_StringToAdr2(token, 0, &adrs[found], MAX_MASTER_ADDRESSES-found);
//we don't do this logic because windows doesn't look up ipv6 names if it only has teredo
//this means an ipv4+teredo client cannot see ivp6-only servers. and that sucks.
// if (first && found)
// break; //if we found one by name, don't try any fallback ip addresses.
// first = false;
}
}
//add the main ip address
@ -1563,7 +1593,7 @@ void Master_AddMaster (char *address, enum mastertype_e mastertype, enum masterp
strcpy(mast->address, address);
mast->sends = 1;
COM_AddWork(WG_LOADER, CLMaster_AddMaster_Worker_Resolve, NULL, mast, 0, 0);
COM_AddWork(WG_LOADER, CLMaster_AddMaster_Worker_Resolve, NULL, mast, 0, true/*Master_MasterProtocolIsEnabled(protocol)*/);
}
void MasterInfo_Shutdown(void)
@ -3361,6 +3391,13 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
memcpy(info->moreinfo, &details, sizeof(serverdetailedinfo_t));
}
info->qccategory = 0;
#ifdef MENU_DAT
categorisingserver = info;
info->qccategory = MP_GetServerCategory(-1);
categorisingserver = NULL;
#endif
return true;
}

View file

@ -310,6 +310,7 @@ typedef struct part_type_s {
vec3_t dl_scales;
//PT_NODLSHADOW
int dl_cubemapnum;
int dl_lightstyle;
vec3_t stain_rgb;
float stain_radius;
@ -970,10 +971,10 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn)
/*texture looks good, make a shader, and give it the texture as a diffuse stage*/
ptype->looks.shader = R_RegisterShader(va("%s%s", ptype->texname, namepostfix), SUF_NONE, defaultshader);
}
R_BuildDefaultTexnums(&tn, ptype->looks.shader);
R_BuildDefaultTexnums(&tn, ptype->looks.shader, 0);
}
else
R_BuildDefaultTexnums(NULL, ptype->looks.shader);
R_BuildDefaultTexnums(NULL, ptype->looks.shader, 0);
}
static void P_ResetToDefaults(part_type_t *ptype)
@ -2219,6 +2220,8 @@ parsefluid:
ptype->flags = (ptype->flags & ~PT_NODLSHADOW) | (atof(value)?0:PT_NODLSHADOW);
else if (!strcmp(var, "lightcubemap"))
ptype->dl_cubemapnum = atoi(value);
else if (!strcmp(var, "lightstyle"))
ptype->dl_lightstyle = bound(0, atoi(value)+1, 256);
else if (!strcmp(var, "lightscales"))
{ //ambient diffuse specular
ptype->dl_scales[0] = atof(value);
@ -2577,6 +2580,7 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen)
Q_strncatz(outstr, va("lighttime %g\n", ptype->dl_time), outstrlen);
Q_strncatz(outstr, va("lightshadows %g\n", (ptype->flags & PT_NODLSHADOW)?0.0f:1.0f), outstrlen);
Q_strncatz(outstr, va("lightcubemap %i\n", ptype->dl_cubemapnum), outstrlen);
Q_strncatz(outstr, va("lightstyle %i\n", ptype->dl_lightstyle-1), outstrlen);
Q_strncatz(outstr, va("lightcorona %g %g\n", ptype->dl_corona_intensity, ptype->dl_corona_scale), outstrlen);
Q_strncatz(outstr, va("lightscales %g %g %g\n", ptype->dl_scales[0], ptype->dl_scales[1], ptype->dl_scales[2]), outstrlen);
}
@ -2847,6 +2851,7 @@ static void FinishEffectinfoParticleType(part_type_t *ptype, qboolean blooddecal
}
static void P_ImportEffectInfo(char *config, char *line)
{
float printtimer = 0;
part_type_t *ptype = NULL;
int parenttype;
char arg[8][1024];
@ -3222,19 +3227,19 @@ static void P_ImportEffectInfo(char *config, char *line)
}
#if 1
else if (!strcmp(arg[0], "staincolor") && args == 3) //stainmaps multiplier
Con_DPrintf("Particle effect token %s not supported\n", arg[0]);
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]);
else if (!strcmp(arg[0], "stainalpha") && args == 3) //affects stainmaps AND stain-decals.
Con_DPrintf("Particle effect token %s not supported\n", arg[0]);
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]);
else if (!strcmp(arg[0], "stainsize") && args == 3) //affects stainmaps AND stain-decals.
Con_DPrintf("Particle effect token %s not supported\n", arg[0]);
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]);
else if (!strcmp(arg[0], "staintex") && args == 3) //actually spawns a decal
Con_DPrintf("Particle effect token %s not supported\n", arg[0]);
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]);
else if (!strcmp(arg[0], "stainless") && args == 2)
Con_DPrintf("Particle effect token %s not supported\n", arg[0]);
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]);
else if (!strcmp(arg[0], "relativeoriginoffset") && args == 4)
Con_DPrintf("Particle effect token %s not supported\n", arg[0]);
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]);
else if (!strcmp(arg[0], "relativevelocityoffset") && args == 4)
Con_DPrintf("Particle effect token %s not supported\n", arg[0]);
Con_ThrottlePrintf(&printtimer, 1, "Particle effect token %s not supported\n", arg[0]);
#endif
else if (!strcmp(arg[0], "rotate") && args == 5)
{
@ -3249,7 +3254,7 @@ static void P_ImportEffectInfo(char *config, char *line)
ptype->rotationstartmin += M_PI/4;
}
else
Con_Printf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
Con_ThrottlePrintf(&printtimer, 0, "Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
args = 0;
}
@ -4411,6 +4416,8 @@ static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t axis[3]
dl->flags |= LFLAG_NOSHADOWS;
if (ptype->dl_cubemapnum)
Q_snprintfz(dl->cubemapname, sizeof(dl->cubemapname), "cubemaps/%i", ptype->dl_cubemapnum);
if (ptype->dl_lightstyle > 0)
dl->style = ptype->dl_lightstyle;
}
if (ptype->numsounds)
{

View file

@ -769,7 +769,7 @@ void QCBUILTIN PF_cl_sethostcachemaskstring(pubprogfuncs_t *prinst, struct globa
const char *str = PR_GetStringOfs(prinst, OFS_PARM2);
int op = G_FLOAT(OFS_PARM3);
Master_SetMaskString(mask, field, str, op);
Master_SetMaskString((mask&512)?true:false, field, str, op);
}
//void sethostcachemasknumber(float mask, float fld, float num, float op) = #617;
void QCBUILTIN PF_cl_sethostcachemasknumber(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -779,7 +779,7 @@ void QCBUILTIN PF_cl_sethostcachemasknumber(pubprogfuncs_t *prinst, struct globa
int str = G_FLOAT(OFS_PARM2);
int op = G_FLOAT(OFS_PARM3);
Master_SetMaskInteger(mask, field, str, op);
Master_SetMaskInteger((mask&512)?true:false, field, str, op);
}
//void resorthostcache(void) = #618;
void QCBUILTIN PF_cl_resorthostcache(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)

View file

@ -1562,7 +1562,11 @@ void QCBUILTIN PF_R_PolygonBegin(pubprogfuncs_t *prinst, struct globalvars_s *pr
else if (twod)
shader = R_RegisterPic(shadername, NULL);
else
{
shader = R_RegisterSkin(shadername, NULL);
if (!shader->defaulttextures->base && (shader->flags & SHADER_HASDIFFUSE))
R_BuildDefaultTexnums(NULL, shader, 0);
}
if (R2D_Flush && (R2D_Flush != CSQC_PolyFlush || csqc_poly_shader != shader || csqc_poly_flags != beflags || csqc_poly_2d != twod))
R2D_Flush();
@ -5739,6 +5743,7 @@ static void QCBUILTIN PF_cs_getplayerstat(pubprogfuncs_t *prinst, struct globalv
static void QCBUILTIN PF_V_CalcRefdef(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //this function is essentially an overcomplicated way to shirk from defining your own view bobbing.
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
vec3_t savedvel;
/*enum
{
TELEPORTED,
@ -5760,9 +5765,13 @@ static void QCBUILTIN PF_V_CalcRefdef(pubprogfuncs_t *prinst, struct globalvars_
r_refdef.drawsbar = false; //csqc defaults to no sbar.
r_refdef.drawcrosshair = false;
VectorCopy(csqc_playerview->simvel, savedvel);
VectorCopy(ent->v->origin, csqc_playerview->simorg);
VectorCopy (ent->v->velocity, csqc_playerview->simvel);
csqc_playerview->onground = !!((int)ent->v->flags & FL_ONGROUND);
V_CalcRefdef(csqc_playerview); //set up the defaults
VectorCopy(savedvel, csqc_playerview->simvel);
}
#if 1

View file

@ -771,7 +771,7 @@ void QCBUILTIN PF_CL_readimage (pubprogfuncs_t *prinst, struct globalvars_s *pr_
const char *filename = PR_GetStringOfs(prinst, OFS_PARM0);
int imagewidth, imageheight;
qboolean hasalpha;
uploadfmt_t format;
void *filedata;
G_INT(OFS_RETURN) = 0; //assume the worst
@ -782,7 +782,7 @@ void QCBUILTIN PF_CL_readimage (pubprogfuncs_t *prinst, struct globalvars_s *pr_
if (filedata)
{
qbyte *imagedata = Read32BitImageFile(filedata, filesize, &imagewidth, &imageheight, &hasalpha, filename);
qbyte *imagedata = ReadRawImageFile(filedata, filesize, &imagewidth, &imageheight, &format, true, filename);
Z_Free(filedata);
if (imagedata)
@ -1259,7 +1259,7 @@ static void QCBUILTIN PF_menu_cvar (pubprogfuncs_t *prinst, struct globalvars_s
else
{
str = RemapCvarNameFromDPToFTE(str);
var = Cvar_Get(str, "", 0, "menu cvars");
var = PF_Cvar_FindOrGet(str);
if (var && !(var->flags & CVAR_NOUNSAFEEXPAND))
{
//menuqc sees desired settings, not latched settings.
@ -1281,8 +1281,8 @@ static void QCBUILTIN PF_menu_cvar_set (pubprogfuncs_t *prinst, struct globalvar
var_name = RemapCvarNameFromDPToFTE(var_name);
val = PR_GetStringOfs(prinst, OFS_PARM1);
var = Cvar_Get(var_name, val, 0, "QC variables");
if (var->flags & CVAR_NOTFROMSERVER)
var = PF_Cvar_FindOrGet(var_name);
if (var && var->flags & CVAR_NOTFROMSERVER)
{
//fixme: menuqc needs some way to display a prompt to allow it anyway.
return;
@ -1292,7 +1292,7 @@ static void QCBUILTIN PF_menu_cvar_set (pubprogfuncs_t *prinst, struct globalvar
static void QCBUILTIN PF_menu_cvar_string (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *str = PR_GetStringOfs(prinst, OFS_PARM0);
cvar_t *cv = Cvar_Get(RemapCvarNameFromDPToFTE(str), "", 0, "QC variables");
cvar_t *cv = PF_Cvar_FindOrGet(RemapCvarNameFromDPToFTE(str));
if (!cv)
G_INT(OFS_RETURN) = 0;
else if (cv->flags & CVAR_NOUNSAFEEXPAND)
@ -2419,15 +2419,19 @@ menuedict_t *menu_edicts;
int num_menu_edicts;
world_t menu_world;
func_t mp_init_function;
func_t mp_shutdown_function;
func_t mp_draw_function;
func_t mp_drawloading_function;
func_t mp_keydown_function;
func_t mp_keyup_function;
func_t mp_inputevent_function;
func_t mp_toggle_function;
func_t mp_consolecommand_function;
static struct
{
func_t init;
func_t shutdown;
func_t draw;
func_t drawloading;
func_t keydown;
func_t keyup;
func_t inputevent;
func_t toggle;
func_t consolecommand;
func_t gethostcachecategory;
} mpfuncs;
jmp_buf mp_abort;
@ -2447,8 +2451,8 @@ void MP_Shutdown (void)
Z_Free(buffer);
}
*/
temp = mp_shutdown_function;
mp_shutdown_function = 0;
temp = mpfuncs.shutdown;
mpfuncs.shutdown = 0;
if (temp && !inmenuprogs)
PR_ExecuteProgram(menu_world.progs, temp);
@ -2666,17 +2670,18 @@ qboolean MP_Init (void)
EDICT_NUM_PB(menu_world.progs, 0)->ereftype = ER_ENTITY;
mp_init_function = PR_FindFunction(menu_world.progs, "m_init", PR_ANY);
mp_shutdown_function = PR_FindFunction(menu_world.progs, "m_shutdown", PR_ANY);
mp_draw_function = PR_FindFunction(menu_world.progs, "m_draw", PR_ANY);
mp_drawloading_function = PR_FindFunction(menu_world.progs, "m_drawloading", PR_ANY);
mp_inputevent_function = PR_FindFunction(menu_world.progs, "Menu_InputEvent", PR_ANY);
mp_keydown_function = PR_FindFunction(menu_world.progs, "m_keydown", PR_ANY);
mp_keyup_function = PR_FindFunction(menu_world.progs, "m_keyup", PR_ANY);
mp_toggle_function = PR_FindFunction(menu_world.progs, "m_toggle", PR_ANY);
mp_consolecommand_function = PR_FindFunction(menu_world.progs, "m_consolecommand", PR_ANY);
if (mp_init_function)
PR_ExecuteProgram(menu_world.progs, mp_init_function);
mpfuncs.init = PR_FindFunction(menu_world.progs, "m_init", PR_ANY);
mpfuncs.shutdown = PR_FindFunction(menu_world.progs, "m_shutdown", PR_ANY);
mpfuncs.draw = PR_FindFunction(menu_world.progs, "m_draw", PR_ANY);
mpfuncs.drawloading = PR_FindFunction(menu_world.progs, "m_drawloading", PR_ANY);
mpfuncs.inputevent = PR_FindFunction(menu_world.progs, "Menu_InputEvent", PR_ANY);
mpfuncs.keydown = PR_FindFunction(menu_world.progs, "m_keydown", PR_ANY);
mpfuncs.keyup = PR_FindFunction(menu_world.progs, "m_keyup", PR_ANY);
mpfuncs.toggle = PR_FindFunction(menu_world.progs, "m_toggle", PR_ANY);
mpfuncs.consolecommand = PR_FindFunction(menu_world.progs, "m_consolecommand", PR_ANY);
mpfuncs.gethostcachecategory = PR_FindFunction(menu_world.progs, "m_gethostcachecategory", PR_ANY);
if (mpfuncs.init)
PR_ExecuteProgram(menu_world.progs, mpfuncs.init);
inmenuprogs--;
EDICT_NUM_PB(menu_world.progs, 0)->readonly = true;
@ -2711,7 +2716,7 @@ qboolean MP_ConsoleCommand(const char *cmdtext)
void *pr_globals;
if (!menu_world.progs)
return false;
if (!mp_consolecommand_function)
if (!mpfuncs.consolecommand)
return false;
if (setjmp(mp_abort))
@ -2719,7 +2724,7 @@ qboolean MP_ConsoleCommand(const char *cmdtext)
inmenuprogs++;
pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
(((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(menu_world.progs, cmdtext));
PR_ExecuteProgram (menu_world.progs, mp_consolecommand_function);
PR_ExecuteProgram (menu_world.progs, mpfuncs.consolecommand);
inmenuprogs--;
return G_FLOAT(OFS_RETURN);
}
@ -2798,7 +2803,25 @@ void MP_RegisterCvarsAndCmds(void)
qboolean MP_UsingGamecodeLoadingScreen(void)
{
return menu_world.progs && mp_drawloading_function;
return menu_world.progs && mpfuncs.drawloading;
}
int MP_GetServerCategory(int index)
{
int category = 0;
if (menu_world.progs && mpfuncs.gethostcachecategory)
{
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
if (!setjmp(mp_abort))
{
inmenuprogs++;
G_FLOAT(OFS_PARM0) = index;
PR_ExecuteProgram(menu_world.progs, mpfuncs.gethostcachecategory);
category = G_FLOAT(OFS_RETURN);
inmenuprogs--;
}
}
return category;
}
void MP_Draw(void)
@ -2825,14 +2848,14 @@ void MP_Draw(void)
if (scr_drawloading||scr_disabled_for_loading)
{ //don't draw the menu if we're meant to be drawing a loading screen
//the menu should provide a special function if it wants to draw custom loading screens. this is for compat with old/dp/lazy/crappy menus.
if (mp_drawloading_function)
if (mpfuncs.drawloading)
{
((float *)pr_globals)[OFS_PARM1] = scr_disabled_for_loading;
PR_ExecuteProgram(menu_world.progs, mp_drawloading_function);
PR_ExecuteProgram(menu_world.progs, mpfuncs.drawloading);
}
}
else if (mp_draw_function)
PR_ExecuteProgram(menu_world.progs, mp_draw_function);
else if (mpfuncs.draw)
PR_ExecuteProgram(menu_world.progs, mpfuncs.draw);
inmenuprogs--;
}
@ -2869,24 +2892,24 @@ qboolean MP_Keydown(int key, int unicode, unsigned int devid)
*menu_world.g.time = menutime;
inmenuprogs++;
if (mp_inputevent_function)
if (mpfuncs.inputevent)
{
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = CSIE_KEYDOWN;
G_FLOAT(OFS_PARM1) = qcinput_scan = MP_TranslateFTEtoQCCodes(key);
G_FLOAT(OFS_PARM2) = qcinput_unicode = unicode;
G_FLOAT(OFS_PARM3) = devid;
PR_ExecuteProgram(menu_world.progs, mp_inputevent_function);
PR_ExecuteProgram(menu_world.progs, mpfuncs.inputevent);
result = G_FLOAT(OFS_RETURN);
qcinput_scan = 0;
qcinput_unicode = 0;
}
else if (mp_keydown_function)
else if (mpfuncs.keydown)
{
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key);
G_FLOAT(OFS_PARM1) = unicode;
PR_ExecuteProgram(menu_world.progs, mp_keydown_function);
PR_ExecuteProgram(menu_world.progs, mpfuncs.keydown);
result = true; //doesn't have a return value, so if the menu is set up for key events, all events are considered eaten.
}
inmenuprogs--;
@ -2912,21 +2935,21 @@ void MP_Keyup(int key, int unicode, unsigned int devid)
*menu_world.g.time = menutime;
inmenuprogs++;
if (mp_inputevent_function)
if (mpfuncs.inputevent)
{
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = CSIE_KEYUP;
G_FLOAT(OFS_PARM1) = MP_TranslateFTEtoQCCodes(key);
G_FLOAT(OFS_PARM2) = unicode;
G_FLOAT(OFS_PARM3) = devid;
PR_ExecuteProgram(menu_world.progs, mp_inputevent_function);
PR_ExecuteProgram(menu_world.progs, mpfuncs.inputevent);
}
else if (mp_keyup_function)
else if (mpfuncs.keyup)
{
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key);
G_FLOAT(OFS_PARM1) = unicode;
PR_ExecuteProgram(menu_world.progs, mp_keyup_function);
PR_ExecuteProgram(menu_world.progs, mpfuncs.keyup);
}
inmenuprogs--;
}
@ -2935,7 +2958,7 @@ qboolean MP_MousePosition(float xabs, float yabs, unsigned int devid)
{
void *pr_globals;
if (!menu_world.progs || !mp_inputevent_function)
if (!menu_world.progs || !mpfuncs.inputevent)
return false;
if (setjmp(mp_abort))
@ -2946,7 +2969,7 @@ qboolean MP_MousePosition(float xabs, float yabs, unsigned int devid)
G_FLOAT(OFS_PARM1) = (xabs * vid.width) / vid.pixelwidth;
G_FLOAT(OFS_PARM2) = (yabs * vid.height) / vid.pixelheight;
G_FLOAT(OFS_PARM3) = devid;
PR_ExecuteProgram (menu_world.progs, mp_inputevent_function);
PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent);
inmenuprogs--;
return G_FLOAT(OFS_RETURN);
}
@ -2954,7 +2977,7 @@ qboolean MP_MouseMove(float xdelta, float ydelta, unsigned int devid)
{
void *pr_globals;
if (!menu_world.progs || !mp_inputevent_function)
if (!menu_world.progs || !mpfuncs.inputevent)
return false;
if (setjmp(mp_abort))
@ -2965,7 +2988,7 @@ qboolean MP_MouseMove(float xdelta, float ydelta, unsigned int devid)
G_FLOAT(OFS_PARM1) = (xdelta * vid.width) / vid.pixelwidth;
G_FLOAT(OFS_PARM2) = (ydelta * vid.height) / vid.pixelheight;
G_FLOAT(OFS_PARM3) = devid;
PR_ExecuteProgram (menu_world.progs, mp_inputevent_function);
PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent);
inmenuprogs--;
return G_FLOAT(OFS_RETURN);
}
@ -2973,7 +2996,7 @@ qboolean MP_MouseMove(float xdelta, float ydelta, unsigned int devid)
qboolean MP_JoystickAxis(int axis, float value, unsigned int devid)
{
void *pr_globals;
if (!menu_world.progs || !mp_inputevent_function)
if (!menu_world.progs || !mpfuncs.inputevent)
return false;
if (setjmp(mp_abort))
return false;
@ -2983,7 +3006,7 @@ qboolean MP_JoystickAxis(int axis, float value, unsigned int devid)
G_FLOAT(OFS_PARM1) = axis;
G_FLOAT(OFS_PARM2) = value;
G_FLOAT(OFS_PARM3) = devid;
PR_ExecuteProgram (menu_world.progs, mp_inputevent_function);
PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent);
inmenuprogs--;
return G_FLOAT(OFS_RETURN);
}
@ -3008,11 +3031,11 @@ qboolean MP_Toggle(int mode)
*menu_world.g.time = menutime;
inmenuprogs++;
if (mp_toggle_function)
if (mpfuncs.toggle)
{
void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = mode;
PR_ExecuteProgram(menu_world.progs, mp_toggle_function);
PR_ExecuteProgram(menu_world.progs, mpfuncs.toggle);
}
inmenuprogs--;

View file

@ -166,9 +166,9 @@ extern "C" {
#include "net.h"
#include "protocol.h"
#include "cmd.h"
#include "wad.h"
#include "console.h"
#include "screen.h"
#include "wad.h"
#include "sbar.h"
#include "sound.h"
#include "merged.h"

View file

@ -422,6 +422,8 @@ enum imageflags
IF_MIPCAP = 1<<12,
IF_PREMULTIPLYALPHA = 1<<13, //rgb *= alpha
IF_WORLDTEX = 1<<18, //gl_picmip_world
IF_SPRITETEX = 1<<19, //gl_picmip_sprites
IF_NOSRGB = 1<<20, //ignore srgb when loading. this is guarenteed to be linear, for normalmaps etc.
IF_PALETTIZE = 1<<21,
@ -482,7 +484,7 @@ texid_tf R_LoadHiResTexture(const char *name, const char *subpath, unsigned int
texid_tf R_LoadBumpmapTexture(const char *name, const char *subpath);
void R_LoadNumberedLightTexture(struct dlight_s *dl, int cubetexnum);
qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean *hasalpha, const char *fname);
qbyte *ReadRawImageFile(qbyte *buf, int len, int *width, int *height, uploadfmt_t *format, qboolean force_rgba8, const char *fname);
extern texid_t particletexture;
extern texid_t particlecqtexture;
@ -577,13 +579,13 @@ void RQ_Shutdown(void);
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 *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *hasalpha, int asgrey);
qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_t *format, qboolean greyonly, uploadfmt_t forceformat);
qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height);
qbyte *ReadPNGFile(qbyte *buf, int length, int *width, int *height, const char *name);
qbyte *ReadPCXPalette(qbyte *buf, int len, qbyte *out);
void Image_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight);
void BoostGamma(qbyte *rgba, int width, int height);
void BoostGamma(qbyte *rgba, int width, int height, uploadfmt_t fmt);
void SaturateR8G8B8(qbyte *data, int size, float sat);
void AddOcranaLEDsIndexed (qbyte *image, int h, int w);

View file

@ -389,6 +389,9 @@ cvar_t gl_overbright_all = CVARF ("gl_overbright_all", "0",
CVAR_ARCHIVE);
cvar_t gl_picmip = CVARFD ("gl_picmip", "0", CVAR_ARCHIVE, "Reduce world/model texture sizes by some exponential factor.");
cvar_t gl_picmip2d = CVARFD ("gl_picmip2d", "0", CVAR_ARCHIVE, "Reduce hud/menu texture sizes by some exponential factor.");
cvar_t gl_picmip_world = CVARFD ("gl_picmip_world", "0", CVAR_ARCHIVE, "Effectively added to gl_picmip for the purposes of world textures.");
cvar_t gl_picmip_sprites = CVARFD ("gl_picmip_sprites", "0", CVAR_ARCHIVE, "Effectively added to gl_picmip for the purposes of sprite textures.");
cvar_t gl_picmip_other = CVARFD ("gl_picmip_other", "0", CVAR_ARCHIVE, "Effectively added to gl_picmip for the purposes of model textures.");
cvar_t gl_nohwblend = CVARD ("gl_nohwblend","1", "If 1, don't use hardware gamma ramps for transient effects that change each frame (does not affect long-term effects like holding quad or underwater tints).");
//cvar_t gl_schematics = CVARD ("gl_schematics", "0", "Gimmick rendering mode that draws the length of various world edges.");
cvar_t gl_skyboxdist = CVARD ("gl_skyboxdist", "0", "The distance of the skybox. If 0, the engine will determine it based upon the far clip plane distance."); //0 = guess.
@ -544,6 +547,9 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_picmip, GLRENDEREROPTIONS);
Cvar_Register (&gl_picmip2d, GLRENDEREROPTIONS);
Cvar_Register (&gl_picmip_world, GLRENDEREROPTIONS);
Cvar_Register (&gl_picmip_sprites, GLRENDEREROPTIONS);
Cvar_Register (&gl_picmip_other, GLRENDEREROPTIONS);
Cvar_Register (&r_shaderblobs, GLRENDEREROPTIONS);
Cvar_Register (&gl_compress, GLRENDEREROPTIONS);

View file

@ -98,8 +98,10 @@ typedef enum uploadfmt
PTI_BGRX8_SRGB, //no alpha channel
PTI_RGB8, //24bit packed format. generally not supported
PTI_BGR8, //24bit packed format. generally not supported
PTI_L8, //8bit format (legacy more than anything else). luminance gets flooded to all RGB channels. might be supported using swizzles.
PTI_L8A8, //16bit format (legacy more than anything else). L=luminance
PTI_L8, //8bit format. luminance gets flooded to all RGB channels. might be supported using swizzles.
PTI_L8A8, //16bit format. L=luminance. might be supported using swizzles.
PTI_L8_SRGB, //8bit format. luminance gets flooded to all RGB channels. might be supported using swizzles.
PTI_L8A8_SRGB, //16bit format. L=luminance. note: this cannot be implemented as a swizzle as there's no way to get srgb on red without it on green.
//small formats.
PTI_R8, //used for paletted data
PTI_RG8, //might be useful for normalmaps
@ -196,6 +198,9 @@ typedef enum uploadfmt
TF_H2_TRANS8_0, /*8bit data, 0 is transparent, not 255*/
TF_H2_T4A4, /*8bit data, weird packing*/
PTI_LLLX8, /*RGB data where the RGB values were all the same. we can convert to L8 to use less memory (common with shirt/pants/reflection)*/
PTI_LLLA8, /*RGBA data where the RGB values were all the same. we can convert to LA8 to use less memory (common with gloss)*/
/*this block requires an explicit (separate) palette*/
TF_8PAL24,
TF_8PAL32,
@ -223,7 +228,7 @@ typedef enum uploadfmt
TF_R8 = PTI_R8
//these are emulated formats. this 'case' value allows drivers to easily ignore them
#define PTI_EMULATED TF_INVALID:case TF_BGR24_FLIP:case TF_MIP4_R8:case TF_MIP4_SOLID8:case TF_MIP4_8PAL24:case TF_MIP4_8PAL24_T255:case TF_SOLID8:case TF_TRANS8:case TF_TRANS8_FULLBRIGHT:case TF_HEIGHT8:case TF_HEIGHT8PAL:case TF_H2_T7G1:case TF_H2_TRANS8_0:case TF_H2_T4A4:case TF_8PAL24:case TF_8PAL32
#define PTI_EMULATED TF_INVALID:case TF_BGR24_FLIP:case TF_MIP4_R8:case TF_MIP4_SOLID8:case TF_MIP4_8PAL24:case TF_MIP4_8PAL24_T255:case TF_SOLID8:case TF_TRANS8:case TF_TRANS8_FULLBRIGHT:case TF_HEIGHT8:case TF_HEIGHT8PAL:case TF_H2_T7G1:case TF_H2_TRANS8_0:case TF_H2_T4A4:case TF_8PAL24:case TF_8PAL32:case PTI_LLLX8:case PTI_LLLA8
} uploadfmt_t;
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, int bytestride, int width, int height, enum uploadfmt fmt);

View file

@ -920,7 +920,8 @@ static void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t forcedecode, siz
data = FS_LoadMallocFile(namebuffer, &filesize);
if (data)
{
Con_DPrintf("S_LoadSound: %s%s requested, but could only find %s\n", prefixes[pre], name, namebuffer);
static float throttletimer;
Con_ThrottlePrintf(&throttletimer, 1, "S_LoadSound: %s%s requested, but could only find %s\n", prefixes[pre], name, namebuffer);
break;
}
}

View file

@ -531,6 +531,9 @@ qboolean QDECL S_LoadOVSound (sfx_t *s, qbyte *data, size_t datalen, int sndspee
s->decoder.decodedata(s, NULL, 0, 100);
if (p_ov_time_total(&buffer->vf, -1) < 5) //short sounds might as well remain cached.
buffer->nopurge = true;
return true;
}

View file

@ -371,7 +371,7 @@ void W_ApplyGamma (qbyte *data, int len, int skipalpha)
}
}
*/
qbyte *W_ConvertWAD3Texture(miptex_t *tex, size_t lumpsize, int *width, int *height, qboolean *usesalpha) //returns rgba
qbyte *W_ConvertWAD3Texture(miptex_t *tex, size_t lumpsize, int *width, int *height, uploadfmt_t *format) //returns rgba
{
qbyte *in, *data, *out, *pal;
int d, p;
@ -447,13 +447,13 @@ qbyte *W_ConvertWAD3Texture(miptex_t *tex, size_t lumpsize, int *width, int *hei
}
out += 4;
}
*format = alpha?PTI_RGBA8:PTI_RGBX8;
if (!vid_hardwaregamma.value)
BoostGamma(data, tex->width, tex->height);
*usesalpha = !!alpha;
BoostGamma(data, tex->width, tex->height, *format);
return data;
}
qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalpha)//returns rgba
qbyte *W_GetTexture(const char *name, int *width, int *height, uploadfmt_t *format)//returns rgba
{
char texname[17];
int i, j;
@ -482,7 +482,7 @@ qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalp
*width = 128;
*height = 128;
*usesalpha = false;
*format = PTI_RGBX8;
data = BZ_Malloc(128 * 128 * 4);
for (i = 0; i < 128 * 128; i++)
@ -500,7 +500,7 @@ qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalp
{
*width = p->width;
*height = p->height;
*usesalpha = false;
*format = PTI_RGBX8;
data = BZ_Malloc(p->width * p->height * 4);
for (i = 0; i < p->width * p->height; i++)
@ -514,7 +514,7 @@ qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalp
qbyte *pal = p->data+p->width*p->height+4;
*width = p->width;
*height = p->height;
*usesalpha = true;
*format = PTI_RGBA8;
data = BZ_Malloc(p->width * p->height * 4);
for (i = 0; i < p->width * p->height; i++)
@ -552,7 +552,7 @@ qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalp
for (j = 0;j < MIPLEVELS;j++)
tex->offsets[j] = LittleLong(tex->offsets[j]);
data = W_ConvertWAD3Texture(tex, texwadlump[i].size, width, height, usesalpha);
data = W_ConvertWAD3Texture(tex, texwadlump[i].size, width, height, format);
BZ_Free(tex);
return data;
}

View file

@ -102,8 +102,8 @@ void SwapPic (qpic_t *pic);
struct model_s;
void Mod_ParseWadsFromEntityLump(char *data);
qbyte *W_ConvertWAD3Texture(miptex_t *tex, size_t lumpsize, int *width, int *height, qboolean *usesalpha);
qbyte *W_ConvertWAD3Texture(miptex_t *tex, size_t lumpsize, int *width, int *height, uploadfmt_t *format);
void Mod_ParseInfoFromEntityLump(struct model_s *wmodel);
qboolean Wad_NextDownload (void);
qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalpha);
qbyte *W_GetTexture(const char *name, int *width, int *height, uploadfmt_t *format);
miptex_t *W_GetMipTex(const char *name);

View file

@ -1491,7 +1491,7 @@ const char *Cmd_ExpandCvar(char *cvarterm, int maxaccesslevel, int *newaccesslev
pl = 2;
quotetype = 1;
}
else if (fixup-cvarterm > 2 && !strncmp(fixup-5, " asis", 5))
else if (fixup-cvarterm > 5 && !strncmp(fixup-5, " asis", 5))
{ //no escaping...
pl = 5;
quotetype = 0;

View file

@ -1429,12 +1429,14 @@ static void Alias_BuildGPUWeights(model_t *mod, galiasinfo_t *inf, size_t num_tr
inf->ofs_skel_xyz[v][0] += t->org[0] * matrix[0] + t->org[1] * matrix[1] + t->org[2] * matrix[ 2] + t->org[3] * matrix[ 3];
inf->ofs_skel_xyz[v][1] += t->org[0] * matrix[4] + t->org[1] * matrix[5] + t->org[2] * matrix[ 6] + t->org[3] * matrix[ 7];
inf->ofs_skel_xyz[v][2] += t->org[0] * matrix[8] + t->org[1] * matrix[9] + t->org[2] * matrix[10] + t->org[3] * matrix[11];
#ifndef SERVERONLY
if (!calcnorms)
{
inf->ofs_skel_norm[v][0] += t->org[0] * matrix[0] + t->org[1] * matrix[1] + t->org[2] * matrix[ 2];
inf->ofs_skel_norm[v][1] += t->org[0] * matrix[4] + t->org[1] * matrix[5] + t->org[2] * matrix[ 6];
inf->ofs_skel_norm[v][2] += t->org[0] * matrix[8] + t->org[1] * matrix[9] + t->org[2] * matrix[10];
inf->ofs_skel_norm[v][0] += t->normal[0] * matrix[0] + t->normal[1] * matrix[1] + t->normal[2] * matrix[ 2];
inf->ofs_skel_norm[v][1] += t->normal[0] * matrix[4] + t->normal[1] * matrix[5] + t->normal[2] * matrix[ 6];
inf->ofs_skel_norm[v][2] += t->normal[0] * matrix[8] + t->normal[1] * matrix[9] + t->normal[2] * matrix[10];
}
#endif
//we sorted them so we're guarenteed to see the highest influences first.
for (j = 0; j < 4; j++)
@ -3026,7 +3028,7 @@ void Mod_LoadAliasShaders(model_t *mod)
R_BuildLegacyTexnums(f->shader, basename, alttexpath, loadflags, imageflags, skintranstype, s->skinwidth, s->skinheight, mipdata, host_basepal);
}
else
R_BuildDefaultTexnums(&f->texnums, f->shader);
R_BuildDefaultTexnums(&f->texnums, f->shader, 0);
}
}
Mod_WipeSkin(skinid, false);

View file

@ -115,7 +115,7 @@ cvar_t com_parseutf8 = CVARD("com_parseutf8", "1", "Interpret console messages/p
cvar_t com_parseezquake = CVARD("com_parseezquake", "0", "Treat chevron chars from configs as a per-character flag. You should use this only for compat with nquake's configs.");
#endif
cvar_t com_highlightcolor = CVARD("com_highlightcolor", STRINGIFY(COLOR_RED), "ANSI colour to be used for highlighted text, used when com_parseutf8 is active.");
cvar_t com_nogamedirnativecode = CVARFD("com_nogamedirnativecode", "1", CVAR_NOTFROMSERVER, FULLENGINENAME" blocks all downloads of files with a .dll or .so extension, however other engines (eg: ezquake and fodquake) do not - this omission can be used to trigger delayed eremote exploits in any engine (including "DISTRIBUTION") which is later run from the same gamedir.\nQuake2, Quake3(when debugging), and KTX typically run native gamecode from within gamedirs, so if you wish to run any of these games you will need to ensure this cvar is changed to 0, as well as ensure that you don't run unsafe clients.\n");
cvar_t com_nogamedirnativecode = CVARFD("com_nogamedirnativecode", "1", CVAR_NOTFROMSERVER, FULLENGINENAME" blocks all downloads of files with a .dll or .so extension, however other engines (eg: ezquake and fodquake) do not - this omission can be used to trigger delayed eremote exploits in any engine (including "DISTRIBUTION") which is later run from the same gamedir.\nQuake2, Quake3(when debugging), and KTX typically run native gamecode from within gamedirs, so if you wish to run any of these games you will need to ensure this cvar is changed to 0, as well as ensure that you don't run unsafe clients.");
cvar_t sys_platform = CVAR("sys_platform", PLATFORM);
cvar_t pm_downloads_url = CVARFD("pm_downloads_url", NULL, CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "The URL of a package updates list."); //read from the default.fmf
cvar_t pm_autoupdate = CVARFD("pm_autoupdate", "1", CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "Controls autoupdates, can only be changed via the downloads menu.\n0: off.\n1: enabled (stable only).\n2: enabled (unstable).\nNote that autoupdate will still prompt the user to actually apply the changes."); //read from the package list only.

View file

@ -141,7 +141,7 @@ typedef struct console_s
char prompt[128];
char icon[MAX_QPATH]; //should really dynamically allocate this stuff.
char backimage[MAX_QPATH];
shader_t *backshader;
struct shader_s *backshader;
float wnd_x;
float wnd_y;
float wnd_w;
@ -171,7 +171,7 @@ typedef struct console_s
//WARNING: note that links do NOT represent any sort of security. text can be inserted from anywhere. Its fine to use such things for context, but don't treat them as sescure.
int (*linebuffered) (struct console_s *con, char *line); //if present, called on enter, causes the standard console input to appear. return 2 to not save the line in history.
qboolean (*redirect) (struct console_s *con, unsigned int unicode, int key); //if present, called every character.
qboolean (*mouseover)(struct console_s *con, char **out_tiptext, shader_t **out_shader);
qboolean (*mouseover)(struct console_s *con, char **out_tiptext, struct shader_s **out_shader);
qboolean (*close) (struct console_s *con, qboolean force);
void *userdata; //user context
conline_t *userline; //editor cursor line

View file

@ -197,6 +197,8 @@ void *ZF_Malloc(int size)
void *ret = NULL;
if (!posix_memalign(&ret, max(sizeof(float)*4, sizeof(void*)), size))
memset(ret, 0, size);
else
ret = NULL;
return ret;
#else
return calloc(size, 1);

View file

@ -296,7 +296,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
skintext = COM_ParseToken(skintext, NULL);
Q_strncpyz(shadername, com_token, sizeof(shadername));
skin->mappings[skin->nummappings].shader = R_RegisterSkin(shadername, skin->skinname);
R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader);
R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader, 0);
skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures;
skin->nummappings++;
}
@ -317,7 +317,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
skintext = COM_ParseToken(skintext, NULL);
Q_strncpyz(shadername, com_token, sizeof(shadername));
skin->mappings[skin->nummappings].shader = R_RegisterSkin(shadername, skin->skinname);
R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader);
R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader, 0);
skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures;
//parse the lines, and start to load the various shaders.
@ -396,7 +396,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
skintext = COM_ParseToken(skintext+1, NULL);
Q_strncpyz(shadername, com_token, sizeof(shadername));
skin->mappings[skin->nummappings].shader = R_RegisterCustom (shadername, 0, Shader_DefaultSkin, NULL);
R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader);
R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader, 0);
skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures;
skin->nummappings++;
}
@ -656,7 +656,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
if (s)
{
if (!TEXVALID(s->defaulttextures->base))
R_BuildDefaultTexnums(NULL, s);
R_BuildDefaultTexnums(NULL, s, 0);
return s;
}
}
@ -1330,7 +1330,7 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
return e->light_known-1;
e->light_dir[0] = 0; e->light_dir[1] = 1; e->light_dir[2] = 0;
if (clmodel->engineflags & MDLF_FLAME || r_fullbright.ival)
if ((clmodel->engineflags & MDLF_FLAME) || r_fullbright.ival)
{
e->light_avg[0] = e->light_avg[1] = e->light_avg[2] = 1;
e->light_range[0] = e->light_range[1] = e->light_range[2] = 0;

View file

@ -2412,18 +2412,28 @@ static void deformgen(const deformv_t *deformv, int cnt, vecV_t *src, vecV_t *ds
for (j = 0; j+3 < cnt; j+=4, src+=4, dst+=4)
{
vec3_t mid, d;
float radius;
vec2_t mid2;
float radius, s,t;
vec2_t *fte_restrict st = &mesh->st_array[j];
mid[0] = 0.25*(src[0][0] + src[1][0] + src[2][0] + src[3][0]);
mid[1] = 0.25*(src[0][1] + src[1][1] + src[2][1] + src[3][1]);
mid[2] = 0.25*(src[0][2] + src[1][2] + src[2][2] + src[3][2]);
VectorSubtract(src[0], mid, d);
radius = 2*VectorLength(d);
radius = VectorLength(d);
mid2[0] = 0.25*(st[0][0] + st[1][0] + st[2][0] + st[3][0]);
mid2[1] = 0.25*(st[0][1] + st[1][1] + st[2][1] + st[3][1]);
for (k = 0; k < 4; k++)
{
dst[k][0] = mid[0] + radius*((mesh->st_array[j+k][0]-0.5)*r_refdef.m_view[0+0]-(mesh->st_array[j+k][1]-0.5)*r_refdef.m_view[0+1]);
dst[k][1] = mid[1] + radius*((mesh->st_array[j+k][0]-0.5)*r_refdef.m_view[4+0]-(mesh->st_array[j+k][1]-0.5)*r_refdef.m_view[4+1]);
dst[k][2] = mid[2] + radius*((mesh->st_array[j+k][0]-0.5)*r_refdef.m_view[8+0]-(mesh->st_array[j+k][1]-0.5)*r_refdef.m_view[8+1]);
//q3 fully regenerates verts. we don't because that destroys ST coords.
//even so, if the ST coords are non-centered for some reason then we still need to get the right values as if they were.
//hence the mid2.
s = (st[k][0] > mid2[0])?1:-1;
t = (st[k][1] > mid2[1])?1:-1;
dst[k][0] = mid[0] + radius*(s*shaderstate.modelviewmatrix[0+0]-t*shaderstate.modelviewmatrix[0+1]);
dst[k][1] = mid[1] + radius*(s*shaderstate.modelviewmatrix[4+0]-t*shaderstate.modelviewmatrix[4+1]);
dst[k][2] = mid[2] + radius*(s*shaderstate.modelviewmatrix[8+0]-t*shaderstate.modelviewmatrix[8+1]);
}
}
break;
@ -5295,7 +5305,7 @@ static qboolean GLBE_GenerateBatchTextures(batch_t *batch, shader_t *bs)
qglClearColor(0, 0, 0, 1);
qglClear(GL_COLOR_BUFFER_BIT);
// r_refdef.waterheight = DotProduct(batch->mesh[0]->xyz_array[0], batch->mesh[0]->normals_array[0]);
// r_refdef.waterheight = DotProduct(batch->mesh[0]->xyz_array[0], batch->mesh[0]->normals_array[0]);
r_refdef.recurse+=1; //paranoid, should stop potential infinite loops
GLBE_SubmitMeshes(cl.worldmodel->batches, SHADER_SORT_RIPPLE, SHADER_SORT_RIPPLE);
@ -5369,8 +5379,17 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
}
if ((bs->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT | SHADER_HASRIPPLEMAP)) && shaderstate.mode != BEM_WIREFRAME)
{
if (!GLBE_GenerateBatchTextures(batch, bs))
continue;
if ((bs->flags&SHADER_HASPORTAL) && shaderstate.mode != BEM_DEPTHONLY && gl_config.arb_depth_clamp)
{ //this little bit of code is meant to prevent issues when the near clip plane intersects the portal surface, allowing us to be that little bit closer to the portal.
qglEnable(GL_DEPTH_CLAMP);
GLBE_SubmitBatch(batch);
qglDisable(GL_DEPTH_CLAMP);
continue;
}
}
GLBE_SubmitBatch(batch);
}

View file

@ -1301,7 +1301,7 @@ qboolean Font_LoadHorizontalFont(struct font_s *f, int fheight, const char *font
qofs_t rawsize;
qbyte *rgbadata = NULL;
int width=0,height=0;
qboolean hasalpha=true;
uploadfmt_t format;
if (fheight < 1)
fheight = 1;
@ -1322,7 +1322,7 @@ qboolean Font_LoadHorizontalFont(struct font_s *f, int fheight, const char *font
rawdata = FS_MallocFile(fontfilename, FS_GAME, &rawsize);
if (rawdata)
rgbadata = Read32BitImageFile(rawdata, rawsize, &width, &height, &hasalpha, fontfilename);
rgbadata = ReadRawImageFile(rawdata, rawsize, &width, &height, &format, true, fontfilename);
FS_FreeFile(rawdata);
if (rgbadata)
@ -1678,9 +1678,9 @@ static texid_t Font_LoadFallbackConchars(void)
int width, height;
unsigned int i;
qbyte *lump;
qboolean hasalpha;
lump = ReadTargaFile(default_conchar, sizeof(default_conchar), &width, &height, &hasalpha, false);
if (!lump)
uploadfmt_t format;
lump = ReadTargaFile(default_conchar, sizeof(default_conchar), &width, &height, &format, false, PTI_INVALID);
if (!lump || format != PTI_RGBA8)
Sys_Error("Corrupt internal drawchars");
/*convert greyscale to alpha*/
for (i = 0; i < width*height; i++)

View file

@ -143,7 +143,7 @@ static void QDECL Terr_LoadSectionTextures(hmsection_t *s)
for (w = s->water; w; w = w->next)
{
w->shader = R_RegisterCustom (w->shadername, SUF_NONE, Shader_DefaultWaterShader, NULL);
R_BuildDefaultTexnums(NULL, w->shader); //this might get expensive. hideously so.
R_BuildDefaultTexnums(NULL, w->shader, IF_WORLDTEX); //this might get expensive. hideously so.
}
#endif
}
@ -5775,7 +5775,7 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e)
R_BuildLegacyTexnums(bt->shader, tx->name, NULL, mapflags, 0, TF_MIP4_SOLID8, tx->width, tx->height, mips, NULL);
}
else
R_BuildDefaultTexnums(NULL, bt->shader);
R_BuildDefaultTexnums(NULL, bt->shader, IF_WORLDTEX);
if (tx)
{

View file

@ -1297,7 +1297,7 @@ static void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
if (!s->shader)
{
s->shader = R_RegisterSkin(s->name, rent->model->name);
R_BuildDefaultTexnums(&s->defaulttex, s->shader);
R_BuildDefaultTexnums(&s->defaulttex, s->shader, 0);
}
b->skin = NULL;
b->shader = s->shader;

View file

@ -1230,19 +1230,25 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
// set necessary engine flags for loading purposes
if (!strcmp(mod->publicname, "progs/player.mdl"))
mod->engineflags |= MDLF_PLAYER | MDLF_DOCRC;
else if (!strcmp(mod->publicname, "progs/flame.mdl") ||
!strcmp(mod->publicname, "progs/flame2.mdl") ||
!strcmp(mod->publicname, "models/flame1.mdl") || //hexen2 small standing flame
!strcmp(mod->publicname, "models/flame2.mdl") || //hexen2 large standing flame
!strcmp(mod->publicname, "models/cflmtrch.mdl")) //hexen2 wall torch
else if (!strcmp(mod->publicname, "progs/flame.mdl")
|| !strcmp(mod->publicname, "progs/flame2.mdl")
#ifdef HEXEN2
|| !strcmp(mod->publicname, "models/flame1.mdl") //hexen2 small standing flame
|| !strcmp(mod->publicname, "models/flame2.mdl") //hexen2 large standing flame
|| !strcmp(mod->publicname, "models/cflmtrch.mdl") //hexen2 wall torch
#endif
)
mod->engineflags |= MDLF_FLAME;
else if (!strcmp(mod->publicname, "progs/bolt.mdl") ||
!strcmp(mod->publicname, "progs/bolt2.mdl") ||
!strcmp(mod->publicname, "progs/bolt3.mdl") ||
!strcmp(mod->publicname, "progs/beam.mdl") ||
!strcmp(mod->publicname, "models/stsunsf2.mdl") ||
!strcmp(mod->publicname, "models/stsunsf1.mdl") ||
!strcmp(mod->publicname, "models/stice.mdl"))
else if (!strcmp(mod->publicname, "progs/bolt.mdl")
|| !strcmp(mod->publicname, "progs/bolt2.mdl")
|| !strcmp(mod->publicname, "progs/bolt3.mdl")
|| !strcmp(mod->publicname, "progs/beam.mdl")
#ifdef HEXEN2
|| !strcmp(mod->publicname, "models/stsunsf2.mdl")
|| !strcmp(mod->publicname, "models/stsunsf1.mdl")
|| !strcmp(mod->publicname, "models/stice.mdl")
#endif
)
mod->engineflags |= MDLF_BOLT;
else if (!strcmp(mod->publicname, "progs/backpack.mdl"))
mod->engineflags |= MDLF_NOTREPLACEMENTS;
@ -4922,7 +4928,7 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
for (a = 0; a < mod->numfogs; a++)
{
mod->fogs[a].shader = R_RegisterShader_Lightmap(mod->fogs[a].shadername);
R_BuildDefaultTexnums(NULL, mod->fogs[a].shader);
R_BuildDefaultTexnums(NULL, mod->fogs[a].shader, IF_WORLDTEX);
if (!mod->fogs[a].shader->fog_dist)
{
//invalid fog shader, don't use.
@ -4939,10 +4945,10 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
for(a = 0; a < mod->numtexinfo; a++)
{
mod->textures[a]->shader = R_RegisterShader_Lightmap(va("%s#BUMPMODELSPACE", mod->textures[a]->name));
R_BuildDefaultTexnums(NULL, mod->textures[a]->shader);
R_BuildDefaultTexnums(NULL, mod->textures[a]->shader, IF_WORLDTEX);
mod->textures[a+mod->numtexinfo]->shader = R_RegisterShader_Vertex (mod->textures[a+mod->numtexinfo]->name);
R_BuildDefaultTexnums(NULL, mod->textures[a+mod->numtexinfo]->shader);
R_BuildDefaultTexnums(NULL, mod->textures[a+mod->numtexinfo]->shader, IF_WORLDTEX);
}
}
else
@ -4950,10 +4956,10 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
for(a = 0; a < mod->numtexinfo; a++)
{
mod->textures[a]->shader = R_RegisterShader_Lightmap(mod->textures[a]->name);
R_BuildDefaultTexnums(NULL, mod->textures[a]->shader);
R_BuildDefaultTexnums(NULL, mod->textures[a]->shader, IF_WORLDTEX);
mod->textures[a+mod->numtexinfo]->shader = R_RegisterShader_Vertex (mod->textures[a+mod->numtexinfo]->name);
R_BuildDefaultTexnums(NULL, mod->textures[a+mod->numtexinfo]->shader);
R_BuildDefaultTexnums(NULL, mod->textures[a+mod->numtexinfo]->shader, IF_WORLDTEX);
}
}
mod->textures[2*mod->numtexinfo]->shader = R_RegisterShader_Flare("noshader");
@ -4977,7 +4983,7 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
// maps |= SHADER_HASNORMALMAP;
if (gl_specular.ival)
maps |= SHADER_HASGLOSS;
R_BuildLegacyTexnums(mod->textures[a]->shader, mod->textures[a]->name, loadname, maps, 0, TF_MIP4_8PAL24, mod->textures[a]->width, mod->textures[a]->height, mod->textures[a]->mips, mod->textures[a]->palette);
R_BuildLegacyTexnums(mod->textures[a]->shader, mod->textures[a]->name, loadname, maps, IF_WORLDTEX, TF_MIP4_8PAL24, mod->textures[a]->width, mod->textures[a]->height, mod->textures[a]->mips, mod->textures[a]->palette);
BZ_Free(mod->textures[a]->mips[0]);
}
}

View file

@ -5387,7 +5387,7 @@ void Shader_UpdateRegistration (void)
}
*/
void Shader_DefaultSkin(const char *shortname, shader_t *s, const void *args);
void QDECL R_BuildDefaultTexnums(texnums_t *src, shader_t *shader)
void QDECL R_BuildDefaultTexnums(texnums_t *src, shader_t *shader, unsigned int imageflags)
{
char *h;
char imagename[MAX_QPATH];
@ -5395,7 +5395,6 @@ void QDECL R_BuildDefaultTexnums(texnums_t *src, shader_t *shader)
char *subpath = NULL;
texnums_t *tex;
unsigned int a, aframes;
unsigned int imageflags = 0;
strcpy(imagename, shader->name);
h = strchr(imagename, '#');
if (h)
@ -5461,18 +5460,18 @@ void QDECL R_BuildDefaultTexnums(texnums_t *src, shader_t *shader)
{
/*dlights/realtime lighting needs some stuff*/
if (!TEXVALID(tex->base) && *tex->mapname)// && (shader->flags & SHADER_HASDIFFUSE))
tex->base = R_LoadHiResTexture(tex->mapname, NULL, 0);
tex->base = R_LoadHiResTexture(tex->mapname, NULL, imageflags);
if (!TEXVALID(tex->base))
tex->base = R_LoadHiResTexture(imagename, subpath, (*imagename=='{')?0:IF_NOALPHA);
tex->base = R_LoadHiResTexture(imagename, subpath, (*imagename=='{')?0:IF_NOALPHA|imageflags);
}
if ((shader->flags & SHADER_HASPALETTED) && !TEXVALID(tex->paletted))
{
if (!TEXVALID(tex->paletted) && *tex->mapname)
tex->paletted = R_LoadHiResTexture(va("%s", tex->mapname), NULL, 0|IF_NEAREST|IF_PALETTIZE);
tex->paletted = R_LoadHiResTexture(va("%s", tex->mapname), NULL, 0|IF_NEAREST|IF_PALETTIZE|imageflags);
if (!TEXVALID(tex->paletted))
tex->paletted = R_LoadHiResTexture(va("%s", imagename), subpath, ((*imagename=='{')?0:IF_NOALPHA)|IF_NEAREST|IF_PALETTIZE);
tex->paletted = R_LoadHiResTexture(va("%s", imagename), subpath, ((*imagename=='{')?0:IF_NOALPHA)|IF_NEAREST|IF_PALETTIZE|imageflags);
}
imageflags |= IF_LOWPRIORITY;
@ -5484,9 +5483,9 @@ void QDECL R_BuildDefaultTexnums(texnums_t *src, shader_t *shader)
if (r_loadbumpmapping || (shader->flags & SHADER_HASNORMALMAP))
{
if (!TEXVALID(tex->bump) && *mapname && (shader->flags & SHADER_HASNORMALMAP))
tex->bump = R_LoadHiResTexture(va("%s_norm", mapname), NULL, imageflags|IF_TRYBUMP|IF_NOSRGB);
tex->bump = R_LoadHiResTexture(va("%s_norm", mapname), NULL, imageflags|IF_TRYBUMP|IF_NOSRGB|imageflags);
if (!TEXVALID(tex->bump))
tex->bump = R_LoadHiResTexture(va("%s_norm", imagename), subpath, imageflags|IF_TRYBUMP|IF_NOSRGB);
tex->bump = R_LoadHiResTexture(va("%s_norm", imagename), subpath, imageflags|IF_TRYBUMP|IF_NOSRGB|imageflags);
}
}

View file

@ -2727,7 +2727,7 @@ static void *X11VID_CreateCursor(const char *filename, float hotx, float hoty, f
{
void *r;
qbyte *rgbadata;
qboolean hasalpha;
uploadfmt_t format;
void *filedata;
int filelen, width, height;
if (!filename || !*filename)
@ -2736,13 +2736,12 @@ static void *X11VID_CreateCursor(const char *filename, float hotx, float hoty, f
if (!filedata)
return NULL;
hasalpha = false;
rgbadata = Read32BitImageFile(filedata, filelen, &width, &height, &hasalpha, filename);
rgbadata = ReadRawImageFile(filedata, filelen, &width, &height, &format, true, filename);
FS_FreeFile(filedata);
if (!rgbadata)
return NULL;
if (!hasalpha && !strchr(filename, ':'))
if (format==PTI_RGBX8 && !strchr(filename, ':'))
{ //people seem to insist on using jpgs, which don't have alpha.
//so screw over the alpha channel if needed.
unsigned int alpha_width, alpha_height, p;
@ -2758,7 +2757,7 @@ static void *X11VID_CreateCursor(const char *filename, float hotx, float hoty, f
alphsize = FS_LoadFile(filename, (void**)&alph);
if (alph)
{
if ((alphadata = Read32BitImageFile(alph, alphsize, &alpha_width, &alpha_height, &hasalpha, aname)))
if ((alphadata = ReadRawImageFile(alph, alphsize, &alpha_width, &alpha_height, &format, true, aname)))
{
if (alpha_width == width && alpha_height == height)
for (p = 0; p < alpha_width*alpha_height; p++)
@ -2801,7 +2800,10 @@ static void X11VID_DestroyCursor(void *qcursor)
}
static qboolean X11VID_SetCursor(void *qcursor)
{
vid_newcursor = *(Cursor*)qcursor;
if (qcursor)
vid_newcursor = *(Cursor*)qcursor;
else
vid_newcursor = None;
if (vid_dpy)
UpdateGrabs();
@ -2988,8 +2990,8 @@ void X_StoreIcon(Window wnd)
{
int imagewidth, imageheight;
int *iconblob;
qboolean hasalpha;
qbyte *imagedata = Read32BitImageFile(filedata, filesize, &imagewidth, &imageheight, &hasalpha, "icon.png");
uploadfmt_t format;
qbyte *imagedata = ReadRawImageFile(filedata, filesize, &imagewidth, &imageheight, &format, true, "icon.png");
Z_Free(filedata);
iconblob = BZ_Malloc(sizeof(int)*(2+imagewidth*imageheight));

View file

@ -78,7 +78,7 @@ void R_SetSky(const char *sky)
if (tex.reflectcube->width)
{
forcedsky = R_RegisterShader(va("skybox_%s", sky), 0, "{\nsort sky\nprogram defaultskybox\n{\nmap \"$cube:$reflectcube\"\ntcgen skybox\n}\nsurfaceparm nodlight\nsurfaceparm sky\n}");
R_BuildDefaultTexnums(&tex, forcedsky);
R_BuildDefaultTexnums(&tex, forcedsky, IF_WORLDTEX);
return;
}
}
@ -918,8 +918,8 @@ void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int
if (filedata)
{
int imagewidth, imageheight;
qboolean hasalpha; //fixme, if this is false, is it worth all this code?
unsigned int *imagedata = (unsigned int*)Read32BitImageFile(filedata, filesize, &imagewidth, &imageheight, &hasalpha, name);
uploadfmt_t format; //fixme, if this has no alpha, is it worth all this code?
unsigned int *imagedata = (unsigned int*)ReadRawImageFile(filedata, filesize, &imagewidth, &imageheight, &format, true, name);
Z_Free(filedata);
if (imagedata && !(imagewidth&1))

File diff suppressed because it is too large Load diff

View file

@ -688,7 +688,7 @@ shader_t *R_RegisterShader_Flare (const char *name);
shader_t *QDECL R_RegisterSkin (const char *shadername, const char *modname);
shader_t *R_RegisterCustom (const char *name, unsigned int usageflags, shader_gen_t *defaultgen, const void *args);
//once loaded, most shaders should have one of the following two calls used upon it
void QDECL R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader);
void QDECL R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader, unsigned int imageflags);
void QDECL R_BuildLegacyTexnums(shader_t *shader, const char *fallbackname, const char *subpath, unsigned int loadflags, unsigned int imageflags, uploadfmt_t basefmt, size_t width, size_t height, qbyte *mipdata[4], qbyte *palette);
void R_RemapShader(const char *sourcename, const char *destname, float timeoffset);

View file

@ -5567,66 +5567,66 @@ static void QCBUILTIN PF_qtBroadcast_WriteEntity (pubprogfuncs_t *prinst, struct
//======================================================
//copes with any qw point entities.
void SV_point_tempentity (vec3_t o, int qwtype, int count) //count (usually 1) is available for some tent types.
void SV_point_tempentity (vec3_t o, int type, int count) //count (usually 1) is available for some tent types.
{
int split=0;
int qwtype[2] = {type,type};
#ifdef NQPROT
int nqtype = qwtype;
int nqtype[2] = {type,type};
#endif
int i;
#ifdef SERVER_DEMO_PLAYBACK
if (sv.demofile)
return;
#endif
//this is for lamers with old (or unsupported) clients
MSG_WriteByte (&sv.multicast, svc_temp_entity);
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, svc_temp_entity);
#endif
switch(qwtype)
switch(type) //uses the QW types...
{
case TE_BULLET:
MSG_WriteByte (&sv.multicast, TE_SPIKE);
qwtype = TE_BULLET;
qwtype[1] = TE_SPIKE;
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, TE_SPIKE);
nqtype = TE_BULLET;
qwtype[1] = qwtype[0] = TE_SPIKE;
#endif
split = PEXT_TE_BULLET;
break;
case TEQW_SUPERBULLET:
MSG_WriteByte (&sv.multicast, TE_SUPERSPIKE);
qwtype = TEQW_SUPERBULLET;
qwtype[1] = TE_SUPERSPIKE;
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, TE_SUPERSPIKE);
nqtype = TE_SUPERSPIKE;
qwtype[1] = qwtype[0] = TE_SUPERSPIKE;
#endif
split = PEXT_TE_BULLET;
break;
case TEQW_QWBLOOD:
case TEQW_QWGUNSHOT:
MSG_WriteByte (&sv.multicast, qwtype);
MSG_WriteByte (&sv.multicast, count);
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, nqtype); //nq doesn't have a count.
nqtype[0] = nqtype[1] = 73|256;
#endif
break;
case TEQW_LIGHTNINGBLOOD:
#ifdef NQPROT
nqtype[0] = nqtype[1] = 225|256;
#endif
break;
case TEQW_QWGUNSHOT:
#ifdef NQPROT
nqtype[0] = TENQ_QWGUNSHOT;
nqtype[1] = TENQ_NQGUNSHOT;
split = PEXT_TE_BULLET;
#endif
break;
case TEQW_QWEXPLOSION:
MSG_WriteByte (&sv.multicast, TEQW_QWEXPLOSION);
qwtype = -1;
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, TENQ_NQEXPLOSION);
nqtype = TENQ_QWEXPLOSION;
nqtype[0] = TENQ_QWEXPLOSION;
nqtype[1] = TENQ_NQEXPLOSION;
#endif
split = PEXT_TE_BULLET;
break;
case TEQW_NQEXPLOSION:
MSG_WriteByte (&sv.multicast, TEQW_QWEXPLOSION);
qwtype = TEQW_NQEXPLOSION;
qwtype[0] = TEQW_NQEXPLOSION;
qwtype[1] = TEQW_QWEXPLOSION;
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, TENQ_NQEXPLOSION);
nqtype = -1;
nqtype[0] = TENQ_NQEXPLOSION;
nqtype[1] = TENQ_NQEXPLOSION;
#endif
split = PEXT_TE_BULLET;
break;
@ -5636,71 +5636,72 @@ void SV_point_tempentity (vec3_t o, int qwtype, int count) //count (usually 1) i
SV_Error("SV_point_tempentity - type is a beam\n");
break;
default:
MSG_WriteByte (&sv.multicast, qwtype);
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, nqtype);
#endif
break;
}
MSG_WriteCoord (&sv.multicast, o[0]);
MSG_WriteCoord (&sv.multicast, o[1]);
MSG_WriteCoord (&sv.multicast, o[2]);
#ifdef NQPROT
MSG_WriteCoord (&sv.nqmulticast, o[0]);
MSG_WriteCoord (&sv.nqmulticast, o[1]);
MSG_WriteCoord (&sv.nqmulticast, o[2]);
#endif
if (qwtype == TEQW_QWBLOOD || qwtype == TEQW_LIGHTNINGBLOOD)
for (i = 0; i < 2; i++)
{
if (qwtype[i] >= 0)
{
MSG_WriteByte (&sv.multicast, svc_temp_entity);
MSG_WriteByte (&sv.multicast, qwtype[i]);
if (qwtype[i] == TEQW_QWBLOOD || qwtype[i] == TEQW_QWGUNSHOT)
MSG_WriteByte (&sv.multicast, count);
MSG_WriteCoord (&sv.multicast, o[0]);
MSG_WriteCoord (&sv.multicast, o[1]);
MSG_WriteCoord (&sv.multicast, o[2]);
}
#ifdef NQPROT
sv.nqmulticast.cursize = 0; //don't send a te_blood or lightningblood to an nq client - they'll die horribly.
if (nqtype[i] >= 256)
{
//send a particle instead
MSG_WriteByte (&sv.nqmulticast, svc_particle);
MSG_WriteCoord (&sv.nqmulticast, o[0]);
MSG_WriteCoord (&sv.nqmulticast, o[1]);
MSG_WriteCoord (&sv.nqmulticast, o[2]);
//no direction.
MSG_WriteChar (&sv.nqmulticast, 0);
MSG_WriteChar (&sv.nqmulticast, 0);
MSG_WriteChar (&sv.nqmulticast, 0);
MSG_WriteByte (&sv.nqmulticast, count*20);
MSG_WriteByte (&sv.nqmulticast, nqtype[i]&0xff);
}
else if (nqtype[i] >= 0)
{
int nqcount = min(3,count);
do
{
MSG_WriteByte (&sv.nqmulticast, svc_temp_entity);
MSG_WriteByte (&sv.nqmulticast, nqtype[i]);
if (nqtype[i] == TEDP_BLOOD)
{
MSG_WriteChar(&sv.nqmulticast, 0);
MSG_WriteChar(&sv.nqmulticast, 0);
MSG_WriteChar(&sv.nqmulticast, 0);
}
if (/*nqtype == TENQ_QWBLOOD ||*/ nqtype[i] == TENQ_QWGUNSHOT)
MSG_WriteByte (&sv.multicast, count);
MSG_WriteCoord (&sv.nqmulticast, o[0]);
MSG_WriteCoord (&sv.nqmulticast, o[1]);
MSG_WriteCoord (&sv.nqmulticast, o[2]);
//send a particle instead
MSG_WriteByte (&sv.nqmulticast, svc_particle);
MSG_WriteCoord (&sv.nqmulticast, o[0]);
MSG_WriteCoord (&sv.nqmulticast, o[1]);
MSG_WriteCoord (&sv.nqmulticast, o[2]);
//no direction.
MSG_WriteChar (&sv.nqmulticast, 0);
MSG_WriteChar (&sv.nqmulticast, 0);
MSG_WriteChar (&sv.nqmulticast, 0);
MSG_WriteByte (&sv.nqmulticast, count*20);
if (qwtype == TEQW_QWBLOOD)
MSG_WriteByte (&sv.nqmulticast, 73);
else
MSG_WriteByte (&sv.nqmulticast, 225);
//messy - TENQ_NQGUNSHOT looks until we reach our counter. should probably randomize positions a little
if (nqcount > 1 && nqtype[i] == TENQ_NQGUNSHOT)
{
nqcount--;
continue;
}
} while(0);
}
#endif
if (i)
{
SV_MulticastProtExt (o, MULTICAST_PHS, pr_global_struct->dimension_send, 0, split);
break;
}
SV_MulticastProtExt (o, MULTICAST_PHS, pr_global_struct->dimension_send, split, 0);
if (!split)
break;
}
SV_MulticastProtExt (o, MULTICAST_PHS, pr_global_struct->dimension_send, split, 0);
if (!split) //don't bother sending again.
return;
//this is for people with an extension to do that effect properly
if (qwtype >= 0)
{
MSG_WriteByte (&sv.multicast, svc_temp_entity);
MSG_WriteByte (&sv.multicast, qwtype);
if (qwtype == TEQW_QWBLOOD || qwtype == TEQW_QWGUNSHOT)
MSG_WriteByte (&sv.multicast, count);
MSG_WriteCoord (&sv.multicast, o[0]);
MSG_WriteCoord (&sv.multicast, o[1]);
MSG_WriteCoord (&sv.multicast, o[2]);
}
#ifdef NQPROT
if (nqtype >= 0)
{
MSG_WriteByte (&sv.nqmulticast, svc_temp_entity);
MSG_WriteByte (&sv.nqmulticast, nqtype);
if (/*nqtype == TENQ_QWBLOOD ||*/ nqtype == TEQW_NQGUNSHOT)
MSG_WriteByte (&sv.multicast, count);
MSG_WriteCoord (&sv.nqmulticast, o[0]);
MSG_WriteCoord (&sv.nqmulticast, o[1]);
MSG_WriteCoord (&sv.nqmulticast, o[2]);
}
#endif
SV_MulticastProtExt (o, MULTICAST_PHS, pr_global_struct->dimension_send, 0, split);
}
void SV_beam_tempentity (int ownerent, vec3_t start, vec3_t end, int type)

View file

@ -121,6 +121,18 @@ pbool SV_ExtendedSaveData(pubprogfuncs_t *progfuncs, void *loadctx, const char *
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_STRING)return false;
sv.strings.model_precache[idx] = PR_AddString(svprogfuncs, token, 0, false);
}
#ifndef NOLEGACY
else if (!strcmp(token, "vwep"))
{ //vwep N "MODELNAME"
//0 IS valid, and frankly this stuff sucks.
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;
idx = atoi(token);
if (idx >= countof(sv.strings.vw_model_precache))
return false; //unsupported index.
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_STRING)return false;
sv.strings.vw_model_precache[idx] = PR_AddString(svprogfuncs, token, 0, false);
}
#endif
else if (!strcmp(token, "sound_precache") || !strcmp(token, "sound"))
{ //sound_precache N "MODELNAME"
l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false;

View file

@ -87,7 +87,7 @@ cvar_t allow_download_anymap = CVARD("allow_download_pakmaps", "0", "If 1, perm
cvar_t allow_download_pakcontents = CVARD("allow_download_pakcontents", "1", "controls whether clients connected to this server are allowed to download files from within packages.\nDoes NOT implicitly allow downloading bsps, set allow_download_pakmaps to enable that.\nWhile treating each file contained within packages is often undesirable, this is often needed for compatibility with legacy clients (despite it potentially allowing copyright violations).");
cvar_t allow_download_root = CVARD("allow_download_root", "0", "If set, enables downloading from the root of the gamedir (not the basedir). This setting has a lower priority than extension-based checks.");
cvar_t allow_download_textures = CVARD("allow_download_textures", "1", "0 blocks downloading of any file in the textures/ directory");
cvar_t allow_download_packages = CVARD("allow_download_packages", "1", "if 1, permits downloading files (from root directory or elsewhere) with known package extensions (eg: pak+pk3). Packages with a name starting 'pak' are covered by allow_download_copyrighted as well. This does not prevent ");
cvar_t allow_download_packages = CVARD("allow_download_packages", "1", "if 1, permits downloading files (from root directory or elsewhere) with known package extensions (eg: pak+pk3). Packages with a name starting 'pak' are covered by allow_download_copyrighted as well.");
cvar_t allow_download_refpackages = CVARD("allow_download_refpackages", "1", "If set to 1, packages that contain files needed during spawn functions will be become 'referenced' and automatically downloaded to clients.\nThis cvar should probably not be set if you have large packages that provide replacement pickup models on public servers.\nThe path command will show a '(ref)' tag next to packages which clients will automatically attempt to download.");
cvar_t allow_download_wads = CVARD("allow_download_wads", "1", "0 blocks downloading of any file in the wads/ directory, or is in the root directory with the extension .wad");
cvar_t allow_download_configs = CVARD("allow_download_configs", "0", "1 allows downloading of config files, either with the extension .cfg or in the subdir configs/.\n"CON_ERROR"THIS IS DANGEROUS AS IT CAN ALLOW PEOPLE TO READ YOUR RCON PASSWORD ETC.");

View file

@ -1414,6 +1414,8 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
float bouncestop = ent->xv->bouncestop;
if (!bouncestop)
bouncestop = 60;
else
bouncestop *= movevars.gravity * (ent->xv->gravity?ent->xv->gravity:1);
if (sv_gameplayfix_bouncedownslopes.ival)
bouncespeed = DotProduct(trace.plane.normal, ent->v->velocity);
else

View file

@ -3022,7 +3022,14 @@ static qboolean SV_SyncInfoBuf(client_t *client)
{ //vanilla-compatible info.
if (ISNQCLIENT(client))
{ //except that nq never had any userinfo
const char *s = va("//ui %i \"%s\" \"%s\"\n", (int)((client_t*)info-svs.clients), enckey, encval);
const char *s;
if (info == &svs.info)
s = va("//svi \"%s\" \"%s\"\n", enckey, encval);
else
{
int playerslot = (client_t*)((char*)info-(char*)&((client_t*)NULL)->userinfo)-svs.clients;
s = va("//ui %i \"%s\" \"%s\"\n", playerslot, enckey, encval);
}
ClientReliableWrite_Begin(client, svc_stufftext, strlen(s)+2);
ClientReliableWrite_String(client, s);
}

View file

@ -5597,7 +5597,12 @@ static void SVNQ_Spawn_f (void)
ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters);
}
//SV_Begin_Core(host_client);
//nq servers call ClientConnect early.
//qw servers hold off until the last possible moment.
//so qw servers prevent the player from getting shot too early.
//while nq ensures that reliables sent in ClientConnect are actually flushed before unreliables/entities start to arrive.
// if (nqcompat_spawnbeforeready.ival)
SV_Begin_Core(host_client);
ClientReliableWrite_Begin (host_client, svcnq_signonnum, 2);
ClientReliableWrite_Byte (host_client, 3);
@ -5714,7 +5719,8 @@ static void SVNQ_PreSpawn_f (void)
}
static void SVNQ_NQInfo_f (void)
{
Cmd_TokenizeString(va("setinfo \"%s\" \"%s\"\n", Cmd_Argv(0), Cmd_Argv(1)), false, false);
char buf[8192];
Cmd_TokenizeString(va("setinfo \"%s\" %s\n", Cmd_Argv(0), COM_QuotedString(Cmd_Argv(1), buf, sizeof(buf), false)), false, false);
SV_SetInfo_f();
}

View file

@ -57,8 +57,11 @@ void dumpprogstring(FILE *out, FILE *src)
j++;
if ((line[j] == '/' && line[j] == '/') || line[j] == '\r' || line[j] == '\n')
{
while (line[j])
fputc(line[j++], out);
for (; line[j]; j++)
{
if (line[j] != '\r')
fputc(line[j], out);
}
}
else
{

View file

@ -50,16 +50,13 @@ varying vec3 normal;
void main ()
{
#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
vec3 n, s, t, w;
gl_Position = skeletaltransform_wnst(w,n,s,t);
#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
vec3 eyeminusvertex = e_eyepos - w.xyz;
eyevector.x = dot(eyeminusvertex, s.xyz);
eyevector.y = dot(eyeminusvertex, t.xyz);
eyevector.z = dot(eyeminusvertex, n.xyz);
#else
vec3 n, s, t, w;
gl_Position = skeletaltransform_wnst(w,n,s,t);
#endif
#ifdef REFLECTCUBEMASK
invsurface[0] = s;
@ -258,7 +255,7 @@ void main ()
vec3 bumps = normalize(vec3(texture2D(s_normalmap, tc)) - 0.5);
vec4 specs = texture2D(s_specular, tc);
vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0));
vec3 halfdir = normalize(normalize(eyevector) + e_light_dir);
float spec = pow(max(dot(halfdir, bumps), 0.0), FTE_SPECULAR_EXPONENT * specs.a);
col.rgb += FTE_SPECULAR_MULTIPLIER * spec * specs.rgb;
#elif defined(REFLECTCUBEMASK)

View file

@ -4551,6 +4551,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
void VKBE_SubmitBatch(batch_t *batch)
{
shader_t *shader = batch->shader;
unsigned int bf;
shaderstate.nummeshes = batch->meshes - batch->firstmesh;
if (!shaderstate.nummeshes)
return;
@ -4558,8 +4559,10 @@ void VKBE_SubmitBatch(batch_t *batch)
shaderstate.batchvbo = batch->vbo;
shaderstate.meshlist = batch->mesh + batch->firstmesh;
shaderstate.curshader = shader->remapto;
if (shaderstate.curentity != batch->ent)
bf = batch->flags | shaderstate.forcebeflags;
if (shaderstate.curentity != batch->ent || shaderstate.flags != bf)
{
shaderstate.flags = bf;
BE_RotateForEntity(batch->ent, batch->ent->model);
shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime;
}
@ -4569,7 +4572,6 @@ void VKBE_SubmitBatch(batch_t *batch)
shaderstate.curtexnums = shader->defaulttextures + ((int)(shader->defaulttextures_fps * shaderstate.curtime) % shader->numdefaulttextures);
else
shaderstate.curtexnums = shader->defaulttextures;
shaderstate.flags = batch->flags | shaderstate.forcebeflags;
BE_DrawMeshChain_Internal();
}

View file

@ -967,8 +967,8 @@ qboolean VK_AllocatePoolMemory(uint32_t pooltype, VkDeviceSize memsize, VkDevice
if (!vk_usememorypools.ival)
return false;
if (memsize > 1024*1024*4)
return false;
// if (memsize > 1024*1024*4)
// return false;
for (p = vk.mempools; p; p = p->next)
{
if (p->memtype == pooltype)
@ -1052,6 +1052,7 @@ qboolean VK_AllocateImageMemory(VkImage image, qboolean dedicated, vk_poolmem_t
{ //make it dedicated one way or another.
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
VkMemoryDedicatedAllocateInfoKHR khr_mdai = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
VkResult err;
//shouldn't really happen, but just in case...
mem_reqs2.memoryRequirements.size = max(1,mem_reqs2.memoryRequirements.size);
@ -1070,14 +1071,20 @@ qboolean VK_AllocateImageMemory(VkImage image, qboolean dedicated, vk_poolmem_t
mem->size = mem_reqs2.memoryRequirements.size;
mem->memory = VK_NULL_HANDLE;
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &mem->memory));
err = vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &mem->memory);
if (err != VK_SUCCESS)
return false;
return true;
}
}
void VK_AllocateBindImageMemory(vk_image_t *image, qboolean dedicated)
qboolean VK_AllocateBindImageMemory(vk_image_t *image, qboolean dedicated)
{
if (VK_AllocateImageMemory(image->image, dedicated, &image->mem))
{
VkAssert(vkBindImageMemory(vk.device, image->image, image->mem.memory, image->mem.offset));
return true;
}
return false; //out of memory?
}
@ -1121,6 +1128,8 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
//swizzled/legacy formats
case PTI_L8: format = VK_FORMAT_R8_UNORM; break;
case PTI_L8A8: format = VK_FORMAT_R8G8_UNORM; break;
case PTI_L8_SRGB: format = VK_FORMAT_R8_SRGB; break;
case PTI_L8A8_SRGB: /*unsupportable*/ break;
//compressed formats
case PTI_BC1_RGB: format = VK_FORMAT_BC1_RGB_UNORM_BLOCK; break;
case PTI_BC1_RGB_SRGB: format = VK_FORMAT_BC1_RGB_SRGB_BLOCK; break;
@ -1227,11 +1236,12 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &ret.image));
VK_AllocateBindImageMemory(&ret, false);
ret.view = VK_NULL_HANDLE;
ret.sampler = VK_NULL_HANDLE;
if (!VK_AllocateBindImageMemory(&ret, false))
return ret; //oom?
viewInfo.flags = 0;
viewInfo.image = ret.image;
@ -1548,6 +1558,12 @@ qboolean VK_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
{
target = VK_CreateTexture2DArray(mips->mip[0].width, mips->mip[0].height, layers, mipcount/layers, mips->encoding, mips->type, !!(tex->flags&IF_RENDERTARGET));
if (target.mem.memory == VK_NULL_HANDLE)
{
VK_DestroyVkTexture(&target);
return false; //the alloc failed? can't copy to that which does not exist.
}
{
//images have weird layout representations.
//we need to use a side-effect of memory barriers in order to convert from one layout to another, so that we can actually use the image.
@ -1592,7 +1608,11 @@ qboolean VK_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
vkGetBufferMemoryRequirements(vk.device, fence->stagingbuffer, &mem_reqs);
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &fence->stagingmemory));
if (VK_SUCCESS != vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &fence->stagingmemory))
{
VK_FencedSubmit(fence);
return false; //some sort of oom error?
}
VkAssert(vkBindBufferMemory(vk.device, fence->stagingbuffer, fence->stagingmemory, 0));
VkAssert(vkMapMemory(vk.device, fence->stagingmemory, 0, bci.size, 0, &mapdata));
if (!mapdata)

View file

@ -479,7 +479,7 @@ void VKBE_RT_Destroy(struct vk_rendertarg *targ);
qboolean VK_AllocatePoolMemory(uint32_t pooltype, VkDeviceSize memsize, VkDeviceSize poolalignment, vk_poolmem_t *mem);
void VK_ReleasePoolMemory(vk_poolmem_t *mem);
qboolean VK_AllocateImageMemory(VkImage image, qboolean dedicated, vk_poolmem_t *mem); //dedicated should normally be TRUE for render targets
void VK_AllocateBindImageMemory(vk_image_t *image, qboolean dedicated); //dedicated should normally be TRUE for render targets
qboolean VK_AllocateBindImageMemory(vk_image_t *image, qboolean dedicated); //dedicated should normally be TRUE for render targets
struct stagingbuf
{
VkBuffer buf;

View file

@ -98,6 +98,25 @@ CONTENTS_LADDER = -16 //borrowed from halflife
Presence of this lump permits hulls 1 and 2 to be entirely omitted from the BSP (0 is still used for rendering), but doing so will harm compatibility with engines that do not understand this (presumably a solid-but-valid tree should be written, just in case). This could boost load times.
The engine is expected to insert the brushes into the bsp's various nodes. Inserting them into the leafs is suboptimal as leaf 0 will end up containing every brush...
ENVMAP:
(applies to fte)
Generated by fte's map_findcubemaps by parsing the entities lump for env_cubemap entities.
struct
{
vec3_t origin;
int cubesize;
} envmaps[];
This defines the various envmaps in the bsp, for mdls to use.
envmaps will be loaded from textures/env/MAPNAME_X_Y_Z using the engine's regular cubemap rules (xyz are rounded to ints).
SURFENVMAP:
(applies to fte)
Generated by fte's map_findcubemaps by parsing the entities lump for env_cubemap entities.
struct
{
unsigned int envmapindex;
} persurface[];
This provides each surface in the bsp with info about its most appropriate(nearest) envmap. if the index is ~0u, then no envmap is specified.
Other features: