From 9af4c7df7f52cf2588166cab7903b1a3509fed91 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 27 Nov 2004 08:16:25 +0000 Subject: [PATCH] we can connect to DP servers, dynamic lighting code was revised a little, a new cvar was added to control the extra feature, lights can be flagged with where they should appear, skin code was revised (to include models), fruity textures fixed, r_loadlit 2 failing to save is fixed. NQ demos smoothed. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@537 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_ents.c | 368 +++++++++++++++++++++++++++++++++-- engine/client/cl_input.c | 8 + engine/client/cl_main.c | 1 - engine/client/cl_parse.c | 267 ++++++++++++++++++++----- engine/client/cl_pred.c | 24 ++- engine/client/cl_ui.c | 4 +- engine/client/client.h | 6 +- engine/client/renderer.c | 5 +- engine/client/skin.c | 38 +++- engine/client/view.c | 3 + engine/common/bspfile.h | 2 +- engine/common/common.c | 63 +++--- engine/common/common.h | 1 + engine/common/zone.c | 2 +- engine/gl/gl_alias.c | 36 ++-- engine/gl/gl_backend.c | 6 +- engine/gl/gl_model.c | 9 +- engine/gl/gl_ppl.c | 113 +++++++++-- engine/gl/gl_rlight.c | 4 +- engine/gl/gl_rmisc.c | 67 +++++++ engine/qclib/pr_exec.c | 5 +- engine/qclib/qcc_pr_comp.c | 34 +++- engine/server/net_preparse.c | 6 + engine/server/pr_cmds.c | 3 +- engine/server/sv_init.c | 2 + 25 files changed, 923 insertions(+), 154 deletions(-) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 0b7cff7ff..38e466467 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -72,7 +72,7 @@ dlight_t *CL_AllocDlight (int key) dl = cl_dlights; for (i=0 ; idie < cl.time) + if (!dl->radius) { memset (dl, 0, sizeof(*dl)); dl->key = key; @@ -101,7 +101,7 @@ dlight_t *CL_NewDlight (int key, float x, float y, float z, float radius, float dl->origin[1] = y; dl->origin[2] = z; dl->radius = radius; - dl->die = cl.time + time; + dl->die = (float)cl.time + time; if (type == 0) { dl->color[0] = 0.2; dl->color[1] = 0.1; @@ -156,9 +156,15 @@ void CL_DecayLights (void) dl = cl_dlights; for (i=0 ; idie < cl.time || !dl->radius) + if (!dl->radius) continue; - + + if (dl->die < (float)cl.time) + { + dl->radius = 0; + continue; + } + dl->radius -= host_frametime*dl->decay; if (dl->radius < 0) dl->radius = 0; @@ -591,6 +597,324 @@ entity_state_t *CL_FindOldPacketEntity(int num) } return NULL; } +// reset all entity fields (typically used if status changed) +#define E5_FULLUPDATE (1<<0) +// E5_ORIGIN32=0: short[3] = s->origin[0] * 8, s->origin[1] * 8, s->origin[2] * 8 +// E5_ORIGIN32=1: float[3] = s->origin[0], s->origin[1], s->origin[2] +#define E5_ORIGIN (1<<1) +// E5_ANGLES16=0: byte[3] = s->angle[0] * 256 / 360, s->angle[1] * 256 / 360, s->angle[2] * 256 / 360 +// E5_ANGLES16=1: short[3] = s->angle[0] * 65536 / 360, s->angle[1] * 65536 / 360, s->angle[2] * 65536 / 360 +#define E5_ANGLES (1<<2) +// E5_MODEL16=0: byte = s->modelindex +// E5_MODEL16=1: short = s->modelindex +#define E5_MODEL (1<<3) +// E5_FRAME16=0: byte = s->frame +// E5_FRAME16=1: short = s->frame +#define E5_FRAME (1<<4) +// byte = s->skin +#define E5_SKIN (1<<5) +// E5_EFFECTS16=0 && E5_EFFECTS32=0: byte = s->effects +// E5_EFFECTS16=1 && E5_EFFECTS32=0: short = s->effects +// E5_EFFECTS16=0 && E5_EFFECTS32=1: int = s->effects +// E5_EFFECTS16=1 && E5_EFFECTS32=1: int = s->effects +#define E5_EFFECTS (1<<6) +// bits >= (1<<8) +#define E5_EXTEND1 (1<<7) + +// byte = s->renderflags +#define E5_FLAGS (1<<8) +// byte = bound(0, s->alpha * 255, 255) +#define E5_ALPHA (1<<9) +// byte = bound(0, s->scale * 16, 255) +#define E5_SCALE (1<<10) +// flag +#define E5_ORIGIN32 (1<<11) +// flag +#define E5_ANGLES16 (1<<12) +// flag +#define E5_MODEL16 (1<<13) +// byte = s->colormap +#define E5_COLORMAP (1<<14) +// bits >= (1<<16) +#define E5_EXTEND2 (1<<15) + +// short = s->tagentity +// byte = s->tagindex +#define E5_ATTACHMENT (1<<16) +// short[4] = s->light[0], s->light[1], s->light[2], s->light[3] +// byte = s->lightstyle +// byte = s->lightpflags +#define E5_LIGHT (1<<17) +// byte = s->glowsize +// byte = s->glowcolor +#define E5_GLOW (1<<18) +// short = s->effects +#define E5_EFFECTS16 (1<<19) +// int = s->effects +#define E5_EFFECTS32 (1<<20) +// flag +#define E5_FRAME16 (1<<21) +// unused +#define E5_UNUSED22 (1<<22) +// bits >= (1<<24) +#define E5_EXTEND3 (1<<23) + +// unused +#define E5_UNUSED24 (1<<24) +// unused +#define E5_UNUSED25 (1<<25) +// unused +#define E5_UNUSED26 (1<<26) +// unused +#define E5_UNUSED27 (1<<27) +// unused +#define E5_UNUSED28 (1<<28) +// unused +#define E5_UNUSED29 (1<<29) +// unused +#define E5_UNUSED30 (1<<30) +// bits2 > 0 +#define E5_EXTEND4 (1<<31) + + static entity_state_t defaultstate; +void DP5_ParseDelta(entity_state_t *s) +{ + int bits; + bits = MSG_ReadByte(); + if (bits & E5_EXTEND1) + { + bits |= MSG_ReadByte() << 8; + if (bits & E5_EXTEND2) + { + bits |= MSG_ReadByte() << 16; + if (bits & E5_EXTEND3) + bits |= MSG_ReadByte() << 24; + } + } + if (bits & E5_FULLUPDATE) + { + *s = defaultstate; +// s->active = true; + } + if (bits & E5_FLAGS) + s->flags = MSG_ReadByte(); + if (bits & E5_ORIGIN) + { + if (bits & E5_ORIGIN32) + { + s->origin[0] = MSG_ReadFloat(); + s->origin[1] = MSG_ReadFloat(); + s->origin[2] = MSG_ReadFloat(); + } + else + { + s->origin[0] = MSG_ReadShort()*(1/8.0f); + s->origin[1] = MSG_ReadShort()*(1/8.0f); + s->origin[2] = MSG_ReadShort()*(1/8.0f); + } + } + if (bits & E5_ANGLES) + { + if (bits & E5_ANGLES16) + { + s->angles[0] = MSG_ReadAngle16(); + s->angles[1] = MSG_ReadAngle16(); + s->angles[2] = MSG_ReadAngle16(); + } + else + { + s->angles[0] = MSG_ReadChar() * (360.0/256); + s->angles[1] = MSG_ReadChar() * (360.0/256); + s->angles[2] = MSG_ReadChar() * (360.0/256); + } + } + if (bits & E5_MODEL) + { + if (bits & E5_MODEL16) + s->modelindex = (unsigned short) MSG_ReadShort(); + else + s->modelindex = MSG_ReadByte(); + } + if (bits & E5_FRAME) + { + if (bits & E5_FRAME16) + s->frame = (unsigned short) MSG_ReadShort(); + else + s->frame = MSG_ReadByte(); + } + if (bits & E5_SKIN) + s->skinnum = MSG_ReadByte(); + if (bits & E5_EFFECTS) + { + if (bits & E5_EFFECTS32) + s->effects = (unsigned int) MSG_ReadLong(); + else if (bits & E5_EFFECTS16) + s->effects = (unsigned short) MSG_ReadShort(); + else + s->effects = MSG_ReadByte(); + } + if (bits & E5_ALPHA) + s->trans = MSG_ReadByte()/255.0f; + if (bits & E5_SCALE) + s->scale = MSG_ReadByte()/255.0f; + if (bits & E5_COLORMAP) + s->colormap = MSG_ReadByte(); + if (bits & E5_ATTACHMENT) + { + MSG_ReadShort(); + MSG_ReadByte(); +// s->tagentity = (unsigned short) MSG_ReadShort(); +// s->tagindex = MSG_ReadByte(); + } + if (bits & E5_LIGHT) + { + MSG_ReadShort(); + MSG_ReadShort(); + MSG_ReadShort(); + MSG_ReadShort(); + MSG_ReadByte(); + MSG_ReadByte(); +// s->light[0] = (unsigned short) MSG_ReadShort(); +// s->light[1] = (unsigned short) MSG_ReadShort(); +// s->light[2] = (unsigned short) MSG_ReadShort(); +// s->light[3] = (unsigned short) MSG_ReadShort(); +// s->lightstyle = MSG_ReadByte(); +// s->lightpflags = MSG_ReadByte(); + } + if (bits & E5_GLOW) + { + MSG_ReadByte(); + MSG_ReadByte(); +// s->glowsize = MSG_ReadByte(); +// s->glowcolor = MSG_ReadByte(); + } +} + +int cl_latestframenum; +void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o( +{ + //the incoming entities do not come in in any order. :( + //well, they come in in order of priorities, but that's not useful to us. + //I guess this means we'll have to go slowly. + + packet_entities_t *pack, *oldpack; + + entity_state_t *to, *from; + unsigned short read; + int oldi; + qboolean remove; + + cls.netchan.incoming_sequence++; + + cl.validsequence=1; + + cl_latestframenum = MSG_ReadLong(); + + pack = &cl.frames[(cls.netchan.incoming_sequence)&UPDATE_MASK].packet_entities; + oldpack = &cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities; + + from = oldpack->entities; + oldi = 0; + pack->num_entities = 0; + + for (oldi = 0; oldi < oldpack->num_entities; oldi++) + { + from = &oldpack->entities[oldi]; + from->flags &= ~0x80000000; + } + + for (read = MSG_ReadShort(); read!=0x8000; read = MSG_ReadShort()) + { + if (msg_badread) + Host_EndGame("Corrupt entitiy message packet\n"); + remove = !!(read&0x8000); + read&=~0x8000; + + from = &defaultstate; + + for (oldi=0 ; oldinum_entities ; oldi++) + { + if (read == oldpack->entities[oldi].number) + { + from = &oldpack->entities[oldi]; + break; + } + } + + from->flags = 0x80000000; + if (remove) + { + continue; + } + + + if (pack->num_entities==pack->max_entities) + { + pack->max_entities = pack->num_entities+16; + pack->entities = BZ_Realloc(pack->entities, sizeof(entity_state_t)*pack->max_entities); + } + + to = &pack->entities[pack->num_entities]; + pack->num_entities++; + memcpy(to, from, sizeof(*to)); + DP5_ParseDelta(to); + + to->number = read; + + if (!from || to->modelindex != from->modelindex || to->number != from->number) //model changed... or entity changed... + cl.lerpents[to->number].lerptime = -10; + else if (to->frame != from->frame || to->origin[0] != from->origin[0] || to->origin[1] != from->origin[1] || to->origin[2] != from->origin[2]) + { + cl.lerpents[to->number].origin[0] = from->origin[0]; + cl.lerpents[to->number].origin[1] = from->origin[1]; + cl.lerpents[to->number].origin[2] = from->origin[2]; + + cl.lerpents[to->number].angles[0] = from->angles[0]; + cl.lerpents[to->number].angles[1] = from->angles[1]; + cl.lerpents[to->number].angles[2] = from->angles[2]; + //we have three sorts of movement. + //1: stepping monsters. These have frames and tick at 10fps. + //2: physics. Objects moving acording to gravity. + //3: both. This is really awkward. And I'm really lazy. + cl.lerpents[to->number].lerprate = cl.time-cl.lerpents[to->number].lerptime; //time per update + cl.lerpents[to->number].frame = from->frame; + cl.lerpents[to->number].lerptime = cl.time; + + if (cl.lerpents[to->number].lerprate>0.5) + cl.lerpents[to->number].lerprate=0.1; + + //store this off for new ents to use. + // if (new) + // cl.lerpents[state->number].lerptime = newlerprate; + // else + if (to->frame == from->frame) + newlerprate = cl.time-cl.lerpents[to->number].lerptime; + } + + to->flags &= ~0x80000000; + } + + //the pack has all the new ones in it, now copy the old ones in that wern't removed (or changed). + for (oldi = 0; oldi < oldpack->num_entities; oldi++) + { + from = &oldpack->entities[oldi]; + if (from->flags & 0x80000000) + continue; + + if (pack->num_entities==pack->max_entities) + { + pack->max_entities = pack->num_entities+16; + pack->entities = BZ_Realloc(pack->entities, sizeof(entity_state_t)*pack->max_entities); + } + + to = &pack->entities[pack->num_entities]; + pack->num_entities++; + + from = &oldpack->entities[oldi]; + + memcpy(to, from, sizeof(*to)); + } +} void CLNQ_ParseEntity(unsigned int bits) { @@ -688,7 +1012,7 @@ void CLNQ_ParseEntity(unsigned int bits) state = &pack->entities[pack->num_entities++]; } - from = CL_FindOldPacketEntity(num); + from = CL_FindOldPacketEntity(num); //this could be optimised. base = &cl_baselines[num]; @@ -902,7 +1226,8 @@ void CL_LinkPacketEntities (void) vec3_t old_origin; float autorotate; int i; - int pnum, spnum; + int pnum; + //, spnum; dlight_t *dl; vec3_t angles; @@ -916,20 +1241,20 @@ void CL_LinkPacketEntities (void) // spawn light flashes, even ones coming from invisible objects if ((s1->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 3); + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0, 3); else if (s1->effects & EF_BLUE) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 1); + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0, 1); else if (s1->effects & EF_RED) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 2); + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0, 2); else if (s1->effects & EF_BRIGHTLIGHT) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand()&31), 0.1, 0); + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand()&31), 0, 0); else if (s1->effects & EF_DIMLIGHT) - CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 0); + CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0, 0); // if set to invisible, skip - if (!s1->modelindex) + if (s1->modelindex<0) continue; - +#if 0 for (spnum = 0; spnum < cl.splitclients; spnum++) { if (s1->number == cl.viewentity[spnum]) @@ -973,7 +1298,7 @@ void CL_LinkPacketEntities (void) }*/ } } - +#endif // create a new entity if (cl_numvisedicts == MAX_VISEDICTS) break; // object list is full @@ -1023,7 +1348,7 @@ void CL_LinkPacketEntities (void) // set colormap if (s1->colormap && (s1->colormap <= MAX_CLIENTS) - && (gl_nocolors.value == -1 || (ent->model && s1->modelindex == cl_playerindex))) + && (gl_nocolors.value == -1 || (ent->model/* && s1->modelindex == cl_playerindex*/))) { ent->colormap = cl.players[s1->colormap-1].translations; ent->scoreboard = &cl.players[s1->colormap-1]; @@ -1167,7 +1492,7 @@ void CL_LinkPacketEntities (void) dl = CL_AllocDlight (s1->number); VectorCopy (ent->origin, dl->origin); dl->radius = 200; - dl->die = cl.time + 0.1; + dl->die = (float)cl.time; dl->color[0] = 0.20; dl->color[1] = 0.1; dl->color[2] = 0.05; @@ -1178,21 +1503,21 @@ void CL_LinkPacketEntities (void) dl = CL_AllocDlight (i); VectorCopy (ent->origin, dl->origin); dl->radius = 120 - (rand() % 20); - dl->die = cl.time + 0.01; + dl->die = (float)cl.time; } else if (model->flags & EF_ACIDBALL) { dl = CL_AllocDlight (i); VectorCopy (ent->origin, dl->origin); dl->radius = 120 - (rand() % 20); - dl->die = cl.time + 0.01; + dl->die = (float)cl.time; } else if (model->flags & EF_SPIT) { dl = CL_AllocDlight (i); VectorCopy (ent->origin, dl->origin); dl->radius = -120 - (rand() % 20); - dl->die = cl.time + 0.05; + dl->die = (float)cl.time; } } } @@ -1898,7 +2223,7 @@ void CL_SetSolidEntities (void) { state = &pak->entities[i]; - if (!state->modelindex) + if (state->modelindex<0) continue; if (!cl.model_precache[state->modelindex]) continue; @@ -2077,6 +2402,9 @@ void CL_EmitEntities (void) { if (cls.state != ca_active) return; + + CL_DecayLights (); + #ifdef Q2CLIENT if (cls.q2server) { diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 4a4ee8d65..2f2a1926b 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -617,6 +617,7 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum) } void CLNQ_SendCmd(void) { + extern int cl_latestframenum, nq_dp_protocol; usercmd_t cmd; if (cls.state <= ca_connected) @@ -641,6 +642,13 @@ void CLNQ_SendCmd(void) MSG_WriteByte(&cls.netchan.message, clc_stringcmd); MSG_WriteString(&cls.netchan.message, va("name \"%s\"\n", name.string)); } + + if (nq_dp_protocol > 0) + { + MSG_WriteByte(&cls.netchan.message, 50); + MSG_WriteLong(&cls.netchan.message, cl_latestframenum); + } + // send the reliable message if (!cls.netchan.message.cursize) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index d82c8d271..5597be26c 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -2548,7 +2548,6 @@ CL_RequestNextDownload(); if (cls.state == ca_active) { S_Update (r_origin, vpn, vright, vup); - CL_DecayLights (); } else S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index d506ade0d..e7d9352f5 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" void CL_GetNumberedEntityInfo (int num, float *org, float *ang); +void CLNQ_ParseDarkPlaces5Entities(void); void R_ParseParticleEffect2 (void); void R_ParseParticleEffect3 (void); @@ -312,7 +313,7 @@ void R_ParseParticleEffect4 (void); #define Q2MZ2_WIDOW2_BEAM_SWEEP_11 210 - +int nq_dp_protocol; @@ -579,6 +580,8 @@ qboolean CL_CheckOrDownloadFile (char *filename, int nodelay) MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname)); + SCR_EndLoadingPlaque(); //release console. + return false; } @@ -1200,6 +1203,17 @@ void CL_ParseServerData (void) Host_EndGame ("Server returned version %i, not %i\nYou probably need to upgrade.\nCheck http://www.quakeworld.net/", protover, PROTOCOL_VERSION); #endif + if (cls.fteprotocolextensions & PEXT_FLOATCOORDS) + { + sizeofcoord = 4; + sizeofangle = 1; + } + else + { + sizeofcoord = 2; + sizeofangle = 1; + } + svcnt = MSG_ReadLong (); // game directory @@ -1324,6 +1338,9 @@ void CLQ2_ParseServerData (void) int i; int svcnt; // int cflag; + + sizeofcoord = 2; + sizeofangle = 1; Con_DPrintf ("Serverdata packet received.\n"); // @@ -1416,8 +1433,20 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. protover = MSG_ReadLong (); + sizeofcoord = 2; + sizeofangle = 1; + + nq_dp_protocol = 0; + if (protover == 250) Host_EndGame ("Nehahra demo net protocol is not supported\n"); + else if (protover == 3502) + { + //darkplaces5 + nq_dp_protocol = 5; + sizeofcoord = 4; + sizeofangle = 2; + } else if (protover != NQ_PROTOCOL_VERSION) { Host_EndGame ("Server returned version %i, not %i\nYou will need to use a different client.", protover, NQ_PROTOCOL_VERSION); @@ -1573,11 +1602,39 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); #define SU_WEAPONFRAME (1<<12) #define SU_ARMOR (1<<13) #define SU_WEAPON (1<<14) + +#define DPSU_EXTEND1 (1<<15) +// first extend byte +#define DPSU_PUNCHVEC1 (1<<16) +#define DPSU_PUNCHVEC2 (1<<17) +#define DPSU_PUNCHVEC3 (1<<18) +#define DPSU_VIEWZOOM (1<<19) // byte factor (0 = 0.0 (not valid), 255 = 1.0) +#define DPSU_UNUSED20 (1<<20) +#define DPSU_UNUSED21 (1<<21) +#define DPSU_UNUSED22 (1<<22) +#define DPSU_EXTEND2 (1<<23) // another byte to follow, future expansion +// second extend byte +#define DPSU_UNUSED24 (1<<24) +#define DPSU_UNUSED25 (1<<25) +#define DPSU_UNUSED26 (1<<26) +#define DPSU_UNUSED27 (1<<27) +#define DPSU_UNUSED28 (1<<28) +#define DPSU_UNUSED29 (1<<29) +#define DPSU_UNUSED30 (1<<30) +#define DPSU_EXTEND3 (1<<31) // another byte to follow, future expansion + + #define DEFAULT_VIEWHEIGHT 22 void CLNQ_ParseClientdata (int bits) { - extern player_state_t *view_message; int i, j; + + bits &= 0xffff; + + if (bits & DPSU_EXTEND1) + bits |= (MSG_ReadByte() << 16); + if (bits & DPSU_EXTEND2) + bits |= (MSG_ReadByte() << 24); if (bits & SU_VIEWHEIGHT) cl.viewheight[0] = MSG_ReadChar (); @@ -1593,17 +1650,30 @@ void CLNQ_ParseClientdata (int bits) for (i=0 ; i<3 ; i++) { if (bits & (SU_PUNCH1<weaponframe = i; - - if (bits & SU_ARMOR) - i = MSG_ReadByte (); - else - i = 0; - if (cl.stats[0][STAT_ARMOR] != i) + if (nq_dp_protocol == 5) { - cl.stats[0][STAT_ARMOR] = i; - Sbar_Changed (); - } + if (bits & SU_WEAPONFRAME) + i = MSG_ReadShort (); + else + i = 0; - if (bits & SU_WEAPON) - i = MSG_ReadByte (); - else - i = 0; - if (cl.stats[0][STAT_WEAPON] != i) - { - cl.stats[0][STAT_WEAPON] = i; - Sbar_Changed (); - } - - i = MSG_ReadShort (); - if (cl.stats[0][STAT_HEALTH] != i) - { - cl.stats[0][STAT_HEALTH] = i; - Sbar_Changed (); - } + cl.stats[0][STAT_WEAPONFRAME] = i; - i = MSG_ReadByte (); - if (cl.stats[0][STAT_AMMO] != i) - { - cl.stats[0][STAT_AMMO] = i; - Sbar_Changed (); - } - - for (i=0 ; i<4 ; i++) - { - j = MSG_ReadByte (); - if (cl.stats[0][STAT_SHELLS+i] != j) + if (bits & SU_ARMOR) + i = MSG_ReadShort (); + else + i = 0; + if (cl.stats[0][STAT_ARMOR] != i) { - cl.stats[0][STAT_SHELLS+i] = j; + cl.stats[0][STAT_ARMOR] = i; Sbar_Changed (); } - } - i = MSG_ReadByte (); + if (bits & SU_WEAPON) + i = MSG_ReadShort (); + else + i = 0; + if (cl.stats[0][STAT_WEAPON] != i) + { + cl.stats[0][STAT_WEAPON] = i; + Sbar_Changed (); + } + + i = MSG_ReadShort (); + if (cl.stats[0][STAT_HEALTH] != i) + { + cl.stats[0][STAT_HEALTH] = i; + Sbar_Changed (); + } + + i = MSG_ReadShort (); + if (cl.stats[0][STAT_AMMO] != i) + { + cl.stats[0][STAT_AMMO] = i; + Sbar_Changed (); + } + + for (i=0 ; i<4 ; i++) + { + j = MSG_ReadShort (); + if (cl.stats[0][STAT_SHELLS+i] != j) + { + cl.stats[0][STAT_SHELLS+i] = j; + Sbar_Changed (); + } + } + + i = MSG_ReadShort (); + + } + else + { + if (bits & SU_WEAPONFRAME) + i = MSG_ReadByte (); + else + i = 0; + + cl.stats[0][STAT_WEAPONFRAME] = i; + + if (bits & SU_ARMOR) + i = MSG_ReadByte (); + else + i = 0; + if (cl.stats[0][STAT_ARMOR] != i) + { + cl.stats[0][STAT_ARMOR] = i; + Sbar_Changed (); + } + + if (bits & SU_WEAPON) + i = MSG_ReadByte (); + else + i = 0; + if (cl.stats[0][STAT_WEAPON] != i) + { + cl.stats[0][STAT_WEAPON] = i; + Sbar_Changed (); + } + + i = MSG_ReadShort (); + if (cl.stats[0][STAT_HEALTH] != i) + { + cl.stats[0][STAT_HEALTH] = i; + Sbar_Changed (); + } + + i = MSG_ReadByte (); + if (cl.stats[0][STAT_AMMO] != i) + { + cl.stats[0][STAT_AMMO] = i; + Sbar_Changed (); + } + + for (i=0 ; i<4 ; i++) + { + j = MSG_ReadByte (); + if (cl.stats[0][STAT_SHELLS+i] != j) + { + cl.stats[0][STAT_SHELLS+i] = j; + Sbar_Changed (); + } + } + + i = MSG_ReadByte (); + } if (standard_quake) { @@ -1688,6 +1815,21 @@ void CLNQ_ParseClientdata (int bits) Sbar_Changed (); } } + + + + if (bits & DPSU_VIEWZOOM) + { + if (nq_dp_protocol == 5) + i = (unsigned short) MSG_ReadShort(); + else + i = MSG_ReadByte(); + if (i < 2) + i = 2; +// cl.viewzoomnew = (float) i * (1.0f / 255.0f); + } +// else +// cl.viewzoomnew = 1; } #endif /* @@ -2370,6 +2512,8 @@ void CL_ProcessUserInfo (int slot, player_info_t *player) if (slot == cl.playernum[0] && player->name[0]) cl.spectator = player->spectator; + player->model = NULL; + if (cls.state == ca_active) Skin_Find (player); @@ -3290,6 +3434,7 @@ int getplayerchatcolour(char *msg) } #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x); +#define SHOWNET2(x, y) if(cl_shownet.value==2)Con_Printf ("%3i:%3i:%s\n", msg_readcount-1, y, x); /* ===================== CL_ParseServerMessage @@ -3941,7 +4086,7 @@ void CLNQ_ParseServerMessage (void) continue; } - SHOWNET(svc_nqstrings[cmd>(sizeof(svc_nqstrings)/sizeof(char*))?0:cmd]); + SHOWNET2(svc_nqstrings[cmd>(sizeof(svc_nqstrings)/sizeof(char*))?0:cmd], cmd); // other commands switch (cmd) @@ -4040,8 +4185,12 @@ void CLNQ_ParseServerMessage (void) cl.last_servermessage = realtime; cl.gametime = MSG_ReadFloat(); cl.gametimemark = realtime; - 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; + if (nq_dp_protocol!=5) + { + cls.netchan.incoming_sequence++; +// 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; + } break; case svc_updatename: @@ -4156,6 +4305,16 @@ void CLNQ_ParseServerMessage (void) case svcnq_effect2: CL_ParseEffect(true); break; + + case 57://svc_entities + if (cls.signon == 4 - 1) + { // first update is the final signon stage + cls.signon = 4; + CLNQ_SignonReply (); + } + //well, it's really any protocol, but we're only going to support version 5. + CLNQ_ParseDarkPlaces5Entities(); + break; } } } diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 3cd82664e..cef2dbde0 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -533,6 +533,7 @@ void CL_PredictMovePNum (int pnum) float f; frame_t *from, *to = NULL; int oldphysent; + vec3_t lrp; //these are to make svc_viewentity work better float *vel; @@ -609,17 +610,36 @@ void CL_PredictMovePNum (int pnum) #ifdef PEXT_SETVIEW if (cl.viewentity[pnum]) { + entity_state_t *CL_FindOldPacketEntity(int num); entity_state_t *CL_FindPacketEntity(int num); - entity_state_t *state; + entity_state_t *state, *old; state = CL_FindPacketEntity (cl.viewentity[pnum]); + old = CL_FindOldPacketEntity (cl.viewentity[pnum]); if (state) { - org = state->origin; + if (old) + { + float f = (cl.time-cl.lerpents[cl.viewentity[pnum]].lerptime)/cl.lerpents[cl.viewentity[pnum]].lerprate; + f=1-f; + if (f<0)f=0; + if (f>1)f=1; + + for (i=0 ; i<3 ; i++) + lrp[i] = state->origin[i] + + f * (old->origin[i] - state->origin[i]); + + org = lrp; + } + else + org = state->origin; + + goto fixedorg; } } #endif if ((cl_nopred.value|| cl.fixangle)) { +fixedorg: VectorCopy (vel, cl.simvel[pnum]); VectorCopy (org, cl.simorg[pnum]); diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 6059998be..e3bc32d67 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -1278,8 +1278,8 @@ void UI_Start (void) return; uivm = VM_Create(NULL, "vm/qwui", UI_SystemCalls, UI_SystemCallsEx); -// if (!uivm) //broken currently, I believe. -// uivm = VM_Create(NULL, "vm/ui", UI_SystemCalls, UI_SystemCallsEx); + if (!uivm) //broken currently, I believe. + uivm = VM_Create(NULL, "vm/ui", UI_SystemCalls, UI_SystemCallsEx); if (uivm) { apiversion = VM_Call(uivm, UI_GETAPIVERSION, UI_API_VERSION); diff --git a/engine/client/client.h b/engine/client/client.h index 95722661d..ce81f2926 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -205,11 +205,11 @@ typedef struct // // client_state_t should hold all pieces of the client state // -#define MAX_DLIGHTS 32 +#define MAX_DLIGHTS 256 typedef struct dlight_s { int key; // so entities can reuse same entry - qboolean noppl; + qboolean noppl, nodynamic, noflash, isstatic; vec3_t origin; float radius; float die; // stop lighting after this time @@ -217,6 +217,8 @@ typedef struct dlight_s float minlight; // don't add when contributing less float color[3]; float channelfade[3]; + + struct shadowmesh_s *worldshadowmesh; } dlight_t; typedef struct diff --git a/engine/client/renderer.c b/engine/client/renderer.c index dcd80af33..1ecbb50fd 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -147,6 +147,7 @@ cvar_t gl_specular = {"gl_specular", "0"}; cvar_t gl_waterripples = {"gl_waterripples", "0"}; cvar_t gl_detail = {"gl_detail", "0", NULL, CVAR_ARCHIVE}; cvar_t r_shadows = {"r_shadows", "0", NULL, CVAR_ARCHIVE|CVAR_RENDERERLATCH}; +cvar_t r_shadow_realtime_world = {"r_shadow_realtime_world", "0", NULL, CVAR_CHEAT}; cvar_t r_noaliasshadows = {"r_noaliasshadows", "0", NULL, CVAR_ARCHIVE}; cvar_t gl_maxshadowlights = {"gl_maxshadowlights", "2", NULL, CVAR_ARCHIVE}; cvar_t gl_bump = {"gl_bump", "0", NULL, CVAR_ARCHIVE|CVAR_RENDERERLATCH}; @@ -156,7 +157,7 @@ cvar_t gl_ati_truform = {"gl_ati_truform", "0"}; cvar_t gl_ati_truform_type = {"gl_ati_truform_type", "1"}; cvar_t gl_ati_truform_tesselation = {"gl_ati_truform_tesselation", "3"}; -cvar_t gl_lateswap = {"gl_lateswap", "1"}; +cvar_t gl_lateswap = {"gl_lateswap", "0"}; cvar_t scr_sshot_type = {"scr_sshot_type", "jpg"}; @@ -253,6 +254,8 @@ void GLRenderer_Init(void) Cvar_Register (&r_lightmap, GLRENDEREROPTIONS); Cvar_Register (&r_norefresh, GLRENDEREROPTIONS); + Cvar_Register (&r_shadow_realtime_world, GLRENDEREROPTIONS); + Cvar_Register (&gl_clear, GLRENDEREROPTIONS); Cvar_Register (&gl_cull, GLRENDEREROPTIONS); diff --git a/engine/client/skin.c b/engine/client/skin.c index 88663632c..18fbe7f03 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -43,23 +43,43 @@ void Skin_Find (player_info_t *sc) { skin_t *skin; int i; - char name[128], *s; + char name[128], *s, *mn; + model_t *model; + + mn = Info_ValueForKey (sc->userinfo, "model"); + while(s = strchr(mn, '/')) + *mn = '\0'; if (allskins[0]) - strcpy (name, allskins); + s = allskins; else { s = Info_ValueForKey (sc->userinfo, "skin"); - if (s && s[0]) - strcpy (name, s); - else - strcpy (name, baseskin.string); + if (!s[0]) + s = baseskin.string; } - if (strstr (name, "..") || *name == '.') - strcpy (name, "base"); + if (*mn) + mn = va("%s/%s", mn, s); - COM_StripExtension (name, name); + if (strstr (mn, "..") || *mn == '.') + mn = "base"; + + COM_StripExtension (mn, name); + + s = strchr(name, '/'); + if (s) + { + *s = '\0'; + model = Mod_ForName(va("models/players/%s.mdl", name), false); + if (model->type == mod_dummy) + model = NULL; + *s = '/'; + } + else + model = NULL; + + sc->model = model; for (i=0 ; iplayerstate[cl.playernum[plnum]]; + if (cls.netcon) + view_message->weaponframe = cl.stats[0][STAT_WEAPONFRAME]; + cl.simangles[plnum][ROLL] = 0; // FIXME @@@ diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index 5cb77d001..77bdc631d 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -348,7 +348,7 @@ typedef struct q2miptex_s #define MAX_Q2MAP_AREAS 256 #define MAX_Q2MAP_AREAPORTALS 1024 -#define MAX_Q2MAP_PLANES 0x00030000 +#define MAX_Q2MAP_PLANES 0x00040000 #define MAX_Q2MAP_NODES 65536 #define MAX_Q2MAP_BRUSHSIDES 0x40000 #define MAX_Q2MAP_LEAFS 65536 diff --git a/engine/common/common.c b/engine/common/common.c index c469305fc..28389a8ef 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -681,6 +681,7 @@ void MSG_WriteString (sizebuf_t *sb, char *s) } int sizeofcoord=2; +int sizeofangle=1; float MSG_FromCoord(coorddata c, int bytes) { switch(bytes) @@ -719,16 +720,19 @@ void MSG_WriteCoord (sizebuf_t *sb, float f) SZ_Write (sb, (void*)&i, sizeofcoord); } -void MSG_WriteAngle (sizebuf_t *sb, float f) -{ - MSG_WriteByte (sb, (int)(f*256/360) & 255); -} - void MSG_WriteAngle16 (sizebuf_t *sb, float f) { MSG_WriteShort (sb, (int)(f*65536/360) & 65535); } +void MSG_WriteAngle (sizebuf_t *sb, float f) +{ + if (sizeofangle==2) + MSG_WriteAngle16(sb, f); + else + MSG_WriteByte (sb, (int)(f*256/360) & 255); +} + void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd) { int bits; @@ -990,9 +994,9 @@ float MSG_ReadCoord (void) void MSG_ReadPos (vec3_t pos) { - pos[0] = MSG_ReadShort() * (1.0/8); - pos[1] = MSG_ReadShort() * (1.0/8); - pos[2] = MSG_ReadShort() * (1.0/8); + pos[0] = MSG_ReadCoord(); + pos[1] = MSG_ReadCoord(); + pos[2] = MSG_ReadCoord(); } #define Q2NUMVERTEXNORMALS 162 @@ -1035,15 +1039,17 @@ void MSG_WriteDir (sizebuf_t *sb, vec3_t dir) } MSG_WriteByte (sb, best); } -float MSG_ReadAngle (void) -{ - return MSG_ReadChar() * (360.0/256); -} float MSG_ReadAngle16 (void) { return MSG_ReadShort() * (360.0/65536); } +float MSG_ReadAngle (void) +{ + if (sizeofangle==2) + return MSG_ReadAngle16(); + return MSG_ReadChar() * (360.0/256); +} void MSG_ReadDeltaUsercmd (usercmd_t *from, usercmd_t *move) { @@ -2200,7 +2206,7 @@ void COM_WriteFile (char *filename, void *data, int len) f = fopen (name, "wb"); if (!f) { - Con_Printf("Error opening %s\n", filename); + Con_Printf("Error opening %s for writing\n", filename); return; } } @@ -2301,17 +2307,11 @@ int FS_RebuildOSFSHash(char *filename, int filesize, void *data) return true; } -void FS_RebuildFSHash(void) +void FS_FlushFSHash(void) { - int i; - searchpath_t *search; - if (!filesystemhash.numbuckets) - { - filesystemhash.numbuckets = 1024; - filesystemhash.bucket = BZ_Malloc(Hash_BytesForBuckets(filesystemhash.numbuckets)); - } - else + if (filesystemhash.numbuckets) { + int i; bucket_t *bucket, *next; for (i = 0; i < filesystemhash.numbuckets; i++) @@ -2327,6 +2327,23 @@ void FS_RebuildFSHash(void) } } } + + com_fschanged = true; +} + +void FS_RebuildFSHash(void) +{ + int i; + searchpath_t *search; + if (!filesystemhash.numbuckets) + { + filesystemhash.numbuckets = 1024; + filesystemhash.bucket = BZ_Malloc(Hash_BytesForBuckets(filesystemhash.numbuckets)); + } + else + { + FS_FlushFSHash(); + } Hash_InitTable(&filesystemhash, filesystemhash.numbuckets, filesystemhash.bucket); fs_hash_dups = 0; @@ -3952,6 +3969,8 @@ void COM_Gamedir (char *dir) cl.gamedirchanged = true; #endif + FS_FlushFSHash(); + // // free up any current game dir info // diff --git a/engine/common/common.h b/engine/common/common.h index 7155068ee..8c125bd3f 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -112,6 +112,7 @@ typedef union { //note: reading from packets can be misaligned float f; } coorddata; extern int sizeofcoord; +extern int sizeofangle; float MSG_FromCoord(coorddata c, int bytes); coorddata MSG_ToCoord(float f, int bytes); diff --git a/engine/common/zone.c b/engine/common/zone.c index c76944a8e..e917ebeaf 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -34,7 +34,7 @@ void Cache_FreeLow (int new_low_hunk); void Cache_FreeHigh (int new_high_hunk); #ifdef _DEBUG -#define MEMDEBUG 8192 //Debugging adds sentinels (the number is the size - I have the ram) +//#define MEMDEBUG 8192 //Debugging adds sentinels (the number is the size - I have the ram) #endif #ifndef MEMDEBUG diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 374264bb0..c9e668a11 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -351,7 +351,7 @@ static void R_GAliasAddDlights(mesh_t *mesh, vec3_t org, vec3_t angles) AngleVectors(angles, axis[0], axis[1], axis[2]); for (l=0 ; l= cl.time) + if (cl_dlights[l].radius) { VectorSubtract (cl_dlights[l].origin, org, @@ -623,7 +623,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, entity_ galiascolourmapped_t *cm; cc = (tc<<4)|bc; - if (!strstr(modelname, "player")) + if (!strstr(modelname, "progs/player.mdl")) skinname = modelname; else { @@ -661,18 +661,18 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, entity_ cm->texnum.fullbright = 0; cm->texnum.base = 0; cm->texnum.bump = texnums[cm->skinnum].bump; //can't colour bumpmapping - if (skins->ofstexels) - { - original = (qbyte *)skins + skins->ofstexels; - inwidth = skins->skinwidth; - inheight = skins->skinheight; - } - else if (skinname!=modelname && e->scoreboard && e->scoreboard->skin) + if (skinname!=modelname && e->scoreboard && e->scoreboard->skin) { original = Skin_Cache8(e->scoreboard->skin); inwidth = e->scoreboard->skin->width; inheight = e->scoreboard->skin->height; } + else if (skins->ofstexels) + { + original = (qbyte *)skins + skins->ofstexels; + inwidth = skins->skinwidth; + inheight = skins->skinheight; + } else { original = NULL; @@ -971,7 +971,7 @@ void GL_DrawAliasMesh (mesh_t *mesh, int texnum) void R_DrawGAliasModel (entity_t *e) { - model_t *clmodel = e->model; + model_t *clmodel; vec3_t mins, maxs; vec3_t dist; vec_t add; @@ -989,6 +989,18 @@ void R_DrawGAliasModel (entity_t *e) if (e->flags & Q2RF_VIEWERMODEL && e->keynum == cl.playernum[r_refdef.currentplayernum]+1) return; + { + extern int cl_playerindex; + if (e->scoreboard && e->model == cl.model_precache[cl_playerindex]) + { + clmodel = e->scoreboard->model; + if (!clmodel || clmodel->type != mod_alias) + clmodel = e->model; + } + else + clmodel = e->model; + } + VectorAdd (e->origin, clmodel->mins, mins); VectorAdd (e->origin, clmodel->maxs, maxs); @@ -1012,7 +1024,7 @@ void R_DrawGAliasModel (entity_t *e) { for (i=0 ; i= cl.time) + if (cl_dlights[i].radius) { VectorSubtract (e->origin, cl_dlights[i].origin, @@ -1452,7 +1464,7 @@ void R_DrawGAliasModelLighting (entity_t *e) for (i=0 ; i= cl.time) + if (cl_dlights[i].radius) { VectorSubtract (e->origin, cl_dlights[i].origin, diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index e78822d75..556ff4a54 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -61,12 +61,10 @@ void GL_BindType (int type, int texnum) void GL_TexEnv( GLenum mode ) { - static int lastmodes[MAX_TEXTURE_UNITS] = { -1, -1 }; - - if ( mode != lastmodes[gl_state.currenttmu] ) + if ( mode != gl_state.texenvmode[gl_state.currenttmu] ) { qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode ); - lastmodes[gl_state.currenttmu] = mode; + gl_state.texenvmode[gl_state.currenttmu] = mode; } } diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 683f0c92b..626ae2563 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -420,8 +420,15 @@ void GLMod_Think (void) if (relitsurface >= lightmodel->numsurfaces) { char filename[MAX_QPATH]; + char *f; Con_Printf("Finished lighting level\n"); - + + + strcpy(filename, lightmodel->name); + f = COM_SkipPath(filename); + *f = '\0'; + Sys_mkdir(va("%s/%s", com_gamedir, filename)); + if (lightmodel->deluxdata) { COM_StripExtension(lightmodel->name, filename); diff --git a/engine/gl/gl_ppl.c b/engine/gl/gl_ppl.c index 2e897be71..337a5b182 100644 --- a/engine/gl/gl_ppl.c +++ b/engine/gl/gl_ppl.c @@ -19,6 +19,7 @@ extern cvar_t gl_part_flame; extern cvar_t gl_part_flame; extern cvar_t gl_maxshadowlights; +extern cvar_t r_shadow_realtime_world; extern int detailtexture; //end header confict @@ -40,6 +41,13 @@ int ppl_specular_fragmentprogram; //#define glBegin glEnd +typedef struct shadowmesh_s { + int numindicies; + int *indicies; + vec3_t *verts; +} shadowmesh_t; + + #define Q2RF_WEAPONMODEL 4 // only draw through eyes struct { @@ -837,7 +845,60 @@ void PPL_LoadSpecularFragmentProgram(void) "MUL_SAT ocol.rgb, diff, lm;\n" //that's all folks. "END"; +/* + //okay, the NV fallback + char *nvfp = "!!FP1.0\n" + "PARAM half = { 0.5, 0.5, 0.5, 0.5 };\n" + "PARAM negone = { -1,-1,-1,-1 };\n" + + "ATTRIB tm_tc = fragment.texcoord[0];\n" + "ATTRIB lm_tc = fragment.texcoord[1];\n" + "ATTRIB cm_tc = fragment.texcoord[2];\n" + + + + "TEMP diff, spec, nm, ld, cm, gm, lm, dm;\n" + + + "TEX nm.rgb, tm_tc, f[TEX1], 2D;\n" //normalmap + "TEX ld.rgb, lm_tc, f[TEX3], 2D;\n" // + "TEX dm.rgb, tm_tc, f[TEX0], 2D;\n" //deluxmap + "TEX gm.rgb, tm_tc, f[TEX4], 2D;\n" //glossmap + "TEX lm.rgb, lm_tc, f[TEX2], 2D;\n" //lightmap + "TEX cm.rgb, cm_tc, f[TEX5], CUBE;\n" //cubemap + + //textures loaded - get diffuse + "MAD nm.rgb, nm, 2, negone;\n" + "MAD ld.rgb, ld, 2, negone;\n" + "DP3 diff.rgb, nm, ld;\n" + "MUL diff.rgb, diff, dm;\n" + //diff now contains the entire diffuse part of the equation. + + //l 19 + "MAD cm.rgb, cm, 2, negone;\n" + "DP3 spec.rgb, nm, cm;\n" + + "MUL spec.rgb, spec, spec;\n" + "MUL spec.rgb, spec, spec;\n" + "MUL spec.rgb, spec, spec;\n" + + "MUL spec.rgb, spec, gm;\n" + //that's the specular part done. + + //we have diffuse and specular - wahoo + //combine then halve. + "ADD diff.rgb, diff, spec;\n" + //"MUL diff.rgb, diff, half;\n" + + + //multiply by inverse lm and output the result. +// "SUB lm.rgb, 1, lm;\n" + "MUL_SAT o[COLR].rgb, diff, lm;\n" + "" + + "END"; +*/ ppl_specular_fragmentprogram = 0; for (i = 0; i < MAXARRAYVERTS; i++) @@ -1755,6 +1816,7 @@ void PPL_LightTextures(model_t *model, vec3_t modelorigin, dlight_t *light) { GL_TexEnv(GL_MODULATE); glDisable(GL_TEXTURE_2D); + GL_SelectTexture(GL_TEXTURE1_ARB); GL_TexEnv(GL_MODULATE); glDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -1763,6 +1825,7 @@ void PPL_LightTextures(model_t *model, vec3_t modelorigin, dlight_t *light) GL_SelectTexture(GL_TEXTURE0_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(surfvertexarray_t), varray_v->stw); + glDisable(GL_TEXTURE_2D); } for (; s; s=s->texturechain) @@ -2669,6 +2732,14 @@ void PPL_RecursiveWorldNode (dlight_t *dl) float *v1, *v2; vec3_t v3, v4; + if (dl->worldshadowmesh) + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(vec3_t), dl->worldshadowmesh->verts); + glDrawElements(GL_TRIANGLES, dl->worldshadowmesh->numindicies, GL_UNSIGNED_INT, dl->worldshadowmesh->indicies); + return; + } + lightradius = dl->radius; lightorg[0] = dl->origin[0]+0.5; @@ -2989,7 +3060,7 @@ void PPL_UpdateNodeShadowFrames(qbyte *lvis) } } } -/* + #if 1 //DP's stolen code static void GL_Scissor (int x, int y, int width, int height) { @@ -3048,7 +3119,10 @@ qboolean PPL_ScissorForBox(vec3_t mins, vec3_t maxs) v[1] = (i & 2) ? mins[1] : maxs[1]; v[2] = (i & 4) ? mins[2] : maxs[2]; v[3] = 1.0f; - GL_TransformToScreen(v, v2); + ML_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, vid.width/vid.height, r_refdef.fov_y); + v2[0]*=r_view_width; + v2[1]*=r_view_height; +// GL_TransformToScreen(v, v2); //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); x = v2[0]; y = v2[1]; @@ -3115,7 +3189,10 @@ qboolean PPL_ScissorForBox(vec3_t mins, vec3_t maxs) v[1] = v2[0] * vright[1] + v2[1] * vup[1] + v2[2] * vpn[1] + r_refdef.vieworg[1]; v[2] = v2[0] * vright[2] + v2[1] * vup[2] + v2[2] * vpn[2] + r_refdef.vieworg[2]; v[3] = 1.0f; - GL_TransformToScreen(v, v2); + ML_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, vid.width/vid.height, r_refdef.fov_y); + v2[0]*=r_view_width; + v2[1]*=r_view_height; +// GL_TransformToScreen(v, v2); //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); x = v2[0]; y = v2[1]; @@ -3143,6 +3220,8 @@ qboolean PPL_ScissorForBox(vec3_t mins, vec3_t maxs) v[2] = (i & 4) ? mins[2] : maxs[2]; v[3] = 1.0f; GL_TransformToScreen(v, v2); + v2[0]*=r_view_width; + v2[1]*=r_view_height; //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); if (v2[2] > 0) { @@ -3174,7 +3253,7 @@ qboolean PPL_ScissorForBox(vec3_t mins, vec3_t maxs) return false; } #endif -*/ + void CL_NewDlight (int key, float x, float y, float z, float radius, float time, int type); //generates stencil shadows of the world geometry. @@ -3205,8 +3284,8 @@ void PPL_AddLight(dlight_t *dl) if (R_CullBox(mins, maxs)) return; -// if (PPL_ScissorForBox(mins, maxs)) -// return; //was culled. + if (PPL_ScissorForBox(mins, maxs)) + return; //was culled. if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3) i = cl.worldmodel->funcs.LeafForPoint(r_refdef.vieworg, cl.worldmodel); @@ -3222,7 +3301,7 @@ void PPL_AddLight(dlight_t *dl) if (!PPL_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect. return; -// glEnable(GL_SCISSOR_TEST); + glEnable(GL_SCISSOR_TEST); glDisable(GL_BLEND); @@ -3410,12 +3489,16 @@ void PPL_DrawWorld (void) { for (l = cl_dlights, i=0 ; idie < cl.time || !l->radius || l->noppl) + if (!l->radius || l->noppl) continue; if (l->color[0]<0) continue; //quick check for darklight - if (!maxshadowlights--) - break; + + if (l->isstatic) + { + if (!r_shadow_realtime_world.value) + continue; + } mins[0] = l->origin[0] - l->radius; mins[1] = l->origin[1] - l->radius; @@ -3428,15 +3511,23 @@ void PPL_DrawWorld (void) if (R_CullSphere(l->origin, l->radius)) continue; + if (!maxshadowlights--) + break; + + if(!l->isstatic) + { l->color[0]*=2.5; l->color[1]*=2.5; l->color[2]*=2.5; - + } TRACE(("dbg: calling PPL_AddLight\n")); PPL_AddLight(l); + if(!l->isstatic) + { l->color[0]/=2.5; l->color[1]/=2.5; l->color[2]/=2.5; + } } glEnable(GL_TEXTURE_2D); } diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index f07546975..99958bdbd 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -157,7 +157,7 @@ void R_RenderDlights (void) l = cl_dlights; for (i=0 ; idie < cl.time || !l->radius) + if (!l->radius || l->noflash) continue; R_RenderDlight (l); } @@ -349,7 +349,7 @@ void GLR_PushDlights (void) l = cl_dlights; for (i=0 ; idie < cl.time || !l->radius) + if (!l->radius || l->nodynamic) continue; cl.worldmodel->funcs.MarkLights( l, 1<nodes ); } diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 0a24e1b72..c5682588f 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -827,6 +827,67 @@ void R_TranslatePlayerSkin (int playernum) } } + +void R_LoadRTLights(void) +{ + dlight_t *dl; + char fname[MAX_QPATH]; + char *file; + char *end; + + vec3_t org; + float radius; + vec3_t rgb; + + COM_StripExtension(cl.worldmodel->name, fname); + strncat(fname, ".rtlights", MAX_QPATH-1); + + file = COM_LoadTempFile(fname); + if (!file) + return; + while(1) + { + end = strchr(file, '\n'); + if (!end) + end = file + strlen(file); + if (end == file) + break; + *end = '\0'; + + file = COM_Parse(file); + org[0] = atof(com_token); + file = COM_Parse(file); + org[1] = atof(com_token); + file = COM_Parse(file); + org[2] = atof(com_token); + + file = COM_Parse(file); + radius = atof(com_token); + + file = COM_Parse(file); + rgb[0] = atof(com_token); + file = COM_Parse(file); + rgb[1] = atof(com_token); + file = COM_Parse(file); + rgb[2] = atof(com_token); + + if (!file) + break; + + dl = CL_AllocDlight(0); + VectorCopy(org, dl->origin); + dl->radius = radius; + VectorCopy(rgb, dl->color); + dl->die = cl.time + 0x7fffffff; + dl->isstatic = true; + + dl->nodynamic = true; + dl->noflash = true; + + file = end+1; + } +} + /* =============== R_NewMap @@ -899,6 +960,12 @@ TRACE(("dbg: GLR_NewMap: ui\n")); UI_Reset(); TRACE(("dbg: GLR_NewMap: tp\n")); TP_NewMap(); + + + if (r_shadows.value) + { + R_LoadRTLights(); + } } void GLR_PreNewMap(void) diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index f23c9f421..4aba8602a 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -198,7 +198,10 @@ void VARGS PR_RunError (progfuncs_t *progfuncs, char *error, ...) Q_vsnprintf (string,sizeof(string)-1, error,argptr); va_end (argptr); - SV_EndRedirect(); + { + void SV_EndRedirect (void); + SV_EndRedirect(); + } // PR_PrintStatement (pr_statements + pr_xstatement); PR_StackTrace (progfuncs); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 1529792c1..166c236bc 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -3306,6 +3306,7 @@ reloop: if (def_ret.temp->used && ao != &def_ret) QCC_PR_ParseWarning(0, "RETURN VALUE ALREADY IN USE"); + def_parms[0].type = type_float; QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_F], ao, &def_parms[0], NULL)); if (QCC_PR_Check("=")) @@ -4646,6 +4647,7 @@ void QCC_PR_ParseStatement (void) } else { +// QCC_PR_ParseWarning(0, "using the else"); QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2)); patch1->b = &statements[numstatements] - patch1; QCC_PR_ParseStatement (); @@ -4675,6 +4677,13 @@ void QCC_PR_ParseStatement (void) e = QCC_PR_Expression (TOP_PRIORITY); conditional = false; + if (e == &def_ret) + { //copy it out, so our hack just below doesn't crash us + if (e->type->type == ev_vector) + e = QCC_PR_Statement(pr_opcodes+OP_STORE_V, QCC_GetTemp(type_vector), e, NULL); + else + e = QCC_PR_Statement(pr_opcodes+OP_STORE_F, QCC_GetTemp(type_float), e, NULL); + } et = e->temp; e->temp = NULL; //so noone frees it until we finish this loop @@ -4745,11 +4754,18 @@ void QCC_PR_ParseStatement (void) oldst = numstatements; QCC_PR_ParseStatement (); - /* if (oldst != numstatements && QCC_PR_) + //this is so that a missing goto at the end of your switch doesn't end up in the jumptable again + if (oldst == numstatements || (QCC_AStatementJumpsTo(numstatements-1, oldst, numstatements-1))) { - } - else*/ QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_GOTO], 0, 0, &patch2)); //the P1 statement/the theyforgotthebreak statement. +// QCC_PR_ParseWarning(0, "emitted goto"); + } + else + { + patch2 = NULL; +// QCC_PR_ParseWarning(0, "No goto"); + } + if (hcstyle) patch1->b = &statements[numstatements] - patch1; //the goto start part else @@ -4850,7 +4866,8 @@ void QCC_PR_ParseStatement (void) patch3 = &statements[numstatements]; - patch2->a = patch3 - patch2; //set P1 jump + if (patch2) + patch2->a = patch3 - patch2; //set P1 jump if (breaks != num_breaks) { @@ -5494,8 +5511,11 @@ void QCC_CheckForDeadAndMissingReturns(int first, int last, int rettype) if (rettype != ev_void) if (statements[last-1].op != OP_RETURN) { - QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name ); - return; + if (statements[last-1].op != OP_GOTO || (signed)statements[last-1].a > 0) + { + QCC_PR_ParseWarning(WARN_MISSINGRETURN, "%s: not all control paths return a value", pr_scope->name ); + return; + } } for (st = first; st < last; st++) @@ -5578,7 +5598,7 @@ int QCC_AStatementJumpsTo(int targ, int first, int last) { if (pr_opcodes[statements[st].op].type_a == NULL) { - if (st + (signed)statements[st].a == targ) + if (st + (signed)statements[st].a == targ && statements[st].a) { return true; } diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 0359b4b92..7bd735f0b 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -404,6 +404,12 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) multicasttype=MULTICAST_PHS; break; + case 74: //TE_FLAMEJET + protocollen = sizeofcoord*6 +sizeof(qbyte)*3; + multicastpos = 2; + multicasttype=MULTICAST_PVS; + break; + case 76: protocollen = sizeofcoord*9+sizeof(qbyte)*2; multicastpos = 2; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index bdff65240..5834d6238 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -6210,6 +6210,7 @@ void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals) chain = (edict_t *) *prinst->parms->sv_edicts; f = G_INT(OFS_PARM0)+prinst->fieldadjust; + f += prinst->parms->edictsize/4; s = PR_GetStringOfs(prinst, OFS_PARM1); for (i = 1; i < *prinst->parms->sv_num_edicts; i++) @@ -6217,7 +6218,7 @@ void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent = EDICT_NUM(prinst, i); if (ent->isfree) continue; - t = *(string_t *)&((float*)&ent->v)[f] + prinst->stringtable; + t = *(string_t *)&((float*)ent)[f] + prinst->stringtable; if (!t) continue; if (strcmp(t, s)) diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 66aa4f990..037751c9f 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -545,6 +545,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us else sizeofcoord = 2; + sizeofangle = 1; + VoteFlushAll(); #ifndef SERVERONLY D_FlushCaches();