4 static void QW_TranslateEffects(entity_state_t *s, int qweffects)
7 s->internaleffects = 0;
8 if (qweffects & QW_EF_BRIGHTFIELD)
9 s->effects |= EF_BRIGHTFIELD;
10 if (qweffects & QW_EF_MUZZLEFLASH)
11 s->effects |= EF_MUZZLEFLASH;
12 if (qweffects & QW_EF_FLAG1)
14 // mimic FTEQW's interpretation of EF_FLAG1 as EF_NODRAW on non-player entities
15 if (s->number > cl.maxclients)
16 s->effects |= EF_NODRAW;
18 s->internaleffects |= INTEF_FLAG1QW;
20 if (qweffects & QW_EF_FLAG2)
22 // mimic FTEQW's interpretation of EF_FLAG2 as EF_ADDITIVE on non-player entities
23 if (s->number > cl.maxclients)
24 s->effects |= EF_ADDITIVE;
26 s->internaleffects |= INTEF_FLAG2QW;
28 if (qweffects & QW_EF_RED)
30 if (qweffects & QW_EF_BLUE)
31 s->effects |= EF_RED | EF_BLUE;
35 else if (qweffects & QW_EF_BLUE)
36 s->effects |= EF_BLUE;
37 else if (qweffects & QW_EF_BRIGHTLIGHT)
38 s->effects |= EF_BRIGHTLIGHT;
39 else if (qweffects & QW_EF_DIMLIGHT)
40 s->effects |= EF_DIMLIGHT;
43 extern cvar_t cl_rollangle;
44 extern cvar_t cl_rollspeed;
46 void EntityStateQW_ReadPlayerUpdate(void)
48 int slot = MSG_ReadByte(&cl_message);
49 int enumber = slot + 1;
56 entity_t *ent = cl.entities + enumber;
60 // slide the current state into the previous
61 ent->state_previous = ent->state_current;
64 s = &ent->state_current;
66 s->active = ACTIVE_NETWORK;
68 s->colormap = enumber;
69 playerflags = MSG_ReadShort(&cl_message);
70 MSG_ReadVector(&cl_message, s->origin, cls.protocol);
71 s->frame = MSG_ReadByte(&cl_message);
73 VectorClear(viewangles);
74 VectorClear(velocity);
76 if (playerflags & QW_PF_MSEC)
78 // time difference between last update this player sent to the server,
79 // and last input we sent to the server (this packet is in response to
80 // our input, so msec is how long ago the last update of this player
81 // entity occurred, compared to our input being received)
82 msec = MSG_ReadByte(&cl_message);
86 if (playerflags & QW_PF_COMMAND)
88 bits = MSG_ReadByte(&cl_message);
89 if (bits & QW_CM_ANGLE1)
90 viewangles[0] = MSG_ReadAngle16i(&cl_message); // cmd->angles[0]
91 if (bits & QW_CM_ANGLE2)
92 viewangles[1] = MSG_ReadAngle16i(&cl_message); // cmd->angles[1]
93 if (bits & QW_CM_ANGLE3)
94 viewangles[2] = MSG_ReadAngle16i(&cl_message); // cmd->angles[2]
95 if (bits & QW_CM_FORWARD)
96 MSG_ReadShort(&cl_message); // cmd->forwardmove
97 if (bits & QW_CM_SIDE)
98 MSG_ReadShort(&cl_message); // cmd->sidemove
100 MSG_ReadShort(&cl_message); // cmd->upmove
101 if (bits & QW_CM_BUTTONS)
102 (void) MSG_ReadByte(&cl_message); // cmd->buttons
103 if (bits & QW_CM_IMPULSE)
104 (void) MSG_ReadByte(&cl_message); // cmd->impulse
105 (void) MSG_ReadByte(&cl_message); // cmd->msec
107 if (playerflags & QW_PF_VELOCITY1)
108 velocity[0] = MSG_ReadShort(&cl_message);
109 if (playerflags & QW_PF_VELOCITY2)
110 velocity[1] = MSG_ReadShort(&cl_message);
111 if (playerflags & QW_PF_VELOCITY3)
112 velocity[2] = MSG_ReadShort(&cl_message);
113 if (playerflags & QW_PF_MODEL)
114 s->modelindex = MSG_ReadByte(&cl_message);
116 s->modelindex = cl.qw_modelindex_player;
117 if (playerflags & QW_PF_SKINNUM)
118 s->skin = MSG_ReadByte(&cl_message);
119 if (playerflags & QW_PF_EFFECTS)
120 QW_TranslateEffects(s, MSG_ReadByte(&cl_message));
121 if (playerflags & QW_PF_WEAPONFRAME)
122 weaponframe = MSG_ReadByte(&cl_message);
126 if (enumber == cl.playerentity)
128 // if this is an update on our player, update the angles
129 VectorCopy(cl.viewangles, viewangles);
132 // calculate the entity angles from the viewangles
133 s->angles[0] = viewangles[0] * -0.0333;
134 s->angles[1] = viewangles[1];
136 s->angles[2] = Com_CalcRoll(s->angles, velocity, cl_rollangle.value, cl_rollspeed.value)*4;
138 // if this is an update on our player, update interpolation state
139 if (enumber == cl.playerentity)
141 VectorCopy (cl.mpunchangle[0], cl.mpunchangle[1]);
142 VectorCopy (cl.mpunchvector[0], cl.mpunchvector[1]);
143 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
144 cl.mviewzoom[1] = cl.mviewzoom[0];
147 cl.mpunchangle[0][0] = 0;
148 cl.mpunchangle[0][1] = 0;
149 cl.mpunchangle[0][2] = 0;
150 cl.mpunchvector[0][0] = 0;
151 cl.mpunchvector[0][1] = 0;
152 cl.mpunchvector[0][2] = 0;
153 cl.mvelocity[0][0] = 0;
154 cl.mvelocity[0][1] = 0;
155 cl.mvelocity[0][2] = 0;
158 VectorCopy(velocity, cl.mvelocity[0]);
159 cl.stats[STAT_WEAPONFRAME] = weaponframe;
160 if (playerflags & QW_PF_GIB)
161 cl.stats[STAT_VIEWHEIGHT] = 8;
162 else if (playerflags & QW_PF_DEAD)
163 cl.stats[STAT_VIEWHEIGHT] = -16;
165 cl.stats[STAT_VIEWHEIGHT] = 22;
168 // set the cl.entities_active flag
169 cl.entities_active[enumber] = (s->active == ACTIVE_NETWORK);
170 // set the update time
171 s->time = cl.mtime[0] - msec * 0.001; // qw has no clock
172 // check if we need to update the lerp stuff
173 if (s->active == ACTIVE_NETWORK)
174 CL_MoveLerpEntityStates(&cl.entities[enumber]);
177 static void EntityStateQW_ReadEntityUpdate(entity_state_t *s, int bits)
180 s->active = ACTIVE_NETWORK;
181 s->number = bits & 511;
183 if (bits & QW_U_MOREBITS)
184 bits |= MSG_ReadByte(&cl_message);
186 // store the QW_U_SOLID bit here?
188 if (bits & QW_U_MODEL)
189 s->modelindex = MSG_ReadByte(&cl_message);
190 if (bits & QW_U_FRAME)
191 s->frame = MSG_ReadByte(&cl_message);
192 if (bits & QW_U_COLORMAP)
193 s->colormap = MSG_ReadByte(&cl_message);
194 if (bits & QW_U_SKIN)
195 s->skin = MSG_ReadByte(&cl_message);
196 if (bits & QW_U_EFFECTS)
197 QW_TranslateEffects(s, qweffects = MSG_ReadByte(&cl_message));
198 if (bits & QW_U_ORIGIN1)
199 s->origin[0] = MSG_ReadCoord13i(&cl_message);
200 if (bits & QW_U_ANGLE1)
201 s->angles[0] = MSG_ReadAngle8i(&cl_message);
202 if (bits & QW_U_ORIGIN2)
203 s->origin[1] = MSG_ReadCoord13i(&cl_message);
204 if (bits & QW_U_ANGLE2)
205 s->angles[1] = MSG_ReadAngle8i(&cl_message);
206 if (bits & QW_U_ORIGIN3)
207 s->origin[2] = MSG_ReadCoord13i(&cl_message);
208 if (bits & QW_U_ANGLE3)
209 s->angles[2] = MSG_ReadAngle8i(&cl_message);
211 if (developer_networkentities.integer >= 2)
213 Con_Printf("ReadFields e%i", s->number);
214 if (bits & QW_U_MODEL)
215 Con_Printf(" U_MODEL %i", s->modelindex);
216 if (bits & QW_U_FRAME)
217 Con_Printf(" U_FRAME %i", s->frame);
218 if (bits & QW_U_COLORMAP)
219 Con_Printf(" U_COLORMAP %i", s->colormap);
220 if (bits & QW_U_SKIN)
221 Con_Printf(" U_SKIN %i", s->skin);
222 if (bits & QW_U_EFFECTS)
223 Con_Printf(" U_EFFECTS %i", qweffects);
224 if (bits & QW_U_ORIGIN1)
225 Con_Printf(" U_ORIGIN1 %f", s->origin[0]);
226 if (bits & QW_U_ANGLE1)
227 Con_Printf(" U_ANGLE1 %f", s->angles[0]);
228 if (bits & QW_U_ORIGIN2)
229 Con_Printf(" U_ORIGIN2 %f", s->origin[1]);
230 if (bits & QW_U_ANGLE2)
231 Con_Printf(" U_ANGLE2 %f", s->angles[1]);
232 if (bits & QW_U_ORIGIN3)
233 Con_Printf(" U_ORIGIN3 %f", s->origin[2]);
234 if (bits & QW_U_ANGLE3)
235 Con_Printf(" U_ANGLE3 %f", s->angles[2]);
236 if (bits & QW_U_SOLID)
237 Con_Printf(" U_SOLID");
242 entityframeqw_database_t *EntityFrameQW_AllocDatabase(mempool_t *pool)
244 entityframeqw_database_t *d;
245 d = (entityframeqw_database_t *)Mem_Alloc(pool, sizeof(*d));
249 void EntityFrameQW_FreeDatabase(entityframeqw_database_t *d)
254 void EntityFrameQW_CL_ReadFrame(qbool delta)
256 qbool invalid = false;
257 int number, oldsnapindex, newsnapindex, oldindex, newindex, oldnum, newnum;
259 entityframeqw_database_t *d;
260 entityframeqw_snapshot_t *oldsnap, *newsnap;
262 if (!cl.entitydatabaseqw)
263 cl.entitydatabaseqw = EntityFrameQW_AllocDatabase(cls.levelmempool);
264 d = cl.entitydatabaseqw;
266 // there is no cls.netcon in demos, so this reading code can't access
267 // cls.netcon-> at all... so cls.qw_incoming_sequence and
268 // cls.qw_outgoing_sequence are updated every time the corresponding
269 // cls.netcon->qw. variables are updated
270 // read the number of this frame to echo back in next input packet
271 cl.qw_validsequence = cls.qw_incoming_sequence;
272 newsnapindex = cl.qw_validsequence & QW_UPDATE_MASK;
273 newsnap = d->snapshot + newsnapindex;
274 memset(newsnap, 0, sizeof(*newsnap));
278 number = MSG_ReadByte(&cl_message);
279 oldsnapindex = cl.qw_deltasequence[newsnapindex];
280 if ((number & QW_UPDATE_MASK) != (oldsnapindex & QW_UPDATE_MASK))
281 Con_DPrintf("WARNING: from mismatch\n");
282 if (oldsnapindex != -1)
284 if (cls.qw_outgoing_sequence - oldsnapindex >= QW_UPDATE_BACKUP-1)
286 Con_DPrintf("delta update too old\n");
287 newsnap->invalid = invalid = true; // too old
290 oldsnap = d->snapshot + (oldsnapindex & QW_UPDATE_MASK);
296 // if we can't decode this frame properly, report that to the server
298 cl.qw_validsequence = 0;
300 // read entity numbers until we find a 0x0000
301 // (which would be an empty update on world entity, but is actually a terminator)
302 newsnap->num_entities = 0;
306 int word = (unsigned short)MSG_ReadShort(&cl_message);
307 if (cl_message.badread)
308 return; // just return, the main parser will print an error
309 newnum = word == 0 ? 512 : (word & 511);
310 oldnum = delta ? (oldindex >= oldsnap->num_entities ? 9999 : oldsnap->entities[oldindex].number) : 9999;
312 // copy unmodified oldsnap entities
313 while (newnum > oldnum) // delta only
315 if (developer_networkentities.integer >= 2)
316 Con_Printf("copy %i\n", oldnum);
317 // copy one of the old entities
318 if (newsnap->num_entities >= QW_MAX_PACKET_ENTITIES)
319 Host_Error("EntityFrameQW_CL_ReadFrame: newsnap->num_entities == MAX_PACKETENTITIES");
320 newsnap->entities[newsnap->num_entities] = oldsnap->entities[oldindex++];
321 newsnap->num_entities++;
322 oldnum = oldindex >= oldsnap->num_entities ? 9999 : oldsnap->entities[oldindex].number;
328 if (developer_networkentities.integer >= 2)
330 if (word & QW_U_REMOVE)
331 Con_Printf("remove %i\n", newnum);
332 else if (newnum == oldnum)
333 Con_Printf("delta %i\n", newnum);
335 Con_Printf("baseline %i\n", newnum);
338 if (word & QW_U_REMOVE)
340 if (newnum != oldnum && !delta && !invalid)
342 cl.qw_validsequence = 0;
343 Con_Printf(CON_WARN "WARNING: U_REMOVE %i on full update\n", newnum);
348 if (newsnap->num_entities >= QW_MAX_PACKET_ENTITIES)
349 Host_Error("EntityFrameQW_CL_ReadFrame: newsnap->num_entities == MAX_PACKETENTITIES");
350 newsnap->entities[newsnap->num_entities] = (newnum == oldnum) ? oldsnap->entities[oldindex] : cl.entities[newnum].state_baseline;
351 EntityStateQW_ReadEntityUpdate(newsnap->entities + newsnap->num_entities, word);
352 newsnap->num_entities++;
355 if (newnum == oldnum)
359 // expand cl.num_entities to include every entity we've seen this game
360 newnum = newsnap->num_entities ? newsnap->entities[newsnap->num_entities - 1].number : 1;
361 if (cl.num_entities <= newnum)
363 cl.num_entities = newnum + 1;
364 if (cl.max_entities < newnum + 1)
365 CL_ExpandEntities(newnum);
368 // now update the non-player entities from the snapshot states
369 number = cl.maxclients + 1;
370 for (newindex = 0;;newindex++)
372 newnum = newindex >= newsnap->num_entities ? cl.num_entities : newsnap->entities[newindex].number;
373 // kill any missing entities
374 for (;number < newnum;number++)
376 if (cl.entities_active[number])
378 cl.entities_active[number] = false;
379 cl.entities[number].state_current.active = ACTIVE_NOT;
382 if (number >= cl.num_entities)
385 ent = &cl.entities[number];
386 ent->state_previous = ent->state_current;
387 ent->state_current = newsnap->entities[newindex];
388 ent->state_current.time = cl.mtime[0];
389 CL_MoveLerpEntityStates(ent);
390 // the entity lives again...
391 cl.entities_active[number] = true;