From ce07219448d05c5f31dfd9a20539805a93c71ebd Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 11 Aug 2010 03:36:31 +0000 Subject: [PATCH] Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded. git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_demo.c | 8 +- engine/client/cl_ents.c | 179 ++--- engine/client/cl_input.c | 18 +- engine/client/cl_main.c | 22 +- engine/client/cl_parse.c | 215 +++-- engine/client/cl_pred.c | 75 +- engine/client/cl_screen.c | 41 +- engine/client/cl_tent.c | 11 +- engine/client/cl_ui.c | 2 - engine/client/client.h | 35 +- engine/client/clq2_ents.c | 28 +- engine/client/clq3_parse.c | 2 +- engine/client/image.c | 129 ++- engine/client/m_items.c | 2 +- engine/client/m_master.c | 6 +- engine/client/m_options.c | 3 +- engine/client/m_single.c | 38 +- engine/client/modelgen.h | 36 +- engine/client/net_master.c | 4 +- engine/client/p_null.c | 2 +- engine/client/p_script.c | 46 +- engine/client/pr_csqc.c | 27 +- engine/client/r_2d.c | 17 +- engine/client/r_surf.c | 1431 +++++++++++++--------------------- engine/client/render.h | 4 +- engine/client/renderer.c | 59 +- engine/client/sbar.c | 64 +- engine/client/skin.c | 9 +- engine/client/snd_mem.c | 7 +- engine/client/sys_npfte.c | 30 +- engine/client/sys_plugfte.c | 91 ++- engine/client/textedit.c | 1 + engine/client/view.c | 17 +- engine/client/view.h | 1 - engine/client/wad.c | 20 +- engine/client/wad.h | 4 +- engine/common/bothdefs.h | 8 +- engine/common/com_mesh.c | 768 ++++++++++++++---- engine/common/com_mesh.h | 3 + engine/common/com_phys_ode.c | 10 +- engine/common/common.c | 42 +- engine/common/common.h | 13 +- engine/common/cvar.c | 2 + engine/common/fs.c | 9 +- engine/common/gl_q2bsp.c | 2 +- engine/common/huff.c | 18 +- engine/common/mathlib.c | 30 + engine/common/mathlib.h | 1 + engine/common/net.h | 1 + engine/common/net_chan.c | 6 +- engine/common/pmove.c | 8 +- engine/common/pmovetst.c | 16 +- engine/common/pr_bgcmd.c | 1 + engine/common/protocol.h | 61 ++ engine/common/q3common.c | 4 +- engine/common/world.h | 1 + engine/d3d/vid_d3d.c | 6 - engine/d3d9/vid_d3d9.c | 19 - engine/ftequake/ftequake.dsp | 72 +- engine/ftequake/ftequake.dsw | 12 + engine/gl/gl_alias.c | 26 +- engine/gl/gl_backend.c | 121 ++- engine/gl/gl_bloom.c | 12 +- engine/gl/gl_draw.c | 108 +-- engine/gl/gl_font.c | 57 ++ engine/gl/gl_model.c | 37 +- engine/gl/gl_rlight.c | 35 +- engine/gl/gl_rmain.c | 351 ++------- engine/gl/gl_rmisc.c | 3 + engine/gl/gl_rsurf.c | 22 +- engine/gl/gl_screen.c | 3 + engine/gl/gl_shader.c | 207 +++-- engine/gl/gl_shadow.c | 307 +++----- engine/gl/gl_vidnt.c | 19 +- engine/gl/glquake.h | 2 - engine/gl/glsupp.h | 6 +- engine/gl/shader.h | 3 + engine/qclib/hash.c | 38 +- engine/qclib/hash.h | 16 +- engine/qclib/pr_exec.c | 4 +- engine/qclib/qcc.h | 1 + engine/qclib/qcc_pr_comp.c | 18 +- engine/qclib/qccmain.c | 1 - engine/server/net_preparse.c | 633 ++++++++++++++- engine/server/pr_cmds.c | 293 ++++--- engine/server/pr_q1qvm.c | 3 +- engine/server/progdefs.h | 2 +- engine/server/server.h | 12 +- engine/server/sv_ccmds.c | 4 +- engine/server/sv_ents.c | 151 ++-- engine/server/sv_init.c | 54 +- engine/server/sv_main.c | 32 +- engine/server/sv_master.c | 4 +- engine/server/sv_mvd.c | 2 +- engine/server/sv_phys.c | 15 +- engine/server/sv_send.c | 6 +- engine/server/sv_user.c | 88 ++- engine/server/svq2_ents.c | 19 + engine/server/svq3_game.c | 2 +- engine/server/world.c | 48 +- 100 files changed, 3805 insertions(+), 2757 deletions(-) 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; }