mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 14:42:13 +00:00
fix q2 bsp texture animations.
fix q2 prediction. fix q2 saved games issues. fix q2bsp fullbright/fullwhite lights. fix potential issues from svs.clients no longer being preallocated. fix rtlights not doing q1 bsp texture animations. misc crash fixes. hack to allow a clickable hud when using a touchscreen. gl_max_size no longer affects 2d images. select faithful fps preset option by default. gl_font a,b,c works to select fallback fonts. freetype fonts reused to reduce memory usage when the same font is used multiple times either with different sizes or as fallbacks as part of other fonts. allow static member functions. allow static locals. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4552 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
409c17b9fc
commit
218006198d
41 changed files with 503 additions and 237 deletions
|
@ -917,7 +917,7 @@ ifeq ($(shell echo $(FTE_TARGET)|grep -E -v "win(32|64)$$"),)
|
|||
# The extra object file called resources.o is specific for MinGW to link the icon in
|
||||
|
||||
#cygwin's gcc requires an extra command to use mingw instead of cygwin (default paths, etc).
|
||||
ifneq ($(shell $(CC) -v 2>&1 | grep cygwin),)
|
||||
ifneq ($(shell $(CC) -dumpmachine 2>&1 | grep cygwin),)
|
||||
W32_CFLAGS=-mno-cygwin
|
||||
endif
|
||||
|
||||
|
|
|
@ -672,7 +672,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
|
|||
Cam_Lock(pv, i);
|
||||
return;
|
||||
}
|
||||
i = (i + 1) % MAX_CLIENTS;
|
||||
i = (i + 1) % cl.allocated_client_slots;
|
||||
} while (i != end);
|
||||
// stay on same guy?
|
||||
i = pv->cam_spec_track;
|
||||
|
|
|
@ -3327,7 +3327,7 @@ void CL_LinkPacketEntities (void)
|
|||
ent->topcolour = (state->colormap>>4) & 0xf;
|
||||
ent->bottomcolour = (state->colormap>>0) & 0xf;
|
||||
}
|
||||
else if (state->colormap > 0 && state->colormap <= MAX_CLIENTS)
|
||||
else if (state->colormap > 0 && state->colormap <= cl.allocated_client_slots)
|
||||
{
|
||||
ent->playerindex = state->colormap-1;
|
||||
ent->topcolour = cl.players[ent->playerindex].ttopcolor;
|
||||
|
|
|
@ -285,6 +285,7 @@ void CLQ2_PredictMovement (void) //q2 doesn't support split clients.
|
|||
{
|
||||
frame = ack & (UPDATE_MASK);
|
||||
cmd = (q2usercmd_t*)&cl.outframes[frame].cmd[0];
|
||||
cmd->msec = cl.outframes[frame].cmd[0].msec;
|
||||
|
||||
pm.cmd = *cmd;
|
||||
Q2_Pmove (&pm);
|
||||
|
@ -296,6 +297,7 @@ void CLQ2_PredictMovement (void) //q2 doesn't support split clients.
|
|||
if (independantphysics[0].msec)
|
||||
{
|
||||
cmd = (q2usercmd_t*)&independantphysics[0];
|
||||
cmd->msec = independantphysics[0].msec;
|
||||
|
||||
pm.cmd = *cmd;
|
||||
Q2_Pmove (&pm);
|
||||
|
|
|
@ -1726,7 +1726,7 @@ typedef struct _TargaHeader {
|
|||
|
||||
|
||||
#if defined(AVAIL_JPEGLIB) && !defined(NO_JPEG)
|
||||
void screenshotJPEG(char *filename, int compression, qbyte *screendata, int screenwidth, int screenheight);
|
||||
qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int screenwidth, int screenheight);
|
||||
#endif
|
||||
#ifdef AVAIL_PNGLIB
|
||||
int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, int height);
|
||||
|
@ -1783,14 +1783,14 @@ qboolean SCR_ScreenShot (char *filename, void *rgb_buffer, int width, int height
|
|||
#ifdef AVAIL_PNGLIB
|
||||
if (!strcmp(ext, "png"))
|
||||
{
|
||||
Image_WritePNG(filename, scr_sshot_compression.value, rgb_buffer, width, height);
|
||||
return Image_WritePNG(filename, scr_sshot_compression.value, rgb_buffer, width, height);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef AVAIL_JPEGLIB
|
||||
if (!strcmp(ext, "jpeg") || !strcmp(ext, "jpg"))
|
||||
{
|
||||
screenshotJPEG(filename, scr_sshot_compression.value, rgb_buffer, width, height);
|
||||
return screenshotJPEG(filename, scr_sshot_compression.value, rgb_buffer, width, height);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
|
@ -1306,7 +1306,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
|
|||
{ // use custom player skin
|
||||
ent.skinnum = 0;
|
||||
|
||||
player = &cl.players[s1->skinnum%MAX_CLIENTS];
|
||||
player = &cl.players[(s1->skinnum&0xff)%cl.allocated_client_slots];
|
||||
ent.model = player->model;
|
||||
if (!ent.model || ent.model->needload) //we need to do better than this
|
||||
{
|
||||
|
@ -1316,7 +1316,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
|
|||
if (!ent.model || ent.model->needload)
|
||||
ent.model = Mod_ForName("players/male/tris.md2", false);
|
||||
}
|
||||
ent.playerindex = s1->skinnum%MAX_CLIENTS;
|
||||
ent.playerindex = (s1->skinnum&0xff)%cl.allocated_client_slots;
|
||||
player->model = ent.model;
|
||||
/* ci = &cl.clientinfo[s1->skinnum & 0xff];
|
||||
// ent.skin = ci->skin;
|
||||
|
@ -1404,7 +1404,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
|
|||
|
||||
ent.angles[0]*=-1; //q2 has it fixed.
|
||||
|
||||
if (s1->number == cl.playerview[pnum].playernum+1) //woo! this is us!
|
||||
if (s1->number == cl.playerview[0].playernum+1) //woo! this is us!
|
||||
{
|
||||
// VectorCopy(cl.predicted_origin, ent.origin);
|
||||
// VectorCopy(cl.predicted_origin, ent.oldorigin);
|
||||
|
|
|
@ -1877,7 +1877,8 @@ void Con_DrawConsole (int lines, qboolean noback)
|
|||
char *key;
|
||||
if (!info)
|
||||
info = "";
|
||||
*end = 0;
|
||||
if (end)
|
||||
*end = 0;
|
||||
#ifdef PLUGINS
|
||||
if (!Plug_ConsoleLinkMouseOver(mousecursor_x, mousecursor_y, mouseover+2, info))
|
||||
#endif
|
||||
|
|
|
@ -607,7 +607,7 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *
|
|||
}
|
||||
else
|
||||
Con_Printf("Unsupported version\n");
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef AVAIL_PNGLIB
|
||||
|
@ -746,16 +746,6 @@ qboolean LibPNG_Init(void)
|
|||
return LIBPNG_LOADED();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(MING) //hehehe... add annother symbol so the statically linked cygwin libpng can link
|
||||
#undef setjmp
|
||||
int setjmp (jmp_buf jb)
|
||||
{
|
||||
return _setjmp(jb);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *data;
|
||||
int readposition;
|
||||
|
@ -1441,7 +1431,7 @@ METHODDEF(void) jpeg_error_exit (j_common_ptr cinfo)
|
|||
{
|
||||
longjmp(((jpeg_error_mgr_wrapper *) cinfo->err)->setjmp_buffer, 1);
|
||||
}
|
||||
void screenshotJPEG(char *filename, int compression, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba
|
||||
qboolean screenshotJPEG(char *filename, int compression, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba
|
||||
{
|
||||
qbyte *buffer;
|
||||
vfsfile_t *outfile;
|
||||
|
@ -1450,7 +1440,7 @@ void screenshotJPEG(char *filename, int compression, qbyte *screendata, int scre
|
|||
JSAMPROW row_pointer[1];
|
||||
|
||||
if (!LIBJPEG_LOADED())
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY)))
|
||||
{
|
||||
|
@ -1458,7 +1448,7 @@ void screenshotJPEG(char *filename, int compression, qbyte *screendata, int scre
|
|||
if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY)))
|
||||
{
|
||||
Con_Printf("Error opening %s\n", filename);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1478,7 +1468,7 @@ void screenshotJPEG(char *filename, int compression, qbyte *screendata, int scre
|
|||
VFS_CLOSE(outfile);
|
||||
FS_Remove(filename, FS_GAME);
|
||||
Con_Printf("Failed to create jpeg\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
#ifdef DYNAMIC_LIBJPEG
|
||||
qjpeg_create_compress(&cinfo);
|
||||
|
@ -1529,6 +1519,7 @@ void screenshotJPEG(char *filename, int compression, qbyte *screendata, int scre
|
|||
#else
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -349,7 +349,7 @@ void IN_MoveMouse(struct mouse_s *mouse, float *movements, int pnum)
|
|||
|
||||
if (mouse->type == M_TOUCH)
|
||||
{
|
||||
if (m_strafeonright.ival && mouse->downpos[0] > vid.pixelwidth/2 && movements != NULL && !Key_Dest_Has(kdm_game))
|
||||
if (m_strafeonright.ival && mouse->downpos[0] > vid.pixelwidth/2 && movements != NULL && !Key_Dest_Has(~kdm_game))
|
||||
{
|
||||
//if they're strafing, calculate the speed to move at based upon their displacement
|
||||
if (mouse->down)
|
||||
|
|
|
@ -533,7 +533,7 @@ void Key_DefaultLinkClicked(char *text, char *info)
|
|||
{
|
||||
unsigned int player = atoi(c);
|
||||
int i;
|
||||
if (player >= MAX_CLIENTS || !*cl.players[player].name)
|
||||
if (player >= cl.allocated_client_slots || !*cl.players[player].name)
|
||||
return;
|
||||
|
||||
c = Info_ValueForKey(info, "action");
|
||||
|
@ -1874,6 +1874,7 @@ qboolean Key_MouseShouldBeFree(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
int Sbar_TranslateHudClick(void);
|
||||
/*
|
||||
===================
|
||||
Key_Event
|
||||
|
@ -2196,6 +2197,18 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
|
|||
if (key == K_RSHIFT)//simulate a singular alt for binds. really though, this code should translate to csqc/menu keycodes and back to resolve the weirdness instead.
|
||||
key = K_SHIFT;
|
||||
|
||||
if ((key == K_MOUSE1 || key == K_MOUSE2) && 1)
|
||||
{
|
||||
int nkey = Sbar_TranslateHudClick();
|
||||
if (nkey)
|
||||
{
|
||||
//handle +/- events 'properly' the only safe way we can - by releasing them instantly and discarding the mouse-up event.
|
||||
Key_Event(devid, nkey, 0, true);
|
||||
Key_Event(devid, nkey, 0, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
kb = keybindings[key][keystate];
|
||||
if (kb)
|
||||
{
|
||||
|
|
|
@ -649,8 +649,8 @@ void M_Menu_Preset_f (void)
|
|||
};
|
||||
menu = M_Options_Title(&y, 0);
|
||||
MC_AddBulk(menu, bulk, 16, 216, y);
|
||||
//bottoms up! highlight 'fast' as the default option
|
||||
menu->selecteditem = menu->options->common.next->common.next->common.next->common.next;
|
||||
//bottoms up! highlight 'normal' as the default option
|
||||
menu->selecteditem = menu->options->common.next->common.next->common.next;
|
||||
menu->cursoritem->common.posy = menu->selecteditem->common.posy;
|
||||
}
|
||||
|
||||
|
|
|
@ -967,8 +967,15 @@ static void QCBUILTIN PF_R_AddEntityMask(pubprogfuncs_t *prinst, struct globalva
|
|||
{
|
||||
if (mask & MASK_DELTA)
|
||||
{
|
||||
CL_LinkPlayers ();
|
||||
CL_LinkPacketEntities ();
|
||||
#ifdef Q2CLIENT
|
||||
if (cls.protocol == CP_QUAKE2)
|
||||
CLQ2_AddEntities();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
CL_LinkPlayers ();
|
||||
CL_LinkPacketEntities ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -979,6 +979,8 @@ void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
// key_menu
|
||||
m_state = m_menu_dat;
|
||||
Key_Dest_Remove(kdm_message);
|
||||
if (!Key_Dest_Has(kdm_menu))
|
||||
Key_Dest_Remove(kdm_console);
|
||||
Key_Dest_Add(kdm_menu);
|
||||
break;
|
||||
case 1:
|
||||
|
@ -1525,7 +1527,7 @@ static struct {
|
|||
{"bufstr_add", PF_bufstr_add, 448},
|
||||
{"bufstr_free", PF_bufstr_free, 449},
|
||||
//gap
|
||||
{"is_cached_pic", PF_CL_is_cached_pic, 451},
|
||||
{"iscachedpic", PF_CL_is_cached_pic, 451},
|
||||
{"precache_pic", PF_CL_precache_pic, 452},
|
||||
{"free_pic", PF_CL_free_pic, 453},
|
||||
{"drawcharacter", PF_CL_drawcharacter, 454},
|
||||
|
@ -1568,7 +1570,7 @@ static struct {
|
|||
{"gecko_keyevent", PF_cs_gecko_keyevent, 490},
|
||||
{"gecko_mousemove", PF_cs_gecko_mousemove, 491},
|
||||
{"gecko_resize", PF_cs_gecko_resize, 492},
|
||||
{"gecko_get_texture_extent",PF_gecko_get_texture_extent,493},
|
||||
{"gecko_get_texture_extent",PF_cs_gecko_get_texture_extent,493},
|
||||
{"crc16", PF_crc16, 494},
|
||||
{"cvar_type", PF_cvar_type, 495},
|
||||
{"numentityfields", PF_numentityfields, 496},
|
||||
|
|
|
@ -608,6 +608,56 @@ void R2D_Conback_Callback(struct cvar_s *var, char *oldvalue)
|
|||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
qboolean R2D_Font_WasAdded(char *buffer, char *fontfilename)
|
||||
{
|
||||
char *match;
|
||||
if (!fontfilename)
|
||||
return true;
|
||||
match = strstr(buffer, fontfilename);
|
||||
if (!match)
|
||||
return false;
|
||||
if (!(match == buffer || match[-1] == ','))
|
||||
return false;
|
||||
match += strlen(fontfilename);
|
||||
if (*match && *match != ',')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
extern qboolean WinNT;
|
||||
qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen);
|
||||
qboolean MyRegGetStringValueMultiSz(HKEY base, char *keyname, char *valuename, void *data, int datalen);
|
||||
void R2D_Font_AddFontLink(char *buffer, int buffersize, char *fontname)
|
||||
{
|
||||
char link[1024];
|
||||
char *res, *comma, *othercomma, *nl;
|
||||
if (fontname)
|
||||
if (MyRegGetStringValueMultiSz(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink", fontname, link, sizeof(link)))
|
||||
{
|
||||
res = nl = link;
|
||||
while (*nl)
|
||||
{
|
||||
nl += strlen(nl);
|
||||
nl++;
|
||||
comma = strchr(res, ',');
|
||||
if (comma)
|
||||
{
|
||||
*comma++ = 0;
|
||||
othercomma = strchr(comma, ',');
|
||||
if (othercomma)
|
||||
*othercomma = 0;
|
||||
}
|
||||
else
|
||||
comma = "";
|
||||
if (!R2D_Font_WasAdded(buffer, res))
|
||||
{
|
||||
Q_strncatz(buffer, ",", buffersize);
|
||||
Q_strncatz(buffer, res, buffersize);
|
||||
R2D_Font_AddFontLink(buffer, buffersize, comma);
|
||||
}
|
||||
res = nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void R2D_Font_Callback(struct cvar_s *var, char *oldvalue)
|
||||
{
|
||||
|
@ -631,7 +681,6 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue)
|
|||
LOGFONT lf = {0};
|
||||
CHOOSEFONTA cf = {sizeof(cf)};
|
||||
extern HWND mainwindow;
|
||||
extern qboolean WinNT;
|
||||
font_conchar = Font_LoadFont(8, "");
|
||||
|
||||
cf.hwndOwner = mainwindow;
|
||||
|
@ -643,22 +692,26 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue)
|
|||
|
||||
if (pChooseFontA && pChooseFontA(&cf))
|
||||
{
|
||||
char fname[MAX_OSPATH];
|
||||
char fname[MAX_OSPATH*8];
|
||||
char *keyname;
|
||||
keyname = va("%s%s%s (TrueType)", lf.lfFaceName, lf.lfWeight>=FW_BOLD?" Bold":"", lf.lfItalic?" Italic":"");
|
||||
if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, fname, sizeof(fname)))
|
||||
*fname = 0;
|
||||
//FIXME: should enumerate and split & and ignore sizes and () crap.
|
||||
if (!*fname)
|
||||
{
|
||||
Cvar_Set(var, fname);
|
||||
return;
|
||||
keyname = va("%s%s%s (TrueType)", lf.lfFaceName, lf.lfWeight>=FW_BOLD?" Bold":"", lf.lfItalic?" Italic":"");
|
||||
if (!MyRegGetStringValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, fname, sizeof(fname)))
|
||||
*fname = 0;
|
||||
}
|
||||
keyname = va("%s (OpenType)", lf.lfFaceName);
|
||||
if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, fname, sizeof(fname)))
|
||||
if (!*fname)
|
||||
{
|
||||
Cvar_Set(var, fname);
|
||||
return;
|
||||
keyname = va("%s (OpenType)", lf.lfFaceName);
|
||||
if (!MyRegGetStringValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, fname, sizeof(fname)))
|
||||
*fname = 0;
|
||||
}
|
||||
|
||||
R2D_Font_AddFontLink(fname, sizeof(fname), lf.lfFaceName);
|
||||
Cvar_Set(var, fname);
|
||||
}
|
||||
Cvar_Set(var, "");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2182,12 +2182,15 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent)
|
|||
if (!b)
|
||||
continue;
|
||||
*b = *ob;
|
||||
if (b->texture)
|
||||
b->shader = R_TextureAnimation(ent->framestate.g[FS_REG].frame[0], b->texture)->shader;
|
||||
// if (b->texture)
|
||||
// b->shader = R_TextureAnimation(ent->framestate.g[FS_REG].frame[0], b->texture)->shader;
|
||||
b->meshes = b->maxmeshes;
|
||||
b->ent = ent;
|
||||
b->flags = bef;
|
||||
|
||||
if (b->buildmeshes)
|
||||
b->buildmeshes(b);
|
||||
|
||||
if (bef & BEF_FORCEADDITIVE)
|
||||
{
|
||||
b->next = batches[SHADER_SORT_ADDITIVE];
|
||||
|
|
|
@ -1627,6 +1627,54 @@ void Sbar_DrawInventory (playerview_t *pv)
|
|||
}
|
||||
}
|
||||
|
||||
static qboolean PointInBox(float px, float py, float x, float y, float w, float h)
|
||||
{
|
||||
if (px >= x && px < x+w)
|
||||
if (py >= y && py < y+h)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
int Sbar_TranslateHudClick(void)
|
||||
{
|
||||
int i;
|
||||
float vx = mousecursor_x - sbar_rect.x;
|
||||
float vy = mousecursor_y - (sbar_rect.y + (sbar_rect.height-SBAR_HEIGHT));
|
||||
|
||||
qboolean headsup = !(cl_sbar.value || (scr_viewsize.value<100&&cl.splitclients==1));
|
||||
qboolean hudswap = cl_hudswap.value; // Get that nasty float out :)
|
||||
|
||||
//inventory. clicks do specific-weapon impulses.
|
||||
if (sb_lines > 24)
|
||||
{
|
||||
for (i=0 ; i<7 ; i++)
|
||||
{
|
||||
if (headsup)
|
||||
{
|
||||
if (i || sbar_rect.height>200)
|
||||
if (PointInBox (vx, vy, (hudswap) ? 0 : (sbar_rect.width-24),-68-(7-i)*16, 24,16))
|
||||
return '2' + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PointInBox (vx, vy, i*24, -16, (i==6)?48:24, 16))
|
||||
return '2' + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//armour. trigger backtick, to toggle the console (which enables the on-screen keyboard on android).
|
||||
if (PointInBox (vx, vy, 0, 0, 96, 24))
|
||||
return '`';
|
||||
//face. do showscores.
|
||||
if (PointInBox (vx, vy, 112, 0, 96, 24))
|
||||
return K_TAB;
|
||||
//currentammo+icon. trigger '/' binding, which defaults to weapon-switch (impulse 10)
|
||||
if (PointInBox (vx, vy, 224, 0, 96, 24))
|
||||
return '/';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
|
|
|
@ -2141,6 +2141,23 @@ qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *da
|
|||
((char*)data)[0] = 0;
|
||||
return result;
|
||||
}
|
||||
qboolean MyRegGetStringValueMultiSz(HKEY base, char *keyname, char *valuename, void *data, int datalen)
|
||||
{
|
||||
qboolean result = false;
|
||||
HKEY subkey;
|
||||
DWORD type = REG_NONE;
|
||||
if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD dwlen;
|
||||
result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &dwlen);
|
||||
datalen = dwlen;
|
||||
RegCloseKey (subkey);
|
||||
}
|
||||
|
||||
if (type == REG_MULTI_SZ)
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean MyRegSetValue(HKEY base, char *keyname, char *valuename, int type, void *data, int datalen)
|
||||
{
|
||||
|
|
|
@ -1238,11 +1238,16 @@ qboolean CMod_LoadTexInfo (lump_t *l) //yes I know these load from the same plac
|
|||
out->mipadjust = 1;
|
||||
|
||||
if (out->flags & TI_SKY)
|
||||
snprintf(sname, sizeof(sname), "sky/%s", in->texture);
|
||||
snprintf(sname, sizeof(sname), "sky/%s%s", in->texture, in->nexttexinfo==-1?"":"#ANIMLOOP");
|
||||
else if (out->flags & (TI_WARP|TI_TRANS33|TI_TRANS66))
|
||||
snprintf(sname, sizeof(sname), "%s/%s#ALPHA=%s", ((out->flags&TI_WARP)?"warp":"trans"), in->texture, ((out->flags&TI_TRANS66)?"0.66":(out->flags&TI_TRANS33?"0.33":"1")));
|
||||
snprintf(sname, sizeof(sname), "%s/%s#ALPHA=%s%s", ((out->flags&TI_WARP)?"warp":"trans"), in->texture, ((out->flags&TI_TRANS66)?"0.66":(out->flags&TI_TRANS33?"0.33":"1")), in->nexttexinfo==-1?"":"#ANIMLOOP");
|
||||
else
|
||||
snprintf(sname, sizeof(sname), "wall/%s", in->texture);
|
||||
snprintf(sname, sizeof(sname), "wall/%s%s", in->texture, in->nexttexinfo==-1?"":"#ANIMLOOP");
|
||||
|
||||
//in q2, 'TEX_SPECIAL' is TI_LIGHT, and that conflicts.
|
||||
out->flags &= ~TI_LIGHT;
|
||||
if (out->flags & (TI_SKY|TI_TRANS33|TI_TRANS66|TI_WARP))
|
||||
out->flags |= TEX_SPECIAL;
|
||||
|
||||
//compact the textures.
|
||||
for (j=0; j < texcount; j++)
|
||||
|
@ -1275,6 +1280,29 @@ qboolean CMod_LoadTexInfo (lump_t *l) //yes I know these load from the same plac
|
|||
|
||||
loadmodel->textures[texcount++] = out->texture;
|
||||
}
|
||||
|
||||
if (in->nexttexinfo != -1)
|
||||
{
|
||||
Con_DPrintf("FIXME: %s should animate to %s\n", in->texture, (in->nexttexinfo+(q2texinfo_t *)(cmod_base + l->fileofs))->texture);
|
||||
}
|
||||
}
|
||||
|
||||
in = (void *)(cmod_base + l->fileofs);
|
||||
out = loadmodel->texinfo;
|
||||
for (i=0 ; i<count ; i++)
|
||||
{
|
||||
if (in[i].nexttexinfo >= 0 && in[i].nexttexinfo < count)
|
||||
out[i].texture->anim_next = out[in[i].nexttexinfo].texture;
|
||||
}
|
||||
for (i=0 ; i<count ; i++)
|
||||
{
|
||||
texture_t *tex;
|
||||
if (!out[i].texture->anim_next)
|
||||
continue;
|
||||
|
||||
out[i].texture->anim_total = 1;
|
||||
for (tex = out[i].texture->anim_next ; tex && tex != out[i].texture ; tex=tex->anim_next)
|
||||
out[i].texture->anim_total++;
|
||||
}
|
||||
|
||||
loadmodel->numtextures = texcount;
|
||||
|
@ -6035,4 +6063,3 @@ void CM_Init(void) //register cvars.
|
|||
Cvar_Register(&r_subdivisions, MAPOPTIONS);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -268,7 +268,7 @@ static void BE_CreateSamplerStates(void)
|
|||
if (flags & SHADER_PASS_NEAREST)
|
||||
sampdesc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
|
||||
else
|
||||
sampdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
sampdesc.Filter = /*D3D11_FILTER_MIN_MAG_MIP_POINT;D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;*/D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
sampdesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
}
|
||||
if (flags & SHADER_PASS_CLAMP)
|
||||
|
@ -2799,7 +2799,7 @@ void D3D11BE_SubmitBatch(batch_t *batch)
|
|||
shaderstate.batchvbo = batch->vbo;
|
||||
shaderstate.meshlist = batch->mesh + batch->firstmesh;
|
||||
shaderstate.curshader = batch->shader;
|
||||
shaderstate.curtexnums = batch->skin;
|
||||
shaderstate.curtexnums = batch->skin?batch->skin:&batch->shader->defaulttextures;
|
||||
shaderstate.flags = batch->flags;
|
||||
|
||||
if (!shaderstate.batchvbo)
|
||||
|
@ -2864,11 +2864,6 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
|
||||
if (batch->buildmeshes)
|
||||
batch->buildmeshes(batch);
|
||||
else if (batch->texture)
|
||||
{
|
||||
batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader;
|
||||
batch->skin = &batch->shader->defaulttextures;
|
||||
}
|
||||
|
||||
if (batch->shader->flags & SHADER_NODLIGHT)
|
||||
if (shaderstate.mode == BEM_LIGHT)
|
||||
|
@ -3149,9 +3144,6 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist)
|
|||
|
||||
if (batch->buildmeshes)
|
||||
batch->buildmeshes(batch);
|
||||
else
|
||||
batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader;
|
||||
|
||||
|
||||
/*draw already-drawn portals as depth-only, to ensure that their contents are not harmed*/
|
||||
BE_SelectMode(BEM_DEPTHONLY);
|
||||
|
|
|
@ -29640,43 +29640,6 @@
|
|||
RelativePath="..\common\net_ice.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\net_sellingmysoultothedevil.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="MinGLDebug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="GLDebug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAs="2"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug Dedicated Server|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="D3DRelease|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common\net_ssl_winsspi.c"
|
||||
>
|
||||
|
|
|
@ -4115,8 +4115,8 @@ static void GLBE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist)
|
|||
|
||||
if (batch->buildmeshes)
|
||||
batch->buildmeshes(batch);
|
||||
else
|
||||
batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader;
|
||||
// else
|
||||
// batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader;
|
||||
|
||||
|
||||
/*draw already-drawn portals as depth-only, to ensure that their contents are not harmed*/
|
||||
|
@ -4165,13 +4165,14 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
if (shaderstate.mode == BEM_STENCIL || shaderstate.mode == BEM_DEPTHONLY) //fixme: depthonly is not just shadows.
|
||||
continue;
|
||||
|
||||
//buildmeshes updates shaders and generates pose information for sufaces that need it.
|
||||
//the shader flags checked *after* this call may be a performance issue if it generated lots of new mesh data.
|
||||
//FIXME: should we assume that the batch's shader will have the same flags?
|
||||
if (batch->buildmeshes)
|
||||
{
|
||||
TRACE(("GLBE_SubmitMeshesSortList: build\n"));
|
||||
batch->buildmeshes(batch);
|
||||
}
|
||||
else if (batch->texture)
|
||||
batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader;
|
||||
|
||||
TRACE(("GLBE_SubmitMeshesSortList: shader %s\n", batch->shader->name));
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ unsigned char *d_15to8table;
|
|||
qboolean inited15to8;
|
||||
#endif
|
||||
|
||||
int maxtexsize; //max_size for 2d images.
|
||||
extern cvar_t gl_max_size;
|
||||
extern cvar_t gl_picmip;
|
||||
extern cvar_t gl_lerpimages;
|
||||
|
@ -450,14 +451,13 @@ void GLDraw_Init (void)
|
|||
{
|
||||
char ver[40];
|
||||
|
||||
int maxtexsize;
|
||||
|
||||
if (gltextures)
|
||||
gltextures = NULL;
|
||||
|
||||
memset(gltexturetablebuckets, 0, sizeof(gltexturetablebuckets));
|
||||
Hash_InitTable(&gltexturetable, sizeof(gltexturetablebuckets)/sizeof(gltexturetablebuckets[0]), gltexturetablebuckets);
|
||||
|
||||
maxtexsize = 256;
|
||||
qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize);
|
||||
if (gl_max_size.value > maxtexsize)
|
||||
{
|
||||
|
@ -465,8 +465,6 @@ void GLDraw_Init (void)
|
|||
Cvar_ForceSet (&gl_max_size, ver);
|
||||
}
|
||||
|
||||
maxtexsize = gl_max_size.value;
|
||||
|
||||
if (uploadmemorybuffer)
|
||||
BZ_Free(uploadmemorybuffer);
|
||||
if (uploadmemorybufferintermediate)
|
||||
|
@ -1035,8 +1033,9 @@ qboolean GL_UploadCompressed (qbyte *file, int *out_width, int *out_height, unsi
|
|||
}
|
||||
|
||||
|
||||
void GL_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap)
|
||||
void GL_RoundDimensions(int *scaled_width, int *scaled_height, unsigned int flags)
|
||||
{
|
||||
qboolean mipmap = flags & IF_NOMIPMAP;
|
||||
if (r_config.texture_non_power_of_two) //NPOT is a simple extension that relaxes errors.
|
||||
{
|
||||
TRACE(("dbg: GL_RoundDimensions: GL_ARB_texture_non_power_of_two\n"));
|
||||
|
@ -1060,25 +1059,36 @@ void GL_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap)
|
|||
}
|
||||
}
|
||||
|
||||
if (mipmap)
|
||||
if (flags & IF_NOMIPMAP)
|
||||
{
|
||||
TRACE(("dbg: GL_RoundDimensions: %f\n", gl_picmip.value));
|
||||
*scaled_width >>= (int)gl_picmip.value;
|
||||
*scaled_height >>= (int)gl_picmip.value;
|
||||
*scaled_width >>= gl_picmip2d.ival;
|
||||
*scaled_height >>= gl_picmip2d.ival;
|
||||
}
|
||||
else
|
||||
{
|
||||
*scaled_width >>= (int)gl_picmip2d.value;
|
||||
*scaled_height >>= (int)gl_picmip2d.value;
|
||||
TRACE(("dbg: GL_RoundDimensions: %f\n", gl_picmip.value));
|
||||
*scaled_width >>= gl_picmip.ival;
|
||||
*scaled_height >>= gl_picmip.ival;
|
||||
}
|
||||
|
||||
TRACE(("dbg: GL_RoundDimensions: %f\n", gl_max_size.value));
|
||||
if (gl_max_size.value)
|
||||
|
||||
if (maxtexsize)
|
||||
{
|
||||
if (*scaled_width > gl_max_size.value)
|
||||
*scaled_width = gl_max_size.value;
|
||||
if (*scaled_height > gl_max_size.value)
|
||||
*scaled_height = gl_max_size.value;
|
||||
if (*scaled_width > maxtexsize)
|
||||
*scaled_width = maxtexsize;
|
||||
if (*scaled_height > maxtexsize)
|
||||
*scaled_height = maxtexsize;
|
||||
}
|
||||
if (!(flags & IF_UIPIC))
|
||||
{
|
||||
if (gl_max_size.value)
|
||||
{
|
||||
if (*scaled_width > gl_max_size.value)
|
||||
*scaled_width = gl_max_size.value;
|
||||
if (*scaled_height > gl_max_size.value)
|
||||
*scaled_height = gl_max_size.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (*scaled_width < 1)
|
||||
|
@ -1139,7 +1149,7 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
|
||||
scaled_width = width;
|
||||
scaled_height = height;
|
||||
GL_RoundDimensions(&scaled_width, &scaled_height, !(flags & IF_NOMIPMAP));
|
||||
GL_RoundDimensions(&scaled_width, &scaled_height, flags);
|
||||
|
||||
if (!(flags & IF_NOALPHA))
|
||||
{ //make sure it does actually have those alpha pixels (q3 compat)
|
||||
|
@ -1402,7 +1412,7 @@ void GL_Upload24BGR (char *name, qbyte *framedata, int inwidth, int inheight, un
|
|||
|
||||
outwidth = inwidth;
|
||||
outheight = inheight;
|
||||
GL_RoundDimensions(&outwidth, &outheight, !(flags&IF_NOMIPMAP));
|
||||
GL_RoundDimensions(&outwidth, &outheight, flags);
|
||||
|
||||
if (outwidth*outheight*4 > sizeofuploadmemorybufferintermediate)
|
||||
{
|
||||
|
@ -1472,7 +1482,7 @@ void GL_Upload24BGR_Flip (char *name, qbyte *framedata, int inwidth, int inheigh
|
|||
|
||||
outwidth = inwidth;
|
||||
outheight = inheight;
|
||||
GL_RoundDimensions(&outwidth, &outheight, !(flags&IF_NOMIPMAP));
|
||||
GL_RoundDimensions(&outwidth, &outheight, flags);
|
||||
|
||||
if (outwidth*outheight*4 > sizeofuploadmemorybufferintermediate)
|
||||
{
|
||||
|
@ -1540,7 +1550,7 @@ void GL_Upload8Grey (unsigned char*data, int width, int height, unsigned int fla
|
|||
|
||||
scaled_width = width;
|
||||
scaled_height = height;
|
||||
GL_RoundDimensions(&scaled_width, &scaled_height, !(flags&IF_NOMIPMAP));
|
||||
GL_RoundDimensions(&scaled_width, &scaled_height, flags);
|
||||
|
||||
if (scaled_width * scaled_height*4 > sizeofuploadmemorybuffer)
|
||||
{
|
||||
|
@ -1718,7 +1728,7 @@ static unsigned int * genNormalMap(qbyte *pixels, int w, int h, float scale)
|
|||
}
|
||||
|
||||
//PENTA
|
||||
void GL_UploadBump(qbyte *data, int width, int height, unsigned int mipmap, float bumpscale)
|
||||
void GL_UploadBump(qbyte *data, int width, int height, unsigned int flags, float bumpscale)
|
||||
{
|
||||
unsigned char *scaled;
|
||||
int scaled_width, scaled_height;
|
||||
|
@ -1728,7 +1738,7 @@ void GL_UploadBump(qbyte *data, int width, int height, unsigned int mipmap, floa
|
|||
|
||||
scaled_width = width;
|
||||
scaled_height = height;
|
||||
GL_RoundDimensions(&scaled_width, &scaled_height, mipmap);
|
||||
GL_RoundDimensions(&scaled_width, &scaled_height, flags);
|
||||
|
||||
if (scaled_width*scaled_height*4 > sizeofuploadmemorybuffer)
|
||||
{
|
||||
|
@ -1757,7 +1767,7 @@ void GL_UploadBump(qbyte *data, int width, int height, unsigned int mipmap, floa
|
|||
|
||||
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if (mipmap)
|
||||
if (!(flags & IF_NOMIPMAP))
|
||||
{
|
||||
int miplevel;
|
||||
|
||||
|
@ -1781,7 +1791,7 @@ void GL_UploadBump(qbyte *data, int width, int height, unsigned int mipmap, floa
|
|||
}
|
||||
}
|
||||
|
||||
if (mipmap)
|
||||
if (!(flags & IF_NOMIPMAP))
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
||||
if (0 & IF_NEAREST)
|
||||
|
@ -1809,7 +1819,7 @@ void GL_UploadBump(qbyte *data, int width, int height, unsigned int mipmap, floa
|
|||
|
||||
#ifdef GL_USE8BITTEX
|
||||
#ifdef GL_EXT_paletted_texture
|
||||
void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qboolean alpha)
|
||||
void GL_Upload8_EXT (qbyte *data, int width, int height, unsigned int flags, qboolean alpha)
|
||||
{
|
||||
int i, s;
|
||||
qboolean noalpha;
|
||||
|
@ -1837,7 +1847,7 @@ void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qbool
|
|||
|
||||
scaled_width = width;
|
||||
scaled_height = height;
|
||||
GL_RoundDimensions(&scaled_width, &scaled_height, mipmap);
|
||||
GL_RoundDimensions(&scaled_width, &scaled_height, flags);
|
||||
|
||||
if (scaled_width*scaled_height*4 > sizeofuploadmemorybuffer)
|
||||
{
|
||||
|
@ -2014,7 +2024,7 @@ void GL_Upload8 (char *name, qbyte *data, int width, int height, unsigned int fl
|
|||
#ifdef GL_USE8BITTEX
|
||||
#ifdef GL_EXT_paletted_texture
|
||||
if (GLVID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
|
||||
GL_Upload8_EXT (data, width, height, mipmap, alpha);
|
||||
GL_Upload8_EXT (data, width, height, flags, alpha);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,7 @@ qboolean triedtoloadfreetype;
|
|||
dllhandle_t *fontmodule;
|
||||
FT_Error (VARGS *pFT_Init_FreeType) (FT_Library *alibrary);
|
||||
FT_Error (VARGS *pFT_Load_Char) (FT_Face face, FT_ULong char_code, FT_Int32 load_flags);
|
||||
FT_UInt (VARGS *pFT_Get_Char_Index) (FT_Face face, FT_ULong charcode);
|
||||
FT_Error (VARGS *pFT_Set_Pixel_Sizes) (FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height);
|
||||
FT_Error (VARGS *pFT_New_Face) (FT_Library library, const char *pathname, FT_Long face_index, FT_Face *aface);
|
||||
FT_Error (VARGS *pFT_New_Memory_Face) (FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface);
|
||||
|
@ -162,6 +163,22 @@ static const char *imgs[] =
|
|||
#define PLANEWIDTH (1<<8)
|
||||
#define PLANEHEIGHT PLANEWIDTH
|
||||
|
||||
//windows' font linking allows linking multiple extra fonts to a main font.
|
||||
//this means that a single selected font can use chars from lots of different files if the first one(s) didn't provide that font.
|
||||
//they're provided as fallbacks.
|
||||
#define MAX_FTFACES 32
|
||||
|
||||
typedef struct ftfontface_s
|
||||
{
|
||||
struct ftfontface_s *next;
|
||||
struct ftfontface_s **link; //like prev, but not.
|
||||
char name[MAX_OSPATH];
|
||||
int refs;
|
||||
int activeheight; //needs reconfiguring when different sizes are used
|
||||
FT_Face face;
|
||||
void *membuf;
|
||||
} ftfontface_t;
|
||||
static ftfontface_t *ftfaces;
|
||||
|
||||
|
||||
#define GEN_CONCHAR_GLYPHS 0 //set to 0 or 1 to define whether to generate glyphs from conchars too, or if it should just draw them as glquake always used to
|
||||
|
@ -170,6 +187,8 @@ extern cvar_t con_ocranaleds;
|
|||
|
||||
typedef struct font_s
|
||||
{
|
||||
//FIXME: use a hash table? will need it if we go beyond ucs-2.
|
||||
//currently they're in a single block so the font can be checked from scanning the active chars when shutting down. we could instead scan all 65k chars in every font instead...
|
||||
struct charcache_s
|
||||
{
|
||||
struct charcache_s *nextchar;
|
||||
|
@ -186,18 +205,20 @@ typedef struct font_s
|
|||
short top;
|
||||
short left;
|
||||
} chars[FONTCHARS];
|
||||
char name[64];
|
||||
char name[MAX_OSPATH];
|
||||
|
||||
short charheight;
|
||||
texid_t singletexture;
|
||||
#ifdef AVAIL_FREETYPE
|
||||
FT_Face face;
|
||||
void *membuf;
|
||||
//FIXME: multiple sized font_t objects should refer to a single FT_Face.
|
||||
int ftfaces;
|
||||
ftfontface_t *face[MAX_FTFACES];
|
||||
#endif
|
||||
struct font_s *alt;
|
||||
vec3_t alttint;
|
||||
} font_t;
|
||||
|
||||
//shared between fonts.
|
||||
typedef struct {
|
||||
texid_t texnum[FONTPLANES];
|
||||
texid_t defaultfont;
|
||||
|
@ -214,7 +235,6 @@ typedef struct {
|
|||
shader_t *shader;
|
||||
shader_t *backshader;
|
||||
} fontplanes_t;
|
||||
|
||||
static fontplanes_t fontplanes;
|
||||
|
||||
#define FONT_CHAR_BUFFER 512
|
||||
|
@ -582,23 +602,34 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
|
|||
}
|
||||
|
||||
#ifdef AVAIL_FREETYPE
|
||||
if (f->face)
|
||||
if (f->ftfaces)
|
||||
{
|
||||
if (pFT_Load_Char(f->face, charidx, FT_LOAD_RENDER) == 0)
|
||||
int file;
|
||||
for (file = 0; file < f->ftfaces; file++)
|
||||
{
|
||||
FT_GlyphSlot slot;
|
||||
FT_Bitmap *bm;
|
||||
|
||||
slot = f->face->glyph;
|
||||
bm = &slot->bitmap;
|
||||
c = Font_LoadGlyphData(f, charidx, true, bm->buffer, bm->width, bm->rows, bm->pitch);
|
||||
|
||||
if (c)
|
||||
FT_Face face = f->face[file]->face;
|
||||
if (f->face[file]->activeheight != f->charheight)
|
||||
{
|
||||
c->advance = slot->advance.x >> 6;
|
||||
c->left = slot->bitmap_left;
|
||||
c->top = f->charheight*3/4 - slot->bitmap_top;
|
||||
return c;
|
||||
f->face[file]->activeheight = f->charheight;
|
||||
pFT_Set_Pixel_Sizes(face, 0, f->charheight);
|
||||
}
|
||||
if (charidx == 0xfffe || pFT_Get_Char_Index(face, charidx)) //ignore glyph 0 (undefined)
|
||||
if (pFT_Load_Char(face, charidx, FT_LOAD_RENDER) == 0)
|
||||
{
|
||||
FT_GlyphSlot slot;
|
||||
FT_Bitmap *bm;
|
||||
|
||||
slot = face->glyph;
|
||||
bm = &slot->bitmap;
|
||||
c = Font_LoadGlyphData(f, charidx, true, bm->buffer, bm->width, bm->rows, bm->pitch);
|
||||
|
||||
if (c)
|
||||
{
|
||||
c->advance = slot->advance.x >> 6;
|
||||
c->left = slot->bitmap_left;
|
||||
c->top = f->charheight*3/4 - slot->bitmap_top;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -658,18 +689,35 @@ static struct charcache_s *Font_GetChar(font_t *f, CHARIDXTYPE charidx)
|
|||
qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename)
|
||||
{
|
||||
#ifdef AVAIL_FREETYPE
|
||||
ftfontface_t *qface;
|
||||
FT_Face face = NULL;
|
||||
FT_Error error;
|
||||
flocation_t loc;
|
||||
void *fbase = NULL;
|
||||
if (!*fontfilename)
|
||||
return false;
|
||||
|
||||
//ran out of font slots.
|
||||
if (f->ftfaces == MAX_FTFACES)
|
||||
return false;
|
||||
|
||||
for (qface = ftfaces; qface; qface = qface->next)
|
||||
{
|
||||
if (!strcmp(qface->name, fontfilename))
|
||||
{
|
||||
qface->refs++;
|
||||
f->face[f->ftfaces++] = qface;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fontlib)
|
||||
{
|
||||
dllfunction_t ft2funcs[] =
|
||||
{
|
||||
{(void**)&pFT_Init_FreeType, "FT_Init_FreeType"},
|
||||
{(void**)&pFT_Load_Char, "FT_Load_Char"},
|
||||
{(void**)&pFT_Get_Char_Index, "FT_Get_Char_Index"},
|
||||
{(void**)&pFT_Set_Pixel_Sizes, "FT_Set_Pixel_Sizes"},
|
||||
{(void**)&pFT_New_Face, "FT_New_Face"},
|
||||
{(void**)&pFT_New_Memory_Face, "FT_New_Memory_Face"},
|
||||
|
@ -763,8 +811,17 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename)
|
|||
if (!error)
|
||||
{
|
||||
/*success!*/
|
||||
f->membuf = fbase;
|
||||
f->face = face;
|
||||
qface = Z_Malloc(sizeof(*qface));
|
||||
qface->link = &ftfaces;
|
||||
qface->next = *qface->link;
|
||||
*qface->link = qface;
|
||||
qface->face = face;
|
||||
qface->membuf = fbase;
|
||||
qface->refs++;
|
||||
qface->activeheight = height;
|
||||
Q_strncpyz(qface->name, fontfilename, sizeof(qface->name));
|
||||
|
||||
f->face[f->ftfaces++] = qface;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1149,7 +1206,27 @@ struct font_s *Font_LoadFont(int vheight, char *fontfilename)
|
|||
else
|
||||
f->alt = Font_LoadFont(vheight, aname+1);
|
||||
}
|
||||
if (!Font_LoadFreeTypeFont(f, height, fontfilename))
|
||||
|
||||
{
|
||||
char *start;
|
||||
start = fontfilename;
|
||||
for(;;)
|
||||
{
|
||||
char *end = strchr(start, ',');
|
||||
if (end)
|
||||
*end = 0;
|
||||
Font_LoadFreeTypeFont(f, height, start);
|
||||
if (end)
|
||||
{
|
||||
*end = ',';
|
||||
start = end+1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f->ftfaces)
|
||||
{
|
||||
//default to only map the ascii-compatible chars from the quake font.
|
||||
if (*fontfilename)
|
||||
|
@ -1245,10 +1322,22 @@ void Font_Free(struct font_s *f)
|
|||
}
|
||||
|
||||
#ifdef AVAIL_FREETYPE
|
||||
if (f->face)
|
||||
pFT_Done_Face(f->face);
|
||||
if (f->membuf)
|
||||
BZ_Free(f->membuf);
|
||||
while(f->ftfaces --> 0)
|
||||
{
|
||||
ftfontface_t *qface = f->face[f->ftfaces];
|
||||
qface->refs--;
|
||||
if (!qface->refs)
|
||||
{
|
||||
if (qface->face)
|
||||
pFT_Done_Face(qface->face);
|
||||
if (qface->membuf)
|
||||
BZ_Free(qface->membuf);
|
||||
*qface->link = qface->next;
|
||||
if (qface->next)
|
||||
qface->next->link = qface->link;
|
||||
Z_Free(qface);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Z_Free(f);
|
||||
}
|
||||
|
|
|
@ -2619,6 +2619,60 @@ static void Mod_Batches_BuildModelMeshes(model_t *mod, int maxverts, int maxindi
|
|||
}
|
||||
}
|
||||
|
||||
//q1 autoanimates. if the frame is set, it uses the alternate animation.
|
||||
void Mod_UpdateBatchShader_Q1 (struct batch_s *batch)
|
||||
{
|
||||
texture_t *base = batch->texture;
|
||||
int reletive;
|
||||
int count;
|
||||
|
||||
if (batch->ent->framestate.g[FS_REG].frame[0])
|
||||
{
|
||||
if (base->alternate_anims)
|
||||
base = base->alternate_anims;
|
||||
}
|
||||
|
||||
if (base->anim_total)
|
||||
{
|
||||
reletive = (int)(cl.time*10) % base->anim_total;
|
||||
|
||||
count = 0;
|
||||
while (base->anim_min > reletive || base->anim_max <= reletive)
|
||||
{
|
||||
base = base->anim_next;
|
||||
if (!base)
|
||||
Sys_Error ("R_TextureAnimation: broken cycle");
|
||||
if (++count > 100)
|
||||
Sys_Error ("R_TextureAnimation: infinite cycle");
|
||||
}
|
||||
}
|
||||
|
||||
batch->shader = base->shader;
|
||||
}
|
||||
|
||||
//q2 has direct control over the texture frames used, but typically has the client generate the frame (different flags autogenerate different ranges).
|
||||
void Mod_UpdateBatchShader_Q2 (struct batch_s *batch)
|
||||
{
|
||||
texture_t *base = batch->texture;
|
||||
int reletive;
|
||||
int frame = batch->ent->framestate.g[FS_REG].frame[0];
|
||||
if (batch->ent == &r_worldentity)
|
||||
frame = cl.time*2;
|
||||
|
||||
if (base->anim_total)
|
||||
{
|
||||
reletive = frame % base->anim_total;
|
||||
while (reletive --> 0)
|
||||
{
|
||||
base = base->anim_next;
|
||||
if (!base)
|
||||
Sys_Error ("R_TextureAnimation: broken cycle");
|
||||
}
|
||||
}
|
||||
|
||||
batch->shader = base->shader;
|
||||
}
|
||||
|
||||
/*
|
||||
batch->firstmesh is set only in and for this function, its cleared out elsewhere
|
||||
*/
|
||||
|
@ -2709,6 +2763,14 @@ static void Mod_Batches_Generate(model_t *mod)
|
|||
batch->lightmap[3] = surf->lightmaptexturenums[3];
|
||||
#endif
|
||||
batch->texture = surf->texinfo->texture;
|
||||
batch->shader = surf->texinfo->texture->shader;
|
||||
if (surf->texinfo->texture->alternate_anims || surf->texinfo->texture->anim_total)
|
||||
{
|
||||
if (mod->fromgame == fg_quake2)
|
||||
batch->buildmeshes = Mod_UpdateBatchShader_Q2;
|
||||
else
|
||||
batch->buildmeshes = Mod_UpdateBatchShader_Q1;
|
||||
}
|
||||
batch->next = mod->batches[sortid];
|
||||
batch->ent = &r_worldentity;
|
||||
batch->fog = surf->fog;
|
||||
|
|
|
@ -2242,7 +2242,7 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int sms
|
|||
if (!smesh->batches[tno].count)
|
||||
continue;
|
||||
tex = cl.worldmodel->shadowbatches[tno].tex;
|
||||
if (tex->shader->flags & SHADER_NODLIGHT)
|
||||
if (tex->shader->flags & SHADER_NODLIGHT) //FIXME: shadows not lights
|
||||
continue;
|
||||
BE_DrawMesh_List(tex->shader, smesh->batches[tno].count, smesh->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, &tex->shader->defaulttextures, 0);
|
||||
}
|
||||
|
@ -2588,6 +2588,7 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour)
|
|||
{
|
||||
int tno;
|
||||
texture_t *tex;
|
||||
shader_t *shader;
|
||||
shadowmesh_t *sm;
|
||||
|
||||
sm = light->worldshadowmesh;
|
||||
|
@ -2600,10 +2601,11 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour)
|
|||
if (!sm->batches[tno].count)
|
||||
continue;
|
||||
tex = cl.worldmodel->shadowbatches[tno].tex;
|
||||
if (tex->shader->flags & SHADER_NODLIGHT)
|
||||
shader = R_TextureAnimation(false, tex)->shader;
|
||||
if (shader->flags & SHADER_NODLIGHT)
|
||||
continue;
|
||||
//FIXME: it may be worth building a dedicated ebo
|
||||
BE_DrawMesh_List(tex->shader, sm->batches[tno].count, sm->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, &tex->shader->defaulttextures, 0);
|
||||
BE_DrawMesh_List(shader, sm->batches[tno].count, sm->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, &shader->defaulttextures, 0);
|
||||
RQuantAdd(RQUANT_LITFACES, sm->batches[tno].count);
|
||||
}
|
||||
|
||||
|
|
|
@ -10714,7 +10714,7 @@ void QCC_PR_ParseDefs (char *classname)
|
|||
isconstant = true;
|
||||
else if (QCC_PR_CheckKeyword(keyword_var, "var"))
|
||||
isvar = true;
|
||||
else if (!pr_scope && QCC_PR_CheckKeyword(keyword_var, "static"))
|
||||
else if (QCC_PR_CheckKeyword(keyword_var, "static"))
|
||||
isstatic = true;
|
||||
else if (!pr_scope && QCC_PR_CheckKeyword(keyword_var, "nonstatic"))
|
||||
isstatic = false;
|
||||
|
|
|
@ -4079,14 +4079,18 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
|
|||
if (newparm->type == ev_function)
|
||||
{
|
||||
if (isstatic)
|
||||
QCC_PR_ParseError(ERR_INTERNAL, "%s::%s static functions are not supported at this time.", classname, parmname);
|
||||
{
|
||||
isstatic = false;
|
||||
isnonvirt = true;
|
||||
// QCC_PR_ParseError(ERR_INTERNAL, "%s::%s static member functions are not supported at this time.", classname, parmname);
|
||||
}
|
||||
|
||||
if (!strcmp(classname, parmname))
|
||||
{
|
||||
if (isstatic)
|
||||
QCC_PR_ParseError(ERR_INTERNAL, "Constructor %s::%s may not be static.", classname, pr_token);
|
||||
if (!isvirt)
|
||||
isnonvirt = true;//silently promote constructors to nonvirt
|
||||
isnonvirt = true;//silently promote constructors to static
|
||||
}
|
||||
else if (!isvirt && !isnonvirt && !isstatic)
|
||||
{
|
||||
|
|
|
@ -10364,6 +10364,8 @@ void PR_DumpPlatform_f(void)
|
|||
{"noise3", ".string", QW|NQ},
|
||||
{"end_sys_fields", "void", QW|NQ|CS|MENU},
|
||||
|
||||
{"time", "float", MENU, "The current local time. Increases while paused."},
|
||||
|
||||
#define comfieldfloat(name,desc) {#name, ".float", FL, desc},
|
||||
#define comfieldvector(name,desc) {#name, ".vector", FL, desc},
|
||||
#define comfieldentity(name,desc) {#name, ".entity", FL, desc},
|
||||
|
|
|
@ -769,8 +769,8 @@ typedef struct
|
|||
|
||||
struct ftenet_connections_s *sockets;
|
||||
|
||||
int allocated_client_slots;
|
||||
client_t *clients;
|
||||
int allocated_client_slots; //number of entries in the clients array
|
||||
client_t *clients; //[svs.allocated_client_slots]
|
||||
int serverflags; // episode completion information
|
||||
|
||||
double last_heartbeat;
|
||||
|
|
|
@ -1491,7 +1491,7 @@ void SV_Status_f (void)
|
|||
Con_Printf ("name userid frags\n");
|
||||
Con_Printf (" address rate ping drop\n");
|
||||
Con_Printf (" ---------------- ---- ---- -----\n");
|
||||
for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
|
||||
for (i=0,cl=svs.clients ; i<svs.allocated_client_slots ; i++,cl++)
|
||||
{
|
||||
if (!cl->state)
|
||||
continue;
|
||||
|
@ -2059,7 +2059,7 @@ void SV_Snap (int uid)
|
|||
if (cl->userid == uid)
|
||||
break;
|
||||
}
|
||||
if (i >= MAX_CLIENTS)
|
||||
if (i >= svs.allocated_client_slots)
|
||||
{
|
||||
Con_TPrintf ("Couldn't find user number %i\n", uid);
|
||||
return;
|
||||
|
|
|
@ -310,7 +310,7 @@ void SV_LoadClientDemo_f (void)
|
|||
SV_BroadcastCommand ("changing\n"); //but this arrives BEFORE the serverdata
|
||||
|
||||
ohc = host_client;
|
||||
for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
|
||||
for (i=0, host_client = svs.clients ; i<svs.allocated_client_slots ; i++, host_client++)
|
||||
{
|
||||
if (host_client->state != cs_spawned)
|
||||
continue;
|
||||
|
@ -506,7 +506,7 @@ qboolean SV_ReadMVD (void)
|
|||
sv.democausesreconnect = false;
|
||||
svs.spawncount++;
|
||||
|
||||
for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
|
||||
for (i=0, host_client = svs.clients ; i<svs.allocated_client_slots ; i++, host_client++)
|
||||
{
|
||||
if (host_client->state != cs_spawned)
|
||||
continue;
|
||||
|
@ -525,7 +525,7 @@ qboolean SV_ReadMVD (void)
|
|||
{
|
||||
if (!svd.demofile)
|
||||
{ //demo ended.
|
||||
for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
|
||||
for (i=0, cl = svs.clients ; i<svs.allocated_client_slots ; i++, cl++)
|
||||
{
|
||||
cl->sendinfo = true;
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ qboolean SV_ReadMVD (void)
|
|||
break;
|
||||
// case dem_read: //baseline stuff
|
||||
case dem_single:
|
||||
for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
|
||||
for (i=0, cl = svs.clients ; i<svs.allocated_client_slots ; i++, cl++)
|
||||
{
|
||||
if (!cl->state)
|
||||
continue;
|
||||
|
@ -585,7 +585,7 @@ qboolean SV_ReadMVD (void)
|
|||
VFS_CLOSE(svd.demofile);
|
||||
svd.demofile = NULL;
|
||||
|
||||
for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
|
||||
for (i=0, host_client = svs.clients ; i<svs.allocated_client_slots ; i++, host_client++)
|
||||
{
|
||||
if (host_client->state != cs_spawned)
|
||||
continue;
|
||||
|
|
|
@ -2138,7 +2138,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t *
|
|||
clstate_t clst;
|
||||
extern float olddemotime, nextdemotime;
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
||||
{
|
||||
//FIXME: Add PVS stuff.
|
||||
|
||||
|
@ -2222,7 +2222,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t *
|
|||
clst.fteext = 0;//client->fteprotocolextensions;
|
||||
clst.zext = 0;//client->zquake_extensions;
|
||||
clst.vw_index = 0;
|
||||
clst.playernum = MAX_CLIENTS-1;
|
||||
clst.playernum = svs.allocated_client_slots-1;
|
||||
clst.isself = true;
|
||||
clst.modelindex = 0;
|
||||
clst.hull = 1;
|
||||
|
@ -2761,7 +2761,7 @@ static void SV_Snapshot_Build_Playback(client_t *client, packet_entities_t *pack
|
|||
if (!dement->modelindex)
|
||||
continue;
|
||||
|
||||
if (e >= 1 && e <= MAX_CLIENTS)
|
||||
if (e >= 1 && e <= svs.allocated_client_slots)
|
||||
continue;
|
||||
|
||||
if (pack->num_entities == pack->max_entities)
|
||||
|
|
|
@ -166,7 +166,7 @@ baseline will be transmitted
|
|||
continue;
|
||||
// create baselines for all player slots,
|
||||
// and any other edict that has a visible model
|
||||
if (entnum > MAX_CLIENTS && !svent->v->modelindex)
|
||||
if (entnum > svs.allocated_client_slots && !svent->v->modelindex)
|
||||
continue;
|
||||
|
||||
//
|
||||
|
@ -176,7 +176,7 @@ baseline will be transmitted
|
|||
VectorCopy (svent->v->angles, svent->baseline.angles);
|
||||
svent->baseline.frame = svent->v->frame;
|
||||
svent->baseline.skinnum = svent->v->skin;
|
||||
if (entnum > 0 && entnum <= MAX_CLIENTS)
|
||||
if (entnum > 0 && entnum <= svs.allocated_client_slots)
|
||||
{
|
||||
svent->baseline.colormap = entnum;
|
||||
svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl")&255;
|
||||
|
@ -1330,53 +1330,30 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
char crc[12];
|
||||
sprintf(crc, "%i", QCRC_Block(file, com_filesize));
|
||||
Info_SetValueForStarKey(svs.info, "*entfile", crc, MAX_SERVERINFO_STRING);
|
||||
switch(svs.gametype)
|
||||
{
|
||||
case GT_MAX:
|
||||
break;
|
||||
case GT_Q1QVM:
|
||||
case GT_PROGS:
|
||||
sv.world.edict_size = PR_LoadEnts(svprogfuncs, file, spawnflagmask);
|
||||
break;
|
||||
case GT_QUAKE2:
|
||||
#ifdef Q2SERVER
|
||||
ge->SpawnEntities(sv.name, file, startspot?startspot:"");
|
||||
#endif
|
||||
break;
|
||||
case GT_QUAKE3:
|
||||
break;
|
||||
case GT_HALFLIFE:
|
||||
#ifdef HLSERVER
|
||||
SVHL_SpawnEntities(file);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
BZ_Free(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info_SetValueForStarKey(svs.info, "*entfile", "", MAX_SERVERINFO_STRING);
|
||||
switch(svs.gametype)
|
||||
{
|
||||
case GT_MAX:
|
||||
break;
|
||||
case GT_Q1QVM:
|
||||
case GT_PROGS:
|
||||
sv.world.edict_size = PR_LoadEnts(svprogfuncs, sv.world.worldmodel->entities, spawnflagmask);
|
||||
break;
|
||||
case GT_QUAKE2:
|
||||
|
||||
switch(svs.gametype)
|
||||
{
|
||||
case GT_MAX:
|
||||
break;
|
||||
case GT_Q1QVM:
|
||||
case GT_PROGS:
|
||||
sv.world.edict_size = PR_LoadEnts(svprogfuncs, file?file :sv.world.worldmodel->entities, spawnflagmask);
|
||||
break;
|
||||
case GT_QUAKE2:
|
||||
#ifdef Q2SERVER
|
||||
ge->SpawnEntities(sv.name, sv.world.worldmodel->entities, startspot?startspot:"");
|
||||
ge->SpawnEntities(sv.name, file?file :sv.world.worldmodel->entities, startspot?startspot:"");
|
||||
#endif
|
||||
break;
|
||||
case GT_QUAKE3:
|
||||
break;
|
||||
case GT_HALFLIFE:
|
||||
break;
|
||||
case GT_QUAKE3:
|
||||
break;
|
||||
case GT_HALFLIFE:
|
||||
#ifdef HLSERVER
|
||||
SVHL_SpawnEntities(sv.world.worldmodel->entities);
|
||||
SVHL_SpawnEntities(file?file :sv.world.worldmodel->entities));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
|
|
|
@ -114,8 +114,8 @@ cvar_t allow_download_sounds = CVAR("allow_download_sounds", "1");
|
|||
cvar_t allow_download_demos = CVAR("allow_download_demos", "1");
|
||||
cvar_t allow_download_maps = CVAR("allow_download_maps", "1");
|
||||
cvar_t allow_download_anymap = CVAR("allow_download_pakmaps", "0");
|
||||
cvar_t allow_download_pakcontents = CVAR("allow_download_pakcontents", "1");
|
||||
cvar_t allow_download_root = CVAR("allow_download_root", "0");
|
||||
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. Does NOT implicitly allow downloading bsps, set allow_download_pakmaps to enable that.");
|
||||
cvar_t allow_download_root = CVAR("allow_download_root", "0", "If set, enables downloading from the root of the gamedir (not the basedir). This setting is dangerous as it can allow downloading configs.");
|
||||
cvar_t allow_download_textures = CVAR("allow_download_textures", "1");
|
||||
cvar_t allow_download_packages = CVAR("allow_download_packages", "1");
|
||||
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.");
|
||||
|
@ -1044,7 +1044,7 @@ void SVC_Status (void)
|
|||
SV_BeginRedirect (RD_PACKET, TL_FindLanguage(""));
|
||||
if (displayflags&STATUS_SERVERINFO)
|
||||
Con_Printf ("%s\n", svs.info);
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
||||
{
|
||||
cl = &svs.clients[i];
|
||||
if ((cl->state == cs_connected || cl->state == cs_spawned || cl->name[0]) && ((cl->spectator && displayflags&STATUS_SPECTATORS) || (!cl->spectator && displayflags&STATUS_PLAYERS)))
|
||||
|
@ -1107,7 +1107,7 @@ void SVC_GetInfo (char *challenge, int fullstatus)
|
|||
if (!sv_listen_nq.ival && !sv_listen_dp.ival)
|
||||
return;
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
||||
{
|
||||
cl = &svs.clients[i];
|
||||
if ((cl->state == cs_connected || cl->state == cs_spawned || cl->name[0]) && !cl->spectator)
|
||||
|
@ -1167,7 +1167,7 @@ void SVC_GetInfo (char *challenge, int fullstatus)
|
|||
resp[-1] = '\n'; //replace the null terminator that we already wrote
|
||||
|
||||
//on the following lines we have an entry for each client
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
||||
{
|
||||
cl = &svs.clients[i];
|
||||
if ((cl->state == cs_connected || cl->state == cs_spawned || cl->name[0]) && !cl->spectator)
|
||||
|
@ -1221,7 +1221,7 @@ void SVC_InfoQ2 (void)
|
|||
else
|
||||
{
|
||||
count = 0;
|
||||
for (i=0 ; i<maxclients.value ; i++)
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
||||
if (svs.clients[i].state >= cs_connected)
|
||||
count++;
|
||||
|
||||
|
@ -2517,7 +2517,7 @@ client_t *SVC_DirectConnect(void)
|
|||
|
||||
newcl->realip_ping = (((rand()^(rand()<<8) ^ *(int*)&realtime)&0xffffff)<<8) | (newcl-svs.clients);
|
||||
|
||||
if (newcl->istobeloaded)
|
||||
if (newcl->istobeloaded && newcl->edict)
|
||||
newcl->playerclass = newcl->edict->xv->playerclass;
|
||||
|
||||
// parse some info from the info strings
|
||||
|
@ -2902,7 +2902,7 @@ void SVC_RealIP (void)
|
|||
slotnum = atoi(Cmd_Argv(1));
|
||||
cookie = atoi(Cmd_Argv(2));
|
||||
|
||||
if (slotnum >= MAX_CLIENTS)
|
||||
if (slotnum >= svs.allocated_client_slots)
|
||||
{
|
||||
//a malitious user
|
||||
return;
|
||||
|
@ -4516,7 +4516,7 @@ void Master_Heartbeat (void)
|
|||
{
|
||||
// count active users
|
||||
active = 0;
|
||||
for (j=0 ; j<MAX_CLIENTS ; j++)
|
||||
for (j=0 ; j<svs.allocated_client_slots ; j++)
|
||||
if (svs.clients[j].state == cs_connected ||
|
||||
svs.clients[j].state == cs_spawned )
|
||||
active++;
|
||||
|
|
|
@ -802,7 +802,7 @@ void Rank_Refresh_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
|
||||
for (i=0, host_client = svs.clients ; i<svs.allocated_client_slots ; i++, host_client++)
|
||||
{
|
||||
if (host_client->state != cs_spawned)
|
||||
continue;
|
||||
|
|
|
@ -476,7 +476,7 @@ void VARGS SV_BroadcastCommand (char *fmt, ...)
|
|||
vsnprintf (string,sizeof(string), fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
|
||||
for (i=0, cl = svs.clients ; i<svs.allocated_client_slots ; i++, cl++)
|
||||
{
|
||||
if (cl->controller)
|
||||
continue;
|
||||
|
@ -2140,7 +2140,7 @@ void SV_UpdateToReliableMessages (void)
|
|||
{
|
||||
if (host_client->old_frags != (int)host_client->edict->v->frags)
|
||||
{
|
||||
for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
|
||||
for (j=0, client = svs.clients ; j<svs.allocated_client_slots ; j++, client++)
|
||||
{
|
||||
if (client->state < cs_connected)
|
||||
continue;
|
||||
|
|
|
@ -1617,7 +1617,7 @@ void SV_SpawnSpectator (void)
|
|||
// search for an info_playerstart to spawn the spectator at
|
||||
//this is only useful when a mod doesn't nativly support spectators. old qw on nq mods.
|
||||
|
||||
for (i=MAX_CLIENTS+1 ; i<sv.world.num_edicts ; i++)
|
||||
for (i=svs.allocated_client_slots+1 ; i<sv.world.num_edicts ; i++)
|
||||
{
|
||||
e = EDICT_NUM(svprogfuncs, i);
|
||||
if (!strcmp(PR_GetString(svprogfuncs, e->v->classname), "info_player_start"))
|
||||
|
@ -2307,7 +2307,7 @@ void SV_VoiceReadPacket(void)
|
|||
/*figure out which team members are meant to receive it*/
|
||||
for (j = 0; j < (MAX_CLIENTS+7)/8; j++)
|
||||
ring->receiver[j] = 0;
|
||||
for (j = 0, cl = svs.clients; j < sv.allocated_client_slots; j++, cl++)
|
||||
for (j = 0, cl = svs.clients; j < svs.allocated_client_slots; j++, cl++)
|
||||
{
|
||||
if (cl->state != cs_spawned && cl->state != cs_connected)
|
||||
continue;
|
||||
|
@ -2458,7 +2458,7 @@ void SV_Voice_Ignore_f(void)
|
|||
type = -1;
|
||||
}
|
||||
other = atoi(Cmd_Argv(1));
|
||||
if (other >= MAX_CLIENTS)
|
||||
if (other >= svs.allocated_client_slots)
|
||||
return;
|
||||
|
||||
switch(type)
|
||||
|
@ -2486,7 +2486,7 @@ void SV_Voice_Target_f(void)
|
|||
else if (*t >= '0' && *t <= '9')
|
||||
{
|
||||
other = atoi(t);
|
||||
if (other >= MAX_CLIENTS)
|
||||
if (other >= svs.allocated_client_slots)
|
||||
return;
|
||||
host_client->voice_target = VT_PLAYERSLOT0 + other;
|
||||
}
|
||||
|
@ -3334,7 +3334,7 @@ void SV_Pings_f (void)
|
|||
if (ISNQCLIENT(host_client))
|
||||
{
|
||||
char *s;
|
||||
ClientReliableWrite_Begin(host_client, svc_stufftext, 15+10*MAX_CLIENTS);
|
||||
ClientReliableWrite_Begin(host_client, svc_stufftext, 15+10*sv.allocated_client_slots);
|
||||
ClientReliableWrite_SZ(host_client, "pingplreport", 12);
|
||||
for (j = 0, client = svs.clients; j < sv.allocated_client_slots && j < host_client->max_net_clients; j++, client++)
|
||||
{
|
||||
|
@ -4784,7 +4784,7 @@ void SVNQ_Ping_f(void)
|
|||
//don't translate this, most advanced clients (including us) automate and parse them, the results being visible in the scoreboard and NOT the console.
|
||||
//translating these prints can thus confuse things greatly.
|
||||
SV_PrintToClient(host_client, PRINT_HIGH, "Client ping times:\n");
|
||||
for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
|
||||
for (i=0,cl=svs.clients ; i<sv.allocated_client_slots ; i++,cl++)
|
||||
{
|
||||
if (!cl->state)
|
||||
continue;
|
||||
|
|
|
@ -1322,7 +1322,7 @@ void SVHL_SpawnEntities(char *entstring)
|
|||
|
||||
//initialise globals
|
||||
SVHL_Globals.stringbase = "";
|
||||
SVHL_Globals.maxclients = MAX_CLIENTS;
|
||||
SVHL_Globals.maxclients = svs.allocated_client_slots;
|
||||
SVHL_Globals.deathmatch = deathmatch.value;
|
||||
SVHL_Globals.coop = coop.value;
|
||||
SVHL_Globals.serverflags = 0;
|
||||
|
|
|
@ -287,7 +287,7 @@ void SVQ2_EmitPacketEntities (q2client_frame_t *from, q2client_frame_t *to, size
|
|||
if (msg->cursize+128 > msg->maxsize)
|
||||
memcpy(newent, oldent, sizeof(*newent)); //too much data, so set the ent up as the same as the old, so it's sent next frame
|
||||
else
|
||||
MSGQ2_WriteDeltaEntity (oldent, newent, msg, false, newent->number <= MAX_CLIENTS);
|
||||
MSGQ2_WriteDeltaEntity (oldent, newent, msg, false, newent->number <= svs.allocated_client_slots);
|
||||
oldindex++;
|
||||
newindex++;
|
||||
continue;
|
||||
|
|
|
@ -92,7 +92,7 @@ static void VARGS PFQ2_Unicast (q2edict_t *ent, qboolean reliable)
|
|||
return;
|
||||
|
||||
p = Q2NUM_FOR_EDICT(ent);
|
||||
if (p < 1 || p > MAX_CLIENTS)
|
||||
if (p < 1 || p > svs.allocated_client_slots)
|
||||
return;
|
||||
|
||||
client = svs.clients + (p-1);
|
||||
|
@ -145,7 +145,7 @@ static void VARGS PFQ2_cprintf (q2edict_t *ent, int level, char *fmt, ...)
|
|||
if (ent)
|
||||
{
|
||||
n = Q2NUM_FOR_EDICT(ent);
|
||||
if (n < 1 || n > MAX_CLIENTS)
|
||||
if (n < 1 || n > svs.allocated_client_slots)
|
||||
{
|
||||
Sys_Error ("cprintf to a non-client");
|
||||
return;
|
||||
|
@ -183,7 +183,7 @@ static void VARGS PFQ2_centerprintf (q2edict_t *ent, char *fmt, ...)
|
|||
int n;
|
||||
|
||||
n = Q2NUM_FOR_EDICT(ent);
|
||||
if (n < 1 || n > MAX_CLIENTS)
|
||||
if (n < 1 || n > svs.allocated_client_slots)
|
||||
return; // Com_Error (ERR_DROP, "centerprintf to a non-client");
|
||||
|
||||
if (svs.clients[n-1].state < cs_connected)
|
||||
|
|
|
@ -3206,7 +3206,7 @@ void JCL_CheckClientCaps(jclient_t *jcl, buddy_t *buddy, bresource_t *bres)
|
|||
|
||||
//one of google's nodes. ONLY google get this fucked up evil hack because they're the only ones that are arrogant enough to not bother to query what that 'ext' actually means - and then to not even bother to tell other clients.
|
||||
//every other client is expected to have its act together and not fuck up like this.
|
||||
googlefuckedup = !!strstr(bres->client_node, "google.com") || !!strstr(bres->client_node, "android.com");
|
||||
googlefuckedup = bres->client_node && (!!strstr(bres->client_node, "google.com") || !!strstr(bres->client_node, "android.com"));
|
||||
|
||||
//and ask for info about each extension too. which should only be used if the specified version isn't a hash.
|
||||
if (bres->client_hash && !*bres->client_hash)
|
||||
|
|
Loading…
Reference in a new issue