diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 56b65994a..d2e58a390 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -862,6 +862,7 @@ readit: olddemotime = demotime; + net_from.type = NA_INVALID; return 1; } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 3a38ce81c..c876fdf37 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -2263,11 +2263,15 @@ void CL_Packet_f (void) if (Cmd_FromGamecode()) //some mvd servers stuffcmd a packet command which lets them know which ip the client is from. { //unfortunatly, 50% of servers are badly configured. + if (cls.demoplayback) + { + Con_DPrintf ("Not sending realip packet from demo\n"); + return; + } + if (adr.type == NA_IP) - if (adr.address.ip[0] == 127) - if (adr.address.ip[1] == 0) - if (adr.address.ip[2] == 0) - if (adr.address.ip[3] == 1) + if ((adr.address.ip[0] == 127 && adr.address.ip[1] == 0 && adr.address.ip[2] == 0 && adr.address.ip[3] == 1) || + (adr.address.ip[0] == 0 && adr.address.ip[1] == 0 && adr.address.ip[2] == 0 && adr.address.ip[3] == 0)) { adr.address.ip[0] = cls.netchan.remote_address.address.ip[0]; adr.address.ip[1] = cls.netchan.remote_address.address.ip[1]; @@ -2613,32 +2617,36 @@ void CL_ConnectionlessPacket (void) Con_TPrintf ("redirect to %s\n", data); NET_StringToAdr(data, PORT_QWSERVER, &adr); data = "\xff\xff\xff\xffgetchallenge\n"; - connectinfo.istransfer = true; - connectinfo.adr = adr; - NET_SendPacket (NS_CLIENT, strlen(data), data, &adr); + + if (NET_CompareAdr(&connectinfo.adr, &net_from)) + { + connectinfo.istransfer = true; + connectinfo.adr = adr; + NET_SendPacket (NS_CLIENT, strlen(data), data, &adr); + } return; } else if (!strcmp(s, "reject")) { //generic rejection. stop trying. char *data = MSG_ReadStringLine(); Con_Printf ("reject\n%s\n", data); - connectinfo.trying = false; + if (NET_CompareAdr(&connectinfo.adr, &net_from)) + connectinfo.trying = false; return; } else if (!strcmp(s, "badname")) { //rejected purely because of player name - Con_Printf ("f%s\n", s); - connectinfo.trying = false; - return; + if (NET_CompareAdr(&connectinfo.adr, &net_from)) + connectinfo.trying = false; } else if (!strcmp(s, "badaccount")) { //rejected because username or password is wrong - Con_Printf ("f%s\n", s); - connectinfo.trying = false; - return; + if (NET_CompareAdr(&connectinfo.adr, &net_from)) + connectinfo.trying = false; } - else - Con_Printf ("f%s", s); + + Con_Printf ("f%s\n", s); + return; } if (c == S2C_CHALLENGE) @@ -2916,6 +2924,8 @@ void CL_ConnectionlessPacket (void) #ifdef Q2CLIENT client_connect: //fixme: make function #endif + if (net_from.type == NA_INVALID) + return; //I've found a qizmo demo that contains one of these. its best left ignored. if (!NET_CompareAdr(&connectinfo.adr, &net_from)) { @@ -2980,7 +2990,7 @@ client_connect: //fixme: make function { char cmdtext[2048]; - if (net_from.type != net_local_cl_ipadr.type || net_from.type != NA_IP + if (net_from.type == NA_INVALID || net_from.type != net_local_cl_ipadr.type || net_from.type != NA_IP || ((*(unsigned *)net_from.address.ip != *(unsigned *)net_local_cl_ipadr.address.ip) && (*(unsigned *)net_from.address.ip != htonl(INADDR_LOOPBACK)))) { Con_TPrintf ("Command packet from remote host. Ignored.\n"); @@ -3047,7 +3057,7 @@ client_connect: //fixme: make function } //happens in demos - if (c == svc_disconnect && cls.demoplayback != DPB_NONE) + if (c == svc_disconnect && cls.demoplayback != DPB_NONE && net_from.type == NA_INVALID) { Host_EndGame ("End of Demo"); return; diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 59d7bca9f..7e28ef63a 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -383,9 +383,9 @@ void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state VectorCopy (from->velocity, pmove.velocity); VectorCopy (from->gravitydir, pmove.gravitydir); - if (!(pmove.velocity[0] == 0) && !(pmove.velocity[0] != 0)) + if (IS_NAN(pmove.velocity[0])) { - Con_Printf("nan velocity!\n"); + Con_DPrintf("nan velocity!\n"); pmove.velocity[0] = 0; pmove.velocity[1] = 0; pmove.velocity[2] = 0; diff --git a/engine/client/m_single.c b/engine/client/m_single.c index db040d387..3bd3411f8 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -445,14 +445,19 @@ typedef struct demoitem_s { char name[1]; } demoitem_t; +typedef struct { + int fsroot; //FS_SYSTEM, FS_GAME, FS_GAMEONLY. if FS_SYSTEM, executed command will have a leading # + char path[MAX_OSPATH]; + char selname[MAX_OSPATH]; +} demoloc_t; + typedef struct { menucustom_t *list; demoitem_t *selected; demoitem_t *firstitem; + demoloc_t *fs; int pathlen; - char path[MAX_OSPATH]; - int fsroot; //FS_SYSTEM, FS_GAME, FS_GAMEONLY. if FS_SYSTEM, executed command will have a leading # char *command[64]; //these let the menu be used for nearly any sort of file browser. char *ext[64]; @@ -524,34 +529,34 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key, unsigned case K_UPARROW: if (info->selected && info->selected->prev) info->selected = info->selected->prev; - return true; + break; case K_MWHEELDOWN: case K_DOWNARROW: if (info->selected && info->selected->next) info->selected = info->selected->next; - return true; + break; case K_HOME: info->selected = info->items; - return true; + break; case K_END: info->selected = info->items; while(info->selected->next) info->selected = info->selected->next; - return true; + break; case K_PGUP: for (i = 0; i < 10; i++) { if (info->selected && info->selected->prev) info->selected = info->selected->prev; } - return true; + break; case K_PGDN: for (i = 0; i < 10; i++) { if (info->selected && info->selected->next) info->selected = info->selected->next; } - return true; + break; case K_ENTER: case K_KP_ENTER: if (info->selected) @@ -568,13 +573,20 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key, unsigned if (extnum == info->numext) //wasn't on our list of extensions. extnum = 0; - Cbuf_AddText(va("%s \"%s%s\"\n", info->command[extnum], (info->fsroot==FS_SYSTEM)?"#":"", info->selected->name), RESTRICT_LOCAL); - M_RemoveMenu(menu); + Cbuf_AddText(va("%s \"%s%s\"\n", info->command[extnum], (info->fs->fsroot==FS_SYSTEM)?"#":"", info->selected->name), RESTRICT_LOCAL); + M_RemoveMenu(menu); + return true; } } - return true; + break; + default: + return false; } - return false; + if (info->selected) + Q_strncpyz(info->fs->selname, info->selected->name, sizeof(info->fs->selname)); + else + Q_strncpyz(info->fs->selname, "", sizeof(info->fs->selname)); + return true; } static int QDECL DemoAddItem(const char *filename, qofs_t size, time_t modified, void *parm, searchpathfuncs_t *spath) @@ -730,23 +742,27 @@ static void ShowDemoMenu (menu_t *menu, const char *path) char *s; char match[256]; - if (*path == '/') - path++; - Q_strncpyz(info->path, path, sizeof(info->path)); - if (info->fsroot == FS_GAME) + if (path != info->fs->path) + { + if (*path == '/') + path++; + Q_strncpyz(info->fs->path, path, sizeof(info->fs->path)); + } + + if (info->fs->fsroot == FS_GAME) { if (!strcmp(path, "../")) { - FS_NativePath("", FS_ROOT, info->path, sizeof(info->path)); - info->fsroot = FS_SYSTEM; - while((s = strchr(info->path, '\\'))) + FS_NativePath("", FS_ROOT, info->fs->path, sizeof(info->fs->path)); + info->fs->fsroot = FS_SYSTEM; + while((s = strchr(info->fs->path, '\\'))) *s = '/'; } } - while (!strcmp(info->path+strlen(info->path)-3, "../")) + while (!strcmp(info->fs->path+strlen(info->fs->path)-3, "../")) { c = 0; - for (s = info->path+strlen(info->path)-3; s >= info->path; s--) + for (s = info->fs->path+strlen(info->fs->path)-3; s >= info->fs->path; s--) { if (*s == '/') { @@ -757,71 +773,85 @@ static void ShowDemoMenu (menu_t *menu, const char *path) } } if (c<2) - *info->path = '\0'; + *info->fs->path = '\0'; } info->selected = NULL; - info->pathlen = strlen(info->path); + info->pathlen = strlen(info->fs->path); M_Demo_Flush(menu->data); - if (info->fsroot == FS_SYSTEM) + if (info->fs->fsroot == FS_SYSTEM) { - s = strchr(info->path, '/'); + s = strchr(info->fs->path, '/'); if (s && strchr(s+1, '/')) { - Q_snprintfz(match, sizeof(match), "%s../", info->path); + Q_snprintfz(match, sizeof(match), "%s../", info->fs->path); DemoAddItem(match, 0, 0, info, NULL); } } - else if (*info->path) + else if (*info->fs->path) { - Q_snprintfz(match, sizeof(match), "%s../", info->path); + Q_snprintfz(match, sizeof(match), "%s../", info->fs->path); DemoAddItem(match, 0, 0, info, NULL); } - else if (info->fsroot == FS_GAME) + else if (info->fs->fsroot == FS_GAME) { Q_snprintfz(match, sizeof(match), "../"); DemoAddItem(match, 0, 0, info, NULL); } - if (info->fsroot == FS_SYSTEM) + if (info->fs->fsroot == FS_SYSTEM) { - if (info->path) - Q_snprintfz(match, sizeof(match), "%s*", info->path); + if (info->fs->path) + Q_snprintfz(match, sizeof(match), "%s*", info->fs->path); else Q_snprintfz(match, sizeof(match), "/*"); Sys_EnumerateFiles("", match, DemoAddItem, info, NULL); } else { - Q_snprintfz(match, sizeof(match), "%s*", info->path); + Q_snprintfz(match, sizeof(match), "%s*", info->fs->path); COM_EnumerateFiles(match, DemoAddItem, info); } M_Demo_Flatten(info); } +void M_Demo_Reselect(demomenu_t *info, const char *name) +{ + demoitem_t *item; + for(item = info->items; item; item = item->next) + { + if (!strcmp(item->name, name)) + { + info->selected = item; + return; + } + } +} void M_Menu_Demos_f (void) { demomenu_t *info; - menu_t *menu; + menu_t *menu; + static demoloc_t mediareenterloc = {FS_GAME}; Key_Dest_Add(kdm_menu); + Key_Dest_Remove(kdm_console); m_state = m_complex; menu = M_CreateMenu(sizeof(demomenu_t)); menu->remove = M_Demo_Remove; info = menu->data; - info->fsroot = FS_GAME; + info->fs = &mediareenterloc; info->numext = 0; - info->command[info->numext] = "playdemo"; + info->command[info->numext] = "closemenu;playdemo"; info->ext[info->numext++] = ".qwd"; - info->command[info->numext] = "playdemo"; + info->command[info->numext] = "closemenu;playdemo"; info->ext[info->numext++] = ".dem"; - info->command[info->numext] = "playdemo"; + info->command[info->numext] = "closemenu;playdemo"; info->ext[info->numext++] = ".dm2"; - info->command[info->numext] = "playdemo"; + info->command[info->numext] = "closemenu;playdemo"; info->ext[info->numext++] = ".mvd"; - info->command[info->numext] = "playdemo"; + info->command[info->numext] = "closemenu;playdemo"; info->ext[info->numext++] = ".mvd.gz"; //there are also qizmo demos (.qwz) out there... //we don't support them, but if we were to ask quizmo to decode them for us, we could do. @@ -845,13 +875,15 @@ void M_Menu_Demos_f (void) menu->selecteditem = (menuoption_t*)info->list; - ShowDemoMenu(menu, ""); + ShowDemoMenu(menu, info->fs->path); + M_Demo_Reselect(info, info->fs->selname); } void M_Menu_MediaFiles_f (void) { demomenu_t *info; - menu_t *menu; + menu_t *menu; + static demoloc_t mediareenterloc = {FS_GAME}; Key_Dest_Add(kdm_menu); m_state = m_complex; @@ -860,7 +892,7 @@ void M_Menu_MediaFiles_f (void) menu->remove = M_Demo_Remove; info = menu->data; - info->fsroot = FS_GAME; + info->fs = &mediareenterloc; info->ext[0] = ".m3u"; info->command[0] = "mediaplaylist"; @@ -889,6 +921,7 @@ void M_Menu_MediaFiles_f (void) menu->selecteditem = (menuoption_t*)info->list; - ShowDemoMenu(menu, ""); + ShowDemoMenu(menu, info->fs->path); + M_Demo_Reselect(info, info->fs->selname); } #endif diff --git a/engine/client/render.h b/engine/client/render.h index 58ed971e0..7eedb5a59 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -80,23 +80,25 @@ typedef unsigned int skinid_t; //skin 0 is 'unused' struct dlight_s; typedef struct entity_s { + //FIXME: instancing somehow. separate visentity+visinstance. only viable with full glsl though. + //will need to generate a vbo somehow for the instances. + int keynum; // for matching entities in different frames vec3_t origin; - vec3_t angles; + vec3_t angles; // fixme: should be redundant. vec3_t axis[3]; vec4_t shaderRGBAf; /*colormod+alpha, available for shaders to mix*/ float shaderTime; /*timestamp, for syncing shader times to spawns*/ vec3_t glowmod; /*meant to be a multiplier for the fullbrights*/ - int light_known; /*bsp lighting has been caled*/ + int light_known; /*bsp lighting has been calced*/ vec3_t light_avg; /*midpoint level*/ vec3_t light_range; /*avg + this = max, avg - this = min*/ vec3_t light_dir; - vec3_t oldorigin; - vec3_t oldangles; - + vec3_t oldorigin; /*for q2/q3 beams*/ + struct model_s *model; // NULL = no model int skinnum; // for Alias models skinid_t customskin; // quake3 style skins diff --git a/engine/client/valid.c b/engine/client/valid.c index 5ef902172..b0ef72013 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -389,6 +389,7 @@ rulesetrule_t rulesetrules_strict[] = { {"r_shadow_realtime_world", "0"}, /*static lighting can be used to cast shadows around corners*/ {"ruleset_allow_in", "0"}, {"r_projection", "0"}, + {"gl_shadeq1_name", "*"}, {NULL} }; @@ -408,6 +409,7 @@ rulesetrule_t rulesetrules_nqr[] = { {"sbar_teamstatus", "0"}, {"ruleset_allow_in", "0"}, {"r_projection", "0"}, + {"gl_shadeq1_name", "*"}, {NULL} }; diff --git a/engine/client/view.c b/engine/client/view.c index 2e1274706..dbc21cfa3 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1540,6 +1540,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam) qboolean haveinfo; unsigned int textflags; int h; + char *pname; static vec4_t healthcolours[] = { @@ -1600,6 +1601,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam) health = pl->statsf[STAT_HEALTH]; armour = pl->statsf[STAT_ARMOR]; items = pl->stats[STAT_ITEMS]; + pname = pl->name; haveinfo = true; } else @@ -1607,12 +1609,16 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam) health = pl->tinfo.health; armour = pl->tinfo.armour; items = pl->tinfo.items; + pname = ((*pl->tinfo.nick)?pl->tinfo.nick:(cl.teamfortress?"-":pl->name)); haveinfo = pl->tinfo.time > cl.time; } - y -= 8; - len = COM_ParseFunString(textflags, pl->name, buffer, sizeof(buffer), false) - buffer; - Draw_ExpandedString(x - len*4, y, buffer); + if (strcmp(pname, "-")) //a tinfo nick of - hides names. this can be used for TF to hide names for spies. + { + y -= 8; + len = COM_ParseFunString(textflags, pname, buffer, sizeof(buffer), false) - buffer; + Draw_ExpandedString(x - len*4, y, buffer); + } if (!haveinfo) return; //we don't trust the info that we have, so no ids. @@ -1705,6 +1711,7 @@ void R_DrawNameTags(void) lerpents_t *le; qboolean isteam; char *ourteam; + int ourcolour; extern cvar_t r_showfields, r_projection; @@ -1791,9 +1798,15 @@ void R_DrawNameTags(void) return; if (r_refdef.playerview->cam_state != CAM_FREECAM && r_refdef.playerview->cam_spec_track >= 0) + { ourteam = cl.players[r_refdef.playerview->cam_spec_track].team; + ourcolour = cl.players[r_refdef.playerview->cam_spec_track].rbottomcolor; + } else + { ourteam = cl.players[r_refdef.playerview->playernum].team; + ourcolour = cl.players[r_refdef.playerview->playernum].rbottomcolor; + } for (i = 0; i < cl.allocated_client_slots; i++) { @@ -1826,14 +1839,16 @@ void R_DrawNameTags(void) if (i == Cam_TrackNum(r_refdef.playerview)) //no tag for the player that you're tracking, either. continue; - if (!cl.teamplay || !scr_autoid_team.ival || strcmp(cl.players[i].team, ourteam)) - { + if (!cl.teamplay || !scr_autoid_team.ival) + isteam = false; + else if (cl.teamfortress && !cl.spectator) //teamfortress should go by their colours instead, because spies. primarily this is to allow enemy spies to appear through walls as well as your own team (note that the qc will also need tinfo stuff for tf, to avoid issues with just checking player names). + isteam = cl.players[i].rbottomcolor == ourcolour; + else + isteam = !strcmp(cl.players[i].team, ourteam); + + if (!isteam) if (!cl.spectator && !cls.demoplayback || !scr_autoid.ival) continue; //only show our team when playing, too cheaty otherwise. - isteam = false; - } - else - isteam = true; SCR_DrawAutoID(nametagorg[i], &cl.players[i], isteam); } diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 3b9ab3603..14f0b493a 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -313,10 +313,10 @@ qboolean NET_CompareAdr (netadr_t *a, netadr_t *b) } #endif - Sys_Error("NET_CompareAdr: Bad address type"); + Con_Printf("NET_CompareAdr: Bad address type\n"); return false; } - + /* =================== NET_CompareBaseAdr diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 58fbe42b7..7be3987c2 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -932,6 +932,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) Con_DPrintf("GLSL available\n"); } + + if (gl_config.arb_shader_objects) + qglGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &gl_config.maxattribs); #endif qglGetProgramBinary = NULL; @@ -1999,25 +2002,35 @@ GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLh qglBindAttribLocationARB(program, VATTR_VERTEX1, "v_position1"); qglBindAttribLocationARB(program, VATTR_COLOUR, "v_colour"); -#if MAXRLIGHTMAPS > 1 - qglBindAttribLocationARB(program, VATTR_COLOUR2, "v_colour2"); - qglBindAttribLocationARB(program, VATTR_COLOUR3, "v_colour3"); - qglBindAttribLocationARB(program, VATTR_COLOUR4, "v_colour4"); -#endif qglBindAttribLocationARB(program, VATTR_TEXCOORD, "v_texcoord"); qglBindAttribLocationARB(program, VATTR_LMCOORD, "v_lmcoord"); -#if MAXRLIGHTMAPS > 1 - qglBindAttribLocationARB(program, VATTR_LMCOORD2, "v_lmcoord2"); - qglBindAttribLocationARB(program, VATTR_LMCOORD3, "v_lmcoord3"); - qglBindAttribLocationARB(program, VATTR_LMCOORD4, "v_lmcoord4"); -#endif qglBindAttribLocationARB(program, VATTR_NORMALS, "v_normal"); qglBindAttribLocationARB(program, VATTR_SNORMALS, "v_svector"); qglBindAttribLocationARB(program, VATTR_TNORMALS, "v_tvector"); - qglBindAttribLocationARB(program, VATTR_BONENUMS, "v_bone"); - qglBindAttribLocationARB(program, VATTR_BONEWEIGHTS, "v_weight"); qglBindAttribLocationARB(program, VATTR_VERTEX2, "v_position2"); + //the following MAY not be valid in gles2. + if (gl_config.maxattribs > VATTR_BONENUMS) + qglBindAttribLocationARB(program, VATTR_BONENUMS, "v_bone"); + if (gl_config.maxattribs > VATTR_BONEWEIGHTS) + qglBindAttribLocationARB(program, VATTR_BONEWEIGHTS, "v_weight"); +#if MAXRLIGHTMAPS > 1 + if (gl_config.maxattribs > VATTR_COLOUR2) + qglBindAttribLocationARB(program, VATTR_COLOUR2, "v_colour2"); + if (gl_config.maxattribs > VATTR_COLOUR3) + qglBindAttribLocationARB(program, VATTR_COLOUR3, "v_colour3"); + if (gl_config.maxattribs > VATTR_COLOUR4) + qglBindAttribLocationARB(program, VATTR_COLOUR4, "v_colour4"); +#endif +#if MAXRLIGHTMAPS > 1 + if (gl_config.maxattribs > VATTR_LMCOORD2) + qglBindAttribLocationARB(program, VATTR_LMCOORD2, "v_lmcoord2"); + if (gl_config.maxattribs > VATTR_LMCOORD3) + qglBindAttribLocationARB(program, VATTR_LMCOORD3, "v_lmcoord3"); + if (gl_config.maxattribs > VATTR_LMCOORD4) + qglBindAttribLocationARB(program, VATTR_LMCOORD4, "v_lmcoord4"); +#endif + qglLinkProgramARB(program); return program; } @@ -2170,6 +2183,13 @@ qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned ver = 120; #endif } + if ((permu & PERMUTATION_SKELETAL) && gl_config.maxattribs < 10) + return false; //can happen in gles2 +#if MAXRLIGHTMAPS > 1 + if ((permu & PERMUTATION_LIGHTSTYLES) && gl_config.maxattribs < 16) + return false; //can happen in gles2 +#endif + prog->permu[permu].handle = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, tcs, tes, geom, frag, noerrors, blobfile); if (prog->permu[permu].handle.glsl.handle) return true; diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 522a2bebb..1f01752c9 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -220,6 +220,7 @@ qboolean GL_CheckExtension(char *extname); typedef struct { float glversion; int maxglslversion; + int maxattribs; //max generic attributes. probably only 16 on nvidia. qboolean nofixedfunc; qboolean gles; qboolean webgl_ie; //workaround ie webgl bugs/omissions. diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 33ec383b1..e8f6778a6 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -315,21 +315,24 @@ typedef struct enum{ PERMUTATION_GENERIC = 0, - PERMUTATION_BUMPMAP = 1, - PERMUTATION_FULLBRIGHT = 2, - PERMUTATION_UPPERLOWER = 4, - PERMUTATION_REFLECTCUBEMASK = 8, + PERMUTATION_BUMPMAP = 1, //FIXME: make argument somehow + PERMUTATION_FULLBRIGHT = 2, //FIXME: make argument somehow + PERMUTATION_UPPERLOWER = 4, //FIXME: make argument somehow + PERMUTATION_REFLECTCUBEMASK = 8, //FIXME: make argument somehow PERMUTATION_SKELETAL = 16, - PERMUTATION_FOG = 32, + PERMUTATION_FOG = 32, //FIXME: remove. PERMUTATION_FRAMEBLEND = 64, #if MAXRLIGHTMAPS > 1 - PERMUTATION_LIGHTSTYLES = 128, + PERMUTATION_LIGHTSTYLES = 128, //FIXME: make argument #endif PERMUTATIONS = 256 }; enum shaderattribs_e { + //GLES2 has a limit of 8. + //GL2 has a limit of 16. + //vendors may provide more. VATTR_VERTEX1=0, //NOTE: read the comment about VATTR_LEG_VERTEX VATTR_VERTEX2=1, VATTR_COLOUR=2, diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 35094c6f4..8f9468a0e 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -9768,7 +9768,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"con_printf", PF_Fixme, 0, 0, 0, 392, D("void(string conname, string messagefmt, ...)", "Prints onto a named console.")}, {"con_draw", PF_Fixme, 0, 0, 0, 393, D("void(string conname, vector pos, vector size, float fontsize)", "Draws the named console.")}, {"con_input", PF_Fixme, 0, 0, 0, 394, D("float(string conname, float inevtype, float parama, float paramb, float paramc)", "Forwards input events to the named console. Mouse updates should be absolute only.")}, - {"cvar_unsaved", PF_Fixme, 0, 0, 0, 0, D("float()", "Returns true if any archived cvar has an unsaved value.")}, + {"cvars_haveunsaved",PF_Fixme, 0, 0, 0, 0, D("float()", "Returns true if any archived cvar has an unsaved value.")}, //end fte extras //DP extras