diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 49cc34b1f..5518b4caa 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -203,11 +203,11 @@ int demo_preparsedemo(unsigned char *buffer, int bytes) { return parsed; //not got it all } - if ((buffer[1]&dem_mask) == dem_all && (buffer[1] & ~dem_mask) && length < MAX_NQMSGLEN) + if ((buffer[1]&dem_mask) == dem_all && (buffer[1] & ~dem_mask) && length < MAX_OVERALLMSGLEN) { net_message.cursize = length; memcpy(net_message.data, buffer+ofs, length); - MSG_BeginReading(); + MSG_BeginReading(cls.netchan.netprim); CL_ParseServerMessage(); } @@ -1969,6 +1969,8 @@ void CL_QTVPlay_f (void) CL_ParseQTVDescriptor(VFSOS_Open(connrequest+1, "rt"), connrequest+1); return; } + strcpy(cls.servername, "qtv:"); + Q_strncpyz(cls.servername+4, connrequest, sizeof(cls.servername)-4); SCR_SetLoadingStage(LS_CONNECTION); @@ -2135,6 +2137,8 @@ void CL_FinishTimeDemo (void) Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time); cls.td_startframe = 0; + + TP_ExecTrigger ("f_timedemoend"); } /* diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 92e5ca253..046fbaf3c 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -85,6 +85,7 @@ qboolean CL_FilterModelindex(int modelindex, int frame) void CL_FreeDlights(void) { +#pragma message("not freeing shadowmeshes") rtlights_max = cl_maxdlights = 0; BZ_Free(cl_dlights); cl_dlights = NULL; @@ -98,9 +99,13 @@ void CL_InitDlights(void) static void CL_ClearDlight(dlight_t *dl, int key) { + void *sm; texid_t st; st = dl->stexture; + sm = dl->worldshadowmesh; memset (dl, 0, sizeof(*dl)); + dl->rebuildcache = true; + dl->worldshadowmesh = sm; dl->stexture = st; dl->axis[0][0] = 1; dl->axis[1][1] = 1; @@ -857,7 +862,7 @@ void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o( cl_latestframenum = MSG_ReadLong(); - if (nq_dp_protocol >=7) + if (cls.protocol_nq >= CPNQ_DP7) cl.ackedinputsequence = MSG_ReadLong(); pack = &cl.frames[(cls.netchan.incoming_sequence)&UPDATE_MASK].packet_entities; @@ -946,48 +951,6 @@ void CLNQ_ParseEntity(unsigned int bits) static float lasttime; packet_entities_t *pack; -#define NQU_MOREBITS (1<<0) -#define NQU_ORIGIN1 (1<<1) -#define NQU_ORIGIN2 (1<<2) -#define NQU_ORIGIN3 (1<<3) -#define NQU_ANGLE2 (1<<4) -#define NQU_NOLERP (1<<5) // don't interpolate movement -#define NQU_FRAME (1<<6) -#define NQU_SIGNAL (1<<7) // just differentiates from other updates - -// svc_update can pass all of the fast update bits, plus more -#define NQU_ANGLE1 (1<<8) -#define NQU_ANGLE3 (1<<9) -#define NQU_MODEL (1<<10) -#define NQU_COLORMAP (1<<11) -#define NQU_SKIN (1<<12) -#define NQU_EFFECTS (1<<13) -#define NQU_LONGENTITY (1<<14) - - -// LordHavoc's: protocol extension -#define DPU_EXTEND1 (1<<15) -// LordHavoc: first extend byte -#define DPU_DELTA (1<<16) // no data, while this is set the entity is delta compressed (uses previous frame as a baseline, meaning only things that have changed from the previous frame are sent, except for the forced full update every half second) -#define DPU_ALPHA (1<<17) // 1 byte, 0.0-1.0 maps to 0-255, not sent if exactly 1, and the entity is not sent if <=0 unless it has effects (model effects are checked as well) -#define DPU_SCALE (1<<18) // 1 byte, scale / 16 positive, not sent if 1.0 -#define DPU_EFFECTS2 (1<<19) // 1 byte, this is .effects & 0xFF00 (second byte) -#define DPU_GLOWSIZE (1<<20) // 1 byte, encoding is float/4.0, unsigned, not sent if 0 -#define DPU_GLOWCOLOR (1<<21) // 1 byte, palette index, default is 254 (white), this IS used for darklight (allowing colored darklight), however the particles from a darklight are always black, not sent if default value (even if glowsize or glowtrail is set) -// LordHavoc: colormod feature has been removed, because no one used it -#define DPU_COLORMOD (1<<22) // 1 byte, 3 bit red, 3 bit green, 2 bit blue, this lets you tint an object artifically, so you could make a red rocket, or a blue fiend... -#define DPU_EXTEND2 (1<<23) // another byte to follow -// LordHavoc: second extend byte -#define DPU_GLOWTRAIL (1<<24) // leaves a trail of particles (of color .glowcolor, or black if it is a negative glowsize) -#define DPU_VIEWMODEL (1<<25) // attachs the model to the view (origin and angles become relative to it), only shown to owner, a more powerful alternative to .weaponmodel and such -#define DPU_FRAME2 (1<<26) // 1 byte, this is .frame & 0xFF00 (second byte) -#define DPU_MODEL2 (1<<27) // 1 byte, this is .modelindex & 0xFF00 (second byte) -#define DPU_EXTERIORMODEL (1<<28) // causes this model to not be drawn when using a first person view (third person will draw it, first person will not) -#define DPU_UNUSED29 (1<<29) // future expansion -#define DPU_UNUSED30 (1<<30) // future expansion -#define DPU_EXTEND3 (1<<31) // another byte to follow, future expansion - - if (cls.signon == 4 - 1) { // first update is the final signon stage cls.signon = 4; @@ -1093,63 +1056,81 @@ void CLNQ_ParseEntity(unsigned int bits) else state->angles[2] = base->angles[2]; - if (bits & DPU_ALPHA) - i = MSG_ReadByte(); - else - i = -1; - -#ifdef PEXT_TRANS - if (i == -1) - state->trans = base->trans; - else - state->trans = i; -#endif - - if (bits & DPU_SCALE) - i = MSG_ReadByte(); - else - i = -1; - -#ifdef PEXT_SCALE - if (i == -1) - state->scale = base->scale; - else - state->scale = i; -#endif - - if (bits & DPU_EFFECTS2) - state->effects |= MSG_ReadByte() << 8; - - if (bits & DPU_GLOWSIZE) - state->glowsize = MSG_ReadByte(); - else - state->glowsize = base->glowsize; - - if (bits & DPU_GLOWCOLOR) - state->glowcolour = MSG_ReadByte(); - else - state->glowcolour = base->glowcolour; - - if (bits & DPU_COLORMOD) + if (cls.protocol_nq == CPNQ_FITZ666) { - i = MSG_ReadByte(); // follows format RRRGGGBB - state->colormod[0] = (qbyte)(((i >> 5) & 7) * (32.0f / 7.0f)); - state->colormod[1] = (qbyte)(((i >> 2) & 7) * (32.0f / 7.0f)); - state->colormod[2] = (qbyte)((i & 3) * (32.0f / 3.0f)); + if (bits & FITZU_ALPHA) + state->trans = MSG_ReadByte(); + else + state->trans = base->trans; + + if (bits & FITZU_FRAME2) + state->frame |= MSG_ReadByte() << 8; + + if (bits & FITZU_MODEL2) + state->modelindex |= MSG_ReadByte() << 8; + + if (bits & FITZU_LERPFINISH) + MSG_ReadByte(); } else { - state->colormod[0] = base->colormod[0]; - state->colormod[1] = base->colormod[1]; - state->colormod[2] = base->colormod[2]; + if (bits & DPU_ALPHA) + i = MSG_ReadByte(); + else + i = -1; + + #ifdef PEXT_TRANS + if (i == -1) + state->trans = base->trans; + else + state->trans = i; + #endif + + if (bits & DPU_SCALE) + i = MSG_ReadByte(); + else + i = -1; + + #ifdef PEXT_SCALE + if (i == -1) + state->scale = base->scale; + else + state->scale = i; + #endif + + if (bits & DPU_EFFECTS2) + state->effects |= MSG_ReadByte() << 8; + + if (bits & DPU_GLOWSIZE) + state->glowsize = MSG_ReadByte(); + else + state->glowsize = base->glowsize; + + if (bits & DPU_GLOWCOLOR) + state->glowcolour = MSG_ReadByte(); + else + state->glowcolour = base->glowcolour; + + if (bits & DPU_COLORMOD) + { + i = MSG_ReadByte(); // follows format RRRGGGBB + state->colormod[0] = (qbyte)(((i >> 5) & 7) * (32.0f / 7.0f)); + state->colormod[1] = (qbyte)(((i >> 2) & 7) * (32.0f / 7.0f)); + state->colormod[2] = (qbyte)((i & 3) * (32.0f / 3.0f)); + } + else + { + state->colormod[0] = base->colormod[0]; + state->colormod[1] = base->colormod[1]; + state->colormod[2] = base->colormod[2]; + } + + if (bits & DPU_FRAME2) + state->frame |= MSG_ReadByte() << 8; + + if (bits & DPU_MODEL2) + state->modelindex |= MSG_ReadByte() << 8; } - - if (bits & DPU_FRAME2) - state->frame |= MSG_ReadByte() << 8; - - if (bits & DPU_MODEL2) - state->modelindex |= MSG_ReadByte() << 8; - if (cls.demoplayback != DPB_NONE) for (pnum = 0; pnum < cl.splitclients; pnum++) if (num == cl.viewentity[pnum]) @@ -1447,8 +1428,8 @@ void CL_LinkStaticEntities(void *pvs) model_t *clmodel; extern cvar_t r_drawflame, gl_part_flame; -// if (!cl_staticentities.ival) -// return; + if (r_drawflame.ival < 0) + return; if (!cl.worldmodel) return; @@ -1460,6 +1441,8 @@ void CL_LinkStaticEntities(void *pvs) stat = &cl_static_entities[i].ent; clmodel = stat->model; + if (!clmodel || clmodel->needload) + continue; if ((!r_drawflame.ival) && (clmodel->engineflags & MDLF_FLAME)) continue; @@ -2631,6 +2614,8 @@ void CL_AddVWeapModel(entity_t *player, model_t *model) { entity_t *newent; vec3_t angles; + if (!model) + return; newent = CL_NewTempEntity (); newent->keynum = player->keynum; diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index bcb6504b7..93e029af2 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -757,19 +757,24 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf) MSG_WriteByte (buf, clc_move); - if (nq_dp_protocol>=7) + if (cls.protocol_nq >= CPNQ_DP7) MSG_WriteLong(buf, cls.netchan.outgoing_sequence); MSG_WriteFloat (buf, cl.gametime); // so server can get ping times for (i=0 ; i<3 ; i++) - MSG_WriteAngle (buf, cl.viewangles[pnum][i]); + { + if (cls.protocol_nq == CPNQ_FITZ666) + MSG_WriteAngle16 (buf, cl.viewangles[pnum][i]); + else + MSG_WriteAngle (buf, cl.viewangles[pnum][i]); + } MSG_WriteShort (buf, cmd->forwardmove); MSG_WriteShort (buf, cmd->sidemove); MSG_WriteShort (buf, cmd->upmove); - if (nq_dp_protocol >= 6) + if (cls.protocol_nq >= CPNQ_DP6) { CL_UpdatePrydonCursor(cmd, cursor_screen, cursor_start, cursor_impact, &cursor_entitynumber); MSG_WriteLong (buf, cmd->buttons); @@ -781,7 +786,7 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf) MSG_WriteByte (buf, cmd->impulse); - if (nq_dp_protocol >= 6) + if (cls.protocol_nq >= CPNQ_DP6) { MSG_WriteShort (buf, cursor_screen[0] * 32767.0f); MSG_WriteShort (buf, cursor_screen[1] * 32767.0f); @@ -808,7 +813,7 @@ void Name_Callback(struct cvar_s *var, char *oldvalue) void CLNQ_SendCmd(sizebuf_t *buf) { - extern int cl_latestframenum, nq_dp_protocol; + extern int cl_latestframenum; if (cls.signon == 4) { @@ -819,7 +824,7 @@ void CLNQ_SendCmd(sizebuf_t *buf) CLNQ_SendMove (&independantphysics[0], 0, buf); } - if (nq_dp_protocol > 0 && cls.signon == 4) + if (CPNQ_IS_DP && cls.signon == 4) { MSG_WriteByte(buf, clcdp_ackframe); MSG_WriteLong(buf, cl_latestframenum); @@ -1498,6 +1503,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) buf.maxsize = sizeof(data); buf.cursize = 0; buf.data = data; + buf.prim = cls.netchan.message.prim; #ifdef IRCCONNECT if (cls.netchan.remote_address.type != NA_IRC) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index a26bc0205..fce844b21 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -135,7 +135,7 @@ cvar_t cl_gunanglex = SCVAR("cl_gunanglex", "0"); cvar_t cl_gunangley = SCVAR("cl_gunangley", "0"); cvar_t cl_gunanglez = SCVAR("cl_gunanglez", "0"); -cvar_t allow_download_csprogs = SCVARF("allow_download_csprogs", "0", CVAR_NOTFROMSERVER); +cvar_t allow_download_csprogs = SCVARF("allow_download_csprogs", "1", CVAR_NOTFROMSERVER); cvar_t allow_download_redirection = SCVARF("allow_download_redirection", "0", CVAR_NOTFROMSERVER); cvar_t requiredownloads = SCVARF("requiredownloads","1", CVAR_ARCHIVE); @@ -182,7 +182,8 @@ client_state_t cl; // alot of this should probably be dynamically allocated entity_state_t *cl_baselines; -static_entity_t cl_static_entities[MAX_STATIC_ENTITIES]; +static_entity_t *cl_static_entities; +unsigned int cl_max_static_entities; lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; //lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; dlight_t *cl_dlights; @@ -1054,6 +1055,8 @@ void CL_ClearState (void) // clear other arrays // memset (cl_dlights, 0, sizeof(cl_dlights)); memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); + for (i = 0; i < MAX_LIGHTSTYLES; i++) + cl_lightstyle[i].colour = 7; rtlights_first = rtlights_max = RTL_FIRST; @@ -2018,7 +2021,7 @@ void CL_ConnectionlessPacket (void) int c; char adr[MAX_ADR_SIZE]; - MSG_BeginReading (); + MSG_BeginReading (msg_nullnetprim); MSG_ReadLong (); // skip the -1 Cmd_TokenizeString(net_message.data+4, false, false); @@ -2410,7 +2413,7 @@ void CLNQ_ConnectionlessPacket(void) char *s; int length; - MSG_BeginReading (); + MSG_BeginReading (msg_nullnetprim); length = LongSwap(MSG_ReadLong ()); if (!(length & NETFLAG_CTL)) return; //not an nq control packet. @@ -2522,7 +2525,7 @@ void CL_ReadPackets (void) #ifdef NQPROT if (cls.demoplayback == DPB_NETQUAKE) { - MSG_BeginReading (); + MSG_BeginReading (cls.netchan.netprim); cls.netchan.last_received = realtime; CLNQ_ParseServerMessage (); @@ -2534,7 +2537,7 @@ void CL_ReadPackets (void) #ifdef Q2CLIENT if (cls.demoplayback == DPB_QUAKE2) { - MSG_BeginReading (); + MSG_BeginReading (cls.netchan.netprim); cls.netchan.last_received = realtime; CLQ2_ParseServerMessage (); continue; @@ -2585,6 +2588,7 @@ void CL_ReadPackets (void) case NQP_DATAGRAM://datagram cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence - 3; case NQP_RELIABLE://reliable + MSG_ChangePrimitives(cls.netchan.netprim); CLNQ_ParseServerMessage (); break; } @@ -2597,6 +2601,7 @@ void CL_ReadPackets (void) if (!Netchan_Process(&cls.netchan)) continue; // wasn't accepted for some reason CLQ2_ParseServerMessage (); + break; #endif case CP_QUAKE3: #ifdef Q3CLIENT @@ -2606,7 +2611,7 @@ void CL_ReadPackets (void) case CP_QUAKEWORLD: if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { - MSG_BeginReading(); + MSG_BeginReading(cls.netchan.netprim); cls.netchan.last_received = realtime; cls.netchan.outgoing_sequence = cls.netchan.incoming_sequence; } @@ -2618,6 +2623,7 @@ void CL_ReadPackets (void) Con_Printf("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); CL_ParseServerMessage (); break; case CP_UNKNOWN: @@ -3616,7 +3622,7 @@ void Host_Init (quakeparms_t *parms) #endif // Con_Printf ("Exe: "__TIME__" "__DATE__"\n"); - Con_TPrintf (TL_HEAPSIZE, parms->memsize/ (1024*1024.0)); + //Con_TPrintf (TL_HEAPSIZE, parms->memsize/ (1024*1024.0)); Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); host_hunklevel = Hunk_LowMark (); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 7216c6db7..ca36e223b 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -27,7 +27,6 @@ void CLNQ_ParseDarkPlaces5Entities(void); void CL_SetStatInt (int pnum, int stat, int value); static qboolean CL_CheckModelResources (char *name); -int nq_dp_protocol; int msgflags; char cl_dp_csqc_progsname[128]; @@ -1767,14 +1766,14 @@ void CLDP_ParseDownloadData(void) { VFS_SEEK(cls.downloadqw, start); VFS_WRITE(cls.downloadqw, buffer, size); + + cls.downloadpercent = start / (float)VFS_GETLEN(cls.downloadqw) * 100; } //this is only reliable because I'm lazy MSG_WriteByte(&cls.netchan.message, clcdp_ackdownloaddata); MSG_WriteLong(&cls.netchan.message, start); MSG_WriteShort(&cls.netchan.message, size); - - cls.downloadpercent = start / (float)VFS_GETLEN(cls.downloadqw) * 100; } void CLDP_ParseDownloadBegin(char *s) @@ -2096,14 +2095,16 @@ void CL_ParseServerData (void) if (cls.fteprotocolextensions & PEXT_FLOATCOORDS) { - sizeofcoord = 4; - sizeofangle = 2; + cls.netchan.netprim.coordsize = 4; + cls.netchan.netprim.anglesize = 2; } else { - sizeofcoord = 2; - sizeofangle = 1; + cls.netchan.netprim.coordsize = 2; + cls.netchan.netprim.anglesize = 1; } + cls.netchan.message.prim = cls.netchan.netprim; + MSG_ChangePrimitives(cls.netchan.netprim); svcnt = MSG_ReadLong (); @@ -2276,8 +2277,9 @@ void CLQ2_ParseServerData (void) int svcnt; // int cflag; - sizeofcoord = 2; - sizeofangle = 1; + cls.netchan.netprim.coordsize = 2; + cls.netchan.netprim.anglesize = 1; + MSG_ChangePrimitives(cls.netchan.netprim); Con_DPrintf ("Serverdata packet received.\n"); // @@ -2316,6 +2318,7 @@ void CLQ2_ParseServerData (void) //I can't really blame q2admin for rejecting engines that don't have this cvar, as it could have been renamed via a hex-edit. CL_ClearState (); + CLQ2_ClearState (); cl.minpitch = -89; cl.maxpitch = 89; cl.servercount = svcnt; @@ -2382,6 +2385,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. char *str; int gametype; int protover; + struct netprim_s netprim; if (developer.ival) Con_TPrintf (TLC_GOTSVDATAPACKET); SCR_SetLoadingStage(LS_CLIENT); @@ -2391,29 +2395,35 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. protover = MSG_ReadLong (); - sizeofcoord = 2; - sizeofangle = 1; + netprim.coordsize = 2; + netprim.anglesize = 1; - nq_dp_protocol = 0; + cls.protocol_nq = 0; cls.z_ext = 0; if (protover == 250) Host_EndGame ("Nehahra demo net protocol is not supported\n"); + else if (protover == 666) + { + //fitzquake 0.85 + cls.protocol_nq = CPNQ_FITZ666; + Con_DPrintf("FitzQuake 666 protocol\n"); + } else if (protover == 3502) { //darkplaces5 - nq_dp_protocol = 5; - sizeofcoord = 4; - sizeofangle = 2; + cls.protocol_nq = CPNQ_DP5; + netprim.coordsize = 4; + netprim.anglesize = 2; Con_DPrintf("DP5 protocols\n"); } else if (protover == DP6_PROTOCOL_VERSION) { //darkplaces6 (it's a small difference from dp5) - nq_dp_protocol = 6; - sizeofcoord = 4; - sizeofangle = 2; + cls.protocol_nq = CPNQ_DP6; + netprim.coordsize = 4; + netprim.anglesize = 2; cls.z_ext = Z_EXT_VIEWHEIGHT; @@ -2422,9 +2432,9 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. else if (protover == DP7_PROTOCOL_VERSION) { //darkplaces7 (it's a small difference from dp5) - nq_dp_protocol = 7; - sizeofcoord = 4; - sizeofangle = 2; + cls.protocol_nq = CPNQ_DP7; + netprim.coordsize = 4; + netprim.anglesize = 2; cls.z_ext = Z_EXT_VIEWHEIGHT; @@ -2438,6 +2448,8 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. { Con_DPrintf("Standard NQ protocols\n"); } + cls.netchan.message.prim = cls.netchan.netprim = netprim; + MSG_ChangePrimitives(netprim); if (MSG_ReadByte() > MAX_CLIENTS) { @@ -2491,7 +2503,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. } strcpy (cl.sound_name[numsounds], str); -#pragma message("the logic that we should have here is rather long") +#pragma message("CLNQ_ParseServerData: no sound autodownloads") //CL_CheckOrEnqueDownloadFile(str, NULL, 0); S_TouchSound (str); @@ -2522,8 +2534,8 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. Info_SetValueForStarKey(cl.serverinfo, "deathmatch", "0", sizeof(cl.serverinfo)); Info_SetValueForStarKey(cl.serverinfo, "teamplay", "0", sizeof(cl.serverinfo)); - //allow shaders - Info_SetValueForStarKey(cl.serverinfo, "allow_shaders", "1", sizeof(cl.serverinfo)); + //allow some things by default that quakeworld bans by default + Info_SetValueForStarKey(cl.serverinfo, "watervis", "1", sizeof(cl.serverinfo)); //pretend it came from the server, and update cheat/permissions/etc CL_CheckServerInfo(); @@ -2557,7 +2569,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); CL_SendClientCommand(true, "spawn %s", ""); - if (nq_dp_protocol) //dp needs a couple of extras to work properly. + if (CPNQ_IS_DP) //dp needs a couple of extras to work properly. { CL_SendClientCommand(true, "rate %s", rate.string); @@ -2644,7 +2656,7 @@ void CLNQ_ParseClientdata (void) if (bits & SU_VIEWHEIGHT) CL_SetStatInt(0, STAT_VIEWHEIGHT, MSG_ReadChar ()); - else if (nq_dp_protocol < 6) + else if (CPNQ_IS_DP || cls.protocol_nq == CPNQ_DP5) CL_SetStatInt(0, STAT_VIEWHEIGHT, DEFAULT_VIEWHEIGHT); if (bits & SU_IDEALPITCH) @@ -2656,7 +2668,7 @@ void CLNQ_ParseClientdata (void) for (i=0 ; i<3 ; i++) { if (bits & (SU_PUNCH1<= 5) + if (CPNQ_IS_DP) /*cl.simvel[0][i] =*/ MSG_ReadFloat(); else /*cl.mvelocity[0][i] =*/ MSG_ReadChar()/**16*/; @@ -2684,10 +2696,7 @@ void CLNQ_ParseClientdata (void) // cl.onground = (bits & SU_ONGROUND) != 0; // cl.inwater = (bits & SU_INWATER) != 0; - if (nq_dp_protocol >= 6) - { - } - else if (nq_dp_protocol == 5) + if (cls.protocol_nq == CPNQ_DP5) { CL_SetStatInt(0, STAT_WEAPONFRAME, (bits & SU_WEAPONFRAME)?(unsigned short)MSG_ReadShort():0); CL_SetStatInt(0, STAT_ARMOR, (bits & SU_ARMOR)?MSG_ReadShort():0); @@ -2704,6 +2713,10 @@ void CLNQ_ParseClientdata (void) CL_SetStatInt(0, STAT_ACTIVEWEAPON, (unsigned short)MSG_ReadShort()); } + else if (CPNQ_IS_DP) + { + /*nothing*/ + } else { CL_SetStatInt(0, STAT_WEAPONFRAME, (bits & SU_WEAPONFRAME)?(unsigned char)MSG_ReadByte():0); @@ -2720,20 +2733,54 @@ void CLNQ_ParseClientdata (void) CL_SetStatInt(0, STAT_CELLS, MSG_ReadByte()); CL_SetStatInt(0, STAT_ACTIVEWEAPON, MSG_ReadByte()); + + if (cls.protocol_nq == CPNQ_FITZ666) + { +#define FITZSU_WEAPON2 (1<<16) // 1 byte, this is .weaponmodel & 0xFF00 (second byte) +#define FITZSU_ARMOR2 (1<<17) // 1 byte, this is .armorvalue & 0xFF00 (second byte) +#define FITZSU_AMMO2 (1<<18) // 1 byte, this is .currentammo & 0xFF00 (second byte) +#define FITZSU_SHELLS2 (1<<19) // 1 byte, this is .ammo_shells & 0xFF00 (second byte) +#define FITZSU_NAILS2 (1<<20) // 1 byte, this is .ammo_nails & 0xFF00 (second byte) +#define FITZSU_ROCKETS2 (1<<21) // 1 byte, this is .ammo_rockets & 0xFF00 (second byte) +#define FITZSU_CELLS2 (1<<22) // 1 byte, this is .ammo_cells & 0xFF00 (second byte) +#define FITZSU_WEAPONFRAME2 (1<<24) // 1 byte, this is .weaponframe & 0xFF00 (second byte) +#define FITZSU_WEAPONALPHA (1<<25) // 1 byte, this is alpha for weaponmodel, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT + if (bits & FITZSU_WEAPON2) + MSG_ReadByte(); + if (bits & FITZSU_ARMOR2) + MSG_ReadByte(); + if (bits & FITZSU_AMMO2) + MSG_ReadByte(); + if (bits & FITZSU_SHELLS2) + MSG_ReadByte(); + if (bits & FITZSU_NAILS2) + MSG_ReadByte(); + if (bits & FITZSU_ROCKETS2) + MSG_ReadByte(); + if (bits & FITZSU_CELLS2) + MSG_ReadByte(); + if (bits & FITZSU_WEAPONFRAME2) + MSG_ReadByte(); + if (bits & FITZSU_WEAPONALPHA) + MSG_ReadByte(); + } } - if (bits & DPSU_VIEWZOOM) + if (CPNQ_IS_DP || cls.protocol_nq == CPNQ_DP5) { - if (nq_dp_protocol >= 5) - i = (unsigned short) MSG_ReadShort(); + if (bits & DPSU_VIEWZOOM) + { + if (cls.protocol_nq) + i = (unsigned short) MSG_ReadShort(); + else + i = MSG_ReadByte(); + if (i < 2) + i = 2; + CL_SetStatInt(0, STAT_VIEWZOOM, i); + } else - i = MSG_ReadByte(); - if (i < 2) - i = 2; - CL_SetStatInt(0, STAT_VIEWZOOM, i); + CL_SetStatInt(0, STAT_VIEWZOOM, 255); } - else if (nq_dp_protocol < 6) - CL_SetStatInt(0, STAT_VIEWZOOM, 255); } #endif /* @@ -3105,6 +3152,28 @@ void CL_ParseBaseline2 (void) memcpy(cl_baselines + es.number, &es, sizeof(es)); } +void CLFitz_ParseBaseline2 (entity_state_t *es) +{ + int i; + int bits; + + memcpy(es, &nullentitystate, sizeof(entity_state_t)); + + bits = MSG_ReadByte(); + es->modelindex = (bits & FITZB_LARGEMODEL) ? MSG_ReadShort() : MSG_ReadByte(); + es->frame = (bits & FITZB_LARGEFRAME) ? MSG_ReadShort() : MSG_ReadByte(); + es->colormap = MSG_ReadByte(); + es->skinnum = MSG_ReadByte(); + + for (i=0 ; i<3 ; i++) + { + es->origin[i] = MSG_ReadCoord (); + es->angles[i] = MSG_ReadAngle (); + } + + es->trans = (bits & FITZB_ALPHA) ? MSG_ReadByte() : 255; +} + void CLQ2_Precache_f (void) { Model_CheckDownloads(); @@ -3157,15 +3226,17 @@ void CL_ParseStatic (int version) cl.num_statics++; } - if (i >= MAX_STATIC_ENTITIES) + if (i == cl_max_static_entities) { - cl.num_statics--; - Con_Printf ("Too many static entities"); - return; + cl_max_static_entities += 16; + cl_static_entities = BZ_Realloc(cl_static_entities, sizeof(*cl_static_entities)*cl_max_static_entities); } + + cl_static_entities[i].mdlidx = es.modelindex; + cl_static_entities[i].emit = NULL; + ent = &cl_static_entities[i].ent; memset(ent, 0, sizeof(*ent)); - cl_static_entities[i].emit = NULL; ent->keynum = es.number; @@ -3192,13 +3263,14 @@ void CL_ParseStatic (int version) AngleVectors(es.angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); - if (!cl.worldmodel) + if (!cl.worldmodel || cl.worldmodel->needload) { Con_TPrintf (TLC_PARSESTATICWITHNOMAP); return; } if (ent->model) { + /*FIXME: compensate for angle*/ VectorAdd(es.origin, ent->model->mins, mins); VectorAdd(es.origin, ent->model->maxs, maxs); cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &cl_static_entities[i].pvscache, mins, maxs); @@ -3366,11 +3438,6 @@ void CLQ2_ParseStartSoundPacket(void) #endif #if defined(NQPROT) || defined(PEXT_SOUNDDBL) -#define NQSND_VOLUME (1<<0) // a qbyte -#define NQSND_ATTENUATION (1<<1) // a qbyte -#define DPSND_LOOPING (1<<2) // a long, supposedly -#define DPSND_LARGEENTITY (1<<3) -#define DPSND_LARGESOUND (1<<4) void CLNQ_ParseStartSoundPacket(void) { vec3_t pos; @@ -4519,12 +4586,16 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n Cmd_TokenizeString(stufftext+7, false, false); for (i = 0; i < Cmd_Argc(); i++) { - mname = va("progs/%s.mdl", Cmd_Argv(i)); - Q_strncpyz(cl.model_name_vwep[i], mname, sizeof(cl.model_name_vwep[i])); - if (cls.state == ca_active) + mname = Cmd_Argv(i); + if (strcmp(mname, "-")) { - CL_CheckOrEnqueDownloadFile(mname, NULL, 0); - cl.model_precache_vwep[i] = Mod_ForName(mname, false); + mname = va("progs/%s.mdl", Cmd_Argv(i)); + Q_strncpyz(cl.model_name_vwep[i], mname, sizeof(cl.model_name_vwep[i])); + if (cls.state == ca_active) + { + CL_CheckOrEnqueDownloadFile(mname, NULL, 0); + cl.model_precache_vwep[i] = Mod_ForName(mname, false); + } } } } @@ -5640,7 +5711,7 @@ void CLNQ_ParseServerMessage (void) cl.gametime = MSG_ReadFloat(); cl.gametimemark = realtime; - if (nq_dp_protocol<5) + if (!CPNQ_IS_DP) { // cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities; cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.num_entities=0; @@ -5778,6 +5849,34 @@ void CLNQ_ParseServerMessage (void) V_ParseDamage (0); break; + case svcfitz_skybox: + { + extern cvar_t r_skyboxname; + Cvar_Set(&r_skyboxname, MSG_ReadString()); + } + break; + case svcfitz_bf: + Cmd_ExecuteString("bf", RESTRICT_RCON); + break; + case svcfitz_fog: + /*density =*/ MSG_ReadByte(); + /*red =*/ MSG_ReadByte(); + /*green =*/ MSG_ReadByte(); + /*blue =*/ MSG_ReadByte(); + /*time =*/ MSG_ReadShort(); + break; + case svcfitz_spawnbaseline2: + i = MSG_ReadShort (); + if (!CL_CheckBaselines(i)) + Host_EndGame("CLNQ_ParseServerMessage: svcfitz_spawnbaseline2 failed with ent %i", i); + CLFitz_ParseBaseline2 (cl_baselines + i); + break; +// case svcfitz_spawnstatic2: +// break; +// case svcfitz_spawnstaticsound2: +// break; + + case svcnq_effect: CL_ParseEffect(false); break; diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 1ed2c9adb..24d170ccb 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -363,7 +363,8 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user extern vec3_t player_mins; extern vec3_t player_maxs; // split up very long moves - if (u->msec > 50) { + if (u->msec > 50) + { player_state_t temp; usercmd_t split; @@ -414,10 +415,10 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user } else { - VectorCopy(cl.worldmodel->hulls[pmove.hullnum].clip_mins, player_mins); - VectorCopy(cl.worldmodel->hulls[pmove.hullnum].clip_maxs, player_maxs); + VectorCopy(cl.worldmodel->hulls[pmove.hullnum&(MAX_MAP_HULLSM-1)].clip_mins, player_mins); + VectorCopy(cl.worldmodel->hulls[pmove.hullnum&(MAX_MAP_HULLSM-1)].clip_maxs, player_maxs); } - if (DEFAULT_VIEWHEIGHT > player_maxs[2]) + if (pmove.hullnum & 128) { //this hack is for hexen2. player_maxs[2] -= player_mins[2]; player_mins[2] = 0; @@ -457,7 +458,7 @@ void CL_CatagorizePosition (int pnum) } //Smooth out stair step ups. //Called before CL_EmitEntities so that the player's lightning model origin is updated properly -void CL_CalcCrouch (int pnum) +void CL_CalcCrouch (int pnum, float stepchange) { qboolean teleported; static vec3_t oldorigin[MAX_SPLITS]; @@ -552,14 +553,16 @@ static void CL_LerpMove (int pnum, float msgtime) return; #endif - if (cls.netchan.outgoing_sequence < lastsequence) { + if (cls.netchan.outgoing_sequence < lastsequence) + { // reset lastsequence = -1; lerp_times[0] = -1; demo_latency = 0.01; } - if (cls.netchan.outgoing_sequence > lastsequence) { + if (cls.netchan.outgoing_sequence > lastsequence) + { lastsequence = cls.netchan.outgoing_sequence; // move along lerp_times[2] = lerp_times[1]; @@ -586,14 +589,18 @@ static void CL_LerpMove (int pnum, float msgtime) simtime = realtime - demo_latency; // adjust latency - if (simtime > lerp_times[0]) { + if (simtime > lerp_times[0]) + { // Com_DPrintf ("HIGH clamp\n"); demo_latency = realtime - lerp_times[0]; } - else if (simtime < lerp_times[2]) { + else if (simtime < lerp_times[2]) + { // Com_DPrintf (" low clamp\n"); demo_latency = realtime - lerp_times[2]; - } else { + } + else + { // drift towards ideal latency float ideal_latency = (lerp_times[0] - lerp_times[2]) * 0.6; if (demo_latency > ideal_latency) @@ -601,10 +608,13 @@ static void CL_LerpMove (int pnum, float msgtime) } // decide where to lerp from - if (simtime > lerp_times[1]) { + if (simtime > lerp_times[1]) + { from = 1; to = 0; - } else { + } + else + { from = 2; to = 1; } @@ -727,6 +737,7 @@ void CL_PredictMovePNum (int pnum) //these are to make svc_viewentity work better float *vel; float *org; + float stepheight = 0; cl.nolocalplayer[pnum] = false; @@ -796,42 +807,7 @@ void CL_PredictMovePNum (int pnum) vel = vec3_origin; goto fixedorg; } - -/* entity_state_t *CL_FindOldPacketEntity(int num); - entity_state_t *CL_FindPacketEntity(int num); - entity_state_t *state; - state = CL_FindPacketEntity (cl.viewentity[pnum]); - if (state && state->number < cl.maxlerpents) - { - float f; - extern cvar_t cl_nolerp; - - //figure out the lerp factor - if (cl.lerpents[state->number].lerprate<=0) - f = 0; - else - f = (cl.gametime-cl.servertime)/(cl.gametime-cl.oldgametime);//f = (cl.time-cl.lerpents[state->number].lerptime)/cl.lerpents[state->number].lerprate; - if (f<0) - f=0; - if (f>1) - f=1; - f = 1-f; -// Con_Printf("%f\n", f); - -// if (cl_nolerp.ival) -// f = 1; - - - // calculate origin - for (i=0 ; i<3 ; i++) - lrp[i] = cl.lerpents[state->number].origin[i] + - f * (state->origin[i] - cl.lerpents[state->number].origin[i]); - - org = lrp; - - goto fixedorg; - } -*/ } + } #endif if (!from->playerstate[cl.playernum[pnum]].messagenum) { @@ -925,6 +901,7 @@ fixedorg: cl.onground[pnum] = pmove.onground; } + stepheight = to->playerstate[cl.playernum[pnum]].origin[2] - from->playerstate[cl.playernum[pnum]].origin[2]; } pmove.numphysent = oldphysent; @@ -972,7 +949,7 @@ fixedorg: CL_LerpMove (pnum, to->senttime); out: - CL_CalcCrouch (pnum); + CL_CalcCrouch (pnum, stepheight); cl.waterlevel[pnum] = pmove.waterlevel; } diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 27f730339..1208c8d09 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -445,18 +445,20 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p) p->erase_center = 0; + if (p->flags & CPRINT_BACKGROUND) + { //hexen2 style plaque. + int lines, len; + if (rect->width > 320) + { + rect->x = (rect->x + rect->width/2) - 160; + rect->width = 320; + } + } + Font_BeginString(font_conchar, rect->x, rect->y, &left, &top); Font_BeginString(font_conchar, rect->x+rect->width, rect->y+rect->height, &right, &bottom); linecount = Font_LineBreaks(p->string, p->string + p->charcount, right - left, MAX_CPRINT_LINES, line_start, line_end); - if (p->flags & CPRINT_BACKGROUND) - { //hexen2 style plaque. -// int lines, len; -// SCR_CenterPrintBreaks(start, &lines, &len); -// x = rect.x+(rect.width-len*8)/2; -// Draw_TextBox(x-6, y-8, len-1, lines); - } - if (p->flags & CPRINT_TALIGN) y = top; else if (p->flags & CPRINT_BALIGN) @@ -479,6 +481,13 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p) y = (bottom-top - Font_CharHeight()*linecount) * 0.5 + top; } } + + if (p->flags & CPRINT_BACKGROUND) + { //hexen2 style plaque. + x = rect->x+(rect->width-320)/2; + Draw_TextBox(x-6, y-8, 320/8-1, linecount); + } + for (l = 0; l < linecount; l++, y += Font_CharHeight()) { if (p->flags & CPRINT_RALIGN) @@ -1060,7 +1069,10 @@ Keybinding command */ void SCR_SizeUp_f (void) { - Cvar_SetValue (&scr_viewsize,scr_viewsize.value+10); + if (Cmd_FromGamecode()) + Cvar_ForceSet(&scr_viewsize,va("%i", scr_viewsize.ival+10)); + else + Cvar_SetValue (&scr_viewsize,scr_viewsize.value+10); } @@ -1073,7 +1085,10 @@ Keybinding command */ void SCR_SizeDown_f (void) { - Cvar_SetValue (&scr_viewsize,scr_viewsize.value-10); + if (Cmd_FromGamecode()) + Cvar_ForceSet(&scr_viewsize,va("%i", scr_viewsize.ival-10)); + else + Cvar_SetValue (&scr_viewsize,scr_viewsize.value-10); } //============================================================================ @@ -1228,7 +1243,11 @@ void SCR_DrawFPS (void) #ifdef GLQUAKE case 5: if (qrenderer == QR_OPENGL) - GLR_FrameTimeGraph((int)(1000.0*1.5*host_frametime)); + GLR_FrameTimeGraph((int)(1000.0*2*host_frametime)); + break; + case 7: + if (qrenderer == QR_OPENGL) + GLR_FrameTimeGraph((int)(1000.0*1*host_frametime)); break; #endif case 6: diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index fce595deb..55874308f 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -2861,10 +2861,13 @@ void CL_UpdateExplosions (void) AngleVectors(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); ent->model = ex->model; - ent->framestate.g[FS_REG].frame[0] = (int)f+firstframe; - ent->framestate.g[FS_REG].frame[1] = of+firstframe; - ent->framestate.g[FS_REG].lerpfrac = 1-(f - (int)f); - ent->shaderRGBAf[3] = 1.0 - f/(numframes); + ent->framestate.g[FS_REG].frame[1] = (int)f+firstframe; + ent->framestate.g[FS_REG].frame[0] = of+firstframe; + ent->framestate.g[FS_REG].lerpfrac = (f - (int)f); + if (ent->model->type == mod_sprite) + ent->shaderRGBAf[3] = 1; + else + ent->shaderRGBAf[3] = 1.0 - f/(numframes); ent->flags = ex->flags; } diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 73c866a87..ed555cb69 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -601,7 +601,6 @@ void VQ3_RenderView(const q3refdef_t *ref) #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { - gl_ztrickdisabled|=16; qglDisable(GL_ALPHA_TEST); qglDisable(GL_BLEND); } @@ -610,7 +609,6 @@ void VQ3_RenderView(const q3refdef_t *ref) #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { - gl_ztrickdisabled&=~16; GL_Set2D (); qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_TexEnv(GL_MODULATE); diff --git a/engine/client/client.h b/engine/client/client.h index 447dc99dc..101ebd487 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -263,6 +263,7 @@ typedef struct dlight_s unsigned int flags; //the following are used for rendering (client code should clear on create) + qboolean rebuildcache; struct shadowmesh_s *worldshadowmesh; texid_t stexture; struct { @@ -315,6 +316,7 @@ typedef struct // connection information cactive_t state; + /*Specifies which protocol family we're speaking*/ enum { CP_UNKNOWN, CP_QUAKEWORLD, @@ -324,6 +326,25 @@ typedef struct CP_PLUGIN } protocol; + /*QuakeWorld protocol flags*/ +#ifdef PROTOCOLEXTENSIONS + unsigned long fteprotocolextensions; + unsigned long fteprotocolextensions2; +#endif + unsigned long z_ext; + + /*NQ Protocol flags*/ + enum + { + CPNQ_ID, + CPNQ_FITZ666, + CPNQ_DP5, + CPNQ_DP6, + CPNQ_DP7 + } protocol_nq; + #define CPNQ_IS_DP (cls.protocol_nq >= CPNQ_DP5) + + qboolean resendinfo; qboolean findtrack; @@ -397,11 +418,6 @@ typedef struct float maxfps; //server capped enum {GAME_DEATHMATCH, GAME_COOP} gamemode; -#ifdef PROTOCOLEXTENSIONS - unsigned long fteprotocolextensions; - unsigned long fteprotocolextensions2; -#endif - unsigned long z_ext; #ifdef NQPROT int signon; #endif @@ -412,8 +428,6 @@ typedef struct extern client_static_t cls; -extern int nq_dp_protocol; - typedef struct downloadlist_s { char rname[128]; char localname[128]; @@ -695,20 +709,20 @@ extern cvar_t ruleset_allow_sensative_texture_replacements; extern cvar_t ruleset_allow_localvolume; extern cvar_t ruleset_allow_shaders; -#define MAX_STATIC_ENTITIES 256 // torches, etc - extern client_state_t cl; typedef struct { entity_t ent; trailstate_t *emit; + int mdlidx; /*negative are csqc indexes*/ pvscache_t pvscache; } static_entity_t; // FIXME, allocate dynamically extern entity_state_t *cl_baselines; -extern static_entity_t cl_static_entities[MAX_STATIC_ENTITIES]; +extern static_entity_t *cl_static_entities; +extern unsigned int cl_max_static_entities; extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; extern dlight_t *cl_dlights; extern unsigned int cl_maxdlights; @@ -820,6 +834,7 @@ void CL_UpdateTEnts (void); void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end); void CL_ClearState (void); +void CLQ2_ClearState(void); void CL_ReadPackets (void); void CL_ClampPitch (int pnum); diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index 0b5888093..2d2b770e0 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -113,6 +113,11 @@ entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES]; void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs); void CL_SmokeAndFlash(vec3_t origin); +void CLQ2_ClearState(void) +{ + memset(cl_entities, 0, sizeof(cl_entities)); +} + //extern struct model_s *cl_mod_powerscreen; //PGM @@ -894,7 +899,7 @@ void CLQ2_ParsePacketEntities (q2frame_t *oldframe, q2frame_t *newframe) while (oldnum < newnum) { // one or more entities from the old packet are unchanged - if (cl_shownet.value == 3) + if (cl_shownet.ival == 3) Con_Printf (" unchanged: %i\n", oldnum); CLQ2_DeltaEntity (newframe, oldnum, oldstate, 0); @@ -911,7 +916,7 @@ void CLQ2_ParsePacketEntities (q2frame_t *oldframe, q2frame_t *newframe) if (bits & Q2U_REMOVE) { // the entity present in oldframe is not in the current frame - if (cl_shownet.value == 3) + if (cl_shownet.ival == 3) Con_Printf (" remove: %i\n", newnum); if (oldnum != newnum) Con_Printf ("U_REMOVE: oldnum != newnum\n"); @@ -930,7 +935,7 @@ void CLQ2_ParsePacketEntities (q2frame_t *oldframe, q2frame_t *newframe) if (oldnum == newnum) { // delta from previous state - if (cl_shownet.value == 3) + if (cl_shownet.ival == 3) Con_Printf (" delta: %i\n", newnum); CLQ2_DeltaEntity (newframe, newnum, oldstate, bits); @@ -948,7 +953,7 @@ void CLQ2_ParsePacketEntities (q2frame_t *oldframe, q2frame_t *newframe) if (oldnum > newnum) { // delta from baseline - if (cl_shownet.value == 3) + if (cl_shownet.ival == 3) Con_Printf (" baseline: %i\n", newnum); CLQ2_DeltaEntity (newframe, newnum, &cl_entities[newnum].baseline, bits); continue; @@ -959,7 +964,7 @@ void CLQ2_ParsePacketEntities (q2frame_t *oldframe, q2frame_t *newframe) // any remaining entities in the old frame are copied over while (oldnum != 99999) { // one or more entities from the old packet are unchanged - if (cl_shownet.value == 3) + if (cl_shownet.ival == 3) Con_Printf (" unchanged: %i\n", oldnum); CLQ2_DeltaEntity (newframe, oldnum, oldstate, 0); @@ -2070,25 +2075,12 @@ void CLQ2_AddEntities (void) else cl.lerpfrac = 1.0 - (cl.q2frame.servertime - cl.time*1000) * 0.01; -// if (cl_timedemo.value) -// cl.lerpfrac = 1.0; - -// CLQ2_AddPacketEntities (&cl.qwframe); -// CLQ2_AddTEnts (); -// CLQ2_AddParticles (); -// CLQ2_AddDLights (); -// CLQ2_AddLightStyles (); - CLQ2_CalcViewValues (); - // PMM - moved this here so the heat beam has the right values for the vieworg, and can lock the beam to the gun CLQ2_AddPacketEntities (&cl.q2frame); #if 0 CLQ2_AddProjectiles (); #endif CL_UpdateTEnts (); -// CLQ2_AddParticles (); -// CLQ2_AddDLights (); -// CLQ2_AddLightStyles (); } void CL_GetNumberedEntityInfo (int num, float *org, float *ang) diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index ad7f5932a..31293efa8 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -623,7 +623,7 @@ void CLQ3_ParseServerMessage (void) Con_TPrintf (TLC_LINEBREAK_MINUS); net_message.packing = SZ_RAWBYTES; - MSG_BeginReading(); + MSG_BeginReading(msg_nullnetprim); ccs.serverMessageNum = MSG_ReadLong(); net_message.packing = SZ_HUFFMAN; //the rest is huffman compressed. net_message.currentbit = msg_readcount*8; diff --git a/engine/client/image.c b/engine/client/image.c index 769ff568b..5433a6c20 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -1951,6 +1951,44 @@ qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, char *fn return NULL; } +static struct +{ + char *name; + int enabled; +} tex_extensions[] = +{//reverse order of preference - (match commas with optional file types) + {".pcx", 1}, //pcxes are the original gamedata of q2. So we don't want them to override pngs. +#ifdef AVAIL_JPEGLIB + {".jpg", 1}, //q3 uses some jpegs, for some reason +#endif + {".bmp", 0}, //wtf? at least not lossy +#ifdef AVAIL_PNGLIB + {".png", 1}, //pngs, fairly common, but slow +#endif + {".tga", 1}, //fairly fast to load +#ifdef DDS + {".dds", 1}, //compressed or something +#endif + {"", 1} //someone forgot an extension +}; + +static struct +{ + int args; + char *path; + + int enabled; +} tex_path[] = +{ + /*if three args, first is the subpath*/ + /*the last two args are texturename then extension*/ + {2, "%s%s", 1}, /*directly named texture*/ + {3, "textures/%s/%s%s", 1}, /*fuhquake compatibility*/ + {3, "%s/%s%s", 1}, /*fuhquake compatibility*/ + {2, "textures/%s%s", 1}, /*directly named texture with textures/ prefix*/ + {2, "override/%s%s", 1} /*tenebrae compatibility*/ +}; + int image_width, image_height; qbyte *COM_LoadFile (char *path, int usehunk); //fixme: should probably get rid of the 'Mod' prefix, and use something more suitable. @@ -1962,31 +2000,6 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags) // int h; char fname[MAX_QPATH], nicename[MAX_QPATH]; - static char *extensions[] = - {//reverse order of preference - (match commas with optional file types) - ".pcx", //pcxes are the original gamedata of q2. So we don't want them to override pngs. -#ifdef AVAIL_JPEGLIB - ".jpg", -#endif - ".bmp", -#ifdef AVAIL_PNGLIB - ".png", -#endif - ".tga", - "" - }; - - static char *path[] = - { - /*if three args, first is the subpath*/ - /*the last two args are texturename then extension*/ - "2%s%s", - "3textures/%s/%s%s", - "3%s/%s%s", - "2textures/%s%s", - "2override/%s%s" - }; - int i, e; image_width = 0; @@ -2020,39 +2033,34 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags) i = 1; //should write this nicer. - for (; i < sizeof(path)/sizeof(char *); i++) + for (; i < sizeof(tex_path)/sizeof(tex_path[0]); i++) { -#ifdef DDS - if (path[i][0] >= '3') + if (!tex_path[i].enabled) + continue; + for (e = sizeof(tex_extensions)/sizeof(tex_extensions[0])-1; e >=0 ; e--) { - if (!subpath) - continue; - snprintf(fname, sizeof(fname)-1, path[i]+1, subpath, /*COM_SkipPath*/(nicename), ".dds"); - } - else - snprintf(fname, sizeof(fname)-1, path[i]+1, nicename, ".dds"); - if ((buf = COM_LoadFile (fname, 5))) - { - tex = GL_LoadTextureDDS(buf, com_filesize); - BZ_Free(buf); - if (TEXVALID(tex)) - return tex; - } -#endif + if (!tex_extensions[e].enabled) + continue; - for (e = sizeof(extensions)/sizeof(char *)-1; e >=0 ; e--) - { - if (path[i][0] >= '3') + if (tex_path[i].args >= 3) { if (!subpath) continue; - snprintf(fname, sizeof(fname)-1, path[i]+1, subpath, /*COM_SkipPath*/(nicename), extensions[e]); + snprintf(fname, sizeof(fname)-1, tex_path[i].path, subpath, nicename, tex_extensions[e].name); } else - snprintf(fname, sizeof(fname)-1, path[i]+1, nicename, extensions[e]); + snprintf(fname, sizeof(fname)-1, tex_path[i].path, nicename, tex_extensions[e].name); TRACE(("dbg: Mod_LoadHiResTexture: trying %s\n", fname)); if ((buf = COM_LoadFile (fname, 5))) { +#ifdef DDS + tex = GL_LoadTextureDDS(buf, com_filesize); + if (TEXVALID(tex)) + { + BZ_Free(buf); + return tex; + } +#endif if ((data = Read32BitImageFile(buf, com_filesize, &image_width, &image_height, fname))) { extern cvar_t vid_hardwaregamma; @@ -2132,14 +2140,6 @@ texid_t R_LoadBumpmapTexture(char *name, char *subpath) "" }; - static char *path[] = - { - "%s%s", - "textures/%s/%s%s", //this is special... It's special name is Mr Ben Ian Graham Hacksworth. - "textures/%s%s", - "override/%s%s" - }; - int i, e; TRACE(("dbg: Mod_LoadBumpmapTexture: texture %s\n", name)); @@ -2160,23 +2160,20 @@ texid_t R_LoadBumpmapTexture(char *name, char *subpath) i = 1; //should write this nicer. - for (; i < sizeof(path)/sizeof(char *); i++) + for (; i < sizeof(tex_path)/sizeof(tex_path[0]); i++) { + if (!tex_path[i].enabled) + continue; for (e = sizeof(extensions)/sizeof(char *)-1; e >=0 ; e--) { - if (i == 1) + if (tex_path[i].args >= 3) { - char map [MAX_QPATH*2]; -#ifndef CLIENTONLY - if (*sv.name) //server loads before the client knows what's happening. I suppose we could have some sort of param... - Q_strncpyz(map, sv.name, sizeof(map)); - else -#endif - COM_FileBase(cl.model_name[1], map, sizeof(map)); - snprintf(fname, sizeof(fname)-1, path[i], map, nicename, extensions[e]); + if (!subpath) + continue; + snprintf(fname, sizeof(fname)-1, tex_path[i].path, subpath, nicename, extensions[e]); } else - snprintf(fname, sizeof(fname)-1, path[i], nicename, extensions[e]); + snprintf(fname, sizeof(fname)-1, tex_path[i].path, nicename, extensions[e]); TRACE(("dbg: Mod_LoadBumpmapTexture: opening %s\n", fname)); diff --git a/engine/client/m_items.c b/engine/client/m_items.c index a00a8c408..4cf20038c 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -106,7 +106,7 @@ void Draw_Hexen2BigFontString(int x, int y, const char *text) sy=-1; } if(sx>=0) - Draw_SubPic(x, y, 20, 20, p, sx, sy, 20*8, 20*8); + Draw_SubPic(x, y, 20, 20, p, sx, sy, 20*8, 20*4); x+=20; text++; } diff --git a/engine/client/m_master.c b/engine/client/m_master.c index bcec18ca9..dd96da4b6 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -85,7 +85,7 @@ static void NM_PrintWhite (int cx, int cy, qbyte *str) static void NM_PrintColoured (int cx, int cy, int colour, qbyte *str) { -#pragma message("needs reimplementing") +#pragma message("NM_PrintColoured: needs reimplementing") /* while (*str) { @@ -98,7 +98,7 @@ static void NM_PrintColoured (int cx, int cy, int colour, qbyte *str) static void NM_PrintHighlighted (int cx, int cy, int colour, int bg, qbyte *str) { -#pragma message("needs reimplementing") +#pragma message("NM_PrintHighlighted: needs reimplementing") /* while (*str) { @@ -258,7 +258,7 @@ int M_AddColumn (int right, int y, char *text, int maxchars, int colour, int hig right = left; -#pragma message("needs reimplementing") +#pragma message("M_AddColumn: needs reimplementing") /* if (highlight >= 0) { diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 31641a974..d5d72ffc6 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -920,7 +920,7 @@ void M_Menu_Textures_f (void) extern cvar_t r_bloom_sample_size, r_bloom_darken, r_bloom_intensity, r_bloom_diamond_size, r_bloom_alpha, r_bloom_fast_sample; #endif - extern cvar_t r_bloom, gl_load24bit, gl_specular, r_waterlayers, gl_bump, gl_detail, gl_detailscale, gl_compress, gl_savecompressedtex, gl_ztrick, gl_triplebuffer, gl_picmip, gl_picmip2d, gl_playermip, gl_max_size, r_stains, r_bloodstains, r_stainfadetime, r_stainfadeammount, gl_skyboxdist, r_drawflat, gl_schematics, gl_texturemode, gl_texture_anisotropic_filtering; + extern cvar_t r_bloom, gl_load24bit, gl_specular, r_waterlayers, gl_bump, gl_detail, gl_detailscale, gl_compress, gl_savecompressedtex, gl_triplebuffer, gl_picmip, gl_picmip2d, gl_playermip, gl_max_size, r_stains, r_bloodstains, r_stainfadetime, r_stainfadeammount, gl_skyboxdist, r_drawflat, gl_schematics, gl_texturemode, gl_texture_anisotropic_filtering; int y; menu_t *menu = M_Options_Title(&y, sizeof(*info)); info = menu->data; @@ -1029,7 +1029,6 @@ void M_Menu_Textures_f (void) MC_AddSlider(menu, 16, y, " Texture Detail Scale", &gl_detailscale,0,10,1); y+=8; MC_AddCheckBox(menu, 16, y, " Texture Compression", &gl_compress,0); y+=8; MC_AddCheckBox(menu, 16, y, "Save Compressed Textures", &gl_savecompressedtex,0); y+=8; - MC_AddCheckBox(menu, 16, y, " Z Trick", &gl_ztrick,0); y+=8; MC_AddCheckBox(menu, 16, y, " Triple Buffering", &gl_triplebuffer,0); y+=8; MC_AddSlider(menu, 16, y, " 3D Texture Picmip", &gl_picmip,0,16,1); y+=8; MC_AddSlider(menu, 16, y, " 2D Texture Picmip", &gl_picmip2d,0,16,1); y+=8; diff --git a/engine/client/m_single.c b/engine/client/m_single.c index 7167c2fac..bbfc1da44 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -164,9 +164,18 @@ void M_Menu_SinglePlayer_f (void) } else if (mgt == MGT_HEXEN2) { //h2 + int y; cvar_t *pc; + qboolean havemp; static char *classlist[] = { "Random", + "Paladin", + "Crusader", + "Necromancer", + "Assasin", + NULL + }; + static char *classlistmp[] = { "Paladin", "Crusader", "Necromancer", @@ -183,21 +192,34 @@ void M_Menu_SinglePlayer_f (void) "5", NULL }; + havemp = COM_FCheckExists("maps/keep1.bsp"); menu = M_CreateMenu(0); MC_AddPicture(menu, 16, 0, 35, 176, "gfx/menu/hplaque.lmp"); MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title1.lmp"); - menu->selecteditem = (menuoption_t*) - MC_AddConsoleCommand (menu, 64, 64, "Easy", "closemenu\nskill 0;deathmatch 0; coop 0;map demo1\n"); - MC_AddConsoleCommand (menu, 64, 72, "Medium", "closemenu\nskill 1;deathmatch 0; coop 0;map demo1\n"); - MC_AddConsoleCommand (menu, 64, 80, "Hard", "closemenu\nskill 2;deathmatch 0; coop 0;map demo1\n"); - - MC_AddConsoleCommand (menu, 64, 96, "Load Game", "menu_load\n"); - MC_AddConsoleCommand (menu, 64, 104, "Save Game", "menu_save\n"); + y = 64-8; pc = Cvar_Get("cl_playerclass", "1", CVAR_USERINFO|CVAR_ARCHIVE, "Hexen2"); if (pc) - MC_AddCvarCombo (menu, 64, 104+16, "Player class", pc, (const char **)classlist, (const char **)classvalues); + MC_AddCvarCombo (menu, 64, y+=8, "Player class", pc, havemp?(const char **)classlistmp:(const char **)classlist, (const char **)(classvalues+havemp)); + y+=8; + + menu->selecteditem = (menuoption_t*) + MC_AddConsoleCommand (menu, 64, y+=8, "Classic: Easy", "closemenu\nskill 0;deathmatch 0; coop 0;disconnect;wait;map demo1\n"); + MC_AddConsoleCommand (menu, 64, y+=8, "Classic: Medium", "closemenu\nskill 1;deathmatch 0; coop 0;disconnect;wait;map demo1\n"); + MC_AddConsoleCommand (menu, 64, y+=8, "Classic: Hard", "closemenu\nskill 2;deathmatch 0; coop 0;disconnect;wait;map demo1\n"); + y+=8; + + if (havemp) + { + MC_AddConsoleCommand(menu, 64, y+=8, "Expansion: Easy", "closemenu\nskill 0;deathmatch 0; coop 0;disconnect;wait;map keep1\n"); + MC_AddConsoleCommand(menu, 64, y+=8, "Expansion: Medium", "closemenu\nskill 1;deathmatch 0; coop 0;disconnect;wait;map keep1\n"); + MC_AddConsoleCommand(menu, 64, y+=8, "Expansion: Hard", "closemenu\nskill 2;deathmatch 0; coop 0;disconnect;wait;map keep1\n"); + y+=8; + } + + MC_AddConsoleCommand (menu, 64, y+=8, "Load Game", "menu_load\n"); + MC_AddConsoleCommand (menu, 64, y+=8, "Save Game", "menu_save\n"); return; } diff --git a/engine/client/modelgen.h b/engine/client/modelgen.h index f15d7adb7..44c52bd92 100644 --- a/engine/client/modelgen.h +++ b/engine/client/modelgen.h @@ -57,25 +57,6 @@ typedef enum { ALIAS_SINGLE=0, ALIAS_GROUP, ALIAS_GROUP_SWAPPED=16777216 } alias typedef enum { ALIAS_SKIN_SINGLE=0, ALIAS_SKIN_GROUP } aliasskintype_t; -typedef struct { - int ident; - int version; - vec3_t scale; - vec3_t scale_origin; - float boundingradius; - vec3_t eyeposition; - int numskins; - int skinwidth; - int skinheight; - int numverts; - int numstverts; - int numtris; - int numframes; - synctype_t synctype; - int flags; - float size; -} mmdl_t; - typedef struct { int ident; int version; @@ -90,8 +71,12 @@ typedef struct { int numtris; int numframes; synctype_t synctype; +//qtest stops here int flags; float size; +//quake stops here + int num_st; +//rapo stops here } dmdl_t; // TODO: could be shorts @@ -112,6 +97,12 @@ typedef struct dtriangle_s { int vertindex[3]; } dtriangle_t; +typedef struct dh2triangle_s { + int facesfront; + unsigned short vertindex[3]; + unsigned short stindex[3]; +} dh2triangle_t; + typedef struct dmd2triangle_s { short xyz_index[3]; short st_index[3]; @@ -165,7 +156,8 @@ typedef struct { aliasskintype_t type; } daliasskintype_t; -#define IDPOLYHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I') -#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I') - // little-endian "IDPO" +#define IDPOLYHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I') /*little-endian "IDPO"*/ +#define RAPOLYHEADER (('O'<<24)+('P'<<16)+('A'<<8)+'R') /*used by hexen2 mp*/ +#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I') /*quake3, duh*/ + diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 6fcbbec3d..8429be9fd 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -902,7 +902,7 @@ int NET_CheckPollSockets(void) int c; char *s; - MSG_BeginReading (); + MSG_BeginReading (msg_nullnetprim); MSG_ReadLong (); // skip the -1 c = msg_readcount; @@ -995,7 +995,7 @@ int NET_CheckPollSockets(void) int control; - MSG_BeginReading (); + MSG_BeginReading (msg_nullnetprim); control = BigLong(*((int *)net_message.data)); MSG_ReadLong(); if (control == -1) diff --git a/engine/client/p_null.c b/engine/client/p_null.c index 30892db57..ff671835b 100644 --- a/engine/client/p_null.c +++ b/engine/client/p_null.c @@ -31,7 +31,7 @@ static void PNULL_RunParticleEffect4 (vec3_t org, float radius, int color, int e static void PNULL_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk){} static void PNULL_EmitSkyEffectTris(model_t *mod, msurface_t *fa){} -static int PNULL_InitParticles (void) +static qboolean PNULL_InitParticles (void) { CL_RegisterParticles(); return true; diff --git a/engine/client/p_script.c b/engine/client/p_script.c index f5649beae..aa2252304 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -134,6 +134,7 @@ typedef struct { float scalefactor; float invscalefactor; + float stretch; } plooks_t; //these could be deltas or absolutes depending on ramping mode. @@ -360,7 +361,8 @@ static part_type_t *P_GetParticleType(char *name) ptype = &part_type[numparticletypes++]; memset(ptype, 0, sizeof(*ptype)); strcpy(ptype->name, name); - ptype->assoc=P_INVALID; + ptype->assoc = P_INVALID; + ptype->inwater = P_INVALID; ptype->cliptype = P_INVALID; ptype->emit = P_INVALID; @@ -470,8 +472,13 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) if (qrenderer == QR_NONE) return; - /*try and load the shader, fail if we would need to generate one*/ - ptype->looks.shader = R_RegisterCustom(ptype->texname, NULL, NULL); + if (*ptype->texname) + { + /*try and load the shader, fail if we would need to generate one*/ + ptype->looks.shader = R_RegisterCustom(ptype->texname, NULL, NULL); + } + else + ptype->looks.shader = NULL; if (!ptype->looks.shader) { @@ -1410,6 +1417,8 @@ void FinishParticleType(part_type_t *ptype) /*too lazy to go through ramps*/ ptype->looks.scalefactor = 1; } + if (ptype->looks.type == PT_TEXTUREDSPARK) + ptype->looks.stretch *= 0.04; } static void P_ImportEffectInfo_f(void) @@ -1499,6 +1508,7 @@ static void P_ImportEffectInfo_f(void) ptype->looks.invscalefactor = 0; ptype->looks.type = PT_NORMAL; ptype->looks.blendmode = BM_BLEND; + ptype->looks.stretch = 1; } else if (!ptype) { @@ -1565,7 +1575,7 @@ static void P_ImportEffectInfo_f(void) ptype->t1 = 1/8.0 * (mini>>3); ptype->t2 = 1/8.0 * (1+(mini>>3)); ptype->texsstride = 1/8.0; - ptype->randsmax = (maxi - mini)+1; + ptype->randsmax = (maxi - mini); if (ptype->randsmax < 1) ptype->randsmax = 1; } @@ -1647,6 +1657,8 @@ static void P_ImportEffectInfo_f(void) ptype->randdie = atof(arg[1]) - ptype->die; } } + else if (!strcmp(arg[0], "stretchfactor") && args == 2) + ptype->looks.stretch = atof(arg[1]); #if 0 else if (!strcmp(arg[0], "blend") && args == 2) ; /*overrides blendmode*/ @@ -1656,8 +1668,6 @@ static void P_ImportEffectInfo_f(void) ; else if (!strcmp(arg[0], "lightcubemapnum") && args == 2) ; - else if (!strcmp(arg[0], "stretchfactor") && args == 2) - ; else if (!strcmp(arg[0], "staincolor") && args == 2) ; else if (!strcmp(arg[0], "stainalpha") && args == 2) @@ -3340,6 +3350,13 @@ static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype offs = ptype->texsstride * (rand()%ptype->randsmax); p->s1 += offs; p->s2 += offs; + while (p->s1 >= 1) + { + p->s1 -= 1; + p->s2 -= 1; + p->t1 += ptype->texsstride; + p->t2 += ptype->texsstride; + } } if (len < nrfirst || len >= nrlast) @@ -3613,7 +3630,7 @@ static void GL_DrawTexturedParticle(int count, particle_t **plist, plooks_t *typ } if (type->scalefactor == 1) - scale = p->scale; + scale = p->scale*0.25; else { scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] @@ -3783,17 +3800,24 @@ static void GL_DrawTexturedSparkParticle(int count, particle_t **plist, plooks_t Vector2Set(pscripttexcoords[pscriptmesh.numvertexes+3], p->s2, p->t1); + if (type->stretch) + { + VectorMA(p->org, type->stretch, p->vel, o2); + VectorMA(p->org, -type->stretch, p->vel, v); + VectorSubtract(r_refdef.vieworg, v, v); + } + else + { + VectorMA(p->org, 0.1, p->vel, o2); + VectorSubtract(r_refdef.vieworg, p->org, v); + } - VectorSubtract(r_refdef.vieworg, p->org, v); CrossProduct(v, p->vel, cr); VectorNormalize(cr); VectorMA(p->org, -p->scale/2, cr, pscriptverts[pscriptmesh.numvertexes+0]); VectorMA(p->org, p->scale/2, cr, pscriptverts[pscriptmesh.numvertexes+1]); - - VectorMA(p->org, 0.1, p->vel, o2); - VectorSubtract(r_refdef.vieworg, o2, v); CrossProduct(v, p->vel, cr); VectorNormalize(cr); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 7c6c156f6..a9804d366 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -763,19 +763,17 @@ static void PF_cs_makestatic (progfuncs_t *prinst, struct globalvars_s *pr_globa csqcedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0); entity_t *ent; - if (cl.num_statics >= MAX_STATIC_ENTITIES) + if (cl.num_statics == cl_max_static_entities) { - Con_Printf ("Too many static entities"); - - PF_cs_remove(prinst, pr_globals); - return; + cl_max_static_entities += 16; + cl_static_entities = BZ_Realloc(cl_static_entities, sizeof(*cl_static_entities) * cl_max_static_entities); } ent = &cl_static_entities[cl.num_statics].ent; if (CopyCSQCEdictToEntity(in, ent)) { - #pragma message("Link static entity") cl.num_statics++; + cl_static_entities[cl.num_statics].mdlidx = in->v->modelindex; } PF_cs_remove(prinst, pr_globals); @@ -1370,13 +1368,6 @@ static void PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s *pr_global if (cl.worldmodel) R_PushDlights (); -#ifdef GLQUAKE - if (qrenderer == QR_OPENGL) - { - gl_ztrickdisabled|=16; - } -#endif - r_refdef.currentplayernum = csqc_lplayernum; VectorCopy (r_refdef.vieworg, cl.viewent[csqc_lplayernum].origin); @@ -1387,7 +1378,6 @@ static void PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s *pr_global #ifdef GLQUAKE if (qrenderer == QR_OPENGL) { - gl_ztrickdisabled&=~16; GL_Set2D (); } #endif @@ -2281,18 +2271,18 @@ static void PF_cs_serverkey (progfuncs_t *prinst, struct globalvars_s *pr_global ret = "QuakeWorld"; break; case CP_NETQUAKE: - switch (nq_dp_protocol) + switch (cls.protocol_nq) { default: ret = "NetQuake"; break; - case 5: + case CPNQ_DP5: ret = "NetQuake DarkPlaces 5"; break; - case 6: + case CPNQ_DP6: ret = "NetQuake DarkPlaces 6"; break; - case 7: + case CPNQ_DP7: ret = "NetQuake DarkPlaces 7"; break; } @@ -5461,6 +5451,7 @@ qboolean CSQC_Init (unsigned int checksum) csqcmapentitydataloaded = true; csqcprogs = InitProgs(&csqcprogparms); csqc_world.progs = csqcprogs; + csqc_world.usesolidcorpse = true; PR_Configure(csqcprogs, -1, 16); csqc_world.worldmodel = cl.worldmodel; csqc_world.Event_Touch = CSQC_Event_Touch; diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 8c0154de1..8016fc404 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -339,6 +339,12 @@ void R2D_TileClear (int x, int y, int w, int h) void R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) { + if (qrenderer == QR_NONE) + { + conback = NULL; + return; + } + if (*var->string) conback = R_RegisterPic(var->string); if (!conback || !conback->width) @@ -346,7 +352,9 @@ void R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) conback = R_RegisterCustom("console", NULL, NULL); if (!conback) { - if (M_GameType() == MGT_QUAKE2) + if (M_GameType() == MGT_HEXEN2) + conback = R_RegisterPic("gfx/menu/conback.lmp"); + else if (M_GameType() == MGT_QUAKE2) conback = R_RegisterPic("pics/conback.pcx"); else conback = R_RegisterPic("gfx/conback.lmp"); @@ -358,6 +366,13 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue) { if (font_conchar) Font_Free(font_conchar); + + if (qrenderer == QR_NONE) + { + font_conchar = NULL; + return; + } + font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, var->string); if (!font_conchar && *var->string) font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, ""); diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index a9ea438e8..c4d279572 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "renderque.h" #include +extern cvar_t r_ambient; extern cvar_t gl_bump; static vec3_t modelorg; /*set before recursively entering the visible surface finder*/ @@ -42,11 +43,7 @@ texid_t *deluxmap_textures; #define MAX_LIGHTMAP_SIZE LMBLOCK_WIDTH vec3_t blocknormals[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; -unsigned blocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; -#ifdef PEXT_LIGHTSTYLECOL -unsigned greenblklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; -unsigned blueblklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; -#endif +unsigned blocklights[3*MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; lightmapinfo_t **lightmap; int numlightmaps; @@ -324,6 +321,7 @@ static void Surf_AddDynamicLights (msurface_t *surf) int smax, tmax; mtexinfo_t *tex; float a; + unsigned *bl; smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; @@ -360,6 +358,7 @@ static void Surf_AddDynamicLights (msurface_t *surf) a = 256*(cl_dlights[lnum].color[0]*1.5 + cl_dlights[lnum].color[1]*2.95 + cl_dlights[lnum].color[2]*0.55); + bl = blocklights; for (t = 0 ; t>1); if (dist < minlight) - blocklights[t*smax + s] += (rad - dist)*a; + bl[0] += (rad - dist)*a; + bl++; } } } @@ -466,6 +466,7 @@ static void Surf_AddDynamicLightsColours (msurface_t *surf) mtexinfo_t *tex; // float temp; float r, g, b; + unsigned *bl; smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; @@ -527,8 +528,9 @@ static void Surf_AddDynamicLightsColours (msurface_t *surf) } } else - { -*/ for (t = 0 ; t>1); if (dist < minlight) { - blocklights[t*smax + s] += (rad - dist)*r; - greenblklights[t*smax + s] += (rad - dist)*g; - blueblklights[t*smax + s] += (rad - dist)*b; + bl[0] += (rad - dist)*r; + bl[1] += (rad - dist)*g; + bl[2] += (rad - dist)*b; } + bl += 3; } } -// } + } } } #endif @@ -673,6 +676,251 @@ store: } } +enum lm_mode +{ + bgra4_os, + bgra4, + rgb3_os, + lum +}; +/*any sane compiler will inline and split this, removing the stainsrc stuff +just unpacks the internal lightmap block into texture info ready for upload +merges stains and oversaturates overbrights. +*/ +static void Surf_StoreLightmap(qbyte *dest, int smax, int tmax, unsigned int shift, enum lm_mode lm_mode, stmap *stainsrc) +{ + int r, g, b, t; + int cr, cg, cb; + unsigned int i, j; + unsigned int *bl; + int stride; + switch (lm_mode) + { + case bgra4_os: + stride = LMBLOCK_WIDTH*4 - (smax<<2); + + bl = blocklights; + + for (i=0 ; i> shift; + g = *bl++ >> shift; + b = *bl++ >> shift; + + if (stainsrc) // merge in stain + { + r = (127+r*(*stainsrc++)) >> 8; + g = (127+g*(*stainsrc++)) >> 8; + b = (127+b*(*stainsrc++)) >> 8; + } + + cr = 0; + cg = 0; + cb = 0; + + if (r > 255) //ak too much red + { + cr -= (255-r)/2; + cg += (255-r)/4; //reduce it, and indicate to drop the others too. + cb += (255-r)/4; + r = 255; + } + + if (g > 255) + { + cr += (255-g)/4; + cg -= (255-g)/2; + cb += (255-g)/4; + g = 255; + } + + if (b > 255) + { + cr += (255-b)/4; + cg += (255-b)/4; + cb -= (255-b)/2; + b = 255; + } + + r+=cr; + if (r > 255) + dest[2] = 255; + else if (r < 0) + dest[2] = 0; + else + dest[2] = r; + + g+=cg; + if (g > 255) + dest[1] = 255; + else if (g < 0) + dest[1] = 0; + else + dest[1] = g; + + b+=cb; + if (b > 255) + dest[0] = 255; + else if (b < 0) + dest[0] = 0; + else + dest[0] = b; + + dest[3] = 255; + dest += 4; + } + if (stainsrc) + stainsrc += (LMBLOCK_WIDTH - smax)*3; + } + break; + + case bgra4: + stride = LMBLOCK_WIDTH*4 - (smax<<2); + + bl = blocklights; + + for (i=0 ; i> shift; + g = *bl++ >> shift; + b = *bl++ >> shift; + + if (stainsrc) // merge in stain + { + r = (127+r*(*stainsrc++)) >> 8; + g = (127+g*(*stainsrc++)) >> 8; + b = (127+b*(*stainsrc++)) >> 8; + } + + if (r > 255) + dest[2] = 255; + else if (r < 0) + dest[2] = 0; + else + dest[2] = r; + + if (g > 255) + dest[1] = 255; + else if (g < 0) + dest[1] = 0; + else + dest[1] = g; + + if (b > 255) + dest[0] = 255; + else if (b < 0) + dest[0] = 0; + else + dest[0] = b; + + dest[3] = 255; + dest += 4; + } + if (stainsrc) + stainsrc += (LMBLOCK_WIDTH - smax)*3; + } + break; + + case rgb3_os: + stride = LMBLOCK_WIDTH*3 - (smax*3); + bl = blocklights; + + for (i=0 ; i> shift; + g = *bl++ >> shift; + b = *bl++ >> shift; + + if (stainsrc) // merge in stain + { + r = (127+r*(*stainsrc++)) >> 8; + g = (127+g*(*stainsrc++)) >> 8; + b = (127+b*(*stainsrc++)) >> 8; + } + + cr = 0; + cg = 0; + cb = 0; + + if (r > 255) //ak too much red + { + cr -= (255-r)/2; + cg += (255-r)/4; //reduce it, and indicate to drop the others too. + cb += (255-r)/4; + r = 255; + } + + if (g > 255) + { + cr += (255-g)/4; + cg -= (255-g)/2; + cb += (255-g)/4; + g = 255; + } + + if (b > 255) + { + cr += (255-b)/4; + cg += (255-b)/4; + cb -= (255-b)/2; + b = 255; + } + + r+=cr; + if (r > 255) + dest[0] = 255; + else if (r < 0) + dest[0] = 0; + else + dest[0] = (r+cr); + + g+=cg; + if (g > 255) + dest[1] = 255; + else if (g < 0) + dest[1] = 0; + else + dest[1] = g; + + b+=cb; + if (b > 255) + dest[2] = 255; + else if (b < 0) + dest[2] = 0; + else + dest[2] = b; + dest += 3; + } + if (stainsrc) + stainsrc += (LMBLOCK_WIDTH - smax)*3; + } + break; + case lum: + stride = LMBLOCK_WIDTH; + bl = blocklights; + for (i=0 ; i>= shift; + if (t > 255) + t = 255; + dest[j] = t; + } + } + break; + default: + Sys_Error ("Bad lightmap format"); + } +} + /* =============== R_BuildLightMap @@ -680,7 +928,7 @@ R_BuildLightMap Combine and scale multiple lightmaps into the 8.8 format in blocklights =============== */ -static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, stmap *stainsrc, int shift) +static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, stmap *stainsrc, int shift, int ambient) { int smax, tmax; int t; @@ -689,19 +937,11 @@ static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, unsigned scale; int maps; unsigned *bl; - qboolean isstained; - extern cvar_t r_ambient; extern cvar_t gl_lightmap_shift; -#ifdef PEXT_LIGHTSTYLECOL - unsigned *blg; - unsigned *blb; - int r, g, b; - int cr, cg, cb; -#endif int stride = LMBLOCK_WIDTH*lightmap_bytes; - if (!surf->samples && currentmodel->lightdata) + if (!surf->samples && currentmodel->lightdata && ambient >= 0) return; shift += 7; // increase to base value @@ -721,928 +961,239 @@ static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, if (currentmodel->deluxdata) Surf_BuildDeluxMap(surf, deluxdest); - #ifdef PEXT_LIGHTSTYLECOL if (lightmap_bytes == 4 || lightmap_bytes == 3) { // set to full bright if no light data - if (r_fullbright.value>0) //not qw + if (ambient < 0) { - for (i=0 ; icached_light[maps] = -1-ambient; + surf->cached_colour[maps] = 0xff; + } + } + else if (r_fullbright.value>0) //not qw + { + for (i=0 ; idlightframe == r_framecount) - Surf_AddDynamicLightsColours (surf); - } - goto store; } - if (!currentmodel->lightdata) + else if (!currentmodel->lightdata) { - for (i=0 ; idlightframe == r_framecount) - Surf_AddDynamicLightsColours (surf); - goto store; } - -// clear to no light - t = r_ambient.value*255; - for (i=0 ; ifromgame == fg_quake3) //rgb + if (lightmap) { - if (lightmap_bgra) + if (currentmodel->fromgame == fg_quake3) //rgb { - for (i = 0; i < tmax; i++) //q3 maps store their light in a block fashion, q1/q2/hl store it in a linear fashion. + /*q3 lightmaps are meant to be pre-built + this code is misguided, and ought never be executed anyway. + */ + bl = blocklights; + for (i = 0; i < tmax; i++) { for (j = 0; j < smax; j++) { - blocklights[i*smax+j] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3+2]; - greenblklights[i*smax+j] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3+1]; - blueblklights[i*smax+j] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3 ]; + bl[0] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3]; + bl[1] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3+1]; + bl[2] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3+2]; + bl+=3; } } } + else if (currentmodel->engineflags & MDLF_RGBLIGHTING) //rgb + { + for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; + maps++) + { + scale = d_lightstylevalue[surf->styles[maps]]; + surf->cached_light[maps] = scale; // 8.8 fraction + surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; + + if (scale) + { + if (cl_lightstyle[surf->styles[maps]].colour == 7) //hopefully a faster alternative. + { + bl = blocklights; + for (i=0 ; istyles[maps]].colour & 1) + for (i=0 ; istyles[maps]].colour & 2) + for (i=0 ; istyles[maps]].colour & 4) + for (i=0 ; istyles[maps] != 255 ; + maps++) { - for (j = 0; j < smax; j++) - { - blocklights[i*smax+j] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3]; - greenblklights[i*smax+j] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3+1]; - blueblklights[i*smax+j] = 255*lightmap[(i*LMBLOCK_WIDTH+j)*3+2]; - } - } - } - } - else if (currentmodel->engineflags & MDLF_RGBLIGHTING) //rgb - { - for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; - maps++) - { - scale = d_lightstylevalue[surf->styles[maps]]; - surf->cached_light[maps] = scale; // 8.8 fraction - surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; + scale = d_lightstylevalue[surf->styles[maps]]; + surf->cached_light[maps] = scale; // 8.8 fraction + surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; - if (lightmap_bgra) - { if (cl_lightstyle[surf->styles[maps]].colour == 7) //hopefully a faster alternative. { + bl = blocklights; for (i=0 ; istyles[maps]].colour & 1) - for (i=0 ; istyles[maps]].colour & 2) - for (i=0 ; istyles[maps]].colour & 4) - for (i=0 ; istyles[maps]].colour == 7) //hopefully a faster alternative. - { - for (i=0 ; istyles[maps]].colour & 1) - for (i=0 ; istyles[maps]].colour & 2) - for (i=0 ; istyles[maps]].colour & 4) - for (i=0 ; istyles[maps] != 255 ; - maps++) - { - scale = d_lightstylevalue[surf->styles[maps]]; - surf->cached_light[maps] = scale; // 8.8 fraction - surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; - - if (cl_lightstyle[surf->styles[maps]].colour == 7) //hopefully a faster alternative. - { - for (i=0 ; istyles[maps]].colour & 1) - for (i=0 ; istyles[maps]].colour & 2) - for (i=0 ; istyles[maps]].colour & 4) - for (i=0 ; idlightframe == r_framecount) Surf_AddDynamicLightsColours (surf); + + if (lightmap_bytes == 4) + { + if (lightmap_bgra) + { + if (!r_stains.value || !surf->stained) + Surf_StoreLightmap(dest, smax, tmax, shift, bgra4_os, NULL); + else + Surf_StoreLightmap(dest, smax, tmax, shift, bgra4_os, stainsrc); + } + else + { + /*if (!r_stains.value || !surf->stained) + Surf_StoreLightmap(dest, smax, tmax, shift, rgba4, NULL); + else + Surf_StoreLightmap(dest, smax, tmax, shift, rgba4, stainsrc); + */ + } + } + else if (lightmap_bytes == 3) + { + if (lightmap_bgra) + { + /* + if (!r_stains.value || !surf->stained) + Surf_StoreLightmap(dest, smax, tmax, shift, bgr3, NULL); + else + Surf_StoreLightmap(dest, smax, tmax, shift, bgr3, stainsrc); + */ + } + else + { + if (!r_stains.value || !surf->stained) + Surf_StoreLightmap(dest, smax, tmax, shift, rgb3_os, NULL); + else + Surf_StoreLightmap(dest, smax, tmax, shift, rgb3_os, stainsrc); + } + } } else - { #endif + { // set to full bright if no light data - if (r_fullbright.value || !currentmodel->lightdata) + if (r_fullbright.ival || !currentmodel->lightdata) { for (i=0 ; iengineflags & MDLF_RGBLIGHTING) //rgb - for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; - maps++) - { - scale = d_lightstylevalue[surf->styles[maps]]/3; - surf->cached_light[maps] = scale; // 8.8 fraction - surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; - for (i=0 ; istyles[maps] != 255 ; - maps++) - { - scale = d_lightstylevalue[surf->styles[maps]]; - surf->cached_light[maps] = scale; // 8.8 fraction - surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; - for (i=0 ; iengineflags & MDLF_RGBLIGHTING) //rgb + for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; + maps++) + { + scale = d_lightstylevalue[surf->styles[maps]]/3; + surf->cached_light[maps] = scale; // 8.8 fraction + surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; + for (i=0 ; istyles[maps] != 255 ; + maps++) + { + scale = d_lightstylevalue[surf->styles[maps]]; + surf->cached_light[maps] = scale; // 8.8 fraction + surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; + for (i=0 ; idlightframe == r_framecount) + Surf_AddDynamicLights (surf); } - // add all the dynamic lights - if (surf->dlightframe == r_framecount) - Surf_AddDynamicLights (surf); -#ifdef PEXT_LIGHTSTYLECOL + if (!r_stains.value || !surf->stained) + Surf_StoreLightmap(dest, smax, tmax, shift, lum, NULL); + else + Surf_StoreLightmap(dest, smax, tmax, shift, lum, stainsrc); } -#endif - -// bound, invert, and shift -store: -#ifdef INVERTLIGHTMAPS - switch (gl_lightmap_format) - { -#ifdef PEXT_LIGHTSTYLECOL - case GL_RGBA: - stride -= (smax<<2); - bl = blocklights; - blg = greenblklights; - blb = blueblklights; - - if (!r_stains.value) - isstained = false; - else - isstained = surf->stained; - -/* if (!gl_lightcomponantreduction.value) - { - for (i=0 ; i>= 7; - if (t > 255) - dest[0] = 0; - else if (t < 0) - dest[0] = 256; - else - dest[0] = (255-t); - - t = *blg++; - t >>= 7; - if (t > 255) - dest[1] = 0; - else if (t < 0) - dest[1] = 256; - else - dest[1] = (255-t); - - t = *blb++; - t >>= 7; - if (t > 255) - dest[2] = 0; - else if (t < 0) - dest[2] = 256; - else - dest[2] = (255-t); - - dest[3] = 0;//(dest[0]+dest[1]+dest[2])/3; - dest += 4; - } - } - } - else -*/ { - stmap *stain; - for (i=0 ; i>= shift; - g >>= shift; - b >>= shift; - - if (isstained) // merge in stain - { - r = (127+r*(*stain++)) >> 8; - g = (127+g*(*stain++)) >> 8; - b = (127+b*(*stain++)) >> 8; - } - - cr = 0; - cg = 0; - cb = 0; - - if (r > 255) //ak too much red - { - cr -= (255-r)/2; - cg += (255-r)/4; //reduce it, and indicate to drop the others too. - cb += (255-r)/4; - r = 255; - } -// else if (r < 0) -// r = 0; - - if (g > 255) - { - cr += (255-g)/4; - cg -= (255-g)/2; - cb += (255-g)/4; - g = 255; - } -// else if (g < 0) -// g = 0; - - if (b > 255) - { - cr += (255-b)/4; - cg += (255-b)/4; - cb -= (255-b)/2; - b = 255; - } -// else if (b < 0) -// b = 0; - //* - if ((r+cr) > 255) - dest[0] = 0; //inverse lighting - else if ((r+cr) < 0) - dest[0] = 255; - else - dest[0] = 255-(r+cr); - - if ((g+cg) > 255) - dest[1] = 0; - else if ((g+cg) < 0) - dest[1] = 255; - else - dest[1] = 255-(g+cg); - - if ((b+cb) > 255) - dest[2] = 0; - else if ((b+cb) < 0) - dest[2] = 255; - else - dest[2] = 255-(b+cb); -/*/ - if ((r+cr) > 255) - dest[0] = 255; //non-inverse lighting - else if ((r+cr) < 0) - dest[0] = 0; - else - dest[0] = (r+cr); - - if ((g+cg) > 255) - dest[1] = 255; - else if ((g+cg) < 0) - dest[1] = 0; - else - dest[1] = (g+cg); - - if ((b+cb) > 255) - dest[2] = 255; - else if ((b+cb) < 0) - dest[2] = 0; - else - dest[2] = (b+cb); -*/ - - - - dest[3] = (dest[0]+dest[1]+dest[2])/3; //alpha?!?! - dest += 4; - } - } - } - break; - - case GL_RGB: - stride -= smax*3; - bl = blocklights; - blg = greenblklights; - blb = blueblklights; - - if (!r_stains.value) - isstained = false; - else - isstained = surf->stained; - -/* if (!gl_lightcomponantreduction.value) - { - for (i=0 ; i>= 7; - if (t > 255) - dest[0] = 0; - else if (t < 0) - dest[0] = 256; - else - dest[0] = (255-t); - - t = *blg++; - t >>= 7; - if (t > 255) - dest[1] = 0; - else if (t < 0) - dest[1] = 256; - else - dest[1] = (255-t); - - t = *blb++; - t >>= 7; - if (t > 255) - dest[2] = 0; - else if (t < 0) - dest[2] = 256; - else - dest[2] = (255-t); - - dest += 3; - } - } - } - else -*/ { - stmap *stain; - for (i=0 ; i>= shift; - g >>= shift; - b >>= shift; - - if (isstained) // merge in stain - { - r = (127+r*(*stain++)) >> 8; - g = (127+g*(*stain++)) >> 8; - b = (127+b*(*stain++)) >> 8; - } - - cr = 0; - cg = 0; - cb = 0; - - if (r > 255) //ak too much red - { - cr -= (255-r)/2; - cg += (255-r)/4; //reduce it, and indicate to drop the others too. - cb += (255-r)/4; - r = 255; - } -// else if (r < 0) -// r = 0; - - if (g > 255) - { - cr += (255-g)/4; - cg -= (255-g)/2; - cb += (255-g)/4; - g = 255; - } -// else if (g < 0) -// g = 0; - - if (b > 255) - { - cr += (255-b)/4; - cg += (255-b)/4; - cb -= (255-b)/2; - b = 255; - } -// else if (b < 0) -// b = 0; - //* - if ((r+cr) > 255) - dest[0] = 0; //inverse lighting - else if ((r+cr) < 0) - dest[0] = 255; - else - dest[0] = 255-(r+cr); - - if ((g+cg) > 255) - dest[1] = 0; - else if ((g+cg) < 0) - dest[1] = 255; - else - dest[1] = 255-(g+cg); - - if ((b+cb) > 255) - dest[2] = 0; - else if ((b+cb) < 0) - dest[2] = 255; - else - dest[2] = 255-(b+cb); -/*/ - if ((r+cr) > 255) - dest[0] = 255; //non-inverse lighting - else if ((r+cr) < 0) - dest[0] = 0; - else - dest[0] = (r+cr); - - if ((g+cg) > 255) - dest[1] = 255; - else if ((g+cg) < 0) - dest[1] = 0; - else - dest[1] = (g+cg); - - if ((b+cb) > 255) - dest[2] = 255; - else if ((b+cb) < 0) - dest[2] = 0; - else - dest[2] = (b+cb); -// */ - dest += 3; - } - } - } - break; -#else - case GL_RGBA: - stride -= (smax<<2); - bl = blocklights; - for (i=0 ; i>= shift; - if (t > 255) - t = 255; - dest[3] = 255-t; - dest += 4; - } - } - break; -#endif - case GL_ALPHA: - case GL_LUMINANCE: - case GL_INTENSITY: - bl = blocklights; - for (i=0 ; i>= shift; - if (t > 255) - t = 255; - dest[j] = 255-t; - } - } - break; - default: - Sys_Error ("Bad lightmap format"); - } -#else - switch (lightmap_bytes) - { -#ifdef PEXT_LIGHTSTYLECOL - case 4: - stride -= (smax<<2); - bl = blocklights; - blg = greenblklights; - blb = blueblklights; - - if (!r_stains.value) - isstained = false; - else - isstained = surf->stained; - -/* if (!gl_lightcomponantreduction.value) - { - for (i=0 ; i>= 7; - if (t > 255) - dest[0] = 0; - else if (t < 0) - dest[0] = 256; - else - dest[0] = (255-t); - - t = *blg++; - t >>= 7; - if (t > 255) - dest[1] = 0; - else if (t < 0) - dest[1] = 256; - else - dest[1] = (255-t); - - t = *blb++; - t >>= 7; - if (t > 255) - dest[2] = 0; - else if (t < 0) - dest[2] = 256; - else - dest[2] = (255-t); - - dest[3] = 0;//(dest[0]+dest[1]+dest[2])/3; - dest += 4; - } - } - } - else -*/ { - stmap *stain; - for (i=0 ; i>= shift; - g >>= shift; - b >>= shift; - - if (isstained) // merge in stain - { - r = (127+r*(*stain++)) >> 8; - g = (127+g*(*stain++)) >> 8; - b = (127+b*(*stain++)) >> 8; - } - - cr = 0; - cg = 0; - cb = 0; - - if (r > 255) //ak too much red - { - cr -= (255-r)/2; - cg += (255-r)/4; //reduce it, and indicate to drop the others too. - cb += (255-r)/4; - r = 255; - } -// else if (r < 0) -// r = 0; - - if (g > 255) - { - cr += (255-g)/4; - cg -= (255-g)/2; - cb += (255-g)/4; - g = 255; - } -// else if (g < 0) -// g = 0; - - if (b > 255) - { - cr += (255-b)/4; - cg += (255-b)/4; - cb -= (255-b)/2; - b = 255; - } -// else if (b < 0) -// b = 0; - /* - if ((r+cr) > 255) - dest[0] = 0; //inverse lighting - else if ((r+cr) < 0) - dest[0] = 255; - else - dest[0] = 255-(r+cr); - - if ((g+cg) > 255) - dest[1] = 0; - else if ((g+cg) < 0) - dest[1] = 255; - else - dest[1] = 255-(g+cg); - - if ((b+cb) > 255) - dest[2] = 0; - else if ((b+cb) < 0) - dest[2] = 255; - else - dest[2] = 255-(b+cb); -/*/ - if ((r+cr) > 255) - dest[0] = 255; //non-inverse lighting - else if ((r+cr) < 0) - dest[0] = 0; - else - dest[0] = (r+cr); - - if ((g+cg) > 255) - dest[1] = 255; - else if ((g+cg) < 0) - dest[1] = 0; - else - dest[1] = (g+cg); - - if ((b+cb) > 255) - dest[2] = 255; - else if ((b+cb) < 0) - dest[2] = 0; - else - dest[2] = (b+cb); -//*/ - - - - dest[3] = (dest[0]+dest[1]+dest[2])/3; //alpha?!?! - dest += 4; - } - } - } - break; - - case 3: - stride -= smax*3; - bl = blocklights; - blg = greenblklights; - blb = blueblklights; - - if (!r_stains.value) - isstained = false; - else - isstained = surf->stained; - -/* if (!gl_lightcomponantreduction.value) - { - for (i=0 ; i>= 7; - if (t > 255) - dest[0] = 255; - else if (t < 0) - dest[0] = 0; - else - dest[0] = t; - - t = *blg++; - t >>= 7; - if (t > 255) - dest[1] = 255; - else if (t < 0) - dest[1] = 0; - else - dest[1] = t; - - t = *blb++; - t >>= 7; - if (t > 255) - dest[2] = 255; - else if (t < 0) - dest[2] = 0; - else - dest[2] = t; - - dest += 3; - } - } - } - else -*/ { - stmap *stain; - for (i=0 ; i>= shift; - g >>= shift; - b >>= shift; - - if (isstained) // merge in stain - { - r = (127+r*(*stain++)) >> 8; - g = (127+g*(*stain++)) >> 8; - b = (127+b*(*stain++)) >> 8; - } - - cr = 0; - cg = 0; - cb = 0; - - if (r > 255) //ak too much red - { - cr -= (255-r)/2; - cg += (255-r)/4; //reduce it, and indicate to drop the others too. - cb += (255-r)/4; - r = 255; - } -// else if (r < 0) -// r = 0; - - if (g > 255) - { - cr += (255-g)/4; - cg -= (255-g)/2; - cb += (255-g)/4; - g = 255; - } -// else if (g < 0) -// g = 0; - - if (b > 255) - { - cr += (255-b)/4; - cg += (255-b)/4; - cb -= (255-b)/2; - b = 255; - } -// else if (b < 0) -// b = 0; - //* - if ((r+cr) > 255) - dest[0] = 255; //inverse lighting - else if ((r+cr) < 0) - dest[0] = 0; - else - dest[0] = (r+cr); - - if ((g+cg) > 255) - dest[1] = 255; - else if ((g+cg) < 0) - dest[1] = 0; - else - dest[1] = (g+cg); - - if ((b+cb) > 255) - dest[2] = 255; - else if ((b+cb) < 0) - dest[2] = 0; - else - dest[2] = (b+cb); -/*/ - if ((r+cr) > 255) - dest[0] = 255; //non-inverse lighting - else if ((r+cr) < 0) - dest[0] = 0; - else - dest[0] = (r+cr); - - if ((g+cg) > 255) - dest[1] = 255; - else if ((g+cg) < 0) - dest[1] = 0; - else - dest[1] = (g+cg); - - if ((b+cb) > 255) - dest[2] = 255; - else if ((b+cb) < 0) - dest[2] = 0; - else - dest[2] = (b+cb); -// */ - dest += 3; - } - } - } - break; -#else - case 4: - stride -= (smax<<2); - bl = blocklights; - for (i=0 ; i>= shift; - if (t > 255) - t = 255; - dest[3] = t; - dest += 4; - } - } - break; -#endif - case 1: - bl = blocklights; - for (i=0 ; i>= shift; - if (t > 255) - t = 255; - dest[j] = t; - } - } - break; - default: - Sys_Error ("Bad lightmap format"); - } -#endif } @@ -1751,7 +1302,93 @@ dynamic: base += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; stainbase = lightmap[fa->lightmaptexturenum]->stainmaps; stainbase += (fa->light_t * LMBLOCK_WIDTH + fa->light_s) * 3; - Surf_BuildLightMap (fa, base, luxbase, stainbase, shift); + Surf_BuildLightMap (fa, base, luxbase, stainbase, shift, r_ambient.value*255); + + RSpeedEnd(RSPEED_DYNAMIC); + } +} + +void Surf_RenderAmbientLightmaps (msurface_t *fa, int shift, int ambient) +{ + qbyte *base, *luxbase; + stmap *stainbase; + glRect_t *theRect; + int smax, tmax; + + if (!fa->mesh) + return; + + //surfaces without lightmaps + if (fa->lightmaptexturenum<0) + return; + + //surfaces with lightmaps that do not animate, supposedly + if (fa->texinfo->flags & (TI_SKY|TI_TRANS33|TI_TRANS66|TI_WARP)) + return; + + if (fa->cached_light[0] != ambient || fa->cached_colour[0] != 0xff) + goto dynamic; + + if (fa->dlightframe == r_framecount // dynamic this frame + || fa->cached_dlight) // dynamic previously + { + RSpeedLocals(); +dynamic: + RSpeedRemark(); + + lightmap[fa->lightmaptexturenum]->modified = true; + + smax = (fa->extents[0]>>4)+1; + tmax = (fa->extents[1]>>4)+1; + + theRect = &lightmap[fa->lightmaptexturenum]->rectchange; + if (fa->light_t < theRect->t) { + if (theRect->h) + theRect->h += theRect->t - fa->light_t; + theRect->t = fa->light_t; + } + if (fa->light_s < theRect->l) { + if (theRect->w) + theRect->w += theRect->l - fa->light_s; + theRect->l = fa->light_s; + } + if ((theRect->w + theRect->l) < (fa->light_s + smax)) + theRect->w = (fa->light_s-theRect->l)+smax; + if ((theRect->h + theRect->t) < (fa->light_t + tmax)) + theRect->h = (fa->light_t-theRect->t)+tmax; + + if (gl_bump.ival) + { + lightmap[fa->lightmaptexturenum]->deluxmodified = true; + theRect = &lightmap[fa->lightmaptexturenum]->deluxrectchange; + if (fa->light_t < theRect->t) { + if (theRect->h) + theRect->h += theRect->t - fa->light_t; + theRect->t = fa->light_t; + } + if (fa->light_s < theRect->l) { + if (theRect->w) + theRect->w += theRect->l - fa->light_s; + theRect->l = fa->light_s; + } + + if ((theRect->w + theRect->l) < (fa->light_s + smax)) + theRect->w = (fa->light_s-theRect->l)+smax; + if ((theRect->h + theRect->t) < (fa->light_t + tmax)) + theRect->h = (fa->light_t-theRect->t)+tmax; + + luxbase = lightmap[fa->lightmaptexturenum]->deluxmaps; + luxbase += fa->light_t * LMBLOCK_WIDTH * 3 + fa->light_s * 3; + } + else + luxbase = NULL; + + + base = lightmap[fa->lightmaptexturenum]->lightmaps; + base += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; + stainbase = lightmap[fa->lightmaptexturenum]->stainmaps; + stainbase += (fa->light_t * LMBLOCK_WIDTH + fa->light_s) * 3; + Surf_BuildLightMap (fa, base, luxbase, stainbase, shift, -1-ambient); RSpeedEnd(RSPEED_DYNAMIC); } @@ -2254,7 +1891,6 @@ R_DrawWorld void Surf_DrawWorld (void) { - int tmp; qbyte *vis; RSpeedLocals(); @@ -2263,6 +1899,11 @@ void Surf_DrawWorld (void) currentmodel = cl.worldmodel; currententity = &r_worldentity; +#ifdef MAP_DOOM + if (currentmodel->fromgame = fg_doom) + GLR_DoomWorld(); + else +#endif #ifdef TERRAIN if (currentmodel->type == mod_heightmap) GL_DrawHeightmapModel(currententity); @@ -2314,13 +1955,11 @@ void Surf_DrawWorld (void) } } - tmp = cl_numvisedicts; CL_LinkStaticEntities(vis); RSpeedEnd(RSPEED_WORLDNODE); TRACE(("dbg: calling BE_DrawWorld\n")); BE_DrawWorld(vis); - cl_numvisedicts = tmp; /*FIXME: move this away*/ @@ -2643,7 +2282,7 @@ static void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift) stainbase = lightmap[surf->lightmaptexturenum]->stainmaps; stainbase += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * 3; - Surf_BuildLightMap (surf, base, luxbase, stainbase, shift); + Surf_BuildLightMap (surf, base, luxbase, stainbase, shift, r_ambient.value*255); } @@ -2720,15 +2359,24 @@ void Surf_BuildLightmaps (void) lightmap_bgra = (qrenderer == QR_DIRECT3D); if (qrenderer == QR_DIRECT3D) + { lightmap_bytes = 4; - else if ((cl.worldmodel->engineflags & MDLF_RGBLIGHTING) || cl.worldmodel->deluxdata || r_loadlits.value) + lightmap_bgra = true; + } + else if (cl.worldmodel->fromgame == fg_quake3 || (cl.worldmodel->engineflags & MDLF_RGBLIGHTING) || cl.worldmodel->deluxdata || r_loadlits.value) + { + lightmap_bgra = false; lightmap_bytes = 3; + } else lightmap_bytes = 1; if (cl.worldmodel->fromgame == fg_quake3 && lightmap_bytes != 3 && lightmap_bytes != 4) lightmap_bytes = 3; + lightmap_bgra = true; + lightmap_bytes = 4; + for (j=1 ; jtextures[t]->shader->sort == SHADER_SORT_PORTAL) { if (surf->flags & SURF_PLANEBACK) diff --git a/engine/client/render.h b/engine/client/render.h index cf0a18110..5d73e3c75 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -177,6 +177,7 @@ void Surf_Clear(struct model_s *mod); void Surf_BuildLightmaps(void); void Surf_BuildSurfaceDisplayList (struct model_s *mod, struct msurface_s *fa); void Surf_RenderDynamicLightmaps (struct msurface_s *fa, int shift); +void Surf_RenderAmbientLightmaps (struct msurface_s *fa, int shift, int ambient); int Surf_LightmapShift (struct model_s *model); #ifndef LMBLOCK_WIDTH #define LMBLOCK_WIDTH 128 @@ -201,7 +202,8 @@ extern lightmapinfo_t **lightmap; extern int numlightmaps; extern texid_t *lightmap_textures; extern texid_t *deluxmap_textures; -extern int lightmap_bytes; // 1, 3(, or 4) +extern int lightmap_bytes; // 1, 3, or 4 +extern qboolean lightmap_bgra; /*true=bgra, false=rgba*/ #endif diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 7a32d6961..45f6fbf86 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -137,7 +137,7 @@ cvar_t r_replacemodels = CVARF ("r_replacemodels", IFMINIMAL("","md3 md2"), //otherwise it would defeat the point. cvar_t scr_allowsnap = CVARF ("scr_allowsnap", "1", CVAR_NOTFROMSERVER); -cvar_t scr_centersbar = CVAR ("scr_centersbar", "0"); +cvar_t scr_centersbar = CVAR ("scr_centersbar", "2"); cvar_t scr_centertime = CVAR ("scr_centertime", "2"); cvar_t scr_chatmodecvar = CVAR ("scr_chatmode", "0"); cvar_t scr_conalpha = CVARC ("scr_conalpha", "0.7", @@ -234,7 +234,8 @@ rendererstate_t currentrendererstate; #if defined(GLQUAKE) cvar_t vid_gl_context_version = SCVAR ("vid_gl_context_version", ""); -cvar_t vid_gl_context_forwardcompatible = SCVAR ("vid_gl_context_breakeverything", "0"); //not useful, yet, hence the name +cvar_t vid_gl_context_forwardcompatible = SCVAR ("vid_gl_context_forwardcompatible", "0"); +cvar_t vid_gl_context_compatibility = SCVAR ("vid_gl_context_compatibility", "1"); cvar_t vid_gl_context_debug = SCVAR ("vid_gl_context_debug", "0"); //for my ati drivers, debug 1 only works if version >= 3 #endif @@ -308,7 +309,6 @@ cvar_t gl_texturemode2d = CVARFC("gl_texturemode2d", "GL_LINEAR", cvar_t gl_triplebuffer = SCVARF ("gl_triplebuffer", "1", CVAR_ARCHIVE); -cvar_t gl_ztrick = SCVAR ("gl_ztrick", "0"); cvar_t r_noportals = SCVAR ("r_noportals", "0"); cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", @@ -358,6 +358,7 @@ void GLRenderer_Init(void) Cvar_Register (&vid_gl_context_version, GLRENDEREROPTIONS); Cvar_Register (&vid_gl_context_debug, GLRENDEREROPTIONS); Cvar_Register (&vid_gl_context_forwardcompatible, GLRENDEREROPTIONS); + Cvar_Register (&vid_gl_context_compatibility, GLRENDEREROPTIONS); //screen Cvar_Register (&gl_triplebuffer, GLRENDEREROPTIONS); @@ -397,8 +398,6 @@ void GLRenderer_Init(void) Cvar_Register (&gl_keeptjunctions, GLRENDEREROPTIONS); Cvar_Register (&gl_reporttjunctions, GLRENDEREROPTIONS); - Cvar_Register (&gl_ztrick, GLRENDEREROPTIONS); - Cvar_Register (&gl_motionblur, GLRENDEREROPTIONS); Cvar_Register (&gl_motionblurscale, GLRENDEREROPTIONS); Cvar_Register (&gl_max_size, GLRENDEREROPTIONS); @@ -1650,19 +1649,6 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n")); TRACE(("dbg: R_ApplyRenderer: starting on client state\n")); if (cl.worldmodel) { - int staticmodelindex[MAX_STATIC_ENTITIES]; - - for (i = 0; i < cl.num_statics; i++) //static entities contain pointers to the model index. - { - staticmodelindex[i] = 0; - for (j = 1; j < MAX_MODELS; j++) - if (cl_static_entities[i].ent.model == cl.model_precache[j]) - { - staticmodelindex[i] = j; - break; - } - } - cl.worldmodel = NULL; cl_numvisedicts = 0; cl_numstrisidx = 0; @@ -1745,11 +1731,20 @@ TRACE(("dbg: R_ApplyRenderer: R_NewMap\n")); TRACE(("dbg: R_ApplyRenderer: efrags\n")); for (i = 0; i < cl.num_statics; i++) //make the static entities reappear. { - cl_static_entities[i].ent.model = cl.model_precache[staticmodelindex[i]]; - if (cl_static_entities[i].ent.model) - cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &cl_static_entities[i].pvscache, NULL, NULL); -#pragma message("STATIC ENTITITES --- relink") + cl_static_entities[i].ent.model = NULL; + if (cl_static_entities[i].mdlidx < 0) + { + if (cl_static_entities[i].mdlidx > -MAX_CSQCMODELS) + cl_static_entities[i].ent.model = cl.model_csqcprecache[-cl_static_entities[i].mdlidx]; + } + else + { + if (cl_static_entities[i].mdlidx < MAX_MODELS) + cl_static_entities[i].ent.model = cl.model_precache[cl_static_entities[i].mdlidx]; + } } + + Skin_FlushPlayers(); } #ifdef VM_UI else @@ -2437,6 +2432,24 @@ qboolean R_CullEntityBox(entity_t *e, vec3_t modmins, vec3_t modmaxs) { int i; vec3_t wmin, wmax; + +#if 1 + float mrad = 0, v; + for (i = 0; i < 3; i++) + { + v = fabs(modmins[i]); + if (mrad < v) + mrad = v; + v = fabs(modmaxs[i]); + if (mrad < v) + mrad = v; + } + for (i = 0; i < 3; i++) + { + wmin[i] = e->origin[i]-mrad; + wmax[i] = e->origin[i]+mrad; + } +#else float fmin, fmax; //convert the model's bbox to the expanded maximum size of the entity, as drawn with this model. @@ -2463,7 +2476,7 @@ qboolean R_CullEntityBox(entity_t *e, vec3_t modmins, vec3_t modmaxs) wmax[i] = e->origin[i]+fmin; } } - +#endif return R_CullBox(wmin, wmax); } diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 473d06b92..6cf0ac883 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -973,7 +973,13 @@ void Draw_TinyString (int x, int y, const qbyte *str) #pragma message("hexen2: use a tinychar *6 font") if (!font_tiny) - return; + { +// font_tiny = Font_LoadFont(6*vid.pixelheight/vid.height, var->string); +// if (!font_tiny && *var->string) + font_tiny = Font_LoadFont(6*vid.pixelheight/vid.height, "gfx/tinyfont"); + if (!font_tiny) + return; + } Font_BeginString(font_tiny, x, y, &x, &y); xstart = x; @@ -987,7 +993,7 @@ void Draw_TinyString (int x, int y, const qbyte *str) str++; continue; } - x = Font_DrawChar(x, y, *str++); + x = Font_DrawChar(x, y, CON_WHITEMASK|*str++); } Font_EndString(font_tiny); } @@ -1132,7 +1138,7 @@ void Sbar_Hexen2DrawNum (int x, int y, int num, int digits) else frame = *ptr -'0'; - Sbar_DrawPic (x, y, FINDOUT, FINDOUT, sb_nums[0][frame]); + Sbar_DrawPic (x, y, 12, 16, sb_nums[0][frame]); x += 13; ptr++; } @@ -1791,14 +1797,14 @@ void Sbar_DrawScoreboard (void) void Sbar_Hexen2DrawItem(int pnum, int x, int y, int itemnum) { int num; - Sbar_DrawPic(x, y, FINDOUT, FINDOUT, Draw_SafeCachePic(va("gfx/arti%02d.lmp", itemnum))); + Sbar_DrawPic(x, y, 29, 28, Draw_SafeCachePic(va("gfx/arti%02d.lmp", itemnum))); num = cl.stats[pnum][STAT_H2_CNT_TORCH+itemnum]; if(num > 0) { if (num >= 10) - Sbar_DrawPic(x+20, y+21, FINDOUT, FINDOUT, Draw_SafeCachePic(va("gfx/artinum%d.lmp", num/10))); - Sbar_DrawPic(x+20+4, y+21, FINDOUT, FINDOUT, Draw_SafeCachePic(va("gfx/artinum%d.lmp", num%10))); + Sbar_DrawPic(x+20, y+21, 4, 6, Draw_SafeCachePic(va("gfx/artinum%d.lmp", num/10))); + Sbar_DrawPic(x+20+4, y+21, 4, 6, Draw_SafeCachePic(va("gfx/artinum%d.lmp", num%10))); } } @@ -1814,7 +1820,7 @@ void Sbar_Hexen2DrawInventory(int pnum) for (i = 0, x=320/2-114; i < 7; i++, x+=33) { if ((sb_hexen2_cur_item-3+i+30)%15 == sb_hexen2_cur_item) - Sbar_DrawPic(x+9, y-12, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/artisel.lmp")); + Sbar_DrawPic(x+9, y-12, 11, 11, Draw_SafeCachePic("gfx/artisel.lmp")); Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item-3+i+30)%15); } #else @@ -1859,8 +1865,8 @@ void Sbar_Hexen2DrawExtra (int pnum) //adjust it so there's space sbar_rect.y -= 46+98-SBAR_HEIGHT; - Sbar_DrawPic(0, 46, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/btmbar1.lmp")); - Sbar_DrawPic(160, 46, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/btmbar2.lmp")); + Sbar_DrawPic(0, 46, 160, 98, Draw_SafeCachePic("gfx/btmbar1.lmp")); + Sbar_DrawPic(160, 46, 160, 98, Draw_SafeCachePic("gfx/btmbar2.lmp")); Sbar_DrawTinyString (11, 48, pclassname[pclass]); @@ -1893,7 +1899,7 @@ void Sbar_Hexen2DrawExtra (int pnum) { if (cl.stats[pnum][STAT_H2_ARMOUR1+i] > 0) { - Sbar_DrawPic (164+i*40, 115, FINDOUT, FINDOUT, Draw_SafeCachePic(va("gfx/armor%d.lmp", i+1))); + Sbar_DrawPic (164+i*40, 115, 28, 19, Draw_SafeCachePic(va("gfx/armor%d.lmp", i+1))); Sbar_DrawTinyString (168+i*40, 136, va("+%d", cl.stats[pnum][STAT_H2_ARMOUR1+i])); } } @@ -1901,14 +1907,14 @@ void Sbar_Hexen2DrawExtra (int pnum) { if (cl.stats[pnum][STAT_H2_FLIGHT_T+i] > 0) { - Sbar_DrawPic (ringpos[i], 119, FINDOUT, FINDOUT, Draw_SafeCachePic(va("gfx/ring_f.lmp"))); + Sbar_DrawPic (ringpos[i], 119, 32, 22, Draw_SafeCachePic(va("gfx/ring_f.lmp"))); val = cl.stats[pnum][STAT_H2_FLIGHT_T+i]; if (val > 100) val = 100; if (val < 0) val = 0; - Sbar_DrawPic(ringpos[i]+29 - (int)(26 * (val/(float)100)),142, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/ringhlth.lmp")); - Sbar_DrawPic(ringpos[i]+29, 142, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/rhlthcvr.lmp")); + Sbar_DrawPic(ringpos[i]+29 - (int)(26 * (val/(float)100)),142, 26, 1, Draw_SafeCachePic("gfx/ringhlth.lmp")); + Sbar_DrawPic(ringpos[i]+29, 142, 26, 1, Draw_SafeCachePic("gfx/rhlthcvr.lmp")); } } @@ -1917,23 +1923,23 @@ void Sbar_Hexen2DrawExtra (int pnum) { if (cl.statsstr[pnum][STAT_H2_PUZZLE1+i]) { - Sbar_DrawPic (194+(slot%4)*31, slot<4?51:82, FINDOUT, FINDOUT, Draw_SafeCachePic(va("gfx/puzzle/%s.lmp", cl.statsstr[pnum][STAT_H2_PUZZLE1+i]))); + Sbar_DrawPic (194+(slot%4)*31, slot<4?51:82, 26, 26, Draw_SafeCachePic(va("gfx/puzzle/%s.lmp", cl.statsstr[pnum][STAT_H2_PUZZLE1+i]))); slot++; } } - Sbar_DrawPic(134, 50, FINDOUT, FINDOUT, Draw_SafeCachePic(va("gfx/cport%d.lmp", pclass))); + Sbar_DrawPic(134, 50, 49, 56, Draw_SafeCachePic(va("gfx/cport%d.lmp", pclass))); } void Sbar_Hexen2DrawBasic(int pnum) { int chainpos; int val, maxval; - Sbar_DrawPic(0, 0, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/topbar1.lmp")); - Sbar_DrawPic(160, 0, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/topbar2.lmp")); - Sbar_DrawPic(0, -23, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/topbumpl.lmp")); - Sbar_DrawPic(138, -8, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/topbumpm.lmp")); - Sbar_DrawPic(269, -23, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/topbumpr.lmp")); + Sbar_DrawPic(0, 0, 160, 46, Draw_SafeCachePic("gfx/topbar1.lmp")); + Sbar_DrawPic(160, 0, 160, 46, Draw_SafeCachePic("gfx/topbar2.lmp")); + Sbar_DrawPic(0, -23, 51, 23, Draw_SafeCachePic("gfx/topbumpl.lmp")); + Sbar_DrawPic(138, -8, 39, 8, Draw_SafeCachePic("gfx/topbumpm.lmp")); + Sbar_DrawPic(269, -23, 51, 23, Draw_SafeCachePic("gfx/topbumpr.lmp")); //mana1 maxval = cl.stats[pnum][STAT_H2_MAXMANA]; @@ -1942,8 +1948,8 @@ void Sbar_Hexen2DrawBasic(int pnum) Sbar_DrawTinyString(201, 22, va("%03d", val)); if(val) { - Sbar_DrawPic(190, 26-(int)((val*18.0)/(float)maxval+0.5), FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/bmana.lmp")); - Sbar_DrawPic(190, 27, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/bmanacov.lmp")); + Sbar_DrawPic(190, 26-(int)((val*18.0)/(float)maxval+0.5), 3, 19, Draw_SafeCachePic("gfx/bmana.lmp")); + Sbar_DrawPic(190, 27, 3, 19, Draw_SafeCachePic("gfx/bmanacov.lmp")); } //mana2 @@ -1953,8 +1959,8 @@ void Sbar_Hexen2DrawBasic(int pnum) Sbar_DrawTinyString(243, 22, va("%03d", val)); if(val) { - Sbar_DrawPic(232, 26-(int)((val*18.0)/(float)maxval+0.5), FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/gmana.lmp")); - Sbar_DrawPic(232, 27, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/gmanacov.lmp")); + Sbar_DrawPic(232, 26-(int)((val*18.0)/(float)maxval+0.5), 3, 19, Draw_SafeCachePic("gfx/gmana.lmp")); + Sbar_DrawPic(232, 27, 3, 19, Draw_SafeCachePic("gfx/gmanacov.lmp")); } @@ -1972,10 +1978,10 @@ void Sbar_Hexen2DrawBasic(int pnum) chainpos = (195.0f*cl.stats[pnum][STAT_HEALTH]) / cl.stats[pnum][STAT_H2_MAXHEALTH]; if (chainpos < 0) chainpos = 0; - Sbar_DrawPic(45+((int)chainpos&7), 38, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/hpchain.lmp")); - Sbar_DrawPic(45+(int)chainpos, 36, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/hpgem.lmp")); - Sbar_DrawPic(43, 36, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/chnlcov.lmp")); - Sbar_DrawPic(267, 36, FINDOUT, FINDOUT, Draw_SafeCachePic("gfx/chnrcov.lmp")); + Sbar_DrawPic(45+((int)chainpos&7), 38, 222, 5, Draw_SafeCachePic("gfx/hpchain.lmp")); + Sbar_DrawPic(45+(int)chainpos, 36, 35, 9, Draw_SafeCachePic("gfx/hpgem.lmp")); + Sbar_DrawPic(43, 36, 10, 10, Draw_SafeCachePic("gfx/chnlcov.lmp")); + Sbar_DrawPic(267, 36, 10, 10, Draw_SafeCachePic("gfx/chnrcov.lmp")); Sbar_Hexen2DrawItem(pnum, 144, 3, sb_hexen2_cur_item); @@ -2156,7 +2162,7 @@ void Sbar_Draw (void) sbar_rect.x = 0; sbar_rect.y = 0; - if (scr_centersbar.ival) + if (scr_centersbar.ival || (scr_centersbar.ival == 2 && !cl.deathmatch)) { sbar_rect.x = (vid.width - 320)/2; sbar_rect.width -= sbar_rect.x; diff --git a/engine/client/skin.c b/engine/client/skin.c index d18b7b963..d5dd0701e 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -596,10 +596,13 @@ void Skin_Skins_f (void) Skin_NextDownload (); - SCR_SetLoadingStage(LS_NONE); +// if (Cmd_FromServer()) + { + SCR_SetLoadingStage(LS_NONE); - CL_SendClientCommand(true, "begin %i", cl.servercount); - Cache_Report (); // print remaining memory + CL_SendClientCommand(true, "begin %i", cl.servercount); + Cache_Report (); // print remaining memory + } } diff --git a/engine/client/snd_mem.c b/engine/client/snd_mem.c index 96dd80e62..2838041a2 100644 --- a/engine/client/snd_mem.c +++ b/engine/client/snd_mem.c @@ -633,6 +633,8 @@ sfxcache_t *S_LoadDoomSpeakerSound (sfx_t *s, qbyte *data, int datalen, int snds inaccum = inrate; if (*data) timerfreq = DSPK_BASE * pow((double)2.0, DSPK_EXP * (*data)); + else + timerfreq = 0; while (len > 0) { @@ -920,7 +922,7 @@ WAV loading =============================================================================== */ - +char *wavname; qbyte *data_p; qbyte *iff_end; qbyte *last_chunk; @@ -972,7 +974,7 @@ unsigned int FindNextChunk(char *name) } if (iff_chunk_len > dataleft) { - Con_Printf ("Sound file seems truncated by %i bytes\n", iff_chunk_len-dataleft); + Con_DPrintf ("\"%s\" seems truncated by %i bytes\n", wavname, iff_chunk_len-dataleft); #if 1 iff_chunk_len = dataleft; #else @@ -1038,6 +1040,7 @@ wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength) iff_data = wav; iff_end = wav + wavlength; + wavname = name; // find "RIFF" chunk chunklen = FindChunk("RIFF"); diff --git a/engine/client/sys_npfte.c b/engine/client/sys_npfte.c index e4c6c7a62..ccc61f3d0 100644 --- a/engine/client/sys_npfte.c +++ b/engine/client/sys_npfte.c @@ -11,6 +11,7 @@ #include "npapi/npupp.h" #include "sys_plugfte.h" +/*work around absolute crapness in the npapi headers*/ #define Q_STRINGZ_TO_NPVARIANT(_val, _v) \ NP_BEGIN_MACRO \ NPString str = { _val, strlen(_val) }; \ @@ -20,6 +21,15 @@ NP_END_MACRO #undef STRINGZ_TO_NPVARIANT #define STRINGZ_TO_NPVARIANT Q_STRINGZ_TO_NPVARIANT +#define Q_STRINGN_TO_NPVARIANT(_val, _len, _v) \ +NP_BEGIN_MACRO \ + NPString str = { _val, _len }; \ + (_v).type = NPVariantType_String; \ + (_v).value.stringValue = str; \ +NP_END_MACRO +#undef STRINGN_TO_NPVARIANT +#define STRINGN_TO_NPVARIANT Q_STRINGN_TO_NPVARIANT + #define FIREFOX_BUGS_OVER_25MB //TODO: player name input (before allowing them to join) @@ -502,13 +512,21 @@ bool npscript_getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) char *ns; int len; len = strlen(strval); - ns = browserfuncs->memalloc(len); - if (ns) + if (!len) { - memcpy(ns, strval, len); - STRINGZ_TO_NPVARIANT(ns, *result); + STRINGN_TO_NPVARIANT(NULL, 0, *result); success = true; } + else + { + ns = browserfuncs->memalloc(len); + if (ns) + { + memcpy(ns, strval, len); + STRINGZ_TO_NPVARIANT(ns, *result); + success = true; + } + } Plug_GotString(strval); } else if (Plug_GetInteger(ctx, prop, &intval)) @@ -646,10 +664,10 @@ NPError OSCALL NP_GetValue(void *instance, NPPVariable variable, void *value) switch(variable) { case NPPVpluginNameString: - *(char**)value = "QTV Viewer"; + *(char**)value = "FTE QuakeWorld"; break; case NPPVpluginDescriptionString: - *(char**)value = "QTV Viewer"; + *(char**)value = "FTE QuakeWorld"; break; default: return NPERR_INVALID_PARAM; diff --git a/engine/client/sys_plugfte.c b/engine/client/sys_plugfte.c index 1707dccdb..5fe20a6b4 100644 --- a/engine/client/sys_plugfte.c +++ b/engine/client/sys_plugfte.c @@ -314,6 +314,7 @@ int Plug_PluginThread(void *ctxptr) while(host_initialized && !ctx->shutdown && ctx->packagelist) { int total=0, done=0; + ctx->resetvideo = false; Sys_LockMutex(ctx->mutex); for (dl = ctx->packagelist; dl; dl = dl->next) { @@ -367,10 +368,12 @@ int Plug_PluginThread(void *ctxptr) } else if (ctx->resetvideo) { - ctx->resetvideo = false; sys_parentwindow = ctx->windowhnd; sys_parentwidth = ctx->windowwidth; sys_parentheight = ctx->windowheight; + if (ctx->resetvideo == 2) + SetParent(mainwindow, sys_parentwindow); + ctx->resetvideo = false; Cbuf_AddText("vid_recenter\n", RESTRICT_LOCAL); } else @@ -479,35 +482,27 @@ qboolean Plug_ChangeWindow(struct context *ctx, void *whnd, int width, int heigh { qboolean result = false; + Plug_LockPlugin(ctx, true); + //if the window changed if (ctx->windowhnd != whnd) { result = true; - -#ifdef _WIN32 - if (ctx->pub.running) - { - Plug_LockPlugin(ctx, true); - if (mainwindow && ctx->windowhnd == sys_parentwindow) - { - sys_parentwindow = ctx->windowhnd; - SetParent(mainwindow, ctx->windowhnd); - } - Plug_LockPlugin(ctx, false); - } -#endif ctx->windowhnd = whnd; + ctx->resetvideo = 2; } if (ctx->windowwidth != width && ctx->windowheight != height) { ctx->windowwidth = width; ctx->windowheight = height; - Plug_LockPlugin(ctx, true); - if (ctx->pub.running) + if (ctx->pub.running && !ctx->resetvideo) ctx->resetvideo = true; - Plug_LockPlugin(ctx, false); } + Plug_LockPlugin(ctx, false); + + while(ctx->pub.running && ctx->resetvideo) + Sleep(10); return result; } @@ -617,12 +612,14 @@ static void UnpackAndExtractPakFiles_Complete(struct dl_download *dl) Plug_LockPlugin(dl->user_ctx, true); - zip = zipfilefuncs.OpenNew(dl->file, dl->url); + if (dl->status == DL_FINISHED) + zip = zipfilefuncs.OpenNew(dl->file, dl->url); + else + zip = NULL; + /*the zip code will have eaten the file handle*/ + dl->file = NULL; if (zip) { - /*the zip code will eat the file handle*/ - dl->file = NULL; - /*scan it to extract its contents*/ zipfilefuncs.EnumerateFiles(zip, "*.pk3", ExtractDataFile, zip); zipfilefuncs.EnumerateFiles(zip, "*.pak", ExtractDataFile, zip); @@ -762,22 +759,34 @@ void pscript_property_running_setb(struct context *ctx, int i) char *pscript_property_startserver_gets(struct context *ctx) { - return ctx->qtvf.server; + return strdup(ctx->qtvf.server); } void pscript_property_startserver_sets(struct context *ctx, const char *val) { + if (strchr(val, '$') || strchr(val, ';') || strchr(val, '\n')) + return; + ctx->qtvf.connectiontype = QTVCT_JOIN; Q_strncpyz(ctx->qtvf.server, val, sizeof(ctx->qtvf.server)); } char *pscript_property_curserver_gets(struct context *ctx) { + extern char lastdemoname[]; if (!pscript_property_running_getb(ctx)) return pscript_property_startserver_gets(ctx); - return cls.servername; + if (cls.demoplayback) + return strdup(va("demo:%s",lastdemoname)); + else if (cls.state != ca_disconnected) + return strdup(cls.servername); + else + return strdup(""); } void pscript_property_curserver_sets(struct context *ctx, const char *val) { + if (strchr(val, '$') || strchr(val, ';') || strchr(val, '\n')) + return; + if (!pscript_property_running_getb(ctx)) { pscript_property_startserver_sets(ctx, val); @@ -790,6 +799,9 @@ void pscript_property_curserver_sets(struct context *ctx, const char *val) void pscript_property_stream_sets(struct context *ctx, const char *val) { + if (strchr(val, '$') || strchr(val, ';') || strchr(val, '\n')) + return; + ctx->qtvf.connectiontype = QTVCT_STREAM; Q_strncpyz(ctx->qtvf.server, val, sizeof(ctx->qtvf.server)); @@ -798,8 +810,9 @@ void pscript_property_stream_sets(struct context *ctx, const char *val) } void pscript_property_map_sets(struct context *ctx, const char *val) { + if (strchr(val, '$') || strchr(val, ';') || strchr(val, '\n')) + return; ctx->qtvf.connectiontype = QTVCT_MAP; - FILTER(val) Q_strncpyz(ctx->qtvf.server, val, sizeof(ctx->qtvf.server)); if (pscript_property_running_getb(ctx)) @@ -826,6 +839,9 @@ void pscript_property_datadownload_sets(struct context *ctx, const char *val) void pscript_property_game_sets(struct context *ctx, const char *val) { + if (strchr(val, '$') || strchr(val, ';') || strchr(val, '\n')) + return; + if (!strstr(val, ".")) if (!strstr(val, "/")) if (!strstr(val, "\\")) @@ -854,6 +870,15 @@ void pscript_property_splash_sets(struct context *ctx, const char *val) } } +char *pscript_property_build_gets(struct context *ctx) +{ + return strdup(DISTRIBUTION " " __DATE__ " " __TIME__ +#if defined(DEBUG) || defined(_DEBUG) + " (debug)" +#endif + ); +} + extern cvar_t skin, team, topcolor, bottomcolor, vid_fullscreen, cl_download_mapsrc; static struct pscript_property pscript_properties[] = { @@ -874,12 +899,14 @@ static struct pscript_property pscript_properties[] = {"game", false, NULL, NULL, pscript_property_game_sets}, {"availver", false, NULL, NULL, NULL, NULL, NULL, NULL, pscript_property_availver_setf}, + {"plugver", false, NULL, NULL, NULL, NULL, NULL, pscript_property_curver_getf}, {"splash", false, NULL, NULL, pscript_property_splash_sets}, {"stream", false, NULL, NULL, pscript_property_stream_sets}, {"map", false, NULL, NULL, pscript_property_map_sets}, + {"build", false, NULL, pscript_property_build_gets}, /* else if (!stricmp(argn[i], "connType")) { @@ -1044,9 +1071,13 @@ qboolean Plug_SetFloat(struct context *ctx, struct pscript_property *field, floa return true; } -#pragma message("Plug_Get* not implemented yet") qboolean Plug_GetString(struct context *ctx, struct pscript_property *field, const char **value) { + if (field->getstring) + { + *value = field->getstring(ctx); + return true; + } return false; } void Plug_GotString(const char *value) @@ -1055,10 +1086,20 @@ void Plug_GotString(const char *value) } qboolean Plug_GetInteger(struct context *ctx, struct pscript_property *field, int *value) { + if (field->getint) + { + *value = field->getint(ctx); + return true; + } return false; } qboolean Plug_GetFloat(struct context *ctx, struct pscript_property *field, float *value) { + if (field->getfloat) + { + *value = field->getfloat(ctx); + return true; + } return false; } diff --git a/engine/client/textedit.c b/engine/client/textedit.c index aab80257e..348308375 100644 --- a/engine/client/textedit.c +++ b/engine/client/textedit.c @@ -162,6 +162,7 @@ void CloseEditor(void) key_dest = key_console; editoractive = false; + editprogfuncs = NULL; if (!firstblock) return; diff --git a/engine/client/view.c b/engine/client/view.c index 39c6be625..079743081 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1093,7 +1093,6 @@ the entity origin, so any view position inside that will be valid */ extern vrect_t scr_vrect; -int gl_ztrickdisabled; qboolean r_secondaryview; #ifdef SIDEVIEWS @@ -1270,7 +1269,6 @@ void V_RenderPlayerViews(int plnum) vec3_t dir; extern void vectoangles(vec3_t vec, vec3_t ang); - gl_ztrickdisabled|=16; r_refdef.vrect.y -= r_refdef.vrect.height; vid.recalc_refdef=true; r_secondaryview = 2; @@ -1284,8 +1282,6 @@ void V_RenderPlayerViews(int plnum) R_RenderView (); vid.recalc_refdef=true; } - else - gl_ztrickdisabled&=~16; #ifdef SIDEVIEWS @@ -1296,9 +1292,6 @@ void V_RenderPlayerViews(int plnum) r_refdef.vrect.height += vsecheight; } */ -#ifdef GLQUAKE - gl_ztrickdisabled&=~1; -#endif for (viewnum = 0; viewnum < SIDEVIEWS; viewnum++) if (vsec_scalex[viewnum].value>0&&vsec_scaley[viewnum].value>0 && ((vsec_enabled[viewnum].value && vsec_enabled[viewnum].value != 2 && cls.allow_rearview) //rearview if v2_enabled = 1 and not 2 @@ -1312,7 +1305,6 @@ void V_RenderPlayerViews(int plnum) float ofx; float ofy; - gl_ztrickdisabled|=1; vid.recalc_refdef=true; r_secondaryview = true; @@ -1415,7 +1407,7 @@ void V_RenderView (void) //work out which packet entities are solid CL_SetSolidEntities (); - CL_EmitEntities(); +// CL_EmitEntities(); // Set up prediction for other players CL_SetUpPlayerPrediction(false); @@ -1427,7 +1419,7 @@ void V_RenderView (void) CL_SetUpPlayerPrediction(true); // build a refresh entity list -// CL_EmitEntities (); + CL_EmitEntities (); CL_AllowIndependantSendCmd(true); @@ -1445,11 +1437,6 @@ void V_RenderView (void) alreadyrendering=true; #endif - if (cl.splitclients>1) - gl_ztrickdisabled|=8; - else - gl_ztrickdisabled&=~8; - r_secondaryview = 0; for (viewnum = 0; viewnum < cl.splitclients; viewnum++) { diff --git a/engine/client/view.h b/engine/client/view.h index 4e1e943d4..f6c66f7ea 100644 --- a/engine/client/view.h +++ b/engine/client/view.h @@ -24,7 +24,6 @@ extern cvar_t lcd_x; extern float sw_blend[4]; extern float hw_blend[4]; -extern int gl_ztrickdisabled; extern qboolean r_secondaryview; void V_Init (void); diff --git a/engine/client/wad.c b/engine/client/wad.c index c6b7b4cc9..80bee9bd5 100644 --- a/engine/client/wad.c +++ b/engine/client/wad.c @@ -573,14 +573,10 @@ void CL_Skygroup_f(void) } } -//extern model_t *loadmodel; - char wads[4096]; -void Mod_ParseInfoFromEntityLump(char *data, char *mapname) //actually, this should be in the model code. +void Mod_ParseInfoFromEntityLump(model_t *wmodel, char *data, char *mapname) //actually, this should be in the model code. { - extern model_t *loadmodel; char key[128]; - char skyname[64]; mapskys_t *msky; cl.skyrotate = 0; @@ -595,16 +591,16 @@ void Mod_ParseInfoFromEntityLump(char *data, char *mapname) //actually, this sho // this hack is necessary to ensure Quake 2 maps get their // default skybox - if (loadmodel->fromgame == fg_quake2) - strcpy(skyname, "unit1_"); + if (wmodel->fromgame == fg_quake2) + strcpy(cl.skyname, "unit1_"); else - skyname[0] = '\0'; + cl.skyname[0] = '\0'; for (msky = mapskies; msky; msky = msky->next) { if (!strcmp(msky->mapname, mapname)) { - Q_strncpyz(skyname, msky->skyname, sizeof(skyname)); + Q_strncpyz(cl.skyname, msky->skyname, sizeof(cl.skyname)); break; } } @@ -626,7 +622,7 @@ void Mod_ParseInfoFromEntityLump(char *data, char *mapname) //actually, this sho break; // error if (!strcmp("wad", key)) // for HalfLife maps { - if (loadmodel->fromgame == fg_halflife) + if (wmodel->fromgame == fg_halflife) { strncat(wads, ";", 4095); //cache it for later (so that we don't play with any temp memory yet) strncat(wads, com_token, 4095); //cache it for later (so that we don't play with any temp memory yet) @@ -634,11 +630,11 @@ void Mod_ParseInfoFromEntityLump(char *data, char *mapname) //actually, this sho } else if (!strcmp("skyname", key)) // for HalfLife maps { - Q_strncpyz(skyname, com_token, sizeof(skyname)); + Q_strncpyz(cl.skyname, com_token, sizeof(cl.skyname)); } else if (!strcmp("sky", key)) // for Quake2 maps { - Q_strncpyz(skyname, com_token, sizeof(skyname)); + Q_strncpyz(cl.skyname, com_token, sizeof(cl.skyname)); } else if (!strcmp("skyrotate", key)) { diff --git a/engine/client/wad.h b/engine/client/wad.h index b33831a9b..31a47d409 100644 --- a/engine/client/wad.h +++ b/engine/client/wad.h @@ -108,10 +108,10 @@ void Wads_Flush (void); void SwapPic (qpic_t *pic); - +struct model_s; void Mod_ParseWadsFromEntityLump(char *data); qbyte *W_ConvertWAD3Texture(miptex_t *tex, int *width, int *height, qboolean *usesalpha); -void Mod_ParseInfoFromEntityLump(char *data, char *mapname); +void Mod_ParseInfoFromEntityLump(struct model_s *wmodel, char *data, char *mapname); qboolean Wad_NextDownload (void); qbyte *W_GetTexture(char *name, int *width, int *height, qboolean *usesalpha); diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index e5445f0aa..7bd5637b7 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -141,7 +141,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ZYMOTICMODELS //zymotic skeletal models. #define HUFFNETWORK //huffman network compression #define HALFLIFEMODELS //halflife model support (experimental) -// #define DOOMWADS //doom wad/map/sprite support + //#define DOOMWADS //doom wad/sprite support + //#define MAP_DOOM //doom map support + //#define MAP_PROC //doom3/quake4 map support //#define WOLF3DSUPPORT //wolfenstein3d map support (not started yet) #define Q2BSPS //quake 2 bsp support #define Q3BSPS //quake 3 bsp support @@ -424,10 +426,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ON_EPSILON 0.1 // point on plane side epsilon -#define MAX_NQMSGLEN 8000 // max length of a reliable message +#define MAX_NQMSGLEN 65536 // max length of a reliable message #define MAX_Q2MSGLEN 1400 #define MAX_QWMSGLEN 1450 -#define MAX_OVERALLMSGLEN 8192 // mvdsv sends packets this big +#define MAX_OVERALLMSGLEN 65536 // mvdsv sends packets this big #define MAX_DATAGRAM 1450 // max length of unreliable message #define MAX_Q2DATAGRAM MAX_Q2MSGLEN #define MAX_NQDATAGRAM 1024 // max length of unreliable message diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index bf772b48c..4ef337bd7 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -753,29 +753,45 @@ void R_LightArrays(vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *norm extern cvar_t r_vertexdlights; int i; float l; -#ifdef SSE_INTRINSICS - __m128 va, vs, vl, vr; - va = _mm_load_ps(ambientlight); - vs = _mm_load_ps(shadelight); - va.m128_f32[3] = 0; - vs.m128_f32[3] = 1; -#endif - for (i = vertcount-1; i >= 0; i--) + if (VectorCompare(ambientlight, shadelight)) { - l = DotProduct(normals[i], shadevector); + for (i = vertcount-1; i >= 0; i--) + { + colours[i][0] = ambientlight[0]; + colours[i][1] = ambientlight[1]; + colours[i][2] = ambientlight[2]; + } + } + else + { + vec3_t meanambient; #ifdef SSE_INTRINSICS - vl = _mm_load1_ps(&l); - vr = _mm_mul_ss(va,vl); - vr = _mm_add_ss(vr,vs); - - _mm_storeu_ps(colours[i], vr); - //stomp on colour[i][3] (will be set to 1) -#else - colours[i][0] = l*ambientlight[0]+shadelight[0]; - colours[i][1] = l*ambientlight[1]+shadelight[1]; - colours[i][2] = l*ambientlight[2]+shadelight[2]; + __m128 va, vs, vl, vr; + va = _mm_load_ps(ambientlight); + vs = _mm_load_ps(shadelight); + va.m128_f32[3] = 0; + vs.m128_f32[3] = 1; #endif + /*dotproduct will return a value between 1 and -1, so increase the ambient to be correct for normals facing away from the light*/ + VectorMA(ambientlight, 1, shadelight, meanambient); + + for (i = vertcount-1; i >= 0; i--) + { + l = DotProduct(normals[i], shadevector); + #ifdef SSE_INTRINSICS + vl = _mm_load1_ps(&l); + vr = _mm_mul_ss(va,vl); + vr = _mm_add_ss(vr,vs); + + _mm_storeu_ps(colours[i], vr); + //stomp on colour[i][3] (will be set to 1) + #else + colours[i][0] = l*shadelight[0]+meanambient[0]; + colours[i][1] = l*shadelight[1]+meanambient[1]; + colours[i][2] = l*shadelight[2]+meanambient[2]; + #endif + } } if (r_vertexdlights.ival && r_dynamic.ival) @@ -825,8 +841,6 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float extern cvar_t r_nolerp, r_nolightdir; float blerp = 1-lerp; int i; - float l; - int temp; vecV_t *p1v, *p2v; vec3_t *p1n, *p2n; vec3_t *p1s, *p2s; @@ -847,6 +861,7 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float mesh->normals_array = p1n; mesh->snormals_array = p1s; mesh->tnormals_array = p1t; + mesh->colors4f_array = NULL; if (p1v == p2v || r_nolerp.value) { @@ -854,69 +869,18 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float mesh->snormals_array = p1s; mesh->tnormals_array = p1t; mesh->xyz_array = p1v; - if (r_nolightdir.value || nolightdir) - { - mesh->colors4f_array = NULL; - } - else - { - for (i = 0; i < mesh->numvertexes; i++) - { - l = DotProduct(mesh->normals_array[i], shadevector); - - temp = l*ambientlight[0]+shadelight[0]; - mesh->colors4f_array[i][0] = temp; - - temp = l*ambientlight[1]+shadelight[1]; - mesh->colors4f_array[i][1] = temp; - - temp = l*ambientlight[2]+shadelight[2]; - mesh->colors4f_array[i][2] = temp; - - mesh->colors4f_array[i][3] = alpha; - } - } } else { - if (r_nolightdir.ival || nolightdir) + for (i = 0; i < mesh->numvertexes; i++) { - mesh->colors4f_array = NULL; - for (i = 0; i < mesh->numvertexes; i++) - { - mesh->normals_array[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp; - mesh->normals_array[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp; - mesh->normals_array[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp; + mesh->normals_array[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp; + mesh->normals_array[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp; + mesh->normals_array[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp; - mesh->xyz_array[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp; - mesh->xyz_array[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp; - mesh->xyz_array[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp; - } - } - else - { - for (i = 0; i < mesh->numvertexes; i++) - { - mesh->normals_array[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp; - mesh->normals_array[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp; - mesh->normals_array[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp; - - mesh->xyz_array[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp; - mesh->xyz_array[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp; - mesh->xyz_array[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp; - - l = DotProduct(mesh->normals_array[i], shadevector); - temp = l*ambientlight[0]+shadelight[0]; - mesh->colors4f_array[i][0] = temp; - - temp = l*ambientlight[1]+shadelight[1]; - mesh->colors4f_array[i][1] = temp; - - temp = l*ambientlight[2]+shadelight[2]; - mesh->colors4f_array[i][2] = temp; - - mesh->colors4f_array[i][3] = alpha; - } + mesh->xyz_array[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp; + mesh->xyz_array[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp; + mesh->xyz_array[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp; } } if (expand) @@ -1906,6 +1870,132 @@ static void *Q1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) return pframetype; } +static void *H1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) +{ + galiaspose_t *pose; + galiasgroup_t *frame; + dtrivertx_t *pinframe; + daliasframe_t *frameinfo; + int i, j, k; + daliasgroup_t *ingroup; + daliasinterval_t *intervals; + float sinter; + + vec3_t *normals, *svec, *tvec; + vecV_t *verts; + + frame = (galiasgroup_t*)((char *)galias + galias->groupofs); + + for (i = 0; i < pq1inmodel->numframes; i++) + { + switch(LittleLong(pframetype->type)) + { + case ALIAS_SINGLE: + frameinfo = (daliasframe_t*)((char *)(pframetype+1)); + pinframe = (dtrivertx_t*)((char*)frameinfo+sizeof(daliasframe_t)); + pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + (sizeof(vecV_t)+sizeof(vec3_t)*3)*galias->numverts); + frame->poseofs = (char *)pose - (char *)frame; + frame->numposes = 1; + galias->groups++; + + Q_strncpyz(frame->name, frameinfo->name, sizeof(frame->name)); + + verts = (vecV_t *)(pose+1); + normals = (vec3_t*)&verts[galias->numverts]; + svec = &normals[galias->numverts]; + tvec = &svec[galias->numverts]; + pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY + pose->ofsnormals = (char *)normals - (char *)pose; + pose->ofssvector = (char *)svec - (char *)pose; + pose->ofstvector = (char *)tvec - (char *)pose; +#else +#pragma message("wasted memory") +#endif + + for (j = 0; j < galias->numverts; j++) + { + verts[j][0] = pinframe[seamremaps[j]].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; + verts[j][1] = pinframe[seamremaps[j]].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; + verts[j][2] = pinframe[seamremaps[j]].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; +#ifndef SERVERONLY + VectorCopy(r_avertexnormals[pinframe[seamremaps[j]].lightnormalindex], normals[j]); +#endif + } + +// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); + + pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts]; + break; + + case ALIAS_GROUP: + case ALIAS_GROUP_SWAPPED: // prerelease + ingroup = (daliasgroup_t *)(pframetype+1); + + pose = (galiaspose_t *)Hunk_Alloc(LittleLong(ingroup->numframes)*(sizeof(galiaspose_t) + (sizeof(vecV_t)+sizeof(vec3_t)*3)*galias->numverts)); + frame->poseofs = (char *)pose - (char *)frame; + frame->numposes = LittleLong(ingroup->numframes); + frame->loop = true; + galias->groups++; + + verts = (vecV_t *)(pose+frame->numposes); + normals = (vec3_t*)&verts[galias->numverts]; + svec = &normals[galias->numverts]; + tvec = &svec[galias->numverts]; + + intervals = (daliasinterval_t *)(ingroup+1); + sinter = LittleFloat(intervals->interval); + if (sinter <= 0) + sinter = 0.1; + frame->rate = 1/sinter; + + pinframe = (dtrivertx_t *)(intervals+frame->numposes); + for (k = 0; k < frame->numposes; k++) + { + pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY + pose->ofsnormals = (char *)normals - (char *)pose; + pose->ofssvector = (char *)svec - (char *)pose; + pose->ofstvector = (char *)tvec - (char *)pose; +#endif + + frameinfo = (daliasframe_t*)pinframe; + pinframe = (dtrivertx_t *)((char *)frameinfo + sizeof(daliasframe_t)); + + if (k == 0) + Q_strncpyz(frame->name, frameinfo->name, sizeof(frame->name)); + + for (j = 0; j < galias->numverts; j++) + { + verts[j][0] = pinframe[seamremaps[j]].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; + verts[j][1] = pinframe[seamremaps[j]].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; + verts[j][2] = pinframe[seamremaps[j]].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; +#ifndef SERVERONLY + VectorCopy(r_avertexnormals[pinframe[seamremaps[j]].lightnormalindex], normals[j]); +#endif + } + verts = (vecV_t*)&tvec[galias->numverts]; + normals = (vec3_t*)&verts[galias->numverts]; + svec = &normals[galias->numverts]; + tvec = &svec[galias->numverts]; + pose++; + + pinframe += pq1inmodel->numverts; + } + +// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); + + pframetype = (daliasframetype_t *)pinframe; + break; + default: + Con_Printf(CON_ERROR "Bad frame type in %s\n", loadmodel->name); + return NULL; + } + frame++; + } + return pframetype; +} + //greatly reduced version of Q1_LoadSkins //just skips over the data static void *Q1_LoadSkins_SV (daliasskintype_t *pskintype, qboolean alpha) @@ -2010,16 +2100,30 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran if (!TEXVALID(texture)) { snprintf(skinname, sizeof(skinname), "%s__%i", loadname, i); - texture = R_LoadTexture8(skinname, outskin->skinwidth, outskin->skinheight, saved, (skintranstype?0:IF_NOALPHA)|IF_NOGAMMA, skintranstype); - if (r_fb_models.ival) + switch (skintranstype) { - snprintf(skinname, sizeof(skinname), "%s__%i_luma", loadname, i); - fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA); - } - if (gl_bump.ival) - { - snprintf(skinname, sizeof(skinname), "%s__%i_bump", loadname, i); - bumptexture = R_LoadTexture8BumpPal(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA); + default: + texture = R_LoadTexture(skinname,outskin->skinwidth,outskin->skinheight, TF_SOLID8, saved, IF_NOALPHA|IF_NOGAMMA); + if (r_fb_models.ival) + { + snprintf(skinname, sizeof(skinname), "%s__%i_luma", loadname, i); + fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA); + } + if (gl_bump.ival) + { + snprintf(skinname, sizeof(skinname), "%s__%i_bump", loadname, i); + bumptexture = R_LoadTexture8BumpPal(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA); + } + break; + case 2: + texture = R_LoadTexture(skinname,outskin->skinwidth,outskin->skinheight, TF_H2_T7G1, saved, IF_NOGAMMA); + break; + case 3: + texture = R_LoadTexture(skinname,outskin->skinwidth,outskin->skinheight, TF_H2_TRANS8_0, saved, IF_NOGAMMA); + break; + case 4: + texture = R_LoadTexture(skinname,outskin->skinwidth,outskin->skinheight, TF_H2_T4A4, saved, IF_NOGAMMA); + break; } } } @@ -2032,7 +2136,27 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran sprintf(skinname, "%s_%i", loadname, i); - texnums->shader = R_RegisterSkin(skinname); + if (skintranstype == 4) + texnums->shader = R_RegisterShader(skinname, + "{\n" + "{\n" + "map $diffuse\n" + "blendfunc gl_one_minus_src_alpha gl_src_alpha\n" + "rgbgen lightingDiffuse\n" + "cull disable\n" + "}\n" + "}\n"); + else if (skintranstype) + texnums->shader = R_RegisterShader(skinname, + "{\n" + "{\n" + "map $diffuse\n" + "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" + "rgbgen lightingDiffuse\n" + "}\n" + "}\n"); + else + texnums->shader = R_RegisterSkin(skinname); R_BuildDefaultTexnums(texnums, texnums->shader); texnums->loweroverlay = r_nulltex; @@ -2159,14 +2283,16 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) int version; int i, onseams; dstvert_t *pinstverts; - dtriangle_t *pintriangles; + dtriangle_t *pinq1triangles; + dh2triangle_t *pinh2triangles; int *seamremap; index_t *indexes; - qboolean qtest = false; daliasskintype_t *skinstart; int skintranstype; int size; + unsigned int hdrsize; + void *end; loadmodel=mod; @@ -2174,11 +2300,17 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) pq1inmodel = (dmdl_t *)buffer; + hdrsize = sizeof(dmdl_t) - sizeof(int); + loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; version = LittleLong(pq1inmodel->version); if (version == QTESTALIAS_VERSION) - qtest = true; + { + hdrsize = sizeof(dmdl_t) - sizeof(int)*3; + } + else if (version == 50) + hdrsize = sizeof(dmdl_t); else if (version != ALIAS_VERSION) { Con_Printf (CON_ERROR "%s has wrong version number (%i should be %i)\n", @@ -2188,10 +2320,7 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) seamremap = (int*)pq1inmodel; //I like overloading locals. - if (qtest) - i = sizeof(dmdl_t)/4 - sizeof(int)*2 - 1; - else - i = sizeof(dmdl_t)/4 - 1; + i = hdrsize/4 - 1; for (; i >= 0; i--) seamremap[i] = LittleLong(seamremap[i]); @@ -2207,7 +2336,7 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) return false; } - if (qtest) + if (hdrsize <= (unsigned int)&((dmdl_t*)NULL)->flags) mod->flags = 0; // Qtest has no flags in header else mod->flags = pq1inmodel->flags; @@ -2226,10 +2355,8 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) galias->nextsurf = 0; //skins - if (qtest) - skinstart = (daliasskintype_t *)((char *)buffer + sizeof(dmdl_t) - sizeof(int)*2); - else - skinstart = (daliasskintype_t *)(pq1inmodel+1); + skinstart = (daliasskintype_t *)((char*)pq1inmodel+hdrsize); + if( mod->flags & EFH2_HOLEY ) skintranstype = 3; //hexen2 else if( mod->flags & EFH2_TRANSPARENT ) @@ -2252,81 +2379,155 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) break; } - - - //count number of verts that are onseam. - for (onseams=0,i = 0; i < pq1inmodel->numverts; i++) + if (hdrsize == sizeof(dmdl_t)) { - if (pinstverts[i].onseam) - onseams++; - } - seamremap = BZ_Malloc(sizeof(int)*pq1inmodel->numverts); + int t, v, k; + int *stremap; + /*separate st + vert lists*/ + pinh2triangles = (dh2triangle_t *)&pinstverts[pq1inmodel->num_st]; - galias->numverts = pq1inmodel->numverts+onseams; + /*each triangle can use one coord and one st, for each vert, that's a lot of combinations*/ + + seamremap = BZ_Malloc(sizeof(int)*pq1inmodel->numtris*6); + stremap = seamremap + pq1inmodel->numtris*3; - //st -#ifndef SERVERONLY - st_array = Hunk_Alloc(sizeof(*st_array)*(pq1inmodel->numverts+onseams)); - galias->ofs_st_array = (char *)st_array - (char *)galias; - for (j=pq1inmodel->numverts,i = 0; i < pq1inmodel->numverts; i++) - { - st_array[i][0] = (LittleLong(pinstverts[i].s)+0.5)/(float)pq1inmodel->skinwidth; - st_array[i][1] = (LittleLong(pinstverts[i].t)+0.5)/(float)pq1inmodel->skinheight; - - if (pinstverts[i].onseam) + /*output the indicies as we figure out which verts we want*/ + galias->numindexes = pq1inmodel->numtris*3; + indexes = Hunk_Alloc(galias->numindexes*sizeof(*indexes)); + galias->ofs_indexes = (char *)indexes - (char *)galias; + for (i = 0; i < pq1inmodel->numtris; i++) { - st_array[j][0] = st_array[i][0]+0.5; - st_array[j][1] = st_array[i][1]; - seamremap[i] = j; - j++; + for (j = 0; j < 3; j++) + { + v = LittleShort(pinh2triangles[i].vertindex[j]); + t = LittleShort(pinh2triangles[i].stindex[j]); + if (pinstverts[t].onseam && !pinh2triangles[i].facesfront) + t += pq1inmodel->num_st; + for (k = 0; k < galias->numverts; k++) /*big fatoff slow loop*/ + { + if (stremap[k] == t && seamremap[k] == v) + break; + } + if (k == galias->numverts) + { + galias->numverts++; + stremap[k] = t; + seamremap[k] = v; + } + indexes[i*3+j] = k; + } } - else - seamremap[i] = i; - } -#endif - //trianglelists; - pintriangles = (dtriangle_t *)&pinstverts[pq1inmodel->numverts]; - - galias->numindexes = pq1inmodel->numtris*3; - indexes = Hunk_Alloc(galias->numindexes*sizeof(*indexes)); - galias->ofs_indexes = (char *)indexes - (char *)galias; - for (i=0 ; inumtris ; i++) - { - if (!pintriangles[i].facesfront) + st_array = Hunk_Alloc(sizeof(*st_array)*(galias->numverts)); + galias->ofs_st_array = (char *)st_array - (char *)galias; + /*generate our st_array now we know which vertexes we want*/ + for (k = 0; k < galias->numverts; k++) { - indexes[i*3+0] = seamremap[LittleLong(pintriangles[i].vertindex[0])]; - indexes[i*3+1] = seamremap[LittleLong(pintriangles[i].vertindex[1])]; - indexes[i*3+2] = seamremap[LittleLong(pintriangles[i].vertindex[2])]; + if (stremap[k] > pq1inmodel->num_st) + { /*onseam verts? shrink the index, and add half a texture width to the s coord*/ + st_array[k][0] = 0.5+(LittleLong(pinstverts[stremap[k]-pq1inmodel->num_st].s)+0.5)/(float)pq1inmodel->skinwidth; + st_array[k][1] = (LittleLong(pinstverts[stremap[k]-pq1inmodel->num_st].t)+0.5)/(float)pq1inmodel->skinheight; + } + else + { + st_array[k][0] = (LittleLong(pinstverts[stremap[k]].s)+0.5)/(float)pq1inmodel->skinwidth; + st_array[k][1] = (LittleLong(pinstverts[stremap[k]].t)+0.5)/(float)pq1inmodel->skinheight; + } } - else - { - indexes[i*3+0] = LittleLong(pintriangles[i].vertindex[0]); - indexes[i*3+1] = LittleLong(pintriangles[i].vertindex[1]); - indexes[i*3+2] = LittleLong(pintriangles[i].vertindex[2]); - } - } - //frames - if (qtest) - { - if (QTest_LoadFrameGroup((daliasframetype_t *)&pintriangles[pq1inmodel->numtris], seamremap) == NULL) + end = &pinh2triangles[pq1inmodel->numtris]; + + if (H1_LoadFrameGroup((daliasframetype_t *)end, seamremap) == NULL) { BZ_Free(seamremap); Hunk_FreeToLowMark (hunkstart); return false; } + + BZ_Free(seamremap); } else { - if (Q1_LoadFrameGroup((daliasframetype_t *)&pintriangles[pq1inmodel->numtris], seamremap) == NULL) + /*onseam means +=skinwidth/2 + verticies that are marked as onseam potentially generate two output verticies. + the triangle chooses which side based upon its 'onseam' field. + */ + + //count number of verts that are onseam. + for (onseams=0,i = 0; i < pq1inmodel->numverts; i++) { - BZ_Free(seamremap); - Hunk_FreeToLowMark (hunkstart); - return false; + if (pinstverts[i].onseam) + onseams++; } + seamremap = BZ_Malloc(sizeof(int)*pq1inmodel->numverts); + + galias->numverts = pq1inmodel->numverts+onseams; + + //st + #ifndef SERVERONLY + st_array = Hunk_Alloc(sizeof(*st_array)*(pq1inmodel->numverts+onseams)); + galias->ofs_st_array = (char *)st_array - (char *)galias; + for (j=pq1inmodel->numverts,i = 0; i < pq1inmodel->numverts; i++) + { + st_array[i][0] = (LittleLong(pinstverts[i].s)+0.5)/(float)pq1inmodel->skinwidth; + st_array[i][1] = (LittleLong(pinstverts[i].t)+0.5)/(float)pq1inmodel->skinheight; + + if (pinstverts[i].onseam) + { + st_array[j][0] = st_array[i][0]+0.5; + st_array[j][1] = st_array[i][1]; + seamremap[i] = j; + j++; + } + else + seamremap[i] = i; + } + #endif + + //trianglelists; + pinq1triangles = (dtriangle_t *)&pinstverts[pq1inmodel->numverts]; + + galias->numindexes = pq1inmodel->numtris*3; + indexes = Hunk_Alloc(galias->numindexes*sizeof(*indexes)); + galias->ofs_indexes = (char *)indexes - (char *)galias; + for (i=0 ; inumtris ; i++) + { + if (!pinq1triangles[i].facesfront) + { + indexes[i*3+0] = seamremap[LittleLong(pinq1triangles[i].vertindex[0])]; + indexes[i*3+1] = seamremap[LittleLong(pinq1triangles[i].vertindex[1])]; + indexes[i*3+2] = seamremap[LittleLong(pinq1triangles[i].vertindex[2])]; + } + else + { + indexes[i*3+0] = LittleLong(pinq1triangles[i].vertindex[0]); + indexes[i*3+1] = LittleLong(pinq1triangles[i].vertindex[1]); + indexes[i*3+2] = LittleLong(pinq1triangles[i].vertindex[2]); + } + } + end = &pinq1triangles[pq1inmodel->numtris]; + + //frames + if (hdrsize <= (unsigned int)&((dmdl_t*)NULL)->flags) + { + if (QTest_LoadFrameGroup((daliasframetype_t *)end, seamremap) == NULL) + { + BZ_Free(seamremap); + Hunk_FreeToLowMark (hunkstart); + return false; + } + } + else + { + if (Q1_LoadFrameGroup((daliasframetype_t *)end, seamremap) == NULL) + { + BZ_Free(seamremap); + Hunk_FreeToLowMark (hunkstart); + return false; + } + } + BZ_Free(seamremap); } - BZ_Free(seamremap); Mod_CompileTriangleNeighbours(galias); @@ -4139,6 +4340,261 @@ qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer) #endif //ZYMOTICMODELS + +#ifdef INTERQUAKEMODELS +#define IQM_MAGIC "INTERQUAKEMODEL" +#define IQM_VERSION 1 + +struct iqmheader +{ + char magic[16]; + unsigned int version; + unsigned int filesize; + unsigned int flags; + unsigned int num_text, ofs_text; + 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; + unsigned int num_poses, ofs_poses; + unsigned int num_anims, ofs_anims; + unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds; + unsigned int num_comment, ofs_comment; + unsigned int num_extensions, ofs_extensions; +}; + +struct iqmmesh +{ + unsigned int name; + unsigned int material; + unsigned int first_vertex, num_vertexes; + unsigned int first_triangle, num_triangles; +}; + +enum +{ + IQM_POSITION = 0, + IQM_TEXCOORD = 1, + IQM_NORMAL = 2, + IQM_TANGENT = 3, + IQM_BLENDINDEXES = 4, + IQM_BLENDWEIGHTS = 5, + IQM_COLOR = 6, + IQM_CUSTOM = 0x10 +}; + +enum +{ + IQM_BYTE = 0, + IQM_UBYTE = 1, + IQM_SHORT = 2, + IQM_USHORT = 3, + IQM_INT = 4, + IQM_UINT = 5, + IQM_HALF = 6, + IQM_FLOAT = 7, + IQM_DOUBLE = 8, +}; + +struct iqmtriangle +{ + unsigned int vertex[3]; +}; + +struct iqmjoint +{ + unsigned int name; + int parent; + float translate[3], rotate[3], scale[3]; +}; + +struct iqmpose +{ + int parent; + unsigned int mask; + float channeloffset[9]; + float channelscale[9]; +}; + +struct iqmanim +{ + unsigned int name; + unsigned int first_frame, num_frames; + float framerate; + unsigned int flags; +}; + +enum +{ + IQM_LOOP = 1<<0 +}; + +struct iqmvertexarray +{ + unsigned int type; + unsigned int flags; + unsigned int format; + unsigned int size; + unsigned int offset; +}; + +struct iqmbounds +{ + float bbmin[3], bbmax[3]; + float xyradius, radius; +}; + +galisskeletaltransforms_t *IQM_ImportTransforms(int *resultcount, int inverts, float *vpos, float *tcoord, float *vnorm, float *vtang, unsigned char *vbone, unsigned char *vweight) +{ + galisskeletaltransforms_t *t, *r; + unsigned int num_t = 0; + unsigned int 0; + for (v = 0; v < inverts*4; v++) + { + if (vweight[v]) + num_t++; + } + t = r = Hunk_Alloc(sizeof(*r)*num_t); + for (v = 0; v < inverts; v++) + { + for (j = 0; j < 4; j++) + { + if (vweight[v<<2+j]) + { + t->boneindex = vbone[v<<2+j]; + t->vertexindex = v; + VectorScale(vpos, vweight[v<<2+j]/255.0, t->org); + VectorScale(vnorm, vweight[v<<2+j]/255.0, t->normal); + t++; + } + } + } + return r; +} + +galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer) +{ + struct iqmheader *h = (struct iqmheader *)buffer; + struct iqmjoint *joint; + struct iqmmesh *mesh; + struct iqmvertexarray *varray; + + galiasinfo_t *gai; + + if (memcmp(h->magic, IQM_MAGIC, sizeof(h->magic)) + { + Con_Printf("%s: format not recognised\n", mod->name); + return false; + } + if (h->version != IQM_VERSION) + { + Con_Printf("%s: unsupported version\n", mod->name); + return false; + } + if (h->filesize != com_filesize) + { + Con_Printf("%s: size (%u != %u)\n", mod->name, h->filesize, com_filesize); + return false; + } + + 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; + + + float *vpos = NULL, *tcoord = NULL, *vnorm = NULL, *vtang = NULL; + unsigned char *vbone = NULL, *vweight = NULL; + unsigned int type, fmt, size, offset; + + varray = (struct iqmvertexarray*)(buffer + h->ofs_vertexarrays); + for (i = 0; i < h->num_vertexarrays; i++) + { + type = LittleLong(varray[i].type); + fmt = LittleLong(varray[i].format); + size = LittleLong(varray[i].size); + offset = LittleLong(varray[i].offset); + if (type == IQM_POSITION && fmt == IQM_FLOAT && size == 3) + vpos = (float*)(buffer + offset); + else if (type == IQM_TEXCOORD && fmt == IQM_FLOAT && size == 2) + tcoord = (float*)(buffer + offset); + else if (type == IQM_NORMAL && fmt == IQM_FLOAT && size == 3) + vnorm = (float*)(buffer + offset); + else if (type == IQM_TANGENT && fmt == IQM_FLOAT && size == 4) /*yup, 4*/ + vtang = (float*)(buffer + offset); + else if (type == IQM_BLENDINDEXES && fmt == IQM_UBYTE && size == 4) + vbone = (unsigned char *)(buffer + offset); + else if (type == IQM_BLENDWEIGHTS && fmt == IQM_UBYTE && size == 4) + vweight = (unsigned char *)(buffer + offset); + } + + gai = Hunk_Alloc(sizeof(*gai)*h->num_meshes); + for (i = 0; i < h->num_meshes; i++) + { + gai[i].nextsurf = (i == (h->num_meshes-1))?0:sizeof(*gai); + gai[i].sharesverts = false; //used with models with two shaders using the same vertex - use last mesh's verts + gai[i].sharesbones = i != 0; + gai[i].numverts = LittleLong(mesh[i].num_vertexes); + offset = LittleLong(mesh[i].first_vertex); + + /*generate transforms for each vertex*/ + gai[i].ofstransforms = (char*)IQM_ImportTransforms(&gai[i].numtransforms, gai[i].numverts, vpos+offset*3, tcoord+offset*2, vnorm+offset*3, vtang+offset*4, vbone+offset*4, vweight+offset*4) - (char*)gai; + } +galiasinfo_t + unsigned int name; + unsigned int material; + unsigned int first_vertex, num_vertexes; + unsigned int first_triangle, num_triangles; + +} + +qboolean Mod_ParseIQMAnim(char *buffer, galiasinfo_t *prototype, void**poseofs, galiasgroup_t *gat) +{ +} + + + +qboolean Mod_LoadInterQuakeModel(model_t *mod, void *buffer) +{ + galiasinfo_t *root; + struct iqmheader *h = (struct iqmheader *)buffer; + + hunkstart = Hunk_LowMark(); + root = Mod_ParseMD5MeshModel(buffer); + if (!root) + return false; + hunkend = Hunk_LowMark(); + + mod->flags = h->flags; + + Mod_ClampModelSize(mod); + + Hunk_Alloc(0); + hunktotal = hunkend - hunkstart; + + Cache_Alloc (&mod->cache, hunktotal, loadname); + mod->type = mod_alias; + if (!mod->cache.data) + { + Hunk_FreeToLowMark (hunkstart); + return false; + } + memcpy (mod->cache.data, root, hunktotal); + + Hunk_FreeToLowMark (hunkstart); + return true; +} +#endif + + + + + #ifdef MD5MODELS static void GenMatrix(float x, float y, float z, float qx, float qy, float qz, float result[12]) diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index 0abb3eb50..ef0b1b0f3 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -141,6 +141,9 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer); qboolean Mod_LoadMD5MeshModel(model_t *mod, void *buffer); qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer); #endif +#ifdef MAP_PROC + qboolean Mod_LoadMap_Proc(model_t *mode, void *buffer); +#endif void Mod_AccumulateTextureVectors(vecV_t *vc, vec2_t *tc, vec3_t *nv, vec3_t *sv, vec3_t *tv, index_t *idx, int numidx); void Mod_AccumulateMeshTextureVectors(mesh_t *mesh); diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index e4df89b3a..3bb068d89 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -1883,8 +1883,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) ed->ode.ode_geom = (void *)dCreateSphere(world->ode.ode_space, geomsize[0] * 0.5f); dMassSetSphereTotal(&mass, massval, geomsize[0] * 0.5f); break; -#pragma message("SOLID_PHYSICS_CAPSULE not supported") -/* case SOLID_PHYSICS_CAPSULE: + case SOLID_PHYSICS_CAPSULE: axisindex = 0; if (geomsize[axisindex] < geomsize[1]) axisindex = 1; @@ -1896,11 +1895,11 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) // transform to it memset(capsulerot, 0, sizeof(capsulerot)); if (axisindex == 0) - Matrix4_CreateFromQuakeEntity(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 90, 1); + Matrix4_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 90, 1); else if (axisindex == 1) - Matrix4_CreateFromQuakeEntity(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 90, 0, 0, 1); + Matrix4_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 90, 0, 0, 1); else - Matrix4_CreateFromQuakeEntity(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 0, 1); + Matrix4_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 0, 1); radius = geomsize[!axisindex] * 0.5f; // any other axis is the radius length = geomsize[axisindex] - radius*2; // because we want to support more than one axisindex, we have to @@ -1909,7 +1908,6 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) ed->ode.ode_geom = (void *)dCreateCapsule(world->ode.ode_space, radius, length); dMassSetCapsuleTotal(&mass, massval, axisindex+1, radius, length); break; -*/ default: Sys_Error("World_Physics_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid); } diff --git a/engine/common/common.c b/engine/common/common.c index 3409992a4..79bf9d300 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -759,8 +759,6 @@ void MSG_WriteString (sizebuf_t *sb, const char *s) SZ_Write (sb, s, Q_strlen(s)+1); } -int sizeofcoord=2; -int sizeofangle=1; float MSG_FromCoord(coorddata c, int bytes) { switch(bytes) @@ -829,8 +827,8 @@ coorddata MSG_ToAngle(float f, int bytes) //return value is NOT byteswapped. void MSG_WriteCoord (sizebuf_t *sb, float f) { - coorddata i = MSG_ToCoord(f, sizeofcoord); - SZ_Write (sb, (void*)&i, sizeofcoord); + coorddata i = MSG_ToCoord(f, sb->prim.coordsize); + SZ_Write (sb, (void*)&i, sb->prim.coordsize); } void MSG_WriteAngle16 (sizebuf_t *sb, float f) @@ -850,8 +848,10 @@ void MSG_WriteAngle8 (sizebuf_t *sb, float f) void MSG_WriteAngle (sizebuf_t *sb, float f) { - if (sizeofangle==2) + if (sb->prim.anglesize==2) MSG_WriteAngle16(sb, f); + else if (sb->prim.anglesize==4) + MSG_WriteFloat(sb, f); else MSG_WriteAngle8 (sb, f); } @@ -959,13 +959,20 @@ void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd) // int msg_readcount; qboolean msg_badread; +struct netprim_s msg_nullnetprim; -void MSG_BeginReading (void) +void MSG_BeginReading (struct netprim_s prim) { msg_readcount = 0; msg_badread = false; net_message.currentbit = 0; net_message.packing = SZ_RAWBYTES; + net_message.prim = prim; +} + +void MSG_ChangePrimitives(struct netprim_s prim) +{ + net_message.prim = prim; } int MSG_GetReadCount(void) @@ -1286,8 +1293,8 @@ char *MSG_ReadStringLine (void) float MSG_ReadCoord (void) { coorddata c = {{0}}; - MSG_ReadData(&c, sizeofcoord); - return MSG_FromCoord(c, sizeofcoord); + MSG_ReadData(&c, net_message.prim.coordsize); + return MSG_FromCoord(c, net_message.prim.coordsize); } void MSG_ReadPos (vec3_t pos) @@ -1297,12 +1304,14 @@ void MSG_ReadPos (vec3_t pos) pos[2] = MSG_ReadCoord(); } +#if defined(Q2CLIENT) || defined(Q2SERVER) #define Q2NUMVERTEXNORMALS 162 vec3_t bytedirs[Q2NUMVERTEXNORMALS] = { #include "../client/q2anorms.h" }; -#ifndef SERVERONLY +#endif +#ifdef Q2CLIENT void MSG_ReadDir (vec3_t dir) { int b; @@ -1316,6 +1325,7 @@ void MSG_ReadDir (vec3_t dir) VectorCopy (bytedirs[b], dir); } #endif +#ifdef Q2SERVER void MSG_WriteDir (sizebuf_t *sb, vec3_t dir) { int i, best; @@ -1340,6 +1350,7 @@ void MSG_WriteDir (sizebuf_t *sb, vec3_t dir) } MSG_WriteByte (sb, best); } +#endif float MSG_ReadAngle16 (void) { @@ -1347,9 +1358,18 @@ float MSG_ReadAngle16 (void) } float MSG_ReadAngle (void) { - if (sizeofangle==2) + switch(net_message.prim.anglesize) + { + case 2: return MSG_ReadAngle16(); - return MSG_ReadChar() * (360.0/256); + case 4: + return MSG_ReadFloat(); + case 1: + return MSG_ReadChar() * (360.0/256); + default: + Host_Error("Bad angle size\n"); + return 0; + } } void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move) diff --git a/engine/common/common.h b/engine/common/common.h index 4fa3e6da4..485634377 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -38,6 +38,11 @@ typedef enum {false, true} qboolean; #define MAX_SERVERINFO_STRING 1024 //standard quake has 512 here. #define MAX_LOCALINFO_STRING 32768 +struct netprim_s +{ + int coordsize; + int anglesize; +}; //============================================================================ typedef enum { @@ -55,6 +60,8 @@ typedef struct sizebuf_s int cursize; int packing; int currentbit; + + struct netprim_s prim; } sizebuf_t; void SZ_Clear (sizebuf_t *buf); @@ -127,8 +134,6 @@ typedef union { //note: reading from packets can be misaligned int b4; float f; } coorddata; -extern int sizeofcoord; -extern int sizeofangle; float MSG_FromCoord(coorddata c, int bytes); coorddata MSG_ToCoord(float f, int bytes); coorddata MSG_ToAngle(float f, int bytes); @@ -149,8 +154,10 @@ void MSG_WriteDir (sizebuf_t *sb, float *dir); extern int msg_readcount; extern qboolean msg_badread; // set if a read goes beyond end of message +struct netprim_s msg_nullnetprim; -void MSG_BeginReading (void); +void MSG_BeginReading (struct netprim_s prim); +void MSG_ChangePrimitives(struct netprim_s prim); int MSG_GetReadCount(void); int MSG_ReadChar (void); int MSG_ReadBits(int bits); diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 0efba7b17..d49ce5a28 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -148,6 +148,8 @@ char *Cvar_FlagToName(int flag) return "nounsafeexpand"; case CVAR_RULESETLATCH: return "rulesetlatch"; + case CVAR_SHADERSYSTEM: + return "shadersystem"; } return NULL; diff --git a/engine/common/fs.c b/engine/common/fs.c index bfdf7cc77..9ef2794e9 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -292,12 +292,12 @@ void COM_Locate_f (void) { if (!*loc.rawname) { - Con_Printf("File is compressed inside "); + Con_Printf("File is %i bytes compressed inside ", loc.len); loc.search->funcs->PrintPath(loc.search->handle); } else { - Con_Printf("Inside %s\n", loc.rawname); + Con_Printf("Inside %s (%i bytes)\n", loc.rawname, loc.len); loc.search->funcs->PrintPath(loc.search->handle); } } @@ -1803,6 +1803,7 @@ void COM_Gamedir (const char *dir) #define DPCOMPAT "set dpcompat_set 1\nset dpcompat_trailparticles 1\n" #define NEXCFG DPCOMPAT "set sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\nset r_particlesdesc effectinfo\n" #define DMFCFG "set com_parseutf8 1\npm_airstep 1\n" +#define HEX2CFG "set sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\n" typedef struct { const char *protocolname; //sent to the master server when this is the current gamemode. @@ -1828,9 +1829,11 @@ const gamemode_info_t gamemode_info[] = { {"DMF", "dmf", "-dmf", "base/src/progs.src",DMFCFG,{"base", }, "DMF"}, //supported commercial mods (some are currently only partially supported) - {"FTE-Hexen2", "hexen", "-hexen2", "data1/pak0.pak", NULL, {"data1", "fteh2"}, "Hexen II"}, + {"FTE-H2MP", "h2mp", "-portals", "portals/hexen.rc", HEX2CFG,{"data1", "portals", "fteh2"}, "Hexen II MP"}, + {"FTE-Hexen2", "hexen", "-hexen2", "data1/pak0.pak", HEX2CFG,{"data1", "fteh2"}, "Hexen II"}, {"FTE-Quake2", "q2", "-q2", "baseq2/pak0.pak", NULL, {"baseq2", "fteq2"}, "Quake II"}, {"FTE-Quake3", "q3", "-q3", "baseq3/pak0.pk3", NULL, {"baseq3", "fteq3"}, "Quake III Arena"}, + {"FTE-Quake4", "q4", "-q4", "q4base/pak00.pk4", NULL, {"q4base", "fteq4"}, "Quake 4"}, {"FTE-JK2", "jk2", "-jk2", "base/assets0.pk3", NULL, {"base", "fte"}, "Jedi Knight II: Jedi Outcast"}, diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 0c258ff79..6302f9263 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -3886,7 +3886,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned } #ifndef SERVERONLY - Mod_ParseInfoFromEntityLump(loadmodel->entities, loadname); //only done for client's world model (or server if the server is loading it for client) + Mod_ParseInfoFromEntityLump(loadmodel, loadmodel->entities, loadname); //only done for client's world model (or server if the server is loading it for client) #endif CM_InitBoxHull (); diff --git a/engine/common/huff.c b/engine/common/huff.c index 1c3082550..b49c7122d 100644 --- a/engine/common/huff.c +++ b/engine/common/huff.c @@ -595,7 +595,7 @@ beginning from specified offset void Huff_EncryptPacket(sizebuf_t *msg, int offset) { tree_t tree; - qbyte buffer[MAX_NQMSGLEN]; + qbyte buffer[MAX_OVERALLMSGLEN]; qbyte *data; int outLen; int inLen; @@ -603,7 +603,7 @@ void Huff_EncryptPacket(sizebuf_t *msg, int offset) data = msg->data + offset; inLen = msg->cursize - offset; - if (inLen <= 0 || inLen >= MAX_NQMSGLEN) + if (inLen <= 0 || inLen >= MAX_OVERALLMSGLEN) { return; } @@ -638,7 +638,7 @@ beginning from specified offset void Huff_DecryptPacket(sizebuf_t *msg, int offset) { tree_t tree; - qbyte buffer[MAX_NQMSGLEN]; + qbyte buffer[MAX_OVERALLMSGLEN]; qbyte *data; int outLen; int inLen; @@ -784,7 +784,7 @@ beginning from specified offset */ void Huff_CompressPacket( sizebuf_t *msg, int offset ) { - qbyte buffer[MAX_NQMSGLEN]; + qbyte buffer[MAX_OVERALLMSGLEN]; qbyte *data; int outLen; int inLen; @@ -795,7 +795,7 @@ void Huff_CompressPacket( sizebuf_t *msg, int offset ) data = msg->data + offset; inLen = msg->cursize - offset; - if (inLen <= 0 || inLen >= MAX_NQMSGLEN) + if (inLen <= 0 || inLen >= MAX_OVERALLMSGLEN) { return; } @@ -803,7 +803,7 @@ void Huff_CompressPacket( sizebuf_t *msg, int offset ) outLen = 0; for (i=0; i < inLen; i++) { - if (i == MAX_NQMSGLEN) + if (i == MAX_OVERALLMSGLEN) Sys_Error("Compression became too large\n"); Huff_EmitByte(data[i], buffer, &outLen); @@ -841,7 +841,7 @@ beginning from specified offset */ void Huff_DecompressPacket(sizebuf_t *msg, int offset) { - qbyte buffer[MAX_NQMSGLEN]; + qbyte buffer[MAX_OVERALLMSGLEN]; qbyte *data; int outLen; int inLen; @@ -852,7 +852,7 @@ void Huff_DecompressPacket(sizebuf_t *msg, int offset) data = msg->data + offset; inLen = msg->cursize - offset; - if (inLen <= 0 || inLen >= MAX_NQMSGLEN) + if (inLen <= 0 || inLen >= MAX_OVERALLMSGLEN) { return; } @@ -872,7 +872,7 @@ void Huff_DecompressPacket(sizebuf_t *msg, int offset) outLen = 0; for(i=0; outLen < inLen; i++) { - if (i == MAX_NQMSGLEN) + if (i == MAX_OVERALLMSGLEN) Sys_Error("Decompression became too large\n"); buffer[i] = Huff_GetByte(data, &outLen); } diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 2c56e2229..27eb9cd60 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -1061,6 +1061,36 @@ void Matrix4_ModelMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t Matrix4_Multiply(Matrix4_NewTranslation(vieworg[0], vieworg[1], vieworg[2]), tempmat, modelview); // put Z going up } +void Matrix4_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitch, vec_t yaw, vec_t roll, vec_t scale) +{ + float tempmat[16]; + //load identity. + memset(modelview, 0, sizeof(*modelview)*16); +#if FULLYGL + modelview[0] = 1; + modelview[5] = 1; + modelview[10] = 1; + modelview[15] = 1; + + Matrix4_Multiply(modelview, Matrix4_NewRotation(-90, 1, 0, 0), tempmat); // put Z going up + Matrix4_Multiply(tempmat, Matrix4_NewRotation(90, 0, 0, 1), modelview); // put Z going up +#else + //use this lame wierd and crazy identity matrix.. + modelview[2] = -1; + modelview[4] = -1; + modelview[9] = 1; + modelview[15] = 1; +#endif + //figure out the current modelview matrix + + //I would if some of these, but then I'd still need a couple of copys + Matrix4_Multiply(modelview, Matrix4_NewRotation(-roll, 1, 0, 0), tempmat); + Matrix4_Multiply(tempmat, Matrix4_NewRotation(-pitch, 0, 1, 0), modelview); + Matrix4_Multiply(modelview, Matrix4_NewRotation(-yaw, 0, 0, 1), tempmat); + + Matrix4_Multiply(tempmat, Matrix4_NewTranslation(x, y, z), modelview); +} + void Matrix4_Identity(float *outm) { outm[ 0] = 1; diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 5f9b0dc48..ca3240029 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -137,6 +137,7 @@ void Matrix4Q_Invert_Simple (const float *in1, float *out); void Matrix4_CreateTranslate (float *out, float x, float y, float z); void Matrix4Q_CreateTranslate (float *out, float x, float y, float z); void Matrix4_ModelMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); +void Matrix4_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitch, vec_t yaw, vec_t roll, vec_t scale); void Matrix4_ModelViewMatrix (float *modelview, const vec3_t viewangles, const vec3_t vieworg); void Matrix4_ModelViewMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); void Matrix4_CreateFromQuakeEntity (float *matrix, float x, float y, float z, float pitch, float yaw, float roll, float scale); diff --git a/engine/common/net.h b/engine/common/net.h index 8dcbc4cfd..5a113ee11 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -117,6 +117,7 @@ typedef struct #ifdef NQPROT qboolean isnqprotocol; + struct netprim_s netprim; #endif float last_received; // for timeouts diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 06be21e36..cb3a8fa89 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -244,7 +244,7 @@ nqprot_t NQNetChan_Process(netchan_t *chan) int sequence; int drop; - MSG_BeginReading (); + MSG_BeginReading (chan->netprim); header = LongSwap(MSG_ReadLong()); if (net_message.cursize != (header & NETFLAG_LENGTH_MASK)) @@ -326,7 +326,7 @@ nqprot_t NQNetChan_Process(netchan_t *chan) SZ_Clear(&net_message); SZ_Write(&net_message, chan->in_fragment_buf, chan->in_fragment_length); chan->in_fragment_length = 0; - MSG_BeginReading(); + MSG_BeginReading(chan->netprim); return NQP_RELIABLE; //we can read it now } } @@ -548,7 +548,7 @@ qboolean Netchan_Process (netchan_t *chan) return false; // get sequence numbers - MSG_BeginReading (); + MSG_BeginReading (chan->netprim); sequence = MSG_ReadLong (); sequence_ack = MSG_ReadLong (); diff --git a/engine/common/pmove.c b/engine/common/pmove.c index 434949598..c347110ce 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -952,18 +952,18 @@ void PM_NudgePosition (void) vec3_t base; int x, y, z; int i; - static int sign[3] = {0, -1, 1}; + static int sign[5] = {0, -1, 1, -2, 2}; VectorCopy (pmove.origin, base); for (i=0 ; i<3 ; i++) pmove.origin[i] = ((int)(pmove.origin[i]*8)) * 0.125; - for (z=0 ; z<=2 ; z++) + for (z=0 ; z<=4 ; z++) { - for (x=0 ; x<=2 ; x++) + for (x=0 ; x<=4 ; x++) { - for (y=0 ; y<=2 ; y++) + for (y=0 ; y<=4 ; y++) { pmove.origin[0] = base[0] + (sign[x] * 1.0/8); pmove.origin[1] = base[1] + (sign[y] * 1.0/8); diff --git a/engine/common/pmovetst.c b/engine/common/pmovetst.c index 21cc09ffe..52b678fea 100644 --- a/engine/common/pmovetst.c +++ b/engine/common/pmovetst.c @@ -363,18 +363,24 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end) if (pe->nonsolid) continue; - if (!pe->model) + if (!pe->model || pe->model->needload) { vec3_t mins, maxs; VectorSubtract (pe->mins, player_maxs, mins); VectorSubtract (pe->maxs, player_mins, maxs); PM_HullForBox (mins, maxs); - } - // trace a line through the apropriate clipping hull - if (!PM_TransformedHullCheck (pe->model, start, end, &trace, pe->origin, pe->angles)) - continue; + // trace a line through the apropriate clipping hull + if (!PM_TransformedHullCheck (NULL, start, end, &trace, pe->origin, pe->angles)) + continue; + } + else + { + // trace a line through the apropriate clipping hull + if (!PM_TransformedHullCheck (pe->model, start, end, &trace, pe->origin, pe->angles)) + continue; + } if (trace.allsolid) trace.startsolid = true; diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 3064b14d9..ae9f736cd 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -2833,6 +2833,7 @@ lh_extension_t QSG_Extensions[] = { {"ZQ_MOVETYPE_NOCLIP"}, {"ZQ_MOVETYPE_NONE"}, // {"ZQ_QC_PARTICLE"}, //particle builtin works in QW ( we don't mimic ZQ fully though) + {"ZQ_VWEP", 1, NULL, {"precache_vwep_model"}}, {"ZQ_QC_STRINGS", 7, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone"}} //a trimmed down FRIK_FILE. diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 6ea5d6cef..359febb15 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -270,6 +270,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svcfte_cgamepacket 83 +//fitz svcs +#define svcfitz_skybox 37 +#define svcfitz_bf 40 +#define svcfitz_fog 41 +#define svcfitz_spawnbaseline2 42 +#define svcfitz_spawnstatic2 43 +#define svcfitz_spawnstaticsound2 44 + //DP extended svcs #define svcdp_downloaddata 50 #define svcdp_updatestatbyte 51 @@ -497,6 +505,55 @@ enum clcq2_ops_e #endif +#ifdef NQPROT + +#define NQU_MOREBITS (1<<0) +#define NQU_ORIGIN1 (1<<1) +#define NQU_ORIGIN2 (1<<2) +#define NQU_ORIGIN3 (1<<3) +#define NQU_ANGLE2 (1<<4) +#define NQU_NOLERP (1<<5) // don't interpolate movement +#define NQU_FRAME (1<<6) +#define NQU_SIGNAL (1<<7) // just differentiates from other updates + +// svc_update can pass all of the fast update bits, plus more +#define NQU_ANGLE1 (1<<8) +#define NQU_ANGLE3 (1<<9) +#define NQU_MODEL (1<<10) +#define NQU_COLORMAP (1<<11) +#define NQU_SKIN (1<<12) +#define NQU_EFFECTS (1<<13) +#define NQU_LONGENTITY (1<<14) + + +// LordHavoc's: protocol extension +#define DPU_EXTEND1 (1<<15) +// LordHavoc: first extend byte +#define DPU_DELTA (1<<16) // no data, while this is set the entity is delta compressed (uses previous frame as a baseline, meaning only things that have changed from the previous frame are sent, except for the forced full update every half second) +#define DPU_ALPHA (1<<17) // 1 byte, 0.0-1.0 maps to 0-255, not sent if exactly 1, and the entity is not sent if <=0 unless it has effects (model effects are checked as well) +#define DPU_SCALE (1<<18) // 1 byte, scale / 16 positive, not sent if 1.0 +#define DPU_EFFECTS2 (1<<19) // 1 byte, this is .effects & 0xFF00 (second byte) +#define DPU_GLOWSIZE (1<<20) // 1 byte, encoding is float/4.0, unsigned, not sent if 0 +#define DPU_GLOWCOLOR (1<<21) // 1 byte, palette index, default is 254 (white), this IS used for darklight (allowing colored darklight), however the particles from a darklight are always black, not sent if default value (even if glowsize or glowtrail is set) +// LordHavoc: colormod feature has been removed, because no one used it +#define DPU_COLORMOD (1<<22) // 1 byte, 3 bit red, 3 bit green, 2 bit blue, this lets you tint an object artifically, so you could make a red rocket, or a blue fiend... +#define DPU_EXTEND2 (1<<23) // another byte to follow +// LordHavoc: second extend byte +#define DPU_GLOWTRAIL (1<<24) // leaves a trail of particles (of color .glowcolor, or black if it is a negative glowsize) +#define DPU_VIEWMODEL (1<<25) // attachs the model to the view (origin and angles become relative to it), only shown to owner, a more powerful alternative to .weaponmodel and such +#define DPU_FRAME2 (1<<26) // 1 byte, this is .frame & 0xFF00 (second byte) +#define DPU_MODEL2 (1<<27) // 1 byte, this is .modelindex & 0xFF00 (second byte) +#define DPU_EXTERIORMODEL (1<<28) // causes this model to not be drawn when using a first person view (third person will draw it, first person will not) +#define DPU_UNUSED29 (1<<29) // future expansion +#define DPU_UNUSED30 (1<<30) // future expansion +#define DPU_EXTEND3 (1<<31) // another byte to follow, future expansion + +#define FITZU_ALPHA (1<<16) +#define FITZU_FRAME2 (1<<17) +#define FITZU_MODEL2 (1<<18) +#define FITZU_LERPFINISH (1<<19) + +#endif @@ -1285,3 +1342,7 @@ typedef struct q1usercmd_s #define E5_EXTEND4 (1<<31) #define E5_ALLUNUSED (E5_UNUSED24|E5_UNUSED25|E5_UNUSED26|E5_UNUSED27|E5_UNUSED28|E5_UNUSED29|E5_UNUSED30) + +#define FITZB_LARGEMODEL (1<<0) // modelindex is short instead of byte +#define FITZB_LARGEFRAME (1<<1) // frame is short instead of byte +#define FITZB_ALPHA (1<<2) // 1 byte, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT diff --git a/engine/common/q3common.c b/engine/common/q3common.c index 446b598b5..9376d0dbc 100644 --- a/engine/common/q3common.c +++ b/engine/common/q3common.c @@ -545,7 +545,7 @@ qboolean Netchan_ProcessQ3 (netchan_t *chan) char adr[MAX_ADR_SIZE]; // Get sequence number - MSG_BeginReading(); + MSG_BeginReading(msg_nullnetprim); sequence = MSG_ReadBits(32); // Read the qport if we are a server @@ -657,7 +657,7 @@ qboolean Netchan_ProcessQ3 (netchan_t *chan) MSG_WriteLong(&net_message, sequence); SZ_Write(&net_message, chan->in_fragment_buf, chan->in_fragment_length); - MSG_BeginReading(); + MSG_BeginReading(msg_nullnetprim); MSG_ReadLong(); // No more fragments diff --git a/engine/common/world.h b/engine/common/world.h index 5a4e9e365..1725261d1 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -126,6 +126,7 @@ 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; model_t *worldmodel; areanode_t areanodes[AREA_NODES]; int numareanodes; diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 668a497f4..41b4d26c7 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -1126,12 +1126,6 @@ void (D3D9_R_LessenStains) (void); qboolean (D3D9_VID_Init) (rendererstate_t *info, unsigned char *palette); void (D3D9_VID_DeInit) (void); -void (D3D9_VID_LockBuffer) (void); -void (D3D9_VID_UnlockBuffer) (void); -void (D3D9_D_BeginDirectRect) (int x, int y, qbyte *pbitmap, int width, int height); -void (D3D9_D_EndDirectRect) (int x, int y, int width, int height); -void (D3D9_VID_ForceLockState) (int lk); -int (D3D9_VID_ForceUnlockedAndReturnState) (void); void (D3D9_VID_SetPalette) (unsigned char *palette); void (D3D9_VID_ShiftPalette) (unsigned char *palette); char *(D3D9_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight); diff --git a/engine/d3d9/vid_d3d9.c b/engine/d3d9/vid_d3d9.c index 7d4d938e7..948ec0bd8 100644 --- a/engine/d3d9/vid_d3d9.c +++ b/engine/d3d9/vid_d3d9.c @@ -871,25 +871,6 @@ void (D3D9_VID_DeInit) (void) mainwindow = NULL; } } -void (D3D9_VID_LockBuffer) (void) -{ -} -void (D3D9_VID_UnlockBuffer) (void) -{ -} -void (D3D9_D_BeginDirectRect) (int x, int y, qbyte *pbitmap, int width, int height) -{ -} -void (D3D9_D_EndDirectRect) (int x, int y, int width, int height) -{ -} -void (D3D9_VID_ForceLockState) (int lk) -{ -} -int (D3D9_VID_ForceUnlockedAndReturnState) (void) -{ - return 0; -} void (D3D9_VID_SetPalette) (unsigned char *palette) { diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 5542617e3..7ae5fb403 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -119,7 +119,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 comctl32.lib wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /map /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../fteglqw_dbg.exe" /libpath:"../libs/dxsdk7/lib" +# ADD LINK32 comctl32.lib wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /map /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../fteglqwvc6.exe" /libpath:"../libs/dxsdk7/lib" # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" @@ -2116,6 +2116,41 @@ SOURCE=..\client\p_null.c # Begin Source File SOURCE=..\client\p_qmb.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +!ENDIF + # End Source File # Begin Source File @@ -3521,6 +3556,41 @@ SOURCE=..\gl\gl_font.c # End Source File # Begin Source File +SOURCE=..\gl\gl_glsl.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\gl\gl_heightmap.c !IF "$(CFG)" == "ftequake - Win32 Release" diff --git a/engine/ftequake/ftequake.dsw b/engine/ftequake/ftequake.dsw index 74d44edf1..688bc4640 100644 --- a/engine/ftequake/ftequake.dsw +++ b/engine/ftequake/ftequake.dsw @@ -18,6 +18,18 @@ Package=<4> ############################################################################### +Project: "ftecs"=..\..\QUAKEC\ftecs\ftecs.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Project: "ftequake"=.\ftequake.dsp - Package Owner=<4> Package=<5> diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 8292e1968..d5a144bf9 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -728,7 +728,14 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel, unsigned int if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { if (e->flags & Q2RF_WEAPONMODEL) + { cl.worldmodel->funcs.LightPointValues(cl.worldmodel, r_refdef.vieworg, shadelight, ambientlight, lightdir); + for (i = 0; i < 3; i++) + { /*viewmodels may not be pure black*/ + if (ambientlight[i] < 24) + ambientlight[i] = 24; + } + } else cl.worldmodel->funcs.LightPointValues(cl.worldmodel, e->origin, shadelight, ambientlight, lightdir); } @@ -770,17 +777,8 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel, unsigned int { if (ambientlight[i] > 128) ambientlight[i] = 128; - if (ambientlight[i] + shadelight[i] > 192) - shadelight[i] = 192 - ambientlight[i]; - } - - if (e->flags & Q2RF_WEAPONMODEL) - { - for (i = 0; i < 3; i++) - { - if (ambientlight[i] < 24) - ambientlight[i] = shadelight[i] = 24; - } + if (shadelight[i] > 192) + shadelight[i] = 192; } //MORE HUGE HACKS! WHEN WILL THEY CEASE! @@ -850,7 +848,7 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel, unsigned int { vec3_t temp; temp[0] = DotProduct(shadevector, vpn); - temp[1] = DotProduct(shadevector, vright); + temp[1] = -DotProduct(shadevector, vright); temp[2] = DotProduct(shadevector, vup); VectorCopy(temp, shadevector); @@ -945,7 +943,7 @@ void R_DrawGAliasModel (entity_t *e, unsigned int rmode) { bef |= BEF_FORCEADDITIVE; } - else if (e->drawflags & DRF_TRANSLUCENT) + else if (e->drawflags & DRF_TRANSLUCENT) //hexen2 { bef |= BEF_FORCETRANSPARENT; e->shaderRGBAf[3] = r_wateralpha.value; @@ -964,7 +962,7 @@ void R_DrawGAliasModel (entity_t *e, unsigned int rmode) //BEFIXME: this needs to generate the right sort of default instead //(alpha test) } - else if (e->shaderRGBAf[3] < 1) + else if (e->shaderRGBAf[3] < 1 && cls.protocol != CP_QUAKE3) bef |= BEF_FORCETRANSPARENT; BE_SelectMode(rmode, bef); diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index b61f8f712..542a6f55e 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -657,6 +657,8 @@ static void RevertToKnownState(void) qglEnableClientState(GL_VERTEX_ARRAY); checkerror(); + GL_TexEnv(GL_REPLACE); + qglColor3f(1,1,1); shaderstate.shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY); @@ -2585,6 +2587,9 @@ static void BaseBrushTextures(entity_t *ent) model = ent->model; + if (R_CullEntityBox (ent, model->mins, model->maxs)) + return; + #ifdef RTLIGHTS if (BE_LightCullModel(ent->origin, model)) return; @@ -2617,10 +2622,18 @@ static void BaseBrushTextures(entity_t *ent) } shift = Surf_LightmapShift(model); - -//update lightmaps. - for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) - Surf_RenderDynamicLightmaps (s, shift); + if ((ent->drawflags & MLS_MASKIN) == MLS_ABSLIGHT) + { + //update lightmaps. + for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) + Surf_RenderAmbientLightmaps (s, shift, ent->abslight); + } + else + { + //update lightmaps. + for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) + Surf_RenderDynamicLightmaps (s, shift); + } } memset(&batch, 0, sizeof(batch)); @@ -2699,10 +2712,17 @@ void BE_BaseEntTextures(void) switch(currententity->model->type) { case mod_brush: + if (r_drawentities.ival == 2) + continue; bef = BEF_PUSHDEPTH; if (currententity->flags & Q2RF_ADDITIVE) bef |= BEF_FORCEADDITIVE; - else if (currententity->shaderRGBAf[3] < 1) + else if (currententity->drawflags & DRF_TRANSLUCENT && r_wateralpha.value != 1) + { + bef |= BEF_FORCETRANSPARENT; + currententity->shaderRGBAf[3] = r_wateralpha.value; + } + else if (currententity->shaderRGBAf[3] < 1 && cls.protocol != CP_QUAKE3) bef |= BEF_FORCETRANSPARENT; if (currententity->flags & RF_NODEPTHTEST) bef |= BEF_FORCENODEPTH; @@ -2710,6 +2730,8 @@ void BE_BaseEntTextures(void) BaseBrushTextures(currententity); break; case mod_alias: + if (r_drawentities.ival == 3) + continue; R_DrawGAliasModel (currententity, shaderstate.mode); break; } @@ -2752,37 +2774,6 @@ static void BE_SubmitBatch(batch_t *batch) } else { - if (lightmap[lm]->modified) - { - glRect_t *theRect; - lightmap[lm]->modified = false; - theRect = &lightmap[lm]->rectchange; - GL_Bind(lightmap_textures[lm]); - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, ((lightmap_bytes==3)?GL_RGB:GL_LUMINANCE), GL_UNSIGNED_BYTE, - lightmap[lm]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*lightmap_bytes); - theRect->l = LMBLOCK_WIDTH; - theRect->t = LMBLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; - checkerror(); - - if (lightmap[lm]->deluxmodified) - { - lightmap[lm]->deluxmodified = false; - theRect = &lightmap[lm]->deluxrectchange; - GL_Bind(deluxmap_textures[lm]); - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, - lightmap[lm]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); - theRect->l = LMBLOCK_WIDTH; - theRect->t = LMBLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; - checkerror(); - } - } - shaderstate.curlightmap = lightmap_textures[lm]; shaderstate.curdeluxmap = deluxmap_textures[lm]; } @@ -2888,12 +2879,70 @@ void BE_SubmitMeshes (void) currententity = &r_worldentity; } +static void BE_UpdateLightmaps(void) +{ + int lm; + for (lm = 0; lm < numlightmaps; lm++) + { + if (!lightmap[lm]) + continue; + if (lightmap[lm]->modified) + { + extern cvar_t temp1; + glRect_t *theRect; + lightmap[lm]->modified = false; + theRect = &lightmap[lm]->rectchange; + GL_Bind(lightmap_textures[lm]); + switch (lightmap_bytes) + { + case 4: + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV, + lightmap[lm]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*4); + break; + case 3: + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE, + lightmap[lm]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*3); + break; + case 1: + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, GL_LUMINANCE, GL_UNSIGNED_BYTE, + lightmap[lm]->lightmaps+(theRect->t) *LMBLOCK_WIDTH); + break; + } + theRect->l = LMBLOCK_WIDTH; + theRect->t = LMBLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + checkerror(); + + if (lightmap[lm]->deluxmodified) + { + lightmap[lm]->deluxmodified = false; + theRect = &lightmap[lm]->deluxrectchange; + GL_Bind(deluxmap_textures[lm]); + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, + lightmap[lm]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); + theRect->l = LMBLOCK_WIDTH; + theRect->t = LMBLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + checkerror(); + } + } + } +} + void BE_DrawWorld (qbyte *vis) { extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; RSpeedLocals(); GL_DoSwap(); + BE_UpdateLightmaps(); + //make sure the world draws correctly r_worldentity.shaderRGBAf[0] = 1; r_worldentity.shaderRGBAf[1] = 1; diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 34df45712..90b45e9b1 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -45,9 +45,9 @@ cvar_t r_bloom_fast_sample = CVARF("r_bloom_fast_sample", "0", CVAR_RENDERERLAT typedef struct { //texture numbers - texid_t tx_screen; - texid_t tx_effect; - texid_t tx_backup; + texid_t tx_screen; /*a copy of the screen*/ + texid_t tx_effect; /*blured copy of bright pixels*/ + texid_t tx_backup; /*a copy of the screen to replace the pixels that we'll clobber. FIXME: use a FBO instead*/ texid_t tx_downsample; //the viewport dimensions @@ -506,8 +506,8 @@ void R_BloomBlend (void) bs.scr_h < bs.size_sample) return; -#pragma message("backend fixme") - Con_Printf("bloom is not updated for the backend\n"); + PPL_RevertToKnownState(); +#pragma message("Note: Bloom doesn't use the backend.") //set up full screen workspace qglViewport(0, 0, vid.pixelwidth, vid.pixelheight); @@ -578,6 +578,8 @@ void R_BloomBlend (void) if (qglGetError()) Con_Printf("GL Error whilst rendering bloom\n"); + + PPL_RevertToKnownState(); } #endif diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 22ac1780a..1ce7dabbb 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -108,6 +108,13 @@ texid_t GL_LoadTextureFmt (char *name, int width, int height, enum uploadfmt fmt case TF_SOLID8: return GL_LoadTexture(name, width, height, data, flags, 0); + case TF_H2_T7G1: + return GL_LoadTexture(name, width, height, data, flags, 2); + case TF_H2_TRANS8_0: + return GL_LoadTexture(name, width, height, data, flags, 3); + case TF_H2_T4A4: + return GL_LoadTexture(name, width, height, data, flags, 4); + case TF_HEIGHT8PAL: case TF_HEIGHT8: return GL_LoadTexture8Bump(name, width, height, data, flags, r_shadow_bumpscale_basetexture.value); @@ -161,8 +168,6 @@ mpic_t *conback; hashtable_t gltexturetable; bucket_t *gltexturetablebuckets[256]; -int gl_lightmap_format = 4; - int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; int gl_filter_max = GL_LINEAR; int gl_filter_max_2d = GL_LINEAR; @@ -739,107 +744,12 @@ void GLDraw_FadeScreen (void) extern cvar_t gl_menutint_shader; extern texid_t scenepp_texture; extern int scenepp_mt_program, scenepp_mt_parm_colorf, scenepp_mt_parm_inverti; + extern shader_t *scenepp_mt_shader; if (!faderender) return; -#pragma message("Warning: This doesn't use the backend") - if (scenepp_mt_program && gl_menutint_shader.ival) - { - float vwidth = 1, vheight = 1; - float vs, vt; - // get the powers of 2 for the size of the texture that will hold the scene - while (vwidth < vid.pixelwidth) - vwidth *= 2; - while (vheight < vid.pixelheight) - vheight *= 2; - - // get the maxtexcoords while we're at it (cache this or just use largest?) - vs = vid.pixelwidth / vwidth; - vt = vid.pixelheight / vheight; - - // 2d mode, but upside down to quake's normal 2d drawing - // this makes grabbing the sreen a lot easier - qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); - - qglMatrixMode(GL_PROJECTION); - // Push the matrices to go into 2d mode, that matches opengl's mode - qglPushMatrix(); - qglLoadIdentity (); - // TODO: use actual window width and height - qglOrtho (0, vid.pixelwidth, 0, vid.pixelheight, -99999, 99999); - - qglMatrixMode(GL_MODELVIEW); - qglPushMatrix(); - qglLoadIdentity (); - - GL_Bind(scenepp_texture); - qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (qglGetError()) - Con_Printf(CON_ERROR "GL Error after qglCopyTexImage2D\n"); - - GLSlang_UseProgram(scenepp_mt_program); - qglUniform3fvARB(scenepp_mt_parm_colorf, 1, fadecolor); - if (faderender == GL_ONE_MINUS_DST_COLOR) - qglUniform1iARB(scenepp_mt_parm_inverti, 1); - else - qglUniform1iARB(scenepp_mt_parm_inverti, 0); - - if (qglGetError()) - Con_Printf(CON_ERROR "GL Error after GLSlang_UseProgram\n"); - - qglEnable(GL_TEXTURE_2D); - GL_Bind(scenepp_texture); - - qglBegin(GL_QUADS); - - qglTexCoord2f (0, 0); - qglVertex2f(0, 0); - qglTexCoord2f (vs, 0); - qglVertex2f(vid.pixelwidth, 0); - qglTexCoord2f (vs, vt); - qglVertex2f(vid.pixelwidth, vid.pixelheight); - qglTexCoord2f (0, vt); - qglVertex2f(0, vid.pixelheight); - - qglEnd(); - - GLSlang_UseProgram(0); - - // After all the post processing, pop the matrices - qglMatrixMode(GL_PROJECTION); - qglPopMatrix(); - qglMatrixMode(GL_MODELVIEW); - qglPopMatrix(); - - if (qglGetError()) - Con_Printf(CON_ERROR "GL Error after drawing with shaderobjects\n"); - } - else - { - // shaderless way - qglEnable (GL_BLEND); - qglBlendFunc(faderender, GL_ZERO); - qglDisable(GL_ALPHA_TEST); - qglDisable (GL_TEXTURE_2D); - qglColor4f (fadecolor[0], fadecolor[1], fadecolor[2], 1); - qglBegin (GL_QUADS); - - qglVertex2f (0,0); - qglVertex2f (vid.width, 0); - qglVertex2f (vid.width, vid.height); - qglVertex2f (0, vid.height); - - qglEnd (); - qglColor4f (1,1,1,1); - qglEnable (GL_TEXTURE_2D); - qglDisable (GL_BLEND); - qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - qglEnable(GL_ALPHA_TEST); - } + R2D_ScalePic(0, 0, vid.width, vid.height, scenepp_mt_shader); Sbar_Changed(); } diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 1264a1de5..6cb7ef56b 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -802,6 +802,63 @@ struct font_s *Font_LoadFont(int height, char *fontfilename) f = Z_Malloc(sizeof(*f)); f->charheight = height; + if (!strcmp(fontfilename, "gfx/tinyfont")) + { + unsigned int *img; + int x, y; + unsigned char *w = W_SafeGetLumpName(fontfilename+4); + if (!w) + { + Z_Free(f); + return NULL; + } + img = Z_Malloc(PLANEWIDTH*PLANEWIDTH*4); + for (y = 0; y < 32; y++) + for (x = 0; x < 128; x++) + img[x + y*PLANEWIDTH] = w[x + y*128]?d_8to24rgbtable[w[x + y*128]]:0; + + f->singletexture = R_LoadTexture(fontfilename,PLANEWIDTH,PLANEWIDTH,TF_RGBA32,img,IF_NOPICMIP|IF_NOMIPMAP); + Z_Free(img); + + for (i = 0x00; i <= 0xff; i++) + { + f->chars[i].advance = height; + f->chars[i].left = 0; + f->chars[i].top = 0; + f->chars[i].nextchar = 0; //these chars are not linked in + f->chars[i].pad = 0; + f->chars[i].texplane = BITMAPPLANE; /*if its a 'raster' font, don't use the default chars, always use the raster images*/ + + + if (i >= 'a' && i <= 'z') + { + f->chars[i].bmx = ((i - 64)&15)*8; + f->chars[i].bmy = ((i - 64)/16)*8; + f->chars[i].bmh = 8; + f->chars[i].bmw = 8; + } + else if (i >= 32 && i < 96) + { + f->chars[i].bmx = ((i - 32)&15)*8; + f->chars[i].bmy = ((i - 32)/16)*8; + f->chars[i].bmh = 8; + f->chars[i].bmw = 8; + } + else + { + f->chars[i].bmh = 0; + f->chars[i].bmw = 0; + f->chars[i].bmx = 0; + f->chars[i].bmy = 0; + } + } + for (i = 0xe000; i <= 0xe0ff; i++) + { + f->chars[i] = f->chars[i&0xff]; + } + return f; + } + if (!Font_LoadFreeTypeFont(f, height, fontfilename)) { if (*fontfilename) diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index d68955e82..7ea8223a8 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -571,6 +571,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash) switch (LittleLong(*(unsigned *)buf)) { //The binary 3d mesh model formats + case RAPOLYHEADER: case IDPOLYHEADER: if (!Mod_LoadQ1Model(mod, buf)) continue; @@ -931,8 +932,11 @@ void Mod_FinishTexture(texture_t *tx, texnums_t tn) extern cvar_t gl_shadeq1_name; char altname[MAX_QPATH]; char *star; + /*skies? just replace with the override sky*/ + if (!strncmp(tx->name, "sky", 3) && *cl.skyname) + tx->shader = R_RegisterCustom (va("skybox_%s", cl.skyname), Shader_DefaultSkybox, NULL); //just load the regular name. //find the * - if (!*gl_shadeq1_name.string || !strcmp(gl_shadeq1_name.string, "*")) + else if (!*gl_shadeq1_name.string || !strcmp(gl_shadeq1_name.string, "*")) tx->shader = R_RegisterCustom (tx->name, Shader_DefaultBSPQ1, NULL); //just load the regular name. else if (!(star = strchr(gl_shadeq1_name.string, '*')) || (strlen(gl_shadeq1_name.string)+strlen(tx->name)+1>=sizeof(altname))) //it's got to fit. tx->shader = R_RegisterCustom (gl_shadeq1_name.string, Shader_DefaultBSPQ1, NULL); @@ -2889,6 +2893,19 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) crouchhullfile = NULL; +#ifndef CLIENTONLY + if (sv.state) //if the server is running + { + if (!strcmp(loadmodel->name, va("maps/%s.bsp", sv.name))) + Mod_ParseInfoFromEntityLump(loadmodel, mod_base + header->lumps[LUMP_ENTITIES].fileofs, loadname); + } + else +#endif + { + if (!cl.model_precache[1]) //not copied across yet + Mod_ParseInfoFromEntityLump(loadmodel, mod_base + header->lumps[LUMP_ENTITIES].fileofs, loadname); + } + // load into heap if (!isDedicated || ode) { @@ -2939,19 +2956,6 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) return false; } -#ifndef CLIENTONLY - if (sv.state) //if the server is running - { - if (!strcmp(loadmodel->name, va("maps/%s.bsp", sv.name))) - Mod_ParseInfoFromEntityLump(mod_base + header->lumps[LUMP_ENTITIES].fileofs, loadname); - } - else -#endif - { - if (!cl.model_precache[1]) //not copied across yet - Mod_ParseInfoFromEntityLump(mod_base + header->lumps[LUMP_ENTITIES].fileofs, loadname); - } - Q1BSP_SetModelFuncs(mod); mod->funcs.LightPointValues = GLQ1BSP_LightPointValues; mod->funcs.StainNode = Q1BSP_StainNode; @@ -2983,7 +2987,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) mod->hulls[j].firstclipnode = bm->headnode[j]; mod->hulls[j].lastclipnode = mod->numclipnodes-1; - mod->hulls[j].available = bm->hullavailable[j]; + mod->hulls[j].available &= bm->hullavailable[j]; if (mod->hulls[j].firstclipnode > mod->hulls[j].lastclipnode) mod->hulls[j].available = false; @@ -3184,14 +3188,11 @@ void * RMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, if (!TEXVALID(texnum)) texnum = R_LoadTexture32 (name, width, height, (unsigned *)(pinframe + 1), IF_NOGAMMA); } -#pragma message("no hl sprites") -#ifdef R_LoadTexture8Pal32 else if (version == SPRITEHL_VERSION) { if (!TEXVALID(texnum)) texnum = R_LoadTexture8Pal32 (name, width, height, (qbyte *)(pinframe + 1), (qbyte*)palette, IF_NOGAMMA); } -#endif else { if (!TEXVALID(texnum)) diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 78ea12c87..8540312a4 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -47,7 +47,7 @@ void R_AnimateLight (void) f = 0; i = (int)f; - if (r_lightstylesmooth.value) + if (r_lightstylesmooth.ival) f -= i; //this can require updates at 1000 times a second.. Depends on your framerate of course else f = 0; //only update them 10 times a second @@ -741,13 +741,6 @@ float *GLRecursiveLightPoint3C (mnode_t *node, vec3_t start, vec3_t end) float scale; int maps; - if (!cl.worldmodel->lightdata) - { - l[0]=255;l[1]=255;l[2]=255; - l[3]=0;l[4]=1;l[5]=1; - return l; - } - if (cl.worldmodel->fromgame == fg_quake2) { if (node->contents != -1) @@ -939,6 +932,23 @@ void GLQ1BSP_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec3_t end; float *r; + if (!cl.worldmodel->lightdata || r_fullbright.ival) + { + res_diffuse[0] = 0; + res_diffuse[1] = 0; + res_diffuse[2] = 0; + + res_ambient[0] = 255; + res_ambient[1] = 255; + res_ambient[2] = 255; + + res_dir[0] = 1; + res_dir[1] = 1; + res_dir[2] = 0.1; + VectorNormalize(res_dir); + return; + } + end[0] = point[0]; end[1] = point[1]; end[2] = point[2] - 2048; @@ -964,17 +974,16 @@ void GLQ1BSP_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, res_diffuse[1] = r[1]; res_diffuse[2] = r[2]; - res_ambient[0] = r[0]; - res_ambient[1] = r[1]; - res_ambient[2] = r[2]; + res_ambient[0] = 0; + res_ambient[1] = 0; + res_ambient[2] = 0; res_dir[0] = r[3]; res_dir[1] = r[4]; res_dir[2] = -r[5]; - VectorNormalize(res_dir); - if (!res_dir[0] && !res_dir[1] && !res_dir[2]) res_dir[1] = res_dir[2] = 1; + VectorNormalize(res_dir); } } diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 98d438e82..fa2412d0f 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -108,23 +108,16 @@ extern cvar_t gl_blendsprites; cvar_t r_xflip = SCVAR("leftisright", "0"); #endif -extern cvar_t gl_ztrick; extern cvar_t scr_fov; shader_t *scenepp_waterwarp; +shader_t *scenepp_mt_shader; // post processing stuff texid_t sceneblur_texture; -texid_t scenepp_texture; texid_t scenepp_texture_warp; texid_t scenepp_texture_edge; -int scenepp_ww_program; -int scenepp_ww_parm_texture0i; -int scenepp_ww_parm_texture1i; -int scenepp_ww_parm_texture2i; -int scenepp_ww_parm_ampscalef; - int scenepp_mt_program; int scenepp_mt_parm_texture0i; int scenepp_mt_parm_colorf; @@ -141,7 +134,6 @@ int scenepp_panorama_parm_fov; // processing shaders void GL_InitSceneProcessingShaders_WaterWarp (void) { -#if 1 /* inputs: texcoords: edge points @@ -221,70 +213,6 @@ void GL_InitSceneProcessingShaders_WaterWarp (void) scenepp_waterwarp->defaulttextures.upperoverlay = scenepp_texture_warp; scenepp_waterwarp->defaulttextures.loweroverlay = scenepp_texture_edge; } -#else - char *genericvert = "\ - varying vec2 v_texCoord0;\ - varying vec2 v_texCoord1;\ - varying vec2 v_texCoord2;\ - void main (void)\ - {\ - vec4 v = vec4( gl_Vertex.x, gl_Vertex.y, gl_Vertex.z, 1.0 );\ - gl_Position = gl_ModelViewProjectionMatrix * v;\ - v_texCoord0 = gl_MultiTexCoord0.xy;\ - v_texCoord1 = gl_MultiTexCoord1.xy;\ - v_texCoord2 = gl_MultiTexCoord2.xy;\ - }\ - "; - - char *wwfrag = "\ - varying vec2 v_texCoord0;\ - varying vec2 v_texCoord1;\ - varying vec2 v_texCoord2;\ - uniform sampler2D theTexture0;\ - uniform sampler2D theTexture1;\ - uniform sampler2D theTexture2;\ - uniform float ampscale;\ - void main (void)\ - {\ - float amptemp;\ - vec3 edge;\ - edge = texture2D( theTexture2, v_texCoord2 ).rgb;\ - amptemp = ampscale * edge.x;\ - vec3 offset;\ - offset = texture2D( theTexture1, v_texCoord1 ).rgb;\ - offset.x = (offset.x - 0.5) * 2.0;\ - offset.y = (offset.y - 0.5) * 2.0;\ - vec2 temp;\ - temp.x = v_texCoord0.x + offset.x * amptemp;\ - temp.y = v_texCoord0.y + offset.y * amptemp;\ - gl_FragColor = texture2D( theTexture0, temp );\ - }\ - "; - - if (qglGetError()) - Con_Printf("GL Error before initing shader object\n"); - - scenepp_ww_program = GLSlang_CreateProgram(NULL, genericvert, wwfrag); - - if (!scenepp_ww_program) - return; - - scenepp_ww_parm_texture0i = GLSlang_GetUniformLocation(scenepp_ww_program, "theTexture0"); - scenepp_ww_parm_texture1i = GLSlang_GetUniformLocation(scenepp_ww_program, "theTexture1"); - scenepp_ww_parm_texture2i = GLSlang_GetUniformLocation(scenepp_ww_program, "theTexture2"); - scenepp_ww_parm_ampscalef = GLSlang_GetUniformLocation(scenepp_ww_program, "ampscale"); - - GLSlang_UseProgram(scenepp_ww_program); - - GLSlang_SetUniform1i(scenepp_ww_parm_texture0i, 0); - GLSlang_SetUniform1i(scenepp_ww_parm_texture1i, 1); - GLSlang_SetUniform1i(scenepp_ww_parm_texture2i, 2); - - GLSlang_UseProgram(0); - - if (qglGetError()) - Con_Printf(CON_ERROR "GL Error initing shader object\n"); -#endif } void GL_InitFisheyeFov(void) @@ -350,49 +278,66 @@ void GL_InitFisheyeFov(void) void GL_InitSceneProcessingShaders_MenuTint(void) { - char *vshader = "\ - varying vec2 texcoord;\ - void main(void)\ - {\ - texcoord = gl_MultiTexCoord0.xy;\ - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ - }"; - char *fshader = "\ - varying vec2 texcoord;\ - uniform vec3 colorparam;\ - uniform sampler2D source;\ - uniform int invert;\ - const vec3 lumfactors = vec3(0.299, 0.587, 0.114);\ - const vec3 invertvec = vec3(1.0, 1.0, 1.0);\ - void main(void)\ - {\ - vec3 texcolor = texture2D(source, texcoord).rgb;\ - float luminance = dot(lumfactors, texcolor);\ - texcolor = vec3(luminance, luminance, luminance);\ - texcolor *= colorparam;\ - texcolor = invert > 0 ? (invertvec - texcolor) : texcolor;\ - gl_FragColor = vec4(texcolor, 1.0);\ - }"; + extern cvar_t gl_menutint_shader; + if (gl_config.arb_shader_objects && gl_menutint_shader.ival) + { + scenepp_mt_shader = R_RegisterShader("menutint", + "{\n" + "glslprogram\n" + "{\n" + "#ifdef VERTEX_SHADER\n" + "\ + varying vec2 texcoord;\ + uniform vec3 rendertexturescale;\ + void main(void)\ + {\ + texcoord.x = gl_MultiTexCoord0.x*rendertexturescale.x;\ + texcoord.y = (1-gl_MultiTexCoord0.y)*rendertexturescale.y;\ + gl_Position = ftransform();\ + }\ + \n" + "#endif\n" + "#ifdef FRAGMENT_SHADER\n" + "\ + varying vec2 texcoord;\ + uniform vec3 colorparam;\ + uniform sampler2D source;\ + uniform int invert;\ + const vec3 lumfactors = vec3(0.299, 0.587, 0.114);\ + const vec3 invertvec = vec3(1.0, 1.0, 1.0);\ + void main(void)\ + {\ + vec3 texcolor = texture2D(source, texcoord).rgb;\ + float luminance = dot(lumfactors, texcolor);\ + texcolor = vec3(luminance, luminance, luminance);\ + texcolor *= colorparam;\ + texcolor = invert > 0 ? (invertvec - texcolor) : texcolor;\ + gl_FragColor = vec4(texcolor, 1.0);\ + }\n" + "#endif\n" + "}\n" + "param cvari r_menutint_inverse invert\n" + "param cvar3f r_menutint colorparam\n" + "param texture 0 source\n" - if (qglGetError()) - Con_Printf("GL Error before initing shader object\n"); - - scenepp_mt_program = GLSlang_CreateProgram(NULL, vshader, fshader); - - if (!scenepp_mt_program) - return; - - scenepp_mt_parm_texture0i = GLSlang_GetUniformLocation(scenepp_mt_program, "source"); - scenepp_mt_parm_colorf = GLSlang_GetUniformLocation(scenepp_mt_program, "colorparam"); - scenepp_mt_parm_inverti = GLSlang_GetUniformLocation(scenepp_mt_program, "invert"); - - GLSlang_UseProgram(scenepp_mt_program); - GLSlang_SetUniform1i(scenepp_mt_parm_texture0i, 0); - - GLSlang_UseProgram(0); - - if (qglGetError()) - Con_Printf(CON_ERROR "GL Error initing shader object\n"); + "{\n" + "map $currentrender\n" + "}\n" + "param rendertexturescale rendertexturescale\n" + "}"); + } + if (!scenepp_mt_shader) + { + scenepp_mt_shader = R_RegisterShader("menutint", + "{\n" + "{\n" + "map $whitetexture\n" + "blendfunc gl_dst_color gl_zero\n" + "rgbgen const $r_menutint\n" + "}\n" + "}\n" + ); + } } void GL_InitSceneProcessingShaders (void) @@ -421,7 +366,6 @@ void GL_SetupSceneProcessingTextures (void) if (!gl_config.arb_shader_objects) return; - scenepp_texture = GL_AllocNewTexture(); scenepp_texture_warp = GL_AllocNewTexture(); scenepp_texture_edge = GL_AllocNewTexture(); @@ -664,7 +608,7 @@ void R_DrawSpriteModel (entity_t *e) unsigned int fl; unsigned int sprtype; - static vec2_t texcoords[4]={{0, 0},{0,1},{1,1},{1,0}}; + static vec2_t texcoords[4]={{0, 1},{0,0},{1,0},{1,1}}; static index_t indexes[6] = {0, 1, 2, 0, 2, 3}; vecV_t vertcoords[4]; avec4_t colours[4]; @@ -1227,6 +1171,7 @@ r_refdef must be set before the first call */ void R_RenderScene (void) { + int tmpvisents = cl_numvisedicts; /*world rendering is allowed to add additional ents, but we don't want to keep them for recursive views*/ if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap)) r_refdef.flags |= Q2RDF_NOWORLDMODEL; @@ -1260,6 +1205,8 @@ void R_RenderScene (void) P_DrawParticles (); } RQ_RenderBatchClear(); + + cl_numvisedicts = tmpvisents; } /*generates a new modelview matrix, as well as vpn vectors*/ static void R_MirrorMatrix(plane_t *plane) @@ -1514,32 +1461,6 @@ void R_Clear (void) { /*tbh, this entire function should be in the backend*/ GL_ForceDepthWritable(); -#ifdef SIDEVIEWS - if (gl_ztrick.value && !gl_ztrickdisabled) -#else - if (gl_ztrick.value) -#endif - { - static int trickframe; - - if (gl_clear.value && !(r_refdef.flags & Q2RDF_NOWORLDMODEL)) - qglClear (GL_COLOR_BUFFER_BIT); - - trickframe++; - if (trickframe & 1) - { - gldepthmin = 0; - gldepthmax = 0.49999; - gldepthfunc=GL_LEQUAL; - } - else - { - gldepthmin = 1; - gldepthmax = 0.5; - gldepthfunc=GL_GEQUAL; - } - } - else { if (gl_clear.value && !r_secondaryview && !(r_refdef.flags & Q2RDF_NOWORLDMODEL)) qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -1680,148 +1601,6 @@ static void R_RenderMotionBlur(void) PPL_RevertToKnownState(); } -static void R_RenderWaterWarp(void) -{ - float vwidth = 1, vheight = 1; - float vs, vt; - - PPL_RevertToKnownState(); - -#pragma message("backend fixme") - Con_Printf("waterwarp is not updated for the backend\n"); - - // get the powers of 2 for the size of the texture that will hold the scene - - if (gl_config.arb_texture_non_power_of_two) - { - vwidth = vid.pixelwidth; - vheight = vid.pixelheight; - } - else - { - while (vwidth < vid.pixelwidth) - { - vwidth *= 2; - } - while (vheight < vid.pixelheight) - { - vheight *= 2; - } - } - - // get the maxtexcoords while we're at it - vs = vid.pixelwidth / vwidth; - vt = vid.pixelheight / vheight; - - // 2d mode, but upside down to quake's normal 2d drawing - // this makes grabbing the sreen a lot easier - qglViewport (0, 0, vid.pixelwidth, vid.pixelheight); - - qglMatrixMode(GL_PROJECTION); - // Push the matrices to go into 2d mode, that matches opengl's mode - qglPushMatrix(); - qglLoadIdentity (); - // TODO: use actual window width and height - qglOrtho (0, vid.pixelwidth, 0, vid.pixelheight, -99999, 99999); - - qglMatrixMode(GL_MODELVIEW); - qglPushMatrix(); - qglLoadIdentity (); - - qglDisable (GL_DEPTH_TEST); - GL_CullFace(0); - qglDisable (GL_BLEND); - qglEnable (GL_ALPHA_TEST); - - // copy the scene to texture - GL_Bind(scenepp_texture); - qglEnable(GL_TEXTURE_2D); - qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (qglGetError()) - Con_Printf(CON_ERROR "GL Error after qglCopyTexImage2D\n"); - - // Here we apply the shaders - currently just waterwarp - GLSlang_UseProgram(scenepp_ww_program); - //keep the amp proportional to the size of the scene in texture coords - // WARNING - waterwarp can change the amplitude, but if it's too big it'll exceed - // the size determined by the edge texture, after which black bits will be shown. - // Suggest clamping to a suitable range. - if (r_waterwarp.value<0) - { - GLSlang_SetUniform1f(scenepp_ww_parm_ampscalef, (0.005 / 0.625) * vs*(-r_waterwarp.value)); - } - else - { - GLSlang_SetUniform1f(scenepp_ww_parm_ampscalef, (0.005 / 0.625) * vs*r_waterwarp.value); - } - - if (qglGetError()) - Con_Printf("GL Error after GLSlang_UseProgram\n"); - - { - float xmin, xmax, ymin, ymax; - - xmin = cl.time * 0.25; - ymin = cl.time * 0.25; - xmax = xmin + 1; - ymax = ymin + 1/vt*vs; - - GL_SelectTexture(1); - qglEnable(GL_TEXTURE_2D); - GL_Bind (scenepp_texture_warp); - - GL_SelectTexture(2); - qglEnable(GL_TEXTURE_2D); - GL_Bind(scenepp_texture_edge); - - qglBegin(GL_QUADS); - - qglMTexCoord2fSGIS (mtexid0, 0, 0); - qglMTexCoord2fSGIS (mtexid1, xmin, ymin); - qglMTexCoord2fSGIS (mtexid1+1, 0, 0); - qglVertex2f(0, 0); - - qglMTexCoord2fSGIS (mtexid0, vs, 0); - qglMTexCoord2fSGIS (mtexid1, xmax, ymin); - qglMTexCoord2fSGIS (mtexid1+1, 1, 0); - qglVertex2f(vid.pixelwidth, 0); - - qglMTexCoord2fSGIS (mtexid0, vs, vt); - qglMTexCoord2fSGIS (mtexid1, xmax, ymax); - qglMTexCoord2fSGIS (mtexid1+1, 1, 1); - qglVertex2f(vid.pixelwidth, vid.pixelheight); - - qglMTexCoord2fSGIS (mtexid0, 0, vt); - qglMTexCoord2fSGIS (mtexid1, xmin, ymax); - qglMTexCoord2fSGIS (mtexid1+1, 0, 1); - qglVertex2f(0, vid.pixelheight); - - qglEnd(); - - qglDisable(GL_TEXTURE_2D); - GL_SelectTexture(1); - qglDisable(GL_TEXTURE_2D); - GL_SelectTexture(0); - } - - // Disable shaders - GLSlang_UseProgram(0); - - // After all the post processing, pop the matrices - qglMatrixMode(GL_PROJECTION); - qglPopMatrix(); - qglMatrixMode(GL_MODELVIEW); - qglPopMatrix(); - - PPL_RevertToKnownState(); - - if (qglGetError()) - Con_Printf("GL Error after drawing with shaderobjects\n"); -} - #ifdef FISH /*FIXME: we could use geometry shaders to draw to all 6 faces at once*/ qboolean R_RenderScene_Fish(void) @@ -2128,8 +1907,6 @@ void GLR_RenderView (void) GL_Set2D(); if (scenepp_waterwarp) R2D_ScalePic(0, 0, vid.width, vid.height, scenepp_waterwarp); - else if (scenepp_ww_program) - R_RenderWaterWarp(); } diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index b72e60b66..435354b35 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -969,6 +969,9 @@ void GLR_NewMap (void) r_viewcluster = -1; r_oldviewcluster = 0; r_viewcluster2 = -1; + + Mod_ParseInfoFromEntityLump(cl.worldmodel, cl.worldmodel->entities, cl.worldmodel->name); + TRACE(("dbg: GLR_NewMap: clear particles\n")); P_ClearParticles (); TRACE(("dbg: GLR_NewMap: wiping them stains (getting the cloth out)\n")); diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index d1aa35105..0c5577ea3 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -298,10 +298,24 @@ void BE_UploadAllLightmaps(void) GL_Bind(lightmap_textures[i]); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qglTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes - , LMBLOCK_WIDTH, LMBLOCK_HEIGHT, 0, - ((lightmap_bytes==3)?GL_RGB:GL_LUMINANCE), GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); - + switch (lightmap_bytes) + { + case 4: + qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, + LMBLOCK_WIDTH, LMBLOCK_WIDTH, 0, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV, + lightmap[i]->lightmaps); + break; + case 3: + qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, + LMBLOCK_WIDTH, LMBLOCK_WIDTH, 0, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE, + lightmap[i]->lightmaps); + break; + case 1: + qglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, + LMBLOCK_WIDTH, LMBLOCK_WIDTH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, + lightmap[i]->lightmaps); + break; + } if (gl_bump.ival) { lightmap[i]->deluxmodified = false; diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index cf7ceb42d..a3e85aa45 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -99,6 +99,9 @@ void GLVID_Console_Resize(void) vid.recalc_refdef = true; + if (font_tiny) + Font_Free(font_tiny); + font_tiny = NULL; if (font_conchar) Font_Free(font_conchar); font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, gl_font.string); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index ca185c0c6..5e7f97f38 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -206,6 +206,55 @@ static void Shader_ReadShader(shader_t *s, char *shadersource); //=========================================================================== +static qboolean Shader_EvaluateCondition(char **ptr) +{ + char *token; + cvar_t *cv; + qboolean conditiontrue = true; + token = COM_ParseExt ( ptr, false ); + if (*token == '!') + { + conditiontrue = false; + token++; + } + if (*token == '$') + { + extern cvar_t gl_bump; + token++; + if (!Q_stricmp(token, "lightmap")) + conditiontrue = conditiontrue == !r_fullbright.value; + else if (!Q_stricmp(token, "deluxmap") ) + conditiontrue = conditiontrue == !!gl_bump.value; + + //normalmaps are generated if they're not already known. + else if (!Q_stricmp(token, "normalmap") ) + conditiontrue = conditiontrue == !!gl_bump.value; + +#pragma message("shader fixme") + else if (!Q_stricmp(token, "diffuse") ) + conditiontrue = conditiontrue == true; + else if (!Q_stricmp(token, "specular") ) + conditiontrue = conditiontrue == false; + else if (!Q_stricmp(token, "fullbright") ) + conditiontrue = conditiontrue == false; + else if (!Q_stricmp(token, "topoverlay") ) + conditiontrue = conditiontrue == false; + else if (!Q_stricmp(token, "loweroverlay") ) + conditiontrue = conditiontrue == false; + + else + conditiontrue = conditiontrue == false; + } + else + { + cv = Cvar_Get(token, "", 0, "Shader Conditions"); + if (cv) + conditiontrue = conditiontrue == !!cv->value; + } + + return conditiontrue; +} + static char *Shader_ParseString ( char **ptr ) { char *token; @@ -269,6 +318,7 @@ static void Shader_ParseVector ( char **ptr, vec3_t v ) v[2] = 1; return; } + var->flags |= CVAR_SHADERSYSTEM; ptr = &scratch; scratch = var->string; @@ -568,9 +618,9 @@ static void Shader_SurfaceParm ( shader_t *shader, shaderpass_t *pass, char **pt token = Shader_ParseString ( ptr ); if ( !Q_stricmp( token, "nodraw" ) ) - shader->flags = SHADER_NODRAW; + shader->flags |= SHADER_NODRAW; else if ( !Q_stricmp( token, "nodlight" ) ) - shader->flags = SHADER_NODLIGHT; + shader->flags |= SHADER_NODLIGHT; } static void Shader_Sort ( shader_t *shader, shaderpass_t *pass, char **ptr ) @@ -596,6 +646,8 @@ static void Shader_Sort ( shader_t *shader, shaderpass_t *pass, char **ptr ) shader->sort = SHADER_SORT_UNDERWATER; } else if( !Q_stricmp( token, "nearest" ) ) { shader->sort = SHADER_SORT_NEAREST; + } else if( !Q_stricmp( token, "blend" ) ) { + shader->sort = SHADER_SORT_BLEND; } else { shader->sort = atoi ( token ); clamp ( shader->sort, SHADER_SORT_NONE, SHADER_SORT_NEAREST ); @@ -728,6 +780,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p cvar_t *cv; int specialint = 0; float specialfloat = 0; + vec3_t specialvec = {0}; enum shaderprogparmtype_e parmtype = SP_BAD; char *token; qboolean silent = false; @@ -750,7 +803,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p cv = Cvar_Get(token, "", 0, "GLSL Shader parameters"); if (cv) { //Cvar_Get returns null if the cvar is the name of a command - specialint = atoi(cv->string); + specialint = cv->ival; specialfloat = cv->value; } parmtype = SP_CVARI; @@ -761,11 +814,21 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p cv = Cvar_Get(token, "", 0, "GLSL Shader parameters"); if (cv) { //Cvar_Get returns null if the cvar is the name of a command - specialint = atoi(cv->string); + specialint = cv->ival; specialfloat = cv->value; } parmtype = SP_CVARF; } + else if (!Q_stricmp(token, "cvar3f")) + { + token = Shader_ParseSensString(ptr); + cv = Cvar_Get(token, "", 0, "GLSL Shader parameters"); + if (cv) + { + SCR_StringToRGB(cv->string, specialvec, 1); + } + parmtype = SP_CVAR3F; + } else if (!Q_stricmp(token, "time")) parmtype = SP_TIME; else if (!Q_stricmp(token, "eyepos")) @@ -816,10 +879,13 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p break; case SP_TEXTURE: case SP_CVARI: - GLSlang_SetUniform1i(uniformloc, specialint); + qglUniform1iARB(uniformloc, specialint); break; case SP_CVARF: - GLSlang_SetUniform1f(uniformloc, specialfloat); + qglUniform1fARB(uniformloc, specialfloat); + break; + case SP_CVAR3F: + qglUniform3fvARB(uniformloc, 1, specialvec); break; default: shader->progparm[shader->numprogparams].type = parmtype; @@ -1774,6 +1840,23 @@ void Shader_Readpass (shader_t *shader, char **ptr) { break; } + else if (!Q_stricmp(token, "if")) + { + qboolean conditionistrue = Shader_EvaluateCondition(ptr); + + while (*ptr) + { + token = COM_ParseExt (ptr, true); + if ( !token[0] ) + continue; + else if (token[0] == ']') + break; + else if (conditionistrue) + { + Shader_Parsetok (shader, pass, shaderpasskeys, token, ptr); + } + } + } else if ( Shader_Parsetok (shader, pass, shaderpasskeys, token, ptr) ) { break; @@ -1827,55 +1910,6 @@ void Shader_Readpass (shader_t *shader, char **ptr) } } -static qboolean Shader_EvaluateCondition(char **ptr) -{ - char *token; - cvar_t *cv; - qboolean conditiontrue = true; - token = COM_ParseExt ( ptr, false ); - if (*token == '!') - { - conditiontrue = false; - token++; - } - if (*token == '$') - { - extern cvar_t gl_bump; - token++; - if (!Q_stricmp(token, "lightmap")) - conditiontrue = conditiontrue == !r_fullbright.value; - else if (!Q_stricmp(token, "deluxmap") ) - conditiontrue = conditiontrue == !!gl_bump.value; - - //normalmaps are generated if they're not already known. - else if (!Q_stricmp(token, "normalmap") ) - conditiontrue = conditiontrue == !!gl_bump.value; - -#pragma message("shader fixme") - else if (!Q_stricmp(token, "diffuse") ) - conditiontrue = conditiontrue == true; - else if (!Q_stricmp(token, "specular") ) - conditiontrue = conditiontrue == false; - else if (!Q_stricmp(token, "fullbright") ) - conditiontrue = conditiontrue == false; - else if (!Q_stricmp(token, "topoverlay") ) - conditiontrue = conditiontrue == false; - else if (!Q_stricmp(token, "loweroverlay") ) - conditiontrue = conditiontrue == false; - - else - conditiontrue = conditiontrue == false; - } - else - { - cv = Cvar_Get(token, "", 0, "Shader Conditions"); - if (cv) - conditiontrue = conditiontrue == !!cv->value; - } - - return conditiontrue; -} - static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey_t *keys, char *token, char **ptr) { shaderkey_t *key; @@ -2310,6 +2344,10 @@ done:; } Shader_SetFeatures(s); + +#ifdef FORCEGLSL + BE_GenerateProgram(s); +#endif } /* void Shader_UpdateRegistration (void) @@ -2416,7 +2454,7 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) if (!builtin) builtin = ( "{\n" - "if $deluxmap\n" + "if gl_bump\n" "[\n" "{\n" "map $normalmap\n" @@ -2431,19 +2469,19 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) "{\n" "map $diffuse\n" "tcgen base\n" - "if $deluxmap\n" + "if gl_bump\n" "[\n" "blendfunc gl_one gl_zero\n" "]\n" "}\n" - "if $lightmap\n" + "if !r_fullbright\n" "[\n" "{\n" "map $lightmap\n" "blendfunc gl_dst_color gl_zero\n" "}\n" "]\n" - "if r_fb_bmodels\n" + "if gl_fb_bmodels\n" "[\n" "{\n" "map $fullbright\n" @@ -2590,6 +2628,7 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) "alphagen const $r_mirroralpha\n" "depthwrite\n" "}\n" + "surfaceparm nodlight\n" "}\n"; } @@ -2602,10 +2641,12 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) { builtin = ( "{\n" + "sort seethrough\n" "{\n" "map $whiteimage\n" - "rgbgen $r_fastturbcolour\n" + "rgbgen const $r_fastturbcolour\n" "}\n" + "surfaceparm nodlight\n" "}\n" ); } @@ -2630,6 +2671,7 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) "#ifdef FRAGMENT_SHADER\n" "uniform sampler2D watertexture;\n" "uniform float time;\n" + "uniform float wateralpha;\n" "varying vec2 tc;\n" "void main (void)\n" @@ -2639,16 +2681,19 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) " ntc.t = tc.t + sin(tc.s+time)*0.125;\n" " vec3 ts = vec3(texture2D(watertexture, ntc));\n" - " gl_FragColor.rgb = ts;\n" + " gl_FragColor = vec4(ts, wateralpha);\n" "}\n" "#endif\n" "}\n" "param time time\n" "param texture 0 watertexture\n" + "param cvarf r_wateralpha wateralpha\n" "surfaceparm nodlight\n" "{\n" "map $diffuse\n" + "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" "}\n" + "sort blend\n" "}\n" ); } @@ -2675,12 +2720,14 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) "map $whiteimage\n" "rgbgen const $r_fastskycolour\n" "}\n" + "surfaceparm nodlight\n" "}\n" ); else if (*r_skyboxname.string) builtin = ( "{\n" "skyparms $r_skybox - -\n" + "surfaceparm nodlight\n" "}\n" ); #ifdef GLQUAKE @@ -2929,33 +2976,21 @@ void Shader_DefaultSkinShell(char *shortname, shader_t *s, const void *args) } void Shader_Default2D(char *shortname, shader_t *s, const void *genargs) { - shaderpass_t *pass; - pass = &s->passes[0]; - pass->flags = SHADER_PASS_NOCOLORARRAY; - pass->shaderbits |= SBITS_SRCBLEND_SRC_ALPHA; - pass->shaderbits |= SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA; - pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, IF_NOPICMIP|IF_NOMIPMAP); + Shader_DefaultScript(shortname, s, + "{\n" + "{\n" + "map $diffuse\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "blendfunc gl_src_alpha gl_one_minus_src_alpha\n" + "}\n" + "sort additive\n" + "}\n" + ); + + s->defaulttextures.base = R_LoadHiResTexture(shortname, NULL, IF_NOPICMIP|IF_NOMIPMAP); s->width = image_width; s->height = image_height; - pass->rgbgen = RGB_GEN_VERTEX; - pass->alphagen = ALPHA_GEN_VERTEX; - pass->numtcmods = 0; - pass->tcgen = TC_GEN_BASE; - pass->numMergedPasses = 1; - Shader_SetBlendmode(pass); - - if (!TEXVALID(pass->anim_frames[0])) - { - Con_DPrintf (CON_WARNING "Shader %s has a stage with no image: %s.\n", s->name, shortname ); - pass->anim_frames[0] = missing_texture; - } - - s->numpasses = 1; - s->numdeforms = 0; - s->flags = SHADER_NOPICMIP|SHADER_NOMIPMAPS|SHADER_BLEND; - s->features = MF_STCOORDS|MF_COLORS; - s->sort = SHADER_SORT_ADDITIVE; - s->uses = 1; } //loads a shader string into an existing shader object, and finalises it and stuff diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index c6075d2ba..84a6fffd3 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -68,120 +68,114 @@ static int sh_vertnum; //vertex number (set to 0 at SH_Begin) static shadowmesh_t *sh_shmesh, sh_tempshmesh; /* functions to add geometry to the shadow mesh */ -static void SHM_Begin (GLenum e) +static void SHM_BeginQuads (void) { - sh_type = e; sh_firstindex = sh_shmesh->numverts; } static void SHM_End (void) { int i; - int v1, v2; - switch(sh_type) + i = (sh_shmesh->numindicies+(sh_vertnum/4)*6+inc+5)&~(inc-1); //and a bit of padding + if (sh_shmesh->maxindicies != i) { - case GL_POLYGON: - i = (sh_shmesh->numindicies+(sh_vertnum-2)*3+inc+5)&~(inc-1); //and a bit of padding - if (sh_shmesh->maxindicies != i) - { - sh_shmesh->maxindicies = i; - sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, i * sizeof(*sh_shmesh->indicies)); - } - //decompose the poly into a triangle fan. - v1 = sh_firstindex + 0; - v2 = sh_firstindex + 1; - for (i = 2; i < sh_vertnum; i++) - { - sh_shmesh->indicies[sh_shmesh->numindicies++] = v1; - sh_shmesh->indicies[sh_shmesh->numindicies++] = v2; - sh_shmesh->indicies[sh_shmesh->numindicies++] = v2 = sh_firstindex + i; - } - sh_vertnum = 0; - break; - case GL_TRIANGLES: - i = (sh_shmesh->numindicies+(sh_vertnum)+inc+5)&~(inc-1); //and a bit of padding - if (sh_shmesh->maxindicies != i) - { - sh_shmesh->maxindicies = i; - sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, i * sizeof(*sh_shmesh->indicies)); - } - //add the extra triangles - for (i = 0; i < sh_vertnum; i+=3) - { - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+0; - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+1; - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+2; - } - sh_vertnum = 0; - break; - case GL_QUADS: - i = (sh_shmesh->numindicies+(sh_vertnum/4)*6+inc+5)&~(inc-1); //and a bit of padding - if (sh_shmesh->maxindicies != i) - { - sh_shmesh->maxindicies = i; - sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, i * sizeof(*sh_shmesh->indicies)); - } - //add the extra triangles - for (i = 0; i < sh_vertnum; i+=4) - { - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+0; - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+1; - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+2; - - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+0; - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+2; - sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+3; - } - sh_vertnum = 0; - break; - default: - if (sh_vertnum) - Sys_Error("SH_End: verticies were left"); + sh_shmesh->maxindicies = i; + sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, i * sizeof(*sh_shmesh->indicies)); } + //add the extra triangles + for (i = 0; i < sh_vertnum; i+=4) + { + sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+0; + sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+1; + sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+2; + + sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+0; + sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+2; + sh_shmesh->indicies[sh_shmesh->numindicies++] = sh_firstindex + i+3; + } + sh_vertnum = 0; } -static void SHM_Vertex3f (GLfloat x, GLfloat y, GLfloat z) +static void SHM_Vertex3fv (const GLfloat *v) { int i; //add the verts as we go i = (sh_shmesh->numverts+inc+5)&~(inc-1); //and a bit of padding - if (sh_shmesh->maxverts != i) + if (sh_shmesh->maxverts < i) { sh_shmesh->maxverts = i; sh_shmesh->verts = BZ_Realloc(sh_shmesh->verts, i * sizeof(*sh_shmesh->verts)); } - sh_shmesh->verts[sh_shmesh->numverts][0] = x; - sh_shmesh->verts[sh_shmesh->numverts][1] = y; - sh_shmesh->verts[sh_shmesh->numverts][2] = z; + sh_shmesh->verts[sh_shmesh->numverts][0] = v[0]; + sh_shmesh->verts[sh_shmesh->numverts][1] = v[1]; + sh_shmesh->verts[sh_shmesh->numverts][2] = v[2]; sh_vertnum++; sh_shmesh->numverts++; - switch(sh_type) + + if (sh_vertnum == 4) { - case GL_POLYGON: - break; - case GL_TRIANGLES: - if (sh_vertnum == 3) - { - SHM_End(); - sh_firstindex = sh_shmesh->numverts; - } - break; - case GL_QUADS: - if (sh_vertnum == 4) - { - SHM_End(); - sh_firstindex = sh_shmesh->numverts; - } - break; - default: - Sys_Error("SH_Vertex3f: bad type"); + SHM_End(); + sh_firstindex = sh_shmesh->numverts; } } -static void APIENTRY SHM_Vertex3fv (const GLfloat *v) + +void SHM_TriangleFan(int numverts, vecV_t *verts, vec3_t lightorg, float pd) { - SHM_Vertex3f(v[0], v[1], v[2]); + int v, i, idxs; + float *v1; + vec3_t v3; + vecV_t *outv; + index_t *outi; + + /*make sure there's space*/ + v = (sh_shmesh->numverts+numverts*2 + inc)&~(inc-1); //and a bit of padding + if (sh_shmesh->maxverts < v) + { + sh_shmesh->maxverts = v; + sh_shmesh->verts = BZ_Realloc(sh_shmesh->verts, v * sizeof(*sh_shmesh->verts)); + } + outv = sh_shmesh->verts + sh_shmesh->numverts; + + for (v = 0; v < numverts; v++) + { + v1 = verts[v]; + VectorCopy(v1, outv[v]); + + v3[0] = ( v1[0]-lightorg[0] )*pd; + v3[1] = ( v1[1]-lightorg[1] )*pd; + v3[2] = ( v1[2]-lightorg[2] )*pd; + + outv[v+numverts][0] = v1[0]+v3[0]; + outv[v+numverts][1] = v1[1]+v3[1]; + outv[v+numverts][2] = v1[2]+v3[2]; + } + + idxs = (numverts-2)*3; + /*now add the verts in a fan*/ + v = (sh_shmesh->numindicies+idxs*2+inc)&~(inc-1); //and a bit of padding + if (sh_shmesh->maxindicies < v) + { + sh_shmesh->maxindicies = v; + sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, v * sizeof(*sh_shmesh->indicies)); + } + outi = sh_shmesh->indicies + sh_shmesh->numindicies; + + for (v = 2, i = 0; v < numverts; v++, i+=3) + { + outi[i+0] = sh_shmesh->numverts; + outi[i+1] = sh_shmesh->numverts+v-1; + outi[i+2] = sh_shmesh->numverts+v; + + outi[i+0+idxs] = sh_shmesh->numverts+numverts+v; + outi[i+1+idxs] = sh_shmesh->numverts+numverts+v-1; + outi[i+2+idxs] = sh_shmesh->numverts+numverts; + } + + /*we added this many*/ + sh_shmesh->numverts += numverts*2; + sh_shmesh->numindicies += i*2; } static void SHM_Shadow_Cache_Surface(msurface_t *surf) @@ -209,27 +203,50 @@ static void SHM_Shadow_Cache_Leaf(mleaf_t *leaf) sh_shmesh->litleaves[i>>3] |= 1<<(i&7); } +void SH_FreeShadowMesh(shadowmesh_t *sm) +{ + unsigned int i; + for (i = 0; i < sm->numsurftextures; i++) + Z_Free(sm->litsurfs[i].s); + Z_Free(sm->litsurfs); + Z_Free(sm->indicies); + Z_Free(sm->verts); + Z_Free(sm); +} + static void SHM_BeginShadowMesh(dlight_t *dl) { unsigned int i; + unsigned int lb; sh_vertnum = 0; - if (!dl->die) + lb = (cl.worldmodel->numleafs+7)/8; + if (!dl->die || !dl->key) { - sh_shmesh = Z_Malloc(sizeof(*sh_shmesh) + (cl.worldmodel->numleafs+7)/8); - sh_shmesh->leafbytes = (cl.worldmodel->numleafs+7)/8; - sh_shmesh->litleaves = (unsigned char*)(sh_shmesh+1); + sh_shmesh = dl->worldshadowmesh; + if (!sh_shmesh || sh_shmesh->leafbytes != lb) + { + /*this shouldn't happen too often*/ + if (sh_shmesh) + { + SH_FreeShadowMesh(sh_shmesh); + } - dl->worldshadowmesh = sh_shmesh; + /*Create a new shadowmesh for this light*/ + sh_shmesh = Z_Malloc(sizeof(*sh_shmesh) + lb); + sh_shmesh->leafbytes = lb; + sh_shmesh->litleaves = (unsigned char*)(sh_shmesh+1); + + dl->worldshadowmesh = sh_shmesh; + } + dl->rebuildcache = false; } else { - unsigned int lb; -//FIXME: many dynamic lights are static. cache for a frame and see if it can be reused. sh_shmesh = &sh_tempshmesh; - lb = (cl.worldmodel->numleafs+7)/8; if (sh_shmesh->leafbytes != lb) { + /*this happens on map changes*/ sh_shmesh->leafbytes = lb; Z_Free(sh_shmesh->litleaves); sh_shmesh->litleaves = Z_Malloc(lb); @@ -240,7 +257,7 @@ static void SHM_BeginShadowMesh(dlight_t *dl) sh_shmesh->maxindicies = 0; sh_shmesh->numindicies = 0; - if (sh_shmesh->numsurftextures < cl.worldmodel->numtextures) + if (sh_shmesh->numsurftextures != cl.worldmodel->numtextures) { if (sh_shmesh->litsurfs) { @@ -281,9 +298,6 @@ static void SHM_RecursiveWorldNodeQ1_r (dlight_t *dl, mnode_t *node) double dot; int v; - float *v1; - vec3_t v3; - float l, maxdist; int j, s, t; vec3_t impact; @@ -407,9 +421,7 @@ static void SHM_RecursiveWorldNodeQ1_r (dlight_t *dl, mnode_t *node) { SHM_Shadow_Cache_Surface(surf); - - - #define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff + #define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff //build a list of the edges that are to be drawn. for (v = 0; v < surf->numedges; v++) @@ -454,26 +466,7 @@ static void SHM_RecursiveWorldNodeQ1_r (dlight_t *dl, mnode_t *node) } } - //fixme:this only works becuse q1bsps don't have combined meshes yet... - SHM_Begin(GL_POLYGON); - for (v = 0; v < surf->mesh->numvertexes; v++) - { - SHM_Vertex3fv(surf->mesh->xyz_array[v]); - } - SHM_End(); - - //back (depth precision doesn't matter) - SHM_Begin(GL_POLYGON); - for (v = surf->mesh->numvertexes-1; v >=0; v--) - { - v1 = surf->mesh->xyz_array[v]; - v3[0] = ( v1[0]-dl->origin[0] )*PROJECTION_DISTANCE; - v3[1] = ( v1[1]-dl->origin[1] )*PROJECTION_DISTANCE; - v3[2] = ( v1[2]-dl->origin[2] )*PROJECTION_DISTANCE; - - SHM_Vertex3f( v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2] ); - } - SHM_End(); + SHM_TriangleFan(surf->mesh->numvertexes, surf->mesh->xyz_array, dl->origin, PROJECTION_DISTANCE); } } } @@ -492,9 +485,6 @@ static void SHM_RecursiveWorldNodeQ2_r (dlight_t *dl, mnode_t *node) double dot; int v; - float *v1; - vec3_t v3; - float l, maxdist; int j, s, t; vec3_t impact; @@ -665,25 +655,7 @@ static void SHM_RecursiveWorldNodeQ2_r (dlight_t *dl, mnode_t *node) } } - SHM_Begin(GL_POLYGON); - for (v = 0; v < surf->mesh->numvertexes; v++) - { - SHM_Vertex3fv(surf->mesh->xyz_array[v]); - } - SHM_End(); - - //back (depth precision doesn't matter) - SHM_Begin(GL_POLYGON); - for (v = surf->mesh->numvertexes-1; v >=0; v--) - { - v1 = surf->mesh->xyz_array[v]; - v3[0] = ( v1[0]-dl->origin[0] )*PROJECTION_DISTANCE; - v3[1] = ( v1[1]-dl->origin[1] )*PROJECTION_DISTANCE; - v3[2] = ( v1[2]-dl->origin[2] )*PROJECTION_DISTANCE; - - SHM_Vertex3f( v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2] ); - } - SHM_End(); + SHM_TriangleFan(surf->mesh->numvertexes, surf->mesh->xyz_array, dl->origin, PROJECTION_DISTANCE); } } } @@ -851,8 +823,6 @@ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) unsigned int sno; unsigned int vno, vno2; unsigned int fvert, lvert; - float *v1; - vec3_t v3; mesh_t *sm; for (tno = 0; tno < sh_shmesh->numsurftextures; tno++) { @@ -870,27 +840,7 @@ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) //continue; fvert = sh_shmesh->numverts; - //front - SHM_Begin(GL_POLYGON); - for (vno = 0; vno < sm->numvertexes; vno++) - { - SHM_Vertex3fv(sm->xyz_array[vno]); - } - SHM_End(); - - //back (depth precision doesn't matter) - SHM_Begin(GL_POLYGON); - for (vno = sm->numvertexes; vno > 0; ) - { - vno--; - v1 = sm->xyz_array[vno]; - v3[0] = (v1[0]-dl->origin[0])*PROJECTION_DISTANCE; - v3[1] = (v1[1]-dl->origin[1])*PROJECTION_DISTANCE; - v3[2] = (v1[2]-dl->origin[2])*PROJECTION_DISTANCE; - - SHM_Vertex3f(v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2]); - } - SHM_End(); + SHM_TriangleFan(sm->numvertexes, sm->xyz_array, dl->origin, PROJECTION_DISTANCE); vno = (sh_shmesh->numindicies+sm->numvertexes*6); //and a bit of padding if (sh_shmesh->maxindicies < vno) @@ -944,7 +894,7 @@ static struct shadowmesh_s *SHM_BuildShadowVolumeMesh(dlight_t *dl, unsigned cha float *v1, *v2; vec3_t v3, v4; - if (dl->worldshadowmesh) + if (dl->worldshadowmesh && !dl->rebuildcache) return dl->worldshadowmesh; if (cl.worldmodel->fromgame == fg_quake || cl.worldmodel->fromgame == fg_halflife) @@ -981,7 +931,7 @@ static struct shadowmesh_s *SHM_BuildShadowVolumeMesh(dlight_t *dl, unsigned cha else return NULL; - SHM_Begin(GL_QUADS); + SHM_BeginQuads(); while(firstedge) { //border @@ -1461,12 +1411,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) checkerror(); } - if (l->worldshadowmesh) - smesh = l->worldshadowmesh; - else - { - smesh = SHM_BuildShadowVolumeMesh(l, lvis, NULL); - } + smesh = SHM_BuildShadowVolumeMesh(l, lvis, NULL); /*polygon offsets. urgh.*/ qglEnable(GL_POLYGON_OFFSET_FILL); @@ -1678,6 +1623,8 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) currententity = &r_worldentity; sm = light->worldshadowmesh; + if (light->rebuildcache) + sm = &sh_tempshmesh; if (sm) { for (tno = 0; tno < sm->numsurftextures; tno++) @@ -1690,16 +1637,12 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) BE_BaseEntTextures(); } - else - { -#pragma message("FIXME: For dynamic lights, the entire view is redrawn! Bad!") - BE_SubmitMeshes(); - } } #define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff /*Fixme: this is brute forced*/ +#pragma message("brush shadows are bruteforced") static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) { int v; @@ -1902,7 +1845,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) maxs[1] = dl->origin[1] + dl->radius; maxs[2] = dl->origin[2] + dl->radius; - if (dl->worldshadowmesh) + if (!dl->rebuildcache) { //fixme: check head node first? if (!Sh_LeafInView(dl->worldshadowmesh->litleaves, vvis)) @@ -2091,7 +2034,7 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) return; //this should be the more common case } - if (dl->worldshadowmesh) + if (!dl->rebuildcache) { //fixme: check head node first? if (!Sh_LeafInView(dl->worldshadowmesh->litleaves, vvis)) diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 99434a776..a3f1f865f 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -171,6 +171,7 @@ extern cvar_t vid_preservegamma; extern cvar_t vid_gl_context_version; extern cvar_t vid_gl_context_debug; extern cvar_t vid_gl_context_forwardcompatible; +extern cvar_t vid_gl_context_compatibility; int window_center_x, window_center_y, window_x, window_y, window_width, window_height; RECT window_rect; @@ -238,7 +239,12 @@ HGLRC (APIENTRY *qwglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext, cons #define WGL_CONTEXT_FLAGS_ARB 0x2094 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 #define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 + qboolean GLInitialise (char *renderer) @@ -857,7 +863,6 @@ qboolean VID_AttachGL (rendererstate_t *info) #ifdef USE_D3D if (!Q_strcasecmp(info->glrenderer, "D3D")) { - extern cvar_t gl_ztrick; int zbpp = info->bpp > 16 ? 24 : 16; gl_canstencil = false; TRACE(("dbg: VID_AttachGL: D3DInitialize\n")); @@ -869,16 +874,12 @@ qboolean VID_AttachGL (rendererstate_t *info) TRACE(("dbg: VID_AttachGL: d3dSetMode\n")); d3dSetMode(info->fullscreen, info->width, info->height, info->bpp, zbpp); //d3d cheats to get it's dimensions and stuff... One that we can currently live with though. - gl_ztrickdisabled |= 2; //ztrick does funny things. - Cvar_Set(&gl_ztrick, "0"); - maindc = GetDC(mainwindow); Con_Printf(CON_NOTICE "OpenGL to Direct3D wrapper enabled\n"); //green to make it show. break; } #endif - gl_ztrickdisabled &= ~2; TRACE(("dbg: VID_AttachGL: GLInitialise\n")); if (GLInitialise(info->glrenderer)) { @@ -967,6 +968,14 @@ qboolean VID_AttachGL (rendererstate_t *info) i += 2; } + attribs[i+1] = 0; + if (vid_gl_context_compatibility.value) + attribs[i+1] |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + else + attribs[i+1] |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + attribs[i] = WGL_CONTEXT_PROFILE_MASK_ARB; + i+=2; + attribs[i] = 0; if (!i) diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 2004ae224..f72a6f6b7 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -222,8 +222,6 @@ extern int d_lightstylevalue[256]; // 8.8 fraction of base light value extern texid_t netgraphtexture; // netgraph texture -extern int gl_lightmap_format; - extern int mirrortexturenum; // quake texturenum, not gltexturenum extern qboolean mirror; extern mplane_t *mirror_plane; diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index aebf96cdd..37128cd1b 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -40,10 +40,14 @@ extern qlpMTex2FUNC qglMultiTexCoord2fARB; ./gl/gl_draw.c:3251: error: for each function it appears in.) */ #ifndef GL_EXT_bgra -#define GL_BGR_EXT 0x80E0 +#define GL_BGR_EXT 0x80E0 /*core in opengl 1.2*/ #define GL_BGRA_EXT 0x80E1 #endif +#ifndef GL_UNSIGNED_INT_8_8_8_8_REV +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 /*opengl 1.2*/ +#endif + #ifndef GL_ARB_multitexture #define GL_ARB_multitexture 1 #define GL_TEXTURE0_ARB 0x84C0 diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 38839fd9f..d446411ae 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -264,6 +264,7 @@ typedef struct { SP_FIRSTIMMEDIATE, //never set SP_CVARI, SP_CVARF, + SP_CVAR3F, SP_TEXTURE } type; unsigned int handle; @@ -405,6 +406,8 @@ void BE_GenBrushModelVBO(model_t *mod); void BE_ClearVBO(vbo_t *vbo); //Uploads all modified lightmaps void BE_UploadAllLightmaps(void); +//Builds a hardware shader from the software representation +void BE_GenerateProgram(shader_t *shader); #ifdef RTLIGHTS void BE_PushOffsetShadow(qboolean foobar); diff --git a/engine/qclib/hash.c b/engine/qclib/hash.c index 143a4372a..dff0dc19a 100644 --- a/engine/qclib/hash.c +++ b/engine/qclib/hash.c @@ -9,21 +9,21 @@ #endif // hash init assumes we get clean memory -void Hash_InitTable(hashtable_t *table, int numbucks, void *mem) +void Hash_InitTable(hashtable_t *table, unsigned int numbucks, void *mem) { table->numbuckets = numbucks; table->bucket = (bucket_t **)mem; } -int Hash_Key(const char *name, int modulus) +unsigned int Hash_Key(const char *name, unsigned int modulus) { //fixme: optimize. unsigned int key; for (key=0;*name; name++) key += ((key<<3) + (key>>28) + *name); - return (int)(key%modulus); + return (key%modulus); } -int Hash_KeyInsensative(const char *name, int modulus) +unsigned int Hash_KeyInsensative(const char *name, unsigned int modulus) { //fixme: optimize. unsigned int key; for (key=0;*name; name++) @@ -34,12 +34,12 @@ int Hash_KeyInsensative(const char *name, int modulus) key += ((key<<3) + (key>>28) + *name); } - return (int)(key%modulus); + return (key%modulus); } void *Hash_Get(hashtable_t *table, const char *name) { - int bucknum = Hash_Key(name, table->numbuckets); + unsigned int bucknum = Hash_Key(name, table->numbuckets); bucket_t *buck; buck = table->bucket[bucknum]; @@ -55,7 +55,7 @@ void *Hash_Get(hashtable_t *table, const char *name) } void *Hash_GetInsensative(hashtable_t *table, const char *name) { - int bucknum = Hash_KeyInsensative(name, table->numbuckets); + unsigned int bucknum = Hash_KeyInsensative(name, table->numbuckets); bucket_t *buck; buck = table->bucket[bucknum]; @@ -69,9 +69,9 @@ void *Hash_GetInsensative(hashtable_t *table, const char *name) } return NULL; } -void *Hash_GetKey(hashtable_t *table, int key) +void *Hash_GetKey(hashtable_t *table, unsigned int key) { - int bucknum = key%table->numbuckets; + unsigned int bucknum = key%table->numbuckets; bucket_t *buck; buck = table->bucket[bucknum]; @@ -87,7 +87,7 @@ void *Hash_GetKey(hashtable_t *table, int key) } void *Hash_GetNext(hashtable_t *table, const char *name, void *old) { - int bucknum = Hash_Key(name, table->numbuckets); + unsigned int bucknum = Hash_Key(name, table->numbuckets); bucket_t *buck; buck = table->bucket[bucknum]; @@ -117,7 +117,7 @@ void *Hash_GetNext(hashtable_t *table, const char *name, void *old) } void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old) { - int bucknum = Hash_KeyInsensative(name, table->numbuckets); + unsigned int bucknum = Hash_KeyInsensative(name, table->numbuckets); bucket_t *buck; buck = table->bucket[bucknum]; @@ -149,7 +149,7 @@ void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old) void *Hash_Add(hashtable_t *table, const char *name, void *data, bucket_t *buck) { - int bucknum = Hash_Key(name, table->numbuckets); + unsigned int bucknum = Hash_Key(name, table->numbuckets); buck->data = data; buck->key.string = name; @@ -160,7 +160,7 @@ void *Hash_Add(hashtable_t *table, const char *name, void *data, bucket_t *buck) } void *Hash_AddInsensative(hashtable_t *table, const char *name, void *data, bucket_t *buck) { - int bucknum = Hash_KeyInsensative(name, table->numbuckets); + unsigned int bucknum = Hash_KeyInsensative(name, table->numbuckets); buck->data = data; buck->key.string = name; @@ -169,9 +169,9 @@ void *Hash_AddInsensative(hashtable_t *table, const char *name, void *data, buck return buck; } -void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck) +void *Hash_AddKey(hashtable_t *table, unsigned int key, void *data, bucket_t *buck) { - int bucknum = key%table->numbuckets; + unsigned int bucknum = key%table->numbuckets; buck->data = data; buck->key.value = key; @@ -183,7 +183,7 @@ void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck) void Hash_Remove(hashtable_t *table, const char *name) { - int bucknum = Hash_Key(name, table->numbuckets); + unsigned int bucknum = Hash_Key(name, table->numbuckets); bucket_t *buck; buck = table->bucket[bucknum]; @@ -210,7 +210,7 @@ void Hash_Remove(hashtable_t *table, const char *name) void Hash_RemoveData(hashtable_t *table, const char *name, void *data) { - int bucknum = Hash_Key(name, table->numbuckets); + unsigned int bucknum = Hash_Key(name, table->numbuckets); bucket_t *buck; buck = table->bucket[bucknum]; @@ -238,9 +238,9 @@ void Hash_RemoveData(hashtable_t *table, const char *name, void *data) } -void Hash_RemoveKey(hashtable_t *table, int key) +void Hash_RemoveKey(hashtable_t *table, unsigned int key) { - int bucknum = key%table->numbuckets; + unsigned int bucknum = key%table->numbuckets; bucket_t *buck; buck = table->bucket[bucknum]; diff --git a/engine/qclib/hash.h b/engine/qclib/hash.h index fbc8474c2..951399629 100644 --- a/engine/qclib/hash.h +++ b/engine/qclib/hash.h @@ -5,34 +5,34 @@ #ifndef HASH_H__ #define HASH_H__ -#define Hash_BytesForBuckets(b) (sizeof(bucket_t*)*b) +#define Hash_BytesForBuckets(b) (sizeof(bucket_t*)*(b)) #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc typedef struct bucket_s { void *data; union { const char *string; - int value; + unsigned int value; } key; struct bucket_s *next; } bucket_t; typedef struct hashtable_s { - int numbuckets; + unsigned int numbuckets; bucket_t **bucket; } hashtable_t; -void Hash_InitTable(hashtable_t *table, int numbucks, void *mem); //mem must be 0 filled. (memset(mem, 0, size)) -int Hash_Key(const char *name, int modulus); +void Hash_InitTable(hashtable_t *table, unsigned int numbucks, void *mem); //mem must be 0 filled. (memset(mem, 0, size)) +unsigned int Hash_Key(const char *name, unsigned int modulus); void *Hash_Get(hashtable_t *table, const char *name); void *Hash_GetInsensative(hashtable_t *table, const char *name); -void *Hash_GetKey(hashtable_t *table, int key); +void *Hash_GetKey(hashtable_t *table, unsigned int key); void *Hash_GetNext(hashtable_t *table, const char *name, void *old); void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old); void *Hash_Add(hashtable_t *table, const char *name, void *data, bucket_t *buck); void *Hash_AddInsensative(hashtable_t *table, const char *name, void *data, bucket_t *buck); void Hash_Remove(hashtable_t *table, const char *name); void Hash_RemoveData(hashtable_t *table, const char *name, void *data); -void Hash_RemoveKey(hashtable_t *table, int key); -void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck); +void Hash_RemoveKey(hashtable_t *table, unsigned int key); +void *Hash_AddKey(hashtable_t *table, unsigned int key, void *data, bucket_t *buck); #endif diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index bdd2af959..62fb0be2e 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -504,7 +504,7 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key) fdef = ED_FindField (progfuncs, assignment); if (!fdef) { - int l,nl = strlen(assignment); + size_t l,nl = strlen(assignment); strcpy(buf, "Can't find field "); l = strlen(buf); if (nl > sizeof(buf)-l-2) @@ -537,7 +537,7 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key) func = ED_FindFunction (progfuncs, s, &i, progsnum); if (!func) { - int l,nl = strlen(s); + size_t l,nl = strlen(s); assignment[-1] = '='; diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 4aa5b986b..36e229cc7 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -540,6 +540,7 @@ CompilerConstant_t *QCC_PR_DefineName(char *name); void QCC_RemapOffsets(unsigned int firststatement, unsigned int laststatement, unsigned int min, unsigned int max, unsigned int newmin); #ifndef COMMONINLINES +pbool QCC_PR_CheckImmediate (char *string); pbool QCC_PR_CheckToken (char *string); pbool QCC_PR_CheckName (char *string); void QCC_PR_Expect (char *string); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index d7efd25dd..6899be712 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -7931,7 +7931,7 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a { if (!pHash_Get(&globalstable, "end_sys_fields")) first->references++; //anything above needs to be left in, and so warning about not using it is just going to pee people off. - if (arraysize <= 1) + if (arraysize <= 1 && first->type->type != ev_field) first->constant = false; if (scope) pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t))); @@ -9044,13 +9044,14 @@ void QCC_PR_ParseDefs (char *classname) continue; } -#pragma message("this is experimental") if (pr_scope) { d = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); + if (typecmp(def->type, d->type)) + QCC_PR_ParseError (ERR_BADIMMEDIATETYPE, "wrong immediate type for %s", name); if (d->constant) { - for (i = 0; i < d->type->size; i++) + for (i = 0; (unsigned)i < def->type->size; i++) G_INT(def->ofs+i) = G_INT(d->ofs+i); def->constant = !isvar; def->initialized = 1; @@ -9599,8 +9600,15 @@ void QCC_PR_ParseDefs (char *classname) def->initialized = 1; } - if (isconstant && type->type == ev_field) - def->constant = 2; //special flag on fields, 2, makes the pointer obtained from them also constant. + if (type->type == ev_field) + { + if (isconstant) + def->constant = 2; //special flag on fields, 2, makes the pointer obtained from them also constant. + else if (isvar) + def->constant = 0; + else + def->constant = 1; + } else def->constant = isconstant; } diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 31b25cb25..d40cc5290 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -3121,7 +3121,6 @@ newstyle: { while (pr_file_p=QCC_COM_Parse(pr_file_p)) { - struct stat s; if (stat(qcc_token, &s) == -1 || s.st_mtime > os.st_mtime) { printf("%s changed\n", qcc_token); diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index abc93f731..7b9646499 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -1,6 +1,564 @@ #include "qwsvdef.h" #ifndef CLIENTONLY +/*Testing this code should typically be done with the three following mods: +Prydon gate +Nexuiz +FrikBots (both NQ+QW). + +If those 3 mods work, then pretty much everything else will +*/ + +//#define NEWPREPARSE + +/*I want to rewrite this +to use something like +*/ + +#ifdef NEWPREPARSE +enum protocol_type +{ + PPT_FLOAT, + PPT_ENT, + PPT_COORD, + PPT_ANGLE, + PPT_BYTE, + PPT_SHORT, + PPT_LONG, + PPT_STRING +}; + +#define PPT_POS PPT_COORD,PPT_COORD,PPT_COORD + +union protocol_data +{ + float fd; + int id; + unsigned char *str; +}; + +static union protocol_data pp_data[1024]; +static enum protocol_type pp_temptypes[1024], *pp_types; +static unsigned char pp_sdata[4096]; +static unsigned int pp_sdata_offset; +static int pp_dest; +static qboolean pp_fault; + +static unsigned int pp_expectedelements; +static unsigned int pp_receivedelements; +static qboolean (*pp_curdecision) (enum protocol_type *pt, union protocol_data *pd); + +static enum protocol_type pp_root[] = {PPT_BYTE}; +static qboolean pp_root_decide(enum protocol_type *pt, union protocol_data *pd); + +static void decide(enum protocol_type *types, unsigned int numtypes, qboolean (*newdecision) (enum protocol_type *pt, union protocol_data *pd)) +{ + pp_types = types; + pp_expectedelements = numtypes; + pp_curdecision = newdecision; +} + +static void pp_flush(multicast_t to, vec3_t origin, void (*flushfunc)(client_t *cl, sizebuf_t *msg, enum protocol_type *pt, union protocol_data *pd), enum protocol_type *pt, union protocol_data *pd) +{ + + client_t *client; + qbyte *mask; + int leafnum; + int j; + qboolean reliable; + + decide(pp_root, 1, pp_root_decide); + + + + { + reliable = false; + + switch (to) + { + case MULTICAST_ALL_R: + reliable = true; // intentional fallthrough + case MULTICAST_ALL: + mask = sv.pvs; // leaf 0 is everything; + break; + + case MULTICAST_PHS_R: + reliable = true; // intentional fallthrough + case MULTICAST_PHS: + if (!sv.phs) + 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; + + default: + return; + } + + // send the data to all relevent clients + for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) + { + if (client->state != cs_spawned) + continue; + + if (client->controller) + continue; //FIXME: send if at least one of the players is near enough. + + if (!((int)client->edict->xv->dimension_see & (int)pr_global_struct->dimension_send)) + continue; + + if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) + { + vec3_t delta; + VectorSubtract(origin, client->edict->v->origin, delta); + if (Length(delta) <= 1024) + goto inrange; + } + + // -1 is because pvs rows are 1 based, not 0 based like leafs + if (mask != sv.pvs) + { + leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, client->edict->v->origin)-1; + if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + { + continue; + } + } + +inrange: + if (client->protocol == SCP_BAD) + { + /*bot*/ + continue; + } + if (reliable) + flushfunc(client, &client->netchan.message, pt, pd); + else + flushfunc(client, &client->datagram, pt, pd); + } + } +/* + if (sv.mvdrecording && !with) //mvds don't get the pext stuff + { + flushfunc(&dem.recorder, + if (reliable) + { + MVDWrite_Begin(dem_all, 0, sv.multicast.cursize); + SZ_Write((sizebuf_t*)demo.dbuf, sv.multicast.data, sv.multicast.cursize); + } else + SZ_Write(&demo.datagram, sv.multicast.data, sv.multicast.cursize); + }*/ + + pp_sdata_offset = 0; + pp_receivedelements = 0; +} + +#define DECIDE(t) decide(t, sizeof(t)/sizeof(*t), t##_decide) +#define DECIDE2(t,f) decide(t, sizeof(t)/sizeof(*t), f) + +static void pp_identity_flush(client_t *cl, sizebuf_t *msg, enum protocol_type *pt, union protocol_data *pd) +{ + unsigned int i; + for (i = 0; i < pp_receivedelements; i++) + { + switch(pt[i]) + { + case PPT_BYTE: + MSG_WriteByte(msg, pd[i].id); + break; + case PPT_ENT: + case PPT_SHORT: + MSG_WriteShort(msg, pd[i].id); + break; + case PPT_COORD: + MSG_WriteCoord(msg, pd[i].fd); + break; + case PPT_ANGLE: + MSG_WriteAngle(msg, pd[i].fd); + break; + case PPT_STRING: + MSG_WriteString(msg, pd[i].str); + break; + } + } +} + +/*flush is our last attempt to cope with unrecognised/invalid messages, it will send stuff though as it was, and most likely get things wrong*/ +void NPP_Flush(void) +{ + pp_fault = false; + pp_flush(MULTICAST_ALL_R, NULL, pp_identity_flush, pp_types, pp_data); +} + +static void pp_entry(int dest, enum protocol_type pt, union protocol_data pd) +{ + if (pp_receivedelements) + { + if (pp_dest != dest) + { + if (!pp_fault) + Con_Printf("Preparse: MSG destination changed in the middle of a packet 0x%x.\n", pp_data[0].id); + NPP_Flush(); + } + } + pp_dest = dest; + + if (pp_fault) + { + pp_types[pp_receivedelements] = pt; + pp_data[pp_receivedelements] = pd; + pp_receivedelements++; + } + else if (pp_types[pp_receivedelements] != pt) + { + Con_Printf("Preparse: Unmatched expectation at entry %i in svc 0x%x.\n", pp_receivedelements+1, pp_data[0].id); + + pp_types[pp_receivedelements] = pt; + pp_data[pp_receivedelements] = pd; + pp_receivedelements++; + +faulted: + pp_fault = true; + if (pp_temptypes != pp_types) + { + memcpy(pp_temptypes, pp_types, sizeof(*pp_temptypes)*pp_receivedelements); + pp_types = pp_temptypes; + } + } + else + { + pp_data[pp_receivedelements++] = pd; + + if (pp_expectedelements == pp_receivedelements) + { + if (!pp_curdecision(pp_types, pp_data)) + { + if (pp_types[pp_receivedelements-1] == PPT_BYTE) + Con_Printf("Preparse: Unhandled byte %i@%i in svc%i.\n", pd.id, pp_receivedelements, pp_data[0].id); + else + Con_Printf("Preparse: Unhandled data @%i in svc%i.\n", pp_receivedelements, pp_data[0].id); + goto faulted; + } + } + } +} + +void NPP_NQWriteByte(int dest, qbyte data) +{ + union protocol_data pd; + pd.id = data; + pp_entry(dest, PPT_BYTE, pd); +} +void NPP_NQWriteChar(int dest, char data) +{ + union protocol_data pd; + pd.id = (unsigned char)data; + pp_entry(dest, PPT_BYTE, pd); +} +void NPP_NQWriteShort(int dest, short data) +{ + union protocol_data pd; + pd.id = (unsigned char)data; + pp_entry(dest, PPT_SHORT, pd); +} +void NPP_NQWriteLong(int dest, long data) +{ + union protocol_data pd; + pd.id = data; + pp_entry(dest, PPT_LONG, pd); +} +void NPP_NQWriteAngle(int dest, float data) +{ + union protocol_data pd; + pd.fd = data; + pp_entry(dest, PPT_ANGLE, pd); +} +void NPP_NQWriteCoord(int dest, float data) +{ + union protocol_data pd; + pd.fd = data; + pp_entry(dest, PPT_COORD, pd); +} +void NPP_NQWriteString(int dest, char *data) +{ + unsigned int l; + union protocol_data pd; + l = strlen(data)+1; + if (pp_sdata_offset + l > sizeof(pp_sdata)) + SV_Error("preparse string overflow\n"); + pd.str = pp_sdata + pp_sdata_offset; + memcpy(pd.str, data, l); + pp_entry(dest, PPT_STRING, pd); +} +void NPP_NQWriteEntity(int dest, short data) +{ + union protocol_data pd; + pd.id = (unsigned short)data; + pp_entry(dest, PPT_COORD, pd); +} + +void NPP_QWWriteByte(int dest, qbyte data) +{ + NPP_NQWriteByte(dest, data); +} +void NPP_QWWriteChar(int dest, char data) +{ + NPP_NQWriteChar(dest, data); +} +void NPP_QWWriteShort(int dest, short data) +{ + NPP_NQWriteShort(dest, data); +} +void NPP_QWWriteLong(int dest, long data) +{ + NPP_NQWriteLong(dest, data); +} +void NPP_QWWriteAngle(int dest, float data) +{ + NPP_NQWriteAngle(dest, data); +} +void NPP_QWWriteCoord(int dest, float data) +{ + NPP_NQWriteCoord(dest, data); +} +void NPP_QWWriteString(int dest, char *data) +{ + NPP_NQWriteString(dest, data); +} +void NPP_QWWriteEntity(int dest, short data) +{ + NPP_NQWriteEntity(dest, data); +} + + + + + + + + + + + +static enum protocol_type pp_svc_temp_entity_beam[] = {PPT_BYTE, PPT_BYTE, PPT_ENT, PPT_POS, PPT_POS}; +static void pp_svc_temp_entity_beam_flush(client_t *cl, sizebuf_t *msg, enum protocol_type *pt, union protocol_data *pd) +{ + MSG_WriteByte(msg, pd[0].id); + MSG_WriteByte(msg, pd[1].id); + MSG_WriteShort(msg, pd[2].id); + MSG_WriteCoord(msg, pd[3].fd); + MSG_WriteCoord(msg, pd[4].fd); + MSG_WriteCoord(msg, pd[5].fd); + MSG_WriteCoord(msg, pd[6].fd); + MSG_WriteCoord(msg, pd[7].fd); + MSG_WriteCoord(msg, pd[8].fd); +} +static qboolean pp_svc_temp_entity_beam_decide(enum protocol_type *pt, union protocol_data *pd) +{ + vec3_t org; + org[0] = pd[3].fd; + org[1] = pd[4].fd; + org[2] = pd[5].fd; + pp_flush(MULTICAST_PHS, org, pp_svc_temp_entity_beam_flush, pt, pd); + return true; +} + +static void pp_svc_temp_entity_gunshot_flush(client_t *cl, sizebuf_t *msg, enum protocol_type *pt, union protocol_data *pd) +{ + int offset = (progstype == PROG_QW)?3:2; + int count = (offset == 3)?pd[2].id:1; + + while (count > 0) + { + MSG_WriteByte(msg, pd[0].id); + MSG_WriteByte(msg, pd[1].id); + if (cl->protocol == SCP_QUAKEWORLD) + { + if (count > 255) + { + MSG_WriteByte(msg, 255); + count-=255; + } + else + { + MSG_WriteByte(msg, count); + count = 0; + } + } + else + count--; + MSG_WriteCoord(msg, pd[offset+0].fd); + MSG_WriteCoord(msg, pd[offset+1].fd); + MSG_WriteCoord(msg, pd[offset+2].fd); + } +} +static qboolean pp_svc_temp_entity_gunshot(enum protocol_type *pt, union protocol_data *pd) +{ + vec3_t org; + int offset = (progstype == PROG_QW)?3:2; + org[0] = pd[offset+0].fd; + org[1] = pd[offset+1].fd; + org[2] = pd[offset+2].fd; + pp_flush(MULTICAST_PHS, org, pp_svc_temp_entity_gunshot_flush, pt, pd); + return true; +} + +static qboolean pp_decide_pvs_2(enum protocol_type *pt, union protocol_data *pd) +{ + vec3_t org; + org[0] = pd[2].fd; + org[1] = pd[3].fd; + org[2] = pd[4].fd; + pp_flush(MULTICAST_PVS, org, pp_identity_flush, pt, pd); + return true; +} +static qboolean pp_decide_phs_2(enum protocol_type *pt, union protocol_data *pd) +{ + vec3_t org; + org[0] = pd[2].fd; + org[1] = pd[3].fd; + org[2] = pd[4].fd; + pp_flush(MULTICAST_PHS, org, pp_identity_flush, pt, pd); + return true; +} + +static enum protocol_type pp_svc_temp_entity[] = {PPT_BYTE, PPT_BYTE}; +static qboolean pp_svc_temp_entity_decide(enum protocol_type *pt, union protocol_data *pd) +{ + switch(pd[1].id) + { + case TE_LIGHTNING1: + case TE_LIGHTNING2: + case TE_LIGHTNING3: + DECIDE(pp_svc_temp_entity_beam); + return true; + case TE_EXPLOSION: + case TEDP_EXPLOSIONQUAD: + case TE_SPIKE: + case TE_SUPERSPIKE: + case TEDP_SPIKEQUAD: + case TEDP_SUPERSPIKEQUAD: + case TEDP_SMALLFLASH: + { + static enum protocol_type fmt[] = {PPT_BYTE, PPT_BYTE, PPT_POS}; + DECIDE2(fmt, pp_decide_phs_2); + } + return true; + + case TEDP_GUNSHOTQUAD: + case TE_TAREXPLOSION: + case TE_WIZSPIKE: + case TE_KNIGHTSPIKE: + case TE_LAVASPLASH: + case TE_TELEPORT: + { + static enum protocol_type fmt[] = {PPT_BYTE, PPT_BYTE, PPT_POS}; + DECIDE2(fmt, pp_decide_pvs_2); + } + return true; + + case TE_GUNSHOT: + if (progstype == PROG_QW) + { + static enum protocol_type fmt[] = {PPT_BYTE, PPT_BYTE, PPT_BYTE, PPT_POS}; + DECIDE2(fmt, pp_svc_temp_entity_gunshot); + } + else + { + static enum protocol_type fmt[] = {PPT_BYTE, PPT_BYTE, PPT_POS}; + DECIDE2(fmt, pp_svc_temp_entity_gunshot); + } + return true; + + case 12: + if (progstype == PROG_QW) + { + /*TEQW_BLOOD*/ + } + else + { + /*TENQ_EXPLOSION2*/ + } + return false; + + case 13: + if (progstype == PROG_QW) + { + /*TEQW_LIGHTNINGBLOOD*/ + } + else + { + /*TENQ_BEAM*/ + } + return false; + + case TEDP_BLOOD: + case TEDP_SPARK: + { + static enum protocol_type fmt[] = {PPT_BYTE, PPT_BYTE, PPT_POS, PPT_BYTE,PPT_BYTE,PPT_BYTE, PPT_BYTE}; + DECIDE2(fmt, pp_decide_pvs_2); + } + return true; + + case TE_BULLET: + case TE_SUPERBULLET: + + case TE_RAILTRAIL: + + // hexen 2 + case TEH2_STREAM_CHAIN: + case TEH2_STREAM_SUNSTAFF1: + case TEH2_STREAM_SUNSTAFF2: + case TEH2_STREAM_LIGHTNING: + case TEH2_STREAM_COLORBEAM: + case TEH2_STREAM_ICECHUNKS: + case TEH2_STREAM_GAZE: + case TEH2_STREAM_FAMINE: + + case TEDP_BLOODSHOWER: + case TEDP_EXPLOSIONRGB: + case TEDP_PARTICLECUBE: + case TEDP_PARTICLERAIN: // [vector] min [vector] max [vector] dir [short] count [byte] color + case TEDP_PARTICLESNOW: // [vector] min [vector] max [vector] dir [short] count [byte] color + case TEDP_CUSTOMFLASH: + case TEDP_FLAMEJET: + case TEDP_PLASMABURN: + case TEDP_TEI_G3: + case TEDP_SMOKE: + case TEDP_TEI_BIGEXPLOSION: + case TEDP_TEI_PLASMAHIT: + default: + return false; + } +} + +qboolean pp_root_decide(enum protocol_type *pt, union protocol_data *pd) +{ + switch (pd[0].id) + { + case svc_temp_entity: + DECIDE(pp_svc_temp_entity); + return true; + default: + return false; + } +} + + + + + +#else static sizebuf_t *writedest; static client_t *cldest; @@ -194,12 +752,12 @@ void NPP_NQFlush(void) vec3_t org; coorddata cd; - memcpy(&cd, &buffer[multicastpos+sizeofcoord*0], sizeofcoord); - org[0] = MSG_FromCoord(cd, sizeofcoord); - memcpy(&cd, &buffer[multicastpos+sizeofcoord*1], sizeofcoord); - org[1] = MSG_FromCoord(cd, sizeofcoord); - memcpy(&cd, &buffer[multicastpos+sizeofcoord*2], sizeofcoord); - org[2] = MSG_FromCoord(cd, sizeofcoord); + memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*0], writedest->prim.coordsize); + org[0] = MSG_FromCoord(cd, writedest->prim.coordsize); + memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*1], writedest->prim.coordsize); + org[1] = MSG_FromCoord(cd, writedest->prim.coordsize); + memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*2], writedest->prim.coordsize); + org[2] = MSG_FromCoord(cd, writedest->prim.coordsize); SV_MulticastProtExt(org, multicasttype, pr_global_struct->dimension_send, requireextension, 0); } @@ -360,7 +918,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) switch(majortype) { case svc_sound: - protocollen = 5+sizeofcoord*3; + protocollen = 5+writedest->prim.coordsize*3; if (data & NQSND_VOLUME) protocollen++; if (data & NQSND_ATTENUATION) @@ -383,7 +941,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_LIGHTNING3: multicastpos=4; multicasttype=MULTICAST_PHS; - protocollen = sizeofcoord*6+sizeof(short)+sizeof(qbyte)*2; + protocollen = writedest->prim.coordsize*6+sizeof(short)+sizeof(qbyte)*2; break; case TE_GUNSHOT: multicastpos=3; @@ -392,14 +950,14 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) //emit it here and we don't need to remember to play with temp_entity later NPP_AddData(&data, sizeof(qbyte)); data = 1; - protocollen = sizeofcoord*3+sizeof(qbyte)*3; + protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*3; break; case TE_EXPLOSION: case TE_SPIKE: case TE_SUPERSPIKE: multicastpos=2; multicasttype=MULTICAST_PHS_R; - protocollen = sizeofcoord*3+sizeof(qbyte)*2; + protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; break; case TE_TAREXPLOSION: case TE_WIZSPIKE: @@ -408,25 +966,25 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_TELEPORT: multicastpos=2; multicasttype=MULTICAST_PVS; - protocollen = sizeofcoord*3+sizeof(qbyte)*2; + protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; break; case TE_EXPLOSION3_NEH: - protocollen = sizeof(qbyte) + sizeofcoord*6; + protocollen = sizeof(qbyte) + writedest->prim.coordsize*6; ignoreprotocol = true; break; case TENQ_EXPLOSION2: - protocollen = sizeof(qbyte)*4 + sizeofcoord*3; + protocollen = sizeof(qbyte)*4 + writedest->prim.coordsize*3; multicastpos=2; multicasttype=MULTICAST_PHS_R; break; case TE_EXPLOSIONSMALL2: data = TE_EXPLOSION; - protocollen = sizeof(qbyte)*2 + sizeofcoord*3; + protocollen = sizeof(qbyte)*2 + writedest->prim.coordsize*3; multicastpos=2; multicasttype=MULTICAST_PHS; break; case TE_RAILTRAIL: - protocollen = sizeofcoord*6+sizeof(qbyte)*1; + protocollen = writedest->prim.coordsize*6+sizeof(qbyte)*1; multicastpos=2; multicasttype=MULTICAST_PHS; break; @@ -437,42 +995,42 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TEH2_STREAM_ICECHUNKS: case TEH2_STREAM_GAZE: case TEH2_STREAM_FAMINE: - protocollen = sizeofcoord*6+sizeof(short)+sizeof(qbyte)*(2+2); + protocollen = writedest->prim.coordsize*6+sizeof(short)+sizeof(qbyte)*(2+2); multicastpos = 8; multicasttype=MULTICAST_PHS; break; case TEH2_STREAM_COLORBEAM: - protocollen = sizeofcoord*6+sizeof(short)+sizeof(qbyte)*(3+2); + protocollen = writedest->prim.coordsize*6+sizeof(short)+sizeof(qbyte)*(3+2); multicastpos = 8; multicasttype=MULTICAST_PHS; break; case TEDP_FLAMEJET: //TE_FLAMEJET - protocollen = sizeofcoord*6 +sizeof(qbyte)*3; + protocollen = writedest->prim.coordsize*6 +sizeof(qbyte)*3; multicastpos = 2; multicasttype=MULTICAST_PVS; break; case TEDP_TEI_G3: - protocollen = sizeofcoord*9+sizeof(qbyte)*2; + protocollen = writedest->prim.coordsize*9+sizeof(qbyte)*2; multicastpos = 2; multicasttype=MULTICAST_PHS; break; case TEDP_SMOKE: - protocollen = sizeofcoord*6+sizeof(qbyte)*3; + protocollen = writedest->prim.coordsize*6+sizeof(qbyte)*3; multicastpos = 2; multicasttype=MULTICAST_PHS; break; case TEDP_TEI_BIGEXPLOSION: - protocollen = sizeofcoord*3+sizeof(qbyte)*2; + protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; multicastpos = 2; multicasttype=MULTICAST_PHS; break; case TEDP_TEI_PLASMAHIT: - protocollen = sizeofcoord*6+sizeof(qbyte)*3; + protocollen = writedest->prim.coordsize*6+sizeof(qbyte)*3; multicastpos = 2; multicasttype=MULTICAST_PHS; break; @@ -647,7 +1205,7 @@ void NPP_NQWriteCoord(int dest, float in) //replacement write func (nq to qw) MSG_WriteCoord (NQWriteDest(dest), in); #endif - if (sizeofcoord==4) + if (writedest->prim.coordsize==4) { dataf = LittleFloat(dataf); NPP_AddData(&dataf, sizeof(float)); @@ -933,7 +1491,7 @@ void NPP_QWFlush(void) NPP_AddData(&svc, sizeof(qbyte)); for (i = 0; i < 3; i++) { - if (sizeofcoord == 4) + if (writedest->prim.coordsize == 4) NPP_AddData(&org[i], sizeof(float)); else { @@ -991,12 +1549,12 @@ void NPP_QWFlush(void) vec3_t org; coorddata cd; - memcpy(&cd, &buffer[multicastpos+sizeofcoord*0], sizeofcoord); - org[0] = MSG_FromCoord(cd, sizeofcoord); - memcpy(&cd, &buffer[multicastpos+sizeofcoord*1], sizeofcoord); - org[1] = MSG_FromCoord(cd, sizeofcoord); - memcpy(&cd, &buffer[multicastpos+sizeofcoord*2], sizeofcoord); - org[2] = MSG_FromCoord(cd, sizeofcoord); + memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*0], writedest->prim.coordsize); + org[0] = MSG_FromCoord(cd, writedest->prim.coordsize); + memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*1], writedest->prim.coordsize); + org[1] = MSG_FromCoord(cd, writedest->prim.coordsize); + memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*2], writedest->prim.coordsize); + org[2] = MSG_FromCoord(cd, writedest->prim.coordsize); qwsize = sv.multicast.cursize; sv.multicast.cursize = 0; @@ -1167,13 +1725,13 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_LIGHTNING3: multicastpos=4; multicasttype=MULTICAST_PHS; - protocollen = sizeofcoord*6+sizeof(short)+sizeof(qbyte)*2; + protocollen = writedest->prim.coordsize*6+sizeof(short)+sizeof(qbyte)*2; break; case TEQW_BLOOD: //needs to be converted to a particle case TE_GUNSHOT: //needs qbyte 2 removed multicastpos=3; multicasttype=MULTICAST_PVS; - protocollen = sizeofcoord*3+sizeof(qbyte)*3; + protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*3; break; case TEQW_LIGHTNINGBLOOD: case TE_EXPLOSION: @@ -1181,7 +1739,7 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_SUPERSPIKE: multicastpos=2; multicasttype=MULTICAST_PHS_R; - protocollen = sizeofcoord*3+sizeof(qbyte)*2; + protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; break; case TE_TAREXPLOSION: case TE_WIZSPIKE: @@ -1190,12 +1748,12 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_TELEPORT: multicastpos=2; multicasttype=MULTICAST_PVS; - protocollen = sizeofcoord*3+sizeof(qbyte)*2; + protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; break; case TE_RAILTRAIL: multicastpos=1; multicasttype=MULTICAST_PVS; - protocollen = sizeofcoord*3+sizeof(qbyte)*1; + protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*1; break; default: protocollen = sizeof(buffer); @@ -1260,7 +1818,7 @@ void NPP_QWWriteLong(int dest, long data) //replacement write func (nq to qw) } void NPP_QWWriteAngle(int dest, float in) //replacement write func (nq to qw) { - if (sizeofangle==1) + if (writedest->prim.anglesize==1) { char data = (int)(in*256/360) & 255; NPP_QWWriteChar(dest, data); @@ -1273,7 +1831,7 @@ void NPP_QWWriteAngle(int dest, float in) //replacement write func (nq to qw) } void NPP_QWWriteCoord(int dest, float in) //replacement write func (nq to qw) { - if (sizeofcoord==4) + if (writedest->prim.coordsize==4) { NPP_QWWriteFloat(dest, in); } @@ -2318,3 +2876,4 @@ void NPP_Flush(void) #endif } #endif +#endif diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 0a438cd0f..ad35283b9 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -62,7 +62,7 @@ cvar_t pr_maxedicts = SCVARF("pr_maxedicts", "2048", CVAR_LATCH); cvar_t pr_no_playerphysics = SCVARF("pr_no_playerphysics", "0", CVAR_LATCH); -cvar_t progs = SCVARF("progs", "", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER); +cvar_t progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER); cvar_t qc_nonetaccess = SCVAR("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 pr_overridebuiltins = SCVAR("pr_overridebuiltins", "1"); @@ -764,7 +764,7 @@ progsnum_t AddProgs(char *name) } } } - + sv.world.usesolidcorpse = (progstype != PROG_H2); if (num != -1) { PR_LoadGlabalStruct(); @@ -1725,7 +1725,55 @@ char *Translate(char *message); */ +static void SV_Effect(vec3_t org, int mdlidx, int startframe, int endframe, int framerate) +{ + if (startframe>255 || mdlidx>255) + { + MSG_WriteByte (&sv.multicast, svcfte_effect2); + MSG_WriteCoord (&sv.multicast, org[0]); + MSG_WriteCoord (&sv.multicast, org[1]); + MSG_WriteCoord (&sv.multicast, org[2]); + MSG_WriteShort (&sv.multicast, mdlidx); + MSG_WriteShort (&sv.multicast, startframe); + MSG_WriteByte (&sv.multicast, endframe); + MSG_WriteByte (&sv.multicast, framerate); +#ifdef NQPROT + MSG_WriteByte (&sv.nqmulticast, svcnq_effect2); + MSG_WriteCoord (&sv.nqmulticast, org[0]); + MSG_WriteCoord (&sv.nqmulticast, org[1]); + MSG_WriteCoord (&sv.nqmulticast, org[2]); + MSG_WriteShort (&sv.nqmulticast, mdlidx); + MSG_WriteShort (&sv.nqmulticast, startframe); + MSG_WriteByte (&sv.nqmulticast, endframe); + MSG_WriteByte (&sv.nqmulticast, framerate); +#endif + } + else + { + MSG_WriteByte (&sv.multicast, svcfte_effect); + MSG_WriteCoord (&sv.multicast, org[0]); + MSG_WriteCoord (&sv.multicast, org[1]); + MSG_WriteCoord (&sv.multicast, org[2]); + MSG_WriteByte (&sv.multicast, mdlidx); + MSG_WriteByte (&sv.multicast, startframe); + MSG_WriteByte (&sv.multicast, endframe); + MSG_WriteByte (&sv.multicast, framerate); + +#ifdef NQPROT + MSG_WriteByte (&sv.nqmulticast, svcnq_effect); + MSG_WriteCoord (&sv.nqmulticast, org[0]); + MSG_WriteCoord (&sv.nqmulticast, org[1]); + MSG_WriteCoord (&sv.nqmulticast, org[2]); + MSG_WriteByte (&sv.nqmulticast, mdlidx); + MSG_WriteByte (&sv.nqmulticast, startframe); + MSG_WriteByte (&sv.nqmulticast, endframe); + MSG_WriteByte (&sv.nqmulticast, framerate); +#endif + } + + SV_Multicast(org, MULTICAST_PVS); +} @@ -1792,11 +1840,21 @@ static void PF_objerror (progfuncs_t *prinst, struct globalvars_s *pr_globals) (*prinst->pr_trace) = 2; else { - ED_Free (prinst, ed); - - prinst->AbortStack(prinst); - - PR_BIError (prinst, "Program error: %s", s); + Con_Printf("Program error: %s\n", s); + if (developer.value) + { + struct globalvars_s *pr_globals = PR_globals(prinst, PR_CURRENT); + *prinst->pr_trace = 1; + G_INT(OFS_RETURN)=0; //just in case it was a float and should be an ent... + G_INT(OFS_RETURN+1)=0; + G_INT(OFS_RETURN+2)=0; + } + else + { + ED_Free (prinst, ed); + PR_StackTrace(prinst); + PR_AbortStack(prinst); + } if (sv.time > 10) Cbuf_AddText("restart\n", RESTRICT_LOCAL); @@ -2691,7 +2749,7 @@ void PF_svtraceline (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent->xv->hull = savedhull; if (trace.startsolid) - if (!sv_gameplayfix_honest_tracelines.value) + if (!sv_gameplayfix_honest_tracelines.ival) trace.fraction = 1; pr_global_struct->trace_allsolid = trace.allsolid; @@ -2734,7 +2792,7 @@ static void PF_traceboxh2 (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent->xv->hull = savedhull; if (trace.startsolid) - if (!sv_gameplayfix_honest_tracelines.value) + if (!sv_gameplayfix_honest_tracelines.ival) trace.fraction = 1; pr_global_struct->trace_allsolid = trace.allsolid; @@ -2774,7 +2832,7 @@ static void PF_traceboxdp (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent->xv->hull = savedhull; if (trace.startsolid) - if (!sv_gameplayfix_honest_tracelines.value) + if (!sv_gameplayfix_honest_tracelines.ival) trace.fraction = 1; pr_global_struct->trace_allsolid = trace.allsolid; @@ -4645,59 +4703,42 @@ int SV_ModelIndex (char *name); void PF_makestatic (progfuncs_t *prinst, struct globalvars_s *pr_globals) { edict_t *ent; - int mdlindex, i; + int mdlindex; entity_state_t *state; ent = G_EDICT(prinst, OFS_PARM0); - SV_FlushSignon (); - mdlindex = SV_ModelIndex(PR_GetString(prinst, ent->v->model)); - if (ent->xv->drawflags || ent->xv->alpha || mdlindex > 255 || ent->v->frame > 255 || ent->xv->scale || ent->xv->abslight) + if (sv.num_static_entities == sv_max_staticentities) { - if (sv.numextrastatics==sizeof(sv.extendedstatics)/sizeof(sv.extendedstatics[0])) - return; //fail the whole makestatic thing. - - state = &sv.extendedstatics[sv.numextrastatics++]; - memset(state, 0, sizeof(*state)); - state->number = sv.numextrastatics; - state->flags = 0; - VectorCopy (ent->v->origin, state->origin); - VectorCopy (ent->v->angles, state->angles); - state->modelindex = mdlindex;//ent->v->modelindex; - state->frame = ent->v->frame; - state->colormap = ent->v->colormap; - state->skinnum = ent->v->skin; - state->effects = ent->v->effects; - state->hexen2flags = ent->xv->drawflags; - state->abslight = (int)(ent->xv->abslight*255) & 255; - state->trans = ent->xv->alpha*255; - if (!ent->xv->alpha) - state->trans = 255; - state->fatness = ent->xv->fatness; - state->scale = ent->xv->scale*16.0; - if (!ent->xv->scale) - state->scale = 1*16; - - if (progstype != PROG_QW) //don't send extra nq effects to a qw client. - state->effects &= EF_BRIGHTLIGHT | EF_DIMLIGHT; + sv_max_staticentities += 16; + sv_staticentities = BZ_Realloc(sv_staticentities, sizeof(*sv_staticentities) * sv_max_staticentities); } - else - { - MSG_WriteByte (&sv.signon,svc_spawnstatic); - MSG_WriteByte (&sv.signon, mdlindex&255); + state = &sv_staticentities[sv.num_static_entities++]; + memset(state, 0, sizeof(*state)); + state->number = sv.num_static_entities; + state->flags = 0; + VectorCopy (ent->v->origin, state->origin); + VectorCopy (ent->v->angles, state->angles); + state->modelindex = mdlindex;//ent->v->modelindex; + state->frame = ent->v->frame; + state->colormap = ent->v->colormap; + state->skinnum = ent->v->skin; + state->effects = ent->v->effects; + state->hexen2flags = ent->xv->drawflags; + state->abslight = (int)(ent->xv->abslight*255) & 255; + state->trans = ent->xv->alpha*255; + if (!ent->xv->alpha) + state->trans = 255; + state->fatness = ent->xv->fatness; + state->scale = ent->xv->scale*16.0; + if (!ent->xv->scale) + state->scale = 1*16; - MSG_WriteByte (&sv.signon, ent->v->frame); - MSG_WriteByte (&sv.signon, (int)ent->v->colormap); - MSG_WriteByte (&sv.signon, (int)ent->v->skin); - for (i=0 ; i<3 ; i++) - { - MSG_WriteCoord(&sv.signon, ent->v->origin[i]); - MSG_WriteAngle(&sv.signon, ent->v->angles[i]); - } - } + if (progstype != PROG_QW) //don't send extra nq effects to a qw client. + state->effects &= EF_BRIGHTLIGHT | EF_DIMLIGHT; // throw the entity away now ED_Free (svprogfuncs, ent); @@ -7096,7 +7137,91 @@ void PF_h2matchAngleToSlope(progfuncs_t *prinst, struct globalvars_s *pr_globals void PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - Con_DPrintf("Start effect %i\n", (int)G_FLOAT(OFS_PARM0)); + switch((int)G_FLOAT(OFS_PARM0)) + { + case 4: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/whtsmk1.spr"), 0, 5, 20); + break; + case 6: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/spark.spr"), 0, 10, 20); + break; + case 7: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fcircle.spr"), 0, 6, 20); + break; + case 9: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/sm_white.spr"), 0, 3, 20); + break; + case 11: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/yr_flash.spr"), 0, 21, 20); + break; + case 13: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/bluflash.spr"), 0, 5, 20); + break; + case 14: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/redspt.spr"), 0, 5, 20); + break; + case 15: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/sm_expld.spr"), 0, 12, 20); + break; + case 16: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/bg_expld.spr"), 0, 12, 20); + break; + case 17: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fl_expld.spr"), 0, 20, 20); + break; + case 24: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/rspark.spr"), 0, 10, 20); + break; + case 25: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/gspark.spr"), 0, 10, 20); + break; + case 26: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/telesmk1.spr"), 0, 4, 20); + break; + case 28: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/icehit.spr"), 0, 6, 20); + break; + case 33: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/gen_expl.spr"), 0, 14, 20); + break; + case 34: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/mm_explod.spr"), 0, 50, 20); + break; + case 42: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/flamestr.spr"), 0, 12, 20); + break; + case 45: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/xplsn_1.spr"), 0, 7, 20); + break; + case 47: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/axplsn_2.spr"), 0, 14, 20); + break; + case 48: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal1.spr"), 0, 18, 20); + break; + case 49: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal5.spr"), 0, 30, 20); + break; + case 50: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal4.spr"), 0, 29, 20); + break; + case 56: + SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/pow.spr"), 0, 6, 20); + break; + case 40: +// SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/boneshot.mdl"), 0, 50, 20); +// break; + + case 2: + case 55: + Con_DPrintf("Start unsupported effect %i\n", (int)G_FLOAT(OFS_PARM0)); + break; + + + default: + Con_Printf("Start effect %i\n", (int)G_FLOAT(OFS_PARM0)); + break; + } } void PF_h2endeffect(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -7112,6 +7237,10 @@ void PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *pr_globals) { } +void PF_h2updatesoundpos(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} + void PF_h2getstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *s = T_GetString(G_FLOAT(OFS_PARM0)-1); @@ -7916,52 +8045,7 @@ static void PF_effect(progfuncs_t *prinst, struct globalvars_s *pr_globals) float framerate = G_FLOAT(OFS_PARM4); int index = SV_ModelIndex(name); - if (startframe>255 || index>255) - { - MSG_WriteByte (&sv.multicast, svcfte_effect2); - MSG_WriteCoord (&sv.multicast, org[0]); - MSG_WriteCoord (&sv.multicast, org[1]); - MSG_WriteCoord (&sv.multicast, org[2]); - MSG_WriteShort (&sv.multicast, index); - MSG_WriteShort (&sv.multicast, startframe); - MSG_WriteByte (&sv.multicast, endframe); - MSG_WriteByte (&sv.multicast, framerate); - -#ifdef NQPROT - MSG_WriteByte (&sv.nqmulticast, svcnq_effect2); - MSG_WriteCoord (&sv.nqmulticast, org[0]); - MSG_WriteCoord (&sv.nqmulticast, org[1]); - MSG_WriteCoord (&sv.nqmulticast, org[2]); - MSG_WriteShort (&sv.nqmulticast, index); - MSG_WriteShort (&sv.nqmulticast, startframe); - MSG_WriteByte (&sv.nqmulticast, endframe); - MSG_WriteByte (&sv.nqmulticast, framerate); -#endif - } - else - { - MSG_WriteByte (&sv.multicast, svcfte_effect); - MSG_WriteCoord (&sv.multicast, org[0]); - MSG_WriteCoord (&sv.multicast, org[1]); - MSG_WriteCoord (&sv.multicast, org[2]); - MSG_WriteByte (&sv.multicast, index); - MSG_WriteByte (&sv.multicast, startframe); - MSG_WriteByte (&sv.multicast, endframe); - MSG_WriteByte (&sv.multicast, framerate); - -#ifdef NQPROT - MSG_WriteByte (&sv.nqmulticast, svcnq_effect); - MSG_WriteCoord (&sv.nqmulticast, org[0]); - MSG_WriteCoord (&sv.nqmulticast, org[1]); - MSG_WriteCoord (&sv.nqmulticast, org[2]); - MSG_WriteByte (&sv.nqmulticast, index); - MSG_WriteByte (&sv.nqmulticast, startframe); - MSG_WriteByte (&sv.nqmulticast, endframe); - MSG_WriteByte (&sv.nqmulticast, framerate); -#endif - } - - SV_Multicast(org, MULTICAST_PVS); + SV_Effect(org, index, startframe, endframe, framerate); } //DP_TE_PLASMABURN @@ -8475,7 +8559,12 @@ void PF_sv_gettaginfo(progfuncs_t *prinst, struct globalvars_s *pr_globals) return; } -#pragma message("This function doesn't honour attachments") + if (ent->xv->tag_entity) + { + #pragma message("PF_sv_gettaginfo: This function doesn't honour attachments") + Con_Printf("PF_sv_gettaginfo doesn't support attachments\n"); + } + EdictToTransform(ent, transent); R_ConcatTransforms((void*)transent, (void*)transtag, (void*)result); @@ -9194,6 +9283,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"precache_sound4", PF_precache_sound, 0, 0, 101, 0}, {"precache_model4", PF_precache_model, 0, 0, 102, 0}, {"precache_file4", PF_precache_file, 0, 0, 103, 0}, + {"dowhiteflash", PF_Fixme, 0, 0, 104, 0}, + {"updatesoundpos", PF_h2updatesoundpos,0, 0, 105, 0}, {"stopsound", PF_h2StopSound, 0, 0, 106, 0}, {"precache_model4", PF_precache_model, 0, 0, 116, 0},//please don't use... diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 60e4956e1..0c25f37ef 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -458,7 +458,7 @@ static eval_t *Q1QVMPF_GetEdictFieldValue(progfuncs_t *pf, edict_t *e, char *fie { if (!strcmp(fieldname, "message")) { - return (eval_t*)&e->v->message; + return (eval_t*)&e->v->_message; } return NULL; } @@ -1452,6 +1452,7 @@ qboolean PR_LoadQ1QVM(void) sv.world.progs = &q1qvmprogfuncs; sv.world.edicts = (wedict_t*)EDICT_NUM(svprogfuncs, 0); + sv.world.usesolidcorpse = true; return true; } diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index c9ce1809d..c2ec14a86 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -181,7 +181,7 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldentity(dmg_inflictor,_dmg_inflictor,_dmg_inflictor);\ comfieldentity(owner,owner,owner);\ comfieldvector(movedir,movedir,movedir);\ - comfieldstring(message,_message,_message); /*not used directly, hexen2 uses floats, so we go via qclib for message*/\ + comfieldstring(_message,_message,_message); /*not used directly, hexen2 uses floats, so we go via qclib for message*/\ comfieldfloat(sounds,_sounds,_sounds);\ comfieldstring(_noise,_noise,_noise);\ comfieldstring(_noise1,_noise1,_noise1);\ diff --git a/engine/server/server.h b/engine/server/server.h index 48100577d..37d73c0e4 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -103,6 +103,9 @@ typedef struct char fatness; } mvdentity_state_t; +extern entity_state_t *sv_staticentities; +extern int sv_max_staticentities; + typedef struct { qboolean active; // false when server is going down @@ -160,7 +163,7 @@ typedef struct // the multicast buffer is used to send a message to a set of clients sizebuf_t multicast; - qbyte multicast_buf[MAX_NQMSGLEN]; + qbyte multicast_buf[MAX_QWMSGLEN]; #ifdef NQPROT sizebuf_t nqdatagram; @@ -264,8 +267,7 @@ typedef struct #endif //==================================================== - entity_state_t extendedstatics[MAX_STATIC_ENTITIES]; - int numextrastatics; + int num_static_entities; // movevars_t demomovevars; //FIXME:! //end this lot... (demo playback) @@ -499,6 +501,7 @@ typedef struct client_s unsigned long fteprotocolextensions2; #endif unsigned long zquake_extensions; + unsigned int max_net_ents; enum { SCP_BAD, //don't send (a bot) @@ -756,6 +759,7 @@ typedef struct unsigned long fteprotocolextensions; unsigned long fteprotocolextensions2; #endif + struct netprim_s netprim; qboolean demoplayback; qboolean demorecording; @@ -892,6 +896,7 @@ extern netadr_t master_adr[MAX_MASTERS]; // address of the master server extern cvar_t spawn; extern cvar_t teamplay; extern cvar_t deathmatch; +extern cvar_t coop; extern cvar_t fraglimit; extern cvar_t timelimit; @@ -971,6 +976,7 @@ void SV_BuildClientFrame (client_t *client); void SV_WriteFrameToClient (client_t *client, sizebuf_t *msg); #ifdef Q2SERVER void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity); +void SVQ2_BuildBaselines(void); #endif //q3 stuff diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 014e503c1..318bed13b 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -437,7 +437,7 @@ void SV_Map_f (void) nextserver = 0; #ifndef SERVERONLY - if (!Renderer_Started()) + if (!Renderer_Started() && !isDedicated) { Cbuf_AddText(va("wait;map %s\n", Cmd_Args()), Cmd_ExecLevel); return; @@ -1374,6 +1374,7 @@ void SV_Status_f (void) char adr[MAX_ADR_SIZE]; int columns = 80; + extern cvar_t sv_listen_qw, sv_listen_nq, sv_listen_dp, sv_listen_q3; if (sv_redirected != RD_OBLIVION && (sv_redirected != RD_NONE #ifndef SERVERONLY @@ -1414,6 +1415,7 @@ void SV_Status_f (void) if (sv.csqcdebug) Con_Printf("csqc debug : true\n"); Con_Printf("public : %s\n", sv_public.value?"yes":"no"); + Con_Printf("client types :%s%s%s%s\n", sv_listen_qw.ival?" QW":"", sv_listen_nq.ival?" NQ":"", sv_listen_dp.ival?" DP":"", sv_listen_q3.ival?" Q3":""); // min fps lat drp if (columns < 80) diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 00428256c..ed4da1663 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -275,6 +275,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) csqcmsgbuffer.data = messagebuffer; csqcmsgbuffer.maxsize = sizeof(messagebuffer); csqcmsgbuffer.packing = msg->packing; + csqcmsgbuffer.prim = msg->prim; for (en = 0; en < csqcnuments; en++) { @@ -438,12 +439,12 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb // send an update bits = 0; - if (sizeofcoord == 2) + if (msg->prim.coordsize == 2) { for (i=0 ; i<3 ; i++) { - coordd[i] = MSG_ToCoord(to->origin[i], sizeofcoord); - if (MSG_ToCoord(from->origin[i], sizeofcoord).b4 != coordd[i].b4) + coordd[i] = MSG_ToCoord(to->origin[i], msg->prim.coordsize); + if (MSG_ToCoord(from->origin[i], msg->prim.coordsize).b4 != coordd[i].b4) bits |= U_ORIGIN1<origin[i] = from->origin[i]; @@ -453,26 +454,26 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb { for (i=0 ; i<3 ; i++) { - coordd[i] = MSG_ToCoord(to->origin[i], sizeofcoord); + coordd[i] = MSG_ToCoord(to->origin[i], msg->prim.coordsize); if (to->origin[i] != from->origin[i]) bits |= U_ORIGIN1<angles[0], sizeofangle); - if (MSG_ToAngle(from->angles[0], sizeofcoord).b4 != angled[0].b4) + angled[0] = MSG_ToAngle(to->angles[0], msg->prim.anglesize); + if (MSG_ToAngle(from->angles[0], msg->prim.anglesize).b4 != angled[0].b4) bits |= U_ANGLE1; else to->angles[0] = from->angles[0]; - angled[1] = MSG_ToAngle(to->angles[1], sizeofangle); - if (MSG_ToAngle(from->angles[1], sizeofcoord).b4 != angled[1].b4) + angled[1] = MSG_ToAngle(to->angles[1], msg->prim.anglesize); + if (MSG_ToAngle(from->angles[1], msg->prim.anglesize).b4 != angled[1].b4) bits |= U_ANGLE2; else to->angles[1] = from->angles[1]; - angled[2] = MSG_ToAngle(to->angles[2], sizeofangle); - if (MSG_ToAngle(from->angles[2], sizeofcoord).b4 != angled[2].b4) + angled[2] = MSG_ToAngle(to->angles[2], msg->prim.anglesize); + if (MSG_ToAngle(from->angles[2], msg->prim.anglesize).b4 != angled[2].b4) bits |= U_ANGLE3; else to->angles[2] = from->angles[2]; @@ -610,17 +611,17 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb if (bits & U_EFFECTS) MSG_WriteByte (msg, to->effects&0x00ff); if (bits & U_ORIGIN1) - SZ_Write(msg, &coordd[0], sizeofcoord); + SZ_Write(msg, &coordd[0], msg->prim.coordsize); if (bits & U_ANGLE1) - SZ_Write(msg, &angled[0], sizeofangle); + SZ_Write(msg, &angled[0], msg->prim.anglesize); if (bits & U_ORIGIN2) - SZ_Write(msg, &coordd[1], sizeofcoord); + SZ_Write(msg, &coordd[1], msg->prim.coordsize); if (bits & U_ANGLE2) - SZ_Write(msg, &angled[1], sizeofangle); + SZ_Write(msg, &angled[1], msg->prim.anglesize); if (bits & U_ORIGIN3) - SZ_Write(msg, &coordd[2], sizeofcoord); + SZ_Write(msg, &coordd[2], msg->prim.coordsize); if (bits & U_ANGLE3) - SZ_Write(msg, &angled[2], sizeofangle); + SZ_Write(msg, &angled[2], msg->prim.anglesize); #ifdef U_SCALE if (evenmorebits & U_SCALE) @@ -1104,7 +1105,7 @@ int SV_HullNumForPlayer(int h2hull, float *mins, float *maxs) } if (h2hull) - return h2hull-1; + return h2hull-1 | (mins[2]?0:128); hullnum = 0; @@ -1661,7 +1662,7 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * #endif for (j=0,cl=svs.clients ; jstate != cs_spawned || (cl->state == cs_free && cl->name[0])) //this includes bots, and nq bots + if (cl->state != cs_spawned && !(cl->state == cs_free && cl->name[0])) //this includes bots, and nq bots continue; isbot = (!cl->name[0] || cl->protocol == SCP_BAD); @@ -1841,45 +1842,6 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * void SVNQ_EmitEntityState(sizebuf_t *msg, entity_state_t *ent) { entity_state_t *baseline = &EDICT_NUM(svprogfuncs, ent->number)->baseline; -#define NQU_MOREBITS (1<<0) -#define NQU_ORIGIN1 (1<<1) -#define NQU_ORIGIN2 (1<<2) -#define NQU_ORIGIN3 (1<<3) -#define NQU_ANGLE2 (1<<4) -#define NQU_STEP (1<<5) // don't interpolate movement -#define NQU_FRAME (1<<6) -#define NQU_SIGNAL (1<<7) // just differentiates from other updates - -// svc_update can pass all of the fast update bits, plus more -#define NQU_ANGLE1 (1<<8) -#define NQU_ANGLE3 (1<<9) -#define NQU_MODEL (1<<10) -#define NQU_COLORMAP (1<<11) -#define NQU_SKIN (1<<12) -#define NQU_EFFECTS (1<<13) -#define NQU_LONGENTITY (1<<14) - -// LordHavoc's: protocol extension -#define DPU_EXTEND1 (1<<15) -// LordHavoc: first extend byte -#define DPU_DELTA (1<<16) // no data, while this is set the entity is delta compressed (uses previous frame as a baseline, meaning only things that have changed from the previous frame are sent, except for the forced full update every half second) -#define DPU_ALPHA (1<<17) // 1 byte, 0.0-1.0 maps to 0-255, not sent if exactly 1, and the entity is not sent if <=0 unless it has effects (model effects are checked as well) -#define DPU_SCALE (1<<18) // 1 byte, scale / 16 positive, not sent if 1.0 -#define DPU_EFFECTS2 (1<<19) // 1 byte, this is .effects & 0xFF00 (second byte) -#define DPU_GLOWSIZE (1<<20) // 1 byte, encoding is float/4.0, unsigned, not sent if 0 -#define DPU_GLOWCOLOR (1<<21) // 1 byte, palette index, default is 254 (white), this IS used for darklight (allowing colored darklight), however the particles from a darklight are always black, not sent if default value (even if glowsize or glowtrail is set) -// LordHavoc: colormod feature has been removed, because no one used it -#define DPU_COLORMOD (1<<22) // 1 byte, 3 bit red, 3 bit green, 2 bit blue, this lets you tint an object artifically, so you could make a red rocket, or a blue fiend... -#define DPU_EXTEND2 (1<<23) // another byte to follow -// LordHavoc: second extend byte -#define DPU_GLOWTRAIL (1<<24) // leaves a trail of particles (of color .glowcolor, or black if it is a negative glowsize) -#define DPU_VIEWMODEL (1<<25) // attachs the model to the view (origin and angles become relative to it), only shown to owner, a more powerful alternative to .weaponmodel and such -#define DPU_FRAME2 (1<<26) // 1 byte, this is .frame & 0xFF00 (second byte) -#define DPU_MODEL2 (1<<27) // 1 byte, this is .modelindex & 0xFF00 (second byte) -#define DPU_EXTERIORMODEL (1<<28) // causes this model to not be drawn when using a first person view (third person will draw it, first person will not) -#define DPU_UNUSED29 (1<<29) // future expansion -#define DPU_UNUSED30 (1<<30) // future expansion -#define DPU_EXTEND3 (1<<31) // another byte to follow, future expansion int i, eff; float miss; @@ -1904,7 +1866,7 @@ int glowsize=0, glowcolor=0, colourmod=0; bits |= NQU_ANGLE3; if (ent->dpflags & RENDER_STEP) - bits |= NQU_STEP; // don't mess up the step animation + bits |= NQU_NOLERP; // don't mess up the step animation if (baseline->colormap != ent->colormap && ent->colormap>=0) bits |= NQU_COLORMAP; @@ -2446,6 +2408,23 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, continue; } + if (progstype != PROG_QW) + { +// if (progstype == PROG_H2) +// if (ent->v->effects == H2EF_NODRAW) +// continue; + if ((int)ent->v->effects & EF_MUZZLEFLASH) + { + if (needcleanup < e) + { + needcleanup = e; + MSG_WriteByte(&sv.multicast, svc_muzzleflash); + MSG_WriteShort(&sv.multicast, e); + SV_Multicast(ent->v->origin, MULTICAST_PVS); + } + } + } + if (ent->xv->viewmodelforclient) { if (ent->xv->viewmodelforclient != (clent?EDICT_TO_PROG(svprogfuncs, clent):0)) @@ -2463,23 +2442,6 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, continue; pvsflags = ent->xv->pvsflags; - if (progstype != PROG_QW) - { - // if (progstype == PROG_H2) - // if (ent->v->effects == H2EF_NODRAW) - // continue; - if ((int)ent->v->effects & EF_MUZZLEFLASH) - { - if (needcleanup < e) - { - needcleanup = e; - MSG_WriteByte(&sv.multicast, svc_muzzleflash); - MSG_WriteShort(&sv.multicast, e); - SV_Multicast(ent->v->origin, MULTICAST_PVS); - } - } - } - if (pvs && ent != clent) //self doesn't get a pvs test, to cover teleporters { if ((int)ent->v->effects & EF_NODEPTHTEST) @@ -2509,13 +2471,16 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, { int leafnum; unsigned char *mask; - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, host_client->edict->v->origin); - mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); - - leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, ent->v->origin)-1; - if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + if (sv.phs) { - continue; + leafnum = sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, host_client->edict->v->origin); + mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); + + leafnum = sv.world.worldmodel->funcs.LeafnumForPoint (sv.world.worldmodel, ent->v->origin)-1; + if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + { + continue; + } } } @@ -2569,20 +2534,8 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, //FIXME: add an option to drop clients... entity fog could be killed in this way. if (!ISDPCLIENT(client)) { - if (e >= 512) - { - if (!(client->fteprotocolextensions & PEXT_ENTITYDBL)) - { - continue; - } - else if (e >= 1024) - { - if (!(client->fteprotocolextensions & PEXT_ENTITYDBL2)) - continue; - else if (e >= 2048) - continue; - } - } + if (e >= client->max_net_ents) + continue; #ifdef PEXT_MODELDBL if (ent->v->modelindex >= 256 && !(client->fteprotocolextensions & PEXT_MODELDBL)) continue; @@ -2657,7 +2610,13 @@ qbyte *SV_Snapshot_SetupPVS(client_t *client, qbyte *pvs, unsigned int pvsbufsiz for (; client; client = client->controlled) { - VectorAdd (client->edict->v->origin, client->edict->v->view_ofs, org); + if (client->viewent) + { + edict_t *e = PROG_TO_EDICT(svprogfuncs, client->viewent); + VectorAdd (e->v->origin, client->edict->v->view_ofs, org); + } + else + VectorAdd (client->edict->v->origin, client->edict->v->view_ofs, org); sv.world.worldmodel->funcs.FatPVS(sv.world.worldmodel, org, pvs, pvsbufsize, leavepvs); leavepvs = true; diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 50707afd8..0a2188dfe 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -28,6 +28,9 @@ char *T_GetString(int num); server_static_t svs; // persistant server info server_t sv; // local server +entity_state_t *sv_staticentities; +int sv_max_staticentities; + char localmodels[MAX_MODELS][5]; // inline model names for precache char localinfo[MAX_LOCALINFO_STRING+1]; // local game info @@ -39,6 +42,7 @@ extern cvar_t sv_gamespeed; extern cvar_t sv_csqcdebug; extern cvar_t sv_csqc_progname; extern qboolean sv_allow_cheats; +extern cvar_t sv_calcphs; /* ================ @@ -107,6 +111,7 @@ void SV_FlushSignon (void) sv.signon.data = sv.signon_buffers[sv.num_signon_buffers]; sv.num_signon_buffers++; sv.signon.cursize = 0; + sv.signon.prim = svs.netprim; } #ifdef SERVER_DEMO_PLAYBACK void SV_FlushDemoSignon (void) @@ -471,6 +476,13 @@ void SV_CalcPHS (void) } } + if (!sv_calcphs.ival || (sv_calcphs.ival == 2 && (rowbytes*num >= 0x100000 || (!deathmatch.ival && !coop.ival)))) + { + Con_DPrintf("Skipping PHS\n"); + sv.phs = NULL; + return; + } + /*this routine takes an exponential amount of time, so cache it if its too big*/ if (rowbytes*num >= 0x100000) { @@ -665,8 +677,21 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us T_FreeStrings(); } + if (sv_bigcoords.value) + { + svs.netprim.coordsize = 4; + svs.netprim.anglesize = 2; + } + else + { + svs.netprim.coordsize = 2; + svs.netprim.anglesize = 1; + } + for (i = 0; i < MAX_CLIENTS; i++) { + svs.clients[i].datagram.prim = svs.netprim; + svs.clients[i].netchan.message.prim = svs.netprim; svs.clients[i].nextservertimeupdate = 0; if (!svs.clients[i].state) //bots with the net_preparse module. svs.clients[i].userinfo[0] = '\0'; //clear the userinfo to clear the name @@ -679,17 +704,6 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us svs.clients[i].csqcactive = false; } - if (sv_bigcoords.value) - { - sizeofcoord = 4; - sizeofangle = 2; - } - else - { - sizeofcoord = 2; - sizeofangle = 1; - } - VoteFlushAll(); #ifndef SERVERONLY cl.worldmodel = NULL; @@ -728,43 +742,54 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us sv.datagram.maxsize = sizeof(sv.datagram_buf); sv.datagram.data = sv.datagram_buf; sv.datagram.allowoverflow = true; - + sv.datagram.prim = svs.netprim; sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf); sv.reliable_datagram.data = sv.reliable_datagram_buf; + sv.reliable_datagram.prim = svs.netprim; sv.multicast.maxsize = sizeof(sv.multicast_buf); sv.multicast.data = sv.multicast_buf; + sv.multicast.prim = svs.netprim; #ifdef NQPROT sv.nqdatagram.maxsize = sizeof(sv.nqdatagram_buf); sv.nqdatagram.data = sv.nqdatagram_buf; sv.nqdatagram.allowoverflow = true; + sv.nqdatagram.prim = svs.netprim; sv.nqreliable_datagram.maxsize = sizeof(sv.nqreliable_datagram_buf); sv.nqreliable_datagram.data = sv.nqreliable_datagram_buf; + sv.nqreliable_datagram.prim = svs.netprim; sv.nqmulticast.maxsize = sizeof(sv.nqmulticast_buf); sv.nqmulticast.data = sv.nqmulticast_buf; + sv.nqmulticast.prim = svs.netprim; #endif +#ifdef Q2SERVER sv.q2datagram.maxsize = sizeof(sv.q2datagram_buf); sv.q2datagram.data = sv.q2datagram_buf; sv.q2datagram.allowoverflow = true; + sv.q2datagram.prim = svs.netprim; sv.q2reliable_datagram.maxsize = sizeof(sv.q2reliable_datagram_buf); sv.q2reliable_datagram.data = sv.q2reliable_datagram_buf; + sv.q2reliable_datagram.prim = svs.netprim; sv.q2multicast.maxsize = sizeof(sv.q2multicast_buf); sv.q2multicast.data = sv.q2multicast_buf; + sv.q2multicast.prim = svs.netprim; +#endif sv.master.maxsize = sizeof(sv.master_buf); sv.master.data = sv.master_buf; + sv.master.prim = msg_nullnetprim; sv.signon.maxsize = sizeof(sv.signon_buffers[0]); sv.signon.data = sv.signon_buffers[0]; + sv.signon.prim = svs.netprim; sv.num_signon_buffers = 1; - sv.numextrastatics = 0; strcpy (sv.name, server); #ifndef SERVERONLY @@ -1370,6 +1395,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us // SV_CreateBaseline (); if (svprogfuncs) SVNQ_CreateBaseline(); +#ifdef Q2SERVER + SVQ2_BuildBaselines(); +#endif sv.signon_buffer_size[sv.num_signon_buffers-1] = sv.signon.cursize; // all spawning is completed, any further precache statements diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index d89a3e777..6608d748d 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -142,6 +142,7 @@ cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "10000", cvar_t sv_minping = CVARF("sv_minping", "0", CVAR_SERVERINFO); cvar_t sv_bigcoords = CVARF("sv_bigcoords", "", CVAR_SERVERINFO); +cvar_t sv_calcphs = CVAR("sv_calcphs", "2"); cvar_t sv_cullplayers_trace = CVARF("sv_cullplayers_trace", "", CVAR_SERVERINFO); cvar_t sv_cullentities_trace = CVARF("sv_cullentities_trace", "", CVAR_SERVERINFO); @@ -1700,7 +1701,7 @@ client_t *SVC_DirectConnect(void) //it's a darkplaces client. s = Info_ValueForKey(userinfo[0], "protocols"); - if (sizeofcoord != 4) + if (svs.netprim.coordsize != 4) { //we allow nq with sv_listen_nq 0... //reason: dp is too similar for concerns about unsupported code, while the main reason why we disable nq is because of the lack of challenges //(and no, this isn't a way to bypass invalid challenges) @@ -1879,6 +1880,19 @@ client_t *SVC_DirectConnect(void) newcl->fteprotocolextensions2 = protextsupported2; newcl->protocol = protocol; + if (protocol == SCP_QUAKEWORLD) //readd? + { + newcl->max_net_ents = 512; + if (newcl->fteprotocolextensions & PEXT_ENTITYDBL) + newcl->max_net_ents += 512; + if (newcl->fteprotocolextensions & PEXT_ENTITYDBL2) + newcl->max_net_ents += 1024; + } + else if (ISDPCLIENT(newcl)) + newcl->max_net_ents = 32767; + else + newcl->max_net_ents = 600; + if (sv.msgfromdemo) newcl->wasrecorded = true; @@ -2174,7 +2188,7 @@ client_t *SVC_DirectConnect(void) } newcl->zquake_extensions &= SUPPORTED_Z_EXTENSIONS; - Netchan_Setup (NS_SERVER, &newcl->netchan , adr, qport); + Netchan_Setup (NS_SERVER, &newcl->netchan, adr, qport); if (huffcrc) newcl->netchan.compress = true; @@ -2195,6 +2209,10 @@ client_t *SVC_DirectConnect(void) newcl->datagram.data = newcl->datagram_buf; newcl->datagram.maxsize = sizeof(newcl->datagram_buf); + newcl->netchan.netprim = svs.netprim; + newcl->datagram.prim = svs.netprim; + newcl->netchan.message.prim = svs.netprim; + // spectator mode can ONLY be set at join time newcl->spectator = spectator; @@ -2632,7 +2650,7 @@ qboolean SV_ConnectionlessPacket (void) char *c; char adr[MAX_ADR_SIZE]; - MSG_BeginReading (); + MSG_BeginReading (svs.netprim); if (net_message.cursize >= MAX_QWMSGLEN) //add a null term in message space { @@ -2676,7 +2694,7 @@ qboolean SV_ConnectionlessPacket (void) { //if name isn't in the string, assume they're q3 //this isn't quite true though, hence the listen check. but users shouldn't be connecting with an empty name anyway. more fool them. Huff_DecryptPacket(&net_message, 12); - MSG_BeginReading(); + MSG_BeginReading(svs.netprim); MSG_ReadLong(); s = MSG_ReadStringLine(); Cmd_TokenizeString(s, false, false); @@ -2734,7 +2752,7 @@ void SVNQ_ConnectionlessPacket(void) if (sv_bigcoords.value) return; //no, start using dp7 instead. - MSG_BeginReading(); + MSG_BeginReading(svs.netprim); header = LongSwap(MSG_ReadLong()); if (!(header & NETFLAG_CTL)) return; //no idea what it is. @@ -2966,7 +2984,7 @@ qboolean SV_ReadPackets (void) // read the qport out of the message so we can fix up // stupid address translating routers - MSG_BeginReading (); + MSG_BeginReading (svs.netprim); MSG_ReadLong (); // sequence number MSG_ReadLong (); // sequence number qport = MSG_ReadShort () & 0xffff; @@ -3653,7 +3671,7 @@ void SV_InitLocal (void) Cvar_Register (&secure, cvargroup_serverpermissions); Cvar_Register (&sv_highchars, cvargroup_servercontrol); - + Cvar_Register (&sv_calcphs, cvargroup_servercontrol); Cvar_Register (&sv_phs, cvargroup_servercontrol); Cvar_Register (&sv_cullplayers_trace, cvargroup_servercontrol); Cvar_Register (&sv_cullentities_trace, cvargroup_servercontrol); diff --git a/engine/server/sv_master.c b/engine/server/sv_master.c index 7b2907d52..d06d0a956 100644 --- a/engine/server/sv_master.c +++ b/engine/server/sv_master.c @@ -162,10 +162,10 @@ void SVM_Think(int port) SVM_RemoveOldServers(); - MSG_BeginReading(); + MSG_BeginReading(msg_nullnetprim); if (MSG_ReadLong() != -1 || msg_badread) { //go back to start... - MSG_BeginReading(); + MSG_BeginReading(msg_nullnetprim); } s = MSG_ReadStringLine(); s = COM_Parse(s); diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 1192baae6..1c28babe5 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -1645,7 +1645,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest) gamedir = "qw"; MSG_WriteByte (&buf, svc_serverdata); - if (sizeofcoord == 4) //sorry. + if (svs.netprim.coordsize == 4) //sorry. { MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE); MSG_WriteLong (&buf, PEXT_FLOATCOORDS); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index bf4483b63..683377c2e 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -22,6 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "qwsvdef.h" #ifndef CLIENTONLY +#include "pr_common.h" + #pragma message("fixme, fix this up before adding to csqc") extern nqglobalvars_t realpr_nqglobal_struct; @@ -928,6 +930,7 @@ if (l > 1.0/64) { // Con_Printf ("**** snap: %f\n", Length (l)); VectorCopy (oldorg, ent->v->origin); + VectorCopy (oldang, ent->v->angles); SV_Push (ent, move, amove); } @@ -1125,11 +1128,17 @@ static void SV_Physics_Toss (edict_t *ent) if (ent->v->movetype == MOVETYPE_BOUNCE) backoff = 1.5; else if (ent->v->movetype == MOVETYPE_BOUNCEMISSILE) - backoff = 2; + { +// if (progstype == PROG_H2 && ent->v->solid == SOLID_PHASEH2 && ((int)((wedict_t*)trace.ent)->v->flags & (FL_MONSTER|FL_CLIENT))) +// backoff = 0; +// else + backoff = 2; + } else backoff = 1; - ClipVelocity (ent->v->velocity, trace.plane.normal, ent->v->velocity, backoff); + if (backoff) + ClipVelocity (ent->v->velocity, trace.plane.normal, ent->v->velocity, backoff); // stop if on ground @@ -2092,7 +2101,7 @@ qboolean SV_Physics (void) break; if (host_frametime > sv_maxtic.value) { - if (--maxtics == 0) + if (maxtics-- <= 0) { //timewarp, as we're running too slowly sv.world.physicstime = sv.time; diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 5924ae143..8c2c0978d 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -633,7 +633,10 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int case MULTICAST_PHS_R: reliable = true; // intentional fallthrough case MULTICAST_PHS: - mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); + if (!sv.phs) /*broadcast if no pvs*/ + mask = sv.pvs; + else + mask = sv.phs + leafnum * 4*((sv.world.worldmodel->numleafs+31)>>5); break; case MULTICAST_PVS_R: @@ -1639,6 +1642,7 @@ qboolean SV_SendClientDatagram (client_t *client) msg.cursize = 0; msg.allowoverflow = true; msg.overflowed = false; + msg.prim = client->datagram.prim; if (sv.world.worldmodel && !client->controller) { diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 03ba4de25..b264701a9 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -236,7 +236,7 @@ void SV_New_f (void) SZ_Clear(&host_client->netchan.message); } */ - if (sizeofcoord > 2 && !(host_client->fteprotocolextensions & PEXT_FLOATCOORDS)) + if (svs.netprim.coordsize > 2 && !(host_client->fteprotocolextensions & PEXT_FLOATCOORDS)) { SV_ClientPrintf(host_client, 2, "\n\n\n\nSorry, but your client does not appear to support FTE's bigcoords\nFTE users will need to set cl_nopext to 0 and then reconnect, or to upgrade\n"); Con_Printf("%s does not support bigcoords\n", host_client->name); @@ -251,7 +251,7 @@ void SV_New_f (void) if (host_client->fteprotocolextensions)//let the client know { ClientReliableWrite_Long (host_client, PROTOCOL_VERSION_FTE); - if (sizeofcoord == 2) //we're not using float orgs on this level. + if (svs.netprim.coordsize == 2) //we're not using float orgs on this level. ClientReliableWrite_Long (host_client, host_client->fteprotocolextensions&~PEXT_FLOATCOORDS); else ClientReliableWrite_Long (host_client, host_client->fteprotocolextensions); @@ -962,7 +962,7 @@ void SV_Modellist_f (void) Q_strncpy(mname, sv.strings.vw_model_precache[i], sizeof(mname)); //strip .mdl extensions - if (!strcmp(COM_FileExtension(mname), ".mdl")) + if (!strcmp(COM_FileExtension(mname), "mdl")) COM_StripExtension(mname, mname, sizeof(mname)); //add it to the vweap command, taking care of any remaining spaces in names. @@ -1026,12 +1026,10 @@ void SV_Modellist_f (void) #endif { for (i = 1+n; - i < maxclientsupportedmodels && sv.strings.model_precache[i] && host_client->netchan.message.cursize < (MAX_QWMSGLEN/2); //make sure we don't send a 0 next... + i < maxclientsupportedmodels && sv.strings.model_precache[i] && (((i-1)&255)==0 || host_client->netchan.message.cursize < (MAX_QWMSGLEN/2)); //make sure we don't send a 0 next... i++) { MSG_WriteString (&host_client->netchan.message, sv.strings.model_precache[i]); - if (((n&255)==255) && n != i-1) - break; } n = i-1; @@ -1080,7 +1078,7 @@ void SV_PreSpawn_f (void) else #endif bufs = sv.num_signon_buffers; - statics = sv.numextrastatics; + statics = sv.num_static_entities; buf = atoi(Cmd_Argv(2)); if (buf >= bufs+statics+sv.world.num_edicts+255) @@ -1140,21 +1138,29 @@ void SV_PreSpawn_f (void) memset(&from, 0, sizeof(from)); while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) //static entities { - if (buf - bufs >= sv.numextrastatics) + if (buf - bufs >= sv.num_static_entities) break; - state = &sv.extendedstatics[buf - bufs]; + state = &sv_staticentities[buf - bufs]; + buf++; if (host_client->fteprotocolextensions & PEXT_SPAWNSTATIC2) { - MSG_WriteByte(&host_client->netchan.message, svc_spawnstatic2); - SV_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions); + /*if it uses some new feature, use the updated spawnstatic*/ + if (state->hexen2flags || state->trans || state->modelindex >= 256 || state->frame > 255 || state->scale || state->abslight) + { + MSG_WriteByte(&host_client->netchan.message, svc_spawnstatic2); + SV_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions); + continue; + } } - else if (state->modelindex < 256) + /*couldn't use protocol extensions? + use the fallback, unless the model is invalid as that's silly*/ + if (state->modelindex < 256) { MSG_WriteByte(&host_client->netchan.message, svc_spawnstatic); - MSG_WriteByte (&host_client->netchan.message, state->modelindex&255); + MSG_WriteByte (&host_client->netchan.message, state->modelindex); MSG_WriteByte (&host_client->netchan.message, state->frame); MSG_WriteByte (&host_client->netchan.message, (int)state->colormap); @@ -1164,15 +1170,15 @@ void SV_PreSpawn_f (void) MSG_WriteCoord(&host_client->netchan.message, state->origin[i]); MSG_WriteAngle(&host_client->netchan.message, state->angles[i]); } + continue; } - buf++; } while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) //baselines { - if (buf - bufs - sv.numextrastatics >= sv.world.num_edicts) + if (buf - bufs - sv.num_static_entities >= sv.world.num_edicts) break; - ent = EDICT_NUM(svprogfuncs, buf - bufs - sv.numextrastatics); + ent = EDICT_NUM(svprogfuncs, buf - bufs - sv.num_static_entities); state = &ent->baseline; if (!state->number || !state->modelindex) @@ -1185,7 +1191,7 @@ void SV_PreSpawn_f (void) { MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); - MSG_WriteShort (&host_client->netchan.message, buf - bufs - sv.numextrastatics); + MSG_WriteShort (&host_client->netchan.message, buf - bufs - sv.num_static_entities); MSG_WriteByte (&host_client->netchan.message, 0); @@ -1207,7 +1213,7 @@ void SV_PreSpawn_f (void) { MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); - MSG_WriteShort (&host_client->netchan.message, buf - bufs - sv.numextrastatics); + MSG_WriteShort (&host_client->netchan.message, buf - bufs - sv.num_static_entities); MSG_WriteByte (&host_client->netchan.message, state->modelindex); @@ -1225,7 +1231,7 @@ void SV_PreSpawn_f (void) } while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) { - i = buf - bufs - sv.numextrastatics - sv.world.num_edicts; + i = buf - bufs - sv.num_static_entities - sv.world.num_edicts; if (i >= 255) break; @@ -1264,7 +1270,7 @@ void SV_PreSpawn_f (void) } else if (buf >= bufs) { - buf = bufs+sv.numextrastatics+sv.world.num_edicts+255; + buf = bufs+sv.num_static_entities+sv.world.num_edicts+255; } else { @@ -1291,7 +1297,7 @@ void SV_PreSpawn_f (void) } } } - if (buf == bufs+sv.numextrastatics+sv.world.num_edicts+255) + if (buf == bufs+sv.num_static_entities+sv.world.num_edicts+255) { // all done prespawning MSG_WriteByte (&host_client->netchan.message, svc_stufftext); MSG_WriteString (&host_client->netchan.message, va("cmd spawn %i\n",svs.spawncount) ); @@ -3682,7 +3688,8 @@ void Cmd_Join_f (void) // FIXME, bump the client's userid? // call the progs to get default spawn parms for the new client - PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); + if (pr_nqglobal_struct->SetNewParms) + PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); for (i=0 ; iSetNewParms); + if (pr_nqglobal_struct->SetNewParms) + PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); for (i=0 ; iname); + SV_BroadcastPrintf (PRINT_HIGH, "warning: %s eyes or player model not verified\n", host_client->name); } @@ -4332,7 +4340,7 @@ void SVNQ_PreSpawn_f (void) return; } - for (e = 1; e < sv.world.num_edicts; e++) + for (e = 1; e < sv.world.num_edicts && e < host_client->max_net_ents; e++) { ent = EDICT_NUM(svprogfuncs, e); state = &ent->baseline; @@ -4361,7 +4369,7 @@ void SVNQ_PreSpawn_f (void) } else { - if (host_client->protocol != SCP_NETQUAKE && (state->modelindex > 255 || state->frame > 255)) + if (ISDPCLIENT(host_client) && (state->modelindex > 255 || state->frame > 255)) { MSG_WriteByte(&host_client->netchan.message, svcdp_spawnbaseline2); @@ -4900,6 +4908,8 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) double tmp_time; qboolean jumpable; char adr[MAX_ADR_SIZE]; + vec3_t new_vel; + vec3_t old_vel; // DMW copied this KK hack copied from QuakeForge anti-cheat // (also extra inside parm on all SV_RunCmds that follow) @@ -5098,7 +5108,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) if (progstype != PROG_QW) { #define FL_JUMPRELEASED 4096 - jumpable = (int)sv_player->v->flags & FL_JUMPRELEASED; + jumpable = ((int)sv_player->v->flags & FL_JUMPRELEASED) && ((int)sv_player->v->flags & FL_ONGROUND); pmove.waterjumptime = sv_player->v->teleport_time; if (pmove.waterjumptime > sv.time) @@ -5232,17 +5242,7 @@ if (sv_player->v->health > 0 && before && !after ) else sv_player->v->flags = (int)sv_player->v->flags & ~FL_ONGROUND; - for (i=0 ; i<3 ; i++) - sv_player->v->origin[i] = pmove.origin[i];// - (sv_player->v->mins[i] - player_mins[i]); - -#if 0 - // truncate velocity the same way the net protocol will - for (i=0 ; i<3 ; i++) - sv_player->v->velocity[i] = (int)pmove.velocity[i]; -#else - VectorCopy (pmove.velocity, sv_player->v->velocity); -#endif - + VectorCopy (pmove.origin, sv_player->v->origin); VectorCopy (pmove.angles, sv_player->v->v_angle); player_mins[0] = -16; @@ -5253,6 +5253,12 @@ if (sv_player->v->health > 0 && before && !after ) player_maxs[1] = 16; player_maxs[2] = 32; + VectorCopy(sv_player->v->velocity, old_vel); + VectorCopy(pmove.velocity, new_vel); + if (progstype == PROG_QW) + VectorCopy(new_vel, sv_player->v->velocity); + + if (!host_client->spectator) { // link into place and touch triggers @@ -5304,6 +5310,12 @@ if (sv_player->v->health > 0 && before && !after ) playertouch[n/8] |= 1 << (n%8); } } + + if (progstype != PROG_QW) + { + if (VectorCompare(sv_player->v->velocity, old_vel)) + VectorCopy(new_vel, sv_player->v->velocity); + } } /* diff --git a/engine/server/svq2_ents.c b/engine/server/svq2_ents.c index 8e9727a16..16e460a74 100644 --- a/engine/server/svq2_ents.c +++ b/engine/server/svq2_ents.c @@ -751,6 +751,25 @@ void SV_BuildClientFrame (client_t *client) } } +void SVQ2_BuildBaselines(void) +{ + unsigned int e; + q2edict_t *ent; + q2entity_state_t *base; + + if (!ge) + return; + + for (e=1 ; enum_edicts ; e++) + { + ent = Q2EDICT_NUM(e); + base = &ent->s; + + if (base->modelindex || base->sound || base->effects) + sv_baselines[e] = *base; + } +} + void SVQ2_Ents_Init(void) { extern cvar_t maxclients; diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 8016cdfc5..22bd3310c 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -3050,7 +3050,7 @@ void SVQ3_HandleClient(void) if (net_message.cursize<6) return; //urm. :/ - MSG_BeginReading(); + MSG_BeginReading(msg_nullnetprim); MSG_ReadBits(32); qport = (unsigned short)MSG_ReadBits(16); diff --git a/engine/server/world.c b/engine/server/world.c index a6d129923..958d96a99 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -1468,13 +1468,15 @@ static void World_ClipToEverything (world_t *w, moveclip_t *clip) if (clip->passedict) { - // don't clip corpse against character - if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE)) - continue; - // don't clip character against corpse - if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE) - continue; - + if (w->usesolidcorpse) + { + // don't clip corpse against character + if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE)) + continue; + // don't clip character against corpse + if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE) + continue; + } if (!((int)clip->passedict->xv->dimension_hit & (int)touch->xv->dimension_solid)) continue; } @@ -1620,13 +1622,15 @@ static void World_ClipToLinks (world_t *w, areanode_t *node, moveclip_t *clip) if (clip->passedict) { - // don't clip corpse against character - if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE)) - continue; - // don't clip character against corpse - if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE) - continue; - + if (w->usesolidcorpse) + { + // don't clip corpse against character + if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE)) + continue; + // don't clip character against corpse + if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE) + continue; + } if (!((int)clip->passedict->xv->dimension_hit & (int)touch->xv->dimension_solid)) continue; } @@ -1906,13 +1910,15 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e if (clip.passedict) { - // don't clip corpse against character - if (clip.passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE)) - continue; - // don't clip character against corpse - if (clip.passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE) - continue; - + if (w->usesolidcorpse) + { + // don't clip corpse against character + if (clip.passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE)) + continue; + // don't clip character against corpse + if (clip.passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE) + continue; + } if (!((int)clip.passedict->xv->dimension_hit & (int)touch->xv->dimension_solid)) continue; }