diff --git a/engine/Makefile b/engine/Makefile index bf2ef660e..d330c05d4 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -327,7 +327,6 @@ CLIENT_OBJS = \ cl_cg.o \ clq3_parse.o \ pr_csqc.o \ - pr_skelobj.o \ console.o \ image.o \ keys.o \ diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 6264286ca..1334721d4 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1925,7 +1925,7 @@ void CL_TransitionEntities (void) /*and transition players too*/ { float frac, a1, a2; - int i,j, p; + int i, p; vec3_t move; lerpents_t *le; player_state_t *pnew, *pold; @@ -1935,12 +1935,17 @@ void CL_TransitionEntities (void) frac = (servertime-packold->servertime)/(packnew->servertime-packold->servertime); pnew = &cl.frames[newf].playerstate[0]; pold = &cl.frames[oldf].playerstate[0]; - for (p = 0; p < MAX_CLIENTS; p++, pnew++, pold++) + for (p = 0; p < cl.allocated_client_slots; p++, pnew++, pold++) { + if (pnew->messagenum != cl.parsecount) + continue; le = &cl.lerpplayers[p]; VectorSubtract(pnew->origin, pold->origin, move); + if (DotProduct(move, move) > 120*120) + frac = 1; + //lerp based purely on the packet times, for (i = 0; i < 3; i++) { @@ -3105,26 +3110,7 @@ void CL_LinkPlayers (void) // only predict half the move to minimize overruns msec = 500*(playertime - state->state_time); - /* - if (1) - { - float f; - int i; - f = (cl.gametime-cl.servertime)/(cl.gametime-cl.oldgametime); - if (f<0) - f=0; - if (f>1) - f=1; - for (i=0 ; i<3 ; i++) - { - ent->origin[i] = state->origin[i] + - f * (fromf->playerstate[j].origin[i] - state->origin[i]); - } - - } - else - */ if (pnum < cl.splitclients) { //this is a local player } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 85ab10a51..fa338b79e 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -654,6 +654,7 @@ void CL_CheckForResend (void) netadr_t adr; char data[2048]; double t1, t2; + int contype = 0; #ifndef CLIENTONLY if (!cls.state && sv.state) @@ -799,8 +800,19 @@ void CL_CheckForResend (void) Con_TPrintf (TLC_CONNECTINGTO, cls.servername); + contype |= 1; /*always try qw type connections*/ +// if ((connect_tries&3)==3) || (connect_defaultport==26000)) + contype |= 2; /*try nq connections periodically (or if its the default nq port)*/ + + /*DP, QW, Q2, Q3*/ + if (contype & 1) + { + Q_snprintfz (data, sizeof(data), "%c%c%c%cgetchallenge\n", 255, 255, 255, 255); + NET_SendPacket (NS_CLIENT, strlen(data), data, adr); + } + /*NQ*/ #ifdef NQPROT - if (((connect_tries&3)==3) != (connect_defaultport==26000)) + if (contype & 2) { sizebuf_t sb; memset(&sb, 0, sizeof(sb)); @@ -823,18 +835,13 @@ void CL_CheckForResend (void) MSG_WriteByte(&sb, 0); /*flags*/ MSG_WriteLong(&sb, strtoul(password.string, NULL, 0)); /*password*/ - /*so dual-protocol servers can send a more useful reply*/ + /*FTE servers will detect this string and treat it as a qw challenge instead (if it allows qw clients), so protocol choice is deterministic*/ MSG_WriteString(&sb, "getchallenge"); *(int*)sb.data = LongSwap(NETFLAG_CTL | sb.cursize); NET_SendPacket (NS_CLIENT, sb.cursize, sb.data, adr); } - else #endif - { - Q_snprintfz (data, sizeof(data), "%c%c%c%cgetchallenge\n", 255, 255, 255, 255); - NET_SendPacket (NS_CLIENT, strlen(data), data, adr); - } connect_tries++; } @@ -1602,6 +1609,9 @@ void CL_CheckServerInfo(void) cls.allow_lightmapgamma=true; s = Info_ValueForKey(cl.serverinfo, "allow_fish"); + if (cl.spectator || cls.demoplayback || !*s || atoi(s)) + cls.allow_postproc=true; + s = Info_ValueForKey(cl.serverinfo, "allow_postproc"); if (cl.spectator || cls.demoplayback || !*s || atoi(s)) cls.allow_postproc=true; @@ -2280,6 +2290,8 @@ void CL_ConnectionlessPacket (void) if (c == S2C_CHALLENGE) { + static unsigned int lasttime = 0xdeadbeef; + unsigned int curtime = Sys_Milliseconds(); unsigned long pext = 0, pext2 = 0, huffcrc=0; Con_TPrintf (TLC_S2C_CHALLENGE); @@ -2287,9 +2299,15 @@ void CL_ConnectionlessPacket (void) COM_Parse(s); if (!strcmp(com_token, "hallengeResponse")) { + /*Quake3*/ #ifdef Q3CLIENT if (cls.protocol == CP_QUAKE3 || cls.protocol == CP_UNKNOWN) { + /*throttle*/ + if (curtime - lasttime < 500) + return; + lasttime = curtime; + cls.protocol = CP_QUAKE3; cls.challenge = atoi(s+17); CL_SendConnectPacket (0, 0, 0/*, ...*/); @@ -2307,7 +2325,13 @@ void CL_ConnectionlessPacket (void) } else if (!strcmp(com_token, "hallenge")) { + /*Quake2 or Darkplaces*/ char *s2; + /*throttle*/ + if (curtime - lasttime < 500) + return; + lasttime = curtime; + for (s2 = s+9; *s2; s2++) { if ((*s2 < '0' || *s2 > '9') && *s2 != '-') @@ -2354,6 +2378,9 @@ void CL_ConnectionlessPacket (void) goto client_connect; } #endif + + /*no idea, assume a QuakeWorld challenge response ('c' packet)*/ + else if (cls.protocol == CP_QUAKEWORLD || cls.protocol == CP_UNKNOWN) cls.protocol = CP_QUAKEWORLD; else @@ -2361,6 +2388,12 @@ void CL_ConnectionlessPacket (void) Con_Printf("\nChallenge from another protocol, ignoring QW challenge\n"); return; } + + /*throttle*/ + if (curtime - lasttime < 500) + return; + lasttime = curtime; + cls.challenge = atoi(s); for(;;) @@ -2778,7 +2811,7 @@ void CL_ReadPackets (void) if (cls.netchan.incoming_sequence > cls.netchan.outgoing_sequence) { //server should not be responding to packets we have not sent yet - Con_Printf("Server is from the future! (%i packets)\n", cls.netchan.incoming_sequence - cls.netchan.outgoing_sequence); + Con_DPrintf("Server is from the future! (%i packets)\n", cls.netchan.incoming_sequence - cls.netchan.outgoing_sequence); cls.netchan.outgoing_sequence = cls.netchan.incoming_sequence; } MSG_ChangePrimitives(cls.netchan.netprim); @@ -3484,7 +3517,9 @@ double Host_Frame (double time) RSpeedLocals(); if (setjmp (host_abort) ) + { return 0; // something bad happened, or the server disconnected + } realframetime = time = Media_TweekCaptureFrameTime(time); diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index 09d288cc3..3a31836b1 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -15,6 +15,7 @@ enum { MT_BAD, //this would be an error MT_MASTERHTTPNQ, //an http/ftp based master server with NQ servers MT_MASTERHTTPQW,//an http/ftp based master server with QW servers + MT_MASTERHTTPJSON,//quakeone's server listing MT_BCASTQW, //-1status MT_BCASTQ2, //-1status MT_BCASTQ3, diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 922a2cd76..b34cb99f2 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1962,6 +1962,7 @@ void CLDP_ParseDownloadFinished(char *s) Cmd_TokenizeString(s+1, false, false); VFS_CLOSE (cls.downloadqw); + FS_FlushFSHash(); cls.downloadqw = FS_OpenVFS (cls.downloadtempname, "rb", FS_GAME); if (cls.downloadqw) @@ -4408,10 +4409,13 @@ char *CL_ParseChat(char *text, player_info_t **player) S_LocalSound (cl_enemychatsound.string); } - if (cl_nofake.value == 1 || (cl_nofake.value == 2 && flags != 2)) { - for (p = s; *p; p++) - if (*p == 13 || (*p == 10 && p[1])) - *p = ' '; + if (flags) + { + if (cl_nofake.value == 1 || (cl_nofake.value == 2 && flags != 2)) { + for (p = s; *p; p++) + if (*p == 13 || (*p == 10 && p[1])) + *p = ' '; + } } msgflags = flags; @@ -4436,6 +4440,7 @@ void CL_ParsePrint(char *msg, int level) Stats_ParsePrintLine(printtext); TP_SearchForMsgTriggers(printtext, level); + *msg = '\n'; msg++; memmove(printtext, msg, strlen(msg)+1); diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 11fa9be6e..703d6e8bb 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -853,6 +853,13 @@ void CL_PredictMovePNum (int pnum) if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV)|| cl.fixangle[pnum] || cl.paused)) { + if (cl_lerp_players.ival && !cls.demoplayback) + { + lerpents_t *le = &cl.lerpplayers[spec_track[pnum]]; + org = le->origin; + vel = vec3_origin; + } + fixedorg: VectorCopy (vel, cl.simvel[pnum]); VectorCopy (org, cl.simorg[pnum]); diff --git a/engine/client/client.h b/engine/client/client.h index 815df6b19..323596690 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1246,7 +1246,10 @@ int CIN_RunCinematic (struct cinematics_s *cin, qbyte **outdata, int *outwidth, typedef struct cin_s cin_t; #ifdef NOMEDIA -#define Media_Playing false +#define Media_Playing() false +#define Media_Init() 0 +#define Media_PlayingFullScreen() false +#define Media_PlayFilm(n) false #else /*media playing system*/ qboolean Media_PlayingFullScreen(void); diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 9e8b1b8fc..fb188d2ca 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -4,28 +4,23 @@ #include "cl_master.h" //filtering -cvar_t sb_hideempty = SCVARF("sb_hideempty", "0", CVAR_ARCHIVE); -cvar_t sb_hidenotempty = SCVARF("sb_hidenotempty", "0", CVAR_ARCHIVE); -cvar_t sb_hidefull = SCVARF("sb_hidefull", "0", CVAR_ARCHIVE); -cvar_t sb_hidedead = SCVARF("sb_hidedead", "1", CVAR_ARCHIVE); +static cvar_t sb_hideempty = SCVARF("sb_hideempty", "0", CVAR_ARCHIVE); +static cvar_t sb_hidenotempty = SCVARF("sb_hidenotempty", "0", CVAR_ARCHIVE); +static cvar_t sb_hidefull = SCVARF("sb_hidefull", "0", CVAR_ARCHIVE); +static cvar_t sb_hidedead = SCVARF("sb_hidedead", "1", CVAR_ARCHIVE); cvar_t sb_hidequake2 = SCVARF("sb_hidequake2", "1", CVAR_ARCHIVE); cvar_t sb_hidequake3 = SCVARF("sb_hidequake3", "1", CVAR_ARCHIVE); cvar_t sb_hidenetquake = SCVARF("sb_hidenetquake", "1", CVAR_ARCHIVE); cvar_t sb_hidequakeworld = SCVARF("sb_hidequakeworld","0", CVAR_ARCHIVE); -cvar_t sb_maxping = SCVARF("sb_maxping", "0", CVAR_ARCHIVE); -cvar_t sb_gamedir = SCVARF("sb_gamedir", "", CVAR_ARCHIVE); -cvar_t sb_mapname = SCVARF("sb_mapname", "", CVAR_ARCHIVE); -cvar_t sb_showping = SCVARF("sb_showping", "1", CVAR_ARCHIVE); -cvar_t sb_showaddress = SCVARF("sb_showaddress", "0", CVAR_ARCHIVE); -cvar_t sb_showmap = SCVARF("sb_showmap", "0", CVAR_ARCHIVE); -cvar_t sb_showgamedir = SCVARF("sb_showgamedir", "0", CVAR_ARCHIVE); -cvar_t sb_showplayers = SCVARF("sb_showplayers", "1", CVAR_ARCHIVE); -cvar_t sb_showfraglimit = SCVARF("sb_showfraglimit","0", CVAR_ARCHIVE); -cvar_t sb_showtimelimit = SCVARF("sb_showtimelimit","0", CVAR_ARCHIVE); +static cvar_t sb_showping = SCVARF("sb_showping", "1", CVAR_ARCHIVE); +static cvar_t sb_showaddress = SCVARF("sb_showaddress", "0", CVAR_ARCHIVE); +static cvar_t sb_showmap = SCVARF("sb_showmap", "0", CVAR_ARCHIVE); +static cvar_t sb_showgamedir = SCVARF("sb_showgamedir", "0", CVAR_ARCHIVE); +static cvar_t sb_showplayers = SCVARF("sb_showplayers", "1", CVAR_ARCHIVE); +static cvar_t sb_showfraglimit = SCVARF("sb_showfraglimit","0", CVAR_ARCHIVE); +static cvar_t sb_showtimelimit = SCVARF("sb_showtimelimit","0", CVAR_ARCHIVE); -cvar_t sb_filterkey = SCVARF("sb_filterkey", "hostname", CVAR_ARCHIVE); -cvar_t sb_filtervalue = SCVARF("sb_filtervalue", "", CVAR_ARCHIVE); extern cvar_t slist_writeserverstxt; extern cvar_t slist_cacheinfo; @@ -43,10 +38,6 @@ void M_Serverlist_Init(void) Cvar_Register(&sb_hidenetquake, grp); Cvar_Register(&sb_hidequakeworld, grp); - Cvar_Register(&sb_maxping, grp); - Cvar_Register(&sb_gamedir, grp); - Cvar_Register(&sb_mapname, grp); - Cvar_Register(&sb_showping, grp); Cvar_Register(&sb_showaddress, grp); Cvar_Register(&sb_showmap, grp); @@ -59,840 +50,6 @@ void M_Serverlist_Init(void) Cvar_Register(&slist_cacheinfo, grp); } -enum { - SLISTTYPE_SERVERS, - SLISTTYPE_FAVORITES, - SLISTTYPE_SOURCES, - SLISTTYPE_OPTIONS //must be last -} slist_option; - -int slist_numoptions; -int slist_firstoption; - -int slist_type; - - - -static void NM_Print (int cx, int cy, qbyte *str) -{ - Draw_AltFunString(cx, cy, str); -} - -static void NM_PrintWhite (int cx, int cy, qbyte *str) -{ - Draw_FunString(cx, cy, str); -} - -static void NM_PrintColoured (int cx, int cy, int colour, qbyte *str) -{ -#ifdef warningmsg -#pragma warningmsg("NM_PrintColoured: needs reimplementing") -#endif -/* - while (*str) - { - NM_DrawColouredCharacter (cx, cy, (*str) | (colour<special & SS_FAVORITE)) - return true; -#ifdef Q2CLIENT - if (sb_hidequake2.value) -#endif - if (server->special & SS_QUAKE2) - return true; -#ifdef Q2CLIENT - if (sb_hidequake3.value) -#endif - if (server->special & SS_QUAKE3) - return true; -#ifdef NQPROT - if (sb_hidenetquake.value) -#endif - if (server->special & (SS_NETQUAKE|SS_DARKPLACES)) - return true; - if (sb_hidequakeworld.value) - if (!(server->special & (SS_QUAKE2|SS_QUAKE3|SS_NETQUAKE|SS_DARKPLACES))) - return true; - if (sb_hideempty.value) - if (!server->players) - return true; - if (sb_hidenotempty.value) - if (server->players) - return true; - if (sb_hidefull.value) - if (server->players == server->maxplayers) - return true; - if (sb_hidedead.value) - if (server->maxplayers == 0) - return true; - if (sb_maxping.value) - if (server->ping > sb_maxping.value) - return true; - if (*sb_gamedir.string) - if (strcmp(server->gamedir, sb_gamedir.string)) - return true; - if (*sb_mapname.string) - if (!strstr(server->map, sb_mapname.string)) - return true; - - return false; -} - -qboolean M_MasterIsFiltered(master_t *mast) -{ -#ifndef Q2CLIENT - if (mast->type == MT_BCASTQ2 || mast->type == MT_SINGLEQ2 || mast->type == MT_MASTERQ2) - return true; -#endif -#ifndef NQPROT - if (mast->type == MT_BCASTNQ || mast->type == MT_SINGLENQ) - return true; -#endif - return false; -} - - -void M_DrawOneServer (int inity) -{ - char key[512]; - char value[512]; - char *o; - int l, i; - char *s; - - int miny=8*5; - int y=8*(5-selectedserver.linenum); - - miny += inity; - y += inity; - - if (!selectedserver.detail) - { - NM_Print (0, y, "No details\n"); - return; - } - - s = selectedserver.detail->info; - - if (*s == '\\') - s++; - while (*s) - { - o = key; - while (*s && *s != '\\') - *o++ = *s++; - - l = o - key; -// if (l < 20) -// { -// memset (o, ' ', 20-l); -// key[20] = 0; -// } -// else - *o = 0; - if (y>=miny) - NM_Print (0, y, va("%19s", key)); - - if (!*s) - { - if (y>=miny) - NM_Print (0, y, "MISSING VALUE\n"); - return; - } - - o = value; - s++; - while (*s && *s != '\\') - *o++ = *s++; - *o = 0; - - if (*s) - s++; - if (y>=miny) - NM_Print (320/2, y, va("%s\n", value)); - - y+=8; - } - - for ( i = 0; i < selectedserver.detail->numplayers; i++) - { - if (y>=miny) - { - R2D_ImagePaletteColour(Sbar_ColorForMap(selectedserver.detail->players[i].topc), 1.0); - R2D_FillBlock (12, y, 28, 4); - R2D_ImagePaletteColour(Sbar_ColorForMap(selectedserver.detail->players[i].botc), 1.0); - R2D_FillBlock (12, y+4, 28, 4); - R2D_ImageColours(1.0, 1.0, 1.0, 1.0); - NM_PrintWhite (12, y, va("%3i", selectedserver.detail->players[i].frags)); - NM_Print (12+8*4, y, selectedserver.detail->players[i].name); - } - y+=8; - } - - if (y<=miny) //whoops, there was a hole at the end, try scrolling up. - selectedserver.linenum--; -} - -int M_AddColumn (int right, int y, char *text, int maxchars, int colour, int highlight) -{ - int left; - left = right - maxchars*8; - if (left < 0) - return right; - - right = left; - -#ifdef warningmsg -#pragma warningmsg("M_AddColumn: needs reimplementing") -#endif -/* - if (highlight >= 0) - { - while (*text && maxchars>0) - { - NM_DrawColouredCharacter (right, y, (*(unsigned char *)text) | (colour<0) - { - NM_DrawColouredCharacter (right, y, (*(unsigned char *)text) | (colour<next) - if (M_IsFiltered(server)) - filtered++; - else - slist_numoptions++; - - if (!slist_numoptions) - { - char *text, *text2="", *text3=""; - if (filtered) - { - if (slist_type == SLISTTYPE_FAVORITES) - { - text = "Highlight a server"; - text2 = "and press \'f\'"; - text3 = "to add it to this list"; - } - else - text = "All servers were filtered out"; - } - else - text = "No servers found"; - NM_PrintColoured((vid.width-strlen(text)*8)/2, 8*5, COLOR_WHITE, text); - NM_PrintColoured((vid.width-strlen(text2)*8)/2, 8*5+8, COLOR_WHITE, text2); - NM_PrintColoured((vid.width-strlen(text3)*8)/2, 8*5+16, COLOR_WHITE, text3); - - return; - } - - - if (slist_option >= slist_numoptions) - slist_option = slist_numoptions-1; - op = vid.height/2/8; - op/=2; - op=slist_option-op; - snum = op; - - - if (selectedserver.inuse == true) - { - M_DrawOneServer(8*5); - return; - } - - if (op < 0) - op = 0; - if (snum < 0) - snum = 0; - //find the server that we want - for (server = firstserver; op>0; server=server->next) - { - if (M_IsFiltered(server)) - continue; - op--; - } - - y = 8*2; - x = vid.width; - if (sb_showtimelimit.value) - x = M_AddColumn(x, y, "tl", 3, COLOR_RED, -1); - if (sb_showfraglimit.value) - x = M_AddColumn(x, y, "fl", 3, COLOR_RED, -1); - if (sb_showplayers.value) - x = M_AddColumn(x, y, "plyrs", 6, COLOR_RED, -1); - if (sb_showmap.value) - x = M_AddColumn(x, y, "map", 9, COLOR_RED, -1); - if (sb_showgamedir.value) - x = M_AddColumn(x, y, "gamedir", 9, COLOR_RED, -1); - if (sb_showping.value) - x = M_AddColumn(x, y, "png", 4, COLOR_RED, -1); - if (sb_showaddress.value) - x = M_AddColumn(x, y, "address", 21, COLOR_RED, -1); - x = M_AddColumn(x, y, "name", x/8-1, COLOR_RED, -1); - - y = 8*3; - while(server) - { - if (M_IsFiltered(server)) - { - server = server->next; - continue; //doesn't count - } - - if (y > vid.height/2) - break; - - if (slist_option == snum) - highlight = COLOR_DARKBLUE; - else - highlight = -1; - - if (*server->name) - { - if (server->special & SS_FAVORITE) - colour = COLOR_GREEN; - else if (server->special & SS_FTESERVER) - colour = COLOR_RED; - else if (server->special & SS_QUAKE2) - colour = COLOR_YELLOW; - else if (server->special & SS_QUAKE3) - colour = COLOR_BLUE; - else if (server->special & SS_NETQUAKE) - colour = COLOR_GREY; - else if (server->special & SS_PROXY) - colour = COLOR_MAGENTA; - else - colour = COLOR_WHITE; - - x = vid.width; - - // make sure we have a highlighted background - if (highlight >= 0) - { - R2D_ImageColours(consolecolours[highlight].fr, consolecolours[highlight].fg, consolecolours[highlight].fb, 1.0); - R2D_FillBlock(8, y, vid.width-16, 8); - } - - if (sb_showtimelimit.value) - x = M_AddColumn(x, y, va("%i", server->tl), 3, colour, highlight); //time limit - if (sb_showfraglimit.value) - x = M_AddColumn(x, y, va("%i", server->fl), 3, colour, highlight); //frag limit - if (sb_showplayers.value) - x = M_AddColumn(x, y, va("%i/%i", server->players, server->maxplayers), 6, colour, highlight); - if (sb_showmap.value) - x = M_AddColumn(x, y, server->map, 9, colour, highlight); - if (sb_showgamedir.value) - x = M_AddColumn(x, y, server->gamedir, 9, colour, highlight); - if (sb_showping.value) - x = M_AddColumn(x, y, va("%i", server->ping), 4, colour, highlight); //frag limit - if (sb_showaddress.value) - x = M_AddColumn(x, y, NET_AdrToString(adr, sizeof(adr), server->adr), 21, colour, highlight); - x = M_AddColumn(x, y, server->name, x/8-1, colour, highlight); - } - - if (*server->name) - y+=8; - - server = server->next; - - snum++; - } - - selectedserver.inuse=2; - M_DrawOneServer(vid.height/2-4*8); -} - -void M_DrawSources (void) -{ - int snum=0; - int op; - int y = 3*8; - master_t *mast; - int clr; - - slist_numoptions = 0; - //find total sources. - for (mast = master; mast; mast = mast->next) - slist_numoptions++; - - if (!slist_numoptions) - { - char *text; - if (0)//filtered) - text = "All servers were filtered out\n"; - else - text = "No sources were found\n"; - NM_PrintColoured((vid.width-strlen(text)*8)/2, 8*5, COLOR_WHITE, text); - - return; - } - - if (slist_option >= slist_numoptions) - slist_option = slist_numoptions-1; - op=slist_option-vid.height/2/8; - snum = op; - - if (op < 0) - op = 0; - if (snum < 0) - snum = 0; - //find the server that we want - for (mast = master; op>0; mast=mast->next) - { - if (M_MasterIsFiltered(mast)) - continue; - op--; - } - - for (; mast; mast = mast->next) - { - if (M_MasterIsFiltered(mast)) - continue; - - switch (mast->type) - { - case MT_MASTERHTTPNQ: - case MT_MASTERHTTPQW: - clr = COLOR_YELLOW; - break; - case MT_MASTERQW: - case MT_MASTERQ2: - clr = COLOR_WHITE; - break; - case MT_SINGLENQ: - case MT_SINGLEQW: - case MT_SINGLEQ2: - clr = COLOR_GREEN; - break; - default: - clr = COLOR_RED; - } - - if (slist_option == snum) // highlight it if selected - NM_PrintHighlighted(46, y, clr, COLOR_DARKBLUE, va("%s", mast->name)); - else - NM_PrintColoured(46, y, clr, va("%s", mast->name)); - - y+=8; - snum++; - } -} - -#define NUMSLISTOPTIONS (8+7+4) - struct { - char *title; - cvar_t *cvar; - int type; - } options[NUMSLISTOPTIONS] = { - {"Hide Empty", &sb_hideempty}, - {"Hide Not Empty", &sb_hidenotempty}, - {"Hide Full", &sb_hidefull}, - {"Hide Dead", &sb_hidedead}, - {"Hide Quake 2", &sb_hidequake2}, - {"Hide Quake 3", &sb_hidequake3}, - {"Hide Quake 1", &sb_hidenetquake}, - {"Hide QuakeWorld", &sb_hidequakeworld}, - - {"Show pings", &sb_showping}, - {"Show Addresses", &sb_showaddress}, - {"Show map", &sb_showmap}, - {"Show Game Dir", &sb_showgamedir}, - {"Show Players", &sb_showplayers}, - {"Show Fraglimit", &sb_showfraglimit}, - {"Show Timelimit", &sb_showtimelimit}, - - {"Max ping", &sb_maxping, 1}, - {"GameDir", &sb_gamedir, 2}, - {"Using map", &sb_mapname, 2}, - {"Game", &com_protocolname, 2} - }; - -void M_DrawSListOptions (void) -{ - int c; - int op; - char *s; - - slist_numoptions = NUMSLISTOPTIONS; - - for (op = 0; op < NUMSLISTOPTIONS; op++) - { - if (options[op].cvar->value>0 || (*options[op].cvar->string && *options[op].cvar->string != '0')) - c = COLOR_RED; - else - c = COLOR_WHITE; - - switch(options[op].type) - { - default: - s = options[op].title; - break; - case 1: - if (!options[op].cvar->value) - { - s = va("%s ", options[op].title); - break; - } - case 2: - s = va("%s %s", options[op].title, options[op].cvar->string); - break; - } - - if (slist_option == op) // selected - NM_PrintHighlighted(46, op*8+8*3, c, COLOR_DARKBLUE, s); - else - NM_PrintColoured(46, op*8+8*3, c, s); - } -} - -void M_SListOptions_Key (int key) -{ - if (key == K_UPARROW) - { - slist_option--; - if (slist_option<0) - slist_option=0; - return; - } - else if (key == K_DOWNARROW) - { - slist_option++; - if (slist_option >= slist_numoptions) - slist_option = slist_numoptions-1; - return; - } - - switch(options[slist_option].type) - { - default: - if (key == K_ENTER) - { - if (options[slist_option].cvar->value) - Cvar_Set(options[slist_option].cvar, "0"); - else - Cvar_Set(options[slist_option].cvar, "1"); - } - break; - case 1: - if (key >= '0' && key <= '9') - Cvar_SetValue(options[slist_option].cvar, options[slist_option].cvar->value*10+key-'0'); - else if (key == K_DEL) - Cvar_SetValue(options[slist_option].cvar, 0); - else if (key == K_BACKSPACE) - Cvar_SetValue(options[slist_option].cvar, (int)options[slist_option].cvar->value/10); - break; - case 2: - if ((key >= '0' && key <= '9') || (key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')|| key == '_') - Cvar_Set(options[slist_option].cvar, va("%s%c", options[slist_option].cvar->string, key)); - else if (key == K_DEL) - Cvar_Set(options[slist_option].cvar, ""); - else if (key == K_BACKSPACE) //FIXME - Cvar_Set(options[slist_option].cvar, ""); - break; - } -} - - -void M_DrawServers(void) -{ -#define NUMSLISTHEADERS (SLISTTYPE_OPTIONS+1) - char *titles[NUMSLISTHEADERS] = { - "Servers", - "Favorites", - "Sources", -// "Players", - "Options" - }; - int snum=0; - - int width, lofs; - - NET_CheckPollSockets(); //see if we were told something important. - - width = vid.width / NUMSLISTHEADERS; - lofs = width/2 - 7*4; - for (snum = 0; snum < NUMSLISTHEADERS; snum++) - { - if (slist_type == snum) - NM_PrintHighlighted(width*snum+width/2 - strlen(titles[snum])*4, 0, COLOR_WHITE, COLOR_DARKBLUE, titles[snum]); - else - NM_PrintColoured(width*snum+width/2 - strlen(titles[snum])*4, 0, COLOR_WHITE, titles[snum]); - } - NM_PrintColoured(8, 8, COLOR_WHITE, "\35"); - for (snum = 16; snum < vid.width-16; snum+=8) - NM_PrintColoured(snum, 8, COLOR_WHITE, "\36"); - NM_PrintColoured(snum, 8, COLOR_WHITE, "\37"); - - switch(slist_type) - { - case SLISTTYPE_SERVERS: - case SLISTTYPE_FAVORITES: - M_DrawServerList(); - break; - case SLISTTYPE_SOURCES: - M_DrawSources (); - break; - case SLISTTYPE_OPTIONS: - M_DrawSListOptions (); - break; - } -} - -serverinfo_t *M_FindCurrentServer(void) -{ - serverinfo_t *server; - int op = slist_option; - for (server = firstserver; server; server = server->next) - { - if (M_IsFiltered(server)) - continue; //doesn't count - if (!op--) - return server; - } - return NULL; -} - -master_t *M_FindCurrentMaster(void) -{ - master_t *mast; - int op = slist_option; - - for (mast = master; mast; mast = mast->next) - { - if (M_MasterIsFiltered(mast)) - continue; - if (!op--) - return mast; - } - return NULL; -} - -void M_SListKey(int key) -{ - char adr[MAX_ADR_SIZE]; - - if (key == K_ESCAPE) - { -// if (selectedserver.inuse) -// selectedserver.inuse = false; -// else - M_Menu_MultiPlayer_f(); - return; - } - else if (key == K_LEFTARROW) - { - slist_type--; - if (slist_type<0) - slist_type=0; - - selectedserver.linenum--; - if (selectedserver.linenum<0) - selectedserver.linenum=0; - - slist_numoptions=0; - return; - } - else if (key == K_RIGHTARROW) - { - slist_type++; - if (slist_type>NUMSLISTHEADERS-1) - slist_type=NUMSLISTHEADERS-1; - - selectedserver.linenum++; - - slist_numoptions = 0; - return; - } - else if (key == 'q') - selectedserver.linenum--; - else if (key == 'a') - selectedserver.linenum++; - - if (!slist_numoptions) - return; - - if (slist_type == SLISTTYPE_OPTIONS) - { - M_SListOptions_Key(key); - return; - } - - if (key == K_UPARROW) - { - slist_option--; - if (slist_option<0) - slist_option=0; - - if (slist_type == SLISTTYPE_SERVERS || slist_type == SLISTTYPE_FAVORITES) - SListOptionChanged(M_FindCurrentServer()); //go for these early. - } - else if (key == K_DOWNARROW) - { - slist_option++; - if (slist_option >= slist_numoptions) - slist_option = slist_numoptions-1; - - if (slist_type == SLISTTYPE_SERVERS || slist_type == SLISTTYPE_FAVORITES) - SListOptionChanged(M_FindCurrentServer()); //go for these early. - } - else if (key == K_PGDN) - { - slist_option+=10; - if (slist_option >= slist_numoptions) - slist_option = slist_numoptions-1; - - if (slist_type == SLISTTYPE_SERVERS || slist_type == SLISTTYPE_FAVORITES) - SListOptionChanged(M_FindCurrentServer()); //go for these early. - } - else if (key == K_PGUP) - { - slist_option-=10; - if (slist_option<0) - slist_option=0; - - if (slist_type == SLISTTYPE_SERVERS || slist_type == SLISTTYPE_FAVORITES) - SListOptionChanged(M_FindCurrentServer()); //go for these early. - } - else if (key == 'r') - MasterInfo_Refresh(); - else if (key == K_SPACE) - { - if (slist_type == SLISTTYPE_SERVERS || slist_type == SLISTTYPE_FAVORITES) - { - selectedserver.inuse = !selectedserver.inuse; - if (selectedserver.inuse) - SListOptionChanged(M_FindCurrentServer()); - } - } - else if (key == 'c') - { - Sys_SaveClipboard(NET_AdrToString(adr, sizeof(adr), selectedserver.adr)); - } - else if (key == 'f') - { - serverinfo_t *server; - if (slist_type == SLISTTYPE_SERVERS) //add to favorites - { - server = M_FindCurrentServer(); - if (server) - { - server->special |= SS_FAVORITE; - MasterInfo_WriteServers(); - } - } - if (slist_type == SLISTTYPE_FAVORITES) //remove from favorites - { - server = M_FindCurrentServer(); - if (server) - { - server->special &= ~SS_FAVORITE; - MasterInfo_WriteServers(); - } - } - } - else if (key==K_ENTER || key == 's' || key == 'j') - { - serverinfo_t *server; - if (slist_type == SLISTTYPE_SERVERS || slist_type == SLISTTYPE_FAVORITES) - { - if (!selectedserver.inuse) - { - selectedserver.inuse = true; - SListOptionChanged(M_FindCurrentServer()); - return; - } - server = M_FindCurrentServer(); - if (!server) - return; //ah. off the end. - - if (key == 's') - Cbuf_AddText("spectator 1\n", RESTRICT_LOCAL); - else if (key == 'j') - Cbuf_AddText("spectator 0\n", RESTRICT_LOCAL); - - if (server->special & SS_NETQUAKE) - Cbuf_AddText(va("nqconnect %s\n", NET_AdrToString(adr, sizeof(adr), server->adr)), RESTRICT_LOCAL); - else - Cbuf_AddText(va("connect %s\n", NET_AdrToString(adr, sizeof(adr), server->adr)), RESTRICT_LOCAL); - - M_ToggleMenu_f(); - M_ToggleMenu_f(); - } - else if (slist_type == SLISTTYPE_SOURCES) - { - MasterInfo_Request(M_FindCurrentMaster(), true); - } - - return; - } -} - - - - - - - - - - - - - typedef struct { int visibleslots; int scrollpos; @@ -909,7 +66,7 @@ typedef struct { menupicture_t *mappic; } serverlist_t; -void SL_DrawColumnTitle (int *x, int y, int xlen, int mx, char *str, qboolean recolor, qbyte clr, qboolean *filldraw) +static void SL_DrawColumnTitle (int *x, int y, int xlen, int mx, char *str, qboolean recolor, qbyte clr, qboolean *filldraw) { int xmin; @@ -932,7 +89,7 @@ void SL_DrawColumnTitle (int *x, int y, int xlen, int mx, char *str, qboolean re *x -= xlen + 8; } -void SL_TitlesDraw (int x, int y, menucustom_t *ths, menu_t *menu) +static void SL_TitlesDraw (int x, int y, menucustom_t *ths, menu_t *menu) { int sf = Master_GetSortField(); extern int mousecursor_x, mousecursor_y; @@ -957,7 +114,7 @@ void SL_TitlesDraw (int x, int y, menucustom_t *ths, menu_t *menu) SL_DrawColumnTitle(NULL, y, x, mx, "hostname ", (sf==SLKEY_NAME), clr, &filldraw); } -qboolean SL_TitlesKey (menucustom_t *ths, menu_t *menu, int key) +static qboolean SL_TitlesKey (menucustom_t *ths, menu_t *menu, int key) { int x; extern int mousecursor_x, mousecursor_y; @@ -999,7 +156,7 @@ typedef enum { MAX_SERVERTYPES } servertypes_t; -float serverbackcolor[MAX_SERVERTYPES * 2][3] = +static float serverbackcolor[MAX_SERVERTYPES * 2][3] = { {0.08, 0.08, 0.08}, // default {0.16, 0.16, 0.16}, @@ -1019,7 +176,7 @@ float serverbackcolor[MAX_SERVERTYPES * 2][3] = {0.02, 0.26, 0.26} }; -float serverhighlight[MAX_SERVERTYPES][3] = +static float serverhighlight[MAX_SERVERTYPES][3] = { {0.35, 0.35, 0.45}, // Default {0.60, 0.30, 0.30}, // FTE Server @@ -1031,7 +188,7 @@ float serverhighlight[MAX_SERVERTYPES][3] = {0.10, 0.60, 0.60} // Favorite }; -servertypes_t flagstoservertype(int flags) +static servertypes_t flagstoservertype(int flags) { if (flags & SS_FAVORITE) return ST_FAVORITE; @@ -1042,8 +199,10 @@ servertypes_t flagstoservertype(int flags) else return ST_PROXY; } +#ifdef _DEBUG if (flags & SS_FTESERVER) return ST_FTESERVER; +#endif if ((flags & SS_NETQUAKE) || (flags & SS_DARKPLACES)) return ST_NETQUAKE; if (flags & SS_QUAKE2) @@ -1054,7 +213,7 @@ servertypes_t flagstoservertype(int flags) return ST_NORMALQW; } -void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) +static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) { extern int mousecursor_x, mousecursor_y; serverlist_t *info = (serverlist_t*)(menu + 1); @@ -1100,7 +259,7 @@ void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) Draw_FunStringWidth(0, y, si->name, x); } } -qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key) +static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key) { static int lastclick; int curtime; @@ -1175,7 +334,7 @@ joinserver: } return false; } -void SL_PreDraw (menu_t *menu) +static void SL_PreDraw (menu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); NET_CheckPollSockets(); @@ -1185,7 +344,7 @@ void SL_PreDraw (menu_t *menu) snprintf(info->refreshtext, sizeof(info->refreshtext), "Refresh - %u of %u\n", Master_NumPolled(), Master_TotalCount()); info->numslots = Master_NumSorted(); } -qboolean SL_Key (int key, menu_t *menu) +static qboolean SL_Key (int key, menu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); @@ -1247,7 +406,7 @@ qboolean SL_Key (int key, menu_t *menu) return true; } -void SL_ServerPlayer (int x, int y, menucustom_t *ths, menu_t *menu) +static void SL_ServerPlayer (int x, int y, menucustom_t *ths, menu_t *menu) { if (selectedserver.inuse) { @@ -1259,14 +418,14 @@ void SL_ServerPlayer (int x, int y, menucustom_t *ths, menu_t *menu) R2D_FillBlock (x, y, 28, 4); R2D_ImagePaletteColour (Sbar_ColorForMap(selectedserver.detail->players[i].botc), 1.0); R2D_FillBlock (x, y+4, 28, 4); - NM_PrintWhite (x, y, va("%3i", selectedserver.detail->players[i].frags)); + Draw_FunStringWidth (x, y, va("%3i", selectedserver.detail->players[i].frags), 28); Draw_FunStringWidth (x+28, y, selectedserver.detail->players[i].name, 12*8); } } } -void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) +static void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); @@ -1332,7 +491,7 @@ void SL_SliderDraw (int x, int y, menucustom_t *ths, menu_t *menu) info->sliderpressed = false; } } -qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key) +static qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key) { if (key == K_MOUSE1) { @@ -1363,7 +522,7 @@ qboolean SL_SliderKey (menucustom_t *ths, menu_t *menu, int key) return false; } -void CalcFilters(menu_t *menu) +static void CalcFilters(menu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); @@ -1379,7 +538,7 @@ void CalcFilters(menu_t *menu) if (info->filter[7]) Master_SetMaskInteger(false, SLKEY_FREEPLAYERS, 0, SLIST_TEST_NOTEQUAL); } -qboolean SL_ReFilter (menucheck_t *option, menu_t *menu, chk_set_t set) +static qboolean SL_ReFilter (menucheck_t *option, menu_t *menu, chk_set_t set) { serverlist_t *info = (serverlist_t*)(menu + 1); switch(set) @@ -1407,7 +566,7 @@ qboolean SL_ReFilter (menucheck_t *option, menu_t *menu, chk_set_t set) return true; } -void SL_Remove (menu_t *menu) +static void SL_Remove (menu_t *menu) { serverlist_t *info = (serverlist_t*)(menu + 1); @@ -1420,7 +579,7 @@ void SL_Remove (menu_t *menu) Cvar_Set(&sb_hidefull, info->filter[7]?"1":"0"); } -qboolean SL_DoRefresh (menuoption_t *opt, menu_t *menu, int key) +static qboolean SL_DoRefresh (menuoption_t *opt, menu_t *menu, int key) { MasterInfo_Refresh(); return true; @@ -1525,9 +684,9 @@ void M_Menu_ServerList2_f(void) MasterInfo_Refresh(); } -float quickconnecttimeout; +static float quickconnecttimeout; -void M_QuickConnect_PreDraw(menu_t *menu) +static void M_QuickConnect_PreDraw(menu_t *menu) { serverinfo_t *best = NULL; serverinfo_t *s; @@ -1578,21 +737,21 @@ void M_QuickConnect_PreDraw(menu_t *menu) } } -qboolean M_QuickConnect_Key (int key, menu_t *menu) +static qboolean M_QuickConnect_Key (int key, menu_t *menu) { return false; } -void M_QuickConnect_Remove (menu_t *menu) +static void M_QuickConnect_Remove (menu_t *menu) { } -qboolean M_QuickConnect_Cancel (menuoption_t *opt, menu_t *menu, int key) +static qboolean M_QuickConnect_Cancel (menuoption_t *opt, menu_t *menu, int key) { return false; } -void M_QuickConnect_DrawStatus (int x, int y, menucustom_t *ths, menu_t *menu) +static void M_QuickConnect_DrawStatus (int x, int y, menucustom_t *ths, menu_t *menu) { Draw_FunString(x, y, va("Polling, %i secs\n", (int)(quickconnecttimeout - Sys_DoubleTime() + 0.9))); } diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 3cc6c995b..873dace60 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -2464,11 +2464,9 @@ void Media_Init(void) #else -void Media_Init(void){} void M_Media_Draw (void){} void M_Media_Key (int key) {} qboolean Media_ShowFilm(void){return false;} -qboolean Media_PlayFilm(char *name) {return false;} double Media_TweekCaptureFrameTime(double time) { return time ; } void Media_RecordFrame (void) {} @@ -2481,7 +2479,6 @@ void M_Menu_Media_f (void) {} char *Media_NextTrack(int musicchannelnum) {return NULL;} qboolean Media_PausedDemo(void) {return false;} -qboolean Media_PlayingFullScreen(void) {return false;} int filmtexture; #endif diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index fc93daf1b..f845ce25c 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -44,7 +44,7 @@ void M_Menu_MultiPlayer_f (void) mgt=64; menu->selecteditem = (menuoption_t*) - MC_AddConsoleCommandHexen2BigFont (menu, 80, mgt, "Join A Game ", "menu_slist\n");mgt+=20; + MC_AddConsoleCommandHexen2BigFont (menu, 80, mgt, "Server List ", "menu_slist\n");mgt+=20; MC_AddConsoleCommandHexen2BigFont (menu, 80, mgt, "New Server ", "menu_newmulti\n");mgt+=20; MC_AddConsoleCommandHexen2BigFont (menu, 80, mgt, "Player Setup", "menu_setup\n");mgt+=20; MC_AddConsoleCommandHexen2BigFont (menu, 80, mgt, "Demos ", "menu_demo\n");mgt+=20; @@ -59,7 +59,7 @@ void M_Menu_MultiPlayer_f (void) mgt=32; menu->selecteditem = (menuoption_t*) - MC_AddConsoleCommandQBigFont (menu, 72, mgt, "Join A Game ", "menu_slist\n");mgt+=20; + MC_AddConsoleCommandQBigFont (menu, 72, mgt, "Server List ", "menu_slist\n");mgt+=20; MC_AddConsoleCommandQBigFont (menu, 72, mgt, "Quick Connect", "quickconnect qw\n");mgt+=20; MC_AddConsoleCommandQBigFont (menu, 72, mgt, "New Server ", "menu_newmulti\n");mgt+=20; MC_AddConsoleCommandQBigFont (menu, 72, mgt, "Player Setup", "menu_setup\n");mgt+=20; @@ -444,33 +444,6 @@ void M_Menu_Setup_f (void) -#ifdef CL_MASTER -void M_Menu_ServerList_f (void) -{ - key_dest = key_menu; - m_state = m_slist; - - MasterInfo_Refresh(); -} -#endif - -void M_ServerList_Draw (void) -{ -#ifdef CL_MASTER - M_DrawServers(); -#endif -} - -void M_ServerList_Key (int k) -{ -#ifdef CL_MASTER - M_SListKey(k); -#endif -} - - - - #ifdef CLIENTONLY void M_Menu_GameOptions_f (void) diff --git a/engine/client/m_options.c b/engine/client/m_options.c index ea2086791..13efdda71 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -341,6 +341,7 @@ void M_Menu_Particles_f (void) static const char *pdescopts[] = { + "Classic", "Faithful", "High FPS", "Fancy", @@ -351,6 +352,7 @@ void M_Menu_Particles_f (void) }; static const char *pdescvals[] = { + "classic", "faithful", "highfps", "spikeset", @@ -380,8 +382,8 @@ void M_Menu_Particles_f (void) menubulk_t bulk[] = { MB_REDTEXT("Particle Options", false), MB_TEXT("\x80\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x82", false), - MB_COMBOCVAR("Particle System", r_particlesystem, psystemopts, psystemvals, "Selects particle system to use. Classic is standard Quake particles, script is FTE style scripted particles, and none disables particles entirely."), - MB_COMBOCVAR("Script Set", r_particledesc, pdescopts, pdescvals, "Selects particle set to use with script system."), +// MB_COMBOCVAR("Particle System", r_particlesystem, psystemopts, psystemvals, "Selects particle system to use. Classic is standard Quake particles, script is FTE style scripted particles, and none disables particles entirely."), + MB_COMBOCVAR("Particle Set", r_particledesc, pdescopts, pdescvals, "Selects particle set to use with the scripted particle system."), MB_SPACING(4), MB_COMBOCVAR("Rocket Trail", r_rockettrail, trailopts, trailvals, "Chooses effect to replace rocket trails."), MB_COMBOCVAR("Grenade Trail", r_grenadetrail, trailopts, trailvals, "Chooses effect to replace grenade trails."), diff --git a/engine/client/menu.c b/engine/client/menu.c index 0d7669eb9..225198346 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -823,7 +823,6 @@ void M_Init_Internal (void) #ifdef CL_MASTER Cmd_AddRemCommand ("menu_servers", M_Menu_ServerList2_f); - Cmd_AddRemCommand ("menu_serversold", M_Menu_ServerList_f); Cmd_AddRemCommand ("menu_slist", M_Menu_ServerList2_f); #endif Cmd_AddRemCommand ("menu_setup", M_Menu_Setup_f); @@ -889,7 +888,6 @@ void M_DeInit_Internal (void) #ifdef CL_MASTER Cmd_RemoveCommand ("menu_servers"); - Cmd_RemoveCommand ("menu_serversold"); Cmd_RemoveCommand ("menu_slist"); #endif Cmd_RemoveCommand ("menu_setup"); @@ -1007,10 +1005,6 @@ void M_Draw (int uimenu) M_Help_Draw (); break; - case m_slist: - M_ServerList_Draw (); - break; - case m_media: M_Media_Draw (); break; @@ -1044,10 +1038,6 @@ void M_Keydown (int key, int unicode) M_Help_Key (key); return; - case m_slist: - M_ServerList_Key (key); - return; - case m_media: M_Media_Key (key); return; diff --git a/engine/client/menu.h b/engine/client/menu.h index 781c31198..734011dd7 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -115,7 +115,7 @@ void M_Menu_Quit_f (void); struct menu_s; -typedef enum {m_none, m_complex, m_help, m_slist, m_media, m_plugin, m_menu_dat} m_state_t; +typedef enum {m_none, m_complex, m_help, m_media, m_plugin, m_menu_dat} m_state_t; extern m_state_t m_state; typedef enum { diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 0c18b6ef0..1353b1798 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -133,6 +133,11 @@ void Master_HideServer(serverinfo_t *server) void Master_InsertAt(serverinfo_t *server, int pos) { int i; + if (numvisibleservers >= maxvisibleservers) + { + maxvisibleservers = maxvisibleservers+10; + visibleservers = BZ_Realloc(visibleservers, maxvisibleservers*sizeof(serverinfo_t*)); + } for (i = numvisibleservers; i > pos; i--) { visibleservers[i] = visibleservers[i-1]; @@ -714,6 +719,8 @@ qboolean Master_LoadMasterList (char *filename, int defaulttype, int depth) servertype = MT_MASTERQ2; else if (!strcmp(com_token, "master:q3")) servertype = MT_MASTERQ3; + else if (!strcmp(com_token, "master:httpjson")) + servertype = MT_MASTERHTTPJSON; else if (!strcmp(com_token, "master:httpnq")) servertype = MT_MASTERHTTPNQ; else if (!strcmp(com_token, "master:httpqw")) @@ -776,12 +783,14 @@ qboolean Master_LoadMasterList (char *filename, int defaulttype, int depth) { switch (servertype) { + case MT_MASTERHTTPJSON: case MT_MASTERHTTPNQ: case MT_MASTERHTTPQW: Master_AddMasterHTTP(line, servertype, name); break; default: Master_AddMaster(line, servertype, name); + break; } } @@ -1138,6 +1147,7 @@ void MasterInfo_ProcessHTTP(vfsfile_t *file, int type) info->sends = 1; info->special = type; info->refreshtime = 0; + info->ping = 0xffff; snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adrbuf, sizeof(adrbuf), info->adr)); @@ -1149,6 +1159,118 @@ void MasterInfo_ProcessHTTP(vfsfile_t *file, int type) } } +char *jsonnode(int level, char *node) +{ + netadr_t adr = {NA_INVALID}; + char servername[256] = {0}; + char key[256]; + int flags = 0; + int port = 0; + int cp = 0, mp = 0; + if (*node != '{') + return node; + do + { + node++; + node = COM_ParseToken(node, ",:{}[]"); + if (*node != ':') + continue; + node++; + if (*node == '[') + { + do + { + node++; + node = jsonnode(level+1, node); + if (!node) + return NULL; + if (*node == ']') + { + break; + } + } while(*node == ','); + if (*node != ']') + return NULL; + node++; + } + else + { + Q_strncpyz(key, com_token, sizeof(key)); + node = COM_ParseToken(node, ",:{}[]"); + + if (level == 1) + { + if (!strcmp(key, "IPAddress")) + NET_StringToAdr(com_token, &adr); + if (!strcmp(key, "Port")) + port = atoi(com_token); + if (!strcmp(key, "DNS")) + Q_strncpyz(servername, com_token, sizeof(servername)); + if (!strcmp(key, "CurrentPlayerCount")) + cp = atoi(com_token); + if (!strcmp(key, "MaxPlayers")) + mp = atoi(com_token); + if (!strcmp(key, "Game")) + { + if (!strcmp(com_token, "NetQuake")) + flags |= SS_NETQUAKE; + if (!strcmp(com_token, "Quake2")) + flags |= SS_QUAKE2; + if (!strcmp(com_token, "Quake3")) + flags |= SS_QUAKE3; + } + } + } + } while(*node == ','); + + if (*node == '}') + node++; + + if (adr.type != NA_INVALID) + { + serverinfo_t *info; + + if (port) + adr.port = htons(port); + + if ((info = Master_InfoForServer(adr))) //remove if the server already exists. + { + info->sends = 1; //reset. + } + else + { + info = Z_Malloc(sizeof(serverinfo_t)); + info->adr = adr; + info->sends = 1; + info->special = flags; + info->refreshtime = 0; + info->players = cp; + info->maxplayers = mp; + + snprintf(info->name, sizeof(info->name), "%s", *servername?servername:NET_AdrToString(servername, sizeof(servername), info->adr)); + + info->next = firstserver; + firstserver = info; + + Master_ResortServer(info); + } + } + + return node; +} + +void MasterInfo_ProcessHTTPJSON(struct dl_download *dl) +{ + int len; + char *buf; + len = VFS_GETLEN(dl->file); + buf = malloc(len + 1); + VFS_READ(dl->file, buf, len); + buf[len] = 0; + jsonnode(0, buf); + free(buf); +} + // wrapper functions for the different server types void MasterInfo_ProcessHTTPNQ(struct dl_download *dl) { @@ -1234,6 +1356,9 @@ void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles) break; #endif #ifdef WEBCLIENT + case MT_MASTERHTTPJSON: + HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPJSON); + break; case MT_MASTERHTTPNQ: HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPNQ); break; @@ -1387,6 +1512,7 @@ void MasterInfo_Refresh(void) { //Master_AddMaster("12.166.196.192:27950", MT_MASTERDP, "DarkPlaces Master 3"); Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake", MT_MASTERHTTPNQ, "gameaholic's NQ master"); + Master_AddMasterHTTP("http://servers.quakeone.com/index.php?format=json", MT_MASTERHTTPJSON, "quakeone's server listing"); Master_AddMaster("ghdigital.com:27950", MT_MASTERDP, "DarkPlaces Master 1"); // LordHavoc Master_AddMaster("dpmaster.deathmask.net:27950", MT_MASTERDP, "DarkPlaces Master 2"); // Willis Master_AddMaster("dpmaster.tchr.no:27950", MT_MASTERDP, "DarkPlaces Master 3"); // tChr @@ -1957,6 +2083,8 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad) } if ((old = Master_InfoForServer(info->adr))) //remove if the server already exists. { + if ((info->special & (SS_DARKPLACES | SS_NETQUAKE | SS_QUAKE2 | SS_QUAKE3)) && !(type & (SS_DARKPLACES | SS_NETQUAKE | SS_QUAKE2 | SS_QUAKE3))) + old->special = type | (old->special & SS_FAVORITE); old->sends = 1; //reset. Z_Free(info); } diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c index fd5fb1f8c..878167f62 100644 --- a/engine/client/p_classic.c +++ b/engine/client/p_classic.c @@ -217,6 +217,7 @@ static qboolean PClassic_InitParticles (void) #endif classicshader = R_RegisterShader("particles_classic", "{\n" + "program defaultsprite\n" "nomipmaps\n" "{\n" "map $diffuse\n" @@ -384,9 +385,9 @@ static void PClassic_DrawParticles(void) cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert); } - Vector4Set(cl_strisvertc[cl_numstrisvert+0],1,1,1,1); - Vector4Set(cl_strisvertc[cl_numstrisvert+1],1,1,1,1); - Vector4Set(cl_strisvertc[cl_numstrisvert+2],1,1,1,1); +// Vector4Set(cl_strisvertc[cl_numstrisvert+0],1,1,1,1); +// Vector4Set(cl_strisvertc[cl_numstrisvert+1],1,1,1,1); +// Vector4Set(cl_strisvertc[cl_numstrisvert+2],1,1,1,1); Vector4Set(cl_strisvertc[cl_numstrisvert+0], ((p->rgb&0xff)>>0)/256.0, ((p->rgb&0xff00)>>8)/256.0, ((p->rgb&0xff0000)>>16)/256.0, ((p->type == pt_fire)?((6 - p->ramp) *0.166666):1.0)); Vector4Copy(cl_strisvertc[cl_numstrisvert+0], cl_strisvertc[cl_numstrisvert+1]); diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 4c2e321b5..ae6bd5d49 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -527,6 +527,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) namepostfix = "_blend"; defaultshader = "{\n" + "program defaultsprite\n" "nomipmaps\n" "{\n" "map $diffuse\n" @@ -542,6 +543,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) namepostfix = "_bc"; defaultshader = "{\n" + "program defaultsprite\n" "nomipmaps\n" "{\n" "map $diffuse\n" @@ -557,6 +559,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) namepostfix = "_add"; defaultshader = "{\n" + "program defaultsprite\n" "nomipmaps\n" "{\n" "map $diffuse\n" @@ -572,6 +575,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) namepostfix = "_invmod"; defaultshader = "{\n" + "program defaultsprite\n" "nomipmaps\n" "{\n" "map $diffuse\n" @@ -587,6 +591,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) namepostfix = "_sub"; defaultshader = "{\n" + "program defaultsprite\n" "nomipmaps\n" "{\n" "map $diffuse\n" @@ -825,7 +830,7 @@ static void P_ParticleEffect_f(void) if (*buf == '{') { int nest = 1; - char *str = BZ_Malloc(2); + char *str = BZ_Malloc(3); int slen = 2; str[0] = '{'; str[1] = '\n'; @@ -4267,6 +4272,7 @@ static void PScript_DrawParticleTypes (void) int traces=r_particle_tracelimit.ival; int rampind; + static float oldtime; RSpeedMark(); if (r_plooksdirty) @@ -4288,11 +4294,16 @@ static void PScript_DrawParticleTypes (void) r_plooksdirty = false; CL_RegisterParticles(); } - +#if 1 + pframetime = cl.time - oldtime; + if (pframetime < 0) + pframetime = 0; + oldtime = cl.time; +#else pframetime = host_frametime; if (cl.paused || r_secondaryview || r_refdef.recurse) pframetime = 0; - +#endif VectorScale (vup, 1.5, pup); VectorScale (vright, 1.5, pright); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index da57bf8bb..e3643c09d 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -619,7 +619,8 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) else { VectorCopy(in->v->angles, out->angles); - out->angles[0]*=-1; + if (model->type == mod_alias) + out->angles[0]*=-1; AngleVectors(out->angles, out->axis[0], out->axis[1], out->axis[2]); VectorInverse(out->axis[1]); @@ -3235,62 +3236,6 @@ static void QCBUILTIN PF_rotatevectorsbytag (progfuncs_t *prinst, struct globalv VectorCopy(srcorg, retorg); } -static void EdictToTransform(csqcedict_t *ed, float *trans) -{ - AngleVectors(ed->v->angles, trans+0, trans+4, trans+8); - VectorInverse(trans+4); - - trans[3] = ed->v->origin[0]; - trans[7] = ed->v->origin[1]; - trans[11] = ed->v->origin[2]; -} - -static void QCBUILTIN PF_cs_gettaginfo (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); - int tagnum = G_FLOAT(OFS_PARM1); - - float *origin = G_VECTOR(OFS_RETURN); - - int modelindex = ent->v->modelindex; - - model_t *mod = CSQC_GetModelForIndex(modelindex); - - float transent[12]; - float transforms[12]; - float result[12]; - - framestate_t fstate; - - cs_getframestate(ent, ent->xv->renderflags, &fstate); - -#ifdef warningmsg -#pragma warningmsg("PF_cs_gettaginfo: This function doesn't honour attachments (but setattachment isn't implemented yet anyway)") -#endif - if (!Mod_GetTag(mod, tagnum, &fstate, transforms)) - { - memset(transforms, 0, sizeof(transforms)); - } - - EdictToTransform(ent, transent); - R_ConcatTransforms((void*)transent, (void*)transforms, (void*)result); - - origin[0] = result[3]; - origin[1] = result[7]; - origin[2] = result[11]; - VectorCopy((result+0), csqcg.forward); - VectorCopy((result+4), csqcg.right); - VectorCopy((result+8), csqcg.up); - -} -static void QCBUILTIN PF_cs_gettagindex (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); - char *tagname = PR_GetStringOfs(prinst, OFS_PARM1); - - model_t *mod = CSQC_GetModelForIndex(ent->v->modelindex); - G_FLOAT(OFS_RETURN) = Mod_TagNumForName(mod, tagname); -} static void QCBUILTIN PF_rotatevectorsbyangles (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *ang = G_VECTOR(OFS_PARM0); @@ -3439,12 +3384,6 @@ static void QCBUILTIN PF_cs_walkmove (progfuncs_t *prinst, struct globalvars_s * *csqcg.self = oldself; } -void PF_cs_touchtriggers(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - wedict_t *ent = (wedict_t*)PROG_TO_EDICT(prinst, *csqcg.self); - World_LinkEdict (&csqc_world, ent, true); -} - static void QCBUILTIN PF_cs_movetogoal (progfuncs_t *prinst, struct globalvars_s *pr_globals) { wedict_t *ent; @@ -3990,19 +3929,6 @@ static void QCBUILTIN PF_ReadServerEntityState(progfuncs_t *prinst, struct globa } #endif -static void QCBUILTIN PF_cs_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int action = G_FLOAT(OFS_PARM0); - float *pos = G_VECTOR(OFS_PARM1); - float radius = G_FLOAT(OFS_PARM2); - float quant = G_FLOAT(OFS_PARM3); -#if defined(TERRAIN) - G_FLOAT(OFS_RETURN) = Heightmap_Edit(csqc_world.worldmodel, action, pos, radius, quant); -#else - G_FLOAT(OFS_RETURN) = false; -#endif -} - #define PF_FixTen PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme //prefixes: @@ -4238,8 +4164,8 @@ static struct { {"frameforname", PF_frameforname, 276},//void(float modidx, string framename) frameforname = #276 (FTE_CSQC_SKELETONOBJECTS) {"frameduration", PF_frameduration, 277},//void(float modidx, float framenum) frameduration = #277 (FTE_CSQC_SKELETONOBJECTS) - {"terrain_edit", PF_cs_terrain_edit, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT??) - {"touchtriggers", PF_cs_touchtriggers, 279},//void() touchtriggers = #279; + {"terrain_edit", PF_terrain_edit, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT??) + {"touchtriggers", PF_touchtriggers, 279},//void() touchtriggers = #279; {"skel_ragupdate", PF_skel_ragedit, 281},// (FTE_QC_RAGDOLL) {"skel_mmap", PF_skel_mmap, 282},// (FTE_QC_RAGDOLL) //300 @@ -4386,17 +4312,17 @@ static struct { {"te_lightning1", PF_cl_te_lightning1, 428}, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) {"te_lightning2", PF_cl_te_lightning2,429}, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) - {"te_lightning3", PF_cl_te_lightning3,430}, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) - {"te_beam", PF_cl_te_beam, 431}, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) - {"vectorvectors", PF_cs_vectorvectors,432}, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) - {"te_plasmaburn", PF_cl_te_plasmaburn,433}, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) -// {"getsurfacenumpoints", PF_Fixme, 434}, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) + {"te_lightning3", PF_cl_te_lightning3, 430}, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) + {"te_beam", PF_cl_te_beam, 431}, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) + {"vectorvectors", PF_cs_vectorvectors, 432}, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) + {"te_plasmaburn", PF_cl_te_plasmaburn, 433}, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) + {"getsurfacenumpoints", PF_getsurfacenumpoints, 434}, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) -// {"getsurfacepoint", PF_Fixme, 435}, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) -// {"getsurfacenormal", PF_Fixme, 436}, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) -// {"getsurfacetexture", PF_Fixme, 437}, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) -// {"getsurfacenearpoint", PF_Fixme, 438}, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) -// {"getsurfaceclippedpoint", PF_Fixme, 439}, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) + {"getsurfacepoint", PF_getsurfacepoint, 435}, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) + {"getsurfacenormal", PF_getsurfacenormal, 436}, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) + {"getsurfacetexture", PF_getsurfacetexture, 437}, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) + {"getsurfacenearpoint", PF_getsurfacenearpoint, 438}, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) + {"getsurfaceclippedpoint", PF_getsurfaceclippedpoint, 439}, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) {"clientcommand", PF_NoCSQC, 440}, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) (don't implement) {"tokenize", PF_Tokenize, 441}, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) @@ -4411,8 +4337,8 @@ static struct { {"findflags", PF_FindFlags, 449}, // #449 entity(entity start, .entity fld, float match) findflags (DP_QC_FINDFLAGS) {"findchainflags", PF_cs_findchainflags, 450}, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS) - {"gettagindex", PF_cs_gettagindex, 451}, // #451 float(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO) - {"gettaginfo", PF_cs_gettaginfo, 452}, // #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO) + {"gettagindex", PF_gettagindex, 451}, // #451 float(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO) + {"gettaginfo", PF_gettaginfo, 452}, // #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO) {"dropclient", PF_NoCSQC, 453}, // #453 void(entity player) dropclient (DP_SV_BOTCLIENT) (don't implement) {"spawnclient", PF_NoCSQC, 454}, // #454 entity() spawnclient (DP_SV_BOTCLIENT) (don't implement) @@ -5608,8 +5534,10 @@ void CSQC_ParseEntities(void) if (!csqcprogs) Host_EndGame("CSQC needs to be initialized for this server.\n"); - if (!csqcg.ent_update || !csqcg.self || !csqc_world.worldmodel || csqc_world.worldmodel->needload) + if (!csqcg.ent_update || !csqcg.self) Host_EndGame("CSQC is unable to parse entities\n"); + if (!csqc_world.worldmodel || csqc_world.worldmodel->needload) + Host_EndGame("world is not yet initialised\n"); pr_globals = PR_globals(csqcprogs, PR_CURRENT); diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c index b85dce5ca..817560552 100644 --- a/engine/client/pr_skelobj.c +++ b/engine/client/pr_skelobj.c @@ -23,7 +23,7 @@ this file deals with qc builtins to apply custom skeletal blending (skeletal obj #include "quakedef.h" -#ifdef CSQC_DAT +#if defined(CSQC_DAT) || !defined(CLIENTONLY) #define RAGDOLL #include "pr_common.h" @@ -94,6 +94,23 @@ static doll_t *dolllist; static skelobject_t skelobjects[MAX_SKEL_OBJECTS]; static int numskelobjectsused; +static void bonemat_fromidentity(float *out) +{ + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; +} static void bonemat_fromqcvectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]) { out[0] = vx[0]; @@ -109,6 +126,20 @@ static void bonemat_fromqcvectors(float *out, const float vx[3], const float vy[ out[10] = vz[2]; out[11] = t[2]; } +static void bonemat_fromentity(world_t *w, wedict_t *ed, float *trans) +{ + vec3_t d[3], a; + model_t *mod; + mod = w->Get_CModel(w, ed->v->modelindex); + if (!mod || mod->type == mod_alias) + a[0] = -ed->v->angles[0]; + else + a[0] = ed->v->angles[0]; + a[1] = ed->v->angles[1]; + a[2] = ed->v->angles[2]; + AngleVectors(a, d[0], d[1], d[2]); + bonemat_fromqcvectors(trans, d[0], d[1], d[2], ed->v->origin); +} static void bonemat_toqcvectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]) { vx[0] = in[0]; @@ -742,6 +773,71 @@ void QCBUILTIN PF_skel_get_boneabs (progfuncs_t *prinst, struct globalvars_s *pr } } +//void(entity ent, float bonenum, vector org, optional fwd, right, up) skel_set_bone_world (FTE_CSQC_SKELETONOBJECTS2) (reads v_forward etc) +void QCBUILTIN PF_skel_set_bone_world (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + wedict_t *ent = G_WEDICT(prinst, OFS_PARM0); + unsigned int boneidx = G_FLOAT(OFS_PARM1)-1; + float *matrix[3]; + skelobject_t *skelobj; + float *bone; + float childworld[12], parentinv[12]; + + /*sort out the parameters*/ + if (*prinst->callargc == 4) + { + vec3_t d[3], a; + a[0] = G_VECTOR(OFS_PARM2)[0] * -1; /*mod_alias bug*/ + a[1] = G_VECTOR(OFS_PARM2)[1]; + a[2] = G_VECTOR(OFS_PARM2)[2]; + AngleVectors(a, d[0], d[1], d[2]); + bonemat_fromqcvectors(childworld, d[0], d[1], d[2], G_VECTOR(OFS_PARM2)); + } + else + { + if (*prinst->callargc > 5) + { + matrix[0] = G_VECTOR(OFS_PARM3); + matrix[1] = G_VECTOR(OFS_PARM4); + matrix[2] = G_VECTOR(OFS_PARM5); + } + else + { + matrix[0] = w->g.v_forward; + matrix[1] = w->g.v_right; + matrix[2] = w->g.v_up; + } + bonemat_fromqcvectors(childworld, matrix[0], matrix[1], matrix[2], G_VECTOR(OFS_PARM2)); + } + + /*make sure the skeletal object is correct*/ + skelobj = skel_get(prinst, ent->xv->skeletonindex, 0); + if (!skelobj || boneidx >= skelobj->numbones) + return; + + /*get the inverse of the parent matrix*/ + { + float parentabs[12]; + float parentw[12]; + float parentent[12]; + framestate_t fstate; + w->Get_FrameState(w, ent, &fstate); + if (!Mod_GetTag(skelobj->model, boneidx+1, &fstate, parentabs)) + { + bonemat_fromidentity(parentabs); + } + + bonemat_fromentity(w, ent, parentent); + Matrix3x4_Multiply(parentent, parentabs, parentw); + Matrix3x4_Invert_Simple(parentw, parentinv); + } + + /*calc the result*/ + bone = skelobj->bonematrix+12*boneidx; + Matrix3x4_Multiply(parentinv, childworld, bone); +} + //void(float skel, float bonenum, vector org) skel_set_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) void QCBUILTIN PF_skel_set_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -770,7 +866,7 @@ void QCBUILTIN PF_skel_set_bone (progfuncs_t *prinst, struct globalvars_s *pr_gl return; bone = skelobj->bonematrix+12*boneidx; - bonemat_fromqcvectors(skelobj->bonematrix+12*boneidx, matrix[0], matrix[1], matrix[2], G_VECTOR(OFS_PARM2)); + bonemat_fromqcvectors(bone, matrix[0], matrix[1], matrix[2], G_VECTOR(OFS_PARM2)); } //void(float skel, float bonenum, vector org [, vector fwd, vector right, vector up]) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) @@ -908,5 +1004,56 @@ void QCBUILTIN PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_glob pendingkill = true; } } + +//vector(entity ent, float tag) gettaginfo (DP_MD3_TAGSINFO) +void QCBUILTIN PF_gettaginfo (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + wedict_t *ent = G_WEDICT(prinst, OFS_PARM0); + int tagnum = G_FLOAT(OFS_PARM1); + + int modelindex = ent->v->modelindex; + + model_t *mod = w->Get_CModel(w, modelindex); + + float transent[12]; + float transforms[12]; + float result[12]; + + framestate_t fstate; + + w->Get_FrameState(w, ent, &fstate); + + if (!Mod_GetTag(mod, tagnum, &fstate, transforms)) + { + bonemat_fromidentity(transforms); + } + + if (ent->xv->tag_entity) + { +#ifdef warningmsg + #pragma warningmsg("PF_gettaginfo: This function doesn't honour attachments") +#endif + Con_Printf("bug: PF_gettaginfo doesn't support attachments\n"); + } + + bonemat_fromentity(w, ent, transent); + R_ConcatTransforms((void*)transent, (void*)transforms, (void*)result); + + bonemat_toqcvectors(result, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN)); +} + +//vector(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO) +void QCBUILTIN PF_gettagindex (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + wedict_t *ent = G_WEDICT(prinst, OFS_PARM0); + char *tagname = PR_GetStringOfs(prinst, OFS_PARM1); + model_t *mod = *tagname?w->Get_CModel(w, ent->v->modelindex):NULL; + if (mod) + G_FLOAT(OFS_RETURN) = Mod_TagNumForName(mod, tagname); + else + G_FLOAT(OFS_RETURN) = 0; +} #endif diff --git a/engine/client/render.h b/engine/client/render.h index b9fd04a4c..f7f4662da 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -158,8 +158,8 @@ typedef struct float m_view[16]; vec3_t gfog_rgb; - float gfog_alpha; float gfog_density; + float gfog_alpha; vrect_t pxrect; /*vrect, but in pixels rather than virtual coords*/ qboolean externalview; /*draw external models and not viewmodels*/ @@ -204,8 +204,8 @@ void Surf_RenderDynamicLightmaps (struct msurface_s *fa); void Surf_RenderAmbientLightmaps (struct msurface_s *fa, int ambient); int Surf_LightmapShift (struct model_s *model); #ifndef LMBLOCK_WIDTH -#define LMBLOCK_WIDTH 256 -#define LMBLOCK_HEIGHT 256 +#define LMBLOCK_WIDTH 128 +#define LMBLOCK_HEIGHT 128 typedef struct glRect_s { unsigned char l,t,w,h; } glRect_t; @@ -272,6 +272,8 @@ enum imageflags IF_NOALPHA = 1<<3, IF_NOGAMMA = 1<<4, IF_NEAREST = 1<<5, + IF_CUBEMAP = 1<<6, + IF_3DMAP = 1<<7, IF_SUBDIRONLY = 1<<31 }; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 3b6437285..8d5422ad5 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -92,8 +92,8 @@ cvar_t r_flashblend = SCVARF ("gl_flashblend", "0", CVAR_ARCHIVE); cvar_t r_flashblendscale = SCVARF ("gl_flashblendscale", "0.35", CVAR_ARCHIVE); -cvar_t r_floorcolour = SCVARF ("r_floorcolour", "255 255 255", - CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); +cvar_t r_floorcolour = CVARAF ("r_floorcolour", "255 255 255", + "r_floorcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); cvar_t r_floortexture = SCVARF ("r_floortexture", "", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); cvar_t r_fullbright = SCVARF ("r_fullbright", "0", @@ -122,8 +122,8 @@ cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1"); cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"), CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback); -cvar_t r_wallcolour = CVARF ("r_wallcolour", "255 255 255", - CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);//FIXME: broken +cvar_t r_wallcolour = CVARAF ("r_wallcolour", "255 255 255", + "r_wallcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);//FIXME: broken cvar_t r_walltexture = CVARF ("r_walltexture", "", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); //FIXME: broken cvar_t r_wateralpha = CVARF ("r_wateralpha", "1", diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 31bbce7b7..41d07b640 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -2031,9 +2031,9 @@ void Sbar_Hexen2DrawExtra (int pnum) Sbar_DrawTinyString (11, 79, va("abilities")); if (cl.stats[pnum][STAT_H2_FLAGS] & (1<<22)) - Sbar_DrawTinyString (8, 89, va("ability 1")); + Sbar_DrawTinyString (8, 89, T_GetString(400 + 2*(pclass-1) + 0)); if (cl.stats[pnum][STAT_H2_FLAGS] & (1<<23)) - Sbar_DrawTinyString (8, 96, va("ability 2")); + Sbar_DrawTinyString (8, 96, T_GetString(400 + 2*(pclass-1) + 1)); for (i = 0; i < 4; i++) { @@ -2404,14 +2404,14 @@ void Sbar_Draw (void) if (sbar_hexen2) { - if (sb_lines > 0) + if (sb_lines > 24 || sb_hexen2_extra_info[pnum]) { Sbar_Hexen2DrawExtra(pnum); Sbar_Hexen2DrawBasic(pnum); - Sbar_Hexen2DrawInventory(pnum); } - else + else if (sb_lines > 0) Sbar_Hexen2DrawMinimal(pnum); + Sbar_Hexen2DrawInventory(pnum); if (cl.deathmatch) Sbar_MiniDeathmatchOverlay (); diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index bed19dd99..eaca37448 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -51,7 +51,6 @@ unsigned int sys_parenttop; unsigned int sys_parentwidth; //valid if sys_parentwindow is set unsigned int sys_parentheight; - /* ================ Sys_RandomBytes @@ -813,7 +812,7 @@ void Sys_Quit (void) longjmp (host_abort, 1); } #else - exit (0); + exit(1); #endif } diff --git a/engine/client/view.c b/engine/client/view.c index d8a1635e6..40fc37d75 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -366,7 +366,7 @@ void GLV_Gamma_Callback(struct cvar_s *var, char *oldvalue) { BuildGammaTable (v_gamma.value, v_contrast.value); vid.recalc_refdef = 1; // force a surface cache flush - GLV_UpdatePalette (true, 0); + V_UpdatePalette (true); } #endif @@ -625,9 +625,7 @@ void V_CalcPowerupCshift (void) V_CalcBlend ============= */ -#if defined(GLQUAKE) || defined(D3DQUAKE) - -void GLV_CalcBlend (float *hw_blend) +void V_CalcBlend (float *hw_blend) { float a2; int j; @@ -689,14 +687,20 @@ void GLV_CalcBlend (float *hw_blend) V_UpdatePalette ============= */ -void GLV_UpdatePalette (qboolean force, double ftime) +void V_UpdatePalette (qboolean force) { int i; float newhw_blend[4]; int ir, ig, ib; - + float ftime; + static float oldtime; RSpeedMark(); + ftime = cl.time - oldtime; + oldtime = cl.time; + if (ftime < 0) + ftime = 0; + V_CalcPowerupCshift (); // drop the damage value @@ -709,7 +713,7 @@ void GLV_UpdatePalette (qboolean force, double ftime) if (cl.cshifts[CSHIFT_BONUS].percent <= 0) cl.cshifts[CSHIFT_BONUS].percent = 0; - GLV_CalcBlend(newhw_blend); + V_CalcBlend(newhw_blend); if (hw_blend[0] != newhw_blend[0] || hw_blend[1] != newhw_blend[1] || hw_blend[2] != newhw_blend[2] || hw_blend[3] != newhw_blend[3] || force) { @@ -744,7 +748,7 @@ void GLV_UpdatePalette (qboolean force, double ftime) RSpeedEnd(RSPEED_PALETTEFLASHES); } -#endif + /* ============= V_UpdatePalette @@ -1468,8 +1472,6 @@ void V_RenderView (void) //work out which packet entities are solid CL_SetSolidEntities (); -// CL_EmitEntities(); - // Set up prediction for other players CL_SetUpPlayerPrediction(false); diff --git a/engine/client/view.h b/engine/client/view.h index ff3f9c6a4..1e1a8f7f3 100644 --- a/engine/client/view.h +++ b/engine/client/view.h @@ -29,8 +29,7 @@ extern qboolean r_secondaryview; void V_Init (void); void V_RenderView (void); float V_CalcRoll (vec3_t angles, vec3_t velocity); -void GLV_UpdatePalette (qboolean force, double ftime); -void SWV_UpdatePalette (qboolean force, double ftime); +void V_UpdatePalette (qboolean force); void V_ClearCShifts (void); entity_t *V_AddEntity(entity_t *in); void VQ2_AddLerpEntity(entity_t *in); diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 0bcd08890..261ae40b2 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -245,6 +245,18 @@ static void GenMatrixPosQuat4Scale(vec3_t pos, vec4_t quat, vec3_t scale, float result[1*4+3] = pos[1]; result[2*4+3] = pos[2]; } +/*like above, but guess the quat.w*/ +static void GenMatrixPosQuat3Scale(vec3_t pos, vec3_t quat3, vec3_t scale, float result[12]) +{ + vec4_t quat4; + float term = 1 - DotProduct(quat3, quat3); + if (term < 0) + quat4[3] = 0; + else + quat4[3] = - (float) sqrt(term); + VectorCopy(quat3, quat4); + GenMatrixPosQuat4Scale(pos, quat4, scale, result); +} static void GenMatrix(float x, float y, float z, float qx, float qy, float qz, float result[12]) { @@ -777,7 +789,7 @@ static int Alias_BuildLerps(float plerp[4], float *pose[4], int numbones, galias return l; } -// +//ignores any skeletal objects int Alias_GetBoneRelations(galiasinfo_t *inf, framestate_t *fstate, float *result, int firstbone, int lastbones) { #ifdef SKELETALMODELS @@ -894,7 +906,7 @@ int Alias_GetBoneRelations(galiasinfo_t *inf, framestate_t *fstate, float *resul } //_may_ write into bonepose, return value is the real result. obtains absolute values -float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *buffer, int buffersize) +float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *buffer, int buffersize, qboolean renderable) { #ifdef SKELETALMODELS float relationsbuf[MAX_BONES][12]; @@ -909,7 +921,19 @@ float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *bu relations = fstate->bonestate; numbones = inf->numbones; if (fstate->boneabs) + { + /*we may need to invert by the inverse of the base pose to get the bones into the proper positions*/ + if (!inf->numswtransforms && renderable) + { + int i; + for (i = 0; i < inf->numbones; i++) + { + R_ConcatTransforms((void*)(relations + i*12), (void*)(bones[i].inverse), (void*)(buffer + i*12)); + } + return buffer; + } return relations; + } } else { @@ -921,13 +945,30 @@ float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *bu { int i, k; - for (i = 0; i < numbones; i++) + if (!inf->numswtransforms && renderable) { - if (bones[i].parent >= 0) - R_ConcatTransforms((void*)(buffer + bones[i].parent*12), (void*)((float*)relations+i*12), (void*)(buffer+i*12)); - else - for (k = 0;k < 12;k++) //parentless - buffer[i*12+k] = ((float*)relations)[i*12+k]; + float tmp[12]; + for (i = 0; i < numbones; i++) + { + if (bones[i].parent >= 0) + R_ConcatTransforms((void*)(buffer + bones[i].parent*12), (void*)((float*)relations+i*12), (void*)tmp); + else + for (k = 0;k < 12;k++) //parentless + tmp[k] = ((float*)relations)[i*12+k]; + + R_ConcatTransforms((void*)tmp, (void*)bones[i].inverse, (void*)(buffer+i*12)); + } + } + else + { + for (i = 0; i < numbones; i++) + { + if (bones[i].parent >= 0) + R_ConcatTransforms((void*)(buffer + bones[i].parent*12), (void*)((float*)relations+i*12), (void*)(buffer+i*12)); + else + for (k = 0;k < 12;k++) //parentless + buffer[i*12+k] = ((float*)relations)[i*12+k]; + } } return buffer; } @@ -995,7 +1036,7 @@ float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *bu return buffer; } #endif - return 0; + return NULL; } @@ -1480,7 +1521,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent meshcache.usebonepose = NULL; if (inf->numbones) { - meshcache.usebonepose = Alias_GetBonePositions(inf, &e->framestate, meshcache.bonepose, MAX_BONES); + meshcache.usebonepose = Alias_GetBonePositions(inf, &e->framestate, meshcache.bonepose, MAX_BONES, true); if (e->fatness || !inf->ofs_skel_idx || !usebones) { @@ -3420,56 +3461,79 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res #ifdef warningmsg #pragma warningmsg("fixme: no base info") #endif - frame1 = fstate->g[FS_REG].frame[0]; - frame2 = fstate->g[FS_REG].frame[1]; - f1time = fstate->g[FS_REG].frametime[0]; - f2time = fstate->g[FS_REG].frametime[1]; - f2ness = fstate->g[FS_REG].lerpfrac; if (tagnum <= 0 || tagnum > inf->numbones) return false; tagnum--; //tagnum 0 is 'use my angles/org' - if (frame1 < 0 || frame1 >= inf->groups) - return false; - if (frame2 < 0 || frame2 >= inf->groups) - { - f2ness = 0; - frame2 = frame1; - } - bone = (galiasbone_t*)((char*)inf + inf->ofsbones); -//the higher level merges old/new anims, but we still need to blend between automated frame-groups. - g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); - g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); - f1time *= g1->rate; - frame1 = (int)f1time%g1->numposes; - frame2 = ((int)f1time+1)%g1->numposes; - f1time = f1time - (int)f1time; - pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame1); - plerp[numposes] = (1-f1time) * (1-f2ness); - numposes++; - if (frame1 != frame2) + if (fstate->bonestate) { - pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame2); - plerp[numposes] = f1time * (1-f2ness); - numposes++; - } - if (f2ness) - { - f2time *= g2->rate; - frame1 = (int)f2time%g2->numposes; - frame2 = ((int)f2time+1)%g2->numposes; - f2time = f2time - (int)f2time; - pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame1); - plerp[numposes] = (1-f2time) * f2ness; - numposes++; - if (frame1 != frame2) + if (tagnum >= fstate->bonecount) + return false; + + if (fstate->boneabs) { - pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame2); - plerp[numposes] = f2time * f2ness; + memcpy(result, fstate->bonestate + 12 * tagnum, 12*sizeof(*result)); + return true; + } + + pose[0] = fstate->bonestate; + plerp[0] = 1; + numposes = 1; + } + else + { + frame1 = fstate->g[FS_REG].frame[0]; + frame2 = fstate->g[FS_REG].frame[1]; + f1time = fstate->g[FS_REG].frametime[0]; + f2time = fstate->g[FS_REG].frametime[1]; + f2ness = fstate->g[FS_REG].lerpfrac; + + if (frame1 < 0 || frame1 >= inf->groups) + return false; + if (frame2 < 0 || frame2 >= inf->groups) + { + f2ness = 0; + frame2 = frame1; + } + + //the higher level merges old/new anims, but we still need to blend between automated frame-groups. + g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); + g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); + + if (f2ness != 1) + { + f1time *= g1->rate; + frame1 = (int)f1time%g1->numposes; + frame2 = ((int)f1time+1)%g1->numposes; + f1time = f1time - (int)f1time; + pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame1); + plerp[numposes] = (1-f1time) * (1-f2ness); numposes++; + if (frame1 != frame2) + { + pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame2); + plerp[numposes] = f1time * (1-f2ness); + numposes++; + } + } + if (f2ness) + { + f2time *= g2->rate; + frame1 = (int)f2time%g2->numposes; + frame2 = ((int)f2time+1)%g2->numposes; + f2time = f2time - (int)f2time; + pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame1); + plerp[numposes] = (1-f2time) * f2ness; + numposes++; + if (frame1 != frame2) + { + pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame2); + plerp[numposes] = f2time * f2ness; + numposes++; + } } } @@ -5596,7 +5660,8 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) texnums_t *texnum; index_t *idx; float basepose[12 * MAX_BONES]; - float invbasepose[12 * MAX_BONES]; + qboolean baseposeonly; + qboolean noweights; if (memcmp(h->magic, IQM_MAGIC, sizeof(h->magic))) { @@ -5613,17 +5678,6 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) Con_Printf("%s: size (%u != %u)\n", mod->name, h->filesize, com_filesize); return NULL; } -/* - struct iqmjoint - unsigned int name; - int parent; - float translate[3], rotate[3], scale[3]; - - unsigned int num_meshes, ofs_meshes; - unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays; - unsigned int num_triangles, ofs_triangles, ofs_adjacency; - unsigned int num_joints, ofs_joints; -*/ varray = (struct iqmvertexarray*)(buffer + h->ofs_vertexarrays); for (i = 0; i < h->num_vertexarrays; i++) @@ -5651,6 +5705,20 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) if (!h->num_meshes) return NULL; + if (h->num_vertexes > 0 && (!vpos || !tcoord)) + { + Con_Printf("%s is missing vertex array data\n", loadmodel->name); + return NULL; + } + noweights = !vbone || !vweight; + if (noweights) + { + if (h->num_frames || h->num_anims || h->num_joints) + return NULL; + } + + baseposeonly = !h->num_anims; + strings = buffer + h->ofs_text; mesh = (struct iqmmesh*)(buffer + h->ofs_meshes); @@ -5660,18 +5728,27 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) #ifndef SERVERONLY sizeof(*skin)*h->num_meshes + sizeof(*texnum)*h->num_meshes + #endif - sizeof(*fgroup)*h->num_anims + sizeof(float)*12*h->num_poses*h->num_frames + sizeof(*bones)*h->num_joints + - (sizeof(*opos) + sizeof(*onorm) + sizeof(*oweight) + sizeof(*otcoords) + sizeof(*oindex)) * h->num_vertexes); + sizeof(*fgroup)*(baseposeonly?1:h->num_anims) + sizeof(float)*12*(baseposeonly?h->num_joints:(h->num_poses*h->num_frames)) + sizeof(*bones)*h->num_joints + + (sizeof(*opos) + sizeof(*onorm) + sizeof(*otcoords) + (noweights?0:(sizeof(*oindex)+sizeof(*oweight)))) * h->num_vertexes); bones = (galiasbone_t*)(gai + h->num_meshes); opos = (vecV_t*)(bones + h->num_joints); onorm = (vec3_t*)(opos + h->num_vertexes); - oindex = (byte_vec4_t*)(onorm + h->num_vertexes); - oweight = (vec4_t*)(oindex + h->num_vertexes); - otcoords = (vec2_t*)(oweight + h->num_vertexes); + if (noweights) + { + oindex = NULL; + oweight = NULL; + otcoords = (vec2_t*)(onorm + h->num_vertexes); + } + else + { + oindex = (byte_vec4_t*)(onorm + h->num_vertexes); + oweight = (vec4_t*)(oindex + h->num_vertexes); + otcoords = (vec2_t*)(oweight + h->num_vertexes); + } fgroup = (galiasgroup_t*)(otcoords + h->num_vertexes); - opose = (float*)(fgroup + h->num_anims); + opose = (float*)(fgroup + (baseposeonly?1:h->num_anims)); #ifndef SERVERONLY - skin = (galiasskin_t*)(opose + 12*h->num_poses*h->num_frames); + skin = (galiasskin_t*)(opose + 12*(baseposeonly?h->num_joints:h->num_poses*h->num_frames)); texnum = (texnums_t*)(skin + h->num_meshes); #endif @@ -5686,23 +5763,20 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) vec3_t pos; vec4_t quat; vec3_t scale; - float mat[12], mat2[12]; + float mat[12]; for (i = 0; i < h->num_joints; i++) { Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(ijoint[i].name)); bones[i].parent = ijoint[i].parent; - GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]); + GenMatrixPosQuat3Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]); - Matrix3x4_Invert(&basepose[i*12], &invbasepose[12*i]); if (ijoint[i].parent >= 0) - { - Matrix3x4_Multiply(&basepose[i*12], &basepose[ijoint[i].parent*12], mat); + Matrix3x4_Multiply(mat, &basepose[ijoint[i].parent*12], &basepose[i*12]); + else memcpy(&basepose[i*12], mat, sizeof(mat)); - Matrix3x4_Multiply(&invbasepose[ijoint[i].parent*12], &invbasepose[i*12], mat); - memcpy(&invbasepose[i*12], mat, sizeof(mat)); - } + Matrix3x4_Invert_Simple(&basepose[i*12], bones[i].inverse); } for (i = 0; i < h->num_frames; i++) @@ -5721,15 +5795,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) quat[3] = -sqrt(max(1.0 - pow(VectorLength(quat),2), 0.0)); - GenMatrixPosQuat4Scale(pos, quat, scale, opose + (i*h->num_poses+j)*12); - - if (ijoint[j].parent >= 0) - { - Matrix3x4_Multiply(mat, &basepose[ijoint[j].parent*12], mat2); - Matrix3x4_Multiply(&invbasepose[j*12], mat2, &opose[(i*h->num_poses+j)*12]); - } - else - Matrix3x4_Multiply(&invbasepose[j*12], mat, &opose[(i*h->num_poses+j)*12]); + GenMatrixPosQuat3Scale(pos, quat, scale, &opose[(i*h->num_poses+j)*12]); } } } @@ -5740,23 +5806,20 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) vec3_t pos; vec4_t quat; vec3_t scale; - float mat[12], mat2[12]; + float mat[12]; for (i = 0; i < h->num_joints; i++) { Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(bones[i].name)); bones[i].parent = ijoint[i].parent; - GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]); + GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, mat); - Matrix3x4_Invert(&basepose[i*12], &invbasepose[12*i]); if (ijoint[i].parent >= 0) - { - Matrix3x4_Multiply(&basepose[i*12], &basepose[ijoint[i].parent*12], mat); + Matrix3x4_Multiply(mat, &basepose[ijoint[i].parent*12], &basepose[i*12]); + else memcpy(&basepose[i*12], mat, sizeof(mat)); - Matrix3x4_Multiply(&invbasepose[ijoint[i].parent*12], &invbasepose[i*12], mat); - memcpy(&invbasepose[i*12], mat, sizeof(mat)); - } + Matrix3x4_Invert_Simple(&basepose[i*12], bones[i].inverse); } for (i = 0; i < h->num_frames; i++) @@ -5774,29 +5837,35 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) scale[1] = p->channeloffset[8]; if (p->mask & 256) scale[1] += *framedata++ * p->channelscale[8]; scale[2] = p->channeloffset[9]; if (p->mask & 512) scale[2] += *framedata++ * p->channelscale[9]; - GenMatrixPosQuat4Scale(pos, quat, scale, mat); - - if (ijoint[j].parent >= 0) - { - Matrix3x4_Multiply(mat, &basepose[ijoint[j].parent*12], mat2); - Matrix3x4_Multiply(&invbasepose[j*12], mat2, &opose[(i*h->num_poses+j)*12]); - } - else - Matrix3x4_Multiply(&invbasepose[j*12], mat, &opose[(i*h->num_poses+j)*12]); + GenMatrixPosQuat4Scale(pos, quat, scale, &opose[(i*h->num_poses+j)*12]); } } } - /*load the framegroup info*/ - anim = (struct iqmanim*)(buffer + h->ofs_anims); - for (i = 0; i < h->num_anims; i++) + if (baseposeonly) { - fgroup[i].isheirachical = true; - fgroup[i].loop = LittleLong(anim[i].flags) & IQM_LOOP; - Q_strncpyz(fgroup[i].name, strings+anim[i].name, sizeof(fgroup[i].name)); - fgroup[i].numposes = LittleLong(anim[i].num_frames); - fgroup[i].poseofs = (char*)(opose+LittleLong(anim[i].first_frame)*12*h->num_poses) - (char*)&fgroup[i]; - fgroup[i].rate = LittleFloat(anim[i].framerate); + fgroup->isheirachical = false; + fgroup->loop = true; + Q_strncpyz(fgroup->name, "base", sizeof(fgroup->name)); + fgroup->numposes = 1; + fgroup->poseofs = (char*)opose - (char*)fgroup; + fgroup->rate = 10; + + memcpy(opose, basepose, sizeof(float)*12 * h->num_joints); + } + else + { + /*load the framegroup info*/ + anim = (struct iqmanim*)(buffer + h->ofs_anims); + for (i = 0; i < h->num_anims; i++) + { + fgroup[i].isheirachical = true; + fgroup[i].loop = LittleLong(anim[i].flags) & IQM_LOOP; + Q_strncpyz(fgroup[i].name, strings+anim[i].name, sizeof(fgroup[i].name)); + fgroup[i].numposes = LittleLong(anim[i].num_frames); + fgroup[i].poseofs = (char*)(opose+LittleLong(anim[i].first_frame)*12*h->num_poses) - (char*)&fgroup[i]; + fgroup[i].rate = LittleFloat(anim[i].framerate); + } } for (i = 0; i < h->num_meshes; i++) @@ -5807,7 +5876,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) gai[i].shares_bones = 0; gai[i].numbones = h->num_joints; gai[i].ofsbones = (char*)bones - (char*)&gai[i]; - gai[i].groups = h->num_anims; + gai[i].groups = baseposeonly?1:h->num_anims; gai[i].groupofs = (char*)fgroup - (char*)&gai[i]; offset = LittleLong(mesh[i].first_vertex); @@ -5850,16 +5919,22 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) gai[i].ofs_skel_norm = (char*)(onorm+offset) - (char*)&gai[i]; gai[i].ofs_skel_svect = 0; gai[i].ofs_skel_tvect = 0; - gai[i].ofs_skel_idx = (char*)(oindex+offset) - (char*)&gai[i]; - gai[i].ofs_skel_weight = (char*)(oweight+offset) - (char*)&gai[i]; + gai[i].ofs_skel_idx = oindex?(char*)(oindex+offset) - (char*)&gai[i]:0; + gai[i].ofs_skel_weight = oweight?(char*)(oweight+offset) - (char*)&gai[i]:0; + } + if (!noweights) + { + for (i = 0; i < h->num_vertexes; i++) + { + Vector4Copy(vbone+i*4, oindex[i]); + Vector4Scale(vweight+i*4, 1/255.0, oweight[i]); + } } for (i = 0; i < h->num_vertexes; i++) { Vector2Copy(tcoord+i*2, otcoords[i]); VectorCopy(vpos+i*3, opos[i]); VectorCopy(vnorm+i*4, onorm[i]); - Vector4Copy(vbone+i*4, oindex[i]); - Vector4Scale(vweight+i*4, 1/255.0, oweight[i]); } return gai; } diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index 1a2843244..a140f3626 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -81,11 +81,13 @@ typedef struct { vec3_t scale_origin; } galiaspose_t; +typedef struct galiasbone_s galiasbone_t; #ifdef SKELETALMODELS -typedef struct galiasbone_s { +struct galiasbone_s { char name[32]; int parent; -} galiasbone_t; + float inverse[12]; +}; typedef struct { //skeletal poses refer to this. @@ -123,7 +125,7 @@ typedef struct { } galiascolourmapped_t; #endif -float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *buffer, int buffersize); +float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *buffer, int buffersize, qboolean renderable); #ifdef SKELETALMODELS void Alias_TransformVerticies(float *bonepose, galisskeletaltransforms_t *weights, int numweights, vecV_t *xyzout, vec3_t *normout); #endif diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index fa2fa7b5d..4e5dc5358 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -47,13 +47,22 @@ cvar_t physics_ode_worldquickstep_iterations = CVARDP4(0, "physics_ode_worldquic cvar_t physics_ode_contact_mu = CVARDP4(0, "physics_ode_contact_mu", "1", "contact solver mu parameter - friction pyramid approximation 1 (see ODE User Guide)"); cvar_t physics_ode_contact_erp = CVARDP4(0, "physics_ode_contact_erp", "0.96", "contact solver erp parameter - Error Restitution Percent (see ODE User Guide)"); cvar_t physics_ode_contact_cfm = CVARDP4(0, "physics_ode_contact_cfm", "0", "contact solver cfm parameter - Constraint Force Mixing (see ODE User Guide)"); -cvar_t physics_ode_world_damping_angle = CVARDP4(0, "physics_ode_world_damping_angle", "0", "damping"); -cvar_t physics_ode_world_damping_linear = CVARDP4(0, "physics_ode_world_damping_linear", "0", "damping"); +cvar_t physics_ode_world_damping = CVARDP4(0, "physics_ode_world_damping", "1", "enabled damping scale (see ODE User Guide), this scales all damping values, be aware that behavior depends of step type"); +cvar_t physics_ode_world_damping_linear = CVARDP4(0, "physics_ode_world_damping_linear", "0.005", "world linear damping scale (see ODE User Guide); use defaults when set to -1"); +cvar_t physics_ode_world_damping_linear_threshold = CVARDP4(0, "physics_ode_world_damping_linear_threshold", "0.01", "world linear damping threshold (see ODE User Guide); use defaults when set to -1"); +cvar_t physics_ode_world_damping_angular = CVARDP4(0, "physics_ode_world_damping_angular", "0.005", "world angular damping scale (see ODE User Guide); use defaults when set to -1"); +cvar_t physics_ode_world_damping_angular_threshold = CVARDP4(0, "physics_ode_world_damping_angular_threshold", "0.01", "world angular damping threshold (see ODE User Guide); use defaults when set to -1"); cvar_t physics_ode_world_erp = CVARDP4(0, "physics_ode_world_erp", "-1", "world solver erp parameter - Error Restitution Percent (see ODE User Guide); use defaults when set to -1"); cvar_t physics_ode_world_cfm = CVARDP4(0, "physics_ode_world_cfm", "-1", "world solver cfm parameter - Constraint Force Mixing (see ODE User Guide); not touched when -1"); cvar_t physics_ode_iterationsperframe = CVARDP4(0, "physics_ode_iterationsperframe", "4", "divisor for time step, runs multiple physics steps per frame"); cvar_t physics_ode_movelimit = CVARDP4(0, "physics_ode_movelimit", "0.5", "clamp velocity if a single move would exceed this percentage of object thickness, to prevent flying through walls"); cvar_t physics_ode_spinlimit = CVARDP4(0, "physics_ode_spinlimit", "10000", "reset spin velocity if it gets too large"); +cvar_t physics_ode_autodisable = CVARDP4(0, "physics_ode_autodisable", "1", "automatic disabling of objects which dont move for long period of time, makes object stacking a lot faster"); +cvar_t physics_ode_autodisable_steps = CVARDP4(0, "physics_ode_autodisable_steps", "10", "how many steps object should be dormant to be autodisabled"); +cvar_t physics_ode_autodisable_time = CVARDP4(0, "physics_ode_autodisable_time", "0", "how many seconds object should be dormant to be autodisabled"); +cvar_t physics_ode_autodisable_threshold_linear = CVARDP4(0, "physics_ode_autodisable_threshold_linear", "0.2", "body will be disabled if it's linear move below this value"); +cvar_t physics_ode_autodisable_threshold_angular = CVARDP4(0, "physics_ode_autodisable_threshold_angular", "0.3", "body will be disabled if it's angular move below this value"); +cvar_t physics_ode_autodisable_threshold_samples = CVARDP4(0, "physics_ode_autodisable_threshold_samples", "5", "average threshold with this number of samples"); // LordHavoc: this large chunk of definitions comes from the ODE library // include files. @@ -294,30 +303,30 @@ void (ODE_API *dWorldSetContactSurfaceLayer)(dWorldID, dReal depth); //void (ODE_API *dWorldSetAutoEnableDepthSF1)(dWorldID, int autoEnableDepth); //int (ODE_API *dWorldGetAutoEnableDepthSF1)(dWorldID); //dReal (ODE_API *dWorldGetAutoDisableLinearThreshold)(dWorldID); -//void (ODE_API *dWorldSetAutoDisableLinearThreshold)(dWorldID, dReal linear_threshold); +void (ODE_API *dWorldSetAutoDisableLinearThreshold)(dWorldID, dReal linear_threshold); //dReal (ODE_API *dWorldGetAutoDisableAngularThreshold)(dWorldID); -//void (ODE_API *dWorldSetAutoDisableAngularThreshold)(dWorldID, dReal angular_threshold); +void (ODE_API *dWorldSetAutoDisableAngularThreshold)(dWorldID, dReal angular_threshold); //dReal (ODE_API *dWorldGetAutoDisableLinearAverageThreshold)(dWorldID); //void (ODE_API *dWorldSetAutoDisableLinearAverageThreshold)(dWorldID, dReal linear_average_threshold); //dReal (ODE_API *dWorldGetAutoDisableAngularAverageThreshold)(dWorldID); //void (ODE_API *dWorldSetAutoDisableAngularAverageThreshold)(dWorldID, dReal angular_average_threshold); //int (ODE_API *dWorldGetAutoDisableAverageSamplesCount)(dWorldID); -//void (ODE_API *dWorldSetAutoDisableAverageSamplesCount)(dWorldID, unsigned int average_samples_count ); +void (ODE_API *dWorldSetAutoDisableAverageSamplesCount)(dWorldID, unsigned int average_samples_count ); //int (ODE_API *dWorldGetAutoDisableSteps)(dWorldID); -//void (ODE_API *dWorldSetAutoDisableSteps)(dWorldID, int steps); +void (ODE_API *dWorldSetAutoDisableSteps)(dWorldID, int steps); //dReal (ODE_API *dWorldGetAutoDisableTime)(dWorldID); -//void (ODE_API *dWorldSetAutoDisableTime)(dWorldID, dReal time); +void (ODE_API *dWorldSetAutoDisableTime)(dWorldID, dReal time); //int (ODE_API *dWorldGetAutoDisableFlag)(dWorldID); void (ODE_API *dWorldSetAutoDisableFlag)(dWorldID, int do_auto_disable); //dReal (ODE_API *dWorldGetLinearDampingThreshold)(dWorldID w); -//void (ODE_API *dWorldSetLinearDampingThreshold)(dWorldID w, dReal threshold); +void (ODE_API *dWorldSetLinearDampingThreshold)(dWorldID w, dReal threshold); //dReal (ODE_API *dWorldGetAngularDampingThreshold)(dWorldID w); -//void (ODE_API *dWorldSetAngularDampingThreshold)(dWorldID w, dReal threshold); +void (ODE_API *dWorldSetAngularDampingThreshold)(dWorldID w, dReal threshold); //dReal (ODE_API *dWorldGetLinearDamping)(dWorldID w); -//void (ODE_API *dWorldSetLinearDamping)(dWorldID w, dReal scale); +void (ODE_API *dWorldSetLinearDamping)(dWorldID w, dReal scale); //dReal (ODE_API *dWorldGetAngularDamping)(dWorldID w); -//void (ODE_API *dWorldSetAngularDamping)(dWorldID w, dReal scale); -void (ODE_API *dWorldSetDamping)(dWorldID w, dReal linear_scale, dReal angular_scale); +void (ODE_API *dWorldSetAngularDamping)(dWorldID w, dReal scale); +//void (ODE_API *dWorldSetDamping)(dWorldID w, dReal linear_scale, dReal angular_scale); //dReal (ODE_API *dWorldGetMaxAngularSpeed)(dWorldID w); //void (ODE_API *dWorldSetMaxAngularSpeed)(dWorldID w, dReal max_speed); //dReal (ODE_API *dBodyGetAutoDisableLinearThreshold)(dBodyID); @@ -759,30 +768,30 @@ static dllfunction_t odefuncs[] = // {"dWorldSetAutoEnableDepthSF1", (void **) &dWorldSetAutoEnableDepthSF1}, // {"dWorldGetAutoEnableDepthSF1", (void **) &dWorldGetAutoEnableDepthSF1}, // {"dWorldGetAutoDisableLinearThreshold", (void **) &dWorldGetAutoDisableLinearThreshold}, -// {"dWorldSetAutoDisableLinearThreshold", (void **) &dWorldSetAutoDisableLinearThreshold}, + {(void **) &dWorldSetAutoDisableLinearThreshold,"dWorldSetAutoDisableLinearThreshold"}, // {"dWorldGetAutoDisableAngularThreshold", (void **) &dWorldGetAutoDisableAngularThreshold}, -// {"dWorldSetAutoDisableAngularThreshold", (void **) &dWorldSetAutoDisableAngularThreshold}, + {(void **) &dWorldSetAutoDisableAngularThreshold,"dWorldSetAutoDisableAngularThreshold"}, // {"dWorldGetAutoDisableLinearAverageThreshold", (void **) &dWorldGetAutoDisableLinearAverageThreshold}, // {"dWorldSetAutoDisableLinearAverageThreshold", (void **) &dWorldSetAutoDisableLinearAverageThreshold}, // {"dWorldGetAutoDisableAngularAverageThreshold", (void **) &dWorldGetAutoDisableAngularAverageThreshold}, // {"dWorldSetAutoDisableAngularAverageThreshold", (void **) &dWorldSetAutoDisableAngularAverageThreshold}, // {"dWorldGetAutoDisableAverageSamplesCount", (void **) &dWorldGetAutoDisableAverageSamplesCount}, -// {"dWorldSetAutoDisableAverageSamplesCount", (void **) &dWorldSetAutoDisableAverageSamplesCount}, + {(void **)&dWorldSetAutoDisableAverageSamplesCount, "dWorldSetAutoDisableAverageSamplesCount"}, // {"dWorldGetAutoDisableSteps", (void **) &dWorldGetAutoDisableSteps}, -// {"dWorldSetAutoDisableSteps", (void **) &dWorldSetAutoDisableSteps}, + {(void **) &dWorldSetAutoDisableSteps, "dWorldSetAutoDisableSteps"}, // {"dWorldGetAutoDisableTime", (void **) &dWorldGetAutoDisableTime}, -// {"dWorldSetAutoDisableTime", (void **) &dWorldSetAutoDisableTime}, + {(void **) &dWorldSetAutoDisableTime, "dWorldSetAutoDisableTime"}, // {"dWorldGetAutoDisableFlag", (void **) &dWorldGetAutoDisableFlag}, {(void **) &dWorldSetAutoDisableFlag, "dWorldSetAutoDisableFlag"}, // {"dWorldGetLinearDampingThreshold", (void **) &dWorldGetLinearDampingThreshold}, -// {"dWorldSetLinearDampingThreshold", (void **) &dWorldSetLinearDampingThreshold}, + {(void **) &dWorldSetLinearDampingThreshold, "dWorldSetLinearDampingThreshold"}, // {"dWorldGetAngularDampingThreshold", (void **) &dWorldGetAngularDampingThreshold}, -// {"dWorldSetAngularDampingThreshold", (void **) &dWorldSetAngularDampingThreshold}, + {(void **) &dWorldSetAngularDampingThreshold, "dWorldSetAngularDampingThreshold"}, // {"dWorldGetLinearDamping", (void **) &dWorldGetLinearDamping}, -// {"dWorldSetLinearDamping", (void **) &dWorldSetLinearDamping}, + {(void **) &dWorldSetLinearDamping, "dWorldSetLinearDamping"}, // {"dWorldGetAngularDamping", (void **) &dWorldGetAngularDamping}, -// {"dWorldSetAngularDamping", (void **) &dWorldSetAngularDamping}, - {(void **) &dWorldSetDamping, "dWorldSetDamping"}, + {(void **) &dWorldSetAngularDamping, "dWorldSetAngularDamping"}, +// {(void **) &dWorldSetDamping, "dWorldSetDamping"}, // {"dWorldGetMaxAngularSpeed", (void **) &dWorldGetMaxAngularSpeed}, // {"dWorldSetMaxAngularSpeed", (void **) &dWorldSetMaxAngularSpeed}, // {"dBodyGetAutoDisableLinearThreshold", (void **) &dBodyGetAutoDisableLinearThreshold}, @@ -1187,13 +1196,22 @@ void World_ODE_Init(void) Cvar_Register(&physics_ode_contact_mu, "ODE Physics Library"); Cvar_Register(&physics_ode_contact_erp, "ODE Physics Library"); Cvar_Register(&physics_ode_contact_cfm, "ODE Physics Library"); - Cvar_Register(&physics_ode_world_damping_angle, "ODE Physics Library"); + Cvar_Register(&physics_ode_world_damping, "ODE Physics Library"); Cvar_Register(&physics_ode_world_damping_linear, "ODE Physics Library"); + Cvar_Register(&physics_ode_world_damping_linear_threshold, "ODE Physics Library"); + Cvar_Register(&physics_ode_world_damping_angular, "ODE Physics Library"); + Cvar_Register(&physics_ode_world_damping_angular_threshold, "ODE Physics Library"); Cvar_Register(&physics_ode_world_erp, "ODE Physics Library"); Cvar_Register(&physics_ode_world_cfm, "ODE Physics Library"); Cvar_Register(&physics_ode_iterationsperframe, "ODE Physics Library"); Cvar_Register(&physics_ode_movelimit, "ODE Physics Library"); Cvar_Register(&physics_ode_spinlimit, "ODE Physics Library"); + Cvar_Register(&physics_ode_autodisable, "ODE Physics Library"); + Cvar_Register(&physics_ode_autodisable_steps, "ODE Physics Library"); + Cvar_Register(&physics_ode_autodisable_time, "ODE Physics Library"); + Cvar_Register(&physics_ode_autodisable_threshold_linear, "ODE Physics Library"); + Cvar_Register(&physics_ode_autodisable_threshold_angular, "ODE Physics Library"); + Cvar_Register(&physics_ode_autodisable_threshold_samples, "ODE Physics Library"); #ifdef ODE_DYNAMIC // Load the DLL @@ -1263,12 +1281,37 @@ static void World_ODE_Enable(world_t *world) world->ode.ode_world = dWorldCreate(); world->ode.ode_space = dQuadTreeSpaceCreate(NULL, center, extents, bound(1, physics_ode_quadtree_depth.ival, 10)); world->ode.ode_contactgroup = dJointGroupCreate(0); + + if(physics_ode_world_erp.value >= 0) dWorldSetERP(world->ode.ode_world, physics_ode_world_erp.value); if(physics_ode_world_cfm.value >= 0) dWorldSetCFM(world->ode.ode_world, physics_ode_world_cfm.value); - dWorldSetDamping(world->ode.ode_world, physics_ode_world_damping_linear.value, physics_ode_world_damping_angle.value); -// dWorldSetAutoDisableFlag (world->ode.ode_world, true); + if (physics_ode_world_damping.ival) + { + dWorldSetLinearDamping(world->ode.ode_world, (physics_ode_world_damping_linear.value >= 0) ? (physics_ode_world_damping_linear.value * physics_ode_world_damping.value) : 0); + dWorldSetLinearDampingThreshold(world->ode.ode_world, (physics_ode_world_damping_linear_threshold.value >= 0) ? (physics_ode_world_damping_linear_threshold.value * physics_ode_world_damping.value) : 0); + dWorldSetAngularDamping(world->ode.ode_world, (physics_ode_world_damping_angular.value >= 0) ? (physics_ode_world_damping_angular.value * physics_ode_world_damping.value) : 0); + dWorldSetAngularDampingThreshold(world->ode.ode_world, (physics_ode_world_damping_angular_threshold.value >= 0) ? (physics_ode_world_damping_angular_threshold.value * physics_ode_world_damping.value) : 0); + } + else + { + dWorldSetLinearDamping(world->ode.ode_world, 0); + dWorldSetLinearDampingThreshold(world->ode.ode_world, 0); + dWorldSetAngularDamping(world->ode.ode_world, 0); + dWorldSetAngularDampingThreshold(world->ode.ode_world, 0); + } + if (physics_ode_autodisable.ival) + { + dWorldSetAutoDisableSteps(world->ode.ode_world, bound(1, physics_ode_autodisable_steps.ival, 100)); + dWorldSetAutoDisableTime(world->ode.ode_world, physics_ode_autodisable_time.value); + dWorldSetAutoDisableAverageSamplesCount(world->ode.ode_world, bound(1, physics_ode_autodisable_threshold_samples.ival, 100)); + dWorldSetAutoDisableLinearThreshold(world->ode.ode_world, physics_ode_autodisable_threshold_linear.value); + dWorldSetAutoDisableAngularThreshold(world->ode.ode_world, physics_ode_autodisable_threshold_angular.value); + dWorldSetAutoDisableFlag (world->ode.ode_world, true); + } + else + dWorldSetAutoDisableFlag (world->ode.ode_world, false); } void World_ODE_Start(world_t *world) @@ -1967,7 +2010,7 @@ static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed) gravity = false; // compatibility for legacy entities - //if (!VectorLength2(forward) || solid == SOLID_BSP) +// if (!DotProduct(forward,forward) || solid == SOLID_BSP) { vec3_t qangles, qavelocity; VectorCopy(angles, qangles); @@ -2270,6 +2313,21 @@ void World_ODE_Frame(world_t *world, double frametime, double gravity) int i; wedict_t *ed; + if (!world->ode.hasodeents) + { + for (i = 0; i < world->num_edicts; i++) + { + ed = (wedict_t*)EDICT_NUM(world->progs, i); + if (ed->v->movetype >= SOLID_PHYSICS_BOX) + { + world->ode.hasodeents = true; + break; + } + } + if (!world->ode.hasodeents) + return; + } + world->ode.ode_iterations = bound(1, physics_ode_iterationsperframe.ival, 1000); world->ode.ode_step = frametime / world->ode.ode_iterations; world->ode.ode_movelimit = physics_ode_movelimit.value / world->ode.ode_step; diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index f0a8b26f2..827744db5 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -1956,14 +1956,14 @@ qboolean CModQ3_LoadSubmodels (lump_t *l) out->maxs[j] = LittleFloat (in->maxs[j]) + 1; out->origin[j] = (out->maxs[j] + out->mins[j])/2; } + out->firstsurface = LittleLong (in->firstsurface); + out->numsurfaces = LittleLong (in->num_surfaces); if (!i) out->headnode = 0; else { //create a new leaf to hold the bruses and be directly clipped out->headnode = -1 - numleafs; - out->firstsurface = LittleLong (in->firstsurface); - out->numsurfaces = LittleLong (in->num_surfaces); // out->firstbrush = LittleLong(in->firstbrush); // out->num_brushes = LittleLong(in->num_brushes); @@ -3937,6 +3937,8 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c mod->hulls[j].available = false; } + mod->nummodelsurfaces = map_cmodels[0].numsurfaces; + for (i=1 ; i< loadmodel->numsubmodels ; i++) { cmodel_t *bm; diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 0d128cea6..f11185abe 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -321,12 +321,12 @@ void VectorAngles(float *forward, float *up, float *result) //up may be NULL { if (forward[2] > 0) { - pitch = 90; + pitch = -M_PI * 0.5; yaw = up ? atan2(-up[1], -up[0]) : 0; } else { - pitch = 270; + pitch = M_PI * 0.5; yaw = up ? atan2(up[1], up[0]) : 0; } roll = 0; diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index da17f527a..95a1c9f6d 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -1275,7 +1275,7 @@ qboolean NET_IsClientLegal(netadr_t *adr) NetadrToSockadr (adr, &sadr); - if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) Sys_Error ("NET_IsClientLegal: socket:", strerror(qerrno)); sadr.sin_port = 0; @@ -1785,7 +1785,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i ftenet_generic_connection_t *newcon; unsigned long _true = true; - int newsocket = INVALID_SOCKET; + SOCKET newsocket = INVALID_SOCKET; int temp; netadr_t adr; struct sockaddr_qstorage qs; @@ -1848,8 +1848,10 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i return NULL; } - if (family == AF_INET6 && !net_hybriddualstack.ival) +#ifdef IPV6_V6ONLY + if (family == AF_INET6) setsockopt(newsocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&_true, sizeof(_true)); +#endif bufsz = 1<<18; setsockopt(newsocket, SOL_SOCKET, SO_RCVBUF, (void*)&bufsz, sizeof(bufsz)); @@ -3071,7 +3073,7 @@ int maxport = port + 100; int UDP_OpenSocket (int port, qboolean bcast) { - int newsocket; + SOCKET newsocket; struct sockaddr_in address; unsigned long _true = true; int i; @@ -3128,7 +3130,7 @@ int maxport = port + 100; int UDP6_OpenSocket (int port, qboolean bcast) { int err; - int newsocket; + SOCKET newsocket; struct sockaddr_in6 address; unsigned long _true = true; // int i; @@ -3136,7 +3138,7 @@ int maxport = port + 100; memset(&address, 0, sizeof(address)); - if ((newsocket = socket (PF_INET6, SOCK_DGRAM, 0)) == -1) + if ((newsocket = socket (PF_INET6, SOCK_DGRAM, 0)) == INVALID_SOCKET) { Con_Printf("IPV6 is not supported: %s\n", strerror(qerrno)); return INVALID_SOCKET; @@ -3213,11 +3215,11 @@ int IPX_OpenSocket (int port, qboolean bcast) #ifndef USEIPX return 0; #else - int newsocket; + SOCKET newsocket; struct sockaddr_ipx address; u_long _true = 1; - if ((newsocket = socket (PF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == -1) + if ((newsocket = socket (PF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == INVALID_SOCKET) { if (qerrno != EAFNOSUPPORT) Con_Printf ("WARNING: IPX_Socket: socket: %i\n", qerrno); @@ -3347,7 +3349,7 @@ void NET_GetLocalAddress (int socket, netadr_t *out) } #ifndef CLIENTONLY -void SVNET_AddPort(void) +void SVNET_AddPort_f(void) { netadr_t adr; char *s = Cmd_Argv(1); @@ -3441,6 +3443,10 @@ void NET_Init (void) #endif Cvar_Register(&net_hybriddualstack, "networking"); + +#ifndef CLIENTONLY + Cmd_AddCommand("sv_addport", SVNET_AddPort_f); +#endif } #ifndef SERVERONLY void NET_InitClient(void) diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 48106d554..f9011caa7 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -178,6 +178,228 @@ void VARGS PR_CB_Free(void *mem) BZ_Free(mem); } + +//////////////////////////////////////////////////// +//model functions +//DP_QC_GETSURFACE +// #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) +void QCBUILTIN PF_getsurfacenumpoints(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int surfnum; + model_t *model; + wedict_t *ent; + world_t *w = prinst->parms->user; + + ent = G_WEDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + + model = w->Get_CModel(w, ent->v->modelindex); + + if (!model || model->type != mod_brush || surfnum >= model->nummodelsurfaces) + G_FLOAT(OFS_RETURN) = 0; + else + { + surfnum += model->firstmodelsurface; + G_FLOAT(OFS_RETURN) = model->surfaces[surfnum].mesh->numvertexes; + } +} +// #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) +void QCBUILTIN PF_getsurfacepoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int surfnum, pointnum; + model_t *model; + wedict_t *ent; + world_t *w = prinst->parms->user; + + ent = G_WEDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + pointnum = G_FLOAT(OFS_PARM2); + + model = w->Get_CModel(w, ent->v->modelindex); + + if (!model || model->type != mod_brush || surfnum >= model->nummodelsurfaces) + { + G_FLOAT(OFS_RETURN+0) = 0; + G_FLOAT(OFS_RETURN+1) = 0; + G_FLOAT(OFS_RETURN+2) = 0; + } + else + { + surfnum += model->firstmodelsurface; + + G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].mesh->xyz_array[pointnum][0]; + G_FLOAT(OFS_RETURN+1) = model->surfaces[surfnum].mesh->xyz_array[pointnum][1]; + G_FLOAT(OFS_RETURN+2) = model->surfaces[surfnum].mesh->xyz_array[pointnum][2]; + } +} +// #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) +void QCBUILTIN PF_getsurfacenormal(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int surfnum, pointnum; + model_t *model; + wedict_t *ent; + world_t *w = prinst->parms->user; + + ent = G_WEDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + pointnum = G_FLOAT(OFS_PARM2); + + model = w->Get_CModel(w, ent->v->modelindex); + + if (!model || model->type != mod_brush || surfnum >= model->nummodelsurfaces) + { + G_FLOAT(OFS_RETURN+0) = 0; + G_FLOAT(OFS_RETURN+1) = 0; + G_FLOAT(OFS_RETURN+2) = 0; + } + else + { + surfnum += model->firstmodelsurface; + + G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].plane->normal[0]; + G_FLOAT(OFS_RETURN+1) = model->surfaces[surfnum].plane->normal[1]; + G_FLOAT(OFS_RETURN+2) = model->surfaces[surfnum].plane->normal[2]; + if (model->surfaces[surfnum].flags & SURF_PLANEBACK) + VectorInverse(G_VECTOR(OFS_RETURN)); + } +} +// #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) +void QCBUILTIN PF_getsurfacetexture(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + model_t *model; + wedict_t *ent; + msurface_t *surf; + int surfnum; + world_t *w = prinst->parms->user; + + ent = G_WEDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + + model = w->Get_CModel(w, ent->v->modelindex); + + G_INT(OFS_RETURN) = 0; + if (!model || model->type != mod_brush) + return; + + if (surfnum < 0 || surfnum > model->nummodelsurfaces) + return; + surfnum += model->firstmodelsurface; + surf = &model->surfaces[surfnum]; + G_INT(OFS_RETURN) = PR_TempString(prinst, surf->texinfo->texture->name); +} +// #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) +void QCBUILTIN PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + model_t *model; + wedict_t *ent; + msurface_t *surf; + int i; + float planedist; + float *point; + + vec3_t edgedir; + vec3_t edgenormal; + vec3_t cpoint, temp; + mvertex_t *v1, *v2; + int edge; + int e; + float bestdist = 10000000000000, dist; + int bestsurf = -1; + world_t *w = prinst->parms->user; + + ent = G_WEDICT(prinst, OFS_PARM0); + point = G_VECTOR(OFS_PARM1); + + G_FLOAT(OFS_RETURN) = -1; + + model = w->Get_CModel(w, ent->v->modelindex); + + if (!model || model->type != mod_brush) + return; + + if (model->fromgame != fg_quake) + return; + + + surf = model->surfaces + model->firstmodelsurface; + for (i = 0; i < model->nummodelsurfaces; i++, surf++) + { + planedist = DotProduct(point, surf->plane->normal) - surf->plane->dist; + //don't care about SURF_PLANEBACK, the maths works out the same. + + if (planedist*planedist < bestdist) + { //within a specific range + //make sure it's within the poly + VectorMA(point, planedist, surf->plane->normal, cpoint); + for (e = surf->firstedge+surf->numedges; e > surf->firstedge; edge++) + { + edge = model->surfedges[--e]; + if (edge < 0) + { + v1 = &model->vertexes[model->edges[-edge].v[0]]; + v2 = &model->vertexes[model->edges[-edge].v[1]]; + } + else + { + v2 = &model->vertexes[model->edges[edge].v[0]]; + v1 = &model->vertexes[model->edges[edge].v[1]]; + } + + VectorSubtract(v1->position, v2->position, edgedir); + CrossProduct(edgedir, surf->plane->normal, edgenormal); + if (!(surf->flags & SURF_PLANEBACK)) + { + VectorNegate(edgenormal, edgenormal); + } + VectorNormalize(edgenormal); + + dist = DotProduct(v1->position, edgenormal) - DotProduct(cpoint, edgenormal); + if (dist < 0) + VectorMA(cpoint, dist, edgenormal, cpoint); + } + + VectorSubtract(cpoint, point, temp); + dist = DotProduct(temp, temp); + if (dist < bestdist) + { + bestsurf = i; + bestdist = dist; + } + } + } + G_FLOAT(OFS_RETURN) = bestsurf; +} + +// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) +void QCBUILTIN PF_getsurfaceclippedpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} + +void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + int action = G_FLOAT(OFS_PARM0); + float *pos = G_VECTOR(OFS_PARM1); + float radius = G_FLOAT(OFS_PARM2); + float quant = G_FLOAT(OFS_PARM3); +#if defined(TERRAIN) + G_FLOAT(OFS_RETURN) = Heightmap_Edit(w->worldmodel, action, pos, radius, quant); +#else + G_FLOAT(OFS_RETURN) = false; +#endif +} + +//end model functions +//////////////////////////////////////////////////// + +void PF_touchtriggers(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + wedict_t *ent = (wedict_t*)PROG_TO_EDICT(prinst, *w->g.self); + World_LinkEdict (w, ent, true); +} + + //////////////////////////////////////////////////// //Finding @@ -280,7 +502,7 @@ void QCBUILTIN PF_FindFlags (progfuncs_t *prinst, struct globalvars_s *pr_global { int e, f; int s; - edict_t *ed; + wedict_t *ed; e = G_EDICTNUM(prinst, OFS_PARM0); f = G_INT(OFS_PARM1)+prinst->fieldadjust; @@ -288,7 +510,7 @@ void QCBUILTIN PF_FindFlags (progfuncs_t *prinst, struct globalvars_s *pr_global for (e++; e < *prinst->parms->sv_num_edicts; e++) { - ed = EDICT_NUM(prinst, e); + ed = WEDICT_NUM(prinst, e); if (ed->isfree) continue; if ((int)((float *)ed->v)[f] & s) @@ -306,7 +528,7 @@ void QCBUILTIN PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_global { int e, f; int s; - edict_t *ed; + wedict_t *ed; if (*prinst->callargc != 3) //I can hate mvdsv if I want to. { @@ -320,7 +542,7 @@ void QCBUILTIN PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_global for (e++; e < *prinst->parms->sv_num_edicts; e++) { - ed = EDICT_NUM(prinst, e); + ed = WEDICT_NUM(prinst, e); if (ed->isfree) continue; if (((int *)ed->v)[f] == s) @@ -340,7 +562,7 @@ void QCBUILTIN PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globa int f; char *s; string_t t; - edict_t *ed; + wedict_t *ed; e = G_EDICTNUM(prinst, OFS_PARM0); f = G_INT(OFS_PARM1)+prinst->fieldadjust; @@ -353,7 +575,7 @@ void QCBUILTIN PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globa for (e++ ; e < *prinst->parms->sv_num_edicts ; e++) { - ed = EDICT_NUM(prinst, e); + ed = WEDICT_NUM(prinst, e); if (ed->isfree) continue; t = ((string_t *)ed->v)[f]; @@ -436,6 +658,20 @@ void QCBUILTIN PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals Cvar_Set (var, val); } +void QCBUILTIN PF_cvar_setlatch (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *var_name, *val; + cvar_t *var; + + var_name = PR_GetStringOfs(prinst, OFS_PARM0); + val = PR_GetStringOfs(prinst, OFS_PARM1); + + var = Cvar_Get(var_name, val, 0, "QC variables"); + if (!var) + return; + Cvar_LockFromServer(var, val); +} + void QCBUILTIN PF_cvar_setf (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *var_name; @@ -1003,15 +1239,15 @@ void PR_fclose_progs (progfuncs_t *prinst) void QCBUILTIN PF_WasFreed (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - edict_t *ent; - ent = (edict_t*)G_EDICT(prinst, OFS_PARM0); + wedict_t *ent; + ent = G_WEDICT(prinst, OFS_PARM0); G_FLOAT(OFS_RETURN) = ent->isfree; } void QCBUILTIN PF_num_for_edict (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - edict_t *ent; - ent = (edict_t*)G_EDICT(prinst, OFS_PARM0); + wedict_t *ent; + ent = G_WEDICT(prinst, OFS_PARM0); G_FLOAT(OFS_RETURN) = ent->entnum; } @@ -1027,7 +1263,7 @@ void QCBUILTIN PF_edict_for_num(progfuncs_t *prinst, struct globalvars_s *pr_glo void QCBUILTIN PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int i; - edict_t *ent; + wedict_t *ent; i = G_EDICTNUM(prinst, OFS_PARM0); while (1) @@ -1038,7 +1274,7 @@ void QCBUILTIN PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_EDICT(prinst, *prinst->parms->sv_edicts); return; } - ent = EDICT_NUM(prinst, i); + ent = WEDICT_NUM(prinst, i); if (!ent->isfree) { RETURN_EDICT(prinst, ent); @@ -2545,7 +2781,7 @@ void QCBUILTIN PF_eprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) int size = 1024*1024; char *buffer = BZ_Malloc(size); char *buf; - buf = prinst->saveent(prinst, buffer, &size, G_EDICT(prinst, OFS_PARM0)); + buf = prinst->saveent(prinst, buffer, &size, (struct edict_s*)G_WEDICT(prinst, OFS_PARM0)); Con_Printf("Entity %i:\n%s\n", G_EDICTNUM(prinst, OFS_PARM0), buf); BZ_Free(buffer); } @@ -2981,7 +3217,10 @@ static void PR_AutoCvarApply(progfuncs_t *prinst, eval_t *val, etype_t type, cva break; case ev_string: PR_RemoveProgsString(prinst, val->_int); - val->_int = PR_SetString(prinst, var->string); + if (*var->string) + val->_int = PR_SetString(prinst, var->string); + else + val->_int = 0; break; case ev_vector: { diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 3d8c2311a..46918d7d2 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -174,6 +174,13 @@ void PR_AutoCvarSetup(progfuncs_t *prinst); void PR_AutoCvar(progfuncs_t *prinst, cvar_t *var); +void QCBUILTIN PF_getsurfacenumpoints(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_getsurfacepoint(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_getsurfacenormal(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_getsurfacetexture(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_getsurfaceclippedpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_set_bone_world (progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_mmap(progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_ragedit(progfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -192,6 +199,10 @@ void QCBUILTIN PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_glob void skel_lookup(progfuncs_t *prinst, int skelidx, framestate_t *out); void skel_dodelete(progfuncs_t *prinst); void skel_reset(progfuncs_t *prinst); +void QCBUILTIN PF_gettaginfo (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_gettagindex (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_touchtriggers(progfuncs_t *prinst, struct globalvars_s *pr_globals); //pr_cmds.c builtins that need to be moved to a common. void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...) LIKEPRINTF(2); @@ -366,33 +377,6 @@ pbool ED_CanFree (edict_t *ed); #define DAMAGE_YES 1 #define DAMAGE_AIM 2 -// edict->flags -#define FL_FLY (1<<0) -#define FL_SWIM (1<<1) -#define FL_GLIMPSE (1<<2) -#define FL_CLIENT (1<<3) -#define FL_INWATER (1<<4) -#define FL_MONSTER (1<<5) -#define FL_GODMODE (1<<6) -#define FL_NOTARGET (1<<7) -#define FL_ITEM (1<<8) -#define FL_ONGROUND (1<<9) -#define FL_PARTIALGROUND (1<<10) // not all corners are valid -#define FL_WATERJUMP (1<<11) // player jumping out of water - //12 - //13 -#define FL_FINDABLE_NONSOLID (1<<14) //a cpqwsv feature -#define FL_MOVECHAIN_ANGLE (1<<15) // when in a move chain, will update the angle -#define FL_LAGGEDMOVE (1<<16) - //17 - //18 - //19 - //20 -#define FL_CLASS_DEPENDENT (1<<21) - - - - //shared constants typedef enum { diff --git a/engine/common/translate.c b/engine/common/translate.c index c6f011a7f..e4478ba24 100644 --- a/engine/common/translate.c +++ b/engine/common/translate.c @@ -762,7 +762,7 @@ void TL_InitLanguages(void) -#ifndef CLIENTONLY +//#ifndef CLIENTONLY //this stuff is for hexen2 translation strings. //(hexen2 is uuuuggllyyyy...) static char *strings_list; @@ -828,7 +828,7 @@ char *T_GetString(int num) return strings_table[num]; } -#endif +//#endif #ifndef SERVERONLY static char *info_strings_list; diff --git a/engine/common/world.h b/engine/common/world.h index 9c9a2bf81..f2f725295 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -85,6 +85,33 @@ typedef struct q2trace_s void *ent; // not set by CM_*() functions } q2trace_t; + +// edict->flags +#define FL_FLY (1<<0) +#define FL_SWIM (1<<1) +//#define FL_GLIMPSE (1<<2) +#define FL_CLIENT (1<<3) +#define FL_INWATER (1<<4) +#define FL_MONSTER (1<<5) +#define FL_GODMODE (1<<6) +#define FL_NOTARGET (1<<7) +#define FL_ITEM (1<<8) +#define FL_ONGROUND (1<<9) +#define FL_PARTIALGROUND (1<<10) // not all corners are valid +#define FL_WATERJUMP (1<<11) // player jumping out of water +// FL_JUMPRELEASED //12 + //13 +#define FL_FINDABLE_NONSOLID (1<<14) //a cpqwsv feature +#define FL_MOVECHAIN_ANGLE (1<<15) // hexen2 - when in a move chain, will update the angle +#define FL_LAGGEDMOVE (1<<16) + //17 + //18 + //19 + //20 +#define FL_CLASS_DEPENDENT (1<<21) //hexen2 + + + #define MOVE_NORMAL 0 #define MOVE_NOMONSTERS 1 #define MOVE_MISSILE 2 @@ -110,6 +137,7 @@ typedef struct areanode_s typedef struct wedict_s wedict_t; #define PROG_TO_WEDICT (wedict_t*)PROG_TO_EDICT #define WEDICT_NUM (wedict_t *)EDICT_NUM +#define G_WEDICT (wedict_t *)G_EDICT typedef struct { @@ -130,20 +158,22 @@ struct world_s /*FTE_DEPRECATED*/ unsigned int edict_size; //still used in copyentity wedict_t *edicts; // can NOT be array indexed. struct progfuncs_s *progs; - qboolean usesolidcorpse; + qboolean usesolidcorpse; //to disable SOLID_CORPSE when running hexen2 due to conflict. model_t *worldmodel; areanode_t areanodes[AREA_NODES]; int numareanodes; - double physicstime; + double physicstime; // the last time global physics were run unsigned int framenum; int lastcheck; // used by PF_checkclient double lastchecktime; // for monster ai + /*antilag*/ float lagentsfrac; laggedentinfo_t *lagents; unsigned int maxlagents; + /*qc globals*/ struct { int *self; int *other; diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 0700890ce..c7d4396c2 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -131,6 +131,7 @@ typedef struct float depthfactor; float m_model[16]; unsigned int lastpasscount; + vbo_t *batchvbo; texid_t curtex[MAX_TMUS]; unsigned int tmuflags[MAX_TMUS]; @@ -179,7 +180,8 @@ enum D3D_VDEC_ST3 = 1<<4, D3D_VDEC_NORM = 1<<5, D3D_VDEC_SKEL = 1<<6, - D3D_VDEC_MAX = 1<<7 + D3D_VDEC_MAX = 1<<7, + }; #define STRM_VERT 0 #define STRM_COL 1 @@ -193,7 +195,7 @@ enum #define STRM_BONENUM 9 #define STRM_BONEWEIGHT 10 #define STRM_MAX 11 -IDirect3DVertexDeclaration9 *vertexdecls[D3D_VDEC_MAX]; +static IDirect3DVertexDeclaration9 *vertexdecls[D3D_VDEC_MAX]; static void BE_ApplyTMUState(unsigned int tu, unsigned int flags) { @@ -575,6 +577,8 @@ static void BindTexture(unsigned int tu, void *id) static void SelectPassTexture(unsigned int tu, shaderpass_t *pass) { + int last; + switch(pass->texgen) { default: @@ -619,58 +623,74 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass) BE_ApplyTMUState(tu, pass->flags); + if (tu == 0) + { + if (shaderstate.passsinglecolour) + { + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_CONSTANT, shaderstate.passcolour); + last = D3DTA_CONSTANT; + } + else + { + last = D3DTA_DIFFUSE; + } + } + else + last = D3DTA_CURRENT; switch (pass->blendmode) { case PBM_DOTPRODUCT: - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); -// IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); +// IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); break; case PBM_REPLACE: - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_SELECTARG2); if (shaderstate.flags & (BEF_FORCETRANSPARENT | BEF_FORCEADDITIVE)) { - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_MODULATE); } else { - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - // IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + // IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); } break; case PBM_ADD: - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA); - shaderstate.passcolour &= 0xff000000; + if (tu == 0) + goto forcemod; + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_ADD); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); break; case PBM_DECAL: if (!tu) goto forcemod; - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); -// IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_CURRENT); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); +// IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); break; case PBM_OVERBRIGHT: - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_TEXTURE); { extern cvar_t gl_overbright; switch (gl_overbright.ival) @@ -687,48 +707,25 @@ static void SelectPassTexture(unsigned int tu, shaderpass_t *pass) break; } } - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_MODULATE); break; default: case PBM_MODULATE: forcemod: - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_MODULATE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG1, last); + IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_MODULATE); break; } - - if (tu == 0) - { - if (shaderstate.passsinglecolour) - { - if (shaderstate.passcolour == D3DCOLOR_RGBA(255,255,255,255)) - { - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - } - else - { - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_CONSTANT); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_CONSTANT); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_CONSTANT, shaderstate.passcolour); - } - } - else - { - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - IDirect3DDevice9_SetTextureStageState(pD3DDev9, tu, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - } - } } -static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, byte_vec4_t *dst, const mesh_t *mesh) +static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, vec4_t *srcf, byte_vec4_t *dst, const mesh_t *mesh) { D3DCOLOR block; switch (pass->rgbgen) @@ -749,40 +746,64 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, b break; case RGB_GEN_VERTEX_LIGHTING: case RGB_GEN_VERTEX_EXACT: - if (!src) - { - while((cnt)--) - { - dst[cnt][0] = 255; - dst[cnt][1] = 255; - dst[cnt][2] = 255; - } - } - else + if (srcb) { while((cnt)--) { qbyte r, g, b; - r=src[cnt][0]; - g=src[cnt][1]; - b=src[cnt][2]; + r=srcb[cnt][0]; + g=srcb[cnt][1]; + b=srcb[cnt][2]; dst[cnt][0] = b; dst[cnt][1] = g; dst[cnt][2] = r; } } + else if (srcf) + { + while((cnt)--) + { + int r, g, b; + r=srcf[cnt][0]*255; + g=srcf[cnt][1]*255; + b=srcf[cnt][2]*255; + dst[cnt][0] = bound(0, b, 255); + dst[cnt][1] = bound(0, g, 255); + dst[cnt][2] = bound(0, r, 255); + } + } + else + goto identity; break; case RGB_GEN_ONE_MINUS_VERTEX: - while((cnt)--) + if (srcb) { - qbyte r, g, b; - r=255-src[cnt][0]; - g=255-src[cnt][1]; - b=255-src[cnt][2]; - dst[cnt][0] = b; - dst[cnt][1] = g; - dst[cnt][2] = r; + while((cnt)--) + { + qbyte r, g, b; + r=255-srcb[cnt][0]; + g=255-srcb[cnt][1]; + b=255-srcb[cnt][2]; + dst[cnt][0] = b; + dst[cnt][1] = g; + dst[cnt][2] = r; + } } + else if (srcf) + { + while((cnt)--) + { + int r, g, b; + r=255-srcf[cnt][0]*255; + g=255-srcf[cnt][1]*255; + b=255-srcf[cnt][2]*255; + dst[cnt][0] = bound(0, b, 255); + dst[cnt][1] = bound(0, g, 255); + dst[cnt][2] = bound(0, r, 255); + } + } + else + goto identity; break; case RGB_GEN_IDENTITY_LIGHTING: //compensate for overbrights @@ -793,6 +814,7 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, b } break; default: + identity: case RGB_GEN_IDENTITY: block = D3DCOLOR_RGBA(255, 255, 255, 255); while((cnt)--) @@ -855,7 +877,7 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, b } } -static void alphagenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, byte_vec4_t *dst, const mesh_t *mesh) +static void alphagenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, vec4_t *srcf, byte_vec4_t *dst, const mesh_t *mesh) { /*FIXME: Skip this if the rgbgen did it*/ float *table; @@ -913,18 +935,26 @@ static void alphagenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, by break; case ALPHA_GEN_VERTEX: - if (!src) + if (srcb) + { + while(cnt--) + { + dst[cnt][3] = srcb[cnt][3]; + } + } + else if (srcf) + { + while(cnt--) + { + dst[cnt][3] = bound(0, srcf[cnt][3]*255, 255); + } + } + else { while(cnt--) { dst[cnt][3] = 255; } - break; - } - - while(cnt--) - { - dst[cnt][3] = src[cnt][3]; } break; @@ -975,75 +1005,38 @@ static unsigned int BE_GenerateColourMods(unsigned int vertcount, const shaderpa { shaderstate.passsinglecolour = true; shaderstate.passcolour = D3DCOLOR_RGBA(255,255,255,255); - colourgenbyte(pass, 1, (byte_vec4_t*)&shaderstate.passcolour, (byte_vec4_t*)&shaderstate.passcolour, m); - alphagenbyte(pass, 1, (byte_vec4_t*)&shaderstate.passcolour, (byte_vec4_t*)&shaderstate.passcolour, m); + colourgenbyte(pass, 1, (byte_vec4_t*)&shaderstate.passcolour, NULL, (byte_vec4_t*)&shaderstate.passcolour, m); + alphagenbyte(pass, 1, (byte_vec4_t*)&shaderstate.passcolour, NULL, (byte_vec4_t*)&shaderstate.passcolour, m); /*FIXME: just because there's no rgba set, there's no reason to assume it should be a single colour (unshaded ents)*/ d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, NULL, 0, 0)); } else { - unsigned int v; - int c; - float *src; - shaderstate.passsinglecolour = false; ret |= D3D_VDEC_COL4B; - allocvertexbuffer(shaderstate.dyncol_buff, shaderstate.dyncol_size, &shaderstate.dyncol_offs, (void**)&map, vertcount*sizeof(D3DCOLOR)); - if (m->colors4b_array) - { - for (vertcount = 0, mno = 0; mno < shaderstate.nummeshes; mno++) - { - m = shaderstate.meshlist[mno]; - colourgenbyte(pass, m->numvertexes, (byte_vec4_t*)m->colors4b_array, (byte_vec4_t*)map, m); - alphagenbyte(pass, m->numvertexes, (byte_vec4_t*)m->colors4b_array, (byte_vec4_t*)map, m); - map += m->numvertexes*4; - vertcount += m->numvertexes; - } - } - else if (m->colors4f_array && + if (shaderstate.batchvbo && (m->colors4f_array && ((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING) || (pass->rgbgen == RGB_GEN_VERTEX_EXACT) || - (pass->rgbgen == RGB_GEN_ONE_MINUS_VERTEX) || + (pass->rgbgen == RGB_GEN_ONE_MINUS_VERTEX)) && (pass->alphagen == ALPHA_GEN_VERTEX))) { - for (vertcount = 0, mno = 0; mno < shaderstate.nummeshes; mno++) - { - m = shaderstate.meshlist[mno]; - src = m->colors4f_array[0]; - for (v = 0; v < m->numvertexes; v++) - { - c = src[0]*255; - map[0] = bound(0, c, 255); - c = src[1]*255; - map[1] = bound(0, c, 255); - c = src[2]*255; - map[2] = bound(0, c, 255); - c = src[3]*255; - map[3] = bound(0, c, 255); - map += 4; - src += 4; - } - vertcount += m->numvertexes; - } - map -= vertcount*4; - /*FIXME: m is wrong. its the last ent only*/ - colourgenbyte(pass, vertcount, (byte_vec4_t*)map, (byte_vec4_t*)map, m); - alphagenbyte(pass, vertcount, (byte_vec4_t*)map, (byte_vec4_t*)map, m); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.batchvbo->colours.d3d.buff, shaderstate.batchvbo->colours.d3d.offs, sizeof(byte_vec4_t))); } else { + allocvertexbuffer(shaderstate.dyncol_buff, shaderstate.dyncol_size, &shaderstate.dyncol_offs, (void**)&map, vertcount*sizeof(D3DCOLOR)); for (vertcount = 0, mno = 0; mno < shaderstate.nummeshes; mno++) { m = shaderstate.meshlist[mno]; - colourgenbyte(pass, m->numvertexes, NULL, (byte_vec4_t*)map, m); - alphagenbyte(pass, m->numvertexes, NULL, (byte_vec4_t*)map, m); + colourgenbyte(pass, m->numvertexes, m->colors4b_array, m->colors4f_array, (byte_vec4_t*)map, m); + alphagenbyte(pass, m->numvertexes, m->colors4b_array, m->colors4f_array, (byte_vec4_t*)map, m); map += m->numvertexes*4; vertcount += m->numvertexes; } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dyncol_buff)); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.dyncol_buff, shaderstate.dyncol_offs - vertcount*sizeof(D3DCOLOR), sizeof(D3DCOLOR))); } - d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dyncol_buff)); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.dyncol_buff, shaderstate.dyncol_offs - vertcount*sizeof(D3DCOLOR), sizeof(D3DCOLOR))); } return ret; } @@ -1220,7 +1213,7 @@ static void GenerateTCMods(const shaderpass_t *pass, float *dest) } else if (src != dest) { - memcpy(dest, src, 8*mesh->numvertexes); + memcpy(dest, src, sizeof(vec2_t)*mesh->numvertexes); } dest += mesh->numvertexes*2; } @@ -1493,7 +1486,6 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert return false; /*all meshes in a chain must have the same features*/ - vdec = 0; /*we only use one colour, generated from the first pass*/ @@ -1513,10 +1505,17 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert SelectPassTexture(tmu, pass+passno); vdec |= D3D_VDEC_ST0<texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vec2_t))); + else if (shaderstate.batchvbo && pass[passno].tcgen == TC_GEN_LIGHTMAP && !pass[passno].numtcmods) + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.batchvbo->lmcoord.d3d.buff, shaderstate.batchvbo->lmcoord.d3d.offs, sizeof(vec2_t))); + else + { + allocvertexbuffer(shaderstate.dynst_buff[tmu], shaderstate.dynst_size, &shaderstate.dynst_offs[tmu], &map, vertcount*sizeof(vec2_t)); + GenerateTCMods(pass+passno, map); + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[tmu])); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+tmu, shaderstate.dynst_buff[tmu], shaderstate.dynst_offs[tmu] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); + } tmu++; } /*deactivate any extras*/ @@ -1544,6 +1543,43 @@ static qboolean BE_DrawMeshChain_SetupPass(shaderpass_t *pass, unsigned int vert return true; } +static void BE_SubmitMeshChain(int idxfirst) +{ + int startv, starti, endv, endi; + int m; + mesh_t *mesh; + +// if (shaderstate.batchvbo) +// IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, 0, shaderstate.batchvbo->vertcount, idxfirst, shaderstate.batchvbo->indexcount/3); + + for (m = 0, mesh = shaderstate.meshlist[0]; m < shaderstate.nummeshes; ) + { + startv = mesh->vbofirstvert; + starti = mesh->vbofirstelement; + + endv = startv+mesh->numvertexes; + endi = starti+mesh->numindexes; + + //find consecutive surfaces + for (++m; m < shaderstate.nummeshes; m++) + { + mesh = shaderstate.meshlist[m]; +/* if (endi == mesh->vbofirstelement) + { + endv = mesh->vbofirstvert+mesh->numvertexes; + endi = mesh->vbofirstelement+mesh->numindexes; + } + else +*/ { + break; + } + } + + IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, startv, endv - startv, idxfirst + starti, (endi-starti)/3); + RQuantAdd(RQUANT_DRAWS, 1); + } +} + static void BE_ApplyUniforms(program_t *prog, int permu) { int i; @@ -1649,67 +1685,82 @@ static void BE_RenderMeshProgram(unsigned int vertcount, unsigned int idxfirst, /*colours*/ if (vdec & D3D_VDEC_COL4B) { - int mno,v; - void *map; - mesh_t *m; - allocvertexbuffer(shaderstate.dynst_buff[0], shaderstate.dynst_size, &shaderstate.dynst_offs[0], &map, vertcount*sizeof(byte_vec4_t)); - for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + if (shaderstate.batchvbo) + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_COL, shaderstate.batchvbo->colours.d3d.buff, shaderstate.batchvbo->colours.d3d.offs, sizeof(byte_vec4_t))); + else { - byte_vec4_t *dest = (byte_vec4_t*)((char*)map+vertcount*sizeof(byte_vec4_t)); - m = shaderstate.meshlist[mno]; - if (m->colors4f_array) + int mno,v; + void *map; + mesh_t *m; + allocvertexbuffer(shaderstate.dynst_buff[0], shaderstate.dynst_size, &shaderstate.dynst_offs[0], &map, vertcount*sizeof(byte_vec4_t)); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) { - for (v = 0; v < m->numvertexes; v++) + byte_vec4_t *dest = (byte_vec4_t*)((char*)map+vertcount*sizeof(byte_vec4_t)); + m = shaderstate.meshlist[mno]; + if (m->colors4f_array) { - dest[v][0] = bound(0, m->colors4f_array[v][0] * 255, 255); - dest[v][1] = bound(0, m->colors4f_array[v][1] * 255, 255); - dest[v][2] = bound(0, m->colors4f_array[v][2] * 255, 255); - dest[v][3] = bound(0, m->colors4f_array[v][3] * 255, 255); + for (v = 0; v < m->numvertexes; v++) + { + dest[v][0] = bound(0, m->colors4f_array[v][0] * 255, 255); + dest[v][1] = bound(0, m->colors4f_array[v][1] * 255, 255); + dest[v][2] = bound(0, m->colors4f_array[v][2] * 255, 255); + dest[v][3] = bound(0, m->colors4f_array[v][3] * 255, 255); + } } + else if (m->colors4b_array) + memcpy(dest, m->colors4b_array, m->numvertexes*sizeof(byte_vec4_t)); + else + memset(dest, 0, m->numvertexes*sizeof(byte_vec4_t)); + vertcount += m->numvertexes; } - else if (m->colors4b_array) - memcpy(dest, m->colors4b_array, m->numvertexes*sizeof(byte_vec4_t)); - else - memset(dest, 0, m->numvertexes*sizeof(byte_vec4_t)); - vertcount += m->numvertexes; + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[0])); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(byte_vec4_t), sizeof(byte_vec4_t))); } - d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[0])); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(byte_vec4_t), sizeof(byte_vec4_t))); } /*texture coords*/ if (vdec & D3D_VDEC_ST0) { - int mno; - void *map; - mesh_t *m; - allocvertexbuffer(shaderstate.dynst_buff[0], shaderstate.dynst_size, &shaderstate.dynst_offs[0], &map, vertcount*sizeof(vec2_t)); - for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + if (shaderstate.batchvbo) + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vec2_t))); + else { - vec2_t *dest = (vec2_t*)((char*)map+vertcount*sizeof(vec2_t)); - m = shaderstate.meshlist[mno]; - memcpy(dest, m->st_array, m->numvertexes*sizeof(vec2_t)); - vertcount += m->numvertexes; + int mno; + void *map; + mesh_t *m; + allocvertexbuffer(shaderstate.dynst_buff[0], shaderstate.dynst_size, &shaderstate.dynst_offs[0], &map, vertcount*sizeof(vec2_t)); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + vec2_t *dest = (vec2_t*)((char*)map+vertcount*sizeof(vec2_t)); + m = shaderstate.meshlist[mno]; + memcpy(dest, m->st_array, m->numvertexes*sizeof(vec2_t)); + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[0])); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); } - d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[0])); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); } /*lm coords*/ if (vdec & D3D_VDEC_ST1) { - int mno; - void *map; - mesh_t *m; - allocvertexbuffer(shaderstate.dynst_buff[1], shaderstate.dynst_size, &shaderstate.dynst_offs[1], &map, vertcount*sizeof(vec2_t)); - for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + if (shaderstate.batchvbo) + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC1, shaderstate.batchvbo->lmcoord.d3d.buff, shaderstate.batchvbo->lmcoord.d3d.offs, sizeof(vec2_t))); + else { - vec2_t *dest = (vec2_t*)((char*)map+vertcount*sizeof(vec2_t)); - m = shaderstate.meshlist[mno]; - memcpy(dest, m->lmst_array, m->numvertexes*sizeof(vec2_t)); - vertcount += m->numvertexes; + int mno; + void *map; + mesh_t *m; + allocvertexbuffer(shaderstate.dynst_buff[1], shaderstate.dynst_size, &shaderstate.dynst_offs[1], &map, vertcount*sizeof(vec2_t)); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + vec2_t *dest = (vec2_t*)((char*)map+vertcount*sizeof(vec2_t)); + m = shaderstate.meshlist[mno]; + memcpy(dest, m->lmst_array, m->numvertexes*sizeof(vec2_t)); + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[1])); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC1, shaderstate.dynst_buff[1], shaderstate.dynst_offs[1] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); } - d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[1])); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[1], shaderstate.dynst_offs[1] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); } /*normals/tangents/bitangents*/ @@ -1733,7 +1784,7 @@ static void BE_RenderMeshProgram(unsigned int vertcount, unsigned int idxfirst, } // IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, - d3dcheck(IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, 0, vertcount, idxfirst, idxcount/3)); + BE_SubmitMeshChain(idxfirst); IDirect3DDevice9_SetVertexShader(pD3DDev9, NULL); IDirect3DDevice9_SetPixelShader(pD3DDev9, NULL); @@ -1794,41 +1845,64 @@ static void BE_DrawMeshChain_Internal(void) // IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&shaderstate.depthfactor); // } - for (mno = 0, vertcount = 0, idxcount = 0; mno < shaderstate.nummeshes; mno++) + if (shaderstate.batchvbo) { - m = shaderstate.meshlist[mno]; - vertcount += m->numvertexes; - idxcount += m->numindexes; + vertcount = shaderstate.batchvbo->vertcount; + idxcount = shaderstate.batchvbo->indexcount; + } + else + { + for (mno = 0, vertcount = 0, idxcount = 0; mno < shaderstate.nummeshes; mno++) + { + m = shaderstate.meshlist[mno]; + vertcount += m->numvertexes; + idxcount += m->numindexes; + } } /*vertex buffers are common to all passes*/ - allocvertexbuffer(shaderstate.dynxyz_buff, shaderstate.dynxyz_size, &shaderstate.dynxyz_offs, &map, vertcount*sizeof(vecV_t)); - for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + if (shaderstate.batchvbo && !shaderstate.curshader->numdeforms) { - vecV_t *dest = (vecV_t*)((char*)map+vertcount*sizeof(vecV_t)); - m = shaderstate.meshlist[mno]; - deformgen(&shaderstate.curshader->deforms[0], m->numvertexes, m->xyz_array, dest, m); - for (i = 1; i < shaderstate.curshader->numdeforms; i++) - { - deformgen(&shaderstate.curshader->deforms[i], m->numvertexes, dest, dest, m); - } - vertcount += m->numvertexes; + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.batchvbo->coord.d3d.buff, shaderstate.batchvbo->coord.d3d.offs, sizeof(vecV_t))); + } + else + { + allocvertexbuffer(shaderstate.dynxyz_buff, shaderstate.dynxyz_size, &shaderstate.dynxyz_offs, &map, vertcount*sizeof(vecV_t)); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + vecV_t *dest = (vecV_t*)((char*)map+vertcount*sizeof(vecV_t)); + m = shaderstate.meshlist[mno]; + deformgen(&shaderstate.curshader->deforms[0], m->numvertexes, m->xyz_array, dest, m); + for (i = 1; i < shaderstate.curshader->numdeforms; i++) + { + deformgen(&shaderstate.curshader->deforms[i], m->numvertexes, dest, dest, m); + } + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynxyz_buff)); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.dynxyz_buff, shaderstate.dynxyz_offs - vertcount*sizeof(vecV_t), sizeof(vecV_t))); } - d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynxyz_buff)); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.dynxyz_buff, shaderstate.dynxyz_offs - vertcount*sizeof(vecV_t), sizeof(vecV_t))); /*so are index buffers*/ - idxfirst = allocindexbuffer(&map, idxcount); - for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + if (shaderstate.batchvbo) { - m = shaderstate.meshlist[mno]; - for (i = 0; i < m->numindexes; i++) - ((index_t*)map)[i] = m->indexes[i]+vertcount; - map = (char*)map + m->numindexes*sizeof(index_t); - vertcount += m->numvertexes; + d3dcheck(IDirect3DDevice9_SetIndices(pD3DDev9, shaderstate.batchvbo->indicies.d3d.buff)); + idxfirst = 0; + } + else + { + idxfirst = allocindexbuffer(&map, idxcount); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + m = shaderstate.meshlist[mno]; + for (i = 0; i < m->numindexes; i++) + ((index_t*)map)[i] = m->indexes[i]+vertcount; + map = (char*)map + m->numindexes*sizeof(index_t); + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DIndexBuffer9_Unlock(shaderstate.dynidx_buff)); + d3dcheck(IDirect3DDevice9_SetIndices(pD3DDev9, shaderstate.dynidx_buff)); } - d3dcheck(IDirect3DIndexBuffer9_Unlock(shaderstate.dynidx_buff)); - d3dcheck(IDirect3DDevice9_SetIndices(pD3DDev9, shaderstate.dynidx_buff)); switch (shaderstate.mode) { @@ -1850,7 +1924,7 @@ static void BE_DrawMeshChain_Internal(void) passno++; } shaderstate.lastpasscount = 0; - d3dcheck(IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, 0, vertcount, idxfirst, idxcount/3)); + BE_SubmitMeshChain(idxfirst); IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE|D3DCOLORWRITEENABLE_ALPHA); break; default: @@ -1871,7 +1945,8 @@ static void BE_DrawMeshChain_Internal(void) if (shaderstate.bench.clamp && shaderstate.bench.clamp < shaderstate.bench.draws) continue; #endif - d3dcheck(IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, 0, vertcount, idxfirst, idxcount/3)); + BE_SubmitMeshChain(idxfirst); +// d3dcheck(IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, 0, vertcount, idxfirst, idxcount/3)); } } break; @@ -1897,9 +1972,19 @@ void D3DBE_GenBrushModelVBO(model_t *mod) unsigned int meshes; vbo_t *vbo; - char *vboedata; + index_t *vboedata; mesh_t *m; char *vbovdata; + IDirect3DVertexBuffer9 *vbuff; + IDirect3DIndexBuffer9 *ebuff; + + vecV_t *coord; + vec2_t *texcoord; + vec2_t *lmcoord; + vec3_t *normals; + vec3_t *svector; + vec3_t *tvector; + byte_vec4_t *colours; if (!mod->numsurfaces) return; @@ -1945,17 +2030,40 @@ void D3DBE_GenBrushModelVBO(model_t *mod) sizeof(vec3_t)+ //tdir sizeof(vec4_t); //colours - vbovdata = BZ_Malloc(maxvboverts*pervertsize); - vboedata = BZ_Malloc(maxvboelements*sizeof(index_t)); + IDirect3DDevice9_CreateIndexBuffer(pD3DDev9, sizeof(index_t) * maxvboelements, 0, D3DFMT_QINDEX, D3DPOOL_MANAGED, &ebuff, NULL); + IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, pervertsize * maxvboverts, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &vbuff, NULL); - vbo->coord = (vecV_t*)(vbovdata); - vbo->texcoord = (vec2_t*)((char*)vbo->coord+maxvboverts*sizeof(*vbo->coord)); - vbo->lmcoord = (vec2_t*)((char*)vbo->texcoord+maxvboverts*sizeof(*vbo->texcoord)); - vbo->normals = (vec3_t*)((char*)vbo->lmcoord+maxvboverts*sizeof(*vbo->lmcoord)); - vbo->svector = (vec3_t*)((char*)vbo->normals+maxvboverts*sizeof(*vbo->normals)); - vbo->tvector = (vec3_t*)((char*)vbo->svector+maxvboverts*sizeof(*vbo->svector)); - vbo->colours4f = (vec4_t*)((char*)vbo->tvector+maxvboverts*sizeof(*vbo->tvector)); - vbo->indicies = (index_t*)vboedata; + IDirect3DIndexBuffer9_Lock(ebuff, 0, sizeof(index_t) * maxvboelements, &vboedata, D3DLOCK_DISCARD); + IDirect3DVertexBuffer9_Lock(vbuff, 0, pervertsize * maxvboverts, &vbovdata, D3DLOCK_DISCARD); + + vbo->vertdata = vbuff; + vbo->indexcount = maxvboelements; + vbo->vertcount = maxvboverts; + + vbo->coord.d3d.buff = vbuff; + vbo->coord.d3d.offs = 0; + vbo->texcoord.d3d.buff = vbuff; + vbo->texcoord.d3d.offs = vbo->coord.d3d.offs+maxvboverts*sizeof(vecV_t); + vbo->lmcoord.d3d.buff = vbuff; + vbo->lmcoord.d3d.offs = vbo->texcoord.d3d.offs+maxvboverts*sizeof(vec2_t); + vbo->normals.d3d.buff = vbuff; + vbo->normals.d3d.offs = vbo->lmcoord.d3d.offs+maxvboverts*sizeof(vec2_t); + vbo->svector.d3d.buff = vbuff; + vbo->svector.d3d.offs = vbo->normals.d3d.offs+maxvboverts*sizeof(vec3_t); + vbo->tvector.d3d.buff = vbuff; + vbo->tvector.d3d.offs = vbo->svector.d3d.offs+maxvboverts*sizeof(vec3_t); + vbo->colours.d3d.buff = vbuff; + vbo->colours.d3d.offs = vbo->tvector.d3d.offs+maxvboverts*sizeof(vec3_t); + vbo->indicies.d3d.buff = ebuff; + vbo->indicies.d3d.offs = 0; + + coord = (void*)(vbovdata + vbo->coord.d3d.offs); + texcoord = (void*)(vbovdata + vbo->texcoord.d3d.offs); + lmcoord = (void*)(vbovdata + vbo->lmcoord.d3d.offs); + normals = (void*)(vbovdata + vbo->normals.d3d.offs); + svector = (void*)(vbovdata + vbo->svector.d3d.offs); + tvector = (void*)(vbovdata + vbo->tvector.d3d.offs); + colours = (void*)(vbovdata + vbo->colours.d3d.offs); vbo->meshcount = meshes; vbo->meshlist = BZ_Malloc(meshes*sizeof(*vbo->meshlist)); @@ -1976,66 +2084,74 @@ void D3DBE_GenBrushModelVBO(model_t *mod) m->vbofirstvert = vcount; m->vbofirstelement = ecount; for (v = 0; v < m->numindexes; v++) - vbo->indicies[ecount++] = vcount + m->indexes[v]; + vboedata[ecount++] = vcount + m->indexes[v]; for (v = 0; v < m->numvertexes; v++) { - vbo->coord[vcount+v][0] = m->xyz_array[v][0]; - vbo->coord[vcount+v][1] = m->xyz_array[v][1]; - vbo->coord[vcount+v][2] = m->xyz_array[v][2]; + coord[vcount+v][0] = m->xyz_array[v][0]; + coord[vcount+v][1] = m->xyz_array[v][1]; + coord[vcount+v][2] = m->xyz_array[v][2]; + coord[vcount+v][3] = 1; if (m->st_array) { - vbo->texcoord[vcount+v][0] = m->st_array[v][0]; - vbo->texcoord[vcount+v][1] = m->st_array[v][1]; + texcoord[vcount+v][0] = m->st_array[v][0]; + texcoord[vcount+v][1] = m->st_array[v][1]; } if (m->lmst_array) { - vbo->lmcoord[vcount+v][0] = m->lmst_array[v][0]; - vbo->lmcoord[vcount+v][1] = m->lmst_array[v][1]; + lmcoord[vcount+v][0] = m->lmst_array[v][0]; + lmcoord[vcount+v][1] = m->lmst_array[v][1]; } if (m->normals_array) { - vbo->normals[vcount+v][0] = m->normals_array[v][0]; - vbo->normals[vcount+v][1] = m->normals_array[v][1]; - vbo->normals[vcount+v][2] = m->normals_array[v][2]; + normals[vcount+v][0] = m->normals_array[v][0]; + normals[vcount+v][1] = m->normals_array[v][1]; + normals[vcount+v][2] = m->normals_array[v][2]; } if (m->snormals_array) { - vbo->svector[vcount+v][0] = m->snormals_array[v][0]; - vbo->svector[vcount+v][1] = m->snormals_array[v][1]; - vbo->svector[vcount+v][2] = m->snormals_array[v][2]; + svector[vcount+v][0] = m->snormals_array[v][0]; + svector[vcount+v][1] = m->snormals_array[v][1]; + svector[vcount+v][2] = m->snormals_array[v][2]; } if (m->tnormals_array) { - vbo->tvector[vcount+v][0] = m->tnormals_array[v][0]; - vbo->tvector[vcount+v][1] = m->tnormals_array[v][1]; - vbo->tvector[vcount+v][2] = m->tnormals_array[v][2]; + tvector[vcount+v][0] = m->tnormals_array[v][0]; + tvector[vcount+v][1] = m->tnormals_array[v][1]; + tvector[vcount+v][2] = m->tnormals_array[v][2]; + } + if (m->colors4b_array) + { + colours[vcount+v][0] = m->colors4b_array[v][0]; + colours[vcount+v][1] = m->colors4b_array[v][1]; + colours[vcount+v][2] = m->colors4b_array[v][2]; + colours[vcount+v][3] = m->colors4b_array[v][3]; } if (m->colors4f_array) { - vbo->colours4f[vcount+v][0] = m->colors4f_array[v][0]; - vbo->colours4f[vcount+v][1] = m->colors4f_array[v][1]; - vbo->colours4f[vcount+v][2] = m->colors4f_array[v][2]; - vbo->colours4f[vcount+v][3] = m->colors4f_array[v][3]; + colours[vcount+v][0] = m->colors4f_array[v][0] * 255; + colours[vcount+v][1] = m->colors4f_array[v][1] * 255; + colours[vcount+v][2] = m->colors4f_array[v][2] * 255; + colours[vcount+v][3] = m->colors4f_array[v][3] * 255; } } vcount += v; } -// if (GL_BuildVBO(vbo, vbovdata, vcount*pervertsize, vboedata, ecount*sizeof(index_t))) - { - BZ_Free(vbovdata); - BZ_Free(vboedata); - } + IDirect3DIndexBuffer9_Unlock(ebuff); + IDirect3DVertexBuffer9_Unlock(vbuff); } - //for (i=0 ; inumsurfaces ; i++) - //{ - // if (!mod->surfaces[i].mark) - // Host_EndGame("Surfaces with bad textures detected\n"); - //} } /*Wipes a vbo*/ void D3DBE_ClearVBO(vbo_t *vbo) { + IDirect3DVertexBuffer9 *vbuff = vbo->vertdata; + IDirect3DIndexBuffer9 *ebuff = vbo->indicies.d3d.buff; + if (vbuff) + IDirect3DVertexBuffer9_Release(vbuff); + if (ebuff) + IDirect3DIndexBuffer9_Release(ebuff); + vbo->vertdata = NULL; + vbo->indicies.d3d.buff = NULL; } /*upload all lightmaps at the start to reduce lags*/ @@ -2234,6 +2350,10 @@ void D3DBE_SubmitBatch(batch_t *batch) BE_RotateForEntity(batch->ent, batch->ent->model); shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime; } + if (batch->texture) + shaderstate.batchvbo = &batch->texture->vbo; + else + shaderstate.batchvbo = batch->vbo; shaderstate.meshlist = batch->mesh + batch->firstmesh; shaderstate.curshader = batch->shader; shaderstate.curtexnums = batch->skin; @@ -2248,6 +2368,7 @@ void D3DBE_SubmitBatch(batch_t *batch) void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) { + shaderstate.batchvbo = vbo; shaderstate.curshader = shader; shaderstate.curtexnums = texnums; shaderstate.curlightmap = r_nulltex; @@ -2260,6 +2381,7 @@ void D3DBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo void D3DBE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums, unsigned int beflags) { + shaderstate.batchvbo = vbo; shaderstate.curtime = realtime; shaderstate.curshader = shader; shaderstate.curtexnums = texnums?texnums:&shader->defaulttextures; @@ -2597,7 +2719,7 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) } } -void BE_SubmitMeshes (qboolean drawworld, batch_t **blist) +void D3DBE_SubmitMeshes (qboolean drawworld, batch_t **blist) { model_t *model = cl.worldmodel; int i; @@ -2652,13 +2774,13 @@ void D3DBE_DrawWorld (qbyte *vis) BE_SelectMode(BEM_STANDARD); RSpeedRemark(); - BE_SubmitMeshes(true, batches); + D3DBE_SubmitMeshes(true, batches); RSpeedEnd(RSPEED_WORLD); } else { RSpeedRemark(); - BE_SubmitMeshes(false, batches); + D3DBE_SubmitMeshes(false, batches); RSpeedEnd(RSPEED_DRAWENTITIES); } diff --git a/engine/d3d/d3d_image.c b/engine/d3d/d3d_image.c index 393279f58..7e188c015 100644 --- a/engine/d3d/d3d_image.c +++ b/engine/d3d/d3d_image.c @@ -34,9 +34,12 @@ static d3dtexture_t *d3d_lookup_texture(char *ident) { d3dtexture_t *tex; - for (tex = d3dtextures; tex; tex = tex->next) - if (!strcmp(tex->name, ident)) - return tex; + if (*ident) + { + for (tex = d3dtextures; tex; tex = tex->next) + if (!strcmp(tex->name, ident)) + return tex; + } tex = calloc(1, sizeof(*tex)+strlen(ident)); strcpy(tex->name, ident); @@ -256,7 +259,7 @@ static void D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned char *data, unsigned else { noalpha = false; - trans[i] = pal32[p] & 0x00ffffff; + trans[i] = 0; } } } diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index 827562573..b5ecd79c1 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -157,13 +157,8 @@ void D3DShader_Init(void) void D3DShader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag) { - int i, j, k; D3DXMACRO defines[64]; LPD3DXBUFFER code = NULL, errors = NULL; - D3DXCONSTANTTABLE_DESC ctd; - D3DXHANDLE ch; - D3DXCONSTANT_DESC d; - UINT dc; prog->handle[permu].hlsl.vert = NULL; prog->handle[permu].hlsl.frag = NULL; diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 35e79882c..61bb2fb1d 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -57,7 +57,7 @@ LPDIRECT3DDEVICE9 pD3DDev9; static D3DPRESENT_PARAMETERS d3dpp; float d3d_trueprojection[16]; -static qboolean vid_initializing; +qboolean vid_initializing; extern qboolean scr_initialized; // ready to draw extern qboolean scr_drawloading; @@ -368,7 +368,7 @@ static LRESULT WINAPI D3D9_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { - Sys_Quit (); + Cbuf_AddText("\nquit\n", RESTRICT_LOCAL); } break; @@ -741,8 +741,6 @@ static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette) static void (D3D9_R_NewMap) (void) { r_worldentity.model = cl.worldmodel; - R_AnimateLight(); - Surf_BuildLightmaps(); #ifdef MAP_PROC if (cl.worldmodel && cl.worldmodel->fromgame == fg_doom3) @@ -751,6 +749,12 @@ static void (D3D9_R_NewMap) (void) /*wipe any lingering particles*/ P_ClearParticles(); + CL_RegisterParticles(); + + R_AnimateLight(); + Surf_DeInit(); + Surf_WipeStains(); + Surf_BuildLightmaps(); } extern mleaf_t *r_viewleaf, *r_oldviewleaf; @@ -987,7 +991,7 @@ static void (D3D9_SCR_UpdateScreen) (void) if (editormodal) { Editor_Draw(); - GLV_UpdatePalette (false, host_frametime); + V_UpdatePalette (false); #if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); #endif @@ -1005,7 +1009,7 @@ static void (D3D9_SCR_UpdateScreen) (void) if (Media_ShowFilm()) { M_Draw(0); -// GLV_UpdatePalette (false, host_frametime); +// V_UpdatePalette (false); #if defined(_WIN32) Media_RecordFrame(); #endif @@ -1072,7 +1076,7 @@ static void (D3D9_SCR_UpdateScreen) (void) SCR_DrawTwoDimensional(uimenu, nohud); - GLV_UpdatePalette (false, host_frametime); + V_UpdatePalette (false); #if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); #endif @@ -1195,12 +1199,12 @@ static void (D3D9_R_RenderView) (void) d3d9error(IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1, 0)); R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); RQ_BeginFrame(); - Surf_DrawWorld(); if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { if (cl.worldmodel) P_DrawParticles (); } + Surf_DrawWorld(); RQ_RenderBatchClear(); } diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index 875b7e6b2..d029c4d32 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -20,7 +20,7 @@ @@ -1128,7 +1119,7 @@ - - @@ -23817,6 +23792,7 @@ Name="VCCLCompilerTool" AdditionalIncludeDirectories="" PreprocessorDefinitions="" + UsePrecompiledHeader="0" /> + + diff --git a/engine/dotnet2005/npfte.vcproj b/engine/dotnet2005/npfte.vcproj index 20d4ef107..3c177f0a4 100644 --- a/engine/dotnet2005/npfte.vcproj +++ b/engine/dotnet2005/npfte.vcproj @@ -89,6 +89,7 @@ GenerateDebugInformation="true" GenerateMapFile="true" SubSystem="2" + TargetMachine="1" /> + + + flags & RF_NOSHADOW) b->flags |= BEF_NOSHADOWS; - b->vbo = 0; + b->vbo = NULL; b->next = batches[sort]; batches[sort] = b; } @@ -1115,7 +1115,7 @@ void R_Sprite_GenerateBatches(entity_t *e, batch_t **batches) b->lightmap = -1; b->surf_first = surfnum; b->flags = 0; - b->vbo = 0; + b->vbo = NULL; b->next = batches[shader->sort]; batches[shader->sort] = b; } diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 663695754..1d7878615 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -137,6 +137,7 @@ void main ()\n\ #define LIGHTPASS_GLSL_FRAGMENT "\ #ifdef FRAGMENT_SHADER\n\ +#include \"sys/fog.h\"\n\ uniform sampler2D s_t0;\n"/*base texture*/"\ #if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n\ uniform sampler2D s_t1;\n"/*normalmap/height texture*/"\ @@ -230,7 +231,7 @@ vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot l_lightcolour *= texture2d(s_t3, shadowcoord);\n\ #endif\n\ \n\ - gl_FragColor.rgb = diff*colorscale*l_lightcolour;\n\ + gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n\ }\n\ \ #endif\n\ @@ -252,6 +253,7 @@ static const char LIGHTPASS_SHADER[] = "\ !!permu FULLBRIGHT\n\ !!permu OFFSETMAPPING\n\ !!permu SKELETAL\n\ + !!permu FOG\n\ #define LIGHTPASS\n\ %s\n\ }\n\ @@ -352,6 +354,7 @@ struct { int currentprogram; vbo_t dummyvbo; + int colourarraytype; int currentvbo; int currentebo; @@ -949,7 +952,7 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea t = shaderstate.curshadowmap; break; - case T_GEN_SKYBOX: + case T_GEN_CUBEMAP: t = pass->anim_frames[0]; GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray); return; @@ -958,6 +961,13 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray); return; + case T_GEN_3DMAP: + t = pass->anim_frames[0]; + checkglerror(); + GL_LazyBind(tmu, GL_TEXTURE_3D, t, useclientarray); + checkglerror(); + return; + case T_GEN_VIDEOMAP: #ifdef NOMEDIA t = shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex; @@ -1976,15 +1986,15 @@ static void GenerateColourMods(const shaderpass_t *pass) mesh_t *meshlist; meshlist = shaderstate.meshes[0]; - if (shaderstate.sourcevbo->colours4ub) + /*if (shaderstate.sourcevbo->colours4ub) { //hack... - GL_SelectVBO(shaderstate.sourcevbo->vbocolours); + GL_SelectVBO(shaderstate.sourcevbo->colours.gl.vbo); qglEnableClientState(GL_COLOR_ARRAY); - qglColorPointer(4, GL_UNSIGNED_BYTE, 0, shaderstate.sourcevbo->colours4ub); + qglColorPointer(4, GL_UNSIGNED_BYTE, 0, shaderstate.sourcevbo->colours4ub.gl.addr); qglShadeModel(GL_SMOOTH); return; - } + }*/ if (pass->flags & SHADER_PASS_NOCOLORARRAY && qglColor4fv) { avec4_t scol; @@ -2037,8 +2047,8 @@ static void GenerateColourMods(const shaderpass_t *pass) //if its vetex lighting, just use the vbo if (((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING && shaderstate.identitylighting == 1) || pass->rgbgen == RGB_GEN_VERTEX_EXACT) && pass->alphagen == ALPHA_GEN_VERTEX) { - GL_SelectVBO(shaderstate.sourcevbo->vbocolours); - qglColorPointer(4, GL_FLOAT, 0, shaderstate.sourcevbo->colours4f); + GL_SelectVBO(shaderstate.sourcevbo->colours.gl.vbo); + qglColorPointer(4, shaderstate.colourarraytype, 0, shaderstate.sourcevbo->colours.gl.addr); qglEnableClientState(GL_COLOR_ARRAY); return; } @@ -2065,36 +2075,36 @@ static void BE_GeneratePassTC(const shaderpass_t *pass, int passno) //if there are no tcmods, pass through here as fast as possible if (pass->tcgen == TC_GEN_BASE) { - GL_SelectVBO(shaderstate.sourcevbo->vbotexcoord); - qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->texcoord); + GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); + qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->texcoord.gl.addr); } else if (pass->tcgen == TC_GEN_LIGHTMAP) { - if (!shaderstate.sourcevbo->lmcoord) + if (!shaderstate.sourcevbo->lmcoord.gl.addr) { - GL_SelectVBO(shaderstate.sourcevbo->vbotexcoord); - qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->texcoord); + GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); + qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->texcoord.gl.addr); } else { - GL_SelectVBO(shaderstate.sourcevbo->vbolmcoord); - qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->lmcoord); + GL_SelectVBO(shaderstate.sourcevbo->lmcoord.gl.vbo); + qglTexCoordPointer(2, GL_FLOAT, 0, shaderstate.sourcevbo->lmcoord.gl.addr); } } else if (pass->tcgen == TC_GEN_NORMAL) { - GL_SelectVBO(shaderstate.sourcevbo->vbonormals); - qglTexCoordPointer(3, GL_FLOAT, 0, shaderstate.sourcevbo->normals); + GL_SelectVBO(shaderstate.sourcevbo->normals.gl.vbo); + qglTexCoordPointer(3, GL_FLOAT, 0, shaderstate.sourcevbo->normals.gl.addr); } else if (pass->tcgen == TC_GEN_SVECTOR) { - GL_SelectVBO(shaderstate.sourcevbo->vbosvector); - qglTexCoordPointer(3, GL_FLOAT, 0, shaderstate.sourcevbo->svector); + GL_SelectVBO(shaderstate.sourcevbo->svector.gl.vbo); + qglTexCoordPointer(3, GL_FLOAT, 0, shaderstate.sourcevbo->svector.gl.addr); } else if (pass->tcgen == TC_GEN_TVECTOR) { - GL_SelectVBO(shaderstate.sourcevbo->vbotvector); - qglTexCoordPointer(3, GL_FLOAT, 0, shaderstate.sourcevbo->tvector); + GL_SelectVBO(shaderstate.sourcevbo->tvector.gl.vbo); + qglTexCoordPointer(3, GL_FLOAT, 0, shaderstate.sourcevbo->tvector.gl.addr); } else { @@ -2351,7 +2361,7 @@ static void BE_SubmitMeshChain(void) } } - qglDrawRangeElements(GL_TRIANGLES, startv, endv, endi-starti, GL_INDEX_TYPE, shaderstate.sourcevbo->indicies + starti); + qglDrawRangeElements(GL_TRIANGLES, startv, endv, endi-starti, GL_INDEX_TYPE, (index_t*)shaderstate.sourcevbo->indicies.gl.addr + starti); RQuantAdd(RQUANT_DRAWS, 1); } /* @@ -2420,52 +2430,52 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vecV_t), shaderstate.pendingvertexpointer); return 1u<handle[perm]; case SP_ATTR_COLOUR: - if (shaderstate.sourcevbo->colours4f) + if (shaderstate.sourcevbo->colours.gl.addr) { - GL_SelectVBO(shaderstate.sourcevbo->vbocolours); - qglVertexAttribPointer(p->handle[perm], 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->colours4f); + GL_SelectVBO(shaderstate.sourcevbo->colours.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 4, shaderstate.colourarraytype, GL_FALSE, 0, shaderstate.sourcevbo->colours.gl.addr); return 1u<handle[perm]; } - else if (shaderstate.sourcevbo->colours4ub) +/* else if (shaderstate.sourcevbo->colours4ub) { - GL_SelectVBO(shaderstate.sourcevbo->vbocolours); - qglVertexAttribPointer(p->handle[perm], 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(byte_vec4_t), shaderstate.sourcevbo->colours4ub); + GL_SelectVBO(shaderstate.sourcevbo->colours.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(byte_vec4_t), shaderstate.sourcevbo->colours.gl.addr); return 1u<handle[perm]; - } + }*/ break; case SP_ATTR_TEXCOORD: - GL_SelectVBO(shaderstate.sourcevbo->vbotexcoord); - qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->texcoord); + GL_SelectVBO(shaderstate.sourcevbo->texcoord.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->texcoord.gl.addr); return 1u<handle[perm]; case SP_ATTR_LMCOORD: - GL_SelectVBO(shaderstate.sourcevbo->vbolmcoord); - qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord); + GL_SelectVBO(shaderstate.sourcevbo->lmcoord.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord.gl.addr); return 1u<handle[perm]; case SP_ATTR_NORMALS: - if (!shaderstate.sourcevbo->normals) + if (!shaderstate.sourcevbo->normals.gl.addr) return 0; - GL_SelectVBO(shaderstate.sourcevbo->vbonormals); - qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->normals); + GL_SelectVBO(shaderstate.sourcevbo->normals.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->normals.gl.addr); return 1u<handle[perm]; case SP_ATTR_SNORMALS: - if (!shaderstate.sourcevbo->normals) + if (!shaderstate.sourcevbo->svector.gl.addr) return 0; - GL_SelectVBO(shaderstate.sourcevbo->vbosvector); - qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->svector); + GL_SelectVBO(shaderstate.sourcevbo->svector.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->svector.gl.addr); return 1u<handle[perm]; case SP_ATTR_TNORMALS: - if (!shaderstate.sourcevbo->normals) + if (!shaderstate.sourcevbo->tvector.gl.addr) return 0; - GL_SelectVBO(shaderstate.sourcevbo->vbotvector); - qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->tvector); + GL_SelectVBO(shaderstate.sourcevbo->tvector.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->tvector.gl.addr); return 1u<handle[perm]; case SP_ATTR_BONENUMS: - GL_SelectVBO(shaderstate.sourcevbo->vbobonenums); - qglVertexAttribPointer(p->handle[perm], 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(byte_vec4_t), shaderstate.sourcevbo->bonenums); + GL_SelectVBO(shaderstate.sourcevbo->bonenums.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(byte_vec4_t), shaderstate.sourcevbo->bonenums.gl.addr); return 1u<handle[perm]; case SP_ATTR_BONEWEIGHTS: - GL_SelectVBO(shaderstate.sourcevbo->vboboneweights); - qglVertexAttribPointer(p->handle[perm], 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->boneweights); + GL_SelectVBO(shaderstate.sourcevbo->boneweights.gl.vbo); + qglVertexAttribPointer(p->handle[perm], 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->boneweights.gl.addr); return 1u<handle[perm]; case SP_M_VIEW: @@ -2563,7 +2573,6 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned case SP_LIGHTSCREEN: { float v[4], tempv[4]; - float out[3]; v[0] = shaderstate.lightorg[0]; v[1] = shaderstate.lightorg[1]; @@ -2587,6 +2596,9 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned case SP_LIGHTCOLOUR: qglUniform3fvARB(p->handle[perm], 1, shaderstate.lightcolours); break; + case SP_W_FOG: + qglUniform4fvARB(p->handle[perm], 1, r_refdef.gfog_rgb); + break; case SP_V_EYEPOS: qglUniform3fvARB(p->handle[perm], 1, r_origin); break; @@ -2683,6 +2695,8 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas perm |= PERMUTATION_LOWER; if (TEXVALID(shaderstate.curtexnums->upperoverlay) && p->handle[perm|PERMUTATION_UPPER].glsl) perm |= PERMUTATION_UPPER; + if (r_refdef.gfog_alpha && p->handle[perm|PERMUTATION_FOG].glsl) + perm |= PERMUTATION_FOG; if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET].glsl) perm |= PERMUTATION_OFFSET; GL_SelectProgram(p->handle[perm].glsl); @@ -2786,7 +2800,8 @@ void GLBE_SelectMode(backendmode_t mode) { GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); } - qglShadeModel(GL_FLAT); + if (qglShadeModel) + qglShadeModel(GL_FLAT); //we don't write or blend anything (maybe alpha test... but mneh) BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS); @@ -2991,13 +3006,13 @@ static void DrawMeshes(void) RQuantAdd(RQUANT_ENTBATCHES, 1); } - GL_SelectEBO(shaderstate.sourcevbo->vboe); + GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); if (shaderstate.curshader->numdeforms) GenerateVertexDeforms(shaderstate.curshader); else { - shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord; - shaderstate.pendingvertexvbo = shaderstate.sourcevbo->vbocoord; + shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord.gl.addr; + shaderstate.pendingvertexvbo = shaderstate.sourcevbo->coord.gl.vbo; } #ifndef FORCESTATE @@ -3127,18 +3142,26 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ { m = *meshlist++; - shaderstate.dummyvbo.coord = m->xyz_array; - shaderstate.dummyvbo.texcoord = m->st_array; - shaderstate.dummyvbo.indicies = m->indexes; - shaderstate.dummyvbo.normals = m->normals_array; - shaderstate.dummyvbo.svector = m->snormals_array; - shaderstate.dummyvbo.tvector = m->tnormals_array; - shaderstate.dummyvbo.colours4f = m->colors4f_array; - shaderstate.dummyvbo.colours4ub = m->colors4b_array; + shaderstate.dummyvbo.coord.gl.addr = m->xyz_array; + shaderstate.dummyvbo.texcoord.gl.addr = m->st_array; + shaderstate.dummyvbo.indicies.gl.addr = m->indexes; + shaderstate.dummyvbo.normals.gl.addr = m->normals_array; + shaderstate.dummyvbo.svector.gl.addr = m->snormals_array; + shaderstate.dummyvbo.tvector.gl.addr = m->tnormals_array; + if (m->colors4f_array) + { + shaderstate.colourarraytype = GL_FLOAT; + shaderstate.dummyvbo.colours.gl.addr = m->colors4f_array; + } + else + { + shaderstate.colourarraytype = GL_UNSIGNED_BYTE; + shaderstate.dummyvbo.colours.gl.addr = m->colors4b_array; + } shaderstate.dummyvbo.bones = m->bones; shaderstate.dummyvbo.numbones = m->numbones; - shaderstate.dummyvbo.bonenums = m->bonenums; - shaderstate.dummyvbo.boneweights = m->boneweights; + shaderstate.dummyvbo.bonenums.gl.addr = m->bonenums; + shaderstate.dummyvbo.boneweights.gl.addr = m->boneweights; shaderstate.meshcount = 1; shaderstate.meshes = &m; @@ -3148,6 +3171,7 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ else { shaderstate.sourcevbo = vbo; + shaderstate.colourarraytype = GL_FLOAT; shaderstate.curshader = shader; shaderstate.flags = beflags; if (shaderstate.curentity != &r_worldentity) @@ -3177,22 +3201,31 @@ void GLBE_SubmitBatch(batch_t *batch) if (batch->texture) { shaderstate.sourcevbo = &batch->texture->vbo; + shaderstate.colourarraytype = GL_FLOAT; lm = batch->lightmap; } else { - shaderstate.dummyvbo.coord = batch->mesh[0]->xyz_array; - shaderstate.dummyvbo.texcoord = batch->mesh[0]->st_array; - shaderstate.dummyvbo.indicies = batch->mesh[0]->indexes; - shaderstate.dummyvbo.normals = batch->mesh[0]->normals_array; - shaderstate.dummyvbo.svector = batch->mesh[0]->snormals_array; - shaderstate.dummyvbo.tvector = batch->mesh[0]->tnormals_array; - shaderstate.dummyvbo.colours4f = batch->mesh[0]->colors4f_array; - shaderstate.dummyvbo.colours4ub = batch->mesh[0]->colors4b_array; + shaderstate.dummyvbo.coord.gl.addr = batch->mesh[0]->xyz_array; + shaderstate.dummyvbo.texcoord.gl.addr = batch->mesh[0]->st_array; + shaderstate.dummyvbo.indicies.gl.addr = batch->mesh[0]->indexes; + shaderstate.dummyvbo.normals.gl.addr = batch->mesh[0]->normals_array; + shaderstate.dummyvbo.svector.gl.addr = batch->mesh[0]->snormals_array; + shaderstate.dummyvbo.tvector.gl.addr = batch->mesh[0]->tnormals_array; + if (batch->mesh[0]->colors4f_array) + { + shaderstate.colourarraytype = GL_FLOAT; + shaderstate.dummyvbo.colours.gl.addr = batch->mesh[0]->colors4f_array; + } + else + { + shaderstate.colourarraytype = GL_UNSIGNED_BYTE; + shaderstate.dummyvbo.colours.gl.addr = batch->mesh[0]->colors4b_array; + } shaderstate.dummyvbo.bones = batch->mesh[0]->bones; shaderstate.dummyvbo.numbones = batch->mesh[0]->numbones; - shaderstate.dummyvbo.bonenums = batch->mesh[0]->bonenums; - shaderstate.dummyvbo.boneweights = batch->mesh[0]->boneweights; + shaderstate.dummyvbo.bonenums.gl.addr = batch->mesh[0]->bonenums; + shaderstate.dummyvbo.boneweights.gl.addr = batch->mesh[0]->boneweights; shaderstate.sourcevbo = &shaderstate.dummyvbo; lm = -1; } @@ -3637,12 +3670,13 @@ void GLBE_DrawWorld (qbyte *vis) GLBE_SubmitMeshes(true, batches, SHADER_SORT_DECAL, SHADER_SORT_NEAREST); - if (r_refdef.gfog_alpha) +/* if (r_refdef.gfog_alpha) { BE_SelectMode(BEM_FOG); BE_SelectFog(r_refdef.gfog_rgb, r_refdef.gfog_alpha, r_refdef.gfog_density); GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); } +*/ } else { diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 9099ab5e2..1b529037f 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -1153,6 +1153,43 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne if (gl_config.arb_texture_compression && gl_compress.value && name && !(flags&IF_NOMIPMAP)) samples = (flags&IF_NOALPHA) ? GL_COMPRESSED_RGB_ARB : GL_COMPRESSED_RGBA_ARB; + if (flags & IF_3DMAP) + { + int r,d; + if (scaled_height * scaled_height != scaled_width) + return; + + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + if (flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + if (flags&IF_CLAMP) + { + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + } + else + { + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT); + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT); + qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT); + } + + for (d = 0; d < scaled_height; d++) + { + /*each 'layer' is sequential, which means we need to de-interlace the layers*/ + for (r = 0; r < scaled_height; r++) + { + memcpy(scaled + (r + d*scaled_height) * scaled_height, data + (r*scaled_height + d) * scaled_height, scaled_height*sizeof(*data)); + } + } + qglTexImage3D (GL_TEXTURE_3D, 0, samples, scaled_height, scaled_height, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled); + return; + } + if (gl_config.sgis_generate_mipmap && !(flags&IF_NOMIPMAP)) { TRACE(("dbg: GL_Upload32: GL_SGIS_generate_mipmap\n")); @@ -2191,7 +2228,10 @@ texid_t GL_LoadTexture32 (char *identifier, int width, int height, void *data, u glt->bpp = 32; glt->flags = flags; - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); + if (flags & IF_3DMAP) + GL_MTBind(0, GL_TEXTURE_3D, glt->texnum); + else + GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload32 (identifier, data, width, height, flags); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index be3e0b2cd..2109e591a 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -1201,7 +1201,7 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); snprintf(altname, sizeof(altname)-1, "%s_bump", mt->name); } - if (!TEXVALID(tn.bump) && loadmodel->fromgame != fg_halflife) +/* if (!TEXVALID(tn.bump) && loadmodel->fromgame != fg_halflife) { //no mip levels here, would be absurd. base = (qbyte *)(mt+1); //convert to greyscale. @@ -1210,7 +1210,7 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); tn.bump = R_LoadTexture8BumpPal(altname, tx->width, tx->height, base, true); //normalise it and then bump it. } - +*/ //don't do any complex quake 8bit -> glossmap. It would likly look a little ugly... if (gl_specular.value && gl_load24bit.value) { @@ -1373,7 +1373,7 @@ void RMod_NowLoadExternal(void) tn.bump = R_LoadBumpmapTexture(va("%s_bump", tx->name), loadname); if (!TEXVALID(tn.bump)) tn.bump = R_LoadBumpmapTexture(va("%s_bump", tx->name), "bmodels"); - if (!TEXVALID(tn.bump)) +/* if (!TEXVALID(tn.bump)) { qbyte *data; qbyte *heightmap; @@ -1392,7 +1392,7 @@ void RMod_NowLoadExternal(void) tn.bump = R_LoadTexture8BumpPal (va("%s_bump", tx->name), width, height, heightmap-j, true); } } - } +*/ } if (!TEXVALID(tn.base)) { tn.base = R_LoadTexture8("notexture", 16, 16, r_notexture_mip+1, IF_NOALPHA, 0); diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 1d8311101..69a2218cd 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -234,45 +234,60 @@ typedef struct texnums_s { struct shader_s *shader; //fixme: remove... } texnums_t; +typedef struct vboarray_s +{ + union + { + int dummy; + +#ifdef GLQUAKE + struct + { + int vbo; + void *addr; + } gl; +#endif + +#ifdef D3DQUAKE + struct + { + void *buff; + unsigned int offs; + } d3d; +#endif + }; +} vboarray_t; + typedef struct vbo_s { - int numvisible; + unsigned int numvisible; struct msurface_s **vislist; - int meshcount; + unsigned int indexcount; + unsigned int vertcount; + unsigned int meshcount; struct msurface_s **meshlist; - int vboe; - index_t *indicies; + vboarray_t indicies; void *vertdata; /*internal use*/ - int vbocoord; - vecV_t *coord; - int vbotexcoord; - vec2_t *texcoord; - int vbolmcoord; - vec2_t *lmcoord; + vboarray_t coord; + vboarray_t texcoord; + vboarray_t lmcoord; - int vbonormals; - vec3_t *normals; - int vbosvector; - vec3_t *svector; - int vbotvector; - vec3_t *tvector; + vboarray_t normals; + vboarray_t svector; + vboarray_t tvector; - int vbocolours; - vec4_t *colours4f; - byte_vec4_t *colours4ub; + vboarray_t colours; - int vbobonenums; - byte_vec4_t *bonenums; + vboarray_t bonenums; - int vboboneweights; - vec4_t *boneweights; + vboarray_t boneweights; - int vbobones; + unsigned int vbobones; float *bones; - int numbones; + unsigned int numbones; } vbo_t; void GL_SelectVBO(int vbo); void GL_SelectEBO(int vbo); diff --git a/engine/gl/gl_ngraph.c b/engine/gl/gl_ngraph.c index 5fd25d4aa..9158119f7 100644 --- a/engine/gl/gl_ngraph.c +++ b/engine/gl/gl_ngraph.c @@ -169,7 +169,7 @@ void GLR_FrameTimeGraph (int frametime) void R_NetgraphInit(void) { - TEXASSIGN(netgraphtexture, GL_AllocNewTexture("***netgraph***", NET_TIMINGS, NET_GRAPHHEIGHT)); + TEXASSIGN(netgraphtexture, R_AllocNewTexture("***netgraph***", NET_TIMINGS, NET_GRAPHHEIGHT)); netgraphshader = R_RegisterShader("netgraph", "{\n" "{\n" diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index cf636ae1f..a2798bfd4 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -99,7 +99,8 @@ void AddLightBlend (float r, float g, float b, float a2) //Con_Printf("AddLightBlend(): %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]); } -static float bubble_sintable[17], bubble_costable[17]; +#define FLASHBLEND_VERTS 16 +static float bubble_sintable[FLASHBLEND_VERTS+1], bubble_costable[FLASHBLEND_VERTS+1]; static void R_InitBubble(void) { @@ -110,15 +111,14 @@ static void R_InitBubble(void) bub_sin = bubble_sintable; bub_cos = bubble_costable; - for (i=16 ; i>=0 ; i--) + for (i=FLASHBLEND_VERTS ; i>=0 ; i--) { - a = i/16.0 * M_PI*2; + a = i/(float)FLASHBLEND_VERTS * M_PI*2; *bub_sin++ = sin(a); *bub_cos++ = cos(a); } } -#define FLASHBLEND_VERTS 16 avec4_t flashblend_colours[FLASHBLEND_VERTS+1]; vecV_t flashblend_vcoords[FLASHBLEND_VERTS+1]; vec2_t flashblend_tccoords[FLASHBLEND_VERTS+1]; @@ -128,9 +128,32 @@ mesh_t flashblend_mesh; mesh_t flashblend_fsmesh; shader_t *flashblend_shader; shader_t *lpplight_shader; + +void R_GenerateFlashblendTexture(void) +{ + float dx, dy; + int x, y, a; + unsigned char pixels[32][32][4]; + for (y = 0;y < 32;y++) + { + dy = (y - 15.5f) * (1.0f / 16.0f); + for (x = 0;x < 32;x++) + { + dx = (x - 15.5f) * (1.0f / 16.0f); + a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2))); + a = bound(0, a, 255); + pixels[y][x][0] = a; + pixels[y][x][1] = a; + pixels[y][x][2] = a; + pixels[y][x][3] = 255; + } + } + R_LoadTexture32("***flashblend***", 32, 32, pixels, 0); +} void R_InitFlashblends(void) { int i; + R_InitBubble(); for (i = 0; i < FLASHBLEND_VERTS; i++) { flashblend_indexes[i*3+0] = 0; @@ -139,7 +162,12 @@ void R_InitFlashblends(void) else flashblend_indexes[i*3+1] = i+2; flashblend_indexes[i*3+2] = i+1; + + flashblend_tccoords[i+1][0] = 0.5 + bubble_sintable[i]*0.5; + flashblend_tccoords[i+1][1] = 0.5 + bubble_costable[i]*0.5; } + flashblend_tccoords[0][0] = 0.5; + flashblend_tccoords[0][1] = 0.5; flashblend_mesh.numvertexes = FLASHBLEND_VERTS+1; flashblend_mesh.xyz_array = flashblend_vcoords; flashblend_mesh.st_array = flashblend_tccoords; @@ -156,10 +184,13 @@ void R_InitFlashblends(void) flashblend_fsmesh.numindexes = 6; flashblend_fsmesh.istrifan = true; + R_GenerateFlashblendTexture(); + flashblend_shader = R_RegisterShader("flashblend", "{\n" + "program defaultadditivesprite\n" "{\n" - "map %whiteimage\n" + "map ***flashblend***\n" "blendfunc gl_one gl_one\n" "rgbgen vertex\n" "alphagen vertex\n" @@ -167,8 +198,6 @@ void R_InitFlashblends(void) "}\n" ); lpplight_shader = NULL; - - R_InitBubble(); } static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expand) @@ -353,7 +382,7 @@ void R_GenDlightBatches(batch_t *batches[]) b->lightmap = -1; b->surf_first = i; b->flags |= BEF_NOSHADOWS; - b->vbo = 0; + b->vbo = NULL; b->next = batches[sort]; batches[sort] = b; } diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index c4504fdc7..1a8b9e341 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -78,6 +78,7 @@ cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0"); cvar_t gl_reporttjunctions = SCVAR("gl_reporttjunctions","0"); cvar_t gl_finish = SCVAR("gl_finish","0"); cvar_t gl_dither = SCVAR("gl_dither", "1"); +cvar_t r_postprocshader = CVARD("r_postprocshader", "", "Specifies a shader to use as a post-processing shader"); extern cvar_t gl_screenangle; @@ -921,6 +922,8 @@ qboolean R_RenderScene_Cubemap(void) return false; if (!ffov.value) return false; + if (!cls.allow_postproc) + return false; facemask = 0; if (ffov.value < 0) @@ -1032,6 +1035,7 @@ qboolean R_RenderScene_Cubemap(void) R_RenderScene (); GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_postproc_cube); +//FIXME: use a render target instead. qglCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, 0, 0, 0, 0, vid.pixelheight - (prect.y + cmapsize), cmapsize, cmapsize); } @@ -1160,9 +1164,11 @@ void GLR_RenderView (void) // we check if we need to use any shaders - currently it's just waterwarp if ((r_waterwarp.value>0 && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER)) { - GL_Set2D(); if (scenepp_waterwarp) + { + GL_Set2D(); R2D_ScalePic(0, 0, vid.width, vid.height, scenepp_waterwarp); + } } @@ -1170,6 +1176,16 @@ void GLR_RenderView (void) if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D) R_RenderMotionBlur(); + if (*r_postprocshader.string) + { + shader_t *postproc = R_RegisterCustom(r_postprocshader.string, NULL, NULL); + if (postproc) + { + GL_Set2D(); + R2D_ScalePic(0, 0, vid.width, vid.height, postproc); + } + } + if (qglGetError()) Con_Printf("GL Error drawing post processing\n"); } diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index a7fa272ad..8b1117877 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -996,6 +996,7 @@ TRACE(("dbg: GLR_NewMap: tp\n")); if (rtlights_first == rtlights_max) R_ImportRTLights(cl.worldmodel->entities); } + Sh_PreGenerateLights(); #endif } diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 2432f7dd5..eb506ae2c 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -30,13 +30,13 @@ void GLBE_ClearVBO(vbo_t *vbo) { int vboh[7]; int i, j; - vboh[0] = vbo->vboe; - vboh[1] = vbo->vbocoord; - vboh[2] = vbo->vbotexcoord; - vboh[3] = vbo->vbolmcoord; - vboh[4] = vbo->vbonormals; - vboh[5] = vbo->vbosvector; - vboh[6] = vbo->vbotvector; + vboh[0] = vbo->indicies.gl.vbo; + vboh[1] = vbo->coord.gl.vbo; + vboh[2] = vbo->texcoord.gl.vbo; + vboh[3] = vbo->lmcoord.gl.vbo; + vboh[4] = vbo->normals.gl.vbo; + vboh[5] = vbo->svector.gl.vbo; + vboh[6] = vbo->tvector.gl.vbo; for (i = 0; i < 7; i++) { @@ -82,45 +82,45 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int //opengl ate our data, fixup the vbo arrays to point to the vbo instead of the raw data - if (vbo->indicies && elementsize) + if (vbo->indicies.gl.addr && elementsize) { - vbo->vboe = vbos[1]; - vbo->indicies = (index_t*)((char*)vbo->indicies - (char*)edata); + vbo->indicies.gl.vbo = vbos[1]; + vbo->indicies.gl.addr = (index_t*)((char*)vbo->indicies.gl.addr - (char*)edata); } - if (vbo->coord) + if (vbo->coord.gl.addr) { - vbo->vbocoord = vbos[0]; - vbo->coord = (vecV_t*)((char*)vbo->coord - (char*)vdata); + vbo->coord.gl.vbo = vbos[0]; + vbo->coord.gl.addr = (vecV_t*)((char*)vbo->coord.gl.addr - (char*)vdata); } - if (vbo->texcoord) + if (vbo->texcoord.gl.addr) { - vbo->vbotexcoord = vbos[0]; - vbo->texcoord = (vec2_t*)((char*)vbo->texcoord - (char*)vdata); + vbo->texcoord.gl.vbo = vbos[0]; + vbo->texcoord.gl.addr = (vec2_t*)((char*)vbo->texcoord.gl.addr - (char*)vdata); } - if (vbo->lmcoord) + if (vbo->lmcoord.gl.addr) { - vbo->vbolmcoord = vbos[0]; - vbo->lmcoord = (vec2_t*)((char*)vbo->lmcoord - (char*)vdata); + vbo->lmcoord.gl.vbo = vbos[0]; + vbo->lmcoord.gl.addr = (vec2_t*)((char*)vbo->lmcoord.gl.addr - (char*)vdata); } - if (vbo->normals) + if (vbo->normals.gl.addr) { - vbo->vbonormals = vbos[0]; - vbo->normals = (vec3_t*)((char*)vbo->normals - (char*)vdata); + vbo->normals.gl.vbo = vbos[0]; + vbo->normals.gl.addr = (vec3_t*)((char*)vbo->normals.gl.addr - (char*)vdata); } - if (vbo->svector) + if (vbo->svector.gl.addr) { - vbo->vbosvector = vbos[0]; - vbo->svector = (vec3_t*)((char*)vbo->svector - (char*)vdata); + vbo->svector.gl.vbo = vbos[0]; + vbo->svector.gl.addr = (vec3_t*)((char*)vbo->svector.gl.addr - (char*)vdata); } - if (vbo->tvector) + if (vbo->tvector.gl.addr) { - vbo->vbotvector = vbos[0]; - vbo->tvector = (vec3_t*)((char*)vbo->tvector - (char*)vdata); + vbo->tvector.gl.vbo = vbos[0]; + vbo->tvector.gl.addr = (vec3_t*)((char*)vbo->tvector.gl.addr - (char*)vdata); } - if (vbo->colours4f) + if (vbo->colours.gl.addr) { - vbo->vbocolours = vbos[0]; - vbo->colours4f = (vec4_t*)((char*)vbo->colours4f - (char*)vdata); + vbo->colours.gl.vbo = vbos[0]; + vbo->colours.gl.addr = (vec4_t*)((char*)vbo->colours.gl.addr - (char*)vdata); } return true; @@ -152,6 +152,15 @@ void GLBE_GenBrushModelVBO(model_t *mod) mesh_t *m; char *p; + vecV_t *coord; + vec2_t *texcoord; + vec2_t *lmcoord; + vec3_t *normals; + vec3_t *svector; + vec3_t *tvector; + vec4_t *colours; + index_t *indicies; + if (!mod->numsurfaces) return; @@ -200,14 +209,23 @@ void GLBE_GenBrushModelVBO(model_t *mod) p = vbo->vertdata; - vbo->coord = allocbuf(&p, maxvboverts, sizeof(*vbo->coord)); - vbo->texcoord = allocbuf(&p, maxvboverts, sizeof(*vbo->texcoord)); - vbo->lmcoord = allocbuf(&p, maxvboverts, sizeof(*vbo->lmcoord)); - vbo->normals = allocbuf(&p, maxvboverts, sizeof(*vbo->normals)); - vbo->svector = allocbuf(&p, maxvboverts, sizeof(*vbo->svector)); - vbo->tvector = allocbuf(&p, maxvboverts, sizeof(*vbo->tvector)); - vbo->colours4f = allocbuf(&p, maxvboverts, sizeof(*vbo->colours4f)); - vbo->indicies = allocbuf(&p, maxvboelements, sizeof(index_t)); + vbo->coord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vecV_t)); + vbo->texcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); + vbo->lmcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); + vbo->normals.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); + vbo->svector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); + vbo->tvector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); + vbo->colours.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec4_t)); + vbo->indicies.gl.addr = allocbuf(&p, maxvboelements, sizeof(index_t)); + + coord = vbo->coord.gl.addr; + texcoord = vbo->texcoord.gl.addr; + lmcoord = vbo->lmcoord.gl.addr; + normals = vbo->normals.gl.addr; + svector = vbo->svector.gl.addr; + tvector = vbo->tvector.gl.addr; + colours = vbo->colours.gl.addr; + indicies = vbo->indicies.gl.addr; vbo->meshcount = meshes; vbo->meshlist = BZ_Malloc(meshes*sizeof(*vbo->meshlist)); @@ -228,62 +246,57 @@ void GLBE_GenBrushModelVBO(model_t *mod) m->vbofirstvert = vcount; m->vbofirstelement = ecount; for (v = 0; v < m->numindexes; v++) - vbo->indicies[ecount++] = vcount + m->indexes[v]; + indicies[ecount++] = vcount + m->indexes[v]; for (v = 0; v < m->numvertexes; v++) { - vbo->coord[vcount+v][0] = m->xyz_array[v][0]; - vbo->coord[vcount+v][1] = m->xyz_array[v][1]; - vbo->coord[vcount+v][2] = m->xyz_array[v][2]; + coord[vcount+v][0] = m->xyz_array[v][0]; + coord[vcount+v][1] = m->xyz_array[v][1]; + coord[vcount+v][2] = m->xyz_array[v][2]; if (m->st_array) { - vbo->texcoord[vcount+v][0] = m->st_array[v][0]; - vbo->texcoord[vcount+v][1] = m->st_array[v][1]; + texcoord[vcount+v][0] = m->st_array[v][0]; + texcoord[vcount+v][1] = m->st_array[v][1]; } if (m->lmst_array) { - vbo->lmcoord[vcount+v][0] = m->lmst_array[v][0]; - vbo->lmcoord[vcount+v][1] = m->lmst_array[v][1]; + lmcoord[vcount+v][0] = m->lmst_array[v][0]; + lmcoord[vcount+v][1] = m->lmst_array[v][1]; } if (m->normals_array) { - vbo->normals[vcount+v][0] = m->normals_array[v][0]; - vbo->normals[vcount+v][1] = m->normals_array[v][1]; - vbo->normals[vcount+v][2] = m->normals_array[v][2]; + normals[vcount+v][0] = m->normals_array[v][0]; + normals[vcount+v][1] = m->normals_array[v][1]; + normals[vcount+v][2] = m->normals_array[v][2]; } if (m->snormals_array) { - vbo->svector[vcount+v][0] = m->snormals_array[v][0]; - vbo->svector[vcount+v][1] = m->snormals_array[v][1]; - vbo->svector[vcount+v][2] = m->snormals_array[v][2]; + svector[vcount+v][0] = m->snormals_array[v][0]; + svector[vcount+v][1] = m->snormals_array[v][1]; + svector[vcount+v][2] = m->snormals_array[v][2]; } if (m->tnormals_array) { - vbo->tvector[vcount+v][0] = m->tnormals_array[v][0]; - vbo->tvector[vcount+v][1] = m->tnormals_array[v][1]; - vbo->tvector[vcount+v][2] = m->tnormals_array[v][2]; + tvector[vcount+v][0] = m->tnormals_array[v][0]; + tvector[vcount+v][1] = m->tnormals_array[v][1]; + tvector[vcount+v][2] = m->tnormals_array[v][2]; } if (m->colors4f_array) { - vbo->colours4f[vcount+v][0] = m->colors4f_array[v][0]; - vbo->colours4f[vcount+v][1] = m->colors4f_array[v][1]; - vbo->colours4f[vcount+v][2] = m->colors4f_array[v][2]; - vbo->colours4f[vcount+v][3] = m->colors4f_array[v][3]; + colours[vcount+v][0] = m->colors4f_array[v][0]; + colours[vcount+v][1] = m->colors4f_array[v][1]; + colours[vcount+v][2] = m->colors4f_array[v][2]; + colours[vcount+v][3] = m->colors4f_array[v][3]; } } vcount += v; } - if (GL_BuildVBO(vbo, vbo->coord, vcount*pervertsize, vbo->indicies, ecount*sizeof(index_t))) + if (GL_BuildVBO(vbo, vbo->vertdata, vcount*pervertsize, indicies, ecount*sizeof(index_t))) { BZ_Free(vbo->vertdata); vbo->vertdata = NULL; } } -/* for (i=0 ; inumsurfaces ; i++) - { - if (!mod->surfaces[i].mark) - Host_EndGame("Surfaces with bad textures detected\n"); - }*/ } void GLBE_UploadAllLightmaps(void) diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 436de105d..25433900c 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -110,7 +110,7 @@ void GLSCR_UpdateScreen (void) if (editormodal) { Editor_Draw(); - GLV_UpdatePalette (false, host_frametime); + V_UpdatePalette (false); #if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); #endif @@ -127,7 +127,7 @@ void GLSCR_UpdateScreen (void) if (Media_ShowFilm()) { M_Draw(0); - GLV_UpdatePalette (false, host_frametime); + V_UpdatePalette (false); #if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); #endif @@ -205,7 +205,7 @@ void GLSCR_UpdateScreen (void) SCR_DrawTwoDimensional(uimenu, nohud); - GLV_UpdatePalette (false, host_frametime); + V_UpdatePalette (false); #if defined(_WIN32) && defined(GLQUAKE) Media_RecordFrame(); #endif diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 3d15a35d5..77260a6c4 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -52,6 +52,7 @@ int be_maxpasses; #define Q_stricmp stricmp +#define Q_strnicmp strnicmp #define Com_sprintf snprintf #define clamp(v,min, max) (v) = (((v)<(min))?(min):(((v)>(max))?(max):(v))); @@ -229,7 +230,7 @@ static qboolean Shader_EvaluateCondition(char **ptr) { token++; if (!Q_stricmp(token, "lpp")) - conditiontrue = conditiontrue == !r_lightprepass.ival; + conditiontrue = conditiontrue == r_lightprepass.ival; else if (!Q_stricmp(token, "lightmap")) conditiontrue = conditiontrue == !r_fullbright.value; else if (!Q_stricmp(token, "deluxmap") ) @@ -537,10 +538,21 @@ static void Shader_ParseFunc ( char **ptr, shaderfunc_t *func ) //=========================================================================== -static int Shader_SetImageFlags ( shader_t *shader ) +static int Shader_SetImageFlags(shader_t *shader, char **name) { int flags = 0; + while (name) + { + if (!Q_strnicmp(*name, "$3d:", 4)) + { + *name+=4; + flags|= IF_3DMAP; + } + else + name = NULL; + } + // if (shader->flags & SHADER_SKY) // flags |= IF_SKY; if (shader->flags & SHADER_NOMIPMAPS) @@ -562,7 +574,7 @@ static texid_t Shader_FindImage ( char *name, int flags ) if (!Q_stricmp (name, "_black")) { int wibuf[16] = {0}; - return R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);; + return R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA); } } else @@ -776,7 +788,7 @@ static void Shader_EntityMergable ( shader_t *shader, shaderpass_t *pass, char * shader->flags |= SHADER_ENTITY_MERGABLE; } -static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames); +static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvartypes); /*program text is already loaded, this function parses the 'header' of it to see which permutations it provides, and how many times we need to recompile it*/ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, int qrtype, int ver) { @@ -789,6 +801,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i "#define UPPER\n", "#define OFFSETMAPPING\n", "#define SKELETAL\n", + "#define FOG\n", NULL }; char *permutationdefines[sizeof(permutationname)/sizeof(permutationname[0])]; @@ -796,10 +809,11 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i int p, n, pn; char *end; - char *cvarfnames[64]; - int cvarfcount = 0; + char *cvarnames[64]; + int cvartypes[64]; + int cvarcount = 0; - cvarfnames[cvarfcount] = NULL; + cvarnames[cvarcount] = NULL; for(;;) { @@ -813,9 +827,28 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i end = script; while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_') end++; - if (cvarfcount+1 != sizeof(cvarfnames)/sizeof(cvarfnames[0])) - cvarfnames[cvarfcount++] = script; - cvarfnames[cvarfcount] = NULL; + if (cvarcount+1 != sizeof(cvarnames)/sizeof(cvarnames[0])) + { + cvartypes[cvarcount] = SP_CVARF; + cvarnames[cvarcount++] = script; + cvarnames[cvarcount] = NULL; + } + script = end; + } + else if (!strncmp(script, "!!cvarv", 7)) + { + script += 7; + while (*script == ' ' || *script == '\t') + script++; + end = script; + while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_') + end++; + if (cvarcount+1 != sizeof(cvarnames)/sizeof(cvarnames[0])) + { + cvartypes[cvarcount] = SP_CVAR3F; + cvarnames[cvarcount++] = script; + cvarnames[cvarcount] = NULL; + } script = end; } else if (!strncmp(script, "!!permu", 7)) @@ -890,7 +923,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i #endif } - Shader_ProgAutoFields(prog, cvarfnames); + Shader_ProgAutoFields(prog, cvarnames, cvartypes); } typedef struct sgeneric_s { @@ -991,6 +1024,63 @@ struct sbuiltin_s "}\n" "#endif\n" }, + + {QR_OPENGL, 110, "defaultsprite", + "!!permu FOG\n" + "#include \"sys/fog.h\"\n" + "#ifdef VERTEX_SHADER\n" + "attribute vec2 v_texcoord;\n" + "attribute vec4 v_colour;\n" + "varying vec2 tc;\n" + "varying vec4 vc;\n" + + "void main ()\n" + "{\n" + " tc = v_texcoord;\n" + " vc = v_colour;\n" + " gl_Position = ftetransform();\n" + "}\n" + "#endif\n" + + "#ifdef FRAGMENT_SHADER\n" + "uniform sampler2D s_t0;\n" + "in vec2 tc;\n" + "varying vec4 vc;\n" + + "void main ()\n" + "{\n" + " gl_FragColor = fog4blend(texture2D(s_t0, tc) * vc);\n" + "}\n" + "#endif\n" + }, + {QR_OPENGL, 110, "defaultadditivesprite", + "!!permu FOG\n" + "#include \"sys/fog.h\"\n" + "#ifdef VERTEX_SHADER\n" + "attribute vec2 v_texcoord;\n" + "attribute vec4 v_colour;\n" + "varying vec2 tc;\n" + "varying vec4 vc;\n" + + "void main ()\n" + "{\n" + " tc = v_texcoord;\n" + " vc = v_colour;\n" + " gl_Position = ftetransform();\n" + "}\n" + "#endif\n" + + "#ifdef FRAGMENT_SHADER\n" + "uniform sampler2D s_t0;\n" + "in vec2 tc;\n" + "varying vec4 vc;\n" + + "void main ()\n" + "{\n" + " gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc);\n" + "}\n" + "#endif\n" + }, /*draws a wall, with lightmap.*/ {QR_OPENGL/*ES*/, 100, "defaultwall", "!!cvarf gl_overbright\n" @@ -1025,6 +1115,8 @@ struct sbuiltin_s }, {QR_OPENGL, 110, "defaultwall", "!!cvarf gl_overbright\n" + "!!permu FOG\n" + "#include \"sys/fog.h\"\n" "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" "attribute vec2 v_lmcoord;\n" @@ -1050,7 +1142,41 @@ struct sbuiltin_s "void main ()\n" "{\n" " float scale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n" - " gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1);\n" + " gl_FragColor = fog4(texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1));\n" + "}\n" + "#endif\n" + }, + {QR_OPENGL, 110, "drawflat_wall", + "!!cvarf gl_overbright\n" + "!!cvarv r_floorcolor\n" + "!!cvarv r_wallcolor\n" + "!!permu FOG\n" + "#include \"sys/fog.h\"\n" + "varying vec4 col;\n" + "#ifdef VERTEX_SHADER\n" + "attribute vec3 v_normal;\n" + "attribute vec2 v_lmcoord;\n" + "varying vec2 lm;\n" + "uniform vec3 cvar_r_wallcolor;\n" + "uniform vec3 cvar_r_floorcolor;\n" + "uniform float cvar_gl_overbright;\n" + + "void main ()\n" + "{\n" + " float scale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0))) / 255.0;\n" + " col = scale * vec4((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor, 1.0);\n" + " lm = v_lmcoord;\n" + " gl_Position = ftetransform();\n" + "}\n" + "#endif\n" + + "#ifdef FRAGMENT_SHADER\n" + "uniform sampler2D s_t0;\n" /*tex_lightmap*/ + "varying vec2 lm;\n" + + "void main ()\n" + "{\n" + " gl_FragColor = fog4(col * texture2D(s_t0, lm));\n" "}\n" "#endif\n" }, @@ -1085,6 +1211,8 @@ struct sbuiltin_s }, {QR_OPENGL, 110, "defaultwarp", "!!cvarf r_wateralpha\n" + "!!permu FOG\n" + "#include \"sys/fog.h\"\n" "varying vec2 tc;\n" "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" @@ -1107,7 +1235,7 @@ struct sbuiltin_s " ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n" " vec3 ts = vec3(texture2D(s_t0, ntc));\n" - " gl_FragColor = vec4(ts, cvar_r_wateralpha);\n" + " gl_FragColor = fog4(vec4(ts, cvar_r_wateralpha));\n" "}\n" "#endif\n" }, @@ -1366,6 +1494,7 @@ struct sbuiltin_s "!!permu LOWER\n" "!!permu UPPER\n" "!!permu SKELETAL\n" + "!!permu FOG\n" "varying vec2 tc;\n" "varying vec3 light;\n" "#ifdef VERTEX_SHADER\n" @@ -1385,6 +1514,7 @@ struct sbuiltin_s "#endif\n" "#ifdef FRAGMENT_SHADER\n" + "#include \"sys/fog.h\"\n" "uniform sampler2D s_t0;\n" /*tex_diffuse*/ "#ifdef LOWER\n" "uniform sampler2D s_t1;\n" /*tex_lower*/ @@ -1416,14 +1546,13 @@ struct sbuiltin_s " vec4 fb = texture2D(s_t3, tc);\n" " col.rgb = mix(col.rgb, fb.rgb, fb.a);\n" "#endif\n" - " gl_FragColor = col * e_colourident;\n" + " gl_FragColor = fog4(col * e_colourident);\n" "}\n" "#endif\n" }, {QR_OPENGL, 110, "lpp_depthnorm", "!!permu BUMP\n" "!!permu SKELETAL\n" - "varying vec2 pos;\n" "varying vec3 norm, tang, bitang;\n" "#if defined(BUMP)\n" "varying vec2 tc;\n" @@ -1439,7 +1568,6 @@ struct sbuiltin_s "#else\n" "gl_Position = skeletaltransform_n(norm);\n" "#endif\n" - "pos = gl_Position.zw;\n" "}\n" "#endif\n" "#ifdef FRAGMENT_SHADER\n" @@ -1456,7 +1584,7 @@ struct sbuiltin_s "#else\n" "onorm = norm;\n" "#endif\n" - "gl_FragColor = vec4(onorm.xyz, pos.x/pos.y);\n" + "gl_FragColor = vec4(onorm.xyz, gl_FragCoord.z / gl_FragCoord.w);\n" "}\n" "#endif\n" }, @@ -1569,6 +1697,35 @@ struct sbuiltin_s "#endif\n" }, + {QR_OPENGL, 110, "colourtint", + "varying vec4 tf;\n" + "#ifdef VERTEX_SHADER\n" + "void main ()\n" + "{\n" + "gl_Position = tf = vec4(v_position.xy,-1.0, 1.0);\n" + "}\n" + "#endif\n" + + "#ifdef FRAGMENT_SHADER\n" + "uniform sampler2D s_t0;\n" + "uniform sampler3D s_t1;\n" + "void main()\n" + "{\n" + "vec2 fc;\n" + "fc = tf.xy / tf.w;\n" + "vec3 raw = texture2D(s_t0, (1.0 + fc) / 2.0).rgb;\n" + + //scale+bias the sample to not clamp out at the edges + "#define LUTSIZE 16.0\n" + "vec3 scale = vec3((LUTSIZE-1.0)/LUTSIZE);\n" + "vec3 bias = vec3(1.0/(2.0*LUTSIZE));\n" + + "gl_FragColor = texture3D(s_t1, raw * scale + bias);\n" + + "}\n" + "#endif\n" + }, + {QR_OPENGL, 110, "crepuscular_rays", /*yoinked from http://fabiensanglard.net/lightScattering/index.php*/ "!!cvarf crep_decay\n" @@ -1586,10 +1743,10 @@ struct sbuiltin_s "#endif\n" "#ifdef FRAGMENT_SHADER\n" - "uniform float cvar_crep_decay;\n" - "uniform float cvar_crep_density;\n" - "uniform float cvar_crep_weight;\n" - "uniform float l_lightcolour;\n" + "const float crep_decay = 0.94;\n" + "const float crep_density = 0.5;\n" + "const float crep_weight = 0.2;\n" + "uniform vec3 l_lightcolour;\n" "uniform vec3 l_lightscreen;\n" "uniform sampler2D s_t0;\n" "const int NUM_SAMPLES = 100;\n" @@ -1599,18 +1756,18 @@ struct sbuiltin_s // "gl_FragColor = texture2D(s_t0, tc.st);\n" "vec2 deltaTextCoord = vec2( tc.st - l_lightscreen.xy );\n" "vec2 textCoo = tc.st;\n" - "deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * cvar_crep_density;\n" + "deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * crep_density;\n" "float illuminationDecay = 1.0;\n" "for(int i=0; i < NUM_SAMPLES ; i++)\n" "{\n" "textCoo -= deltaTextCoord;\n" "vec4 sample = texture2D(s_t0, textCoo);\n" - "sample *= illuminationDecay * cvar_crep_weight;\n" + "sample *= illuminationDecay * crep_weight;\n" "gl_FragColor += sample;\n" - "illuminationDecay *= cvar_crep_decay;\n" + "illuminationDecay *= crep_decay;\n" "}\n" - "gl_FragColor *= l_lightcolour;\n" + "gl_FragColor *= vec4(l_lightcolour, 1.0);\n" "}\n" "#endif\n" }, @@ -1761,18 +1918,29 @@ struct sbuiltin_s static sgeneric_t *sgenerics; void Shader_UnloadGeneric(program_t *prog) { - int p; if (prog->refs == 1) { #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { + int p; for (p = 0; p < PERMUTATIONS; p++) { if (prog->handle[p].glsl) qglDeleteProgramObject_(prog->handle[p].glsl); } } +#endif +#ifdef D3DQUAKE + if (qrenderer == QR_DIRECT3D) + { + int p; + for (p = 0; p < PERMUTATIONS; p++) + { +// if (prog->handle[p].hlsl.vert || prog->handle[p].hlsl.frag) +// D3DShader_DeleteProgram(&prog->handle[p].hlsl); + } + } #endif free(prog); } @@ -1938,6 +2106,7 @@ struct shader_field_names_s shader_field_names[] = /*viewer properties*/ {"v_eyepos", SP_V_EYEPOS}, + {"w_fog", SP_W_FOG}, /*ent properties*/ {"e_origin", SP_E_ORIGIN}, @@ -1962,7 +2131,7 @@ struct shader_field_names_s shader_field_names[] = {NULL} }; -static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) +static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvartypes) { unsigned int i, p; qboolean found; @@ -1978,15 +2147,18 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) prog->nofixedcompat = true; /*set cvar unirforms*/ - for (i = 0; cvarfnames[i]; i++) + for (i = 0; cvarnames[i]; i++) { - for (p = 0; cvarfnames[i][p] && (unsigned char)cvarfnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) - tmpname[p] = cvarfnames[i][p]; + for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) + tmpname[p] = cvarnames[i][p]; tmpname[p] = 0; cvar = Cvar_Get(tmpname, "0", CVAR_SHADERSYSTEM, "glsl cvars"); if (!cvar) continue; cvar->flags |= CVAR_SHADERSYSTEM; + prog->parm[prog->numparams].type = cvartypes[i]; + prog->parm[prog->numparams].pval = cvar; + found = false; for (p = 0; p < PERMUTATIONS; p++) { if (!prog->handle[p].glsl) @@ -1994,8 +2166,14 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) GL_SelectProgram(prog->handle[p].glsl); uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, va("cvar_%s", tmpname)); if (uniformloc != -1) + { qglUniform1fARB(uniformloc, cvar->value); + found = true; + } + prog->parm[prog->numparams].handle[p] = uniformloc; } + if (found) + prog->numparams++; } for (i = 0; shader_field_names[i].name; i++) { @@ -2044,10 +2222,10 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) prog->nofixedcompat = true; /*set cvar uniforms*/ - for (i = 0; cvarfnames[i]; i++) + for (i = 0; cvarnames[i]; i++) { - for (p = 0; cvarfnames[i][p] && (unsigned char)cvarfnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) - tmpname[p] = cvarfnames[i][p]; + for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) + tmpname[p] = cvarnames[i][p]; tmpname[p] = 0; cvar = Cvar_FindVar(tmpname); if (!cvar) @@ -2486,8 +2664,11 @@ static void Shaderpass_Map (shader_t *shader, shaderpass_t *pass, char **ptr) token = Shader_ParseString (ptr); if (!ShaderPass_MapGen(shader, pass, token)) { - pass->texgen = T_GEN_SINGLEMAP; - flags = Shader_SetImageFlags (shader); + flags = Shader_SetImageFlags (shader, &token); + if (flags & IF_3DMAP) + pass->texgen = T_GEN_3DMAP; + else + pass->texgen = T_GEN_SINGLEMAP; pass->tcgen = TC_GEN_BASE; pass->anim_frames[0] = Shader_FindImage (token, flags); @@ -2500,7 +2681,7 @@ static void Shaderpass_AnimMap (shader_t *shader, shaderpass_t *pass, char **ptr char *token; texid_t image; - flags = Shader_SetImageFlags (shader); + flags = Shader_SetImageFlags (shader, NULL); pass->tcgen = TC_GEN_BASE; pass->flags |= SHADER_PASS_ANIMMAP; @@ -2542,15 +2723,21 @@ static void Shaderpass_ClampMap (shader_t *shader, shaderpass_t *pass, char **pt if (!ShaderPass_MapGen(shader, pass, token)) { - flags = Shader_SetImageFlags (shader); + flags = Shader_SetImageFlags (shader, &token); pass->tcgen = TC_GEN_BASE; pass->anim_frames[0] = Shader_FindImage (token, flags | IF_CLAMP); - pass->texgen = T_GEN_SINGLEMAP; + if (flags & IF_3DMAP) + pass->texgen = T_GEN_3DMAP; + else + pass->texgen = T_GEN_SINGLEMAP; if (!TEXVALID(pass->anim_frames[0])) { - pass->anim_frames[0] = missing_texture; + if (flags & (IF_3DMAP | IF_CUBEMAP)) + pass->anim_frames[0] = r_nulltex; + else + pass->anim_frames[0] = missing_texture; Con_DPrintf (CON_WARNING "Shader %s has a stage with no image: %s.\n", shader->name, token); } } @@ -3096,10 +3283,12 @@ static void Shaderpass_TexGen(shader_t *shader, shaderpass_t *pass, char **ptr) } static void Shaderpass_CubeMap(shader_t *shader, shaderpass_t *pass, char **ptr) { + char *token = Shader_ParseString(ptr); + if (pass->tcgen == TC_GEN_BASE) pass->tcgen = TC_GEN_SKYBOX; - pass->texgen = T_GEN_SKYBOX; - pass->anim_frames[0] = r_nulltex;//Shader_FindImage(token, flags); + pass->texgen = T_GEN_CUBEMAP; + pass->anim_frames[0] = Shader_FindImage(token, IF_CUBEMAP); if (!TEXVALID(pass->anim_frames[0])) { @@ -3794,7 +3983,7 @@ void Shader_Finish (shader_t *s) if (TEXVALID(s->defaulttextures.base)) s->flags &= ~SHADER_NOIMAGE; - if (!s->numpasses && s->sort != SHADER_SORT_PORTAL && !(s->flags & (SHADER_NODRAW|SHADER_SKY)) && !s->fog_dist) + if (!s->numpasses && s->sort != SHADER_SORT_PORTAL && !(s->flags & (SHADER_NODRAW|SHADER_SKY)) && !s->fog_dist && !s->prog) { pass = &s->passes[s->numpasses++]; pass = &s->passes[0]; @@ -4143,6 +4332,7 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) if (!builtin && r_drawflat.value) builtin = ( "{\n" + "program drawflat_wall\n" "{\n" "map $lightmap\n" "tcgen lightmap\n" @@ -4151,59 +4341,62 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) "}\n" ); #ifdef GLQUAKE - if (!builtin && r_lightprepass.ival) + if (qrenderer == QR_OPENGL) { - builtin = ( - "{\n" - "program lpp_wall\n" + if (!builtin && r_lightprepass.ival) + { + builtin = ( "{\n" - "map $sourcecolour\n" + "program lpp_wall\n" + "{\n" + "map $sourcecolour\n" + "}\n" + "{\n" + "map $diffuse\n" + "}\n" + "{\n" + "map $lightmap\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $deluxmap\n" + "}\n" + "{\n" + "map $fullbright\n" + "}\n" "}\n" + ); + } + if (!builtin && gl_config.arb_shader_objects) + { + builtin = ( "{\n" - "map $diffuse\n" + "program defaultwall\n" + /*"param texture 0 tex_diffuse\n" + "param texture 1 tex_lightmap\n" + "param texture 2 tex_normalmap\n" + "param texture 3 tex_deluxmap\n" + "param texture 4 tex_fullbright\n"*/ + "{\n" + "map $diffuse\n" + "}\n" + "{\n" + "map $lightmap\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $deluxmap\n" + "}\n" + "{\n" + "map $fullbright\n" + "}\n" "}\n" - "{\n" - "map $lightmap\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $deluxmap\n" - "}\n" - "{\n" - "map $fullbright\n" - "}\n" - "}\n" - ); - } - if (!builtin && gl_config.arb_shader_objects && gl_config.nofixedfunc) - { - builtin = ( - "{\n" - "program defaultwall\n" - /*"param texture 0 tex_diffuse\n" - "param texture 1 tex_lightmap\n" - "param texture 2 tex_normalmap\n" - "param texture 3 tex_deluxmap\n" - "param texture 4 tex_fullbright\n"*/ - "{\n" - "map $diffuse\n" - "}\n" - "{\n" - "map $lightmap\n" - "}\n" - "{\n" - "map $normalmap\n" - "}\n" - "{\n" - "map $deluxmap\n" - "}\n" - "{\n" - "map $fullbright\n" - "}\n" - "}\n" - ); + ); + } } #endif if (!builtin) @@ -4619,9 +4812,9 @@ void Shader_DefaultSkin(char *shortname, shader_t *s, const void *args) "{\n" "if $lpp\n" "[\n" - "program defaultskin\n" - "][\n" "program lpp_skin\n" + "][\n" + "program defaultskin\n" "]\n" "{\n" "map $diffuse\n" diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 1f8dddfbb..42a18a432 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -882,7 +882,7 @@ static void SHM_ComposeVolume_Fan(vecV_t *points, int numpoints) int i; #define MAX_ARRAY_VERTS 65535 - static int pointidx[MAX_ARRAY_VERTS]; + static index_t pointidx[MAX_ARRAY_VERTS]; /*make sure there's space*/ newmax = (cv.numpoints+numpoints + inc)&~(inc-1); @@ -913,19 +913,19 @@ static void SHM_ComposeVolume_Fan(vecV_t *points, int numpoints) { cv.tris[cv.numtris].edge[0] = lastedge; cv.tris[cv.numtris].edge[1] = SHM_ComposeVolume_FindEdge(pointidx[i-1], pointidx[i]); - lastedge = SHM_ComposeVolume_FindEdge(pointidx[i], pointidx[i-2]); + lastedge = SHM_ComposeVolume_FindEdge(pointidx[i], pointidx[0]); cv.tris[cv.numtris].edge[2] = lastedge; lastedge = -(lastedge+1); cv.numtris++; } } -static void SHM_ComposeVolume_Soup(vecV_t *points, int numpoints, int *idx, int numidx) +static void SHM_ComposeVolume_Soup(vecV_t *points, int numpoints, index_t *idx, int numidx) { int newmax; int i; #define MAX_ARRAY_VERTS 65535 - static int pointidx[MAX_ARRAY_VERTS]; + static index_t pointidx[MAX_ARRAY_VERTS]; /*make sure there's space*/ newmax = (cv.numpoints+numpoints + inc)&~(inc-1); @@ -1024,9 +1024,9 @@ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) VectorNormalize(ext); /*back face*/ - sh_shmesh->verts[(i * 2) + 1][0] = cv.points[i][0] + ext[0] * dl->radius*2; - sh_shmesh->verts[(i * 2) + 1][1] = cv.points[i][1] + ext[1] * dl->radius*2; - sh_shmesh->verts[(i * 2) + 1][2] = cv.points[i][2] + ext[2] * dl->radius*2; + sh_shmesh->verts[(i * 2) + 1][0] = cv.points[i][0] + ext[0] * dl->radius; + sh_shmesh->verts[(i * 2) + 1][1] = cv.points[i][1] + ext[1] * dl->radius; + sh_shmesh->verts[(i * 2) + 1][2] = cv.points[i][2] + ext[2] * dl->radius; } sh_shmesh->numverts = i*2; @@ -1100,9 +1100,20 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi { case fg_quake: case fg_halflife: - SHM_BeginShadowMesh(dl, surfonly); - SHM_MarkLeavesQ1(dl, lvis); - SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes); + if (!dl->die) + { + SHM_BeginShadowMesh(dl, true); + SHM_MarkLeavesQ1(dl, lvis); + SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes); + if (!surfonly) + SHM_ComposeVolume_BruteForce(dl); + } + else + { + SHM_BeginShadowMesh(dl, surfonly); + SHM_MarkLeavesQ1(dl, lvis); + SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes); + } break; #ifdef Q2BSPS case fg_quake2: @@ -2111,13 +2122,17 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) v2 = surf->mesh->xyz_array[( v+1 )%surf->mesh->numvertexes]; //get positions of v3 and v4 based on the light position - v3[0] = ( v1[0]-lightorg[0] )*PROJECTION_DISTANCE; - v3[1] = ( v1[1]-lightorg[1] )*PROJECTION_DISTANCE; - v3[2] = ( v1[2]-lightorg[2] )*PROJECTION_DISTANCE; + v3[0] = ( v1[0]-lightorg[0] ); + v3[1] = ( v1[1]-lightorg[1] ); + v3[2] = ( v1[2]-lightorg[2] ); + VectorNormalizeFast(v3); + VectorScale(v3, PROJECTION_DISTANCE, v3); - v4[0] = ( v2[0]-lightorg[0] )*PROJECTION_DISTANCE; - v4[1] = ( v2[1]-lightorg[1] )*PROJECTION_DISTANCE; - v4[2] = ( v2[2]-lightorg[2] )*PROJECTION_DISTANCE; + v4[0] = ( v2[0]-lightorg[0] ); + v4[1] = ( v2[1]-lightorg[1] ); + v4[2] = ( v2[2]-lightorg[2] ); + VectorNormalizeFast(v4); + VectorScale(v4, PROJECTION_DISTANCE, v4); //Now draw the quad from the two verts to the projected light //verts @@ -2135,9 +2150,11 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) for (v = surf->mesh->numvertexes-1; v >=0; v--) { v1 = surf->mesh->xyz_array[v]; - v3[0] = (v1[0]-lightorg[0])*PROJECTION_DISTANCE; - v3[1] = (v1[1]-lightorg[1])*PROJECTION_DISTANCE; - v3[2] = (v1[2]-lightorg[2])*PROJECTION_DISTANCE; + v3[0] = (v1[0]-lightorg[0]); + v3[1] = (v1[1]-lightorg[1]); + v3[2] = (v1[2]-lightorg[2]); + VectorNormalizeFast(v3); + VectorScale(v3, PROJECTION_DISTANCE, v3); qglVertex3f(v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2]); } @@ -2472,7 +2489,7 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); - SHM_BuildShadowMesh(dl, lvis, vvis, false); + SHM_BuildShadowMesh(dl, lvis, vvis, true); if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect. { @@ -2595,6 +2612,42 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches) #endif } +void Sh_PreGenerateLights(void) +{ + unsigned int ignoreflags; + dlight_t *dl; + qboolean shadow; + int leaf; + qbyte *lvis; + qbyte lvisb[MAX_MAP_LEAFS/8]; + int i; + + ignoreflags = (r_shadow_realtime_world.value?LFLAG_REALTIMEMODE:LFLAG_NORMALMODE); + + for (dl = cl_dlights+rtlights_first, i=rtlights_first; iradius) + continue; //dead + + if (!(dl->flags & ignoreflags)) + continue; + + if (dl->flags & LFLAG_CREPUSCULAR) + continue; + else if (((!dl->die)?!r_shadow_realtime_world_shadows.ival:!r_shadow_realtime_dlight_shadows.ival) || dl->flags & LFLAG_NOSHADOWS) + shadow = false; + else if (dl->flags & LFLAG_SHADOWMAP) + shadow = false; + else + shadow = true; + + leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); + lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); + + SHM_BuildShadowMesh(dl, lvis, NULL, !shadow); + } +} + void Sh_DrawLights(qbyte *vis, batch_t **mbatches) { vec3_t colour; diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 5759b0fbe..3986aa065 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -69,6 +69,7 @@ void (APIENTRY *qglTexEnvi) (GLenum target, GLenum pname, GLint param); void (APIENTRY *qglTexGeni) (GLenum coord, GLenum pname, GLint param); void (APIENTRY *qglTexGenfv) (GLenum coord, GLenum pname, const GLfloat *param); void (APIENTRY *qglTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +void (APIENTRY *qglTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); void (APIENTRY *qglTexParameteri) (GLenum target, GLenum pname, GLint param); void (APIENTRY *qglTexParameterf) (GLenum target, GLenum pname, GLfloat param); void (APIENTRY *qglTexParameteriv) (GLenum target, GLenum pname, const GLint *params); @@ -757,6 +758,64 @@ static const char *glsl_hdrs[] = "}\n" "#endif\n" , + "sys/fog.h", + "#ifdef FRAGMENT_SHADER\n" + "#ifdef FOG\n" + "uniform vec4 w_fog;\n" + "vec3 fog3(in vec3 regularcolour)" + "{" + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" + "float fac = exp2(-(" + "w_fog.w * w_fog.w * " + "z * z * " + "1.442695));\n" + "fac = clamp(fac, 0.0, 1.0);\n" + "return mix(w_fog.rgb, regularcolour, fac);\n" + "}\n" + "vec3 fog3additive(in vec3 regularcolour)" + "{" + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" + "float fac = exp2(-(" + "w_fog.w * w_fog.w * " + "z * z * " + "1.442695));\n" + "fac = clamp(fac, 0.0, 1.0);\n" + "return regularcolour * fac;\n" + "}\n" + "vec4 fog4(in vec4 regularcolour)" + "{" + "return vec4(fog3(regularcolour.rgb), 1.0) * regularcolour.a;\n" + "}\n" + "vec4 fog4additive(in vec4 regularcolour)" + "{" + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" + "float fac = exp2(-(" + "w_fog.w * w_fog.w * " + "z * z * " + "1.442695));\n" + "fac = clamp(fac, 0.0, 1.0);\n" + "return regularcolour * vec4(fac, fac, fac, 1.0);\n" + "}\n" + "vec4 fog4blend(in vec4 regularcolour)" + "{" + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" + "float fac = exp2(-(" + "w_fog.w * w_fog.w * " + "z * z * " + "1.442695));\n" + "fac = clamp(fac, 0.0, 1.0);\n" + "return regularcolour * vec4(1.0, 1.0, 1.0, fac);\n" + "}\n" + "#else\n" + /*don't use macros for this - mesa bugs out*/ + "vec3 fog3(in vec3 regularcolour) { return regularcolour; }\n" + "vec3 fog3additive(in vec3 regularcolour) { return regularcolour; }\n" + "vec4 fog4(in vec4 regularcolour) { return regularcolour; }\n" + "vec4 fog4additive(in vec4 regularcolour) { return regularcolour; }\n" + "vec4 fog4blend(in vec4 regularcolour) { return regularcolour; }\n" + "#endif\n" + "#endif\n" + , NULL }; @@ -1100,6 +1159,7 @@ void GL_Init(void *(*getglfunction) (char *name)) qglTexGeni = (void *)getglcore("glTexGeni"); qglTexGenfv = (void *)getglcore("glTexGenfv"); qglTexImage2D = (void *)getglcore("glTexImage2D"); + qglTexImage3D = (void *)getglext("glTexImage3D"); qglTexParameteri = (void *)getglcore("glTexParameteri"); qglTexParameterf = (void *)getglcore("glTexParameterf"); qglTexParameteriv = (void *)getglcore("glTexParameteriv"); diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index b1d696329..8e8b1b9a0 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -274,6 +274,7 @@ FTE_DEPRECATED void PPL_RevertToKnownState(void); qboolean R_CullBox (vec3_t mins, vec3_t maxs); qboolean R_CullEntityBox(entity_t *e, vec3_t modmins, vec3_t modmaxs); qboolean R_CullSphere (vec3_t origin, float radius); +void Sh_PreGenerateLights(void); #ifdef GLQUAKE void R_TranslatePlayerSkin (int playernum); @@ -716,6 +717,7 @@ extern void (APIENTRY *qglTexGeni) (GLenum coord, GLenum pname, GLint param); extern void (APIENTRY *qglTexGeniv) (GLenum coord, GLenum pname, const GLint *params); extern void (APIENTRY *qglTexImage1D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); extern void (APIENTRY *qglTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +extern void (APIENTRY *qglTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); extern void (APIENTRY *qglTexParameterf) (GLenum target, GLenum pname, GLfloat param); extern void (APIENTRY *qglTexParameterfv) (GLenum target, GLenum pname, const GLfloat *params); extern void (APIENTRY *qglTexParameteri) (GLenum target, GLenum pname, GLint param); diff --git a/engine/gl/shader.h b/engine/gl/shader.h index c91322e7a..cd98aee33 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -226,7 +226,8 @@ typedef struct shaderpass_s { T_GEN_SOURCECUBE, //used for render-to-texture targets T_GEN_VIDEOMAP, //use the media playback as an image source, updating each frame for which it is visible - T_GEN_SKYBOX, //use a skybox instead, otherwise T_GEN_SINGLEMAP + T_GEN_CUBEMAP, //use a cubemap instead, otherwise like T_GEN_SINGLEMAP + T_GEN_3DMAP, //use a 3d texture instead, otherwise T_GEN_SINGLEMAP. } texgen; enum { @@ -258,8 +259,9 @@ enum{ PERMUTATION_UPPER = 16, PERMUTATION_OFFSET = 32, PERMUTATION_SKELETAL = 64, + PERMUTATION_FOG = 128, - PERMUTATIONS = 128 + PERMUTATIONS = 256 }; typedef struct { @@ -291,6 +293,7 @@ typedef struct { SP_E_L_AMBIENT, SP_E_EYEPOS, /*viewer's eyepos, in model space*/ SP_V_EYEPOS, /*viewer's eyepos, in world space*/ + SP_W_FOG, SP_M_ENTBONES, SP_M_VIEW, @@ -393,6 +396,7 @@ struct shader_s SHADER_NODLIGHT = 1 << 15, //from surfaceflags SHADER_HASLIGHTMAP = 1 << 16, SHADER_HASTOPBOTTOM = 1 << 17, + SHADER_STATICDATA = 1 << 18 //set if true: no deforms, no tcgen, rgbgen=identitylighting, alphagen=identity, tmu0=st + tmu1=lm(if available) for every pass, no norms } flags; program_t *prog; @@ -502,6 +506,8 @@ void BE_PushOffsetShadow(qboolean foobar); void BE_SetupForShadowMap(void); //Called from shadowmapping code into backend void BE_BaseEntTextures(void); +//prebuilds shadow volumes +void Sh_PreGenerateLights(void); //Draws lights, called from the backend void Sh_DrawLights(qbyte *vis, batch_t **mbatches); void Sh_Shutdown(void); diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 55ca766a5..03231db5f 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -146,7 +146,8 @@ void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount) VirtualFree(addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p addressablehunk = NULL; } - addressablehunk = VirtualAlloc (addressablehunk, totalammount, MEM_RESERVE, PAGE_NOACCESS); + if (!addressablehunk) + addressablehunk = VirtualAlloc (addressablehunk, totalammount, MEM_RESERVE, PAGE_NOACCESS); #else if (addressablehunk) free(addressablehunk); diff --git a/engine/qclib/pr_multi.c b/engine/qclib/pr_multi.c index fb050d1c8..334536ec0 100644 --- a/engine/qclib/pr_multi.c +++ b/engine/qclib/pr_multi.c @@ -243,8 +243,15 @@ int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, s { if (field[i].type != type) { - printf("Field type mismatch on \"%s\". %i != %i\n", name, field[i].type, type); - continue; + /*Hexen2/DP compat hack: if the new type is a float and the original type is a vector, make the new def alias to the engine's _x field + this 'works around' the unused .vector color field used for rtlight colours vs the .float color used for particle colours (the float initialisers in map files will expand into the x slot safely). + qc/hc can work around this by just using .vector color/color_x instead, which is the same as this hack, but would resolve defs to allow rtlight colours. + */ + if (field[i].type != ev_vector || type != ev_float) + { + printf("Field type mismatch on \"%s\". %i != %i\n", name, field[i].type, type); + continue; + } } if (!progfuncs->fieldadjust && engineofs>=0) if ((unsigned)engineofs/4 != field[i].ofs) diff --git a/engine/qclib/qcc_cmdlib.c b/engine/qclib/qcc_cmdlib.c index fd39a5350..8c1fd8802 100644 --- a/engine/qclib/qcc_cmdlib.c +++ b/engine/qclib/qcc_cmdlib.c @@ -26,7 +26,7 @@ const unsigned int type_size[12] = {1, //void sizeof(func_t)/4,//function 1, //pointer (its an int index) 1, //integer - 1, //fixme: how big should a variant be? + 3, //fixme: how big should a variant be? 0, //ev_struct. variable sized. 0 //ev_union. variable sized. }; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 84350bbe7..3ffcf653b 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -3545,7 +3545,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could { if (!strncmp(func->name,"precache_file", 13)) { - if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string) + if (pr_token_type == tt_immediate && pr_immediate_type->type == ev_string && pr_scope && !strcmp(pr_scope->name, "main")) { optres_precache_file += strlen(pr_immediate_string); QCC_PR_Lex(); diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 410924239..68fc0d7a9 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -649,8 +649,8 @@ pbool QCC_WriteData (int crc) if (compressoutput) progs.blockscompressed |=64; //line numbers if (compressoutput) progs.blockscompressed |=128; //types //include a type block? - types = debugtarget;//!!QCC_PR_CheckCompConstDefined("TYPES"); //useful for debugging and saving (maybe, anyway...). - if (sizeof(char *) != sizeof(string_t)) + types = debugtarget; + if (types && sizeof(char *) != sizeof(string_t)) { //qcc_typeinfo_t has a char* inside it, which changes size printf("AMD64 builds cannot write typeinfo structures\n"); diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index aa43c38e6..b520e0989 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -654,24 +654,41 @@ void NPP_NQFlush(void) { if (cl->state == cs_spawned && ISQWCLIENT(cl)) { + char *h2finale = NULL; if (cl->zquake_extensions & Z_EXT_SERVERTIME) { ClientReliableCheckBlock(cl, 6); ClientReliableWrite_Byte(cl, svc_updatestatlong); ClientReliableWrite_Byte(cl, STAT_TIME); - ClientReliableWrite_Long(cl, (int)(sv.time * 1000)); - cl->nextservertimeupdate = sv.time+10; + ClientReliableWrite_Long(cl, (int)(sv.world.physicstime * 1000)); + cl->nextservertimeupdate = sv.world.physicstime+10; } - ClientReliableCheckBlock(cl, 16); - ClientReliableWrite_Byte(cl, svc_intermission); - ClientReliableWrite_Coord(cl, cl->edict->v->origin[0]); - ClientReliableWrite_Coord(cl, cl->edict->v->origin[1]); - ClientReliableWrite_Coord(cl, cl->edict->v->origin[2]+cl->edict->v->view_ofs[2]); - ClientReliableWrite_Angle(cl, cl->edict->v->angles[0]); - ClientReliableWrite_Angle(cl, cl->edict->v->angles[1]); - ClientReliableWrite_Angle(cl, cl->edict->v->angles[2]); + if (progstype == PROG_H2) + { + /*hexen2 does something like this in the client, but we don't support those protocols, so translate to something usable*/ + int lookup[13] = {394, 395, 356, 357, 358, 411, 386+6, 386+7, 386+8, 391, 538, 545, 561}; + if (buffer[1] < 13) + h2finale = T_GetString(lookup[buffer[1]]); + } + if (h2finale) + { + ClientReliableCheckBlock(cl, 16); + ClientReliableWrite_Byte(cl, svc_finale); + ClientReliableWrite_String(cl, h2finale); + } + else + { + ClientReliableCheckBlock(cl, 16); + ClientReliableWrite_Byte(cl, svc_intermission); + ClientReliableWrite_Coord(cl, cl->edict->v->origin[0]); + ClientReliableWrite_Coord(cl, cl->edict->v->origin[1]); + ClientReliableWrite_Coord(cl, cl->edict->v->origin[2]+cl->edict->v->view_ofs[2]); + ClientReliableWrite_Angle(cl, cl->edict->v->angles[0]); + ClientReliableWrite_Angle(cl, cl->edict->v->angles[1]); + ClientReliableWrite_Angle(cl, cl->edict->v->angles[2]); + } } } bufferlen = 0; @@ -1064,9 +1081,16 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) default: protocollen = sizeof(buffer); - te_515sevilhackworkaround = true; - Con_Printf("NQWriteByte: bad tempentity %i\n", data); - PR_StackTrace(svprogfuncs); + if (dest == MSG_MULTICAST) + { + Con_DPrintf("NQWriteByte: unknown tempentity %i\n", data); + } + else + { + te_515sevilhackworkaround = true; + Con_Printf("NQWriteByte: unknown tempentity %i\n", data); + PR_StackTrace(svprogfuncs); + } break; } break; @@ -1395,8 +1419,8 @@ void NPP_QWFlush(void) ClientReliableCheckBlock(cl, 6); ClientReliableWrite_Byte(cl, svc_updatestatlong); ClientReliableWrite_Byte(cl, STAT_TIME); - ClientReliableWrite_Long(cl, (int)(sv.time * 1000)); - cl->nextservertimeupdate = sv.time+10; + ClientReliableWrite_Long(cl, (int)(sv.world.physicstime * 1000)); + cl->nextservertimeupdate = sv.world.physicstime+10; } ClientReliableCheckBlock(cl, 1); diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 31ba97284..ec952928a 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -66,6 +66,7 @@ cvar_t pr_no_parsecommand = CVARF("pr_no_parsecommand", "0", 0); cvar_t pr_ssqc_progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER); cvar_t qc_nonetaccess = CVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc. +cvar_t qc_netpreparse = CVAR("qc_netpreparse", "1"); //server-side writebyte protocol translation cvar_t pr_overridebuiltins = CVAR("pr_overridebuiltins", "1"); @@ -77,6 +78,8 @@ cvar_t pr_droptofloorunits = CVAR("pr_droptofloorunits", ""); cvar_t sv_gameplayfix_honest_tracelines = CVAR("sv_gameplayfix_honest_tracelines", "1"); cvar_t sv_gameplayfix_blowupfallenzombies = CVAR("sv_gameplayfix_blowupfallenzombies", "0"); +cvar_t sv_gameplayfix_setmodelrealbox = CVAR("sv_gameplayfix_setmodelrealbox", "0"); +cvar_t sv_gameplayfix_setmodelsize_qw = CVAR("sv_gameplayfix_setmodelsize_qw", "0"); cvar_t sv_addon[MAXADDONS]; char cvargroup_progs[] = "Progs variables"; @@ -348,6 +351,9 @@ void PR_SV_FillWorldGlobals(world_t *w) w->g.frametime = pr_global_ptrs->frametime; w->g.newmis = pr_global_ptrs->newmis; w->g.time = pr_global_ptrs->time; + w->g.v_forward = *pr_global_ptrs->v_forward; + w->g.v_right = *pr_global_ptrs->v_right; + w->g.v_up = *pr_global_ptrs->v_up; } void PR_SSQC_Relocated(progfuncs_t *pr, char *oldb, char *newb, int oldlen) @@ -454,10 +460,19 @@ int QCEditor (progfuncs_t *prinst, char *filename, int line, int nump, char **pa model_t *SVPR_GetCModel(world_t *w, int modelindex) { if ((unsigned int)modelindex < MAX_MODELS) + { + if (!sv.models[modelindex] && sv.strings.model_precache[modelindex]) + sv.models[modelindex] = Mod_ForName(sv.strings.model_precache[modelindex], false); return sv.models[modelindex]; + } else return NULL; } +void SVPR_Get_FrameState(world_t *w, wedict_t *ent, framestate_t *fstate) +{ + memset(fstate, 0, sizeof(*fstate)); + fstate->g[FS_REG].frame[0] = ent->v->frame; +} void SVPR_Event_Touch(world_t *w, wedict_t *s, wedict_t *o) { @@ -524,6 +539,7 @@ void Q_SetProgsParms(qboolean forcompiler) if (pr_ssqc_memsize.ival == -2) svprogparms.addressablerelocated = PR_SSQC_Relocated; + svprogparms.user = &sv.world; if (!svprogfuncs) { sv.world.progs = svprogfuncs = InitProgs(&svprogparms); @@ -532,6 +548,7 @@ void Q_SetProgsParms(qboolean forcompiler) sv.world.Event_Think = SVPR_Event_Think; sv.world.Event_Sound = SVQ1_StartSound; sv.world.Get_CModel = SVPR_GetCModel; + sv.world.Get_FrameState = SVPR_Get_FrameState; PRSV_ClearThreads(); PR_fclose_progs(svprogfuncs); @@ -1181,6 +1198,8 @@ void PR_Init(void) Cvar_Register (&sv_gameplayfix_honest_tracelines, cvargroup_progs); Cvar_Register (&sv_gameplayfix_blowupfallenzombies, cvargroup_progs); + Cvar_Register (&sv_gameplayfix_setmodelrealbox, cvargroup_progs); + Cvar_Register (&sv_gameplayfix_setmodelsize_qw, cvargroup_progs); #ifdef SQL SQL_Init(); @@ -2192,7 +2211,7 @@ void PF_setmodel_Internal (progfuncs_t *prinst, edict_t *e, char *m) else #endif m = sv.strings.model_precache[i] = PR_AddString(prinst, m, 0); - if (!strcmp(m + strlen(m) - 4, ".bsp")) + if (!strcmp(m + strlen(m) - 4, ".bsp")) //always precache bsps sv.models[i] = Mod_FindName(m); Con_Printf("WARNING: SV_ModelIndex: model %s not precached\n", m); @@ -2235,7 +2254,7 @@ void PF_setmodel_Internal (progfuncs_t *prinst, edict_t *e, char *m) return; } - if (progstype == PROG_H2) + /*if (progstype == PROG_H2) { e->v->mins[0] = 0; e->v->mins[1] = 0; @@ -2247,15 +2266,18 @@ void PF_setmodel_Internal (progfuncs_t *prinst, edict_t *e, char *m) VectorSubtract (e->v->maxs, e->v->mins, e->v->size); } - else + else*/ { - if (progstype != PROG_QW) + if (sv_gameplayfix_setmodelrealbox.ival) + mod = SVPR_GetCModel(&sv.world, i); + else + mod = sv.models[i]; + + if (progstype != PROG_QW || sv_gameplayfix_setmodelsize_qw.ival) { //also sets size. //nq dedicated servers load bsps and mdls //qw dedicated servers only load bsps (better) - - mod = sv.models[i]; if (mod) { mod = Mod_ForName (m, false); @@ -2285,16 +2307,12 @@ void PF_setmodel_Internal (progfuncs_t *prinst, edict_t *e, char *m) } else { - if (sv.models[i]) + if (mod && mod->type != mod_alias) { - mod = Mod_ForName (m, false); - if (mod) - { - VectorCopy (mod->mins, e->v->mins); - VectorCopy (mod->maxs, e->v->maxs); - VectorSubtract (mod->maxs, mod->mins, e->v->size); - World_LinkEdict (&sv.world, (wedict_t*)e, false); - } + VectorCopy (mod->mins, e->v->mins); + VectorCopy (mod->maxs, e->v->maxs); + VectorSubtract (mod->maxs, mod->mins, e->v->size); + World_LinkEdict (&sv.world, (wedict_t*)e, false); } //qw was fixed - it never sets the size of an alias model, mostly because it doesn't know it. } @@ -2328,7 +2346,7 @@ static void QCBUILTIN PF_frameforname (progfuncs_t *prinst, struct globalvars_s { unsigned int modelindex = G_FLOAT(OFS_PARM0); char *str = PF_VarString(prinst, 1, pr_globals); - model_t *mod = (modelindex>= MAX_MODELS)?NULL:sv.models[modelindex]; + model_t *mod = SVPR_GetCModel(&sv.world, modelindex); if (mod && Mod_FrameForName) G_FLOAT(OFS_RETURN) = Mod_FrameForName(mod, str); @@ -2345,9 +2363,7 @@ static void QCBUILTIN PF_frameduration (progfuncs_t *prinst, struct globalvars_s G_FLOAT(OFS_RETURN) = 0; else { - mod = sv.models[modelindex]; - if (!mod) - mod = sv.models[modelindex] = Mod_ForName(sv.strings.model_precache[modelindex], false); + mod = SVPR_GetCModel(&sv.world, modelindex); if (mod && Mod_GetFrameDuration) G_FLOAT(OFS_RETURN) = Mod_GetFrameDuration(mod, framenum); @@ -2360,7 +2376,7 @@ static void QCBUILTIN PF_skinforname (progfuncs_t *prinst, struct globalvars_s * #ifndef SERVERONLY unsigned int modelindex = G_FLOAT(OFS_PARM0); char *str = PF_VarString(prinst, 1, pr_globals); - model_t *mod = (modelindex>= MAX_MODELS)?NULL:sv.models[modelindex]; + model_t *mod = SVPR_GetCModel(&sv.world, modelindex); if (mod && Mod_SkinForName) @@ -3523,7 +3539,12 @@ void PR_CheckEmptyString (char *s) */ static void QCBUILTIN PF_precache_file (progfuncs_t *prinst, struct globalvars_s *pr_globals) { // precache_file is only used to copy files with qcc, it does nothing + char *s = PR_GetStringOfs(prinst, OFS_PARM0); + G_INT(OFS_RETURN) = G_INT(OFS_PARM0); + + /*touch the file, so any packs will be referenced. this is fte behaviour.*/ + FS_FLocateFile(s, FSLFRT_IFFOUND, NULL); } void PF_precache_sound_Internal (progfuncs_t *prinst, char *s) @@ -3542,6 +3563,8 @@ void PF_precache_sound_Internal (progfuncs_t *prinst, char *s) { strcpy(sv.strings.sound_precache[i], s); + /*touch the file, so any packs will be referenced*/ + FS_FLocateFile(s, FSLFRT_IFFOUND, NULL); if (sv.state != ss_loading) { @@ -3601,8 +3624,13 @@ int PF_precache_model_Internal (progfuncs_t *prinst, char *s, qboolean queryonly #endif sv.strings.model_precache[i] = PR_AddString(prinst, s, 0); s = sv.strings.model_precache[i]; - if (!strcmp(s + strlen(s) - 4, ".bsp")) + if (!strcmp(s + strlen(s) - 4, ".bsp") || sv_gameplayfix_setmodelrealbox.ival) sv.models[i] = Mod_FindName(s); + else + { + /*touch the file, so any packs will be referenced*/ + FS_FLocateFile(s, FSLFRT_IFFOUND, NULL); + } if (sv.state != ss_loading) { @@ -3775,12 +3803,6 @@ static void QCBUILTIN PF_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_ pr_global_struct->self = oldself; } -void PF_sv_touchtriggers(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - wedict_t *ent = (wedict_t*)PROG_TO_EDICT(prinst, pr_global_struct->self); - World_LinkEdict (&sv.world, ent, true); -} - /* =============== PF_droptofloor @@ -4309,7 +4331,8 @@ client_t *Write_GetClient(void) extern sizebuf_t csqcmsgbuffer; void QCBUILTIN PF_WriteByte (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + int dest = G_FLOAT(OFS_PARM0); + if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteByte(&csqcmsgbuffer, G_FLOAT(OFS_PARM1)); return; @@ -4325,17 +4348,18 @@ void QCBUILTIN PF_WriteByte (progfuncs_t *prinst, struct globalvars_s *pr_global if (progstype == PROG_NQ || progstype == PROG_H2) { - NPP_NQWriteByte(G_FLOAT(OFS_PARM0), (qbyte)G_FLOAT(OFS_PARM1)); + NPP_NQWriteByte(dest, (qbyte)G_FLOAT(OFS_PARM1)); return; } #ifdef NQPROT else { - NPP_QWWriteByte(G_FLOAT(OFS_PARM0), (qbyte)G_FLOAT(OFS_PARM1)); + NPP_QWWriteByte(dest, (qbyte)G_FLOAT(OFS_PARM1)); return; } -#else - else if (G_FLOAT(OFS_PARM0) == MSG_ONE) +#endif + + if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); if (!cl) @@ -4345,7 +4369,6 @@ void QCBUILTIN PF_WriteByte (progfuncs_t *prinst, struct globalvars_s *pr_global } else MSG_WriteByte (QWWriteDest(G_FLOAT(OFS_PARM0)), G_FLOAT(OFS_PARM1)); -#endif } void QCBUILTIN PF_WriteChar (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -6477,12 +6500,13 @@ static void QCBUILTIN PF_h2matchAngleToSlope(progfuncs_t *prinst, struct globalv vec3_t v_forward, old_forward, old_right, new_angles2 = { 0, 0, 0 }; float pitch, mod, dot; + // OFS_PARM0 is used by PF_vectoangles below actor = G_EDICT(prinst, OFS_PARM1); AngleVectors(actor->v->angles, old_forward, old_right, P_VEC(v_up)); - PF_vectoangles(prinst, pr_globals); + VectorAngles(G_VECTOR(OFS_PARM0), NULL, G_VECTOR(OFS_RETURN)); pitch = G_FLOAT(OFS_RETURN) - 90; @@ -8095,9 +8119,7 @@ static void QCBUILTIN PF_ChangePic(progfuncs_t *prinst, struct globalvars_s *pr_ int SV_TagForName(int modelindex, char *tagname) { - model_t *model = sv.models[modelindex]; - if (!model) - model = Mod_ForName(sv.strings.model_precache[modelindex], false); + model_t *model = SVPR_GetCModel(&sv.world, modelindex); if (!model) return 0; @@ -8110,7 +8132,7 @@ static void QCBUILTIN PF_setattachment(progfuncs_t *prinst, struct globalvars_s edict_t *tagentity = G_EDICT(prinst, OFS_PARM1); char *tagname = PR_GetStringOfs(prinst, OFS_PARM2); - int modelindex; + model_t *model; int tagidx; @@ -8118,115 +8140,21 @@ static void QCBUILTIN PF_setattachment(progfuncs_t *prinst, struct globalvars_s if (tagentity != (edict_t*)sv.world.edicts && tagname && tagname[0]) { - modelindex = (int)tagentity->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS) + model = SVPR_GetCModel(&sv.world, tagentity->v->modelindex); + if (model) { - if (!sv.models[modelindex]) - sv.models[modelindex] = Mod_ForName(sv.strings.model_precache[modelindex], false); - if (sv.models[modelindex]) - { - tagidx = SV_TagForName(modelindex, tagname); - if (tagidx == 0) - Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity), sv.models[modelindex]->name); - } - else - Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): Couldn't load model %s\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, sv.strings.model_precache[modelindex]); + tagidx = Mod_TagNumForName(model, tagname); + if (tagidx == 0) + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity), model->name); } else - Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity)); - + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): Couldn't load model\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname); } e->xv->tag_entity = EDICT_TO_PROG(prinst,tagentity); e->xv->tag_index = tagidx; } -// #451 float(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO) -static void QCBUILTIN PF_gettagindex(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - edict_t *e = G_EDICT(prinst, OFS_PARM0); - char *tagname = PR_GetStringOfs(prinst, OFS_PARM1); - - int modelindex; - - int tagidx; - - tagidx = 0; - - if (tagname && tagname[0]) - { - modelindex = (int)e->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS && sv.strings.model_precache[modelindex]) - { - tagidx = SV_TagForName(modelindex, tagname); - if (tagidx == 0) - Con_DPrintf("PF_gettagindex(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, e), tagname, tagname, NUM_FOR_EDICT(prinst, e), sv.models[modelindex]->name); - } - else - Con_DPrintf("PF_gettagindex(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, e), tagname, tagname, NUM_FOR_EDICT(prinst, e)); - - } - - G_FLOAT(OFS_RETURN) = tagidx; -} - -static void EdictToTransform(edict_t *ed, float *trans) -{ - AngleVectors(ed->v->angles, trans+0, trans+4, trans+8); - VectorInverse(trans+4); - - trans[3] = ed->v->origin[0]; - trans[7] = ed->v->origin[1]; - trans[11] = ed->v->origin[2]; -} - -// #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO) -static void QCBUILTIN PF_sv_gettaginfo(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - framestate_t fstate; - float transtag[12]; - float transent[12]; - float result[12]; - edict_t *ent = G_EDICT(prinst, OFS_PARM0); - int tagnum = G_FLOAT(OFS_PARM1); - model_t *model = sv.models[(int)ent->v->modelindex]; - - float *origin = G_VECTOR(OFS_RETURN); - float *axis[3]; - axis[0] = P_VEC(v_forward); - axis[1] = P_VEC(v_up); - axis[2] = P_VEC(v_right); - - if (!model) - model = Mod_FindName(sv.strings.model_precache[(int)ent->v->modelindex]); - - memset(&fstate, 0, sizeof(fstate)); - fstate.g[FS_REG].frame[0] = fstate.g[FS_REG].frame[0] = ent->v->frame; - - if (!Mod_GetTag(model, tagnum, &fstate, transtag)) - { - return; - } - - if (ent->xv->tag_entity) - { -#ifdef warningmsg - #pragma warningmsg("PF_sv_gettaginfo: This function doesn't honour attachments") -#endif - Con_Printf("PF_sv_gettaginfo doesn't support attachments\n"); - } - - EdictToTransform(ent, transent); - R_ConcatTransforms((void*)transent, (void*)transtag, (void*)result); - - origin[0] = result[3]; - origin[1] = result[7]; - origin[2] = result[11]; - VectorCopy((result+0), axis[0]); - VectorCopy((result+4), axis[1]); - VectorCopy((result+8), axis[2]); -} - //the first implementation of this function was (float type, float num, string name) //it is now float num, float type, .field //EXT_CSQC_1 @@ -8474,219 +8402,6 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) return false; } -//DP_QC_GETSURFACE -// #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) -static void QCBUILTIN PF_getsurfacenumpoints(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - unsigned int surfnum; - model_t *model; - int modelindex; - edict_t *ent; - - ent = G_EDICT(prinst, OFS_PARM0); - surfnum = G_FLOAT(OFS_PARM1); - - modelindex = ent->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS) - model = sv.models[(int)ent->v->modelindex]; - else - model = NULL; - - if (!model || model->type != mod_brush || surfnum >= model->nummodelsurfaces) - G_FLOAT(OFS_RETURN) = 0; - else - { - surfnum += model->firstmodelsurface; - G_FLOAT(OFS_RETURN) = model->surfaces[surfnum].mesh->numvertexes; - } -} -// #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) -static void QCBUILTIN PF_getsurfacepoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - unsigned int surfnum, pointnum; - model_t *model; - int modelindex; - edict_t *ent; - - ent = G_EDICT(prinst, OFS_PARM0); - surfnum = G_FLOAT(OFS_PARM1); - pointnum = G_FLOAT(OFS_PARM2); - - modelindex = ent->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS) - model = sv.models[(int)ent->v->modelindex]; - else - model = NULL; - - if (!model || model->type != mod_brush || surfnum >= model->nummodelsurfaces) - { - G_FLOAT(OFS_RETURN+0) = 0; - G_FLOAT(OFS_RETURN+1) = 0; - G_FLOAT(OFS_RETURN+2) = 0; - } - else - { - surfnum += model->firstmodelsurface; - - G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].mesh->xyz_array[pointnum][0]; - G_FLOAT(OFS_RETURN+1) = model->surfaces[surfnum].mesh->xyz_array[pointnum][1]; - G_FLOAT(OFS_RETURN+2) = model->surfaces[surfnum].mesh->xyz_array[pointnum][2]; - } -} -// #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) -static void QCBUILTIN PF_getsurfacenormal(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - unsigned int surfnum, pointnum; - model_t *model; - int modelindex; - edict_t *ent; - - ent = G_EDICT(prinst, OFS_PARM0); - surfnum = G_FLOAT(OFS_PARM1); - pointnum = G_FLOAT(OFS_PARM2); - - modelindex = ent->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS) - model = sv.models[(int)ent->v->modelindex]; - else - model = NULL; - - if (!model || model->type != mod_brush || surfnum >= model->nummodelsurfaces) - { - G_FLOAT(OFS_RETURN+0) = 0; - G_FLOAT(OFS_RETURN+1) = 0; - G_FLOAT(OFS_RETURN+2) = 0; - } - else - { - surfnum += model->firstmodelsurface; - - G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].plane->normal[0]; - G_FLOAT(OFS_RETURN+1) = model->surfaces[surfnum].plane->normal[1]; - G_FLOAT(OFS_RETURN+2) = model->surfaces[surfnum].plane->normal[2]; - if (model->surfaces[surfnum].flags & SURF_PLANEBACK) - VectorInverse(G_VECTOR(OFS_RETURN)); - } -} -// #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) -void PF_getsurfacetexture(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - model_t *model; - edict_t *ent; - msurface_t *surf; - int modelindex; - int surfnum; - - ent = G_EDICT(prinst, OFS_PARM0); - surfnum = G_FLOAT(OFS_PARM1); - - modelindex = ent->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS) - model = sv.models[(int)ent->v->modelindex]; - else - model = NULL; - - G_INT(OFS_RETURN) = 0; - if (!model || model->type != mod_brush) - return; - - if (surfnum < 0 || surfnum > model->nummodelsurfaces) - return; - surfnum += model->firstmodelsurface; - surf = &model->surfaces[surfnum]; - G_INT(OFS_RETURN) = PR_TempString(prinst, surf->texinfo->texture->name); -} -// #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) -static void QCBUILTIN PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - model_t *model; - edict_t *ent; - msurface_t *surf; - int i; - float planedist; - float *point; - int modelindex; - - vec3_t edgedir; - vec3_t edgenormal; - vec3_t cpoint, temp; - mvertex_t *v1, *v2; - int edge; - int e; - float bestdist = 10000000000000, dist; - int bestsurf = -1; - - ent = G_EDICT(prinst, OFS_PARM0); - point = G_VECTOR(OFS_PARM1); - - G_FLOAT(OFS_RETURN) = -1; - - modelindex = ent->v->modelindex; - if (modelindex > 0 && modelindex < MAX_MODELS) - model = sv.models[(int)ent->v->modelindex]; - else - model = NULL; - - if (!model || model->type != mod_brush) - return; - - if (model->fromgame != fg_quake) - return; - - - surf = model->surfaces + model->firstmodelsurface; - for (i = 0; i < model->nummodelsurfaces; i++, surf++) - { - planedist = DotProduct(point, surf->plane->normal) - surf->plane->dist; - //don't care about SURF_PLANEBACK, the maths works out the same. - - if (planedist*planedist < bestdist) - { //within a specific range - //make sure it's within the poly - VectorMA(point, planedist, surf->plane->normal, cpoint); - for (e = surf->firstedge+surf->numedges; e > surf->firstedge; edge++) - { - edge = model->surfedges[--e]; - if (edge < 0) - { - v1 = &model->vertexes[model->edges[-edge].v[0]]; - v2 = &model->vertexes[model->edges[-edge].v[1]]; - } - else - { - v2 = &model->vertexes[model->edges[edge].v[0]]; - v1 = &model->vertexes[model->edges[edge].v[1]]; - } - - VectorSubtract(v1->position, v2->position, edgedir); - CrossProduct(edgedir, surf->plane->normal, edgenormal); - if (!(surf->flags & SURF_PLANEBACK)) - { - VectorNegate(edgenormal, edgenormal); - } - VectorNormalize(edgenormal); - - dist = DotProduct(v1->position, edgenormal) - DotProduct(cpoint, edgenormal); - if (dist < 0) - VectorMA(cpoint, dist, edgenormal, cpoint); - } - - VectorSubtract(cpoint, point, temp); - dist = DotProduct(temp, temp); - if (dist < bestdist) - { - bestsurf = i; - bestdist = dist; - } - } - } - G_FLOAT(OFS_RETURN) = bestsurf; -} -// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) -static void QCBUILTIN PF_getsurfaceclippedpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ -} - qbyte qcpvs[(MAX_MAP_LEAFS+7)/8]; //#240 float(vector viewpos, entity viewee) checkpvs (FTE_QC_CHECKPVS) //note: this requires a correctly setorigined entity. @@ -8746,24 +8461,13 @@ static void QCBUILTIN PF_SendPacket(progfuncs_t *prinst, struct globalvars_s *pr NET_SendPacket(NS_SERVER, strlen(contents), contents, to); } -static void QCBUILTIN PF_sv_terrain_edit(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int action = G_FLOAT(OFS_PARM0); - float *pos = G_VECTOR(OFS_PARM1); - float radius = G_FLOAT(OFS_PARM2); - float quant = G_FLOAT(OFS_PARM3); -#if defined(TERRAIN) - G_FLOAT(OFS_RETURN) = Heightmap_Edit(sv.world.worldmodel, action, pos, radius, quant); -#else - G_FLOAT(OFS_RETURN) = false; -#endif -} + #define STUB ,true #ifdef DEBUG -#define NYI ,true -#else #define NYI ,false +#else +#define NYI ,true #endif BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"fixme", PF_Fixme, 0, 0, 0, 0, "void()"}, @@ -8825,7 +8529,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"changeyaw", PF_changeyaw, 49, 49, 49, 0, "#define ChangeYaw changeyaw\nvoid()"}, // {"qtest_precacheitem", NULL, 50}, // defined QTest builtin that is never called {"vhlen", PF_vhlen, 0, 0, 50, 0, "float(vector)"}, - {"vectoangles", PF_vectoangles, 51, 51, 51, 0, "vector(vector fwd)"}, + {"vectoangles", PF_vectoangles, 51, 51, 51, 0, "vector(vector fwd, optional vector up)"}, {"WriteByte", PF_WriteByte, 52, 52, 52, 0, "void(float to, float val)"}, //52 {"WriteChar", PF_WriteChar, 53, 53, 53, 0, "void(float to, float val)"}, //53 @@ -8915,7 +8619,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"infokey", PF_infokey, 0, 80, 0, 80, "string(entity e, string key)"}, //80 {"stof", PF_stof, 0, 81, 0, 81, "float(string)"}, //81 - {"multicast", PF_multicast, 0, 82, 0, 0, "void(vector where, float set)"}, //82 + {"multicast", PF_multicast, 0, 82, 0, 82, "void(vector where, float set)"}, //82 @@ -9078,7 +8782,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"rotatevectorsbyangle", PF_Fixme, 0, 0, 0, 235, "void(vector angle)"}, // #235 {"rotatevectorsbyvectors", PF_Fixme, 0, 0, 0, 236, "void(vector fwd, vector right, vector up)"}, // #236 {"skinforname", PF_skinforname, 0, 0, 0, 237, "float(float mdlindex, string skinname)"}, // #237 - {"shaderforname", PF_Fixme, 0, 0, 0, 238, "float(string shadername, optional string defaultshader)"}, + {"shaderforname", PF_Fixme, 0, 0, 0, 238, "float(string shadername, optional string defaultshader, ...)"}, {"te_bloodqw", PF_te_bloodqw, 0, 0, 0, 239, "void(vector org, optional float count)"}, {"checkpvs", PF_checkpvs, 0, 0, 0, 240, "float(vector viewpos, entity entity)"}, @@ -9121,11 +8825,14 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"frameforname", PF_frameforname, 0, 0, 0, 276, "void(float modidx, string framename)"},// (FTE_CSQC_SKELETONOBJECTS) {"frameduration", PF_frameduration, 0, 0, 0, 277, "float(float modidx, float framenum)"},// (FTE_CSQC_SKELETONOBJECTS) - {"terrain_edit", PF_sv_terrain_edit, 0, 0, 0, 278, "void(float action, vector pos, float radius, float quant)"},// (??FTE_TERRAIN_EDIT?? - {"touchtriggers", PF_sv_touchtriggers,0, 0, 0, 279, "void()"},// + {"terrain_edit", PF_terrain_edit, 0, 0, 0, 278, "void(float action, vector pos, float radius, float quant)"},// (??FTE_TERRAIN_EDIT?? + {"touchtriggers", PF_touchtriggers, 0, 0, 0, 279, "void()"},// {"writefloat", PF_WriteFloat, 0, 0, 0, 280, "void(float buf, float fl)"},// {"skel_ragupdate", PF_skel_ragedit, 0, 0, 0, 281, "float(float skel, string dollname, float parentskel, vector trans, vector fwd, vector rt, vector up)" NYI}, // (FTE_CSQC_RAGDOLL) {"skel_mmap", PF_skel_mmap, 0, 0, 0, 282, "float*(float skel)"},// (FTE_QC_RAGDOLL) + {"skel_set_bone_world",PF_skel_set_bone_world,0,0, 0, 283, "void(entity ent, float bonenum, vector org, optional vector angorfwd, optional vector right, optional vector up)"}, + +// {"cvar_setlatch", PF_cvar_setlatch, 0, 0, 0, 284, "void(string cvarname, optional string value)"}, //72 {"clearscene", PF_Fixme, 0, 0, 0, 300, "void()"},// (EXT_CSQC) @@ -9181,12 +8888,12 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"cprint", PF_Fixme, 0, 0, 0, 338, "void(string s, ...)"},//(EXT_CSQC) {"print", PF_print, 0, 0, 0, 339, "void(string s, ...)"},//(EXT_CSQC) - + {"keynumtostring", PF_Fixme, 0, 0, 0, 340, "string(float keynum)"},// (EXT_CSQC) {"stringtokeynum", PF_Fixme, 0, 0, 0, 341, "float(string keyname)"},// (EXT_CSQC) {"getkeybind", PF_Fixme, 0, 0, 0, 342, "string(float keynum)"},// (EXT_CSQC) - {"getmousepos", PF_Fixme, 0, 0, 0, 344, "", true}, // #344 This is a DP extension + {"getmousepos", PF_Fixme, 0, 0, 0, 344, "vector()"}, // #344 This is a DP extension {"getinputstate", PF_Fixme, 0, 0, 0, 345, "float(float framenum)"},// (EXT_CSQC) {"setsensitivityscaler",PF_Fixme,0, 0, 0, 346, "void(float sens)"},// (EXT_CSQC) @@ -9286,7 +8993,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"getsurfacenormal",PF_getsurfacenormal,0, 0, 0, 436, "vector(entity e, float s)"},// (DP_QC_GETSURFACE) {"getsurfacetexture",PF_getsurfacetexture,0, 0, 0, 437, "string(entity e, float s)"},// (DP_QC_GETSURFACE) {"getsurfacenearpoint",PF_getsurfacenearpoint,0,0, 0, 438, "float(entity e, vector p)"},// (DP_QC_GETSURFACE) - {"getsurfaceclippedpoint",PF_getsurfaceclippedpoint,0,0,0, 439, "vector(entity e, float s, vector p)"},// (DP_QC_GETSURFACE) + {"getsurfaceclippedpoint",PF_getsurfaceclippedpoint,0,0,0, 439, "vector(entity e, float s, vector p)" STUB},// (DP_QC_GETSURFACE) //KRIMZON_SV_PARSECLIENTCOMMAND {"clientcommand", PF_clientcommand, 0, 0, 0, 440, "void(entity e, string s)"},// (KRIMZON_SV_PARSECLIENTCOMMAND) @@ -9309,7 +9016,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"findchainflags", PF_sv_findchainflags,0, 0, 0, 450, "entity(.float fld, float match)"},// //DP_MD3_TAGSINFO {"gettagindex", PF_gettagindex, 0, 0, 0, 451, "float(entity ent, string tagname)"},// (DP_MD3_TAGSINFO) - {"gettaginfo", PF_sv_gettaginfo, 0, 0, 0, 452, "vector(entity ent, float tagindex)"},// (DP_MD3_TAGSINFO) + {"gettaginfo", PF_gettaginfo, 0, 0, 0, 452, "vector(entity ent, float tagindex)"},// (DP_MD3_TAGSINFO) //DP_SV_BOTCLIENT {"dropclient", PF_dropclient, 0, 0, 0, 453, "void(entity player)"},//DP_SV_BOTCLIENT @@ -9423,12 +9130,39 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"buf_cvarlist", PF_buf_cvarlist, 0, 0, 0, 517, "void(float strbuf)" STUB}, {"cvar_description",PF_cvar_description,0, 0, 0, 518, "string(string cvarname)"}, {"gettime", PF_Fixme, 0, 0, 0, 519, "float(optional float timetype)"}, -//end dp extras +// {"loadfromdata", VM_loadfromdata, 0, 0, 0, 529, "??" STUB}, +// {"loadfromfile", VM_loadfromfile, 0, 0, 0, 530, "??" STUB}, +// {"setpause", VM_SV_setpause, 0, 0, 0, 531, "void(float pause)" STUB}, + + //end dp extras {"precache_vwep_model",PF_precache_vwep_model,0,0, 0, 532, "float(string mname)"}, + //restart dp extras +// {"log", VM_Fixme, 0, 0, 0, 532, "float(string mname)", true}, +// {"getsoundtime", VM_getsoundtime, 0, 0, 0, 533, "float(entity e, float channel)" STUB}, +// {"soundlength", VM_soundlength, 0, 0, 0, 534, "float(string sample)" STUB}, + + + {"physics_enable", PF_Ignore, 0, 0, 0, 540, "void(entity e, float physics_enabled)" STUB}, + {"physics_addforce",PF_Ignore, 0, 0, 0, 541, "void(entity e, vector force, vector relative_ofs)" STUB}, + {"physics_addtorque",PF_Ignore, 0, 0, 0, 542, "void(entity e, vector torque)" STUB}, + +//VM_callfunction, // #605 +//VM_writetofile, // #606 +//VM_isfunction, // #607 +//VM_parseentitydata, // #613 +//VM_SV_getextresponse, // #624 string getextresponse(void) {"sprintf", PF_sprintf, 0, 0, 0, 627, "string(...)" STUB}, +// {"getsurfacenumpoints",VM_getsurfacenumtriangles,0,0, 0, 628, "float(entity e, float s)" STUB}, +// {"getsurfacepoint",VM_getsurfacenumtriangles,0,0, 0, 629, "vector(entity e, float s, float n)" STUB}, +//VM_digest_hex, // #639 + + + //end dp extras + + {"getrmqeffectsversion", PF_Ignore, 0, 0, 0, 666, "float()" STUB}, //don't exceed sizeof(pr_builtin)/sizeof(pr_builtin[0]) (currently 1024) without modifing the size of pr_builtin {NULL} @@ -9702,7 +9436,7 @@ void PR_RegisterFields(void) //it's just easier to do it this way. #define comfieldfloat(name) PR_RegisterFieldVar(svprogfuncs, ev_float, #name, (size_t)&((stdentvars_t*)0)->name, -1); #define comfieldvector(name) PR_RegisterFieldVar(svprogfuncs, ev_vector, #name, (size_t)&((stdentvars_t*)0)->name, -1); #define comfieldentity(name) PR_RegisterFieldVar(svprogfuncs, ev_entity, #name, (size_t)&((stdentvars_t*)0)->name, -1); -#define comfieldstring(name) PR_RegisterFieldVar(svprogfuncs, ev_string, #name, (size_t)&((stdentvars_t*)0)->name, -1); +#define comfieldstring(name) PR_RegisterFieldVar(svprogfuncs, ev_string, (((size_t)&((stdentvars_t*)0)->name==(size_t)&((stdentvars_t*)0)->message)?"_"#name:#name), (size_t)&((stdentvars_t*)0)->name, -1); #define comfieldfunction(name, typestr) PR_RegisterFieldVar(svprogfuncs, ev_function, #name, (size_t)&((stdentvars_t*)0)->name, -1); comqcfields #undef comfieldfloat @@ -9767,6 +9501,7 @@ void PR_DumpPlatform_f(void) int d = 0, nd; vfsfile_t *f; char *fname = ""; + char dbgfname[MAX_OSPATH]; unsigned int targ = 0; qboolean defines = false; @@ -9941,6 +9676,41 @@ void PR_DumpPlatform_f(void) {"TRUE", "const float", QW|NQ|CS, 1}, {"FALSE", "const float", QW|NQ|CS, 0}, + {"MOVETYPE_NONE", "const float", QW|NQ|CS, MOVETYPE_NONE}, + {"MOVETYPE_WALK", "const float", QW|NQ|CS, MOVETYPE_WALK}, + {"MOVETYPE_STEP", "const float", QW|NQ|CS, MOVETYPE_STEP}, + {"MOVETYPE_FLY", "const float", QW|NQ|CS, MOVETYPE_FLY}, + {"MOVETYPE_TOSS", "const float", QW|NQ|CS, MOVETYPE_TOSS}, + {"MOVETYPE_PUSH", "const float", QW|NQ|CS, MOVETYPE_PUSH}, + {"MOVETYPE_NOCLIP", "const float", QW|NQ|CS, MOVETYPE_NOCLIP}, + {"MOVETYPE_FLYMISSILE", "const float", QW|NQ|CS, MOVETYPE_FLYMISSILE}, + {"MOVETYPE_BOUNCE", "const float", QW|NQ|CS, MOVETYPE_BOUNCE}, + {"MOVETYPE_BOUNCEMISSILE", "const float", QW|NQ|CS, MOVETYPE_BOUNCEMISSILE}, + {"MOVETYPE_FOLLOW", "const float", QW|NQ|CS, MOVETYPE_FOLLOW}, + {"MOVETYPE_PHYSICS", "const float", QW|NQ|CS, MOVETYPE_PHYSICS}, + + {"SOLID_NOT", "const float", QW|NQ|CS, SOLID_NOT}, + {"SOLID_TRIGGER", "const float", QW|NQ|CS, SOLID_TRIGGER}, + {"SOLID_BBOX", "const float", QW|NQ|CS, SOLID_BBOX}, + {"SOLID_SLIDEBOX", "const float", QW|NQ|CS, SOLID_SLIDEBOX}, + {"SOLID_BSP", "const float", QW|NQ|CS, SOLID_BSP}, + {"SOLID_CORPSE", "const float", QW|NQ|CS, SOLID_CORPSE}, + {"SOLID_LADDER", "const float", QW|NQ|CS, SOLID_LADDER}, + {"SOLID_PHYSICS_BOX", "const float", QW|NQ|CS, SOLID_PHYSICS_BOX}, + {"SOLID_PHYSICS_SPHERE", "const float", QW|NQ|CS, SOLID_PHYSICS_SPHERE}, + {"SOLID_PHYSICS_CAPSULE", "const float", QW|NQ|CS, SOLID_PHYSICS_CAPSULE}, + + {"JOINTTYPE_FIXED", "const float", QW|NQ|CS, JOINTTYPE_FIXED}, + {"JOINTTYPE_POINT", "const float", QW|NQ|CS, JOINTTYPE_POINT}, + {"JOINTTYPE_HINGE", "const float", QW|NQ|CS, JOINTTYPE_HINGE}, + {"JOINTTYPE_SLIDER", "const float", QW|NQ|CS, JOINTTYPE_SLIDER}, + {"JOINTTYPE_UNIVERSAL", "const float", QW|NQ|CS, JOINTTYPE_UNIVERSAL}, + {"JOINTTYPE_HINGE2", "const float", QW|NQ|CS, JOINTTYPE_HINGE2}, + + {"DAMAGE_NO", "const float", QW|NQ, DAMAGE_NO}, + {"DAMAGE_YES", "const float", QW|NQ, DAMAGE_YES}, + {"DAMAGE_AIM", "const float", QW|NQ, DAMAGE_AIM}, + {"CONTENT_EMPTY", "const float", QW|NQ|CS, Q1CONTENTS_EMPTY}, {"CONTENT_SOLID", "const float", QW|NQ|CS, Q1CONTENTS_SOLID}, {"CONTENT_WATER", "const float", QW|NQ|CS, Q1CONTENTS_WATER}, @@ -9959,6 +9729,51 @@ void PR_DumpPlatform_f(void) // {"ATTN_IDLE", "const float", QW|NQ|CS, ATTN_IDLE}, // {"ATTN_STATIC", "const float", QW|NQ|CS, ATTN_STATIC}, + {"MSG_BROADCAST", "const float", QW|NQ, MSG_BROADCAST}, + {"MSG_ONE", "const float", QW|NQ, MSG_ONE}, + {"MSG_ALL", "const float", QW|NQ, MSG_ALL}, + {"MSG_INIT", "const float", QW|NQ, MSG_INIT}, + {"MSG_MULTICAST", "const float", QW|NQ, MSG_MULTICAST}, + {"MSG_ENTITY", "const float", QW|NQ, MSG_CSQC}, + + {"MULTICAST_ALL", "const float", QW|NQ, MULTICAST_ALL}, + {"MULTICAST_PHS", "const float", QW|NQ, MULTICAST_PHS}, + {"MULTICAST_PVS", "const float", QW|NQ, MULTICAST_PVS}, + {"MULTICAST_ONE", "const float", QW|NQ, MULTICAST_ONE}, + {"MULTICAST_ALL_R", "const float", QW|NQ, MULTICAST_ALL_R}, + {"MULTICAST_PHS_R", "const float", QW|NQ, MULTICAST_PHS_R}, + {"MULTICAST_PVS_R", "const float", QW|NQ, MULTICAST_PVS_R}, + {"MULTICAST_ONE_R", "const float", QW|NQ, MULTICAST_ONE_R}, + + {"PRINT_LOW", "const float", QW, PRINT_LOW}, + {"PRINT_MEDIUM", "const float", QW, PRINT_MEDIUM}, + {"PRINT_HIGH", "const float", QW, PRINT_HIGH}, + {"PRINT_CHAT", "const float", QW, PRINT_CHAT}, + + // edict.flags + {"FL_FLY", "const float", QW|NQ|CS, FL_FLY}, + {"FL_SWIM", "const float", QW|NQ|CS, FL_SWIM}, + {"FL_CLIENT", "const float", QW|NQ|CS, FL_CLIENT}, + {"FL_INWATER", "const float", QW|NQ|CS, FL_INWATER}, + {"FL_MONSTER", "const float", QW|NQ|CS, FL_MONSTER}, + {"FL_GODMODE", "const float", QW|NQ, FL_GODMODE}, + {"FL_NOTARGET", "const float", QW|NQ, FL_NOTARGET}, + {"FL_ITEM", "const float", QW|NQ|CS, FL_ITEM}, + {"FL_ONGROUND", "const float", QW|NQ|CS, FL_ONGROUND}, + {"FL_PARTIALGROUND", "const float", QW|NQ|CS, FL_PARTIALGROUND}, + {"FL_WATERJUMP", "const float", QW|NQ|CS, FL_WATERJUMP}, +// {"FL_MOVECHAIN_ANGLE", "const float", QW|NQ, FL_MOVECHAIN_ANGLE}, + {"FL_LAGGEDMOVE", "const float", QW|NQ, FL_LAGGEDMOVE}, +// {"FL_CLASS_DEPENDENT", "const float", QW|NQ, FL_CLASS_DEPENDENT}, + + {"MOVE_NORMAL", "const float", QW|NQ|CS, MOVE_NORMAL}, + {"MOVE_NOMONSTERS", "const float", QW|NQ|CS, MOVE_NOMONSTERS}, + {"MOVE_MISSILE", "const float", QW|NQ|CS, MOVE_MISSILE}, + {"MOVE_HITMODEL", "const float", QW|NQ|CS, MOVE_HITMODEL}, + {"MOVE_TRIGGERS", "const float", QW|NQ|CS, MOVE_TRIGGERS}, + {"MOVE_EVERYTHING", "const float", QW|NQ|CS, MOVE_EVERYTHING}, + {"MOVE_LAGGED", "const float", QW|NQ, MOVE_LAGGED}, + {"MOVE_ENTCHAIN", "const float", QW|NQ|CS, MOVE_ENTCHAIN}, {"EF_BRIGHTFIELD", "const float", QW|NQ|CS, EF_BRIGHTFIELD}, {"EF_MUZZLEFLASH", "const float", NQ|CS, EF_MUZZLEFLASH}, @@ -10080,7 +9895,15 @@ void PR_DumpPlatform_f(void) if (!*fname) fname = "fteextensions"; - f = FS_OpenVFS(va("src/%s.qc", fname), "wb", FS_GAMEONLY); + fname = va("src/%s.qc", fname); + FS_NativePath(fname, FS_GAMEONLY, dbgfname, sizeof(dbgfname)); + FS_CreatePath(fname, FS_GAMEONLY); + f = FS_OpenVFS(fname, "wb", FS_GAMEONLY); + if (!f) + { + Con_Printf("Unable to create \"%s\"\n", dbgfname); + return; + } VFS_PRINTF(f, "/*\n" "This file was automatically generated by %s v%i.%02i\n" @@ -10203,7 +10026,11 @@ void PR_DumpPlatform_f(void) else { if (BuiltinList[i].bifunc == PF_Fixme || BuiltinList[i].bifunc == PF_Ignore) - continue; /*neither*/ + { + /*neither*/ + BuiltinList[i].obsolete = true; + nd = d; /*don't switch ifdefs*/ + } else nd = 1; /*ssqc only*/ } @@ -10217,7 +10044,7 @@ void PR_DumpPlatform_f(void) VFS_PRINTF(f, "#ifdef CSQC\n"); d = nd; } - VFS_PRINTF(f, "%s %s = #%u;\n", BuiltinList[i].prototype, BuiltinList[i].name, idx); + VFS_PRINTF(f, "%s%s %s = #%u;\n", BuiltinList[i].obsolete?"//":"", BuiltinList[i].prototype, BuiltinList[i].name, idx); } } if (d) @@ -10227,6 +10054,7 @@ void PR_DumpPlatform_f(void) VFS_CLOSE(f); FS_FlushFSHash(); + Con_Printf("Written \"%s\"\n", dbgfname); #endif } diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index be3cd1d66..097c39c71 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -177,7 +177,7 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldentity(dmg_inflictor)\ comfieldentity(owner)\ comfieldvector(movedir)\ - comfieldstring(message) /*not used directly, hexen2 uses floats, so we go via qclib for message*/\ + comfieldstring(message) /*don't use directly, hexen2 uses floats, so we go via qclib for message*/\ comfieldfloat(sounds)\ comfieldstring(noise)\ comfieldstring(noise1)\ @@ -196,6 +196,8 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(scale)/*DP_ENT_SCALE*/\ comfieldfloat(fatness)/*FTE_PEXT_FATNESS*/\ comfieldfloat(alpha)/*DP_ENT_ALPHA*/\ + comfieldentity(tag_entity)\ + comfieldfloat(skeletonindex) /*FTE_CSQC_SKELETONOBJECTS*/\ comfieldvector(colormod)\ comfieldfloat(pmove_flags)/*EXT_CSQC_1*/\ comfieldfloat(jointtype)/*DP_...PHYSICS*/\ @@ -220,7 +222,6 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(button7)\ comfieldfloat(button8)\ comfieldfloat(viewzoom)/*DP_VIEWZOOM*/\ - comfieldentity(tag_entity)\ comfieldfloat(tag_index)\ comfieldfloat(glow_size)\ comfieldfloat(glow_color)\ @@ -272,8 +273,6 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(subblendfrac) /*FTE_CSQC_HALFLIFE_MODELS*/\ comfieldfloat(basesubblendfrac) /*FTE_CSQC_HALFLIFE_MODELS+FTE_CSQC_BASEFRAME*/\ \ - comfieldfloat(skeletonindex) /*FTE_CSQC_SKELETONOBJECTS*/\ - \ comfieldfloat(drawmask) /*So that the qc can specify all rockets at once or all bannanas at once*/ \ comfieldfunction(predraw, ".void()") /*If present, is called just before it's drawn.*/ \ comfieldvector(glowmod) \ @@ -409,6 +408,7 @@ typedef struct { // for ODE physics engine qboolean ode; // if true then ode is activated + qboolean hasodeents; // if true then we have some ode body somewhere, and we consume more cycles processing full physics, instead of trying to skip as much as we can void *ode_world; void *ode_space; void *ode_contactgroup; diff --git a/engine/server/q2game.h b/engine/server/q2game.h index 75eec8a36..c877722ae 100644 --- a/engine/server/q2game.h +++ b/engine/server/q2game.h @@ -27,7 +27,10 @@ typedef enum multicast_e MULTICAST_PVS, MULTICAST_ALL_R, MULTICAST_PHS_R, - MULTICAST_PVS_R + MULTICAST_PVS_R, + + MULTICAST_ONE, + MULTICAST_ONE_R } multicast_t; extern float pm_q2stepheight; diff --git a/engine/server/server.h b/engine/server/server.h index 4ffe7679f..a1cb100ec 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -809,30 +809,6 @@ typedef struct #define DAMAGE_YES 1 #define DAMAGE_AIM 2 -// edict->flags -#define FL_FLY (1<<0) -#define FL_SWIM (1<<1) -#define FL_GLIMPSE (1<<2) -#define FL_CLIENT (1<<3) -#define FL_INWATER (1<<4) -#define FL_MONSTER (1<<5) -#define FL_GODMODE (1<<6) -#define FL_NOTARGET (1<<7) -#define FL_ITEM (1<<8) -#define FL_ONGROUND (1<<9) -#define FL_PARTIALGROUND (1<<10) // not all corners are valid -#define FL_WATERJUMP (1<<11) // player jumping out of water - //12 - //13 -#define FL_FINDABLE_NONSOLID (1<<14) //a cpqwsv feature -#define FL_MOVECHAIN_ANGLE (1<<15) // when in a move chain, will update the angle -#define FL_LAGGEDMOVE (1<<16) - //17 - //18 - //19 - //20 -#define FL_CLASS_DEPENDENT (1<<21) - #define PVSF_NORMALPVS 0x0 #define PVSF_NOTRACECHECK 0x1 #define PVSF_USEPHS 0x2 diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 5610bbc2c..31c867819 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -514,7 +514,10 @@ void SV_Map_f (void) COM_FlushFSCache(); - if (strlen(level) > 4 && !strcmp(level + strlen(level)-4, ".cin")) + if (strlen(level) > 4 && + (!strcmp(level + strlen(level)-4, ".cin") || + !strcmp(level + strlen(level)-4, ".roq") || + !strcmp(level + strlen(level)-4, ".avi"))) { cinematic = true; } @@ -627,7 +630,7 @@ void SV_Map_f (void) } SV_SendMessagesToAll (); - if (newunit || !startspot || !SV_LoadLevelCache(NULL, level, startspot, false)) + if (newunit || !startspot || cinematic || !SV_LoadLevelCache(NULL, level, startspot, false)) { if (waschangelevel && !startspot) startspot = ""; diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 976f9f3c3..136aa6eec 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -596,6 +596,7 @@ void SV_UnspawnServer (void) //terminate the running server. if (svs.clients[i].state) SV_DropClient(svs.clients+i); } + PR_Deinit(); #ifdef Q2SERVER SVQ2_ShutdownGameProgs(); #endif diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 55b646e6a..ed7fb5da7 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -320,9 +320,6 @@ void VARGS SV_Error (char *error, ...) #ifndef SERVERONLY if (cls.state) { - if (sv.state) - SV_UnspawnServer(); - inerror = false; Host_EndGame("SV_Error: %s\n",string); } diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 197f1c98e..fa0ff0e3f 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -505,6 +505,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int int leafnum; int j; qboolean reliable; + int pnum = 0; // to = MULTICAST_ALL; #ifdef Q2BSPS @@ -642,8 +643,6 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int else #endif { - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); - reliable = false; switch (to) @@ -660,15 +659,30 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int if (!sv.phs) /*broadcast if no pvs*/ mask = sv.pvs; else + { + leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); + } break; case MULTICAST_PVS_R: reliable = true; // intentional fallthrough case MULTICAST_PVS: + leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, origin); mask = sv.pvs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); break; + case MULTICAST_ONE_R: + reliable = true; + case MULTICAST_ONE: + if (svprogfuncs) + { + edict_t *ent = PROG_TO_EDICT(svprogfuncs, pr_global_struct->msg_entity); + pnum = NUM_FOR_EDICT(svprogfuncs, ent) - 1; + } + mask = NULL; + break; + default: mask = NULL; SV_Error ("SV_Multicast: bad to:%i", to); @@ -697,7 +711,12 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int } } - if (svprogfuncs) + if (!mask) + { + if (pnum != j) + continue; + } + else if (svprogfuncs) { if (!((int)client->edict->xv->dimension_see & dimension_mask)) continue; @@ -777,12 +796,22 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int if (sv.mvdrecording && !with) //mvds don't get the pext stuff { - if (reliable) + if (!mask) { - MVDWrite_Begin(dem_all, 0, sv.multicast.cursize); + /*no distinction between reliable or not*/ + MVDWrite_Begin(dem_single, pnum, sv.multicast.cursize); SZ_Write(&demo.dbuf->sb, sv.multicast.data, sv.multicast.cursize); - } else - SZ_Write(&demo.datagram, sv.multicast.data, sv.multicast.cursize); + } + else + { + if (reliable) + { + MVDWrite_Begin(dem_all, 0, sv.multicast.cursize); + SZ_Write(&demo.dbuf->sb, sv.multicast.data, sv.multicast.cursize); + } + else + SZ_Write(&demo.datagram, sv.multicast.data, sv.multicast.cursize); + } } #ifdef NQPROT diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 72d60ce8f..def217697 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -5226,6 +5226,8 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node ) pe->notouch = !((int)player->xv->dimension_solid & (int)check->xv->dimension_hit); if (!((int)player->xv->dimension_hit & (int)check->xv->dimension_solid)) continue; + if (!check->v->size[0]) //points are not meant to be solid + continue; pmove.numphysent++; VectorCopy (check->v->origin, pe->origin); @@ -5625,7 +5627,6 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) pmove.waterjumptime = sv_player->v->teleport_time; if (pmove.waterjumptime > sv.time) sv_player->v->flags = (int)sv_player->v->flags | FL_WATERJUMP; - sv_player->v->teleport_time = sv.time + pmove.waterjumptime; } else jumpable = false; @@ -5729,7 +5730,10 @@ if (sv_player->v->health > 0 && before && !after ) host_client->jump_held = pmove.jump_held; if (progstype != PROG_QW) //this is just annoying. - sv_player->v->teleport_time = pmove.waterjumptime + sv.time; + { + if (pmove.waterjumptime) + sv_player->v->teleport_time = pmove.waterjumptime + sv.time; + } else sv_player->v->teleport_time = pmove.waterjumptime; sv_player->v->waterlevel = pmove.waterlevel; diff --git a/engine/server/svmodel.c b/engine/server/svmodel.c index ac73b4a4c..ba6353811 100644 --- a/engine/server/svmodel.c +++ b/engine/server/svmodel.c @@ -882,7 +882,23 @@ qboolean Mod_LoadEdges (lump_t *l, qboolean lm) if (lm) { -#pragma warningmsg("bsp2 todo") + dledge_t *in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); + + loadmodel->edges = out; + loadmodel->numedges = count; + + for ( i=0 ; iv[0] = (unsigned int)LittleLong(in->v[0]); + out->v[1] = (unsigned int)LittleLong(in->v[1]); + } } else { @@ -1038,66 +1054,85 @@ Mod_LoadFaces */ qboolean Mod_LoadFaces (lump_t *l, qboolean lm) { - dsface_t *in; + dsface_t *ins; + dlface_t *inl; msurface_t *out; int i, count, surfnum; int planenum, side; + int tn, lofs; if (lm) { - in = NULL; -#pragma warningmsg("bsp2 fixme") - } - else - { - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + ins = NULL; + inl = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*inl)) { Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); return false; } - count = l->filelen / sizeof(*in); + count = l->filelen / sizeof(*inl); + } + else + { + inl = NULL; + ins = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*ins)) + { + Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*ins); } out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->surfaces = out; loadmodel->numsurfaces = count; - for ( surfnum=0 ; surfnumplanenum); + side = LittleLong(inl->side); + out->firstedge = LittleLong(inl->firstedge); + out->numedges = LittleLong(inl->numedges); + tn = LittleLong (inl->texinfo); + for (i=0 ; istyles[i] = inl->styles[i]; + lofs = LittleLong(inl->lightofs); + inl++; } else { - out->firstedge = LittleLong(in->firstedge); - out->numedges = LittleShort(in->numedges); + planenum = LittleShort(ins->planenum); + side = LittleShort(ins->side); + out->firstedge = LittleLong(ins->firstedge); + out->numedges = LittleShort(ins->numedges); + tn = LittleShort (ins->texinfo); + for (i=0 ; istyles[i] = ins->styles[i]; + lofs = LittleLong(ins->lightofs); + ins++; } + out->flags = 0; - planenum = LittleShort(in->planenum); - side = LittleShort(in->side); if (side) out->flags |= SURF_PLANEBACK; out->plane = loadmodel->planes + planenum; - out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); + out->texinfo = loadmodel->texinfo + tn; CalcSurfaceExtents (out); // lighting info - - for (i=0 ; istyles[i] = in->styles[i]; - i = LittleLong(in->lightofs); - if (i == -1) + if (lofs == -1) out->samples = NULL; else if (loadmodel->fromgame == fg_halflife) - out->samples = loadmodel->lightdata + i; + out->samples = loadmodel->lightdata + lofs; else - out->samples = loadmodel->lightdata + i*3; + out->samples = loadmodel->lightdata + lofs*3; // set the drawing flags flag @@ -1145,15 +1180,50 @@ Mod_LoadNodes qboolean Mod_LoadNodes (lump_t *l, qboolean lm) { int i, j, count, p; - dsnode_t *in; mnode_t *out; if (lm) { -#pragma warningmsg("bsp2 fixme") + dlnode_t *in; + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->nodes = out; + loadmodel->numnodes = count; + + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->planenum); + out->plane = loadmodel->planes + p; + + out->firstsurface = LittleLong (in->firstface); + out->numsurfaces = LittleLong (in->numfaces); + + for (j=0 ; j<2 ; j++) + { + p = LittleLong (in->children[j]); + if (p >= 0) + out->children[j] = loadmodel->nodes + p; + else + out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + } + } } else { + dsnode_t *in; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) { @@ -1202,16 +1272,52 @@ Mod_LoadLeafs */ qboolean Mod_LoadLeafs (lump_t *l, qboolean lm) { - dsleaf_t *in; mleaf_t *out; int i, j, count, p; if (lm) { -#pragma warningmsg("bsp2 fixme") + dlleaf_t *in; + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->leafs = out; + loadmodel->numleafs = count; + + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->contents); + out->contents = p; + + out->firstmarksurface = loadmodel->marksurfaces + + (unsigned int)LittleLong(in->firstmarksurface); + out->nummarksurfaces = (unsigned int)LittleLong(in->nummarksurfaces); + + p = LittleLong(in->visofs); + if (p == -1) + out->compressed_vis = NULL; + else + out->compressed_vis = loadmodel->visdata + p; + + for (j=0 ; j<4 ; j++) + out->ambient_sound_level[j] = in->ambient_level[j]; + } } else { + dsleaf_t *in; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) { @@ -1260,18 +1366,13 @@ Mod_LoadClipnodes */ qboolean Mod_LoadClipnodes (lump_t *l, qboolean lm) { - dsclipnode_t *in; mclipnode_t *out; int i, count; hull_t *hull; if (lm) { -#pragma warningmsg("bsp2 fixme") - in = NULL; - } - else - { + dlclipnode_t *in; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) { @@ -1279,8 +1380,34 @@ qboolean Mod_LoadClipnodes (lump_t *l, qboolean lm) return false; } count = l->filelen / sizeof(*in); + + out = Hunk_AllocName ( count*sizeof(*out), loadname); + for (i=0 ; iplanenum); + out[i].children[0] = LittleLong(in->children[0]); + out[i].children[1] = LittleLong(in->children[1]); + } + } + else + { + dsclipnode_t *in; + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + + out = Hunk_AllocName ( count*sizeof(*out), loadname); + for (i=0 ; iplanenum); + out[i].children[0] = LittleShort(in->children[0]); + out[i].children[1] = LittleShort(in->children[1]); + } } - out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->clipnodes = out; loadmodel->numclipnodes = count; @@ -1444,20 +1571,6 @@ qboolean Mod_LoadClipnodes (lump_t *l, qboolean lm) hull->available = false; } - if (lm) - { -#pragma warningmsg("bsp2 fixme") - } - else - { - for (i=0 ; iplanenum = LittleLong(in->planenum); - out->children[0] = LittleShort(in->children[0]); - out->children[1] = LittleShort(in->children[1]); - } - } - return true; }