diff --git a/Quake/cl_parse.c b/Quake/cl_parse.c index 1f037929..0099eb7e 100644 --- a/Quake/cl_parse.c +++ b/Quake/cl_parse.c @@ -1802,7 +1802,7 @@ CL_ParseBaseline static void CL_ParseBaseline (entity_t *ent, int version) //johnfitz -- added argument { int i; - int bits; //johnfitz + int bits, unknownbits; if (version == 6) { @@ -1831,7 +1831,17 @@ static void CL_ParseBaseline (entity_t *ent, int version) //johnfitz -- added ar ent->baseline.angles[i] = MSG_ReadAngle (cl.protocolflags); } - ent->baseline.alpha = (bits & B_ALPHA) ? MSG_ReadByte() : ENTALPHA_DEFAULT; //johnfitz -- PROTOCOL_FITZQUAKE + if (bits & B_ALPHA) + ent->baseline.alpha = MSG_ReadByte(); + if (bits & B_SCALE) //not actually valid in 666, but reading anyway for servers that don't distinguish properly. The warning will have to suffice. + ent->baseline.scale = MSG_ReadByte(); + + if (cl.protocol == PROTOCOL_RMQ) + unknownbits = ~(B_LARGEMODEL|B_LARGEFRAME|B_ALPHA|B_SCALE); + else + unknownbits = ~(B_LARGEMODEL|B_LARGEFRAME|B_ALPHA); + if (bits & unknownbits) + Con_Warning("CL_ParseBaseline: Unknown bits %#x\n", bits & unknownbits); } diff --git a/Quake/cl_tent.c b/Quake/cl_tent.c index 1f66a213..8185b04c 100644 --- a/Quake/cl_tent.c +++ b/Quake/cl_tent.c @@ -541,9 +541,7 @@ entity_t *CL_NewTempEntity (void) cl_visedicts[cl_numvisedicts] = ent; cl_numvisedicts++; - ent->netstate.scale = 16; - ent->netstate.colormod[0] = ent->netstate.colormod[1] = ent->netstate.colormod[2] = 32; - ent->netstate.colormap = 0; + ent->netstate = nullentitystate; return ent; } diff --git a/Quake/common.c b/Quake/common.c index 8a40080b..608761a2 100644 --- a/Quake/common.c +++ b/Quake/common.c @@ -1787,9 +1787,9 @@ static void COM_SetupNullState(void) // nullentitystate.glowmod[0] = 32; // nullentitystate.glowmod[1] = 32; // nullentitystate.glowmod[2] = 32; - nullentitystate.alpha = 0; //fte has 255 by default, with 0 for invisible. fitz uses 1 for invisible, 0 default, and 255=full alpha - nullentitystate.scale = 16; -// nullentitystate.solidsize = 0;//ES_SOLID_BSP; + nullentitystate.alpha = ENTALPHA_DEFAULT; //fte has 255 by default, with 0 for invisible. fitz uses 1 for invisible, 0 default, and 255=full alpha + nullentitystate.scale = ENTSCALE_DEFAULT; + nullentitystate.solidsize = ES_SOLID_NOT; } /* diff --git a/Quake/gl_rmain.c b/Quake/gl_rmain.c index 746a19d3..fe499ad2 100644 --- a/Quake/gl_rmain.c +++ b/Quake/gl_rmain.c @@ -300,7 +300,7 @@ R_CullModelForEntity -- johnfitz -- uses correct bounds based on rotation qboolean R_CullModelForEntity (entity_t *e) { vec3_t mins, maxs; - float scale = e->netstate.scale/16.0; + float scale = ENTSCALE_DECODE(e->netstate.scale); if (e->angles[0] || e->angles[2]) //pitch or roll { @@ -333,8 +333,8 @@ void R_RotateForEntity (vec3_t origin, vec3_t angles, unsigned char scale) glRotatef (-angles[0], 0, 1, 0); glRotatef (angles[2], 1, 0, 0); - if (scale != 16) - glScalef (scale/16.0, scale/16.0, scale/16.0); + if (scale != ENTSCALE_DEFAULT) + glScalef (ENTSCALE_DECODE(scale), ENTSCALE_DECODE(scale), ENTSCALE_DECODE(scale)); } /* diff --git a/Quake/host.c b/Quake/host.c index 5d82242a..c6509f62 100644 --- a/Quake/host.c +++ b/Quake/host.c @@ -748,6 +748,7 @@ qmodel_t *CL_ModelForIndex(int index) static void CL_LoadCSProgs(void) { qboolean fullcsqc = false; + int i; PR_ClearProgs(&cl.qcvm); if (pr_checkextension.value && !cl_nocsqc.value) { //only try to use csqc if qc extensions are enabled. @@ -774,6 +775,8 @@ static void CL_LoadCSProgs(void) qcvm->edicts = (edict_t *) malloc (qcvm->max_edicts*qcvm->edict_size); qcvm->num_edicts = qcvm->reserved_edicts = 1; memset(qcvm->edicts, 0, qcvm->num_edicts*qcvm->edict_size); + for (i = 0; i < qcvm->num_edicts; i++) + EDICT_NUM(i)->baseline = nullentitystate; //in terms of exploit protection this is kinda pointless as someone can just strip out this check and compile themselves. oh well. if ((*versionedname && qcvm->progshash == csqchash && qcvm->progssize == csqcsize) || cls.demoplayback) diff --git a/Quake/pr_edict.c b/Quake/pr_edict.c index 19b8aeee..a64684c8 100644 --- a/Quake/pr_edict.c +++ b/Quake/pr_edict.c @@ -95,7 +95,7 @@ edict_t *ED_Alloc (void) qcvm->num_edicts++; e = EDICT_NUM(i); memset(e, 0, qcvm->edict_size); // ericw -- switched sv.edicts to malloc(), so we are accessing uninitialized memory and must fully zero it, not just ED_ClearEdict - + e->baseline = nullentitystate; return e; } diff --git a/Quake/pr_ext.c b/Quake/pr_ext.c index 2ef9cc67..214de18a 100644 --- a/Quake/pr_ext.c +++ b/Quake/pr_ext.c @@ -6084,8 +6084,8 @@ static void PR_addentity_internal(edict_t *ed) //adds a csqc entity into the sce e->netstate.colormod[2] *= colormod->vector[2]; } e->alpha = alpha?ENTALPHA_ENCODE(alpha->_float):ENTALPHA_DEFAULT; - if (scale && scale->_float) - e->netstate.scale *= scale->_float; + if (scale) + e->netstate.scale = ENTSCALE_ENCODE(scale->_float); //can't exactly use currentpose/previous pose, as we don't know them. e->lerpflags = LERP_EXPLICIT|LERP_RESETANIM|LERP_RESETMOVE; @@ -6937,7 +6937,7 @@ static void PF_cl_getrenderentity(void) AngleVectors(tmp, tmp, tmp, G_VECTOR(OFS_RETURN)); break; case GE_SCALE: - G_FLOAT(OFS_RETURN+0) = cl.entities[entnum].netstate.scale/16.0; + G_FLOAT(OFS_RETURN+0) = ENTSCALE_DECODE(cl.entities[entnum].netstate.scale); break; case GE_ALPHA: G_FLOAT(OFS_RETURN+0) = ENTALPHA_DECODE(cl.entities[entnum].alpha); diff --git a/Quake/protocol.h b/Quake/protocol.h index ff81f827..59cd6b60 100644 --- a/Quake/protocol.h +++ b/Quake/protocol.h @@ -241,6 +241,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define B_LARGEMODEL (1<<0) // modelindex is short instead of byte #define B_LARGEFRAME (1<<1) // frame is short instead of byte #define B_ALPHA (1<<2) // 1 byte, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT +#define B_SCALE (1<<3) // added as part of rmq 999 (NOT valid for 666) //johnfitz //johnfitz -- PROTOCOL_FITZQUAKE -- alpha encoding @@ -252,6 +253,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ENTALPHA_TOSAVE(a) (((a)==ENTALPHA_DEFAULT)?0.0f:(((a)==ENTALPHA_ZERO)?-1.0f:((float)(a)-1)/(254))) //server convert to float for savegame //johnfitz +#define ENTSCALE_DEFAULT 16 +#define ENTSCALE_ENCODE(f) ((f)?CLAMP(1,(int)(ENTSCALE_DEFAULT*(f)),255):ENTSCALE_DEFAULT) +#define ENTSCALE_DECODE(es) ((es)/(float)ENTSCALE_DEFAULT) +#define ENTSCALE_QS_IS_BROKEN //FIXME: remove this once QS fixes its support for B_SCALE, allowing for scaled makestatic and baselines. Until then we are no worse than DP, just with more bloated ent deltas (replacementdeltas avoids spawnstatic feature loss). + // defaults for clientinfo messages #define DEFAULT_VIEWHEIGHT 22 diff --git a/Quake/r_sprite.c b/Quake/r_sprite.c index d463d520..753946e3 100644 --- a/Quake/r_sprite.c +++ b/Quake/r_sprite.c @@ -143,10 +143,7 @@ void R_DrawSpriteModel (entity_t *e) if (psprite->type == SPR_ORIENTED) GL_PolygonOffset (OFFSET_DECAL); - if (e->netstate.scale != 16) - scale = e->netstate.scale/16.0; - else - scale = 1; + scale = ENTSCALE_DECODE(e->netstate.scale); glColor3f (e->netstate.colormod[0]/32.0,e->netstate.colormod[0]/32.0,e->netstate.colormod[0]/32.0); diff --git a/Quake/sv_main.c b/Quake/sv_main.c index 20551cd9..f9c3f9b3 100644 --- a/Quake/sv_main.c +++ b/Quake/sv_main.c @@ -1110,10 +1110,10 @@ void SV_BuildEntityState(edict_t *ent, entity_state_t *state) state->frame = ent->v.frame; state->colormap = ent->v.colormap; state->skin = ent->v.skin; - if ((val = GetEdictFieldValue(ent, qcvm->extfields.scale)) && val->_float) - state->scale = val->_float*16; + if ((val = GetEdictFieldValue(ent, qcvm->extfields.scale))) + state->scale = ENTSCALE_ENCODE(val->_float); else - state->scale = 16; + state->scale = ENTSCALE_DEFAULT; if ((val = GetEdictFieldValue(ent, qcvm->extfields.alpha))) state->alpha = ENTALPHA_ENCODE(val->_float); else @@ -1325,6 +1325,10 @@ void MSG_WriteStaticOrBaseLine(sizebuf_t *buf, int idx, entity_state_t *state, u bits |= B_LARGEFRAME; if (state->alpha != ENTALPHA_DEFAULT) bits |= B_ALPHA; +#ifndef ENTSCALE_QS_IS_BROKEN + if (state->scale != ENTSCALE_DEFAULT && protocol == PROTOCOL_RMQ) + bits |= B_SCALE; +#endif } if (idx>=0) { @@ -1357,6 +1361,8 @@ void MSG_WriteStaticOrBaseLine(sizebuf_t *buf, int idx, entity_state_t *state, u } if (bits & B_ALPHA) MSG_WriteByte (buf, state->alpha); + if (bits & B_SCALE) + MSG_WriteByte (buf, state->scale); } } @@ -2399,6 +2405,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg) eval_t *val; int maxsize = msg->maxsize; int effects; + int scale = ENTSCALE_DEFAULT; //try to avoid sounds getting lost. flickering entities are weird, but missing sounds+particles are just eerie. maxsize -= client->datagram.cursize; @@ -2514,6 +2521,10 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg) continue; //johnfitz + val = GetEdictFieldValue(ent, qcvm->extfields.scale); + if (val) + scale = ENTSCALE_ENCODE(val->_float); + //spike -- PROTOCOL_VERSION_BJP3 if (sv.protocol == PROTOCOL_VERSION_BJP3) { @@ -2524,11 +2535,11 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg) //johnfitz -- PROTOCOL_FITZQUAKE if (sv.protocol != PROTOCOL_NETQUAKE) { - if (ent->baseline.alpha != ent->alpha) bits |= U_ALPHA; if (bits & U_FRAME && (int)ent->v.frame & 0xFF00) bits |= U_FRAME2; if (bits & U_MODEL && (int)ent->v.modelindex & 0xFF00) bits |= U_MODEL2; if (ent->sendinterval) bits |= U_LERPFINISH; + if (ent->baseline.scale != scale && sv.protocol == PROTOCOL_RMQ) bits |= U_SCALE; if (bits >= 65536) bits |= U_EXTEND1; if (bits >= 16777216) bits |= U_EXTEND2; } @@ -2615,6 +2626,8 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg) //johnfitz -- PROTOCOL_FITZQUAKE if (bits & U_ALPHA) MSG_WriteByte(msg, ent->alpha); + if (bits & U_SCALE) + MSG_WriteByte(msg, scale); if (bits & U_FRAME2) MSG_WriteByte(msg, (int)ent->v.frame >> 8); if (bits & U_MODEL2) @@ -3386,6 +3399,7 @@ void SV_CreateBaseline (void) // // create entity baseline // + svent->baseline = nullentitystate; VectorCopy (svent->v.origin, svent->baseline.origin); VectorCopy (svent->v.angles, svent->baseline.angles); svent->baseline.frame = svent->v.frame; @@ -3407,7 +3421,13 @@ void SV_CreateBaseline (void) svent->baseline.alpha = svent->alpha; //johnfitz -- alpha support } - //Spike -- baselines are now generated on a per-client basis. +#ifndef ENTSCALE_QS_IS_BROKEN //Older versions of QS do NOT support B_SCALE. If we use default baseline values here then we will simply fall back to spamming U_SCALE every time instead. + val = GetEdictFieldValue(svent, qcvm->extfields.scale); + if (val) + svent->baseline.scale = ENTALPHA_ENCODE(val->_float); +#endif + + //Spike -- baselines are now transmitted on a per-client basis. //FIXME: should merge the above with other edict->entity_state copies (updates, baselines, spawnstatics) //1) this allows per-client extensions. //2) this avoids pre-generating a single signon buffer, splitting it over multiple packets.