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
This commit is contained in:
Spoike 2010-08-11 03:36:31 +00:00
parent 3a30ac63c4
commit ce07219448
100 changed files with 3805 additions and 2757 deletions

View file

@ -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");
}
/*

View file

@ -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;

View file

@ -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)

View file

@ -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 ();

View file

@ -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<<i) )
/*cl.punchangle[i] =*/ nq_dp_protocol?MSG_ReadAngle16():MSG_ReadChar();
/*cl.punchangle[i] =*/ CPNQ_IS_DP?MSG_ReadAngle16():MSG_ReadChar();
// else
// cl.punchangle[i] = 0;
@ -2669,7 +2681,7 @@ void CLNQ_ParseClientdata (void)
if (bits & (SU_VELOCITY1<<i) )
{
if (nq_dp_protocol >= 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;

View file

@ -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;
}

View file

@ -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:

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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;

View file

@ -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));

View file

@ -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++;
}

View file

@ -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)
{

View file

@ -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;

View file

@ -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;
}

View file

@ -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*/

View file

@ -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)

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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, "");

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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);
}

View file

@ -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;

View file

@ -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
}
}

View file

@ -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");

View file

@ -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;

View file

@ -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;
}

View file

@ -162,6 +162,7 @@ void CloseEditor(void)
key_dest = key_console;
editoractive = false;
editprogfuncs = NULL;
if (!firstblock)
return;

View file

@ -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++)
{

View file

@ -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);

View file

@ -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))
{

View file

@ -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);

View file

@ -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

View file

@ -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 ; i<pq1inmodel->numtris ; 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 ; i<pq1inmodel->numtris ; 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])

View file

@ -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);

View file

@ -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);
}

View file

@ -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)

View file

@ -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);

View file

@ -148,6 +148,8 @@ char *Cvar_FlagToName(int flag)
return "nounsafeexpand";
case CVAR_RULESETLATCH:
return "rulesetlatch";
case CVAR_SHADERSYSTEM:
return "shadersystem";
}
return NULL;

View file

@ -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"},

View file

@ -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 ();

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -117,6 +117,7 @@ typedef struct
#ifdef NQPROT
qboolean isnqprotocol;
struct netprim_s netprim;
#endif
float last_received; // for timeouts

View file

@ -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 ();

View file

@ -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);

View file

@ -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;

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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)
{

View file

@ -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"

View file

@ -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>

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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();
}

View file

@ -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)

View file

@ -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))

View file

@ -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);
}
}

View file

@ -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();
}

View file

@ -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"));

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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))

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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];

View file

@ -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

View file

@ -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] = '=';

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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...

View file

@ -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;
}

View file

@ -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);\

View file

@ -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

View file

@ -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)

View file

@ -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<<i;
else
to->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<<i;
}
}
angled[0] = MSG_ToAngle(to->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 ; j<sv.allocated_client_slots ; j++,cl++)
{
if (cl->state != 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;

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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)
{

View file

@ -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 ; i<NUM_SPAWN_PARMS ; i++)
{
if (spawnparamglobals[i])
@ -3773,7 +3780,8 @@ void Cmd_Observe_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 ; i<NUM_SPAWN_PARMS ; i++)
{
if (spawnparamglobals[i])
@ -4283,7 +4291,7 @@ void SVNQ_Begin_f (void)
if (pmodel != sv.model_player_checksum ||
emodel != sv.eyes_player_checksum)
SV_BroadcastTPrintf (PRINT_HIGH, STL_POSSIBLEMODELCHEAT, host_client->name);
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);
}
}
/*

View file

@ -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 ; e<ge->num_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;

View file

@ -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);

View file

@ -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;
}